211 lines
7.6 KiB
Java
211 lines
7.6 KiB
Java
package net.minecraft.world.level.block.entity;
|
|
|
|
import java.util.Optional;
|
|
import net.minecraft.core.BlockPos;
|
|
import net.minecraft.core.Direction;
|
|
import net.minecraft.core.NonNullList;
|
|
import net.minecraft.core.HolderLookup.Provider;
|
|
import net.minecraft.core.component.DataComponents;
|
|
import net.minecraft.core.component.DataComponentMap.Builder;
|
|
import net.minecraft.core.particles.ParticleTypes;
|
|
import net.minecraft.nbt.CompoundTag;
|
|
import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket;
|
|
import net.minecraft.server.level.ServerLevel;
|
|
import net.minecraft.util.Mth;
|
|
import net.minecraft.util.RandomSource;
|
|
import net.minecraft.world.Clearable;
|
|
import net.minecraft.world.ContainerHelper;
|
|
import net.minecraft.world.Containers;
|
|
import net.minecraft.world.entity.LivingEntity;
|
|
import net.minecraft.world.item.ItemStack;
|
|
import net.minecraft.world.item.component.ItemContainerContents;
|
|
import net.minecraft.world.item.crafting.CampfireCookingRecipe;
|
|
import net.minecraft.world.item.crafting.RecipeHolder;
|
|
import net.minecraft.world.item.crafting.RecipeManager;
|
|
import net.minecraft.world.item.crafting.RecipeType;
|
|
import net.minecraft.world.item.crafting.SingleRecipeInput;
|
|
import net.minecraft.world.level.Level;
|
|
import net.minecraft.world.level.block.CampfireBlock;
|
|
import net.minecraft.world.level.block.state.BlockState;
|
|
import net.minecraft.world.level.gameevent.GameEvent;
|
|
import net.minecraft.world.level.gameevent.GameEvent.Context;
|
|
import org.jetbrains.annotations.Nullable;
|
|
|
|
public class CampfireBlockEntity extends BlockEntity implements Clearable {
|
|
private static final int BURN_COOL_SPEED = 2;
|
|
private static final int NUM_SLOTS = 4;
|
|
private final NonNullList<ItemStack> items = NonNullList.withSize(4, ItemStack.EMPTY);
|
|
private final int[] cookingProgress = new int[4];
|
|
private final int[] cookingTime = new int[4];
|
|
|
|
public CampfireBlockEntity(BlockPos pos, BlockState blockState) {
|
|
super(BlockEntityType.CAMPFIRE, pos, blockState);
|
|
}
|
|
|
|
public static void cookTick(
|
|
ServerLevel level, BlockPos pos, BlockState state, CampfireBlockEntity campfire, RecipeManager.CachedCheck<SingleRecipeInput, CampfireCookingRecipe> check
|
|
) {
|
|
boolean bl = false;
|
|
|
|
for (int i = 0; i < campfire.items.size(); i++) {
|
|
ItemStack itemStack = campfire.items.get(i);
|
|
if (!itemStack.isEmpty()) {
|
|
bl = true;
|
|
campfire.cookingProgress[i]++;
|
|
if (campfire.cookingProgress[i] >= campfire.cookingTime[i]) {
|
|
SingleRecipeInput singleRecipeInput = new SingleRecipeInput(itemStack);
|
|
ItemStack itemStack2 = (ItemStack)check.getRecipeFor(singleRecipeInput, level)
|
|
.map(recipeHolder -> ((CampfireCookingRecipe)recipeHolder.value()).assemble(singleRecipeInput, level.registryAccess()))
|
|
.orElse(itemStack);
|
|
if (itemStack2.isItemEnabled(level.enabledFeatures())) {
|
|
Containers.dropItemStack(level, pos.getX(), pos.getY(), pos.getZ(), itemStack2);
|
|
campfire.items.set(i, ItemStack.EMPTY);
|
|
level.sendBlockUpdated(pos, state, state, 3);
|
|
level.gameEvent(GameEvent.BLOCK_CHANGE, pos, Context.of(state));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (bl) {
|
|
setChanged(level, pos, state);
|
|
}
|
|
}
|
|
|
|
public static void cooldownTick(Level level, BlockPos pos, BlockState state, CampfireBlockEntity blockEntity) {
|
|
boolean bl = false;
|
|
|
|
for (int i = 0; i < blockEntity.items.size(); i++) {
|
|
if (blockEntity.cookingProgress[i] > 0) {
|
|
bl = true;
|
|
blockEntity.cookingProgress[i] = Mth.clamp(blockEntity.cookingProgress[i] - 2, 0, blockEntity.cookingTime[i]);
|
|
}
|
|
}
|
|
|
|
if (bl) {
|
|
setChanged(level, pos, state);
|
|
}
|
|
}
|
|
|
|
public static void particleTick(Level level, BlockPos pos, BlockState state, CampfireBlockEntity blockEntity) {
|
|
RandomSource randomSource = level.random;
|
|
if (randomSource.nextFloat() < 0.11F) {
|
|
for (int i = 0; i < randomSource.nextInt(2) + 2; i++) {
|
|
CampfireBlock.makeParticles(level, pos, (Boolean)state.getValue(CampfireBlock.SIGNAL_FIRE), false);
|
|
}
|
|
}
|
|
|
|
int i = ((Direction)state.getValue(CampfireBlock.FACING)).get2DDataValue();
|
|
|
|
for (int j = 0; j < blockEntity.items.size(); j++) {
|
|
if (!blockEntity.items.get(j).isEmpty() && randomSource.nextFloat() < 0.2F) {
|
|
Direction direction = Direction.from2DDataValue(Math.floorMod(j + i, 4));
|
|
float f = 0.3125F;
|
|
double d = pos.getX() + 0.5 - direction.getStepX() * 0.3125F + direction.getClockWise().getStepX() * 0.3125F;
|
|
double e = pos.getY() + 0.5;
|
|
double g = pos.getZ() + 0.5 - direction.getStepZ() * 0.3125F + direction.getClockWise().getStepZ() * 0.3125F;
|
|
|
|
for (int k = 0; k < 4; k++) {
|
|
level.addParticle(ParticleTypes.SMOKE, d, e, g, 0.0, 5.0E-4, 0.0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @return the items currently held in this campfire
|
|
*/
|
|
public NonNullList<ItemStack> getItems() {
|
|
return this.items;
|
|
}
|
|
|
|
@Override
|
|
protected void loadAdditional(CompoundTag tag, Provider registries) {
|
|
super.loadAdditional(tag, registries);
|
|
this.items.clear();
|
|
ContainerHelper.loadAllItems(tag, this.items, registries);
|
|
if (tag.contains("CookingTimes", 11)) {
|
|
int[] is = tag.getIntArray("CookingTimes");
|
|
System.arraycopy(is, 0, this.cookingProgress, 0, Math.min(this.cookingTime.length, is.length));
|
|
}
|
|
|
|
if (tag.contains("CookingTotalTimes", 11)) {
|
|
int[] is = tag.getIntArray("CookingTotalTimes");
|
|
System.arraycopy(is, 0, this.cookingTime, 0, Math.min(this.cookingTime.length, is.length));
|
|
}
|
|
}
|
|
|
|
@Override
|
|
protected void saveAdditional(CompoundTag tag, Provider registries) {
|
|
super.saveAdditional(tag, registries);
|
|
ContainerHelper.saveAllItems(tag, this.items, true, registries);
|
|
tag.putIntArray("CookingTimes", this.cookingProgress);
|
|
tag.putIntArray("CookingTotalTimes", this.cookingTime);
|
|
}
|
|
|
|
public ClientboundBlockEntityDataPacket getUpdatePacket() {
|
|
return ClientboundBlockEntityDataPacket.create(this);
|
|
}
|
|
|
|
@Override
|
|
public CompoundTag getUpdateTag(Provider registries) {
|
|
CompoundTag compoundTag = new CompoundTag();
|
|
ContainerHelper.saveAllItems(compoundTag, this.items, true, registries);
|
|
return compoundTag;
|
|
}
|
|
|
|
public boolean placeFood(ServerLevel level, @Nullable LivingEntity entity, ItemStack stack) {
|
|
for (int i = 0; i < this.items.size(); i++) {
|
|
ItemStack itemStack = this.items.get(i);
|
|
if (itemStack.isEmpty()) {
|
|
Optional<RecipeHolder<CampfireCookingRecipe>> optional = level.recipeAccess()
|
|
.getRecipeFor(RecipeType.CAMPFIRE_COOKING, new SingleRecipeInput(stack), level);
|
|
if (optional.isEmpty()) {
|
|
return false;
|
|
}
|
|
|
|
this.cookingTime[i] = ((CampfireCookingRecipe)((RecipeHolder)optional.get()).value()).cookingTime();
|
|
this.cookingProgress[i] = 0;
|
|
this.items.set(i, stack.consumeAndReturn(1, entity));
|
|
level.gameEvent(GameEvent.BLOCK_CHANGE, this.getBlockPos(), Context.of(entity, this.getBlockState()));
|
|
this.markUpdated();
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
private void markUpdated() {
|
|
this.setChanged();
|
|
this.getLevel().sendBlockUpdated(this.getBlockPos(), this.getBlockState(), this.getBlockState(), 3);
|
|
}
|
|
|
|
@Override
|
|
public void clearContent() {
|
|
this.items.clear();
|
|
}
|
|
|
|
public void dowse() {
|
|
if (this.level != null) {
|
|
this.markUpdated();
|
|
}
|
|
}
|
|
|
|
@Override
|
|
protected void applyImplicitComponents(BlockEntity.DataComponentInput componentInput) {
|
|
super.applyImplicitComponents(componentInput);
|
|
componentInput.getOrDefault(DataComponents.CONTAINER, ItemContainerContents.EMPTY).copyInto(this.getItems());
|
|
}
|
|
|
|
@Override
|
|
protected void collectImplicitComponents(Builder components) {
|
|
super.collectImplicitComponents(components);
|
|
components.set(DataComponents.CONTAINER, ItemContainerContents.fromItems(this.getItems()));
|
|
}
|
|
|
|
@Override
|
|
public void removeComponentsFromTag(CompoundTag tag) {
|
|
tag.remove("Items");
|
|
}
|
|
}
|