mirror of
https://github.com/Creators-of-Create/Create.git
synced 2024-12-27 07:27:15 +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
|
||||
b7181bcd8182b2f17088e5aa881f374c9c65470c assets/create/blockstates/zinc_ore.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
|
||||
b48060cba1a382f373a05bf0039054053eccf076 assets/create/models/block/acacia_window_pane_noside.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
|
||||
2a2700b43614f86d3294726595cb28ed7dca4387 data/create/tags/blocks/brittle.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
|
||||
d4a3b66f4b763b9a2dcdea74b7273f0ae85cb335 data/create/tags/blocks/copycat_deny.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.too_far": "Minecarts are too far apart",
|
||||
|
||||
"create.contraptions.moving_container": "Moving %1$s",
|
||||
"create.contraptions.movement_mode": "Movement Mode",
|
||||
"create.contraptions.movement_mode.move_place": "Always Place when Stopped",
|
||||
"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,
|
||||
COPYCAT_ALLOW,
|
||||
COPYCAT_DENY,
|
||||
CONTRAPTION_INVENTORY_DENY,
|
||||
|
||||
RELOCATION_NOT_SUPPORTED(FORGE),
|
||||
WG_STONE(FORGE),
|
||||
|
|
|
@ -278,9 +278,12 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit
|
|||
InteractionHand interactionHand) {
|
||||
int indexOfSeat = contraption.getSeats()
|
||||
.indexOf(localPos);
|
||||
if (indexOfSeat == -1 || AllItems.WRENCH.isIn(player.getItemInHand(interactionHand)))
|
||||
return contraption.interactors.containsKey(localPos) && contraption.interactors.get(localPos)
|
||||
.handlePlayerInteraction(player, interactionHand, localPos, this);
|
||||
if (indexOfSeat == -1 || AllItems.WRENCH.isIn(player.getItemInHand(interactionHand))) {
|
||||
if (contraption.interactors.containsKey(localPos))
|
||||
return contraption.interactors.get(localPos)
|
||||
.handlePlayerInteraction(player, interactionHand, localPos, this);
|
||||
return contraption.storage.handlePlayerStorageInteraction(contraption, player, localPos);
|
||||
}
|
||||
if (player.isPassenger())
|
||||
return false;
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package com.simibubi.create.content.contraptions.components.structureMovement;
|
||||
|
||||
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.processing.ProcessingInventory;
|
||||
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.ChestBlockEntity;
|
||||
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.items.CapabilityItemHandler;
|
||||
import net.minecraftforge.items.IItemHandler;
|
||||
|
@ -47,9 +49,30 @@ public class MountedStorage {
|
|||
if (be instanceof ItemVaultBlockEntity)
|
||||
return true;
|
||||
|
||||
LazyOptional<IItemHandler> capability = be.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY);
|
||||
IItemHandler handler = capability.orElse(null);
|
||||
return handler instanceof ItemStackHandler && !(handler instanceof ProcessingInventory);
|
||||
try {
|
||||
LazyOptional<IItemHandler> capability = be.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY);
|
||||
IItemHandler handler = capability.orElse(null);
|
||||
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) {
|
||||
|
@ -182,7 +205,7 @@ public class MountedStorage {
|
|||
public boolean isValid() {
|
||||
return valid;
|
||||
}
|
||||
|
||||
|
||||
public boolean canUseForFuel() {
|
||||
return !noFuel;
|
||||
}
|
||||
|
|
|
@ -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.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.Contraption.ContraptionInvWrapper;
|
||||
import com.simibubi.create.content.contraptions.fluids.tank.FluidTankBlockEntity;
|
||||
import com.simibubi.create.foundation.fluid.CombinedTankWrapper;
|
||||
import com.simibubi.create.foundation.utility.Components;
|
||||
import com.simibubi.create.foundation.utility.NBTHelper;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.ListTag;
|
||||
import net.minecraft.nbt.NbtUtils;
|
||||
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.level.block.ChestBlock;
|
||||
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.phys.Vec3;
|
||||
import net.minecraftforge.fluids.FluidStack;
|
||||
import net.minecraftforge.fluids.IFluidTank;
|
||||
import net.minecraftforge.fluids.capability.IFluidHandler;
|
||||
import net.minecraftforge.fluids.capability.IFluidHandler.FluidAction;
|
||||
import net.minecraftforge.fluids.capability.templates.FluidTank;
|
||||
import net.minecraftforge.items.IItemHandlerModifiable;
|
||||
import net.minecraftforge.items.wrapper.CombinedInvWrapper;
|
||||
|
||||
public class MountedStorageManager {
|
||||
|
||||
|
@ -202,4 +213,50 @@ public class MountedStorageManager {
|
|||
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.too_far": "Minecarts are too far apart",
|
||||
|
||||
"create.contraptions.moving_container": "Moving %1$s",
|
||||
|
||||
"create.contraptions.movement_mode": "Movement Mode",
|
||||
"create.contraptions.movement_mode.move_place": "Always Place when Stopped",
|
||||
"create.contraptions.movement_mode.move_place_returned": "Place only in Starting Position",
|
||||
|
|
Loading…
Reference in a new issue