diff --git a/src/main/java/gregtech/GregTechMod.java b/src/main/java/gregtech/GregTechMod.java
index 1942c3a0c9f..3d9cbeabd6c 100644
--- a/src/main/java/gregtech/GregTechMod.java
+++ b/src/main/java/gregtech/GregTechMod.java
@@ -3,9 +3,7 @@
import gregtech.api.GTValues;
import gregtech.api.GregTechAPI;
import gregtech.api.modules.ModuleContainerRegistryEvent;
-import gregtech.api.util.oreglob.OreGlob;
import gregtech.client.utils.BloomEffectUtil;
-import gregtech.common.covers.filter.oreglob.impl.OreGlobParser;
import gregtech.modules.GregTechModules;
import gregtech.modules.ModuleManager;
@@ -15,7 +13,17 @@
import net.minecraftforge.fml.common.Loader;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.Mod.EventHandler;
-import net.minecraftforge.fml.common.event.*;
+import net.minecraftforge.fml.common.event.FMLConstructionEvent;
+import net.minecraftforge.fml.common.event.FMLInitializationEvent;
+import net.minecraftforge.fml.common.event.FMLInterModComms;
+import net.minecraftforge.fml.common.event.FMLLoadCompleteEvent;
+import net.minecraftforge.fml.common.event.FMLPostInitializationEvent;
+import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
+import net.minecraftforge.fml.common.event.FMLServerAboutToStartEvent;
+import net.minecraftforge.fml.common.event.FMLServerStartedEvent;
+import net.minecraftforge.fml.common.event.FMLServerStartingEvent;
+import net.minecraftforge.fml.common.event.FMLServerStoppedEvent;
+import net.minecraftforge.fml.common.event.FMLServerStoppingEvent;
@Mod(modid = GTValues.MODID,
name = "GregTech",
@@ -43,7 +51,6 @@ public GregTechMod() {
public void onConstruction(FMLConstructionEvent event) {
moduleManager = ModuleManager.getInstance();
GregTechAPI.moduleManager = moduleManager;
- OreGlob.setCompiler(input -> new OreGlobParser(input).compile());
moduleManager.registerContainer(new GregTechModules());
MinecraftForge.EVENT_BUS.post(new ModuleContainerRegistryEvent());
moduleManager.setup(event.getASMHarvestedData(), Loader.instance().getConfigDir());
diff --git a/src/main/java/gregtech/api/gui/GuiTextures.java b/src/main/java/gregtech/api/gui/GuiTextures.java
index 20936a052b2..e2a19ec6dcb 100644
--- a/src/main/java/gregtech/api/gui/GuiTextures.java
+++ b/src/main/java/gregtech/api/gui/GuiTextures.java
@@ -435,6 +435,10 @@ public class GuiTextures {
.fullImage("textures/items/metaitems/cover.controller.png");
// Ore Filter
+ public static final TextureArea ORE_FILTER_BUTTON_CASE_SENSITIVE = TextureArea
+ .fullImage("textures/gui/widget/ore_filter/button_case_sensitive.png");
+ public static final TextureArea ORE_FILTER_BUTTON_MATCH_ALL = TextureArea
+ .fullImage("textures/gui/widget/ore_filter/button_match_all.png");
public static final TextureArea ORE_FILTER_INFO = TextureArea.fullImage("textures/gui/widget/ore_filter/info.png");
public static final TextureArea ORE_FILTER_SUCCESS = TextureArea
.fullImage("textures/gui/widget/ore_filter/success.png");
diff --git a/src/main/java/gregtech/api/util/oreglob/OreGlob.java b/src/main/java/gregtech/api/util/oreglob/OreGlob.java
index 072e4959eeb..a560fcae1bf 100644
--- a/src/main/java/gregtech/api/util/oreglob/OreGlob.java
+++ b/src/main/java/gregtech/api/util/oreglob/OreGlob.java
@@ -7,21 +7,19 @@
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
+import java.util.Collection;
import java.util.List;
-import java.util.Set;
-import java.util.function.Function;
/**
* Glob-like string matcher language designed for ore dictionary matching.
*
- * An OreGlob instance provides two functions: the ability to match strings,
- * and the ability to translate expression structure into user-friendly text
- * explanations. The text can be either a plaintext, or a text formatted by standard
+ * An OreGlob instance provides two functions: the ability to match strings, and the ability to translate expression
+ * structure into user-friendly text explanations. The text can be either a plaintext, or a text formatted by standard
* Minecraft text format.
*/
public abstract class OreGlob {
- private static Function compiler;
+ private static OreGlobCompiler compiler;
/**
* Tries to compile the string expression into OreGlob instance.
@@ -29,15 +27,31 @@ public abstract class OreGlob {
* @param expression OreGlob expression
* @return Compilation result
* @throws IllegalStateException If compiler is not provided yet
+ * @deprecated use {@link #compile(String, boolean)}
*/
@NotNull
+ @Deprecated
+ @ApiStatus.ScheduledForRemoval(inVersion = "2.9")
public static OreGlobCompileResult compile(@NotNull String expression) {
+ return compile(expression, true);
+ }
+
+ /**
+ * Tries to compile the string expression into OreGlob instance.
+ *
+ * @param expression OreGlob expression
+ * @param ignoreCase Whether the resulting OreGlob instance should do case-insensitive matches
+ * @return Compilation result
+ * @throws IllegalStateException If compiler is not provided yet
+ */
+ @NotNull
+ public static OreGlobCompileResult compile(@NotNull String expression, boolean ignoreCase) {
if (compiler == null) throw new IllegalStateException("Compiler unavailable");
- return compiler.apply(expression);
+ return compiler.compile(expression, ignoreCase);
}
@ApiStatus.Internal
- public static void setCompiler(@NotNull Function compiler) {
+ public static void setCompiler(@NotNull OreGlobCompiler compiler) {
OreGlob.compiler = compiler;
}
@@ -60,30 +74,97 @@ public static void setCompiler(@NotNull Function c
public abstract boolean matches(@NotNull String input);
/**
- * Tries to match each ore dictionary entries associated with given item.
- * If any of them matches, {@code true} is returned.
*
- * For items not associated with any ore dictionary entries, this method returns
- * {@code true} if this instance matches empty string instead.
+ * Tries to match each ore dictionary entries associated with given item. If any of them matches, {@code true} is
+ * returned.
+ *
+ *
+ * For items not associated with any ore dictionary entries, this method returns {@code true} if this instance
+ * matches empty string instead.
+ *
*
* @param stack Item input
* @return Whether this instance matches the input
+ * @deprecated use {@link #matchesAll(ItemStack)} or {@link #matchesAny(ItemStack)}
*/
+ @Deprecated
+ @ApiStatus.ScheduledForRemoval(inVersion = "2.9")
public final boolean matches(@NotNull ItemStack stack) {
- Set oreDicts = OreDictUnifier.getOreDictionaryNames(stack);
- if (oreDicts.isEmpty()) {
- return matches("");
- } else {
- for (String oreDict : oreDicts) {
- if (matches(oreDict)) return true;
- }
- return false;
- }
+ return matchesAny(stack);
+ }
+
+ /**
+ *
+ * Tries to match each ore dictionary entries associated with given item. If any of them matches, {@code true} is
+ * returned.
+ *
+ *
+ * For items not associated with any ore dictionary entries, this method returns {@code true} if this instance
+ * matches empty string instead.
+ *
+ *
+ * @param stack Item input
+ * @return Whether this instance matches the input
+ */
+ public final boolean matchesAny(@NotNull ItemStack stack) {
+ return matchesAny(OreDictUnifier.getOreDictionaryNames(stack), true);
+ }
+
+ /**
+ *
+ * Tries to match each ore dictionary entries associated with given item. If all of them matches, {@code true} is
+ * returned.
+ *
+ *
+ * For items not associated with any ore dictionary entries, this method returns {@code true} if this instance
+ * matches empty string instead.
+ *
+ *
+ * @param stack Item input
+ * @return Whether this instance matches the input
+ */
+ public final boolean matchesAll(@NotNull ItemStack stack) {
+ return matchesAll(OreDictUnifier.getOreDictionaryNames(stack), true);
+ }
+
+ /**
+ *
+ * Tries to match each input. If any of them matches, {@code true} is returned.
+ *
+ *
+ * @param inputs Collection of input strings
+ * @param specialEmptyMatch If {@code true}, this method will match an empty string ({@code ""}) if the input
+ * collection is empty. If {@code true}, this method will return {@code false} in such
+ * scenario.
+ * @return Whether this instance matches the input
+ */
+ public final boolean matchesAny(@NotNull Collection inputs, boolean specialEmptyMatch) {
+ if (specialEmptyMatch && inputs.isEmpty()) return matches("");
+ for (String input : inputs) if (matches(input)) return true;
+ return false;
+ }
+
+ /**
+ *
+ * Tries to match each input. If all of them matches, {@code true} is returned. Note that this method does not have
+ * special case for empty inputs.
+ *
+ *
+ * @param inputs Collection of input strings
+ * @param specialEmptyMatch If {@code true}, this method will match an empty string ({@code ""}) if the input
+ * collection is empty. If {@code true}, this method will return {@code true} in such
+ * scenario.
+ * @return Whether this instance matches the input
+ */
+ public final boolean matchesAll(@NotNull Collection inputs, boolean specialEmptyMatch) {
+ if (specialEmptyMatch && inputs.isEmpty()) return matches("");
+ for (String input : inputs) if (!matches(input)) return false;
+ return true;
}
/**
- * Visualize this instance with standard Minecraft text formatting. Two spaces (' ') will
- * be used as indentation.
+ * Visualize this instance with standard Minecraft text formatting. Two spaces ({@code ' '}) will be used as
+ * indentation.
*
* @return Formatted visualization
* @see OreGlob#toFormattedString(String)
diff --git a/src/main/java/gregtech/api/util/oreglob/OreGlobCompiler.java b/src/main/java/gregtech/api/util/oreglob/OreGlobCompiler.java
new file mode 100644
index 00000000000..d66fb7785a0
--- /dev/null
+++ b/src/main/java/gregtech/api/util/oreglob/OreGlobCompiler.java
@@ -0,0 +1,10 @@
+package gregtech.api.util.oreglob;
+
+import org.jetbrains.annotations.NotNull;
+
+@FunctionalInterface
+public interface OreGlobCompiler {
+
+ @NotNull
+ OreGlobCompileResult compile(@NotNull String expression, boolean ignoreCase);
+}
diff --git a/src/main/java/gregtech/common/covers/filter/OreDictionaryItemFilter.java b/src/main/java/gregtech/common/covers/filter/OreDictionaryItemFilter.java
index 95cc2f172e0..1db9a6087e3 100644
--- a/src/main/java/gregtech/common/covers/filter/OreDictionaryItemFilter.java
+++ b/src/main/java/gregtech/common/covers/filter/OreDictionaryItemFilter.java
@@ -2,12 +2,15 @@
import gregtech.api.gui.GuiTextures;
import gregtech.api.gui.Widget;
+import gregtech.api.gui.resources.TextureArea;
import gregtech.api.gui.widgets.DrawableWidget;
+import gregtech.api.gui.widgets.ImageCycleButtonWidget;
import gregtech.api.gui.widgets.ImageWidget;
import gregtech.api.unification.OreDictUnifier;
import gregtech.api.unification.stack.ItemVariantMap;
import gregtech.api.unification.stack.MultiItemVariantMap;
import gregtech.api.unification.stack.SingleItemVariantMap;
+import gregtech.api.util.function.BooleanConsumer;
import gregtech.api.util.oreglob.OreGlob;
import gregtech.api.util.oreglob.OreGlobCompileResult;
import gregtech.common.covers.filter.oreglob.impl.ImpossibleOreGlob;
@@ -18,55 +21,90 @@
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.network.PacketBuffer;
import net.minecraft.util.text.TextFormatting;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import java.util.Map;
import java.util.Set;
+import java.util.function.BooleanSupplier;
import java.util.function.Consumer;
public class OreDictionaryItemFilter extends ItemFilter {
+ private final Map- > matchCache = new Object2ObjectOpenHashMap<>();
+ private final SingleItemVariantMap noOreDictMatch = new SingleItemVariantMap<>();
+
protected String expression = "";
+
private OreGlob glob = ImpossibleOreGlob.getInstance();
private boolean error;
- private final Map
- > matchCache = new Object2ObjectOpenHashMap<>();
- private final SingleItemVariantMap noOreDictMatch = new SingleItemVariantMap<>();
+ private boolean caseSensitive;
+ /**
+ * {@code false} requires any of the entry to be match in order for the match to be success, {@code true} requires
+ * all entries to match
+ */
+ private boolean matchAll;
+ @NotNull
public String getExpression() {
return expression;
}
+ @NotNull
+ public OreGlob getGlob() {
+ return this.glob;
+ }
+
+ protected void recompile(@Nullable Consumer<@Nullable OreGlobCompileResult> callback) {
+ clearCache();
+ String expr = this.expression;
+ if (!expr.isEmpty()) {
+ OreGlobCompileResult result = OreGlob.compile(expr, !this.caseSensitive);
+ this.glob = result.getInstance();
+ this.error = result.hasError();
+ if (callback != null) callback.accept(result);
+ } else {
+ this.glob = ImpossibleOreGlob.getInstance();
+ this.error = true;
+ if (callback != null) callback.accept(null);
+ }
+ }
+
+ protected void clearCache() {
+ this.matchCache.clear();
+ this.noOreDictMatch.clear();
+ }
+
@Override
public void initUI(Consumer widgetGroup) {
ItemOreFilterTestSlot[] testSlot = new ItemOreFilterTestSlot[5];
for (int i = 0; i < testSlot.length; i++) {
- testSlot[i] = new ItemOreFilterTestSlot(20 + 22 * i, 0);
- widgetGroup.accept(testSlot[i]);
+ ItemOreFilterTestSlot slot = new ItemOreFilterTestSlot(20 + 22 * i, 0);
+ slot.setGlob(getGlob());
+ slot.setMatchAll(this.matchAll);
+ widgetGroup.accept(slot);
+ testSlot[i] = slot;
}
OreGlobCompileStatusWidget compilationStatus = new OreGlobCompileStatusWidget(10, 10);
+
+ Consumer<@Nullable OreGlobCompileResult> compileCallback = result -> {
+ compilationStatus.setCompileResult(result);
+ for (ItemOreFilterTestSlot slot : testSlot) {
+ slot.setGlob(getGlob());
+ }
+ };
+
HighlightedTextField textField = new HighlightedTextField(14, 26, 152, 14, () -> this.expression,
s -> {
if (s.equals(this.expression)) return;
this.expression = s;
- if (!s.isEmpty()) {
- OreGlobCompileResult result = OreGlob.compile(s);
- this.glob = result.getInstance();
- this.error = result.hasError();
- compilationStatus.setCompileResult(result);
- } else {
- this.glob = ImpossibleOreGlob.getInstance();
- this.error = true;
- compilationStatus.setCompileResult(null);
- }
- this.matchCache.clear();
- this.noOreDictMatch.clear();
markDirty();
- for (ItemOreFilterTestSlot slot : testSlot) {
- slot.setGlob(this.error ? null : this.glob);
- }
+ recompile(compileCallback);
});
compilationStatus.setTextField(textField);
@@ -91,7 +129,7 @@ public void initUI(Consumer widgetGroup) {
case '*', '?' -> h.format(i, TextFormatting.GREEN);
case '!' -> h.format(i, TextFormatting.RED);
case '\\' -> h.format(i++, TextFormatting.YELLOW);
- case '$' -> {
+ case '$' -> { // TODO: remove this switch case in 2.9
h.format(i, TextFormatting.DARK_GREEN);
for (; i < t.length(); i++) {
switch (t.charAt(i)) {
@@ -114,6 +152,25 @@ public void initUI(Consumer widgetGroup) {
h.format(i + 1, TextFormatting.RESET);
}
}).setMaxLength(64));
+ widgetGroup.accept(new ForcedInitialSyncImageCycleButtonWidget(130, 38, 18, 18,
+ GuiTextures.ORE_FILTER_BUTTON_CASE_SENSITIVE, () -> this.caseSensitive, caseSensitive -> {
+ if (this.caseSensitive == caseSensitive) return;
+ this.caseSensitive = caseSensitive;
+ markDirty();
+ recompile(compileCallback);
+ }).setTooltipHoverString(
+ i -> "cover.ore_dictionary_filter.button.case_sensitive." + (i == 0 ? "disabled" : "enabled")));
+ widgetGroup.accept(new ForcedInitialSyncImageCycleButtonWidget(148, 38, 18, 18,
+ GuiTextures.ORE_FILTER_BUTTON_MATCH_ALL, () -> this.matchAll, matchAll -> {
+ if (this.matchAll == matchAll) return;
+ this.matchAll = matchAll;
+ markDirty();
+ clearCache();
+ for (ItemOreFilterTestSlot slot : testSlot) {
+ slot.setMatchAll(matchAll);
+ }
+ }).setTooltipHoverString(
+ i -> "cover.ore_dictionary_filter.button.match_all." + (i == 0 ? "disabled" : "enabled")));
}
@Override
@@ -122,7 +179,7 @@ public Object matchItemStack(ItemStack itemStack) {
"wtf is this system?? i can put any non null object here and it i will work??? $arch" : null;
}
- public boolean matchesItemStack(ItemStack itemStack) {
+ public boolean matchesItemStack(@NotNull ItemStack itemStack) {
if (this.error) return false;
Item item = itemStack.getItem();
ItemVariantMap> oreDictEntry = OreDictUnifier.getOreDictionaryEntry(item);
@@ -160,7 +217,7 @@ public boolean matchesItemStack(ItemStack itemStack) {
}
this.matchCache.put(item, cacheEntry);
}
- boolean matches = this.glob.matches(itemStack);
+ boolean matches = this.matchAll ? this.glob.matchesAll(itemStack) : this.glob.matchesAny(itemStack);
cacheEntry.put(itemStack, matches);
return matches;
}
@@ -181,20 +238,43 @@ public int getTotalOccupiedHeight() {
}
@Override
- public void writeToNBT(NBTTagCompound tagCompound) {
- tagCompound.setString("OreDictionaryFilter", expression);
+ public void writeToNBT(NBTTagCompound tag) {
+ tag.setString("OreDictionaryFilter", expression);
+ if (this.caseSensitive) tag.setBoolean("caseSensitive", true);
+ if (this.matchAll) tag.setBoolean("matchAll", true);
}
@Override
- public void readFromNBT(NBTTagCompound tagCompound) {
- this.expression = tagCompound.getString("OreDictionaryFilter");
- if (!this.expression.isEmpty()) {
- OreGlobCompileResult result = OreGlob.compile(this.expression);
- this.glob = result.getInstance();
- this.error = result.hasError();
- } else {
- this.glob = ImpossibleOreGlob.getInstance();
- this.error = true;
+ public void readFromNBT(NBTTagCompound tag) {
+ this.expression = tag.getString("OreDictionaryFilter");
+ this.caseSensitive = tag.getBoolean("caseSensitive");
+ this.matchAll = tag.getBoolean("matchAll");
+ recompile(null);
+ }
+
+ public static class ForcedInitialSyncImageCycleButtonWidget extends ImageCycleButtonWidget {
+
+ private final BooleanConsumer updater;
+
+ public ForcedInitialSyncImageCycleButtonWidget(int xPosition, int yPosition, int width, int height,
+ TextureArea buttonTexture, BooleanSupplier supplier,
+ BooleanConsumer updater) {
+ super(xPosition, yPosition, width, height, buttonTexture, supplier, updater);
+ this.currentOption = 0;
+ this.updater = updater;
+ }
+
+ @Override
+ public void readUpdateInfo(int id, PacketBuffer buffer) {
+ if (id == 1) {
+ int currentOptionCache = this.currentOption;
+ super.readUpdateInfo(id, buffer);
+ if (this.currentOption != currentOptionCache) {
+ this.updater.apply(currentOption >= 1); // call updater to apply necessary state changes
+ }
+ } else {
+ super.readUpdateInfo(id, buffer);
+ }
}
}
}
diff --git a/src/main/java/gregtech/common/covers/filter/oreglob/impl/OreGlobMessages.java b/src/main/java/gregtech/common/covers/filter/oreglob/impl/OreGlobMessages.java
index 6b3da3ca6fd..d0c2d44e7df 100644
--- a/src/main/java/gregtech/common/covers/filter/oreglob/impl/OreGlobMessages.java
+++ b/src/main/java/gregtech/common/covers/filter/oreglob/impl/OreGlobMessages.java
@@ -2,6 +2,8 @@
import gregtech.api.util.LocalizationUtils;
+import org.jetbrains.annotations.ApiStatus;
+
import java.util.Locale;
interface OreGlobMessages {
@@ -102,21 +104,32 @@ static String compileErrorUnexpectedTokenAfterEOF(String token) {
return LocalizationUtils.format(COMPILE_ERROR_PREFIX + "unexpected_token_after_eof", token);
}
+ // compilation flags are expected to be removed in future release
+
+ @Deprecated
+ @SuppressWarnings("DeprecatedIsStillUsed")
+ @ApiStatus.ScheduledForRemoval(inVersion = "2.9")
static String compileErrorUnexpectedCompilationFlag() {
// Compilation flags in the middle of expression
return LocalizationUtils.format(COMPILE_ERROR_PREFIX + "unexpected_compilation_flag");
}
+ @Deprecated
+ @ApiStatus.ScheduledForRemoval(inVersion = "2.9")
static String compileErrorEmptyCompilationFlag() {
// No compilation flags given
return LocalizationUtils.format(COMPILE_ERROR_PREFIX + "empty_compilation_flag");
}
+ @Deprecated
+ @ApiStatus.ScheduledForRemoval(inVersion = "2.9")
static String compileErrorUnknownCompilationFlag(String flag) {
// Unknown compilation flag '%s'
return LocalizationUtils.format(COMPILE_ERROR_PREFIX + "unknown_compilation_flag", flag);
}
+ @Deprecated
+ @ApiStatus.ScheduledForRemoval(inVersion = "2.9")
static String compileErrorRedundantCompilationFlag(String flag) {
// Compilation flag '%s' written twice
return LocalizationUtils.format(COMPILE_ERROR_PREFIX + "redundant_compilation_flag", flag);
diff --git a/src/main/java/gregtech/common/covers/filter/oreglob/impl/OreGlobParser.java b/src/main/java/gregtech/common/covers/filter/oreglob/impl/OreGlobParser.java
index 0bc564d69db..b4cec035040 100644
--- a/src/main/java/gregtech/common/covers/filter/oreglob/impl/OreGlobParser.java
+++ b/src/main/java/gregtech/common/covers/filter/oreglob/impl/OreGlobParser.java
@@ -5,6 +5,7 @@
import gregtech.common.covers.filter.oreglob.node.OreGlobNode;
import gregtech.common.covers.filter.oreglob.node.OreGlobNodes;
+import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
@@ -14,7 +15,7 @@
/**
* Top-down parser for oreGlob expression.
- *
+ *
*
* oreGlob = [ FLAG ], [ or ], EOF
*
@@ -47,8 +48,7 @@ public final class OreGlobParser {
private boolean error;
- private boolean caseSensitive;
-
+ private boolean ignoreCase;
private int inputIndex;
private TokenType tokenType;
@@ -56,8 +56,9 @@ public final class OreGlobParser {
@Nullable
private String tokenLiteralValue;
- public OreGlobParser(String input) {
+ public OreGlobParser(String input, boolean ignoreCase) {
this.input = input;
+ this.ignoreCase = ignoreCase;
}
// Get codepoint at current position and incr index
@@ -68,6 +69,7 @@ private int readNextChar() {
return input.codePointAt(i);
}
+ @SuppressWarnings("deprecation")
private void advance() {
boolean first = this.inputIndex == 0;
while (true) {
@@ -84,7 +86,7 @@ private void advance() {
case '^' -> setCurrentToken(XOR, start, 1);
case '*' -> setCurrentToken(ANY, start, 1);
case '?' -> setCurrentToken(ANY_CHAR, start, 1);
- case '$' -> {
+ case '$' -> { // TODO: remove this switch case in 2.9
if (!first) {
error(OreGlobMessages.compileErrorUnexpectedCompilationFlag(), start, 1);
}
@@ -145,8 +147,10 @@ private String gatherLiteralValue() {
}
}
+ @Deprecated
+ @SuppressWarnings("DeprecatedIsStillUsed")
+ @ApiStatus.ScheduledForRemoval(inVersion = "2.9")
private void gatherFlags(boolean add) {
- boolean flagsAdded = false;
while (true) {
int i = this.inputIndex;
int c = readNextChar();
@@ -156,39 +160,27 @@ private void gatherFlags(boolean add) {
if (c == CHAR_EOF) {
error(OreGlobMessages.compileErrorEOFAfterEscape(), i, 1);
} else if (add) {
- addFlag(c, i);
- flagsAdded = true;
+ addFlag(c);
continue;
}
}
case ' ', '\t', '\n', '\r', CHAR_EOF -> {}
default -> {
if (add) {
- addFlag(c, i);
- flagsAdded = true;
+ addFlag(c);
}
continue;
}
}
- if (!flagsAdded && add) {
- error(OreGlobMessages.compileErrorEmptyCompilationFlag(), i, 1);
- }
+ warn("Compilation flags ('$') are scheduled to be removed in future releases.");
return;
}
}
- private void addFlag(int flag, int index) {
- switch (flag) {
- case 'c', 'C' -> {
- if (this.caseSensitive) {
- warn(OreGlobMessages.compileErrorRedundantCompilationFlag("c"), index, 1);
- } else {
- this.caseSensitive = true;
- }
- }
- default -> warn(OreGlobMessages.compileErrorUnknownCompilationFlag(
- new StringBuilder().appendCodePoint(flag).toString()), index, 1);
- }
+ @Deprecated
+ @ApiStatus.ScheduledForRemoval(inVersion = "2.9")
+ private void addFlag(int flag) {
+ if (flag == 'c' || flag == 'C') this.ignoreCase = false;
}
private boolean advanceIf(TokenType type) {
@@ -296,7 +288,7 @@ private OreGlobNode primary() {
return switch (tokenType) {
case LITERAL -> {
if (tokenLiteralValue != null) {
- OreGlobNode result = OreGlobNodes.match(tokenLiteralValue, !this.caseSensitive);
+ OreGlobNode result = OreGlobNodes.match(tokenLiteralValue, this.ignoreCase);
advance();
yield result;
} else { // likely caused by program error, not user issue
diff --git a/src/main/java/gregtech/common/gui/widget/orefilter/OreFilterTestSlot.java b/src/main/java/gregtech/common/gui/widget/orefilter/OreFilterTestSlot.java
index 6bde8f6cb5b..fd81e80bcd7 100644
--- a/src/main/java/gregtech/common/gui/widget/orefilter/OreFilterTestSlot.java
+++ b/src/main/java/gregtech/common/gui/widget/orefilter/OreFilterTestSlot.java
@@ -23,7 +23,6 @@
import java.util.Arrays;
import java.util.Collections;
-import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
@@ -32,6 +31,9 @@
*/
public abstract class OreFilterTestSlot extends WidgetGroup {
+ private final ImageWidget match;
+ private final ImageWidget noMatch;
+
@Nullable
private OreGlob glob;
private boolean expectedResult = true;
@@ -48,8 +50,7 @@ public abstract class OreFilterTestSlot extends WidgetGroup {
private boolean initialized = false;
- private final ImageWidget match;
- private final ImageWidget noMatch;
+ private boolean matchAll;
public OreFilterTestSlot(int xPosition, int yPosition) {
super(xPosition, yPosition, 18, 18);
@@ -86,30 +87,42 @@ public OreFilterTestSlot onMatchChange(@Nullable BooleanConsumer onMatchChange)
}
public void setGlob(@Nullable OreGlob glob) {
+ if (this.glob == glob) return;
this.glob = glob;
updatePreview();
}
+ public void setMatchAll(boolean matchAll) {
+ if (this.matchAll == matchAll) return;
+ this.matchAll = matchAll;
+ updatePreview();
+ }
+
protected void updatePreview() {
if (!this.initialized) return;
Set oreDicts = getTestCandidates();
if (oreDicts != null) {
- boolean success;
OreGlob glob = this.glob;
if (oreDicts.isEmpty()) {
// no oredict entries
- this.testResult = Object2BooleanMaps.singleton("", success = glob != null && glob.matches(""));
+ this.testResult = Object2BooleanMaps.singleton("", glob != null && glob.matches(""));
this.matchType = MatchType.NO_ORE_DICT_MATCH;
} else {
this.testResult = new Object2BooleanAVLTreeMap<>();
- success = false;
for (String oreDict : oreDicts) {
boolean matches = glob != null && glob.matches(oreDict);
this.testResult.put(oreDict, matches);
- success |= matches;
}
this.matchType = MatchType.ORE_DICT_MATCH;
}
+ boolean success = this.matchAll;
+ for (var e : testResult.object2BooleanEntrySet()) {
+ boolean result = e.getBooleanValue();
+ if (result == !this.matchAll) {
+ success = !this.matchAll;
+ break;
+ }
+ }
updateAndNotifyMatchSuccess(this.expectedResult == success);
this.match.setVisible(this.expectedResult == success);
this.noMatch.setVisible(this.expectedResult != success);
@@ -131,9 +144,8 @@ private void updateAndNotifyMatchSuccess(boolean newValue) {
}
/**
- * Get each test candidate for current state of test slot. An empty collection indicates that the
- * match is for items without any ore dictionary entry. A {@code null} value indicates that the
- * input state is invalid or empty.
+ * Get each test candidate for current state of test slot. An empty collection indicates that the match is for items
+ * without any ore dictionary entry. A {@code null} value indicates that the input state is invalid or empty.
*
* @return each test candidate for current state of test slot
*/
@@ -168,26 +180,17 @@ public void drawInBackground(int mouseX, int mouseY, float partialTicks, IRender
@Override
public void drawInForeground(int mouseX, int mouseY) {
if (isActive() && isMouseOverElement(mouseX, mouseY)) {
- List list;
- switch (this.matchType) {
- case NO_ORE_DICT_MATCH:
- list = Collections.singletonList(I18n.format(this.matchSuccess ?
- "cover.ore_dictionary_filter.test_slot.no_oredict.matches" :
- "cover.ore_dictionary_filter.test_slot.no_oredict.matches_not"));
- break;
- case ORE_DICT_MATCH:
- list = this.testResult.object2BooleanEntrySet().stream().map(
- e -> I18n.format(e.getBooleanValue() ?
- "cover.ore_dictionary_filter.test_slot.matches" :
- "cover.ore_dictionary_filter.test_slot.matches_not", e.getKey()))
- .collect(Collectors.toList());
- break;
- case INVALID:
- default:
- list = Arrays.asList(LocalizationUtils.formatLines("cover.ore_dictionary_filter.test_slot.info"));
- break;
- }
- drawHoveringText(ItemStack.EMPTY, list, 300, mouseX, mouseY);
+ drawHoveringText(ItemStack.EMPTY, switch (this.matchType) {
+ case NO_ORE_DICT_MATCH -> Collections.singletonList(I18n.format(this.matchSuccess ?
+ "cover.ore_dictionary_filter.test_slot.no_oredict.matches" :
+ "cover.ore_dictionary_filter.test_slot.no_oredict.matches_not"));
+ case ORE_DICT_MATCH -> this.testResult.object2BooleanEntrySet().stream().map(
+ e -> I18n.format(e.getBooleanValue() ?
+ "cover.ore_dictionary_filter.test_slot.matches" :
+ "cover.ore_dictionary_filter.test_slot.matches_not", e.getKey()))
+ .collect(Collectors.toList());
+ default -> Arrays.asList(LocalizationUtils.formatLines("cover.ore_dictionary_filter.test_slot.info"));
+ }, 300, mouseX, mouseY);
}
}
diff --git a/src/main/java/gregtech/core/CoreModule.java b/src/main/java/gregtech/core/CoreModule.java
index c063eec5c15..d103159380f 100644
--- a/src/main/java/gregtech/core/CoreModule.java
+++ b/src/main/java/gregtech/core/CoreModule.java
@@ -25,6 +25,7 @@
import gregtech.api.util.CapesRegistry;
import gregtech.api.util.VirtualTankRegistry;
import gregtech.api.util.input.KeyBind;
+import gregtech.api.util.oreglob.OreGlob;
import gregtech.api.worldgen.bedrockFluids.BedrockFluidVeinHandler;
import gregtech.api.worldgen.bedrockFluids.BedrockFluidVeinSaveData;
import gregtech.api.worldgen.config.WorldGenRegistry;
@@ -40,6 +41,7 @@
import gregtech.common.command.worldgen.CommandWorldgen;
import gregtech.common.covers.CoverBehaviors;
import gregtech.common.covers.filter.FilterTypeRegistry;
+import gregtech.common.covers.filter.oreglob.impl.OreGlobParser;
import gregtech.common.items.MetaItems;
import gregtech.common.items.ToolItems;
import gregtech.common.metatileentities.MetaTileEntities;
@@ -111,6 +113,8 @@ public CoreModule() {
// must be set here because of GroovyScript compat
// trying to read this before the pre-init stage
GregTechAPI.materialManager = MaterialRegistryManager.getInstance();
+
+ OreGlob.setCompiler((expr, ignoreCase) -> new OreGlobParser(expr, ignoreCase).compile());
}
@NotNull
diff --git a/src/main/resources/assets/gregtech/lang/en_us.lang b/src/main/resources/assets/gregtech/lang/en_us.lang
index 531dfc20c6a..0a99c369d6a 100644
--- a/src/main/resources/assets/gregtech/lang/en_us.lang
+++ b/src/main/resources/assets/gregtech/lang/en_us.lang
@@ -1175,7 +1175,7 @@ cover.filter.blacklist.disabled=Whitelist
cover.filter.blacklist.enabled=Blacklist
cover.ore_dictionary_filter.title=Ore Dictionary Filter
-cover.ore_dictionary_filter.info=§bAccepts complex expressions/n§6a & b§r = AND/n§6a | b§r = OR/n§6a ^ b§r = XOR/n§6! abc§r = NOT/n§6( abc )§r for grouping/n§6*§r for wildcard (i.e. 0 or more characters)/n§6?§r for any 1 character/n§6()§r for matching empty entry (including items with no ore dictionary)/n§6$c§r at the start of expression for case-sensitive match/n§bExample:/n§6dust*Gold | (plate* & !*Double*)/nWill match all gold dusts of all sizes or all plates, but not double plates
+cover.ore_dictionary_filter.info=§bAccepts complex expressions/n§6a & b§r = AND/n§6a | b§r = OR/n§6a ^ b§r = XOR/n§6! abc§r = NOT/n§6( abc )§r for grouping/n§6*§r for wildcard (i.e. 0 or more characters)/n§6?§r for any 1 character/n§6()§r for matching empty entry (including items with no ore dictionary)/n§bExample:/n§6dust*Gold | (plate* & !*Double*)/nWill match all gold dusts of all sizes or all plates, but not double plates
cover.ore_dictionary_filter.test_slot.info=Insert a item to test if it matches the filter expression
cover.ore_dictionary_filter.test_slot.matches=§a* %s
cover.ore_dictionary_filter.test_slot.matches_not=§c* %s
@@ -1186,6 +1186,10 @@ cover.ore_dictionary_filter.status.err_warn=§c%s error(s) and %s warning(s)
cover.ore_dictionary_filter.status.warn=§7%s warning(s)
cover.ore_dictionary_filter.status.no_issues=§aNo issues
cover.ore_dictionary_filter.status.explain=Ore filter explanation:
+cover.ore_dictionary_filter.button.case_sensitive.disabled=Case insensitive match
+cover.ore_dictionary_filter.button.case_sensitive.enabled=Case sensitive match
+cover.ore_dictionary_filter.button.match_all.disabled=Match any one of ore dictionary entries
+cover.ore_dictionary_filter.button.match_all.enabled=Match all ore dictionary entries
cover.ore_dictionary_filter.preview.next=... followed by
cover.ore_dictionary_filter.preview.match='%s'
diff --git a/src/main/resources/assets/gregtech/textures/gui/widget/ore_filter/button_case_sensitive.png b/src/main/resources/assets/gregtech/textures/gui/widget/ore_filter/button_case_sensitive.png
new file mode 100644
index 00000000000..6615e156d4f
Binary files /dev/null and b/src/main/resources/assets/gregtech/textures/gui/widget/ore_filter/button_case_sensitive.png differ
diff --git a/src/main/resources/assets/gregtech/textures/gui/widget/ore_filter/button_match_all.png b/src/main/resources/assets/gregtech/textures/gui/widget/ore_filter/button_match_all.png
new file mode 100644
index 00000000000..b86b782c8de
Binary files /dev/null and b/src/main/resources/assets/gregtech/textures/gui/widget/ore_filter/button_match_all.png differ
diff --git a/src/test/java/gregtech/api/util/OreGlobTest.java b/src/test/java/gregtech/api/util/OreGlobTest.java
index f9f888f02f2..fb094484f73 100644
--- a/src/test/java/gregtech/api/util/OreGlobTest.java
+++ b/src/test/java/gregtech/api/util/OreGlobTest.java
@@ -190,11 +190,7 @@ public void matchTest() {
assertMatch(expr, "anyDoubleSomething", false);
assertMatch(expr, "shouldn't match!", false);
- expr = compile("$c caseSensitiveMatch");
- assertMatch(expr, "casesensitivematch", false);
- assertMatch(expr, "caseSensitiveMatch", true);
-
- expr = compile("$\\c caseSensitiveMatch");
+ expr = compile("caseSensitiveMatch", true);
assertMatch(expr, "casesensitivematch", false);
assertMatch(expr, "caseSensitiveMatch", true);
@@ -249,8 +245,6 @@ public void matchTest() {
@Test
public void errorTest() {
assertReport("End of file after escape character ('\\'): \\", true);
- assertReport("$asdf Tags at middle of expression $12345", true);
- assertReport("End of file after escape character ('\\'): $123\\", true);
assertReport(")", true);
assertReport("a | b | c | ", true);
assertReport(")))))))", true);
@@ -262,12 +256,15 @@ public void errorTest() {
assertReport("dust !impure !iron", false);
assertReport("dust !(impure) !(iron)", false);
- assertReport("$cc 1", false);
}
private static OreGlob compile(String expression) {
+ return compile(expression, false);
+ }
+
+ private static OreGlob compile(String expression, boolean caseSensitive) {
long t = System.nanoTime();
- OreGlobCompileResult result = new OreGlobParser(expression).compile();
+ OreGlobCompileResult result = new OreGlobParser(expression, !caseSensitive).compile();
assertThat(result.hasError(), is(false));
if (LOG) {
@@ -333,7 +330,7 @@ protected boolean matchesSafely(OreGlob item) {
}
private static void assertReport(String expression, boolean error) {
- OreGlobCompileResult result = new OreGlobParser(expression).compile();
+ OreGlobCompileResult result = new OreGlobParser(expression, true).compile();
assertThat(result, new TypeSafeMatcher<>(OreGlobCompileResult.class) {
@Override