aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/gregtech/api/metatileentity/implementations/MTECubicMultiBlockBase.java
blob: c8b0c8ce3f0d79b949bfd9826595dc47bd028a10 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
package gregtech.api.metatileentity.implementations;

import static com.gtnewhorizon.structurelib.structure.StructureUtility.lazy;
import static com.gtnewhorizon.structurelib.structure.StructureUtility.ofChain;
import static com.gtnewhorizon.structurelib.structure.StructureUtility.onElementPass;
import static com.gtnewhorizon.structurelib.structure.StructureUtility.transpose;
import static gregtech.api.enums.HatchElement.Energy;
import static gregtech.api.enums.HatchElement.InputBus;
import static gregtech.api.enums.HatchElement.InputHatch;
import static gregtech.api.enums.HatchElement.Maintenance;
import static gregtech.api.enums.HatchElement.Muffler;
import static gregtech.api.enums.HatchElement.OutputBus;
import static gregtech.api.enums.HatchElement.OutputHatch;

import java.util.List;

import net.minecraft.item.ItemStack;

import com.google.common.collect.ImmutableList;
import com.gtnewhorizon.structurelib.alignment.constructable.ISurvivalConstructable;
import com.gtnewhorizon.structurelib.structure.IStructureDefinition;
import com.gtnewhorizon.structurelib.structure.IStructureElement;
import com.gtnewhorizon.structurelib.structure.ISurvivalBuildEnvironment;
import com.gtnewhorizon.structurelib.structure.StructureDefinition;

import gregtech.api.interfaces.IHatchElement;
import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
import gregtech.api.util.GTStructureUtility;

/**
 * A simple 3x3x3 hollow cubic multiblock, that can be arbitrarily rotated, made of a single type of machine casing and
 * accepts hatches everywhere. Controller will be placed in front center of the structure.
 * <p>
 * Note: You cannot use different casing for the same Class. Make a new subclass for it. You also should not change the
 * casing dynamically, i.e. it should be a dumb method returning some sort of constant.
 * <p>
 * Implementation tips: 1. To restrict hatches, override {@link #addDynamoToMachineList(IGregTechTileEntity, int)} and
 * its cousins instead of overriding the whole {@link #getStructureDefinition()} or change
 * {@link #checkHatches(IGregTechTileEntity, ItemStack)}. The former is a total overkill, while the later cannot stop
 * the structure check early. 2. To limit rotation, override {@link #getInitialAlignmentLimits()}
 *
 * @param <T>
 */
public abstract class MTECubicMultiBlockBase<T extends MTECubicMultiBlockBase<T>> extends MTEEnhancedMultiBlockBase<T>
    implements ISurvivalConstructable {

    protected static final String STRUCTURE_PIECE_MAIN = "main";
    protected static final ClassValue<IStructureDefinition<MTECubicMultiBlockBase<?>>> STRUCTURE_DEFINITION = new ClassValue<>() {

        @Override
        protected IStructureDefinition<MTECubicMultiBlockBase<?>> computeValue(Class<?> type) {
            return StructureDefinition.<MTECubicMultiBlockBase<?>>builder()
                .addShape(
                    STRUCTURE_PIECE_MAIN,
                    transpose(
                        new String[][] { { "hhh", "hhh", "hhh" }, { "h~h", "h-h", "hhh" }, { "hhh", "hhh", "hhh" }, }))
                .addElement(
                    'h',
                    ofChain(
                        lazy(
                            t -> GTStructureUtility.<MTECubicMultiBlockBase<?>>buildHatchAdder()
                                .atLeastList(t.getAllowedHatches())
                                .casingIndex(t.getHatchTextureIndex())
                                .dot(1)
                                .build()),
                        onElementPass(
                            MTECubicMultiBlockBase::onCorrectCasingAdded,
                            lazy(MTECubicMultiBlockBase::getCasingElement))))
                .build();
        }
    };
    private int mCasingAmount = 0;

    protected MTECubicMultiBlockBase(int aID, String aName, String aNameRegional) {
        super(aID, aName, aNameRegional);
    }

    protected MTECubicMultiBlockBase(String aName) {
        super(aName);
    }

    /**
     * Create a simple 3x3x3 hollow cubic structure made of a single type of machine casing and accepts hatches
     * everywhere.
     * <p>
     * The created definition contains a single piece named {@link #STRUCTURE_PIECE_MAIN}.
     */
    @Override
    @SuppressWarnings("unchecked")
    public IStructureDefinition<T> getStructureDefinition() {
        return (IStructureDefinition<T>) STRUCTURE_DEFINITION.get(getClass());
    }

    @Override
    public void construct(ItemStack aStack, boolean aHintsOnly) {
        buildPiece(STRUCTURE_PIECE_MAIN, aStack, aHintsOnly, 1, 1, 0);
    }

    @Override
    public int survivalConstruct(ItemStack stackSize, int elementBudget, ISurvivalBuildEnvironment env) {
        if (mMachine) return -1;
        return survivialBuildPiece(STRUCTURE_PIECE_MAIN, stackSize, 1, 1, 0, elementBudget, env, false, true);
    }

    @Override
    public boolean checkMachine(IGregTechTileEntity aBaseMetaTileEntity, ItemStack aStack) {
        mCasingAmount = 0;
        return checkPiece(STRUCTURE_PIECE_MAIN, 1, 1, 0) && mCasingAmount >= getRequiredCasingCount()
            && checkHatches(aBaseMetaTileEntity, aStack);
    }

    /**
     * Called by {@link #checkMachine(IGregTechTileEntity, ItemStack)} to check if all required hatches are present.
     * <p>
     * Default implementation requires EXACTLY ONE maintenance hatch to be present, and ignore all other conditions.
     *
     * @param aBaseMetaTileEntity the tile entity of self
     * @param aStack              The item stack inside the controller
     * @return true if the test passes, false otherwise
     */
    protected boolean checkHatches(IGregTechTileEntity aBaseMetaTileEntity, ItemStack aStack) {
        return mMaintenanceHatches.size() == 1;
    }

    protected abstract IStructureElement<MTECubicMultiBlockBase<?>> getCasingElement();

    protected List<IHatchElement<? super MTECubicMultiBlockBase<?>>> getAllowedHatches() {
        return ImmutableList.of(InputHatch, OutputHatch, InputBus, OutputBus, Muffler, Maintenance, Energy);
    }

    /**
     * The hatch's texture index.
     */
    protected abstract int getHatchTextureIndex();

    protected abstract int getRequiredCasingCount();

    protected void onCorrectCasingAdded() {
        mCasingAmount++;
    }
}