Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/improve-structure-errors' into dev
Browse files Browse the repository at this point in the history
# Conflicts:
#	src/main/resources/assets/gregtech/lang/en_US.lang
  • Loading branch information
Dream-Master committed Feb 3, 2025
2 parents 1c9c753 + 3c5cc24 commit b8cdc81
Show file tree
Hide file tree
Showing 6 changed files with 216 additions and 22 deletions.
14 changes: 14 additions & 0 deletions src/main/java/gregtech/api/enums/StructureError.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package gregtech.api.enums;

/**
* Used as a bit set for {@link gregtech.api.metatileentity.implementations.MTEMultiBlockBase#mStructureErrors}.
* You can reorder these as needed.
*/
public enum StructureError {
MISSING_MAINTENANCE,
MISSING_MUFFLER,
UNNEEDED_MUFFLER,
TOO_FEW_CASINGS,
MISSING_CRYO_HATCH,
TOO_MANY_CRYO_HATCHES;
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@
import java.time.Duration;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.BitSet;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
Expand Down Expand Up @@ -66,6 +68,7 @@
import cpw.mods.fml.relauncher.SideOnly;
import gregtech.GTMod;
import gregtech.api.enums.SoundResource;
import gregtech.api.enums.StructureError;
import gregtech.api.enums.VoidingMode;
import gregtech.api.gui.modularui.GTUIInfos;
import gregtech.api.gui.modularui.GTUITextures;
Expand Down Expand Up @@ -172,6 +175,9 @@ public abstract class MTEMultiBlockBase extends MetaTileEntity
private static final int CHECK_INTERVAL = 100; // How often should we check for a new recipe on an idle machine?
private final int randomTickOffset = (int) (Math.random() * CHECK_INTERVAL + 1);

/** A list of unparameterized structure errors. */
protected EnumSet<StructureError> mStructureErrors = EnumSet.noneOf(StructureError.class);

protected static final byte INTERRUPT_SOUND_INDEX = 8;
protected static final byte PROCESS_START_SOUND_INDEX = 1;

Expand Down Expand Up @@ -439,6 +445,7 @@ public void clearHatches() {
mMaintenanceHatches.clear();
mDualInputHatches.clear();
mSmartInputHatches.clear();
mStructureErrors = EnumSet.noneOf(StructureError.class);
}

public boolean checkStructure(boolean aForceReset) {
Expand All @@ -451,11 +458,40 @@ public boolean checkStructure(boolean aForceReset, IGregTechTileEntity aBaseMeta
if ((mStructureChanged || aForceReset)) {
clearHatches();
mMachine = checkMachine(aBaseMetaTileEntity, mInventory[1]);
// intentionally not predicated on checkMachine
validateStructure();
if (hasStructureErrors()) mMachine = false;
}
mStructureChanged = false;
return mMachine;
}

/**
* Validates this multi's structure (hatch/casing counts mainly) for any errors.
* Runs regardless of whether the structure is complete. Check or update {@link #mMachine} as needed.
* Should update {@link #mStructureErrors} as needed.
*/
protected void validateStructure() {

}

/**
* Scans {@link #mStructureErrors} or other fields as needed and emits localized structure error messages.
* mStructureErrors is synced already, but any newly introduced fields need to be synced manually.
*/
@SideOnly(Side.CLIENT)
protected void getStructureErrors(ArrayList<String> lines) {

}

/**
* Controls whether the error message widget is shown. If you have any new structure status fields, make sure to
* check them here.
*/
protected boolean hasStructureErrors() {
return !mStructureErrors.isEmpty();
}

/**
* Returns the error ID displayed on the GUI.
*/
Expand Down Expand Up @@ -2685,6 +2721,50 @@ protected String generateCurrentRecipeInfoString() {
protected void drawTexts(DynamicPositionedColumn screenElements, SlotWidget inventorySlot) {
screenElements.setSynced(false)
.setSpace(0);

screenElements.widget(
new FakeSyncWidget<EnumSet<StructureError>>(
() -> mStructureErrors,
status -> mStructureErrors = status,
(packetBuffer, structureErrors) -> {
BitSet bits = new BitSet();

for (StructureError error : structureErrors) {
bits.set(error.ordinal());
}

byte[] data = bits.toByteArray();

packetBuffer.writeVarIntToBuffer(data.length);
packetBuffer.writeBytes(data);
},
packetBuffer -> {
byte[] data = new byte[packetBuffer.readVarIntFromBuffer()];
packetBuffer.readBytes(data);

BitSet bits = BitSet.valueOf(data);

EnumSet<StructureError> out = EnumSet.noneOf(StructureError.class);

for (StructureError error : StructureError.values()) {
if (bits.get(error.ordinal())) {
out.add(error);
}
}

return out;
}));

screenElements.widgets(TextWidget.dynamicString(() -> {
ArrayList<String> lines = new ArrayList<>();
getStructureErrors(lines);
return String.join("\n", lines);
})
.setSynced(false)
.setTextAlignment(Alignment.CenterLeft)
.setDefaultColor(EnumChatFormatting.DARK_RED)
.setEnabled(w -> hasStructureErrors()));

if (supportsMachineModeSwitch()) {
screenElements.widget(
TextWidget
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import javax.annotation.Nullable;

import net.minecraft.block.Block;
import net.minecraft.client.resources.I18n;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
Expand All @@ -43,8 +44,11 @@
import com.gtnewhorizons.modularui.common.widget.FakeSyncWidget;
import com.gtnewhorizons.modularui.common.widget.TextWidget;

import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import gregtech.api.enums.GTValues;
import gregtech.api.enums.Materials;
import gregtech.api.enums.StructureError;
import gregtech.api.enums.Textures;
import gregtech.api.enums.VoidingMode;
import gregtech.api.gui.modularui.GTUITextures;
Expand Down Expand Up @@ -490,8 +494,42 @@ public void updateSlots() {
super.updateSlots();
}

@SideOnly(Side.CLIENT)
protected void getStructureErrors(ArrayList<String> lines) {
super.getStructureErrors(lines);

if (mStructureErrors.contains(StructureError.MISSING_MAINTENANCE)) {
lines.add(I18n.format("GT5U.gui.text.no_maintenance"));
}

if (mStructureErrors.contains(StructureError.MISSING_MUFFLER)) {
lines.add(I18n.format("GT5U.gui.text.no_muffler"));
}

if (mStructureErrors.contains(StructureError.UNNEEDED_MUFFLER)) {
lines.add(I18n.format("GT5U.gui.text.unneeded_muffler"));
}
}

@Override
protected void validateStructure() {
super.validateStructure();

if (mMaintenanceHatches.isEmpty()) {
mStructureErrors.add(StructureError.MISSING_MAINTENANCE);
}

if (this.getPollutionPerSecond(null) > 0 && mMufflerHatches.isEmpty()) {
mStructureErrors.add(StructureError.MISSING_MUFFLER);
}

if (this.getPollutionPerSecond(null) == 0 && !mMufflerHatches.isEmpty()) {
mStructureErrors.add(StructureError.UNNEEDED_MUFFLER);
}
}

public boolean checkHatch() {
return mMaintenanceHatches.size() <= 1 && (this.getPollutionPerSecond(null) <= 0 || !mMufflerHatches.isEmpty());
return true;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,24 @@
import java.util.ArrayList;
import java.util.Objects;

import net.minecraft.client.resources.I18n;
import net.minecraft.item.ItemStack;
import net.minecraftforge.fluids.FluidStack;

import com.gtnewhorizon.structurelib.alignment.constructable.ISurvivalConstructable;
import com.gtnewhorizon.structurelib.structure.IStructureDefinition;
import com.gtnewhorizon.structurelib.structure.ISurvivalBuildEnvironment;
import com.gtnewhorizon.structurelib.structure.StructureDefinition;
import com.gtnewhorizons.modularui.common.widget.DynamicPositionedColumn;
import com.gtnewhorizons.modularui.common.widget.FakeSyncWidget;
import com.gtnewhorizons.modularui.common.widget.SlotWidget;

import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import gregtech.api.GregTechAPI;
import gregtech.api.enums.MetaTileEntityIDs;
import gregtech.api.enums.SoundResource;
import gregtech.api.enums.StructureError;
import gregtech.api.enums.TAE;
import gregtech.api.interfaces.IIconContainer;
import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
Expand All @@ -40,6 +47,7 @@
import gtPlusPlus.api.recipe.GTPPRecipeMaps;
import gtPlusPlus.core.block.ModBlocks;
import gtPlusPlus.core.util.minecraft.FluidUtils;
import gtPlusPlus.xmod.gregtech.api.enums.GregtechItemList;
import gtPlusPlus.xmod.gregtech.api.metatileentity.implementations.base.GTPPMultiBlockBase;
import gtPlusPlus.xmod.gregtech.api.metatileentity.implementations.base.MTEHatchCustomFluidBase;
import gtPlusPlus.xmod.gregtech.common.blocks.textures.TexturesGtBlock;
Expand All @@ -48,30 +56,35 @@ public class MTEIndustrialVacuumFreezer extends GTPPMultiBlockBase<MTEIndustrial
implements ISurvivalConstructable {

public static int CASING_TEXTURE_ID;
public static String mCryoFuelName = "Gelid Cryotheum";
public static String mCasingName = "Advanced Cryogenic Casing";
public static String mHatchName = "Cryotheum Hatch";
public static FluidStack mFuelStack;
private int mCasing;
public static String CASING_NAME;
public static String HATCH_NAME;
public static FluidStack CRYO_STACK;
private static IStructureDefinition<MTEIndustrialVacuumFreezer> STRUCTURE_DEFINITION = null;

private int mCasing;

private final ArrayList<MTEHatchCustomFluidBase> mCryotheumHatches = new ArrayList<>();

public MTEIndustrialVacuumFreezer(final int aID, final String aName, final String aNameRegional) {
super(aID, aName, aNameRegional);
mFuelStack = FluidUtils.getFluidStack("cryotheum", 1);
CASING_TEXTURE_ID = TAE.getIndexFromPage(2, 10);

GregTechAPI.sAfterGTLoad.add(() -> {
CRYO_STACK = FluidUtils.getFluidStack("cryotheum", 1);
CASING_NAME = GregtechItemList.Casing_AdvancedVacuum.get(1)
.getDisplayName();
HATCH_NAME = GregtechItemList.Hatch_Input_Cryotheum.get(1)
.getDisplayName();
});
}

public MTEIndustrialVacuumFreezer(final String aName) {
super(aName);
mFuelStack = FluidUtils.getFluidStack("cryotheum", 1);
CASING_TEXTURE_ID = TAE.getIndexFromPage(2, 10);
protected MTEIndustrialVacuumFreezer(MTEIndustrialVacuumFreezer prototype) {
super(prototype.mName);
}

@Override
public IMetaTileEntity newMetaEntity(final IGregTechTileEntity aTileEntity) {
return new MTEIndustrialVacuumFreezer(this.mName);
return new MTEIndustrialVacuumFreezer(this);
}

@Override
Expand All @@ -85,20 +98,20 @@ protected MultiblockTooltipBuilder createTooltip() {
tt.addMachineType(getMachineType())
.addInfo("Factory Grade Advanced Vacuum Freezer")
.addInfo("Speed: +100% | EU Usage: 100% | Parallel: 4")
.addInfo("Consumes 10L of " + mCryoFuelName + "/s during operation")
.addInfo("Consumes 10L of " + CRYO_STACK.getLocalizedName() + "/s during operation")
.addInfo("Constructed exactly the same as a normal Vacuum Freezer")
.addPollutionAmount(getPollutionPerSecond(null))
.beginStructureBlock(3, 3, 3, true)
.addController("Front Center")
.addCasingInfoMin(mCasingName, 10, false)
.addCasingInfoMin(CASING_NAME, 10, false)
.addInputBus("Any Casing", 1)
.addOutputBus("Any Casing", 1)
.addInputHatch("Any Casing", 1)
.addOutputHatch("Any Casing", 1)
.addEnergyHatch("Any Casing", 1)
.addMufflerHatch("Any Casing", 1)
.addMaintenanceHatch("Any Casing", 1)
.addOtherStructurePart(mHatchName, "Any Casing", 1)
.addOtherStructurePart(HATCH_NAME, "Any Casing", 1)
.toolTipFinisher();
return tt;
}
Expand All @@ -116,8 +129,7 @@ public IStructureDefinition<MTEIndustrialVacuumFreezer> getStructureDefinition()
ofChain(
buildHatchAdder(MTEIndustrialVacuumFreezer.class)
.adder(MTEIndustrialVacuumFreezer::addCryotheumHatch)
.hatchId(967)
.shouldReject(t -> !t.mCryotheumHatches.isEmpty())
.hatchId(MetaTileEntityIDs.Hatch_Input_Cryotheum.ID)
.casingIndex(CASING_TEXTURE_ID)
.dot(1)
.build(),
Expand All @@ -144,15 +156,57 @@ public int survivalConstruct(ItemStack stackSize, int elementBudget, ISurvivalBu
}

@Override
public boolean checkMachine(IGregTechTileEntity aBaseMetaTileEntity, ItemStack aStack) {
public void clearHatches() {
super.clearHatches();
mCasing = 0;
mCryotheumHatches.clear();
return checkPiece(mName, 1, 1, 0) && mCasing >= 10 && checkHatch();
}

@Override
public boolean checkHatch() {
return super.checkHatch() && !mCryotheumHatches.isEmpty();
public boolean checkMachine(IGregTechTileEntity aBaseMetaTileEntity, ItemStack aStack) {
return checkPiece(mName, 1, 1, 0);
}

@Override
public void validateStructure() {
super.validateStructure();

if (mCasing < 10) {
mStructureErrors.add(StructureError.TOO_FEW_CASINGS);
}

if (mCryotheumHatches.isEmpty()) {
mStructureErrors.add(StructureError.MISSING_CRYO_HATCH);
}

if (mCryotheumHatches.size() > 1) {
mStructureErrors.add(StructureError.TOO_MANY_CRYO_HATCHES);
}
}

@Override
protected void drawTexts(DynamicPositionedColumn screenElements, SlotWidget inventorySlot) {
super.drawTexts(screenElements, inventorySlot);

screenElements.widgets(new FakeSyncWidget.IntegerSyncer(() -> mCasing, casings -> mCasing = casings));
}

@Override
@SideOnly(Side.CLIENT)
protected void getStructureErrors(ArrayList<String> lines) {
super.getStructureErrors(lines);

if (mStructureErrors.contains(StructureError.TOO_FEW_CASINGS)) {
lines.add(I18n.format("GT5U.gui.missing_casings", 10, mCasing));
}

if (mStructureErrors.contains(StructureError.MISSING_CRYO_HATCH)) {
lines.add(I18n.format("GT5U.gui.missing_hatch", HATCH_NAME));
}

if (mStructureErrors.contains(StructureError.TOO_MANY_CRYO_HATCHES)) {
lines.add(I18n.format("GT5U.gui.too_many_hatches", HATCH_NAME, 1));
}
}

private boolean addCryotheumHatch(IGregTechTileEntity aTileEntity, int aBaseCasingIndex) {
Expand All @@ -161,7 +215,7 @@ private boolean addCryotheumHatch(IGregTechTileEntity aTileEntity, int aBaseCasi
} else {
IMetaTileEntity aMetaTileEntity = aTileEntity.getMetaTileEntity();
if (aMetaTileEntity instanceof MTEHatchCustomFluidBase && aMetaTileEntity.getBaseMetaTileEntity()
.getMetaTileID() == 967) {
.getMetaTileID() == MetaTileEntityIDs.Hatch_Input_Cryotheum.ID) {
return addToMachineListInternal(mCryotheumHatches, aTileEntity, aBaseCasingIndex);
}
}
Expand Down
Loading

0 comments on commit b8cdc81

Please sign in to comment.