Search in sources :

Example 11 with PrettyPrinter

use of org.spongepowered.common.util.PrettyPrinter in project SpongeCommon by SpongePowered.

the class AsyncScheduler method close.

public void close() {
    this.running = false;
    // Cancel all tasks
    final Set<ScheduledTask> tasks = this.tasks();
    tasks.forEach(ScheduledTask::cancel);
    // Shut down the executor
    this.executor.shutdown();
    try {
        if (!this.executor.awaitTermination(5, TimeUnit.SECONDS)) {
            new PrettyPrinter().add("Sponge async scheduler failed to shut down in 5 seconds! Tasks that may have been active:").addWithIndices(tasks).add().add("We will now attempt immediate shutdown.").log(SpongeCommon.logger(), Level.WARN);
            this.executor.shutdownNow();
        }
    } catch (final InterruptedException e) {
        SpongeCommon.logger().error("The async scheduler was interrupted while awaiting shutdown!");
    }
}
Also used : PrettyPrinter(org.spongepowered.common.util.PrettyPrinter) ScheduledTask(org.spongepowered.api.scheduler.ScheduledTask)

Example 12 with PrettyPrinter

use of org.spongepowered.common.util.PrettyPrinter in project SpongeCommon by SpongePowered.

the class SpongeCommandManager method prettyPrintThrowableError.

