diff --git a/.gitignore b/.gitignore index f8677d309..74c938753 100644 --- a/.gitignore +++ b/.gitignore @@ -23,6 +23,7 @@ run design/ libs/ +logs/ # Files from Forge MDK forge*changelog.txt diff --git a/src/main/java/ru/dbotthepony/mc/otm/OverdriveThatMatters.java b/src/main/java/ru/dbotthepony/mc/otm/OverdriveThatMatters.java index 3cbb9adbc..b30db5e4e 100644 --- a/src/main/java/ru/dbotthepony/mc/otm/OverdriveThatMatters.java +++ b/src/main/java/ru/dbotthepony/mc/otm/OverdriveThatMatters.java @@ -28,7 +28,6 @@ import ru.dbotthepony.mc.otm.capability.drive.DrivePool; import ru.dbotthepony.mc.otm.client.AndroidGui; import ru.dbotthepony.mc.otm.client.EventHandler; import ru.dbotthepony.mc.otm.item.ItemPortableCondensationDrive; -import ru.dbotthepony.mc.otm.matter.MatterGrid; import ru.dbotthepony.mc.otm.matter.MatterRegistry; import ru.dbotthepony.mc.otm.network.MatteryNetworking; import ru.dbotthepony.mc.otm.storage.ItemStackWrapper; @@ -129,7 +128,6 @@ public class OverdriveThatMatters { MinecraftForge.EVENT_BUS.register(this); MinecraftForge.EVENT_BUS.register(AndroidCapabilityPlayer.class); MinecraftForge.EVENT_BUS.register(AndroidCapability.class); - MinecraftForge.EVENT_BUS.register(MatterGrid.class); MinecraftForge.EVENT_BUS.register(MatterRegistry.class); MinecraftForge.EVENT_BUS.register(BlockEntityBlackHole.BlackHoleExplosionQueue.class); diff --git a/src/main/java/ru/dbotthepony/mc/otm/block/BlockMatterCable.java b/src/main/java/ru/dbotthepony/mc/otm/block/BlockMatterCable.java index 04ead0386..bdc12da85 100644 --- a/src/main/java/ru/dbotthepony/mc/otm/block/BlockMatterCable.java +++ b/src/main/java/ru/dbotthepony/mc/otm/block/BlockMatterCable.java @@ -19,7 +19,6 @@ import net.minecraft.world.phys.shapes.BooleanOp; import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.Shapes; import net.minecraft.world.phys.shapes.VoxelShape; -import ru.dbotthepony.mc.otm.capability.matter.IMatterGridCell; import ru.dbotthepony.mc.otm.block.entity.BlockEntityMatterCable; import javax.annotation.Nullable; @@ -172,62 +171,6 @@ public class BlockMatterCable extends Block implements EntityBlock { return true; } - // doesn't work at all - /* - @Nullable - @Override - public BlockState getStateForPlacement(BlockPlaceContext p_49820_) { - Level level = p_49820_.getLevel(); - - if (level.isClientSide) - return this.defaultBlockState(); - - BlockState state = this.defaultBlockState(); - - for (int i = 0; i < MAPPING_CONNECTION_PROP.length; i++) { - OverdriveThatMatters.LOGGER.info("{} {} {}", Direction.values()[i], p_49820_.getClickedPos().offset(Direction.values()[i].getNormal()), level.getBlockEntity(p_49820_.getClickedPos().offset(p_49820_.getClickedFace().getNormal()).offset(Direction.values()[i].getNormal()))); - - if ( - level.getBlockEntity(p_49820_.getClickedPos().offset(Direction.values()[i].getNormal())) instanceof IMatterGridCell cell && cell.isValidMatterCell()// || - //level.getBlockState(p_49820_.getClickedPos().offset(p_49820_.getClickedFace().getNormal()).offset(Direction.values()[i].getNormal())).getBlock() instanceof BlockMatterCable - ) { - state.setValue(MAPPING_CONNECTION_PROP[i], true); - } - } - - return state; - } - */ - - // blocks - @Override - @SuppressWarnings("deprecation") - public void neighborChanged(BlockState self, Level level, BlockPos position_self, Block block_notifier, BlockPos position_notifier, boolean unknown_flag) { - Direction normal = Direction.fromNormal(position_notifier.subtract(position_self)); - boolean updated = false; - BlockEntity get_entity = level.getBlockEntity(position_notifier); - - if (!self.getValue(MAPPING_CONNECTION_PROP[normal.ordinal()]) && get_entity instanceof IMatterGridCell cell && cell.isValidMatterCell()) { - self = self.setValue(MAPPING_CONNECTION_PROP[normal.ordinal()], true); - updated = true; - } else if (self.getValue(MAPPING_CONNECTION_PROP[normal.ordinal()]) && (get_entity == null || get_entity instanceof IMatterGridCell cell && !cell.isValidMatterCell())) { - self = self.setValue(MAPPING_CONNECTION_PROP[normal.ordinal()], false); - updated = true; - } - - if (updated) { - level.setBlock(position_self, self, UPDATE_CLIENTS); - } - - super.neighborChanged(self, level, position_self, block_notifier, position_notifier, unknown_flag); - } - - // tiles - /*@Override - public void onNeighborChange(BlockState state, LevelReader world, BlockPos pos, BlockPos neighbor) { - super.onNeighborChange(state, world, pos, neighbor); - }*/ - @Override protected void createBlockStateDefinition(StateDefinition.Builder builder) { builder.add(CONNECTION_SOUTH, diff --git a/src/main/java/ru/dbotthepony/mc/otm/block/entity/BlockEntityMatterCable.java b/src/main/java/ru/dbotthepony/mc/otm/block/entity/BlockEntityMatterCable.java deleted file mode 100644 index 8b20ddd51..000000000 --- a/src/main/java/ru/dbotthepony/mc/otm/block/entity/BlockEntityMatterCable.java +++ /dev/null @@ -1,111 +0,0 @@ -package ru.dbotthepony.mc.otm.block.entity; - -import net.minecraft.MethodsReturnNonnullByDefault; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraftforge.common.capabilities.Capability; -import net.minecraftforge.common.util.LazyOptional; -import ru.dbotthepony.mc.otm.capability.matter.IMatterGridCell; -import ru.dbotthepony.mc.otm.capability.MatteryCapability; -import ru.dbotthepony.mc.otm.matter.MatterGrid; -import ru.dbotthepony.mc.otm.Registry; -import ru.dbotthepony.mc.otm.block.BlockMatterCable; -import ru.dbotthepony.mc.otm.capability.matter.IMatterHandler; -import ru.dbotthepony.mc.otm.capability.matter.IPatternStorage; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import javax.annotation.ParametersAreNonnullByDefault; - -@MethodsReturnNonnullByDefault -@ParametersAreNonnullByDefault -public class BlockEntityMatterCable extends BlockEntity implements IMatterGridCell { - public BlockEntityMatterCable(BlockPos p_155229_, BlockState p_155230_) { - super(Registry.BlockEntities.MATTER_CABLE, p_155229_, p_155230_); - // OverdriveThatMatters.LOGGER.debug("create cable block entity {} {} {}", this, p_155229_, p_155230_); - } - - private MatterGrid grid; - - private LazyOptional resolver_grid = LazyOptional.of(() -> this); - private boolean valid = true; - - @Override - public void invalidateCaps() { - super.invalidateCaps(); - valid = false; - resolver_grid.invalidate(); - } - - @Override - public void reviveCaps() { - super.reviveCaps(); - valid = true; - resolver_grid = LazyOptional.of(() -> this); - } - - @Nonnull - @Override - public LazyOptional getCapability(@Nonnull Capability cap, @Nullable Direction side) { - if (valid && cap == MatteryCapability.MATTER_CELL) - return resolver_grid.cast(); - - return super.getCapability(cap, side); - } - - @Override - public void setLevel(Level p_155231_) { - super.setLevel(p_155231_); - - if (grid == null) - MatterGrid.scheduleDiscoverNeighbours(this, getBlockPos(), p_155231_); - } - - @Nullable - @Override - public IPatternStorage getPatternStorage() { - return null; - } - - @Override - public void onNeighbourMatterCell(Level level, BlockPos pos, Direction direction, IMatterGridCell cell, BlockEntity entity) { - BlockState new_state = getBlockState().setValue(BlockMatterCable.MAPPING_CONNECTION_PROP[direction.ordinal()], true); - - if (new_state != getBlockState()) - level.setBlock(getBlockPos(), new_state, Block.UPDATE_CLIENTS); - } - - @Override - public void setRemoved() { - super.setRemoved(); - - if (grid != null) - grid.remove(this); - } - - @Nullable - @Override - public MatterGrid getMatterGrid() { - return grid; - } - - @Nullable - @Override - public IMatterHandler getMatterHandler() { - return null; - } - - @Override - public boolean isValidMatterCell() { - return valid; - } - - @Override - public void setMatterGrid(MatterGrid grid) { - this.grid = grid; - } -} diff --git a/src/main/java/ru/dbotthepony/mc/otm/block/entity/BlockEntityMatterDecomposer.java b/src/main/java/ru/dbotthepony/mc/otm/block/entity/BlockEntityMatterDecomposer.java deleted file mode 100644 index 0163bccec..000000000 --- a/src/main/java/ru/dbotthepony/mc/otm/block/entity/BlockEntityMatterDecomposer.java +++ /dev/null @@ -1,221 +0,0 @@ -package ru.dbotthepony.mc.otm.block.entity; - -import net.minecraft.MethodsReturnNonnullByDefault; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.TranslatableComponent; -import net.minecraft.world.entity.player.Inventory; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.inventory.AbstractContainerMenu; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.entity.BlockEntity; -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 net.minecraftforge.items.IItemHandler; -import ru.dbotthepony.mc.otm.*; -import ru.dbotthepony.mc.otm.block.entity.worker.BlockEntityMatteryWorker; -import ru.dbotthepony.mc.otm.block.entity.worker.MachineJob; -import ru.dbotthepony.mc.otm.block.entity.worker.MachineJobStatus; -import ru.dbotthepony.mc.otm.capability.*; -import ru.dbotthepony.mc.otm.capability.matter.IMatterHandler; -import ru.dbotthepony.mc.otm.capability.matter.IPatternStorage; -import ru.dbotthepony.mc.otm.capability.matter.MatterHandlerCapability; -import ru.dbotthepony.mc.otm.container.MatteryContainer; -import ru.dbotthepony.mc.otm.capability.matter.IMatterGridCell; -import ru.dbotthepony.mc.otm.core.Fraction; -import ru.dbotthepony.mc.otm.matter.MatterGrid; -import ru.dbotthepony.mc.otm.matter.MatterRegistry; -import ru.dbotthepony.mc.otm.menu.MatterDecomposerMenu; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import javax.annotation.ParametersAreNonnullByDefault; -import java.math.BigDecimal; - -@MethodsReturnNonnullByDefault -@ParametersAreNonnullByDefault -public class BlockEntityMatterDecomposer extends BlockEntityMatteryWorker implements IMatterGridCell { - private static final TranslatableComponent MACHINE_NAME = new TranslatableComponent("block.overdrive_that_matters.matter_decomposer"); - private boolean valid = true; - public final MatterHandlerCapability matter = new MatterHandlerCapability(this::setChanged, IMatterHandler.MatterDirection.EXTRACT, new Fraction("20")); - private LazyOptional matter_resolver = LazyOptional.of(() -> matter); - - // вход, выход - public final MatteryContainer item_container = new MatteryContainer(this::setChanged, 2); - - private final LazyOptional handler_resolver = LazyOptional.of(() -> item_container.handler( - (slot, stack) -> slot == 0 && MatterRegistry.canDecompose(stack), - (slot, amount, stack) -> slot == 1 - )); - - public BlockEntityMatterDecomposer(BlockPos p_155229_, BlockState p_155230_) { - super(Registry.BlockEntities.MATTER_DECOMPOSER, p_155229_, p_155230_); - energy = new MatteryMachineEnergyStorage(this, MatteryMachineEnergyStorage.MachineType.WORKER, new Fraction(400_000), new Fraction(2000), new Fraction(2000)); - } - - @Override - protected Component getDefaultDisplayName() { - return MACHINE_NAME; - } - - @Nullable - @Override - public AbstractContainerMenu createMenu(int containerID, Inventory inventory, Player ply) { - return new MatterDecomposerMenu(containerID, inventory, this); - } - - @Nullable - @Override - public IPatternStorage getPatternStorage() { - return null; - } - - @Override - public void saveAdditional(CompoundTag nbt) { - super.saveAdditional(nbt); - nbt.put("work_slots", item_container.serializeNBT()); - nbt.put("matter_capability", matter.serializeNBT()); - } - - @Override - public void load(CompoundTag nbt) { - super.load(nbt); - - if (nbt.contains("matter_capability") && nbt.get("matter_capability") instanceof CompoundTag tag) - matter.deserializeNBT(tag); - - item_container.deserializeNBT(nbt.get("work_slots")); - } - - @Override - public void reviveCaps() { - valid = true; - super.reviveCaps(); - matter_resolver = LazyOptional.of(() -> matter); - resolver_grid = LazyOptional.of(() -> this); - } - - @Override - public void invalidateCaps() { - valid = false; - super.invalidateCaps(); - matter_resolver.invalidate(); - resolver_grid.invalidate(); - } - - private LazyOptional resolver_grid = LazyOptional.of(() -> this); - - @Nonnull - @Override - public LazyOptional getCapability(@Nonnull Capability cap, @Nullable Direction side) { - if (valid) { - if (cap == MatteryCapability.MATTER) - return matter_resolver.cast(); - - if (cap == MatteryCapability.MATTER_CELL) - return resolver_grid.cast(); - - if (cap == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) - return handler_resolver.cast(); - } - - return super.getCapability(cap, side); - } - - @Nonnull - @Override - protected MachineJobStatus onJobFinish(MachineJob job) { - var matter_value = MatterRegistry.getMatterValue(job.stack()); - matter.receiveMatterInner(matter_value, false); - return new MachineJobStatus(); - } - - @Nullable - @Override - protected MachineJob getNextJob() { - ItemStack stack = item_container.getItem(0); - - if (!stack.isEmpty()) { - ItemStack copy = stack.copy(); - copy.setCount(1); - - if (MatterRegistry.canDecompose(copy)) { - var matter_value = MatterRegistry.getMatterValue(copy); - - if (!matter_value.equals(Fraction.ZERO) && matter.canReceiveAll(matter_value)) { - stack.shrink(1); - return new MachineJob(copy, matter_value.toDouble() * 12_500d); - } - } - } - - return null; - } - - public static void tick(Level level, BlockPos blockPos, BlockState blockState, T t) { - if (t instanceof BlockEntityMatterDecomposer tile) { - tile.batteryChargeLoop(); - tile.workerLoop(); - - if (tile.matter.getStoredMatter().compareTo(Fraction.ZERO) > 0 && tile.grid != null) { - var diff = tile.matter.extractMatterInner(tile.matter.getStoredMatter(), true); - var diff2 = tile.grid.softPushMatter(diff, true); - - tile.matter.extractMatterInner(diff2, false); - tile.grid.softPushMatter(diff2, false); - } - } - } - - private MatterGrid grid; - - @Override - public void setRemoved() { - super.setRemoved(); - - if (level != null && !level.isClientSide && grid != null) - grid.remove(this); - } - - @Override - public void setLevel(Level p_155231_) { - super.setLevel(p_155231_); - - if (!p_155231_.isClientSide) - MatterGrid.scheduleDiscoverNeighbours(this, getBlockPos(), p_155231_); - } - - @Nullable - @Override - public MatterGrid getMatterGrid() { - return grid; - } - - @Nullable - @Override - public IMatterHandler getMatterHandler() { - return valid ? matter : null; - } - - @Override - public boolean isValidMatterCell() { - return valid; - } - - @Override - public void setMatterGrid(MatterGrid grid) { - this.grid = grid; - } - - private static final Fraction BASE_CONSUMPTION = new Fraction(240); - - @Override - protected Fraction getBaseConsumption() { - return BASE_CONSUMPTION; - } -} diff --git a/src/main/java/ru/dbotthepony/mc/otm/capability/MatteryCapability.java b/src/main/java/ru/dbotthepony/mc/otm/capability/MatteryCapability.java index 8a98c78d3..80112e916 100644 --- a/src/main/java/ru/dbotthepony/mc/otm/capability/MatteryCapability.java +++ b/src/main/java/ru/dbotthepony/mc/otm/capability/MatteryCapability.java @@ -4,13 +4,12 @@ import net.minecraftforge.common.capabilities.*; import net.minecraftforge.energy.IEnergyStorage; import ru.dbotthepony.mc.otm.capability.android.IAndroidCapability; import ru.dbotthepony.mc.otm.capability.drive.IMatteryDrive; -import ru.dbotthepony.mc.otm.capability.matter.IMatterGridCell; import ru.dbotthepony.mc.otm.capability.matter.IMatterHandler; import ru.dbotthepony.mc.otm.capability.matter.IMatterTaskProvider; import ru.dbotthepony.mc.otm.capability.matter.IPatternStorage; import ru.dbotthepony.mc.otm.core.Fraction; +import ru.dbotthepony.mc.otm.graph.matter.IMatterGraphNode; -import java.math.BigDecimal; import java.math.MathContext; import java.math.RoundingMode; @@ -18,7 +17,7 @@ public class MatteryCapability { public static final Capability ENERGY = CapabilityManager.get(new CapabilityToken<>() {}); public static final Capability ANDROID = CapabilityManager.get(new CapabilityToken<>() {}); public static final Capability MATTER = CapabilityManager.get(new CapabilityToken<>() {}); - public static final Capability MATTER_CELL = CapabilityManager.get(new CapabilityToken<>() {}); + public static final Capability MATTER_CELL = CapabilityManager.get(new CapabilityToken<>() {}); public static final Capability PATTERN = CapabilityManager.get(new CapabilityToken<>() {}); public static final Capability TASK = CapabilityManager.get(new CapabilityToken<>() {}); public static final Capability DRIVE = CapabilityManager.get(new CapabilityToken<>() {}); @@ -29,11 +28,11 @@ public class MatteryCapability { event.register(IMatteryEnergyStorage.class); event.register(IAndroidCapability.class); event.register(IMatterHandler.class); - event.register(IMatterGridCell.class); event.register(IPatternStorage.class); event.register(IMatterTaskProvider.class); event.register(IMatteryDrive.class); event.register(IStorageGridCell.class); + event.register(IMatterGraphNode.class); } public static final MathContext ROUND_RULES = new MathContext(32, RoundingMode.HALF_DOWN); diff --git a/src/main/java/ru/dbotthepony/mc/otm/capability/matter/IMatterGridCell.java b/src/main/java/ru/dbotthepony/mc/otm/capability/matter/IMatterGridCell.java deleted file mode 100644 index e9aaf2951..000000000 --- a/src/main/java/ru/dbotthepony/mc/otm/capability/matter/IMatterGridCell.java +++ /dev/null @@ -1,65 +0,0 @@ -package ru.dbotthepony.mc.otm.capability.matter; - -import net.minecraft.MethodsReturnNonnullByDefault; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.entity.BlockEntity; -import ru.dbotthepony.mc.otm.capability.MatteryCapability; -import ru.dbotthepony.mc.otm.matter.MatterGrid; - -import javax.annotation.Nullable; -import javax.annotation.ParametersAreNonnullByDefault; - -import static ru.dbotthepony.mc.otm.AbstractGrid.createOrConnectGrid; - -@MethodsReturnNonnullByDefault -@ParametersAreNonnullByDefault -public interface IMatterGridCell extends IMatterGridListener { - @Nullable - MatterGrid getMatterGrid(); - - @Nullable - default IMatterHandler getMatterHandler() { - return null; - } - - @Nullable - default IPatternStorage getPatternStorage() { - return null; - } - - @Nullable - default IMatterTaskProvider getTaskProvider() { - return null; - } - - boolean isValidMatterCell(); - - void setMatterGrid(@Nullable MatterGrid grid); - - default void scheduleDiscoverNeighbours(Level level, BlockPos pos) { - MatterGrid.scheduleDiscoverNeighbours(this, pos, level); - } - - default boolean connectOrCreateMatterGrid(Level level, BlockPos pos) { - return connectOrCreateMatterGrid(pos, level, false); - } - - default void onNeighbourMatterCell(Level level, BlockPos pos, Direction direction, IMatterGridCell cell, BlockEntity entity) { - - } - - default boolean connectOrCreateMatterGrid(BlockPos pos, Level level, boolean force) { - return createOrConnectGrid( - this, - MatteryCapability.MATTER_CELL, - level, - pos, - force, - MatterGrid::new, - IMatterGridCell::getMatterGrid, - this::onNeighbourMatterCell - ); - } -} diff --git a/src/main/java/ru/dbotthepony/mc/otm/capability/matter/IMatterGridListener.java b/src/main/java/ru/dbotthepony/mc/otm/capability/matter/IMatterGridListener.java deleted file mode 100644 index f6484cd72..000000000 --- a/src/main/java/ru/dbotthepony/mc/otm/capability/matter/IMatterGridListener.java +++ /dev/null @@ -1,18 +0,0 @@ -package ru.dbotthepony.mc.otm.capability.matter; - -import net.minecraft.MethodsReturnNonnullByDefault; - -import javax.annotation.ParametersAreNonnullByDefault; - -@MethodsReturnNonnullByDefault -@ParametersAreNonnullByDefault -public interface IMatterGridListener { - default void onPatternAdded(PatternState state) { } - default void onPatternRemoved(PatternState state) { } - default void onPatternUpdated(PatternState new_state, PatternState old_state) { } - - default void onMatterTaskCreated(MatterTask task) { } - default void onMatterTaskUpdated(MatterTask new_state, MatterTask old_state) { } - default void onMatterTaskFinished(MatterTask state) { } - default void onMatterTaskRemoved(MatterTask state) { } -} diff --git a/src/main/java/ru/dbotthepony/mc/otm/matter/MatterGrid.java b/src/main/java/ru/dbotthepony/mc/otm/matter/MatterGrid.java deleted file mode 100644 index 59978248b..000000000 --- a/src/main/java/ru/dbotthepony/mc/otm/matter/MatterGrid.java +++ /dev/null @@ -1,453 +0,0 @@ -package ru.dbotthepony.mc.otm.matter; - -import com.google.common.collect.ImmutableList; -import net.minecraft.MethodsReturnNonnullByDefault; -import net.minecraft.core.BlockPos; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.item.Item; -import net.minecraft.world.level.Level; -import ru.dbotthepony.mc.otm.AbstractGrid; -import ru.dbotthepony.mc.otm.OverdriveThatMatters; -import ru.dbotthepony.mc.otm.capability.MatteryCapability; -import ru.dbotthepony.mc.otm.capability.matter.*; -import ru.dbotthepony.mc.otm.core.Fraction; - -import javax.annotation.Nullable; -import javax.annotation.ParametersAreNonnullByDefault; -import java.math.BigDecimal; -import java.util.*; -import java.util.function.Predicate; - -@MethodsReturnNonnullByDefault -@ParametersAreNonnullByDefault -public class MatterGrid extends AbstractGrid implements IMatterGridListener { - private final Set listeners = new HashSet<>(); - - public static void scheduleDiscoverNeighbours(IMatterGridCell cell, BlockPos pos, Level level) { - if (level instanceof ServerLevel) - OverdriveThatMatters.tickUntil(level, () -> !cell.isValidMatterCell() || cell.connectOrCreateMatterGrid(pos, level, true)); - } - - public MatterGrid() { - super(MatteryCapability.MATTER_CELL); - } - - public Fraction getCapacity() { - Fraction summ = Fraction.ZERO; - - for (IMatterGridCell cell : cells) { - IMatterHandler handler = cell.getMatterHandler(); - - if (handler != null && handler.getDirection() == IMatterHandler.MatterDirection.BIDIRECTIONAL) { - summ = summ.plus(handler.getMaxStoredMatter()); - } - } - - return summ; - } - - public Fraction getPotentialCapacity() { - Fraction summ = Fraction.ZERO; - - for (IMatterGridCell cell : cells) { - IMatterHandler handler = cell.getMatterHandler(); - - if (handler != null && handler.getDirection() != IMatterHandler.MatterDirection.RECEIVE) { - summ = summ.plus(handler.getMaxStoredMatter()); - } - } - - return summ; - } - - public Fraction getStored() { - Fraction summ = Fraction.ZERO; - - for (IMatterGridCell cell : cells) { - IMatterHandler handler = cell.getMatterHandler(); - - if (handler != null && handler.getDirection() == IMatterHandler.MatterDirection.BIDIRECTIONAL) { - summ = summ.plus(handler.getStoredMatter()); - } - } - - return summ; - } - - public Fraction getPotentialStored() { - Fraction summ = Fraction.ZERO; - - for (IMatterGridCell cell : cells) { - IMatterHandler handler = cell.getMatterHandler(); - - if (handler != null && handler.getDirection() != IMatterHandler.MatterDirection.RECEIVE) { - summ = summ.plus(handler.getStoredMatter()); - } - } - - return summ; - } - - public Fraction extractMatter(Fraction howMuch, boolean simulate) { - if (howMuch.compareTo(Fraction.ZERO) <= 0) - return Fraction.ZERO; - - validate(); - - Fraction extracted = Fraction.ZERO; - - for (IMatterGridCell cell : cells) { - IMatterHandler handler = cell.getMatterHandler(); - - if (handler != null && handler.getDirection() != IMatterHandler.MatterDirection.RECEIVE) { - var drain = handler.extractMatterOuter(howMuch, simulate); - - if (!drain.equalsCompact(Fraction.ZERO)) { - extracted = extracted.plus(drain); - howMuch = howMuch.minus(drain); - - if (howMuch.compareTo(Fraction.ZERO) <= 0) { - break; - } - } - } - } - - return extracted; - } - - public Fraction softPushMatter(Fraction howMuch, boolean simulate) { - if (howMuch.compareTo(Fraction.ZERO) <= 0) - return Fraction.ZERO; - - validate(); - - Fraction received = Fraction.ZERO; - - for (IMatterGridCell cell : cells) { - IMatterHandler handler = cell.getMatterHandler(); - - if (handler != null && handler.getDirection() == IMatterHandler.MatterDirection.BIDIRECTIONAL) { - var receive = handler.receiveMatterOuter(howMuch, simulate); - - if (!receive.equalsCompact(Fraction.ZERO)) { - received = received.plus(receive); - howMuch = howMuch.minus(receive); - - if (howMuch.compareTo(Fraction.ZERO) <= 0) { - break; - } - } - } - } - - return received; - } - - public Fraction pushMatter(Fraction howMuch, boolean simulate) { - if (howMuch.compareTo(Fraction.ZERO) <= 0) - return Fraction.ZERO; - - validate(); - - Fraction received = Fraction.ZERO; - - for (IMatterGridCell cell : cells) { - IMatterHandler handler = cell.getMatterHandler(); - - if (handler != null && handler.getDirection() != IMatterHandler.MatterDirection.EXTRACT) { - var receive = handler.receiveMatterOuter(howMuch, simulate); - - if (!receive.equalsCompact(Fraction.ZERO)) { - received = received.plus(receive); - howMuch = howMuch.minus(receive); - - if (howMuch.compareTo(Fraction.ZERO) <= 0) { - break; - } - } - } - } - - return received; - } - - public PatternInsertStatus insertPattern(PatternState state, boolean only_update, boolean simulate) { - validate(); - - for (IMatterGridCell cell : cells) { - IPatternStorage storage = cell.getPatternStorage(); - - if (storage != null) { - var status = storage.insertPattern(state, true, simulate); - - if (status.status() != PatternInsertStatus.Status.FAIL) { - return status; - } - } - } - - if (only_update) - return new PatternInsertStatus(); - - for (IMatterGridCell cell : cells) { - IPatternStorage storage = cell.getPatternStorage(); - - if (storage != null) { - var status = storage.insertPattern(state, false, simulate); - - if (status.status() != PatternInsertStatus.Status.FAIL) { - return status; - } - } - } - - return new PatternInsertStatus(); - } - - public Collection getStoredPatterns() { - validate(); - - ArrayList list = new ArrayList<>(); - - for (IMatterGridCell cell : cells) { - IPatternStorage storage = cell.getPatternStorage(); - - if (storage != null) { - list.addAll(storage.getStoredPatterns()); - } - } - - return ImmutableList.copyOf(list); - } - - public long getStoredPatternCount() { - validate(); - - long value = 0; - - for (IMatterGridCell cell : cells) { - IPatternStorage storage = cell.getPatternStorage(); - - if (storage != null) { - value += storage.getStored(); - } - } - - return value; - } - - public long getPatternCapacity() { - validate(); - - long value = 0; - - for (IMatterGridCell cell : cells) { - IPatternStorage storage = cell.getPatternStorage(); - - if (storage != null) { - value += storage.getCapacity(); - } - } - - return value; - } - - public Collection findPatterns(Item item) { - return findPatterns((patternState -> item == patternState.item())); - } - - public Collection findPatterns(Predicate item) { - validate(); - - ArrayList list = new ArrayList<>(); - - for (IMatterGridCell cell : cells) { - IPatternStorage storage = cell.getPatternStorage(); - - if (storage != null) { - list.addAll(storage.findPatterns(item)); - } - } - - return ImmutableList.copyOf(list); - } - - @Nullable - public PatternState getPattern(PatternState state) { - return getPattern(state.id()); - } - - @Nullable - public PatternState getPattern(UUID id) { - validate(); - - for (IMatterGridCell cell : cells) { - IPatternStorage storage = cell.getPatternStorage(); - - if (storage != null) { - var get = storage.getPattern(id); - - if (get != null) { - return get; - } - } - } - - return null; - } - - public boolean hasPattern(UUID id) { - return getPattern(id) != null; - } - - @Nullable - public MatterTaskAllocation allocateTask(boolean simulate) { - validate(); - - for (IMatterGridCell cell : cells) { - IMatterTaskProvider tasks = cell.getTaskProvider(); - - if (tasks != null) { - MatterTaskAllocation allocated = tasks.allocateTask(simulate); - - if (allocated != null) { - return allocated; - } - } - } - - return null; - } - - public boolean notifyTaskCompletion(MatterTask task) { - validate(); - - for (IMatterGridCell cell : cells) { - IMatterTaskProvider tasks = cell.getTaskProvider(); - - if (tasks != null) { - if (tasks.notifyTaskCompletion(task)) { - return true; - } - } - } - - return false; - } - - @Override - protected void onAdded(IMatterGridCell cell) { - cell.setMatterGrid(this); - - var tasks = cell.getTaskProvider(); - - if (tasks != null) { - for (var task : tasks.getAllTasks()) { - onMatterTaskCreated(task); - } - } - - var patterns = cell.getPatternStorage(); - - if (patterns != null) { - for (var pattern : patterns.getStoredPatterns()) { - onPatternAdded(pattern); - } - } - } - - @Override - protected void onRemoved(IMatterGridCell cell) { - cell.setMatterGrid(null); - - var tasks = cell.getTaskProvider(); - - if (tasks != null) { - for (var task : tasks.getAllTasks()) { - onMatterTaskRemoved(task); - } - } - - var patterns = cell.getPatternStorage(); - - if (patterns != null) { - for (var pattern : patterns.getStoredPatterns()) { - onPatternRemoved(pattern); - } - } - } - - public void attach(IMatterGridListener listener) { - listeners.add(listener); - } - - public void detach(IMatterGridListener listener) { - listeners.remove(listener); - } - - public void validate() { - ArrayList invalid = new ArrayList<>(); - - for (IMatterGridCell entity : cells) { - if (!entity.isValidMatterCell()) { - invalid.add(entity); - } - } - - if (invalid.size() != 0) { - for (IMatterGridCell entity : invalid) { - remove(entity); - } - } - } - - @Override - public void onPatternAdded(PatternState state) { - // validate(); - cells.forEach(cell -> cell.onPatternAdded(state)); - listeners.forEach(cell -> cell.onPatternAdded(state)); - } - - @Override - public void onPatternRemoved(PatternState state) { - // validate(); - cells.forEach(cell -> cell.onPatternRemoved(state)); - listeners.forEach(cell -> cell.onPatternRemoved(state)); - } - - @Override - public void onPatternUpdated(PatternState new_state, PatternState old_state) { - // validate(); - cells.forEach(cell -> cell.onPatternUpdated(new_state, old_state)); - listeners.forEach(cell -> cell.onPatternUpdated(new_state, old_state)); - } - - @Override - public void onMatterTaskCreated(MatterTask task) { - // validate(); - cells.forEach(cell -> cell.onMatterTaskCreated(task)); - listeners.forEach(cell -> cell.onMatterTaskCreated(task)); - } - - @Override - public void onMatterTaskUpdated(MatterTask new_state, MatterTask old_state) { - // validate(); - cells.forEach(cell -> cell.onMatterTaskUpdated(new_state, old_state)); - listeners.forEach(cell -> cell.onMatterTaskUpdated(new_state, old_state)); - } - - @Override - public void onMatterTaskFinished(MatterTask state) { - // validate(); - cells.forEach(cell -> cell.onMatterTaskFinished(state)); - listeners.forEach(cell -> cell.onMatterTaskFinished(state)); - } - - @Override - public void onMatterTaskRemoved(MatterTask state) { - // validate(); - cells.forEach(cell -> cell.onMatterTaskRemoved(state)); - listeners.forEach(cell -> cell.onMatterTaskRemoved(state)); - } -} diff --git a/src/main/java/ru/dbotthepony/mc/otm/menu/MatterDecomposerMenu.java b/src/main/java/ru/dbotthepony/mc/otm/menu/MatterDecomposerMenu.java index f5231773f..10c667176 100644 --- a/src/main/java/ru/dbotthepony/mc/otm/menu/MatterDecomposerMenu.java +++ b/src/main/java/ru/dbotthepony/mc/otm/menu/MatterDecomposerMenu.java @@ -27,7 +27,7 @@ public class MatterDecomposerMenu extends PoweredMatteryMenu { public MatterDecomposerMenu(int containerID, Inventory inventory, @Nullable BlockEntityMatterDecomposer tile) { super(Registry.Menus.MATTER_DECOMPOSER, containerID, inventory, tile); - Container container = tile != null ? tile.item_container : new SimpleContainer(2); + Container container = tile != null ? tile.itemContainer : new SimpleContainer(2); // Вход input = new MatterySlot(container, 0, 61, 36) { diff --git a/src/main/java/ru/dbotthepony/mc/otm/menu/MatterReplicatorMenu.java b/src/main/java/ru/dbotthepony/mc/otm/menu/MatterReplicatorMenu.java index d71687251..eb2b06b66 100644 --- a/src/main/java/ru/dbotthepony/mc/otm/menu/MatterReplicatorMenu.java +++ b/src/main/java/ru/dbotthepony/mc/otm/menu/MatterReplicatorMenu.java @@ -21,7 +21,7 @@ public class MatterReplicatorMenu extends PoweredMatteryMenu { public MatterReplicatorMenu(int p_38852_, Inventory inventory, BlockEntityMatterReplicator tile) { super(Registry.Menus.MATTER_REPLICATOR, p_38852_, inventory, tile); - Container container = tile != null ? tile.regular_slots : new SimpleContainer(3); + Container container = tile != null ? tile.regularSlots : new SimpleContainer(3); for (int i = 0; i < container.getContainerSize(); i++) { output_slots[i] = new MachineOutputSlot(container, i, 64 + 18 * i, 38, true); diff --git a/src/main/java/ru/dbotthepony/mc/otm/network/MatterTaskPacket.java b/src/main/java/ru/dbotthepony/mc/otm/network/MatterTaskPacket.java index cbb23fef3..c3843879f 100644 --- a/src/main/java/ru/dbotthepony/mc/otm/network/MatterTaskPacket.java +++ b/src/main/java/ru/dbotthepony/mc/otm/network/MatterTaskPacket.java @@ -10,14 +10,16 @@ import ru.dbotthepony.mc.otm.capability.matter.MatterTask; import ru.dbotthepony.mc.otm.menu.MatterPanelMenu; import javax.annotation.ParametersAreNonnullByDefault; +import java.util.ArrayList; +import java.util.Collection; import java.util.Objects; import java.util.function.Supplier; @ParametersAreNonnullByDefault -public record MatterTaskPacket(boolean action, MatterTask...state) { +public record MatterTaskPacket(boolean action, Collection state) { public void write(FriendlyByteBuf buffer) { buffer.writeBoolean(action); - buffer.writeInt(state.length); + buffer.writeInt(state.size()); for (var state1 : state) state1.write(buffer); @@ -42,10 +44,10 @@ public record MatterTaskPacket(boolean action, MatterTask...state) { public static MatterTaskPacket read(FriendlyByteBuf buffer) { boolean action = buffer.readBoolean(); int amount = buffer.readInt(); - var list = new MatterTask[amount]; + var list = new ArrayList(amount); for (int i = 0; i < amount; i++) - list[i] = Objects.requireNonNull(MatterTask.read(buffer)); + list.add(Objects.requireNonNull(MatterTask.read(buffer))); return new MatterTaskPacket(action, list); } diff --git a/src/main/java/ru/dbotthepony/mc/otm/network/NetworkHelper.java b/src/main/java/ru/dbotthepony/mc/otm/network/NetworkHelper.java index 83a41f18c..a1d3e4063 100644 --- a/src/main/java/ru/dbotthepony/mc/otm/network/NetworkHelper.java +++ b/src/main/java/ru/dbotthepony/mc/otm/network/NetworkHelper.java @@ -44,11 +44,17 @@ public class NetworkHelper { } public static byte[] shortsToBytes(short[] input) { - byte[] values = new byte[input.length * 2]; + return shortsToBytes(input, 0); + } - for (int i = 0; i < input.length; i++) { - values[i * 2] = (byte) (input[i] & 0xFF); - values[i * 2 + 1] = (byte) ((input[i] & 0xFF00) >> 8); + public static byte[] shortsToBytes(short[] input, int offset) { + byte[] values = new byte[(input.length - offset) * 2]; + + for (int i = offset; i < input.length; i++) { + int realI = i - offset; + + values[realI * 2] = (byte) (input[i] & 0xFF); + values[realI * 2 + 1] = (byte) ((input[i] & 0xFF00) >> 8); } return values; diff --git a/src/main/java/ru/dbotthepony/mc/otm/network/PatternGridPacket.java b/src/main/java/ru/dbotthepony/mc/otm/network/PatternGridPacket.java index 77e945a84..e9c668a9e 100644 --- a/src/main/java/ru/dbotthepony/mc/otm/network/PatternGridPacket.java +++ b/src/main/java/ru/dbotthepony/mc/otm/network/PatternGridPacket.java @@ -10,14 +10,16 @@ import ru.dbotthepony.mc.otm.capability.matter.PatternState; import ru.dbotthepony.mc.otm.menu.MatterPanelMenu; import javax.annotation.ParametersAreNonnullByDefault; +import java.util.ArrayList; +import java.util.Collection; import java.util.Objects; import java.util.function.Supplier; @ParametersAreNonnullByDefault -public record PatternGridPacket(boolean action, PatternState ...state) { +public record PatternGridPacket(boolean action, Collection state) { public void write(FriendlyByteBuf buffer) { buffer.writeBoolean(action); - buffer.writeInt(state.length); + buffer.writeInt(state.size()); for (var state1 : state) state1.write(buffer); @@ -44,10 +46,10 @@ public record PatternGridPacket(boolean action, PatternState ...state) { public static PatternGridPacket read(FriendlyByteBuf buffer) { boolean action = buffer.readBoolean(); int amount = buffer.readInt(); - var list = new PatternState[amount]; + var list = new ArrayList(amount); for (int i = 0; i < amount; i++) - list[i] = Objects.requireNonNull(PatternState.read(buffer)); + list.add(Objects.requireNonNull(PatternState.read(buffer))); return new PatternGridPacket(action, list); } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/Ext.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/Ext.kt index a790dd77d..7501043aa 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/Ext.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/Ext.kt @@ -44,3 +44,11 @@ fun CompoundTag.ifHas(s: String, type: Byte, consumer: (Tag) -> Unit) { consumer(tag) } } + +fun CompoundTag.ifHas(s: String, type: Class, consumer: (T) -> Unit) { + val tag = get(s) + + if (tag != null && tag::class.java == type) { + consumer(tag as T) + } +} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/BlockMatterBottler.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/BlockMatterBottler.kt index 18d1df6d2..62ded3322 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/BlockMatterBottler.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/BlockMatterBottler.kt @@ -1,40 +1,41 @@ -package ru.dbotthepony.mc.otm.block; +package ru.dbotthepony.mc.otm.block -import net.minecraft.MethodsReturnNonnullByDefault; -import net.minecraft.core.BlockPos; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.EntityBlock; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.entity.BlockEntityTicker; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.StateDefinition; -import ru.dbotthepony.mc.otm.Registry; -import ru.dbotthepony.mc.otm.block.entity.BlockEntityMatterBottler; -import ru.dbotthepony.mc.otm.block.entity.worker.WorkerState; - -import javax.annotation.Nullable; -import javax.annotation.ParametersAreNonnullByDefault; +import net.minecraft.MethodsReturnNonnullByDefault +import javax.annotation.ParametersAreNonnullByDefault +import ru.dbotthepony.mc.otm.block.BlockMatteryRotatable +import net.minecraft.world.level.block.EntityBlock +import net.minecraft.core.BlockPos +import net.minecraft.world.level.Level +import net.minecraft.world.level.block.Block +import net.minecraft.world.level.block.state.BlockState +import net.minecraft.world.level.block.entity.BlockEntity +import ru.dbotthepony.mc.otm.block.entity.BlockEntityMatterBottler +import net.minecraft.world.level.block.entity.BlockEntityType +import net.minecraft.world.level.block.entity.BlockEntityTicker +import net.minecraft.world.level.block.state.StateDefinition +import ru.dbotthepony.mc.otm.Registry +import ru.dbotthepony.mc.otm.block.entity.worker.WorkerState @MethodsReturnNonnullByDefault @ParametersAreNonnullByDefault -public class BlockMatterBottler extends BlockMatteryRotatable implements EntityBlock { - @Nullable - @Override - public BlockEntity newBlockEntity(BlockPos blockPos, BlockState blockState) { - return new BlockEntityMatterBottler(blockPos, blockState); +class BlockMatterBottler : BlockMatteryRotatable(), EntityBlock { + override fun newBlockEntity(blockPos: BlockPos, blockState: BlockState): BlockEntity? { + return BlockEntityMatterBottler(blockPos, blockState) } - @Nullable - @Override - public BlockEntityTicker getTicker(Level p_153212_, BlockState p_153213_, BlockEntityType p_153214_) { - return p_153212_.isClientSide || p_153214_ != Registry.BlockEntities.MATTER_BOTTLER ? null : BlockEntityMatterBottler::tick; + override fun getTicker( + p_153212_: Level, + p_153213_: BlockState, + p_153214_: BlockEntityType + ): BlockEntityTicker? { + if (p_153212_.isClientSide || p_153214_ !== Registry.BlockEntities.MATTER_BOTTLER) + return null + + return BlockEntityTicker {_, _, _, tile -> if (tile is BlockEntityMatterBottler) tile.tick()} } - @Override - protected void createBlockStateDefinition(StateDefinition.Builder builder) { - super.createBlockStateDefinition(builder); - builder.add(WorkerState.SEMI_WORKER_STATE); + override fun createBlockStateDefinition(builder: StateDefinition.Builder) { + super.createBlockStateDefinition(builder) + builder.add(WorkerState.SEMI_WORKER_STATE) } -} +} \ No newline at end of file diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/BlockMatterDecomposer.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/BlockMatterDecomposer.kt index da9ef2779..4d22ac117 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/BlockMatterDecomposer.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/BlockMatterDecomposer.kt @@ -1,67 +1,69 @@ -package ru.dbotthepony.mc.otm.block; +package ru.dbotthepony.mc.otm.block -import net.minecraft.MethodsReturnNonnullByDefault; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.world.level.BlockGetter; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.EntityBlock; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.entity.BlockEntityTicker; -import net.minecraft.world.level.block.entity.BlockEntityType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.StateDefinition; -import net.minecraft.world.phys.shapes.CollisionContext; -import net.minecraft.world.phys.shapes.VoxelShape; -import ru.dbotthepony.mc.otm.Registry; -import ru.dbotthepony.mc.otm.block.entity.BlockEntityMatterDecomposer; -import ru.dbotthepony.mc.otm.block.entity.worker.WorkerState; -import ru.dbotthepony.mc.otm.shapes.BlockShapes; - -import javax.annotation.Nullable; -import javax.annotation.ParametersAreNonnullByDefault; -import java.util.List; +import net.minecraft.MethodsReturnNonnullByDefault +import javax.annotation.ParametersAreNonnullByDefault +import ru.dbotthepony.mc.otm.block.BlockMatteryRotatable +import net.minecraft.world.level.block.EntityBlock +import net.minecraft.core.BlockPos +import net.minecraft.core.Direction +import net.minecraft.world.level.block.state.BlockState +import net.minecraft.world.level.block.entity.BlockEntity +import ru.dbotthepony.mc.otm.block.entity.BlockEntityMatterDecomposer +import net.minecraft.world.level.block.entity.BlockEntityType +import net.minecraft.world.level.block.entity.BlockEntityTicker +import net.minecraft.world.level.block.state.StateDefinition +import net.minecraft.world.level.BlockGetter +import net.minecraft.world.level.Level +import net.minecraft.world.level.block.Block +import net.minecraft.world.phys.shapes.CollisionContext +import net.minecraft.world.phys.shapes.VoxelShape +import ru.dbotthepony.mc.otm.Registry +import ru.dbotthepony.mc.otm.block.BlockMatterDecomposer +import ru.dbotthepony.mc.otm.block.entity.worker.WorkerState +import ru.dbotthepony.mc.otm.shapes.BlockShapes @MethodsReturnNonnullByDefault @ParametersAreNonnullByDefault -public class BlockMatterDecomposer extends BlockMatteryRotatable implements EntityBlock { - @Nullable - @Override - public BlockEntity newBlockEntity(BlockPos blockPos, BlockState blockState) { - return new BlockEntityMatterDecomposer(blockPos, blockState); +class BlockMatterDecomposer : BlockMatteryRotatable(), EntityBlock { + override fun newBlockEntity(blockPos: BlockPos, blockState: BlockState): BlockEntity? { + return BlockEntityMatterDecomposer(blockPos, blockState) } - @Nullable - @Override - public BlockEntityTicker getTicker(Level p_153212_, BlockState p_153213_, BlockEntityType p_153214_) { - return p_153212_.isClientSide || p_153214_ != Registry.BlockEntities.MATTER_DECOMPOSER ? null : BlockEntityMatterDecomposer::tick; + override fun getTicker( + p_153212_: Level, + p_153213_: BlockState, + p_153214_: BlockEntityType + ): BlockEntityTicker? { + if (p_153212_.isClientSide || p_153214_ !== Registry.BlockEntities.MATTER_DECOMPOSER) + return null + + return BlockEntityTicker {_, _, _, t -> if (t is BlockEntityMatterDecomposer) t.tick()} } - @Override - protected void createBlockStateDefinition(StateDefinition.Builder builder) { - super.createBlockStateDefinition(builder); - builder.add(WorkerState.WORKER_STATE); + override fun createBlockStateDefinition(builder: StateDefinition.Builder) { + super.createBlockStateDefinition(builder) + builder.add(WorkerState.WORKER_STATE) } - private static final List SHAPES; + override fun getShape( + p_60555_: BlockState, + p_60556_: BlockGetter, + p_60557_: BlockPos, + p_60558_: CollisionContext + ): VoxelShape { + return SHAPES[p_60555_.getValue(FACING).ordinal] + } - static { - var def = BlockShapes.MATTER_DECOMPOSER.computeShape(); + companion object { + private val def = BlockShapes.MATTER_DECOMPOSER.computeShape() - SHAPES = List.of( + private val SHAPES: List = listOf( def, def, def, BlockShapes.MATTER_DECOMPOSER.rotate(Direction.NORTH).computeShape(), BlockShapes.MATTER_DECOMPOSER.rotate(Direction.WEST).computeShape(), BlockShapes.MATTER_DECOMPOSER.rotate(Direction.EAST).computeShape() - ); + ) } - - @Override - @SuppressWarnings("deprecation") - public VoxelShape getShape(BlockState p_60555_, BlockGetter p_60556_, BlockPos p_60557_, CollisionContext p_60558_) { - return SHAPES.get(p_60555_.getValue(FACING).ordinal()); - } -} +} \ No newline at end of file diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/BlockEntityChemicalGenerator.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/BlockEntityChemicalGenerator.kt index 207ac86b1..6b95de134 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/BlockEntityChemicalGenerator.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/BlockEntityChemicalGenerator.kt @@ -43,7 +43,7 @@ class BlockEntityChemicalGenerator(pos: BlockPos, state: BlockState) : BlockEnti private var valid = true private var resolver = LazyOptional.of {energy} - override fun getCapability(cap: Capability, side: Direction?): LazyOptional { + override fun getCapability(cap: Capability, side: Direction?): LazyOptional { if (valid && (cap == MatteryCapability.ENERGY || cap == CapabilityEnergy.ENERGY) && side != blockState.getValue(BlockMatteryRotatable.FACING)) return resolver.cast() diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/BlockEntityMatterBottler.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/BlockEntityMatterBottler.kt index ec9f81981..68a2dece9 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/BlockEntityMatterBottler.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/BlockEntityMatterBottler.kt @@ -1,366 +1,329 @@ -package ru.dbotthepony.mc.otm.block.entity; +package ru.dbotthepony.mc.otm.block.entity -import net.minecraft.MethodsReturnNonnullByDefault; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.TranslatableComponent; -import net.minecraft.world.entity.player.Inventory; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.inventory.AbstractContainerMenu; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.entity.BlockEntity; -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.entity.worker.WorkerState; -import ru.dbotthepony.mc.otm.capability.*; -import ru.dbotthepony.mc.otm.capability.matter.IMatterGridCell; -import ru.dbotthepony.mc.otm.capability.matter.IMatterHandler; -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.matter.MatterGrid; -import ru.dbotthepony.mc.otm.menu.MatterBottlerMenu; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import javax.annotation.ParametersAreNonnullByDefault; -import java.math.BigDecimal; +import net.minecraft.MethodsReturnNonnullByDefault +import javax.annotation.ParametersAreNonnullByDefault +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.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.level.Level +import net.minecraft.world.level.block.Block +import net.minecraftforge.common.capabilities.Capability +import ru.dbotthepony.mc.otm.Registry +import ru.dbotthepony.mc.otm.block.entity.worker.WorkerState +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.set @MethodsReturnNonnullByDefault @ParametersAreNonnullByDefault -public class BlockEntityMatterBottler extends BlockEntityMatteryPowered implements IMatterGridCell { - public BlockEntityMatterBottler(BlockPos p_155229_, BlockState p_155230_) { - super(Registry.BlockEntities.MATTER_BOTTLER, p_155229_, p_155230_); - energy = new MatteryMachineEnergyStorage(this, MatteryMachineEnergyStorage.MachineType.WORKER); - } +class BlockEntityMatterBottler(p_155229_: BlockPos, p_155230_: BlockState) : + BlockEntityMatteryPowered(Registry.BlockEntities.MATTER_BOTTLER, p_155229_, p_155230_), IMatterGraphNode { - private static final TranslatableComponent MACHINE_NAME = new TranslatableComponent("block.overdrive_that_matters.matter_bottler"); + private val node = Graph6Node(this) + private val resolverNode = LazyOptional.of { this } - public boolean getWorkFlow() { - return work_flow; - } - - public void setWorkFlow(boolean work_flow) { - this.work_flow = work_flow; - this.setChanged(); - } - - public void switchWorkFlow() { - setWorkFlow(!work_flow); + override fun getAsMatterNode(): Graph6Node { + return node } // true - bottling // false - unbottling - protected boolean work_flow = true; + var workFlow: Boolean = true + set(value) { + field = value + this.setChangedLight() + } + fun switchWorkFlow() { + workFlow = !workFlow + } + + // TODO: оно должно что то делать // true - continue even if empty when bottling / if full while unbottling // false - spit into output slot - protected boolean work_behavior = true; + //private var work_behavior = true - public final MatteryContainer work_slots = new MatteryContainer(this::setChanged, 6) { - @Override - public int getMaxStackSize(int slot) { - return 1; + @JvmField + val container: MatteryContainer = object : MatteryContainer(this::setChangedLight, 6) { + override fun getMaxStackSize(slot: Int): Int { + return 1 } - }; + } - public final MatteryContainerHandler work_slots_handler = work_slots.handler((slot, stack) -> { - if (work_flow) { - return slot < 3 && stack.getCapability(MatteryCapability.MATTER).isPresent(); + val itemHandler = container.handler({ slot: Int, stack: ItemStack -> + if (this.workFlow) { + return@handler slot < 3 && stack.getCapability(MatteryCapability.MATTER).isPresent + } + slot >= 3 && stack.getCapability(MatteryCapability.MATTER).isPresent + }, { slot: Int, amount: Int, stack: ItemStack? -> + if (this.workFlow) { + return@handler slot >= 3 + } + slot < 3 + }) + + @JvmField + val matter: MatterHandlerCapability = + object : MatterHandlerCapability(this::setChangedLight, MatterDirection.BIDIRECTIONAL, Fraction(4)) { + override fun getDirection(): MatterDirection { + return if (this@BlockEntityMatterBottler.workFlow) MatterDirection.RECEIVE else MatterDirection.EXTRACT + } } - return slot >= 3 && stack.getCapability(MatteryCapability.MATTER).isPresent(); - }, (slot, amount, stack) -> { - if (work_flow) { - return slot >= 3; - } + private var initialCapacity: Fraction? = null + private var lastWorkStack: ItemStack? = null - return slot < 3; - }); - - public final MatterHandlerCapability matter = new MatterHandlerCapability(this::setChanged, IMatterHandler.MatterDirection.BIDIRECTIONAL, new Fraction(4)) { - @Nonnull - @Override - public MatterDirection getDirection() { - return work_flow ? MatterDirection.RECEIVE : MatterDirection.EXTRACT; - } - }; - - private static final Fraction MATTER_EXCHANGE_RATE = new Fraction("0.04"); - private static final Fraction ENERGY_CONSUMPTION = new Fraction(20); - - private LazyOptional cell_resolver = LazyOptional.of(() -> this); - - protected Fraction initial_capacity; - protected ItemStack last_work_stack; - - private MatterGrid grid; - - @Nullable - @Override - public MatterGrid getMatterGrid() { - return grid; + override fun getMatterHandler(): IMatterHandler { + return matter } - @Override - public boolean isValidMatterCell() { - return valid; + override fun setLevel(p_155231_: Level) { + super.setLevel(p_155231_) + + if (p_155231_ is ServerLevel) + MatterNetworkGraph.discoverFull(this, node) } - @Override - public void setMatterGrid(MatterGrid grid) { - this.grid = grid; + private var valid = true + + override fun invalidateCaps() { + super.invalidateCaps() + valid = false + itemHandler.invalidate() + matter.invalidate() } - @Nullable - @Override - public IMatterHandler getMatterHandler() { - return matter; + override fun reviveCaps() { + super.reviveCaps() + valid = true + itemHandler.revive() + matter.revive() } - @Override - public void setLevel(Level p_155231_) { - super.setLevel(p_155231_); - - if (grid == null) - scheduleDiscoverNeighbours(p_155231_, getBlockPos()); - } - - private boolean valid = true; - - @Override - public void invalidateCaps() { - super.invalidateCaps(); - valid = false; - work_slots_handler.invalidate(); - matter.invalidate(); - cell_resolver.invalidate(); - } - - @Override - public void reviveCaps() { - super.reviveCaps(); - valid = true; - work_slots_handler.revive(); - matter.revive(); - cell_resolver = LazyOptional.of(() -> this); - } - - @Nonnull - @Override - public LazyOptional getCapability(@Nonnull Capability cap, @Nullable Direction side) { + override fun getCapability(cap: Capability, side: Direction?): LazyOptional { if (valid) { - if (cap == MatteryCapability.MATTER) { - return matter.get().cast(); + if (cap === MatteryCapability.MATTER) { + return matter.get().cast() } - if (cap == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) { - return work_slots_handler.get().cast(); + if (cap === CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) { + return itemHandler.get().cast() } - if (cap == MatteryCapability.MATTER_CELL) { - return cell_resolver.cast(); + if (cap === MatteryCapability.MATTER_CELL) { + return resolverNode.cast() } } - return super.getCapability(cap, side); + return super.getCapability(cap, side) } - @Override - protected Component getDefaultDisplayName() { - return MACHINE_NAME; + override fun getDefaultDisplayName(): Component { + return MACHINE_NAME } - @Nullable - @Override - public AbstractContainerMenu createMenu(int containerID, Inventory inventory, Player ply) { - return new MatterBottlerMenu(containerID, inventory, this); + override fun createMenu(containerID: Int, inventory: Inventory, ply: Player): AbstractContainerMenu { + return MatterBottlerMenu(containerID, inventory, this) } - @Override - public void saveAdditional(CompoundTag nbt) { - super.saveAdditional(nbt); - nbt.put("work_slots", work_slots.serializeNBT()); - nbt.putBoolean("work_flow", work_flow); - nbt.put("matter_capability", matter.serializeNBT()); + override fun saveAdditional(nbt: CompoundTag) { + super.saveAdditional(nbt) + nbt["work_slots"] = container.serializeNBT() + nbt["work_flow"] = this.workFlow + nbt["matter_capability"] = matter.serializeNBT() } - @Override - public void load(CompoundTag nbt) { - super.load(nbt); - work_slots.deserializeNBT(nbt.get("work_slots")); - work_flow = nbt.getBoolean("work_flow"); + override fun load(nbt: CompoundTag) { + super.load(nbt) + container.deserializeNBT(nbt["work_slots"]) + workFlow = nbt.getBoolean("work_flow") - if (nbt.get("matter_capability") instanceof CompoundTag _matter) - matter.deserializeNBT(_matter); + nbt.ifHas("matter_capability", CompoundTag::class.java) { + matter.deserializeNBT(it) + } } - private static final Fraction EXTRACTION_TICKS = new Fraction(200); + init { + energy = MatteryMachineEnergyStorage(this, MatteryMachineEnergyStorage.MachineType.WORKER) + } - public float getWorkProgress() { - if (last_work_stack == null) { - return 0; + fun getWorkProgress(): Float { + if (lastWorkStack == null) { + return 0f } - var cap = last_work_stack.getCapability(MatteryCapability.MATTER).resolve(); + val resolver = lastWorkStack!!.getCapability(MatteryCapability.MATTER).resolve() - if (cap.isEmpty()) { - return 0; + if (resolver.isEmpty) { + return 0f } - if (work_flow) { - if (cap.get().getMaxStoredMatter().minus(initial_capacity).compareTo(Fraction.ZERO) <= 0) { - return 0; + val cap = resolver.get() + + if (this.workFlow) { + if (cap.maxStoredMatter - initialCapacity!! <= Fraction.ZERO) { + return 0f } - return cap.get().getStoredMatter().minus(initial_capacity).div(cap.get().getMaxStoredMatter().minus(initial_capacity)).toFloat(); + return ((cap.storedMatter - initialCapacity!!) / (cap.maxStoredMatter - initialCapacity!!)).toFloat() } - if (initial_capacity.compareTo(Fraction.ZERO) <= 0) { - return 0; + if (initialCapacity!! <= Fraction.ZERO) { + return 0f } - return Fraction.ONE.minus(cap.get().getStoredMatter().div(initial_capacity)).toFloat(); + return (Fraction.ONE - cap.storedMatter / initialCapacity!!).toFloat() } - public static void tick(Level level, BlockPos blockPos, BlockState blockState, T t) { - if (t instanceof BlockEntityMatterBottler tile) { - tile.batteryChargeLoop(); + fun tick() { + batteryChargeLoop() - if (tile.isBlockedByRedstone()) { - if (tile.getBlockState().getValue(WorkerState.SEMI_WORKER_STATE) != WorkerState.IDLE) { - level.setBlock(tile.getBlockPos(), tile.getBlockState().setValue(WorkerState.SEMI_WORKER_STATE, WorkerState.IDLE), Block.UPDATE_CLIENTS); - } - - return; + if (isBlockedByRedstone) { + if (blockState.getValue(WorkerState.SEMI_WORKER_STATE) != WorkerState.IDLE) { + level!!.setBlock( + blockPos, + blockState.setValue(WorkerState.SEMI_WORKER_STATE, WorkerState.IDLE), + Block.UPDATE_CLIENTS + ) } - ItemStack work_stack = null; - IMatterHandler capability = null; - int align = tile.work_flow ? 0 : 3; - int work_slot = -1; + return + } - for (int i = align; i < align + 3; i++) { - var get = tile.work_slots.getItem(i); + var work_stack: ItemStack? = null + var capability: IMatterHandler? = null + val align = if (workFlow) 0 else 3 + var work_slot = -1 + val unexpectedDirection = if (workFlow) MatterDirection.EXTRACT else MatterDirection.RECEIVE - if (!get.isEmpty()) { - var cap = get.getCapability(MatteryCapability.MATTER).resolve(); + for (i in align until align + 3) { + val itemStack = container.getItem(i) - if (cap.isPresent() && cap.get().getDirection() != (tile.work_flow ? IMatterHandler.MatterDirection.EXTRACT : IMatterHandler.MatterDirection.RECEIVE) && (tile.work_flow ? cap.get().getMissingMatter().compareTo(Fraction.ZERO) > 0 : cap.get().getStoredMatter().compareTo(Fraction.ZERO) > 0)) { - work_stack = get; - capability = cap.get(); - work_slot = i; - break; + if (!itemStack.isEmpty) { + val cap = itemStack.getCapability(MatteryCapability.MATTER).resolve() + + if (cap.isPresent && cap.get().direction != unexpectedDirection) { + if (this.workFlow && cap.get().missingMatter > Fraction.ZERO || !this.workFlow && cap.get().storedMatter > Fraction.ZERO) { + work_stack = itemStack + capability = cap.get() + work_slot = i + break } } } + } - if (work_stack == null) { - tile.last_work_stack = null; - tile.initial_capacity = null; - } else if (work_stack != tile.last_work_stack) { - tile.last_work_stack = work_stack; - tile.initial_capacity = capability.getStoredMatter(); + if (work_stack == null) { + lastWorkStack = null + initialCapacity = null + } else if (work_stack != lastWorkStack) { + lastWorkStack = work_stack + initialCapacity = capability!!.storedMatter + } + + val graph = node.graph as MatterNetworkGraph? + + if (capability != null) { + if (blockState.getValue(WorkerState.SEMI_WORKER_STATE) != WorkerState.WORKING) { + level!!.setBlock(blockPos, blockState.setValue(WorkerState.SEMI_WORKER_STATE, WorkerState.WORKING), Block.UPDATE_CLIENTS) } - if (tile.work_flow) { - if (capability != null) { - if (tile.getBlockState().getValue(WorkerState.SEMI_WORKER_STATE) != WorkerState.WORKING) { - level.setBlock(tile.getBlockPos(), tile.getBlockState().setValue(WorkerState.SEMI_WORKER_STATE, WorkerState.WORKING), Block.UPDATE_CLIENTS); + if (workFlow) { + if (matter.storedMatter < MATTER_EXCHANGE_RATE && graph != null) { + val extracted = graph.extractMatter( + matter.missingMatter.min(MATTER_EXCHANGE_RATE * EXTRACTION_TICKS, capability.missingMatter - matter.storedMatter), true + ) + + if (extracted > Fraction.ZERO) { + val received = matter.receiveMatterOuter(extracted, false) + graph.extractMatter(received, false) } + } - if (tile.matter.getStoredMatter().compareTo(MATTER_EXCHANGE_RATE) < 0) { - if (tile.grid != null) { - var extracted = tile.grid.extractMatter( - tile.matter.getMissingMatter() - .min(MATTER_EXCHANGE_RATE.times(EXTRACTION_TICKS)) - .min(capability.getMissingMatter().minus(tile.matter.getStoredMatter())) - , true); + if (matter.storedMatter > Fraction.ZERO) { + val energyExtracted = energy.extractEnergyInner(ENERGY_CONSUMPTION, true) - if (extracted.compareTo(Fraction.ZERO) > 0) { - var received = tile.matter.receiveMatterOuter(extracted, false); - tile.grid.extractMatter(received, false); - } - } - } + if (!energyExtracted.isZero()) { + val matter = capability.receiveMatterOuter(MATTER_EXCHANGE_RATE.min(matter.storedMatter) * (energyExtracted / ENERGY_CONSUMPTION), true) - if (tile.matter.getStoredMatter().compareTo(Fraction.ZERO) > 0) { - var energy = tile.energy.extractEnergyInner(ENERGY_CONSUMPTION, true); + if (!matter.isZero()) { + energy.extractEnergyInner(ENERGY_CONSUMPTION * matter / MATTER_EXCHANGE_RATE,false) - if (energy.compareTo(Fraction.ZERO) > 0) { - var matter = capability.receiveMatterOuter(MATTER_EXCHANGE_RATE.min(tile.matter.getStoredMatter()).times(energy.div(ENERGY_CONSUMPTION)), true); + capability.receiveMatterOuter(matter, false) + this.matter.extractMatterInner(matter, false) - if (matter.compareTo(Fraction.ZERO) > 0) { - tile.energy.extractEnergyInner(ENERGY_CONSUMPTION.times(matter.div(MATTER_EXCHANGE_RATE)), false); - capability.receiveMatterOuter(matter, false); - tile.matter.extractMatterInner(matter, false); - - if (capability.getMissingMatter().compareTo(Fraction.ZERO) == 0) { - for (int i = 3; i < 6; i++) { - if (tile.work_slots.getItem(i).isEmpty()) { - tile.work_slots.setItem(work_slot, ItemStack.EMPTY); - tile.work_slots.setItem(i, work_stack); - break; - } + if (capability.missingMatter.isZero()) { + for (i in 3..5) { + if (container.getItem(i).isEmpty) { + container.setItem(work_slot, ItemStack.EMPTY) + container.setItem(i, work_stack!!) + break } } } } } - } else { - if (tile.getBlockState().getValue(WorkerState.SEMI_WORKER_STATE) != WorkerState.IDLE) { - level.setBlock(tile.getBlockPos(), tile.getBlockState().setValue(WorkerState.SEMI_WORKER_STATE, WorkerState.IDLE), Block.UPDATE_CLIENTS); - } } } else { - if (capability != null) { - if (tile.getBlockState().getValue(WorkerState.SEMI_WORKER_STATE) != WorkerState.WORKING) { - level.setBlock(tile.getBlockPos(), tile.getBlockState().setValue(WorkerState.SEMI_WORKER_STATE, WorkerState.WORKING), Block.UPDATE_CLIENTS); - } + val energyExtracted = energy.extractEnergyInner(ENERGY_CONSUMPTION, true) - var energy = tile.energy.extractEnergyInner(ENERGY_CONSUMPTION, true); + if (!energyExtracted.isZero()) { + val matter = capability.extractMatterOuter(MATTER_EXCHANGE_RATE.min(matter.missingMatter) * energyExtracted / ENERGY_CONSUMPTION, true) - if (energy.compareTo(Fraction.ZERO) > 0) { - var matter = capability.extractMatterOuter(MATTER_EXCHANGE_RATE.min(tile.matter.getMissingMatter()).times(energy.div(ENERGY_CONSUMPTION)), true); + if (!matter.isZero()) { + this.energy.extractEnergyInner(ENERGY_CONSUMPTION * matter / MATTER_EXCHANGE_RATE,false) - if (matter.compareTo(Fraction.ZERO) > 0) { - tile.energy.extractEnergyInner(ENERGY_CONSUMPTION.times(matter.div(MATTER_EXCHANGE_RATE)), false); - capability.extractMatterOuter(matter, false); - tile.matter.receiveMatterInner(matter, false); + capability.extractMatterOuter(matter, false) + this.matter.receiveMatterInner(matter, false) - if (capability.getStoredMatter().compareTo(Fraction.ZERO) == 0) { - for (int i = 2; i >= 0; i--) { - if (tile.work_slots.getItem(i).isEmpty()) { - tile.work_slots.setItem(work_slot, ItemStack.EMPTY); - tile.work_slots.setItem(i, work_stack); - break; - } + if (capability.storedMatter.isZero()) { + for (i in 2 downTo 0) { + if (container.getItem(i).isEmpty) { + container.setItem(work_slot, ItemStack.EMPTY) + container.setItem(i, work_stack!!) + break } } } } - } else { - if (tile.getBlockState().getValue(WorkerState.SEMI_WORKER_STATE) != WorkerState.IDLE) { - level.setBlock(tile.getBlockPos(), tile.getBlockState().setValue(WorkerState.SEMI_WORKER_STATE, WorkerState.IDLE), Block.UPDATE_CLIENTS); - } - } - - if (tile.matter.getStoredMatter().compareTo(Fraction.ZERO) > 0 && tile.grid != null) { - var diff = tile.matter.extractMatterInner(tile.matter.getStoredMatter(), true); - var diff2 = tile.grid.softPushMatter(diff, true); - - tile.matter.extractMatterInner(diff2, false); - tile.grid.softPushMatter(diff2, false); } } + } else { + level!!.setBlock(blockPos, blockState.setValue(WorkerState.SEMI_WORKER_STATE, WorkerState.IDLE), Block.UPDATE_CLIENTS) + } + + if (!workFlow && !matter.storedMatter.isZero() && graph != null) { + val diff = matter.extractMatterInner(matter.storedMatter, true) + val diff2 = graph.receiveMatter(diff, true) + matter.extractMatterInner(diff2, false) + graph.receiveMatter(diff2, false) } } -} + + companion object { + private val MACHINE_NAME = TranslatableComponent("block.overdrive_that_matters.matter_bottler") + private val MATTER_EXCHANGE_RATE = Fraction("0.04") + private val ENERGY_CONSUMPTION = Fraction(20) + private val EXTRACTION_TICKS = Fraction(200) + } +} \ No newline at end of file diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/BlockEntityMatterCable.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/BlockEntityMatterCable.kt new file mode 100644 index 000000000..75797fb3b --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/BlockEntityMatterCable.kt @@ -0,0 +1,71 @@ +package ru.dbotthepony.mc.otm.block.entity + +import net.minecraft.core.BlockPos +import net.minecraft.core.Direction +import net.minecraft.server.level.ServerLevel +import net.minecraft.world.level.Level +import net.minecraft.world.level.block.Block +import net.minecraft.world.level.block.entity.BlockEntity +import net.minecraft.world.level.block.state.BlockState +import net.minecraftforge.common.capabilities.Capability +import net.minecraftforge.common.util.LazyOptional +import ru.dbotthepony.mc.otm.Registry +import ru.dbotthepony.mc.otm.block.BlockMatterCable +import ru.dbotthepony.mc.otm.capability.MatteryCapability +import ru.dbotthepony.mc.otm.graph.Graph6Node +import ru.dbotthepony.mc.otm.graph.GraphNodeListener +import ru.dbotthepony.mc.otm.graph.matter.IMatterGraphNode +import ru.dbotthepony.mc.otm.graph.matter.MatterNetworkGraph + +class BlockEntityMatterCable(p_155229_: BlockPos, p_155230_: BlockState) : + BlockEntity(Registry.BlockEntities.MATTER_CABLE, p_155229_, p_155230_), IMatterGraphNode, GraphNodeListener { + + private var valid = true + private val node = Graph6Node(this) + private val resolverNode = LazyOptional.of { this } + + override fun getAsMatterNode(): Graph6Node { + return node + } + + override fun invalidateCaps() { + super.invalidateCaps() + valid = false + } + + override fun reviveCaps() { + super.reviveCaps() + valid = true + } + + override fun getCapability(cap: Capability, side: Direction?): LazyOptional { + if (valid) { + if (cap === MatteryCapability.MATTER_CELL) + return resolverNode.cast() + } + + return super.getCapability(cap, side) + } + + override fun setLevel(p_155231_: Level) { + super.setLevel(p_155231_) + + if (p_155231_ is ServerLevel) + MatterNetworkGraph.discoverFull(this, node) + } + + override fun onNeighbour(node: Graph6Node<*>, direction: Direction) { + val new_state = blockState.setValue(BlockMatterCable.MAPPING_CONNECTION_PROP[direction.ordinal], true) + if (new_state !== blockState) level!!.setBlock(blockPos, new_state, Block.UPDATE_CLIENTS) + } + + override fun onUnNeighbour(node: Graph6Node<*>, direction: Direction) { + val new_state = blockState.setValue(BlockMatterCable.MAPPING_CONNECTION_PROP[direction.ordinal], false) + if (new_state !== blockState) level!!.setBlock(blockPos, new_state, Block.UPDATE_CLIENTS) + } + + override fun setRemoved() { + super.setRemoved() + node.destroy(::MatterNetworkGraph) + } +} \ No newline at end of file diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/BlockEntityMatterCapacitorBank.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/BlockEntityMatterCapacitorBank.kt index ddf8e7127..1343fa9f1 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/BlockEntityMatterCapacitorBank.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/BlockEntityMatterCapacitorBank.kt @@ -1,279 +1,207 @@ -package ru.dbotthepony.mc.otm.block.entity; +package ru.dbotthepony.mc.otm.block.entity -import net.minecraft.MethodsReturnNonnullByDefault; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.TranslatableComponent; -import net.minecraft.world.entity.player.Inventory; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.inventory.AbstractContainerMenu; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraftforge.common.capabilities.Capability; -import net.minecraftforge.common.util.LazyOptional; -import ru.dbotthepony.mc.otm.block.BlockBatteryBank; -import ru.dbotthepony.mc.otm.capability.matter.IMatterGridCell; -import ru.dbotthepony.mc.otm.core.Fraction; -import ru.dbotthepony.mc.otm.matter.MatterGrid; -import ru.dbotthepony.mc.otm.Registry; -import ru.dbotthepony.mc.otm.capability.matter.IMatterHandler; -import ru.dbotthepony.mc.otm.capability.matter.IPatternStorage; -import ru.dbotthepony.mc.otm.capability.MatteryCapability; -import ru.dbotthepony.mc.otm.container.MatteryContainer; -import ru.dbotthepony.mc.otm.menu.MatterCapacitorBankMenu; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import javax.annotation.ParametersAreNonnullByDefault; -import java.math.BigDecimal; -import java.util.Optional; +import net.minecraft.MethodsReturnNonnullByDefault +import net.minecraft.core.BlockPos +import net.minecraft.core.Direction +import net.minecraft.nbt.CompoundTag +import net.minecraft.network.chat.Component +import net.minecraft.network.chat.TranslatableComponent +import net.minecraft.server.level.ServerLevel +import net.minecraft.world.entity.player.Inventory +import net.minecraft.world.entity.player.Player +import net.minecraft.world.inventory.AbstractContainerMenu +import net.minecraft.world.item.ItemStack +import net.minecraft.world.level.Level +import net.minecraft.world.level.block.Block +import net.minecraft.world.level.block.state.BlockState +import net.minecraftforge.common.capabilities.Capability +import net.minecraftforge.common.util.LazyOptional +import ru.dbotthepony.mc.otm.Registry +import ru.dbotthepony.mc.otm.block.BlockBatteryBank +import ru.dbotthepony.mc.otm.capability.MatteryCapability +import ru.dbotthepony.mc.otm.capability.matter.IMatterHandler +import ru.dbotthepony.mc.otm.capability.matter.IMatterHandler.MatterDirection +import ru.dbotthepony.mc.otm.container.MatteryContainer +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.menu.MatterCapacitorBankMenu +import ru.dbotthepony.mc.otm.set +import javax.annotation.ParametersAreNonnullByDefault @MethodsReturnNonnullByDefault @ParametersAreNonnullByDefault -public class BlockEntityMatterCapacitorBank extends BlockEntityMattery implements IMatterGridCell { - public final IMatterHandler matter = new IMatterHandler() { - @Nonnull - @Override - public Fraction getStoredMatter() { - Fraction summ = Fraction.ZERO; +class BlockEntityMatterCapacitorBank(p_155229_: BlockPos, p_155230_: BlockState) : + BlockEntityMattery(Registry.BlockEntities.MATTER_CAPACITOR_BANK, p_155229_, p_155230_), IMatterGraphNode, IMatterHandler { - for (int i = 0; i < matter_container.getContainerSize(); i++) { - ItemStack stack = matter_container.getItem(i); + private val node = Graph6Node(this) + private val resolverNode = LazyOptional.of { this } - if (!stack.isEmpty()) { - Optional handler = stack.getCapability(MatteryCapability.MATTER).resolve(); + override fun getAsMatterNode(): Graph6Node { + return node + } - if (handler.isPresent()) { - summ = summ.plus(handler.get().getStoredMatter()); - } + override fun getStoredMatter(): Fraction { + var summ = Fraction.ZERO + + for (stack in matterContainer) + if (!stack.isEmpty) + stack.getCapability(MatteryCapability.MATTER).ifPresent { + summ += it.storedMatter + } + + return summ + } + + override fun getMaxStoredMatter(): Fraction { + var summ = Fraction.ZERO + + for (stack in matterContainer) + if (!stack.isEmpty) + stack.getCapability(MatteryCapability.MATTER).ifPresent { + summ += it.maxStoredMatter + } + + return summ + } + + override fun receiveMatterOuter(howMuch: Fraction, simulate: Boolean): Fraction { + return receiveMatterInner(howMuch, simulate) + } + + override fun receiveMatterInner(howMuch: Fraction, simulate: Boolean): Fraction { + var howMuch = howMuch + var summ = Fraction.ZERO + + for (stack in matterContainer) { + if (!stack.isEmpty) { + stack.getCapability(MatteryCapability.MATTER).ifPresent { + val diff = it.receiveMatterOuter(howMuch, simulate) + summ += diff + howMuch -= diff + } + + if (howMuch.isZero()) { + break } } - - return summ; } - @Nonnull - @Override - public Fraction getMaxStoredMatter() { - Fraction summ = Fraction.ZERO; + return summ + } - for (int i = 0; i < matter_container.getContainerSize(); i++) { - ItemStack stack = matter_container.getItem(i); + override fun extractMatterOuter(howMuch: Fraction, simulate: Boolean): Fraction { + return extractMatterInner(howMuch, simulate) + } - if (!stack.isEmpty()) { - Optional handler = stack.getCapability(MatteryCapability.MATTER).resolve(); + override fun extractMatterInner(howMuch: Fraction, simulate: Boolean): Fraction { + var howMuch = howMuch + var summ = Fraction.ZERO - if (handler.isPresent()) { - summ = summ.plus(handler.get().getMaxStoredMatter()); - } + for (stack in matterContainer) { + if (!stack.isEmpty) { + stack.getCapability(MatteryCapability.MATTER).ifPresent { + val diff = it.extractMatterOuter(howMuch, simulate) + summ += diff + howMuch -= diff + } + + if (howMuch.isZero()) { + break } } - - return summ; } + return summ + } - @Nonnull - @Override - public Fraction receiveMatterOuter(Fraction howMuch, boolean simulate) { - return receiveMatterInner(howMuch, simulate); - } + override fun getDirection(): MatterDirection { + return MatterDirection.BIDIRECTIONAL + } - @Nonnull - @Override - public Fraction receiveMatterInner(Fraction howMuch, boolean simulate) { - Fraction summ = Fraction.ZERO; + private var resolver = LazyOptional.of { this } - for (int i = 0; i < matter_container.getContainerSize(); i++) { - ItemStack stack = matter_container.getItem(i); - - if (!stack.isEmpty()) { - Optional handler = stack.getCapability(MatteryCapability.MATTER).resolve(); - - if (handler.isPresent()) { - var diff = handler.get().receiveMatterOuter(howMuch, simulate); - summ = summ.plus(diff); - howMuch = howMuch.minus(diff); - - if (howMuch.compareTo(Fraction.ZERO) == 0) { - break; - } - } - } - } - - return summ; - } - - @Nonnull - @Override - public Fraction extractMatterOuter(Fraction howMuch, boolean simulate) { - return extractMatterInner(howMuch, simulate); - } - - @Nonnull - @Override - public Fraction extractMatterInner(Fraction howMuch, boolean simulate) { - Fraction summ = Fraction.ZERO; - - for (int i = 0; i < matter_container.getContainerSize(); i++) { - ItemStack stack = matter_container.getItem(i); - - if (!stack.isEmpty()) { - Optional handler = stack.getCapability(MatteryCapability.MATTER).resolve(); - - if (handler.isPresent()) { - var diff = handler.get().extractMatterOuter(howMuch, simulate); - summ = summ.plus(diff); - howMuch = howMuch.minus(diff); - - if (howMuch.compareTo(Fraction.ZERO) == 0) { - break; - } - } - } - } - - return summ; - } - - @Nonnull - @Override - public MatterDirection getDirection() { - return MatterDirection.BIDIRECTIONAL; - } - }; - - private LazyOptional resolver = LazyOptional.of(() -> matter); - - public final MatteryContainer matter_container = new MatteryContainer(this::setChanged, 6 * 2) { - @Override - public void setChanged(int slot, ItemStack new_state, ItemStack old_state) { - super.setChanged(slot, new_state, old_state); + @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) + val level = level if (level != null) { - var state = getBlockState(); + var state = blockState - for (int i = 0; i < BlockBatteryBank.BATTERY_SLOTS_PROPS.length; i++) { - state = state.setValue(BlockBatteryBank.BATTERY_SLOTS_PROPS[i], getItem(i).getCapability(MatteryCapability.MATTER).isPresent()); + for (i in BlockBatteryBank.BATTERY_SLOTS_PROPS.indices) { + state = state.setValue( + BlockBatteryBank.BATTERY_SLOTS_PROPS[i], + getItem(i).getCapability(MatteryCapability.MATTER).isPresent + ) } - if (state != getBlockState()) { - level.setBlock(getBlockPos(), state, Block.UPDATE_CLIENTS); + if (state !== blockState) { + level.setBlock(blockPos, state, Block.UPDATE_CLIENTS) } } } - }; - - public BlockEntityMatterCapacitorBank(BlockPos p_155229_, BlockState p_155230_) { - super(Registry.BlockEntities.MATTER_CAPACITOR_BANK, p_155229_, p_155230_); } - private final TranslatableComponent MACHINE_NAME = new TranslatableComponent("block.overdrive_that_matters.matter_capacitor_bank"); - - @Override - protected Component getDefaultDisplayName() { - return MACHINE_NAME; + companion object { + private val MACHINE_NAME = TranslatableComponent("block.overdrive_that_matters.matter_capacitor_bank") } - @Override - public void saveAdditional(CompoundTag nbt) { - super.saveAdditional(nbt); - nbt.put("matter_container", matter_container.serializeNBT()); + override fun getDefaultDisplayName(): Component { + return MACHINE_NAME } - @Override - public void load(CompoundTag nbt) { - matter_container.deserializeNBT(nbt.get("matter_container")); - super.load(nbt); + override fun saveAdditional(nbt: CompoundTag) { + super.saveAdditional(nbt) + nbt["matter_container"] = matterContainer.serializeNBT() } - @Nullable - @Override - public AbstractContainerMenu createMenu(int containerID, Inventory inventory, Player ply) { - return new MatterCapacitorBankMenu(containerID, inventory, this); + override fun load(nbt: CompoundTag) { + matterContainer.deserializeNBT(nbt["matter_container"]) + super.load(nbt) } - private boolean valid = true; - - @Override - public void invalidateCaps() { - super.invalidateCaps(); - valid = false; - resolver.invalidate(); - resolver_grid.invalidate(); + override fun createMenu(containerID: Int, inventory: Inventory, ply: Player): AbstractContainerMenu { + return MatterCapacitorBankMenu(containerID, inventory, this) } - @Override - public void reviveCaps() { - super.reviveCaps(); - valid = true; - resolver = LazyOptional.of(() -> matter); - resolver_grid = LazyOptional.of(() -> this); + private var valid = true + + override fun invalidateCaps() { + super.invalidateCaps() + valid = false + resolver.invalidate() } - private LazyOptional resolver_grid = LazyOptional.of(() -> this); + override fun reviveCaps() { + super.reviveCaps() + valid = true + resolver = LazyOptional.of { this } + } - @Nonnull - @Override - public LazyOptional getCapability(@Nonnull Capability cap, @Nullable Direction side) { + override fun getCapability(cap: Capability, side: Direction?): LazyOptional { if (valid) { - if (cap == MatteryCapability.MATTER) - return resolver.cast(); - - if (cap == MatteryCapability.MATTER_CELL) - return resolver_grid.cast(); + if (cap === MatteryCapability.MATTER) return resolver.cast() + if (cap === MatteryCapability.MATTER_CELL) return resolverNode.cast() } - return super.getCapability(cap, side); + return super.getCapability(cap, side) } - private MatterGrid grid; - - @Nullable - @Override - public MatterGrid getMatterGrid() { - return grid; + override fun setRemoved() { + super.setRemoved() + node.destroy(::MatterNetworkGraph) } - @Override - public void setRemoved() { - super.setRemoved(); + override fun setLevel(p_155231_: Level) { + super.setLevel(p_155231_) - if (grid != null) - grid.remove(this); + if (p_155231_ is ServerLevel) + MatterNetworkGraph.discoverFull(this, node) } - @Override - public void setLevel(Level p_155231_) { - super.setLevel(p_155231_); - - if (!p_155231_.isClientSide) - MatterGrid.scheduleDiscoverNeighbours(this, getBlockPos(), p_155231_); + override fun getMatterHandler(): IMatterHandler { + return this } - - @Nullable - @Override - public IMatterHandler getMatterHandler() { - return valid ? matter : null; - } - - @Nullable - @Override - public IPatternStorage getPatternStorage() { - return null; - } - - @Override - public boolean isValidMatterCell() { - return valid; - } - - @Override - public void setMatterGrid(MatterGrid grid) { - this.grid = grid; - } -} +} \ No newline at end of file diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/BlockEntityMatterDecomposer.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/BlockEntityMatterDecomposer.kt new file mode 100644 index 000000000..0eb663b77 --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/BlockEntityMatterDecomposer.kt @@ -0,0 +1,186 @@ +package ru.dbotthepony.mc.otm.block.entity + +import net.minecraft.core.BlockPos +import net.minecraft.core.Direction +import net.minecraft.nbt.CompoundTag +import net.minecraft.network.chat.Component +import net.minecraft.network.chat.TranslatableComponent +import net.minecraft.server.level.ServerLevel +import net.minecraft.world.entity.player.Inventory +import net.minecraft.world.entity.player.Player +import net.minecraft.world.inventory.AbstractContainerMenu +import net.minecraft.world.item.ItemStack +import net.minecraft.world.level.Level +import net.minecraft.world.level.block.state.BlockState +import net.minecraftforge.common.capabilities.Capability +import net.minecraftforge.common.util.LazyOptional +import net.minecraftforge.items.CapabilityItemHandler +import net.minecraftforge.items.IItemHandler +import ru.dbotthepony.mc.otm.Registry +import ru.dbotthepony.mc.otm.block.entity.worker.BlockEntityMatteryWorker +import ru.dbotthepony.mc.otm.block.entity.worker.MachineJob +import ru.dbotthepony.mc.otm.block.entity.worker.MachineJobStatus +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.MatterHandlerCapability +import ru.dbotthepony.mc.otm.container.MatteryContainer +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.matter.MatterRegistry +import ru.dbotthepony.mc.otm.menu.MatterDecomposerMenu +import ru.dbotthepony.mc.otm.set + +class BlockEntityMatterDecomposer(pos: BlockPos, state: BlockState) + : BlockEntityMatteryWorker(Registry.BlockEntities.MATTER_DECOMPOSER, pos, state), IMatterGraphNode { + + companion object { + private val MACHINE_NAME = TranslatableComponent("block.overdrive_that_matters.matter_decomposer") + private val BASE_CONSUMPTION = Fraction(240) + } + + init { + energy = MatteryMachineEnergyStorage( + this, + MatteryMachineEnergyStorage.MachineType.WORKER, + Fraction(400000), + Fraction(2000), + Fraction(2000) + ) + } + + private var valid = true + private val node = Graph6Node(this) + + override fun getAsMatterNode(): Graph6Node { + return node + } + + @JvmField + val matter = MatterHandlerCapability(this::setChangedLight, IMatterHandler.MatterDirection.EXTRACT, Fraction("20")) + + private var resolverMatter = LazyOptional.of { matter } + private var resolverNode = LazyOptional.of { this } + + // вход, выход + @JvmField + val itemContainer = MatteryContainer(this::setChangedLight, 2) + + private val itemHandler = LazyOptional.of { + itemContainer.handler( + { slot: Int, stack: ItemStack? -> slot == 0 && MatterRegistry.canDecompose(stack) }, + { slot: Int, amount: Int, stack: ItemStack? -> slot == 1 }) + } + + override fun getDefaultDisplayName(): Component? { + return MACHINE_NAME + } + + override fun createMenu(containerID: Int, inventory: Inventory, ply: Player): AbstractContainerMenu { + return MatterDecomposerMenu(containerID, inventory, this) + } + + override fun saveAdditional(nbt: CompoundTag) { + super.saveAdditional(nbt) + nbt["work_slots"] = itemContainer.serializeNBT() + nbt["matter_capability"] = matter.serializeNBT() + } + + override fun load(nbt: CompoundTag) { + super.load(nbt) + + nbt.ifHas("matter_capability") { + if (it is CompoundTag) + matter.deserializeNBT(it) + } + + nbt.ifHas("work_slots") { + itemContainer.deserializeNBT(it) + } + } + + override fun reviveCaps() { + valid = true + super.reviveCaps() + resolverMatter = LazyOptional.of { matter } + } + + override fun invalidateCaps() { + valid = false + super.invalidateCaps() + resolverMatter.invalidate() + } + + override fun getCapability(cap: Capability, side: Direction?): LazyOptional { + if (valid) { + if (cap === MatteryCapability.MATTER) return resolverMatter.cast() + if (cap === MatteryCapability.MATTER_CELL) return resolverNode.cast() + if (cap === CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) return itemHandler.cast() + } + + return super.getCapability(cap, side) + } + + override fun onJobFinish(job: MachineJob): MachineJobStatus { + matter.receiveMatterInner(MatterRegistry.getMatterValue(job.stack()), false) + return MachineJobStatus() + } + + override fun getNextJob(): MachineJob? { + val stack = itemContainer.getItem(0) + + if (!stack.isEmpty) { + val copy = stack.copy() + copy.count = 1 + + if (MatterRegistry.canDecompose(copy)) { + val value = MatterRegistry.getMatterValue(copy) + + if (value != Fraction.ZERO && matter.canReceiveAll(value)) { + stack.shrink(1) + return MachineJob(copy, value.toDouble() * 12500.0) + } + } + } + + return null + } + + override fun setRemoved() { + super.setRemoved() + node.destroy(::MatterNetworkGraph) + } + + override fun setLevel(p_155231_: Level) { + super.setLevel(p_155231_) + + if (p_155231_ is ServerLevel) + MatterNetworkGraph.discoverFull(this, node) + } + + override fun getMatterHandler(): IMatterHandler { + return matter + } + + override fun getBaseConsumption(): Fraction { + return BASE_CONSUMPTION + } + + fun tick() { + batteryChargeLoop(); + workerLoop(); + + val grid = node.graph as MatterNetworkGraph? + + if (!matter.storedMatter.isZero() && grid != null) { + val diff = matter.extractMatterInner(matter.getStoredMatter(), true) + val diff2 = grid.receiveMatter(diff, true) + + matter.extractMatterInner(diff2, false) + grid.receiveMatter(diff2, false) + } + } +} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/BlockEntityMatterPanel.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/BlockEntityMatterPanel.kt index 627b25798..84db42e23 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/BlockEntityMatterPanel.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/BlockEntityMatterPanel.kt @@ -1,276 +1,229 @@ -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.nbt.ListTag; -import net.minecraft.nbt.Tag; -import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.TranslatableComponent; -import net.minecraft.world.entity.player.Inventory; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.inventory.AbstractContainerMenu; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraftforge.common.capabilities.Capability; -import net.minecraftforge.common.util.LazyOptional; -import ru.dbotthepony.mc.otm.Registry; -import ru.dbotthepony.mc.otm.capability.*; -import ru.dbotthepony.mc.otm.capability.matter.*; -import ru.dbotthepony.mc.otm.matter.MatterGrid; -import ru.dbotthepony.mc.otm.menu.MatterPanelMenu; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import javax.annotation.ParametersAreNonnullByDefault; -import java.util.*; -import java.util.stream.Collectors; +import net.minecraft.MethodsReturnNonnullByDefault +import javax.annotation.ParametersAreNonnullByDefault +import net.minecraft.core.BlockPos +import net.minecraft.core.Direction +import net.minecraft.world.level.block.state.BlockState +import ru.dbotthepony.mc.otm.capability.matter.IMatterTaskProvider +import ru.dbotthepony.mc.otm.menu.MatterPanelMenu +import net.minecraft.world.entity.player.Inventory +import net.minecraft.world.entity.player.Player +import net.minecraft.world.inventory.AbstractContainerMenu +import net.minecraftforge.common.util.LazyOptional +import ru.dbotthepony.mc.otm.capability.MatteryCapability +import java.util.HashMap +import java.util.UUID +import ru.dbotthepony.mc.otm.capability.matter.MatterTask +import java.util.stream.Collectors +import ru.dbotthepony.mc.otm.capability.matter.MatterTaskAllocation +import ru.dbotthepony.mc.otm.capability.matter.PatternState +import net.minecraft.nbt.CompoundTag +import net.minecraft.nbt.ListTag +import net.minecraft.nbt.Tag +import net.minecraft.network.chat.Component +import net.minecraft.network.chat.TranslatableComponent +import net.minecraft.server.level.ServerLevel +import net.minecraft.world.level.Level +import net.minecraftforge.common.capabilities.Capability +import ru.dbotthepony.mc.otm.Registry +import ru.dbotthepony.mc.otm.graph.Graph6Node +import ru.dbotthepony.mc.otm.graph.matter.IMatterGraphNode +import ru.dbotthepony.mc.otm.graph.matter.MatterNetworkGraph +import java.util.ArrayList +import java.util.List +import java.util.function.Consumer @MethodsReturnNonnullByDefault @ParametersAreNonnullByDefault -public class BlockEntityMatterPanel extends BlockEntityMattery implements IMatterGridCell, IMatterTaskProvider { - public BlockEntityMatterPanel(BlockPos p_155229_, BlockState p_155230_) { - super(Registry.BlockEntities.MATTER_PANEL, p_155229_, p_155230_); +class BlockEntityMatterPanel(p_155229_: BlockPos, p_155230_: BlockState) : + BlockEntityMattery(Registry.BlockEntities.MATTER_PANEL, p_155229_, p_155230_), IMatterGraphNode, IMatterTaskProvider { + + private val listeners = ArrayList() + private val node = Graph6Node(this) + + override fun getAsMatterNode(): Graph6Node { + return node } - private static final TranslatableComponent NAME = new TranslatableComponent("block.overdrive_that_matters.matter_panel"); - - private final ArrayList listeners = new ArrayList<>(); - - public void attachMenu(MatterPanelMenu menu) { - listeners.add(menu); + fun attachMenu(menu: MatterPanelMenu) { + listeners.add(menu) } - public void deatachMenu(MatterPanelMenu menu) { - listeners.remove(menu); + fun deatachMenu(menu: MatterPanelMenu) { + listeners.remove(menu) } - @Override - protected Component getDefaultDisplayName() { - return NAME; + override fun getDefaultDisplayName(): Component { + return NAME } - @Nullable - @Override - public AbstractContainerMenu createMenu(int containerID, Inventory inventory, Player ply) { - return new MatterPanelMenu(containerID, inventory, this); + override fun createMenu(containerID: Int, inventory: Inventory, ply: Player): AbstractContainerMenu { + return MatterPanelMenu(containerID, inventory, this) } - private boolean valid = true; + private var valid = true - @Override - public void invalidateCaps() { - super.invalidateCaps(); - valid = false; - resolver.invalidate(); + override fun invalidateCaps() { + super.invalidateCaps() + valid = false + resolver.invalidate() } - @Override - public void reviveCaps() { - super.reviveCaps(); - valid = true; - resolver = LazyOptional.of(() -> this); + override fun reviveCaps() { + super.reviveCaps() + valid = true + resolver = LazyOptional.of { this } } - private LazyOptional resolver = LazyOptional.of(() -> this); + private var resolver = LazyOptional.of { this } - @Nonnull - @Override - public LazyOptional getCapability(@Nonnull Capability cap, @Nullable Direction side) { - if (valid && (cap == MatteryCapability.MATTER_CELL || cap == MatteryCapability.TASK)) - return resolver.cast(); + override fun getCapability(cap: Capability, side: Direction?): LazyOptional { + if (valid && (cap === MatteryCapability.MATTER_CELL || cap === MatteryCapability.TASK)) + return resolver.cast() - return super.getCapability(cap, side); + return super.getCapability(cap, side) } - private MatterGrid grid; + override fun setLevel(p_155231_: Level) { + super.setLevel(p_155231_) - @Override - public void setLevel(Level p_155231_) { - super.setLevel(p_155231_); - - if (grid == null) - scheduleDiscoverNeighbours(p_155231_, getBlockPos()); + if (p_155231_ is ServerLevel) + MatterNetworkGraph.discoverFull(this, node) } - @Override - public void setRemoved() { - super.setRemoved(); - - if (level != null && !level.isClientSide && grid != null) - grid.remove(this); + override fun setRemoved() { + super.setRemoved() + node.destroy(::MatterNetworkGraph) } - @Nullable - @Override - public MatterGrid getMatterGrid() { - return grid; + override fun getTaskHandler(): IMatterTaskProvider? { + return this } - @Override - public boolean isValidMatterCell() { - return valid; + private val tasks = HashMap() + + override fun getTasks(): Collection { + return tasks.values.stream().filter { task: MatterTask? -> task!!.required() > 0 }.collect(Collectors.toList()) as Collection } - @Override - public void setMatterGrid(MatterGrid grid) { - this.grid = grid; + override fun getAllTasks(): Collection { + return List.copyOf(tasks.values) as Collection } - @Nullable - @Override - public IMatterTaskProvider getTaskProvider() { - return this; - } + override fun allocateTask(simulate: Boolean): MatterTaskAllocation? { + val graph = node.graph as MatterNetworkGraph? ?: return null - private final HashMap tasks = new HashMap<>(); + for ((key, task) in tasks) { + if (task!!.required > 0) { + val getPattern = graph.getPattern(task.pattern!!) - @Nonnull - @Override - public Collection getTasks() { - return tasks.values().stream().filter(task -> task.required() > 0).collect(Collectors.toList()); - } - - @Nonnull - @Override - public Collection getAllTasks() { - return List.copyOf(tasks.values()); - } - - @Nullable - @Override - public MatterTaskAllocation allocateTask(boolean simulate) { - if (grid == null) - return null; - - for (var entry : tasks.entrySet()) { - var task = entry.getValue(); - - if (task.required() > 0) { - var get_pattern = grid.getPattern(task.pattern()); - - if (get_pattern != null) { + if (getPattern != null) { if (!simulate) { - var newer = task.shrinkRequired(1); - tasks.put(entry.getKey(), newer); - listeners.forEach(menu -> menu.taskUpdated(newer)); - grid.onMatterTaskUpdated(newer, task); - setChanged(); + val new = task.shrinkRequired(1) + tasks[key] = new + listeners.forEach { menu: MatterPanelMenu -> menu.taskUpdated(new) } + graph.onMatterTaskUpdated(new, task) + setChanged() } - return new MatterTaskAllocation(task, get_pattern); + return MatterTaskAllocation(task, getPattern) } } } - return null; + return null } - @Override - public boolean notifyTaskCompletion(MatterTask task) { - var get_task = tasks.get(task.id()); + override fun notifyTaskCompletion(task: MatterTask): Boolean { + var localTask = tasks[task.id] ?: return false + val oldTask = localTask - if (get_task == null) { - return false; - } + localTask = localTask.shrinkInProgress(1) + val graph = node.graph as MatterNetworkGraph? - var old_task = get_task; - get_task = get_task.shrinkInProgress(1); - - if (get_task.required() <= 0 && get_task.in_progress() <= 0) { - tasks.remove(task.id()); - - if (grid != null) - grid.onMatterTaskCreated(task); - - MatterTask finalGet_task1 = get_task; - listeners.forEach(menu -> menu.taskRemoved(finalGet_task1)); + // Задача полностью выполнена + if (localTask.required <= 0 && localTask.in_progress <= 0) { + tasks.remove(task.id) + graph?.onMatterTaskCreated(task) + listeners.forEach { menu: MatterPanelMenu -> menu.taskRemoved(localTask) } } else { - tasks.put(task.id(), get_task); - - if (grid != null) { - grid.onMatterTaskUpdated(get_task, old_task); - } - - MatterTask finalGet_task = get_task; - listeners.forEach(menu -> menu.taskUpdated(finalGet_task)); + // Задача обновлена + tasks[task.id()] = localTask + graph?.onMatterTaskUpdated(localTask, oldTask) + listeners.forEach { menu: MatterPanelMenu -> menu.taskUpdated(localTask) } } - setChanged(); - - return true; + setChanged() + return true } - @Override - public void saveAdditional(CompoundTag nbt) { - super.saveAdditional(nbt); - ListTag list = new ListTag(); + override fun saveAdditional(nbt: CompoundTag) { + super.saveAdditional(nbt) - for (MatterTask task : tasks.values()) { - list.add(task.serializeNBT()); + val list = ListTag() + + for (task in tasks.values) { + list.add(task!!.serializeNBT()) } - nbt.put("tasks", list); + nbt.put("tasks", list) } - @Override - public void load(CompoundTag nbt) { - super.load(nbt); - tasks.clear(); + override fun load(nbt: CompoundTag) { + super.load(nbt) + tasks.clear() + val list = nbt.getList("tasks", Tag.TAG_COMPOUND.toInt()) - ListTag list = nbt.getList("tasks", Tag.TAG_COMPOUND); - - for (Tag tag : list) { - MatterTask task = MatterTask.deserializeNBT(tag); + for (tag in list) { + val task = MatterTask.deserializeNBT(tag) if (task != null) { - tasks.put(task.id(), task); + tasks[task.id()] = task } } } - @Nullable - @Override - public MatterTask getTask(UUID id) { - return tasks.get(id); + override fun getTask(id: UUID): MatterTask? { + return tasks[id] } - public void removeTask(UUID id) { - var task = tasks.get(id); + fun removeTask(id: UUID) { + val task = tasks[id] ?: return + tasks.remove(id) - if (task == null) - return; + (node.graph as MatterNetworkGraph?)?.onMatterTaskRemoved(task) - tasks.remove(id); - - if (grid != null) - grid.onMatterTaskRemoved(task); - - listeners.forEach(menu -> menu.taskRemoved(task)); - setChanged(); + listeners.forEach { menu: MatterPanelMenu -> menu.taskRemoved(task) } + setChanged() } - public void removeTask(PatternState state) { - removeTask(state.id()); + fun removeTask(state: PatternState) = removeTask(state.id) + + fun addTask(state: PatternState, how_much: Int): MatterTask { + val task = MatterTask(UUID.randomUUID(), state.id, state.item, 0, 0, how_much) + tasks[task.id()] = task + + (node.graph as MatterNetworkGraph?)?.onMatterTaskCreated(task) + + listeners.forEach { menu: MatterPanelMenu -> menu.taskUpdated(task) } + setChanged() + + return task } - public MatterTask addTask(PatternState state, int how_much) { - var task = new MatterTask(UUID.randomUUID(), state.id(), state.item(), 0, 0, how_much); - tasks.put(task.id(), task); + override fun dropAllTasks() { + val graph = node.graph as MatterNetworkGraph? - if (grid != null) - grid.onMatterTaskCreated(task); + for (task in tasks.values) { + graph?.onMatterTaskRemoved(task!!) + listeners.forEach { menu: MatterPanelMenu -> menu.taskUpdated(task!!) } + } - listeners.forEach(menu -> menu.taskUpdated(task)); - - setChanged(); - - return task; + tasks.clear() } - @Override - public void dropAllTasks() { - tasks.clear(); + companion object { + private val NAME = TranslatableComponent("block.overdrive_that_matters.matter_panel") } -} +} \ No newline at end of file diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/BlockEntityMatterReplicator.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/BlockEntityMatterReplicator.kt index 66350cc85..7752c0ca7 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/BlockEntityMatterReplicator.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/BlockEntityMatterReplicator.kt @@ -1,278 +1,236 @@ -package ru.dbotthepony.mc.otm.block.entity; +package ru.dbotthepony.mc.otm.block.entity -import net.minecraft.MethodsReturnNonnullByDefault; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.TranslatableComponent; -import net.minecraft.world.entity.player.Inventory; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.inventory.AbstractContainerMenu; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraftforge.common.capabilities.Capability; -import net.minecraftforge.common.util.LazyOptional; -import net.minecraftforge.items.CapabilityItemHandler; -import ru.dbotthepony.mc.otm.Registry; -import ru.dbotthepony.mc.otm.block.entity.worker.BlockEntityMatteryWorker; -import ru.dbotthepony.mc.otm.block.entity.worker.MachineJob; -import ru.dbotthepony.mc.otm.block.entity.worker.MachineJobStatus; -import ru.dbotthepony.mc.otm.block.entity.worker.WorkTickContext; -import ru.dbotthepony.mc.otm.capability.*; -import ru.dbotthepony.mc.otm.capability.matter.*; -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.matter.MatterGrid; -import ru.dbotthepony.mc.otm.matter.MatterRegistry; -import ru.dbotthepony.mc.otm.menu.MatterReplicatorMenu; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import javax.annotation.ParametersAreNonnullByDefault; -import java.math.BigDecimal; +import net.minecraft.MethodsReturnNonnullByDefault +import javax.annotation.ParametersAreNonnullByDefault +import net.minecraft.core.BlockPos +import net.minecraft.core.Direction +import net.minecraft.world.level.block.state.BlockState +import ru.dbotthepony.mc.otm.block.entity.worker.BlockEntityMatteryWorker +import ru.dbotthepony.mc.otm.capability.matter.MatterHandlerCapability +import ru.dbotthepony.mc.otm.capability.matter.IMatterHandler +import ru.dbotthepony.mc.otm.container.MatteryContainer +import net.minecraft.world.item.ItemStack +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.MatterReplicatorMenu +import ru.dbotthepony.mc.otm.block.entity.worker.MachineJob +import ru.dbotthepony.mc.otm.block.entity.worker.MachineJobStatus +import ru.dbotthepony.mc.otm.capability.matter.MatterTask +import ru.dbotthepony.mc.otm.capability.matter.PatternState +import ru.dbotthepony.mc.otm.matter.MatterRegistry +import ru.dbotthepony.mc.otm.block.entity.worker.WorkTickContext +import net.minecraft.nbt.CompoundTag +import net.minecraft.network.chat.Component +import net.minecraftforge.common.util.LazyOptional +import ru.dbotthepony.mc.otm.capability.MatteryCapability +import net.minecraftforge.items.CapabilityItemHandler +import ru.dbotthepony.mc.otm.capability.MatteryMachineEnergyStorage +import net.minecraft.network.chat.TranslatableComponent +import net.minecraft.server.level.ServerLevel +import net.minecraft.world.level.Level +import net.minecraftforge.common.capabilities.Capability +import ru.dbotthepony.mc.otm.Registry +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.set @MethodsReturnNonnullByDefault @ParametersAreNonnullByDefault -public class BlockEntityMatterReplicator extends BlockEntityMatteryWorker implements IMatterGridCell { - public BlockEntityMatterReplicator(BlockPos p_155229_, BlockState p_155230_) { - super(Registry.BlockEntities.MATTER_REPLICATOR, p_155229_, p_155230_); - energy = new MatteryMachineEnergyStorage(this, MatteryMachineEnergyStorage.MachineType.WORKER, new Fraction(200_000), new Fraction(4000), new Fraction(4000)); +class BlockEntityMatterReplicator(p_155229_: BlockPos, p_155230_: BlockState) : + BlockEntityMatteryWorker(Registry.BlockEntities.MATTER_REPLICATOR, p_155229_, p_155230_), IMatterGraphNode { + + private val node = Graph6Node(this) + private val resolverNode = LazyOptional.of { this } + + override fun getAsMatterNode(): Graph6Node { + return node } - public final MatterHandlerCapability matter = new MatterHandlerCapability(this::setChanged, IMatterHandler.MatterDirection.RECEIVE, new Fraction(2)); + @JvmField + val matter = MatterHandlerCapability(this::setChangedLight, IMatterHandler.MatterDirection.RECEIVE, Fraction(2)) // обычные запросы - public final MatteryContainer regular_slots = new MatteryContainer(this::setChanged, 3); + @JvmField + val regularSlots = MatteryContainer(this::setChangedLight, 3) - // запросы от matter replicator interface - public final MatteryContainer reserved_slots = new MatteryContainer(this::setChanged, 3); + // запросы от matter replicator interface? + val reservedSlots = MatteryContainer(this::setChangedLight, 3) - private final MatteryContainerHandler slots_handler = regular_slots.handler((slot, stack) -> false); + private val itemHandler = regularSlots.handler { slot: Int, stack: ItemStack? -> false } - private static final TranslatableComponent NAME = new TranslatableComponent("block.overdrive_that_matters.matter_replicator"); - - private static final Fraction BASE_CONSUMPTION = new Fraction(400); - - @Override - protected Component getDefaultDisplayName() { - return NAME; + override fun getDefaultDisplayName(): Component { + return NAME } - @Nullable - @Override - public AbstractContainerMenu createMenu(int containerID, Inventory inventory, Player ply) { - return new MatterReplicatorMenu(containerID, inventory, this); + override fun createMenu(containerID: Int, inventory: Inventory, ply: Player): AbstractContainerMenu { + return MatterReplicatorMenu(containerID, inventory, this) } - @Nonnull - @Override - protected Fraction getBaseConsumption() { - return BASE_CONSUMPTION; + override fun getBaseConsumption(): Fraction { + return BASE_CONSUMPTION } - @Nonnull - @Override - protected MachineJobStatus onJobFinish(MachineJob job) { - if (!regular_slots.fullyAddItem(job.stack())) { - return new MachineJobStatus(false, 20); + override fun onJobFinish(job: MachineJob): MachineJobStatus { + if (!regularSlots.fullyAddItem(job.stack())) { + return MachineJobStatus(false, 20) } - if (grid != null) { - grid.notifyTaskCompletion(MatterTask.deserializeNBT(job.data().get("task"))); - } - - return new MachineJobStatus(); + (node.graph as MatterNetworkGraph?)?.notifyTaskCompletion(MatterTask.deserializeNBT(job.data["task"])!!) + return MachineJobStatus() } - @Override - public void onMatterTaskCreated(MatterTask task) { - is_idling = false; + override fun onMatterTaskCreated(task: MatterTask) { + is_idling = false } - @Override - public void onMatterTaskUpdated(MatterTask new_state, MatterTask old_state) { - is_idling = false; + override fun onMatterTaskUpdated(new_state: MatterTask, old_state: MatterTask) { + is_idling = false } - @Override - public void onPatternAdded(PatternState state) { - is_idling = false; + override fun onPatternAdded(state: PatternState) { + is_idling = false } - @Override - public void setRemoved() { - super.setRemoved(); - - if (level != null && !level.isClientSide && grid != null) - grid.remove(this); + override fun setRemoved() { + super.setRemoved() + node.destroy(::MatterNetworkGraph) } - private static final double TICKS_PER_MTU = 20_000d; - private static final Fraction TICKS_PER_MTU_BD = new Fraction(20_000); - private static final double MTU_PER_TICK = 1d / 20_000d; - private static final Fraction MTU_PER_TICK_BD = Fraction.ONE.div(TICKS_PER_MTU_BD); + override fun setLevel(p_155231_: Level) { + super.setLevel(p_155231_) - @Override - public void setLevel(Level p_155231_) { - super.setLevel(p_155231_); - - if (grid == null) - scheduleDiscoverNeighbours(p_155231_, getBlockPos()); + if (p_155231_ is ServerLevel) + MatterNetworkGraph.discoverFull(this, node) } - @Nullable - @Override - protected MachineJob getNextJob() { - if (grid == null) - return null; - - MatterTaskAllocation allocation = grid.allocateTask(false); - - if (allocation == null) - return null; - - ItemStack stack = allocation.task().stack(1); + override fun getNextJob(): MachineJob? { + val graph = node.graph as MatterNetworkGraph? ?: return null + val allocation = graph.allocateTask(false) ?: return null + val stack = allocation.task().stack(1) // ???????? - if (!MatterRegistry.hasMatterValue(stack)) - return null; + if (!MatterRegistry.hasMatterValue(stack)) return null + val job = MachineJob(stack, MatterRegistry.getMatterValue(stack).toDouble() * TICKS_PER_MTU) - MachineJob job = new MachineJob(stack, MatterRegistry.getMatterValue(stack).toDouble() * TICKS_PER_MTU); + job.data["task"] = allocation.task.serializeNBT() + if (allocation.pattern != null) job.data["pattern"] = allocation.pattern!!.serializeNBT() - job.data().put("task", allocation.task().serializeNBT()); - - if (allocation.pattern() != null) - job.data().put("pattern", allocation.pattern().serializeNBT()); - - return job; + return job } - private static final Fraction DRAIN_MULT = new Fraction(200); + override fun onWorkTick(context: WorkTickContext): MachineJobStatus { + val drainPerTick = MTU_PER_TICK_BD.times(context.work_speed()) + val graph = node.graph as MatterNetworkGraph? ?: return MachineJobStatus(false, 20) - @Override - protected MachineJobStatus onWorkTick(WorkTickContext context) { - var drain_per_tick = MTU_PER_TICK_BD.times(context.work_speed()); - - if (matter.extractMatterInner(drain_per_tick, true).compareTo(drain_per_tick) < 0) { + if (matter.extractMatterInner(drainPerTick, true) < drainPerTick) { // в машине недостаточно материи - if (grid == null) - return new MachineJobStatus(false, 20); - if (drain_per_tick.compareTo(matter.getMaxStoredMatter()) > 0) { + if (drainPerTick > matter.maxStoredMatter) { // в тик требуется больше материи, чем её может хранить репликатор - var to_extract = drain_per_tick.minus(matter.extractMatterInner(drain_per_tick, true)); - var drain = grid.extractMatter(to_extract, true); + val toExtract = drainPerTick - matter.extractMatterInner(drainPerTick, true) + val drain = graph.extractMatter(toExtract, true) - if (drain.compareTo(to_extract) < 0) { + if (drain < toExtract) { // недостаточно материи в сети - return new MachineJobStatus(false, 200); + return MachineJobStatus(false, 200) } // достаточно материи в сети + внутри машины - matter.extractMatterInner(drain_per_tick, false); - grid.extractMatter(drain, false); - - return new MachineJobStatus(); + matter.extractMatterInner(drainPerTick, false) + graph.extractMatter(drain, false) + return MachineJobStatus() } else { // в тик требуется меньше материи, чем её может хранить репликатор // примем из сети недостающее количество бака материи, или 200 тиков репликации, что меньше - var to_extract = matter.getMissingMatter().min(drain_per_tick.times(DRAIN_MULT)); - var drain = grid.extractMatter(to_extract, true); + val toExtract = + matter.missingMatter.min(drainPerTick.times(DRAIN_MULT)) - if (drain.compareTo(Fraction.ZERO) == 0) { + val drain = graph.extractMatter(toExtract, true) + + if (drain.isZero()) { // в сети нет материи - return new MachineJobStatus(false, 200); + return MachineJobStatus(false, 200) } - var received = matter.receiveMatterOuter(drain, false); - grid.extractMatter(received, false); + val received = matter.receiveMatterOuter(drain, false) + graph.extractMatter(received, false) // получили материю, проверяем возможность работы - if (matter.extractMatterInner(drain_per_tick, false).compareTo(drain_per_tick) >= 0) { - return new MachineJobStatus(); + if (matter.extractMatterInner(drainPerTick, false) >= drainPerTick) { + return MachineJobStatus() } else { // :( - return new MachineJobStatus(false, 200); + return MachineJobStatus(false, 200) } } } // в машине достаточно материи - - matter.extractMatterInner(drain_per_tick, false); - return new MachineJobStatus(); + matter.extractMatterInner(drainPerTick, false) + return MachineJobStatus() } - @Override - public void saveAdditional(CompoundTag nbt) { - super.saveAdditional(nbt); - nbt.put("regular_slots", regular_slots.serializeNBT()); - nbt.put("reserved_slots", reserved_slots.serializeNBT()); - nbt.put("matter_capability", matter.serializeNBT()); + override fun saveAdditional(nbt: CompoundTag) { + super.saveAdditional(nbt) + nbt["regular_slots"] = regularSlots.serializeNBT() + nbt["reserved_slots"] = reservedSlots.serializeNBT() + nbt["matter_capability"] = matter.serializeNBT() } - @Override - public void load(CompoundTag nbt) { - super.load(nbt); - regular_slots.deserializeNBT(nbt.get("regular_slots")); - reserved_slots.deserializeNBT(nbt.get("reserved_slots")); + override fun load(nbt: CompoundTag) { + super.load(nbt) + regularSlots.deserializeNBT(nbt["regular_slots"]) + reservedSlots.deserializeNBT(nbt["reserved_slots"]) - if (nbt.get("matter_capability") instanceof CompoundTag tag) - matter.deserializeNBT(tag); + nbt.ifHas("matter_capability", CompoundTag::class.java) { + matter.deserializeNBT(it) + } } - private boolean valid = true; + private var valid = true - @Override - public void invalidateCaps() { - super.invalidateCaps(); - valid = false; - slots_handler.invalidate(); - resolver_self.invalidate(); + override fun invalidateCaps() { + super.invalidateCaps() + valid = false + itemHandler.invalidate() } - @Override - public void reviveCaps() { - super.reviveCaps(); - valid = true; - slots_handler.revive(); - resolver_self = LazyOptional.of(() -> this); + override fun reviveCaps() { + super.reviveCaps() + valid = true + itemHandler.revive() } - private LazyOptional resolver_self = LazyOptional.of(() -> this); - - @Nonnull - @Override - public LazyOptional getCapability(@Nonnull Capability cap, @Nullable Direction side) { + override fun getCapability(cap: Capability, side: Direction?): LazyOptional { if (valid) { - if (cap == MatteryCapability.MATTER_CELL) - return resolver_self.cast(); - - if (cap == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) - return slots_handler.get().cast(); + if (cap === MatteryCapability.MATTER_CELL) return resolverNode.cast() + if (cap === CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) return itemHandler.get().cast() } - return super.getCapability(cap, side); + return super.getCapability(cap, side) } - private MatterGrid grid; - - @Nullable - @Override - public MatterGrid getMatterGrid() { - return grid; + init { + energy = MatteryMachineEnergyStorage( + this, + MatteryMachineEnergyStorage.MachineType.WORKER, + Fraction(200000), + Fraction(4000), + Fraction(4000) + ) } - @Override - public boolean isValidMatterCell() { - return valid; + companion object { + private val NAME = TranslatableComponent("block.overdrive_that_matters.matter_replicator") + private val BASE_CONSUMPTION = Fraction(400) + private const val TICKS_PER_MTU = 20000.0 + private val TICKS_PER_MTU_BD = Fraction(20000) + private const val MTU_PER_TICK = 1.0 / 20000.0 + private val MTU_PER_TICK_BD = Fraction.ONE.div(TICKS_PER_MTU_BD) + private val DRAIN_MULT = Fraction(200) } - - @Override - public void setMatterGrid(MatterGrid grid) { - this.grid = grid; - } -} +} \ No newline at end of file diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/BlockEntityMatterScanner.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/BlockEntityMatterScanner.kt index 8316a8cb2..300c6702f 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/BlockEntityMatterScanner.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/BlockEntityMatterScanner.kt @@ -1,267 +1,208 @@ -package ru.dbotthepony.mc.otm.block.entity; +package ru.dbotthepony.mc.otm.block.entity -import net.minecraft.MethodsReturnNonnullByDefault; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.TranslatableComponent; -import net.minecraft.world.entity.player.Inventory; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.inventory.AbstractContainerMenu; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.entity.BlockEntity; -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.block.entity.worker.BlockEntityMatteryWorker; -import ru.dbotthepony.mc.otm.block.entity.worker.MachineJob; -import ru.dbotthepony.mc.otm.block.entity.worker.MachineJobStatus; -import ru.dbotthepony.mc.otm.capability.*; -import ru.dbotthepony.mc.otm.capability.matter.*; -import ru.dbotthepony.mc.otm.container.MatteryContainerHandler; -import ru.dbotthepony.mc.otm.core.Fraction; -import ru.dbotthepony.mc.otm.matter.MatterGrid; -import ru.dbotthepony.mc.otm.matter.MatterRegistry; -import ru.dbotthepony.mc.otm.Registry; -import ru.dbotthepony.mc.otm.container.MatteryContainer; -import ru.dbotthepony.mc.otm.menu.MatterScannerMenu; +import net.minecraft.core.BlockPos +import net.minecraft.core.Direction +import net.minecraft.nbt.CompoundTag +import net.minecraft.network.chat.Component +import net.minecraft.network.chat.TranslatableComponent +import net.minecraft.server.level.ServerLevel +import net.minecraft.world.entity.player.Inventory +import net.minecraft.world.entity.player.Player +import net.minecraft.world.inventory.AbstractContainerMenu +import net.minecraft.world.item.ItemStack +import net.minecraft.world.level.Level +import net.minecraft.world.level.block.state.BlockState +import net.minecraftforge.common.capabilities.Capability +import net.minecraftforge.common.util.LazyOptional +import net.minecraftforge.items.CapabilityItemHandler +import ru.dbotthepony.mc.otm.Registry +import ru.dbotthepony.mc.otm.block.entity.worker.BlockEntityMatteryWorker +import ru.dbotthepony.mc.otm.block.entity.worker.MachineJob +import ru.dbotthepony.mc.otm.block.entity.worker.MachineJobStatus +import ru.dbotthepony.mc.otm.capability.MatteryCapability +import ru.dbotthepony.mc.otm.capability.MatteryMachineEnergyStorage +import ru.dbotthepony.mc.otm.capability.matter.* +import ru.dbotthepony.mc.otm.container.MatteryContainer +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.matter.MatterRegistry +import ru.dbotthepony.mc.otm.menu.MatterScannerMenu +import java.util.* -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import javax.annotation.ParametersAreNonnullByDefault; -import java.math.BigDecimal; -import java.util.Collection; -import java.util.UUID; +class BlockEntityMatterScanner(p_155229_: BlockPos, p_155230_: BlockState) : + BlockEntityMatteryWorker(Registry.BlockEntities.MATTER_SCANNER, p_155229_, p_155230_), IMatterGraphNode { -@MethodsReturnNonnullByDefault -@ParametersAreNonnullByDefault -public class BlockEntityMatterScanner extends BlockEntityMatteryWorker implements IMatterGridCell { - private static final TranslatableComponent NAME = new TranslatableComponent("block.overdrive_that_matters.matter_scanner"); + val input_slot = MatteryContainer(this::setChanged, 1) - public final MatteryContainer input_slot = new MatteryContainer(this::setChanged, 1); + private val inputHandler = input_slot.handler( + { slot: Int, stack: ItemStack? -> MatterRegistry.canDecompose(stack) }, + { slot: Int, amount: Int, stack: ItemStack? -> is_idling } + ) - private final MatteryContainerHandler input_handler = input_slot.handler( - (slot, stack) -> MatterRegistry.canDecompose(stack), - (slot, amount, stack) -> is_idling - ); - - public BlockEntityMatterScanner(BlockPos p_155229_, BlockState p_155230_) { - super(Registry.BlockEntities.MATTER_SCANNER, p_155229_, p_155230_); - energy = new MatteryMachineEnergyStorage(this, MatteryMachineEnergyStorage.MachineType.WORKER, new Fraction(40000), new Fraction(400), new Fraction(400)); + // IMatterGraphNode + override fun getAsMatterNode(): Graph6Node { + return matterNode } - private boolean valid = true; + override fun onPatternAdded(state: PatternState) { + is_idling = false + } - private LazyOptional resolver_grid = LazyOptional.of(() -> this); + override fun onPatternRemoved(state: PatternState) { + is_idling = false + } - @Nonnull - @Override - public LazyOptional getCapability(@Nonnull Capability cap, @Nullable Direction side) { + override fun onPatternUpdated(new_state: PatternState, old_state: PatternState) { + is_idling = false + } + // /IMatterGraphNode + + private var valid = true + private val matterNode: Graph6Node = Graph6Node(this) + private var resolverNode = LazyOptional.of { this } + + override fun getCapability(cap: Capability, side: Direction?): LazyOptional { if (valid) { - if (cap == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) - return input_handler.get().cast(); - - if (cap == MatteryCapability.MATTER_CELL) - return resolver_grid.cast(); + if (cap === CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) return inputHandler.get().cast() + //if (cap === MatteryCapability.MATTER_CELL) return resolver_grid.cast() + if (cap == MatteryCapability.MATTER_CELL) return resolverNode.cast() } - return super.getCapability(cap, side); + return super.getCapability(cap, side) } - @Override - public void invalidateCaps() { - super.invalidateCaps(); - valid = false; - input_handler.invalidate(); - resolver_grid.invalidate(); + override fun invalidateCaps() { + super.invalidateCaps() + valid = false + inputHandler.invalidate() + resolverNode.invalidate() + matterNode.destroy(::MatterNetworkGraph) } - @Override - public void reviveCaps() { - super.reviveCaps(); - valid = true; - input_handler.revive(); - resolver_grid = LazyOptional.of(() -> this); + override fun reviveCaps() { + super.reviveCaps() + valid = true + inputHandler.revive() + resolverNode = LazyOptional.of { this } } - @Override - public void onPatternAdded(PatternState state) { - is_idling = false; + override fun setRemoved() { + super.setRemoved() + matterNode.destroy(::MatterNetworkGraph) } - @Override - public void onPatternRemoved(PatternState state) { - is_idling = false; + override fun getDefaultDisplayName(): Component { + return NAME } - @Override - public void onPatternUpdated(PatternState new_state, PatternState old_state) { - is_idling = false; + override fun createMenu(containerID: Int, inventory: Inventory, ply: Player): AbstractContainerMenu? { + return MatterScannerMenu(containerID, inventory, this) } - @Override - public void setRemoved() { - super.setRemoved(); - - if (level != null && !level.isClientSide && grid != null) - grid.remove(this); + override fun saveAdditional(nbt: CompoundTag) { + super.saveAdditional(nbt) + nbt.put("work_slots", input_slot.serializeNBT()) } - @Override - public void onNeighbourMatterCell(Level level, BlockPos pos, Direction direction, IMatterGridCell cell, BlockEntity entity) { - is_idling = false; + override fun load(nbt: CompoundTag) { + input_slot.deserializeNBT(nbt["work_slots"]) + super.load(nbt) } - @Override - protected Component getDefaultDisplayName() { - return NAME; + override fun getBaseConsumption(): Fraction { + return BASE_CONSUMPTION } - @Nullable - @Override - public AbstractContainerMenu createMenu(int containerID, Inventory inventory, Player ply) { - return new MatterScannerMenu(containerID, inventory, this); - } + override fun onJobFinish(job: MachineJob): MachineJobStatus { + val grid = matterNode.graph as MatterNetworkGraph? ?: return MachineJobStatus(false, 100) - @Override - public void saveAdditional(CompoundTag nbt) { - super.saveAdditional(nbt); - nbt.put("work_slots", input_slot.serializeNBT()); - } + val stack = job.stack() + if (stack.isEmpty || !MatterRegistry.hasMatterValue(stack)) return MachineJobStatus() - @Override - public void load(CompoundTag nbt) { - input_slot.deserializeNBT(nbt.get("work_slots")); - super.load(nbt); - } + val get_state = grid.findPatterns(stack.item) + var find_state: PatternState? = null - private static final Fraction BASE_CONSUMPTION = new Fraction("40"); - - @Override - @Nonnull - protected Fraction getBaseConsumption() { - return BASE_CONSUMPTION; - } - - @Nonnull - @Override - protected MachineJobStatus onJobFinish(MachineJob job) { - if (grid == null) - return new MachineJobStatus(false, 100); - - ItemStack stack = job.stack(); - - if (stack.isEmpty() || !MatterRegistry.hasMatterValue(stack)) - return new MachineJobStatus(); - - - Collection get_state = grid.findPatterns(stack.getItem()); - PatternState find_state = null; - - for (PatternState state : get_state) { - if (state.item() == stack.getItem()) { - if (find_state == null && state.research_percent() < 1d) { - find_state = state; + for (state in get_state) { + if (state.item() === stack.item) { + if (find_state == null && state.research_percent() < 1.0) { + find_state = state } else if (find_state != null && find_state.research_percent() < state.research_percent()) { - find_state = state; + find_state = state } } } - PatternState new_state; + val new_state = + if (find_state != null) { + PatternState(find_state.id(), stack.item, find_state.research_percent() + 0.2) + } else { + PatternState(UUID.randomUUID(), stack.item, 0.2) + } - if (find_state != null) { - new_state = new PatternState(find_state.id(), stack.getItem(), find_state.research_percent() + 0.2d); + if (grid.insertPattern(new_state, false, false).status != PatternInsertStatus.Status.FAIL) { + return MachineJobStatus() } else { - new_state = new PatternState(UUID.randomUUID(), stack.getItem(), 0.2d); + return MachineJobStatus(false, 200) } - - if (grid.insertPattern(new_state, false, false).status() != PatternInsertStatus.Status.FAIL) { - return new MachineJobStatus(); - } - - return new MachineJobStatus(false, 200); } - @Nullable - @Override - protected MachineJob getNextJob() { - if (grid == null) - return null; + override fun getNextJob(): MachineJob? { + val grid = matterNode.graph as MatterNetworkGraph? ?: return null - ItemStack stack = input_slot.getItem(0); + val stack = input_slot.getItem(0) + if (stack.isEmpty || !MatterRegistry.canDecompose(stack)) return null - if (stack.isEmpty() || !MatterRegistry.canDecompose(stack)) - return null; + val getState = grid.findPatterns(stack.item) + var findState: PatternState? = null - Collection get_state = grid.findPatterns(stack.getItem()); - PatternState find_state = null; - - for (PatternState state : get_state) { - if (state.item() == stack.getItem() && state.research_percent() < 1d) { - find_state = state; - } else if (state.item() == stack.getItem() && state.research_percent() >= 1d) { - return null; + for (state in getState) { + if (state.item() === stack.item && state.research_percent() < 1.0) { + findState = state + } else if (state.item() === stack.item && state.research_percent() >= 1.0) { + return null } } - PatternState new_state; + val new_state: PatternState = + if (findState != null) { + PatternState(findState.id, stack.item, findState.research_percent + 0.2) + } else { + PatternState(UUID.randomUUID(), stack.item, 0.2) + } - if (find_state != null) { - new_state = new PatternState(find_state.id(), stack.getItem(), find_state.research_percent() + 0.2d); - } else { - new_state = new PatternState(UUID.randomUUID(), stack.getItem(), 0.2d); + if (grid.insertPattern(new_state, false, true).status != PatternInsertStatus.Status.FAIL) { + val copy = stack.copy() + copy.count = 1 + stack.shrink(1) + input_slot.setChanged() + return MachineJob(copy, MatterRegistry.getMatterValue(copy).toDouble() * 35000.0) } - if (grid.insertPattern(new_state, false, true).status() != PatternInsertStatus.Status.FAIL) { - ItemStack copy = stack.copy(); - copy.setCount(1); - stack.shrink(1); - input_slot.setChanged(); - return new MachineJob(copy, MatterRegistry.getMatterValue(copy).toDouble() * 35_000d); + return null + } + + init { + energy = MatteryMachineEnergyStorage( + this, + MatteryMachineEnergyStorage.MachineType.WORKER, + Fraction(40000), + Fraction(400), + Fraction(400) + ) + } + + override fun setLevel(p_155231_: Level) { + super.setLevel(p_155231_) + + if (p_155231_ is ServerLevel) { + MatterNetworkGraph.discoverFull(this, matterNode) } - - return null; } - @Nullable - @Override - public IPatternStorage getPatternStorage() { - return null; + companion object { + private val NAME = TranslatableComponent("block.overdrive_that_matters.matter_scanner") + private val BASE_CONSUMPTION = Fraction("40") } - - private MatterGrid grid; - - @Override - public void setLevel(Level p_155231_) { - super.setLevel(p_155231_); - - if (grid == null) - scheduleDiscoverNeighbours(p_155231_, getBlockPos()); - } - - @Nullable - @Override - public MatterGrid getMatterGrid() { - return grid; - } - - @Nullable - @Override - public IMatterHandler getMatterHandler() { - return null; - } - - @Override - public boolean isValidMatterCell() { - return valid; - } - - @Override - public void setMatterGrid(MatterGrid grid) { - this.grid = grid; - } -} +} \ No newline at end of file diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/BlockEntityPatternStorage.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/BlockEntityPatternStorage.kt index 7ca4d463c..79c1c31f4 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/BlockEntityPatternStorage.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/BlockEntityPatternStorage.kt @@ -1,243 +1,214 @@ -package ru.dbotthepony.mc.otm.block.entity; +package ru.dbotthepony.mc.otm.block.entity -import com.google.common.collect.ImmutableList; -import net.minecraft.MethodsReturnNonnullByDefault; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.TranslatableComponent; -import net.minecraft.world.entity.player.Inventory; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.inventory.AbstractContainerMenu; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.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 net.minecraftforge.items.IItemHandler; -import ru.dbotthepony.mc.otm.block.BlockPatternStorage; -import ru.dbotthepony.mc.otm.capability.*; -import ru.dbotthepony.mc.otm.capability.matter.*; -import ru.dbotthepony.mc.otm.container.MatteryContainerHandler; -import ru.dbotthepony.mc.otm.matter.MatterGrid; -import ru.dbotthepony.mc.otm.Registry; -import ru.dbotthepony.mc.otm.container.MatteryContainer; -import ru.dbotthepony.mc.otm.menu.PatternStorageMenu; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import javax.annotation.ParametersAreNonnullByDefault; -import java.util.ArrayList; -import java.util.Collection; +import javax.annotation.ParametersAreNonnullByDefault +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 +import ru.dbotthepony.mc.otm.block.BlockPatternStorage +import net.minecraft.nbt.CompoundTag +import net.minecraftforge.common.util.LazyOptional +import net.minecraftforge.items.CapabilityItemHandler +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.PatternStorageMenu +import net.minecraft.MethodsReturnNonnullByDefault +import net.minecraft.core.Direction +import net.minecraft.network.chat.Component +import ru.dbotthepony.mc.otm.capability.matter.PatternInsertStatus +import net.minecraft.network.chat.TranslatableComponent +import net.minecraft.server.level.ServerLevel +import net.minecraft.world.level.Level +import net.minecraft.world.level.block.Block +import net.minecraftforge.common.capabilities.Capability +import ru.dbotthepony.mc.otm.Registry +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.set +import java.util.ArrayList @MethodsReturnNonnullByDefault @ParametersAreNonnullByDefault -public class BlockEntityPatternStorage extends BlockEntityMattery implements IMatterGridCell, IPatternStorage { - public BlockEntityPatternStorage(BlockPos p_155229_, BlockState p_155230_) { - super(Registry.BlockEntities.PATTERN_STORAGE, p_155229_, p_155230_); - } +class BlockEntityPatternStorage(p_155229_: BlockPos, p_155230_: BlockState) : + BlockEntityMattery(Registry.BlockEntities.PATTERN_STORAGE, p_155229_, p_155230_), IMatterGraphNode, IPatternStorage { + + private val node = Graph6Node(this) + private val resolverPatterns = LazyOptional.of { this } + 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 grid = node.graph as MatterNetworkGraph? - public final MatteryContainer patterns = new MatteryContainer(this::setChanged, 8) { - @Override - public void setChanged(int slot, ItemStack new_state, ItemStack old_state) { if (grid != null && !ItemStack.isSameItemSameTags(new_state, old_state)) { - if (!old_state.isEmpty()) { - old_state.getCapability(MatteryCapability.PATTERN).ifPresent(cap -> cap.getStoredPatterns().forEach(grid::onPatternRemoved)); + if (!old_state.isEmpty) { + old_state.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 -> cap.getStoredPatterns().forEach(grid::onPatternAdded)); + if (!new_state.isEmpty) { + new_state.getCapability(MatteryCapability.PATTERN).ifPresent { cap: IPatternStorage -> + cap.storedPatterns.forEach { state: PatternState? -> grid.onPatternAdded(state!!) } + } } - updateBlockstate(); + updateBlockstate() } - super.setChanged(slot, new_state, old_state); + super.setChanged(slot, new_state, old_state) } - @Override - public int getMaxStackSize() { - return 1; - } - }; - - private void updateBlockstate() { - if (level == null) - return; - - var state = getBlockState(); - - for (int i = 0; i < 8; i++) { - state = state.setValue(BlockPatternStorage.PATTERN_STORAGE_DISKS_PROPS[i], patterns.getItem(i).getCapability(MatteryCapability.PATTERN).isPresent()); - } - - if (state != getBlockState()) { - level.setBlock(getBlockPos(), state, Block.UPDATE_CLIENTS); + override fun getMaxStackSize(): Int { + return 1 } } - private final MatteryContainerHandler resolver_item = patterns.handler( - ((slot, stack) -> stack.getCapability(MatteryCapability.PATTERN).isPresent()) - ); + private fun updateBlockstate() { + val level = level ?: return - private MatterGrid grid; + var state = blockState - @Override - public void saveAdditional(CompoundTag nbt) { - super.saveAdditional(nbt); - nbt.put("patterns", patterns.serializeNBT()); + for (i in 0..7) { + state = state.setValue( + BlockPatternStorage.PATTERN_STORAGE_DISKS_PROPS[i], + patterns.getItem(i).getCapability(MatteryCapability.PATTERN).isPresent + ) + } + + if (state !== blockState) { + level.setBlock(blockPos, state, Block.UPDATE_CLIENTS) + } } - @Override - public void load(CompoundTag nbt) { - super.load(nbt); - patterns.deserializeNBT(nbt.get("patterns")); + private val resolverItem = + patterns.handler { slot: Int, stack: ItemStack -> stack.getCapability(MatteryCapability.PATTERN).isPresent } + + override fun saveAdditional(nbt: CompoundTag) { + super.saveAdditional(nbt) + nbt["patterns"] = patterns.serializeNBT() } - @Override - public void setLevel(Level p_155231_) { - super.setLevel(p_155231_); + override fun load(nbt: CompoundTag) { + super.load(nbt) - if (grid == null) - MatterGrid.scheduleDiscoverNeighbours(this, getBlockPos(), p_155231_); + nbt.ifHas("patterns") { + patterns.deserializeNBT(it) + } } - @Nullable - @Override - public MatterGrid getMatterGrid() { - return grid; + override fun setLevel(p_155231_: Level) { + super.setLevel(p_155231_) + + if (p_155231_ is ServerLevel) + MatterNetworkGraph.discoverFull(this, node) } - @Nullable - @Override - public IMatterHandler getMatterHandler() { - return null; + override fun getAsMatterNode(): Graph6Node { + return node } - @Nullable - @Override - public IPatternStorage getPatternStorage() { - return valid ? this : null; + override fun getPatternHandler(): IPatternStorage { + return this } - private boolean valid = true; + private var valid = true - @Override - public boolean isValidMatterCell() { - return valid; + override fun invalidateCaps() { + super.invalidateCaps() + valid = false + resolverItem.invalidate() + node.destroy(::MatterNetworkGraph) } - @Override - public void setMatterGrid(MatterGrid grid) { - this.grid = grid; + override fun reviveCaps() { + super.reviveCaps() + valid = true + resolverItem.revive() } - @Override - public void invalidateCaps() { - super.invalidateCaps(); - valid = false; - resolver_item.invalidate(); - } - - @Override - public void reviveCaps() { - super.reviveCaps(); - valid = true; - resolver_item.revive(); - } - - private final LazyOptional resolver = LazyOptional.of(() -> this); - - @Nonnull - @Override - public LazyOptional getCapability(@Nonnull Capability cap, @Nullable Direction side) { + override fun getCapability(cap: Capability, side: Direction?): LazyOptional { if (valid) { - if (cap == MatteryCapability.PATTERN || cap == MatteryCapability.MATTER_CELL) - return resolver.cast(); - - if (cap == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) - return resolver_item.get().cast(); + if (cap === MatteryCapability.PATTERN) return resolverPatterns.cast() + if (cap === MatteryCapability.MATTER_CELL) return resolverNode.cast() + if (cap === CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) return resolverItem.get().cast() } - return super.getCapability(cap, side); + return super.getCapability(cap, side) } - private static final TranslatableComponent NAME = new TranslatableComponent("block.overdrive_that_matters.pattern_storage"); - - @Override - protected Component getDefaultDisplayName() { - return NAME; + override fun getDefaultDisplayName(): Component { + return NAME } - @Nullable - @Override - public AbstractContainerMenu createMenu(int containerID, Inventory inventory, Player ply) { - return new PatternStorageMenu(containerID, inventory, this); + override fun createMenu(containerID: Int, inventory: Inventory, ply: Player): AbstractContainerMenu { + return PatternStorageMenu(containerID, inventory, this) } - @Nonnull - @Override - public Collection getStoredPatterns() { - ArrayList list = new ArrayList<>(); - patterns.consumeCapability(MatteryCapability.PATTERN, capability -> list.addAll(capability.getStoredPatterns())); - return ImmutableList.copyOf(list); + override fun getStoredPatterns(): Collection { + val list = ArrayList() + patterns.consumeCapability(MatteryCapability.PATTERN) { capability: IPatternStorage -> list.addAll(capability.storedPatterns) } + return list } - @Override - public int getCapacity() { - long stored = 0; + override fun getCapacity(): Int { + var stored = 0L - for (var pattern : patterns.capabilityIterator(MatteryCapability.PATTERN)) { - stored += pattern.getCapacity(); - } + for (pattern in patterns.capabilityIterator(MatteryCapability.PATTERN)) + stored += pattern.capacity.toLong() - return stored > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int) stored; + return if (stored > Int.MAX_VALUE) Int.MAX_VALUE else stored.toInt() } - @Override - public int getStored() { - long stored = 0; + override fun getStored(): Int { + var stored = 0L - for (var pattern : patterns.capabilityIterator(MatteryCapability.PATTERN)) { - stored += pattern.getStored(); - } + for (pattern in patterns.capabilityIterator(MatteryCapability.PATTERN)) + stored += pattern.stored.toLong() - return stored > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int) stored; + return if (stored > Int.MAX_VALUE) Int.MAX_VALUE else stored.toInt() } - @Override - public void setRemoved() { - super.setRemoved(); - - if (level != null && !level.isClientSide && grid != null) - grid.remove(this); + override fun setRemoved() { + super.setRemoved() + node.destroy(::MatterNetworkGraph) } - @Override - public PatternInsertStatus insertPattern(PatternState pattern, boolean only_update, boolean simulate) { - for (IPatternStorage storage : patterns.capabilityIterator(MatteryCapability.PATTERN)) { - var status = storage.insertPattern(pattern, only_update, simulate); + override fun insertPattern(pattern: PatternState, only_update: Boolean, simulate: Boolean): PatternInsertStatus { + for (storage in patterns.capabilityIterator(MatteryCapability.PATTERN)) { + val status = storage.insertPattern(pattern, only_update, simulate) if (status.status() != PatternInsertStatus.Status.FAIL) { if (!simulate) { - setChanged(); + setChanged() - if (grid != null) { + val graph = node.graph as MatterNetworkGraph? + + if (graph != null) { if (status.status() == PatternInsertStatus.Status.INSERTED) { - grid.onPatternAdded(status.new_state()); + graph.onPatternAdded(status.new_state()!!) } else { - grid.onPatternUpdated(status.new_state(), status.old_state()); + graph.onPatternUpdated(status.new_state()!!, status.old_state()!!) } } } - return status; + return status } } - return new PatternInsertStatus(); + return PatternInsertStatus() } -} + + companion object { + private val NAME = TranslatableComponent("block.overdrive_that_matters.pattern_storage") + } +} \ No newline at end of file diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/BatteryBankScreen.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/BatteryBankScreen.kt index 57230f777..c2e0c1926 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/BatteryBankScreen.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/BatteryBankScreen.kt @@ -24,4 +24,4 @@ class BatteryBankScreen(menu: BatteryBankMenu, p_97742_: Inventory, p_97743_: Co return frame } -} \ No newline at end of file +} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/MatterBottlerScreen.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/MatterBottlerScreen.kt index 7a1b3a40f..c61e7a8c4 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/MatterBottlerScreen.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/screen/MatterBottlerScreen.kt @@ -1,33 +1,48 @@ -package ru.dbotthepony.mc.otm.client.screen; +package ru.dbotthepony.mc.otm.client.screen -import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.TranslatableComponent; -import net.minecraft.world.entity.player.Inventory; -import ru.dbotthepony.mc.otm.client.screen.panels.*; -import ru.dbotthepony.mc.otm.client.screen.widget.MatterGaugePanel; -import ru.dbotthepony.mc.otm.client.screen.widget.PowerGaugePanel; -import ru.dbotthepony.mc.otm.client.screen.widget.ProgressGaugePanel; -import ru.dbotthepony.mc.otm.menu.MatterBottlerMenu; -import ru.dbotthepony.mc.otm.menu.slot.MatterySlot; +import net.minecraft.network.chat.Component +import net.minecraft.network.chat.TranslatableComponent +import net.minecraft.world.entity.player.Inventory +import ru.dbotthepony.mc.otm.client.screen.panels.ButtonPanel +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.MatterGaugePanel +import ru.dbotthepony.mc.otm.client.screen.widget.PowerGaugePanel +import ru.dbotthepony.mc.otm.client.screen.widget.ProgressGaugePanel +import ru.dbotthepony.mc.otm.menu.MatterBottlerMenu -import javax.annotation.Nullable; -import java.util.List; +class MatterBottlerScreen(menu: MatterBottlerMenu, inventory: Inventory, title: Component) : + MatteryScreen(menu, inventory, title) { -public class MatterBottlerScreen extends MatteryScreen { - public MatterBottlerScreen(MatterBottlerMenu menu, Inventory inventory, Component title) { - super(menu, inventory, title); + private var progress: ProgressGaugePanel? = null + + override fun makeMainFrame(): FramePanel { + val frame = super.makeMainFrame()!! + + val p = PowerGaugePanel(this, frame, menu.battery_widget, LEFT_MARGIN, GAUGE_TOP_WITH_SLOT) + MatterGaugePanel(this, frame, menu.matterWidget, LEFT_MARGIN + p.width, GAUGE_TOP_WITH_SLOT) + + SlotPanel(this, frame, menu.battery_slot, LEFT_MARGIN, SLOT_TOP_UNDER_GAUGE) + + for (i in 0 .. 2) { + SlotPanel(this, frame, menu.container[i], 31f + i * 18, PROGRESS_SLOT_TOP) + } + + for (i in 3 .. 5) { + SlotPanel(this, frame, menu.container[i], 116f + (i - 3) * 18, PROGRESS_SLOT_TOP) + } + + progress = ProgressGaugePanel(this, frame, menu.progressWidget, 90f, PROGRESS_ARROW_TOP) + + val mode = ButtonPanel(this, frame, 46f, 69f, 100f, 20f, TranslatableComponent("otm.matter_bottler.switch_mode")) + mode.bindOnPress { menu.switchBottlerMode() } + + return frame } - @Nullable - @Override - protected FramePanel makeMainFrame() { - var frame = super.makeMainFrame(); + override fun containerTick() { + super.containerTick() - var mode = new ButtonPanel(this, frame, 0, 0, 100, 20, new TranslatableComponent("otm.matter_bottler.switch_mode")); - mode.bindOnPress(menu::switchBottlerMode); - mode.setDock(Dock.TOP); - mode.asGrid(); // for auto alignment on center - - return frame; + progress?.flop = !menu.workFlow.value } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/core/Fraction.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/core/Fraction.kt index 3fd36cdb9..10a41d88f 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/core/Fraction.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/core/Fraction.kt @@ -4,6 +4,7 @@ import net.minecraft.nbt.ByteArrayTag import net.minecraft.nbt.StringTag import net.minecraft.nbt.Tag import net.minecraft.network.FriendlyByteBuf +import org.apache.logging.log4j.LogManager import java.math.BigDecimal import java.math.BigInteger import java.math.MathContext @@ -44,6 +45,196 @@ inline fun invertCompare(int: Int): Int { } private val BI_MINUS_ZERO = BigInteger("-0") +private val BI_MINUS_ONE = BigInteger("-1") +private val BI_DIV = BigInteger.valueOf(1_000_000_000) +private val BI_DIV2 = BigInteger.valueOf(10) +private val BI_MINUS_DIV = BigInteger.valueOf(-1_000_000_000) + +private fun isZero(value: BigInteger): Boolean { + return when (value.signum()) { + 0 -> true + 1 -> value == BigInteger.ZERO + -1 -> value == BI_MINUS_ZERO + else -> false + } +} + +private fun isOne(value: BigInteger): Boolean { + return when (value.signum()) { + 0 -> false + 1 -> value == BigInteger.ONE + -1 -> value == BI_MINUS_ONE + else -> false + } +} + +private fun compactTwoMod(value1: BigInteger, value2: BigInteger, compact: Boolean = true): Fraction { + val mod = value1.divideAndRemainder(value2) + + if (isZero(mod[1])) + return Fraction(mod[0], compact = compact) + + return Fraction(value1, value2, compact = compact) +} + +private fun positive(value: BigInteger): BigInteger { + return when (value.signum()) { + 0 -> value + 1 -> value + -1 -> -value + else -> throw InternalError() + } +} + +private val GCDs = arrayOf( + BigInteger.valueOf(2), BigInteger.valueOf(3), BigInteger.valueOf(5), BigInteger.valueOf(7), BigInteger.valueOf(11), BigInteger.valueOf(13), BigInteger.valueOf(17), BigInteger.valueOf(19), BigInteger.valueOf(23), BigInteger.valueOf(29), BigInteger.valueOf(31), BigInteger.valueOf(37), BigInteger.valueOf(41), BigInteger.valueOf(43), BigInteger.valueOf(47), BigInteger.valueOf(53), BigInteger.valueOf(59), BigInteger.valueOf(61), BigInteger.valueOf(67), BigInteger.valueOf(71), + BigInteger.valueOf(73), BigInteger.valueOf(79), BigInteger.valueOf(83), BigInteger.valueOf(89), BigInteger.valueOf(97), BigInteger.valueOf(101), BigInteger.valueOf(103), BigInteger.valueOf(107), BigInteger.valueOf(109), BigInteger.valueOf(113), BigInteger.valueOf(127), BigInteger.valueOf(131), BigInteger.valueOf(137), BigInteger.valueOf(139), BigInteger.valueOf(149), BigInteger.valueOf(151), BigInteger.valueOf(157), BigInteger.valueOf(163), BigInteger.valueOf(167), BigInteger.valueOf(173), + BigInteger.valueOf(179), BigInteger.valueOf(181), BigInteger.valueOf(191), BigInteger.valueOf(193), BigInteger.valueOf(197), BigInteger.valueOf(199), BigInteger.valueOf(211), BigInteger.valueOf(223), BigInteger.valueOf(227), BigInteger.valueOf(229), BigInteger.valueOf(233), BigInteger.valueOf(239), BigInteger.valueOf(241), BigInteger.valueOf(251), BigInteger.valueOf(257), BigInteger.valueOf(263), BigInteger.valueOf(269), BigInteger.valueOf(271), BigInteger.valueOf(277), BigInteger.valueOf(281), + BigInteger.valueOf(283), BigInteger.valueOf(293), BigInteger.valueOf(307), BigInteger.valueOf(311), BigInteger.valueOf(313), BigInteger.valueOf(317), BigInteger.valueOf(331), BigInteger.valueOf(337), BigInteger.valueOf(347), BigInteger.valueOf(349), BigInteger.valueOf(353), BigInteger.valueOf(359), BigInteger.valueOf(367), BigInteger.valueOf(373), BigInteger.valueOf(379), BigInteger.valueOf(383), BigInteger.valueOf(389), BigInteger.valueOf(397), BigInteger.valueOf(401), BigInteger.valueOf(409), + BigInteger.valueOf(419), BigInteger.valueOf(421), BigInteger.valueOf(431), BigInteger.valueOf(433), BigInteger.valueOf(439), BigInteger.valueOf(443), BigInteger.valueOf(449), BigInteger.valueOf(457), BigInteger.valueOf(461), BigInteger.valueOf(463), BigInteger.valueOf(467), BigInteger.valueOf(479), BigInteger.valueOf(487), BigInteger.valueOf(491), BigInteger.valueOf(499), BigInteger.valueOf(503), BigInteger.valueOf(509), BigInteger.valueOf(521), BigInteger.valueOf(523), BigInteger.valueOf(541), + BigInteger.valueOf(547), BigInteger.valueOf(557), BigInteger.valueOf(563), BigInteger.valueOf(569), BigInteger.valueOf(571), BigInteger.valueOf(577), BigInteger.valueOf(587), BigInteger.valueOf(593), BigInteger.valueOf(599), BigInteger.valueOf(601), BigInteger.valueOf(607), BigInteger.valueOf(613), BigInteger.valueOf(617), BigInteger.valueOf(619), BigInteger.valueOf(631), BigInteger.valueOf(641), BigInteger.valueOf(643), BigInteger.valueOf(647), BigInteger.valueOf(653), BigInteger.valueOf(659), + BigInteger.valueOf(661), BigInteger.valueOf(673), BigInteger.valueOf(677), BigInteger.valueOf(683), BigInteger.valueOf(691), BigInteger.valueOf(701), BigInteger.valueOf(709), BigInteger.valueOf(719), BigInteger.valueOf(727), BigInteger.valueOf(733), BigInteger.valueOf(739), BigInteger.valueOf(743), BigInteger.valueOf(751), BigInteger.valueOf(757), BigInteger.valueOf(761), BigInteger.valueOf(769), BigInteger.valueOf(773), BigInteger.valueOf(787), BigInteger.valueOf(797), BigInteger.valueOf(809), + BigInteger.valueOf(811), BigInteger.valueOf(821), BigInteger.valueOf(823), BigInteger.valueOf(827), BigInteger.valueOf(829), BigInteger.valueOf(839), BigInteger.valueOf(853), BigInteger.valueOf(857), BigInteger.valueOf(859), BigInteger.valueOf(863), BigInteger.valueOf(877), BigInteger.valueOf(881), BigInteger.valueOf(883), BigInteger.valueOf(887), BigInteger.valueOf(907), BigInteger.valueOf(911), BigInteger.valueOf(919), BigInteger.valueOf(929), BigInteger.valueOf(937), BigInteger.valueOf(941), + BigInteger.valueOf(947), BigInteger.valueOf(953), BigInteger.valueOf(967), BigInteger.valueOf(971), BigInteger.valueOf(977), BigInteger.valueOf(983), BigInteger.valueOf(991), BigInteger.valueOf(997), BigInteger.valueOf(1009), BigInteger.valueOf(1013), BigInteger.valueOf(1019), BigInteger.valueOf(1021), BigInteger.valueOf(1031), BigInteger.valueOf(1033), BigInteger.valueOf(1039), BigInteger.valueOf(1049), BigInteger.valueOf(1051), BigInteger.valueOf(1061), BigInteger.valueOf(1063), BigInteger.valueOf(1069), + BigInteger.valueOf(1087), BigInteger.valueOf(1091), BigInteger.valueOf(1093), BigInteger.valueOf(1097), BigInteger.valueOf(1103), BigInteger.valueOf(1109), BigInteger.valueOf(1117), BigInteger.valueOf(1123), BigInteger.valueOf(1129), BigInteger.valueOf(1151), BigInteger.valueOf(1153), BigInteger.valueOf(1163), BigInteger.valueOf(1171), BigInteger.valueOf(1181), BigInteger.valueOf(1187), BigInteger.valueOf(1193), BigInteger.valueOf(1201), BigInteger.valueOf(1213), BigInteger.valueOf(1217), BigInteger.valueOf(1223), + BigInteger.valueOf(1229), BigInteger.valueOf(1231), BigInteger.valueOf(1237), BigInteger.valueOf(1249), BigInteger.valueOf(1259), BigInteger.valueOf(1277), BigInteger.valueOf(1279), BigInteger.valueOf(1283), BigInteger.valueOf(1289), BigInteger.valueOf(1291), BigInteger.valueOf(1297), BigInteger.valueOf(1301), BigInteger.valueOf(1303), BigInteger.valueOf(1307), BigInteger.valueOf(1319), BigInteger.valueOf(1321), BigInteger.valueOf(1327), BigInteger.valueOf(1361), BigInteger.valueOf(1367), BigInteger.valueOf(1373), + BigInteger.valueOf(1381), BigInteger.valueOf(1399), BigInteger.valueOf(1409), BigInteger.valueOf(1423), BigInteger.valueOf(1427), BigInteger.valueOf(1429), BigInteger.valueOf(1433), BigInteger.valueOf(1439), BigInteger.valueOf(1447), BigInteger.valueOf(1451), BigInteger.valueOf(1453), BigInteger.valueOf(1459), BigInteger.valueOf(1471), BigInteger.valueOf(1481), BigInteger.valueOf(1483), BigInteger.valueOf(1487), BigInteger.valueOf(1489), BigInteger.valueOf(1493), BigInteger.valueOf(1499), BigInteger.valueOf(1511), + BigInteger.valueOf(1523), BigInteger.valueOf(1531), BigInteger.valueOf(1543), BigInteger.valueOf(1549), BigInteger.valueOf(1553), BigInteger.valueOf(1559), BigInteger.valueOf(1567), BigInteger.valueOf(1571), BigInteger.valueOf(1579), BigInteger.valueOf(1583), BigInteger.valueOf(1597), BigInteger.valueOf(1601), BigInteger.valueOf(1607), BigInteger.valueOf(1609), BigInteger.valueOf(1613), BigInteger.valueOf(1619), BigInteger.valueOf(1621), BigInteger.valueOf(1627), BigInteger.valueOf(1637), BigInteger.valueOf(1657), + BigInteger.valueOf(1663), BigInteger.valueOf(1667), BigInteger.valueOf(1669), BigInteger.valueOf(1693), BigInteger.valueOf(1697), BigInteger.valueOf(1699), BigInteger.valueOf(1709), BigInteger.valueOf(1721), BigInteger.valueOf(1723), BigInteger.valueOf(1733), BigInteger.valueOf(1741), BigInteger.valueOf(1747), BigInteger.valueOf(1753), BigInteger.valueOf(1759), BigInteger.valueOf(1777), BigInteger.valueOf(1783), BigInteger.valueOf(1787), BigInteger.valueOf(1789), BigInteger.valueOf(1801), BigInteger.valueOf(1811), + BigInteger.valueOf(1823), BigInteger.valueOf(1831), BigInteger.valueOf(1847), BigInteger.valueOf(1861), BigInteger.valueOf(1867), BigInteger.valueOf(1871), BigInteger.valueOf(1873), BigInteger.valueOf(1877), BigInteger.valueOf(1879), BigInteger.valueOf(1889), BigInteger.valueOf(1901), BigInteger.valueOf(1907), BigInteger.valueOf(1913), BigInteger.valueOf(1931), BigInteger.valueOf(1933), BigInteger.valueOf(1949), BigInteger.valueOf(1951), BigInteger.valueOf(1973), BigInteger.valueOf(1979), BigInteger.valueOf(1987), + BigInteger.valueOf(1993), BigInteger.valueOf(1997), BigInteger.valueOf(1999), BigInteger.valueOf(2003), BigInteger.valueOf(2011), BigInteger.valueOf(2017), BigInteger.valueOf(2027), BigInteger.valueOf(2029), BigInteger.valueOf(2039), BigInteger.valueOf(2053), BigInteger.valueOf(2063), BigInteger.valueOf(2069), BigInteger.valueOf(2081), BigInteger.valueOf(2083), BigInteger.valueOf(2087), BigInteger.valueOf(2089), BigInteger.valueOf(2099), BigInteger.valueOf(2111), BigInteger.valueOf(2113), BigInteger.valueOf(2129), + BigInteger.valueOf(2131), BigInteger.valueOf(2137), BigInteger.valueOf(2141), BigInteger.valueOf(2143), BigInteger.valueOf(2153), BigInteger.valueOf(2161), BigInteger.valueOf(2179), BigInteger.valueOf(2203), BigInteger.valueOf(2207), BigInteger.valueOf(2213), BigInteger.valueOf(2221), BigInteger.valueOf(2237), BigInteger.valueOf(2239), BigInteger.valueOf(2243), BigInteger.valueOf(2251), BigInteger.valueOf(2267), BigInteger.valueOf(2269), BigInteger.valueOf(2273), BigInteger.valueOf(2281), BigInteger.valueOf(2287), + BigInteger.valueOf(2293), BigInteger.valueOf(2297), BigInteger.valueOf(2309), BigInteger.valueOf(2311), BigInteger.valueOf(2333), BigInteger.valueOf(2339), BigInteger.valueOf(2341), BigInteger.valueOf(2347), BigInteger.valueOf(2351), BigInteger.valueOf(2357), BigInteger.valueOf(2371), BigInteger.valueOf(2377), BigInteger.valueOf(2381), BigInteger.valueOf(2383), BigInteger.valueOf(2389), BigInteger.valueOf(2393), BigInteger.valueOf(2399), BigInteger.valueOf(2411), BigInteger.valueOf(2417), BigInteger.valueOf(2423), + BigInteger.valueOf(2437), BigInteger.valueOf(2441), BigInteger.valueOf(2447), BigInteger.valueOf(2459), BigInteger.valueOf(2467), BigInteger.valueOf(2473), BigInteger.valueOf(2477), BigInteger.valueOf(2503), BigInteger.valueOf(2521), BigInteger.valueOf(2531), BigInteger.valueOf(2539), BigInteger.valueOf(2543), BigInteger.valueOf(2549), BigInteger.valueOf(2551), BigInteger.valueOf(2557), BigInteger.valueOf(2579), BigInteger.valueOf(2591), BigInteger.valueOf(2593), BigInteger.valueOf(2609), BigInteger.valueOf(2617), + BigInteger.valueOf(2621), BigInteger.valueOf(2633), BigInteger.valueOf(2647), BigInteger.valueOf(2657), BigInteger.valueOf(2659), BigInteger.valueOf(2663), BigInteger.valueOf(2671), BigInteger.valueOf(2677), BigInteger.valueOf(2683), BigInteger.valueOf(2687), BigInteger.valueOf(2689), BigInteger.valueOf(2693), BigInteger.valueOf(2699), BigInteger.valueOf(2707), BigInteger.valueOf(2711), BigInteger.valueOf(2713), BigInteger.valueOf(2719), BigInteger.valueOf(2729), BigInteger.valueOf(2731), BigInteger.valueOf(2741), + BigInteger.valueOf(2749), BigInteger.valueOf(2753), BigInteger.valueOf(2767), BigInteger.valueOf(2777), BigInteger.valueOf(2789), BigInteger.valueOf(2791), BigInteger.valueOf(2797), BigInteger.valueOf(2801), BigInteger.valueOf(2803), BigInteger.valueOf(2819), BigInteger.valueOf(2833), BigInteger.valueOf(2837), BigInteger.valueOf(2843), BigInteger.valueOf(2851), BigInteger.valueOf(2857), BigInteger.valueOf(2861), BigInteger.valueOf(2879), BigInteger.valueOf(2887), BigInteger.valueOf(2897), BigInteger.valueOf(2903), + BigInteger.valueOf(2909), BigInteger.valueOf(2917), BigInteger.valueOf(2927), BigInteger.valueOf(2939), BigInteger.valueOf(2953), BigInteger.valueOf(2957), BigInteger.valueOf(2963), BigInteger.valueOf(2969), BigInteger.valueOf(2971), BigInteger.valueOf(2999), BigInteger.valueOf(3001), BigInteger.valueOf(3011), BigInteger.valueOf(3019), BigInteger.valueOf(3023), BigInteger.valueOf(3037), BigInteger.valueOf(3041), BigInteger.valueOf(3049), BigInteger.valueOf(3061), BigInteger.valueOf(3067), BigInteger.valueOf(3079), + BigInteger.valueOf(3083), BigInteger.valueOf(3089), BigInteger.valueOf(3109), BigInteger.valueOf(3119), BigInteger.valueOf(3121), BigInteger.valueOf(3137), BigInteger.valueOf(3163), BigInteger.valueOf(3167), BigInteger.valueOf(3169), BigInteger.valueOf(3181), BigInteger.valueOf(3187), BigInteger.valueOf(3191), BigInteger.valueOf(3203), BigInteger.valueOf(3209), BigInteger.valueOf(3217), BigInteger.valueOf(3221), BigInteger.valueOf(3229), BigInteger.valueOf(3251), BigInteger.valueOf(3253), BigInteger.valueOf(3257), + BigInteger.valueOf(3259), BigInteger.valueOf(3271), BigInteger.valueOf(3299), BigInteger.valueOf(3301), BigInteger.valueOf(3307), BigInteger.valueOf(3313), BigInteger.valueOf(3319), BigInteger.valueOf(3323), BigInteger.valueOf(3329), BigInteger.valueOf(3331), BigInteger.valueOf(3343), BigInteger.valueOf(3347), BigInteger.valueOf(3359), BigInteger.valueOf(3361), BigInteger.valueOf(3371), BigInteger.valueOf(3373), BigInteger.valueOf(3389), BigInteger.valueOf(3391), BigInteger.valueOf(3407), BigInteger.valueOf(3413), + BigInteger.valueOf(3433), BigInteger.valueOf(3449), BigInteger.valueOf(3457), BigInteger.valueOf(3461), BigInteger.valueOf(3463), BigInteger.valueOf(3467), BigInteger.valueOf(3469), BigInteger.valueOf(3491), BigInteger.valueOf(3499), BigInteger.valueOf(3511), BigInteger.valueOf(3517), BigInteger.valueOf(3527), BigInteger.valueOf(3529), BigInteger.valueOf(3533), BigInteger.valueOf(3539), BigInteger.valueOf(3541), BigInteger.valueOf(3547), BigInteger.valueOf(3557), BigInteger.valueOf(3559), BigInteger.valueOf(3571), +) + +private val COMPACT_THRESHOLD = BigInteger("1000000000000000000000") + +private fun compactTwo(value1: BigInteger, value2: BigInteger, compact: Boolean = true): Fraction { + when (value1.signum()) { + 0 -> return Fraction(value1, value2, compact = compact) + 1 -> if (value1 < BI_DIV) return compactTwoMod(value1, value2, compact) + -1 -> if (value1 > BI_MINUS_DIV) return compactTwoMod(value1, value2, compact) + } + + when (value2.signum()) { + 0 -> return Fraction(value1, value2, compact = compact) + 1 -> if (value2 < BI_DIV) return compactTwoMod(value1, value2, compact) + -1 -> if (value2 > BI_MINUS_DIV) return compactTwoMod(value1, value2, compact) + } + + var value1 = value1 + var value2 = value2 + + while (true) { + val _a = value1.divideAndRemainder(BI_DIV) + val _b = value2.divideAndRemainder(BI_DIV) + + if (!isZero(_a[1]) || !isZero(_b[1])) + break + + value1 = _a[0] + value2 = _b[0] + } + + while (true) { + val _a = value1.divideAndRemainder(BI_DIV2) + val _b = value2.divideAndRemainder(BI_DIV2) + + if (!isZero(_a[1]) || !isZero(_b[1])) + break + + value1 = _a[0] + value2 = _b[0] + } + + val p1 = positive(value1) + val p2 = positive(value2) + + if (p1 > COMPACT_THRESHOLD || p2 > COMPACT_THRESHOLD) { + var hit = true + + while (hit) { + hit = false + + for (i in GCDs.size - 1 downTo 0) { + val div = GCDs[i] + + while (true) { + val _a = value1.divideAndRemainder(div) + val _b = value2.divideAndRemainder(div) + + if (!isZero(_a[1]) || !isZero(_b[1])) + break + + value1 = _a[0] + value2 = _b[0] + hit = true + } + } + } + } else if (p1 > GCDs[0] && p2 > GCDs[0]) { + var hit = true + + while (hit) { + hit = false + + for (i in 4 downTo 0) { + val div = GCDs[i] + + while (true) { + val _a = value1.divideAndRemainder(div) + val _b = value2.divideAndRemainder(div) + + if (!isZero(_a[1]) || !isZero(_b[1])) + break + + value1 = _a[0] + value2 = _b[0] + hit = true + } + } + } + } + + return compactTwoMod(value1, value2, compact) +} + +fun unsignedInt(value: Byte): Int { + if (value < 0) { + return 256 + value + } + + return value.toInt() +} + +private data class MagnitudeCrunchResult(val value: BigInteger, val mag: Int) + +private fun magnitude(value: BigInteger): MagnitudeCrunchResult { + if (isZero(value)) + return MagnitudeCrunchResult(value, 0) + + var mag = 0 + var value = value + + while (true) { + val c = value.divideAndRemainder(BI_DIV2) + + if (!isZero(c[1])) + break + + value = c[0] + mag++ + } + + return MagnitudeCrunchResult(value, mag) +} @JvmRecord @Suppress("unused") @@ -72,26 +263,21 @@ data class Fraction @JvmOverloads constructor(@JvmField val value: BigInteger, @ val c = divisor.signum() if (a != b && a != c) { - if (divisor == BigInteger.ZERO || divisor == BI_MINUS_ZERO) + if (isZero(divisor)) return Fraction(-value, -divisor) - val mod = value % divisor + val mod = value.divideAndRemainder(divisor) - if (mod == BigInteger.ZERO) - return Fraction(-value / -divisor, compact = compact) + if (isZero(mod[1])) + return Fraction(mod[0], compact = compact) return Fraction(-value, -divisor) } - if (divisor == BigInteger.ZERO || divisor == BI_MINUS_ZERO) + if (isZero(divisor)) return this - val mod = value % divisor - - if (mod == BigInteger.ZERO) - return Fraction(value / divisor, compact = compact) - - return this + return compactTwo(value, divisor, compact) } fun isZero(): Boolean { @@ -108,12 +294,7 @@ data class Fraction @JvmOverloads constructor(@JvmField val value: BigInteger, @ if (divisor == BigInteger.ZERO || divisor == BI_MINUS_ZERO) return this - val mod = value % divisor - - if (mod == BigInteger.ZERO) - return Fraction(value / divisor, compact = compact) - - return this + return compactTwo(value, divisor, compact) } fun canonize(): Fraction { @@ -181,8 +362,8 @@ data class Fraction @JvmOverloads constructor(@JvmField val value: BigInteger, @ if (isNaN()) return this if (divisor == other.divisor) { - if (divisor == BigInteger.ONE) - return Fraction(value + other.value) + if (isOne(divisor)) + return Fraction(value + other.value, divisor) val new = value + other.value @@ -192,12 +373,7 @@ data class Fraction @JvmOverloads constructor(@JvmField val value: BigInteger, @ if (divisor == BigInteger.ZERO || divisor == BI_MINUS_ZERO) return Fraction(new, divisor) - val mod = new % divisor - - if (mod == BigInteger.ZERO) - return Fraction(new / divisor) - - return Fraction(new, divisor) + return compactTwo(new, divisor) } val new = value * other.divisor + other.value * divisor @@ -206,12 +382,7 @@ data class Fraction @JvmOverloads constructor(@JvmField val value: BigInteger, @ if (div == BigInteger.ZERO || div == BI_MINUS_ZERO) return Fraction(new, div) - val mod = new % div - - if (mod == BigInteger.ZERO) - return Fraction(new / div) - - return Fraction(new, div) + return compactTwo(new, div) } operator fun plus(other: Fraction): Fraction { @@ -230,8 +401,8 @@ data class Fraction @JvmOverloads constructor(@JvmField val value: BigInteger, @ private fun minusCompact(other: Fraction): Fraction { if (divisor == other.divisor) { - if (divisor == BigInteger.ONE) - return Fraction(value - other.value) + if (isOne(divisor)) + return Fraction(value - other.value, divisor) val new = value - other.value @@ -241,12 +412,7 @@ data class Fraction @JvmOverloads constructor(@JvmField val value: BigInteger, @ if (divisor == BigInteger.ZERO || divisor == BI_MINUS_ZERO) return Fraction(new, divisor) - val mod = new % divisor - - if (mod == BigInteger.ZERO) - return Fraction(new / divisor) - - return Fraction(new, divisor) + return compactTwo(new, divisor) } val new = value * other.divisor - other.value * divisor @@ -255,12 +421,7 @@ data class Fraction @JvmOverloads constructor(@JvmField val value: BigInteger, @ if (div == BigInteger.ZERO || div == BI_MINUS_ZERO) return Fraction(new, div) - val mod = new % div - - if (mod == BigInteger.ZERO) - return Fraction(new / div) - - return Fraction(new, div) + return compactTwo(new, div) } operator fun minus(other: Fraction): Fraction { @@ -288,12 +449,7 @@ data class Fraction @JvmOverloads constructor(@JvmField val value: BigInteger, @ if (div == BigInteger.ZERO || div == BI_MINUS_ZERO) return Fraction(new, div) - val mod = new % div - - if (mod == BigInteger.ZERO) - return Fraction(new / div) - - return Fraction(new, div) + return compactTwo(new, div) } operator fun times(other: Fraction): Fraction { @@ -317,12 +473,7 @@ data class Fraction @JvmOverloads constructor(@JvmField val value: BigInteger, @ if (div == BigInteger.ZERO || div == BI_MINUS_ZERO) return Fraction(new, div) - val mod = new % div - - if (mod == BigInteger.ZERO) - return Fraction(new / div) - - return Fraction(new, div) + return compactTwo(new, div) } operator fun div(other: Fraction): Fraction { @@ -423,13 +574,32 @@ data class Fraction @JvmOverloads constructor(@JvmField val value: BigInteger, @ fun toByteArray(): ByteArray { if (isNaN()) { - return byteArrayOf(1, 0, 1, 0) + return byteArrayOf(1, 0, 0, 0, 0, 1, 0, 0, 0, 0) } - val bytesA = value.toByteArray() - val bytesB = divisor.toByteArray() + val magValue = magnitude(value) + val magDiv = magnitude(divisor) - return byteArrayOf(bytesA.size.toByte(), *bytesA, bytesB.size.toByte(), *bytesB) + val bytesA = magValue.value.toByteArray() + val bytesB = magDiv.value.toByteArray() + + return byteArrayOf( + (bytesA.size and 0xFF).toByte(), + (bytesA.size ushr 8).toByte(), + + (magValue.mag and 0xFF).toByte(), + (magValue.mag ushr 8).toByte(), + + *bytesA, + + (bytesB.size and 0xFF).toByte(), + (bytesB.size ushr 8).toByte(), + + (magDiv.mag and 0xFF).toByte(), + (magDiv.mag ushr 8).toByte(), + + *bytesB + ) } fun toInt(): Int { @@ -592,6 +762,8 @@ data class Fraction @JvmOverloads constructor(@JvmField val value: BigInteger, @ } companion object { + private val LOGGER = LogManager.getLogger() + @JvmField val ZERO = Fraction(BigInteger.ZERO) @@ -635,11 +807,27 @@ data class Fraction @JvmOverloads constructor(@JvmField val value: BigInteger, @ @JvmStatic fun fromByteArray(bytes: ByteArray): Fraction { - val bytesA = bytes.copyOfRange(1, 1 + bytes[0].toInt()) - val offsetB = 1 + bytes[0].toInt() - val bytesB = bytes.copyOfRange(offsetB + 1, offsetB + 1 + bytes[offsetB].toInt()) + try { + val rangeA = unsignedInt(bytes[0]) or (unsignedInt(bytes[1]) shl 8) + val magA = unsignedInt(bytes[2]) or (unsignedInt(bytes[3]) shl 8) - return Fraction(if (bytesA.isNotEmpty()) BigInteger(bytesA) else BigInteger.ZERO, if (bytesB.isNotEmpty()) BigInteger(bytesB) else BigInteger.ZERO) + val bytesA = bytes.copyOfRange(4, 4 + rangeA) + + val offsetB = 4 + rangeA + + val rangeB = unsignedInt(bytes[offsetB]) or (unsignedInt(bytes[offsetB + 1]) shl 8) + val magB = unsignedInt(bytes[offsetB + 2]) or (unsignedInt(bytes[offsetB + 3]) shl 8) + + val bytesB = bytes.copyOfRange(offsetB + 4, offsetB + 4 + rangeB) + + if (bytesB.isEmpty()) + return NaN + + return Fraction(if (bytesA.isNotEmpty()) (BigInteger(bytesA) * BigInteger("1" + "0".repeat(magA))) else BigInteger.ZERO, BigInteger(bytesB) * BigInteger("1" + "0".repeat(magB))) + } catch(err: Throwable) { + LOGGER.error("Unable to load Fraction from byte array", err) + return NaN + } } @JvmStatic diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/graph/Abstract6Graph.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/graph/Abstract6Graph.kt new file mode 100644 index 000000000..75faf5023 --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/graph/Abstract6Graph.kt @@ -0,0 +1,159 @@ +package ru.dbotthepony.mc.otm.graph + +import net.minecraft.core.BlockPos +import net.minecraft.core.Direction +import net.minecraft.core.SectionPos +import net.minecraft.server.level.ServerLevel +import net.minecraft.world.level.block.entity.BlockEntity +import ru.dbotthepony.mc.otm.OverdriveThatMatters +import ru.dbotthepony.mc.otm.plus +import java.util.* +import kotlin.collections.ArrayList + +abstract class Abstract6Graph { + @JvmField + protected val _nodes = ArrayList>() + fun size() = _nodes.size + + @JvmField + val nodes = Collections.unmodifiableCollection(_nodes) + + abstract fun onNodeRemoved(node: Graph6Node) + abstract fun onNodeAdded(node: Graph6Node) + + fun removeNode(node: Graph6Node) { + if (!_nodes.contains(node)) + throw IllegalStateException("Not containing node $node") + + _nodes.remove(node) + node.graph = null + onNodeRemoved(node) + } + + fun addNode(node: Graph6Node) { + if (_nodes.contains(node)) + throw IllegalStateException("Already containing node $node") + + _nodes.add(node) + node.graph = this + onNodeAdded(node) + } + + fun merge(other: Abstract6Graph): Abstract6Graph { + if (other === this) + return this + + if (size() >= other.size()) { + for (node in other._nodes) { + _nodes.add(node) + node.graph = this + onNodeAdded(node) + } + + return this + } else { + return other.merge(this) + } + } + + companion object { + fun > discoverFull( + level: ServerLevel, + blockPos: BlockPos, + node: Graph6Node, + nodeGetter: (BlockEntity) -> Graph6Node?, + factory: () -> G + ) { + OverdriveThatMatters.tickUntil(level) { + !node.valid || discover(level, blockPos, node, nodeGetter, factory) + } + } + + @JvmStatic + fun > discover( + level: ServerLevel, + blockPos: BlockPos, + node: Graph6Node, + nodeGetter: (BlockEntity) -> Graph6Node?, + factory: () -> G + ): Boolean { + var fullDiscovery = true + + node.nullifyConnections() + + var _graph = node.graph + + // для начала найдем граф к которому будем принадлежать + if (_graph == null) { + for (dir in Direction.values()) { + val offset = blockPos + dir + val chunk = level.chunkSource.getChunkNow(SectionPos.blockToSectionCoord(offset.x), SectionPos.blockToSectionCoord(offset.z)) + + if (chunk == null) { + fullDiscovery = false + continue + } + + val entity = chunk.getBlockEntity(offset) + + if (entity != null) { + val getNode = nodeGetter(entity) + + if (getNode?.graph != null) { + _graph = getNode.graph + break + } + } + } + + // мы нашли граф рядом + if (_graph != null) { + node.graph = _graph + _graph.addNode(node) + } else { + // графов рядом нет, создаем свой + _graph = factory() + node.graph = _graph + _graph.addNode(node) + } + } + + // теперь снова смотрим на соседей, если у них нет графа - присоединяем к своему + // если у них есть граф - слияем его со своим или свой с его + for (dir in Direction.values()) { + val offset = blockPos + dir + val chunk = level.chunkSource.getChunkNow(SectionPos.blockToSectionCoord(offset.x), SectionPos.blockToSectionCoord(offset.z)) + + if (chunk == null) { + fullDiscovery = false + continue + } + + val entity = chunk.getBlockEntity(offset) + + if (entity != null) { + val getNode = nodeGetter(entity) + + if (getNode != null) { + // у вершины нет своего графа + // добавляем в свой граф + if (getNode.graph == null) { + getNode.graph = node.graph!! + node.graph!!.addNode(getNode) + } else if (getNode.graph != node.graph) { + // у вершины уже есть свой граф, и он не наш + // произведём слияние графов + val merged = getNode.graph!!.merge(node.graph!!) + getNode.graph = merged + node.graph = merged + } + + node.setToNeightbour(getNode, dir) + } + } + } + + return fullDiscovery + } + } +} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/graph/Graph6Node.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/graph/Graph6Node.kt new file mode 100644 index 000000000..27b558425 --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/graph/Graph6Node.kt @@ -0,0 +1,299 @@ +package ru.dbotthepony.mc.otm.graph + +import net.minecraft.core.Direction + +interface GraphNodeListener { + fun onNeighbourTop(node: Graph6Node<*>) = onNeighbour(node, Direction.UP) + fun onNeighbourBottom(node: Graph6Node<*>) = onNeighbour(node, Direction.DOWN) + fun onNeighbourLeft(node: Graph6Node<*>) = onNeighbour(node, Direction.WEST) + fun onNeighbourRight(node: Graph6Node<*>) = onNeighbour(node, Direction.EAST) + fun onNeighbourFront(node: Graph6Node<*>) = onNeighbour(node, Direction.SOUTH) + fun onNeighbourBack(node: Graph6Node<*>) = onNeighbour(node, Direction.NORTH) + + fun onNeighbour(node: Graph6Node<*>, direction: Direction) + + fun onUnNeighbourTop(node: Graph6Node<*>) = onUnNeighbour(node, Direction.UP) + fun onUnNeighbourBottom(node: Graph6Node<*>) = onUnNeighbour(node, Direction.DOWN) + fun onUnNeighbourLeft(node: Graph6Node<*>) = onUnNeighbour(node, Direction.WEST) + fun onUnNeighbourRight(node: Graph6Node<*>) = onUnNeighbour(node, Direction.EAST) + fun onUnNeighbourFront(node: Graph6Node<*>) = onUnNeighbour(node, Direction.SOUTH) + fun onUnNeighbourBack(node: Graph6Node<*>) = onUnNeighbour(node, Direction.NORTH) + + fun onUnNeighbour(node: Graph6Node<*>, direction: Direction) +} + +// Вершина графа, содержит то, к какому графу принадлежит, соседей и своё "значение" +class Graph6Node(@JvmField val value: T, graph: Abstract6Graph? = null) { + var graph: Abstract6Graph? = null + + init { + this.graph = graph + } + + var top: Graph6Node? = null + set(value) { + if (value != null && (graph == null || value.graph !== graph)) throw IllegalStateException("Can not be neighbour with node from different graph") + + if (field != value && this.value is GraphNodeListener) { + if (field != null) { + this.value.onUnNeighbourTop(field!!) + } + + if (value != null) { + this.value.onNeighbourTop(value) + } + } + + field = value + } + + var bottom: Graph6Node? = null + set(value) { + if (value != null && (graph == null || value.graph !== graph)) throw IllegalStateException("Can not be neighbour with node from different graph") + + if (field != value && this.value is GraphNodeListener) { + if (field != null) { + this.value.onUnNeighbourBottom(field!!) + } + + if (value != null) { + this.value.onNeighbourBottom(value) + } + } + + field = value + } + + var left: Graph6Node? = null + set(value) { + if (value != null && (graph == null || value.graph !== graph)) throw IllegalStateException("Can not be neighbour with node from different graph") + + if (field != value && this.value is GraphNodeListener) { + if (field != null) { + this.value.onUnNeighbourLeft(field!!) + } + + if (value != null) { + this.value.onNeighbourLeft(value) + } + } + + field = value + } + + var right: Graph6Node? = null + set(value) { + if (value != null && (graph == null || value.graph !== graph)) throw IllegalStateException("Can not be neighbour with node from different graph") + + if (field != value && this.value is GraphNodeListener) { + if (field != null) { + this.value.onUnNeighbourRight(field!!) + } + + if (value != null) { + this.value.onNeighbourRight(value) + } + } + + field = value + } + + var front: Graph6Node? = null + set(value) { + if (value != null && (graph == null || value.graph !== graph)) throw IllegalStateException("Can not be neighbour with node from different graph") + + if (field != value && this.value is GraphNodeListener) { + if (field != null) { + this.value.onUnNeighbourFront(field!!) + } + + if (value != null) { + this.value.onNeighbourFront(value) + } + } + + field = value + } + + var back: Graph6Node? = null + set(value) { + if (value != null && (graph == null || value.graph !== graph)) throw IllegalStateException("Can not be neighbour with node from different graph") + + if (field != value && this.value is GraphNodeListener) { + if (field != null) { + this.value.onUnNeighbourBack(field!!) + } + + if (value != null) { + this.value.onNeighbourBack(value) + } + } + + field = value + } + + fun nullifyConnections() { + top?.bottom = null + bottom?.top = null + left?.right = null + right?.left = null + front?.back = null + back?.front = null + + top = null + bottom = null + left = null + right = null + front = null + back = null + } + + fun setToNeightbour(node: Graph6Node, direction: Direction) { + when (direction) { + Direction.DOWN -> { + node.top = this + bottom = node + } + + Direction.UP -> { + node.bottom = this + top = node + } + + Direction.NORTH -> { + node.front = this + back = node + } + + Direction.SOUTH -> { + node.back = this + front = node + } + + Direction.WEST -> { + node.right = this + left = node + } + + Direction.EAST -> { + node.left = this + right = node + } + } + } + + var seen: Int = 0 + + private fun _flood(): List> { + val list = ArrayList>() + var seen = Int.MAX_VALUE + + GraphFlooder.floodIf(top, seen) { + seen = it.seen + list.add(it) + } + + GraphFlooder.floodIf(bottom, seen) { + seen = it.seen + list.add(it) + } + + GraphFlooder.floodIf(left, seen) { + seen = it.seen + list.add(it) + } + + GraphFlooder.floodIf(right, seen) { + seen = it.seen + list.add(it) + } + + GraphFlooder.floodIf(front, seen) { + seen = it.seen + list.add(it) + } + + GraphFlooder.floodIf(back, seen) { + seen = it.seen + list.add(it) + } + + return list + } + + fun flood(): List> { + top?.bottom = null + bottom?.top = null + left?.right = null + right?.left = null + front?.back = null + back?.front = null + + val list = _flood() + + top?.bottom = this + bottom?.top = this + left?.right = this + right?.left = this + front?.back = this + back?.front = this + + return list + } + + var valid = true + private set + + fun destroy(factory: () -> Abstract6Graph): List> { + if (!valid) return emptyList() + + top?.bottom = null + bottom?.top = null + left?.right = null + right?.left = null + front?.back = null + back?.front = null + + graph?.removeNode(this) + + var num = 0 + + if (top != null) num++ + if (bottom != null) num++ + if (left != null) num++ + if (right != null) num++ + if (front != null) num++ + if (back != null) num++ + + if (num < 2) { + return emptyList() + } + + val paths = _flood() + + if (paths.size < 2) { + return paths + } + + var biggest = paths[0] + + for (i in 1 until paths.size) { + if (biggest.size() < paths[i].size()) { + biggest = paths[i] + } + } + + for (flooder in paths) { + if (flooder == biggest) continue + + val graph = factory() + + for (node in flooder.nodes) { + node.graph?.removeNode(node) + graph.addNode(node) + } + } + + return paths + } +} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/graph/GraphFlooder.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/graph/GraphFlooder.kt new file mode 100644 index 000000000..361ef2155 --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/graph/GraphFlooder.kt @@ -0,0 +1,64 @@ +package ru.dbotthepony.mc.otm.graph + +import java.util.* +import kotlin.collections.ArrayList + +class GraphFlooder(val startNode: Graph6Node, @JvmField val seen: Int = nextSeen++) { + var flooded = false + private set + + private val _nodes = ArrayList>() + + @JvmField + val nodes = Collections.unmodifiableCollection(_nodes) + + fun size() = _nodes.size + + private fun flood(node: Graph6Node) { + if (node.seen >= seen) return + + _nodes.add(node) + node.seen = seen + + if (node.top != null) flood(node.top!!) + if (node.bottom != null) flood(node.bottom!!) + if (node.left != null) flood(node.left!!) + if (node.right != null) flood(node.right!!) + if (node.front != null) flood(node.front!!) + if (node.back != null) flood(node.back!!) + } + + fun flood() { + if (flooded) throw IllegalStateException("Already flooded") + + flooded = true + + _nodes.add(startNode) + startNode.seen = seen + + if (startNode.top != null) flood(startNode.top!!) + if (startNode.bottom != null) flood(startNode.bottom!!) + if (startNode.left != null) flood(startNode.left!!) + if (startNode.right != null) flood(startNode.right!!) + if (startNode.front != null) flood(startNode.front!!) + if (startNode.back != null) flood(startNode.back!!) + } + + companion object { + private var nextSeen = 0 + + fun floodIf(node: Graph6Node?, seen: Int, runnable: (GraphFlooder) -> Unit) { + if (node != null && node.seen < seen) { + if (seen == Int.MAX_VALUE) { + val flooder = GraphFlooder(node) + flooder.flood() + runnable(flooder) + } else { + val flooder = GraphFlooder(node, seen) + flooder.flood() + runnable(flooder) + } + } + } + } +} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/graph/matter/IMatterGraphNode.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/graph/matter/IMatterGraphNode.kt new file mode 100644 index 000000000..ea1ef6303 --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/graph/matter/IMatterGraphNode.kt @@ -0,0 +1,23 @@ +package ru.dbotthepony.mc.otm.graph.matter + +import ru.dbotthepony.mc.otm.capability.matter.* +import ru.dbotthepony.mc.otm.graph.Graph6Node + +interface IMatterGraphListener { + fun onPatternAdded(state: PatternState) {} + fun onPatternRemoved(state: PatternState) {} + fun onPatternUpdated(new_state: PatternState, old_state: PatternState) {} + + fun onMatterTaskCreated(task: MatterTask) {} + fun onMatterTaskUpdated(new_state: MatterTask, old_state: MatterTask) {} + fun onMatterTaskFinished(state: MatterTask) {} + fun onMatterTaskRemoved(state: MatterTask) {} +} + +interface IMatterGraphNode : IMatterGraphListener { + fun getMatterHandler(): IMatterHandler? = null + fun getPatternHandler(): IPatternStorage? = null + fun getTaskHandler(): IMatterTaskProvider? = null + fun getAsMatterNode(): Graph6Node + fun getAsMatterGraph(): MatterNetworkGraph? = getAsMatterNode().graph as MatterNetworkGraph? +} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/graph/matter/MatterNetworkGraph.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/graph/matter/MatterNetworkGraph.kt new file mode 100644 index 000000000..e2aa51a59 --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/graph/matter/MatterNetworkGraph.kt @@ -0,0 +1,416 @@ +package ru.dbotthepony.mc.otm.graph.matter + +import net.minecraft.server.level.ServerLevel +import net.minecraft.world.item.Item +import net.minecraft.world.level.block.entity.BlockEntity +import ru.dbotthepony.mc.otm.capability.MatteryCapability +import ru.dbotthepony.mc.otm.capability.matter.* +import ru.dbotthepony.mc.otm.core.Fraction +import ru.dbotthepony.mc.otm.graph.Abstract6Graph +import ru.dbotthepony.mc.otm.graph.Graph6Node +import java.util.* +import kotlin.collections.ArrayList +import kotlin.collections.HashSet + +@Suppress("unused") +class MatterNetworkGraph : Abstract6Graph(), IMatterGraphListener { + private val listeners = HashSet() + + fun addListener(listener: IMatterGraphListener) = listeners.add(listener) + fun removeListener(listener: IMatterGraphListener) = listeners.remove(listener) + + override fun onNodeRemoved(node: Graph6Node) { + val patterns = node.value.getPatternHandler() + + if (patterns != null) { + for (pattern in patterns.storedPatterns) { + onPatternRemoved(pattern) + } + } + + val tasks = node.value.getTaskHandler() + + if (tasks != null) { + for (task in tasks.tasks) { + onMatterTaskRemoved(task) + } + } + + for (pattern in getStoredPatterns()) { + node.value.onPatternRemoved(pattern) + } + + for (task in getTasks()) { + node.value.onMatterTaskRemoved(task) + } + } + + override fun onNodeAdded(node: Graph6Node) { + for (pattern in getStoredPatterns()) { + node.value.onPatternAdded(pattern) + } + + for (task in getTasks()) { + node.value.onMatterTaskCreated(task) + } + + val patterns = node.value.getPatternHandler() + + if (patterns != null) { + for (pattern in patterns.storedPatterns) { + onPatternAdded(pattern) + } + } + + val tasks = node.value.getTaskHandler() + + if (tasks != null) { + for (task in tasks.tasks) { + onMatterTaskCreated(task) + } + } + } + + fun getMatterStorageLevel(): Fraction { + var level = Fraction.ZERO + + for (node in _nodes) { + val matter = node.value.getMatterHandler() + + if (matter != null && matter.direction == IMatterHandler.MatterDirection.BIDIRECTIONAL) { + level += matter.storedMatter + } + } + + return level + } + + fun getMatterStorageMaxLevel(): Fraction { + var level = Fraction.ZERO + + for (node in _nodes) { + val matter = node.value.getMatterHandler() + + if (matter != null && matter.direction == IMatterHandler.MatterDirection.BIDIRECTIONAL) { + level += matter.maxStoredMatter + } + } + + return level + } + + fun extractMatter(howMuch: Fraction, simulate: Boolean): Fraction { + if (howMuch <= Fraction.ZERO) + return Fraction.ZERO + + var howMuch = howMuch + var extracted = Fraction.ZERO + + for (node in _nodes) { + val matter = node.value.getMatterHandler() + + if (matter != null) { + val value = matter.extractMatterOuter(howMuch, simulate) + howMuch -= value + extracted += value + + if (howMuch <= Fraction.ZERO) + return extracted + } + } + + return extracted + } + + fun receiveMatter(howMuch: Fraction, simulate: Boolean): Fraction { + if (howMuch <= Fraction.ZERO) + return Fraction.ZERO + + var howMuch = howMuch + var received = Fraction.ZERO + + for (node in _nodes) { + val matter = node.value.getMatterHandler() + + if (matter != null && matter.direction == IMatterHandler.MatterDirection.BIDIRECTIONAL) { + val value = matter.receiveMatterOuter(howMuch, simulate) + howMuch -= value + received += value + + if (howMuch <= Fraction.ZERO) + return received + } + } + + return received + } + + fun receiveMatterForce(howMuch: Fraction, simulate: Boolean): Fraction { + if (howMuch <= Fraction.ZERO) + return Fraction.ZERO + + var howMuch = howMuch + var received = Fraction.ZERO + + for (node in _nodes) { + val matter = node.value.getMatterHandler() + + if (matter != null && matter.direction != IMatterHandler.MatterDirection.EXTRACT) { + val value = matter.receiveMatterOuter(howMuch, simulate) + howMuch -= value + received += value + + if (howMuch <= Fraction.ZERO) + return received + } + } + + return received + } + + private fun _insertPattern(state: PatternState, onlyUpdate: Boolean, simulate: Boolean): PatternInsertStatus { + for (node in _nodes) { + val storage = node.value.getPatternHandler() + + if (storage != null) { + val status = storage.insertPattern(state, onlyUpdate, simulate) + + if (status.status != PatternInsertStatus.Status.FAIL) { + return status + } + } + } + + return PatternInsertStatus() + } + + fun insertPattern(state: PatternState, onlyUpdate: Boolean, simulate: Boolean): PatternInsertStatus { + if (onlyUpdate) return _insertPattern(state, true, simulate) + val status = _insertPattern(state, true, simulate) + if (status.status != PatternInsertStatus.Status.FAIL) return status + return _insertPattern(state, false, simulate) + } + + fun getTasks(): Collection { + val list = ArrayList() + + for (node in _nodes) { + val tasks = node.value.getTaskHandler() + + if (tasks != null) { + list.addAll(tasks.tasks) + } + } + + return list + } + + fun getStoredPatterns(): Collection { + val list = ArrayList() + + for (node in _nodes) { + val storage = node.value.getPatternHandler() + + if (storage != null) { + list.addAll(storage.storedPatterns) + } + } + + return list + } + + fun getPatternCount(): Long { + var value = 0L + + for (node in _nodes) { + val storage = node.value.getPatternHandler() + + if (storage != null) { + value += storage.stored + } + } + + return value + } + + fun getPatternCapacity(): Long { + var value = 0L + + for (node in _nodes) { + val storage = node.value.getPatternHandler() + + if (storage != null) { + value += storage.capacity + } + } + + return value + } + + fun getPattern(id: UUID): PatternState? { + for (node in _nodes) { + val storage = node.value.getPatternHandler() + + if (storage != null) { + val get = storage.getPattern(id) + + if (get != null) { + return get + } + } + } + + return null + } + + fun getPattern(state: PatternState) = getPattern(state.id) + fun hasPattern(state: PatternState) = getPattern(state.id) != null + fun hasPattern(id: UUID) = getPattern(id) != null + + fun findPattern(predicate: (PatternState) -> Boolean): PatternState? { + for (node in _nodes) { + val storage = node.value.getPatternHandler() + + if (storage != null) { + for (state in storage.storedPatterns) { + if (predicate(state)) { + return state + } + } + } + } + + return null + } + + fun findPattern(predicate: Item) = findPattern { it.item == predicate } + + fun findPatterns(predicate: (PatternState) -> Boolean): Collection { + val list = ArrayList() + + for (node in _nodes) { + val storage = node.value.getPatternHandler() + + if (storage != null) { + for (state in storage.storedPatterns) { + if (predicate(state)) { + list.add(state) + } + } + } + } + + return list + } + + fun findPatterns(predicate: Item) = findPatterns { it.item == predicate } + + fun allocateTask(simulate: Boolean): MatterTaskAllocation? { + for (node in _nodes) { + val tasks = node.value.getTaskHandler() + + if (tasks != null) { + val allocated = tasks.allocateTask(simulate) + + if (allocated != null) { + return allocated + } + } + } + + return null + } + + fun notifyTaskCompletion(task: MatterTask): Boolean { + for (node in _nodes) { + val tasks = node.value.getTaskHandler() + + if (tasks != null && tasks.notifyTaskCompletion(task)) { + return true + } + } + + return false + } + + override fun onPatternAdded(state: PatternState) { + for (node in _nodes) node.value.onPatternAdded(state) + for (node in listeners) node.onPatternAdded(state) + } + + override fun onPatternRemoved(state: PatternState) { + for (node in _nodes) node.value.onPatternRemoved(state) + for (node in listeners) node.onPatternRemoved(state) + } + + override fun onPatternUpdated(new_state: PatternState, old_state: PatternState) { + for (node in _nodes) node.value.onPatternUpdated(new_state, old_state) + for (node in listeners) node.onPatternUpdated(new_state, old_state) + } + + override fun onMatterTaskCreated(task: MatterTask) { + for (node in _nodes) node.value.onMatterTaskCreated(task) + for (node in listeners) node.onMatterTaskCreated(task) + } + + override fun onMatterTaskUpdated(new_state: MatterTask, old_state: MatterTask) { + for (node in _nodes) node.value.onMatterTaskUpdated(new_state, old_state) + for (node in listeners) node.onMatterTaskUpdated(new_state, old_state) + } + + override fun onMatterTaskFinished(state: MatterTask) { + for (node in _nodes) node.value.onMatterTaskFinished(state) + for (node in listeners) node.onMatterTaskFinished(state) + } + + override fun onMatterTaskRemoved(state: MatterTask) { + for (node in _nodes) node.value.onMatterTaskRemoved(state) + for (node in listeners) node.onMatterTaskRemoved(state) + } + + companion object { + @JvmStatic + fun discoverFull(tile: BlockEntity, node: Graph6Node) { + if (tile.level !is ServerLevel) + return + + return discoverFull( + tile.level!! as ServerLevel, + tile.blockPos, + node, + fun(_tile): Graph6Node? { + val resolve = _tile.getCapability(MatteryCapability.MATTER_CELL) + + return if (resolve.isPresent) { + resolve.resolve().get().getAsMatterNode() + } else { + null + } + }, + ::MatterNetworkGraph + ) + } + + @JvmStatic + fun discover(tile: BlockEntity, node: Graph6Node): Boolean { + if (tile.level !is ServerLevel) + return false + + return discover( + tile.level!! as ServerLevel, + tile.blockPos, + node, + fun(_tile): Graph6Node? { + val resolve = _tile.getCapability(MatteryCapability.MATTER_CELL) + + return if (resolve.isPresent) { + resolve.resolve().get().getAsMatterNode() + } else { + null + } + }, + ::MatterNetworkGraph + ) + } + } +} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/MatterBottlerMenu.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/MatterBottlerMenu.kt index d800096b5..fe4d2eee7 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/MatterBottlerMenu.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/MatterBottlerMenu.kt @@ -1,103 +1,83 @@ -package ru.dbotthepony.mc.otm.menu; +package ru.dbotthepony.mc.otm.menu -import net.minecraft.world.SimpleContainer; -import net.minecraft.world.entity.player.Inventory; -import net.minecraft.world.inventory.ContainerData; -import net.minecraft.world.item.ItemStack; -import ru.dbotthepony.mc.otm.Registry; -import ru.dbotthepony.mc.otm.block.entity.BlockEntityMatterBottler; -import ru.dbotthepony.mc.otm.capability.matter.IMatterHandler; -import ru.dbotthepony.mc.otm.capability.MatteryCapability; -import ru.dbotthepony.mc.otm.menu.slot.MatterySlot; -import ru.dbotthepony.mc.otm.menu.widget.LevelGaugeWidget; -import ru.dbotthepony.mc.otm.menu.widget.ProgressGaugeWidget; -import ru.dbotthepony.mc.otm.network.MatterBottlerSwitchPacket; -import ru.dbotthepony.mc.otm.network.MatteryNetworking; -import ru.dbotthepony.mc.otm.client.screen.UVWindingOrder; +import net.minecraft.world.SimpleContainer +import net.minecraft.world.entity.player.Inventory +import net.minecraft.world.item.ItemStack +import ru.dbotthepony.mc.otm.Registry +import ru.dbotthepony.mc.otm.block.entity.BlockEntityMatterBottler +import ru.dbotthepony.mc.otm.capability.MatteryCapability +import ru.dbotthepony.mc.otm.capability.matter.IMatterHandler +import ru.dbotthepony.mc.otm.menu.data.BooleanDataContainer +import ru.dbotthepony.mc.otm.menu.slot.MatterySlot +import ru.dbotthepony.mc.otm.menu.widget.LevelGaugeWidget +import ru.dbotthepony.mc.otm.menu.widget.ProgressGaugeWidget +import ru.dbotthepony.mc.otm.network.MatterBottlerSwitchPacket +import ru.dbotthepony.mc.otm.network.MatteryNetworking -public class MatterBottlerMenu extends PoweredMatteryMenu { - public MatterBottlerMenu(int p_38852_, Inventory inventory) { - this(p_38852_, inventory, null); - } +class MatterBottlerMenu @JvmOverloads constructor( + p_38852_: Int, + inventory: Inventory, + tile: BlockEntityMatterBottler? = null +) : PoweredMatteryMenu( + Registry.Menus.MATTER_BOTTLER, p_38852_, inventory, tile +) { + var workFlow = BooleanDataContainer() - public ContainerData work_flow = new ContainerData() { - private int value; + val progressWidget: ProgressGaugeWidget + val matterWidget: LevelGaugeWidget + val container = arrayOfNulls(6) - @Override - public int get(int i) { - if (tile != null) { - return ((BlockEntityMatterBottler) tile).getWorkFlow() ? 1 : 0; + init { + val container = tile?.container ?: SimpleContainer(6) + + if (tile == null) { + progressWidget = ProgressGaugeWidget(this) + matterWidget = LevelGaugeWidget(this) + } else { + progressWidget = ProgressGaugeWidget(this) { tile.getWorkProgress() } + matterWidget = LevelGaugeWidget(this, tile.matter) + } + + for (i in 0 until container.containerSize) { + this.container[i] = object : MatterySlot(container, i) { + override fun mayPlace(p_40231_: ItemStack): Boolean { + val cap = p_40231_.getCapability(MatteryCapability.MATTER).resolve() + if (!cap.isPresent) return false + + if (workFlow.value) { + return index < 3 && cap.get().direction != IMatterHandler.MatterDirection.EXTRACT + } else { + return index >= 3 && cap.get().direction != IMatterHandler.MatterDirection.RECEIVE + } + } } - return value; + addSlot(this.container[i]!!) } - @Override - public void set(int i, int i1) { - value = i1; - } + addDataSlots(workFlow) + addBatterySlot() + addInventorySlots() + } - @Override - public int getCount() { - return 1; - } - }; + override fun broadcastChanges() { + super.broadcastChanges() + workFlow.value = (tile as BlockEntityMatterBottler).workFlow + } - public ProgressGaugeWidget progress; - public LevelGaugeWidget matter_widget; + override fun getWorkingSlotStart(): Int { + return 0 + } - public MatterySlot[] work_slots = new MatterySlot[6]; - - public MatterBottlerMenu(int p_38852_, Inventory inventory, BlockEntityMatterBottler tile) { - super(Registry.Menus.MATTER_BOTTLER, p_38852_, inventory, tile); - - var container = tile != null ? tile.work_slots : new SimpleContainer(6); + override fun getWorkingSlotEnd(): Int { + return 7 + } + fun switchBottlerMode() { if (tile == null) { - progress = new ProgressGaugeWidget(this); - matter_widget = new LevelGaugeWidget(this); + MatteryNetworking.CHANNEL.sendToServer(MatterBottlerSwitchPacket()) } else { - progress = new ProgressGaugeWidget(this, tile::getWorkProgress); - matter_widget = new LevelGaugeWidget(this, tile.matter); - } - - for (int i = 0; i < container.getContainerSize(); i++) { - work_slots[i] = new MatterySlot(container, i) { - @Override - public boolean mayPlace(ItemStack p_40231_) { - var cap = p_40231_.getCapability(MatteryCapability.MATTER).resolve(); - - if (work_flow.get(0) > 0) { - return index < 3 && cap.isPresent() && cap.get().getDirection() != IMatterHandler.MatterDirection.EXTRACT; - } - - return index >= 3 && cap.isPresent() && cap.get().getDirection() != IMatterHandler.MatterDirection.RECEIVE; - } - }; - - addSlot(work_slots[i]); - } - - addDataSlots(work_flow); - addBatterySlot(); - addInventorySlots(); - } - - @Override - protected int getWorkingSlotStart() { - return 0; - } - - @Override - protected int getWorkingSlotEnd() { - return 7; - } - - public void switchBottlerMode() { - if (tile == null) { - MatteryNetworking.CHANNEL.sendToServer(new MatterBottlerSwitchPacket()); - } else { - ((BlockEntityMatterBottler) tile).switchWorkFlow(); + (tile as BlockEntityMatterBottler).switchWorkFlow() } } -} +} \ No newline at end of file diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/MatterCapacitorBankMenu.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/MatterCapacitorBankMenu.kt index 8fc9602dd..878fc80ea 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/MatterCapacitorBankMenu.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/MatterCapacitorBankMenu.kt @@ -1,69 +1,63 @@ -package ru.dbotthepony.mc.otm.menu; +package ru.dbotthepony.mc.otm.menu -import net.minecraft.world.Container; -import net.minecraft.world.SimpleContainer; -import net.minecraft.world.entity.player.Inventory; -import ru.dbotthepony.mc.otm.Registry; -import ru.dbotthepony.mc.otm.block.entity.BlockEntityMatterCapacitorBank; -import ru.dbotthepony.mc.otm.capability.matter.IMatterHandler; -import ru.dbotthepony.mc.otm.core.Fraction; -import ru.dbotthepony.mc.otm.menu.slot.MatterContainerInputSlot; -import ru.dbotthepony.mc.otm.menu.widget.LevelGaugeWidget; +import net.minecraft.world.SimpleContainer +import net.minecraft.world.entity.player.Inventory +import ru.dbotthepony.mc.otm.Registry +import ru.dbotthepony.mc.otm.block.entity.BlockEntityMatterCapacitorBank +import ru.dbotthepony.mc.otm.capability.matter.IMatterHandler +import ru.dbotthepony.mc.otm.core.Fraction +import ru.dbotthepony.mc.otm.graph.matter.MatterNetworkGraph +import ru.dbotthepony.mc.otm.menu.slot.MatterContainerInputSlot +import ru.dbotthepony.mc.otm.menu.widget.LevelGaugeWidget -import java.math.BigDecimal; - -public class MatterCapacitorBankMenu extends MatteryMenu { - public MatterCapacitorBankMenu(int p_38852_, Inventory inventory) { - this(p_38852_, inventory, null); - } - - public LevelGaugeWidget matter_widget; - public LevelGaugeWidget total_matter_widget; - - public MatterContainerInputSlot[] container_slots = new MatterContainerInputSlot[2 * 6]; - - public MatterCapacitorBankMenu(int p_38852_, Inventory inventory, BlockEntityMatterCapacitorBank tile) { - super(Registry.Menus.MATTER_CAPACITOR_BANK, p_38852_, inventory, tile); +class MatterCapacitorBankMenu @JvmOverloads constructor( + p_38852_: Int, + inventory: Inventory?, + tile: BlockEntityMatterCapacitorBank? = null +) : MatteryMenu( + Registry.Menus.MATTER_CAPACITOR_BANK, p_38852_, inventory!!, tile +) { + val matter_widget: LevelGaugeWidget + val total_matter_widget: LevelGaugeWidget + val container_slots = arrayOfNulls(2 * 6) + init { if (tile == null) { - matter_widget = new LevelGaugeWidget(this); - total_matter_widget = new LevelGaugeWidget(this); + matter_widget = LevelGaugeWidget(this) + total_matter_widget = LevelGaugeWidget(this) } else { - matter_widget = new LevelGaugeWidget(this, tile.matter); - total_matter_widget = new LevelGaugeWidget(this, () -> { - if (tile.getMatterGrid() != null) { - return tile.getMatterGrid().getStored(); - } - - return Fraction.ZERO; - }, () -> { - if (tile.getMatterGrid() != null) { - return tile.getMatterGrid().getCapacity(); - } - - return Fraction.ZERO; - }); + matter_widget = LevelGaugeWidget(this, tile) + total_matter_widget = LevelGaugeWidget(this, { + (tile.getAsMatterNode().graph as MatterNetworkGraph?)?.getMatterStorageLevel() ?: Fraction.ZERO + }, { + (tile.getAsMatterNode().graph as MatterNetworkGraph?)?.getMatterStorageMaxLevel() ?: Fraction.ZERO + }) } - Container container = tile != null ? tile.matter_container : new SimpleContainer(2 * 6); + val container = tile?.matterContainer ?: SimpleContainer(2 * 6) - for (int row = 0; row < 2; row++){ - for (int column = 0; column < 6; column++) { - container_slots[row * 6 + column] = new MatterContainerInputSlot(container, row * 6 + column, 44 + column * 18, 20 + row * 18, true, IMatterHandler.MatterDirection.BIDIRECTIONAL); - addSlot(container_slots[row * 6 + column]); + for (row in 0..1) { + for (column in 0..5) { + container_slots[row * 6 + column] = MatterContainerInputSlot( + container, + row * 6 + column, + 44 + column * 18, + 20 + row * 18, + true, + IMatterHandler.MatterDirection.BIDIRECTIONAL + ) + + addSlot(container_slots[row * 6 + column]!!) } } - - addInventorySlots(); + addInventorySlots() } - @Override - protected int getWorkingSlotStart() { - return 0; + override fun getWorkingSlotStart(): Int { + return 0 } - @Override - protected int getWorkingSlotEnd() { - return 2 * 6; + override fun getWorkingSlotEnd(): Int { + return 2 * 6 } -} +} \ No newline at end of file diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/MatterPanelMenu.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/MatterPanelMenu.kt index df3b5ff0d..1ad8167cb 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/MatterPanelMenu.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/MatterPanelMenu.kt @@ -1,214 +1,186 @@ -package ru.dbotthepony.mc.otm.menu; +package ru.dbotthepony.mc.otm.menu -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.entity.player.Inventory; -import net.minecraft.world.entity.player.Player; -import net.minecraftforge.network.PacketDistributor; -import ru.dbotthepony.mc.otm.OverdriveThatMatters; -import ru.dbotthepony.mc.otm.Registry; -import ru.dbotthepony.mc.otm.block.entity.BlockEntityMatterPanel; -import ru.dbotthepony.mc.otm.capability.matter.IMatterGridListener; -import ru.dbotthepony.mc.otm.capability.matter.MatterTask; -import ru.dbotthepony.mc.otm.capability.matter.PatternState; -import ru.dbotthepony.mc.otm.matter.MatterGrid; -import ru.dbotthepony.mc.otm.network.CancelMatterTaskPacket; -import ru.dbotthepony.mc.otm.network.MatterTaskPacket; -import ru.dbotthepony.mc.otm.network.MatteryNetworking; -import ru.dbotthepony.mc.otm.network.PatternGridPacket; +import net.minecraft.server.level.ServerPlayer +import net.minecraft.world.entity.player.Inventory +import net.minecraft.world.entity.player.Player +import net.minecraftforge.network.PacketDistributor +import ru.dbotthepony.mc.otm.OverdriveThatMatters +import ru.dbotthepony.mc.otm.Registry +import ru.dbotthepony.mc.otm.block.entity.BlockEntityMatterPanel +import ru.dbotthepony.mc.otm.capability.matter.MatterTask +import ru.dbotthepony.mc.otm.capability.matter.PatternState +import ru.dbotthepony.mc.otm.graph.matter.IMatterGraphListener +import ru.dbotthepony.mc.otm.graph.matter.MatterNetworkGraph +import ru.dbotthepony.mc.otm.network.CancelMatterTaskPacket +import ru.dbotthepony.mc.otm.network.MatterTaskPacket +import ru.dbotthepony.mc.otm.network.MatteryNetworking +import ru.dbotthepony.mc.otm.network.PatternGridPacket +import java.util.* +import java.util.function.Consumer -import java.util.ArrayList; -import java.util.UUID; -import java.util.function.Consumer; - -public class MatterPanelMenu extends MatteryMenu implements IMatterGridListener { - public MatterPanelMenu(int p_38852_, Inventory inventory) { - this(p_38852_, inventory, null); +class MatterPanelMenu @JvmOverloads constructor( + p_38852_: Int, + inventory: Inventory, + tile: BlockEntityMatterPanel? = null +) : MatteryMenu(Registry.Menus.MATTER_PANEL, p_38852_, inventory, tile), IMatterGraphListener { + fun taskUpdated(task: MatterTask) { + sendNetwork(MatterTaskPacket(true, listOf(task))) } - private BlockEntityMatterPanel tile; - private MatterGrid grid; - - public MatterPanelMenu(int p_38852_, Inventory inventory, BlockEntityMatterPanel tile) { - super(Registry.Menus.MATTER_PANEL, p_38852_, inventory, tile); - this.tile = tile; - - if (tile != null) { - grid = tile.getMatterGrid(); - tile.attachMenu(this); - - if (grid != null) { - grid.attach(this); - } - } - } - - public void taskUpdated(MatterTask task) { - sendNetwork(new MatterTaskPacket(true, task)); - } - - public void taskRemoved(MatterTask task) { - sendNetwork(new MatterTaskPacket(false, task)); + fun taskRemoved(task: MatterTask) { + sendNetwork(MatterTaskPacket(false, listOf(task))) } // client code - public ArrayList patterns = new ArrayList<>(); - public ArrayList tasks = new ArrayList<>(); - public int changeset = 0; + @JvmField + var patterns = ArrayList() - public void networkPatternsUpdated(PatternState[] patterns) { - changeset++; + @JvmField + var tasks = ArrayList() - for (var pattern : patterns) { - var index_of = this.patterns.indexOf(pattern); + var changeset = 0 - if (index_of != -1) { - this.patterns.set(index_of, pattern); + fun networkPatternsUpdated(patterns: Collection) { + changeset++ + + for (pattern in patterns) { + val index = this.patterns.indexOf(pattern) + + if (index != -1) { + this.patterns[index] = pattern } else { - this.patterns.add(pattern); + this.patterns.add(pattern) } } } - public void networkPatternsRemoved(PatternState[] patterns) { - changeset++; + fun networkPatternsRemoved(patterns: Collection) { + changeset++ - for (var pattern : patterns) { - this.patterns.remove(pattern); + for (pattern in patterns) { + this.patterns.remove(pattern) } } - public void networkTasksUpdated(MatterTask[] tasks) { - changeset++; + fun networkTasksUpdated(tasks: Collection) { + changeset++ - for (var task : tasks) { - var index_of = this.tasks.indexOf(task); + for (task in tasks) { + val index = this.tasks.indexOf(task) - if (index_of != -1) { - this.tasks.set(index_of, task); + if (index != -1) { + this.tasks[index] = task } else { - this.tasks.add(task); + this.tasks.add(task) } - if (watcher_update != null) - watcher_update.accept(task); + watcher_update?.accept(task) } } - public void networkTasksRemoved(MatterTask[] tasks) { - changeset++; + fun networkTasksRemoved(tasks: Collection) { + changeset++ - for (var task : tasks) { - this.tasks.remove(task); - - if (watcher_delete != null) - watcher_delete.accept(task); + for (task in tasks) { + this.tasks.remove(task) + watcher_delete?.accept(task) } } - private Consumer watcher_delete; - private Consumer watcher_update; + private var watcher_delete: Consumer? = null + private var watcher_update: Consumer? = null - public void networkTaskWatcher(Consumer watcher_update, Consumer watcher_delete) { - this.watcher_delete = watcher_delete; - this.watcher_update = watcher_update; + fun networkTaskWatcher(watcher_update: Consumer, watcher_delete: Consumer) { + this.watcher_delete = watcher_delete + this.watcher_update = watcher_update } // server code - public void requestReplication(ServerPlayer ply, PatternState state, int how_much) { - if (tile == null) - return; + fun requestReplication(ply: ServerPlayer, state: PatternState, how_much: Int) { + val tile = tile as BlockEntityMatterPanel? ?: return - var grid = tile.getMatterGrid(); + val graph = tile.getAsMatterNode().graph as MatterNetworkGraph? ?: return - if (grid == null) - return; - - var get_pattern = grid.getPattern(state); - - if (get_pattern == null) { - OverdriveThatMatters.LOGGER.error("Received replication request from {} of {}, but it is no longer in grid", ply, state); - return; + if (graph.getPattern(state) == null) { + OverdriveThatMatters.LOGGER.error("Received replication request from {} of {}, but it is no longer in grid", ply, state) + return } - tile.addTask(state, how_much); + tile.addTask(state, how_much) } - public void receiveTaskCancel(ServerPlayer ply, UUID id) { - if (tile == null) - return; - - tile.removeTask(id); + fun receiveTaskCancel(ply: ServerPlayer, id: UUID) { + (tile as BlockEntityMatterPanel?)?.removeTask(id) } - public void requestTaskCancel(UUID id) { - MatteryNetworking.CHANNEL.sendToServer(new CancelMatterTaskPacket(id)); + fun requestTaskCancel(id: UUID) { + MatteryNetworking.CHANNEL.sendToServer(CancelMatterTaskPacket(id)) } - @Override - public void onPatternAdded(PatternState state) { - sendNetwork(new PatternGridPacket(true, state)); + override fun onPatternAdded(state: PatternState) { + sendNetwork(PatternGridPacket(true, listOf(state))) } - @Override - public void onPatternRemoved(PatternState state) { - sendNetwork(new PatternGridPacket(false, state)); + override fun onPatternRemoved(state: PatternState) { + sendNetwork(PatternGridPacket(false, listOf(state))) } - @Override - public void onPatternUpdated(PatternState new_state, PatternState old_state) { - sendNetwork(new PatternGridPacket(true, new_state)); + override fun onPatternUpdated(new_state: PatternState, old_state: PatternState) { + sendNetwork(PatternGridPacket(true, listOf(new_state))) } - private boolean initial_send = false; + private var initial_send = false - @Override - public void removed(Player p_38940_) { - super.removed(p_38940_); + private var listeningGrid: MatterNetworkGraph? = null - if (tile != null) - tile.deatachMenu(this); - - if (grid != null) - grid.detach(this); + init { + if (tile != null) { + listeningGrid = tile.getAsMatterNode().graph as MatterNetworkGraph? + tile.attachMenu(this) + listeningGrid?.addListener(this) + } } - @Override - public void broadcastChanges() { - super.broadcastChanges(); - - if (!initial_send) - fullPatternBroadcast(); + override fun removed(p_38940_: Player) { + super.removed(p_38940_) + (tile as BlockEntityMatterPanel?)?.deatachMenu(this) + listeningGrid?.removeListener(this) } - private void sendNetwork(Object packet) { - MatteryNetworking.CHANNEL.send(PacketDistributor.PLAYER.with(() -> (ServerPlayer) inventory.player), packet); + override fun broadcastChanges() { + super.broadcastChanges() + if (!initial_send) fullPatternBroadcast() } - public void fullPatternBroadcast() { + private fun sendNetwork(packet: Any) { + MatteryNetworking.CHANNEL.send(PacketDistributor.PLAYER.with { inventory.player as ServerPlayer }, packet) + } + + fun fullPatternBroadcast() { if (inventory.player.level.isClientSide) { - initial_send = true; - return; + initial_send = true + return } + val tile = tile as BlockEntityMatterPanel? + if (tile != null) { - var grid = tile.getMatterGrid(); + val grid = tile.getAsMatterNode().graph as MatterNetworkGraph? if (grid != null) { - initial_send = true; - sendNetwork(new PatternGridPacket(true, grid.getStoredPatterns().toArray(new PatternState[0]))); + initial_send = true + sendNetwork(PatternGridPacket(true, grid.getStoredPatterns())) } - sendNetwork(new MatterTaskPacket(true, tile.getAllTasks().toArray(new MatterTask[0]))); + sendNetwork(MatterTaskPacket(true, tile.allTasks)) } } - @Override - protected int getWorkingSlotStart() { - return 0; + override fun getWorkingSlotStart(): Int { + return 0 } - @Override - protected int getWorkingSlotEnd() { - return 0; + override fun getWorkingSlotEnd(): Int { + return 0 } -} +} \ No newline at end of file diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/MatterScannerMenu.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/MatterScannerMenu.kt index bf4695019..736dbab27 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/MatterScannerMenu.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/MatterScannerMenu.kt @@ -11,6 +11,7 @@ import net.minecraft.world.SimpleContainer import net.minecraft.world.item.ItemStack import ru.dbotthepony.mc.otm.Registry import ru.dbotthepony.mc.otm.core.Fraction +import ru.dbotthepony.mc.otm.graph.matter.MatterNetworkGraph import ru.dbotthepony.mc.otm.matter.MatterRegistry import java.math.BigInteger @@ -38,8 +39,8 @@ class MatterScannerMenu @JvmOverloads constructor( if (tile != null) { progress = ProgressGaugeWidget(this, { tile.workProgress.toFloat() }) { tile.cantProcessJob() } patterns = LevelGaugeWidget(this, - { Fraction(tile.matterGrid?.storedPatternCount?.toBigInteger() ?: BigInteger.ZERO) }, - { Fraction(tile.matterGrid?.patternCapacity?.toBigInteger() ?: BigInteger.ZERO) }) + { Fraction(tile.getAsMatterGraph()?.getPatternCount()?.toBigInteger() ?: BigInteger.ZERO) }, + { Fraction(tile.getAsMatterGraph()?.getPatternCapacity()?.toBigInteger() ?: BigInteger.ZERO) }) } else { progress = ProgressGaugeWidget(this) patterns = LevelGaugeWidget(this) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/PatternStorageMenu.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/PatternStorageMenu.kt index d9a3f4ed6..07fa74d41 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/PatternStorageMenu.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/PatternStorageMenu.kt @@ -1,66 +1,55 @@ -package ru.dbotthepony.mc.otm.menu; +package ru.dbotthepony.mc.otm.menu -import net.minecraft.world.Container; -import net.minecraft.world.SimpleContainer; -import net.minecraft.world.entity.player.Inventory; -import ru.dbotthepony.mc.otm.Registry; -import ru.dbotthepony.mc.otm.block.entity.BlockEntityPatternStorage; -import ru.dbotthepony.mc.otm.core.Fraction; -import ru.dbotthepony.mc.otm.menu.slot.PatternSlot; -import ru.dbotthepony.mc.otm.menu.widget.LevelGaugeWidget; +import net.minecraft.world.SimpleContainer +import net.minecraft.world.entity.player.Inventory +import ru.dbotthepony.mc.otm.Registry +import ru.dbotthepony.mc.otm.block.entity.BlockEntityPatternStorage +import ru.dbotthepony.mc.otm.core.Fraction +import ru.dbotthepony.mc.otm.graph.matter.MatterNetworkGraph +import ru.dbotthepony.mc.otm.menu.slot.PatternSlot +import ru.dbotthepony.mc.otm.menu.widget.LevelGaugeWidget -public class PatternStorageMenu extends MatteryMenu { - public PatternStorageMenu(int p_38852_, Inventory inventory) { - this(p_38852_, inventory, null); - } - - public PatternSlot[] pattern_slots = new PatternSlot[2 * 4]; - - public LevelGaugeWidget stored_this; - public LevelGaugeWidget stored_grid; - - public PatternStorageMenu(int p_38852_, Inventory inventory, BlockEntityPatternStorage tile) { - super(Registry.Menus.PATTERN_STORAGE, p_38852_, inventory, tile); +class PatternStorageMenu @JvmOverloads constructor( + p_38852_: Int, + inventory: Inventory?, + tile: BlockEntityPatternStorage? = null +) : MatteryMenu( + Registry.Menus.PATTERN_STORAGE, p_38852_, inventory!!, tile +) { + val pattern_slots = arrayOfNulls(2 * 4) + val stored_this: LevelGaugeWidget + val stored_grid: LevelGaugeWidget + init { if (tile == null) { - stored_this = new LevelGaugeWidget(this); - stored_grid = new LevelGaugeWidget(this); + stored_this = LevelGaugeWidget(this) + stored_grid = LevelGaugeWidget(this) } else { - stored_this = new LevelGaugeWidget(this, tile.getPatternStorage()); - stored_grid = new LevelGaugeWidget(this, () -> { - if (tile.getMatterGrid() != null) { - return new Fraction(tile.getMatterGrid().getStoredPatternCount()); - } - - return Fraction.ZERO; - }, () -> { - if (tile.getMatterGrid() != null) { - return new Fraction(tile.getMatterGrid().getPatternCapacity()); - } - - return Fraction.ZERO; - }); + stored_this = LevelGaugeWidget(this, tile) + stored_grid = LevelGaugeWidget(this, { + Fraction((tile.getAsMatterNode().graph as MatterNetworkGraph?)?.getPatternCount() ?: 0) + }, { + Fraction((tile.getAsMatterNode().graph as MatterNetworkGraph?)?.getPatternCapacity() ?: 0) + }) } - Container patterns = tile != null ? tile.patterns : new SimpleContainer(2 * 4); + val patterns = tile?.patterns ?: SimpleContainer(2 * 4) - for (int row = 0; row < 2; row++) { - for (int column = 0; column < 4; column++) { - pattern_slots[row * 4 + column] = new PatternSlot(patterns, row * 4 + column, 48 + column * 20, 27 + row * 24); - addSlot(pattern_slots[row * 4 + column]); + for (row in 0..1) { + for (column in 0..3) { + pattern_slots[row * 4 + column] = PatternSlot(patterns, row * 4 + column, 48 + column * 20, 27 + row * 24) + addSlot(pattern_slots[row * 4 + column]!!) } } - addInventorySlots(); + addInventorySlots() } - @Override - protected int getWorkingSlotStart() { - return 0; + override fun getWorkingSlotStart(): Int { + return 0 } - @Override - protected int getWorkingSlotEnd() { - return 2 * 4; + override fun getWorkingSlotEnd(): Int { + return 2 * 4 } -} +} \ No newline at end of file diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/data/FractionDataContainer.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/data/FractionDataContainer.kt index 50f8fd8d9..801a20954 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/menu/data/FractionDataContainer.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/menu/data/FractionDataContainer.kt @@ -1,26 +1,47 @@ package ru.dbotthepony.mc.otm.menu.data import net.minecraft.world.inventory.ContainerData +import org.apache.logging.log4j.LogManager import ru.dbotthepony.mc.otm.core.Fraction import ru.dbotthepony.mc.otm.network.NetworkHelper +import java.util.zip.CRC32 class FractionDataContainer : ContainerData { companion object { - const val NETWORK_PAYLOAD_SIZE = 32 + // CRC32 + Данные + const val NETWORK_PAYLOAD_SIZE = 64 + 2 + private val LOGGER = LogManager.getLogger() } private var _value: Fraction? = Fraction.ZERO + private var _value2: Fraction? = Fraction.ZERO fun hasComputedValue(): Boolean { return _value != null } + private var mute = false + var value: Fraction get() { if (_value != null) return _value!! - _value = Fraction.fromByteArray(NetworkHelper.shortsToBytes(buffer)) + val bytes = NetworkHelper.shortsToBytes(buffer, 2) + + val crc = CRC32() + crc.update(bytes) + val crcValue = crc.value + + val a = (crcValue and 0xFFFF).toShort() + val b = ((crcValue and 0xFFFF0000) ushr 16).toShort() + + if (a == buffer[0] && b == buffer[1]) { + _value = Fraction.fromByteArray(bytes) + } else { + _value = _value2 + } + return _value!! } set(value) { @@ -31,7 +52,28 @@ class FractionDataContainer : ContainerData { return } - NetworkHelper.bytesToShorts(_value!!.toByteArray()).copyInto(buffer) + try { + val bytes = ByteArray(128) {0} + _value!!.toByteArray().copyInto(bytes) + + val crc = CRC32() + crc.update(bytes) + val crcValue = crc.value + + val a = (crcValue and 0xFFFF).toShort() + val b = ((crcValue and 0xFFFF0000) ushr 16).toShort() + buffer[0] = a + buffer[1] = b + + NetworkHelper.bytesToShorts(bytes).copyInto(buffer, destinationOffset = 2) + } catch(err: Throwable) { + if (!mute) { + LOGGER.error("Unable to serialize value $value for network transportation", err) + mute = true + } + + buffer.fill(0) + } } val buffer = ShortArray(NETWORK_PAYLOAD_SIZE) @@ -42,6 +84,7 @@ class FractionDataContainer : ContainerData { override operator fun set(p_39285_: Int, p_39286_: Int) { buffer[p_39285_] = p_39286_.toShort() + if (_value != null) _value2 = _value _value = null } diff --git a/src/test/kotlin/ru/dbotthepony/mc/otm/tests/FractionTests.kt b/src/test/kotlin/ru/dbotthepony/mc/otm/tests/FractionTests.kt index f494d7aff..116245957 100644 --- a/src/test/kotlin/ru/dbotthepony/mc/otm/tests/FractionTests.kt +++ b/src/test/kotlin/ru/dbotthepony/mc/otm/tests/FractionTests.kt @@ -4,8 +4,10 @@ import org.junit.jupiter.api.DisplayName import org.junit.jupiter.api.Test import org.junit.jupiter.api.assertThrows import ru.dbotthepony.mc.otm.core.Fraction +import java.lang.Math.floor import java.math.BigDecimal import java.math.BigInteger +import kotlin.random.Random object FractionTests { @Test @@ -113,12 +115,121 @@ object FractionTests { fun math() { assert((Fraction(1) / Fraction(1)) == Fraction(1)) assert((Fraction(2) / Fraction(1)) == Fraction(2, 1)) - assert((Fraction(2) / Fraction(2)) == Fraction(1)) + assert((Fraction(2) / Fraction(2)) == Fraction(1)) { Fraction(2) / Fraction(2) } assert((Fraction(4, 3) / Fraction(5, 4)) == (Fraction(4, 3) * Fraction(4, 5))) assert((Fraction(4, 3) + Fraction(5, 4)) == Fraction(31, 12)) } + @Test + @DisplayName("Fraction compacting") + fun compacting() { + val frac = Fraction("2721280000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "25600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000") + + println("Compacting $frac => ${frac + Fraction.ZERO}") + } + + private val samples = arrayOf( + Fraction(9475, 4729), + Fraction(23535, 58723), + Fraction(-4852, 6859), + Fraction(-45623, -76849), + Fraction(38494, -76849), + Fraction(1043, -648), + ) + + private val samples2 = arrayOf( + (9475.0 / 4729), + (23535.0 / 58723), + (-4852.0 / 6859), + (-45623.0 / -76849), + (38494.0 / -76849), + (1043.0 / -648), + ) + + private val samples3 = arrayOf( + BigDecimal((9475.0 / 4729).toString()), + BigDecimal((23535.0 / 58723).toString()), + BigDecimal((-4852.0 / 6859).toString()), + BigDecimal((-45623.0 / -76849).toString()), + BigDecimal((38494.0 / -76849).toString()), + BigDecimal((1043.0 / -648).toString()), + ) + + @Test + @DisplayName("Fraction performance measurement") + fun performance() { + val rand = java.util.Random() + val blackHole = arrayOfNulls(100_000) + val size = samples.size + var time = System.currentTimeMillis() + + for (i in 0 until 100_000) { + when (rand.nextInt(3)) { + 0 -> blackHole[i] = samples[rand.nextInt(size)] + samples[rand.nextInt(size)] + 1 -> blackHole[i] = samples[rand.nextInt(size)] - samples[rand.nextInt(size)] + 2 -> blackHole[i] = samples[rand.nextInt(size)] * samples[rand.nextInt(size)] + // 3 -> blackHole[i] = samples[rand.nextInt(size)] / samples[rand.nextInt(size)] + } + } + + println("Mean time for Fraction operation is ~${System.currentTimeMillis() - time} ms per 100,000 ops") + + var sum = Fraction.ZERO + + // перемешаем чтоб оптимизатор не отбросил + for (i in 0 until size) { + sum += blackHole[i]!! + blackHole[i] = blackHole[rand.nextInt(size)] + } + + val blackHole2 = arrayOfNulls(100_000) + time = System.currentTimeMillis() + + for (i in 0 until 100_000) { + when (rand.nextInt(3)) { + 0 -> blackHole2[i] = samples2[rand.nextInt(size)] + samples2[rand.nextInt(size)] + 1 -> blackHole2[i] = samples2[rand.nextInt(size)] - samples2[rand.nextInt(size)] + 2 -> blackHole2[i] = samples2[rand.nextInt(size)] * samples2[rand.nextInt(size)] + // 3 -> blackHole2[i] = samples2[rand.nextInt(size)] / samples2[rand.nextInt(size)] + } + } + + println("Mean time for Double operation is ~${System.currentTimeMillis() - time} ms per 100,000 ops") + + val blackHole3 = arrayOfNulls(100_000) + time = System.currentTimeMillis() + + for (i in 0 until 100_000) { + when (rand.nextInt(3)) { + 0 -> blackHole3[i] = samples3[rand.nextInt(size)] + samples3[rand.nextInt(size)] + 1 -> blackHole3[i] = samples3[rand.nextInt(size)] - samples3[rand.nextInt(size)] + 2 -> blackHole3[i] = samples3[rand.nextInt(size)] * samples3[rand.nextInt(size)] + // 3 -> blackHole2[i] = samples2[rand.nextInt(size)] / samples2[rand.nextInt(size)] + } + } + + println("Mean time for BigDecimal operation is ~${System.currentTimeMillis() - time} ms per 100,000 ops") + + var sum2 = 0.0 + + // перемешаем чтоб оптимизатор не отбросил + for (i in 0 until size) { + sum2 += blackHole2[i]!! + blackHole2[i] = blackHole2[rand.nextInt(size)] + } + + var sum3 = 0.0 + + // перемешаем чтоб оптимизатор не отбросил + for (i in 0 until size) { + sum3 += blackHole2[i]!! + blackHole3[i] = blackHole3[rand.nextInt(size)] + } + + println("$sum $sum2 $sum3") + } + @Test @DisplayName("Fraction serialization test") fun serialization() { @@ -146,6 +257,26 @@ object FractionTests { serialized = value.serializeNBT() assert(value.compareTo(Fraction.deserializeNBT(serialized)) == 0) + + value = Fraction("320", "100") + serialized = value.serializeNBT() + assert(value.compareTo(Fraction.deserializeNBT(serialized)) == 0) + + value = Fraction("324", "100") + serialized = value.serializeNBT() + assert(value.compareTo(Fraction.deserializeNBT(serialized)) == 0) + + value = Fraction("328", "100") + serialized = value.serializeNBT() + assert(value.compareTo(Fraction.deserializeNBT(serialized)) == 0) + + value = Fraction("332", "100") + serialized = value.serializeNBT() + assert(value.compareTo(Fraction.deserializeNBT(serialized)) == 0) + + value = Fraction("336", "100") + serialized = value.serializeNBT() + assert(value.compareTo(Fraction.deserializeNBT(serialized)) == 0) } @Test