Files
libremetaverse/Programs/Simian/SceneExtensions/ParcelManager.cs
John Hurliman 241b480320 [Simian]
* Created an LLUDP folder to hold extensions that are purely LLUDP packet handlers. This is not a complete abstraction away from transport protocols, but it's a start
* Moved physics code from Movement.cs into PhysicsSimple.cs, and moved the physics loop into a thread in SceneManager
* Simian.ini cleanup


git-svn-id: http://libopenmetaverse.googlecode.com/svn/libopenmetaverse/trunk@2490 52acb1d6-8a22-11de-b505-999d5b087335
2009-03-17 22:33:22 +00:00

174 lines
6.7 KiB
C#

using System;
using System.Collections.Generic;
using ExtensionLoader;
using OpenMetaverse;
using OpenMetaverse.Packets;
namespace Simian
{
public class ParcelManager : IExtension<ISceneProvider>, IParcelProvider
{
ISceneProvider scene;
Dictionary<int, Parcel> parcels = new Dictionary<int, Parcel>();
/// <summary>X,Y ordered 2D array of the parcelIDs for each sq. meter of a simulator</summary>
int[] parcelOverlay = new int[64 * 64];
public ParcelManager()
{
}
public bool Start(ISceneProvider scene)
{
this.scene = scene;
lock (parcels)
parcels.Clear();
// Create a default parcel
Parcel parcel = new Parcel(0);
parcel.Desc = "Simian Parcel";
parcel.Flags = Parcel.ParcelFlags.AllowAPrimitiveEntry | Parcel.ParcelFlags.AllowFly | Parcel.ParcelFlags.AllowGroupScripts |
Parcel.ParcelFlags.AllowLandmark | Parcel.ParcelFlags.AllowOtherScripts | Parcel.ParcelFlags.AllowTerraform |
Parcel.ParcelFlags.AllowVoiceChat | Parcel.ParcelFlags.CreateGroupObjects | Parcel.ParcelFlags.CreateObjects |
Parcel.ParcelFlags.UseBanList;
parcel.Landing = Parcel.LandingType.Direct;
parcel.MaxPrims = 20000;
parcel.Name = "Simian";
parcel.Status = Parcel.ParcelStatus.Leased;
parcel.UserLocation = (parcel.AABBMin + parcel.AABBMax) * 0.5f;
parcel.Bitmap = new byte[512];
for (int i = 0; i < 512; i++)
parcel.Bitmap[i] = Byte.MaxValue;
// The parcelOverlay defaults to all zeroes, and the LocalID of this parcel is zero,
// so we don't need to modify parcelOverlay before calling this
UpdateParcelSize(ref parcel);
// Add the default parcel to the list
parcels[parcel.LocalID] = parcel;
return true;
}
public void Stop()
{
}
public void SendParcelOverlay(Agent agent)
{
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 < 64; y++)
{
for (int x = 0; x < 64; x++)
{
byte tempByte = 0; // The flags for the current 4x4m parcel square
Parcel parcel;
if (parcels.TryGetValue(parcelOverlay[y * 64 + x], out parcel))
{
// Set the ownership/sale flag
if (parcel.OwnerID == agent.ID)
tempByte = (byte)ParcelOverlayType.OwnedBySelf;
else if (parcel.AuctionID != 0)
tempByte = (byte)ParcelOverlayType.Auction;
else if (parcel.SalePrice > 0 && (parcel.AuthBuyerID == UUID.Zero || parcel.AuthBuyerID == agent.ID))
tempByte = (byte)ParcelOverlayType.ForSale;
else if (parcel.GroupID != UUID.Zero)
tempByte = (byte)ParcelOverlayType.OwnedByGroup;
else if (parcel.OwnerID != UUID.Zero)
tempByte = (byte)ParcelOverlayType.OwnedByOther;
else
tempByte = (byte)ParcelOverlayType.Public;
// Set the border flags
if (x == 0)
tempByte |= (byte)ParcelOverlayType.BorderWest;
else if (parcelOverlay[y * 64 + (x - 1)] != parcel.LocalID)
// Parcel to the west is different from the current parcel
tempByte |= (byte)ParcelOverlayType.BorderWest;
if (y == 0)
tempByte |= (byte)ParcelOverlayType.BorderSouth;
else if (parcelOverlay[(y - 1) * 64 + x] != parcel.LocalID)
// Parcel to the south is different from the current parcel
tempByte |= (byte)ParcelOverlayType.BorderSouth;
byteArray[byteArrayCount] = tempByte;
++byteArrayCount;
if (byteArrayCount >= LAND_BLOCKS_PER_PACKET)
{
// Send a ParcelOverlay packet
ParcelOverlayPacket overlay = new ParcelOverlayPacket();
overlay.ParcelData.SequenceID = sequenceID;
overlay.ParcelData.Data = byteArray;
scene.UDP.SendPacket(agent.ID, overlay, PacketCategory.State);
byteArrayCount = 0;
++sequenceID;
}
}
else
{
Logger.Log("Parcel overlay references missing parcel " + parcelOverlay[y * 64 + x],
Helpers.LogLevel.Warning);
}
}
}
}
public void UpdateParcel(Parcel parcel)
{
lock (parcels) parcels[parcel.LocalID] = parcel;
}
public int GetParcelID(int x, int y)
{
return parcelOverlay[y * 64 + x];
}
public bool TryGetParcel(int parcelID, out Parcel parcel)
{
return parcels.TryGetValue(parcelID, out parcel);
}
void UpdateParcelSize(ref Parcel parcel)
{
int minX = 64;
int minY = 64;
int maxX = 0;
int maxY = 0;
int area = 0;
for (int y = 0; y < 64; y++)
{
for (int x = 0; x < 64; x++)
{
if (parcelOverlay[y * 64 + x] == parcel.LocalID)
{
int x4 = x * 4;
int y4 = y * 4;
if (minX > x4) minX = x4;
if (minY > y4) minY = y4;
if (maxX < x4) maxX = x4;
if (maxX < y4) maxY = y4;
area += 16;
}
}
}
parcel.AABBMin.X = minX;
parcel.AABBMin.Y = minY;
parcel.AABBMax.X = maxX;
parcel.AABBMax.Y = maxY;
parcel.Area = area;
}
}
}