private void prettyPrintThrowableError(final Throwable thr, final String commandNoArgs, final String args, final CommandCause cause) {
    final String commandString;
    if (args != null && !args.isEmpty()) {
        commandString = commandNoArgs + " " + args;
    } else {
        commandString = commandNoArgs;
    }
    final SpongeCommandMapping mapping = this.commandMappings.get(commandNoArgs.toLowerCase());
    final PrettyPrinter prettyPrinter = new PrettyPrinter(100).add("Unexpected error occurred while executing command '%s'", commandString).centre().hr().addWrapped("While trying to run '%s', an error occurred that the command processor was not expecting. " + "This usually indicates an error in the plugin that owns this command. Report this error " + "to the plugin developer first - this is usually not a Sponge error.", commandString).hr().add().add("Command: %s", commandString).add("Owning Plugin: %s", mapping.plugin().map(x -> x.metadata().id()).orElse("unknown")).add("Owning Registrar: %s", mapping.registrar().getClass().getName()).add().add("Exception Details: ");
    if (thr instanceof SpongeCommandSyntaxException) {
        // we know the inner exception was wrapped by us.
        prettyPrinter.add(thr.getCause());
    } else {
        prettyPrinter.add(thr);
    }
    prettyPrinter.add().add("CommandCause details: ").addWrapped(cause.cause().toString()).log(SpongeCommon.logger(), Level.ERROR);
}
Also used : LiteralCommandNode(com.mojang.brigadier.tree.LiteralCommandNode) Object2BooleanMap(it.unimi.dsi.fastutil.objects.Object2BooleanMap) SpongeCommandDispatcher(org.spongepowered.common.command.brigadier.dispatcher.SpongeCommandDispatcher) Arrays(java.util.Arrays) Game(org.spongepowered.api.Game) Inject(com.google.inject.Inject) Level(org.apache.logging.log4j.Level) CommandFailedRegistrationException(org.spongepowered.api.command.manager.CommandFailedRegistrationException) SpongeAdventure(org.spongepowered.common.adventure.SpongeAdventure) CommandPhaseContext(org.spongepowered.common.event.tracking.phase.general.CommandPhaseContext) MinecraftServer(net.minecraft.server.MinecraftServer) HashMultimap(com.google.common.collect.HashMultimap) Locale(java.util.Locale) Map(java.util.Map) RootCommandTreeNode(org.spongepowered.common.command.registrar.tree.builder.RootCommandTreeNode) TransactionalCaptureSupplier(org.spongepowered.common.event.tracking.context.transaction.TransactionalCaptureSupplier) Subject(org.spongepowered.api.service.permission.Subject) Object2BooleanOpenHashMap(it.unimi.dsi.fastutil.objects.Object2BooleanOpenHashMap) PrintWriter(java.io.PrintWriter) SpongeCommandCompletion(org.spongepowered.common.command.SpongeCommandCompletion) ImmutableSet(com.google.common.collect.ImmutableSet) CommandCompletion(org.spongepowered.api.command.CommandCompletion) Collection(java.util.Collection) Launch(org.spongepowered.common.launch.Launch) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) Sponge(org.spongepowered.api.Sponge) Set(java.util.Set) SpongeCommandResult(org.spongepowered.common.command.result.SpongeCommandResult) TypeToken(io.leangen.geantyref.TypeToken) Collectors(java.util.stream.Collectors) LiteralArgumentBuilder(com.mojang.brigadier.builder.LiteralArgumentBuilder) NamedTextColor(net.kyori.adventure.text.format.NamedTextColor) SpongeParameterizedCommandRegistrar(org.spongepowered.common.command.registrar.SpongeParameterizedCommandRegistrar) Player(net.minecraft.world.entity.player.Player) Objects(java.util.Objects) ExecuteCommandEvent(org.spongepowered.api.event.command.ExecuteCommandEvent) List(java.util.List) PhaseContext(org.spongepowered.common.event.tracking.PhaseContext) Optional(java.util.Optional) HoverEvent(net.kyori.adventure.text.event.HoverEvent) CommandManager(org.spongepowered.api.command.manager.CommandManager) SpongePaginationService(org.spongepowered.common.service.game.pagination.SpongePaginationService) CommandRegistrar(org.spongepowered.api.command.registrar.CommandRegistrar) NonNull(org.checkerframework.checker.nullness.qual.NonNull) EventContextKeys(org.spongepowered.api.event.EventContextKeys) ComponentMessageThrowable(net.kyori.adventure.util.ComponentMessageThrowable) SharedSuggestionProvider(net.minecraft.commands.SharedSuggestionProvider) CommandSourceStack(net.minecraft.commands.CommandSourceStack) Constants(org.spongepowered.common.util.Constants) Command(com.mojang.brigadier.Command) CommandsBridge(org.spongepowered.common.bridge.commands.CommandsBridge) PrettyPrinter(org.spongepowered.common.util.PrettyPrinter) HashMap(java.util.HashMap) BrigadierCommandRegistrar(org.spongepowered.common.command.registrar.BrigadierCommandRegistrar) Multimap(com.google.common.collect.Multimap) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) LinkedHashMap(java.util.LinkedHashMap) SpongeCommand(org.spongepowered.common.command.sponge.SpongeCommand) Component(net.kyori.adventure.text.Component) CallbackCommand(org.spongepowered.common.adventure.CallbackCommand) CauseStackManager(org.spongepowered.api.event.CauseStackManager) Nullable(org.checkerframework.checker.nullness.qual.Nullable) GeneralPhase(org.spongepowered.common.event.tracking.phase.general.GeneralPhase) CommandResult(org.spongepowered.api.command.CommandResult) SpongeCommandSyntaxException(org.spongepowered.common.command.exception.SpongeCommandSyntaxException) RegisterCommandEventImpl(org.spongepowered.common.event.lifecycle.RegisterCommandEventImpl) Parameterized(org.spongepowered.api.command.Command.Parameterized) Identity(net.kyori.adventure.identity.Identity) CommandTreeNode(org.spongepowered.api.command.registrar.tree.CommandTreeNode) SpongeEventFactory(org.spongepowered.api.event.SpongeEventFactory) StringWriter(java.io.StringWriter) CommandRegistrarType(org.spongepowered.api.command.registrar.CommandRegistrarType) SpongeCommon(org.spongepowered.common.SpongeCommon) PhaseTracker(org.spongepowered.common.event.tracking.PhaseTracker) PaginationService(org.spongepowered.api.service.pagination.PaginationService) RegistryTypes(org.spongepowered.api.registry.RegistryTypes) Cause(org.spongepowered.api.event.Cause) CommandCause(org.spongepowered.api.command.CommandCause) CommandMapping(org.spongepowered.api.command.manager.CommandMapping) Provider(com.google.inject.Provider) PluginContainer(org.spongepowered.plugin.PluginContainer) Audience(net.kyori.adventure.audience.Audience) SpongeConfigs(org.spongepowered.common.applaunch.config.core.SpongeConfigs) CommandNode(com.mojang.brigadier.tree.CommandNode) GenericTypeReflector(io.leangen.geantyref.GenericTypeReflector) CommandSyntaxException(com.mojang.brigadier.exceptions.CommandSyntaxException) Collections(java.util.Collections) CommandException(org.spongepowered.api.command.exception.CommandException) ServerPlayer(org.spongepowered.api.entity.living.player.server.ServerPlayer) PrettyPrinter(org.spongepowered.common.util.PrettyPrinter) SpongeCommandSyntaxException(org.spongepowered.common.command.exception.SpongeCommandSyntaxException)

