Skip to content

Commit

Permalink
完善自动锻造台代码
Browse files Browse the repository at this point in the history
  • Loading branch information
YipKei committed Aug 25, 2024
1 parent 2bac513 commit e997af6
Show file tree
Hide file tree
Showing 10 changed files with 271 additions and 51 deletions.
6 changes: 2 additions & 4 deletions src/main/java/com/yipkei/vanilladdition/VanillaAddition.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
package com.yipkei.vanilladdition;

import com.yipkei.vanilladdition.custom.ModDispenserBehavior;
import com.yipkei.vanilladdition.init.ModBlockEntityType;
import com.yipkei.vanilladdition.init.ModBlocks;
import com.yipkei.vanilladdition.init.ModItemGroups;
import com.yipkei.vanilladdition.init.ModItems;
import com.yipkei.vanilladdition.init.*;
import com.yipkei.vanilladdition.livingentity.villager.ModVillagers;
import com.yipkei.vanilladdition.util.ModLootTableModifiers;
import com.yipkei.vanilladdition.util.VanillaTradeModifiers;
Expand Down Expand Up @@ -35,6 +32,7 @@ public void onInitialize() {
ModItemGroups.registerModItemGroup();
ModVillagers.registerModVillagers();
ModBlockEntityType.registerBlockEntities();
ModScreenHandlerType.registerScreenHandlerType();

ModLootTableModifiers.modifierLootTables();
VanillaTradeModifiers.registerVanillaVillageTrades();
Expand Down
159 changes: 140 additions & 19 deletions src/main/java/com/yipkei/vanilladdition/block/SmitherBlock.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,45 @@

import com.mojang.serialization.MapCodec;
import com.yipkei.vanilladdition.block.entity.SmitherBlockEntity;
import net.minecraft.block.AbstractBlock;
import com.yipkei.vanilladdition.init.ModBlockEntityType;
import net.minecraft.block.Block;
import net.minecraft.block.BlockRenderType;
import net.minecraft.block.BlockState;
import net.minecraft.block.BlockWithEntity;
import net.minecraft.block.dispenser.ItemDispenserBehavior;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.block.entity.BlockEntityTicker;
import net.minecraft.block.entity.BlockEntityType;
import net.minecraft.block.entity.HopperBlockEntity;
import net.minecraft.block.enums.Orientation;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.inventory.Inventory;
import net.minecraft.item.ItemPlacementContext;
import net.minecraft.item.ItemStack;
import net.minecraft.recipe.RecipeEntry;
import net.minecraft.recipe.RecipeType;
import net.minecraft.recipe.SmithingRecipe;
import net.minecraft.recipe.input.SmithingRecipeInput;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.state.StateManager;
import net.minecraft.state.property.BooleanProperty;
import net.minecraft.state.property.EnumProperty;
import net.minecraft.state.property.Properties;
import net.minecraft.util.ActionResult;
import net.minecraft.util.BlockMirror;
import net.minecraft.util.BlockRotation;
import net.minecraft.util.ItemScatterer;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.math.random.Random;
import net.minecraft.world.World;
import net.minecraft.world.WorldEvents;
import org.jetbrains.annotations.Nullable;

import java.util.List;
import java.util.Optional;

public class SmitherBlock extends BlockWithEntity {
Expand All @@ -35,7 +52,7 @@ public class SmitherBlock extends BlockWithEntity {

private static final int TRIGGER_DELAY = 4;

public SmitherBlock(AbstractBlock.Settings settings) {
public SmitherBlock(Settings settings) {
super(settings);
this.setDefaultState(this.stateManager.getDefaultState().with(ORIENTATION, Orientation.NORTH_UP).with(TRIGGERED, false).with(SMITHING, false));
}
Expand All @@ -45,6 +62,42 @@ public SmitherBlock(AbstractBlock.Settings settings) {
@Override
protected boolean hasComparatorOutput(BlockState state) { return true; }

@Override
protected int getComparatorOutput(BlockState state, World world, BlockPos pos) {
BlockEntity blockEntity = world.getBlockEntity(pos);
if (blockEntity instanceof SmitherBlockEntity smitherBlockEntity) {
return smitherBlockEntity.getComparatorOutput();
}
return 0;
}

@Override
protected void neighborUpdate(BlockState state, World world, BlockPos pos, Block sourceBlock, BlockPos sourcePos, boolean notify) {
boolean bl = world.isReceivingRedstonePower(pos);
boolean bl2 = state.get(TRIGGERED);
BlockEntity blockEntity = world.getBlockEntity(pos);
if (bl && !bl2) {
world.scheduleBlockTick(pos, this, TRIGGER_DELAY);
world.setBlockState(pos, state.with(TRIGGERED, true), Block.NOTIFY_LISTENERS);
this.setTriggered(blockEntity, true);
} else if (!bl && bl2) {
world.setBlockState(pos, state.with(TRIGGERED, false).with(SMITHING, false), Block.NOTIFY_LISTENERS);
this.setTriggered(blockEntity, false);
}
}

@Override
protected void scheduledTick(BlockState state, ServerWorld world, BlockPos pos, Random random){
this.smith(state, world, pos);
System.out.println("scheduledTick");
}

@Override
@Nullable
public <T extends BlockEntity> BlockEntityTicker<T> getTicker(World world, BlockState state, BlockEntityType<T> type) {
return world.isClient ? null : SmitherBlock.validateTicker(type, ModBlockEntityType.SMITHER, SmitherBlockEntity::tickSmithing);
}

private void setTriggered(@Nullable BlockEntity blockEntity, boolean triggered) {
if (blockEntity instanceof SmitherBlockEntity smitherBlockEntity) {
smitherBlockEntity.setTriggered(triggered);
Expand All @@ -62,7 +115,6 @@ public BlockEntity createBlockEntity(BlockPos pos, BlockState state) {
public BlockState getPlacementState(ItemPlacementContext ctx) {
Direction direction = ctx.getPlayerLookDirection().getOpposite();
Direction direction2 = switch (direction) {
default -> throw new MatchException(null, null);
case UP -> ctx.getHorizontalPlayerFacing();
case DOWN -> ctx.getHorizontalPlayerFacing().getOpposite();
case EAST, SOUTH, WEST, NORTH -> Direction.UP;
Expand All @@ -78,35 +130,104 @@ public void onPlaced(World world, BlockPos pos, BlockState state, LivingEntity p
}

@Override
protected void neighborUpdate(BlockState state, World world, BlockPos pos, Block sourceBlock, BlockPos sourcePos, boolean notify) {
boolean bl = world.isReceivingRedstonePower(pos);
boolean bl2 = state.get(TRIGGERED);
BlockEntity blockEntity = world.getBlockEntity(pos);
if (bl && !bl2) {
world.scheduleBlockTick(pos, this, TRIGGER_DELAY);
world.setBlockState(pos, state.with(TRIGGERED, true), Block.NOTIFY_LISTENERS);
this.setTriggered(blockEntity, true);
} else if (!bl && bl2) {
while (world.setBlockState(pos, state.with(TRIGGERED, false).with(SMITHING, false), Block.NOTIFY_LISTENERS));
this.setTriggered(blockEntity, false);
}
protected void onStateReplaced(BlockState state, World world, BlockPos pos, BlockState newState, boolean moved) {
ItemScatterer.onStateReplaced(state, newState, world, pos);
super.onStateReplaced(state, world, pos, newState, moved);
}

@Override
protected void scheduledTick(BlockState state, ServerWorld world, BlockPos pos, Random random){
this.smith(state, world, pos);
protected ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, BlockHitResult hit) {
if (world.isClient) {
return ActionResult.SUCCESS;
}
BlockEntity blockEntity = world.getBlockEntity(pos);
if (blockEntity instanceof SmitherBlockEntity) {
player.openHandledScreen((SmitherBlockEntity)blockEntity);
}
return ActionResult.CONSUME;
}

protected void smith(BlockState state, ServerWorld world, BlockPos pos) {
System.out.println("smith start");
BlockEntity blockEntity = world.getBlockEntity(pos);
if (!(blockEntity instanceof SmitherBlockEntity smitherBlockEntity)) return;
SmithingRecipeInput smithingRecipeInput = new SmithingRecipeInput(((SmitherBlockEntity) blockEntity).getStack(0), ((SmitherBlockEntity) blockEntity).getStack(1), ((SmitherBlockEntity) blockEntity).getStack(2));
System.out.println(smithingRecipeInput.getStackInSlot(0));
Optional<RecipeEntry<SmithingRecipe>> optional = SmitherBlock.getSmithingRecipe(world, smithingRecipeInput);
System.out.println(optional);
if (optional.isEmpty()) {
world.syncWorldEvent(WorldEvents.CRAFTER_FAILS, pos, 0);
return;
}
RecipeEntry<SmithingRecipe> recipeEntry = optional.get();
ItemStack itemStack = recipeEntry.value().craft(smithingRecipeInput, world.getRegistryManager());
if (itemStack.isEmpty()) {
world.syncWorldEvent(WorldEvents.CRAFTER_FAILS, pos, 0);
return;
}
smitherBlockEntity.setSmithingTicksRemaining(6);
world.setBlockState(pos, state.with(SMITHING, true), Block.NOTIFY_LISTENERS);
itemStack.onCraftByCrafter(world);
this.transferOrSpawnStack(world, pos, smitherBlockEntity, itemStack, state, recipeEntry);
for (ItemStack itemStack2 : recipeEntry.value().getRemainder(smithingRecipeInput)) {
if (itemStack2.isEmpty()) continue;
this.transferOrSpawnStack(world, pos, smitherBlockEntity, itemStack2, state, recipeEntry);
}
smitherBlockEntity.getHeldStacks().forEach(stack -> {
if (stack.isEmpty()) {
return;
}
stack.decrement(1);
});
smitherBlockEntity.markDirty();
}

public static Optional<RecipeEntry<SmithingRecipe>> getSmithingRecipe(World world, SmithingRecipeInput input) {
if (input.isEmpty()) return Optional.empty();
List<RecipeEntry<SmithingRecipe>> list = world.getRecipeManager().getAllMatches(RecipeType.SMITHING, input, world);
if (list.isEmpty()) return Optional.empty();
return Optional.ofNullable(list.getFirst());
}

private void transferOrSpawnStack(ServerWorld world, BlockPos pos, SmitherBlockEntity blockEntity, ItemStack stack, BlockState state, RecipeEntry<SmithingRecipe> recipe) {
Direction direction = state.get(ORIENTATION).getFacing();
Inventory inventory = HopperBlockEntity.getInventoryAt(world, pos.offset(direction));
ItemStack itemStack = stack.copy();
if (inventory != null && (inventory instanceof SmitherBlockEntity || stack.getCount() > inventory.getMaxCount(stack))) {
ItemStack itemStack2;
ItemStack itemStack3;
while (!itemStack.isEmpty() && (itemStack3 = HopperBlockEntity.transfer(blockEntity, inventory, itemStack2 = itemStack.copyWithCount(1), direction.getOpposite())).isEmpty()) {
itemStack.decrement(1);
}
} else if (inventory != null) {
int i ;
while (!itemStack.isEmpty() && (i = itemStack.getCount()) != (itemStack = HopperBlockEntity.transfer(blockEntity, inventory, itemStack, direction.getOpposite())).getCount()){

}
}
if (!itemStack.isEmpty()) {
Vec3d vec3d = Vec3d.ofCenter(pos);
Vec3d vec3d2 = vec3d.offset(direction, 0.7);
ItemDispenserBehavior.spawnItem(world, itemStack, 6, direction, vec3d2);
}
world.syncWorldEvent(WorldEvents.CRAFTER_CRAFTS, pos, 0);
world.syncWorldEvent(WorldEvents.CRAFTER_SHOOTS, pos, direction.getId());
}

@Override
protected BlockRenderType getRenderType(BlockState state) { return BlockRenderType.MODEL; }

return null;
@Override
protected BlockState rotate(BlockState state, BlockRotation rotation) {
return (BlockState)state.with(ORIENTATION, rotation.getDirectionTransformation().mapJigsawOrientation(state.get(ORIENTATION)));
}

@Override
protected BlockState mirror(BlockState state, BlockMirror mirror) {
return (BlockState)state.with(ORIENTATION, mirror.getDirectionTransformation().mapJigsawOrientation(state.get(ORIENTATION)));
}

@Override
protected void appendProperties(StateManager.Builder<Block, BlockState> builder){
builder.add(ORIENTATION, TRIGGERED, SMITHING);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

import com.yipkei.vanilladdition.block.SmitherBlock;
import com.yipkei.vanilladdition.block.screen.SmitherScreenHandler;
import com.yipkei.vanilladdition.init.ModBlockEntityType;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.entity.BlockEntityType;
import net.minecraft.block.entity.LootableContainerBlockEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.PlayerInventory;
Expand All @@ -15,6 +15,7 @@
import net.minecraft.nbt.NbtCompound;
import net.minecraft.recipe.RecipeMatcher;
import net.minecraft.registry.RegistryWrapper;
import net.minecraft.screen.PropertyDelegate;
import net.minecraft.screen.ScreenHandler;
import net.minecraft.screen.ScreenHandlerContext;
import net.minecraft.text.Text;
Expand All @@ -26,23 +27,53 @@ public class SmitherBlockEntity extends LootableContainerBlockEntity implements
public static final int GRID_SIZE = 3;
private DefaultedList<ItemStack> inputStacks = DefaultedList.ofSize(3, ItemStack.EMPTY);
private int smithingTicksRemaining = 0;
private boolean triggered = false;
protected final PropertyDelegate propertyDelegate = new PropertyDelegate() {
private int triggered = 0;

@Override
public int get(int index) {
return this.triggered;
}

@Override
public void set(int index, int value) {
this.triggered = value;
}

@Override
public int size() {
return 1;
}
};

public SmitherBlockEntity(BlockPos pos, BlockState state){
super(BlockEntityType.CRAFTER, pos, state);
super(ModBlockEntityType.SMITHER, pos, state);
}

protected Text getContainerName() { return Text.translatable("container.smither");}

@Override
protected ScreenHandler createScreenHandler(int syncId, PlayerInventory playerInventory) {
return new SmitherScreenHandler(syncId, playerInventory, this, this.triggered, ScreenHandlerContext.create(world, pos));
return new SmitherScreenHandler(syncId, playerInventory, this.propertyDelegate, ScreenHandlerContext.create(world, pos));
}

// setSlotEnabled & isSlotDisabled 设置与读取禁用槽位
// isValid 读取是否可用槽位,用于物品输入(通用)
// betterSlotExists 剩余槽位是否可用

@Override
public boolean isValid(int slot, ItemStack stack) {
ItemStack itemStack = this.inputStacks.get(slot);
int i = itemStack.getCount();
if (i >= itemStack.getMaxCount()) {
return false;
}
if (itemStack.isEmpty()) {
return true;
}
return super.isValid(slot, stack);
}

@Override
protected void readNbt(NbtCompound nbt, RegistryWrapper.WrapperLookup registryLookup) {
super.readNbt(nbt, registryLookup);
Expand All @@ -51,7 +82,7 @@ protected void readNbt(NbtCompound nbt, RegistryWrapper.WrapperLookup registryLo
if (!this.readLootTable(nbt)) {
Inventories.readNbt(nbt, this.inputStacks, registryLookup);
}
this.triggered = nbt.getBoolean("triggered");
this.propertyDelegate.set(0, nbt.getInt("triggered"));
}

@Override
Expand All @@ -61,7 +92,7 @@ protected void writeNbt(NbtCompound nbt, RegistryWrapper.WrapperLookup registryL
if (!this.writeLootTable(nbt)) {
Inventories.writeNbt(nbt, this.inputStacks, registryLookup);
}
nbt.putBoolean("triggered", this.triggered);
nbt.putInt("triggered", this.propertyDelegate.get(0));
}

@Override
Expand Down Expand Up @@ -119,11 +150,11 @@ public void provideRecipeInputs(RecipeMatcher finder) {


public void setTriggered(boolean triggered) {
this.triggered = triggered;
this.propertyDelegate.set(0, triggered ? 1 : 0);
}

public boolean isTriggered() {
return this.triggered;
return this.propertyDelegate.get(0) == 1;
}

public static void tickSmithing(World world, BlockPos pos, BlockState state, SmitherBlockEntity blockEntity) {
Expand Down
Loading

0 comments on commit e997af6

Please sign in to comment.