// ===============================================================
        public void Objects_ObjectUpdate(Object sender, OMV.PrimEventArgs args)
        {
            if (args.IsAttachment) {
            Objects_AttachmentUpdate(sender, args);
            return;
            }
            if (QueueTilOnline(args.Simulator, CommActionCode.OnObjectUpdated, sender, args)) return;
            lock (m_opLock) {
            LLRegionContext rcontext = FindRegion(args.Simulator);
            if (!ParentExists(rcontext, args.Prim.ParentID)) {
                // if this requires a parent and the parent isn't here yet, queue this operation til later
                rcontext.RequestLocalID(args.Prim.ParentID);
                m_statRequestLocalID++;
                QueueTilLater(args.Simulator, CommActionCode.OnObjectUpdated, sender, args);
                return;
            }
            this.m_statObjObjectUpdate++;
            IEntity updatedEntity = null;
            // a full update says everything changed
            UpdateCodes updateFlags = 0;
            updateFlags |= UpdateCodes.Position | UpdateCodes.Rotation;
            m_log.Log(LogLevel.DUPDATEDETAIL, "Object update: id={0}, p={1}, r={2}",
                args.Prim.LocalID, args.Prim.Position.ToString(), args.Prim.Rotation.ToString());
            try {
                if (rcontext.TryGetCreateEntityLocalID(args.Prim.LocalID, out updatedEntity, delegate() {
                            // code called to create the entry if it's not found
                            updateFlags |= UpdateCodes.New;
                            updateFlags |= UpdateCodes.Acceleration | UpdateCodes.AngularVelocity | UpdateCodes.Velocity;
                            return new LLEntityPhysical(rcontext.AssetContext,
                                             rcontext, args.Simulator.Handle, args.Prim.LocalID, args.Prim);
                        }) ) {
                    // new prim created
                    // If this requires special rendering parameters add those parameters
                    // At the moment, the only case is foliage
                    if (args.Prim.PrimData.PCode == OpenMetaverse.PCode.Grass
                                || args.Prim.PrimData.PCode == OpenMetaverse.PCode.Tree
                                || args.Prim.PrimData.PCode == OpenMetaverse.PCode.NewTree) {
                        LLSpecialRenderType srt = new LLSpecialRenderType();
                        srt.Type = SpecialRenderTypes.Foliage;
                        srt.FoliageType = args.Prim.PrimData.PCode;
                        srt.TreeType = args.Prim.TreeSpecies;
                        updatedEntity.RegisterInterface<ISpecialRender>(srt);
                    }
                    // if there are animations for this entity
                    ProcessEntityAnimation(updatedEntity, ref updateFlags, args.Prim.AngularVelocity);
                }
                // send updates for this entity updates
                ProcessEntityUpdates(updatedEntity, updateFlags);
            }
            catch (Exception e) {
                m_log.Log(LogLevel.DBADERROR, "FAILED CREATION OF NEW PRIM: " + e.ToString());
            }
            }

            return;
        }
        // ===============================================================
        private void Objects_TerseObjectUpdate(Object sender, OMV.TerseObjectUpdateEventArgs args)
        {
            if (QueueTilOnline(args.Simulator, CommActionCode.TerseObjectUpdate, sender, args)) return;
            LLRegionContext rcontext = FindRegion(args.Simulator);
            OMV.ObjectMovementUpdate update = args.Update;
            this.m_statObjTerseUpdate++;
            IEntity updatedEntity = null;
            UpdateCodes updateFlags = 0;
            lock (m_opLock) {
            if (args.Prim.Acceleration != args.Update.Acceleration) updateFlags |= UpdateCodes.Acceleration;
            if (args.Prim.Velocity != args.Update.Velocity) updateFlags |= UpdateCodes.Velocity;
            if (args.Prim.AngularVelocity != args.Update.AngularVelocity) updateFlags |= UpdateCodes.AngularVelocity;
            if (args.Prim.Position != args.Update.Position) updateFlags |= UpdateCodes.Position;
            if (args.Prim.Rotation != args.Update.Rotation) updateFlags |= UpdateCodes.Rotation;
            if (update.Avatar) updateFlags |= UpdateCodes.CollisionPlane;
            if (update.Textures != null) updateFlags |= UpdateCodes.Textures;
            m_log.Log(LogLevel.DUPDATEDETAIL, "Object update: id={0}, p={1}, r={2}",
                    update.LocalID, update.Position.ToString(), update.Rotation.ToString());

            try {
                if (args.Prim.ID == OMV.UUID.Zero) {
                    m_log.Log(LogLevel.DBADERROR, "TerseObjectUpdate: received prim with UUID zero");
                    return;
                }
                if (rcontext.TryGetCreateEntityLocalID(args.Prim.LocalID, out updatedEntity, delegate() {
                            // code called to create the entry if it's not found
                            updateFlags |= UpdateCodes.New;
                            updateFlags |= UpdateCodes.Acceleration | UpdateCodes.AngularVelocity | UpdateCodes.Velocity;
                            return new LLEntityPhysical(rcontext.AssetContext,
                                             rcontext, args.Simulator.Handle, args.Prim.LocalID, args.Prim);
                        }) ) {
                    // new prim created
                    // If this requires special rendering parameters add those parameters
                    // At the moment, the only case is foliage
                    if (args.Prim.PrimData.PCode == OpenMetaverse.PCode.Grass
                                || args.Prim.PrimData.PCode == OpenMetaverse.PCode.Tree
                                || args.Prim.PrimData.PCode == OpenMetaverse.PCode.NewTree) {
                        LLSpecialRenderType srt = new LLSpecialRenderType();
                        srt.Type = SpecialRenderTypes.Foliage;
                        srt.FoliageType = args.Prim.PrimData.PCode;
                        srt.TreeType = args.Prim.TreeSpecies;
                        updatedEntity.RegisterInterface<ISpecialRender>(srt);
                    }
                    // if there are animations for this entity
                    ProcessEntityAnimation(updatedEntity, ref updateFlags, args.Prim.AngularVelocity);
                }
                // send updates for this entity updates
                ProcessEntityUpdates(updatedEntity, updateFlags);
            }
            catch (Exception e) {
                m_log.Log(LogLevel.DBADERROR, "FAILED CREATION OF NEW PRIM: " + e.ToString());
            }
            }

            return;
        }