237 lines
7.7 KiB
C#
237 lines
7.7 KiB
C#
/*
|
|
* Copyright (c) Contributors, http://opensimulator.org/
|
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
|
*
|
|
* 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.
|
|
* * Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
* * Neither the name of the OpenSimulator Project 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 DEVELOPERS ``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 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 OpenSim.Framework;
|
|
|
|
namespace OpenSim.Region.Framework.Scenes
|
|
{
|
|
/// <summary>
|
|
/// Specifies the fields that have been changed when sending a prim or
|
|
/// avatar update
|
|
/// </summary>
|
|
[Flags]
|
|
public enum ObjectPropertyUpdateFlags : byte
|
|
{
|
|
None = 0,
|
|
Family = 1,
|
|
Object = 2,
|
|
|
|
NoFamily = unchecked((byte)~Family),
|
|
NoObject = unchecked((byte)~Object)
|
|
}
|
|
|
|
public class EntityUpdate
|
|
{
|
|
// for priority queue
|
|
public int PriorityQueue;
|
|
public int PriorityQueueIndex;
|
|
public ulong EntryOrder;
|
|
|
|
private ISceneEntity m_entity;
|
|
private PrimUpdateFlags m_flags;
|
|
public ObjectPropertyUpdateFlags m_propsFlags;
|
|
|
|
public ObjectPropertyUpdateFlags PropsFlags
|
|
{
|
|
get
|
|
{
|
|
return m_propsFlags;
|
|
}
|
|
set
|
|
{
|
|
m_propsFlags = value;
|
|
}
|
|
}
|
|
|
|
public ISceneEntity Entity
|
|
{
|
|
get
|
|
{
|
|
return m_entity;
|
|
}
|
|
internal set
|
|
{
|
|
m_entity = value;
|
|
}
|
|
}
|
|
|
|
public PrimUpdateFlags Flags
|
|
{
|
|
get { return m_flags; }
|
|
set { m_flags = value; }
|
|
}
|
|
|
|
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
|
|
public void Update(int pqueue, ulong entry)
|
|
{
|
|
if ((m_flags & PrimUpdateFlags.CancelKill) != 0)
|
|
{
|
|
if ((m_flags & PrimUpdateFlags.UpdateProbe) != 0)
|
|
m_flags = PrimUpdateFlags.UpdateProbe;
|
|
else
|
|
m_flags = PrimUpdateFlags.FullUpdatewithAnim;
|
|
}
|
|
|
|
PriorityQueue = pqueue;
|
|
EntryOrder = entry;
|
|
}
|
|
|
|
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
|
|
public void UpdateFromNew(EntityUpdate newupdate, int pqueue)
|
|
{
|
|
m_propsFlags |= newupdate.PropsFlags;
|
|
PrimUpdateFlags newFlags = newupdate.Flags;
|
|
|
|
if ((newFlags & PrimUpdateFlags.UpdateProbe) != 0)
|
|
m_flags &= ~PrimUpdateFlags.UpdateProbe;
|
|
|
|
if ((newFlags & PrimUpdateFlags.CancelKill) != 0)
|
|
{
|
|
if ((newFlags & PrimUpdateFlags.UpdateProbe) != 0)
|
|
m_flags = PrimUpdateFlags.UpdateProbe;
|
|
else
|
|
m_flags = PrimUpdateFlags.FullUpdatewithAnim;
|
|
}
|
|
else
|
|
m_flags |= newFlags;
|
|
|
|
PriorityQueue = pqueue;
|
|
}
|
|
|
|
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
|
|
public void Free()
|
|
{
|
|
m_entity = null;
|
|
PriorityQueueIndex = -1;
|
|
EntityUpdatesPool.Free(this);
|
|
}
|
|
|
|
public EntityUpdate(ISceneEntity entity, PrimUpdateFlags flags)
|
|
{
|
|
m_entity = entity;
|
|
m_flags = flags;
|
|
}
|
|
|
|
public EntityUpdate(ISceneEntity entity, PrimUpdateFlags flags, bool sendfam, bool sendobj)
|
|
{
|
|
m_entity = entity;
|
|
m_flags = flags;
|
|
|
|
if (sendfam)
|
|
m_propsFlags |= ObjectPropertyUpdateFlags.Family;
|
|
|
|
if (sendobj)
|
|
m_propsFlags |= ObjectPropertyUpdateFlags.Object;
|
|
}
|
|
|
|
public override string ToString()
|
|
{
|
|
return String.Format("[{0},{1},{2}]", PriorityQueue, EntryOrder, m_entity.LocalId);
|
|
}
|
|
}
|
|
|
|
public static class EntityUpdatesPool
|
|
{
|
|
const int MAXSIZE = 32768;
|
|
const int PREALLOC = 16384;
|
|
private static readonly EntityUpdate[] m_pool = new EntityUpdate[MAXSIZE];
|
|
private static readonly object m_poollock = new object();
|
|
private static int m_poolPtr;
|
|
//private static int m_min = int.MaxValue;
|
|
//private static int m_max = int.MinValue;
|
|
|
|
static EntityUpdatesPool()
|
|
{
|
|
for(int i = 0; i < PREALLOC; ++i)
|
|
m_pool[i] = new EntityUpdate(null, 0);
|
|
m_poolPtr = PREALLOC - 1;
|
|
}
|
|
|
|
public static EntityUpdate Get(ISceneEntity entity, PrimUpdateFlags flags)
|
|
{
|
|
lock (m_poollock)
|
|
{
|
|
if (m_poolPtr >= 0)
|
|
{
|
|
EntityUpdate eu = m_pool[m_poolPtr];
|
|
m_pool[m_poolPtr] = null;
|
|
m_poolPtr--;
|
|
//if (m_min > m_poolPtr)
|
|
// m_min = m_poolPtr;
|
|
eu.Entity = entity;
|
|
eu.Flags = flags;
|
|
return eu;
|
|
}
|
|
}
|
|
return new EntityUpdate(entity, flags);
|
|
}
|
|
|
|
public static EntityUpdate Get(ISceneEntity entity, PrimUpdateFlags flags, bool sendfam, bool sendobj)
|
|
{
|
|
lock (m_poollock)
|
|
{
|
|
if (m_poolPtr >= 0)
|
|
{
|
|
EntityUpdate eu = m_pool[m_poolPtr];
|
|
m_pool[m_poolPtr] = null;
|
|
m_poolPtr--;
|
|
//if (m_min > m_poolPtr)
|
|
// m_min = m_poolPtr;
|
|
eu.Entity = entity;
|
|
eu.Flags = flags;
|
|
ObjectPropertyUpdateFlags tmp = 0;
|
|
if (sendfam)
|
|
tmp |= ObjectPropertyUpdateFlags.Family;
|
|
|
|
if (sendobj)
|
|
tmp |= ObjectPropertyUpdateFlags.Object;
|
|
|
|
eu.PropsFlags = tmp;
|
|
return eu;
|
|
}
|
|
}
|
|
return new EntityUpdate(entity, flags, sendfam, sendobj);
|
|
}
|
|
|
|
public static void Free(EntityUpdate eu)
|
|
{
|
|
lock (m_poollock)
|
|
{
|
|
if (m_poolPtr < MAXSIZE - 1)
|
|
{
|
|
m_poolPtr++;
|
|
//if (m_max < m_poolPtr)
|
|
// m_max = m_poolPtr;
|
|
m_pool[m_poolPtr] = eu;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|