Update drive viewer screen, move to PoweredVirtualComponent
This commit is contained in:
parent
287238c2d1
commit
d9ba74bc0f
@ -33,6 +33,7 @@ import ru.dbotthepony.mc.otm.matter.MatterRegistry;
|
||||
import ru.dbotthepony.mc.otm.network.MatteryNetworking;
|
||||
import ru.dbotthepony.mc.otm.storage.ItemStackWrapper;
|
||||
import ru.dbotthepony.mc.otm.storage.StorageObjectRegistry;
|
||||
import ru.dbotthepony.mc.otm.storage.StorageObjectTuple;
|
||||
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
import java.util.ArrayList;
|
||||
@ -160,13 +161,15 @@ public class OverdriveThatMatters {
|
||||
};
|
||||
}
|
||||
|
||||
public static StorageObjectTuple<ItemStackWrapper> ITEM_STORAGE;
|
||||
|
||||
private void setup(final FMLCommonSetupEvent event) {
|
||||
MatteryNetworking.register();
|
||||
// LOGGER.info("Registered network");
|
||||
|
||||
MatterRegistry.registerInitialItems();
|
||||
|
||||
StorageObjectRegistry.register(ItemStackWrapper.class, ItemStackWrapper.EMPTY, new Fraction("3.125"));
|
||||
ITEM_STORAGE = StorageObjectRegistry.register(ItemStackWrapper.class, ItemStackWrapper.EMPTY, new Fraction("3.125"));
|
||||
}
|
||||
|
||||
private void setupClient(final FMLClientSetupEvent event) {
|
||||
|
@ -1,250 +0,0 @@
|
||||
package ru.dbotthepony.mc.otm.client.screen;
|
||||
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.chat.TranslatableComponent;
|
||||
import net.minecraft.world.entity.player.Inventory;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import ru.dbotthepony.mc.otm.client.screen.panels.*;
|
||||
import ru.dbotthepony.mc.otm.item.ItemPortableCondensationDrive;
|
||||
import ru.dbotthepony.mc.otm.menu.DriveViewerMenu;
|
||||
import ru.dbotthepony.mc.otm.network.MatteryNetworking;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class DriveViewerScreen extends MatteryScreen<DriveViewerMenu> {
|
||||
public static final int FRAME_WIDTH = 210;
|
||||
public static final int FRAME_HEIGHT = 110;
|
||||
|
||||
public static final int GRID_WIDTH = 9;
|
||||
public static final int GRID_HEIGHT = 5;
|
||||
|
||||
public DriveViewerScreen(DriveViewerMenu menu, Inventory inventory, Component title) {
|
||||
super(menu, inventory, title);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
protected FramePanel makeMainFrame() {
|
||||
var frame = new FramePanel(this, null, 0, 0, FRAME_WIDTH, FRAME_HEIGHT, getTitle());
|
||||
|
||||
var view_panels = new ArrayList<EditablePanel>();
|
||||
var settings_panels = new ArrayList<EditablePanel>();
|
||||
|
||||
var view_button = frame.addTab(FramePanel.FrameTabPosition.TOP);
|
||||
var settings_button = frame.addTab(FramePanel.FrameTabPosition.TOP);
|
||||
|
||||
view_button.bindOnOpen(() -> {
|
||||
for (var panel : view_panels) {
|
||||
panel.setVisible(true);
|
||||
}
|
||||
});
|
||||
|
||||
view_button.bindOnClose(() -> {
|
||||
for (var panel : view_panels) {
|
||||
panel.setVisible(false);
|
||||
}
|
||||
});
|
||||
|
||||
settings_button.bindOnOpen(() -> {
|
||||
for (var panel : settings_panels) {
|
||||
panel.setVisible(true);
|
||||
}
|
||||
});
|
||||
|
||||
settings_button.bindOnClose(() -> {
|
||||
for (var panel : settings_panels) {
|
||||
panel.setVisible(false);
|
||||
}
|
||||
});
|
||||
|
||||
var grid = new GridPanel(this, frame, 0, 0, 0, 0, GRID_WIDTH, GRID_HEIGHT);
|
||||
grid.setDock(Dock.FILL);
|
||||
grid.setDockMargin(2, 2, 2, 2);
|
||||
|
||||
var scroll_bar = new ScrollBarPanel(this, frame, 0, 0, 0);
|
||||
scroll_bar.setDock(Dock.RIGHT);
|
||||
scroll_bar.setupRowMultiplier(() -> {
|
||||
return menu.view.getItems().size() / GRID_WIDTH;
|
||||
});
|
||||
|
||||
view_panels.add(grid);
|
||||
view_panels.add(scroll_bar);
|
||||
|
||||
for (int i = 0; i < GRID_WIDTH * GRID_HEIGHT; i++) {
|
||||
final int index = i;
|
||||
|
||||
new AbstractSlotPanel(this, grid, 0, 0) {
|
||||
@Nonnull
|
||||
@Override
|
||||
protected ItemStack getItemStack() {
|
||||
int findex = index + scroll_bar.getScroll(menu.view.getItems().size() / GRID_WIDTH);
|
||||
|
||||
var list = menu.view.getItems();
|
||||
|
||||
if (findex >= list.size()) {
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
return list.get(findex).stack();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean mouseScrolledInner(double mouse_x, double mouse_y, double scroll) {
|
||||
return scroll_bar.mouseScrolledInner(mouse_x, mouse_y, scroll);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean mouseClickedInner(double mouse_x, double mouse_y, int mouse_click_type) {
|
||||
int findex = index + scroll_bar.getScroll(GRID_WIDTH);
|
||||
menu.view.mouseClick(findex, mouse_click_type);
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
var dock_left = new FlexGridPanel(this, frame, 0, 0, 90, 0);
|
||||
dock_left.setDock(Dock.LEFT);
|
||||
dock_left.setDockMargin(4, 0, 4, 0);
|
||||
|
||||
var grid_filter = new FlexGridPanel(this, frame);
|
||||
grid_filter.setDock(Dock.FILL);
|
||||
|
||||
settings_panels.add(dock_left);
|
||||
settings_panels.add(grid_filter);
|
||||
|
||||
for (int i = 0; i < ItemPortableCondensationDrive.FilterSettings.MAX_FILTERS; i++) {
|
||||
final int index = i;
|
||||
|
||||
new AbstractSlotPanel(this, grid_filter, 0, 0) {
|
||||
@Nonnull
|
||||
@Override
|
||||
protected ItemStack getItemStack() {
|
||||
var filter = menu.getFilter();
|
||||
|
||||
if (filter == null)
|
||||
return ItemStack.EMPTY;
|
||||
|
||||
return filter.items[index];
|
||||
}
|
||||
|
||||
private boolean clicking = false;
|
||||
|
||||
@Override
|
||||
protected boolean mouseClickedInner(double mouse_x, double mouse_y, int flag) {
|
||||
clicking = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean mouseReleasedInner(double mouse_x, double mouse_y, int flag) {
|
||||
if (clicking)
|
||||
MatteryNetworking.send(null, new DriveViewerMenu.FilterSetPacket(menu.containerId, index, menu.getCarried()));
|
||||
|
||||
clicking = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
final var no = new TranslatableComponent("otm.filter.no");
|
||||
final var yes = new TranslatableComponent("otm.filter.yes");
|
||||
|
||||
var match_nbt = new ButtonPanel(this, dock_left, 0, 0, 90, 20, new TranslatableComponent("otm.filter.match_nbt", no)) {
|
||||
@Override
|
||||
public void tick() {
|
||||
super.tick();
|
||||
|
||||
var filter = menu.getFilter();
|
||||
|
||||
if (filter != null) {
|
||||
getOrCreateWidget().setMessage(new TranslatableComponent("otm.filter.match_nbt", filter.matchNbt ? yes : no));
|
||||
getOrCreateWidget().active = !isWidgetDisabled();
|
||||
} else {
|
||||
getOrCreateWidget().active = false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPress() {
|
||||
super.onPress();
|
||||
|
||||
var filter = menu.getFilter();
|
||||
|
||||
if (filter != null) {
|
||||
MatteryNetworking.send(null, new DriveViewerMenu.FilterSwitchPacket(menu.containerId, DriveViewerMenu.FilterSwitch.MATCH_NBT, !filter.matchNbt));
|
||||
disableFor(20);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var match_tag = new ButtonPanel(this, dock_left, 0, 0, 90, 20, new TranslatableComponent("otm.filter.match_tag", no)) {
|
||||
@Override
|
||||
public void tick() {
|
||||
super.tick();
|
||||
|
||||
var filter = menu.getFilter();
|
||||
|
||||
if (filter != null) {
|
||||
getOrCreateWidget().setMessage(new TranslatableComponent("otm.filter.match_tag", filter.matchTag ? yes : no));
|
||||
getOrCreateWidget().active = !isWidgetDisabled();
|
||||
} else {
|
||||
getOrCreateWidget().active = false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPress() {
|
||||
super.onPress();
|
||||
|
||||
var filter = menu.getFilter();
|
||||
|
||||
if (filter != null) {
|
||||
MatteryNetworking.send(null, new DriveViewerMenu.FilterSwitchPacket(menu.containerId, DriveViewerMenu.FilterSwitch.MATCH_TAG, !filter.matchTag));
|
||||
disableFor(20);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var blacklist = new ButtonPanel(this, dock_left, 0, 0, 90, 20, new TranslatableComponent("otm.filter.blacklist", no)) {
|
||||
@Override
|
||||
public void tick() {
|
||||
super.tick();
|
||||
|
||||
var filter = menu.getFilter();
|
||||
|
||||
if (filter != null) {
|
||||
getOrCreateWidget().setMessage(new TranslatableComponent("otm.filter.blacklist", filter.isBlacklist ? yes : no));
|
||||
getOrCreateWidget().active = !isWidgetDisabled();
|
||||
} else {
|
||||
getOrCreateWidget().active = false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPress() {
|
||||
super.onPress();
|
||||
|
||||
var filter = menu.getFilter();
|
||||
|
||||
if (filter != null) {
|
||||
MatteryNetworking.send(null, new DriveViewerMenu.FilterSwitchPacket(menu.containerId, DriveViewerMenu.FilterSwitch.BLACKLIST, !filter.isBlacklist));
|
||||
disableFor(20);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
match_nbt.setDockMargin(0, 4, 0, 0);
|
||||
match_tag.setDockMargin(0, 4, 0, 0);
|
||||
blacklist.setDockMargin(0, 4, 0, 0);
|
||||
|
||||
for (var panel : settings_panels) {
|
||||
panel.setVisible(false);
|
||||
}
|
||||
|
||||
return frame;
|
||||
}
|
||||
}
|
@ -115,11 +115,11 @@ public abstract class MatteryScreen<T extends MatteryMenu> extends AbstractConta
|
||||
this.menu = menu;
|
||||
playerInventoryTitle = inventory.getDisplayName();
|
||||
|
||||
if (menu.inventory_slots.size() != 0) {
|
||||
if (menu.inventorySlots.size() != 0) {
|
||||
inventory_frame = new FramePanel(this, null, 0, 0, INVENTORY_FRAME_WIDTH, INVENTORY_FRAME_HEIGHT, inventory.getDisplayName());
|
||||
panels.add(inventory_frame);
|
||||
|
||||
for (var slot : menu.inventory_slots) {
|
||||
for (var slot : menu.inventorySlots) {
|
||||
new SlotPanel<>(
|
||||
this,
|
||||
inventory_frame,
|
||||
@ -359,10 +359,6 @@ public abstract class MatteryScreen<T extends MatteryMenu> extends AbstractConta
|
||||
|
||||
if (main_frame != null) {
|
||||
addPanel(main_frame);
|
||||
|
||||
for (var slot : menu.main_slots) {
|
||||
new SlotPanel<>(this, main_frame, slot);
|
||||
}
|
||||
}
|
||||
|
||||
movePanels();
|
||||
|
@ -1,266 +0,0 @@
|
||||
package ru.dbotthepony.mc.otm.menu;
|
||||
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.world.SimpleContainer;
|
||||
import net.minecraft.world.entity.player.Inventory;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraftforge.energy.CapabilityEnergy;
|
||||
import net.minecraftforge.network.NetworkEvent;
|
||||
import ru.dbotthepony.mc.otm.Registry;
|
||||
import ru.dbotthepony.mc.otm.block.entity.BlockEntityDriveViewer;
|
||||
import ru.dbotthepony.mc.otm.capability.MatteryCapability;
|
||||
import ru.dbotthepony.mc.otm.capability.drive.IMatteryDrive;
|
||||
import ru.dbotthepony.mc.otm.item.ItemPortableCondensationDrive;
|
||||
import ru.dbotthepony.mc.otm.menu.data.INetworkedItemViewSupplier;
|
||||
import ru.dbotthepony.mc.otm.menu.data.NetworkedItemView;
|
||||
import ru.dbotthepony.mc.otm.storage.ItemStackWrapper;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class DriveViewerMenu extends PoweredMatteryMenu implements INetworkedItemViewSupplier {
|
||||
public final NetworkedItemView view;
|
||||
public MatterySlot drive_slot;
|
||||
public IMatteryDrive<ItemStackWrapper> last_drive;
|
||||
|
||||
@Override
|
||||
public NetworkedItemView getNetworkedItemView() {
|
||||
return view;
|
||||
}
|
||||
|
||||
public DriveViewerMenu(int containerID, Inventory inventory) {
|
||||
this(containerID, inventory, null);
|
||||
}
|
||||
|
||||
public DriveViewerMenu(int containerID, Inventory inventory, @Nullable BlockEntityDriveViewer tile) {
|
||||
super(Registry.Menus.DRIVE_VIEWER, containerID, inventory, tile);
|
||||
|
||||
var container = tile != null ? tile.drive_slot : new SimpleContainer(1);
|
||||
|
||||
drive_slot = new MatterySlot(container, 0) {
|
||||
@Override
|
||||
public boolean mayPlace(ItemStack stack) {
|
||||
return stack.getCapability(MatteryCapability.DRIVE).isPresent();
|
||||
}
|
||||
};
|
||||
|
||||
view = new NetworkedItemView(inventory.player, this, tile == null) {
|
||||
@Override
|
||||
public int calculateIOAmount(int desired_amount) {
|
||||
if (tile != null)
|
||||
return tile.getIOItemCount(desired_amount, true);
|
||||
|
||||
return super.calculateIOAmount(desired_amount);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doneIOAmount(int done_amount) {
|
||||
if (tile != null) {
|
||||
tile.getIOItemCount(done_amount, false);
|
||||
return;
|
||||
}
|
||||
|
||||
super.doneIOAmount(done_amount);
|
||||
}
|
||||
};
|
||||
|
||||
addSlot(drive_slot);
|
||||
addBatterySlot();
|
||||
addInventorySlots();
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void broadcastChanges() {
|
||||
super.broadcastChanges();
|
||||
|
||||
if (tile != null) {
|
||||
var get = ((BlockEntityDriveViewer) tile).drive_slot.getItem(0);
|
||||
|
||||
if (get.isEmpty()) {
|
||||
last_drive = null;
|
||||
} else {
|
||||
var get_cap = get.getCapability(MatteryCapability.DRIVE).resolve();
|
||||
|
||||
if (get_cap.isEmpty() || get_cap.get().storageIdentity() != ItemStackWrapper.class) {
|
||||
last_drive = null;
|
||||
} else {
|
||||
last_drive = (IMatteryDrive<ItemStackWrapper>) get_cap.get();
|
||||
}
|
||||
}
|
||||
|
||||
view.setComponent(last_drive);
|
||||
view.network();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getWorkingSlotStart() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getWorkingSlotEnd() {
|
||||
return 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removed(Player p_38940_) {
|
||||
super.removed(p_38940_);
|
||||
|
||||
if (last_drive != null) {
|
||||
last_drive.removeListener(view);
|
||||
view.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack quickMoveStack(Player ply, int slot_index) {
|
||||
var slot = slots.get(slot_index);
|
||||
var item = slot.getItem();
|
||||
|
||||
if (item.isEmpty() || item.getCapability(MatteryCapability.DRIVE).isPresent() || item.getCapability(CapabilityEnergy.ENERGY).isPresent())
|
||||
return super.quickMoveStack(ply, slot_index);
|
||||
|
||||
if (last_drive == null || tile == null)
|
||||
return ItemStack.EMPTY;
|
||||
|
||||
var tile = (BlockEntityDriveViewer) this.tile;
|
||||
int amount = tile.getIOItemCount(item.getCount(), true);
|
||||
|
||||
if (amount == 0)
|
||||
return ItemStack.EMPTY;
|
||||
|
||||
if (amount == item.getCount()) {
|
||||
var remaining = last_drive.insertStack(new ItemStackWrapper(item), false);
|
||||
|
||||
if (remaining.getCount().toInt() == item.getCount())
|
||||
return ItemStack.EMPTY;
|
||||
|
||||
if (remaining.isEmpty()) {
|
||||
var copy = item.copy();
|
||||
slot.set(ItemStack.EMPTY);
|
||||
tile.getIOItemCount(item.getCount(), false);
|
||||
return copy;
|
||||
}
|
||||
|
||||
var copy = item.copy();
|
||||
tile.getIOItemCount(item.getCount() - remaining.getCount().toInt(), false);
|
||||
item.shrink(remaining.getCount().toInt());
|
||||
slot.setChanged();
|
||||
|
||||
return copy;
|
||||
}
|
||||
|
||||
var copy_insert = item.copy();
|
||||
copy_insert.setCount(amount);
|
||||
|
||||
var remaining = last_drive.insertStack(new ItemStackWrapper(copy_insert), false);
|
||||
|
||||
if (remaining.getCount().toInt() == copy_insert.getCount())
|
||||
return ItemStack.EMPTY;
|
||||
|
||||
var copy = item.copy();
|
||||
tile.getIOItemCount(amount - remaining.getCount().toInt(), false);
|
||||
item.shrink(amount - remaining.getCount().toInt());
|
||||
slot.setChanged();
|
||||
|
||||
return copy;
|
||||
}
|
||||
|
||||
public enum FilterSwitch {
|
||||
MATCH_NBT,
|
||||
MATCH_TAG,
|
||||
BLACKLIST
|
||||
}
|
||||
|
||||
public ItemPortableCondensationDrive.FilterSettings getFilter() {
|
||||
if (drive_slot.getItem().isEmpty())
|
||||
return null;
|
||||
|
||||
if (drive_slot.getItem().getItem() instanceof ItemPortableCondensationDrive item)
|
||||
return item.getFilterSettings(drive_slot.getItem());
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public record FilterSetPacket(int id, int slot, ItemStack value) {
|
||||
public void write(FriendlyByteBuf buffer) {
|
||||
buffer.writeInt(id);
|
||||
buffer.writeInt(slot);
|
||||
buffer.writeItem(value);
|
||||
}
|
||||
|
||||
public static FilterSetPacket read(FriendlyByteBuf buffer) {
|
||||
return new FilterSetPacket(buffer.readInt(), buffer.readInt(), buffer.readItem());
|
||||
}
|
||||
|
||||
public void play(Supplier<NetworkEvent.Context> context) {
|
||||
context.get().setPacketHandled(true);
|
||||
|
||||
if (slot < 0 || slot >= ItemPortableCondensationDrive.FilterSettings.MAX_FILTERS)
|
||||
return;
|
||||
|
||||
if (value.getCount() > 1)
|
||||
value.setCount(1);
|
||||
|
||||
context.get().enqueueWork(() -> {
|
||||
var ply = context.get().getSender();
|
||||
|
||||
if (ply.containerMenu instanceof DriveViewerMenu menu && menu.containerId == id) {
|
||||
if (menu.drive_slot.getItem().isEmpty())
|
||||
return;
|
||||
|
||||
if (menu.drive_slot.getItem().getItem() instanceof ItemPortableCondensationDrive drive) {
|
||||
var filter = drive.getFilterSettings(menu.drive_slot.getItem());
|
||||
filter.items[slot] = value;
|
||||
filter.serializeNBT(menu.drive_slot.getItem());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public record FilterSwitchPacket(int id, FilterSwitch type, boolean value) {
|
||||
public void write(FriendlyByteBuf buffer) {
|
||||
buffer.writeInt(id);
|
||||
buffer.writeEnum(type);
|
||||
buffer.writeBoolean(value);
|
||||
}
|
||||
|
||||
public static FilterSwitchPacket read(FriendlyByteBuf buffer) {
|
||||
return new FilterSwitchPacket(buffer.readInt(), buffer.readEnum(FilterSwitch.class), buffer.readBoolean());
|
||||
}
|
||||
|
||||
public void play(Supplier<NetworkEvent.Context> context) {
|
||||
context.get().setPacketHandled(true);
|
||||
context.get().enqueueWork(() -> {
|
||||
var ply = context.get().getSender();
|
||||
|
||||
if (ply.containerMenu instanceof DriveViewerMenu menu && menu.containerId == id) {
|
||||
var settings = menu.getFilter();
|
||||
|
||||
if (settings == null)
|
||||
return;
|
||||
|
||||
switch (type) {
|
||||
case MATCH_NBT -> {
|
||||
settings.matchNbt = value;
|
||||
}
|
||||
|
||||
case MATCH_TAG -> {
|
||||
settings.matchTag = value;
|
||||
}
|
||||
|
||||
case BLACKLIST -> {
|
||||
settings.isBlacklist = value;
|
||||
}
|
||||
}
|
||||
|
||||
settings.serializeNBT(menu.drive_slot.getItem());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
@ -1,293 +0,0 @@
|
||||
package ru.dbotthepony.mc.otm.menu.data;
|
||||
|
||||
import com.mojang.blaze3d.platform.InputConstants;
|
||||
import net.minecraft.MethodsReturnNonnullByDefault;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.inventory.ClickAction;
|
||||
import net.minecraft.world.inventory.ClickType;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraftforge.network.PacketDistributor;
|
||||
import ru.dbotthepony.mc.otm.core.Fraction;
|
||||
import ru.dbotthepony.mc.otm.menu.MatteryMenu;
|
||||
import ru.dbotthepony.mc.otm.network.MatteryNetworking;
|
||||
import ru.dbotthepony.mc.otm.network.SetCarriedPacket;
|
||||
import ru.dbotthepony.mc.otm.storage.*;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import static net.minecraft.client.gui.screens.Screen.hasShiftDown;
|
||||
|
||||
/**
|
||||
* Creates a virtual, slotless container for Player's interaction with.
|
||||
*/
|
||||
|
||||
@MethodsReturnNonnullByDefault
|
||||
@ParametersAreNonnullByDefault
|
||||
public class NetworkedItemView implements IStorageListener<ItemStackWrapper> {
|
||||
public final boolean remote;
|
||||
public final MatteryMenu menu;
|
||||
public final Player ply;
|
||||
|
||||
protected int next_stack_id = 0;
|
||||
|
||||
protected final HashMap<Integer, NetworkedItem> state = new HashMap<>();
|
||||
protected final HashMap<UUID, NetworkedItem> upstream_state = new HashMap<>();
|
||||
protected final ArrayList<Object> backlog = new ArrayList<>();
|
||||
|
||||
@Nullable
|
||||
public NetworkedItem get(int id) {
|
||||
return state.get(id);
|
||||
}
|
||||
|
||||
private List<NetworkedItem> view_cache;
|
||||
|
||||
protected IStorageComponent<ItemStackWrapper> provider;
|
||||
|
||||
public NetworkedItemView(Player ply, MatteryMenu menu, boolean remote) {
|
||||
this.remote = remote;
|
||||
this.menu = menu;
|
||||
this.ply = ply;
|
||||
}
|
||||
|
||||
public void mouseClick(int index, int mouse_click_type) {
|
||||
var list = getItems();
|
||||
var action = mouse_click_type == InputConstants.MOUSE_BUTTON_LEFT ? ClickAction.PRIMARY : ClickAction.SECONDARY;
|
||||
var type = mouse_click_type == InputConstants.MOUSE_BUTTON_MIDDLE ? ClickType.CLONE : hasShiftDown() ? ClickType.QUICK_MOVE : ClickType.PICKUP;
|
||||
|
||||
MatteryNetworking.send(null, new InteractPacket(menu.containerId, index >= list.size() ? -1 : list.get(index).id(), type, action));
|
||||
}
|
||||
|
||||
public void setComponent(@Nullable IStorageComponent<ItemStackWrapper> provider) {
|
||||
if (provider == this.provider)
|
||||
return;
|
||||
|
||||
if (this.provider != null)
|
||||
this.provider.removeListenerAuto(this);
|
||||
|
||||
this.provider = provider;
|
||||
|
||||
if (provider != null)
|
||||
provider.addListenerAuto(this);
|
||||
}
|
||||
|
||||
public void removed() {
|
||||
if (this.provider != null)
|
||||
this.provider.removeListenerAuto(this);
|
||||
}
|
||||
|
||||
public record NetworkedItem(int id, ItemStack stack, @Nullable UUID id_upstream) {
|
||||
public NetworkedItem(int id, ItemStack stack) {
|
||||
this(id, stack, null);
|
||||
}
|
||||
}
|
||||
|
||||
public void clearCache() {
|
||||
view_cache = null;
|
||||
}
|
||||
|
||||
public List<NetworkedItem> getItems() {
|
||||
if (view_cache != null)
|
||||
return view_cache;
|
||||
|
||||
return view_cache = List.copyOf(state.values());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addObject(ItemStackWrapper stack, UUID id, IStorageView<ItemStackWrapper> provider) {
|
||||
addObject(stack.stack(), id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void changeObject(UUID id, Fraction newCount) {
|
||||
changeObject(id, newCount.toInt());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeObject(UUID id) {
|
||||
var get = upstream_state.get(id);
|
||||
|
||||
if (get == null)
|
||||
throw new IllegalStateException("Unknown ItemStack with upstream id " + id + "!");
|
||||
|
||||
upstream_state.remove(id);
|
||||
state.remove(get.id);
|
||||
|
||||
if (!remote) {
|
||||
backlog.add(new StackRemovePacket(menu.containerId, get.id));
|
||||
}
|
||||
|
||||
clearCache();
|
||||
}
|
||||
|
||||
public void addObject(ItemStack stack, UUID id_upstream) {
|
||||
if (upstream_state.containsKey(id_upstream))
|
||||
throw new IllegalStateException("Already tracking ItemStack with upstream id " + id_upstream + "!");
|
||||
|
||||
var state = new NetworkedItem(next_stack_id++, stack.copy(), id_upstream);
|
||||
this.state.put(state.id, state);
|
||||
this.upstream_state.put(id_upstream, state);
|
||||
|
||||
if (!remote) {
|
||||
backlog.add(new StackAddPacket(menu.containerId, state.id, stack));
|
||||
}
|
||||
|
||||
clearCache();
|
||||
}
|
||||
|
||||
public void changeObject(UUID id_upstream, int new_count) {
|
||||
var get = upstream_state.get(id_upstream);
|
||||
|
||||
if (get == null)
|
||||
throw new IllegalStateException("Unknown ItemStack with upstream id " + id_upstream + "!");
|
||||
|
||||
get.stack.setCount(new_count);
|
||||
|
||||
if (!remote) {
|
||||
backlog.add(new StackChangePacket(menu.containerId, get.id, new_count));
|
||||
}
|
||||
|
||||
clearCache();
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
clearCache();
|
||||
upstream_state.clear();
|
||||
state.clear();
|
||||
|
||||
if (!remote) {
|
||||
backlog.clear();
|
||||
backlog.add(new ClearPacket(menu.containerId));
|
||||
}
|
||||
}
|
||||
|
||||
public void network() {
|
||||
if (remote)
|
||||
throw new IllegalStateException("Not a server");
|
||||
|
||||
var consumer = PacketDistributor.PLAYER.with(() -> (ServerPlayer) ply);
|
||||
|
||||
for (var packet : backlog) {
|
||||
MatteryNetworking.CHANNEL.send(consumer, packet);
|
||||
}
|
||||
|
||||
backlog.clear();
|
||||
}
|
||||
|
||||
public int calculateIOAmount(int desired_amount) {
|
||||
return desired_amount;
|
||||
}
|
||||
|
||||
public void doneIOAmount(int done_amount) {
|
||||
|
||||
}
|
||||
|
||||
public void playerInteract(InteractPacket packet) {
|
||||
if (provider == null)
|
||||
return;
|
||||
|
||||
var click = packet.click();
|
||||
var action = packet.action();
|
||||
var stack_id = packet.stack_id();
|
||||
|
||||
if (click == ClickType.CLONE) {
|
||||
if (stack_id < 0 || !ply.getAbilities().instabuild)
|
||||
return;
|
||||
|
||||
var get_state = get(stack_id);
|
||||
|
||||
if (get_state == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
var copy = get_state.stack().copy();
|
||||
copy.setCount(Math.min(copy.getCount(), copy.getMaxStackSize()));
|
||||
|
||||
ply.containerMenu.setCarried(copy);
|
||||
MatteryNetworking.send((ServerPlayer) ply, new SetCarriedPacket(ply.containerMenu.getCarried()));
|
||||
ply.containerMenu.setRemoteCarried(ply.containerMenu.getCarried().copy());
|
||||
return;
|
||||
}
|
||||
|
||||
if (click == ClickType.QUICK_MOVE && stack_id > -1) {
|
||||
var get_state = get(stack_id);
|
||||
|
||||
if (get_state == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
int amount = calculateIOAmount(action == ClickAction.PRIMARY ? get_state.stack().getMaxStackSize() : Math.max(1, get_state.stack().getMaxStackSize() / 2));
|
||||
var extracted = provider.extractStack(get_state.id_upstream(), new Fraction(amount), true);
|
||||
|
||||
if (!extracted.isEmpty()) {
|
||||
var move = menu.quickMoveToInventory(extracted.stack(), false);
|
||||
|
||||
if (move.remaining().getCount() != extracted.stack().getCount()) {
|
||||
provider.extractStack(get_state.id_upstream(), new Fraction(extracted.stack().getCount() - move.remaining().getCount()), false);
|
||||
doneIOAmount(extracted.stack().getCount() - move.remaining().getCount());
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!menu.getCarried().isEmpty() && click != ClickType.QUICK_MOVE) {
|
||||
// try to put
|
||||
if (action == ClickAction.PRIMARY) {
|
||||
var carried = menu.getCarried();
|
||||
int amount = calculateIOAmount(carried.getCount());
|
||||
|
||||
if (amount == carried.getCount()) {
|
||||
var leftover = provider.insertStack(new ItemStackWrapper(menu.getCarried()), false);
|
||||
menu.setCarried(leftover.stack());
|
||||
doneIOAmount(amount - leftover.stack().getCount());
|
||||
|
||||
MatteryNetworking.send((ServerPlayer) ply, new SetCarriedPacket(menu.getCarried()));
|
||||
menu.setRemoteCarried(menu.getCarried().copy());
|
||||
} else if (amount != 0) {
|
||||
var copy = carried.copy();
|
||||
copy.setCount(amount);
|
||||
|
||||
var leftover = provider.insertStack(new ItemStackWrapper(copy), false);
|
||||
doneIOAmount(amount - leftover.stack().getCount());
|
||||
|
||||
leftover.setCount(carried.getCount() - amount + leftover.getCountInt());
|
||||
menu.setCarried(leftover.stack());
|
||||
|
||||
MatteryNetworking.send((ServerPlayer) ply, new SetCarriedPacket(menu.getCarried()));
|
||||
menu.setRemoteCarried(menu.getCarried().copy());
|
||||
}
|
||||
} else {
|
||||
var copy = menu.getCarried().copy();
|
||||
copy.setCount(1);
|
||||
|
||||
if (calculateIOAmount(1) == 1 && provider.insertStack(new ItemStackWrapper(copy), false).isEmpty()) {
|
||||
menu.getCarried().shrink(1);
|
||||
doneIOAmount(1);
|
||||
MatteryNetworking.send((ServerPlayer) ply, new SetCarriedPacket(menu.getCarried()));
|
||||
menu.setRemoteCarried(menu.getCarried().copy());
|
||||
}
|
||||
}
|
||||
} else if (stack_id > -1) {
|
||||
var get_state = get(stack_id);
|
||||
|
||||
if (get_state == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
int amount = calculateIOAmount(action == ClickAction.PRIMARY ? get_state.stack().getMaxStackSize() : Math.max(1, get_state.stack().getMaxStackSize() / 2));
|
||||
|
||||
var extracted = provider.extractStack(get_state.id_upstream(), new Fraction(amount), false);
|
||||
|
||||
doneIOAmount(extracted.getCountInt());
|
||||
menu.setCarried(extracted.stack());
|
||||
MatteryNetworking.send((ServerPlayer) ply, new SetCarriedPacket(menu.getCarried()));
|
||||
menu.setRemoteCarried(menu.getCarried().copy());
|
||||
}
|
||||
}
|
||||
}
|
@ -1,45 +1,42 @@
|
||||
package ru.dbotthepony.mc.otm.block;
|
||||
package ru.dbotthepony.mc.otm.block
|
||||
|
||||
import net.minecraft.MethodsReturnNonnullByDefault;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.EntityBlock;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityTicker;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.block.state.StateDefinition;
|
||||
import net.minecraft.world.level.block.state.properties.BooleanProperty;
|
||||
import ru.dbotthepony.mc.otm.Registry;
|
||||
import ru.dbotthepony.mc.otm.block.entity.BlockEntityDriveViewer;
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.world.level.Level
|
||||
import net.minecraft.world.level.block.Block
|
||||
import net.minecraft.world.level.block.EntityBlock
|
||||
import net.minecraft.world.level.block.entity.BlockEntity
|
||||
import net.minecraft.world.level.block.entity.BlockEntityTicker
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType
|
||||
import net.minecraft.world.level.block.state.BlockState
|
||||
import net.minecraft.world.level.block.state.StateDefinition
|
||||
import net.minecraft.world.level.block.state.properties.BooleanProperty
|
||||
import ru.dbotthepony.mc.otm.Registry
|
||||
import ru.dbotthepony.mc.otm.block.entity.BlockEntityDriveViewer
|
||||
import ru.dbotthepony.mc.otm.block.entity.worker.WorkerState
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
|
||||
import static ru.dbotthepony.mc.otm.block.entity.worker.WorkerState.SEMI_WORKER_STATE;
|
||||
|
||||
@MethodsReturnNonnullByDefault
|
||||
@ParametersAreNonnullByDefault
|
||||
public class BlockDriveViewer extends BlockMatteryRotatable implements EntityBlock {
|
||||
@Nullable
|
||||
@Override
|
||||
public BlockEntity newBlockEntity(BlockPos blockPos, BlockState blockState) {
|
||||
return new BlockEntityDriveViewer(blockPos, blockState);
|
||||
class BlockDriveViewer : BlockMatteryRotatable(), EntityBlock {
|
||||
override fun newBlockEntity(blockPos: BlockPos, blockState: BlockState): BlockEntity {
|
||||
return BlockEntityDriveViewer(blockPos, blockState)
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public <T extends BlockEntity> BlockEntityTicker<T> getTicker(Level p_153212_, BlockState p_153213_, BlockEntityType<T> p_153214_) {
|
||||
return p_153212_.isClientSide || p_153214_ != Registry.BlockEntities.DRIVE_VIEWER ? null : BlockEntityDriveViewer::ticker;
|
||||
override fun <T : BlockEntity> getTicker(
|
||||
p_153212_: Level,
|
||||
p_153213_: BlockState,
|
||||
p_153214_: BlockEntityType<T>
|
||||
): BlockEntityTicker<T>? {
|
||||
if (p_153212_.isClientSide || p_153214_ !== Registry.BlockEntities.DRIVE_VIEWER)
|
||||
return null
|
||||
|
||||
return BlockEntityTicker { _, _, _, tile -> if (tile is BlockEntityDriveViewer) tile.tick() }
|
||||
}
|
||||
|
||||
public static final BooleanProperty DRIVE_PRESENT = BooleanProperty.create("drive");
|
||||
override fun createBlockStateDefinition(builder: StateDefinition.Builder<Block, BlockState>) {
|
||||
super.createBlockStateDefinition(builder)
|
||||
builder.add(WorkerState.SEMI_WORKER_STATE)
|
||||
builder.add(DRIVE_PRESENT)
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
|
||||
super.createBlockStateDefinition(builder);
|
||||
builder.add(SEMI_WORKER_STATE);
|
||||
builder.add(DRIVE_PRESENT);
|
||||
companion object {
|
||||
val DRIVE_PRESENT = BooleanProperty.create("drive")
|
||||
}
|
||||
}
|
||||
|
@ -1,137 +1,113 @@
|
||||
package ru.dbotthepony.mc.otm.block.entity;
|
||||
package ru.dbotthepony.mc.otm.block.entity
|
||||
|
||||
import net.minecraft.MethodsReturnNonnullByDefault;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.chat.TranslatableComponent;
|
||||
import net.minecraft.world.entity.player.Inventory;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.inventory.AbstractContainerMenu;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import ru.dbotthepony.mc.otm.OverdriveThatMatters;
|
||||
import ru.dbotthepony.mc.otm.Registry;
|
||||
import ru.dbotthepony.mc.otm.block.BlockDriveViewer;
|
||||
import ru.dbotthepony.mc.otm.block.entity.worker.WorkerState;
|
||||
import ru.dbotthepony.mc.otm.capability.MatteryCapability;
|
||||
import ru.dbotthepony.mc.otm.capability.MatteryMachineEnergyStorage;
|
||||
import ru.dbotthepony.mc.otm.container.MatteryContainer;
|
||||
import ru.dbotthepony.mc.otm.core.Fraction;
|
||||
import ru.dbotthepony.mc.otm.menu.DriveViewerMenu;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
import net.minecraft.MethodsReturnNonnullByDefault
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.nbt.CompoundTag
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.network.chat.TranslatableComponent
|
||||
import net.minecraft.world.entity.player.Inventory
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.inventory.AbstractContainerMenu
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.level.Level
|
||||
import net.minecraft.world.level.block.Block
|
||||
import net.minecraft.world.level.block.state.BlockState
|
||||
import ru.dbotthepony.mc.otm.OverdriveThatMatters
|
||||
import ru.dbotthepony.mc.otm.Registry
|
||||
import ru.dbotthepony.mc.otm.block.BlockDriveViewer
|
||||
import ru.dbotthepony.mc.otm.block.entity.worker.WorkerState
|
||||
import ru.dbotthepony.mc.otm.capability.MatteryCapability
|
||||
import ru.dbotthepony.mc.otm.capability.MatteryMachineEnergyStorage
|
||||
import ru.dbotthepony.mc.otm.container.MatteryContainer
|
||||
import ru.dbotthepony.mc.otm.core.Fraction
|
||||
import ru.dbotthepony.mc.otm.ifHas
|
||||
import ru.dbotthepony.mc.otm.menu.DriveViewerMenu
|
||||
import ru.dbotthepony.mc.otm.set
|
||||
import javax.annotation.ParametersAreNonnullByDefault
|
||||
|
||||
@MethodsReturnNonnullByDefault
|
||||
@ParametersAreNonnullByDefault
|
||||
public class BlockEntityDriveViewer extends BlockEntityMatteryPowered {
|
||||
public static final Fraction MTE_PER_OPERATION = new Fraction("3.125");
|
||||
class BlockEntityDriveViewer(p_155229_: BlockPos, p_155230_: BlockState) : BlockEntityMatteryPowered(Registry.BlockEntities.DRIVE_VIEWER, p_155229_, p_155230_) {
|
||||
override fun setChanged() {
|
||||
super.setChanged()
|
||||
|
||||
public boolean canIOItems() {
|
||||
return energy.getBatteryLevel().compareTo(MTE_PER_OPERATION) >= 0;
|
||||
}
|
||||
val level = level
|
||||
|
||||
private void updateState(Level level) {
|
||||
if (isRemoved())
|
||||
return;
|
||||
if (level != null) {
|
||||
OverdriveThatMatters.tickOnceSelf(level) {
|
||||
if (isRemoved) return@tickOnceSelf
|
||||
|
||||
var state = getBlockState();
|
||||
var state = blockState
|
||||
|
||||
if (drive_slot.getItem(0).getCapability(MatteryCapability.DRIVE).isPresent() && canIOItems()) {
|
||||
state = state.setValue(WorkerState.SEMI_WORKER_STATE, WorkerState.WORKING);
|
||||
if (drive_slot.getItem(0).getCapability(MatteryCapability.DRIVE).isPresent && energy.batteryLevel >= OverdriveThatMatters.ITEM_STORAGE.energyPerOperation()) {
|
||||
state = state.setValue(WorkerState.SEMI_WORKER_STATE, WorkerState.WORKING)
|
||||
} else {
|
||||
state = state.setValue(WorkerState.SEMI_WORKER_STATE, WorkerState.IDLE);
|
||||
state = state.setValue(WorkerState.SEMI_WORKER_STATE, WorkerState.IDLE)
|
||||
}
|
||||
|
||||
if (state != getBlockState()) {
|
||||
level.setBlock(getBlockPos(), state, Block.UPDATE_CLIENTS);
|
||||
if (state !== blockState) {
|
||||
it.setBlock(blockPos, state, Block.UPDATE_CLIENTS)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setChanged() {
|
||||
super.setChanged();
|
||||
@JvmField
|
||||
val drive_slot: MatteryContainer = object : MatteryContainer(this::setChanged, 1) {
|
||||
override fun setChanged(slot: Int, new_state: ItemStack, old_state: ItemStack) {
|
||||
super.setChanged(slot, new_state, old_state)
|
||||
|
||||
if (level != null)
|
||||
OverdriveThatMatters.tickOnceSelf(level, this::updateState);
|
||||
}
|
||||
val level = level
|
||||
if (level != null) {
|
||||
OverdriveThatMatters.tickOnceSelf(level) {
|
||||
if (!isRemoved) {
|
||||
var state = blockState
|
||||
|
||||
public int getIOItemCount(int desired, boolean simulate) {
|
||||
if (!canIOItems())
|
||||
return 0;
|
||||
|
||||
var extracted = energy.extractEnergyInner(MTE_PER_OPERATION.times(desired), true);
|
||||
var modulo = extracted.rem(MTE_PER_OPERATION);
|
||||
|
||||
if (simulate)
|
||||
return modulo.toInt();
|
||||
|
||||
energy.extractEnergyInner(modulo.times(MTE_PER_OPERATION), false);
|
||||
|
||||
return modulo.toInt();
|
||||
}
|
||||
|
||||
public BlockEntityDriveViewer(BlockPos p_155229_, BlockState p_155230_) {
|
||||
super(Registry.BlockEntities.DRIVE_VIEWER, p_155229_, p_155230_);
|
||||
energy = new MatteryMachineEnergyStorage(this, MatteryMachineEnergyStorage.MachineType.WORKER, new Fraction(30_000));
|
||||
}
|
||||
|
||||
private static final TranslatableComponent NAME = new TranslatableComponent("block.overdrive_that_matters.drive_viewer");
|
||||
|
||||
public final MatteryContainer drive_slot = new MatteryContainer(this::setChanged, 1) {
|
||||
@Override
|
||||
public void setChanged(int slot, ItemStack new_state, ItemStack old_state) {
|
||||
super.setChanged(slot, new_state, old_state);
|
||||
|
||||
if (level != null)
|
||||
OverdriveThatMatters.tickOnceSelf(level, (level) -> {
|
||||
if (!isRemoved()) {
|
||||
var state = getBlockState();
|
||||
|
||||
if (new_state.getCapability(MatteryCapability.DRIVE).isPresent()) {
|
||||
state = state.setValue(BlockDriveViewer.DRIVE_PRESENT, true);
|
||||
if (new_state.getCapability(MatteryCapability.DRIVE).isPresent) {
|
||||
state = state.setValue(BlockDriveViewer.DRIVE_PRESENT, true)
|
||||
} else {
|
||||
state = state.setValue(BlockDriveViewer.DRIVE_PRESENT, false);
|
||||
state = state.setValue(BlockDriveViewer.DRIVE_PRESENT, false)
|
||||
}
|
||||
|
||||
if (state != getBlockState()) {
|
||||
level.setBlock(getBlockPos(), state, Block.UPDATE_CLIENTS);
|
||||
if (state !== blockState) {
|
||||
level.setBlock(blockPos, state, Block.UPDATE_CLIENTS)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
protected Component getDefaultDisplayName() {
|
||||
return NAME;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public AbstractContainerMenu createMenu(int containerID, Inventory inventory, Player ply) {
|
||||
return new DriveViewerMenu(containerID, inventory, this);
|
||||
init {
|
||||
energy = MatteryMachineEnergyStorage(this, MatteryMachineEnergyStorage.MachineType.WORKER, Fraction(30000))
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveAdditional(CompoundTag nbt) {
|
||||
super.saveAdditional(nbt);
|
||||
nbt.put("drive_slot", drive_slot.serializeNBT());
|
||||
override fun getDefaultDisplayName(): Component {
|
||||
return NAME
|
||||
}
|
||||
|
||||
@Override
|
||||
public void load(CompoundTag nbt) {
|
||||
super.load(nbt);
|
||||
drive_slot.deserializeNBT(nbt.get("drive_slot"));
|
||||
override fun createMenu(containerID: Int, inventory: Inventory, ply: Player): AbstractContainerMenu? {
|
||||
return DriveViewerMenu(containerID, inventory, this)
|
||||
}
|
||||
|
||||
public static <T extends BlockEntity> void ticker(Level level, BlockPos blockPos, BlockState blockState, T t) {
|
||||
if (t instanceof BlockEntityDriveViewer tile) {
|
||||
tile.batteryChargeLoop();
|
||||
override fun saveAdditional(nbt: CompoundTag) {
|
||||
super.saveAdditional(nbt)
|
||||
nbt["drive_slot"] = drive_slot.serializeNBT()
|
||||
}
|
||||
|
||||
override fun load(nbt: CompoundTag) {
|
||||
super.load(nbt)
|
||||
|
||||
nbt.ifHas("drive_slot") {
|
||||
drive_slot.deserializeNBT(it)
|
||||
}
|
||||
}
|
||||
|
||||
fun tick() {
|
||||
batteryChargeLoop()
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val NAME = TranslatableComponent("block.overdrive_that_matters.drive_viewer")
|
||||
}
|
||||
}
|
@ -0,0 +1,233 @@
|
||||
package ru.dbotthepony.mc.otm.client.screen
|
||||
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.network.chat.TranslatableComponent
|
||||
import net.minecraft.world.entity.player.Inventory
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import ru.dbotthepony.mc.otm.client.screen.panels.*
|
||||
import ru.dbotthepony.mc.otm.client.screen.widget.PowerGaugePanel
|
||||
import ru.dbotthepony.mc.otm.item.ItemPortableCondensationDrive.FilterSettings
|
||||
import ru.dbotthepony.mc.otm.menu.DriveViewerMenu
|
||||
import ru.dbotthepony.mc.otm.menu.DriveViewerMenu.FilterSetPacket
|
||||
import ru.dbotthepony.mc.otm.menu.DriveViewerMenu.FilterSwitchPacket
|
||||
import ru.dbotthepony.mc.otm.network.MatteryNetworking
|
||||
|
||||
class DriveViewerScreen(menu: DriveViewerMenu, inventory: Inventory, title: Component) :
|
||||
MatteryScreen<DriveViewerMenu>(menu, inventory, title) {
|
||||
|
||||
override fun makeMainFrame(): FramePanel {
|
||||
val frame = FramePanel(this, null, 0f, 0f, FRAME_WIDTH, FRAME_HEIGHT, getTitle())
|
||||
|
||||
val views = ArrayList<EditablePanel>()
|
||||
val settings = ArrayList<EditablePanel>()
|
||||
val viewButton = frame.addTab(FramePanel.FrameTabPosition.TOP)
|
||||
val settingsButton = frame.addTab(FramePanel.FrameTabPosition.TOP)
|
||||
|
||||
viewButton.bindOnOpen {
|
||||
for (panel in views) {
|
||||
panel.visible = true
|
||||
}
|
||||
}
|
||||
|
||||
viewButton.bindOnClose {
|
||||
for (panel in views) {
|
||||
panel.visible = false
|
||||
}
|
||||
}
|
||||
|
||||
settingsButton.bindOnOpen {
|
||||
for (panel in settings) {
|
||||
panel.visible = true
|
||||
}
|
||||
}
|
||||
|
||||
settingsButton.bindOnClose {
|
||||
for (panel in settings) {
|
||||
panel.visible = false
|
||||
}
|
||||
}
|
||||
|
||||
views.add(PowerGaugePanel(this, frame, menu.battery_widget, 8f, 16f))
|
||||
views.add(SlotPanel(this, frame, menu.battery_slot, 8f, 67f))
|
||||
views.add(SlotPanel(this, frame, menu.driveSlot, 8f, 85f))
|
||||
|
||||
val grid = GridPanel(this, frame, 28f, 16f, GRID_WIDTH * 18f, GRID_HEIGHT * 18f, GRID_WIDTH, GRID_HEIGHT)
|
||||
|
||||
val scroll_bar = ScrollBarPanel(this, frame, 192f, 14f, 92f)
|
||||
scroll_bar.setupRowMultiplier { menu.view.getItemCount() / GRID_WIDTH }
|
||||
views.add(grid)
|
||||
views.add(scroll_bar)
|
||||
|
||||
for (i in 0 until GRID_WIDTH * GRID_HEIGHT) {
|
||||
object : AbstractSlotPanel(this@DriveViewerScreen, grid, 0f, 0f) {
|
||||
override fun getItemStack(): ItemStack {
|
||||
val index = i + scroll_bar.getScroll(menu.view.getItems().size / GRID_WIDTH)
|
||||
val list = menu.view.getItems()
|
||||
|
||||
return if (index >= list.size) {
|
||||
ItemStack.EMPTY
|
||||
} else list[index].stack
|
||||
}
|
||||
|
||||
override fun mouseScrolledInner(mouse_x: Double, mouse_y: Double, scroll: Double): Boolean {
|
||||
return scroll_bar.mouseScrolledInner(mouse_x, mouse_y, scroll)
|
||||
}
|
||||
|
||||
override fun mouseClickedInner(mouse_x: Double, mouse_y: Double, mouse_click_type: Int): Boolean {
|
||||
val index = i + scroll_bar.getScroll(GRID_WIDTH)
|
||||
menu.view.mouseClick(index, mouse_click_type)
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val dock_left = FlexGridPanel(this, frame, 0f, 0f, 90f, 0f)
|
||||
dock_left.dock = Dock.LEFT
|
||||
dock_left.setDockMargin(4f, 0f, 4f, 0f)
|
||||
|
||||
val grid_filter = FlexGridPanel(this, frame)
|
||||
grid_filter.dock = Dock.FILL
|
||||
settings.add(dock_left)
|
||||
settings.add(grid_filter)
|
||||
|
||||
for (i in 0 until FilterSettings.MAX_FILTERS) {
|
||||
object : AbstractSlotPanel(this@DriveViewerScreen, grid_filter, 0f, 0f) {
|
||||
override fun getItemStack(): ItemStack {
|
||||
val filter = menu.getFilter() ?: return ItemStack.EMPTY
|
||||
return filter.items[i]
|
||||
}
|
||||
|
||||
private var clicking = false
|
||||
|
||||
override fun mouseClickedInner(mouse_x: Double, mouse_y: Double, mouse_click_type: Int): Boolean {
|
||||
clicking = true
|
||||
return true
|
||||
}
|
||||
|
||||
override fun mouseReleasedInner(mouse_x: Double, mouse_y: Double, flag: Int): Boolean {
|
||||
if (clicking)
|
||||
MatteryNetworking.send(null, FilterSetPacket(menu.containerId, i, menu.carried))
|
||||
|
||||
clicking = false
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val no = TranslatableComponent("otm.filter.no")
|
||||
val yes = TranslatableComponent("otm.filter.yes")
|
||||
|
||||
val matchNbt =
|
||||
object : ButtonPanel(this@DriveViewerScreen, dock_left, 0f, 0f, 90f, 20f, TranslatableComponent("otm.filter.match_nbt", no)) {
|
||||
override fun tick() {
|
||||
super.tick()
|
||||
|
||||
val filter = menu.getFilter()
|
||||
if (filter != null) {
|
||||
orCreateWidget.message = TranslatableComponent("otm.filter.match_nbt", if (filter.matchNbt) yes else no)
|
||||
orCreateWidget.active = !isWidgetDisabled
|
||||
} else {
|
||||
orCreateWidget.active = false
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPress() {
|
||||
super.onPress()
|
||||
|
||||
val filter = menu.getFilter()
|
||||
if (filter != null) {
|
||||
MatteryNetworking.send(
|
||||
null,
|
||||
FilterSwitchPacket(
|
||||
menu.containerId,
|
||||
DriveViewerMenu.FilterSwitch.MATCH_NBT,
|
||||
!filter.matchNbt
|
||||
)
|
||||
)
|
||||
disableFor(20)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val matchTag =
|
||||
object : ButtonPanel(this@DriveViewerScreen, dock_left, 0f, 0f, 90f, 20f, TranslatableComponent("otm.filter.match_tag", no)) {
|
||||
override fun tick() {
|
||||
super.tick()
|
||||
|
||||
val filter = menu.getFilter()
|
||||
if (filter != null) {
|
||||
orCreateWidget.message =
|
||||
TranslatableComponent("otm.filter.match_tag", if (filter.matchTag) yes else no)
|
||||
orCreateWidget.active = !isWidgetDisabled
|
||||
} else {
|
||||
orCreateWidget.active = false
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPress() {
|
||||
super.onPress()
|
||||
|
||||
val filter = menu.getFilter()
|
||||
if (filter != null) {
|
||||
MatteryNetworking.send(
|
||||
null,
|
||||
FilterSwitchPacket(
|
||||
menu.containerId,
|
||||
DriveViewerMenu.FilterSwitch.MATCH_TAG,
|
||||
!filter.matchTag
|
||||
)
|
||||
)
|
||||
disableFor(20)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val blacklist =
|
||||
object : ButtonPanel(this@DriveViewerScreen, dock_left, 0f, 0f, 90f, 20f, TranslatableComponent("otm.filter.blacklist", no)) {
|
||||
override fun tick() {
|
||||
super.tick()
|
||||
|
||||
val filter = menu.getFilter()
|
||||
if (filter != null) {
|
||||
orCreateWidget.message = TranslatableComponent("otm.filter.blacklist", if (filter.isBlacklist) yes else no)
|
||||
orCreateWidget.active = !isWidgetDisabled
|
||||
} else {
|
||||
orCreateWidget.active = false
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPress() {
|
||||
super.onPress()
|
||||
val filter = menu.getFilter()
|
||||
if (filter != null) {
|
||||
MatteryNetworking.send(
|
||||
null,
|
||||
FilterSwitchPacket(
|
||||
menu.containerId,
|
||||
DriveViewerMenu.FilterSwitch.BLACKLIST,
|
||||
!filter.isBlacklist
|
||||
)
|
||||
)
|
||||
disableFor(20)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
matchNbt.setDockMargin(0f, 4f, 0f, 0f)
|
||||
matchTag.setDockMargin(0f, 4f, 0f, 0f)
|
||||
blacklist.setDockMargin(0f, 4f, 0f, 0f)
|
||||
|
||||
for (panel in settings) {
|
||||
panel.visible = false
|
||||
}
|
||||
|
||||
return frame
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val FRAME_WIDTH = 210f
|
||||
const val FRAME_HEIGHT = 110f
|
||||
const val GRID_WIDTH = 9
|
||||
const val GRID_HEIGHT = 5
|
||||
}
|
||||
}
|
@ -17,16 +17,16 @@ class ItemMonitorScreen(menu: ItemMonitorMenu, inventory: Inventory, title: Comp
|
||||
SlotPanel(this, frame, menu.battery_slot, 8f, 80f)
|
||||
|
||||
val scrollBar = ScrollBarPanel(this, frame, 192f, 14f, 92f)
|
||||
scrollBar.setupRowMultiplier { menu.view.items.size / GRID_WIDTH }
|
||||
scrollBar.setupRowMultiplier { menu.view.getItemCount() / GRID_WIDTH }
|
||||
|
||||
val gridPanel = GridPanel(this, frame, 28f, 16f, GRID_WIDTH * 18f, GRID_HEIGHT * 18f, GRID_WIDTH, GRID_HEIGHT)
|
||||
|
||||
for (i in 0 until GRID_WIDTH * GRID_HEIGHT) {
|
||||
object : AbstractSlotPanel(this@ItemMonitorScreen, gridPanel) {
|
||||
override fun getItemStack(): ItemStack {
|
||||
val index = i + scrollBar.getScroll(menu.view.items.size / GRID_WIDTH)
|
||||
val list = menu.view.items
|
||||
return if (index >= list.size) ItemStack.EMPTY else list[index].stack()
|
||||
val index = i + scrollBar.getScroll(menu.view.getItemCount() / GRID_WIDTH)
|
||||
val list = menu.view.getItems()
|
||||
return if (index >= list.size) ItemStack.EMPTY else list[index].stack
|
||||
}
|
||||
|
||||
override fun mouseScrolledInner(mouse_x: Double, mouse_y: Double, scroll: Double): Boolean {
|
||||
|
241
src/main/kotlin/ru/dbotthepony/mc/otm/menu/DriveViewerMenu.kt
Normal file
241
src/main/kotlin/ru/dbotthepony/mc/otm/menu/DriveViewerMenu.kt
Normal file
@ -0,0 +1,241 @@
|
||||
package ru.dbotthepony.mc.otm.menu
|
||||
|
||||
import net.minecraft.network.FriendlyByteBuf
|
||||
import net.minecraft.world.SimpleContainer
|
||||
import net.minecraft.world.entity.player.Inventory
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraftforge.energy.CapabilityEnergy
|
||||
import net.minecraftforge.network.NetworkEvent
|
||||
import ru.dbotthepony.mc.otm.Registry
|
||||
import ru.dbotthepony.mc.otm.block.entity.BlockEntityDriveViewer
|
||||
import ru.dbotthepony.mc.otm.capability.MatteryCapability
|
||||
import ru.dbotthepony.mc.otm.capability.drive.IMatteryDrive
|
||||
import ru.dbotthepony.mc.otm.item.ItemPortableCondensationDrive
|
||||
import ru.dbotthepony.mc.otm.item.ItemPortableCondensationDrive.FilterSettings
|
||||
import ru.dbotthepony.mc.otm.menu.data.INetworkedItemViewSupplier
|
||||
import ru.dbotthepony.mc.otm.menu.data.NetworkedItemView
|
||||
import ru.dbotthepony.mc.otm.storage.ItemStackWrapper
|
||||
import ru.dbotthepony.mc.otm.storage.PoweredVirtualComponent
|
||||
import java.util.function.Supplier
|
||||
|
||||
class DriveViewerMenu @JvmOverloads constructor(
|
||||
containerID: Int,
|
||||
inventory: Inventory,
|
||||
tile: BlockEntityDriveViewer? = null
|
||||
) : PoweredMatteryMenu(
|
||||
Registry.Menus.DRIVE_VIEWER, containerID, inventory, tile
|
||||
), INetworkedItemViewSupplier {
|
||||
@JvmField val view: NetworkedItemView
|
||||
private val powered: PoweredVirtualComponent<ItemStackWrapper>?
|
||||
@JvmField val driveSlot: MatterySlot
|
||||
private var lastDrive: IMatteryDrive<ItemStackWrapper>? = null
|
||||
|
||||
override fun getNetworkedItemView() = view
|
||||
|
||||
init {
|
||||
val container = if (tile != null) tile.drive_slot else SimpleContainer(1)
|
||||
|
||||
driveSlot = object : MatterySlot(container, 0) {
|
||||
override fun mayPlace(stack: ItemStack): Boolean {
|
||||
return stack.getCapability(MatteryCapability.DRIVE).isPresent
|
||||
}
|
||||
}
|
||||
|
||||
view = NetworkedItemView(inventory.player, this, tile == null)
|
||||
|
||||
if (tile != null) {
|
||||
powered = PoweredVirtualComponent(
|
||||
ItemStackWrapper::class.java,
|
||||
tile.getCapability(MatteryCapability.ENERGY).resolve().get()
|
||||
)
|
||||
|
||||
view.setComponent(powered)
|
||||
} else {
|
||||
powered = null
|
||||
}
|
||||
|
||||
addSlot(driveSlot)
|
||||
addBatterySlot()
|
||||
addInventorySlots()
|
||||
}
|
||||
|
||||
override fun broadcastChanges() {
|
||||
super.broadcastChanges()
|
||||
|
||||
if (tile != null) {
|
||||
val itemStack = (tile as BlockEntityDriveViewer).drive_slot.getItem(0)
|
||||
|
||||
val prev = lastDrive
|
||||
lastDrive = null
|
||||
|
||||
if (!itemStack.isEmpty) {
|
||||
itemStack.getCapability(MatteryCapability.DRIVE).ifPresent {
|
||||
if (it.storageIdentity() == ItemStackWrapper::class.java) {
|
||||
lastDrive = it as IMatteryDrive<ItemStackWrapper>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (prev != lastDrive) {
|
||||
if (prev != null)
|
||||
powered!!.remove(prev)
|
||||
|
||||
view.clear()
|
||||
|
||||
if (lastDrive != null)
|
||||
powered!!.add(lastDrive!!)
|
||||
}
|
||||
|
||||
view.network()
|
||||
}
|
||||
}
|
||||
|
||||
override fun getWorkingSlotStart(): Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
override fun getWorkingSlotEnd(): Int {
|
||||
return 2
|
||||
}
|
||||
|
||||
override fun removed(p_38940_: Player) {
|
||||
super.removed(p_38940_)
|
||||
|
||||
if (powered != null)
|
||||
lastDrive?.removeListener(powered)
|
||||
|
||||
view.clear()
|
||||
}
|
||||
|
||||
override fun quickMoveStack(ply: Player, slot_index: Int): ItemStack {
|
||||
val slot = slots[slot_index]
|
||||
val item = slot.item
|
||||
|
||||
if (item.isEmpty || item.getCapability(MatteryCapability.DRIVE).isPresent || item.getCapability(CapabilityEnergy.ENERGY).isPresent)
|
||||
return super.quickMoveStack(ply, slot_index)
|
||||
|
||||
val powered = powered
|
||||
if (lastDrive == null || powered == null)
|
||||
return ItemStack.EMPTY
|
||||
|
||||
val remaining = powered.insertStack(ItemStackWrapper(item), false)
|
||||
|
||||
if (remaining.count.toInt() == item.count)
|
||||
return ItemStack.EMPTY
|
||||
|
||||
if (remaining.isEmpty()) {
|
||||
val copy = item.copy()
|
||||
slot.set(ItemStack.EMPTY)
|
||||
return copy
|
||||
}
|
||||
|
||||
val copy = item.copy()
|
||||
item.shrink(remaining.count.toInt())
|
||||
slot.setChanged()
|
||||
return copy
|
||||
}
|
||||
|
||||
enum class FilterSwitch {
|
||||
MATCH_NBT, MATCH_TAG, BLACKLIST
|
||||
}
|
||||
|
||||
fun getFilter(): FilterSettings? {
|
||||
if (driveSlot.item.isEmpty)
|
||||
return null
|
||||
|
||||
val item = driveSlot.item.item
|
||||
return if (item is ItemPortableCondensationDrive) item.getFilterSettings(driveSlot.item) else null
|
||||
}
|
||||
|
||||
class FilterSetPacket(val id: Int, val slot: Int, val value: ItemStack) {
|
||||
fun write(buffer: FriendlyByteBuf) {
|
||||
buffer.writeInt(id)
|
||||
buffer.writeInt(slot)
|
||||
buffer.writeItem(value)
|
||||
}
|
||||
|
||||
fun play(context: Supplier<NetworkEvent.Context>) {
|
||||
context.get().packetHandled = true
|
||||
|
||||
if (slot < 0 || slot >= FilterSettings.MAX_FILTERS)
|
||||
return
|
||||
|
||||
if (value.count > 1)
|
||||
value.count = 1
|
||||
|
||||
context.get().enqueueWork {
|
||||
val ply = context.get().sender!!
|
||||
val menu = ply.containerMenu
|
||||
|
||||
if (menu is DriveViewerMenu && menu.containerId == id) {
|
||||
if (menu.driveSlot.item.isEmpty)
|
||||
return@enqueueWork
|
||||
|
||||
val itemStack = menu.driveSlot.item
|
||||
val item = itemStack.item
|
||||
|
||||
if (item is ItemPortableCondensationDrive) {
|
||||
val filter = item.getFilterSettings(itemStack)
|
||||
filter.items[slot] = value
|
||||
filter.serializeNBT(itemStack)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun read(buffer: FriendlyByteBuf): FilterSetPacket {
|
||||
return FilterSetPacket(buffer.readInt(), buffer.readInt(), buffer.readItem())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class FilterSwitchPacket(val id: Int, val type: FilterSwitch, val value: Boolean) {
|
||||
fun write(buffer: FriendlyByteBuf) {
|
||||
buffer.writeInt(id)
|
||||
buffer.writeEnum(type)
|
||||
buffer.writeBoolean(value)
|
||||
}
|
||||
|
||||
fun play(context: Supplier<NetworkEvent.Context>) {
|
||||
context.get().packetHandled = true
|
||||
context.get().enqueueWork {
|
||||
val ply = context.get().sender!!
|
||||
val menu = ply.containerMenu
|
||||
|
||||
if (menu is DriveViewerMenu && menu.containerId == id) {
|
||||
val settings = menu.getFilter() ?: return@enqueueWork
|
||||
|
||||
when (type) {
|
||||
FilterSwitch.MATCH_NBT -> {
|
||||
settings.matchNbt = value
|
||||
}
|
||||
|
||||
FilterSwitch.MATCH_TAG -> {
|
||||
settings.matchTag = value
|
||||
}
|
||||
|
||||
FilterSwitch.BLACKLIST -> {
|
||||
settings.isBlacklist = value
|
||||
}
|
||||
}
|
||||
|
||||
settings.serializeNBT(menu.driveSlot.item)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun read(buffer: FriendlyByteBuf): FilterSwitchPacket {
|
||||
return FilterSwitchPacket(
|
||||
buffer.readInt(),
|
||||
buffer.readEnum(FilterSwitch::class.java),
|
||||
buffer.readBoolean()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -2,6 +2,7 @@ package ru.dbotthepony.mc.otm.menu
|
||||
|
||||
import net.minecraft.world.entity.player.Inventory
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import ru.dbotthepony.mc.otm.Registry
|
||||
import ru.dbotthepony.mc.otm.block.entity.BlockEntityItemMonitor
|
||||
import ru.dbotthepony.mc.otm.capability.IMatteryEnergyStorage
|
||||
@ -58,4 +59,12 @@ class ItemMonitorMenu @JvmOverloads constructor(
|
||||
override fun getWorkingSlotEnd(): Int {
|
||||
return 1
|
||||
}
|
||||
|
||||
override fun quickMoveStack(ply: Player, slot_index: Int): ItemStack {
|
||||
if (slot_index in inventorySlotIndexStart..inventorySlotIndexEnd) {
|
||||
|
||||
}
|
||||
|
||||
return super.quickMoveStack(ply, slot_index)
|
||||
}
|
||||
}
|
||||
|
@ -9,32 +9,26 @@ import ru.dbotthepony.mc.otm.menu.widget.AbstractWidget
|
||||
import java.util.function.Consumer
|
||||
|
||||
@JvmRecord
|
||||
data class MoveResult(val merge_occured: Boolean, val remaining: ItemStack, val changed_slots: Set<Slot>)
|
||||
data class MoveResult(val mergeOccurred: Boolean, val remaining: ItemStack, val changed_slots: Set<Slot>)
|
||||
|
||||
abstract class MatteryMenu protected @JvmOverloads constructor(
|
||||
p_38851_: MenuType<*>?,
|
||||
p_38852_: Int,
|
||||
@JvmField val inventory: Inventory,
|
||||
tile: BlockEntity? = null
|
||||
@JvmField val tile: BlockEntity? = null
|
||||
) : AbstractContainerMenu(p_38851_, p_38852_) {
|
||||
@JvmField
|
||||
val tile: BlockEntity?
|
||||
|
||||
@JvmField
|
||||
val ply: Player = inventory.player
|
||||
|
||||
@JvmField
|
||||
val mattery_widgets = ArrayList<AbstractWidget>()
|
||||
val matteryWidgets = ArrayList<AbstractWidget>()
|
||||
|
||||
@JvmField
|
||||
val inventory_slots = ArrayList<MatterySlot>()
|
||||
val inventorySlots = ArrayList<MatterySlot>()
|
||||
|
||||
@JvmField
|
||||
val main_slots = ArrayList<MatterySlot>()
|
||||
|
||||
@JvmField
|
||||
protected val locked_inventory_slots: MutableSet<Int> = HashSet()
|
||||
protected fun isInventorySlotLocked(index: Int): Boolean = locked_inventory_slots.contains(index)
|
||||
protected val lockedInventorySlots: MutableSet<Int> = HashSet()
|
||||
protected open fun isInventorySlotLocked(index: Int): Boolean = lockedInventorySlots.contains(index)
|
||||
|
||||
@JvmField
|
||||
protected var _synchronizer: ContainerSynchronizer? = null
|
||||
@ -45,27 +39,17 @@ abstract class MatteryMenu protected @JvmOverloads constructor(
|
||||
}
|
||||
|
||||
fun addWidget(widget: AbstractWidget, consumer: Consumer<Consumer<ContainerData>>) {
|
||||
if (!mattery_widgets.contains(widget)) {
|
||||
mattery_widgets.add(widget)
|
||||
if (!matteryWidgets.contains(widget)) {
|
||||
matteryWidgets.add(widget)
|
||||
consumer.accept(Consumer { p_38885_: ContainerData -> addDataSlots(p_38885_) })
|
||||
}
|
||||
}
|
||||
|
||||
fun addMainSlot(slot: MatterySlot): MatterySlot {
|
||||
addSlot(slot)
|
||||
main_slots.add(slot)
|
||||
return slot
|
||||
}
|
||||
@JvmField
|
||||
protected var inventorySlotIndexStart = 0
|
||||
|
||||
@JvmField
|
||||
protected var inventory_slot_index_start = 0
|
||||
|
||||
@JvmField
|
||||
protected var inventory_slot_index_end = 0
|
||||
|
||||
init {
|
||||
this.tile = tile
|
||||
}
|
||||
protected var inventorySlotIndexEnd = 0
|
||||
|
||||
@JvmOverloads
|
||||
protected fun addInventorySlots(offset: Int = 97) {
|
||||
@ -83,12 +67,12 @@ abstract class MatteryMenu protected @JvmOverloads constructor(
|
||||
}
|
||||
}
|
||||
|
||||
inventory_slots.add(slot)
|
||||
inventorySlots.add(slot)
|
||||
addSlot(slot)
|
||||
|
||||
if (first) {
|
||||
first = false
|
||||
inventory_slot_index_start = slot.index
|
||||
inventorySlotIndexStart = slot.index
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -107,14 +91,14 @@ abstract class MatteryMenu protected @JvmOverloads constructor(
|
||||
}
|
||||
|
||||
addSlot(last)
|
||||
inventory_slots.add(last)
|
||||
inventorySlots.add(last)
|
||||
}
|
||||
|
||||
inventory_slot_index_end = last!!.index
|
||||
inventorySlotIndexEnd = last!!.index
|
||||
}
|
||||
|
||||
override fun broadcastChanges() {
|
||||
for (widget in mattery_widgets) {
|
||||
for (widget in matteryWidgets) {
|
||||
widget.updateServer()
|
||||
}
|
||||
|
||||
@ -122,7 +106,7 @@ abstract class MatteryMenu protected @JvmOverloads constructor(
|
||||
}
|
||||
|
||||
override fun broadcastFullState() {
|
||||
for (widget in mattery_widgets) {
|
||||
for (widget in matteryWidgets) {
|
||||
widget.updateServer()
|
||||
}
|
||||
|
||||
@ -148,7 +132,7 @@ abstract class MatteryMenu protected @JvmOverloads constructor(
|
||||
// It shall return item stack that got moved
|
||||
override fun quickMoveStack(ply: Player, slot_index: Int): ItemStack {
|
||||
// this.moveItemStackTo(ItemStack, int start_slot_index, int end_slot_index, boolean iteration_order)
|
||||
// returns boolean, telling whenever ItemStack was modified (moved or sharnk)
|
||||
// returns boolean, telling whenever ItemStack was modified (moved or shrank)
|
||||
// false means nothing happened
|
||||
// Last boolean determine order of slot iteration, where:
|
||||
// if TRUE, iteration order is end_slot_index -> start_slot_index
|
||||
@ -161,26 +145,26 @@ abstract class MatteryMenu protected @JvmOverloads constructor(
|
||||
}
|
||||
|
||||
var moved = ItemStack.EMPTY
|
||||
val get_slot = slots[slot_index]
|
||||
val initialSlot = slots[slot_index]
|
||||
|
||||
if (get_slot.hasItem()) {
|
||||
val slot_item = get_slot.item
|
||||
moved = slot_item.copy()
|
||||
if (initialSlot.hasItem()) {
|
||||
val initialItem = initialSlot.item
|
||||
moved = initialItem.copy()
|
||||
|
||||
if (slot_index < inventory_slot_index_start) {
|
||||
if (slot_index < inventorySlotIndexStart) {
|
||||
// Moving FROM machine TO inventory
|
||||
if (!moveItemStackTo(slot_item, inventory_slot_index_start, inventory_slot_index_end + 1, false)) {
|
||||
if (!moveItemStackTo(initialItem, inventorySlotIndexStart, inventorySlotIndexEnd + 1, false)) {
|
||||
return ItemStack.EMPTY
|
||||
}
|
||||
} else if (!moveItemStackTo(slot_item, start, end, false)) {
|
||||
} else if (!moveItemStackTo(initialItem, start, end, false)) {
|
||||
// Moving FROM inventory TO machine
|
||||
return ItemStack.EMPTY
|
||||
}
|
||||
|
||||
if (slot_item.isEmpty) {
|
||||
get_slot.set(ItemStack.EMPTY)
|
||||
if (initialItem.isEmpty) {
|
||||
initialSlot.set(ItemStack.EMPTY)
|
||||
} else {
|
||||
get_slot.setChanged()
|
||||
initialSlot.setChanged()
|
||||
}
|
||||
}
|
||||
|
||||
@ -188,12 +172,12 @@ abstract class MatteryMenu protected @JvmOverloads constructor(
|
||||
}
|
||||
|
||||
fun quickMoveToInventory(stack: ItemStack, simulate: Boolean): MoveResult {
|
||||
return if (inventory_slot_index_start == 0 && inventory_slot_index_end == 0) {
|
||||
MoveResult(false, stack, java.util.Set.of<Slot>())
|
||||
return if (inventorySlotIndexStart == 0 && inventorySlotIndexEnd == 0) {
|
||||
MoveResult(false, stack, setOf())
|
||||
} else customMoveItemStackTo(
|
||||
stack,
|
||||
inventory_slot_index_start,
|
||||
inventory_slot_index_end + 1,
|
||||
inventorySlotIndexStart,
|
||||
inventorySlotIndexEnd + 1,
|
||||
false,
|
||||
simulate
|
||||
)
|
||||
@ -205,27 +189,27 @@ abstract class MatteryMenu protected @JvmOverloads constructor(
|
||||
final_slot: Int,
|
||||
reverse_direction: Boolean
|
||||
): Boolean {
|
||||
val move_result = customMoveItemStackTo(stack_to_move, initial_slot, final_slot, reverse_direction, false)
|
||||
val remaining: ItemStack = move_result.remaining
|
||||
val moveResult = customMoveItemStackTo(stack_to_move, initial_slot, final_slot, reverse_direction, false)
|
||||
val remaining: ItemStack = moveResult.remaining
|
||||
if (remaining.count == stack_to_move.count) return false
|
||||
stack_to_move.count = remaining.count
|
||||
return move_result.merge_occured
|
||||
return moveResult.mergeOccurred
|
||||
}
|
||||
|
||||
protected fun customMoveItemStackTo(
|
||||
_stack_to_move: ItemStack,
|
||||
stackToMove1: ItemStack,
|
||||
initial_slot: Int,
|
||||
final_slot: Int,
|
||||
reverse_direction: Boolean,
|
||||
simulate: Boolean
|
||||
): MoveResult {
|
||||
var merge_occured = false
|
||||
var mergeOccurred = false
|
||||
var i = if (reverse_direction) final_slot - 1 else initial_slot
|
||||
val changed = HashSet<Slot>()
|
||||
val stack_to_move = _stack_to_move.copy()
|
||||
val stackToMove = stackToMove1.copy()
|
||||
|
||||
if (stack_to_move.isStackable) {
|
||||
while (!stack_to_move.isEmpty) {
|
||||
if (stackToMove.isStackable) {
|
||||
while (!stackToMove.isEmpty) {
|
||||
if (reverse_direction) {
|
||||
if (i < initial_slot) {
|
||||
break
|
||||
@ -237,29 +221,29 @@ abstract class MatteryMenu protected @JvmOverloads constructor(
|
||||
val slot = slots[i]
|
||||
val slot_stack = slot.item
|
||||
|
||||
if (!slot_stack.isEmpty && ItemStack.isSameItemSameTags(stack_to_move, slot_stack)) {
|
||||
val j = slot_stack.count + stack_to_move.count
|
||||
val maxSize = slot.getMaxStackSize(stack_to_move)
|
||||
if (!slot_stack.isEmpty && ItemStack.isSameItemSameTags(stackToMove, slot_stack)) {
|
||||
val j = slot_stack.count + stackToMove.count
|
||||
val maxSize = slot.getMaxStackSize(stackToMove)
|
||||
|
||||
if (j <= maxSize) {
|
||||
stack_to_move.count = 0
|
||||
stackToMove.count = 0
|
||||
|
||||
if (!simulate) {
|
||||
slot_stack.count = j
|
||||
slot.setChanged()
|
||||
}
|
||||
|
||||
merge_occured = true
|
||||
mergeOccurred = true
|
||||
changed.add(slot)
|
||||
} else if (slot_stack.count < maxSize) {
|
||||
stack_to_move.shrink(maxSize - slot_stack.count)
|
||||
stackToMove.shrink(maxSize - slot_stack.count)
|
||||
|
||||
if (!simulate) {
|
||||
slot_stack.count = maxSize
|
||||
slot.setChanged()
|
||||
}
|
||||
|
||||
merge_occured = true
|
||||
mergeOccurred = true
|
||||
changed.add(slot)
|
||||
}
|
||||
}
|
||||
@ -268,7 +252,7 @@ abstract class MatteryMenu protected @JvmOverloads constructor(
|
||||
}
|
||||
}
|
||||
|
||||
if (!stack_to_move.isEmpty) {
|
||||
if (!stackToMove.isEmpty) {
|
||||
i = if (reverse_direction) final_slot - 1 else initial_slot
|
||||
|
||||
while (true) {
|
||||
@ -283,18 +267,18 @@ abstract class MatteryMenu protected @JvmOverloads constructor(
|
||||
val slot = slots[i]
|
||||
val slot_stack = slot.item
|
||||
|
||||
if (slot_stack.isEmpty && slot.mayPlace(stack_to_move)) {
|
||||
if (slot_stack.isEmpty && slot.mayPlace(stackToMove)) {
|
||||
if (!simulate) {
|
||||
if (stack_to_move.count > slot.maxStackSize) {
|
||||
slot.set(stack_to_move.split(slot.maxStackSize))
|
||||
if (stackToMove.count > slot.maxStackSize) {
|
||||
slot.set(stackToMove.split(slot.maxStackSize))
|
||||
} else {
|
||||
slot.set(stack_to_move.split(stack_to_move.count))
|
||||
slot.set(stackToMove.split(stackToMove.count))
|
||||
}
|
||||
|
||||
slot.setChanged()
|
||||
}
|
||||
|
||||
merge_occured = true
|
||||
mergeOccurred = true
|
||||
changed.add(slot)
|
||||
break
|
||||
}
|
||||
@ -302,6 +286,7 @@ abstract class MatteryMenu protected @JvmOverloads constructor(
|
||||
i += if (reverse_direction) -1 else 1
|
||||
}
|
||||
}
|
||||
return MoveResult(merge_occured, stack_to_move, changed)
|
||||
|
||||
return MoveResult(mergeOccurred, stackToMove, changed)
|
||||
}
|
||||
}
|
@ -0,0 +1,213 @@
|
||||
package ru.dbotthepony.mc.otm.menu.data
|
||||
|
||||
import com.mojang.blaze3d.platform.InputConstants
|
||||
import net.minecraft.client.gui.screens.Screen
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.inventory.ClickAction
|
||||
import net.minecraft.world.inventory.ClickType
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraftforge.network.PacketDistributor
|
||||
import ru.dbotthepony.mc.otm.core.Fraction
|
||||
import ru.dbotthepony.mc.otm.menu.MatteryMenu
|
||||
import ru.dbotthepony.mc.otm.network.MatteryNetworking
|
||||
import ru.dbotthepony.mc.otm.network.SetCarriedPacket
|
||||
import ru.dbotthepony.mc.otm.storage.IStorageComponent
|
||||
import ru.dbotthepony.mc.otm.storage.IStorageListener
|
||||
import ru.dbotthepony.mc.otm.storage.IStorageView
|
||||
import ru.dbotthepony.mc.otm.storage.ItemStackWrapper
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* Creates a virtual, slotless container for Player's interaction with.
|
||||
*/
|
||||
open class NetworkedItemView(val ply: Player, val menu: MatteryMenu, val remote: Boolean) : IStorageListener<ItemStackWrapper> {
|
||||
@JvmRecord
|
||||
data class NetworkedItem @JvmOverloads constructor(val id: Int, val stack: ItemStack, val upstreamId: UUID? = null)
|
||||
|
||||
@JvmField protected var next_stack_id = 0
|
||||
@JvmField val state = HashMap<Int, NetworkedItem>()
|
||||
|
||||
@JvmField protected val upstream_state = HashMap<UUID, NetworkedItem>()
|
||||
@JvmField protected val backlog = ArrayList<Any>()
|
||||
|
||||
operator fun get(id: Int): NetworkedItem? {
|
||||
return state[id]
|
||||
}
|
||||
|
||||
private var cachedView: List<NetworkedItem>? = null
|
||||
@JvmField protected var provider: IStorageComponent<ItemStackWrapper>? = null
|
||||
|
||||
fun mouseClick(index: Int, mouse_click_type: Int) {
|
||||
val list = getItems()
|
||||
|
||||
val action =
|
||||
if (mouse_click_type == InputConstants.MOUSE_BUTTON_LEFT) ClickAction.PRIMARY else ClickAction.SECONDARY
|
||||
|
||||
val type =
|
||||
if (mouse_click_type == InputConstants.MOUSE_BUTTON_MIDDLE) ClickType.CLONE else if (Screen.hasShiftDown()) ClickType.QUICK_MOVE else ClickType.PICKUP
|
||||
|
||||
MatteryNetworking.send(
|
||||
null,
|
||||
InteractPacket(menu.containerId, if (index >= list.size) -1 else list[index].id, type, action)
|
||||
)
|
||||
}
|
||||
|
||||
fun setComponent(provider: IStorageComponent<ItemStackWrapper>?) {
|
||||
if (provider === this.provider) return
|
||||
|
||||
this.provider?.removeListenerAuto(this)
|
||||
this.provider = provider
|
||||
provider?.addListenerAuto(this)
|
||||
}
|
||||
|
||||
fun removed() {
|
||||
provider?.removeListenerAuto(this)
|
||||
}
|
||||
|
||||
fun clearCache() {
|
||||
cachedView = null
|
||||
}
|
||||
|
||||
fun getItems(): List<NetworkedItem> {
|
||||
return if (cachedView != null) cachedView!! else java.util.List.copyOf(state.values).also { cachedView = it }
|
||||
}
|
||||
|
||||
fun getItemCount(): Int {
|
||||
return state.values.size
|
||||
}
|
||||
|
||||
override fun addObject(stack: ItemStackWrapper, id: UUID, provider: IStorageView<ItemStackWrapper>) = addObject(stack.stack, id)
|
||||
override fun changeObject(id: UUID, newCount: Fraction) = changeObject(id, newCount.toInt())
|
||||
|
||||
protected fun network(fn: () -> Any) {
|
||||
if (!remote) {
|
||||
backlog.add(fn())
|
||||
}
|
||||
}
|
||||
|
||||
override fun removeObject(id: UUID) {
|
||||
val get = upstream_state[id] ?: throw IllegalStateException("Unknown ItemStack with upstream id $id!")
|
||||
upstream_state.remove(id)
|
||||
state.remove(get.id)
|
||||
network { StackRemovePacket(menu.containerId, get.id) }
|
||||
clearCache()
|
||||
}
|
||||
|
||||
fun addObject(stack: ItemStack, id_upstream: UUID) {
|
||||
check(!upstream_state.containsKey(id_upstream)) { "Already tracking ItemStack with upstream id $id_upstream!" }
|
||||
|
||||
val state = NetworkedItem(next_stack_id++, stack.copy(), id_upstream)
|
||||
|
||||
this.state[state.id] = state
|
||||
upstream_state[id_upstream] = state
|
||||
network { StackAddPacket(menu.containerId, state.id, stack) }
|
||||
clearCache()
|
||||
}
|
||||
|
||||
fun changeObject(id_upstream: UUID, new_count: Int) {
|
||||
val get = upstream_state[id_upstream] ?: throw IllegalStateException("Unknown ItemStack with upstream id $id_upstream!")
|
||||
get.stack.count = new_count
|
||||
network { StackChangePacket(menu.containerId, get.id, new_count) }
|
||||
clearCache()
|
||||
}
|
||||
|
||||
fun clear() {
|
||||
clearCache()
|
||||
upstream_state.clear()
|
||||
state.clear()
|
||||
|
||||
if (!remote) {
|
||||
backlog.clear()
|
||||
backlog.add(ClearPacket(menu.containerId))
|
||||
}
|
||||
}
|
||||
|
||||
fun network() {
|
||||
check(!remote) { "Not a server" }
|
||||
val consumer = PacketDistributor.PLAYER.with { ply as ServerPlayer }
|
||||
for (packet in backlog) MatteryNetworking.CHANNEL.send(consumer, packet)
|
||||
backlog.clear()
|
||||
}
|
||||
|
||||
fun playerInteract(packet: InteractPacket) {
|
||||
val provider = provider ?: return
|
||||
|
||||
val click = packet.click()
|
||||
val action = packet.action()
|
||||
val stack_id = packet.stack_id()
|
||||
|
||||
if (click == ClickType.CLONE) {
|
||||
if (stack_id < 0 || !ply.abilities.instabuild) return
|
||||
|
||||
val state = get(stack_id) ?: return
|
||||
val copy: ItemStack = state.stack.copy()
|
||||
|
||||
copy.count = Math.min(copy.count, copy.maxStackSize)
|
||||
ply.containerMenu.carried = copy
|
||||
MatteryNetworking.send(ply as ServerPlayer, SetCarriedPacket(ply.containerMenu.carried))
|
||||
ply.containerMenu.setRemoteCarried(ply.containerMenu.carried.copy())
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if (click == ClickType.QUICK_MOVE && stack_id > -1) {
|
||||
val state = get(stack_id) ?: return
|
||||
|
||||
val amount =
|
||||
if (action == ClickAction.PRIMARY)
|
||||
state.stack.maxStackSize
|
||||
else
|
||||
Math.max(1, state.stack.maxStackSize / 2)
|
||||
|
||||
val extracted = provider.extractStack(state.upstreamId!!, amount, true)
|
||||
|
||||
if (!extracted.isEmpty()) {
|
||||
val (_, remaining) = menu.quickMoveToInventory(extracted.stack, false)
|
||||
|
||||
if (remaining.count != extracted.stack.count) {
|
||||
provider.extractStack(state.upstreamId, extracted.stack.count - remaining.count, false)
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if (!menu.carried.isEmpty && click != ClickType.QUICK_MOVE) {
|
||||
// try to put
|
||||
if (action == ClickAction.PRIMARY) {
|
||||
val carried = menu.carried
|
||||
val amount = carried.count
|
||||
|
||||
if (amount == carried.count) {
|
||||
val (stack) = provider.insertStack(ItemStackWrapper(menu.carried), false)
|
||||
menu.carried = stack
|
||||
MatteryNetworking.send(ply as ServerPlayer, SetCarriedPacket(menu.carried))
|
||||
menu.setRemoteCarried(menu.carried.copy())
|
||||
}
|
||||
} else {
|
||||
val copy = menu.carried.copy()
|
||||
copy.count = 1
|
||||
|
||||
if (provider.insertStack(ItemStackWrapper(copy), false).isEmpty()) {
|
||||
menu.carried.shrink(1)
|
||||
MatteryNetworking.send(ply as ServerPlayer, SetCarriedPacket(menu.carried))
|
||||
menu.setRemoteCarried(menu.carried.copy())
|
||||
}
|
||||
}
|
||||
} else if (stack_id > -1) {
|
||||
val state = get(stack_id) ?: return
|
||||
|
||||
val amount =
|
||||
if (action == ClickAction.PRIMARY)
|
||||
state.stack.maxStackSize
|
||||
else
|
||||
Math.max(1, state.stack.maxStackSize / 2)
|
||||
|
||||
val extracted = provider.extractStack(state.upstreamId!!, amount, false)
|
||||
menu.carried = extracted.stack
|
||||
MatteryNetworking.send(ply as ServerPlayer, SetCarriedPacket(menu.carried))
|
||||
menu.setRemoteCarried(menu.carried.copy())
|
||||
}
|
||||
}
|
||||
}
|
@ -84,6 +84,8 @@ interface IStorageView<T : IStorageStack> : IStorageTrigger<T> {
|
||||
* @return copy of object, with amount of units actually extracted
|
||||
*/
|
||||
fun extractStack(id: UUID, amount: Fraction, simulate: Boolean): T
|
||||
fun extractStack(id: UUID, amount: Int, simulate: Boolean): T = extractStack(id, Fraction(amount), simulate)
|
||||
fun extractStack(id: UUID, amount: Long, simulate: Boolean): T = extractStack(id, Fraction(amount), simulate)
|
||||
|
||||
/**
|
||||
* Designed for views, for extraction with less computation overhead caused by
|
||||
@ -98,6 +100,9 @@ interface IStorageView<T : IStorageStack> : IStorageTrigger<T> {
|
||||
return extractStack(id, amount, simulate).count
|
||||
}
|
||||
|
||||
fun extractStackCount(id: UUID, amount: Int, simulate: Boolean): Fraction = extractStackCount(id, Fraction(amount), simulate)
|
||||
fun extractStackCount(id: UUID, amount: Long, simulate: Boolean): Fraction = extractStackCount(id, Fraction(amount), simulate)
|
||||
|
||||
fun getStacks(): Collection<IStorageTuple<T>>
|
||||
|
||||
fun addListenerAuto(listener: IStorageListener<T>): Boolean {
|
||||
|
@ -15,7 +15,7 @@ data class ItemStackWrapper(val stack: ItemStack) : IStorageStack {
|
||||
}
|
||||
|
||||
override var count: Fraction
|
||||
get() = Fraction(stack.getCount())
|
||||
get() = Fraction(stack.count)
|
||||
set(value) = setCount(value.toInt())
|
||||
|
||||
fun getCountInt() = stack.count
|
||||
|
Loading…
Reference in New Issue
Block a user