protected override void OnTick() { if (RandomEncounterEngine.Debug) { Console.Write("\n****RandomEncounters: Running Cleaner... "); } ArrayList removeList = new ArrayList(); foreach (XmlAttachment attachment in XmlAttach.AllAttachments.Values) { if (attachment is XmlDateCount) { XmlDateCount xmlDate = (XmlDateCount)attachment; long then = xmlDate.Date.Ticks; long now = DateTime.Now.Ticks; long elapsed = (now - then) / 10000000; // the timer doesn't sweep encounters that aren't in the cleanup window if (elapsed < RandomEncounterEngine.Cleanup) { //Console.WriteLine("Object too new {0} for cleanup; skipping", elapsed ); continue; } // now we'll inspect the actual encounter object object o = xmlDate.AttachedTo; if (o == null) // can happen because xmlattach uses lazy evaluation to // cleanup the deletes { continue; } //Console.WriteLine("Object {0} has been around for {1} ", o, elapsed); if (o is Item) { Item i = (Item)o; if (!i.Movable) { if (MaybeRemove(xmlDate, i)) { removeList.Add(new object[2] { xmlDate, i }); } } object parent = i.Parent; // check up the containment hierarchy... while (true) { if (parent == null) { if (MaybeRemove(xmlDate, i)) { removeList.Add(new object[2] { xmlDate, i }); } break; } if (parent is Item) { parent = ((Item)parent).Parent; } else if (parent is Mobile) { // once owned picked up, it will NEVER be cleaned removeList.Add(new object[2] { xmlDate, null }); break; } } } else if (o is Mobile) { if (o is BaseCreature) { BaseCreature c = (BaseCreature)o; if (c.Owners.Count > 0) { // once tamed, it will NEVER be cleaned //Console.WriteLine("Detaching tamed creature: "+o); removeList.Add(new object[2] { xmlDate, null }); continue; } } Mobile m = (Mobile)o; if (m.Combatant == null) { if (MaybeRemove(xmlDate, m)) { removeList.Add(new object[2] { xmlDate, m }); } } } } //------------------------------------------------------------------ // Below following code is a small optimization to keep a big sweep // from causing a lag spike. Basically, it will offset the sweep work // in time in the server, giving the server 1/10th of a second breathers // in the sweep work. //------------------------------------------------------------------ // not quite right because of the possibility of first 250 attachmnts // being not xmldates.... would never do the work. //if( nIterations > 250 ) //{ // DeleteTimer workoff = new DeleteTimer( .10F, 0 ); // workoff.Start(); // break; //} } int nDetached = 0; int nDeleted = 0; foreach (object[] arr in removeList) { XmlDateCount xmlDate = (XmlDateCount)arr[0]; object o = arr[1]; if (o != null) { if (o is Item) { Item i = (Item)o; nDeleted++; i.Delete(); } if (o is Mobile) { Mobile m = (Mobile)o; nDeleted++; m.Delete(); } XmlAttach.Defrag(o); } nDetached++; xmlDate.Delete(); XmlAttach.AllAttachments.Remove(xmlDate.Serial.Value); } if (RandomEncounterEngine.Debug) { Console.WriteLine(" detached = {0}; deleted = {1}", nDetached, nDeleted); } if (Interval.Ticks == 0) { Stop(); } }