diff --git a/src/main/java/ru/betterend/mixin/common/AbstractBlockMixin.java b/src/main/java/ru/betterend/mixin/common/AbstractBlockMixin.java index 8c0b3358..bb711bfd 100644 --- a/src/main/java/ru/betterend/mixin/common/AbstractBlockMixin.java +++ b/src/main/java/ru/betterend/mixin/common/AbstractBlockMixin.java @@ -19,6 +19,7 @@ import net.minecraft.item.Items; import net.minecraft.loot.context.LootContext; import net.minecraft.loot.context.LootContextParameters; import net.minecraft.util.math.MathHelper; + import ru.betterend.item.EndHammer; import ru.betterend.util.MHelper; diff --git a/src/main/java/ru/betterend/mixin/common/AnvilScreenHandlerMixin.java b/src/main/java/ru/betterend/mixin/common/AnvilScreenHandlerMixin.java new file mode 100644 index 00000000..68497c07 --- /dev/null +++ b/src/main/java/ru/betterend/mixin/common/AnvilScreenHandlerMixin.java @@ -0,0 +1,77 @@ +package ru.betterend.mixin.common; + +import java.util.List; + +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.entity.player.PlayerInventory; +import net.minecraft.item.ItemStack; +import net.minecraft.recipe.RecipeManager; +import net.minecraft.screen.AnvilScreenHandler; +import net.minecraft.screen.ForgingScreenHandler; +import net.minecraft.screen.Property; +import net.minecraft.screen.ScreenHandlerContext; +import net.minecraft.screen.ScreenHandlerType; +import net.minecraft.world.World; + +import ru.betterend.recipe.AnvilSmithingRecipe; + +@Mixin(AnvilScreenHandler.class) +public abstract class AnvilScreenHandlerMixin extends ForgingScreenHandler { + + private final World world = this.player.world; + private final RecipeManager recipeManager = this.world.getRecipeManager(); + private AnvilSmithingRecipe currentRecipe; + + @Final + @Shadow + private Property levelCost; + + public AnvilScreenHandlerMixin(ScreenHandlerType type, int syncId, PlayerInventory playerInventory, + ScreenHandlerContext context) { + super(type, syncId, playerInventory, context); + } + + @Inject(method = "canTakeOutput", at = @At("RETURN")) + protected void canTakeOutput(PlayerEntity player, boolean present, CallbackInfoReturnable info) { + if (!info.getReturnValue()) { + info.setReturnValue(currentRecipe != null && !currentRecipe.craft(input, player).isEmpty()); + } + } + + @Inject(method = "onTakeOutput", at = @At("HEAD"), cancellable = true) + protected void onTakeOutput(PlayerEntity player, ItemStack stack, CallbackInfoReturnable info) { + if (currentRecipe != null) { + this.input.getStack(0).decrement(1); + if (!currentRecipe.matches(input)) { + this.currentRecipe = null; + } + info.cancel(); + } + } + + @Inject(method = "updateResult", at = @At("HEAD"), cancellable = true) + public void updateResult(CallbackInfo info) { + this.currentRecipe = null; + List recipes = this.recipeManager.listAllOfType(AnvilSmithingRecipe.TYPE); + for (AnvilSmithingRecipe entry : recipes) { + if (entry.matches(input)) { + this.currentRecipe = entry; + break; + } + } + if (currentRecipe != null) { + this.levelCost.set(0); + this.output.setStack(0, currentRecipe.getOutput()); + this.sendContentUpdates(); + info.cancel(); + } + } +} diff --git a/src/main/java/ru/betterend/recipe/AlloyingRecipe.java b/src/main/java/ru/betterend/recipe/AlloyingRecipe.java index d3b8ccf5..cf44ca5d 100644 --- a/src/main/java/ru/betterend/recipe/AlloyingRecipe.java +++ b/src/main/java/ru/betterend/recipe/AlloyingRecipe.java @@ -103,6 +103,7 @@ public class AlloyingRecipe implements Recipe { return this.type; } + @Override @Environment(EnvType.CLIENT) public String getGroup() { return this.group; diff --git a/src/main/java/ru/betterend/recipe/AnvilSmithingRecipe.java b/src/main/java/ru/betterend/recipe/AnvilSmithingRecipe.java new file mode 100644 index 00000000..5e24d595 --- /dev/null +++ b/src/main/java/ru/betterend/recipe/AnvilSmithingRecipe.java @@ -0,0 +1,145 @@ +package ru.betterend.recipe; + +import com.google.gson.JsonObject; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; + +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.inventory.Inventory; +import net.minecraft.item.ItemStack; +import net.minecraft.item.ToolItem; +import net.minecraft.network.PacketByteBuf; +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.util.JsonHelper; +import net.minecraft.util.registry.Registry; +import net.minecraft.world.World; + +import ru.betterend.registry.ItemTagRegistry; + +public class AnvilSmithingRecipe implements Recipe { + + public final static RecipeType TYPE = EndRecipeManager.registerType("smithing"); + public final static Serializer SERIALIZER = EndRecipeManager.registerSerializer("smithing", new Serializer()); + + private final Identifier id; + private final Ingredient input; + private final ItemStack output; + private final int damage; + private final int level; + + public AnvilSmithingRecipe(Identifier identifier, Ingredient input, ItemStack output, int level, int damage) { + this.id = identifier; + this.input = input; + this.output = output; + this.level = level; + this.damage = damage; + } + + @Override + public RecipeSerializer getSerializer() { + return SERIALIZER; + } + + @Override + public boolean isIgnoredInRecipeBook() { + return false; + } + + @Override + public ItemStack getOutput() { + return ItemStack.EMPTY; + } + + @Override + public boolean matches(Inventory craftingInventory, World world) { + return this.matches(craftingInventory); + } + + @Override + public ItemStack craft(Inventory craftingInventory) { + if (!matches(craftingInventory)) return ItemStack.EMPTY; + ItemStack hammer = craftingInventory.getStack(1); + int damage = hammer.getDamage() + this.damage; + if (damage >= hammer.getMaxDamage()) return ItemStack.EMPTY; + hammer.setDamage(damage); + return this.output.copy(); + } + + public ItemStack craft(Inventory craftingInventory, PlayerEntity player) { + if (!matches(craftingInventory)) return ItemStack.EMPTY; + + ItemStack hammer = craftingInventory.getStack(1); + int damage = hammer.getDamage() + this.damage; + if (damage >= hammer.getMaxDamage()) return ItemStack.EMPTY; + + hammer.damage(this.damage, player, ((entity) -> { + entity.sendEquipmentBreakStatus(null); + })); + return this.output.copy(); + } + + public boolean matches(Inventory craftingInventory) { + ItemStack hammer = craftingInventory.getStack(1); + System.out.println(ItemTagRegistry.HAMMERS.values()); + if (hammer.isEmpty() || !ItemTagRegistry.HAMMERS.contains(hammer.getItem())) { + return false; + } + int level = ((ToolItem) hammer.getItem()).getMaterial().getMiningLevel(); + return level >= this.level && this.input.test(craftingInventory.getStack(0)); + } + + @Override + @Environment(EnvType.CLIENT) + public boolean fits(int width, int height) { + return true; + } + + @Override + public Identifier getId() { + return this.id; + } + + @Override + public RecipeType getType() { + return TYPE; + } + + public static class Serializer implements RecipeSerializer { + @Override + public AnvilSmithingRecipe read(Identifier id, JsonObject json) { + Ingredient input = Ingredient.fromJson(JsonHelper.getObject(json, "input")); + String resultStr = JsonHelper.getString(json, "result"); + Identifier resultId = new Identifier(resultStr); + ItemStack output = new ItemStack(Registry.ITEM.getOrEmpty(resultId).orElseThrow(() -> { + return new IllegalStateException("Item: " + resultStr + " does not exists!"); + })); + int level = JsonHelper.getInt(json, "level", 0); + int damage = JsonHelper.getInt(json, "damage", 1); + + return new AnvilSmithingRecipe(id, input, output, level, damage); + } + + @Override + public AnvilSmithingRecipe read(Identifier id, PacketByteBuf packetBuffer) { + Ingredient input = Ingredient.fromPacket(packetBuffer); + ItemStack output = packetBuffer.readItemStack(); + int level = packetBuffer.readVarInt(); + int damage = packetBuffer.readVarInt(); + + return new AnvilSmithingRecipe(id, input, output, level, damage); + } + + @Override + public void write(PacketByteBuf packetBuffer, AnvilSmithingRecipe recipe) { + recipe.input.write(packetBuffer); + packetBuffer.writeItemStack(recipe.output); + packetBuffer.writeVarInt(recipe.level); + packetBuffer.writeVarInt(recipe.damage); + } + } +} diff --git a/src/main/java/ru/betterend/recipe/CraftingRecipes.java b/src/main/java/ru/betterend/recipe/CraftingRecipes.java index 220e85f8..01fcc6b8 100644 --- a/src/main/java/ru/betterend/recipe/CraftingRecipes.java +++ b/src/main/java/ru/betterend/recipe/CraftingRecipes.java @@ -2,7 +2,11 @@ package ru.betterend.recipe; import net.minecraft.block.Blocks; import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; import net.minecraft.item.Items; +import net.minecraft.recipe.Ingredient; +import net.minecraft.recipe.RecipeType; +import ru.betterend.BetterEnd; import ru.betterend.registry.BlockRegistry; import ru.betterend.registry.ItemRegistry; @@ -68,6 +72,8 @@ public class CraftingRecipes { RecipeBuilder.make("creeping_moss_dye", Items.CYAN_DYE).setList("#").addMaterial('#', BlockRegistry.CREEPING_MOSS).build(); RecipeBuilder.make("umbrella_moss_dye", Items.YELLOW_DYE).setList("#").addMaterial('#', BlockRegistry.UMBRELLA_MOSS).build(); RecipeBuilder.make("umbrella_moss_tall_dye", Items.YELLOW_DYE).setList("#").addMaterial('#', BlockRegistry.UMBRELLA_MOSS_TALL).build(); + + EndRecipeManager.addRecipe(AnvilSmithingRecipe.TYPE, new AnvilSmithingRecipe(BetterEnd.makeID("ender_pearl_to_dust"), Ingredient.ofItems(Items.ENDER_PEARL), new ItemStack(ItemRegistry.ENDER_DUST), 4, 1)); } private static void registerHelmet(String name, Item material, Item result) { diff --git a/src/main/java/ru/betterend/registry/ItemTagRegistry.java b/src/main/java/ru/betterend/registry/ItemTagRegistry.java index 20620e69..727520c4 100644 --- a/src/main/java/ru/betterend/registry/ItemTagRegistry.java +++ b/src/main/java/ru/betterend/registry/ItemTagRegistry.java @@ -11,7 +11,7 @@ import net.minecraft.util.Identifier; import ru.betterend.BetterEnd; public class ItemTagRegistry { - public final static Tag HAMMERS = registerFabricItemTag("hammer"); + public final static Tag HAMMERS = registerFabricItemTag("hammers"); public static Tag registerItemTag(String name) { return TagRegistry.item(BetterEnd.makeID(name)); diff --git a/src/main/resources/betterend.mixins.common.json b/src/main/resources/betterend.mixins.common.json index 0d868909..dcca3bc6 100644 --- a/src/main/resources/betterend.mixins.common.json +++ b/src/main/resources/betterend.mixins.common.json @@ -10,6 +10,7 @@ "TagGroupLoaderMixin", "CraftingScreenHandlerMixin", "GenerationSettingsMixin", + "AnvilScreenHandlerMixin", "AbstractBlockMixin", "LivingEntityMixin", "BiomeMixin"