Example 13 with PrettyPrinter

use of org.spongepowered.common.util.PrettyPrinter in project SpongeCommon by SpongePowered.

the class SpongeServiceProvider method init.

// Service Discovery
/**
 * Discovers services by querying plugins with the
 * {@link ProvideServiceEvent}. To be called at the appropriate moment in
 * the lifecycle.
 */
public final void init() {
    if (!this.services.isEmpty()) {
        throw new IllegalStateException("Services have already been initialised");
    }
    final ServicesCategory.ServicePluginSubCategory servicePluginSubCategory = SpongeConfigs.getCommon().get().services.plugins;
    // This does NOT support third party service interfaces, only impls.
    for (final Service<?> candidate : this.servicesToSelect()) {
        // If the configuration file has a specific plugin ID, we look for it.
        final String pluginId = candidate.providePluginId(servicePluginSubCategory);
        final boolean isSpecific = !pluginId.isEmpty() && !pluginId.equals("?");
        final Class<?> serviceClass = candidate.getServiceClass();
        final String serviceName = serviceClass.getSimpleName();
        Registration<?> registration = null;
        if (isSpecific) {
            final Optional<PluginContainer> specificPluginContainer = Launch.instance().pluginManager().plugin(pluginId);
            if (specificPluginContainer.isPresent()) {
                registration = this.getSpecificRegistration(specificPluginContainer.get(), candidate);
                if (registration == null) {
                    final PrettyPrinter prettyPrinter = new PrettyPrinter(80).add("Service Registration Failed: %s (Service Not Provided)", serviceName).hr().addWrapped("Sponge is configured to obtain the service %s from the plugin with ID %s," + "however, that plugin did not provide any service implementation when " + "requested.", serviceName, pluginId).add().add("To fix this problem, do one of the following:").add().add(" * Check that the plugin %s can actually provide the service (check the plugin" + "   documentation if you need more assistance with that plugin).", pluginId).add(" * Set the config entry for this service to \"?\" to let Sponge find another " + "   plugin to provide the service.").add(" * Set the config entry for this service to the ID of another plugin that can" + "   provide the service.");
                    if (candidate.suppliesDefault()) {
                        prettyPrinter.add().add("Sponge will continue using the inbuilt default service.");
                    }
                    prettyPrinter.log(SpongeCommon.logger(), Level.ERROR);
                }
            } else {
                final PrettyPrinter prettyPrinter = new PrettyPrinter(80).add("Service Registration Failed: %s (Plugin Not Found)", serviceName).hr().addWrapped("Sponge is configured to obtain the service %s from the plugin with ID %s," + "however, that plugin isn't installed.", serviceName, pluginId).add().add("To fix this problem, do one of the following:").add().add(" * Install the plugin %s", pluginId).add(" * Set the config entry for this service to \"?\" to let Sponge find another " + "   plugin to provide the service.").add(" * Set the config entry for this service to the ID of another plugin that can" + "   provide the service.");
                if (candidate.suppliesDefault()) {
                    prettyPrinter.add().add("Sponge will continue using the inbuilt default service.");
                }
                prettyPrinter.log(SpongeCommon.logger(), Level.ERROR);
            }
        } else {
            final Collection<PluginContainer> toQuery = Launch.instance().pluginManager().plugins();
            registration = this.attemptRegistration(toQuery, candidate);
        }
        if (registration == null) {
            // If we don't have a registration, we try a Sponge one (which is lowest priority)
            registration = this.createRegistration(candidate, Launch.instance().commonPlugin());
        }
        // If after all that we have a registration, we... register it.
        if (registration != null) {
            this.services.put(candidate.getServiceClass(), registration);
            SpongeCommon.logger().info("Registered service [{}] to plugin '{}'.", registration.clazz.getSimpleName(), registration.pluginContainer.metadata().id());
        }
    }
}
Also used : PrettyPrinter(org.spongepowered.common.util.PrettyPrinter) PluginContainer(org.spongepowered.plugin.PluginContainer) ServicesCategory(org.spongepowered.common.applaunch.config.common.ServicesCategory)

