Merge remote-tracking branch 'upstream/main'
This commit is contained in:
@ -11,7 +11,7 @@ java {
|
|||||||
|
|
||||||
val annotationsVersion = "26.0.2"
|
val annotationsVersion = "26.0.2"
|
||||||
// Keep in sync with paper-server adventure-text-serializer-ansi dep
|
// Keep in sync with paper-server adventure-text-serializer-ansi dep
|
||||||
val adventureVersion = "4.21.0"
|
val adventureVersion = "4.23.0"
|
||||||
val bungeeCordChatVersion = "1.21-R0.2-deprecated+build.21"
|
val bungeeCordChatVersion = "1.21-R0.2-deprecated+build.21"
|
||||||
val slf4jVersion = "2.0.16"
|
val slf4jVersion = "2.0.16"
|
||||||
val log4jVersion = "2.24.1"
|
val log4jVersion = "2.24.1"
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
package io.papermc.paper;
|
package io.papermc.paper;
|
||||||
|
|
||||||
|
import io.papermc.paper.command.brigadier.CommandSourceStack;
|
||||||
import io.papermc.paper.world.damagesource.CombatEntry;
|
import io.papermc.paper.world.damagesource.CombatEntry;
|
||||||
import io.papermc.paper.world.damagesource.FallLocationType;
|
import io.papermc.paper.world.damagesource.FallLocationType;
|
||||||
import net.kyori.adventure.util.Services;
|
import net.kyori.adventure.util.Services;
|
||||||
@ -11,6 +12,8 @@ import org.jetbrains.annotations.ApiStatus;
|
|||||||
import org.jspecify.annotations.NullMarked;
|
import org.jspecify.annotations.NullMarked;
|
||||||
import org.jspecify.annotations.Nullable;
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Static bridge to the server internals.
|
* Static bridge to the server internals.
|
||||||
* <p>
|
* <p>
|
||||||
@ -73,5 +76,15 @@ public interface InternalAPIBridge {
|
|||||||
* @return combat entry
|
* @return combat entry
|
||||||
*/
|
*/
|
||||||
CombatEntry createCombatEntry(DamageSource damageSource, float damage, @Nullable FallLocationType fallLocationType, float fallDistance);
|
CombatEntry createCombatEntry(DamageSource damageSource, float damage, @Nullable FallLocationType fallLocationType, float fallDistance);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Causes this predicate to be considered restricted.
|
||||||
|
* Applying this to a command node prevents this command from being executed from an
|
||||||
|
* unattended context, such as click events.
|
||||||
|
*
|
||||||
|
* @param predicate wrapped predicate
|
||||||
|
* @return wrapped predicate
|
||||||
|
*/
|
||||||
|
Predicate<CommandSourceStack> restricted(Predicate<CommandSourceStack> predicate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import com.mojang.brigadier.arguments.ArgumentType;
|
|||||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||||
import com.mojang.brigadier.builder.RequiredArgumentBuilder;
|
import com.mojang.brigadier.builder.RequiredArgumentBuilder;
|
||||||
import com.mojang.brigadier.tree.LiteralCommandNode;
|
import com.mojang.brigadier.tree.LiteralCommandNode;
|
||||||
|
import io.papermc.paper.InternalAPIBridge;
|
||||||
import io.papermc.paper.plugin.bootstrap.BootstrapContext;
|
import io.papermc.paper.plugin.bootstrap.BootstrapContext;
|
||||||
import io.papermc.paper.plugin.bootstrap.PluginBootstrap;
|
import io.papermc.paper.plugin.bootstrap.PluginBootstrap;
|
||||||
import io.papermc.paper.plugin.configuration.PluginMeta;
|
import io.papermc.paper.plugin.configuration.PluginMeta;
|
||||||
@ -13,6 +14,7 @@ import io.papermc.paper.plugin.lifecycle.event.registrar.Registrar;
|
|||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.function.Predicate;
|
||||||
import org.jetbrains.annotations.ApiStatus;
|
import org.jetbrains.annotations.ApiStatus;
|
||||||
import org.jetbrains.annotations.Unmodifiable;
|
import org.jetbrains.annotations.Unmodifiable;
|
||||||
import org.jspecify.annotations.NullMarked;
|
import org.jspecify.annotations.NullMarked;
|
||||||
@ -85,6 +87,22 @@ public interface Commands extends Registrar {
|
|||||||
return RequiredArgumentBuilder.argument(name, argumentType);
|
return RequiredArgumentBuilder.argument(name, argumentType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a restricted {@link Predicate} that wraps the given predicate.
|
||||||
|
* <p>
|
||||||
|
* A restricted predicate prevents execution in unattended contexts, such as from
|
||||||
|
* chat click events. A warning is shown on the client before executing the command.
|
||||||
|
* <p>
|
||||||
|
* This is used by vanilla to prevent invocation of sensitive commands (like op) from
|
||||||
|
* players without their knowledge.
|
||||||
|
*
|
||||||
|
* @param predicate the original predicate to wrap
|
||||||
|
* @return a new predicate with restricted execution behavior
|
||||||
|
*/
|
||||||
|
static Predicate<CommandSourceStack> restricted(final Predicate<CommandSourceStack> predicate) {
|
||||||
|
return InternalAPIBridge.get().restricted(predicate);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the underlying {@link CommandDispatcher}.
|
* Gets the underlying {@link CommandDispatcher}.
|
||||||
*
|
*
|
||||||
|
|||||||
@ -4,6 +4,8 @@ import com.destroystokyo.paper.util.SneakyThrow;
|
|||||||
import org.jetbrains.annotations.ApiStatus;
|
import org.jetbrains.annotations.ApiStatus;
|
||||||
import org.jspecify.annotations.NullMarked;
|
import org.jspecify.annotations.NullMarked;
|
||||||
import org.jspecify.annotations.Nullable;
|
import org.jspecify.annotations.Nullable;
|
||||||
|
import java.lang.reflect.Constructor;
|
||||||
|
import java.lang.reflect.InaccessibleObjectException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An <b>internal</b> utility type that holds logic for loading a provider-like type from a classloaders.
|
* An <b>internal</b> utility type that holds logic for loading a provider-like type from a classloaders.
|
||||||
@ -56,7 +58,14 @@ public final class ProviderUtil {
|
|||||||
throw new ClassCastException("class '%s' does not extend '%s'".formatted(clazz, classType));
|
throw new ClassCastException("class '%s' does not extend '%s'".formatted(clazz, classType));
|
||||||
}
|
}
|
||||||
|
|
||||||
clazzInstance = pluginClass.getDeclaredConstructor().newInstance();
|
final Constructor<? extends T> constructor = pluginClass.getDeclaredConstructor();
|
||||||
|
try {
|
||||||
|
constructor.setAccessible(true); // Allow non-public constructors
|
||||||
|
} catch (final InaccessibleObjectException | SecurityException ex) {
|
||||||
|
throw new RuntimeException("Inaccessible constructor");
|
||||||
|
}
|
||||||
|
|
||||||
|
clazzInstance = constructor.newInstance();
|
||||||
} catch (final IllegalAccessException exception) {
|
} catch (final IllegalAccessException exception) {
|
||||||
throw new RuntimeException("No public constructor");
|
throw new RuntimeException("No public constructor");
|
||||||
} catch (final InstantiationException exception) {
|
} catch (final InstantiationException exception) {
|
||||||
|
|||||||
@ -76,16 +76,14 @@ public sealed interface RegistryKey<T> extends Keyed permits RegistryKeyImpl {
|
|||||||
*/
|
*/
|
||||||
RegistryKey<PotionEffectType> MOB_EFFECT = create("mob_effect");
|
RegistryKey<PotionEffectType> MOB_EFFECT = create("mob_effect");
|
||||||
/**
|
/**
|
||||||
* @apiNote DO NOT USE
|
* Built-in registry for block types.
|
||||||
|
* @see io.papermc.paper.registry.keys.BlockTypeKeys
|
||||||
*/
|
*/
|
||||||
@ApiStatus.Internal
|
|
||||||
RegistryKey<BlockType> BLOCK = create("block");
|
RegistryKey<BlockType> BLOCK = create("block");
|
||||||
/**
|
/**
|
||||||
* @apiNote use preferably only in the context of registry entries.
|
* Built-in registry for item types.
|
||||||
* @see io.papermc.paper.registry.data
|
|
||||||
* @see io.papermc.paper.registry.keys.ItemTypeKeys
|
* @see io.papermc.paper.registry.keys.ItemTypeKeys
|
||||||
*/
|
*/
|
||||||
@ApiStatus.Experimental // Paper - already required for registry builders
|
|
||||||
RegistryKey<ItemType> ITEM = create("item");
|
RegistryKey<ItemType> ITEM = create("item");
|
||||||
/**
|
/**
|
||||||
* Built-in registry for villager professions.
|
* Built-in registry for villager professions.
|
||||||
|
|||||||
@ -37,7 +37,7 @@ public enum SoundCategory implements Sound.Source.Provider {
|
|||||||
case PLAYERS -> Sound.Source.PLAYER;
|
case PLAYERS -> Sound.Source.PLAYER;
|
||||||
case AMBIENT -> Sound.Source.AMBIENT;
|
case AMBIENT -> Sound.Source.AMBIENT;
|
||||||
case VOICE -> Sound.Source.VOICE;
|
case VOICE -> Sound.Source.VOICE;
|
||||||
case UI -> throw new UnsupportedOperationException("Waiting on adventure release for the UI sound source"); // todo adventure
|
case UI -> Sound.Source.UI;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,9 +2,10 @@ package org.bukkit.block;
|
|||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
import net.kyori.adventure.key.Key;
|
||||||
|
import net.kyori.adventure.key.KeyPattern;
|
||||||
import org.bukkit.Keyed;
|
import org.bukkit.Keyed;
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
import org.bukkit.NamespacedKey;
|
|
||||||
import org.bukkit.Registry;
|
import org.bukkit.Registry;
|
||||||
import org.bukkit.Translatable;
|
import org.bukkit.Translatable;
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
@ -82,7 +83,6 @@ import org.bukkit.block.data.type.MangrovePropagule;
|
|||||||
import org.bukkit.block.data.type.MossyCarpet;
|
import org.bukkit.block.data.type.MossyCarpet;
|
||||||
import org.bukkit.block.data.type.NoteBlock;
|
import org.bukkit.block.data.type.NoteBlock;
|
||||||
import org.bukkit.block.data.type.Observer;
|
import org.bukkit.block.data.type.Observer;
|
||||||
import org.bukkit.block.data.type.PinkPetals;
|
|
||||||
import org.bukkit.block.data.type.Piston;
|
import org.bukkit.block.data.type.Piston;
|
||||||
import org.bukkit.block.data.type.PistonHead;
|
import org.bukkit.block.data.type.PistonHead;
|
||||||
import org.bukkit.block.data.type.PitcherCrop;
|
import org.bukkit.block.data.type.PitcherCrop;
|
||||||
@ -122,18 +122,14 @@ import org.bukkit.block.data.type.WallHangingSign;
|
|||||||
import org.bukkit.block.data.type.WallSign;
|
import org.bukkit.block.data.type.WallSign;
|
||||||
import org.bukkit.block.data.type.WallSkull;
|
import org.bukkit.block.data.type.WallSkull;
|
||||||
import org.bukkit.inventory.ItemType;
|
import org.bukkit.inventory.ItemType;
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
import org.jetbrains.annotations.Unmodifiable;
|
import org.jetbrains.annotations.Unmodifiable;
|
||||||
|
import org.jspecify.annotations.NullMarked;
|
||||||
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* While this API is in a public interface, it is not intended for use by
|
* Represents a block type.
|
||||||
* plugins until further notice. The purpose of these types is to make
|
|
||||||
* {@link Material} more maintenance friendly, but will in due time be the
|
|
||||||
* official replacement for the aforementioned enum. Entirely incompatible
|
|
||||||
* changes may occur. Do not use this API in plugins.
|
|
||||||
*/
|
*/
|
||||||
@org.jetbrains.annotations.ApiStatus.Experimental // Paper - data component API - already required for data component API
|
@NullMarked
|
||||||
public interface BlockType extends Keyed, Translatable, net.kyori.adventure.translation.Translatable, io.papermc.paper.world.flag.FeatureDependant { // Paper - add translatable & feature flag API
|
public interface BlockType extends Keyed, Translatable, net.kyori.adventure.translation.Translatable, io.papermc.paper.world.flag.FeatureDependant { // Paper - add translatable & feature flag API
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -150,7 +146,6 @@ public interface BlockType extends Keyed, Translatable, net.kyori.adventure.tran
|
|||||||
*
|
*
|
||||||
* @return the BlockData class of this BlockType
|
* @return the BlockData class of this BlockType
|
||||||
*/
|
*/
|
||||||
@NotNull
|
|
||||||
@Override
|
@Override
|
||||||
Class<B> getBlockDataClass();
|
Class<B> getBlockDataClass();
|
||||||
|
|
||||||
@ -161,7 +156,6 @@ public interface BlockType extends Keyed, Translatable, net.kyori.adventure.tran
|
|||||||
* @param consumer consumer to run on new instance before returning
|
* @param consumer consumer to run on new instance before returning
|
||||||
* @return new data instance
|
* @return new data instance
|
||||||
*/
|
*/
|
||||||
@NotNull
|
|
||||||
B createBlockData(@Nullable Consumer<? super B> consumer);
|
B createBlockData(@Nullable Consumer<? super B> consumer);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -170,7 +164,6 @@ public interface BlockType extends Keyed, Translatable, net.kyori.adventure.tran
|
|||||||
*
|
*
|
||||||
* @return new data instance
|
* @return new data instance
|
||||||
*/
|
*/
|
||||||
@NotNull
|
|
||||||
@Override
|
@Override
|
||||||
B createBlockData();
|
B createBlockData();
|
||||||
|
|
||||||
@ -181,7 +174,7 @@ public interface BlockType extends Keyed, Translatable, net.kyori.adventure.tran
|
|||||||
* @return new block data collection
|
* @return new block data collection
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
@Unmodifiable @NotNull Collection<B> createBlockDataStates();
|
@Unmodifiable Collection<B> createBlockDataStates();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new {@link BlockData} instance for this block type, with all
|
* Creates a new {@link BlockData} instance for this block type, with all
|
||||||
@ -192,7 +185,6 @@ public interface BlockType extends Keyed, Translatable, net.kyori.adventure.tran
|
|||||||
* @return new data instance
|
* @return new data instance
|
||||||
* @throws IllegalArgumentException if the specified data is not valid
|
* @throws IllegalArgumentException if the specified data is not valid
|
||||||
*/
|
*/
|
||||||
@NotNull
|
|
||||||
B createBlockData(@Nullable String data);
|
B createBlockData(@Nullable String data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2411,10 +2403,10 @@ public interface BlockType extends Keyed, Translatable, net.kyori.adventure.tran
|
|||||||
// End generate - BlockType
|
// End generate - BlockType
|
||||||
//</editor-fold>
|
//</editor-fold>
|
||||||
|
|
||||||
@NotNull
|
@SuppressWarnings("unchecked")
|
||||||
private static <B extends BlockType> B getBlockType(@NotNull String key) {
|
private static <B extends BlockType> B getBlockType(@KeyPattern.Value final String key) {
|
||||||
// Cast instead of using BlockType#typed, since block type can be a mock during testing and would return null
|
// Cast instead of using BlockType#typed, since block type can be a mock during testing and would return null
|
||||||
return (B) Registry.BLOCK.getOrThrow(NamespacedKey.minecraft(key));
|
return (B) Registry.BLOCK.getOrThrow(Key.key(Key.MINECRAFT_NAMESPACE, key));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -2422,7 +2414,6 @@ public interface BlockType extends Keyed, Translatable, net.kyori.adventure.tran
|
|||||||
*
|
*
|
||||||
* @return the typed block type.
|
* @return the typed block type.
|
||||||
*/
|
*/
|
||||||
@NotNull
|
|
||||||
BlockType.Typed<BlockData> typed();
|
BlockType.Typed<BlockData> typed();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -2432,8 +2423,7 @@ public interface BlockType extends Keyed, Translatable, net.kyori.adventure.tran
|
|||||||
* @param <B> the generic type of the block data to type this block type with.
|
* @param <B> the generic type of the block data to type this block type with.
|
||||||
* @return the typed block type.
|
* @return the typed block type.
|
||||||
*/
|
*/
|
||||||
@NotNull
|
<B extends BlockData> BlockType.Typed<B> typed(Class<B> blockDataType);
|
||||||
<B extends BlockData> BlockType.Typed<B> typed(@NotNull Class<B> blockDataType);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if this BlockType has a corresponding {@link ItemType}.
|
* Returns true if this BlockType has a corresponding {@link ItemType}.
|
||||||
@ -2447,12 +2437,14 @@ public interface BlockType extends Keyed, Translatable, net.kyori.adventure.tran
|
|||||||
* Returns the corresponding {@link ItemType} for the given BlockType.
|
* Returns the corresponding {@link ItemType} for the given BlockType.
|
||||||
* <p>
|
* <p>
|
||||||
* If there is no corresponding {@link ItemType} an error will be thrown.
|
* If there is no corresponding {@link ItemType} an error will be thrown.
|
||||||
|
* <p>This is <b>NOT</b> the same as the {@link ItemType} with the same key,
|
||||||
|
* but instead is the item associated with this block if this block
|
||||||
|
* can be represented with an item.</p>
|
||||||
*
|
*
|
||||||
* @return the corresponding ItemType
|
* @return the corresponding ItemType
|
||||||
* @see #hasItemType()
|
* @see #hasItemType()
|
||||||
* @see BlockData#getPlacementMaterial()
|
* @see BlockData#getPlacementMaterial()
|
||||||
*/
|
*/
|
||||||
@NotNull
|
|
||||||
ItemType getItemType();
|
ItemType getItemType();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -2460,7 +2452,6 @@ public interface BlockType extends Keyed, Translatable, net.kyori.adventure.tran
|
|||||||
*
|
*
|
||||||
* @return the BlockData class of this BlockType
|
* @return the BlockData class of this BlockType
|
||||||
*/
|
*/
|
||||||
@NotNull
|
|
||||||
Class<? extends BlockData> getBlockDataClass();
|
Class<? extends BlockData> getBlockDataClass();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -2469,7 +2460,6 @@ public interface BlockType extends Keyed, Translatable, net.kyori.adventure.tran
|
|||||||
*
|
*
|
||||||
* @return new data instance
|
* @return new data instance
|
||||||
*/
|
*/
|
||||||
@NotNull
|
|
||||||
BlockData createBlockData();
|
BlockData createBlockData();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -2478,7 +2468,7 @@ public interface BlockType extends Keyed, Translatable, net.kyori.adventure.tran
|
|||||||
*
|
*
|
||||||
* @return new block data collection
|
* @return new block data collection
|
||||||
*/
|
*/
|
||||||
@Unmodifiable @NotNull Collection<? extends BlockData> createBlockDataStates();
|
@Unmodifiable Collection<? extends BlockData> createBlockDataStates();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new {@link BlockData} instance for this block type, with all
|
* Creates a new {@link BlockData} instance for this block type, with all
|
||||||
@ -2489,7 +2479,6 @@ public interface BlockType extends Keyed, Translatable, net.kyori.adventure.tran
|
|||||||
* @return new data instance
|
* @return new data instance
|
||||||
* @throws IllegalArgumentException if the specified data is not valid
|
* @throws IllegalArgumentException if the specified data is not valid
|
||||||
*/
|
*/
|
||||||
@NotNull
|
|
||||||
BlockData createBlockData(@Nullable String data);
|
BlockData createBlockData(@Nullable String data);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -2607,7 +2596,7 @@ public interface BlockType extends Keyed, Translatable, net.kyori.adventure.tran
|
|||||||
* @deprecated use {@link io.papermc.paper.world.flag.FeatureFlagSetHolder#isEnabled(io.papermc.paper.world.flag.FeatureDependant)}
|
* @deprecated use {@link io.papermc.paper.world.flag.FeatureFlagSetHolder#isEnabled(io.papermc.paper.world.flag.FeatureDependant)}
|
||||||
*/
|
*/
|
||||||
@Deprecated(forRemoval = true, since = "1.21.1") // Paper
|
@Deprecated(forRemoval = true, since = "1.21.1") // Paper
|
||||||
boolean isEnabledByFeature(@NotNull World world);
|
boolean isEnabledByFeature(World world);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tries to convert this BlockType into a Material
|
* Tries to convert this BlockType into a Material
|
||||||
@ -2619,21 +2608,17 @@ public interface BlockType extends Keyed, Translatable, net.kyori.adventure.tran
|
|||||||
@Deprecated(since = "1.20.6")
|
@Deprecated(since = "1.20.6")
|
||||||
Material asMaterial();
|
Material asMaterial();
|
||||||
|
|
||||||
// Paper start - add Translatable
|
|
||||||
/**
|
/**
|
||||||
* @deprecated use {@link #translationKey()} and {@link net.kyori.adventure.text.Component#translatable(net.kyori.adventure.translation.Translatable)}
|
* @deprecated use {@link #translationKey()} and {@link net.kyori.adventure.text.Component#translatable(net.kyori.adventure.translation.Translatable)}
|
||||||
*/
|
*/
|
||||||
@Deprecated(forRemoval = true)
|
@Deprecated(forRemoval = true)
|
||||||
@Override
|
@Override
|
||||||
@NotNull String getTranslationKey();
|
String getTranslationKey();
|
||||||
// Paper end - add Translatable
|
|
||||||
|
|
||||||
// Paper start - hasCollision API
|
|
||||||
/**
|
/**
|
||||||
* Checks if this block type has collision.
|
* Checks if this block type has collision.
|
||||||
* <p>
|
* <p>
|
||||||
* @return false if this block never has collision, true if it <b>might</b> have collision
|
* @return false if this block never has collision, true if it <b>might</b> have collision
|
||||||
*/
|
*/
|
||||||
boolean hasCollision();
|
boolean hasCollision();
|
||||||
// Paper end - hasCollision API
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,10 +1,13 @@
|
|||||||
package org.bukkit.inventory;
|
package org.bukkit.inventory;
|
||||||
|
|
||||||
import com.google.common.collect.Multimap;
|
import com.google.common.collect.Multimap;
|
||||||
|
import io.papermc.paper.datacomponent.DataComponentType;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
import net.kyori.adventure.key.Key;
|
||||||
|
import net.kyori.adventure.key.KeyPattern;
|
||||||
import org.bukkit.Keyed;
|
import org.bukkit.Keyed;
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
import org.bukkit.NamespacedKey;
|
|
||||||
import org.bukkit.Registry;
|
import org.bukkit.Registry;
|
||||||
import org.bukkit.Translatable;
|
import org.bukkit.Translatable;
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
@ -36,17 +39,14 @@ import org.bukkit.inventory.meta.SpawnEggMeta;
|
|||||||
import org.bukkit.inventory.meta.SuspiciousStewMeta;
|
import org.bukkit.inventory.meta.SuspiciousStewMeta;
|
||||||
import org.bukkit.inventory.meta.TropicalFishBucketMeta;
|
import org.bukkit.inventory.meta.TropicalFishBucketMeta;
|
||||||
import org.jetbrains.annotations.ApiStatus;
|
import org.jetbrains.annotations.ApiStatus;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.Unmodifiable;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jspecify.annotations.NullMarked;
|
||||||
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* While this API is in a public interface, it is not intended for use by
|
* Represents an item type.
|
||||||
* plugins until further notice. The purpose of these types is to make
|
|
||||||
* {@link Material} more maintenance friendly, but will in due time be the
|
|
||||||
* official replacement for the aforementioned enum. Entirely incompatible
|
|
||||||
* changes may occur. Do not use this API in plugins.
|
|
||||||
*/
|
*/
|
||||||
@ApiStatus.Experimental // Paper - already required for registry builders
|
@NullMarked
|
||||||
public interface ItemType extends Keyed, Translatable, net.kyori.adventure.translation.Translatable, io.papermc.paper.world.flag.FeatureDependant { // Paper - add Translatable & feature flag API
|
public interface ItemType extends Keyed, Translatable, net.kyori.adventure.translation.Translatable, io.papermc.paper.world.flag.FeatureDependant { // Paper - add Translatable & feature flag API
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -54,7 +54,11 @@ public interface ItemType extends Keyed, Translatable, net.kyori.adventure.trans
|
|||||||
* at compile time.
|
* at compile time.
|
||||||
*
|
*
|
||||||
* @param <M> the generic type of the item meta that represents the item type.
|
* @param <M> the generic type of the item meta that represents the item type.
|
||||||
|
* @apiNote Do not use methods exclusive to this interface unless you are
|
||||||
|
* fine with them being possibly removed in the future.
|
||||||
*/
|
*/
|
||||||
|
@ApiStatus.Experimental
|
||||||
|
@ApiStatus.NonExtendable
|
||||||
interface Typed<M extends ItemMeta> extends ItemType {
|
interface Typed<M extends ItemMeta> extends ItemType {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -63,7 +67,7 @@ public interface ItemType extends Keyed, Translatable, net.kyori.adventure.trans
|
|||||||
* @return the ItemMeta class of this ItemType
|
* @return the ItemMeta class of this ItemType
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
@NotNull
|
@ApiStatus.Experimental
|
||||||
Class<M> getItemMetaClass();
|
Class<M> getItemMetaClass();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -73,7 +77,7 @@ public interface ItemType extends Keyed, Translatable, net.kyori.adventure.trans
|
|||||||
* May be null if no intent exists to mutate the item meta at this point.
|
* May be null if no intent exists to mutate the item meta at this point.
|
||||||
* @return the created and configured item stack.
|
* @return the created and configured item stack.
|
||||||
*/
|
*/
|
||||||
@NotNull
|
@ApiStatus.Experimental
|
||||||
ItemStack createItemStack(@Nullable Consumer<? super M> metaConfigurator);
|
ItemStack createItemStack(@Nullable Consumer<? super M> metaConfigurator);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -84,7 +88,7 @@ public interface ItemType extends Keyed, Translatable, net.kyori.adventure.trans
|
|||||||
* May be null if no intent exists to mutate the item meta at this point.
|
* May be null if no intent exists to mutate the item meta at this point.
|
||||||
* @return the created and configured item stack.
|
* @return the created and configured item stack.
|
||||||
*/
|
*/
|
||||||
@NotNull
|
@ApiStatus.Experimental
|
||||||
ItemStack createItemStack(int amount, @Nullable Consumer<? super M> metaConfigurator);
|
ItemStack createItemStack(int amount, @Nullable Consumer<? super M> metaConfigurator);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2923,18 +2927,19 @@ public interface ItemType extends Keyed, Translatable, net.kyori.adventure.trans
|
|||||||
// End generate - ItemType
|
// End generate - ItemType
|
||||||
//</editor-fold>
|
//</editor-fold>
|
||||||
|
|
||||||
@NotNull
|
@SuppressWarnings("unchecked")
|
||||||
private static <M extends ItemType> M getItemType(@NotNull String key) {
|
private static <M extends ItemType> M getItemType(@KeyPattern.Value final String key) {
|
||||||
// Cast instead of using ItemType#typed, since item type can be a mock during testing and would return null
|
// Cast instead of using ItemType#typed, since item type can be a mock during testing and would return null
|
||||||
return (M) Registry.ITEM.getOrThrow(NamespacedKey.minecraft(key));
|
return (M) Registry.ITEM.getOrThrow(Key.key(Key.MINECRAFT_NAMESPACE, key));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Yields this item type as a typed version of itself with a plain {@link ItemMeta} representing it.
|
* Yields this item type as a typed version of itself with a plain {@link ItemMeta} representing it.
|
||||||
*
|
*
|
||||||
* @return the typed item type.
|
* @return the typed item type.
|
||||||
|
* @apiNote The Typed interface is experimental and may be removed in future versions.
|
||||||
*/
|
*/
|
||||||
@NotNull
|
@ApiStatus.Experimental
|
||||||
Typed<ItemMeta> typed();
|
Typed<ItemMeta> typed();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -2943,16 +2948,16 @@ public interface ItemType extends Keyed, Translatable, net.kyori.adventure.trans
|
|||||||
* @param itemMetaType the class type of the {@link ItemMeta} to type this {@link ItemType} with.
|
* @param itemMetaType the class type of the {@link ItemMeta} to type this {@link ItemType} with.
|
||||||
* @param <M> the generic type of the item meta to type this item type with.
|
* @param <M> the generic type of the item meta to type this item type with.
|
||||||
* @return the typed item type.
|
* @return the typed item type.
|
||||||
|
* @apiNote The Typed interface is experimental and may be removed in future versions.
|
||||||
*/
|
*/
|
||||||
@NotNull
|
@ApiStatus.Experimental
|
||||||
<M extends ItemMeta> Typed<M> typed(@NotNull Class<M> itemMetaType);
|
<M extends ItemMeta> Typed<M> typed(Class<M> itemMetaType);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a new itemstack with this item type that has the amount 1.
|
* Constructs a new itemstack with this item type that has the amount 1.
|
||||||
*
|
*
|
||||||
* @return the constructed item stack.
|
* @return the constructed item stack.
|
||||||
*/
|
*/
|
||||||
@NotNull
|
|
||||||
ItemStack createItemStack();
|
ItemStack createItemStack();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -2961,7 +2966,6 @@ public interface ItemType extends Keyed, Translatable, net.kyori.adventure.trans
|
|||||||
* @param amount the amount of the item stack.
|
* @param amount the amount of the item stack.
|
||||||
* @return the constructed item stack.
|
* @return the constructed item stack.
|
||||||
*/
|
*/
|
||||||
@NotNull
|
|
||||||
ItemStack createItemStack(int amount);
|
ItemStack createItemStack(int amount);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -2976,11 +2980,12 @@ public interface ItemType extends Keyed, Translatable, net.kyori.adventure.trans
|
|||||||
* Returns the corresponding {@link BlockType} for the given ItemType.
|
* Returns the corresponding {@link BlockType} for the given ItemType.
|
||||||
* <p>
|
* <p>
|
||||||
* If there is no corresponding {@link BlockType} an error will be thrown.
|
* If there is no corresponding {@link BlockType} an error will be thrown.
|
||||||
|
* <p>This is <b>NOT</b> the same as the {@link BlockType} with the same key,
|
||||||
|
* but instead is the block associated with this item if this item represents a block.</p>
|
||||||
*
|
*
|
||||||
* @return the corresponding BlockType
|
* @return the corresponding BlockType
|
||||||
* @see #hasBlockType()
|
* @see #hasBlockType()
|
||||||
*/
|
*/
|
||||||
@NotNull
|
|
||||||
BlockType getBlockType();
|
BlockType getBlockType();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -2988,7 +2993,6 @@ public interface ItemType extends Keyed, Translatable, net.kyori.adventure.trans
|
|||||||
*
|
*
|
||||||
* @return the ItemMeta class of this ItemType
|
* @return the ItemMeta class of this ItemType
|
||||||
*/
|
*/
|
||||||
@NotNull
|
|
||||||
Class<? extends ItemMeta> getItemMetaClass();
|
Class<? extends ItemMeta> getItemMetaClass();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -3064,20 +3068,8 @@ public interface ItemType extends Keyed, Translatable, net.kyori.adventure.trans
|
|||||||
*
|
*
|
||||||
* @return the item left behind when crafting, or null if nothing is.
|
* @return the item left behind when crafting, or null if nothing is.
|
||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable ItemType getCraftingRemainingItem();
|
||||||
ItemType getCraftingRemainingItem();
|
|
||||||
|
|
||||||
// /**
|
|
||||||
// * Get the best suitable slot for this item type.
|
|
||||||
// *
|
|
||||||
// * For most items this will be {@link EquipmentSlot#HAND}.
|
|
||||||
// *
|
|
||||||
// * @return the best EquipmentSlot for this item type
|
|
||||||
// */
|
|
||||||
// @NotNull
|
|
||||||
// EquipmentSlot getEquipmentSlot();
|
|
||||||
|
|
||||||
// Paper start - improve default item attribute API
|
|
||||||
/**
|
/**
|
||||||
* Return an immutable copy of all default {@link Attribute}s and their
|
* Return an immutable copy of all default {@link Attribute}s and their
|
||||||
* {@link AttributeModifier}s.
|
* {@link AttributeModifier}s.
|
||||||
@ -3089,8 +3081,7 @@ public interface ItemType extends Keyed, Translatable, net.kyori.adventure.trans
|
|||||||
* @return the immutable {@link Multimap} with the respective default
|
* @return the immutable {@link Multimap} with the respective default
|
||||||
* Attributes and modifiers, or an empty map if no attributes are set.
|
* Attributes and modifiers, or an empty map if no attributes are set.
|
||||||
*/
|
*/
|
||||||
@NotNull @org.jetbrains.annotations.Unmodifiable Multimap<Attribute, AttributeModifier> getDefaultAttributeModifiers();
|
@Unmodifiable Multimap<Attribute, AttributeModifier> getDefaultAttributeModifiers();
|
||||||
// Paper end - improve default item attribute API
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return an immutable copy of all default {@link Attribute}s and their
|
* Return an immutable copy of all default {@link Attribute}s and their
|
||||||
@ -3103,8 +3094,7 @@ public interface ItemType extends Keyed, Translatable, net.kyori.adventure.trans
|
|||||||
* @return the immutable {@link Multimap} with the respective default
|
* @return the immutable {@link Multimap} with the respective default
|
||||||
* Attributes and modifiers, or an empty map if no attributes are set.
|
* Attributes and modifiers, or an empty map if no attributes are set.
|
||||||
*/
|
*/
|
||||||
@NotNull
|
@Unmodifiable Multimap<Attribute, AttributeModifier> getDefaultAttributeModifiers(EquipmentSlot slot);
|
||||||
Multimap<Attribute, AttributeModifier> getDefaultAttributeModifiers(@NotNull EquipmentSlot slot);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the {@link CreativeCategory} to which this item type belongs.
|
* Get the {@link CreativeCategory} to which this item type belongs.
|
||||||
@ -3112,9 +3102,8 @@ public interface ItemType extends Keyed, Translatable, net.kyori.adventure.trans
|
|||||||
* @return the creative category. null if does not belong to a category
|
* @return the creative category. null if does not belong to a category
|
||||||
<!-- * @deprecated use #getCreativeCategories() -->
|
<!-- * @deprecated use #getCreativeCategories() -->
|
||||||
*/
|
*/
|
||||||
@Nullable
|
|
||||||
@Deprecated(since = "1.20.6", forRemoval = true)
|
@Deprecated(since = "1.20.6", forRemoval = true)
|
||||||
CreativeCategory getCreativeCategory();
|
@Nullable CreativeCategory getCreativeCategory();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets if the ItemType is enabled by the features in a world.
|
* Gets if the ItemType is enabled by the features in a world.
|
||||||
@ -3124,7 +3113,7 @@ public interface ItemType extends Keyed, Translatable, net.kyori.adventure.trans
|
|||||||
* @deprecated use {@link io.papermc.paper.world.flag.FeatureFlagSetHolder#isEnabled(io.papermc.paper.world.flag.FeatureDependant)}
|
* @deprecated use {@link io.papermc.paper.world.flag.FeatureFlagSetHolder#isEnabled(io.papermc.paper.world.flag.FeatureDependant)}
|
||||||
*/
|
*/
|
||||||
@Deprecated(forRemoval = true, since = "1.21.1") // Paper
|
@Deprecated(forRemoval = true, since = "1.21.1") // Paper
|
||||||
boolean isEnabledByFeature(@NotNull World world);
|
boolean isEnabledByFeature(World world);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tries to convert this ItemType into a Material
|
* Tries to convert this ItemType into a Material
|
||||||
@ -3132,38 +3121,33 @@ public interface ItemType extends Keyed, Translatable, net.kyori.adventure.trans
|
|||||||
* @return the converted Material or null
|
* @return the converted Material or null
|
||||||
* @deprecated only for internal use
|
* @deprecated only for internal use
|
||||||
*/
|
*/
|
||||||
@Nullable
|
|
||||||
@Deprecated(since = "1.20.6")
|
@Deprecated(since = "1.20.6")
|
||||||
Material asMaterial();
|
@Nullable Material asMaterial();
|
||||||
|
|
||||||
// Paper start - add Translatable
|
|
||||||
/**
|
/**
|
||||||
* @deprecated use {@link #translationKey()} and {@link net.kyori.adventure.text.Component#translatable(net.kyori.adventure.translation.Translatable)}
|
* @deprecated use {@link #translationKey()} and {@link net.kyori.adventure.text.Component#translatable(net.kyori.adventure.translation.Translatable)}
|
||||||
*/
|
*/
|
||||||
@Deprecated(forRemoval = true)
|
@Deprecated(forRemoval = true)
|
||||||
@Override
|
@Override
|
||||||
@NotNull String getTranslationKey();
|
String getTranslationKey();
|
||||||
// Paper end - add Translatable
|
|
||||||
|
|
||||||
// Paper start - expand ItemRarity API
|
|
||||||
/**
|
/**
|
||||||
* Returns the item rarity for the item.
|
* Returns the item rarity for the item.
|
||||||
*
|
*
|
||||||
* @return the item rarity (or null if none is set)
|
* @return the item rarity (or null if none is set)
|
||||||
*/
|
*/
|
||||||
@Nullable ItemRarity getItemRarity();
|
@Nullable ItemRarity getItemRarity();
|
||||||
// Paper end - expand ItemRarity API
|
|
||||||
// Paper start - data component API
|
|
||||||
/**
|
/**
|
||||||
* Gets the default value of the data component type for this item type.
|
* Gets the default value of the data component type for this item type.
|
||||||
*
|
*
|
||||||
* @param type the data component type
|
* @param type the data component type
|
||||||
* @param <T> the value type
|
* @param <T> the value type
|
||||||
* @return the default value or {@code null} if there is none
|
* @return the default value or {@code null} if there is none
|
||||||
* @see #hasDefaultData(io.papermc.paper.datacomponent.DataComponentType) for DataComponentType.NonValued
|
* @see #hasDefaultData(DataComponentType) for DataComponentType.NonValued
|
||||||
*/
|
*/
|
||||||
@org.jetbrains.annotations.ApiStatus.Experimental
|
@ApiStatus.Experimental
|
||||||
@Nullable <T> T getDefaultData(io.papermc.paper.datacomponent.DataComponentType.@NotNull Valued<T> type);
|
@Nullable <T> T getDefaultData(DataComponentType.Valued<T> type);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if the data component type has a default value for this item type.
|
* Checks if the data component type has a default value for this item type.
|
||||||
@ -3172,14 +3156,13 @@ public interface ItemType extends Keyed, Translatable, net.kyori.adventure.trans
|
|||||||
* @return {@code true} if there is a default value
|
* @return {@code true} if there is a default value
|
||||||
*/
|
*/
|
||||||
@org.jetbrains.annotations.ApiStatus.Experimental
|
@org.jetbrains.annotations.ApiStatus.Experimental
|
||||||
boolean hasDefaultData(io.papermc.paper.datacomponent.@NotNull DataComponentType type);
|
boolean hasDefaultData(DataComponentType type);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the default data component types for this item type.
|
* Gets the default data component types for this item type.
|
||||||
*
|
*
|
||||||
* @return an immutable set of data component types
|
* @return an immutable set of data component types
|
||||||
*/
|
*/
|
||||||
@org.jetbrains.annotations.ApiStatus.Experimental
|
@ApiStatus.Experimental
|
||||||
java.util.@org.jetbrains.annotations.Unmodifiable @NotNull Set<io.papermc.paper.datacomponent.DataComponentType> getDefaultDataTypes();
|
@Unmodifiable Set<DataComponentType> getDefaultDataTypes();
|
||||||
// Paper end - data component API
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -29,7 +29,7 @@ public interface PluginManager extends io.papermc.paper.plugin.PermissionManager
|
|||||||
/**
|
/**
|
||||||
* Checks if the given plugin is loaded and returns it when applicable
|
* Checks if the given plugin is loaded and returns it when applicable
|
||||||
* <p>
|
* <p>
|
||||||
* Please note that the name of the plugin is case-sensitive
|
* Please note that the name of the plugin is case-insensitive
|
||||||
*
|
*
|
||||||
* @param name Name of the plugin to check
|
* @param name Name of the plugin to check
|
||||||
* @return Plugin if it exists, otherwise null
|
* @return Plugin if it exists, otherwise null
|
||||||
@ -48,7 +48,7 @@ public interface PluginManager extends io.papermc.paper.plugin.PermissionManager
|
|||||||
/**
|
/**
|
||||||
* Checks if the given plugin is enabled or not
|
* Checks if the given plugin is enabled or not
|
||||||
* <p>
|
* <p>
|
||||||
* Please note that the name of the plugin is case-sensitive.
|
* Please note that the name of the plugin is case-insensitive.
|
||||||
*
|
*
|
||||||
* @param name Name of the plugin to check
|
* @param name Name of the plugin to check
|
||||||
* @return true if the plugin is enabled, otherwise false
|
* @return true if the plugin is enabled, otherwise false
|
||||||
|
|||||||
@ -464,7 +464,7 @@ public final class SimplePluginManager implements PluginManager {
|
|||||||
/**
|
/**
|
||||||
* Checks if the given plugin is loaded and returns it when applicable
|
* Checks if the given plugin is loaded and returns it when applicable
|
||||||
* <p>
|
* <p>
|
||||||
* Please note that the name of the plugin is case-sensitive
|
* Please note that the name of the plugin is case-insensitive
|
||||||
*
|
*
|
||||||
* @param name Name of the plugin to check
|
* @param name Name of the plugin to check
|
||||||
* @return Plugin if it exists, otherwise null
|
* @return Plugin if it exists, otherwise null
|
||||||
@ -486,7 +486,7 @@ public final class SimplePluginManager implements PluginManager {
|
|||||||
/**
|
/**
|
||||||
* Checks if the given plugin is enabled or not
|
* Checks if the given plugin is enabled or not
|
||||||
* <p>
|
* <p>
|
||||||
* Please note that the name of the plugin is case-sensitive.
|
* Please note that the name of the plugin is case-insensitive.
|
||||||
*
|
*
|
||||||
* @param name Name of the plugin to check
|
* @param name Name of the plugin to check
|
||||||
* @return true if the plugin is enabled, otherwise false
|
* @return true if the plugin is enabled, otherwise false
|
||||||
|
|||||||
@ -6,6 +6,7 @@ import java.io.File;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.lang.reflect.Constructor;
|
import java.lang.reflect.Constructor;
|
||||||
|
import java.lang.reflect.InaccessibleObjectException;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
@ -91,13 +92,20 @@ public final class PluginClassLoader extends URLClassLoader implements io.paperm
|
|||||||
try {
|
try {
|
||||||
pluginConstructor = pluginClass.getDeclaredConstructor();
|
pluginConstructor = pluginClass.getDeclaredConstructor();
|
||||||
} catch (NoSuchMethodException ex) {
|
} catch (NoSuchMethodException ex) {
|
||||||
throw new InvalidPluginException("main class `" + description.getMain() + "' must have a public no-args constructor", ex);
|
throw new InvalidPluginException("main class `" + description.getMain() + "' must have a no-args constructor", ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Support non-public constructors
|
||||||
|
pluginConstructor.setAccessible(true);
|
||||||
|
} catch (InaccessibleObjectException | SecurityException ex) {
|
||||||
|
throw new InvalidPluginException("main class `" + description.getMain() + "' constructor inaccessible", ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
plugin = pluginConstructor.newInstance();
|
plugin = pluginConstructor.newInstance();
|
||||||
} catch (IllegalAccessException ex) {
|
} catch (IllegalAccessException ex) {
|
||||||
throw new InvalidPluginException("main class `" + description.getMain() + "' constructor must be public", ex);
|
throw new InvalidPluginException("main class `" + description.getMain() + "' constructor inaccessible", ex);
|
||||||
} catch (InstantiationException ex) {
|
} catch (InstantiationException ex) {
|
||||||
throw new InvalidPluginException("main class `" + description.getMain() + "' must not be abstract", ex);
|
throw new InvalidPluginException("main class `" + description.getMain() + "' must not be abstract", ex);
|
||||||
} catch (IllegalArgumentException ex) {
|
} catch (IllegalArgumentException ex) {
|
||||||
|
|||||||
@ -8,13 +8,14 @@ import org.bukkit.block.spawner.SpawnerEntry;
|
|||||||
import org.bukkit.entity.EntitySnapshot;
|
import org.bukkit.entity.EntitySnapshot;
|
||||||
import org.bukkit.entity.EntityType;
|
import org.bukkit.entity.EntityType;
|
||||||
import org.bukkit.entity.minecart.SpawnerMinecart;
|
import org.bukkit.entity.minecart.SpawnerMinecart;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jspecify.annotations.NullMarked;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a basic entity spawner. <br>
|
* Represents a basic entity spawner. <br>
|
||||||
* May be a {@link SpawnerMinecart}, {@link CreatureSpawner} or {@link TrialSpawnerConfiguration}.
|
* May be a {@link SpawnerMinecart}, {@link CreatureSpawner} or {@link TrialSpawnerConfiguration}.
|
||||||
*/
|
*/
|
||||||
|
@NullMarked
|
||||||
public interface BaseSpawner {
|
public interface BaseSpawner {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -23,7 +24,7 @@ public interface BaseSpawner {
|
|||||||
* @return The creature type or null if it not set.
|
* @return The creature type or null if it not set.
|
||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
public EntityType getSpawnedType();
|
EntityType getSpawnedType();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the spawner's creature type. <br>
|
* Set the spawner's creature type. <br>
|
||||||
@ -31,7 +32,7 @@ public interface BaseSpawner {
|
|||||||
*
|
*
|
||||||
* @param creatureType The creature type or null to clear.
|
* @param creatureType The creature type or null to clear.
|
||||||
*/
|
*/
|
||||||
public void setSpawnedType(@Nullable EntityType creatureType);
|
void setSpawnedType(@Nullable EntityType creatureType);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the spawner's delay.
|
* Get the spawner's delay.
|
||||||
@ -40,14 +41,14 @@ public interface BaseSpawner {
|
|||||||
*
|
*
|
||||||
* @return The delay.
|
* @return The delay.
|
||||||
*/
|
*/
|
||||||
public int getDelay();
|
int getDelay();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the spawner's delay.
|
* Set the spawner's delay.
|
||||||
*
|
*
|
||||||
* @param delay The delay.
|
* @param delay The delay.
|
||||||
*/
|
*/
|
||||||
public void setDelay(int delay);
|
void setDelay(int delay);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the maximum distance(squared) a player can be in order for this
|
* Get the maximum distance(squared) a player can be in order for this
|
||||||
@ -61,7 +62,7 @@ public interface BaseSpawner {
|
|||||||
* @return the maximum distance(squared) a player can be in order for this
|
* @return the maximum distance(squared) a player can be in order for this
|
||||||
* spawner to be active.
|
* spawner to be active.
|
||||||
*/
|
*/
|
||||||
public int getRequiredPlayerRange();
|
int getRequiredPlayerRange();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the maximum distance (squared) a player can be in order for this
|
* Set the maximum distance (squared) a player can be in order for this
|
||||||
@ -73,7 +74,7 @@ public interface BaseSpawner {
|
|||||||
* @param requiredPlayerRange the maximum distance (squared) a player can be
|
* @param requiredPlayerRange the maximum distance (squared) a player can be
|
||||||
* in order for this spawner to be active.
|
* in order for this spawner to be active.
|
||||||
*/
|
*/
|
||||||
public void setRequiredPlayerRange(int requiredPlayerRange);
|
void setRequiredPlayerRange(int requiredPlayerRange);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the radius around which the spawner will attempt to spawn mobs in.
|
* Get the radius around which the spawner will attempt to spawn mobs in.
|
||||||
@ -89,7 +90,7 @@ public interface BaseSpawner {
|
|||||||
*
|
*
|
||||||
* @return the spawn range
|
* @return the spawn range
|
||||||
*/
|
*/
|
||||||
public int getSpawnRange();
|
int getSpawnRange();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the new spawn range.
|
* Set the new spawn range.
|
||||||
@ -98,7 +99,7 @@ public interface BaseSpawner {
|
|||||||
* @param spawnRange the new spawn range
|
* @param spawnRange the new spawn range
|
||||||
* @see #getSpawnRange()
|
* @see #getSpawnRange()
|
||||||
*/
|
*/
|
||||||
public void setSpawnRange(int spawnRange);
|
void setSpawnRange(int spawnRange);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the {@link EntitySnapshot} that will be spawned by this spawner or null
|
* Gets the {@link EntitySnapshot} that will be spawned by this spawner or null
|
||||||
@ -111,7 +112,7 @@ public interface BaseSpawner {
|
|||||||
* spawner.
|
* spawner.
|
||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
public EntitySnapshot getSpawnedEntity();
|
EntitySnapshot getSpawnedEntity();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the entity that will be spawned by this spawner. <br>
|
* Sets the entity that will be spawned by this spawner. <br>
|
||||||
@ -123,7 +124,7 @@ public interface BaseSpawner {
|
|||||||
*
|
*
|
||||||
* @param snapshot the entity snapshot or null to clear
|
* @param snapshot the entity snapshot or null to clear
|
||||||
*/
|
*/
|
||||||
public void setSpawnedEntity(@Nullable EntitySnapshot snapshot);
|
void setSpawnedEntity(@Nullable EntitySnapshot snapshot);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the {@link SpawnerEntry} that will be spawned by this spawner. <br>
|
* Sets the {@link SpawnerEntry} that will be spawned by this spawner. <br>
|
||||||
@ -132,14 +133,14 @@ public interface BaseSpawner {
|
|||||||
*
|
*
|
||||||
* @param spawnerEntry the spawner entry to use
|
* @param spawnerEntry the spawner entry to use
|
||||||
*/
|
*/
|
||||||
public void setSpawnedEntity(@NotNull SpawnerEntry spawnerEntry);
|
void setSpawnedEntity(SpawnerEntry spawnerEntry);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a new {@link EntitySnapshot} to the list of entities this spawner can
|
* Adds a new {@link EntitySnapshot} to the list of entities this spawner can
|
||||||
* spawn.
|
* spawn.
|
||||||
* <p>
|
* <p>
|
||||||
* The weight will determine how often this entry is chosen to spawn, higher
|
* The weight will determine how often this entry is chosen to spawn, higher
|
||||||
* weighted entries will spawn more often than lower weighted ones. <br>
|
* weighted entries will spawn more often than lower-weighted ones. <br>
|
||||||
* The {@link SpawnRule} will determine under what conditions this entry can
|
* The {@link SpawnRule} will determine under what conditions this entry can
|
||||||
* spawn, passing null will use the default conditions for the given entity.
|
* spawn, passing null will use the default conditions for the given entity.
|
||||||
*
|
*
|
||||||
@ -147,7 +148,7 @@ public interface BaseSpawner {
|
|||||||
* @param weight the weight
|
* @param weight the weight
|
||||||
* @param spawnRule the spawn rule for this entity, or null
|
* @param spawnRule the spawn rule for this entity, or null
|
||||||
*/
|
*/
|
||||||
public void addPotentialSpawn(@NotNull EntitySnapshot snapshot, int weight, @Nullable SpawnRule spawnRule);
|
void addPotentialSpawn(EntitySnapshot snapshot, int weight, @Nullable SpawnRule spawnRule);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a new {@link SpawnerEntry} to the list of entities this spawner can
|
* Adds a new {@link SpawnerEntry} to the list of entities this spawner can
|
||||||
@ -156,7 +157,7 @@ public interface BaseSpawner {
|
|||||||
* @param spawnerEntry the spawner entry to use
|
* @param spawnerEntry the spawner entry to use
|
||||||
* @see #addPotentialSpawn(EntitySnapshot, int, SpawnRule)
|
* @see #addPotentialSpawn(EntitySnapshot, int, SpawnRule)
|
||||||
*/
|
*/
|
||||||
public void addPotentialSpawn(@NotNull final SpawnerEntry spawnerEntry);
|
void addPotentialSpawn(final SpawnerEntry spawnerEntry);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the list of {@link SpawnerEntry} this spawner can spawn. <br>
|
* Sets the list of {@link SpawnerEntry} this spawner can spawn. <br>
|
||||||
@ -165,7 +166,7 @@ public interface BaseSpawner {
|
|||||||
*
|
*
|
||||||
* @param entries the list of entries
|
* @param entries the list of entries
|
||||||
*/
|
*/
|
||||||
public void setPotentialSpawns(@NotNull final Collection<SpawnerEntry> entries);
|
void setPotentialSpawns(final Collection<SpawnerEntry> entries);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a list of potential spawns from this spawner or an empty list if no
|
* Gets a list of potential spawns from this spawner or an empty list if no
|
||||||
@ -177,6 +178,5 @@ public interface BaseSpawner {
|
|||||||
* entities have been assigned to this spawner
|
* entities have been assigned to this spawner
|
||||||
* @see #getSpawnedType()
|
* @see #getSpawnedType()
|
||||||
*/
|
*/
|
||||||
@NotNull
|
List<SpawnerEntry> getPotentialSpawns();
|
||||||
public List<SpawnerEntry> getPotentialSpawns();
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,11 +3,14 @@ package org.bukkit.spawner;
|
|||||||
import org.bukkit.block.CreatureSpawner;
|
import org.bukkit.block.CreatureSpawner;
|
||||||
import org.bukkit.entity.EntityType;
|
import org.bukkit.entity.EntityType;
|
||||||
import org.bukkit.entity.minecart.SpawnerMinecart;
|
import org.bukkit.entity.minecart.SpawnerMinecart;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.jspecify.annotations.NullMarked;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents an entity spawner. <br>
|
* Represents an entity spawner. <br>
|
||||||
* May be a {@link SpawnerMinecart} or a {@link CreatureSpawner}.
|
* May be a {@link SpawnerMinecart} or a {@link CreatureSpawner}.
|
||||||
*/
|
*/
|
||||||
|
@NullMarked
|
||||||
public interface Spawner extends BaseSpawner {
|
public interface Spawner extends BaseSpawner {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -19,7 +22,7 @@ public interface Spawner extends BaseSpawner {
|
|||||||
* @param delay The delay.
|
* @param delay The delay.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void setDelay(int delay);
|
void setDelay(int delay);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The minimum spawn delay amount (in ticks).
|
* The minimum spawn delay amount (in ticks).
|
||||||
@ -32,7 +35,7 @@ public interface Spawner extends BaseSpawner {
|
|||||||
*
|
*
|
||||||
* @return the minimum spawn delay amount
|
* @return the minimum spawn delay amount
|
||||||
*/
|
*/
|
||||||
public int getMinSpawnDelay();
|
int getMinSpawnDelay();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the minimum spawn delay amount (in ticks).
|
* Set the minimum spawn delay amount (in ticks).
|
||||||
@ -40,7 +43,7 @@ public interface Spawner extends BaseSpawner {
|
|||||||
* @param delay the minimum spawn delay amount
|
* @param delay the minimum spawn delay amount
|
||||||
* @see #getMinSpawnDelay()
|
* @see #getMinSpawnDelay()
|
||||||
*/
|
*/
|
||||||
public void setMinSpawnDelay(int delay);
|
void setMinSpawnDelay(int delay);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The maximum spawn delay amount (in ticks).
|
* The maximum spawn delay amount (in ticks).
|
||||||
@ -56,7 +59,7 @@ public interface Spawner extends BaseSpawner {
|
|||||||
*
|
*
|
||||||
* @return the maximum spawn delay amount
|
* @return the maximum spawn delay amount
|
||||||
*/
|
*/
|
||||||
public int getMaxSpawnDelay();
|
int getMaxSpawnDelay();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the maximum spawn delay amount (in ticks).
|
* Set the maximum spawn delay amount (in ticks).
|
||||||
@ -67,7 +70,7 @@ public interface Spawner extends BaseSpawner {
|
|||||||
* @param delay the new maximum spawn delay amount
|
* @param delay the new maximum spawn delay amount
|
||||||
* @see #getMaxSpawnDelay()
|
* @see #getMaxSpawnDelay()
|
||||||
*/
|
*/
|
||||||
public void setMaxSpawnDelay(int delay);
|
void setMaxSpawnDelay(int delay);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get how many mobs attempt to spawn.
|
* Get how many mobs attempt to spawn.
|
||||||
@ -76,27 +79,27 @@ public interface Spawner extends BaseSpawner {
|
|||||||
*
|
*
|
||||||
* @return the current spawn count
|
* @return the current spawn count
|
||||||
*/
|
*/
|
||||||
public int getSpawnCount();
|
int getSpawnCount();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set how many mobs attempt to spawn.
|
* Set how many mobs attempt to spawn.
|
||||||
*
|
*
|
||||||
* @param spawnCount the new spawn count
|
* @param spawnCount the new spawn count
|
||||||
*/
|
*/
|
||||||
public void setSpawnCount(int spawnCount);
|
void setSpawnCount(int spawnCount);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the new maximum amount of similar entities that are allowed to be
|
* Get the maximum number of similar entities that are allowed to be
|
||||||
* within spawning range of this spawner.
|
* within the spawning range of this spawner.
|
||||||
* <br>
|
* <br>
|
||||||
* If more than the maximum number of entities are within range, the spawner
|
* If more than the maximum number of entities are within range, the spawner
|
||||||
* will not spawn and try again with a new {@link #getDelay()}.
|
* will not spawn and try again with a new {@link #getDelay()}.
|
||||||
* <br>
|
* <br>
|
||||||
* Default value is 16.
|
* Default value is 6.
|
||||||
*
|
*
|
||||||
* @return the maximum number of nearby, similar, entities
|
* @return the maximum number of nearby, similar, entities
|
||||||
*/
|
*/
|
||||||
public int getMaxNearbyEntities();
|
int getMaxNearbyEntities();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the maximum number of similar entities that are allowed to be within
|
* Set the maximum number of similar entities that are allowed to be within
|
||||||
@ -106,20 +109,19 @@ public interface Spawner extends BaseSpawner {
|
|||||||
*
|
*
|
||||||
* @param maxNearbyEntities the maximum number of nearby, similar, entities
|
* @param maxNearbyEntities the maximum number of nearby, similar, entities
|
||||||
*/
|
*/
|
||||||
public void setMaxNearbyEntities(int maxNearbyEntities);
|
void setMaxNearbyEntities(int maxNearbyEntities);
|
||||||
|
|
||||||
// Paper start
|
|
||||||
/**
|
/**
|
||||||
* Check if spawner is activated (a player is close enough)
|
* Check if spawner is activated (a player is close enough)
|
||||||
*
|
*
|
||||||
* @return True if a player is close enough to activate it
|
* @return True if a player is close enough to activate it
|
||||||
*/
|
*/
|
||||||
public boolean isActivated();
|
boolean isActivated();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resets the spawn delay timer within the min/max range
|
* Resets the spawn delay timer within the min/max range
|
||||||
*/
|
*/
|
||||||
public void resetTimer();
|
void resetTimer();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the {@link EntityType} to {@link EntityType#ITEM} and sets the data to the given
|
* Sets the {@link EntityType} to {@link EntityType#ITEM} and sets the data to the given
|
||||||
@ -128,9 +130,8 @@ public interface Spawner extends BaseSpawner {
|
|||||||
* {@link #setSpawnCount(int)} does not dictate the amount of items in the stack spawned, but rather how many
|
* {@link #setSpawnCount(int)} does not dictate the amount of items in the stack spawned, but rather how many
|
||||||
* stacks should be spawned.
|
* stacks should be spawned.
|
||||||
*
|
*
|
||||||
* @param itemStack The item to spawn. Must not {@link org.bukkit.Material#isAir be air}.
|
* @param itemStack The item to spawn. Must not {@link ItemStack#isEmpty() be empty}.
|
||||||
* @see #setSpawnedType(EntityType)
|
* @see #setSpawnedType(EntityType)
|
||||||
*/
|
*/
|
||||||
void setSpawnedItem(org.bukkit.inventory.@org.jetbrains.annotations.NotNull ItemStack itemStack);
|
void setSpawnedItem(ItemStack itemStack);
|
||||||
// Paper end
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
import io.papermc.fill.model.BuildChannel
|
||||||
import io.papermc.paperweight.attribute.DevBundleOutput
|
import io.papermc.paperweight.attribute.DevBundleOutput
|
||||||
import io.papermc.paperweight.util.*
|
import io.papermc.paperweight.util.*
|
||||||
import io.papermc.paperweight.util.data.FileEntry
|
import io.papermc.paperweight.util.data.FileEntry
|
||||||
@ -10,6 +11,7 @@ plugins {
|
|||||||
`maven-publish`
|
`maven-publish`
|
||||||
idea
|
idea
|
||||||
id("io.papermc.paperweight.core")
|
id("io.papermc.paperweight.core")
|
||||||
|
id("io.papermc.fill.gradle") version "1.0.3"
|
||||||
}
|
}
|
||||||
|
|
||||||
val paperMavenPublicUrl = "https://repo.papermc.io/repository/maven-public/"
|
val paperMavenPublicUrl = "https://repo.papermc.io/repository/maven-public/"
|
||||||
@ -132,7 +134,7 @@ dependencies {
|
|||||||
implementation("org.jline:jline-terminal-ffm:3.27.1") // use ffm on java 22+
|
implementation("org.jline:jline-terminal-ffm:3.27.1") // use ffm on java 22+
|
||||||
implementation("org.jline:jline-terminal-jni:3.27.1") // fall back to jni on java 21
|
implementation("org.jline:jline-terminal-jni:3.27.1") // fall back to jni on java 21
|
||||||
implementation("net.minecrell:terminalconsoleappender:1.3.0")
|
implementation("net.minecrell:terminalconsoleappender:1.3.0")
|
||||||
implementation("net.kyori:adventure-text-serializer-ansi:4.21.0") // Keep in sync with adventureVersion from Paper-API build file
|
implementation("net.kyori:adventure-text-serializer-ansi:4.23.0") // Keep in sync with adventureVersion from Paper-API build file
|
||||||
runtimeConfiguration(sourceSets.main.map { it.runtimeClasspath })
|
runtimeConfiguration(sourceSets.main.map { it.runtimeClasspath })
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -372,3 +374,20 @@ tasks.registerRunTask("runReobfPaperclip") {
|
|||||||
classpath(tasks.createReobfPaperclipJar.flatMap { it.outputZip })
|
classpath(tasks.createReobfPaperclipJar.flatMap { it.outputZip })
|
||||||
mainClass.set(null as String?)
|
mainClass.set(null as String?)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fill {
|
||||||
|
project("paper")
|
||||||
|
versionFamily(paperweight.minecraftVersion.map { it.split(".", "-").takeWhile { part -> part.toIntOrNull() != null }.take(2).joinToString(".") })
|
||||||
|
version(paperweight.minecraftVersion)
|
||||||
|
|
||||||
|
build {
|
||||||
|
channel = BuildChannel.STABLE
|
||||||
|
|
||||||
|
downloads {
|
||||||
|
register("server:default") {
|
||||||
|
file = tasks.createMojmapPaperclipJar.flatMap { it.outputZip }
|
||||||
|
nameResolver.set { project, _, version, build -> "$project-$version-$build.jar" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -354,7 +354,7 @@ index 0000000000000000000000000000000000000000..ae2bb9a73106febfe5f0d090abd4252b
|
|||||||
+ }
|
+ }
|
||||||
+}
|
+}
|
||||||
diff --git a/net/minecraft/server/level/ChunkMap.java b/net/minecraft/server/level/ChunkMap.java
|
diff --git a/net/minecraft/server/level/ChunkMap.java b/net/minecraft/server/level/ChunkMap.java
|
||||||
index 7b5ed00c9b2f22af5cbc44171192d674936dc7d7..5fe3c9a159908785e08fa874982bc1a82283bb1d 100644
|
index d51645b115780dac9ff6010806e8bd62dedc8e9f..3faf1b5556c55f3468182f75b2dbff4aaa3aae3a 100644
|
||||||
--- a/net/minecraft/server/level/ChunkMap.java
|
--- a/net/minecraft/server/level/ChunkMap.java
|
||||||
+++ b/net/minecraft/server/level/ChunkMap.java
|
+++ b/net/minecraft/server/level/ChunkMap.java
|
||||||
@@ -4,7 +4,6 @@ import com.google.common.collect.ImmutableList;
|
@@ -4,7 +4,6 @@ import com.google.common.collect.ImmutableList;
|
||||||
@ -484,7 +484,7 @@ index c70a58f5f633fa8e255f74c42f5e87c96b7b013a..ec20a5a6d7c8f65abda528fec36bec7b
|
|||||||
public void tick() {
|
public void tick() {
|
||||||
super.tick();
|
super.tick();
|
||||||
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
|
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
|
||||||
index f961540a00bfb5e1c8eb0e739f8ae535e9eee8f3..7453ddb09f349b7836f966573e4933646a75cba6 100644
|
index 75f81a6bc156a6455a616b8de0d7701fd2255a2d..b3d951670b3a097d04cfe347d7df496b1d0a0e09 100644
|
||||||
--- a/net/minecraft/world/entity/Entity.java
|
--- a/net/minecraft/world/entity/Entity.java
|
||||||
+++ b/net/minecraft/world/entity/Entity.java
|
+++ b/net/minecraft/world/entity/Entity.java
|
||||||
@@ -409,6 +409,15 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
|
@@ -409,6 +409,15 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
|
||||||
@ -661,10 +661,10 @@ index 3f780276be6766ef253c50212e06fd93a96b0caa..7e70c7bee633c54497d1cd2854dd60f4
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
diff --git a/net/minecraft/world/entity/item/ItemEntity.java b/net/minecraft/world/entity/item/ItemEntity.java
|
diff --git a/net/minecraft/world/entity/item/ItemEntity.java b/net/minecraft/world/entity/item/ItemEntity.java
|
||||||
index 548d7c8dc517da6c4db86b11f579ae63e6db56cf..a29860af4c37b2b45df49f9ba18f7e38921dfb02 100644
|
index fca31bbab8e7830933ceffcf992ff56ccc84414c..51804b611f469f2ab53e455e8c633b867b00cc88 100644
|
||||||
--- a/net/minecraft/world/entity/item/ItemEntity.java
|
--- a/net/minecraft/world/entity/item/ItemEntity.java
|
||||||
+++ b/net/minecraft/world/entity/item/ItemEntity.java
|
+++ b/net/minecraft/world/entity/item/ItemEntity.java
|
||||||
@@ -121,6 +121,29 @@ public class ItemEntity extends Entity implements TraceableEntity {
|
@@ -129,6 +129,29 @@ public class ItemEntity extends Entity implements TraceableEntity {
|
||||||
return 0.04;
|
return 0.04;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -695,7 +695,7 @@ index 548d7c8dc517da6c4db86b11f579ae63e6db56cf..a29860af4c37b2b45df49f9ba18f7e38
|
|||||||
public void tick() {
|
public void tick() {
|
||||||
if (this.getItem().isEmpty()) {
|
if (this.getItem().isEmpty()) {
|
||||||
diff --git a/net/minecraft/world/entity/npc/Villager.java b/net/minecraft/world/entity/npc/Villager.java
|
diff --git a/net/minecraft/world/entity/npc/Villager.java b/net/minecraft/world/entity/npc/Villager.java
|
||||||
index b0607f4a9b35570b319423c7876bb904d5154e8e..98c8653647dc52059d8becfe38a74d4e62edf08f 100644
|
index ef8347329b440833b45a54be2b6e4204ac0a425e..43f16df230f87a43e249a58fc10ef2da517f22ee 100644
|
||||||
--- a/net/minecraft/world/entity/npc/Villager.java
|
--- a/net/minecraft/world/entity/npc/Villager.java
|
||||||
+++ b/net/minecraft/world/entity/npc/Villager.java
|
+++ b/net/minecraft/world/entity/npc/Villager.java
|
||||||
@@ -269,11 +269,35 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
|
@@ -269,11 +269,35 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
|
||||||
@ -838,7 +838,7 @@ index 52acc72841f0c6980f5f3f8ef21d0b29dd472ce3..41a6ec508a10a49a37539d2f10171d15
|
|||||||
+
|
+
|
||||||
}
|
}
|
||||||
diff --git a/net/minecraft/world/level/Level.java b/net/minecraft/world/level/Level.java
|
diff --git a/net/minecraft/world/level/Level.java b/net/minecraft/world/level/Level.java
|
||||||
index d26e4d85d8fd8bd4f0c7de30b50a2ce370b37bf5..bab28e7afb7b1249d40631aabff16fc18cf95ea0 100644
|
index 06069d3ac598f5f12feab038de4f1199794298f6..980eaba27ce2616c1573a4760cf4acc2dd251190 100644
|
||||||
--- a/net/minecraft/world/level/Level.java
|
--- a/net/minecraft/world/level/Level.java
|
||||||
+++ b/net/minecraft/world/level/Level.java
|
+++ b/net/minecraft/world/level/Level.java
|
||||||
@@ -143,6 +143,12 @@ public abstract class Level implements LevelAccessor, UUIDLookup<Entity>, AutoCl
|
@@ -143,6 +143,12 @@ public abstract class Level implements LevelAccessor, UUIDLookup<Entity>, AutoCl
|
||||||
|
|||||||
@ -5,10 +5,10 @@ Subject: [PATCH] Anti-Xray
|
|||||||
|
|
||||||
|
|
||||||
diff --git a/io/papermc/paper/FeatureHooks.java b/io/papermc/paper/FeatureHooks.java
|
diff --git a/io/papermc/paper/FeatureHooks.java b/io/papermc/paper/FeatureHooks.java
|
||||||
index 55cc0dec4a88baea17f160e95d5d8316e0bb7a50..338dc0fb07cdba5f7350cca332fa3e942c622bfb 100644
|
index 811a8e5141f2061a185b53b63d951646141c0c7d..33d3eb510c5844e72bbc382bd24641aae080962d 100644
|
||||||
--- a/io/papermc/paper/FeatureHooks.java
|
--- a/io/papermc/paper/FeatureHooks.java
|
||||||
+++ b/io/papermc/paper/FeatureHooks.java
|
+++ b/io/papermc/paper/FeatureHooks.java
|
||||||
@@ -40,20 +40,25 @@ public final class FeatureHooks {
|
@@ -45,20 +45,25 @@ public final class FeatureHooks {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static LevelChunkSection createSection(final Registry<Biome> biomeRegistry, final Level level, final ChunkPos chunkPos, final int chunkSection) {
|
public static LevelChunkSection createSection(final Registry<Biome> biomeRegistry, final Level level, final ChunkPos chunkPos, final int chunkSection) {
|
||||||
|
|||||||
@ -14,17 +14,17 @@ movement will load only the chunk the player enters anyways and avoids loading
|
|||||||
massive amounts of surrounding chunks due to large AABB lookups.
|
massive amounts of surrounding chunks due to large AABB lookups.
|
||||||
|
|
||||||
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
|
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
|
||||||
index 7453ddb09f349b7836f966573e4933646a75cba6..58eda0d6426f30cda604f4120f1ddb012316c108 100644
|
index 23dfc87db1d5e90099270627197abc0f787a4393..27a01fd28ea565221768f31df02f0a2ddf242fce 100644
|
||||||
--- a/net/minecraft/world/entity/Entity.java
|
--- a/net/minecraft/world/entity/Entity.java
|
||||||
+++ b/net/minecraft/world/entity/Entity.java
|
+++ b/net/minecraft/world/entity/Entity.java
|
||||||
@@ -229,6 +229,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
|
@@ -230,6 +230,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
|
||||||
// Paper end - Share random for entities to make them more random
|
|
||||||
public @Nullable org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason; // Paper - Entity#getEntitySpawnReason
|
public @Nullable org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason; // Paper - Entity#getEntitySpawnReason
|
||||||
|
|
||||||
|
private volatile @Nullable org.bukkit.craftbukkit.entity.CraftEntity bukkitEntity; // Paper - Folia schedulers - volatile
|
||||||
+ public boolean collisionLoadChunks = false; // Paper
|
+ public boolean collisionLoadChunks = false; // Paper
|
||||||
private @Nullable org.bukkit.craftbukkit.entity.CraftEntity bukkitEntity;
|
|
||||||
|
|
||||||
public org.bukkit.craftbukkit.entity.CraftEntity getBukkitEntity() {
|
public org.bukkit.craftbukkit.entity.CraftEntity getBukkitEntity() {
|
||||||
|
if (this.bukkitEntity == null) {
|
||||||
diff --git a/net/minecraft/world/level/BlockCollisions.java b/net/minecraft/world/level/BlockCollisions.java
|
diff --git a/net/minecraft/world/level/BlockCollisions.java b/net/minecraft/world/level/BlockCollisions.java
|
||||||
index ed6e4f9fd0c7ad1219e66bc1cb4038191dd6edd8..45a20dbb935b12d429153463dba5d6fd3385dd7a 100644
|
index ed6e4f9fd0c7ad1219e66bc1cb4038191dd6edd8..45a20dbb935b12d429153463dba5d6fd3385dd7a 100644
|
||||||
--- a/net/minecraft/world/level/BlockCollisions.java
|
--- a/net/minecraft/world/level/BlockCollisions.java
|
||||||
|
|||||||
@ -32481,7 +32481,7 @@ index 0000000000000000000000000000000000000000..b028017b9c44821a8a313a04e0b10f5d
|
|||||||
+ }
|
+ }
|
||||||
+}
|
+}
|
||||||
diff --git a/ca/spottedleaf/moonrise/paper/PaperHooks.java b/ca/spottedleaf/moonrise/paper/PaperHooks.java
|
diff --git a/ca/spottedleaf/moonrise/paper/PaperHooks.java b/ca/spottedleaf/moonrise/paper/PaperHooks.java
|
||||||
index 0c611598a6912b692a7639301811ee557e2304f1..6f65564f6a6e99d6549de9a23a031b1f4a8a9798 100644
|
index e4f0653c575c33b1ef8160b6c88e29ee9fb44508..b6a34796d33f1593301c3a67a013fa7e812cb329 100644
|
||||||
--- a/ca/spottedleaf/moonrise/paper/PaperHooks.java
|
--- a/ca/spottedleaf/moonrise/paper/PaperHooks.java
|
||||||
+++ b/ca/spottedleaf/moonrise/paper/PaperHooks.java
|
+++ b/ca/spottedleaf/moonrise/paper/PaperHooks.java
|
||||||
@@ -211,6 +211,43 @@ public final class PaperHooks extends BaseChunkSystemHooks implements PlatformHo
|
@@ -211,6 +211,43 @@ public final class PaperHooks extends BaseChunkSystemHooks implements PlatformHo
|
||||||
@ -32542,7 +32542,7 @@ index 6536dc08c80170f5679acedd65cd2b9f6ad3fb3a..294cd15a796ad25823c8ccf98fbfae46
|
|||||||
return structureTemplate.save(new CompoundTag());
|
return structureTemplate.save(new CompoundTag());
|
||||||
}
|
}
|
||||||
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
|
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
|
||||||
index 794a01ee70a2a30d91550f5265f774ba73828cf9..c716521fb1497dc8a22d827ddb50fc1cc21a05f4 100644
|
index 2d597e50dcd957bd566c4da384fac5f36b5362f7..75aba65cbe1a943f21c7464ff9465e64f63e8e5b 100644
|
||||||
--- a/net/minecraft/server/MinecraftServer.java
|
--- a/net/minecraft/server/MinecraftServer.java
|
||||||
+++ b/net/minecraft/server/MinecraftServer.java
|
+++ b/net/minecraft/server/MinecraftServer.java
|
||||||
@@ -305,6 +305,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
@@ -305,6 +305,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||||
@ -32585,10 +32585,10 @@ index 8c1417c659ea0e079e99b9bfa79e1cf6ba9b712b..a8a32edea080f32fd25c9e009d4efa41
|
|||||||
if (stopBelowZero) {
|
if (stopBelowZero) {
|
||||||
chunkData.putString("Status", net.minecraft.core.registries.BuiltInRegistries.CHUNK_STATUS.getKey(net.minecraft.world.level.chunk.status.ChunkStatus.SPAWN).toString());
|
chunkData.putString("Status", net.minecraft.core.registries.BuiltInRegistries.CHUNK_STATUS.getKey(net.minecraft.world.level.chunk.status.ChunkStatus.SPAWN).toString());
|
||||||
diff --git a/net/minecraft/world/level/chunk/storage/SimpleRegionStorage.java b/net/minecraft/world/level/chunk/storage/SimpleRegionStorage.java
|
diff --git a/net/minecraft/world/level/chunk/storage/SimpleRegionStorage.java b/net/minecraft/world/level/chunk/storage/SimpleRegionStorage.java
|
||||||
index 6be673172548c1382c7402ec4e1ec6ef51f702d3..18750f1ea3101b6c0ab0b8e33c304eb7fa1ed04d 100644
|
index 6be673172548c1382c7402ec4e1ec6ef51f702d3..49be43ac896d60587511a97445c53c10c587a341 100644
|
||||||
--- a/net/minecraft/world/level/chunk/storage/SimpleRegionStorage.java
|
--- a/net/minecraft/world/level/chunk/storage/SimpleRegionStorage.java
|
||||||
+++ b/net/minecraft/world/level/chunk/storage/SimpleRegionStorage.java
|
+++ b/net/minecraft/world/level/chunk/storage/SimpleRegionStorage.java
|
||||||
@@ -32,13 +32,30 @@ public class SimpleRegionStorage implements AutoCloseable {
|
@@ -32,13 +32,32 @@ public class SimpleRegionStorage implements AutoCloseable {
|
||||||
return this.worker.store(chunkPos, data);
|
return this.worker.store(chunkPos, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -32609,7 +32609,9 @@ index 6be673172548c1382c7402ec4e1ec6ef51f702d3..18750f1ea3101b6c0ab0b8e33c304eb7
|
|||||||
- return this.dataFixType.updateToCurrentVersion(this.fixerUpper, tag, dataVersion);
|
- return this.dataFixType.updateToCurrentVersion(this.fixerUpper, tag, dataVersion);
|
||||||
+ // Paper start - rewrite data conversion system
|
+ // Paper start - rewrite data conversion system
|
||||||
+ final int dataVer = NbtUtils.getDataVersion(tag, version);
|
+ final int dataVer = NbtUtils.getDataVersion(tag, version);
|
||||||
+ return ca.spottedleaf.dataconverter.minecraft.MCDataConverter.convertTag(this.getDataConverterType(), tag, dataVer, ca.spottedleaf.dataconverter.minecraft.util.Version.getCurrentVersion());
|
+ final CompoundTag ret = ca.spottedleaf.dataconverter.minecraft.MCDataConverter.convertTag(this.getDataConverterType(), tag, dataVer, ca.spottedleaf.dataconverter.minecraft.util.Version.getCurrentVersion());
|
||||||
|
+ NbtUtils.addCurrentDataVersion(ret); // Fix MC-299110
|
||||||
|
+ return ret;
|
||||||
+ // Paper end - rewrite data conversion system
|
+ // Paper end - rewrite data conversion system
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -23061,7 +23061,7 @@ index 0000000000000000000000000000000000000000..f1f72a051083b61273202cb4e67ecb11
|
|||||||
+ private SaveUtil() {}
|
+ private SaveUtil() {}
|
||||||
+}
|
+}
|
||||||
diff --git a/io/papermc/paper/FeatureHooks.java b/io/papermc/paper/FeatureHooks.java
|
diff --git a/io/papermc/paper/FeatureHooks.java b/io/papermc/paper/FeatureHooks.java
|
||||||
index 338dc0fb07cdba5f7350cca332fa3e942c622bfb..e1fe49e4bf014e2405708270efd81bab4e1512da 100644
|
index b1a7af2dd3a3e166b1e58125f13ce08b9ec6d9ff..df6fbb35e5023b42de0b97434712e04a6b3e66a3 100644
|
||||||
--- a/io/papermc/paper/FeatureHooks.java
|
--- a/io/papermc/paper/FeatureHooks.java
|
||||||
+++ b/io/papermc/paper/FeatureHooks.java
|
+++ b/io/papermc/paper/FeatureHooks.java
|
||||||
@@ -1,6 +1,9 @@
|
@@ -1,6 +1,9 @@
|
||||||
@ -23074,8 +23074,13 @@ index 338dc0fb07cdba5f7350cca332fa3e942c622bfb..e1fe49e4bf014e2405708270efd81bab
|
|||||||
import it.unimi.dsi.fastutil.longs.LongOpenHashSet;
|
import it.unimi.dsi.fastutil.longs.LongOpenHashSet;
|
||||||
import it.unimi.dsi.fastutil.longs.LongSet;
|
import it.unimi.dsi.fastutil.longs.LongSet;
|
||||||
import it.unimi.dsi.fastutil.longs.LongSets;
|
import it.unimi.dsi.fastutil.longs.LongSets;
|
||||||
@@ -31,12 +34,16 @@ import org.bukkit.World;
|
@@ -32,16 +35,20 @@ public final class FeatureHooks {
|
||||||
public final class FeatureHooks {
|
|
||||||
|
// this includes non-accessible entities
|
||||||
|
public static Iterable<Entity> getAllEntities(final net.minecraft.server.level.ServerLevel world) {
|
||||||
|
- return ((net.minecraft.world.level.entity.LevelEntityGetterAdapter<Entity>)world.getEntities()).sectionStorage.getAllEntities();
|
||||||
|
+ return ((ca.spottedleaf.moonrise.patches.chunk_system.level.entity.EntityLookup)world.getEntities()).getAllMapped(); // Paper - rewrite chunk system
|
||||||
|
}
|
||||||
|
|
||||||
public static void setPlayerChunkUnloadDelay(final long ticks) {
|
public static void setPlayerChunkUnloadDelay(final long ticks) {
|
||||||
+ ca.spottedleaf.moonrise.patches.chunk_system.player.RegionizedPlayerChunkLoader.setUnloadDelay(ticks); // Paper - rewrite chunk system
|
+ ca.spottedleaf.moonrise.patches.chunk_system.player.RegionizedPlayerChunkLoader.setUnloadDelay(ticks); // Paper - rewrite chunk system
|
||||||
@ -23091,7 +23096,7 @@ index 338dc0fb07cdba5f7350cca332fa3e942c622bfb..e1fe49e4bf014e2405708270efd81bab
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static LevelChunkSection createSection(final Registry<Biome> biomeRegistry, final Level level, final ChunkPos chunkPos, final int chunkSection) {
|
public static LevelChunkSection createSection(final Registry<Biome> biomeRegistry, final Level level, final ChunkPos chunkPos, final int chunkSection) {
|
||||||
@@ -62,111 +69,58 @@ public final class FeatureHooks {
|
@@ -67,111 +74,58 @@ public final class FeatureHooks {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Set<Long> getSentChunkKeys(final ServerPlayer player) {
|
public static Set<Long> getSentChunkKeys(final ServerPlayer player) {
|
||||||
@ -23224,7 +23229,7 @@ index 338dc0fb07cdba5f7350cca332fa3e942c622bfb..e1fe49e4bf014e2405708270efd81bab
|
|||||||
|
|
||||||
org.bukkit.Chunk chunk = null;
|
org.bukkit.Chunk chunk = null;
|
||||||
for (net.minecraft.server.level.Ticket ticket : tickets) {
|
for (net.minecraft.server.level.Ticket ticket : tickets) {
|
||||||
@@ -186,15 +140,15 @@ public final class FeatureHooks {
|
@@ -191,15 +145,15 @@ public final class FeatureHooks {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int getViewDistance(net.minecraft.server.level.ServerLevel world) {
|
public static int getViewDistance(net.minecraft.server.level.ServerLevel world) {
|
||||||
@ -23243,7 +23248,7 @@ index 338dc0fb07cdba5f7350cca332fa3e942c622bfb..e1fe49e4bf014e2405708270efd81bab
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void setViewDistance(net.minecraft.server.level.ServerLevel world, int distance) {
|
public static void setViewDistance(net.minecraft.server.level.ServerLevel world, int distance) {
|
||||||
@@ -212,35 +166,31 @@ public final class FeatureHooks {
|
@@ -217,35 +171,31 @@ public final class FeatureHooks {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void setSendViewDistance(net.minecraft.server.level.ServerLevel world, int distance) {
|
public static void setSendViewDistance(net.minecraft.server.level.ServerLevel world, int distance) {
|
||||||
@ -23286,6 +23291,7 @@ index 338dc0fb07cdba5f7350cca332fa3e942c622bfb..e1fe49e4bf014e2405708270efd81bab
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
\ No newline at end of file
|
||||||
diff --git a/io/papermc/paper/command/subcommands/ChunkDebugCommand.java b/io/papermc/paper/command/subcommands/ChunkDebugCommand.java
|
diff --git a/io/papermc/paper/command/subcommands/ChunkDebugCommand.java b/io/papermc/paper/command/subcommands/ChunkDebugCommand.java
|
||||||
new file mode 100644
|
new file mode 100644
|
||||||
index 0000000000000000000000000000000000000000..2dca7afbd93cfbb8686f336fcd3b45dd01fba0fc
|
index 0000000000000000000000000000000000000000..2dca7afbd93cfbb8686f336fcd3b45dd01fba0fc
|
||||||
@ -23861,7 +23867,7 @@ index 46de98a6bbbae48c4837e1e588ba198a363d2dde..fd3553bdc1c3cdbf6aa3dc00e0a4987f
|
|||||||
thread1 -> {
|
thread1 -> {
|
||||||
DedicatedServer dedicatedServer1 = new DedicatedServer(
|
DedicatedServer dedicatedServer1 = new DedicatedServer(
|
||||||
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
|
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
|
||||||
index c716521fb1497dc8a22d827ddb50fc1cc21a05f4..80442494db670fec34df310390ea787fb963eef4 100644
|
index 75aba65cbe1a943f21c7464ff9465e64f63e8e5b..32475c0958fd7e0f1f9b494b0cc78a4a718d12b8 100644
|
||||||
--- a/net/minecraft/server/MinecraftServer.java
|
--- a/net/minecraft/server/MinecraftServer.java
|
||||||
+++ b/net/minecraft/server/MinecraftServer.java
|
+++ b/net/minecraft/server/MinecraftServer.java
|
||||||
@@ -173,7 +173,7 @@ import net.minecraft.world.phys.Vec2;
|
@@ -173,7 +173,7 @@ import net.minecraft.world.phys.Vec2;
|
||||||
@ -23960,7 +23966,7 @@ index c716521fb1497dc8a22d827ddb50fc1cc21a05f4..80442494db670fec34df310390ea787f
|
|||||||
this.server.getPluginManager().callEvent(new org.bukkit.event.world.WorldLoadEvent(serverLevel.getWorld()));
|
this.server.getPluginManager().callEvent(new org.bukkit.event.world.WorldLoadEvent(serverLevel.getWorld()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -844,6 +915,11 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
@@ -845,6 +916,11 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||||
public abstract boolean shouldRconBroadcast();
|
public abstract boolean shouldRconBroadcast();
|
||||||
|
|
||||||
public boolean saveAllChunks(boolean suppressLog, boolean flush, boolean forced) {
|
public boolean saveAllChunks(boolean suppressLog, boolean flush, boolean forced) {
|
||||||
@ -23972,7 +23978,7 @@ index c716521fb1497dc8a22d827ddb50fc1cc21a05f4..80442494db670fec34df310390ea787f
|
|||||||
boolean flag = false;
|
boolean flag = false;
|
||||||
|
|
||||||
for (ServerLevel serverLevel : this.getAllLevels()) {
|
for (ServerLevel serverLevel : this.getAllLevels()) {
|
||||||
@@ -851,7 +927,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
@@ -852,7 +928,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||||
LOGGER.info("Saving chunks for level '{}'/{}", serverLevel, serverLevel.dimension().location());
|
LOGGER.info("Saving chunks for level '{}'/{}", serverLevel, serverLevel.dimension().location());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -23981,7 +23987,7 @@ index c716521fb1497dc8a22d827ddb50fc1cc21a05f4..80442494db670fec34df310390ea787f
|
|||||||
flag = true;
|
flag = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -944,7 +1020,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
@@ -945,7 +1021,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -23990,7 +23996,7 @@ index c716521fb1497dc8a22d827ddb50fc1cc21a05f4..80442494db670fec34df310390ea787f
|
|||||||
this.nextTickTimeNanos = Util.getNanos() + TimeUtil.NANOSECONDS_PER_MILLISECOND;
|
this.nextTickTimeNanos = Util.getNanos() + TimeUtil.NANOSECONDS_PER_MILLISECOND;
|
||||||
|
|
||||||
for (ServerLevel serverLevelx : this.getAllLevels()) {
|
for (ServerLevel serverLevelx : this.getAllLevels()) {
|
||||||
@@ -954,18 +1030,14 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
@@ -955,18 +1031,14 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||||
|
|
||||||
this.waitUntilNextTick();
|
this.waitUntilNextTick();
|
||||||
}
|
}
|
||||||
@ -24016,7 +24022,7 @@ index c716521fb1497dc8a22d827ddb50fc1cc21a05f4..80442494db670fec34df310390ea787f
|
|||||||
|
|
||||||
this.isSaving = false;
|
this.isSaving = false;
|
||||||
this.resources.close();
|
this.resources.close();
|
||||||
@@ -985,6 +1057,14 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
@@ -986,6 +1058,14 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||||
this.getProfileCache().save(false); // Paper - Perf: Async GameProfileCache saving
|
this.getProfileCache().save(false); // Paper - Perf: Async GameProfileCache saving
|
||||||
}
|
}
|
||||||
// Spigot end
|
// Spigot end
|
||||||
@ -24031,7 +24037,7 @@ index c716521fb1497dc8a22d827ddb50fc1cc21a05f4..80442494db670fec34df310390ea787f
|
|||||||
// Paper start - Improved watchdog support - move final shutdown items here
|
// Paper start - Improved watchdog support - move final shutdown items here
|
||||||
Util.shutdownExecutors();
|
Util.shutdownExecutors();
|
||||||
try {
|
try {
|
||||||
@@ -1169,6 +1249,13 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
@@ -1170,6 +1250,13 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||||
profilerFiller.push("tick");
|
profilerFiller.push("tick");
|
||||||
this.tickFrame.start();
|
this.tickFrame.start();
|
||||||
this.tickServer(flag ? () -> false : this::haveTime);
|
this.tickServer(flag ? () -> false : this::haveTime);
|
||||||
@ -24045,7 +24051,7 @@ index c716521fb1497dc8a22d827ddb50fc1cc21a05f4..80442494db670fec34df310390ea787f
|
|||||||
this.tickFrame.end();
|
this.tickFrame.end();
|
||||||
profilerFiller.popPush("nextTickWait");
|
profilerFiller.popPush("nextTickWait");
|
||||||
this.mayHaveDelayedTasks = true;
|
this.mayHaveDelayedTasks = true;
|
||||||
@@ -1339,6 +1426,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
@@ -1340,6 +1427,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||||
|
|
||||||
private boolean pollTaskInternal() {
|
private boolean pollTaskInternal() {
|
||||||
if (super.pollTask()) {
|
if (super.pollTask()) {
|
||||||
@ -24053,7 +24059,7 @@ index c716521fb1497dc8a22d827ddb50fc1cc21a05f4..80442494db670fec34df310390ea787f
|
|||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
boolean ret = false; // Paper - force execution of all worlds, do not just bias the first
|
boolean ret = false; // Paper - force execution of all worlds, do not just bias the first
|
||||||
@@ -2468,6 +2556,12 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
@@ -2478,6 +2566,12 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -24067,7 +24073,7 @@ index c716521fb1497dc8a22d827ddb50fc1cc21a05f4..80442494db670fec34df310390ea787f
|
|||||||
// CraftBukkit start
|
// CraftBukkit start
|
||||||
public boolean isDebugging() {
|
public boolean isDebugging() {
|
||||||
diff --git a/net/minecraft/server/dedicated/DedicatedServer.java b/net/minecraft/server/dedicated/DedicatedServer.java
|
diff --git a/net/minecraft/server/dedicated/DedicatedServer.java b/net/minecraft/server/dedicated/DedicatedServer.java
|
||||||
index 5db176be3bd31eb886a541eeaee922ee30ee9908..5fea5e2e9fc10d348fa3e65cd354ef6a4a717a4d 100644
|
index 4488d0a2f05ef07afab0f9a1483f54b21757b29e..98927d4a5fba2a0dcdb147ac10b82c3286ccdc6b 100644
|
||||||
--- a/net/minecraft/server/dedicated/DedicatedServer.java
|
--- a/net/minecraft/server/dedicated/DedicatedServer.java
|
||||||
+++ b/net/minecraft/server/dedicated/DedicatedServer.java
|
+++ b/net/minecraft/server/dedicated/DedicatedServer.java
|
||||||
@@ -391,7 +391,33 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface
|
@@ -391,7 +391,33 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface
|
||||||
@ -27685,7 +27691,7 @@ index 49008b4cbaead8a66a93d2b0d4b50b335a6c3eed..f9c96bbdc54e68b9216b7f8662bfae03
|
|||||||
}
|
}
|
||||||
|
|
||||||
diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
|
diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
|
||||||
index 69dbff3f62e3a9ba7090156380f842bb44deebf8..c0b74d408340101bc3aac4cb4b7232c5cc78b08a 100644
|
index 6f7f92cc43c56a7453b289f205502d089474ef6d..b390ba657b8b880e431c84e9dd948ac9c84af2fd 100644
|
||||||
--- a/net/minecraft/server/level/ServerPlayer.java
|
--- a/net/minecraft/server/level/ServerPlayer.java
|
||||||
+++ b/net/minecraft/server/level/ServerPlayer.java
|
+++ b/net/minecraft/server/level/ServerPlayer.java
|
||||||
@@ -193,7 +193,7 @@ import net.minecraft.world.scores.Team;
|
@@ -193,7 +193,7 @@ import net.minecraft.world.scores.Team;
|
||||||
@ -28722,7 +28728,7 @@ index 8cc5c0716392ba06501542ff5cbe71ee43979e5d..09fd99c9cbd23b5f3c899bfb00c9b896
|
|||||||
+ // Paper end - block counting
|
+ // Paper end - block counting
|
||||||
}
|
}
|
||||||
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
|
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
|
||||||
index fa2ffc44336c3ddfe576b202154f14ef91a301b9..7546ff4c5ffc62d93a3f874519db8fef1e3bfbcb 100644
|
index 06d07f93e42edcfdd7d69df0b52efe2a58e7dfc1..da880f52920b1101f23ef94f3fd0dbdea218c373 100644
|
||||||
--- a/net/minecraft/world/entity/Entity.java
|
--- a/net/minecraft/world/entity/Entity.java
|
||||||
+++ b/net/minecraft/world/entity/Entity.java
|
+++ b/net/minecraft/world/entity/Entity.java
|
||||||
@@ -147,7 +147,7 @@ import net.minecraft.world.waypoints.WaypointTransmitter;
|
@@ -147,7 +147,7 @@ import net.minecraft.world.waypoints.WaypointTransmitter;
|
||||||
@ -29430,7 +29436,7 @@ index fa2ffc44336c3ddfe576b202154f14ef91a301b9..7546ff4c5ffc62d93a3f874519db8fef
|
|||||||
if (!checkPosition(this, x, y, z)) {
|
if (!checkPosition(this, x, y, z)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -4828,6 +5135,12 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
|
@@ -4818,6 +5125,12 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final void setRemoved(Entity.RemovalReason removalReason, @Nullable org.bukkit.event.entity.EntityRemoveEvent.Cause cause) { // CraftBukkit - add Bukkit remove cause
|
public final void setRemoved(Entity.RemovalReason removalReason, @Nullable org.bukkit.event.entity.EntityRemoveEvent.Cause cause) { // CraftBukkit - add Bukkit remove cause
|
||||||
@ -29443,7 +29449,7 @@ index fa2ffc44336c3ddfe576b202154f14ef91a301b9..7546ff4c5ffc62d93a3f874519db8fef
|
|||||||
org.bukkit.craftbukkit.event.CraftEventFactory.callEntityRemoveEvent(this, cause); // CraftBukkit
|
org.bukkit.craftbukkit.event.CraftEventFactory.callEntityRemoveEvent(this, cause); // CraftBukkit
|
||||||
final boolean alreadyRemoved = this.removalReason != null; // Paper - Folia schedulers
|
final boolean alreadyRemoved = this.removalReason != null; // Paper - Folia schedulers
|
||||||
if (this.removalReason == null) {
|
if (this.removalReason == null) {
|
||||||
@@ -4838,7 +5151,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
|
@@ -4828,7 +5141,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
|
||||||
this.stopRiding();
|
this.stopRiding();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -29452,7 +29458,7 @@ index fa2ffc44336c3ddfe576b202154f14ef91a301b9..7546ff4c5ffc62d93a3f874519db8fef
|
|||||||
this.levelCallback.onRemove(removalReason);
|
this.levelCallback.onRemove(removalReason);
|
||||||
this.onRemoval(removalReason);
|
this.onRemoval(removalReason);
|
||||||
// Paper start - Folia schedulers
|
// Paper start - Folia schedulers
|
||||||
@@ -4872,7 +5185,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
|
@@ -4862,7 +5175,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
|
||||||
public boolean shouldBeSaved() {
|
public boolean shouldBeSaved() {
|
||||||
return (this.removalReason == null || this.removalReason.shouldSave())
|
return (this.removalReason == null || this.removalReason.shouldSave())
|
||||||
&& !this.isPassenger()
|
&& !this.isPassenger()
|
||||||
@ -34311,7 +34317,7 @@ index 15417fab103feec3c1f7d5bd5b332e89d3ace3f5..2e6263d8b466e0f61bc72eb818044734
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
diff --git a/net/minecraft/world/level/chunk/storage/SimpleRegionStorage.java b/net/minecraft/world/level/chunk/storage/SimpleRegionStorage.java
|
diff --git a/net/minecraft/world/level/chunk/storage/SimpleRegionStorage.java b/net/minecraft/world/level/chunk/storage/SimpleRegionStorage.java
|
||||||
index 18750f1ea3101b6c0ab0b8e33c304eb7fa1ed04d..bf708ff89ea1f2c7279e48c41c4f44abc77ceebb 100644
|
index 49be43ac896d60587511a97445c53c10c587a341..1b070cf7e3612dbcb170cf5d954eba5f5b3c777c 100644
|
||||||
--- a/net/minecraft/world/level/chunk/storage/SimpleRegionStorage.java
|
--- a/net/minecraft/world/level/chunk/storage/SimpleRegionStorage.java
|
||||||
+++ b/net/minecraft/world/level/chunk/storage/SimpleRegionStorage.java
|
+++ b/net/minecraft/world/level/chunk/storage/SimpleRegionStorage.java
|
||||||
@@ -14,7 +14,7 @@ import net.minecraft.util.datafix.DataFixTypes;
|
@@ -14,7 +14,7 @@ import net.minecraft.util.datafix.DataFixTypes;
|
||||||
@ -36675,10 +36681,10 @@ index c634d795644be86ad85395ffa39fbac33bf7418b..66d0a6390febe929ef774b0a78133290
|
|||||||
|
|
||||||
for (SavedTick<T> savedTick : this.pendingTicks) {
|
for (SavedTick<T> savedTick : this.pendingTicks) {
|
||||||
diff --git a/net/minecraft/world/waypoints/WaypointTransmitter.java b/net/minecraft/world/waypoints/WaypointTransmitter.java
|
diff --git a/net/minecraft/world/waypoints/WaypointTransmitter.java b/net/minecraft/world/waypoints/WaypointTransmitter.java
|
||||||
index b579839c03b371d408e3750ec09af7da1d7bc9a0..9b41c62afc861847571ad739d1dd848b8276230c 100644
|
index 47382efcd50f29601a6623876be50c4d047336c5..5d1c933dfa862d0733777d305563a89ea7827f07 100644
|
||||||
--- a/net/minecraft/world/waypoints/WaypointTransmitter.java
|
--- a/net/minecraft/world/waypoints/WaypointTransmitter.java
|
||||||
+++ b/net/minecraft/world/waypoints/WaypointTransmitter.java
|
+++ b/net/minecraft/world/waypoints/WaypointTransmitter.java
|
||||||
@@ -31,7 +31,10 @@ public interface WaypointTransmitter extends Waypoint {
|
@@ -32,7 +32,10 @@ public interface WaypointTransmitter extends Waypoint {
|
||||||
}
|
}
|
||||||
|
|
||||||
static boolean isChunkVisible(ChunkPos pos, ServerPlayer player) {
|
static boolean isChunkVisible(ChunkPos pos, ServerPlayer player) {
|
||||||
|
|||||||
@ -5,10 +5,10 @@ Subject: [PATCH] Incremental chunk and player saving
|
|||||||
|
|
||||||
|
|
||||||
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
|
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
|
||||||
index 80442494db670fec34df310390ea787fb963eef4..2dd512565ab901bf853f34b384155902b0fe8120 100644
|
index 338ef549efe82c250c74365c1c1071986920c8c9..39581095ccc69d113d954ed835bdfa32d25b5489 100644
|
||||||
--- a/net/minecraft/server/MinecraftServer.java
|
--- a/net/minecraft/server/MinecraftServer.java
|
||||||
+++ b/net/minecraft/server/MinecraftServer.java
|
+++ b/net/minecraft/server/MinecraftServer.java
|
||||||
@@ -954,7 +954,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
@@ -955,7 +955,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||||
boolean var4;
|
boolean var4;
|
||||||
try {
|
try {
|
||||||
this.isSaving = true;
|
this.isSaving = true;
|
||||||
@ -17,7 +17,7 @@ index 80442494db670fec34df310390ea787fb963eef4..2dd512565ab901bf853f34b384155902
|
|||||||
var4 = this.saveAllChunks(suppressLog, flush, forced);
|
var4 = this.saveAllChunks(suppressLog, flush, forced);
|
||||||
} finally {
|
} finally {
|
||||||
this.isSaving = false;
|
this.isSaving = false;
|
||||||
@@ -1533,9 +1533,29 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
@@ -1534,9 +1534,29 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||||
}
|
}
|
||||||
|
|
||||||
this.ticksUntilAutosave--;
|
this.ticksUntilAutosave--;
|
||||||
|
|||||||
@ -48,10 +48,10 @@ index 0000000000000000000000000000000000000000..24a2090e068ad3c0d08705050944abdf
|
|||||||
+ }
|
+ }
|
||||||
+}
|
+}
|
||||||
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
|
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
|
||||||
index 2dd512565ab901bf853f34b384155902b0fe8120..d6dcb6d146d89a8fb96e7c669e5deb802223abd6 100644
|
index cff9d761dfee8a90b19fb2f3e678f99a39fc000c..0a260fdf6b198a8ab52e60bf6db2fb5eab719c48 100644
|
||||||
--- a/net/minecraft/server/MinecraftServer.java
|
--- a/net/minecraft/server/MinecraftServer.java
|
||||||
+++ b/net/minecraft/server/MinecraftServer.java
|
+++ b/net/minecraft/server/MinecraftServer.java
|
||||||
@@ -1708,6 +1708,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
@@ -1718,6 +1718,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||||
serverLevel.hasPhysicsEvent = org.bukkit.event.block.BlockPhysicsEvent.getHandlerList().getRegisteredListeners().length > 0; // Paper - BlockPhysicsEvent
|
serverLevel.hasPhysicsEvent = org.bukkit.event.block.BlockPhysicsEvent.getHandlerList().getRegisteredListeners().length > 0; // Paper - BlockPhysicsEvent
|
||||||
serverLevel.hasEntityMoveEvent = io.papermc.paper.event.entity.EntityMoveEvent.getHandlerList().getRegisteredListeners().length > 0; // Paper - Add EntityMoveEvent
|
serverLevel.hasEntityMoveEvent = io.papermc.paper.event.entity.EntityMoveEvent.getHandlerList().getRegisteredListeners().length > 0; // Paper - Add EntityMoveEvent
|
||||||
serverLevel.updateLagCompensationTick(); // Paper - lag compensation
|
serverLevel.updateLagCompensationTick(); // Paper - lag compensation
|
||||||
|
|||||||
@ -0,0 +1,204 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
|
||||||
|
Date: Tue, 24 Jun 2025 03:41:38 -0700
|
||||||
|
Subject: [PATCH] Improve keepalive ping system
|
||||||
|
|
||||||
|
Send more keepalives, record all transactions within the last minute.
|
||||||
|
We send more keepalives so that the latency calculation is more
|
||||||
|
accurate. Since we send more keepalives, we track all pending
|
||||||
|
keepalives in case multiple end up in flight.
|
||||||
|
|
||||||
|
Additionally, replace the latency calculation with a true
|
||||||
|
average over the last 5 seconds of keepalive transactions.
|
||||||
|
|
||||||
|
diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
|
||||||
|
index 53f038e1b5e7a13a08a0c925c8bd3f8a40868195..f3eca351021c37b64315872d075bd0a84aeee267 100644
|
||||||
|
--- a/net/minecraft/server/level/ServerPlayer.java
|
||||||
|
+++ b/net/minecraft/server/level/ServerPlayer.java
|
||||||
|
@@ -461,6 +461,70 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
|
||||||
|
return this.viewDistanceHolder;
|
||||||
|
}
|
||||||
|
// Paper end - rewrite chunk system
|
||||||
|
+ // Paper start - improve keepalives
|
||||||
|
+ public long lastKeepAliveTx = System.nanoTime();
|
||||||
|
+ public static final record KeepAliveResponse(long txTimeNS, long rxTimeNS) {
|
||||||
|
+ public long latencyNS() {
|
||||||
|
+ return this.rxTimeNS - this.txTimeNS;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ public static final record PendingKeepAlive(long txTimeNS, long challengeId) {}
|
||||||
|
+
|
||||||
|
+ public final ca.spottedleaf.concurrentutil.collection.MultiThreadedQueue<PendingKeepAlive> pendingKeepAlives = new ca.spottedleaf.concurrentutil.collection.MultiThreadedQueue<>();
|
||||||
|
+
|
||||||
|
+ public final PingCalculator pingCalculator1m = new PingCalculator(java.util.concurrent.TimeUnit.MINUTES.toNanos(1L));
|
||||||
|
+ public final PingCalculator pingCalculator5s = new PingCalculator(java.util.concurrent.TimeUnit.SECONDS.toNanos(5L));
|
||||||
|
+
|
||||||
|
+ public static final class PingCalculator {
|
||||||
|
+
|
||||||
|
+ private final long intervalNS;
|
||||||
|
+ private final ca.spottedleaf.concurrentutil.collection.MultiThreadedQueue<KeepAliveResponse> responses = new ca.spottedleaf.concurrentutil.collection.MultiThreadedQueue<>();
|
||||||
|
+
|
||||||
|
+ private long timeSumNS;
|
||||||
|
+ private int timeSumCount;
|
||||||
|
+ private volatile long lastAverageNS;
|
||||||
|
+
|
||||||
|
+ public PingCalculator(long intervalNS) {
|
||||||
|
+ this.intervalNS = intervalNS;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ public void update(KeepAliveResponse response) {
|
||||||
|
+ long currTime = response.txTimeNS;
|
||||||
|
+
|
||||||
|
+ this.responses.add(response);
|
||||||
|
+
|
||||||
|
+ ++this.timeSumCount;
|
||||||
|
+ this.timeSumNS += response.latencyNS();
|
||||||
|
+
|
||||||
|
+ // remove out-of-window times
|
||||||
|
+ KeepAliveResponse removed;
|
||||||
|
+ while ((removed = this.responses.pollIf((ka) -> (currTime - ka.txTimeNS) > this.intervalNS)) != null) {
|
||||||
|
+ --this.timeSumCount;
|
||||||
|
+ this.timeSumNS -= removed.latencyNS();
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ this.lastAverageNS = this.timeSumNS / (long)this.timeSumCount;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ public int getAvgLatencyMS() {
|
||||||
|
+ return (int)java.util.concurrent.TimeUnit.NANOSECONDS.toMillis(this.getAvgLatencyNS());
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ public long getAvgLatencyNS() {
|
||||||
|
+ return this.lastAverageNS;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ public it.unimi.dsi.fastutil.longs.LongArrayList getAllNS() {
|
||||||
|
+ it.unimi.dsi.fastutil.longs.LongArrayList ret = new it.unimi.dsi.fastutil.longs.LongArrayList();
|
||||||
|
+
|
||||||
|
+ for (KeepAliveResponse response : this.responses) {
|
||||||
|
+ ret.add(response.latencyNS());
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return ret;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ // Paper end - improve keepalives
|
||||||
|
|
||||||
|
public ServerPlayer(MinecraftServer server, ServerLevel level, GameProfile gameProfile, ClientInformation clientInformation) {
|
||||||
|
super(level, gameProfile);
|
||||||
|
diff --git a/net/minecraft/server/network/ServerCommonPacketListenerImpl.java b/net/minecraft/server/network/ServerCommonPacketListenerImpl.java
|
||||||
|
index 85e01c3a1536b41a0301a5a6506e058ff9633a4a..43f70a5561d6cc62aaeba6d1e39598ecb382e369 100644
|
||||||
|
--- a/net/minecraft/server/network/ServerCommonPacketListenerImpl.java
|
||||||
|
+++ b/net/minecraft/server/network/ServerCommonPacketListenerImpl.java
|
||||||
|
@@ -38,12 +38,12 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack
|
||||||
|
protected final MinecraftServer server;
|
||||||
|
public final Connection connection; // Paper
|
||||||
|
private final boolean transferred;
|
||||||
|
- private long keepAliveTime;
|
||||||
|
- private boolean keepAlivePending;
|
||||||
|
- private long keepAliveChallenge;
|
||||||
|
+ //private long keepAliveTime; // Paper - improve keepalives
|
||||||
|
+ //private boolean keepAlivePending; // Paper - improve keepalives
|
||||||
|
+ //private long keepAliveChallenge; // Paper - improve keepalives
|
||||||
|
private long closedListenerTime;
|
||||||
|
private boolean closed = false;
|
||||||
|
- private int latency;
|
||||||
|
+ private volatile int latency; // Paper - improve keepalives - make volatile
|
||||||
|
private volatile boolean suspendFlushingOnServerThread = false;
|
||||||
|
// CraftBukkit start
|
||||||
|
protected final net.minecraft.server.level.ServerPlayer player;
|
||||||
|
@@ -57,7 +57,7 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack
|
||||||
|
public ServerCommonPacketListenerImpl(MinecraftServer server, Connection connection, CommonListenerCookie cookie, net.minecraft.server.level.ServerPlayer player) { // CraftBukkit
|
||||||
|
this.server = server;
|
||||||
|
this.connection = connection;
|
||||||
|
- this.keepAliveTime = Util.getMillis();
|
||||||
|
+ //this.keepAliveTime = Util.getMillis(); // Paper - improve keepalives
|
||||||
|
this.latency = cookie.latency();
|
||||||
|
this.transferred = cookie.transferred();
|
||||||
|
// CraftBukkit start - add fields and methods
|
||||||
|
@@ -120,13 +120,41 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleKeepAlive(ServerboundKeepAlivePacket packet) {
|
||||||
|
- if (this.keepAlivePending && packet.getId() == this.keepAliveChallenge) {
|
||||||
|
- int i = (int)(Util.getMillis() - this.keepAliveTime);
|
||||||
|
- this.latency = (this.latency * 3 + i) / 4;
|
||||||
|
- this.keepAlivePending = false;
|
||||||
|
- } else if (!this.isSingleplayerOwner()) {
|
||||||
|
- this.disconnectAsync(TIMEOUT_DISCONNECTION_MESSAGE, org.bukkit.event.player.PlayerKickEvent.Cause.TIMEOUT); // Paper - add proper async disconnect
|
||||||
|
+ // Paper start - improve keepalives
|
||||||
|
+ long now = System.nanoTime();
|
||||||
|
+ net.minecraft.server.level.ServerPlayer.PendingKeepAlive pending = this.player.pendingKeepAlives.peek();
|
||||||
|
+ if (pending != null && pending.challengeId() == packet.getId()) {
|
||||||
|
+ this.player.pendingKeepAlives.remove(pending);
|
||||||
|
+
|
||||||
|
+ net.minecraft.server.level.ServerPlayer.KeepAliveResponse response = new net.minecraft.server.level.ServerPlayer.KeepAliveResponse(pending.txTimeNS(), now);
|
||||||
|
+
|
||||||
|
+ this.player.pingCalculator1m.update(response);
|
||||||
|
+ this.player.pingCalculator5s.update(response);
|
||||||
|
+
|
||||||
|
+ this.latency = this.player.pingCalculator5s.getAvgLatencyMS();
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ for (java.util.Iterator<net.minecraft.server.level.ServerPlayer.PendingKeepAlive> itr = this.player.pendingKeepAlives.iterator(); itr.hasNext();) {
|
||||||
|
+ net.minecraft.server.level.ServerPlayer.PendingKeepAlive ka = itr.next();
|
||||||
|
+ if (ka.challengeId() == packet.getId()) {
|
||||||
|
+ itr.remove();
|
||||||
|
+
|
||||||
|
+ if (!this.processedDisconnect) {
|
||||||
|
+ LOGGER.info("Disconnecting " + this.player.getScoreboardName() + " for sending keepalive response (" + packet.getId() + ") out-of-order!");
|
||||||
|
+ this.disconnectAsync(TIMEOUT_DISCONNECTION_MESSAGE, org.bukkit.event.player.PlayerKickEvent.Cause.TIMEOUT);
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+ if (!this.processedDisconnect) {
|
||||||
|
+ LOGGER.info("Disconnecting " + this.player.getScoreboardName() + " for sending keepalive response (" + packet.getId() + ") without matching challenge!");
|
||||||
|
+ this.disconnectAsync(TIMEOUT_DISCONNECTION_MESSAGE, org.bukkit.event.player.PlayerKickEvent.Cause.TIMEOUT);
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+ // Paper end - improve keepalives
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@@ -247,20 +275,23 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack
|
||||||
|
protected void keepConnectionAlive() {
|
||||||
|
Profiler.get().push("keepAlive");
|
||||||
|
long millis = Util.getMillis();
|
||||||
|
- // Paper start - give clients a longer time to respond to pings as per pre 1.12.2 timings
|
||||||
|
- // This should effectively place the keepalive handling back to "as it was" before 1.12.2
|
||||||
|
- final long elapsedTime = millis - this.keepAliveTime;
|
||||||
|
- if (!this.isSingleplayerOwner() && elapsedTime >= 15000L) { // use vanilla's 15000L between keep alive packets
|
||||||
|
- if (this.keepAlivePending) {
|
||||||
|
- if (!this.processedDisconnect && elapsedTime >= KEEPALIVE_LIMIT) { // check keepalive limit, don't fire if already disconnected
|
||||||
|
- this.disconnect(TIMEOUT_DISCONNECTION_MESSAGE, org.bukkit.event.player.PlayerKickEvent.Cause.TIMEOUT); // Paper - kick event cause
|
||||||
|
- }
|
||||||
|
- // Paper end - give clients a longer time to respond to pings as per pre 1.12.2 timings
|
||||||
|
- } else if (this.checkIfClosed(millis)) {
|
||||||
|
- this.keepAlivePending = true;
|
||||||
|
- this.keepAliveTime = millis;
|
||||||
|
- this.keepAliveChallenge = millis;
|
||||||
|
- this.send(new ClientboundKeepAlivePacket(this.keepAliveChallenge));
|
||||||
|
+ // Paper start - improve keepalives
|
||||||
|
+ if (this.checkIfClosed(millis) && !this.processedDisconnect) {
|
||||||
|
+ long currTime = System.nanoTime();
|
||||||
|
+
|
||||||
|
+ if ((currTime - this.player.lastKeepAliveTx) >= java.util.concurrent.TimeUnit.SECONDS.toNanos(1L)) {
|
||||||
|
+ this.player.lastKeepAliveTx = currTime;
|
||||||
|
+
|
||||||
|
+ net.minecraft.server.level.ServerPlayer.PendingKeepAlive pka = new net.minecraft.server.level.ServerPlayer.PendingKeepAlive(currTime, millis);
|
||||||
|
+ this.player.pendingKeepAlives.add(pka);
|
||||||
|
+ this.send(new ClientboundKeepAlivePacket(pka.challengeId()));
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ net.minecraft.server.level.ServerPlayer.PendingKeepAlive oldest = this.player.pendingKeepAlives.peek();
|
||||||
|
+ if (oldest != null && (currTime - oldest.txTimeNS()) > java.util.concurrent.TimeUnit.MILLISECONDS.toNanos(KEEPALIVE_LIMIT)) {
|
||||||
|
+ LOGGER.warn(this.player.getScoreboardName() + " was kicked due to keepalive timeout!");
|
||||||
|
+ this.disconnect(TIMEOUT_DISCONNECTION_MESSAGE, org.bukkit.event.player.PlayerKickEvent.Cause.TIMEOUT);
|
||||||
|
+ // Paper end - improve keepalives
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@ -0,0 +1,84 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
|
||||||
|
Date: Tue, 24 Jun 2025 07:05:51 -0700
|
||||||
|
Subject: [PATCH] Optimise EntityScheduler ticking
|
||||||
|
|
||||||
|
The vast majority of the time, there are no tasks scheduled to
|
||||||
|
the EntityScheduler. We can avoid iterating the entire entity list
|
||||||
|
by tracking which schedulers have any tasks scheduled.
|
||||||
|
|
||||||
|
diff --git a/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/server/ServerEntityLookup.java b/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/server/ServerEntityLookup.java
|
||||||
|
index 5f2deeb5cc01d8bbeb7449bd4e59c466b3dfdf57..82824ae7ffbced513a8bcace684af94916135e84 100644
|
||||||
|
--- a/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/server/ServerEntityLookup.java
|
||||||
|
+++ b/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/server/ServerEntityLookup.java
|
||||||
|
@@ -96,6 +96,7 @@ public final class ServerEntityLookup extends EntityLookup {
|
||||||
|
if (entity instanceof ThrownEnderpearl enderpearl) {
|
||||||
|
this.addEnderPearl(CoordinateUtils.getChunkKey(enderpearl.chunkPosition()));
|
||||||
|
}
|
||||||
|
+ entity.registerScheduler(); // Paper - optimise Folia entity scheduler
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
|
||||||
|
index 0a260fdf6b198a8ab52e60bf6db2fb5eab719c48..52fa5112cd90ba766c94512a02401dd3aee82cc9 100644
|
||||||
|
--- a/net/minecraft/server/MinecraftServer.java
|
||||||
|
+++ b/net/minecraft/server/MinecraftServer.java
|
||||||
|
@@ -1654,33 +1654,22 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ public final io.papermc.paper.threadedregions.EntityScheduler.EntitySchedulerTickList entitySchedulerTickList = new io.papermc.paper.threadedregions.EntityScheduler.EntitySchedulerTickList(); // Paper - optimise Folia entity scheduler
|
||||||
|
+
|
||||||
|
protected void tickChildren(BooleanSupplier hasTimeLeft) {
|
||||||
|
ProfilerFiller profilerFiller = Profiler.get();
|
||||||
|
this.getPlayerList().getPlayers().forEach(serverPlayer1 -> serverPlayer1.connection.suspendFlushing());
|
||||||
|
this.server.getScheduler().mainThreadHeartbeat(); // CraftBukkit
|
||||||
|
- // Paper start - Folia scheduler API
|
||||||
|
- ((io.papermc.paper.threadedregions.scheduler.FoliaGlobalRegionScheduler) org.bukkit.Bukkit.getGlobalRegionScheduler()).tick();
|
||||||
|
- for (ServerPlayer player : this.playerList.players) {
|
||||||
|
- if (!this.playerList.players.contains(player)) {
|
||||||
|
+ // Paper start - optimise Folia entity scheduler
|
||||||
|
+ ((io.papermc.paper.threadedregions.scheduler.FoliaGlobalRegionScheduler)org.bukkit.Bukkit.getGlobalRegionScheduler()).tick();
|
||||||
|
+ for (io.papermc.paper.threadedregions.EntityScheduler scheduler : this.entitySchedulerTickList.getAllSchedulers()) {
|
||||||
|
+ if (scheduler.isRetired()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
- final org.bukkit.craftbukkit.entity.CraftEntity bukkit = player.getBukkitEntityRaw();
|
||||||
|
- if (bukkit != null) {
|
||||||
|
- bukkit.taskScheduler.executeTick();
|
||||||
|
- }
|
||||||
|
+
|
||||||
|
+ scheduler.executeTick();
|
||||||
|
}
|
||||||
|
- getAllLevels().forEach(level -> {
|
||||||
|
- for (final net.minecraft.world.entity.Entity entity : io.papermc.paper.FeatureHooks.getAllEntities(level)) {
|
||||||
|
- if (entity.isRemoved() || entity instanceof ServerPlayer) {
|
||||||
|
- continue;
|
||||||
|
- }
|
||||||
|
- final org.bukkit.craftbukkit.entity.CraftEntity bukkit = entity.getBukkitEntityRaw();
|
||||||
|
- if (bukkit != null) {
|
||||||
|
- bukkit.taskScheduler.executeTick();
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
- });
|
||||||
|
- // Paper end - Folia scheduler API
|
||||||
|
+ // Paper end - optimise Folia entity scheduler
|
||||||
|
io.papermc.paper.adventure.providers.ClickCallbackProviderImpl.CALLBACK_MANAGER.handleQueue(this.tickCount); // Paper
|
||||||
|
profilerFiller.push("commandFunctions");
|
||||||
|
this.getFunctions().tick();
|
||||||
|
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
|
||||||
|
index da880f52920b1101f23ef94f3fd0dbdea218c373..3d2c0a4d3a1f9d3e5cc6cd0cdb988ae1205de821 100644
|
||||||
|
--- a/net/minecraft/world/entity/Entity.java
|
||||||
|
+++ b/net/minecraft/world/entity/Entity.java
|
||||||
|
@@ -5165,6 +5165,11 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
|
||||||
|
this.getBukkitEntity().taskScheduler.retire();
|
||||||
|
}
|
||||||
|
// Paper end - Folia schedulers
|
||||||
|
+ // Paper start - optimise Folia entity scheduler
|
||||||
|
+ public final void registerScheduler() {
|
||||||
|
+ this.getBukkitEntity().taskScheduler.registerTo(net.minecraft.server.MinecraftServer.getServer().entitySchedulerTickList);
|
||||||
|
+ }
|
||||||
|
+ // Paper end - optimise Folia entity scheduler
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setLevelCallback(EntityInLevelCallback levelCallback) {
|
||||||
@ -1,6 +1,6 @@
|
|||||||
--- /dev/null
|
--- /dev/null
|
||||||
+++ b/io/papermc/paper/FeatureHooks.java
|
+++ b/io/papermc/paper/FeatureHooks.java
|
||||||
@@ -1,0 +_,241 @@
|
@@ -1,0 +_,246 @@
|
||||||
+package io.papermc.paper;
|
+package io.papermc.paper;
|
||||||
+
|
+
|
||||||
+import io.papermc.paper.command.PaperSubcommand;
|
+import io.papermc.paper.command.PaperSubcommand;
|
||||||
@ -33,6 +33,11 @@
|
|||||||
+
|
+
|
||||||
+public final class FeatureHooks {
|
+public final class FeatureHooks {
|
||||||
+
|
+
|
||||||
|
+ // this includes non-accessible entities
|
||||||
|
+ public static Iterable<Entity> getAllEntities(final net.minecraft.server.level.ServerLevel world) {
|
||||||
|
+ return ((net.minecraft.world.level.entity.LevelEntityGetterAdapter<Entity>)world.getEntities()).sectionStorage.getAllEntities();
|
||||||
|
+ }
|
||||||
|
+
|
||||||
+ public static void setPlayerChunkUnloadDelay(final long ticks) {
|
+ public static void setPlayerChunkUnloadDelay(final long ticks) {
|
||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
|
|||||||
@ -1,6 +1,13 @@
|
|||||||
--- a/net/minecraft/commands/Commands.java
|
--- a/net/minecraft/commands/Commands.java
|
||||||
+++ b/net/minecraft/commands/Commands.java
|
+++ b/net/minecraft/commands/Commands.java
|
||||||
@@ -176,6 +_,11 @@
|
@@ -170,12 +_,18 @@
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isRestricted(CommandNode<CommandSourceStack> node) {
|
||||||
|
+ if (node.getRequirement() instanceof PermissionSource.RestrictedMarker) return true; // Paper - restricted api
|
||||||
|
return node.getRequirement() instanceof PermissionCheck<?> permissionCheck && permissionCheck.requiredLevel() > 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
private final CommandDispatcher<CommandSourceStack> dispatcher = new CommandDispatcher<>();
|
private final CommandDispatcher<CommandSourceStack> dispatcher = new CommandDispatcher<>();
|
||||||
|
|
||||||
public Commands(Commands.CommandSelection selection, CommandBuildContext context) {
|
public Commands(Commands.CommandSelection selection, CommandBuildContext context) {
|
||||||
@ -55,76 +62,29 @@
|
|||||||
this.dispatcher.setConsumer(ExecutionCommandSource.resultConsumer());
|
this.dispatcher.setConsumer(ExecutionCommandSource.resultConsumer());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -289,9 +_,41 @@
|
@@ -299,6 +_,13 @@
|
||||||
return new ParseResults<>(commandContextBuilder, parseResults.getReader(), parseResults.getExceptions());
|
|
||||||
}
|
|
||||||
|
|
||||||
+ // CraftBukkit start
|
|
||||||
+ public void dispatchServerCommand(CommandSourceStack sender, String command) {
|
|
||||||
+ com.google.common.base.Joiner joiner = com.google.common.base.Joiner.on(" ");
|
|
||||||
+ if (command.startsWith("/")) {
|
|
||||||
+ command = command.substring(1);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ org.bukkit.event.server.ServerCommandEvent event = new org.bukkit.event.server.ServerCommandEvent(sender.getBukkitSender(), command);
|
|
||||||
+ org.bukkit.Bukkit.getPluginManager().callEvent(event);
|
|
||||||
+ if (event.isCancelled()) {
|
|
||||||
+ return;
|
|
||||||
+ }
|
|
||||||
+ command = event.getCommand();
|
|
||||||
+
|
|
||||||
+ String[] args = command.split(" ");
|
|
||||||
+ if (args.length == 0) return; // Paper - empty commands shall not be dispatched
|
|
||||||
+
|
|
||||||
+ // Paper - Fix permission levels for command blocks
|
|
||||||
+
|
|
||||||
+ // Handle vanilla commands; // Paper - handled in CommandNode/CommandDispatcher
|
|
||||||
+
|
|
||||||
+ String newCommand = joiner.join(args);
|
|
||||||
+ this.performPrefixedCommand(sender, newCommand, newCommand);
|
|
||||||
+ }
|
|
||||||
+ // CraftBukkit end
|
|
||||||
+
|
|
||||||
public void performPrefixedCommand(CommandSourceStack source, String command) {
|
|
||||||
+ // CraftBukkit start
|
|
||||||
+ this.performPrefixedCommand(source, command, command);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ public void performPrefixedCommand(CommandSourceStack source, String command, String label) {
|
|
||||||
command = trimOptionalPrefix(command);
|
|
||||||
- this.performCommand(this.dispatcher.parse(command, source), command);
|
|
||||||
+ this.performCommand(this.dispatcher.parse(command, source), command, label);
|
|
||||||
+ // CraftBukkit end
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String trimOptionalPrefix(String command) {
|
|
||||||
@@ -299,9 +_,20 @@
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void performCommand(ParseResults<CommandSourceStack> parseResults, String command) {
|
public void performCommand(ParseResults<CommandSourceStack> parseResults, String command) {
|
||||||
+ // CraftBukkit start
|
+ // Paper start
|
||||||
+ this.performCommand(parseResults, command, command);
|
+ this.performCommand(parseResults, command, false);
|
||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
+ public void performCommand(ParseResults<CommandSourceStack> parseResults, String command, String label) {
|
+ public void performCommand(ParseResults<CommandSourceStack> parseResults, String command, boolean throwCommandError) {
|
||||||
+ // CraftBukkit end
|
+ org.spigotmc.AsyncCatcher.catchOp("Cannot perform command async");
|
||||||
+ // Paper start
|
|
||||||
+ this.performCommand(parseResults, command, label, false);
|
|
||||||
+ }
|
|
||||||
+ public void performCommand(ParseResults<CommandSourceStack> parseResults, String command, String label, boolean throwCommandError) {
|
|
||||||
+ // Paper end
|
+ // Paper end
|
||||||
CommandSourceStack commandSourceStack = parseResults.getContext().getSource();
|
CommandSourceStack commandSourceStack = parseResults.getContext().getSource();
|
||||||
Profiler.get().push(() -> "/" + command);
|
Profiler.get().push(() -> "/" + command);
|
||||||
- ContextChain<CommandSourceStack> contextChain = finishParsing(parseResults, command, commandSourceStack);
|
ContextChain<CommandSourceStack> contextChain = finishParsing(parseResults, command, commandSourceStack);
|
||||||
+ ContextChain contextChain = this.finishParsing(parseResults, command, commandSourceStack, label); // CraftBukkit // Paper - Add UnknownCommandEvent
|
@@ -312,10 +_,13 @@
|
||||||
|
)
|
||||||
try {
|
|
||||||
if (contextChain != null) {
|
|
||||||
@@ -313,9 +_,10 @@
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} catch (Exception var12) {
|
- } catch (Exception var12) {
|
||||||
+ if (throwCommandError) throw var12; // Paper
|
+ // Paper start
|
||||||
|
+ } catch (Throwable var12) { // always gracefully handle it, no matter how bad:tm:
|
||||||
|
+ if (throwCommandError) throw var12; // rethrow directly if requested
|
||||||
|
+ // Paper end
|
||||||
MutableComponent mutableComponent = Component.literal(var12.getMessage() == null ? var12.getClass().getName() : var12.getMessage());
|
MutableComponent mutableComponent = Component.literal(var12.getMessage() == null ? var12.getClass().getName() : var12.getMessage());
|
||||||
- if (LOGGER.isDebugEnabled()) {
|
- if (LOGGER.isDebugEnabled()) {
|
||||||
- LOGGER.error("Command exception: /{}", command, var12);
|
- LOGGER.error("Command exception: /{}", command, var12);
|
||||||
@ -133,12 +93,12 @@
|
|||||||
StackTraceElement[] stackTrace = var12.getStackTrace();
|
StackTraceElement[] stackTrace = var12.getStackTrace();
|
||||||
|
|
||||||
for (int i = 0; i < Math.min(stackTrace.length, 3); i++) {
|
for (int i = 0; i < Math.min(stackTrace.length, 3); i++) {
|
||||||
@@ -341,18 +_,22 @@
|
@@ -341,13 +_,17 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
- private static ContextChain<CommandSourceStack> finishParsing(ParseResults<CommandSourceStack> parseResults, String command, CommandSourceStack source) {
|
- private static ContextChain<CommandSourceStack> finishParsing(ParseResults<CommandSourceStack> parseResults, String command, CommandSourceStack source) {
|
||||||
+ private ContextChain<CommandSourceStack> finishParsing(ParseResults<CommandSourceStack> parseResults, String command, CommandSourceStack source, String label) { // CraftBukkit // Paper - Add UnknownCommandEvent
|
+ private ContextChain<CommandSourceStack> finishParsing(ParseResults<CommandSourceStack> parseResults, String command, CommandSourceStack source) {
|
||||||
try {
|
try {
|
||||||
validateParseResults(parseResults);
|
validateParseResults(parseResults);
|
||||||
return ContextChain.tryFlatten(parseResults.getContext().build(command))
|
return ContextChain.tryFlatten(parseResults.getContext().build(command))
|
||||||
@ -153,12 +113,6 @@
|
|||||||
if (var7.getInput() != null && var7.getCursor() >= 0) {
|
if (var7.getInput() != null && var7.getCursor() >= 0) {
|
||||||
int min = Math.min(var7.getInput().length(), var7.getCursor());
|
int min = Math.min(var7.getInput().length(), var7.getCursor());
|
||||||
MutableComponent mutableComponent = Component.empty()
|
MutableComponent mutableComponent = Component.empty()
|
||||||
.withStyle(ChatFormatting.GRAY)
|
|
||||||
- .withStyle(style -> style.withClickEvent(new ClickEvent.SuggestCommand("/" + command)));
|
|
||||||
+ .withStyle(style -> style.withClickEvent(new ClickEvent.SuggestCommand("/" + label))); // CraftBukkit // Paper
|
|
||||||
if (min > 10) {
|
|
||||||
mutableComponent.append(CommonComponents.ELLIPSIS);
|
|
||||||
}
|
|
||||||
@@ -364,7 +_,17 @@
|
@@ -364,7 +_,17 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,16 +1,18 @@
|
|||||||
--- a/net/minecraft/commands/PermissionSource.java
|
--- a/net/minecraft/commands/PermissionSource.java
|
||||||
+++ b/net/minecraft/commands/PermissionSource.java
|
+++ b/net/minecraft/commands/PermissionSource.java
|
||||||
@@ -9,9 +_,20 @@
|
@@ -9,9 +_,22 @@
|
||||||
return this.hasPermission(2);
|
return this.hasPermission(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
- public record Check<T extends PermissionSource>(@Override int requiredLevel) implements PermissionCheck<T> {
|
- public record Check<T extends PermissionSource>(@Override int requiredLevel) implements PermissionCheck<T> {
|
||||||
+ public record Check<T extends PermissionSource>(@Override int requiredLevel, java.util.concurrent.atomic.AtomicReference<com.mojang.brigadier.tree.CommandNode<CommandSourceStack>> vanillaNode) implements PermissionCheck<T> { // Paper
|
+ // Paper start - Vanilla Command permission checking & expose restricted API
|
||||||
+ // Paper start - Vanilla Command permission checking
|
+ interface RestrictedMarker { }
|
||||||
|
+
|
||||||
|
+ public record Check<T extends PermissionSource>(@Override int requiredLevel, java.util.concurrent.atomic.AtomicReference<com.mojang.brigadier.tree.CommandNode<CommandSourceStack>> vanillaNode) implements PermissionCheck<T> {
|
||||||
+ public Check(int requiredLevel) {
|
+ public Check(int requiredLevel) {
|
||||||
+ this(requiredLevel, new java.util.concurrent.atomic.AtomicReference<>());
|
+ this(requiredLevel, new java.util.concurrent.atomic.AtomicReference<>());
|
||||||
+ }
|
+ }
|
||||||
+ // Paper end - Vanilla Command permission checking
|
+ // Paper end - Vanilla Command permission checking & expose restricted API
|
||||||
@Override
|
@Override
|
||||||
public boolean test(T source) {
|
public boolean test(T source) {
|
||||||
+ // Paper start - Vanilla Command permission checking
|
+ // Paper start - Vanilla Command permission checking
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
--- a/net/minecraft/network/protocol/game/VecDeltaCodec.java
|
--- a/net/minecraft/network/protocol/game/VecDeltaCodec.java
|
||||||
+++ b/net/minecraft/network/protocol/game/VecDeltaCodec.java
|
+++ b/net/minecraft/network/protocol/game/VecDeltaCodec.java
|
||||||
@@ -5,16 +_,16 @@
|
@@ -5,7 +_,7 @@
|
||||||
|
|
||||||
public class VecDeltaCodec {
|
public class VecDeltaCodec {
|
||||||
private static final double TRUNCATION_STEPS = 4096.0;
|
private static final double TRUNCATION_STEPS = 4096.0;
|
||||||
@ -9,14 +9,3 @@
|
|||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
static long encode(double value) {
|
static long encode(double value) {
|
||||||
- return Math.round(value * 4096.0);
|
|
||||||
+ return Math.round(value * 4096.0); // Paper - Fix MC-4; diff on change
|
|
||||||
}
|
|
||||||
|
|
||||||
@VisibleForTesting
|
|
||||||
static double decode(long value) {
|
|
||||||
- return value / 4096.0;
|
|
||||||
+ return value / 4096.0; // Paper - Fix MC-4; diff on change
|
|
||||||
}
|
|
||||||
|
|
||||||
public Vec3 decode(long x, long y, long z) {
|
|
||||||
|
|||||||
@ -172,7 +172,7 @@
|
|||||||
if (profiledDuration != null) {
|
if (profiledDuration != null) {
|
||||||
profiledDuration.finish(true);
|
profiledDuration.finish(true);
|
||||||
}
|
}
|
||||||
@@ -364,25 +_,265 @@
|
@@ -364,25 +_,266 @@
|
||||||
protected void forceDifficulty() {
|
protected void forceDifficulty() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -439,6 +439,7 @@
|
|||||||
+ if (io.papermc.paper.plugin.PluginInitializerManager.instance().pluginRemapper != null) io.papermc.paper.plugin.PluginInitializerManager.instance().pluginRemapper.pluginsEnabled(); // Paper - Remap plugins
|
+ if (io.papermc.paper.plugin.PluginInitializerManager.instance().pluginRemapper != null) io.papermc.paper.plugin.PluginInitializerManager.instance().pluginRemapper.pluginsEnabled(); // Paper - Remap plugins
|
||||||
+ io.papermc.paper.command.brigadier.PaperCommands.INSTANCE.setValid(); // Paper - reset invalid state for event fire below
|
+ io.papermc.paper.command.brigadier.PaperCommands.INSTANCE.setValid(); // Paper - reset invalid state for event fire below
|
||||||
+ io.papermc.paper.plugin.lifecycle.event.LifecycleEventRunner.INSTANCE.callReloadableRegistrarEvent(io.papermc.paper.plugin.lifecycle.event.types.LifecycleEvents.COMMANDS, io.papermc.paper.command.brigadier.PaperCommands.INSTANCE, org.bukkit.plugin.Plugin.class, io.papermc.paper.plugin.lifecycle.event.registrar.ReloadableRegistrarEvent.Cause.INITIAL); // Paper - call commands event for regular plugins
|
+ io.papermc.paper.plugin.lifecycle.event.LifecycleEventRunner.INSTANCE.callReloadableRegistrarEvent(io.papermc.paper.plugin.lifecycle.event.types.LifecycleEvents.COMMANDS, io.papermc.paper.command.brigadier.PaperCommands.INSTANCE, org.bukkit.plugin.Plugin.class, io.papermc.paper.plugin.lifecycle.event.registrar.ReloadableRegistrarEvent.Cause.INITIAL); // Paper - call commands event for regular plugins
|
||||||
|
+ this.server.getCommandMap().registerServerAliases(); // Paper - relocate initial CommandMap#registerServerAliases() call
|
||||||
+ ((org.bukkit.craftbukkit.help.SimpleHelpMap) this.server.getHelpMap()).initializeCommands();
|
+ ((org.bukkit.craftbukkit.help.SimpleHelpMap) this.server.getHelpMap()).initializeCommands();
|
||||||
+ this.server.getPluginManager().callEvent(new org.bukkit.event.server.ServerLoadEvent(org.bukkit.event.server.ServerLoadEvent.LoadType.STARTUP));
|
+ this.server.getPluginManager().callEvent(new org.bukkit.event.server.ServerLoadEvent(org.bukkit.event.server.ServerLoadEvent.LoadType.STARTUP));
|
||||||
+ this.connection.acceptConnections();
|
+ this.connection.acceptConnections();
|
||||||
@ -983,16 +984,25 @@
|
|||||||
ObjectArrayList<GameProfile> list = new ObjectArrayList<>(min);
|
ObjectArrayList<GameProfile> list = new ObjectArrayList<>(min);
|
||||||
int randomInt = Mth.nextInt(this.random, 0, players.size() - min);
|
int randomInt = Mth.nextInt(this.random, 0, players.size() - min);
|
||||||
|
|
||||||
@@ -1040,17 +_,66 @@
|
@@ -1040,17 +_,75 @@
|
||||||
protected void tickChildren(BooleanSupplier hasTimeLeft) {
|
protected void tickChildren(BooleanSupplier hasTimeLeft) {
|
||||||
ProfilerFiller profilerFiller = Profiler.get();
|
ProfilerFiller profilerFiller = Profiler.get();
|
||||||
this.getPlayerList().getPlayers().forEach(serverPlayer1 -> serverPlayer1.connection.suspendFlushing());
|
this.getPlayerList().getPlayers().forEach(serverPlayer1 -> serverPlayer1.connection.suspendFlushing());
|
||||||
+ this.server.getScheduler().mainThreadHeartbeat(); // CraftBukkit
|
+ this.server.getScheduler().mainThreadHeartbeat(); // CraftBukkit
|
||||||
+ // Paper start - Folia scheduler API
|
+ // Paper start - Folia scheduler API
|
||||||
+ ((io.papermc.paper.threadedregions.scheduler.FoliaGlobalRegionScheduler) org.bukkit.Bukkit.getGlobalRegionScheduler()).tick();
|
+ ((io.papermc.paper.threadedregions.scheduler.FoliaGlobalRegionScheduler) org.bukkit.Bukkit.getGlobalRegionScheduler()).tick();
|
||||||
|
+ for (ServerPlayer player : this.playerList.players) {
|
||||||
|
+ if (!this.playerList.players.contains(player)) {
|
||||||
|
+ continue;
|
||||||
|
+ }
|
||||||
|
+ final org.bukkit.craftbukkit.entity.CraftEntity bukkit = player.getBukkitEntityRaw();
|
||||||
|
+ if (bukkit != null) {
|
||||||
|
+ bukkit.taskScheduler.executeTick();
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
+ getAllLevels().forEach(level -> {
|
+ getAllLevels().forEach(level -> {
|
||||||
+ for (final net.minecraft.world.entity.Entity entity : level.getEntities().getAll()) {
|
+ for (final net.minecraft.world.entity.Entity entity : io.papermc.paper.FeatureHooks.getAllEntities(level)) {
|
||||||
+ if (entity.isRemoved()) {
|
+ if (entity.isRemoved() || entity instanceof ServerPlayer) {
|
||||||
+ continue;
|
+ continue;
|
||||||
+ }
|
+ }
|
||||||
+ final org.bukkit.craftbukkit.entity.CraftEntity bukkit = entity.getBukkitEntityRaw();
|
+ final org.bukkit.craftbukkit.entity.CraftEntity bukkit = entity.getBukkitEntityRaw();
|
||||||
|
|||||||
@ -273,7 +273,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -291,13 +_,23 @@
|
@@ -291,12 +_,20 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
public void handleConsoleInput(String msg, CommandSourceStack source) {
|
public void handleConsoleInput(String msg, CommandSourceStack source) {
|
||||||
@ -284,23 +284,19 @@
|
|||||||
public void handleConsoleInputs() {
|
public void handleConsoleInputs() {
|
||||||
- while (!this.consoleInput.isEmpty()) {
|
- while (!this.consoleInput.isEmpty()) {
|
||||||
- ConsoleInput consoleInput = this.consoleInput.remove(0);
|
- ConsoleInput consoleInput = this.consoleInput.remove(0);
|
||||||
- this.getCommands().performPrefixedCommand(consoleInput.source, consoleInput.msg);
|
|
||||||
+ // Paper start - Perf: use proper queue
|
+ // Paper start - Perf: use proper queue
|
||||||
+ ConsoleInput servercommand;
|
+ ConsoleInput consoleInput;
|
||||||
+ while ((servercommand = this.serverCommandQueue.poll()) != null) {
|
+ while ((consoleInput = this.serverCommandQueue.poll()) != null) {
|
||||||
+ // Paper end - Perf: use proper queue
|
+ // Paper end - Perf: use proper queue
|
||||||
+ // CraftBukkit start - ServerCommand for preprocessing
|
+ // CraftBukkit start - ServerCommand for preprocessing
|
||||||
+ org.bukkit.event.server.ServerCommandEvent event = new org.bukkit.event.server.ServerCommandEvent(this.console, servercommand.msg);
|
+ org.bukkit.event.server.ServerCommandEvent event = new org.bukkit.event.server.ServerCommandEvent(this.console, consoleInput.msg);
|
||||||
+ this.server.getPluginManager().callEvent(event);
|
+ this.server.getPluginManager().callEvent(event);
|
||||||
+ if (event.isCancelled()) continue;
|
+ if (event.isCancelled()) continue;
|
||||||
+ servercommand = new ConsoleInput(event.getCommand(), servercommand.source);
|
+ consoleInput = new ConsoleInput(event.getCommand(), consoleInput.source);
|
||||||
+
|
|
||||||
+ // this.getCommands().performPrefixedCommand(servercommand.source, servercommand.msg); // Called in dispatchServerCommand
|
|
||||||
+ this.server.dispatchServerCommand(this.console, servercommand);
|
|
||||||
+ // CraftBukkit end
|
+ // CraftBukkit end
|
||||||
|
this.getCommands().performPrefixedCommand(consoleInput.source, consoleInput.msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -430,7 +_,11 @@
|
@@ -430,7 +_,11 @@
|
||||||
@Override
|
@Override
|
||||||
public boolean enforceSecureProfile() {
|
public boolean enforceSecureProfile() {
|
||||||
@ -314,7 +310,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -515,14 +_,54 @@
|
@@ -515,14 +_,53 @@
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getPluginNames() {
|
public String getPluginNames() {
|
||||||
@ -365,8 +361,7 @@
|
|||||||
+ if (event.isCancelled()) {
|
+ if (event.isCancelled()) {
|
||||||
+ return;
|
+ return;
|
||||||
+ }
|
+ }
|
||||||
+ ConsoleInput serverCommand = new ConsoleInput(event.getCommand(), wrapper);
|
+ this.getCommands().performPrefixedCommand(wrapper, event.getCommand());
|
||||||
+ this.server.dispatchServerCommand(event.getSender(), serverCommand);
|
|
||||||
+ });
|
+ });
|
||||||
+ return rconConsoleSource.getCommandResponse();
|
+ return rconConsoleSource.getCommandResponse();
|
||||||
+ // CraftBukkit end
|
+ // CraftBukkit end
|
||||||
|
|||||||
@ -1334,7 +1334,8 @@
|
|||||||
if (traceItem) {
|
if (traceItem) {
|
||||||
- ItemStack itemStack = itemEntity != null ? itemEntity.getItem() : ItemStack.EMPTY;
|
- ItemStack itemStack = itemEntity != null ? itemEntity.getItem() : ItemStack.EMPTY;
|
||||||
if (!itemStack.isEmpty()) {
|
if (!itemStack.isEmpty()) {
|
||||||
this.awardStat(Stats.ITEM_DROPPED.get(itemStack.getItem()), droppedItem.getCount());
|
- this.awardStat(Stats.ITEM_DROPPED.get(itemStack.getItem()), droppedItem.getCount());
|
||||||
|
+ this.awardStat(Stats.ITEM_DROPPED.get(itemStack.getItem()), itemStack.getCount()); // Paper - use size from dropped item
|
||||||
this.awardStat(Stats.DROP);
|
this.awardStat(Stats.DROP);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
--- a/net/minecraft/server/network/ServerCommonPacketListenerImpl.java
|
--- a/net/minecraft/server/network/ServerCommonPacketListenerImpl.java
|
||||||
+++ b/net/minecraft/server/network/ServerCommonPacketListenerImpl.java
|
+++ b/net/minecraft/server/network/ServerCommonPacketListenerImpl.java
|
||||||
@@ -29,30 +_,67 @@
|
@@ -29,14 +_,14 @@
|
||||||
import net.minecraft.util.profiling.Profiler;
|
import net.minecraft.util.profiling.Profiler;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
|
||||||
@ -15,11 +15,9 @@
|
|||||||
- protected final Connection connection;
|
- protected final Connection connection;
|
||||||
+ public final Connection connection; // Paper
|
+ public final Connection connection; // Paper
|
||||||
private final boolean transferred;
|
private final boolean transferred;
|
||||||
- private long keepAliveTime;
|
private long keepAliveTime;
|
||||||
+ private long keepAliveTime = Util.getMillis(); // Paper
|
|
||||||
private boolean keepAlivePending;
|
private boolean keepAlivePending;
|
||||||
private long keepAliveChallenge;
|
@@ -45,14 +_,51 @@
|
||||||
private long closedListenerTime;
|
|
||||||
private boolean closed = false;
|
private boolean closed = false;
|
||||||
private int latency;
|
private int latency;
|
||||||
private volatile boolean suspendFlushingOnServerThread = false;
|
private volatile boolean suspendFlushingOnServerThread = false;
|
||||||
|
|||||||
@ -295,7 +295,7 @@
|
|||||||
|
|
||||||
rootVehicle.absSnapTo(d, d1, d2, f, f1);
|
rootVehicle.absSnapTo(d, d1, d2, f, f1);
|
||||||
+ // CraftBukkit start - fire PlayerMoveEvent TODO: this should be removed.
|
+ // CraftBukkit start - fire PlayerMoveEvent TODO: this should be removed.
|
||||||
+ this.player.absSnapTo(x, y, z, this.player.getYRot(), this.player.getXRot()); // Paper - TODO: This breaks alot of stuff
|
+ this.player.absSnapTo(d, d1, d2, this.player.getYRot(), this.player.getXRot()); // Paper - TODO: This breaks alot of stuff
|
||||||
+ org.bukkit.entity.Player player = this.getCraftPlayer();
|
+ org.bukkit.entity.Player player = this.getCraftPlayer();
|
||||||
+ if (!this.hasMoved) {
|
+ if (!this.hasMoved) {
|
||||||
+ this.lastPosX = prevX;
|
+ this.lastPosX = prevX;
|
||||||
@ -1146,8 +1146,7 @@
|
|||||||
|
|
||||||
return;
|
return;
|
||||||
case RELEASE_USE_ITEM:
|
case RELEASE_USE_ITEM:
|
||||||
- this.player.releaseUsingItem();
|
this.player.releaseUsingItem();
|
||||||
+ if (this.player.getUseItem() == this.player.getItemInHand(this.player.getUsedItemHand())) this.player.releaseUsingItem(); // Paper - validate use item before processing release
|
|
||||||
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.updateEquipmentOnPlayerActions) this.player.detectEquipmentUpdates(); // Paper - Force update attributes.
|
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.updateEquipmentOnPlayerActions) this.player.detectEquipmentUpdates(); // Paper - Force update attributes.
|
||||||
return;
|
return;
|
||||||
case START_DESTROY_BLOCK:
|
case START_DESTROY_BLOCK:
|
||||||
@ -2610,7 +2609,7 @@
|
|||||||
if (!this.receivedMovementThisTick) {
|
if (!this.receivedMovementThisTick) {
|
||||||
this.player.setKnownMovement(Vec3.ZERO);
|
this.player.setKnownMovement(Vec3.ZERO);
|
||||||
}
|
}
|
||||||
@@ -2078,4 +_,17 @@
|
@@ -2078,4 +_,29 @@
|
||||||
interface EntityInteraction {
|
interface EntityInteraction {
|
||||||
InteractionResult run(ServerPlayer player, Entity entity, InteractionHand hand);
|
InteractionResult run(ServerPlayer player, Entity entity, InteractionHand hand);
|
||||||
}
|
}
|
||||||
@ -2627,4 +2626,16 @@
|
|||||||
+ return event;
|
+ return event;
|
||||||
+ }
|
+ }
|
||||||
+ // Paper end - Add fail move event
|
+ // Paper end - Add fail move event
|
||||||
|
+
|
||||||
|
+ // Paper start - Implement click callbacks with custom click action
|
||||||
|
+ @Override
|
||||||
|
+ public void handleCustomClickAction(final net.minecraft.network.protocol.common.ServerboundCustomClickActionPacket packet) {
|
||||||
|
+ super.handleCustomClickAction(packet);
|
||||||
|
+ if (packet.id().equals(io.papermc.paper.adventure.providers.ClickCallbackProviderImpl.CLICK_CALLBACK_RESOURCE_LOCATION)) {
|
||||||
|
+ packet.payload().ifPresent(tag ->
|
||||||
|
+ io.papermc.paper.adventure.providers.ClickCallbackProviderImpl.CALLBACK_MANAGER.tryRunCallback(this.player.getBukkitEntity(), tag)
|
||||||
|
+ );
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ // Paper end - Implement click callbacks with custom click action
|
||||||
}
|
}
|
||||||
|
|||||||
@ -85,7 +85,7 @@
|
|||||||
+ // Paper end - Share random for entities to make them more random
|
+ // Paper end - Share random for entities to make them more random
|
||||||
+ public @Nullable org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason; // Paper - Entity#getEntitySpawnReason
|
+ public @Nullable org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason; // Paper - Entity#getEntitySpawnReason
|
||||||
+
|
+
|
||||||
+ private @Nullable org.bukkit.craftbukkit.entity.CraftEntity bukkitEntity;
|
+ private volatile @Nullable org.bukkit.craftbukkit.entity.CraftEntity bukkitEntity; // Paper - Folia schedulers - volatile
|
||||||
+
|
+
|
||||||
+ public org.bukkit.craftbukkit.entity.CraftEntity getBukkitEntity() {
|
+ public org.bukkit.craftbukkit.entity.CraftEntity getBukkitEntity() {
|
||||||
+ if (this.bukkitEntity == null) {
|
+ if (this.bukkitEntity == null) {
|
||||||
@ -1786,7 +1786,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void addDeltaMovement(Vec3 addend) {
|
public void addDeltaMovement(Vec3 addend) {
|
||||||
@@ -3661,9 +_,45 @@
|
@@ -3661,9 +_,35 @@
|
||||||
return this.getZ((2.0 * this.random.nextDouble() - 1.0) * scale);
|
return this.getZ((2.0 * this.random.nextDouble() - 1.0) * scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1815,16 +1815,6 @@
|
|||||||
+ return;
|
+ return;
|
||||||
+ }
|
+ }
|
||||||
+ // Paper end - Block invalid positions and bounding box
|
+ // Paper end - Block invalid positions and bounding box
|
||||||
+ // Paper start - Fix MC-4
|
|
||||||
+ if (this instanceof ItemEntity) {
|
|
||||||
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().misc.fixEntityPositionDesync) {
|
|
||||||
+ // encode/decode from VecDeltaCodec todo computation changed?
|
|
||||||
+ x = Mth.lfloor(x * 4096.0) * (1 / 4096.0);
|
|
||||||
+ y = Mth.lfloor(y * 4096.0) * (1 / 4096.0);
|
|
||||||
+ z = Mth.lfloor(z * 4096.0) * (1 / 4096.0);
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ // Paper end - Fix MC-4
|
|
||||||
if (this.position.x != x || this.position.y != y || this.position.z != z) {
|
if (this.position.x != x || this.position.y != y || this.position.z != z) {
|
||||||
+ synchronized (this.posLock) { // Paper - detailed watchdog information
|
+ synchronized (this.posLock) { // Paper - detailed watchdog information
|
||||||
this.position = new Vec3(x, y, z);
|
this.position = new Vec3(x, y, z);
|
||||||
|
|||||||
@ -27,3 +27,25 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -120,7 +_,12 @@
|
||||||
|
return this.level().getBlockState(this.pos).is(BlockTags.FENCES);
|
||||||
|
}
|
||||||
|
|
||||||
|
+ // Paper start - Track if a knot was created
|
||||||
|
public static LeashFenceKnotEntity getOrCreateKnot(Level level, BlockPos pos) {
|
||||||
|
+ return getOrCreateKnot(level, pos, null);
|
||||||
|
+ }
|
||||||
|
+ public static LeashFenceKnotEntity getOrCreateKnot(Level level, BlockPos pos, @Nullable org.apache.commons.lang3.mutable.MutableBoolean created) {
|
||||||
|
+ // Paper end - Track if a knot was created
|
||||||
|
int x = pos.getX();
|
||||||
|
int y = pos.getY();
|
||||||
|
int z = pos.getZ();
|
||||||
|
@@ -134,7 +_,7 @@
|
||||||
|
}
|
||||||
|
|
||||||
|
LeashFenceKnotEntity leashFenceKnotEntity1 = new LeashFenceKnotEntity(level, pos);
|
||||||
|
- level.addFreshEntity(leashFenceKnotEntity1);
|
||||||
|
+ if (level.addFreshEntity(leashFenceKnotEntity1) && created != null) { created.setTrue(); } // Paper - Track if a knot was created
|
||||||
|
return leashFenceKnotEntity1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@ -24,6 +24,21 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
public ItemEntity(Level level, double posX, double posY, double posZ, ItemStack itemStack, double deltaX, double deltaY, double deltaZ) {
|
public ItemEntity(Level level, double posX, double posY, double posZ, ItemStack itemStack, double deltaX, double deltaY, double deltaZ) {
|
||||||
|
@@ -79,6 +_,14 @@
|
||||||
|
this.bobOffs = other.bobOffs;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ // Paper start - Require item entities to send their location precisely (Fixes MC-4)
|
||||||
|
+ {
|
||||||
|
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().misc.sendFullPosForItemEntities) {
|
||||||
|
+ this.setRequiresPrecisePosition(true);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ // Paper end - Require item entities to send their location precisely (Fixes MC-4)
|
||||||
|
+
|
||||||
|
@Override
|
||||||
|
public boolean dampensVibrations() {
|
||||||
|
return this.getItem().is(ItemTags.DAMPENS_VIBRATIONS);
|
||||||
@@ -116,7 +_,7 @@
|
@@ -116,7 +_,7 @@
|
||||||
@Override
|
@Override
|
||||||
public void tick() {
|
public void tick() {
|
||||||
|
|||||||
@ -43,23 +43,36 @@
|
|||||||
if (this.getItemBySlot(EquipmentSlot.HEAD).isEmpty()) {
|
if (this.getItemBySlot(EquipmentSlot.HEAD).isEmpty()) {
|
||||||
LocalDate localDate = LocalDate.now();
|
LocalDate localDate = LocalDate.now();
|
||||||
int i = localDate.get(ChronoField.DAY_OF_MONTH);
|
int i = localDate.get(ChronoField.DAY_OF_MONTH);
|
||||||
@@ -196,9 +_,19 @@
|
@@ -188,7 +_,8 @@
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void performRangedAttack(LivingEntity target, float distanceFactor) {
|
||||||
|
- ItemStack itemInHand = this.getItemInHand(ProjectileUtil.getWeaponHoldingHand(this, Items.BOW));
|
||||||
|
+ net.minecraft.world.InteractionHand hand = ProjectileUtil.getWeaponHoldingHand(this, Items.BOW); // Paper - call EntityShootBowEvent
|
||||||
|
+ ItemStack itemInHand = this.getItemInHand(hand); // Paper - call EntityShootBowEvent
|
||||||
|
ItemStack projectile = this.getProjectile(itemInHand);
|
||||||
|
AbstractArrow arrow = this.getArrow(projectile, distanceFactor, itemInHand);
|
||||||
|
double d = target.getX() - this.getX();
|
||||||
|
@@ -196,9 +_,21 @@
|
||||||
double d2 = target.getZ() - this.getZ();
|
double d2 = target.getZ() - this.getZ();
|
||||||
double squareRoot = Math.sqrt(d * d + d2 * d2);
|
double squareRoot = Math.sqrt(d * d + d2 * d2);
|
||||||
if (this.level() instanceof ServerLevel serverLevel) {
|
if (this.level() instanceof ServerLevel serverLevel) {
|
||||||
+ // CraftBukkit start
|
- Projectile.spawnProjectileUsingShoot(
|
||||||
+ org.bukkit.event.entity.EntityShootBowEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityShootBowEvent(this, this.getMainHandItem(), arrow.getPickupItem(), arrow, net.minecraft.world.InteractionHand.MAIN_HAND, distanceFactor, true); // Paper - improve entity shoot bow event, add arrow stack to event
|
+ Projectile.Delayed<AbstractArrow> delayedEntity = Projectile.spawnProjectileUsingShootDelayed( // Paper - delayed
|
||||||
|
arrow, serverLevel, projectile, d, d1 + squareRoot * 0.2F, d2, 1.6F, 14 - serverLevel.getDifficulty().getId() * 4
|
||||||
|
);
|
||||||
|
+
|
||||||
|
+ // Paper start - call EntityShootBowEvent
|
||||||
|
+ org.bukkit.event.entity.EntityShootBowEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityShootBowEvent(this, itemInHand, arrow.getPickupItem(), arrow, hand, distanceFactor, true);
|
||||||
+ if (event.isCancelled()) {
|
+ if (event.isCancelled()) {
|
||||||
+ event.getProjectile().remove();
|
+ event.getProjectile().remove();
|
||||||
+ return;
|
+ return;
|
||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
+ if (event.getProjectile() == arrow.getBukkitEntity()) {
|
+ if (event.getProjectile() == arrow.getBukkitEntity()) {
|
||||||
+ // CraftBukkit end
|
+ delayedEntity.spawn();
|
||||||
Projectile.spawnProjectileUsingShoot(
|
+ }
|
||||||
arrow, serverLevel, projectile, d, d1 + squareRoot * 0.2F, d2, 1.6F, 14 - serverLevel.getDifficulty().getId() * 4
|
+ // Paper end - call EntityShootBowEvent
|
||||||
);
|
|
||||||
+ } // CraftBukkit
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.playSound(SoundEvents.SKELETON_SHOOT, 1.0F, 1.0F / (this.getRandom().nextFloat() * 0.4F + 0.8F));
|
this.playSound(SoundEvents.SKELETON_SHOOT, 1.0F, 1.0F / (this.getRandom().nextFloat() * 0.4F + 0.8F));
|
||||||
|
|||||||
@ -1,22 +1,35 @@
|
|||||||
--- a/net/minecraft/world/entity/monster/Illusioner.java
|
--- a/net/minecraft/world/entity/monster/Illusioner.java
|
||||||
+++ b/net/minecraft/world/entity/monster/Illusioner.java
|
+++ b/net/minecraft/world/entity/monster/Illusioner.java
|
||||||
@@ -180,9 +_,19 @@
|
@@ -172,7 +_,8 @@
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void performRangedAttack(LivingEntity target, float distanceFactor) {
|
||||||
|
- ItemStack itemInHand = this.getItemInHand(ProjectileUtil.getWeaponHoldingHand(this, Items.BOW));
|
||||||
|
+ net.minecraft.world.InteractionHand hand = ProjectileUtil.getWeaponHoldingHand(this, Items.BOW); // Paper - call EntityShootBowEvent
|
||||||
|
+ ItemStack itemInHand = this.getItemInHand(hand); // Paper - call EntityShootBowEvent
|
||||||
|
ItemStack projectile = this.getProjectile(itemInHand);
|
||||||
|
AbstractArrow mobArrow = ProjectileUtil.getMobArrow(this, projectile, distanceFactor, itemInHand);
|
||||||
|
double d = target.getX() - this.getX();
|
||||||
|
@@ -180,9 +_,21 @@
|
||||||
double d2 = target.getZ() - this.getZ();
|
double d2 = target.getZ() - this.getZ();
|
||||||
double squareRoot = Math.sqrt(d * d + d2 * d2);
|
double squareRoot = Math.sqrt(d * d + d2 * d2);
|
||||||
if (this.level() instanceof ServerLevel serverLevel) {
|
if (this.level() instanceof ServerLevel serverLevel) {
|
||||||
+ // Paper start - EntityShootBowEvent
|
- Projectile.spawnProjectileUsingShoot(
|
||||||
+ org.bukkit.event.entity.EntityShootBowEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityShootBowEvent(this, this.getMainHandItem(), mobArrow.getPickupItem(), mobArrow, target.getUsedItemHand(), distanceFactor, true);
|
+ Projectile.Delayed<AbstractArrow> delayedEntity = Projectile.spawnProjectileUsingShootDelayed( // Paper - delayed
|
||||||
|
mobArrow, serverLevel, projectile, d, d1 + squareRoot * 0.2F, d2, 1.6F, 14 - serverLevel.getDifficulty().getId() * 4
|
||||||
|
);
|
||||||
|
+
|
||||||
|
+ // Paper start - call EntityShootBowEvent
|
||||||
|
+ org.bukkit.event.entity.EntityShootBowEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityShootBowEvent(this, itemInHand, mobArrow.getPickupItem(), mobArrow, hand, distanceFactor, true);
|
||||||
+ if (event.isCancelled()) {
|
+ if (event.isCancelled()) {
|
||||||
+ event.getProjectile().remove();
|
+ event.getProjectile().remove();
|
||||||
+ return;
|
+ return;
|
||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
+ if (event.getProjectile() == mobArrow.getBukkitEntity()) {
|
+ if (event.getProjectile() == mobArrow.getBukkitEntity()) {
|
||||||
Projectile.spawnProjectileUsingShoot(
|
+ delayedEntity.spawn();
|
||||||
mobArrow, serverLevel, projectile, d, d1 + squareRoot * 0.2F, d2, 1.6F, 14 - serverLevel.getDifficulty().getId() * 4
|
|
||||||
);
|
|
||||||
+ }
|
+ }
|
||||||
+ // Paper end - EntityShootBowEvent
|
+ // Paper end - call EntityShootBowEvent
|
||||||
}
|
}
|
||||||
|
|
||||||
this.playSound(SoundEvents.SKELETON_SHOOT, 1.0F, 1.0F / (this.getRandom().nextFloat() * 0.4F + 0.8F));
|
this.playSound(SoundEvents.SKELETON_SHOOT, 1.0F, 1.0F / (this.getRandom().nextFloat() * 0.4F + 0.8F));
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
--- a/net/minecraft/world/item/LeadItem.java
|
--- a/net/minecraft/world/item/LeadItem.java
|
||||||
+++ b/net/minecraft/world/item/LeadItem.java
|
+++ b/net/minecraft/world/item/LeadItem.java
|
||||||
@@ -26,24 +_,43 @@
|
@@ -26,24 +_,46 @@
|
||||||
if (blockState.is(BlockTags.FENCES)) {
|
if (blockState.is(BlockTags.FENCES)) {
|
||||||
Player player = context.getPlayer();
|
Player player = context.getPlayer();
|
||||||
if (!level.isClientSide && player != null) {
|
if (!level.isClientSide && player != null) {
|
||||||
@ -22,8 +22,11 @@
|
|||||||
+ for (java.util.Iterator<Leashable> iterator = list.iterator(); iterator.hasNext();) { // Paper - use iterator to remove
|
+ for (java.util.Iterator<Leashable> iterator = list.iterator(); iterator.hasNext();) { // Paper - use iterator to remove
|
||||||
+ Leashable leashable = iterator.next(); // Paper - use iterator to remove
|
+ Leashable leashable = iterator.next(); // Paper - use iterator to remove
|
||||||
if (leashFenceKnotEntity == null) {
|
if (leashFenceKnotEntity == null) {
|
||||||
leashFenceKnotEntity = LeashFenceKnotEntity.getOrCreateKnot(level, pos);
|
- leashFenceKnotEntity = LeashFenceKnotEntity.getOrCreateKnot(level, pos);
|
||||||
+ // CraftBukkit start - fire HangingPlaceEvent
|
+ // CraftBukkit start - fire HangingPlaceEvent
|
||||||
|
+ org.apache.commons.lang3.mutable.MutableBoolean created = new org.apache.commons.lang3.mutable.MutableBoolean(false);
|
||||||
|
+ leashFenceKnotEntity = LeashFenceKnotEntity.getOrCreateKnot(level, pos, created);
|
||||||
|
+ if (created.booleanValue()) {
|
||||||
+ org.bukkit.inventory.EquipmentSlot hand = org.bukkit.craftbukkit.CraftEquipmentSlot.getHand(interactionHand);
|
+ org.bukkit.inventory.EquipmentSlot hand = org.bukkit.craftbukkit.CraftEquipmentSlot.getHand(interactionHand);
|
||||||
+ org.bukkit.event.hanging.HangingPlaceEvent event = new org.bukkit.event.hanging.HangingPlaceEvent((org.bukkit.entity.Hanging) leashFenceKnotEntity.getBukkitEntity(), player != null ? (org.bukkit.entity.Player) player.getBukkitEntity() : null, org.bukkit.craftbukkit.block.CraftBlock.at(level, pos), org.bukkit.block.BlockFace.SELF, hand);
|
+ org.bukkit.event.hanging.HangingPlaceEvent event = new org.bukkit.event.hanging.HangingPlaceEvent((org.bukkit.entity.Hanging) leashFenceKnotEntity.getBukkitEntity(), player != null ? (org.bukkit.entity.Player) player.getBukkitEntity() : null, org.bukkit.craftbukkit.block.CraftBlock.at(level, pos), org.bukkit.block.BlockFace.SELF, hand);
|
||||||
+ level.getCraftServer().getPluginManager().callEvent(event);
|
+ level.getCraftServer().getPluginManager().callEvent(event);
|
||||||
@ -32,6 +35,7 @@
|
|||||||
+ leashFenceKnotEntity.discard(null); // CraftBukkit - add Bukkit remove cause
|
+ leashFenceKnotEntity.discard(null); // CraftBukkit - add Bukkit remove cause
|
||||||
+ return InteractionResult.PASS;
|
+ return InteractionResult.PASS;
|
||||||
+ }
|
+ }
|
||||||
|
+ }
|
||||||
+ // CraftBukkit end
|
+ // CraftBukkit end
|
||||||
leashFenceKnotEntity.playPlacementSound();
|
leashFenceKnotEntity.playPlacementSound();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,12 +12,18 @@
|
|||||||
|
|
||||||
public int getSuccessCount() {
|
public int getSuccessCount() {
|
||||||
return this.successCount;
|
return this.successCount;
|
||||||
@@ -108,7 +_,7 @@
|
@@ -108,7 +_,13 @@
|
||||||
this.successCount++;
|
this.successCount++;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
- server.getCommands().performPrefixedCommand(commandSourceStack, this.command);
|
- server.getCommands().performPrefixedCommand(commandSourceStack, this.command);
|
||||||
+ server.getCommands().dispatchServerCommand(commandSourceStack, this.command); // CraftBukkit
|
+ // Paper start - ServerCommandEvent
|
||||||
|
+ org.bukkit.event.server.ServerCommandEvent event = new org.bukkit.event.server.ServerCommandEvent(commandSourceStack.getBukkitSender(), net.minecraft.commands.Commands.trimOptionalPrefix(this.command));
|
||||||
|
+ if (!event.callEvent()) {
|
||||||
|
+ return true;
|
||||||
|
+ }
|
||||||
|
+ server.getCommands().performPrefixedCommand(commandSourceStack, event.getCommand());
|
||||||
|
+ // Paper end - ServerCommandEvent
|
||||||
} catch (Throwable var6) {
|
} catch (Throwable var6) {
|
||||||
CrashReport crashReport = CrashReport.forThrowable(var6, "Executing command block");
|
CrashReport crashReport = CrashReport.forThrowable(var6, "Executing command block");
|
||||||
CrashReportCategory crashReportCategory = crashReport.addCategory("Command to be executed");
|
CrashReportCategory crashReportCategory = crashReport.addCategory("Command to be executed");
|
||||||
|
|||||||
@ -30,7 +30,7 @@
|
|||||||
- builder.withParameter(LootContextParams.EXPLOSION_RADIUS, explosion.radius());
|
- builder.withParameter(LootContextParams.EXPLOSION_RADIUS, explosion.radius());
|
||||||
+ // CraftBukkit start - add yield
|
+ // CraftBukkit start - add yield
|
||||||
+ if (explosion instanceof net.minecraft.world.level.ServerExplosion serverExplosion && serverExplosion.yield < 1.0F) {
|
+ if (explosion instanceof net.minecraft.world.level.ServerExplosion serverExplosion && serverExplosion.yield < 1.0F) {
|
||||||
+ builder.withParameter(LootContextParams.EXPLOSION_RADIUS, serverExplosion.yield == 0 ? 0 : 1.0F / serverExplosion.yield);
|
+ builder.withParameter(LootContextParams.EXPLOSION_RADIUS, 1.0F / serverExplosion.yield);
|
||||||
+ // CraftBukkit end
|
+ // CraftBukkit end
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,15 @@
|
|||||||
|
--- a/net/minecraft/world/level/entity/EntitySection.java
|
||||||
|
+++ b/net/minecraft/world/level/entity/EntitySection.java
|
||||||
|
@@ -19,6 +_,12 @@
|
||||||
|
this.storage = new ClassInstanceMultiMap<>(entityClazz);
|
||||||
|
}
|
||||||
|
|
||||||
|
+ // Paper start - support retrieving all entities, regardless of whether they are accessible
|
||||||
|
+ public void getEntities(java.util.List<T> into) {
|
||||||
|
+ into.addAll(this.storage);
|
||||||
|
+ }
|
||||||
|
+ // Paper end - support retrieving all entities, regardless of whether they are accessible
|
||||||
|
+
|
||||||
|
public void add(T entity) {
|
||||||
|
this.storage.add(entity);
|
||||||
|
}
|
||||||
@ -0,0 +1,19 @@
|
|||||||
|
--- a/net/minecraft/world/level/entity/EntitySectionStorage.java
|
||||||
|
+++ b/net/minecraft/world/level/entity/EntitySectionStorage.java
|
||||||
|
@@ -34,6 +_,16 @@
|
||||||
|
this.intialSectionVisibility = initialSectionVisibility;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ // Paper start - support retrieving all entities, regardless of whether they are accessible
|
||||||
|
+ public Iterable<T> getAllEntities() {
|
||||||
|
+ java.util.List<T> ret = new java.util.ArrayList<>();
|
||||||
|
+ for (EntitySection<T> section : this.sections.values()) {
|
||||||
|
+ section.getEntities(ret);
|
||||||
|
+ }
|
||||||
|
+ return ret;
|
||||||
|
+ }
|
||||||
|
+ // Paper end - support retrieving all entities, regardless of whether they are accessible
|
||||||
|
+
|
||||||
|
public void forEachAccessibleNonEmptySection(AABB boundingBox, AbortableIterationConsumer<EntitySection<T>> consumer) {
|
||||||
|
int sectionPosCoord = SectionPos.posToSectionCoord(boundingBox.minX - 2.0);
|
||||||
|
int sectionPosCoord1 = SectionPos.posToSectionCoord(boundingBox.minY - 4.0);
|
||||||
@ -0,0 +1,11 @@
|
|||||||
|
--- a/net/minecraft/world/level/entity/LevelEntityGetterAdapter.java
|
||||||
|
+++ b/net/minecraft/world/level/entity/LevelEntityGetterAdapter.java
|
||||||
|
@@ -8,7 +_,7 @@
|
||||||
|
|
||||||
|
public class LevelEntityGetterAdapter<T extends EntityAccess> implements LevelEntityGetter<T> {
|
||||||
|
private final EntityLookup<T> visibleEntities;
|
||||||
|
- private final EntitySectionStorage<T> sectionStorage;
|
||||||
|
+ public final EntitySectionStorage<T> sectionStorage; // Paper - public
|
||||||
|
|
||||||
|
public LevelEntityGetterAdapter(EntityLookup<T> visibleEntities, EntitySectionStorage<T> sectionStorage) {
|
||||||
|
this.visibleEntities = visibleEntities;
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
--- a/net/minecraft/world/waypoints/WaypointTransmitter.java
|
||||||
|
+++ b/net/minecraft/world/waypoints/WaypointTransmitter.java
|
||||||
|
@@ -20,6 +_,7 @@
|
||||||
|
Waypoint.Icon waypointIcon();
|
||||||
|
|
||||||
|
static boolean doesSourceIgnoreReceiver(LivingEntity entity, ServerPlayer player) {
|
||||||
|
+ if (!player.getBukkitEntity().canSee(entity.getBukkitEntity())) return true; // Paper - ignore if entity is hidden from player
|
||||||
|
if (player.isSpectator()) {
|
||||||
|
return false;
|
||||||
|
} else if (!entity.isSpectator() && !entity.hasIndirectPassenger(player)) {
|
||||||
@ -1,10 +1,12 @@
|
|||||||
package io.papermc.paper;
|
package io.papermc.paper;
|
||||||
|
|
||||||
|
import io.papermc.paper.command.brigadier.CommandSourceStack;
|
||||||
import io.papermc.paper.world.damagesource.CombatEntry;
|
import io.papermc.paper.world.damagesource.CombatEntry;
|
||||||
import io.papermc.paper.world.damagesource.FallLocationType;
|
import io.papermc.paper.world.damagesource.FallLocationType;
|
||||||
import io.papermc.paper.world.damagesource.PaperCombatEntryWrapper;
|
import io.papermc.paper.world.damagesource.PaperCombatEntryWrapper;
|
||||||
import io.papermc.paper.world.damagesource.PaperCombatTrackerWrapper;
|
import io.papermc.paper.world.damagesource.PaperCombatTrackerWrapper;
|
||||||
import net.minecraft.Optionull;
|
import net.minecraft.Optionull;
|
||||||
|
import net.minecraft.commands.PermissionSource;
|
||||||
import net.minecraft.world.damagesource.FallLocation;
|
import net.minecraft.world.damagesource.FallLocation;
|
||||||
import org.bukkit.block.Biome;
|
import org.bukkit.block.Biome;
|
||||||
import org.bukkit.craftbukkit.block.CraftBiome;
|
import org.bukkit.craftbukkit.block.CraftBiome;
|
||||||
@ -16,6 +18,7 @@ import org.bukkit.damage.DamageSource;
|
|||||||
import org.bukkit.entity.LivingEntity;
|
import org.bukkit.entity.LivingEntity;
|
||||||
import org.jspecify.annotations.NullMarked;
|
import org.jspecify.annotations.NullMarked;
|
||||||
import org.jspecify.annotations.Nullable;
|
import org.jspecify.annotations.Nullable;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
@NullMarked
|
@NullMarked
|
||||||
public class PaperServerInternalAPIBridge implements InternalAPIBridge {
|
public class PaperServerInternalAPIBridge implements InternalAPIBridge {
|
||||||
@ -71,4 +74,16 @@ public class PaperServerInternalAPIBridge implements InternalAPIBridge {
|
|||||||
damageSource, damage, fallLocation, fallDistance
|
damageSource, damage, fallLocation, fallDistance
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Predicate<CommandSourceStack> restricted(final Predicate<CommandSourceStack> predicate) {
|
||||||
|
record RestrictedPredicate(Predicate<CommandSourceStack> predicate) implements Predicate<CommandSourceStack>, PermissionSource.RestrictedMarker {
|
||||||
|
@Override
|
||||||
|
public boolean test(final CommandSourceStack commandSourceStack) {
|
||||||
|
return this.predicate.test(commandSourceStack);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new RestrictedPredicate(predicate);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
package io.papermc.paper.adventure;
|
package io.papermc.paper.adventure;
|
||||||
|
|
||||||
|
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||||
import com.mojang.datafixers.util.Either;
|
import com.mojang.datafixers.util.Either;
|
||||||
import com.mojang.serialization.Codec;
|
import com.mojang.serialization.Codec;
|
||||||
import com.mojang.serialization.DataResult;
|
import com.mojang.serialization.DataResult;
|
||||||
@ -14,6 +15,7 @@ import java.util.function.Function;
|
|||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||||
import net.kyori.adventure.key.Key;
|
import net.kyori.adventure.key.Key;
|
||||||
|
import net.kyori.adventure.nbt.api.BinaryTagHolder;
|
||||||
import net.kyori.adventure.text.BlockNBTComponent;
|
import net.kyori.adventure.text.BlockNBTComponent;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import net.kyori.adventure.text.EntityNBTComponent;
|
import net.kyori.adventure.text.EntityNBTComponent;
|
||||||
@ -37,6 +39,9 @@ import net.kyori.adventure.text.format.TextDecoration;
|
|||||||
import net.minecraft.commands.arguments.selector.SelectorPattern;
|
import net.minecraft.commands.arguments.selector.SelectorPattern;
|
||||||
import net.minecraft.core.UUIDUtil;
|
import net.minecraft.core.UUIDUtil;
|
||||||
import net.minecraft.core.registries.BuiltInRegistries;
|
import net.minecraft.core.registries.BuiltInRegistries;
|
||||||
|
import net.minecraft.nbt.CompoundTag;
|
||||||
|
import net.minecraft.nbt.Tag;
|
||||||
|
import net.minecraft.nbt.TagParser;
|
||||||
import net.minecraft.network.RegistryFriendlyByteBuf;
|
import net.minecraft.network.RegistryFriendlyByteBuf;
|
||||||
import net.minecraft.network.chat.ComponentSerialization;
|
import net.minecraft.network.chat.ComponentSerialization;
|
||||||
import net.minecraft.network.chat.contents.KeybindContents;
|
import net.minecraft.network.chat.contents.KeybindContents;
|
||||||
@ -44,6 +49,7 @@ import net.minecraft.network.chat.contents.ScoreContents;
|
|||||||
import net.minecraft.network.chat.contents.TranslatableContents;
|
import net.minecraft.network.chat.contents.TranslatableContents;
|
||||||
import net.minecraft.network.codec.ByteBufCodecs;
|
import net.minecraft.network.codec.ByteBufCodecs;
|
||||||
import net.minecraft.network.codec.StreamCodec;
|
import net.minecraft.network.codec.StreamCodec;
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import net.minecraft.util.ExtraCodecs;
|
import net.minecraft.util.ExtraCodecs;
|
||||||
import net.minecraft.util.StringRepresentable;
|
import net.minecraft.util.StringRepresentable;
|
||||||
import net.minecraft.world.item.Item;
|
import net.minecraft.world.item.Item;
|
||||||
@ -63,7 +69,14 @@ import static net.kyori.adventure.text.TranslationArgument.numeric;
|
|||||||
|
|
||||||
@DefaultQualifier(NonNull.class)
|
@DefaultQualifier(NonNull.class)
|
||||||
public final class AdventureCodecs {
|
public final class AdventureCodecs {
|
||||||
|
public static final Codec<BinaryTagHolder> BINARY_TAG_HOLDER_CODEC = ExtraCodecs.NBT.flatComapMap(tag -> BinaryTagHolder.encode(tag, PaperAdventure.NBT_CODEC), api -> {
|
||||||
|
try {
|
||||||
|
final Tag tag = api.get(PaperAdventure.NBT_CODEC);
|
||||||
|
return DataResult.success(tag);
|
||||||
|
} catch (CommandSyntaxException e) {
|
||||||
|
return DataResult.error(e::getMessage);
|
||||||
|
}
|
||||||
|
});
|
||||||
public static final Codec<Component> COMPONENT_CODEC = recursive("adventure Component", AdventureCodecs::createCodec);
|
public static final Codec<Component> COMPONENT_CODEC = recursive("adventure Component", AdventureCodecs::createCodec);
|
||||||
public static final StreamCodec<RegistryFriendlyByteBuf, Component> STREAM_COMPONENT_CODEC = ByteBufCodecs.fromCodecWithRegistriesTrusted(COMPONENT_CODEC);
|
public static final StreamCodec<RegistryFriendlyByteBuf, Component> STREAM_COMPONENT_CODEC = ByteBufCodecs.fromCodecWithRegistriesTrusted(COMPONENT_CODEC);
|
||||||
|
|
||||||
@ -89,27 +102,37 @@ public final class AdventureCodecs {
|
|||||||
return Key.parseable(s) ? DataResult.success(Key.key(s)) : DataResult.error(() -> "Cannot convert " + s + " to adventure Key");
|
return Key.parseable(s) ? DataResult.success(Key.key(s)) : DataResult.error(() -> "Cannot convert " + s + " to adventure Key");
|
||||||
}, Key::asString);
|
}, Key::asString);
|
||||||
|
|
||||||
|
static final Function<ClickEvent, String> TEXT_PAYLOAD_EXTRACTOR = a -> ((ClickEvent.Payload.Text) a.payload()).value();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Click
|
* Click
|
||||||
*/
|
*/
|
||||||
static final MapCodec<ClickEvent> OPEN_URL_CODEC = mapCodec((instance) -> instance.group(
|
static final MapCodec<ClickEvent> OPEN_URL_CODEC = mapCodec((instance) -> instance.group(
|
||||||
ExtraCodecs.UNTRUSTED_URI.fieldOf("url").forGetter(a -> URI.create(!a.value().contains("://") ? "https://" + a.value() : a.value()))
|
ExtraCodecs.UNTRUSTED_URI.fieldOf("url").forGetter(a -> {
|
||||||
|
final String url = ((ClickEvent.Payload.Text) a.payload()).value();
|
||||||
|
return URI.create(!url.contains("://") ? "https://" + url : url);
|
||||||
|
}
|
||||||
|
)
|
||||||
).apply(instance, (url) -> ClickEvent.openUrl(url.toString())));
|
).apply(instance, (url) -> ClickEvent.openUrl(url.toString())));
|
||||||
static final MapCodec<ClickEvent> OPEN_FILE_CODEC = mapCodec((instance) -> instance.group(
|
static final MapCodec<ClickEvent> OPEN_FILE_CODEC = mapCodec((instance) -> instance.group(
|
||||||
Codec.STRING.fieldOf("path").forGetter(ClickEvent::value)
|
Codec.STRING.fieldOf("path").forGetter(TEXT_PAYLOAD_EXTRACTOR)
|
||||||
).apply(instance, ClickEvent::openFile));
|
).apply(instance, ClickEvent::openFile));
|
||||||
static final MapCodec<ClickEvent> RUN_COMMAND_CODEC = mapCodec((instance) -> instance.group(
|
static final MapCodec<ClickEvent> RUN_COMMAND_CODEC = mapCodec((instance) -> instance.group(
|
||||||
ExtraCodecs.CHAT_STRING.fieldOf("command").forGetter(ClickEvent::value)
|
ExtraCodecs.CHAT_STRING.fieldOf("command").forGetter(TEXT_PAYLOAD_EXTRACTOR)
|
||||||
).apply(instance, ClickEvent::runCommand));
|
).apply(instance, ClickEvent::runCommand));
|
||||||
static final MapCodec<ClickEvent> SUGGEST_COMMAND_CODEC = mapCodec((instance) -> instance.group(
|
static final MapCodec<ClickEvent> SUGGEST_COMMAND_CODEC = mapCodec((instance) -> instance.group(
|
||||||
ExtraCodecs.CHAT_STRING.fieldOf("command").forGetter(ClickEvent::value)
|
ExtraCodecs.CHAT_STRING.fieldOf("command").forGetter(TEXT_PAYLOAD_EXTRACTOR)
|
||||||
).apply(instance, ClickEvent::suggestCommand));
|
).apply(instance, ClickEvent::suggestCommand));
|
||||||
static final MapCodec<ClickEvent> CHANGE_PAGE_CODEC = mapCodec((instance) -> instance.group(
|
static final MapCodec<ClickEvent> CHANGE_PAGE_CODEC = mapCodec((instance) -> instance.group(
|
||||||
ExtraCodecs.POSITIVE_INT.fieldOf("page").forGetter(a -> Integer.parseInt(a.value()))
|
ExtraCodecs.POSITIVE_INT.fieldOf("page").forGetter(a -> ((ClickEvent.Payload.Int) a.payload()).integer())
|
||||||
).apply(instance, ClickEvent::changePage));
|
).apply(instance, ClickEvent::changePage));
|
||||||
static final MapCodec<ClickEvent> COPY_TO_CLIPBOARD_CODEC = mapCodec((instance) -> instance.group(
|
static final MapCodec<ClickEvent> COPY_TO_CLIPBOARD_CODEC = mapCodec((instance) -> instance.group(
|
||||||
Codec.STRING.fieldOf("value").forGetter(ClickEvent::value)
|
Codec.STRING.fieldOf("value").forGetter(TEXT_PAYLOAD_EXTRACTOR)
|
||||||
).apply(instance, ClickEvent::copyToClipboard));
|
).apply(instance, ClickEvent::copyToClipboard));
|
||||||
|
static final MapCodec<ClickEvent> CUSTOM_CODEC = mapCodec((instance) -> instance.group(
|
||||||
|
KEY_CODEC.fieldOf("id").forGetter(a -> ((ClickEvent.Payload.Custom) a.payload()).key()),
|
||||||
|
BINARY_TAG_HOLDER_CODEC.fieldOf("payload").forGetter(a -> ((ClickEvent.Payload.Custom) a.payload()).nbt())
|
||||||
|
).apply(instance, ClickEvent::custom));
|
||||||
|
|
||||||
static final ClickEventType OPEN_URL_CLICK_EVENT_TYPE = new ClickEventType(OPEN_URL_CODEC, "open_url");
|
static final ClickEventType OPEN_URL_CLICK_EVENT_TYPE = new ClickEventType(OPEN_URL_CODEC, "open_url");
|
||||||
static final ClickEventType OPEN_FILE_CLICK_EVENT_TYPE = new ClickEventType(OPEN_FILE_CODEC, "open_file");
|
static final ClickEventType OPEN_FILE_CLICK_EVENT_TYPE = new ClickEventType(OPEN_FILE_CODEC, "open_file");
|
||||||
@ -117,7 +140,8 @@ public final class AdventureCodecs {
|
|||||||
static final ClickEventType SUGGEST_COMMAND_CLICK_EVENT_TYPE = new ClickEventType(SUGGEST_COMMAND_CODEC, "suggest_command");
|
static final ClickEventType SUGGEST_COMMAND_CLICK_EVENT_TYPE = new ClickEventType(SUGGEST_COMMAND_CODEC, "suggest_command");
|
||||||
static final ClickEventType CHANGE_PAGE_CLICK_EVENT_TYPE = new ClickEventType(CHANGE_PAGE_CODEC, "change_page");
|
static final ClickEventType CHANGE_PAGE_CLICK_EVENT_TYPE = new ClickEventType(CHANGE_PAGE_CODEC, "change_page");
|
||||||
static final ClickEventType COPY_TO_CLIPBOARD_CLICK_EVENT_TYPE = new ClickEventType(COPY_TO_CLIPBOARD_CODEC, "copy_to_clipboard");
|
static final ClickEventType COPY_TO_CLIPBOARD_CLICK_EVENT_TYPE = new ClickEventType(COPY_TO_CLIPBOARD_CODEC, "copy_to_clipboard");
|
||||||
static final Codec<ClickEventType> CLICK_EVENT_TYPE_CODEC = StringRepresentable.fromValues(() -> new ClickEventType[]{OPEN_URL_CLICK_EVENT_TYPE, OPEN_FILE_CLICK_EVENT_TYPE, RUN_COMMAND_CLICK_EVENT_TYPE, SUGGEST_COMMAND_CLICK_EVENT_TYPE, CHANGE_PAGE_CLICK_EVENT_TYPE, COPY_TO_CLIPBOARD_CLICK_EVENT_TYPE});
|
static final ClickEventType CUSTOM_CLICK_EVENT_TYPE = new ClickEventType(CUSTOM_CODEC, "custom");
|
||||||
|
static final Codec<ClickEventType> CLICK_EVENT_TYPE_CODEC = StringRepresentable.fromValues(() -> new ClickEventType[]{OPEN_URL_CLICK_EVENT_TYPE, OPEN_FILE_CLICK_EVENT_TYPE, RUN_COMMAND_CLICK_EVENT_TYPE, SUGGEST_COMMAND_CLICK_EVENT_TYPE, CHANGE_PAGE_CLICK_EVENT_TYPE, COPY_TO_CLIPBOARD_CLICK_EVENT_TYPE, CUSTOM_CLICK_EVENT_TYPE});
|
||||||
|
|
||||||
record ClickEventType(MapCodec<ClickEvent> codec, String id) implements StringRepresentable {
|
record ClickEventType(MapCodec<ClickEvent> codec, String id) implements StringRepresentable {
|
||||||
@Override
|
@Override
|
||||||
@ -126,22 +150,16 @@ public final class AdventureCodecs {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final Function<ClickEvent, ClickEventType> GET_CLICK_EVENT_TYPE = he -> {
|
private static final Function<ClickEvent, ClickEventType> GET_CLICK_EVENT_TYPE =
|
||||||
if (he.action() == ClickEvent.Action.OPEN_URL) {
|
he -> switch (he.action()) {
|
||||||
return OPEN_URL_CLICK_EVENT_TYPE;
|
case OPEN_URL -> OPEN_URL_CLICK_EVENT_TYPE;
|
||||||
} else if (he.action() == ClickEvent.Action.OPEN_FILE) {
|
case OPEN_FILE -> OPEN_FILE_CLICK_EVENT_TYPE;
|
||||||
return OPEN_FILE_CLICK_EVENT_TYPE;
|
case RUN_COMMAND -> RUN_COMMAND_CLICK_EVENT_TYPE;
|
||||||
} else if (he.action() == ClickEvent.Action.RUN_COMMAND) {
|
case SUGGEST_COMMAND -> SUGGEST_COMMAND_CLICK_EVENT_TYPE;
|
||||||
return RUN_COMMAND_CLICK_EVENT_TYPE;
|
case CHANGE_PAGE -> CHANGE_PAGE_CLICK_EVENT_TYPE;
|
||||||
} else if (he.action() == ClickEvent.Action.SUGGEST_COMMAND) {
|
case COPY_TO_CLIPBOARD -> COPY_TO_CLIPBOARD_CLICK_EVENT_TYPE;
|
||||||
return SUGGEST_COMMAND_CLICK_EVENT_TYPE;
|
case SHOW_DIALOG -> throw new UnsupportedOperationException(); // todo: dialog codec with dialog "api"
|
||||||
} else if (he.action() == ClickEvent.Action.CHANGE_PAGE) {
|
case CUSTOM -> CUSTOM_CLICK_EVENT_TYPE;
|
||||||
return CHANGE_PAGE_CLICK_EVENT_TYPE;
|
|
||||||
} else if (he.action() == ClickEvent.Action.COPY_TO_CLIPBOARD) {
|
|
||||||
return COPY_TO_CLIPBOARD_CLICK_EVENT_TYPE;
|
|
||||||
} else {
|
|
||||||
throw new IllegalStateException();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static final Codec<ClickEvent> CLICK_EVENT_CODEC = CLICK_EVENT_TYPE_CODEC.dispatch("action", GET_CLICK_EVENT_TYPE, ClickEventType::codec);
|
static final Codec<ClickEvent> CLICK_EVENT_CODEC = CLICK_EVENT_TYPE_CODEC.dispatch("action", GET_CLICK_EVENT_TYPE, ClickEventType::codec);
|
||||||
|
|||||||
@ -35,8 +35,6 @@ import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
|
|||||||
import net.kyori.adventure.text.serializer.plain.PlainComponentSerializer;
|
import net.kyori.adventure.text.serializer.plain.PlainComponentSerializer;
|
||||||
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
|
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
|
||||||
import net.kyori.adventure.translation.GlobalTranslator;
|
import net.kyori.adventure.translation.GlobalTranslator;
|
||||||
import net.kyori.adventure.translation.TranslationRegistry;
|
|
||||||
import net.kyori.adventure.translation.Translator;
|
|
||||||
import net.kyori.adventure.util.Codec;
|
import net.kyori.adventure.util.Codec;
|
||||||
import net.minecraft.ChatFormatting;
|
import net.minecraft.ChatFormatting;
|
||||||
import net.minecraft.commands.CommandSourceStack;
|
import net.minecraft.commands.CommandSourceStack;
|
||||||
@ -78,16 +76,16 @@ import static java.util.Objects.requireNonNull;
|
|||||||
public final class PaperAdventure {
|
public final class PaperAdventure {
|
||||||
private static final Pattern LOCALIZATION_PATTERN = Pattern.compile("%(?:(\\d+)\\$)?s");
|
private static final Pattern LOCALIZATION_PATTERN = Pattern.compile("%(?:(\\d+)\\$)?s");
|
||||||
public static final ComponentFlattener FLATTENER = ComponentFlattener.basic().toBuilder()
|
public static final ComponentFlattener FLATTENER = ComponentFlattener.basic().toBuilder()
|
||||||
|
.nestingLimit(30) // todo: should this be configurable? a system property or config value?
|
||||||
.complexMapper(TranslatableComponent.class, (translatable, consumer) -> {
|
.complexMapper(TranslatableComponent.class, (translatable, consumer) -> {
|
||||||
if (!Language.getInstance().has(translatable.key())) {
|
final Language language = Language.getInstance();
|
||||||
for (final Translator source : GlobalTranslator.translator().sources()) {
|
final @Nullable String fallback = translatable.fallback();
|
||||||
if (source instanceof TranslationRegistry registry && registry.contains(translatable.key())) {
|
if (!language.has(translatable.key()) && (fallback == null || !language.has(fallback))) {
|
||||||
|
if (GlobalTranslator.translator().canTranslate(translatable.key(), Locale.US)) {
|
||||||
consumer.accept(GlobalTranslator.render(translatable, Locale.US));
|
consumer.accept(GlobalTranslator.render(translatable, Locale.US));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
final @Nullable String fallback = translatable.fallback();
|
|
||||||
final @NotNull String translated = Language.getInstance().getOrDefault(translatable.key(), fallback != null ? fallback : translatable.key());
|
final @NotNull String translated = Language.getInstance().getOrDefault(translatable.key(), fallback != null ? fallback : translatable.key());
|
||||||
|
|
||||||
final Matcher matcher = LOCALIZATION_PATTERN.matcher(translated);
|
final Matcher matcher = LOCALIZATION_PATTERN.matcher(translated);
|
||||||
@ -379,6 +377,7 @@ public final class PaperAdventure {
|
|||||||
case PLAYER -> SoundSource.PLAYERS;
|
case PLAYER -> SoundSource.PLAYERS;
|
||||||
case AMBIENT -> SoundSource.AMBIENT;
|
case AMBIENT -> SoundSource.AMBIENT;
|
||||||
case VOICE -> SoundSource.VOICE;
|
case VOICE -> SoundSource.VOICE;
|
||||||
|
case UI -> SoundSource.UI;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,24 +1,33 @@
|
|||||||
package io.papermc.paper.adventure.providers;
|
package io.papermc.paper.adventure.providers;
|
||||||
|
|
||||||
|
import io.papermc.paper.adventure.PaperAdventure;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Queue;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||||
import net.kyori.adventure.audience.Audience;
|
import net.kyori.adventure.audience.Audience;
|
||||||
|
import net.kyori.adventure.key.Key;
|
||||||
import net.kyori.adventure.text.event.ClickCallback;
|
import net.kyori.adventure.text.event.ClickCallback;
|
||||||
import net.kyori.adventure.text.event.ClickEvent;
|
import net.kyori.adventure.text.event.ClickEvent;
|
||||||
|
import net.minecraft.nbt.CompoundTag;
|
||||||
|
import net.minecraft.nbt.Tag;
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.util.Queue;
|
|
||||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
|
||||||
|
|
||||||
@SuppressWarnings("UnstableApiUsage") // permitted provider
|
@SuppressWarnings("UnstableApiUsage") // permitted provider
|
||||||
public class ClickCallbackProviderImpl implements ClickCallback.Provider {
|
public class ClickCallbackProviderImpl implements ClickCallback.Provider {
|
||||||
|
private static final Key CLICK_CALLBACK_KEY = Key.key("paper", "click_callback");
|
||||||
|
private static final String ID_KEY = "id";
|
||||||
|
|
||||||
|
public static final ResourceLocation CLICK_CALLBACK_RESOURCE_LOCATION = PaperAdventure.asVanilla(CLICK_CALLBACK_KEY);
|
||||||
public static final CallbackManager CALLBACK_MANAGER = new CallbackManager();
|
public static final CallbackManager CALLBACK_MANAGER = new CallbackManager();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NotNull ClickEvent create(final @NotNull ClickCallback<Audience> callback, final ClickCallback.@NotNull Options options) {
|
public @NotNull ClickEvent create(final @NotNull ClickCallback<Audience> callback, final ClickCallback.@NotNull Options options) {
|
||||||
return ClickEvent.runCommand("/paper:callback " + CALLBACK_MANAGER.addCallback(callback, options));
|
final CompoundTag tag = new CompoundTag();
|
||||||
|
tag.putString(ID_KEY, CALLBACK_MANAGER.addCallback(callback, options).toString());
|
||||||
|
return ClickEvent.custom(CLICK_CALLBACK_KEY, PaperAdventure.asBinaryTagHolder(tag));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final class CallbackManager {
|
public static final class CallbackManager {
|
||||||
@ -48,12 +57,21 @@ public class ClickCallbackProviderImpl implements ClickCallback.Provider {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void runCallback(final @NotNull Audience audience, final UUID id) {
|
public void tryRunCallback(final @NotNull Audience audience, final Tag tag) {
|
||||||
|
tag.asCompound().flatMap(t -> t.getString(ID_KEY)).ifPresent(s -> {
|
||||||
|
final UUID id;
|
||||||
|
try {
|
||||||
|
id = UUID.fromString(s);
|
||||||
|
} catch (final IllegalArgumentException ignored) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
final StoredCallback callback = this.callbacks.get(id);
|
final StoredCallback callback = this.callbacks.get(id);
|
||||||
if (callback != null && callback.valid()) { //TODO Message if expired/invalid?
|
if (callback != null && callback.valid()) {
|
||||||
callback.takeUse();
|
callback.takeUse();
|
||||||
callback.callback.accept(audience);
|
callback.callback.accept(audience);
|
||||||
}
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,35 +0,0 @@
|
|||||||
package io.papermc.paper.command;
|
|
||||||
|
|
||||||
import io.papermc.paper.adventure.providers.ClickCallbackProviderImpl;
|
|
||||||
import org.bukkit.command.Command;
|
|
||||||
import org.bukkit.command.CommandSender;
|
|
||||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
|
||||||
import org.checkerframework.framework.qual.DefaultQualifier;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
@DefaultQualifier(NonNull.class)
|
|
||||||
public class CallbackCommand extends Command {
|
|
||||||
|
|
||||||
protected CallbackCommand(final String name) {
|
|
||||||
super(name);
|
|
||||||
this.description = "ClickEvent callback";
|
|
||||||
this.usageMessage = "/callback <uuid>";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean execute(final CommandSender sender, final String commandLabel, final String[] args) {
|
|
||||||
if (args.length != 1) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
final UUID id;
|
|
||||||
try {
|
|
||||||
id = UUID.fromString(args[0]);
|
|
||||||
} catch (final IllegalArgumentException ignored) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
ClickCallbackProviderImpl.CALLBACK_MANAGER.runCallback(sender, id);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -23,7 +23,6 @@ public final class PaperCommands {
|
|||||||
|
|
||||||
public static void registerCommands(final MinecraftServer server) {
|
public static void registerCommands(final MinecraftServer server) {
|
||||||
COMMANDS.put("paper", new PaperCommand("paper"));
|
COMMANDS.put("paper", new PaperCommand("paper"));
|
||||||
COMMANDS.put("callback", new CallbackCommand("callback"));
|
|
||||||
COMMANDS.put("mspt", new MSPTCommand("mspt"));
|
COMMANDS.put("mspt", new MSPTCommand("mspt"));
|
||||||
|
|
||||||
COMMANDS.forEach((s, command) -> {
|
COMMANDS.forEach((s, command) -> {
|
||||||
|
|||||||
@ -20,6 +20,7 @@ import java.util.Spliterator;
|
|||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
import org.bukkit.command.Command;
|
import org.bukkit.command.Command;
|
||||||
|
import org.bukkit.craftbukkit.command.VanillaCommandWrapper;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
@ -96,7 +97,7 @@ public class BukkitBrigForwardingMap extends HashMap<String, Command> {
|
|||||||
public Command put(String key, Command value) {
|
public Command put(String key, Command value) {
|
||||||
Command old = this.get(key);
|
Command old = this.get(key);
|
||||||
this.getDispatcher().getRoot().removeCommand(key); // Override previous command
|
this.getDispatcher().getRoot().removeCommand(key); // Override previous command
|
||||||
if (value instanceof PluginVanillaCommandWrapper wrapper && wrapper.getName().equals(key)) {
|
if (value instanceof VanillaCommandWrapper wrapper && wrapper.getName().equals(key)) {
|
||||||
// Don't break when some plugin tries to remove and add back a plugin command registered with modern API...
|
// Don't break when some plugin tries to remove and add back a plugin command registered with modern API...
|
||||||
this.getDispatcher().getRoot().addChild((CommandNode) wrapper.vanillaCommand);
|
this.getDispatcher().getRoot().addChild((CommandNode) wrapper.vanillaCommand);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package io.papermc.paper.command.subcommands;
|
package io.papermc.paper.command.subcommands;
|
||||||
|
|
||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
|
import io.papermc.paper.FeatureHooks;
|
||||||
import io.papermc.paper.command.CommandUtil;
|
import io.papermc.paper.command.CommandUtil;
|
||||||
import io.papermc.paper.command.PaperSubcommand;
|
import io.papermc.paper.command.PaperSubcommand;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
@ -9,7 +10,6 @@ import java.util.Locale;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import net.kyori.adventure.text.event.ClickEvent;
|
import net.kyori.adventure.text.event.ClickEvent;
|
||||||
import net.kyori.adventure.text.event.HoverEvent;
|
import net.kyori.adventure.text.event.HoverEvent;
|
||||||
@ -102,7 +102,7 @@ public final class EntityCommand implements PaperSubcommand {
|
|||||||
ServerLevel world = ((CraftWorld) bukkitWorld).getHandle();
|
ServerLevel world = ((CraftWorld) bukkitWorld).getHandle();
|
||||||
Map<ResourceLocation, Integer> nonEntityTicking = Maps.newHashMap();
|
Map<ResourceLocation, Integer> nonEntityTicking = Maps.newHashMap();
|
||||||
ServerChunkCache chunkProviderServer = world.getChunkSource();
|
ServerChunkCache chunkProviderServer = world.getChunkSource();
|
||||||
world.getAllEntities().forEach(e -> {
|
FeatureHooks.getAllEntities(world).forEach(e -> {
|
||||||
ResourceLocation key = EntityType.getKey(e.getType());
|
ResourceLocation key = EntityType.getKey(e.getType());
|
||||||
|
|
||||||
MutablePair<Integer, Map<ChunkPos, Integer>> info = list.computeIfAbsent(key, k -> MutablePair.of(0, Maps.newHashMap()));
|
MutablePair<Integer, Map<ChunkPos, Integer>> info = list.computeIfAbsent(key, k -> MutablePair.of(0, Maps.newHashMap()));
|
||||||
|
|||||||
@ -343,7 +343,7 @@ public class GlobalConfiguration extends ConfigurationPart {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
public int maxJoinsPerTick = 5;
|
public int maxJoinsPerTick = 5;
|
||||||
public boolean fixEntityPositionDesync = true;
|
public boolean sendFullPosForItemEntities = false;
|
||||||
public boolean loadPermissionsYmlBeforePlugins = true;
|
public boolean loadPermissionsYmlBeforePlugins = true;
|
||||||
@Constraints.Min(4)
|
@Constraints.Min(4)
|
||||||
public int regionFileCacheSize = 256;
|
public int regionFileCacheSize = 256;
|
||||||
|
|||||||
@ -82,6 +82,7 @@ interface RemovedConfigurations {
|
|||||||
path("unsupported-settings", "allow-grindstone-overstacking"),
|
path("unsupported-settings", "allow-grindstone-overstacking"),
|
||||||
path("unsupported-settings", "allow-tripwire-disarming-exploits"),
|
path("unsupported-settings", "allow-tripwire-disarming-exploits"),
|
||||||
path("commands", "fix-target-selector-tag-completion"),
|
path("commands", "fix-target-selector-tag-completion"),
|
||||||
|
path("misc", "fix-entity-position-desync")
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package io.papermc.paper.threadedregions;
|
package io.papermc.paper.threadedregions;
|
||||||
|
|
||||||
import ca.spottedleaf.concurrentutil.util.Validate;
|
import ca.spottedleaf.concurrentutil.util.Validate;
|
||||||
|
import ca.spottedleaf.moonrise.common.list.ReferenceList;
|
||||||
import ca.spottedleaf.moonrise.common.util.TickThread;
|
import ca.spottedleaf.moonrise.common.util.TickThread;
|
||||||
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
|
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
|
||||||
import net.minecraft.world.entity.Entity;
|
import net.minecraft.world.entity.Entity;
|
||||||
@ -9,6 +10,8 @@ import org.bukkit.craftbukkit.entity.CraftEntity;
|
|||||||
import java.util.ArrayDeque;
|
import java.util.ArrayDeque;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
|
import java.util.concurrent.locks.StampedLock;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -43,6 +46,8 @@ public final class EntityScheduler {
|
|||||||
private static final long RETIRED_TICK_COUNT = -1L;
|
private static final long RETIRED_TICK_COUNT = -1L;
|
||||||
private final Object stateLock = new Object();
|
private final Object stateLock = new Object();
|
||||||
private final Long2ObjectOpenHashMap<List<ScheduledTask>> oneTimeDelayed = new Long2ObjectOpenHashMap<>();
|
private final Long2ObjectOpenHashMap<List<ScheduledTask>> oneTimeDelayed = new Long2ObjectOpenHashMap<>();
|
||||||
|
private EntitySchedulerTickList scheduledList;
|
||||||
|
private boolean insideScheduledList;
|
||||||
|
|
||||||
private final ArrayDeque<ScheduledTask> currentlyExecuting = new ArrayDeque<>();
|
private final ArrayDeque<ScheduledTask> currentlyExecuting = new ArrayDeque<>();
|
||||||
|
|
||||||
@ -50,6 +55,51 @@ public final class EntityScheduler {
|
|||||||
this.entity = Validate.notNull(entity);
|
this.entity = Validate.notNull(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// must own state lock
|
||||||
|
private boolean hasTasks() {
|
||||||
|
return !this.currentlyExecuting.isEmpty() || !this.oneTimeDelayed.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void registerTo(final EntitySchedulerTickList newTickList) {
|
||||||
|
synchronized (this.stateLock) {
|
||||||
|
final EntitySchedulerTickList prevList = this.scheduledList;
|
||||||
|
if (prevList == newTickList) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.scheduledList = newTickList;
|
||||||
|
|
||||||
|
// make sure tasks scheduled before registration can be ticked
|
||||||
|
if (prevList == null && this.hasTasks()) {
|
||||||
|
this.insideScheduledList = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// transfer to new list
|
||||||
|
if (this.insideScheduledList) {
|
||||||
|
if (prevList != null) {
|
||||||
|
prevList.remove(this);
|
||||||
|
}
|
||||||
|
if (newTickList != null) {
|
||||||
|
newTickList.add(this);
|
||||||
|
} else {
|
||||||
|
// retired
|
||||||
|
this.insideScheduledList = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether this scheduler is retired.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* Note: This should only be invoked on the owning thread for the entity.
|
||||||
|
* </p>
|
||||||
|
* @return whether this scheduler is retired.
|
||||||
|
*/
|
||||||
|
public boolean isRetired() {
|
||||||
|
return this.tickCount == RETIRED_TICK_COUNT;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retires the scheduler, preventing new tasks from being scheduled and invoking the retired callback
|
* Retires the scheduler, preventing new tasks from being scheduled and invoking the retired callback
|
||||||
* on all currently scheduled tasks.
|
* on all currently scheduled tasks.
|
||||||
@ -66,6 +116,7 @@ public final class EntityScheduler {
|
|||||||
throw new IllegalStateException("Already retired");
|
throw new IllegalStateException("Already retired");
|
||||||
}
|
}
|
||||||
this.tickCount = RETIRED_TICK_COUNT;
|
this.tickCount = RETIRED_TICK_COUNT;
|
||||||
|
this.registerTo(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
final Entity thisEntity = this.entity.getHandleRaw();
|
final Entity thisEntity = this.entity.getHandleRaw();
|
||||||
@ -127,6 +178,11 @@ public final class EntityScheduler {
|
|||||||
this.oneTimeDelayed.computeIfAbsent(this.tickCount + Math.max(1L, delay), (final long keyInMap) -> {
|
this.oneTimeDelayed.computeIfAbsent(this.tickCount + Math.max(1L, delay), (final long keyInMap) -> {
|
||||||
return new ArrayList<>();
|
return new ArrayList<>();
|
||||||
}).add(task);
|
}).add(task);
|
||||||
|
|
||||||
|
if (!this.insideScheduledList && this.scheduledList != null) {
|
||||||
|
this.scheduledList.add(this);
|
||||||
|
this.insideScheduledList = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -147,6 +203,12 @@ public final class EntityScheduler {
|
|||||||
throw new IllegalStateException("Ticking retired scheduler");
|
throw new IllegalStateException("Ticking retired scheduler");
|
||||||
}
|
}
|
||||||
++this.tickCount;
|
++this.tickCount;
|
||||||
|
|
||||||
|
if (this.scheduledList != null && !this.hasTasks()) {
|
||||||
|
this.scheduledList.remove(this);
|
||||||
|
this.insideScheduledList = false;
|
||||||
|
}
|
||||||
|
|
||||||
if (this.oneTimeDelayed.isEmpty()) {
|
if (this.oneTimeDelayed.isEmpty()) {
|
||||||
toRun = null;
|
toRun = null;
|
||||||
} else {
|
} else {
|
||||||
@ -178,4 +240,34 @@ public final class EntityScheduler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static final class EntitySchedulerTickList {
|
||||||
|
|
||||||
|
private static final EntityScheduler[] ENTITY_SCHEDULER_ARRAY = new EntityScheduler[0];
|
||||||
|
|
||||||
|
private final ReferenceList<EntityScheduler> entitySchedulers = new ReferenceList<>(ENTITY_SCHEDULER_ARRAY);
|
||||||
|
|
||||||
|
public boolean add(final EntityScheduler scheduler) {
|
||||||
|
synchronized (this) {
|
||||||
|
return this.entitySchedulers.add(scheduler);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void remove(final EntityScheduler scheduler) {
|
||||||
|
synchronized (this) {
|
||||||
|
this.entitySchedulers.remove(scheduler);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public EntityScheduler[] getAllSchedulers() {
|
||||||
|
EntityScheduler[] ret = new EntityScheduler[this.entitySchedulers.size()];
|
||||||
|
synchronized (this) {
|
||||||
|
if (ret.length != this.entitySchedulers.size()) {
|
||||||
|
ret = new EntityScheduler[this.entitySchedulers.size()];
|
||||||
|
}
|
||||||
|
System.arraycopy(this.entitySchedulers.getRawDataUnchecked(), 0, ret, 0, this.entitySchedulers.size());
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -302,7 +302,6 @@ public final class CraftServer implements Server {
|
|||||||
public CraftDataPackManager dataPackManager;
|
public CraftDataPackManager dataPackManager;
|
||||||
private final CraftServerTickManager serverTickManager;
|
private final CraftServerTickManager serverTickManager;
|
||||||
private final CraftServerLinks serverLinks;
|
private final CraftServerLinks serverLinks;
|
||||||
public boolean playerCommandState;
|
|
||||||
private boolean printSaveWarning;
|
private boolean printSaveWarning;
|
||||||
private CraftIconCache icon;
|
private CraftIconCache icon;
|
||||||
private boolean overrideAllCommandBlockCommands = false;
|
private boolean overrideAllCommandBlockCommands = false;
|
||||||
@ -613,7 +612,6 @@ public final class CraftServer implements Server {
|
|||||||
// Spigot start - Allow vanilla commands to be forced to be the main command
|
// Spigot start - Allow vanilla commands to be forced to be the main command
|
||||||
this.commandMap.setFallbackCommands();
|
this.commandMap.setFallbackCommands();
|
||||||
// Spigot end
|
// Spigot end
|
||||||
this.commandMap.registerServerAliases();
|
|
||||||
DefaultPermissions.registerCorePermissions();
|
DefaultPermissions.registerCorePermissions();
|
||||||
CraftDefaultPermissions.registerCorePermissions();
|
CraftDefaultPermissions.registerCorePermissions();
|
||||||
if (!io.papermc.paper.configuration.GlobalConfiguration.get().misc.loadPermissionsYmlBeforePlugins) this.loadCustomPermissions(); // Paper
|
if (!io.papermc.paper.configuration.GlobalConfiguration.get().misc.loadPermissionsYmlBeforePlugins) this.loadCustomPermissions(); // Paper
|
||||||
@ -974,41 +972,13 @@ public final class CraftServer implements Server {
|
|||||||
return this.playerList;
|
return this.playerList;
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: Should only be called from DedicatedServer.ah()
|
|
||||||
public boolean dispatchServerCommand(CommandSender sender, ConsoleInput serverCommand) {
|
|
||||||
if (sender instanceof Conversable) {
|
|
||||||
Conversable conversable = (Conversable) sender;
|
|
||||||
|
|
||||||
if (conversable.isConversing()) {
|
|
||||||
conversable.acceptConversationInput(serverCommand.msg);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
this.playerCommandState = true;
|
|
||||||
return this.dispatchCommand(sender, serverCommand.msg);
|
|
||||||
} catch (Exception ex) {
|
|
||||||
this.getLogger().log(Level.WARNING, "Unexpected exception while parsing console command \"" + serverCommand.msg + '"', ex);
|
|
||||||
return false;
|
|
||||||
} finally {
|
|
||||||
this.playerCommandState = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean dispatchCommand(CommandSender sender, String commandLine) {
|
public boolean dispatchCommand(CommandSender rawSender, String commandLine) {
|
||||||
Preconditions.checkArgument(sender != null, "sender cannot be null");
|
Preconditions.checkArgument(rawSender != null, "sender cannot be null");
|
||||||
Preconditions.checkArgument(commandLine != null, "commandLine cannot be null");
|
Preconditions.checkArgument(commandLine != null, "commandLine cannot be null");
|
||||||
org.spigotmc.AsyncCatcher.catchOp("Command Dispatched Async: " + commandLine); // Spigot // Paper - Include command in error message
|
org.spigotmc.AsyncCatcher.catchOp("Command Dispatched Async: " + commandLine); // Spigot // Paper - Include command in error message
|
||||||
|
CommandSourceStack sourceStack = VanillaCommandWrapper.getListener(rawSender);
|
||||||
|
|
||||||
if (this.commandMap.dispatch(sender, commandLine)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.dispatchCommand(VanillaCommandWrapper.getListener(sender), commandLine);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean dispatchCommand(CommandSourceStack sourceStack, String commandLine) {
|
|
||||||
net.minecraft.commands.Commands commands = this.getHandle().getServer().getCommands();
|
net.minecraft.commands.Commands commands = this.getHandle().getServer().getCommands();
|
||||||
com.mojang.brigadier.CommandDispatcher<CommandSourceStack> dispatcher = commands.getDispatcher();
|
com.mojang.brigadier.CommandDispatcher<CommandSourceStack> dispatcher = commands.getDispatcher();
|
||||||
com.mojang.brigadier.ParseResults<CommandSourceStack> results = dispatcher.parse(commandLine, sourceStack);
|
com.mojang.brigadier.ParseResults<CommandSourceStack> results = dispatcher.parse(commandLine, sourceStack);
|
||||||
@ -1018,7 +988,12 @@ public final class CraftServer implements Server {
|
|||||||
Command target = this.commandMap.getCommand(args[0].toLowerCase(java.util.Locale.ENGLISH));
|
Command target = this.commandMap.getCommand(args[0].toLowerCase(java.util.Locale.ENGLISH));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
commands.performCommand(results, commandLine, commandLine, true);
|
if (results.getContext().getNodes().isEmpty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Commands.validateParseResults(results);
|
||||||
|
commands.performCommand(results, commandLine, true);
|
||||||
|
return true;
|
||||||
} catch (CommandException ex) {
|
} catch (CommandException ex) {
|
||||||
new com.destroystokyo.paper.event.server.ServerExceptionEvent(new com.destroystokyo.paper.exception.ServerCommandException(ex, target, sender, args)).callEvent(); // Paper
|
new com.destroystokyo.paper.event.server.ServerExceptionEvent(new com.destroystokyo.paper.exception.ServerCommandException(ex, target, sender, args)).callEvent(); // Paper
|
||||||
throw ex;
|
throw ex;
|
||||||
@ -1027,9 +1002,6 @@ public final class CraftServer implements Server {
|
|||||||
new com.destroystokyo.paper.event.server.ServerExceptionEvent(new com.destroystokyo.paper.exception.ServerCommandException(ex, target, sender, args)).callEvent(); // Paper
|
new com.destroystokyo.paper.event.server.ServerExceptionEvent(new com.destroystokyo.paper.exception.ServerCommandException(ex, target, sender, args)).callEvent(); // Paper
|
||||||
throw new CommandException(msg, ex);
|
throw new CommandException(msg, ex);
|
||||||
}
|
}
|
||||||
// Paper end
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -2609,7 +2581,7 @@ public final class CraftServer implements Server {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void checkSaveState() {
|
public void checkSaveState() {
|
||||||
if (this.playerCommandState || this.printSaveWarning || this.console.autosavePeriod <= 0) {
|
if (this.printSaveWarning || this.console.autosavePeriod <= 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.printSaveWarning = true;
|
this.printSaveWarning = true;
|
||||||
|
|||||||
@ -29,6 +29,7 @@ import java.util.UUID;
|
|||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
import net.kyori.adventure.pointer.PointersSupplier;
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.core.Holder;
|
import net.minecraft.core.Holder;
|
||||||
import net.minecraft.core.HolderSet;
|
import net.minecraft.core.HolderSet;
|
||||||
@ -157,6 +158,10 @@ import org.jetbrains.annotations.Nullable;
|
|||||||
public class CraftWorld extends CraftRegionAccessor implements World {
|
public class CraftWorld extends CraftRegionAccessor implements World {
|
||||||
public static final int CUSTOM_DIMENSION_OFFSET = 10;
|
public static final int CUSTOM_DIMENSION_OFFSET = 10;
|
||||||
private static final CraftPersistentDataTypeRegistry DATA_TYPE_REGISTRY = new CraftPersistentDataTypeRegistry();
|
private static final CraftPersistentDataTypeRegistry DATA_TYPE_REGISTRY = new CraftPersistentDataTypeRegistry();
|
||||||
|
private static final PointersSupplier<World> POINTERS_SUPPLIER = PointersSupplier.<World>builder()
|
||||||
|
.resolving(net.kyori.adventure.identity.Identity.NAME, World::getName)
|
||||||
|
.resolving(net.kyori.adventure.identity.Identity.UUID, World::getUID)
|
||||||
|
.build();
|
||||||
|
|
||||||
private final ServerLevel world;
|
private final ServerLevel world;
|
||||||
private WorldBorder worldBorder;
|
private WorldBorder worldBorder;
|
||||||
@ -168,7 +173,6 @@ public class CraftWorld extends CraftRegionAccessor implements World {
|
|||||||
private final BlockMetadataStore blockMetadata = new BlockMetadataStore(this);
|
private final BlockMetadataStore blockMetadata = new BlockMetadataStore(this);
|
||||||
private final Object2IntOpenHashMap<SpawnCategory> spawnCategoryLimit = new Object2IntOpenHashMap<>();
|
private final Object2IntOpenHashMap<SpawnCategory> spawnCategoryLimit = new Object2IntOpenHashMap<>();
|
||||||
private final CraftPersistentDataContainer persistentDataContainer = new CraftPersistentDataContainer(CraftWorld.DATA_TYPE_REGISTRY);
|
private final CraftPersistentDataContainer persistentDataContainer = new CraftPersistentDataContainer(CraftWorld.DATA_TYPE_REGISTRY);
|
||||||
private net.kyori.adventure.pointer.Pointers adventure$pointers; // Paper - implement pointers
|
|
||||||
// Paper start - void damage configuration
|
// Paper start - void damage configuration
|
||||||
private boolean voidDamageEnabled;
|
private boolean voidDamageEnabled;
|
||||||
private float voidDamageAmount;
|
private float voidDamageAmount;
|
||||||
@ -2481,14 +2485,7 @@ public class CraftWorld extends CraftRegionAccessor implements World {
|
|||||||
// Paper start - implement pointers
|
// Paper start - implement pointers
|
||||||
@Override
|
@Override
|
||||||
public net.kyori.adventure.pointer.Pointers pointers() {
|
public net.kyori.adventure.pointer.Pointers pointers() {
|
||||||
if (this.adventure$pointers == null) {
|
return POINTERS_SUPPLIER.view(this);
|
||||||
this.adventure$pointers = net.kyori.adventure.pointer.Pointers.builder()
|
|
||||||
.withDynamic(net.kyori.adventure.identity.Identity.NAME, this::getName)
|
|
||||||
.withDynamic(net.kyori.adventure.identity.Identity.UUID, this::getUID)
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.adventure$pointers;
|
|
||||||
}
|
}
|
||||||
// Paper end
|
// Paper end
|
||||||
}
|
}
|
||||||
|
|||||||
@ -74,7 +74,7 @@ public abstract class CraftBlockEntityState<T extends BlockEntity> extends Craft
|
|||||||
this.loadData(state.getSnapshotNBT());
|
this.loadData(state.getSnapshotNBT());
|
||||||
}
|
}
|
||||||
|
|
||||||
private RegistryAccess getRegistryAccess() {
|
public RegistryAccess getRegistryAccess() {
|
||||||
LevelAccessor worldHandle = this.getWorldHandle();
|
LevelAccessor worldHandle = this.getWorldHandle();
|
||||||
return (worldHandle != null) ? worldHandle.registryAccess() : CraftRegistry.getMinecraftRegistry();
|
return (worldHandle != null) ? worldHandle.registryAccess() : CraftRegistry.getMinecraftRegistry();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,7 +8,6 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import net.minecraft.core.RegistryAccess;
|
|
||||||
import net.minecraft.nbt.CompoundTag;
|
import net.minecraft.nbt.CompoundTag;
|
||||||
import net.minecraft.util.InclusiveRange;
|
import net.minecraft.util.InclusiveRange;
|
||||||
import net.minecraft.util.ProblemReporter;
|
import net.minecraft.util.ProblemReporter;
|
||||||
@ -51,7 +50,7 @@ public class CraftCreatureSpawner extends CraftBlockEntityState<SpawnerBlockEnti
|
|||||||
}
|
}
|
||||||
|
|
||||||
try (ProblemReporter.ScopedCollector scopedCollector = new ProblemReporter.ScopedCollector(() -> "spawner@" + getLocation(), LOGGER)) {
|
try (ProblemReporter.ScopedCollector scopedCollector = new ProblemReporter.ScopedCollector(() -> "spawner@" + getLocation(), LOGGER)) {
|
||||||
ValueInput valueInput = TagValueInput.create(scopedCollector, this.getInternalWorld().registryAccess(), spawnData.entityToSpawn());
|
ValueInput valueInput = TagValueInput.create(scopedCollector, this.getRegistryAccess(), spawnData.entityToSpawn());
|
||||||
Optional<net.minecraft.world.entity.EntityType<?>> type = net.minecraft.world.entity.EntityType.by(valueInput);
|
Optional<net.minecraft.world.entity.EntityType<?>> type = net.minecraft.world.entity.EntityType.by(valueInput);
|
||||||
return type.map(CraftEntityType::minecraftToBukkit).orElse(null);
|
return type.map(CraftEntityType::minecraftToBukkit).orElse(null);
|
||||||
}
|
}
|
||||||
@ -183,7 +182,7 @@ public class CraftCreatureSpawner extends CraftBlockEntityState<SpawnerBlockEnti
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
try (ProblemReporter.ScopedCollector scopedCollector = new ProblemReporter.ScopedCollector(() -> "spawner@" + getLocation(), LOGGER)) {
|
try (ProblemReporter.ScopedCollector scopedCollector = new ProblemReporter.ScopedCollector(() -> "spawner@" + getLocation(), LOGGER)) {
|
||||||
ValueInput valueInput = TagValueInput.create(scopedCollector, this.getInternalWorld().registryAccess(), spawnData.getEntityToSpawn());
|
ValueInput valueInput = TagValueInput.create(scopedCollector, this.getRegistryAccess(), spawnData.getEntityToSpawn());
|
||||||
Optional<net.minecraft.world.entity.EntityType<?>> type = net.minecraft.world.entity.EntityType.by(valueInput);
|
Optional<net.minecraft.world.entity.EntityType<?>> type = net.minecraft.world.entity.EntityType.by(valueInput);
|
||||||
|
|
||||||
return type.map(CraftEntityType::minecraftToBukkit).map(CraftEntityType::bukkitToString).orElse(null);
|
return type.map(CraftEntityType::minecraftToBukkit).map(CraftEntityType::bukkitToString).orElse(null);
|
||||||
|
|||||||
@ -2,6 +2,7 @@ package org.bukkit.craftbukkit.command;
|
|||||||
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import net.kyori.adventure.pointer.PointersSupplier;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.Server;
|
import org.bukkit.Server;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
@ -12,8 +13,12 @@ import org.bukkit.permissions.PermissionAttachmentInfo;
|
|||||||
import org.bukkit.plugin.Plugin;
|
import org.bukkit.plugin.Plugin;
|
||||||
|
|
||||||
public abstract class ServerCommandSender implements CommandSender {
|
public abstract class ServerCommandSender implements CommandSender {
|
||||||
|
private static final PointersSupplier<ServerCommandSender> POINTERS_SUPPLIER = PointersSupplier.<ServerCommandSender>builder()
|
||||||
|
.resolving(net.kyori.adventure.identity.Identity.DISPLAY_NAME, ServerCommandSender::name)
|
||||||
|
.resolving(net.kyori.adventure.permission.PermissionChecker.POINTER, serverCommandSender -> serverCommandSender::permissionValue)
|
||||||
|
.build();
|
||||||
|
|
||||||
public final PermissibleBase perm;
|
public final PermissibleBase perm;
|
||||||
private net.kyori.adventure.pointer.Pointers adventure$pointers;
|
|
||||||
|
|
||||||
protected ServerCommandSender() {
|
protected ServerCommandSender() {
|
||||||
this.perm = new PermissibleBase(this);
|
this.perm = new PermissibleBase(this);
|
||||||
@ -126,13 +131,6 @@ public abstract class ServerCommandSender implements CommandSender {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public net.kyori.adventure.pointer.Pointers pointers() {
|
public net.kyori.adventure.pointer.Pointers pointers() {
|
||||||
if (this.adventure$pointers == null) {
|
return POINTERS_SUPPLIER.view(this);
|
||||||
this.adventure$pointers = net.kyori.adventure.pointer.Pointers.builder()
|
|
||||||
.withDynamic(net.kyori.adventure.identity.Identity.DISPLAY_NAME, this::name)
|
|
||||||
.withStatic(net.kyori.adventure.permission.PermissionChecker.POINTER, this::permissionValue)
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.adventure$pointers;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -50,7 +50,7 @@ public class VanillaCommandWrapper extends BukkitCommand { // Paper
|
|||||||
if (!this.testPermission(sender)) return true;
|
if (!this.testPermission(sender)) return true;
|
||||||
|
|
||||||
CommandSourceStack source = VanillaCommandWrapper.getListener(sender);
|
CommandSourceStack source = VanillaCommandWrapper.getListener(sender);
|
||||||
this.commands().performPrefixedCommand(source, this.toDispatcher(args, this.getName()), this.toDispatcher(args, commandLabel)); // Paper
|
this.commands().performPrefixedCommand(source, this.toDispatcher(args, this.getName()));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -14,6 +14,7 @@ import java.util.Set;
|
|||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import io.papermc.paper.entity.LookAnchor;
|
import io.papermc.paper.entity.LookAnchor;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import net.kyori.adventure.pointer.PointersSupplier;
|
||||||
import net.kyori.adventure.util.TriState;
|
import net.kyori.adventure.util.TriState;
|
||||||
import net.minecraft.nbt.CompoundTag;
|
import net.minecraft.nbt.CompoundTag;
|
||||||
import net.minecraft.network.chat.Component;
|
import net.minecraft.network.chat.Component;
|
||||||
@ -85,13 +86,17 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
|
|||||||
|
|
||||||
private static PermissibleBase perm;
|
private static PermissibleBase perm;
|
||||||
private static final CraftPersistentDataTypeRegistry DATA_TYPE_REGISTRY = new CraftPersistentDataTypeRegistry();
|
private static final CraftPersistentDataTypeRegistry DATA_TYPE_REGISTRY = new CraftPersistentDataTypeRegistry();
|
||||||
|
static final PointersSupplier<org.bukkit.entity.Entity> POINTERS_SUPPLIER = PointersSupplier.<org.bukkit.entity.Entity>builder()
|
||||||
|
.resolving(net.kyori.adventure.identity.Identity.DISPLAY_NAME, org.bukkit.entity.Entity::name)
|
||||||
|
.resolving(net.kyori.adventure.identity.Identity.UUID, org.bukkit.entity.Entity::getUniqueId)
|
||||||
|
.resolving(net.kyori.adventure.permission.PermissionChecker.POINTER, entity1 -> entity1::permissionValue)
|
||||||
|
.build();
|
||||||
|
|
||||||
protected final CraftServer server;
|
protected final CraftServer server;
|
||||||
protected Entity entity;
|
protected Entity entity;
|
||||||
private final EntityType entityType;
|
private final EntityType entityType;
|
||||||
private EntityDamageEvent lastDamageEvent;
|
private EntityDamageEvent lastDamageEvent;
|
||||||
private final CraftPersistentDataContainer persistentDataContainer = new CraftPersistentDataContainer(CraftEntity.DATA_TYPE_REGISTRY);
|
private final CraftPersistentDataContainer persistentDataContainer = new CraftPersistentDataContainer(CraftEntity.DATA_TYPE_REGISTRY);
|
||||||
protected net.kyori.adventure.pointer.Pointers adventure$pointers; // Paper - implement pointers
|
|
||||||
// Paper start - Folia shedulers
|
// Paper start - Folia shedulers
|
||||||
public final io.papermc.paper.threadedregions.EntityScheduler taskScheduler = new io.papermc.paper.threadedregions.EntityScheduler(this);
|
public final io.papermc.paper.threadedregions.EntityScheduler taskScheduler = new io.papermc.paper.threadedregions.EntityScheduler(this);
|
||||||
private final io.papermc.paper.threadedregions.scheduler.FoliaEntityScheduler apiScheduler = new io.papermc.paper.threadedregions.scheduler.FoliaEntityScheduler(this);
|
private final io.papermc.paper.threadedregions.scheduler.FoliaEntityScheduler apiScheduler = new io.papermc.paper.threadedregions.scheduler.FoliaEntityScheduler(this);
|
||||||
@ -670,15 +675,7 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public net.kyori.adventure.pointer.Pointers pointers() {
|
public net.kyori.adventure.pointer.Pointers pointers() {
|
||||||
if (this.adventure$pointers == null) {
|
return POINTERS_SUPPLIER.view(this);
|
||||||
this.adventure$pointers = net.kyori.adventure.pointer.Pointers.builder()
|
|
||||||
.withDynamic(net.kyori.adventure.identity.Identity.DISPLAY_NAME, this::name)
|
|
||||||
.withDynamic(net.kyori.adventure.identity.Identity.UUID, this::getUniqueId)
|
|
||||||
.withStatic(net.kyori.adventure.permission.PermissionChecker.POINTER, this::permissionValue)
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.adventure$pointers;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import com.google.common.base.Preconditions;
|
|||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
import net.minecraft.core.RegistryAccess;
|
||||||
import net.minecraft.util.ProblemReporter;
|
import net.minecraft.util.ProblemReporter;
|
||||||
import net.minecraft.util.RandomSource;
|
import net.minecraft.util.RandomSource;
|
||||||
import net.minecraft.util.random.WeightedList;
|
import net.minecraft.util.random.WeightedList;
|
||||||
@ -186,6 +187,11 @@ public class CraftMinecartMobSpawner extends CraftMinecart implements SpawnerMin
|
|||||||
return this.getHandle().level();
|
return this.getHandle().level();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RegistryAccess getRegistryAccess() {
|
||||||
|
return this.getHandle().registryAccess();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public net.minecraft.core.BlockPos getInternalPosition() {
|
public net.minecraft.core.BlockPos getInternalPosition() {
|
||||||
return this.getHandle().blockPosition();
|
return this.getHandle().blockPosition();
|
||||||
|
|||||||
@ -44,6 +44,8 @@ import java.util.concurrent.CompletableFuture;
|
|||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
import net.kyori.adventure.identity.Identity;
|
||||||
|
import net.kyori.adventure.pointer.PointersSupplier;
|
||||||
import net.kyori.adventure.util.TriState;
|
import net.kyori.adventure.util.TriState;
|
||||||
import net.md_5.bungee.api.chat.BaseComponent;
|
import net.md_5.bungee.api.chat.BaseComponent;
|
||||||
import net.minecraft.advancements.AdvancementProgress;
|
import net.minecraft.advancements.AdvancementProgress;
|
||||||
@ -213,6 +215,12 @@ import org.jspecify.annotations.Nullable;
|
|||||||
|
|
||||||
@DelegateDeserialization(CraftOfflinePlayer.class)
|
@DelegateDeserialization(CraftOfflinePlayer.class)
|
||||||
public class CraftPlayer extends CraftHumanEntity implements Player {
|
public class CraftPlayer extends CraftHumanEntity implements Player {
|
||||||
|
private static final PointersSupplier<Player> POINTERS_SUPPLIER = PointersSupplier.<Player>builder()
|
||||||
|
.parent(CraftEntity.POINTERS_SUPPLIER)
|
||||||
|
.resolving(Identity.NAME, Player::getName)
|
||||||
|
.resolving(Identity.DISPLAY_NAME, Player::displayName)
|
||||||
|
.resolving(Identity.LOCALE, Player::locale)
|
||||||
|
.build();
|
||||||
|
|
||||||
private long firstPlayed = 0;
|
private long firstPlayed = 0;
|
||||||
private long lastPlayed = 0;
|
private long lastPlayed = 0;
|
||||||
@ -3283,17 +3291,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public net.kyori.adventure.pointer.Pointers pointers() {
|
public net.kyori.adventure.pointer.Pointers pointers() {
|
||||||
if (this.adventure$pointers == null) {
|
return POINTERS_SUPPLIER.view(this);
|
||||||
this.adventure$pointers = net.kyori.adventure.pointer.Pointers.builder()
|
|
||||||
.withDynamic(net.kyori.adventure.identity.Identity.DISPLAY_NAME, this::displayName)
|
|
||||||
.withDynamic(net.kyori.adventure.identity.Identity.NAME, this::getName)
|
|
||||||
.withDynamic(net.kyori.adventure.identity.Identity.UUID, this::getUniqueId)
|
|
||||||
.withStatic(net.kyori.adventure.permission.PermissionChecker.POINTER, this::permissionValue)
|
|
||||||
.withDynamic(net.kyori.adventure.identity.Identity.LOCALE, this::locale)
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.adventure$pointers;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -185,11 +185,6 @@ public class CraftItemType<M extends ItemMeta> extends HolderableBase<Item> impl
|
|||||||
return expectedItem.isEmpty() ? null : CraftItemType.minecraftToBukkitNew(expectedItem.getItem());
|
return expectedItem.isEmpty() ? null : CraftItemType.minecraftToBukkitNew(expectedItem.getItem());
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Override
|
|
||||||
// public EquipmentSlot getEquipmentSlot() {
|
|
||||||
// return CraftEquipmentSlot.getSlot(EntityInsentient.getEquipmentSlotForItem(CraftItemStack.asNMSCopy(ItemStack.of(this))));
|
|
||||||
// }
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Multimap<Attribute, AttributeModifier> getDefaultAttributeModifiers() {
|
public Multimap<Attribute, AttributeModifier> getDefaultAttributeModifiers() {
|
||||||
return this.getDefaultAttributeModifiers(sg -> true);
|
return this.getDefaultAttributeModifiers(sg -> true);
|
||||||
|
|||||||
@ -34,6 +34,8 @@ public interface PaperSharedSpawnerLogic extends Spawner {
|
|||||||
|
|
||||||
Level getInternalWorld();
|
Level getInternalWorld();
|
||||||
|
|
||||||
|
RegistryAccess getRegistryAccess();
|
||||||
|
|
||||||
BlockPos getInternalPosition();
|
BlockPos getInternalPosition();
|
||||||
default boolean isActivated() {
|
default boolean isActivated() {
|
||||||
return this.getSpawner().isNearPlayer(this.getInternalWorld(), this.getInternalPosition());
|
return this.getSpawner().isNearPlayer(this.getInternalWorld(), this.getInternalPosition());
|
||||||
|
|||||||
@ -11,11 +11,14 @@ import java.lang.annotation.ElementType;
|
|||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
import java.lang.annotation.Target;
|
import java.lang.annotation.Target;
|
||||||
|
import java.net.URI;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
import net.kyori.adventure.key.Key;
|
import net.kyori.adventure.key.Key;
|
||||||
|
import net.kyori.adventure.nbt.api.BinaryTagHolder;
|
||||||
import net.kyori.adventure.text.BlockNBTComponent;
|
import net.kyori.adventure.text.BlockNBTComponent;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import net.kyori.adventure.text.event.ClickEvent;
|
import net.kyori.adventure.text.event.ClickEvent;
|
||||||
@ -106,23 +109,35 @@ class AdventureCodecsTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@ParameterizedTest(name = PARAMETERIZED_NAME)
|
@ParameterizedTest(name = PARAMETERIZED_NAME)
|
||||||
@EnumSource(value = ClickEvent.Action.class, mode = EnumSource.Mode.EXCLUDE, names = {"OPEN_FILE"})
|
@EnumSource(value = ClickEvent.Action.class, mode = EnumSource.Mode.EXCLUDE, names = {"OPEN_FILE", "SHOW_DIALOG", "CUSTOM"})
|
||||||
void testClickEvent(final ClickEvent.Action action) {
|
void testClickEvent(final ClickEvent.Action action) {
|
||||||
final ClickEvent event = ClickEvent.clickEvent(action, action.name().equals("OPEN_URL") ? "https://google.com" : "1337");
|
final ClickEvent event = switch (action) {
|
||||||
final Tag result = CLICK_EVENT_CODEC.encodeStart(NbtOps.INSTANCE, event).result().orElseThrow();
|
case OPEN_URL -> openUrl("https://google.com");
|
||||||
|
case RUN_COMMAND -> ClickEvent.runCommand("/say hello");
|
||||||
|
case SUGGEST_COMMAND -> suggestCommand("/suggest hello");
|
||||||
|
case CHANGE_PAGE -> ClickEvent.changePage(2);
|
||||||
|
case COPY_TO_CLIPBOARD -> ClickEvent.copyToClipboard("clipboard content");
|
||||||
|
case CUSTOM -> ClickEvent.custom(key("test"), BinaryTagHolder.binaryTagHolder("3"));
|
||||||
|
case SHOW_DIALOG, OPEN_FILE -> throw new IllegalArgumentException();
|
||||||
|
};
|
||||||
|
final Tag result = CLICK_EVENT_CODEC.encodeStart(NbtOps.INSTANCE, event).result().orElseThrow(() -> new RuntimeException("Failed to encode ClickEvent: " + event));
|
||||||
final net.minecraft.network.chat.ClickEvent nms = net.minecraft.network.chat.ClickEvent.CODEC.decode(NbtOps.INSTANCE, result).result().orElseThrow().getFirst();
|
final net.minecraft.network.chat.ClickEvent nms = net.minecraft.network.chat.ClickEvent.CODEC.decode(NbtOps.INSTANCE, result).result().orElseThrow().getFirst();
|
||||||
assertEquals(event.action().toString(), nms.action().getSerializedName());
|
assertEquals(event.action().toString(), nms.action().getSerializedName());
|
||||||
switch (nms) {
|
switch (nms) {
|
||||||
case net.minecraft.network.chat.ClickEvent.OpenUrl(java.net.URI uri) ->
|
case net.minecraft.network.chat.ClickEvent.OpenUrl(URI uri) ->
|
||||||
assertEquals(event.value(), uri.toString());
|
assertEquals(((ClickEvent.Payload.Text) event.payload()).value(), uri.toString());
|
||||||
case net.minecraft.network.chat.ClickEvent.SuggestCommand(String command) ->
|
case net.minecraft.network.chat.ClickEvent.SuggestCommand(String command) ->
|
||||||
assertEquals(event.value(), command);
|
assertEquals(((ClickEvent.Payload.Text) event.payload()).value(), command);
|
||||||
case net.minecraft.network.chat.ClickEvent.RunCommand(String command) ->
|
case net.minecraft.network.chat.ClickEvent.RunCommand(String command) ->
|
||||||
assertEquals(event.value(), command);
|
assertEquals(((ClickEvent.Payload.Text) event.payload()).value(), command);
|
||||||
case net.minecraft.network.chat.ClickEvent.CopyToClipboard(String value) ->
|
case net.minecraft.network.chat.ClickEvent.CopyToClipboard(String value) ->
|
||||||
assertEquals(event.value(), value);
|
assertEquals(((ClickEvent.Payload.Text) event.payload()).value(), value);
|
||||||
case net.minecraft.network.chat.ClickEvent.ChangePage(int page) ->
|
case net.minecraft.network.chat.ClickEvent.ChangePage(int page) ->
|
||||||
assertEquals(event.value(), String.valueOf(page));
|
assertEquals(((ClickEvent.Payload.Int) event.payload()).integer(), page);
|
||||||
|
case net.minecraft.network.chat.ClickEvent.Custom(ResourceLocation id, Optional<Tag> payload) -> {
|
||||||
|
assertEquals(((ClickEvent.Payload.Custom) event.payload()).key().toString(), id.toString());
|
||||||
|
assertEquals(((ClickEvent.Payload.Custom) event.payload()).nbt(), payload.orElseThrow().asString());
|
||||||
|
}
|
||||||
default -> throw new AssertionError("Unexpected ClickEvent type: " + nms.getClass());
|
default -> throw new AssertionError("Unexpected ClickEvent type: " + nms.getClass());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -294,10 +309,10 @@ class AdventureCodecsTest {
|
|||||||
.clickEvent(openUrl("https://github.com"))
|
.clickEvent(openUrl("https://github.com"))
|
||||||
.build(),
|
.build(),
|
||||||
style()
|
style()
|
||||||
.hoverEvent(HoverEvent.showEntity(HoverEvent.ShowEntity.showEntity(
|
.hoverEvent(showEntity(HoverEvent.ShowEntity.showEntity(
|
||||||
Key.key(Key.MINECRAFT_NAMESPACE, "pig"),
|
key(Key.MINECRAFT_NAMESPACE, "pig"),
|
||||||
UUID.randomUUID(),
|
UUID.randomUUID(),
|
||||||
Component.text("Dolores", TextColor.color(0x0a1ab9))
|
text("Dolores", color(0x0a1ab9))
|
||||||
)))
|
)))
|
||||||
.build()
|
.build()
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user