Skip to content

Commit 52f68e0

Browse files
authored
Make Ender Cover and Virtual Registry Abstract (#2510)
1 parent b580ca9 commit 52f68e0

24 files changed

Lines changed: 1772 additions & 706 deletions

src/main/java/gregtech/api/mui/GTGuiTextures.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,8 @@ public static class IDs {
206206
"textures/gui/widget/button_public_private.png",
207207
18, 36, 18, 18, true);
208208

209+
public static final UITexture MENU_OVERLAY = fullImage("textures/gui/overlay/menu_overlay.png");
210+
209211
// todo bronze/steel/primitive fluid slots?
210212

211213
// SLOT OVERLAYS

src/main/java/gregtech/api/mui/GTGuis.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
import net.minecraft.item.ItemStack;
1111

12+
import com.cleanroommc.modularui.api.widget.Interactable;
1213
import com.cleanroommc.modularui.factory.GuiManager;
1314
import com.cleanroommc.modularui.screen.ModularPanel;
1415
import com.cleanroommc.modularui.utils.Alignment;
@@ -62,7 +63,15 @@ public PopupPanel(@NotNull String name, int width, int height, boolean disableBe
6263
super(name);
6364
size(width, height).align(Alignment.Center);
6465
background(GTGuiTextures.BACKGROUND_POPUP);
65-
child(ButtonWidget.panelCloseButton().top(5).right(5));
66+
child(ButtonWidget.panelCloseButton().top(5).right(5)
67+
.onMousePressed(mouseButton -> {
68+
if (mouseButton == 0 || mouseButton == 1) {
69+
this.closeIfOpen(true);
70+
Interactable.playButtonClickSound();
71+
return true;
72+
}
73+
return false;
74+
}));
6675
this.disableBelow = disableBelow;
6776
this.closeOnOutsideClick = closeOnOutsideClick;
6877
}
Lines changed: 224 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,224 @@
1+
package gregtech.api.mui.sync;
2+
3+
import gregtech.api.util.GTUtility;
4+
5+
import net.minecraft.entity.item.EntityItem;
6+
import net.minecraft.entity.player.EntityPlayer;
7+
import net.minecraft.item.ItemStack;
8+
import net.minecraft.network.PacketBuffer;
9+
import net.minecraft.util.SoundCategory;
10+
import net.minecraft.util.SoundEvent;
11+
import net.minecraftforge.fluids.FluidStack;
12+
import net.minecraftforge.fluids.IFluidTank;
13+
import net.minecraftforge.fluids.capability.CapabilityFluidHandler;
14+
import net.minecraftforge.fluids.capability.IFluidHandlerItem;
15+
16+
import com.cleanroommc.modularui.network.NetworkUtils;
17+
import com.cleanroommc.modularui.value.sync.SyncHandler;
18+
import org.jetbrains.annotations.NotNull;
19+
20+
public class GTFluidSyncHandler extends SyncHandler {
21+
22+
private static final int TRY_CLICK_CONTAINER = 1;
23+
24+
private final IFluidTank tank;
25+
private boolean canDrainSlot = true;
26+
private boolean canFillSlot = true;
27+
28+
public GTFluidSyncHandler(IFluidTank tank) {
29+
this.tank = tank;
30+
}
31+
32+
public FluidStack getFluid() {
33+
return this.tank.getFluid();
34+
}
35+
36+
public int getCapacity() {
37+
return this.tank.getCapacity();
38+
}
39+
40+
public GTFluidSyncHandler canDrainSlot(boolean canDrainSlot) {
41+
this.canDrainSlot = canDrainSlot;
42+
return this;
43+
}
44+
45+
public boolean canDrainSlot() {
46+
return this.canDrainSlot;
47+
}
48+
49+
public GTFluidSyncHandler canFillSlot(boolean canFillSlot) {
50+
this.canFillSlot = canFillSlot;
51+
return this;
52+
}
53+
54+
public boolean canFillSlot() {
55+
return this.canFillSlot;
56+
}
57+
58+
@Override
59+
public void readOnClient(int id, PacketBuffer buf) {
60+
if (id == TRY_CLICK_CONTAINER) {
61+
replaceCursorItemStack(NetworkUtils.readItemStack(buf));
62+
}
63+
}
64+
65+
@Override
66+
public void readOnServer(int id, PacketBuffer buf) {
67+
if (id == TRY_CLICK_CONTAINER) {
68+
var stack = tryClickContainer(buf.readBoolean());
69+
if (!stack.isEmpty())
70+
syncToClient(TRY_CLICK_CONTAINER, buffer -> NetworkUtils.writeItemStack(buffer, stack));
71+
}
72+
}
73+
74+
public ItemStack tryClickContainer(boolean tryFillAll) {
75+
ItemStack playerHeldStack = getSyncManager().getCursorItem();
76+
if (playerHeldStack.isEmpty())
77+
return ItemStack.EMPTY;
78+
79+
ItemStack useStack = GTUtility.copy(1, playerHeldStack);
80+
IFluidHandlerItem fluidHandlerItem = useStack
81+
.getCapability(CapabilityFluidHandler.FLUID_HANDLER_ITEM_CAPABILITY, null);
82+
if (fluidHandlerItem == null) return ItemStack.EMPTY;
83+
84+
FluidStack tankFluid = tank.getFluid();
85+
FluidStack heldFluid = fluidHandlerItem.drain(Integer.MAX_VALUE, false);
86+
87+
// nothing to do, return
88+
if (tankFluid == null && heldFluid == null)
89+
return ItemStack.EMPTY;
90+
91+
// tank is empty, try to fill tank
92+
if (canFillSlot && tankFluid == null) {
93+
return fillTankFromStack(fluidHandlerItem, heldFluid, tryFillAll);
94+
95+
// hand is empty, try to drain tank
96+
} else if (canDrainSlot && heldFluid == null) {
97+
return drainTankFromStack(fluidHandlerItem, tankFluid, tryFillAll);
98+
99+
// neither is empty but tank is not full, try to fill tank
100+
} else if (canFillSlot && tank.getFluidAmount() < tank.getCapacity() && heldFluid != null) {
101+
return fillTankFromStack(fluidHandlerItem, heldFluid, tryFillAll);
102+
}
103+
104+
return ItemStack.EMPTY;
105+
}
106+
107+
private ItemStack fillTankFromStack(IFluidHandlerItem fluidHandler, @NotNull FluidStack heldFluid,
108+
boolean tryFillAll) {
109+
ItemStack heldItem = getSyncManager().getCursorItem();
110+
if (heldItem.isEmpty()) return ItemStack.EMPTY;
111+
112+
FluidStack currentFluid = tank.getFluid();
113+
// Fluid type does not match
114+
if (currentFluid != null && !currentFluid.isFluidEqual(heldFluid)) return ItemStack.EMPTY;
115+
116+
int freeSpace = tank.getCapacity() - tank.getFluidAmount();
117+
if (freeSpace <= 0) return ItemStack.EMPTY;
118+
119+
ItemStack itemStackEmptied = ItemStack.EMPTY;
120+
int fluidAmountTaken = 0;
121+
122+
FluidStack drained = fluidHandler.drain(freeSpace, true);
123+
if (drained != null && drained.amount > 0) {
124+
itemStackEmptied = fluidHandler.getContainer();
125+
fluidAmountTaken = drained.amount;
126+
}
127+
if (itemStackEmptied == ItemStack.EMPTY) {
128+
return ItemStack.EMPTY;
129+
}
130+
131+
// find out how many fills we can do
132+
// same round down behavior as drain
133+
int additional = tryFillAll ? Math.min(freeSpace / fluidAmountTaken, heldItem.getCount()) : 1;
134+
FluidStack copiedFluidStack = heldFluid.copy();
135+
copiedFluidStack.amount = fluidAmountTaken * additional;
136+
tank.fill(copiedFluidStack, true);
137+
138+
itemStackEmptied.setCount(additional);
139+
replaceCursorItemStack(itemStackEmptied);
140+
playSound(heldFluid, true);
141+
return itemStackEmptied;
142+
}
143+
144+
private ItemStack drainTankFromStack(IFluidHandlerItem fluidHandler, FluidStack tankFluid, boolean tryFillAll) {
145+
ItemStack heldItem = getSyncManager().getCursorItem();
146+
if (heldItem.isEmpty()) return ItemStack.EMPTY;
147+
148+
ItemStack fluidContainer = fluidHandler.getContainer();
149+
int filled = fluidHandler.fill(tankFluid, false);
150+
if (filled > 0) {
151+
tank.drain(filled, true);
152+
fluidHandler.fill(tankFluid, true);
153+
if (tryFillAll) {
154+
// Determine how many more items we can fill. One item is already filled.
155+
// Integer division means it will round down, so it will only fill equivalent fluid amounts.
156+
// For example:
157+
// Click with 3 cells, with 2500L of fluid in the tank.
158+
// 2 cells will be filled, and 500L will be left behind in the tank.
159+
int additional = Math.min(heldItem.getCount(), tankFluid.amount / filled) - 1;
160+
tank.drain(filled * additional, true);
161+
fluidContainer.grow(additional);
162+
}
163+
replaceCursorItemStack(fluidContainer);
164+
playSound(tankFluid, false);
165+
return fluidContainer;
166+
}
167+
return ItemStack.EMPTY;
168+
}
169+
170+
/**
171+
* Replace the ItemStack on the player's cursor with the passed stack. Use to replace empty cells with filled, or
172+
* filled cells with empty. If it is not fully emptied/filled, it will place the new items into the player inventory
173+
* instead, and shrink the held stack by the appropriate amount.
174+
*/
175+
private void replaceCursorItemStack(ItemStack resultStack) {
176+
int resultStackSize = resultStack.getMaxStackSize();
177+
ItemStack playerStack = getSyncManager().getCursorItem();
178+
179+
if (!getSyncManager().isClient())
180+
syncToClient(TRY_CLICK_CONTAINER, buffer -> NetworkUtils.writeItemStack(buffer, resultStack));
181+
182+
while (resultStack.getCount() > resultStackSize) {
183+
playerStack.shrink(resultStackSize);
184+
addItemToPlayerInventory(resultStack.splitStack(resultStackSize));
185+
}
186+
if (playerStack.getCount() == resultStack.getCount()) {
187+
// every item on the cursor is mutated, so leave it there
188+
getSyncManager().setCursorItem(resultStack);
189+
} else {
190+
// some items not mutated. Mutated items go into the inventory/world.
191+
playerStack.shrink(resultStack.getCount());
192+
getSyncManager().setCursorItem(playerStack);
193+
addItemToPlayerInventory(resultStack);
194+
}
195+
}
196+
197+
/** Place an item into the player's inventory, or drop it in-world as an item entity if it cannot fit. */
198+
private void addItemToPlayerInventory(ItemStack stack) {
199+
if (stack == null) return;
200+
var player = getSyncManager().getPlayer();
201+
202+
if (!player.inventory.addItemStackToInventory(stack) && !player.world.isRemote) {
203+
EntityItem dropItem = player.entityDropItem(stack, 0);
204+
if (dropItem != null) dropItem.setPickupDelay(0);
205+
}
206+
}
207+
208+
/**
209+
* Play the appropriate fluid interaction sound for the fluid. <br />
210+
* Must be called on server to work correctly
211+
**/
212+
private void playSound(FluidStack fluid, boolean fill) {
213+
if (fluid == null) return;
214+
SoundEvent soundEvent;
215+
if (fill) {
216+
soundEvent = fluid.getFluid().getFillSound(fluid);
217+
} else {
218+
soundEvent = fluid.getFluid().getEmptySound(fluid);
219+
}
220+
EntityPlayer player = getSyncManager().getPlayer();
221+
player.world.playSound(null, player.posX, player.posY + 0.5, player.posZ,
222+
soundEvent, SoundCategory.PLAYERS, 1.0F, 1.0F);
223+
}
224+
}

src/main/java/gregtech/api/util/FluidTankSwitchShim.java

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,17 @@
1111
// probably causes problems
1212
public class FluidTankSwitchShim implements IFluidTank, IFluidHandler {
1313

14-
IFluidTank tank;
14+
@Nullable
15+
private IFluidTank tank;
16+
private static final FluidTankInfo NO_INFO = new FluidTankInfo(null, 0);
17+
private static final IFluidTankProperties[] NO_PROPS = new IFluidTankProperties[0];
1518

1619
public FluidTankSwitchShim(IFluidTank tank) {
1720
changeTank(tank);
1821
}
1922

2023
public void changeTank(IFluidTank tank) {
21-
if (!(tank instanceof IFluidHandler)) {
24+
if (tank != null && !(tank instanceof IFluidHandler)) {
2225
throw new IllegalArgumentException("Shim tank must be both IFluidTank and IFluidHandler!");
2326
}
2427
this.tank = tank;
@@ -27,43 +30,49 @@ public void changeTank(IFluidTank tank) {
2730
@Nullable
2831
@Override
2932
public FluidStack getFluid() {
30-
return tank.getFluid();
33+
return tank == null ? null : tank.getFluid();
3134
}
3235

3336
@Override
3437
public int getFluidAmount() {
35-
return tank.getFluidAmount();
38+
return tank == null ? 0 : tank.getFluidAmount();
3639
}
3740

3841
@Override
3942
public int getCapacity() {
40-
return tank.getCapacity();
43+
return tank == null ? 0 : tank.getCapacity();
4144
}
4245

4346
@Override
4447
public FluidTankInfo getInfo() {
45-
return tank.getInfo();
48+
return tank == null ? NO_INFO : tank.getInfo();
4649
}
4750

4851
@Override
4952
public IFluidTankProperties[] getTankProperties() {
53+
if (tank == null)
54+
return NO_PROPS;
55+
5056
return ((IFluidHandler) tank).getTankProperties();
5157
}
5258

5359
@Override
5460
public int fill(FluidStack resource, boolean doFill) {
61+
if (tank == null) return 0;
5562
return ((IFluidHandler) tank).fill(resource, doFill);
5663
}
5764

5865
@Nullable
5966
@Override
6067
public FluidStack drain(FluidStack resource, boolean doDrain) {
68+
if (tank == null) return null;
6169
return ((IFluidHandler) tank).drain(resource, doDrain);
6270
}
6371

6472
@Nullable
6573
@Override
6674
public FluidStack drain(int maxDrain, boolean doDrain) {
75+
if (tank == null) return null;
6776
return tank.drain(maxDrain, doDrain);
6877
}
6978
}

0 commit comments

Comments
 (0)