mirror of
https://github.com/Creators-of-Create/Create.git
synced 2024-12-28 16:06:48 +01:00
Trekking Inventory
- Contraption storage now accepts more chests and barrels from other mods - Players can now open chests and barrels on assembled contraptions - Added a `#contraption_inventory_deny` block tag as a way to opt out
This commit is contained in:
parent
379b8d1f26
commit
36cd43997d
9 changed files with 168 additions and 8 deletions
|
@ -567,7 +567,7 @@ bf2b0310500213ff853c748c236eb5d01f61658e assets/create/blockstates/yellow_toolbo
|
||||||
7f39521b211441f5c3e06d60c5978cebe16cacfb assets/create/blockstates/zinc_block.json
|
7f39521b211441f5c3e06d60c5978cebe16cacfb assets/create/blockstates/zinc_block.json
|
||||||
b7181bcd8182b2f17088e5aa881f374c9c65470c assets/create/blockstates/zinc_ore.json
|
b7181bcd8182b2f17088e5aa881f374c9c65470c assets/create/blockstates/zinc_ore.json
|
||||||
f1bedeb51c35e70a2247178634e61ea637a6622e assets/create/lang/en_ud.json
|
f1bedeb51c35e70a2247178634e61ea637a6622e assets/create/lang/en_ud.json
|
||||||
59bd0d1e0f74f1dbfd2443b3e6cb8c683b57827a assets/create/lang/en_us.json
|
59fd557ef593efa3c7b783195ec5dc789eae1834 assets/create/lang/en_us.json
|
||||||
487a511a01b2a4531fb672f917922312db78f958 assets/create/models/block/acacia_window.json
|
487a511a01b2a4531fb672f917922312db78f958 assets/create/models/block/acacia_window.json
|
||||||
b48060cba1a382f373a05bf0039054053eccf076 assets/create/models/block/acacia_window_pane_noside.json
|
b48060cba1a382f373a05bf0039054053eccf076 assets/create/models/block/acacia_window_pane_noside.json
|
||||||
3066db1bf03cffa1a9c7fbacf47ae586632f4eb3 assets/create/models/block/acacia_window_pane_noside_alt.json
|
3066db1bf03cffa1a9c7fbacf47ae586632f4eb3 assets/create/models/block/acacia_window_pane_noside_alt.json
|
||||||
|
@ -5652,6 +5652,7 @@ ac265a674626e0e832330086fd18fe0be37fc327 data/create/recipes/weathered_copper_ti
|
||||||
5942a571f79c40524bbf408775cf91de4715f2b6 data/create/recipes/weathered_copper_tile_stairs_from_weathered_copper_tiles_stonecutting.json
|
5942a571f79c40524bbf408775cf91de4715f2b6 data/create/recipes/weathered_copper_tile_stairs_from_weathered_copper_tiles_stonecutting.json
|
||||||
2a2700b43614f86d3294726595cb28ed7dca4387 data/create/tags/blocks/brittle.json
|
2a2700b43614f86d3294726595cb28ed7dca4387 data/create/tags/blocks/brittle.json
|
||||||
d99d5c67bdffff60789a19bd51a5c5267c75e0a4 data/create/tags/blocks/casing.json
|
d99d5c67bdffff60789a19bd51a5c5267c75e0a4 data/create/tags/blocks/casing.json
|
||||||
|
74700d556ca80c7a1db5fd4efb09c3ddb26cad66 data/create/tags/blocks/contraption_inventory_deny.json
|
||||||
bc203f09dd7f48965d146d0bd035fb904cb75e7d data/create/tags/blocks/copycat_allow.json
|
bc203f09dd7f48965d146d0bd035fb904cb75e7d data/create/tags/blocks/copycat_allow.json
|
||||||
d4a3b66f4b763b9a2dcdea74b7273f0ae85cb335 data/create/tags/blocks/copycat_deny.json
|
d4a3b66f4b763b9a2dcdea74b7273f0ae85cb335 data/create/tags/blocks/copycat_deny.json
|
||||||
2b4c93e5a752ebf54217594766f30d8d60cb4343 data/create/tags/blocks/fan_transparent.json
|
2b4c93e5a752ebf54217594766f30d8d60cb4343 data/create/tags/blocks/fan_transparent.json
|
||||||
|
|
|
@ -1048,6 +1048,7 @@
|
||||||
"create.minecart_coupling.removed": "Removed all couplings from minecart",
|
"create.minecart_coupling.removed": "Removed all couplings from minecart",
|
||||||
"create.minecart_coupling.too_far": "Minecarts are too far apart",
|
"create.minecart_coupling.too_far": "Minecarts are too far apart",
|
||||||
|
|
||||||
|
"create.contraptions.moving_container": "Moving %1$s",
|
||||||
"create.contraptions.movement_mode": "Movement Mode",
|
"create.contraptions.movement_mode": "Movement Mode",
|
||||||
"create.contraptions.movement_mode.move_place": "Always Place when Stopped",
|
"create.contraptions.movement_mode.move_place": "Always Place when Stopped",
|
||||||
"create.contraptions.movement_mode.move_place_returned": "Place only in Starting Position",
|
"create.contraptions.movement_mode.move_place_returned": "Place only in Starting Position",
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"replace": false,
|
||||||
|
"values": []
|
||||||
|
}
|
|
@ -87,6 +87,7 @@ public class AllTags {
|
||||||
WRENCH_PICKUP,
|
WRENCH_PICKUP,
|
||||||
COPYCAT_ALLOW,
|
COPYCAT_ALLOW,
|
||||||
COPYCAT_DENY,
|
COPYCAT_DENY,
|
||||||
|
CONTRAPTION_INVENTORY_DENY,
|
||||||
|
|
||||||
RELOCATION_NOT_SUPPORTED(FORGE),
|
RELOCATION_NOT_SUPPORTED(FORGE),
|
||||||
WG_STONE(FORGE),
|
WG_STONE(FORGE),
|
||||||
|
|
|
@ -278,9 +278,12 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit
|
||||||
InteractionHand interactionHand) {
|
InteractionHand interactionHand) {
|
||||||
int indexOfSeat = contraption.getSeats()
|
int indexOfSeat = contraption.getSeats()
|
||||||
.indexOf(localPos);
|
.indexOf(localPos);
|
||||||
if (indexOfSeat == -1 || AllItems.WRENCH.isIn(player.getItemInHand(interactionHand)))
|
if (indexOfSeat == -1 || AllItems.WRENCH.isIn(player.getItemInHand(interactionHand))) {
|
||||||
return contraption.interactors.containsKey(localPos) && contraption.interactors.get(localPos)
|
if (contraption.interactors.containsKey(localPos))
|
||||||
|
return contraption.interactors.get(localPos)
|
||||||
.handlePlayerInteraction(player, interactionHand, localPos, this);
|
.handlePlayerInteraction(player, interactionHand, localPos, this);
|
||||||
|
return contraption.storage.handlePlayerStorageInteraction(contraption, player, localPos);
|
||||||
|
}
|
||||||
if (player.isPassenger())
|
if (player.isPassenger())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package com.simibubi.create.content.contraptions.components.structureMovement;
|
package com.simibubi.create.content.contraptions.components.structureMovement;
|
||||||
|
|
||||||
import com.simibubi.create.AllBlockEntityTypes;
|
import com.simibubi.create.AllBlockEntityTypes;
|
||||||
|
import com.simibubi.create.AllTags.AllBlockTags;
|
||||||
import com.simibubi.create.content.contraptions.components.crafter.MechanicalCrafterBlockEntity;
|
import com.simibubi.create.content.contraptions.components.crafter.MechanicalCrafterBlockEntity;
|
||||||
import com.simibubi.create.content.contraptions.processing.ProcessingInventory;
|
import com.simibubi.create.content.contraptions.processing.ProcessingInventory;
|
||||||
import com.simibubi.create.content.logistics.block.inventories.BottomlessItemHandler;
|
import com.simibubi.create.content.logistics.block.inventories.BottomlessItemHandler;
|
||||||
|
@ -15,6 +16,7 @@ import net.minecraft.world.level.block.entity.BarrelBlockEntity;
|
||||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||||
import net.minecraft.world.level.block.entity.ChestBlockEntity;
|
import net.minecraft.world.level.block.entity.ChestBlockEntity;
|
||||||
import net.minecraft.world.level.block.entity.ShulkerBoxBlockEntity;
|
import net.minecraft.world.level.block.entity.ShulkerBoxBlockEntity;
|
||||||
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
import net.minecraftforge.common.util.LazyOptional;
|
import net.minecraftforge.common.util.LazyOptional;
|
||||||
import net.minecraftforge.items.CapabilityItemHandler;
|
import net.minecraftforge.items.CapabilityItemHandler;
|
||||||
import net.minecraftforge.items.IItemHandler;
|
import net.minecraftforge.items.IItemHandler;
|
||||||
|
@ -47,9 +49,30 @@ public class MountedStorage {
|
||||||
if (be instanceof ItemVaultBlockEntity)
|
if (be instanceof ItemVaultBlockEntity)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
try {
|
||||||
LazyOptional<IItemHandler> capability = be.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY);
|
LazyOptional<IItemHandler> capability = be.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY);
|
||||||
IItemHandler handler = capability.orElse(null);
|
IItemHandler handler = capability.orElse(null);
|
||||||
return handler instanceof ItemStackHandler && !(handler instanceof ProcessingInventory);
|
if (handler instanceof ItemStackHandler)
|
||||||
|
return !(handler instanceof ProcessingInventory);
|
||||||
|
return canUseModdedInventory(be, handler);
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean canUseModdedInventory(BlockEntity be, IItemHandler handler) {
|
||||||
|
if (!(handler instanceof IItemHandlerModifiable validItemHandler))
|
||||||
|
return false;
|
||||||
|
BlockState blockState = be.getBlockState();
|
||||||
|
if (AllBlockTags.CONTRAPTION_INVENTORY_DENY.matches(blockState))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// There doesn't appear to be much of a standard for tagging chests/barrels
|
||||||
|
String blockId = blockState.getBlock()
|
||||||
|
.getRegistryName()
|
||||||
|
.getPath();
|
||||||
|
return blockId.endsWith("_chest") || blockId.endsWith("_barrel");
|
||||||
}
|
}
|
||||||
|
|
||||||
public MountedStorage(BlockEntity be) {
|
public MountedStorage(BlockEntity be) {
|
||||||
|
|
|
@ -0,0 +1,68 @@
|
||||||
|
package com.simibubi.create.content.contraptions.components.structureMovement;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import com.simibubi.create.foundation.utility.Lang;
|
||||||
|
|
||||||
|
import net.minecraft.network.chat.Component;
|
||||||
|
import net.minecraft.util.Mth;
|
||||||
|
import net.minecraft.world.MenuProvider;
|
||||||
|
import net.minecraft.world.entity.player.Inventory;
|
||||||
|
import net.minecraft.world.entity.player.Player;
|
||||||
|
import net.minecraft.world.inventory.AbstractContainerMenu;
|
||||||
|
import net.minecraft.world.inventory.ChestMenu;
|
||||||
|
import net.minecraft.world.inventory.MenuType;
|
||||||
|
import net.minecraftforge.items.IItemHandlerModifiable;
|
||||||
|
import net.minecraftforge.items.wrapper.RecipeWrapper;
|
||||||
|
|
||||||
|
public class MountedStorageInteraction {
|
||||||
|
|
||||||
|
public static final List<MenuType<?>> menus = ImmutableList.of(MenuType.GENERIC_9x1, MenuType.GENERIC_9x2,
|
||||||
|
MenuType.GENERIC_9x3, MenuType.GENERIC_9x4, MenuType.GENERIC_9x5, MenuType.GENERIC_9x6);
|
||||||
|
|
||||||
|
public static MenuProvider createMenuProvider(Component displayName, IItemHandlerModifiable handler,
|
||||||
|
int slotCount, Supplier<Boolean> stillValid) {
|
||||||
|
int rows = Mth.clamp(slotCount / 9, 1, 6);
|
||||||
|
MenuType<?> menuType = menus.get(rows - 1);
|
||||||
|
Component menuName = Lang.translateDirect("contraptions.moving_container", displayName);
|
||||||
|
|
||||||
|
return new MenuProvider() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AbstractContainerMenu createMenu(int pContainerId, Inventory pPlayerInventory, Player pPlayer) {
|
||||||
|
return new ChestMenu(menuType, pContainerId, pPlayerInventory, new StorageInteractionContainer(handler, stillValid),
|
||||||
|
rows);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Component getDisplayName() {
|
||||||
|
return menuName;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class StorageInteractionContainer extends RecipeWrapper {
|
||||||
|
|
||||||
|
private Supplier<Boolean> stillValid;
|
||||||
|
|
||||||
|
public StorageInteractionContainer(IItemHandlerModifiable inv, Supplier<Boolean> stillValid) {
|
||||||
|
super(inv);
|
||||||
|
this.stillValid = stillValid;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean stillValid(Player player) {
|
||||||
|
return stillValid.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getMaxStackSize() {
|
||||||
|
return 64;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -6,27 +6,38 @@ import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.function.Supplier;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.Contraption.ContraptionInvWrapper;
|
import com.simibubi.create.content.contraptions.components.structureMovement.Contraption.ContraptionInvWrapper;
|
||||||
import com.simibubi.create.content.contraptions.fluids.tank.FluidTankBlockEntity;
|
import com.simibubi.create.content.contraptions.fluids.tank.FluidTankBlockEntity;
|
||||||
import com.simibubi.create.foundation.fluid.CombinedTankWrapper;
|
import com.simibubi.create.foundation.fluid.CombinedTankWrapper;
|
||||||
|
import com.simibubi.create.foundation.utility.Components;
|
||||||
import com.simibubi.create.foundation.utility.NBTHelper;
|
import com.simibubi.create.foundation.utility.NBTHelper;
|
||||||
|
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
|
import net.minecraft.core.Direction;
|
||||||
import net.minecraft.nbt.CompoundTag;
|
import net.minecraft.nbt.CompoundTag;
|
||||||
import net.minecraft.nbt.ListTag;
|
import net.minecraft.nbt.ListTag;
|
||||||
import net.minecraft.nbt.NbtUtils;
|
import net.minecraft.nbt.NbtUtils;
|
||||||
import net.minecraft.nbt.Tag;
|
import net.minecraft.nbt.Tag;
|
||||||
|
import net.minecraft.network.chat.Component;
|
||||||
|
import net.minecraft.sounds.SoundEvents;
|
||||||
|
import net.minecraft.sounds.SoundSource;
|
||||||
|
import net.minecraft.world.entity.player.Player;
|
||||||
import net.minecraft.world.item.ItemStack;
|
import net.minecraft.world.item.ItemStack;
|
||||||
|
import net.minecraft.world.level.block.ChestBlock;
|
||||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||||
|
import net.minecraft.world.level.block.state.properties.ChestType;
|
||||||
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate.StructureBlockInfo;
|
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate.StructureBlockInfo;
|
||||||
|
import net.minecraft.world.phys.Vec3;
|
||||||
import net.minecraftforge.fluids.FluidStack;
|
import net.minecraftforge.fluids.FluidStack;
|
||||||
import net.minecraftforge.fluids.IFluidTank;
|
import net.minecraftforge.fluids.IFluidTank;
|
||||||
import net.minecraftforge.fluids.capability.IFluidHandler;
|
import net.minecraftforge.fluids.capability.IFluidHandler;
|
||||||
import net.minecraftforge.fluids.capability.IFluidHandler.FluidAction;
|
import net.minecraftforge.fluids.capability.IFluidHandler.FluidAction;
|
||||||
import net.minecraftforge.fluids.capability.templates.FluidTank;
|
import net.minecraftforge.fluids.capability.templates.FluidTank;
|
||||||
import net.minecraftforge.items.IItemHandlerModifiable;
|
import net.minecraftforge.items.IItemHandlerModifiable;
|
||||||
|
import net.minecraftforge.items.wrapper.CombinedInvWrapper;
|
||||||
|
|
||||||
public class MountedStorageManager {
|
public class MountedStorageManager {
|
||||||
|
|
||||||
|
@ -202,4 +213,50 @@ public class MountedStorageManager {
|
||||||
return fluidInventory;
|
return fluidInventory;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean handlePlayerStorageInteraction(Contraption contraption, Player player, BlockPos localPos) {
|
||||||
|
if (player.level.isClientSide()) {
|
||||||
|
BlockEntity localBE = contraption.presentBlockEntities.get(localPos);
|
||||||
|
return MountedStorage.canUseAsStorage(localBE);
|
||||||
|
}
|
||||||
|
|
||||||
|
MountedStorageManager storageManager = contraption.getStorageForSpawnPacket();
|
||||||
|
MountedStorage storage = storageManager.storage.get(localPos);
|
||||||
|
if (storage == null || storage.getItemHandler() == null)
|
||||||
|
return false;
|
||||||
|
IItemHandlerModifiable handler = storage.getItemHandler();
|
||||||
|
|
||||||
|
StructureBlockInfo info = contraption.getBlocks()
|
||||||
|
.get(localPos);
|
||||||
|
if (info != null && info.state.hasProperty(ChestBlock.TYPE)) {
|
||||||
|
ChestType chestType = info.state.getValue(ChestBlock.TYPE);
|
||||||
|
Direction facing = info.state.getOptionalValue(ChestBlock.FACING)
|
||||||
|
.orElse(Direction.SOUTH);
|
||||||
|
Direction connectedDirection =
|
||||||
|
chestType == ChestType.LEFT ? facing.getClockWise() : facing.getCounterClockWise();
|
||||||
|
|
||||||
|
if (chestType != ChestType.SINGLE) {
|
||||||
|
MountedStorage storage2 = storageManager.storage.get(localPos.relative(connectedDirection));
|
||||||
|
if (storage2 != null && storage2.getItemHandler() != null)
|
||||||
|
handler = chestType == ChestType.RIGHT ? new CombinedInvWrapper(handler, storage2.getItemHandler())
|
||||||
|
: new CombinedInvWrapper(storage2.getItemHandler(), handler);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int slotCount = handler.getSlots();
|
||||||
|
if (slotCount == 0)
|
||||||
|
return false;
|
||||||
|
if (slotCount % 9 != 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
Supplier<Boolean> stillValid = () -> contraption.entity.isAlive()
|
||||||
|
&& player.distanceToSqr(contraption.entity.toGlobalVector(Vec3.atCenterOf(localPos), 0)) < 64;
|
||||||
|
Component name = info != null ? info.state.getBlock()
|
||||||
|
.getName() : Components.literal("Container");
|
||||||
|
player.openMenu(MountedStorageInteraction.createMenuProvider(name, handler, slotCount, stillValid));
|
||||||
|
|
||||||
|
Vec3 soundPos = contraption.entity.toGlobalVector(Vec3.atCenterOf(localPos), 0);
|
||||||
|
player.level.playSound(null, new BlockPos(soundPos), SoundEvents.BARREL_OPEN, SoundSource.BLOCKS, 0.75f, 1f);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -180,6 +180,8 @@
|
||||||
"create.minecart_coupling.removed": "Removed all couplings from minecart",
|
"create.minecart_coupling.removed": "Removed all couplings from minecart",
|
||||||
"create.minecart_coupling.too_far": "Minecarts are too far apart",
|
"create.minecart_coupling.too_far": "Minecarts are too far apart",
|
||||||
|
|
||||||
|
"create.contraptions.moving_container": "Moving %1$s",
|
||||||
|
|
||||||
"create.contraptions.movement_mode": "Movement Mode",
|
"create.contraptions.movement_mode": "Movement Mode",
|
||||||
"create.contraptions.movement_mode.move_place": "Always Place when Stopped",
|
"create.contraptions.movement_mode.move_place": "Always Place when Stopped",
|
||||||
"create.contraptions.movement_mode.move_place_returned": "Place only in Starting Position",
|
"create.contraptions.movement_mode.move_place_returned": "Place only in Starting Position",
|
||||||
|
|
Loading…
Reference in a new issue