mmb.menu.world.window.TabInventory Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of multimachinebuilder Show documentation
Show all versions of multimachinebuilder Show documentation
Dependency for the MultiMachineBuilder, a voxel game about building an industrial empire in a finite world.
THIS RELEASE IS NOT PLAYABLE. To play the game, donwload from >ITCH.IO LINK HERE< or >GH releases link here<
/**
*
*/
package mmb.menu.world.window;
import javax.swing.JPanel;
import net.miginfocom.swing.MigLayout;
import javax.swing.JScrollPane;
import javax.swing.Timer;
import com.pploder.events.Event;
import monniasza.collects.Collects;
import javax.swing.JButton;
import javax.swing.JLabel;
import static mmb.engine.settings.GlobalSettings.*;
import java.awt.Color;
import javax.swing.JSpinner;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.Set;
import java.util.function.Predicate;
import javax.swing.BoxLayout;
import javax.swing.DefaultListModel;
import javax.swing.JCheckBox;
import javax.swing.JList;
import io.github.parubok.text.multiline.MultilineLabel;
import mmb.NN;
import mmb.Nil;
import mmb.content.electric.VoltageTier;
import mmb.engine.CatchingEvent;
import mmb.engine.block.Block;
import mmb.engine.block.BlockEntityType;
import mmb.engine.block.BlockType;
import mmb.engine.craft.GlobalRecipeRegistrar;
import mmb.engine.craft.Recipe;
import mmb.engine.debug.Debugger;
import mmb.engine.inv.Inventory;
import mmb.engine.inv.ItemRecord;
import mmb.engine.item.Item;
import mmb.engine.item.ItemEntityType;
import mmb.engine.item.ItemEntry;
import mmb.engine.item.ItemType;
import mmb.engine.item.Items;
import mmb.engine.worlds.world.Player;
import mmb.menu.components.BoundCheckBox;
import mmb.menu.world.CreativeItemList;
import mmb.menu.world.inv.CraftGUI;
import mmb.menu.world.inv.InventoryController;
/**
* @author oskar
*
*/
public class TabInventory extends JPanel {
private static final long serialVersionUID = 4210914960590758120L;
private JScrollPane creativeScrollPane;
private CreativeItemList creativeItemList;
@NN private static final Debugger debug = new Debugger("PLAYER INVENTORY");
private Player player;
public final Event playerChanged = new CatchingEvent<>(debug, "Failed to process player changed event");
public final WorldWindow window;
//Tag selectors (tagsels)
public static interface Tagsel{
@NN public DefaultListModel eligible();
@NN public String title();
}
/**
* Selects all items
* @author oskar
*/
public static class AllTagsel implements Tagsel{
@NN private static final String title = "1 "+$res("wguit-all");
@Override
public DefaultListModel eligible() {
return CreativeItemList.model;
}
@Override
public String title() {
return title;
}
@Override
public String toString() {
return title;
}
}
/**
* Selects items which match criteria
* @author oskar
*/
public static class FilterTagsel implements Tagsel{
@NN public final String tag;
@NN public final DefaultListModel set;
public FilterTagsel(String s, Predicate filter) {
tag = "2 "+s;
set = new DefaultListModel<>();
for(ItemType item: Items.items) {
if(filter.test(item)) set.addElement(item);
}
}
@Override
public DefaultListModel eligible() {
return set;
}
@Override
public String title() {
return tag;
}
@Override
public String toString() {
return tag;
}
}
/**
* Selects items by tag
* @author oskar
*/
public static class TaggedSel implements Tagsel{
/** The tag selection */
@NN public final String tag;
@NN public final DefaultListModel set;
public TaggedSel(String s, Set set2) {
tag = "3 "+s;
set = new DefaultListModel<>();
for(ItemType item: set2) {
set.addElement(item);
}
}
@Override
public DefaultListModel eligible() {
return set;
}
@Override
public String title() {
return tag;
}
@Override
public String toString() {
return tag;
}
}
/**
* Create an inventory panel with a player pre-set
* @param window world window, for which the tab is created
* @param player player represented in this tab
*/
public TabInventory(WorldWindow window, Player player) {
this(window);
setPlayer(player);
}
/**
* Create an inventory panel without a player
* @param window world window, for which the tab is created
* @wbp.parser.constructor
*/
public TabInventory(WorldWindow window) {
this.window = window;
setLayout(new MigLayout("", "[:400.00:400.00,grow,fill][][grow]", "[20px,grow]"));
InventoryController ctrl = new InventoryController();
craftGUI = new CraftGUI(2, null, null, ctrl);
timer = new Timer(0, e -> craftGUI.inventoryController.refresh());
add(craftGUI, "cell 1 0,growy");
creativePanel = new JPanel();
add(creativePanel, "cell 0 0,grow");
creativePanel.setLayout(new MigLayout("", "[grow][grow]", "[][grow][grow][]"));
lblSort = new JLabel($res("wgui-sort"));
creativePanel.add(lblSort, "cell 0 0");
panel = new JPanel();
creativePanel.add(panel, "cell 1 0,growx");
panel.setLayout(new MigLayout("", "[][]", "[][][][][]"));
lblCreativeItems = new JLabel($res("wgui-creati"));
panel.add(lblCreativeItems, "cell 0 0");
checkSurvival = new BoundCheckBox();
checkSurvival.setText($res("wgui-creamode"));
panel.add(checkSurvival, "cell 1 0");
lbAddRemoveCount = new JLabel($res("wgui-icount"));
panel.add(lbAddRemoveCount, "cell 0 1");
itemAmt = new JSpinner();
panel.add(itemAmt, "cell 1 1,growx");
JButton btnAdd = new JButton($res("wgui-a1"));
panel.add(btnAdd, "cell 0 2,growx");
btnAdd.addActionListener(e -> addItems(1));
btnAdd.setBackground(new Color(0, 170, 0));
JButton btnAddN = new JButton($res("wgui-an"));
panel.add(btnAddN, "cell 1 2,growx");
btnAddN.addActionListener(e -> {
@SuppressWarnings("boxing")
int amt = (Integer)(itemAmt.getValue());
addItems(amt);
});
btnAddN.setBackground(new Color(0, 204, 0));
JButton btnRemove = new JButton($res("wgui-r1"));
panel.add(btnRemove, "cell 0 3,growx");
btnRemove.addActionListener(e -> removeItems(1));
btnRemove.setBackground(new Color(170, 0, 0));
JButton btnRemoveN = new JButton($res("wgui-rn"));
btnRemoveN.addActionListener(e -> {
@SuppressWarnings("boxing")
int amt = (Integer)(itemAmt.getValue());
removeItems(amt);
});
btnRemoveN.setBackground(new Color(204, 0, 0));
panel.add(btnRemoveN, "cell 1 3");
JButton btnREmoveAll = new JButton($res("wgui-ra"));
btnREmoveAll.addActionListener(e -> removeItems(Integer.MAX_VALUE));
btnREmoveAll.setBackground(new Color(255, 0, 0));
panel.add(btnREmoveAll, "cell 0 4 2 1,growx");
selectSortItemTypes = new SelectSortItemTypes(() -> tags);
creativePanel.add(selectSortItemTypes, "cell 0 1,grow");
//Creative Item List
creativeScrollPane = new JScrollPane();
creativePanel.add(creativeScrollPane, "cell 1 1 1 2,grow");
creativeItemList = new CreativeItemList();
creativeItemList.addListSelectionListener(e -> {
ItemType item = creativeItemList.getSelectedValue();
String s = (item==null)?null:item.description();
multilineLabel.setText(s==null?"":s);
});
creativeScrollPane.setViewportView(creativeItemList);
lblResults = new JLabel($res("wgui-results"));
creativeScrollPane.setColumnHeaderView(lblResults);
//Tags
DefaultListModel model = new DefaultListModel<>();
model.addElement(new AllTagsel());
model.addElement(new FilterTagsel($res("wguit-block"), i -> i instanceof BlockType));
model.addElement(new FilterTagsel($res("wguit-items"), i -> !(i instanceof BlockType)));
model.addElement(new FilterTagsel($res("wguit-bents"), i -> i instanceof BlockEntityType));
model.addElement(new FilterTagsel($res("wguit-ients"), i -> i instanceof ItemEntityType));
model.addElement(new FilterTagsel($res("wguit-sblk"), i -> i instanceof Block));
model.addElement(new FilterTagsel($res("wguit-sitem"), i -> i instanceof Item && !(i instanceof BlockType)));
model.addElement(new FilterTagsel($res("wguit-notags"), i -> !Items.tags.containsValue(i)));
model.addElement(new FilterTagsel($res("wguit-tags"), i -> Items.tags.containsValue(i)));
model.addElement(new FilterTagsel($res("wguit-norecipes"), i -> !GlobalRecipeRegistrar.craftable.contains(i)));
model.addElement(new FilterTagsel($res("wguit-recipes"), i -> GlobalRecipeRegistrar.craftable.contains(i)));
model.addElement(new FilterTagsel($res("wguit-noway"), i -> !GlobalRecipeRegistrar.obtainable.contains(i)));
model.addElement(new FilterTagsel($res("wguit-way"), i -> GlobalRecipeRegistrar.obtainable.contains(i)));
model.addElement(new FilterTagsel($res("wguit-noins"), i -> !GlobalRecipeRegistrar.consumable.contains(i)));
model.addElement(new FilterTagsel($res("wguit-ins"), i -> GlobalRecipeRegistrar.consumable.contains(i)));
model.addElement(new FilterTagsel($res("wguit-nochance"), i -> !GlobalRecipeRegistrar.chanceable.contains(i)));
model.addElement(new FilterTagsel($res("wguit-chance"), i -> GlobalRecipeRegistrar.chanceable.contains(i)));
for(Entry> data : Items.tags.asMap().entrySet()) {
String s = data.getKey();
Set set = (Set) data.getValue();
model.addElement(new TaggedSel(s, set));
}
scrollPane = new JScrollPane();
creativePanel.add(scrollPane, "cell 0 2 1 2,grow");
tags = new JList<>();
scrollPane.setViewportView(tags);
tags.setModel(model);
multilineLabel = new MultilineLabel();
multilineLabel.setBackground(new Color(0, 191, 255));
multilineLabel.setOpaque(true);
creativePanel.add(multilineLabel, "cell 1 3,grow");
tags.addListSelectionListener(e -> {
Tagsel sel = tags.getSelectedValue();
Comparator cmp = selectSortItemTypes.getSelectedValue();
if(cmp == null) return;
DefaultListModel model0 = sel.eligible();
lblResults.setText(model0.getSize()+" "+$res("wgui-results"));
CreativeItemList.resort(cmp, model0);
creativeItemList.setModel(model0);
});
//Sort the tags
Collections.sort(Collects.toWritableList(model), (a, b) -> a.title().compareTo(b.title()));
//Crafting
craftingsPanel = new JPanel();
add(craftingsPanel, "cell 2 0,grow");
craftingsPanel.setLayout(new BoxLayout(craftingsPanel, BoxLayout.Y_AXIS));
//Find recipes
JLabel lblRecipes = new JLabel($res("wguicf-head"));
craftingsPanel.add(lblRecipes);
JButton btnCraftTo = new JButton($res("wguicf-prod"));
btnCraftTo.addActionListener(e -> {
ItemEntry item = findSourceItem();
if(item != null) {
queryRecipes(producing(item));
}else {
queryRecipes(all());
}
});
btnCraftTo.setBackground(Color.GREEN);
craftingsPanel.add(btnCraftTo);
JButton btnCraftRandom = new JButton($res("wguicf-chan"));
btnCraftRandom.setBackground(new Color(204, 255, 0));
btnCraftRandom.addActionListener(e -> {
ItemEntry item = findSourceItem();
if(item != null) {
queryRecipes(gambling(item));
}else {
queryRecipes(all());
}
});
craftingsPanel.add(btnCraftRandom);
JButton btnCraftFrom = new JButton($res("wguicf-cons"));
btnCraftFrom.setBackground(Color.RED);
btnCraftFrom.addActionListener(e -> {
ItemEntry item = findSourceItem();
if(item != null) {
queryRecipes(consuming(item));
}else {
queryRecipes(all());
}
});
craftingsPanel.add(btnCraftFrom);
JButton btnCraftBy = new JButton($res("wguicf-mac"));
btnCraftBy.setEnabled(false);
btnCraftBy.setBackground(Color.BLUE);
craftingsPanel.add(btnCraftBy);
JButton btnCraftWith = new JButton($res("wguicf-cat"));
btnCraftWith.setBackground(new Color(255, 255, 0));
btnCraftWith.addActionListener(e -> {
ItemEntry item = findSourceItem();
if(item != null) {
queryRecipes(catalysing(item));
}else {
queryRecipes(all());
}
});
craftingsPanel.add(btnCraftWith);
JButton btnCraftAll = new JButton("ALL recipes");
btnCraftAll.setBackground(Color.GRAY);
btnCraftAll.addActionListener(e -> queryRecipes(all()));
craftingsPanel.add(btnCraftAll);
checkUseCIL = new JCheckBox("Use the creative item list");
checkUseCIL.setSelected(true);
craftingsPanel.add(checkUseCIL);
}
private void removeItems(int amount) {
int remain = amount;
List records = craftGUI.inventoryController.getSelectedValuesList();
for(ItemRecord record: records) {
if(remain == 0) return;
remain -= record.extract(amount);
}
craftGUI.inventoryController.refresh();
}
private void addItems(int amount) {
Inventory inv = craftGUI.inventoryController.getInv();
if(inv == null) {
debug.printl("Got null inventory");
return;
}
List items = creativeItemList.getSelectedValuesList();
if(items == null) {
debug.printl("Got null item list");
return;
}
for(ItemType item: items) {
if(item == null) {
debug.printl("Got null item");
continue;
}
inv.insert(item.create(), amount);
}
craftGUI.inventoryController.refresh();
}
/**
* @return the player
*/
public Player getPlayer() {
return player;
}
/**
* @param player the player to set
*/
public void setPlayer(Player player) {
if(this.player == player) return;
this.player = player;
playerChanged.trigger(player);
craftGUI.inventoryController.setInv(player.inv);
checkSurvival.setVariable(player.creative);
}
private final Timer timer;
private JLabel lblCreativeItems;
private BoundCheckBox checkSurvival;
private JLabel lbAddRemoveCount;
private JPanel panel;
private JSpinner itemAmt;
public final CraftGUI craftGUI;
private SelectSortItemTypes selectSortItemTypes;
private JLabel lblSort;
private JPanel creativePanel;
private JPanel craftingsPanel;
private JCheckBox checkUseCIL;
private JList tags;
private JScrollPane scrollPane;
private MultilineLabel multilineLabel;
private JLabel lblResults;
/**
* @author oskar
* Describes a rule or set of rules to filter recipes
*/
public static interface RecipeQuery{
/**
* Returns a large set of eligible items
* The recipes which pass both phases 1 and 2 must be exactly the same as all recipes which pass this query's filter
* @return potentially eligible items
*/
@Nil public Set<@NN Recipe> phase1();
/**
* Narrows down the list of items to produce an exact list
* The recipes which pass both phases 1 and 2 must be exactly the same as all recipes which pass this query's filter
* @param recipe the recipe to test
* @return does recipe match?
*/
public boolean phase2(Recipe> recipe);
/** @return all eligible items*/
@NN public default Set> eligible(){
Set<@NN Recipe> recipes = phase1();
Set> model = new HashSet<>();
if(recipes != null) for(Recipe> item: recipes) {
if(phase2(item)) model.add(item);
}
return model;
}
/**
* @return the displayed query string
*/
public String name();
/**
* @param recipe the recipe to test
* @return does recipe match?
*/public boolean filter(Recipe> recipe);
}
private void queryRecipes(RecipeQuery query) {
debug.printl("Querying recipes");
window.openAndShowWindow(new QueriedRecipes(query, window), "Recipe search: "+query.name());
debug.printl("Query finished");
}
/**
* @return a recipe query, which accepts all recipes
*/
@NN public static RecipeQuery all() {
return new RecipeQuery() {
@Override
public String name() {
return "All recipes";
}
@Override
public boolean filter(Recipe> recipe) {
return true;
}
@Override
public @Nil Set<@NN Recipe> phase1() {
return GlobalRecipeRegistrar.recipes;
}
@Override
public boolean phase2(Recipe> recipe) {
return true;
}
};
}
/**
* @param item
* @return a recipe query, which accepts recipes
*/
@NN public static RecipeQuery consuming(ItemEntry item) {
return new RecipeQuery() {
@Override
public String name() {
return "Recipes which consume: "+item.title();
}
@Override
public boolean filter(Recipe> recipe) {
return recipe.inputs().contains(item);
}
@Override
public @Nil Set<@NN Recipe> phase1() {
return GlobalRecipeRegistrar.inputs.multimap().get(item);
}
@Override
public boolean phase2(Recipe> recipe) {
return true;
}
};
}
@NN public static RecipeQuery producing(ItemEntry item) {
return new RecipeQuery() {
@Override
public String name() {
return "Recipes which produce: "+item.title();
}
@Override
public boolean filter(Recipe> recipe) {
return recipe.output().contains(item);
}
@Override
public @Nil Set<@NN Recipe> phase1() {
return GlobalRecipeRegistrar.output.multimap().get(item);
}
@Override
public boolean phase2(Recipe> recipe) {
return true;
}
};
}
@NN public static RecipeQuery gambling(ItemEntry item) {
return new RecipeQuery() {
@Override
public String name() {
return "Recipes which may produce: "+item.title();
}
@Override
public boolean filter(Recipe> recipe) {
return recipe.luck().contains(item);
}
@Override
public @Nil Set<@NN Recipe> phase1() {
return GlobalRecipeRegistrar.chance.multimap().get(item);
}
@Override
public boolean phase2(Recipe> recipe) {
return true;
}
};
}
@NN public static RecipeQuery catalysing(ItemEntry item) {
return new RecipeQuery() {
@Override
public String name() {
return "Recipes which catalyze: "+item.title();
}
@Override
public boolean filter(Recipe> recipe) {
return Objects.equals(item, recipe.catalyst());
}
@Override
public Set<@NN Recipe> phase1() {
return GlobalRecipeRegistrar.catalyst.multimap().get(item);
}
@Override
public boolean phase2(Recipe> recipe) {
return true;
}
};
}
@NN public static RecipeQuery byVolt(VoltageTier item) {
return new RecipeQuery() {
@Override
public String name() {
return "Recipes at: "+item.name;
}
@Override
public boolean filter(Recipe> recipe) {
return recipe.voltTier() == item;
}
@Override
public @Nil Set<@NN Recipe> phase1() {
return GlobalRecipeRegistrar.volt.multimap().get(item);
}
@Override
public boolean phase2(Recipe> recipe) {
return true;
}
};
}
@NN public static RecipeQuery alone(Set<@NN Recipe> recipes) {
return new RecipeQuery() {
@Override
public String name() {
return "Selected recipe";
}
@Override
public boolean filter(Recipe> recipe) {
return true;
}
@Override
public @Nil Set<@NN Recipe> phase1() {
return recipes;
}
@Override
public boolean phase2(Recipe> recipe) {
return true;
}
};
}
private ItemEntry findSourceItem() {
ItemRecord irecord = craftGUI.inventoryController.getSelectedValue();
if(irecord != null) return irecord.item();
ItemType type = creativeItemList.getSelectedValue();
if(type == null) return null;
return type.create();
}
public void dispose() {
timer.stop();
}
}