diff --git a/.classpath b/.classpath index 22fc6b2..1efc791 100644 --- a/.classpath +++ b/.classpath @@ -1,6 +1,5 @@ - @@ -18,610 +17,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + diff --git a/.project b/.project index a1b1dc8..6b24044 100644 --- a/.project +++ b/.project @@ -2,21 +2,22 @@ quickiemod - + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.buildship.core.gradleprojectbuilder + + + + org.eclipse.jdt.core.javanature org.eclipse.buildship.core.gradleprojectnature - - - org.eclipse.jdt.core.javabuilder - - - - org.eclipse.buildship.core.gradleprojectbuilder - - - - - diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs index f3eb3df..db08bef 100644 --- a/.settings/org.eclipse.jdt.core.prefs +++ b/.settings/org.eclipse.jdt.core.prefs @@ -1,5 +1,5 @@ # -#Sat Jun 15 13:57:14 CEST 2024 +#Mon Jun 24 21:17:32 CEST 2024 eclipse.preferences.version=1 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled org.eclipse.jdt.core.compiler.codegen.targetPlatform=21 diff --git a/gradle.properties b/gradle.properties index 45528df..cbc0c06 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,7 +9,7 @@ yarn_mappings=1.21+build.2 loader_version=0.15.11 # Mod Properties -mod_version=1.21.0.1 +mod_version=1.21.0.2 maven_group=de.jottyfan.quickiemod archives_base_name=quickiemod diff --git a/src/main/java/de/jottyfan/quickiemod/QuickieMod.java b/src/main/java/de/jottyfan/quickiemod/QuickieMod.java index 4761c84..0b45dda 100644 --- a/src/main/java/de/jottyfan/quickiemod/QuickieMod.java +++ b/src/main/java/de/jottyfan/quickiemod/QuickieMod.java @@ -14,12 +14,14 @@ import net.fabricmc.api.ModInitializer; public class QuickieMod implements ModInitializer { public static final String MODID = "quickiemod"; - private static final Logger LOGGER = LoggerFactory.getLogger(MODID); + public static final Logger LOGGER = LoggerFactory.getLogger(MODID); @Override public void onInitialize() { LOGGER.info("loading {}", MODID); + RegistryManager.registerBlockEntityTypes(); + RegistryManager.registerScreenHandlerTypes(); RegistryManager.registerItems(); RegistryManager.registerEvents(); RegistryManager.registerBlocks(); diff --git a/src/main/java/de/jottyfan/quickiemod/QuickieModClient.java b/src/main/java/de/jottyfan/quickiemod/QuickieModClient.java index 7c3be44..95dd0e5 100644 --- a/src/main/java/de/jottyfan/quickiemod/QuickieModClient.java +++ b/src/main/java/de/jottyfan/quickiemod/QuickieModClient.java @@ -1,10 +1,13 @@ package de.jottyfan.quickiemod; import de.jottyfan.quickiemod.blocks.QuickieBlocks; +import de.jottyfan.quickiemod.container.BlockStackerScreen; +import de.jottyfan.quickiemod.container.ScreenHandlerTypes; import net.fabricmc.api.ClientModInitializer; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import net.fabricmc.fabric.api.blockrenderlayer.v1.BlockRenderLayerMap; +import net.minecraft.client.gui.screen.ingame.HandledScreens; import net.minecraft.client.render.RenderLayer; /** @@ -16,6 +19,7 @@ import net.minecraft.client.render.RenderLayer; public class QuickieModClient implements ClientModInitializer { @Override public void onInitializeClient() { +// HandledScreens.register(ScreenHandlerTypes.BLOCKSTACKER_SCREEN_HANDLER, BlockStackerScreen::new); BlockRenderLayerMap.INSTANCE.putBlock(QuickieBlocks.COTTONPLANT.getBlock(), RenderLayer.getCutout()); BlockRenderLayerMap.INSTANCE.putBlock(QuickieBlocks.CANOLAPLANT.getBlock(), RenderLayer.getCutout()); } diff --git a/src/main/java/de/jottyfan/quickiemod/blockentity/BlockEntityTypes.java b/src/main/java/de/jottyfan/quickiemod/blockentity/BlockEntityTypes.java index 9f9532f..9f1da77 100644 --- a/src/main/java/de/jottyfan/quickiemod/blockentity/BlockEntityTypes.java +++ b/src/main/java/de/jottyfan/quickiemod/blockentity/BlockEntityTypes.java @@ -29,4 +29,9 @@ public class BlockEntityTypes { BlockEntityType.Builder.create(DrillBlockWestEntity::new, QuickieBlocks.DRILL_WEST.getBlock()).build(null)); public static final BlockEntityType DRILL_NORTH = Registry.register(Registries.BLOCK_ENTITY_TYPE, BlockEntityIdentity.DRILL_NORTH, BlockEntityType.Builder.create(DrillBlockNorthEntity::new, QuickieBlocks.DRILL_NORTH.getBlock()).build(null)); + public static final BlockEntityType BLOCKSTACKER_ENTITY = Registry.register(Registries.BLOCK_ENTITY_TYPE, + BlockEntityIdentity.BLOCKSTACKERUP, + BlockEntityType.Builder.create(BlockStackerEntity::new, QuickieBlocks.BLOCKSTACKERUP.getBlock(), QuickieBlocks.BLOCKSTACKERDOWN.getBlock(), + QuickieBlocks.BLOCKSTACKEREAST.getBlock(), QuickieBlocks.BLOCKSTACKERWEST.getBlock(), QuickieBlocks.BLOCKSTACKERNORTH.getBlock(), + QuickieBlocks.BLOCKSTACKERSOUTH.getBlock()).build(null)); } diff --git a/src/main/java/de/jottyfan/quickiemod/blockentity/BlockStackerEntity.java b/src/main/java/de/jottyfan/quickiemod/blockentity/BlockStackerEntity.java new file mode 100644 index 0000000..09d380b --- /dev/null +++ b/src/main/java/de/jottyfan/quickiemod/blockentity/BlockStackerEntity.java @@ -0,0 +1,265 @@ +package de.jottyfan.quickiemod.blockentity; + +import java.util.ArrayList; +import java.util.List; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import de.jottyfan.quickiemod.QuickieMod; +import de.jottyfan.quickiemod.blocks.help.BlockStacker; +import de.jottyfan.quickiemod.container.BlockStackerScreenHandler; +import de.jottyfan.quickiemod.container.ImplementedInventory; +import net.minecraft.block.BlockState; +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.block.entity.LootableContainerBlockEntity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.entity.player.PlayerInventory; +import net.minecraft.inventory.Inventories; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; +import net.minecraft.nbt.NbtCompound; +import net.minecraft.registry.RegistryWrapper.WrapperLookup; +import net.minecraft.screen.NamedScreenHandlerFactory; +import net.minecraft.screen.ScreenHandler; +import net.minecraft.text.Text; +import net.minecraft.util.collection.DefaultedList; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; + +/** + * + * @author jotty + * + */ +public class BlockStackerEntity extends BlockEntity implements NamedScreenHandlerFactory, ImplementedInventory { + private static final Logger LOGGER = LoggerFactory.getLogger(QuickieMod.MODID); + + private final DefaultedList inventory = DefaultedList.ofSize(BlockStackerScreenHandler.SLOTSIZE, ItemStack.EMPTY); + + public BlockStackerEntity(BlockPos blockPos, BlockState blockState) { + super(BlockEntityTypes.BLOCKSTACKER_ENTITY, blockPos, blockState); + } + + @Override + public DefaultedList getItems() { + return inventory; + } + + public List getWhiteList() { + int counter = 0; + List list = new ArrayList<>(); + for (ItemStack stack : inventory) { + counter++; + if (counter < 10) { // first 9 items are whitelist items + list.add(stack); + } + } + return list; + } + + public List getBlackList() { + int counter = 0; + List list = new ArrayList<>(); + for (ItemStack stack : inventory) { + counter++; + if (counter > 9) { // second 9 items are blacklist items + list.add(stack); + } + } + return list; + } + + @Override + public ScreenHandler createMenu(int syncId, PlayerInventory playerInventory, PlayerEntity player) { + return new BlockStackerScreenHandler(syncId, playerInventory, this); + } + + @Override + public Text getDisplayName() { + return Text.translatable(getCachedState().getBlock().getTranslationKey()); + } + + @Override + protected void readNbt(NbtCompound nbt, WrapperLookup registryLookup) { + super.readNbt(nbt, registryLookup); + Inventories.readNbt(nbt, inventory, registryLookup); + } + + @Override + protected void writeNbt(NbtCompound nbt, WrapperLookup registryLookup) { + Inventories.writeNbt(nbt, inventory, registryLookup); + super.writeNbt(nbt, registryLookup); + } + + /** + * if whitelist, return true if current == pattern; return false otherwise + * + * @param current the current item stack + * @param pattern the item stack to compare with + * @param whitelist if true, filter only current == pattern, if false, filter + * all but that + * @return true or false + */ + public static final Boolean filter(ItemStack current, ItemStack pattern, Boolean whitelist) { + Boolean matches = pattern.getItem().equals(current.getItem()); + return whitelist ? matches : !matches; + } + + public static void tick(World world, BlockPos pos, BlockState state, BlockStackerEntity entity) { + if (!world.isClient) { + pos.down(); + BlockStacker block = (BlockStacker) state.getBlock(); + BlockEntity source = world.getBlockEntity(pos.offset(block.getSourceOffset())); + BlockEntity dest = world.getBlockEntity(pos.offset(block.getDestOffset())); + Boolean sourceIsLootable = source instanceof LootableContainerBlockEntity; + Boolean destIsLootable = dest instanceof LootableContainerBlockEntity; + if (sourceIsLootable && destIsLootable) { + LootableContainerBlockEntity lootableSource = (LootableContainerBlockEntity) source; + LootableContainerBlockEntity lootableDest = (LootableContainerBlockEntity) dest; + transferOneStack(lootableSource, lootableDest, entity.getWhiteList(), entity.getBlackList()); + } + } + } + + private static final Boolean transferOneStack(LootableContainerBlockEntity source, LootableContainerBlockEntity dest, List whiteList, List blackList) { + + // whitelist behaviour + List checked = new ArrayList<>(); + + // this way, we block whitelist items that are in the blacklist + for (ItemStack stack : blackList) { + if (stack != null && !stack.isEmpty()) { + checked.add(stack.getItem()); + } + } + Boolean found = false; + + if (hasItems(whiteList)) { + Item matchItem = findNextItem(whiteList, checked); + while(!found && matchItem != null) { + checked.add(matchItem); + List matchItems = new ArrayList<>(); + matchItems.add(matchItem); + found = transferOneStack(source, dest, matchItems, true); + matchItem = findNextItem(whiteList, checked); + } + } else { + // transport all but the items of the blacklist + found = transferOneStack(source, dest, checked, false); + } + return found; + } + + private static final Boolean transferOneStack(LootableContainerBlockEntity source, LootableContainerBlockEntity dest, + List ignoreItems, Boolean whitelist) { + Boolean result = false; + Integer sourceSlot = findItemStackPos(source, ignoreItems, whitelist); + if (sourceSlot != null && !Items.AIR.equals(source.getStack(sourceSlot).getItem())) { + ItemStack sourceStack = source.getStack(sourceSlot); + Integer destSlot = findItemStackPos(dest, sourceStack); + if (destSlot != null) { + Integer occupied = dest.getStack(destSlot).getCount(); + Integer free = dest.getStack(destSlot).getMaxCount() - occupied; + Integer candidates = source.getStack(sourceSlot).getCount(); + Integer travellers = candidates > free ? free : candidates; + if (travellers > 0) { + LOGGER.debug("transfer {}/{} of {} from slot {} to slot {} on top of {} ones", travellers, candidates, + source.getStack(sourceSlot).getItem().toString(), sourceSlot, destSlot, occupied); + source.getStack(sourceSlot).decrement(travellers); + if (source.getStack(sourceSlot).getCount() < 1) { + source.removeStack(sourceSlot); // make empty slots really empty + } + dest.getStack(destSlot).increment(travellers); + result = true; + } + } else { + Integer destFreeSlot = findItemStackPos(dest, true); + if (destFreeSlot != null) { + LOGGER.debug("transfer all of {} from slot {} to slot {}", source.getStack(sourceSlot).getItem().toString(), + sourceSlot, destSlot); + dest.setStack(destFreeSlot, source.removeStack(sourceSlot)); + result = true; + } + } + } + return result; + } + + private static final Boolean hasItems(List list) { + Boolean result = false; + for (ItemStack stack : list) { + result = result || (stack != null && !stack.isEmpty() && stack.getCount() > 0); + } + return result; + } + + private static final Item findNextItem(List inventory, List exclude) { + for (ItemStack stack : inventory) { + if (!stack.isEmpty()) { + Item item = stack.getItem(); + if (!exclude.contains(item)) { + return item; + } + } + } + return null; + } + + private static final Integer findItemStackPos(LootableContainerBlockEntity lcbe, ItemStack sourceStack) { + Integer counter = lcbe.size(); + while (counter > 0) { + counter--; + ItemStack stack = lcbe.getStack(counter); + if (sourceStack.getItem().equals(stack.getItem())) { + if (stack.getCount() < stack.getMaxCount()) { + return counter; + } + } + } + return null; + } + + private static final Integer findItemStackPos(LootableContainerBlockEntity lcbe, Boolean empty) { + Integer counter = lcbe.size(); + while (counter > 0) { + counter--; + ItemStack stack = lcbe.getStack(counter); + if (empty.equals(ItemStack.EMPTY.equals(stack))) { + return counter; + } + } + return null; + } + + private static final Integer findItemStackPos(LootableContainerBlockEntity lcbe, List filterItems, Boolean whitelist) { + if (whitelist == null) { + whitelist = true; + LOGGER.error("whitelist is null"); + } + if (filterItems == null || filterItems.size() < 1) { + if (whitelist) { + return null; + } else { + return findItemStackPos(lcbe, false); + } + } else { + Integer counter = lcbe.size(); + while (counter > 0) { + counter--; + ItemStack stack = lcbe.getStack(counter); + Boolean found = whitelist ? filterItems.contains(stack.getItem()) : !filterItems.contains(stack.getItem()); + if (found) { + return counter; + } + } + return null; + } + } + + @Override + public int size() { + return inventory.size(); + } +} diff --git a/src/main/java/de/jottyfan/quickiemod/blocks/BlockStackerDown.java b/src/main/java/de/jottyfan/quickiemod/blocks/BlockStackerDown.java new file mode 100644 index 0000000..e306b03 --- /dev/null +++ b/src/main/java/de/jottyfan/quickiemod/blocks/BlockStackerDown.java @@ -0,0 +1,111 @@ +package de.jottyfan.quickiemod.blocks; + +import java.util.List; + +import com.mojang.serialization.MapCodec; + +import de.jottyfan.quickiemod.blockentity.BlockEntityTypes; +import de.jottyfan.quickiemod.blockentity.BlockStackerEntity; +import de.jottyfan.quickiemod.blocks.help.BlockStacker; +import net.minecraft.block.AbstractBlock; +import net.minecraft.block.BlockRenderType; +import net.minecraft.block.BlockState; +import net.minecraft.block.BlockWithEntity; +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.block.entity.BlockEntityTicker; +import net.minecraft.block.entity.BlockEntityType; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.loot.context.LootContextParameterSet.Builder; +import net.minecraft.screen.NamedScreenHandlerFactory; +import net.minecraft.screen.ScreenHandler; +import net.minecraft.util.ActionResult; +import net.minecraft.util.ItemScatterer; +import net.minecraft.util.hit.BlockHitResult; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Direction; +import net.minecraft.world.World; + +/** + * + * @author jotty + * + */ +public class BlockStackerDown extends BlockWithEntity implements BlockStacker { + + public BlockStackerDown() { + super(AbstractBlock.Settings.create().hardness(2.5f)); + } + + @Override + public Direction getSourceOffset() { + return Direction.UP; + } + + @Override + public Direction getDestOffset() { + return Direction.DOWN; + } + + @Override + public BlockEntity createBlockEntity(BlockPos pos, BlockState state) { + return new BlockStackerEntity(pos, state); + } + + @Override + public BlockRenderType getRenderType(BlockState state) { + return BlockRenderType.MODEL; + } + + @Override + public List getDroppedStacks(BlockState state, Builder builder) { + return List.of(new ItemStack(QuickieBlocks.BLOCKSTACKERDOWN.getBlock())); + } + + @Override + public BlockEntityTicker getTicker(World world, BlockState state, + BlockEntityType type) { + return validateTicker(type, BlockEntityTypes.BLOCKSTACKER_ENTITY, + (world1, pos, state1, be) -> BlockStackerEntity.tick(world1, pos, state1, be)); + } + + @Override + protected ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, BlockHitResult hit) { +// if (!world.isClient) { +// NamedScreenHandlerFactory screenHandlerFactory = state.createScreenHandlerFactory(world, pos); +// if (screenHandlerFactory != null) { +// player.openHandledScreen(screenHandlerFactory); +// } +// } + return ActionResult.SUCCESS; + } + + @Override + public void onStateReplaced(BlockState state, World world, BlockPos pos, BlockState newState, boolean moved) { + if (state.getBlock() != newState.getBlock()) { + BlockEntity blockEntity = world.getBlockEntity(pos); + if (blockEntity instanceof BlockStackerEntity) { + ItemScatterer.spawn(world, pos, (BlockStackerEntity) blockEntity); + // update comparators + world.updateComparators(pos, this); + } + super.onStateReplaced(state, world, pos, newState, moved); + } + } + + @Override + public boolean hasComparatorOutput(BlockState state) { + return true; + } + + @Override + public int getComparatorOutput(BlockState state, World world, BlockPos pos) { + return ScreenHandler.calculateComparatorOutput(world.getBlockEntity(pos)); + } + + @Override + protected MapCodec getCodec() { + // TODO Auto-generated method stub + return null; + } +} diff --git a/src/main/java/de/jottyfan/quickiemod/blocks/BlockStackerEast.java b/src/main/java/de/jottyfan/quickiemod/blocks/BlockStackerEast.java new file mode 100644 index 0000000..605726c --- /dev/null +++ b/src/main/java/de/jottyfan/quickiemod/blocks/BlockStackerEast.java @@ -0,0 +1,111 @@ +package de.jottyfan.quickiemod.blocks; + +import java.util.List; + +import com.mojang.serialization.MapCodec; + +import de.jottyfan.quickiemod.blockentity.BlockEntityTypes; +import de.jottyfan.quickiemod.blockentity.BlockStackerEntity; +import de.jottyfan.quickiemod.blocks.help.BlockStacker; +import net.minecraft.block.AbstractBlock; +import net.minecraft.block.BlockRenderType; +import net.minecraft.block.BlockState; +import net.minecraft.block.BlockWithEntity; +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.block.entity.BlockEntityTicker; +import net.minecraft.block.entity.BlockEntityType; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.loot.context.LootContextParameterSet.Builder; +import net.minecraft.screen.NamedScreenHandlerFactory; +import net.minecraft.screen.ScreenHandler; +import net.minecraft.util.ActionResult; +import net.minecraft.util.ItemScatterer; +import net.minecraft.util.hit.BlockHitResult; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Direction; +import net.minecraft.world.World; + +/** + * + * @author jotty + * + */ +public class BlockStackerEast extends BlockWithEntity implements BlockStacker { + + public BlockStackerEast() { + super(AbstractBlock.Settings.create().hardness(2.5f)); + } + + @Override + public Direction getSourceOffset() { + return Direction.WEST; + } + + @Override + public Direction getDestOffset() { + return Direction.EAST; + } + + @Override + public BlockEntity createBlockEntity(BlockPos pos, BlockState state) { + return new BlockStackerEntity(pos, state); + } + + @Override + public BlockRenderType getRenderType(BlockState state) { + return BlockRenderType.MODEL; + } + + @Override + public List getDroppedStacks(BlockState state, Builder builder) { + return List.of(new ItemStack(QuickieBlocks.BLOCKSTACKEREAST.getBlock())); + } + + @Override + public BlockEntityTicker getTicker(World world, BlockState state, + BlockEntityType type) { + return validateTicker(type, BlockEntityTypes.BLOCKSTACKER_ENTITY, + (world1, pos, state1, be) -> BlockStackerEntity.tick(world1, pos, state1, be)); + } + + @Override + protected ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, BlockHitResult hit) { + if (!world.isClient) { + NamedScreenHandlerFactory screenHandlerFactory = state.createScreenHandlerFactory(world, pos); + if (screenHandlerFactory != null) { + player.openHandledScreen(screenHandlerFactory); + } + } + return ActionResult.SUCCESS; + } + + @Override + public void onStateReplaced(BlockState state, World world, BlockPos pos, BlockState newState, boolean moved) { + if (state.getBlock() != newState.getBlock()) { + BlockEntity blockEntity = world.getBlockEntity(pos); + if (blockEntity instanceof BlockStackerEntity) { + ItemScatterer.spawn(world, pos, (BlockStackerEntity) blockEntity); + // update comparators + world.updateComparators(pos, this); + } + super.onStateReplaced(state, world, pos, newState, moved); + } + } + + @Override + public boolean hasComparatorOutput(BlockState state) { + return true; + } + + @Override + public int getComparatorOutput(BlockState state, World world, BlockPos pos) { + return ScreenHandler.calculateComparatorOutput(world.getBlockEntity(pos)); + } + + @Override + protected MapCodec getCodec() { + // TODO Auto-generated method stub + return null; + } +} diff --git a/src/main/java/de/jottyfan/quickiemod/blocks/BlockStackerNorth.java b/src/main/java/de/jottyfan/quickiemod/blocks/BlockStackerNorth.java new file mode 100644 index 0000000..c34cda7 --- /dev/null +++ b/src/main/java/de/jottyfan/quickiemod/blocks/BlockStackerNorth.java @@ -0,0 +1,111 @@ +package de.jottyfan.quickiemod.blocks; + +import java.util.List; + +import com.mojang.serialization.MapCodec; + +import de.jottyfan.quickiemod.blockentity.BlockEntityTypes; +import de.jottyfan.quickiemod.blockentity.BlockStackerEntity; +import de.jottyfan.quickiemod.blocks.help.BlockStacker; +import net.minecraft.block.AbstractBlock; +import net.minecraft.block.BlockRenderType; +import net.minecraft.block.BlockState; +import net.minecraft.block.BlockWithEntity; +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.block.entity.BlockEntityTicker; +import net.minecraft.block.entity.BlockEntityType; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.loot.context.LootContextParameterSet.Builder; +import net.minecraft.screen.NamedScreenHandlerFactory; +import net.minecraft.screen.ScreenHandler; +import net.minecraft.util.ActionResult; +import net.minecraft.util.ItemScatterer; +import net.minecraft.util.hit.BlockHitResult; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Direction; +import net.minecraft.world.World; + +/** + * + * @author jotty + * + */ +public class BlockStackerNorth extends BlockWithEntity implements BlockStacker { + + public BlockStackerNorth() { + super(AbstractBlock.Settings.create().hardness(2.5f)); + } + + @Override + public Direction getSourceOffset() { + return Direction.SOUTH; + } + + @Override + public Direction getDestOffset() { + return Direction.NORTH; + } + + @Override + public BlockEntity createBlockEntity(BlockPos pos, BlockState state) { + return new BlockStackerEntity(pos, state); + } + + @Override + public BlockRenderType getRenderType(BlockState state) { + return BlockRenderType.MODEL; + } + + @Override + public List getDroppedStacks(BlockState state, Builder builder) { + return List.of(new ItemStack(QuickieBlocks.BLOCKSTACKERNORTH.getBlock())); + } + + @Override + public BlockEntityTicker getTicker(World world, BlockState state, + BlockEntityType type) { + return validateTicker(type, BlockEntityTypes.BLOCKSTACKER_ENTITY, + (world1, pos, state1, be) -> BlockStackerEntity.tick(world1, pos, state1, be)); + } + + @Override + protected ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, BlockHitResult hit) { + if (!world.isClient) { + NamedScreenHandlerFactory screenHandlerFactory = state.createScreenHandlerFactory(world, pos); + if (screenHandlerFactory != null) { + player.openHandledScreen(screenHandlerFactory); + } + } + return ActionResult.SUCCESS; + } + + @Override + public void onStateReplaced(BlockState state, World world, BlockPos pos, BlockState newState, boolean moved) { + if (state.getBlock() != newState.getBlock()) { + BlockEntity blockEntity = world.getBlockEntity(pos); + if (blockEntity instanceof BlockStackerEntity) { + ItemScatterer.spawn(world, pos, (BlockStackerEntity) blockEntity); + // update comparators + world.updateComparators(pos, this); + } + super.onStateReplaced(state, world, pos, newState, moved); + } + } + + @Override + public boolean hasComparatorOutput(BlockState state) { + return true; + } + + @Override + public int getComparatorOutput(BlockState state, World world, BlockPos pos) { + return ScreenHandler.calculateComparatorOutput(world.getBlockEntity(pos)); + } + + @Override + protected MapCodec getCodec() { + // TODO Auto-generated method stub + return null; + } +} diff --git a/src/main/java/de/jottyfan/quickiemod/blocks/BlockStackerSouth.java b/src/main/java/de/jottyfan/quickiemod/blocks/BlockStackerSouth.java new file mode 100644 index 0000000..afbb7b2 --- /dev/null +++ b/src/main/java/de/jottyfan/quickiemod/blocks/BlockStackerSouth.java @@ -0,0 +1,111 @@ +package de.jottyfan.quickiemod.blocks; + +import java.util.List; + +import com.mojang.serialization.MapCodec; + +import de.jottyfan.quickiemod.blockentity.BlockEntityTypes; +import de.jottyfan.quickiemod.blockentity.BlockStackerEntity; +import de.jottyfan.quickiemod.blocks.help.BlockStacker; +import net.minecraft.block.AbstractBlock; +import net.minecraft.block.BlockRenderType; +import net.minecraft.block.BlockState; +import net.minecraft.block.BlockWithEntity; +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.block.entity.BlockEntityTicker; +import net.minecraft.block.entity.BlockEntityType; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.loot.context.LootContextParameterSet.Builder; +import net.minecraft.screen.NamedScreenHandlerFactory; +import net.minecraft.screen.ScreenHandler; +import net.minecraft.util.ActionResult; +import net.minecraft.util.ItemScatterer; +import net.minecraft.util.hit.BlockHitResult; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Direction; +import net.minecraft.world.World; + +/** + * + * @author jotty + * + */ +public class BlockStackerSouth extends BlockWithEntity implements BlockStacker { + + public BlockStackerSouth() { + super(AbstractBlock.Settings.create().hardness(2.5f)); + } + + @Override + public Direction getSourceOffset() { + return Direction.NORTH; + } + + @Override + public Direction getDestOffset() { + return Direction.SOUTH; + } + + @Override + public BlockEntity createBlockEntity(BlockPos pos, BlockState state) { + return new BlockStackerEntity(pos, state); + } + + @Override + public BlockRenderType getRenderType(BlockState state) { + return BlockRenderType.MODEL; + } + + @Override + public List getDroppedStacks(BlockState state, Builder builder) { + return List.of(new ItemStack(QuickieBlocks.BLOCKSTACKERSOUTH.getBlock())); + } + + @Override + public BlockEntityTicker getTicker(World world, BlockState state, + BlockEntityType type) { + return validateTicker(type, BlockEntityTypes.BLOCKSTACKER_ENTITY, + (world1, pos, state1, be) -> BlockStackerEntity.tick(world1, pos, state1, be)); + } + + @Override + protected ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, BlockHitResult hit) { + if (!world.isClient) { + NamedScreenHandlerFactory screenHandlerFactory = state.createScreenHandlerFactory(world, pos); + if (screenHandlerFactory != null) { + player.openHandledScreen(screenHandlerFactory); + } + } + return ActionResult.SUCCESS; + } + + @Override + public void onStateReplaced(BlockState state, World world, BlockPos pos, BlockState newState, boolean moved) { + if (state.getBlock() != newState.getBlock()) { + BlockEntity blockEntity = world.getBlockEntity(pos); + if (blockEntity instanceof BlockStackerEntity) { + ItemScatterer.spawn(world, pos, (BlockStackerEntity) blockEntity); + // update comparators + world.updateComparators(pos, this); + } + super.onStateReplaced(state, world, pos, newState, moved); + } + } + + @Override + public boolean hasComparatorOutput(BlockState state) { + return true; + } + + @Override + public int getComparatorOutput(BlockState state, World world, BlockPos pos) { + return ScreenHandler.calculateComparatorOutput(world.getBlockEntity(pos)); + } + + @Override + protected MapCodec getCodec() { + // TODO Auto-generated method stub + return null; + } +} diff --git a/src/main/java/de/jottyfan/quickiemod/blocks/BlockStackerUp.java b/src/main/java/de/jottyfan/quickiemod/blocks/BlockStackerUp.java new file mode 100644 index 0000000..67d13e8 --- /dev/null +++ b/src/main/java/de/jottyfan/quickiemod/blocks/BlockStackerUp.java @@ -0,0 +1,111 @@ +package de.jottyfan.quickiemod.blocks; + +import java.util.List; + +import com.mojang.serialization.MapCodec; + +import de.jottyfan.quickiemod.blockentity.BlockEntityTypes; +import de.jottyfan.quickiemod.blockentity.BlockStackerEntity; +import de.jottyfan.quickiemod.blocks.help.BlockStacker; +import net.minecraft.block.AbstractBlock; +import net.minecraft.block.BlockRenderType; +import net.minecraft.block.BlockState; +import net.minecraft.block.BlockWithEntity; +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.block.entity.BlockEntityTicker; +import net.minecraft.block.entity.BlockEntityType; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.loot.context.LootContextParameterSet.Builder; +import net.minecraft.screen.NamedScreenHandlerFactory; +import net.minecraft.screen.ScreenHandler; +import net.minecraft.util.ActionResult; +import net.minecraft.util.ItemScatterer; +import net.minecraft.util.hit.BlockHitResult; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Direction; +import net.minecraft.world.World; + +/** + * + * @author jotty + * + */ +public class BlockStackerUp extends BlockWithEntity implements BlockStacker { + + public BlockStackerUp() { + super(AbstractBlock.Settings.create().hardness(2.5f)); + } + + @Override + public Direction getSourceOffset() { + return Direction.DOWN; + } + + @Override + public Direction getDestOffset() { + return Direction.UP; + } + + @Override + public BlockEntity createBlockEntity(BlockPos pos, BlockState state) { + return new BlockStackerEntity(pos, state); + } + + @Override + public BlockRenderType getRenderType(BlockState state) { + return BlockRenderType.MODEL; + } + + @Override + public List getDroppedStacks(BlockState state, Builder builder) { + return List.of(new ItemStack(QuickieBlocks.BLOCKSTACKERUP.getBlock())); + } + + @Override + public BlockEntityTicker getTicker(World world, BlockState state, + BlockEntityType type) { + return validateTicker(type, BlockEntityTypes.BLOCKSTACKER_ENTITY, + (world1, pos, state1, be) -> BlockStackerEntity.tick(world1, pos, state1, be)); + } + + @Override + protected ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, BlockHitResult hit) { + if (!world.isClient) { + NamedScreenHandlerFactory screenHandlerFactory = state.createScreenHandlerFactory(world, pos); + if (screenHandlerFactory != null) { + player.openHandledScreen(screenHandlerFactory); + } + } + return ActionResult.SUCCESS; + } + + @Override + public void onStateReplaced(BlockState state, World world, BlockPos pos, BlockState newState, boolean moved) { + if (state.getBlock() != newState.getBlock()) { + BlockEntity blockEntity = world.getBlockEntity(pos); + if (blockEntity instanceof BlockStackerEntity) { + ItemScatterer.spawn(world, pos, (BlockStackerEntity) blockEntity); + // update comparators + world.updateComparators(pos, this); + } + super.onStateReplaced(state, world, pos, newState, moved); + } + } + + @Override + public boolean hasComparatorOutput(BlockState state) { + return true; + } + + @Override + public int getComparatorOutput(BlockState state, World world, BlockPos pos) { + return ScreenHandler.calculateComparatorOutput(world.getBlockEntity(pos)); + } + + @Override + protected MapCodec getCodec() { + // TODO Auto-generated method stub + return null; + } +} diff --git a/src/main/java/de/jottyfan/quickiemod/blocks/BlockStackerWest.java b/src/main/java/de/jottyfan/quickiemod/blocks/BlockStackerWest.java new file mode 100644 index 0000000..f970db8 --- /dev/null +++ b/src/main/java/de/jottyfan/quickiemod/blocks/BlockStackerWest.java @@ -0,0 +1,111 @@ +package de.jottyfan.quickiemod.blocks; + +import java.util.List; + +import com.mojang.serialization.MapCodec; + +import de.jottyfan.quickiemod.blockentity.BlockEntityTypes; +import de.jottyfan.quickiemod.blockentity.BlockStackerEntity; +import de.jottyfan.quickiemod.blocks.help.BlockStacker; +import net.minecraft.block.AbstractBlock; +import net.minecraft.block.BlockRenderType; +import net.minecraft.block.BlockState; +import net.minecraft.block.BlockWithEntity; +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.block.entity.BlockEntityTicker; +import net.minecraft.block.entity.BlockEntityType; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.loot.context.LootContextParameterSet.Builder; +import net.minecraft.screen.NamedScreenHandlerFactory; +import net.minecraft.screen.ScreenHandler; +import net.minecraft.util.ActionResult; +import net.minecraft.util.ItemScatterer; +import net.minecraft.util.hit.BlockHitResult; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Direction; +import net.minecraft.world.World; + +/** + * + * @author jotty + * + */ +public class BlockStackerWest extends BlockWithEntity implements BlockStacker { + + public BlockStackerWest() { + super(AbstractBlock.Settings.create().hardness(2.5f)); + } + + @Override + public List getDroppedStacks(BlockState state, Builder builder) { + return List.of(new ItemStack(QuickieBlocks.BLOCKSTACKERWEST.getBlock())); + } + + @Override + public Direction getSourceOffset() { + return Direction.EAST; + } + + @Override + public Direction getDestOffset() { + return Direction.WEST; + } + + @Override + public BlockEntity createBlockEntity(BlockPos pos, BlockState state) { + return new BlockStackerEntity(pos, state); + } + + @Override + public BlockRenderType getRenderType(BlockState state) { + return BlockRenderType.MODEL; + } + + @Override + public BlockEntityTicker getTicker(World world, BlockState state, + BlockEntityType type) { + return validateTicker(type, BlockEntityTypes.BLOCKSTACKER_ENTITY, + (world1, pos, state1, be) -> BlockStackerEntity.tick(world1, pos, state1, be)); + } + + @Override + protected ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, BlockHitResult hit) { + if (!world.isClient) { + NamedScreenHandlerFactory screenHandlerFactory = state.createScreenHandlerFactory(world, pos); + if (screenHandlerFactory != null) { + player.openHandledScreen(screenHandlerFactory); + } + } + return ActionResult.SUCCESS; + } + + @Override + public void onStateReplaced(BlockState state, World world, BlockPos pos, BlockState newState, boolean moved) { + if (state.getBlock() != newState.getBlock()) { + BlockEntity blockEntity = world.getBlockEntity(pos); + if (blockEntity instanceof BlockStackerEntity) { + ItemScatterer.spawn(world, pos, (BlockStackerEntity) blockEntity); + // update comparators + world.updateComparators(pos, this); + } + super.onStateReplaced(state, world, pos, newState, moved); + } + } + + @Override + public boolean hasComparatorOutput(BlockState state) { + return true; + } + + @Override + public int getComparatorOutput(BlockState state, World world, BlockPos pos) { + return ScreenHandler.calculateComparatorOutput(world.getBlockEntity(pos)); + } + + @Override + protected MapCodec getCodec() { + // TODO Auto-generated method stub + return null; + } +} diff --git a/src/main/java/de/jottyfan/quickiemod/blocks/QuickieBlocks.java b/src/main/java/de/jottyfan/quickiemod/blocks/QuickieBlocks.java index 8d83df5..9e34c6a 100644 --- a/src/main/java/de/jottyfan/quickiemod/blocks/QuickieBlocks.java +++ b/src/main/java/de/jottyfan/quickiemod/blocks/QuickieBlocks.java @@ -9,6 +9,12 @@ import net.minecraft.block.Block; */ public enum QuickieBlocks { // @formatter:off + BLOCKSTACKERUP(new BlockStackerUp(), "blockstackerup"), + BLOCKSTACKERDOWN(new BlockStackerDown(), "blockstackerdown"), + BLOCKSTACKEREAST(new BlockStackerEast(), "blockstackereast"), + BLOCKSTACKERWEST(new BlockStackerWest(), "blockstackerwest"), + BLOCKSTACKERNORTH(new BlockStackerNorth(), "blockstackernorth"), + BLOCKSTACKERSOUTH(new BlockStackerSouth(), "blockstackersouth"), DRILL_DOWN(new BlockDrillDown(), "drill"), DRILL_EAST(new BlockDrillEast(), "drilleast"), DRILL_SOUTH(new BlockDrillSouth(), "drillsouth"), diff --git a/src/main/java/de/jottyfan/quickiemod/blocks/help/BlockStacker.java b/src/main/java/de/jottyfan/quickiemod/blocks/help/BlockStacker.java new file mode 100644 index 0000000..582ea1c --- /dev/null +++ b/src/main/java/de/jottyfan/quickiemod/blocks/help/BlockStacker.java @@ -0,0 +1,25 @@ +package de.jottyfan.quickiemod.blocks.help; + +import net.minecraft.block.BlockEntityProvider; +import net.minecraft.util.math.Direction; + +/** + * + * @author jotty + * + */ +public interface BlockStacker extends BlockEntityProvider { + /** + * define the source offset + * + * @return the direction of the source offset (1 block beside) + */ + public Direction getSourceOffset(); + + /** + * define the dest offset + * + * @return the direction of the dest offset (1 block beside) + */ + public Direction getDestOffset(); +} diff --git a/src/main/java/de/jottyfan/quickiemod/container/BlockStackerInventory.java b/src/main/java/de/jottyfan/quickiemod/container/BlockStackerInventory.java new file mode 100644 index 0000000..9238be4 --- /dev/null +++ b/src/main/java/de/jottyfan/quickiemod/container/BlockStackerInventory.java @@ -0,0 +1,30 @@ +package de.jottyfan.quickiemod.container; + +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.inventory.SimpleInventory; +import net.minecraft.sound.SoundEvents; + +/** + * + * @author jotty + * + */ +public class BlockStackerInventory extends SimpleInventory { + + public BlockStackerInventory(Integer slotsize) { + super(slotsize); + } + + @Override + public void onOpen(PlayerEntity player) { + super.onOpen(player); + player.playSound(SoundEvents.BLOCK_CHEST_OPEN, 1f, 1f); + } + + @Override + public void onClose(PlayerEntity player) { + super.onClose(player); + player.playSound(SoundEvents.BLOCK_CHEST_CLOSE, 1f, 1f); + } + +} diff --git a/src/main/java/de/jottyfan/quickiemod/container/BlockStackerScreen.java b/src/main/java/de/jottyfan/quickiemod/container/BlockStackerScreen.java new file mode 100644 index 0000000..d860c97 --- /dev/null +++ b/src/main/java/de/jottyfan/quickiemod/container/BlockStackerScreen.java @@ -0,0 +1,44 @@ +package de.jottyfan.quickiemod.container; + +import de.jottyfan.quickiemod.QuickieMod; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.gui.screen.ingame.HandledScreen; +import net.minecraft.client.gui.screen.ingame.ScreenHandlerProvider; +import net.minecraft.entity.player.PlayerInventory; +import net.minecraft.text.Text; +import net.minecraft.util.Identifier; + +/** + * + * @author jotty + * + */ +@Environment(EnvType.CLIENT) +public class BlockStackerScreen extends HandledScreen + implements ScreenHandlerProvider { + private final static Identifier TEXTURE = Identifier.of(QuickieMod.MODID, "textures/gui/blockstacker.png"); + private final Integer containerHeight = 222; + private final Integer containerWidth = 176; + + public BlockStackerScreen(BlockStackerScreenHandler handler, PlayerInventory inventory, Text title) { + super(handler, inventory, title); + } + + @Override + public void render(DrawContext drawContext, int mouseX, int mouseY, float partialTicks) { + this.renderInGameBackground(drawContext); + super.render(drawContext, mouseX, mouseY, partialTicks); + this.drawMouseoverTooltip(drawContext, mouseX, mouseY); + } + + @Override + protected void drawBackground(DrawContext context, float delta, int mouseX, int mouseY) { +// context.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); + int guiX = (this.width - this.containerWidth) / 2; + int guiY = (this.height - this.containerHeight) / 2; + super.renderInGameBackground(context); + context.drawTexture(TEXTURE, guiX, guiY, 0, 0, containerWidth, containerHeight); + } +} diff --git a/src/main/java/de/jottyfan/quickiemod/container/BlockStackerScreenHandler.java b/src/main/java/de/jottyfan/quickiemod/container/BlockStackerScreenHandler.java new file mode 100644 index 0000000..9d4da6f --- /dev/null +++ b/src/main/java/de/jottyfan/quickiemod/container/BlockStackerScreenHandler.java @@ -0,0 +1,97 @@ +package de.jottyfan.quickiemod.container; + +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.entity.player.PlayerInventory; +import net.minecraft.inventory.Inventory; +import net.minecraft.item.ItemStack; +import net.minecraft.screen.NamedScreenHandlerFactory; +import net.minecraft.screen.ScreenHandler; +import net.minecraft.screen.slot.Slot; + +/** + * + * @author jotty + * + */ +public class BlockStackerScreenHandler extends ScreenHandler { + + public static final Integer SLOTSIZE = 18; + + private final Inventory inventory; + + /** + * client constructor + * + * @param syncId + * @param playerInventory + */ + public BlockStackerScreenHandler(int syncId, PlayerInventory playerInventory) { + this(syncId, playerInventory, new BlockStackerInventory(SLOTSIZE)); + } + + /** + * server constructor + * + * @param syncId + * @param playerInventory + * @param inventory + */ + public BlockStackerScreenHandler(int syncId, PlayerInventory playerInventory, Inventory inventory) { + super(ScreenHandlerTypes.BLOCKSTACKER_SCREEN_HANDLER, syncId); + checkSize(inventory, SLOTSIZE); + this.inventory = inventory; + inventory.onOpen(playerInventory.player); + int m; + int l; + // whitelist + for (m = 0; m < 3; ++m) { + for (l = 0; l < 3; ++l) { + this.addSlot(new Slot(inventory, l + m * 3, 8 + l * 18, 17 + m * 18)); + } + } + + // blacklist + for (m = 0; m < 3; ++m) { + for (l = 0; l < 3; ++l) { + this.addSlot(new Slot(inventory, l + m * 3 + 9, 116 + l * 18, 17 + m * 18)); + } + } + + for (m = 0; m < 3; ++m) { + for (l = 0; l < 9; ++l) { + this.addSlot(new Slot(playerInventory, l + m * 9 + 9, 8 + l * 18, 84 + m * 18)); + } + } + for (m = 0; m < 9; ++m) { + this.addSlot(new Slot(playerInventory, m, 8 + m * 18, 142)); + } + } + + @Override + public boolean canUse(PlayerEntity player) { + return this.inventory.canPlayerUse(player); + } + + @Override + public ItemStack quickMove(PlayerEntity player, int invSlot) { + ItemStack newStack = ItemStack.EMPTY; + Slot slot = this.slots.get(invSlot); + if (slot != null && slot.hasStack()) { + ItemStack originalStack = slot.getStack(); + newStack = originalStack.copy(); + if (invSlot < this.inventory.size()) { + if (!this.insertItem(originalStack, this.inventory.size(), this.slots.size(), true)) { + return ItemStack.EMPTY; + } + } else if (!this.insertItem(originalStack, 0, this.inventory.size(), false)) { + return ItemStack.EMPTY; + } + if (originalStack.isEmpty()) { + slot.setStack(ItemStack.EMPTY); + } else { + slot.markDirty(); + } + } + return newStack; + } +} diff --git a/src/main/java/de/jottyfan/quickiemod/container/ImplementedInventory.java b/src/main/java/de/jottyfan/quickiemod/container/ImplementedInventory.java new file mode 100644 index 0000000..add90a5 --- /dev/null +++ b/src/main/java/de/jottyfan/quickiemod/container/ImplementedInventory.java @@ -0,0 +1,133 @@ +package de.jottyfan.quickiemod.container; + +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.inventory.Inventories; +import net.minecraft.inventory.Inventory; +import net.minecraft.item.ItemStack; +import net.minecraft.util.collection.DefaultedList; + +/** + * + * @author jotty + * + * @see https://fabricmc.net/wiki/tutorial:inventory + * + */ +public interface ImplementedInventory extends Inventory { + + /** + * Retrieves the item list of this inventory. + * Must return the same instance every time it's called. + */ + DefaultedList getItems(); + + /** + * Creates an inventory from the item list. + */ + static ImplementedInventory of(DefaultedList items) { + return () -> items; + } + + /** + * Creates a new inventory with the specified size. + */ + static ImplementedInventory ofSize(int size) { + return of(DefaultedList.ofSize(size, ItemStack.EMPTY)); + } + + /** + * Returns the inventory size. + */ + @Override + default int size() { + return getItems().size(); + } + + /** + * Checks if the inventory is empty. + * @return true if this inventory has only empty stacks, false otherwise. + */ + @Override + default boolean isEmpty() { + for (int i = 0; i < size(); i++) { + ItemStack stack = getStack(i); + if (!stack.isEmpty()) { + return false; + } + } + return true; + } + + /** + * Retrieves the item in the slot. + */ + @Override + default ItemStack getStack(int slot) { + return getItems().get(slot); + } + + /** + * Removes items from an inventory slot. + * @param slot The slot to remove from. + * @param count How many items to remove. If there are less items in the slot than what are requested, + * takes all items in that slot. + */ + @Override + default ItemStack removeStack(int slot, int count) { + ItemStack result = Inventories.splitStack(getItems(), slot, count); + if (!result.isEmpty()) { + markDirty(); + } + return result; + } + + /** + * Removes all items from an inventory slot. + * @param slot The slot to remove from. + */ + @Override + default ItemStack removeStack(int slot) { + return Inventories.removeStack(getItems(), slot); + } + + /** + * Replaces the current stack in an inventory slot with the provided stack. + * @param slot The inventory slot of which to replace the itemstack. + * @param stack The replacing itemstack. If the stack is too big for + * this inventory ({@link Inventory#getMaxCountPerStack()}), + * it gets resized to this inventory's maximum amount. + */ + @Override + default void setStack(int slot, ItemStack stack) { + getItems().set(slot, stack); + if (stack.getCount() > stack.getMaxCount()) { + stack.setCount(stack.getMaxCount()); + } + } + + /** + * Clears the inventory. + */ + @Override + default void clear() { + getItems().clear(); + } + + /** + * Marks the state as dirty. + * Must be called after changes in the inventory, so that the game can properly save + * the inventory contents and notify neighboring blocks of inventory changes. + */ + @Override + default void markDirty() { + // Override if you want behavior. + } + + /** + * @return true if the player can use the inventory, false otherwise. + */ + @Override + default boolean canPlayerUse(PlayerEntity player) { + return true; + } +} \ No newline at end of file diff --git a/src/main/java/de/jottyfan/quickiemod/container/ScreenHandlerTypes.java b/src/main/java/de/jottyfan/quickiemod/container/ScreenHandlerTypes.java new file mode 100644 index 0000000..e82a510 --- /dev/null +++ b/src/main/java/de/jottyfan/quickiemod/container/ScreenHandlerTypes.java @@ -0,0 +1,14 @@ +package de.jottyfan.quickiemod.container; + +import net.minecraft.resource.featuretoggle.FeatureFlags; +import net.minecraft.screen.ScreenHandlerType; + +/** + * + * @author jotty + * + */ +public class ScreenHandlerTypes { + public static final ScreenHandlerType BLOCKSTACKER_SCREEN_HANDLER = new ScreenHandlerType<>(BlockStackerScreenHandler::new, + FeatureFlags.VANILLA_FEATURES); +} diff --git a/src/main/java/de/jottyfan/quickiemod/event/EventBlockBreak.java b/src/main/java/de/jottyfan/quickiemod/event/EventBlockBreak.java index 7e790c4..19620bf 100644 --- a/src/main/java/de/jottyfan/quickiemod/event/EventBlockBreak.java +++ b/src/main/java/de/jottyfan/quickiemod/event/EventBlockBreak.java @@ -66,7 +66,7 @@ public class EventBlockBreak { List validBlocks = tool.getBlockList(currentBlock); HarvestRange range = tool.getRange(itemStack); - LOGGER.info("current tool: {}", tool); + LOGGER.debug("current tool: {}", tool); if (QuickieItems.SPEEDPOWDERAXE.getItem().equals(tool)) { return breakBlockRecursive(new ArrayList<>(), world, validBlocks, pos, tool, range, BlockBreakDirection.UPWARDS, diff --git a/src/main/java/de/jottyfan/quickiemod/init/RegistryManager.java b/src/main/java/de/jottyfan/quickiemod/init/RegistryManager.java index c13c900..02e3f3a 100644 --- a/src/main/java/de/jottyfan/quickiemod/init/RegistryManager.java +++ b/src/main/java/de/jottyfan/quickiemod/init/RegistryManager.java @@ -89,6 +89,14 @@ public class RegistryManager { } public static final void registerBlockEntityTypes() { - new BlockEntityTypes(); + try { + Class.forName(BlockEntityTypes.class.getName()); + LOGGER.info("registering block entity types"); + } catch (ClassNotFoundException e) { + LOGGER.error("class BlockEntityType not loaded", e); + } + } + + public static final void registerScreenHandlerTypes() { } } diff --git a/src/main/resources/assets/quickiemod/blockstates/blockstackerdown.json b/src/main/resources/assets/quickiemod/blockstates/blockstackerdown.json new file mode 100644 index 0000000..6bb43c7 --- /dev/null +++ b/src/main/resources/assets/quickiemod/blockstates/blockstackerdown.json @@ -0,0 +1,7 @@ +{ + "variants": { + "": { + "model": "quickiemod:block/blockstackerdown" + } + } +} diff --git a/src/main/resources/assets/quickiemod/blockstates/blockstackereast.json b/src/main/resources/assets/quickiemod/blockstates/blockstackereast.json new file mode 100644 index 0000000..7b1fd09 --- /dev/null +++ b/src/main/resources/assets/quickiemod/blockstates/blockstackereast.json @@ -0,0 +1,7 @@ +{ + "variants": { + "": { + "model": "quickiemod:block/blockstackereast" + } + } +} diff --git a/src/main/resources/assets/quickiemod/blockstates/blockstackernorth.json b/src/main/resources/assets/quickiemod/blockstates/blockstackernorth.json new file mode 100644 index 0000000..d20bddd --- /dev/null +++ b/src/main/resources/assets/quickiemod/blockstates/blockstackernorth.json @@ -0,0 +1,7 @@ +{ + "variants": { + "": { + "model": "quickiemod:block/blockstackernorth" + } + } +} diff --git a/src/main/resources/assets/quickiemod/blockstates/blockstackersouth.json b/src/main/resources/assets/quickiemod/blockstates/blockstackersouth.json new file mode 100644 index 0000000..d18af44 --- /dev/null +++ b/src/main/resources/assets/quickiemod/blockstates/blockstackersouth.json @@ -0,0 +1,7 @@ +{ + "variants": { + "": { + "model": "quickiemod:block/blockstackersouth" + } + } +} diff --git a/src/main/resources/assets/quickiemod/blockstates/blockstackerup.json b/src/main/resources/assets/quickiemod/blockstates/blockstackerup.json new file mode 100644 index 0000000..dc4b60c --- /dev/null +++ b/src/main/resources/assets/quickiemod/blockstates/blockstackerup.json @@ -0,0 +1,7 @@ +{ + "variants": { + "": { + "model": "quickiemod:block/blockstackerup" + } + } +} diff --git a/src/main/resources/assets/quickiemod/blockstates/blockstackerwest.json b/src/main/resources/assets/quickiemod/blockstates/blockstackerwest.json new file mode 100644 index 0000000..18629ae --- /dev/null +++ b/src/main/resources/assets/quickiemod/blockstates/blockstackerwest.json @@ -0,0 +1,7 @@ +{ + "variants": { + "": { + "model": "quickiemod:block/blockstackerwest" + } + } +} diff --git a/src/main/resources/assets/quickiemod/models/block/blockstackerdown.json b/src/main/resources/assets/quickiemod/models/block/blockstackerdown.json new file mode 100644 index 0000000..1de4eb6 --- /dev/null +++ b/src/main/resources/assets/quickiemod/models/block/blockstackerdown.json @@ -0,0 +1,8 @@ +{ + "parent": "block/cube_bottom_top", + "textures": { + "bottom": "quickiemod:block/blockstackerout", + "side": "quickiemod:block/blockstackerdown", + "top": "quickiemod:block/blockstackerin" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/quickiemod/models/block/blockstackereast.json b/src/main/resources/assets/quickiemod/models/block/blockstackereast.json new file mode 100644 index 0000000..7e907bc --- /dev/null +++ b/src/main/resources/assets/quickiemod/models/block/blockstackereast.json @@ -0,0 +1,11 @@ +{ + "parent": "block/cube_directional", + "textures": { + "up": "quickiemod:block/blockstackerright", + "down": "quickiemod:block/blockstackerleft", + "north": "quickiemod:block/blockstackerleft", + "east": "quickiemod:block/blockstackerout", + "south": "quickiemod:block/blockstackerright", + "west": "quickiemod:block/blockstackerin" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/quickiemod/models/block/blockstackernorth.json b/src/main/resources/assets/quickiemod/models/block/blockstackernorth.json new file mode 100644 index 0000000..721b498 --- /dev/null +++ b/src/main/resources/assets/quickiemod/models/block/blockstackernorth.json @@ -0,0 +1,11 @@ +{ + "parent": "block/cube_directional", + "textures": { + "up": "quickiemod:block/blockstackerup", + "down": "quickiemod:block/blockstackerup", + "north": "quickiemod:block/blockstackerout", + "east": "quickiemod:block/blockstackerup", + "south": "quickiemod:block/blockstackerin", + "west": "quickiemod:block/blockstackerup" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/quickiemod/models/block/blockstackersouth.json b/src/main/resources/assets/quickiemod/models/block/blockstackersouth.json new file mode 100644 index 0000000..5b9efea --- /dev/null +++ b/src/main/resources/assets/quickiemod/models/block/blockstackersouth.json @@ -0,0 +1,11 @@ +{ + "parent": "block/cube_directional", + "textures": { + "up": "quickiemod:block/blockstackerdown", + "down": "quickiemod:block/blockstackerdown", + "north": "quickiemod:block/blockstackerin", + "east": "quickiemod:block/blockstackerdown", + "south": "quickiemod:block/blockstackerout", + "west": "quickiemod:block/blockstackerdown" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/quickiemod/models/block/blockstackerup.json b/src/main/resources/assets/quickiemod/models/block/blockstackerup.json new file mode 100644 index 0000000..bea5c62 --- /dev/null +++ b/src/main/resources/assets/quickiemod/models/block/blockstackerup.json @@ -0,0 +1,8 @@ +{ + "parent": "block/cube_bottom_top", + "textures": { + "bottom": "quickiemod:block/blockstackerin", + "side": "quickiemod:block/blockstackerup", + "top": "quickiemod:block/blockstackerout" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/quickiemod/models/block/blockstackerwest.json b/src/main/resources/assets/quickiemod/models/block/blockstackerwest.json new file mode 100644 index 0000000..76b588e --- /dev/null +++ b/src/main/resources/assets/quickiemod/models/block/blockstackerwest.json @@ -0,0 +1,11 @@ +{ + "parent": "block/cube_directional", + "textures": { + "up": "quickiemod:block/blockstackerleft", + "down": "quickiemod:block/blockstackerright", + "north": "quickiemod:block/blockstackerright", + "east": "quickiemod:block/blockstackerin", + "south": "quickiemod:block/blockstackerleft", + "west": "quickiemod:block/blockstackerout" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/quickiemod/models/item/blockstackerdown.json b/src/main/resources/assets/quickiemod/models/item/blockstackerdown.json new file mode 100644 index 0000000..62e0d3f --- /dev/null +++ b/src/main/resources/assets/quickiemod/models/item/blockstackerdown.json @@ -0,0 +1,10 @@ +{ + "parent": "quickiemod:block/blockstackerdown", + "display": { + "thirdperson": { + "rotation": [ 10, -45, 170 ], + "translation": [ 0, 1.5, -2.75 ], + "scale": [ 0.375, 0.375, 0.375 ] + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/quickiemod/models/item/blockstackereast.json b/src/main/resources/assets/quickiemod/models/item/blockstackereast.json new file mode 100644 index 0000000..3626d53 --- /dev/null +++ b/src/main/resources/assets/quickiemod/models/item/blockstackereast.json @@ -0,0 +1,10 @@ +{ + "parent": "quickiemod:block/blockstackerwest", + "display": { + "thirdperson": { + "rotation": [ 10, -45, 170 ], + "translation": [ 0, 1.5, -2.75 ], + "scale": [ 0.375, 0.375, 0.375 ] + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/quickiemod/models/item/blockstackernorth.json b/src/main/resources/assets/quickiemod/models/item/blockstackernorth.json new file mode 100644 index 0000000..29de363 --- /dev/null +++ b/src/main/resources/assets/quickiemod/models/item/blockstackernorth.json @@ -0,0 +1,10 @@ +{ + "parent": "quickiemod:block/blockstackernorth", + "display": { + "thirdperson": { + "rotation": [ 10, -45, 170 ], + "translation": [ 0, 1.5, -2.75 ], + "scale": [ 0.375, 0.375, 0.375 ] + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/quickiemod/models/item/blockstackersouth.json b/src/main/resources/assets/quickiemod/models/item/blockstackersouth.json new file mode 100644 index 0000000..2fdb3f4 --- /dev/null +++ b/src/main/resources/assets/quickiemod/models/item/blockstackersouth.json @@ -0,0 +1,10 @@ +{ + "parent": "quickiemod:block/blockstackersouth", + "display": { + "thirdperson": { + "rotation": [ 10, -45, 170 ], + "translation": [ 0, 1.5, -2.75 ], + "scale": [ 0.375, 0.375, 0.375 ] + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/quickiemod/models/item/blockstackerup.json b/src/main/resources/assets/quickiemod/models/item/blockstackerup.json new file mode 100644 index 0000000..db2bd6a --- /dev/null +++ b/src/main/resources/assets/quickiemod/models/item/blockstackerup.json @@ -0,0 +1,10 @@ +{ + "parent": "quickiemod:block/blockstackerup", + "display": { + "thirdperson": { + "rotation": [ 10, -45, 170 ], + "translation": [ 0, 1.5, -2.75 ], + "scale": [ 0.375, 0.375, 0.375 ] + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/quickiemod/models/item/blockstackerwest.json b/src/main/resources/assets/quickiemod/models/item/blockstackerwest.json new file mode 100644 index 0000000..18f7e4f --- /dev/null +++ b/src/main/resources/assets/quickiemod/models/item/blockstackerwest.json @@ -0,0 +1,10 @@ +{ + "parent": "quickiemod:block/blockstackereast", + "display": { + "thirdperson": { + "rotation": [ 10, -45, 170 ], + "translation": [ 0, 1.5, -2.75 ], + "scale": [ 0.375, 0.375, 0.375 ] + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/quickiemod/textures/block/blockstackerdown.png b/src/main/resources/assets/quickiemod/textures/block/blockstackerdown.png new file mode 100644 index 0000000..558ce81 Binary files /dev/null and b/src/main/resources/assets/quickiemod/textures/block/blockstackerdown.png differ diff --git a/src/main/resources/assets/quickiemod/textures/block/blockstackerin.png b/src/main/resources/assets/quickiemod/textures/block/blockstackerin.png new file mode 100644 index 0000000..a9b29e2 Binary files /dev/null and b/src/main/resources/assets/quickiemod/textures/block/blockstackerin.png differ diff --git a/src/main/resources/assets/quickiemod/textures/block/blockstackerleft.png b/src/main/resources/assets/quickiemod/textures/block/blockstackerleft.png new file mode 100644 index 0000000..fb5e280 Binary files /dev/null and b/src/main/resources/assets/quickiemod/textures/block/blockstackerleft.png differ diff --git a/src/main/resources/assets/quickiemod/textures/block/blockstackerout.png b/src/main/resources/assets/quickiemod/textures/block/blockstackerout.png new file mode 100644 index 0000000..45febea Binary files /dev/null and b/src/main/resources/assets/quickiemod/textures/block/blockstackerout.png differ diff --git a/src/main/resources/assets/quickiemod/textures/block/blockstackerright.png b/src/main/resources/assets/quickiemod/textures/block/blockstackerright.png new file mode 100644 index 0000000..6395790 Binary files /dev/null and b/src/main/resources/assets/quickiemod/textures/block/blockstackerright.png differ diff --git a/src/main/resources/assets/quickiemod/textures/block/blockstackerup.png b/src/main/resources/assets/quickiemod/textures/block/blockstackerup.png new file mode 100644 index 0000000..3adebd0 Binary files /dev/null and b/src/main/resources/assets/quickiemod/textures/block/blockstackerup.png differ diff --git a/src/main/resources/assets/quickiemod/textures/gui/backpack.png b/src/main/resources/assets/quickiemod/textures/gui/backpack.png new file mode 100644 index 0000000..f24c05b Binary files /dev/null and b/src/main/resources/assets/quickiemod/textures/gui/backpack.png differ diff --git a/src/main/resources/assets/quickiemod/textures/gui/blockstacker.png b/src/main/resources/assets/quickiemod/textures/gui/blockstacker.png new file mode 100644 index 0000000..1a10e11 Binary files /dev/null and b/src/main/resources/assets/quickiemod/textures/gui/blockstacker.png differ diff --git a/src/main/resources/assets/quickiemod/textures/gui/slot.png b/src/main/resources/assets/quickiemod/textures/gui/slot.png new file mode 100644 index 0000000..32b0bfa Binary files /dev/null and b/src/main/resources/assets/quickiemod/textures/gui/slot.png differ diff --git a/src/main/resources/data/quickiemod/recipe/shaped_blockstacker.json b/src/main/resources/data/quickiemod/recipe/shaped_blockstacker.json new file mode 100644 index 0000000..a9fcee0 --- /dev/null +++ b/src/main/resources/data/quickiemod/recipe/shaped_blockstacker.json @@ -0,0 +1,20 @@ +{ + "type": "minecraft:crafting_shaped", + "pattern": [ + "s s", + "scs", + " s " + ], + "key": { + "s": { + "item": "quickiemod:speedingot" + }, + "c": { + "item": "minecraft:chest" + } + }, + "result": { + "id": "quickiemod:blockstackerdown", + "count": 4 + } +} \ No newline at end of file diff --git a/src/main/resources/data/quickiemod/recipe/shapeless_blockstackerdown_up.json b/src/main/resources/data/quickiemod/recipe/shapeless_blockstackerdown_up.json new file mode 100644 index 0000000..4c7ed96 --- /dev/null +++ b/src/main/resources/data/quickiemod/recipe/shapeless_blockstackerdown_up.json @@ -0,0 +1,12 @@ +{ + "type": "minecraft:crafting_shapeless", + "ingredients": [ + { + "item": "quickiemod:blockstackerup" + } + ], + "result": { + "id": "quickiemod:blockstackerdown", + "count": 1 + } +} \ No newline at end of file diff --git a/src/main/resources/data/quickiemod/recipe/shapeless_blockstackereast_down.json b/src/main/resources/data/quickiemod/recipe/shapeless_blockstackereast_down.json new file mode 100644 index 0000000..e2f8413 --- /dev/null +++ b/src/main/resources/data/quickiemod/recipe/shapeless_blockstackereast_down.json @@ -0,0 +1,12 @@ +{ + "type": "minecraft:crafting_shapeless", + "ingredients": [ + { + "item": "quickiemod:blockstackerdown" + } + ], + "result": { + "id": "quickiemod:blockstackereast", + "count": 1 + } +} \ No newline at end of file diff --git a/src/main/resources/data/quickiemod/recipe/shapeless_blockstackernorth_west.json b/src/main/resources/data/quickiemod/recipe/shapeless_blockstackernorth_west.json new file mode 100644 index 0000000..c78e9e2 --- /dev/null +++ b/src/main/resources/data/quickiemod/recipe/shapeless_blockstackernorth_west.json @@ -0,0 +1,12 @@ +{ + "type": "minecraft:crafting_shapeless", + "ingredients": [ + { + "item": "quickiemod:blockstackerwest" + } + ], + "result": { + "id": "quickiemod:blockstackernorth", + "count": 1 + } +} \ No newline at end of file diff --git a/src/main/resources/data/quickiemod/recipe/shapeless_blockstackersouth_east.json b/src/main/resources/data/quickiemod/recipe/shapeless_blockstackersouth_east.json new file mode 100644 index 0000000..4f1a3c3 --- /dev/null +++ b/src/main/resources/data/quickiemod/recipe/shapeless_blockstackersouth_east.json @@ -0,0 +1,12 @@ +{ + "type": "minecraft:crafting_shapeless", + "ingredients": [ + { + "item": "quickiemod:blockstackereast" + } + ], + "result": { + "id": "quickiemod:blockstackersouth", + "count": 1 + } +} \ No newline at end of file diff --git a/src/main/resources/data/quickiemod/recipe/shapeless_blockstackerup_north.json b/src/main/resources/data/quickiemod/recipe/shapeless_blockstackerup_north.json new file mode 100644 index 0000000..c95b9bd --- /dev/null +++ b/src/main/resources/data/quickiemod/recipe/shapeless_blockstackerup_north.json @@ -0,0 +1,12 @@ +{ + "type": "minecraft:crafting_shapeless", + "ingredients": [ + { + "item": "quickiemod:blockstackernorth" + } + ], + "result": { + "id": "quickiemod:blockstackerup", + "count": 1 + } +} \ No newline at end of file diff --git a/src/main/resources/data/quickiemod/recipe/shapeless_blockstackerwest_south.json b/src/main/resources/data/quickiemod/recipe/shapeless_blockstackerwest_south.json new file mode 100644 index 0000000..89abf70 --- /dev/null +++ b/src/main/resources/data/quickiemod/recipe/shapeless_blockstackerwest_south.json @@ -0,0 +1,12 @@ +{ + "type": "minecraft:crafting_shapeless", + "ingredients": [ + { + "item": "quickiemod:blockstackersouth" + } + ], + "result": { + "id": "quickiemod:blockstackerwest", + "count": 1 + } +} \ No newline at end of file