/*
* Copyright (c) 2006-2008, openmetaverse.org
* 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 openmetaverse.org 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 System.Threading;
using OpenMetaverse.Packets;
namespace OpenMetaverse
{
///
/// Access to the Linden dataserver which allows searching for land, events, people, etc
///
public class DirectoryManager
{
///
/// The different categories a classified ad can be placed in
///
public enum ClassifiedCategories
{
///
Any = 0,
///
Shopping,
///
LandRental,
///
PropertyRental,
///
SpecialAttraction,
///
NewProducts,
///
Employment,
///
Wanted,
///
Service,
///
Personal
}
public enum EventCategories
{
All = 0,
Discussion = 18,
Sports = 19,
LiveMusic = 20,
Commercial = 22,
Nightlife = 23,
Games = 24,
Pageants = 25,
Education = 26,
Arts = 27,
Charity = 28,
Miscellaneous = 29
}
///
///
///
[Flags]
public enum DirFindFlags
{
///
People = 1 << 0,
///
Online = 1 << 1,
//
//[Obsolete]
//Places = 1 << 2,
///
Events = 1 << 3,
///
Groups = 1 << 4,
///
DateEvents = 1 << 5,
///
AgentOwned = 1 << 6,
///
ForSale = 1 << 7,
///
GroupOwned = 1 << 8,
//
//[Obsolete]
//Auction = 1 << 9,
///
DwellSort = 1 << 10,
///
PgSimsOnly = 1 << 11,
///
PicturesOnly = 1 << 12,
///
PgEventsOnly = 1 << 13,
///
MatureSimsOnly = 1 << 14,
///
SortAsc = 1 << 15,
///
PricesSort = 1 << 16,
///
PerMeterSort = 1 << 17,
///
AreaSort = 1 << 18,
///
NameSort = 1 << 19,
///
LimitByPrice = 1 << 20,
///
LimitByArea = 1 << 21
}
///
/// Land types to search dataserver for
///
[Flags]
public enum SearchTypeFlags
{
/// Do not search
None = 0,
/// Land which is currently up for auction
Auction = 1 << 1,
// Land available to new landowners (formerly the FirstLand program)
//[Obsolete]
//Newbie = 1 << 2,
/// Parcels which are on the mainland (Linden owned) continents
Mainland = 1 << 3,
/// Parcels which are on privately owned simulators
Estate = 1 << 4
}
[Flags]
public enum EventFlags
{
None = 0,
Mature = 1 << 1
}
///
/// A classified ad on the grid
///
public struct Classified
{
/// UUID for this ad, useful for looking up detailed
/// information about it
public UUID ID;
/// The title of this classified ad
public string Name;
/// Unknown
public byte Flags;
/// Creation date of the ad
public DateTime CreationDate;
/// Expiration date of the ad
public DateTime ExpirationDate;
/// Price that was paid for this ad
public int Price;
}
///
/// A parcel retrieved from the dataserver such as results from the
/// "For-Sale" listings
///
public struct DirectoryParcel
{
///
public UUID ID;
///
public string Name;
///
public int ActualArea;
///
public int SalePrice;
///
public bool Auction;
///
public bool ForSale;
}
///
/// An Avatar returned from the dataserver
///
public struct AgentSearchData
{
/// Online status of agent
public bool Online;
/// Agents first name
public string FirstName;
/// Agents last name
public string LastName;
/// Agents
public UUID AgentID;
}
///
/// Response to a "Groups" Search
///
public struct GroupSearchData
{
public UUID GroupID;
public string GroupName;
public int Members;
}
///
/// Response to a "Places" Search
/// Note: This is not DirPlacesReply
///
public struct PlacesSearchData
{
public UUID OwnerID;
public string Name;
public string Desc;
public int ActualArea;
public int BillableArea;
public byte Flags;
public float GlobalX;
public float GlobalY;
public float GlobalZ;
public string SimName;
public UUID SnapshotID;
public float Dwell;
public int Price;
}
///
/// Response to "Events" search
///
public struct EventsSearchData
{
public UUID Owner;
public string Name;
public uint ID;
public string Date;
public uint Time;
public EventFlags Flags;
}
///
/// an Event returned from the dataserver
///
public struct EventInfo
{
public uint ID;
public UUID Creator;
public string Name;
public EventCategories Category;
public string Desc;
public string Date;
public UInt32 DateUTC;
public UInt32 Duration;
public UInt32 Cover;
public UInt32 Amount;
public string SimName;
public Vector3d GlobalPos;
public EventFlags Flags;
}
///
///
///
///
public delegate void ClassifiedReplyCallback(List classifieds);
///
///
///
///
public delegate void DirLandReplyCallback(List dirParcels);
///
///
///
///
///
public delegate void DirPeopleReplyCallback(UUID queryID, List matchedPeople);
///
///
///
///
///
public delegate void DirGroupsReplyCallback(UUID queryID, List matchedGroups);
///
///
///
///
///
public delegate void PlacesReplyCallback(UUID queryID, List matchedPlaces);
///
///
///
///
///
public delegate void EventReplyCallback(UUID queryID, List matchedEvents);
///
///
///
///
public delegate void EventInfoCallback(EventInfo matchedEvent);
///
///
///
public event ClassifiedReplyCallback OnClassifiedReply;
///
///
///
public event DirLandReplyCallback OnDirLandReply;
public event DirPeopleReplyCallback OnDirPeopleReply;
public event DirGroupsReplyCallback OnDirGroupsReply;
public event PlacesReplyCallback OnPlacesReply;
// List of Events
public event EventReplyCallback OnEventsReply;
// Event Details
public event EventInfoCallback OnEventInfo;
private GridClient Client;
public DirectoryManager(GridClient client)
{
Client = client;
Client.Network.RegisterCallback(PacketType.DirClassifiedReply, new NetworkManager.PacketCallback(DirClassifiedReplyHandler));
Client.Network.RegisterCallback(PacketType.DirLandReply, new NetworkManager.PacketCallback(DirLandReplyHandler));
Client.Network.RegisterCallback(PacketType.DirPeopleReply, new NetworkManager.PacketCallback(DirPeopleReplyHandler));
Client.Network.RegisterCallback(PacketType.DirGroupsReply, new NetworkManager.PacketCallback(DirGroupsReplyHandler));
Client.Network.RegisterCallback(PacketType.PlacesReply, new NetworkManager.PacketCallback(PlacesReplyHandler));
Client.Network.RegisterCallback(PacketType.DirEventsReply, new NetworkManager.PacketCallback(EventsReplyHandler));
Client.Network.RegisterCallback(PacketType.EventInfoReply, new NetworkManager.PacketCallback(EventInfoReplyHandler));
}
public UUID StartClassifiedSearch(string searchText, ClassifiedCategories categories, bool mature)
{
DirClassifiedQueryPacket query = new DirClassifiedQueryPacket();
UUID queryID = UUID.Random();
query.AgentData.AgentID = Client.Self.AgentID;
query.AgentData.SessionID = Client.Self.SessionID;
query.QueryData.Category = (uint)categories;
query.QueryData.QueryFlags = (uint)(mature ? 0 : 2);
query.QueryData.QueryID = queryID;
query.QueryData.QueryText = Utils.StringToBytes(searchText);
Client.Network.SendPacket(query);
return queryID;
}
///
/// Starts a search for land sales using the directory
///
/// What type of land to search for. Auction,
/// estate, mainland, "first land", etc
/// A unique identifier that can identify packets associated
/// with this query from other queries
/// The OnDirLandReply event handler must be registered before
/// calling this function. There is no way to determine how many
/// results will be returned, or how many times the callback will be
/// fired other than you won't get more than 100 total parcels from
/// each query.
public UUID StartLandSearch(SearchTypeFlags typeFlags)
{
return StartLandSearch(DirFindFlags.SortAsc | DirFindFlags.PerMeterSort, typeFlags, 0, 0, 0);
}
///
/// Starts a search for land sales using the directory
///
/// What type of land to search for. Auction,
/// estate, mainland, "first land", etc
/// Maximum price to search for
/// Maximum area to search for
/// Each request is limited to 100 parcels
/// being returned. To get the first 100 parcels of a request use 0,
/// from 100-199 use 1, 200-299 use 2, etc.
/// A unique identifier that can identify packets associated
/// with this query from other queries
/// The OnDirLandReply event handler must be registered before
/// calling this function. There is no way to determine how many
/// results will be returned, or how many times the callback will be
/// fired other than you won't get more than 100 total parcels from
/// each query.
public UUID StartLandSearch(SearchTypeFlags typeFlags, int priceLimit, int areaLimit, int queryStart)
{
return StartLandSearch(DirFindFlags.SortAsc | DirFindFlags.PerMeterSort | DirFindFlags.LimitByPrice |
DirFindFlags.LimitByArea, typeFlags, priceLimit, areaLimit, queryStart);
}
///
/// Starts a search for land sales using the directory
///
/// A flags parameter that can modify the way
/// search results are returned, for example changing the ordering of
/// results or limiting based on price or area
/// What type of land to search for. Auction,
/// estate, mainland, "first land", etc
/// Maximum price to search for, the
/// DirFindFlags.LimitByPrice flag must be set
/// Maximum area to search for, the
/// DirFindFlags.LimitByArea flag must be set
/// Each request is limited to 100 parcels
/// being returned. To get the first 100 parcels of a request use 0,
/// from 100-199 use 100, 200-299 use 200, etc.
/// A unique identifier that can identify packets associated
/// with this query from other queries
/// The OnDirLandReply event handler must be registered before
/// calling this function. There is no way to determine how many
/// results will be returned, or how many times the callback will be
/// fired other than you won't get more than 100 total parcels from
/// each query.
public UUID StartLandSearch(DirFindFlags findFlags, SearchTypeFlags typeFlags, int priceLimit,
int areaLimit, int queryStart)
{
UUID queryID = UUID.Random();
DirLandQueryPacket query = new DirLandQueryPacket();
query.AgentData.AgentID = Client.Self.AgentID;
query.AgentData.SessionID = Client.Self.SessionID;
query.QueryData.Area = areaLimit;
query.QueryData.Price = priceLimit;
query.QueryData.QueryStart = queryStart;
query.QueryData.SearchType = (uint)typeFlags;
query.QueryData.QueryFlags = (uint)findFlags;
query.QueryData.QueryID = queryID;
Client.Network.SendPacket(query);
return queryID;
}
///
/// Starts a search for a Group in the directory manager
///
///
/// The text to search for
/// Each request is limited to 100 parcels
/// being returned. To get the first 100 parcels of a request use 0,
/// from 100-199 use 100, 200-299 use 200, etc.
/// A unique identifier that can identify packets associated
/// with this query from other queries
/// The OnDirLandReply event handler must be registered before
/// calling this function. There is no way to determine how many
/// results will be returned, or how many times the callback will be
/// fired other than you won't get more than 100 total parcels from
/// each query.
public UUID StartGroupSearch(DirFindFlags findFlags, string searchText, int queryStart)
{
return StartGroupSearch(findFlags, searchText, queryStart, UUID.Random());
}
public UUID StartGroupSearch(DirFindFlags findFlags, string searchText, int queryStart, UUID queryID)
{
DirFindQueryPacket find = new DirFindQueryPacket();
find.AgentData.AgentID = Client.Self.AgentID;
find.AgentData.SessionID = Client.Self.SessionID;
find.QueryData.QueryFlags = (uint)findFlags;
find.QueryData.QueryText = Utils.StringToBytes(searchText);
find.QueryData.QueryID = queryID;
find.QueryData.QueryStart = queryStart;
Client.Network.SendPacket(find);
return queryID;
}
public UUID StartPeopleSearch(DirFindFlags findFlags, string searchText, int queryStart)
{
return StartPeopleSearch(findFlags, searchText, queryStart, UUID.Random());
}
public UUID StartPeopleSearch(DirFindFlags findFlags, string searchText, int queryStart, UUID queryID)
{
DirFindQueryPacket find = new DirFindQueryPacket();
find.AgentData.AgentID = Client.Self.AgentID;
find.AgentData.SessionID = Client.Self.SessionID;
find.QueryData.QueryFlags = (uint)findFlags;
find.QueryData.QueryText = Utils.StringToBytes(searchText);
find.QueryData.QueryID = queryID;
find.QueryData.QueryStart = queryStart;
Client.Network.SendPacket(find);
return queryID;
}
///
/// Search "places" for Land you personally own
///
public UUID StartPlacesSearch()
{
return StartPlacesSearch(DirFindFlags.AgentOwned, Parcel.ParcelCategory.Any, String.Empty, String.Empty,
UUID.Zero, UUID.Zero);
}
///
/// Searches Places for Land owned by a specific user or group
///
/// One of the Values from the DirFindFlags struct, ie: AgentOwned, GroupOwned, etc.
/// LLUID of group you want to recieve land list for (You must be in group), or
/// LLUID.Zero for Your own land
/// Transaction (Query) ID which can be associated with results from your request.
public UUID StartPlacesSearch(DirFindFlags findFlags, UUID groupID)
{
return StartPlacesSearch(findFlags, Parcel.ParcelCategory.Any, String.Empty, String.Empty, groupID,
UUID.Random());
}
///
/// Search Places
///
/// One of the Values from the DirFindFlags struct, ie: AgentOwned, GroupOwned, etc.
/// One of the values from the SearchCategory Struct, ie: Any, Linden, Newcomer
/// LLUID of group you want to recieve results for
/// Transaction (Query) ID which can be associated with results from your request.
/// Transaction (Query) ID which can be associated with results from your request.
public UUID StartPlacesSearch(DirFindFlags findFlags, Parcel.ParcelCategory searchCategory, UUID groupID, UUID transactionID)
{
return StartPlacesSearch(findFlags, searchCategory, String.Empty, String.Empty, groupID, transactionID);
}
///
/// Search Places - All Options
///
/// One of the Values from the DirFindFlags struct, ie: AgentOwned, GroupOwned, etc.
/// One of the values from the SearchCategory Struct, ie: Any, Linden, Newcomer
/// String Text to search for
/// String Simulator Name to search in
/// LLUID of group you want to recieve results for
/// Transaction (Query) ID which can be associated with results from your request.
/// Transaction (Query) ID which can be associated with results from your request.
public UUID StartPlacesSearch(DirFindFlags findFlags, Parcel.ParcelCategory searchCategory, string searchText, string simulatorName, UUID groupID, UUID transactionID)
{
PlacesQueryPacket find = new PlacesQueryPacket();
find.AgentData.AgentID = Client.Self.AgentID;
find.AgentData.SessionID = Client.Self.SessionID;
find.AgentData.QueryID = groupID;
find.TransactionData.TransactionID = transactionID;
find.QueryData.QueryText = Utils.StringToBytes(searchText);
find.QueryData.QueryFlags = (uint)findFlags;
find.QueryData.Category = (sbyte)searchCategory;
find.QueryData.SimName = Utils.StringToBytes(simulatorName);
Client.Network.SendPacket(find);
return transactionID;
}
///
/// Search All Events with specifid searchText in all categories, includes Mature
///
/// Text to search for
/// UUID of query to correlate results in callback.
public UUID StartEventsSearch(string searchText)
{
return StartEventsSearch(searchText, true, EventCategories.All);
}
///
/// Search Events with Options to specify category and Mature events.
///
/// Text to search for
/// true to include Mature events
/// category to search
/// UUID of query to correlate results in callback.
public UUID StartEventsSearch(string searchText, bool showMature, EventCategories category)
{
return StartEventsSearch(searchText, showMature, "u", 0, category, UUID.Random());
}
///
/// Search Events - ALL options
///
/// string text to search for e.g.: live music
/// Include mature events in results
/// "u" for now and upcoming events, -or- number of days since/until event is scheduled
/// For example "0" = Today, "1" = tomorrow, "2" = following day, "-1" = yesterday, etc.
/// Page # to show, 0 for First Page
/// EventCategory event is listed under.
/// a UUID that can be used to track queries with results.
/// UUID of query to correlate results in callback.
public UUID StartEventsSearch(string searchText, bool showMature, string eventDay, uint queryStart, EventCategories category, UUID queryID)
{
DirFindQueryPacket find = new DirFindQueryPacket();
find.AgentData.AgentID = Client.Self.AgentID;
find.AgentData.SessionID = Client.Self.SessionID;
find.QueryData.QueryID = queryID;
find.QueryData.QueryText = Utils.StringToBytes(eventDay + "|" + (int)category + "|" + searchText);
find.QueryData.QueryFlags = showMature ? (uint)32 : (uint)8224;
find.QueryData.QueryStart = (int)queryStart;
Client.Network.SendPacket(find);
return queryID;
}
/// Requests Event Details
/// ID of Event returned from Places Search
public void EventInfoRequest(uint eventID)
{
EventInfoRequestPacket find = new EventInfoRequestPacket();
find.AgentData.AgentID = Client.Self.AgentID;
find.AgentData.SessionID = Client.Self.SessionID;
find.EventData.EventID = eventID;
Client.Network.SendPacket(find);
}
#region Blocking Functions
public bool PeopleSearch(DirFindFlags findFlags, string searchText, int queryStart,
int timeoutMS, out List results)
{
AutoResetEvent searchEvent = new AutoResetEvent(false);
UUID id = UUID.Random();
List people = null;
DirPeopleReplyCallback callback =
delegate(UUID queryid, List matches)
{
if (id == queryid)
{
people = matches;
searchEvent.Set();
}
};
OnDirPeopleReply += callback;
StartPeopleSearch(findFlags, searchText, queryStart, id);
searchEvent.WaitOne(timeoutMS, false);
OnDirPeopleReply -= callback;
results = people;
return (results != null);
}
#endregion Blocking Functions
#region Packet Handlers
private void DirClassifiedReplyHandler(Packet packet, Simulator simulator)
{
if (OnClassifiedReply != null)
{
DirClassifiedReplyPacket reply = (DirClassifiedReplyPacket)packet;
List classifieds = new List();
foreach (DirClassifiedReplyPacket.QueryRepliesBlock block in reply.QueryReplies)
{
Classified classified = new Classified();
classified.CreationDate = Utils.UnixTimeToDateTime(block.CreationDate);
classified.ExpirationDate = Utils.UnixTimeToDateTime(block.ExpirationDate);
classified.Flags = block.ClassifiedFlags;
classified.ID = block.ClassifiedID;
classified.Name = Utils.BytesToString(block.Name);
classified.Price = block.PriceForListing;
classifieds.Add(classified);
}
try { OnClassifiedReply(classifieds); }
catch (Exception e) { Logger.Log(e.Message, Helpers.LogLevel.Error, Client, e); }
}
}
private void DirLandReplyHandler(Packet packet, Simulator simulator)
{
if (OnDirLandReply != null)
{
List parcelsForSale = new List();
DirLandReplyPacket reply = (DirLandReplyPacket)packet;
foreach (DirLandReplyPacket.QueryRepliesBlock block in reply.QueryReplies)
{
DirectoryParcel dirParcel = new DirectoryParcel();
dirParcel.ActualArea = block.ActualArea;
dirParcel.ID = block.ParcelID;
dirParcel.Name = Utils.BytesToString(block.Name);
dirParcel.SalePrice = block.SalePrice;
dirParcel.Auction = block.Auction;
dirParcel.ForSale = block.ForSale;
parcelsForSale.Add(dirParcel);
}
try { OnDirLandReply(parcelsForSale); }
catch (Exception e) { Logger.Log(e.Message, Helpers.LogLevel.Error, Client, e); }
}
}
protected void DirPeopleReplyHandler(Packet packet, Simulator simulator)
{
if (OnDirPeopleReply != null)
{
DirPeopleReplyPacket peopleReply = packet as DirPeopleReplyPacket;
List matches = new List(peopleReply.QueryReplies.Length);
foreach (DirPeopleReplyPacket.QueryRepliesBlock reply in peopleReply.QueryReplies) {
AgentSearchData searchData = new AgentSearchData();
searchData.Online = reply.Online;
searchData.FirstName = Utils.BytesToString(reply.FirstName);
searchData.LastName = Utils.BytesToString(reply.LastName);
searchData.AgentID = reply.AgentID;
matches.Add(searchData);
}
try { OnDirPeopleReply(peopleReply.QueryData.QueryID, matches); }
catch (Exception e) { Logger.Log(e.Message, Helpers.LogLevel.Error, Client, e); }
}
}
protected void DirGroupsReplyHandler(Packet packet, Simulator simulator)
{
if (OnDirGroupsReply != null)
{
DirGroupsReplyPacket groupsReply = packet as DirGroupsReplyPacket;
List matches = new List(groupsReply.QueryReplies.Length);
foreach (DirGroupsReplyPacket.QueryRepliesBlock reply in groupsReply.QueryReplies)
{
GroupSearchData groupsData = new GroupSearchData();
groupsData.GroupID = reply.GroupID;
groupsData.GroupName = Utils.BytesToString(reply.GroupName);
groupsData.Members = reply.Members;
matches.Add(groupsData);
}
try { OnDirGroupsReply(groupsReply.QueryData.QueryID, matches); }
catch (Exception e) { Logger.Log(e.Message, Helpers.LogLevel.Error, Client, e); }
}
}
private void PlacesReplyHandler(Packet packet, Simulator simulator)
{
if (OnPlacesReply != null)
{
PlacesReplyPacket placesReply = packet as PlacesReplyPacket;
List places = new List();
foreach (PlacesReplyPacket.QueryDataBlock block in placesReply.QueryData)
{
PlacesSearchData place = new PlacesSearchData();
place.OwnerID = block.OwnerID;
place.Name = Utils.BytesToString(block.Name);
place.Desc = Utils.BytesToString(block.Desc);
place.ActualArea = block.ActualArea;
place.BillableArea = block.BillableArea;
place.Flags = block.Flags;
place.GlobalX = block.GlobalX;
place.GlobalY = block.GlobalY;
place.GlobalZ = block.GlobalZ;
place.SimName = Utils.BytesToString(block.SimName);
place.SnapshotID = block.SnapshotID;
place.Dwell = block.Dwell;
place.Price = block.Price;
places.Add(place);
}
try { OnPlacesReply(placesReply.TransactionData.TransactionID, places); }
catch (Exception e) { Logger.Log(e.Message, Helpers.LogLevel.Error, Client, e); }
}
}
private void EventsReplyHandler(Packet packet, Simulator simulator)
{
if (OnEventsReply != null)
{
DirEventsReplyPacket eventsReply = packet as DirEventsReplyPacket;
List matches = new List(eventsReply.QueryReplies.Length);
foreach (DirEventsReplyPacket.QueryRepliesBlock reply in eventsReply.QueryReplies)
{
EventsSearchData eventsData = new EventsSearchData();
eventsData.Owner = reply.OwnerID;
eventsData.Name = Utils.BytesToString(reply.Name);
eventsData.ID = reply.EventID;
eventsData.Date = Utils.BytesToString(reply.Date);
eventsData.Time = reply.UnixTime;
eventsData.Flags = (EventFlags)reply.EventFlags;
matches.Add(eventsData);
}
try { OnEventsReply(eventsReply.QueryData.QueryID, matches); }
catch (Exception e) { Logger.Log(e.Message, Helpers.LogLevel.Error, Client, e); }
}
}
private void EventInfoReplyHandler(Packet packet, Simulator simulator)
{
if (OnEventInfo != null)
{
EventInfoReplyPacket eventReply = (EventInfoReplyPacket)packet;
EventInfo evinfo = new EventInfo();
evinfo.ID = eventReply.EventData.EventID;
evinfo.Name = Utils.BytesToString(eventReply.EventData.Name);
evinfo.Desc = Utils.BytesToString(eventReply.EventData.Desc);
evinfo.Amount = eventReply.EventData.Amount;
evinfo.Category = (EventCategories)Utils.BytesToUInt(eventReply.EventData.Category);
evinfo.Cover = eventReply.EventData.Cover;
evinfo.Creator = (UUID)Utils.BytesToString(eventReply.EventData.Creator);
evinfo.Date = Utils.BytesToString(eventReply.EventData.Date);
evinfo.DateUTC = eventReply.EventData.DateUTC;
evinfo.Duration = eventReply.EventData.Duration;
evinfo.Flags = (EventFlags)eventReply.EventData.EventFlags;
evinfo.SimName = Utils.BytesToString(eventReply.EventData.SimName);
evinfo.GlobalPos = eventReply.EventData.GlobalPos;
try { OnEventInfo(evinfo); }
catch (Exception e) { Logger.Log(e.Message, Helpers.LogLevel.Error, Client, e); }
}
}
#endregion Packet Handlers
}
}