实现卓越物品接口物品传输

This commit is contained in:
Light_Quanta 2025-06-21 00:48:18 +08:00
parent 082a33dc50
commit 1f5841da89
No known key found for this signature in database
GPG key ID: 11A39A1B8C890959
3 changed files with 68 additions and 94 deletions

View file

@ -4,10 +4,12 @@ import com.atsuishio.superbwarfare.block.entity.SuperbItemInterfaceBlockEntity;
import com.atsuishio.superbwarfare.init.ModBlockEntities; import com.atsuishio.superbwarfare.init.ModBlockEntities;
import com.mojang.serialization.MapCodec; import com.mojang.serialization.MapCodec;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.world.Containers; import net.minecraft.world.Containers;
import net.minecraft.world.InteractionResult; import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.player.Player;
import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.item.context.BlockPlaceContext;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.BaseEntityBlock; import net.minecraft.world.level.block.BaseEntityBlock;
import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Block;
@ -21,6 +23,7 @@ import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition; import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.BlockStateProperties; import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import net.minecraft.world.level.block.state.properties.BooleanProperty; import net.minecraft.world.level.block.state.properties.BooleanProperty;
import net.minecraft.world.level.block.state.properties.DirectionProperty;
import net.minecraft.world.level.material.MapColor; import net.minecraft.world.level.material.MapColor;
import net.minecraft.world.level.pathfinder.PathComputationType; import net.minecraft.world.level.pathfinder.PathComputationType;
import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.BlockHitResult;
@ -33,13 +36,17 @@ public class SuperbItemInterfaceBlock extends BaseEntityBlock {
public static final BooleanProperty ENABLED = BlockStateProperties.ENABLED; public static final BooleanProperty ENABLED = BlockStateProperties.ENABLED;
public static final DirectionProperty FACING = DirectionProperty.create("facing");
public SuperbItemInterfaceBlock() { public SuperbItemInterfaceBlock() {
this(BlockBehaviour.Properties.of().mapColor(MapColor.STONE).requiresCorrectToolForDrops().strength(3.0F, 4.8F).sound(SoundType.METAL)); this(BlockBehaviour.Properties.of().mapColor(MapColor.STONE).requiresCorrectToolForDrops().strength(3.0F, 4.8F).sound(SoundType.METAL));
} }
public SuperbItemInterfaceBlock(BlockBehaviour.Properties properties) { public SuperbItemInterfaceBlock(BlockBehaviour.Properties properties) {
super(properties); super(properties);
this.registerDefaultState(this.stateDefinition.any().setValue(ENABLED, true)); this.registerDefaultState(this.stateDefinition.any().setValue(ENABLED, true));
this.registerDefaultState(this.stateDefinition.any().setValue(FACING, Direction.DOWN));
} }
@Nullable @Nullable
@ -55,15 +62,14 @@ public class SuperbItemInterfaceBlock extends BaseEntityBlock {
return pLevel.isClientSide ? null : createTickerHelper(pBlockEntityType, ModBlockEntities.SUPERB_ITEM_INTERFACE.get(), SuperbItemInterfaceBlockEntity::serverTick); return pLevel.isClientSide ? null : createTickerHelper(pBlockEntityType, ModBlockEntities.SUPERB_ITEM_INTERFACE.get(), SuperbItemInterfaceBlockEntity::serverTick);
} }
// @Override @Nullable
// public void setPlacedBy(@NotNull Level pLevel, @NotNull BlockPos pPos, @NotNull BlockState pState, LivingEntity pPlacer, ItemStack pStack) { @Override
// if (pStack.get(DataComponents.CUSTOM_NAME) != null) { public BlockState getStateForPlacement(@NotNull BlockPlaceContext context) {
// BlockEntity blockentity = pLevel.getBlockEntity(pPos); Direction direction = context.getClickedFace().getOpposite();
// if (blockentity instanceof SuperbItemInterfaceBlockEntity entity) { return this.defaultBlockState()
// entity.setCustomName(pStack.getHoverName()); .setValue(FACING, direction)
// } .setValue(ENABLED, true);
// } }
// }
@Override @Override
public void onPlace(BlockState pState, @NotNull Level pLevel, @NotNull BlockPos pPos, BlockState pOldState, boolean pIsMoving) { public void onPlace(BlockState pState, @NotNull Level pLevel, @NotNull BlockPos pPos, BlockState pOldState, boolean pIsMoving) {
@ -137,7 +143,7 @@ public class SuperbItemInterfaceBlock extends BaseEntityBlock {
@Override @Override
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> pBuilder) { protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> pBuilder) {
pBuilder.add(ENABLED); pBuilder.add(ENABLED).add(FACING);
} }
@Override @Override

View file

@ -1,5 +1,6 @@
package com.atsuishio.superbwarfare.block.entity; package com.atsuishio.superbwarfare.block.entity;
import com.atsuishio.superbwarfare.block.SuperbItemInterfaceBlock;
import com.atsuishio.superbwarfare.init.ModBlockEntities; import com.atsuishio.superbwarfare.init.ModBlockEntities;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction; import net.minecraft.core.Direction;
@ -9,110 +10,80 @@ import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
import net.minecraft.world.Container; import net.minecraft.world.Container;
import net.minecraft.world.ContainerHelper; import net.minecraft.world.ContainerHelper;
import net.minecraft.world.WorldlyContainer; import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.player.Player;
import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.HopperBlock;
import net.minecraft.world.level.block.entity.BaseContainerBlockEntity; import net.minecraft.world.level.block.entity.BaseContainerBlockEntity;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.AABB;
import net.neoforged.neoforge.capabilities.Capabilities;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import javax.annotation.ParametersAreNonnullByDefault; import javax.annotation.ParametersAreNonnullByDefault;
import java.util.function.BooleanSupplier;
import java.util.stream.IntStream;
public class SuperbItemInterfaceBlockEntity extends BaseContainerBlockEntity { public class SuperbItemInterfaceBlockEntity extends BaseContainerBlockEntity {
public static final int MOVE_ITEM_SPEED = 64; public static final int TRANSFER_COOLDOWN = 20;
public static final int CONTAINER_SIZE = 5; public static final int CONTAINER_SIZE = 5;
private NonNullList<ItemStack> items = NonNullList.withSize(CONTAINER_SIZE, ItemStack.EMPTY); private NonNullList<ItemStack> items = NonNullList.withSize(CONTAINER_SIZE, ItemStack.EMPTY);
private int cooldownTime = -1; private int cooldownTime = -1;
private long tickedGameTime;
private Direction facing;
public SuperbItemInterfaceBlockEntity(BlockPos pPos, BlockState pBlockState) { public SuperbItemInterfaceBlockEntity(BlockPos pPos, BlockState pBlockState) {
super(ModBlockEntities.SUPERB_ITEM_INTERFACE.get(), pPos, pBlockState); super(ModBlockEntities.SUPERB_ITEM_INTERFACE.get(), pPos, pBlockState);
this.facing = pBlockState.getValue(SuperbItemInterfaceBlock.FACING);
} }
public static void serverTick(Level level, BlockPos pos, BlockState state, SuperbItemInterfaceBlockEntity blockEntity) { public static void serverTick(Level level, BlockPos pos, BlockState state, SuperbItemInterfaceBlockEntity blockEntity) {
--blockEntity.cooldownTime; --blockEntity.cooldownTime;
blockEntity.tickedGameTime = level.getGameTime(); if (blockEntity.isOnCooldown()) return;
if (!blockEntity.isOnCooldown()) { blockEntity.setCooldown(TRANSFER_COOLDOWN);
blockEntity.setCooldown(0);
// tryMoveItems(level, pos, state, blockEntity, () -> suckInItems(level, blockEntity)); if (blockEntity.isEmpty()) return;
// find entities
var x = pos.getX() + blockEntity.facing.getStepX();
var y = pos.getY() + blockEntity.facing.getStepY();
var z = pos.getZ() + blockEntity.facing.getStepZ();
var list = level.getEntities(
(Entity) null,
new AABB(x - 0.5, y - 0.5, z - 0.5, x + 0.5, y + 0.5, z + 0.5),
entity -> entity.getCapability(Capabilities.ItemHandler.ENTITY, null) != null
);
if (list.isEmpty()) return;
var target = list.get(level.random.nextInt(list.size()));
// item transfer
var index = -1;
for (int i = 0; i < blockEntity.items.size(); i++) {
var stack = blockEntity.items.get(i);
if (!stack.isEmpty()) {
index = i;
break;
} }
} }
if (index == -1) return;
var stack = blockEntity.items.get(index);
var itemHandler = target.getCapability(Capabilities.ItemHandler.ENTITY, null);
assert itemHandler != null;
for (int i = 0; i < itemHandler.getSlots(); i++) {
if (stack.isEmpty()) break;
stack = itemHandler.insertItem(i, stack, false);
}
private static boolean tryMoveItems(Level pLevel, BlockPos pPos, BlockState pState, SuperbItemInterfaceBlockEntity pBlockEntity, BooleanSupplier pValidator) { blockEntity.items.set(index, stack);
if (!pLevel.isClientSide) { blockEntity.setChanged();
if (!pBlockEntity.isOnCooldown() && pState.getValue(HopperBlock.ENABLED)) {
boolean flag = false;
if (!pBlockEntity.isEmpty()) {
flag = ejectItems(pLevel, pPos, pState, pBlockEntity);
}
if (!pBlockEntity.inventoryFull()) {
flag |= pValidator.getAsBoolean();
}
if (flag) {
pBlockEntity.setCooldown(8);
setChanged(pLevel, pPos, pState);
return true;
}
}
}
return false;
}
private static boolean ejectItems(Level pLevel, BlockPos pPos, BlockState pState, SuperbItemInterfaceBlockEntity pSourceContainer) {
// if (net.minecraftforge.items.VanillaInventoryCodeHooks.insertHook(pSourceContainer)) return true;
// Container container = getAttachedContainer(pLevel, pPos, pState);
// if (container == null) {
// return false;
// } else {
// TODO 替换成开启吸物品的directions
// Direction direction = pState.getValue(HopperBlock.FACING).getOpposite();
// if (!isFullContainer(container, direction)) {
// for (int i = 0; i < pSourceContainer.getContainerSize(); ++i) {
// if (!pSourceContainer.getItem(i).isEmpty()) {
// ItemStack itemstack = pSourceContainer.getItem(i).copy();
// ItemStack itemstack1 = addItem(pSourceContainer, container, pSourceContainer.removeItem(i, 1), direction);
// if (itemstack1.isEmpty()) {
// container.setChanged();
// return true;
// }
//
// pSourceContainer.setItem(i, itemstack);
// }
// }
// }
return false;
// }
}
private static IntStream getSlots(Container pContainer, Direction pDirection) {
return pContainer instanceof WorldlyContainer ? IntStream.of(((WorldlyContainer) pContainer).getSlotsForFace(pDirection)) : IntStream.range(0, pContainer.getContainerSize());
}
private static boolean isFullContainer(Container pContainer, Direction pDirection) {
return getSlots(pContainer, pDirection).allMatch((p_59379_) -> {
ItemStack itemstack = pContainer.getItem(p_59379_);
return itemstack.getCount() >= itemstack.getMaxStackSize();
});
}
private boolean inventoryFull() {
for (ItemStack itemstack : this.items) {
if (itemstack.isEmpty() || itemstack.getCount() != itemstack.getMaxStackSize()) {
return false;
}
}
return true;
} }
@Override @Override
@ -139,6 +110,7 @@ public class SuperbItemInterfaceBlockEntity extends BaseContainerBlockEntity {
return Component.translatable("container.superbwarfare.superb_item_interface"); return Component.translatable("container.superbwarfare.superb_item_interface");
} }
// TODO 实现菜单
@Override @Override
protected @NotNull AbstractContainerMenu createMenu(int pContainerId, @NotNull Inventory pInventory) { protected @NotNull AbstractContainerMenu createMenu(int pContainerId, @NotNull Inventory pInventory) {
return null; return null;
@ -151,13 +123,7 @@ public class SuperbItemInterfaceBlockEntity extends BaseContainerBlockEntity {
@Override @Override
public boolean isEmpty() { public boolean isEmpty() {
for (ItemStack itemstack : this.items) { return this.items.stream().allMatch(ItemStack::isEmpty);
if (!itemstack.isEmpty()) {
return false;
}
}
return true;
} }
@Override @Override
@ -201,10 +167,6 @@ public class SuperbItemInterfaceBlockEntity extends BaseContainerBlockEntity {
return this.cooldownTime > 0; return this.cooldownTime > 0;
} }
public long getLastUpdateTime() {
return this.tickedGameTime;
}
@Override @Override
protected @NotNull NonNullList<ItemStack> getItems() { protected @NotNull NonNullList<ItemStack> getItems() {
return this.items; return this.items;

View file

@ -102,5 +102,11 @@ public class ModCapabilities {
(obj, ctx) -> obj.getEnergyStorage() (obj, ctx) -> obj.getEnergyStorage()
); );
// 卓越物品接口
event.registerBlockEntity(Capabilities.ItemHandler.BLOCK,
ModBlockEntities.SUPERB_ITEM_INTERFACE.get(),
(object, context) -> new InvWrapper(object)
);
} }
} }