Example 14 with PrettyPrinter

use of org.spongepowered.common.util.PrettyPrinter in project SpongeCommon by SpongePowered.

the class LivingEntityMixin_Attack_impl method hurt.

// @formatter:on
/**
 * @author bloodmc - November 22, 2015
 * @author gabizou - Updated April 11th, 2016 - Update for 1.9 changes
 * @author Aaron1011 - Updated Nov 11th, 2016 - Update for 1.11 changes
 * @author gabizou - Updated Nov 15th, 2020 - Update for 1.15 changes
 * @author gabizou - Updated Jan 26th, 2022 - Update for 1.16.5 changes
 * @reason Reroute damageEntity calls to our hook in order to prevent damage.
 */
@Overwrite
public boolean hurt(final DamageSource source, final float amount) {
    // Sponge start - Add certain hooks for necessities
    this.lastDamageSource = source;
    if (source == null) {
        new PrettyPrinter(60).centre().add("Null DamageSource").hr().addWrapped("Sponge has found a null damage source! This should NEVER happen " + "as the DamageSource is used for all sorts of calculations. Usually" + " this can be considered developer error. Please report the following" + " stacktrace to the most appropriate mod/plugin available.").add().add(new IllegalArgumentException("Null DamageSource")).log(SpongeCommon.logger(), Level.WARN);
        return false;
    }
    // Sponge - This hook is for forge use mainly
    if (!this.bridge$onLivingAttack((LivingEntity) (Object) this, source, amount)) {
        return false;
    }
    // Sponge end
    if (this.shadow$isInvulnerableTo(source)) {
        return false;
    } else if (this.level.isClientSide) {
        return false;
    // Sponge - Also ignore our customary damage source
    } else if (this.shadow$isDeadOrDying() && source != SpongeDamageSources.IGNORED) {
        return false;
    } else if (source.isFire() && this.shadow$hasEffect(MobEffects.FIRE_RESISTANCE)) {
        return false;
    } else {
        if (this.shadow$isSleeping() && !this.level.isClientSide) {
            this.shadow$stopSleeping();
        }
        this.noActionTime = 0;
        final float f = amount;
        // Sponge - ignore as this is handled in our damageEntityHook
        // if ((source == DamageSource.ANVIL || source == DamageSource.FALLING_BLOCK) && !this.getItemStackFromSlot(EntityEquipmentSlot.HEAD).isEmpty())
        // {
        // this.getItemStackFromSlot(EquipmentSlotType.HEAD).damageItem((int)(amount * 4.0F + this.rand.nextFloat() * amount * 2.0F), this, (p_213341_0_) -> {
        // p_213341_0_.sendBreakAnimation(EquipmentSlotType.HEAD);
        // });
        // amount *= 0.75F;
        // }
        // Sponge End
        // Sponge - set the 'shield blocking ran' flag to the proper value, since
        // we comment out the logic below
        float f1 = 0.0F;
        final boolean flag = amount > 0.0F && this.shadow$isDamageSourceBlocked(source);
        // but we need to account for the amount later.
        if (flag) {
            f1 = amount;
        }
        // boolean flag = false;
        // 
        // if (amount > 0.0F && this.shadow$canBlockDamageSource(source))
        // {
        // this.damageShield(amount);
        // amount = 0.0F;
        // 
        // if (!source.isProjectile())
        // {
        // Entity entity = source.getImmediateSource();
        // 
        // if (entity instanceof EntityLivingBase)
        // {
        // this.blockUsingShield((EntityLivingBase)entity);
        // }
        // }
        // 
        // flag = true;
        // }
        // Sponge end
        this.animationSpeed = 1.5F;
        boolean flag1 = true;
        if ((float) this.invulnerableTime > 10.0F) {
            if (amount <= this.lastHurt) {
                // Technically, this is wrong since 'amount' won't be 0 if a shield is used. However, we need bridge$damageEntityHook so that we process the shield, so we leave it as-is
                return false;
            }
            // damageEntity method, which would re-run our bridge$damageEntityHook.
            if (((EntityTypeBridge) this.shadow$getType()).bridge$overridesDamageEntity()) {
                this.shadow$actuallyHurt(source, amount - this.lastHurt);
            } else {
                if (!this.bridge$damageEntity(source, amount - this.lastHurt)) {
                    return false;
                }
            }
            // this.damageEntity(source, amount - this.lastHurt); // handled above
            // Sponge end
            this.lastHurt = amount;
            flag1 = false;
        } else {
            // Sponge start - reroute to our damage hook
            if (((EntityTypeBridge) this.shadow$getType()).bridge$overridesDamageEntity()) {
                this.shadow$actuallyHurt(source, amount);
            } else {
                if (!this.bridge$damageEntity(source, amount)) {
                    return false;
                }
            }
            this.lastHurt = amount;
            this.invulnerableTime = 20;
            // this.damageEntity(source, amount); // handled above
            // Sponge end
            this.hurtDuration = 10;
            this.hurtTime = this.hurtDuration;
        }
        this.hurtDir = 0.0F;
        final Entity entity = source.getEntity();
        if (entity != null) {
            if (entity instanceof LivingEntity) {
                this.shadow$setLastHurtByMob((LivingEntity) entity);
            }
            if (entity instanceof Player) {
                this.lastHurtByPlayerTime = 100;
                this.lastHurtByPlayer = (Player) entity;
            // Forge Start - use TameableEntity instead of WolfEntity
            // } else if (entity1 instanceof WolfEntity) {
            // WolfEntity wolfentity = (WolfEntity)entity1;
            } else if (entity instanceof TamableAnimal) {
                final TamableAnimal wolfentity = (TamableAnimal) entity;
                if (wolfentity.isTame()) {
                    this.lastHurtByPlayerTime = 100;
                    final LivingEntity livingentity = wolfentity.getOwner();
                    if (livingentity != null && livingentity.getType() == EntityType.PLAYER) {
                        this.lastHurtByPlayer = (Player) livingentity;
                    } else {
                        this.lastHurtByPlayer = null;
                    }
                }
            }
        }
        if (flag1) {
            if (flag) {
                this.level.broadcastEntityEvent((LivingEntity) (Object) this, (byte) 29);
            } else if (source instanceof EntityDamageSource && ((EntityDamageSource) source).isThorns()) {
                this.level.broadcastEntityEvent((LivingEntity) (Object) this, (byte) 33);
            } else {
                final byte b0;
                if (source == DamageSource.DROWN) {
                    b0 = 36;
                } else if (source.isFire()) {
                    b0 = 37;
                } else if (source == DamageSource.SWEET_BERRY_BUSH) {
                    b0 = 44;
                } else {
                    b0 = 2;
                }
                this.level.broadcastEntityEvent((LivingEntity) (Object) this, b0);
            }
            if (source != DamageSource.DROWN && !flag) {
                // Sponge - remove 'amount > 0.0F' - it's redundant in Vanilla, and breaks our handling of shields
                this.shadow$markHurt();
            }
            if (entity != null) {
                double d1 = entity.getX() - this.shadow$getX();
                double d0;
                for (d0 = entity.getZ() - this.shadow$getZ(); d1 * d1 + d0 * d0 < 1.0E-4D; d0 = (Math.random() - Math.random()) * 0.01D) {
                    d1 = (Math.random() - Math.random()) * 0.01D;
                }
                this.hurtDir = (float) (Mth.atan2(d0, d1) * 57.2957763671875D - (double) this.yRot);
                this.shadow$knockback(0.4F, d1, d0);
            } else {
                this.hurtDir = (float) (Math.random() * 2.0D * 180);
            }
        }
        if (this.shadow$isDeadOrDying()) {
            if (!this.shadow$checkTotemDeathProtection(source)) {
                final SoundEvent soundevent = this.shadow$getDeathSound();
                // Sponge - Check that we're not vanished
                if (this.bridge$vanishState().createsSounds() && flag1 && soundevent != null) {
                    this.shadow$playSound(soundevent, this.shadow$getSoundVolume(), this.shadow$getVoicePitch());
                }
                // Sponge tracker will redirect this call
                this.shadow$die(source);
            }
        } else if (flag1) {
            // Sponge - Check if we're vanished
            if (this.bridge$vanishState().createsSounds()) {
                this.shadow$playHurtSound(source);
            }
        }
        // Sponge - remove 'amount > 0.0F' since it's handled in the event
        final boolean flag2 = !flag;
        if (flag2) {
            this.lastDamageSource = source;
            this.lastDamageStamp = this.level.getGameTime();
        }
        if ((LivingEntity) (Object) this instanceof net.minecraft.server.level.ServerPlayer) {
            CriteriaTriggers.ENTITY_HURT_PLAYER.trigger((net.minecraft.server.level.ServerPlayer) (Object) this, source, f, amount, flag);
            if (f1 > 0.0F && f1 < 3.4028235E37F) {
                ((net.minecraft.server.level.ServerPlayer) (Object) this).awardStat(Stats.DAMAGE_BLOCKED_BY_SHIELD, Math.round(f1 * 10.0F));
            }
        }
        if (entity instanceof net.minecraft.server.level.ServerPlayer) {
            CriteriaTriggers.PLAYER_HURT_ENTITY.trigger((net.minecraft.server.level.ServerPlayer) entity, (Entity) (Object) this, source, f, amount, flag);
        }
        return flag2;
    }
}
Also used : LivingEntity(net.minecraft.world.entity.LivingEntity) Entity(net.minecraft.world.entity.Entity) Player(net.minecraft.world.entity.player.Player) TamableAnimal(net.minecraft.world.entity.TamableAnimal) EntityDamageSource(net.minecraft.world.damagesource.EntityDamageSource) LivingEntity(net.minecraft.world.entity.LivingEntity) SoundEvent(net.minecraft.sounds.SoundEvent) PrettyPrinter(org.spongepowered.common.util.PrettyPrinter) Overwrite(org.spongepowered.asm.mixin.Overwrite)

