mirror of
https://github.com/GTNewHorizons/NotEnoughItems.git
synced 2026-10-26 22:33:52 +00:00
Compare commits
28
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5576f1ba09 | ||
|
|
d64c270e3a | ||
|
|
12da0ba608 | ||
|
|
3d07a33e3c | ||
|
|
4062f6c001 | ||
|
|
8fbb876a81 | ||
|
|
e050faaa90 | ||
|
|
576da1468c | ||
|
|
316494df15 | ||
|
|
66deab6dbd | ||
|
|
4953edde4b | ||
|
|
9873de760f | ||
|
|
355cc5bd0e | ||
|
|
183e40a6c2 | ||
|
|
79660a09d5 | ||
|
|
b03ae51e3c | ||
|
|
91d57c28b7 | ||
|
|
06cdea3fd6 | ||
|
|
ceae486a31 | ||
|
|
d35e77661f | ||
|
|
4285632807 | ||
|
|
b16916dbe6 | ||
|
|
57db3fa789 | ||
|
|
c5c798c61a | ||
|
|
f9cba79a22 | ||
|
|
0a24334693 | ||
|
|
8ef88ff9f2 | ||
|
|
4cfbe6b3ad |
No files matched your search
+24
-5
@@ -1,4 +1,4 @@
|
||||
//version: 1704751096
|
||||
//version: 1706545953
|
||||
/*
|
||||
DO NOT CHANGE THIS FILE!
|
||||
Also, you may replace this file at any time if there is an update available.
|
||||
@@ -122,6 +122,7 @@ propertyDefaultIfUnset("modrinthProjectId", "")
|
||||
propertyDefaultIfUnset("modrinthRelations", "")
|
||||
propertyDefaultIfUnset("curseForgeProjectId", "")
|
||||
propertyDefaultIfUnset("curseForgeRelations", "")
|
||||
propertyDefaultIfUnset("versionPattern", "")
|
||||
propertyDefaultIfUnset("minimizeShadowedDependencies", true)
|
||||
propertyDefaultIfUnset("relocateShadowedDependencies", true)
|
||||
// Deprecated properties (kept for backwards compat)
|
||||
@@ -370,6 +371,7 @@ catch (Exception ignored) {
|
||||
// Pulls version first from the VERSION env and then git tag
|
||||
String identifiedVersion
|
||||
String versionOverride = System.getenv("VERSION") ?: null
|
||||
boolean checkVersion = false
|
||||
try {
|
||||
// Produce a version based on the tag, or for branches something like 0.2.2-configurable-maven-and-extras.38+43090270b6-dirty
|
||||
if (versionOverride == null) {
|
||||
@@ -388,6 +390,8 @@ try {
|
||||
}
|
||||
} else if (isDirty) {
|
||||
identifiedVersion += "-${branchName}+${gitDetails.gitHash}-dirty"
|
||||
} else {
|
||||
checkVersion = true
|
||||
}
|
||||
} else {
|
||||
identifiedVersion = versionOverride
|
||||
@@ -409,6 +413,8 @@ ext {
|
||||
|
||||
if (identifiedVersion == versionOverride) {
|
||||
out.style(Style.Failure).text('Override version to ').style(Style.Identifier).text(modVersion).style(Style.Failure).println('!\7')
|
||||
} else if (checkVersion && versionPattern && !(identifiedVersion ==~ versionPattern)) {
|
||||
throw new GradleException("Invalid version: '$identifiedVersion' does not match version pattern '$versionPattern'")
|
||||
}
|
||||
|
||||
group = "com.github.GTNewHorizons"
|
||||
@@ -428,18 +434,31 @@ minecraft {
|
||||
for (f in replaceGradleTokenInFile.split(',')) {
|
||||
tagReplacementFiles.add f
|
||||
}
|
||||
out.style(Style.Info).text('replaceGradleTokenInFile is deprecated! Consider using generateGradleTokenClass.').println()
|
||||
}
|
||||
if (gradleTokenModId) {
|
||||
injectedTags.put gradleTokenModId, modId
|
||||
if (replaceGradleTokenInFile) {
|
||||
injectedTags.put gradleTokenModId, modId
|
||||
} else {
|
||||
out.style(Style.Failure).text('gradleTokenModId is deprecated! The field will no longer be generated.').println()
|
||||
}
|
||||
}
|
||||
if (gradleTokenModName) {
|
||||
injectedTags.put gradleTokenModName, modName
|
||||
if (replaceGradleTokenInFile) {
|
||||
injectedTags.put gradleTokenModName, modName
|
||||
} else {
|
||||
out.style(Style.Failure).text('gradleTokenModName is deprecated! The field will no longer be generated.').println()
|
||||
}
|
||||
}
|
||||
if (gradleTokenVersion) {
|
||||
injectedTags.put gradleTokenVersion, modVersion
|
||||
}
|
||||
if (gradleTokenGroupName) {
|
||||
injectedTags.put gradleTokenGroupName, modGroup
|
||||
if (replaceGradleTokenInFile) {
|
||||
injectedTags.put gradleTokenGroupName, modGroup
|
||||
} else {
|
||||
out.style(Style.Failure).text('gradleTokenGroupName is deprecated! The field will no longer be generated.').println()
|
||||
}
|
||||
}
|
||||
if (enableGenericInjection.toBoolean()) {
|
||||
injectMissingGenerics.set(true)
|
||||
@@ -632,7 +651,7 @@ repositories {
|
||||
|
||||
def mixinProviderGroup = "io.github.legacymoddingmc"
|
||||
def mixinProviderModule = "unimixins"
|
||||
def mixinProviderVersion = "0.1.13"
|
||||
def mixinProviderVersion = "0.1.15"
|
||||
def mixinProviderSpecNoClassifer = "${mixinProviderGroup}:${mixinProviderModule}:${mixinProviderVersion}"
|
||||
def mixinProviderSpec = "${mixinProviderSpecNoClassifer}:dev"
|
||||
ext.mixinProviderSpec = mixinProviderSpec
|
||||
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
// Add your dependencies here
|
||||
|
||||
dependencies {
|
||||
api('com.github.GTNewHorizons:CodeChickenLib:1.2.0:dev')
|
||||
api('com.github.GTNewHorizons:CodeChickenCore:1.2.0:dev')
|
||||
api('com.github.GTNewHorizons:CodeChickenLib:1.2.1:dev')
|
||||
api('com.github.GTNewHorizons:CodeChickenCore:1.2.1:dev')
|
||||
shadowImplementation('org.apache.commons:commons-csv:1.10.0')
|
||||
}
|
||||
+3
-3
@@ -28,10 +28,10 @@ developmentEnvironmentUserName = Developer
|
||||
# Leave these properties empty to skip individual token replacements
|
||||
# Generate a class with String fields for the mod id, name, version and group name named with the fields below
|
||||
generateGradleTokenClass = codechicken.nei.Tags
|
||||
gradleTokenModId = MODID
|
||||
gradleTokenModName = MODNAME
|
||||
gradleTokenModId =
|
||||
gradleTokenModName =
|
||||
gradleTokenVersion = VERSION
|
||||
gradleTokenGroupName = GROUPNAME
|
||||
gradleTokenGroupName =
|
||||
# [DEPRECATED]
|
||||
# Multiple source files can be defined here by providing a comma-seperated list: Class1.java,Class2.java,Class3.java
|
||||
# public static final String VERSION = "GRADLETOKEN_VERSION";
|
||||
|
||||
@@ -0,0 +1,315 @@
|
||||
package codechicken.nei;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraftforge.fluids.FluidStack;
|
||||
|
||||
import codechicken.nei.BookmarkPanel.ItemStackMetadata;
|
||||
import codechicken.nei.recipe.BookmarkRecipeId;
|
||||
import codechicken.nei.recipe.StackInfo;
|
||||
|
||||
public class BookmarkCraftingChain {
|
||||
|
||||
public HashMap<ItemStack, ItemStack> calculatedItems = new HashMap<>();
|
||||
public HashMap<ItemStack, Integer> multiplier = new HashMap<>();
|
||||
|
||||
public HashMap<ItemStack, ItemStack> inputs = new HashMap<>();
|
||||
public HashMap<ItemStack, ItemStack> outputs = new HashMap<>();
|
||||
public HashMap<ItemStack, ItemStack> intermediate = new HashMap<>();
|
||||
|
||||
protected static class CraftingChainItem {
|
||||
|
||||
public String guid;
|
||||
public int stackIndex = 0;
|
||||
public int recipeIndex = 0;
|
||||
public int factor = 0;
|
||||
public int count = 0;
|
||||
public boolean ingredient = false;
|
||||
public int fluidCellAmount = 1;
|
||||
public ItemStack stack = null;
|
||||
|
||||
public CraftingChainItem(ItemStack stack, ItemStackMetadata stackMetadata) {
|
||||
FluidStack fluid = StackInfo.getFluid(stack);
|
||||
this.recipeIndex = getRecipeIndex(stackMetadata.recipeId);
|
||||
this.ingredient = stackMetadata.ingredient;
|
||||
this.stack = stack;
|
||||
|
||||
if (fluid != null) {
|
||||
this.stackIndex = getStackIndex(fluid);
|
||||
this.count = fluid.amount * Math.max(0, stack.stackSize);
|
||||
this.fluidCellAmount = StackInfo.isFluidContainer(stack) ? fluid.amount : 1;
|
||||
this.factor = this.fluidCellAmount * stackMetadata.factor;
|
||||
} else {
|
||||
this.stackIndex = getStackIndex(stack);
|
||||
this.count = StackInfo.itemStackToNBT(stack).getInteger("Count");
|
||||
this.factor = stackMetadata.factor;
|
||||
}
|
||||
|
||||
this.guid = this.stackIndex + " " + this.recipeIndex;
|
||||
}
|
||||
|
||||
public ItemStack getItemStack(long count) {
|
||||
return StackInfo.loadFromNBT(
|
||||
StackInfo.itemStackToNBT(this.stack),
|
||||
this.factor > 0 ? (count / this.fluidCellAmount) : 0);
|
||||
}
|
||||
|
||||
public static void clearStatic() {
|
||||
itemCache.clear();
|
||||
fluidCache.clear();
|
||||
recipeCache.clear();
|
||||
}
|
||||
|
||||
private static HashMap<ItemStack, Integer> itemCache = new HashMap<>();
|
||||
|
||||
private static int getStackIndex(ItemStack stackA) {
|
||||
|
||||
if (!itemCache.containsKey(stackA)) {
|
||||
|
||||
for (ItemStack item : itemCache.keySet()) {
|
||||
if (StackInfo.equalItemAndNBT(stackA, item, true)) {
|
||||
itemCache.put(stackA, itemCache.get(item));
|
||||
return itemCache.get(stackA);
|
||||
}
|
||||
}
|
||||
|
||||
itemCache.put(stackA, itemCache.size() + fluidCache.size());
|
||||
}
|
||||
|
||||
return itemCache.get(stackA);
|
||||
}
|
||||
|
||||
private static HashMap<FluidStack, Integer> fluidCache = new HashMap<>();
|
||||
|
||||
private static int getStackIndex(FluidStack fluidA) {
|
||||
|
||||
if (!fluidCache.containsKey(fluidA)) {
|
||||
for (FluidStack item : fluidCache.keySet()) {
|
||||
if (fluidA.isFluidEqual(item)) {
|
||||
fluidCache.put(fluidA, fluidCache.get(item));
|
||||
return fluidCache.get(fluidA);
|
||||
}
|
||||
}
|
||||
|
||||
fluidCache.put(fluidA, itemCache.size() + fluidCache.size());
|
||||
}
|
||||
|
||||
return fluidCache.get(fluidA);
|
||||
}
|
||||
|
||||
private static HashMap<BookmarkRecipeId, Integer> recipeCache = new HashMap<>();
|
||||
|
||||
private static int getRecipeIndex(BookmarkRecipeId recipe) {
|
||||
|
||||
if (recipe == null) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!recipeCache.containsKey(recipe)) {
|
||||
for (BookmarkRecipeId item : recipeCache.keySet()) {
|
||||
if (item.equals(recipe)) {
|
||||
recipeCache.put(recipe, recipeCache.get(item));
|
||||
return recipeCache.get(recipe);
|
||||
}
|
||||
}
|
||||
|
||||
recipeCache.put(recipe, recipeCache.size());
|
||||
}
|
||||
|
||||
return recipeCache.get(recipe);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected static class CraftingChainRequest {
|
||||
|
||||
public List<CraftingChainItem> items = new ArrayList<>();
|
||||
|
||||
public HashMap<Integer, Integer> multiplier = new HashMap<>();
|
||||
public HashMap<String, Long> counts = new HashMap<>();
|
||||
|
||||
public HashMap<Integer, HashSet<CraftingChainItem>> inputs = new HashMap<>();
|
||||
public HashMap<Integer, HashSet<CraftingChainItem>> outputs = new HashMap<>();
|
||||
|
||||
public HashSet<Integer> initialItems = new HashSet<>();
|
||||
public HashSet<Integer> startedIngrs = new HashSet<>();
|
||||
|
||||
public CraftingChainRequest(List<ItemStack> items, List<ItemStackMetadata> metadata) {
|
||||
HashSet<Integer> inputs = new HashSet<>();
|
||||
HashSet<Integer> outputs = new HashSet<>();
|
||||
|
||||
for (int index = 0; index < items.size(); index++) {
|
||||
CraftingChainItem item = new CraftingChainItem(items.get(index), metadata.get(index));
|
||||
item.guid = item.ingredient ? "i" + item.guid : "r" + item.guid;
|
||||
this.items.add(item);
|
||||
|
||||
if (this.multiplier.get(item.recipeIndex) == null) {
|
||||
this.multiplier.put(item.recipeIndex, 0);
|
||||
}
|
||||
|
||||
this.counts.put(item.guid, this.counts.getOrDefault(item.guid, 0L) + item.count);
|
||||
|
||||
if (item.ingredient) {
|
||||
inputs.add(item.recipeIndex);
|
||||
|
||||
if (this.inputs.get(item.stackIndex) == null) {
|
||||
this.inputs.put(item.stackIndex, new HashSet<>());
|
||||
}
|
||||
|
||||
this.inputs.get(item.stackIndex).add(item);
|
||||
} else {
|
||||
outputs.add(item.recipeIndex);
|
||||
|
||||
if (this.outputs.get(item.stackIndex) == null) {
|
||||
this.outputs.put(item.stackIndex, new HashSet<>());
|
||||
}
|
||||
|
||||
this.outputs.get(item.stackIndex).add(item);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
for (int recipeIndex : this.multiplier.keySet()) {
|
||||
if (recipeIndex == -1 || !inputs.contains(recipeIndex) || !outputs.contains(recipeIndex)) {
|
||||
this.initialItems.add(recipeIndex);
|
||||
}
|
||||
}
|
||||
|
||||
for (CraftingChainItem item : this.items) {
|
||||
if (item.ingredient == false && !this.initialItems.contains(item.recipeIndex)) {
|
||||
this.startedIngrs.add(item.stackIndex);
|
||||
}
|
||||
}
|
||||
|
||||
CraftingChainItem.clearStatic();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void refresh(List<ItemStack> items, List<ItemStackMetadata> metadata) {
|
||||
CraftingChainRequest request = new CraftingChainRequest(items, metadata);
|
||||
HashMap<Integer, Long> iShift = new HashMap<>();
|
||||
HashMap<Integer, Long> oShift = new HashMap<>();
|
||||
boolean change = true;
|
||||
int iteration = 100;
|
||||
|
||||
while (--iteration > 0 && change) {
|
||||
change = false;
|
||||
for (int stackIndex : request.startedIngrs) {
|
||||
change = calculateShift(request, stackIndex) || change;
|
||||
}
|
||||
}
|
||||
|
||||
this.inputs.clear();
|
||||
this.outputs.clear();
|
||||
this.intermediate.clear();
|
||||
this.calculatedItems.clear();
|
||||
this.multiplier.clear();
|
||||
|
||||
for (CraftingChainItem item : request.items) {
|
||||
if (request.initialItems.contains(item.recipeIndex)) {
|
||||
long iCount = calculateCount(request, request.inputs.get(item.stackIndex))
|
||||
- iShift.getOrDefault(item.stackIndex, 0L);
|
||||
this.calculatedItems.put(item.stack, item.stack);
|
||||
|
||||
if (iCount == 0) {
|
||||
this.inputs.put(item.stack, item.getItemStack(0));
|
||||
} else {
|
||||
long count = Math.min(iCount, item.count);
|
||||
this.inputs.put(item.stack, item.getItemStack(count));
|
||||
iShift.put(item.stackIndex, iShift.getOrDefault(item.stackIndex, 0L) + count);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
for (CraftingChainItem item : request.items) {
|
||||
if (!request.initialItems.contains(item.recipeIndex)) {
|
||||
long count = item.count + item.factor * request.multiplier.get(item.recipeIndex);
|
||||
this.calculatedItems.put(item.stack, item.getItemStack(count));
|
||||
|
||||
if (item.ingredient) { // input
|
||||
long oCount = calculateCount(request, request.outputs.get(item.stackIndex))
|
||||
- oShift.getOrDefault(item.stackIndex, 0L);
|
||||
|
||||
if (oCount < count) {
|
||||
this.inputs.put(item.stack, item.getItemStack(count - oCount));
|
||||
oShift.put(item.stackIndex, oShift.getOrDefault(item.stackIndex, 0L) + oCount);
|
||||
} else if (oCount >= count) {
|
||||
this.intermediate.put(item.stack, item.getItemStack(0));
|
||||
oShift.put(item.stackIndex, oShift.getOrDefault(item.stackIndex, 0L) + count);
|
||||
}
|
||||
|
||||
} else { // output
|
||||
long iCount = calculateCount(request, request.inputs.get(item.stackIndex))
|
||||
- iShift.getOrDefault(item.stackIndex, 0L);
|
||||
this.multiplier.put(item.stack, item.factor > 0 ? (int) (count / item.factor) : 0);
|
||||
|
||||
if (iCount < count) {
|
||||
this.outputs.put(item.stack, item.getItemStack(count - iCount));
|
||||
iShift.put(item.stackIndex, iShift.getOrDefault(item.stackIndex, 0L) + iCount);
|
||||
} else if (iCount >= count) {
|
||||
this.intermediate.put(item.stack, item.getItemStack(0));
|
||||
iShift.put(item.stackIndex, iShift.getOrDefault(item.stackIndex, 0L) + count);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private boolean calculateShift(CraftingChainRequest request, int stackIndex) {
|
||||
|
||||
if (!request.outputs.containsKey(stackIndex)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int minRecipeIndex = 0;
|
||||
int minShift = Integer.MAX_VALUE;
|
||||
|
||||
for (CraftingChainItem item : request.outputs.get(stackIndex)) {
|
||||
if (!request.initialItems.contains(item.recipeIndex) && item.factor > 0) {
|
||||
long ingrCount = calculateCount(request, request.inputs.get(item.stackIndex), item.recipeIndex);
|
||||
long outputCount = calculateCount(request, request.outputs.get(item.stackIndex));
|
||||
long shift = (long) Math.ceil((ingrCount - outputCount) / (double) item.factor);
|
||||
|
||||
if (shift > 0 && shift < minShift) {
|
||||
minShift = (int) shift;
|
||||
minRecipeIndex = item.recipeIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (minShift < Integer.MAX_VALUE) {
|
||||
request.multiplier.put(minRecipeIndex, request.multiplier.get(minRecipeIndex) + minShift);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private long calculateCount(CraftingChainRequest request, HashSet<CraftingChainItem> items) {
|
||||
return calculateCount(request, items, -1);
|
||||
}
|
||||
|
||||
private long calculateCount(CraftingChainRequest request, HashSet<CraftingChainItem> items, int recipeIndex) {
|
||||
long count = 0L;
|
||||
|
||||
if (items != null) {
|
||||
for (CraftingChainItem item : items) {
|
||||
if (item.recipeIndex != recipeIndex || recipeIndex == -1) {
|
||||
count += request.counts.get(item.guid) + item.factor * request.multiplier.get(item.recipeIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -28,6 +28,7 @@ import net.minecraft.entity.item.EntityItem;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.client.event.RenderWorldLastEvent;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import net.minecraftforge.event.world.WorldEvent;
|
||||
|
||||
import org.apache.commons.csv.CSVFormat;
|
||||
import org.apache.commons.csv.CSVParser;
|
||||
@@ -48,6 +49,8 @@ import cpw.mods.fml.common.FMLCommonHandler;
|
||||
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
|
||||
import cpw.mods.fml.common.gameevent.TickEvent;
|
||||
import cpw.mods.fml.common.gameevent.TickEvent.Phase;
|
||||
import cpw.mods.fml.relauncher.Side;
|
||||
import cpw.mods.fml.relauncher.SideOnly;
|
||||
|
||||
public class ClientHandler {
|
||||
|
||||
@@ -145,6 +148,7 @@ public class ClientHandler {
|
||||
public static void preInit() {
|
||||
loadSerialHandlers();
|
||||
loadHeightHackHandlers();
|
||||
loadHiddenHandlers();
|
||||
ItemInfo.preInit();
|
||||
StackInfo.loadGuidFilters();
|
||||
}
|
||||
@@ -197,6 +201,30 @@ public class ClientHandler {
|
||||
}
|
||||
}
|
||||
|
||||
public static void loadHiddenHandlers() {
|
||||
File file = NEIClientConfig.hiddenHandlersFile;
|
||||
if (!file.exists()) {
|
||||
try (FileWriter writer = new FileWriter(file)) {
|
||||
NEIClientConfig.logger.info("Creating default hidden handlers list {}", file);
|
||||
URL defaultHeightHackHandlersResource = ClientHandler.class
|
||||
.getResource("/assets/nei/cfg/hiddenhandlers.cfg");
|
||||
if (defaultHeightHackHandlersResource != null) {
|
||||
IOUtils.copy(defaultHeightHackHandlersResource.openStream(), writer);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
NEIClientConfig.logger.error("Failed to save default hidden handlers list to file {}", file, e);
|
||||
}
|
||||
}
|
||||
|
||||
try (FileReader reader = new FileReader(file)) {
|
||||
NEIClientConfig.logger.info("Loading hidden handlers from file {}", file);
|
||||
NEIClientConfig.hiddenHandlers = IOUtils.readLines(reader).stream().filter((line) -> !line.startsWith("#"))
|
||||
.collect(Collectors.toCollection(HashSet::new));
|
||||
} catch (IOException e) {
|
||||
NEIClientConfig.logger.error("Failed to load hidden handlers from file {}", file, e);
|
||||
}
|
||||
}
|
||||
|
||||
public static void load() {
|
||||
instance = new ClientHandler();
|
||||
|
||||
@@ -305,6 +333,15 @@ public class ClientHandler {
|
||||
if (NEIClientConfig.isEnabled()) WorldOverlayRenderer.render(event.partialTicks);
|
||||
}
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
@SubscribeEvent
|
||||
public void onWorldUnload(WorldEvent.Unload event) {
|
||||
Minecraft mc = Minecraft.getMinecraft();
|
||||
if (event.world == mc.theWorld) {
|
||||
NEIClientConfig.unloadWorld();
|
||||
}
|
||||
}
|
||||
|
||||
public void loadWorld(World world, boolean fromServer) {
|
||||
if (world != lastworld) {
|
||||
SMPmagneticItems.clear();
|
||||
|
||||
@@ -81,7 +81,6 @@ public class ContainerPotionCreator extends ContainerExtended {
|
||||
public void markDirty() {
|
||||
super.markDirty();
|
||||
NEIClientConfig.global.nbt.setTag("potionStore", tag);
|
||||
NEIClientConfig.global.saveNBT();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -62,7 +62,6 @@ public class GuiEnchantmentModifier extends GuiContainer {
|
||||
|
||||
public static void toggleEnchantmentValidation() {
|
||||
NEIClientConfig.world.nbt.setBoolean("validateenchantments", !validateEnchantments());
|
||||
NEIClientConfig.world.saveNBT();
|
||||
}
|
||||
|
||||
protected void actionPerformed(GuiButton guibutton) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package codechicken.nei;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
@@ -84,6 +85,10 @@ public class ItemList {
|
||||
this.filters = filters;
|
||||
}
|
||||
|
||||
public AllMultiItemFilter(ItemFilter... filters) {
|
||||
this(Arrays.asList(filters));
|
||||
}
|
||||
|
||||
public AllMultiItemFilter() {
|
||||
this(new LinkedList<>());
|
||||
}
|
||||
@@ -91,7 +96,7 @@ public class ItemList {
|
||||
@Override
|
||||
public boolean matches(ItemStack item) {
|
||||
for (ItemFilter filter : filters) try {
|
||||
if (!filter.matches(item)) return false;
|
||||
if (filter != null && !filter.matches(item)) return false;
|
||||
} catch (Exception e) {
|
||||
NEIClientConfig.logger.error("Exception filtering " + item + " with " + filter, e);
|
||||
}
|
||||
@@ -254,7 +259,7 @@ public class ItemList {
|
||||
|
||||
try {
|
||||
filtered = ItemList.forkJoinPool.submit(
|
||||
() -> items.parallelStream().filter(PresetsWidget::matches).filter(filter::matches)
|
||||
() -> items.parallelStream().filter(filter::matches)
|
||||
.collect(Collectors.toCollection(ArrayList::new)))
|
||||
.get();
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
|
||||
@@ -64,18 +64,18 @@ public class ItemPanel extends PanelWidget {
|
||||
if (newItems != null) {
|
||||
realItems = newItems;
|
||||
newItems = null;
|
||||
onGridChanged();
|
||||
onItemsChanged();
|
||||
}
|
||||
|
||||
super.refresh(gui);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void drawSlotOutline(@Nullable ItemPanelSlot focused, int slotIdx, Rectangle4i rect) {
|
||||
protected void beforeDrawSlot(@Nullable ItemPanelSlot focused, int slotIdx, Rectangle4i rect) {
|
||||
if (PresetsWidget.inEditMode()) {
|
||||
if (!PresetsWidget.isHidden(getItem(slotIdx))) drawRect(rect.x, rect.y, rect.w, rect.h, 0xee555555);
|
||||
} else {
|
||||
super.drawSlotOutline(focused, slotIdx, rect);
|
||||
super.beforeDrawSlot(focused, slotIdx, rect);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -142,7 +142,7 @@ public class ItemPanel extends PanelWidget {
|
||||
}
|
||||
|
||||
public String getLabelText() {
|
||||
return String.format("(%d/%d)", getPage(), Math.max(1, getNumPages()));
|
||||
return String.format("%d/%d", getPage(), Math.max(1, getNumPages()));
|
||||
}
|
||||
|
||||
protected String getPositioningSettingName() {
|
||||
|
||||
@@ -203,6 +203,11 @@ public class ItemStackMap<T> {
|
||||
return map == null ? null : map.get(key);
|
||||
}
|
||||
|
||||
public T getOrDefault(ItemStack key, T defaultValue) {
|
||||
T e = get(key);
|
||||
return e == null ? defaultValue : e;
|
||||
}
|
||||
|
||||
public void put(ItemStack key, T value) {
|
||||
if (key == null || key.getItem() == null) return;
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package codechicken.nei;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
@@ -27,6 +29,11 @@ public class ItemStackSet extends ItemStackMap<ItemStack> implements ItemFilter
|
||||
put(item, item);
|
||||
}
|
||||
|
||||
public ItemStackSet addAll(List<ItemStack> items) {
|
||||
for (ItemStack item : items) add(item);
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean contains(ItemStack item) {
|
||||
return get(item) != null;
|
||||
}
|
||||
|
||||
@@ -1,37 +1,27 @@
|
||||
package codechicken.nei;
|
||||
|
||||
import static codechicken.lib.gui.GuiDraw.drawRect;
|
||||
import static codechicken.lib.gui.GuiDraw.getMousePosition;
|
||||
|
||||
import java.awt.Point;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.GuiButton;
|
||||
import net.minecraft.client.gui.ScaledResolution;
|
||||
import net.minecraft.client.gui.inventory.GuiContainer;
|
||||
import net.minecraft.client.renderer.OpenGlHelper;
|
||||
import net.minecraft.client.renderer.RenderHelper;
|
||||
import net.minecraft.client.renderer.Tessellator;
|
||||
import net.minecraft.client.shader.Framebuffer;
|
||||
import net.minecraft.inventory.Slot;
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL12;
|
||||
|
||||
import codechicken.lib.vec.Rectangle4i;
|
||||
import codechicken.nei.ItemPanel.ItemPanelSlot;
|
||||
import codechicken.nei.api.GuiInfo;
|
||||
import codechicken.nei.guihook.GuiContainerManager;
|
||||
import codechicken.nei.recipe.BookmarkRecipeId;
|
||||
import codechicken.nei.recipe.GuiCraftingRecipe;
|
||||
import codechicken.nei.recipe.GuiRecipe;
|
||||
import codechicken.nei.recipe.StackInfo;
|
||||
|
||||
public class ItemsGrid {
|
||||
@@ -53,7 +43,7 @@ public class ItemsGrid {
|
||||
|
||||
protected int rows;
|
||||
protected int columns;
|
||||
protected boolean showRecipeTooltips = false;
|
||||
protected List<Integer> gridMask = null;
|
||||
|
||||
protected boolean[] invalidSlotMap;
|
||||
|
||||
@@ -79,7 +69,7 @@ public class ItemsGrid {
|
||||
public int indexOf(ItemStack stackA, boolean useNBT) {
|
||||
|
||||
for (int idx = 0; idx < realItems.size(); idx++) {
|
||||
if (StackInfo.equalItemAndNBT(stackA, getItem(idx), useNBT)) {
|
||||
if (StackInfo.equalItemAndNBT(stackA, realItems.get(idx), useNBT)) {
|
||||
return idx;
|
||||
}
|
||||
}
|
||||
@@ -116,6 +106,10 @@ public class ItemsGrid {
|
||||
return columns;
|
||||
}
|
||||
|
||||
public int getLastRowIndex() {
|
||||
return this.columns > 0 ? (int) Math.ceil((float) this.getMask().size() / this.columns) - 1 : 0;
|
||||
}
|
||||
|
||||
public void setGridSize(int mleft, int mtop, int w, int h) {
|
||||
marginLeft = mleft;
|
||||
marginTop = mtop;
|
||||
@@ -159,10 +153,11 @@ public class ItemsGrid {
|
||||
|
||||
protected void onGridChanged() {
|
||||
refreshBuffer = true;
|
||||
this.gridMask = null;
|
||||
}
|
||||
|
||||
public void setShowRecipeTooltips(boolean show) {
|
||||
this.showRecipeTooltips = show;
|
||||
protected void onItemsChanged() {
|
||||
onGridChanged();
|
||||
}
|
||||
|
||||
public void refresh(GuiContainer gui) {
|
||||
@@ -198,9 +193,9 @@ public class ItemsGrid {
|
||||
|
||||
for (int r = 0; r < rows; r++) {
|
||||
final int idx = columns * r + c;
|
||||
if (GuiInfo.hideItemPanelSlot(gui, getSlotRect(r, c)) && idx >= 0
|
||||
&& idx < invalidSlotMap.length
|
||||
&& !invalidSlotMap[idx]) {
|
||||
if (idx >= 0 && idx < invalidSlotMap.length
|
||||
&& !invalidSlotMap[idx]
|
||||
&& GuiInfo.hideItemPanelSlot(gui, getSlotRect(r, c))) {
|
||||
invalidSlotMap[idx] = true;
|
||||
validColumn = false;
|
||||
perPage--;
|
||||
@@ -238,154 +233,51 @@ public class ItemsGrid {
|
||||
}
|
||||
|
||||
protected List<Integer> getMask() {
|
||||
List<Integer> mask = new ArrayList<>();
|
||||
|
||||
int idx = page * perPage;
|
||||
for (int i = 0; i < rows * columns && idx < size(); i++) {
|
||||
mask.add(isInvalidSlot(i) ? null : idx++);
|
||||
if (this.gridMask == null) {
|
||||
this.gridMask = new ArrayList<>();
|
||||
int idx = page * perPage;
|
||||
|
||||
for (int i = 0; i < rows * columns && idx < size(); i++) {
|
||||
this.gridMask.add(isInvalidSlot(i) ? null : idx++);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return mask;
|
||||
return this.gridMask;
|
||||
}
|
||||
|
||||
private void drawSlotOutlines(int mousex, int mousey) {
|
||||
ItemPanelSlot focused = getSlotMouseOver(mousex, mousey);
|
||||
private void beforeDrawItems(int mousex, int mousey, @Nullable ItemPanelSlot focused) {
|
||||
|
||||
final List<Integer> mask = getMask();
|
||||
|
||||
for (int i = 0; i < mask.size(); i++) {
|
||||
if (mask.get(i) != null) {
|
||||
drawSlotOutline(focused, mask.get(i), getSlotRect(i));
|
||||
beforeDrawSlot(focused, mask.get(i), getSlotRect(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int recipeTooltipSlotIdx = -1;
|
||||
private int recipeTooltipLines = 2;
|
||||
private Runnable recipeTooltipUpdater = null;
|
||||
private GuiRecipe<?> recipeTooltipGui = null;
|
||||
|
||||
public void update() {
|
||||
if (recipeTooltipUpdater != null) {
|
||||
recipeTooltipUpdater.run();
|
||||
recipeTooltipUpdater = null;
|
||||
}
|
||||
if (recipeTooltipGui != null) {
|
||||
recipeTooltipGui.updateAsTooltip();
|
||||
}
|
||||
}
|
||||
|
||||
private static <T> List<T> listOrEmptyList(final List<T> listOrNull) {
|
||||
return listOrNull == null ? Collections.emptyList() : listOrNull;
|
||||
}
|
||||
|
||||
private void drawRecipeTooltip(int mousex, int mousey, List<String> itemTooltip) {
|
||||
if (!NEIClientConfig.isLoaded()) {
|
||||
return;
|
||||
}
|
||||
|
||||
final Minecraft mc = Minecraft.getMinecraft();
|
||||
ItemPanelSlot focused = getSlotMouseOver(mousex, mousey);
|
||||
if (focused == null) {
|
||||
recipeTooltipSlotIdx = -1;
|
||||
recipeTooltipGui = null;
|
||||
return;
|
||||
}
|
||||
private void afterDrawItems(int mousex, int mousey, @Nullable ItemPanelSlot focused) {
|
||||
final List<Integer> mask = getMask();
|
||||
|
||||
int slotIdx = -1;
|
||||
for (int i = 0; i < mask.size(); i++) {
|
||||
if (mask.get(i) == null) {
|
||||
continue;
|
||||
if (mask.get(i) != null) {
|
||||
afterDrawSlot(focused, mask.get(i), getSlotRect(i));
|
||||
}
|
||||
if (focused.slotIndex != mask.get(i)) {
|
||||
continue;
|
||||
}
|
||||
slotIdx = i;
|
||||
break;
|
||||
}
|
||||
if (slotIdx == -1) {
|
||||
recipeTooltipSlotIdx = -1;
|
||||
recipeTooltipGui = null;
|
||||
return;
|
||||
}
|
||||
|
||||
final Point mouseover = getMousePosition();
|
||||
final ItemPanelSlot panelSlot = ItemPanels.bookmarkPanel.getSlotMouseOver(mouseover.x, mouseover.y);
|
||||
final BookmarkRecipeId recipeId;
|
||||
if (panelSlot != null) {
|
||||
recipeId = ItemPanels.bookmarkPanel.getBookmarkRecipeId(panelSlot.slotIndex);
|
||||
} else {
|
||||
recipeId = ItemPanels.bookmarkPanel.getBookmarkRecipeId(focused.item);
|
||||
}
|
||||
if (recipeId == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (slotIdx != recipeTooltipSlotIdx) {
|
||||
recipeTooltipSlotIdx = slotIdx;
|
||||
recipeTooltipGui = null;
|
||||
recipeTooltipUpdater = () -> {
|
||||
recipeTooltipGui = GuiCraftingRecipe.createRecipeGui("item", false, false, false, focused.item);
|
||||
if (recipeTooltipGui != null) {
|
||||
recipeTooltipGui.limitToOneRecipe();
|
||||
recipeTooltipGui.initGui(true);
|
||||
recipeTooltipGui.guiTop = 0;
|
||||
recipeTooltipGui.guiLeft = 0;
|
||||
}
|
||||
recipeTooltipLines = Math.max(1, itemTooltip.size());
|
||||
};
|
||||
}
|
||||
if (recipeTooltipGui == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
GL11.glPushMatrix();
|
||||
final float tooltipYOffset;
|
||||
if (mousey - marginTop > height / 2) {
|
||||
tooltipYOffset = mousey - recipeTooltipGui.getHeightAsWidget() + 8;
|
||||
} else {
|
||||
tooltipYOffset = mousey + ((recipeTooltipLines < 2) ? 1 : 3 + ((recipeTooltipLines - 1) * 10));
|
||||
}
|
||||
GL11.glTranslatef(mousex, tooltipYOffset, 500);
|
||||
|
||||
final GuiContainer gui;
|
||||
if (mc.currentScreen instanceof GuiRecipe) {
|
||||
gui = ((GuiRecipe<?>) mc.currentScreen).firstGui;
|
||||
} else if (mc.currentScreen instanceof GuiContainer) {
|
||||
gui = (GuiContainer) mc.currentScreen;
|
||||
} else {
|
||||
gui = null;
|
||||
}
|
||||
GL11.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS);
|
||||
RenderHelper.disableStandardItemLighting();
|
||||
recipeTooltipGui.drawGuiContainerBackgroundLayer(0.0f, -100, -100);
|
||||
GL11.glPopAttrib();
|
||||
if (recipeTooltipGui.slotcontainer != null) {
|
||||
GL11.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS);
|
||||
RenderHelper.enableGUIStandardItemLighting();
|
||||
GL11.glEnable(GL12.GL_RESCALE_NORMAL);
|
||||
@SuppressWarnings("unchecked")
|
||||
List<Slot> slots = (List<Slot>) recipeTooltipGui.slotcontainer.inventorySlots;
|
||||
for (Slot slot : slots) {
|
||||
if (slot != null && slot.getStack() != null) {
|
||||
GuiContainerManager.drawItem(slot.xDisplayPosition, slot.yDisplayPosition, slot.getStack());
|
||||
}
|
||||
}
|
||||
GL11.glPopAttrib();
|
||||
}
|
||||
recipeTooltipGui.drawGuiContainerForegroundLayer(-100, -100);
|
||||
for (GuiButton btn : recipeTooltipGui.getOverlayButtons()) {
|
||||
btn.drawButton(mc, -100, -100);
|
||||
}
|
||||
GL11.glPopMatrix();
|
||||
}
|
||||
|
||||
protected void drawSlotOutline(@Nullable ItemPanelSlot focused, int slotIdx, Rectangle4i rect) {
|
||||
public void update() {}
|
||||
|
||||
protected void beforeDrawSlot(@Nullable ItemPanelSlot focused, int slotIdx, Rectangle4i rect) {
|
||||
if (focused != null && focused.slotIndex == slotIdx) {
|
||||
drawRect(rect.x, rect.y, rect.w, rect.h, 0xee555555); // highlight
|
||||
}
|
||||
}
|
||||
|
||||
protected void afterDrawSlot(@Nullable ItemPanelSlot focused, int slotIdx, Rectangle4i rect) {}
|
||||
|
||||
private void blitExistingBuffer() {
|
||||
Minecraft minecraft = Minecraft.getMinecraft();
|
||||
GL11.glEnable(GL11.GL_BLEND);
|
||||
@@ -427,12 +319,18 @@ public class ItemsGrid {
|
||||
GuiContainerManager.disableMatrixStackLogging();
|
||||
}
|
||||
|
||||
protected boolean shouldCacheItemRendering() {
|
||||
return NEIClientConfig.shouldCacheItemRendering();
|
||||
}
|
||||
|
||||
public void draw(int mousex, int mousey) {
|
||||
if (getPerPage() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (NEIClientConfig.shouldCacheItemRendering()) {
|
||||
final ItemPanelSlot focused = getSlotMouseOver(mousex, mousey);
|
||||
|
||||
if (shouldCacheItemRendering()) {
|
||||
|
||||
if (refreshBuffer) {
|
||||
Minecraft minecraft = Minecraft.getMinecraft();
|
||||
@@ -457,23 +355,17 @@ public class ItemsGrid {
|
||||
refreshBuffer = false;
|
||||
}
|
||||
|
||||
drawSlotOutlines(mousex, mousey);
|
||||
beforeDrawItems(mousex, mousey, focused);
|
||||
blitExistingBuffer();
|
||||
} else {
|
||||
drawSlotOutlines(mousex, mousey);
|
||||
beforeDrawItems(mousex, mousey, focused);
|
||||
drawItems();
|
||||
}
|
||||
|
||||
afterDrawItems(mousex, mousey, focused);
|
||||
}
|
||||
|
||||
public void postDrawTooltips(int mousex, int mousey, List<String> tooltip) {
|
||||
if (NEIClientConfig.showRecipeTooltips() && showRecipeTooltips) {
|
||||
try {
|
||||
drawRecipeTooltip(mousex, mousey, tooltip);
|
||||
} catch (Exception e) {
|
||||
NEIClientConfig.logger.warn("Cannot draw recipe tooltip", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
public void postDrawTooltips(int mousex, int mousey, List<String> tooltip) {}
|
||||
|
||||
public void setVisible() {
|
||||
if (getItems().isEmpty() && getMessageOnEmpty() != null) {
|
||||
@@ -510,16 +402,20 @@ public class ItemsGrid {
|
||||
}
|
||||
|
||||
public boolean contains(int px, int py) {
|
||||
final Rectangle4i rect = new Rectangle4i(
|
||||
marginLeft + paddingLeft,
|
||||
marginTop,
|
||||
columns * SLOT_SIZE,
|
||||
rows * SLOT_SIZE);
|
||||
|
||||
if (!(new Rectangle4i(marginLeft + paddingLeft, marginTop, columns * SLOT_SIZE, height)).contains(px, py)) {
|
||||
if (!rect.contains(px, py)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final int r = (int) ((py - marginTop) / SLOT_SIZE);
|
||||
final int c = (int) ((px - marginLeft - paddingLeft) / SLOT_SIZE);
|
||||
final int slt = columns * r + c;
|
||||
|
||||
return r >= rows || c >= columns || !isInvalidSlot(slt);
|
||||
return !isInvalidSlot(columns * r + c);
|
||||
}
|
||||
|
||||
public String getMessageOnEmpty() {
|
||||
|
||||
@@ -14,7 +14,6 @@ import static codechicken.nei.NEIClientConfig.isEnabled;
|
||||
import static codechicken.nei.NEIClientConfig.isHidden;
|
||||
import static codechicken.nei.NEIClientConfig.showIDs;
|
||||
import static codechicken.nei.NEIClientConfig.toggleBooleanSetting;
|
||||
import static codechicken.nei.NEIClientConfig.world;
|
||||
import static codechicken.nei.NEIClientUtils.cycleGamemode;
|
||||
import static codechicken.nei.NEIClientUtils.decreaseSlotStack;
|
||||
import static codechicken.nei.NEIClientUtils.deleteEverything;
|
||||
@@ -226,10 +225,6 @@ public class LayoutManager implements IContainerInputHandler, IContainerTooltipH
|
||||
return true;
|
||||
}
|
||||
|
||||
if (NEIClientConfig.isKeyHashDown("gui.bookmark_pull_items")) {
|
||||
return bookmarkPanel.pullBookmarkItems();
|
||||
}
|
||||
|
||||
if (isEnabled() && !isHidden()) {
|
||||
for (Widget widget : controlWidgets) if (inputFocused == null) widget.lastKeyTyped(keyID, keyChar);
|
||||
}
|
||||
@@ -286,7 +281,7 @@ public class LayoutManager implements IContainerInputHandler, IContainerTooltipH
|
||||
|
||||
@Override
|
||||
public void postRenderTooltips(GuiContainer gui, int mousex, int mousey, List<String> tooltip) {
|
||||
if (!isHidden() && isEnabled()) {
|
||||
if (!isHidden() && isEnabled() && GuiContainerManager.shouldShowTooltip(gui)) {
|
||||
for (Widget widget : drawWidgets) widget.postDrawTooltips(mousex, mousey, tooltip);
|
||||
}
|
||||
}
|
||||
@@ -337,6 +332,8 @@ public class LayoutManager implements IContainerInputHandler, IContainerTooltipH
|
||||
|
||||
if (gui.guiLeft - 4 < 76) visiblity.showWidgets = false;
|
||||
|
||||
if (!itemsLoaded) visiblity.showPresetsDropdown = false;
|
||||
|
||||
try {
|
||||
GuiInfo.readLock.lock();
|
||||
GuiInfo.guiHandlers.forEach(handler -> handler.modifyVisiblity(gui, visiblity));
|
||||
@@ -735,7 +732,7 @@ public class LayoutManager implements IContainerInputHandler, IContainerTooltipH
|
||||
|
||||
@Override
|
||||
public boolean shouldShowTooltip(GuiContainer gui) {
|
||||
return itemPanel.draggedStack == null && bookmarkPanel.sortedStackIndex == -1;
|
||||
return itemPanel.draggedStack == null && !bookmarkPanel.inEditingState();
|
||||
}
|
||||
|
||||
/** Note: this method isn't actually used by this mod, but NEI add-ons might need it. */
|
||||
@@ -758,17 +755,21 @@ public class LayoutManager implements IContainerInputHandler, IContainerTooltipH
|
||||
|
||||
@Override
|
||||
public void renderSlotOverlay(GuiContainer window, Slot slot) {
|
||||
ItemStack item = slot.getStack();
|
||||
if (world.nbt.getBoolean("searchinventories") && (item == null ? !getSearchExpression().equals("")
|
||||
: !((SearchField) searchField).getFilter().matches(item))) {
|
||||
GL11.glDisable(GL11.GL_LIGHTING);
|
||||
GL11.glDisable(GL11.GL_DEPTH_TEST);
|
||||
GL11.glTranslatef(0, 0, 150);
|
||||
drawRect(slot.xDisplayPosition, slot.yDisplayPosition, 16, 16, 0x80000000);
|
||||
GL11.glTranslatef(0, 0, -150);
|
||||
GL11.glEnable(GL11.GL_LIGHTING);
|
||||
GL11.glEnable(GL11.GL_DEPTH_TEST);
|
||||
|
||||
if (SearchField.searchInventories()) {
|
||||
ItemStack item = slot.getStack();
|
||||
|
||||
if (item == null ? !getSearchExpression().equals("") : !searchField.getFilter().matches(item)) {
|
||||
GL11.glDisable(GL11.GL_LIGHTING);
|
||||
GL11.glDisable(GL11.GL_DEPTH_TEST);
|
||||
GL11.glTranslatef(0, 0, 150);
|
||||
drawRect(slot.xDisplayPosition, slot.yDisplayPosition, 16, 16, 0x80000000);
|
||||
GL11.glTranslatef(0, 0, -150);
|
||||
GL11.glEnable(GL11.GL_LIGHTING);
|
||||
GL11.glEnable(GL11.GL_DEPTH_TEST);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static void drawIcon(int x, int y, Image image) {
|
||||
|
||||
@@ -73,6 +73,7 @@ public class NEIClientConfig {
|
||||
public static final File serialHandlersFile = new File(configDir, "serialhandlers.cfg");
|
||||
public static final File heightHackHandlersFile = new File(configDir, "heighthackhandlers.cfg");
|
||||
public static final File handlerOrderingFile = new File(configDir, "handlerordering.csv");
|
||||
public static final File hiddenHandlersFile = new File(configDir, "hiddenhandlers.csv");
|
||||
|
||||
@Deprecated
|
||||
public static File bookmarkFile;
|
||||
@@ -84,6 +85,9 @@ public class NEIClientConfig {
|
||||
// We use regex here so that we can apply the height hack to entire mods with one entry.
|
||||
public static HashSet<Pattern> heightHackHandlerRegex = new HashSet<>();
|
||||
|
||||
// Set of handler Name or Id of handlers that need hide.
|
||||
public static HashSet<String> hiddenHandlers = new HashSet<>();
|
||||
|
||||
// Map of handler ID to sort order.
|
||||
// Handlers will be sorted in ascending order, so smaller numbers show up earlier.
|
||||
// Any handler not in the map will be assigned to 0, and negative numbers are fine.
|
||||
@@ -237,14 +241,14 @@ public class NEIClientConfig {
|
||||
|
||||
tag.getTag("inventory.bookmarksEnabled").setComment("Enable/disable bookmarks").getBooleanValue(true);
|
||||
API.addOption(new OptionToggleButton("inventory.bookmarksEnabled", true));
|
||||
tag.getTag("inventory.useNBTInBookmarks").setComment("Use NBT in Bookmarks").getBooleanValue(true);
|
||||
API.addOption(new OptionToggleButton("inventory.useNBTInBookmarks", true));
|
||||
|
||||
tag.getTag("inventory.bookmarksAnimationEnabled").setComment("REI Style Animation in Bookmarks")
|
||||
.getBooleanValue(true);
|
||||
API.addOption(new OptionToggleButton("inventory.bookmarksAnimationEnabled", true));
|
||||
tag.getTag("inventory.recipeTooltipsEnabled").setComment("Show recipe tooltips in Bookmarks")
|
||||
.getBooleanValue(true);
|
||||
API.addOption(new OptionToggleButton("inventory.recipeTooltipsEnabled", true));
|
||||
|
||||
tag.getTag("inventory.recipeTooltipsMode").setComment("Show recipe tooltips in Bookmarks").getIntValue(1);
|
||||
API.addOption(new OptionCycled("inventory.recipeTooltipsMode", 4, true));
|
||||
|
||||
tag.getTag("inventory.showRecipeMarker").setComment("Show Recipe Marker").getBooleanValue(false);
|
||||
API.addOption(new OptionToggleButton("inventory.showRecipeMarker", true));
|
||||
|
||||
@@ -256,9 +260,11 @@ public class NEIClientConfig {
|
||||
|
||||
tag.getTag("inventory.jei_style_tabs").setComment("Enable/disable JEI Style Tabs").getBooleanValue(true);
|
||||
API.addOption(new OptionToggleButtonBoubs("inventory.jei_style_tabs", true));
|
||||
|
||||
tag.getTag("inventory.jei_style_item_presence_overlay")
|
||||
.setComment("Enable/disable JEI Style item presence overlay on ?-hover").getBooleanValue(true);
|
||||
API.addOption(new OptionToggleButton("inventory.jei_style_item_presence_overlay", true));
|
||||
|
||||
tag.getTag("inventory.jei_style_recipe_catalyst").setComment("Enable/disable JEI Style Recipe Catalysts")
|
||||
.getBooleanValue(true);
|
||||
API.addOption(new OptionToggleButton("inventory.jei_style_recipe_catalyst", true));
|
||||
@@ -355,6 +361,7 @@ public class NEIClientConfig {
|
||||
"gui.bookmark_recipe_count",
|
||||
Keyboard.KEY_A + NEIClientUtils.SHIFT_HASH + NEIClientUtils.CTRL_HASH);
|
||||
API.addHashBind("gui.bookmark_pull_items", Keyboard.KEY_V);
|
||||
API.addHashBind("gui.bookmark_pull_items_ingredients", Keyboard.KEY_V + NEIClientUtils.SHIFT_HASH);
|
||||
API.addHashBind("gui.overlay", Keyboard.KEY_S);
|
||||
API.addHashBind("gui.overlay_use", Keyboard.KEY_S + NEIClientUtils.SHIFT_HASH);
|
||||
API.addHashBind("gui.overlay_hide", Keyboard.KEY_S + NEIClientUtils.CTRL_HASH);
|
||||
@@ -424,6 +431,16 @@ public class NEIClientConfig {
|
||||
world.saveNBT();
|
||||
}
|
||||
|
||||
public static void unloadWorld() {
|
||||
if (ItemPanels.bookmarkPanel != null) {
|
||||
ItemPanels.bookmarkPanel.saveBookmarks();
|
||||
}
|
||||
|
||||
if (world != null) {
|
||||
world.saveNBT();
|
||||
}
|
||||
}
|
||||
|
||||
public static int getKeyBinding(String string) {
|
||||
return getSetting("keys." + string).getIntValue(Keyboard.KEY_NONE);
|
||||
}
|
||||
@@ -556,16 +573,12 @@ public class NEIClientConfig {
|
||||
return !getBooleanSetting("inventory.bookmarksEnabled");
|
||||
}
|
||||
|
||||
public static boolean useNBTInBookmarks() {
|
||||
return getBooleanSetting("inventory.useNBTInBookmarks");
|
||||
}
|
||||
|
||||
public static boolean areBookmarksAnimated() {
|
||||
return getBooleanSetting("inventory.bookmarksAnimationEnabled");
|
||||
}
|
||||
|
||||
public static boolean showRecipeTooltips() {
|
||||
return getBooleanSetting("inventory.recipeTooltipsEnabled");
|
||||
public static int getRecipeTooltipsMode() {
|
||||
return getIntSetting("inventory.recipeTooltipsMode");
|
||||
}
|
||||
|
||||
public static boolean showRecipeMarker() {
|
||||
@@ -689,7 +702,6 @@ public class NEIClientConfig {
|
||||
|
||||
public static void setSearchExpression(String expression) {
|
||||
world.nbt.setString("search", expression);
|
||||
world.saveNBT();
|
||||
}
|
||||
|
||||
public static boolean isMouseScrollTransferEnabled() {
|
||||
|
||||
@@ -394,7 +394,6 @@ public class NEIClientUtils extends NEIServerUtils {
|
||||
|
||||
public static void setItemQuantity(int i) {
|
||||
world.nbt.setInteger("quantity", i);
|
||||
world.saveNBT();
|
||||
}
|
||||
|
||||
public static GuiContainer getGuiContainer() {
|
||||
|
||||
@@ -328,7 +328,7 @@ public abstract class PanelWidget extends Widget {
|
||||
ItemPanelSlot hoverSlot = getSlotMouseOver(mousex, mousey);
|
||||
|
||||
if (hoverSlot != null && hoverSlot.slotIndex == mouseDownSlot && draggedStack == null) {
|
||||
ItemStack item = hoverSlot.item;
|
||||
ItemStack item = hoverSlot.item.copy();
|
||||
|
||||
if (NEIController.manager.window instanceof GuiRecipe || !NEIClientConfig.canCheatItem(item)) {
|
||||
|
||||
|
||||
@@ -26,8 +26,11 @@ public class PositionedStack {
|
||||
relx = x;
|
||||
rely = y;
|
||||
|
||||
if (genPerms) generatePermutations();
|
||||
else setPermutationToRender(0);
|
||||
if (genPerms) {
|
||||
generatePermutations();
|
||||
} else {
|
||||
setPermutationToRender(0);
|
||||
}
|
||||
}
|
||||
|
||||
public PositionedStack(Object object, int x, int y) {
|
||||
@@ -77,10 +80,13 @@ public class PositionedStack {
|
||||
|
||||
public void setPermutationToRender(int index) {
|
||||
item = items[index].copy();
|
||||
if (item.getItem() == null) item = new ItemStack(Blocks.fire);
|
||||
else if (item.getItemDamage() == OreDictionary.WILDCARD_VALUE && item.getItem() != null
|
||||
&& item.getItem().isRepairable())
|
||||
item.setItemDamage(0);
|
||||
|
||||
if (item.getItem() == null) {
|
||||
item = new ItemStack(Blocks.fire);
|
||||
} else if (item.getItemDamage() == OreDictionary.WILDCARD_VALUE && item.getItem() != null
|
||||
&& item.getItem().isRepairable()) {
|
||||
item.setItemDamage(0);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean contains(ItemStack ingredient) {
|
||||
|
||||
@@ -6,6 +6,8 @@ import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
@@ -30,39 +32,55 @@ import codechicken.core.CommonUtils;
|
||||
import codechicken.core.gui.GuiScrollSlot;
|
||||
import codechicken.lib.gui.GuiDraw;
|
||||
import codechicken.lib.vec.Rectangle4i;
|
||||
import codechicken.nei.ItemList.ItemsLoadedCallback;
|
||||
import codechicken.nei.ItemPanel.ItemPanelSlot;
|
||||
import codechicken.nei.api.API;
|
||||
import codechicken.nei.api.IRecipeFilter;
|
||||
import codechicken.nei.api.IRecipeFilter.IRecipeFilterProvider;
|
||||
import codechicken.nei.api.ItemFilter;
|
||||
import codechicken.nei.api.ItemFilter.ItemFilterProvider;
|
||||
import codechicken.nei.recipe.GuiRecipe;
|
||||
import codechicken.nei.recipe.IRecipeHandler;
|
||||
import codechicken.nei.recipe.StackInfo;
|
||||
import codechicken.nei.util.NBTJson;
|
||||
import cpw.mods.fml.common.registry.GameRegistry;
|
||||
|
||||
public class PresetsWidget extends Widget {
|
||||
public class PresetsWidget extends Widget implements ItemFilterProvider, ItemsLoadedCallback, ItemFilter {
|
||||
|
||||
public static class PresetTag implements ItemFilter {
|
||||
protected static enum PresetTagState {
|
||||
|
||||
WHITELIST,
|
||||
BLACKLIST,
|
||||
BLACKLIST_PLUS;
|
||||
|
||||
public PresetTagState next() {
|
||||
if (this == PresetTagState.WHITELIST) return PresetTagState.BLACKLIST;
|
||||
if (this == PresetTagState.BLACKLIST) return PresetTagState.BLACKLIST_PLUS;
|
||||
if (this == PresetTagState.BLACKLIST_PLUS) return PresetTagState.WHITELIST;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
public static class PresetTag {
|
||||
|
||||
public String filename = null;
|
||||
public String displayName = "";
|
||||
public boolean whitelist = true;
|
||||
public HashSet<String> items;
|
||||
public PresetTagState state = PresetTagState.BLACKLIST;
|
||||
public ItemStackSet items;
|
||||
|
||||
public PresetTag(String displayName) {
|
||||
this(displayName, new HashSet<>(), false, null);
|
||||
this(displayName, null, PresetTagState.BLACKLIST, null);
|
||||
}
|
||||
|
||||
public PresetTag(String displayName, HashSet<String> items) {
|
||||
this(displayName, items, true, null);
|
||||
}
|
||||
|
||||
public PresetTag(String displayName, HashSet<String> items, boolean whitelist, String filename) {
|
||||
public PresetTag(String displayName, ItemStackSet items, PresetTagState state, String filename) {
|
||||
this.displayName = displayName;
|
||||
this.items = items != null ? items : new HashSet<>();
|
||||
this.whitelist = whitelist;
|
||||
this.items = items != null ? items : new ItemStackSet();
|
||||
this.state = state;
|
||||
this.filename = filename;
|
||||
}
|
||||
|
||||
public boolean matches(final ItemStack stack) {
|
||||
return items.contains(StackInfo.getItemStackGUID(stack)) == whitelist;
|
||||
return items.contains(stack) == (state == PresetTagState.WHITELIST);
|
||||
}
|
||||
|
||||
public static PresetTag loadFromFile(File file) {
|
||||
@@ -84,14 +102,18 @@ public class PresetsWidget extends Widget {
|
||||
final JsonParser parser = new JsonParser();
|
||||
final JsonObject metaObject = parser.parse(itemStrings.remove(0)).getAsJsonObject();
|
||||
final String displayName = metaObject.get("displayName").getAsString();
|
||||
final boolean whitelist = metaObject.get("whitelist").getAsBoolean();
|
||||
final HashSet<String> items = new HashSet<>();
|
||||
final PresetTagState state = metaObject.has("state")
|
||||
? PresetTagState.valueOf(metaObject.get("state").getAsString())
|
||||
: PresetTagState.BLACKLIST;
|
||||
final ItemStackSet items = new ItemStackSet();
|
||||
|
||||
for (String itemStr : itemStrings) {
|
||||
items.add(itemStr);
|
||||
for (ItemStack stack : ItemList.items) {
|
||||
if (itemStrings.contains(StackInfo.getItemStackGUID(stack))) {
|
||||
items.add(stack);
|
||||
}
|
||||
}
|
||||
|
||||
return new PresetTag(displayName, items, whitelist, file.getName());
|
||||
return new PresetTag(displayName, items, state, file.getName());
|
||||
} catch (Throwable th) {
|
||||
NEIClientConfig.logger.error("Failed to load presets ItemStack from file", file);
|
||||
}
|
||||
@@ -127,12 +149,16 @@ public class PresetsWidget extends Widget {
|
||||
final JsonObject row = new JsonObject();
|
||||
|
||||
row.add("displayName", new JsonPrimitive(displayName));
|
||||
row.add("whitelist", new JsonPrimitive(whitelist));
|
||||
row.add("state", new JsonPrimitive(state.toString()));
|
||||
|
||||
strings.add(NBTJson.toJson(row));
|
||||
|
||||
try {
|
||||
strings.addAll(items);
|
||||
|
||||
for (ItemStack stack : items.values()) {
|
||||
strings.add(StackInfo.getItemStackGUID(stack));
|
||||
}
|
||||
|
||||
} catch (JsonSyntaxException e) {
|
||||
NEIClientConfig.logger.error("Failed to stringify presets ItemStack to json string");
|
||||
}
|
||||
@@ -146,9 +172,8 @@ public class PresetsWidget extends Widget {
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public PresetTag copy() {
|
||||
return new PresetTag(displayName, (HashSet) items.clone(), whitelist, null);
|
||||
return new PresetTag(displayName, new ItemStackSet().addAll(items.values()), state, null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -290,7 +315,7 @@ public class PresetsWidget extends Widget {
|
||||
selected.remove(tag);
|
||||
tag.deleteFile();
|
||||
} else if (direction.contains(mx, my)) {
|
||||
tag.whitelist = !tag.whitelist;
|
||||
tag.state = tag.state.next();
|
||||
tag.saveToFile();
|
||||
}
|
||||
|
||||
@@ -299,6 +324,7 @@ public class PresetsWidget extends Widget {
|
||||
PresetsWidget.openListBox = !presets.isEmpty()
|
||||
&& (NEIClientUtils.controlKey() || NEIClientUtils.shiftKey() || !option.contains(mx, my));
|
||||
ItemList.updateFilter.restart();
|
||||
PresetsRecipeFilter.blacklist = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -319,13 +345,22 @@ public class PresetsWidget extends Widget {
|
||||
|
||||
final String displayName = NEIClientUtils
|
||||
.cropText(PresetsWidget.fontRenderer, tag.displayName, option.w - 6);
|
||||
final String dirName = tag.whitelist ? translate("presets.whitelist.label")
|
||||
: translate("presets.blacklist.label");
|
||||
String stateLabel = translate("presets.blacklist.label");
|
||||
|
||||
if (tag.state == PresetTagState.WHITELIST) {
|
||||
stateLabel = translate("presets.whitelist.label");
|
||||
} else if (tag.state == PresetTagState.BLACKLIST_PLUS) {
|
||||
stateLabel = translate("presets.blacklistPlus.label");
|
||||
}
|
||||
|
||||
// blacklist or whitelist
|
||||
LayoutManager.getLayoutStyle()
|
||||
.drawSubsetTag(null, direction.x, direction.y, direction.w, direction.h, directionState, false);
|
||||
GuiDraw.drawString(dirName, direction.x + 6, direction.y + 5, directionState == 2 ? 0xFFE0E0E0 : 0xFFFFA0);
|
||||
GuiDraw.drawString(
|
||||
stateLabel,
|
||||
direction.x + 6,
|
||||
direction.y + 5,
|
||||
directionState == 2 ? 0xFFE0E0E0 : 0xFFFFA0);
|
||||
|
||||
// option name
|
||||
LayoutManager.getLayoutStyle()
|
||||
@@ -433,6 +468,70 @@ public class PresetsWidget extends Widget {
|
||||
}
|
||||
}
|
||||
|
||||
protected static class PresetsRecipeFilter implements IRecipeFilterProvider, IRecipeFilter {
|
||||
|
||||
protected static ItemStackSet blacklist;
|
||||
|
||||
public IRecipeFilter getFilter() {
|
||||
|
||||
if (PresetsWidget.edit != null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (blacklist == null) {
|
||||
blacklist = new ItemStackSet();
|
||||
|
||||
for (PresetTag tag : listbox.getSelected()) {
|
||||
if (tag.state == PresetTagState.BLACKLIST_PLUS) {
|
||||
blacklist.addAll(tag.items.values());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return blacklist.isEmpty() ? null : this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(IRecipeHandler handler, List<PositionedStack> ingredients, PositionedStack result,
|
||||
List<PositionedStack> others) {
|
||||
|
||||
if (matchPositionedStack(ingredients, false)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (result != null && matchPositionedStack(result)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!others.isEmpty() && matchPositionedStack(others, true)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return result == null && others.isEmpty();
|
||||
}
|
||||
|
||||
private boolean matchPositionedStack(List<PositionedStack> items, boolean dir) {
|
||||
for (PositionedStack pStack : items) {
|
||||
if (matchPositionedStack(pStack) == dir) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean matchPositionedStack(PositionedStack pStack) {
|
||||
for (ItemStack stack : pStack.items) {
|
||||
if (!blacklist.contains(stack)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected static final FontRenderer fontRenderer = Minecraft.getMinecraft().fontRenderer;
|
||||
protected static SubsetListBox listbox = new SubsetListBox();
|
||||
protected static File presetsDir;
|
||||
@@ -517,7 +616,7 @@ public class PresetsWidget extends Widget {
|
||||
|
||||
public boolean onButtonPress(boolean rightclick) {
|
||||
if (!rightclick && edit != null) {
|
||||
edit.whitelist = !edit.whitelist;
|
||||
edit.state = edit.state.next();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -526,20 +625,54 @@ public class PresetsWidget extends Widget {
|
||||
|
||||
@Override
|
||||
public String getRenderLabel() {
|
||||
return edit != null && edit.whitelist ? translate("presets.whitelist.label")
|
||||
: translate("presets.blacklist.label");
|
||||
|
||||
if (edit == null || edit.state == PresetTagState.BLACKLIST) {
|
||||
return translate("presets.blacklist.label");
|
||||
} else if (edit.state == PresetTagState.WHITELIST) {
|
||||
return translate("presets.whitelist.label");
|
||||
} else if (edit.state == PresetTagState.BLACKLIST_PLUS) {
|
||||
return translate("presets.blacklistPlus.label");
|
||||
}
|
||||
|
||||
return translate("presets.blacklist.label");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addTooltips(List<String> tooltip) {
|
||||
if (edit != null) {
|
||||
tooltip.add(
|
||||
edit.whitelist ? translate("presets.whitelist.tooltip")
|
||||
: translate("presets.blacklist.tooltip"));
|
||||
if (edit.state == PresetTagState.BLACKLIST) {
|
||||
tooltip.add(translate("presets.blacklist.tooltip"));
|
||||
} else if (edit.state == PresetTagState.WHITELIST) {
|
||||
tooltip.add(translate("presets.whitelist.tooltip"));
|
||||
} else if (edit.state == PresetTagState.BLACKLIST_PLUS) {
|
||||
tooltip.add(translate("presets.blacklistPlus.tooltip"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
public void itemsLoaded() {
|
||||
|
||||
if (presetsDir != null) {
|
||||
listbox = new SubsetListBox(presetsDir);
|
||||
|
||||
edit = null;
|
||||
openListBox = false;
|
||||
selectedDisplayName.setText("");
|
||||
|
||||
ItemList.updateFilter.restart();
|
||||
PresetsRecipeFilter.blacklist = null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public PresetsWidget() {
|
||||
API.addItemFilter(this);
|
||||
API.addRecipeFilter(new PresetsRecipeFilter());
|
||||
ItemList.loadCallbacks.add(this);
|
||||
}
|
||||
|
||||
protected static void setEditedTag(final PresetTag tag) {
|
||||
edit = tag;
|
||||
openListBox = false;
|
||||
@@ -564,19 +697,15 @@ public class PresetsWidget extends Widget {
|
||||
if (edit != null) {
|
||||
|
||||
if (mouseSelection != null && mouseSelection.items.contains(item)) {
|
||||
return mouseSelection.append != edit.whitelist;
|
||||
return mouseSelection.append != (edit.state == PresetTagState.WHITELIST);
|
||||
}
|
||||
|
||||
return !edit.matches(item);
|
||||
}
|
||||
|
||||
if (!listbox.getSelected().isEmpty()) {
|
||||
final List<PresetTag> selected = listbox.getSelected();
|
||||
|
||||
for (int idx = 0; idx < selected.size(); idx++) {
|
||||
if (!selected.get(idx).matches(item)) {
|
||||
return true;
|
||||
}
|
||||
for (PresetTag tag : listbox.getSelected()) {
|
||||
if (!tag.matches(item)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -619,12 +748,10 @@ public class PresetsWidget extends Widget {
|
||||
}
|
||||
|
||||
protected static void hideItem(final ItemStack stack, boolean append) {
|
||||
final String guid = StackInfo.getItemStackGUID(stack);
|
||||
|
||||
if (append) {
|
||||
edit.items.add(guid);
|
||||
edit.items.add(stack);
|
||||
} else {
|
||||
edit.items.remove(guid);
|
||||
edit.items.remove(stack);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -637,24 +764,44 @@ public class PresetsWidget extends Widget {
|
||||
}
|
||||
|
||||
public static void loadPresets(final String worldPath) {
|
||||
final File dir = new File(CommonUtils.getMinecraftDir(), "saves/NEI/" + worldPath);
|
||||
presetsDir = new File(CommonUtils.getMinecraftDir(), "saves/NEI/" + worldPath + "/presets");
|
||||
|
||||
if (!dir.exists()) {
|
||||
dir.mkdirs();
|
||||
if (!presetsDir.getParentFile().exists()) {
|
||||
presetsDir.getParentFile().mkdirs();
|
||||
}
|
||||
|
||||
if (!presetsDir.exists()) {
|
||||
presetsDir.mkdirs();
|
||||
}
|
||||
|
||||
listbox = new SubsetListBox(presetsDir);
|
||||
if (!(new File(presetsDir, "selected.ini")).exists()) {
|
||||
final File configPresets = new File(NEIClientConfig.configDir, "/presets");
|
||||
|
||||
edit = null;
|
||||
openListBox = false;
|
||||
selectedDisplayName.setText("");
|
||||
if (configPresets.exists()) {
|
||||
for (File file : configPresets.listFiles()) {
|
||||
try {
|
||||
InputStream src = new FileInputStream(file);
|
||||
OutputStream dst = new FileOutputStream(new File(presetsDir, file.getName()));
|
||||
|
||||
IOUtils.copy(src, dst);
|
||||
|
||||
src.close();
|
||||
dst.close();
|
||||
} catch (IOException e) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (LayoutManager.itemsLoaded) {
|
||||
listbox = new SubsetListBox(presetsDir);
|
||||
|
||||
edit = null;
|
||||
openListBox = false;
|
||||
selectedDisplayName.setText("");
|
||||
ItemList.updateFilter.restart();
|
||||
PresetsRecipeFilter.blacklist = null;
|
||||
}
|
||||
|
||||
ItemList.updateFilter.restart();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -903,16 +1050,20 @@ public class PresetsWidget extends Widget {
|
||||
return tooltip;
|
||||
}
|
||||
|
||||
public static boolean matches(ItemStack stack) {
|
||||
@Override
|
||||
public ItemFilter getFilter() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(ItemStack stack) {
|
||||
|
||||
if (edit != null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
final List<PresetTag> selected = listbox.getSelected();
|
||||
|
||||
for (int idx = 0; idx < selected.size(); idx++) {
|
||||
if (!selected.get(idx).matches(stack)) {
|
||||
for (PresetTag tag : listbox.getSelected()) {
|
||||
if (!tag.matches(stack)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
package codechicken.nei;
|
||||
|
||||
import net.minecraft.util.EnumChatFormatting;
|
||||
|
||||
import codechicken.nei.api.ItemFilter;
|
||||
import codechicken.nei.util.TextHistory;
|
||||
|
||||
public abstract class RecipeSearchField extends TextField {
|
||||
|
||||
private static final TextHistory history = new TextHistory();
|
||||
|
||||
public RecipeSearchField(String ident) {
|
||||
super(ident);
|
||||
this.field.setVisible(false);
|
||||
}
|
||||
|
||||
public boolean isVisible() {
|
||||
return this.field.getVisible();
|
||||
}
|
||||
|
||||
public void setVisible(boolean visible) {
|
||||
this.field.setVisible(visible);
|
||||
}
|
||||
|
||||
protected abstract boolean noResults();
|
||||
|
||||
@Override
|
||||
public int getTextColour() {
|
||||
if (!text().isEmpty() && !noResults()) {
|
||||
return focused() ? 0xFFcc3300 : 0xFF993300;
|
||||
} else {
|
||||
return focused() ? 0xFFE0E0E0 : 0xFF909090;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void lastKeyTyped(int keyID, char keyChar) {
|
||||
|
||||
if (focused() && NEIClientConfig.isKeyHashDown("gui.getprevioussearch")) {
|
||||
handleNavigateHistory(TextHistory.Direction.PREVIOUS);
|
||||
}
|
||||
|
||||
if (focused() && NEIClientConfig.isKeyHashDown("gui.getnextsearch")) {
|
||||
handleNavigateHistory(TextHistory.Direction.NEXT);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String filterText(String s) {
|
||||
return EnumChatFormatting.getTextWithoutFormattingCodes(s);
|
||||
}
|
||||
|
||||
public ItemFilter getFilter() {
|
||||
return SearchField.getFilter(text());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFocus(boolean focus) {
|
||||
final boolean previousFocus = field.isFocused();
|
||||
|
||||
if (previousFocus != focus) {
|
||||
history.add(text());
|
||||
}
|
||||
|
||||
super.setFocus(focus);
|
||||
}
|
||||
|
||||
private boolean handleNavigateHistory(TextHistory.Direction direction) {
|
||||
if (focused()) {
|
||||
return history.get(direction, text()).map(newText -> {
|
||||
setText(newText);
|
||||
return true;
|
||||
}).orElse(false);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -101,7 +101,6 @@ public class SearchField extends TextField implements ItemFilterProvider {
|
||||
if (button == 0) {
|
||||
if (focused() && (System.currentTimeMillis() - lastclicktime < 400)) { // double click
|
||||
NEIClientConfig.world.nbt.setBoolean("searchinventories", !searchInventories());
|
||||
NEIClientConfig.world.saveNBT();
|
||||
}
|
||||
lastclicktime = System.currentTimeMillis();
|
||||
}
|
||||
@@ -123,11 +122,11 @@ public class SearchField extends TextField implements ItemFilterProvider {
|
||||
if (isVisible() && NEIClientConfig.isKeyHashDown("gui.search")) {
|
||||
setFocus(true);
|
||||
}
|
||||
if (NEIClientConfig.isKeyHashDown("gui.getprevioussearch") && focused()) {
|
||||
if (focused() && NEIClientConfig.isKeyHashDown("gui.getprevioussearch")) {
|
||||
handleNavigateHistory(TextHistory.Direction.PREVIOUS);
|
||||
}
|
||||
|
||||
if (NEIClientConfig.isKeyHashDown("gui.getnextsearch") && focused()) {
|
||||
if (focused() && NEIClientConfig.isKeyHashDown("gui.getnextsearch")) {
|
||||
handleNavigateHistory(TextHistory.Direction.NEXT);
|
||||
}
|
||||
}
|
||||
@@ -151,22 +150,33 @@ public class SearchField extends TextField implements ItemFilterProvider {
|
||||
try {
|
||||
pattern = Pattern.compile(search);
|
||||
} catch (PatternSyntaxException ignored) {}
|
||||
|
||||
return pattern == null || pattern.toString().length() == 0 ? null : pattern;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemFilter getFilter() {
|
||||
String s_filter = text().toLowerCase();
|
||||
return getFilter(text());
|
||||
}
|
||||
|
||||
public static ItemFilter getFilter(String s_filter) {
|
||||
List<ItemFilter> primary = new LinkedList<>();
|
||||
List<ItemFilter> secondary = new LinkedList<>();
|
||||
s_filter = s_filter.toLowerCase();
|
||||
|
||||
for (ISearchProvider p : searchProviders) {
|
||||
ItemFilter filter = p.getFilter(s_filter);
|
||||
if (filter != null) (p.isPrimary() ? primary : secondary).add(filter);
|
||||
}
|
||||
|
||||
if (!primary.isEmpty()) return new AnyMultiItemFilter(primary);
|
||||
if (!secondary.isEmpty()) return new AnyMultiItemFilter(secondary);
|
||||
if (!primary.isEmpty()) {
|
||||
return new AnyMultiItemFilter(primary);
|
||||
}
|
||||
|
||||
if (!secondary.isEmpty()) {
|
||||
return new AnyMultiItemFilter(secondary);
|
||||
}
|
||||
|
||||
return new EverythingItemFilter();
|
||||
}
|
||||
|
||||
|
||||
@@ -533,7 +533,6 @@ public class SubsetWidget extends Button implements ItemFilterProvider, ItemsLoa
|
||||
NBTTagList list = dirtyHiddenItems.getAndSet(null);
|
||||
if (list != null) {
|
||||
NEIClientConfig.world.nbt.setTag("hiddenItems", list);
|
||||
NEIClientConfig.world.saveNBT();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -27,11 +27,13 @@ import codechicken.nei.SearchField;
|
||||
import codechicken.nei.SearchField.ISearchProvider;
|
||||
import codechicken.nei.SubsetWidget;
|
||||
import codechicken.nei.SubsetWidget.SubsetTag;
|
||||
import codechicken.nei.api.IRecipeFilter.IRecipeFilterProvider;
|
||||
import codechicken.nei.api.ItemFilter.ItemFilterProvider;
|
||||
import codechicken.nei.config.Option;
|
||||
import codechicken.nei.config.OptionKeyBind;
|
||||
import codechicken.nei.recipe.CatalystInfo;
|
||||
import codechicken.nei.recipe.GuiCraftingRecipe;
|
||||
import codechicken.nei.recipe.GuiRecipe;
|
||||
import codechicken.nei.recipe.GuiUsageRecipe;
|
||||
import codechicken.nei.recipe.ICraftingHandler;
|
||||
import codechicken.nei.recipe.IRecipeHandler;
|
||||
@@ -160,7 +162,7 @@ public class API {
|
||||
|
||||
/**
|
||||
* Adds an item to the item panel. Any items added using this function will override the default search pattern.
|
||||
*
|
||||
*
|
||||
* @param item an item with data
|
||||
*/
|
||||
public static void addItemListEntry(ItemStack item) {
|
||||
@@ -183,7 +185,7 @@ public class API {
|
||||
|
||||
/**
|
||||
* Add a custom KeyBinding to be configured in the Controls menu.
|
||||
*
|
||||
*
|
||||
* @param ident An identifier for your key, eg "shoot"
|
||||
* @param defaultKey The default value, commonly obtained from {@link Keyboard}
|
||||
*/
|
||||
@@ -195,7 +197,7 @@ public class API {
|
||||
|
||||
/**
|
||||
* Add a custom KeyBinding to be configured in the Controls menu.
|
||||
*
|
||||
*
|
||||
* @param ident An identifier for your key, eg "shoot"
|
||||
* @param defaultKey The default value, commonly obtained from {@link Keyboard}
|
||||
*/
|
||||
@@ -210,7 +212,7 @@ public class API {
|
||||
|
||||
/**
|
||||
* Add a new Layout Style for the NEI interface
|
||||
*
|
||||
*
|
||||
* @param styleID The Unique ID to be used for storing your style in the config and cycling through avaliable styles
|
||||
* @param style The style to add.
|
||||
*/
|
||||
@@ -220,7 +222,7 @@ public class API {
|
||||
|
||||
/**
|
||||
* Registers a new Infinite Item Handler.
|
||||
*
|
||||
*
|
||||
* @param handler The handler to be registered.
|
||||
*/
|
||||
public static void addInfiniteItemHandler(IInfiniteItemHandler handler) {
|
||||
@@ -229,7 +231,7 @@ public class API {
|
||||
|
||||
/**
|
||||
* Registers a new Infinite Item Handler.
|
||||
*
|
||||
*
|
||||
* @param block The block to handle, null for all.
|
||||
* @param handler The handler to be registered.
|
||||
*/
|
||||
@@ -239,7 +241,7 @@ public class API {
|
||||
|
||||
/**
|
||||
* Tells NEI not to perform any Fast Transfer operations on slots of a particular class
|
||||
*
|
||||
*
|
||||
* @param slotClass The class of slot to be exempted
|
||||
*/
|
||||
public static void addFastTransferExemptSlot(Class<? extends Slot> slotClass) {
|
||||
@@ -248,7 +250,7 @@ public class API {
|
||||
|
||||
/**
|
||||
* Register a new text handler for the block highlight tooltip with a layout specification (HEADER, BODY or FOOTER).
|
||||
*
|
||||
*
|
||||
* @param handler The handler to be registered.
|
||||
* @param layout A HUDAugmenterRegistry.Layout entry. HEADER is displayed before BODY which is displayed before
|
||||
* FOOTER.
|
||||
@@ -259,16 +261,22 @@ public class API {
|
||||
|
||||
/**
|
||||
* Register a mode handler for overriding NEI recipe/utility/cheat mode settings.
|
||||
*
|
||||
*
|
||||
* @param handler The handler to be registered.
|
||||
*/
|
||||
public static void registerModeHandler(INEIModeHandler handler) {
|
||||
NEIInfo.modeHandlers.add(handler);
|
||||
}
|
||||
|
||||
public static void addRecipeFilter(IRecipeFilterProvider filterProvider) {
|
||||
synchronized (GuiRecipe.recipeFilterers) {
|
||||
GuiRecipe.recipeFilterers.add(filterProvider);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a filter provider for the item panel.
|
||||
*
|
||||
*
|
||||
* @param filterProvider The filter provider to be registered.
|
||||
*/
|
||||
public static void addItemFilter(ItemFilterProvider filterProvider) {
|
||||
@@ -279,7 +287,7 @@ public class API {
|
||||
|
||||
/**
|
||||
* Adds a new tag to the item subset dropdown.
|
||||
*
|
||||
*
|
||||
* @param name The fully qualified name, Eg Blocks.MobSpawners. NOT case sensitive
|
||||
* @param filter A filter for matching items that fit in this subset
|
||||
*/
|
||||
@@ -289,7 +297,7 @@ public class API {
|
||||
|
||||
/**
|
||||
* Adds a new tag to the item subset dropdown.
|
||||
*
|
||||
*
|
||||
* @param name The fully qualified name, Eg Blocks.MobSpawners. NOT case sensitive
|
||||
* @param items An iterable of itemstacks to be added as a subset
|
||||
*/
|
||||
@@ -315,7 +323,7 @@ public class API {
|
||||
|
||||
/**
|
||||
* Adds a new sorting option to the item panel sort menu
|
||||
*
|
||||
*
|
||||
* @param name A unique id for this sort option. Will be used in the config for saving and translated in the options
|
||||
* gui. Note that if the translation key name.tip exists, it will be used for a tooltip
|
||||
*/
|
||||
@@ -326,7 +334,7 @@ public class API {
|
||||
/**
|
||||
* Adds an additional item list entry for an item, sorted after the rest of the items are found through the normal
|
||||
* process
|
||||
*
|
||||
*
|
||||
* @param item The item to add the variant for
|
||||
* @param variant The stack to appear in the item panel
|
||||
*/
|
||||
@@ -345,7 +353,7 @@ public class API {
|
||||
* Adds an association between an ingredient and what it can craft. (i.e. Furnace ItemStack -> Smelting and Fuel
|
||||
* Recipes) Allows players to see what ingredient they need to craft in order to make recipes from a recipe
|
||||
* category.
|
||||
*
|
||||
*
|
||||
* @param stack the ingredient that can craft recipes (like a furnace or crafting table)
|
||||
* @param handler the recipe category handled by the ingredient
|
||||
* @param priority higher priority comes first, default to 0
|
||||
@@ -366,7 +374,7 @@ public class API {
|
||||
* Adds an association between an ingredient and what it can craft. (i.e. Furnace ItemStack -> Smelting and Fuel
|
||||
* Recipes) Allows players to see what ingredient they need to craft in order to make recipes from a recipe
|
||||
* category.
|
||||
*
|
||||
*
|
||||
* @param stack the ingredient that can craft recipes (like a furnace or crafting table)
|
||||
* @param handlerID recipe category identifier (see also {@link RecipeCatalysts#getRecipeID(IRecipeHandler)})
|
||||
* @param priority higher priority comes first, default to 0
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
package codechicken.nei.api;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import codechicken.nei.PositionedStack;
|
||||
import codechicken.nei.recipe.IRecipeHandler;
|
||||
|
||||
public interface IRecipeFilter {
|
||||
|
||||
public static interface IRecipeFilterProvider {
|
||||
|
||||
public IRecipeFilter getFilter();
|
||||
}
|
||||
|
||||
public boolean matches(IRecipeHandler handler, List<PositionedStack> ingredients, PositionedStack result,
|
||||
List<PositionedStack> others);
|
||||
|
||||
}
|
||||
@@ -1,5 +1,8 @@
|
||||
package codechicken.nei.api;
|
||||
|
||||
import static codechicken.lib.gui.GuiDraw.getMousePosition;
|
||||
|
||||
import java.awt.Point;
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.client.gui.inventory.GuiContainer;
|
||||
@@ -7,14 +10,18 @@ import net.minecraft.item.ItemStack;
|
||||
|
||||
import org.lwjgl.input.Mouse;
|
||||
|
||||
import codechicken.nei.ItemPanel.ItemPanelSlot;
|
||||
import codechicken.nei.ItemPanels;
|
||||
import codechicken.nei.LayoutManager;
|
||||
import codechicken.nei.NEIClientConfig;
|
||||
import codechicken.nei.NEIClientUtils;
|
||||
import codechicken.nei.PositionedStack;
|
||||
import codechicken.nei.recipe.BookmarkRecipeId;
|
||||
import codechicken.nei.recipe.GuiCraftingRecipe;
|
||||
import codechicken.nei.recipe.GuiRecipe;
|
||||
import codechicken.nei.recipe.GuiUsageRecipe;
|
||||
import codechicken.nei.recipe.StackInfo;
|
||||
import codechicken.nei.recipe.stackinfo.GTFluidStackStringifyHandler;
|
||||
|
||||
public abstract class ShortcutInputHandler {
|
||||
|
||||
@@ -28,6 +35,23 @@ public abstract class ShortcutInputHandler {
|
||||
return hideOverlayRecipe();
|
||||
}
|
||||
|
||||
if (NEIClientConfig.isKeyHashDown("gui.bookmark_pull_items")) {
|
||||
return ItemPanels.bookmarkPanel.pullBookmarkItems(ItemPanels.bookmarkPanel.getHoveredGroupId(true), false);
|
||||
}
|
||||
|
||||
if (NEIClientConfig.isKeyHashDown("gui.bookmark_pull_items_ingredients")) {
|
||||
return ItemPanels.bookmarkPanel.pullBookmarkItems(ItemPanels.bookmarkPanel.getHoveredGroupId(true), true);
|
||||
}
|
||||
|
||||
if (stackover == null && NEIClientConfig.isKeyHashDown("gui.bookmark_recipe")) {
|
||||
final int groupId = ItemPanels.bookmarkPanel.getHoveredGroupId(true);
|
||||
|
||||
if (groupId != -1) {
|
||||
ItemPanels.bookmarkPanel.removeGroup(groupId);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (stackover == null) {
|
||||
return false;
|
||||
}
|
||||
@@ -43,11 +67,11 @@ public abstract class ShortcutInputHandler {
|
||||
}
|
||||
|
||||
if (NEIClientConfig.isKeyHashDown("gui.recipe")) {
|
||||
return GuiCraftingRecipe.openRecipeGui("item", stackover);
|
||||
return GuiCraftingRecipe.openRecipeGui("item", normalizeItemStack(stackover));
|
||||
}
|
||||
|
||||
if (NEIClientConfig.isKeyHashDown("gui.usage")) {
|
||||
return GuiUsageRecipe.openRecipeGui("item", stackover);
|
||||
return GuiUsageRecipe.openRecipeGui("item", normalizeItemStack(stackover));
|
||||
}
|
||||
|
||||
if (NEIClientConfig.isKeyHashDown("gui.bookmark")) {
|
||||
@@ -99,14 +123,28 @@ public abstract class ShortcutInputHandler {
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean openOverlayRecipe(ItemStack stack, boolean shift) {
|
||||
private static boolean openOverlayRecipe(ItemStack stackover, boolean shift) {
|
||||
final GuiContainer gui = NEIClientUtils.getGuiContainer();
|
||||
|
||||
if (gui == null || gui instanceof GuiRecipe) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return GuiCraftingRecipe.openRecipeGui("item", true, shift, stack);
|
||||
final Point mouseover = getMousePosition();
|
||||
ItemPanelSlot panelSlot = ItemPanels.bookmarkPanel.getSlotMouseOver(mouseover.x, mouseover.y);
|
||||
BookmarkRecipeId recipeId = null;
|
||||
|
||||
if (panelSlot != null) {
|
||||
recipeId = ItemPanels.bookmarkPanel.getBookmarkRecipeId(panelSlot.slotIndex);
|
||||
} else {
|
||||
recipeId = ItemPanels.bookmarkPanel.getBookmarkRecipeId(stackover);
|
||||
}
|
||||
|
||||
if (recipeId != null) {
|
||||
return GuiCraftingRecipe.overlayRecipe(stackover, recipeId, shift);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean saveRecipeInBookmark(ItemStack stack, boolean saveIngredients, boolean saveStackSize) {
|
||||
@@ -128,4 +166,11 @@ public abstract class ShortcutInputHandler {
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static ItemStack normalizeItemStack(ItemStack stack) {
|
||||
GTFluidStackStringifyHandler.replaceAE2FCFluidDrop = true;
|
||||
stack = StackInfo.loadFromNBT(StackInfo.itemStackToNBT(stack));
|
||||
GTFluidStackStringifyHandler.replaceAE2FCFluidDrop = false;
|
||||
return stack;
|
||||
}
|
||||
}
|
||||
@@ -16,10 +16,6 @@ import codechicken.nei.util.NBTJson;
|
||||
|
||||
public class BookmarkRecipeId {
|
||||
|
||||
public int position = -1;
|
||||
|
||||
public int recipetype = -1;
|
||||
|
||||
public String handlerName = null;
|
||||
|
||||
public List<NBTTagCompound> ingredients = new ArrayList<>();
|
||||
@@ -121,43 +117,6 @@ public class BookmarkRecipeId {
|
||||
return arr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures the {@link BookmarkRecipeId#recipetype} and {@link BookmarkRecipeId#position} fields point to a valid
|
||||
* recipe. This is needed, because the recipe IDs are loaded lazily on first use.
|
||||
*
|
||||
* @param recipeHandlers The subset of recipe handlers to search for the recipe
|
||||
*/
|
||||
public void updateTargetRecipe(List<? extends IRecipeHandler> recipeHandlers) {
|
||||
if (this.recipetype == -1 || this.position == -1) {
|
||||
this.recipetype = 0;
|
||||
this.position = 0;
|
||||
|
||||
if (this.handlerName != null) {
|
||||
|
||||
for (int j = 0; j < recipeHandlers.size(); j++) {
|
||||
IRecipeHandler localHandler = recipeHandlers.get(j);
|
||||
HandlerInfo localHandlerInfo = GuiRecipeTab.getHandlerInfo(localHandler);
|
||||
|
||||
if (localHandlerInfo.getHandlerName().equals(this.handlerName)) {
|
||||
|
||||
if (!this.ingredients.isEmpty()) {
|
||||
for (int i = 0; i < localHandler.numRecipes(); i++) {
|
||||
|
||||
if (this.equalsIngredients(localHandler.getIngredientStacks(i))) {
|
||||
this.recipetype = j;
|
||||
this.position = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean equals(Object anObject) {
|
||||
if (this == anObject) {
|
||||
return true;
|
||||
|
||||
@@ -6,6 +6,8 @@ import java.awt.Point;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
@@ -23,50 +25,76 @@ public class GuiCraftingRecipe extends GuiRecipe<ICraftingHandler> {
|
||||
public static ArrayList<ICraftingHandler> serialCraftingHandlers = new ArrayList<>();
|
||||
|
||||
public static boolean openRecipeGui(String outputId, Object... results) {
|
||||
return openRecipeGui(outputId, false, false, results);
|
||||
return createRecipeGui(outputId, true, results) != null;
|
||||
}
|
||||
|
||||
public static boolean openRecipeGui(String outputId, final Boolean overlay, final Boolean shift,
|
||||
Object... results) {
|
||||
return createRecipeGui(outputId, overlay, shift, true, results) != null;
|
||||
}
|
||||
|
||||
public static GuiRecipe<?> createRecipeGui(String outputId, final Boolean overlay, final Boolean shift,
|
||||
final boolean open, Object... results) {
|
||||
public static GuiRecipe<?> createRecipeGui(String outputId, boolean open, Object... results) {
|
||||
final Minecraft mc = NEIClientUtils.mc();
|
||||
final BookmarkRecipeId recipeId;
|
||||
|
||||
final BookmarkRecipeId recipeId = "item".equals(outputId)
|
||||
? getRecipeId(mc.currentScreen, (ItemStack) results[0])
|
||||
: getCurrentRecipe(mc.currentScreen);
|
||||
|
||||
if (overlay && recipeId == null) return null;
|
||||
if ("item".equals(outputId)) {
|
||||
recipeId = getRecipeId(mc.currentScreen, (ItemStack) results[0]);
|
||||
} else if ("recipeId".equals(outputId)) {
|
||||
recipeId = (BookmarkRecipeId) results[1];
|
||||
} else {
|
||||
recipeId = getCurrentRecipe(mc.currentScreen);
|
||||
}
|
||||
|
||||
final ArrayList<ICraftingHandler> handlers = getCraftingHandlers(outputId, results);
|
||||
|
||||
if (!handlers.isEmpty()) {
|
||||
GuiCraftingRecipe gui = new GuiCraftingRecipe(handlers, recipeId);
|
||||
final GuiCraftingRecipe gui = new GuiCraftingRecipe(handlers, "recipeId".equals(outputId));
|
||||
|
||||
if (open) {
|
||||
mc.displayGuiScreen(gui);
|
||||
}
|
||||
|
||||
if (recipeId != null) {
|
||||
gui.openTargetRecipe(gui.recipeId);
|
||||
}
|
||||
|
||||
if (overlay) {
|
||||
gui.overlayRecipe(gui.recipeId.position, shift);
|
||||
}
|
||||
|
||||
gui.openTargetRecipe(recipeId);
|
||||
return gui;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static boolean overlayRecipe(ItemStack stack, BookmarkRecipeId recipeId, final Boolean shift) {
|
||||
|
||||
if (stack == null || recipeId == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final ArrayList<ICraftingHandler> handlers = getCraftingHandlers("recipeId", stack, recipeId);
|
||||
|
||||
if (!handlers.isEmpty()) {
|
||||
final GuiCraftingRecipe gui = new GuiCraftingRecipe(handlers, true);
|
||||
final int recipe = gui.openTargetRecipe(recipeId);
|
||||
|
||||
if (recipe != -1) {
|
||||
gui.overlayRecipe(recipe, shift);
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static ArrayList<ICraftingHandler> getCraftingHandlers(String outputId, Object... results) {
|
||||
ArrayList<ICraftingHandler> craftinghandlers = GuiCraftingRecipe.craftinghandlers;
|
||||
ArrayList<ICraftingHandler> serialCraftingHandlers = GuiCraftingRecipe.serialCraftingHandlers;
|
||||
Function<ICraftingHandler, ICraftingHandler> recipeHandlerFunction;
|
||||
|
||||
if ("recipeId".equals(outputId)) {
|
||||
ItemStack stack = (ItemStack) results[0];
|
||||
BookmarkRecipeId recipeId = (BookmarkRecipeId) results[1];
|
||||
craftinghandlers = filterByHandlerName(craftinghandlers, recipeId.handlerName);
|
||||
serialCraftingHandlers = filterByHandlerName(serialCraftingHandlers, recipeId.handlerName);
|
||||
recipeHandlerFunction = h -> h.getRecipeHandler("item", stack);
|
||||
} else {
|
||||
recipeHandlerFunction = h -> h.getRecipeHandler(outputId, results);
|
||||
}
|
||||
|
||||
final RecipeHandlerQuery<ICraftingHandler> recipeQuery = new RecipeHandlerQuery<>(
|
||||
h -> h.getRecipeHandler(outputId, results),
|
||||
recipeHandlerFunction,
|
||||
craftinghandlers,
|
||||
serialCraftingHandlers,
|
||||
"Error while looking up crafting recipe",
|
||||
@@ -76,6 +104,16 @@ public class GuiCraftingRecipe extends GuiRecipe<ICraftingHandler> {
|
||||
return recipeQuery.runWithProfiling("recipe.concurrent.crafting");
|
||||
}
|
||||
|
||||
private static ArrayList<ICraftingHandler> filterByHandlerName(ArrayList<ICraftingHandler> craftinghandlers,
|
||||
String handlerName) {
|
||||
return craftinghandlers.stream().filter(h -> getHandlerName(h).equals(handlerName))
|
||||
.collect(Collectors.toCollection(ArrayList::new));
|
||||
}
|
||||
|
||||
private static String getHandlerName(ICraftingHandler handler) {
|
||||
return GuiRecipeTab.getHandlerInfo(handler).getHandlerName();
|
||||
}
|
||||
|
||||
protected static BookmarkRecipeId getRecipeId(GuiScreen gui, ItemStack stackover) {
|
||||
|
||||
if (gui instanceof GuiRecipe) {
|
||||
@@ -97,10 +135,10 @@ public class GuiCraftingRecipe extends GuiRecipe<ICraftingHandler> {
|
||||
return ItemPanels.bookmarkPanel.getBookmarkRecipeId(stackover);
|
||||
}
|
||||
|
||||
private GuiCraftingRecipe(ArrayList<ICraftingHandler> handlers, BookmarkRecipeId recipeId) {
|
||||
private GuiCraftingRecipe(ArrayList<ICraftingHandler> handlers, boolean limitToOneRecipe) {
|
||||
super(NEIClientUtils.mc().currentScreen);
|
||||
this.limitToOneRecipe = limitToOneRecipe;
|
||||
this.currenthandlers = handlers;
|
||||
this.recipeId = recipeId;
|
||||
}
|
||||
|
||||
public static void registerRecipeHandler(ICraftingHandler handler) {
|
||||
|
||||
@@ -7,11 +7,12 @@ import java.awt.Rectangle;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
import net.minecraft.client.gui.GuiButton;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
@@ -21,22 +22,30 @@ import net.minecraft.client.renderer.OpenGlHelper;
|
||||
import net.minecraft.client.renderer.RenderHelper;
|
||||
import net.minecraft.inventory.Slot;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.EnumChatFormatting;
|
||||
import net.minecraftforge.fluids.FluidStack;
|
||||
|
||||
import org.lwjgl.input.Keyboard;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import codechicken.lib.gui.GuiDraw;
|
||||
import codechicken.nei.Button;
|
||||
import codechicken.nei.GuiNEIButton;
|
||||
import codechicken.nei.LayoutManager;
|
||||
import codechicken.nei.NEICPH;
|
||||
import codechicken.nei.NEIClientConfig;
|
||||
import codechicken.nei.NEIClientUtils;
|
||||
import codechicken.nei.PositionedStack;
|
||||
import codechicken.nei.RecipeSearchField;
|
||||
import codechicken.nei.RestartableTask;
|
||||
import codechicken.nei.VisiblityData;
|
||||
import codechicken.nei.api.IGuiContainerOverlay;
|
||||
import codechicken.nei.api.INEIGuiHandler;
|
||||
import codechicken.nei.api.IOverlayHandler;
|
||||
import codechicken.nei.api.IRecipeFilter;
|
||||
import codechicken.nei.api.IRecipeFilter.IRecipeFilterProvider;
|
||||
import codechicken.nei.api.IRecipeOverlayRenderer;
|
||||
import codechicken.nei.api.ItemFilter;
|
||||
import codechicken.nei.api.TaggedInventoryArea;
|
||||
import codechicken.nei.drawable.DrawableBuilder;
|
||||
import codechicken.nei.drawable.DrawableResource;
|
||||
@@ -62,7 +71,9 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
|
||||
private static final int buttonWidth = 13;
|
||||
private static final int buttonHeight = 12;
|
||||
|
||||
private boolean limitToOneRecipe = false;
|
||||
public static final List<IRecipeFilterProvider> recipeFilterers = new LinkedList<>();
|
||||
|
||||
protected boolean limitToOneRecipe = false;
|
||||
|
||||
// Background image
|
||||
final DrawableResource bgTop = new DrawableBuilder("nei:textures/gui/recipebg.png", 0, BG_TOP_Y, 176, BG_TOP_HEIGHT)
|
||||
@@ -81,9 +92,9 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
|
||||
BG_BOTTOM_HEIGHT).build();
|
||||
|
||||
public ArrayList<H> currenthandlers = new ArrayList<>();
|
||||
|
||||
public int page;
|
||||
public int recipetype;
|
||||
|
||||
public BookmarkRecipeId recipeId;
|
||||
public ContainerRecipe slotcontainer;
|
||||
public GuiContainer firstGui;
|
||||
@@ -100,11 +111,164 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
|
||||
private final Rectangle area = new Rectangle();
|
||||
private final GuiRecipeTabs recipeTabs;
|
||||
private final GuiRecipeCatalyst guiRecipeCatalyst;
|
||||
private H handler;
|
||||
private SearchRecipeHandler<H> handler;
|
||||
private HandlerInfo handlerInfo;
|
||||
|
||||
private int yShift = 0;
|
||||
|
||||
public static class ItemRecipeFilter implements IRecipeFilter {
|
||||
|
||||
public ItemFilter filter;
|
||||
|
||||
public ItemRecipeFilter(ItemFilter filter) {
|
||||
this.filter = filter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(IRecipeHandler handler, List<PositionedStack> ingredients, PositionedStack result,
|
||||
List<PositionedStack> others) {
|
||||
|
||||
if (matchPositionedStack(ingredients)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (matchPositionedStack(result)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (matchPositionedStack(others)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean matchPositionedStack(List<PositionedStack> items) {
|
||||
for (PositionedStack pStack : items) {
|
||||
if (matchPositionedStack(pStack)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean matchPositionedStack(PositionedStack pStack) {
|
||||
if (pStack == null) return false;
|
||||
|
||||
for (ItemStack stack : pStack.items) {
|
||||
if (filter.matches(stack)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class AllMultiRecipeFilter implements IRecipeFilter {
|
||||
|
||||
public List<IRecipeFilter> filters;
|
||||
|
||||
public AllMultiRecipeFilter(List<IRecipeFilter> filters) {
|
||||
this.filters = filters;
|
||||
}
|
||||
|
||||
public AllMultiRecipeFilter(IRecipeFilter filters) {
|
||||
this(Arrays.asList(filters));
|
||||
}
|
||||
|
||||
public AllMultiRecipeFilter() {
|
||||
this(new ArrayList<>());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(IRecipeHandler handler, List<PositionedStack> ingredients, PositionedStack result,
|
||||
List<PositionedStack> others) {
|
||||
for (IRecipeFilter filter : filters) {
|
||||
try {
|
||||
if (filter != null && !filter.matches(handler, ingredients, result, others)) return false;
|
||||
} catch (Exception e) {
|
||||
NEIClientConfig.logger.error("Exception filtering " + handler + " with " + filter, e);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
protected static final RestartableTask updateFilter = new RestartableTask("NEI Recipe Filtering") {
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
final GuiScreen currentScreen = NEIClientUtils.mc().currentScreen;
|
||||
|
||||
if (currentScreen instanceof GuiRecipe) {
|
||||
final GuiRecipe<?> guiRecipe = (GuiRecipe<?>) currentScreen;
|
||||
final SearchRecipeHandler<?> searchHandler = guiRecipe.handler;
|
||||
|
||||
if (searchHandler != null && searchHandler.searchingAvailable()) {
|
||||
|
||||
if (GuiRecipe.searchField.text().isEmpty()) {
|
||||
searchHandler.setSearchIndices(null);
|
||||
guiRecipe.changePage(0);
|
||||
} else {
|
||||
final IRecipeFilter filter = new ItemRecipeFilter(GuiRecipe.searchField.getFilter());
|
||||
ArrayList<Integer> filtered = searchHandler.getSearchResult(filter);
|
||||
|
||||
if (filtered == null) {
|
||||
stop();
|
||||
}
|
||||
|
||||
if (interrupted()) return;
|
||||
searchHandler.setSearchIndices(filtered);
|
||||
guiRecipe.changePage(0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
protected static final RecipeSearchField searchField = new RecipeSearchField("") {
|
||||
|
||||
@Override
|
||||
protected boolean noResults() {
|
||||
GuiScreen currentScreen = NEIClientUtils.mc().currentScreen;
|
||||
return !(currentScreen instanceof GuiRecipe) || ((GuiRecipe<?>) currentScreen).numRecipes() > 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTextChange(String oldText) {
|
||||
updateFilter.restart();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
protected static final Button toggleSearch = new Button() {
|
||||
|
||||
@Override
|
||||
public boolean onButtonPress(boolean rightclick) {
|
||||
if (rightclick) return false;
|
||||
|
||||
if (searchField.isVisible()) {
|
||||
searchField.setText("");
|
||||
searchField.setFocus(false);
|
||||
searchField.setVisible(false);
|
||||
state = 0;
|
||||
} else {
|
||||
searchField.setVisible(true);
|
||||
searchField.setFocus(true);
|
||||
state = 2;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* This will only be true iff height hacking has been configured for the current recipe handler AND we are currently
|
||||
* within the scope of an active {@link CompatibilityHacks} instance.
|
||||
@@ -119,7 +283,10 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
|
||||
|
||||
this.prevGui = prevgui;
|
||||
this.firstGuiGeneral = prevgui;
|
||||
if (prevgui instanceof GuiContainer) this.firstGui = (GuiContainer) prevgui;
|
||||
|
||||
if (prevgui instanceof GuiContainer) {
|
||||
this.firstGui = (GuiContainer) prevgui;
|
||||
}
|
||||
|
||||
if (prevgui instanceof IGuiContainerOverlay) {
|
||||
this.firstGui = ((IGuiContainerOverlay) prevgui).getFirstScreen();
|
||||
@@ -164,7 +331,7 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
|
||||
trueGuiTop = guiTop;
|
||||
|
||||
isHeightHackApplied = NEIClientConfig.heightHackHandlerRegex.stream()
|
||||
.map(pattern -> pattern.matcher(handler.getHandlerId())).anyMatch(Matcher::matches);
|
||||
.map(pattern -> pattern.matcher(handler.original.getHandlerId())).anyMatch(Matcher::matches);
|
||||
if (isHeightHackApplied) {
|
||||
// guiTop is the top edge of the recipe screen on the y-axis. Old recipe handlers expect a single paging
|
||||
// widget at the top and at the bottom of the recipe screen with a height of 16px each, but GTNH NEI
|
||||
@@ -211,16 +378,11 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initGui() {
|
||||
initGui(false);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void initGui(boolean asWidget) {
|
||||
public void initGui() {
|
||||
xSize = 176;
|
||||
ySize = Math.min(Math.max(height - 68, 166), 370);
|
||||
if (!asWidget) {
|
||||
if (!this.limitToOneRecipe) {
|
||||
super.initGui();
|
||||
} else {
|
||||
this.guiLeft = (this.width - this.xSize) / 2;
|
||||
@@ -234,11 +396,14 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
|
||||
this.width = scaledresolution.getScaledWidth();
|
||||
this.height = scaledresolution.getScaledHeight();
|
||||
}
|
||||
guiTop = (height - ySize) / 2 + 10;
|
||||
currenthandlers = getCurrentRecipeHandlers(); // Probably don't comment me out
|
||||
|
||||
if (handler == null) setRecipePage(recipetype);
|
||||
else initOverlayButtons();
|
||||
guiTop = (height - ySize) / 2 + 10;
|
||||
|
||||
if (handler == null) {
|
||||
setRecipePage(recipetype);
|
||||
} else {
|
||||
initOverlayButtons();
|
||||
}
|
||||
|
||||
checkYShift();
|
||||
|
||||
@@ -251,6 +416,9 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
|
||||
nextpage = new GuiNEIButton(2, leftButtonX, guiTop + 17, buttonWidth, buttonHeight, "<");
|
||||
prevpage = new GuiNEIButton(3, rightButtonX, guiTop + 17, buttonWidth, buttonHeight, ">");
|
||||
|
||||
toggleSearch.icon = new DrawableBuilder("nei:textures/nei_sprites.png", 0, 38, 8, 8).setTextureSize(128, 128)
|
||||
.build();
|
||||
|
||||
buttonList.addAll(Arrays.asList(nexttype, prevtype, nextpage, prevpage));
|
||||
|
||||
if (currenthandlers.size() == 1) {
|
||||
@@ -293,6 +461,25 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
|
||||
itemPresenceCacheRecipe = -1;
|
||||
}
|
||||
|
||||
public static IRecipeFilter getRecipeListFilter() {
|
||||
if (recipeFilterers.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final AllMultiRecipeFilter recipeFilter = new AllMultiRecipeFilter();
|
||||
|
||||
synchronized (recipeFilterers) {
|
||||
for (IRecipeFilterProvider p : recipeFilterers) {
|
||||
IRecipeFilter filter = p.getFilter();
|
||||
if (filter != null) {
|
||||
recipeFilter.filters.add(filter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return recipeFilter.filters.size() == 1 ? recipeFilter.filters.get(0) : recipeFilter;
|
||||
}
|
||||
|
||||
private void checkYShift() {
|
||||
yShift = handlerInfo == null ? 0 : handlerInfo.getYShift();
|
||||
}
|
||||
@@ -301,14 +488,20 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
|
||||
setRecipePage(idx, 0);
|
||||
}
|
||||
|
||||
public void setRecipePage(int idx, int position) {
|
||||
recipetype = idx;
|
||||
if (recipetype < 0) recipetype = currenthandlers.size() - 1;
|
||||
else if (recipetype >= currenthandlers.size()) recipetype = 0;
|
||||
public void setRecipePage(int idx, int refIndex) {
|
||||
recipetype = (currenthandlers.size() + idx) % currenthandlers.size();
|
||||
|
||||
handler = currenthandlers.get(recipetype);
|
||||
handlerInfo = GuiRecipeTab.getHandlerInfo(handler);
|
||||
page = Math.min(Math.max(0, position), handler.numRecipes() - 1) / getRecipesPerPage();
|
||||
handler = new SearchRecipeHandler<>(currenthandlers.get(recipetype));
|
||||
handlerInfo = GuiRecipeTab.getHandlerInfo(handler.original);
|
||||
|
||||
if (!limitToOneRecipe) {
|
||||
searchField.setText("");
|
||||
searchField.setVisible(false);
|
||||
toggleSearch.state = 0;
|
||||
}
|
||||
|
||||
page = Math.min(Math.max(0, refIndex), this.numRecipes() - 1) / getRecipesPerPage();
|
||||
changePage(0);
|
||||
recipeTabs.calcPageNumber();
|
||||
checkYShift();
|
||||
initOverlayButtons();
|
||||
@@ -318,22 +511,42 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
|
||||
return Collections.unmodifiableList(Arrays.asList(overlayButtons));
|
||||
}
|
||||
|
||||
public void openTargetRecipe(BookmarkRecipeId recipeId) {
|
||||
public int openTargetRecipe(BookmarkRecipeId recipeId) {
|
||||
int refIndex = -1;
|
||||
int recipetype = 0;
|
||||
|
||||
if (recipeId == null) {
|
||||
return;
|
||||
this.recipeId = recipeId;
|
||||
|
||||
if (this.recipeId != null) {
|
||||
for (int j = 0; j < currenthandlers.size(); j++) {
|
||||
H localHandler = currenthandlers.get(j);
|
||||
HandlerInfo localHandlerInfo = GuiRecipeTab.getHandlerInfo(localHandler);
|
||||
|
||||
if (localHandlerInfo.getHandlerName().equals(this.recipeId.handlerName)) {
|
||||
recipetype = j;
|
||||
|
||||
if (!this.recipeId.ingredients.isEmpty()) {
|
||||
refIndex = SearchRecipeHandler.findFirst(
|
||||
localHandler,
|
||||
(recipeIndex) -> this.recipeId
|
||||
.equalsIngredients(localHandler.getIngredientStacks(recipeIndex)));
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
recipeId.updateTargetRecipe(currenthandlers);
|
||||
setRecipePage(recipeId.recipetype, recipeId.position);
|
||||
setRecipePage(recipetype, Math.max(0, refIndex));
|
||||
|
||||
return refIndex;
|
||||
}
|
||||
|
||||
public List<PositionedStack> getFocusedRecipeIngredients() {
|
||||
final int recipesPerPage = getRecipesPerPage();
|
||||
|
||||
for (int idx = page * recipesPerPage; idx < handler.numRecipes() && idx < (page + 1) * recipesPerPage; idx++) {
|
||||
if (recipeInFocus(idx)) {
|
||||
return handler.getIngredientStacks(idx);
|
||||
for (int recipeIndex : getRecipeIndices()) {
|
||||
if (recipeInFocus(recipeIndex)) {
|
||||
return handler.original.getIngredientStacks(recipeIndex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -341,18 +554,17 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
|
||||
}
|
||||
|
||||
public int prepareFocusedRecipeResultStackSize(ItemStack stackover) {
|
||||
final int recipesPerPage = getRecipesPerPage();
|
||||
|
||||
for (int idx = page * recipesPerPage; idx < handler.numRecipes() && idx < (page + 1) * recipesPerPage; idx++) {
|
||||
if (recipeInFocus(idx)) {
|
||||
final PositionedStack result = handler.getResultStack(idx);
|
||||
for (int recipeIndex : getRecipeIndices()) {
|
||||
if (recipeInFocus(recipeIndex)) {
|
||||
final PositionedStack result = handler.original.getResultStack(recipeIndex);
|
||||
int stackSize = 0;
|
||||
|
||||
if (result != null && StackInfo.equalItemAndNBT(result.item, stackover, true)) {
|
||||
stackSize += result.item.stackSize;
|
||||
}
|
||||
|
||||
final List<PositionedStack> stacks = handler.getOtherStacks(idx);
|
||||
final List<PositionedStack> stacks = handler.original.getOtherStacks(recipeIndex);
|
||||
for (PositionedStack pStack : stacks) {
|
||||
if (StackInfo.equalItemAndNBT(pStack.item, stackover, true)) {
|
||||
stackSize += pStack.item.stackSize;
|
||||
@@ -366,15 +578,15 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
|
||||
return stackover.stackSize;
|
||||
}
|
||||
|
||||
protected boolean recipeInFocus(int idx) {
|
||||
final PositionedStack result = handler.getResultStack(idx);
|
||||
if (result != null && isMouseOver(result, idx)) {
|
||||
protected boolean recipeInFocus(int recipeIndex) {
|
||||
final PositionedStack result = handler.original.getResultStack(recipeIndex);
|
||||
if (result != null && isMouseOver(result, recipeIndex)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
final List<PositionedStack> stacks = handler.getOtherStacks(idx);
|
||||
final List<PositionedStack> stacks = handler.original.getOtherStacks(recipeIndex);
|
||||
for (PositionedStack stack : stacks) {
|
||||
if (isMouseOver(stack, idx)) {
|
||||
if (isMouseOver(stack, recipeIndex)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -387,29 +599,54 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
|
||||
}
|
||||
|
||||
public H getHandler() {
|
||||
return handler;
|
||||
return handler.original;
|
||||
}
|
||||
|
||||
public List<Integer> getRecipeIndices() {
|
||||
final int recipesPerPage = getRecipesPerPage();
|
||||
int minIndex = page * recipesPerPage;
|
||||
int maxIndex = Math.min(handler.numRecipes(), (page + 1) * recipesPerPage);
|
||||
final int minIndex = page * recipesPerPage;
|
||||
final int maxIndex = Math.min(this.numRecipes(), (page + 1) * recipesPerPage);
|
||||
final ArrayList<Integer> range = new ArrayList<>();
|
||||
|
||||
return IntStream.range(minIndex, maxIndex).boxed().collect(Collectors.toList());
|
||||
for (int index = minIndex; index < maxIndex; index++) {
|
||||
range.add(handler.ref(index));
|
||||
}
|
||||
|
||||
return range;
|
||||
}
|
||||
|
||||
private int numRecipes() {
|
||||
return handler == null ? 0 : handler.numRecipes();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void keyTyped(char c, int i) {
|
||||
if (i == Keyboard.KEY_ESCAPE) // esc
|
||||
{
|
||||
|
||||
if (searchField.isVisible() && searchField.focused() && searchField.handleKeyPress(i, c)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (i == Keyboard.KEY_ESCAPE) { // esc
|
||||
mc.displayGuiScreen(firstGuiGeneral);
|
||||
NEICPH.sendRequestContainer();
|
||||
return;
|
||||
}
|
||||
if (GuiContainerManager.getManager(this).lastKeyTyped(i, c)) return;
|
||||
|
||||
if (searchField.isVisible() && searchField.focused()) {
|
||||
searchField.lastKeyTyped(i, c);
|
||||
return;
|
||||
}
|
||||
|
||||
if (GuiContainerManager.getManager(this).lastKeyTyped(i, c)) {
|
||||
return;
|
||||
}
|
||||
|
||||
try (CompatibilityHacks compatibilityHacks = new CompatibilityHacks()) {
|
||||
for (int recipe : getRecipeIndices()) if (handler.keyTyped(this, c, i, recipe)) return;
|
||||
for (int recipeIndex : getRecipeIndices()) {
|
||||
if (handler.original.keyTyped(this, c, i, recipeIndex)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (i == mc.gameSettings.keyBindInventory.getKeyCode()) {
|
||||
@@ -429,18 +666,35 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void mouseClicked(int x, int y, int button) {
|
||||
try (CompatibilityHacks compatibilityHacks = new CompatibilityHacks()) {
|
||||
for (int recipe : getRecipeIndices()) if (handler.mouseClicked(this, button, recipe)) return;
|
||||
protected void mouseClicked(int mousex, int mousey, int button) {
|
||||
|
||||
if (!limitToOneRecipe && handler != null && handler.searchingAvailable()) {
|
||||
if (toggleSearch.contains(mousex - guiLeft, mousey - guiTop)) {
|
||||
toggleSearch.handleClick(mousex - guiLeft, mousey - guiTop, button);
|
||||
} else if (searchField.contains(mousex - guiLeft, mousey - guiTop)) {
|
||||
searchField.handleClick(mousex - guiLeft, mousey - guiTop, button);
|
||||
} else {
|
||||
searchField.onGuiClick(mousex - guiLeft, mousey - guiTop);
|
||||
}
|
||||
}
|
||||
|
||||
if (recipeTabs.mouseClicked(x, y, button)) return;
|
||||
try (CompatibilityHacks compatibilityHacks = new CompatibilityHacks()) {
|
||||
for (int recipeIndex : getRecipeIndices()) {
|
||||
if (handler.original.mouseClicked(this, button, recipeIndex)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
super.mouseClicked(x, y, button);
|
||||
if (recipeTabs.mouseClicked(mousex, mousey, button)) {
|
||||
return;
|
||||
}
|
||||
|
||||
super.mouseClicked(mousex, mousey, button);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseScrolled(int i) {
|
||||
public void mouseScrolled(int scroll) {
|
||||
// Height hacking is not necessary here since mouse scrolling is a new feature, added in
|
||||
// GTNH NEI. So no old mods will use this. Though not hacking the height here does mean that
|
||||
// the value of the height field will be different from in other mouseover methods, which
|
||||
@@ -448,23 +702,33 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
|
||||
|
||||
// First, invoke scroll handling over recipe handler tabbar. Makes sure it is not overwritten by recipe
|
||||
// handler-specific scroll behavior.
|
||||
if (recipeTabs.mouseScrolled(i)) return;
|
||||
if (recipeTabs.mouseScrolled(scroll)) return;
|
||||
|
||||
for (int recipe : getRecipeIndices()) if (handler.mouseScrolled(this, i, recipe)) return;
|
||||
for (int recipeIndex : getRecipeIndices()) {
|
||||
if (handler.original.mouseScrolled(this, scroll, recipeIndex)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// If shift is held, try switching to the next recipe handler. Replicates the GuiRecipeTabs.mouseScrolled()
|
||||
// without the checking for the cursor being inside the tabbar.
|
||||
if (NEIClientUtils.shiftKey()) {
|
||||
if (i < 0) nextType();
|
||||
else prevType();
|
||||
if (scroll < 0) {
|
||||
nextType();
|
||||
} else {
|
||||
prevType();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Finally, if nothing else has handled scrolling, try changing to the next recipe page.
|
||||
if (new Rectangle(guiLeft, guiTop, xSize, ySize).contains(GuiDraw.getMousePosition())) {
|
||||
if (i > 0) prevPage();
|
||||
else nextPage();
|
||||
if (scroll > 0) {
|
||||
prevPage();
|
||||
} else {
|
||||
nextPage();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -485,11 +749,16 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
|
||||
nextPage();
|
||||
return;
|
||||
}
|
||||
|
||||
if (overlayButtons != null && guibutton.id >= OVERLAY_BUTTON_ID_START
|
||||
&& guibutton.id < OVERLAY_BUTTON_ID_START + overlayButtons.length) {
|
||||
overlayRecipe(
|
||||
page * getRecipesPerPage() + guibutton.id - OVERLAY_BUTTON_ID_START,
|
||||
NEIClientUtils.shiftKey());
|
||||
final List<Integer> indices = getRecipeIndices();
|
||||
final int refIndex = guibutton.id - OVERLAY_BUTTON_ID_START;
|
||||
|
||||
if (refIndex >= 0 && refIndex < indices.size()) {
|
||||
mc.displayGuiScreen(firstGui);
|
||||
overlayRecipe(indices.get(refIndex), NEIClientUtils.shiftKey());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -501,24 +770,43 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
|
||||
|
||||
/** updateScreen() that's safe to call when this isn't the currently open GUI */
|
||||
public void updateAsTooltip() {
|
||||
handler.onUpdate();
|
||||
handler.original.onUpdate();
|
||||
refreshPage();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> handleTooltip(GuiContainer gui, int mousex, int mousey, List<String> currenttip) {
|
||||
|
||||
try (CompatibilityHacks compatibilityHacks = new CompatibilityHacks()) {
|
||||
for (int i : getRecipeIndices()) currenttip = handler.handleTooltip(this, currenttip, i);
|
||||
for (int recipeIndex : getRecipeIndices()) {
|
||||
currenttip = handler.original.handleTooltip(this, currenttip, recipeIndex);
|
||||
}
|
||||
}
|
||||
|
||||
recipeTabs.handleTooltip(mousex, mousey, currenttip);
|
||||
|
||||
if (currenttip.isEmpty() && searchField.isVisible()
|
||||
&& new Rectangle(searchField.x + searchField.w, 15, 44, 16)
|
||||
.contains(mousex - guiLeft, mousey - guiTop)) {
|
||||
|
||||
final String s = String.format("%d/%d", page + 1, (this.numRecipes() - 1) / getRecipesPerPage() + 1);
|
||||
|
||||
if (fontRendererObj.getStringWidth(s) >= 45) {
|
||||
currenttip.add(s);
|
||||
}
|
||||
}
|
||||
|
||||
return currenttip;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> handleItemTooltip(GuiContainer gui, ItemStack stack, int mousex, int mousey,
|
||||
List<String> currenttip) {
|
||||
|
||||
try (CompatibilityHacks compatibilityHacks = new CompatibilityHacks()) {
|
||||
for (int i : getRecipeIndices()) currenttip = handler.handleItemTooltip(this, stack, currenttip, i);
|
||||
for (int recipeIndex : getRecipeIndices()) {
|
||||
currenttip = handler.original.handleItemTooltip(this, stack, currenttip, recipeIndex);
|
||||
}
|
||||
}
|
||||
|
||||
return currenttip;
|
||||
@@ -530,13 +818,11 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
|
||||
}
|
||||
|
||||
private void nextPage() {
|
||||
page++;
|
||||
if (page > (handler.numRecipes() - 1) / getRecipesPerPage()) page = 0;
|
||||
changePage(1);
|
||||
}
|
||||
|
||||
private void prevPage() {
|
||||
page--;
|
||||
if (page < 0) page = (handler.numRecipes() - 1) / getRecipesPerPage();
|
||||
changePage(-1);
|
||||
}
|
||||
|
||||
protected void nextType() {
|
||||
@@ -547,32 +833,46 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
|
||||
setRecipePage(--recipetype);
|
||||
}
|
||||
|
||||
protected void overlayRecipe(int recipe, final boolean shift) {
|
||||
boolean moveItems = shift || !NEIClientConfig.requireShiftForOverlayRecipe();
|
||||
if (handler == null || !handler.hasOverlay(firstGui, firstGui.inventorySlots, recipe)) {
|
||||
mc.displayGuiScreen(firstGui);
|
||||
protected void overlayRecipe(int recipeIndex, final boolean shift) {
|
||||
|
||||
if (handler == null || !handler.original.hasOverlay(firstGui, firstGui.inventorySlots, recipeIndex)) {
|
||||
return;
|
||||
}
|
||||
final IRecipeOverlayRenderer renderer = handler.getOverlayRenderer(firstGui, recipe);
|
||||
final IOverlayHandler overlayHandler = handler.getOverlayHandler(firstGui, recipe);
|
||||
|
||||
mc.displayGuiScreen(firstGui);
|
||||
final boolean moveItems = shift || !NEIClientConfig.requireShiftForOverlayRecipe();
|
||||
final IRecipeOverlayRenderer renderer = handler.original.getOverlayRenderer(firstGui, recipeIndex);
|
||||
final IOverlayHandler overlayHandler = handler.original.getOverlayHandler(firstGui, recipeIndex);
|
||||
|
||||
if (renderer == null || moveItems) {
|
||||
if (overlayHandler != null) {
|
||||
overlayHandler.overlayRecipe(firstGui, currenthandlers.get(recipetype), recipe, moveItems);
|
||||
overlayHandler.overlayRecipe(firstGui, handler.original, recipeIndex, moveItems);
|
||||
}
|
||||
} else {
|
||||
LayoutManager.overlayRenderer = renderer;
|
||||
}
|
||||
}
|
||||
|
||||
protected void changePage(int shift) {
|
||||
final int recipesPerPage = getRecipesPerPage();
|
||||
final int numRecipes = this.numRecipes();
|
||||
|
||||
if (numRecipes > 0) {
|
||||
final int numPages = (int) Math.ceil(numRecipes / (float) recipesPerPage);
|
||||
this.page = Math.min(Math.max(0, this.page), numPages);
|
||||
this.page = (numPages + this.page + shift) % numPages;
|
||||
} else {
|
||||
this.page = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void refreshPage() {
|
||||
RecipeCatalysts.updatePosition(ySize - BG_TOP_HEIGHT - (GuiRecipeCatalyst.fullBorder * 2));
|
||||
changePage(0);
|
||||
refreshSlots();
|
||||
final int recipesPerPage = getRecipesPerPage();
|
||||
final boolean multiplepages = handler.numRecipes() > recipesPerPage;
|
||||
|
||||
final int numRecipes = Math.min(handler.numRecipes() - (page * recipesPerPage), recipesPerPage);
|
||||
final boolean multiplepages = this.numRecipes() > recipesPerPage;
|
||||
final int numRecipes = Math.min(this.numRecipes() - (page * recipesPerPage), recipesPerPage);
|
||||
|
||||
area.width = handlerInfo.getWidth();
|
||||
area.height = handlerInfo.getHeight() * numRecipes;
|
||||
@@ -580,6 +880,17 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
|
||||
area.y = guiTop - 4 + yShift;
|
||||
checkYShift();
|
||||
|
||||
if (!limitToOneRecipe) {
|
||||
toggleSearch.w = toggleSearch.h = 12;
|
||||
toggleSearch.x = borderPadding + buttonWidth;
|
||||
toggleSearch.y = 17;
|
||||
|
||||
searchField.y = 16;
|
||||
searchField.x = borderPadding + buttonWidth + toggleSearch.w - 1;
|
||||
searchField.w = xSize - (borderPadding + buttonWidth) * 2 + 1 - toggleSearch.w - 45;
|
||||
searchField.h = 14;
|
||||
}
|
||||
|
||||
nextpage.enabled = prevpage.enabled = multiplepages;
|
||||
|
||||
if (firstGui == null) {
|
||||
@@ -587,12 +898,13 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
|
||||
overlay.visible = false;
|
||||
}
|
||||
} else {
|
||||
final List<Integer> indices = getRecipeIndices();
|
||||
for (int i = 0; i < overlayButtons.length; i++) {
|
||||
if (i >= numRecipes) {
|
||||
if (i >= indices.size()) {
|
||||
overlayButtons[i].visible = false;
|
||||
} else {
|
||||
final int curRecipe = page * recipesPerPage + i;
|
||||
overlayButtons[i].visible = handler.hasOverlay(firstGui, firstGui.inventorySlots, curRecipe);
|
||||
overlayButtons[i].visible = handler.original
|
||||
.hasOverlay(firstGui, firstGui.inventorySlots, indices.get(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -602,9 +914,11 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
|
||||
|
||||
private void refreshSlots() {
|
||||
slotcontainer.inventorySlots.clear();
|
||||
final int recipesPerPage = getRecipesPerPage();
|
||||
for (int i = page * recipesPerPage; i < handler.numRecipes() && i < (page + 1) * recipesPerPage; i++) {
|
||||
Point p = getRecipePosition(i);
|
||||
final List<Integer> indices = getRecipeIndices();
|
||||
|
||||
for (int refIndex = 0; refIndex < indices.size(); refIndex++) {
|
||||
int recipeIndex = indices.get(refIndex);
|
||||
Point p = getRecipePosition(refIndex);
|
||||
// Legacy recipe handlers only expect a single paging widget at the top of the recipe screen, in contrast,
|
||||
// GTNH NEI moves the recipe paging widget from the bottom to the top, which means said legacy handlers will
|
||||
// position item slots 16px too high in the screen.
|
||||
@@ -612,36 +926,40 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
|
||||
p.translate(0, 16);
|
||||
}
|
||||
|
||||
List<PositionedStack> stacks = handler.getIngredientStacks(i);
|
||||
TemplateRecipeHandler.disableCycledIngredients = false;
|
||||
|
||||
List<PositionedStack> stacks = handler.original.getIngredientStacks(recipeIndex);
|
||||
for (PositionedStack stack : stacks) slotcontainer.addSlot(stack, p.x, p.y);
|
||||
|
||||
stacks = handler.getOtherStacks(i);
|
||||
stacks = handler.original.getOtherStacks(recipeIndex);
|
||||
for (PositionedStack stack : stacks) slotcontainer.addSlot(stack, p.x, p.y);
|
||||
|
||||
PositionedStack result = handler.getResultStack(i);
|
||||
PositionedStack result = handler.original.getResultStack(recipeIndex);
|
||||
if (result != null) slotcontainer.addSlot(result, p.x, p.y);
|
||||
|
||||
if (!limitToOneRecipe) {
|
||||
List<PositionedStack> catalysts = RecipeCatalysts.getRecipeCatalysts(handler);
|
||||
List<PositionedStack> catalysts = RecipeCatalysts.getRecipeCatalysts(handler.original);
|
||||
for (PositionedStack catalyst : catalysts) {
|
||||
int xOffset = -GuiRecipeCatalyst.ingredientSize + 1;
|
||||
int yOffset = BG_TOP_Y + GuiRecipeCatalyst.fullBorder;
|
||||
slotcontainer.addSlot(catalyst, xOffset, yOffset);
|
||||
}
|
||||
}
|
||||
|
||||
TemplateRecipeHandler.disableCycledIngredients = true;
|
||||
}
|
||||
}
|
||||
|
||||
private int itemPresenceCacheRecipe = -1;
|
||||
private ArrayList<Boolean> itemPresenceCacheSlots;
|
||||
|
||||
private void updateItemPresenceCache(int recipe) {
|
||||
private void updateItemPresenceCache(int recipeIndex) {
|
||||
if (itemPresenceCacheSlots == null) {
|
||||
itemPresenceCacheSlots = new ArrayList<>();
|
||||
}
|
||||
itemPresenceCacheRecipe = recipe;
|
||||
itemPresenceCacheRecipe = recipeIndex;
|
||||
itemPresenceCacheSlots.clear();
|
||||
List<PositionedStack> ingredients = handler.getIngredientStacks(recipe);
|
||||
List<PositionedStack> ingredients = handler.original.getIngredientStacks(recipeIndex);
|
||||
ArrayList<ItemStack> invStacks = ((List<Slot>) firstGui.inventorySlots.inventorySlots).stream()
|
||||
.filter(
|
||||
s -> s != null && s.getStack() != null
|
||||
@@ -665,42 +983,73 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
|
||||
GuiContainerManager.enable2DRender();
|
||||
final int recipesPerPage = getRecipesPerPage();
|
||||
final int ySkip = limitToOneRecipe ? 25 : 0;
|
||||
|
||||
if (!limitToOneRecipe) {
|
||||
String s = handler.getRecipeName().trim();
|
||||
String s = handler.original.getRecipeName().trim();
|
||||
fontRendererObj.drawStringWithShadow(s, (xSize - fontRendererObj.getStringWidth(s)) / 2, 5, 0xffffff);
|
||||
s = NEIClientUtils.translate("recipe.page", page + 1, (handler.numRecipes() - 1) / recipesPerPage + 1);
|
||||
fontRendererObj.drawStringWithShadow(s, (xSize - fontRendererObj.getStringWidth(s)) / 2, 19, 0xffffff);
|
||||
|
||||
if (handler.searchingAvailable()) {
|
||||
toggleSearch.draw(mouseX - guiLeft, mouseY - guiTop);
|
||||
}
|
||||
|
||||
if (searchField.isVisible()) {
|
||||
searchField.draw(mouseX - guiLeft, mouseY - guiTop);
|
||||
s = NEIClientUtils.cropText(
|
||||
fontRendererObj,
|
||||
String.format("%d/%d", page + 1, (this.numRecipes() - 1) / recipesPerPage + 1),
|
||||
45);
|
||||
fontRendererObj.drawStringWithShadow(
|
||||
s,
|
||||
searchField.x + searchField.w + (44 - fontRendererObj.getStringWidth(s)) / 2,
|
||||
19,
|
||||
0xffffff);
|
||||
} else {
|
||||
s = NEIClientUtils.translate("recipe.page", page + 1, (this.numRecipes() - 1) / recipesPerPage + 1);
|
||||
fontRendererObj.drawStringWithShadow(s, (xSize - fontRendererObj.getStringWidth(s)) / 2, 19, 0xffffff);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
final boolean drawItemPresence = NEIClientConfig.isJEIStyleItemPresenceOverlayVisible();
|
||||
|
||||
GL11.glPushMatrix();
|
||||
GL11.glTranslatef(5, 32 - ySkip + yShift, 0);
|
||||
try (CompatibilityHacks compatibilityHacks = new CompatibilityHacks()) {
|
||||
for (int i = page * recipesPerPage; i < handler.numRecipes() && i < (page + 1) * recipesPerPage; i++) {
|
||||
handler.drawForeground(i);
|
||||
if (drawItemPresence && (isMouseOverOverlayButton(i - page * recipesPerPage) || limitToOneRecipe)
|
||||
&& firstGui != null
|
||||
&& firstGui.inventorySlots != null) {
|
||||
List<PositionedStack> ingredients = handler.getIngredientStacks(i);
|
||||
if (itemPresenceCacheRecipe != i || itemPresenceCacheSlots == null
|
||||
List<Integer> indices = getRecipeIndices();
|
||||
|
||||
for (int refIndex = 0; refIndex < indices.size(); refIndex++) {
|
||||
int recipeIndex = indices.get(refIndex);
|
||||
|
||||
handler.original.drawForeground(recipeIndex);
|
||||
|
||||
if (drawItemPresence && firstGui != null
|
||||
&& firstGui.inventorySlots != null
|
||||
&& (isMouseOverOverlayButton(refIndex) || limitToOneRecipe)) {
|
||||
|
||||
List<PositionedStack> ingredients = handler.original.getIngredientStacks(recipeIndex);
|
||||
|
||||
if (itemPresenceCacheRecipe != recipeIndex || itemPresenceCacheSlots == null
|
||||
|| itemPresenceCacheSlots.size() != ingredients.size()) {
|
||||
updateItemPresenceCache(i);
|
||||
updateItemPresenceCache(recipeIndex);
|
||||
}
|
||||
|
||||
for (int j = 0; j < ingredients.size(); j++) {
|
||||
PositionedStack stack = ingredients.get(j);
|
||||
boolean isPresent = itemPresenceCacheSlots.get(j);
|
||||
LayoutManager.drawItemPresenceOverlay(stack.relx, stack.rely, isPresent);
|
||||
}
|
||||
}
|
||||
|
||||
GL11.glTranslatef(0, handlerInfo.getHeight(), 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
GL11.glPopMatrix();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawGuiContainerBackgroundLayer(float f, int mouseX, int mouseY) {
|
||||
final int recipesPerPage = getRecipesPerPage();
|
||||
final int ySkip = limitToOneRecipe ? 25 : 0;
|
||||
GL11.glColor4f(1, 1, 1, 1);
|
||||
|
||||
@@ -732,10 +1081,12 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
|
||||
GL11.glPushMatrix();
|
||||
GL11.glTranslatef(guiLeft + 5, guiTop - ySkip + 32 + yShift, 0);
|
||||
try (CompatibilityHacks compatibilityHacks = new CompatibilityHacks()) {
|
||||
for (int i = page * recipesPerPage; i < handler.numRecipes() && i < (page + 1) * recipesPerPage; i++) {
|
||||
handler.drawBackground(i);
|
||||
|
||||
for (int recipeIndex : getRecipeIndices()) {
|
||||
handler.original.drawBackground(recipeIndex);
|
||||
GL11.glTranslatef(0, handlerInfo.getHeight(), 0);
|
||||
}
|
||||
|
||||
}
|
||||
GL11.glPopMatrix();
|
||||
}
|
||||
@@ -781,10 +1132,10 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
|
||||
return firstGuiGeneral;
|
||||
}
|
||||
|
||||
public boolean isMouseOver(PositionedStack stack, int recipe) {
|
||||
Slot stackSlot = slotcontainer
|
||||
.getSlotWithStack(stack, getRecipePosition(recipe).x, getRecipePosition(recipe).y);
|
||||
public boolean isMouseOver(PositionedStack stack, int refIndex) {
|
||||
Point p = getRecipePosition(refIndex);
|
||||
Point mousepos = GuiDraw.getMousePosition();
|
||||
Slot stackSlot = slotcontainer.getSlotWithStack(stack, p.x, p.y);
|
||||
Slot mouseoverSlot = getSlotAtPosition(mousepos.x, mousepos.y);
|
||||
|
||||
return stackSlot == mouseoverSlot;
|
||||
@@ -808,13 +1159,19 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
|
||||
}
|
||||
|
||||
private int getRecipesPerPage(HandlerInfo handlerInfo) {
|
||||
if (handlerInfo != null) return Math.max(
|
||||
Math.min(((ySize - (buttonHeight * 3)) / handlerInfo.getHeight()), handlerInfo.getMaxRecipesPerPage()),
|
||||
1);
|
||||
else return (handler.recipiesPerPage());
|
||||
if (handlerInfo != null) {
|
||||
return Math.max(
|
||||
Math.min(
|
||||
((ySize - (buttonHeight * 3)) / handlerInfo.getHeight()),
|
||||
handlerInfo.getMaxRecipesPerPage()),
|
||||
1);
|
||||
} else if (handler != null) {
|
||||
return handler.original.recipiesPerPage();
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
public Point getRecipePosition(int recipe) {
|
||||
public Point getRecipePosition(int refIndex) {
|
||||
// Legacy recipe handlers using the height hack might use getRecipePosition in combination with guiTop/height to
|
||||
// position certain elements like tooltips. Since guiTop is moved down by 16px during height hacking, we need to
|
||||
// reduce the vertical shift here to 16px instead of 32px.
|
||||
@@ -822,7 +1179,7 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
|
||||
5,
|
||||
(isHeightHackApplied ? 16 : 32) - (limitToOneRecipe ? 25 : 0)
|
||||
+ yShift
|
||||
+ ((recipe % getRecipesPerPage()) * handlerInfo.getHeight()));
|
||||
+ ((refIndex % getRecipesPerPage()) * handlerInfo.getHeight()));
|
||||
}
|
||||
|
||||
public abstract ArrayList<H> getCurrentRecipeHandlers();
|
||||
@@ -844,9 +1201,27 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
|
||||
|
||||
@Override
|
||||
public boolean handleDragNDrop(GuiContainer gui, int mousex, int mousey, ItemStack draggedStack, int button) {
|
||||
|
||||
if (searchField.isVisible() && searchField.contains(mousex - guiLeft, mousey - guiTop)) {
|
||||
final FluidStack fluidStack = StackInfo.getFluid(draggedStack);
|
||||
|
||||
if (fluidStack != null) {
|
||||
searchField.setText(formattingText(fluidStack.getLocalizedName()));
|
||||
} else {
|
||||
searchField.setText(formattingText(draggedStack.getDisplayName()));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected String formattingText(String displayName) {
|
||||
return Pattern.compile("[{}()\\[\\].+*?^$\\\\|]")
|
||||
.matcher(EnumChatFormatting.getTextWithoutFormattingCodes(displayName)).replaceAll("\\\\$0");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hideItemPanelSlot(GuiContainer gui, int x, int y, int w, int h) {
|
||||
// Because some of the handlers *cough avaritia* are oversized
|
||||
@@ -855,11 +1230,14 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
|
||||
|
||||
protected static BookmarkRecipeId getCurrentRecipe(GuiScreen gui) {
|
||||
|
||||
if (gui instanceof GuiRecipe) {
|
||||
GuiRecipe<?> gRecipe = (GuiRecipe<?>) gui;
|
||||
if (gui instanceof GuiRecipe && ((GuiRecipe<?>) gui).handler.numRecipes() > 0) {
|
||||
final GuiRecipe<?> gRecipe = (GuiRecipe<?>) gui;
|
||||
final List<Integer> indices = gRecipe.getRecipeIndices();
|
||||
final int curRecipe = indices.isEmpty() ? 0 : indices.get(0);
|
||||
|
||||
return new BookmarkRecipeId(
|
||||
gRecipe.handlerInfo.getHandlerName(),
|
||||
gRecipe.getHandler().getIngredientStacks(gRecipe.page * gRecipe.getRecipesPerPage()));
|
||||
gRecipe.handler.original.getIngredientStacks(curRecipe));
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
@@ -43,7 +43,7 @@ public class GuiRecipeTabs {
|
||||
categoriesPerPage = 0;
|
||||
numHandlers = guiRecipe.currenthandlers.size();
|
||||
|
||||
for (IRecipeHandler handler : guiRecipe.currenthandlers) {
|
||||
for (int i = 0; i < numHandlers; i++) {
|
||||
if (totalWidth + tabWidth < (guiRecipe.xSize - 4)) {
|
||||
totalWidth += tabWidth;
|
||||
categoriesPerPage++;
|
||||
@@ -79,9 +79,11 @@ public class GuiRecipeTabs {
|
||||
IRecipeHandler handler = guiRecipe.currenthandlers.get(index);
|
||||
int tabX = area.x + (i * tabWidth);
|
||||
|
||||
if (NEIClientConfig.useCreativeTabStyle())
|
||||
if (NEIClientConfig.useCreativeTabStyle()) {
|
||||
tabs.add(new GuiRecipeTabCreative(guiRecipe, handler, tabX, area.y));
|
||||
else tabs.add(new GuiRecipeTabJEI(guiRecipe, handler, tabX, area.y));
|
||||
} else {
|
||||
tabs.add(new GuiRecipeTabJEI(guiRecipe, handler, tabX, area.y));
|
||||
}
|
||||
}
|
||||
|
||||
// Maybe add buttons
|
||||
|
||||
@@ -26,19 +26,17 @@ public class GuiUsageRecipe extends GuiRecipe<IUsageHandler> {
|
||||
|
||||
Minecraft mc = NEIClientUtils.mc();
|
||||
BookmarkRecipeId recipeId = getCurrentRecipe(mc.currentScreen);
|
||||
GuiUsageRecipe gui = new GuiUsageRecipe(handlers, recipeId);
|
||||
GuiUsageRecipe gui = new GuiUsageRecipe(handlers);
|
||||
|
||||
mc.displayGuiScreen(gui);
|
||||
|
||||
gui.openTargetRecipe(gui.recipeId);
|
||||
gui.openTargetRecipe(recipeId);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private GuiUsageRecipe(ArrayList<IUsageHandler> handlers, BookmarkRecipeId recipeId) {
|
||||
private GuiUsageRecipe(ArrayList<IUsageHandler> handlers) {
|
||||
super(NEIClientUtils.mc().currentScreen);
|
||||
this.currenthandlers = handlers;
|
||||
this.recipeId = recipeId;
|
||||
}
|
||||
|
||||
public static void registerUsageHandler(IUsageHandler handler) {
|
||||
|
||||
@@ -52,14 +52,14 @@ public interface IRecipeHandler {
|
||||
|
||||
/**
|
||||
* Draw the background of this recipe handler (basically the slot layout image).
|
||||
*
|
||||
*
|
||||
* @param recipe The recipe index to draw at this position.
|
||||
*/
|
||||
void drawBackground(int recipe);
|
||||
|
||||
/**
|
||||
* Draw the foreground of this recipe handler (for things like progress bars).
|
||||
*
|
||||
*
|
||||
* @param recipe The recipe index to draw at this position.
|
||||
*/
|
||||
void drawForeground(int recipe);
|
||||
@@ -74,11 +74,11 @@ public interface IRecipeHandler {
|
||||
|
||||
/**
|
||||
*
|
||||
* @param recipetype The recipe index to get items for.
|
||||
* @param recipe The recipe index to get items for.
|
||||
* @return A list of the other {@link PositionedStack}s in this recipe relative to the top left corner of your
|
||||
* recipe drawing space. For example fuel in furnaces.
|
||||
*/
|
||||
List<PositionedStack> getOtherStacks(int recipetype);
|
||||
List<PositionedStack> getOtherStacks(int recipe);
|
||||
|
||||
/**
|
||||
*
|
||||
|
||||
@@ -80,7 +80,7 @@ public class ProfilerRecipeHandler implements ICraftingHandler, IUsageHandler {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayList<PositionedStack> getOtherStacks(int recipetype) {
|
||||
public ArrayList<PositionedStack> getOtherStacks(int recipe) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
|
||||
@@ -37,6 +37,7 @@ class RecipeHandlerQuery<T extends IRecipeHandler> {
|
||||
profiler.start(profilerSection);
|
||||
try {
|
||||
ArrayList<T> handlers = getRecipeHandlersParallel();
|
||||
|
||||
if (error) {
|
||||
displayRecipeLookupError();
|
||||
}
|
||||
@@ -60,27 +61,37 @@ class RecipeHandlerQuery<T extends IRecipeHandler> {
|
||||
}
|
||||
|
||||
private ArrayList<T> getSerialHandlersWithRecipes() {
|
||||
|
||||
return serialRecipeHandlers.stream().map(handler -> {
|
||||
try {
|
||||
return recipeHandlerFunction.apply(handler);
|
||||
return isHidden(handler) ? null : recipeHandlerFunction.apply(handler);
|
||||
} catch (Throwable t) {
|
||||
printLog(t);
|
||||
error = true;
|
||||
return null;
|
||||
}
|
||||
}).filter(h -> h != null && h.numRecipes() > 0).collect(Collectors.toCollection(ArrayList::new));
|
||||
}).filter(h -> h != null && h.numRecipes() > 0 && SearchRecipeHandler.findFirst(h, (recipeIndex) -> true) != -1)
|
||||
.collect(Collectors.toCollection(ArrayList::new));
|
||||
}
|
||||
|
||||
private ArrayList<T> getHandlersWithRecipes() throws InterruptedException, ExecutionException {
|
||||
|
||||
return ItemList.forkJoinPool.submit(() -> recipeHandlers.parallelStream().map(handler -> {
|
||||
try {
|
||||
return recipeHandlerFunction.apply(handler);
|
||||
return isHidden(handler) ? null : recipeHandlerFunction.apply(handler);
|
||||
} catch (Throwable t) {
|
||||
printLog(t);
|
||||
error = true;
|
||||
return null;
|
||||
}
|
||||
}).filter(h -> h != null && h.numRecipes() > 0).collect(Collectors.toCollection(ArrayList::new))).get();
|
||||
}).filter(h -> h != null && h.numRecipes() > 0 && SearchRecipeHandler.findFirst(h, (recipeIndex) -> true) != -1)
|
||||
.collect(Collectors.toCollection(ArrayList::new))).get();
|
||||
}
|
||||
|
||||
private boolean isHidden(T handler) {
|
||||
final String handlerName = handler.getHandlerId();
|
||||
final String handlerId = handler.getOverlayIdentifier();
|
||||
return NEIClientConfig.hiddenHandlers.stream().anyMatch(h -> h.equals(handlerId) || h.equals(handlerName));
|
||||
}
|
||||
|
||||
private void printLog(Throwable t) {
|
||||
|
||||
@@ -0,0 +1,120 @@
|
||||
package codechicken.nei.recipe;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.IntStream;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import codechicken.nei.ItemList;
|
||||
import codechicken.nei.api.IRecipeFilter;
|
||||
|
||||
class SearchRecipeHandler<H extends IRecipeHandler> {
|
||||
|
||||
public H original;
|
||||
|
||||
private ArrayList<Integer> filteredRecipes;
|
||||
|
||||
private ArrayList<Integer> searchRecipes;
|
||||
|
||||
public SearchRecipeHandler(H handler) {
|
||||
this.original = handler;
|
||||
|
||||
if (this.original.numRecipes() == 0) {
|
||||
this.filteredRecipes = new ArrayList<>();
|
||||
} else {
|
||||
final Stream<Integer> items = IntStream.range(0, this.original.numRecipes()).boxed();
|
||||
final IRecipeFilter filter = this.searchingAvailable() ? GuiRecipe.getRecipeListFilter() : null;
|
||||
|
||||
if (filter == null) {
|
||||
this.filteredRecipes = items.collect(Collectors.toCollection(ArrayList::new));
|
||||
} else {
|
||||
this.filteredRecipes = items.filter(recipe -> mathRecipe(this.original, recipe, filter))
|
||||
.collect(Collectors.toCollection(ArrayList::new));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected static boolean mathRecipe(IRecipeHandler handler, int recipe, IRecipeFilter filter) {
|
||||
return filter.matches(
|
||||
handler,
|
||||
handler.getIngredientStacks(recipe),
|
||||
handler.getResultStack(recipe),
|
||||
handler.getOtherStacks(recipe));
|
||||
}
|
||||
|
||||
public boolean searchingAvailable() {
|
||||
return SearchRecipeHandler.searchingAvailable(this.original);
|
||||
}
|
||||
|
||||
private static boolean searchingAvailable(IRecipeHandler handler) {
|
||||
return handler instanceof TemplateRecipeHandler;
|
||||
}
|
||||
|
||||
public static int findFirst(IRecipeHandler handler, Predicate<Integer> predicate) {
|
||||
final IRecipeFilter filter = searchingAvailable(handler) ? GuiRecipe.getRecipeListFilter() : null;
|
||||
int refIndex = -1;
|
||||
|
||||
for (int recipeIndex = 0; recipeIndex < handler.numRecipes(); recipeIndex++) {
|
||||
if (filter == null || mathRecipe(handler, recipeIndex, filter)) {
|
||||
refIndex++;
|
||||
|
||||
if (predicate.test(recipeIndex)) {
|
||||
return refIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
public ArrayList<Integer> getSearchResult(IRecipeFilter filter) {
|
||||
|
||||
if (filteredRecipes.isEmpty() || !this.searchingAvailable()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
ArrayList<Integer> filtered = null;
|
||||
final ArrayList<Integer> recipes = IntStream.range(0, filteredRecipes.size()).boxed()
|
||||
.collect(Collectors.toCollection(ArrayList::new));
|
||||
|
||||
try {
|
||||
filtered = ItemList.forkJoinPool.submit(
|
||||
() -> recipes.parallelStream()
|
||||
.filter(recipe -> mathRecipe(this.original, filteredRecipes.get(recipe), filter))
|
||||
.collect(Collectors.toCollection(ArrayList::new)))
|
||||
.get();
|
||||
|
||||
filtered.sort((a, b) -> a - b);
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
e.printStackTrace();
|
||||
|
||||
}
|
||||
|
||||
return filtered;
|
||||
}
|
||||
|
||||
public void setSearchIndices(ArrayList<Integer> searchRecipes) {
|
||||
this.searchRecipes = searchRecipes;
|
||||
}
|
||||
|
||||
public int ref(int index) {
|
||||
|
||||
if (searchRecipes != null) {
|
||||
index = searchRecipes.get(index);
|
||||
}
|
||||
|
||||
return filteredRecipes.get(index);
|
||||
}
|
||||
|
||||
public int numRecipes() {
|
||||
|
||||
if (searchRecipes != null) {
|
||||
return searchRecipes.size();
|
||||
}
|
||||
|
||||
return filteredRecipes.size();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -8,14 +8,18 @@ import java.io.InputStreamReader;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.WeakHashMap;
|
||||
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.NBTBase;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.nbt.NBTTagList;
|
||||
import net.minecraftforge.fluids.FluidContainerRegistry;
|
||||
import net.minecraftforge.fluids.FluidStack;
|
||||
import net.minecraftforge.fluids.IFluidContainerItem;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
||||
@@ -29,6 +33,13 @@ public class StackInfo {
|
||||
public static final ArrayList<IStackStringifyHandler> stackStringifyHandlers = new ArrayList<>();
|
||||
private static final HashMap<String, HashMap<String, String[]>> guidfilters = new HashMap<>();
|
||||
private static final WeakHashMap<ItemStack, String> guidcache = new WeakHashMap<>();
|
||||
private static final LinkedHashMap<ItemStack, FluidStack> fluidcache = new LinkedHashMap<ItemStack, FluidStack>() {
|
||||
|
||||
@Override
|
||||
protected boolean removeEldestEntry(Map.Entry<ItemStack, FluidStack> eldest) {
|
||||
return size() > 20;
|
||||
}
|
||||
};
|
||||
|
||||
static {
|
||||
stackStringifyHandlers.add(new DefaultStackStringifyHandler());
|
||||
@@ -49,11 +60,24 @@ public class StackInfo {
|
||||
return nbTag;
|
||||
}
|
||||
|
||||
public static ItemStack loadFromNBT(NBTTagCompound nbtTag, long customCount) {
|
||||
|
||||
if (nbtTag != null) {
|
||||
nbtTag = (NBTTagCompound) nbtTag.copy();
|
||||
nbtTag.setInteger("Count", (int) Math.max(Math.min(customCount, Integer.MAX_VALUE), 0));
|
||||
return loadFromNBT(nbtTag);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static ItemStack loadFromNBT(NBTTagCompound nbtTag) {
|
||||
ItemStack stack = null;
|
||||
|
||||
for (int i = stackStringifyHandlers.size() - 1; i >= 0 && nbtTag != null && stack == null; i--) {
|
||||
stack = stackStringifyHandlers.get(i).convertNBTToItemStack(nbtTag);
|
||||
if (nbtTag != null) {
|
||||
for (int i = stackStringifyHandlers.size() - 1; i >= 0 && stack == null; i--) {
|
||||
stack = stackStringifyHandlers.get(i).convertNBTToItemStack(nbtTag);
|
||||
}
|
||||
}
|
||||
|
||||
return stack;
|
||||
@@ -76,15 +100,24 @@ public class StackInfo {
|
||||
}
|
||||
|
||||
public static FluidStack getFluid(ItemStack stack) {
|
||||
FluidStack fluid = null;
|
||||
FluidStack fluid = fluidcache.get(stack);
|
||||
|
||||
for (int i = stackStringifyHandlers.size() - 1; i >= 0 && fluid == null; i--) {
|
||||
fluid = stackStringifyHandlers.get(i).getFluid(stack);
|
||||
if (fluid == null && !fluidcache.containsKey(stack)) {
|
||||
|
||||
for (int i = stackStringifyHandlers.size() - 1; i >= 0 && fluid == null; i--) {
|
||||
fluid = stackStringifyHandlers.get(i).getFluid(stack);
|
||||
}
|
||||
|
||||
fluidcache.put(stack, fluid);
|
||||
}
|
||||
|
||||
return fluid;
|
||||
}
|
||||
|
||||
public static boolean isFluidContainer(ItemStack stack) {
|
||||
return stack.getItem() instanceof IFluidContainerItem || FluidContainerRegistry.isContainer(stack);
|
||||
}
|
||||
|
||||
public static String getItemStackGUID(ItemStack stack) {
|
||||
if (!guidcache.containsKey(stack)) {
|
||||
|
||||
|
||||
@@ -34,6 +34,8 @@ import com.google.common.base.Stopwatch;
|
||||
|
||||
import codechicken.lib.vec.Rectangle4i;
|
||||
import codechicken.nei.ItemList;
|
||||
import codechicken.nei.ItemList.AllMultiItemFilter;
|
||||
import codechicken.nei.LayoutManager;
|
||||
import codechicken.nei.NEIClientConfig;
|
||||
import codechicken.nei.NEIClientUtils;
|
||||
import codechicken.nei.NEIServerUtils;
|
||||
@@ -42,6 +44,8 @@ import codechicken.nei.api.DefaultOverlayRenderer;
|
||||
import codechicken.nei.api.IOverlayHandler;
|
||||
import codechicken.nei.api.IRecipeOverlayRenderer;
|
||||
import codechicken.nei.api.IStackPositioner;
|
||||
import codechicken.nei.api.ItemFilter;
|
||||
import codechicken.nei.api.ItemInfo;
|
||||
import codechicken.nei.guihook.GuiContainerManager;
|
||||
import codechicken.nei.guihook.IContainerInputHandler;
|
||||
import codechicken.nei.guihook.IContainerTooltipHandler;
|
||||
@@ -174,7 +178,7 @@ public abstract class TemplateRecipeHandler implements ICraftingHandler, IUsageH
|
||||
|
||||
/**
|
||||
* This will perform default cycling of ingredients, mulitItem capable
|
||||
*
|
||||
*
|
||||
* @param cycle Current cycle step
|
||||
* @param ingredients List of ItemStacks to cycle
|
||||
* @return The provided list of ingredients, with their permutations cycled to a different permutation, if one
|
||||
@@ -182,30 +186,53 @@ public abstract class TemplateRecipeHandler implements ICraftingHandler, IUsageH
|
||||
*/
|
||||
public List<PositionedStack> getCycledIngredients(int cycle, List<PositionedStack> ingredients) {
|
||||
|
||||
if (!NEIClientUtils.shiftKey()) {
|
||||
if (!NEIClientUtils.shiftKey() && !disableCycledIngredients) {
|
||||
if (NEIClientConfig.useJEIStyledCycledIngredients()) {
|
||||
jeiStyledRenderPermutation(ingredients, cycle);
|
||||
} else {
|
||||
for (int itemIndex = 0; itemIndex < ingredients.size(); itemIndex++) {
|
||||
randomRenderPermutation(ingredients.get(itemIndex), cycle + itemIndex);
|
||||
}
|
||||
randomRenderPermutation(ingredients, cycle);
|
||||
}
|
||||
}
|
||||
|
||||
return ingredients;
|
||||
}
|
||||
|
||||
public void randomRenderPermutation(PositionedStack stack, long cycle) {
|
||||
Random rand = new Random(cycle + offset);
|
||||
stack.setPermutationToRender(Math.abs(rand.nextInt()) % stack.items.length);
|
||||
protected void randomRenderPermutation(List<PositionedStack> stacks, long cycle) {
|
||||
final ItemFilter filter = getItemFilter();
|
||||
final int randCycle = Math.abs(new Random(cycle + offset).nextInt());
|
||||
|
||||
for (PositionedStack stack : stacks) {
|
||||
if (stack.items.length <= 1) continue;
|
||||
ArrayList<Integer> filtered = getFilteredIngredientAlternatives(stack, filter);
|
||||
if (filtered.isEmpty()) {
|
||||
stack.setPermutationToRender((int) (randCycle % stack.items.length));
|
||||
} else {
|
||||
stack.setPermutationToRender(filtered.get((int) (randCycle % filtered.size())));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void jeiStyledRenderPermutation(List<PositionedStack> stacks, long cycle) {
|
||||
protected void jeiStyledRenderPermutation(List<PositionedStack> stacks, long cycle) {
|
||||
final ItemFilter filter = getItemFilter();
|
||||
|
||||
for (PositionedStack stack : stacks) {
|
||||
stack.setPermutationToRender((int) (cycle % stack.items.length));
|
||||
if (stack.items.length <= 1) continue;
|
||||
ArrayList<Integer> filtered = getFilteredIngredientAlternatives(stack, filter);
|
||||
if (filtered.isEmpty()) {
|
||||
stack.setPermutationToRender((int) (cycle % stack.items.length));
|
||||
} else {
|
||||
stack.setPermutationToRender(filtered.get((int) (cycle % filtered.size())));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
protected void randomRenderPermutation(PositionedStack stack, long cycle) {
|
||||
Random rand = new Random(cycle + offset);
|
||||
stack.setPermutationToRender((int) (Math.abs(rand.nextInt()) % stack.items.length));
|
||||
}
|
||||
|
||||
public void setIngredientPermutation(Collection<PositionedStack> ingredients, ItemStack ingredient) {
|
||||
for (PositionedStack stack : ingredients) {
|
||||
for (int i = 0; i < stack.items.length; i++) {
|
||||
@@ -396,11 +423,32 @@ public abstract class TemplateRecipeHandler implements ICraftingHandler, IUsageH
|
||||
*/
|
||||
public LinkedList<RecipeTransferRect> transferRects = new LinkedList<>();
|
||||
|
||||
public static boolean disableCycledIngredients = true;
|
||||
|
||||
public TemplateRecipeHandler() {
|
||||
loadTransferRects();
|
||||
RecipeTransferRectHandler.registerRectsToGuis(getRecipeTransferRectGuis(), transferRects);
|
||||
}
|
||||
|
||||
protected static ItemFilter getItemFilter() {
|
||||
return new AllMultiItemFilter(
|
||||
item -> !ItemInfo.hiddenItems.contains(item),
|
||||
LayoutManager.presetsPanel != null ? LayoutManager.presetsPanel.getFilter() : null,
|
||||
GuiRecipe.searchField != null ? GuiRecipe.searchField.getFilter() : null);
|
||||
}
|
||||
|
||||
protected static ArrayList<Integer> getFilteredIngredientAlternatives(PositionedStack stack, ItemFilter filter) {
|
||||
final ArrayList<Integer> filtered = new ArrayList<>();
|
||||
|
||||
for (int i = 0; i < stack.items.length; i++) {
|
||||
if (filter.matches(stack.items[i])) {
|
||||
filtered.add(i);
|
||||
}
|
||||
}
|
||||
|
||||
return filtered;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add all RecipeTransferRects to the transferRects list during this call. Afterward they may be added to the input
|
||||
* handler for the corresponding guis from getRecipeTransferRectGuis
|
||||
@@ -541,7 +589,8 @@ public abstract class TemplateRecipeHandler implements ICraftingHandler, IUsageH
|
||||
|
||||
public TemplateRecipeHandler newInstance() {
|
||||
try {
|
||||
// Use the non parallel version since we might already be using the forkJoinPool and might have no threads
|
||||
// Use the non parallel version since we might already be using the forkJoinPool
|
||||
// and might have no threads
|
||||
// available
|
||||
// This will ideally have been pre-cached elsewhere and will be a NOOP
|
||||
findFuelsOnce();
|
||||
@@ -680,8 +729,12 @@ public abstract class TemplateRecipeHandler implements ICraftingHandler, IUsageH
|
||||
|
||||
@Override
|
||||
public boolean mouseClicked(GuiRecipe<?> gui, int button, int recipe) {
|
||||
if (button == 0) return transferRect(gui, recipe, false);
|
||||
else if (button == 1) return transferRect(gui, recipe, true);
|
||||
|
||||
if (button == 0) {
|
||||
return transferRect(gui, recipe, false);
|
||||
} else if (button == 1) {
|
||||
return transferRect(gui, recipe, true);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -690,29 +743,58 @@ public abstract class TemplateRecipeHandler implements ICraftingHandler, IUsageH
|
||||
public boolean mouseScrolled(GuiRecipe<?> gui, int scroll, int recipe) {
|
||||
if (!NEIClientUtils.shiftKey()) return false;
|
||||
|
||||
final Point offset = gui.getRecipePosition(recipe);
|
||||
final Point pos = getMousePosition();
|
||||
final Point offset = gui.getRecipePosition(recipe);
|
||||
final Point relMouse = new Point(pos.x - gui.guiLeft - offset.x, pos.y - gui.guiTop - offset.y);
|
||||
final PositionedStack overStack = getIngredientMouseOver(relMouse.x, relMouse.y, recipe);
|
||||
|
||||
for (PositionedStack pStack : getIngredientStacks(recipe)) {
|
||||
if ((new Rectangle4i(pStack.relx, pStack.rely, 18, 18)).contains(relMouse.x, relMouse.y)) {
|
||||
int index = pStack.items.length + scroll;
|
||||
if (overStack != null && overStack.items.length > 1) {
|
||||
final ItemFilter filter = getItemFilter();
|
||||
|
||||
for (int i = 0; i < pStack.items.length; i++) {
|
||||
if (NEIServerUtils.areStacksSameTypeCraftingWithNBT(pStack.items[i], pStack.item)) {
|
||||
index = index + i;
|
||||
break;
|
||||
}
|
||||
if (NEIClientConfig.useJEIStyledCycledIngredients()) {
|
||||
ItemStack stack = overStack.item;
|
||||
for (PositionedStack pStack : getIngredientStacks(recipe)) {
|
||||
shiftPermutationToRender(pStack, stack, scroll, filter);
|
||||
}
|
||||
|
||||
pStack.setPermutationToRender(index % pStack.items.length);
|
||||
return true;
|
||||
} else {
|
||||
shiftPermutationToRender(overStack, overStack.item, scroll, filter);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void shiftPermutationToRender(PositionedStack pStack, ItemStack stack, int scroll, ItemFilter filter) {
|
||||
|
||||
for (int index = 0; index < pStack.items.length; index++) {
|
||||
if (NEIServerUtils.areStacksSameTypeCraftingWithNBT(pStack.items[index], stack)) {
|
||||
ArrayList<Integer> filtered = getFilteredIngredientAlternatives(pStack, filter);
|
||||
|
||||
if (filtered.isEmpty()) {
|
||||
pStack.setPermutationToRender((int) ((pStack.items.length + scroll + index) % pStack.items.length));
|
||||
} else {
|
||||
pStack.setPermutationToRender(
|
||||
filtered.get((int) ((filtered.size() + scroll + index) % filtered.size())));
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private PositionedStack getIngredientMouseOver(int mousex, int mousey, int recipe) {
|
||||
|
||||
for (PositionedStack pStack : getIngredientStacks(recipe)) {
|
||||
if ((new Rectangle4i(pStack.relx, pStack.rely, 18, 18)).contains(mousex, mousey)) {
|
||||
return pStack;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean transferRect(GuiRecipe<?> gui, int recipe, boolean usage) {
|
||||
Point offset = gui.getRecipePosition(recipe);
|
||||
return transferRect(gui, transferRects, offset.x, offset.y, usage);
|
||||
|
||||
@@ -21,7 +21,7 @@ public class DefaultStackStringifyHandler implements IStackStringifyHandler {
|
||||
|
||||
final NBTTagCompound nbTag = new NBTTagCompound();
|
||||
nbTag.setString("strId", strId);
|
||||
nbTag.setInteger("Count", Math.max(saveStackSize ? stack.stackSize : 1, 1));
|
||||
nbTag.setInteger("Count", saveStackSize ? stack.stackSize : 1);
|
||||
nbTag.setShort("Damage", (short) stack.getItemDamage());
|
||||
|
||||
if (stack.hasTagCompound()) {
|
||||
|
||||
@@ -2,6 +2,7 @@ package codechicken.nei.recipe.stackinfo;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraftforge.fluids.Fluid;
|
||||
@@ -9,16 +10,18 @@ import net.minecraftforge.fluids.FluidRegistry;
|
||||
import net.minecraftforge.fluids.FluidStack;
|
||||
|
||||
import codechicken.nei.api.IStackStringifyHandler;
|
||||
import cpw.mods.fml.common.registry.GameRegistry;
|
||||
|
||||
public class GTFluidStackStringifyHandler implements IStackStringifyHandler {
|
||||
|
||||
public static Class GTDisplayFluid = null;
|
||||
public static Method getFluidDisplayStack = null;
|
||||
public static Method getFluidFromDisplayStack = null;
|
||||
protected static Class<?> GTDisplayFluid = null;
|
||||
protected static Method getFluidDisplayStack = null;
|
||||
protected static Method getFluidFromDisplayStack = null;
|
||||
public static boolean replaceAE2FCFluidDrop = false;
|
||||
|
||||
static {
|
||||
try {
|
||||
final Class gtUtility = Class.forName("gregtech.api.util.GT_Utility");
|
||||
final Class<?> gtUtility = Class.forName("gregtech.api.util.GT_Utility");
|
||||
|
||||
GTDisplayFluid = Class.forName("gregtech.common.items.GT_FluidDisplayItem");
|
||||
getFluidFromDisplayStack = gtUtility.getMethod("getFluidFromDisplayStack", ItemStack.class);
|
||||
@@ -31,13 +34,13 @@ public class GTFluidStackStringifyHandler implements IStackStringifyHandler {
|
||||
|
||||
public NBTTagCompound convertItemStackToNBT(ItemStack stack, boolean saveStackSize) {
|
||||
|
||||
if (GTDisplayFluid != null && GTDisplayFluid.isInstance(stack.getItem())) {
|
||||
if (replaceAE2FCFluidDrop || stack.getItem() != GameRegistry.findItem("ae2fc", "fluid_drop")) {
|
||||
final FluidStack fluidStack = getFluid(stack);
|
||||
|
||||
if (fluidStack != null) {
|
||||
final NBTTagCompound nbTag = new NBTTagCompound();
|
||||
nbTag.setString("gtFluidName", fluidStack.getFluid().getName());
|
||||
nbTag.setInteger("Count", saveStackSize ? fluidStack.amount : 1);
|
||||
nbTag.setInteger("Count", saveStackSize ? fluidStack.amount : 144);
|
||||
return nbTag;
|
||||
}
|
||||
}
|
||||
@@ -66,17 +69,33 @@ public class GTFluidStackStringifyHandler implements IStackStringifyHandler {
|
||||
}
|
||||
|
||||
public FluidStack getFluid(ItemStack stack) {
|
||||
final Item item = stack.getItem();
|
||||
|
||||
if (getFluidFromDisplayStack != null && GTDisplayFluid != null && GTDisplayFluid.isInstance(stack.getItem())) {
|
||||
try {
|
||||
try {
|
||||
if (getFluidFromDisplayStack != null && GTDisplayFluid != null && GTDisplayFluid.isInstance(item)) {
|
||||
final Object obj = getFluidFromDisplayStack.invoke(null, stack);
|
||||
|
||||
if (obj != null) {
|
||||
return (FluidStack) obj;
|
||||
}
|
||||
|
||||
} catch (Exception e) {}
|
||||
}
|
||||
} else if (item == GameRegistry.findItem("ae2fc", "fluid_packet")) {
|
||||
NBTTagCompound nbtTag = stack.getTagCompound();
|
||||
|
||||
return FluidStack.loadFluidStackFromNBT((NBTTagCompound) nbtTag.getTag("FluidStack"));
|
||||
} else if (item == GameRegistry.findItem("ae2fc", "fluid_drop")) {
|
||||
NBTTagCompound nbtTag = stack.getTagCompound();
|
||||
Fluid fluid = FluidRegistry.getFluid(nbtTag.getString("Fluid").toLowerCase());
|
||||
|
||||
if (fluid != null) {
|
||||
FluidStack fluidStack = new FluidStack(fluid, stack.stackSize);
|
||||
if (nbtTag.hasKey("FluidTag")) {
|
||||
fluidStack.tag = nbtTag.getCompoundTag("FluidTag");
|
||||
}
|
||||
return fluidStack;
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -112,6 +112,7 @@ nei.options.keys.gui.bookmark=Add Bookmark
|
||||
nei.options.keys.gui.bookmark_recipe=Add Bookmark with Recipe
|
||||
nei.options.keys.gui.bookmark_count=Add Bookmark with Count
|
||||
nei.options.keys.gui.bookmark_pull_items=Pull all Bookmarked Items
|
||||
nei.options.keys.gui.bookmark_pull_items_ingredients=Pull all Bookmarked Ingredients
|
||||
nei.options.keys.gui.bookmark_recipe_count=Add Bookmark with Recipe & Count
|
||||
nei.options.keys.gui.hide_bookmarks=Toggle Bookmark Panel Visibility
|
||||
nei.options.keys.gui.overlay=Overlay Recipe
|
||||
@@ -155,12 +156,11 @@ nei.options.inventory.jei_style_recipe_catalyst.false=No
|
||||
nei.options.inventory.saveCurrentRecipeInBookmarksEnabled=Save Current Recipe in Bookmarks
|
||||
nei.options.inventory.saveCurrentRecipeInBookmarksEnabled.true=Enabled
|
||||
nei.options.inventory.saveCurrentRecipeInBookmarksEnabled.false=Disabled
|
||||
nei.options.inventory.useNBTInBookmarks=Use NBT in Bookmarks
|
||||
nei.options.inventory.useNBTInBookmarks.true=Yes
|
||||
nei.options.inventory.useNBTInBookmarks.false=No
|
||||
nei.options.inventory.recipeTooltipsEnabled=Show recipe tooltips in Bookmarks
|
||||
nei.options.inventory.recipeTooltipsEnabled.true=Yes
|
||||
nei.options.inventory.recipeTooltipsEnabled.false=No
|
||||
nei.options.inventory.recipeTooltipsMode=Show recipe tooltips in Bookmarks
|
||||
nei.options.inventory.recipeTooltipsMode.0=None
|
||||
nei.options.inventory.recipeTooltipsMode.1=In Horizontal View
|
||||
nei.options.inventory.recipeTooltipsMode.2=In Vertical View
|
||||
nei.options.inventory.recipeTooltipsMode.3=Always
|
||||
nei.options.inventory.bookmarksAnimationEnabled=REI Style Animation in Bookmarks
|
||||
nei.options.inventory.bookmarksAnimationEnabled.true=Yes
|
||||
nei.options.inventory.bookmarksAnimationEnabled.false=No
|
||||
@@ -348,6 +348,8 @@ nei.presets.blacklist.label=B
|
||||
nei.presets.blacklist.tooltip=Blacklist
|
||||
nei.presets.whitelist.label=W
|
||||
nei.presets.whitelist.tooltip=Whitelist
|
||||
nei.presets.blacklistPlus.label=B+
|
||||
nei.presets.blacklistPlus.tooltip=Blacklist Plus
|
||||
nei.presets.textfield.tooltip.1=Enter - save
|
||||
nei.presets.textfield.tooltip.2=Escape - cancel
|
||||
nei.presets.label.tooltip=Double click to edit
|
||||
|
||||
@@ -147,9 +147,6 @@ nei.options.inventory.jei_style_recipe_catalyst.false=否
|
||||
nei.options.inventory.saveCurrentRecipeInBookmarksEnabled=保存书签中的当前合成表
|
||||
nei.options.inventory.saveCurrentRecipeInBookmarksEnabled.true=启用
|
||||
nei.options.inventory.saveCurrentRecipeInBookmarksEnabled.false=禁用
|
||||
nei.options.inventory.useNBTInBookmarks=在书签中启用NBT
|
||||
nei.options.inventory.useNBTInBookmarks.true=是
|
||||
nei.options.inventory.useNBTInBookmarks.false=否
|
||||
nei.options.inventory.bookmarksAnimationEnabled=REI风格书签动画
|
||||
nei.options.inventory.bookmarksAnimationEnabled.true=是
|
||||
nei.options.inventory.bookmarksAnimationEnabled.false=否
|
||||
@@ -271,7 +268,7 @@ nei.recipe.furnace=烧制
|
||||
nei.recipe.fuel=燃料
|
||||
nei.recipe.fuel.smeltCount=可冶炼%s个物品
|
||||
# Deprecated
|
||||
nei.recipe.fuel.required=需要%s个
|
||||
nei.recipe.fuel.required=需要%s个
|
||||
# Deprecated
|
||||
nei.recipe.fuel.processed=可烧制%s个
|
||||
# Deprecated
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 37 KiB After Width: | Height: | Size: 34 KiB |
Reference in new issue
Block a user