package net.minecraft.world.entity.vehicle; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.particles.ParticleTypes; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.syncher.EntityDataAccessor; import net.minecraft.network.syncher.EntityDataSerializers; import net.minecraft.network.syncher.SynchedEntityData; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; import net.minecraft.world.item.crafting.Ingredient; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.FurnaceBlock; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.Vec3; public class MinecartFurnace extends AbstractMinecart { private static final EntityDataAccessor DATA_ID_FUEL = SynchedEntityData.defineId(MinecartFurnace.class, EntityDataSerializers.BOOLEAN); private int fuel; public double xPush; public double zPush; /** * The fuel item used to make the minecart move. */ private static final Ingredient INGREDIENT = Ingredient.of(Items.COAL, Items.CHARCOAL); public MinecartFurnace(EntityType entityType, Level level) { super(entityType, level); } public MinecartFurnace(Level level, double x, double y, double z) { super(EntityType.FURNACE_MINECART, level, x, y, z); } @Override public AbstractMinecart.Type getMinecartType() { return AbstractMinecart.Type.FURNACE; } @Override protected void defineSynchedData(SynchedEntityData.Builder builder) { super.defineSynchedData(builder); builder.define(DATA_ID_FUEL, false); } @Override public void tick() { super.tick(); if (!this.level().isClientSide()) { if (this.fuel > 0) { this.fuel--; } if (this.fuel <= 0) { this.xPush = 0.0; this.zPush = 0.0; } this.setHasFuel(this.fuel > 0); } if (this.hasFuel() && this.random.nextInt(4) == 0) { this.level().addParticle(ParticleTypes.LARGE_SMOKE, this.getX(), this.getY() + 0.8, this.getZ(), 0.0, 0.0, 0.0); } } @Override protected double getMaxSpeed() { return (this.isInWater() ? 3.0 : 4.0) / 20.0; } @Override protected Item getDropItem() { return Items.FURNACE_MINECART; } @Override protected void moveAlongTrack(BlockPos pos, BlockState state) { double d = 1.0E-4; double e = 0.001; super.moveAlongTrack(pos, state); Vec3 vec3 = this.getDeltaMovement(); double f = vec3.horizontalDistanceSqr(); double g = this.xPush * this.xPush + this.zPush * this.zPush; if (g > 1.0E-4 && f > 0.001) { double h = Math.sqrt(f); double i = Math.sqrt(g); this.xPush = vec3.x / h * i; this.zPush = vec3.z / h * i; } } @Override protected void applyNaturalSlowdown() { double d = this.xPush * this.xPush + this.zPush * this.zPush; if (d > 1.0E-7) { d = Math.sqrt(d); this.xPush /= d; this.zPush /= d; Vec3 vec3 = this.getDeltaMovement().multiply(0.8, 0.0, 0.8).add(this.xPush, 0.0, this.zPush); if (this.isInWater()) { vec3 = vec3.scale(0.1); } this.setDeltaMovement(vec3); } else { this.setDeltaMovement(this.getDeltaMovement().multiply(0.98, 0.0, 0.98)); } super.applyNaturalSlowdown(); } @Override public InteractionResult interact(Player player, InteractionHand hand) { ItemStack itemStack = player.getItemInHand(hand); if (INGREDIENT.test(itemStack) && this.fuel + 3600 <= 32000) { itemStack.consume(1, player); this.fuel += 3600; } if (this.fuel > 0) { this.xPush = this.getX() - player.getX(); this.zPush = this.getZ() - player.getZ(); } return InteractionResult.sidedSuccess(this.level().isClientSide); } @Override protected void addAdditionalSaveData(CompoundTag compound) { super.addAdditionalSaveData(compound); compound.putDouble("PushX", this.xPush); compound.putDouble("PushZ", this.zPush); compound.putShort("Fuel", (short)this.fuel); } @Override protected void readAdditionalSaveData(CompoundTag compound) { super.readAdditionalSaveData(compound); this.xPush = compound.getDouble("PushX"); this.zPush = compound.getDouble("PushZ"); this.fuel = compound.getShort("Fuel"); } protected boolean hasFuel() { return this.entityData.get(DATA_ID_FUEL); } protected void setHasFuel(boolean hasFuel) { this.entityData.set(DATA_ID_FUEL, hasFuel); } @Override public BlockState getDefaultDisplayBlockState() { return Blocks.FURNACE.defaultBlockState().setValue(FurnaceBlock.FACING, Direction.NORTH).setValue(FurnaceBlock.LIT, this.hasFuel()); } }