diff --git a/src/main/java/com/simibubi/create/content/logistics/factoryBoard/FactoryPanelBehaviour.java b/src/main/java/com/simibubi/create/content/logistics/factoryBoard/FactoryPanelBehaviour.java index b4be349956..ae481e41f5 100644 --- a/src/main/java/com/simibubi/create/content/logistics/factoryBoard/FactoryPanelBehaviour.java +++ b/src/main/java/com/simibubi/create/content/logistics/factoryBoard/FactoryPanelBehaviour.java @@ -190,30 +190,19 @@ public static FactoryPanelSupportBehaviour linkAt(BlockAndTintGetter world, Fact } public void moveTo(FactoryPanelPosition newPos, ServerPlayer player) { - Level level = getWorld(); - BlockState existingState = level.getBlockState(newPos.pos()); - - // Check if target pos is valid - if (FactoryPanelBehaviour.at(level, newPos) != null) + if (!Create.LOGISTICS.mayInteract(network, player)) return; - boolean isAddedToOtherGauge = AllBlocks.FACTORY_GAUGE.has(existingState); - if (!existingState.isAir() && !isAddedToOtherGauge) + if (!mayModifyConnectedPanels(player)) return; - if (isAddedToOtherGauge && existingState != blockEntity.getBlockState()) + if (!canMoveTo(newPos)) return; + + Level level = getWorld(); + BlockState existingState = level.getBlockState(newPos.pos()); + boolean isAddedToOtherGauge = AllBlocks.FACTORY_GAUGE.has(existingState); if (!isAddedToOtherGauge) level.setBlock(newPos.pos(), blockEntity.getBlockState(), Block.UPDATE_ALL); - for (BlockPos blockPos : targetedByLinks.keySet()) - if (!blockPos.closerThan(newPos.pos(), 24)) - return; - for (FactoryPanelPosition blockPos : targetedBy.keySet()) - if (!blockPos.pos().closerThan(newPos.pos(), 24)) - return; - for (FactoryPanelPosition blockPos : targeting) - if (!blockPos.pos().closerThan(newPos.pos(), 24)) - return; - // Disconnect links for (BlockPos pos : targetedByLinks.keySet()) { FactoryPanelSupportBehaviour at = linkAt(level, new FactoryPanelPosition(pos, slot)); @@ -278,6 +267,62 @@ public void moveTo(FactoryPanelPosition newPos, ServerPlayer player) { .playSound(null, newPos.pos(), SoundEvents.COPPER_BREAK, SoundSource.BLOCKS, 1.0f, 1.0f); } + private boolean canMoveTo(FactoryPanelPosition newPos) { + Level level = getWorld(); + BlockState currentState = blockEntity.getBlockState(); + BlockState existingState = level.getBlockState(newPos.pos()); + + if (FactoryPanelBehaviour.at(level, newPos) != null) + return false; + boolean isAddedToOtherGauge = AllBlocks.FACTORY_GAUGE.has(existingState); + if (!existingState.isAir() && !isAddedToOtherGauge) + return false; + if (isAddedToOtherGauge && existingState != currentState) + return false; + + BlockPos diff = newPos.pos() + .subtract(getPos()); + Direction facing = FactoryPanelBlock.connectedDirection(currentState); + if (facing.getAxis() + .choose(diff.getX(), diff.getY(), diff.getZ()) != 0) + return false; + if (!AllBlocks.FACTORY_GAUGE.get() + .canSurvive(currentState, level, newPos.pos())) + return false; + if (AllBlocks.PACKAGER.has(level.getBlockState(newPos.pos() + .relative(facing.getOpposite())))) + return false; + + for (BlockPos blockPos : targetedByLinks.keySet()) + if (!blockPos.closerThan(newPos.pos(), 24)) + return false; + for (FactoryPanelPosition blockPos : targetedBy.keySet()) + if (!blockPos.pos() + .closerThan(newPos.pos(), 24)) + return false; + for (FactoryPanelPosition blockPos : targeting) + if (!blockPos.pos() + .closerThan(newPos.pos(), 24)) + return false; + + return true; + } + + private boolean mayModifyConnectedPanels(ServerPlayer player) { + Level level = getWorld(); + for (FactoryPanelPosition position : targeting) { + FactoryPanelBehaviour at = at(level, position); + if (at != null && !Create.LOGISTICS.mayInteract(at.network, player)) + return false; + } + for (FactoryPanelPosition position : targetedBy.keySet()) { + FactoryPanelBehaviour at = at(level, position); + if (at != null && !Create.LOGISTICS.mayInteract(at.network, player)) + return false; + } + return true; + } + private void moveToSlot(PanelSlot slot) { this.slot = slot; if (this.getSlotPositioning() instanceof FactoryPanelSlotPositioning fpsp) diff --git a/src/main/java/com/simibubi/create/content/logistics/factoryBoard/FactoryPanelConfigurationPacket.java b/src/main/java/com/simibubi/create/content/logistics/factoryBoard/FactoryPanelConfigurationPacket.java index 2a27072684..01ba666802 100644 --- a/src/main/java/com/simibubi/create/content/logistics/factoryBoard/FactoryPanelConfigurationPacket.java +++ b/src/main/java/com/simibubi/create/content/logistics/factoryBoard/FactoryPanelConfigurationPacket.java @@ -8,6 +8,7 @@ import org.jetbrains.annotations.Nullable; import com.simibubi.create.AllPackets; +import com.simibubi.create.Create; import com.simibubi.create.foundation.networking.BlockEntityConfigurationPacket; import net.createmod.catnip.codecs.stream.CatnipLargerStreamCodecs; @@ -68,9 +69,20 @@ public PacketTypeProvider getTypeProvider() { @Override protected void applySettings(ServerPlayer player, FactoryPanelBlockEntity be) { - FactoryPanelBehaviour behaviour = be.panels.get(position.slot()); + FactoryPanelBehaviour behaviour = FactoryPanelBehaviour.at(be.getLevel(), position); if (behaviour == null) return; + if (!Create.LOGISTICS.mayInteract(behaviour.network, player)) + return; + if (reset && !mayModifyConnectedPanels(player, behaviour)) + return; + + FactoryPanelBehaviour source = null; + if (removeConnection != null) { + source = FactoryPanelBehaviour.at(be.getLevel(), removeConnection); + if (source != null && !Create.LOGISTICS.mayInteract(source.network, player)) + return; + } behaviour.recipeAddress = reset ? "" : address; behaviour.recipeOutput = reset ? 1 : outputAmount; @@ -102,7 +114,6 @@ protected void applySettings(ServerPlayer player, FactoryPanelBlockEntity be) { if (removeConnection != null) { behaviour.targetedBy.remove(removeConnection); - FactoryPanelBehaviour source = FactoryPanelBehaviour.at(be.getLevel(), removeConnection); if (source != null) { source.targeting.remove(behaviour.getPanelPosition()); source.blockEntity.sendData(); @@ -114,4 +125,18 @@ protected void applySettings(ServerPlayer player, FactoryPanelBlockEntity be) { be.notifyUpdate(); } + + private static boolean mayModifyConnectedPanels(ServerPlayer player, FactoryPanelBehaviour behaviour) { + for (FactoryPanelConnection connection : behaviour.targetedBy.values()) { + FactoryPanelBehaviour source = FactoryPanelBehaviour.at(behaviour.getWorld(), connection); + if (source != null && !Create.LOGISTICS.mayInteract(source.network, player)) + return false; + } + for (FactoryPanelPosition position : behaviour.targeting) { + FactoryPanelBehaviour target = FactoryPanelBehaviour.at(behaviour.getWorld(), position); + if (target != null && !Create.LOGISTICS.mayInteract(target.network, player)) + return false; + } + return true; + } } diff --git a/src/main/java/com/simibubi/create/content/logistics/factoryBoard/FactoryPanelConnectionPacket.java b/src/main/java/com/simibubi/create/content/logistics/factoryBoard/FactoryPanelConnectionPacket.java index ba0db7e06d..9bb828ccbd 100644 --- a/src/main/java/com/simibubi/create/content/logistics/factoryBoard/FactoryPanelConnectionPacket.java +++ b/src/main/java/com/simibubi/create/content/logistics/factoryBoard/FactoryPanelConnectionPacket.java @@ -1,12 +1,17 @@ package com.simibubi.create.content.logistics.factoryBoard; import com.simibubi.create.AllPackets; +import com.simibubi.create.Create; +import com.simibubi.create.foundation.block.WrenchableDirectionalBlock; import com.simibubi.create.foundation.networking.BlockEntityConfigurationPacket; import io.netty.buffer.ByteBuf; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; import net.minecraft.network.codec.ByteBufCodecs; import net.minecraft.network.codec.StreamCodec; import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.level.block.state.BlockState; public class FactoryPanelConnectionPacket extends BlockEntityConfigurationPacket { public static final StreamCodec STREAM_CODEC = StreamCodec.composite( @@ -18,7 +23,7 @@ public class FactoryPanelConnectionPacket extends BlockEntityConfigurationPacket private final FactoryPanelPosition fromPos; private final FactoryPanelPosition toPos; - private boolean relocate; + private final boolean relocate; public FactoryPanelConnectionPacket(FactoryPanelPosition fromPos, FactoryPanelPosition toPos, boolean relocate) { super(toPos.pos()); @@ -35,11 +40,89 @@ public PacketTypeProvider getTypeProvider() { @Override protected void applySettings(ServerPlayer player, FactoryPanelBlockEntity be) { FactoryPanelBehaviour behaviour = FactoryPanelBehaviour.at(be.getLevel(), toPos); - if (behaviour != null) - if (relocate) - behaviour.moveTo(fromPos, player); - else - behaviour.addConnection(fromPos); + if (behaviour == null) + return; + if (!mayInteract(player, behaviour)) + return; + + if (relocate) { + if (!player.canInteractWithBlock(fromPos.pos(), maxRange())) + return; + behaviour.moveTo(fromPos, player); + return; + } + + FactoryPanelBehaviour panel = FactoryPanelBehaviour.at(be.getLevel(), fromPos); + if (panel != null) { + if (!mayInteract(player, panel)) + return; + if (!canConnect(behaviour, panel)) + return; + behaviour.addConnection(fromPos); + return; + } + + FactoryPanelSupportBehaviour link = FactoryPanelBehaviour.linkAt(be.getLevel(), fromPos); + if (link == null) + return; + if (!canConnect(behaviour, link)) + return; + behaviour.addConnection(fromPos); + } + + private static boolean mayInteract(ServerPlayer player, FactoryPanelBehaviour behaviour) { + return Create.LOGISTICS.mayInteract(behaviour.network, player); + } + + private static boolean canConnect(FactoryPanelBehaviour from, FactoryPanelBehaviour to) { + if (from.targetedBy.containsKey(to.getPanelPosition())) + return false; + if (from.targetedBy.size() >= 9) + return false; + + BlockState state1 = to.blockEntity.getBlockState(); + BlockState state2 = from.blockEntity.getBlockState(); + BlockPos diff = to.getPos() + .subtract(from.getPos()); + + if (state1.setValue(FactoryPanelBlock.WATERLOGGED, false) + .setValue(FactoryPanelBlock.POWERED, false) != state2.setValue(FactoryPanelBlock.WATERLOGGED, false) + .setValue(FactoryPanelBlock.POWERED, false)) + return false; + + if (FactoryPanelBlock.connectedDirection(state1) + .getAxis() + .choose(diff.getX(), diff.getY(), diff.getZ()) != 0) + return false; + + if (!diff.closerThan(BlockPos.ZERO, 16)) + return false; + + if (to.panelBE().restocker) + return false; + + return !to.getFilter() + .isEmpty() + && !from.getFilter() + .isEmpty(); + } + + private static boolean canConnect(FactoryPanelBehaviour from, FactoryPanelSupportBehaviour to) { + BlockState state1 = from.blockEntity.getBlockState(); + BlockState state2 = to.blockEntity.getBlockState(); + BlockPos diff = to.getPos() + .subtract(from.getPos()); + Direction connectedDirection = FactoryPanelBlock.connectedDirection(state1); + + if (connectedDirection != state2.getOptionalValue(WrenchableDirectionalBlock.FACING) + .orElse(connectedDirection)) + return false; + + if (connectedDirection.getAxis() + .choose(diff.getX(), diff.getY(), diff.getZ()) != 0) + return false; + + return diff.closerThan(BlockPos.ZERO, 16); } @Override diff --git a/src/main/java/com/simibubi/create/content/logistics/redstoneRequester/RedstoneRequesterConfigurationPacket.java b/src/main/java/com/simibubi/create/content/logistics/redstoneRequester/RedstoneRequesterConfigurationPacket.java index b33c9b68b9..6d6373ec5d 100644 --- a/src/main/java/com/simibubi/create/content/logistics/redstoneRequester/RedstoneRequesterConfigurationPacket.java +++ b/src/main/java/com/simibubi/create/content/logistics/redstoneRequester/RedstoneRequesterConfigurationPacket.java @@ -43,6 +43,9 @@ public PacketTypeProvider getTypeProvider() { @Override protected void applySettings(ServerPlayer player, RedstoneRequesterBlockEntity be) { + if (!be.behaviour.mayInteract(player)) + return; + be.encodedTargetAdress = address; List stacks = be.encodedRequest.stacks(); for (int i = 0; i < stacks.size() && i < amounts.size(); i++) { diff --git a/src/main/java/com/simibubi/create/content/logistics/stockTicker/LogisticalStockRequestPacket.java b/src/main/java/com/simibubi/create/content/logistics/stockTicker/LogisticalStockRequestPacket.java index 3e122b71a5..4160819f7c 100644 --- a/src/main/java/com/simibubi/create/content/logistics/stockTicker/LogisticalStockRequestPacket.java +++ b/src/main/java/com/simibubi/create/content/logistics/stockTicker/LogisticalStockRequestPacket.java @@ -23,6 +23,9 @@ public PacketTypeProvider getTypeProvider() { @Override protected void applySettings(ServerPlayer player, StockCheckingBlockEntity be) { + if (!be.behaviour.mayInteract(player)) + return; + be.getRecentSummary() .divideAndSendTo(player, pos); } diff --git a/src/main/java/com/simibubi/create/content/logistics/stockTicker/PackageOrderRequestPacket.java b/src/main/java/com/simibubi/create/content/logistics/stockTicker/PackageOrderRequestPacket.java index c18190369c..2c933e2e75 100644 --- a/src/main/java/com/simibubi/create/content/logistics/stockTicker/PackageOrderRequestPacket.java +++ b/src/main/java/com/simibubi/create/content/logistics/stockTicker/PackageOrderRequestPacket.java @@ -41,6 +41,9 @@ public PacketTypeProvider getTypeProvider() { @Override protected void applySettings(ServerPlayer player, StockTickerBlockEntity be) { + if (!be.behaviour.mayInteract(player)) + return; + if (encodeRequester) { if (!order.isEmpty()) AllSoundEvents.CONFIRM.playOnServer(be.getLevel(), pos); diff --git a/src/main/java/com/simibubi/create/content/logistics/stockTicker/StockKeeperCategoryEditPacket.java b/src/main/java/com/simibubi/create/content/logistics/stockTicker/StockKeeperCategoryEditPacket.java index ba3de1efa3..024f7f210c 100644 --- a/src/main/java/com/simibubi/create/content/logistics/stockTicker/StockKeeperCategoryEditPacket.java +++ b/src/main/java/com/simibubi/create/content/logistics/stockTicker/StockKeeperCategoryEditPacket.java @@ -32,6 +32,9 @@ public PacketTypeProvider getTypeProvider() { @Override protected void applySettings(ServerPlayer player, StockTickerBlockEntity be) { + if (!be.behaviour.mayInteract(player)) + return; + be.categories = schedule; be.notifyUpdate(); } diff --git a/src/main/java/com/simibubi/create/content/logistics/stockTicker/StockKeeperCategoryHidingPacket.java b/src/main/java/com/simibubi/create/content/logistics/stockTicker/StockKeeperCategoryHidingPacket.java index 331036924a..ee14342919 100644 --- a/src/main/java/com/simibubi/create/content/logistics/stockTicker/StockKeeperCategoryHidingPacket.java +++ b/src/main/java/com/simibubi/create/content/logistics/stockTicker/StockKeeperCategoryHidingPacket.java @@ -33,6 +33,9 @@ public PacketTypeProvider getTypeProvider() { @Override protected void applySettings(ServerPlayer player, StockTickerBlockEntity be) { + if (!be.behaviour.mayInteract(player)) + return; + if (indices.isEmpty()) { be.hiddenCategoriesByPlayer.remove(player.getUUID()); } else { diff --git a/src/main/java/com/simibubi/create/content/logistics/stockTicker/StockKeeperCategoryRefundPacket.java b/src/main/java/com/simibubi/create/content/logistics/stockTicker/StockKeeperCategoryRefundPacket.java index efd77d30ee..bc8b7f6380 100644 --- a/src/main/java/com/simibubi/create/content/logistics/stockTicker/StockKeeperCategoryRefundPacket.java +++ b/src/main/java/com/simibubi/create/content/logistics/stockTicker/StockKeeperCategoryRefundPacket.java @@ -31,9 +31,21 @@ public PacketTypeProvider getTypeProvider() { @Override protected void applySettings(ServerPlayer player, StockTickerBlockEntity be) { - if (!filter.isEmpty() && filter.getItem() instanceof FilterItem) + if (!be.behaviour.mayInteract(player)) + return; + if (filter.isEmpty() || !(filter.getItem() instanceof FilterItem)) + return; + + for (int i = 0; i < be.categories.size(); i++) { + ItemStack category = be.categories.get(i); + if (!ItemStack.isSameItemSameComponents(category, filter)) + continue; + be.categories.remove(i); + be.notifyUpdate(); player.getInventory() - .placeItemBackInInventory(filter); + .placeItemBackInInventory(category.copy()); + return; + } } }