Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve structure error feedback #3884

Open
wants to merge 24 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
37023cd
Improve structure error feedback
RecursivePineapple Feb 3, 2025
a2df4ac
Merge branch 'master' (early part) into improve-structure-errors
RecursivePineapple Feb 3, 2025
1f88b67
Merge branch 'master' into improve-structure-errors
Dream-Master Feb 3, 2025
3c5cc24
Rename status field & use error method for mMachine
RecursivePineapple Feb 3, 2025
53a8a02
Respect shouldCheckMaintenance for maint. hatches
RecursivePineapple Feb 4, 2025
7adcaab
Add steam hatch check for steam multi
RecursivePineapple Feb 4, 2025
bf0876f
Merge branch 'master' into improve-structure-errors
RecursivePineapple Feb 4, 2025
42723b8
Merge branch 'master' into improve-structure-errors
Dream-Master Feb 4, 2025
6824c91
Merge branch 'master' into improve-structure-errors
Dream-Master Feb 5, 2025
48100f9
Merge branch 'master' into improve-structure-errors
Dream-Master Feb 5, 2025
a4e22ba
Merge branch 'master' into improve-structure-errors
Dream-Master Feb 5, 2025
ea5dd6c
Merge branch 'master' into improve-structure-errors
Dream-Master Feb 7, 2025
c1fa56d
Merge branch 'master' into improve-structure-errors
Dream-Master Feb 7, 2025
c3d01c3
Made error field private & added synced NBT param
RecursivePineapple Feb 7, 2025
2e58f63
Merge branch 'master' into improve-structure-errors
RecursivePineapple Feb 7, 2025
51e9711
Merge branch 'master' into improve-structure-errors
serenibyss Feb 7, 2025
15dc427
Merge branch 'master' into improve-structure-errors
Dream-Master Feb 10, 2025
a1911d1
Merge branch 'master' into improve-structure-errors
Dream-Master Feb 11, 2025
9dbe1f1
Merge branch 'master' into improve-structure-errors
Dream-Master Feb 12, 2025
47bca43
Changes from review comments
RecursivePineapple Feb 12, 2025
8f1fa74
Merge branch 'master' into improve-structure-errors
Dream-Master Feb 12, 2025
693f72a
Merge branch 'master' into improve-structure-errors
Dream-Master Feb 13, 2025
2fc3186
Merge branch 'master' into improve-structure-errors
Dream-Master Feb 14, 2025
953cc13
Merge branch 'master' into improve-structure-errors
Dream-Master Feb 14, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions src/main/java/gregtech/api/enums/StructureError.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
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,
MISSING_STEAM_HATCH;
}
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)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SideOnly usages should be restricted where it would cause crash if not present. It can be removed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I prefer to use I18n.format for i18n, and I18n is client-only. It doesn't make sense to run this on the server either, since it relies on the user's language. We could just use the server's lang, but I don't think that's a good idea.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't mean to make it available on server, what I meant is you can just remove this annotation. @SideOnly is for stripping the member on runtime, not for marking "Don't use this on server." If the intention is to ensure that it won't get called on server, Java compiler cannot understand this and lets anyone to access it on server side, causing NoSuchMethodError on runtime. If any, adding Javadoc saying "Don't use this on server" is enough.

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 @@ -2671,6 +2707,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;
RecursivePineapple marked this conversation as resolved.
Show resolved Hide resolved
}));

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 (shouldCheckMaintenance() && 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 @@ -12,14 +12,18 @@
import java.util.Collections;
import java.util.List;

import net.minecraft.client.resources.I18n;
import net.minecraft.inventory.IInventory;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.StatCollector;
import net.minecraftforge.common.util.ForgeDirection;
import net.minecraftforge.fluids.FluidStack;

import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import gregtech.GTMod;
import gregtech.api.enums.StructureError;
import gregtech.api.enums.Textures;
import gregtech.api.interfaces.IHatchElement;
import gregtech.api.interfaces.ITexture;
Expand All @@ -36,6 +40,7 @@
import gregtech.api.util.IGTHatchAdder;
import gregtech.api.util.shutdown.ShutDownReasonRegistry;
import gtPlusPlus.core.util.minecraft.FluidUtils;
import gtPlusPlus.xmod.gregtech.api.enums.GregtechItemList;
import gtPlusPlus.xmod.gregtech.api.metatileentity.implementations.MTEHatchSteamBusInput;
import gtPlusPlus.xmod.gregtech.api.metatileentity.implementations.MTEHatchSteamBusOutput;
import mcp.mobius.waila.api.IWailaConfigHandler;
Expand Down Expand Up @@ -351,6 +356,29 @@ public void clearHatches() {
mSteamOutputs.clear();
}

@Override
protected void validateStructure() {
// don't call super method

if (mSteamInputFluids.isEmpty()) {
mStructureErrors.add(StructureError.MISSING_STEAM_HATCH);
}
}

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

if (mStructureErrors.contains(StructureError.MISSING_STEAM_HATCH)) {
lines.add(
I18n.format(
"GT5U.gui.missing_hatch",
GregtechItemList.Hatch_Input_Steam.get(1)
.getDisplayName()));
}
}

@Override
public boolean resetRecipeMapForAllInputHatches(RecipeMap<?> aMap) {
boolean ret = super.resetRecipeMapForAllInputHatches(aMap);
Expand Down
Loading