diff --git a/src/generated/resources/assets/anvilcraft_pigsplus/lang/en_ud.json b/src/generated/resources/assets/anvilcraft_pigsplus/lang/en_ud.json index 6bee1f5..3029ca2 100644 --- a/src/generated/resources/assets/anvilcraft_pigsplus/lang/en_ud.json +++ b/src/generated/resources/assets/anvilcraft_pigsplus/lang/en_ud.json @@ -32,6 +32,7 @@ "anvilcraft_pigsplus.configuration.section.anvilcraft_pigsplus.server.toml": "uoıʇɐɹnbıɟuoƆ ɹǝʌɹǝS snןdsbıԀ ʇɟɐɹɔןıʌuⱯ", "anvilcraft_pigsplus.configuration.section.anvilcraft_pigsplus.server.toml.title": "uoıʇɐɹnbıɟuoƆ ɹǝʌɹǝS snןdsbıԀ ʇɟɐɹɔןıʌuⱯ", "anvilcraft_pigsplus.configuration.title": "uoıʇɐɹnbıɟuoƆ snןdsbıԀ ʇɟɐɹɔןıʌuⱯ", + "block.anvilcraft_pigsplus.auto_jewel_crafting_table": "ǝןqɐ⟘ buıʇɟɐɹƆ ןǝʍǝſ oʇnⱯ", "block.anvilcraft_pigsplus.auto_royal_grindstone": "ǝuoʇspuıɹ⅁ ןɐʎoᴚ oʇnⱯ", "block.anvilcraft_pigsplus.auto_royal_smithing_table": "ǝןqɐ⟘ buıɥʇıɯS ןɐʎoᴚ oʇnⱯ", "block.anvilcraft_pigsplus.block_breaker": "ɹǝʞɐǝɹᗺ ʞɔoןᗺ", diff --git a/src/generated/resources/assets/anvilcraft_pigsplus/lang/en_us.json b/src/generated/resources/assets/anvilcraft_pigsplus/lang/en_us.json index 257d570..4847acb 100644 --- a/src/generated/resources/assets/anvilcraft_pigsplus/lang/en_us.json +++ b/src/generated/resources/assets/anvilcraft_pigsplus/lang/en_us.json @@ -32,6 +32,7 @@ "anvilcraft_pigsplus.configuration.section.anvilcraft_pigsplus.server.toml": "Anvilcraft Pigsplus Server Configuration", "anvilcraft_pigsplus.configuration.section.anvilcraft_pigsplus.server.toml.title": "Anvilcraft Pigsplus Server Configuration", "anvilcraft_pigsplus.configuration.title": "Anvilcraft Pigsplus Configuration", + "block.anvilcraft_pigsplus.auto_jewel_crafting_table": "Auto Jewel Crafting Table", "block.anvilcraft_pigsplus.auto_royal_grindstone": "Auto Royal Grindstone", "block.anvilcraft_pigsplus.auto_royal_smithing_table": "Auto Royal Smithing Table", "block.anvilcraft_pigsplus.block_breaker": "Block Breaker", diff --git a/src/generated/resources/assets/anvilcraft_pigsplus/models/item/auto_jewel_crafting_table.json b/src/generated/resources/assets/anvilcraft_pigsplus/models/item/auto_jewel_crafting_table.json new file mode 100644 index 0000000..be5ee92 --- /dev/null +++ b/src/generated/resources/assets/anvilcraft_pigsplus/models/item/auto_jewel_crafting_table.json @@ -0,0 +1,3 @@ +{ + "parent": "anvilcraft_pigsplus:block/auto_jewel_crafting_table" +} \ No newline at end of file diff --git a/src/generated/resources/data/anvilcraft_pigsplus/advancement/recipes/building_blocks/auto_jewel_crafting_table.json b/src/generated/resources/data/anvilcraft_pigsplus/advancement/recipes/building_blocks/auto_jewel_crafting_table.json new file mode 100644 index 0000000..8ec824a --- /dev/null +++ b/src/generated/resources/data/anvilcraft_pigsplus/advancement/recipes/building_blocks/auto_jewel_crafting_table.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_jewelcrafting_table": { + "conditions": { + "items": [ + { + "items": "anvilcraft:jewelcrafting_table" + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "anvilcraft_pigsplus:auto_jewel_crafting_table" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_the_recipe", + "has_jewelcrafting_table" + ] + ], + "rewards": { + "recipes": [ + "anvilcraft_pigsplus:auto_jewel_crafting_table" + ] + } +} \ No newline at end of file diff --git a/src/generated/resources/data/anvilcraft_pigsplus/loot_table/blocks/auto_jewel_crafting_table.json b/src/generated/resources/data/anvilcraft_pigsplus/loot_table/blocks/auto_jewel_crafting_table.json new file mode 100644 index 0000000..362b51a --- /dev/null +++ b/src/generated/resources/data/anvilcraft_pigsplus/loot_table/blocks/auto_jewel_crafting_table.json @@ -0,0 +1,21 @@ +{ + "type": "minecraft:block", + "pools": [ + { + "bonus_rolls": 0.0, + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "entries": [ + { + "type": "minecraft:item", + "name": "anvilcraft_pigsplus:auto_jewel_crafting_table" + } + ], + "rolls": 1.0 + } + ], + "random_sequence": "anvilcraft_pigsplus:blocks/auto_jewel_crafting_table" +} \ No newline at end of file diff --git a/src/generated/resources/data/anvilcraft_pigsplus/recipe/auto_jewel_crafting_table.json b/src/generated/resources/data/anvilcraft_pigsplus/recipe/auto_jewel_crafting_table.json new file mode 100644 index 0000000..b954011 --- /dev/null +++ b/src/generated/resources/data/anvilcraft_pigsplus/recipe/auto_jewel_crafting_table.json @@ -0,0 +1,24 @@ +{ + "type": "minecraft:crafting_shaped", + "category": "building", + "key": { + "J": { + "item": "anvilcraft:jewelcrafting_table" + }, + "K": { + "item": "anvilcraft_pigsplus:karakuri_component" + }, + "M": { + "item": "anvilcraft:magnetoelectric_core" + } + }, + "pattern": [ + " K ", + " J ", + " M " + ], + "result": { + "count": 1, + "id": "anvilcraft_pigsplus:auto_jewel_crafting_table" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/minecraft/tags/block/mineable/pickaxe.json b/src/generated/resources/data/minecraft/tags/block/mineable/pickaxe.json index 4625271..bffa9cd 100644 --- a/src/generated/resources/data/minecraft/tags/block/mineable/pickaxe.json +++ b/src/generated/resources/data/minecraft/tags/block/mineable/pickaxe.json @@ -4,6 +4,7 @@ "anvilcraft_pigsplus:redstone_conduit_block", "anvilcraft_pigsplus:block_breaker", "anvilcraft_pigsplus:chain_smithing_table", + "anvilcraft_pigsplus:auto_jewel_crafting_table", "anvilcraft_pigsplus:auto_royal_smithing_table", "anvilcraft_pigsplus:auto_royal_grindstone", "anvilcraft_pigsplus:chaotic_raw_ore_block", diff --git a/src/generated/resources/data/minecraft/tags/block/needs_iron_tool.json b/src/generated/resources/data/minecraft/tags/block/needs_iron_tool.json index f8de25f..ccdb1ef 100644 --- a/src/generated/resources/data/minecraft/tags/block/needs_iron_tool.json +++ b/src/generated/resources/data/minecraft/tags/block/needs_iron_tool.json @@ -1,6 +1,7 @@ { "values": [ "anvilcraft_pigsplus:chain_smithing_table", + "anvilcraft_pigsplus:auto_jewel_crafting_table", "anvilcraft_pigsplus:auto_royal_smithing_table", "anvilcraft_pigsplus:auto_royal_grindstone" ] diff --git a/src/main/java/dev/anvilcraft/pigsplus/block/AutoJewelCraftingTableBlock.java b/src/main/java/dev/anvilcraft/pigsplus/block/AutoJewelCraftingTableBlock.java new file mode 100644 index 0000000..8282be8 --- /dev/null +++ b/src/main/java/dev/anvilcraft/pigsplus/block/AutoJewelCraftingTableBlock.java @@ -0,0 +1,174 @@ +package dev.anvilcraft.pigsplus.block; + +import com.mojang.serialization.MapCodec; +import dev.anvilcraft.pigsplus.block.entity.AutoJewelCraftingTableBlockEntity; +import dev.anvilcraft.pigsplus.init.AddonBlockEntities; +import dev.anvilcraft.pigsplus.init.AddonMenuTypes; +import dev.dubhe.anvilcraft.api.hammer.IHammerRemovable; +import dev.dubhe.anvilcraft.api.itemhandler.FilteredItemStackHandler; +import dev.dubhe.anvilcraft.api.power.IPowerComponent; +import dev.dubhe.anvilcraft.block.better.BetterBaseEntityBlock; +import dev.dubhe.anvilcraft.block.entity.BatchCrafterBlockEntity; +import dev.dubhe.anvilcraft.network.MachineOutputDirectionPacket; +import net.minecraft.core.BlockPos; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.util.RandomSource; +import net.minecraft.world.Containers; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.context.BlockPlaceContext; +import net.minecraft.world.level.GameType; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.BaseEntityBlock; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.RenderShape; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.entity.BlockEntityTicker; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.StateDefinition; +import net.minecraft.world.level.block.state.properties.BlockStateProperties; +import net.minecraft.world.level.block.state.properties.BooleanProperty; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraft.world.phys.Vec3; +import net.neoforged.neoforge.network.PacketDistributor; +import org.jetbrains.annotations.Nullable; + +public class AutoJewelCraftingTableBlock extends BetterBaseEntityBlock implements IHammerRemovable { + public static final BooleanProperty POWERED = BlockStateProperties.POWERED; + public static final BooleanProperty OVERLOAD = IPowerComponent.OVERLOAD; + + public AutoJewelCraftingTableBlock(Properties properties) { + super(properties); + this.registerDefaultState(this.stateDefinition + .any() + .setValue(POWERED, false) + .setValue(OVERLOAD, true)); + } + + @Override + protected MapCodec codec() { + return simpleCodec(AutoJewelCraftingTableBlock::new); + } + + @Override + public boolean hasAnalogOutputSignal(BlockState blockState) { + return true; + } + + @Override + public int getAnalogOutputSignal(BlockState blockState, Level level, BlockPos blockPos) { + BlockEntity blockEntity = level.getBlockEntity(blockPos); + if (blockEntity instanceof AutoJewelCraftingTableBlockEntity autoJewelCraftingTableBlockEntity) { + return autoJewelCraftingTableBlockEntity.getRedstoneSignal(); + } + return 0; + } + + @Override + public RenderShape getRenderShape(BlockState state) { + return RenderShape.MODEL; + } + + @Nullable + @Override + public BlockEntity newBlockEntity(BlockPos pos, BlockState state) { + return new AutoJewelCraftingTableBlockEntity(AddonBlockEntities.AUTO_JEWEL_CRAFTING_TABLE.get(), pos, state); + } + + @Override + public InteractionResult use( + BlockState state, + Level level, + BlockPos pos, + Player player, + InteractionHand hand, + BlockHitResult hit + ) { + if (level.isClientSide) return InteractionResult.SUCCESS; + + BlockEntity blockEntity = level.getBlockEntity(pos); + if (blockEntity instanceof AutoJewelCraftingTableBlockEntity entity) { + if (player instanceof ServerPlayer serverPlayer) { + if (serverPlayer.gameMode.getGameModeForPlayer() == GameType.SPECTATOR) return InteractionResult.PASS; + AddonMenuTypes.open(serverPlayer, entity, pos); + PacketDistributor.sendToPlayer(serverPlayer, new MachineOutputDirectionPacket(entity.getDirection())); + } + } + return InteractionResult.SUCCESS; + } + + + @Override + public void onRemove( + BlockState state, + Level level, + BlockPos pos, + BlockState newState, + boolean movedByPiston + ) { + if (state.is(newState.getBlock())) return; + if (level.getBlockEntity(pos) instanceof BatchCrafterBlockEntity entity) { + Vec3 vec3 = entity.getBlockPos().getCenter(); + FilteredItemStackHandler itemHandler = entity.getItemHandler(); + for (int slot = 0; slot < itemHandler.getSlots(); slot++) { + Containers.dropItemStack(level, vec3.x, vec3.y, vec3.z, itemHandler.getStackInSlot(slot)); + } + level.updateNeighbourForOutputSignal(pos, this); + } + super.onRemove(state, level, pos, newState, movedByPiston); + } + + + @Nullable + public BlockState getStateForPlacement(BlockPlaceContext context) { + return this.defaultBlockState() + .setValue(POWERED, context.getLevel().hasNeighborSignal(context.getClickedPos())) + .setValue(OVERLOAD, true); + } + + @Override + protected void createBlockStateDefinition(StateDefinition.Builder builder) { + builder.add(POWERED).add(OVERLOAD); + } + + @Override + public void neighborChanged( + BlockState state, + Level level, + BlockPos pos, + Block neighborBlock, + BlockPos neighborPos, + boolean movedByPiston + ) { + if (level.isClientSide) { + return; + } + level.setBlock(pos, state.setValue(POWERED, level.hasNeighborSignal(pos)), 2); + } + + @Override + public void tick( + BlockState state, + ServerLevel level, + BlockPos pos, + RandomSource random + ) { + if (state.getValue(POWERED) && !level.hasNeighborSignal(pos)) { + level.setBlock(pos, state.cycle(POWERED), 2); + } + } + + @Override + public @Nullable BlockEntityTicker getTicker(Level level, BlockState state, BlockEntityType type) { + if (level.isClientSide) { + return null; + } + return createTickerHelper( + type, AddonBlockEntities.AUTO_JEWEL_CRAFTING_TABLE.get(), + (level1, blockPos, blockState, blockEntity) -> blockEntity.tick(level1, blockPos) + ); + } +} \ No newline at end of file diff --git a/src/main/java/dev/anvilcraft/pigsplus/block/entity/AutoJewelCraftingTableBlockEntity.java b/src/main/java/dev/anvilcraft/pigsplus/block/entity/AutoJewelCraftingTableBlockEntity.java new file mode 100644 index 0000000..8afd09a --- /dev/null +++ b/src/main/java/dev/anvilcraft/pigsplus/block/entity/AutoJewelCraftingTableBlockEntity.java @@ -0,0 +1,296 @@ +package dev.anvilcraft.pigsplus.block.entity; + +import dev.anvilcraft.pigsplus.block.AutoJewelCraftingTableBlock; +import dev.anvilcraft.pigsplus.init.AddonBlocks; +import dev.anvilcraft.pigsplus.init.AddonMenuTypes; +import dev.anvilcraft.pigsplus.inventory.AutoJewelCraftingMenu; +import dev.dubhe.anvilcraft.api.itemhandler.ItemHandlerUtil; +import dev.dubhe.anvilcraft.api.power.IPowerConsumer; +import dev.dubhe.anvilcraft.api.power.PowerGrid; +import dev.dubhe.anvilcraft.block.BatchCrafterBlock; +import dev.dubhe.anvilcraft.block.entity.BaseMachineBlockEntity; +import dev.dubhe.anvilcraft.init.block.ModBlocks; +import dev.dubhe.anvilcraft.recipe.JewelCraftingRecipe; +import dev.dubhe.anvilcraft.recipe.anvil.cache.RecipeCaches; +import lombok.Getter; +import lombok.Setter; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.core.HolderLookup; +import net.minecraft.core.component.DataComponents; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.chat.Component; +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.item.ItemEntity; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.inventory.AbstractContainerMenu; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.crafting.Ingredient; +import net.minecraft.world.item.crafting.RecipeHolder; +import net.minecraft.world.item.enchantment.Enchantments; +import net.minecraft.world.item.enchantment.ItemEnchantments; +import net.minecraft.world.level.GameRules; +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 net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; +import net.neoforged.neoforge.capabilities.Capabilities; +import net.neoforged.neoforge.items.IItemHandler; +import net.neoforged.neoforge.items.ItemStackHandler; +import org.jetbrains.annotations.Nullable; +import org.joml.Vector3f; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.concurrent.atomic.AtomicInteger; + +import static dev.anvilcraft.pigsplus.AnvilCraftPigsPlus.CONFIG; + +@Getter +public class AutoJewelCraftingTableBlockEntity extends BaseMachineBlockEntity implements IPowerConsumer { + private static final AtomicInteger COUNTER = new AtomicInteger(0); + @Getter + private final int inputPower = 16; + @Setter + @Getter + private PowerGrid grid; + private boolean poweredBefore = false; + private int cooldown = 0; + @Getter + private ItemStack resultStack = ItemStack.EMPTY; + @Getter + private @Nullable JewelCraftingRecipe resultRecipe = null; + @Getter + private final int id; + + private final ItemStackHandler itemHandler = new ItemStackHandler(5) { + @Override + public ItemStack insertItem(int slot, ItemStack stack, boolean simulate) { + if (mayPlace(slot, stack)) { + return super.insertItem(slot, stack, simulate); + } else { + return stack; + } + } + + public boolean mayPlace(int slot, ItemStack stack) { + // slot 0 是源物品槽位 + if (slot == 0) { + return RecipeCaches.getAllJewelResultItem().contains(stack.getItem()); + } + if (resultRecipe != null) { + int idx = slot - 1; + var mergedIngredients = resultRecipe.mergedIngredients; + if (idx < mergedIngredients.size()) { + var entry = mergedIngredients.get(idx); + Ingredient ingredient = entry.getKey(); + return ingredient.test(stack); + } + } + return false; + } + + @Override + protected void onContentsChanged(int slot) { + calcResult(); + setChanged(); + } + }; + + public AutoJewelCraftingTableBlockEntity(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + id = COUNTER.incrementAndGet(); + } + + public void calcResult() { + resultStack = ItemStack.EMPTY; + resultRecipe = null; + if (level == null) return; + + ItemStack mainStack = itemHandler.getStackInSlot(0); + + if (mainStack.isEmpty()) return; + + RecipeHolder recipeHolder = RecipeCaches.getJewelRecipeByResult(mainStack); + if (recipeHolder == null) return; + + resultRecipe = recipeHolder.value(); + List materialStack = new ArrayList<>(4); + for (int i = 0; i < 4; i++) { + materialStack.add(itemHandler.getStackInSlot(i + 1)); + } + var input = new JewelCraftingRecipe.Input(mainStack, materialStack); + if (!resultRecipe.matches(input, level)) return; + if (!resultRecipe.isSpecial() && level.getGameRules().getBoolean(GameRules.RULE_LIMITED_CRAFTING)) return; + ItemStack result = resultRecipe.assemble(input, level.registryAccess()); + if (!result.isItemEnabled(level.enabledFeatures())) return; + + resultStack = result.copy(); + ItemEnchantments.Mutable enchantments = new ItemEnchantments.Mutable(ItemEnchantments.EMPTY); + enchantments.set(level.registryAccess().holderOrThrow(Enchantments.VANISHING_CURSE), 1); + resultStack.set(DataComponents.ENCHANTMENTS, enchantments.toImmutable()); + } + + public void tick(Level level, BlockPos pos) { + flushState(level, pos); + BlockState state = level.getBlockState(pos); + level.updateNeighbourForOutputSignal(pos, state.getBlock()); + boolean powered = state.getValue(AutoJewelCraftingTableBlock.POWERED); + // 红石信号上升沿且冷却完毕,尝试进行自动珠宝加工 + cooldown = Math.max(0, cooldown - 1); + if (powered && !poweredBefore && !level.isClientSide && this.cooldown == 0) { + if (work(level)) cooldown = CONFIG.autoRoyalSmithingTableCooldown; + } + poweredBefore = powered; + } + + private boolean work(Level level) { + if (grid == null || !grid.isWorking()) return false; + + calcResult(); + if (resultStack.isEmpty() || resultRecipe == null) return false; + if (!exportItem(resultStack, getDirection())) return false; + + // 消耗输入物品 + JewelCraftingRecipe recipe = this.resultRecipe; + for (int i = 0; i < recipe.mergedIngredients.size(); i++) { + int idx = i + 1; + if (!itemHandler.getStackInSlot(idx).isEmpty()) { + var entry = recipe.mergedIngredients.get(i); + itemHandler.extractItem(idx, entry.getIntValue(), false); + } + } + + level.updateNeighborsAt(getBlockPos(), AddonBlocks.AUTO_JEWEL_CRAFTING_TABLE_BLOCK.get()); + return true; + } + + private boolean exportItem(ItemStack result, Direction direction) { + IItemHandler cap = Objects.requireNonNull(getLevel()).getCapability( + Capabilities.ItemHandler.BLOCK, + getBlockPos().relative(direction), + direction.getOpposite() + ); + if (cap != null) { + // 尝试向容器插入物品 + ItemStack remained = ItemHandlerUtil.insertItem(cap, result, true); + if (!remained.isEmpty()) return false; + ItemHandlerUtil.insertItem(cap, result, false); + } 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)) return false; + + spawnItemEntity(result); + } + return true; + } + + private void spawnItemEntity(ItemStack stack) { + Vec3 center = getBlockPos().relative(getDirection()).getCenter(); + Vector3f step = getDirection().step(); + Level level = this.getLevel(); + if (level == null) return; + ItemEntity itemEntity = + new ItemEntity(level, center.x, center.y, center.z, stack, 0.25 * step.x, 0.25 * step.y, 0.25 * step.z); + itemEntity.setDefaultPickUpDelay(); + level.addFreshEntity(itemEntity); + } + + public IItemHandler getItemHandler() { + return itemHandler; + } + + + @Override + public Packet getUpdatePacket() { + return ClientboundBlockEntityDataPacket.create(this); + } + + @Override + public CompoundTag getUpdateTag(HolderLookup.Provider provider) { + return this.saveWithoutMetadata(provider); + } + + @Override + protected void loadAdditional(CompoundTag tag, HolderLookup.Provider provider) { + super.loadAdditional(tag, provider); + itemHandler.deserializeNBT(provider, tag.getCompound("Inventory")); + if (tag.getBoolean("HasResultItemStack") && tag.contains("ResultItemStack")) { + CompoundTag ct = tag.getCompound("ResultItemStack"); + resultStack = + ct.contains("id") ? ItemStack.parse(provider, ct).orElse(ItemStack.EMPTY) : ItemStack.EMPTY; + } + this.poweredBefore = tag.getBoolean("PoweredBefore"); + this.cooldown = tag.getInt("Cooldown"); + } + + @Override + protected void saveAdditional(CompoundTag tag, HolderLookup.Provider provider) { + super.saveAdditional(tag, provider); + tag.put("Inventory", this.itemHandler.serializeNBT(provider)); + boolean hasResultItemStack = resultStack != null && !resultStack.isEmpty(); + tag.putBoolean("HasResultItemStack", hasResultItemStack); + if (hasResultItemStack) { + CompoundTag item = (CompoundTag) this.resultStack.save(provider); + tag.put("ResultItemStack", item); + } + tag.putBoolean("PoweredBefore", this.poweredBefore); + tag.putInt("Cooldown", this.cooldown); + } + + @Override + public Direction getDirection() { + return Direction.UP; + } + + @Override + public void setDirection(Direction direction) { + if (level == null) return; + BlockPos pos = getBlockPos(); + BlockState state = level.getBlockState(pos); + if (!state.is(ModBlocks.BATCH_CRAFTER.get())) return; + level.setBlockAndUpdate(pos, state.setValue(BatchCrafterBlock.FACING, direction)); + } + + + public int getRedstoneSignal() { + /*输出等同于有物品的输入槽的数量的红石信号*/ + int strength = 0; + for (int index = 0; index < itemHandler.getSlots(); index++) { + ItemStack itemStack = itemHandler.getStackInSlot(index); + if (itemStack.isEmpty()) continue; + strength++; + } + return strength; + } + + @Nullable + @Override + public AbstractContainerMenu createMenu(int i, Inventory inventory, Player player) { + if (player.isSpectator()) return null; + return new AutoJewelCraftingMenu(AddonMenuTypes.AUTO_JEWEL_CRAFTING.get(), i, inventory, this); + } + + @Override + public Component getDisplayName() { + return Component.translatable("block.anvilcraft_pigsplus.auto_jewel_crafting_table"); + } + + @Override + public BlockPos getPos() { + return getBlockPos(); + } + + @Override + public @Nullable Level getCurrentLevel() { + return getLevel(); + } +} \ No newline at end of file diff --git a/src/main/java/dev/anvilcraft/pigsplus/block/entity/AutoRoyalGrindstoneBlockEntity.java b/src/main/java/dev/anvilcraft/pigsplus/block/entity/AutoRoyalGrindstoneBlockEntity.java index d3bed2f..b64bfab 100644 --- a/src/main/java/dev/anvilcraft/pigsplus/block/entity/AutoRoyalGrindstoneBlockEntity.java +++ b/src/main/java/dev/anvilcraft/pigsplus/block/entity/AutoRoyalGrindstoneBlockEntity.java @@ -58,11 +58,11 @@ @Getter public class AutoRoyalGrindstoneBlockEntity extends BaseMachineBlockEntity implements IPowerConsumer { private static final AtomicInteger COUNTER = new AtomicInteger(0); + @Getter + private final int inputPower = 16; @Setter @Getter private PowerGrid grid; - @Getter - private final int inputPower = 16; private boolean poweredBefore = false; private int cooldown = 0; @Getter diff --git a/src/main/java/dev/anvilcraft/pigsplus/block/entity/AutoRoyalSmithingTableBlockEntity.java b/src/main/java/dev/anvilcraft/pigsplus/block/entity/AutoRoyalSmithingTableBlockEntity.java index c19ed7c..600d59f 100644 --- a/src/main/java/dev/anvilcraft/pigsplus/block/entity/AutoRoyalSmithingTableBlockEntity.java +++ b/src/main/java/dev/anvilcraft/pigsplus/block/entity/AutoRoyalSmithingTableBlockEntity.java @@ -50,15 +50,15 @@ @Getter public class AutoRoyalSmithingTableBlockEntity extends BaseMachineBlockEntity implements IPowerConsumer { private static final AtomicInteger COUNTER = new AtomicInteger(0); + @Getter + private final int inputPower = 16; @Setter @Getter private PowerGrid grid; - @Getter - private final int inputPower = 16; private boolean poweredBefore = false; private int cooldown = 0; @Getter - private ItemStack resultItemStack = null; + private @Nullable ItemStack resultItemStack = null; @Getter private final int id; private final ItemStackHandler itemHandler = new ItemStackHandler(3) { diff --git a/src/main/java/dev/anvilcraft/pigsplus/client/gui/screen/AutoJewelCraftingScreen.java b/src/main/java/dev/anvilcraft/pigsplus/client/gui/screen/AutoJewelCraftingScreen.java new file mode 100644 index 0000000..f2f861e --- /dev/null +++ b/src/main/java/dev/anvilcraft/pigsplus/client/gui/screen/AutoJewelCraftingScreen.java @@ -0,0 +1,37 @@ +package dev.anvilcraft.pigsplus.client.gui.screen; + +import dev.anvilcraft.pigsplus.inventory.AutoJewelCraftingMenu; +import dev.dubhe.anvilcraft.AnvilCraft; +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.player.Inventory; + +public class AutoJewelCraftingScreen extends AbstractContainerScreen { + private static final ResourceLocation JEWEL_CRAFTING_LOCATION = + AnvilCraft.of("textures/gui/container/jewelcrafting/background.png"); + + public AutoJewelCraftingScreen(AutoJewelCraftingMenu menu, Inventory playerInventory, Component title) { + super(menu, playerInventory, title); + } + + @Override + protected void init() { + super.init(); + this.titleLabelX = (this.imageWidth - this.font.width(this.title)) / 2; + } + + @Override + protected void renderBg(GuiGraphics guiGraphics, float partialTick, int mouseX, int mouseY) { + int i = (this.width - this.imageWidth) / 2; + int j = (this.height - this.imageHeight) / 2; + guiGraphics.blit(JEWEL_CRAFTING_LOCATION, i, j, 0, 0, this.imageWidth, this.imageHeight); + } + + @Override + public void render(GuiGraphics guiGraphics, int mouseX, int mouseY, float partialTick) { + super.render(guiGraphics, mouseX, mouseY, partialTick); + this.renderTooltip(guiGraphics, mouseX, mouseY); + } +} \ No newline at end of file diff --git a/src/main/java/dev/anvilcraft/pigsplus/event/CapabilitiesEventListener.java b/src/main/java/dev/anvilcraft/pigsplus/event/CapabilitiesEventListener.java index f329983..2e18af6 100644 --- a/src/main/java/dev/anvilcraft/pigsplus/event/CapabilitiesEventListener.java +++ b/src/main/java/dev/anvilcraft/pigsplus/event/CapabilitiesEventListener.java @@ -15,6 +15,7 @@ public class CapabilitiesEventListener { public static void registerCapabilities(final RegisterCapabilitiesEvent event) { List.of( AddonBlockEntities.ELECTRIC_ENCHANTING_TABLE.get(), + AddonBlockEntities.AUTO_JEWEL_CRAFTING_TABLE.get(), AddonBlockEntities.AUTO_ROYAL_SMITHING_TABLE.get(), AddonBlockEntities.AUTO_ROYAL_GRINDSTONE.get() ).forEach(type -> event.registerBlockEntity( diff --git a/src/main/java/dev/anvilcraft/pigsplus/init/AddonBlockEntities.java b/src/main/java/dev/anvilcraft/pigsplus/init/AddonBlockEntities.java index 5ad31b5..eda0469 100644 --- a/src/main/java/dev/anvilcraft/pigsplus/init/AddonBlockEntities.java +++ b/src/main/java/dev/anvilcraft/pigsplus/init/AddonBlockEntities.java @@ -1,6 +1,7 @@ package dev.anvilcraft.pigsplus.init; import com.tterrag.registrate.util.entry.BlockEntityEntry; +import dev.anvilcraft.pigsplus.block.entity.AutoJewelCraftingTableBlockEntity; import dev.anvilcraft.pigsplus.block.entity.AutoRoyalGrindstoneBlockEntity; import dev.anvilcraft.pigsplus.block.entity.AutoRoyalSmithingTableBlockEntity; import dev.anvilcraft.pigsplus.block.entity.CauldronOutputBlockEntity; @@ -23,6 +24,11 @@ public class AddonBlockEntities { .validBlock(AddonBlocks.AUTO_ROYAL_GRINDSTONE_BLOCK) .register(); + public static final BlockEntityEntry AUTO_JEWEL_CRAFTING_TABLE = + REGISTRATE.blockEntity("auto_jewel_crafting_table", AutoJewelCraftingTableBlockEntity::new) + .validBlock(AddonBlocks.AUTO_JEWEL_CRAFTING_TABLE_BLOCK) + .register(); + public static final BlockEntityEntry CAULDRON_OUTPUT = REGISTRATE.blockEntity("cauldron_output", CauldronOutputBlockEntity::new) .validBlock(AddonBlocks.CAULDRON_OUTPUT) diff --git a/src/main/java/dev/anvilcraft/pigsplus/init/AddonBlocks.java b/src/main/java/dev/anvilcraft/pigsplus/init/AddonBlocks.java index ab22333..14335fd 100644 --- a/src/main/java/dev/anvilcraft/pigsplus/init/AddonBlocks.java +++ b/src/main/java/dev/anvilcraft/pigsplus/init/AddonBlocks.java @@ -1,6 +1,7 @@ package dev.anvilcraft.pigsplus.init; import com.tterrag.registrate.util.entry.BlockEntry; +import dev.anvilcraft.pigsplus.block.AutoJewelCraftingTableBlock; import dev.anvilcraft.pigsplus.block.AutoRoyalGrindstoneBlock; import dev.anvilcraft.pigsplus.block.AutoRoyalSmithingTableBlock; import dev.anvilcraft.pigsplus.block.BlockBreakerBlock; @@ -135,6 +136,28 @@ public class AddonBlocks { .save(provider)) .register(); + public static final BlockEntry AUTO_JEWEL_CRAFTING_TABLE_BLOCK = REGISTRATE + .block("auto_jewel_crafting_table", AutoJewelCraftingTableBlock::new) + .lang("Auto Jewel Crafting Table") + .initialProperties(() -> Blocks.IRON_BLOCK) + .properties(p -> p.strength(5.0f, 1200f)) + .blockstate(DataGenUtil::noExtraModelOrState) + .simpleItem() + .tag(BlockTags.MINEABLE_WITH_PICKAXE, BlockTags.NEEDS_IRON_TOOL) + .recipe((ctx, provider) -> ShapedRecipeBuilder.shaped(RecipeCategory.BUILDING_BLOCKS, ctx.get()) + .pattern(" K ") + .pattern(" J ") + .pattern(" M ") + .define('K', AddonItems.KARAKURI_COMPONENT) + .define('J', ModBlocks.JEWEL_CRAFTING_TABLE) + .define('M', ModBlocks.MAGNETO_ELECTRIC_CORE_BLOCK) + .unlockedBy( + AnvilCraftDatagen.hasItem(ModBlocks.JEWEL_CRAFTING_TABLE), + AnvilCraftDatagen.has(ModBlocks.JEWEL_CRAFTING_TABLE) + ) + .save(provider)) + .register(); + public static final BlockEntry AUTO_ROYAL_SMITHING_TABLE_BLOCK = REGISTRATE .block("auto_royal_smithing_table", AutoRoyalSmithingTableBlock::new) .lang("Auto Royal Smithing Table") diff --git a/src/main/java/dev/anvilcraft/pigsplus/init/AddonMenuTypes.java b/src/main/java/dev/anvilcraft/pigsplus/init/AddonMenuTypes.java index 0fa3c4d..cc29e4a 100644 --- a/src/main/java/dev/anvilcraft/pigsplus/init/AddonMenuTypes.java +++ b/src/main/java/dev/anvilcraft/pigsplus/init/AddonMenuTypes.java @@ -1,9 +1,11 @@ package dev.anvilcraft.pigsplus.init; import com.tterrag.registrate.util.entry.MenuEntry; +import dev.anvilcraft.pigsplus.client.gui.screen.AutoJewelCraftingScreen; import dev.anvilcraft.pigsplus.client.gui.screen.AutoRoyalGrindstoneScreen; import dev.anvilcraft.pigsplus.client.gui.screen.AutoRoyalSmithingScreen; import dev.anvilcraft.pigsplus.client.gui.screen.ChainSmithingScreen; +import dev.anvilcraft.pigsplus.inventory.AutoJewelCraftingMenu; import dev.anvilcraft.pigsplus.inventory.AutoRoyalGrindstoneMenu; import dev.anvilcraft.pigsplus.inventory.AutoRoyalSmithingMenu; import dev.anvilcraft.pigsplus.inventory.ChainSmithingMenu; @@ -37,6 +39,10 @@ public class AddonMenuTypes { .menu("auto_royal_grindstone", AutoRoyalGrindstoneMenu::new, () -> AutoRoyalGrindstoneScreen::new) .register(); + public static final MenuEntry AUTO_JEWEL_CRAFTING = REGISTRATE + .menu("auto_jewel_crafting", AutoJewelCraftingMenu::new, () -> AutoJewelCraftingScreen::new) + .register(); + public static void register() { } diff --git a/src/main/java/dev/anvilcraft/pigsplus/inventory/AutoJewelCraftingMenu.java b/src/main/java/dev/anvilcraft/pigsplus/inventory/AutoJewelCraftingMenu.java new file mode 100644 index 0000000..916e84d --- /dev/null +++ b/src/main/java/dev/anvilcraft/pigsplus/inventory/AutoJewelCraftingMenu.java @@ -0,0 +1,199 @@ +package dev.anvilcraft.pigsplus.inventory; + +import dev.anvilcraft.pigsplus.block.entity.AutoJewelCraftingTableBlockEntity; +import dev.anvilcraft.pigsplus.init.AddonBlocks; +import dev.dubhe.anvilcraft.inventory.BaseMachineMenu; +import dev.dubhe.anvilcraft.inventory.component.ReadOnlySlot; +import dev.dubhe.anvilcraft.recipe.JewelCraftingRecipe; +import dev.dubhe.anvilcraft.recipe.anvil.cache.RecipeCaches; +import lombok.Getter; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.world.SimpleContainer; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.inventory.AbstractContainerMenu; +import net.minecraft.world.inventory.ContainerLevelAccess; +import net.minecraft.world.inventory.ContainerListener; +import net.minecraft.world.inventory.MenuType; +import net.minecraft.world.inventory.Slot; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.crafting.Ingredient; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.neoforged.neoforge.items.IItemHandler; +import net.neoforged.neoforge.items.SlotItemHandler; + +@Getter +public class AutoJewelCraftingMenu extends BaseMachineMenu implements ContainerListener { + public final AutoJewelCraftingTableBlockEntity blockEntity; + @Getter + private final Slot resultSlot; + private final Level level; + + public AutoJewelCraftingMenu( + MenuType menuType, int containerId, Inventory inventory, FriendlyByteBuf extraData + ) { + this(menuType, containerId, inventory, inventory.player.level().getBlockEntity(extraData.readBlockPos())); + } + + /** + * 合成器菜单 + * + * @param menuType 菜单类型 + * @param containerId 容器id + * @param inventory 背包 + * @param blockEntity 方块实体 + */ + public AutoJewelCraftingMenu(MenuType menuType, int containerId, Inventory inventory, BlockEntity blockEntity) { + super(menuType, containerId, blockEntity); + AutoJewelCraftingMenu.checkContainerSize(inventory, 9); + + this.blockEntity = (AutoJewelCraftingTableBlockEntity) blockEntity; + this.level = inventory.player.level(); + + this.addPlayerHotbar(inventory); + this.addPlayerInventory(inventory); + this.addMachine(); + this.addSlot(resultSlot = new ReadOnlySlot(new SimpleContainer(1), 0, 134, 51)); + + this.onChanged(); + this.addSlotListener(this); + } + + public class JewelCraftingSlotItemHandler extends SlotItemHandler { + public JewelCraftingSlotItemHandler(IItemHandler itemHandler, int index, int xPosition, int yPosition) { + super(itemHandler, index, xPosition, yPosition); + } + + @Override + public boolean mayPlace(ItemStack stack) { + // slot 0 是源物品槽位 + int slot = this.index; + if (slot == 0) { + if (RecipeCaches.getAllJewelResultItem().contains(stack.getItem())) { + return super.mayPlace(stack); + } + } + JewelCraftingRecipe resultRecipe = blockEntity.getResultRecipe(); + if (resultRecipe != null) { + int idx = slot - 1; + var mergedIngredients = resultRecipe.mergedIngredients; + if (idx < mergedIngredients.size()) { + var entry = mergedIngredients.get(idx); + Ingredient ingredient = entry.getKey(); + if (ingredient.test(stack)) { + return super.mayPlace(stack); + } + } + } + return false; + } + } + + private void addMachine() { + this.addSlot(new JewelCraftingSlotItemHandler(this.blockEntity.getItemHandler(), 0, 80, 19)); + for (int i = 0; i < 4; i++) { + addSlot(new JewelCraftingSlotItemHandler(this.blockEntity.getItemHandler(), i + 1, 26 + i * 18, 51)); + } + } + + private void addPlayerInventory(Inventory playerInventory) { + for (int i = 0; i < 3; ++i) { + for (int l = 0; l < 9; ++l) { + this.addSlot(new Slot(playerInventory, l + i * 9 + 9, 8 + l * 18, 84 + i * 18)); + } + } + } + + private void addPlayerHotbar(Inventory playerInventory) { + for (int i = 0; i < 9; ++i) { + this.addSlot(new Slot(playerInventory, i, 8 + i * 18, 142)); + } + } + + private void onChanged() { + blockEntity.calcResult(); + this.resultSlot.set(blockEntity.getResultStack()); + } + + public static final int HOTBAR_SLOT_COUNT = 9; + public static final int PLAYER_INVENTORY_ROW_COUNT = 3; + public static final int PLAYER_INVENTORY_COLUMN_COUNT = 9; + public static final int PLAYER_INVENTORY_SLOT_COUNT = PLAYER_INVENTORY_COLUMN_COUNT * PLAYER_INVENTORY_ROW_COUNT; + public static final int VANILLA_SLOT_COUNT = HOTBAR_SLOT_COUNT + PLAYER_INVENTORY_SLOT_COUNT; + public static final int VANILLA_FIRST_SLOT_INDEX = 0; + public static final int TE_INVENTORY_FIRST_SLOT_INDEX = VANILLA_FIRST_SLOT_INDEX + VANILLA_SLOT_COUNT; + + // THIS YOU HAVE TO DEFINE! + private static final int TE_INVENTORY_SLOT_COUNT = 5; // must be the number of slots you have! + + + @Override + public ItemStack quickMoveStack(Player player, int index) { + Slot sourceSlot = slots.get(index); + if (!sourceSlot.hasItem()) { + return ItemStack.EMPTY; // EMPTY_ITEM + } + ItemStack sourceStack = sourceSlot.getItem(); + final ItemStack copyOfSourceStack = sourceStack.copy(); + + //noinspection ConstantValue + if (sourceSlot == null || !sourceSlot.hasItem()) { + return ItemStack.EMPTY; + } + if (index < TE_INVENTORY_FIRST_SLOT_INDEX) { + if (!moveItemToActiveSlot(sourceStack)) { + return ItemStack.EMPTY; + } + } else if (index < TE_INVENTORY_FIRST_SLOT_INDEX + TE_INVENTORY_SLOT_COUNT) { + if (!moveItemStackTo( + sourceStack, + VANILLA_FIRST_SLOT_INDEX, + TE_INVENTORY_FIRST_SLOT_INDEX, + false + )) { + return ItemStack.EMPTY; + } + } else { + return ItemStack.EMPTY; + } + // If stack size == 0 (the entire stack was moved) set slot contents to null + if (sourceStack.getCount() == 0) { + sourceSlot.set(ItemStack.EMPTY); + } else { + sourceSlot.setChanged(); + } + sourceSlot.onTake(player, sourceStack); + return copyOfSourceStack; + } + + @Override + public boolean stillValid(Player player) { + return stillValid( + ContainerLevelAccess.create(level, blockEntity.getPos()), + player, + AddonBlocks.AUTO_JEWEL_CRAFTING_TABLE_BLOCK.get() + ); + } + + // 移动物品到可用槽位 + private boolean moveItemToActiveSlot(ItemStack stack) { + int start_index = TE_INVENTORY_FIRST_SLOT_INDEX; + int count = stack.getCount(); + if (RecipeCaches.getAllJewelResultItem().contains(stack.getItem())) { + moveItemStackTo(stack, start_index, start_index + TE_INVENTORY_SLOT_COUNT, false); + } else { + moveItemStackTo(stack, start_index + 1, start_index + TE_INVENTORY_SLOT_COUNT, false); + } + return stack.getCount() < count; + } + + @Override + public void slotChanged(AbstractContainerMenu abstractContainerMenu, int i, ItemStack itemStack) { + onChanged(); + } + + @Override + public void dataChanged(AbstractContainerMenu abstractContainerMenu, int i, int i1) { + } +} \ No newline at end of file diff --git a/src/main/java/dev/anvilcraft/pigsplus/inventory/AutoRoyalGrindstoneMenu.java b/src/main/java/dev/anvilcraft/pigsplus/inventory/AutoRoyalGrindstoneMenu.java index d04b525..00f4bc8 100644 --- a/src/main/java/dev/anvilcraft/pigsplus/inventory/AutoRoyalGrindstoneMenu.java +++ b/src/main/java/dev/anvilcraft/pigsplus/inventory/AutoRoyalGrindstoneMenu.java @@ -106,7 +106,7 @@ private void onChanged() { private static final int TE_INVENTORY_SLOT_COUNT = 2; // must be the number of slots you have! @Override - public ItemStack quickMoveStack(Player playerIn, int index) { + public ItemStack quickMoveStack(Player player, int index) { Slot sourceSlot = slots.get(index); //noinspection ConstantValue if (sourceSlot == null || !sourceSlot.hasItem()) { @@ -139,7 +139,7 @@ public ItemStack quickMoveStack(Player playerIn, int index) { } else { sourceSlot.setChanged(); } - sourceSlot.onTake(playerIn, sourceStack); + sourceSlot.onTake(player, sourceStack); return copyOfSourceStack; } diff --git a/src/main/java/dev/anvilcraft/pigsplus/inventory/AutoRoyalSmithingMenu.java b/src/main/java/dev/anvilcraft/pigsplus/inventory/AutoRoyalSmithingMenu.java index 990cbb4..350983d 100644 --- a/src/main/java/dev/anvilcraft/pigsplus/inventory/AutoRoyalSmithingMenu.java +++ b/src/main/java/dev/anvilcraft/pigsplus/inventory/AutoRoyalSmithingMenu.java @@ -108,7 +108,7 @@ private void onChanged() { private static final int TE_INVENTORY_SLOT_COUNT = 3; // must be the number of slots you have! @Override - public ItemStack quickMoveStack(Player playerIn, int index) { + public ItemStack quickMoveStack(Player player, int index) { Slot sourceSlot = slots.get(index); //noinspection ConstantValue if (sourceSlot == null || !sourceSlot.hasItem()) { @@ -141,7 +141,7 @@ public ItemStack quickMoveStack(Player playerIn, int index) { } else { sourceSlot.setChanged(); } - sourceSlot.onTake(playerIn, sourceStack); + sourceSlot.onTake(player, sourceStack); return copyOfSourceStack; } diff --git a/src/main/resources/assets/anvilcraft_pigsplus/blockstates/auto_jewel_crafting_table.json b/src/main/resources/assets/anvilcraft_pigsplus/blockstates/auto_jewel_crafting_table.json new file mode 100644 index 0000000..29479ce --- /dev/null +++ b/src/main/resources/assets/anvilcraft_pigsplus/blockstates/auto_jewel_crafting_table.json @@ -0,0 +1,7 @@ +{ + "variants": { + "": { + "model": "anvilcraft_pigsplus:block/auto_jewel_crafting_table" + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/anvilcraft_pigsplus/lang/zh_cn.json b/src/main/resources/assets/anvilcraft_pigsplus/lang/zh_cn.json index 1e8f995..f8357ee 100644 --- a/src/main/resources/assets/anvilcraft_pigsplus/lang/zh_cn.json +++ b/src/main/resources/assets/anvilcraft_pigsplus/lang/zh_cn.json @@ -32,6 +32,7 @@ "anvilcraft_pigsplus.configuration.section.anvilcraft_pigsplus.server.toml": "铁砧工艺:猪+ 服务端配置", "anvilcraft_pigsplus.configuration.section.anvilcraft_pigsplus.server.toml.title": "铁砧工艺:猪+ 服务端配置", "anvilcraft_pigsplus.configuration.title": "铁砧工艺:猪+ 配置", + "block.anvilcraft_pigsplus.auto_jewel_crafting_table": "自动珠宝加工台", "block.anvilcraft_pigsplus.auto_royal_grindstone": "自动皇家砂轮", "block.anvilcraft_pigsplus.auto_royal_smithing_table": "自动皇家锻造台", "block.anvilcraft_pigsplus.block_breaker": "方块破坏器", diff --git a/src/main/resources/assets/anvilcraft_pigsplus/models/block/auto_jewel_crafting_table.json b/src/main/resources/assets/anvilcraft_pigsplus/models/block/auto_jewel_crafting_table.json new file mode 100644 index 0000000..d980b25 --- /dev/null +++ b/src/main/resources/assets/anvilcraft_pigsplus/models/block/auto_jewel_crafting_table.json @@ -0,0 +1,25 @@ +{ + "format_version": "1.21.6", + "credit": "Made with Blockbench", + "parent": "minecraft:block/cube", + "textures": { + "0": "anvilcraft_pigsplus:block/auto_jewel_crafting_table_side", + "1": "anvilcraft_pigsplus:block/auto_jewel_crafting_table_top", + "2": "anvilcraft_pigsplus:block/auto_jewel_crafting_table_bottom", + "particle": "anvilcraft_pigsplus:block/auto_jewel_crafting_table_side" + }, + "elements": [ + { + "from": [0, 0, 0], + "to": [16, 16, 16], + "faces": { + "north": {"uv": [0, 0, 16, 16], "texture": "#0"}, + "east": {"uv": [0, 0, 16, 16], "texture": "#0"}, + "south": {"uv": [0, 0, 16, 16], "texture": "#0"}, + "west": {"uv": [0, 0, 16, 16], "texture": "#0"}, + "up": {"uv": [0, 0, 16, 16], "texture": "#1"}, + "down": {"uv": [0, 0, 16, 16], "texture": "#2"} + } + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/anvilcraft_pigsplus/textures/block/auto_jewel_crafting_table_bottom.png b/src/main/resources/assets/anvilcraft_pigsplus/textures/block/auto_jewel_crafting_table_bottom.png new file mode 100644 index 0000000..c0ed50f Binary files /dev/null and b/src/main/resources/assets/anvilcraft_pigsplus/textures/block/auto_jewel_crafting_table_bottom.png differ diff --git a/src/main/resources/assets/anvilcraft_pigsplus/textures/block/auto_jewel_crafting_table_side.png b/src/main/resources/assets/anvilcraft_pigsplus/textures/block/auto_jewel_crafting_table_side.png new file mode 100644 index 0000000..b5999b1 Binary files /dev/null and b/src/main/resources/assets/anvilcraft_pigsplus/textures/block/auto_jewel_crafting_table_side.png differ diff --git a/src/main/resources/assets/anvilcraft_pigsplus/textures/block/auto_jewel_crafting_table_top.png b/src/main/resources/assets/anvilcraft_pigsplus/textures/block/auto_jewel_crafting_table_top.png new file mode 100644 index 0000000..03d00fb Binary files /dev/null and b/src/main/resources/assets/anvilcraft_pigsplus/textures/block/auto_jewel_crafting_table_top.png differ