This finishes off some more of the code to handle parcels, in this update, DirectoryParcel has been created, and the old (pre-rev114) parcel code has been ported over to it.
Note: This is a breaking change. Some variables have been renamed. Others moved into the DirectoryParcel class. Additional packet types are supported, including the all-important "parcel.update()" function which allows you to edit a parcel, then .update() your changes back to the sim. Eg: Parcel x = Region.Parcels[LocalID]; x.Name = "Test Parcel Name"; x.Update(); This patch also nearly completes the parcel class, it now contains a significant number of extra properties. The only major one which is missing in action is Dwell, which is being added seperately. Still a little bit more to be done, but that will be coming soon. -Adam
Index: Packets/ParcelPackets.cs =================================================================== --- Packets/ParcelPackets.cs (revision 114) +++ Packets/ParcelPackets.cs (working copy) @@ -31,6 +31,7 @@ { public class Parcel { + // DataServer Based ------------------------------------------------- public static Packet ParcelInfoRequest(ProtocolManager protocol, LLUUID parcelID, LLUUID agentID, LLUUID sessionID) { @@ -48,6 +49,7 @@ Helpers.MSG_RELIABLE + Helpers.MSG_ZEROCODED); } + // Sim Based --------------------------------------------------------- public static Packet ParcelBuy(ProtocolManager protocol, int localID, bool groupOwned, LLUUID groupID, bool final, LLUUID agentID, LLUUID sessionID) { @@ -67,6 +69,7 @@ return PacketBuilder.BuildPacket("ParcelBuy", protocol, blocks, Helpers.MSG_RELIABLE); } +<<<<<<< .mine public static Packet ParcelDeedToGroup(ProtocolManager protocol, int localID, LLUUID groupID, LLUUID agentID, LLUUID sessionID) @@ -151,5 +154,168 @@ blocks[fields] = "ParcelData"; return PacketBuilder.BuildPacket("ParcelPropertiesRequestByID", protocol, blocks, Helpers.MSG_RELIABLE); } + + public static Packet ParcelPropertiesUpdate(ProtocolManager protocol, LLUUID agentID, LLUUID sessionID, libsecondlife.Parcel parcel) + { + Hashtable blocks = new Hashtable(); + Hashtable fields = new Hashtable(); + + fields["AgentID"] = agentID; + fields["SessionID"] = sessionID; + blocks[fields] = "AgentData"; + + fields = new Hashtable(); + fields["LocalID"] = parcel.LocalID; + fields["Flags"] = 0; //TODO: !!IMPORTANT!! Find out what we are. + fields["ParcelFlags"] = parcel.ParcelFlags; + fields["SalePrice"] = parcel.SalePrice; + fields["Name"] = parcel.Name; + fields["Desc"] = parcel.Desc; + fields["MusicURL"] = parcel.MusicURL; + fields["MediaURL"] = parcel.MediaURL; + fields["MediaID"] = parcel.MediaID; + fields["MediaAutoScale"] = parcel.MediaAutoScale; + fields["GroupID"] = parcel.GroupID; + fields["PassPrice"] = parcel.PassPrice; + fields["PassHours"] = parcel.PassHours; + fields["Category"] = parcel.Category; + fields["AuthBuyerID"] = parcel.AuthBuyerID; + fields["SnapshotID"] = parcel.SnapshotID; + fields["UserLocation"] = parcel.UserLocation; + fields["UserLookAt"] = parcel.UserLookAt; + fields["LandingType"] = parcel.LandingType; + blocks[fields] = "ParcelData"; + + return PacketBuilder.BuildPacket("ParcelPropertiesUpdate", protocol, blocks, Helpers.MSG_RELIABLE); + } + + public static Packet ParcelReturnObjects(ProtocolManager protocol, LLUUID agentID, LLUUID sessionID, int localID, int returnType, + int otherCleanTime) + { + Hashtable blocks = new Hashtable(); + Hashtable fields = new Hashtable(); + + fields["AgentID"] = agentID; + fields["SessionID"] = sessionID; + blocks[fields] = "AgentData"; + + fields = new Hashtable(); + fields["LocalID"] = localID; + fields["ReturnType"] = returnType; + fields["OtherCleanTime"] = otherCleanTime; + blocks[fields] = "ParcelData"; + + return PacketBuilder.BuildPacket("ParcelPropertiesRequestByID", protocol, blocks, Helpers.MSG_RELIABLE); + } + + public static Packet ParcelReturnObjects(ProtocolManager protocol, LLUUID agentID, LLUUID sessionID, int localID, int returnType, + int otherCleanTime, LLUUID ownerID) + { + Hashtable blocks = new Hashtable(); + Hashtable fields = new Hashtable(); + + fields["AgentID"] = agentID; + fields["SessionID"] = sessionID; + blocks[fields] = "AgentData"; + + fields = new Hashtable(); + fields["LocalID"] = localID; + fields["ReturnType"] = returnType; + fields["OtherCleanTime"] = otherCleanTime; + blocks[fields] = "ParcelData"; + + fields = new Hashtable(); + fields["OwnerID"] = ownerID; + + blocks[fields] = "OwnerIDs"; + + return PacketBuilder.BuildPacket("ParcelPropertiesRequestByID", protocol, blocks, Helpers.MSG_RELIABLE); + } +======= + + public static Packet ParcelDeedToGroup(ProtocolManager protocol, int localID, LLUUID groupID, + LLUUID agentID, LLUUID sessionID) + { + Hashtable blocks = new Hashtable(); + Hashtable fields = new Hashtable(); + + fields["LocalID"] = localID; + fields["GroupID"] = groupID; + blocks[fields] = "Data"; + + fields = new Hashtable(); + fields["AgentID"] = agentID; + fields["SessionID"] = sessionID; + blocks[fields] = "AgentData"; + + return PacketBuilder.BuildPacket("ParcelDeedToGroup", protocol, blocks, Helpers.MSG_RELIABLE); + } + + public static Packet ParcelReclaim(ProtocolManager protocol, int localID, + LLUUID agentID, LLUUID sessionID) + { + Hashtable blocks = new Hashtable(); + Hashtable fields = new Hashtable(); + + fields["LocalID"] = localID; + blocks[fields] = "Data"; + + fields = new Hashtable(); + fields["AgentID"] = agentID; + fields["SessionID"] = sessionID; + blocks[fields] = "AgentData"; + + return PacketBuilder.BuildPacket("ParcelReclaim", protocol, blocks, Helpers.MSG_RELIABLE); + } + + public static Packet ParcelRelease(ProtocolManager protocol, int localID, + LLUUID agentID, LLUUID sessionID) + { + Hashtable blocks = new Hashtable(); + Hashtable fields = new Hashtable(); + + fields["LocalID"] = localID; + blocks[fields] = "Data"; + + fields = new Hashtable(); + fields["AgentID"] = agentID; + fields["SessionID"] = sessionID; + blocks[fields] = "AgentData"; + + return PacketBuilder.BuildPacket("ParcelRelease", protocol, blocks, Helpers.MSG_RELIABLE); + } + + public static Packet ParcelPropertiesRequest(ProtocolManager protocol, LLUUID agentID, int sequenceID, + float west, float south, float east, float north, bool snapSelection) + { + Hashtable blocks = new Hashtable(); + Hashtable fields = new Hashtable(); + + fields["AgentID"] = agentID; + fields["SequenceID"] = sequenceID; + fields["West"] = west; + fields["South"] = south; + fields["East"] = east; + fields["North"] = north; + fields["SnapSelection"] = snapSelection; + + blocks[fields] = "ParcelData"; + return PacketBuilder.BuildPacket("ParcelPropertiesRequest", protocol, blocks, Helpers.MSG_RELIABLE); + } + + public static Packet ParcelPropertiesRequestByID(ProtocolManager protocol, LLUUID agentID, int sequenceID, + int localID) + { + Hashtable blocks = new Hashtable(); + Hashtable fields = new Hashtable(); + + fields["AgentID"] = agentID; + fields["SequenceID"] = sequenceID; + fields["LocalID"] = localID; + + blocks[fields] = "ParcelData"; + return PacketBuilder.BuildPacket("ParcelPropertiesRequestByID", protocol, blocks, Helpers.MSG_RELIABLE); + } +>>>>>>> .r114 } } Index: Parcel.cs =================================================================== --- Parcel.cs (revision 114) +++ Parcel.cs (working copy) @@ -22,6 +22,524 @@ * 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. +<<<<<<< .mine + */ + +using System; +using System.Timers; +using System.Collections; + +namespace libsecondlife +{ + // Class for parcels used by the dataserver + // Such as the "For-Sale" listings + public class DirectoryParcel + { + public LLUUID ID; + public LLUUID OwnerID; + public LLUUID SnapshotID; + public U64 RegionHandle; + public string Name; + public string SimName; + public string Desc; + public int SalePrice; + public int ActualArea; + public LLVector3 GlobalPosition; + public LLVector3 SimPosition; + public float Dwell; + + public DirectoryParcel() + { + GlobalPosition = new LLVector3(); + SimPosition = new LLVector3(); + } + } + + // Class for parcels within a sim + public class Parcel + { + public int RequestResult; + public int SequenceID; + public bool SnapSelection; + public int SelfCount; + public int OtherCount; + public int PublicCount; + public int LocalID; + public LLUUID OwnerID; + public bool IsGroupOwned; + public uint AuctionID; + public bool ReservedNewbie; + public int ClaimDate; + public int ClaimPrice; + public int RentPrice; + public LLVector3 AABBMin; + public LLVector3 AABBMax; + public byte[] Bitmap; + public int Area; + public byte Status; + public int SimWideMaxObjects; + public int SimWideTotalObjects; + public int MaxObjects; + public int TotalObjects; + public int OwnerObjects; + public int GroupObjects; + public int OtherObjects; + public float ParcelObjectBonus; + public int OtherCleanTime; + public uint ParcelFlags; + public int SalePrice; + public string Name; + public string Desc; + public string MusicURL; + public string MediaURL; + public LLUUID MediaID; + public byte MediaAutoScale; + public LLUUID GroupID; + public int PassPrice; + public float PassHours; + public byte Category; + public LLUUID AuthBuyerID; + public LLUUID SnapshotID; + public LLVector3 UserLocation; + public LLVector3 UserLookAt; + public byte LandingType; + + private Simulator Sim; // Using Sim instead of Region since it references both + + private void init() + { + RequestResult = 0; + SequenceID = 0; + SnapSelection = false; + SelfCount = 0; + OtherCount = 0; + PublicCount = 0; + LocalID = 0; + OwnerID = new LLUUID(); + IsGroupOwned = false; + AuctionID = 0; + ReservedNewbie = false; + ClaimDate = 0; + ClaimPrice = 0; + RentPrice = 0; + AABBMin = new LLVector3(); + AABBMax = new LLVector3(); + Bitmap = new byte[512]; + Area = 0; + Status = 0; + SimWideMaxObjects = 0; + SimWideTotalObjects = 0; + MaxObjects = 0; + TotalObjects = 0; + OwnerObjects = 0; + GroupObjects = 0; + OtherObjects = 0; + ParcelObjectBonus = 0.0f; + OtherCleanTime = 0; + ParcelFlags = 0; + SalePrice = 0; + Name = ""; + Desc = ""; + MusicURL = ""; + MediaURL = ""; + MediaID = new LLUUID(); + MediaAutoScale = 0; + GroupID = new LLUUID(); + PassPrice = 0; + PassHours = 0.0f; + Category = 0; + AuthBuyerID = new LLUUID(); + SnapshotID = new LLUUID(); + UserLocation = new LLVector3(); + UserLookAt = new LLVector3(); + LandingType = 0; + } + + public Parcel() + { + init(); + } + + public Parcel(Simulator simulator) + { + Sim = simulator; + init(); + } + + public bool Buy(SecondLife client, bool forGroup, LLUUID groupID) + { + Packet buyPacket = Packets.Parcel.ParcelBuy(client.Protocol,LocalID,forGroup,groupID,true,client.Avatar.ID,client.Network.SessionID); + Sim.SendPacket(buyPacket,true); + + return false; + } + + public bool Reclaim(SecondLife client) + { + Packet reclaimPacket = Packets.Parcel.ParcelReclaim(client.Protocol,LocalID,client.Avatar.ID,client.Network.SessionID); + Sim.SendPacket(reclaimPacket,true); + + return false; + } + + public bool Deed(SecondLife client, LLUUID groupID) + { + Packet deedPacket = Packets.Parcel.ParcelDeedToGroup(client.Protocol,LocalID,groupID,client.Avatar.ID,client.Network.SessionID); + Sim.SendPacket(deedPacket,true); + + return false; + } + + public void Update(SecondLife client) + { + Packet updatePacket = Packets.Parcel.ParcelPropertiesUpdate(client.Protocol,client.Avatar.ID,client.Network.SessionID,this); + Sim.SendPacket(updatePacket,true); + } + + public void ReturnObjects(SecondLife client, int returnType, int otherCleanTime) + { + Packet returnPacket = Packets.Parcel.ParcelReturnObjects(client.Protocol,client.Avatar.ID,client.Network.SessionID,LocalID, + returnType,otherCleanTime); + Sim.SendPacket(returnPacket,true); + } + + public void ReturnObjects(SecondLife client, int returnType, int otherCleanTime, LLUUID ownerID) + { + Packet returnPacket = Packets.Parcel.ParcelReturnObjects(client.Protocol,client.Avatar.ID,client.Network.SessionID,LocalID, + returnType,otherCleanTime,ownerID); + Sim.SendPacket(returnPacket,true); + } + } + + public class ParcelManager + { + public ArrayList ParcelsForSale; + + private SecondLife Client; + private bool ReservedNewbie; + private bool ForSale; + private bool Auction; + private bool Finished; + private Timer DirLandTimer; + private bool DirLandTimeout; + private bool ParcelInfoTimeout; + private DirectoryParcel ParcelInfoParcel; + + public ParcelManager(SecondLife client) + { + Client = client; + ParcelsForSale = new ArrayList(); + + // Setup the callbacks + PacketCallback callback = new PacketCallback(DirLandReplyHandler); + Client.Network.RegisterCallback("DirLandReply", callback); + callback = new PacketCallback(ParcelInfoReplyHandler); + Client.Network.RegisterCallback("ParcelInfoReply", callback); + callback = new PacketCallback(ParcelPropertiesHandler); + Client.Network.RegisterCallback("ParcelProperties",callback); + } + + public bool RequestParcelInfo(DirectoryParcel parcel) + { + int attempts = 0; + + Beginning: + if (attempts++ > 3) + { + return false; + } + + Finished = false; + ParcelInfoTimeout = false; + ParcelInfoParcel = parcel; + + // Setup the timer + Timer ParcelInfoTimer = new Timer(5000); + ParcelInfoTimer.Elapsed += new ElapsedEventHandler(ParcelInfoTimerEvent); + ParcelInfoTimeout = false; + + // Build the ParcelInfoRequest packet + Packet parcelInfoPacket = Packets.Parcel.ParcelInfoRequest(Client.Protocol, parcel.ID, + Client.Network.AgentID, Client.Network.SessionID); + + // Start the timer + ParcelInfoTimer.Start(); + + Client.Network.SendPacket(parcelInfoPacket); + + while (!Finished) + { + if (ParcelInfoTimeout) + { + goto Beginning; + } + + Client.Tick(); + } + + return true; + } + + public void ParcelPropertiesHandler(Packet packet, Simulator simulator) + { + // Marked == Added to Parcel Class specifically for this Packet + // -> XYZ == Equivilent to property XYZ in Packet. + int RequestResult = 0; + int SequenceID = 0; + bool SnapSelection = false; + int SelfCount = 0; + int OtherCount = 0; + int PublicCount = 0; + int LocalID = 0; // Marked + LLUUID OwnerID = new LLUUID(); // -> OwnerID + bool IsGroupOwned = false; // Marked + uint AuctionID = 0; + bool ReservedNewbie = false; // Marked -> FirstLand + int ClaimDate = 0; // Marked + int ClaimPrice = 0; + int RentPrice = 0; + LLVector3 AABBMin = new LLVector3(); + LLVector3 AABBMax = new LLVector3(); + byte[] Bitmap = new byte[512]; // Marked + int Area = 0; // -> ActualArea + byte Status = 0; + int SimWideMaxObjects = 0; + int SimWideTotalObjects = 0; + int MaxObjects = 0; + int TotalObjects = 0; + int OwnerObjects = 0; + int GroupObjects = 0; + int OtherObjects = 0; + float ParcelObjectBonus = 0.0f; + int OtherCleanTime = 0; + uint ParcelFlags = 0; + int SalePrice = 0; // -> SalePrice + string Name = ""; + string Desc = ""; + string MusicURL = ""; + string MediaURL = ""; + LLUUID MediaID = new LLUUID(); + byte MediaAutoScale = 0; + LLUUID GroupID = new LLUUID(); + int PassPrice = 0; + float PassHours = 0.0f; + byte Category = 0; + LLUUID AuthBuyerID = new LLUUID(); // Marked + LLUUID SnapshotID = new LLUUID(); // -> SnapshotID + LLVector3 UserLocation = new LLVector3(); + LLVector3 UserLookAt = new LLVector3(); + byte LandingType = 0; + + foreach( Block block in packet.Blocks()) + { + foreach(Field field in block.Fields) + { + if(field.Layout.Name == "RequestResult") + RequestResult = (int)field.Data; + else if(field.Layout.Name == "SequenceID") + SequenceID = (int)field.Data; + else if(field.Layout.Name == "SnapSelection") + SnapSelection = (bool)field.Data; + else if(field.Layout.Name == "SelfCount") + SelfCount = (int)field.Data; + else if(field.Layout.Name == "OtherCount") + OtherCount = (int)field.Data; + else if(field.Layout.Name == "PublicCount") + PublicCount = (int)field.Data; + else if(field.Layout.Name == "LocalID") + LocalID = (int)field.Data; + else if(field.Layout.Name == "OwnerID") + OwnerID = (LLUUID)field.Data; + else if(field.Layout.Name == "IsGroupOwned") + IsGroupOwned = (bool)field.Data; + else if(field.Layout.Name == "AuctionID") + AuctionID = (uint)field.Data; + else if(field.Layout.Name == "ReservedNewbie") + ReservedNewbie = (bool)field.Data; + else if(field.Layout.Name == "ClaimDate") + ClaimDate = (int)field.Data; + else if(field.Layout.Name == "ClaimPrice") + ClaimPrice = (int)field.Data; + else if(field.Layout.Name == "RentPrice") + RentPrice = (int)field.Data; + else if(field.Layout.Name == "AABBMin") + AABBMin = (LLVector3)field.Data; + else if(field.Layout.Name == "AABBMax") + AABBMax = (LLVector3)field.Data; + else if(field.Layout.Name == "Bitmap") + Bitmap = (byte[])field.Data; + else if(field.Layout.Name == "Area") + Area = (int)field.Data; + else if(field.Layout.Name == "Status") + Status = (byte)field.Data; + else if(field.Layout.Name == "SimWideMaxObjects") + SimWideMaxObjects = (int)field.Data; + else if(field.Layout.Name == "SimWideTotalObjects") + SimWideTotalObjects = (int)field.Data; + else if(field.Layout.Name == "MaxObjects") + MaxObjects = (int)field.Data; + else if(field.Layout.Name == "TotalObjects") + TotalObjects = (int)field.Data; + else if(field.Layout.Name == "OwnerObjects") + OwnerObjects = (int)field.Data; + else if(field.Layout.Name == "GroupObjects") + GroupObjects = (int)field.Data; + else if(field.Layout.Name == "OtherObjects") + OtherObjects = (int)field.Data; + else if(field.Layout.Name == "ParcelObjectBonus") + ParcelObjectBonus = (float)field.Data; + else if(field.Layout.Name == "OtherCleanTime") + OtherCleanTime = (int)field.Data; + else if(field.Layout.Name == "ParcelFlags") + ParcelFlags = (uint)field.Data; + else if(field.Layout.Name == "SalePrice") + SalePrice = (int)field.Data; + else if(field.Layout.Name == "Name") + Name = System.Text.Encoding.UTF8.GetString((byte[])field.Data).Replace("\0", ""); + else if(field.Layout.Name == "Desc") + Desc = System.Text.Encoding.UTF8.GetString((byte[])field.Data).Replace("\0", ""); + else if(field.Layout.Name == "MusicURL") + MusicURL = System.Text.Encoding.UTF8.GetString((byte[])field.Data).Replace("\0", ""); + else if(field.Layout.Name == "MediaURL") + MediaURL = System.Text.Encoding.UTF8.GetString((byte[])field.Data).Replace("\0", ""); + else if(field.Layout.Name == "MediaID") + MediaID = (LLUUID)field.Data; + else if(field.Layout.Name == "MediaAutoScale") + MediaAutoScale = (byte)field.Data; + else if(field.Layout.Name == "GroupID") + GroupID = (LLUUID)field.Data; + else if(field.Layout.Name == "PassPrice") + PassPrice = (int)field.Data; + else if(field.Layout.Name == "PassHours") + PassHours = (float)field.Data; + else if(field.Layout.Name == "Category") + Category = (byte)field.Data; + else if(field.Layout.Name == "AuthBuyerID") + AuthBuyerID = (LLUUID)field.Data; + else if(field.Layout.Name == "SnapshotID") + SnapshotID = (LLUUID)field.Data; + else if(field.Layout.Name == "UserLocation") + UserLocation = (LLVector3)field.Data; + else if(field.Layout.Name == "UserLookAt") + UserLookAt = (LLVector3)field.Data; + else if(field.Layout.Name == "LandingType") + LandingType = (byte)field.Data; +// else +// Helpers.Log("Unknown field type '" + field.Layout.Name + "' in ParcelProperties",Helpers.LogLevel.Warning); + + } + } + + /* Mark this area as downloaded */ + int x, y, index, subindex; + byte val; + + for(x = 0; x < 64; x++) + { + for(y = 0; y < 64; y++) + { + if(simulator.Region.ParcelMarked[y,x] == 0) + { + index = ((x * 64) + y); + subindex = index % 8; + index /= 8; + + val = Bitmap[index]; + + simulator.Region.ParcelMarked[y,x] = ((val >> subindex) & 1) == 1 ? LocalID : 0; + } + } + } + + /* Fire off the next request, if we are downloading the whole sim */ + bool hasTriggered = false; + if(simulator.Region.ParcelDownloading == true) + { + for(x = 0; x < 64; x++) + { + for(y = 0; y < 64; y++) + { + if(simulator.Region.ParcelMarked[x,y] == 0) + { + Client.Network.SendPacket(libsecondlife.Packets.Parcel.ParcelPropertiesRequest(Client.Protocol,Client.Avatar.ID, -10000 - (x*64) - y, + (x*4.0f),(y*4.0f),(x*4.0f) + 4.0f,(y*4.0f) + 4.0f, false)); + hasTriggered = true; + + goto exit; + } + } + } + exit:; + } + + /* This map is complete, fire callback */ + if(hasTriggered == false) + { + simulator.Region.FilledParcels(); + } + + /* Save this parcels data */ + // TODO: Lots of values are not being stored, Parcel needs to be expanded to take all the data. + simulator.Region.ParcelsMutex.WaitOne(); + + if(!simulator.Region.Parcels.ContainsKey(LocalID)) + { + simulator.Region.Parcels[LocalID] = new Parcel(simulator); + } + + // God help me should I have to type this out again... argh. + ((Parcel)simulator.Region.Parcels[LocalID]).RequestResult = RequestResult; + ((Parcel)simulator.Region.Parcels[LocalID]).SequenceID = SequenceID; + ((Parcel)simulator.Region.Parcels[LocalID]).SnapSelection = SnapSelection; + ((Parcel)simulator.Region.Parcels[LocalID]).SelfCount = SelfCount; + ((Parcel)simulator.Region.Parcels[LocalID]).OtherCount = OtherCount; + ((Parcel)simulator.Region.Parcels[LocalID]).PublicCount = PublicCount; + ((Parcel)simulator.Region.Parcels[LocalID]).LocalID = LocalID; + ((Parcel)simulator.Region.Parcels[LocalID]).OwnerID = OwnerID; + ((Parcel)simulator.Region.Parcels[LocalID]).IsGroupOwned = IsGroupOwned; + ((Parcel)simulator.Region.Parcels[LocalID]).AuctionID = AuctionID; + ((Parcel)simulator.Region.Parcels[LocalID]).ReservedNewbie = ReservedNewbie; + ((Parcel)simulator.Region.Parcels[LocalID]).ClaimDate = ClaimDate; + ((Parcel)simulator.Region.Parcels[LocalID]).ClaimPrice = ClaimPrice; + ((Parcel)simulator.Region.Parcels[LocalID]).RentPrice = RentPrice; + ((Parcel)simulator.Region.Parcels[LocalID]).AABBMin = AABBMin; + ((Parcel)simulator.Region.Parcels[LocalID]).AABBMax = AABBMax; + ((Parcel)simulator.Region.Parcels[LocalID]).Bitmap = Bitmap; + ((Parcel)simulator.Region.Parcels[LocalID]).Area = Area; + ((Parcel)simulator.Region.Parcels[LocalID]).Status = Status; + ((Parcel)simulator.Region.Parcels[LocalID]).SimWideMaxObjects = SimWideMaxObjects; + ((Parcel)simulator.Region.Parcels[LocalID]).SimWideTotalObjects = SimWideTotalObjects; + ((Parcel)simulator.Region.Parcels[LocalID]).MaxObjects = MaxObjects; + ((Parcel)simulator.Region.Parcels[LocalID]).TotalObjects = TotalObjects; + ((Parcel)simulator.Region.Parcels[LocalID]).OwnerObjects = OwnerObjects; + ((Parcel)simulator.Region.Parcels[LocalID]).GroupObjects = GroupObjects; + ((Parcel)simulator.Region.Parcels[LocalID]).OtherObjects = OtherObjects; + ((Parcel)simulator.Region.Parcels[LocalID]).ParcelObjectBonus = ParcelObjectBonus; + ((Parcel)simulator.Region.Parcels[LocalID]).OtherCleanTime = OtherCleanTime; + ((Parcel)simulator.Region.Parcels[LocalID]).ParcelFlags = ParcelFlags; + ((Parcel)simulator.Region.Parcels[LocalID]).SalePrice = SalePrice; + ((Parcel)simulator.Region.Parcels[LocalID]).Name = Name; + ((Parcel)simulator.Region.Parcels[LocalID]).Desc = Desc; + ((Parcel)simulator.Region.Parcels[LocalID]).MusicURL = MusicURL; + ((Parcel)simulator.Region.Parcels[LocalID]).MediaURL = MediaURL; + ((Parcel)simulator.Region.Parcels[LocalID]).MediaID = MediaID; + ((Parcel)simulator.Region.Parcels[LocalID]).MediaAutoScale = MediaAutoScale; + ((Parcel)simulator.Region.Parcels[LocalID]).GroupID = GroupID; + ((Parcel)simulator.Region.Parcels[LocalID]).PassPrice = PassPrice; + ((Parcel)simulator.Region.Parcels[LocalID]).PassHours = PassHours; + ((Parcel)simulator.Region.Parcels[LocalID]).Category = Category; + ((Parcel)simulator.Region.Parcels[LocalID]).AuthBuyerID = AuthBuyerID; + ((Parcel)simulator.Region.Parcels[LocalID]).SnapshotID = SnapshotID; + ((Parcel)simulator.Region.Parcels[LocalID]).UserLocation = UserLocation; + ((Parcel)simulator.Region.Parcels[LocalID]).UserLookAt = UserLookAt; + ((Parcel)simulator.Region.Parcels[LocalID]).LandingType = LandingType; + + simulator.Region.ParcelsMutex.ReleaseMutex(); + } + + private void ParcelInfoReplyHandler(Packet packet, Simulator simulator) + { +======= */ using System; @@ -379,6 +897,7 @@ private void ParcelInfoReplyHandler(Packet packet, Simulator simulator) { +>>>>>>> .r114 string simName = ""; int actualArea = 0; float globalX = 0.0F; @@ -473,6 +992,149 @@ ParcelInfoParcel.SalePrice = salePrice; ParcelInfoParcel.OwnerID = ownerID; ParcelInfoParcel.SnapshotID = snapshotID; +<<<<<<< .mine + ParcelInfoParcel.Dwell = dwell; + + // Get RegionHandle from GlobalX/GlobalY + uint handleX = (uint)Math.Floor(ParcelInfoParcel.GlobalPosition.X / 256.0F); + handleX *= 256; + uint handleY = (uint)Math.Floor(ParcelInfoParcel.GlobalPosition.Y / 256.0F); + handleY *= 256; + ParcelInfoParcel.RegionHandle = new U64(handleX, handleY); + + // Get SimPosition from GlobalX/GlobalY and RegionHandle + ParcelInfoParcel.SimPosition.X = ParcelInfoParcel.GlobalPosition.X - (float)handleX; + ParcelInfoParcel.SimPosition.Y = ParcelInfoParcel.GlobalPosition.Y - (float)handleY; + ParcelInfoParcel.SimPosition.Z = ParcelInfoParcel.GlobalPosition.Z; + } + catch (Exception e) + { + Helpers.Log(e.ToString(), Helpers.LogLevel.Error); + } + + Finished = true; + } + + private void ParcelInfoTimerEvent(object source, System.Timers.ElapsedEventArgs ea) + { + ParcelInfoTimeout = true; + } + + public int DirLandRequest(bool reservedNewbie, bool forSale, bool auction) + { + // Set the class-wide variables so the callback has them + ReservedNewbie = reservedNewbie; + ForSale = forSale; + Auction = auction; + + // Clear the list + ParcelsForSale.Clear(); + + // Setup the timer + DirLandTimer = new Timer(15000); + DirLandTimer.Elapsed += new ElapsedEventHandler(DirLandTimerEvent); + DirLandTimeout = false; + DirLandTimer.Start(); + + LLUUID queryID = new LLUUID(); + Packet landQuery = Packets.Sim.DirLandQuery(Client.Protocol, ReservedNewbie, ForSale, queryID, + Auction, 0, Client.Network.AgentID, Client.Network.SessionID); + Client.Network.SendPacket(landQuery); + + while (!DirLandTimeout) + { + Client.Tick(); + } + + // Double check the timer is actually stopped + DirLandTimer.Stop(); + + return ParcelsForSale.Count; + } + + private void DirLandReplyHandler(Packet packet, Simulator simulator) + { + if (!DirLandTimeout) + { + // Reset the timer + DirLandTimer.Stop(); + DirLandTimer.Start(); + + foreach (Block block in packet.Blocks()) + { + DirectoryParcel parcel = new DirectoryParcel(); + + if (block.Layout.Name == "QueryReplies") + { + foreach (Field field in block.Fields) + { + if (field.Layout.Name == "ReservedNewbie") + { + if ((bool)field.Data != ReservedNewbie) + { + goto Skip; + } + } + else if (field.Layout.Name == "Auction") + { + if ((bool)field.Data != Auction) + { + goto Skip; + } + } + else if (field.Layout.Name == "ForSale") + { + if ((bool)field.Data != ForSale) + { + goto Skip; + } + } + else if (field.Layout.Name == "ParcelID") + { + parcel.ID = (LLUUID)field.Data; + } + else if (field.Layout.Name == "Name") + { + parcel.Name = System.Text.Encoding.UTF8.GetString((byte[])field.Data).Replace("\0", ""); + } + else if (field.Layout.Name == "ActualArea") + { + parcel.ActualArea = (int)field.Data; + } + else if (field.Layout.Name == "SalePrice") + { + parcel.SalePrice = (int)field.Data; + } + } + + if (parcel.ID != null) + { + ParcelsForSale.Add(parcel); + } + else + { + Helpers.Log("Parcel with no ID found in DirLandReply, skipping", Helpers.LogLevel.Warning); + } + } + + Skip: + ; + } + } + else + { + Console.WriteLine("Received a DirLandReply after the timeout!"); + } + } + + private void DirLandTimerEvent(object source, System.Timers.ElapsedEventArgs ea) + { + DirLandTimer.Stop(); + DirLandTimeout = true; + } + } +} +======= ParcelInfoParcel.Dwell = dwell; // Get RegionHandle from GlobalX/GlobalY @@ -614,3 +1276,4 @@ } } } +>>>>>>> .r114 Index: Region.cs =================================================================== --- Region.cs (revision 114) +++ Region.cs (working copy) @@ -28,6 +28,8 @@ namespace libsecondlife { + public delegate void ParcelCompleteCallback(Region region); + /// <summary> /// Represents a region (also known as a sim) in Second Life. /// </summary> @@ -70,6 +72,8 @@ private SecondLife Client; + public event ParcelCompleteCallback OnParcelCompletion; + public Region(SecondLife client) { Client = client; @@ -156,6 +160,17 @@ 0.0f,0.0f,4.0f,4.0f, false)); } +<<<<<<< .mine + public void FilledParcels() + { + if(OnParcelCompletion != null) + { + OnParcelCompletion(this); + } + } + +======= +>>>>>>> .r114 public override int GetHashCode() { return ID.GetHashCode();
_______________________________________________ libsecondlife-dev mailing list libsecondlife-dev@gna.org https://mail.gna.org/listinfo/libsecondlife-dev