aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/MTEHatchMufflerAdvanced.java
blob: 40e804bf362a6a0c88e695a37205935a2ca52523 (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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
package gtPlusPlus.xmod.gregtech.api.metatileentity.implementations;

import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumChatFormatting;
import net.minecraft.world.World;
import net.minecraftforge.common.util.ForgeDirection;

import com.gtnewhorizons.modularui.api.screen.ModularWindow;
import com.gtnewhorizons.modularui.api.screen.UIBuildContext;
import com.gtnewhorizons.modularui.common.widget.SlotWidget;

import gregtech.GTMod;
import gregtech.api.gui.modularui.GTUIInfos;
import gregtech.api.gui.modularui.GUITextureSet;
import gregtech.api.interfaces.ITexture;
import gregtech.api.interfaces.modularui.IAddGregtechLogo;
import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
import gregtech.api.metatileentity.MetaTileEntity;
import gregtech.api.metatileentity.implementations.MTEHatchMuffler;
import gregtech.api.metatileentity.implementations.MTEMultiBlockBase;
import gregtech.api.objects.GTRenderedTexture;
import gregtech.common.pollution.Pollution;
import gtPlusPlus.core.item.general.ItemAirFilter;
import gtPlusPlus.core.lib.GTPPCore;
import gtPlusPlus.xmod.gregtech.api.gui.GTPPUITextures;
import gtPlusPlus.xmod.gregtech.common.blocks.textures.TexturesGtBlock;

public class MTEHatchMufflerAdvanced extends MTEHatchMuffler implements IAddGregtechLogo {

    protected int SLOT_FILTER = 0;

    public MTEHatchMufflerAdvanced(int aID, String aName, String aNameRegional, int aTier) {
        super(aID, aName, aNameRegional, aTier, 1, new String[] { "" });
    }

    public MTEHatchMufflerAdvanced(String aName, int aTier, String[] aDescription, ITexture[][][] aTextures) {
        super(aName, aTier, 1, aDescription, aTextures);
    }

    final String[] mDescription = new String[] { "Outputs pollution from a multiblock", "DO NOT OBSTRUCT THE OUTPUT!",
        "Requires 3 Air Blocks in front of the exhaust face",
        mTier < 5 ? "Requires an Air Filter"
            : "Requires an Air Filter " + EnumChatFormatting.WHITE + "[Tier 2]" + EnumChatFormatting.GRAY,
        "Can take Air Filters from an input bus of the multiblock",
        "Reduces Pollution to " + calculatePollutionReduction(100, true) + "%",
        "Recovers " + (100 - calculatePollutionReduction(100, true)) + "% of CO2/CO/SO2", GTPPCore.GT_Tooltip.get() };

    @Override
    public String[] getDescription() {
        return mDescription;
    }

    @Override
    public ITexture[] getTexturesActive(ITexture aBaseTexture) {
        return new ITexture[] { aBaseTexture, new GTRenderedTexture(TexturesGtBlock.Overlay_Hatch_Muffler_Adv) };
    }

    @Override
    public ITexture[] getTexturesInactive(ITexture aBaseTexture) {
        return new ITexture[] { aBaseTexture, new GTRenderedTexture(TexturesGtBlock.Overlay_Hatch_Muffler_Adv) };
    }

    @Override
    public boolean isValidSlot(int aIndex) {
        return aIndex == SLOT_FILTER;
    }

    @Override
    public boolean allowPutStack(IGregTechTileEntity aBaseMetaTileEntity, int aIndex, ForgeDirection side,
        ItemStack aStack) {
        return (aIndex == this.SLOT_FILTER && isAirFilter(aStack));
    }

    @Override
    public MetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
        return new MTEHatchMufflerAdvanced(this.mName, this.mTier, mDescriptionArray, this.mTextures);
    }

    @Override
    public boolean onRightclick(IGregTechTileEntity aBaseMetaTileEntity, EntityPlayer aPlayer) {
        GTUIInfos.openGTTileEntityUI(aBaseMetaTileEntity, aPlayer);
        return true;
    }

    @Override
    public boolean polluteEnvironment(MetaTileEntity parentTileEntity, int pollutionAmount) {
        if (!airCheck()) return false; // Muffler obstructed.
        if (pollutionAmount < 10000 && pollutionAmount <= parentTileEntity.getBaseMetaTileEntity()
            .getRandomNumber(10000)) {
            // If we are venting less than the maximum amount of pollution, damage filter with a lower chance.
            // This happens if a multiblock has more than one muffler.
            pollutionAmount = calculatePollutionReduction(pollutionAmount, true);
        } else if (damageAirFilter(parentTileEntity)) {
            // damageAirFilter already checks that we have a valid filter.
            pollutionAmount = calculatePollutionReduction(pollutionAmount, true);
        } else {
            // Revert to reduction of the basic muffler.
            pollutionAmount = super.calculatePollutionReduction(pollutionAmount);
        }
        Pollution.addPollution(getBaseMetaTileEntity(), pollutionAmount);
        return true;
    }

    @Override
    public int calculatePollutionReduction(int aPollution) {
        // This is called by EBF to calculate exhaust gas amounts, we need to check the filter.
        return calculatePollutionReduction(aPollution, false);
    }

    /**
     * Calculates pollution reduction.
     *
     * @param aPollution   Amount of pollution to be reduced.
     * @param ignoreFilter If this is true, assumes that a valid filter is present without checking (for example, to
     *                     build tooltips).
     * @return Amount of pollution after reduction.
     */
    protected int calculatePollutionReduction(int aPollution, boolean ignoreFilter) {
        if (!ignoreFilter && !hasAirFilter()) {
            // Without a filter, downgrade to basic muffler reduction.
            return super.calculatePollutionReduction(aPollution);
        }

        // Special case to be always better than a basic muffler.
        if (mTier < 2) return (int) (aPollution * 0.95);
        if (mTier > 8) return 0;

        return (int) (aPollution * Math.pow(0.64D, mTier - 1));
    }

    /**
     *
     * @return True if enough blocks in front of the muffler are air.
     */
    private boolean airCheck() {
        IGregTechTileEntity bmte = getBaseMetaTileEntity();
        ForgeDirection facing = bmte.getFrontFacing();
        return bmte.getAirAtSide(facing) && bmte.getAirAtSideAndDistance(facing, 1)
            && bmte.getAirAtSideAndDistance(facing, 2);
    }

    /**
     * Try to damage an air filter. Will first try to find a valid filter in the hatch's own inventory, then in the
     * input buses of the parent multiblock. If the filter is destroyed, will try to replace it from the parent
     * multiblock's input buses again.
     *
     * @param parentTileEntity Which multiblock this hatch is a part of. If this is null, only checks inventory of the
     *                         muffler.
     * @return True if the filter has been successfully damaged.
     */
    private boolean damageAirFilter(MetaTileEntity parentTileEntity) {
        if (!findAirFilter(parentTileEntity)) return false; // No filter available.

        ItemStack filter = mInventory[SLOT_FILTER];
        if (filter == null) return false; // This should never happen if findAirFilter() above succeeded.

        long currentDamage = ItemAirFilter.getFilterDamage(filter);
        if (currentDamage < ItemAirFilter.getFilterMaxDamage(filter) - 1) {
            // Damage filter by one step.
            ItemAirFilter.setFilterDamage(filter, currentDamage + 1);
            return true;
        } else {
            // Destroy the filter.
            mInventory[SLOT_FILTER] = null;

            // Try to find a new one.
            findAirFilter(parentTileEntity);

            // Regardless of whether we have a new filter or not, *this* operation succeeded.
            return true;
        }
    }

    /**
     * Try to find a valid air filter in the input buses of the parent multiblock.
     *
     * @param parentTileEntity Which multiblock this hatch is a part of. If this is null, only checks inventory of the
     *                         muffler.
     * @return True if the inventory of the muffler already contains an air filter, or if one was retrieved from the
     *         parent multiblock.
     */
    private boolean findAirFilter(MetaTileEntity parentTileEntity) {
        if (hasAirFilter()) return true; // Has a filter in inventory.
        if (mInventory[SLOT_FILTER] != null) return false; // Has a non-filter item in inventory.
        if (parentTileEntity == null) return false; // Unknown parent multiblock.

        if (parentTileEntity instanceof MTEMultiBlockBase GTMultiBase) {
            for (var inputBus : GTMultiBase.mInputBusses) {
                for (ItemStack stack : inputBus.mInventory) {
                    if (isAirFilter(stack)) {
                        ItemStack stackCopy = stack.copy();
                        if (GTMultiBase.depleteInput(stack)) {
                            mInventory[SLOT_FILTER] = stackCopy;
                            return true;
                        }
                    }
                }
            }
        }

        return false;
    }

    /**
     *
     * @return True if the item currently in the inventory is an air filter valid for this tier of muffler hatch.
     */
    private boolean hasAirFilter() {
        return isAirFilter(mInventory[SLOT_FILTER]);
    }

    /**
     *
     * @param filter
     * @return True if the argument is an air filter valid for this tier of muffler hatch.
     */
    public boolean isAirFilter(ItemStack filter) {
        if (filter == null) return false;
        if (filter.getItem() instanceof ItemAirFilter) {
            if (mTier < 5) {
                // Accept any filter.
                return true;
            } else {
                // Accept only T2 filter.
                return filter.getItemDamage() == 1;
            }
        }
        return false;
    }

    @Override
    public void onPostTick(IGregTechTileEntity aBaseMetaTileEntity, long aTick) {
        super.onPostTick(aBaseMetaTileEntity, aTick);

        if (aBaseMetaTileEntity.isClientSide()) {
            if (this.getBaseMetaTileEntity()
                .isActive()) {
                String aParticleName;
                if ((aTick % 2) == 0) {
                    aParticleName = "cloud";
                } else {
                    aParticleName = "smoke";
                }
                this.pollutionParticles(
                    this.getBaseMetaTileEntity()
                        .getWorld(),
                    aParticleName);
            }
        }
    }

    @Override
    public void pollutionParticles(World aWorld, String name) {
        float ran1 = GTPPCore.RANDOM.nextFloat();
        float ran2 = 0.0F;
        float ran3 = 0.0F;
        boolean chk1 = ran1 * 100.0F < (float) this.calculatePollutionReduction(100);
        boolean chk2;
        boolean chk3;
        int aPollutionAmount = Pollution.getPollution(getBaseMetaTileEntity());
        if (aPollutionAmount >= GTMod.gregtechproxy.mPollutionSmogLimit) {
            ran2 = GTPPCore.RANDOM.nextFloat();
            ran3 = GTPPCore.RANDOM.nextFloat();
            chk2 = ran2 * 100.0F < (float) this.calculatePollutionReduction(100);
            chk3 = ran3 * 100.0F < (float) this.calculatePollutionReduction(100);
            if (!chk1 && !chk2 && !chk3) {
                return;
            }
        } else {
            if (!chk1) {
                return;
            }

            chk3 = false;
            chk2 = false;
        }

        IGregTechTileEntity aMuffler = this.getBaseMetaTileEntity();
        ForgeDirection aDir = aMuffler.getFrontFacing();
        float xPos = (float) aDir.offsetX * 0.76F + (float) aMuffler.getXCoord() + 0.25F;
        float yPos = (float) aDir.offsetY * 0.76F + (float) aMuffler.getYCoord() + 0.25F;
        float zPos = (float) aDir.offsetZ * 0.76F + (float) aMuffler.getZCoord() + 0.25F;
        float ySpd = (float) aDir.offsetY * 0.1F + 0.2F + 0.1F * GTPPCore.RANDOM.nextFloat();
        float xSpd;
        float zSpd;
        if (aDir.offsetY == -1) {
            float temp = GTPPCore.RANDOM.nextFloat() * 2.0F * GTPPCore.PI;
            xSpd = (float) Math.sin(temp) * 0.1F;
            zSpd = (float) Math.cos(temp) * 0.1F;
        } else {
            xSpd = (float) aDir.offsetX * (0.1F + 0.2F * GTPPCore.RANDOM.nextFloat());
            zSpd = (float) aDir.offsetZ * (0.1F + 0.2F * GTPPCore.RANDOM.nextFloat());
        }

        if (chk1) {
            aWorld.spawnParticle(
                name,
                xPos + ran1 * 0.5F,
                yPos + GTPPCore.RANDOM.nextFloat() * 0.5F,
                zPos + GTPPCore.RANDOM.nextFloat() * 0.5F,
                xSpd,
                ySpd,
                zSpd);
        }

        if (chk2) {
            aWorld.spawnParticle(
                name,
                xPos + ran2 * 0.5F,
                yPos + GTPPCore.RANDOM.nextFloat() * 0.5F,
                zPos + GTPPCore.RANDOM.nextFloat() * 0.5F,
                xSpd,
                ySpd,
                zSpd);
        }

        if (chk3) {
            aWorld.spawnParticle(
                name,
                xPos + ran3 * 0.5F,
                yPos + GTPPCore.RANDOM.nextFloat() * 0.5F,
                zPos + GTPPCore.RANDOM.nextFloat() * 0.5F,
                xSpd,
                ySpd,
                zSpd);
        }
    }

    @Override
    public void addGregTechLogo(ModularWindow.Builder builder) {}

    @Override
    public GUITextureSet getGUITextureSet() {
        return new GUITextureSet().setMainBackground(GTPPUITextures.BACKGROUND_YELLOW)
            .setItemSlot(GTPPUITextures.SLOT_ITEM_YELLOW)
            .setTitleTab(
                GTPPUITextures.TAB_TITLE_YELLOW,
                GTPPUITextures.TAB_TITLE_DARK_YELLOW,
                GTPPUITextures.TAB_TITLE_ANGULAR_YELLOW);
    }

    @Override
    public void addUIWidgets(ModularWindow.Builder builder, UIBuildContext buildContext) {
        builder.widget(
            new SlotWidget(inventoryHandler, 0).setFilter(stack -> stack.getItem() instanceof ItemAirFilter)
                .setBackground(getGUITextureSet().getItemSlot())
                .setPos(79, 34));
    }
}