2023-09-09 19:46:41 +02:00
|
|
|
package com.minelittlepony.unicopia.advancement;
|
|
|
|
|
|
|
|
import java.util.Optional;
|
|
|
|
import java.util.function.BiConsumer;
|
|
|
|
|
|
|
|
import com.minelittlepony.unicopia.entity.player.Pony;
|
2023-12-30 11:55:26 +01:00
|
|
|
import com.minelittlepony.unicopia.util.CodecUtils;
|
|
|
|
import com.mojang.serialization.Codec;
|
|
|
|
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
2023-09-09 19:46:41 +02:00
|
|
|
|
|
|
|
import net.fabricmc.fabric.api.util.TriState;
|
|
|
|
import net.minecraft.advancement.criterion.AbstractCriterion;
|
|
|
|
import net.minecraft.entity.LivingEntity;
|
|
|
|
import net.minecraft.entity.player.PlayerEntity;
|
|
|
|
import net.minecraft.item.ItemStack;
|
2023-12-30 11:55:26 +01:00
|
|
|
import net.minecraft.predicate.entity.EntityPredicate;
|
2023-09-09 19:46:41 +02:00
|
|
|
import net.minecraft.predicate.entity.LootContextPredicate;
|
|
|
|
import net.minecraft.predicate.item.ItemPredicate;
|
|
|
|
import net.minecraft.server.network.ServerPlayerEntity;
|
|
|
|
import net.minecraft.server.world.ServerWorld;
|
|
|
|
import net.minecraft.util.TypeFilter;
|
2023-12-30 11:55:26 +01:00
|
|
|
import net.minecraft.util.dynamic.Codecs;
|
2023-09-09 19:46:41 +02:00
|
|
|
|
|
|
|
public class SendViaDragonBreathScrollCriterion extends AbstractCriterion<SendViaDragonBreathScrollCriterion.Conditions> {
|
|
|
|
@Override
|
2023-12-30 11:55:26 +01:00
|
|
|
public Codec<Conditions> getConditionsCodec() {
|
|
|
|
return Conditions.CODEC;
|
2023-09-09 19:46:41 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
public void triggerSent(PlayerEntity player, ItemStack payload, String recipient, BiConsumer<String, Integer> counterCallback) {
|
|
|
|
if (player instanceof ServerPlayerEntity spe) {
|
|
|
|
trigger(spe, c -> {
|
|
|
|
if (c.test(spe, payload, recipient, false)) {
|
|
|
|
c.counter.ifPresent(counter -> {
|
|
|
|
counterCallback.accept(counter, Pony.of(spe).getAdvancementProgress().compute(counter, (key, i) -> i == null ? 1 : i + 1));
|
|
|
|
});
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public void triggerReceived(LivingEntity recipient, ItemStack payload) {
|
|
|
|
if (recipient instanceof ServerPlayerEntity spe) {
|
|
|
|
trigger(spe, c -> c.test(spe, payload, recipient.getDisplayName().getString(), true));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-12-30 11:55:26 +01:00
|
|
|
public record Conditions (
|
|
|
|
Optional<LootContextPredicate> player,
|
|
|
|
Optional<ItemPredicate> item,
|
|
|
|
boolean isReceivingEnd,
|
|
|
|
Optional<String> recipientName,
|
|
|
|
TriState recipientPresent,
|
|
|
|
Optional<String> counter,
|
|
|
|
RacePredicate races
|
|
|
|
) implements AbstractCriterion.Conditions {
|
|
|
|
public static final Codec<Conditions> CODEC = RecordCodecBuilder.create(instance -> instance.group(
|
|
|
|
Codecs.createStrictOptionalFieldCodec(EntityPredicate.LOOT_CONTEXT_PREDICATE_CODEC, "player").forGetter(Conditions::player),
|
|
|
|
ItemPredicate.CODEC.optionalFieldOf("item").forGetter(Conditions::item),
|
|
|
|
Codec.BOOL.optionalFieldOf("is_receiving_end", false).forGetter(Conditions::isReceivingEnd),
|
|
|
|
Codec.STRING.optionalFieldOf("recipient_name").forGetter(Conditions::recipientName),
|
|
|
|
CodecUtils.tristateOf("recipient_present").forGetter(Conditions::recipientPresent),
|
|
|
|
Codec.STRING.optionalFieldOf("counter").forGetter(Conditions::counter),
|
2024-02-08 23:08:26 +01:00
|
|
|
RacePredicate.CODEC.optionalFieldOf("races", RacePredicate.EMPTY).forGetter(Conditions::races)
|
2023-12-30 11:55:26 +01:00
|
|
|
).apply(instance, Conditions::new));
|
2023-09-09 19:46:41 +02:00
|
|
|
|
|
|
|
public boolean test(ServerPlayerEntity player, ItemStack payload, String recipient, boolean receiving) {
|
|
|
|
return isReceivingEnd == receiving
|
|
|
|
&& races.test(player)
|
2023-09-29 20:15:04 +02:00
|
|
|
&& (item.isEmpty() || item.get().test(payload))
|
2023-09-09 19:46:41 +02:00
|
|
|
&& recipientName.map(expectedRecipientname -> recipient.equalsIgnoreCase(expectedRecipientname)).orElse(true)
|
|
|
|
&& (recipientPresent == TriState.DEFAULT || isRecipientAbsent(player.getServerWorld(), recipient) != recipientPresent.get());
|
|
|
|
}
|
|
|
|
|
|
|
|
private boolean isRecipientAbsent(ServerWorld world, String recipient) {
|
|
|
|
return world.getEntitiesByType(TypeFilter.instanceOf(LivingEntity.class), e -> e.hasCustomName() && e.getCustomName().getString().equalsIgnoreCase(recipient)).isEmpty();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|