package gregtech.api.interfaces; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.function.BiPredicate; import java.util.function.ToLongFunction; import net.minecraftforge.common.util.ForgeDirection; import com.google.common.collect.ImmutableList; import com.gtnewhorizon.structurelib.structure.IStructureElement; import gregtech.api.interfaces.metatileentity.IMetaTileEntity; import gregtech.api.interfaces.tileentity.IGregTechTileEntity; import gregtech.api.util.GT_StructureUtility; import gregtech.api.util.IGT_HatchAdder; public interface IHatchElement<T> { List<? extends Class<? extends IMetaTileEntity>> mteClasses(); IGT_HatchAdder<? super T> adder(); String name(); long count(T t); default <T2 extends T> IHatchElement<T2> withMteClass(Class<? extends IMetaTileEntity> aClass) { if (aClass == null) throw new IllegalArgumentException(); return withMteClasses(Collections.singletonList(aClass)); } @SuppressWarnings("unchecked") // can't set SafeVarargs :( default <T2 extends T> IHatchElement<T2> withMteClasses(Class<? extends IMetaTileEntity>... aClasses) { if (aClasses == null) throw new IllegalArgumentException(); return withMteClasses(Arrays.asList(aClasses)); } default <T2 extends T> IHatchElement<T2> withMteClasses(List<Class<? extends IMetaTileEntity>> aClasses) { if (aClasses == null) throw new IllegalArgumentException(); return new HatchElement<>(aClasses, null, null, null, this); } default <T2 extends T> IHatchElement<T2> withAdder(IGT_HatchAdder<T2> aAdder) { if (aAdder == null) throw new IllegalArgumentException(); return new HatchElement<>(null, aAdder, null, null, this); } default IHatchElement<T> withName(String aName) { if (aName == null) throw new IllegalArgumentException(); return new HatchElement<>(null, null, aName, null, this); } default <T2 extends T> IHatchElement<T2> withCount(ToLongFunction<T2> aCount) { if (aCount == null) throw new IllegalArgumentException(); return new HatchElement<>(null, null, null, aCount, this); } default <T2 extends T> IStructureElement<T2> newAny(int aCasingIndex, int aDot) { if (aCasingIndex < 0 || aDot < 0) throw new IllegalArgumentException(); return GT_StructureUtility.<T2>buildHatchAdder() .anyOf(this) .casingIndex(aCasingIndex) .dot(aDot) .continueIfSuccess() .build(); } default <T2 extends T> IStructureElement<T2> newAny(int aCasingIndex, int aDot, ForgeDirection... allowedFacings) { if (aCasingIndex < 0 || aDot < 0) throw new IllegalArgumentException(); return GT_StructureUtility.<T2>buildHatchAdder() .anyOf(this) .casingIndex(aCasingIndex) .dot(aDot) .continueIfSuccess() .allowOnly(allowedFacings) .build(); } default <T2 extends T> IStructureElement<T2> newAny(int aCasingIndex, int aDot, BiPredicate<? super T2, ? super IGregTechTileEntity> aShouldSkip) { if (aCasingIndex < 0 || aDot < 0 || aShouldSkip == null) throw new IllegalArgumentException(); return GT_StructureUtility.<T2>buildHatchAdder() .anyOf(this) .casingIndex(aCasingIndex) .dot(aDot) .shouldSkip(aShouldSkip) .continueIfSuccess() .build(); } default <T2 extends T> IHatchElement<T2> or(IHatchElement<? super T2> fallback) { return new HatchElementEither<>(this, fallback); } } class HatchElementEither<T> implements IHatchElement<T> { private final IHatchElement<? super T> first, second; private ImmutableList<? extends Class<? extends IMetaTileEntity>> mMteClasses; private String name; HatchElementEither(IHatchElement<? super T> first, IHatchElement<? super T> second) { this.first = first; this.second = second; } @Override public List<? extends Class<? extends IMetaTileEntity>> mteClasses() { if (mMteClasses == null) mMteClasses = ImmutableList.<Class<? extends IMetaTileEntity>>builder() .addAll(first.mteClasses()) .addAll(second.mteClasses()) .build(); return mMteClasses; } @Override public IGT_HatchAdder<? super T> adder() { return ((t, te, i) -> first.adder() .apply(t, te, i) || second.adder() .apply(t, te, i)); } @Override public String name() { if (name == null) name = first.name() + " or " + second.name(); return name; } @Override public long count(T t) { return first.count(t) + second.count(t); } } class HatchElement<T> implements IHatchElement<T> { private final List<Class<? extends IMetaTileEntity>> mClasses; private final IGT_HatchAdder<? super T> mAdder; private final String mName; private final IHatchElement<? super T> mBacking; private final ToLongFunction<? super T> mCount; public HatchElement(List<Class<? extends IMetaTileEntity>> aMteClasses, IGT_HatchAdder<? super T> aAdder, String aName, ToLongFunction<? super T> aCount, IHatchElement<? super T> aBacking) { this.mClasses = aMteClasses; this.mAdder = aAdder; this.mName = aName; this.mCount = aCount; this.mBacking = aBacking; } @Override public List<? extends Class<? extends IMetaTileEntity>> mteClasses() { return mClasses == null ? mBacking.mteClasses() : mClasses; } @Override public IGT_HatchAdder<? super T> adder() { return mAdder == null ? mBacking.adder() : mAdder; } @Override public String name() { return mName == null ? mBacking.name() : mName; } @Override public long count(T t) { return mCount == null ? mBacking.count(t) : mCount.applyAsLong(t); } @Override public <T2 extends T> IHatchElement<T2> withMteClasses(List<Class<? extends IMetaTileEntity>> aClasses) { if (aClasses == null) throw new IllegalArgumentException(); return new HatchElement<>(aClasses, mAdder, mName, mCount, mBacking); } @Override public <T2 extends T> IHatchElement<T2> withAdder(IGT_HatchAdder<T2> aAdder) { if (aAdder == null) throw new IllegalArgumentException(); return new HatchElement<>(mClasses, aAdder, mName, mCount, mBacking); } @Override public IHatchElement<T> withName(String aName) { if (aName == null) throw new IllegalArgumentException(); return new HatchElement<>(mClasses, mAdder, aName, mCount, mBacking); } @Override public <T2 extends T> IHatchElement<T2> withCount(ToLongFunction<T2> aCount) { if (aCount == null) throw new IllegalArgumentException(); return new HatchElement<>(mClasses, mAdder, mName, aCount, mBacking); } }