diff options
author | Jakub <53441451+kuba6000@users.noreply.github.com> | 2023-09-05 08:27:22 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-09-05 08:27:22 +0200 |
commit | 74e1d0964ec002482253384c97fe76de54dc7de1 (patch) | |
tree | 281d159099ec7d2c315a54f89bae6eeb3d5b1873 /src/main/java/kubatech | |
parent | d1f7d54620be77d4e9c413978a6c9497401fc9c2 (diff) | |
download | GT5-Unofficial-74e1d0964ec002482253384c97fe76de54dc7de1.tar.gz GT5-Unofficial-74e1d0964ec002482253384c97fe76de54dc7de1.tar.bz2 GT5-Unofficial-74e1d0964ec002482253384c97fe76de54dc7de1.zip |
Merge identical slots in EIG + MApiary GUI (#93)
* Merge identical slots in EIG GUI
* Mega Apiary
* Update MobHandlerLoader.java
* Update GTHelper.java
* Update GT_MetaTileEntity_ExtremeIndustrialGreenhouse.java
* Update GT_MetaTileEntity_MegaIndustrialApiary.java
* Update build.gradle
* crop
* 99+
Diffstat (limited to 'src/main/java/kubatech')
4 files changed, 448 insertions, 216 deletions
diff --git a/src/main/java/kubatech/api/helpers/GTHelper.java b/src/main/java/kubatech/api/helpers/GTHelper.java index 201f8b45b7..e368c7b778 100644 --- a/src/main/java/kubatech/api/helpers/GTHelper.java +++ b/src/main/java/kubatech/api/helpers/GTHelper.java @@ -23,6 +23,14 @@ package kubatech.api.helpers; import static gregtech.api.metatileentity.implementations.GT_MetaTileEntity_MultiBlockBase.isValidMetaTileEntity; import static kubatech.api.Variables.ln4; +import java.io.IOException; +import java.util.ArrayList; + +import net.minecraft.item.ItemStack; +import net.minecraft.network.PacketBuffer; + +import com.kuba6000.mobsinfo.api.utils.ItemID; + import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Energy; import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_MultiBlockBase; import kubatech.api.implementations.KubaTechGTMultiBlockBase; @@ -52,4 +60,41 @@ public class GTHelper { public static int getVoltageTier(GT_MetaTileEntity_MultiBlockBase mte) { return (int) getVoltageTierD(mte); } + + public static class StackableItemSlot { + + public StackableItemSlot(int count, ItemStack stack, ArrayList<Integer> realSlots) { + this.count = count; + this.stack = stack; + this.realSlots = realSlots; + } + + public final int count; + public final ItemStack stack; + public final ArrayList<Integer> realSlots; + + public void write(PacketBuffer buffer) throws IOException { + buffer.writeVarIntToBuffer(count); + buffer.writeItemStackToBuffer(stack); + } + + public static StackableItemSlot read(PacketBuffer buffer) throws IOException { + return new StackableItemSlot( + buffer.readVarIntFromBuffer(), + buffer.readItemStackFromBuffer(), + new ArrayList<>()); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (!(obj instanceof StackableItemSlot)) return false; + StackableItemSlot other = (StackableItemSlot) obj; + return count == other.count && ItemID.createNoCopy(stack, false) + .hashCode() + == ItemID.createNoCopy(other.stack, false) + .hashCode() + && realSlots.equals(other.realSlots); + } + } } diff --git a/src/main/java/kubatech/loaders/MobHandlerLoader.java b/src/main/java/kubatech/loaders/MobHandlerLoader.java index 7089aa6f6e..35d92de13d 100644 --- a/src/main/java/kubatech/loaders/MobHandlerLoader.java +++ b/src/main/java/kubatech/loaders/MobHandlerLoader.java @@ -221,16 +221,10 @@ public class MobHandlerLoader { @SubscribeEvent public void onPostMobRegistration(PostMobRegistrationEvent event) { if (!event.drops.isEmpty() && event.recipe.isUsableInVial) { + @SuppressWarnings("unchecked") ArrayList<MobDrop> drops = (ArrayList<MobDrop>) event.drops.clone(); - // drops.removeIf(d -> d.chance == 0); if (!drops.isEmpty()) { recipeMap.put(event.currentMob, new MobEECRecipe(drops, event.recipe)); - /* - * event.drops.stream() - * .filter(d -> d.chance == 0) - * .forEach( - * d -> d.additionalInfo.add(StatCollector.translateToLocal("kubatech.mobhandler.eec_disabled"))); - */ } } } diff --git a/src/main/java/kubatech/tileentity/gregtech/multiblock/GT_MetaTileEntity_ExtremeIndustrialGreenhouse.java b/src/main/java/kubatech/tileentity/gregtech/multiblock/GT_MetaTileEntity_ExtremeIndustrialGreenhouse.java index 71ed169c1c..2e916e29e0 100644 --- a/src/main/java/kubatech/tileentity/gregtech/multiblock/GT_MetaTileEntity_ExtremeIndustrialGreenhouse.java +++ b/src/main/java/kubatech/tileentity/gregtech/multiblock/GT_MetaTileEntity_ExtremeIndustrialGreenhouse.java @@ -46,7 +46,6 @@ import java.util.Map; import java.util.Objects; import java.util.Random; import java.util.concurrent.atomic.AtomicInteger; -import java.util.stream.Collectors; import net.minecraft.block.Block; import net.minecraft.block.BlockFlower; @@ -91,7 +90,6 @@ import com.gtnewhorizons.modularui.api.math.Pos2d; import com.gtnewhorizons.modularui.api.screen.ModularUIContext; import com.gtnewhorizons.modularui.api.screen.ModularWindow; import com.gtnewhorizons.modularui.api.screen.UIBuildContext; -import com.gtnewhorizons.modularui.api.widget.IWidgetParent; import com.gtnewhorizons.modularui.api.widget.Widget; import com.gtnewhorizons.modularui.common.builder.UIInfo; import com.gtnewhorizons.modularui.common.internal.wrapper.ModularUIContainer; @@ -107,6 +105,7 @@ import com.gtnewhorizons.modularui.common.widget.FakeSyncWidget; import com.gtnewhorizons.modularui.common.widget.Scrollable; import com.gtnewhorizons.modularui.common.widget.SlotWidget; import com.gtnewhorizons.modularui.common.widget.TextWidget; +import com.kuba6000.mobsinfo.api.utils.ItemID; import cpw.mods.fml.common.registry.GameRegistry; import cpw.mods.fml.relauncher.Side; @@ -138,7 +137,9 @@ import ic2.core.Ic2Items; import ic2.core.crop.TileEntityCrop; import kubatech.Tags; import kubatech.api.LoaderReference; +import kubatech.api.helpers.GTHelper; import kubatech.api.implementations.KubaTechGTMultiBlockBase; +import kubatech.api.utils.ModUtils; import kubatech.client.effect.CropRenderer; @SuppressWarnings("unused") @@ -625,7 +626,8 @@ public class GT_MetaTileEntity_ExtremeIndustrialGreenhouse return super.transferStackInSlot(aPlayer, aSlotIndex); } if (mte.addCrop(aStack)) { - s.putStack(null); + if (aStack.stackSize == 0) s.putStack(null); + else s.putStack(aStack); detectAndSendChanges(); return null; } @@ -633,7 +635,8 @@ public class GT_MetaTileEntity_ExtremeIndustrialGreenhouse } } - final List<ItemStack> drawables = new ArrayList<>(mMaxSlots); + List<GTHelper.StackableItemSlot> drawables = new ArrayList<>(); + private int usedSlots = 0; // mStorage.size() @SuppressWarnings("UnstableApiUsage") @Override @@ -681,6 +684,7 @@ public class GT_MetaTileEntity_ExtremeIndustrialGreenhouse ChangeableWidget cropsContainer = new ChangeableWidget(() -> createCropsContainerWidget(player)); AtomicInteger lastMaxSlots = new AtomicInteger(); + AtomicInteger lastUsedSlots = new AtomicInteger(); builder.widget(cropsContainer.attachSyncer(new FakeSyncWidget.IntegerSyncer(() -> { if (lastMaxSlots.get() != mMaxSlots) { lastMaxSlots.set(mMaxSlots); @@ -693,36 +697,60 @@ public class GT_MetaTileEntity_ExtremeIndustrialGreenhouse cropsContainer.notifyChangeNoSync(); } }), builder) - .attachSyncer( - new FakeSyncWidget.ListSyncer<>( - () -> mStorage.stream() - .map(s -> s.input) - .collect(Collectors.toList()), - l -> { - drawables.clear(); - drawables.addAll(l); - if (cropsContainer.getChildren() - .size() > 0) - IWidgetParent.forEachByLayer( - (IWidgetParent) cropsContainer.getChildren() - .get(0), - Widget::notifyTooltipChange); - }, - (buffer, i) -> { - try { - buffer.writeItemStackToBuffer(i); - } catch (IOException e) { - throw new RuntimeException(e); - } - }, - buffer -> { - try { - return buffer.readItemStackFromBuffer(); - } catch (IOException e) { - throw new RuntimeException(e); - } - }), - builder)); + .attachSyncer(new FakeSyncWidget.IntegerSyncer(() -> { + if (lastUsedSlots.get() != mStorage.size()) { + lastUsedSlots.set(mStorage.size()); + cropsContainer.notifyChangeNoSync(); + } + return mStorage.size(); + }, i -> { + if (usedSlots != i) { + usedSlots = i; + cropsContainer.notifyChangeNoSync(); + } + }), builder) + .attachSyncer(new FakeSyncWidget.ListSyncer<>(() -> { + HashMap<ItemID, Integer> itemMap = new HashMap<>(); + HashMap<ItemID, ItemStack> stackMap = new HashMap<>(); + HashMap<ItemID, ArrayList<Integer>> realSlotMap = new HashMap<>(); + for (int i = 0, mStorageSize = mStorage.size(); i < mStorageSize; i++) { + GreenHouseSlot slot = mStorage.get(i); + ItemID id = ItemID.createNoCopy(slot.input, false); + itemMap.merge(id, 1, Integer::sum); + stackMap.putIfAbsent(id, slot.input); + realSlotMap.computeIfAbsent(id, unused -> new ArrayList<>()) + .add(i); + } + List<GTHelper.StackableItemSlot> newDrawables = new ArrayList<>(); + for (Map.Entry<ItemID, Integer> entry : itemMap.entrySet()) { + newDrawables.add( + new GTHelper.StackableItemSlot( + entry.getValue(), + stackMap.get(entry.getKey()), + realSlotMap.get(entry.getKey()))); + } + if (!Objects.equals(newDrawables, drawables)) { + drawables = newDrawables; + cropsContainer.notifyChangeNoSync(); + } + return drawables; + }, l -> { + drawables.clear(); + drawables.addAll(l); + cropsContainer.notifyChangeNoSync(); + }, (buffer, i) -> { + try { + i.write(buffer); + } catch (IOException e) { + throw new RuntimeException(e); + } + }, buffer -> { + try { + return GTHelper.StackableItemSlot.read(buffer); + } catch (IOException e) { + throw new RuntimeException(e); + } + }), builder)); final DynamicPositionedColumn screenElements = new DynamicPositionedColumn(); drawTexts(screenElements, null); @@ -731,85 +759,152 @@ public class GT_MetaTileEntity_ExtremeIndustrialGreenhouse protected Widget createCropsContainerWidget(EntityPlayer player) { Scrollable cropsContainer = new Scrollable().setVerticalScroll(); - final int perRow = 7; - if (mMaxSlots > 0) for (int i = 0, imax = ((mMaxSlots - 1) / perRow); i <= imax; i++) { - DynamicPositionedRow row = new DynamicPositionedRow().setSynced(false); - for (int j = 0, jmax = (i == imax ? (mMaxSlots - 1) % perRow : (perRow - 1)); j <= jmax; j++) { - final int finalI = i * perRow; - final int finalJ = j; - final int ID = finalI + finalJ; - row.widget(new ButtonWidget().setOnClick((clickData, widget) -> { - if (!(player instanceof EntityPlayerMP)) return; - if (!clickData.shift) { - ItemStack input = player.inventory.getItemStack(); - if (input != null) { - if (this.mMaxProgresstime > 0) { - GT_Utility.sendChatToPlayer( - player, - EnumChatFormatting.RED + "Can't replace/insert while running !"); - return; - } - if (addCrop(input, -1, true)) { - if (mStorage.size() > ID) { - GreenHouseSlot removed = mStorage.remove(ID); - addCrop(input, ID, false); - player.inventory.setItemStack(removed.input); - - } else { - addCrop(input); - player.inventory.setItemStack(null); - } - ((EntityPlayerMP) player).isChangingQuantityOnly = false; - ((EntityPlayerMP) player).updateHeldItem(); - } - return; - } - } - if (mStorage.size() <= ID) return; - if (this.mMaxProgresstime > 0) { - GT_Utility.sendChatToPlayer(player, EnumChatFormatting.RED + "Can't eject while running !"); - return; - } - GreenHouseSlot removed = mStorage.remove(ID); - if (clickData.shift) { - if (player.inventory.addItemStackToInventory(removed.input)) { - player.inventoryContainer.detectAndSendChanges(); + ArrayList<Widget> buttons = new ArrayList<>(); + + if (!ModUtils.isClientThreaded()) { + HashMap<ItemID, Integer> itemMap = new HashMap<>(); + HashMap<ItemID, ItemStack> stackMap = new HashMap<>(); + HashMap<ItemID, ArrayList<Integer>> realSlotMap = new HashMap<>(); + for (int i = 0, mStorageSize = mStorage.size(); i < mStorageSize; i++) { + GreenHouseSlot slot = mStorage.get(i); + ItemID id = ItemID.createNoCopy(slot.input, false); + itemMap.merge(id, 1, Integer::sum); + stackMap.putIfAbsent(id, slot.input); + realSlotMap.computeIfAbsent(id, unused -> new ArrayList<>()) + .add(i); + } + drawables = new ArrayList<>(); + for (Map.Entry<ItemID, Integer> entry : itemMap.entrySet()) { + drawables.add( + new GTHelper.StackableItemSlot( + entry.getValue(), + stackMap.get(entry.getKey()), + realSlotMap.get(entry.getKey()))); + } + } + + for (int ID = 0; ID < drawables.size(); ID++) { + final int finalID = ID; + buttons.add(new ButtonWidget().setOnClick((clickData, widget) -> { + if (!(player instanceof EntityPlayerMP)) return; + if (!clickData.shift) { + ItemStack input = player.inventory.getItemStack(); + if (input != null) { + if (this.mMaxProgresstime > 0) { + GT_Utility + .sendChatToPlayer(player, EnumChatFormatting.RED + "Can't replace while running !"); return; } - } - if (clickData.mouseButton == 1) { - if (player.inventory.getItemStack() == null) { - player.inventory.setItemStack(removed.input); + if (addCrop(input, -1, true)) { + if (drawables.size() > finalID) { + int realID = drawables.get(finalID).realSlots.get(0); + GreenHouseSlot removed = mStorage.remove(realID); + addCrop(input, realID, false); + player.inventory.setItemStack(removed.input); + // force widget update?? + } else { + if (input.stackSize == 0) addCrop(input); + player.inventory.setItemStack(null); + } ((EntityPlayerMP) player).isChangingQuantityOnly = false; ((EntityPlayerMP) player).updateHeldItem(); - return; } + return; } - - addOutput(removed.input); - GT_Utility.sendChatToPlayer(player, "Crop ejected !"); - }) - .setBackground( - () -> new IDrawable[] { getBaseMetaTileEntity().getGUITextureSet() - .getItemSlot(), - new ItemDrawable(drawables.size() > ID ? drawables.get(ID) : null) - .withFixedSize(16, 16, 1, 1), - new Text(drawables.size() > ID ? String.valueOf(drawables.get(ID).stackSize) : "") + } + if (drawables.size() <= finalID) return; + if (this.mMaxProgresstime > 0) { + GT_Utility.sendChatToPlayer(player, EnumChatFormatting.RED + "Can't eject while running !"); + return; + } + int realID = drawables.get(finalID).realSlots.get(0); + GreenHouseSlot removed = mStorage.remove(realID); + if (clickData.shift) { + if (player.inventory.addItemStackToInventory(removed.input)) { + player.inventoryContainer.detectAndSendChanges(); + return; + } + } + if (clickData.mouseButton == 1) { + if (player.inventory.getItemStack() == null) { + player.inventory.setItemStack(removed.input); + ((EntityPlayerMP) player).isChangingQuantityOnly = false; + ((EntityPlayerMP) player).updateHeldItem(); + return; + } + } + addOutput(removed.input); + GT_Utility.sendChatToPlayer(player, "Crop ejected !"); + }) + .setBackground( + () -> new IDrawable[] { getBaseMetaTileEntity().getGUITextureSet() + .getItemSlot(), + new ItemDrawable(drawables.size() > finalID ? drawables.get(finalID).stack : null) + .withFixedSize(16, 16, 1, 1), + new Text( + drawables.size() > finalID ? (drawables.get(finalID).count > 99 ? "+99" + : String.valueOf(drawables.get(finalID).count)) : "").color(Color.PURPLE.normal) + .alignment(Alignment.TopRight), + new Text( + drawables.size() > finalID ? String.valueOf(drawables.get(finalID).stack.stackSize) : "") .color(Color.WHITE.normal) .shadow() .alignment(Alignment.BottomRight) }) - .dynamicTooltip(() -> { - if (drawables.size() > ID) return Arrays.asList( - drawables.get(ID) - .getDisplayName(), - EnumChatFormatting.GRAY + "Left click to eject into input bus", - EnumChatFormatting.GRAY + "Right click to get into mouse", - EnumChatFormatting.GRAY + "Shift click to get into inventory", - EnumChatFormatting.GRAY + "Click with other crop in mouse to replace"); - return Collections.emptyList(); - }) - .setSize(18, 18)); + .dynamicTooltip(() -> { + if (drawables.size() > finalID) return Arrays.asList( + "x" + drawables.get(finalID).stack.stackSize + + " " + + drawables.get(finalID).stack.getDisplayName(), + EnumChatFormatting.DARK_PURPLE + "There are " + + drawables.get(finalID).count + + " identical slots", + EnumChatFormatting.GRAY + "Left click to eject into input bus", + EnumChatFormatting.GRAY + "Right click to get into mouse", + EnumChatFormatting.GRAY + "Shift click to get into inventory", + EnumChatFormatting.GRAY + "Click with other crop in mouse to replace"); + return Collections.emptyList(); + }) + .setSize(18, 18)); + } + + buttons.add(new ButtonWidget().setOnClick((clickData, widget) -> { + if (!(player instanceof EntityPlayerMP)) return; + ItemStack input = player.inventory.getItemStack(); + if (input != null) { + if (this.mMaxProgresstime > 0) { + GT_Utility.sendChatToPlayer(player, EnumChatFormatting.RED + "Can't insert while running !"); + return; + } + if (addCrop(input)) { + if (input.stackSize == 0) player.inventory.setItemStack(null); + ((EntityPlayerMP) player).isChangingQuantityOnly = false; + ((EntityPlayerMP) player).updateHeldItem(); + } + } + }) + .setBackground( + () -> new IDrawable[] { getBaseMetaTileEntity().getGUITextureSet() + .getItemSlot(), + new Text(String.valueOf((mMaxSlots - usedSlots) > 99 ? "+99" : (mMaxSlots - usedSlots))) + .color(Color.PURPLE.normal) + .alignment(Alignment.TopRight) }) + .dynamicTooltip( + () -> Arrays.asList( + EnumChatFormatting.GRAY + "Empty slot", + EnumChatFormatting.DARK_PURPLE + "There are " + (mMaxSlots - usedSlots) + " identical slots", + EnumChatFormatting.GRAY + "Click with crop in mouse to insert", + EnumChatFormatting.GRAY + "Shift click a crop in your inventory to insert")) + .setSize(18, 18)); + + final int perRow = 7; + for (int i = 0, imax = ((buttons.size() - 1) / perRow); i <= imax; i++) { + DynamicPositionedRow row = new DynamicPositionedRow().setSynced(false); + for (int j = 0, jmax = (i == imax ? (buttons.size() - 1) % perRow : (perRow - 1)); j <= jmax; j++) { + final int finalI = i * perRow; + final int finalJ = j; + final int ID = finalI + finalJ; + row.widget(buttons.get(ID)); } cropsContainer.widget(row.setPos(0, i * 18)); } diff --git a/src/main/java/kubatech/tileentity/gregtech/multiblock/GT_MetaTileEntity_MegaIndustrialApiary.java b/src/main/java/kubatech/tileentity/gregtech/multiblock/GT_MetaTileEntity_MegaIndustrialApiary.java index 9d5dc463e7..df12c901b8 100644 --- a/src/main/java/kubatech/tileentity/gregtech/multiblock/GT_MetaTileEntity_MegaIndustrialApiary.java +++ b/src/main/java/kubatech/tileentity/gregtech/multiblock/GT_MetaTileEntity_MegaIndustrialApiary.java @@ -49,6 +49,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Collectors; @@ -79,12 +80,12 @@ import com.gtnewhorizons.modularui.api.ModularUITextures; import com.gtnewhorizons.modularui.api.drawable.IDrawable; import com.gtnewhorizons.modularui.api.drawable.ItemDrawable; import com.gtnewhorizons.modularui.api.drawable.Text; +import com.gtnewhorizons.modularui.api.math.Alignment; import com.gtnewhorizons.modularui.api.math.Color; import com.gtnewhorizons.modularui.api.math.Pos2d; import com.gtnewhorizons.modularui.api.screen.ModularUIContext; import com.gtnewhorizons.modularui.api.screen.ModularWindow; import com.gtnewhorizons.modularui.api.screen.UIBuildContext; -import com.gtnewhorizons.modularui.api.widget.IWidgetParent; import com.gtnewhorizons.modularui.api.widget.Widget; import com.gtnewhorizons.modularui.common.builder.UIInfo; import com.gtnewhorizons.modularui.common.internal.wrapper.ModularUIContainer; @@ -100,6 +101,7 @@ import com.gtnewhorizons.modularui.common.widget.FakeSyncWidget; import com.gtnewhorizons.modularui.common.widget.Scrollable; import com.gtnewhorizons.modularui.common.widget.SlotWidget; import com.gtnewhorizons.modularui.common.widget.TextWidget; +import com.kuba6000.mobsinfo.api.utils.ItemID; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; @@ -129,7 +131,9 @@ import gregtech.api.util.GT_Multiblock_Tooltip_Builder; import gregtech.api.util.GT_Utility; import kubatech.Tags; import kubatech.api.LoaderReference; +import kubatech.api.helpers.GTHelper; import kubatech.api.implementations.KubaTechGTMultiBlockBase; +import kubatech.api.utils.ModUtils; import kubatech.client.effect.MegaApiaryBeesRenderer; public class GT_MetaTileEntity_MegaIndustrialApiary @@ -717,7 +721,8 @@ public class GT_MetaTileEntity_MegaIndustrialApiary } } - private final List<ItemStack> drawables = new ArrayList<>(mMaxSlots); + private List<GTHelper.StackableItemSlot> drawables = new ArrayList<>(); + private int usedSlots = 0; // mStorage.size() @SuppressWarnings("UnstableApiUsage") @Override @@ -765,6 +770,7 @@ public class GT_MetaTileEntity_MegaIndustrialApiary ChangeableWidget beesContainer = new ChangeableWidget(() -> createBeesContainerWidget(player)); AtomicInteger lastMaxSlots = new AtomicInteger(); + AtomicInteger lastUsedSlots = new AtomicInteger(); builder.widget(beesContainer.attachSyncer(new FakeSyncWidget.IntegerSyncer(() -> { if (lastMaxSlots.get() != mMaxSlots) { lastMaxSlots.set(mMaxSlots); @@ -777,36 +783,60 @@ public class GT_MetaTileEntity_MegaIndustrialApiary beesContainer.notifyChangeNoSync(); } }), builder) - .attachSyncer( - new FakeSyncWidget.ListSyncer<>( - () -> mStorage.stream() - .map(s -> s.queenStack) - .collect(Collectors.toList()), - l -> { - drawables.clear(); - drawables.addAll(l); - if (beesContainer.getChildren() - .size() > 0) - IWidgetParent.forEachByLayer( - (IWidgetParent) beesContainer.getChildren() - .get(0), - Widget::notifyTooltipChange); - }, - (buffer, i) -> { - try { - buffer.writeItemStackToBuffer(i); - } catch (IOException e) { - throw new RuntimeException(e); - } - }, - buffer -> { - try { - return buffer.readItemStackFromBuffer(); - } catch (IOException e) { - throw new RuntimeException(e); - } - }), - builder) + .attachSyncer(new FakeSyncWidget.IntegerSyncer(() -> { + if (lastUsedSlots.get() != mStorage.size()) { + lastUsedSlots.set(mStorage.size()); + beesContainer.notifyChangeNoSync(); + } + return mStorage.size(); + }, i -> { + if (usedSlots != i) { + usedSlots = i; + beesContainer.notifyChangeNoSync(); + } + }), builder) + .attachSyncer(new FakeSyncWidget.ListSyncer<>(() -> { + HashMap<ItemID, Integer> itemMap = new HashMap<>(); + HashMap<ItemID, ItemStack> stackMap = new HashMap<>(); + HashMap<ItemID, ArrayList<Integer>> realSlotMap = new HashMap<>(); + for (int i = 0, mStorageSize = mStorage.size(); i < mStorageSize; i++) { + BeeSimulator slot = mStorage.get(i); + ItemID id = ItemID.createNoCopy(slot.queenStack, false); + itemMap.merge(id, 1, Integer::sum); + stackMap.putIfAbsent(id, slot.queenStack); + realSlotMap.computeIfAbsent(id, unused -> new ArrayList<>()) + .add(i); + } + List<GTHelper.StackableItemSlot> newDrawables = new ArrayList<>(); + for (Map.Entry<ItemID, Integer> entry : itemMap.entrySet()) { + newDrawables.add( + new GTHelper.StackableItemSlot( + entry.getValue(), + stackMap.get(entry.getKey()), + realSlotMap.get(entry.getKey()))); + } + if (!Objects.equals(newDrawables, drawables)) { + drawables = newDrawables; + beesContainer.notifyChangeNoSync(); + } + return drawables; + }, l -> { + drawables.clear(); + drawables.addAll(l); + beesContainer.notifyChangeNoSync(); + }, (buffer, i) -> { + try { + i.write(buffer); + } catch (IOException e) { + throw new RuntimeException(e); + } + }, buffer -> { + try { + return GTHelper.StackableItemSlot.read(buffer); + } catch (IOException e) { + throw new RuntimeException(e); + } + }), builder) .attachSyncer(new FakeSyncWidget.ListSyncer<>(() -> { if (flowersError) { List<String> s = flowersCheck.stream() @@ -838,90 +868,158 @@ public class GT_MetaTileEntity_MegaIndustrialApiary private Widget createBeesContainerWidget(EntityPlayer player) { Scrollable beesContainer = new Scrollable().setVerticalScroll(); - final int perRow = 7; - if (mMaxSlots > 0) for (int i = 0, imax = ((mMaxSlots - 1) / perRow); i <= imax; i++) { - DynamicPositionedRow row = new DynamicPositionedRow().setSynced(false); - for (int j = 0, jmax = (i == imax ? (mMaxSlots - 1) % perRow : (perRow - 1)); j <= jmax; j++) { - final int finalI = i * perRow; - final int finalJ = j; - final int ID = finalI + finalJ; - row.widget(new ButtonWidget().setOnClick((clickData, widget) -> { - if (!(player instanceof EntityPlayerMP)) return; - if (!clickData.shift) { - ItemStack input = player.inventory.getItemStack(); - if (input != null) { - if (this.mMaxProgresstime > 0) { - GT_Utility.sendChatToPlayer( - player, - EnumChatFormatting.RED + "Can't replace/insert while running !"); - return; - } - if (beeRoot.getType(input) == EnumBeeType.QUEEN) { - World w = getBaseMetaTileEntity().getWorld(); - float t = (float) getVoltageTierExact(); - BeeSimulator bs = new BeeSimulator(input, w, t); - if (bs.isValid) { - if (mStorage.size() > ID) { - BeeSimulator removed = mStorage.remove(ID); - mStorage.add(ID, bs); - player.inventory.setItemStack(removed.queenStack); - - } else { - mStorage.add(bs); - player.inventory.setItemStack(null); - } - ((EntityPlayerMP) player).isChangingQuantityOnly = false; - ((EntityPlayerMP) player).updateHeldItem(); - - isCacheDirty = true; + + ArrayList<Widget> buttons = new ArrayList<>(); + + if (!ModUtils.isClientThreaded()) { + HashMap<ItemID, Integer> itemMap = new HashMap<>(); + HashMap<ItemID, ItemStack> stackMap = new HashMap<>(); + HashMap<ItemID, ArrayList<Integer>> realSlotMap = new HashMap<>(); + for (int i = 0, mStorageSize = mStorage.size(); i < mStorageSize; i++) { + BeeSimulator slot = mStorage.get(i); + ItemID id = ItemID.createNoCopy(slot.queenStack, false); + itemMap.merge(id, 1, Integer::sum); + stackMap.putIfAbsent(id, slot.queenStack); + realSlotMap.computeIfAbsent(id, unused -> new ArrayList<>()) + .add(i); + } + drawables = new ArrayList<>(); + for (Map.Entry<ItemID, Integer> entry : itemMap.entrySet()) { + drawables.add( + new GTHelper.StackableItemSlot( + entry.getValue(), + stackMap.get(entry.getKey()), + realSlotMap.get(entry.getKey()))); + } + } + + for (int ID = 0; ID < drawables.size(); ID++) { + final int finalID = ID; + buttons.add(new ButtonWidget().setOnClick((clickData, widget) -> { + if (!(player instanceof EntityPlayerMP)) return; + if (!clickData.shift) { + ItemStack input = player.inventory.getItemStack(); + if (input != null) { + if (this.mMaxProgresstime > 0) { + GT_Utility + .sendChatToPlayer(player, EnumChatFormatting.RED + "Can't replace while running !"); + return; + } + if (beeRoot.getType(input) == EnumBeeType.QUEEN) { + World w = getBaseMetaTileEntity().getWorld(); + float t = (float) getVoltageTierExact(); + BeeSimulator bs = new BeeSimulator(input, w, t); + if (bs.isValid) { + if (mStorage.size() > finalID) { + int realID = drawables.get(finalID).realSlots.get(0); + BeeSimulator removed = mStorage.remove(realID); + mStorage.add(realID, bs); + player.inventory.setItemStack(removed.queenStack); + } else { + mStorage.add(bs); + player.inventory.setItemStack(null); } + ((EntityPlayerMP) player).isChangingQuantityOnly = false; + ((EntityPlayerMP) player).updateHeldItem(); + + isCacheDirty = true; } - return; } + return; } + } - if (mStorage.size() <= ID) return; - if (this.mMaxProgresstime > 0) { - GT_Utility.sendChatToPlayer(player, EnumChatFormatting.RED + "Can't eject while running !"); + if (mStorage.size() <= finalID) return; + if (this.mMaxProgresstime > 0) { + GT_Utility.sendChatToPlayer(player, EnumChatFormatting.RED + "Can't eject while running !"); + return; + } + int realID = drawables.get(finalID).realSlots.get(0); + BeeSimulator removed = mStorage.remove(realID); + isCacheDirty = true; + if (clickData.shift) { + if (player.inventory.addItemStackToInventory(removed.queenStack)) { + player.inventoryContainer.detectAndSendChanges(); return; } - BeeSimulator removed = mStorage.remove(ID); - isCacheDirty = true; - if (clickData.shift) { - if (player.inventory.addItemStackToInventory(removed.queenStack)) { - player.inventoryContainer.detectAndSendChanges(); - return; - } - } - if (clickData.mouseButton == 1) { - if (player.inventory.getItemStack() == null) { - player.inventory.setItemStack(removed.queenStack); - ((EntityPlayerMP) player).isChangingQuantityOnly = false; - ((EntityPlayerMP) player).updateHeldItem(); - return; - } + } + if (clickData.mouseButton == 1) { + if (player.inventory.getItemStack() == null) { + player.inventory.setItemStack(removed.queenStack); + ((EntityPlayerMP) player).isChangingQuantityOnly = false; + ((EntityPlayerMP) player).updateHeldItem(); + return; } + } - addOutput(removed.queenStack); - GT_Utility.sendChatToPlayer(player, "Queen ejected !"); + addOutput(removed.queenStack); + GT_Utility.sendChatToPlayer(player, "Queen ejected !"); + }) + .setBackground( + () -> new IDrawable[] { getBaseMetaTileEntity().getGUITextureSet() + .getItemSlot(), + new ItemDrawable(drawables.size() > finalID ? drawables.get(finalID).stack : null) + .withFixedSize(16, 16, 1, 1), + new Text( + drawables.size() > finalID ? (drawables.get(finalID).count > 99 ? "+99" + : String.valueOf(drawables.get(finalID).count)) : "").color(Color.PURPLE.normal) + .alignment(Alignment.TopRight) }) + .dynamicTooltip(() -> { + if (drawables.size() > finalID) return Arrays.asList( + drawables.get(finalID).stack.getDisplayName(), + EnumChatFormatting.DARK_PURPLE + "There are " + + drawables.get(finalID).count + + " identical slots", + EnumChatFormatting.GRAY + "Left click to eject into input bus", + EnumChatFormatting.GRAY + "Right click to get into mouse", + EnumChatFormatting.GRAY + "Shift click to get into inventory", + EnumChatFormatting.GRAY + "Click with other queen in mouse to replace"); + return Collections.emptyList(); }) - .setBackground( - () -> new IDrawable[] { getBaseMetaTileEntity().getGUITextureSet() - .getItemSlot(), GT_UITextures.OVERLAY_SLOT_BEE_QUEEN, - new ItemDrawable(drawables.size() > ID ? drawables.get(ID) : null) - .withFixedSize(16, 16, 1, 1) }) - .dynamicTooltip(() -> { - if (drawables.size() > ID) return Arrays.asList( - drawables.get(ID) - .getDisplayName(), - EnumChatFormatting.GRAY + "Left click to eject into input bus", - EnumChatFormatting.GRAY + "Right click to get into mouse", - EnumChatFormatting.GRAY + "Shift click to get into inventory", - EnumChatFormatting.GRAY + "Click with other queen in mouse to replace"); - return Collections - .singletonList(EnumChatFormatting.GRAY + "Click with queen in mouse to insert"); - }) - .setSize(18, 18)); + .setSize(18, 18)); + } + + buttons.add(new ButtonWidget().setOnClick((clickData, widget) -> { + if (!(player instanceof EntityPlayerMP)) return; + ItemStack input = player.inventory.getItemStack(); + if (input != null) { + if (this.mMaxProgresstime > 0) { + GT_Utility.sendChatToPlayer(player, EnumChatFormatting.RED + "Can't insert while running !"); + return; + } + World w = getBaseMetaTileEntity().getWorld(); + float t = (float) getVoltageTierExact(); + BeeSimulator bs = new BeeSimulator(input, w, t); + if (bs.isValid) { + mStorage.add(bs); + player.inventory.setItemStack(null); + ((EntityPlayerMP) player).isChangingQuantityOnly = false; + ((EntityPlayerMP) player).updateHeldItem(); + } + } + }) + .setBackground( + () -> new IDrawable[] { getBaseMetaTileEntity().getGUITextureSet() + .getItemSlot(), GT_UITextures.OVERLAY_SLOT_BEE_QUEEN, + new Text(String.valueOf((mMaxSlots - usedSlots) > 99 ? "+99" : (mMaxSlots - usedSlots))) + .color(Color.PURPLE.normal) + .alignment(Alignment.TopRight) }) + .dynamicTooltip( + () -> Arrays.asList( + EnumChatFormatting.GRAY + "Empty slot", + EnumChatFormatting.DARK_PURPLE + "There are " + (mMaxSlots - usedSlots) + " identical slots", + EnumChatFormatting.GRAY + "Click with queen in mouse to insert", + EnumChatFormatting.GRAY + "Shift click a queen in your inventory to insert")) + .setSize(18, 18)); + + final int perRow = 7; + for (int i = 0, imax = ((buttons.size() - 1) / perRow); i <= imax; i++) { + DynamicPositionedRow row = new DynamicPositionedRow().setSynced(false); + for (int j = 0, jmax = (i == imax ? (buttons.size() - 1) % perRow : (perRow - 1)); j <= jmax; j++) { + final int finalI = i * perRow; + final int finalJ = j; + final int ID = finalI + finalJ; + row.widget(buttons.get(ID)); } beesContainer.widget(row.setPos(0, i * 18)); } |