mirror of
https://github.com/GTNewHorizons/NotEnoughItems.git
synced 2026-10-27 14:53:59 +00:00
Compare commits
9
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3495af917b | ||
|
|
46436bf0de | ||
|
|
b6fc6f0b3f | ||
|
|
46d8509e9e | ||
|
|
c03e9d0442 | ||
|
|
60bb4bca3b | ||
|
|
1dd204a084 | ||
|
|
1ab46be684 | ||
|
|
501fa70037 |
No files matched your search
@@ -14,11 +14,13 @@ import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.WeakHashMap;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
@@ -98,8 +100,7 @@ public class BookmarkPanel extends PanelWidget {
|
||||
ItemStackMetadata meta = topItemIndex >= 0 ? BGrid.metadata.get(topItemIndex) : null;
|
||||
|
||||
if (meta != null && meta.recipeId != null) {
|
||||
while (topItemIndex > 0 && meta.groupId == BGrid.metadata.get(topItemIndex - 1).groupId
|
||||
&& meta.recipeId.equals(BGrid.metadata.get(topItemIndex - 1).recipeId)) {
|
||||
while (topItemIndex > 0 && meta.equalsRecipe(BGrid.metadata.get(topItemIndex - 1))) {
|
||||
topItemIndex--;
|
||||
}
|
||||
|
||||
@@ -118,8 +119,7 @@ public class BookmarkPanel extends PanelWidget {
|
||||
if (meta != null && meta.recipeId != null) {
|
||||
int size = BGrid.size();
|
||||
|
||||
while (bottomItemIndex < size - 1 && meta.groupId == BGrid.metadata.get(bottomItemIndex + 1).groupId
|
||||
&& meta.recipeId.equals(BGrid.metadata.get(bottomItemIndex + 1).recipeId)) {
|
||||
while (bottomItemIndex < size - 1 && meta.equalsRecipe(BGrid.metadata.get(bottomItemIndex + 1))) {
|
||||
bottomItemIndex++;
|
||||
}
|
||||
|
||||
@@ -148,9 +148,21 @@ public class BookmarkPanel extends PanelWidget {
|
||||
this.fluidDisplay = fluidDisplay;
|
||||
}
|
||||
|
||||
public ItemStackMetadata(BookmarkRecipeId recipeId, NBTTagCompound nbTag, boolean ingredient, Integer groupId) {
|
||||
this(recipeId, nbTag.getInteger("Count"), ingredient, groupId, nbTag.hasKey("gtFluidName"));
|
||||
}
|
||||
|
||||
public ItemStackMetadata copy() {
|
||||
return new ItemStackMetadata(this.recipeId, this.factor, this.ingredient, this.groupId, this.fluidDisplay);
|
||||
}
|
||||
|
||||
public boolean equalsRecipe(ItemStackMetadata meta) {
|
||||
return equalsRecipe(meta.recipeId, meta.groupId);
|
||||
}
|
||||
|
||||
public boolean equalsRecipe(BookmarkRecipeId recipeId, int groupId) {
|
||||
return groupId == this.groupId && recipeId != null && recipeId.equals(this.recipeId);
|
||||
}
|
||||
}
|
||||
|
||||
public static enum BookmarkViewMode {
|
||||
@@ -163,6 +175,26 @@ public class BookmarkPanel extends PanelWidget {
|
||||
LOADED
|
||||
}
|
||||
|
||||
public static class BookmarkRecipe {
|
||||
|
||||
public String handlerName = "";
|
||||
public List<ItemStack> result = new ArrayList<>();
|
||||
public List<ItemStack> ingredients = new ArrayList<>();
|
||||
|
||||
public BookmarkRecipe(ItemStack... result) {
|
||||
this.result.addAll(Arrays.asList(result));
|
||||
}
|
||||
|
||||
public BookmarkRecipeId getRecipeId() {
|
||||
|
||||
if (!handlerName.isEmpty() && !ingredients.isEmpty()) {
|
||||
return new BookmarkRecipeId(handlerName, ingredients);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
protected static class BookmarkGroup {
|
||||
|
||||
public BookmarkCraftingChain crafting = null;
|
||||
@@ -607,8 +639,7 @@ public class BookmarkPanel extends PanelWidget {
|
||||
final ArrayList<Integer> items = new ArrayList<>();
|
||||
|
||||
for (int index = idx; index < size; index++) {
|
||||
if (this.metadata.get(index).groupId == groupId
|
||||
&& meta.recipeId.equals(this.metadata.get(index).recipeId)) {
|
||||
if (meta.equalsRecipe(this.metadata.get(index))) {
|
||||
sortingRank.put(index, (this.metadata.get(index).ingredient ? 1 : -1) * dir);
|
||||
items.add(index);
|
||||
}
|
||||
@@ -756,7 +787,7 @@ public class BookmarkPanel extends PanelWidget {
|
||||
final ItemStackMetadata meta = getMetadata(idx);
|
||||
if (meta.groupId == groupId
|
||||
&& (recipeId == null && meta.recipeId == null
|
||||
|| recipeId != null && meta.recipeId != null && recipeId.equals(meta.recipeId))
|
||||
|| recipeId != null && recipeId.equals(meta.recipeId))
|
||||
&& StackInfo.equalItemAndNBT(stackA, getItem(idx), true)) {
|
||||
return idx;
|
||||
}
|
||||
@@ -797,9 +828,15 @@ public class BookmarkPanel extends PanelWidget {
|
||||
}
|
||||
|
||||
protected void removeRecipe(int idx, boolean removeFullRecipe) {
|
||||
final ItemStackMetadata meta = getMetadata(idx);
|
||||
final ItemStackMetadata meta = this.metadata.get(idx);
|
||||
|
||||
if (meta.recipeId != null && (removeFullRecipe || !meta.ingredient)) {
|
||||
if (!removeFullRecipe && meta.recipeId != null && !meta.ingredient) {
|
||||
final Optional<ItemStackMetadata> result = this.metadata.stream()
|
||||
.filter(m -> m != meta && !m.ingredient && meta.equalsRecipe(m)).findAny();
|
||||
removeFullRecipe = !result.isPresent();
|
||||
}
|
||||
|
||||
if (meta.recipeId != null && removeFullRecipe) {
|
||||
removeRecipe(meta.recipeId, meta.groupId);
|
||||
} else {
|
||||
removeItem(idx);
|
||||
@@ -807,12 +844,9 @@ public class BookmarkPanel extends PanelWidget {
|
||||
}
|
||||
|
||||
protected void removeRecipe(BookmarkRecipeId recipeIdA, int groupId) {
|
||||
BookmarkRecipeId recipeIdB;
|
||||
|
||||
for (int slotIndex = metadata.size() - 1; slotIndex >= 0; slotIndex--) {
|
||||
recipeIdB = metadata.get(slotIndex).recipeId;
|
||||
|
||||
if (recipeIdB != null && metadata.get(slotIndex).groupId == groupId && recipeIdB.equals(recipeIdA)) {
|
||||
if (metadata.get(slotIndex).equalsRecipe(recipeIdA, groupId)) {
|
||||
removeItem(slotIndex);
|
||||
}
|
||||
}
|
||||
@@ -889,14 +923,12 @@ public class BookmarkPanel extends PanelWidget {
|
||||
drawRect(rect.x, rect.y, rect.w, rect.h, 0x9966CCFF); // exports
|
||||
}
|
||||
|
||||
} else if (focus != null && meta.recipeId != null
|
||||
&& meta.groupId == getMetadata(focus.slotIndex).groupId
|
||||
&& meta.recipeId.equals(this.getRecipeId(focus.slotIndex))) {
|
||||
drawRect(rect.x, rect.y, rect.w, rect.h, meta.ingredient ? 0x6645DA75 : 0x9966CCFF); // highlight
|
||||
// recipe
|
||||
} else {
|
||||
super.beforeDrawSlot(focus, idx, rect);
|
||||
}
|
||||
} else if (focus != null && meta.equalsRecipe(getMetadata(focus.slotIndex))) {
|
||||
drawRect(rect.x, rect.y, rect.w, rect.h, meta.ingredient ? 0x6645DA75 : 0x9966CCFF); // highlight
|
||||
// recipe
|
||||
} else {
|
||||
super.beforeDrawSlot(focus, idx, rect);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -920,11 +952,9 @@ public class BookmarkPanel extends PanelWidget {
|
||||
if (groupMeta.crafting != null && meta.groupId == this.focusedGroupId
|
||||
&& groupMeta.crafting.multiplier.containsKey(stack)) {
|
||||
multiplier = this.groups.get(meta.groupId).crafting.multiplier.get(stack);
|
||||
} else if (focus != null && meta.factor > 0
|
||||
&& meta.groupId == this.metadata.get(focus.slotIndex).groupId
|
||||
&& meta.recipeId.equals(this.metadata.get(focus.slotIndex).recipeId)) {
|
||||
multiplier = StackInfo.itemStackToNBT(stack).getInteger("Count") / meta.factor;
|
||||
}
|
||||
} else if (focus != null && meta.factor > 0 && meta.equalsRecipe(getMetadata(focus.slotIndex))) {
|
||||
multiplier = StackInfo.itemStackToNBT(stack).getInteger("Count") / meta.factor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1219,7 +1249,7 @@ public class BookmarkPanel extends PanelWidget {
|
||||
addItem(itemStack, true);
|
||||
}
|
||||
|
||||
public void addItem(ItemStack itemStack, boolean saveStackSize) {
|
||||
public void addItem(ItemStack itemStack, boolean saveSize) {
|
||||
final BookmarkGrid BGrid = (BookmarkGrid) grid;
|
||||
int idx = BGrid.indexOf(itemStack, true);
|
||||
|
||||
@@ -1227,7 +1257,7 @@ public class BookmarkPanel extends PanelWidget {
|
||||
BGrid.removeItem(idx);
|
||||
}
|
||||
|
||||
addOrRemoveItem(itemStack, null, null, false, saveStackSize);
|
||||
addOrRemoveItem(itemStack, null, null, false, saveSize);
|
||||
}
|
||||
|
||||
public void addOrRemoveItem(ItemStack stackA) {
|
||||
@@ -1235,7 +1265,7 @@ public class BookmarkPanel extends PanelWidget {
|
||||
}
|
||||
|
||||
public void addOrRemoveItem(ItemStack stackover, final String handlerName, final List<PositionedStack> ingredients,
|
||||
boolean saveIngredients, boolean saveStackSize) {
|
||||
boolean saveIngredients, boolean saveSize) {
|
||||
loadBookmarksIfNeeded();
|
||||
|
||||
final Point mousePos = getMousePosition();
|
||||
@@ -1245,61 +1275,35 @@ public class BookmarkPanel extends PanelWidget {
|
||||
if (slot != null && StackInfo.equalItemAndNBT(slot.item, stackover, true)) {
|
||||
BGrid.removeRecipe(slot.slotIndex, saveIngredients);
|
||||
} else {
|
||||
final NBTTagCompound nbTagA = StackInfo.itemStackToNBT(stackover, saveStackSize);
|
||||
final ItemStack normalizedA = StackInfo.loadFromNBT(nbTagA, saveStackSize ? nbTagA.getInteger("Count") : 0);
|
||||
BookmarkRecipeId recipeId = null;
|
||||
|
||||
if (handlerName != "" && ingredients != null) {
|
||||
if (!handlerName.isEmpty() && ingredients != null) {
|
||||
recipeId = new BookmarkRecipeId(handlerName, ingredients);
|
||||
}
|
||||
|
||||
final int idx = BGrid.indexOf(normalizedA, recipeId);
|
||||
final int idx = BGrid.indexOf(stackover, recipeId);
|
||||
|
||||
if (idx != -1) {
|
||||
BGrid.removeRecipe(idx, saveIngredients);
|
||||
} else {
|
||||
} else if (saveIngredients && !handlerName.isEmpty() && ingredients != null) {
|
||||
BookmarkRecipe recipe = new BookmarkRecipe(stackover);
|
||||
recipe.handlerName = handlerName;
|
||||
|
||||
if (saveIngredients && handlerName != "" && ingredients != null) {
|
||||
final Map<String, Integer> ingredientCount = new HashMap<>();
|
||||
final Map<String, NBTTagCompound> uniqueIngredients = new LinkedHashMap<>();
|
||||
|
||||
BGrid.removeRecipe(recipeId, BookmarkGrid.DEFAULT_GROUP_ID);
|
||||
|
||||
for (PositionedStack stack : ingredients) {
|
||||
final NBTTagCompound nbTag = StackInfo.itemStackToNBT(stack.item, saveStackSize);
|
||||
final String GUID = StackInfo.getItemStackGUID(stack.item);
|
||||
|
||||
if (!uniqueIngredients.containsKey(GUID)) {
|
||||
ingredientCount.put(GUID, nbTag.getInteger("Count"));
|
||||
uniqueIngredients.put(GUID, nbTag);
|
||||
} else {
|
||||
ingredientCount.put(GUID, ingredientCount.get(GUID) + nbTag.getInteger("Count"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
for (String GUID : uniqueIngredients.keySet()) {
|
||||
BGrid.addItem(
|
||||
StackInfo.loadFromNBT(
|
||||
uniqueIngredients.get(GUID),
|
||||
saveStackSize ? ingredientCount.get(GUID) : 0),
|
||||
new ItemStackMetadata(
|
||||
recipeId != null ? recipeId.copy() : null,
|
||||
ingredientCount.get(GUID),
|
||||
true,
|
||||
BookmarkGrid.DEFAULT_GROUP_ID,
|
||||
uniqueIngredients.get(GUID).hasKey("gtFluidName")));
|
||||
}
|
||||
for (PositionedStack stack : ingredients) {
|
||||
recipe.ingredients.add(stack.item);
|
||||
}
|
||||
|
||||
BGrid.addItem(
|
||||
normalizedA,
|
||||
new ItemStackMetadata(
|
||||
recipeId,
|
||||
nbTagA.getInteger("Count"),
|
||||
false,
|
||||
BookmarkGrid.DEFAULT_GROUP_ID,
|
||||
nbTagA.hasKey("gtFluidName")));
|
||||
addRecipe(recipe, saveSize);
|
||||
} else {
|
||||
final NBTTagCompound nbTag = StackInfo.itemStackToNBT(stackover);
|
||||
final ItemStack normalized = StackInfo.loadFromNBT(nbTag, saveSize ? nbTag.getInteger("Count") : 0);
|
||||
final ItemStackMetadata metadata = new ItemStackMetadata(
|
||||
recipeId,
|
||||
nbTag,
|
||||
false,
|
||||
BookmarkGrid.DEFAULT_GROUP_ID);
|
||||
|
||||
BGrid.addItem(normalized, metadata);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1307,6 +1311,92 @@ public class BookmarkPanel extends PanelWidget {
|
||||
saveBookmarks();
|
||||
}
|
||||
|
||||
public void addRecipe(BookmarkRecipe recipe, boolean saveSize) {
|
||||
addRecipe(recipe, saveSize, BookmarkGrid.DEFAULT_GROUP_ID);
|
||||
}
|
||||
|
||||
public void addRecipe(BookmarkRecipe recipe, boolean saveSize, int groupId) {
|
||||
final BookmarkGrid BGrid = (BookmarkGrid) grid;
|
||||
final BookmarkRecipeId recipeId = recipe.getRecipeId();
|
||||
|
||||
if (!BGrid.groups.containsKey(groupId)) {
|
||||
groupId = BookmarkGrid.DEFAULT_GROUP_ID;
|
||||
}
|
||||
|
||||
if (recipeId != null) {
|
||||
final Map<String, NBTTagCompound> uniqueIngredients = new LinkedHashMap<>();
|
||||
|
||||
BGrid.removeRecipe(recipeId, groupId);
|
||||
|
||||
for (ItemStack stack : recipe.ingredients) {
|
||||
final String GUID = StackInfo.getItemStackGUID(stack);
|
||||
final NBTTagCompound nbTagU = uniqueIngredients.get(GUID);
|
||||
final NBTTagCompound nbTagS = StackInfo.itemStackToNBT(stack);
|
||||
|
||||
if (nbTagU == null) {
|
||||
uniqueIngredients.put(GUID, nbTagS);
|
||||
} else {
|
||||
nbTagU.setInteger("Count", nbTagU.getInteger("Count") + nbTagS.getInteger("Count"));
|
||||
}
|
||||
}
|
||||
|
||||
for (String GUID : uniqueIngredients.keySet()) {
|
||||
final NBTTagCompound nbTag = uniqueIngredients.get(GUID);
|
||||
final ItemStack normalized = StackInfo.loadFromNBT(nbTag, saveSize ? nbTag.getInteger("Count") : 0);
|
||||
final ItemStackMetadata metadata = new ItemStackMetadata(recipeId.copy(), nbTag, true, groupId);
|
||||
|
||||
BGrid.addItem(normalized, metadata);
|
||||
}
|
||||
}
|
||||
|
||||
for (ItemStack stack : recipe.result) {
|
||||
final NBTTagCompound nbTag = StackInfo.itemStackToNBT(stack);
|
||||
final ItemStack normalized = StackInfo.loadFromNBT(nbTag, saveSize ? nbTag.getInteger("Count") : 0);
|
||||
final ItemStackMetadata metadata = new ItemStackMetadata(recipeId, nbTag, false, groupId);
|
||||
|
||||
BGrid.addItem(normalized, metadata);
|
||||
}
|
||||
|
||||
fixCountOfNamespaces();
|
||||
saveBookmarks();
|
||||
}
|
||||
|
||||
public void addBookmarkGroup(List<ItemStack> items, BookmarkViewMode viewMode) {
|
||||
List<BookmarkRecipe> recipes = new ArrayList<>();
|
||||
|
||||
for (ItemStack stack : items) {
|
||||
recipes.add(new BookmarkRecipe(stack));
|
||||
}
|
||||
|
||||
addBookmarkGroup(recipes, viewMode, false);
|
||||
}
|
||||
|
||||
public void addBookmarkGroup(List<BookmarkRecipe> recipes, BookmarkViewMode viewMode, boolean crafting) {
|
||||
if (recipes.isEmpty()) return;
|
||||
|
||||
final BookmarkGrid BGrid = (BookmarkGrid) grid;
|
||||
int groupId = BookmarkGrid.DEFAULT_GROUP_ID;
|
||||
|
||||
if (viewMode == null) {
|
||||
viewMode = BGrid.getViewMode(BookmarkGrid.DEFAULT_GROUP_ID);
|
||||
}
|
||||
|
||||
for (ItemStackMetadata meta : BGrid.metadata) {
|
||||
if (meta.groupId > groupId) {
|
||||
groupId = meta.groupId;
|
||||
}
|
||||
}
|
||||
|
||||
BGrid.groups.put(++groupId, new BookmarkGroup(viewMode, crafting));
|
||||
|
||||
for (BookmarkRecipe recipe : recipes) {
|
||||
addRecipe(recipe, true, groupId);
|
||||
}
|
||||
|
||||
fixCountOfNamespaces();
|
||||
saveBookmarks();
|
||||
}
|
||||
|
||||
public BookmarkRecipeId getBookmarkRecipeId(int slotIndex) {
|
||||
ItemStackMetadata meta = ((BookmarkGrid) grid).getMetadata(slotIndex);
|
||||
return meta.ingredient ? null : meta.recipeId;
|
||||
@@ -1774,8 +1864,7 @@ public class BookmarkPanel extends PanelWidget {
|
||||
} else {
|
||||
|
||||
for (int i = 0; i < BGrid.metadata.size(); i++) {
|
||||
if (BGrid.metadata.get(i).recipeId != null && meta.groupId == BGrid.metadata.get(i).groupId
|
||||
&& meta.recipeId.equals(BGrid.metadata.get(i).recipeId)) {
|
||||
if (meta.equalsRecipe(BGrid.getMetadata(i))) {
|
||||
items.add(BGrid.realItems.get(i));
|
||||
metadata.add(BGrid.metadata.get(i));
|
||||
}
|
||||
@@ -1822,7 +1911,7 @@ public class BookmarkPanel extends PanelWidget {
|
||||
} else if (ySlot <= 0.25) {
|
||||
|
||||
if (BGrid.getViewMode(beforeGroupId) == BookmarkViewMode.TODO_LIST
|
||||
&& !existsRecipeIdInGroupId(beforeGroupId, sortMeta.recipeId)) {
|
||||
&& !existsRecipeIdInGroupId(sortMeta.recipeId, beforeGroupId)) {
|
||||
BGrid.moveItem(this.sortableItem, mouseOverSlot.slotIndex, beforeGroupId, true);
|
||||
}
|
||||
|
||||
@@ -1832,12 +1921,12 @@ public class BookmarkPanel extends PanelWidget {
|
||||
&& (afterGroupId != BookmarkGrid.DEFAULT_GROUP_ID
|
||||
|| BGrid.getViewMode(overGroupId) == BookmarkViewMode.DEFAULT)
|
||||
&& BGrid.getViewMode(BookmarkGrid.DEFAULT_GROUP_ID) == BookmarkViewMode.TODO_LIST
|
||||
&& !existsRecipeIdInGroupId(BookmarkGrid.DEFAULT_GROUP_ID, sortMeta.recipeId)) {
|
||||
&& !existsRecipeIdInGroupId(sortMeta.recipeId, BookmarkGrid.DEFAULT_GROUP_ID)) {
|
||||
beforeGroupId = BookmarkGrid.DEFAULT_GROUP_ID;
|
||||
}
|
||||
|
||||
if (BGrid.getViewMode(beforeGroupId) == BookmarkViewMode.TODO_LIST
|
||||
&& !existsRecipeIdInGroupId(beforeGroupId, sortMeta.recipeId)) {
|
||||
&& !existsRecipeIdInGroupId(sortMeta.recipeId, beforeGroupId)) {
|
||||
BGrid.moveItem(this.sortableItem, mouseOverSlot.slotIndex, beforeGroupId, true);
|
||||
}
|
||||
|
||||
@@ -1848,12 +1937,12 @@ public class BookmarkPanel extends PanelWidget {
|
||||
|| BGrid.getViewMode(overGroupId) == BookmarkViewMode.DEFAULT)
|
||||
&& afterGroupId != BookmarkGrid.DEFAULT_GROUP_ID
|
||||
&& BGrid.getViewMode(BookmarkGrid.DEFAULT_GROUP_ID) == BookmarkViewMode.TODO_LIST
|
||||
&& !existsRecipeIdInGroupId(BookmarkGrid.DEFAULT_GROUP_ID, sortMeta.recipeId)) {
|
||||
&& !existsRecipeIdInGroupId(sortMeta.recipeId, BookmarkGrid.DEFAULT_GROUP_ID)) {
|
||||
afterGroupId = BookmarkGrid.DEFAULT_GROUP_ID;
|
||||
}
|
||||
|
||||
if (BGrid.getViewMode(afterGroupId) == BookmarkViewMode.TODO_LIST
|
||||
&& !existsRecipeIdInGroupId(afterGroupId, sortMeta.recipeId)) {
|
||||
&& !existsRecipeIdInGroupId(sortMeta.recipeId, afterGroupId)) {
|
||||
BGrid.moveItem(
|
||||
this.sortableItem,
|
||||
BGrid.getRowItemIndex(overRowIndex, false),
|
||||
@@ -1864,7 +1953,7 @@ public class BookmarkPanel extends PanelWidget {
|
||||
} else if (ySlot >= 0.75) {
|
||||
|
||||
if (BGrid.getViewMode(afterGroupId) == BookmarkViewMode.TODO_LIST
|
||||
&& !existsRecipeIdInGroupId(afterGroupId, sortMeta.recipeId)) {
|
||||
&& !existsRecipeIdInGroupId(sortMeta.recipeId, afterGroupId)) {
|
||||
BGrid.moveItem(
|
||||
this.sortableItem,
|
||||
BGrid.getRowItemIndex(overRowIndex, false),
|
||||
@@ -1909,12 +1998,11 @@ public class BookmarkPanel extends PanelWidget {
|
||||
super.mouseDragged(mousex, mousey, button, heldTime);
|
||||
}
|
||||
|
||||
private boolean existsRecipeIdInGroupId(int groupId, BookmarkRecipeId recipeId) {
|
||||
private boolean existsRecipeIdInGroupId(BookmarkRecipeId recipeId, int groupId) {
|
||||
if (recipeId == null) return false;
|
||||
|
||||
for (ItemStackMetadata meta : ((BookmarkGrid) grid).metadata) {
|
||||
if (meta.groupId == groupId && this.sortableItem.metadata.indexOf(meta) == -1
|
||||
&& recipeId.equals(meta.recipeId)) {
|
||||
if (meta.equalsRecipe(recipeId, groupId) && this.sortableItem.metadata.indexOf(meta) == -1) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -2077,18 +2165,12 @@ public class BookmarkPanel extends PanelWidget {
|
||||
}
|
||||
|
||||
if (NEIClientUtils.shiftKey()) {
|
||||
ItemStackMetadata ingrMeta;
|
||||
|
||||
for (int slotIndex = grid.size() - 1; slotIndex >= 0; slotIndex--) {
|
||||
ingrMeta = BGrid.getMetadata(slotIndex);
|
||||
|
||||
if (ingrMeta.recipeId != null && ingrMeta.groupId == overMeta.groupId
|
||||
&& ingrMeta.recipeId.equals(overMeta.recipeId)
|
||||
&& slotIndex != slot.slotIndex) {
|
||||
if (overMeta.equalsRecipe(BGrid.getMetadata(slotIndex)) && slotIndex != slot.slotIndex) {
|
||||
items.put(slotIndex, shiftStackSize(BGrid, slotIndex, shift, shiftMultiplier));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
items.put(slot.slotIndex, shiftStackSize(BGrid, slot.slotIndex, shift, shiftMultiplier));
|
||||
|
||||
@@ -0,0 +1,364 @@
|
||||
package codechicken.nei;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.regex.PatternSyntaxException;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraftforge.oredict.OreDictionary;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
||||
import codechicken.nei.ItemList.AllMultiItemFilter;
|
||||
import codechicken.nei.ItemList.AnyMultiItemFilter;
|
||||
import codechicken.nei.ItemList.EverythingItemFilter;
|
||||
import codechicken.nei.ItemList.NegatedItemFilter;
|
||||
import codechicken.nei.ItemList.NothingItemFilter;
|
||||
import codechicken.nei.PresetsList.Preset;
|
||||
import codechicken.nei.PresetsList.PresetMode;
|
||||
import codechicken.nei.api.ItemFilter;
|
||||
import cpw.mods.fml.common.registry.GameData;
|
||||
|
||||
public class CollapsibleItems {
|
||||
|
||||
protected static interface ISearchParserProvider {
|
||||
|
||||
public ItemFilter getFilter(String searchText);
|
||||
|
||||
default Predicate<String> getMatcher(String searchText) {
|
||||
|
||||
if (searchText.length() >= 3 && searchText.startsWith("r/") && searchText.endsWith("/")) {
|
||||
|
||||
try {
|
||||
Pattern pattern = Pattern.compile(
|
||||
searchText.substring(2, searchText.length() - 1),
|
||||
Pattern.MULTILINE | Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE);
|
||||
return value -> pattern.matcher(value).find();
|
||||
} catch (PatternSyntaxException ignored) {}
|
||||
|
||||
} else if (!searchText.isEmpty()) {
|
||||
return value -> value.toLowerCase().contains(searchText);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected static class GroupTokenParser {
|
||||
|
||||
protected final HashMap<Character, ISearchParserProvider> searchProviders = new HashMap<>();
|
||||
|
||||
public void addProvider(char prefix, ISearchParserProvider provider) {
|
||||
this.searchProviders.put(prefix, provider);
|
||||
}
|
||||
|
||||
public ItemFilter getFilter(String filterText) {
|
||||
final String[] parts = filterText.toLowerCase().trim().split("\\|");
|
||||
final List<ItemFilter> searchTokens = Arrays.stream(parts).map(s -> parseSearchText(s))
|
||||
.filter(s -> s != null && !s.filters.isEmpty()).collect(Collectors.toCollection(ArrayList::new));
|
||||
|
||||
if (searchTokens.isEmpty()) {
|
||||
return new EverythingItemFilter();
|
||||
} else if (searchTokens.size() == 1) {
|
||||
return searchTokens.get(0);
|
||||
} else {
|
||||
return new AnyMultiItemFilter(searchTokens);
|
||||
}
|
||||
}
|
||||
|
||||
private AllMultiItemFilter parseSearchText(String filterText) {
|
||||
|
||||
if (filterText.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final String[] tokens = filterText.split("\\s+");
|
||||
final AllMultiItemFilter searchTokens = new AllMultiItemFilter();
|
||||
|
||||
for (String token : tokens) {
|
||||
token = token.trim();
|
||||
boolean ignore = token.startsWith("!");
|
||||
|
||||
if (ignore) {
|
||||
token = token.substring(1);
|
||||
}
|
||||
|
||||
if (token.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ISearchParserProvider provider = this.searchProviders.get(token.charAt(0));
|
||||
|
||||
if (provider != null) {
|
||||
token = token.substring(1);
|
||||
} else {
|
||||
provider = this.searchProviders.get('\0');
|
||||
}
|
||||
|
||||
ItemFilter filter = parseToken(ignore ? "!" + token : token, provider);
|
||||
|
||||
if (filter != null) {
|
||||
searchTokens.filters.add(filter);
|
||||
}
|
||||
}
|
||||
|
||||
return searchTokens;
|
||||
}
|
||||
|
||||
private ItemFilter parseToken(String token, ISearchParserProvider provider) {
|
||||
final String[] parts = token.split(",");
|
||||
final AnyMultiItemFilter includeFilter = new AnyMultiItemFilter();
|
||||
final AnyMultiItemFilter expludeFilter = new AnyMultiItemFilter();
|
||||
final AllMultiItemFilter groupFilter = new AllMultiItemFilter();
|
||||
|
||||
for (String part : parts) {
|
||||
boolean ignore = part.startsWith("!");
|
||||
|
||||
if (ignore) {
|
||||
part = part.substring(1);
|
||||
}
|
||||
|
||||
ItemFilter filter = provider.getFilter(part);
|
||||
|
||||
if (filter == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ignore) {
|
||||
expludeFilter.filters.add(filter);
|
||||
} else {
|
||||
includeFilter.filters.add(filter);
|
||||
}
|
||||
}
|
||||
|
||||
if (!includeFilter.filters.isEmpty()) {
|
||||
groupFilter.filters.add(includeFilter);
|
||||
}
|
||||
|
||||
if (!expludeFilter.filters.isEmpty()) {
|
||||
groupFilter.filters.add(new NegatedItemFilter(expludeFilter));
|
||||
}
|
||||
|
||||
return groupFilter.filters.isEmpty() ? null : groupFilter;
|
||||
}
|
||||
}
|
||||
|
||||
protected static class IdentifierFilter implements ISearchParserProvider {
|
||||
|
||||
@Override
|
||||
public ItemFilter getFilter(String searchText) {
|
||||
|
||||
if (Pattern.matches("^\\d+(-\\d+)*$", searchText)) {
|
||||
final Predicate<Integer> filter = generateDamageFilter(searchText);
|
||||
return (stack) -> filter.test(stack.getItemDamage());
|
||||
}
|
||||
|
||||
Predicate<String> matcher = getMatcher(searchText);
|
||||
|
||||
if (matcher != null) {
|
||||
return stack -> matcher.test(getStringIdentifier(stack));
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
protected String getStringIdentifier(ItemStack stack) {
|
||||
String name = GameData.getItemRegistry().getNameForObject(stack.getItem());
|
||||
return name == null || name.isEmpty() ? "Unknown:Unknown" : name;
|
||||
}
|
||||
|
||||
protected Predicate<Integer> generateDamageFilter(String searchText) {
|
||||
String[] range = searchText.split("-");
|
||||
|
||||
if (range.length == 1) {
|
||||
final int damage = Integer.parseInt(range[0]);
|
||||
return (dmg) -> dmg == damage;
|
||||
} else {
|
||||
final int damageStart = Integer.parseInt(range[0]);
|
||||
final int damageEnd = Integer.parseInt(range[1]);
|
||||
return (dmg) -> dmg >= damageStart && dmg <= damageEnd;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected static class OreDictionaryFilter implements ISearchParserProvider {
|
||||
|
||||
@Override
|
||||
public ItemFilter getFilter(String searchText) {
|
||||
Predicate<String> matcher = getMatcher(searchText);
|
||||
|
||||
if (matcher != null) {
|
||||
return stack -> matches(stack, matcher);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
protected boolean matches(ItemStack stack, Predicate<String> matcher) {
|
||||
return IntStream.of(OreDictionary.getOreIDs(stack))
|
||||
.anyMatch(id -> matcher.test(OreDictionary.getOreName(id)));
|
||||
}
|
||||
}
|
||||
|
||||
protected static class GroupItem {
|
||||
|
||||
protected static int lastGroupIndex = 0;
|
||||
|
||||
public final int groupIndex;
|
||||
public final ItemFilter filter;
|
||||
public boolean expanded = false;
|
||||
|
||||
public GroupItem(ItemFilter filter) {
|
||||
this.groupIndex = lastGroupIndex++;
|
||||
this.filter = filter;
|
||||
}
|
||||
|
||||
public boolean matches(ItemStack stack) {
|
||||
return this.filter.matches(stack);
|
||||
}
|
||||
}
|
||||
|
||||
protected static final GroupTokenParser groupParser = new GroupTokenParser();
|
||||
protected final Map<Integer, GroupItem> groups = new ConcurrentHashMap<>();
|
||||
protected final Map<ItemStack, Integer> cache = new ConcurrentHashMap<>();
|
||||
|
||||
static {
|
||||
groupParser.addProvider('\0', new IdentifierFilter());
|
||||
groupParser.addProvider('$', new OreDictionaryFilter());
|
||||
}
|
||||
|
||||
public void reload() {
|
||||
GroupItem.lastGroupIndex = 0;
|
||||
this.groups.clear();
|
||||
this.cache.clear();
|
||||
|
||||
for (int i = PresetsList.presets.size() - 1; i >= 0; i--) {
|
||||
Preset preset = PresetsList.presets.get(i);
|
||||
if (preset.enabled && preset.mode == PresetMode.GROUP) {
|
||||
addGroup(preset);
|
||||
}
|
||||
}
|
||||
|
||||
loadCollapsibleItems();
|
||||
|
||||
if (ItemList.loadFinished) {
|
||||
LayoutManager.markItemsDirty();
|
||||
}
|
||||
}
|
||||
|
||||
protected void loadCollapsibleItems() {
|
||||
File file = NEIClientConfig.collapsibleItemsFile;
|
||||
if (!file.exists()) {
|
||||
try (FileWriter writer = new FileWriter(file)) {
|
||||
NEIClientConfig.logger.info("Creating default collapsible items list {}", file);
|
||||
URL defaultCollapsibleItemsResource = ClientHandler.class
|
||||
.getResource("/assets/nei/cfg/collapsibleitems.cfg");
|
||||
if (defaultCollapsibleItemsResource != null) {
|
||||
IOUtils.copy(defaultCollapsibleItemsResource.openStream(), writer);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
NEIClientConfig.logger.error("Failed to save default collapsible items list to file {}", file, e);
|
||||
}
|
||||
}
|
||||
|
||||
try (FileReader reader = new FileReader(file)) {
|
||||
NEIClientConfig.logger.info("Loading collapsible items from file {}", file);
|
||||
IOUtils.readLines(reader).stream().filter((line) -> !line.startsWith("#") && !line.trim().isEmpty())
|
||||
.forEach(this::addGroup);
|
||||
} catch (IOException e) {
|
||||
NEIClientConfig.logger.error("Failed to load collapsible items from file {}", file, e);
|
||||
}
|
||||
}
|
||||
|
||||
protected void addGroup(String filterText) {
|
||||
addGroup(CollapsibleItems.groupParser.getFilter(filterText.trim()));
|
||||
}
|
||||
|
||||
protected void addGroup(ItemFilter filter) {
|
||||
if (filter == null || filter instanceof EverythingItemFilter || filter instanceof NothingItemFilter) return;
|
||||
GroupItem group = new GroupItem(filter);
|
||||
this.groups.put(group.groupIndex, group);
|
||||
}
|
||||
|
||||
public ItemFilter getItemFilter() {
|
||||
AnyMultiItemFilter filter = new AnyMultiItemFilter();
|
||||
|
||||
for (GroupItem group : this.groups.values()) {
|
||||
filter.filters.add(group.filter);
|
||||
}
|
||||
|
||||
return filter;
|
||||
}
|
||||
|
||||
public void updateCache(final List<ItemStack> items) {
|
||||
this.cache.clear();
|
||||
|
||||
try {
|
||||
|
||||
ItemList.forkJoinPool.submit(() -> items.parallelStream().forEach(stack -> {
|
||||
GroupItem group = this.groups.values().stream().filter(g -> g.matches(stack)).findFirst().orElse(null);
|
||||
|
||||
if (group != null) {
|
||||
this.cache.put(stack, group.groupIndex);
|
||||
}
|
||||
})).get();
|
||||
|
||||
} catch (Exception e) {
|
||||
NEIClientConfig.logger.error("Error create collapsible items groups", e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public int getGroupIndex(ItemStack stack) {
|
||||
|
||||
if (stack == null) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return this.cache.getOrDefault(stack, -1);
|
||||
}
|
||||
|
||||
public boolean isExpanded(int groupIndex) {
|
||||
|
||||
if (this.groups.containsKey(groupIndex)) {
|
||||
return this.groups.get(groupIndex).expanded;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void setExpanded(int groupIndex, boolean expanded) {
|
||||
|
||||
if (this.groups.containsKey(groupIndex)) {
|
||||
this.groups.get(groupIndex).expanded = expanded;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void toggleGroups(Boolean expanded) {
|
||||
|
||||
if (expanded == null) {
|
||||
expanded = !this.groups.values().stream().filter(g -> g.expanded).findAny().isPresent();
|
||||
}
|
||||
|
||||
for (GroupItem group : this.groups.values()) {
|
||||
group.expanded = expanded;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -8,7 +8,7 @@ import net.minecraft.util.EnumChatFormatting;
|
||||
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
class FormattedTextField extends GuiTextField {
|
||||
public class FormattedTextField extends GuiTextField {
|
||||
|
||||
public static interface TextFormatter {
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ package codechicken.nei;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
@@ -38,11 +39,12 @@ public class ItemList {
|
||||
* Updates to this should be synchronised on this
|
||||
*/
|
||||
public static final List<ItemFilterProvider> itemFilterers = new LinkedList<>();
|
||||
|
||||
public static final List<ItemsLoadedCallback> loadCallbacks = new LinkedList<>();
|
||||
public static final CollapsibleItems collapsibleItems = new CollapsibleItems();
|
||||
|
||||
private static final HashSet<Item> erroredItems = new HashSet<>();
|
||||
private static final HashSet<String> stackTraces = new HashSet<>();
|
||||
private static final HashMap<ItemStack, Integer> ordering = new HashMap<>();
|
||||
/**
|
||||
* Unlike {@link LayoutManager#itemsLoaded}, this indicates whether item loading is actually finished or not.
|
||||
*/
|
||||
@@ -223,6 +225,38 @@ public class ItemList {
|
||||
return "";
|
||||
}
|
||||
|
||||
private void updateOrdering(List<ItemStack> items) {
|
||||
ItemList.ordering.clear();
|
||||
|
||||
ItemSorter.sort(items);
|
||||
|
||||
if (NEIClientConfig.enableCollapsibleItems()) {
|
||||
HashMap<Integer, Integer> groups = new HashMap<>();
|
||||
int orderIndex = 0;
|
||||
|
||||
for (ItemStack stack : items) {
|
||||
final int groupIndex = ItemList.collapsibleItems.getGroupIndex(stack);
|
||||
|
||||
if (groupIndex == -1) {
|
||||
ItemList.ordering.put(stack, orderIndex++);
|
||||
} else {
|
||||
|
||||
if (!groups.containsKey(groupIndex)) {
|
||||
groups.put(groupIndex, orderIndex++);
|
||||
}
|
||||
|
||||
ItemList.ordering.put(stack, groups.get(groupIndex));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
int orderIndex = 0;
|
||||
|
||||
for (ItemStack stack : items) {
|
||||
ItemList.ordering.put(stack, orderIndex++);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void execute() {
|
||||
@@ -230,8 +264,8 @@ public class ItemList {
|
||||
ThreadOperationTimer timer = getTimer(NEIClientConfig.getItemLoadingTimeout());
|
||||
loadFinished = false;
|
||||
|
||||
LinkedList<ItemStack> items = new LinkedList<>();
|
||||
LinkedList<ItemStack> permutations = new LinkedList<>();
|
||||
List<ItemStack> items = new LinkedList<>();
|
||||
List<ItemStack> permutations = new LinkedList<>();
|
||||
ListMultimap<Item, ItemStack> itemMap = ArrayListMultimap.create();
|
||||
|
||||
timer.setLimit(NEIClientConfig.getItemLoadingTimeout());
|
||||
@@ -267,9 +301,12 @@ public class ItemList {
|
||||
ItemList.itemMap = itemMap;
|
||||
for (ItemsLoadedCallback callback : loadCallbacks) callback.itemsLoaded();
|
||||
|
||||
updateFilter.restart();
|
||||
if (interrupted()) return;
|
||||
ItemList.collapsibleItems.updateCache(items);
|
||||
updateOrdering(items);
|
||||
|
||||
loadFinished = true;
|
||||
updateFilter.restart();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -284,11 +321,15 @@ public class ItemList {
|
||||
|
||||
public static final RestartableTask updateFilter = new RestartableTask("NEI Item Filtering") {
|
||||
|
||||
private int compare(ItemStack o1, ItemStack o2) {
|
||||
return Integer.compare(ItemList.ordering.get(o1), ItemList.ordering.get(o2));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
// System.out.println("Executing NEI Item Filtering");
|
||||
ArrayList<ItemStack> filtered;
|
||||
if (!loadFinished) return;
|
||||
ItemFilter filter = getItemListFilter();
|
||||
ArrayList<ItemStack> filtered;
|
||||
|
||||
try {
|
||||
filtered = ItemList.forkJoinPool.submit(
|
||||
@@ -302,7 +343,7 @@ public class ItemList {
|
||||
}
|
||||
|
||||
if (interrupted()) return;
|
||||
ItemSorter.sort(filtered);
|
||||
filtered.sort(this::compare);
|
||||
if (interrupted()) return;
|
||||
ItemPanel.updateItemList(filtered);
|
||||
}
|
||||
|
||||
@@ -1,17 +1,27 @@
|
||||
package codechicken.nei;
|
||||
|
||||
import static codechicken.lib.gui.GuiDraw.drawRect;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import net.minecraft.client.gui.inventory.GuiContainer;
|
||||
import net.minecraft.client.renderer.OpenGlHelper;
|
||||
import net.minecraft.client.renderer.Tessellator;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.EnumChatFormatting;
|
||||
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import codechicken.lib.vec.Rectangle4i;
|
||||
import codechicken.nei.guihook.GuiContainerManager;
|
||||
import codechicken.nei.guihook.IContainerTooltipHandler;
|
||||
|
||||
public class ItemPanel extends PanelWidget {
|
||||
public class ItemPanel extends PanelWidget implements IContainerTooltipHandler {
|
||||
|
||||
/**
|
||||
* Backwards compat :-/
|
||||
@@ -35,6 +45,7 @@ public class ItemPanel extends PanelWidget {
|
||||
public Button less;
|
||||
public ItemQuantityField quantity;
|
||||
public ItemHistoryPanel historyPanel;
|
||||
public Button toggleGroups;
|
||||
|
||||
public static class ItemPanelSlot {
|
||||
|
||||
@@ -52,9 +63,29 @@ public class ItemPanel extends PanelWidget {
|
||||
}
|
||||
}
|
||||
|
||||
protected static class MaskMetadata {
|
||||
|
||||
public int groupIndex = -1;
|
||||
public boolean extended = false;
|
||||
|
||||
public Color bgColor = null;
|
||||
public Color color = null;
|
||||
|
||||
public boolean left = false;
|
||||
public boolean top = false;
|
||||
public boolean right = false;
|
||||
public boolean bottom = false;
|
||||
|
||||
}
|
||||
|
||||
protected static class ItemPanelGrid extends ItemsGrid {
|
||||
|
||||
public ArrayList<ItemStack> newItems;
|
||||
public ArrayList<ItemStack> rawItems;
|
||||
|
||||
protected final HashMap<Integer, List<ItemStack>> groupItems = new HashMap<>();
|
||||
protected final HashMap<Integer, MaskMetadata> maskMetadata = new HashMap<>();
|
||||
protected boolean forceExpand = false;
|
||||
|
||||
public void setItems(ArrayList<ItemStack> items) {
|
||||
newItems = items;
|
||||
@@ -62,9 +93,48 @@ public class ItemPanel extends PanelWidget {
|
||||
|
||||
public void refresh(GuiContainer gui) {
|
||||
|
||||
if (newItems != null) {
|
||||
realItems = newItems;
|
||||
newItems = null;
|
||||
if (this.newItems != null) {
|
||||
this.groupItems.clear();
|
||||
this.forceExpand = false;
|
||||
|
||||
if (NEIClientConfig.enableCollapsibleItems() && !this.newItems.isEmpty()) {
|
||||
final Set<Integer> groups = new HashSet<>();
|
||||
boolean outsideGroup = false;
|
||||
|
||||
this.realItems = new ArrayList<>();
|
||||
this.rawItems = new ArrayList<>(this.newItems);
|
||||
|
||||
for (ItemStack stack : this.newItems) {
|
||||
final int groupIndex = ItemList.collapsibleItems.getGroupIndex(stack);
|
||||
|
||||
if (groupIndex == -1) {
|
||||
this.realItems.add(stack);
|
||||
outsideGroup = true;
|
||||
} else {
|
||||
|
||||
if (!groups.contains(groupIndex) || ItemList.collapsibleItems.isExpanded(groupIndex)) {
|
||||
this.realItems.add(stack);
|
||||
groups.add(groupIndex);
|
||||
}
|
||||
|
||||
if (!this.groupItems.containsKey(groupIndex)) {
|
||||
this.groupItems.put(groupIndex, new ArrayList<>());
|
||||
}
|
||||
|
||||
this.groupItems.get(groupIndex).add(stack);
|
||||
}
|
||||
}
|
||||
|
||||
// automatically opens if there are elements from only one group
|
||||
if (!outsideGroup && groups.size() == 1) {
|
||||
this.realItems = new ArrayList<>(this.newItems);
|
||||
this.forceExpand = true;
|
||||
}
|
||||
} else {
|
||||
this.realItems = new ArrayList<>(this.newItems);
|
||||
}
|
||||
|
||||
this.newItems = null;
|
||||
onItemsChanged();
|
||||
}
|
||||
|
||||
@@ -72,11 +142,170 @@ public class ItemPanel extends PanelWidget {
|
||||
}
|
||||
|
||||
@Override
|
||||
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);
|
||||
protected List<Integer> getMask() {
|
||||
final boolean updateBorders = this.gridMask == null;
|
||||
final List<Integer> mask = super.getMask();
|
||||
|
||||
if (updateBorders) {
|
||||
calculateGroupBorders(mask);
|
||||
}
|
||||
|
||||
return mask;
|
||||
}
|
||||
|
||||
protected void calculateGroupBorders(List<Integer> mask) {
|
||||
this.maskMetadata.clear();
|
||||
|
||||
if (mask.isEmpty() || this.groupItems.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
final HashMap<Integer, Integer> maskGroup = new HashMap<>();
|
||||
final Color collapsedColor = new Color(
|
||||
NEIClientConfig.getSetting("inventory.collapsibleItems.collapsedColor").getHexValue(),
|
||||
true);
|
||||
final Color expandedColor = new Color(
|
||||
NEIClientConfig.getSetting("inventory.collapsibleItems.expandedColor").getHexValue(),
|
||||
true);
|
||||
|
||||
for (int slotIndex = 0; slotIndex < mask.size(); slotIndex++) {
|
||||
if (mask.get(slotIndex) == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int idx = mask.get(slotIndex);
|
||||
maskGroup.put(idx, ItemList.collapsibleItems.getGroupIndex(getItem(idx)));
|
||||
}
|
||||
|
||||
for (int slotIndex = 0; slotIndex < mask.size(); slotIndex++) {
|
||||
if (mask.get(slotIndex) == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int idx = mask.get(slotIndex);
|
||||
int groupIndex = maskGroup.get(idx);
|
||||
|
||||
if (groupIndex == -1 || this.groupItems.get(groupIndex).size() == 1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int column = slotIndex % this.columns;
|
||||
int row = slotIndex / this.columns;
|
||||
int prevSlotIndex = (row - 1) * this.columns + column;
|
||||
int nextSlotIndex = (row + 1) * this.columns + column;
|
||||
MaskMetadata metadata = new MaskMetadata();
|
||||
|
||||
metadata.groupIndex = groupIndex;
|
||||
metadata.extended = this.forceExpand || ItemList.collapsibleItems.isExpanded(groupIndex);
|
||||
metadata.bgColor = metadata.extended ? expandedColor : collapsedColor;
|
||||
metadata.color = darkerColor(metadata.bgColor);
|
||||
metadata.left = column == 0 || idx == 0
|
||||
|| mask.get(slotIndex - 1) == null
|
||||
|| maskGroup.getOrDefault(idx - 1, -1) != groupIndex;
|
||||
metadata.right = column == this.columns - 1 || maskGroup.getOrDefault(idx + 1, -1) != groupIndex;
|
||||
|
||||
if (prevSlotIndex >= 0) {
|
||||
Integer previdx = mask.get(prevSlotIndex);
|
||||
metadata.top = previdx == null || maskGroup.getOrDefault(previdx, -1) != groupIndex;
|
||||
} else {
|
||||
metadata.top = true;
|
||||
}
|
||||
|
||||
if (nextSlotIndex < mask.size()) {
|
||||
Integer nextidx = mask.get(nextSlotIndex);
|
||||
metadata.bottom = nextidx == null || maskGroup.getOrDefault(nextidx, -1) != groupIndex;
|
||||
} else {
|
||||
metadata.bottom = true;
|
||||
}
|
||||
|
||||
this.maskMetadata.put(idx, metadata);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void beforeDrawItems(int mousex, int mousey, @Nullable ItemPanelSlot focused) {
|
||||
final List<Integer> mask = getMask();
|
||||
|
||||
super.beforeDrawItems(mousex, mousey, focused);
|
||||
|
||||
for (int i = 0; i < mask.size(); i++) {
|
||||
if (mask.get(i) != null) {
|
||||
drawBorder(mask.get(i), getSlotRect(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void drawBorder(int slotIdx, Rectangle4i rect) {
|
||||
final MaskMetadata metadata = this.maskMetadata.get(slotIdx);
|
||||
|
||||
if (metadata != null) {
|
||||
final float LINE_WIDTH = 0.75f;
|
||||
|
||||
drawRect(rect.x, rect.y, rect.w, rect.h, metadata.bgColor);
|
||||
|
||||
if (metadata.left) {
|
||||
float leftBottom = metadata.bottom ? -LINE_WIDTH : 0;
|
||||
drawRect(rect.x, rect.y, LINE_WIDTH, rect.h + leftBottom, metadata.color);
|
||||
}
|
||||
|
||||
if (metadata.right) {
|
||||
float rightTop = metadata.top ? LINE_WIDTH : 0;
|
||||
drawRect(rect.x + rect.w, rect.y - rightTop, LINE_WIDTH, rect.h + rightTop, metadata.color);
|
||||
}
|
||||
|
||||
if (metadata.top) {
|
||||
drawRect(rect.x, rect.y - LINE_WIDTH, rect.w, LINE_WIDTH, metadata.color);
|
||||
}
|
||||
|
||||
if (metadata.bottom) {
|
||||
drawRect(rect.x, rect.y + rect.h - LINE_WIDTH, rect.w, LINE_WIDTH, metadata.color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static Color darkerColor(Color color) {
|
||||
return new Color(
|
||||
color.getRed(),
|
||||
color.getGreen(),
|
||||
color.getBlue(),
|
||||
Math.min((int) (color.getAlpha() + (255f / 5) * 2), 255));
|
||||
}
|
||||
|
||||
private static void drawRect(double left, double top, double width, double height, Color color) {
|
||||
Tessellator tessellator = Tessellator.instance;
|
||||
|
||||
GL11.glEnable(GL11.GL_BLEND);
|
||||
GL11.glDisable(GL11.GL_TEXTURE_2D);
|
||||
OpenGlHelper.glBlendFunc(770, 771, 1, 0);
|
||||
GL11.glColor4f(
|
||||
color.getRed() / 255f,
|
||||
color.getGreen() / 255f,
|
||||
color.getBlue() / 255f,
|
||||
color.getAlpha() / 255f);
|
||||
tessellator.startDrawingQuads();
|
||||
tessellator.addVertex(left, top + height, 0.0D);
|
||||
tessellator.addVertex(left + width, top + height, 0.0D);
|
||||
tessellator.addVertex(left + width, top, 0.0D);
|
||||
tessellator.addVertex(left, top, 0.0D);
|
||||
tessellator.draw();
|
||||
GL11.glEnable(GL11.GL_TEXTURE_2D);
|
||||
GL11.glDisable(GL11.GL_BLEND);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void drawItem(Rectangle4i rect, int slotIdx) {
|
||||
final MaskMetadata metadata = this.maskMetadata.get(slotIdx);
|
||||
|
||||
if (metadata != null && !metadata.extended) {
|
||||
final List<ItemStack> groupItems = this.groupItems.get(metadata.groupIndex);
|
||||
|
||||
GuiContainerManager.drawItems.zLevel -= 10F;
|
||||
GuiContainerManager.drawItem(rect.x + 1, rect.y - 1, groupItems.get(groupItems.size() - 1), true, "");
|
||||
GuiContainerManager.drawItems.zLevel += 10F;
|
||||
|
||||
GuiContainerManager.drawItem(rect.x - 1, rect.y + 1, getItem(slotIdx), true, "");
|
||||
} else {
|
||||
super.beforeDrawSlot(focused, slotIdx, rect);
|
||||
super.drawItem(rect, slotIdx);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,6 +317,7 @@ public class ItemPanel extends PanelWidget {
|
||||
|
||||
public ItemPanel() {
|
||||
grid = new ItemPanelGrid();
|
||||
GuiContainerManager.addTooltipHandler(this);
|
||||
}
|
||||
|
||||
public static void updateItemList(ArrayList<ItemStack> newItems) {
|
||||
@@ -99,6 +329,21 @@ public class ItemPanel extends PanelWidget {
|
||||
public void init() {
|
||||
super.init();
|
||||
|
||||
toggleGroups = new Button("G") {
|
||||
|
||||
@Override
|
||||
public String getButtonTip() {
|
||||
return NEIClientUtils.translate("itempanel.collapsed.button.tip");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onButtonPress(boolean rightclick) {
|
||||
ItemList.collapsibleItems.toggleGroups(rightclick ? false : null);
|
||||
ItemList.updateFilter.restart();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
more = new Button("+") {
|
||||
|
||||
@Override
|
||||
@@ -167,6 +412,18 @@ public class ItemPanel extends PanelWidget {
|
||||
return gui.height - getMarginTop(gui) - PADDING;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int resizeHeader(GuiContainer gui) {
|
||||
int marginTop = super.resizeHeader(gui);
|
||||
|
||||
toggleGroups.w = pageNext.w;
|
||||
toggleGroups.h = pageNext.h;
|
||||
toggleGroups.y = pageNext.y;
|
||||
toggleGroups.x = pageNext.x - toggleGroups.w - 2;
|
||||
|
||||
return marginTop;
|
||||
}
|
||||
|
||||
protected int resizeFooter(GuiContainer gui) {
|
||||
if (!NEIClientConfig.showItemQuantityWidget() && NEIClientConfig.isSearchWidgetCentered()
|
||||
&& !NEIClientConfig.showHistoryPanelWidget()) {
|
||||
@@ -224,6 +481,10 @@ public class ItemPanel extends PanelWidget {
|
||||
LayoutManager.addWidget(quantity);
|
||||
}
|
||||
|
||||
if (NEIClientConfig.enableCollapsibleItems()) {
|
||||
LayoutManager.addWidget(toggleGroups);
|
||||
}
|
||||
|
||||
if (NEIClientConfig.showHistoryPanelWidget()) {
|
||||
LayoutManager.addWidget(historyPanel);
|
||||
}
|
||||
@@ -251,4 +512,66 @@ public class ItemPanel extends PanelWidget {
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> handleTooltip(GuiContainer gui, int mousex, int mousey, List<String> currenttip) {
|
||||
return currenttip;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> handleItemDisplayName(GuiContainer gui, ItemStack itemstack, List<String> currenttip) {
|
||||
return currenttip;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> handleItemTooltip(GuiContainer gui, ItemStack itemstack, int mousex, int mousey,
|
||||
List<String> currenttip) {
|
||||
final ItemPanelGrid panelGrid = ((ItemPanelGrid) this.grid);
|
||||
|
||||
if (!panelGrid.forceExpand) {
|
||||
final ItemPanelSlot hoverSlot = getSlotMouseOver(mousex, mousey);
|
||||
|
||||
if (hoverSlot != null) {
|
||||
|
||||
final MaskMetadata metadata = panelGrid.maskMetadata.get(hoverSlot.slotIndex);
|
||||
|
||||
if (metadata != null) {
|
||||
final List<ItemStack> items = panelGrid.groupItems.get(metadata.groupIndex);
|
||||
|
||||
if (items != null && items.size() > 1) {
|
||||
String message = metadata.extended ? "itempanel.collapsed.hint.collapse"
|
||||
: "itempanel.collapsed.hint.expand";
|
||||
currenttip.add(
|
||||
1,
|
||||
EnumChatFormatting.GRAY + NEIClientUtils.translate(message, items.size())
|
||||
+ EnumChatFormatting.RESET);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return currenttip;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handleClick(int mousex, int mousey, int button) {
|
||||
final ItemPanelGrid panelGrid = ((ItemPanelGrid) this.grid);
|
||||
|
||||
if (NEIClientUtils.altKey() && button == 0 && !panelGrid.forceExpand) {
|
||||
final ItemPanelSlot hoverSlot = grid.getSlotMouseOver(mousex, mousey);
|
||||
|
||||
if (hoverSlot != null) {
|
||||
final MaskMetadata metadata = panelGrid.maskMetadata.get(hoverSlot.slotIndex);
|
||||
|
||||
if (metadata != null) {
|
||||
ItemList.collapsibleItems.setExpanded(metadata.groupIndex, !metadata.extended);
|
||||
panelGrid.setItems(panelGrid.rawItems);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return super.handleClick(mousex, mousey, button);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -46,7 +46,7 @@ public class ItemSorter implements Comparator<ItemStack>, ItemsLoadedCallback {
|
||||
// optimisations
|
||||
public HashMap<ItemStack, Integer> ordering = null;
|
||||
|
||||
public static void sort(ArrayList<ItemStack> items) {
|
||||
public static void sort(List<ItemStack> items) {
|
||||
try {
|
||||
// items = (ArrayList<ItemStack>)
|
||||
// items.parallelStream().sorted(instance).collect(Collectors.toList());
|
||||
|
||||
@@ -173,11 +173,13 @@ public class ItemsGrid {
|
||||
invalidSlotMap = new boolean[rows * columns];
|
||||
perPage = columns * rows;
|
||||
|
||||
if (NEIClientConfig.optimizeGuiOverlapComputation()) {
|
||||
checkGuiOverlap(gui, 0, columns - 2, 1);
|
||||
checkGuiOverlap(gui, columns - 1, 1, -1);
|
||||
} else {
|
||||
checkGuiOverlap(gui, 0, columns, 1);
|
||||
if (gui != null) {
|
||||
if (NEIClientConfig.optimizeGuiOverlapComputation()) {
|
||||
checkGuiOverlap(gui, 0, columns - 2, 1);
|
||||
checkGuiOverlap(gui, columns - 1, 1, -1);
|
||||
} else {
|
||||
checkGuiOverlap(gui, 0, columns, 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (oldRows != rows || oldColumns != columns || !Arrays.equals(oldSlotMap, invalidSlotMap)) {
|
||||
@@ -247,7 +249,7 @@ public class ItemsGrid {
|
||||
return this.gridMask;
|
||||
}
|
||||
|
||||
private void beforeDrawItems(int mousex, int mousey, @Nullable ItemPanelSlot focused) {
|
||||
protected void beforeDrawItems(int mousex, int mousey, @Nullable ItemPanelSlot focused) {
|
||||
|
||||
final List<Integer> mask = getMask();
|
||||
|
||||
|
||||
@@ -87,7 +87,6 @@ public class LayoutManager implements IContainerInputHandler, IContainerTooltipH
|
||||
public static ItemPanel itemPanel;
|
||||
public static BookmarkPanel bookmarkPanel;
|
||||
public static SubsetWidget dropDown;
|
||||
public static PresetsWidget presetsPanel;
|
||||
public static SearchField searchField;
|
||||
public static boolean searchInitFocusedCancellable = false;
|
||||
protected static int mousePriorX;
|
||||
@@ -381,12 +380,8 @@ public class LayoutManager implements IContainerInputHandler, IContainerTooltipH
|
||||
|
||||
if (visiblity.showBookmarkPanel || gui.guiTop <= 20) visiblity.showSubsetDropdown = false;
|
||||
|
||||
if (!visiblity.showBookmarkPanel || gui.guiTop <= 20) visiblity.showPresetsDropdown = false;
|
||||
|
||||
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));
|
||||
@@ -409,8 +404,8 @@ public class LayoutManager implements IContainerInputHandler, IContainerTooltipH
|
||||
bookmarkPanel.init();
|
||||
|
||||
dropDown = new SubsetWidget();
|
||||
presetsPanel = new PresetsWidget();
|
||||
searchField = new SearchField("search");
|
||||
API.addItemFilter(searchField);
|
||||
|
||||
options = new ButtonCycled(3) {
|
||||
|
||||
@@ -714,13 +709,7 @@ public class LayoutManager implements IContainerInputHandler, IContainerTooltipH
|
||||
addWidget(options);
|
||||
addWidget(bookmarksButton);
|
||||
if (visiblity.showItemPanel) {
|
||||
|
||||
if (PresetsWidget.inEditMode()) {
|
||||
drawWidgets.add(itemPanel);
|
||||
} else {
|
||||
addWidget(itemPanel);
|
||||
}
|
||||
|
||||
addWidget(itemPanel);
|
||||
itemPanel.setVisible();
|
||||
}
|
||||
|
||||
@@ -729,10 +718,6 @@ public class LayoutManager implements IContainerInputHandler, IContainerTooltipH
|
||||
bookmarkPanel.setVisible();
|
||||
}
|
||||
|
||||
if (visiblity.showPresetsDropdown) {
|
||||
addWidget(presetsPanel);
|
||||
}
|
||||
|
||||
searchField.setVisible(visiblity.showSearchSection);
|
||||
if (visiblity.showSearchSection) {
|
||||
addWidget(searchField);
|
||||
|
||||
@@ -11,7 +11,6 @@ import static codechicken.nei.LayoutManager.itemPanel;
|
||||
import static codechicken.nei.LayoutManager.itemPresenceOverlays;
|
||||
import static codechicken.nei.LayoutManager.magnet;
|
||||
import static codechicken.nei.LayoutManager.options;
|
||||
import static codechicken.nei.LayoutManager.presetsPanel;
|
||||
import static codechicken.nei.LayoutManager.rain;
|
||||
import static codechicken.nei.LayoutManager.searchField;
|
||||
import static codechicken.nei.LayoutManager.timeButtons;
|
||||
@@ -121,11 +120,6 @@ public class LayoutStyleMinecraft extends LayoutStyle {
|
||||
dropDown.y = 0;
|
||||
dropDown.x = (gui.width - gui.xSize) / 2 + gui.xSize - dropDown.w;
|
||||
|
||||
presetsPanel.h = 16;
|
||||
presetsPanel.w = 150;
|
||||
presetsPanel.y = 2;
|
||||
presetsPanel.x = (gui.width - gui.xSize) / 2 + gui.xSize - presetsPanel.w;
|
||||
|
||||
searchField.h = 20;
|
||||
if (NEIClientConfig.isSearchWidgetCentered()) {
|
||||
searchField.w = 150;
|
||||
|
||||
@@ -43,6 +43,7 @@ import codechicken.nei.config.GuiHighlightTips;
|
||||
import codechicken.nei.config.GuiNEIOptionList;
|
||||
import codechicken.nei.config.GuiOptionList;
|
||||
import codechicken.nei.config.GuiPanelSettings;
|
||||
import codechicken.nei.config.OptionButton;
|
||||
import codechicken.nei.config.OptionCycled;
|
||||
import codechicken.nei.config.OptionGamemodes;
|
||||
import codechicken.nei.config.OptionIntegerField;
|
||||
@@ -52,6 +53,7 @@ import codechicken.nei.config.OptionTextField;
|
||||
import codechicken.nei.config.OptionToggleButton;
|
||||
import codechicken.nei.config.OptionToggleButtonBoubs;
|
||||
import codechicken.nei.config.OptionUtilities;
|
||||
import codechicken.nei.config.preset.GuiPresetList;
|
||||
import codechicken.nei.event.NEIConfigsLoadedEvent;
|
||||
import codechicken.nei.recipe.GuiRecipeTab;
|
||||
import codechicken.nei.recipe.IRecipeHandler;
|
||||
@@ -79,6 +81,7 @@ public class NEIClientConfig {
|
||||
public static final File handlerOrderingFile = new File(configDir, "handlerordering.csv");
|
||||
public static final File hiddenHandlersFile = new File(configDir, "hiddenhandlers.csv");
|
||||
public static final File enableAutoFocusFile = new File(configDir, "enableautofocus.cfg");
|
||||
public static final File collapsibleItemsFile = new File(configDir, "collapsibleitems.cfg");
|
||||
|
||||
@Deprecated
|
||||
public static File bookmarkFile;
|
||||
@@ -196,7 +199,7 @@ public class NEIClientConfig {
|
||||
});
|
||||
|
||||
tag.getTag("inventory.search.tooltipSearchMode").setComment("Search mode for Tooltips (prefix: #)")
|
||||
.getIntValue(1);
|
||||
.getIntValue(0);
|
||||
API.addOption(new OptionCycled("inventory.search.tooltipSearchMode", 3, true) {
|
||||
|
||||
@Override
|
||||
@@ -207,7 +210,7 @@ public class NEIClientConfig {
|
||||
});
|
||||
|
||||
tag.getTag("inventory.search.identifierSearchMode").setComment("Search mode for identifier (prefix: &)")
|
||||
.getIntValue(1);
|
||||
.getIntValue(0);
|
||||
API.addOption(new OptionCycled("inventory.search.identifierSearchMode", 3, true) {
|
||||
|
||||
@Override
|
||||
@@ -218,7 +221,7 @@ public class NEIClientConfig {
|
||||
});
|
||||
|
||||
tag.getTag("inventory.search.oreDictSearchMode").setComment("Search mode for Tag Names (prefix: $)")
|
||||
.getIntValue(1);
|
||||
.getIntValue(0);
|
||||
API.addOption(new OptionCycled("inventory.search.oreDictSearchMode", 3, true) {
|
||||
|
||||
@Override
|
||||
@@ -229,7 +232,7 @@ public class NEIClientConfig {
|
||||
});
|
||||
|
||||
tag.getTag("inventory.search.subsetsSearchMode").setComment("Search mode for Item Subsets (prefix: %)")
|
||||
.getIntValue(1);
|
||||
.getIntValue(2);
|
||||
API.addOption(new OptionCycled("inventory.search.subsetsSearchMode", 3, true) {
|
||||
|
||||
@Override
|
||||
@@ -252,6 +255,37 @@ public class NEIClientConfig {
|
||||
tag.getTag("inventory.history.splittingMode").getIntValue(1);
|
||||
API.addOption(new OptionCycled("inventory.history.splittingMode", 2, true));
|
||||
|
||||
tag.getTag("inventory.collapsibleItems.enabled").getBooleanValue(true);
|
||||
API.addOption(new OptionToggleButton("inventory.collapsibleItems.enabled", true) {
|
||||
|
||||
@Override
|
||||
public boolean onClick(int button) {
|
||||
LayoutManager.markItemsDirty();
|
||||
return super.onClick(button);
|
||||
}
|
||||
});
|
||||
|
||||
tag.getTag("inventory.collapsibleItems.expandedColor")
|
||||
.setComment("Color of the collapsible item expanded state").getHexValue(0x335555EE);
|
||||
API.addOption(new OptionIntegerField("inventory.collapsibleItems.expandedColor"));
|
||||
|
||||
tag.getTag("inventory.collapsibleItems.collapsedColor")
|
||||
.setComment("Color of the collapsible item collapsed state").getHexValue(0x335555EE);
|
||||
API.addOption(new OptionIntegerField("inventory.collapsibleItems.collapsedColor"));
|
||||
|
||||
API.addOption(
|
||||
new OptionButton(
|
||||
"inventory.collapsibleItems.reloadLabel",
|
||||
"inventory.collapsibleItems.reloadButton",
|
||||
"inventory.collapsibleItems.reloadTip") {
|
||||
|
||||
@Override
|
||||
public boolean onClick(int button) {
|
||||
LayoutManager.markItemsDirty();
|
||||
return super.onClick(button);
|
||||
}
|
||||
});
|
||||
|
||||
tag.getTag("inventory.itemIDs").getIntValue(1);
|
||||
API.addOption(new OptionCycled("inventory.itemIDs", 3, true));
|
||||
|
||||
@@ -272,6 +306,8 @@ public class NEIClientConfig {
|
||||
|
||||
API.addOption(new OptionOpenGui("world.panels", GuiPanelSettings.class));
|
||||
|
||||
API.addOption(new OptionOpenGui("world.presets", GuiPresetList.class));
|
||||
|
||||
tag.getTag("inventory.profileRecipes").getBooleanValue(false);
|
||||
API.addOption(new OptionToggleButton("inventory.profileRecipes", true));
|
||||
|
||||
@@ -645,7 +681,7 @@ public class NEIClientConfig {
|
||||
worldPath = "global";
|
||||
}
|
||||
|
||||
PresetsWidget.loadPresets(worldPath);
|
||||
PresetsList.setPresetsFile(worldPath);
|
||||
}
|
||||
|
||||
public static boolean isWorldSpecific(String setting) {
|
||||
@@ -833,6 +869,10 @@ public class NEIClientConfig {
|
||||
return getBooleanSetting("inventory.cacheItemRendering") && OpenGlHelper.framebufferSupported;
|
||||
}
|
||||
|
||||
public static boolean enableCollapsibleItems() {
|
||||
return getBooleanSetting("inventory.collapsibleItems.enabled");
|
||||
}
|
||||
|
||||
public static boolean getMagnetMode() {
|
||||
return enabledActions.contains("magnet");
|
||||
}
|
||||
|
||||
@@ -42,11 +42,14 @@ public abstract class PanelWidget extends Widget {
|
||||
pagePrev = new Button("Prev") {
|
||||
|
||||
public boolean onButtonPress(boolean rightclick) {
|
||||
if (!rightclick) {
|
||||
|
||||
if (rightclick) {
|
||||
grid.setPage(0);
|
||||
} else {
|
||||
grid.shiftPage(-1);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -57,11 +60,14 @@ public abstract class PanelWidget extends Widget {
|
||||
pageNext = new Button("Next") {
|
||||
|
||||
public boolean onButtonPress(boolean rightclick) {
|
||||
if (!rightclick) {
|
||||
|
||||
if (rightclick) {
|
||||
grid.setPage(grid.getNumPages() - 1);
|
||||
} else {
|
||||
grid.shiftPage(1);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,295 @@
|
||||
package codechicken.nei;
|
||||
|
||||
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.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
import com.google.gson.JsonPrimitive;
|
||||
import com.google.gson.JsonSyntaxException;
|
||||
|
||||
import codechicken.core.CommonUtils;
|
||||
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.IRecipeHandler;
|
||||
import codechicken.nei.recipe.StackInfo;
|
||||
import codechicken.nei.util.NBTJson;
|
||||
|
||||
public class PresetsList {
|
||||
|
||||
public static enum PresetMode {
|
||||
HIDE,
|
||||
REMOVE,
|
||||
GROUP;
|
||||
}
|
||||
|
||||
public static class Preset implements ItemFilter {
|
||||
|
||||
public String name = "";
|
||||
public boolean enabled = true;
|
||||
public PresetMode mode = PresetMode.HIDE;
|
||||
public Set<String> items = new HashSet<>();
|
||||
|
||||
public static String getIdentifier(ItemStack stack) {
|
||||
return StackInfo.getItemStackGUID(stack);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(ItemStack item) {
|
||||
return items.contains(Preset.getIdentifier(item));
|
||||
}
|
||||
|
||||
public Preset copy() {
|
||||
Preset preset = new Preset();
|
||||
|
||||
preset.name = name;
|
||||
preset.enabled = enabled;
|
||||
preset.mode = mode;
|
||||
preset.items = new HashSet<>(items);
|
||||
|
||||
return preset;
|
||||
}
|
||||
}
|
||||
|
||||
protected static class RecipesFilter implements IRecipeFilterProvider, IRecipeFilter {
|
||||
|
||||
public Set<String> cache;
|
||||
|
||||
public IRecipeFilter getFilter() {
|
||||
|
||||
if (cache == null) {
|
||||
cache = PresetsList.presets.stream().filter(p -> p.enabled && p.mode == PresetMode.REMOVE)
|
||||
.flatMap(p -> p.items.stream()).collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
return cache.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 (!cache.contains(Preset.getIdentifier(stack))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected static class ItemPanelFilter implements ItemFilterProvider, ItemFilter {
|
||||
|
||||
public Set<String> cache;
|
||||
|
||||
public ItemFilter getFilter() {
|
||||
|
||||
if (cache == null) {
|
||||
cache = PresetsList.presets.stream()
|
||||
.filter(p -> p.enabled && (p.mode == PresetMode.HIDE || p.mode == PresetMode.REMOVE))
|
||||
.flatMap(p -> p.items.stream()).collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
return cache.isEmpty() ? null : this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(ItemStack stack) {
|
||||
return !cache.contains(Preset.getIdentifier(stack));
|
||||
}
|
||||
}
|
||||
|
||||
public static final List<Preset> presets = new ArrayList<>();
|
||||
|
||||
protected static File presetsFile;
|
||||
protected static RecipesFilter recipeFilter = new RecipesFilter();
|
||||
protected static ItemPanelFilter itemFilter = new ItemPanelFilter();
|
||||
|
||||
static {
|
||||
API.addItemFilter(itemFilter);
|
||||
API.addRecipeFilter(recipeFilter);
|
||||
ItemList.loadCallbacks.add(PresetsList::itemsLoaded);
|
||||
}
|
||||
|
||||
public static ItemFilter getItemFilter() {
|
||||
return itemFilter.getFilter();
|
||||
}
|
||||
|
||||
public static void itemsLoaded() {
|
||||
recipeFilter.cache = null;
|
||||
itemFilter.cache = null;
|
||||
ItemList.collapsibleItems.reload();
|
||||
}
|
||||
|
||||
public static void setPresetsFile(String worldPath) {
|
||||
final File dir = new File(CommonUtils.getMinecraftDir(), "saves/NEI/" + worldPath);
|
||||
|
||||
if (!dir.exists()) {
|
||||
dir.mkdirs();
|
||||
}
|
||||
|
||||
presetsFile = new File(dir, "presets.ini");
|
||||
|
||||
if (!presetsFile.exists()) {
|
||||
final File globalPresets = new File(CommonUtils.getMinecraftDir(), "saves/NEI/global/presets.ini");
|
||||
final File configPresets = new File(NEIClientConfig.configDir, "presets.ini");
|
||||
final File defaultBookmarks = configPresets.exists() ? configPresets : globalPresets;
|
||||
|
||||
if (defaultBookmarks.exists()) {
|
||||
|
||||
try {
|
||||
presetsFile.createNewFile();
|
||||
|
||||
InputStream src = new FileInputStream(defaultBookmarks);
|
||||
OutputStream dst = new FileOutputStream(presetsFile);
|
||||
|
||||
IOUtils.copy(src, dst);
|
||||
|
||||
src.close();
|
||||
dst.close();
|
||||
|
||||
} catch (IOException e) {}
|
||||
}
|
||||
}
|
||||
|
||||
loadPresets();
|
||||
}
|
||||
|
||||
protected static void loadPresets() {
|
||||
|
||||
if (presetsFile == null || !presetsFile.exists()) {
|
||||
return;
|
||||
}
|
||||
|
||||
List<String> itemStrings;
|
||||
try (FileInputStream reader = new FileInputStream(presetsFile)) {
|
||||
NEIClientConfig.logger.info("Loading presets from file {}", presetsFile);
|
||||
itemStrings = IOUtils.readLines(reader, StandardCharsets.UTF_8);
|
||||
} catch (IOException e) {
|
||||
NEIClientConfig.logger.error("Failed to load presets from file {}", presetsFile, e);
|
||||
return;
|
||||
}
|
||||
|
||||
JsonParser parser = new JsonParser();
|
||||
Preset preset = new Preset();
|
||||
presets.clear();
|
||||
|
||||
for (String itemStr : itemStrings) {
|
||||
|
||||
try {
|
||||
|
||||
if (itemStr.isEmpty()) {
|
||||
itemStr = "; {}";
|
||||
}
|
||||
|
||||
if (itemStr.startsWith("; ")) {
|
||||
JsonObject settings = parser.parse(itemStr.substring(2)).getAsJsonObject();
|
||||
|
||||
if (!preset.items.isEmpty()) {
|
||||
// do not create empty namespaces
|
||||
presets.add(preset);
|
||||
preset = new Preset();
|
||||
}
|
||||
|
||||
if (settings.get("name") != null) {
|
||||
preset.name = settings.get("name").getAsString();
|
||||
}
|
||||
|
||||
if (settings.get("enabled") != null) {
|
||||
preset.enabled = settings.get("enabled").getAsBoolean();
|
||||
}
|
||||
|
||||
if (settings.get("mode") != null) {
|
||||
preset.mode = PresetMode.valueOf(settings.get("mode").getAsString());
|
||||
}
|
||||
|
||||
} else {
|
||||
preset.items.add(itemStr);
|
||||
}
|
||||
|
||||
} catch (IllegalArgumentException | JsonSyntaxException | IllegalStateException e) {
|
||||
NEIClientConfig.logger.error("Failed to load presets ItemStack from json string:\n{}", itemStr);
|
||||
}
|
||||
}
|
||||
|
||||
if (!preset.items.isEmpty()) {
|
||||
presets.add(preset);
|
||||
}
|
||||
|
||||
itemsLoaded();
|
||||
}
|
||||
|
||||
public static void savePresets() {
|
||||
|
||||
if (presetsFile == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
List<String> strings = new ArrayList<>();
|
||||
|
||||
for (Preset preset : presets) {
|
||||
JsonObject settings = new JsonObject();
|
||||
|
||||
settings.add("name", new JsonPrimitive(preset.name));
|
||||
settings.add("enabled", new JsonPrimitive(preset.enabled));
|
||||
settings.add("mode", new JsonPrimitive(preset.mode.toString()));
|
||||
|
||||
strings.add("; " + NBTJson.toJson(settings));
|
||||
strings.addAll(preset.items);
|
||||
}
|
||||
|
||||
try (FileOutputStream output = new FileOutputStream(presetsFile)) {
|
||||
IOUtils.writeLines(strings, "\n", output, StandardCharsets.UTF_8);
|
||||
} catch (IOException e) {
|
||||
NEIClientConfig.logger.error("Filed to save presets list to file {}", presetsFile, e);
|
||||
}
|
||||
|
||||
itemsLoaded();
|
||||
}
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,8 +1,8 @@
|
||||
package codechicken.nei;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.util.EnumChatFormatting;
|
||||
|
||||
import codechicken.nei.SearchField.GuiSearchField;
|
||||
import codechicken.nei.api.ItemFilter;
|
||||
import codechicken.nei.util.TextHistory;
|
||||
|
||||
@@ -17,8 +17,7 @@ public abstract class RecipeSearchField extends TextField {
|
||||
|
||||
@Override
|
||||
protected void initInternalTextField() {
|
||||
field = new FormattedTextField(Minecraft.getMinecraft().fontRenderer, 0, 0, 0, 0);
|
||||
((FormattedTextField) field).setFormatter(new SearchTextFormatter(SearchField.searchParser));
|
||||
field = new GuiSearchField();
|
||||
field.setMaxStringLength(maxSearchLength);
|
||||
field.setCursorPositionZero();
|
||||
}
|
||||
@@ -60,7 +59,7 @@ public abstract class RecipeSearchField extends TextField {
|
||||
}
|
||||
|
||||
public ItemFilter getFilter() {
|
||||
return SearchField.getFilter(text());
|
||||
return ((GuiSearchField) field).getFilter();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
package codechicken.nei;
|
||||
|
||||
import static codechicken.nei.NEIClientConfig.world;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
@@ -18,7 +16,6 @@ import codechicken.lib.gui.GuiDraw;
|
||||
import codechicken.nei.ItemList.NothingItemFilter;
|
||||
import codechicken.nei.SearchTokenParser.ISearchParserProvider;
|
||||
import codechicken.nei.SearchTokenParser.SearchMode;
|
||||
import codechicken.nei.api.API;
|
||||
import codechicken.nei.api.ItemFilter;
|
||||
import codechicken.nei.api.ItemFilter.ItemFilterProvider;
|
||||
import codechicken.nei.recipe.StackInfo;
|
||||
@@ -91,28 +88,50 @@ public class SearchField extends TextField implements ItemFilterProvider {
|
||||
}
|
||||
}
|
||||
|
||||
public static class GuiSearchField extends FormattedTextField {
|
||||
|
||||
protected final SearchTokenParser searchParser;
|
||||
|
||||
public GuiSearchField() {
|
||||
this(SearchField.searchParser);
|
||||
}
|
||||
|
||||
public GuiSearchField(SearchTokenParser searchParser) {
|
||||
super(Minecraft.getMinecraft().fontRenderer, 0, 0, 0, 0);
|
||||
this.searchParser = searchParser;
|
||||
setFormatter(new SearchTextFormatter(searchParser));
|
||||
}
|
||||
|
||||
public ItemFilter getFilter() {
|
||||
return getFilter(getText());
|
||||
}
|
||||
|
||||
public ItemFilter getFilter(String filterText) {
|
||||
return this.searchParser.getFilter(filterText);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static List<ISearchProvider> searchProviders = new LinkedList<>();
|
||||
public static SearchTokenParser searchParser = new SearchTokenParser();
|
||||
public static final SearchTokenParser searchParser = new SearchTokenParser();
|
||||
private static final TextHistory history = new TextHistory();
|
||||
private boolean isVisible = true;
|
||||
private long lastclicktime;
|
||||
|
||||
public SearchField(String ident) {
|
||||
super(ident);
|
||||
API.addItemFilter(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initInternalTextField() {
|
||||
field = new FormattedTextField(Minecraft.getMinecraft().fontRenderer, 0, 0, 0, 0);
|
||||
((FormattedTextField) field).setFormatter(new SearchTextFormatter(SearchField.searchParser));
|
||||
field = new GuiSearchField();
|
||||
field.setMaxStringLength(maxSearchLength);
|
||||
field.setCursorPositionZero();
|
||||
}
|
||||
|
||||
public static boolean searchInventories() {
|
||||
return world.nbt.getBoolean("searchinventories");
|
||||
return NEIClientConfig.world.nbt.getBoolean("searchinventories");
|
||||
}
|
||||
|
||||
public boolean isVisible() {
|
||||
@@ -137,10 +156,34 @@ public class SearchField extends TextField implements ItemFilterProvider {
|
||||
super.draw(mousex, mousey);
|
||||
|
||||
if (searchInventories()) {
|
||||
GuiDraw.drawGradientRect(x - 1, y - 1, 1, h + 2, 0xFFFFFF00, 0xFFC0B000); // Left
|
||||
GuiDraw.drawGradientRect(x - 1, y - 1, w + 2, 1, 0xFFFFFF00, 0xFFC0B000); // Top
|
||||
GuiDraw.drawGradientRect(x + w, y - 1, 1, h + 2, 0xFFFFFF00, 0xFFC0B000); // Left
|
||||
GuiDraw.drawGradientRect(x - 1, y + h, w + 2, 1, 0xFFFFFF00, 0xFFC0B000); // Bottom
|
||||
GuiDraw.drawGradientRect(
|
||||
field.xPosition - 1,
|
||||
field.yPosition - 1,
|
||||
1,
|
||||
field.height + 2,
|
||||
0xFFFFFF00,
|
||||
0xFFC0B000); // Left
|
||||
GuiDraw.drawGradientRect(
|
||||
field.xPosition - 1,
|
||||
field.yPosition - 1,
|
||||
field.width + 2,
|
||||
1,
|
||||
0xFFFFFF00,
|
||||
0xFFC0B000); // Top
|
||||
GuiDraw.drawGradientRect(
|
||||
field.xPosition + field.width,
|
||||
field.yPosition - 1,
|
||||
1,
|
||||
field.height + 2,
|
||||
0xFFFFFF00,
|
||||
0xFFC0B000); // Left
|
||||
GuiDraw.drawGradientRect(
|
||||
field.xPosition - 1,
|
||||
field.yPosition + field.height,
|
||||
field.width + 2,
|
||||
1,
|
||||
0xFFFFFF00,
|
||||
0xFFC0B000); // Bottom
|
||||
}
|
||||
}
|
||||
|
||||
@@ -268,7 +311,7 @@ public class SearchField extends TextField implements ItemFilterProvider {
|
||||
|
||||
@Override
|
||||
public ItemFilter getFilter() {
|
||||
return getFilter(text());
|
||||
return ((GuiSearchField) field).getFilter();
|
||||
}
|
||||
|
||||
public static ItemFilter getFilter(String filterText) {
|
||||
|
||||
@@ -15,10 +15,6 @@ public class VisiblityData {
|
||||
* Subset dropdown
|
||||
*/
|
||||
public boolean showSubsetDropdown = true;
|
||||
/**
|
||||
* Presets dropdown
|
||||
*/
|
||||
public boolean showPresetsDropdown = true;
|
||||
/**
|
||||
* Item and search section
|
||||
*/
|
||||
@@ -44,7 +40,6 @@ public class VisiblityData {
|
||||
public void translateDependancies() {
|
||||
if (!showNEI) showWidgets = false;
|
||||
if (!showWidgets) showItemSection = showUtilityButtons = false;
|
||||
if (!showItemSection)
|
||||
showBookmarkPanel = showSubsetDropdown = showPresetsDropdown = showSearchSection = showItemPanel = false;
|
||||
if (!showItemSection) showBookmarkPanel = showSubsetDropdown = showSearchSection = showItemPanel = false;
|
||||
}
|
||||
}
|
||||
@@ -113,8 +113,13 @@ public class GuiItemSorter extends GuiOptionPane {
|
||||
if (nslot != list.indexOf(dragged.e)) {
|
||||
list.remove(dragged.e);
|
||||
list.add(nslot, dragged.e);
|
||||
|
||||
opt.getTag().setValue(ItemSorter.getSaveString(list));
|
||||
if (opt.activeTag() == opt.getTag()) ItemSorter.list = new ArrayList<>(list);
|
||||
LayoutManager.markItemsDirty();
|
||||
|
||||
if (opt.activeTag() == opt.getTag()) {
|
||||
ItemSorter.list = new ArrayList<>(list);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,7 +80,7 @@ public class OptionTextField extends Option {
|
||||
public List<String> handleTooltip(int mousex, int mousey, List<String> currenttip) {
|
||||
if (new Rectangle4i(10, 0, textField.x - 10, 20).contains(mousex, mousey)) {
|
||||
String tip = translateN(name + ".tip");
|
||||
if (!tip.equals(name + ".tip")) currenttip.add(tip);
|
||||
if (!tip.equals(namespaced(name + ".tip"))) currenttip.add(tip);
|
||||
}
|
||||
return currenttip;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
package codechicken.nei.config.preset;
|
||||
|
||||
import static codechicken.lib.gui.GuiDraw.drawStringC;
|
||||
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import codechicken.nei.Button;
|
||||
import codechicken.nei.LayoutManager;
|
||||
|
||||
public abstract class CheckboxButton extends Button {
|
||||
|
||||
protected boolean checked = false;
|
||||
|
||||
public CheckboxButton(String s) {
|
||||
super(s);
|
||||
}
|
||||
|
||||
public void setChecked(boolean checked) {
|
||||
this.checked = checked;
|
||||
this.onChange();
|
||||
}
|
||||
|
||||
public boolean isChecked() {
|
||||
return this.checked;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(int mousex, int mousey) {
|
||||
GL11.glDisable(GL11.GL_LIGHTING);
|
||||
GL11.glColor4f(1, 1, 1, 1);
|
||||
int tex;
|
||||
|
||||
if ((this.state & 0x3) == 2) {
|
||||
tex = 0;
|
||||
} else if ((this.state & 0x4) == 0 && contains(mousex, mousey) || (this.state & 0x3) == 1) {
|
||||
tex = 2;
|
||||
} else {
|
||||
tex = 1;
|
||||
}
|
||||
|
||||
int colour = tex == 2 ? 0xffffa0 : tex == 0 ? 0x601010 : 0xe0e0e0;
|
||||
LayoutManager.drawButtonBackground(x, y, w, h, true, isChecked() ? 0 : tex);
|
||||
drawStringC(getRenderLabel(), x + w / 2, y + (h - 8) / 2, colour);
|
||||
}
|
||||
|
||||
public boolean onButtonPress(boolean rightclick) {
|
||||
this.setChecked(!isChecked());
|
||||
return true;
|
||||
}
|
||||
|
||||
protected abstract void onChange();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,239 @@
|
||||
package codechicken.nei.config.preset;
|
||||
|
||||
import static codechicken.lib.gui.GuiDraw.getStringWidth;
|
||||
|
||||
import java.awt.Rectangle;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import codechicken.core.gui.GuiCCButton;
|
||||
import codechicken.lib.gui.GuiDraw;
|
||||
import codechicken.lib.vec.Rectangle4i;
|
||||
import codechicken.nei.LayoutManager;
|
||||
import codechicken.nei.NEIClientUtils;
|
||||
import codechicken.nei.PresetsList;
|
||||
import codechicken.nei.PresetsList.Preset;
|
||||
import codechicken.nei.config.GuiOptionPane;
|
||||
import codechicken.nei.config.Option;
|
||||
|
||||
public class GuiPresetList extends GuiOptionPane {
|
||||
|
||||
private final Option opt;
|
||||
protected final static int SLOT_HEIGHT = 24;
|
||||
protected final static int BUTTON_HEIGHT = 20;
|
||||
protected GuiCCButton createButton;
|
||||
protected int sortingItemIndex = -1;
|
||||
|
||||
public GuiPresetList(Option opt) {
|
||||
this.opt = opt;
|
||||
this.createButton = new GuiCCButton(0, 2, 0, 16, NEIClientUtils.translate("presets.new"))
|
||||
.setActionCommand("create");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initGui() {
|
||||
super.initGui();
|
||||
this.createButton.width = getStringWidth(this.createButton.text) + 15;
|
||||
this.createButton.x = width - this.createButton.width - 15;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addWidgets() {
|
||||
super.addWidgets();
|
||||
add(this.createButton);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(String ident, Object... params) {
|
||||
super.actionPerformed(ident, params);
|
||||
|
||||
if (ident.equals("create")) {
|
||||
cretePreset();
|
||||
}
|
||||
}
|
||||
|
||||
protected void mouseClicked(int x, int y, int button) {
|
||||
super.mouseClicked(x, y, button);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void mouseMovedOrUp(int x, int y, int button) {
|
||||
super.mouseMovedOrUp(x, y, button);
|
||||
|
||||
if (sortingItemIndex >= 0) {
|
||||
PresetsList.savePresets();
|
||||
} else if (button == 0) {
|
||||
int slot = getSlotMouseOver(x, y);
|
||||
|
||||
if (slot != -1) {
|
||||
Rectangle w = pane.windowBounds();
|
||||
int mx = x - w.x;
|
||||
|
||||
if (mx <= BUTTON_HEIGHT) {
|
||||
Preset preset = PresetsList.presets.get(slot);
|
||||
preset.enabled = !preset.enabled;
|
||||
PresetsList.savePresets();
|
||||
} else if (mx >= 26 && mx <= w.width - 26 * 2) {
|
||||
openPreset(slot);
|
||||
} else if (mx >= w.width - BUTTON_HEIGHT) {
|
||||
PresetsList.presets.remove(slot);
|
||||
PresetsList.savePresets();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sortingItemIndex = -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void mouseClickMove(int x, int y, int button, long time) {
|
||||
super.mouseClickMove(x, y, button, time);
|
||||
|
||||
if (sortingItemIndex == -1) {
|
||||
Rectangle w = pane.windowBounds();
|
||||
int mx = x - w.x;
|
||||
|
||||
if (mx >= 26 && mx <= w.width - 26 * 2) {
|
||||
sortingItemIndex = getSlotMouseOver(x, y);
|
||||
} else {
|
||||
sortingItemIndex = -2;
|
||||
}
|
||||
} else if (sortingItemIndex >= 0) {
|
||||
Rectangle w = pane.windowBounds();
|
||||
|
||||
if (y >= w.y && y <= w.y + w.height) {
|
||||
int my = y + pane.scrolledPixels() - w.y;
|
||||
int slot = my / SLOT_HEIGHT;
|
||||
|
||||
if (my % SLOT_HEIGHT < BUTTON_HEIGHT && slot < PresetsList.presets.size()
|
||||
&& slot != -1
|
||||
&& slot != sortingItemIndex) {
|
||||
PresetsList.presets.add(slot, PresetsList.presets.remove(sortingItemIndex));
|
||||
sortingItemIndex = slot;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected int getSlotMouseOver(int x, int y) {
|
||||
Rectangle w = pane.windowBounds();
|
||||
|
||||
if (x >= w.x && x <= w.x + w.width && y >= w.y && y <= w.y + w.height) {
|
||||
int my = y + pane.scrolledPixels() - w.y;
|
||||
int slot = my / SLOT_HEIGHT;
|
||||
|
||||
if (my % SLOT_HEIGHT < BUTTON_HEIGHT && slot < PresetsList.presets.size()) {
|
||||
return slot;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
protected void cretePreset() {
|
||||
Minecraft.getMinecraft().displayGuiScreen(new GuiPresetSettings(this, -1));
|
||||
}
|
||||
|
||||
protected void openPreset(int slot) {
|
||||
Minecraft.getMinecraft().displayGuiScreen(new GuiPresetSettings(this, slot));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int contentHeight() {
|
||||
return PresetsList.presets.size() * SLOT_HEIGHT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawContent(int mx, int my, float frame) {
|
||||
int scrolled = pane.scrolledPixels();
|
||||
Rectangle w = pane.windowBounds();
|
||||
int y = 0;
|
||||
|
||||
for (int slot = 0; slot < PresetsList.presets.size(); ++slot) {
|
||||
|
||||
if (y + SLOT_HEIGHT > scrolled && y < scrolled + w.height) {
|
||||
|
||||
if (sortingItemIndex != slot) {
|
||||
drawSlot(w, slot, w.x, w.y + y - scrolled, mx, my - y);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
y += SLOT_HEIGHT;
|
||||
}
|
||||
|
||||
if (sortingItemIndex >= 0) {
|
||||
drawSlot(w, sortingItemIndex, w.x, w.y + my - scrolled - BUTTON_HEIGHT / 2, mx, my - y);
|
||||
}
|
||||
}
|
||||
|
||||
protected void drawSlot(Rectangle w, int slot, int x, int y, int mx, int my) {
|
||||
final Rectangle4i delete = new Rectangle4i(x + w.width - BUTTON_HEIGHT, y, BUTTON_HEIGHT, BUTTON_HEIGHT);
|
||||
final Rectangle4i enabled = new Rectangle4i(x, y, BUTTON_HEIGHT, BUTTON_HEIGHT);
|
||||
final Rectangle4i option = new Rectangle4i(x + 26, y, w.width - 26 * 2, BUTTON_HEIGHT);
|
||||
|
||||
final int enabledState = y + my >= w.y && y + my <= w.y + w.height && enabled.contains(x + mx, y + my) ? 2 : 1;
|
||||
final int optionState = y + my >= w.y && y + my <= w.y + w.height && option.contains(x + mx, y + my) ? 2 : 1;
|
||||
final int deleteState = y + my >= w.y && y + my <= w.y + w.height && delete.contains(x + mx, y + my) ? 2 : 1;
|
||||
final Preset preset = PresetsList.presets.get(slot);
|
||||
|
||||
final String displayName = preset.name;
|
||||
final String modeName;
|
||||
|
||||
switch (preset.mode) {
|
||||
case HIDE:
|
||||
modeName = NEIClientUtils.translate("presets.mode.hide.char");
|
||||
break;
|
||||
case REMOVE:
|
||||
modeName = NEIClientUtils.translate("presets.mode.remove.char");
|
||||
break;
|
||||
case GROUP:
|
||||
modeName = NEIClientUtils.translate("presets.mode.group.char");
|
||||
break;
|
||||
default:
|
||||
modeName = "?";
|
||||
break;
|
||||
}
|
||||
|
||||
// enabled icon
|
||||
GL11.glColor4f(1, 1, 1, 1);
|
||||
LayoutManager.drawButtonBackground(
|
||||
enabled.x,
|
||||
enabled.y,
|
||||
enabled.w,
|
||||
enabled.h,
|
||||
true,
|
||||
preset.enabled ? 0 : enabledState);
|
||||
GuiDraw.drawString("✔", enabled.x + 7, enabled.y + 6, enabledState == 2 ? 0xFFFFFFA0 : 0xFFE0E0E0);
|
||||
|
||||
// preset name
|
||||
GL11.glColor4f(1, 1, 1, 1);
|
||||
LayoutManager.drawButtonBackground(option.x, option.y, option.w, option.h, true, optionState);
|
||||
GuiDraw.drawString("⋮⋮", option.x + 4, option.y + 5, optionState == 2 ? 0xFFFFFFA0 : 0xFFE0E0E0);
|
||||
GuiDraw.drawString(
|
||||
NEIClientUtils.cropText(this.fontRendererObj, modeName + ": " + displayName, option.w - 16),
|
||||
option.x + 6 + 4,
|
||||
option.y + 6,
|
||||
optionState == 2 ? 0xFFFFFFA0 : 0xFFE0E0E0);
|
||||
|
||||
// remove icon
|
||||
GL11.glColor4f(1, 1, 1, 1);
|
||||
LayoutManager.drawButtonBackground(delete.x, delete.y, delete.w, delete.h, true, deleteState);
|
||||
GuiDraw.drawString("✕", delete.x + 7, delete.y + 6, deleteState == 2 ? 0xFFFFFFA0 : 0xFFE0E0E0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public GuiScreen getParentScreen() {
|
||||
return opt.slot.getGui();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTitle() {
|
||||
return opt.translateN(opt.name);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,228 @@
|
||||
package codechicken.nei.config.preset;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.Gui;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
import net.minecraft.client.renderer.Tessellator;
|
||||
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.util.Rectangle;
|
||||
|
||||
import codechicken.core.gui.GuiScreenWidget;
|
||||
import codechicken.nei.Button;
|
||||
import codechicken.nei.NEIClientUtils;
|
||||
import codechicken.nei.PresetsList;
|
||||
import codechicken.nei.PresetsList.Preset;
|
||||
import codechicken.nei.config.OptionScrollPane;
|
||||
import codechicken.nei.guihook.GuiContainerManager;
|
||||
|
||||
public class GuiPresetSettings extends GuiScreenWidget {
|
||||
|
||||
protected final Preset preset;
|
||||
protected final GuiScreen parent;
|
||||
protected final int slotIndex;
|
||||
|
||||
public int marginleft;
|
||||
public int margintop;
|
||||
public int marginright;
|
||||
public int marginbottom;
|
||||
|
||||
protected LeftPanel leftPanel;
|
||||
protected RightPanel rightPanel;
|
||||
|
||||
protected Button backButton;
|
||||
protected Button saveButton;
|
||||
|
||||
public GuiPresetSettings(GuiScreen parent, int slotIndex) {
|
||||
this.parent = parent;
|
||||
this.setMargins(6, 20, 6, 30);
|
||||
|
||||
this.slotIndex = slotIndex;
|
||||
|
||||
if (slotIndex == -1) {
|
||||
preset = new Preset();
|
||||
} else {
|
||||
preset = PresetsList.presets.get(slotIndex).copy();
|
||||
}
|
||||
|
||||
leftPanel = new LeftPanel(preset) {
|
||||
|
||||
@Override
|
||||
protected void onItemsChanges() {
|
||||
leftPanel.grid.restartFilter();
|
||||
}
|
||||
};
|
||||
rightPanel = new RightPanel(preset, slotIndex) {
|
||||
|
||||
@Override
|
||||
protected void onItemsChanges() {
|
||||
leftPanel.grid.restartFilter();
|
||||
}
|
||||
};
|
||||
|
||||
backButton = new Button(NEIClientUtils.translate("options.back")) {
|
||||
|
||||
public boolean onButtonPress(boolean rightclick) {
|
||||
Minecraft.getMinecraft().displayGuiScreen(parent);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
saveButton = new Button(NEIClientUtils.translate("options.save")) {
|
||||
|
||||
public boolean onButtonPress(boolean rightclick) {
|
||||
if (state == 0) {
|
||||
|
||||
if (slotIndex == -1) {
|
||||
PresetsList.presets.add(preset);
|
||||
} else {
|
||||
PresetsList.presets.set(slotIndex, preset);
|
||||
}
|
||||
|
||||
PresetsList.savePresets();
|
||||
Minecraft.getMinecraft().displayGuiScreen(parent);
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
add(this.leftPanel);
|
||||
add(this.rightPanel);
|
||||
}
|
||||
|
||||
protected void setMargins(int left, int top, int right, int bottom) {
|
||||
this.marginleft = left;
|
||||
this.margintop = top;
|
||||
this.marginright = right;
|
||||
this.marginbottom = bottom;
|
||||
}
|
||||
|
||||
protected Rectangle windowBounds() {
|
||||
return new Rectangle(
|
||||
this.marginleft,
|
||||
this.margintop,
|
||||
this.width - this.marginleft - this.marginright,
|
||||
this.height - this.margintop - this.marginbottom);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean doesGuiPauseGame() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateScreen() {
|
||||
final Rectangle bounds = windowBounds();
|
||||
final int panelWidth = bounds.getWidth() * 2 / 5;
|
||||
|
||||
this.leftPanel.setSize(bounds.getX(), bounds.getY() + 4, panelWidth, bounds.getHeight() - 6);
|
||||
this.rightPanel.setSize(
|
||||
bounds.getX() + bounds.getWidth() - panelWidth,
|
||||
bounds.getY() + 4,
|
||||
panelWidth,
|
||||
bounds.getHeight() - 6);
|
||||
|
||||
final int w = Math.min(200, width - 40);
|
||||
|
||||
backButton.w = w / 2 - 3;
|
||||
backButton.h = 20;
|
||||
backButton.x = (width - w) / 2;
|
||||
backButton.y = height - 25;
|
||||
|
||||
saveButton.state = preset.name.isEmpty() || preset.mode == null || preset.items.isEmpty() ? 2 : 0;
|
||||
|
||||
saveButton.w = w / 2 - 3;
|
||||
saveButton.h = 20;
|
||||
saveButton.x = width / 2 + 3;
|
||||
saveButton.y = height - 25;
|
||||
|
||||
super.updateScreen();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resize() {
|
||||
this.guiLeft = this.guiTop = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawScreen(int mousex, int mousey, float f) {
|
||||
Rectangle bounds = windowBounds();
|
||||
drawDefaultBackground();
|
||||
|
||||
drawOverlay(bounds.getY(), bounds.getHeight(), width, zLevel);
|
||||
drawCenteredString(
|
||||
Minecraft.getMinecraft().fontRenderer,
|
||||
NEIClientUtils.translate(this.slotIndex == -1 ? "presets.create" : "presets.update"),
|
||||
width / 2,
|
||||
6,
|
||||
-1);
|
||||
|
||||
backButton.draw(mousex, mousey);
|
||||
saveButton.draw(mousex, mousey);
|
||||
|
||||
super.drawScreen(mousex, mousey, f);
|
||||
|
||||
List<String> tooltip = new LinkedList<>();
|
||||
tooltip = leftPanel.handleTooltip(mousex, mousey, tooltip);
|
||||
tooltip = rightPanel.handleTooltip(mousex, mousey, tooltip);
|
||||
|
||||
GuiContainerManager.drawPagedTooltip(Minecraft.getMinecraft().fontRenderer, mousex + 12, mousey - 12, tooltip);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void mouseClicked(int x, int y, int button) {
|
||||
super.mouseClicked(x, y, button);
|
||||
|
||||
if (backButton.contains(x, y)) {
|
||||
backButton.handleClick(x, y, button);
|
||||
}
|
||||
|
||||
if (saveButton.contains(x, y)) {
|
||||
saveButton.handleClick(x, y, button);
|
||||
}
|
||||
}
|
||||
|
||||
public static void drawOverlay(int y, int height, int screenwidth, float zLevel) {
|
||||
OptionScrollPane.drawOverlayTex(0, 0, screenwidth, y, zLevel);
|
||||
OptionScrollPane.drawOverlayTex(0, y + height, screenwidth, screenwidth - y - height, zLevel);
|
||||
OptionScrollPane.drawOverlayGrad(0, screenwidth, y, y + 4, zLevel);
|
||||
OptionScrollPane.drawOverlayGrad(0, screenwidth, y + height, y + height - 4, zLevel);
|
||||
}
|
||||
|
||||
public static void drawOverlayTex(int x, int y, int w, int h, float zLevel) {
|
||||
GL11.glColor4f(1, 1, 1, 1);
|
||||
Minecraft.getMinecraft().renderEngine.bindTexture(Gui.optionsBackground);
|
||||
Tessellator t = Tessellator.instance;
|
||||
t.startDrawingQuads();
|
||||
t.addVertexWithUV(x, y, zLevel, 0, 0);
|
||||
t.addVertexWithUV(x, y + h, zLevel, 0, h / 16D);
|
||||
t.addVertexWithUV(x + w, y + h, zLevel, w / 16D, h / 16D);
|
||||
t.addVertexWithUV(x + w, y, zLevel, w / 16D, 0);
|
||||
t.draw();
|
||||
}
|
||||
|
||||
public static void drawOverlayGrad(int x1, int x2, int y1, int y2, float zLevel) {
|
||||
GL11.glDisable(GL11.GL_TEXTURE_2D);
|
||||
GL11.glDisable(GL11.GL_CULL_FACE);
|
||||
GL11.glEnable(GL11.GL_BLEND);
|
||||
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
|
||||
GL11.glShadeModel(GL11.GL_SMOOTH);
|
||||
Tessellator t = Tessellator.instance;
|
||||
t.startDrawingQuads();
|
||||
t.setColorRGBA_I(0, 255);
|
||||
t.addVertex(x2, y1, zLevel);
|
||||
t.addVertex(x1, y1, zLevel);
|
||||
t.setColorRGBA_I(0, 0);
|
||||
t.addVertex(x1, y2, zLevel);
|
||||
t.addVertex(x2, y2, zLevel);
|
||||
t.draw();
|
||||
GL11.glDisable(GL11.GL_BLEND);
|
||||
GL11.glEnable(GL11.GL_CULL_FACE);
|
||||
GL11.glEnable(GL11.GL_TEXTURE_2D);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,327 @@
|
||||
package codechicken.nei.config.preset;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import net.minecraft.client.renderer.RenderHelper;
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL12;
|
||||
|
||||
import codechicken.core.gui.GuiWidget;
|
||||
import codechicken.lib.gui.GuiDraw;
|
||||
import codechicken.lib.vec.Rectangle4i;
|
||||
import codechicken.nei.ItemList.AllMultiItemFilter;
|
||||
import codechicken.nei.ItemPanel.ItemPanelSlot;
|
||||
import codechicken.nei.ItemsGrid;
|
||||
import codechicken.nei.Label;
|
||||
import codechicken.nei.NEIClientUtils;
|
||||
import codechicken.nei.PresetsList.Preset;
|
||||
import codechicken.nei.PresetsList.PresetMode;
|
||||
import codechicken.nei.TextField;
|
||||
import codechicken.nei.api.ItemFilter;
|
||||
import codechicken.nei.api.ItemInfo;
|
||||
import codechicken.nei.guihook.GuiContainerManager;
|
||||
import codechicken.nei.guihook.IContainerTooltipHandler;
|
||||
|
||||
public class LeftPanel extends GuiWidget {
|
||||
|
||||
protected static class MouseSelection {
|
||||
|
||||
public int startX = -1;
|
||||
public int startY = -1;
|
||||
public int startIndex = -1;
|
||||
public int endIndex = -1;
|
||||
|
||||
public Set<ItemStack> items = new HashSet<>();
|
||||
|
||||
public MouseSelection(int slotIndex, Rectangle4i rec) {
|
||||
endIndex = slotIndex;
|
||||
startIndex = slotIndex;
|
||||
startX = rec.x;
|
||||
startY = rec.y;
|
||||
}
|
||||
}
|
||||
|
||||
protected static final int INPUT_HEIGHT = 20;
|
||||
|
||||
public final PresetItemsGrid grid = new PresetItemsGrid() {
|
||||
|
||||
@Override
|
||||
protected ItemFilter getFilter() {
|
||||
Set<String> identifiers = preset.items;
|
||||
return new AllMultiItemFilter(
|
||||
item -> !ItemInfo.hiddenItems.contains(item),
|
||||
item -> identifiers.contains(Preset.getIdentifier(item)));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isSelected(ItemStack stack) {
|
||||
return mouseSelection != null && mouseSelection.items.contains(stack);
|
||||
}
|
||||
};
|
||||
|
||||
protected Label nameLabel = new Label(NEIClientUtils.translate("presets.name"), false);
|
||||
|
||||
protected TextField nameField = new TextField("name") {
|
||||
|
||||
@Override
|
||||
public void onTextChange(String oldText) {
|
||||
preset.name = text();
|
||||
}
|
||||
};
|
||||
|
||||
protected Label modeLabel = new Label(NEIClientUtils.translate("presets.mode"), false);
|
||||
|
||||
protected CheckboxButton modeHide;
|
||||
protected CheckboxButton modeRemove;
|
||||
protected CheckboxButton modeGroup;
|
||||
|
||||
protected CheckboxButton enabledButton;
|
||||
|
||||
protected final Preset preset;
|
||||
protected MouseSelection mouseSelection;
|
||||
|
||||
public LeftPanel(Preset preset) {
|
||||
super(1, 0, 2, 2);
|
||||
|
||||
this.preset = preset;
|
||||
|
||||
nameField.setText(preset.name);
|
||||
|
||||
modeHide = new CheckboxButton(NEIClientUtils.translate("presets.mode.hide")) {
|
||||
|
||||
@Override
|
||||
public boolean isChecked() {
|
||||
return preset.mode == PresetMode.HIDE;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onChange() {
|
||||
preset.mode = this.checked ? PresetMode.HIDE : null;
|
||||
}
|
||||
};
|
||||
|
||||
modeRemove = new CheckboxButton(NEIClientUtils.translate("presets.mode.remove")) {
|
||||
|
||||
@Override
|
||||
public boolean isChecked() {
|
||||
return preset.mode == PresetMode.REMOVE;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onChange() {
|
||||
preset.mode = this.checked ? PresetMode.REMOVE : null;
|
||||
}
|
||||
};
|
||||
|
||||
modeGroup = new CheckboxButton(NEIClientUtils.translate("presets.mode.group")) {
|
||||
|
||||
@Override
|
||||
public boolean isChecked() {
|
||||
return preset.mode == PresetMode.GROUP;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onChange() {
|
||||
preset.mode = this.checked ? PresetMode.GROUP : null;
|
||||
}
|
||||
};
|
||||
|
||||
enabledButton = new CheckboxButton(NEIClientUtils.translate("presets.enabled")) {
|
||||
|
||||
@Override
|
||||
public boolean isChecked() {
|
||||
return preset.enabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onChange() {
|
||||
preset.enabled = this.checked;
|
||||
}
|
||||
};
|
||||
|
||||
grid.restartFilter();
|
||||
}
|
||||
|
||||
public void mouseClicked(int x, int y, int button) {
|
||||
grid.mouseClicked(x, y, button);
|
||||
|
||||
if (modeHide.contains(x, y)) {
|
||||
modeHide.handleClick(x, y, button);
|
||||
}
|
||||
|
||||
if (modeRemove.contains(x, y)) {
|
||||
modeRemove.handleClick(x, y, button);
|
||||
}
|
||||
|
||||
if (modeGroup.contains(x, y)) {
|
||||
modeGroup.handleClick(x, y, button);
|
||||
}
|
||||
|
||||
if (enabledButton.contains(x, y)) {
|
||||
enabledButton.handleClick(x, y, button);
|
||||
}
|
||||
|
||||
if (nameField.contains(x, y)) {
|
||||
nameField.handleClick(x, y, button);
|
||||
} else {
|
||||
nameField.onGuiClick(x, y);
|
||||
}
|
||||
|
||||
if (mouseSelection == null && button == 0) {
|
||||
ItemPanelSlot slot = grid.getSlotMouseOver(x, y);
|
||||
|
||||
if (slot != null) {
|
||||
mouseSelection = new MouseSelection(slot.slotIndex, grid.getItemRect(slot.slotIndex));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected void onItemsChanges() {}
|
||||
|
||||
public void mouseMovedOrUp(int x, int y, int button) {
|
||||
nameField.mouseUp(x, y, button);
|
||||
|
||||
if (mouseSelection != null && button == 0) {
|
||||
ItemPanelSlot hoverSlot = grid.getSlotMouseOver(x, y);
|
||||
|
||||
if (hoverSlot != null && hoverSlot.slotIndex == mouseSelection.startIndex) {
|
||||
preset.items.remove(Preset.getIdentifier(hoverSlot.item));
|
||||
} else if (!mouseSelection.items.isEmpty()) {
|
||||
|
||||
for (ItemStack stack : mouseSelection.items) {
|
||||
preset.items.remove(Preset.getIdentifier(stack));
|
||||
}
|
||||
}
|
||||
|
||||
mouseSelection = null;
|
||||
onItemsChanges();
|
||||
}
|
||||
}
|
||||
|
||||
public void mouseDragged(int x, int y, int button, long time) {
|
||||
nameField.mouseDragged(x, y, button, time);
|
||||
|
||||
if (mouseSelection != null && button == 0) {
|
||||
final ItemPanelSlot slot = grid.getSlotMouseOver(x, y);
|
||||
|
||||
if (slot != null && slot.slotIndex != mouseSelection.endIndex) {
|
||||
mouseSelection.endIndex = slot.slotIndex;
|
||||
mouseSelection.items.clear();
|
||||
|
||||
final Rectangle4i rec = grid.getItemRect(slot.slotIndex);
|
||||
final Rectangle4i sel = new Rectangle4i(
|
||||
Math.min(rec.x, mouseSelection.startX),
|
||||
Math.min(rec.y, mouseSelection.startY),
|
||||
Math.max(rec.x, mouseSelection.startX) - Math.min(rec.x, mouseSelection.startX),
|
||||
Math.max(rec.y, mouseSelection.startY) - Math.min(rec.y, mouseSelection.startY));
|
||||
|
||||
for (int ix = sel.x; ix <= sel.x + sel.w; ix += ItemsGrid.SLOT_SIZE) {
|
||||
for (int iy = sel.y; iy <= sel.y + sel.h; iy += ItemsGrid.SLOT_SIZE) {
|
||||
ItemPanelSlot over = grid.getSlotMouseOver(ix, iy);
|
||||
|
||||
if (over != null) {
|
||||
mouseSelection.items.add(over.item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void update() {
|
||||
int CHECKBOX_WIDTH = (this.width - 12) / 3;
|
||||
nameLabel.x = this.x + 2;
|
||||
nameLabel.y = this.y + 4;
|
||||
nameLabel.w = this.width;
|
||||
nameLabel.h = 10;
|
||||
|
||||
nameField.x = this.x;
|
||||
nameField.y = nameLabel.y + nameLabel.h;
|
||||
nameField.w = this.width - CHECKBOX_WIDTH - 6;
|
||||
nameField.h = INPUT_HEIGHT;
|
||||
|
||||
enabledButton.x = nameField.x + nameField.w + 6;
|
||||
enabledButton.y = nameField.y;
|
||||
enabledButton.w = CHECKBOX_WIDTH;
|
||||
enabledButton.h = INPUT_HEIGHT;
|
||||
|
||||
modeLabel.x = this.x + 2;
|
||||
modeLabel.y = nameField.y + nameField.h + 6;
|
||||
modeLabel.w = this.width;
|
||||
modeLabel.h = 10;
|
||||
|
||||
modeHide.w = modeRemove.w = modeGroup.w = CHECKBOX_WIDTH;
|
||||
modeHide.h = modeRemove.h = modeGroup.h = INPUT_HEIGHT;
|
||||
modeHide.y = modeRemove.y = modeGroup.y = modeLabel.y + modeLabel.h;
|
||||
|
||||
modeHide.x = this.x + 1;
|
||||
modeRemove.x = modeHide.x + modeHide.w + 6;
|
||||
modeGroup.x = modeRemove.x + modeRemove.w + 6;
|
||||
|
||||
grid.setGridSize(
|
||||
this.x + 1,
|
||||
modeHide.y + modeHide.h + 2,
|
||||
this.width - 2,
|
||||
this.height - (modeHide.y + modeHide.h + 2));
|
||||
grid.refresh(null);
|
||||
}
|
||||
|
||||
public void draw(int mousex, int mousey, float frame) {
|
||||
nameLabel.draw(mousex, mousey);
|
||||
nameField.draw(mousex, mousey);
|
||||
|
||||
modeLabel.draw(mousex, mousey);
|
||||
modeHide.draw(mousex, mousey);
|
||||
modeRemove.draw(mousex, mousey);
|
||||
modeGroup.draw(mousex, mousey);
|
||||
|
||||
enabledButton.draw(mousex, mousey);
|
||||
|
||||
RenderHelper.enableGUIStandardItemLighting();
|
||||
GL11.glPushMatrix();
|
||||
GL11.glEnable(GL12.GL_RESCALE_NORMAL);
|
||||
|
||||
grid.draw(mousex, mousey);
|
||||
|
||||
GL11.glDisable(GL12.GL_RESCALE_NORMAL);
|
||||
GL11.glPopMatrix();
|
||||
RenderHelper.enableStandardItemLighting();
|
||||
}
|
||||
|
||||
public List<String> handleTooltip(int mousex, int mousey, List<String> tooltip) {
|
||||
ItemPanelSlot over = grid.getSlotMouseOver(mousex, mousey);
|
||||
|
||||
if (over != null) {
|
||||
tooltip = GuiContainerManager.itemDisplayNameMultiline(over.item, null, true);
|
||||
|
||||
synchronized (GuiContainerManager.tooltipHandlers) {
|
||||
for (IContainerTooltipHandler handler : GuiContainerManager.tooltipHandlers) {
|
||||
tooltip = handler.handleItemTooltip(null, over.item, mousex, mousey, tooltip);
|
||||
}
|
||||
}
|
||||
|
||||
if (tooltip.size() > 0) {
|
||||
tooltip.set(0, tooltip.get(0) + GuiDraw.TOOLTIP_LINESPACE); // add space after 'title'
|
||||
}
|
||||
|
||||
} else if (modeHide.contains(mousex, mousey)) {
|
||||
tooltip.add(NEIClientUtils.translate("presets.mode.hide.tip"));
|
||||
} else if (modeRemove.contains(mousex, mousey)) {
|
||||
tooltip.add(NEIClientUtils.translate("presets.mode.remove.tip"));
|
||||
} else if (modeGroup.contains(mousex, mousey)) {
|
||||
tooltip.add(NEIClientUtils.translate("presets.mode.group.tip"));
|
||||
}
|
||||
|
||||
return tooltip;
|
||||
}
|
||||
|
||||
public void keyTyped(char c, int keycode) {
|
||||
nameField.handleKeyPress(keycode, c);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,167 @@
|
||||
package codechicken.nei.config.preset;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import net.minecraft.client.gui.inventory.GuiContainer;
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
import codechicken.lib.gui.GuiDraw;
|
||||
import codechicken.lib.vec.Rectangle4i;
|
||||
import codechicken.nei.Button;
|
||||
import codechicken.nei.ItemList;
|
||||
import codechicken.nei.ItemPanel.ItemPanelSlot;
|
||||
import codechicken.nei.ItemSorter;
|
||||
import codechicken.nei.ItemsGrid;
|
||||
import codechicken.nei.Label;
|
||||
import codechicken.nei.RestartableTask;
|
||||
import codechicken.nei.api.ItemFilter;
|
||||
|
||||
public abstract class PresetItemsGrid extends ItemsGrid {
|
||||
|
||||
protected static final int BUTTON_SIZE = 16;
|
||||
|
||||
public Button pagePrev;
|
||||
public Label pageLabel;
|
||||
public Button pageNext;
|
||||
|
||||
protected ArrayList<ItemStack> newItems;
|
||||
|
||||
protected final RestartableTask updateFilter = new RestartableTask("NEI Presets Item Filtering") {
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
ArrayList<ItemStack> filtered;
|
||||
ItemFilter filter = getFilter();
|
||||
|
||||
try {
|
||||
filtered = ItemList.forkJoinPool.submit(
|
||||
() -> ItemList.items.parallelStream().filter(filter::matches)
|
||||
.collect(Collectors.toCollection(ArrayList::new)))
|
||||
.get();
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
filtered = new ArrayList<>();
|
||||
e.printStackTrace();
|
||||
stop();
|
||||
}
|
||||
|
||||
if (interrupted()) return;
|
||||
ItemSorter.sort(filtered);
|
||||
if (interrupted()) return;
|
||||
updateItemList(filtered);
|
||||
}
|
||||
};
|
||||
|
||||
public PresetItemsGrid() {
|
||||
|
||||
pageLabel = new Label("0/0", true);
|
||||
|
||||
pagePrev = new Button("<") {
|
||||
|
||||
public boolean onButtonPress(boolean rightclick) {
|
||||
|
||||
if (rightclick) {
|
||||
setPage(0);
|
||||
} else {
|
||||
shiftPage(-1);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
pageNext = new Button(">") {
|
||||
|
||||
public boolean onButtonPress(boolean rightclick) {
|
||||
|
||||
if (rightclick) {
|
||||
setPage(getNumPages() - 1);
|
||||
} else {
|
||||
shiftPage(1);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
protected String getLabelText() {
|
||||
return String.format("%d/%d", getPage(), Math.max(1, getNumPages()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setGridSize(int mleft, int mtop, int w, int h) {
|
||||
pageLabel.text = getLabelText();
|
||||
|
||||
pagePrev.w = pageNext.w = BUTTON_SIZE;
|
||||
pagePrev.h = pageNext.h = BUTTON_SIZE;
|
||||
pagePrev.y = pageNext.y = mtop;
|
||||
|
||||
pagePrev.x = mleft;
|
||||
pageNext.x = mleft + w - pageNext.w;
|
||||
|
||||
pageLabel.x = mleft + w / 2;
|
||||
pageLabel.y = pagePrev.y + 5;
|
||||
|
||||
super.setGridSize(mleft, mtop + BUTTON_SIZE + 2, w, h - BUTTON_SIZE - 4);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(int mousex, int mousey) {
|
||||
pagePrev.draw(mousex, mousey);
|
||||
pageNext.draw(mousex, mousey);
|
||||
pageLabel.draw(mousex, mousey);
|
||||
|
||||
super.draw(mousex, mousey);
|
||||
}
|
||||
|
||||
public void mouseClicked(int x, int y, int button) {
|
||||
|
||||
if (pagePrev.contains(x, y)) {
|
||||
pagePrev.handleClick(x, y, button);
|
||||
}
|
||||
|
||||
if (pageNext.contains(x, y)) {
|
||||
pageNext.handleClick(x, y, button);
|
||||
}
|
||||
}
|
||||
|
||||
public void restartFilter() {
|
||||
updateFilter.restart();
|
||||
}
|
||||
|
||||
protected void updateItemList(List<ItemStack> newItems) {
|
||||
this.newItems = new ArrayList<>(newItems);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refresh(GuiContainer gui) {
|
||||
|
||||
if (this.newItems != null) {
|
||||
this.realItems = this.newItems;
|
||||
this.newItems = null;
|
||||
onItemsChanged();
|
||||
}
|
||||
|
||||
super.refresh(gui);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void beforeDrawSlot(@Nullable ItemPanelSlot focused, int slotIdx, Rectangle4i rect) {
|
||||
if (isSelected(getItem(slotIdx))) {
|
||||
GuiDraw.drawRect(rect.x, rect.y, rect.w, rect.h, 0xee555555);
|
||||
} else {
|
||||
super.beforeDrawSlot(focused, slotIdx, rect);
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract boolean isSelected(ItemStack stack);
|
||||
|
||||
protected abstract ItemFilter getFilter();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,396 @@
|
||||
package codechicken.nei.config.preset;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import net.minecraft.client.renderer.RenderHelper;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.EnumChatFormatting;
|
||||
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL12;
|
||||
|
||||
import codechicken.core.gui.GuiWidget;
|
||||
import codechicken.lib.gui.GuiDraw;
|
||||
import codechicken.lib.vec.Rectangle4i;
|
||||
import codechicken.nei.ItemList;
|
||||
import codechicken.nei.ItemList.AllMultiItemFilter;
|
||||
import codechicken.nei.ItemList.AnyMultiItemFilter;
|
||||
import codechicken.nei.ItemList.NegatedItemFilter;
|
||||
import codechicken.nei.ItemPanel.ItemPanelSlot;
|
||||
import codechicken.nei.ItemsGrid;
|
||||
import codechicken.nei.NEIClientConfig;
|
||||
import codechicken.nei.NEIClientUtils;
|
||||
import codechicken.nei.PresetsList;
|
||||
import codechicken.nei.PresetsList.Preset;
|
||||
import codechicken.nei.SearchField.GuiSearchField;
|
||||
import codechicken.nei.TextField;
|
||||
import codechicken.nei.api.ItemFilter;
|
||||
import codechicken.nei.api.ItemInfo;
|
||||
import codechicken.nei.guihook.GuiContainerManager;
|
||||
import codechicken.nei.guihook.IContainerTooltipHandler;
|
||||
import codechicken.nei.util.TextHistory;
|
||||
import cpw.mods.fml.common.registry.GameRegistry;
|
||||
|
||||
public class RightPanel extends GuiWidget {
|
||||
|
||||
protected static class MouseSelection {
|
||||
|
||||
public int startX = -1;
|
||||
public int startY = -1;
|
||||
public int startIndex = -1;
|
||||
public int endIndex = -1;
|
||||
|
||||
public Set<ItemStack> items = new HashSet<>();
|
||||
public boolean append = true;
|
||||
|
||||
public MouseSelection(int slotIndex, Rectangle4i rec, boolean ppnd) {
|
||||
append = ppnd;
|
||||
endIndex = slotIndex;
|
||||
startIndex = slotIndex;
|
||||
startX = rec.x;
|
||||
startY = rec.y;
|
||||
}
|
||||
}
|
||||
|
||||
protected static abstract class PresetSearchField extends TextField {
|
||||
|
||||
private static final TextHistory history = new TextHistory();
|
||||
|
||||
public PresetSearchField(String ident) {
|
||||
super(ident);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initInternalTextField() {
|
||||
field = new GuiSearchField();
|
||||
field.setMaxStringLength(maxSearchLength);
|
||||
field.setCursorPositionZero();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTextColour() {
|
||||
if (!text().isEmpty()) {
|
||||
return focused() ? 0xFFcc3300 : 0xFF993300;
|
||||
} else {
|
||||
return focused() ? 0xFFE0E0E0 : 0xFF909090;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void lastKeyTyped(int keyID, char keyChar) {
|
||||
|
||||
if (!focused() && NEIClientConfig.isKeyHashDown("gui.search")) {
|
||||
setFocus(true);
|
||||
}
|
||||
|
||||
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 ((GuiSearchField) field).getFilter();
|
||||
}
|
||||
|
||||
@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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected static final int INPUT_HEIGHT = 20;
|
||||
protected static final int BUTTON_SIZE = 16;
|
||||
|
||||
protected final PresetItemsGrid grid = new PresetItemsGrid() {
|
||||
|
||||
@Override
|
||||
protected ItemFilter getFilter() {
|
||||
AllMultiItemFilter filter = new AllMultiItemFilter();
|
||||
filter.filters.add(item -> !ItemInfo.hiddenItems.contains(item));
|
||||
filter.filters.add(searchField.getFilter());
|
||||
|
||||
if (enabledPresets.isChecked()) {
|
||||
AllMultiItemFilter andFilter = new AllMultiItemFilter();
|
||||
AnyMultiItemFilter orFilter = new AnyMultiItemFilter();
|
||||
Set<String> identifiers = PresetsList.presets.stream().flatMap(p -> p.items.stream())
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
andFilter.filters.add(item -> !identifiers.contains(Preset.getIdentifier(item)));
|
||||
andFilter.filters.add(new NegatedItemFilter(ItemList.collapsibleItems.getItemFilter()));
|
||||
|
||||
if (slotIndex != -1) {
|
||||
orFilter.filters.add(PresetsList.presets.get(slotIndex));
|
||||
}
|
||||
|
||||
orFilter.filters.add(andFilter);
|
||||
filter.filters.add(orFilter);
|
||||
}
|
||||
|
||||
return filter;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isSelected(ItemStack stack) {
|
||||
|
||||
if (mouseSelection != null && mouseSelection.items.contains(stack)) {
|
||||
return mouseSelection.append != false;
|
||||
}
|
||||
|
||||
return preset.items.contains(Preset.getIdentifier(stack));
|
||||
}
|
||||
};
|
||||
|
||||
protected CheckboxButton enabledPresets;
|
||||
|
||||
protected final Preset preset;
|
||||
protected final int slotIndex;
|
||||
protected MouseSelection mouseSelection;
|
||||
|
||||
protected final PresetSearchField searchField = new PresetSearchField("preset-search") {
|
||||
|
||||
@Override
|
||||
public void onTextChange(String oldText) {
|
||||
final String newText = text();
|
||||
if (!newText.equals(oldText)) {
|
||||
grid.restartFilter();
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
public RightPanel(Preset preset, int slotIndex) {
|
||||
super(1, 0, 2, 2);
|
||||
|
||||
this.slotIndex = slotIndex;
|
||||
this.preset = preset;
|
||||
|
||||
enabledPresets = new CheckboxButton(NEIClientUtils.translate("presets.filter")) {
|
||||
|
||||
@Override
|
||||
protected void onChange() {
|
||||
grid.restartFilter();
|
||||
}
|
||||
};
|
||||
|
||||
enabledPresets.setChecked(true);
|
||||
|
||||
grid.restartFilter();
|
||||
}
|
||||
|
||||
public void mouseClicked(int x, int y, int button) {
|
||||
grid.mouseClicked(x, y, button);
|
||||
|
||||
if (enabledPresets.contains(x, y)) {
|
||||
enabledPresets.handleClick(x, y, button);
|
||||
}
|
||||
|
||||
if (searchField.contains(x, y)) {
|
||||
searchField.handleClick(x, y, button);
|
||||
} else {
|
||||
searchField.onGuiClick(x, y);
|
||||
}
|
||||
|
||||
if (mouseSelection == null && (button == 0 || button == 1)) {
|
||||
ItemPanelSlot slot = grid.getSlotMouseOver(x, y);
|
||||
|
||||
if (slot != null) {
|
||||
mouseSelection = new MouseSelection(slot.slotIndex, grid.getItemRect(slot.slotIndex), button == 0);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected void onItemsChanges() {}
|
||||
|
||||
public void mouseMovedOrUp(int x, int y, int button) {
|
||||
searchField.mouseUp(x, y, button);
|
||||
|
||||
if (mouseSelection != null && (button == 0 || button == 1)) {
|
||||
ItemPanelSlot hoverSlot = grid.getSlotMouseOver(x, y);
|
||||
|
||||
if (hoverSlot != null && hoverSlot.slotIndex == mouseSelection.startIndex) {
|
||||
setHidden(hoverSlot.item, button == 0);
|
||||
} else if (!mouseSelection.items.isEmpty()) {
|
||||
|
||||
for (ItemStack stack : mouseSelection.items) {
|
||||
hideItem(stack, mouseSelection.append);
|
||||
}
|
||||
}
|
||||
|
||||
mouseSelection = null;
|
||||
onItemsChanges();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected void setHidden(final ItemStack stack, final boolean append) {
|
||||
|
||||
if (NEIClientUtils.shiftKey()) {
|
||||
final List<ItemStack> items = grid.getItems();
|
||||
|
||||
for (int i = 0; i < items.size(); i++) {
|
||||
if (stack.getItem().equals(items.get(i).getItem())) {
|
||||
hideItem(items.get(i), append);
|
||||
}
|
||||
}
|
||||
|
||||
} else if (NEIClientUtils.controlKey()) {
|
||||
final String modId = getModId(stack);
|
||||
|
||||
if (modId == null) {
|
||||
hideItem(stack, append);
|
||||
} else {
|
||||
final List<ItemStack> items = grid.getItems();
|
||||
|
||||
for (int i = 0; i < items.size(); i++) {
|
||||
final String mod = getModId(items.get(i));
|
||||
if (mod != null && mod.equals(modId)) {
|
||||
hideItem(items.get(i), append);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
hideItem(stack, append);
|
||||
}
|
||||
}
|
||||
|
||||
protected void hideItem(final ItemStack stack, boolean append) {
|
||||
if (append) {
|
||||
preset.items.add(Preset.getIdentifier(stack));
|
||||
} else {
|
||||
preset.items.remove(Preset.getIdentifier(stack));
|
||||
}
|
||||
}
|
||||
|
||||
protected static String getModId(final ItemStack stack) {
|
||||
try {
|
||||
return GameRegistry.findUniqueIdentifierFor(stack.getItem()).modId;
|
||||
} catch (Exception ignored) {}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public void mouseDragged(int x, int y, int button, long time) {
|
||||
searchField.mouseDragged(x, y, button, time);
|
||||
|
||||
if (mouseSelection != null && (button == 0 || button == 1)) {
|
||||
final ItemPanelSlot slot = grid.getSlotMouseOver(x, y);
|
||||
|
||||
if (slot != null && slot.slotIndex != mouseSelection.endIndex) {
|
||||
mouseSelection.endIndex = slot.slotIndex;
|
||||
mouseSelection.items.clear();
|
||||
|
||||
final Rectangle4i rec = grid.getItemRect(slot.slotIndex);
|
||||
final Rectangle4i sel = new Rectangle4i(
|
||||
Math.min(rec.x, mouseSelection.startX),
|
||||
Math.min(rec.y, mouseSelection.startY),
|
||||
Math.max(rec.x, mouseSelection.startX) - Math.min(rec.x, mouseSelection.startX),
|
||||
Math.max(rec.y, mouseSelection.startY) - Math.min(rec.y, mouseSelection.startY));
|
||||
|
||||
for (int ix = sel.x; ix <= sel.x + sel.w; ix += ItemsGrid.SLOT_SIZE) {
|
||||
for (int iy = sel.y; iy <= sel.y + sel.h; iy += ItemsGrid.SLOT_SIZE) {
|
||||
ItemPanelSlot over = grid.getSlotMouseOver(ix, iy);
|
||||
|
||||
if (over != null) {
|
||||
mouseSelection.items.add(over.item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void update() {
|
||||
enabledPresets.w = 20;
|
||||
enabledPresets.h = INPUT_HEIGHT;
|
||||
enabledPresets.x = this.x;
|
||||
enabledPresets.y = this.y + this.height - 2 - INPUT_HEIGHT;
|
||||
|
||||
searchField.w = this.width - enabledPresets.w - 3;
|
||||
searchField.h = INPUT_HEIGHT;
|
||||
searchField.x = enabledPresets.x + enabledPresets.w + 3;
|
||||
searchField.y = enabledPresets.y;
|
||||
|
||||
grid.setGridSize(this.x, this.y, this.width, searchField.y - this.y);
|
||||
grid.refresh(null);
|
||||
}
|
||||
|
||||
public void draw(int mousex, int mousey, float frame) {
|
||||
enabledPresets.draw(mousex, mousey);
|
||||
searchField.draw(mousex, mousey);
|
||||
|
||||
RenderHelper.enableGUIStandardItemLighting();
|
||||
GL11.glPushMatrix();
|
||||
GL11.glEnable(GL12.GL_RESCALE_NORMAL);
|
||||
|
||||
grid.draw(mousex, mousey);
|
||||
|
||||
GL11.glDisable(GL12.GL_RESCALE_NORMAL);
|
||||
GL11.glPopMatrix();
|
||||
RenderHelper.enableStandardItemLighting();
|
||||
}
|
||||
|
||||
public List<String> handleTooltip(int mousex, int mousey, List<String> tooltip) {
|
||||
ItemPanelSlot over = grid.getSlotMouseOver(mousex, mousey);
|
||||
|
||||
if (over != null) {
|
||||
tooltip = GuiContainerManager.itemDisplayNameMultiline(over.item, null, true);
|
||||
|
||||
synchronized (GuiContainerManager.tooltipHandlers) {
|
||||
for (IContainerTooltipHandler handler : GuiContainerManager.tooltipHandlers) {
|
||||
tooltip = handler.handleItemTooltip(null, over.item, mousex, mousey, tooltip);
|
||||
}
|
||||
}
|
||||
|
||||
if (tooltip.size() > 0) {
|
||||
tooltip.set(0, tooltip.get(0) + GuiDraw.TOOLTIP_LINESPACE); // add space after 'title'
|
||||
}
|
||||
|
||||
} else if (enabledPresets.contains(mousex, mousey)) {
|
||||
tooltip.add(NEIClientUtils.translate("presets.filter.tip"));
|
||||
}
|
||||
|
||||
return tooltip;
|
||||
}
|
||||
|
||||
public void keyTyped(char c, int keycode) {
|
||||
searchField.handleKeyPress(keycode, c);
|
||||
}
|
||||
|
||||
public void mouseScrolled(int x, int y, int scroll) {
|
||||
if (grid.contains(x, y)) {
|
||||
grid.shiftPage(-scroll);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -11,7 +11,6 @@ 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;
|
||||
@@ -23,6 +22,7 @@ import net.minecraftforge.fluids.IFluidContainerItem;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
||||
import codechicken.nei.ItemStackMap;
|
||||
import codechicken.nei.NEIClientConfig;
|
||||
import codechicken.nei.api.IStackStringifyHandler;
|
||||
import codechicken.nei.recipe.stackinfo.DefaultStackStringifyHandler;
|
||||
@@ -32,7 +32,7 @@ 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 ItemStackMap<String> guidcache = new ItemStackMap<>();
|
||||
private static final LinkedHashMap<ItemStack, FluidStack> fluidcache = new LinkedHashMap<ItemStack, FluidStack>() {
|
||||
|
||||
@Override
|
||||
@@ -119,64 +119,67 @@ public class StackInfo {
|
||||
}
|
||||
|
||||
public static String getItemStackGUID(ItemStack stack) {
|
||||
if (!guidcache.containsKey(stack)) {
|
||||
String guid = guidcache.get(stack);
|
||||
|
||||
final NBTTagCompound nbTag = itemStackToNBT(stack, false);
|
||||
if (guid != null) {
|
||||
return guid;
|
||||
}
|
||||
|
||||
if (nbTag == null) {
|
||||
return null;
|
||||
}
|
||||
final NBTTagCompound nbTag = itemStackToNBT(stack, false);
|
||||
|
||||
nbTag.removeTag("Count");
|
||||
if (nbTag == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (nbTag.getShort("Damage") == 0) {
|
||||
nbTag.removeTag("Damage");
|
||||
}
|
||||
nbTag.removeTag("Count");
|
||||
|
||||
if (nbTag.hasKey("tag") && nbTag.getCompoundTag("tag").hasNoTags()) {
|
||||
nbTag.removeTag("tag");
|
||||
}
|
||||
if (nbTag.getShort("Damage") == 0) {
|
||||
nbTag.removeTag("Damage");
|
||||
}
|
||||
|
||||
if (nbTag.hasKey("strId") && guidfilters.containsKey(nbTag.getString("strId"))) {
|
||||
final ArrayList<String> keys = new ArrayList<>();
|
||||
final String strId = nbTag.getString("strId");
|
||||
if (nbTag.hasKey("tag") && nbTag.getCompoundTag("tag").hasNoTags()) {
|
||||
nbTag.removeTag("tag");
|
||||
}
|
||||
|
||||
keys.add(strId);
|
||||
if (nbTag.hasKey("strId") && guidfilters.containsKey(nbTag.getString("strId"))) {
|
||||
final ArrayList<String> keys = new ArrayList<>();
|
||||
final String strId = nbTag.getString("strId");
|
||||
|
||||
guidfilters.get(strId).forEach((key, rule) -> {
|
||||
Object local = nbTag;
|
||||
keys.add(strId);
|
||||
|
||||
for (int i = 0; i < rule.length; i++) {
|
||||
guidfilters.get(strId).forEach((key, rule) -> {
|
||||
Object local = nbTag;
|
||||
|
||||
try {
|
||||
for (int i = 0; i < rule.length; i++) {
|
||||
|
||||
if (local instanceof NBTTagCompound) {
|
||||
local = ((NBTTagCompound) local).getTag(rule[i]);
|
||||
} else if (local instanceof NBTTagList) {
|
||||
local = ((NBTTagList) local).tagList.get(Integer.parseInt(rule[i]));
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
try {
|
||||
|
||||
} catch (Throwable e) {
|
||||
if (local instanceof NBTTagCompound) {
|
||||
local = ((NBTTagCompound) local).getTag(rule[i]);
|
||||
} else if (local instanceof NBTTagList) {
|
||||
local = ((NBTTagList) local).tagList.get(Integer.parseInt(rule[i]));
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (local instanceof NBTBase) {
|
||||
keys.add(((NBTBase) local).toString());
|
||||
} else if (local != null) {
|
||||
keys.add(String.valueOf(local));
|
||||
} catch (Throwable e) {
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
synchronized (guidcache) {
|
||||
guidcache.put(stack, keys.toString());
|
||||
}
|
||||
} else {
|
||||
synchronized (guidcache) {
|
||||
guidcache.put(stack, nbTag.toString());
|
||||
if (local instanceof NBTBase) {
|
||||
keys.add(((NBTBase) local).toString());
|
||||
} else if (local != null) {
|
||||
keys.add(String.valueOf(local));
|
||||
}
|
||||
});
|
||||
|
||||
synchronized (guidcache) {
|
||||
guidcache.put(stack, keys.toString());
|
||||
}
|
||||
} else {
|
||||
synchronized (guidcache) {
|
||||
guidcache.put(stack, nbTag.toString());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -35,11 +35,11 @@ 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;
|
||||
import codechicken.nei.PositionedStack;
|
||||
import codechicken.nei.PresetsList;
|
||||
import codechicken.nei.api.DefaultOverlayRenderer;
|
||||
import codechicken.nei.api.IOverlayHandler;
|
||||
import codechicken.nei.api.IRecipeOverlayRenderer;
|
||||
@@ -433,7 +433,7 @@ public abstract class TemplateRecipeHandler implements ICraftingHandler, IUsageH
|
||||
protected static ItemFilter getItemFilter() {
|
||||
return new AllMultiItemFilter(
|
||||
item -> !ItemInfo.hiddenItems.contains(item),
|
||||
LayoutManager.presetsPanel != null ? LayoutManager.presetsPanel.getFilter() : null,
|
||||
PresetsList.getItemFilter(),
|
||||
GuiRecipe.searchField != null ? GuiRecipe.searchField.getFilter() : null);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
# Collapsible Items Filters
|
||||
#
|
||||
# One line - one group
|
||||
# Item added in first valid group
|
||||
# | - logical or. multi-item search (wrench|hammer)
|
||||
# $ - search by ore dictionary ($ore)
|
||||
# ! - logical not. exclude items that match the following expression (-@minecraft)
|
||||
# r/.../ - standard java regex (@r/m\w{6}ft/ = @minecraft)
|
||||
# 0 - damage filter
|
||||
# 0-12 - damage range filter
|
||||
# , - logical or in token
|
||||
#
|
||||
#
|
||||
minecraft:spawn_egg
|
||||
minecraft:mob_spawner
|
||||
minecraft:record_
|
||||
#splash
|
||||
minecraft:potion >16000
|
||||
#lingering
|
||||
minecraft:potion >8000 <9000
|
||||
@@ -13,6 +13,9 @@ nei.bookmark.pullBookmarkedItems.tip=Pull all bookmarked items from storage to i
|
||||
|
||||
nei.itempanel.quantity.default=One stack
|
||||
nei.itempanel.loading=Loading Item List...
|
||||
nei.itempanel.collapsed.button.tip=Toggle Groups
|
||||
nei.itempanel.collapsed.hint.expand=Alt-Click to expand (%d items)
|
||||
nei.itempanel.collapsed.hint.collapse=Alt-Click to collapse (%d items)
|
||||
|
||||
nei.enchant=Enchant
|
||||
nei.enchant.level=Level
|
||||
@@ -85,6 +88,7 @@ nei.chat.chunkoverlay.3=Chunk Overlay: GT Ore Veins
|
||||
|
||||
nei.options=NEI Options
|
||||
nei.options.back=Back
|
||||
nei.options.save=Save
|
||||
nei.options.world=World
|
||||
nei.options.global=Global
|
||||
nei.options.global.tip.0=Options apply to all worlds
|
||||
@@ -266,6 +270,14 @@ nei.options.inventory.invertMouseScrollTransfer.false=False
|
||||
nei.options.inventory.cacheItemRendering=Cache Item Rendering
|
||||
nei.options.inventory.cacheItemRendering.true=True
|
||||
nei.options.inventory.cacheItemRendering.false=False
|
||||
nei.options.inventory.collapsibleItems=Collapsible Items
|
||||
nei.options.inventory.collapsibleItems.enabled=Collapsible Items
|
||||
nei.options.inventory.collapsibleItems.enabled.true=Enabled
|
||||
nei.options.inventory.collapsibleItems.enabled.false=Disabled
|
||||
nei.options.inventory.collapsibleItems.expandedColor=Expanded Color
|
||||
nei.options.inventory.collapsibleItems.collapsedColor=Collapsed Color
|
||||
nei.options.inventory.collapsibleItems.reloadLabel=Reload
|
||||
nei.options.inventory.collapsibleItems.reloadButton=Run
|
||||
nei.options.inventory.history=History Panel
|
||||
nei.options.inventory.history.enabled=History Panel Visibility
|
||||
nei.options.inventory.history.enabled.true=Enabled
|
||||
@@ -294,6 +306,7 @@ nei.options.world.highlight_tips.show=Shown
|
||||
nei.options.world.highlight_tips.sample=Sample
|
||||
|
||||
nei.options.world.panels=Panels Settings
|
||||
nei.options.world.presets=Presets List
|
||||
|
||||
nei.options.tools=Tools
|
||||
nei.options.tools.handler_load_from_config=Load handlers from Config
|
||||
@@ -391,13 +404,20 @@ nei.subsets.Items.Weapons.Ranged=Ranged
|
||||
nei.subsets.Items.Weapons.Swords=Swords
|
||||
nei.subsets.Mod=Mod
|
||||
|
||||
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
|
||||
nei.presets.label.selected=%s Presets
|
||||
nei.presets.new=New Preset
|
||||
nei.presets.create=Create Preset
|
||||
nei.presets.update=Update Preset
|
||||
nei.presets.enabled=Enabled
|
||||
nei.presets.filter=F
|
||||
nei.presets.filter.tip=Hide items from another active presets
|
||||
nei.presets.name=Preset Name
|
||||
nei.presets.mode=Mode
|
||||
nei.presets.mode.hide=Hide
|
||||
nei.presets.mode.hide.char=H
|
||||
nei.presets.mode.hide.tip=Hide items in panel
|
||||
nei.presets.mode.remove=Remove
|
||||
nei.presets.mode.remove.tip=Hide items in panel and it recipes
|
||||
nei.presets.mode.remove.char=R
|
||||
nei.presets.mode.group=Group
|
||||
nei.presets.mode.group.tip=Create custom collapsible items group
|
||||
nei.presets.mode.group.char=G
|
||||
@@ -316,12 +316,3 @@ nei.subsets.Items.Weapons=武器
|
||||
nei.subsets.Items.Weapons.Ranged=远程
|
||||
nei.subsets.Items.Weapons.Swords=剑
|
||||
nei.subsets.Mod=Mod
|
||||
|
||||
nei.presets.blacklist.label=黑
|
||||
nei.presets.blacklist.tooltip=黑名单
|
||||
nei.presets.whitelist.label=白
|
||||
nei.presets.whitelist.tooltip=白名单
|
||||
nei.presets.textfield.tooltip.1=Enter - 保存
|
||||
nei.presets.textfield.tooltip.2=Esc - 取消
|
||||
nei.presets.label.tooltip=双击编辑
|
||||
nei.presets.label.selected=%s 预设
|
||||
Reference in new issue
Block a user