Initial port of storage system to graph
This commit is contained in:
parent
215ecd1f21
commit
4b5a77b92e
@ -9,15 +9,10 @@ import net.minecraft.world.level.block.entity.BlockEntity;
|
|||||||
import net.minecraft.world.level.chunk.LevelChunk;
|
import net.minecraft.world.level.chunk.LevelChunk;
|
||||||
import net.minecraftforge.common.capabilities.Capability;
|
import net.minecraftforge.common.capabilities.Capability;
|
||||||
import net.minecraftforge.common.util.LazyOptional;
|
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 javax.annotation.ParametersAreNonnullByDefault;
|
||||||
import java.security.Provider;
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.function.Consumer;
|
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
@ -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<IStorageGridCell> resolver = LazyOptional.of(() -> this);
|
|
||||||
private boolean valid = true;
|
|
||||||
protected final ArrayList<IStorageIdentity<?>> components = new ArrayList<>();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<? extends IStorageIdentity<?>> getComponents() {
|
|
||||||
return Collections.unmodifiableList(components);
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public <T extends IStorageStack, U extends IStorageIdentity<T>> U computeIfAbsent(Class<T> identity, Supplier<U> provider) {
|
|
||||||
for (var component : components) {
|
|
||||||
if (component.storageIdentity() == identity) {
|
|
||||||
return (U) component;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var factory = provider.get();
|
|
||||||
addStorageComponent(factory);
|
|
||||||
return factory;
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public <T extends IStorageStack, U extends IStorageIdentity<T>> U computeIfAbsent(Class<T> identity, Function<Class<T>, 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<IStorageGridCell> 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;
|
|
||||||
}
|
|
||||||
}
|
|
@ -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.capability.matter.IPatternStorage;
|
||||||
import ru.dbotthepony.mc.otm.core.Fraction;
|
import ru.dbotthepony.mc.otm.core.Fraction;
|
||||||
import ru.dbotthepony.mc.otm.graph.matter.IMatterGraphNode;
|
import ru.dbotthepony.mc.otm.graph.matter.IMatterGraphNode;
|
||||||
|
import ru.dbotthepony.mc.otm.graph.storage.IStorageGraphNode;
|
||||||
|
|
||||||
import java.math.MathContext;
|
import java.math.MathContext;
|
||||||
import java.math.RoundingMode;
|
import java.math.RoundingMode;
|
||||||
@ -21,7 +22,7 @@ public class MatteryCapability {
|
|||||||
public static final Capability<IPatternStorage> PATTERN = CapabilityManager.get(new CapabilityToken<>() {});
|
public static final Capability<IPatternStorage> PATTERN = CapabilityManager.get(new CapabilityToken<>() {});
|
||||||
public static final Capability<IMatterTaskProvider> TASK = CapabilityManager.get(new CapabilityToken<>() {});
|
public static final Capability<IMatterTaskProvider> TASK = CapabilityManager.get(new CapabilityToken<>() {});
|
||||||
public static final Capability<IMatteryDrive> DRIVE = CapabilityManager.get(new CapabilityToken<>() {});
|
public static final Capability<IMatteryDrive> DRIVE = CapabilityManager.get(new CapabilityToken<>() {});
|
||||||
public static final Capability<IStorageGridCell> STORAGE_CELL = CapabilityManager.get(new CapabilityToken<>() {});
|
public static final Capability<IStorageGraphNode> STORAGE_CELL = CapabilityManager.get(new CapabilityToken<>() {});
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public static void register(final RegisterCapabilitiesEvent event) {
|
public static void register(final RegisterCapabilitiesEvent event) {
|
||||||
@ -31,7 +32,7 @@ public class MatteryCapability {
|
|||||||
event.register(IPatternStorage.class);
|
event.register(IPatternStorage.class);
|
||||||
event.register(IMatterTaskProvider.class);
|
event.register(IMatterTaskProvider.class);
|
||||||
event.register(IMatteryDrive.class);
|
event.register(IMatteryDrive.class);
|
||||||
event.register(IStorageGridCell.class);
|
event.register(IStorageGraphNode.class);
|
||||||
event.register(IMatterGraphNode.class);
|
event.register(IMatterGraphNode.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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.SimpleContainer
|
||||||
import net.minecraft.world.entity.player.Inventory;
|
import net.minecraft.world.entity.player.Inventory
|
||||||
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.BlockEntityDriveRack
|
||||||
import ru.dbotthepony.mc.otm.block.entity.BlockEntityDriveRack;
|
|
||||||
import ru.dbotthepony.mc.otm.capability.MatteryCapability;
|
|
||||||
|
|
||||||
public class DriveRackMenu extends PoweredMatteryMenu {
|
class DriveRackMenu @JvmOverloads constructor(
|
||||||
public DriveRackMenu(int p_38852_, Inventory inventory) {
|
p_38852_: Int,
|
||||||
this(p_38852_, inventory, null);
|
inventory: Inventory,
|
||||||
|
tile: BlockEntityDriveRack? = null
|
||||||
|
) : PoweredMatteryMenu(Registry.Menus.DRIVE_RACK, p_38852_, inventory, tile) {
|
||||||
|
val drives = arrayOfNulls<MatterySlot>(4)
|
||||||
|
|
||||||
|
init {
|
||||||
|
val container = tile?.drives ?: SimpleContainer(4)
|
||||||
|
|
||||||
|
for (i in 0 until container.containerSize) {
|
||||||
|
val slot = DriveSlot(container, i)
|
||||||
|
drives[i] = slot
|
||||||
|
addSlot(slot)
|
||||||
}
|
}
|
||||||
|
|
||||||
public final MatterySlot[] drives = new MatterySlot[4];
|
addBatterySlot()
|
||||||
|
addInventorySlots()
|
||||||
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]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
addBatterySlot();
|
override fun getWorkingSlotStart(): Int {
|
||||||
addInventorySlots();
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
override fun getWorkingSlotEnd(): Int {
|
||||||
protected int getWorkingSlotStart() {
|
return 5
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected int getWorkingSlotEnd() {
|
|
||||||
return 5;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,54 +1,43 @@
|
|||||||
package ru.dbotthepony.mc.otm.menu;
|
package ru.dbotthepony.mc.otm.menu
|
||||||
|
|
||||||
import net.minecraft.world.entity.player.Inventory;
|
import net.minecraft.world.entity.player.Inventory
|
||||||
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.menu.data.INetworkedItemViewSupplier;
|
import ru.dbotthepony.mc.otm.menu.data.INetworkedItemViewSupplier
|
||||||
import ru.dbotthepony.mc.otm.menu.data.NetworkedItemView;
|
import ru.dbotthepony.mc.otm.menu.data.NetworkedItemView
|
||||||
import ru.dbotthepony.mc.otm.storage.ItemStackWrapper;
|
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 {
|
override fun getNetworkedItemView(): NetworkedItemView {
|
||||||
public final NetworkedItemView view;
|
return view
|
||||||
|
|
||||||
@Nonnull
|
|
||||||
@Override
|
|
||||||
public NetworkedItemView getNetworkedItemView() {
|
|
||||||
return view;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ItemMonitorMenu(int p_38852_, Inventory inventory) {
|
init {
|
||||||
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);
|
|
||||||
|
|
||||||
if (tile != null) {
|
if (tile != null) {
|
||||||
view.setComponent(tile.cell.getStorageGrid().getVirtualComponent(ItemStackWrapper.class));
|
view.setComponent(tile.cell.storageGrid!!.getVirtualComponent(ItemStackWrapper::class.java))
|
||||||
}
|
}
|
||||||
|
|
||||||
addBatterySlot();
|
addBatterySlot()
|
||||||
addInventorySlots();
|
addInventorySlots()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
override fun broadcastChanges() {
|
||||||
public void broadcastChanges() {
|
super.broadcastChanges()
|
||||||
super.broadcastChanges();
|
view.network()
|
||||||
|
|
||||||
view.network();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
override fun getWorkingSlotStart(): Int {
|
||||||
protected int getWorkingSlotStart() {
|
return 0
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
override fun getWorkingSlotEnd(): Int {
|
||||||
protected int getWorkingSlotEnd() {
|
return 1
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,11 +0,0 @@
|
|||||||
package ru.dbotthepony.mc.otm.storage;
|
|
||||||
|
|
||||||
import net.minecraft.MethodsReturnNonnullByDefault;
|
|
||||||
|
|
||||||
import javax.annotation.ParametersAreNonnullByDefault;
|
|
||||||
|
|
||||||
@MethodsReturnNonnullByDefault
|
|
||||||
@ParametersAreNonnullByDefault
|
|
||||||
public interface IStorageComponent<T extends IStorageStack> extends IStorageView<T>, IStorageConsumer<T> {
|
|
||||||
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
package ru.dbotthepony.mc.otm.storage;
|
|
||||||
|
|
||||||
import net.minecraft.MethodsReturnNonnullByDefault;
|
|
||||||
|
|
||||||
import javax.annotation.ParametersAreNonnullByDefault;
|
|
||||||
|
|
||||||
@MethodsReturnNonnullByDefault
|
|
||||||
@ParametersAreNonnullByDefault
|
|
||||||
public interface IStorageConsumer<T extends IStorageStack> extends IStorageIdentity<T> {
|
|
||||||
T insertStack(T stack, boolean simulate);
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
package ru.dbotthepony.mc.otm.storage;
|
|
||||||
|
|
||||||
import net.minecraft.MethodsReturnNonnullByDefault;
|
|
||||||
|
|
||||||
import javax.annotation.ParametersAreNonnullByDefault;
|
|
||||||
|
|
||||||
@MethodsReturnNonnullByDefault
|
|
||||||
@ParametersAreNonnullByDefault
|
|
||||||
public interface IStorageIdentity<T extends IStorageStack> {
|
|
||||||
Class<T> storageIdentity();
|
|
||||||
}
|
|
@ -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<T extends IStorageStack> {
|
|
||||||
void addObject(T stack, UUID id, IStorageView<T> provider);
|
|
||||||
void changeObject(UUID id, Fraction new_count);
|
|
||||||
void removeObject(UUID id);
|
|
||||||
}
|
|
@ -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<Fraction> 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));
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,12 +0,0 @@
|
|||||||
package ru.dbotthepony.mc.otm.storage;
|
|
||||||
|
|
||||||
import net.minecraft.MethodsReturnNonnullByDefault;
|
|
||||||
|
|
||||||
import javax.annotation.ParametersAreNonnullByDefault;
|
|
||||||
|
|
||||||
@MethodsReturnNonnullByDefault
|
|
||||||
@ParametersAreNonnullByDefault
|
|
||||||
public interface IStorageTrigger<T extends IStorageStack> extends IStorageIdentity<T> {
|
|
||||||
boolean addListener(IStorageListener<T> listener);
|
|
||||||
boolean removeListener(IStorageListener<T> listener);
|
|
||||||
}
|
|
@ -1,8 +0,0 @@
|
|||||||
package ru.dbotthepony.mc.otm.storage;
|
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
public interface IStorageTuple<T extends IStorageStack> {
|
|
||||||
UUID id();
|
|
||||||
T stack();
|
|
||||||
}
|
|
@ -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<IStorageGridCell> {
|
|
||||||
private final HashMap<Class<? extends IStorageStack>, VirtualComponent<? extends IStorageStack>> virtual_components = new HashMap<>();
|
|
||||||
|
|
||||||
public StorageGrid() {
|
|
||||||
super(MatteryCapability.STORAGE_CELL);
|
|
||||||
}
|
|
||||||
|
|
||||||
public <T extends IStorageStack> T insertObject(Class<T> type, T object, boolean simulate) {
|
|
||||||
return getVirtualComponent(type).insertStack(object, simulate);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param type Class, representing identity of stored object
|
|
||||||
* @param <T> The identity itself
|
|
||||||
* @return a virtual IStorageComponent<T>, or null if storage grid contain no view for provided type
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public <T extends IStorageStack> VirtualComponent<T> getVirtualComponent(final Class<T> type) {
|
|
||||||
return (VirtualComponent<T>) virtual_components.computeIfAbsent(type, (k) -> new VirtualComponent<>(type));
|
|
||||||
}
|
|
||||||
|
|
||||||
public <T extends IStorageStack> void add(IStorageIdentity<T> identity) {
|
|
||||||
getVirtualComponent(identity.storageIdentity()).add(identity);
|
|
||||||
}
|
|
||||||
|
|
||||||
public <T extends IStorageStack> void remove(IStorageIdentity<T> 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));
|
|
||||||
}
|
|
||||||
}
|
|
@ -27,6 +27,6 @@ public class StorageObjectRegistry {
|
|||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
public static <T extends IStorageStack> StorageObjectTuple<T> getOrError(Class<T> identity) {
|
public static <T extends IStorageStack> StorageObjectTuple<T> getOrError(Class<T> identity) {
|
||||||
return Objects.requireNonNull(get(identity), "No storage mapping present for " + identity.toString());
|
return Objects.requireNonNull(get(identity), "No storage mapping present for " + identity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +0,0 @@
|
|||||||
package ru.dbotthepony.mc.otm.storage;
|
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
public record StorageTuple<T extends IStorageStack>(UUID id, T stack) implements IStorageTuple<T> {
|
|
||||||
}
|
|
@ -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.BlockPos;
|
import net.minecraft.core.Direction
|
||||||
import net.minecraft.core.Direction;
|
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.server.level.ServerLevel
|
||||||
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.state.BlockState;
|
import net.minecraft.world.level.block.state.BlockState
|
||||||
import net.minecraftforge.common.capabilities.Capability;
|
import net.minecraftforge.common.capabilities.Capability
|
||||||
import net.minecraftforge.common.util.LazyOptional;
|
import net.minecraftforge.common.util.LazyOptional
|
||||||
import ru.dbotthepony.mc.otm.OverdriveThatMatters;
|
import ru.dbotthepony.mc.otm.Registry
|
||||||
import ru.dbotthepony.mc.otm.Registry;
|
import ru.dbotthepony.mc.otm.graph.storage.BasicStorageGraphNode
|
||||||
import ru.dbotthepony.mc.otm.capability.AbstractStorageGridCell;
|
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.DriveRackMenu;
|
import ru.dbotthepony.mc.otm.menu.DriveRackMenu
|
||||||
import ru.dbotthepony.mc.otm.storage.ItemStackWrapper;
|
import ru.dbotthepony.mc.otm.set
|
||||||
import ru.dbotthepony.mc.otm.storage.VirtualComponent;
|
import ru.dbotthepony.mc.otm.graph.storage.StorageNetworkGraph
|
||||||
|
import ru.dbotthepony.mc.otm.storage.VirtualComponent
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
class BlockEntityDriveRack(p_155229_: BlockPos, p_155230_: BlockState) :
|
||||||
import javax.annotation.Nullable;
|
BlockEntityMatteryPowered(Registry.BlockEntities.DRIVE_RACK, p_155229_, p_155230_) {
|
||||||
import javax.annotation.ParametersAreNonnullByDefault;
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
|
|
||||||
@MethodsReturnNonnullByDefault
|
@JvmField
|
||||||
@ParametersAreNonnullByDefault
|
val drives: MatteryContainer = object : MatteryContainer(this::setChanged, 4) {
|
||||||
public class BlockEntityDriveRack extends BlockEntityMatteryPowered {
|
override fun setChanged(slot: Int, new_state: ItemStack, old_state: ItemStack) {
|
||||||
public BlockEntityDriveRack(BlockPos p_155229_, BlockState p_155230_) {
|
super.setChanged(slot, new_state, old_state)
|
||||||
super(Registry.BlockEntities.DRIVE_RACK, p_155229_, p_155230_);
|
|
||||||
energy = new MatteryMachineEnergyStorage(this, MatteryMachineEnergyStorage.MachineType.WORKER, new Fraction(80_000));
|
old_state.getCapability(MatteryCapability.DRIVE).ifPresent {
|
||||||
|
cell.computeIfAbsent(it.storageIdentity()) {c -> VirtualComponent(c)}.remove(it)
|
||||||
}
|
}
|
||||||
|
|
||||||
public final MatteryContainer drives = new MatteryContainer(this::setChanged, 4) {
|
new_state.getCapability(MatteryCapability.DRIVE).ifPresent {
|
||||||
@Override
|
cell.computeIfAbsent(it.storageIdentity()) {c -> VirtualComponent(c)}.add(it)
|
||||||
public void setChanged(int slot, ItemStack new_state, ItemStack old_state) {
|
}
|
||||||
super.setChanged(slot, new_state, old_state);
|
|
||||||
|
|
||||||
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);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
public final AbstractStorageGridCell cell = new AbstractStorageGridCell();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void load(CompoundTag nbt) {
|
|
||||||
super.load(nbt);
|
|
||||||
drives.deserializeNBT(nbt.getCompound("drives"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
val cell = BasicStorageGraphNode()
|
||||||
public void saveAdditional(CompoundTag nbt) {
|
|
||||||
super.saveAdditional(nbt);
|
override fun load(nbt: CompoundTag) {
|
||||||
nbt.put("drives", drives.serializeNBT());
|
super.load(nbt)
|
||||||
|
|
||||||
|
nbt.ifHas("drives", CompoundTag::class.java) {
|
||||||
|
drives.deserializeNBT(it)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
override fun saveAdditional(nbt: CompoundTag) {
|
||||||
public void setLevel(Level p_155231_) {
|
super.saveAdditional(nbt)
|
||||||
super.setLevel(p_155231_);
|
nbt["drives"] = drives.serializeNBT()
|
||||||
|
|
||||||
cell.scheduleDiscoverNeighbours(p_155231_, getBlockPos());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final TranslatableComponent NAME = new TranslatableComponent("block.overdrive_that_matters.drive_rack");
|
override fun setLevel(p_155231_: Level) {
|
||||||
|
super.setLevel(p_155231_)
|
||||||
|
|
||||||
@Override
|
if (p_155231_ is ServerLevel)
|
||||||
protected Component getDefaultDisplayName() {
|
StorageNetworkGraph.discoverFull(this, cell.getAsStorageNode())
|
||||||
return NAME;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
init {
|
||||||
@Override
|
energy = MatteryMachineEnergyStorage(this, MatteryMachineEnergyStorage.MachineType.WORKER, Fraction(80000))
|
||||||
public AbstractContainerMenu createMenu(int containerID, Inventory inventory, Player ply) {
|
|
||||||
return new DriveRackMenu(containerID, inventory, this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
override fun getDefaultDisplayName(): Component {
|
||||||
@Override
|
return NAME
|
||||||
public <T> LazyOptional<T> getCapability(@Nonnull Capability<T> cap, @Nullable Direction side) {
|
|
||||||
if (cap == MatteryCapability.STORAGE_CELL) {
|
|
||||||
return cell.get().cast();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return super.getCapability(cap, side);
|
override fun createMenu(containerID: Int, inventory: Inventory, ply: Player): AbstractContainerMenu? {
|
||||||
|
return DriveRackMenu(containerID, inventory, this)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
override fun <T> getCapability(cap: Capability<T>, side: Direction?): LazyOptional<T> {
|
||||||
public void invalidateCaps() {
|
return if (cap === MatteryCapability.STORAGE_CELL) {
|
||||||
super.invalidateCaps();
|
cell.get().cast()
|
||||||
cell.invalidate();
|
} else super.getCapability(cap, side)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
override fun invalidateCaps() {
|
||||||
public void reviveCaps() {
|
super.invalidateCaps()
|
||||||
super.reviveCaps();
|
cell.invalidate()
|
||||||
cell.revive();
|
}
|
||||||
|
|
||||||
|
override fun reviveCaps() {
|
||||||
|
super.reviveCaps()
|
||||||
|
cell.revive()
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val NAME = TranslatableComponent("block.overdrive_that_matters.drive_rack")
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -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.BlockPos;
|
import net.minecraft.core.Direction
|
||||||
import net.minecraft.core.Direction;
|
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.server.level.ServerLevel
|
||||||
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.level.Level;
|
import net.minecraft.world.level.Level
|
||||||
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.minecraftforge.common.capabilities.Capability
|
||||||
import net.minecraftforge.common.capabilities.Capability;
|
import net.minecraftforge.common.util.LazyOptional
|
||||||
import net.minecraftforge.common.util.LazyOptional;
|
import ru.dbotthepony.mc.otm.Registry
|
||||||
import ru.dbotthepony.mc.otm.Registry;
|
import ru.dbotthepony.mc.otm.graph.storage.BasicStorageGraphNode
|
||||||
import ru.dbotthepony.mc.otm.capability.AbstractStorageGridCell;
|
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.core.Fraction
|
||||||
import ru.dbotthepony.mc.otm.core.Fraction;
|
import ru.dbotthepony.mc.otm.menu.ItemMonitorMenu
|
||||||
import ru.dbotthepony.mc.otm.menu.ItemMonitorMenu;
|
import ru.dbotthepony.mc.otm.graph.storage.StorageNetworkGraph
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
class BlockEntityItemMonitor(p_155229_: BlockPos, p_155230_: BlockState) :
|
||||||
import javax.annotation.Nullable;
|
BlockEntityMatteryPowered(Registry.BlockEntities.ITEM_MONITOR, p_155229_, p_155230_) {
|
||||||
import javax.annotation.ParametersAreNonnullByDefault;
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
|
|
||||||
@MethodsReturnNonnullByDefault
|
@JvmField
|
||||||
@ParametersAreNonnullByDefault
|
val cell = BasicStorageGraphNode()
|
||||||
public class BlockEntityItemMonitor extends BlockEntityMatteryPowered {
|
|
||||||
public BlockEntityItemMonitor(BlockPos p_155229_, BlockState p_155230_) {
|
init {
|
||||||
super(Registry.BlockEntities.ITEM_MONITOR, p_155229_, p_155230_);
|
energy = MatteryMachineEnergyStorage(this, MatteryMachineEnergyStorage.MachineType.WORKER, Fraction(80000))
|
||||||
energy = new MatteryMachineEnergyStorage(this, MatteryMachineEnergyStorage.MachineType.WORKER, new Fraction(80_000));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public final AbstractStorageGridCell cell = new AbstractStorageGridCell();
|
override fun getDefaultDisplayName(): Component {
|
||||||
|
return NAME
|
||||||
private static final TranslatableComponent NAME = new TranslatableComponent("block.overdrive_that_matters.item_storage_viewer");
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Component getDefaultDisplayName() {
|
|
||||||
return NAME;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
override fun createMenu(containerID: Int, inventory: Inventory, ply: Player): AbstractContainerMenu {
|
||||||
@Override
|
return ItemMonitorMenu(containerID, inventory, this)
|
||||||
public AbstractContainerMenu createMenu(int containerID, Inventory inventory, Player ply) {
|
|
||||||
return new ItemMonitorMenu(containerID, inventory, this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
override fun setLevel(p_155231_: Level) {
|
||||||
public void setLevel(Level p_155231_) {
|
super.setLevel(p_155231_)
|
||||||
super.setLevel(p_155231_);
|
|
||||||
|
|
||||||
cell.scheduleDiscoverNeighbours(p_155231_, getBlockPos());
|
if (p_155231_ is ServerLevel)
|
||||||
|
StorageNetworkGraph.discoverFull(this, cell.getAsStorageNode())
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
override fun <T> getCapability(cap: Capability<T>, side: Direction?): LazyOptional<T> {
|
||||||
@Override
|
return if (cap === MatteryCapability.STORAGE_CELL) {
|
||||||
public <T> LazyOptional<T> getCapability(@Nonnull Capability<T> cap, @Nullable Direction side) {
|
cell.get().cast()
|
||||||
if (cap == MatteryCapability.STORAGE_CELL) {
|
} else super.getCapability(cap, side)
|
||||||
return cell.get().cast();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return super.getCapability(cap, side);
|
override fun invalidateCaps() {
|
||||||
|
super.invalidateCaps()
|
||||||
|
cell.invalidate()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
override fun reviveCaps() {
|
||||||
public void invalidateCaps() {
|
super.reviveCaps()
|
||||||
super.invalidateCaps();
|
cell.revive()
|
||||||
cell.invalidate();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
companion object {
|
||||||
public void reviveCaps() {
|
private val NAME = TranslatableComponent("block.overdrive_that_matters.item_storage_viewer")
|
||||||
super.reviveCaps();
|
|
||||||
cell.revive();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -5,14 +5,23 @@ import ru.dbotthepony.mc.otm.menu.DriveRackMenu
|
|||||||
import net.minecraft.world.entity.player.Inventory
|
import net.minecraft.world.entity.player.Inventory
|
||||||
import ru.dbotthepony.mc.otm.client.screen.MatteryScreen
|
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.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<DriveRackMenu>(menu, inventory, title) {
|
MatteryScreen<DriveRackMenu>(menu, inventory, title) {
|
||||||
|
|
||||||
override fun makeMainFrame(): FramePanel {
|
override fun makeMainFrame(): FramePanel {
|
||||||
val frame = super.makeMainFrame()!!
|
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
|
return frame
|
||||||
}
|
}
|
||||||
|
@ -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<IStorageGraphNode> { this }
|
||||||
|
private var valid = true
|
||||||
|
protected val components = ArrayList<IStorageIdentity<*>>()
|
||||||
|
|
||||||
|
private val node = Graph6Node<IStorageGraphNode>(this)
|
||||||
|
|
||||||
|
override fun getAsStorageNode(): Graph6Node<IStorageGraphNode> {
|
||||||
|
return node
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getComponents(): List<IStorageIdentity<*>> {
|
||||||
|
return Collections.unmodifiableList(components)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T : IStorageStack, U : IStorageIdentity<T>> computeIfAbsent(identity: Class<T>, provider: () -> U): U {
|
||||||
|
for (component in components) {
|
||||||
|
if (component.storageIdentity() == identity) {
|
||||||
|
return component as U
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val factory = provider()
|
||||||
|
addStorageComponent(factory)
|
||||||
|
return factory
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T : IStorageStack, U : IStorageIdentity<T>> computeIfAbsent(identity: Class<T>, provider: (Class<T>) -> 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<IStorageGraphNode> {
|
||||||
|
return if (valid) resolver else LazyOptional.empty()
|
||||||
|
}
|
||||||
|
|
||||||
|
override var storageGrid: StorageNetworkGraph? = null
|
||||||
|
}
|
@ -1,26 +1,13 @@
|
|||||||
package ru.dbotthepony.mc.otm.capability;
|
package ru.dbotthepony.mc.otm.graph.storage
|
||||||
|
|
||||||
import net.minecraft.MethodsReturnNonnullByDefault;
|
import net.minecraft.MethodsReturnNonnullByDefault
|
||||||
import net.minecraft.core.BlockPos;
|
import ru.dbotthepony.mc.otm.graph.Graph6Node
|
||||||
import net.minecraft.core.Direction;
|
import ru.dbotthepony.mc.otm.storage.IStorageIdentity
|
||||||
import net.minecraft.core.SectionPos;
|
import javax.annotation.ParametersAreNonnullByDefault
|
||||||
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;
|
|
||||||
|
|
||||||
@MethodsReturnNonnullByDefault
|
@MethodsReturnNonnullByDefault
|
||||||
@ParametersAreNonnullByDefault
|
@ParametersAreNonnullByDefault
|
||||||
public interface IStorageGridCell {
|
interface IStorageGraphNode {
|
||||||
/**
|
/**
|
||||||
* Return all providers that this cell can store. Or nothing, if it is not a storage.
|
* 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
|
* @return a list of all providers, inheriting IStorageIdentity, or an empty list
|
||||||
*/
|
*/
|
||||||
List<? extends IStorageIdentity<?>> getComponents();
|
fun getComponents(): Collection<IStorageIdentity<*>>
|
||||||
|
fun getComponentsForView(): Collection<IStorageIdentity<*>> = getComponents()
|
||||||
|
fun getComponentsForInterfaces(): Collection<IStorageIdentity<*>> = getComponents()
|
||||||
|
fun getComponentsForExporters(): Collection<IStorageIdentity<*>> = getComponents()
|
||||||
|
fun detachStorage() = storageGrid?.detach(getAsStorageNode())
|
||||||
|
fun attachStorage() = storageGrid?.attach(getAsStorageNode())
|
||||||
|
var storageGrid: StorageNetworkGraph?
|
||||||
|
|
||||||
default List<? extends IStorageIdentity<?>> getComponentsForView() {
|
fun getAsStorageNode(): Graph6Node<IStorageGraphNode>
|
||||||
return getComponents();
|
|
||||||
}
|
|
||||||
|
|
||||||
default List<? extends IStorageIdentity<?>> getComponentsForInterfaces() {
|
|
||||||
return getComponents();
|
|
||||||
}
|
|
||||||
|
|
||||||
default List<? extends IStorageIdentity<?>> 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
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -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<IStorageGraphNode>() {
|
||||||
|
private val virtualComponents = HashMap<Class<out IStorageStack>, VirtualComponent<out IStorageStack>>()
|
||||||
|
|
||||||
|
fun <T : IStorageStack> insertObject(type: Class<T>, obj: T, simulate: Boolean): T {
|
||||||
|
return getVirtualComponent(type).insertStack(obj, simulate)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param type Class, representing identity of stored object
|
||||||
|
* @param <T> The identity itself
|
||||||
|
* @return a virtual IStorageComponent<T>
|
||||||
|
*/
|
||||||
|
fun <T : IStorageStack> getVirtualComponent(type: Class<T>): VirtualComponent<T> {
|
||||||
|
return virtualComponents.computeIfAbsent(type) { VirtualComponent(type) } as VirtualComponent<T>
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T : IStorageStack> add(identity: IStorageIdentity<T>) {
|
||||||
|
getVirtualComponent(identity.storageIdentity()).add(identity)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T : IStorageStack> remove(identity: IStorageIdentity<T>) {
|
||||||
|
getVirtualComponent(identity.storageIdentity()).remove(identity)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onNodeRemoved(node: Graph6Node<IStorageGraphNode>) {
|
||||||
|
node.value.storageGrid = null
|
||||||
|
|
||||||
|
for (identity in node.value.getComponents()) {
|
||||||
|
remove(identity)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onNodeAdded(node: Graph6Node<IStorageGraphNode>) {
|
||||||
|
node.value.storageGrid = this
|
||||||
|
|
||||||
|
for (identity in node.value.getComponents()) {
|
||||||
|
add(identity)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun detach(node: Graph6Node<IStorageGraphNode>) {
|
||||||
|
if (_nodes.contains(node)) {
|
||||||
|
for (identity in node.value.getComponents()) {
|
||||||
|
remove(identity)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun attach(node: Graph6Node<IStorageGraphNode>) {
|
||||||
|
if (_nodes.contains(node)) {
|
||||||
|
for (identity in node.value.getComponents()) {
|
||||||
|
add(identity)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
@JvmStatic
|
||||||
|
fun discoverFull(tile: BlockEntity, node: Graph6Node<IStorageGraphNode>) {
|
||||||
|
if (tile.level !is ServerLevel)
|
||||||
|
return
|
||||||
|
|
||||||
|
return discoverFull(
|
||||||
|
tile.level!! as ServerLevel,
|
||||||
|
tile.blockPos,
|
||||||
|
node,
|
||||||
|
fun(_tile): Graph6Node<IStorageGraphNode>? {
|
||||||
|
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<IStorageGraphNode>): Boolean {
|
||||||
|
if (tile.level !is ServerLevel)
|
||||||
|
return false
|
||||||
|
|
||||||
|
return discover(
|
||||||
|
tile.level!! as ServerLevel,
|
||||||
|
tile.blockPos,
|
||||||
|
node,
|
||||||
|
fun(_tile): Graph6Node<IStorageGraphNode>? {
|
||||||
|
val resolve = _tile.getCapability(MatteryCapability.STORAGE_CELL)
|
||||||
|
|
||||||
|
return if (resolve.isPresent) {
|
||||||
|
resolve.resolve().get().getAsStorageNode()
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
::StorageNetworkGraph
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
156
src/main/kotlin/ru/dbotthepony/mc/otm/storage/API.kt
Normal file
156
src/main/kotlin/ru/dbotthepony/mc/otm/storage/API.kt
Normal file
@ -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<Fraction> = 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<T : IStorageStack> {
|
||||||
|
fun storageIdentity(): Class<T>
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IStorageTrigger<T : IStorageStack> : IStorageIdentity<T> {
|
||||||
|
/**
|
||||||
|
* [listener] is [IStorageListener] which want to subscribe to our events
|
||||||
|
*/
|
||||||
|
fun addListener(listener: IStorageListener<T>): Boolean
|
||||||
|
|
||||||
|
/**
|
||||||
|
* [listener] is [IStorageListener] which want to unsubscribe from our events
|
||||||
|
*/
|
||||||
|
fun removeListener(listener: IStorageListener<T>): Boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IStorageConsumer<T : IStorageStack> : IStorageIdentity<T> {
|
||||||
|
fun insertStack(stack: T, simulate: Boolean): T
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IStorageView<T : IStorageStack> : IStorageTrigger<T> {
|
||||||
|
/**
|
||||||
|
* @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<IStorageTuple<T>>
|
||||||
|
|
||||||
|
fun addListenerAuto(listener: IStorageListener<T>): Boolean {
|
||||||
|
if (addListener(listener)) {
|
||||||
|
for (stack in getStacks()) {
|
||||||
|
listener.addObject(stack.stack(), stack.id(), this)
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
fun removeListenerAuto(listener: IStorageListener<T>): Boolean {
|
||||||
|
if (removeListener(listener)) {
|
||||||
|
for (stack in getStacks()) {
|
||||||
|
listener.removeObject(stack.id())
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IStorageListener<T : IStorageStack> {
|
||||||
|
/**
|
||||||
|
* Fired on whenever an object is added (to listener) we subscribed to
|
||||||
|
*/
|
||||||
|
fun addObject(stack: T, id: UUID, provider: IStorageView<T>)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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<T : IStorageStack> {
|
||||||
|
fun id(): UUID
|
||||||
|
fun stack(): T
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmRecord
|
||||||
|
data class StorageTuple<T : IStorageStack>(private val id: UUID, private val stack: T) : IStorageTuple<T> {
|
||||||
|
override fun id(): UUID = id
|
||||||
|
override fun stack(): T = stack
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IStorageComponent<T : IStorageStack> : IStorageView<T>, IStorageConsumer<T>
|
@ -1,67 +1,4 @@
|
|||||||
package ru.dbotthepony.mc.otm.storage;
|
package ru.dbotthepony.mc.otm.storage
|
||||||
|
|
||||||
|
import ru.dbotthepony.mc.otm.core.Fraction
|
||||||
import net.minecraft.MethodsReturnNonnullByDefault;
|
import java.util.*
|
||||||
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<T extends IStorageStack> extends IStorageTrigger<T> {
|
|
||||||
/**
|
|
||||||
* @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<IStorageTuple<T>> getStacks();
|
|
||||||
|
|
||||||
default boolean addListenerAuto(IStorageListener<T> listener) {
|
|
||||||
if (addListener(listener)) {
|
|
||||||
for (var stack : getStacks()) {
|
|
||||||
listener.addObject(stack.stack(), stack.id(), this);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
default boolean removeListenerAuto(IStorageListener<T> listener) {
|
|
||||||
if (removeListener(listener)) {
|
|
||||||
for (var stack : getStacks()) {
|
|
||||||
listener.removeObject(stack.id());
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -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 net.minecraft.world.item.ItemStack;
|
import ru.dbotthepony.mc.otm.core.Fraction
|
||||||
import ru.dbotthepony.mc.otm.core.Fraction;
|
import java.util.*
|
||||||
|
|
||||||
import javax.annotation.ParametersAreNonnullByDefault;
|
@JvmRecord
|
||||||
import java.math.BigDecimal;
|
data class ItemStackWrapper(val stack: ItemStack) : IStorageStack {
|
||||||
import java.util.Optional;
|
override fun copy(): IStorageStack {
|
||||||
|
return ItemStackWrapper(stack.copy())
|
||||||
@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());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
fun setCount(value: Int) {
|
||||||
public void setCount(Fraction value) {
|
stack.count = Math.max(value, 0)
|
||||||
setCount(value.toInt());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCount(int value) {
|
override var count: Fraction
|
||||||
stack.setCount(Math.max(value, 0));
|
get() = Fraction(stack.getCount())
|
||||||
|
set(value) = setCount(value.toInt())
|
||||||
|
|
||||||
|
fun getCountInt() = stack.count
|
||||||
|
|
||||||
|
override fun getMaxStackSize(): Optional<Fraction> {
|
||||||
|
return Optional.of(Fraction(stack.maxStackSize))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
override fun isEmpty(): Boolean = stack.isEmpty
|
||||||
public Fraction getCount() {
|
override fun partitionKey(): Any = stack.item
|
||||||
return new Fraction(stack.getCount());
|
|
||||||
|
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() {
|
companion object {
|
||||||
return stack.getCount();
|
@JvmField
|
||||||
}
|
val EMPTY = ItemStackWrapper(ItemStack.EMPTY)
|
||||||
|
|
||||||
@Override
|
|
||||||
public Optional<Fraction> 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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user