Move to kotlin and streamline more base stuff

This commit is contained in:
DBotThePony 2022-01-04 23:28:00 +07:00
parent 58598f7e3f
commit f23be0c213
Signed by: DBot
GPG Key ID: DCC23B5715498507
25 changed files with 715 additions and 923 deletions

View File

@ -35,13 +35,13 @@ public class BlockAndroidStation extends BlockMattery implements EntityBlock {
}
@Override
public InteractionResult use(BlockState p_60503_, Level level, BlockPos pos, Player ply, InteractionHand p_60507_, BlockHitResult p_60508_) {
public InteractionResult use(BlockState blockState, Level level, BlockPos blockPos, Player ply, InteractionHand hand, BlockHitResult blockHitResult) {
LazyOptional<IAndroidCapability> cap = ply.getCapability(MatteryCapability.ANDROID);
if (cap.resolve().isEmpty() || !cap.resolve().get().isAndroid())
return InteractionResult.FAIL;
return super.use(p_60503_, level, pos, ply, p_60507_, p_60508_);
return super.use(blockState, level, blockPos, ply, hand, blockHitResult);
}
@Override

View File

@ -1,48 +0,0 @@
package ru.dbotthepony.mc.otm.block;
import net.minecraft.MethodsReturnNonnullByDefault;
import net.minecraft.core.Direction;
import net.minecraft.world.item.context.BlockPlaceContext;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.EnumProperty;
import org.apache.commons.lang3.ArrayUtils;
import ru.dbotthepony.mc.otm.OverdriveThatMatters;
import javax.annotation.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;
import java.util.Arrays;
@MethodsReturnNonnullByDefault
@ParametersAreNonnullByDefault
public abstract class BlockMatteryRotatable extends BlockMattery {
public static final EnumProperty<Direction> FACING = EnumProperty.create(
"facing",
Direction.class,
Direction.SOUTH,
Direction.WEST,
Direction.NORTH,
Direction.EAST);
public BlockMatteryRotatable() {
super();
registerDefaultState(this.getStateDefinition().any().setValue(FACING, Direction.SOUTH));
}
@Override
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
builder.add(FACING);
}
@Nullable
@Override
public BlockState getStateForPlacement(BlockPlaceContext context) {
return this.defaultBlockState().setValue(FACING, faceToPlayer(context) ? context.getHorizontalDirection().getOpposite() : context.getHorizontalDirection());
}
public boolean faceToPlayer(BlockPlaceContext context) {
return true;
}
}

View File

@ -1,59 +0,0 @@
package ru.dbotthepony.mc.otm.container;
import net.minecraft.world.Container;
import net.minecraft.world.item.ItemStack;
import net.minecraftforge.common.capabilities.Capability;
import java.util.Iterator;
import java.util.Optional;
import java.util.function.Consumer;
public class ContainerIteratorCapability<T> implements java.util.Iterator<T>, Iterable<T> {
private final Container container;
private final Capability<T> cap;
private int index = 0;
private T next_stack;
public ContainerIteratorCapability(Container container, Capability<T> cap) {
this.container = container;
this.cap = cap;
}
@Override
public boolean hasNext() {
if (index >= container.getContainerSize() && next_stack == null)
return false;
if (next_stack == null) {
while (next_stack == null && index < container.getContainerSize()) {
ItemStack get = container.getItem(index);
if (!get.isEmpty()) {
get.getCapability(cap).ifPresent(t -> next_stack = t);
}
index++;
}
}
return next_stack != null;
}
@Override
public T next() {
T _next_stack = next_stack;
next_stack = null;
return _next_stack;
}
@Override
public Iterator<T> iterator() {
return this;
}
public void consume(Consumer<T> consumer) {
for (T t : this) {
consumer.accept(t);
}
}
}

View File

@ -1,55 +0,0 @@
package ru.dbotthepony.mc.otm.container;
import net.minecraft.world.Container;
import net.minecraft.world.item.ItemStack;
import java.util.Iterator;
import java.util.function.Consumer;
public class ContainerIteratorItemStack implements java.util.Iterator<ItemStack>, Iterable<ItemStack> {
private final Container container;
private int index = 0;
private ItemStack next_stack;
public ContainerIteratorItemStack(Container container) {
this.container = container;
}
@Override
public boolean hasNext() {
if (index >= container.getContainerSize() && next_stack == null)
return false;
if (next_stack == null) {
while (next_stack == null && index < container.getContainerSize()) {
ItemStack get = container.getItem(index);
if (!get.isEmpty()) {
next_stack = get;
}
index++;
}
}
return next_stack != null;
}
@Override
public ItemStack next() {
ItemStack _next_stack = next_stack;
next_stack = null;
return _next_stack;
}
@Override
public Iterator<ItemStack> iterator() {
return this;
}
public void consume(Consumer<ItemStack> consumer) {
for (ItemStack t : this) {
consumer.accept(t);
}
}
}

View File

@ -1,10 +0,0 @@
package ru.dbotthepony.mc.otm.container;
import net.minecraft.world.item.ItemStack;
import javax.annotation.Nonnull;
@FunctionalInterface
public interface MatteryContainerExtractValidator {
boolean apply(int slot, int amount, @Nonnull ItemStack stack);
}

View File

@ -1,10 +0,0 @@
package ru.dbotthepony.mc.otm.container;
import net.minecraft.world.item.ItemStack;
import javax.annotation.Nonnull;
@FunctionalInterface
public interface MatteryContainerInsertValidator {
boolean apply(int slot, @Nonnull ItemStack stack);
}

View File