Example 15 with PrettyPrinter

use of org.spongepowered.common.util.PrettyPrinter in project SpongeCommon by SpongePowered.

the class PhasePrinter method printRunawayPhase.

static void printRunawayPhase(final PhaseStack stack, final IPhaseState<@NonNull ?> state, final PhaseContext<@NonNull ?> context) {
    if (!SpongeConfigs.getCommon().get().phaseTracker.verbose && !PhasePrinter.hasPrintedAboutRunnawayPhases) {
        // Avoiding spam logs.
        return;
    }
    final PrettyPrinter printer = new PrettyPrinter(60);
    printer.add("Switching Phase").centre().hr();
    printer.addWrapped(60, "Detecting a runaway phase! Potentially a problem where something isn't completing a phase!!!");
    printer.add("  %s : %s", "Entering State", state);
    PhasePrinter.CONTEXT_PRINTER.accept(printer, context);
    printer.addWrapped(60, "%s :", "Phases remaining");
    PhasePrinter.printPhaseStackWithException(stack, printer, new Exception("RunawayPhase"));
    if (PhasePrinter.IN_DEVELOPMENT) {
        printer.print(System.err);
    } else {
        printer.log(SpongeCommon.logger(), Level.ERROR);
    }
    if (!SpongeConfigs.getCommon().get().phaseTracker.verbose && PhasePrinter.printRunawayCount++ > SpongeConfigs.getCommon().get().phaseTracker.maximumPrintedRunawayCounts) {
        PhasePrinter.hasPrintedAboutRunnawayPhases = true;
    }
}
Also used : PrettyPrinter(org.spongepowered.common.util.PrettyPrinter)

Aggregations

PrettyPrinter (org.spongepowered.common.util.PrettyPrinter)28 Nullable (org.checkerframework.checker.nullness.qual.Nullable)5 Map (java.util.Map)4 Collection (java.util.Collection)3 HashMap (java.util.HashMap)3 HashSet (java.util.HashSet)3 Collectors (java.util.stream.Collectors)3 ServerLevel (net.minecraft.server.level.ServerLevel)3 Level (org.apache.logging.log4j.Level)3 PluginContainer (org.spongepowered.plugin.PluginContainer)3 ArrayList (java.util.ArrayList)2 Collections (java.util.Collections)2 IdentityHashMap (java.util.IdentityHashMap)2 LinkedHashSet (java.util.LinkedHashSet)2 List (java.util.List)2 Objects (java.util.Objects)2 Optional (java.util.Optional)2 Set (java.util.Set)2 Player (net.minecraft.world.entity.player.Player)2 NonNull (org.checkerframework.checker.nullness.qual.NonNull)2