package net.minecraft.world.entity; import java.util.ArrayList; import java.util.EnumSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.function.Consumer; import net.minecraft.Util; public interface InsideBlockEffectApplier { InsideBlockEffectApplier NOOP = new InsideBlockEffectApplier() { @Override public void apply(InsideBlockEffectType type) { } @Override public void runBefore(InsideBlockEffectType type, Consumer effect) { } @Override public void runAfter(InsideBlockEffectType type, Consumer effect) { } }; void apply(InsideBlockEffectType type); void runBefore(InsideBlockEffectType type, Consumer effect); void runAfter(InsideBlockEffectType type, Consumer effect); public static class StepBasedCollector implements InsideBlockEffectApplier { private static final InsideBlockEffectType[] APPLY_ORDER = InsideBlockEffectType.values(); private static final int NO_STEP = -1; private final Set effectsInStep = EnumSet.noneOf(InsideBlockEffectType.class); private final Map>> beforeEffectsInStep = Util.makeEnumMap( InsideBlockEffectType.class, insideBlockEffectType -> new ArrayList() ); private final Map>> afterEffectsInStep = Util.makeEnumMap( InsideBlockEffectType.class, insideBlockEffectType -> new ArrayList() ); private final List> finalEffects = new ArrayList(); private int lastStep = -1; public void advanceStep(int step) { if (this.lastStep != step) { this.lastStep = step; this.flushStep(); } } public void applyAndClear(Entity entity) { this.flushStep(); for (Consumer consumer : this.finalEffects) { if (!entity.isAlive()) { break; } consumer.accept(entity); } this.finalEffects.clear(); this.lastStep = -1; } private void flushStep() { for (InsideBlockEffectType insideBlockEffectType : APPLY_ORDER) { List> list = (List>)this.beforeEffectsInStep.get(insideBlockEffectType); this.finalEffects.addAll(list); list.clear(); if (this.effectsInStep.remove(insideBlockEffectType)) { this.finalEffects.add(insideBlockEffectType.effect()); } List> list2 = (List>)this.afterEffectsInStep.get(insideBlockEffectType); this.finalEffects.addAll(list2); list2.clear(); } } @Override public void apply(InsideBlockEffectType type) { this.effectsInStep.add(type); } @Override public void runBefore(InsideBlockEffectType type, Consumer effect) { ((List)this.beforeEffectsInStep.get(type)).add(effect); } @Override public void runAfter(InsideBlockEffectType type, Consumer effect) { ((List)this.afterEffectsInStep.get(type)).add(effect); } } }