箱子就是箱子

箱子就是箱子

为原版箱子、木桶及类似容器,以及一些模组对应物提供新功能,让它们更具沉浸感且更有趣。

游戏机制

你是否想过,为什么箱子打开时,物品不会掉进去? ……好吧,我承认,在产生这个想法之前我也没想过。但仔细想想…… 这很合理,对吧?

所以现在,你可以自豪地说箱子就是箱子!享受物品掉进你的存储容器中, 而不是傻乎乎地手动放进去的乐趣吧!

但既然物品可以掉进一个打开的箱子……如果箱子在正确的方向打开, 它们不也应该能从中掉下来吗? 因此,你可以让木桶在朝下打开时,将所有内容物倾倒到地面上!

回到箱子的话题,如果你能打开盖子让物品掉进去,那么盖子打开时难道不应该把物品甩出去吗? 没错!有了这个模组,你可以让箱子在打开时将站在其上的所有物品甩飞! (仅限物品,以保全性命)

最后但同样重要的一点,既然到目前为止打开容器一直只是手动操作, 为了让你能够自动化这些新功能,现在可以通过激活一个指向该容器的空发射器来打开容器!

现在游戏会感觉更自然了,哪怕只是一点点,你同意吗?

功能

  • 将物品放入打开的容器中
    • 默认:启用
    • 游戏规则:chests.insertOpen
  • 让物品从底部打开的容器中掉落
    • 默认:禁用
    • 游戏规则:chests.barrelFall
    • 特殊物品掉落(例如雪球作为实际投掷的雪球掉落)
      • 默认:启用
      • 游戏规则:chests.barrelFall.throwableSpecial
      • 物品标签:#chests_are_chests:special_fall
  • 让箱子盖甩飞物品
    • 默认:禁用
    • 游戏规则:chests.lidFling
    • 实体类型标签:#chests_are_chests:flingable
    • 水平甩飞速度
      • 默认:0.25
      • 游戏规则:chests.lidFling.horizontalPower
    • 垂直甩飞速度
      • 默认:0.6
      • 游戏规则:chests.lidFling.verticalPower
  • 通过给空发射器供能来打开容器
    • 默认:启用
    • 游戏规则:chests.dispenserOpen
    • 自动打开持续时间(以世界刻为单位)
      • 默认:10
      • 游戏规则:chests.dispenserOpen.duration

依赖

Requires Unruled API

模组兼容性

内部兼容性

虽然兼容性已在计划中,但始终更倾向于由模组自身直接实现。 因此,如果你的模组已被计划、正在开发中,甚至已经实现, 请毫不犹豫地自行实现,如有需要,请联系我们寻求帮助,或告知我们 无需保留我们自己的兼容性实现。

已实现

自然兼容

已知(应该)与本模组具有自然兼容性、无需额外实现的模组

正在开发中

已计划

内部拒绝

  • Iron Chests: Restocked 由于模组作者名称注册不当,该模组无法被轻易处理。 因此,决定不尝试实现内置兼容性。

自行实现

容器实现

本模组调整了方块实体和物品实体的行为。 为了实现与本模组的兼容性,你需要让你的自定义方块实体实现 mc.recraftors.chestsarechests.util.FallInContainer 接口。

你也可以利用其他接口,例如 mc.recraftors.chestsarechests.util.BlockOpenableContainer 或 mc.recraftors.chestsarechests.util.BooleanHolder,你可以随意使用它们,或者 在你已经继承了原版箱子或木桶类的情况下加以利用。

请随时查看 箱子 和木桶 的实现,以了解如何在所提供的方法中处理方块打开和朝向。

另外,不必担心更新时出现更多方法而你的模组未实现它们,从而导致问题。 没有任何方法计划被删除,也不会包含主版本变更。所有新方法 将_始终_附带默认实现,以避免无意义的问题。

物品实现

本模组允许某些物品(注册在相应物品标签中)在从容器中“掉落”时具有自定义行为。 为此,物品本身必须实现 mc.recraftors.chestsarechests.util.ContainerItemHelper 接口。

该接口有两个需要实现的方法。第一个是可选的,指示物品掉落方向。 这允许指定物品可以从容器的哪一面开口出来。(例如,向上重力的物品可以 指定向上的掉落方向)

默认情况下,第一个方法将返回 DOWN。

第二个方法是特殊掉落行为的实际实现。它应该使用第一个方法来判断 是否运行,并执行预期的操作。该方法的返回值指示物品堆叠是否 已掉落(理论上已被消耗),还是未掉落,因此不应再尝试让它向 同一方向掉落,以避免造成更多的运行时计算压力。

请随时查看 箭或 雪球的实现 ,以了解如何处理特殊物品掉落。

同样,不必担心更新时出现更多方法,因为所有新方法同样将附带默认 实现(如果可能的话,基于已有的方法)。

示例

与版本 0.5 保持同步

容器实现
public class MyCustomBlockEntity extends BlockEntity implements FallInContainer {
    private boolean isOpen;
    private final int size;
    private final DefaultedList<ItemStack> content;
    private final Map<Integer, Integer> fallUpdateMap = new HashMap<>();

    @Override
    public boolean chests$tryInsertion(ItemEntity entity) {
        return FallInContainer.chests$inventoryInsertion(this.content, entity, this::setStack);
    }

    @Override
    public boolean chests$isOpen() {
        return isOpen;
    }

    @Override
    public VoxelShape chests$InputAreaShape() {
        return FallInContainer.ABOVE;
    }

    @Override
    public void chests$forceOpen(ServerWorld world, BlockPos at, BlockState from) {
        this.isOpen = true;
        this.onOpen();
    }

    @Override
    public boolean chests$tryForceOpen(BlockState from) {
        ServerWorld serverWorld = (ServerWorld) this.getWorld();
        BlockPos blockPos = this.getPos();
        this.chests$forceOpen(serverWorld, blockPos, from);
        ChestsAreChests.scheduleTick(serverWorld, blockPos, duration);
    }

    @Override
    public boolean chests$forceClose() {
        this.isOpen = false;
        this.onClose();
    }

    @Override
    public Map<Integer, Integer> getFallUpdateMap() {
        return this.fallUpdateMap;
    }

    void onOpen() {
        // ...
        // potential rendering stuff
        ChestsAreChests.ejectAbove(Direction.UP, this);
    }
}
物品实现
public class MyCustomItem extends Item implements ContainerItemHelper {
    public Direction[] chests$getFallDirection(ItemStack stack) {
        return new Direction[]{Directions.UP};
    }
    
    public boolean defaultOnOpenTick(ItemStack stack, FallInContainer container, Direction direction, World world, Vec3d pos, Vec3d velocity) {
        if (!ChestsAreChests.isInArray(direction, chests$getFallDirection(stack))) return false;
        MyGravitatedEntity entity = new MyGravitatedEntity(world, pos.x, pos.y, pos.z, stack.copy());
        entity.setVelocity(velocity);
        world.spawnEntity(entity);
        return true;
    }
}

展示