diff --git a/build.gradle.kts b/build.gradle.kts index 6d8f5cf97..02cd106d7 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -46,6 +46,11 @@ repositories { url = uri("https://maven.terraformersmc.com/") } + maven { + name = "Ladysnake" + url = uri("https://maven.ladysnake.org/releases") + } + maven { name = "Shedaniel" url = uri("https://maven.shedaniel.me/") diff --git a/config/checkstyle/checkstyle.xml b/config/checkstyle/checkstyle.xml index 7411d06eb..6a41bb46b 100644 --- a/config/checkstyle/checkstyle.xml +++ b/config/checkstyle/checkstyle.xml @@ -23,7 +23,6 @@ - diff --git a/gradle.properties b/gradle.properties index b424cadd0..3a9f398dc 100644 --- a/gradle.properties +++ b/gradle.properties @@ -5,12 +5,12 @@ paradiseLostVersion=2.1.0-beta+1.19.2 minecraftVersion=1.19.2 yarnVersion=1.19.2+build.28 -loaderVersion=0.14.13 +loaderVersion=0.15.7 javaVersion=17 -fabricApiVersion=0.73.2+1.19.2 +fabricApiVersion=0.77.0+1.19.2 incubusCoreVersion=1.9.4 -customportalapiVersion=0.0.1-beta54-1.19 +customportalapiVersion=0.0.1-beta63.5-1.19.X cardinalComponentsVersion=5.0.1 trinketsVersion=3.4.0 crowdinTranslateVersion=1.19.2 diff --git a/src/main/java/net/id/paradiselost/ParadiseLost.java b/src/main/java/net/id/paradiselost/ParadiseLost.java index 3d0fb406d..4b620067f 100644 --- a/src/main/java/net/id/paradiselost/ParadiseLost.java +++ b/src/main/java/net/id/paradiselost/ParadiseLost.java @@ -26,6 +26,7 @@ import net.id.paradiselost.items.ParadiseLostItems; import net.id.paradiselost.loot.ParadiseLostLootNumberProviderTypes; import net.id.paradiselost.lore.ParadiseLostLore; +import net.id.paradiselost.recipe.ParadiseLostRecipeTypes; import net.id.paradiselost.registry.ParadiseLostRegistries; import net.id.paradiselost.screen.ParadiseLostScreens; import net.id.paradiselost.util.ParadiseLostSoundEvents; @@ -89,6 +90,7 @@ public void onInitialize() { ParadiseLostEntityTypes.init(); ParadiseLostItems.init(); ParadiseLostBlockEntityTypes.init(); + ParadiseLostRecipeTypes.init(); ParadiseLostCommands.init(); ParadiseLostGameRules.init(); ParadiseLostLootNumberProviderTypes.init(); diff --git a/src/main/java/net/id/paradiselost/blocks/ParadiseLostBlocks.java b/src/main/java/net/id/paradiselost/blocks/ParadiseLostBlocks.java index 51293977c..ce83c9c9c 100644 --- a/src/main/java/net/id/paradiselost/blocks/ParadiseLostBlocks.java +++ b/src/main/java/net/id/paradiselost/blocks/ParadiseLostBlocks.java @@ -5,10 +5,24 @@ import net.id.incubus_core.woodtypefactory.api.chest.ChestFactory; import net.id.paradiselost.ParadiseLost; import net.id.paradiselost.blocks.decorative.*; -import net.id.paradiselost.blocks.mechanical.*; -import net.id.paradiselost.blocks.natural.*; -import net.id.paradiselost.blocks.natural.cloud.*; -import net.id.paradiselost.blocks.natural.crop.*; +import net.id.paradiselost.blocks.mechanical.CherineCampfireBlock; +import net.id.paradiselost.blocks.mechanical.FoodBowlBlock; +import net.id.paradiselost.blocks.mechanical.FourBiteCakeBlock; +import net.id.paradiselost.blocks.mechanical.IncubatorBlock; +import net.id.paradiselost.blocks.mechanical.TreeTapBlock; +import net.id.paradiselost.blocks.natural.ParadiseLostGrassBlock; +import net.id.paradiselost.blocks.natural.ParadiseLostSaplingBlock; +import net.id.paradiselost.blocks.natural.ParadiseLostSnowyBlock; +import net.id.paradiselost.blocks.natural.PoofBlock; +import net.id.paradiselost.blocks.natural.SurtrumOreBlock; +import net.id.paradiselost.blocks.natural.cloud.ParadiseLostCloudBlock; +import net.id.paradiselost.blocks.natural.cloud.BlueParadiseLostCloudBlock; +import net.id.paradiselost.blocks.natural.cloud.GoldenParadiseLostCloudBlock; +import net.id.paradiselost.blocks.natural.cloud.PinkParadiseLostCloudBlock; +import net.id.paradiselost.blocks.natural.crop.AmadrysCropBlock; +import net.id.paradiselost.blocks.natural.crop.BlackcurrantBushBlock; +import net.id.paradiselost.blocks.natural.crop.FlaxCropBlock; +import net.id.paradiselost.blocks.natural.crop.SwedrootCropBlock; import net.id.paradiselost.blocks.natural.plant.*; import net.id.paradiselost.blocks.natural.tree.*; import net.id.paradiselost.fluids.ParadiseLostFluids; @@ -41,7 +55,7 @@ @SuppressWarnings("unused") public class ParadiseLostBlocks { - protected static Settings unbreakable(AbstractBlock.Settings settings) { + protected static Settings unbreakable(AbstractBlock.Settings settings) { return settings.strength(-1f, 3600000f); } @@ -375,6 +389,7 @@ private static Settings cherineTorch() { // Usables public static final IncubatorBlock INCUBATOR = add("incubator", new IncubatorBlock(of(Material.WOOD, MapColor.DULL_RED).strength(2.5f).sounds(BlockSoundGroup.WOOD).nonOpaque()), cutoutMippedRenderLayer); public static final FoodBowlBlock FOOD_BOWL = add("food_bowl", new FoodBowlBlock(of(Material.WOOD, MapColor.DULL_RED).strength(2.5f).sounds(BlockSoundGroup.WOOD).nonOpaque()), cutoutMippedRenderLayer); + public static final Block TREE_TAP = add("tree_tap", new TreeTapBlock(of(Material.WOOD, MapColor.OAK_TAN).strength(2.5f).sounds(BlockSoundGroup.WOOD).nonOpaque().ticksRandomly()), cutoutRenderLayer); //dungeon // public static final DungeonSwitchBlock DUNGEON_SWITCH = add("dungeonswitch", new DungeonSwitchBlock(of(Material.METAL, MapColor.BLUE).strength(-1.0F, 3600000.0F))); @@ -395,7 +410,7 @@ private static V add(String id, V block, Action... /* This is the same thing the add method above, but it doesn't wait to register or perform the actions. - This is required because some of the block settings code uses ID caches, so without it some blocks + This is required because some block settings code uses ID caches, so without it some blocks behave like air. */ @SafeVarargs diff --git a/src/main/java/net/id/paradiselost/blocks/blockentity/ParadiseLostBlockEntityTypes.java b/src/main/java/net/id/paradiselost/blocks/blockentity/ParadiseLostBlockEntityTypes.java index a126c706f..73c416c8c 100644 --- a/src/main/java/net/id/paradiselost/blocks/blockentity/ParadiseLostBlockEntityTypes.java +++ b/src/main/java/net/id/paradiselost/blocks/blockentity/ParadiseLostBlockEntityTypes.java @@ -12,12 +12,14 @@ public class ParadiseLostBlockEntityTypes { public static final BlockEntityType FOOD_BOWL = create(FoodBowlBlockEntity::new, ParadiseLostBlocks.FOOD_BOWL).build(); public static final BlockEntityType INCUBATOR = create(IncubatorBlockEntity::new, ParadiseLostBlocks.INCUBATOR).build(); public static final BlockEntityType CHERINE_CAMPFIRE = create(CherineCampfireBlockEntity::new, ParadiseLostBlocks.CHERINE_CAMPFIRE).build(); + public static final BlockEntityType TREE_TAP = create(TreeTapBlockEntity::new, ParadiseLostBlocks.TREE_TAP).build(); // public static final BlockEntityType DUNGEON_SWITCH = create(DungeonSwitchBlockEntity::new, ParadiseLostBlocks.DUNGEON_SWITCH).build(); public static void init() { register("food_bowl", FOOD_BOWL); register("incubator", INCUBATOR); register("cherine_campfire", CHERINE_CAMPFIRE); + register("tree_tap", TREE_TAP); // register("dungeonswitch", DUNGEON_SWITCH); } diff --git a/src/main/java/net/id/paradiselost/blocks/blockentity/TreeTapBlockEntity.java b/src/main/java/net/id/paradiselost/blocks/blockentity/TreeTapBlockEntity.java new file mode 100644 index 000000000..29ee4f0f1 --- /dev/null +++ b/src/main/java/net/id/paradiselost/blocks/blockentity/TreeTapBlockEntity.java @@ -0,0 +1,107 @@ +package net.id.paradiselost.blocks.blockentity; + +import net.id.incubus_core.be.InventoryBlockEntity; +import net.id.paradiselost.recipe.ParadiseLostRecipeTypes; +import net.id.paradiselost.recipe.TreeTapRecipe; +import net.minecraft.block.BlockState; +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.inventory.Inventories; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NbtCompound; +import net.minecraft.network.Packet; +import net.minecraft.network.listener.ClientPlayPacketListener; +import net.minecraft.network.packet.s2c.play.BlockEntityUpdateS2CPacket; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.state.property.Properties; +import net.minecraft.util.Hand; +import net.minecraft.util.ItemScatterer; +import net.minecraft.util.collection.DefaultedList; +import net.minecraft.util.math.BlockPos; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Optional; + +public class TreeTapBlockEntity extends BlockEntity implements InventoryBlockEntity { + + private final DefaultedList inventory; + + public TreeTapBlockEntity(BlockPos pos, BlockState state) { + super(ParadiseLostBlockEntityTypes.TREE_TAP, pos, state); + inventory = DefaultedList.ofSize(1, ItemStack.EMPTY); + } + + public void handleUse(PlayerEntity player, Hand hand, ItemStack handStack) { + ItemStack stored = inventory.get(0); + inventory.set(0, handStack); + player.setStackInHand(hand, stored); + markDirty(); + } + + @Override + public @NotNull HopperStrategy getHopperStrategy() { + return HopperStrategy.IN_ANY_OUT_BOTTOM; + } + + @Override + public DefaultedList getItems() { + return inventory; + } + + @Override + public void readNbt(NbtCompound nbt) { + super.readNbt(nbt); + + Inventories.readNbt(nbt, inventory); + } + + @Override + public void writeNbt(NbtCompound nbt) { + super.writeNbt(nbt); + Inventories.writeNbt(nbt, inventory); + } + + public BlockState getTappedState() { + return this.world.getBlockState(this.pos.offset(getCachedState().get(Properties.HORIZONTAL_FACING).getOpposite())); + } + + public void tryCraft() { + ItemStack stack = getStack(0); + if (stack.isEmpty()) { + return; + } + + Optional recipe = this.world.getRecipeManager().getFirstMatch(ParadiseLostRecipeTypes.TREE_TAP_RECIPE_TYPE, this, this.world); + if (recipe.isPresent()) { + ItemStack output = recipe.get().craft(this); + stack.decrement(1); + + // TODO: play a sound? + if (stack.isEmpty()) { + this.inventory.set(0, output); + updateInClientWorld(); + } else { + ItemScatterer.spawn(world, pos.getX(), pos.getY(), pos.getZ(), output); + } + } + } + + @Override + public NbtCompound toInitialChunkDataNbt() { + NbtCompound nbtCompound = new NbtCompound(); + this.writeNbt(nbtCompound); + return nbtCompound; + } + + @Nullable + @Override + public Packet toUpdatePacket() { + return BlockEntityUpdateS2CPacket.create(this); + } + + public void updateInClientWorld() { + ((ServerWorld) world).getChunkManager().markForUpdate(pos); + } + +} diff --git a/src/main/java/net/id/paradiselost/blocks/mechanical/TreeTapBlock.java b/src/main/java/net/id/paradiselost/blocks/mechanical/TreeTapBlock.java new file mode 100644 index 000000000..10b451530 --- /dev/null +++ b/src/main/java/net/id/paradiselost/blocks/mechanical/TreeTapBlock.java @@ -0,0 +1,141 @@ +package net.id.paradiselost.blocks.mechanical; + +import net.id.paradiselost.blocks.blockentity.TreeTapBlockEntity; +import net.minecraft.block.Block; +import net.minecraft.block.BlockRenderType; +import net.minecraft.block.BlockState; +import net.minecraft.block.ShapeContext; +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.inventory.Inventory; +import net.minecraft.item.ItemPlacementContext; +import net.minecraft.screen.ScreenHandler; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.state.StateManager; +import net.minecraft.state.property.DirectionProperty; +import net.minecraft.state.property.Properties; +import net.minecraft.util.ActionResult; +import net.minecraft.util.BlockMirror; +import net.minecraft.util.BlockRotation; +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.math.Direction; +import net.minecraft.util.math.random.Random; +import net.minecraft.util.shape.VoxelShape; +import net.minecraft.world.BlockView; +import net.minecraft.world.World; +import net.minecraft.world.WorldView; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class TreeTapBlock extends ParadiseLostBlockWithEntity { + + public static final DirectionProperty FACING = Properties.HORIZONTAL_FACING; + private static final VoxelShape SHAPE = Block.createCuboidShape(0, 0, 0, 16, 5, 16); + + public TreeTapBlock(Settings settings) { + super(settings, true); + } + + @Override + public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) { + if (!player.isSneaking() && world.getBlockEntity(pos) instanceof TreeTapBlockEntity treeTapBlockEntity) { + treeTapBlockEntity.handleUse(player, hand, player.getStackInHand(hand)); + return ActionResult.success(world.isClient()); + } + return super.onUse(state, world, pos, player, hand, hit); + } + + @Override + public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) { + return SHAPE; + } + + @Override + public boolean canPlaceAt(BlockState state, WorldView world, BlockPos pos) { + Direction direction = state.get(FACING); + if (!direction.getAxis().isHorizontal()) { + return false; + } + + BlockPos blockPos = pos.offset(direction.getOpposite()); + BlockState blockState = world.getBlockState(blockPos); + return blockState.isSideSolidFullSquare(world, blockPos, direction); + } + + @Override + public BlockRenderType getRenderType(BlockState state) { + return BlockRenderType.MODEL; + } + + @Override + public BlockState getPlacementState(ItemPlacementContext ctx) { + Direction direction = ctx.getSide(); + if (!direction.getAxis().isHorizontal()) { + return null; + } + + return this.getDefaultState().with(FACING, direction); + } + + @Override + protected void appendProperties(StateManager.Builder builder) { + builder.add(WATERLOGGED, POWERED, FACING); + } + + @Override + public BlockState rotate(BlockState state, BlockRotation rotation) { + return state.with(FACING, rotation.rotate(state.get(FACING))); + } + + @Override + public BlockState mirror(BlockState state, BlockMirror mirror) { + return state.rotate(mirror.getRotation(state.get(FACING))); + } + + @Override + public void randomTick(BlockState state, ServerWorld world, BlockPos pos, Random random) { + super.randomTick(state, world, pos, random); + + if (!world.isClient && world.getBlockEntity(pos) instanceof TreeTapBlockEntity treeTapBlockEntity) { + treeTapBlockEntity.tryCraft(); + } + } + + @Nullable + @Override + public BlockEntity createBlockEntity(BlockPos pos, BlockState state) { + return new TreeTapBlockEntity(pos, state); + } + + @Override + public void onStateReplaced(BlockState state, World world, BlockPos pos, BlockState newState, boolean moved) { + if (!state.isOf(newState.getBlock())) { + scatterContents(world, pos); + world.updateComparators(pos, this); + } + super.onStateReplaced(state, world, pos, newState, moved); + } + + public static void scatterContents(World world, BlockPos pos) { + Block block = world.getBlockState(pos).getBlock(); + BlockEntity blockEntity = world.getBlockEntity(pos); + if (blockEntity instanceof Inventory inventory) { + ItemScatterer.spawn(world, pos, inventory); + world.updateComparators(pos, block); + } + } + + @Override + public boolean hasComparatorOutput(BlockState state) { + return true; + } + + @Override + public int getComparatorOutput(BlockState state, @NotNull World world, BlockPos pos) { + return ScreenHandler.calculateComparatorOutput(world.getBlockEntity(pos)); + } + +} diff --git a/src/main/java/net/id/paradiselost/client/rendering/block/ParadiseLostBlockEntityRenderers.java b/src/main/java/net/id/paradiselost/client/rendering/block/ParadiseLostBlockEntityRenderers.java index 3a4ec03e2..877be34e2 100644 --- a/src/main/java/net/id/paradiselost/client/rendering/block/ParadiseLostBlockEntityRenderers.java +++ b/src/main/java/net/id/paradiselost/client/rendering/block/ParadiseLostBlockEntityRenderers.java @@ -2,16 +2,17 @@ import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; -import net.fabricmc.fabric.api.client.rendering.v1.BlockEntityRendererRegistry; import net.id.paradiselost.blocks.blockentity.ParadiseLostBlockEntityTypes; +import net.minecraft.client.render.block.entity.BlockEntityRendererFactories; @Environment(EnvType.CLIENT) public class ParadiseLostBlockEntityRenderers { @Environment(EnvType.CLIENT) public static void initClient() { - BlockEntityRendererRegistry.register(ParadiseLostBlockEntityTypes.INCUBATOR, IncubatorBlockEntityRenderer::new); - BlockEntityRendererRegistry.register(ParadiseLostBlockEntityTypes.CHERINE_CAMPFIRE, CherineCampfireBlockEntityRenderer::new); -// BlockEntityRendererRegistry.register(ParadiseLostBlockEntityTypes.DUNGEON_SWITCH, DungeonSwitchBlockEntityRenderer::new); + BlockEntityRendererFactories.register(ParadiseLostBlockEntityTypes.INCUBATOR, IncubatorBlockEntityRenderer::new); + BlockEntityRendererFactories.register(ParadiseLostBlockEntityTypes.CHERINE_CAMPFIRE, CherineCampfireBlockEntityRenderer::new); + BlockEntityRendererFactories.register(ParadiseLostBlockEntityTypes.TREE_TAP, TreeTapBlockEntityRenderer::new); + // BlockEntityRendererFactories.register(ParadiseLostBlockEntityTypes.DUNGEON_SWITCH, DungeonSwitchBlockEntityRenderer::new); } } diff --git a/src/main/java/net/id/paradiselost/client/rendering/block/TreeTapBlockEntityRenderer.java b/src/main/java/net/id/paradiselost/client/rendering/block/TreeTapBlockEntityRenderer.java new file mode 100644 index 000000000..65d4fc178 --- /dev/null +++ b/src/main/java/net/id/paradiselost/client/rendering/block/TreeTapBlockEntityRenderer.java @@ -0,0 +1,29 @@ +package net.id.paradiselost.client.rendering.block; + +import net.fabricmc.api.*; +import net.id.paradiselost.blocks.blockentity.*; +import net.minecraft.client.*; +import net.minecraft.client.render.*; +import net.minecraft.client.render.block.entity.*; +import net.minecraft.client.render.model.json.*; +import net.minecraft.client.util.math.*; + +@Environment(EnvType.CLIENT) +public class TreeTapBlockEntityRenderer implements BlockEntityRenderer { + + public TreeTapBlockEntityRenderer(BlockEntityRendererFactory.Context ctx) { + } + + @Override + public void render(TreeTapBlockEntity entity, float tickDelta, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, int overlay) { + if (!entity.isEmpty()) { + matrices.push(); + // todo: rotate along facing axis + matrices.translate(0.5, 0.4, 0.5); + matrices.scale(0.75F, 0.75F, 0.75F); + MinecraftClient.getInstance().getItemRenderer().renderItem(entity.getStack(0), ModelTransformation.Mode.FIXED, light, overlay, matrices, vertexConsumers, 0); + matrices.pop(); + } + } + +} diff --git a/src/main/java/net/id/paradiselost/items/ParadiseLostItems.java b/src/main/java/net/id/paradiselost/items/ParadiseLostItems.java index 90579e92b..424ca41d5 100644 --- a/src/main/java/net/id/paradiselost/items/ParadiseLostItems.java +++ b/src/main/java/net/id/paradiselost/items/ParadiseLostItems.java @@ -175,6 +175,7 @@ private static Settings misc() { public static final MoaEggItem MOA_EGG = add("moa_egg", new MoaEggItem(misc().maxCount(1))); public static final BlockItem INCUBATOR = add("incubator", ParadiseLostBlocks.INCUBATOR, misc, fuel(300)); public static final BlockItem FOOD_BOWL = add("food_bowl", ParadiseLostBlocks.FOOD_BOWL, misc, fuel(300)); + public static final BlockItem TREE_TAP = add("tree_tap", ParadiseLostBlocks.TREE_TAP, misc, fuel(300)); public static final AurelBucketItem AUREL_BUCKET = add("aurel_bucket", new AurelBucketItem(misc().maxCount(16)), fuel(200), emptyBucketBehavior); diff --git a/src/main/java/net/id/paradiselost/recipe/ParadiseLostRecipeTypes.java b/src/main/java/net/id/paradiselost/recipe/ParadiseLostRecipeTypes.java new file mode 100644 index 000000000..12f745324 --- /dev/null +++ b/src/main/java/net/id/paradiselost/recipe/ParadiseLostRecipeTypes.java @@ -0,0 +1,33 @@ +package net.id.paradiselost.recipe; + +import net.id.paradiselost.ParadiseLost; +import net.minecraft.recipe.Recipe; +import net.minecraft.recipe.RecipeSerializer; +import net.minecraft.recipe.RecipeType; +import net.minecraft.util.registry.Registry; + +public class ParadiseLostRecipeTypes { + + public static final String TREE_TAP_RECIPE_ID = "tree_tap"; + public static RecipeSerializer TREE_TAP_RECIPE_SERIALIZER; + public static RecipeType TREE_TAP_RECIPE_TYPE; + + static , T extends Recipe> S registerSerializer(String id, S serializer) { + return Registry.register(Registry.RECIPE_SERIALIZER, ParadiseLost.locate(id), serializer); + } + + static > RecipeType registerRecipeType(String id) { + return Registry.register(Registry.RECIPE_TYPE, ParadiseLost.locate(id), new RecipeType() { + @Override + public String toString() { + return ParadiseLost.MOD_ID + ":" + id; + } + }); + } + + public static void init() { + TREE_TAP_RECIPE_SERIALIZER = registerSerializer(TREE_TAP_RECIPE_ID, new TreeTapRecipeSerializer(TreeTapRecipe::new)); + TREE_TAP_RECIPE_TYPE = registerRecipeType(TREE_TAP_RECIPE_ID); + } + +} diff --git a/src/main/java/net/id/paradiselost/recipe/TreeTapRecipe.java b/src/main/java/net/id/paradiselost/recipe/TreeTapRecipe.java new file mode 100644 index 000000000..043da045a --- /dev/null +++ b/src/main/java/net/id/paradiselost/recipe/TreeTapRecipe.java @@ -0,0 +1,74 @@ +package net.id.paradiselost.recipe; + +import net.id.paradiselost.blocks.blockentity.TreeTapBlockEntity; +import net.minecraft.block.Block; +import net.minecraft.item.ItemStack; +import net.minecraft.recipe.Ingredient; +import net.minecraft.recipe.Recipe; +import net.minecraft.recipe.RecipeSerializer; +import net.minecraft.recipe.RecipeType; +import net.minecraft.util.Identifier; +import net.minecraft.world.World; + +public class TreeTapRecipe implements Recipe { + + protected final Identifier id; + protected final String group; + + protected final Ingredient ingredient; + protected final ItemStack output; + protected final Block tappedBlock; + + public TreeTapRecipe(Identifier id, String group, Ingredient ingredient, ItemStack output, Block tappedBlock) { + this.id = id; + this.group = group; + this.ingredient = ingredient; + this.output = output; + this.tappedBlock = tappedBlock; + } + + @Override + public boolean matches(TreeTapBlockEntity inventory, World world) { + if (!ingredient.test(inventory.getStack(0))) { + return false; + } + + return inventory.getTappedState().isOf(this.tappedBlock); + } + + @Override + public ItemStack craft(TreeTapBlockEntity inventory) { + return output.copy(); + } + + @Override + public boolean fits(int width, int height) { + return true; + } + + @Override + public ItemStack getOutput() { + return output; + } + + @Override + public String getGroup() { + return group; + } + + @Override + public Identifier getId() { + return id; + } + + @Override + public RecipeSerializer getSerializer() { + return ParadiseLostRecipeTypes.TREE_TAP_RECIPE_SERIALIZER; + } + + @Override + public RecipeType getType() { + return ParadiseLostRecipeTypes.TREE_TAP_RECIPE_TYPE; + } + +} diff --git a/src/main/java/net/id/paradiselost/recipe/TreeTapRecipeSerializer.java b/src/main/java/net/id/paradiselost/recipe/TreeTapRecipeSerializer.java new file mode 100644 index 000000000..c40fbe7e4 --- /dev/null +++ b/src/main/java/net/id/paradiselost/recipe/TreeTapRecipeSerializer.java @@ -0,0 +1,48 @@ +package net.id.paradiselost.recipe; + +import com.google.gson.JsonObject; +import net.id.incubus_core.recipe.RecipeParser; +import net.minecraft.block.Block; +import net.minecraft.item.ItemStack; +import net.minecraft.network.PacketByteBuf; +import net.minecraft.recipe.Ingredient; +import net.minecraft.recipe.RecipeSerializer; +import net.minecraft.util.Identifier; +import net.minecraft.util.JsonHelper; +import net.minecraft.util.registry.Registry; + +public record TreeTapRecipeSerializer(TreeTapRecipeSerializer.RecipeFactory recipeFactory) implements RecipeSerializer { + + public interface RecipeFactory { + TreeTapRecipe create(Identifier id, String group, Ingredient ingredient, ItemStack output, Block tappedBlock); + } + + @Override + public TreeTapRecipe read(Identifier identifier, JsonObject jsonObject) { + String group = JsonHelper.getString(jsonObject, "group", ""); + Ingredient ingredient = Ingredient.fromJson(JsonHelper.getObject(jsonObject, "ingredient")); + Block tappedBlock = Registry.BLOCK.get(Identifier.tryParse(JsonHelper.getString(jsonObject, "tapped_block"))); + ItemStack output = RecipeParser.getItemStackWithNbtFromJson(JsonHelper.getObject(jsonObject, "result")); + + return this.recipeFactory.create(identifier, group, ingredient, output, tappedBlock); + } + + @Override + public void write(PacketByteBuf packetByteBuf, TreeTapRecipe recipe) { + packetByteBuf.writeString(recipe.group); + recipe.ingredient.write(packetByteBuf); + packetByteBuf.writeIdentifier(Registry.BLOCK.getId(recipe.tappedBlock)); + packetByteBuf.writeItemStack(recipe.output); + } + + @Override + public TreeTapRecipe read(Identifier identifier, PacketByteBuf packetByteBuf) { + String group = packetByteBuf.readString(); + Ingredient ingredient = Ingredient.fromPacket(packetByteBuf); + Block tappedBlock = Registry.BLOCK.get(packetByteBuf.readIdentifier()); + ItemStack output = packetByteBuf.readItemStack(); + + return this.recipeFactory.create(identifier, group, ingredient, output, tappedBlock); + } + +} diff --git a/src/main/resources/assets/paradise_lost/blockstates/tree_tap.json b/src/main/resources/assets/paradise_lost/blockstates/tree_tap.json new file mode 100644 index 000000000..0eb3bc66b --- /dev/null +++ b/src/main/resources/assets/paradise_lost/blockstates/tree_tap.json @@ -0,0 +1,19 @@ +{ + "variants": { + "facing=east": { + "model": "paradise_lost:block/tree_tap", + "y": 180 + }, + "facing=north": { + "model": "paradise_lost:block/tree_tap", + "y": 90 + }, + "facing=south": { + "model": "paradise_lost:block/tree_tap", + "y": 270 + }, + "facing=west": { + "model": "paradise_lost:block/tree_tap" + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/paradise_lost/lang/en_us.json b/src/main/resources/assets/paradise_lost/lang/en_us.json index 96c9a75ba..982173c51 100644 --- a/src/main/resources/assets/paradise_lost/lang/en_us.json +++ b/src/main/resources/assets/paradise_lost/lang/en_us.json @@ -243,6 +243,7 @@ "block.paradise_lost.incubator": "Incubator", "block.paradise_lost.food_bowl": "Feeding Trough", + "block.paradise_lost.tree_tap": "Tree Tap", "block.paradise_lost.crystal_chest": "Crystal Chest", "block.paradise_lost.golden_oak_chest": "Mother Aurel Chest", diff --git a/src/main/resources/assets/paradise_lost/models/block/tree_tap.json b/src/main/resources/assets/paradise_lost/models/block/tree_tap.json new file mode 100644 index 000000000..4652f39b9 --- /dev/null +++ b/src/main/resources/assets/paradise_lost/models/block/tree_tap.json @@ -0,0 +1,45 @@ +{ + "credit": "Made with Blockbench", + "parent": "block/block", + "textures": { + "0": "paradise_lost:block/aurel_planks", + "particle": "paradise_lost:block/aurel_planks" + }, + "elements": [ + { + "from": [5, 0, 2], + "to": [16, 1, 14], + "faces": { + "north": {"uv": [0, 0, 11, 1], "texture": "#0"}, + "east": {"uv": [0, 0, 12, 1], "texture": "#0"}, + "south": {"uv": [0, 0, 11, 1], "texture": "#0"}, + "west": {"uv": [0, 0, 12, 1], "texture": "#0"}, + "up": {"uv": [0, 0, 11, 12], "texture": "#0"}, + "down": {"uv": [0, 0, 11, 12], "texture": "#0"} + } + }, + { + "from": [9, 13, 7], + "to": [16, 15, 9], + "faces": { + "north": {"uv": [0, 0, 7, 2], "texture": "#0"}, + "east": {"uv": [0, 0, 2, 2], "texture": "#0"}, + "south": {"uv": [0, 0, 7, 2], "texture": "#0"}, + "west": {"uv": [0, 0, 2, 2], "texture": "#0"}, + "up": {"uv": [0, 0, 7, 2], "texture": "#0"}, + "down": {"uv": [0, 0, 7, 2], "texture": "#0"} + } + }, + { + "from": [9, 12, 7], + "to": [11, 13, 9], + "faces": { + "north": {"uv": [0, 0, 2, 1], "texture": "#0"}, + "east": {"uv": [0, 0, 2, 1], "texture": "#0"}, + "south": {"uv": [0, 0, 2, 1], "texture": "#0"}, + "west": {"uv": [0, 0, 2, 1], "texture": "#0"}, + "down": {"uv": [0, 0, 2, 2], "texture": "#0"} + } + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/paradise_lost/models/item/tree_tap.json b/src/main/resources/assets/paradise_lost/models/item/tree_tap.json new file mode 100644 index 000000000..8fd0579d8 --- /dev/null +++ b/src/main/resources/assets/paradise_lost/models/item/tree_tap.json @@ -0,0 +1,3 @@ +{ + "parent": "paradise_lost:block/tree_tap" +} diff --git a/src/main/resources/data/paradise_lost/loot_tables/blocks/tree_tap.json b/src/main/resources/data/paradise_lost/loot_tables/blocks/tree_tap.json new file mode 100644 index 000000000..5d560df11 --- /dev/null +++ b/src/main/resources/data/paradise_lost/loot_tables/blocks/tree_tap.json @@ -0,0 +1,20 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "rolls": 1.0, + "bonus_rolls": 0.0, + "entries": [ + { + "type": "minecraft:item", + "name": "paradise_lost:tree_tap" + } + ], + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ] + } + ] +} diff --git a/src/main/resources/data/paradise_lost/recipes/tree_tap.json b/src/main/resources/data/paradise_lost/recipes/tree_tap.json new file mode 100644 index 000000000..61b0199ea --- /dev/null +++ b/src/main/resources/data/paradise_lost/recipes/tree_tap.json @@ -0,0 +1,19 @@ +{ + "type": "minecraft:crafting_shaped", + "pattern": [ + "SSS", + " S", + "PPP" + ], + "key": { + "P": { + "item": "paradise_lost:aurel_planks" + }, + "S": { + "item": "minecraft:stick" + } + }, + "result": { + "item": "paradise_lost:tree_tap" + } +} diff --git a/src/main/resources/data/paradise_lost/recipes/tree_tap/water.json b/src/main/resources/data/paradise_lost/recipes/tree_tap/water.json new file mode 100644 index 000000000..469055eaf --- /dev/null +++ b/src/main/resources/data/paradise_lost/recipes/tree_tap/water.json @@ -0,0 +1,11 @@ +{ + "type": "paradise_lost:tree_tap", + "ingredient": { + "item": "minecraft:glass_bottle" + }, + "tapped_block": "paradise_lost:aurel_log", + "result": { + "item": "minecraft:potion", + "nbt": "{Potion: \"minecraft:water\"}" + } +}