The "too much data pending" exception is
TcpListener specific.
When a socket receives too many data-send requests on an output stream, it can close the stream and throw the exception.
There is a limit as to how much data can be streamed through a socket (at one given time).
It would be advantagious for you to impose a limit of some sort on the
CheckActive method, because
OnThink can be called extremely fast, the rate at which the NPC
ActiveSpeed and
PassiveSpeed are set. Usually between .02 and 1.0 seconds.
With the sheer amount of changes made to the creature's variable properties every call, and each change possibly requiring an update packet to be sent to all players near that creature, it's no surprise that the player's
NetState is flooded with "too much data" and disconnects them.
A simple and effective way to get around this would be to impose a time-delay limit in your code.
Here is a sample of a time-delay conditional operation;
Code:
private DateTime _LastEntry = DateTime.Now;
private TimeSpan _EntryDelay = TimeSpan.FromSeconds( 2.0 );
public void EntryMethod()
{
if( CanEnter() )
{
_LastEntry = DateTime.Now;
//Execute code
}
}
public bool CanEnter()
{
if( _LastEntry.Add( _EntryDelay ) < DateTime.Now )
return true;
return false;
}
When applied to your script, it would look like this (edits in
red);
Code:
using System;
using Server;
using System.Collections;
using System.Collections.Generic;
using Server.Items;
using Server.ContextMenus;
using Server.Misc;
using Server.Network;
using Server.Regions;
using Server.Items.Crops;
using Server.Mobiles;
namespace Server.Mobiles
{
public class BaseAnimal : BaseCreature
{
public bool sneaking = false;
public bool eating = false;
private Item fooditem = null;
private int RangeModifier = 4;
public enum ActivityType
{
Night = 0,
Midnight = 3,
Dawn = 6,
Morning = 9,
Noon = 12,
Afternoon = 15,
Evening = 18,
Dusk = 21
}
public enum EatType
{
Herbivore,
Carnivore,
Omnivore
}
public enum AnimalType
{
Wild,
Town,
Farm
}
public enum GroupingType
{
Solitary,
Herd,
Pack,
Hive,
Flock
}
public enum ComStack
{
None,
Wonder,
Combat,
Backoff,
Flee
}
private int m_Rank;
[CommandProperty( AccessLevel.GameMaster )]
public int Rank
{
get { return m_Rank; }
set { m_Rank= value; }
}
private bool m_Ambush = false;
[CommandProperty( AccessLevel.GameMaster )]
public bool Ambush
{
get { return m_Ambush; }
set { m_Ambush = value; }
}
private bool m_Hibernate = false;
[CommandProperty( AccessLevel.GameMaster )]
public bool Hibernate
{
get { return m_Hibernate ; }
set { m_Hibernate = value; }
}
private ComStack m_AIStack;
[CommandProperty( AccessLevel.GameMaster )]
public ComStack AIStack
{
get { return m_AIStack; }
set { m_AIStack = value; }
}
private int m_Size;
[CommandProperty( AccessLevel.GameMaster )]
public int Size
{
get { return m_Size; }
set { m_Size = value; }
}
private ActivityType m_BActivity = ActivityType.Dawn;
[CommandProperty( AccessLevel.GameMaster )]
public ActivityType BeginActivity
{
get { return m_BActivity; }
set { m_BActivity = value; }
}
private ActivityType m_FActivity = ActivityType.Evening;
[CommandProperty( AccessLevel.GameMaster )]
public ActivityType FinishActivity
{
get { return m_FActivity; }
set { m_FActivity = value; }
}
private EatType m_Eats;
[CommandProperty( AccessLevel.GameMaster )]
public EatType Eats
{
get { return m_Eats; }
set { m_Eats = value; }
}
private AnimalType m_Animal = AnimalType.Wild;
[CommandProperty( AccessLevel.GameMaster )]
public AnimalType Animal
{
get { return m_Animal; }
set { m_Animal = value; }
}
private GroupingType m_Grouping;
[CommandProperty( AccessLevel.GameMaster )]
public GroupingType Grouping
{
get { return m_Grouping; }
set { m_Grouping = value; }
}
public BaseAnimal() : base( AIType.AI_Animal, FightMode.Aggressor, 15, 1, 0.2, 0.4 )
{
}
public BaseAnimal(AIType ai, FightMode mode, int iRangePerception, int iRangeFight, double dActiveSpeed, double dPassiveSpeed): base (ai, mode, iRangePerception, iRangeFight, dActiveSpeed, dPassiveSpeed)
{
}
protected override bool OnMove( Direction d )
{
if (!sneaking)
RevealingAction();
return true;
}
public virtual bool CropFood(Item item)
{
if (item is Grasses)
return true;
else if (item is SpinachCrop || item is SnowPeasCrop || item is PeasCrop || item is LettuceCrop || item is GreenBeanCrop || item is CabbageCrop )
return true;
else if (item is FarmableCabbage || item is FarmableLettuce)
return true;
else if (this.Size > 7)
{
if (item is FarmableWheat || item is FarmablePumpkin)
return true;
else if (item is CornCrop || item is PumpkinCrop || item is WheatCrop || item is SquashCrop || item is SoyCrop || item is OatsCrop || item is HoneydewMelonCrop || item is HayCrop || item is GreenSquashCrop || item is FieldCornCrop || item is CantaloupeCrop )
return true;
}
else if (this.Size <=7)
{
if (item is FarmableCarrot || item is FarmableOnion || item is FarmableTurnip)
return true;
else if (item is TurnipCrop || item is WatermelonCrop || item is StrawberryCrop || item is RadishCrop || item is OnionCrop || item is CucumberCrop || item is CeleryCrop || item is CauliflowerCrop || item is BroccoliCrop || item is BeetCrop || item is AsparagusCrop )
return true;
}
return false;
}
public virtual bool CanEatIt(Item item)
{
if ((item is Corpse) || (item is Remains))
if ((this.Eats == EatType.Carnivore) || (this.Eats == EatType.Omnivore))
return true;
if (CropFood(item ))
if ((this.Eats == EatType.Herbivore) || (this.Eats == EatType.Omnivore))
return true;
if (item is Food)
if (this.Eats == EatType.Omnivore)
return true;
return false;
}
public virtual void FindFood()
{
int HungerRange = 0;
if (Hunger < 5) HungerRange = 30;
else if (Hunger >= 5 && Hunger < 10) HungerRange = 20;
else if (Hunger >= 10 && Hunger <= 20) HungerRange = 10;
else HungerRange = 0;
if (fooditem == null)
{
foreach ( Item item in this.GetItemsInRange( HungerRange ) )
{
if (CanEatIt(item))
{
this.Home = item.Location;
this.RangeHome = 0;
fooditem = item;
break;
}
}
}
else if (fooditem != null)
{
if (InRange ( fooditem, 0))
{
if (fooditem is Corpse)
{
Corpse cor = (Corpse) fooditem;
if (cor.Owner is PlayerMobile)
{
Remains remTorso = new Remains();
remTorso.ItemID = 0x1D9F;
remTorso.RemainsAmount = 4;
remTorso.Name = cor.Owner.Name;
remTorso.MoveToWorld (cor.Location, cor.Map);
Head head = new Head( String.Format( "the head of {0}", cor.Owner.Name ) );
head.HeadName = cor.Owner.Name;
head.MoveToWorld( cor.Location, cor.Map );
Remains remLArm = new Remains();
remLArm.ItemID = 0x1DA1;
remLArm.RemainsAmount = 1;
remLArm.Name = cor.Owner.Name;
remLArm.MoveToWorld (cor.Location, cor.Map);
Remains remRArm = new Remains();
remRArm.ItemID = 0x1DA2;
remRArm.RemainsAmount = 1;
remRArm.Name = cor.Owner.Name;
remRArm.MoveToWorld (cor.Location, cor.Map);
Remains remLLeg = new Remains();
remLLeg.ItemID = 0x1DA3;
remLLeg.RemainsAmount = 2;
remLLeg.Name = cor.Owner.Name;
remLLeg.MoveToWorld (cor.Location, cor.Map);
Remains remRLeg = new Remains();
remRLeg.ItemID = 0x1DA4;
remRLeg.RemainsAmount = 2;
remRLeg.Name = cor.Owner.Name;
remRLeg.MoveToWorld (cor.Location, cor.Map);
List<Item> items = new List<Item>( cor.Items );
Backpack bag = new Backpack();
for ( int i = 0; i < items.Count; ++i )
{
Item item = items[i];
if ( ((item.Layer == Layer.Hair) || (item.Layer == Layer.FacialHair)) || !item.Movable )
continue;
if ((item is BaseClothing) || (item is BaseArmor) || (item is BaseWeapon) || (item is Food))
item.MoveToWorld(cor.Location, cor.Map);
else
bag.DropItem( item );
}
bag.MoveToWorld (cor.Location, cor.Map);
new Blood( 0x122D ).MoveToWorld( cor.Location, cor.Map );
cor.Delete();
this.Hunger += 1;
}
else if (cor.Owner is BaseAnimal)
{
Remains rema = new Remains();
rema.Hue = cor.Hue;
BaseAnimal ba = (BaseAnimal) cor.Owner;
rema.RemainsAmount = ba.Size;
rema.Name = ba.Name;
rema.ItemID = 0x2006;
rema.Amount = ba.Body;
rema.MoveToWorld (cor.Location, cor.Map);
new Blood( 0x122D ).MoveToWorld( cor.Location, cor.Map );
cor.Delete();
this.Hunger += 1;
}
else
{
Remains rema = new Remains();
rema.RemainsAmount = 10;
rema.MoveToWorld(cor.Location, cor.Map);
new Blood( 0x122D ).MoveToWorld( cor.Location, cor.Map );
cor.Delete();
this.Hunger += 1;
}
}
else if (fooditem is Remains)
{
Remains rema = (Remains) fooditem;
if (rema.RemainsAmount < 1)
{
Grasses grass = new Grasses();
grass.Location = rema.Location;
grass.Map = rema.Map;
grass.MoveToWorld(grass.Location, grass.Map);
eating = false;
rema.Delete();
}
else
rema.RemainsAmount -= 1;
this.Hunger += 1;
}
else if ((CropFood(fooditem)))
{
Item fi = (Item) fooditem;
if (fi is Grasses)
this.Hunger += 1;
else
this.Hunger += 4;
eating = false;
fi.Delete();
}
else if (fooditem is Food)
{
Food fi = (Food) fooditem;
this.Hunger += 1;
eating = false;
fi.Delete();
}
fooditem = null;
this.RangeHome = (Size + RangeModifier) * RangeModifier;
}
}
}
public virtual bool IsPrey(Mobile mob)
{
if (mob.AccessLevel >= AccessLevel.GameMaster)
return false;
if ((mob is PlayerMobile) && (this.Size > 8) && (this.Animal == AnimalType.Wild))
return true;
else if (mob is BaseAnimal)
{
BaseAnimal ba = (BaseAnimal) mob;
if ( this.Name == ba.Name )
return false;
else if ((this.Animal == AnimalType.Town) && (ba.Animal == AnimalType.Farm)) //Wild, Town, Farm
return false;
else if ((this.Animal == AnimalType.Town) && (ba.Animal == AnimalType.Town) && (this.Size > ba.Size) )
{
if (Utility.Random(50) == 1)
return true;
else
return false;
}
else if (this.Size > ba.Size)
return true;
}
return false;
}
public virtual bool IsPredator(Mobile mob)
{
if (mob.AccessLevel >= AccessLevel.GameMaster)
return false;
if (mob is BaseAnimal)
{
BaseAnimal ba = (BaseAnimal) mob;
if (this.Name == ba.Name)
return false;
if (ba.Size >= this.Size)
{
if ((this.Animal == AnimalType.Wild) && (ba.Eats != EatType.Herbivore))
return true;
else if ((this.Animal == AnimalType.Town) && (ba.Eats != EatType.Herbivore) && (ba.Size > this.Size +3))
return true;
else if (ba.Eats == EatType.Herbivore)
return false;
}
}
else if (mob is PlayerMobile)
{
if ((this.Eats == EatType.Herbivore) && (this.Size < 15) && (this.Animal == AnimalType.Wild))
return true;
else if ((this.Eats == EatType.Omnivore) && (this.Size < 10) && (this.Animal == AnimalType.Wild))
return true;
else if ((this.Eats == EatType.Carnivore) && (this.Size < 8) && (this.Animal == AnimalType.Wild))
return true;
else if ((this.Animal == AnimalType.Farm) || (this.Animal == AnimalType.Town))
return false;
}
return false;
}
public virtual void CanAmbush(Mobile mob)
{
double HunterRange = GetDistanceToSqrt(mob);
bool StrikeRange, ShortRange, MediumRange, LongRange;
StrikeRange = ShortRange = MediumRange = LongRange = false;
if (HunterRange < 2) StrikeRange = true;
else if ((HunterRange >= 2) && (HunterRange < 10)) ShortRange = true;
else if ((HunterRange >= 10) && (HunterRange < 20)) MediumRange = true;
else if (HunterRange >= 20) LongRange = true;
if(ShortRange)
{
this.Hidden = true;
this.sneaking = true;
}
else if(StrikeRange)
{
this.sneaking = false;
}
else
this.sneaking = false;
}
public override void OnMovement( Mobile m, Point3D oldLocation )
{
if (!m.Hidden && InRange(m, 20) && !InRange( oldLocation, 1 ) && InLOS( m ) && !eating)
{
if (IsPredator(m))
{
this.FightMode = FightMode.Aggressor;
}
else if (IsPrey(m) && (this.Eats != EatType.Herbivore) && IsHungry())
{
if (this.Combatant == null) this.Combatant = (m);
this.FightMode = FightMode.Closest;
if (Ambush) CanAmbush(m);
}
/*
else if (IsEnemy(m))
{
if (this.Combatant == null) this.Combatant = (m);
this.FightMode = FightMode.Closest;
if (Ambush) CanAmbush(m);
}
*/
else
{
this.FightMode = FightMode.Aggressor;
}
}
}
public override bool IsEnemy( Mobile m )
{
if (m.AccessLevel >= AccessLevel.GameMaster)
return false;
return false;
}
public override void OnAfterSpawn()
{
int rankle;
if ((this.Grouping > GroupingType.Solitary) && (this.Rank == 0))
{
rankle = Utility.Random(100);
this.Rank = rankle;
}
this.Hunger = 10;
}
private DateTime _LastActiveCheck = DateTime.Now;
private TimeSpan _ActiveCheckDelay = TimeSpan.FromSeconds( 2.0 );
public bool CanCheckActive()
{
if( _LastActiveCheck.Add( _ActiveCheckDelay ) < DateTime.Now )
return true;
return false;
}
public virtual void CheckActive()
{
if( !CanCheckActive() )
return;
else
_LastActiveCheck = DateTime.Now;
int hours, minutes;
if (Blessed == true)
{
Hunger = 10;
this.RangeHome = (Size + RangeModifier) * RangeModifier;
}
if (!(this.Region is DungeonRegion) )
{
Server.Items.Clock.GetTime(this.Map, this.X, this.Y, out hours, out minutes);
if (m_BActivity < m_FActivity)
{
if ((hours >= (int) m_BActivity ) && (hours <= (int) m_FActivity))
{
this.AccessLevel = AccessLevel.Player;
this.Blessed = false;
this.Hidden = false;
this.sneaking = false;
}
else if (((hours < (int) m_BActivity ) || (hours > (int) m_FActivity)) && (this.Combatant == null))
{
this.AccessLevel = AccessLevel.GameMaster;
this.Blessed = true;
this.Hidden = true;
this.sneaking = true;
}
}
if (m_BActivity > m_FActivity)
{
if ((hours >= (int) m_BActivity ) || (hours <= (int) m_FActivity))
{
this.AccessLevel = AccessLevel.Player;
this.Blessed = false;
this.Hidden = false;
this.sneaking = false;
}
else if (((hours < (int) m_BActivity ) && (hours > (int) m_FActivity)) && (this.Combatant == null))
{
this.AccessLevel = AccessLevel.GameMaster;
this.Blessed = true;
this.Hidden = true;
this.sneaking = true;
}
}
}
if (m_Hibernate == true)
{
Map map;
map = Map.AllMaps[1];
if (map.Season == 2) //2 = fall, 3 = winter
{
this.AccessLevel = AccessLevel.GameMaster;
this.Blessed = true;
this.Hidden = true;
this.sneaking = true;
}
else
{
this.AccessLevel = AccessLevel.Player;
this.Blessed = false;
}
}
}
public virtual bool IsHungry()
{
if (this.Combatant != null)
return false;
else if (this.Hunger < 5)
{
return true;
}
else if ((this.Hunger >= 5) && (this.Hunger <= 20))
{
if (Utility.Random(100) < (21 - this.Hunger))
{
return true;
}
}
return false;
}
public override void OnThink()
{
this.Size = (int) (Math.Round( ((double)this.HitsMax + (double)this.DamageMax + 5) /5));
if (fooditem == null)
{
this.RangeHome = (Size + RangeModifier) * RangeModifier;
}
CheckActive();
if (IsHungry()) FindFood();
}
public BaseAnimal( Serial serial ) : base( serial )
{
}
public override void Serialize( GenericWriter writer )
{
base.Serialize( writer );
writer.Write( (int) 1 ); // version
writer.Write( (int) m_Rank);
writer.Write( (bool) m_Ambush);
writer.Write( (bool) m_Hibernate);
writer.Write( (int) m_AIStack);
writer.Write( (int) m_Size);
writer.Write( (int) m_BActivity );
writer.Write( (int) m_FActivity );
writer.Write( (int) m_Eats);
writer.Write( (int) m_Animal);
writer.Write( (int) m_Grouping);
}
public override void Deserialize( GenericReader reader )
{
base.Deserialize( reader );
int version = reader.ReadInt();
switch (version)
{
case 2:
{
goto case 1;
}
case 1:
{
m_Rank = reader.ReadInt();
m_Ambush = reader.ReadBool();
m_Hibernate = reader.ReadBool();
m_AIStack = (ComStack)reader.ReadInt();
m_Size = reader.ReadInt();
m_BActivity = (ActivityType)reader.ReadInt();
m_FActivity = (ActivityType)reader.ReadInt();
m_Eats = (EatType)reader.ReadInt();
m_Animal = (AnimalType)reader.ReadInt();
m_Grouping = (GroupingType)reader.ReadInt();
goto case 0;
}
case 0:
break;
}
}
}
}
//============================================================================
namespace Server.Items
{
public class Remains : Item
{
private int m_RemainsAmount;
[CommandProperty( AccessLevel.GameMaster )]
public int RemainsAmount
{
get { return m_RemainsAmount; }
set { m_RemainsAmount = value; }
}
[Constructable]
public Remains( ) : base(0x1B19)
{
// To supress console warnings, stackable must be true
Stackable = true;
Name = "remains";
Weight = 10.0;
}
public override bool OnDragLift( Mobile from )
{
from.SendMessage("the remains fall apart in your hands");
this.Delete();
return true;
}
public Remains( Serial serial ) : base( serial )
{
}
public override void GetProperties( ObjectPropertyList list )
{
if (this.Name == null)
list.Add("creature remains");
else
list.Add("the remains of " + this.Name);
}
public override void Serialize( GenericWriter writer )
{
base.Serialize( writer );
writer.Write( (int) 0 ); // version
writer.Write( (int) m_RemainsAmount);
}
public override void Deserialize( GenericReader reader )
{
base.Deserialize( reader );
int version = reader.ReadInt();
switch (version)
{
case 1:
{
goto case 0;
}
case 0:
m_RemainsAmount = reader.ReadInt();
break;
}
}
}
// ===== Grasses =====
public class Grasses : Item
{
[Constructable]
public Grasses( ) : base(0xCC5)
{
ItemID = 0xCC5;
Name = "grasses";
}
public override bool OnDragLift( Mobile from )
{
from.SendMessage("you pull some grass out of the ground");
this.Delete();
return true;
}
public Grasses( Serial serial ) : base( serial )
{
}
public override void Serialize( GenericWriter writer )
{
base.Serialize( writer );
writer.Write( (int) 0 ); // version
}
public override void Deserialize( GenericReader reader )
{
base.Deserialize( reader );
int version = reader.ReadInt();
}
}
}
This will limit the
CheckActive method to executing only once every 2.0 seconds, instead of once every 0.2 to 1.0 seconds.