diff --git a/src/main/java/ru/dbotthepony/mc/otm/AbstractGrid.java b/src/main/java/ru/dbotthepony/mc/otm/AbstractGrid.java index b1b2b6f1d..467249eeb 100644 --- a/src/main/java/ru/dbotthepony/mc/otm/AbstractGrid.java +++ b/src/main/java/ru/dbotthepony/mc/otm/AbstractGrid.java @@ -9,15 +9,10 @@ import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.chunk.LevelChunk; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.util.LazyOptional; -import ru.dbotthepony.mc.otm.capability.IStorageGridCell; -import ru.dbotthepony.mc.otm.capability.MatteryCapability; -import ru.dbotthepony.mc.otm.storage.StorageGrid; import javax.annotation.ParametersAreNonnullByDefault; -import java.security.Provider; import java.util.HashSet; import java.util.List; -import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Supplier; diff --git a/src/main/java/ru/dbotthepony/mc/otm/capability/AbstractStorageGridCell.java b/src/main/java/ru/dbotthepony/mc/otm/capability/AbstractStorageGridCell.java deleted file mode 100644 index a547637d7..000000000 --- a/src/main/java/ru/dbotthepony/mc/otm/capability/AbstractStorageGridCell.java +++ /dev/null @@ -1,118 +0,0 @@ -package ru.dbotthepony.mc.otm.capability; - -import net.minecraft.MethodsReturnNonnullByDefault; -import net.minecraftforge.common.util.LazyOptional; -import ru.dbotthepony.mc.otm.OverdriveThatMatters; -import ru.dbotthepony.mc.otm.storage.IStorageIdentity; -import ru.dbotthepony.mc.otm.storage.IStorageStack; -import ru.dbotthepony.mc.otm.storage.StorageGrid; - -import javax.annotation.Nullable; -import javax.annotation.ParametersAreNonnullByDefault; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.function.Function; -import java.util.function.Supplier; - -@MethodsReturnNonnullByDefault -@ParametersAreNonnullByDefault -public class AbstractStorageGridCell implements IStorageGridCell { - private LazyOptional resolver = LazyOptional.of(() -> this); - private boolean valid = true; - protected final ArrayList> components = new ArrayList<>(); - - @Override - public List> getComponents() { - return Collections.unmodifiableList(components); - } - - @SuppressWarnings("unchecked") - public > U computeIfAbsent(Class identity, Supplier provider) { - for (var component : components) { - if (component.storageIdentity() == identity) { - return (U) component; - } - } - - var factory = provider.get(); - addStorageComponent(factory); - return factory; - } - - @SuppressWarnings("unchecked") - public > U computeIfAbsent(Class identity, Function, U> provider) { - for (var component : components) { - if (component.storageIdentity() == identity) { - return (U) component; - } - } - - var factory = provider.apply(identity); - addStorageComponent(factory); - return factory; - } - - public void addStorageComponent(IStorageIdentity component) { - for (var component1 : components) { - if (component == component1 || component1.storageIdentity() == component.storageIdentity()) { - return; - } - } - - detachStorage(); - components.add(component); - attachStorage(); - } - - public void removeStorageComponent(IStorageIdentity component) { - for (var component1 : components) { - if (component == component1 || component1.storageIdentity() == component.storageIdentity()) { - detachStorage(); - components.remove(component1); - attachStorage(); - return; - } - } - } - - public void invalidate() { - if (!valid) - return; - - valid = false; - resolver.invalidate(); - // detachStorage(); - } - - public void revive() { - if (valid) - return; - - valid = true; - resolver = LazyOptional.of(() -> this); - // attachStorage(); - } - - public LazyOptional get() { - return valid ? resolver : LazyOptional.empty(); - } - - protected StorageGrid storage_grid; - - @Nullable - @Override - public StorageGrid getStorageGrid() { - return storage_grid; - } - - @Override - public void setStorageGrid(@Nullable StorageGrid grid) { - storage_grid = grid; - } - - @Override - public boolean isValidStorageCell() { - return valid; - } -} diff --git a/src/main/java/ru/dbotthepony/mc/otm/capability/MatteryCapability.java b/src/main/java/ru/dbotthepony/mc/otm/capability/MatteryCapability.java index 80112e916..18f32eefe 100644 --- a/src/main/java/ru/dbotthepony/mc/otm/capability/MatteryCapability.java +++ b/src/main/java/ru/dbotthepony/mc/otm/capability/MatteryCapability.java @@ -9,6 +9,7 @@ import ru.dbotthepony.mc.otm.capability.matter.IMatterTaskProvider; import ru.dbotthepony.mc.otm.capability.matter.IPatternStorage; import ru.dbotthepony.mc.otm.core.Fraction; import ru.dbotthepony.mc.otm.graph.matter.IMatterGraphNode; +import ru.dbotthepony.mc.otm.graph.storage.IStorageGraphNode; import java.math.MathContext; import java.math.RoundingMode; @@ -21,7 +22,7 @@ public class MatteryCapability { public static final Capability PATTERN = CapabilityManager.get(new CapabilityToken<>() {}); public static final Capability TASK = CapabilityManager.get(new CapabilityToken<>() {}); public static final Capability DRIVE = CapabilityManager.get(new CapabilityToken<>() {}); - public static final Capability STORAGE_CELL = CapabilityManager.get(new CapabilityToken<>() {}); + public static final Capability STORAGE_CELL = CapabilityManager.get(new CapabilityToken<>() {}); @SuppressWarnings("unused") public static void register(final RegisterCapabilitiesEvent event) { @@ -31,7 +32,7 @@ public class MatteryCapability { event.register(IPatternStorage.class); event.register(IMatterTaskProvider.class); event.register(IMatteryDrive.class); - event.register(IStorageGridCell.class); + event.register(IStorageGraphNode.class); event.register(IMatterGraphNode.class); } diff --git a/src/main/java/ru/dbotthepony/mc/otm/menu/DriveRackMenu.kt b/src/main/java/ru/dbotthepony/mc/otm/menu/DriveRackMenu.kt index 0b5f0a458..a47c0b146 100644 --- a/src/main/java/ru/dbotthepony/mc/otm/menu/DriveRackMenu.kt +++ b/src/main/java/ru/dbotthepony/mc/otm/menu/DriveRackMenu.kt @@ -1,46 +1,35 @@ -package ru.dbotthepony.mc.otm.menu; +package ru.dbotthepony.mc.otm.menu -import net.minecraft.world.SimpleContainer; -import net.minecraft.world.entity.player.Inventory; -import net.minecraft.world.item.ItemStack; -import ru.dbotthepony.mc.otm.Registry; -import ru.dbotthepony.mc.otm.block.entity.BlockEntityDriveRack; -import ru.dbotthepony.mc.otm.capability.MatteryCapability; +import net.minecraft.world.SimpleContainer +import net.minecraft.world.entity.player.Inventory +import ru.dbotthepony.mc.otm.Registry +import ru.dbotthepony.mc.otm.block.entity.BlockEntityDriveRack -public class DriveRackMenu extends PoweredMatteryMenu { - public DriveRackMenu(int p_38852_, Inventory inventory) { - this(p_38852_, inventory, null); - } +class DriveRackMenu @JvmOverloads constructor( + p_38852_: Int, + inventory: Inventory, + tile: BlockEntityDriveRack? = null +) : PoweredMatteryMenu(Registry.Menus.DRIVE_RACK, p_38852_, inventory, tile) { + val drives = arrayOfNulls(4) - public final MatterySlot[] drives = new MatterySlot[4]; + init { + val container = tile?.drives ?: SimpleContainer(4) - public DriveRackMenu(int p_38852_, Inventory inventory, BlockEntityDriveRack tile) { - super(Registry.Menus.DRIVE_RACK, p_38852_, inventory, tile); - - var container = tile != null ? tile.drives : new SimpleContainer(4); - - for (int i = 0; i < container.getContainerSize(); i++) { - drives[i] = new MatterySlot(container, i) { - @Override - public boolean mayPlace(ItemStack p_40231_) { - return p_40231_.getCapability(MatteryCapability.DRIVE).isPresent(); - } - }; - - addSlot(drives[i]); + for (i in 0 until container.containerSize) { + val slot = DriveSlot(container, i) + drives[i] = slot + addSlot(slot) } - addBatterySlot(); - addInventorySlots(); + addBatterySlot() + addInventorySlots() } - @Override - protected int getWorkingSlotStart() { - return 0; + override fun getWorkingSlotStart(): Int { + return 0 } - @Override - protected int getWorkingSlotEnd() { - return 5; + override fun getWorkingSlotEnd(): Int { + return 5 } -} +} \ No newline at end of file diff --git a/src/main/java/ru/dbotthepony/mc/otm/menu/ItemMonitorMenu.kt b/src/main/java/ru/dbotthepony/mc/otm/menu/ItemMonitorMenu.kt index 1244b764c..ab0c2249f 100644 --- a/src/main/java/ru/dbotthepony/mc/otm/menu/ItemMonitorMenu.kt +++ b/src/main/java/ru/dbotthepony/mc/otm/menu/ItemMonitorMenu.kt @@ -1,54 +1,43 @@ -package ru.dbotthepony.mc.otm.menu; +package ru.dbotthepony.mc.otm.menu -import net.minecraft.world.entity.player.Inventory; -import ru.dbotthepony.mc.otm.Registry; -import ru.dbotthepony.mc.otm.block.entity.BlockEntityItemMonitor; -import ru.dbotthepony.mc.otm.menu.data.INetworkedItemViewSupplier; -import ru.dbotthepony.mc.otm.menu.data.NetworkedItemView; -import ru.dbotthepony.mc.otm.storage.ItemStackWrapper; +import net.minecraft.world.entity.player.Inventory +import ru.dbotthepony.mc.otm.Registry +import ru.dbotthepony.mc.otm.block.entity.BlockEntityItemMonitor +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.Nonnull; +class ItemMonitorMenu @JvmOverloads constructor( + p_38852_: Int, + inventory: Inventory, + tile: BlockEntityItemMonitor? = null +) : PoweredMatteryMenu(Registry.Menus.ITEM_MONITOR, p_38852_, inventory, tile), INetworkedItemViewSupplier { + @JvmField + val view = NetworkedItemView(inventory.player, this, tile == null) -public class ItemMonitorMenu extends PoweredMatteryMenu implements INetworkedItemViewSupplier { - public final NetworkedItemView view; - - @Nonnull - @Override - public NetworkedItemView getNetworkedItemView() { - return view; + override fun getNetworkedItemView(): NetworkedItemView { + return view } - public ItemMonitorMenu(int p_38852_, Inventory inventory) { - this(p_38852_, inventory, null); - } - - public ItemMonitorMenu(int p_38852_, Inventory inventory, BlockEntityItemMonitor tile) { - super(Registry.Menus.ITEM_MONITOR, p_38852_, inventory, tile); - - view = new NetworkedItemView(inventory.player, this, tile == null); - + init { if (tile != null) { - view.setComponent(tile.cell.getStorageGrid().getVirtualComponent(ItemStackWrapper.class)); + view.setComponent(tile.cell.storageGrid!!.getVirtualComponent(ItemStackWrapper::class.java)) } - addBatterySlot(); - addInventorySlots(); + addBatterySlot() + addInventorySlots() } - @Override - public void broadcastChanges() { - super.broadcastChanges(); - - view.network(); + override fun broadcastChanges() { + super.broadcastChanges() + view.network() } - @Override - protected int getWorkingSlotStart() { - return 0; + override fun getWorkingSlotStart(): Int { + return 0 } - @Override - protected int getWorkingSlotEnd() { - return 1; + override fun getWorkingSlotEnd(): Int { + return 1 } -} +} \ No newline at end of file diff --git a/src/main/java/ru/dbotthepony/mc/otm/storage/IStorageComponent.java b/src/main/java/ru/dbotthepony/mc/otm/storage/IStorageComponent.java deleted file mode 100644 index 282876316..000000000 --- a/src/main/java/ru/dbotthepony/mc/otm/storage/IStorageComponent.java +++ /dev/null @@ -1,11 +0,0 @@ -package ru.dbotthepony.mc.otm.storage; - -import net.minecraft.MethodsReturnNonnullByDefault; - -import javax.annotation.ParametersAreNonnullByDefault; - -@MethodsReturnNonnullByDefault -@ParametersAreNonnullByDefault -public interface IStorageComponent extends IStorageView, IStorageConsumer { - -} diff --git a/src/main/java/ru/dbotthepony/mc/otm/storage/IStorageConsumer.java b/src/main/java/ru/dbotthepony/mc/otm/storage/IStorageConsumer.java deleted file mode 100644 index 8fc0474f3..000000000 --- a/src/main/java/ru/dbotthepony/mc/otm/storage/IStorageConsumer.java +++ /dev/null @@ -1,11 +0,0 @@ -package ru.dbotthepony.mc.otm.storage; - -import net.minecraft.MethodsReturnNonnullByDefault; - -import javax.annotation.ParametersAreNonnullByDefault; - -@MethodsReturnNonnullByDefault -@ParametersAreNonnullByDefault -public interface IStorageConsumer extends IStorageIdentity { - T insertStack(T stack, boolean simulate); -} diff --git a/src/main/java/ru/dbotthepony/mc/otm/storage/IStorageIdentity.java b/src/main/java/ru/dbotthepony/mc/otm/storage/IStorageIdentity.java deleted file mode 100644 index bf40c902e..000000000 --- a/src/main/java/ru/dbotthepony/mc/otm/storage/IStorageIdentity.java +++ /dev/null @@ -1,11 +0,0 @@ -package ru.dbotthepony.mc.otm.storage; - -import net.minecraft.MethodsReturnNonnullByDefault; - -import javax.annotation.ParametersAreNonnullByDefault; - -@MethodsReturnNonnullByDefault -@ParametersAreNonnullByDefault -public interface IStorageIdentity { - Class storageIdentity(); -} diff --git a/src/main/java/ru/dbotthepony/mc/otm/storage/IStorageListener.java b/src/main/java/ru/dbotthepony/mc/otm/storage/IStorageListener.java deleted file mode 100644 index 10953bc02..000000000 --- a/src/main/java/ru/dbotthepony/mc/otm/storage/IStorageListener.java +++ /dev/null @@ -1,16 +0,0 @@ -package ru.dbotthepony.mc.otm.storage; - -import net.minecraft.MethodsReturnNonnullByDefault; -import ru.dbotthepony.mc.otm.core.Fraction; - -import javax.annotation.ParametersAreNonnullByDefault; -import java.math.BigDecimal; -import java.util.UUID; - -@MethodsReturnNonnullByDefault -@ParametersAreNonnullByDefault -public interface IStorageListener { - void addObject(T stack, UUID id, IStorageView provider); - void changeObject(UUID id, Fraction new_count); - void removeObject(UUID id); -} diff --git a/src/main/java/ru/dbotthepony/mc/otm/storage/IStorageStack.java b/src/main/java/ru/dbotthepony/mc/otm/storage/IStorageStack.java deleted file mode 100644 index 784fef1c3..000000000 --- a/src/main/java/ru/dbotthepony/mc/otm/storage/IStorageStack.java +++ /dev/null @@ -1,65 +0,0 @@ -package ru.dbotthepony.mc.otm.storage; - -import net.minecraft.MethodsReturnNonnullByDefault; -import ru.dbotthepony.mc.otm.core.Fraction; - -import javax.annotation.ParametersAreNonnullByDefault; -import java.math.BigDecimal; -import java.util.Optional; - -/** - * Interface implements all methods required for storage system functioning and interaction - * with your kind of items/objects/whatever. - * - * You can either implement this interface directly (hard dependency, discouraged, unless you do an addon to this storage system) - * or create a record class (preferred), which encapsulate your storage object. - */ -@MethodsReturnNonnullByDefault -@ParametersAreNonnullByDefault -public interface IStorageStack { - IStorageStack copy(); - - void setCount(Fraction value); - Fraction getCount(); - - boolean isEmpty(); - - /** - * @return max stack size for this stack object - * Optional.empty() if unlimited (default) - */ - default Optional getMaxStackSize() { - return Optional.empty(); - } - - /** - * @return Identity utilized to partition view table (if it has any). - * Defaults to no partitioning; meaning performance will degrade much quicker than it should. - * Good object is an object that will influence on sameItem() return result, making it return true. - * It is strictly considered that if !this.itemIdentity().equals(other.itemIdentity()); - * then this.sameItem(other) will never return true. - * - * If implemented, and storage is also partitioned properly, then performance will be flat equally to view table's performance. - * - * Example: ItemStack#getItem() - */ - default Object partitionKey() { - return Object.class; - }; - - /** - * @param other other object to compare; if not the same of this object type just return false - * @return boolean representing whenever internal state of this equals to other; - * this include tags, mapping IDs, capabilities, excluding amount; - * behavior is pretty much the same as ItemStack.isSameItemSameTags - */ - boolean sameItem(IStorageStack other); - - default void grow(Fraction amount) { - setCount(getCount().plus(amount)); - } - - default void shrink(Fraction amount) { - setCount(getCount().minus(amount)); - } -} diff --git a/src/main/java/ru/dbotthepony/mc/otm/storage/IStorageTrigger.java b/src/main/java/ru/dbotthepony/mc/otm/storage/IStorageTrigger.java deleted file mode 100644 index de79c8931..000000000 --- a/src/main/java/ru/dbotthepony/mc/otm/storage/IStorageTrigger.java +++ /dev/null @@ -1,12 +0,0 @@ -package ru.dbotthepony.mc.otm.storage; - -import net.minecraft.MethodsReturnNonnullByDefault; - -import javax.annotation.ParametersAreNonnullByDefault; - -@MethodsReturnNonnullByDefault -@ParametersAreNonnullByDefault -public interface IStorageTrigger extends IStorageIdentity { - boolean addListener(IStorageListener listener); - boolean removeListener(IStorageListener listener); -} diff --git a/src/main/java/ru/dbotthepony/mc/otm/storage/IStorageTuple.java b/src/main/java/ru/dbotthepony/mc/otm/storage/IStorageTuple.java deleted file mode 100644 index 8525985ae..000000000 --- a/src/main/java/ru/dbotthepony/mc/otm/storage/IStorageTuple.java +++ /dev/null @@ -1,8 +0,0 @@ -package ru.dbotthepony.mc.otm.storage; - -import java.util.UUID; - -public interface IStorageTuple { - UUID id(); - T stack(); -} diff --git a/src/main/java/ru/dbotthepony/mc/otm/storage/StorageGrid.java b/src/main/java/ru/dbotthepony/mc/otm/storage/StorageGrid.java deleted file mode 100644 index ff9889082..000000000 --- a/src/main/java/ru/dbotthepony/mc/otm/storage/StorageGrid.java +++ /dev/null @@ -1,83 +0,0 @@ -package ru.dbotthepony.mc.otm.storage; - -import net.minecraft.MethodsReturnNonnullByDefault; -import net.minecraft.core.BlockPos; -import net.minecraft.world.level.Level; -import net.minecraftforge.common.util.LazyOptional; -import ru.dbotthepony.mc.otm.AbstractGrid; -import ru.dbotthepony.mc.otm.OverdriveThatMatters; -import ru.dbotthepony.mc.otm.capability.IStorageGridCell; -import ru.dbotthepony.mc.otm.capability.MatteryCapability; - -import javax.annotation.ParametersAreNonnullByDefault; -import java.util.*; - -@MethodsReturnNonnullByDefault -@ParametersAreNonnullByDefault -public class StorageGrid extends AbstractGrid { - private final HashMap, VirtualComponent> virtual_components = new HashMap<>(); - - public StorageGrid() { - super(MatteryCapability.STORAGE_CELL); - } - - public T insertObject(Class type, T object, boolean simulate) { - return getVirtualComponent(type).insertStack(object, simulate); - } - - /** - * @param type Class, representing identity of stored object - * @param The identity itself - * @return a virtual IStorageComponent, or null if storage grid contain no view for provided type - */ - @SuppressWarnings("unchecked") - public VirtualComponent getVirtualComponent(final Class type) { - return (VirtualComponent) virtual_components.computeIfAbsent(type, (k) -> new VirtualComponent<>(type)); - } - - public void add(IStorageIdentity identity) { - getVirtualComponent(identity.storageIdentity()).add(identity); - } - - public void remove(IStorageIdentity identity) { - getVirtualComponent(identity.storageIdentity()).remove(identity); - } - - @Override - protected void onAdded(IStorageGridCell cell) { - cell.setStorageGrid(this); - - for (var identity : cell.getComponents()) { - add(identity); - } - } - - @Override - protected void onRemoved(IStorageGridCell cell) { - cell.setStorageGrid(null); - - for (var identity : cell.getComponents()) { - remove(identity); - } - } - - public void detach(IStorageGridCell cell) { - if (cells.contains(cell)) { - for (var identity : cell.getComponents()) { - remove(identity); - } - } - } - - public void attach(IStorageGridCell cell) { - if (cells.contains(cell)) { - for (var identity : cell.getComponents()) { - add(identity); - } - } - } - - public static void scheduleDiscoverNeighbours(IStorageGridCell cell, Level level, BlockPos pos) { - OverdriveThatMatters.tickUntil(level, () -> !cell.isValidStorageCell() || cell.connectOrCreateStorageGrid(level, pos, true)); - } -} diff --git a/src/main/java/ru/dbotthepony/mc/otm/storage/StorageObjectRegistry.java b/src/main/java/ru/dbotthepony/mc/otm/storage/StorageObjectRegistry.java index 80d947771..227aadcaa 100644 --- a/src/main/java/ru/dbotthepony/mc/otm/storage/StorageObjectRegistry.java +++ b/src/main/java/ru/dbotthepony/mc/otm/storage/StorageObjectRegistry.java @@ -27,6 +27,6 @@ public class StorageObjectRegistry { @Nonnull public static StorageObjectTuple getOrError(Class identity) { - return Objects.requireNonNull(get(identity), "No storage mapping present for " + identity.toString()); + return Objects.requireNonNull(get(identity), "No storage mapping present for " + identity); } } diff --git a/src/main/java/ru/dbotthepony/mc/otm/storage/StorageTuple.java b/src/main/java/ru/dbotthepony/mc/otm/storage/StorageTuple.java deleted file mode 100644 index 432dbd5b9..000000000 --- a/src/main/java/ru/dbotthepony/mc/otm/storage/StorageTuple.java +++ /dev/null @@ -1,6 +0,0 @@ -package ru.dbotthepony.mc.otm.storage; - -import java.util.UUID; - -public record StorageTuple(UUID id, T stack) implements IStorageTuple { -} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/BlockEntityDriveRack.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/BlockEntityDriveRack.kt index 4014967b9..b0118d4f1 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/BlockEntityDriveRack.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/BlockEntityDriveRack.kt @@ -1,111 +1,100 @@ -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.core.Direction; -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.state.BlockState; -import net.minecraftforge.common.capabilities.Capability; -import net.minecraftforge.common.util.LazyOptional; -import ru.dbotthepony.mc.otm.OverdriveThatMatters; -import ru.dbotthepony.mc.otm.Registry; -import ru.dbotthepony.mc.otm.capability.AbstractStorageGridCell; -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.DriveRackMenu; -import ru.dbotthepony.mc.otm.storage.ItemStackWrapper; -import ru.dbotthepony.mc.otm.storage.VirtualComponent; +import net.minecraft.core.BlockPos +import net.minecraft.core.Direction +import net.minecraft.nbt.CompoundTag +import net.minecraft.network.chat.Component +import net.minecraft.network.chat.TranslatableComponent +import net.minecraft.server.level.ServerLevel +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.state.BlockState +import net.minecraftforge.common.capabilities.Capability +import net.minecraftforge.common.util.LazyOptional +import ru.dbotthepony.mc.otm.Registry +import ru.dbotthepony.mc.otm.graph.storage.BasicStorageGraphNode +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.DriveRackMenu +import ru.dbotthepony.mc.otm.set +import ru.dbotthepony.mc.otm.graph.storage.StorageNetworkGraph +import ru.dbotthepony.mc.otm.storage.VirtualComponent -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import javax.annotation.ParametersAreNonnullByDefault; -import java.math.BigDecimal; +class BlockEntityDriveRack(p_155229_: BlockPos, p_155230_: BlockState) : + BlockEntityMatteryPowered(Registry.BlockEntities.DRIVE_RACK, p_155229_, p_155230_) { -@MethodsReturnNonnullByDefault -@ParametersAreNonnullByDefault -public class BlockEntityDriveRack extends BlockEntityMatteryPowered { - public BlockEntityDriveRack(BlockPos p_155229_, BlockState p_155230_) { - super(Registry.BlockEntities.DRIVE_RACK, p_155229_, p_155230_); - energy = new MatteryMachineEnergyStorage(this, MatteryMachineEnergyStorage.MachineType.WORKER, new Fraction(80_000)); - } + @JvmField + val drives: MatteryContainer = object : MatteryContainer(this::setChanged, 4) { + override fun setChanged(slot: Int, new_state: ItemStack, old_state: ItemStack) { + super.setChanged(slot, new_state, old_state) - public final MatteryContainer drives = new MatteryContainer(this::setChanged, 4) { - @Override - public void setChanged(int slot, ItemStack new_state, ItemStack old_state) { - super.setChanged(slot, new_state, old_state); + old_state.getCapability(MatteryCapability.DRIVE).ifPresent { + cell.computeIfAbsent(it.storageIdentity()) {c -> VirtualComponent(c)}.remove(it) + } - old_state.getCapability(MatteryCapability.DRIVE).ifPresent((drive) -> { - cell.computeIfAbsent(drive.storageIdentity(), VirtualComponent::new).remove(drive); - }); - - new_state.getCapability(MatteryCapability.DRIVE).ifPresent((drive) -> { - cell.computeIfAbsent(drive.storageIdentity(), VirtualComponent::new).add(drive); - }); + new_state.getCapability(MatteryCapability.DRIVE).ifPresent { + cell.computeIfAbsent(it.storageIdentity()) {c -> VirtualComponent(c)}.add(it) + } } - }; - - public final AbstractStorageGridCell cell = new AbstractStorageGridCell(); - - @Override - public void load(CompoundTag nbt) { - super.load(nbt); - drives.deserializeNBT(nbt.getCompound("drives")); } - @Override - public void saveAdditional(CompoundTag nbt) { - super.saveAdditional(nbt); - nbt.put("drives", drives.serializeNBT()); - } + val cell = BasicStorageGraphNode() - @Override - public void setLevel(Level p_155231_) { - super.setLevel(p_155231_); + override fun load(nbt: CompoundTag) { + super.load(nbt) - cell.scheduleDiscoverNeighbours(p_155231_, getBlockPos()); - } - - private static final TranslatableComponent NAME = new TranslatableComponent("block.overdrive_that_matters.drive_rack"); - - @Override - protected Component getDefaultDisplayName() { - return NAME; - } - - @Nullable - @Override - public AbstractContainerMenu createMenu(int containerID, Inventory inventory, Player ply) { - return new DriveRackMenu(containerID, inventory, this); - } - - @Nonnull - @Override - public LazyOptional getCapability(@Nonnull Capability cap, @Nullable Direction side) { - if (cap == MatteryCapability.STORAGE_CELL) { - return cell.get().cast(); + nbt.ifHas("drives", CompoundTag::class.java) { + drives.deserializeNBT(it) } - - return super.getCapability(cap, side); } - @Override - public void invalidateCaps() { - super.invalidateCaps(); - cell.invalidate(); + override fun saveAdditional(nbt: CompoundTag) { + super.saveAdditional(nbt) + nbt["drives"] = drives.serializeNBT() } - @Override - public void reviveCaps() { - super.reviveCaps(); - cell.revive(); + override fun setLevel(p_155231_: Level) { + super.setLevel(p_155231_) + + if (p_155231_ is ServerLevel) + StorageNetworkGraph.discoverFull(this, cell.getAsStorageNode()) } -} + + init { + energy = MatteryMachineEnergyStorage(this, MatteryMachineEnergyStorage.MachineType.WORKER, Fraction(80000)) + } + + override fun getDefaultDisplayName(): Component { + return NAME + } + + override fun createMenu(containerID: Int, inventory: Inventory, ply: Player): AbstractContainerMenu? { + return DriveRackMenu(containerID, inventory, this) + } + + override fun getCapability(cap: Capability, side: Direction?): LazyOptional { + return if (cap === MatteryCapability.STORAGE_CELL) { + cell.get().cast() + } else super.getCapability(cap, side) + } + + override fun invalidateCaps() { + super.invalidateCaps() + cell.invalidate() + } + + override fun reviveCaps() { + super.reviveCaps() + cell.revive() + } + + companion object { + private val NAME = TranslatableComponent("block.overdrive_that_matters.drive_rack") + } +} \ No newline at end of file diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/BlockEntityItemMonitor.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/BlockEntityItemMonitor.kt index af91647bf..bae3321a1 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/BlockEntityItemMonitor.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/BlockEntityItemMonitor.kt @@ -1,79 +1,67 @@ -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.core.Direction; -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.level.Level; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraftforge.common.capabilities.Capability; -import net.minecraftforge.common.util.LazyOptional; -import ru.dbotthepony.mc.otm.Registry; -import ru.dbotthepony.mc.otm.capability.AbstractStorageGridCell; -import ru.dbotthepony.mc.otm.capability.MatteryCapability; -import ru.dbotthepony.mc.otm.capability.MatteryMachineEnergyStorage; -import ru.dbotthepony.mc.otm.core.Fraction; -import ru.dbotthepony.mc.otm.menu.ItemMonitorMenu; +import net.minecraft.core.BlockPos +import net.minecraft.core.Direction +import net.minecraft.network.chat.Component +import net.minecraft.network.chat.TranslatableComponent +import net.minecraft.server.level.ServerLevel +import net.minecraft.world.entity.player.Inventory +import net.minecraft.world.entity.player.Player +import net.minecraft.world.inventory.AbstractContainerMenu +import net.minecraft.world.level.Level +import net.minecraft.world.level.block.state.BlockState +import net.minecraftforge.common.capabilities.Capability +import net.minecraftforge.common.util.LazyOptional +import ru.dbotthepony.mc.otm.Registry +import ru.dbotthepony.mc.otm.graph.storage.BasicStorageGraphNode +import ru.dbotthepony.mc.otm.capability.MatteryCapability +import ru.dbotthepony.mc.otm.capability.MatteryMachineEnergyStorage +import ru.dbotthepony.mc.otm.core.Fraction +import ru.dbotthepony.mc.otm.menu.ItemMonitorMenu +import ru.dbotthepony.mc.otm.graph.storage.StorageNetworkGraph -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import javax.annotation.ParametersAreNonnullByDefault; -import java.math.BigDecimal; +class BlockEntityItemMonitor(p_155229_: BlockPos, p_155230_: BlockState) : + BlockEntityMatteryPowered(Registry.BlockEntities.ITEM_MONITOR, p_155229_, p_155230_) { -@MethodsReturnNonnullByDefault -@ParametersAreNonnullByDefault -public class BlockEntityItemMonitor extends BlockEntityMatteryPowered { - public BlockEntityItemMonitor(BlockPos p_155229_, BlockState p_155230_) { - super(Registry.BlockEntities.ITEM_MONITOR, p_155229_, p_155230_); - energy = new MatteryMachineEnergyStorage(this, MatteryMachineEnergyStorage.MachineType.WORKER, new Fraction(80_000)); + @JvmField + val cell = BasicStorageGraphNode() + + init { + energy = MatteryMachineEnergyStorage(this, MatteryMachineEnergyStorage.MachineType.WORKER, Fraction(80000)) } - public final AbstractStorageGridCell cell = new AbstractStorageGridCell(); - - private static final TranslatableComponent NAME = new TranslatableComponent("block.overdrive_that_matters.item_storage_viewer"); - - @Override - protected Component getDefaultDisplayName() { - return NAME; + override fun getDefaultDisplayName(): Component { + return NAME } - @Nullable - @Override - public AbstractContainerMenu createMenu(int containerID, Inventory inventory, Player ply) { - return new ItemMonitorMenu(containerID, inventory, this); + override fun createMenu(containerID: Int, inventory: Inventory, ply: Player): AbstractContainerMenu { + return ItemMonitorMenu(containerID, inventory, this) } - @Override - public void setLevel(Level p_155231_) { - super.setLevel(p_155231_); + override fun setLevel(p_155231_: Level) { + super.setLevel(p_155231_) - cell.scheduleDiscoverNeighbours(p_155231_, getBlockPos()); + if (p_155231_ is ServerLevel) + StorageNetworkGraph.discoverFull(this, cell.getAsStorageNode()) } - @Nonnull - @Override - public LazyOptional getCapability(@Nonnull Capability cap, @Nullable Direction side) { - if (cap == MatteryCapability.STORAGE_CELL) { - return cell.get().cast(); - } - - return super.getCapability(cap, side); + override fun getCapability(cap: Capability, side: Direction?): LazyOptional { + return if (cap === MatteryCapability.STORAGE_CELL) { + cell.get().cast() + } else super.getCapability(cap, side) } - @Override - public void invalidateCaps() { - super.invalidateCaps(); - cell.invalidate(); + override fun invalidateCaps() { + super.invalidateCaps() + cell.invalidate() } - @Override - public void reviveCaps() { - super.reviveCaps(); - cell.revive(); + override fun reviveCaps() { + super.reviveCaps() + cell.revive() } -} + + companion object { + private val NAME = TranslatableComponent("block.overdrive_that_matters.item_storage_viewer") + } +} \ No newline at end of file diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/DriveRackScreen.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/DriveRackScreen.kt index ca69bf014..76fbeb495 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/DriveRackScreen.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/DriveRackScreen.kt @@ -5,14 +5,23 @@ import ru.dbotthepony.mc.otm.menu.DriveRackMenu import net.minecraft.world.entity.player.Inventory import ru.dbotthepony.mc.otm.client.screen.MatteryScreen import ru.dbotthepony.mc.otm.client.screen.panels.FramePanel +import ru.dbotthepony.mc.otm.client.screen.panels.SlotPanel +import ru.dbotthepony.mc.otm.client.screen.widget.PowerGaugePanel -class DriveRackScreen(menu: DriveRackMenu, inventory: Inventory?, title: Component?) : +class DriveRackScreen(menu: DriveRackMenu, inventory: Inventory, title: Component) : MatteryScreen(menu, inventory, title) { override fun makeMainFrame(): FramePanel { val frame = super.makeMainFrame()!! + PowerGaugePanel(this, frame, menu.battery_widget, LEFT_MARGIN, GAUGE_TOP_WITH_SLOT) + SlotPanel(this, frame, menu.battery_slot, LEFT_MARGIN, SLOT_TOP_UNDER_GAUGE) + SlotPanel(this, frame, menu.drives[0], 71f, 32f) + SlotPanel(this, frame, menu.drives[1], 71f + 18f, 32f) + + SlotPanel(this, frame, menu.drives[2], 71f, 32f + 18f) + SlotPanel(this, frame, menu.drives[3], 71f + 18f, 32f + 18f) return frame } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/graph/storage/BasicStorageGraphNode.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/graph/storage/BasicStorageGraphNode.kt new file mode 100644 index 000000000..3cadfc6e6 --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/graph/storage/BasicStorageGraphNode.kt @@ -0,0 +1,90 @@ +package ru.dbotthepony.mc.otm.graph.storage + +import net.minecraftforge.common.util.LazyOptional +import ru.dbotthepony.mc.otm.graph.Graph6Node +import ru.dbotthepony.mc.otm.storage.IStorageIdentity +import ru.dbotthepony.mc.otm.storage.IStorageStack +import java.util.* + +open class BasicStorageGraphNode : IStorageGraphNode { + private var resolver = LazyOptional.of { this } + private var valid = true + protected val components = ArrayList>() + + private val node = Graph6Node(this) + + override fun getAsStorageNode(): Graph6Node { + return node + } + + override fun getComponents(): List> { + return Collections.unmodifiableList(components) + } + + fun > computeIfAbsent(identity: Class, provider: () -> U): U { + for (component in components) { + if (component.storageIdentity() == identity) { + return component as U + } + } + + val factory = provider() + addStorageComponent(factory) + return factory + } + + fun > computeIfAbsent(identity: Class, provider: (Class) -> U): U { + for (component in components) { + if (component.storageIdentity() == identity) { + return component as U + } + } + + val factory = provider(identity) + addStorageComponent(factory) + return factory + } + + fun addStorageComponent(component: IStorageIdentity<*>) { + for (component1 in components) { + if (component === component1 || component1.storageIdentity() == component.storageIdentity()) { + return + } + } + + detachStorage() + components.add(component) + attachStorage() + } + + fun removeStorageComponent(component: IStorageIdentity<*>) { + for (component1 in components) { + if (component === component1 || component1.storageIdentity() == component.storageIdentity()) { + detachStorage() + components.remove(component1) + attachStorage() + return + } + } + } + + fun invalidate() { + if (!valid) return + valid = false + resolver.invalidate() + // detachStorage(); + } + + fun revive() { + if (valid) return + valid = true + resolver = LazyOptional.of { this } + // attachStorage(); + } + + fun get(): LazyOptional { + return if (valid) resolver else LazyOptional.empty() + } + + override var storageGrid: StorageNetworkGraph? = null +} \ No newline at end of file diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/graph/storage/IStorageGraphNode.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/graph/storage/IStorageGraphNode.kt index 12aa19b0a..fc705d1d4 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/graph/storage/IStorageGraphNode.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/graph/storage/IStorageGraphNode.kt @@ -1,26 +1,13 @@ -package ru.dbotthepony.mc.otm.capability; +package ru.dbotthepony.mc.otm.graph.storage -import net.minecraft.MethodsReturnNonnullByDefault; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.core.SectionPos; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.chunk.LevelChunk; -import ru.dbotthepony.mc.otm.OverdriveThatMatters; -import ru.dbotthepony.mc.otm.storage.IStorageIdentity; -import ru.dbotthepony.mc.otm.storage.StorageGrid; - -import javax.annotation.Nullable; -import javax.annotation.ParametersAreNonnullByDefault; -import java.util.List; - -import static ru.dbotthepony.mc.otm.AbstractGrid.createOrConnectGrid; +import net.minecraft.MethodsReturnNonnullByDefault +import ru.dbotthepony.mc.otm.graph.Graph6Node +import ru.dbotthepony.mc.otm.storage.IStorageIdentity +import javax.annotation.ParametersAreNonnullByDefault @MethodsReturnNonnullByDefault @ParametersAreNonnullByDefault -public interface IStorageGridCell { +interface IStorageGraphNode { /** * Return all providers that this cell can store. Or nothing, if it is not a storage. * @@ -34,64 +21,13 @@ public interface IStorageGridCell { * * @return a list of all providers, inheriting IStorageIdentity, or an empty list */ - List> getComponents(); + fun getComponents(): Collection> + fun getComponentsForView(): Collection> = getComponents() + fun getComponentsForInterfaces(): Collection> = getComponents() + fun getComponentsForExporters(): Collection> = getComponents() + fun detachStorage() = storageGrid?.detach(getAsStorageNode()) + fun attachStorage() = storageGrid?.attach(getAsStorageNode()) + var storageGrid: StorageNetworkGraph? - default List> getComponentsForView() { - return getComponents(); - } - - default List> getComponentsForInterfaces() { - return getComponents(); - } - - default List> getComponentsForExporters() { - return getComponents(); - } - - default void detachStorage() { - var grid = getStorageGrid(); - - if (grid != null) { - grid.detach(this); - } - } - - default void attachStorage() { - var grid = getStorageGrid(); - - if (grid != null) { - grid.attach(this); - } - } - - @Nullable - StorageGrid getStorageGrid(); - void setStorageGrid(@Nullable StorageGrid grid); - boolean isValidStorageCell(); - - default void scheduleDiscoverNeighbours(Level level, BlockPos pos) { - if (level instanceof ServerLevel) - StorageGrid.scheduleDiscoverNeighbours(this, level, pos); - } - - default boolean connectOrCreateStorageGrid(Level level, BlockPos pos) { - return connectOrCreateStorageGrid(level, pos, false); - } - - default void onNeighbourStorageCell(Level level, BlockPos pos, Direction direction, IStorageGridCell cell, BlockEntity entity) { - - } - - default boolean connectOrCreateStorageGrid(Level level, BlockPos pos, boolean force) { - return createOrConnectGrid( - this, - MatteryCapability.STORAGE_CELL, - level, - pos, - force, - StorageGrid::new, - IStorageGridCell::getStorageGrid, - this::onNeighbourStorageCell - ); - } + fun getAsStorageNode(): Graph6Node } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/graph/storage/StorageNetworkGraph.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/graph/storage/StorageNetworkGraph.kt new file mode 100644 index 000000000..22822088b --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/graph/storage/StorageNetworkGraph.kt @@ -0,0 +1,117 @@ +package ru.dbotthepony.mc.otm.graph.storage + +import net.minecraft.MethodsReturnNonnullByDefault +import net.minecraft.server.level.ServerLevel +import net.minecraft.world.level.block.entity.BlockEntity +import ru.dbotthepony.mc.otm.capability.MatteryCapability +import ru.dbotthepony.mc.otm.graph.Abstract6Graph +import ru.dbotthepony.mc.otm.graph.Graph6Node +import ru.dbotthepony.mc.otm.storage.IStorageIdentity +import ru.dbotthepony.mc.otm.storage.IStorageStack +import ru.dbotthepony.mc.otm.storage.VirtualComponent +import javax.annotation.ParametersAreNonnullByDefault + +@MethodsReturnNonnullByDefault +@ParametersAreNonnullByDefault +class StorageNetworkGraph : Abstract6Graph() { + private val virtualComponents = HashMap, VirtualComponent>() + + fun insertObject(type: Class, obj: T, simulate: Boolean): T { + return getVirtualComponent(type).insertStack(obj, simulate) + } + + /** + * @param type Class, representing identity of stored object + * @param The identity itself + * @return a virtual IStorageComponent + */ + fun getVirtualComponent(type: Class): VirtualComponent { + return virtualComponents.computeIfAbsent(type) { VirtualComponent(type) } as VirtualComponent + } + + fun add(identity: IStorageIdentity) { + getVirtualComponent(identity.storageIdentity()).add(identity) + } + + fun remove(identity: IStorageIdentity) { + getVirtualComponent(identity.storageIdentity()).remove(identity) + } + + override fun onNodeRemoved(node: Graph6Node) { + node.value.storageGrid = null + + for (identity in node.value.getComponents()) { + remove(identity) + } + } + + override fun onNodeAdded(node: Graph6Node) { + node.value.storageGrid = this + + for (identity in node.value.getComponents()) { + add(identity) + } + } + + fun detach(node: Graph6Node) { + if (_nodes.contains(node)) { + for (identity in node.value.getComponents()) { + remove(identity) + } + } + } + + fun attach(node: Graph6Node) { + if (_nodes.contains(node)) { + for (identity in node.value.getComponents()) { + add(identity) + } + } + } + + companion object { + @JvmStatic + fun discoverFull(tile: BlockEntity, node: Graph6Node) { + if (tile.level !is ServerLevel) + return + + return discoverFull( + tile.level!! as ServerLevel, + tile.blockPos, + node, + fun(_tile): Graph6Node? { + val resolve = _tile.getCapability(MatteryCapability.STORAGE_CELL) + + return if (resolve.isPresent) { + resolve.resolve().get().getAsStorageNode() + } else { + null + } + }, + ::StorageNetworkGraph + ) + } + + @JvmStatic + fun discover(tile: BlockEntity, node: Graph6Node): Boolean { + if (tile.level !is ServerLevel) + return false + + return discover( + tile.level!! as ServerLevel, + tile.blockPos, + node, + fun(_tile): Graph6Node? { + val resolve = _tile.getCapability(MatteryCapability.STORAGE_CELL) + + return if (resolve.isPresent) { + resolve.resolve().get().getAsStorageNode() + } else { + null + } + }, + ::StorageNetworkGraph + ) + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/Slots.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/Slots.kt index a12d54877..888f820c5 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/Slots.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/Slots.kt @@ -42,3 +42,9 @@ open class PatternSlot(p_40223_: Container, index: Int, x: Int = 0, y: Int = 0) return p_40231_.getCapability(MatteryCapability.PATTERN).isPresent } } + +open class DriveSlot(p_40223_: Container, index: Int, x: Int = 0, y: Int = 0) : MatterySlot(p_40223_, index, x, y) { + override fun mayPlace(p_40231_: ItemStack): Boolean { + return p_40231_.getCapability(MatteryCapability.DRIVE).isPresent + } +} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/storage/API.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/storage/API.kt new file mode 100644 index 000000000..4a53eeeae --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/storage/API.kt @@ -0,0 +1,156 @@ +package ru.dbotthepony.mc.otm.storage + +import ru.dbotthepony.mc.otm.core.Fraction +import java.util.* + +interface IStorageStack { + fun copy(): IStorageStack + + var count: Fraction + fun isEmpty(): Boolean + + /** + * @return max stack size for this stack object + * [Optional.empty()] if unlimited (default) + */ + fun getMaxStackSize(): Optional = Optional.empty() + + /** + * Returns Identity utilized to partition view table (if it has any). + * Defaults to no partitioning; meaning performance will degrade much quicker than it should. + * Good object is an object that will influence on [sameItem] return result, making it return true. + * It is strictly considered that if !this.itemIdentity().equals(other.itemIdentity); + * then this.sameItem(other) will never return true. + * + * If implemented, and storage is also partitioned properly, then performance will be flat equally to view table's performance. + * + * Example: ItemStack#item + */ + fun partitionKey(): Any { + return Any::class.java + } + + /** + * [other] other object to compare; if not the same of this object type just return false + * Returns boolean representing whenever internal state of [this] equals to [other]; + * this include tags, mapping IDs, capabilities, **excluding** amount; + * behavior is pretty much the same as ItemStack.isSameItemSameTags + */ + fun sameItem(other: IStorageStack): Boolean + + fun grow(amount: Fraction) { + count += amount + } + + fun shrink(amount: Fraction) { + count -= amount + } +} + +/** + * Storage system root, along IStorageStack interface + */ +interface IStorageIdentity { + fun storageIdentity(): Class +} + +interface IStorageTrigger : IStorageIdentity { + /** + * [listener] is [IStorageListener] which want to subscribe to our events + */ + fun addListener(listener: IStorageListener): Boolean + + /** + * [listener] is [IStorageListener] which want to unsubscribe from our events + */ + fun removeListener(listener: IStorageListener): Boolean +} + +interface IStorageConsumer : IStorageIdentity { + fun insertStack(stack: T, simulate: Boolean): T +} + +interface IStorageView : IStorageTrigger { + /** + * @param id identifier of object + * @return stored object (not a copy). Do not edit it. + */ + fun getStack(id: UUID): T + + /** + * @param id identifier of object to extract + * @param amount amount of units to extract + * @param simulate whenever to simulate the action or not + * @return copy of object, with amount of units actually extracted + */ + fun extractStack(id: UUID, amount: Fraction, simulate: Boolean): T + + /** + * Designed for views, for extraction with less computation overhead caused by + * copying object extracted + * + * @param id identifier of object to extract + * @param amount desired amount to extract + * @param simulate whenever to simulate the action or not + * @return amount extracted + */ + fun extractStackCount(id: UUID, amount: Fraction, simulate: Boolean): Fraction? { + return extractStack(id, amount, simulate).count + } + + fun getStacks(): Collection> + + fun addListenerAuto(listener: IStorageListener): Boolean { + if (addListener(listener)) { + for (stack in getStacks()) { + listener.addObject(stack.stack(), stack.id(), this) + } + + return true + } + + return false + } + + fun removeListenerAuto(listener: IStorageListener): Boolean { + if (removeListener(listener)) { + for (stack in getStacks()) { + listener.removeObject(stack.id()) + } + + return true + } + + return false + } +} + +interface IStorageListener { + /** + * Fired on whenever an object is added (to listener) we subscribed to + */ + fun addObject(stack: T, id: UUID, provider: IStorageView) + + /** + * Fired on whenever an object is changes on listener we subscribed to + */ + fun changeObject(id: UUID, new_count: Fraction) + + /** + * Fired on whenever an object is removed from listener we subscribed to + */ + fun removeObject(id: UUID) +} + +interface IStorageTuple { + fun id(): UUID + fun stack(): T +} + +@JvmRecord +data class StorageTuple(private val id: UUID, private val stack: T) : IStorageTuple { + override fun id(): UUID = id + override fun stack(): T = stack +} + +interface IStorageComponent : IStorageView, IStorageConsumer diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/storage/IStorageView.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/storage/IStorageView.kt index 88c055f01..e64453201 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/storage/IStorageView.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/storage/IStorageView.kt @@ -1,67 +1,4 @@ -package ru.dbotthepony.mc.otm.storage; +package ru.dbotthepony.mc.otm.storage - -import net.minecraft.MethodsReturnNonnullByDefault; -import ru.dbotthepony.mc.otm.core.Fraction; - -import javax.annotation.ParametersAreNonnullByDefault; -import java.math.BigDecimal; -import java.util.List; -import java.util.UUID; - -@MethodsReturnNonnullByDefault -@ParametersAreNonnullByDefault -public interface IStorageView extends IStorageTrigger { - /** - * @param id identifier of object - * @return stored object (not a copy). Do not edit it. - */ - T getStack(UUID id); - - /** - * @param id identifier of object to extract - * @param amount amount of units to extract - * @param simulate whenever to simulate the action or not - * @return copy of object, with amount of units actually extracted - */ - T extractStack(UUID id, Fraction amount, boolean simulate); - - /** - * Designed for views, for extraction with less computation overhead caused by - * copying object extracted - * - * @param id identifier of object to extract - * @param amount desired amount to extract - * @param simulate whenever to simulate the action or not - * @return amount extracted - */ - default Fraction extractStackCount(UUID id, Fraction amount, boolean simulate) { - return extractStack(id, amount, simulate).getCount(); - } - - List> getStacks(); - - default boolean addListenerAuto(IStorageListener listener) { - if (addListener(listener)) { - for (var stack : getStacks()) { - listener.addObject(stack.stack(), stack.id(), this); - } - - return true; - } - - return false; - } - - default boolean removeListenerAuto(IStorageListener listener) { - if (removeListener(listener)) { - for (var stack : getStacks()) { - listener.removeObject(stack.id()); - } - - return true; - } - - return false; - } -} +import ru.dbotthepony.mc.otm.core.Fraction +import java.util.* diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/storage/ItemStackWrapper.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/storage/ItemStackWrapper.kt index 814919f1f..a89ece183 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/storage/ItemStackWrapper.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/storage/ItemStackWrapper.kt @@ -1,64 +1,44 @@ -package ru.dbotthepony.mc.otm.storage; +package ru.dbotthepony.mc.otm.storage -import net.minecraft.MethodsReturnNonnullByDefault; -import net.minecraft.world.item.ItemStack; -import ru.dbotthepony.mc.otm.core.Fraction; +import net.minecraft.world.item.ItemStack +import ru.dbotthepony.mc.otm.core.Fraction +import java.util.* -import javax.annotation.ParametersAreNonnullByDefault; -import java.math.BigDecimal; -import java.util.Optional; - -@MethodsReturnNonnullByDefault -@ParametersAreNonnullByDefault -public record ItemStackWrapper(ItemStack stack) implements IStorageStack { - public static final ItemStackWrapper EMPTY = new ItemStackWrapper(ItemStack.EMPTY); - - @Override - public IStorageStack copy() { - return new ItemStackWrapper(stack.copy()); +@JvmRecord +data class ItemStackWrapper(val stack: ItemStack) : IStorageStack { + override fun copy(): IStorageStack { + return ItemStackWrapper(stack.copy()) } - @Override - public void setCount(Fraction value) { - setCount(value.toInt()); + fun setCount(value: Int) { + stack.count = Math.max(value, 0) } - public void setCount(int value) { - stack.setCount(Math.max(value, 0)); + override var count: Fraction + get() = Fraction(stack.getCount()) + set(value) = setCount(value.toInt()) + + fun getCountInt() = stack.count + + override fun getMaxStackSize(): Optional { + return Optional.of(Fraction(stack.maxStackSize)) } - @Override - public Fraction getCount() { - return new Fraction(stack.getCount()); + override fun isEmpty(): Boolean = stack.isEmpty + override fun partitionKey(): Any = stack.item + + override fun sameItem(other: IStorageStack): Boolean { + if (this === other) + return true + + if (other is ItemStackWrapper) + return ItemStack.isSameItemSameTags(stack, other.stack); + + return false } - public int getCountInt() { - return stack.getCount(); - } - - @Override - public Optional getMaxStackSize() { - return Optional.of(new Fraction(stack.getMaxStackSize())); - } - - @Override - public boolean isEmpty() { - return stack.isEmpty(); - } - - @Override - public Object partitionKey() { - return stack.getItem(); - } - - @Override - public boolean sameItem(IStorageStack other) { - if (other == this) - return true; - - if (other instanceof ItemStackWrapper obj) - return ItemStack.isSameItemSameTags(stack, obj.stack); - - return false; + companion object { + @JvmField + val EMPTY = ItemStackWrapper(ItemStack.EMPTY) } }