193 lines
8.1 KiB
Java
193 lines
8.1 KiB
Java
/*
|
|
* Decompiled with CFR 0.152.
|
|
*
|
|
* Could not load the following classes:
|
|
* com.google.common.collect.Iterables
|
|
* com.google.common.collect.Maps
|
|
* org.jspecify.annotations.Nullable
|
|
*/
|
|
package net.minecraft.world.item;
|
|
|
|
import com.google.common.collect.Iterables;
|
|
import com.google.common.collect.Maps;
|
|
import java.util.Map;
|
|
import java.util.Objects;
|
|
import java.util.Optional;
|
|
import net.minecraft.core.BlockPos;
|
|
import net.minecraft.core.Direction;
|
|
import net.minecraft.core.component.DataComponents;
|
|
import net.minecraft.network.chat.Component;
|
|
import net.minecraft.server.level.ServerLevel;
|
|
import net.minecraft.server.level.ServerPlayer;
|
|
import net.minecraft.server.permissions.Permissions;
|
|
import net.minecraft.stats.Stats;
|
|
import net.minecraft.world.Difficulty;
|
|
import net.minecraft.world.InteractionHand;
|
|
import net.minecraft.world.InteractionResult;
|
|
import net.minecraft.world.entity.AgeableMob;
|
|
import net.minecraft.world.entity.Entity;
|
|
import net.minecraft.world.entity.EntitySpawnReason;
|
|
import net.minecraft.world.entity.EntityType;
|
|
import net.minecraft.world.entity.LivingEntity;
|
|
import net.minecraft.world.entity.Mob;
|
|
import net.minecraft.world.entity.player.Player;
|
|
import net.minecraft.world.flag.FeatureFlagSet;
|
|
import net.minecraft.world.item.Item;
|
|
import net.minecraft.world.item.ItemStack;
|
|
import net.minecraft.world.item.component.TypedEntityData;
|
|
import net.minecraft.world.item.context.UseOnContext;
|
|
import net.minecraft.world.level.ClipContext;
|
|
import net.minecraft.world.level.Level;
|
|
import net.minecraft.world.level.Spawner;
|
|
import net.minecraft.world.level.block.LiquidBlock;
|
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
|
import net.minecraft.world.level.block.state.BlockState;
|
|
import net.minecraft.world.level.gameevent.GameEvent;
|
|
import net.minecraft.world.phys.BlockHitResult;
|
|
import net.minecraft.world.phys.HitResult;
|
|
import net.minecraft.world.phys.Vec3;
|
|
import org.jspecify.annotations.Nullable;
|
|
|
|
public class SpawnEggItem
|
|
extends Item {
|
|
private static final Map<EntityType<?>, SpawnEggItem> BY_ID = Maps.newIdentityHashMap();
|
|
|
|
public SpawnEggItem(Item.Properties properties) {
|
|
super(properties);
|
|
TypedEntityData<EntityType<?>> entityType = this.components().get(DataComponents.ENTITY_DATA);
|
|
if (entityType != null) {
|
|
BY_ID.put(entityType.type(), this);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public InteractionResult useOn(UseOnContext context) {
|
|
Level level = context.getLevel();
|
|
if (!(level instanceof ServerLevel)) {
|
|
return InteractionResult.SUCCESS;
|
|
}
|
|
ServerLevel serverLevel = (ServerLevel)level;
|
|
ItemStack itemStack = context.getItemInHand();
|
|
BlockPos pos = context.getClickedPos();
|
|
Direction clickedFace = context.getClickedFace();
|
|
BlockState blockState = level.getBlockState(pos);
|
|
BlockEntity blockEntity = level.getBlockEntity(pos);
|
|
if (blockEntity instanceof Spawner) {
|
|
Spawner spawnerHolder = (Spawner)((Object)blockEntity);
|
|
EntityType<?> type = this.getType(itemStack);
|
|
if (type == null) {
|
|
return InteractionResult.FAIL;
|
|
}
|
|
if (!serverLevel.isSpawnerBlockEnabled()) {
|
|
Player player = context.getPlayer();
|
|
if (player instanceof ServerPlayer) {
|
|
ServerPlayer serverPlayer = (ServerPlayer)player;
|
|
serverPlayer.sendSystemMessage(Component.translatable("advMode.notEnabled.spawner"));
|
|
}
|
|
return InteractionResult.FAIL;
|
|
}
|
|
spawnerHolder.setEntityId(type, level.getRandom());
|
|
level.sendBlockUpdated(pos, blockState, blockState, 3);
|
|
level.gameEvent((Entity)context.getPlayer(), GameEvent.BLOCK_CHANGE, pos);
|
|
itemStack.shrink(1);
|
|
return InteractionResult.SUCCESS;
|
|
}
|
|
BlockPos spawnPos = blockState.getCollisionShape(level, pos).isEmpty() ? pos : pos.relative(clickedFace);
|
|
return this.spawnMob(context.getPlayer(), itemStack, level, spawnPos, true, !Objects.equals(pos, spawnPos) && clickedFace == Direction.UP);
|
|
}
|
|
|
|
private InteractionResult spawnMob(@Nullable LivingEntity user, ItemStack itemStack, Level level, BlockPos spawnPos, boolean tryMoveDown, boolean movedUp) {
|
|
EntityType<?> type = this.getType(itemStack);
|
|
if (type == null) {
|
|
return InteractionResult.FAIL;
|
|
}
|
|
if (!type.isAllowedInPeaceful() && level.getDifficulty() == Difficulty.PEACEFUL) {
|
|
return InteractionResult.FAIL;
|
|
}
|
|
if (type.spawn((ServerLevel)level, itemStack, user, spawnPos, EntitySpawnReason.SPAWN_ITEM_USE, tryMoveDown, movedUp) != null) {
|
|
itemStack.consume(1, user);
|
|
level.gameEvent((Entity)user, GameEvent.ENTITY_PLACE, spawnPos);
|
|
}
|
|
return InteractionResult.SUCCESS;
|
|
}
|
|
|
|
@Override
|
|
public InteractionResult use(Level level, Player player, InteractionHand hand) {
|
|
ItemStack itemStack = player.getItemInHand(hand);
|
|
BlockHitResult hitResult = SpawnEggItem.getPlayerPOVHitResult(level, player, ClipContext.Fluid.SOURCE_ONLY);
|
|
if (hitResult.getType() != HitResult.Type.BLOCK) {
|
|
return InteractionResult.PASS;
|
|
}
|
|
if (!(level instanceof ServerLevel)) {
|
|
return InteractionResult.SUCCESS;
|
|
}
|
|
ServerLevel serverLevel = (ServerLevel)level;
|
|
BlockPos pos = hitResult.getBlockPos();
|
|
if (!(level.getBlockState(pos).getBlock() instanceof LiquidBlock)) {
|
|
return InteractionResult.PASS;
|
|
}
|
|
if (!level.mayInteract(player, pos) || !player.mayUseItemAt(pos, hitResult.getDirection(), itemStack)) {
|
|
return InteractionResult.FAIL;
|
|
}
|
|
InteractionResult result = this.spawnMob(player, itemStack, level, pos, false, false);
|
|
if (result == InteractionResult.SUCCESS) {
|
|
player.awardStat(Stats.ITEM_USED.get(this));
|
|
}
|
|
return result;
|
|
}
|
|
|
|
public boolean spawnsEntity(ItemStack itemStack, EntityType<?> type) {
|
|
return Objects.equals(this.getType(itemStack), type);
|
|
}
|
|
|
|
public static @Nullable SpawnEggItem byId(@Nullable EntityType<?> type) {
|
|
return BY_ID.get(type);
|
|
}
|
|
|
|
public static Iterable<SpawnEggItem> eggs() {
|
|
return Iterables.unmodifiableIterable(BY_ID.values());
|
|
}
|
|
|
|
public @Nullable EntityType<?> getType(ItemStack itemStack) {
|
|
TypedEntityData<EntityType<?>> entityData = itemStack.get(DataComponents.ENTITY_DATA);
|
|
if (entityData != null) {
|
|
return entityData.type();
|
|
}
|
|
return null;
|
|
}
|
|
|
|
@Override
|
|
public FeatureFlagSet requiredFeatures() {
|
|
return Optional.ofNullable(this.components().get(DataComponents.ENTITY_DATA)).map(TypedEntityData::type).map(EntityType::requiredFeatures).orElseGet(FeatureFlagSet::of);
|
|
}
|
|
|
|
public Optional<Mob> spawnOffspringFromSpawnEgg(Player player, Mob parent, EntityType<? extends Mob> type, ServerLevel level, Vec3 pos, ItemStack spawnEggStack) {
|
|
if (!this.spawnsEntity(spawnEggStack, type)) {
|
|
return Optional.empty();
|
|
}
|
|
Mob offspring = parent instanceof AgeableMob ? ((AgeableMob)parent).getBreedOffspring(level, (AgeableMob)parent) : type.create(level, EntitySpawnReason.SPAWN_ITEM_USE);
|
|
if (offspring == null) {
|
|
return Optional.empty();
|
|
}
|
|
offspring.setBaby(true);
|
|
if (!offspring.isBaby()) {
|
|
return Optional.empty();
|
|
}
|
|
offspring.snapTo(pos.x(), pos.y(), pos.z(), 0.0f, 0.0f);
|
|
offspring.applyComponentsFromItemStack(spawnEggStack);
|
|
level.addFreshEntityWithPassengers(offspring);
|
|
spawnEggStack.consume(1, player);
|
|
return Optional.of(offspring);
|
|
}
|
|
|
|
@Override
|
|
public boolean shouldPrintOpWarning(ItemStack stack, @Nullable Player player) {
|
|
TypedEntityData<EntityType<?>> entityData;
|
|
if (player != null && player.permissions().hasPermission(Permissions.COMMANDS_GAMEMASTER) && (entityData = stack.get(DataComponents.ENTITY_DATA)) != null) {
|
|
return entityData.type().onlyOpCanSetNbt();
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
|