parallel delta queue processing
thread safe packet construction, compilation, compression, gump compilation, sending, coalescing, and many other fixes TODO: delta queue recursion fixups, ipooledenumerable fixups/generics
This commit is contained in:
parent
9404651774
commit
ddcc4e7a20
16 changed files with 619 additions and 575 deletions
|
|
@ -1315,7 +1315,8 @@ namespace Server.Items
|
|||
|
||||
int inPack = 1;
|
||||
|
||||
foreach ( Mobile m in defender.GetMobilesInRange( 1 ) )
|
||||
IPooledEnumerable eable = defender.GetMobilesInRange( 1 );
|
||||
foreach ( Mobile m in eable )
|
||||
{
|
||||
if ( m != attacker && m is BaseCreature )
|
||||
{
|
||||
|
|
@ -1333,6 +1334,7 @@ namespace Server.Items
|
|||
++inPack;
|
||||
}
|
||||
}
|
||||
eable.Free();
|
||||
|
||||
if ( inPack >= 5 )
|
||||
return 100;
|
||||
|
|
@ -1365,7 +1367,8 @@ namespace Server.Items
|
|||
{
|
||||
Clone bc;
|
||||
|
||||
foreach ( Mobile m in defender.GetMobilesInRange( 4 ) )
|
||||
IPooledEnumerable eable = defender.GetMobilesInRange( 4 );
|
||||
foreach ( Mobile m in eable)
|
||||
{
|
||||
bc = m as Clone;
|
||||
|
||||
|
|
@ -1384,6 +1387,7 @@ namespace Server.Items
|
|||
break;
|
||||
}
|
||||
}
|
||||
eable.Free();
|
||||
}
|
||||
|
||||
PlaySwingAnimation( attacker );
|
||||
|
|
@ -1912,11 +1916,13 @@ namespace Server.Items
|
|||
|
||||
int range = Core.ML ? 5 : 10;
|
||||
|
||||
foreach ( Mobile m in from.GetMobilesInRange( range ) )
|
||||
IPooledEnumerable eable = from.GetMobilesInRange(range);
|
||||
foreach ( Mobile m in eable )
|
||||
{
|
||||
if ( from != m && defender != m && SpellHelper.ValidIndirectTarget( from, m ) && from.CanBeHarmful( m, false ) && ( !Core.ML || from.InLOS( m ) ) )
|
||||
list.Add( m );
|
||||
}
|
||||
eable.Free();
|
||||
|
||||
if ( list.Count == 0 )
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -365,6 +365,8 @@ namespace Server.Misc
|
|||
}
|
||||
}
|
||||
|
||||
/* Must be thread-safe */
|
||||
|
||||
public static int MobileNotoriety( Mobile source, Mobile target )
|
||||
{
|
||||
if ( Core.AOS && ( target.Blessed || ( target is BaseCreature && ( (BaseCreature)target ).IsInvulnerable ) || target is PlayerVendor || target is TownCrier ) )
|
||||
|
|
|
|||
|
|
@ -2632,7 +2632,8 @@ namespace Server.Mobiles
|
|||
if (srcSkill <= 0)
|
||||
return;
|
||||
|
||||
foreach (Mobile trg in m_Mobile.GetMobilesInRange(m_Mobile.RangePerception))
|
||||
IPooledEnumerable eable = m_Mobile.GetMobilesInRange(m_Mobile.RangePerception);
|
||||
foreach (Mobile trg in eable)
|
||||
{
|
||||
if (trg != m_Mobile && trg.Player && trg.Alive && trg.Hidden && trg.AccessLevel == AccessLevel.Player && m_Mobile.InLOS(trg))
|
||||
{
|
||||
|
|
@ -2655,6 +2656,7 @@ namespace Server.Mobiles
|
|||
}
|
||||
}
|
||||
}
|
||||
eable.Free();
|
||||
}
|
||||
|
||||
public virtual void Deactivate()
|
||||
|
|
|
|||
|
|
@ -5429,7 +5429,8 @@ namespace Server.Mobiles
|
|||
{
|
||||
Corpse toRummage = null;
|
||||
|
||||
foreach ( Item item in this.GetItemsInRange( 2 ) )
|
||||
IPooledEnumerable eable = this.GetItemsInRange(2);
|
||||
foreach ( Item item in eable )
|
||||
{
|
||||
if ( item is Corpse && item.Items.Count > 0 )
|
||||
{
|
||||
|
|
@ -5437,6 +5438,7 @@ namespace Server.Mobiles
|
|||
break;
|
||||
}
|
||||
}
|
||||
eable.Free();
|
||||
|
||||
if ( toRummage == null )
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -1210,27 +1210,17 @@ namespace Server.Mobiles
|
|||
m_IsStealthing = false; // IsStealthing should be moved to Server.Mobiles
|
||||
}
|
||||
|
||||
[CommandProperty( AccessLevel.GameMaster )]
|
||||
public override bool Hidden
|
||||
public override void OnHiddenChanged()
|
||||
{
|
||||
get
|
||||
RemoveBuff(BuffIcon.Invisibility); //Always remove, default to the hiding icon EXCEPT in the invis spell where it's explicitly set
|
||||
|
||||
if (!Hidden)
|
||||
{
|
||||
return base.Hidden;
|
||||
RemoveBuff(BuffIcon.HidingAndOrStealth);
|
||||
}
|
||||
set
|
||||
else// if( !InvisibilitySpell.HasTimer( this ) )
|
||||
{
|
||||
base.Hidden = value;
|
||||
|
||||
RemoveBuff( BuffIcon.Invisibility ); //Always remove, default to the hiding icon EXCEPT in the invis spell where it's explicitly set
|
||||
|
||||
if( !Hidden )
|
||||
{
|
||||
RemoveBuff( BuffIcon.HidingAndOrStealth );
|
||||
}
|
||||
else// if( !InvisibilitySpell.HasTimer( this ) )
|
||||
{
|
||||
BuffInfo.AddBuff( this, new BuffInfo( BuffIcon.HidingAndOrStealth, 1075655 ) ); //Hidden/Stealthing & You Are Hidden
|
||||
}
|
||||
BuffInfo.AddBuff(this, new BuffInfo(BuffIcon.HidingAndOrStealth, 1075655)); //Hidden/Stealthing & You Are Hidden
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -176,7 +176,8 @@ namespace Server.Regions
|
|||
{
|
||||
BaseGuard useGuard = null;
|
||||
|
||||
foreach ( Mobile m in focus.GetMobilesInRange( 8 ) )
|
||||
IPooledEnumerable eable = focus.GetMobilesInRange( 8 );
|
||||
foreach ( Mobile m in eable)
|
||||
{
|
||||
if ( m is BaseGuard )
|
||||
{
|
||||
|
|
@ -190,6 +191,8 @@ namespace Server.Regions
|
|||
}
|
||||
}
|
||||
|
||||
eable.Free();
|
||||
|
||||
if ( useGuard == null )
|
||||
{
|
||||
m_GuardParams[0] = focus;
|
||||
|
|
|
|||
|
|
@ -20,7 +20,9 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.IO;
|
||||
|
||||
namespace Server.Diagnostics {
|
||||
|
|
@ -65,11 +67,8 @@ namespace Server.Diagnostics {
|
|||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.Synchronized)]
|
||||
public static PacketSendProfile Acquire( Type type ) {
|
||||
if ( !Core.Profiling ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
PacketSendProfile prof;
|
||||
|
||||
if ( !_profiles.TryGetValue( type, out prof ) ) {
|
||||
|
|
@ -81,13 +80,8 @@ namespace Server.Diagnostics {
|
|||
|
||||
private long _created;
|
||||
|
||||
public long Created {
|
||||
get {
|
||||
return _created;
|
||||
}
|
||||
set {
|
||||
_created = value;
|
||||
}
|
||||
public void Increment() {
|
||||
Interlocked.Increment(ref _created);
|
||||
}
|
||||
|
||||
public PacketSendProfile( Type type )
|
||||
|
|
@ -97,7 +91,7 @@ namespace Server.Diagnostics {
|
|||
public override void WriteTo( TextWriter op ) {
|
||||
base.WriteTo( op );
|
||||
|
||||
op.Write( "\t{0,12:N0}", Created );
|
||||
op.Write( "\t{0,12:N0}", _created );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -110,11 +104,8 @@ namespace Server.Diagnostics {
|
|||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.Synchronized)]
|
||||
public static PacketReceiveProfile Acquire( int packetId ) {
|
||||
if ( !Core.Profiling ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
PacketReceiveProfile prof;
|
||||
|
||||
if ( !_profiles.TryGetValue( packetId, out prof ) ) {
|
||||
|
|
|
|||
162
Server/Item.cs
162
Server/Item.cs
|
|
@ -22,6 +22,10 @@ using System;
|
|||
using System.IO;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
#if Framework_4_0
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
#endif
|
||||
using Server.Network;
|
||||
using Server.Items;
|
||||
using Server.ContextMenus;
|
||||
|
|
@ -1635,14 +1639,17 @@ namespace Server
|
|||
}
|
||||
}
|
||||
|
||||
private object _opll = new object();
|
||||
|
||||
public Packet OPLPacket
|
||||
{
|
||||
get
|
||||
{
|
||||
if ( m_OPLPacket == null )
|
||||
{
|
||||
m_OPLPacket = new OPLInfo( PropertyList );
|
||||
m_OPLPacket.SetStatic();
|
||||
lock (_opll) {
|
||||
if ( m_OPLPacket == null ) {
|
||||
m_OPLPacket = new OPLInfo( PropertyList );
|
||||
m_OPLPacket.SetStatic();
|
||||
}
|
||||
}
|
||||
|
||||
return m_OPLPacket;
|
||||
|
|
@ -1713,6 +1720,10 @@ namespace Server
|
|||
}
|
||||
}
|
||||
|
||||
private object _wpl = new object();
|
||||
private object _wplsa = new object();
|
||||
private object _wplhs = new object();
|
||||
|
||||
public Packet WorldPacket
|
||||
{
|
||||
get
|
||||
|
|
@ -1725,10 +1736,11 @@ namespace Server
|
|||
// - Packet Flags
|
||||
// - Direction
|
||||
|
||||
if ( m_WorldPacket == null )
|
||||
{
|
||||
m_WorldPacket = new WorldItem( this );
|
||||
m_WorldPacket.SetStatic();
|
||||
lock (_wpl) {
|
||||
if ( m_WorldPacket == null ) {
|
||||
m_WorldPacket = new WorldItem( this );
|
||||
m_WorldPacket.SetStatic();
|
||||
}
|
||||
}
|
||||
|
||||
return m_WorldPacket;
|
||||
|
|
@ -1747,10 +1759,11 @@ namespace Server
|
|||
// - Packet Flags
|
||||
// - Direction
|
||||
|
||||
if ( m_WorldPacketSA == null )
|
||||
{
|
||||
m_WorldPacketSA = new WorldItemSA( this );
|
||||
m_WorldPacketSA.SetStatic();
|
||||
lock (_wplsa) {
|
||||
if ( m_WorldPacketSA == null ) {
|
||||
m_WorldPacketSA = new WorldItemSA( this );
|
||||
m_WorldPacketSA.SetStatic();
|
||||
}
|
||||
}
|
||||
|
||||
return m_WorldPacketSA;
|
||||
|
|
@ -1769,10 +1782,11 @@ namespace Server
|
|||
// - Packet Flags
|
||||
// - Direction
|
||||
|
||||
if ( m_WorldPacketHS == null )
|
||||
{
|
||||
m_WorldPacketHS = new WorldItemHS( this );
|
||||
m_WorldPacketHS.SetStatic();
|
||||
lock (_wplhs) {
|
||||
if ( m_WorldPacketHS == null ) {
|
||||
m_WorldPacketHS = new WorldItemHS( this );
|
||||
m_WorldPacketHS.SetStatic();
|
||||
}
|
||||
}
|
||||
|
||||
return m_WorldPacketHS;
|
||||
|
|
@ -3012,6 +3026,8 @@ namespace Server
|
|||
{
|
||||
SetFlag( ImplFlag.InQueue, true );
|
||||
|
||||
if (_processing)
|
||||
Console.WriteLine(new System.Diagnostics.StackTrace());
|
||||
m_DeltaQueue.Add( this );
|
||||
}
|
||||
|
||||
|
|
@ -3026,6 +3042,8 @@ namespace Server
|
|||
{
|
||||
SetFlag( ImplFlag.InQueue, false );
|
||||
|
||||
if (_processing)
|
||||
Console.WriteLine(new System.Diagnostics.StackTrace());
|
||||
m_DeltaQueue.Remove( this );
|
||||
}
|
||||
}
|
||||
|
|
@ -3124,41 +3142,44 @@ namespace Server
|
|||
|
||||
if ( openers != null )
|
||||
{
|
||||
for ( int i = 0; i < openers.Count; ++i )
|
||||
lock (openers)
|
||||
{
|
||||
Mobile mob = openers[i];
|
||||
|
||||
int range = GetUpdateRange( mob );
|
||||
|
||||
if ( mob.Map != map || !mob.InRange( worldLoc, range ) )
|
||||
for (int i = 0; i < openers.Count; ++i)
|
||||
{
|
||||
openers.RemoveAt( i-- );
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( mob == rootParent || mob == tradeRecip )
|
||||
continue;
|
||||
Mobile mob = openers[i];
|
||||
|
||||
NetState ns = mob.NetState;
|
||||
int range = GetUpdateRange(mob);
|
||||
|
||||
if ( ns != null )
|
||||
if (mob.Map != map || !mob.InRange(worldLoc, range))
|
||||
{
|
||||
if ( mob.CanSee( this ) )
|
||||
{
|
||||
if ( ns.ContainerGridLines )
|
||||
ns.Send( new ContainerContentUpdate6017( this ) );
|
||||
else
|
||||
ns.Send( new ContainerContentUpdate( this ) );
|
||||
openers.RemoveAt(i--);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mob == rootParent || mob == tradeRecip)
|
||||
continue;
|
||||
|
||||
if ( ObjectPropertyList.Enabled )
|
||||
ns.Send( OPLPacket );
|
||||
NetState ns = mob.NetState;
|
||||
|
||||
if (ns != null)
|
||||
{
|
||||
if (mob.CanSee(this))
|
||||
{
|
||||
if (ns.ContainerGridLines)
|
||||
ns.Send(new ContainerContentUpdate6017(this));
|
||||
else
|
||||
ns.Send(new ContainerContentUpdate(this));
|
||||
|
||||
if (ObjectPropertyList.Enabled)
|
||||
ns.Send(OPLPacket);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( openers.Count == 0 )
|
||||
contParent.Openers = null;
|
||||
if (openers.Count == 0)
|
||||
contParent.Openers = null;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
|
@ -3168,10 +3189,15 @@ namespace Server
|
|||
{
|
||||
Packet p = null;
|
||||
Point3D worldLoc = GetWorldLocation();
|
||||
object equipUpdateLock = new object();
|
||||
|
||||
IPooledEnumerable eable = map.GetClientsInRange( worldLoc, GetMaxUpdateRange() );
|
||||
|
||||
#if Framework_4_0
|
||||
Parallel.ForEach( eable.Cast<NetState>(), state => {
|
||||
#else
|
||||
foreach ( NetState state in eable ) {
|
||||
#endif
|
||||
Mobile m = state.Mobile;
|
||||
|
||||
if ( m.CanSee( this ) && m.InRange( worldLoc, GetUpdateRange( m ) ) ) {
|
||||
|
|
@ -3185,8 +3211,11 @@ namespace Server
|
|||
else
|
||||
state.Send( new ContainerContentUpdate( this ) );
|
||||
} else if ( m_Parent is Mobile ) {
|
||||
p = new EquipUpdate( this );
|
||||
p.Acquire();
|
||||
lock (equipUpdateLock) {
|
||||
p = new EquipUpdate(this);
|
||||
p.Acquire();
|
||||
}
|
||||
|
||||
state.Send( p );
|
||||
}
|
||||
} else {
|
||||
|
|
@ -3199,6 +3228,9 @@ namespace Server
|
|||
}
|
||||
}
|
||||
}
|
||||
#if Framework_4_0
|
||||
);
|
||||
#endif
|
||||
|
||||
if ( p != null )
|
||||
Packet.Release( p );
|
||||
|
|
@ -3212,11 +3244,15 @@ namespace Server
|
|||
{
|
||||
Packet p = null;
|
||||
Point3D worldLoc = GetWorldLocation();
|
||||
object equipPacketLock = new object();
|
||||
|
||||
IPooledEnumerable eable = map.GetClientsInRange( worldLoc, GetMaxUpdateRange() );
|
||||
|
||||
foreach ( NetState state in eable )
|
||||
{
|
||||
#if Framework_4_0
|
||||
Parallel.ForEach( eable.Cast<NetState>(), state => {
|
||||
#else
|
||||
foreach ( NetState state in eable ) {
|
||||
#endif
|
||||
Mobile m = state.Mobile;
|
||||
|
||||
if ( m.CanSee( this ) && m.InRange( worldLoc, GetUpdateRange( m ) ) )
|
||||
|
|
@ -3224,8 +3260,9 @@ namespace Server
|
|||
//if ( sendOPLUpdate )
|
||||
// state.Send( RemovePacket );
|
||||
|
||||
if ( p == null )
|
||||
p = Packet.Acquire( new EquipUpdate( this ) );
|
||||
lock (equipPacketLock)
|
||||
if ( p == null )
|
||||
p = Packet.Acquire( new EquipUpdate( this ) );
|
||||
|
||||
state.Send( p );
|
||||
|
||||
|
|
@ -3233,6 +3270,9 @@ namespace Server
|
|||
state.Send( OPLPacket );
|
||||
}
|
||||
}
|
||||
#if Framework_4_0
|
||||
);
|
||||
#endif
|
||||
|
||||
Packet.Release( p );
|
||||
|
||||
|
|
@ -3246,33 +3286,45 @@ namespace Server
|
|||
Point3D worldLoc = GetWorldLocation();
|
||||
IPooledEnumerable eable = map.GetClientsInRange( worldLoc, GetMaxUpdateRange() );
|
||||
|
||||
foreach ( NetState state in eable )
|
||||
{
|
||||
#if Framework_4_0
|
||||
Parallel.ForEach( eable.Cast<NetState>(), state => {
|
||||
#else
|
||||
foreach ( NetState state in eable ) {
|
||||
#endif
|
||||
Mobile m = state.Mobile;
|
||||
|
||||
if ( m.CanSee( this ) && m.InRange( worldLoc, GetUpdateRange( m ) ) )
|
||||
state.Send( OPLPacket );
|
||||
}
|
||||
#if Framework_4_0
|
||||
);
|
||||
#endif
|
||||
|
||||
eable.Free();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static bool _processing = false;
|
||||
|
||||
public static void ProcessDeltaQueue()
|
||||
{
|
||||
#if Framework_4_0
|
||||
_processing = true;
|
||||
Parallel.ForEach( m_DeltaQueue, i => i.ProcessDelta() );
|
||||
m_DeltaQueue.Clear();
|
||||
_processing = false;
|
||||
#else
|
||||
int count = m_DeltaQueue.Count;
|
||||
|
||||
for ( int i = 0; i < m_DeltaQueue.Count; ++i )
|
||||
{
|
||||
for (int i = 0; i < m_DeltaQueue.Count; ++i) {
|
||||
m_DeltaQueue[i].ProcessDelta();
|
||||
|
||||
if ( i >= count )
|
||||
if (i >= count)
|
||||
break;
|
||||
}
|
||||
|
||||
if ( m_DeltaQueue.Count > 0 )
|
||||
m_DeltaQueue.Clear();
|
||||
m_DeltaQueue.Clear();
|
||||
#endif
|
||||
}
|
||||
|
||||
public virtual void OnDelete()
|
||||
|
|
|
|||
214
Server/Map.cs
214
Server/Map.cs
|
|
@ -1098,30 +1098,9 @@ namespace Server
|
|||
{
|
||||
private IPooledEnumerator m_Enumerator;
|
||||
|
||||
private static Queue<PooledEnumerable> m_InstancePool = new Queue<PooledEnumerable>();
|
||||
private static int m_Depth = 0;
|
||||
|
||||
public static PooledEnumerable Instantiate( IPooledEnumerator etor )
|
||||
{
|
||||
++m_Depth;
|
||||
|
||||
if ( m_Depth >= 5 )
|
||||
Console.WriteLine( "Warning: Make sure to call .Free() on pooled enumerables." );
|
||||
|
||||
PooledEnumerable e;
|
||||
|
||||
if ( m_InstancePool.Count > 0 )
|
||||
{
|
||||
e = m_InstancePool.Dequeue();
|
||||
e.m_Enumerator = etor;
|
||||
}
|
||||
else
|
||||
{
|
||||
e = new PooledEnumerable( etor );
|
||||
}
|
||||
|
||||
etor.Enumerable = e;
|
||||
|
||||
PooledEnumerable e = new PooledEnumerable( etor );
|
||||
return e;
|
||||
}
|
||||
|
||||
|
|
@ -1133,7 +1112,7 @@ namespace Server
|
|||
public IEnumerator GetEnumerator()
|
||||
{
|
||||
if ( m_Enumerator == null )
|
||||
throw new ObjectDisposedException( "PooledEnumerable", "GetEnumerator() called after Free()" );
|
||||
throw new ObjectDisposedException("PooledEnumerable", "GetEnumerator() called after Free()");
|
||||
|
||||
return m_Enumerator;
|
||||
}
|
||||
|
|
@ -1142,12 +1121,8 @@ namespace Server
|
|||
{
|
||||
if ( m_Enumerator != null )
|
||||
{
|
||||
m_InstancePool.Enqueue( this );
|
||||
|
||||
m_Enumerator.Free();
|
||||
m_Enumerator = null;
|
||||
|
||||
--m_Depth;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1182,27 +1157,10 @@ namespace Server
|
|||
private SectorEnumeratorType m_Type;
|
||||
private object m_Current;
|
||||
|
||||
private static Queue<TypedEnumerator> m_InstancePool = new Queue<TypedEnumerator>();
|
||||
|
||||
public static TypedEnumerator Instantiate( Map map, Rectangle2D bounds, SectorEnumeratorType type )
|
||||
{
|
||||
TypedEnumerator e;
|
||||
|
||||
if ( m_InstancePool.Count > 0 )
|
||||
{
|
||||
e = m_InstancePool.Dequeue();
|
||||
|
||||
e.m_Map = map;
|
||||
e.m_Bounds = bounds;
|
||||
e.m_Type = type;
|
||||
|
||||
e.Reset();
|
||||
}
|
||||
else
|
||||
{
|
||||
e = new TypedEnumerator( map, bounds, type );
|
||||
}
|
||||
public static TypedEnumerator Instantiate( Map map, Rectangle2D bounds, SectorEnumeratorType type ) {
|
||||
TypedEnumerator e = new TypedEnumerator(map, bounds, type);
|
||||
|
||||
e.Reset();
|
||||
return e;
|
||||
}
|
||||
|
||||
|
|
@ -1211,18 +1169,13 @@ namespace Server
|
|||
if ( m_Map == null )
|
||||
return;
|
||||
|
||||
m_InstancePool.Enqueue( this );
|
||||
|
||||
m_Map = null;
|
||||
|
||||
if ( m_Enumerator != null )
|
||||
{
|
||||
m_Enumerator.Free();
|
||||
m_Enumerator = null;
|
||||
}
|
||||
|
||||
if ( m_Enumerable != null )
|
||||
m_Enumerable.Free();
|
||||
m_Map = null;
|
||||
}
|
||||
|
||||
public TypedEnumerator( Map map, Rectangle2D bounds, SectorEnumeratorType type )
|
||||
|
|
@ -1230,22 +1183,22 @@ namespace Server
|
|||
m_Map = map;
|
||||
m_Bounds = bounds;
|
||||
m_Type = type;
|
||||
|
||||
Reset();
|
||||
}
|
||||
|
||||
public object Current
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_Current;
|
||||
}
|
||||
public object Current {
|
||||
get { return m_Current; }
|
||||
}
|
||||
|
||||
public bool MoveNext()
|
||||
{
|
||||
while ( true )
|
||||
{
|
||||
if (m_Enumerator == null)
|
||||
{
|
||||
Console.WriteLine("hmm m_Enumerator null??");
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( m_Enumerator.MoveNext() )
|
||||
{
|
||||
object o;
|
||||
|
|
@ -1256,6 +1209,7 @@ namespace Server
|
|||
}
|
||||
catch
|
||||
{
|
||||
Console.WriteLine("typed Enum current null");
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -1293,10 +1247,6 @@ namespace Server
|
|||
else
|
||||
{
|
||||
m_Current = null;
|
||||
|
||||
m_Enumerator.Free();
|
||||
m_Enumerator = null;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -1305,11 +1255,7 @@ namespace Server
|
|||
public void Reset()
|
||||
{
|
||||
m_Current = null;
|
||||
|
||||
if ( m_Enumerator != null )
|
||||
m_Enumerator.Free();
|
||||
|
||||
m_Enumerator = SectorEnumerator.Instantiate( m_Map, m_Bounds, m_Type );//new SectorEnumerator( m_Map, m_Origin, m_Type, m_Range );
|
||||
m_Enumerator = SectorEnumerator.Instantiate( m_Map, m_Bounds, m_Type );
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
|
|
@ -1333,26 +1279,11 @@ namespace Server
|
|||
private object m_Current;
|
||||
private int m_Index;
|
||||
|
||||
private static Queue<MultiTileEnumerator> m_InstancePool = new Queue<MultiTileEnumerator>();
|
||||
|
||||
public static MultiTileEnumerator Instantiate( Sector sector, Point2D loc )
|
||||
{
|
||||
MultiTileEnumerator e;
|
||||
|
||||
if ( m_InstancePool.Count > 0 )
|
||||
{
|
||||
e = m_InstancePool.Dequeue();
|
||||
|
||||
e.m_List = sector.Multis;
|
||||
e.m_Location = loc;
|
||||
|
||||
e.Reset();
|
||||
}
|
||||
else
|
||||
{
|
||||
e = new MultiTileEnumerator( sector, loc );
|
||||
}
|
||||
MultiTileEnumerator e = new MultiTileEnumerator( sector, loc );
|
||||
|
||||
e.Reset();
|
||||
return e;
|
||||
}
|
||||
|
||||
|
|
@ -1360,14 +1291,10 @@ namespace Server
|
|||
{
|
||||
m_List = sector.Multis;
|
||||
m_Location = loc;
|
||||
|
||||
Reset();
|
||||
}
|
||||
|
||||
public object Current
|
||||
{
|
||||
get
|
||||
{
|
||||
public object Current {
|
||||
get {
|
||||
return m_Current;
|
||||
}
|
||||
}
|
||||
|
|
@ -1415,12 +1342,7 @@ namespace Server
|
|||
if ( m_List == null )
|
||||
return;
|
||||
|
||||
m_InstancePool.Enqueue( this );
|
||||
|
||||
m_List = null;
|
||||
|
||||
if ( m_Enumerable != null )
|
||||
m_Enumerable.Free();
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
|
|
@ -1451,26 +1373,11 @@ namespace Server
|
|||
private int m_Stage; // 0 = items, 1 = mobiles
|
||||
private object m_Current;
|
||||
|
||||
private static Queue<ObjectEnumerator> m_InstancePool = new Queue<ObjectEnumerator>();
|
||||
|
||||
public static ObjectEnumerator Instantiate( Map map, Rectangle2D bounds )
|
||||
{
|
||||
ObjectEnumerator e;
|
||||
|
||||
if ( m_InstancePool.Count > 0 )
|
||||
{
|
||||
e = m_InstancePool.Dequeue();
|
||||
|
||||
e.m_Map = map;
|
||||
e.m_Bounds = bounds;
|
||||
|
||||
e.Reset();
|
||||
}
|
||||
else
|
||||
{
|
||||
e = new ObjectEnumerator( map, bounds );
|
||||
}
|
||||
ObjectEnumerator e = new ObjectEnumerator(map, bounds);
|
||||
|
||||
e.Reset();
|
||||
return e;
|
||||
}
|
||||
|
||||
|
|
@ -1479,8 +1386,6 @@ namespace Server
|
|||
if ( m_Map == null )
|
||||
return;
|
||||
|
||||
m_InstancePool.Enqueue( this );
|
||||
|
||||
m_Map = null;
|
||||
|
||||
if ( m_Enumerator != null )
|
||||
|
|
@ -1488,26 +1393,15 @@ namespace Server
|
|||
m_Enumerator.Free();
|
||||
m_Enumerator = null;
|
||||
}
|
||||
|
||||
if ( m_Enumerable != null )
|
||||
m_Enumerable.Free();
|
||||
}
|
||||
|
||||
private ObjectEnumerator( Map map, Rectangle2D bounds )
|
||||
{
|
||||
m_Map = map;
|
||||
m_Bounds = bounds;
|
||||
|
||||
Reset();
|
||||
}
|
||||
|
||||
public object Current
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_Current;
|
||||
}
|
||||
}
|
||||
public object Current { get { return m_Current; } }
|
||||
|
||||
public bool MoveNext()
|
||||
{
|
||||
|
|
@ -1523,6 +1417,7 @@ namespace Server
|
|||
}
|
||||
catch
|
||||
{
|
||||
Console.WriteLine("OBJ Enum current null");
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -1608,25 +1503,10 @@ namespace Server
|
|||
|
||||
private static Queue<SectorEnumerator> m_InstancePool = new Queue<SectorEnumerator>();
|
||||
|
||||
public static SectorEnumerator Instantiate( Map map, Rectangle2D bounds, SectorEnumeratorType type )
|
||||
{
|
||||
SectorEnumerator e;
|
||||
|
||||
if ( m_InstancePool.Count > 0 )
|
||||
{
|
||||
e = m_InstancePool.Dequeue();
|
||||
|
||||
e.m_Map = map;
|
||||
e.m_Bounds = bounds;
|
||||
e.m_Type = type;
|
||||
|
||||
e.Reset();
|
||||
}
|
||||
else
|
||||
{
|
||||
e = new SectorEnumerator( map, bounds, type );
|
||||
}
|
||||
public static SectorEnumerator Instantiate( Map map, Rectangle2D bounds, SectorEnumeratorType type ) {
|
||||
SectorEnumerator e = new SectorEnumerator(map, bounds, type);
|
||||
|
||||
e.Reset();
|
||||
return e;
|
||||
}
|
||||
|
||||
|
|
@ -1635,12 +1515,7 @@ namespace Server
|
|||
if ( m_Map == null )
|
||||
return;
|
||||
|
||||
m_InstancePool.Enqueue( this );
|
||||
|
||||
m_Map = null;
|
||||
|
||||
if ( m_Enumerable != null )
|
||||
m_Enumerable.Free();
|
||||
//m_Map = null;
|
||||
}
|
||||
|
||||
private SectorEnumerator( Map map, Rectangle2D bounds, SectorEnumeratorType type )
|
||||
|
|
@ -1648,8 +1523,6 @@ namespace Server
|
|||
m_Map = map;
|
||||
m_Bounds = bounds;
|
||||
m_Type = type;
|
||||
|
||||
Reset();
|
||||
}
|
||||
|
||||
private IList GetListForSector( Sector sector )
|
||||
|
|
@ -1667,32 +1540,8 @@ namespace Server
|
|||
}
|
||||
}
|
||||
|
||||
public object Current
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_CurrentList[m_CurrentIndex];
|
||||
/*try
|
||||
{
|
||||
return m_CurrentList[m_CurrentIndex];
|
||||
}
|
||||
catch
|
||||
{
|
||||
Console.WriteLine( "Warning: Object removed during enumeration. May not be recoverable" );
|
||||
|
||||
m_CurrentIndex = -1;
|
||||
m_CurrentList = GetListForSector( m_Map.InternalGetSector( m_xSector, m_ySector ) );
|
||||
|
||||
if ( MoveNext() )
|
||||
{
|
||||
return Current;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception( "Object disposed during enumeration. Was not recoverable." );
|
||||
}
|
||||
}*/
|
||||
}
|
||||
public object Current {
|
||||
get { return m_CurrentList[m_CurrentIndex]; }
|
||||
}
|
||||
|
||||
public bool MoveNext()
|
||||
|
|
@ -1701,6 +1550,9 @@ namespace Server
|
|||
{
|
||||
++m_CurrentIndex;
|
||||
|
||||
if (m_CurrentList == null)
|
||||
return false; // So much fail with PooledEnumerables ><
|
||||
|
||||
if ( m_CurrentIndex == m_CurrentList.Count )
|
||||
{
|
||||
++m_ySector;
|
||||
|
|
|
|||
234
Server/Mobile.cs
234
Server/Mobile.cs
|
|
@ -23,6 +23,10 @@ using System.Collections;
|
|||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
#if Framework_4_0
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
#endif
|
||||
using Server;
|
||||
using Server.Accounting;
|
||||
using Server.Commands;
|
||||
|
|
@ -4913,7 +4917,7 @@ namespace Server
|
|||
}
|
||||
}
|
||||
|
||||
//eable.Free();
|
||||
eable.Free();
|
||||
|
||||
object mutateContext = null;
|
||||
string mutatedText = text;
|
||||
|
|
@ -7988,7 +7992,7 @@ namespace Server
|
|||
}
|
||||
|
||||
[CommandProperty( AccessLevel.GameMaster )]
|
||||
public virtual bool Hidden
|
||||
public bool Hidden
|
||||
{
|
||||
get
|
||||
{
|
||||
|
|
@ -7998,49 +8002,54 @@ namespace Server
|
|||
{
|
||||
if( m_Hidden != value )
|
||||
{
|
||||
m_AllowedStealthSteps = 0;
|
||||
|
||||
m_Hidden = value;
|
||||
//Delta( MobileDelta.Flags );
|
||||
|
||||
if( m_Map != null )
|
||||
OnHiddenChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void OnHiddenChanged()
|
||||
{
|
||||
m_AllowedStealthSteps = 0;
|
||||
|
||||
if (m_Map != null)
|
||||
{
|
||||
Packet p = null;
|
||||
|
||||
IPooledEnumerable eable = m_Map.GetClientsInRange(m_Location);
|
||||
|
||||
foreach (NetState state in eable)
|
||||
{
|
||||
if (!state.Mobile.CanSee(this))
|
||||
{
|
||||
Packet p = null;
|
||||
if (p == null)
|
||||
p = this.RemovePacket;
|
||||
|
||||
IPooledEnumerable eable = m_Map.GetClientsInRange( m_Location );
|
||||
state.Send(p);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (state.StygianAbyss)
|
||||
state.Send(new MobileIncoming(state.Mobile, this));
|
||||
else
|
||||
state.Send(new MobileIncomingOld(state.Mobile, this));
|
||||
|
||||
foreach( NetState state in eable )
|
||||
if (IsDeadBondedPet)
|
||||
state.Send(new BondedStatus(0, m_Serial, 1));
|
||||
|
||||
if (ObjectPropertyList.Enabled)
|
||||
{
|
||||
if( !state.Mobile.CanSee( this ) )
|
||||
{
|
||||
if( p == null )
|
||||
p = this.RemovePacket;
|
||||
state.Send(OPLPacket);
|
||||
|
||||
state.Send( p );
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( state.StygianAbyss )
|
||||
state.Send( new MobileIncoming( state.Mobile, this ) );
|
||||
else
|
||||
state.Send( new MobileIncomingOld( state.Mobile, this ) );
|
||||
|
||||
if( IsDeadBondedPet )
|
||||
state.Send( new BondedStatus( 0, m_Serial, 1 ) );
|
||||
|
||||
if( ObjectPropertyList.Enabled )
|
||||
{
|
||||
state.Send( OPLPacket );
|
||||
|
||||
//foreach ( Item item in m_Items )
|
||||
// state.Send( item.OPLPacket );
|
||||
}
|
||||
}
|
||||
//foreach ( Item item in m_Items )
|
||||
// state.Send( item.OPLPacket );
|
||||
}
|
||||
|
||||
eable.Free();
|
||||
}
|
||||
}
|
||||
|
||||
eable.Free();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -9956,6 +9965,8 @@ namespace Server
|
|||
{
|
||||
m_InDeltaQueue = true;
|
||||
|
||||
if (_processing)
|
||||
Console.WriteLine(new System.Diagnostics.StackTrace());
|
||||
m_DeltaQueue.Enqueue( this );
|
||||
}
|
||||
|
||||
|
|
@ -10121,7 +10132,9 @@ namespace Server
|
|||
sendPublicStats = true;
|
||||
}
|
||||
|
||||
if( (delta & (MobileDelta.WeaponDamage | MobileDelta.Resistances | MobileDelta.Stat | MobileDelta.Weight | MobileDelta.Gold | MobileDelta.Armor | MobileDelta.StatCap | MobileDelta.Followers | MobileDelta.TithingPoints | MobileDelta.Race)) != 0 )
|
||||
if( (delta & (MobileDelta.WeaponDamage | MobileDelta.Resistances | MobileDelta.Stat |
|
||||
MobileDelta.Weight | MobileDelta.Gold | MobileDelta.Armor | MobileDelta.StatCap |
|
||||
MobileDelta.Followers | MobileDelta.TithingPoints | MobileDelta.Race)) != 0 )
|
||||
{
|
||||
sendPrivateStats = true;
|
||||
}
|
||||
|
|
@ -10142,6 +10155,9 @@ namespace Server
|
|||
sendFacialHair = true;
|
||||
}
|
||||
|
||||
#if Framework_4_0
|
||||
Packet[][] cache = new Packet[2][] { new Packet[8], new Packet[8] };
|
||||
#else
|
||||
Packet[][] cache = m_MovingPacketCache;
|
||||
|
||||
if( sendMoving || sendNonlocalMoving || sendHealthbarPoison || sendHealthbarYellow )
|
||||
|
|
@ -10150,6 +10166,7 @@ namespace Server
|
|||
for( int j = 0; j < cache[i].Length; ++j )
|
||||
Packet.Release( ref cache[i][j] );
|
||||
}
|
||||
#endif
|
||||
|
||||
NetState ourState = m.m_NetState;
|
||||
|
||||
|
|
@ -10252,22 +10269,42 @@ namespace Server
|
|||
{
|
||||
Mobile beholder;
|
||||
|
||||
IPooledEnumerable eable = m.Map.GetClientsInRange( m.m_Location );
|
||||
|
||||
Packet hitsPacket = null;
|
||||
Packet statPacketTrue = null, statPacketFalse = null;
|
||||
Packet statPacketTrue = null;
|
||||
Packet statPacketFalse = null;
|
||||
Packet deadPacket = null;
|
||||
Packet hairPacket = null, facialhairPacket = null;
|
||||
Packet hbpPacket = null, hbyPacket = null;
|
||||
Packet hairPacket = null;
|
||||
Packet facialhairPacket = null;
|
||||
Packet hbpPacket = null;
|
||||
Packet hbyPacket = null;
|
||||
|
||||
foreach( NetState state in eable )
|
||||
{
|
||||
// 9 Separate Locks.. Feels Dirty
|
||||
object hitsPacketLock = new object();
|
||||
object statPacketTrueLock = new object();
|
||||
object statPacketFalseLock = new object();
|
||||
object deadPacketLock = new object();
|
||||
object hairPacketLock = new object();
|
||||
object facialhairPacketLock = new object();
|
||||
object hbpPacketLock = new object();
|
||||
object hbyPacketLock = new object();
|
||||
object cacheSync = new object();
|
||||
|
||||
Packet removePacket = RemovePacket;
|
||||
Packet oplPacket = OPLPacket;
|
||||
|
||||
IPooledEnumerable eable = m.Map.GetClientsInRange(m.m_Location);
|
||||
|
||||
#if Framework_4_0
|
||||
Parallel.ForEach( eable.Cast<NetState>(), state => {
|
||||
#else
|
||||
foreach ( NetState state in eable ) {
|
||||
#endif
|
||||
beholder = state.Mobile;
|
||||
|
||||
if( beholder != m && beholder.CanSee( m ) )
|
||||
{
|
||||
if( sendRemove )
|
||||
state.Send( m.RemovePacket );
|
||||
state.Send(removePacket);
|
||||
|
||||
if( sendIncoming )
|
||||
{
|
||||
|
|
@ -10279,8 +10316,11 @@ namespace Server
|
|||
|
||||
if( m.IsDeadBondedPet )
|
||||
{
|
||||
if( deadPacket == null )
|
||||
deadPacket = Packet.Acquire( new BondedStatus( 0, m.m_Serial, 1 ) );
|
||||
lock (deadPacketLock)
|
||||
{
|
||||
if (deadPacket == null)
|
||||
deadPacket = Packet.Acquire(new BondedStatus(0, m.m_Serial, 1));
|
||||
}
|
||||
|
||||
state.Send( deadPacket );
|
||||
}
|
||||
|
|
@ -10291,24 +10331,36 @@ namespace Server
|
|||
{
|
||||
int noto = Notoriety.Compute( beholder, m );
|
||||
|
||||
Packet p = cache[0][noto];
|
||||
Packet p;
|
||||
|
||||
if( p == null )
|
||||
cache[0][noto] = p = Packet.Acquire( new MobileMoving( m, noto ) );
|
||||
lock (cacheSync)
|
||||
{
|
||||
p = cache[0][noto];
|
||||
|
||||
if (p == null)
|
||||
cache[0][noto] = p = Packet.Acquire(new MobileMoving(m, noto));
|
||||
}
|
||||
|
||||
state.Send( p );
|
||||
}
|
||||
|
||||
if ( sendHealthbarPoison ) {
|
||||
if ( hbpPacket == null )
|
||||
hbpPacket = Packet.Acquire( new HealthbarPoison( m ) );
|
||||
|
||||
lock (hbpPacketLock)
|
||||
{
|
||||
if (hbpPacket == null)
|
||||
hbpPacket = Packet.Acquire(new HealthbarPoison(m));
|
||||
}
|
||||
|
||||
state.Send( hbpPacket );
|
||||
}
|
||||
|
||||
if ( sendHealthbarYellow ) {
|
||||
if ( hbyPacket == null )
|
||||
hbyPacket = Packet.Acquire( new HealthbarYellow( m ) );
|
||||
lock (hbyPacketLock)
|
||||
{
|
||||
if (hbyPacket == null)
|
||||
hbyPacket = Packet.Acquire(new HealthbarYellow(m));
|
||||
}
|
||||
|
||||
state.Send( hbyPacket );
|
||||
}
|
||||
} else {
|
||||
|
|
@ -10316,10 +10368,15 @@ namespace Server
|
|||
{
|
||||
int noto = Notoriety.Compute( beholder, m );
|
||||
|
||||
Packet p = cache[1][noto];
|
||||
Packet p;
|
||||
|
||||
if( p == null )
|
||||
cache[1][noto] = p = Packet.Acquire( new MobileMovingOld( m, noto ) );
|
||||
lock (cacheSync)
|
||||
{
|
||||
p = cache[1][noto];
|
||||
|
||||
if (p == null)
|
||||
cache[1][noto] = p = Packet.Acquire(new MobileMovingOld(m, noto));
|
||||
}
|
||||
|
||||
state.Send( p );
|
||||
}
|
||||
|
|
@ -10329,35 +10386,45 @@ namespace Server
|
|||
{
|
||||
if( m.CanBeRenamedBy( beholder ) )
|
||||
{
|
||||
if( statPacketTrue == null )
|
||||
statPacketTrue = Packet.Acquire( new MobileStatusCompact( true, m ) );
|
||||
lock (statPacketTrueLock)
|
||||
{
|
||||
if (statPacketTrue == null)
|
||||
statPacketTrue = Packet.Acquire(new MobileStatusCompact(true, m));
|
||||
}
|
||||
|
||||
state.Send( statPacketTrue );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( statPacketFalse == null )
|
||||
statPacketFalse = Packet.Acquire( new MobileStatusCompact( false, m ) );
|
||||
lock (statPacketFalseLock)
|
||||
{
|
||||
if (statPacketFalse == null)
|
||||
statPacketFalse = Packet.Acquire(new MobileStatusCompact(false, m));
|
||||
}
|
||||
|
||||
state.Send( statPacketFalse );
|
||||
}
|
||||
}
|
||||
else if( sendHits )
|
||||
{
|
||||
if( hitsPacket == null )
|
||||
hitsPacket = Packet.Acquire( new MobileHitsN( m ) );
|
||||
lock (hitsPacketLock)
|
||||
{
|
||||
if (hitsPacket == null)
|
||||
hitsPacket = Packet.Acquire(new MobileHitsN(m));
|
||||
}
|
||||
|
||||
state.Send( hitsPacket );
|
||||
}
|
||||
|
||||
if( sendHair )
|
||||
{
|
||||
if( hairPacket == null )
|
||||
{
|
||||
if( removeHair )
|
||||
hairPacket = Packet.Acquire( new RemoveHair( m ) );
|
||||
else
|
||||
hairPacket = Packet.Acquire( new HairEquipUpdate( m ) );
|
||||
lock (hairPacketLock) {
|
||||
if (hairPacket == null) {
|
||||
if (removeHair)
|
||||
hairPacket = Packet.Acquire(new RemoveHair(m));
|
||||
else
|
||||
hairPacket = Packet.Acquire(new HairEquipUpdate(m));
|
||||
}
|
||||
}
|
||||
|
||||
state.Send( hairPacket );
|
||||
|
|
@ -10365,21 +10432,25 @@ namespace Server
|
|||
|
||||
if( sendFacialHair )
|
||||
{
|
||||
if( facialhairPacket == null )
|
||||
{
|
||||
if( removeFacialHair )
|
||||
facialhairPacket = Packet.Acquire( new RemoveFacialHair( m ) );
|
||||
else
|
||||
facialhairPacket = Packet.Acquire( new FacialHairEquipUpdate( m ) );
|
||||
lock (facialhairPacketLock) {
|
||||
if (facialhairPacket == null) {
|
||||
if (removeFacialHair)
|
||||
facialhairPacket = Packet.Acquire(new RemoveFacialHair(m));
|
||||
else
|
||||
facialhairPacket = Packet.Acquire(new FacialHairEquipUpdate(m));
|
||||
}
|
||||
}
|
||||
|
||||
state.Send( facialhairPacket );
|
||||
}
|
||||
|
||||
if( sendOPLUpdate )
|
||||
state.Send( OPLPacket );
|
||||
state.Send(oplPacket);
|
||||
}
|
||||
}
|
||||
#if Framework_4_0
|
||||
);
|
||||
#endif
|
||||
|
||||
Packet.Release( hitsPacket );
|
||||
Packet.Release( statPacketTrue );
|
||||
|
|
@ -10396,18 +10467,27 @@ namespace Server
|
|||
if( sendMoving || sendNonlocalMoving || sendHealthbarPoison || sendHealthbarYellow )
|
||||
{
|
||||
for( int i = 0; i < cache.Length; ++i )
|
||||
for( int j = 0; j < cache.Length; ++j )
|
||||
Packet.Release( ref cache[i][j] );
|
||||
for( int j = 0; j < cache[i].Length; ++j )
|
||||
Packet.Release(ref cache[i][j]);
|
||||
}
|
||||
}
|
||||
|
||||
public static bool _processing = false;
|
||||
|
||||
public static void ProcessDeltaQueue()
|
||||
{
|
||||
#if Framework_4_0
|
||||
_processing = true;
|
||||
Parallel.ForEach( m_DeltaQueue, m => m.ProcessDelta() );
|
||||
m_DeltaQueue.Clear();
|
||||
_processing = false;
|
||||
#else
|
||||
int count = m_DeltaQueue.Count;
|
||||
int index = 0;
|
||||
|
||||
while( m_DeltaQueue.Count > 0 && index++ < count )
|
||||
m_DeltaQueue.Dequeue().ProcessDelta();
|
||||
#endif
|
||||
}
|
||||
|
||||
[CommandProperty( AccessLevel.Counselor, AccessLevel.GameMaster )]
|
||||
|
|
|
|||
|
|
@ -83,92 +83,104 @@ namespace Server.Network {
|
|||
// If our input exceeds this length, we may potentially overflow the buffer
|
||||
private const int PossibleOverflow = ( ( BufferSize * 8 ) - TerminalCodeLength ) / MaximalCodeLength;
|
||||
|
||||
private static object _syncRoot = new object();
|
||||
|
||||
private static byte[] _outputBuffer = new byte[BufferSize];
|
||||
|
||||
[Obsolete( "Use Compress( byte[], int, int, ref int ) instead.", false )]
|
||||
public static void Compress( byte[] input, int length, out byte[] output, out int outputLength ) {
|
||||
outputLength = 0;
|
||||
output = Compress( input, 0, length, ref outputLength );
|
||||
}
|
||||
|
||||
public unsafe static byte[] Compress( byte[] input, int offset, int count, ref int length ) {
|
||||
if ( input == null ) {
|
||||
throw new ArgumentNullException( "input" );
|
||||
} else if ( offset < 0 || offset >= input.Length ) {
|
||||
throw new ArgumentOutOfRangeException( "offset" );
|
||||
} else if ( count < 0 || count > input.Length ) {
|
||||
throw new ArgumentOutOfRangeException( "count" );
|
||||
} else if ( ( input.Length - offset ) < count ) {
|
||||
public unsafe static void Compress(byte[] input, int offset, int count, byte[] output, ref int length)
|
||||
{
|
||||
if (input == null)
|
||||
{
|
||||
throw new ArgumentNullException("input");
|
||||
}
|
||||
else if (offset < 0 || offset >= input.Length)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException("offset");
|
||||
}
|
||||
else if (count < 0 || count > input.Length)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException("count");
|
||||
}
|
||||
else if ((input.Length - offset) < count)
|
||||
{
|
||||
throw new ArgumentException();
|
||||
}
|
||||
|
||||
length = 0;
|
||||
|
||||
if ( count > DefiniteOverflow ) {
|
||||
return null;
|
||||
if (count > DefiniteOverflow)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
lock ( _syncRoot ) {
|
||||
int bitCount = 0;
|
||||
int bitValue = 0;
|
||||
int bitCount = 0;
|
||||
int bitValue = 0;
|
||||
|
||||
fixed ( int* pTable = _huffmanTable ) {
|
||||
int* pEntry;
|
||||
fixed (int* pTable = _huffmanTable)
|
||||
{
|
||||
int* pEntry;
|
||||
|
||||
fixed ( byte* pInputBuffer = input ) {
|
||||
byte* pInput = pInputBuffer + offset, pInputEnd = pInput + count;
|
||||
fixed (byte* pInputBuffer = input)
|
||||
{
|
||||
byte* pInput = pInputBuffer + offset, pInputEnd = pInput + count;
|
||||
|
||||
fixed ( byte* pOutputBuffer = _outputBuffer ) {
|
||||
byte* pOutput = pOutputBuffer, pOutputEnd = pOutput + BufferSize;
|
||||
fixed (byte* pOutputBuffer = output)
|
||||
{
|
||||
byte* pOutput = pOutputBuffer, pOutputEnd = pOutput + BufferSize;
|
||||
|
||||
while ( pInput < pInputEnd ) {
|
||||
pEntry = &pTable[*pInput++ << 1];
|
||||
|
||||
bitCount += pEntry[CountIndex];
|
||||
|
||||
bitValue <<= pEntry[CountIndex];
|
||||
bitValue |= pEntry[ValueIndex];
|
||||
|
||||
while ( bitCount >= 8 ) {
|
||||
bitCount -= 8;
|
||||
|
||||
if ( pOutput < pOutputEnd ) {
|
||||
*pOutput++ = ( byte ) ( bitValue >> bitCount );
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// terminal code
|
||||
pEntry = &pTable[0x200];
|
||||
while (pInput < pInputEnd)
|
||||
{
|
||||
pEntry = &pTable[*pInput++ << 1];
|
||||
|
||||
bitCount += pEntry[CountIndex];
|
||||
|
||||
bitValue <<= pEntry[CountIndex];
|
||||
bitValue |= pEntry[ValueIndex];
|
||||
|
||||
// align on byte boundary
|
||||
if ( ( bitCount & 7 ) != 0 ) {
|
||||
bitValue <<= ( 8 - ( bitCount & 7 ) );
|
||||
bitCount += ( 8 - ( bitCount & 7 ) );
|
||||
}
|
||||
|
||||
while ( bitCount >= 8 ) {
|
||||
while (bitCount >= 8)
|
||||
{
|
||||
bitCount -= 8;
|
||||
|
||||
if ( pOutput < pOutputEnd ) {
|
||||
*pOutput++ = ( byte ) ( bitValue >> bitCount );
|
||||
} else {
|
||||
return null;
|
||||
if (pOutput < pOutputEnd)
|
||||
{
|
||||
*pOutput++ = (byte)(bitValue >> bitCount);
|
||||
}
|
||||
else
|
||||
{
|
||||
length = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
length = ( int ) ( pOutput - pOutputBuffer );
|
||||
return _outputBuffer;
|
||||
}
|
||||
|
||||
// terminal code
|
||||
pEntry = &pTable[0x200];
|
||||
|
||||
bitCount += pEntry[CountIndex];
|
||||
|
||||
bitValue <<= pEntry[CountIndex];
|
||||
bitValue |= pEntry[ValueIndex];
|
||||
|
||||
// align on byte boundary
|
||||
if ((bitCount & 7) != 0)
|
||||
{
|
||||
bitValue <<= (8 - (bitCount & 7));
|
||||
bitCount += (8 - (bitCount & 7));
|
||||
}
|
||||
|
||||
while (bitCount >= 8)
|
||||
{
|
||||
bitCount -= 8;
|
||||
|
||||
if (pOutput < pOutputEnd)
|
||||
{
|
||||
*pOutput++ = (byte)(bitValue >> bitCount);
|
||||
}
|
||||
else
|
||||
{
|
||||
length = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
length = (int)(pOutput - pOutputBuffer);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -236,7 +236,9 @@ namespace Server.Network
|
|||
return;
|
||||
}
|
||||
|
||||
PacketReceiveProfile prof = PacketReceiveProfile.Acquire( packetID );
|
||||
PacketReceiveProfile prof = null;
|
||||
|
||||
if (Core.Profiling) prof = PacketReceiveProfile.Acquire( packetID );
|
||||
|
||||
if ( prof != null ) {
|
||||
prof.Start();
|
||||
|
|
|
|||
|
|
@ -19,12 +19,14 @@
|
|||
***************************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Threading;
|
||||
#if Framework_4_0
|
||||
using System.Threading.Tasks;
|
||||
#endif
|
||||
using Server;
|
||||
using Server.Accounting;
|
||||
using Server.Network;
|
||||
|
|
@ -588,14 +590,15 @@ namespace Server.Network {
|
|||
}
|
||||
}
|
||||
|
||||
private bool _sending;
|
||||
private object _sendL = new object();
|
||||
|
||||
public virtual void Send( Packet p ) {
|
||||
if ( m_Socket == null || m_BlockAllPackets ) {
|
||||
p.OnSend();
|
||||
return;
|
||||
}
|
||||
|
||||
PacketSendProfile prof = PacketSendProfile.Acquire( p.GetType() );
|
||||
|
||||
int length;
|
||||
byte[] buffer = p.Compile( m_CompressionEnabled, out length );
|
||||
|
||||
|
|
@ -605,6 +608,10 @@ namespace Server.Network {
|
|||
return;
|
||||
}
|
||||
|
||||
PacketSendProfile prof = null;
|
||||
|
||||
if (Core.Profiling) prof = PacketSendProfile.Acquire(p.GetType());
|
||||
|
||||
if ( prof != null ) {
|
||||
prof.Start();
|
||||
}
|
||||
|
|
@ -616,22 +623,27 @@ namespace Server.Network {
|
|||
try {
|
||||
SendQueue.Gram gram;
|
||||
|
||||
lock ( m_SendQueue ) {
|
||||
gram = m_SendQueue.Enqueue( buffer, length );
|
||||
}
|
||||
lock (_sendL) {
|
||||
lock (m_SendQueue)
|
||||
gram = m_SendQueue.Enqueue(buffer, length);
|
||||
|
||||
if ( gram != null ) {
|
||||
if (gram != null) {
|
||||
#if NewAsyncSockets
|
||||
m_SendEventArgs.SetBuffer( gram.Buffer, 0, gram.Length );
|
||||
Send_Start();
|
||||
m_SendEventArgs.SetBuffer( gram.Buffer, 0, gram.Length );
|
||||
Send_Start();
|
||||
#else
|
||||
try {
|
||||
m_Socket.BeginSend( gram.Buffer, 0, gram.Length, SocketFlags.None, m_OnSend, m_Socket );
|
||||
} catch ( Exception ex ) {
|
||||
TraceException( ex );
|
||||
Dispose( false );
|
||||
}
|
||||
try {
|
||||
if (!_sending) {
|
||||
_sending = true;
|
||||
m_Socket.BeginSend(gram.Buffer, 0, gram.Length, SocketFlags.None, m_OnSend, m_Socket);
|
||||
}
|
||||
}
|
||||
catch (Exception ex) {
|
||||
TraceException(ex);
|
||||
Dispose(false);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
} catch ( CapacityExceededException ) {
|
||||
Console.WriteLine( "Client: {0}: Too much data pending, disconnecting...", this );
|
||||
|
|
@ -814,13 +826,15 @@ namespace Server.Network {
|
|||
}
|
||||
|
||||
public bool Flush() {
|
||||
if ( m_Socket == null || !m_SendQueue.IsFlushReady ) {
|
||||
return false;
|
||||
}
|
||||
if ( m_Socket == null )
|
||||
return false;
|
||||
|
||||
SendQueue.Gram gram;
|
||||
|
||||
lock ( m_SendQueue ) {
|
||||
if (!m_SendQueue.IsFlushReady)
|
||||
return false;
|
||||
|
||||
gram = m_SendQueue.CheckFlushReady();
|
||||
}
|
||||
|
||||
|
|
@ -914,23 +928,26 @@ namespace Server.Network {
|
|||
|
||||
m_NextCheckActivity = Core.TickCount + 90000;
|
||||
|
||||
if ( m_CoalesceSleep >= 0 ) {
|
||||
Thread.Sleep( m_CoalesceSleep );
|
||||
if (m_CoalesceSleep >= 0) {
|
||||
Thread.Sleep(m_CoalesceSleep);
|
||||
}
|
||||
|
||||
SendQueue.Gram gram;
|
||||
|
||||
lock ( m_SendQueue ) {
|
||||
lock (m_SendQueue) {
|
||||
gram = m_SendQueue.Dequeue();
|
||||
}
|
||||
|
||||
if ( gram != null ) {
|
||||
if (gram != null) {
|
||||
try {
|
||||
s.BeginSend( gram.Buffer, 0, gram.Length, SocketFlags.None, m_OnSend, s );
|
||||
} catch ( Exception ex ) {
|
||||
TraceException( ex );
|
||||
Dispose( false );
|
||||
s.BeginSend(gram.Buffer, 0, gram.Length, SocketFlags.None, m_OnSend, s);
|
||||
} catch (Exception ex) {
|
||||
TraceException(ex);
|
||||
Dispose(false);
|
||||
}
|
||||
} else {
|
||||
lock (_sendL)
|
||||
_sending = false;
|
||||
}
|
||||
} catch ( Exception ){
|
||||
Dispose( false );
|
||||
|
|
@ -974,23 +991,31 @@ namespace Server.Network {
|
|||
}
|
||||
|
||||
public bool Flush() {
|
||||
if ( m_Socket == null || !m_SendQueue.IsFlushReady ) {
|
||||
if (m_Socket == null)
|
||||
return false;
|
||||
}
|
||||
|
||||
SendQueue.Gram gram;
|
||||
lock (_sendL) {
|
||||
if (_sending)
|
||||
return false;
|
||||
|
||||
lock ( m_SendQueue ) {
|
||||
gram = m_SendQueue.CheckFlushReady();
|
||||
}
|
||||
SendQueue.Gram gram;
|
||||
|
||||
if ( gram != null ) {
|
||||
try {
|
||||
m_Socket.BeginSend( gram.Buffer, 0, gram.Length, SocketFlags.None, m_OnSend, m_Socket );
|
||||
return true;
|
||||
} catch ( Exception ex ) {
|
||||
TraceException( ex );
|
||||
Dispose( false );
|
||||
lock (m_SendQueue) {
|
||||
if (!m_SendQueue.IsFlushReady)
|
||||
return false;
|
||||
|
||||
gram = m_SendQueue.CheckFlushReady();
|
||||
}
|
||||
|
||||
if (gram != null) {
|
||||
try {
|
||||
_sending = true;
|
||||
m_Socket.BeginSend(gram.Buffer, 0, gram.Length, SocketFlags.None, m_OnSend, m_Socket);
|
||||
return true;
|
||||
} catch (Exception ex) {
|
||||
TraceException(ex);
|
||||
Dispose(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1007,11 +1032,13 @@ namespace Server.Network {
|
|||
}
|
||||
|
||||
public static void FlushAll() {
|
||||
#if Framework_4_0
|
||||
Parallel.ForEach( m_Instances, ns => ns.Flush() );
|
||||
#else
|
||||
for ( int i = 0; i < m_Instances.Count; ++i ) {
|
||||
NetState ns = m_Instances[i];
|
||||
|
||||
ns.Flush();
|
||||
m_Instances[i].Flush();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
private static int m_CoalesceSleep = -1;
|
||||
|
|
@ -1109,10 +1136,11 @@ namespace Server.Network {
|
|||
|
||||
m_Running = false;
|
||||
|
||||
m_Disposed.Enqueue( this );
|
||||
lock (m_Disposed)
|
||||
m_Disposed.Enqueue( this );
|
||||
|
||||
if ( /*!flush &&*/ !m_SendQueue.IsEmpty ) {
|
||||
lock ( m_SendQueue )
|
||||
lock (m_SendQueue)
|
||||
if ( /*!flush &&*/ !m_SendQueue.IsEmpty ) {
|
||||
m_SendQueue.Clear();
|
||||
}
|
||||
}
|
||||
|
|
@ -1131,37 +1159,38 @@ namespace Server.Network {
|
|||
}
|
||||
}
|
||||
|
||||
private static Queue m_Disposed = Queue.Synchronized( new Queue() );
|
||||
private static Queue<NetState> m_Disposed = new Queue<NetState>();
|
||||
|
||||
public static void ProcessDisposedQueue() {
|
||||
int breakout = 0;
|
||||
lock (m_Disposed) {
|
||||
int breakout = 0;
|
||||
|
||||
while ( breakout < 200 && m_Disposed.Count > 0 ) {
|
||||
++breakout;
|
||||
while ( breakout < 200 && m_Disposed.Count > 0 ) {
|
||||
++breakout;
|
||||
NetState ns = m_Disposed.Dequeue();
|
||||
|
||||
NetState ns = ( NetState ) m_Disposed.Dequeue();
|
||||
Mobile m = ns.m_Mobile;
|
||||
IAccount a = ns.m_Account;
|
||||
|
||||
Mobile m = ns.m_Mobile;
|
||||
IAccount a = ns.m_Account;
|
||||
if ( m != null ) {
|
||||
m.NetState = null;
|
||||
ns.m_Mobile = null;
|
||||
}
|
||||
|
||||
if ( m != null ) {
|
||||
m.NetState = null;
|
||||
ns.m_Mobile = null;
|
||||
}
|
||||
ns.m_Gumps.Clear();
|
||||
ns.m_Menus.Clear();
|
||||
ns.m_HuePickers.Clear();
|
||||
ns.m_Account = null;
|
||||
ns.m_ServerInfo = null;
|
||||
ns.m_CityInfo = null;
|
||||
|
||||
ns.m_Gumps.Clear();
|
||||
ns.m_Menus.Clear();
|
||||
ns.m_HuePickers.Clear();
|
||||
ns.m_Account = null;
|
||||
ns.m_ServerInfo = null;
|
||||
ns.m_CityInfo = null;
|
||||
m_Instances.Remove( ns );
|
||||
|
||||
m_Instances.Remove( ns );
|
||||
|
||||
if ( a != null ) {
|
||||
ns.WriteConsole( "Disconnected. [{0} Online] [{1}]", m_Instances.Count, a );
|
||||
} else {
|
||||
ns.WriteConsole( "Disconnected. [{0} Online]", m_Instances.Count );
|
||||
if ( a != null ) {
|
||||
ns.WriteConsole( "Disconnected. [{0} Online] [{1}]", m_Instances.Count, a );
|
||||
} else {
|
||||
ns.WriteConsole( "Disconnected. [{0} Online]", m_Instances.Count );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -97,7 +97,7 @@ namespace Server.Network
|
|||
/// <summary>
|
||||
/// Internal format buffer.
|
||||
/// </summary>
|
||||
private static byte[] m_Buffer = new byte[4];
|
||||
private byte[] m_Buffer = new byte[4];
|
||||
|
||||
/// <summary>
|
||||
/// Instantiates a new PacketWriter instance with the default capacity of 4 bytes.
|
||||
|
|
|
|||
|
|
@ -2475,7 +2475,8 @@ namespace Server.Network
|
|||
PacketWriter.ReleaseInstance( m_Strings );
|
||||
}
|
||||
|
||||
private static byte[] m_PackBuffer;
|
||||
private const int GumpBufferSize = 0x4000;
|
||||
private static BufferPool m_PackBuffers = new BufferPool("Gump", 4, GumpBufferSize);
|
||||
|
||||
private void WritePacked( PacketWriter src )
|
||||
{
|
||||
|
|
@ -2493,8 +2494,15 @@ namespace Server.Network
|
|||
wantLength += 4095;
|
||||
wantLength &= ~4095;
|
||||
|
||||
if ( m_PackBuffer == null || m_PackBuffer.Length < wantLength )
|
||||
byte[] m_PackBuffer;
|
||||
lock (m_PackBuffers)
|
||||
m_PackBuffer = m_PackBuffers.AcquireBuffer();
|
||||
|
||||
if (m_PackBuffer.Length < wantLength)
|
||||
{
|
||||
Console.WriteLine("Notice: DisplayGumpPacked creating new {0} byte buffer", wantLength);
|
||||
m_PackBuffer = new byte[wantLength];
|
||||
}
|
||||
|
||||
int packLength = m_PackBuffer.Length;
|
||||
|
||||
|
|
@ -2503,6 +2511,9 @@ namespace Server.Network
|
|||
m_Stream.Write( (int) ( 4 + packLength ) );
|
||||
m_Stream.Write( (int) length );
|
||||
m_Stream.Write( m_PackBuffer, 0, packLength );
|
||||
|
||||
lock (m_PackBuffers)
|
||||
m_PackBuffers.ReleaseBuffer(m_PackBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2517,6 +2528,8 @@ namespace Server.Network
|
|||
|
||||
public DisplayGumpFast( Gump g ) : base( 0xB0 )
|
||||
{
|
||||
m_Buffer[0] = (byte)' ';
|
||||
|
||||
EnsureCapacity( 4096 );
|
||||
|
||||
m_Stream.Write( (int) g.Serial );
|
||||
|
|
@ -2532,12 +2545,7 @@ namespace Server.Network
|
|||
private static byte[] m_BeginTextSeparator = Gump.StringToBuffer( " @" );
|
||||
private static byte[] m_EndTextSeparator = Gump.StringToBuffer( "@" );
|
||||
|
||||
private static byte[] m_Buffer = new byte[48];
|
||||
|
||||
static DisplayGumpFast()
|
||||
{
|
||||
m_Buffer[0] = (byte)' ';
|
||||
}
|
||||
private byte[] m_Buffer = new byte[48];
|
||||
|
||||
public void AppendLayout( bool val )
|
||||
{
|
||||
|
|
@ -4378,10 +4386,9 @@ namespace Server.Network
|
|||
{
|
||||
m_PacketID = packetID;
|
||||
|
||||
PacketSendProfile prof = PacketSendProfile.Acquire( GetType() );
|
||||
|
||||
if ( prof != null ) {
|
||||
prof.Created++;
|
||||
if (Core.Profiling) {
|
||||
PacketSendProfile prof = PacketSendProfile.Acquire( GetType() );
|
||||
prof.Increment();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -4400,10 +4407,9 @@ namespace Server.Network
|
|||
m_Stream = PacketWriter.CreateInstance( length );// new PacketWriter( length );
|
||||
m_Stream.Write( ( byte ) packetID );
|
||||
|
||||
PacketSendProfile prof = PacketSendProfile.Acquire( GetType() );
|
||||
|
||||
if ( prof != null ) {
|
||||
prof.Created++;
|
||||
if (Core.Profiling) {
|
||||
PacketSendProfile prof = PacketSendProfile.Acquire( GetType() );
|
||||
prof.Increment();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -4415,6 +4421,9 @@ namespace Server.Network
|
|||
}
|
||||
}
|
||||
|
||||
private const int CompressorBufferSize = 0x10000;
|
||||
private static BufferPool m_CompressorBuffers = new BufferPool("Compressor", 4, CompressorBufferSize);
|
||||
|
||||
private const int BufferSize = 4096;
|
||||
private static BufferPool m_Buffers = new BufferPool( "Compressed", 16, BufferSize );
|
||||
|
||||
|
|
@ -4490,8 +4499,10 @@ namespace Server.Network
|
|||
{
|
||||
Core.Set();
|
||||
|
||||
if ( (m_State & (State.Acquired | State.Static)) == 0 )
|
||||
Free();
|
||||
lock (this) {
|
||||
if ((m_State & (State.Acquired | State.Static)) == 0)
|
||||
Free();
|
||||
}
|
||||
}
|
||||
|
||||
private void Free()
|
||||
|
|
@ -4499,8 +4510,8 @@ namespace Server.Network
|
|||
if ( m_CompiledBuffer == null )
|
||||
return;
|
||||
|
||||
if ( (m_State & State.Buffered) != 0 )
|
||||
m_Buffers.ReleaseBuffer( m_CompiledBuffer );
|
||||
if ((m_State & State.Buffered) != 0)
|
||||
m_Buffers.ReleaseBuffer(m_CompiledBuffer);
|
||||
|
||||
m_State &= ~(State.Static | State.Acquired | State.Buffered);
|
||||
|
||||
|
|
@ -4509,7 +4520,7 @@ namespace Server.Network
|
|||
|
||||
public void Release()
|
||||
{
|
||||
if ( (m_State & State.Acquired) != 0 )
|
||||
if ((m_State & State.Acquired) != 0)
|
||||
Free();
|
||||
}
|
||||
|
||||
|
|
@ -4518,43 +4529,46 @@ namespace Server.Network
|
|||
|
||||
public byte[] Compile( bool compress, out int length )
|
||||
{
|
||||
if ( m_CompiledBuffer == null )
|
||||
lock (this)
|
||||
{
|
||||
if ( (m_State & State.Accessed) == 0 )
|
||||
if (m_CompiledBuffer == null)
|
||||
{
|
||||
m_State |= State.Accessed;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( (m_State & State.Warned) == 0 )
|
||||
if ((m_State & State.Accessed) == 0)
|
||||
{
|
||||
m_State |= State.Warned;
|
||||
|
||||
try
|
||||
m_State |= State.Accessed;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((m_State & State.Warned) == 0)
|
||||
{
|
||||
using ( StreamWriter op = new StreamWriter( "net_opt.log", true ) )
|
||||
m_State |= State.Warned;
|
||||
|
||||
try
|
||||
{
|
||||
using (StreamWriter op = new StreamWriter("net_opt.log", true))
|
||||
{
|
||||
op.WriteLine("Redundant compile for packet {0}, use Acquire() and Release()", this.GetType());
|
||||
op.WriteLine(new System.Diagnostics.StackTrace());
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
op.WriteLine( "Redundant compile for packet {0}, use Acquire() and Release()", this.GetType() );
|
||||
op.WriteLine( new System.Diagnostics.StackTrace() );
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
|
||||
m_CompiledBuffer = new byte[0];
|
||||
m_CompiledLength = 0;
|
||||
|
||||
length = m_CompiledLength;
|
||||
return m_CompiledBuffer;
|
||||
}
|
||||
|
||||
m_CompiledBuffer = new byte[0];
|
||||
m_CompiledLength = 0;
|
||||
|
||||
length = m_CompiledLength;
|
||||
return m_CompiledBuffer;
|
||||
InternalCompile(compress);
|
||||
}
|
||||
|
||||
InternalCompile( compress );
|
||||
length = m_CompiledLength;
|
||||
return m_CompiledBuffer;
|
||||
}
|
||||
|
||||
length = m_CompiledLength;
|
||||
return m_CompiledBuffer;
|
||||
}
|
||||
|
||||
private void InternalCompile( bool compress )
|
||||
|
|
@ -4578,41 +4592,49 @@ namespace Server.Network
|
|||
m_CompiledBuffer = ms.GetBuffer();
|
||||
int length = (int)ms.Length;
|
||||
|
||||
if ( compress )
|
||||
{
|
||||
m_CompiledBuffer = Compression.Compress(
|
||||
m_CompiledBuffer, 0, length,
|
||||
ref length
|
||||
);
|
||||
|
||||
if ( m_CompiledBuffer == null )
|
||||
{
|
||||
Console.WriteLine( "Warning: Compression buffer overflowed on packet 0x{0:X2} ('{1}') (length={2})", m_PacketID, GetType().Name, length );
|
||||
using ( StreamWriter op = new StreamWriter( "compression_overflow.log", true ) )
|
||||
if ( compress ) {
|
||||
byte[] buffer;
|
||||
lock (m_CompressorBuffers)
|
||||
buffer = m_CompressorBuffers.AcquireBuffer();
|
||||
|
||||
Compression.Compress(m_CompiledBuffer, 0, length, buffer, ref length);
|
||||
|
||||
if (length <= 0) {
|
||||
Console.WriteLine("Warning: Compression buffer overflowed on packet 0x{0:X2} ('{1}') (length={2})", m_PacketID, GetType().Name, length);
|
||||
using (StreamWriter op = new StreamWriter("compression_overflow.log", true))
|
||||
{
|
||||
op.WriteLine("{0} Warning: Compression buffer overflowed on packet 0x{1:X2} ('{2}') (length={3})", DateTime.UtcNow, m_PacketID, GetType().Name, length);
|
||||
op.WriteLine( new System.Diagnostics.StackTrace() );
|
||||
op.WriteLine(new System.Diagnostics.StackTrace());
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
m_CompiledLength = length;
|
||||
|
||||
if ( m_CompiledBuffer != null )
|
||||
{
|
||||
if (length > BufferSize || (m_State & State.Static) != 0) {
|
||||
m_CompiledBuffer = new byte[length];
|
||||
} else {
|
||||
lock (m_Buffers)
|
||||
m_CompiledBuffer = m_Buffers.AcquireBuffer();
|
||||
m_State |= State.Buffered;
|
||||
}
|
||||
|
||||
Buffer.BlockCopy(buffer, 0, m_CompiledBuffer, 0, length);
|
||||
|
||||
lock (m_CompressorBuffers)
|
||||
m_CompressorBuffers.ReleaseBuffer(buffer);
|
||||
}
|
||||
} else if (length > 0) {
|
||||
byte[] old = m_CompiledBuffer;
|
||||
m_CompiledLength = length;
|
||||
|
||||
byte[] old = m_CompiledBuffer;
|
||||
|
||||
if ( length > BufferSize || (m_State & State.Static) != 0 )
|
||||
{
|
||||
if ( length > BufferSize || (m_State & State.Static) != 0 ) {
|
||||
m_CompiledBuffer = new byte[length];
|
||||
}
|
||||
else
|
||||
{
|
||||
m_CompiledBuffer = m_Buffers.AcquireBuffer();
|
||||
} else {
|
||||
lock (m_Buffers)
|
||||
m_CompiledBuffer = m_Buffers.AcquireBuffer();
|
||||
m_State |= State.Buffered;
|
||||
}
|
||||
|
||||
Buffer.BlockCopy( old, 0, m_CompiledBuffer, 0, length );
|
||||
Buffer.BlockCopy(old, 0, m_CompiledBuffer, 0, length);
|
||||
}
|
||||
|
||||
PacketWriter.ReleaseInstance( m_Stream );
|
||||
|
|
|
|||
|
|
@ -104,22 +104,27 @@ namespace Server.Network {
|
|||
if ( m_CoalesceBufferSize == value )
|
||||
return;
|
||||
|
||||
if ( m_UnusedBuffers != null )
|
||||
m_UnusedBuffers.Free();
|
||||
BufferPool old = m_UnusedBuffers;
|
||||
|
||||
m_CoalesceBufferSize = value;
|
||||
m_UnusedBuffers = new BufferPool( "Coalesced", 2048, m_CoalesceBufferSize );
|
||||
lock (old) {
|
||||
if ( m_UnusedBuffers != null )
|
||||
m_UnusedBuffers.Free();
|
||||
|
||||
m_CoalesceBufferSize = value;
|
||||
m_UnusedBuffers = new BufferPool( "Coalesced", 2048, m_CoalesceBufferSize );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static byte[] AcquireBuffer() {
|
||||
return m_UnusedBuffers.AcquireBuffer();
|
||||
lock (m_UnusedBuffers)
|
||||
return m_UnusedBuffers.AcquireBuffer();
|
||||
}
|
||||
|
||||
public static void ReleaseBuffer( byte[] buffer ) {
|
||||
if ( buffer != null && buffer.Length == m_CoalesceBufferSize ) {
|
||||
m_UnusedBuffers.ReleaseBuffer( buffer );
|
||||
}
|
||||
lock (m_UnusedBuffers)
|
||||
if ( buffer != null && buffer.Length == m_CoalesceBufferSize )
|
||||
m_UnusedBuffers.ReleaseBuffer( buffer );
|
||||
}
|
||||
|
||||
private Queue<Gram> _pending;
|
||||
|
|
@ -143,15 +148,9 @@ namespace Server.Network {
|
|||
}
|
||||
|
||||
public Gram CheckFlushReady() {
|
||||
Gram gram = null;
|
||||
|
||||
if ( _pending.Count == 0 && _buffered != null ) {
|
||||
gram = _buffered;
|
||||
|
||||
_pending.Enqueue( _buffered );
|
||||
_buffered = null;
|
||||
}
|
||||
|
||||
Gram gram = _buffered;
|
||||
_pending.Enqueue(_buffered);
|
||||
_buffered = null;
|
||||
return gram;
|
||||
}
|
||||
|
||||
|
|
@ -169,7 +168,7 @@ namespace Server.Network {
|
|||
return gram;
|
||||
}
|
||||
|
||||
private const int PendingCap = 96 * 1024;
|
||||
private const int PendingCap = 128 * 1024;
|
||||
|
||||
public Gram Enqueue( byte[] buffer, int length ) {
|
||||
return Enqueue( buffer, 0, length );
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue