Added compacting drawer

This commit is contained in:
Buuz135 2021-12-19 16:09:09 +01:00
parent c67ee44d4a
commit 7877be2bc6
12 changed files with 851 additions and 23 deletions

View File

@ -4,9 +4,13 @@ ad618fbf42f1c54275c29beaa25710bca73acef2 assets/functionalstorage/blockstates/ac
3b02d94db9f2f0b4d9b7b4a412427929a6f87d2b assets/functionalstorage/blockstates/birch_wood_x_1.json 3b02d94db9f2f0b4d9b7b4a412427929a6f87d2b assets/functionalstorage/blockstates/birch_wood_x_1.json
7bd0dc17af1d849100a423ca36eacb767bb2b1ea assets/functionalstorage/blockstates/birch_wood_x_2.json 7bd0dc17af1d849100a423ca36eacb767bb2b1ea assets/functionalstorage/blockstates/birch_wood_x_2.json
7e20830acae23717dd782ebf628e5eef778de0c1 assets/functionalstorage/blockstates/birch_wood_x_4.json 7e20830acae23717dd782ebf628e5eef778de0c1 assets/functionalstorage/blockstates/birch_wood_x_4.json
78ab16e1714fbed8ba98acfe243a89c15587feb0 assets/functionalstorage/blockstates/compacting_drawer.json
e0fee0fdb3a3e76bd6ca5a8f92f7c6c5e54b5e23 assets/functionalstorage/blockstates/crimson_hyphae_x_1.json e0fee0fdb3a3e76bd6ca5a8f92f7c6c5e54b5e23 assets/functionalstorage/blockstates/crimson_hyphae_x_1.json
17eec305ac9c19c66a32af11de2e1a528fa00894 assets/functionalstorage/blockstates/crimson_hyphae_x_2.json 17eec305ac9c19c66a32af11de2e1a528fa00894 assets/functionalstorage/blockstates/crimson_hyphae_x_2.json
ffcd4cbf2a5406b7e4f96e87ad643b1feb18caf3 assets/functionalstorage/blockstates/crimson_hyphae_x_4.json ffcd4cbf2a5406b7e4f96e87ad643b1feb18caf3 assets/functionalstorage/blockstates/crimson_hyphae_x_4.json
243258d54301c9f1cb03b313a6caf248d9c42943 assets/functionalstorage/blockstates/dark_oak_wood_x_1.json
a3e62a3fe37312b70cfd621784f782d18e063475 assets/functionalstorage/blockstates/dark_oak_wood_x_2.json
586ce6d546f06d679d720166421d049afc7138a2 assets/functionalstorage/blockstates/dark_oak_wood_x_4.json
a75ff2ba030156b42ed5e545fbf8e06f9854bf2c assets/functionalstorage/blockstates/jungle_wood_x_1.json a75ff2ba030156b42ed5e545fbf8e06f9854bf2c assets/functionalstorage/blockstates/jungle_wood_x_1.json
19ae7afc5de0593b427309159c299e8d2ddfc4cd assets/functionalstorage/blockstates/jungle_wood_x_2.json 19ae7afc5de0593b427309159c299e8d2ddfc4cd assets/functionalstorage/blockstates/jungle_wood_x_2.json
228dd78c840b995c601704c32eaf17fe007d0346 assets/functionalstorage/blockstates/jungle_wood_x_4.json 228dd78c840b995c601704c32eaf17fe007d0346 assets/functionalstorage/blockstates/jungle_wood_x_4.json
@ -25,9 +29,13 @@ a0f7a648fc02bbe7951b1616e8b5024e98b9f4bc data/functionalstorage/loot_tables/bloc
9e61407957cd64d6bf221214d2766fbf0387f810 data/functionalstorage/loot_tables/blocks/birch_wood_x_1.json 9e61407957cd64d6bf221214d2766fbf0387f810 data/functionalstorage/loot_tables/blocks/birch_wood_x_1.json
6dc0f3e0eb3c0d95946727dc7a94889eba7b3d9d data/functionalstorage/loot_tables/blocks/birch_wood_x_2.json 6dc0f3e0eb3c0d95946727dc7a94889eba7b3d9d data/functionalstorage/loot_tables/blocks/birch_wood_x_2.json
bb380824c89d14571908e3283170112c0425f832 data/functionalstorage/loot_tables/blocks/birch_wood_x_4.json bb380824c89d14571908e3283170112c0425f832 data/functionalstorage/loot_tables/blocks/birch_wood_x_4.json
5ca84bb6e4d35893da638b52bb7884426a409719 data/functionalstorage/loot_tables/blocks/compacting_drawer.json
751843faeb73f732abf09285fa5db1c22d3e9aa7 data/functionalstorage/loot_tables/blocks/crimson_hyphae_x_1.json 751843faeb73f732abf09285fa5db1c22d3e9aa7 data/functionalstorage/loot_tables/blocks/crimson_hyphae_x_1.json
f5f4160a7223af9205e2df1917b58bd00a65a1bc data/functionalstorage/loot_tables/blocks/crimson_hyphae_x_2.json f5f4160a7223af9205e2df1917b58bd00a65a1bc data/functionalstorage/loot_tables/blocks/crimson_hyphae_x_2.json
598f9907cefdc9a2acd5019ea744979f24c561b2 data/functionalstorage/loot_tables/blocks/crimson_hyphae_x_4.json 598f9907cefdc9a2acd5019ea744979f24c561b2 data/functionalstorage/loot_tables/blocks/crimson_hyphae_x_4.json
ae61cae584aed7ecd672d5223992d9949af4acf0 data/functionalstorage/loot_tables/blocks/dark_oak_wood_x_1.json
8b7272c3fc37b4683678c95502c80d6e3d1618a9 data/functionalstorage/loot_tables/blocks/dark_oak_wood_x_2.json
0e29723f48411634d77aa1f8ccb668761f0f529d data/functionalstorage/loot_tables/blocks/dark_oak_wood_x_4.json
a3f6195051ee19033bb167e924645cfff1982c13 data/functionalstorage/loot_tables/blocks/jungle_wood_x_1.json a3f6195051ee19033bb167e924645cfff1982c13 data/functionalstorage/loot_tables/blocks/jungle_wood_x_1.json
a9054f38503082c4448495eb28477f4aad833b6c data/functionalstorage/loot_tables/blocks/jungle_wood_x_2.json a9054f38503082c4448495eb28477f4aad833b6c data/functionalstorage/loot_tables/blocks/jungle_wood_x_2.json
7d0ec816a992ae76cf1b32cffa386a60ed59a7c8 data/functionalstorage/loot_tables/blocks/jungle_wood_x_4.json 7d0ec816a992ae76cf1b32cffa386a60ed59a7c8 data/functionalstorage/loot_tables/blocks/jungle_wood_x_4.json

View File

@ -0,0 +1,19 @@
{
"variants": {
"subfacing=north": {
"model": "functionalstorage:block/compacting_drawer"
},
"subfacing=south": {
"model": "functionalstorage:block/compacting_drawer",
"y": 180
},
"subfacing=west": {
"model": "functionalstorage:block/compacting_drawer",
"y": 270
},
"subfacing=east": {
"model": "functionalstorage:block/compacting_drawer",
"y": 90
}
}
}

View File

@ -0,0 +1,33 @@
{
"type": "minecraft:block",
"pools": [
{
"rolls": 1.0,
"bonus_rolls": 0.0,
"entries": [
{
"type": "minecraft:item",
"functions": [
{
"function": "minecraft:copy_nbt",
"source": "block_entity",
"ops": [
{
"source": "handler",
"target": "BlockEntityTag.handler",
"op": "replace"
}
]
}
],
"name": "functionalstorage:compacting_drawer"
}
],
"conditions": [
{
"condition": "minecraft:survives_explosion"
}
]
}
]
}

View File

@ -1,6 +1,8 @@
package com.buuz135.functionalstorage; package com.buuz135.functionalstorage;
import com.buuz135.functionalstorage.block.CompactingDrawerBlock;
import com.buuz135.functionalstorage.block.DrawerBlock; import com.buuz135.functionalstorage.block.DrawerBlock;
import com.buuz135.functionalstorage.client.CompactingDrawerRenderer;
import com.buuz135.functionalstorage.client.DrawerRenderer; import com.buuz135.functionalstorage.client.DrawerRenderer;
import com.buuz135.functionalstorage.data.FunctionalStorageBlockstateProvider; import com.buuz135.functionalstorage.data.FunctionalStorageBlockstateProvider;
import com.hrznstudio.titanium.block.BasicTileBlock; import com.hrznstudio.titanium.block.BasicTileBlock;
@ -19,7 +21,6 @@ import net.minecraftforge.client.event.EntityRenderersEvent;
import net.minecraftforge.common.util.NonNullLazy; import net.minecraftforge.common.util.NonNullLazy;
import net.minecraftforge.fml.DistExecutor; import net.minecraftforge.fml.DistExecutor;
import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;
import net.minecraftforge.forge.event.lifecycle.GatherDataEvent; import net.minecraftforge.forge.event.lifecycle.GatherDataEvent;
import net.minecraftforge.registries.ForgeRegistries; import net.minecraftforge.registries.ForgeRegistries;
import net.minecraftforge.registries.RegistryObject; import net.minecraftforge.registries.RegistryObject;
@ -40,6 +41,8 @@ public class FunctionalStorage extends ModuleController {
public static List<String> WOOD_TYPES = new ArrayList<>(); public static List<String> WOOD_TYPES = new ArrayList<>();
public static HashMap<DrawerType, List<RegistryObject<Block>>> DRAWER_TYPES = new HashMap<>(); public static HashMap<DrawerType, List<RegistryObject<Block>>> DRAWER_TYPES = new HashMap<>();
public static RegistryObject<Block> COMPACTING_DRAWER;
public static AdvancedTitaniumTab TAB = new AdvancedTitaniumTab("functionalstorage", true); public static AdvancedTitaniumTab TAB = new AdvancedTitaniumTab("functionalstorage", true);
public FunctionalStorage() { public FunctionalStorage() {
@ -69,7 +72,7 @@ public class FunctionalStorage extends ModuleController {
} }
DRAWER_TYPES.get(value).forEach(blockRegistryObject -> TAB.addIconStacks(() -> new ItemStack(blockRegistryObject.get()))); DRAWER_TYPES.get(value).forEach(blockRegistryObject -> TAB.addIconStacks(() -> new ItemStack(blockRegistryObject.get())));
} }
COMPACTING_DRAWER = getRegistries().register(Block.class, "compacting_drawer", () -> new CompactingDrawerBlock("compacting_drawer"));
} }
public enum DrawerType{ public enum DrawerType{
@ -101,6 +104,8 @@ public class FunctionalStorage extends ModuleController {
registerRenderers.registerBlockEntityRenderer(((BasicTileBlock)blockRegistryObject.get()).getTileEntityType(), p_173571_ -> new DrawerRenderer()); registerRenderers.registerBlockEntityRenderer(((BasicTileBlock)blockRegistryObject.get()).getTileEntityType(), p_173571_ -> new DrawerRenderer());
}); });
} }
registerRenderers.registerBlockEntityRenderer(((BasicTileBlock)COMPACTING_DRAWER.get()).getTileEntityType(), p_173571_ -> new CompactingDrawerRenderer());
}).subscribe(); }).subscribe();
} }

View File

@ -0,0 +1,152 @@
package com.buuz135.functionalstorage.block;
import com.buuz135.functionalstorage.FunctionalStorage;
import com.buuz135.functionalstorage.block.tile.CompactingDrawerTile;
import com.buuz135.functionalstorage.block.tile.DrawerTile;
import com.google.common.collect.Multimap;
import com.google.common.collect.MultimapBuilder;
import com.hrznstudio.titanium.block.RotatableBlock;
import com.hrznstudio.titanium.datagenerator.loot.block.BasicBlockLootTables;
import com.hrznstudio.titanium.module.DeferredRegistryHelper;
import com.hrznstudio.titanium.util.RayTraceUtils;
import com.hrznstudio.titanium.util.TileUtil;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.NonNullList;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.storage.loot.LootTable;
import net.minecraft.world.level.storage.loot.functions.CopyNbtFunction;
import net.minecraft.world.level.storage.loot.providers.nbt.ContextNbtProvider;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.HitResult;
import net.minecraft.world.phys.shapes.BooleanOp;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.Shapes;
import net.minecraft.world.phys.shapes.VoxelShape;
import org.jetbrains.annotations.NotNull;
import javax.annotation.Nonnull;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
public class CompactingDrawerBlock extends RotatableBlock<CompactingDrawerTile> {
public static Multimap<Direction, VoxelShape> CACHED_SHAPES = MultimapBuilder.hashKeys().arrayListValues().build();
static {
CACHED_SHAPES.put(Direction.NORTH, Shapes.box(1/16D, 1/16D, 0, 8/16D, 8/16D, 1/16D));
CACHED_SHAPES.put(Direction.NORTH, Shapes.box(8/16D, 1/16D, 0, 15/16D, 8/16D, 1/16D));
CACHED_SHAPES.put(Direction.NORTH, Shapes.box(1/16D, 8/16D, 0, 15/16D, 15/16D, 1/16D));
CACHED_SHAPES.put(Direction.SOUTH, Shapes.box(8/16D, 1/16D, 15/16D, 15/16D, 8/16D, 1));
CACHED_SHAPES.put(Direction.SOUTH, Shapes.box(1/16D, 1/16D, 15/16D, 8/16D, 8/16D, 1));
CACHED_SHAPES.put(Direction.SOUTH, Shapes.box(1/16D, 8/16D, 15/16D, 15/16D, 15/16D, 1));
CACHED_SHAPES.put(Direction.EAST, Shapes.box(15/16D, 1/16D, 1/16D, 1, 8/16D, 7/16D));
CACHED_SHAPES.put(Direction.EAST, Shapes.box(15/16D, 1/16D, 8/16D, 1, 8/16D, 15/16D));
CACHED_SHAPES.put(Direction.EAST, Shapes.box(15/16D, 8/16D, 1/16D, 1, 15/16D, 15/16D));
CACHED_SHAPES.put(Direction.WEST, Shapes.box(0, 1/16D, 8/16D, 1/16D, 8/16D, 15/16D));
CACHED_SHAPES.put(Direction.WEST, Shapes.box(0, 1/16D, 1/16D, 1/16D, 8/16D, 7/16D));
CACHED_SHAPES.put(Direction.WEST, Shapes.box(0, 8/16D, 1/16D, 1/16D, 15/16D, 15/16D));
}
public CompactingDrawerBlock(String name) {
super(name, Properties.copy(Blocks.OAK_PLANKS), CompactingDrawerTile.class);
setItemGroup(FunctionalStorage.TAB);
registerDefaultState(defaultBlockState().setValue(RotatableBlock.FACING_HORIZONTAL, Direction.NORTH));
}
@Override
public void addAlternatives(DeferredRegistryHelper registry) {
super.addAlternatives(registry);
}
@NotNull
@Override
public RotationType getRotationType() {
return RotationType.FOUR_WAY;
}
@Override
public BlockEntityType.BlockEntitySupplier<CompactingDrawerTile> getTileEntityFactory() {
return (blockPos, state) -> new CompactingDrawerTile(this, blockPos, state);
}
@Override
public List<VoxelShape> getBoundingBoxes(BlockState state, BlockGetter source, BlockPos pos) {
return getShapes(state, source, pos);
}
private static List<VoxelShape> getShapes(BlockState state, BlockGetter source, BlockPos pos){
List<VoxelShape> boxes = new ArrayList<>();
CACHED_SHAPES.get(state.getValue(RotatableBlock.FACING_HORIZONTAL)).forEach(boxes::add); //TODO
VoxelShape total = Shapes.block();
boxes.add(total);
return boxes;
}
@Nonnull
@Override
public VoxelShape getCollisionShape(BlockState state, BlockGetter world, BlockPos pos, CollisionContext selectionContext) {
return Shapes.box(0, 0, 0, 1,1,1);
}
@Override
public boolean hasCustomBoxes(BlockState state, BlockGetter source, BlockPos pos) {
return true;
}
@Override
public boolean hasIndividualRenderVoxelShape() {
return true;
}
@Override
public InteractionResult use(BlockState state, Level worldIn, BlockPos pos, Player player, InteractionHand hand, BlockHitResult ray) {
return TileUtil.getTileEntity(worldIn, pos, CompactingDrawerTile.class).map(drawerTile -> drawerTile.onSlotActivated(player, hand, ray.getDirection(), ray.getLocation().x, ray.getLocation().y, ray.getLocation().z, getHit(state, worldIn, pos, player))).orElse(InteractionResult.PASS);
}
@Override
public void attack(BlockState state, Level worldIn, BlockPos pos, Player player) {
TileUtil.getTileEntity(worldIn, pos, CompactingDrawerTile.class).ifPresent(drawerTile -> drawerTile.onClicked(player, getHit(state, worldIn, pos, player)));
}
public int getHit(BlockState state, Level worldIn, BlockPos pos, Player player) {
HitResult result = RayTraceUtils.rayTraceSimple(worldIn, player, 32, 0);
if (result instanceof BlockHitResult) {
VoxelShape hit = RayTraceUtils.rayTraceVoxelShape((BlockHitResult) result, worldIn, player, 32, 0);
if (hit != null) {
if (hit.equals(Shapes.block())) return -1;
List<VoxelShape> shapes = new ArrayList<>(CACHED_SHAPES.get(state.getValue(RotatableBlock.FACING_HORIZONTAL))); //TODO
for (int i = 0; i < shapes.size(); i++) {
if (Shapes.joinIsNotEmpty(shapes.get(i), hit, BooleanOp.AND)) {
return i;
}
}
}
}
return -1;
}
@Override
public LootTable.Builder getLootTable(@Nonnull BasicBlockLootTables blockLootTables) {
CopyNbtFunction.Builder nbtBuilder = CopyNbtFunction.copyData(ContextNbtProvider.BLOCK_ENTITY);
nbtBuilder.copy("handler", "BlockEntityTag.handler");
return blockLootTables.droppingSelfWithNbt(this, nbtBuilder);
}
@Override
public NonNullList<ItemStack> getDynamicDrops(BlockState state, Level worldIn, BlockPos pos, BlockState newState, boolean isMoving) {
return NonNullList.create();
}
}

View File

@ -66,15 +66,15 @@ public class DrawerBlock extends RotatableBlock<DrawerTile> {
for (VoxelShape voxelShape : CACHED_SHAPES.get(FunctionalStorage.DrawerType.X_2).get(direction)) { for (VoxelShape voxelShape : CACHED_SHAPES.get(FunctionalStorage.DrawerType.X_2).get(direction)) {
AABB bounding = voxelShape.toAabbs().get(0); AABB bounding = voxelShape.toAabbs().get(0);
if (direction == Direction.NORTH || direction == Direction.SOUTH) { if (direction == Direction.NORTH || direction == Direction.SOUTH) {
CACHED_SHAPES.computeIfAbsent(FunctionalStorage.DrawerType.X_4, type1 -> MultimapBuilder.hashKeys().arrayListValues().build()).
put(direction, Shapes.box(bounding.minX, bounding.minY, bounding.minZ , 7/16D, bounding.maxY, bounding.maxZ));
CACHED_SHAPES.computeIfAbsent(FunctionalStorage.DrawerType.X_4, type1 -> MultimapBuilder.hashKeys().arrayListValues().build()). CACHED_SHAPES.computeIfAbsent(FunctionalStorage.DrawerType.X_4, type1 -> MultimapBuilder.hashKeys().arrayListValues().build()).
put(direction, Shapes.box(9/16D, bounding.minY, bounding.minZ ,bounding.maxX, bounding.maxY, bounding.maxZ)); put(direction, Shapes.box(9/16D, bounding.minY, bounding.minZ ,bounding.maxX, bounding.maxY, bounding.maxZ));
CACHED_SHAPES.computeIfAbsent(FunctionalStorage.DrawerType.X_4, type1 -> MultimapBuilder.hashKeys().arrayListValues().build()).
put(direction, Shapes.box(bounding.minX, bounding.minY, bounding.minZ , 7/16D, bounding.maxY, bounding.maxZ));
} else { } else {
CACHED_SHAPES.computeIfAbsent(FunctionalStorage.DrawerType.X_4, type1 -> MultimapBuilder.hashKeys().arrayListValues().build()). CACHED_SHAPES.computeIfAbsent(FunctionalStorage.DrawerType.X_4, type1 -> MultimapBuilder.hashKeys().arrayListValues().build()).
put(direction, Shapes.box(bounding.minX, bounding.minY, 7/16D,bounding.maxX, bounding.maxY, bounding.maxZ)); put(direction, Shapes.box(bounding.minX, bounding.minY, bounding.minZ , bounding.maxX, bounding.maxY, 7/16D));
CACHED_SHAPES.computeIfAbsent(FunctionalStorage.DrawerType.X_4, type1 -> MultimapBuilder.hashKeys().arrayListValues().build()). CACHED_SHAPES.computeIfAbsent(FunctionalStorage.DrawerType.X_4, type1 -> MultimapBuilder.hashKeys().arrayListValues().build()).
put(direction, Shapes.box(bounding.minX, bounding.minY, bounding.minZ , bounding.maxX, bounding.maxY, 9/16D)); put(direction, Shapes.box(bounding.minX, bounding.minY, 9/16D,bounding.maxX, bounding.maxY, bounding.maxZ));
} }
} }
} }

View File

@ -0,0 +1,122 @@
package com.buuz135.functionalstorage.block.tile;
import com.buuz135.functionalstorage.FunctionalStorage;
import com.buuz135.functionalstorage.inventory.BigInventoryHandler;
import com.buuz135.functionalstorage.inventory.CompactingInventoryHandler;
import com.buuz135.functionalstorage.util.CompactingUtil;
import com.hrznstudio.titanium.annotation.Save;
import com.hrznstudio.titanium.block.BasicTileBlock;
import com.hrznstudio.titanium.block.tile.ActiveTile;
import com.hrznstudio.titanium.util.RayTraceUtils;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.util.datafix.fixes.ItemStackTheFlatteningFix;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.HitResult;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.ItemHandlerHelper;
import net.minecraftforge.items.ItemStackHandler;
import org.jetbrains.annotations.NotNull;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.HashMap;
import java.util.UUID;
public class CompactingDrawerTile extends ActiveTile<CompactingDrawerTile> {
private static HashMap<UUID, Long> INTERACTION_LOGGER = new HashMap<>();
@Save
public CompactingInventoryHandler handler;
private final LazyOptional<IItemHandler> lazyStorage;
public CompactingDrawerTile(BasicTileBlock<CompactingDrawerTile> base, BlockPos pos, BlockState state) {
super(base, pos, state);
this.handler = new CompactingInventoryHandler() {
@Override
public void onChange() {
CompactingDrawerTile.this.markForUpdate();
}
};
lazyStorage = LazyOptional.of(() -> this.handler);
//TODO Check for the recipe on load
}
public InteractionResult onSlotActivated(Player playerIn, InteractionHand hand, Direction facing, double hitX, double hitY, double hitZ, int slot) {
if (super.onActivated(playerIn, hand, facing, hitX, hitY, hitZ) == InteractionResult.SUCCESS) {
return InteractionResult.SUCCESS;
}
if (slot == -1){
openGui(playerIn);
} else if (isServer()){
if (!handler.isSetup()){
ItemStack stack = playerIn.getItemInHand(hand).copy();
stack.setCount(1);
CompactingUtil compactingUtil = new CompactingUtil(this.level);
compactingUtil.setup(stack);
handler.setup(compactingUtil);
for (int i = 0; i < handler.getResultList().size(); i++) {
if (ItemStack.isSame(handler.getResultList().get(i).getResult(), stack)){
slot = i;
break;
}
}
}
ItemStack stack = playerIn.getItemInHand(hand);
if (!stack.isEmpty() && handler.isItemValid(slot, stack)) {
playerIn.setItemInHand(hand, handler.insertItem(slot, stack, false));
} else if (System.currentTimeMillis() - INTERACTION_LOGGER.getOrDefault(playerIn.getUUID(), System.currentTimeMillis()) < 300) {
for (ItemStack itemStack : playerIn.getInventory().items) {
if (!itemStack.isEmpty() && handler.insertItem(slot, itemStack, true).isEmpty()) {
handler.insertItem(slot, itemStack.copy(), false);
itemStack.setCount(0);
}
}
}
INTERACTION_LOGGER.put(playerIn.getUUID(), System.currentTimeMillis());
}
return InteractionResult.SUCCESS;
}
public void onClicked(Player playerIn, int slot) {
if (isServer()){
HitResult rayTraceResult = RayTraceUtils.rayTraceSimple(this.level, playerIn, 16, 0);
if (rayTraceResult.getType() == HitResult.Type.BLOCK) {
BlockHitResult blockResult = (BlockHitResult) rayTraceResult;
Direction facing = blockResult.getDirection();
if (facing.equals(this.getFacingDirection())){
ItemHandlerHelper.giveItemToPlayer(playerIn, handler.extractItem(slot, playerIn.isShiftKeyDown() ? 64 : 1, false));
}
}
}
}
@Nonnull
@Override
public <U> LazyOptional<U> getCapability(@Nonnull Capability<U> cap, @Nullable Direction side) {
if (cap == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) {
return lazyStorage.cast();
}
return super.getCapability(cap, side);
}
@NotNull
@Override
public CompactingDrawerTile getSelf() {
return this;
}
public CompactingInventoryHandler getHandler() {
return handler;
}
}

View File

