CarryOn/Common/src/main/java/tschipp/carryon/common/carry/PickupHandler.java
2023-07-06 18:48:28 +02:00

240 lines
8.7 KiB
Java

package tschipp.carryon.common.carry;
import net.minecraft.core.BlockPos;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundSource;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.entity.AgeableMob;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.Entity.RemovalReason;
import net.minecraft.world.entity.MobCategory;
import net.minecraft.world.entity.TamableAnimal;
import net.minecraft.world.entity.animal.Animal;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.GameType;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.Vec3;
import tschipp.carryon.Constants;
import tschipp.carryon.common.config.ListHandler;
import tschipp.carryon.common.pickupcondition.PickupCondition;
import tschipp.carryon.common.pickupcondition.PickupConditionHandler;
import tschipp.carryon.common.scripting.CarryOnScript;
import tschipp.carryon.common.scripting.ScriptManager;
import tschipp.carryon.networking.clientbound.ClientboundStartRidingPacket;
import tschipp.carryon.platform.Services;
import javax.annotation.Nullable;
import java.util.Optional;
import java.util.UUID;
import java.util.function.BiFunction;
import java.util.function.Function;
public class PickupHandler {
public static boolean canCarryGeneral(ServerPlayer player, Vec3 pos)
{
if(!player.getMainHandItem().isEmpty() || !player.getOffhandItem().isEmpty())
return false;
if(player.position().distanceTo(pos) > Constants.COMMON_CONFIG.settings.maxDistance)
return false;
CarryOnData carry = CarryOnDataManager.getCarryData(player);
if(carry.isCarrying())
return false;
if(!carry.isKeyPressed())
return false;
//Needed so that we don't pick up and place in the same tick
if(player.tickCount == carry.getTick())
return false;
if (player.gameMode.getGameModeForPlayer() == GameType.SPECTATOR || player.gameMode.getGameModeForPlayer() == GameType.ADVENTURE)
return false;
return true;
}
public static boolean tryPickUpBlock(ServerPlayer player, BlockPos pos, Level level, @Nullable BiFunction<BlockState, BlockPos, Boolean> pickupCallback)
{
if(!canCarryGeneral(player, Vec3.atCenterOf(pos)))
return false;
CarryOnData carry = CarryOnDataManager.getCarryData(player);
BlockEntity blockEntity = level.getBlockEntity(pos);
BlockState state = level.getBlockState(pos);
CompoundTag nbt = null;
if(blockEntity != null)
nbt = blockEntity.saveWithId();
if(!ListHandler.isPermitted(state.getBlock()))
return false;
if(state.getDestroySpeed(level, pos) == -1 && !player.isCreative() && !Constants.COMMON_CONFIG.settings.pickupUnbreakableBlocks)
return false;
if(blockEntity == null && !Constants.COMMON_CONFIG.settings.pickupAllBlocks)
return false;
//Check if TE is locked
if(blockEntity != null)
{
if(nbt.contains("Lock") && !nbt.getString("Lock").equals(""))
return false;
}
Optional<PickupCondition> cond = PickupConditionHandler.getPickupCondition(state);
if(cond.isPresent())
{
if(!cond.get().isFulfilled(player))
return false;
}
boolean doPickup = pickupCallback == null ? true : pickupCallback.apply(state, pos);
if(!doPickup)
return false;
Optional<CarryOnScript> result = ScriptManager.inspectBlock(state, level, pos, nbt);
if(result.isPresent())
{
CarryOnScript script = result.get();
if(!script.fulfillsConditions(player))
return false;
carry.setActiveScript(script);
String cmd = script.scriptEffects().commandInit();
if(!cmd.isEmpty())
player.getServer().getCommands().performPrefixedCommand(player.getServer().createCommandSourceStack(), "/execute as " + player.getGameProfile().getName() + " run " + cmd);
}
carry.setBlock(state, blockEntity);
level.removeBlockEntity(pos);
level.removeBlock(pos, false);
CarryOnDataManager.setCarryData(player, carry);
level.playSound(null, pos, state.getSoundType().getHitSound(), SoundSource.BLOCKS, 1.0f, 0.5f);
player.swing(InteractionHand.MAIN_HAND, true);
return true;
}
public static boolean tryPickupEntity(ServerPlayer player, Entity entity, @Nullable Function<Entity, Boolean> pickupCallback)
{
if(!canCarryGeneral(player, entity.position()))
return false;
if (entity.invulnerableTime != 0)
return false;
if(entity.isRemoved())
return false;
if (entity instanceof TamableAnimal tame)
{
UUID owner = tame.getOwnerUUID();
UUID playerID = player.getGameProfile().getId();
if (owner != null && !owner.equals(playerID))
return false;
}
if(!ListHandler.isPermitted(entity))
{
//We can pick up baby animals even if the grown up animal is blacklisted.
if(!(entity instanceof AgeableMob ageableMob && Constants.COMMON_CONFIG.settings.allowBabies && (ageableMob.getAge() < 0 || ageableMob.isBaby())))
return false;
}
//Non-Creative only guards
if(!player.isCreative())
{
if(!Constants.COMMON_CONFIG.settings.pickupHostileMobs && entity.getType().getCategory() == MobCategory.MONSTER)
return false;
if(Constants.COMMON_CONFIG.settings.maxEntityHeight < entity.getBbHeight() || Constants.COMMON_CONFIG.settings.maxEntityWidth < entity.getBbWidth())
return false;
}
Optional<PickupCondition> cond = PickupConditionHandler.getPickupCondition(entity);
if(cond.isPresent())
{
if(!cond.get().isFulfilled(player))
return false;
}
boolean doPickup = pickupCallback == null ? true : pickupCallback.apply(entity);
if(!doPickup)
return false;
CarryOnData carry = CarryOnDataManager.getCarryData(player);
Optional<CarryOnScript> result = ScriptManager.inspectEntity(entity);
if(result.isPresent())
{
CarryOnScript script = result.get();
if(!script.fulfillsConditions(player))
return false;
carry.setActiveScript(script);
}
if (entity instanceof Player otherPlayer) {
if (!Constants.COMMON_CONFIG.settings.pickupPlayers)
return false;
if (!player.isCreative() && otherPlayer.isCreative())
return false;
otherPlayer.ejectPassengers();
otherPlayer.stopRiding();
if (result.isPresent()) {
String cmd = result.get().scriptEffects().commandInit();
if (!cmd.isEmpty())
player.getServer().getCommands().performPrefixedCommand(player.getServer().createCommandSourceStack(), "/execute as " + player.getGameProfile().getName() + " run " + cmd);
}
otherPlayer.startRiding(player);
Services.PLATFORM.sendPacketToPlayer(Constants.PACKET_ID_START_RIDING, new ClientboundStartRidingPacket(otherPlayer.getId(), true), player);
carry.setCarryingPlayer();
player.swing(InteractionHand.MAIN_HAND, true);
player.level().playSound(null, player.getOnPos(), SoundEvents.ARMOR_EQUIP_GENERIC, SoundSource.AMBIENT, 1.0f, 0.5f);
CarryOnDataManager.setCarryData(player, carry);
return true;
}
entity.ejectPassengers();
entity.stopRiding();
if (entity instanceof Animal animal) {
animal.dropLeash(true, true);
}
if(result.isPresent())
{
String cmd = result.get().scriptEffects().commandInit();
if(!cmd.isEmpty())
player.getServer().getCommands().performPrefixedCommand(player.getServer().createCommandSourceStack(), "/execute as " + player.getGameProfile().getName() + " run " + cmd);
}
carry.setEntity(entity);
entity.remove(RemovalReason.UNLOADED_WITH_PLAYER);
player.level().playSound(null, player.getOnPos(), SoundEvents.ARMOR_EQUIP_GENERIC, SoundSource.AMBIENT, 1.0f, 0.5f);
CarryOnDataManager.setCarryData(player, carry);
player.swing(InteractionHand.MAIN_HAND, true);
return true;
}
}