@ -51,7 +51,7 @@ inline fun CompoundTag.ifHas(s: String, type: Byte, consumer: (Tag) -> Unit) {
inline fun <reified T : Tag> CompoundTag.ifHas(s: String, type: Class<T>, consumer: (T) -> Unit) {
val tag = get(s)
if (tag != null && tag::class.java == type) {
if (tag != null && tag::class.java === type) {
consumer(tag as T)
}
}

View File

@ -1,6 +1,7 @@
package ru.dbotthepony.mc.otm.block
import net.minecraft.core.BlockPos
import net.minecraft.world.item.context.BlockPlaceContext
import net.minecraft.world.level.Level
import net.minecraft.world.level.block.Block
import net.minecraft.world.level.block.EntityBlock
@ -36,6 +37,10 @@ class BlockDriveViewer : BlockMatteryRotatable(), EntityBlock {
builder.add(DRIVE_PRESENT)
}
override fun getStateForPlacement(context: BlockPlaceContext): BlockState {
return super.getStateForPlacement(context)!!.setValue(DRIVE_PRESENT, false)
}
companion object {
val DRIVE_PRESENT = BooleanProperty.create("drive")
}

View File

@ -1,67 +1,121 @@
package ru.dbotthepony.mc.otm.block;
package ru.dbotthepony.mc.otm.block
import net.minecraft.MethodsReturnNonnullByDefault;
import net.minecraft.core.BlockPos;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.MenuProvider;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.EntityBlock;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.material.Material;
import net.minecraft.world.level.material.MaterialColor;
import net.minecraft.world.phys.BlockHitResult;
import ru.dbotthepony.mc.otm.block.entity.BlockEntityMattery;
import net.minecraft.core.BlockPos
import net.minecraft.core.Direction
import net.minecraft.world.InteractionHand
import net.minecraft.world.InteractionResult
import net.minecraft.world.MenuProvider
import net.minecraft.world.entity.LivingEntity
import net.minecraft.world.entity.player.Player
import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.context.BlockPlaceContext
import net.minecraft.world.level.Level
import net.minecraft.world.level.block.Block
import net.minecraft.world.level.block.EntityBlock
import net.minecraft.world.level.block.state.BlockState
import net.minecraft.world.level.block.state.StateDefinition
import net.minecraft.world.level.block.state.properties.EnumProperty
import net.minecraft.world.level.material.Material
import net.minecraft.world.level.material.MaterialColor
import net.minecraft.world.phys.BlockHitResult
import ru.dbotthepony.mc.otm.block.entity.BlockEntityMattery
import javax.annotation.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;
abstract class BlockMattery @JvmOverloads constructor(
properties: Properties = DEFAULT_PROPERTIES
) : Block(properties) {
override fun setPlacedBy(
level: Level,
blockPos: BlockPos,
blockState: BlockState,
entity: LivingEntity?,
itemStack: ItemStack
) {
if (this is EntityBlock && itemStack.hasCustomHoverName() && !level.isClientSide) {
val tile = level.getBlockEntity(blockPos)
@MethodsReturnNonnullByDefault
@ParametersAreNonnullByDefault
public abstract class BlockMattery extends Block {
public BlockMattery(Properties p_49795_) {
super(p_49795_);
}
public BlockMattery() {
this(BlockBehaviour.Properties.of(Material.STONE, MaterialColor.METAL).requiresCorrectToolForDrops().strength(1.5F, 25.0F));
}
@Override
public void setPlacedBy(Level p_49847_, BlockPos p_49848_, BlockState p_49849_, @Nullable LivingEntity p_49850_, ItemStack p_49851_) {
if (this instanceof EntityBlock && p_49851_.hasCustomHoverName() && !p_49847_.isClientSide && p_49847_.getBlockEntity(p_49848_) instanceof BlockEntityMattery tile) {
tile.setDisplayName(p_49851_.getDisplayName());
if (tile is BlockEntityMattery)
tile.customDisplayName = itemStack.displayName
}
super.setPlacedBy(p_49847_, p_49848_, p_49849_, p_49850_, p_49851_);
super.setPlacedBy(level, blockPos, blockState, entity, itemStack)
}
@Override
@SuppressWarnings("deprecation")
public InteractionResult use(BlockState p_60503_, Level level, BlockPos pos, Player ply, InteractionHand p_60507_, BlockHitResult p_60508_) {
if (this instanceof EntityBlock && !level.isClientSide && level.getBlockEntity(pos) instanceof MenuProvider tile) {
ply.openMenu(tile);
return InteractionResult.CONSUME;
override fun use(
blockState: BlockState,
level: Level,
blockPos: BlockPos,
ply: Player,
hand: InteractionHand,
blockHitResult: BlockHitResult
): InteractionResult {
if (this is EntityBlock && !level.isClientSide) {
val tile = level.getBlockEntity(blockPos)
if (tile is MenuProvider) {
ply.openMenu(tile)
return InteractionResult.CONSUME
}
}
if (this instanceof EntityBlock && level.isClientSide)
return InteractionResult.SUCCESS;
if (this is EntityBlock && level.isClientSide)
return InteractionResult.SUCCESS
return super.use(p_60503_, level, pos, ply, p_60507_, p_60508_);
return super.use(blockState, level, blockPos, ply, hand, blockHitResult)
}
@Override
@SuppressWarnings("deprecation")
public void neighborChanged(BlockState state, Level level, BlockPos pos, Block sender, BlockPos sender_pos, boolean flag) {
super.neighborChanged(state, level, pos, sender, sender_pos, flag);
override fun neighborChanged(
state: BlockState,
level: Level,
pos: BlockPos,
sender: Block,
sender_pos: BlockPos,
flag: Boolean
) {
super.neighborChanged(state, level, pos, sender, sender_pos, flag)
if (this instanceof EntityBlock && !level.isClientSide && level.getBlockEntity(pos) instanceof BlockEntityMattery tile) {
tile.setRedstoneSignal(level.getBestNeighborSignal(pos));
if (this is EntityBlock && !level.isClientSide) {
val tile = level.getBlockEntity(pos)
if (tile is BlockEntityMattery)
tile.redstoneSignal = level.getBestNeighborSignal(pos)
}
}
companion object {
@JvmField
val DEFAULT_PROPERTIES: Properties = Properties.of(Material.STONE, MaterialColor.METAL).requiresCorrectToolForDrops().strength(1.5f, 25.0f)
}
}
abstract class BlockMatteryRotatable @JvmOverloads constructor(properties: Properties = DEFAULT_PROPERTIES) : BlockMattery(properties) {
init {
registerDefaultState(getStateDefinition().any().setValue(FACING, Direction.SOUTH))
}
override fun createBlockStateDefinition(builder: StateDefinition.Builder<Block, BlockState>) {
builder.add(FACING)
}
override fun getStateForPlacement(context: BlockPlaceContext): BlockState? {
return defaultBlockState().setValue(
FACING,
if (faceToPlayer(context)) context.horizontalDirection.opposite else context.horizontalDirection
)
}
open fun faceToPlayer(context: BlockPlaceContext): Boolean {
return true
}
companion object {
@JvmField
val FACING = EnumProperty.create(
"facing",
Direction::class.java,
Direction.SOUTH,
Direction.WEST,
Direction.NORTH,
Direction.EAST
)
}
}

View File

@ -19,7 +19,6 @@ import net.minecraftforge.common.util.LazyOptional
import net.minecraftforge.energy.CapabilityEnergy
import net.minecraftforge.energy.IEnergyStorage
import net.minecraftforge.items.CapabilityItemHandler
import net.minecraftforge.items.IItemHandler
import ru.dbotthepony.mc.otm.Registry
import ru.dbotthepony.mc.otm.block.BlockBatteryBank
import ru.dbotthepony.mc.otm.block.BlockMatteryRotatable
@ -40,8 +39,8 @@ import javax.annotation.ParametersAreNonnullByDefault
class BlockEntityBatteryBank(p_155229_: BlockPos, p_155230_: BlockState) : BlockEntityMattery(Registry.BlockEntities.BATTERY_BANK, p_155229_, p_155230_) {
// 6 на 2
val container: MatteryContainer = object : MatteryContainer(this::setChanged, 6 * 2) {
override fun setChanged(slot: Int, new_state: ItemStack, old_state: ItemStack) {
super.setChanged(slot, new_state, old_state)
override fun setChanged(slot: Int, new: ItemStack, old: ItemStack) {
super.setChanged(slot, new, old)
val level = level
if (level != null) {

View File

@ -31,14 +31,14 @@ class BlockEntityDriveRack(p_155229_: BlockPos, p_155230_: BlockState) :
@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)
override fun setChanged(slot: Int, new: ItemStack, old: ItemStack) {
super.setChanged(slot, new, old)
old_state.getCapability(MatteryCapability.DRIVE).ifPresent {
old.getCapability(MatteryCapability.DRIVE).ifPresent {
cell.computeIfAbsent(it.storageIdentity()) {c -> PoweredVirtualComponent(c, energy)}.remove(it)
}
new_state.getCapability(MatteryCapability.DRIVE).ifPresent {
new.getCapability(MatteryCapability.DRIVE).ifPresent {
cell.computeIfAbsent(it.storageIdentity()) {c -> PoweredVirtualComponent(c, energy)}.add(it)
}
}

View File

@ -9,7 +9,6 @@ import net.minecraft.world.entity.player.Inventory
import net.minecraft.world.entity.player.Player
import net.minecraft.world.inventory.AbstractContainerMenu
import net.minecraft.world.item.ItemStack
import net.minecraft.world.level.Level
import net.minecraft.world.level.block.Block
import net.minecraft.world.level.block.state.BlockState
import ru.dbotthepony.mc.otm.OverdriveThatMatters
@ -54,8 +53,8 @@ class BlockEntityDriveViewer(p_155229_: BlockPos, p_155230_: BlockState) : Block
@JvmField
val drive_slot: MatteryContainer = object : MatteryContainer(this::setChanged, 1) {
override fun setChanged(slot: Int, new_state: ItemStack, old_state: ItemStack) {
super.setChanged(slot, new_state, old_state)
override fun setChanged(slot: Int, new: ItemStack, old: ItemStack) {
super.setChanged(slot, new, old)
val level = level
if (level != null) {
@ -63,7 +62,7 @@ class BlockEntityDriveViewer(p_155229_: BlockPos, p_155230_: BlockState) : Block
if (!isRemoved) {
var state = blockState
if (new_state.getCapability(MatteryCapability.DRIVE).isPresent) {
if (new.getCapability(MatteryCapability.DRIVE).isPresent) {
state = state.setValue(BlockDriveViewer.DRIVE_PRESENT, true)
} else {
state = state.setValue(BlockDriveViewer.DRIVE_PRESENT, false)

View File

@ -2,35 +2,36 @@ package ru.dbotthepony.mc.otm.block.entity
import net.minecraft.core.BlockPos
import net.minecraft.core.Direction
import net.minecraft.world.level.block.state.BlockState
import ru.dbotthepony.mc.otm.container.MatteryContainer
import net.minecraft.world.item.ItemStack
import ru.dbotthepony.mc.otm.capability.matter.IMatterHandler
import ru.dbotthepony.mc.otm.capability.MatteryCapability
import ru.dbotthepony.mc.otm.capability.matter.MatterHandlerCapability
import ru.dbotthepony.mc.otm.capability.matter.IMatterHandler.MatterDirection
import net.minecraftforge.common.util.LazyOptional
import net.minecraftforge.items.CapabilityItemHandler
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 ru.dbotthepony.mc.otm.menu.MatterBottlerMenu
import net.minecraft.nbt.CompoundTag
import net.minecraft.network.chat.Component
import ru.dbotthepony.mc.otm.capability.MatteryMachineEnergyStorage
import net.minecraft.network.chat.TranslatableComponent
import net.minecraft.server.level.ServerLevel
import net.minecraft.world.item.ItemStack
import net.minecraft.world.level.Level
import net.minecraft.world.level.block.Block
import net.minecraft.world.level.block.state.BlockState
import net.minecraftforge.common.capabilities.Capability
import net.minecraftforge.common.util.LazyOptional
import net.minecraftforge.items.CapabilityItemHandler
import ru.dbotthepony.mc.otm.Registry
import ru.dbotthepony.mc.otm.block.BlockMatterBottler
import ru.dbotthepony.mc.otm.block.entity.worker.WorkerState
import ru.dbotthepony.mc.otm.capability.MatteryCapability
import ru.dbotthepony.mc.otm.capability.MatteryMachineEnergyStorage
import ru.dbotthepony.mc.otm.capability.matter.IMatterHandler
import ru.dbotthepony.mc.otm.capability.matter.IMatterHandler.MatterDirection
import ru.dbotthepony.mc.otm.capability.matter.MatterHandlerCapability
import ru.dbotthepony.mc.otm.container.MatteryContainer
import ru.dbotthepony.mc.otm.container.MatteryContainerHandler
import ru.dbotthepony.mc.otm.core.Fraction
import ru.dbotthepony.mc.otm.graph.Graph6Node
import ru.dbotthepony.mc.otm.graph.matter.IMatterGraphNode
import ru.dbotthepony.mc.otm.graph.matter.MatterNetworkGraph
import ru.dbotthepony.mc.otm.ifHas
import ru.dbotthepony.mc.otm.menu.MatterBottlerMenu
import ru.dbotthepony.mc.otm.set
class BlockEntityMatterBottler(p_155229_: BlockPos, p_155230_: BlockState) :
@ -86,8 +87,8 @@ class BlockEntityMatterBottler(p_155229_: BlockPos, p_155230_: BlockState) :
return 1
}
override fun setChanged(slot: Int, new_state: ItemStack, old_state: ItemStack) {
super.setChanged(slot, new_state, old_state)
override fun setChanged(slot: Int, new: ItemStack, old: ItemStack) {
super.setChanged(slot, new, old)
updateBlockState()
}
}

View File

@ -123,8 +123,8 @@ class BlockEntityMatterCapacitorBank(p_155229_: BlockPos, p_155230_: BlockState)
@JvmField
val matterContainer = object : MatteryContainer(this::setChangedLight, 6 * 2) {
override fun setChanged(slot: Int, new_state: ItemStack, old_state: ItemStack) {
super.setChanged(slot, new_state, old_state)
override fun setChanged(slot: Int, new: ItemStack, old: ItemStack) {
super.setChanged(slot, new, old)
val level = level
if (level != null) {

View File

@ -75,7 +75,7 @@ class BlockEntityMatterDecomposer(pos: BlockPos, state: BlockState)
{ slot: Int, amount: Int, stack: ItemStack? -> slot == 1 })
}
override fun getDefaultDisplayName(): Component? {
override fun getDefaultDisplayName(): Component {
return MACHINE_NAME
}

View File

@ -1,182 +1,169 @@
package ru.dbotthepony.mc.otm.block.entity;
package ru.dbotthepony.mc.otm.block.entity
import net.minecraft.MethodsReturnNonnullByDefault;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.nbt.ByteTag;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.StringTag;
import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.MenuProvider;
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.BlockEntity;
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.capabilities.ICapabilityProvider;
import net.minecraftforge.common.util.LazyOptional;
import ru.dbotthepony.mc.otm.OverdriveThatMatters;
import net.minecraft.world.level.block.entity.BlockEntityType
import net.minecraft.core.BlockPos
import net.minecraft.world.level.block.state.BlockState
import net.minecraft.world.level.block.entity.BlockEntity
import net.minecraft.world.MenuProvider
import java.lang.Runnable
import ru.dbotthepony.mc.otm.OverdriveThatMatters
import net.minecraft.server.level.ServerLevel
import net.minecraft.client.multiplayer.ClientLevel
import net.minecraft.core.Direction
import net.minecraft.core.SectionPos
import net.minecraftforge.common.util.LazyOptional
import net.minecraftforge.common.capabilities.ICapabilityProvider
import java.lang.ref.WeakReference
import net.minecraft.world.entity.player.Inventory
import net.minecraft.world.entity.player.Player
import net.minecraft.world.inventory.AbstractContainerMenu
import net.minecraft.nbt.CompoundTag
import net.minecraft.nbt.StringTag
import net.minecraft.nbt.ByteTag
import net.minecraft.network.chat.Component
import net.minecraft.world.level.Level
import net.minecraft.world.level.chunk.ChunkStatus
import net.minecraftforge.common.capabilities.Capability
import ru.dbotthepony.mc.otm.ifHas
import ru.dbotthepony.mc.otm.set
import java.util.function.Consumer
import javax.annotation.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;
import java.lang.ref.WeakReference;
import java.util.function.Consumer;
abstract class BlockEntityMattery(p_155228_: BlockEntityType<*>, p_155229_: BlockPos, p_155230_: BlockState) : BlockEntity(p_155228_, p_155229_, p_155230_), MenuProvider {
var customDisplayName: Component? = null
var redstoneSignal = 0
set(level) {
val old = isBlockedByRedstone
field = level
val state = isBlockedByRedstone
@MethodsReturnNonnullByDefault
@ParametersAreNonnullByDefault
@SuppressWarnings("unused")
public abstract class BlockEntityMattery extends BlockEntity implements MenuProvider {
protected Component display_name;
protected RedstoneSetting redstone_setting = RedstoneSetting.LOW;
protected int redstone_signal = 0;
public BlockEntityMattery(BlockEntityType<?> p_155228_, BlockPos p_155229_, BlockState p_155230_) {
super(p_155228_, p_155229_, p_155230_);
}
public void setDisplayName(Component text) {
display_name = text;
}
abstract protected Component getDefaultDisplayName();
protected void tickOnce(Runnable func) {
if (level != null)
OverdriveThatMatters.tickOnce(level, func);
}
protected void tickOnceServer(Runnable func) {
if (level instanceof ServerLevel level)
OverdriveThatMatters.tickOnce(level, func);
}
protected void tickOnceClient(Runnable func) {
if (level instanceof ClientLevel level)
OverdriveThatMatters.tickOnce(level, func);
}
protected void tickOnce(Consumer<Level> func) {
if (level != null)
OverdriveThatMatters.tickOnceSelf(level, func);
}
protected void tickOnceServer(Consumer<Level> func) {
if (level instanceof ServerLevel level)
OverdriveThatMatters.tickOnceSelf(level, func);
}
protected void tickOnceClient(Consumer<Level> func) {
if (level instanceof ClientLevel level)
OverdriveThatMatters.tickOnceSelf(level, func);
}
protected <T> LazyOptional<T> getAndBind(LazyOptional<T> old, @Nullable ICapabilityProvider provider, Capability<T> cap, @Nullable Direction side, Runnable invalidate) {
final var get = provider != null ? provider.getCapability(cap, side) : LazyOptional.empty();
if (old != get) {
if (get.isPresent()) {
final var ref = new WeakReference<>(invalidate);
get.addListener((l) -> {
final var self = ref.get();
if (self != null) {
self.run();
}
});
}
return get.cast();
}
return get.cast();
}
@Override
public Component getDisplayName() {
return display_name != null ? display_name : getDefaultDisplayName();
}
@Nullable
@Override
abstract public AbstractContainerMenu createMenu(int containerID, Inventory inventory, Player ply);
protected void redstoneStatusUpdated(boolean new_blocked, boolean old_blocked) {
}
public void setRedstoneSignal(int level) {
final var old = isBlockedByRedstone();
redstone_signal = level;
final var state = isBlockedByRedstone();
if (old != state) {
redstoneStatusUpdated(state, old);
}
}
public void setRedstoneSetting(RedstoneSetting setting) {
final var old = isBlockedByRedstone();
redstone_setting = setting;
final var state = isBlockedByRedstone();
if (old != state) {
redstoneStatusUpdated(state, old);
}
}
public RedstoneSetting getRedstoneSetting() {
return redstone_setting;
}
protected boolean isBlockedByRedstone() {
switch (redstone_setting) {
case LOW -> {
return redstone_signal > 0;
}
case HIGH -> {
return redstone_signal <= 0;
if (old != state) {
redstoneStatusUpdated(state, old)
}
}
return false;
var redstoneSetting: RedstoneSetting = RedstoneSetting.LOW
set(setting) {
val old = isBlockedByRedstone
field = setting
val state = isBlockedByRedstone
if (old != state) {
redstoneStatusUpdated(state, old)
}
}
val isBlockedByRedstone: Boolean
get() {
when (redstoneSetting) {
RedstoneSetting.LOW -> {
return redstoneSignal > 0
}
RedstoneSetting.HIGH -> {
return redstoneSignal <= 0
}
RedstoneSetting.IGNORED -> {
return false
}
}
}
protected abstract fun getDefaultDisplayName(): Component
abstract override fun createMenu(containerID: Int, inventory: Inventory, ply: Player): AbstractContainerMenu?
protected fun tickOnce(func: Runnable) {
val level = level
if (level != null) OverdriveThatMatters.tickOnce(level, func)
}
@Override
public void saveAdditional(CompoundTag nbt) {
super.saveAdditional(nbt);
if (display_name != null)
nbt.putString("Name", Component.Serializer.toJson(display_name));
nbt.putByte("redstone", (byte) redstone_setting.ordinal());
nbt.putByte("redstone_signal", (byte) redstone_signal);
protected fun tickOnceServer(func: Runnable) {
val level = level
if (level is ServerLevel) OverdriveThatMatters.tickOnce(level, func)
}
public void load(CompoundTag nbt) {
super.load(nbt);
protected fun tickOnceClient(func: Runnable) {
val level = level
if (level is ClientLevel) OverdriveThatMatters.tickOnce(level, func)
}
if (nbt.get("Name") instanceof StringTag tag)
display_name = Component.Serializer.fromJson(tag.getAsString());
protected fun tickOnce(func: Consumer<Level>) {
val level = level
if (level != null) OverdriveThatMatters.tickOnceSelf(level, func)
}
if (nbt.get("redstone") instanceof ByteTag tag)
redstone_setting = RedstoneSetting.get(tag.getAsByte());
protected fun tickOnceServer(func: Consumer<Level>) {
val level = level
if (level is ServerLevel) OverdriveThatMatters.tickOnceSelf(level, func)
}
if (nbt.get("redstone_signal") instanceof ByteTag tag)
redstone_signal = tag.getAsByte();
protected fun tickOnceClient(func: Consumer<Level>) {
val level = level
if (level is ClientLevel) OverdriveThatMatters.tickOnceSelf(level, func)
}
protected fun <T> getAndBind(
old: LazyOptional<T>,
provider: ICapabilityProvider?,
cap: Capability<T>,
side: Direction,
invalidate: Runnable
): LazyOptional<T> {
val get = provider?.getCapability(cap, side) ?: LazyOptional.empty()
if (old !== get) {
if (get.isPresent) {
val ref = WeakReference(invalidate)
get.addListener {
ref.get()?.run()
}
}
return get.cast()
}
return get.cast()
}
override fun getDisplayName(): Component {
return customDisplayName ?: getDefaultDisplayName()
}
protected open fun redstoneStatusUpdated(new_blocked: Boolean, old_blocked: Boolean) {}
override fun saveAdditional(nbt: CompoundTag) {
super.saveAdditional(nbt)
val customDisplayName = customDisplayName
if (customDisplayName != null)
nbt.putString("Name", Component.Serializer.toJson(customDisplayName))
nbt["redstone"] = redstoneSetting.ordinal.toByte()
nbt["redstone_signal"] = redstoneSignal.toByte()
}
override fun load(nbt: CompoundTag) {
super.load(nbt)
nbt.ifHas("Name", StringTag::class.java) {
customDisplayName = Component.Serializer.fromJson(it.asString)
}
nbt.ifHas("redstone", ByteTag::class.java) {
redstoneSetting = RedstoneSetting.get(it.asInt)
}
nbt.ifHas("redstone_signal", ByteTag::class.java) {
redstoneSignal = it.asInt
}
}
// Just to mark chunk unsaved
public void setChangedLight() {
if (level != null) {
if (level.hasChunkAt(getBlockPos()))
level.getChunkAt(getBlockPos()).setUnsaved(true);
open fun setChangedLight() {
val level = level
if (level is ServerLevel) {
level.chunkSource.getChunkNow(
SectionPos.blockToSectionCoord(blockPos.x),
SectionPos.blockToSectionCoord(blockPos.z))?.isUnsaved = true
}
}
}

View File

@ -1,132 +1,80 @@
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.world.item.ItemStack;
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 net.minecraftforge.energy.CapabilityEnergy;
import net.minecraftforge.energy.IEnergyStorage;
import ru.dbotthepony.mc.otm.capability.IMatteryEnergyStorage;
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 net.minecraft.core.BlockPos
import net.minecraft.core.Direction
import net.minecraft.nbt.CompoundTag
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 net.minecraftforge.energy.CapabilityEnergy
import ru.dbotthepony.mc.otm.capability.IMatteryEnergyStorage
import ru.dbotthepony.mc.otm.capability.MatteryCapability
import ru.dbotthepony.mc.otm.capability.MatteryMachineEnergyStorage
import ru.dbotthepony.mc.otm.capability.extractEnergy
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.set
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;
import java.math.BigDecimal;
import java.util.Optional;
abstract class BlockEntityMatteryPowered(p_155228_: BlockEntityType<*>, p_155229_: BlockPos, p_155230_: BlockState) : BlockEntityMattery(p_155228_, p_155229_, p_155230_) {
protected lateinit var energy: MatteryMachineEnergyStorage
private var resolverEnergy = LazyOptional.of { energy }
private var valid = true
val batteryContainer = MatteryContainer(this::setChangedLight, 1)
@MethodsReturnNonnullByDefault
@ParametersAreNonnullByDefault
abstract public class BlockEntityMatteryPowered extends BlockEntityMattery {
protected MatteryMachineEnergyStorage energy = null;
private LazyOptional<MatteryMachineEnergyStorage> energy_resolver = LazyOptional.of(() -> energy);
private boolean valid = true;
protected fun batteryChargeLoop() {
var demand = energy.receiveEnergyOuter(energy.missingPower, true)
if (demand.isZero()) return
public MatteryContainer battery_container = new MatteryContainer(this::setChanged, 1);
protected void batteryChargeLoop() {
if (energy == null)
return;
if (energy.getMissingPower().compareTo(Fraction.ZERO) <= 0)
return;
var demand = energy.getMissingPower();
if (demand.compareTo(Fraction.ZERO) == 0)
return;
demand = demand.min(energy.receiveEnergyOuter(demand, true));
for (int i = 0; i < battery_container.getContainerSize() && demand.compareTo(Fraction.ZERO) > 0; i++) {
final var stack = battery_container.getItem(i);
if (!stack.isEmpty()) {
final var mattery_storage = stack.getCapability(MatteryCapability.ENERGY).resolve();
if (mattery_storage.isPresent()) {
final var drain = mattery_storage.get().extractEnergyOuter(demand, true);
if (drain.compareTo(Fraction.ZERO) != 0) {
final var receive = energy.receiveEnergyOuter(drain, true);
mattery_storage.get().extractEnergyOuter(receive, false);
energy.receiveEnergyOuter(receive, false);
demand = demand.minus(receive);
}
} else {
final var storage = stack.getCapability(CapabilityEnergy.ENERGY).resolve();
if (storage.isPresent()) {
final var drain = MatteryCapability.drainFE(storage.get(), demand, true);
if (drain.compareTo(Fraction.ZERO) != 0) {
final var receive = energy.receiveEnergyOuter(drain, true);
MatteryCapability.drainFE(storage.get(), receive, false);
energy.receiveEnergyOuter(receive, false);
demand = demand.minus(receive);
}
for (stack in batteryContainer) {
if (!stack.isEmpty) {
stack.getCapability(CapabilityEnergy.ENERGY).ifPresent {
if (it is IMatteryEnergyStorage) {
val diff = it.extractEnergyOuter(demand, false)
energy.receiveEnergyInner(diff, false)
demand -= diff
} else {
val diff = it.extractEnergy(demand, false)
energy.receiveEnergyInner(diff, false)
demand -= diff
}
}
if (demand <= Fraction.ZERO)
return
}
}
}
public BlockEntityMatteryPowered(BlockEntityType<?> p_155228_, BlockPos p_155229_, BlockState p_155230_) {
super(p_155228_, p_155229_, p_155230_);
override fun invalidateCaps() {
super.invalidateCaps()
valid = false
resolverEnergy.invalidate()
}
@Override
public void invalidateCaps() {
super.invalidateCaps();
valid = false;
energy_resolver.invalidate();
override fun reviveCaps() {
super.reviveCaps()
valid = true
resolverEnergy = LazyOptional.of { energy }
}
@Override
public void reviveCaps() {
super.reviveCaps();
valid = true;
energy_resolver = LazyOptional.of(() -> energy);
override fun <T> getCapability(cap: Capability<T>, side: Direction?): LazyOptional<T> {
if (valid && (cap === MatteryCapability.ENERGY || cap === CapabilityEnergy.ENERGY))
return resolverEnergy.cast()
return super.getCapability(cap, side)
}
@Nonnull
public <T> LazyOptional<T> getCapability(@Nonnull Capability<T> cap, @Nullable Direction side) {
if (valid && (cap == MatteryCapability.ENERGY || cap == CapabilityEnergy.ENERGY) && energy != null) {
return energy_resolver.cast();
}
return super.getCapability(cap, side);
public override fun saveAdditional(nbt: CompoundTag) {
super.saveAdditional(nbt)
nbt["energy_cap"] = energy.serializeNBT()
nbt["battery_container"] = batteryContainer.serializeNBT()
}
@Override
public void saveAdditional(CompoundTag nbt) {
super.saveAdditional(nbt);
if (energy != null)
nbt.put("energy_cap", energy.serializeNBT());
nbt.put("battery_container", battery_container.serializeNBT());
override fun load(nbt: CompoundTag) {
nbt.ifHas("energy_cap", CompoundTag::class.java, energy::deserializeNBT)
nbt.ifHas("battery_container", CompoundTag::class.java, batteryContainer::deserializeNBT)
super.load(nbt)
}
public void load(CompoundTag nbt) {
if (energy != null && nbt.get("energy_cap") instanceof CompoundTag tag)
energy.deserializeNBT(tag);
if (nbt.contains("battery_container") && nbt.get("battery_container") instanceof CompoundTag tag)
battery_container = MatteryContainer.of(this::setChanged, tag, 1);
super.load(nbt);
}
}
}

View File

@ -5,7 +5,6 @@ import net.minecraft.core.BlockPos
import net.minecraft.world.level.block.state.BlockState
import ru.dbotthepony.mc.otm.capability.matter.IPatternStorage
import ru.dbotthepony.mc.otm.container.MatteryContainer
import java.lang.Runnable
import net.minecraft.world.item.ItemStack
import ru.dbotthepony.mc.otm.capability.MatteryCapability
import ru.dbotthepony.mc.otm.capability.matter.PatternState
@ -44,19 +43,19 @@ class BlockEntityPatternStorage(p_155229_: BlockPos, p_155230_: BlockState) :
private val resolverNode = LazyOptional.of { this }
@JvmField
val patterns: MatteryContainer = object : MatteryContainer(Runnable { this.setChanged() }, 8) {
override fun setChanged(slot: Int, new_state: ItemStack, old_state: ItemStack) {
val patterns: MatteryContainer = object : MatteryContainer(this::setChanged, 8) {
override fun setChanged(slot: Int, new: ItemStack, old: ItemStack) {
val grid = node.graph as MatterNetworkGraph?
if (grid != null && !ItemStack.isSameItemSameTags(new_state, old_state)) {
if (!old_state.isEmpty) {
old_state.getCapability(MatteryCapability.PATTERN).ifPresent { cap: IPatternStorage ->
if (grid != null && !ItemStack.isSameItemSameTags(new, old)) {
if (!old.isEmpty) {
old.getCapability(MatteryCapability.PATTERN).ifPresent { cap: IPatternStorage ->
cap.storedPatterns.forEach { state: PatternState? -> grid.onPatternRemoved(state!!) }
}
}
if (!new_state.isEmpty) {
new_state.getCapability(MatteryCapability.PATTERN).ifPresent { cap: IPatternStorage ->
if (!new.isEmpty) {
new.getCapability(MatteryCapability.PATTERN).ifPresent { cap: IPatternStorage ->
cap.storedPatterns.forEach { state: PatternState? -> grid.onPatternAdded(state!!) }
}
}
@ -64,7 +63,7 @@ class BlockEntityPatternStorage(p_155229_: BlockPos, p_155230_: BlockState) :
updateBlockstate()
}
super.setChanged(slot, new_state, old_state)
super.setChanged(slot, new, old)
}
override fun getMaxStackSize(): Int {

View File

@ -1,31 +1,26 @@
package ru.dbotthepony.mc.otm.block.entity;
package ru.dbotthepony.mc.otm.block.entity
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TranslatableComponent;
import net.minecraft.network.chat.Component
import net.minecraft.network.chat.TranslatableComponent
public enum RedstoneSetting {
IGNORED(new TranslatableComponent("otm.gui.redstone.ignored"), new TranslatableComponent("otm.gui.redstone.ignored.description")),
LOW(new TranslatableComponent("otm.gui.redstone.low"), new TranslatableComponent("otm.gui.redstone.low.description")),
HIGH(new TranslatableComponent("otm.gui.redstone.high"), new TranslatableComponent("otm.gui.redstone.high.description"));
enum class RedstoneSetting(val label: TranslatableComponent, val description: TranslatableComponent) {
IGNORED(TranslatableComponent("otm.gui.redstone.ignored"), TranslatableComponent("otm.gui.redstone.ignored.description")),
LOW(TranslatableComponent("otm.gui.redstone.low"), TranslatableComponent("otm.gui.redstone.low.description")),
HIGH(TranslatableComponent("otm.gui.redstone.high"), TranslatableComponent("otm.gui.redstone.high.description"));
public final Component name;
public final Component description;
private static final RedstoneSetting[] values = RedstoneSetting.values();
RedstoneSetting(TranslatableComponent name, TranslatableComponent description) {
this.name = name;
this.description = description;
operator fun next(): RedstoneSetting {
return values[(ordinal + 1) % values.size]
}
public RedstoneSetting next() {
return values[(ordinal() + 1) % values.length];
}
companion object {
private val values = values()
public static RedstoneSetting get(int index) {
if (index < 0 || index > 2) {
return LOW;
@JvmStatic
operator fun get(index: Int): RedstoneSetting {
if (index !in 0 .. 2)
return LOW
return values[index]
}
return values[index];
}
}
}

View File

@ -54,7 +54,7 @@ interface IMatteryEnergyStorage : IEnergyStorage {
val batteryLevel: Fraction
val maxBatteryLevel: Fraction
val missingPower: Fraction
get() = maxBatteryLevel - batteryLevel
get() = (maxBatteryLevel - batteryLevel).moreThanZero()
override fun receiveEnergy(maxReceive: Int, simulate: Boolean): Int {
val received = receiveEnergyOuter(maxReceive, true).toInt()

View File

@ -0,0 +1,83 @@
package ru.dbotthepony.mc.otm.container
import net.minecraft.world.Container
import net.minecraft.world.item.ItemStack
import net.minecraftforge.common.capabilities.Capability
import java.util.function.Consumer
class ContainerIteratorItemStack(private val container: Container) : Iterator<ItemStack>, Iterable<ItemStack> {
private var index = 0
private var nextStack: ItemStack? = null
override fun hasNext(): Boolean {
if (index >= container.containerSize && nextStack == null)
return false
while (nextStack == null && index < container.containerSize) {
val get = container.getItem(index)
if (!get.isEmpty) {
nextStack = get
}
index++
}
return nextStack != null
}
override fun next(): ItemStack {
val nextStack = nextStack!!
this.nextStack = null
return nextStack
}
override fun iterator(): Iterator<ItemStack> {
return this
}
fun consume(consumer: Consumer<ItemStack?>) {
for (t in this) {
consumer.accept(t)
}
}
}
class ContainerIteratorCapability<T>(private val container: Container, private val cap: Capability<T>) : Iterator<T>, Iterable<T> {
private var index = 0
private var nextStack: T? = null
override fun hasNext(): Boolean {
if (index >= container.containerSize && nextStack == null)
return false
while (nextStack == null && index < container.containerSize) {
val get = container.getItem(index)
if (!get.isEmpty) {
get.getCapability(cap).ifPresent { t: T -> nextStack = t }
}
index++
}
return nextStack != null
}
override fun next(): T {
val nextStack = nextStack!!
this.nextStack = null
return nextStack
}
override fun iterator(): Iterator<T> {
return this
}
fun consume(consumer: Consumer<T>) {
for (t in this) {
consumer.accept(t)
}
}
}

View File

@ -1,361 +1,304 @@
package ru.dbotthepony.mc.otm.container;
package ru.dbotthepony.mc.otm.container
import net.minecraft.MethodsReturnNonnullByDefault;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag;
import net.minecraft.nbt.Tag;
import net.minecraft.world.Container;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.items.IItemHandler;
import net.minecraft.MethodsReturnNonnullByDefault
import javax.annotation.ParametersAreNonnullByDefault
import net.minecraft.world.item.ItemStack
import net.minecraft.nbt.CompoundTag
import net.minecraft.nbt.ListTag
import net.minecraft.nbt.Tag
import net.minecraft.world.Container
import kotlin.jvm.JvmOverloads
import net.minecraft.world.entity.player.Player
import net.minecraft.world.level.block.entity.BlockEntity
import net.minecraftforge.common.capabilities.Capability
import ru.dbotthepony.mc.otm.ifHas
import ru.dbotthepony.mc.otm.set
import java.util.*
import java.util.function.Consumer
import javax.annotation.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;
import java.util.Arrays;
import java.util.Iterator;
import java.util.function.Consumer;
open class MatteryContainer(val watcher: Runnable, private val size: Int) : Container, Iterable<ItemStack> {
constructor(watcher: BlockEntity, size: Int) : this(watcher::setChanged, size)
// constructor(watcher: BlockEntityMattery, size: Int) : this(watcher::setChangedLight, size)
@MethodsReturnNonnullByDefault
@ParametersAreNonnullByDefault
public class MatteryContainer implements Container, Iterable<ItemStack> {
protected final Runnable watcher;
protected int ignore_change_notifications = 0;
protected final int size;
protected final ItemStack[] slots;
protected final ItemStack[] tracked_slots;
private var ignoreChangeNotifications = 0
@JvmField protected val slots: Array<ItemStack> = Array(size) { ItemStack.EMPTY }
private val trackedSlots: Array<ItemStack> = Array(size) { ItemStack.EMPTY }
public MatteryContainer(Runnable watcher, int size) {
this.size = size;
final override fun getContainerSize() = size
slots = new ItemStack[this.size];
tracked_slots = new ItemStack[this.size];
Arrays.fill(slots, ItemStack.EMPTY);
Arrays.fill(tracked_slots, ItemStack.EMPTY);
this.watcher = watcher;
fun startIgnoreUpdates() {
if (++ignoreChangeNotifications == 1) {
startedIgnoringUpdates()
}
}
@SuppressWarnings("unused")
public void startIgnore() {
ignore_change_notifications++;
fun stopIgnoreUpdates() {
if (--ignoreChangeNotifications == 0) {
stoppedIgnoringUpdates()
}
}
@SuppressWarnings("unused")
public void stopIgnore() {
ignore_change_notifications--;
}
protected open fun startedIgnoringUpdates() {}
protected open fun stoppedIgnoringUpdates() {}
public MatteryContainer of(@Nullable CompoundTag tag) {
if (tag == null)
return this;
fun deserializeNBT(tag: CompoundTag?) {
startIgnoreUpdates()
MatteryContainer container = MatteryContainer.of(watcher, tag, getContainerSize());
if (handler != null)
container.handler = handler.cloneOf(container);
return container;
}
public void deserializeNBT(@Nullable CompoundTag tag) {
ignore_change_notifications++;
for (int i = 0; i < getContainerSize(); i++) {
setItem(i, ItemStack.EMPTY);
for (i in 0 until size) {
setItem(i, ItemStack.EMPTY)
}
if (tag == null) {
ignore_change_notifications--;
return;
stopIgnoreUpdates()
return
}
// нам не интересен размер
if (tag.get("items") instanceof ListTag list) {
for (int i = 0; i < Math.min(list.size(), getContainerSize()); i++) {
if (list.get(i) instanceof CompoundTag get_tag) {
setItem(i, ItemStack.of(get_tag));
}
tag.ifHas("items", ListTag::class.java) {
for (i in 0 until Math.min(it.size, size)) {
setItem(i, ItemStack.of(it[i] as CompoundTag))
}
}
ignore_change_notifications--;
setChanged();
stopIgnoreUpdates()
setChanged()
}
public MatteryContainer of(@Nullable Tag tag) {
if (tag == null)
return this;
if (tag instanceof CompoundTag compound)
return of(watcher, compound, getContainerSize());
return this;
}
public void deserializeNBT(@Nullable Tag tag) {
if (tag == null)
return;
if (tag instanceof CompoundTag compound) {
deserializeNBT(compound);
fun deserializeNBT(tag: Tag?) {
if (tag is CompoundTag) {
deserializeNBT(tag)
}
}
public ContainerIteratorItemStack stackIterator() {
return new ContainerIteratorItemStack(this);
fun stacks(): ContainerIteratorItemStack {
return ContainerIteratorItemStack(this)
}
@SuppressWarnings("unused")
public void consumeNonEmpty(Consumer<ItemStack> consumer) {
stackIterator().consume(consumer);
fun forEachNonEmpty(consumer: (ItemStack) -> Unit) {
for (item in slots) {
if (!item.isEmpty) {
consumer(item)
}
}
}
public <T> ContainerIteratorCapability<T> capabilityIterator(Capability<T> cap) {
return new ContainerIteratorCapability<>(this, cap);
fun forEachNonEmpty(consumer: (ItemStack, Int) -> Unit) {
for (i in 0 until size) {
val item = slots[i]
if (!item.isEmpty) {
consumer(item, i)
}
}
}
public <T> void consumeCapability(Capability<T> cap, Consumer<T> consumer) {
capabilityIterator(cap).consume(consumer);
fun <T> capabilityIterator(cap: Capability<T>): ContainerIteratorCapability<T> {
return ContainerIteratorCapability(this, cap)
}
public void setChanged(int slot, ItemStack new_state, ItemStack old_state) {
if (ignore_change_notifications == 0)
watcher.run();
fun <T> consumeCapability(cap: Capability<T>, consumer: Consumer<T>) {
capabilityIterator(cap).consume(consumer)
}
public CompoundTag serializeNBT() {
CompoundTag tag = new CompoundTag();
tag.putInt("size", getContainerSize());
ListTag list = new ListTag();
tag.put("items", list);
for (int i = 0; i < getContainerSize(); i++)
list.add(getItem(i).serializeNBT());
return tag;
open fun setChanged(slot: Int, new: ItemStack, old: ItemStack) {
if (ignoreChangeNotifications == 0) watcher.run()
}
public static MatteryContainer of(Runnable watcher, @Nullable CompoundTag tag, int fallback_size) {
if (tag == null)
return new MatteryContainer(watcher, fallback_size);
fun serializeNBT(): CompoundTag {
val tag = CompoundTag()
tag["size"] = size
MatteryContainer container;
val list = ListTag()
tag["items"] = list
if (tag.contains("size"))
container = new MatteryContainer(watcher, tag.getInt("size"));
else
container = new MatteryContainer(watcher, fallback_size);
for (i in 0 until size)
list.add(this[i].serializeNBT())
if (tag.get("items") instanceof ListTag list)
for (int i = 0; i < Math.min(list.size(), container.getContainerSize()); i++)
if (list.get(i) instanceof CompoundTag get_tag)
container.setItem(i, ItemStack.of(get_tag));
return container;
return tag
}
@SuppressWarnings("unused")
public boolean hasEmptySlot() {
for (int i = 0; i < getContainerSize(); i++) {
if (getItem(i).isEmpty())
return true;
fun hasEmptySlot(): Boolean {
for (i in 0 until size) {
if (this[i].isEmpty) {
return true
}
}
return false;
return false
}
protected MatteryContainerHandler handler;
protected var handler: MatteryContainerHandler? = null
public MatteryContainerHandler handler(MatteryContainerInsertValidator insert_validator, MatteryContainerExtractValidator extract_validator) {
if (handler != null)
return handler;
return handler = new MatteryContainerHandler(this, insert_validator, extract_validator);
fun handler(
insert_validator: (Int, ItemStack) -> Boolean,
extract_validator: (Int, Int, ItemStack) -> Boolean
): MatteryContainerHandler {
return handler ?: MatteryContainerHandler(this, insert_validator, extract_validator).also { handler = it }
}
public MatteryContainerHandler handler(MatteryContainerInsertValidator insert_validator) {
if (handler != null)
return handler;
return handler = new MatteryContainerHandler(this, insert_validator);
fun handler(insert_validator: (Int, ItemStack) -> Boolean): MatteryContainerHandler {
return handler ?: MatteryContainerHandler(this, insert_validator).also { handler = it }
}
public MatteryContainerHandler handler() {
if (handler != null)
return handler;
return handler = new MatteryContainerHandler(this);
fun handler(): MatteryContainerHandler {
return handler ?: MatteryContainerHandler(this).also { handler = it }
}
public int getMaxStackSize(int slot) {
return getMaxStackSize();
}
open fun getMaxStackSize(slot: Int) = maxStackSize
public ItemStack addItem(ItemStack stack, int start, int end, boolean simulate) {
if (stack.isEmpty() || start < 0 || end > size || start >= end)
return ItemStack.EMPTY;
@JvmOverloads
fun addItem(stack: ItemStack, start: Int = 0, end: Int = size, simulate: Boolean = false): ItemStack {
if (stack.isEmpty || start < 0 || end > size || start >= end)
return ItemStack.EMPTY
final var copy = stack.copy();
val copy = stack.copy()
// двигаем в одинаковые слоты
for (int slot = start; slot < end; slot++) {
for (slot in start until end) {
if (ItemStack.isSameItemSameTags(slots[slot], copy)) {
var this_stack = slots[slot];
int slot_limit = Math.min(getMaxStackSize(slot), this_stack.getMaxStackSize());
val slotStack = slots[slot]
val slotLimit = Math.min(getMaxStackSize(slot), slotStack.maxStackSize)
if (this_stack.getCount() < slot_limit) {
int new_count = Math.min(this_stack.getCount() + copy.getCount(), slot_limit);
int diff = new_count - this_stack.getCount();
if (slotStack.count < slotLimit) {
val newCount = Math.min(slotStack.count + copy.count, slotLimit)
val diff = newCount - slotStack.count
if (!simulate) {
var old = this_stack.copy();
this_stack.setCount(new_count);
tracked_slots[slot] = this_stack.copy();
setChanged(slot, this_stack, old);
val old = slotStack.copy()
slotStack.count = newCount
trackedSlots[slot] = slotStack.copy()
setChanged(slot, slotStack, old)
}
copy.shrink(diff);
copy.shrink(diff)
if (copy.isEmpty()) {
return copy;
if (copy.isEmpty) {
return copy
}
}
}
}
// двигаем в пустые слоты
for (int slot = start; slot < end; slot++) {
if (slots[slot].isEmpty()) {
int diff = Math.min(copy.getCount(), Math.min(getMaxStackSize(slot), copy.getMaxStackSize()));
for (slot in start until end) {
if (slots[slot].isEmpty) {
val diff = Math.min(copy.count, Math.min(getMaxStackSize(slot), copy.maxStackSize))
if (!simulate) {
var put_copy = copy.copy();
put_copy.setCount(diff);
slots[slot] = put_copy;
tracked_slots[slot] = put_copy.copy();
setChanged(slot, put_copy, ItemStack.EMPTY);
val copyToPut = copy.copy()
copyToPut.count = diff
this[slot] = copyToPut
}
copy.shrink(diff);
copy.shrink(diff)
if (copy.isEmpty()) {
return copy;
if (copy.isEmpty) {
return copy
}
}
}
return copy;
return copy
}
@SuppressWarnings("unused")
public ItemStack addItem(ItemStack stack, boolean simulate) {
return addItem(stack, 0, size, simulate);
fun addItem(stack: ItemStack, simulate: Boolean): ItemStack {
return addItem(stack, 0, size, simulate)
}
@SuppressWarnings("unused")
public ItemStack addItem(ItemStack stack) {
return addItem(stack, 0, size, false);
@JvmOverloads
fun fullyAddItem(stack: ItemStack, start: Int = 0, end: Int = size): Boolean {
if (!addItem(stack, start, end, true).isEmpty)
return false
return addItem(stack, start, end, false).isEmpty
}
public boolean fullyAddItem(ItemStack stack) {
if (!addItem(stack, 0, size, true).isEmpty()) {
return false;
override fun isEmpty(): Boolean {
for (stack in slots)
if (!stack.isEmpty)
return false
return true
}
operator fun get(slot: Int) = getItem(slot)
operator fun set(slot: Int, stack: ItemStack) = setItem(slot, stack)
operator fun contains(other: ItemStack): Boolean {
for (i in 0 until size) {
if (ItemStack.isSameItemSameTags(this[i], other)) {
return true
}
}
return addItem(stack, 0, size, false).isEmpty();
return false
}
@SuppressWarnings("unused")
public boolean fullyAddItem(ItemStack stack, int start, int end) {
if (!addItem(stack, start, end, true).isEmpty()) {
return false;
}
final override fun getItem(slot: Int): ItemStack {
val item = slots[slot]
return addItem(stack, start, end, false).isEmpty();
if (item.isEmpty)
return ItemStack.EMPTY
else
return item
}
@Override
public int getContainerSize() {
return size;
final override fun removeItem(slot: Int, amount: Int): ItemStack {
if (amount <= 0 || slot < 0 || slot >= size || slots[slot].isEmpty)
return ItemStack.EMPTY
val old = slots[slot].copy()
val split = slots[slot].split(amount)
trackedSlots[slot] = slots[slot].copy()
setChanged(slot, if (slots[slot].isEmpty) ItemStack.EMPTY else slots[slot], old)
return split
}
@Override
public boolean isEmpty() {
for (var stack : slots)
if (!stack.isEmpty())
return false;
return true;
final override fun removeItemNoUpdate(slot: Int): ItemStack {
val old = slots[slot]
slots[slot] = ItemStack.EMPTY
trackedSlots[slot] = ItemStack.EMPTY
return old
}
@Override
public ItemStack getItem(int slot) {
return slots[slot].isEmpty() ? ItemStack.EMPTY : slots[slot];
final override fun setItem(slot: Int, stack: ItemStack) {
if (slots[slot].isEmpty && stack.isEmpty || stack === slots[slot])
return
val old = slots[slot]
slots[slot] = stack
trackedSlots[slot] = stack.copy()
setChanged(slot, stack, old)
}
@Override
public ItemStack removeItem(int slot, int amount) {
if (amount <= 0 || slot < 0 || slot >= size || slots[slot].isEmpty())
return ItemStack.EMPTY;
var old = slots[slot].copy();
var split = slots[slot].split(amount);
tracked_slots[slot] = slots[slot].copy();
setChanged(slot, slots[slot].isEmpty() ? ItemStack.EMPTY : slots[slot], old);
return split;
}
@Override
public ItemStack removeItemNoUpdate(int slot) {
var old = slots[slot];
slots[slot] = ItemStack.EMPTY;
tracked_slots[slot] = ItemStack.EMPTY;
return old;
}
@Override
public void setItem(int slot, ItemStack stack) {
if (slots[slot].isEmpty() && stack.isEmpty() || stack == slots[slot])
return;
var old = slots[slot];
slots[slot] = stack;
tracked_slots[slot] = stack.copy();
setChanged(slot, stack, old);
}
@Override
public void setChanged() {
for (int slot = 0; slot < size; slot++) {
if (!ItemStack.isSameItemSameTags(slots[slot], tracked_slots[slot])) {
setChanged(slot, slots[slot], tracked_slots[slot]);
tracked_slots[slot] = slots[slot].copy();
final override fun setChanged() {
for (slot in 0 until size) {
if (!ItemStack.isSameItemSameTags(slots[slot], trackedSlots[slot])) {
setChanged(slot, slots[slot], trackedSlots[slot])
trackedSlots[slot] = slots[slot].copy()
// mojang соси))0)0))0)))))0)
}
}
}
@Override
public boolean stillValid(Player player) {
return true;
override fun stillValid(player: Player): Boolean {
return true
}
@Override
public void clearContent() {
for (int slot = 0; slot < size; slot++) {
if (!slots[slot].isEmpty()) {
setChanged(slot, ItemStack.EMPTY, slots[slot]);
final override fun clearContent() {
for (slot in 0 until size) {
if (!slots[slot].isEmpty) {
val old = slots[slot]
slots[slot] = ItemStack.EMPTY
setChanged(slot, ItemStack.EMPTY, old)
}
}
Arrays.fill(tracked_slots, ItemStack.EMPTY);
Arrays.fill(trackedSlots, ItemStack.EMPTY)
}
@Override
public Iterator<ItemStack> iterator() {
return Arrays.stream(slots).iterator();
final override fun iterator(): Iterator<ItemStack> {
return slots.iterator()
}
}

View File

@ -1,132 +1,93 @@
package ru.dbotthepony.mc.otm.container;
package ru.dbotthepony.mc.otm.container
import net.minecraft.world.item.ItemStack;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.items.IItemHandler;
import net.minecraft.world.item.ItemStack
import net.minecraftforge.common.util.LazyOptional
import net.minecraftforge.items.IItemHandler
import javax.annotation.Nonnull;
class MatteryContainerHandler @JvmOverloads internal constructor(
private val container: MatteryContainer,
private val insert_validator: (Int, ItemStack) -> Boolean = { _: Int, _: ItemStack -> true },
private val extract_validator: (Int, Int, ItemStack) -> Boolean = { _: Int, _: Int, _: ItemStack -> true }
) : IItemHandler {
private var handler = LazyOptional.of<IItemHandler> { this }
public class MatteryContainerHandler implements IItemHandler {
private final MatteryContainer container;
private final MatteryContainerInsertValidator insert_validator;
private final MatteryContainerExtractValidator extract_validator;
MatteryContainerHandler(MatteryContainer container, MatteryContainerInsertValidator insert_validator, MatteryContainerExtractValidator extract_validator) {
this.container = container;
this.insert_validator = insert_validator;
this.extract_validator = extract_validator;
fun get(): LazyOptional<IItemHandler> {
return handler
}
MatteryContainerHandler(MatteryContainer container) {
this(container, (slot, stack) -> true, (slot, amount, stack) -> true);
fun invalidate() {
handler.invalidate()
}
MatteryContainerHandler(MatteryContainer container, MatteryContainerInsertValidator insert_validator) {
this(container, insert_validator, (slot, amount, stack) -> true);
fun revive() {
handler = LazyOptional.of { this }
}
private LazyOptional<IItemHandler> handler = LazyOptional.of(() -> this);
override fun getSlots() = container.containerSize
override fun getStackInSlot(slot: Int) = container[slot]
public LazyOptional<IItemHandler> get() {
return handler;
}
override fun insertItem(slot: Int, stack: ItemStack, simulate: Boolean): ItemStack {
if (!insert_validator(slot, stack))
return stack
public void invalidate() {
handler.invalidate();
}
val localStack = container[slot]
public void revive() {
handler = LazyOptional.of(() -> this);
}
@Override
public int getSlots() {
return container.getContainerSize();
}
@Nonnull
@Override
public ItemStack getStackInSlot(int slot) {
return container.getItem(slot);
}
@Nonnull
@Override
public ItemStack insertItem(int slot, @Nonnull ItemStack stack, boolean simulate) {
if (!insert_validator.apply(slot, stack))
return stack;
ItemStack self_stack = container.getItem(slot);
if (self_stack.isEmpty()) {
if (localStack.isEmpty) {
if (!simulate) {
var copy = stack.copy();
container.setChanged(slot, copy, ItemStack.EMPTY);
container.setItem(slot, copy);
val copy = stack.copy()
container.setChanged(slot, copy, ItemStack.EMPTY)
container.setItem(slot, copy)
}
return ItemStack.EMPTY;
} else if (self_stack.isStackable() && self_stack.getMaxStackSize() > self_stack.getCount() && ItemStack.isSameItemSameTags(self_stack, stack)) {
int new_count = Math.min(self_stack.getMaxStackSize(), self_stack.getCount() + stack.getCount());
int diff = new_count - self_stack.getCount();
return ItemStack.EMPTY
} else if (localStack.isStackable && localStack.maxStackSize > localStack.count && ItemStack.isSameItemSameTags(localStack, stack)) {
val newCount = Math.min(localStack.maxStackSize, localStack.count + stack.count)
val diff = newCount - localStack.count
if (diff != 0) {
if (!simulate) {
ItemStack copy_self = self_stack.copy();
self_stack.grow(diff);
container.setChanged(slot, self_stack, copy_self);
val copy = localStack.copy()
localStack.grow(diff)
container.setChanged(slot, localStack, copy)
}
ItemStack copy = stack.copy();
copy.shrink(diff);
return copy;
val copy = stack.copy()
copy.shrink(diff)
return copy
}
}
return stack;
return stack
}
@Nonnull
@Override
public ItemStack extractItem(int slot, int amount, boolean simulate) {
override fun extractItem(slot: Int, amount: Int, simulate: Boolean): ItemStack {
if (amount == 0)
return ItemStack.EMPTY;
return ItemStack.EMPTY
if (amount < 0)
throw new IllegalArgumentException("Can not extract negative amount of items");
require(amount >= 0) { "Can not extract negative amount of items" }
ItemStack self_stack = container.getItem(slot);
val localStack = container.getItem(slot)
if (localStack.isEmpty) return ItemStack.EMPTY
if (!extract_validator(slot, amount, localStack)) return ItemStack.EMPTY
if (self_stack.isEmpty())
return ItemStack.EMPTY;
if (!extract_validator.apply(slot, amount, self_stack))
return ItemStack.EMPTY;
int minimal = Math.min(amount, self_stack.getCount());
ItemStack copy = self_stack.copy();
copy.setCount(minimal);
val minimal = Math.min(amount, localStack.count)
val copy = localStack.copy()
copy.count = minimal
if (!simulate) {
ItemStack copy_self = self_stack.copy();
self_stack.shrink(minimal);
container.setChanged(slot, self_stack, copy_self);
val copy = localStack.copy()
localStack.shrink(minimal)
container.setChanged(slot, localStack, copy)
}
return copy;
return copy
}
@Override
public int getSlotLimit(int slot) {
return container.getMaxStackSize();
override fun getSlotLimit(slot: Int): Int {
return container.maxStackSize
}
@Override
public boolean isItemValid(int slot, @Nonnull ItemStack stack) {
return insert_validator.apply(slot, stack);
}
MatteryContainerHandler cloneOf(MatteryContainer container) {
return new MatteryContainerHandler(container, insert_validator, extract_validator);
override fun isItemValid(slot: Int, stack: ItemStack): Boolean {
return insert_validator(slot, stack)
}
}

View File

@ -57,12 +57,12 @@ abstract class Abstract6Graph<T> {
}
companion object {
fun <T, G : Abstract6Graph<T>> discoverFull(
fun <T> discoverFull(
level: ServerLevel,
blockPos: BlockPos,
node: Graph6Node<T>,
nodeGetter: (BlockEntity) -> Graph6Node<T>?,
factory: () -> G
factory: () -> Abstract6Graph<T>
) {
OverdriveThatMatters.tickUntil(level) {
!node.valid || discover(level, blockPos, node, nodeGetter, factory)
@ -70,12 +70,12 @@ abstract class Abstract6Graph<T> {
}
@JvmStatic
fun <T, G : Abstract6Graph<T>> discover(
fun <T> discover(
level: ServerLevel,
blockPos: BlockPos,
node: Graph6Node<T>,
nodeGetter: (BlockEntity) -> Graph6Node<T>?,
factory: () -> G
factory: () -> Abstract6Graph<T>
): Boolean {
var fullDiscovery = true

View File

@ -22,7 +22,7 @@ abstract class PoweredMatteryMenu protected constructor(
batterySlot = BatterySlot(SimpleContainer(1), 0)
} else {
powerWidget = LevelGaugeWidget(this, tile.getCapability(MatteryCapability.ENERGY).resolve().get())
batterySlot = BatterySlot(tile.battery_container, 0)
batterySlot = BatterySlot(tile.batteryContainer, 0)
}
}
}