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.network.MatteryNetworking;
|
||||||
import ru.dbotthepony.mc.otm.storage.ItemStackWrapper;
|
import ru.dbotthepony.mc.otm.storage.ItemStackWrapper;
|
||||||
import ru.dbotthepony.mc.otm.storage.StorageObjectRegistry;
|
import ru.dbotthepony.mc.otm.storage.StorageObjectRegistry;
|
||||||
|
import ru.dbotthepony.mc.otm.storage.StorageObjectTuple;
|
||||||
|
|
||||||
import javax.annotation.ParametersAreNonnullByDefault;
|
import javax.annotation.ParametersAreNonnullByDefault;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@ -160,13 +161,15 @@ public class OverdriveThatMatters {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static StorageObjectTuple<ItemStackWrapper> ITEM_STORAGE;
|
||||||
|
|
||||||
private void setup(final FMLCommonSetupEvent event) {
|
private void setup(final FMLCommonSetupEvent event) {
|
||||||
MatteryNetworking.register();
|
MatteryNetworking.register();
|
||||||
// LOGGER.info("Registered network");
|
// LOGGER.info("Registered network");
|
||||||
|
|
||||||
MatterRegistry.registerInitialItems();
|
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) {
|
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;
|
this.menu = menu;
|
||||||
playerInventoryTitle = inventory.getDisplayName();
|
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());
|
inventory_frame = new FramePanel(this, null, 0, 0, INVENTORY_FRAME_WIDTH, INVENTORY_FRAME_HEIGHT, inventory.getDisplayName());
|
||||||
panels.add(inventory_frame);
|
panels.add(inventory_frame);
|
||||||
|
|
||||||
for (var slot : menu.inventory_slots) {
|
for (var slot : menu.inventorySlots) {
|
||||||
new SlotPanel<>(
|
new SlotPanel<>(
|
||||||
this,
|
this,
|
||||||
inventory_frame,
|
inventory_frame,
|
||||||
@ -359,10 +359,6 @@ public abstract class MatteryScreen<T extends MatteryMenu> extends AbstractConta
|
|||||||
|
|
||||||
if (main_frame != null) {
|
if (main_frame != null) {
|
||||||
addPanel(main_frame);
|
addPanel(main_frame);
|
||||||
|
|
||||||
for (var slot : menu.main_slots) {
|
|
||||||
new SlotPanel<>(this, main_frame, slot);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
movePanels();
|
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.core.BlockPos;
|
import net.minecraft.world.level.Level
|
||||||
import net.minecraft.world.level.Level;
|
import net.minecraft.world.level.block.Block
|
||||||
import net.minecraft.world.level.block.Block;
|
import net.minecraft.world.level.block.EntityBlock
|
||||||
import net.minecraft.world.level.block.EntityBlock;
|
import net.minecraft.world.level.block.entity.BlockEntity
|
||||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
import net.minecraft.world.level.block.entity.BlockEntityTicker
|
||||||
import net.minecraft.world.level.block.entity.BlockEntityTicker;
|
import net.minecraft.world.level.block.entity.BlockEntityType
|
||||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
import net.minecraft.world.level.block.state.BlockState
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
import net.minecraft.world.level.block.state.StateDefinition
|
||||||
import net.minecraft.world.level.block.state.StateDefinition;
|
import net.minecraft.world.level.block.state.properties.BooleanProperty
|
||||||
import net.minecraft.world.level.block.state.properties.BooleanProperty;
|
import ru.dbotthepony.mc.otm.Registry
|
||||||
import ru.dbotthepony.mc.otm.Registry;
|
import ru.dbotthepony.mc.otm.block.entity.BlockEntityDriveViewer
|
||||||
import ru.dbotthepony.mc.otm.block.entity.BlockEntityDriveViewer;
|
import ru.dbotthepony.mc.otm.block.entity.worker.WorkerState
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
class BlockDriveViewer : BlockMatteryRotatable(), EntityBlock {
|
||||||
import javax.annotation.ParametersAreNonnullByDefault;
|
override fun newBlockEntity(blockPos: BlockPos, blockState: BlockState): BlockEntity {
|
||||||
|
return BlockEntityDriveViewer(blockPos, blockState)
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
override fun <T : BlockEntity> getTicker(
|
||||||
@Override
|
p_153212_: Level,
|
||||||
public <T extends BlockEntity> BlockEntityTicker<T> getTicker(Level p_153212_, BlockState p_153213_, BlockEntityType<T> p_153214_) {
|
p_153213_: BlockState,
|
||||||
return p_153212_.isClientSide || p_153214_ != Registry.BlockEntities.DRIVE_VIEWER ? null : BlockEntityDriveViewer::ticker;
|
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
|
companion object {
|
||||||
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
|
val DRIVE_PRESENT = BooleanProperty.create("drive")
|
||||||
super.createBlockStateDefinition(builder);
|
|
||||||
builder.add(SEMI_WORKER_STATE);
|
|
||||||
builder.add(DRIVE_PRESENT);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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.MethodsReturnNonnullByDefault
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos
|
||||||
import net.minecraft.nbt.CompoundTag;
|
import net.minecraft.nbt.CompoundTag
|
||||||
import net.minecraft.network.chat.Component;
|
import net.minecraft.network.chat.Component
|
||||||
import net.minecraft.network.chat.TranslatableComponent;
|
import net.minecraft.network.chat.TranslatableComponent
|
||||||
import net.minecraft.world.entity.player.Inventory;
|
import net.minecraft.world.entity.player.Inventory
|
||||||
import net.minecraft.world.entity.player.Player;
|
import net.minecraft.world.entity.player.Player
|
||||||
import net.minecraft.world.inventory.AbstractContainerMenu;
|
import net.minecraft.world.inventory.AbstractContainerMenu
|
||||||
import net.minecraft.world.item.ItemStack;
|
import net.minecraft.world.item.ItemStack
|
||||||
import net.minecraft.world.level.Level;
|
import net.minecraft.world.level.Level
|
||||||
import net.minecraft.world.level.block.Block;
|
import net.minecraft.world.level.block.Block
|
||||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
import net.minecraft.world.level.block.state.BlockState
|
||||||
import net.minecraft.world.level.block.state.BlockState;
|
import ru.dbotthepony.mc.otm.OverdriveThatMatters
|
||||||
import ru.dbotthepony.mc.otm.OverdriveThatMatters;
|
import ru.dbotthepony.mc.otm.Registry
|
||||||
import ru.dbotthepony.mc.otm.Registry;
|
import ru.dbotthepony.mc.otm.block.BlockDriveViewer
|
||||||
import ru.dbotthepony.mc.otm.block.BlockDriveViewer;
|
import ru.dbotthepony.mc.otm.block.entity.worker.WorkerState
|
||||||
import ru.dbotthepony.mc.otm.block.entity.worker.WorkerState;
|
import ru.dbotthepony.mc.otm.capability.MatteryCapability
|
||||||
import ru.dbotthepony.mc.otm.capability.MatteryCapability;
|
import ru.dbotthepony.mc.otm.capability.MatteryMachineEnergyStorage
|
||||||
import ru.dbotthepony.mc.otm.capability.MatteryMachineEnergyStorage;
|
import ru.dbotthepony.mc.otm.container.MatteryContainer
|
||||||
import ru.dbotthepony.mc.otm.container.MatteryContainer;
|
import ru.dbotthepony.mc.otm.core.Fraction
|
||||||
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.menu.DriveViewerMenu
|
||||||
|
import ru.dbotthepony.mc.otm.set
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.ParametersAreNonnullByDefault
|
||||||
import javax.annotation.ParametersAreNonnullByDefault;
|
|
||||||
|
|
||||||
@MethodsReturnNonnullByDefault
|
@MethodsReturnNonnullByDefault
|
||||||
@ParametersAreNonnullByDefault
|
@ParametersAreNonnullByDefault
|
||||||
public class BlockEntityDriveViewer extends BlockEntityMatteryPowered {
|
class BlockEntityDriveViewer(p_155229_: BlockPos, p_155230_: BlockState) : BlockEntityMatteryPowered(Registry.BlockEntities.DRIVE_VIEWER, p_155229_, p_155230_) {
|
||||||
public static final Fraction MTE_PER_OPERATION = new Fraction("3.125");
|
override fun setChanged() {
|
||||||
|
super.setChanged()
|
||||||
|
|
||||||
public boolean canIOItems() {
|
val level = level
|
||||||
return energy.getBatteryLevel().compareTo(MTE_PER_OPERATION) >= 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateState(Level level) {
|
if (level != null) {
|
||||||
if (isRemoved())
|
OverdriveThatMatters.tickOnceSelf(level) {
|
||||||
return;
|
if (isRemoved) return@tickOnceSelf
|
||||||
|
|
||||||
var state = getBlockState();
|
var state = blockState
|
||||||
|
|
||||||
if (drive_slot.getItem(0).getCapability(MatteryCapability.DRIVE).isPresent() && canIOItems()) {
|
if (drive_slot.getItem(0).getCapability(MatteryCapability.DRIVE).isPresent && energy.batteryLevel >= OverdriveThatMatters.ITEM_STORAGE.energyPerOperation()) {
|
||||||
state = state.setValue(WorkerState.SEMI_WORKER_STATE, WorkerState.WORKING);
|
state = state.setValue(WorkerState.SEMI_WORKER_STATE, WorkerState.WORKING)
|
||||||
} else {
|
} else {
|
||||||
state = state.setValue(WorkerState.SEMI_WORKER_STATE, WorkerState.IDLE);
|
state = state.setValue(WorkerState.SEMI_WORKER_STATE, WorkerState.IDLE)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state != getBlockState()) {
|
if (state !== blockState) {
|
||||||
level.setBlock(getBlockPos(), state, Block.UPDATE_CLIENTS);
|
it.setBlock(blockPos, state, Block.UPDATE_CLIENTS)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@JvmField
|
||||||
public void setChanged() {
|
val drive_slot: MatteryContainer = object : MatteryContainer(this::setChanged, 1) {
|
||||||
super.setChanged();
|
override fun setChanged(slot: Int, new_state: ItemStack, old_state: ItemStack) {
|
||||||
|
super.setChanged(slot, new_state, old_state)
|
||||||
|
|
||||||
if (level != null)
|
val level = level
|
||||||
OverdriveThatMatters.tickOnceSelf(level, this::updateState);
|
if (level != null) {
|
||||||
}
|
OverdriveThatMatters.tickOnceSelf(level) {
|
||||||
|
if (!isRemoved) {
|
||||||
|
var state = blockState
|
||||||
|
|
||||||
public int getIOItemCount(int desired, boolean simulate) {
|
if (new_state.getCapability(MatteryCapability.DRIVE).isPresent) {
|
||||||
if (!canIOItems())
|
state = state.setValue(BlockDriveViewer.DRIVE_PRESENT, true)
|
||||||
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);
|
|
||||||
} else {
|
} else {
|
||||||
state = state.setValue(BlockDriveViewer.DRIVE_PRESENT, false);
|
state = state.setValue(BlockDriveViewer.DRIVE_PRESENT, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state != getBlockState()) {
|
if (state !== blockState) {
|
||||||
level.setBlock(getBlockPos(), state, Block.UPDATE_CLIENTS);
|
level.setBlock(blockPos, state, Block.UPDATE_CLIENTS)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Component getDefaultDisplayName() {
|
|
||||||
return NAME;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
init {
|
||||||
@Override
|
energy = MatteryMachineEnergyStorage(this, MatteryMachineEnergyStorage.MachineType.WORKER, Fraction(30000))
|
||||||
public AbstractContainerMenu createMenu(int containerID, Inventory inventory, Player ply) {
|
|
||||||
return new DriveViewerMenu(containerID, inventory, this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
override fun getDefaultDisplayName(): Component {
|
||||||
public void saveAdditional(CompoundTag nbt) {
|
return NAME
|
||||||
super.saveAdditional(nbt);
|
|
||||||
nbt.put("drive_slot", drive_slot.serializeNBT());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
override fun createMenu(containerID: Int, inventory: Inventory, ply: Player): AbstractContainerMenu? {
|
||||||
public void load(CompoundTag nbt) {
|
return DriveViewerMenu(containerID, inventory, this)
|
||||||
super.load(nbt);
|
|
||||||
drive_slot.deserializeNBT(nbt.get("drive_slot"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T extends BlockEntity> void ticker(Level level, BlockPos blockPos, BlockState blockState, T t) {
|
override fun saveAdditional(nbt: CompoundTag) {
|
||||||
if (t instanceof BlockEntityDriveViewer tile) {
|
super.saveAdditional(nbt)
|
||||||
tile.batteryChargeLoop();
|
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)
|
SlotPanel(this, frame, menu.battery_slot, 8f, 80f)
|
||||||
|
|
||||||
val scrollBar = ScrollBarPanel(this, frame, 192f, 14f, 92f)
|
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)
|
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) {
|
for (i in 0 until GRID_WIDTH * GRID_HEIGHT) {
|
||||||
object : AbstractSlotPanel(this@ItemMonitorScreen, gridPanel) {
|
object : AbstractSlotPanel(this@ItemMonitorScreen, gridPanel) {
|
||||||
override fun getItemStack(): ItemStack {
|
override fun getItemStack(): ItemStack {
|
||||||
val index = i + scrollBar.getScroll(menu.view.items.size / GRID_WIDTH)
|
val index = i + scrollBar.getScroll(menu.view.getItemCount() / GRID_WIDTH)
|
||||||
val list = menu.view.items
|
val list = menu.view.getItems()
|
||||||
return if (index >= list.size) ItemStack.EMPTY else list[index].stack()
|
return if (index >= list.size) ItemStack.EMPTY else list[index].stack
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun mouseScrolledInner(mouse_x: Double, mouse_y: Double, scroll: Double): Boolean {
|
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.Inventory
|
||||||
import net.minecraft.world.entity.player.Player
|
import net.minecraft.world.entity.player.Player
|
||||||
|
import net.minecraft.world.item.ItemStack
|
||||||
import ru.dbotthepony.mc.otm.Registry
|
import ru.dbotthepony.mc.otm.Registry
|
||||||
import ru.dbotthepony.mc.otm.block.entity.BlockEntityItemMonitor
|
import ru.dbotthepony.mc.otm.block.entity.BlockEntityItemMonitor
|
||||||
import ru.dbotthepony.mc.otm.capability.IMatteryEnergyStorage
|
import ru.dbotthepony.mc.otm.capability.IMatteryEnergyStorage
|
||||||
@ -58,4 +59,12 @@ class ItemMonitorMenu @JvmOverloads constructor(
|
|||||||
override fun getWorkingSlotEnd(): Int {
|
override fun getWorkingSlotEnd(): Int {
|
||||||
return 1
|
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
|
import java.util.function.Consumer
|
||||||
|
|
||||||
@JvmRecord
|
@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(
|
abstract class MatteryMenu protected @JvmOverloads constructor(
|
||||||
p_38851_: MenuType<*>?,
|
p_38851_: MenuType<*>?,
|
||||||
p_38852_: Int,
|
p_38852_: Int,
|
||||||
@JvmField val inventory: Inventory,
|
@JvmField val inventory: Inventory,
|
||||||
tile: BlockEntity? = null
|
@JvmField val tile: BlockEntity? = null
|
||||||
) : AbstractContainerMenu(p_38851_, p_38852_) {
|
) : AbstractContainerMenu(p_38851_, p_38852_) {
|
||||||
@JvmField
|
|
||||||
val tile: BlockEntity?
|
|
||||||
|
|
||||||
@JvmField
|
@JvmField
|
||||||
val ply: Player = inventory.player
|
val ply: Player = inventory.player
|
||||||
|
|
||||||
@JvmField
|
@JvmField
|
||||||
val mattery_widgets = ArrayList<AbstractWidget>()
|
val matteryWidgets = ArrayList<AbstractWidget>()
|
||||||
|
|
||||||
@JvmField
|
@JvmField
|
||||||
val inventory_slots = ArrayList<MatterySlot>()
|
val inventorySlots = ArrayList<MatterySlot>()
|
||||||
|
|
||||||
@JvmField
|
@JvmField
|
||||||
val main_slots = ArrayList<MatterySlot>()
|
protected val lockedInventorySlots: MutableSet<Int> = HashSet()
|
||||||
|
protected open fun isInventorySlotLocked(index: Int): Boolean = lockedInventorySlots.contains(index)
|
||||||
@JvmField
|
|
||||||
protected val locked_inventory_slots: MutableSet<Int> = HashSet()
|
|
||||||
protected fun isInventorySlotLocked(index: Int): Boolean = locked_inventory_slots.contains(index)
|
|
||||||
|
|
||||||
@JvmField
|
@JvmField
|
||||||
protected var _synchronizer: ContainerSynchronizer? = null
|
protected var _synchronizer: ContainerSynchronizer? = null
|
||||||
@ -45,27 +39,17 @@ abstract class MatteryMenu protected @JvmOverloads constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun addWidget(widget: AbstractWidget, consumer: Consumer<Consumer<ContainerData>>) {
|
fun addWidget(widget: AbstractWidget, consumer: Consumer<Consumer<ContainerData>>) {
|
||||||
if (!mattery_widgets.contains(widget)) {
|
if (!matteryWidgets.contains(widget)) {
|
||||||
mattery_widgets.add(widget)
|
matteryWidgets.add(widget)
|
||||||
consumer.accept(Consumer { p_38885_: ContainerData -> addDataSlots(p_38885_) })
|
consumer.accept(Consumer { p_38885_: ContainerData -> addDataSlots(p_38885_) })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addMainSlot(slot: MatterySlot): MatterySlot {
|
@JvmField
|
||||||
addSlot(slot)
|
protected var inventorySlotIndexStart = 0
|
||||||
main_slots.add(slot)
|
|
||||||
return slot
|
|
||||||
}
|
|
||||||
|
|
||||||
@JvmField
|
@JvmField
|
||||||
protected var inventory_slot_index_start = 0
|
protected var inventorySlotIndexEnd = 0
|
||||||
|
|
||||||
@JvmField
|
|
||||||
protected var inventory_slot_index_end = 0
|
|
||||||
|
|
||||||
init {
|
|
||||||
this.tile = tile
|
|
||||||
}
|
|
||||||
|
|
||||||
@JvmOverloads
|
@JvmOverloads
|
||||||
protected fun addInventorySlots(offset: Int = 97) {
|
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)
|
addSlot(slot)
|
||||||
|
|
||||||
if (first) {
|
if (first) {
|
||||||
first = false
|
first = false
|
||||||
inventory_slot_index_start = slot.index
|
inventorySlotIndexStart = slot.index
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -107,14 +91,14 @@ abstract class MatteryMenu protected @JvmOverloads constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
addSlot(last)
|
addSlot(last)
|
||||||
inventory_slots.add(last)
|
inventorySlots.add(last)
|
||||||
}
|
}
|
||||||
|
|
||||||
inventory_slot_index_end = last!!.index
|
inventorySlotIndexEnd = last!!.index
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun broadcastChanges() {
|
override fun broadcastChanges() {
|
||||||
for (widget in mattery_widgets) {
|
for (widget in matteryWidgets) {
|
||||||
widget.updateServer()
|
widget.updateServer()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -122,7 +106,7 @@ abstract class MatteryMenu protected @JvmOverloads constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun broadcastFullState() {
|
override fun broadcastFullState() {
|
||||||
for (widget in mattery_widgets) {
|
for (widget in matteryWidgets) {
|
||||||
widget.updateServer()
|
widget.updateServer()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -148,7 +132,7 @@ abstract class MatteryMenu protected @JvmOverloads constructor(
|
|||||||
// It shall return item stack that got moved
|
// It shall return item stack that got moved
|
||||||
override fun quickMoveStack(ply: Player, slot_index: Int): ItemStack {
|
override fun quickMoveStack(ply: Player, slot_index: Int): ItemStack {
|
||||||
// this.moveItemStackTo(ItemStack, int start_slot_index, int end_slot_index, boolean iteration_order)
|
// 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
|
// false means nothing happened
|
||||||
// Last boolean determine order of slot iteration, where:
|
// Last boolean determine order of slot iteration, where:
|
||||||
// if TRUE, iteration order is end_slot_index -> start_slot_index
|
// 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
|
var moved = ItemStack.EMPTY
|
||||||
val get_slot = slots[slot_index]
|
val initialSlot = slots[slot_index]
|
||||||
|
|
||||||
if (get_slot.hasItem()) {
|
if (initialSlot.hasItem()) {
|
||||||
val slot_item = get_slot.item
|
val initialItem = initialSlot.item
|
||||||
moved = slot_item.copy()
|
moved = initialItem.copy()
|
||||||
|
|
||||||
if (slot_index < inventory_slot_index_start) {
|
if (slot_index < inventorySlotIndexStart) {
|
||||||
// Moving FROM machine TO inventory
|
// 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
|
return ItemStack.EMPTY
|
||||||
}
|
}
|
||||||
} else if (!moveItemStackTo(slot_item, start, end, false)) {
|
} else if (!moveItemStackTo(initialItem, start, end, false)) {
|
||||||
// Moving FROM inventory TO machine
|
// Moving FROM inventory TO machine
|
||||||
return ItemStack.EMPTY
|
return ItemStack.EMPTY
|
||||||
}
|
}
|
||||||
|
|
||||||
if (slot_item.isEmpty) {
|
if (initialItem.isEmpty) {
|
||||||
get_slot.set(ItemStack.EMPTY)
|
initialSlot.set(ItemStack.EMPTY)
|
||||||
} else {
|
} else {
|
||||||
get_slot.setChanged()
|
initialSlot.setChanged()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -188,12 +172,12 @@ abstract class MatteryMenu protected @JvmOverloads constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun quickMoveToInventory(stack: ItemStack, simulate: Boolean): MoveResult {
|
fun quickMoveToInventory(stack: ItemStack, simulate: Boolean): MoveResult {
|
||||||
return if (inventory_slot_index_start == 0 && inventory_slot_index_end == 0) {
|
return if (inventorySlotIndexStart == 0 && inventorySlotIndexEnd == 0) {
|
||||||
MoveResult(false, stack, java.util.Set.of<Slot>())
|
MoveResult(false, stack, setOf())
|
||||||
} else customMoveItemStackTo(
|
} else customMoveItemStackTo(
|
||||||
stack,
|
stack,
|
||||||
inventory_slot_index_start,
|
inventorySlotIndexStart,
|
||||||
inventory_slot_index_end + 1,
|
inventorySlotIndexEnd + 1,
|
||||||
false,
|
false,
|
||||||
simulate
|
simulate
|
||||||
)
|
)
|
||||||
@ -205,27 +189,27 @@ abstract class MatteryMenu protected @JvmOverloads constructor(
|
|||||||
final_slot: Int,
|
final_slot: Int,
|
||||||
reverse_direction: Boolean
|
reverse_direction: Boolean
|
||||||
): Boolean {
|
): Boolean {
|
||||||
val move_result = customMoveItemStackTo(stack_to_move, initial_slot, final_slot, reverse_direction, false)
|
val moveResult = customMoveItemStackTo(stack_to_move, initial_slot, final_slot, reverse_direction, false)
|
||||||
val remaining: ItemStack = move_result.remaining
|
val remaining: ItemStack = moveResult.remaining
|
||||||
if (remaining.count == stack_to_move.count) return false
|
if (remaining.count == stack_to_move.count) return false
|
||||||
stack_to_move.count = remaining.count
|
stack_to_move.count = remaining.count
|
||||||
return move_result.merge_occured
|
return moveResult.mergeOccurred
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun customMoveItemStackTo(
|
protected fun customMoveItemStackTo(
|
||||||
_stack_to_move: ItemStack,
|
stackToMove1: ItemStack,
|
||||||
initial_slot: Int,
|
initial_slot: Int,
|
||||||
final_slot: Int,
|
final_slot: Int,
|
||||||
reverse_direction: Boolean,
|
reverse_direction: Boolean,
|
||||||
simulate: Boolean
|
simulate: Boolean
|
||||||
): MoveResult {
|
): MoveResult {
|
||||||
var merge_occured = false
|
var mergeOccurred = false
|
||||||
var i = if (reverse_direction) final_slot - 1 else initial_slot
|
var i = if (reverse_direction) final_slot - 1 else initial_slot
|
||||||
val changed = HashSet<Slot>()
|
val changed = HashSet<Slot>()
|
||||||
val stack_to_move = _stack_to_move.copy()
|
val stackToMove = stackToMove1.copy()
|
||||||
|
|
||||||
if (stack_to_move.isStackable) {
|
if (stackToMove.isStackable) {
|
||||||
while (!stack_to_move.isEmpty) {
|
while (!stackToMove.isEmpty) {
|
||||||
if (reverse_direction) {
|
if (reverse_direction) {
|
||||||
if (i < initial_slot) {
|
if (i < initial_slot) {
|
||||||
break
|
break
|
||||||
@ -237,29 +221,29 @@ abstract class MatteryMenu protected @JvmOverloads constructor(
|
|||||||
val slot = slots[i]
|
val slot = slots[i]
|
||||||
val slot_stack = slot.item
|
val slot_stack = slot.item
|
||||||
|
|
||||||
if (!slot_stack.isEmpty && ItemStack.isSameItemSameTags(stack_to_move, slot_stack)) {
|
if (!slot_stack.isEmpty && ItemStack.isSameItemSameTags(stackToMove, slot_stack)) {
|
||||||
val j = slot_stack.count + stack_to_move.count
|
val j = slot_stack.count + stackToMove.count
|
||||||
val maxSize = slot.getMaxStackSize(stack_to_move)
|
val maxSize = slot.getMaxStackSize(stackToMove)
|
||||||
|
|
||||||
if (j <= maxSize) {
|
if (j <= maxSize) {
|
||||||
stack_to_move.count = 0
|
stackToMove.count = 0
|
||||||
|
|
||||||
if (!simulate) {
|
if (!simulate) {
|
||||||
slot_stack.count = j
|
slot_stack.count = j
|
||||||
slot.setChanged()
|
slot.setChanged()
|
||||||
}
|
}
|
||||||
|
|
||||||
merge_occured = true
|
mergeOccurred = true
|
||||||
changed.add(slot)
|
changed.add(slot)
|
||||||
} else if (slot_stack.count < maxSize) {
|
} else if (slot_stack.count < maxSize) {
|
||||||
stack_to_move.shrink(maxSize - slot_stack.count)
|
stackToMove.shrink(maxSize - slot_stack.count)
|
||||||
|
|
||||||
if (!simulate) {
|
if (!simulate) {
|
||||||
slot_stack.count = maxSize
|
slot_stack.count = maxSize
|
||||||
slot.setChanged()
|
slot.setChanged()
|
||||||
}
|
}
|
||||||
|
|
||||||
merge_occured = true
|
mergeOccurred = true
|
||||||
changed.add(slot)
|
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
|
i = if (reverse_direction) final_slot - 1 else initial_slot
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
@ -283,18 +267,18 @@ abstract class MatteryMenu protected @JvmOverloads constructor(
|
|||||||
val slot = slots[i]
|
val slot = slots[i]
|
||||||
val slot_stack = slot.item
|
val slot_stack = slot.item
|
||||||
|
|
||||||
if (slot_stack.isEmpty && slot.mayPlace(stack_to_move)) {
|
if (slot_stack.isEmpty && slot.mayPlace(stackToMove)) {
|
||||||
if (!simulate) {
|
if (!simulate) {
|
||||||
if (stack_to_move.count > slot.maxStackSize) {
|
if (stackToMove.count > slot.maxStackSize) {
|
||||||
slot.set(stack_to_move.split(slot.maxStackSize))
|
slot.set(stackToMove.split(slot.maxStackSize))
|
||||||
} else {
|
} else {
|
||||||
slot.set(stack_to_move.split(stack_to_move.count))
|
slot.set(stackToMove.split(stackToMove.count))
|
||||||
}
|
}
|
||||||
|
|
||||||
slot.setChanged()
|
slot.setChanged()
|
||||||
}
|
}
|
||||||
|
|
||||||
merge_occured = true
|
mergeOccurred = true
|
||||||
changed.add(slot)
|
changed.add(slot)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -302,6 +286,7 @@ abstract class MatteryMenu protected @JvmOverloads constructor(
|
|||||||
i += if (reverse_direction) -1 else 1
|
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
|
* @return copy of object, with amount of units actually extracted
|
||||||
*/
|
*/
|
||||||
fun extractStack(id: UUID, amount: Fraction, simulate: Boolean): T
|
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
|
* 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
|
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 getStacks(): Collection<IStorageTuple<T>>
|
||||||
|
|
||||||
fun addListenerAuto(listener: IStorageListener<T>): Boolean {
|
fun addListenerAuto(listener: IStorageListener<T>): Boolean {
|
||||||
|
@ -15,7 +15,7 @@ data class ItemStackWrapper(val stack: ItemStack) : IStorageStack {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override var count: Fraction
|
override var count: Fraction
|
||||||
get() = Fraction(stack.getCount())
|
get() = Fraction(stack.count)
|
||||||
set(value) = setCount(value.toInt())
|
set(value) = setCount(value.toInt())
|
||||||
|
|
||||||
fun getCountInt() = stack.count
|
fun getCountInt() = stack.count
|
||||||
|
Loading…
Reference in New Issue
Block a user