diff --git a/common/src/main/java/dev/dubhe/anvilcraft/api/depository/ItemDepositoryHelper.java b/common/src/main/java/dev/dubhe/anvilcraft/api/depository/ItemDepositoryHelper.java index 17285cc4f..c5028b087 100644 --- a/common/src/main/java/dev/dubhe/anvilcraft/api/depository/ItemDepositoryHelper.java +++ b/common/src/main/java/dev/dubhe/anvilcraft/api/depository/ItemDepositoryHelper.java @@ -36,36 +36,29 @@ private ItemDepositoryHelper() { * @param source 物品源 * @param maxAmount 导出的最大数量 * @param predicate 能够导出的物品 - * @param level 当前 Level - * @param pos 导出目标的位置 - * @param direction 导出目标的方向 + * @param target 目标 */ - @SuppressWarnings({"DuplicatedCode", "UnreachableCode"}) + @SuppressWarnings("DuplicatedCode") public static void exportToTarget( - IItemDepository source, + @NotNull IItemDepository source, int maxAmount, Predicate predicate, - @NotNull Level level, - BlockPos pos, - Direction direction + IItemDepository target ) { - if (level.getBlockState(pos).hasBlockEntity()) { - IItemDepository target = getItemDepository(level, pos, direction); - for (int srcIndex = 0; srcIndex < source.getSlots(); srcIndex++) { - ItemStack sourceStack = source.extract(srcIndex, Integer.MAX_VALUE, true); - if (sourceStack.isEmpty() || !predicate.test(sourceStack)) { - continue; - } - ItemStack remainder = insertItem(target, sourceStack, true); - int amountToInsert = sourceStack.getCount() - remainder.getCount(); - if (amountToInsert > 0) { - sourceStack = source.extract(srcIndex, Math.min(maxAmount, amountToInsert), false); - remainder = insertItem(target, sourceStack, false); - maxAmount -= Math.min(maxAmount, amountToInsert); - source.insert(srcIndex, remainder, false); - } - if (maxAmount <= 0) return; + for (int srcIndex = 0; srcIndex < source.getSlots(); srcIndex++) { + ItemStack sourceStack = source.extract(srcIndex, Integer.MAX_VALUE, true); + if (sourceStack.isEmpty() || !predicate.test(sourceStack)) { + continue; } + ItemStack remainder = insertItem(target, sourceStack, true); + int amountToInsert = sourceStack.getCount() - remainder.getCount(); + if (amountToInsert > 0) { + sourceStack = source.extract(srcIndex, Math.min(maxAmount, amountToInsert), false); + remainder = insertItem(target, sourceStack, false); + maxAmount -= Math.min(maxAmount, amountToInsert); + source.insert(srcIndex, remainder, false); + } + if (maxAmount <= 0) return; } } @@ -75,35 +68,28 @@ public static void exportToTarget( * @param target 物品目标 * @param maxAmount 导入的最大数量 * @param predicate 能够导入的物品 - * @param level 当前 Level - * @param pos 导入物品源的位置 - * @param direction 导入物品源的方向 + * @param source 物品源 */ - @SuppressWarnings({"DuplicatedCode", "UnreachableCode"}) + @SuppressWarnings("DuplicatedCode") public static void importToTarget( IItemDepository target, int maxAmount, Predicate predicate, - @NotNull Level level, - BlockPos pos, - Direction direction + @NotNull IItemDepository source ) { - if (level.getBlockState(pos).hasBlockEntity()) { - IItemDepository source = getItemDepository(level, pos, direction); - for (int srcIndex = 0; srcIndex < source.getSlots(); srcIndex++) { - ItemStack sourceStack = source.extract(srcIndex, Integer.MAX_VALUE, true); - if (sourceStack.isEmpty() || !predicate.test(sourceStack)) { - continue; - } - ItemStack remainder = insertItem(target, sourceStack, true); - int amountToInsert = sourceStack.getCount() - remainder.getCount(); - if (amountToInsert > 0) { - sourceStack = source.extract(srcIndex, Math.min(maxAmount, amountToInsert), false); - insertItem(target, sourceStack, false); - maxAmount -= Math.min(maxAmount, amountToInsert); - } - if (maxAmount <= 0) return; + for (int srcIndex = 0; srcIndex < source.getSlots(); srcIndex++) { + ItemStack sourceStack = source.extract(srcIndex, Integer.MAX_VALUE, true); + if (sourceStack.isEmpty() || !predicate.test(sourceStack)) { + continue; + } + ItemStack remainder = insertItem(target, sourceStack, true); + int amountToInsert = sourceStack.getCount() - remainder.getCount(); + if (amountToInsert > 0) { + sourceStack = source.extract(srcIndex, Math.min(maxAmount, amountToInsert), false); + insertItem(target, sourceStack, false); + maxAmount -= Math.min(maxAmount, amountToInsert); } + if (maxAmount <= 0) return; } } diff --git a/common/src/main/java/dev/dubhe/anvilcraft/block/MobAmberBlock.java b/common/src/main/java/dev/dubhe/anvilcraft/block/MobAmberBlock.java new file mode 100644 index 000000000..8770c4d16 --- /dev/null +++ b/common/src/main/java/dev/dubhe/anvilcraft/block/MobAmberBlock.java @@ -0,0 +1,27 @@ +package dev.dubhe.anvilcraft.block; + +import dev.dubhe.anvilcraft.init.ModBlockEntities; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.block.BaseEntityBlock; +import net.minecraft.world.level.block.RenderShape; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class MobAmberBlock extends BaseEntityBlock { + public MobAmberBlock(Properties properties) { + super(properties); + } + + @Nullable + @Override + public BlockEntity newBlockEntity(@NotNull BlockPos pos, @NotNull BlockState state) { + return ModBlockEntities.MOB_AMBER_BLOCK.create(pos, state); + } + + @Override + public @NotNull RenderShape getRenderShape(@NotNull BlockState state) { + return RenderShape.MODEL; + } +} diff --git a/common/src/main/java/dev/dubhe/anvilcraft/block/ResentfulAmberBlock.java b/common/src/main/java/dev/dubhe/anvilcraft/block/ResentfulAmberBlock.java new file mode 100644 index 000000000..a9a13ec0c --- /dev/null +++ b/common/src/main/java/dev/dubhe/anvilcraft/block/ResentfulAmberBlock.java @@ -0,0 +1,20 @@ +package dev.dubhe.anvilcraft.block; + +import dev.dubhe.anvilcraft.init.ModBlockEntities; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class ResentfulAmberBlock extends MobAmberBlock { + public ResentfulAmberBlock(Properties properties) { + super(properties); + } + + @Nullable + @Override + public BlockEntity newBlockEntity(@NotNull BlockPos pos, @NotNull BlockState state) { + return ModBlockEntities.RESENTFUL_AMBER_BLOCK.create(pos, state); + } +} diff --git a/common/src/main/java/dev/dubhe/anvilcraft/block/entity/ChuteBlockEntity.java b/common/src/main/java/dev/dubhe/anvilcraft/block/entity/ChuteBlockEntity.java index 919aaeba8..51d8fc1fd 100644 --- a/common/src/main/java/dev/dubhe/anvilcraft/block/entity/ChuteBlockEntity.java +++ b/common/src/main/java/dev/dubhe/anvilcraft/block/entity/ChuteBlockEntity.java @@ -3,6 +3,7 @@ import dev.architectury.injectables.annotations.ExpectPlatform; import dev.dubhe.anvilcraft.AnvilCraft; import dev.dubhe.anvilcraft.api.depository.FilteredItemDepository; +import dev.dubhe.anvilcraft.api.depository.IItemDepository; import dev.dubhe.anvilcraft.api.depository.ItemDepositoryHelper; import dev.dubhe.anvilcraft.block.ChuteBlock; import dev.dubhe.anvilcraft.init.ModBlocks; @@ -109,44 +110,50 @@ public void load(@NotNull CompoundTag tag) { public void tick() { if (cooldown <= 0) { if (getBlockState().getValue(ChuteBlock.ENABLED)) { - if (ItemDepositoryHelper.getItemDepository(getLevel(), - getBlockPos().relative(Direction.UP), Direction.UP.getOpposite()) != null) { + IItemDepository depository = ItemDepositoryHelper.getItemDepository( + getLevel(), + getBlockPos().relative(Direction.UP), + Direction.UP.getOpposite() + ); + if (depository != null) { // 尝试从上方容器输入 - ItemDepositoryHelper.importToTarget(depository, - 64, stack -> true, getLevel(), - getBlockPos().relative(Direction.UP), Direction.UP.getOpposite()); + ItemDepositoryHelper.importToTarget(this.depository, 64, stack -> true, depository); } else { List itemEntities = getLevel().getEntitiesOfClass( ItemEntity.class, new AABB(getBlockPos().relative(Direction.UP)), itemEntity -> !itemEntity.getItem().isEmpty()); for (ItemEntity itemEntity : itemEntities) { - ItemStack remaining = ItemDepositoryHelper.insertItem(depository, itemEntity.getItem(), true); + ItemStack remaining = ItemDepositoryHelper.insertItem( + this.depository, itemEntity.getItem(), true + ); if (!remaining.isEmpty()) continue; - ItemDepositoryHelper.insertItem(depository, itemEntity.getItem(), false); + ItemDepositoryHelper.insertItem(this.depository, itemEntity.getItem(), false); itemEntity.kill(); break; } } - if (ItemDepositoryHelper.getItemDepository(getLevel(), - getBlockPos().relative(getDirection()), getDirection().getOpposite()) != null) { + depository = ItemDepositoryHelper.getItemDepository( + getLevel(), + getBlockPos().relative(this.getDirection()), + this.getDirection().getOpposite() + ); + if (depository != null) { // 尝试向朝向容器输出 - if (!depository.isEmpty()) { - ItemDepositoryHelper.exportToTarget(depository, - 64, stack -> true, getLevel(), - getBlockPos().relative(getDirection()), getDirection().getOpposite()); + if (!this.depository.isEmpty()) { + ItemDepositoryHelper.exportToTarget(this.depository, 64, stack -> true, depository); } } else { Vec3 center = getBlockPos().relative(getDirection()).getCenter(); AABB aabb = new AABB(center.add(-0.125, -0.125, -0.125), center.add(0.125, 0.125, 0.125)); if (getLevel().noCollision(aabb)) { - for (int i = 0; i < depository.getSlots(); i++) { - ItemStack stack = depository.getStack(i); + for (int i = 0; i < this.depository.getSlots(); i++) { + ItemStack stack = this.depository.getStack(i); if (!stack.isEmpty()) { ItemEntity itemEntity = new ItemEntity( getLevel(), center.x, center.y, center.z, stack, 0, 0, 0); itemEntity.setDefaultPickUpDelay(); getLevel().addFreshEntity(itemEntity); - depository.setStack(i, ItemStack.EMPTY); + this.depository.setStack(i, ItemStack.EMPTY); break; } } diff --git a/common/src/main/java/dev/dubhe/anvilcraft/block/entity/HasMobBlockEntity.java b/common/src/main/java/dev/dubhe/anvilcraft/block/entity/HasMobBlockEntity.java new file mode 100644 index 000000000..6db1cdecb --- /dev/null +++ b/common/src/main/java/dev/dubhe/anvilcraft/block/entity/HasMobBlockEntity.java @@ -0,0 +1,96 @@ +package dev.dubhe.anvilcraft.block.entity; + +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.protocol.Packet; +import net.minecraft.network.protocol.game.ClientGamePacketListener; +import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Optional; + +public abstract class HasMobBlockEntity extends BlockEntity { + private CompoundTag entity = null; + private Entity displayEntity = null; + + protected HasMobBlockEntity(BlockEntityType type, BlockPos pos, BlockState blockState) { + super(type, pos, blockState); + } + + /** + * 设置实体 + */ + public void setEntity(Entity entity) { + if (entity == null) return; + if (this.entity == null) this.entity = new CompoundTag(); + entity.save(this.entity); + this.entity.remove(Entity.UUID_TAG); + } + + /** + * 设置实体 + */ + public void setEntity(CompoundTag entity) { + if (entity == null) return; + this.entity = entity; + this.entity.remove(Entity.UUID_TAG); + } + + @Override + protected void saveAdditional(@NotNull CompoundTag tag) { + super.saveAdditional(tag); + if (this.entity != null) { + tag.put("entity", this.entity); + } + } + + @Override + public void load(@NotNull CompoundTag tag) { + if (tag.contains("entity")) { + this.entity = tag.getCompound("entity"); + if (this.level != null) { + this.getEntity(this.level); + } + } + super.load(tag); + } + + @Override + public @NotNull CompoundTag getUpdateTag() { + return this.saveWithoutMetadata(); + } + + @Nullable + @Override + public Packet getUpdatePacket() { + return ClientboundBlockEntityDataPacket.create(this); + } + + /** + * @return 实体 + */ + @Nullable + public Entity getOrCreateDisplayEntity(Level level) { + if (this.displayEntity == null && this.entity != null) { + this.getEntity(level); + } + return this.displayEntity; + } + + private void getEntity(Level level) { + Optional> optional = EntityType.by(this.entity); + if (optional.isEmpty()) return; + EntityType type = optional.get(); + Entity entity = type.create(level); + if (entity == null) return; + entity.load(this.entity); + this.displayEntity = entity; + } +} diff --git a/common/src/main/java/dev/dubhe/anvilcraft/block/entity/MobAmberBlockEntity.java b/common/src/main/java/dev/dubhe/anvilcraft/block/entity/MobAmberBlockEntity.java new file mode 100644 index 000000000..c4836b1ac --- /dev/null +++ b/common/src/main/java/dev/dubhe/anvilcraft/block/entity/MobAmberBlockEntity.java @@ -0,0 +1,18 @@ +package dev.dubhe.anvilcraft.block.entity; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import org.jetbrains.annotations.NotNull; + +public class MobAmberBlockEntity extends HasMobBlockEntity { + protected MobAmberBlockEntity(BlockEntityType type, BlockPos pos, BlockState blockState) { + super(type, pos, blockState); + } + + public static @NotNull MobAmberBlockEntity createBlockEntity( + BlockEntityType type, BlockPos pos, BlockState blockState + ) { + return new MobAmberBlockEntity(type, pos, blockState); + } +} diff --git a/common/src/main/java/dev/dubhe/anvilcraft/block/entity/ResentfulAmberBlock.java b/common/src/main/java/dev/dubhe/anvilcraft/block/entity/ResentfulAmberBlock.java new file mode 100644 index 000000000..be638ca0a --- /dev/null +++ b/common/src/main/java/dev/dubhe/anvilcraft/block/entity/ResentfulAmberBlock.java @@ -0,0 +1,18 @@ +package dev.dubhe.anvilcraft.block.entity; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import org.jetbrains.annotations.NotNull; + +public class ResentfulAmberBlock extends MobAmberBlockEntity { + private ResentfulAmberBlock(BlockEntityType type, BlockPos pos, BlockState blockState) { + super(type, pos, blockState); + } + + public static @NotNull ResentfulAmberBlock createBlockEntity( + BlockEntityType type, BlockPos pos, BlockState blockState + ) { + return new ResentfulAmberBlock(type, pos, blockState); + } +} diff --git a/common/src/main/java/dev/dubhe/anvilcraft/block/entity/SimpleChuteBlockEntity.java b/common/src/main/java/dev/dubhe/anvilcraft/block/entity/SimpleChuteBlockEntity.java index 5a14c9e65..62d0e5118 100644 --- a/common/src/main/java/dev/dubhe/anvilcraft/block/entity/SimpleChuteBlockEntity.java +++ b/common/src/main/java/dev/dubhe/anvilcraft/block/entity/SimpleChuteBlockEntity.java @@ -2,6 +2,7 @@ import dev.architectury.injectables.annotations.ExpectPlatform; import dev.dubhe.anvilcraft.AnvilCraft; +import dev.dubhe.anvilcraft.api.depository.IItemDepository; import dev.dubhe.anvilcraft.api.depository.ItemDepository; import dev.dubhe.anvilcraft.api.depository.ItemDepositoryHelper; import dev.dubhe.anvilcraft.block.SimpleChuteBlock; @@ -65,26 +66,28 @@ public void load(@NotNull CompoundTag tag) { public void tick() { if (cooldown <= 0) { if (getBlockState().getValue(SimpleChuteBlock.ENABLED)) { - if (ItemDepositoryHelper.getItemDepository(getLevel(), - getBlockPos().relative(getDirection()), getDirection().getOpposite()) != null) { + IItemDepository depository = ItemDepositoryHelper.getItemDepository( + getLevel(), + getBlockPos().relative(getDirection()), + getDirection().getOpposite() + ); + if (depository != null) { // 尝试向朝向容器输出 - if (!depository.isEmpty()) { - ItemDepositoryHelper.exportToTarget(depository, - 64, stack -> true, getLevel(), - getBlockPos().relative(getDirection()), getDirection().getOpposite()); + if (!this.depository.isEmpty()) { + ItemDepositoryHelper.exportToTarget(this.depository, 64, stack -> true, depository); } } else { Vec3 center = getBlockPos().relative(getDirection()).getCenter(); AABB aabb = new AABB(center.add(-0.125, -0.125, -0.125), center.add(0.125, 0.125, 0.125)); if (getLevel().noCollision(aabb)) { - for (int i = 0; i < depository.getSlots(); i++) { - ItemStack stack = depository.getStack(i); + for (int i = 0; i < this.depository.getSlots(); i++) { + ItemStack stack = this.depository.getStack(i); if (!stack.isEmpty()) { ItemEntity itemEntity = new ItemEntity(getLevel(), center.x, center.y, center.z, stack, 0, 0, 0); itemEntity.setDefaultPickUpDelay(); getLevel().addFreshEntity(itemEntity); - depository.setStack(i, ItemStack.EMPTY); + this.depository.setStack(i, ItemStack.EMPTY); break; } } diff --git a/common/src/main/java/dev/dubhe/anvilcraft/client/renderer/blockentity/HasMobBlockRenderer.java b/common/src/main/java/dev/dubhe/anvilcraft/client/renderer/blockentity/HasMobBlockRenderer.java new file mode 100644 index 000000000..fb696d463 --- /dev/null +++ b/common/src/main/java/dev/dubhe/anvilcraft/client/renderer/blockentity/HasMobBlockRenderer.java @@ -0,0 +1,39 @@ +package dev.dubhe.anvilcraft.client.renderer.blockentity; + +import com.mojang.blaze3d.vertex.PoseStack; +import dev.dubhe.anvilcraft.block.entity.HasMobBlockEntity; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.blockentity.BlockEntityRenderer; +import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; +import net.minecraft.client.renderer.entity.EntityRenderDispatcher; +import net.minecraft.world.entity.Entity; +import org.jetbrains.annotations.NotNull; + +public class HasMobBlockRenderer implements BlockEntityRenderer { + @SuppressWarnings("unused") + public HasMobBlockRenderer(BlockEntityRendererProvider.Context context) { + } + + @Override + public void render( + @NotNull HasMobBlockEntity blockEntity, float partialTick, @NotNull PoseStack poseStack, + @NotNull MultiBufferSource buffer, int packedLight, int packedOverlay + ) { + Entity entity = blockEntity.getOrCreateDisplayEntity(blockEntity.getLevel()); + if (entity == null) return; + poseStack.pushPose(); + poseStack.translate(0.5f, 0.0f, 0.5f); + float size = 0.73125f; + float max = Math.max(entity.getBbWidth(), entity.getBbHeight()); + if ((double) max > 1.0) { + size /= max; + } + poseStack.translate(0.0f, 0.14f, 0.0f); + poseStack.scale(size, size, size); + Minecraft minecraft = Minecraft.getInstance(); + EntityRenderDispatcher dispatcher = minecraft.getEntityRenderDispatcher(); + dispatcher.render(entity, 0, 0, 0, 0, 0, poseStack, buffer, packedLight); + poseStack.popPose(); + } +} diff --git a/common/src/main/java/dev/dubhe/anvilcraft/data/generator/lang/OtherLang.java b/common/src/main/java/dev/dubhe/anvilcraft/data/generator/lang/OtherLang.java index f30f90df1..60c197ab3 100644 --- a/common/src/main/java/dev/dubhe/anvilcraft/data/generator/lang/OtherLang.java +++ b/common/src/main/java/dev/dubhe/anvilcraft/data/generator/lang/OtherLang.java @@ -32,10 +32,5 @@ public static void init(@NotNull RegistrateLangProvider provider) { "entity.minecraft.villager.jeweler", "Jeweler" ); - - provider.add( - "block.anvilcraft.resin_block.has_mob", - "Contains %s Resin Block" - ); } } diff --git a/common/src/main/java/dev/dubhe/anvilcraft/data/generator/recipe/TimeWarpRecipesLoader.java b/common/src/main/java/dev/dubhe/anvilcraft/data/generator/recipe/TimeWarpRecipesLoader.java index 17cd62f15..db24925d3 100644 --- a/common/src/main/java/dev/dubhe/anvilcraft/data/generator/recipe/TimeWarpRecipesLoader.java +++ b/common/src/main/java/dev/dubhe/anvilcraft/data/generator/recipe/TimeWarpRecipesLoader.java @@ -25,7 +25,6 @@ public class TimeWarpRecipesLoader { public static void init(RegistrateRecipeProvider provider) { timeWarpWithWater(ModItems.SEA_HEART_SHELL_SHARD, ModItems.SEA_HEART_SHELL, provider); timeWarp(ModItems.RESIN, ModItems.AMBER, 1, provider); - timeWarp(ModBlocks.RESIN_BLOCK, ModBlocks.AMBER_BLOCK.asItem(), 1, provider); timeWarp(Items.OBSIDIAN, Items.CRYING_OBSIDIAN, 1, provider); timeWarp(Items.CHARCOAL, Items.COAL, 1, provider); timeWarp(Items.SAND, Items.DIRT, 1, provider); diff --git a/common/src/main/java/dev/dubhe/anvilcraft/data/recipe/anvil/AnvilRecipe.java b/common/src/main/java/dev/dubhe/anvilcraft/data/recipe/anvil/AnvilRecipe.java index 7f804e195..dcdc98842 100644 --- a/common/src/main/java/dev/dubhe/anvilcraft/data/recipe/anvil/AnvilRecipe.java +++ b/common/src/main/java/dev/dubhe/anvilcraft/data/recipe/anvil/AnvilRecipe.java @@ -30,6 +30,7 @@ import net.minecraft.data.recipes.FinishedRecipe; import net.minecraft.data.recipes.RecipeBuilder; import net.minecraft.data.recipes.RecipeCategory; +import net.minecraft.nbt.CompoundTag; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.resources.ResourceLocation; import net.minecraft.tags.TagKey; @@ -51,6 +52,7 @@ import java.util.ArrayList; import java.util.Arrays; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.function.Consumer; @@ -63,6 +65,7 @@ public class AnvilRecipe implements Recipe { @Getter private final List outcomes = new ArrayList<>(); private final ItemStack icon; + private final Map data = new HashMap<>(); public AnvilRecipe(ResourceLocation id, ItemStack icon) { this.id = id; @@ -97,8 +100,19 @@ public boolean matches(@NotNull AnvilCraftingContainer container, @NotNull Level */ public boolean craft(@NotNull AnvilCraftingContainer container) { if (!this.matches(container, container.getLevel())) return false; - for (RecipePredicate predicate : this.predicates) predicate.process(container); - for (RecipeOutcome outcome : this.outcomes) outcome.process(container); + for (RecipePredicate predicate : this.predicates) { + predicate.process(container); + if (predicate instanceof HasData hasData) { + Map.Entry entry = hasData.getData(); + if (entry != null) this.data.put(entry.getKey(), entry.getValue()); + } + } + for (RecipeOutcome outcome : this.outcomes) { + if (outcome instanceof CanSetData canSetData) { + canSetData.setData(this.data); + } + outcome.process(container); + } return true; } diff --git a/common/src/main/java/dev/dubhe/anvilcraft/data/recipe/anvil/CanSetData.java b/common/src/main/java/dev/dubhe/anvilcraft/data/recipe/anvil/CanSetData.java new file mode 100644 index 000000000..e0c0101a6 --- /dev/null +++ b/common/src/main/java/dev/dubhe/anvilcraft/data/recipe/anvil/CanSetData.java @@ -0,0 +1,12 @@ +package dev.dubhe.anvilcraft.data.recipe.anvil; + +import net.minecraft.nbt.CompoundTag; + +import java.util.Map; + +/** + * 可以设置数据 + */ +public interface CanSetData { + void setData(Map data); +} diff --git a/common/src/main/java/dev/dubhe/anvilcraft/data/recipe/anvil/HasData.java b/common/src/main/java/dev/dubhe/anvilcraft/data/recipe/anvil/HasData.java new file mode 100644 index 000000000..9a983ea1c --- /dev/null +++ b/common/src/main/java/dev/dubhe/anvilcraft/data/recipe/anvil/HasData.java @@ -0,0 +1,12 @@ +package dev.dubhe.anvilcraft.data.recipe.anvil; + +import net.minecraft.nbt.CompoundTag; + +import java.util.Map; + +/** + * 包含数据 + */ +public interface HasData { + Map.Entry getData(); +} diff --git a/common/src/main/java/dev/dubhe/anvilcraft/data/recipe/anvil/outcome/SelectOne.java b/common/src/main/java/dev/dubhe/anvilcraft/data/recipe/anvil/outcome/SelectOne.java index a1020158a..9f0686260 100644 --- a/common/src/main/java/dev/dubhe/anvilcraft/data/recipe/anvil/outcome/SelectOne.java +++ b/common/src/main/java/dev/dubhe/anvilcraft/data/recipe/anvil/outcome/SelectOne.java @@ -4,8 +4,11 @@ import com.google.gson.JsonElement; import com.google.gson.JsonObject; import dev.dubhe.anvilcraft.data.recipe.anvil.AnvilCraftingContainer; +import dev.dubhe.anvilcraft.data.recipe.anvil.CanSetData; import dev.dubhe.anvilcraft.data.recipe.anvil.RecipeOutcome; import lombok.Getter; +import lombok.Setter; +import net.minecraft.nbt.CompoundTag; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.util.GsonHelper; import net.minecraft.util.RandomSource; @@ -13,13 +16,17 @@ import org.jetbrains.annotations.Nullable; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; @Getter -public class SelectOne implements RecipeOutcome { +public class SelectOne implements RecipeOutcome, CanSetData { private final String type = "select_one"; private final double chance; private final List outcomes = new ArrayList<>(); + @Setter + private Map data = new HashMap<>(); public SelectOne add(RecipeOutcome outcome) { this.outcomes.add(outcome); @@ -63,6 +70,9 @@ public boolean process(@NotNull AnvilCraftingContainer container) { if (random.nextDouble() > this.chance) return true; List weights = this.outcomes.stream().map(RecipeOutcome::getChance).toList(); RecipeOutcome outcome = SelectOne.weightedRandomSelect(this.outcomes, weights, random); + if (outcome instanceof CanSetData canSetData) { + canSetData.setData(this.data); + } if (outcome != null) outcome.process(container); return true; } diff --git a/common/src/main/java/dev/dubhe/anvilcraft/data/recipe/anvil/outcome/SpawnItem.java b/common/src/main/java/dev/dubhe/anvilcraft/data/recipe/anvil/outcome/SpawnItem.java index ff771e1a8..06de803f3 100644 --- a/common/src/main/java/dev/dubhe/anvilcraft/data/recipe/anvil/outcome/SpawnItem.java +++ b/common/src/main/java/dev/dubhe/anvilcraft/data/recipe/anvil/outcome/SpawnItem.java @@ -6,10 +6,13 @@ import com.google.gson.JsonPrimitive; import com.google.gson.JsonSyntaxException; import dev.dubhe.anvilcraft.data.recipe.anvil.AnvilCraftingContainer; +import dev.dubhe.anvilcraft.data.recipe.anvil.CanSetData; import dev.dubhe.anvilcraft.data.recipe.anvil.RecipeOutcome; import dev.dubhe.anvilcraft.util.IItemStackUtil; import lombok.Getter; +import lombok.Setter; import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.util.GsonHelper; import net.minecraft.util.RandomSource; @@ -19,12 +22,22 @@ import net.minecraft.world.phys.Vec3; import org.jetbrains.annotations.NotNull; +import java.util.Map; + @Getter -public class SpawnItem implements RecipeOutcome { +public class SpawnItem implements RecipeOutcome, CanSetData { private final String type = "spawn_item"; private final Vec3 offset; private final double chance; private final ItemStack result; + private String path = null; + @Setter + private Map data = null; + + public SpawnItem loadItemData(String path) { + this.path = path; + return this; + } /** * 产生物品 @@ -45,6 +58,9 @@ public SpawnItem(Vec3 offset, double chance, ItemStack result) { public SpawnItem(@NotNull FriendlyByteBuf buffer) { this.offset = new Vec3(buffer.readVector3f()); this.chance = buffer.readDouble(); + if (buffer.readBoolean()) { + this.path = buffer.readUtf(); + } this.result = buffer.readItem(); } @@ -67,6 +83,9 @@ public SpawnItem(@NotNull JsonObject serializedRecipe) { if (serializedRecipe.has("chance")) { this.chance = GsonHelper.getAsDouble(serializedRecipe, "chance"); } else this.chance = 1.0; + if (serializedRecipe.has("data_path")) { + this.path = GsonHelper.getAsString(serializedRecipe, "data_path"); + } this.result = IItemStackUtil.fromJson(GsonHelper.getAsJsonObject(serializedRecipe, "result")); } @@ -77,7 +96,11 @@ public boolean process(@NotNull AnvilCraftingContainer container) { if (random.nextDouble() > this.chance) return true; BlockPos pos = container.getPos(); Vec3 vec3 = pos.getCenter().add(this.offset); - ItemEntity entity = new ItemEntity(level, vec3.x, vec3.y, vec3.z, this.result.copy(), 0.0d, 0.0d, 0.0d); + ItemStack stack = this.result.copy(); + if (this.path != null && this.data != null && this.data.containsKey(this.path)) { + stack.setTag(this.data.get(this.path)); + } + ItemEntity entity = new ItemEntity(level, vec3.x, vec3.y, vec3.z, stack, 0.0d, 0.0d, 0.0d); return level.addFreshEntity(entity); } @@ -86,6 +109,10 @@ public void toNetwork(@NotNull FriendlyByteBuf buffer) { buffer.writeUtf(this.getType()); buffer.writeVector3f(this.offset.toVector3f()); buffer.writeDouble(this.chance); + buffer.writeBoolean(this.path == null); + if (this.path != null) { + buffer.writeUtf(this.path); + } buffer.writeItem(this.result); } @@ -99,6 +126,7 @@ public JsonElement toJson() { object.add("offset", offset); object.addProperty("chance", this.chance); object.add("result", IItemStackUtil.toJson(this.result)); + if (this.path != null) object.addProperty("data_path", this.path); return object; } } diff --git a/common/src/main/java/dev/dubhe/anvilcraft/data/recipe/anvil/predicate/HasItem.java b/common/src/main/java/dev/dubhe/anvilcraft/data/recipe/anvil/predicate/HasItem.java index 5fa993865..96a1a98a9 100644 --- a/common/src/main/java/dev/dubhe/anvilcraft/data/recipe/anvil/predicate/HasItem.java +++ b/common/src/main/java/dev/dubhe/anvilcraft/data/recipe/anvil/predicate/HasItem.java @@ -8,10 +8,12 @@ import com.google.gson.JsonSyntaxException; import dev.dubhe.anvilcraft.AnvilCraft; import dev.dubhe.anvilcraft.data.recipe.anvil.AnvilCraftingContainer; +import dev.dubhe.anvilcraft.data.recipe.anvil.HasData; import dev.dubhe.anvilcraft.data.recipe.anvil.RecipePredicate; import lombok.Getter; import net.minecraft.advancements.critereon.ItemPredicate; import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.util.GsonHelper; import net.minecraft.world.entity.item.ItemEntity; @@ -22,19 +24,41 @@ import net.minecraft.world.phys.Vec3; import org.jetbrains.annotations.NotNull; +import java.util.ArrayList; import java.util.List; +import java.util.Map; -public class HasItem implements RecipePredicate { +public class HasItem implements RecipePredicate, HasData { @Getter private final String type = "has_item"; protected final Vec3 offset; protected final ItemPredicate matchItem; + protected String path = null; + @Getter + protected Map.Entry data = null; + protected final List hasTag = new ArrayList<>(); + protected final List notHasTag = new ArrayList<>(); public HasItem(Vec3 offset, ItemPredicate matchItem) { this.offset = offset; this.matchItem = matchItem; } + public HasItem saveItemData(String path) { + this.path = path; + return this; + } + + public HasItem hasTag(String path) { + this.hasTag.add(path); + return this; + } + + public HasItem notHasTag(String path) { + this.notHasTag.add(path); + return this; + } + /** * 拥有物品 * @@ -50,12 +74,35 @@ public HasItem(JsonObject serializedRecipe) { } else throw new JsonSyntaxException("Expected offset to be a Double, was " + GsonHelper.getType(element)); } this.offset = new Vec3(vec3[0], vec3[1], vec3[2]); + if (serializedRecipe.has("data_path")) { + this.path = GsonHelper.getAsString(serializedRecipe, "data_path"); + } if (!serializedRecipe.has("match_item")) throw new JsonSyntaxException("Missing match_item"); + if (serializedRecipe.has("has_tag")) { + JsonArray array1 = GsonHelper.getAsJsonArray(serializedRecipe, "has_tag"); + array1.forEach(element -> this.hasTag.add(element.getAsString())); + } + if (serializedRecipe.has("not_has_tag")) { + JsonArray array1 = GsonHelper.getAsJsonArray(serializedRecipe, "not_has_tag"); + array1.forEach(element -> this.notHasTag.add(element.getAsString())); + } this.matchItem = ItemPredicate.fromJson(serializedRecipe.get("match_item")); } + /** + * @param buffer 缓冲区 + */ public HasItem(@NotNull FriendlyByteBuf buffer) { this.offset = new Vec3(buffer.readVector3f()); + if (buffer.readBoolean()) { + this.path = buffer.readUtf(); + } + for (int i = 0; i < buffer.readVarInt(); i++) { + this.hasTag.add(buffer.readUtf()); + } + for (int i = 0; i < buffer.readVarInt(); i++) { + this.notHasTag.add(buffer.readUtf()); + } this.matchItem = ItemPredicate.fromJson(AnvilCraft.GSON.fromJson(buffer.readUtf(), JsonElement.class)); } @@ -66,9 +113,35 @@ public boolean matches(@NotNull AnvilCraftingContainer container) { AABB aabb = new AABB(pos).move(this.offset); List entities = level.getEntities(EntityTypeTest.forClass(ItemEntity.class), aabb, Predicates.alwaysTrue()); + entities: for (ItemEntity entity : entities) { ItemStack item = entity.getItem(); - if (this.matchItem.matches(item)) return true; + if (this.matchItem.matches(item)) { + for (String path : this.hasTag) { + if (!item.hasTag()) continue; + CompoundTag tag = item.getOrCreateTag(); + String[] paths = path.split("\\."); + for (int i = 0; i < paths.length; i++) { + if (!tag.contains(paths[i])) continue entities; + if (i != paths.length - 1) { + tag = tag.getCompound(paths[i]); + } + } + } + for (String path : this.notHasTag) { + CompoundTag tag = item.getOrCreateTag(); + String[] paths = path.split("\\."); + for (int i = 0; i < paths.length; i++) { + if (i != paths.length - 1) { + tag = tag.getCompound(paths[i]); + } else if (tag.contains(paths[i])) continue entities; + } + } + if (this.path != null) { + this.data = Map.entry(this.path, item.hasTag() ? item.getOrCreateTag() : new CompoundTag()); + } + return true; + } } return false; } @@ -82,6 +155,14 @@ public boolean process(AnvilCraftingContainer container) { public void toNetwork(@NotNull FriendlyByteBuf buffer) { buffer.writeUtf(this.getType()); buffer.writeVector3f(this.offset.toVector3f()); + buffer.writeBoolean(this.path == null); + if (this.path != null) { + buffer.writeUtf(this.path); + } + buffer.writeVarInt(this.hasTag.size()); + this.hasTag.forEach(buffer::writeUtf); + buffer.writeVarInt(this.notHasTag.size()); + this.notHasTag.forEach(buffer::writeUtf); buffer.writeUtf(this.matchItem.serializeToJson().toString()); } @@ -92,11 +173,18 @@ public void toNetwork(@NotNull FriendlyByteBuf buffer) { for (double v : vec3) { offset.add(new JsonPrimitive(v)); } - JsonElement matchItem = this.matchItem.serializeToJson(); JsonObject object = new JsonObject(); object.addProperty("type", this.getType()); object.add("offset", offset); + if (this.path != null) object.addProperty("data_path", this.path); + JsonElement matchItem = this.matchItem.serializeToJson(); object.add("match_item", matchItem); + JsonArray hasTag = new JsonArray(); + this.hasTag.forEach(hasTag::add); + if (!hasTag.isEmpty()) object.add("has_tag", hasTag); + JsonArray notHasTag = new JsonArray(); + this.notHasTag.forEach(notHasTag::add); + if (!notHasTag.isEmpty()) object.add("not_has_tag", notHasTag); return object; } } diff --git a/common/src/main/java/dev/dubhe/anvilcraft/init/ModBlockEntities.java b/common/src/main/java/dev/dubhe/anvilcraft/init/ModBlockEntities.java index 2ead2b990..f802a0805 100644 --- a/common/src/main/java/dev/dubhe/anvilcraft/init/ModBlockEntities.java +++ b/common/src/main/java/dev/dubhe/anvilcraft/init/ModBlockEntities.java @@ -8,9 +8,12 @@ import dev.dubhe.anvilcraft.block.entity.CrabTrapBlockEntity; import dev.dubhe.anvilcraft.block.entity.CreativeGeneratorBlockEntity; import dev.dubhe.anvilcraft.block.entity.HeaterBlockEntity; +import dev.dubhe.anvilcraft.block.entity.MobAmberBlockEntity; +import dev.dubhe.anvilcraft.block.entity.ResentfulAmberBlock; import dev.dubhe.anvilcraft.block.entity.SimpleChuteBlockEntity; import dev.dubhe.anvilcraft.block.entity.TransmissionPoleBlockEntity; import dev.dubhe.anvilcraft.client.renderer.blockentity.CorruptedBeaconRenderer; +import dev.dubhe.anvilcraft.client.renderer.blockentity.HasMobBlockRenderer; import static dev.dubhe.anvilcraft.AnvilCraft.REGISTRATE; @@ -65,6 +68,18 @@ public class ModBlockEntities { .validBlock(ModBlocks.CHARGE_COLLECTOR) .register(); + public static final BlockEntityEntry MOB_AMBER_BLOCK = REGISTRATE + .blockEntity("mob_amber_block", MobAmberBlockEntity::createBlockEntity) + .renderer(() -> HasMobBlockRenderer::new) + .validBlock(ModBlocks.MOB_AMBER_BLOCK) + .register(); + + public static final BlockEntityEntry RESENTFUL_AMBER_BLOCK = REGISTRATE + .blockEntity("resentful_amber_block", ResentfulAmberBlock::createBlockEntity) + .renderer(() -> HasMobBlockRenderer::new) + .validBlock(ModBlocks.RESENTFUL_AMBER_BLOCK) + .register(); + public static void register() { } } diff --git a/common/src/main/java/dev/dubhe/anvilcraft/init/ModBlocks.java b/common/src/main/java/dev/dubhe/anvilcraft/init/ModBlocks.java index 4f9c703c8..a1a921024 100644 --- a/common/src/main/java/dev/dubhe/anvilcraft/init/ModBlocks.java +++ b/common/src/main/java/dev/dubhe/anvilcraft/init/ModBlocks.java @@ -17,7 +17,9 @@ import dev.dubhe.anvilcraft.block.LavaCauldronBlock; import dev.dubhe.anvilcraft.block.MagnetBlock; import dev.dubhe.anvilcraft.block.MeltGemCauldron; +import dev.dubhe.anvilcraft.block.MobAmberBlock; import dev.dubhe.anvilcraft.block.PiezoelectricCrystalBlock; +import dev.dubhe.anvilcraft.block.ResentfulAmberBlock; import dev.dubhe.anvilcraft.block.ResinBlock; import dev.dubhe.anvilcraft.block.RoyalAnvilBlock; import dev.dubhe.anvilcraft.block.RoyalGrindstone; @@ -29,13 +31,23 @@ import dev.dubhe.anvilcraft.data.generator.AnvilCraftDatagen; import dev.dubhe.anvilcraft.data.generator.recipe.SmashBlockRecipesLoader; import dev.dubhe.anvilcraft.data.recipe.anvil.AnvilRecipe; +import dev.dubhe.anvilcraft.data.recipe.anvil.RecipeOutcome; +import dev.dubhe.anvilcraft.data.recipe.anvil.RecipePredicate; +import dev.dubhe.anvilcraft.data.recipe.anvil.outcome.SelectOne; +import dev.dubhe.anvilcraft.data.recipe.anvil.outcome.SpawnItem; +import dev.dubhe.anvilcraft.data.recipe.anvil.predicate.HasItem; +import dev.dubhe.anvilcraft.data.recipe.anvil.predicate.HasItemIngredient; import dev.dubhe.anvilcraft.item.CursedBlockItem; +import dev.dubhe.anvilcraft.item.HasMobBlockItem; import dev.dubhe.anvilcraft.item.PlaceInWaterBlockItem; import dev.dubhe.anvilcraft.item.ResinBlockItem; import dev.dubhe.anvilcraft.item.TransmissionPoleBlockItem; +import net.minecraft.advancements.critereon.ItemPredicate; +import net.minecraft.advancements.critereon.MinMaxBounds; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.data.recipes.RecipeCategory; import net.minecraft.data.recipes.ShapedRecipeBuilder; +import net.minecraft.nbt.CompoundTag; import net.minecraft.tags.BlockTags; import net.minecraft.tags.ItemTags; import net.minecraft.world.item.BlockItem; @@ -431,6 +443,7 @@ public class ModBlocks { AnvilCraftDatagen.has(ModItems.RESIN)) .save(provider)) .register(); + public static final BlockEntry AMBER_BLOCK = REGISTRATE .block("amber_block", HalfTransparentBlock::new) .initialProperties(() -> Blocks.EMERALD_BLOCK) @@ -440,14 +453,129 @@ public class ModBlocks { .simpleItem() .defaultLoot() .tag(BlockTags.MINEABLE_WITH_PICKAXE) - .recipe((ctx, provider) -> ShapedRecipeBuilder.shaped(RecipeCategory.MISC, ctx.get()) - .pattern("AAA") - .pattern("AAA") - .pattern("AAA") - .define('A', ModItems.AMBER) - .unlockedBy(AnvilCraftDatagen.hasItem(ModItems.AMBER), AnvilCraftDatagen.has(ModItems.AMBER)) - .save(provider)) + .recipe((ctx, provider) -> { + ShapedRecipeBuilder.shaped(RecipeCategory.MISC, ctx.get()) + .pattern("AAA") + .pattern("AAA") + .pattern("AAA") + .define('A', ModItems.AMBER) + .unlockedBy(AnvilCraftDatagen.hasItem(ModItems.AMBER), AnvilCraftDatagen.has(ModItems.AMBER)) + .save(provider); + ItemPredicate.Builder item = ItemPredicate.Builder + .item() + .of(ModBlocks.RESIN_BLOCK) + .withCount(MinMaxBounds.Ints.atLeast(1)); + HasItem hasItem = new HasItemIngredient(new Vec3(0.0, -1.0, 0.0), item.build()).notHasTag("entity"); + AnvilRecipe.Builder.create(RecipeCategory.MISC) + .icon(ctx.get()) + .hasBlock( + ModBlocks.CORRUPTED_BEACON.get(), + new Vec3(0.0, -2.0, 0.0), + Map.entry(CorruptedBeaconBlock.LIT, true) + ) + .hasBlock(Blocks.CAULDRON) + .addPredicates(hasItem) + .spawnItem(new Vec3(0.0, -1.0, 0.0), ctx.get(), 1) + .unlockedBy(AnvilCraftDatagen.hasItem(ctx.get()), AnvilCraftDatagen.has(ModBlocks.RESIN_BLOCK)) + .save( + provider, + AnvilCraft.of("timewarp/" + BuiltInRegistries.ITEM.getKey(ctx.get().asItem()).getPath()) + ); + }) + .register(); + + public static final BlockEntry MOB_AMBER_BLOCK = REGISTRATE + .block("mob_amber_block", MobAmberBlock::new) + .blockstate((ctx, provider) -> { + }) + .item(HasMobBlockItem::new) + .recipe((ctx, provider) -> { + CompoundTag tag = new CompoundTag(); + tag.putBoolean("is_monster", false); + ItemPredicate.Builder item = ItemPredicate.Builder + .item() + .of(ModBlocks.RESIN_BLOCK) + .withCount(MinMaxBounds.Ints.atLeast(1)) + .hasNbt(tag); + tag.putBoolean("is_monster", true); + ItemPredicate.Builder monster = ItemPredicate.Builder + .item() + .of(ModBlocks.RESIN_BLOCK) + .withCount(MinMaxBounds.Ints.atLeast(1)) + .hasNbt(tag); + RecipePredicate hasItem = new HasItemIngredient(new Vec3(0.0, -1.0, 0.0), item.build()) + .hasTag("entity") + .saveItemData("resin"); + RecipePredicate hasItemMonster = new HasItemIngredient(new Vec3(0.0, -1.0, 0.0), monster.build()) + .hasTag("entity") + .saveItemData("resin"); + RecipeOutcome spawnItem0 = new SpawnItem( + new Vec3(0.0, -1.0, 0.0), + 1.0, + ctx.get().getDefaultInstance() + ).loadItemData("resin"); + RecipeOutcome spawnItem1 = new SpawnItem( + new Vec3(0.0, -1.0, 0.0), + 0.95, + ctx.get().getDefaultInstance() + ).loadItemData("resin"); + RecipeOutcome spawnItem2 = new SpawnItem( + new Vec3(0.0, -1.0, 0.0), + 0.05, + ModBlocks.RESENTFUL_AMBER_BLOCK.asItem().getDefaultInstance() + ).loadItemData("resin"); + AnvilRecipe.Builder.create(RecipeCategory.MISC) + .icon(ctx.get()) + .hasBlock( + ModBlocks.CORRUPTED_BEACON.get(), + new Vec3(0.0, -2.0, 0.0), + Map.entry(CorruptedBeaconBlock.LIT, true) + ) + .hasBlock(Blocks.CAULDRON) + .addPredicates(hasItem) + .addOutcomes(spawnItem0) + .unlockedBy(AnvilCraftDatagen.hasItem(ctx.get()), AnvilCraftDatagen.has(ModBlocks.RESIN_BLOCK)) + .save( + provider, + AnvilCraft.of("timewarp/" + BuiltInRegistries.ITEM.getKey(ctx.get().asItem()).getPath()) + ); + AnvilRecipe.Builder.create(RecipeCategory.MISC) + .icon(ctx.get()) + .hasBlock( + ModBlocks.CORRUPTED_BEACON.get(), + new Vec3(0.0, -2.0, 0.0), + Map.entry(CorruptedBeaconBlock.LIT, true) + ) + .hasBlock(Blocks.CAULDRON) + .addPredicates(hasItemMonster) + .addOutcomes(new SelectOne().add(spawnItem1).add(spawnItem2)) + .unlockedBy(AnvilCraftDatagen.hasItem(ctx.get()), AnvilCraftDatagen.has(ModBlocks.RESIN_BLOCK)) + .save( + provider, + AnvilCraft.of( + "timewarp/" + + BuiltInRegistries.ITEM.getKey(ctx.get().asItem()).getPath() + + "_resentful" + ) + ); + }) + .build() + .initialProperties(ModBlocks.AMBER_BLOCK) + .defaultLoot() + .tag(BlockTags.MINEABLE_WITH_PICKAXE) + .register(); + + public static final BlockEntry RESENTFUL_AMBER_BLOCK = REGISTRATE + .block("resentful_amber_block", ResentfulAmberBlock::new) + .blockstate((ctx, provider) -> { + }) + .item(HasMobBlockItem::new) + .build() + .initialProperties(ModBlocks.AMBER_BLOCK) + .defaultLoot() + .tag(BlockTags.MINEABLE_WITH_PICKAXE) .register(); + public static final BlockEntry CREATIVE_GENERATOR = REGISTRATE .block("creative_generator", CreativeGeneratorBlock::new) .initialProperties(ModBlocks.MAGNET_BLOCK) diff --git a/common/src/main/java/dev/dubhe/anvilcraft/item/AmethystPickaxeItem.java b/common/src/main/java/dev/dubhe/anvilcraft/item/AmethystPickaxeItem.java index eb9c89854..07d7ed77a 100644 --- a/common/src/main/java/dev/dubhe/anvilcraft/item/AmethystPickaxeItem.java +++ b/common/src/main/java/dev/dubhe/anvilcraft/item/AmethystPickaxeItem.java @@ -1,15 +1,35 @@ package dev.dubhe.anvilcraft.item; +import net.minecraft.ChatFormatting; +import net.minecraft.network.chat.Component; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.PickaxeItem; +import net.minecraft.world.item.TooltipFlag; import net.minecraft.world.item.enchantment.Enchantments; +import net.minecraft.world.level.Level; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.List; public class AmethystPickaxeItem extends PickaxeItem { public AmethystPickaxeItem(Properties properties) { super(ModTiers.AMETHYST, 1, -2.8f, properties); } + @Override + public void appendHoverText( + @NotNull ItemStack stack, + @Nullable Level level, + @NotNull List tooltipComponents, + @NotNull TooltipFlag isAdvanced + ) { + super.appendHoverText(stack, level, tooltipComponents, isAdvanced); + tooltipComponents + .add(Component.translatable("item.anvilcraft.amethyst_pickaxe.tooltip") + .withStyle(ChatFormatting.GRAY)); + } + @Override public @NotNull ItemStack getDefaultInstance() { ItemStack stack = super.getDefaultInstance(); diff --git a/common/src/main/java/dev/dubhe/anvilcraft/item/HasMobBlockItem.java b/common/src/main/java/dev/dubhe/anvilcraft/item/HasMobBlockItem.java index 6f86240d1..a8e5c2ce6 100644 --- a/common/src/main/java/dev/dubhe/anvilcraft/item/HasMobBlockItem.java +++ b/common/src/main/java/dev/dubhe/anvilcraft/item/HasMobBlockItem.java @@ -1,15 +1,34 @@ package dev.dubhe.anvilcraft.item; +import dev.dubhe.anvilcraft.block.entity.HasMobBlockEntity; +import net.minecraft.ChatFormatting; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.chat.Component; +import net.minecraft.sounds.SoundSource; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.effect.MobEffectInstance; +import net.minecraft.world.effect.MobEffects; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.Mob; +import net.minecraft.world.entity.monster.Monster; +import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.BlockItem; +import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.TooltipFlag; +import net.minecraft.world.item.context.UseOnContext; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.SoundType; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.List; import java.util.Optional; public class HasMobBlockItem extends BlockItem { @@ -17,11 +36,43 @@ public HasMobBlockItem(Block block, Properties properties) { super(block, properties); } + @Override + public void appendHoverText( + @NotNull ItemStack stack, @Nullable Level level, + @NotNull List tooltipComponents, @NotNull TooltipFlag isAdvanced + ) { + super.appendHoverText(stack, level, tooltipComponents, isAdvanced); + Entity entity = HasMobBlockItem.getMobFromItem(level, stack); + if (entity != null) { + tooltipComponents.add( + Component.literal("- ").append(entity.getDisplayName()).withStyle(ChatFormatting.DARK_GRAY) + ); + } + } + public static boolean hasMob(@NotNull ItemStack stack) { if (!stack.hasTag()) return false; return stack.getOrCreateTag().contains("entity"); } + @Override + public @NotNull InteractionResult useOn(@NotNull UseOnContext context) { + InteractionResult result = super.useOn(context); + Level level = context.getLevel(); + Direction clickedFace = context.getClickedFace(); + BlockPos pos = context.getClickedPos(); + ItemStack item = context.getItemInHand(); + BlockEntity blockEntity = level.getBlockEntity(pos.relative(clickedFace)); + if ( + blockEntity != null + && item.getItem() instanceof HasMobBlockItem + && blockEntity instanceof HasMobBlockEntity entity + ) { + entity.setEntity(HasMobBlockItem.getMobFromItem(level, item)); + } + return result; + } + /** * 获取物品中的实体 */ @@ -37,4 +88,41 @@ public static boolean hasMob(@NotNull ItemStack stack) { entity.load(entityTag); return entity; } + + /** + * 向物品中存入实体 + */ + public static void saveMobInItem( + @NotNull Level level, @NotNull Mob entity, @NotNull Player player, @NotNull ItemStack stack + ) { + stack = stack.split(1); + if (level.isClientSide()) { + Item item = stack.getItem(); + if (item instanceof ResinBlockItem item1) { + BlockPos blockPos = entity.getOnPos(); + BlockState blockState = item1.getBlock().defaultBlockState(); + SoundType soundType = blockState.getSoundType(); + level.playSound( + player, blockPos, item1.getPlaceSound(blockState), SoundSource.BLOCKS, + (soundType.getVolume() + 1.0f) / 2.0f, soundType.getPitch() * 0.8f + ); + } + return; + } + CompoundTag tag = stack.getOrCreateTag(); + if (entity instanceof Monster monster) { + MobEffectInstance instance = monster.getEffect(MobEffects.WEAKNESS); + if (instance == null) return; + tag.putBoolean("is_monster", true); + } else { + tag.putBoolean("is_monster", false); + } + CompoundTag entityTag = new CompoundTag(); + entity.save(entityTag); + entityTag.remove(Entity.UUID_TAG); + tag.put("entity", entityTag); + stack.setTag(tag); + player.getInventory().placeItemBackInInventory(stack); + entity.remove(Entity.RemovalReason.DISCARDED); + } } diff --git a/common/src/main/java/dev/dubhe/anvilcraft/item/ResinBlockItem.java b/common/src/main/java/dev/dubhe/anvilcraft/item/ResinBlockItem.java index 3f5fe119a..01c7feebb 100644 --- a/common/src/main/java/dev/dubhe/anvilcraft/item/ResinBlockItem.java +++ b/common/src/main/java/dev/dubhe/anvilcraft/item/ResinBlockItem.java @@ -1,20 +1,13 @@ package dev.dubhe.anvilcraft.item; import dev.dubhe.anvilcraft.init.ModItems; -import net.minecraft.ChatFormatting; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.MutableComponent; -import net.minecraft.network.chat.Style; import net.minecraft.sounds.SoundSource; import net.minecraft.util.RandomSource; import net.minecraft.world.InteractionResult; -import net.minecraft.world.effect.MobEffectInstance; -import net.minecraft.world.effect.MobEffects; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Mob; -import net.minecraft.world.entity.monster.Monster; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; @@ -80,40 +73,4 @@ private static void spawnMobFromItem(@NotNull Level level, Player player, BlockP ItemStack back = new ItemStack(ModItems.RESIN, random.nextInt(1, 4)); player.getInventory().placeItemBackInInventory(back); } - - private static void saveMobInItem( - @NotNull Level level, @NotNull Mob entity, @NotNull Player player, @NotNull ItemStack stack - ) { - stack = stack.split(1); - if (level.isClientSide()) { - Item item = stack.getItem(); - if (item instanceof ResinBlockItem item1) { - BlockPos blockPos = entity.getOnPos(); - BlockState blockState = item1.getBlock().defaultBlockState(); - SoundType soundType = blockState.getSoundType(); - level.playSound( - player, blockPos, item1.getPlaceSound(blockState), SoundSource.BLOCKS, - (soundType.getVolume() + 1.0f) / 2.0f, soundType.getPitch() * 0.8f - ); - } - return; - } - if (entity instanceof Monster monster) { - MobEffectInstance instance = monster.getEffect(MobEffects.WEAKNESS); - if (instance == null) return; - } - CompoundTag entityTag = new CompoundTag(); - entity.save(entityTag); - entityTag.remove(Entity.UUID_TAG); - MutableComponent name = Component.translatable( - "block.anvilcraft.resin_block.has_mob", - entity.getDisplayName().copy().withStyle(ChatFormatting.DARK_PURPLE) - ).withStyle(ChatFormatting.AQUA).withStyle(Style.EMPTY.withItalic(false)); - stack.setHoverName(name); - CompoundTag tag = stack.getOrCreateTag(); - tag.put("entity", entityTag); - stack.setTag(tag); - player.getInventory().placeItemBackInInventory(stack); - entity.remove(Entity.RemovalReason.DISCARDED); - } } diff --git a/common/src/main/java/dev/dubhe/anvilcraft/item/RoyalPickaxeItem.java b/common/src/main/java/dev/dubhe/anvilcraft/item/RoyalPickaxeItem.java index 1ea86c322..1d26fb01c 100644 --- a/common/src/main/java/dev/dubhe/anvilcraft/item/RoyalPickaxeItem.java +++ b/common/src/main/java/dev/dubhe/anvilcraft/item/RoyalPickaxeItem.java @@ -28,9 +28,6 @@ public void appendHoverText( @NotNull TooltipFlag isAdvanced ) { super.appendHoverText(stack, level, tooltipComponents, isAdvanced); - tooltipComponents - .add(Component.translatable("item.anvilcraft.amethyst_pickaxe.tooltip") - .withStyle(ChatFormatting.GRAY)); tooltipComponents.addAll(this.getDefaultEnchantmentsTooltip()); } diff --git a/common/src/main/resources/assets/anvilcraft/blockstates/mob_amber_block.json b/common/src/main/resources/assets/anvilcraft/blockstates/mob_amber_block.json new file mode 100644 index 000000000..557072bba --- /dev/null +++ b/common/src/main/resources/assets/anvilcraft/blockstates/mob_amber_block.json @@ -0,0 +1,7 @@ +{ + "variants": { + "": { + "model": "anvilcraft:block/mob_amber_block" + } + } +} \ No newline at end of file diff --git a/common/src/main/resources/assets/anvilcraft/blockstates/resentful_amber_block.json b/common/src/main/resources/assets/anvilcraft/blockstates/resentful_amber_block.json new file mode 100644 index 000000000..268da8b56 --- /dev/null +++ b/common/src/main/resources/assets/anvilcraft/blockstates/resentful_amber_block.json @@ -0,0 +1,7 @@ +{ + "variants": { + "": { + "model": "anvilcraft:block/resentful_amber_block" + } + } +} \ No newline at end of file diff --git a/common/src/main/resources/assets/anvilcraft/models/block/mob_amber_block.json b/common/src/main/resources/assets/anvilcraft/models/block/mob_amber_block.json new file mode 100644 index 000000000..bf5d511b2 --- /dev/null +++ b/common/src/main/resources/assets/anvilcraft/models/block/mob_amber_block.json @@ -0,0 +1,7 @@ +{ + "parent": "minecraft:block/cube_all", + "render_type": "minecraft:translucent", + "textures": { + "all": "anvilcraft:block/amber_block" + } +} \ No newline at end of file diff --git a/fabric/src/generated/resources/assets/anvilcraft/lang/en_ud.json b/fabric/src/generated/resources/assets/anvilcraft/lang/en_ud.json index 11ec759bc..a055e5677 100644 --- a/fabric/src/generated/resources/assets/anvilcraft/lang/en_ud.json +++ b/fabric/src/generated/resources/assets/anvilcraft/lang/en_ud.json @@ -19,11 +19,12 @@ "block.anvilcraft.lava_cauldron": "uoɹpןnɐƆ ɐʌɐꞀ", "block.anvilcraft.magnet_block": "ʞɔoןᗺ ʇǝubɐW", "block.anvilcraft.melt_gem_cauldron": "uoɹpןnɐƆ ɯǝ⅁ ʇןǝW", + "block.anvilcraft.mob_amber_block": "ʞɔoןᗺ ɹǝqɯⱯ qoW", "block.anvilcraft.nether_dust": "ʇsnᗡ ɹǝɥʇǝN", "block.anvilcraft.piezoelectric_crystal": "ןɐʇsʎɹƆ ɔıɹʇɔǝןǝozǝıԀ", "block.anvilcraft.quartz_sand": "puɐS zʇɹɐnὉ", + "block.anvilcraft.resentful_amber_block": "ʞɔoןᗺ ɹǝqɯⱯ ןnɟʇuǝsǝᴚ", "block.anvilcraft.resin_block": "ʞɔoןᗺ uısǝᴚ", - "block.anvilcraft.resin_block.has_mob": "ʞɔoןᗺ uısǝᴚ %s suıɐʇuoƆ", "block.anvilcraft.royal_anvil": "ןıʌuⱯ ןɐʎoᴚ", "block.anvilcraft.royal_grindstone": "ǝuoʇspuıɹ⅁ ןɐʎoᴚ", "block.anvilcraft.royal_smithing_table": "ǝןqɐ⟘ buıɥʇıɯS ןɐʎoᴚ", diff --git a/fabric/src/generated/resources/assets/anvilcraft/lang/en_us.json b/fabric/src/generated/resources/assets/anvilcraft/lang/en_us.json index 18e759f6e..c34c5144a 100644 --- a/fabric/src/generated/resources/assets/anvilcraft/lang/en_us.json +++ b/fabric/src/generated/resources/assets/anvilcraft/lang/en_us.json @@ -19,11 +19,12 @@ "block.anvilcraft.lava_cauldron": "Lava Cauldron", "block.anvilcraft.magnet_block": "Magnet Block", "block.anvilcraft.melt_gem_cauldron": "Melt Gem Cauldron", + "block.anvilcraft.mob_amber_block": "Mob Amber Block", "block.anvilcraft.nether_dust": "Nether Dust", "block.anvilcraft.piezoelectric_crystal": "Piezoelectric Crystal", "block.anvilcraft.quartz_sand": "Quartz Sand", + "block.anvilcraft.resentful_amber_block": "Resentful Amber Block", "block.anvilcraft.resin_block": "Resin Block", - "block.anvilcraft.resin_block.has_mob": "Contains %s Resin Block", "block.anvilcraft.royal_anvil": "Royal Anvil", "block.anvilcraft.royal_grindstone": "Royal Grindstone", "block.anvilcraft.royal_smithing_table": "Royal Smithing Table", diff --git a/fabric/src/generated/resources/assets/anvilcraft/models/item/mob_amber_block.json b/fabric/src/generated/resources/assets/anvilcraft/models/item/mob_amber_block.json new file mode 100644 index 000000000..71a10ecf5 --- /dev/null +++ b/fabric/src/generated/resources/assets/anvilcraft/models/item/mob_amber_block.json @@ -0,0 +1,3 @@ +{ + "parent": "anvilcraft:block/mob_amber_block" +} \ No newline at end of file diff --git a/fabric/src/generated/resources/assets/anvilcraft/models/item/resentful_amber_block.json b/fabric/src/generated/resources/assets/anvilcraft/models/item/resentful_amber_block.json new file mode 100644 index 000000000..bc7bb0a26 --- /dev/null +++ b/fabric/src/generated/resources/assets/anvilcraft/models/item/resentful_amber_block.json @@ -0,0 +1,3 @@ +{ + "parent": "anvilcraft:block/resentful_amber_block" +} \ No newline at end of file diff --git a/fabric/src/generated/resources/data/anvilcraft/advancements/recipes/misc/timewarp/amber_block.json b/fabric/src/generated/resources/data/anvilcraft/advancements/recipes/misc/timewarp/amber_block.json index a724cbcf2..214f8f0c6 100644 --- a/fabric/src/generated/resources/data/anvilcraft/advancements/recipes/misc/timewarp/amber_block.json +++ b/fabric/src/generated/resources/data/anvilcraft/advancements/recipes/misc/timewarp/amber_block.json @@ -1,7 +1,7 @@ { "parent": "minecraft:recipes/root", "criteria": { - "has_resin_block": { + "has_amber_block": { "conditions": { "items": [ { @@ -22,7 +22,7 @@ }, "requirements": [ [ - "has_resin_block", + "has_amber_block", "has_the_recipe" ] ], diff --git a/fabric/src/generated/resources/data/anvilcraft/advancements/recipes/misc/timewarp/mob_amber_block.json b/fabric/src/generated/resources/data/anvilcraft/advancements/recipes/misc/timewarp/mob_amber_block.json new file mode 100644 index 000000000..1ec5179f6 --- /dev/null +++ b/fabric/src/generated/resources/data/anvilcraft/advancements/recipes/misc/timewarp/mob_amber_block.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_mob_amber_block": { + "conditions": { + "items": [ + { + "items": [ + "anvilcraft:resin_block" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "anvilcraft:timewarp/mob_amber_block" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_mob_amber_block", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "anvilcraft:timewarp/mob_amber_block" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/fabric/src/generated/resources/data/anvilcraft/advancements/recipes/misc/timewarp/mob_amber_block_resentful.json b/fabric/src/generated/resources/data/anvilcraft/advancements/recipes/misc/timewarp/mob_amber_block_resentful.json new file mode 100644 index 000000000..b244e7ecd --- /dev/null +++ b/fabric/src/generated/resources/data/anvilcraft/advancements/recipes/misc/timewarp/mob_amber_block_resentful.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_mob_amber_block": { + "conditions": { + "items": [ + { + "items": [ + "anvilcraft:resin_block" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "anvilcraft:timewarp/mob_amber_block_resentful" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_mob_amber_block", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "anvilcraft:timewarp/mob_amber_block_resentful" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/fabric/src/generated/resources/data/anvilcraft/loot_tables/blocks/mob_amber_block.json b/fabric/src/generated/resources/data/anvilcraft/loot_tables/blocks/mob_amber_block.json new file mode 100644 index 000000000..c7230482b --- /dev/null +++ b/fabric/src/generated/resources/data/anvilcraft/loot_tables/blocks/mob_amber_block.json @@ -0,0 +1,21 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "anvilcraft:mob_amber_block" + } + ], + "rolls": 1.0 + } + ], + "random_sequence": "anvilcraft:blocks/mob_amber_block" +} \ No newline at end of file diff --git a/fabric/src/generated/resources/data/anvilcraft/loot_tables/blocks/resentful_amber_block.json b/fabric/src/generated/resources/data/anvilcraft/loot_tables/blocks/resentful_amber_block.json new file mode 100644 index 000000000..5466245f3 --- /dev/null +++ b/fabric/src/generated/resources/data/anvilcraft/loot_tables/blocks/resentful_amber_block.json @@ -0,0 +1,21 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "anvilcraft:resentful_amber_block" + } + ], + "rolls": 1.0 + } + ], + "random_sequence": "anvilcraft:blocks/resentful_amber_block" +} \ No newline at end of file diff --git a/fabric/src/generated/resources/data/anvilcraft/recipes/timewarp/amber_block.json b/fabric/src/generated/resources/data/anvilcraft/recipes/timewarp/amber_block.json index b82851de6..bfe312012 100644 --- a/fabric/src/generated/resources/data/anvilcraft/recipes/timewarp/amber_block.json +++ b/fabric/src/generated/resources/data/anvilcraft/recipes/timewarp/amber_block.json @@ -57,6 +57,9 @@ "anvilcraft:resin_block" ] }, + "not_has_tag": [ + "entity" + ], "offset": [ 0.0, -1.0, diff --git a/fabric/src/generated/resources/data/anvilcraft/recipes/timewarp/mob_amber_block.json b/fabric/src/generated/resources/data/anvilcraft/recipes/timewarp/mob_amber_block.json new file mode 100644 index 000000000..d6fc953f8 --- /dev/null +++ b/fabric/src/generated/resources/data/anvilcraft/recipes/timewarp/mob_amber_block.json @@ -0,0 +1,73 @@ +{ + "type": "anvilcraft:anvil_processing", + "icon": { + "item": "anvilcraft:mob_amber_block" + }, + "outcomes": [ + { + "type": "spawn_item", + "chance": 1.0, + "data_path": "resin", + "offset": [ + 0.0, + -1.0, + 0.0 + ], + "result": { + "item": "anvilcraft:mob_amber_block" + } + } + ], + "predicates": [ + { + "type": "has_block", + "match_block": { + "blocks": [ + "anvilcraft:corrupted_beacon" + ], + "state": { + "lit": "true" + } + }, + "offset": [ + 0.0, + -2.0, + 0.0 + ] + }, + { + "type": "has_block", + "match_block": { + "blocks": [ + "minecraft:cauldron" + ] + }, + "offset": [ + 0.0, + -1.0, + 0.0 + ] + }, + { + "type": "has_item_ingredient", + "data_path": "resin", + "has_tag": [ + "entity" + ], + "match_item": { + "count": { + "min": 1 + }, + "items": [ + "anvilcraft:resin_block" + ], + "nbt": "{is_monster:1b}" + }, + "offset": [ + 0.0, + -1.0, + 0.0 + ] + } + ] +} \ No newline at end of file diff --git a/fabric/src/generated/resources/data/anvilcraft/recipes/timewarp/mob_amber_block_resentful.json b/fabric/src/generated/resources/data/anvilcraft/recipes/timewarp/mob_amber_block_resentful.json new file mode 100644 index 000000000..20a9be465 --- /dev/null +++ b/fabric/src/generated/resources/data/anvilcraft/recipes/timewarp/mob_amber_block_resentful.json @@ -0,0 +1,92 @@ +{ + "type": "anvilcraft:anvil_processing", + "icon": { + "item": "anvilcraft:mob_amber_block" + }, + "outcomes": [ + { + "type": "select_one", + "chance": 1.0, + "outcomes": [ + { + "type": "spawn_item", + "chance": 0.95, + "data_path": "resin", + "offset": [ + 0.0, + -1.0, + 0.0 + ], + "result": { + "item": "anvilcraft:mob_amber_block" + } + }, + { + "type": "spawn_item", + "chance": 0.05, + "data_path": "resin", + "offset": [ + 0.0, + -1.0, + 0.0 + ], + "result": { + "item": "anvilcraft:resentful_amber_block" + } + } + ] + } + ], + "predicates": [ + { + "type": "has_block", + "match_block": { + "blocks": [ + "anvilcraft:corrupted_beacon" + ], + "state": { + "lit": "true" + } + }, + "offset": [ + 0.0, + -2.0, + 0.0 + ] + }, + { + "type": "has_block", + "match_block": { + "blocks": [ + "minecraft:cauldron" + ] + }, + "offset": [ + 0.0, + -1.0, + 0.0 + ] + }, + { + "type": "has_item_ingredient", + "data_path": "resin", + "has_tag": [ + "entity" + ], + "match_item": { + "count": { + "min": 1 + }, + "items": [ + "anvilcraft:resin_block" + ], + "nbt": "{is_monster:1b}" + }, + "offset": [ + 0.0, + -1.0, + 0.0 + ] + } + ] +} \ No newline at end of file diff --git a/fabric/src/generated/resources/data/minecraft/tags/blocks/mineable/pickaxe.json b/fabric/src/generated/resources/data/minecraft/tags/blocks/mineable/pickaxe.json index 7d9d857a1..cc8bbc088 100644 --- a/fabric/src/generated/resources/data/minecraft/tags/blocks/mineable/pickaxe.json +++ b/fabric/src/generated/resources/data/minecraft/tags/blocks/mineable/pickaxe.json @@ -24,6 +24,8 @@ "anvilcraft:sapphire_block", "anvilcraft:resin_block", "anvilcraft:amber_block", + "anvilcraft:mob_amber_block", + "anvilcraft:resentful_amber_block", "anvilcraft:creative_generator", "anvilcraft:heater", "anvilcraft:transmission_pole", diff --git a/fabric/src/main/java/dev/dubhe/anvilcraft/api/depository/fabric/ItemDepositoryHelperImpl.java b/fabric/src/main/java/dev/dubhe/anvilcraft/api/depository/fabric/ItemDepositoryHelperImpl.java index faa53ad25..f112d9aca 100644 --- a/fabric/src/main/java/dev/dubhe/anvilcraft/api/depository/fabric/ItemDepositoryHelperImpl.java +++ b/fabric/src/main/java/dev/dubhe/anvilcraft/api/depository/fabric/ItemDepositoryHelperImpl.java @@ -1,15 +1,21 @@ package dev.dubhe.anvilcraft.api.depository.fabric; import dev.dubhe.anvilcraft.api.depository.IItemDepository; +import net.fabricmc.fabric.api.transfer.v1.item.InventoryStorage; import net.fabricmc.fabric.api.transfer.v1.item.ItemStorage; import net.fabricmc.fabric.api.transfer.v1.item.ItemVariant; import net.fabricmc.fabric.api.transfer.v1.storage.Storage; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.vehicle.ContainerEntity; import net.minecraft.world.level.Level; +import net.minecraft.world.phys.AABB; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.List; + @SuppressWarnings("UnstableApiUsage") public class ItemDepositoryHelperImpl { /** @@ -23,6 +29,14 @@ public class ItemDepositoryHelperImpl { @Nullable public static IItemDepository getItemDepository(@NotNull Level level, BlockPos pos, Direction direction) { Storage target = ItemStorage.SIDED.find(level, pos, direction); + List entities = level.getEntitiesOfClass(Entity.class, new AABB(pos)); + if (target == null) { + for (Entity entity : entities) { + if (!(entity instanceof ContainerEntity container)) continue; + target = InventoryStorage.of(container, null); + break; + } + } if (target == null) return null; return toItemDepository(target); } @@ -33,7 +47,7 @@ public static IItemDepository getItemDepository(@NotNull Level level, BlockPos p * @param storage 要转换的 Storage * @return 转换为的 ItemDepository */ - public static IItemDepository toItemDepository(Storage storage) { + public static @NotNull IItemDepository toItemDepository(Storage storage) { return new ItemStorageProxyItemDepository(storage); } @@ -43,7 +57,7 @@ public static IItemDepository toItemDepository(Storage storage) { * @param itemDepository 要转换的 itemDepository * @return 转换为的 存有 {@link ItemVariant} 的 {@link Storage} */ - public static Storage toStorage(IItemDepository itemDepository) { + public static @NotNull Storage toStorage(IItemDepository itemDepository) { return new ItemDepositoryProxyStorage(itemDepository); } } diff --git a/fabric/src/main/java/dev/dubhe/anvilcraft/client/fabric/AnvilCraftFabricClient.java b/fabric/src/main/java/dev/dubhe/anvilcraft/client/fabric/AnvilCraftFabricClient.java index 1eec315a2..dd2259814 100644 --- a/fabric/src/main/java/dev/dubhe/anvilcraft/client/fabric/AnvilCraftFabricClient.java +++ b/fabric/src/main/java/dev/dubhe/anvilcraft/client/fabric/AnvilCraftFabricClient.java @@ -14,6 +14,8 @@ public void onInitializeClient() { BlockRenderLayerMap.INSTANCE.putBlock(ModBlocks.CORRUPTED_BEACON.get(), RenderType.cutout()); BlockRenderLayerMap.INSTANCE.putBlock(ModBlocks.RESIN_BLOCK.get(), RenderType.translucent()); BlockRenderLayerMap.INSTANCE.putBlock(ModBlocks.AMBER_BLOCK.get(), RenderType.translucent()); + BlockRenderLayerMap.INSTANCE.putBlock(ModBlocks.MOB_AMBER_BLOCK.get(), RenderType.translucent()); + BlockRenderLayerMap.INSTANCE.putBlock(ModBlocks.RESENTFUL_AMBER_BLOCK.get(), RenderType.translucent()); BlockRenderLayerMap.INSTANCE.putBlock(ModBlocks.TEMPERING_GLASS.get(), RenderType.translucent()); BlockRenderLayerMap.INSTANCE.putBlock(ModBlocks.HEATER.get(), RenderType.translucent()); BlockRenderLayerMap.INSTANCE.putBlock(ModBlocks.CRAB_TRAP.get(), RenderType.cutout()); diff --git a/fabric/src/main/java/dev/dubhe/anvilcraft/util/fabric/ModCustomTrades.java b/fabric/src/main/java/dev/dubhe/anvilcraft/util/fabric/ModCustomTrades.java index 521956ce5..a0bed032e 100644 --- a/fabric/src/main/java/dev/dubhe/anvilcraft/util/fabric/ModCustomTrades.java +++ b/fabric/src/main/java/dev/dubhe/anvilcraft/util/fabric/ModCustomTrades.java @@ -57,9 +57,12 @@ stack, new ItemStack(Items.EMERALD, 8), new ItemStack(Items.NAUTILUS_SHELL), ItemStack.EMPTY, new ItemStack(Items.EMERALD, 2), 12, 10, 0.05f )); - factories.add((entity, random) -> new MerchantOffer( - new ItemStack(ModBlocks.CORRUPTED_BEACON), ItemStack.EMPTY, new ItemStack(Items.EMERALD, 24), - 2, 2, 30, 0.05f + factories.add((entity, random) -> ((int) (random.nextDouble() * 2)) == 1 ? new MerchantOffer( + new ItemStack(ModBlocks.MOB_AMBER_BLOCK), ItemStack.EMPTY, new ItemStack(Items.EMERALD, 8), + 2, 10, 0.05f + ) : new MerchantOffer( + new ItemStack(ModBlocks.RESENTFUL_AMBER_BLOCK), ItemStack.EMPTY, new ItemStack(Items.EMERALD, 24), + 2, 30, 0.05f )); }); TradeOfferHelper.registerVillagerOffers(ModVillagers.JEWELER, 5, factories -> { diff --git a/forge/src/generated/resources/assets/anvilcraft/lang/en_ud.json b/forge/src/generated/resources/assets/anvilcraft/lang/en_ud.json index 11ec759bc..a055e5677 100644 --- a/forge/src/generated/resources/assets/anvilcraft/lang/en_ud.json +++ b/forge/src/generated/resources/assets/anvilcraft/lang/en_ud.json @@ -19,11 +19,12 @@ "block.anvilcraft.lava_cauldron": "uoɹpןnɐƆ ɐʌɐꞀ", "block.anvilcraft.magnet_block": "ʞɔoןᗺ ʇǝubɐW", "block.anvilcraft.melt_gem_cauldron": "uoɹpןnɐƆ ɯǝ⅁ ʇןǝW", + "block.anvilcraft.mob_amber_block": "ʞɔoןᗺ ɹǝqɯⱯ qoW", "block.anvilcraft.nether_dust": "ʇsnᗡ ɹǝɥʇǝN", "block.anvilcraft.piezoelectric_crystal": "ןɐʇsʎɹƆ ɔıɹʇɔǝןǝozǝıԀ", "block.anvilcraft.quartz_sand": "puɐS zʇɹɐnὉ", + "block.anvilcraft.resentful_amber_block": "ʞɔoןᗺ ɹǝqɯⱯ ןnɟʇuǝsǝᴚ", "block.anvilcraft.resin_block": "ʞɔoןᗺ uısǝᴚ", - "block.anvilcraft.resin_block.has_mob": "ʞɔoןᗺ uısǝᴚ %s suıɐʇuoƆ", "block.anvilcraft.royal_anvil": "ןıʌuⱯ ןɐʎoᴚ", "block.anvilcraft.royal_grindstone": "ǝuoʇspuıɹ⅁ ןɐʎoᴚ", "block.anvilcraft.royal_smithing_table": "ǝןqɐ⟘ buıɥʇıɯS ןɐʎoᴚ", diff --git a/forge/src/generated/resources/assets/anvilcraft/lang/en_us.json b/forge/src/generated/resources/assets/anvilcraft/lang/en_us.json index 18e759f6e..c34c5144a 100644 --- a/forge/src/generated/resources/assets/anvilcraft/lang/en_us.json +++ b/forge/src/generated/resources/assets/anvilcraft/lang/en_us.json @@ -19,11 +19,12 @@ "block.anvilcraft.lava_cauldron": "Lava Cauldron", "block.anvilcraft.magnet_block": "Magnet Block", "block.anvilcraft.melt_gem_cauldron": "Melt Gem Cauldron", + "block.anvilcraft.mob_amber_block": "Mob Amber Block", "block.anvilcraft.nether_dust": "Nether Dust", "block.anvilcraft.piezoelectric_crystal": "Piezoelectric Crystal", "block.anvilcraft.quartz_sand": "Quartz Sand", + "block.anvilcraft.resentful_amber_block": "Resentful Amber Block", "block.anvilcraft.resin_block": "Resin Block", - "block.anvilcraft.resin_block.has_mob": "Contains %s Resin Block", "block.anvilcraft.royal_anvil": "Royal Anvil", "block.anvilcraft.royal_grindstone": "Royal Grindstone", "block.anvilcraft.royal_smithing_table": "Royal Smithing Table", diff --git a/forge/src/generated/resources/assets/anvilcraft/models/item/mob_amber_block.json b/forge/src/generated/resources/assets/anvilcraft/models/item/mob_amber_block.json new file mode 100644 index 000000000..71a10ecf5 --- /dev/null +++ b/forge/src/generated/resources/assets/anvilcraft/models/item/mob_amber_block.json @@ -0,0 +1,3 @@ +{ + "parent": "anvilcraft:block/mob_amber_block" +} \ No newline at end of file diff --git a/forge/src/generated/resources/assets/anvilcraft/models/item/resentful_amber_block.json b/forge/src/generated/resources/assets/anvilcraft/models/item/resentful_amber_block.json new file mode 100644 index 000000000..bc7bb0a26 --- /dev/null +++ b/forge/src/generated/resources/assets/anvilcraft/models/item/resentful_amber_block.json @@ -0,0 +1,3 @@ +{ + "parent": "anvilcraft:block/resentful_amber_block" +} \ No newline at end of file diff --git a/forge/src/generated/resources/data/anvilcraft/advancements/recipes/misc/timewarp/amber_block.json b/forge/src/generated/resources/data/anvilcraft/advancements/recipes/misc/timewarp/amber_block.json index a724cbcf2..214f8f0c6 100644 --- a/forge/src/generated/resources/data/anvilcraft/advancements/recipes/misc/timewarp/amber_block.json +++ b/forge/src/generated/resources/data/anvilcraft/advancements/recipes/misc/timewarp/amber_block.json @@ -1,7 +1,7 @@ { "parent": "minecraft:recipes/root", "criteria": { - "has_resin_block": { + "has_amber_block": { "conditions": { "items": [ { @@ -22,7 +22,7 @@ }, "requirements": [ [ - "has_resin_block", + "has_amber_block", "has_the_recipe" ] ], diff --git a/forge/src/generated/resources/data/anvilcraft/advancements/recipes/misc/timewarp/mob_amber_block.json b/forge/src/generated/resources/data/anvilcraft/advancements/recipes/misc/timewarp/mob_amber_block.json new file mode 100644 index 000000000..1ec5179f6 --- /dev/null +++ b/forge/src/generated/resources/data/anvilcraft/advancements/recipes/misc/timewarp/mob_amber_block.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_mob_amber_block": { + "conditions": { + "items": [ + { + "items": [ + "anvilcraft:resin_block" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "anvilcraft:timewarp/mob_amber_block" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_mob_amber_block", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "anvilcraft:timewarp/mob_amber_block" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/forge/src/generated/resources/data/anvilcraft/advancements/recipes/misc/timewarp/mob_amber_block_resentful.json b/forge/src/generated/resources/data/anvilcraft/advancements/recipes/misc/timewarp/mob_amber_block_resentful.json new file mode 100644 index 000000000..b244e7ecd --- /dev/null +++ b/forge/src/generated/resources/data/anvilcraft/advancements/recipes/misc/timewarp/mob_amber_block_resentful.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_mob_amber_block": { + "conditions": { + "items": [ + { + "items": [ + "anvilcraft:resin_block" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "anvilcraft:timewarp/mob_amber_block_resentful" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_mob_amber_block", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "anvilcraft:timewarp/mob_amber_block_resentful" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/forge/src/generated/resources/data/anvilcraft/loot_tables/blocks/mob_amber_block.json b/forge/src/generated/resources/data/anvilcraft/loot_tables/blocks/mob_amber_block.json new file mode 100644 index 000000000..c7230482b --- /dev/null +++ b/forge/src/generated/resources/data/anvilcraft/loot_tables/blocks/mob_amber_block.json @@ -0,0 +1,21 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "anvilcraft:mob_amber_block" + } + ], + "rolls": 1.0 + } + ], + "random_sequence": "anvilcraft:blocks/mob_amber_block" +} \ No newline at end of file diff --git a/forge/src/generated/resources/data/anvilcraft/loot_tables/blocks/resentful_amber_block.json b/forge/src/generated/resources/data/anvilcraft/loot_tables/blocks/resentful_amber_block.json new file mode 100644 index 000000000..5466245f3 --- /dev/null +++ b/forge/src/generated/resources/data/anvilcraft/loot_tables/blocks/resentful_amber_block.json @@ -0,0 +1,21 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "anvilcraft:resentful_amber_block" + } + ], + "rolls": 1.0 + } + ], + "random_sequence": "anvilcraft:blocks/resentful_amber_block" +} \ No newline at end of file diff --git a/forge/src/generated/resources/data/anvilcraft/recipes/timewarp/amber_block.json b/forge/src/generated/resources/data/anvilcraft/recipes/timewarp/amber_block.json index b82851de6..bfe312012 100644 --- a/forge/src/generated/resources/data/anvilcraft/recipes/timewarp/amber_block.json +++ b/forge/src/generated/resources/data/anvilcraft/recipes/timewarp/amber_block.json @@ -57,6 +57,9 @@ "anvilcraft:resin_block" ] }, + "not_has_tag": [ + "entity" + ], "offset": [ 0.0, -1.0, diff --git a/forge/src/generated/resources/data/anvilcraft/recipes/timewarp/mob_amber_block.json b/forge/src/generated/resources/data/anvilcraft/recipes/timewarp/mob_amber_block.json new file mode 100644 index 000000000..d6fc953f8 --- /dev/null +++ b/forge/src/generated/resources/data/anvilcraft/recipes/timewarp/mob_amber_block.json @@ -0,0 +1,73 @@ +{ + "type": "anvilcraft:anvil_processing", + "icon": { + "item": "anvilcraft:mob_amber_block" + }, + "outcomes": [ + { + "type": "spawn_item", + "chance": 1.0, + "data_path": "resin", + "offset": [ + 0.0, + -1.0, + 0.0 + ], + "result": { + "item": "anvilcraft:mob_amber_block" + } + } + ], + "predicates": [ + { + "type": "has_block", + "match_block": { + "blocks": [ + "anvilcraft:corrupted_beacon" + ], + "state": { + "lit": "true" + } + }, + "offset": [ + 0.0, + -2.0, + 0.0 + ] + }, + { + "type": "has_block", + "match_block": { + "blocks": [ + "minecraft:cauldron" + ] + }, + "offset": [ + 0.0, + -1.0, + 0.0 + ] + }, + { + "type": "has_item_ingredient", + "data_path": "resin", + "has_tag": [ + "entity" + ], + "match_item": { + "count": { + "min": 1 + }, + "items": [ + "anvilcraft:resin_block" + ], + "nbt": "{is_monster:1b}" + }, + "offset": [ + 0.0, + -1.0, + 0.0 + ] + } + ] +} \ No newline at end of file diff --git a/forge/src/generated/resources/data/anvilcraft/recipes/timewarp/mob_amber_block_resentful.json b/forge/src/generated/resources/data/anvilcraft/recipes/timewarp/mob_amber_block_resentful.json new file mode 100644 index 000000000..20a9be465 --- /dev/null +++ b/forge/src/generated/resources/data/anvilcraft/recipes/timewarp/mob_amber_block_resentful.json @@ -0,0 +1,92 @@ +{ + "type": "anvilcraft:anvil_processing", + "icon": { + "item": "anvilcraft:mob_amber_block" + }, + "outcomes": [ + { + "type": "select_one", + "chance": 1.0, + "outcomes": [ + { + "type": "spawn_item", + "chance": 0.95, + "data_path": "resin", + "offset": [ + 0.0, + -1.0, + 0.0 + ], + "result": { + "item": "anvilcraft:mob_amber_block" + } + }, + { + "type": "spawn_item", + "chance": 0.05, + "data_path": "resin", + "offset": [ + 0.0, + -1.0, + 0.0 + ], + "result": { + "item": "anvilcraft:resentful_amber_block" + } + } + ] + } + ], + "predicates": [ + { + "type": "has_block", + "match_block": { + "blocks": [ + "anvilcraft:corrupted_beacon" + ], + "state": { + "lit": "true" + } + }, + "offset": [ + 0.0, + -2.0, + 0.0 + ] + }, + { + "type": "has_block", + "match_block": { + "blocks": [ + "minecraft:cauldron" + ] + }, + "offset": [ + 0.0, + -1.0, + 0.0 + ] + }, + { + "type": "has_item_ingredient", + "data_path": "resin", + "has_tag": [ + "entity" + ], + "match_item": { + "count": { + "min": 1 + }, + "items": [ + "anvilcraft:resin_block" + ], + "nbt": "{is_monster:1b}" + }, + "offset": [ + 0.0, + -1.0, + 0.0 + ] + } + ] +} \ No newline at end of file diff --git a/forge/src/generated/resources/data/minecraft/tags/blocks/mineable/pickaxe.json b/forge/src/generated/resources/data/minecraft/tags/blocks/mineable/pickaxe.json index 7d9d857a1..cc8bbc088 100644 --- a/forge/src/generated/resources/data/minecraft/tags/blocks/mineable/pickaxe.json +++ b/forge/src/generated/resources/data/minecraft/tags/blocks/mineable/pickaxe.json @@ -24,6 +24,8 @@ "anvilcraft:sapphire_block", "anvilcraft:resin_block", "anvilcraft:amber_block", + "anvilcraft:mob_amber_block", + "anvilcraft:resentful_amber_block", "anvilcraft:creative_generator", "anvilcraft:heater", "anvilcraft:transmission_pole", diff --git a/forge/src/main/java/dev/dubhe/anvilcraft/api/depository/forge/ItemDepositoryHelperImpl.java b/forge/src/main/java/dev/dubhe/anvilcraft/api/depository/forge/ItemDepositoryHelperImpl.java index 5701469b0..776d38bbd 100644 --- a/forge/src/main/java/dev/dubhe/anvilcraft/api/depository/forge/ItemDepositoryHelperImpl.java +++ b/forge/src/main/java/dev/dubhe/anvilcraft/api/depository/forge/ItemDepositoryHelperImpl.java @@ -101,7 +101,7 @@ public boolean isItemValid(int slot, ItemStack stack) { * @param depository 物品容器 * @return 物品容器 */ - public static IItemHandler toItemHandler(IItemDepository depository) { + public static @NotNull IItemHandler toItemHandler(IItemDepository depository) { return new IItemHandler() { @Override diff --git a/forge/src/main/java/dev/dubhe/anvilcraft/event/forge/VillagerEventListener.java b/forge/src/main/java/dev/dubhe/anvilcraft/event/forge/VillagerEventListener.java index 9e2236500..8e1f2713d 100644 --- a/forge/src/main/java/dev/dubhe/anvilcraft/event/forge/VillagerEventListener.java +++ b/forge/src/main/java/dev/dubhe/anvilcraft/event/forge/VillagerEventListener.java @@ -71,9 +71,12 @@ stack, new ItemStack(Items.EMERALD, 8), new ItemStack(Items.NAUTILUS_SHELL), ItemStack.EMPTY, new ItemStack(Items.EMERALD, 2), 12, 10, 0.05f )); - trades.get(4).add((entity, random) -> new MerchantOffer( - new ItemStack(ModBlocks.CORRUPTED_BEACON), ItemStack.EMPTY, new ItemStack(Items.EMERALD, 24), - 2, 2, 30, 0.05f + trades.get(4).add((entity, random) -> ((int) (random.nextDouble() * 2)) == 1 ? new MerchantOffer( + new ItemStack(ModBlocks.MOB_AMBER_BLOCK), ItemStack.EMPTY, new ItemStack(Items.EMERALD, 8), + 2, 10, 0.05f + ) : new MerchantOffer( + new ItemStack(ModBlocks.RESENTFUL_AMBER_BLOCK), ItemStack.EMPTY, new ItemStack(Items.EMERALD, 24), + 2, 30, 0.05f )); // level 5