Search in sources :

Example 1 with EventContextKey

use of org.spongepowered.api.event.EventContextKey in project SpongeCommon by SpongePowered.

the class PhaseTracker method popCauseFrame.

@Override
public void popCauseFrame(final StackFrame oldFrame) {
    checkNotNull(oldFrame, "oldFrame");
    this.enforceMainThread();
    @Nullable final SpongeCauseStackFrame frame = this.frames.peek();
    if (frame != oldFrame) {
        // If the given frame is not the top frame then some form of
        // corruption of the stack has occurred and we do our best to correct
        // it.
        // If the target frame is still in the stack then we can pop frames
        // off the stack until we reach it, otherwise we have no choice but
        // to simply throw an error.
        int offset = -1;
        int i = 0;
        for (final SpongeCauseStackFrame f : this.frames) {
            if (f == oldFrame) {
                offset = i;
                break;
            }
            i++;
        }
        if (!PhaseTracker.DEBUG_CAUSE_FRAMES && offset == -1) {
            // that was erroneously popped.
            throw new IllegalStateException("Cause Stack Frame Corruption! Attempted to pop a frame that was not on the stack.");
        }
        final PrettyPrinter printer = new PrettyPrinter(100).add("Cause Stack Frame Corruption!").centre().hr().add("Found %d frames left on the stack. Clearing them all.", new Object[] { offset + 1 });
        if (!PhaseTracker.DEBUG_CAUSE_FRAMES) {
            printer.add().add("Please add -Dsponge.debugcauseframes=true to your startup flags to enable further debugging output.");
            SpongeCommon.logger().warn("  Add -Dsponge.debugcauseframes to your startup flags to enable further debugging output.");
        } else {
            printer.add().add("Attempting to pop frame:").add(frame.stackDebug).add().add("Frames being popped are:").add(((SpongeCauseStackFrame) oldFrame).stackDebug);
        }
        while (offset >= 0) {
            @Nullable final SpongeCauseStackFrame f = this.frames.peek();
            if (PhaseTracker.DEBUG_CAUSE_FRAMES && offset > 0) {
                printer.add("   Stack frame in position %d :", new Object[] { offset });
                printer.add(f.stackDebug);
            }
            this.popCauseFrame(f);
            offset--;
        }
        printer.trace(System.err, SpongeCommon.logger(), Level.ERROR);
        if (offset == -1) {
            // so we throw an exception.
            throw new IllegalStateException("Cause Stack Frame Corruption! Attempted to pop a frame that was not on the stack.");
        }
        return;
    }
    this.frames.pop();
    // Remove new values
    for (final Map.Entry<EventContextKey<?>, Object> entry : frame.getOriginalContextDelta().entrySet()) {
        this.cached_ctx = null;
        if (entry.getValue() == null) {
            // wasn't present before, remove
            this.ctx.remove(entry.getKey());
        } else {
            // was there, replace
            this.ctx.put(entry.getKey(), entry.getValue());
        }
    }
    // If there were any objects left on the stack then we pop them off
    while (this.cause.size() > this.min_depth) {
        final int index = this.cause.size();
        // there was a duplicate cause pushed prior to the frame being popped.
        if (this.duplicateCauses.length > index) {
            // At this point, we now need to "clean" the duplicate causes array of duplicates
            // to avoid potentially pruning earlier frame's potentially duplicate causes.
            // And of course, reset the number of duplicates in the entry.
            this.duplicateCauses[index] = 0;
        }
        this.cause.pop();
        // and clear the cached causes
        this.cached_cause = null;
    }
    this.min_depth = frame.old_min_depth;
    final int size = this.cause.size();
    if (this.duplicateCauses.length > size) {
        // Then set the last cause index to whatever the size of the entry was at the time.
        this.duplicateCauses[size] = frame.lastCauseSize;
    }
    // finally, return the frame to the pool
    if (this.framePool.size() < PhaseTracker.MAX_POOL_SIZE) {
        // cache it, but also call clear so we remove references to
        // other objects that may go out of scope
        frame.clear();
        this.framePool.push(frame);
    }
}
Also used : PrettyPrinter(org.spongepowered.common.util.PrettyPrinter) EventContextKey(org.spongepowered.api.event.EventContextKey) Map(java.util.Map) IdentityHashMap(java.util.IdentityHashMap) Nullable(org.checkerframework.checker.nullness.qual.Nullable)

Example 2 with EventContextKey

use of org.spongepowered.api.event.EventContextKey in project SpongeCommon by SpongePowered.

the class ContextValueFilterSourceDelegate method insertCauseCall.

@Override
protected void insertCauseCall(final MethodVisitor mv, final ListenerClassVisitor.ListenerParameter param, final Type targetType) {
    final Field targetField;
    try {
        targetField = EventContextKeys.class.getField(this.anno.value());
    } catch (final NoSuchFieldException ex) {
        throw new IllegalArgumentException(String.format("Field %s specified by GetValue annotation was not found in EventContextKeys", this.anno.value()));
    }
    if (!EventContextKey.class.isAssignableFrom(targetField.getType())) {
        throw new IllegalArgumentException(String.format("Field %s.%s was not an EventContextKey", targetField.getName(), targetField.getType()));
    }
    // cause.context().get(EventContextKeys.<anno.value()>
    mv.visitMethodInsn(INVOKEVIRTUAL, CauseFilterSourceDelegate.CAUSE.getInternalName(), "context", "()" + ContextValueFilterSourceDelegate.EVENT_CONTEXT.getDescriptor(), false);
    mv.visitFieldInsn(GETSTATIC, ContextValueFilterSourceDelegate.EVENT_CONTEXT_KEYS.getInternalName(), this.anno.value(), ContextValueFilterSourceDelegate.EVENT_CONTEXT_KEY.getDescriptor());
    mv.visitMethodInsn(INVOKEVIRTUAL, ContextValueFilterSourceDelegate.EVENT_CONTEXT.getInternalName(), "get", Type.getMethodDescriptor(ParameterFilterSourceDelegate.OPTIONAL, ContextValueFilterSourceDelegate.EVENT_CONTEXT_KEY), false);
}
Also used : Field(java.lang.reflect.Field) EventContextKey(org.spongepowered.api.event.EventContextKey) EventContextKeys(org.spongepowered.api.event.EventContextKeys)

Aggregations

EventContextKey (org.spongepowered.api.event.EventContextKey)2 Field (java.lang.reflect.Field)1 IdentityHashMap (java.util.IdentityHashMap)1 Map (java.util.Map)1 Nullable (org.checkerframework.checker.nullness.qual.Nullable)1 EventContextKeys (org.spongepowered.api.event.EventContextKeys)1 PrettyPrinter (org.spongepowered.common.util.PrettyPrinter)1