diff --git a/projectfiles/brewing_keg.bbmodel b/projectfiles/brewing_keg.bbmodel new file mode 100644 index 0000000..d59766d --- /dev/null +++ b/projectfiles/brewing_keg.bbmodel @@ -0,0 +1 @@ +{"meta":{"format_version":"4.10","model_format":"java_block","box_uv":false},"name":"brewing_keg","parent":"","ambientocclusion":true,"front_gui_light":false,"visible_box":[1,1,0],"variable_placeholders":"","variable_placeholder_buttons":[],"unhandled_root_fields":{},"resolution":{"width":32,"height":32},"elements":[{"name":"cube","box_uv":false,"rescale":false,"locked":false,"render_order":"default","allow_mirror_modeling":true,"from":[4,0,1],"to":[12,8,15],"autouv":0,"color":0,"origin":[1,0,1],"faces":{"north":{"uv":[0,16,8,24],"texture":0},"east":{"uv":[0,0,14,8],"texture":0},"south":{"uv":[22,0,30,8],"texture":0},"west":{"uv":[0,8,14,16],"texture":0},"up":{"uv":[22,14,14,0],"texture":0},"down":{"uv":[22,14,14,28],"texture":0}},"type":"cube","uuid":"ace94742-e271-d0f1-c39a-b273e03e79ba"}],"outliner":["ace94742-e271-d0f1-c39a-b273e03e79ba"],"textures":[{"path":"D:\\Users\\EUGENE\\Desktop\\brewing_keg.png","name":"brewing_keg.png","folder":"","namespace":"ukrainian_delight","id":"0","width":32,"height":32,"uv_width":32,"uv_height":32,"particle":true,"use_as_default":false,"layers_enabled":false,"sync_to_project":"","render_mode":"default","render_sides":"auto","frame_time":1,"frame_order_type":"loop","frame_order":"","frame_interpolate":false,"visible":true,"internal":true,"saved":true,"uuid":"9b067532-71e6-c92f-d4ce-2481db24007f","relative_path":"brewing_keg.png","source":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAAAPNJREFUWEdjdH7R+5+BDFD4JgSvLhfOiXjlOZT7GEEKGEEOsBAXI8kJJ16+YgA5wEJFBqu+E3eeMIAcwC6tjlX+59ObDKMOGA2BwRUCJGUBqGJicgE+c+Eh8KWtjaxy4IBfNN5s6KMjD87nhAAjyAHcinKE1KHIf73/iGHUAaMhAAoBfIDmiTD+9ju8Dlg7v4f4XEBSFoAqBjlAWlwCq9anL18wEO2A6D1f8JYDS114sPokOLHkP9UcoCDBjdUnD158ZRh1wGgIjIwQwFcO0DwEyCmEQHqoVg6MOoCSEMCnl+i6gFwHUEsfUVUmtSzDZs6oAwAxWzww+MGyEgAAAABJRU5ErkJggg=="}]} \ No newline at end of file diff --git a/projectfiles/interface.psd b/projectfiles/interface.psd new file mode 100644 index 0000000..f7aeb05 Binary files /dev/null and b/projectfiles/interface.psd differ diff --git a/projectfiles/interface2.psd b/projectfiles/interface2.psd new file mode 100644 index 0000000..435c007 Binary files /dev/null and b/projectfiles/interface2.psd differ diff --git a/src/main/java/com/megatrex4/ukrainian_dlight/UkrainianDelight.java b/src/main/java/com/megatrex4/ukrainian_dlight/UkrainianDelight.java index a54ccfd..b82a0fb 100644 --- a/src/main/java/com/megatrex4/ukrainian_dlight/UkrainianDelight.java +++ b/src/main/java/com/megatrex4/ukrainian_dlight/UkrainianDelight.java @@ -2,11 +2,13 @@ import com.megatrex4.ukrainian_dlight.block.DrinkBottleBlock; import com.megatrex4.ukrainian_dlight.block.FoodJarBlocks; -import com.megatrex4.ukrainian_dlight.block.ModBlock; +import com.megatrex4.ukrainian_dlight.block.ModBlocks; +import com.megatrex4.ukrainian_dlight.block.entity.ModBlockEntities; import com.megatrex4.ukrainian_dlight.item.ModItemGroups; import com.megatrex4.ukrainian_dlight.item.ModItems; import com.megatrex4.ukrainian_dlight.item.ToolTipHelper; -import com.megatrex4.ukrainian_dlight.util.Config; +import com.megatrex4.ukrainian_dlight.screen.ModScreenHandlers; +import com.megatrex4.ukrainian_dlight.screen.ModScreens; import net.fabricmc.api.ModInitializer; import net.minecraft.entity.damage.DamageType; @@ -15,7 +17,6 @@ import net.minecraft.util.Identifier; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.Objects; public class UkrainianDelight implements ModInitializer { public static final String MOD_ID = "ukrainian_delight"; @@ -33,11 +34,17 @@ public void onInitialize() { FoodJarBlocks.registerFoodBlocks(); DrinkBottleBlock.registerDrinkBlock(); - ModBlock.registerModBlocks(); + ModBlocks.registerModBlocks(); ModItems.registerModItems(); ModItemGroups.registerItemGroups(); ToolTipHelper.registerTooltip(); + ModBlockEntities.registerBLockEntities(); + ModScreenHandlers.registerModScreenHandlers(); + + ModScreens.registerScreens(); LOGGER.info("Hello Fabric world it's " + MOD_ID + "!"); } + + } \ No newline at end of file diff --git a/src/main/java/com/megatrex4/ukrainian_dlight/UkrainianDeligthClient.java b/src/main/java/com/megatrex4/ukrainian_dlight/UkrainianDeligthClient.java new file mode 100644 index 0000000..07b6b56 --- /dev/null +++ b/src/main/java/com/megatrex4/ukrainian_dlight/UkrainianDeligthClient.java @@ -0,0 +1,18 @@ +package com.megatrex4.ukrainian_dlight; + +import com.megatrex4.ukrainian_dlight.screen.BrewingKegScreen; +import com.megatrex4.ukrainian_dlight.screen.ModScreenHandlers; +import net.fabricmc.api.ClientModInitializer; +import net.fabricmc.fabric.api.blockrenderlayer.v1.BlockRenderLayerMap; +import net.fabricmc.fabric.api.client.rendering.v1.EntityModelLayerRegistry; +import net.fabricmc.fabric.api.client.rendering.v1.EntityRendererRegistry; +import net.minecraft.client.gui.screen.ingame.HandledScreens; +import net.minecraft.client.render.RenderLayer; + +public class UkrainianDeligthClient implements ClientModInitializer { + + @Override + public void onInitializeClient() { + HandledScreens.register(ModScreenHandlers.BREWING_KEG_SCREEN_HANDLER, BrewingKegScreen::new); + } +} diff --git a/src/main/java/com/megatrex4/ukrainian_dlight/block/ModBlock.java b/src/main/java/com/megatrex4/ukrainian_dlight/block/ModBlocks.java similarity index 77% rename from src/main/java/com/megatrex4/ukrainian_dlight/block/ModBlock.java rename to src/main/java/com/megatrex4/ukrainian_dlight/block/ModBlocks.java index 74532ff..013c6b4 100644 --- a/src/main/java/com/megatrex4/ukrainian_dlight/block/ModBlock.java +++ b/src/main/java/com/megatrex4/ukrainian_dlight/block/ModBlocks.java @@ -1,7 +1,8 @@ package com.megatrex4.ukrainian_dlight.block; import com.megatrex4.ukrainian_dlight.UkrainianDelight; -import com.megatrex4.ukrainian_dlight.block.custom.CustomSaltBlock; +import com.megatrex4.ukrainian_dlight.block.custom.BrewingKegBlock; +import com.megatrex4.ukrainian_dlight.block.custom.SaltBlock; import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; import net.minecraft.block.Block; import net.minecraft.block.Blocks; @@ -12,10 +13,10 @@ import net.minecraft.sound.BlockSoundGroup; import net.minecraft.util.Identifier; -public class ModBlock { +public class ModBlocks { public static final Block SALT_BLOCK = registerBlock("salt_block", - new CustomSaltBlock(Block.Settings.copy(Blocks.STONE).sounds(BlockSoundGroup.STONE))); + new SaltBlock(Block.Settings.copy(Blocks.STONE).sounds(BlockSoundGroup.STONE))); public static final Block SALT_BAG = registerBlock("salt_bag", new Block(FabricBlockSettings.copyOf(Blocks.WHITE_WOOL).sounds(BlockSoundGroup.WOOL))); @@ -23,6 +24,9 @@ public class ModBlock { public static final Block CUCUMBER_CRATE = registerBlock("cucumber_crate", new Block(FabricBlockSettings.copyOf(Blocks.OAK_PLANKS).sounds(BlockSoundGroup.WOOD))); + public static final Block BREWING_KEG = registerBlock("brewing_keg", + new BrewingKegBlock(FabricBlockSettings.copyOf(Blocks.OAK_PLANKS).sounds(BlockSoundGroup.WOOD).nonOpaque())); + private static Block registerBlock(String name, Block block){ registerBlockItem(name, block); return Registry.register(Registries.BLOCK, new Identifier(UkrainianDelight.MOD_ID, name), block); diff --git a/src/main/java/com/megatrex4/ukrainian_dlight/block/custom/BrewingKegBlock.java b/src/main/java/com/megatrex4/ukrainian_dlight/block/custom/BrewingKegBlock.java new file mode 100644 index 0000000..071345e --- /dev/null +++ b/src/main/java/com/megatrex4/ukrainian_dlight/block/custom/BrewingKegBlock.java @@ -0,0 +1,76 @@ +package com.megatrex4.ukrainian_dlight.block.custom; + +import com.megatrex4.ukrainian_dlight.block.entity.BrewingKegBlockEntity; +import com.megatrex4.ukrainian_dlight.block.entity.ModBlockEntities; +import net.minecraft.block.*; +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.screen.NamedScreenHandlerFactory; +import net.minecraft.util.ActionResult; +import net.minecraft.util.Hand; +import net.minecraft.util.ItemScatterer; +import net.minecraft.util.hit.BlockHitResult; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.shape.VoxelShape; +import net.minecraft.world.BlockView; +import net.minecraft.world.World; +import org.jetbrains.annotations.Nullable; + +public class BrewingKegBlock extends BlockWithEntity implements BlockEntityProvider { + private static final VoxelShape SHAPE = Block.createCuboidShape(0, 0, 0, 16, 12, 16); + + public BrewingKegBlock (Settings settings) { + super(settings); + } + + @Override + public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) { + return SHAPE; + } + + @Override + public BlockRenderType getRenderType(BlockState state) { + return BlockRenderType.MODEL; + } + + @Nullable + @Override + public BlockEntity createBlockEntity(BlockPos pos, BlockState state) { + return new BrewingKegBlockEntity(pos, state); + } + + @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 BrewingKegBlockEntity) { + ItemScatterer.spawn(world, pos, (BrewingKegBlockEntity)blockEntity); + world.updateComparators(pos,this); + } + super.onStateReplaced(state, world, pos, newState, moved); + } + } + + @Override + public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) { + if (!world.isClient) { + NamedScreenHandlerFactory screenHandlerFactory = ((BrewingKegBlockEntity) world.getBlockEntity(pos)); + + if (screenHandlerFactory != null) { + player.openHandledScreen(screenHandlerFactory); + } + } + + return ActionResult.SUCCESS; + } + + @Nullable + @Override + public BlockEntityTicker getTicker(World world, BlockState state, BlockEntityType type) { + return checkType(type, ModBlockEntities.BREWING_KEG_BLOCK_ENTITY, + (world1, pos, state1, blockEntity) -> blockEntity.tick(world1, pos, state1)); + } +} diff --git a/src/main/java/com/megatrex4/ukrainian_dlight/block/custom/CustomSaltBlock.java b/src/main/java/com/megatrex4/ukrainian_dlight/block/custom/SaltBlock.java similarity index 92% rename from src/main/java/com/megatrex4/ukrainian_dlight/block/custom/CustomSaltBlock.java rename to src/main/java/com/megatrex4/ukrainian_dlight/block/custom/SaltBlock.java index dab6b7b..5ecb7f5 100644 --- a/src/main/java/com/megatrex4/ukrainian_dlight/block/custom/CustomSaltBlock.java +++ b/src/main/java/com/megatrex4/ukrainian_dlight/block/custom/SaltBlock.java @@ -9,10 +9,10 @@ import net.minecraft.util.math.random.Random; import net.minecraft.world.World; -public class CustomSaltBlock extends Block { +public class SaltBlock extends Block { private static final int SCHEDULED_TICK_DELAY = 20; - public CustomSaltBlock(Settings settings) { + public SaltBlock(Settings settings) { super(settings); } diff --git a/src/main/java/com/megatrex4/ukrainian_dlight/block/entity/BrewingKegBlockEntity.java b/src/main/java/com/megatrex4/ukrainian_dlight/block/entity/BrewingKegBlockEntity.java new file mode 100644 index 0000000..bc73aa6 --- /dev/null +++ b/src/main/java/com/megatrex4/ukrainian_dlight/block/entity/BrewingKegBlockEntity.java @@ -0,0 +1,172 @@ +package com.megatrex4.ukrainian_dlight.block.entity; + +import com.megatrex4.ukrainian_dlight.block.DrinkBottleBlock; +import com.megatrex4.ukrainian_dlight.block.ModBlocks; +import com.megatrex4.ukrainian_dlight.item.DrinkBlockItem; +import com.megatrex4.ukrainian_dlight.item.ModItems; +import com.megatrex4.ukrainian_dlight.screen.BrewingKegScreenHandler; +import net.fabricmc.fabric.api.screenhandler.v1.ExtendedScreenHandlerFactory; +import net.minecraft.block.BlockState; +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.block.entity.BlockEntityType; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.entity.player.PlayerInventory; +import net.minecraft.inventory.Inventories; +import net.minecraft.inventory.Inventory; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NbtCompound; +import net.minecraft.network.PacketByteBuf; +import net.minecraft.screen.PropertyDelegate; +import net.minecraft.screen.ScreenHandler; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.text.Text; +import net.minecraft.util.collection.DefaultedList; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import org.jetbrains.annotations.Nullable; + +public class BrewingKegBlockEntity extends BlockEntity implements ExtendedScreenHandlerFactory, ImplementedInventory { + private final DefaultedList inventory = DefaultedList.ofSize(10, ItemStack.EMPTY); + + //adds 6 input ingredients slot + public static final int INGREDIENT_SLOT_1 = 0; + public static final int INGREDIENT_SLOT_2 = 1; + public static final int INGREDIENT_SLOT_3 = 2; + public static final int INGREDIENT_SLOT_4 = 3; + public static final int INGREDIENT_SLOT_5 = 4; + public static final int INGREDIENT_SLOT_6 = 5; + //adds container(like bottle of vial) input + public static final int CONTAINER_SLOT = 6; + //adds 1 input slot for water + public static final int INPUT_SLOT = 7; + //adds 1 output slot and display slot + public static final int DRINKS_DISPLAY_SLOT = 8; + public static final int OUTPUT_SLOT = 9; + + protected final PropertyDelegate propertyDelegate; + private int progress; + private int maxProgress = 72; + + public BrewingKegBlockEntity(BlockPos pos, BlockState state){ + super(ModBlockEntities.BREWING_KEG_BLOCK_ENTITY, pos, state); + this.propertyDelegate = new PropertyDelegate() { + @Override + public int get(int index) { + return switch (index){ + case 0 -> BrewingKegBlockEntity.this.progress; + case 1 -> BrewingKegBlockEntity.this.maxProgress; + default -> 0; + }; + } + + @Override + public void set(int index, int value) { + switch (index){ + case 0 -> BrewingKegBlockEntity.this.progress = value; + case 1 -> BrewingKegBlockEntity.this.maxProgress = value; + } + } + + @Override + public int size() { + return 2; + } + }; + } + + @Override + public DefaultedList getItems() { + return inventory; + } + + @Override + protected void writeNbt(NbtCompound nbt) { + super.writeNbt(nbt); + Inventories.writeNbt(nbt, inventory); + nbt.putInt("brewing_keg.progress", progress); + } + + @Override + public void readNbt(NbtCompound nbt) { + super.readNbt(nbt); + Inventories.readNbt(nbt, inventory); + progress = nbt.getInt("brewing_keg.progress"); + } + + @Override + public void writeScreenOpeningData(ServerPlayerEntity player, PacketByteBuf buf) { + buf.writeBlockPos(this.pos); + } + + @Override + public Text getDisplayName() { + return Text.translatable("gui.ukrainian_delight.brewing_keg"); + } + + @Nullable + @Override + public ScreenHandler createMenu(int syncId, PlayerInventory playerInventory, PlayerEntity player) { + return new BrewingKegScreenHandler(syncId, playerInventory, this, propertyDelegate); + } + + public void tick(World world, BlockPos pos, BlockState state) { + if(world.isClient){ + return; + } + + if(isOutoutSlotEmptyOrReceivable()){ + if(this.hasRecipe()){ + this.increaseCraftProgress(); + markDirty(world, pos, state); + + if(hasCraftingFinished()){ + this.craftItem(); + this.resetProgress(); + } + } else { + this.resetProgress(); + } + } else { + this.resetProgress(); + markDirty(world, pos, state); + } + } + + private void resetProgress() { + this.progress = 0; + } + + private void craftItem() { + this.removeStack(INGREDIENT_SLOT_1, 1); + ItemStack result = new ItemStack(DrinkBottleBlock.WINE_BOTTLE); + this.setStack(OUTPUT_SLOT, new ItemStack(result.getItem(), getStack(OUTPUT_SLOT).getCount() + result.getCount())); + } + + private boolean hasCraftingFinished() { + return progress >= maxProgress; + } + + private void increaseCraftProgress() { + progress++; + } + + private boolean hasRecipe() { + ItemStack result = new ItemStack(DrinkBottleBlock.WINE_BOTTLE); + boolean hasInput = getStack(INGREDIENT_SLOT_1).getItem() == ModItems.APPLE_SLICE; + + return hasInput && canInsertAmoutIntoOutputSlot(result) && canInstertItemIntoOutputSlot(result.getItem()); + } + + private boolean canInstertItemIntoOutputSlot(Item item) { + return this.getStack(OUTPUT_SLOT).getItem() == item || this.getStack(OUTPUT_SLOT).isEmpty(); + } + + private boolean canInsertAmoutIntoOutputSlot(ItemStack result) { + return this.getStack(OUTPUT_SLOT).getCount() + result.getCount() <= getStack(OUTPUT_SLOT).getMaxCount(); + } + + private boolean isOutoutSlotEmptyOrReceivable() { + return this.getStack(OUTPUT_SLOT).isEmpty() || this.getStack(OUTPUT_SLOT).getCount() < this.getStack(OUTPUT_SLOT).getMaxCount(); + } +} diff --git a/src/main/java/com/megatrex4/ukrainian_dlight/block/entity/ImplementedInventory.java b/src/main/java/com/megatrex4/ukrainian_dlight/block/entity/ImplementedInventory.java new file mode 100644 index 0000000..0967f9c --- /dev/null +++ b/src/main/java/com/megatrex4/ukrainian_dlight/block/entity/ImplementedInventory.java @@ -0,0 +1,213 @@ +package com.megatrex4.ukrainian_dlight.block.entity; + +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.inventory.Inventories; +import net.minecraft.inventory.Inventory; +import net.minecraft.inventory.SidedInventory; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NbtCompound; +import net.minecraft.util.collection.DefaultedList; +import net.minecraft.util.math.Direction; +import org.jetbrains.annotations.Nullable; + +import java.util.List; + +/** + * A simple {@code SidedInventory} implementation with only default methods + an item list getter. + * + *

Reading and writing to tags

+ * Use {@link Inventories#writeNbt(NbtCompound, DefaultedList)} and {@link Inventories#readNbt(NbtCompound, DefaultedList)} + * on {@linkplain #getItems() the item list}. + * + * License: CC0 + * @author Juuz + */ +@FunctionalInterface +public interface ImplementedInventory extends SidedInventory { + /** + * Gets the item list of this inventory. + * Must return the same instance every time it's called. + * + * @return the item list + */ + DefaultedList getItems(); + + /** + * Creates an inventory from the item list. + * + * @param items the item list + * @return a new inventory + */ + static ImplementedInventory of(DefaultedList items) { + return () -> items; + } + + /** + * Creates a new inventory with the size. + * + * @param size the inventory size + * @return a new inventory + */ + static ImplementedInventory ofSize(int size) { + return of(DefaultedList.ofSize(size, ItemStack.EMPTY)); + } + + // SidedInventory + + /** + * Gets the available slots to automation on the side. + * + *

The default implementation returns an array of all slots. + * + * @param side the side + * @return the available slots + */ + @Override + default int[] getAvailableSlots(Direction side) { + int[] result = new int[getItems().size()]; + for (int i = 0; i < result.length; i++) { + result[i] = i; + } + + return result; + } + + /** + * Returns true if the stack can be inserted in the slot at the side. + * + *

The default implementation returns true. + * + * @param slot the slot + * @param stack the stack + * @param side the side + * @return true if the stack can be inserted + */ + @Override + default boolean canInsert(int slot, ItemStack stack, @Nullable Direction side) { + return true; + } + + /** + * Returns true if the stack can be extracted from the slot at the side. + * + *

The default implementation returns true. + * + * @param slot the slot + * @param stack the stack + * @param side the side + * @return true if the stack can be extracted + */ + @Override + default boolean canExtract(int slot, ItemStack stack, Direction side) { + return true; + } + + // Inventory + + /** + * Returns the inventory size. + * + *

The default implementation returns the size of {@link #getItems()}. + * + * @return the inventory size + */ + @Override + default int size() { + return getItems().size(); + } + + /** + * @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; + } + + /** + * Gets the item in the slot. + * + * @param slot the slot + * @return the item in the slot + */ + @Override + default ItemStack getStack(int slot) { + return getItems().get(slot); + } + + /** + * Takes a stack of the size from the slot. + * + *

(default implementation) If there are less items in the slot than what are requested, + * takes all items in that slot. + * + * @param slot the slot + * @param count the item count + * @return a stack + */ + @Override + default ItemStack removeStack(int slot, int count) { + ItemStack result = Inventories.splitStack(getItems(), slot, count); + if (!result.isEmpty()) { + markDirty(); + } + + return result; + } + + /** + * Removes the current stack in the {@code slot} and returns it. + * + *

The default implementation uses {@link Inventories#removeStack(List, int)} + * + * @param slot the slot + * @return the removed stack + */ + @Override + default ItemStack removeStack(int slot) { + return Inventories.removeStack(getItems(), slot); + } + + /** + * Replaces the current stack in the {@code slot} with the provided stack. + * + *

If the stack is too big for this inventory ({@link Inventory#getMaxCountPerStack()}), + * it gets resized to this inventory's maximum amount. + * + * @param slot the slot + * @param stack the stack + */ + @Override + default void setStack(int slot, ItemStack stack) { + getItems().set(slot, stack); + if (stack.getCount() > getMaxCountPerStack()) { + stack.setCount(getMaxCountPerStack()); + } + markDirty(); + } + + /** + * Clears {@linkplain #getItems() the item list}}. + */ + @Override + default void clear() { + getItems().clear(); + } + + @Override + default void markDirty() { + // Override if you want behavior. + } + + @Override + default boolean canPlayerUse(PlayerEntity player) { + return true; + } +} diff --git a/src/main/java/com/megatrex4/ukrainian_dlight/block/entity/ModBlockEntities.java b/src/main/java/com/megatrex4/ukrainian_dlight/block/entity/ModBlockEntities.java new file mode 100644 index 0000000..c33e470 --- /dev/null +++ b/src/main/java/com/megatrex4/ukrainian_dlight/block/entity/ModBlockEntities.java @@ -0,0 +1,20 @@ +package com.megatrex4.ukrainian_dlight.block.entity; + +import net.fabricmc.fabric.api.object.builder.v1.block.entity.FabricBlockEntityTypeBuilder; +import com.megatrex4.ukrainian_dlight.UkrainianDelight; +import com.megatrex4.ukrainian_dlight.block.ModBlocks; +import net.minecraft.block.entity.BlockEntityType; +import net.minecraft.registry.Registries; +import net.minecraft.registry.Registry; +import net.minecraft.util.Identifier; + +public class ModBlockEntities { + public static final BlockEntityType BREWING_KEG_BLOCK_ENTITY = + Registry.register(Registries.BLOCK_ENTITY_TYPE, new Identifier(UkrainianDelight.MOD_ID, "brewing_keg_be"), + FabricBlockEntityTypeBuilder.create(BrewingKegBlockEntity::new, + ModBlocks.BREWING_KEG).build()); + + public static void registerBLockEntities() { + UkrainianDelight.LOGGER.info("Registering Mod Block Entities for " + UkrainianDelight.MOD_ID); + } +} diff --git a/src/main/java/com/megatrex4/ukrainian_dlight/item/ModItemGroups.java b/src/main/java/com/megatrex4/ukrainian_dlight/item/ModItemGroups.java index 4a3339d..20a13e6 100644 --- a/src/main/java/com/megatrex4/ukrainian_dlight/item/ModItemGroups.java +++ b/src/main/java/com/megatrex4/ukrainian_dlight/item/ModItemGroups.java @@ -3,7 +3,7 @@ import com.megatrex4.ukrainian_dlight.UkrainianDelight; import com.megatrex4.ukrainian_dlight.block.DrinkBottleBlock; import com.megatrex4.ukrainian_dlight.block.FoodJarBlocks; -import com.megatrex4.ukrainian_dlight.block.ModBlock; +import com.megatrex4.ukrainian_dlight.block.ModBlocks; import net.fabricmc.fabric.api.itemgroup.v1.FabricItemGroup; import net.minecraft.item.ItemGroup; import net.minecraft.item.ItemStack; @@ -31,12 +31,13 @@ public class ModItemGroups { .displayName(Text.translatable("itemgroup.ingredients_ukrainian_delight")) .icon(() -> new ItemStack(ModItems.CUCUMBER)) .entries((displayContext, entries) -> { - entries.add(ModBlock.SALT_BAG); - entries.add(ModBlock.SALT_BLOCK); + entries.add(ModBlocks.BREWING_KEG); + entries.add(ModBlocks.SALT_BAG); + entries.add(ModBlocks.SALT_BLOCK); entries.add(ModItems.SALT); entries.add(ModItems.HORSERADISH); - entries.add(ModBlock.CUCUMBER_CRATE); + entries.add(ModBlocks.CUCUMBER_CRATE); entries.add(ModItems.CUCUMBER); entries.add(ModItems.CUTTED_CUCUMBER); entries.add(ModItems.APPLE_SLICE); diff --git a/src/main/java/com/megatrex4/ukrainian_dlight/screen/BrewingKegScreen.java b/src/main/java/com/megatrex4/ukrainian_dlight/screen/BrewingKegScreen.java new file mode 100644 index 0000000..0f9eeaf --- /dev/null +++ b/src/main/java/com/megatrex4/ukrainian_dlight/screen/BrewingKegScreen.java @@ -0,0 +1,52 @@ +package com.megatrex4.ukrainian_dlight.screen; + +import com.megatrex4.ukrainian_dlight.UkrainianDelight; +import com.mojang.blaze3d.systems.RenderSystem; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.gui.screen.ingame.HandledScreen; +import net.minecraft.client.render.GameRenderer; +import net.minecraft.entity.player.PlayerInventory; +import net.minecraft.text.Text; +import net.minecraft.util.Identifier; + +public class BrewingKegScreen extends HandledScreen { + private static final Identifier TEXTURE = new Identifier(UkrainianDelight.MOD_ID, "textures/gui/brewing_keg_gui.png"); + + public BrewingKegScreen(BrewingKegScreenHandler handler, PlayerInventory inventory, Text title) { + super(handler, inventory, title); + } + + @Override + protected void init() { + super.init(); + titleX = 53; + playerInventoryTitleY = 1000; + } + + @Override + protected void drawBackground(DrawContext context, float delta, int mouseX, int mouseY) { + RenderSystem.setShader(GameRenderer::getPositionTexProgram); + RenderSystem.setShaderColor(1f, 1f, 1f, 1f); + RenderSystem.setShaderTexture(0, TEXTURE); + int x = (width - backgroundWidth) / 2; + int y = (height - backgroundHeight) / 2; + + context.drawTexture(TEXTURE, x, y, 0, 0, backgroundWidth, backgroundHeight); + + renderProgressBar(context, x, y); + } + + private void renderProgressBar(DrawContext context, int x, int y) { + if(handler.isCrafting()){ + context.drawTexture(TEXTURE, x + 110, y + 27, 177, 17,18, handler.getScaledProgress()); + } + } + + @Override + public void render(DrawContext context, int mouseX, int mouseY, float delta) { + // Fix the renderBackground call by removing the extra parameters + renderBackground(context); + super.render(context, mouseX, mouseY, delta); + drawMouseoverTooltip(context, mouseX, mouseY); + } +} diff --git a/src/main/java/com/megatrex4/ukrainian_dlight/screen/BrewingKegScreenHandler.java b/src/main/java/com/megatrex4/ukrainian_dlight/screen/BrewingKegScreenHandler.java new file mode 100644 index 0000000..8800b5b --- /dev/null +++ b/src/main/java/com/megatrex4/ukrainian_dlight/screen/BrewingKegScreenHandler.java @@ -0,0 +1,133 @@ +package com.megatrex4.ukrainian_dlight.screen; + +import com.megatrex4.ukrainian_dlight.block.entity.BrewingKegBlockEntity; +import net.minecraft.block.entity.BlockEntity; +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.network.PacketByteBuf; +import net.minecraft.screen.ArrayPropertyDelegate; +import net.minecraft.screen.PropertyDelegate; +import net.minecraft.screen.ScreenHandler; +import net.minecraft.screen.slot.Slot; +import org.jetbrains.annotations.Nullable; + +public class BrewingKegScreenHandler extends ScreenHandler { + + private final Inventory inventory; + private final PropertyDelegate propertyDelegate; + public final BrewingKegBlockEntity blockEntity; + + public BrewingKegScreenHandler(int syncId, PlayerInventory inventory, PacketByteBuf buf) { + this(syncId, inventory, inventory.player.getWorld().getBlockEntity(buf.readBlockPos()), + new ArrayPropertyDelegate(10)); + } + + public BrewingKegScreenHandler(int syncId, PlayerInventory playerInventory, + BlockEntity blockEntity, PropertyDelegate arrayPropertyDelegate) { + super(ModScreenHandlers.BREWING_KEG_SCREEN_HANDLER, syncId); + checkSize(((Inventory) blockEntity), 10); + this.inventory = ((Inventory) blockEntity); + inventory.onOpen(playerInventory.player); + this.propertyDelegate = arrayPropertyDelegate; + this.blockEntity = ((BrewingKegBlockEntity) blockEntity); + + //add 6 ingredients slots + int inputStartX = 53; + int inputStartY = 18; + int borderSlotSize = 18; + for (int row = 0; row < 2; ++row) { + for (int column = 0; column < 3; ++column) { + addSlot(new Slot(inventory, (row * 3) + column, + inputStartX + (column * borderSlotSize), + inputStartY + (row * borderSlotSize))); + } + } + + //adds container(like bottle of vial) input + this.addSlot(new Slot(inventory, 6, 97, 59)); + //adds 1 input slot for water + this.addSlot(new Slot(inventory, 7, 30, 59)); + //adds 1 display slot that does not allow item insertion or extraction + this.addSlot(new Slot(inventory, 8, 131, 28) { + @Override + public boolean canInsert(ItemStack stack) { + return false; + } + + @Override + public boolean canTakeItems(PlayerEntity playerEntity) { + return false; + } + }); + //adds 1 output slot that only allows item extraction + this.addSlot(new Slot(inventory, 9, 131, 59) { + @Override + public boolean canInsert(ItemStack stack) { + return false; + } + }); + + addPlayerInventory(playerInventory); + addPlayerHotbar(playerInventory); + + addProperties(arrayPropertyDelegate); + } + + public boolean isCrafting() { + return propertyDelegate.get(0) > 0; + } + + public int getScaledProgress() { + int progress = this.propertyDelegate.get(0); + int maxProgress = this.propertyDelegate.get(1); // Max Progress + int progressArrowSize = 19; // This is the width in pixels of your arrow + + return maxProgress != 0 && progress != 0 ? progress * progressArrowSize / maxProgress : 0; + } + + @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; + } + + @Override + public boolean canUse(PlayerEntity player) { + return this.inventory.canPlayerUse(player); + } + + private void addPlayerInventory(PlayerInventory playerInventory) { + for (int i = 0; i < 3; ++i) { + for (int l = 0; l < 9; ++l) { + this.addSlot(new Slot(playerInventory, l + i * 9 + 9, 8 + l * 18, 84 + i * 18)); + } + } + } + + private void addPlayerHotbar(PlayerInventory playerInventory) { + for (int i = 0; i < 9; ++i) { + this.addSlot(new Slot(playerInventory, i, 8 + i * 18, 142)); + } + } +} diff --git a/src/main/java/com/megatrex4/ukrainian_dlight/screen/ModScreenHandlers.java b/src/main/java/com/megatrex4/ukrainian_dlight/screen/ModScreenHandlers.java new file mode 100644 index 0000000..9486978 --- /dev/null +++ b/src/main/java/com/megatrex4/ukrainian_dlight/screen/ModScreenHandlers.java @@ -0,0 +1,19 @@ +package com.megatrex4.ukrainian_dlight.screen; + +import com.megatrex4.ukrainian_dlight.UkrainianDelight; +import net.fabricmc.fabric.api.screenhandler.v1.ExtendedScreenHandlerType; +import net.minecraft.registry.Registries; +import net.minecraft.registry.Registry; +import net.minecraft.screen.ScreenHandlerType; +import net.minecraft.util.Identifier; + +public class ModScreenHandlers { + public static final ScreenHandlerType BREWING_KEG_SCREEN_HANDLER = + Registry.register(Registries.SCREEN_HANDLER, new Identifier(UkrainianDelight.MOD_ID, "brewing_keg_screen_handler"), + new ExtendedScreenHandlerType<>(BrewingKegScreenHandler::new)); + + public static void registerModScreenHandlers() { + UkrainianDelight.LOGGER.info("Registering Mod Screen Handlers for " + UkrainianDelight.MOD_ID); + // If there are more screen handlers, register them here + } +} diff --git a/src/main/java/com/megatrex4/ukrainian_dlight/screen/ModScreens.java b/src/main/java/com/megatrex4/ukrainian_dlight/screen/ModScreens.java new file mode 100644 index 0000000..a3f1563 --- /dev/null +++ b/src/main/java/com/megatrex4/ukrainian_dlight/screen/ModScreens.java @@ -0,0 +1,9 @@ +package com.megatrex4.ukrainian_dlight.screen; + +import net.fabricmc.fabric.api.client.screenhandler.v1.ScreenRegistry; + +public class ModScreens { + public static void registerScreens() { + ScreenRegistry.register(ModScreenHandlers.BREWING_KEG_SCREEN_HANDLER, BrewingKegScreen::new); + } +} diff --git a/src/main/resources/assets/ukrainian_delight/blockstates/brewing_keg.json b/src/main/resources/assets/ukrainian_delight/blockstates/brewing_keg.json new file mode 100644 index 0000000..f73ebaf --- /dev/null +++ b/src/main/resources/assets/ukrainian_delight/blockstates/brewing_keg.json @@ -0,0 +1,7 @@ +{ + "variants": { + "": { + "model": "ukrainian_delight:block/brewing_keg" + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/ukrainian_delight/lang/en_us.json b/src/main/resources/assets/ukrainian_delight/lang/en_us.json index af236b0..7a66b90 100644 --- a/src/main/resources/assets/ukrainian_delight/lang/en_us.json +++ b/src/main/resources/assets/ukrainian_delight/lang/en_us.json @@ -35,6 +35,7 @@ "block.ukrainian_delight.wine_bottle": "Wine Bottle", "_comment6": "blocks", + "block.ukrainian_delight.brewing_keg": "Brewing Keg", "block.ukrainian_delight.salt_block": "Salt Block", "block.ukrainian_delight.salt_bag": "Salt Bag", @@ -48,6 +49,7 @@ "ukrainian_delight.advancement.lean_borscht.desc": "Cook lean borscht", "_comment8": "misc", + "gui.ukrainian_delight.brewing_keg": "Brewing Keg", "death.attack.glass_damage": "%s was not careful with glass", "tooltip.ukrainian_delight.no_effects": "No effects", "biome.ukrainian_delight.salt_caves": "Salt Caves", diff --git a/src/main/resources/assets/ukrainian_delight/lang/uk_ua.json b/src/main/resources/assets/ukrainian_delight/lang/uk_ua.json index 10b68df..f2fd373 100644 --- a/src/main/resources/assets/ukrainian_delight/lang/uk_ua.json +++ b/src/main/resources/assets/ukrainian_delight/lang/uk_ua.json @@ -35,6 +35,7 @@ "block.ukrainian_delight.wine_bottle": "Пляшка для вина", "_comment6": "blocks", + "block.ukrainian_delight.brewing_keg": "Бродило", "block.ukrainian_delight.salt_block": "Блок солі", "block.ukrainian_delight.salt_bag": "Мішок солі", @@ -48,6 +49,7 @@ "ukrainian_delight.advancement.lean_borscht.desc": "Зваріть пісний борщ", "_comment8": "misc", + "gui.ukrainian_delight.brewing_keg": "Бродило", "death.attack.glass_damage": "%s був не обережний зі склом" } \ No newline at end of file diff --git a/src/main/resources/assets/ukrainian_delight/models/block/brewing_keg.json b/src/main/resources/assets/ukrainian_delight/models/block/brewing_keg.json new file mode 100644 index 0000000..2c81c37 --- /dev/null +++ b/src/main/resources/assets/ukrainian_delight/models/block/brewing_keg.json @@ -0,0 +1,23 @@ +{ + "credit": "Made with Blockbench", + "texture_size": [32, 32], + "textures": { + "0": "ukrainian_delight:block/brewing_keg", + "particle": "ukrainian_delight:block/brewing_keg" + }, + "elements": [ + { + "from": [4, 0, 1], + "to": [12, 8, 15], + "rotation": {"angle": 0, "axis": "y", "origin": [1, 0, 1]}, + "faces": { + "north": {"uv": [0, 8, 4, 12], "texture": "#0"}, + "east": {"uv": [0, 0, 7, 4], "texture": "#0"}, + "south": {"uv": [11, 0, 15, 4], "texture": "#0"}, + "west": {"uv": [0, 4, 7, 8], "texture": "#0"}, + "up": {"uv": [11, 7, 7, 0], "texture": "#0"}, + "down": {"uv": [11, 7, 7, 14], "texture": "#0"} + } + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/ukrainian_delight/models/item/brewing_keg.json b/src/main/resources/assets/ukrainian_delight/models/item/brewing_keg.json new file mode 100644 index 0000000..f2d54bf --- /dev/null +++ b/src/main/resources/assets/ukrainian_delight/models/item/brewing_keg.json @@ -0,0 +1,3 @@ +{ + "parent": "tutorialmod:block/brewing_keg" +} \ No newline at end of file diff --git a/src/main/resources/assets/ukrainian_delight/textures/block/brewing_keg.png b/src/main/resources/assets/ukrainian_delight/textures/block/brewing_keg.png new file mode 100644 index 0000000..669a774 Binary files /dev/null and b/src/main/resources/assets/ukrainian_delight/textures/block/brewing_keg.png differ diff --git a/src/main/resources/assets/ukrainian_delight/textures/gui/brewing_keg_gui.png b/src/main/resources/assets/ukrainian_delight/textures/gui/brewing_keg_gui.png new file mode 100644 index 0000000..9af8311 Binary files /dev/null and b/src/main/resources/assets/ukrainian_delight/textures/gui/brewing_keg_gui.png differ