@ -75,7 +75,7 @@ public class DrawerTile extends ActiveTile<DrawerTile> {
} }
public void onClicked(Player playerIn, int slot) { public void onClicked(Player playerIn, int slot) {
if (isServer()){ if (isServer() && slot != -1){
HitResult rayTraceResult = RayTraceUtils.rayTraceSimple(this.level, playerIn, 16, 0); HitResult rayTraceResult = RayTraceUtils.rayTraceSimple(this.level, playerIn, 16, 0);
if (rayTraceResult.getType() == HitResult.Type.BLOCK) { if (rayTraceResult.getType() == HitResult.Type.BLOCK) {
BlockHitResult blockResult = (BlockHitResult) rayTraceResult; BlockHitResult blockResult = (BlockHitResult) rayTraceResult;

View File

@ -0,0 +1,83 @@
package com.buuz135.functionalstorage.client;
import com.buuz135.functionalstorage.FunctionalStorage;
import com.buuz135.functionalstorage.block.tile.CompactingDrawerTile;
import com.buuz135.functionalstorage.block.tile.DrawerTile;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.math.Matrix3f;
import com.mojang.math.Quaternion;
import com.mojang.math.Vector3f;
import net.minecraft.ChatFormatting;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.Font;
import net.minecraft.client.renderer.LevelRenderer;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.block.model.ItemTransforms;
import net.minecraft.client.renderer.blockentity.BlockEntityRenderer;
import net.minecraft.core.Direction;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TextComponent;
import net.minecraft.world.item.BlockItem;
import net.minecraft.world.item.ItemStack;
public class CompactingDrawerRenderer implements BlockEntityRenderer<CompactingDrawerTile> {
private static final Matrix3f FAKE_NORMALS;
static {
Vector3f NORMAL = new Vector3f(1, 1, 1);
NORMAL.normalize();
FAKE_NORMALS = new Matrix3f(new Quaternion(NORMAL, 0, true));
}
@Override
public void render(CompactingDrawerTile tile, float partialTicks, PoseStack matrixStack, MultiBufferSource bufferIn, int combinedLightIn, int combinedOverlayIn) {
matrixStack.pushPose();
Direction facing = tile.getFacingDirection();
matrixStack.mulPose(Vector3f.YP.rotationDegrees(-180));
matrixStack.last().normal().load(FAKE_NORMALS);
if (facing == Direction.NORTH) {
//matrixStack.translate(0, 0, 1.016 / 16D);
matrixStack.translate(-1, 0, 0);
}
if (facing == Direction.EAST) {
matrixStack.translate(-1, 0, -1);
matrixStack.mulPose(Vector3f.YP.rotationDegrees(-90));
}
if (facing == Direction.SOUTH) {
matrixStack.translate(0, 0,-1);
matrixStack.mulPose(Vector3f.YP.rotationDegrees(-180));
}
if (facing == Direction.WEST) {
matrixStack.mulPose(Vector3f.YP.rotationDegrees(90));
}
combinedLightIn = LevelRenderer.getLightColor(tile.getLevel(), tile.getBlockPos().relative(facing));
ItemStack stack = tile.getHandler().getResultList().get(0).getResult();
if (!stack.isEmpty()){
matrixStack.pushPose();
matrixStack.translate(0.725, 0.30f, 0.0005f);
matrixStack.scale(0.5f, 0.5f, 1);
DrawerRenderer.renderStack(matrixStack, bufferIn, combinedLightIn, combinedOverlayIn, stack, tile.getHandler().getStackInSlot(0).getCount(), 0.02f);
matrixStack.popPose();
}
stack = tile.getHandler().getResultList().get(1).getResult();
if (!stack.isEmpty()){
matrixStack.pushPose();
matrixStack.translate(0.275, 0.30f, 0.0005f);
matrixStack.scale(0.5f, 0.5f, 1);
DrawerRenderer.renderStack(matrixStack, bufferIn, combinedLightIn, combinedOverlayIn, stack, tile.getHandler().getStackInSlot(1).getCount(), 0.02f);
matrixStack.popPose();
}
stack = tile.getHandler().getResultList().get(2).getResult();
if (!stack.isEmpty()){
matrixStack.pushPose();
matrixStack.translate(0.5, 0.75f, 0.0005f);
matrixStack.scale(0.5f, 0.5f, 1);
DrawerRenderer.renderStack(matrixStack, bufferIn, combinedLightIn, combinedOverlayIn, stack, tile.getHandler().getStackInSlot(2).getCount(), 0.02f);
matrixStack.popPose();
}
matrixStack.popPose();
}
}

View File

@ -14,6 +14,7 @@ import net.minecraft.client.renderer.LevelRenderer;
import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.block.model.ItemTransforms; import net.minecraft.client.renderer.block.model.ItemTransforms;
import net.minecraft.client.renderer.blockentity.BlockEntityRenderer; import net.minecraft.client.renderer.blockentity.BlockEntityRenderer;
import net.minecraft.client.resources.model.BakedModel;
import net.minecraft.core.Direction; import net.minecraft.core.Direction;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TextComponent; import net.minecraft.network.chat.TextComponent;
@ -36,7 +37,7 @@ public class DrawerRenderer implements BlockEntityRenderer<DrawerTile> {
Direction facing = tile.getFacingDirection(); Direction facing = tile.getFacingDirection();
matrixStack.mulPose(Vector3f.YP.rotationDegrees(-180)); matrixStack.mulPose(Vector3f.YP.rotationDegrees(-180));
matrixStack.last().normal().load(FAKE_NORMALS); if (facing != Direction.SOUTH) matrixStack.last().normal().load(FAKE_NORMALS);
if (facing == Direction.NORTH) { if (facing == Direction.NORTH) {
//matrixStack.translate(0, 0, 1.016 / 16D); //matrixStack.translate(0, 0, 1.016 / 16D);
matrixStack.translate(-1, 0, 0); matrixStack.translate(-1, 0, 0);
@ -52,6 +53,7 @@ public class DrawerRenderer implements BlockEntityRenderer<DrawerTile> {
if (facing == Direction.WEST) { if (facing == Direction.WEST) {
matrixStack.mulPose(Vector3f.YP.rotationDegrees(90)); matrixStack.mulPose(Vector3f.YP.rotationDegrees(90));
} }
matrixStack.translate(0,0,-0.5/16D);
combinedLightIn = LevelRenderer.getLightColor(tile.getLevel(), tile.getBlockPos().relative(facing)); combinedLightIn = LevelRenderer.getLightColor(tile.getLevel(), tile.getBlockPos().relative(facing));
if (tile.getDrawerType() == FunctionalStorage.DrawerType.X_1) render1Slot(matrixStack, bufferIn, combinedLightIn, combinedOverlayIn, tile); if (tile.getDrawerType() == FunctionalStorage.DrawerType.X_1) render1Slot(matrixStack, bufferIn, combinedLightIn, combinedOverlayIn, tile);
if (tile.getDrawerType() == FunctionalStorage.DrawerType.X_2) render2Slot(matrixStack, bufferIn, combinedLightIn, combinedOverlayIn, tile); if (tile.getDrawerType() == FunctionalStorage.DrawerType.X_2) render2Slot(matrixStack, bufferIn, combinedLightIn, combinedOverlayIn, tile);
@ -70,7 +72,7 @@ public class DrawerRenderer implements BlockEntityRenderer<DrawerTile> {
private void render2Slot(PoseStack matrixStack, MultiBufferSource bufferIn, int combinedLightIn, int combinedOverlayIn, DrawerTile tile){ private void render2Slot(PoseStack matrixStack, MultiBufferSource bufferIn, int combinedLightIn, int combinedOverlayIn, DrawerTile tile){
if (!tile.getHandler().getStackInSlot(0).isEmpty()){ if (!tile.getHandler().getStackInSlot(0).isEmpty()){
matrixStack.pushPose(); matrixStack.pushPose();
matrixStack.translate(0.5, 0.30f, 0.0005f); matrixStack.translate(0.5, 0.27f, 0.0005f);
matrixStack.scale(0.5f, 0.5f, 1); matrixStack.scale(0.5f, 0.5f, 1);
ItemStack stack = tile.getHandler().getStackInSlot(0); ItemStack stack = tile.getHandler().getStackInSlot(0);
renderStack(matrixStack, bufferIn, combinedLightIn, combinedOverlayIn, stack, stack.getCount(), 0.02f); renderStack(matrixStack, bufferIn, combinedLightIn, combinedOverlayIn, stack, stack.getCount(), 0.02f);
@ -78,7 +80,7 @@ public class DrawerRenderer implements BlockEntityRenderer<DrawerTile> {
} }
if (!tile.getHandler().getStackInSlot(1).isEmpty()){ if (!tile.getHandler().getStackInSlot(1).isEmpty()){
matrixStack.pushPose(); matrixStack.pushPose();
matrixStack.translate(0.5, 0.75f, 0.0005f); matrixStack.translate(0.5, 0.77f, 0.0005f);
matrixStack.scale(0.5f, 0.5f, 1); matrixStack.scale(0.5f, 0.5f, 1);
ItemStack stack = tile.getHandler().getStackInSlot(1); ItemStack stack = tile.getHandler().getStackInSlot(1);
renderStack(matrixStack, bufferIn, combinedLightIn, combinedOverlayIn, stack, stack.getCount(), 0.02f); renderStack(matrixStack, bufferIn, combinedLightIn, combinedOverlayIn, stack, stack.getCount(), 0.02f);
@ -88,7 +90,7 @@ public class DrawerRenderer implements BlockEntityRenderer<DrawerTile> {
private void render4Slot(PoseStack matrixStack, MultiBufferSource bufferIn, int combinedLightIn, int combinedOverlayIn, DrawerTile tile){ private void render4Slot(PoseStack matrixStack, MultiBufferSource bufferIn, int combinedLightIn, int combinedOverlayIn, DrawerTile tile){
if (!tile.getHandler().getStackInSlot(0).isEmpty()){ //BOTTOM RIGHT if (!tile.getHandler().getStackInSlot(0).isEmpty()){ //BOTTOM RIGHT
matrixStack.pushPose(); matrixStack.pushPose();
matrixStack.translate(0.725, 0.30f, 0.0005f); matrixStack.translate(0.75, 0.27f, 0.0005f);
matrixStack.scale(0.5f, 0.5f, 1); matrixStack.scale(0.5f, 0.5f, 1);
ItemStack stack = tile.getHandler().getStackInSlot(0); ItemStack stack = tile.getHandler().getStackInSlot(0);
renderStack(matrixStack, bufferIn, combinedLightIn, combinedOverlayIn, stack, stack.getCount(), 0.02f); renderStack(matrixStack, bufferIn, combinedLightIn, combinedOverlayIn, stack, stack.getCount(), 0.02f);
@ -96,7 +98,7 @@ public class DrawerRenderer implements BlockEntityRenderer<DrawerTile> {
} }
if (!tile.getHandler().getStackInSlot(1).isEmpty()){ //BOTTOM LEFT if (!tile.getHandler().getStackInSlot(1).isEmpty()){ //BOTTOM LEFT
matrixStack.pushPose(); matrixStack.pushPose();
matrixStack.translate(0.275, 0.30f, 0.0005f); matrixStack.translate(0.25, 0.27f, 0.0005f);
matrixStack.scale(0.5f, 0.5f, 1); matrixStack.scale(0.5f, 0.5f, 1);
ItemStack stack = tile.getHandler().getStackInSlot(1); ItemStack stack = tile.getHandler().getStackInSlot(1);
renderStack(matrixStack, bufferIn, combinedLightIn, combinedOverlayIn, stack, stack.getCount(), 0.02f); renderStack(matrixStack, bufferIn, combinedLightIn, combinedOverlayIn, stack, stack.getCount(), 0.02f);
@ -104,7 +106,7 @@ public class DrawerRenderer implements BlockEntityRenderer<DrawerTile> {
} }
if (!tile.getHandler().getStackInSlot(2).isEmpty()){ //TOP RIGHT if (!tile.getHandler().getStackInSlot(2).isEmpty()){ //TOP RIGHT
matrixStack.pushPose(); matrixStack.pushPose();
matrixStack.translate(0.725, 0.75f, 0.0005f); matrixStack.translate(0.75, 0.77f, 0.0005f);
matrixStack.scale(0.5f, 0.5f, 1); matrixStack.scale(0.5f, 0.5f, 1);
ItemStack stack = tile.getHandler().getStackInSlot(2); ItemStack stack = tile.getHandler().getStackInSlot(2);
renderStack(matrixStack, bufferIn, combinedLightIn, combinedOverlayIn, stack, stack.getCount(), 0.02f); renderStack(matrixStack, bufferIn, combinedLightIn, combinedOverlayIn, stack, stack.getCount(), 0.02f);
@ -112,7 +114,7 @@ public class DrawerRenderer implements BlockEntityRenderer<DrawerTile> {
} }
if (!tile.getHandler().getStackInSlot(3).isEmpty()){ //TOP LEFT if (!tile.getHandler().getStackInSlot(3).isEmpty()){ //TOP LEFT
matrixStack.pushPose(); matrixStack.pushPose();
matrixStack.translate(0.275, 0.75f, 0.0005f); matrixStack.translate(0.25, 0.77f, 0.0005f);
matrixStack.scale(0.5f, 0.5f, 1); matrixStack.scale(0.5f, 0.5f, 1);
ItemStack stack = tile.getHandler().getStackInSlot(3); ItemStack stack = tile.getHandler().getStackInSlot(3);
renderStack(matrixStack, bufferIn, combinedLightIn, combinedOverlayIn, stack, stack.getCount(), 0.02f); renderStack(matrixStack, bufferIn, combinedLightIn, combinedOverlayIn, stack, stack.getCount(), 0.02f);
@ -121,25 +123,30 @@ public class DrawerRenderer implements BlockEntityRenderer<DrawerTile> {
} }
private void renderStack(PoseStack matrixStack, MultiBufferSource bufferIn, int combinedLightIn, int combinedOverlayIn, ItemStack stack, int amount, float scale){ public static void renderStack(PoseStack matrixStack, MultiBufferSource bufferIn, int combinedLightIn, int combinedOverlayIn, ItemStack stack, int amount, float scale){
if (stack.getItem() instanceof BlockItem){ BakedModel model = Minecraft.getInstance().getItemRenderer().getModel(stack, Minecraft.getInstance().level, null, 0);
matrixStack.scale(0.5f, 0.5f, 0.0001f); if (model.isGui3d()){
matrixStack.translate(0,0, -0.23f);
matrixStack.scale(0.5f, 0.5f, 0.5f);
} else { } else {
matrixStack.scale(0.4f, 0.4f, 0.0001f); matrixStack.scale(0.4f, 0.4f, 0.4f);
} }
Minecraft.getInstance().getItemRenderer().renderStatic(stack, ItemTransforms.TransformType.GUI, combinedLightIn, combinedOverlayIn, matrixStack, bufferIn, 0);
if (!(stack.getItem() instanceof BlockItem)){ Minecraft.getInstance().getItemRenderer().renderStatic(stack, ItemTransforms.TransformType.NONE, combinedLightIn, combinedOverlayIn, matrixStack, bufferIn, 0);
if (!model.isGui3d()){
matrixStack.scale(1/0.4f, 1/0.4f, 1/0.0001f); matrixStack.scale(1/0.4f, 1/0.4f, 1/0.0001f);
matrixStack.scale(0.5f, 0.5f, 0.0001f); matrixStack.scale(0.5f, 0.5f, 0.0001f);
}else {
matrixStack.translate(0,0, 0.23f*2);
} }
renderText(matrixStack, bufferIn, combinedOverlayIn, new TextComponent(ChatFormatting.WHITE + "" + stack.getCount()), Direction.NORTH, scale); renderText(matrixStack, bufferIn, combinedOverlayIn, new TextComponent(ChatFormatting.WHITE + "" + amount), Direction.NORTH, scale);
} }
/* Thanks Mekanism */ /* Thanks Mekanism */
private void renderText(PoseStack matrix, MultiBufferSource renderer, int overlayLight, Component text, Direction side, float maxScale) { public static void renderText(PoseStack matrix, MultiBufferSource renderer, int overlayLight, Component text, Direction side, float maxScale) {
matrix.translate(0, -0.8, 0); matrix.translate(0, -0.745, 0);
float displayWidth = 1; float displayWidth = 1;

View File

@ -0,0 +1,162 @@
package com.buuz135.functionalstorage.inventory;
import com.buuz135.functionalstorage.util.CompactingUtil;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.item.ItemStack;
import net.minecraftforge.common.util.INBTSerializable;
import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.ItemHandlerHelper;
import javax.annotation.Nonnull;
import java.util.ArrayList;
import java.util.List;
public abstract class CompactingInventoryHandler implements IItemHandler, INBTSerializable<CompoundTag> {
public static String VOID = "Void";
public static String BIG_ITEMS = "BigItems";
public static String STACK = "Stack";
public static String AMOUNT = "Amount";
private final int TOTAL_AMOUNT = 8192 * 9 * 9;
private int amount;
private boolean voidItems;
private List<CompactingUtil.Result> resultList;
public CompactingInventoryHandler(){
this.resultList = new ArrayList<>();
for (int i = 0; i < 3; i++) {
this.resultList.add(i, new CompactingUtil.Result(ItemStack.EMPTY, 1));
}
this.voidItems = false;
}
@Override
public int getSlots() {
return 3;
}
@Nonnull
@Override
public ItemStack getStackInSlot(int slot) {
CompactingUtil.Result bigStack = this.resultList.get(slot);
ItemStack copied = bigStack.getResult().copy();
copied.setCount(this.amount / bigStack.getNeeded());
return copied;
}
@Nonnull
@Override
public ItemStack insertItem(int slot, @Nonnull ItemStack stack, boolean simulate) {
if (isItemValid(slot, stack)) {
CompactingUtil.Result result = this.resultList.get(slot);
int inserted = Math.min(TOTAL_AMOUNT - amount, stack.getCount() * result.getNeeded());
inserted = (int) (Math.floor(inserted / result.getNeeded()) * result.getNeeded());
if (!simulate){
this.amount = Math.min(this.amount + inserted, TOTAL_AMOUNT);
onChange();
}
if (inserted == stack.getCount() * result.getNeeded() || voidItems) return ItemStack.EMPTY;
return ItemHandlerHelper.copyStackWithSize(stack, stack.getCount() - inserted / result.getNeeded());
}
return stack;
}
public boolean isSetup(){
return !this.resultList.get(this.resultList.size() -1).getResult().isEmpty();
}
public void setup(CompactingUtil compactingUtil){
this.resultList = compactingUtil.getResults();
onChange();
}
public void reset(){
this.resultList.forEach(result -> {
result.setResult(ItemStack.EMPTY);
result.setNeeded(1);
});
}
@Nonnull
@Override
public ItemStack extractItem(int slot, int amount, boolean simulate) {
if (amount == 0) return ItemStack.EMPTY;
if (slot < 3){
CompactingUtil.Result bigStack = this.resultList.get(slot);
if (bigStack.getResult().isEmpty()) return ItemStack.EMPTY;
int stackAmount = bigStack.getNeeded() * amount;
if (stackAmount >= this.amount) {
ItemStack out = bigStack.getResult().copy();
int newAmount = (int) Math.floor(this.amount / bigStack.getNeeded());
if (!simulate) {
//TODO Dont change if locked
this.amount -= (newAmount * bigStack.getNeeded());
if (this.amount == 0) reset();
onChange();
}
out.setCount(newAmount);
return out;
} else {
if (!simulate) {
this.amount -= stackAmount;
onChange();
}
return ItemHandlerHelper.copyStackWithSize(bigStack.getResult(), amount);
}
}
return ItemStack.EMPTY;
}
@Override
public int getSlotLimit(int slot) {
return (int) Math.floor(TOTAL_AMOUNT / this.resultList.get(slot).getNeeded());
}
@Override
public boolean isItemValid(int slot, @Nonnull ItemStack stack) {
if (slot < 3){
CompactingUtil.Result bigStack = this.resultList.get(slot);
ItemStack fl = bigStack.getResult();
return !fl.isEmpty() && fl.sameItem(stack) && ItemStack.tagMatches(fl, stack);
}
return false;
}
@Override
public CompoundTag serializeNBT() {
CompoundTag compoundTag = new CompoundTag();
compoundTag.putBoolean(VOID, voidItems);
compoundTag.putInt(AMOUNT, this.amount);
CompoundTag items = new CompoundTag();
for (int i = 0; i < this.resultList.size(); i++) {
CompoundTag bigStack = new CompoundTag();
bigStack.put(STACK, this.resultList.get(i).getResult().serializeNBT());
bigStack.putInt(AMOUNT, this.resultList.get(i).getNeeded());
items.put(i + "", bigStack);
}
compoundTag.put(BIG_ITEMS, items);
return compoundTag;
}
@Override
public void deserializeNBT(CompoundTag nbt) {
this.voidItems = nbt.getBoolean(VOID);
this.amount = nbt.getInt(AMOUNT);
for (String allKey : nbt.getCompound(BIG_ITEMS).getAllKeys()) {
this.resultList.get(Integer.parseInt(allKey)).setResult(ItemStack.of(nbt.getCompound(BIG_ITEMS).getCompound(allKey).getCompound(STACK)));
this.resultList.get(Integer.parseInt(allKey)).setNeeded(Math.max(1, nbt.getCompound(BIG_ITEMS).getCompound(allKey).getInt(AMOUNT)));
}
}
public abstract void onChange();
public List<CompactingUtil.Result> getResultList() {
return resultList;
}
}

View File

@ -0,0 +1,237 @@
package com.buuz135.functionalstorage.util;
import net.minecraft.core.NonNullList;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.inventory.CraftingContainer;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.crafting.CraftingRecipe;
import net.minecraft.world.item.crafting.Ingredient;
import net.minecraft.world.item.crafting.RecipeType;
import net.minecraft.world.level.Level;
import java.util.*;
/**
* Some code in this class is from the original Storage Drawers
* findSimilar
* findAllMatchingRecipes
* tryMatch
* findLowerTier
*/
public class CompactingUtil {
private final Level level;
private List<Result> results;
public CompactingUtil(Level level) {
this.level = level;
this.results = new ArrayList<>();
}
public void setup(ItemStack stack){
results.add(new Result(stack, 1));
Result result = findUpperTier(stack);
if (!result.getResult().isEmpty()){
results.add(result);
result = findUpperTier(result.getResult());
if (!result.getResult().isEmpty()){
result.setNeeded(result.getNeeded() * this.results.get(this.results.size() - 1).getNeeded());
results.add(result);
}
}
boolean canFind = true;
while (canFind && results.size() < 3){
result = findLowerTier(results.get(0).getResult());
if (!result.getResult().isEmpty()){
for (Result result1 : results) {
result1.setNeeded(result1.getNeeded() * result.getNeeded());
}
result.setNeeded(1);
results.add(0, result);
}else{
canFind = false;
}
}
while (results.size() < 3){
results.add(0, new Result(ItemStack.EMPTY, 1));
}
}
public List<Result> getResults() {
return results;
}
private Result findUpperTier(ItemStack stack){
//Checking 3x3
int sizeCheck = 9;
CraftingContainer container = createContainerAndFill(3, stack);
List<ItemStack> outputs = findAllMatchingRecipes(container);
List<ItemStack> realOutputs = new ArrayList<>();
if (outputs.size() == 0){
//Checking 2x2
sizeCheck = 4;
container = createContainerAndFill(2, stack);
outputs = findAllMatchingRecipes(container);
}
if (outputs.size() > 0){
for (ItemStack output : outputs) {
container = createContainerAndFill(1, output);
List<ItemStack> reversed = findAllMatchingRecipes(container);
for (ItemStack reversedStack : reversed) {
if (reversedStack.getCount() != sizeCheck || !ItemStack.isSame(reversedStack, stack)){
continue;
}
realOutputs.add(output);
}
}
}
ItemStack similar = findSimilar(stack, realOutputs);
if (!similar.isEmpty()){
return new Result(similar, sizeCheck);
}
if (realOutputs.size() > 0){
return new Result(realOutputs.get(0), sizeCheck);
}
return new Result(ItemStack.EMPTY, 0);
}
private Result findLowerTier(ItemStack stack){
List<ItemStack> candidates = new ArrayList<>();
Map<ItemStack, Integer> candidatesRate = new HashMap<>();
for (CraftingRecipe craftingRecipe : level.getRecipeManager().getAllRecipesFor(RecipeType.CRAFTING)) {
ItemStack output = craftingRecipe.getResultItem();
if (!ItemStack.isSame(stack, output)) continue;
ItemStack match = tryMatch(stack, craftingRecipe.getIngredients());
if (!match.isEmpty()){
CraftingContainer container = createContainerAndFill(1, output);
List<ItemStack> matchStacks = findAllMatchingRecipes(container);
for (ItemStack matchStack : matchStacks) {
int recipeSize = craftingRecipe.getIngredients().size();
if (ItemStack.isSame(match, matchStack) && matchStack.getCount() == recipeSize){
candidates.add(match);
candidatesRate.put(match, recipeSize);
}
}
}
}
ItemStack similar = findSimilar(stack, candidates);
if (!similar.isEmpty()){
return new Result(similar, candidatesRate.get(similar));
}
if (candidates.size() > 0){
return new Result(candidates.get(0), candidatesRate.get(candidates.get(0)));
}
return new Result(ItemStack.EMPTY, 0);
}
private List<ItemStack> findAllMatchingRecipes(CraftingContainer crafting) {
List<ItemStack> candidates = new ArrayList<>();
for (CraftingRecipe recipe : level.getRecipeManager().getRecipesFor(RecipeType.CRAFTING, crafting, level)) {
if (recipe.matches(crafting, level)) {
ItemStack result = recipe.assemble(crafting);
if (!result.isEmpty())
candidates.add(result);
}
}
return candidates;
}
private ItemStack findSimilar(ItemStack reference, List<ItemStack> candidates) {
ResourceLocation referenceName = reference.getItem().getRegistryName();
if (referenceName != null) {
for (ItemStack candidate : candidates) {
ResourceLocation matchName = candidate.getItem().getRegistryName();
if (matchName != null) {
if (referenceName.getNamespace().equals(matchName.getNamespace()))
return candidate;
}
}
}
return ItemStack.EMPTY;
}
private ItemStack tryMatch(ItemStack stack, NonNullList<Ingredient> ingredients) {
if (ingredients.size() != 9 && ingredients.size() != 4)
return ItemStack.EMPTY;
Ingredient refIngredient = ingredients.get(0);
ItemStack[] refMatchingStacks = refIngredient.getItems();
if (refMatchingStacks.length == 0)
return ItemStack.EMPTY;
for (int i = 1, n = ingredients.size(); i < n; i++) {
Ingredient ingredient = ingredients.get(i);
ItemStack match = ItemStack.EMPTY;
for (ItemStack ingItemMatch : refMatchingStacks) {
if (ingredient.test(ingItemMatch)) {
match = ingItemMatch;
break;
}
}
if (match.isEmpty())
return ItemStack.EMPTY;
}
ItemStack match = findSimilar(stack, Arrays.asList(refMatchingStacks));
if (match.isEmpty())
match = refMatchingStacks[0];
return match;
}
private CraftingContainer createContainerAndFill(int size, ItemStack stack){
CraftingContainer inventoryCrafting = new CraftingContainer(new AbstractContainerMenu(null, 0) {
@Override
public boolean stillValid(Player playerIn) {
return false;
}
}, size, size);
for (int i = 0; i < size * size; i++) {
inventoryCrafting.setItem(i, stack.copy());
}
return inventoryCrafting;
}
public static class Result{
private ItemStack result;
private int needed;
public Result(ItemStack result, int needed) {
this.result = result;
this.needed = needed;
}
public ItemStack getResult() {
return result;
}
public void setResult(ItemStack result) {
this.result = result;
}
public int getNeeded() {
return needed;
}
public void setNeeded(int needed) {
this.needed = needed;
}
@Override
public String toString() {
return "Result{" +
"result=" + result +
", needed=" + needed +
'}';
}
}
}