Merge pull request 'Merge Latest Changes' (#2) from update into main
Some checks failed
Build Paper / build (21) (push) Has been cancelled
Build Paper / Event File (push) Has been cancelled

Reviewed-on: https://steamwar.de/devlabs/SteamWar/Paper/pulls/2
This commit is contained in:
Lixfel
2025-01-01 12:39:18 +01:00
172 changed files with 2994 additions and 1313 deletions

View File

@ -31,6 +31,11 @@ ij_java_generate_final_locals = true
ij_java_generate_final_parameters = true ij_java_generate_final_parameters = true
ij_java_method_parameters_new_line_after_left_paren = true ij_java_method_parameters_new_line_after_left_paren = true
ij_java_method_parameters_right_paren_on_new_line = true ij_java_method_parameters_right_paren_on_new_line = true
ij_java_use_fq_class_names = false
ij_java_class_names_in_javadoc = 1
[paper-server/src/minecraft/java/**/*.java]
ij_java_use_fq_class_names = true
[paper-server/src/minecraft/resources/data/**/*.json] [paper-server/src/minecraft/resources/data/**/*.json]
indent_size = 2 indent_size = 2

View File

@ -16,8 +16,17 @@ on:
jobs: jobs:
build: build:
# Run on all label events (won't be duplicated) or all push events or on PR syncs not from the same repo # The goal of the build workflow is split into multiple requirements.
if: (github.event_name == 'pull_request' && github.event.action == 'labeled' && github.event.label.name == 'build-pr-jar') || github.event_name != 'pull_request' || github.repository != github.event.pull_request.head.repo.full_name # 1. Run on pushes to same repo.
# 2. Run on PR open/reopen/syncs from repos that are not the same (PRs from the same repo are covered by 1)
# 3. Run on labeled PRs that have the build-pr-jar flag.
if: >
(
(github.event_name == 'push')
|| (github.event_name == 'pull_request' && github.repository != github.event.pull_request.head.repo.full_name && contains(fromJSON('["opened", "reopened", "synchronize"]'), github.event.action))
|| (github.event_name == 'pull_request' && github.event.action == 'labeled' && github.event.label.name == 'build-pr-jar')
)
runs-on: ubuntu-latest runs-on: ubuntu-latest
strategy: strategy:
matrix: matrix:

View File

@ -1,4 +1,4 @@
tiny 2 0 spigot mojang+yarn tiny 2 0 spigot mojang
# Originally DistanceManager, which also implements DistanceManager, so clashes since the implemented class # Originally DistanceManager, which also implements DistanceManager, so clashes since the implemented class
# is imported and not fully qualified. Easiest fix is to just change the name # is imported and not fully qualified. Easiest fix is to just change the name

View File

@ -110,6 +110,8 @@ public net.minecraft.server.network.ServerLoginPacketListenerImpl connection
public net.minecraft.server.network.ServerLoginPacketListenerImpl state public net.minecraft.server.network.ServerLoginPacketListenerImpl state
public net.minecraft.server.network.ServerLoginPacketListenerImpl$State public net.minecraft.server.network.ServerLoginPacketListenerImpl$State
public net.minecraft.server.packs.VanillaPackResourcesBuilder safeGetPath(Ljava/net/URI;)Ljava/nio/file/Path; public net.minecraft.server.packs.VanillaPackResourcesBuilder safeGetPath(Ljava/net/URI;)Ljava/nio/file/Path;
public net.minecraft.server.packs.repository.FolderRepositorySource$FolderPackDetector
public net.minecraft.server.packs.repository.FolderRepositorySource$FolderPackDetector <init>(Lnet/minecraft/world/level/validation/DirectoryValidator;)V
public net.minecraft.server.packs.repository.Pack resources public net.minecraft.server.packs.repository.Pack resources
public net.minecraft.server.players.PlayerList playerIo public net.minecraft.server.players.PlayerList playerIo
public net.minecraft.server.players.PlayerList players public net.minecraft.server.players.PlayerList players

View File

@ -10,7 +10,7 @@
# a significant amount of time for us to track down every possible issue, so this file will likely be around and in # a significant amount of time for us to track down every possible issue, so this file will likely be around and in
# use - at least in some capacity - for a long time. # use - at least in some capacity - for a long time.
tiny 2 0 mojang+yarn spigot tiny 2 0 mojang spigot
# CraftBukkit changes type # CraftBukkit changes type
c net/minecraft/server/level/ServerLevel net/minecraft/server/level/WorldServer c net/minecraft/server/level/ServerLevel net/minecraft/server/level/WorldServer

View File

@ -12,7 +12,7 @@ import java.nio.file.Path
import kotlin.random.Random import kotlin.random.Random
plugins { plugins {
id("io.papermc.paperweight.core") version "2.0.0-beta.8" apply false id("io.papermc.paperweight.core") version "2.0.0-beta.10" apply false
} }
subprojects { subprojects {

View File

@ -16,7 +16,7 @@ dependencies {
implementation("com.squareup:javapoet:1.13.0") implementation("com.squareup:javapoet:1.13.0")
implementation(project(":paper-api")) implementation(project(":paper-api"))
implementation("io.github.classgraph:classgraph:4.8.47") implementation("io.github.classgraph:classgraph:4.8.47")
implementation("org.jetbrains:annotations:24.1.0") implementation("org.jetbrains:annotations:26.0.1")
testImplementation("org.junit.jupiter:junit-jupiter:5.10.2") testImplementation("org.junit.jupiter:junit-jupiter:5.10.2")
testRuntimeOnly("org.junit.platform:junit-platform-launcher") testRuntimeOnly("org.junit.platform:junit-platform-launcher")
} }

View File

@ -0,0 +1,288 @@
package io.papermc.paper.registry.keys.tags;
import static net.kyori.adventure.key.Key.key;
import io.papermc.paper.generated.GeneratedFrom;
import io.papermc.paper.registry.RegistryKey;
import io.papermc.paper.registry.tag.TagKey;
import net.kyori.adventure.key.Key;
import org.bukkit.entity.EntityType;
import org.jetbrains.annotations.ApiStatus;
import org.jspecify.annotations.NullMarked;
/**
* Vanilla keys for {@link RegistryKey#ENTITY_TYPE}.
*
* @apiNote The fields provided here are a direct representation of
* what is available from the vanilla game source. They may be
* changed (including removals) on any Minecraft version
* bump, so cross-version compatibility is not provided on the
* same level as it is on most of the other API.
*/
@SuppressWarnings({
"unused",
"SpellCheckingInspection"
})
@GeneratedFrom("1.21.4")
@NullMarked
@ApiStatus.Experimental
public final class EntityTypeTagKeys {
/**
* {@code #minecraft:aquatic}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TagKey<EntityType> AQUATIC = create(key("aquatic"));
/**
* {@code #minecraft:arrows}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TagKey<EntityType> ARROWS = create(key("arrows"));
/**
* {@code #minecraft:arthropod}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TagKey<EntityType> ARTHROPOD = create(key("arthropod"));
/**
* {@code #minecraft:axolotl_always_hostiles}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TagKey<EntityType> AXOLOTL_ALWAYS_HOSTILES = create(key("axolotl_always_hostiles"));
/**
* {@code #minecraft:axolotl_hunt_targets}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TagKey<EntityType> AXOLOTL_HUNT_TARGETS = create(key("axolotl_hunt_targets"));
/**
* {@code #minecraft:beehive_inhabitors}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TagKey<EntityType> BEEHIVE_INHABITORS = create(key("beehive_inhabitors"));
/**
* {@code #minecraft:boat}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TagKey<EntityType> BOAT = create(key("boat"));
/**
* {@code #minecraft:can_breathe_under_water}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TagKey<EntityType> CAN_BREATHE_UNDER_WATER = create(key("can_breathe_under_water"));
/**
* {@code #minecraft:can_turn_in_boats}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TagKey<EntityType> CAN_TURN_IN_BOATS = create(key("can_turn_in_boats"));
/**
* {@code #minecraft:deflects_projectiles}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TagKey<EntityType> DEFLECTS_PROJECTILES = create(key("deflects_projectiles"));
/**
* {@code #minecraft:dismounts_underwater}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TagKey<EntityType> DISMOUNTS_UNDERWATER = create(key("dismounts_underwater"));
/**
* {@code #minecraft:fall_damage_immune}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TagKey<EntityType> FALL_DAMAGE_IMMUNE = create(key("fall_damage_immune"));
/**
* {@code #minecraft:freeze_hurts_extra_types}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TagKey<EntityType> FREEZE_HURTS_EXTRA_TYPES = create(key("freeze_hurts_extra_types"));
/**
* {@code #minecraft:freeze_immune_entity_types}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TagKey<EntityType> FREEZE_IMMUNE_ENTITY_TYPES = create(key("freeze_immune_entity_types"));
/**
* {@code #minecraft:frog_food}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TagKey<EntityType> FROG_FOOD = create(key("frog_food"));
/**
* {@code #minecraft:ignores_poison_and_regen}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TagKey<EntityType> IGNORES_POISON_AND_REGEN = create(key("ignores_poison_and_regen"));
/**
* {@code #minecraft:illager}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TagKey<EntityType> ILLAGER = create(key("illager"));
/**
* {@code #minecraft:illager_friends}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TagKey<EntityType> ILLAGER_FRIENDS = create(key("illager_friends"));
/**
* {@code #minecraft:immune_to_infested}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TagKey<EntityType> IMMUNE_TO_INFESTED = create(key("immune_to_infested"));
/**
* {@code #minecraft:immune_to_oozing}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TagKey<EntityType> IMMUNE_TO_OOZING = create(key("immune_to_oozing"));
/**
* {@code #minecraft:impact_projectiles}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TagKey<EntityType> IMPACT_PROJECTILES = create(key("impact_projectiles"));
/**
* {@code #minecraft:inverted_healing_and_harm}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TagKey<EntityType> INVERTED_HEALING_AND_HARM = create(key("inverted_healing_and_harm"));
/**
* {@code #minecraft:no_anger_from_wind_charge}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TagKey<EntityType> NO_ANGER_FROM_WIND_CHARGE = create(key("no_anger_from_wind_charge"));
/**
* {@code #minecraft:non_controlling_rider}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TagKey<EntityType> NON_CONTROLLING_RIDER = create(key("non_controlling_rider"));
/**
* {@code #minecraft:not_scary_for_pufferfish}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TagKey<EntityType> NOT_SCARY_FOR_PUFFERFISH = create(key("not_scary_for_pufferfish"));
/**
* {@code #minecraft:powder_snow_walkable_mobs}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TagKey<EntityType> POWDER_SNOW_WALKABLE_MOBS = create(key("powder_snow_walkable_mobs"));
/**
* {@code #minecraft:raiders}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TagKey<EntityType> RAIDERS = create(key("raiders"));
/**
* {@code #minecraft:redirectable_projectile}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TagKey<EntityType> REDIRECTABLE_PROJECTILE = create(key("redirectable_projectile"));
/**
* {@code #minecraft:sensitive_to_bane_of_arthropods}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TagKey<EntityType> SENSITIVE_TO_BANE_OF_ARTHROPODS = create(key("sensitive_to_bane_of_arthropods"));
/**
* {@code #minecraft:sensitive_to_impaling}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TagKey<EntityType> SENSITIVE_TO_IMPALING = create(key("sensitive_to_impaling"));
/**
* {@code #minecraft:sensitive_to_smite}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TagKey<EntityType> SENSITIVE_TO_SMITE = create(key("sensitive_to_smite"));
/**
* {@code #minecraft:skeletons}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TagKey<EntityType> SKELETONS = create(key("skeletons"));
/**
* {@code #minecraft:undead}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TagKey<EntityType> UNDEAD = create(key("undead"));
/**
* {@code #minecraft:wither_friends}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TagKey<EntityType> WITHER_FRIENDS = create(key("wither_friends"));
/**
* {@code #minecraft:zombies}
*
* @apiNote This field is version-dependant and may be removed in future Minecraft versions
*/
public static final TagKey<EntityType> ZOMBIES = create(key("zombies"));
private EntityTypeTagKeys() {
}
/**
* Creates a tag key for {@link EntityType} in the registry {@code minecraft:entity_type}.
*
* @param key the tag key's key
* @return a new tag key
*/
@ApiStatus.Experimental
public static TagKey<EntityType> create(final Key key) {
return TagKey.create(RegistryKey.ENTITY_TYPE, key);
}
}

View File

@ -21,6 +21,7 @@ import org.bukkit.block.banner.PatternType;
import org.bukkit.damage.DamageType; import org.bukkit.damage.DamageType;
import org.bukkit.enchantments.Enchantment; import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.Cat; import org.bukkit.entity.Cat;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Frog; import org.bukkit.entity.Frog;
import org.bukkit.entity.Villager; import org.bukkit.entity.Villager;
import org.bukkit.entity.Wolf; import org.bukkit.entity.Wolf;
@ -79,6 +80,9 @@ public interface Generators {
simpleTagKey("BannerPatternTagKeys", PatternType.class, Registries.BANNER_PATTERN, RegistryKey.BANNER_PATTERN), simpleTagKey("BannerPatternTagKeys", PatternType.class, Registries.BANNER_PATTERN, RegistryKey.BANNER_PATTERN),
simpleTagKey("PaintingVariantTagKeys", Art.class, Registries.PAINTING_VARIANT, RegistryKey.PAINTING_VARIANT), simpleTagKey("PaintingVariantTagKeys", Art.class, Registries.PAINTING_VARIANT, RegistryKey.PAINTING_VARIANT),
simpleTagKey("InstrumentTagKeys", MusicInstrument.class, Registries.INSTRUMENT, RegistryKey.INSTRUMENT), simpleTagKey("InstrumentTagKeys", MusicInstrument.class, Registries.INSTRUMENT, RegistryKey.INSTRUMENT),
// api only
simpleTagKey("EntityTypeTagKeys", EntityType.class, Registries.ENTITY_TYPE, RegistryKey.ENTITY_TYPE),
new MobGoalGenerator("VanillaGoal", "com.destroystokyo.paper.entity.ai") new MobGoalGenerator("VanillaGoal", "com.destroystokyo.paper.entity.ai")
}; };

View File

@ -9,9 +9,9 @@ java {
withJavadocJar() withJavadocJar()
} }
val annotationsVersion = "24.1.0" val annotationsVersion = "26.0.1"
val bungeeCordChatVersion = "1.20-R0.2" val bungeeCordChatVersion = "1.20-R0.2"
val adventureVersion = "4.17.0" val adventureVersion = "4.18.0"
val slf4jVersion = "2.0.9" val slf4jVersion = "2.0.9"
val log4jVersion = "2.17.1" val log4jVersion = "2.17.1"
@ -68,9 +68,6 @@ dependencies {
apiAndDocs("net.kyori:adventure-text-serializer-plain") apiAndDocs("net.kyori:adventure-text-serializer-plain")
apiAndDocs("net.kyori:adventure-text-logger-slf4j") apiAndDocs("net.kyori:adventure-text-logger-slf4j")
implementation("org.ow2.asm:asm:9.7.1")
implementation("org.ow2.asm:asm-commons:9.7.1")
api("org.apache.maven:maven-resolver-provider:3.9.6") // make API dependency for Paper Plugins api("org.apache.maven:maven-resolver-provider:3.9.6") // make API dependency for Paper Plugins
compileOnly("org.apache.maven.resolver:maven-resolver-connector-basic:1.9.18") compileOnly("org.apache.maven.resolver:maven-resolver-connector-basic:1.9.18")
compileOnly("org.apache.maven.resolver:maven-resolver-transport-http:1.9.18") compileOnly("org.apache.maven.resolver:maven-resolver-transport-http:1.9.18")

View File

@ -1,54 +0,0 @@
package com.destroystokyo.paper.event.executor;
import com.destroystokyo.paper.util.SneakyThrow;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.reflect.Method;
import org.bukkit.event.Event;
import org.bukkit.event.EventException;
import org.bukkit.event.Listener;
import org.bukkit.plugin.EventExecutor;
import org.jetbrains.annotations.ApiStatus;
import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;
@ApiStatus.Internal
@NullMarked
public class MethodHandleEventExecutor implements EventExecutor {
private final Class<? extends Event> eventClass;
private final MethodHandle handle;
private final @Nullable Method method;
public MethodHandleEventExecutor(final Class<? extends Event> eventClass, final MethodHandle handle) {
this.eventClass = eventClass;
this.handle = handle;
this.method = null;
}
public MethodHandleEventExecutor(final Class<? extends Event> eventClass, final Method m) {
this.eventClass = eventClass;
try {
m.setAccessible(true);
this.handle = MethodHandles.lookup().unreflect(m);
} catch (final IllegalAccessException e) {
throw new AssertionError("Unable to set accessible", e);
}
this.method = m;
}
@Override
public void execute(final Listener listener, final Event event) throws EventException {
if (!this.eventClass.isInstance(event)) return;
try {
this.handle.invoke(listener, event);
} catch (final Throwable t) {
SneakyThrow.sneaky(t);
}
}
@Override
public String toString() {
return "MethodHandleEventExecutor['" + this.method + "']";
}
}

View File

@ -1,51 +0,0 @@
package com.destroystokyo.paper.event.executor;
import com.destroystokyo.paper.util.SneakyThrow;
import com.google.common.base.Preconditions;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import org.bukkit.event.Event;
import org.bukkit.event.EventException;
import org.bukkit.event.Listener;
import org.bukkit.plugin.EventExecutor;
import org.jetbrains.annotations.ApiStatus;
import org.jspecify.annotations.NullMarked;
@ApiStatus.Internal
@NullMarked
public class StaticMethodHandleEventExecutor implements EventExecutor {
private final Class<? extends Event> eventClass;
private final MethodHandle handle;
private final Method method;
public StaticMethodHandleEventExecutor(final Class<? extends Event> eventClass, final Method m) {
Preconditions.checkArgument(Modifier.isStatic(m.getModifiers()), "Not a static method: %s", m);
Preconditions.checkArgument(eventClass != null, "eventClass is null");
this.eventClass = eventClass;
try {
m.setAccessible(true);
this.handle = MethodHandles.lookup().unreflect(m);
} catch (final IllegalAccessException e) {
throw new AssertionError("Unable to set accessible", e);
}
this.method = m;
}
@Override
public void execute(final Listener listener, final Event event) throws EventException {
if (!this.eventClass.isInstance(event)) return;
try {
this.handle.invoke(event);
} catch (final Throwable throwable) {
SneakyThrow.sneaky(throwable);
}
}
@Override
public String toString() {
return "StaticMethodHandleEventExecutor['" + this.method + "']";
}
}

View File

@ -1,59 +0,0 @@
package com.destroystokyo.paper.event.executor.asm;
import java.lang.reflect.Method;
import java.util.concurrent.atomic.AtomicInteger;
import org.bukkit.plugin.EventExecutor;
import org.jetbrains.annotations.ApiStatus;
import org.jspecify.annotations.NullMarked;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.GeneratorAdapter;
import static org.objectweb.asm.Opcodes.ACC_PUBLIC;
import static org.objectweb.asm.Opcodes.INVOKEINTERFACE;
import static org.objectweb.asm.Opcodes.INVOKESPECIAL;
import static org.objectweb.asm.Opcodes.INVOKEVIRTUAL;
import static org.objectweb.asm.Opcodes.V1_8;
@ApiStatus.Internal
@NullMarked
public final class ASMEventExecutorGenerator {
private static final String EXECUTE_DESCRIPTOR = "(Lorg/bukkit/event/Listener;Lorg/bukkit/event/Event;)V";
public static byte[] generateEventExecutor(final Method m, final String name) {
final ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
writer.visit(V1_8, ACC_PUBLIC, name.replace('.', '/'), null, Type.getInternalName(Object.class), new String[]{Type.getInternalName(EventExecutor.class)});
// Generate constructor
GeneratorAdapter methodGenerator = new GeneratorAdapter(writer.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null), ACC_PUBLIC, "<init>", "()V");
methodGenerator.loadThis();
methodGenerator.visitMethodInsn(INVOKESPECIAL, Type.getInternalName(Object.class), "<init>", "()V", false); // Invoke the super class (Object) constructor
methodGenerator.returnValue();
methodGenerator.endMethod();
// Generate the execute method
methodGenerator = new GeneratorAdapter(writer.visitMethod(ACC_PUBLIC, "execute", EXECUTE_DESCRIPTOR, null, null), ACC_PUBLIC, "execute", EXECUTE_DESCRIPTOR);
methodGenerator.loadArg(0);
methodGenerator.checkCast(Type.getType(m.getDeclaringClass()));
methodGenerator.loadArg(1);
methodGenerator.checkCast(Type.getType(m.getParameterTypes()[0]));
methodGenerator.visitMethodInsn(m.getDeclaringClass().isInterface() ? INVOKEINTERFACE : INVOKEVIRTUAL, Type.getInternalName(m.getDeclaringClass()), m.getName(), Type.getMethodDescriptor(m), m.getDeclaringClass().isInterface());
// The only purpose of this switch statement is to generate the correct pop instruction, should the event handler method return something other than void.
// Non-void event handlers will be unsupported in a future release.
switch (Type.getType(m.getReturnType()).getSize()) {
// case 0 is omitted because the only type that has size 0 is void - no pop instruction needed.
case 1 -> methodGenerator.pop(); // handles reference types and most primitives
case 2 -> methodGenerator.pop2(); // handles long and double
}
methodGenerator.returnValue();
methodGenerator.endMethod();
writer.visitEnd();
return writer.toByteArray();
}
public static AtomicInteger NEXT_ID = new AtomicInteger(1);
public static String generateName() {
final int id = NEXT_ID.getAndIncrement();
return "com.destroystokyo.paper.event.executor.asm.generated.GeneratedEventExecutor" + id;
}
}

View File

@ -1,35 +0,0 @@
package com.destroystokyo.paper.event.executor.asm;
import org.jetbrains.annotations.ApiStatus;
import org.jspecify.annotations.NullMarked;
@ApiStatus.Internal
@NullMarked
public interface ClassDefiner {
/**
* Returns if the defined classes can bypass access checks
*
* @return if classes bypass access checks
*/
default boolean isBypassAccessChecks() {
return false;
}
/**
* Define a class
*
* @param parentLoader the parent classloader
* @param name the name of the class
* @param data the class data to load
* @return the defined class
* @throws ClassFormatError if the class data is invalid
* @throws NullPointerException if any of the arguments are null
*/
Class<?> defineClass(ClassLoader parentLoader, String name, byte[] data);
static ClassDefiner getInstance() {
return SafeClassDefiner.INSTANCE;
}
}

View File

@ -1,66 +0,0 @@
package com.destroystokyo.paper.event.executor.asm;
import com.google.common.base.Preconditions;
import com.google.common.collect.MapMaker;
import java.util.concurrent.ConcurrentMap;
import org.jetbrains.annotations.ApiStatus;
import org.jspecify.annotations.NullMarked;
@ApiStatus.Internal
@NullMarked
public class SafeClassDefiner implements ClassDefiner {
/* default */ static final SafeClassDefiner INSTANCE = new SafeClassDefiner();
private SafeClassDefiner() {
}
private final ConcurrentMap<ClassLoader, GeneratedClassLoader> loaders = new MapMaker().weakKeys().makeMap();
@Override
public Class<?> defineClass(final ClassLoader parentLoader, final String name, final byte[] data) {
final GeneratedClassLoader loader = this.loaders.computeIfAbsent(parentLoader, GeneratedClassLoader::new);
synchronized (loader.getClassLoadingLock(name)) {
Preconditions.checkState(!loader.hasClass(name), "%s already defined", name);
final Class<?> c = loader.define(name, data);
assert c.getName().equals(name);
return c;
}
}
private static class GeneratedClassLoader extends ClassLoader {
static {
ClassLoader.registerAsParallelCapable();
}
protected GeneratedClassLoader(final ClassLoader parent) {
super(parent);
}
private Class<?> define(final String name, final byte[] data) {
synchronized (this.getClassLoadingLock(name)) {
assert !this.hasClass(name);
final Class<?> c = this.defineClass(name, data, 0, data.length);
this.resolveClass(c);
return c;
}
}
@Override
public Object getClassLoadingLock(final String name) {
return super.getClassLoadingLock(name);
}
public boolean hasClass(final String name) {
synchronized (this.getClassLoadingLock(name)) {
try {
Class.forName(name);
return true;
} catch (final ClassNotFoundException e) {
return false;
}
}
}
}
}

View File

@ -304,8 +304,7 @@ public class PaperServerListPingEvent extends ServerListPingEvent implements Can
return new PlayerIterator(); return new PlayerIterator();
} }
@NotNull protected @NotNull Object @NotNull [] getOnlinePlayers() {
protected Object[] getOnlinePlayers() {
return Bukkit.getOnlinePlayers().toArray(); return Bukkit.getOnlinePlayers().toArray();
} }

View File

@ -0,0 +1,39 @@
package io.papermc.paper;
import net.kyori.adventure.util.Services;
import org.bukkit.damage.DamageEffect;
import org.jetbrains.annotations.ApiStatus;
import org.jspecify.annotations.NullMarked;
/**
* Static bridge to the server internals.
* <p>
* Any and all methods in here are *not* to be called by plugin developers, may change at any time and may generally
* cause issues when called under unexpected circumstances.
*/
@ApiStatus.Internal
@NullMarked
public interface InternalAPIBridge {
/**
* Yields the instance of this API bridge by lazily requesting it from the java service loader API.
*
* @return the instance.
*/
static InternalAPIBridge get() {
class Holder {
public static final InternalAPIBridge INSTANCE = Services.service(InternalAPIBridge.class).orElseThrow();
}
return Holder.INSTANCE;
}
/**
* Creates a damage effect instance for the passed key.
*
* @param key the string key.
* @return the damage effect.
*/
DamageEffect getDamageEffect(String key);
}

View File

@ -1,10 +1,8 @@
package io.papermc.paper.datapack; package io.papermc.paper.datapack;
import java.util.Set;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import org.bukkit.FeatureFlag; import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.Unmodifiable;
import org.jspecify.annotations.NullMarked; import org.jspecify.annotations.NullMarked;
/** /**
@ -12,50 +10,8 @@ import org.jspecify.annotations.NullMarked;
* won't be updated as datapacks are updated. * won't be updated as datapacks are updated.
*/ */
@NullMarked @NullMarked
public interface Datapack { @ApiStatus.NonExtendable
public interface Datapack extends DiscoveredDatapack {
/**
* Gets the name/id of this datapack.
*
* @return the name of the pack
*/
@Contract(pure = true)
String getName();
/**
* Gets the title component of this datapack.
*
* @return the title
*/
Component getTitle();
/**
* Gets the description component of this datapack.
*
* @return the description
*/
Component getDescription();
/**
* Gets if this datapack is required to be enabled.
*
* @return true if the pack is required
*/
boolean isRequired();
/**
* Gets the compatibility status of this pack.
*
* @return the compatibility of the pack
*/
Compatibility getCompatibility();
/**
* Gets the set of required features for this datapack.
*
* @return the set of required features
*/
@Unmodifiable Set<FeatureFlag> getRequiredFeatures();
/** /**
* Gets the enabled state of this pack. * Gets the enabled state of this pack.
@ -74,13 +30,6 @@ public interface Datapack {
*/ */
void setEnabled(boolean enabled); void setEnabled(boolean enabled);
/**
* Gets the source for this datapack.
*
* @return the pack source
*/
DatapackSource getSource();
/** /**
* Computes the component vanilla Minecraft uses * Computes the component vanilla Minecraft uses
* to display this datapack. Includes the {@link #getSource()}, * to display this datapack. Includes the {@link #getSource()},
@ -96,4 +45,11 @@ public interface Datapack {
TOO_NEW, TOO_NEW,
COMPATIBLE, COMPATIBLE,
} }
/**
* Position of the pack in the load order.
*/
enum Position {
TOP, BOTTOM
}
} }

View File

@ -0,0 +1,202 @@
package io.papermc.paper.datapack;
import io.papermc.paper.plugin.configuration.PluginMeta;
import io.papermc.paper.plugin.lifecycle.event.registrar.Registrar;
import java.io.IOException;
import java.net.URI;
import java.nio.file.Path;
import java.util.Map;
import java.util.function.Consumer;
import net.kyori.adventure.text.Component;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.Unmodifiable;
import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;
/**
* The registrar for datapacks. The event for this registrar
* is called anytime the game tries to discover datapacks at any of the
* configured locations. This means that if a datapack should stay available to the server,
* it must always be discovered whenever this event fires.
* <p>An example of a plugin loading a datapack from within it's own jar is below</p>
* <pre>{@code
* public class YourPluginBootstrap implements PluginBootstrap {
* @Override
* public void bootstrap(BoostrapContext context) {
* final LifecycleEventManager<BootstrapContext> manager = context.getLifecycleManager();
* manager.registerEventHandler(LifecycleEvents.DATAPACK_DISCOVERY, event -> {
* DatapackRegistrar registrar = event.registrar();
* try {
* final URI uri = Objects.requireNonNull(
* YourPluginBootstrap.class.getResource("/pack")
* ).toURI();
* registrar.discoverPack(uri, "packId");
* } catch (final URISyntaxException | IOException e) {
* throw new RuntimeException(e);
* }
* });
* }
* }
* }</pre>
* @see io.papermc.paper.plugin.lifecycle.event.types.LifecycleEvents#DATAPACK_DISCOVERY
*/
@ApiStatus.NonExtendable
@ApiStatus.Experimental
@NullMarked
public interface DatapackRegistrar extends Registrar {
/**
* Checks if a datapack with the specified name has been discovered.
*
* @param name the name of the pack
* @return true if the pack has been discovered
* @see Datapack#getName()
*/
@Contract(pure = true)
boolean hasPackDiscovered(String name);
/**
* Gets a discovered datapack by its name.
*
* @param name the name of the pack
* @return the datapack
* @throws java.util.NoSuchElementException if the pack is not discovered
* @see Datapack#getName()
*/
@Contract(pure = true)
DiscoveredDatapack getDiscoveredPack(String name);
/**
* Removes a discovered datapack by its name.
*
* @param name the name of the pack
* @return true if the pack was removed
* @see Datapack#getName()
*/
@Contract(mutates = "this")
boolean removeDiscoveredPack(String name);
/**
* Gets all discovered datapacks.
*
* @return an unmodifiable map of discovered packs
*/
@Contract(pure = true)
@Unmodifiable Map<String, DiscoveredDatapack> getDiscoveredPacks();
/**
* Discovers a datapack at the specified {@link URI} with the id.
* <p>Symlinks obey the {@code allowed_symlinks.txt} in the server root directory.</p>
*
* @param uri the location of the pack
* @param id a unique id (will be combined with plugin for the datapacks name)
* @return the discovered datapack (or null if it failed)
* @throws IOException if any IO error occurs
*/
default @Nullable DiscoveredDatapack discoverPack(final URI uri, final String id) throws IOException {
return this.discoverPack(uri, id, c -> {});
}
/**
* Discovers a datapack at the specified {@link URI} with the id.
* <p>Symlinks obey the {@code allowed_symlinks.txt} in the server root directory.</p>
*
* @param uri the location of the pack
* @param id a unique id (will be combined with plugin for the datapacks name)
* @param configurer a configurer for extra options
* @return the discovered datapack (or null if it failed)
* @throws IOException if any IO error occurs
*/
@Nullable DiscoveredDatapack discoverPack(URI uri, String id, Consumer<Configurer> configurer) throws IOException;
/**
* Discovers a datapack at the specified {@link Path} with the id.
* <p>Symlinks obey the {@code allowed_symlinks.txt} in the server root directory.</p>
*
* @param path the location of the pack
* @param id a unique id (will be combined with plugin for the datapacks name)
* @return the discovered datapack (or null if it failed)
* @throws IOException if any IO error occurs
*/
default @Nullable DiscoveredDatapack discoverPack(final Path path, final String id) throws IOException {
return this.discoverPack(path, id, c -> {});
}
/**
* Discovers a datapack at the specified {@link Path} with the id.
* <p>Symlinks obey the {@code allowed_symlinks.txt} in the server root directory.</p>
*
* @param path the location of the pack
* @param id a unique id (will be combined with plugin for the datapacks name)
* @param configurer a configurer for extra options
* @return the discovered datapack (or null if it failed)
* @throws IOException if any IO error occurs
*/
@Nullable DiscoveredDatapack discoverPack(Path path, String id, Consumer<Configurer> configurer) throws IOException;
/**
* Discovers a datapack at the specified {@link URI} with the id.
* <p>Symlinks obey the {@code allowed_symlinks.txt} in the server root directory.</p>
*
* @param pluginMeta the plugin which will be the "owner" of this datapack
* @param uri the location of the pack
* @param id a unique id (will be combined with plugin for the datapacks name)
* @param configurer a configurer for extra options
* @return the discovered datapack (or null if it failed)
* @throws IOException if any IO error occurs
*/
@Nullable DiscoveredDatapack discoverPack(PluginMeta pluginMeta, URI uri, String id, Consumer<Configurer> configurer) throws IOException;
/**
* Discovers a datapack at the specified {@link Path} with the id.
* <p>Symlinks obey the {@code allowed_symlinks.txt} in the server root directory.</p>
*
* @param pluginMeta the plugin which will be the "owner" of this datapack
* @param path the location of the pack
* @param id a unique id (will be combined with plugin for the datapacks name)
* @param configurer a configurer for extra options
* @return the discovered datapack (or null if it failed)
* @throws IOException if any IO error occurs
*/
@Nullable DiscoveredDatapack discoverPack(PluginMeta pluginMeta, Path path, String id, Consumer<Configurer> configurer) throws IOException;
/**
* Configures additional, optional, details about a datapack.
*/
@ApiStatus.NonExtendable
@ApiStatus.Experimental
interface Configurer {
/**
* Changes the title of the datapack from the default which
* is just the "id" in the {@code registerPack} methods.
*
* @param title the new title
* @return the configurer for chaining
*/
@Contract(value = "_ -> this", mutates = "this")
Configurer title(Component title);
/**
* Sets whether this pack is going to be automatically enabled on server starts even if previously disabled.
* Defaults to false.
*
* @param autoEnableOnServerStart true to ensure the pack is enabled on server starts.
* @return the configurer for chaining
*/
@Contract(value = "_ -> this", mutates = "this")
Configurer autoEnableOnServerStart(boolean autoEnableOnServerStart);
/**
* Configures the position in the
* load order of this datapack.
*
* @param fixed won't move around in the load order as packs are added/removed
* @param position try to insert at the top of the order or bottom
* @return the configurer for chaining
*/
@Contract(value = "_, _ -> this", mutates = "this")
Configurer position(boolean fixed, Datapack.Position position);
}
}

View File

@ -13,6 +13,7 @@ public sealed interface DatapackSource permits DatapackSourceImpl {
DatapackSource FEATURE = create("feature"); DatapackSource FEATURE = create("feature");
DatapackSource WORLD = create("world"); DatapackSource WORLD = create("world");
DatapackSource SERVER = create("server"); DatapackSource SERVER = create("server");
DatapackSource PLUGIN = create("plugin");
private static DatapackSource create(final String name) { private static DatapackSource create(final String name) {
return new DatapackSourceImpl(name); return new DatapackSourceImpl(name);

View File

@ -0,0 +1,74 @@
package io.papermc.paper.datapack;
import java.util.Set;
import net.kyori.adventure.text.Component;
import org.bukkit.FeatureFlag;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.Unmodifiable;
import org.jspecify.annotations.NullMarked;
/**
* Represents a snapshot of a datapack that the server has found by
* searching available sources. It may or may not be enabled and isn't
* guaranteed to be available. This object won't be
* updated as datapacks are updated.
* @see DatapackRegistrar
*/
@NullMarked
@ApiStatus.NonExtendable
public interface DiscoveredDatapack {
/**
* Gets the name/id of this datapack.
*
* @return the name of the pack
*/
@Contract(pure = true)
String getName();
/**
* Gets the title component of this datapack.
*
* @return the title
*/
Component getTitle();
/**
* Gets the description component of this datapack.
*
* @return the description
*/
Component getDescription();
/**
* Gets if this datapack is required.
* <p>
* A "required" datapack will always be enabled on server startup, even if previously disabled.
*
* @return true if the pack is required
*/
boolean isRequired();
/**
* Gets the compatibility status of this pack.
*
* @return the compatibility of the pack
*/
Datapack.Compatibility getCompatibility();
/**
* Gets the set of required features for this datapack.
*
* @return the set of required features
*/
@Unmodifiable
Set<FeatureFlag> getRequiredFeatures();
/**
* Gets the source for this datapack.
*
* @return the pack source
*/
DatapackSource getSource();
}

View File

@ -0,0 +1,38 @@
package io.papermc.paper.entity;
import org.bukkit.UnsafeValues;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
/**
* Represents flags for entity serialization.
*
* @see UnsafeValues#serializeEntity(Entity, EntitySerializationFlag... serializationFlags)
* @since 1.21.4
*/
public enum EntitySerializationFlag {
/**
* Serialize entities that wouldn't be serialized normally
* (e.g. dead, despawned, non-persistent, etc.).
*
* @see Entity#isValid()
* @see Entity#isPersistent()
*/
FORCE,
/**
* Serialize misc non-saveable entities like lighting bolts, fishing bobbers, etc.
* <br>Note: players require a separate flag: {@link #PLAYER}.
*/
MISC,
/**
* Include passengers in the serialized data.
*/
PASSENGERS,
/**
* Allow serializing {@link Player}s.
* <p>Note: deserializing player data will always fail.
*/
PLAYER
}

View File

@ -0,0 +1,74 @@
package io.papermc.paper.event.executor;
import org.bukkit.event.Event;
import org.bukkit.event.Listener;
import org.bukkit.plugin.EventExecutor;
import org.jetbrains.annotations.ApiStatus;
import org.jspecify.annotations.NullMarked;
import java.io.IOException;
import java.io.InputStream;
import java.lang.constant.ConstantDescs;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.List;
import java.util.Objects;
@ApiStatus.Internal
@NullMarked
public final class EventExecutorFactory {
private static final byte[] TEMPLATE_CLASS_BYTES;
static {
try (final InputStream is = EventExecutorFactory.class.getResourceAsStream("MethodHandleEventExecutorTemplate.class")) {
TEMPLATE_CLASS_BYTES = Objects.requireNonNull(is, "template class is missing").readAllBytes();
} catch (IOException e) {
throw new AssertionError(e);
}
}
private EventExecutorFactory() {
}
/**
* {@return an {@link EventExecutor} implemented by a hidden class calling a method handle}
*
* @param method the method to be invoked by the created event executor
* @param eventClass the class of the event to handle
*/
public static EventExecutor create(final Method method, final Class<? extends Event> eventClass) {
final List<?> classData = List.of(method, eventClass);
try {
final MethodHandles.Lookup newClass = MethodHandles.lookup().defineHiddenClassWithClassData(TEMPLATE_CLASS_BYTES, classData, true);
return newClass.lookupClass().asSubclass(EventExecutor.class).getDeclaredConstructor().newInstance();
} catch (ReflectiveOperationException e) {
throw new AssertionError(e);
}
}
record ClassData(Method method, MethodHandle methodHandle, Class<? extends Event> eventClass) {
}
/**
* Extracts the class data and creates an adjusted MethodHandle directly usable by the lookup class.
* The logic is kept here to minimize memory usage per created class.
*/
static ClassData classData(final MethodHandles.Lookup lookup) {
try {
final Method method = MethodHandles.classDataAt(lookup, ConstantDescs.DEFAULT_NAME, Method.class, 0);
MethodHandle mh = lookup.unreflect(method);
if (Modifier.isStatic(method.getModifiers())) {
mh = MethodHandles.dropArguments(mh, 0, Listener.class);
}
mh = mh.asType(MethodType.methodType(void.class, Listener.class, Event.class));
final Class<?> eventClass = MethodHandles.classDataAt(lookup, ConstantDescs.DEFAULT_NAME, Class.class, 1);
return new ClassData(method, mh, eventClass.asSubclass(Event.class));
} catch (ReflectiveOperationException e) {
throw new AssertionError(e);
}
}
}

View File

@ -0,0 +1,56 @@
package io.papermc.paper.event.executor;
import com.destroystokyo.paper.util.SneakyThrow;
import org.bukkit.event.Event;
import org.bukkit.event.EventException;
import org.bukkit.event.Listener;
import org.bukkit.plugin.EventExecutor;
import org.jetbrains.annotations.ApiStatus;
import org.jspecify.annotations.NullMarked;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.reflect.Method;
/**
* This class is designed to be used as hidden class template.
* Initializing the class directly will fail due to missing {@code classData}.
* Instead, {@link java.lang.invoke.MethodHandles.Lookup#defineHiddenClassWithClassData(byte[], Object, boolean, MethodHandles.Lookup.ClassOption...)}
* must be used, with the {@code classData} object being a list consisting of two elements:
* <ol>
* <li>A {@link Method} representing the event handler method</li>
* <li>A {@link Class} representing the event type</li>
* </ol>
* The method must take {@link Event} or a subtype of it as its single parameter.
* If the method is non-static, it also needs to reside in a class implementing {@link Listener}.
*/
@SuppressWarnings("unused")
@ApiStatus.Internal
@NullMarked
class MethodHandleEventExecutorTemplate implements EventExecutor {
private static final Method METHOD;
private static final MethodHandle HANDLE;
private static final Class<? extends Event> EVENT_CLASS;
static {
final MethodHandles.Lookup lookup = MethodHandles.lookup();
final EventExecutorFactory.ClassData classData = EventExecutorFactory.classData(lookup);
METHOD = classData.method();
HANDLE = classData.methodHandle();
EVENT_CLASS = classData.eventClass();
}
@Override
public void execute(final Listener listener, final Event event) throws EventException {
if (!EVENT_CLASS.isInstance(event)) return;
try {
HANDLE.invokeExact(listener, event);
} catch (Throwable t) {
SneakyThrow.sneaky(t);
}
}
@Override
public String toString() {
return "MethodHandleEventExecutorTemplate['" + METHOD + "']";
}
}

View File

@ -1,10 +1,12 @@
package io.papermc.paper.plugin.lifecycle.event.types; package io.papermc.paper.plugin.lifecycle.event.types;
import io.papermc.paper.command.brigadier.Commands; import io.papermc.paper.command.brigadier.Commands;
import io.papermc.paper.datapack.DatapackRegistrar;
import io.papermc.paper.plugin.bootstrap.BootstrapContext; import io.papermc.paper.plugin.bootstrap.BootstrapContext;
import io.papermc.paper.plugin.lifecycle.event.LifecycleEvent; import io.papermc.paper.plugin.lifecycle.event.LifecycleEvent;
import io.papermc.paper.plugin.lifecycle.event.LifecycleEventManager; import io.papermc.paper.plugin.lifecycle.event.LifecycleEventManager;
import io.papermc.paper.plugin.lifecycle.event.LifecycleEventOwner; import io.papermc.paper.plugin.lifecycle.event.LifecycleEventOwner;
import io.papermc.paper.plugin.lifecycle.event.registrar.RegistrarEvent;
import io.papermc.paper.plugin.lifecycle.event.registrar.ReloadableRegistrarEvent; import io.papermc.paper.plugin.lifecycle.event.registrar.ReloadableRegistrarEvent;
import org.bukkit.plugin.Plugin; import org.bukkit.plugin.Plugin;
import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.ApiStatus;
@ -32,6 +34,14 @@ public final class LifecycleEvents {
*/ */
public static final TagEventTypeProvider TAGS = LifecycleEventTypeProvider.provider().tagProvider(); public static final TagEventTypeProvider TAGS = LifecycleEventTypeProvider.provider().tagProvider();
/**
* This event is for informing the server about any available datapacks from other sources such as inside a plugin's jar. You
* can register a handler for this event only in {@link io.papermc.paper.plugin.bootstrap.PluginBootstrap#bootstrap(BootstrapContext)}.
* @see DatapackRegistrar an example of a datapack being discovered
*/
public static final LifecycleEventType.Prioritizable<BootstrapContext, RegistrarEvent<DatapackRegistrar>> DATAPACK_DISCOVERY = bootstrapPrioritized("datapack_discovery");
//<editor-fold desc="helper methods" defaultstate="collapsed"> //<editor-fold desc="helper methods" defaultstate="collapsed">
@ApiStatus.Internal @ApiStatus.Internal
static <E extends LifecycleEvent> LifecycleEventType.Monitorable<Plugin, E> plugin(final String name) { static <E extends LifecycleEvent> LifecycleEventType.Monitorable<Plugin, E> plugin(final String name) {

View File

@ -0,0 +1,39 @@
package io.papermc.paper.registry;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Contract;
import org.jspecify.annotations.NullMarked;
/**
* A factory to create a {@link RegistryBuilder} for a given {@link TypedKey}. For
* each instance of this class, once either {@link #empty()} or {@link #copyFrom(TypedKey)}
* is called once, any future calls to either method will throw an {@link IllegalStateException}.
*
* @param <T> The type of the registry
* @param <B> The type of the registry builder
*/
@NullMarked
@ApiStatus.Experimental
@ApiStatus.NonExtendable
public interface RegistryBuilderFactory<T, B extends RegistryBuilder<T>> {
/**
* Creates a new empty {@link RegistryBuilder}.
*
* @return A new empty {@link RegistryBuilder}
* @throws IllegalStateException if this method or {@link #copyFrom(TypedKey)}) has already been called once
*/
@Contract("-> new")
B empty();
/**
* Creates a new {@link RegistryBuilder} with the same properties as the given {@link TypedKey}.
*
* @param key The key to copy properties from
* @return A new {@link RegistryBuilder} with the same properties as the given key
* @throws IllegalStateException if this method or {@link #empty()} has already been called once
* @throws IllegalArgumentException if key doesn't exist
*/
@Contract("_ -> new")
B copyFrom(TypedKey<T> key);
}

View File

@ -1,6 +1,8 @@
package io.papermc.paper.registry; package io.papermc.paper.registry;
import io.papermc.paper.datacomponent.DataComponentType; import io.papermc.paper.datacomponent.DataComponentType;
import net.kyori.adventure.key.Key;
import net.kyori.adventure.key.KeyPattern;
import net.kyori.adventure.key.Keyed; import net.kyori.adventure.key.Keyed;
import org.bukkit.Art; import org.bukkit.Art;
import org.bukkit.Fluid; import org.bukkit.Fluid;
@ -200,4 +202,26 @@ public sealed interface RegistryKey<T> extends Keyed permits RegistryKeyImpl {
RegistryKey<Particle> PARTICLE_TYPE = create("particle_type"); RegistryKey<Particle> PARTICLE_TYPE = create("particle_type");
RegistryKey<PotionType> POTION = create("potion"); RegistryKey<PotionType> POTION = create("potion");
RegistryKey<MemoryKey<?>> MEMORY_MODULE_TYPE = create("memory_module_type"); RegistryKey<MemoryKey<?>> MEMORY_MODULE_TYPE = create("memory_module_type");
/**
* Constructs a new {@link TypedKey} for this registry given the typed key's key.
*
* @param key the key of the typed key.
* @return the constructed typed key.
*/
@ApiStatus.Experimental
default TypedKey<T> typedKey(final Key key) {
return TypedKey.create(this, key);
}
/**
* Constructs a new {@link TypedKey} for this registry given the typed key's key.
*
* @param key the string representation of the key that will be passed to {@link Key#key(String)}.
* @return the constructed typed key.
*/
@ApiStatus.Experimental
default TypedKey<T> typedKey(final @KeyPattern String key) {
return TypedKey.create(this, key);
}
} }

View File

@ -1,6 +1,7 @@
package io.papermc.paper.registry; package io.papermc.paper.registry;
import net.kyori.adventure.key.Key; import net.kyori.adventure.key.Key;
import net.kyori.adventure.key.KeyPattern;
import net.kyori.adventure.key.Keyed; import net.kyori.adventure.key.Keyed;
import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.ApiStatus;
import org.jspecify.annotations.NullMarked; import org.jspecify.annotations.NullMarked;
@ -42,4 +43,18 @@ public sealed interface TypedKey<T> extends Key permits TypedKeyImpl {
static <T> TypedKey<T> create(final RegistryKey<T> registryKey, final Key key) { static <T> TypedKey<T> create(final RegistryKey<T> registryKey, final Key key) {
return new TypedKeyImpl<>(key, registryKey); return new TypedKeyImpl<>(key, registryKey);
} }
/**
* Create a typed key from a string and a registry key.
*
* @param registryKey the registry this key is for
* @param key the string version of a {@link Key} that will be passed to {@link Key#key(String)} for parsing.
* @param <T> value type
* @return a new key for the value key and registry key
* @see Key#key(String)
*/
@ApiStatus.Experimental
static <T> TypedKey<T> create(final RegistryKey<T> registryKey, final @KeyPattern String key) {
return create(registryKey, Key.key(key));
}
} }

View File

@ -0,0 +1,65 @@
package io.papermc.paper.registry.data;
import io.papermc.paper.registry.RegistryBuilder;
import net.kyori.adventure.key.Key;
import org.bukkit.block.banner.PatternType;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Contract;
/**
* A data-centric version-specific registry entry for the {@link PatternType} type.
*/
@ApiStatus.Experimental
@ApiStatus.NonExtendable
public interface BannerPatternRegistryEntry {
/**
* Provides the asset id of the pattern type, which is the location of the sprite to use.
*
* @return the asset id.
*/
Key assetId();
/**
* Provides the translation key for displaying the pattern inside the banner's tooltip.
*
* @return the translation key.
*/
String translationKey();
/**
* A mutable builder for the {@link BannerPatternRegistryEntry} plugins may change in applicable registry events.
* <p>
* The following values are required for each builder:
* <ul>
* <li>{@link #assetId(Key)}</li>
* <li>{@link #translationKey(String)}</li>
* </ul>
*/
@ApiStatus.Experimental
@ApiStatus.NonExtendable
interface Builder extends BannerPatternRegistryEntry, RegistryBuilder<PatternType> {
/**
* Sets the asset id of the pattern type, which is the location of the sprite to use.
*
* @param assetId the asset id.
* @return this builder instance.
* @see BannerPatternRegistryEntry#assetId()
*/
@Contract(value = "_ -> this", mutates = "this")
Builder assetId(Key assetId);
/**
* Sets the translation key for displaying the pattern inside the banner's tooltip.
*
* @param translationKey the translation key.
* @return this builder instance.
* @see BannerPatternRegistryEntry#translationKey()
*/
@Contract(value = "_ -> this", mutates = "this")
Builder translationKey(String translationKey);
}
}

View File

@ -0,0 +1,120 @@
package io.papermc.paper.registry.data;
import io.papermc.paper.registry.RegistryBuilder;
import org.bukkit.damage.DamageEffect;
import org.bukkit.damage.DamageScaling;
import org.bukkit.damage.DamageType;
import org.bukkit.damage.DeathMessageType;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Contract;
/**
* A data-centric version-specific registry entry for the {@link DamageType} type.
*/
@ApiStatus.Experimental
@ApiStatus.NonExtendable
public interface DamageTypeRegistryEntry {
/**
* Provides part of the death message translation key. (death.attack.&lt;message_id&gt;)
* <p>
* <strong>Note</strong> The translation key is only used if
* {@link #deathMessageType()} is {@link DeathMessageType#DEFAULT}
*
* @return part of the translation key
*/
String messageId();
/**
* Provides the amount of hunger exhaustion caused by this damage type.
*
* @return the exhaustion
*/
float exhaustion();
/**
* Provides the {@link DamageScaling} for this damage type.
*
* @return the damage scaling
*/
DamageScaling damageScaling();
/**
* Provides the {@link DamageEffect} for this damage type.
*
* @return the damage effect
*/
DamageEffect damageEffect();
/**
* Provides the {@link DeathMessageType} for this damage type.
*
* @return the death message type
*/
DeathMessageType deathMessageType();
/**
* A mutable builder for the {@link DamageTypeRegistryEntry} plugins may change in applicable registry events.
* <p>
* The following values are required for each builder:
* <ul>
* <li>{@link #messageId(String)}</li>
* <li>{@link #exhaustion(float)}</li>
* <li>{@link #damageScaling(DamageScaling)}</li>
* </ul>
*/
@ApiStatus.Experimental
@ApiStatus.NonExtendable
interface Builder extends DamageTypeRegistryEntry, RegistryBuilder<DamageType> {
/**
* Sets part of the death message translation key.
*
* @return this builder instance.
* @see DamageTypeRegistryEntry#messageId()
* @see DamageType#getTranslationKey()
*/
@Contract(value = "_ -> this", mutates = "this")
Builder messageId(String messageId);
/**
* Sets the amount of hunger exhaustion caused by this damage type.
*
* @return this builder instance.
* @see DamageTypeRegistryEntry#exhaustion()
* @see DamageType#getExhaustion()
*/
@Contract(value = "_ -> this", mutates = "this")
Builder exhaustion(float exhaustion);
/**
* Sets the {@link DamageScaling} for this damage type.
*
* @return this builder instance.
* @see DamageTypeRegistryEntry#damageScaling()
* @see DamageType#getDamageScaling()
*/
@Contract(value = "_ -> this", mutates = "this")
Builder damageScaling(DamageScaling scaling);
/**
* Sets the {@link DamageEffect} for this damage type.
*
* @return this builder instance.
* @see DamageTypeRegistryEntry#damageEffect()
* @see DamageType#getDamageEffect()
*/
@Contract(value = "_ -> this", mutates = "this")
Builder damageEffect(DamageEffect effect);
/**
* Sets the {@link DeathMessageType} for this damage type.
*
* @return this builder instance.
* @see DamageTypeRegistryEntry#deathMessageType()
* @see DamageType#getDeathMessageType()
*/
@Contract(value = "_ -> this", mutates = "this")
Builder deathMessageType(DeathMessageType deathMessageType);
}
}

View File

@ -0,0 +1,22 @@
package io.papermc.paper.registry.data;
import io.papermc.paper.registry.RegistryBuilderFactory;
import java.util.Optional;
import java.util.ServiceLoader;
import java.util.function.Consumer;
import org.bukkit.Art;
import org.jetbrains.annotations.ApiStatus;
@ApiStatus.Internal
@ApiStatus.NonExtendable
public interface InlinedRegistryBuilderProvider {
static InlinedRegistryBuilderProvider instance() {
class Holder {
static final Optional<InlinedRegistryBuilderProvider> INSTANCE = ServiceLoader.load(InlinedRegistryBuilderProvider.class).findFirst();
}
return Holder.INSTANCE.orElseThrow();
}
Art createPaintingVariant(Consumer<RegistryBuilderFactory<Art, ? extends PaintingVariantRegistryEntry.Builder>> value);
}

View File

@ -1,11 +1,15 @@
package io.papermc.paper.registry.event; package io.papermc.paper.registry.event;
import io.papermc.paper.registry.RegistryKey; import io.papermc.paper.registry.RegistryKey;
import io.papermc.paper.registry.data.BannerPatternRegistryEntry;
import io.papermc.paper.registry.data.DamageTypeRegistryEntry;
import io.papermc.paper.registry.data.EnchantmentRegistryEntry; import io.papermc.paper.registry.data.EnchantmentRegistryEntry;
import io.papermc.paper.registry.data.GameEventRegistryEntry; import io.papermc.paper.registry.data.GameEventRegistryEntry;
import io.papermc.paper.registry.data.PaintingVariantRegistryEntry; import io.papermc.paper.registry.data.PaintingVariantRegistryEntry;
import org.bukkit.Art; import org.bukkit.Art;
import org.bukkit.GameEvent; import org.bukkit.GameEvent;
import org.bukkit.block.banner.PatternType;
import org.bukkit.damage.DamageType;
import org.bukkit.enchantments.Enchantment; import org.bukkit.enchantments.Enchantment;
import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.ApiStatus;
import org.jspecify.annotations.NullMarked; import org.jspecify.annotations.NullMarked;
@ -23,6 +27,8 @@ public final class RegistryEvents {
public static final RegistryEventProvider<GameEvent, GameEventRegistryEntry.Builder> GAME_EVENT = create(RegistryKey.GAME_EVENT); public static final RegistryEventProvider<GameEvent, GameEventRegistryEntry.Builder> GAME_EVENT = create(RegistryKey.GAME_EVENT);
public static final RegistryEventProvider<Enchantment, EnchantmentRegistryEntry.Builder> ENCHANTMENT = create(RegistryKey.ENCHANTMENT); public static final RegistryEventProvider<Enchantment, EnchantmentRegistryEntry.Builder> ENCHANTMENT = create(RegistryKey.ENCHANTMENT);
public static final RegistryEventProvider<Art, PaintingVariantRegistryEntry.Builder> PAINTING_VARIANT = create(RegistryKey.PAINTING_VARIANT); public static final RegistryEventProvider<Art, PaintingVariantRegistryEntry.Builder> PAINTING_VARIANT = create(RegistryKey.PAINTING_VARIANT);
public static final RegistryEventProvider<PatternType, BannerPatternRegistryEntry.Builder> BANNER_PATTERN = create(RegistryKey.BANNER_PATTERN);
public static final RegistryEventProvider<DamageType, DamageTypeRegistryEntry.Builder> DAMAGE_TYPE = create(RegistryKey.DAMAGE_TYPE);
private RegistryEvents() { private RegistryEvents() {
} }

View File

@ -1,6 +1,7 @@
package io.papermc.paper.registry.event; package io.papermc.paper.registry.event;
import io.papermc.paper.registry.RegistryBuilder; import io.papermc.paper.registry.RegistryBuilder;
import io.papermc.paper.registry.RegistryBuilderFactory;
import io.papermc.paper.registry.TypedKey; import io.papermc.paper.registry.TypedKey;
import java.util.function.Consumer; import java.util.function.Consumer;
import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.ApiStatus;
@ -24,5 +25,18 @@ public interface WritableRegistry<T, B extends RegistryBuilder<T>> {
* @param key the entry's key (must be unique from others) * @param key the entry's key (must be unique from others)
* @param value a consumer for the entry's builder * @param value a consumer for the entry's builder
*/ */
void register(TypedKey<T> key, Consumer<? super B> value); default void register(final TypedKey<T> key, final Consumer<? super B> value) {
this.registerWith(key, factory -> value.accept(factory.empty()));
}
/**
* Register a new value with the specified key. This will
* fire a {@link RegistryEntryAddEvent} for the new entry. The
* {@link RegistryBuilderFactory} lets you pre-fill a builder with
* an already-existing entry's properties.
*
* @param key the entry's key (must be unique from others)
* @param value a consumer of a builder factory
*/
void registerWith(TypedKey<T> key, Consumer<RegistryBuilderFactory<T, B>> value);
} }

View File

@ -2,9 +2,14 @@ package org.bukkit;
import com.google.common.base.Preconditions; import com.google.common.base.Preconditions;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import io.papermc.paper.registry.RegistryBuilderFactory;
import io.papermc.paper.registry.data.InlinedRegistryBuilderProvider;
import io.papermc.paper.registry.data.PaintingVariantRegistryEntry;
import java.util.Locale; import java.util.Locale;
import java.util.function.Consumer;
import org.bukkit.packs.DataPack; import org.bukkit.packs.DataPack;
import org.bukkit.util.OldEnum; import org.bukkit.util.OldEnum;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@ -18,6 +23,17 @@ import org.jetbrains.annotations.Nullable;
*/ */
public interface Art extends OldEnum<Art>, Keyed { public interface Art extends OldEnum<Art>, Keyed {
/**
* Create an inlined painting variant.
*
* @param value a consumer for the builder factory
* @return the created painting variant
*/
@ApiStatus.Experimental
static @NotNull Art create(final @NotNull Consumer<RegistryBuilderFactory<Art, ? extends PaintingVariantRegistryEntry.Builder>> value) {
return InlinedRegistryBuilderProvider.instance().createPaintingVariant(value);
}
Art KEBAB = getArt("kebab"); Art KEBAB = getArt("kebab");
Art AZTEC = getArt("aztec"); Art AZTEC = getArt("aztec");
Art ALBAN = getArt("alban"); Art ALBAN = getArt("alban");

View File

@ -1184,7 +1184,7 @@ public final class Bukkit {
* @return the {@link Recipe} resulting from the given crafting matrix. * @return the {@link Recipe} resulting from the given crafting matrix.
*/ */
@Nullable @Nullable
public static Recipe getCraftingRecipe(@NotNull ItemStack[] craftingMatrix, @NotNull World world) { public static Recipe getCraftingRecipe(@NotNull ItemStack @NotNull [] craftingMatrix, @NotNull World world) {
return server.getCraftingRecipe(craftingMatrix, world); return server.getCraftingRecipe(craftingMatrix, world);
} }
@ -1213,7 +1213,7 @@ public final class Bukkit {
* @return resulting {@link ItemCraftResult} containing the resulting item, matrix and any overflow items. * @return resulting {@link ItemCraftResult} containing the resulting item, matrix and any overflow items.
*/ */
@NotNull @NotNull
public static ItemCraftResult craftItemResult(@NotNull ItemStack[] craftingMatrix, @NotNull World world, @NotNull Player player) { public static ItemCraftResult craftItemResult(@NotNull ItemStack @NotNull [] craftingMatrix, @NotNull World world, @NotNull Player player) {
return server.craftItemResult(craftingMatrix, world, player); return server.craftItemResult(craftingMatrix, world, player);
} }
@ -1235,7 +1235,7 @@ public final class Bukkit {
* @return resulting {@link ItemCraftResult} containing the resulting item, matrix and any overflow items. * @return resulting {@link ItemCraftResult} containing the resulting item, matrix and any overflow items.
*/ */
@NotNull @NotNull
public static ItemCraftResult craftItemResult(@NotNull ItemStack[] craftingMatrix, @NotNull World world) { public static ItemCraftResult craftItemResult(@NotNull ItemStack @NotNull [] craftingMatrix, @NotNull World world) {
return server.craftItemResult(craftingMatrix, world); return server.craftItemResult(craftingMatrix, world);
} }
@ -1266,7 +1266,7 @@ public final class Bukkit {
* an ItemStack of {@link Material#AIR} is returned. * an ItemStack of {@link Material#AIR} is returned.
*/ */
@NotNull @NotNull
public static ItemStack craftItem(@NotNull ItemStack[] craftingMatrix, @NotNull World world, @NotNull Player player) { public static ItemStack craftItem(@NotNull ItemStack @NotNull [] craftingMatrix, @NotNull World world, @NotNull Player player) {
return server.craftItem(craftingMatrix, world, player); return server.craftItem(craftingMatrix, world, player);
} }
@ -1289,7 +1289,7 @@ public final class Bukkit {
* an ItemStack of {@link Material#AIR} is returned. * an ItemStack of {@link Material#AIR} is returned.
*/ */
@NotNull @NotNull
public static ItemStack craftItem(@NotNull ItemStack[] craftingMatrix, @NotNull World world) { public static ItemStack craftItem(@NotNull ItemStack @NotNull [] craftingMatrix, @NotNull World world) {
return server.craftItem(craftingMatrix, world); return server.craftItem(craftingMatrix, world);
} }
@ -1756,8 +1756,7 @@ public final class Bukkit {
* *
* @return an array containing all previous players * @return an array containing all previous players
*/ */
@NotNull public static @NotNull OfflinePlayer @NotNull [] getOfflinePlayers() {
public static OfflinePlayer[] getOfflinePlayers() {
return server.getOfflinePlayers(); return server.getOfflinePlayers();
} }
@ -2404,8 +2403,7 @@ public final class Bukkit {
* Gets the current server TPS * Gets the current server TPS
* @return current server TPS (1m, 5m, 15m in Paper-Server) * @return current server TPS (1m, 5m, 15m in Paper-Server)
*/ */
@NotNull public static double @NotNull [] getTPS() {
public static double[] getTPS() {
return server.getTPS(); return server.getTPS();
} }
@ -2414,8 +2412,7 @@ public final class Bukkit {
* *
* @return A sample of the servers last tick times (in nanos) * @return A sample of the servers last tick times (in nanos)
*/ */
@NotNull public static long @NotNull [] getTickTimes() {
public static long[] getTickTimes() {
return server.getTickTimes(); return server.getTickTimes();
} }

View File

@ -133,8 +133,7 @@ public interface Chunk extends PersistentDataHolder {
* *
* @return The entities. * @return The entities.
*/ */
@NotNull @NotNull Entity @NotNull [] getEntities();
Entity[] getEntities();
/** /**
* Get a list of all tile entities in the chunk. * Get a list of all tile entities in the chunk.
@ -143,7 +142,7 @@ public interface Chunk extends PersistentDataHolder {
*/ */
@NotNull @NotNull
// Paper start // Paper start
default BlockState[] getTileEntities() { default BlockState @NotNull [] getTileEntities() {
return getTileEntities(true); return getTileEntities(true);
} }
@ -154,7 +153,7 @@ public interface Chunk extends PersistentDataHolder {
* @return The tile entities. * @return The tile entities.
*/ */
@NotNull @NotNull
BlockState[] getTileEntities(boolean useSnapshot); BlockState @NotNull [] getTileEntities(boolean useSnapshot);
/** /**
* Get a list of all tile entities that match a given predicate in the chunk. * Get a list of all tile entities that match a given predicate in the chunk.

View File

@ -3,13 +3,22 @@ package org.bukkit;
import com.google.common.base.Preconditions; import com.google.common.base.Preconditions;
import com.google.common.base.Predicates; import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import io.papermc.paper.datacomponent.DataComponentType;
import io.papermc.paper.registry.RegistryAccess;
import io.papermc.paper.registry.RegistryKey;
import io.papermc.paper.registry.TypedKey;
import io.papermc.paper.registry.tag.Tag;
import io.papermc.paper.registry.tag.TagKey;
import java.util.Collection;
import java.util.Iterator; import java.util.Iterator;
import java.util.Locale; import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Objects; import java.util.Objects;
import java.util.function.Predicate; import java.util.function.Predicate;
import java.util.stream.Stream; import java.util.stream.Stream;
import java.util.stream.StreamSupport; import java.util.stream.StreamSupport;
import net.kyori.adventure.key.Key;
import org.bukkit.advancement.Advancement; import org.bukkit.advancement.Advancement;
import org.bukkit.attribute.Attribute; import org.bukkit.attribute.Attribute;
import org.bukkit.block.Biome; import org.bukkit.block.Biome;
@ -35,8 +44,8 @@ import org.bukkit.map.MapCursor;
import org.bukkit.potion.PotionEffectType; import org.bukkit.potion.PotionEffectType;
import org.bukkit.potion.PotionType; import org.bukkit.potion.PotionType;
import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull; import org.jspecify.annotations.NullMarked;
import org.jetbrains.annotations.Nullable; import org.jspecify.annotations.Nullable;
/** /**
* Represents a registry of Bukkit objects that may be retrieved by * Represents a registry of Bukkit objects that may be retrieved by
@ -44,39 +53,34 @@ import org.jetbrains.annotations.Nullable;
* *
* @param <T> type of item in the registry * @param <T> type of item in the registry
*/ */
@NullMarked
public interface Registry<T extends Keyed> extends Iterable<T> { public interface Registry<T extends Keyed> extends Iterable<T> {
private static <A extends Keyed> Registry<A> registryFor(final RegistryKey<A> registryKey) {
return RegistryAccess.registryAccess().getRegistry(registryKey);
}
@SuppressWarnings("removal")
@Deprecated(forRemoval = true, since = "1.21.4")
private static <A extends Keyed> Registry<A> legacyRegistryFor(final Class<A> clazz) {
return Objects.requireNonNull(RegistryAccess.registryAccess().getRegistry(clazz), "No registry present for " + clazz.getSimpleName() + ". This is a bug.");
}
/** /**
* Server advancements. * Server advancements.
* *
* @see Bukkit#getAdvancement(org.bukkit.NamespacedKey) * @see Bukkit#getAdvancement(NamespacedKey)
* @see Bukkit#advancementIterator() * @see Bukkit#advancementIterator()
* @deprecated use {@link Bukkit#getAdvancement(NamespacedKey)} and {@link Bukkit#advancementIterator()}
*/ */
Registry<Advancement> ADVANCEMENT = new Registry<Advancement>() { @Deprecated(since = "1.21.4", forRemoval = true)
Registry<Advancement> ADVANCEMENT = new NotARegistry<>() {
@Nullable
@Override @Override
public Advancement get(@NotNull NamespacedKey key) { public @Nullable Advancement get(final NamespacedKey key) {
return Bukkit.getAdvancement(key); return Bukkit.getAdvancement(key);
} }
@NotNull
@Override
public Advancement getOrThrow(@NotNull NamespacedKey key) {
Advancement advancement = get(key);
Preconditions.checkArgument(advancement != null, "No Advancement registry entry found for key %s.", key);
return advancement;
}
@NotNull
@Override
public Stream<Advancement> stream() {
return StreamSupport.stream(spliterator(), false);
}
@NotNull
@Override @Override
public Iterator<Advancement> iterator() { public Iterator<Advancement> iterator() {
return Bukkit.advancementIterator(); return Bukkit.advancementIterator();
@ -86,71 +90,54 @@ public interface Registry<T extends Keyed> extends Iterable<T> {
* Server art. * Server art.
* *
* @see Art * @see Art
* @deprecated use {@link io.papermc.paper.registry.RegistryAccess#getRegistry(io.papermc.paper.registry.RegistryKey)} with {@link io.papermc.paper.registry.RegistryKey#PAINTING_VARIANT} * @deprecated use {@link RegistryAccess#getRegistry(RegistryKey)} with {@link RegistryKey#PAINTING_VARIANT}
*/ */
@Deprecated(since = "1.21.3") // Paper @Deprecated(since = "1.21.3") // Paper
Registry<Art> ART = Objects.requireNonNull(io.papermc.paper.registry.RegistryAccess.registryAccess().getRegistry(Art.class), "No registry present for Art. This is a bug."); Registry<Art> ART = legacyRegistryFor(Art.class);
/** /**
* Attribute. * Attribute.
* *
* @see Attribute * @see Attribute
*/ */
Registry<Attribute> ATTRIBUTE = io.papermc.paper.registry.RegistryAccess.registryAccess().getRegistry(io.papermc.paper.registry.RegistryKey.ATTRIBUTE); // Paper Registry<Attribute> ATTRIBUTE = registryFor(RegistryKey.ATTRIBUTE);
/** /**
* Server banner patterns. * Server banner patterns.
* *
* @see PatternType * @see PatternType
* @deprecated use {@link io.papermc.paper.registry.RegistryAccess#getRegistry(io.papermc.paper.registry.RegistryKey)} with {@link io.papermc.paper.registry.RegistryKey#BANNER_PATTERN} * @deprecated use {@link RegistryAccess#getRegistry(RegistryKey)} with {@link RegistryKey#BANNER_PATTERN}
*/ */
@Deprecated(since = "1.21") // Paper @Deprecated(since = "1.21") // Paper
Registry<PatternType> BANNER_PATTERN = Objects.requireNonNull(io.papermc.paper.registry.RegistryAccess.registryAccess().getRegistry(PatternType.class), "No registry present for PatternType. This is a bug."); // Paper Registry<PatternType> BANNER_PATTERN = legacyRegistryFor(PatternType.class);
/** /**
* Server biomes. * Server biomes.
* *
* @see Biome * @see Biome
* @deprecated use {@link io.papermc.paper.registry.RegistryAccess#getRegistry(io.papermc.paper.registry.RegistryKey)} with {@link io.papermc.paper.registry.RegistryKey#BIOME} * @deprecated use {@link RegistryAccess#getRegistry(RegistryKey)} with {@link RegistryKey#BIOME}
*/ */
@Deprecated(since = "1.21.3") // Paper @Deprecated(since = "1.21.3") // Paper
Registry<Biome> BIOME = Objects.requireNonNull(io.papermc.paper.registry.RegistryAccess.registryAccess().getRegistry(Biome.class), "No registry present for Biome. This is a bug."); Registry<Biome> BIOME = legacyRegistryFor(Biome.class);
/** /**
* Server block types. * Server block types.
* *
* @see BlockType * @see BlockType
* @apiNote BlockType is not ready for public usage yet
*/ */
@ApiStatus.Internal @ApiStatus.Experimental
Registry<BlockType> BLOCK = io.papermc.paper.registry.RegistryAccess.registryAccess().getRegistry(io.papermc.paper.registry.RegistryKey.BLOCK); // Paper Registry<BlockType> BLOCK = registryFor(RegistryKey.BLOCK);
/** /**
* Custom boss bars. * Custom boss bars.
* *
* @see Bukkit#getBossBar(org.bukkit.NamespacedKey) * @see Bukkit#getBossBar(org.bukkit.NamespacedKey)
* @see Bukkit#getBossBars() * @see Bukkit#getBossBars()
* @deprecated use {@link Bukkit#getBossBar(NamespacedKey)} and {@link Bukkit#getBossBars()}
*/ */
Registry<KeyedBossBar> BOSS_BARS = new Registry<KeyedBossBar>() { @Deprecated(since = "1.21.4", forRemoval = true)
Registry<KeyedBossBar> BOSS_BARS = new NotARegistry<>() {
@Nullable
@Override @Override
public KeyedBossBar get(@NotNull NamespacedKey key) { public @Nullable KeyedBossBar get(final NamespacedKey key) {
return Bukkit.getBossBar(key); return Bukkit.getBossBar(key);
} }
@NotNull
@Override
public KeyedBossBar getOrThrow(@NotNull NamespacedKey key) {
KeyedBossBar keyedBossBar = get(key);
Preconditions.checkArgument(keyedBossBar != null, "No KeyedBossBar registry entry found for key %s.", key);
return keyedBossBar;
}
@NotNull
@Override
public Stream<KeyedBossBar> stream() {
return StreamSupport.stream(spliterator(), false);
}
@NotNull
@Override @Override
public Iterator<KeyedBossBar> iterator() { public Iterator<KeyedBossBar> iterator() {
return Bukkit.getBossBars(); return Bukkit.getBossBars();
@ -161,37 +148,36 @@ public interface Registry<T extends Keyed> extends Iterable<T> {
* *
* @see Cat.Type * @see Cat.Type
*/ */
Registry<Cat.Type> CAT_VARIANT = io.papermc.paper.registry.RegistryAccess.registryAccess().getRegistry(io.papermc.paper.registry.RegistryKey.CAT_VARIANT); // Paper Registry<Cat.Type> CAT_VARIANT = registryFor(RegistryKey.CAT_VARIANT);
/** /**
* Server enchantments. * Server enchantments.
* *
* @see Enchantment * @see Enchantment
* @deprecated use {@link io.papermc.paper.registry.RegistryAccess#getRegistry(io.papermc.paper.registry.RegistryKey)} with {@link io.papermc.paper.registry.RegistryKey#ENCHANTMENT} * @deprecated use {@link RegistryAccess#getRegistry(RegistryKey)} with {@link RegistryKey#ENCHANTMENT}
*/ */
@Deprecated(since = "1.21") @Deprecated(since = "1.21")
Registry<Enchantment> ENCHANTMENT = Objects.requireNonNull(io.papermc.paper.registry.RegistryAccess.registryAccess().getRegistry(Enchantment.class), "No registry present for Enchantment. This is a bug."); // Paper Registry<Enchantment> ENCHANTMENT = legacyRegistryFor(Enchantment.class);
/** /**
* Server entity types. * Server entity types.
* *
* @see EntityType * @see EntityType
*/ */
Registry<EntityType> ENTITY_TYPE = io.papermc.paper.registry.RegistryAccess.registryAccess().getRegistry(io.papermc.paper.registry.RegistryKey.ENTITY_TYPE); // Paper Registry<EntityType> ENTITY_TYPE = registryFor(RegistryKey.ENTITY_TYPE);
/** /**
* Server instruments. * Server instruments.
* *
* @see MusicInstrument * @see MusicInstrument
* @deprecated use {@link io.papermc.paper.registry.RegistryAccess#getRegistry(io.papermc.paper.registry.RegistryKey)} with {@link io.papermc.paper.registry.RegistryKey#INSTRUMENT} * @deprecated use {@link RegistryAccess#getRegistry(RegistryKey)} with {@link RegistryKey#INSTRUMENT}
*/ */
@Deprecated(since = "1.21.2") @Deprecated(since = "1.21.2")
Registry<MusicInstrument> INSTRUMENT = Objects.requireNonNull(io.papermc.paper.registry.RegistryAccess.registryAccess().getRegistry(MusicInstrument.class), "No registry present for Instruments. This is a bug."); // Paper Registry<MusicInstrument> INSTRUMENT = legacyRegistryFor(MusicInstrument.class);
/** /**
* Server item types. * Server item types.
* *
* @see ItemType * @see ItemType
* @apiNote ItemType is not ready for public usage yet
*/ */
@ApiStatus.Internal @ApiStatus.Experimental
Registry<ItemType> ITEM = io.papermc.paper.registry.RegistryAccess.registryAccess().getRegistry(io.papermc.paper.registry.RegistryKey.ITEM); // Paper Registry<ItemType> ITEM = registryFor(RegistryKey.ITEM);
/** /**
* Default server loot tables. * Default server loot tables.
* *
@ -210,25 +196,25 @@ public interface Registry<T extends Keyed> extends Iterable<T> {
* @see MenuType * @see MenuType
*/ */
@ApiStatus.Experimental @ApiStatus.Experimental
Registry<MenuType> MENU = io.papermc.paper.registry.RegistryAccess.registryAccess().getRegistry(io.papermc.paper.registry.RegistryKey.MENU); // Paper Registry<MenuType> MENU = registryFor(RegistryKey.MENU);
/** /**
* Server mob effects. * Server mob effects.
* *
* @see PotionEffectType * @see PotionEffectType
*/ */
Registry<PotionEffectType> EFFECT = io.papermc.paper.registry.RegistryAccess.registryAccess().getRegistry(io.papermc.paper.registry.RegistryKey.MOB_EFFECT); // Paper Registry<PotionEffectType> MOB_EFFECT = registryFor(RegistryKey.MOB_EFFECT);
/** /**
* Server particles. * Server particles.
* *
* @see Particle * @see Particle
*/ */
Registry<Particle> PARTICLE_TYPE = io.papermc.paper.registry.RegistryAccess.registryAccess().getRegistry(io.papermc.paper.registry.RegistryKey.PARTICLE_TYPE); // Paper Registry<Particle> PARTICLE_TYPE = registryFor(RegistryKey.PARTICLE_TYPE); // Paper
/** /**
* Server potions. * Server potions.
* *
* @see PotionType * @see PotionType
*/ */
Registry<PotionType> POTION = io.papermc.paper.registry.RegistryAccess.registryAccess().getRegistry(io.papermc.paper.registry.RegistryKey.POTION); // Paper Registry<PotionType> POTION = registryFor(RegistryKey.POTION); // Paper
/** /**
* Server statistics. * Server statistics.
* *
@ -239,160 +225,161 @@ public interface Registry<T extends Keyed> extends Iterable<T> {
* Server structures. * Server structures.
* *
* @see Structure * @see Structure
* @deprecated use {@link io.papermc.paper.registry.RegistryAccess#getRegistry(io.papermc.paper.registry.RegistryKey)} with {@link io.papermc.paper.registry.RegistryKey#STRUCTURE} * @deprecated use {@link RegistryAccess#getRegistry(RegistryKey)} with {@link RegistryKey#STRUCTURE}
*/ */
@Deprecated(since = "1.20.6") // Paper @Deprecated(since = "1.20.6") // Paper
Registry<Structure> STRUCTURE = Objects.requireNonNull(io.papermc.paper.registry.RegistryAccess.registryAccess().getRegistry(Structure.class), "No registry present for Structure. This is a bug."); // Paper Registry<Structure> STRUCTURE = legacyRegistryFor(Structure.class);
/** /**
* Server structure types. * Server structure types.
* *
* @see StructureType * @see StructureType
*/ */
Registry<StructureType> STRUCTURE_TYPE = Objects.requireNonNull(io.papermc.paper.registry.RegistryAccess.registryAccess().getRegistry(io.papermc.paper.registry.RegistryKey.STRUCTURE_TYPE), "No registry present for StructureType. This is a bug."); // Paper Registry<StructureType> STRUCTURE_TYPE = registryFor(RegistryKey.STRUCTURE_TYPE);
/** /**
* Sound keys. * Sound events.
* *
* @see Sound * @see Sound
*/ */
Registry<Sound> SOUNDS = io.papermc.paper.registry.RegistryAccess.registryAccess().getRegistry(io.papermc.paper.registry.RegistryKey.SOUND_EVENT); // Paper Registry<Sound> SOUND_EVENT = registryFor(RegistryKey.SOUND_EVENT);
/** /**
* Trim materials. * Trim materials.
* *
* @see TrimMaterial * @see TrimMaterial
* @deprecated use {@link io.papermc.paper.registry.RegistryAccess#getRegistry(io.papermc.paper.registry.RegistryKey)} with {@link io.papermc.paper.registry.RegistryKey#TRIM_MATERIAL} * @deprecated use {@link RegistryAccess#getRegistry(RegistryKey)} with {@link RegistryKey#TRIM_MATERIAL}
*/ */
@Deprecated(since = "1.20.6") // Paper @Deprecated(since = "1.20.6") // Paper
Registry<TrimMaterial> TRIM_MATERIAL = Objects.requireNonNull(io.papermc.paper.registry.RegistryAccess.registryAccess().getRegistry(TrimMaterial.class), "No registry present for TrimMaterial. This is a bug."); // Paper Registry<TrimMaterial> TRIM_MATERIAL = legacyRegistryFor(TrimMaterial.class);
/** /**
* Trim patterns. * Trim patterns.
* *
* @see TrimPattern * @see TrimPattern
* @deprecated use {@link io.papermc.paper.registry.RegistryAccess#getRegistry(io.papermc.paper.registry.RegistryKey)} with {@link io.papermc.paper.registry.RegistryKey#TRIM_PATTERN} * @deprecated use {@link RegistryAccess#getRegistry(RegistryKey)} with {@link RegistryKey#TRIM_PATTERN}
*/ */
@Deprecated(since = "1.20.6") @Deprecated(since = "1.20.6")
Registry<TrimPattern> TRIM_PATTERN = Objects.requireNonNull(io.papermc.paper.registry.RegistryAccess.registryAccess().getRegistry(TrimPattern.class), "No registry present for TrimPattern. This is a bug."); // Paper Registry<TrimPattern> TRIM_PATTERN = legacyRegistryFor(TrimPattern.class);
/** /**
* Damage types. * Damage types.
* *
* @see DamageType * @see DamageType
* @deprecated use {@link io.papermc.paper.registry.RegistryAccess#getRegistry(io.papermc.paper.registry.RegistryKey)} with {@link io.papermc.paper.registry.RegistryKey#DAMAGE_TYPE} * @deprecated use {@link RegistryAccess#getRegistry(RegistryKey)} with {@link RegistryKey#DAMAGE_TYPE}
*/ */
@Deprecated(since = "1.20.6") @Deprecated(since = "1.20.6")
Registry<DamageType> DAMAGE_TYPE = Objects.requireNonNull(io.papermc.paper.registry.RegistryAccess.registryAccess().getRegistry(DamageType.class), "No registry present for DamageType. This is a bug."); // Paper Registry<DamageType> DAMAGE_TYPE = legacyRegistryFor(DamageType.class);
/** /**
* Jukebox songs. * Jukebox songs.
* *
* @see JukeboxSong * @see JukeboxSong
* @deprecated use {@link io.papermc.paper.registry.RegistryAccess#getRegistry(io.papermc.paper.registry.RegistryKey)} with {@link io.papermc.paper.registry.RegistryKey#JUKEBOX_SONG} * @deprecated use {@link RegistryAccess#getRegistry(RegistryKey)} with {@link RegistryKey#JUKEBOX_SONG}
*/ */
@ApiStatus.Experimental @ApiStatus.Experimental
@Deprecated(since = "1.21") @Deprecated(since = "1.21")
Registry<JukeboxSong> JUKEBOX_SONG = Objects.requireNonNull(io.papermc.paper.registry.RegistryAccess.registryAccess().getRegistry(JukeboxSong.class), "No registry present for JukeboxSong. This is a bug."); // Paper Registry<JukeboxSong> JUKEBOX_SONG = legacyRegistryFor(JukeboxSong.class);
/** /**
* Villager profession. * Villager profession.
* *
* @see Villager.Profession * @see Villager.Profession
*/ */
Registry<Villager.Profession> VILLAGER_PROFESSION = io.papermc.paper.registry.RegistryAccess.registryAccess().getRegistry(io.papermc.paper.registry.RegistryKey.VILLAGER_PROFESSION); // Paper Registry<Villager.Profession> VILLAGER_PROFESSION = registryFor(RegistryKey.VILLAGER_PROFESSION);
/** /**
* Villager type. * Villager type.
* *
* @see Villager.Type * @see Villager.Type
*/ */
Registry<Villager.Type> VILLAGER_TYPE = io.papermc.paper.registry.RegistryAccess.registryAccess().getRegistry(io.papermc.paper.registry.RegistryKey.VILLAGER_TYPE); // Paper Registry<Villager.Type> VILLAGER_TYPE = registryFor(RegistryKey.VILLAGER_TYPE);
/** /**
* Memory Keys. * Memory Keys.
* *
* @see MemoryKey * @see MemoryKey
*/ */
Registry<MemoryKey> MEMORY_MODULE_TYPE = new Registry<MemoryKey>() { Registry<MemoryKey> MEMORY_MODULE_TYPE = new NotARegistry<>() {
@NotNull
@Override @Override
public Iterator iterator() { public Iterator iterator() {
return MemoryKey.values().iterator(); return MemoryKey.values().iterator();
} }
@Nullable
@Override @Override
public MemoryKey get(@NotNull NamespacedKey key) { public @Nullable MemoryKey get(final NamespacedKey key) {
return MemoryKey.getByKey(key); return MemoryKey.getByKey(key);
} }
@NotNull
@Override
public MemoryKey getOrThrow(@NotNull NamespacedKey key) {
MemoryKey memoryKey = get(key);
Preconditions.checkArgument(memoryKey != null, "No MemoryKey registry entry found for key %s.", key);
return memoryKey;
}
@NotNull
@Override
public Stream<MemoryKey> stream() {
return StreamSupport.stream(spliterator(), false);
}
}; };
/** /**
* Server fluids. * Server fluids.
* *
* @see Fluid * @see Fluid
*/ */
Registry<Fluid> FLUID = io.papermc.paper.registry.RegistryAccess.registryAccess().getRegistry(io.papermc.paper.registry.RegistryKey.FLUID); // Paper Registry<Fluid> FLUID = registryFor(RegistryKey.FLUID);
/** /**
* Frog variants. * Frog variants.
* *
* @see Frog.Variant * @see Frog.Variant
*/ */
Registry<Frog.Variant> FROG_VARIANT = io.papermc.paper.registry.RegistryAccess.registryAccess().getRegistry(io.papermc.paper.registry.RegistryKey.FROG_VARIANT); // Paper Registry<Frog.Variant> FROG_VARIANT = registryFor(RegistryKey.FROG_VARIANT);
/** /**
* Wolf variants. * Wolf variants.
* *
* @see Wolf.Variant * @see Wolf.Variant
* @deprecated use {@link io.papermc.paper.registry.RegistryAccess#getRegistry(io.papermc.paper.registry.RegistryKey)} with {@link io.papermc.paper.registry.RegistryKey#WOLF_VARIANT} * @deprecated use {@link RegistryAccess#getRegistry(RegistryKey)} with {@link RegistryKey#WOLF_VARIANT}
*/ */
@Deprecated(since = "1.20.6") @Deprecated(since = "1.20.6")
Registry<Wolf.Variant> WOLF_VARIANT = Objects.requireNonNull(io.papermc.paper.registry.RegistryAccess.registryAccess().getRegistry(Wolf.Variant.class), "No registry present for Wolf$Variant. This is a bug."); // Paper Registry<Wolf.Variant> WOLF_VARIANT = legacyRegistryFor(Wolf.Variant.class);
/** /**
* Map cursor types. * Map cursor types.
* *
* @see MapCursor.Type * @see MapCursor.Type
*/ */
Registry<MapCursor.Type> MAP_DECORATION_TYPE = io.papermc.paper.registry.RegistryAccess.registryAccess().getRegistry(io.papermc.paper.registry.RegistryKey.MAP_DECORATION_TYPE); // Paper Registry<MapCursor.Type> MAP_DECORATION_TYPE = registryFor(RegistryKey.MAP_DECORATION_TYPE);
/** /**
* Game events. * Game events.
* *
* @see GameEvent * @see GameEvent
* @see io.papermc.paper.registry.event.RegistryEvents#GAME_EVENT
*/ */
Registry<GameEvent> GAME_EVENT = io.papermc.paper.registry.RegistryAccess.registryAccess().getRegistry(io.papermc.paper.registry.RegistryKey.GAME_EVENT); // Paper Registry<GameEvent> GAME_EVENT = registryFor(RegistryKey.GAME_EVENT);
/**
* Data component types.
*
* @see DataComponentType
*/
Registry<DataComponentType> DATA_COMPONENT_TYPE = registryFor(RegistryKey.DATA_COMPONENT_TYPE); // Paper
// Paper start - potion effect type registry //<editor-fold desc="renames" defaultstate="collapsed">
/** /**
* Potion effect types. * @apiNote use {@link #MOB_EFFECT} instead
* * @hidden
* @see org.bukkit.potion.PotionEffectType
*/ */
@ApiStatus.Obsolete(since = "1.21.4")
Registry<PotionEffectType> EFFECT = MOB_EFFECT;
/**
* @apiNote use {@link #MOB_EFFECT} instead
* @hidden
*/
@ApiStatus.Obsolete(since = "1.21.4")
Registry<org.bukkit.potion.PotionEffectType> POTION_EFFECT_TYPE = EFFECT; Registry<org.bukkit.potion.PotionEffectType> POTION_EFFECT_TYPE = EFFECT;
// Paper end - potion effect type registry
Registry<io.papermc.paper.datacomponent.DataComponentType> DATA_COMPONENT_TYPE = io.papermc.paper.registry.RegistryAccess.registryAccess().getRegistry(io.papermc.paper.registry.RegistryKey.DATA_COMPONENT_TYPE); // Paper
/** /**
* Get the object by its key. * @apiNote use {@link #SOUND_EVENT}
* * @hidden
* @param key non-null key
* @return item or null if does not exist
*/ */
@Nullable @ApiStatus.Obsolete(since = "1.21.4")
T get(@NotNull NamespacedKey key); Registry<Sound> SOUNDS = registryFor(RegistryKey.SOUND_EVENT);
// Paper start //</editor-fold>
/** /**
* Get the object by its key. * Get the object by its key.
* *
* @param key non-null key * @param key non-null key
* @return item or null if it does not exist * @return item or null if it does not exist
*/ */
default @Nullable T get(final net.kyori.adventure.key.@NotNull Key key) { @Nullable T get(NamespacedKey key);
// Paper start
/**
* Get the object by its key.
*
* @param key non-null key
* @return item or null if it does not exist
*/
default @Nullable T get(final Key key) {
return key instanceof final NamespacedKey nsKey ? this.get(nsKey) : this.get(new NamespacedKey(key.namespace(), key.value())); return key instanceof final NamespacedKey nsKey ? this.get(nsKey) : this.get(new NamespacedKey(key.namespace(), key.value()));
} }
@ -402,23 +389,26 @@ public interface Registry<T extends Keyed> extends Iterable<T> {
* @param typedKey non-null typed key * @param typedKey non-null typed key
* @return item or null if it does not exist * @return item or null if it does not exist
*/ */
default @Nullable T get(final io.papermc.paper.registry.@NotNull TypedKey<T> typedKey) { default @Nullable T get(final TypedKey<T> typedKey) {
Preconditions.checkArgument(typedKey != null, "typedKey cannot be null");
return this.get(typedKey.key()); return this.get(typedKey.key());
} }
// Paper end // Paper end
// Paper start - improve Registry // Paper start - improve Registry
/** /**
* Gets the object by its key or throws if it doesn't exist. * Gets the object by its key or throws if it doesn't exist.
* *
* @param key the key to get the object of in this registry * @param key the key to get the object of in this registry
* @return the object for the key * @return the object for the key
* @throws java.util.NoSuchElementException if the key doesn't point to an object in the registry * @throws NoSuchElementException if the key doesn't point to an object in the registry
*/ */
default @NotNull T getOrThrow(final net.kyori.adventure.key.@NotNull Key key) { default T getOrThrow(final net.kyori.adventure.key.Key key) {
Preconditions.checkArgument(key != null, "key cannot be null");
final T value = this.get(key); final T value = this.get(key);
if (value == null) { if (value == null) {
throw new java.util.NoSuchElementException("No value for " + key + " in " + this); throw new NoSuchElementException("No value for " + key + " in " + this);
} }
return value; return value;
} }
@ -428,12 +418,12 @@ public interface Registry<T extends Keyed> extends Iterable<T> {
* *
* @param key the key to get the object of in this registry * @param key the key to get the object of in this registry
* @return the object for the key * @return the object for the key
* @throws java.util.NoSuchElementException if the key doesn't point to an object in the registry * @throws NoSuchElementException if the key doesn't point to an object in the registry
*/ */
default @NotNull T getOrThrow(final io.papermc.paper.registry.@NotNull TypedKey<T> key) { default T getOrThrow(final TypedKey<T> key) {
final T value = this.get(key); final T value = this.get(key);
if (value == null) { if (value == null) {
throw new java.util.NoSuchElementException("No value for " + key + " in " + this); throw new NoSuchElementException("No value for " + key + " in " + this);
} }
return value; return value;
} }
@ -447,14 +437,13 @@ public interface Registry<T extends Keyed> extends Iterable<T> {
* *
* @param value the value to get the key of in this registry * @param value the value to get the key of in this registry
* @return the key for the value * @return the key for the value
* @throws java.util.NoSuchElementException if the value doesn't exist in this registry * @throws NoSuchElementException if the value doesn't exist in this registry
* @see #getKey(Keyed) * @see #getKey(Keyed)
*/ */
default @NotNull NamespacedKey getKeyOrThrow(final @NotNull T value) { default NamespacedKey getKeyOrThrow(final T value) {
Preconditions.checkArgument(value != null, "value cannot be null");
final NamespacedKey key = this.getKey(value); final NamespacedKey key = this.getKey(value);
if (key == null) { if (key == null) {
throw new java.util.NoSuchElementException(value + " has no key in " + this); throw new NoSuchElementException(value + " has no key in " + this);
} }
return key; return key;
} }
@ -470,14 +459,7 @@ public interface Registry<T extends Keyed> extends Iterable<T> {
* @return the key for the value or null if not in the registry * @return the key for the value or null if not in the registry
* @see #getKeyOrThrow(Keyed) * @see #getKeyOrThrow(Keyed)
*/ */
default @Nullable NamespacedKey getKey(final @NotNull T value) { @Nullable NamespacedKey getKey(T value);
Preconditions.checkArgument(value != null, "value cannot be null");
//noinspection ConstantValue (it might not be in the future...)
if (value instanceof Keyed) {
return value.getKey();
}
return null;
}
// Paper end - improve Registry // Paper end - improve Registry
// Paper start - RegistrySet API // Paper start - RegistrySet API
@ -486,46 +468,52 @@ public interface Registry<T extends Keyed> extends Iterable<T> {
* *
* @param key the key to check for * @param key the key to check for
* @return true if this registry has a tag with the given key, false otherwise * @return true if this registry has a tag with the given key, false otherwise
* @see #getTag(io.papermc.paper.registry.tag.TagKey) * @throws UnsupportedOperationException if this registry doesn't have or support tags
* @see #getTag(TagKey)
*/ */
@ApiStatus.Experimental @ApiStatus.Experimental
default boolean hasTag(final io.papermc.paper.registry.tag.@NotNull TagKey<T> key) { boolean hasTag(TagKey<T> key);
throw new UnsupportedOperationException(this + " doesn't have tags");
}
/** /**
* Gets the named registry set (tag) for the given key. * Gets the named registry set (tag) for the given key.
* *
* @param key the key to get the tag for * @param key the key to get the tag for
* @return the tag for the key * @return the tag for the key
* @throws java.util.NoSuchElementException if no tag with the given key is found * @throws NoSuchElementException if no tag with the given key is found
* @throws UnsupportedOperationException if this registry doesn't have or support tags * @throws UnsupportedOperationException if this registry doesn't have or support tags
* @see #hasTag(io.papermc.paper.registry.tag.TagKey) * @see #hasTag(TagKey)
*/ */
@ApiStatus.Experimental @ApiStatus.Experimental
default @NotNull io.papermc.paper.registry.tag.Tag<T> getTag(final io.papermc.paper.registry.tag.@NotNull TagKey<T> key) { Tag<T> getTag(TagKey<T> key);
throw new UnsupportedOperationException(this + " doesn't have tags");
} /**
* Gets all the tags in this registry.
*
* @return a stream of all tags in this registry
* @throws UnsupportedOperationException if this registry doesn't have or support tags
*/
@ApiStatus.Experimental
Collection<Tag<T>> getTags();
// Paper end - RegistrySet API // Paper end - RegistrySet API
/** /**
* Get the object by its key. * Get the object by its key.
* * <p>
* If there is no object with the given key, an exception will be thrown. * If there is no object with the given key, an exception will be thrown.
* *
* @param key to get the object from * @param key to get the object from
* @return object with the given key * @return object with the given key
* @throws IllegalArgumentException if there is no object with the given key * @throws NoSuchElementException if there is no object with the given key
*/ */
@NotNull default T getOrThrow(final NamespacedKey key) {
T getOrThrow(@NotNull NamespacedKey key); return this.getOrThrow((Key) key);
}
/** /**
* Returns a new stream, which contains all registry items, which are registered to the registry. * Returns a new stream, which contains all registry items, which are registered to the registry.
* *
* @return a stream of all registry items * @return a stream of all registry items
*/ */
@NotNull
Stream<T> stream(); Stream<T> stream();
/** /**
@ -539,64 +527,47 @@ public interface Registry<T extends Keyed> extends Iterable<T> {
* @deprecated this method's behavior is broken and not useful. If you want to get an object * @deprecated this method's behavior is broken and not useful. If you want to get an object
* based on its vanilla name, or a key, wrap it in a {@link NamespacedKey} object and use {@link #get(NamespacedKey)} * based on its vanilla name, or a key, wrap it in a {@link NamespacedKey} object and use {@link #get(NamespacedKey)}
*/ */
@Nullable // Paper
@Deprecated(forRemoval = true) // Paper @Deprecated(forRemoval = true)
default T match(@NotNull String input) { default @Nullable T match(final String input) {
Preconditions.checkArgument(input != null, "input must not be null"); Preconditions.checkArgument(input != null, "input must not be null");
String filtered = input.toLowerCase(Locale.ROOT).replaceAll("\\s+", "_"); final String filtered = input.toLowerCase(Locale.ROOT).replaceAll("\\s+", "_");
NamespacedKey namespacedKey = NamespacedKey.fromString(filtered); final NamespacedKey namespacedKey = NamespacedKey.fromString(filtered);
return (namespacedKey != null) ? get(namespacedKey) : null; return (namespacedKey != null) ? this.get(namespacedKey) : null;
} }
class SimpleRegistry<T extends Enum<T> & Keyed> implements Registry<T> { // Paper - remove final @ApiStatus.Internal
class SimpleRegistry<T extends Enum<T> & Keyed> extends NotARegistry<T> { // Paper - remove final
private final Class<T> type; private final Class<T> type;
private final Map<NamespacedKey, T> map; private final Map<NamespacedKey, T> map;
protected SimpleRegistry(@NotNull Class<T> type) { protected SimpleRegistry(final Class<T> type) {
this(type, Predicates.<T>alwaysTrue()); this(type, Predicates.alwaysTrue());
} }
protected SimpleRegistry(@NotNull Class<T> type, @NotNull Predicate<T> predicate) { protected SimpleRegistry(final Class<T> type, final Predicate<T> predicate) {
ImmutableMap.Builder<NamespacedKey, T> builder = ImmutableMap.builder(); final ImmutableMap.Builder<NamespacedKey, T> builder = ImmutableMap.builder();
for (T entry : type.getEnumConstants()) { for (final T entry : type.getEnumConstants()) {
if (predicate.test(entry)) { if (predicate.test(entry)) {
builder.put(entry.getKey(), entry); builder.put(entry.getKey(), entry);
} }
} }
map = builder.build(); this.map = builder.build();
this.type = type; this.type = type;
} }
@Nullable
@Override @Override
public T get(@NotNull NamespacedKey key) { public @Nullable T get(final NamespacedKey key) {
return map.get(key); return this.map.get(key);
} }
@NotNull
@Override
public T getOrThrow(@NotNull NamespacedKey key) {
T object = get(key);
Preconditions.checkArgument(object != null, "No %s registry entry found for key %s.", type, key);
return object;
}
@NotNull
@Override
public Stream<T> stream() {
return StreamSupport.stream(spliterator(), false);
}
@NotNull
@Override @Override
public Iterator<T> iterator() { public Iterator<T> iterator() {
return map.values().iterator(); return this.map.values().iterator();
} }
@ApiStatus.Internal @ApiStatus.Internal
@ -604,12 +575,34 @@ public interface Registry<T extends Keyed> extends Iterable<T> {
public Class<T> getType() { public Class<T> getType() {
return this.type; return this.type;
} }
}
@ApiStatus.Internal
abstract class NotARegistry<A extends Keyed> implements Registry<A> {
// Paper start - improve Registry
@Override @Override
public @NotNull NamespacedKey getKey(final @NotNull T value) { public Stream<A> stream() {
return StreamSupport.stream(this.spliterator(), false);
}
@Override
public NamespacedKey getKey(final A value) {
return value.getKey(); return value.getKey();
} }
// Paper end - improve Registry
@Override
public boolean hasTag(final TagKey<A> key) {
throw new UnsupportedOperationException("This is not a real registry and therefore cannot support tags");
}
@Override
public Tag<A> getTag(final TagKey<A> key) {
throw new UnsupportedOperationException("This is not a real registry and therefore cannot support tags");
}
@Override
public Collection<Tag<A>> getTags() {
throw new UnsupportedOperationException("This is not a real registry and therefore cannot support tags");
}
} }
} }

View File

@ -1018,7 +1018,7 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi
* @return the {@link Recipe} resulting from the given crafting matrix. * @return the {@link Recipe} resulting from the given crafting matrix.
*/ */
@Nullable @Nullable
public Recipe getCraftingRecipe(@NotNull ItemStack[] craftingMatrix, @NotNull World world); public Recipe getCraftingRecipe(@NotNull ItemStack @NotNull [] craftingMatrix, @NotNull World world);
/** /**
* Get the crafted item using the list of {@link ItemStack} provided. * Get the crafted item using the list of {@link ItemStack} provided.
@ -1046,7 +1046,7 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi
* an ItemStack of {@link Material#AIR} is returned. * an ItemStack of {@link Material#AIR} is returned.
*/ */
@NotNull @NotNull
public ItemStack craftItem(@NotNull ItemStack[] craftingMatrix, @NotNull World world, @NotNull Player player); public ItemStack craftItem(@NotNull ItemStack @NotNull [] craftingMatrix, @NotNull World world, @NotNull Player player);
/** /**
* Get the crafted item using the list of {@link ItemStack} provided. * Get the crafted item using the list of {@link ItemStack} provided.
@ -1067,7 +1067,7 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi
* an ItemStack of {@link Material#AIR} is returned. * an ItemStack of {@link Material#AIR} is returned.
*/ */
@NotNull @NotNull
public ItemStack craftItem(@NotNull ItemStack[] craftingMatrix, @NotNull World world); public ItemStack craftItem(@NotNull ItemStack @NotNull [] craftingMatrix, @NotNull World world);
/** /**
* Get the crafted item using the list of {@link ItemStack} provided. * Get the crafted item using the list of {@link ItemStack} provided.
@ -1094,7 +1094,7 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi
* @return resulting {@link ItemCraftResult} containing the resulting item, matrix and any overflow items. * @return resulting {@link ItemCraftResult} containing the resulting item, matrix and any overflow items.
*/ */
@NotNull @NotNull
public ItemCraftResult craftItemResult(@NotNull ItemStack[] craftingMatrix, @NotNull World world, @NotNull Player player); public ItemCraftResult craftItemResult(@NotNull ItemStack @NotNull [] craftingMatrix, @NotNull World world, @NotNull Player player);
/** /**
* Get the crafted item using the list of {@link ItemStack} provided. * Get the crafted item using the list of {@link ItemStack} provided.
@ -1114,7 +1114,7 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi
* @return resulting {@link ItemCraftResult} containing the resulting item, matrix and any overflow items. * @return resulting {@link ItemCraftResult} containing the resulting item, matrix and any overflow items.
*/ */
@NotNull @NotNull
public ItemCraftResult craftItemResult(@NotNull ItemStack[] craftingMatrix, @NotNull World world); public ItemCraftResult craftItemResult(@NotNull ItemStack @NotNull [] craftingMatrix, @NotNull World world);
/** /**
* Get an iterator through the list of crafting recipes. * Get an iterator through the list of crafting recipes.
@ -1503,8 +1503,7 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi
* *
* @return an array containing all previous players * @return an array containing all previous players
*/ */
@NotNull public @NotNull OfflinePlayer @NotNull [] getOfflinePlayers();
public OfflinePlayer[] getOfflinePlayers();
/** /**
* Gets the {@link Messenger} responsible for this server. * Gets the {@link Messenger} responsible for this server.
@ -2057,16 +2056,14 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi
* *
* @return current server TPS (1m, 5m, 15m in Paper-Server) * @return current server TPS (1m, 5m, 15m in Paper-Server)
*/ */
@NotNull public double @NotNull [] getTPS();
public double[] getTPS();
/** /**
* Get a sample of the servers last tick times (in nanos) * Get a sample of the servers last tick times (in nanos)
* *
* @return A sample of the servers last tick times (in nanos) * @return A sample of the servers last tick times (in nanos)
*/ */
@NotNull long @NotNull [] getTickTimes();
long[] getTickTimes();
/** /**
* Get the average tick time (in millis) * Get the average tick time (in millis)

View File

@ -1050,9 +1050,16 @@ public interface Tag<T extends Keyed> extends Keyed {
*/ */
Tag<Material> ITEMS_REPAIRS_WOLF_ARMOR = Bukkit.getTag(REGISTRY_ITEMS, NamespacedKey.minecraft("repairs_wolf_armor"), Material.class); Tag<Material> ITEMS_REPAIRS_WOLF_ARMOR = Bukkit.getTag(REGISTRY_ITEMS, NamespacedKey.minecraft("repairs_wolf_armor"), Material.class);
/** /**
* Vanilla item tag representing all furnace materials. * Vanilla item tag representing all stone based materials for crafting.
*/ */
Tag<Material> ITEMS_FURNACE_MATERIALS = Bukkit.getTag(REGISTRY_ITEMS, NamespacedKey.minecraft("furnace_materials"), Material.class); Tag<Material> ITEMS_STONE_CRAFTING_MATERIALS = Bukkit.getTag(REGISTRY_ITEMS, NamespacedKey.minecraft("stone_crafting_materials"), Material.class);
/**
* Vanilla item tag representing all furnace materials.
*
* @deprecated partially replaced by {@link #ITEMS_STONE_CRAFTING_MATERIALS}
*/
@Deprecated(since = "1.16.2", forRemoval = true)
Tag<Material> ITEMS_FURNACE_MATERIALS = ITEMS_STONE_CRAFTING_MATERIALS;
/** /**
* Vanilla item tag representing all compasses. * Vanilla item tag representing all compasses.
*/ */

View File

@ -1,6 +1,7 @@
package org.bukkit; package org.bukkit;
import com.google.common.collect.Multimap; import com.google.common.collect.Multimap;
import io.papermc.paper.entity.EntitySerializationFlag;
import org.bukkit.advancement.Advancement; import org.bukkit.advancement.Advancement;
import org.bukkit.attribute.Attribute; import org.bukkit.attribute.Attribute;
import org.bukkit.attribute.AttributeModifier; import org.bukkit.attribute.AttributeModifier;
@ -9,7 +10,9 @@ import org.bukkit.block.data.BlockData;
import org.bukkit.damage.DamageEffect; import org.bukkit.damage.DamageEffect;
import org.bukkit.damage.DamageSource; import org.bukkit.damage.DamageSource;
import org.bukkit.damage.DamageType; import org.bukkit.damage.DamageType;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType; import org.bukkit.entity.EntityType;
import org.bukkit.event.entity.CreatureSpawnEvent;
import org.bukkit.inventory.CreativeCategory; import org.bukkit.inventory.CreativeCategory;
import org.bukkit.inventory.EquipmentSlot; import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
@ -123,10 +126,6 @@ public interface UnsafeValues {
@Deprecated(since = "1.20.2", forRemoval = true) @Deprecated(since = "1.20.2", forRemoval = true)
PotionType.InternalPotionData getInternalPotionData(NamespacedKey key); PotionType.InternalPotionData getInternalPotionData(NamespacedKey key);
@ApiStatus.Internal
@Nullable
DamageEffect getDamageEffect(@NotNull String key);
/** /**
* Create a new {@link DamageSource.Builder}. * Create a new {@link DamageSource.Builder}.
* *
@ -198,13 +197,81 @@ public interface UnsafeValues {
*/ */
@NotNull ItemStack deserializeItemFromJson(@NotNull com.google.gson.JsonObject data) throws IllegalArgumentException; @NotNull ItemStack deserializeItemFromJson(@NotNull com.google.gson.JsonObject data) throws IllegalArgumentException;
byte[] serializeEntity(org.bukkit.entity.Entity entity); /**
* Serializes the provided entity.
*
* @param entity entity
* @return serialized entity data
* @see #serializeEntity(Entity, EntitySerializationFlag...)
* @see #deserializeEntity(byte[], World, boolean, boolean)
* @throws IllegalArgumentException if couldn't serialize the entity
* @since 1.17.1
*/
default byte @NotNull [] serializeEntity(@NotNull Entity entity) {
return serializeEntity(entity, new EntitySerializationFlag[0]);
}
default org.bukkit.entity.Entity deserializeEntity(byte[] data, World world) { /**
* Serializes the provided entity.
*
* @param entity entity
* @param serializationFlags serialization flags
* @return serialized entity data
* @throws IllegalArgumentException if couldn't serialize the entity
* @see #deserializeEntity(byte[], World, boolean, boolean)
* @since 1.21.4
*/
byte @NotNull [] serializeEntity(@NotNull Entity entity, @NotNull EntitySerializationFlag... serializationFlags);
/**
* Deserializes the entity from data.
* <br>The entity's {@link java.util.UUID} as well as passengers will not be preserved.
*
* @param data serialized entity data
* @param world world
* @return deserialized entity
* @throws IllegalArgumentException if invalid serialized entity data provided
* @see #deserializeEntity(byte[], World, boolean, boolean)
* @see #serializeEntity(Entity, EntitySerializationFlag...)
* @see Entity#spawnAt(Location, CreatureSpawnEvent.SpawnReason)
* @since 1.17.1
*/
default @NotNull Entity deserializeEntity(byte @NotNull [] data, @NotNull World world) {
return deserializeEntity(data, world, false); return deserializeEntity(data, world, false);
} }
org.bukkit.entity.Entity deserializeEntity(byte[] data, World world, boolean preserveUUID); /**
* Deserializes the entity from data.
* <br>The entity's passengers will not be preserved.
*
* @param data serialized entity data
* @param world world
* @param preserveUUID whether to preserve the entity's uuid
* @return deserialized entity
* @throws IllegalArgumentException if invalid serialized entity data provided
* @see #deserializeEntity(byte[], World, boolean, boolean)
* @see #serializeEntity(Entity, EntitySerializationFlag...)
* @see Entity#spawnAt(Location, CreatureSpawnEvent.SpawnReason)
* @since 1.17.1
*/
default @NotNull Entity deserializeEntity(byte @NotNull [] data, @NotNull World world, boolean preserveUUID) {
return deserializeEntity(data, world, preserveUUID, false);
}
/**
* Deserializes the entity from data.
*
* @param data serialized entity data
* @param world world
* @param preserveUUID whether to preserve uuids of the entity and its passengers
* @param preservePassengers whether to preserve passengers
* @return deserialized entity
* @throws IllegalArgumentException if invalid serialized entity data provided
* @see #serializeEntity(Entity, EntitySerializationFlag...)
* @see Entity#spawnAt(Location, CreatureSpawnEvent.SpawnReason)
* @since 1.21.4
*/
@NotNull Entity deserializeEntity(byte @NotNull [] data, @NotNull World world, boolean preserveUUID, boolean preservePassengers);
/** /**
* Creates and returns the next EntityId available. * Creates and returns the next EntityId available.

View File

@ -346,8 +346,7 @@ public interface World extends RegionAccessor, WorldInfo, PluginMessageRecipient
* *
* @return Chunk[] containing all loaded chunks * @return Chunk[] containing all loaded chunks
*/ */
@NotNull public @NotNull Chunk @NotNull [] getLoadedChunks();
public Chunk[] getLoadedChunks();
/** /**
* Loads the specified {@link Chunk}. * Loads the specified {@link Chunk}.
@ -3563,8 +3562,7 @@ public interface World extends RegionAccessor, WorldInfo, PluginMessageRecipient
* *
* @return An array of {@link GameRule} names. * @return An array of {@link GameRule} names.
*/ */
@NotNull public @NotNull String @NotNull [] getGameRules();
public String[] getGameRules();
/** /**
* Gets the current state of the specified rule * Gets the current state of the specified rule

View File

@ -89,7 +89,7 @@ public interface Attribute extends OldEnum<Attribute>, Keyed, Translatable, net.
*/ */
Attribute JUMP_STRENGTH = getAttribute("jump_strength"); Attribute JUMP_STRENGTH = getAttribute("jump_strength");
/** /**
* How long an entity remains burning after ingition. * How long an entity remains burning after ignition.
*/ */
Attribute BURNING_TIME = getAttribute("burning_time"); Attribute BURNING_TIME = getAttribute("burning_time");
/** /**

View File

@ -66,7 +66,7 @@ public abstract class Command {
* @param args All arguments passed to the command, split via ' ' * @param args All arguments passed to the command, split via ' '
* @return true if the command was successful, otherwise false * @return true if the command was successful, otherwise false
*/ */
public abstract boolean execute(@NotNull CommandSender sender, @NotNull String commandLabel, @NotNull String[] args); public abstract boolean execute(@NotNull CommandSender sender, @NotNull String commandLabel, @NotNull String @NotNull [] args);
/** /**
* Executed on tab completion for this command, returning a list of * Executed on tab completion for this command, returning a list of
@ -80,7 +80,7 @@ public abstract class Command {
* @throws IllegalArgumentException if sender, alias, or args is null * @throws IllegalArgumentException if sender, alias, or args is null
*/ */
@NotNull @NotNull
public List<String> tabComplete(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] args) throws IllegalArgumentException { public List<String> tabComplete(@NotNull CommandSender sender, @NotNull String alias, @NotNull String @NotNull [] args) throws IllegalArgumentException {
return tabComplete0(sender, alias, args, null); return tabComplete0(sender, alias, args, null);
} }
@ -97,7 +97,7 @@ public abstract class Command {
* @throws IllegalArgumentException if sender, alias, or args is null * @throws IllegalArgumentException if sender, alias, or args is null
*/ */
@NotNull @NotNull
public List<String> tabComplete(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] args, @Nullable Location location) throws IllegalArgumentException { public List<String> tabComplete(@NotNull CommandSender sender, @NotNull String alias, @NotNull String @NotNull [] args, @Nullable Location location) throws IllegalArgumentException {
return tabComplete(sender, alias, args); return tabComplete(sender, alias, args);
} }

View File

@ -19,5 +19,5 @@ public interface CommandExecutor {
* @param args Passed command arguments * @param args Passed command arguments
* @return true if a valid command, otherwise false * @return true if a valid command, otherwise false
*/ */
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args); public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String @NotNull [] args);
} }

View File

@ -22,7 +22,7 @@ import org.jetbrains.annotations.Nullable;
public interface MessageCommandSender extends CommandSender { public interface MessageCommandSender extends CommandSender {
@Override @Override
default void sendMessage(@NotNull String[] messages) { default void sendMessage(@NotNull String @NotNull [] messages) {
for (String message : messages) { for (String message : messages) {
sendMessage(message); sendMessage(message);
} }
@ -34,7 +34,7 @@ public interface MessageCommandSender extends CommandSender {
} }
@Override @Override
default void sendMessage(@Nullable UUID sender, @NotNull String[] messages) { default void sendMessage(@Nullable UUID sender, @NotNull String @NotNull [] messages) {
for (String message : messages) { for (String message : messages) {
sendMessage(message); sendMessage(message);
} }

View File

@ -18,8 +18,7 @@ public class MultipleCommandAlias extends Command {
* *
* @return commands associated with alias * @return commands associated with alias
*/ */
@NotNull public @NotNull Command @NotNull [] getCommands() {
public Command[] getCommands() {
return commands; return commands;
} }

View File

@ -23,5 +23,5 @@ public interface TabCompleter {
* to default to the command executor * to default to the command executor
*/ */
@Nullable @Nullable
public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args); public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String @NotNull [] args);
} }

View File

@ -1,7 +1,7 @@
package org.bukkit.damage; package org.bukkit.damage;
import com.google.common.base.Preconditions; import com.google.common.base.Preconditions;
import org.bukkit.Bukkit; import io.papermc.paper.InternalAPIBridge;
import org.bukkit.Sound; import org.bukkit.Sound;
import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@ -40,7 +40,7 @@ public interface DamageEffect {
@NotNull @NotNull
private static DamageEffect getDamageEffect(@NotNull String key) { private static DamageEffect getDamageEffect(@NotNull String key) {
return Preconditions.checkNotNull(Bukkit.getUnsafe().getDamageEffect(key), "No DamageEffect found for %s. This is a bug.", key); return Preconditions.checkNotNull(InternalAPIBridge.get().getDamageEffect(key), "No DamageEffect found for %s. This is a bug.", key);
} }
/** /**

View File

@ -14,6 +14,7 @@ import org.bukkit.World;
import org.bukkit.block.BlockFace; import org.bukkit.block.BlockFace;
import org.bukkit.block.PistonMoveReaction; import org.bukkit.block.PistonMoveReaction;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.bukkit.event.entity.CreatureSpawnEvent;
import org.bukkit.event.entity.EntityDamageEvent; import org.bukkit.event.entity.EntityDamageEvent;
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause; import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
import org.bukkit.material.Directional; import org.bukkit.material.Directional;
@ -1072,11 +1073,12 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent
* <p> * <p>
* Also, this method will fire the same events as a normal entity spawn. * Also, this method will fire the same events as a normal entity spawn.
* *
* @param location The location to spawn the entity at. * @param location the location to spawn the entity at
* @return Whether the entity was successfully spawned. * @return whether the entity was successfully spawned
* @since 1.17.1
*/ */
public default boolean spawnAt(@NotNull Location location) { default boolean spawnAt(@NotNull Location location) {
return spawnAt(location, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DEFAULT); return spawnAt(location, CreatureSpawnEvent.SpawnReason.DEFAULT);
} }
/** /**
@ -1086,11 +1088,12 @@ public interface Entity extends Metadatable, CommandSender, Nameable, Persistent
* <p> * <p>
* Also, this method will fire the same events as a normal entity spawn. * Also, this method will fire the same events as a normal entity spawn.
* *
* @param location The location to spawn the entity at. * @param location the location to spawn the entity at
* @param reason The reason for the entity being spawned. * @param reason the reason for the entity being spawned
* @return Whether the entity was successfully spawned. * @return whether the entity was successfully spawned
* @since 1.17.1
*/ */
public boolean spawnAt(@NotNull Location location, @NotNull org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason reason); boolean spawnAt(@NotNull Location location, @NotNull CreatureSpawnEvent.SpawnReason reason);
/** /**
* Check if entity is inside powdered snow. * Check if entity is inside powdered snow.

View File

@ -2,10 +2,12 @@ package org.bukkit.entity;
import java.util.Collection; import java.util.Collection;
import java.util.Set; import java.util.Set;
import java.util.function.Consumer;
import org.bukkit.GameMode; import org.bukkit.GameMode;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.NamespacedKey; import org.bukkit.NamespacedKey;
import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.inventory.Inventory; import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryHolder; import org.bukkit.inventory.InventoryHolder;
import org.bukkit.inventory.InventoryView; import org.bukkit.inventory.InventoryView;
@ -14,6 +16,7 @@ import org.bukkit.inventory.MainHand;
import org.bukkit.inventory.Merchant; import org.bukkit.inventory.Merchant;
import org.bukkit.inventory.PlayerInventory; import org.bukkit.inventory.PlayerInventory;
import org.bukkit.inventory.meta.FireworkMeta; import org.bukkit.inventory.meta.FireworkMeta;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@ -703,8 +706,115 @@ public interface HumanEntity extends LivingEntity, AnimalTamer, InventoryHolder
* *
* @param dropAll True to drop entire stack, false to drop 1 of the stack * @param dropAll True to drop entire stack, false to drop 1 of the stack
* @return True if item was dropped successfully * @return True if item was dropped successfully
* @apiNote You should instead use {@link #dropItem(EquipmentSlot, int)} or {@link #dropItem(EquipmentSlot)} with a {@link EquipmentSlot#HAND} parameter.
*/ */
public boolean dropItem(boolean dropAll); @ApiStatus.Obsolete(since = "1.21.4")
boolean dropItem(boolean dropAll);
/**
* Makes the player drop all items from their inventory based on the inventory slot.
*
* @param slot the equipment slot to drop
* @return the dropped item entity, or null if the action was unsuccessful
*/
@Nullable
default Item dropItem(final int slot) {
return this.dropItem(slot, Integer.MAX_VALUE);
}
/**
* Makes the player drop an item from their inventory based on the inventory slot.
*
* @param slot the slot to drop
* @param amount the number of items to drop from this slot. Values below one always return null
* @return the dropped item entity, or null if the action was unsuccessful
* @throws IllegalArgumentException if the slot is negative or bigger than the player's inventory
*/
@Nullable
default Item dropItem(final int slot, final int amount) {
return this.dropItem(slot, amount, false, null);
}
/**
* Makes the player drop an item from their inventory based on the inventory slot.
*
* @param slot the slot to drop
* @param amount the number of items to drop from this slot. Values below one always return null
* @param throwRandomly controls the randomness of the dropped items velocity, where {@code true} mimics dropped
* items during a player's death, while {@code false} acts like a normal item drop.
* @param entityOperation the function to be run before adding the entity into the world
* @return the dropped item entity, or null if the action was unsuccessful
* @throws IllegalArgumentException if the slot is negative or bigger than the player's inventory
*/
@Nullable
Item dropItem(int slot, int amount, boolean throwRandomly, @Nullable Consumer<Item> entityOperation);
/**
* Makes the player drop all items from their inventory based on the equipment slot.
*
* @param slot the equipment slot to drop
* @return the dropped item entity, or null if the action was unsuccessful
*/
@Nullable
default Item dropItem(final @NotNull EquipmentSlot slot) {
return this.dropItem(slot, Integer.MAX_VALUE);
}
/**
* Makes the player drop an item from their inventory based on the equipment slot.
*
* @param slot the equipment slot to drop
* @param amount the amount of items to drop from this equipment slot. Values below one always return null
* @return the dropped item entity, or null if the action was unsuccessful
*/
@Nullable
default Item dropItem(final @NotNull EquipmentSlot slot, final int amount) {
return this.dropItem(slot, amount, false, null);
}
/**
* Makes the player drop an item from their inventory based on the equipment slot.
*
* @param slot the equipment slot to drop
* @param amount The amount of items to drop from this equipment slot. Values below one always return null
* @param throwRandomly controls the randomness of the dropped items velocity, where {@code true} mimics dropped
* items during a player's death, while {@code false} acts like a normal item drop.
* @param entityOperation the function to be run before adding the entity into the world
* @return the dropped item entity, or null if the action was unsuccessful
*/
@Nullable
Item dropItem(@NotNull EquipmentSlot slot, int amount, boolean throwRandomly, @Nullable Consumer<Item> entityOperation);
/**
* Makes the player drop any arbitrary {@link ItemStack}, independently of whether the player actually
* has that item in their inventory.
* <p>
* This method modifies neither the item nor the player's inventory.
* Item removal has to be handled by the method caller.
*
* @param itemStack the itemstack to drop
* @return the dropped item entity, or null if the action was unsuccessful
*/
@Nullable
default Item dropItem(final @NotNull ItemStack itemStack) {
return this.dropItem(itemStack, false, null);
}
/**
* Makes the player drop any arbitrary {@link ItemStack}, independently of whether the player actually
* has that item in their inventory.
* <p>
* This method modifies neither the item nor the player's inventory.
* Item removal has to be handled by the method caller.
*
* @param itemStack the itemstack to drop
* @param throwRandomly controls the randomness of the dropped items velocity, where {@code true} mimics dropped
* items during a player's death, while {@code false} acts like a normal item drop.
* @param entityOperation the function to be run before adding the entity into the world
* @return the dropped item entity, or null if the action was unsuccessful
*/
@Nullable
Item dropItem(final @NotNull ItemStack itemStack, boolean throwRandomly, @Nullable Consumer<Item> entityOperation);
/** /**
* Gets the players current exhaustion level. * Gets the players current exhaustion level.

View File

@ -2308,7 +2308,7 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
* long. * long.
*/ */
@Deprecated // Paper - adventure @Deprecated // Paper - adventure
public void setResourcePack(@NotNull String url, @Nullable byte[] hash); public void setResourcePack(@NotNull String url, byte @Nullable [] hash);
/** /**
* Request that the player's client download and switch resource packs. * Request that the player's client download and switch resource packs.
@ -2353,7 +2353,7 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
* long. * long.
*/ */
@Deprecated // Paper - adventure @Deprecated // Paper - adventure
public void setResourcePack(@NotNull String url, @Nullable byte[] hash, @Nullable String prompt); public void setResourcePack(@NotNull String url, byte @Nullable [] hash, @Nullable String prompt);
// Paper start // Paper start
/** /**
@ -2447,7 +2447,7 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
* @deprecated in favour of {@link #sendResourcePacks(net.kyori.adventure.resource.ResourcePackRequest)} * @deprecated in favour of {@link #sendResourcePacks(net.kyori.adventure.resource.ResourcePackRequest)}
*/ */
@Deprecated // Paper - adventure @Deprecated // Paper - adventure
public void setResourcePack(@NotNull String url, @Nullable byte[] hash, boolean force); public void setResourcePack(@NotNull String url, byte @Nullable [] hash, boolean force);
/** /**
* Request that the player's client download and switch resource packs. * Request that the player's client download and switch resource packs.
@ -2494,7 +2494,7 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
* @deprecated in favour of {@link #sendResourcePacks(net.kyori.adventure.resource.ResourcePackRequest)} * @deprecated in favour of {@link #sendResourcePacks(net.kyori.adventure.resource.ResourcePackRequest)}
*/ */
@Deprecated // Paper @Deprecated // Paper
public void setResourcePack(@NotNull String url, @Nullable byte[] hash, @Nullable String prompt, boolean force); public void setResourcePack(@NotNull String url, byte @Nullable [] hash, @Nullable String prompt, boolean force);
// Paper start // Paper start
/** /**
@ -2592,7 +2592,7 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
* @deprecated in favour of {@link #sendResourcePacks(net.kyori.adventure.resource.ResourcePackRequest)} * @deprecated in favour of {@link #sendResourcePacks(net.kyori.adventure.resource.ResourcePackRequest)}
*/ */
@Deprecated // Paper - adventure @Deprecated // Paper - adventure
public void setResourcePack(@NotNull UUID id, @NotNull String url, @Nullable byte[] hash, @Nullable String prompt, boolean force); public void setResourcePack(@NotNull UUID id, @NotNull String url, byte @Nullable [] hash, @Nullable String prompt, boolean force);
// Paper start // Paper start
/** /**

View File

@ -203,8 +203,7 @@ public class HandlerList {
* *
* @return the array of registered listeners * @return the array of registered listeners
*/ */
@NotNull public @NotNull RegisteredListener @NotNull [] getRegisteredListeners() {
public RegisteredListener[] getRegisteredListeners() {
RegisteredListener[] handlers; RegisteredListener[] handlers;
while ((handlers = this.handlers) == null) bake(); // This prevents fringe cases of returning null while ((handlers = this.handlers) == null) bake(); // This prevents fringe cases of returning null
return handlers; return handlers;

View File

@ -241,6 +241,9 @@ public class PlayerInteractEvent extends PlayerEvent implements Cancellable {
@Nullable @Nullable
@Deprecated // Paper @Deprecated // Paper
public Vector getClickedPosition() { public Vector getClickedPosition() {
if (this.clickedPosistion == null) {
return null;
}
return clickedPosistion.clone(); return clickedPosistion.clone();
} }

View File

@ -329,7 +329,7 @@ public interface EntityEquipment {
* *
* @param items The items to set the armor as. Individual items may be null. * @param items The items to set the armor as. Individual items may be null.
*/ */
void setArmorContents(@NotNull ItemStack[] items); void setArmorContents(@NotNull ItemStack @NotNull [] items);
/** /**
* Clears the entity of all armor and held items * Clears the entity of all armor and held items

View File

@ -24,8 +24,7 @@ public interface ItemCraftResult {
* *
* @return resulting matrix * @return resulting matrix
*/ */
@NotNull public @NotNull ItemStack @NotNull [] getResultingMatrix();
public ItemStack[] getResultingMatrix();
/** /**
* Gets the overflowed items for items that don't fit back into the crafting * Gets the overflowed items for items that don't fit back into the crafting

View File

@ -5,6 +5,7 @@ import com.google.common.collect.ImmutableMap;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.Locale; import java.util.Locale;
import java.util.Map; import java.util.Map;
import net.kyori.adventure.text.Component;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.NamespacedKey; import org.bukkit.NamespacedKey;
@ -710,6 +711,17 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, Translat
return Bukkit.getServer().getItemFactory().displayName(this); return Bukkit.getServer().getItemFactory().displayName(this);
} }
/**
* Gets the effective name of this item stack shown to player in inventory.
* It takes into account the display name (with italics) from the item meta,
* the potion effect, translatable name, rarity etc.
*
* @return the effective name of this item stack
*/
public @NotNull Component effectiveName() {
return this.craftDelegate.effectiveName();
}
/** /**
* Minecraft updates are converting simple item stacks into more complex NBT oriented Item Stacks. * Minecraft updates are converting simple item stacks into more complex NBT oriented Item Stacks.
* *
@ -732,8 +744,7 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, Translat
* @param bytes bytes representing an item in NBT * @param bytes bytes representing an item in NBT
* @return ItemStack migrated to this version of Minecraft if needed. * @return ItemStack migrated to this version of Minecraft if needed.
*/ */
@NotNull public static @NotNull ItemStack deserializeBytes(final byte @NotNull [] bytes) {
public static ItemStack deserializeBytes(@NotNull byte[] bytes) {
return org.bukkit.Bukkit.getUnsafe().deserializeItem(bytes); return org.bukkit.Bukkit.getUnsafe().deserializeItem(bytes);
} }
@ -742,8 +753,7 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, Translat
* use the built in data converter instead of bukkits dangerous serialization system. * use the built in data converter instead of bukkits dangerous serialization system.
* @return bytes representing this item in NBT. * @return bytes representing this item in NBT.
*/ */
@NotNull public byte @NotNull [] serializeAsBytes() {
public byte[] serializeAsBytes() {
return org.bukkit.Bukkit.getUnsafe().serializeItem(this); return org.bukkit.Bukkit.getUnsafe().serializeItem(this);
} }

View File

@ -118,7 +118,7 @@ public interface PlayerInventory extends Inventory {
* *
* @param items The ItemStacks to use as armour * @param items The ItemStacks to use as armour
*/ */
public void setArmorContents(@Nullable ItemStack[] items); public void setArmorContents(@Nullable ItemStack @NotNull [] items);
/** /**
* Put the given ItemStacks into the extra slots * Put the given ItemStacks into the extra slots
@ -127,7 +127,7 @@ public interface PlayerInventory extends Inventory {
* *
* @param items The ItemStacks to use as extra * @param items The ItemStacks to use as extra
*/ */
public void setExtraContents(@Nullable ItemStack[] items); public void setExtraContents(@Nullable ItemStack @NotNull [] items);
/** /**
* Put the given ItemStack into the helmet slot. This does not check if * Put the given ItemStack into the helmet slot. This does not check if

View File

@ -234,8 +234,7 @@ public class ShapedRecipe extends CraftingRecipe {
* @return The recipe's shape. * @return The recipe's shape.
* @throws NullPointerException when not set yet * @throws NullPointerException when not set yet
*/ */
@NotNull public @NotNull String @NotNull [] getShape() {
public String[] getShape() {
return rows.clone(); return rows.clone();
} }
} }

View File

@ -4,6 +4,7 @@ import org.bukkit.enchantments.EnchantmentOffer;
import org.bukkit.inventory.EnchantingInventory; import org.bukkit.inventory.EnchantingInventory;
import org.bukkit.inventory.InventoryView; import org.bukkit.inventory.InventoryView;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jspecify.annotations.Nullable;
/** /**
* An instance of {@link InventoryView} which provides extra methods related to * An instance of {@link InventoryView} which provides extra methods related to
@ -36,8 +37,7 @@ public interface EnchantmentView extends InventoryView {
* *
* @return The enchantment offers that are provided * @return The enchantment offers that are provided
*/ */
@NotNull @Nullable EnchantmentOffer @NotNull [] getOffers();
EnchantmentOffer[] getOffers();
/** /**
* Sets the offers to provide to the player. * Sets the offers to provide to the player.
@ -45,5 +45,5 @@ public interface EnchantmentView extends InventoryView {
* @param offers The offers to provide * @param offers The offers to provide
* @throws IllegalArgumentException if the array length isn't 3 * @throws IllegalArgumentException if the array length isn't 3
*/ */
void setOffers(@NotNull EnchantmentOffer[] offers) throws IllegalArgumentException; void setOffers(@Nullable EnchantmentOffer @NotNull [] offers) throws IllegalArgumentException;
} }

View File

@ -16,7 +16,7 @@ public interface Lootable {
/** /**
* Set the loot table for a container or entity. * Set the loot table for a container or entity.
* <br> * <br>
* To remove a loot table use null. * If the provided loot table is null, the loot table will be reset to its default behavior.
* *
* @param table the Loot Table this {@link org.bukkit.block.Container} or * @param table the Loot Table this {@link org.bukkit.block.Container} or
* {@link org.bukkit.entity.Mob} will have. * {@link org.bukkit.entity.Mob} will have.
@ -38,6 +38,8 @@ public interface Lootable {
// Paper start // Paper start
/** /**
* Set the loot table and seed for a container or entity at the same time. * Set the loot table and seed for a container or entity at the same time.
* <br>
* If the provided loot table is null, the loot table will be reset to its default behavior.
* *
* @param table the Loot Table this {@link org.bukkit.block.Container} or {@link org.bukkit.entity.Mob} will have. * @param table the Loot Table this {@link org.bukkit.block.Container} or {@link org.bukkit.entity.Mob} will have.
* @param seed the seed to used to generate loot. Default is 0. * @param seed the seed to used to generate loot. Default is 0.
@ -53,7 +55,8 @@ public interface Lootable {
} }
/** /**
* Clears the associated Loot Table to this object * Clears the associated Loot Table to this object, essentially resetting it to default
* @see #setLootTable(LootTable)
*/ */
default void clearLootTable() { default void clearLootTable() {
this.setLootTable(null); this.setLootTable(null);

View File

@ -112,7 +112,7 @@ public class MapFont {
private final int height; private final int height;
private final boolean[] data; private final boolean[] data;
public CharacterSprite(int width, int height, @NotNull boolean[] data) { public CharacterSprite(int width, int height, boolean @NotNull [] data) {
this.width = width; this.width = width;
this.height = height; this.height = height;
this.data = data; this.data = data;

View File

@ -1,24 +1,15 @@
package org.bukkit.plugin; package org.bukkit.plugin;
import com.google.common.base.Preconditions;
import io.papermc.paper.event.executor.EventExecutorFactory;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import org.bukkit.event.Event; import org.bukkit.event.Event;
import org.bukkit.event.EventException; import org.bukkit.event.EventException;
import org.bukkit.event.Listener; import org.bukkit.event.Listener;
import org.bukkit.plugin.java.JavaPlugin;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
// Paper start
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.function.Function;
import com.destroystokyo.paper.event.executor.MethodHandleEventExecutor;
import com.destroystokyo.paper.event.executor.StaticMethodHandleEventExecutor;
import com.destroystokyo.paper.event.executor.asm.ASMEventExecutorGenerator;
import com.destroystokyo.paper.event.executor.asm.ClassDefiner;
import com.google.common.base.Preconditions;
// Paper end
/** /**
* Interface which defines the class for event call backs to plugins * Interface which defines the class for event call backs to plugins
*/ */
@ -26,69 +17,25 @@ public interface EventExecutor {
public void execute(@NotNull Listener listener, @NotNull Event event) throws EventException; public void execute(@NotNull Listener listener, @NotNull Event event) throws EventException;
// Paper start // Paper start
ConcurrentMap<Method, Class<? extends EventExecutor>> eventExecutorMap = new ConcurrentHashMap<Method, Class<? extends EventExecutor>>() {
@NotNull
@Override
public Class<? extends EventExecutor> computeIfAbsent(@NotNull Method key, @NotNull Function<? super Method, ? extends Class<? extends EventExecutor>> mappingFunction) {
Class<? extends EventExecutor> executorClass = get(key);
if (executorClass != null)
return executorClass;
//noinspection SynchronizationOnLocalVariableOrMethodParameter
synchronized (key) {
executorClass = get(key);
if (executorClass != null)
return executorClass;
return super.computeIfAbsent(key, mappingFunction);
}
}
};
@NotNull @NotNull
public static EventExecutor create(@NotNull Method m, @NotNull Class<? extends Event> eventClass) { static EventExecutor create(@NotNull Method m, @NotNull Class<? extends Event> eventClass) {
Preconditions.checkNotNull(m, "Null method"); Preconditions.checkNotNull(m, "Null method");
Preconditions.checkArgument(m.getParameterCount() != 0, "Incorrect number of arguments %s", m.getParameterCount()); Preconditions.checkArgument(m.getParameterCount() != 0, "Incorrect number of arguments %s", m.getParameterCount());
Preconditions.checkArgument(m.getParameterTypes()[0] == eventClass, "First parameter %s doesn't match event class %s", m.getParameterTypes()[0], eventClass); Preconditions.checkArgument(m.getParameterTypes()[0] == eventClass, "First parameter %s doesn't match event class %s", m.getParameterTypes()[0], eventClass);
ClassDefiner definer = ClassDefiner.getInstance();
if (m.getReturnType() != Void.TYPE) { if (m.getReturnType() != Void.TYPE) {
final org.bukkit.plugin.java.JavaPlugin plugin = org.bukkit.plugin.java.JavaPlugin.getProvidingPlugin(m.getDeclaringClass()); final JavaPlugin plugin = JavaPlugin.getProvidingPlugin(m.getDeclaringClass());
org.bukkit.Bukkit.getLogger().warning("@EventHandler method " + m.getDeclaringClass().getName() + (Modifier.isStatic(m.getModifiers()) ? '.' : '#') + m.getName() org.bukkit.Bukkit.getLogger().warning("@EventHandler method " + m.getDeclaringClass().getName() + (Modifier.isStatic(m.getModifiers()) ? '.' : '#') + m.getName()
+ " returns non-void type " + m.getReturnType().getName() + ". This is unsupported behavior and will no longer work in a future version of Paper." + " returns non-void type " + m.getReturnType().getName() + ". This is unsupported behavior and will no longer work in a future version of Paper."
+ " This should be reported to the developers of " + plugin.getPluginMeta().getDisplayName() + " (" + String.join(",", plugin.getPluginMeta().getAuthors()) + ')'); + " This should be reported to the developers of " + plugin.getPluginMeta().getDisplayName() + " (" + String.join(",", plugin.getPluginMeta().getAuthors()) + ')');
} }
if (Modifier.isStatic(m.getModifiers())) { if (!m.trySetAccessible()) {
return new StaticMethodHandleEventExecutor(eventClass, m); final JavaPlugin plugin = JavaPlugin.getProvidingPlugin(m.getDeclaringClass());
} else if (definer.isBypassAccessChecks() || Modifier.isPublic(m.getDeclaringClass().getModifiers()) && Modifier.isPublic(m.getModifiers())) { throw new AssertionError(
// get the existing generated EventExecutor class for the Method or generate one "@EventHandler method " + m.getDeclaringClass().getName() + (Modifier.isStatic(m.getModifiers()) ? '.' : '#') + m.getName() + " is not accessible."
Class<? extends EventExecutor> executorClass = eventExecutorMap.computeIfAbsent(m, (__) -> { + " This should be reported to the developers of " + plugin.getDescription().getName() + " (" + String.join(",", plugin.getDescription().getAuthors()) + ')'
String name = ASMEventExecutorGenerator.generateName(); );
byte[] classData = ASMEventExecutorGenerator.generateEventExecutor(m, name);
return definer.defineClass(m.getDeclaringClass().getClassLoader(), name, classData).asSubclass(EventExecutor.class);
});
try {
EventExecutor asmExecutor = executorClass.newInstance();
// Define a wrapper to conform to bukkit stupidity (passing in events that don't match and wrapper exception)
return new EventExecutor() {
@Override
public void execute(@NotNull Listener listener, @NotNull Event event) throws EventException {
if (!eventClass.isInstance(event)) return;
asmExecutor.execute(listener, event);
}
@Override
@NotNull
public String toString() {
return "ASMEventExecutor['" + m + "']";
}
};
} catch (InstantiationException | IllegalAccessException e) {
throw new AssertionError("Unable to initialize generated event executor", e);
}
} else {
return new MethodHandleEventExecutor(eventClass, m);
} }
return EventExecutorFactory.create(m, eventClass);
} }
// Paper end // Paper end
} }

View File

@ -319,7 +319,7 @@ public abstract class JavaPlugin extends PluginBase {
* {@inheritDoc} * {@inheritDoc}
*/ */
@Override @Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String @NotNull [] args) {
return false; return false;
} }
@ -328,7 +328,7 @@ public abstract class JavaPlugin extends PluginBase {
*/ */
@Override @Override
@Nullable @Nullable
public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias, @NotNull String[] args) { public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias, @NotNull String @NotNull [] args) {
return null; return null;
} }

View File

@ -229,5 +229,5 @@ public interface Messenger {
* @param channel Channel that the message was sent by. * @param channel Channel that the message was sent by.
* @param message Raw payload of the message. * @param message Raw payload of the message.
*/ */
public void dispatchIncomingMessage(@NotNull Player source, @NotNull String channel, @NotNull byte[] message); public void dispatchIncomingMessage(@NotNull Player source, @NotNull String channel, byte @NotNull [] message);
} }

View File

@ -17,5 +17,5 @@ public interface PluginMessageListener {
* @param player Source of the message. * @param player Source of the message.
* @param message The raw message that was sent. * @param message The raw message that was sent.
*/ */
public void onPluginMessageReceived(@NotNull String channel, @NotNull Player player, @NotNull byte[] message); public void onPluginMessageReceived(@NotNull String channel, @NotNull Player player, byte @NotNull [] message);
} }

View File

@ -27,7 +27,7 @@ public interface PluginMessageRecipient {
* @throws ChannelNotRegisteredException Thrown if the channel is not * @throws ChannelNotRegisteredException Thrown if the channel is not
* registered for this plugin. * registered for this plugin.
*/ */
public void sendPluginMessage(@NotNull Plugin source, @NotNull String channel, @NotNull byte[] message); public void sendPluginMessage(@NotNull Plugin source, @NotNull String channel, byte @NotNull [] message);
/** /**
* Gets a set containing all the Plugin Channels that this client is * Gets a set containing all the Plugin Channels that this client is

View File

@ -439,7 +439,7 @@ public class StandardMessenger implements Messenger {
} }
@Override @Override
public void dispatchIncomingMessage(@NotNull Player source, @NotNull String channel, @NotNull byte[] message) { public void dispatchIncomingMessage(@NotNull Player source, @NotNull String channel, byte @NotNull [] message) {
if (source == null) { if (source == null) {
throw new IllegalArgumentException("Player source cannot be null"); throw new IllegalArgumentException("Player source cannot be null");
} }
@ -534,7 +534,7 @@ public class StandardMessenger implements Messenger {
* @throws ChannelNotRegisteredException Thrown if the channel is not * @throws ChannelNotRegisteredException Thrown if the channel is not
* registered for this plugin. * registered for this plugin.
*/ */
public static void validatePluginMessage(@NotNull Messenger messenger, @NotNull Plugin source, @NotNull String channel, @NotNull byte[] message) { public static void validatePluginMessage(@NotNull Messenger messenger, @NotNull Plugin source, @NotNull String channel, byte @NotNull [] message) {
if (messenger == null) { if (messenger == null) {
throw new IllegalArgumentException("Messenger cannot be null"); throw new IllegalArgumentException("Messenger cannot be null");
} }

View File

@ -150,7 +150,7 @@ public class ChatPaginator {
private int pageNumber; private int pageNumber;
private int totalPages; private int totalPages;
public ChatPage(@NotNull String[] lines, int pageNumber, int totalPages) { public ChatPage(@NotNull String @NotNull [] lines, int pageNumber, int totalPages) {
this.lines = lines; this.lines = lines;
this.pageNumber = pageNumber; this.pageNumber = pageNumber;
this.totalPages = totalPages; this.totalPages = totalPages;
@ -165,7 +165,7 @@ public class ChatPaginator {
} }
@NotNull @NotNull
public String[] getLines() { public String @NotNull [] getLines() {
return lines; return lines;
} }
} }

View File

@ -12,7 +12,7 @@ public abstract class OctaveGenerator {
protected double yScale = 1; protected double yScale = 1;
protected double zScale = 1; protected double zScale = 1;
protected OctaveGenerator(@NotNull NoiseGenerator[] octaves) { protected OctaveGenerator(@NotNull NoiseGenerator @NotNull [] octaves) {
this.octaves = octaves; this.octaves = octaves;
} }
@ -90,7 +90,7 @@ public abstract class OctaveGenerator {
* @return Clone of the individual octaves * @return Clone of the individual octaves
*/ */
@NotNull @NotNull
public NoiseGenerator[] getOctaves() { public NoiseGenerator @NotNull [] getOctaves() {
return octaves.clone(); return octaves.clone();
} }

View File

@ -78,15 +78,15 @@ public class SimplexNoiseGenerator extends PerlinNoiseGenerator {
offsetW = rand.nextDouble() * 256; offsetW = rand.nextDouble() * 256;
} }
protected static double dot(@NotNull int[] g, double x, double y) { protected static double dot(int @NotNull [] g, double x, double y) {
return g[0] * x + g[1] * y; return g[0] * x + g[1] * y;
} }
protected static double dot(@NotNull int[] g, double x, double y, double z) { protected static double dot(int @NotNull [] g, double x, double y, double z) {
return g[0] * x + g[1] * y + g[2] * z; return g[0] * x + g[1] * y + g[2] * z;
} }
protected static double dot(@NotNull int[] g, double x, double y, double z, double w) { protected static double dot(int @NotNull [] g, double x, double y, double z, double w) {
return g[0] * x + g[1] * y + g[2] * z + g[3] * w; return g[0] * x + g[1] * y + g[2] * z + g[3] * w;
} }

View File

@ -205,14 +205,16 @@ public class AnnotationTest {
// Paper start - skip class if it's @NullMarked // Paper start - skip class if it's @NullMarked
private static boolean isClassNullMarked(@NotNull ClassNode clazz, @NotNull Map<String, ClassNode> allClasses) { private static boolean isClassNullMarked(@NotNull ClassNode clazz, @NotNull Map<String, ClassNode> allClasses) {
if (isClassNullMarked0(clazz)) {
return true;
}
if (clazz.nestHostClass != null) { if (clazz.nestHostClass != null) {
final ClassNode nestHostNode = allClasses.get(clazz.nestHostClass); final ClassNode nestHostNode = allClasses.get(clazz.nestHostClass);
if (nestHostNode != null) { if (nestHostNode != null) {
return isClassNullMarked0(nestHostNode); return isClassNullMarked(nestHostNode, allClasses);
} }
} }
return false;
return isClassNullMarked0(clazz);
} }
private static boolean isClassNullMarked0(@NotNull ClassNode clazz) { private static boolean isClassNullMarked0(@NotNull ClassNode clazz) {

View File

@ -11,7 +11,7 @@ plugins {
val paperMavenPublicUrl = "https://repo.papermc.io/repository/maven-public/" val paperMavenPublicUrl = "https://repo.papermc.io/repository/maven-public/"
dependencies { dependencies {
mache("io.papermc:mache:1.21.4+build.6") mache("io.papermc:mache:1.21.4+build.7")
paperclip("io.papermc:paperclip:3.0.3") paperclip("io.papermc:paperclip:3.0.3")
testRuntimeOnly("org.junit.platform:junit-platform-launcher") testRuntimeOnly("org.junit.platform:junit-platform-launcher")
} }
@ -128,7 +128,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.17.0") // Keep in sync with adventureVersion from Paper-API build file implementation("net.kyori:adventure-text-serializer-ansi:4.18.0") // Keep in sync with adventureVersion from Paper-API build file
/* /*
Required to add the missing Log4j2Plugins.dat file from log4j-core Required to add the missing Log4j2Plugins.dat file from log4j-core

View File

@ -239,7 +239,7 @@ index 0f346faa82b988e86834c38837f6f11bea7f31c6..771d6ed6a7c889c09efd4ff6e20298c8
if (blockState == null) { if (blockState == null) {
// CraftBukkit start - remove blockstate if failed (or the same) // CraftBukkit start - remove blockstate if failed (or the same)
diff --git a/net/minecraft/world/level/chunk/ChunkAccess.java b/net/minecraft/world/level/chunk/ChunkAccess.java diff --git a/net/minecraft/world/level/chunk/ChunkAccess.java b/net/minecraft/world/level/chunk/ChunkAccess.java
index 809b3c37d3749c76c3c243cd91c593d03693e9b3..860d1c9729c4ee97ec6f40f7aa969829070b27c0 100644 index c82780db7fe5b1557a7802d3111f38099be55ac1..d63d745a0220963a297cfedf1e8983aeb471a045 100644
--- a/net/minecraft/world/level/chunk/ChunkAccess.java --- a/net/minecraft/world/level/chunk/ChunkAccess.java
+++ b/net/minecraft/world/level/chunk/ChunkAccess.java +++ b/net/minecraft/world/level/chunk/ChunkAccess.java
@@ -114,14 +114,14 @@ public abstract class ChunkAccess implements BiomeManager.NoiseBiomeSource, Ligh @@ -114,14 +114,14 @@ public abstract class ChunkAccess implements BiomeManager.NoiseBiomeSource, Ligh
@ -261,7 +261,7 @@ index 809b3c37d3749c76c3c243cd91c593d03693e9b3..860d1c9729c4ee97ec6f40f7aa969829
} }
} }
diff --git a/net/minecraft/world/level/chunk/LevelChunk.java b/net/minecraft/world/level/chunk/LevelChunk.java diff --git a/net/minecraft/world/level/chunk/LevelChunk.java b/net/minecraft/world/level/chunk/LevelChunk.java
index 51a136cf015de730ca0d1b48cf618a2ed69ea89f..96b0342ab7b922aa16d07b6c00542e6cb66c974a 100644 index ce781ba2c8b3f9f051201d3809a9cb041036f93a..cad71ac79fc52225a192aa5c5d07b13c831fc2c1 100644
--- a/net/minecraft/world/level/chunk/LevelChunk.java --- a/net/minecraft/world/level/chunk/LevelChunk.java
+++ b/net/minecraft/world/level/chunk/LevelChunk.java +++ b/net/minecraft/world/level/chunk/LevelChunk.java
@@ -109,7 +109,7 @@ public class LevelChunk extends ChunkAccess { @@ -109,7 +109,7 @@ public class LevelChunk extends ChunkAccess {
@ -270,11 +270,11 @@ index 51a136cf015de730ca0d1b48cf618a2ed69ea89f..96b0342ab7b922aa16d07b6c00542e6c
) { ) {
- super(pos, data, level, level.registryAccess().lookupOrThrow(Registries.BIOME), inhabitedTime, sections, blendingData); - super(pos, data, level, level.registryAccess().lookupOrThrow(Registries.BIOME), inhabitedTime, sections, blendingData);
+ super(pos, data, level, net.minecraft.server.MinecraftServer.getServer().registryAccess().lookupOrThrow(Registries.BIOME), inhabitedTime, sections, blendingData); // Paper - Anti-Xray - The world isn't ready yet, use server singleton for registry + super(pos, data, level, net.minecraft.server.MinecraftServer.getServer().registryAccess().lookupOrThrow(Registries.BIOME), inhabitedTime, sections, blendingData); // Paper - Anti-Xray - The world isn't ready yet, use server singleton for registry
this.level = (net.minecraft.server.level.ServerLevel) level; // CraftBukkit - type this.level = (ServerLevel) level; // CraftBukkit - type
this.gameEventListenerRegistrySections = new Int2ObjectOpenHashMap<>(); this.gameEventListenerRegistrySections = new Int2ObjectOpenHashMap<>();
diff --git a/net/minecraft/world/level/chunk/LevelChunkSection.java b/net/minecraft/world/level/chunk/LevelChunkSection.java diff --git a/net/minecraft/world/level/chunk/LevelChunkSection.java b/net/minecraft/world/level/chunk/LevelChunkSection.java
index baa9f3e2e6e45c250930658e82bad70a3a292b05..fc21c3268c4b4fda2933d71f0913db28e3796653 100644 index b3d600b0d6deaf44f232dfc86e1456c867e1c07f..a7fabde0f32f09d7f7bed65576ce469f069a21fa 100644
--- a/net/minecraft/world/level/chunk/LevelChunkSection.java --- a/net/minecraft/world/level/chunk/LevelChunkSection.java
+++ b/net/minecraft/world/level/chunk/LevelChunkSection.java +++ b/net/minecraft/world/level/chunk/LevelChunkSection.java
@@ -38,9 +38,15 @@ public class LevelChunkSection { @@ -38,9 +38,15 @@ public class LevelChunkSection {
@ -550,7 +550,7 @@ index bfbb1a2bb4abbb369a24f2f01439e9ea3e16794b..8d6ed8be4d93f7d4e6ea80c351020d88
int getSerializedSize(); int getSerializedSize();
diff --git a/net/minecraft/world/level/chunk/storage/SerializableChunkData.java b/net/minecraft/world/level/chunk/storage/SerializableChunkData.java diff --git a/net/minecraft/world/level/chunk/storage/SerializableChunkData.java b/net/minecraft/world/level/chunk/storage/SerializableChunkData.java
index 37437a86d74291fab1de9495008aafb15dfadce0..cf6e2053d81f7b0f8c8e58b9c0fad3285ebc047d 100644 index c7c87bc8df86ceeef3e15a8f23fc252d4cee1984..3b55e7fb27d680204b8621666ae9200870def3eb 100644
--- a/net/minecraft/world/level/chunk/storage/SerializableChunkData.java --- a/net/minecraft/world/level/chunk/storage/SerializableChunkData.java
+++ b/net/minecraft/world/level/chunk/storage/SerializableChunkData.java +++ b/net/minecraft/world/level/chunk/storage/SerializableChunkData.java
@@ -94,7 +94,7 @@ public record SerializableChunkData( @@ -94,7 +94,7 @@ public record SerializableChunkData(
@ -607,9 +607,9 @@ index 37437a86d74291fab1de9495008aafb15dfadce0..cf6e2053d81f7b0f8c8e58b9c0fad328
@@ -414,7 +418,7 @@ public record SerializableChunkData( @@ -414,7 +418,7 @@ public record SerializableChunkData(
// CraftBukkit start - read/write // CraftBukkit start - read/write
private static Codec<PalettedContainer<Holder<Biome>>> makeBiomeCodecRW(Registry<Biome> iregistry) { private static Codec<PalettedContainer<Holder<Biome>>> makeBiomeCodecRW(Registry<Biome> biomeRegistry) {
- return PalettedContainer.codecRW(iregistry.asHolderIdMap(), iregistry.holderByNameCodec(), PalettedContainer.Strategy.SECTION_BIOMES, iregistry.getOrThrow(Biomes.PLAINS)); - return PalettedContainer.codecRW(biomeRegistry.asHolderIdMap(), biomeRegistry.holderByNameCodec(), PalettedContainer.Strategy.SECTION_BIOMES, biomeRegistry.getOrThrow(Biomes.PLAINS));
+ return PalettedContainer.codecRW(iregistry.asHolderIdMap(), iregistry.holderByNameCodec(), PalettedContainer.Strategy.SECTION_BIOMES, iregistry.getOrThrow(Biomes.PLAINS), null); // Paper - Anti-Xray - Add preset biomes + return PalettedContainer.codecRW(biomeRegistry.asHolderIdMap(), biomeRegistry.holderByNameCodec(), PalettedContainer.Strategy.SECTION_BIOMES, biomeRegistry.getOrThrow(Biomes.PLAINS), null); // Paper - Anti-Xray - Add preset biomes
} }
// CraftBukkit end // CraftBukkit end

View File

@ -30633,10 +30633,10 @@ index 0d65bf24f515b80701150fdc430f324a533cb478..b92a3da5c325e69f5601416d4205fb33
Thread thread = new ca.spottedleaf.moonrise.common.util.TickThread(() -> atomicReference.get().runServer(), "Server thread"); Thread thread = new ca.spottedleaf.moonrise.common.util.TickThread(() -> atomicReference.get().runServer(), "Server thread");
thread.setUncaughtExceptionHandler((thread1, exception) -> LOGGER.error("Uncaught exception in server thread", exception)); thread.setUncaughtExceptionHandler((thread1, exception) -> LOGGER.error("Uncaught exception in server thread", exception));
diff --git a/net/minecraft/world/level/chunk/storage/ChunkStorage.java b/net/minecraft/world/level/chunk/storage/ChunkStorage.java diff --git a/net/minecraft/world/level/chunk/storage/ChunkStorage.java b/net/minecraft/world/level/chunk/storage/ChunkStorage.java
index 1b931e68634e72c3465a99aa29aa53009163046b..80bc7ad9ad076968d06279dedd845d5946cf2501 100644 index 1a0455936cbca2d3812866b332e00a3aaacae8bd..5ba7f724687401c9ea1756a6491498e03548a257 100644
--- a/net/minecraft/world/level/chunk/storage/ChunkStorage.java --- a/net/minecraft/world/level/chunk/storage/ChunkStorage.java
+++ b/net/minecraft/world/level/chunk/storage/ChunkStorage.java +++ b/net/minecraft/world/level/chunk/storage/ChunkStorage.java
@@ -85,7 +85,7 @@ public class ChunkStorage implements AutoCloseable { @@ -54,7 +54,7 @@ public class ChunkStorage implements AutoCloseable {
} else { } else {
try { try {
// CraftBukkit start // CraftBukkit start
@ -30644,8 +30644,8 @@ index 1b931e68634e72c3465a99aa29aa53009163046b..80bc7ad9ad076968d06279dedd845d59
+ if (false && version < 1466) { // Paper - no longer needed, data converter system / DFU handles it now + if (false && version < 1466) { // Paper - no longer needed, data converter system / DFU handles it now
CompoundTag level = chunkData.getCompound("Level"); CompoundTag level = chunkData.getCompound("Level");
if (level.getBoolean("TerrainPopulated") && !level.getBoolean("LightPopulated")) { if (level.getBoolean("TerrainPopulated") && !level.getBoolean("LightPopulated")) {
net.minecraft.server.level.ServerChunkCache cps = (generatoraccess == null) ? null : ((net.minecraft.server.level.ServerLevel) generatoraccess).getChunkSource(); // Light is purged updating to 1.14+. We need to set light populated to true so the converter recognizes the chunk as being "full"
@@ -96,7 +96,7 @@ public class ChunkStorage implements AutoCloseable { @@ -63,7 +63,7 @@ public class ChunkStorage implements AutoCloseable {
} }
// CraftBukkit end // CraftBukkit end
if (version < 1493) { if (version < 1493) {
@ -30654,7 +30654,7 @@ index 1b931e68634e72c3465a99aa29aa53009163046b..80bc7ad9ad076968d06279dedd845d59
if (chunkData.getCompound("Level").getBoolean("hasLegacyStructureData")) { if (chunkData.getCompound("Level").getBoolean("hasLegacyStructureData")) {
LegacyStructureDataHandler legacyStructureHandler = this.getLegacyStructureHandler(levelKey, storage); LegacyStructureDataHandler legacyStructureHandler = this.getLegacyStructureHandler(levelKey, storage);
chunkData = legacyStructureHandler.updateFromLegacy(chunkData); chunkData = legacyStructureHandler.updateFromLegacy(chunkData);
@@ -113,7 +113,7 @@ public class ChunkStorage implements AutoCloseable { @@ -80,7 +80,7 @@ public class ChunkStorage implements AutoCloseable {
// Spigot end // Spigot end
injectDatafixingContext(chunkData, levelKey, chunkGeneratorKey); injectDatafixingContext(chunkData, levelKey, chunkGeneratorKey);
@ -30741,7 +30741,7 @@ index feb4cd21e26598509dc140028496a6f4254c0680..de43e54698125ce9f319d4889dd49f70
} }
diff --git a/net/minecraft/world/level/storage/PlayerDataStorage.java b/net/minecraft/world/level/storage/PlayerDataStorage.java diff --git a/net/minecraft/world/level/storage/PlayerDataStorage.java b/net/minecraft/world/level/storage/PlayerDataStorage.java
index 6c9640f5432e9110e7811b6db246d268c6243feb..45f2800c4862a726490048576fca8e1f24252676 100644 index d68c6c978ac0f154ffe541fd204bec03f033ae96..c44110b123ba5912af18faf0065e9ded780da9b7 100644
--- a/net/minecraft/world/level/storage/PlayerDataStorage.java --- a/net/minecraft/world/level/storage/PlayerDataStorage.java
+++ b/net/minecraft/world/level/storage/PlayerDataStorage.java +++ b/net/minecraft/world/level/storage/PlayerDataStorage.java
@@ -115,7 +115,7 @@ public class PlayerDataStorage { @@ -115,7 +115,7 @@ public class PlayerDataStorage {

View File

@ -23508,10 +23508,10 @@ index 3d3eec1db91cb47395f40c4f47aa77164ad42175..216f97207dac88cc1dc3df59c6ee8a62
+ // Paper end - optimise collisions + // Paper end - optimise collisions
} }
diff --git a/net/minecraft/core/MappedRegistry.java b/net/minecraft/core/MappedRegistry.java diff --git a/net/minecraft/core/MappedRegistry.java b/net/minecraft/core/MappedRegistry.java
index 47b1fafd91b39e73c4e9134b0b8048000fba108a..76994c1491221c06cca5405ba239e6ff642b19ed 100644 index 452c358c2cfa0c39e0b09853cd4a9a12c6ced65d..5f752603aa5611ce9d3dd44cc5b70c27ac46a86e 100644
--- a/net/minecraft/core/MappedRegistry.java --- a/net/minecraft/core/MappedRegistry.java
+++ b/net/minecraft/core/MappedRegistry.java +++ b/net/minecraft/core/MappedRegistry.java
@@ -50,6 +50,19 @@ public class MappedRegistry<T> implements WritableRegistry<T> { @@ -51,6 +51,19 @@ public class MappedRegistry<T> implements WritableRegistry<T> {
return this.getTags(); return this.getTags();
} }
@ -23531,10 +23531,10 @@ index 47b1fafd91b39e73c4e9134b0b8048000fba108a..76994c1491221c06cca5405ba239e6ff
public MappedRegistry(ResourceKey<? extends Registry<T>> key, Lifecycle registryLifecycle) { public MappedRegistry(ResourceKey<? extends Registry<T>> key, Lifecycle registryLifecycle) {
this(key, registryLifecycle, false); this(key, registryLifecycle, false);
} }
@@ -114,6 +127,7 @@ public class MappedRegistry<T> implements WritableRegistry<T> { @@ -116,6 +129,7 @@ public class MappedRegistry<T> implements WritableRegistry<T> {
this.toId.put(value, size);
this.registrationInfos.put(key, registrationInfo); this.registrationInfos.put(key, registrationInfo);
this.registryLifecycle = this.registryLifecycle.add(registrationInfo.lifecycle()); this.registryLifecycle = this.registryLifecycle.add(registrationInfo.lifecycle());
this.temporaryUnfrozenMap.put(key.location(), value); // Paper - support pre-filling in registry mod API
+ this.injectFluidRegister(key, value); // Paper - fluid method optimisations + this.injectFluidRegister(key, value); // Paper - fluid method optimisations
return reference; return reference;
} }
@ -26719,7 +26719,7 @@ index 2f49dbc919f7f5eea9abce6106723c72f5ae45fb..87d4291a3944f706a694536da6de0f28
} }
} }
diff --git a/net/minecraft/server/level/ServerEntity.java b/net/minecraft/server/level/ServerEntity.java diff --git a/net/minecraft/server/level/ServerEntity.java b/net/minecraft/server/level/ServerEntity.java
index 70f6d068b3f3665b282d9750310c883839120ab2..870b9efd445ddadb3725e88351555ad986ce7c72 100644 index da793ad12565c36fffb26eb771ff68c76632caf7..db06f966077928419bfe469260f04d7dfda69f28 100644
--- a/net/minecraft/server/level/ServerEntity.java --- a/net/minecraft/server/level/ServerEntity.java
+++ b/net/minecraft/server/level/ServerEntity.java +++ b/net/minecraft/server/level/ServerEntity.java
@@ -91,6 +91,11 @@ public class ServerEntity { @@ -91,6 +91,11 @@ public class ServerEntity {
@ -27496,7 +27496,7 @@ index 192977dd661ee795ada13db895db770293e9b402..95a4e37a3c93f9b3c56c7a7376ed521c
} }
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 ff5889f8fed0707a6654d9d21862e32e2ebc866d..e61fe83479f095e8addbd3e8f1d5179c998ae1eb 100644 index 097ec55166b9e9269142be58992c29687122fe28..aeabb79512aabd7a9e8af1be72e1745f0e7eefe4 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
@@ -178,7 +178,7 @@ import net.minecraft.world.scores.Team; @@ -178,7 +178,7 @@ import net.minecraft.world.scores.Team;
@ -28372,7 +28372,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 45f69a914d5a0565196c4105d61541047301470f..f42bdae2f80805e5069212bd16e3ab6814aef9ee 100644 index 189385600b9094291152035b17df869eaccc0428..25a1089a7376f0cbd96bb43b5c203640c88fc282 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
@@ -135,7 +135,7 @@ import net.minecraft.world.scores.ScoreHolder; @@ -135,7 +135,7 @@ import net.minecraft.world.scores.ScoreHolder;
@ -28725,7 +28725,7 @@ index 45f69a914d5a0565196c4105d61541047301470f..f42bdae2f80805e5069212bd16e3ab68
} }
private static float[] collectCandidateStepUpHeights(AABB box, List<VoxelShape> colliders, float deltaY, float maxUpStep) { private static float[] collectCandidateStepUpHeights(AABB box, List<VoxelShape> colliders, float deltaY, float maxUpStep) {
@@ -2664,23 +2812,110 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess @@ -2662,23 +2810,110 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
} }
public boolean isInWall() { public boolean isInWall() {
@ -28849,7 +28849,7 @@ index 45f69a914d5a0565196c4105d61541047301470f..f42bdae2f80805e5069212bd16e3ab68
} }
public InteractionResult interact(Player player, InteractionHand hand) { public InteractionResult interact(Player player, InteractionHand hand) {
@@ -4104,15 +4339,17 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess @@ -4102,15 +4337,17 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
} }
public Iterable<Entity> getIndirectPassengers() { public Iterable<Entity> getIndirectPassengers() {
@ -28875,7 +28875,7 @@ index 45f69a914d5a0565196c4105d61541047301470f..f42bdae2f80805e5069212bd16e3ab68
} }
public int countPlayerPassengers() { public int countPlayerPassengers() {
@@ -4250,77 +4487,136 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess @@ -4248,77 +4485,136 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
return Mth.lerp(partialTick, this.yRotO, this.yRot); return Mth.lerp(partialTick, this.yRotO, this.yRot);
} }
@ -29066,7 +29066,7 @@ index 45f69a914d5a0565196c4105d61541047301470f..f42bdae2f80805e5069212bd16e3ab68
public boolean touchingUnloadedChunk() { public boolean touchingUnloadedChunk() {
AABB aabb = this.getBoundingBox().inflate(1.0); AABB aabb = this.getBoundingBox().inflate(1.0);
@@ -4473,6 +4769,15 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess @@ -4471,6 +4767,15 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
this.setPosRaw(x, y, z, false); this.setPosRaw(x, y, z, false);
} }
public final void setPosRaw(double x, double y, double z, boolean forceBoundingBoxUpdate) { public final void setPosRaw(double x, double y, double z, boolean forceBoundingBoxUpdate) {
@ -29082,7 +29082,7 @@ index 45f69a914d5a0565196c4105d61541047301470f..f42bdae2f80805e5069212bd16e3ab68
if (!checkPosition(this, x, y, z)) { if (!checkPosition(this, x, y, z)) {
return; return;
} }
@@ -4603,6 +4908,12 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess @@ -4601,6 +4906,12 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
@Override @Override
public final void setRemoved(Entity.RemovalReason removalReason, org.bukkit.event.entity.EntityRemoveEvent.Cause cause) { public final void setRemoved(Entity.RemovalReason removalReason, org.bukkit.event.entity.EntityRemoveEvent.Cause cause) {
@ -29095,7 +29095,7 @@ index 45f69a914d5a0565196c4105d61541047301470f..f42bdae2f80805e5069212bd16e3ab68
org.bukkit.craftbukkit.event.CraftEventFactory.callEntityRemoveEvent(this, cause); org.bukkit.craftbukkit.event.CraftEventFactory.callEntityRemoveEvent(this, cause);
// CraftBukkit end // CraftBukkit end
final boolean alreadyRemoved = this.removalReason != null; // Paper - Folia schedulers final boolean alreadyRemoved = this.removalReason != null; // Paper - Folia schedulers
@@ -4614,7 +4925,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess @@ -4612,7 +4923,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
this.stopRiding(); this.stopRiding();
} }
@ -29104,7 +29104,7 @@ index 45f69a914d5a0565196c4105d61541047301470f..f42bdae2f80805e5069212bd16e3ab68
this.levelCallback.onRemove(removalReason); this.levelCallback.onRemove(removalReason);
this.onRemoval(removalReason); this.onRemoval(removalReason);
// Paper start - Folia schedulers // Paper start - Folia schedulers
@@ -4648,7 +4959,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess @@ -4646,7 +4957,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()
@ -30907,7 +30907,7 @@ index 8d98cba3830dc5dfb5cae9a6f5fedfffee0d2cd8..73962e79a0f3d892e3155443a1b84508
public interface NoiseBiomeSource { public interface NoiseBiomeSource {
diff --git a/net/minecraft/world/level/block/Block.java b/net/minecraft/world/level/block/Block.java diff --git a/net/minecraft/world/level/block/Block.java b/net/minecraft/world/level/block/Block.java
index 91d7d250f7c3de8a71aef26e23c12764b06b322b..0d36b1ac7d54283af71f2494accded11c059dba5 100644 index a4eb9a10b6c1351c7341bc031bb9f819e17ff1e5..976de81d65b6494cdad20f4ec5125fceec86f951 100644
--- a/net/minecraft/world/level/block/Block.java --- a/net/minecraft/world/level/block/Block.java
+++ b/net/minecraft/world/level/block/Block.java +++ b/net/minecraft/world/level/block/Block.java
@@ -259,7 +259,7 @@ public class Block extends BlockBehaviour implements ItemLike { @@ -259,7 +259,7 @@ public class Block extends BlockBehaviour implements ItemLike {
@ -30920,7 +30920,7 @@ index 91d7d250f7c3de8a71aef26e23c12764b06b322b..0d36b1ac7d54283af71f2494accded11
public void animateTick(BlockState state, Level level, BlockPos pos, RandomSource random) { public void animateTick(BlockState state, Level level, BlockPos pos, RandomSource random) {
diff --git a/net/minecraft/world/level/block/state/BlockBehaviour.java b/net/minecraft/world/level/block/state/BlockBehaviour.java diff --git a/net/minecraft/world/level/block/state/BlockBehaviour.java b/net/minecraft/world/level/block/state/BlockBehaviour.java
index 25e49a24cedfa8ad04245d59fcac3231bcd62103..061d94a35d957ca72a01bae959d38aab59b1a64d 100644 index fa816de449a6077c05fee76835a1625f5b2008ac..5473b4006f7e0266ea11a7b05cef78a113c30d97 100644
--- a/net/minecraft/world/level/block/state/BlockBehaviour.java --- a/net/minecraft/world/level/block/state/BlockBehaviour.java
+++ b/net/minecraft/world/level/block/state/BlockBehaviour.java +++ b/net/minecraft/world/level/block/state/BlockBehaviour.java
@@ -416,7 +416,7 @@ public abstract class BlockBehaviour implements FeatureElement { @@ -416,7 +416,7 @@ public abstract class BlockBehaviour implements FeatureElement {
@ -31399,7 +31399,7 @@ index 92350434746f06bbf4a161c6bc42602de7b45220..1c24f38d21da1be9740512981f219924
public Property.Value<T> value(T value) { public Property.Value<T> value(T value) {
diff --git a/net/minecraft/world/level/chunk/ChunkAccess.java b/net/minecraft/world/level/chunk/ChunkAccess.java diff --git a/net/minecraft/world/level/chunk/ChunkAccess.java b/net/minecraft/world/level/chunk/ChunkAccess.java
index 860d1c9729c4ee97ec6f40f7aa969829070b27c0..94de1217d18e1a7a0fb7b83f21436eaf0a5998c6 100644 index d63d745a0220963a297cfedf1e8983aeb471a045..6d565b52552534ce9cacfc35ad1bf4adcb69eac3 100644
--- a/net/minecraft/world/level/chunk/ChunkAccess.java --- a/net/minecraft/world/level/chunk/ChunkAccess.java
+++ b/net/minecraft/world/level/chunk/ChunkAccess.java +++ b/net/minecraft/world/level/chunk/ChunkAccess.java
@@ -57,7 +57,7 @@ import net.minecraft.world.ticks.SavedTick; @@ -57,7 +57,7 @@ import net.minecraft.world.ticks.SavedTick;
@ -31537,8 +31537,8 @@ index 860d1c9729c4ee97ec6f40f7aa969829070b27c0..94de1217d18e1a7a0fb7b83f21436eaf
+ // Paper end - get block chunk optimisation + // Paper end - get block chunk optimisation
} }
// CraftBukkit start // CraftBukkit start
public void setBiome(int i, int j, int k, Holder<Biome> biome) { public void setBiome(int x, int y, int z, Holder<Biome> biome) {
@@ -507,12 +572,12 @@ public abstract class ChunkAccess implements BiomeManager.NoiseBiomeSource, Ligh @@ -503,12 +568,12 @@ public abstract class ChunkAccess implements BiomeManager.NoiseBiomeSource, Ligh
} }
public void initializeLightSources() { public void initializeLightSources() {
@ -31554,7 +31554,7 @@ index 860d1c9729c4ee97ec6f40f7aa969829070b27c0..94de1217d18e1a7a0fb7b83f21436eaf
public record PackedTicks(List<SavedTick<Block>> blocks, List<SavedTick<Fluid>> fluids) { public record PackedTicks(List<SavedTick<Block>> blocks, List<SavedTick<Fluid>> fluids) {
diff --git a/net/minecraft/world/level/chunk/ChunkGenerator.java b/net/minecraft/world/level/chunk/ChunkGenerator.java diff --git a/net/minecraft/world/level/chunk/ChunkGenerator.java b/net/minecraft/world/level/chunk/ChunkGenerator.java
index 65117a9cb9d1b8684cae8d36ea3b8e2050fb928c..a9d65e28b849c9660a14ef7c16ed17bd5182bd7e 100644 index b320519578f7e2c52b2116afb247e071b322696e..6ed51cf42b5864194d671b5b56f5b9bdf0291dc0 100644
--- a/net/minecraft/world/level/chunk/ChunkGenerator.java --- a/net/minecraft/world/level/chunk/ChunkGenerator.java
+++ b/net/minecraft/world/level/chunk/ChunkGenerator.java +++ b/net/minecraft/world/level/chunk/ChunkGenerator.java
@@ -116,7 +116,7 @@ public abstract class ChunkGenerator { @@ -116,7 +116,7 @@ public abstract class ChunkGenerator {
@ -31717,7 +31717,7 @@ index e7c0f4da8508fbca467326f475668d66454d7b77..41856c98d97e7eb0782f8e441b9a269a
@Override @Override
public BlockEntity getBlockEntity(BlockPos pos) { public BlockEntity getBlockEntity(BlockPos pos) {
diff --git a/net/minecraft/world/level/chunk/LevelChunk.java b/net/minecraft/world/level/chunk/LevelChunk.java diff --git a/net/minecraft/world/level/chunk/LevelChunk.java b/net/minecraft/world/level/chunk/LevelChunk.java
index 96b0342ab7b922aa16d07b6c00542e6cb66c974a..c1ae7755e8d6fa8501d2210dab7605d993c55722 100644 index cad71ac79fc52225a192aa5c5d07b13c831fc2c1..761fdcd4a4e18f45547afd8edff44f61c6eeacb4 100644
--- a/net/minecraft/world/level/chunk/LevelChunk.java --- a/net/minecraft/world/level/chunk/LevelChunk.java
+++ b/net/minecraft/world/level/chunk/LevelChunk.java +++ b/net/minecraft/world/level/chunk/LevelChunk.java
@@ -52,7 +52,7 @@ import net.minecraft.world.ticks.LevelChunkTicks; @@ -52,7 +52,7 @@ import net.minecraft.world.ticks.LevelChunkTicks;
@ -31896,7 +31896,7 @@ index 96b0342ab7b922aa16d07b6c00542e6cb66c974a..c1ae7755e8d6fa8501d2210dab7605d9
@Nullable @Nullable
diff --git a/net/minecraft/world/level/chunk/LevelChunkSection.java b/net/minecraft/world/level/chunk/LevelChunkSection.java diff --git a/net/minecraft/world/level/chunk/LevelChunkSection.java b/net/minecraft/world/level/chunk/LevelChunkSection.java
index fc21c3268c4b4fda2933d71f0913db28e3796653..2ff691bcd32f587e8add2d8eda7e7339ccbde6e8 100644 index a7fabde0f32f09d7f7bed65576ce469f069a21fa..412e7b1cf8c24f0ddf6d174967bedad576f10aba 100644
--- a/net/minecraft/world/level/chunk/LevelChunkSection.java --- a/net/minecraft/world/level/chunk/LevelChunkSection.java
+++ b/net/minecraft/world/level/chunk/LevelChunkSection.java +++ b/net/minecraft/world/level/chunk/LevelChunkSection.java
@@ -13,7 +13,7 @@ import net.minecraft.world.level.block.Blocks; @@ -13,7 +13,7 @@ import net.minecraft.world.level.block.Blocks;
@ -32627,7 +32627,7 @@ index 7a4d299d2ce36982204e30de9278ddfd5b37c3df..b8348976e80578d9eff64eea68c04c60
private final ChunkStatus status; private final ChunkStatus status;
@Nullable @Nullable
diff --git a/net/minecraft/world/level/chunk/storage/ChunkStorage.java b/net/minecraft/world/level/chunk/storage/ChunkStorage.java diff --git a/net/minecraft/world/level/chunk/storage/ChunkStorage.java b/net/minecraft/world/level/chunk/storage/ChunkStorage.java
index 80bc7ad9ad076968d06279dedd845d5946cf2501..433feab7f7c1931f79836164a0b8c4a1c3b75ba6 100644 index 5ba7f724687401c9ea1756a6491498e03548a257..64343a3f6e6009eed5b392482ec053be8e00ee63 100644
--- a/net/minecraft/world/level/chunk/storage/ChunkStorage.java --- a/net/minecraft/world/level/chunk/storage/ChunkStorage.java
+++ b/net/minecraft/world/level/chunk/storage/ChunkStorage.java +++ b/net/minecraft/world/level/chunk/storage/ChunkStorage.java
@@ -22,20 +22,30 @@ import net.minecraft.world.level.chunk.ChunkGenerator; @@ -22,20 +22,30 @@ import net.minecraft.world.level.chunk.ChunkGenerator;
@ -32665,7 +32665,7 @@ index 80bc7ad9ad076968d06279dedd845d5946cf2501..433feab7f7c1931f79836164a0b8c4a1
} }
// CraftBukkit start // CraftBukkit start
@@ -99,7 +109,9 @@ public class ChunkStorage implements AutoCloseable { @@ -66,7 +76,9 @@ public class ChunkStorage implements AutoCloseable {
chunkData = ca.spottedleaf.dataconverter.minecraft.MCDataConverter.convertTag(ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry.CHUNK, chunkData, version, 1493); // Paper - replace chunk converter chunkData = ca.spottedleaf.dataconverter.minecraft.MCDataConverter.convertTag(ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry.CHUNK, chunkData, version, 1493); // Paper - replace chunk converter
if (chunkData.getCompound("Level").getBoolean("hasLegacyStructureData")) { if (chunkData.getCompound("Level").getBoolean("hasLegacyStructureData")) {
LegacyStructureDataHandler legacyStructureHandler = this.getLegacyStructureHandler(levelKey, storage); LegacyStructureDataHandler legacyStructureHandler = this.getLegacyStructureHandler(levelKey, storage);
@ -32675,7 +32675,7 @@ index 80bc7ad9ad076968d06279dedd845d5946cf2501..433feab7f7c1931f79836164a0b8c4a1
} }
} }
@@ -163,7 +175,13 @@ public class ChunkStorage implements AutoCloseable { @@ -130,7 +142,13 @@ public class ChunkStorage implements AutoCloseable {
} }
public CompletableFuture<Optional<CompoundTag>> read(ChunkPos chunkPos) { public CompletableFuture<Optional<CompoundTag>> read(ChunkPos chunkPos) {
@ -32690,7 +32690,7 @@ index 80bc7ad9ad076968d06279dedd845d5946cf2501..433feab7f7c1931f79836164a0b8c4a1
} }
public CompletableFuture<Void> write(ChunkPos pos, Supplier<CompoundTag> tagSupplier) { public CompletableFuture<Void> write(ChunkPos pos, Supplier<CompoundTag> tagSupplier) {
@@ -179,29 +197,54 @@ public class ChunkStorage implements AutoCloseable { @@ -146,29 +164,54 @@ public class ChunkStorage implements AutoCloseable {
}; };
// Paper end - guard against possible chunk pos desync // Paper end - guard against possible chunk pos desync
this.handleLegacyStructureIndex(pos); this.handleLegacyStructureIndex(pos);
@ -32784,7 +32784,7 @@ index 889e188e920edb284f04b264bcdd06146f54a4cb..2199a9e2a0141c646d108f2687a27f1d
private final Long2ObjectLinkedOpenHashMap<CompletableFuture<BitSet>> regionCacheForBlender = new Long2ObjectLinkedOpenHashMap<>(); private final Long2ObjectLinkedOpenHashMap<CompletableFuture<BitSet>> regionCacheForBlender = new Long2ObjectLinkedOpenHashMap<>();
private static final int REGION_CACHE_SIZE = 1024; private static final int REGION_CACHE_SIZE = 1024;
diff --git a/net/minecraft/world/level/chunk/storage/RegionFile.java b/net/minecraft/world/level/chunk/storage/RegionFile.java diff --git a/net/minecraft/world/level/chunk/storage/RegionFile.java b/net/minecraft/world/level/chunk/storage/RegionFile.java
index 783a2d80f6197dd0af0dc81909f0353a8ea2ecf4..7da388ffab162c282cad0f297bb7304f3c2abbaf 100644 index 4eb07097986aac67421dd8e6a17cc5436da91187..984db72272d552c7210bd6f437ea88694ddd2828 100644
--- a/net/minecraft/world/level/chunk/storage/RegionFile.java --- a/net/minecraft/world/level/chunk/storage/RegionFile.java
+++ b/net/minecraft/world/level/chunk/storage/RegionFile.java +++ b/net/minecraft/world/level/chunk/storage/RegionFile.java
@@ -22,7 +22,7 @@ import net.minecraft.util.profiling.jfr.JvmProfiler; @@ -22,7 +22,7 @@ import net.minecraft.util.profiling.jfr.JvmProfiler;
@ -33324,7 +33324,7 @@ index 7dc1ffffd9d0fec54dbc254c154ee85ee750174d..778bd73a938c94ecb85ca0f8b686ff4e
record PackedChunk<T>(Int2ObjectMap<T> sectionsByY, boolean versionChanged) { record PackedChunk<T>(Int2ObjectMap<T> sectionsByY, boolean versionChanged) {
diff --git a/net/minecraft/world/level/chunk/storage/SerializableChunkData.java b/net/minecraft/world/level/chunk/storage/SerializableChunkData.java diff --git a/net/minecraft/world/level/chunk/storage/SerializableChunkData.java b/net/minecraft/world/level/chunk/storage/SerializableChunkData.java
index cf6e2053d81f7b0f8c8e58b9c0fad3285ebc047d..70a9972252576e039ac126f6057a6ed66b80cdfc 100644 index 3b55e7fb27d680204b8621666ae9200870def3eb..879d411775a2fece1d8a970300cb3a550baa6305 100644
--- a/net/minecraft/world/level/chunk/storage/SerializableChunkData.java --- a/net/minecraft/world/level/chunk/storage/SerializableChunkData.java
+++ b/net/minecraft/world/level/chunk/storage/SerializableChunkData.java +++ b/net/minecraft/world/level/chunk/storage/SerializableChunkData.java
@@ -148,7 +148,7 @@ public record SerializableChunkData( @@ -148,7 +148,7 @@ public record SerializableChunkData(
@ -33700,10 +33700,10 @@ index 342c83309b19c64d86e0dd97c1756c96be52772b..423779a2b690f387a4f0bd07b97b50e0
} }
} }
diff --git a/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java b/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java diff --git a/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java b/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java
index 29d9f6e54421c539e9e55ab9f51b4c872da3fbb8..d77016287f5f9a0964d56f05d2d5256ef2e6e86c 100644 index 6d61739574155f89511b9adcaf1174841bdc7da7..65728ef17e63d71833677fdcbd5bb90794b4822b 100644
--- a/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java --- a/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java
+++ b/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java +++ b/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java
@@ -78,7 +78,7 @@ public final class NoiseBasedChunkGenerator extends ChunkGenerator { @@ -77,7 +77,7 @@ public final class NoiseBasedChunkGenerator extends ChunkGenerator {
return CompletableFuture.supplyAsync(() -> { return CompletableFuture.supplyAsync(() -> {
this.doCreateBiomes(blender, randomState, structureManager, chunk); this.doCreateBiomes(blender, randomState, structureManager, chunk);
return chunk; return chunk;
@ -33712,7 +33712,7 @@ index 29d9f6e54421c539e9e55ab9f51b4c872da3fbb8..d77016287f5f9a0964d56f05d2d5256e
} }
private void doCreateBiomes(Blender blender, RandomState random, StructureManager structureManager, ChunkAccess chunk) { private void doCreateBiomes(Blender blender, RandomState random, StructureManager structureManager, ChunkAccess chunk) {
@@ -318,7 +318,7 @@ public final class NoiseBasedChunkGenerator extends ChunkGenerator { @@ -317,7 +317,7 @@ public final class NoiseBasedChunkGenerator extends ChunkGenerator {
} }
return var20; return var20;
@ -34002,7 +34002,7 @@ index ca23af013967b50420ebee178878ea79333de53b..d41b9266625ca6c5e32c5126f35a1f77
public int getLightSectionCount() { public int getLightSectionCount() {
diff --git a/net/minecraft/world/level/material/FlowingFluid.java b/net/minecraft/world/level/material/FlowingFluid.java diff --git a/net/minecraft/world/level/material/FlowingFluid.java b/net/minecraft/world/level/material/FlowingFluid.java
index 130ef38a50f1df1faa26b433b0c605a4507f71af..f6daca279788c3d983a9ee213df85d5d93fc6eed 100644 index 86fd2b831f42bdb5bd045e44b26489d5a8697dd9..e30499bdcd6600e5c9d4a755c1182fb6dff3735f 100644
--- a/net/minecraft/world/level/material/FlowingFluid.java --- a/net/minecraft/world/level/material/FlowingFluid.java
+++ b/net/minecraft/world/level/material/FlowingFluid.java +++ b/net/minecraft/world/level/material/FlowingFluid.java
@@ -45,6 +45,48 @@ public abstract class FlowingFluid extends Fluid { @@ -45,6 +45,48 @@ public abstract class FlowingFluid extends Fluid {

View File

@ -60,7 +60,7 @@ index 3dff97f13586be3b52bbe786852c185f6753a019..ff6503bf8eb88d1264c3d848a89d0255
} else if (this.seenBy.remove(player.connection)) { } else if (this.seenBy.remove(player.connection)) {
this.serverEntity.removePairing(player); this.serverEntity.removePairing(player);
diff --git a/net/minecraft/server/level/ServerEntity.java b/net/minecraft/server/level/ServerEntity.java diff --git a/net/minecraft/server/level/ServerEntity.java b/net/minecraft/server/level/ServerEntity.java
index 870b9efd445ddadb3725e88351555ad986ce7c72..a4da36060ca75968f5831adfc3f7117281649b7a 100644 index db06f966077928419bfe469260f04d7dfda69f28..0fb253aa55a24b56b17f524b3261c5b75c7d7e59 100644
--- a/net/minecraft/server/level/ServerEntity.java --- a/net/minecraft/server/level/ServerEntity.java
+++ b/net/minecraft/server/level/ServerEntity.java +++ b/net/minecraft/server/level/ServerEntity.java
@@ -90,6 +90,13 @@ public class ServerEntity { @@ -90,6 +90,13 @@ public class ServerEntity {
@ -77,7 +77,7 @@ index 870b9efd445ddadb3725e88351555ad986ce7c72..a4da36060ca75968f5831adfc3f71172
public void sendChanges() { public void sendChanges() {
// Paper start - optimise collisions // Paper start - optimise collisions
if (((ca.spottedleaf.moonrise.patches.chunk_system.entity.ChunkSystemEntity)this.entity).moonrise$isHardColliding()) { if (((ca.spottedleaf.moonrise.patches.chunk_system.entity.ChunkSystemEntity)this.entity).moonrise$isHardColliding()) {
@@ -130,7 +137,7 @@ public class ServerEntity { @@ -131,7 +138,7 @@ public class ServerEntity {
this.sendDirtyEntityData(); this.sendDirtyEntityData();
} }
@ -86,7 +86,7 @@ index 870b9efd445ddadb3725e88351555ad986ce7c72..a4da36060ca75968f5831adfc3f71172
byte b = Mth.packDegrees(this.entity.getYRot()); byte b = Mth.packDegrees(this.entity.getYRot());
byte b1 = Mth.packDegrees(this.entity.getXRot()); byte b1 = Mth.packDegrees(this.entity.getXRot());
boolean flag = Math.abs(b - this.lastSentYRot) >= 1 || Math.abs(b1 - this.lastSentXRot) >= 1; boolean flag = Math.abs(b - this.lastSentYRot) >= 1 || Math.abs(b1 - this.lastSentXRot) >= 1;
@@ -165,7 +172,7 @@ public class ServerEntity { @@ -166,7 +173,7 @@ public class ServerEntity {
long l1 = this.positionCodec.encodeY(vec3); long l1 = this.positionCodec.encodeY(vec3);
long l2 = this.positionCodec.encodeZ(vec3); long l2 = this.positionCodec.encodeZ(vec3);
boolean flag5 = l < -32768L || l > 32767L || l1 < -32768L || l1 > 32767L || l2 < -32768L || l2 > 32767L; boolean flag5 = l < -32768L || l > 32767L || l1 < -32768L || l1 > 32767L || l2 < -32768L || l2 > 32767L;
@ -95,7 +95,7 @@ index 870b9efd445ddadb3725e88351555ad986ce7c72..a4da36060ca75968f5831adfc3f71172
this.wasOnGround = this.entity.onGround(); this.wasOnGround = this.entity.onGround();
this.teleportDelay = 0; this.teleportDelay = 0;
packet = ClientboundEntityPositionSyncPacket.of(this.entity); packet = ClientboundEntityPositionSyncPacket.of(this.entity);
@@ -230,6 +237,7 @@ public class ServerEntity { @@ -231,6 +238,7 @@ public class ServerEntity {
} }
this.entity.hasImpulse = false; this.entity.hasImpulse = false;

View File

@ -1,6 +1,6 @@
--- a/net/minecraft/core/MappedRegistry.java --- a/net/minecraft/core/MappedRegistry.java
+++ b/net/minecraft/core/MappedRegistry.java +++ b/net/minecraft/core/MappedRegistry.java
@@ -33,11 +_,11 @@ @@ -33,17 +_,18 @@
public class MappedRegistry<T> implements WritableRegistry<T> { public class MappedRegistry<T> implements WritableRegistry<T> {
private final ResourceKey<? extends Registry<T>> key; private final ResourceKey<? extends Registry<T>> key;
private final ObjectList<Holder.Reference<T>> byId = new ObjectArrayList<>(256); private final ObjectList<Holder.Reference<T>> byId = new ObjectArrayList<>(256);
@ -17,6 +17,29 @@
private Lifecycle registryLifecycle; private Lifecycle registryLifecycle;
private final Map<TagKey<T>, HolderSet.Named<T>> frozenTags = new IdentityHashMap<>(); private final Map<TagKey<T>, HolderSet.Named<T>> frozenTags = new IdentityHashMap<>();
MappedRegistry.TagSet<T> allTags = MappedRegistry.TagSet.unbound(); MappedRegistry.TagSet<T> allTags = MappedRegistry.TagSet.unbound();
private boolean frozen;
@Nullable
private Map<T, Holder.Reference<T>> unregisteredIntrusiveHolders;
+ public final Map<ResourceLocation, T> temporaryUnfrozenMap = new HashMap<>(); // Paper - support pre-filling in registry mod API
@Override
public Stream<HolderSet.Named<T>> listTags() {
@@ -114,6 +_,7 @@
this.toId.put(value, size);
this.registrationInfos.put(key, registrationInfo);
this.registryLifecycle = this.registryLifecycle.add(registrationInfo.lifecycle());
+ this.temporaryUnfrozenMap.put(key.location(), value); // Paper - support pre-filling in registry mod API
return reference;
}
}
@@ -275,6 +_,7 @@
return this;
} else {
this.frozen = true;
+ this.temporaryUnfrozenMap.clear(); // Paper - support pre-filling in registry mod API
this.byValue.forEach((object, reference) -> reference.bindValue((T)object));
List<ResourceLocation> list = this.byKey
.entrySet()
@@ -509,4 +_,13 @@ @@ -509,4 +_,13 @@
Stream<HolderSet.Named<T>> getTags(); Stream<HolderSet.Named<T>> getTags();

View File

@ -26,7 +26,7 @@
ResourceLocation resourceLocation = key.location(); ResourceLocation resourceLocation = key.location();
LOADERS.put(resourceLocation, () -> bootstrap.run(registry)); LOADERS.put(resourceLocation, () -> bootstrap.run(registry));
WRITABLE_REGISTRY.register((ResourceKey)key, registry, RegistrationInfo.BUILT_IN); WRITABLE_REGISTRY.register((ResourceKey)key, registry, RegistrationInfo.BUILT_IN);
@@ -328,7 +_,14 @@ @@ -328,16 +_,34 @@
} }
public static void bootStrap() { public static void bootStrap() {
@ -41,6 +41,26 @@
freeze(); freeze();
validate(REGISTRY); validate(REGISTRY);
} }
private static void createContents() {
+ // Paper start - class-load org.bukkit.Registry
+ // we have to class-load Registry here to create all the CraftRegistry instances
+ // that will be created when Registry is class-loaded before RegistryAccess#getRegistry
+ // would try to create them in lockReferenceHolder
+ try {
+ Class.forName(org.bukkit.Registry.class.getName());
+ } catch (final ClassNotFoundException ex) {
+ throw new RuntimeException(ex);
+ }
+ // Paper end - class-load org.bukkit.Registry
LOADERS.forEach((resourceLocation, supplier) -> {
if (supplier.get() == null) {
LOGGER.error("Unable to bootstrap registry '{}'", resourceLocation);
}
+ io.papermc.paper.registry.PaperRegistryAccess.instance().lockReferenceHolders(ResourceKey.createRegistryKey(resourceLocation)); // Paper - lock reference holder creation
});
}
@@ -346,6 +_,7 @@ @@ -346,6 +_,7 @@
for (Registry<?> registry : REGISTRY) { for (Registry<?> registry : REGISTRY) {

View File

@ -34,11 +34,12 @@
} catch (Exception var14) { } catch (Exception var14) {
loadingErrors.put( loadingErrors.put(
resourceKey, resourceKey,
@@ -283,7 +_,8 @@ @@ -283,7 +_,9 @@
} }
} }
- TagLoader.loadTagsForRegistry(resourceManager, registry); - TagLoader.loadTagsForRegistry(resourceManager, registry);
+ io.papermc.paper.registry.PaperRegistryAccess.instance().lockReferenceHolders(registry.key()); // Paper - lock reference holders
+ io.papermc.paper.registry.PaperRegistryListenerManager.INSTANCE.runFreezeListeners(registry.key(), conversions); // Paper - run pre-freeze listeners + io.papermc.paper.registry.PaperRegistryListenerManager.INSTANCE.runFreezeListeners(registry.key(), conversions); // Paper - run pre-freeze listeners
+ TagLoader.loadTagsForRegistry(resourceManager, registry, io.papermc.paper.plugin.lifecycle.event.registrar.ReloadableRegistrarEvent.Cause.INITIAL); // Paper - tag lifecycle - add cause + TagLoader.loadTagsForRegistry(resourceManager, registry, io.papermc.paper.plugin.lifecycle.event.registrar.ReloadableRegistrarEvent.Cause.INITIAL); // Paper - tag lifecycle - add cause
} }

View File

@ -1193,15 +1193,18 @@
return ReloadableServerResources.loadResources( return ReloadableServerResources.loadResources(
closeableResourceManager, closeableResourceManager,
this.registries, this.registries,
@@ -1520,6 +_,7 @@ @@ -1520,20 +_,39 @@
) )
.thenAcceptAsync( .thenAcceptAsync(
reloadableResources -> { reloadableResources -> {
+ io.papermc.paper.command.brigadier.PaperBrigadier.moveBukkitCommands(this.resources.managers().getCommands(), reloadableResources.managers().commands); // Paper + io.papermc.paper.command.brigadier.PaperBrigadier.moveBukkitCommands(this.resources.managers().getCommands(), reloadableResources.managers().commands); // Paper
this.resources.close(); this.resources.close();
this.resources = reloadableResources; this.resources = reloadableResources;
this.packRepository.setSelected(selectedIds); - this.packRepository.setSelected(selectedIds);
@@ -1529,11 +_,29 @@ + this.packRepository.setSelected(selectedIds, false); // Paper - add pendingReload flag to determine required pack loading - false as this is *after* a reload (see above)
WorldDataConfiguration worldDataConfiguration = new WorldDataConfiguration(
getSelectedPacks(this.packRepository, true), this.worldData.enabledFeatures()
);
this.worldData.setDataConfiguration(worldDataConfiguration); this.worldData.setDataConfiguration(worldDataConfiguration);
this.resources.managers.updateStaticRegistryTags(); this.resources.managers.updateStaticRegistryTags();
this.resources.managers.getRecipeManager().finalizeRecipeLoading(this.worldData.enabledFeatures()); this.resources.managers.getRecipeManager().finalizeRecipeLoading(this.worldData.enabledFeatures());
@ -1232,6 +1235,33 @@
}, },
this this
); );
@@ -1550,7 +_,7 @@
DataPackConfig dataPackConfig = initialDataConfig.dataPacks();
FeatureFlagSet featureFlagSet = initMode ? FeatureFlagSet.of() : initialDataConfig.enabledFeatures();
FeatureFlagSet featureFlagSet1 = initMode ? FeatureFlags.REGISTRY.allFlags() : initialDataConfig.enabledFeatures();
- packRepository.reload();
+ packRepository.reload(true); // Paper - will load resource packs
if (safeMode) {
return configureRepositoryWithSelection(packRepository, List.of("vanilla"), featureFlagSet, false);
} else {
@@ -1605,7 +_,7 @@
private static WorldDataConfiguration configureRepositoryWithSelection(
PackRepository packRepository, Collection<String> selectedPacks, FeatureFlagSet enabledFeatures, boolean safeMode
) {
- packRepository.setSelected(selectedPacks);
+ packRepository.setSelected(selectedPacks, true); // Paper - add pendingReload flag to determine required pack loading - before the initial server load
enableForcedFeaturePacks(packRepository, enabledFeatures);
DataPackConfig selectedPacks1 = getSelectedPacks(packRepository, safeMode);
FeatureFlagSet featureFlagSet = packRepository.getRequestedFeatureFlags().join(enabledFeatures);
@@ -1637,7 +_,7 @@
}
}
- packRepository.setSelected(set);
+ packRepository.setSelected(set, true); // Paper - add pendingReload flag to determine required pack loading - before the initial server start
}
}
@@ -1652,10 +_,11 @@ @@ -1652,10 +_,11 @@
if (this.isEnforceWhitelist()) { if (this.isEnforceWhitelist()) {
PlayerList playerList = commandSource.getServer().getPlayerList(); PlayerList playerList = commandSource.getServer().getPlayerList();

View File

@ -9,6 +9,15 @@
LOGGER.warn("Failed to execute reload", throwable); LOGGER.warn("Failed to execute reload", throwable);
source.sendFailure(Component.translatable("commands.reload.failure")); source.sendFailure(Component.translatable("commands.reload.failure"));
return null; return null;
@@ -24,7 +_,7 @@
}
private static Collection<String> discoverNewPacks(PackRepository packRepository, WorldData worldData, Collection<String> selectedIds) {
- packRepository.reload();
+ packRepository.reload(true); // Paper - will perform a full reload
Collection<String> list = Lists.newArrayList(selectedIds);
Collection<String> disabled = worldData.getDataConfiguration().dataPacks().getDisabled();
@@ -36,6 +_,16 @@ @@ -36,6 +_,16 @@
return list; return list;

View File

@ -29,7 +29,7 @@
removedPassengers(passengers, this.lastPassengers) removedPassengers(passengers, this.lastPassengers)
.forEach( .forEach(
removedPassenger -> { removedPassenger -> {
@@ -102,10 +_,10 @@ @@ -102,13 +_,14 @@
this.lastPassengers = passengers; this.lastPassengers = passengers;
} }
@ -42,7 +42,12 @@
+ MapId mapId = itemFrame.cachedMapId; // Paper - Perf: Cache map ids on item frames + MapId mapId = itemFrame.cachedMapId; // Paper - Perf: Cache map ids on item frames
MapItemSavedData savedData = MapItem.getSavedData(mapId, this.level); MapItemSavedData savedData = MapItem.getSavedData(mapId, this.level);
if (savedData != null) { if (savedData != null) {
for (ServerPlayer serverPlayer : this.level.players()) { - for (ServerPlayer serverPlayer : this.level.players()) {
+ for (final net.minecraft.server.network.ServerPlayerConnection connection : this.trackedPlayers) { // Paper
+ final ServerPlayer serverPlayer = connection.getPlayer(); // Paper
savedData.tickCarriedBy(serverPlayer, item);
Packet<?> updatePacket = savedData.getUpdatePacket(mapId, serverPlayer);
if (updatePacket != null) {
@@ -141,7 +_,13 @@ @@ -141,7 +_,13 @@
} else { } else {
this.teleportDelay++; this.teleportDelay++;

View File

@ -1342,17 +1342,18 @@
} }
public SectionPos getLastSectionPos() { public SectionPos getLastSectionPos() {
@@ -1930,21 +_,54 @@ @@ -1930,21 +_,55 @@
} }
@Override @Override
- public ItemEntity drop(ItemStack droppedItem, boolean dropAround, boolean traceItem) { - public ItemEntity drop(ItemStack droppedItem, boolean dropAround, boolean traceItem) {
+ public ItemEntity drop(ItemStack droppedItem, boolean dropAround, boolean traceItem, boolean callEvent) { // CraftBukkit - SPIGOT-2942: Add boolean to call event + public ItemEntity drop(ItemStack droppedItem, boolean dropAround, boolean traceItem, boolean callEvent, @Nullable java.util.function.Consumer<org.bukkit.entity.Item> entityOperation) { // Paper start - Extend HumanEntity#dropItem API
ItemEntity itemEntity = this.createItemStackToDrop(droppedItem, dropAround, traceItem); ItemEntity itemEntity = this.createItemStackToDrop(droppedItem, dropAround, traceItem);
if (itemEntity == null) { if (itemEntity == null) {
return null; return null;
} else { } else {
+ // CraftBukkit start - fire PlayerDropItemEvent + // CraftBukkit start - fire PlayerDropItemEvent
+ if (entityOperation != null) entityOperation.accept((org.bukkit.entity.Item) itemEntity.getBukkitEntity());
+ if (callEvent) { + if (callEvent) {
+ org.bukkit.entity.Player player = this.getBukkitEntity(); + org.bukkit.entity.Player player = this.getBukkitEntity();
+ org.bukkit.entity.Item drop = (org.bukkit.entity.Item) itemEntity.getBukkitEntity(); + org.bukkit.entity.Item drop = (org.bukkit.entity.Item) itemEntity.getBukkitEntity();

View File

@ -95,7 +95,7 @@
} }
} }
@@ -88,30 +_,117 @@ @@ -88,30 +_,119 @@
public void handlePong(ServerboundPongPacket packet) { public void handlePong(ServerboundPongPacket packet) {
} }
@ -208,15 +208,16 @@
Profiler.get().push("keepAlive"); Profiler.get().push("keepAlive");
long millis = Util.getMillis(); long millis = Util.getMillis();
- if (!this.isSingleplayerOwner() && millis - this.keepAliveTime >= 15000L) { - if (!this.isSingleplayerOwner() && millis - this.keepAliveTime >= 15000L) {
- if (this.keepAlivePending) {
- this.disconnect(TIMEOUT_DISCONNECTION_MESSAGE);
+ // Paper start - give clients a longer time to respond to pings as per pre 1.12.2 timings + // 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 + // This should effectively place the keepalive handling back to "as it was" before 1.12.2
+ final long elapsedTime = millis - this.keepAliveTime; + final long elapsedTime = millis - this.keepAliveTime;
+ if (!this.isSingleplayerOwner() && elapsedTime >= 15000L) { // use vanilla's 15000L between keep alive packets + if (!this.isSingleplayerOwner() && elapsedTime >= 15000L) { // use vanilla's 15000L between keep alive packets
+ if (this.keepAlivePending && !this.processedDisconnect && elapsedTime >= KEEPALIVE_LIMIT) { // check keepalive limit, don't fire if already disconnected if (this.keepAlivePending) {
- this.disconnect(TIMEOUT_DISCONNECTION_MESSAGE);
+ 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 + // Paper end - give clients a longer time to respond to pings as per pre 1.12.2 timings
+ this.disconnect(TIMEOUT_DISCONNECTION_MESSAGE, org.bukkit.event.player.PlayerKickEvent.Cause.TIMEOUT); // Paper - kick event cause
} else if (this.checkIfClosed(millis)) { } else if (this.checkIfClosed(millis)) {
this.keepAlivePending = true; this.keepAlivePending = true;
this.keepAliveTime = millis; this.keepAliveTime = millis;

View File

@ -0,0 +1,76 @@
--- a/net/minecraft/server/packs/repository/PackRepository.java
+++ b/net/minecraft/server/packs/repository/PackRepository.java
@@ -21,9 +_,13 @@
private final Set<RepositorySource> sources;
private Map<String, Pack> available = ImmutableMap.of();
private List<Pack> selected = ImmutableList.of();
+ private final net.minecraft.world.level.validation.DirectoryValidator validator; // Paper - add validator
- public PackRepository(RepositorySource... sources) {
- this.sources = ImmutableSet.copyOf(sources);
+ // Paper start - add validator
+ public PackRepository(net.minecraft.world.level.validation.DirectoryValidator validator, RepositorySource... providers) {
+ this.validator = validator;
+ // Paper end - add validator
+ this.sources = ImmutableSet.copyOf(providers);
}
public static String displayPackList(Collection<Pack> packs) {
@@ -31,9 +_,14 @@
}
public void reload() {
+ // Paper start - add pendingReload flag to determine required pack loading
+ this.reload(false);
+ }
+ public void reload(final boolean pendingReload) {
+ // Paper end - add pendingReload flag to determine required pack loading
List<String> list = this.selected.stream().map(Pack::getId).collect(ImmutableList.toImmutableList());
this.available = this.discoverAvailable();
- this.selected = this.rebuildSelected(list);
+ this.selected = this.rebuildSelected(list, pendingReload); // Paper - add pendingReload flag to determine required pack loading
}
private Map<String, Pack> discoverAvailable() {
@@ -43,16 +_,23 @@
repositorySource.loadPacks(pack -> map.put(pack.getId(), pack));
}
- return ImmutableMap.copyOf(map);
+ // Paper start - custom plugin-loaded datapacks
+ final io.papermc.paper.datapack.PaperDatapackRegistrar registrar = new io.papermc.paper.datapack.PaperDatapackRegistrar(this.validator, map);
+ io.papermc.paper.plugin.lifecycle.event.LifecycleEventRunner.INSTANCE.callStaticRegistrarEvent(io.papermc.paper.plugin.lifecycle.event.types.LifecycleEvents.DATAPACK_DISCOVERY,
+ registrar,
+ io.papermc.paper.plugin.bootstrap.BootstrapContext.class
+ );
+ return ImmutableMap.copyOf(registrar.discoveredPacks);
+ // Paper end - custom plugin-loaded datapacks
}
public boolean isAbleToClearAnyPack() {
- List<Pack> list = this.rebuildSelected(List.of());
+ List<Pack> list = this.rebuildSelected(List.of(), false); // Paper - add pendingReload flag to determine required pack loading
return !this.selected.equals(list);
}
- public void setSelected(Collection<String> ids) {
- this.selected = this.rebuildSelected(ids);
+ public void setSelected(Collection<String> ids, final boolean pendingReload) { // Paper - add pendingReload flag to determine required pack loading
+ this.selected = this.rebuildSelected(ids, pendingReload); // Paper - add pendingReload flag to determine required pack loading
}
public boolean addPack(String id) {
@@ -79,11 +_,11 @@
}
}
- private List<Pack> rebuildSelected(Collection<String> ids) {
+ private List<Pack> rebuildSelected(Collection<String> ids, boolean pendingReload) { // Paper - add pendingReload flag to determine required pack loading
List<Pack> list = this.getAvailablePacks(ids).collect(Util.toMutableList());
for (Pack pack : this.available.values()) {
- if (pack.isRequired() && !list.contains(pack)) {
+ if (pack.isRequired() && !list.contains(pack) && pendingReload) { // Paper - add pendingReload flag to determine required pack loading
pack.getDefaultPosition().insert(list, pack, Pack::selectionConfig, false);
}
}

View File

@ -9,7 +9,7 @@
.applyDevelopmentConfig() .applyDevelopmentConfig()
.pushJarResources() .pushJarResources()
.build(VANILLA_PACK_INFO); .build(VANILLA_PACK_INFO);
@@ -68,7 +_,18 @@ @@ -68,15 +_,26 @@
@Nullable @Nullable
@Override @Override
protected Pack createBuiltinPack(String id, Pack.ResourcesSupplier resources, Component title) { protected Pack createBuiltinPack(String id, Pack.ResourcesSupplier resources, Component title) {
@ -29,3 +29,13 @@
} }
public static PackRepository createPackRepository(Path folder, DirectoryValidator validator) { public static PackRepository createPackRepository(Path folder, DirectoryValidator validator) {
- return new PackRepository(new ServerPacksSource(validator), new FolderRepositorySource(folder, PackType.SERVER_DATA, PackSource.WORLD, validator));
+ return new PackRepository(validator, new ServerPacksSource(validator), new FolderRepositorySource(folder, PackType.SERVER_DATA, PackSource.WORLD, validator)); // Paper - add validator
}
public static PackRepository createVanillaTrustedRepository() {
- return new PackRepository(new ServerPacksSource(new DirectoryValidator(path -> true)));
+ return new PackRepository(new DirectoryValidator(path -> true), new ServerPacksSource(new DirectoryValidator(path -> true))); // Paper - add validator
}
public static PackRepository createPackRepository(LevelStorageSource.LevelStorageAccess level) {

View File

@ -706,52 +706,44 @@
public void awardKillScore(Entity entity, DamageSource damageSource) { public void awardKillScore(Entity entity, DamageSource damageSource) {
if (entity instanceof ServerPlayer) { if (entity instanceof ServerPlayer) {
@@ -1752,34 +_,70 @@ @@ -1752,15 +_,22 @@
} }
public boolean saveAsPassenger(CompoundTag compound) { public boolean saveAsPassenger(CompoundTag compound) {
- if (this.removalReason != null && !this.removalReason.shouldSave()) {
+ // CraftBukkit start - allow excluding certain data when saving + // CraftBukkit start - allow excluding certain data when saving
+ return this.saveAsPassenger(compound, true); + // Paper start - Raw entity serialization API
+ return this.saveAsPassenger(compound, true, false, false);
+ } + }
+ + public boolean saveAsPassenger(CompoundTag compound, boolean includeAll, boolean includeNonSaveable, boolean forceSerialization) {
+ public boolean saveAsPassenger(CompoundTag compound, boolean includeAll) { + // Paper end - Raw entity serialization API
+ // CraftBukkit end + // CraftBukkit end
if (this.removalReason != null && !this.removalReason.shouldSave()) { + if (this.removalReason != null && !this.removalReason.shouldSave() && !forceSerialization) { // Paper - Raw entity serialization API
return false; return false;
} else { } else {
String encodeId = this.getEncodeId(); - String encodeId = this.getEncodeId();
- if (encodeId == null) { - if (encodeId == null) {
+ if (!this.persist || encodeId == null) { // CraftBukkit - persist flag + String encodeId = this.getEncodeId(includeNonSaveable); // Paper - Raw entity serialization API
+ if ((!this.persist && !forceSerialization) || encodeId == null) { // CraftBukkit - persist flag // Paper - Raw entity serialization API
return false; return false;
} else { } else {
compound.putString("id", encodeId); compound.putString("id", encodeId);
- this.saveWithoutId(compound); - this.saveWithoutId(compound);
+ this.saveWithoutId(compound, includeAll); // CraftBukkit - pass on includeAll + this.saveWithoutId(compound, includeAll, includeNonSaveable, forceSerialization); // CraftBukkit - pass on includeAll // Paper - Raw entity serialization API
return true; return true;
} }
} }
} @@ -1771,15 +_,37 @@
+
+ // Paper start - Entity serialization api
+ public boolean serializeEntity(CompoundTag compound) {
+ List<Entity> pass = new java.util.ArrayList<>(this.getPassengers());
+ this.passengers = ImmutableList.of();
+ boolean result = save(compound);
+ this.passengers = ImmutableList.copyOf(pass);
+ return result;
+ }
+ // Paper end - Entity serialization api
public boolean save(CompoundTag compound) {
return !this.isPassenger() && this.saveAsPassenger(compound);
} }
public CompoundTag saveWithoutId(CompoundTag compound) { public CompoundTag saveWithoutId(CompoundTag compound) {
+ // CraftBukkit start - allow excluding certain data when saving + // CraftBukkit start - allow excluding certain data when saving
+ return this.saveWithoutId(compound, true); + // Paper start - Raw entity serialization API
+ return this.saveWithoutId(compound, true, false, false);
+ } + }
+ +
+ public CompoundTag saveWithoutId(CompoundTag compound, boolean includeAll) { + public CompoundTag saveWithoutId(CompoundTag compound, boolean includeAll, boolean includeNonSaveable, boolean forceSerialization) {
+ // Paper end - Raw entity serialization API
+ // CraftBukkit end + // CraftBukkit end
try { try {
- if (this.vehicle != null) { - if (this.vehicle != null) {
@ -827,7 +819,7 @@
for (Entity entity : this.getPassengers()) { for (Entity entity : this.getPassengers()) {
CompoundTag compoundTag = new CompoundTag(); CompoundTag compoundTag = new CompoundTag();
- if (entity.saveAsPassenger(compoundTag)) { - if (entity.saveAsPassenger(compoundTag)) {
+ if (entity.saveAsPassenger(compoundTag, includeAll)) { // CraftBukkit - pass on includeAll + if (entity.saveAsPassenger(compoundTag, includeAll, includeNonSaveable, forceSerialization)) { // CraftBukkit - pass on includeAll // Paper - Raw entity serialization API
listTag.add(compoundTag); listTag.add(compoundTag);
} }
} }
@ -935,19 +927,30 @@
} catch (Throwable var17) { } catch (Throwable var17) {
CrashReport crashReport = CrashReport.forThrowable(var17, "Loading entity NBT"); CrashReport crashReport = CrashReport.forThrowable(var17, "Loading entity NBT");
CrashReportCategory crashReportCategory = crashReport.addCategory("Entity being loaded"); CrashReportCategory crashReportCategory = crashReport.addCategory("Entity being loaded");
@@ -1949,6 +_,12 @@ @@ -1944,10 +_,21 @@
return type.canSerialize() && key != null ? key.toString() : null;
}
@Nullable
public final String getEncodeId() {
+ // Paper start - Raw entity serialization API
+ return getEncodeId(false);
+ }
+ public final @Nullable String getEncodeId(boolean includeNonSaveable) {
+ // Paper end - Raw entity serialization API
EntityType<?> type = this.getType();
ResourceLocation key = EntityType.getKey(type);
- return type.canSerialize() && key != null ? key.toString() : null;
- }
+ return (type.canSerialize() || includeNonSaveable) && key != null ? key.toString() : null; // Paper - Raw entity serialization API
+ }
+
+ // CraftBukkit start - allow excluding certain data when saving + // CraftBukkit start - allow excluding certain data when saving
+ protected void addAdditionalSaveData(CompoundTag tag, boolean includeAll) { + protected void addAdditionalSaveData(CompoundTag tag, boolean includeAll) {
+ this.addAdditionalSaveData(tag); + this.addAdditionalSaveData(tag);
+ } + }
+ // CraftBukkit end + // CraftBukkit end
+
protected abstract void readAdditionalSaveData(CompoundTag tag); protected abstract void readAdditionalSaveData(CompoundTag tag);
protected abstract void addAdditionalSaveData(CompoundTag tag);
@@ -1990,11 +_,61 @@ @@ -1990,11 +_,61 @@
@Nullable @Nullable

View File

@ -48,7 +48,12 @@
List<Entity> entities = this.level() List<Entity> entities = this.level()
.getEntities( .getEntities(
this, this,
@@ -172,22 +_,30 @@ @@ -168,26 +_,34 @@
}
private void spawnFire(int extraIgnitions) {
- if (!this.visualOnly && this.level() instanceof ServerLevel serverLevel && serverLevel.getGameRules().getBoolean(GameRules.RULE_DOFIRETICK)) {
+ if (!this.visualOnly && !this.isEffect && this.level() instanceof ServerLevel serverLevel && serverLevel.getGameRules().getBoolean(GameRules.RULE_DOFIRETICK)) { // Paper - prevent any fire if only effect
BlockPos blockPos = this.blockPosition(); BlockPos blockPos = this.blockPosition();
BlockState state = BaseFireBlock.getState(this.level(), blockPos); BlockState state = BaseFireBlock.getState(this.level(), blockPos);
if (this.level().getBlockState(blockPos).isAir() && state.canSurvive(this.level(), blockPos)) { if (this.level().getBlockState(blockPos).isAir() && state.canSurvive(this.level(), blockPos)) {

View File

@ -112,16 +112,21 @@
this.removeEntitiesOnShoulder(); this.removeEntitiesOnShoulder();
} }
} }
@@ -717,6 +_,13 @@ @@ -717,6 +_,18 @@
@Nullable @Nullable
public ItemEntity drop(ItemStack droppedItem, boolean dropAround, boolean includeThrowerName) { public ItemEntity drop(ItemStack droppedItem, boolean dropAround, boolean includeThrowerName) {
+ // CraftBukkit start - SPIGOT-2942: Add boolean to call event + // CraftBukkit start - SPIGOT-2942: Add boolean to call event
+ return this.drop(droppedItem, dropAround, includeThrowerName, true); + return this.drop(droppedItem, dropAround, includeThrowerName, true, null);
+ } + }
+ +
+ @Nullable + @Nullable
+ public ItemEntity drop(ItemStack droppedItem, boolean dropAround, boolean includeThrowerName, boolean callEvent) { + public ItemEntity drop(ItemStack droppedItem, boolean dropAround, boolean includeThrowerName, boolean callEvent) {
+ return this.drop(droppedItem, dropAround, includeThrowerName, callEvent, null);
+ }
+
+ @Nullable
+ public ItemEntity drop(ItemStack droppedItem, boolean dropAround, boolean includeThrowerName, boolean callEvent, @Nullable java.util.function.Consumer<org.bukkit.entity.Item> entityOperation) {
+ // CraftBukkit end + // CraftBukkit end
if (!droppedItem.isEmpty() && this.level().isClientSide) { if (!droppedItem.isEmpty() && this.level().isClientSide) {
this.swing(InteractionHand.MAIN_HAND); this.swing(InteractionHand.MAIN_HAND);

View File

@ -34,9 +34,9 @@
- BlockState blockState = this.getBlockState(traversePos); - BlockState blockState = this.getBlockState(traversePos);
- FluidState fluidState = this.getFluidState(traversePos); - FluidState fluidState = this.getFluidState(traversePos);
+ // CraftBukkit start - moved block handling into separate method for use by Block#rayTrace + // CraftBukkit start - moved block handling into separate method for use by Block#rayTrace
+ default BlockHitResult clip(ClipContext raytrace1, BlockPos blockposition) { + default BlockHitResult clip(ClipContext traverseContext, BlockPos traversePos) {
+ // Paper start - Add predicate for blocks when raytracing + // Paper start - Add predicate for blocks when raytracing
+ return clip(raytrace1, blockposition, null); + return clip(traverseContext, traversePos, null);
+ } + }
+ +
+ default BlockHitResult clip(ClipContext traverseContext, BlockPos traversePos, java.util.function.Predicate<? super org.bukkit.block.Block> canCollide) { + default BlockHitResult clip(ClipContext traverseContext, BlockPos traversePos, java.util.function.Predicate<? super org.bukkit.block.Block> canCollide) {

View File

@ -5,11 +5,11 @@
} }
- if (!canSetSpawn(level)) { - if (!canSetSpawn(level)) {
+ if (false && !canSetSpawn(level)) { // CraftBukkit - moved world and biome check into EntityHuman + if (false && !canSetSpawn(level)) { // CraftBukkit - moved world and biome check into Player
level.removeBlock(pos, false); level.removeBlock(pos, false);
BlockPos blockPos = pos.relative(state.getValue(FACING).getOpposite()); BlockPos blockPos = pos.relative(state.getValue(FACING).getOpposite());
if (level.getBlockState(blockPos).is(this)) { if (level.getBlockState(blockPos).is(this)) {
@@ -103,22 +_,62 @@ @@ -103,22 +_,56 @@
level.explode(null, level.damageSources().badRespawnPointExplosion(center), null, center, 5.0F, true, Level.ExplosionInteraction.BLOCK); level.explode(null, level.damageSources().badRespawnPointExplosion(center), null, center, 5.0F, true, Level.ExplosionInteraction.BLOCK);
return InteractionResult.SUCCESS_SERVER; return InteractionResult.SUCCESS_SERVER;
} else if (state.getValue(OCCUPIED)) { } else if (state.getValue(OCCUPIED)) {
@ -21,20 +21,20 @@
return InteractionResult.SUCCESS_SERVER; return InteractionResult.SUCCESS_SERVER;
} else { } else {
+ // CraftBukkit start + // CraftBukkit start
+ BlockState finaliblockdata = state; + final BlockState finalBlockState = state;
+ BlockPos finalblockposition = pos; + final BlockPos finalBlockPos = pos;
+ // CraftBukkit end + // CraftBukkit end
player.startSleepInBed(pos).ifLeft(bedSleepingProblem -> { player.startSleepInBed(pos).ifLeft(bedSleepingProblem -> {
+ // Paper start - PlayerBedFailEnterEvent + // Paper start - PlayerBedFailEnterEvent
+ if (bedSleepingProblem != null) { + if (bedSleepingProblem != null) {
+ io.papermc.paper.event.player.PlayerBedFailEnterEvent event = new io.papermc.paper.event.player.PlayerBedFailEnterEvent((org.bukkit.entity.Player) player.getBukkitEntity(), io.papermc.paper.event.player.PlayerBedFailEnterEvent.FailReason.values()[bedSleepingProblem.ordinal()], org.bukkit.craftbukkit.block.CraftBlock.at(level, finalblockposition), !level.dimensionType().bedWorks(), io.papermc.paper.adventure.PaperAdventure.asAdventure(bedSleepingProblem.getMessage())); + io.papermc.paper.event.player.PlayerBedFailEnterEvent event = new io.papermc.paper.event.player.PlayerBedFailEnterEvent((org.bukkit.entity.Player) player.getBukkitEntity(), io.papermc.paper.event.player.PlayerBedFailEnterEvent.FailReason.values()[bedSleepingProblem.ordinal()], org.bukkit.craftbukkit.block.CraftBlock.at(level, finalBlockPos), !level.dimensionType().bedWorks(), io.papermc.paper.adventure.PaperAdventure.asAdventure(bedSleepingProblem.getMessage()));
+ if (!event.callEvent()) { + if (!event.callEvent()) {
+ return; + return;
+ } + }
+ // Paper end - PlayerBedFailEnterEvent + // Paper end - PlayerBedFailEnterEvent
+ // CraftBukkit start - handling bed explosion from below here + // CraftBukkit start - handling bed explosion from below here
+ if (event.getWillExplode()) { // Paper - PlayerBedFailEnterEvent + if (event.getWillExplode()) { // Paper - PlayerBedFailEnterEvent
+ this.explodeBed(finaliblockdata, level, finalblockposition); + this.explodeBed(finalBlockState, level, finalBlockPos);
+ } else + } else
+ // CraftBukkit end + // CraftBukkit end
if (bedSleepingProblem.getMessage() != null) { if (bedSleepingProblem.getMessage() != null) {
@ -49,24 +49,18 @@
} }
} }
+ // CraftBukkit start + // CraftBukkit start - Copied from the above method
+ private InteractionResult explodeBed(BlockState iblockdata, Level world, BlockPos blockposition) { + private InteractionResult explodeBed(BlockState state, Level level, BlockPos pos) {
+ { + org.bukkit.block.BlockState blockState = org.bukkit.craftbukkit.block.CraftBlock.at(level, pos).getState(); // CraftBukkit - capture BlockState before remove block
+ { + level.removeBlock(pos, false);
+ org.bukkit.block.BlockState blockState = org.bukkit.craftbukkit.block.CraftBlock.at(world, blockposition).getState(); // CraftBukkit - capture BlockState before remove block + BlockPos blockPos = pos.relative(state.getValue(FACING).getOpposite());
+ world.removeBlock(blockposition, false); + if (level.getBlockState(blockPos).is(this)) {
+ BlockPos blockposition1 = blockposition.relative(((Direction) iblockdata.getValue(BedBlock.FACING)).getOpposite()); + level.removeBlock(blockPos, false);
+ }
+ +
+ if (world.getBlockState(blockposition1).getBlock() == this) { + Vec3 center = pos.getCenter();
+ world.removeBlock(blockposition1, false); + level.explode(null, level.damageSources().badRespawnPointExplosion(center, blockState), null, center, 5.0F, true, Level.ExplosionInteraction.BLOCK); // CraftBukkit - add state
+ } + return InteractionResult.SUCCESS_SERVER;
+
+ Vec3 vec3d = blockposition.getCenter();
+
+ world.explode(null, world.damageSources().badRespawnPointExplosion(vec3d, blockState), null, vec3d, 5.0F, true, Level.ExplosionInteraction.BLOCK); // CraftBukkit - add state
+ return InteractionResult.SUCCESS;
+ }
+ }
+ } + }
+ // CraftBukkit end + // CraftBukkit end
+ +

View File

@ -19,8 +19,8 @@
- this.setTiltAndScheduleTick(state, level, pos, Tilt.UNSTABLE, null); - this.setTiltAndScheduleTick(state, level, pos, Tilt.UNSTABLE, null);
+ // CraftBukkit start - tilt dripleaf + // CraftBukkit start - tilt dripleaf
+ org.bukkit.event.Cancellable cancellable; + org.bukkit.event.Cancellable cancellable;
+ if (entity instanceof net.minecraft.world.entity.player.Player) { + if (entity instanceof net.minecraft.world.entity.player.Player player) {
+ cancellable = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerInteractEvent((net.minecraft.world.entity.player.Player) entity, org.bukkit.event.block.Action.PHYSICAL, pos, null, null, null); + cancellable = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerInteractEvent(player, org.bukkit.event.block.Action.PHYSICAL, pos, null, null, null);
+ } else { + } else {
+ cancellable = new org.bukkit.event.entity.EntityInteractEvent(entity.getBukkitEntity(), level.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ())); + cancellable = new org.bukkit.event.entity.EntityInteractEvent(entity.getBukkitEntity(), level.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()));
+ level.getCraftServer().getPluginManager().callEvent((org.bukkit.event.entity.EntityInteractEvent) cancellable); + level.getCraftServer().getPluginManager().callEvent((org.bukkit.event.entity.EntityInteractEvent) cancellable);

View File

@ -133,7 +133,7 @@
+ return 0; // CraftBukkit + return 0; // CraftBukkit
+ } + }
+ // CraftBukkit start + // CraftBukkit start
+ public int getExpDrop(BlockState iblockdata, ServerLevel worldserver, BlockPos blockposition, ItemStack itemstack, boolean flag) { + public int getExpDrop(BlockState state, ServerLevel level, BlockPos pos, ItemStack stack, boolean dropExperience) {
+ return 0; + return 0;
+ } + }
+ // CraftBukkit end + // CraftBukkit end

View File

@ -1,13 +1,5 @@
--- a/net/minecraft/world/level/block/BushBlock.java --- a/net/minecraft/world/level/block/BushBlock.java
+++ b/net/minecraft/world/level/block/BushBlock.java +++ b/net/minecraft/world/level/block/BushBlock.java
@@ -6,6 +_,7 @@
import net.minecraft.tags.BlockTags;
import net.minecraft.util.RandomSource;
import net.minecraft.world.level.BlockGetter;
+import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.ScheduledTickAccess;
import net.minecraft.world.level.block.state.BlockBehaviour;
@@ -35,9 +_,15 @@ @@ -35,9 +_,15 @@
BlockState neighborState, BlockState neighborState,
RandomSource random RandomSource random
@ -18,7 +10,7 @@
+ // CraftBukkit start + // CraftBukkit start
+ if (!state.canSurvive(level, pos)) { + if (!state.canSurvive(level, pos)) {
+ // Suppress during worldgen + // Suppress during worldgen
+ if (!(level instanceof net.minecraft.server.level.ServerLevel world1 && world1.hasPhysicsEvent) || !org.bukkit.craftbukkit.event.CraftEventFactory.callBlockPhysicsEvent(world1, pos).isCancelled()) { // Paper + if (!(level instanceof net.minecraft.server.level.ServerLevel serverLevel && serverLevel.hasPhysicsEvent) || !org.bukkit.craftbukkit.event.CraftEventFactory.callBlockPhysicsEvent(serverLevel, pos).isCancelled()) { // Paper
+ return Blocks.AIR.defaultBlockState(); + return Blocks.AIR.defaultBlockState();
+ } + }
+ } + }

View File

@ -29,7 +29,7 @@
- player.getFoodData().eat(2, 0.1F); - player.getFoodData().eat(2, 0.1F);
- int bitesValue = state.getValue(BITES); - int bitesValue = state.getValue(BITES);
+ // CraftBukkit start + // CraftBukkit start
+ // entityhuman.getFoodData().eat(2, 0.1F); + // player.getFoodData().eat(2, 0.1F);
+ int oldFoodLevel = player.getFoodData().foodLevel; + int oldFoodLevel = player.getFoodData().foodLevel;
+ +
+ org.bukkit.event.entity.FoodLevelChangeEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callFoodLevelChangeEvent(player, 2 + oldFoodLevel); + org.bukkit.event.entity.FoodLevelChangeEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callFoodLevelChangeEvent(player, 2 + oldFoodLevel);

View File

@ -10,8 +10,8 @@
+ return InteractionResult.SUCCESS; + return InteractionResult.SUCCESS;
+ } + }
+ +
+ if (entity instanceof net.minecraft.world.entity.player.Player) { + if (entity instanceof net.minecraft.world.entity.player.Player player) {
+ org.bukkit.event.player.PlayerHarvestBlockEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerHarvestBlockEvent(level, pos, (net.minecraft.world.entity.player.Player) entity, net.minecraft.world.InteractionHand.MAIN_HAND, java.util.Collections.singletonList(new ItemStack(Items.GLOW_BERRIES, 1))); + org.bukkit.event.player.PlayerHarvestBlockEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerHarvestBlockEvent(level, pos, player, net.minecraft.world.InteractionHand.MAIN_HAND, java.util.Collections.singletonList(new ItemStack(Items.GLOW_BERRIES, 1)));
+ if (event.isCancelled()) { + if (event.isCancelled()) {
+ return InteractionResult.SUCCESS; // We need to return a success either way, because making it PASS or FAIL will result in a bug where cancelling while harvesting w/ block in hand places block + return InteractionResult.SUCCESS; // We need to return a success either way, because making it PASS or FAIL will result in a bug where cancelling while harvesting w/ block in hand places block
+ } + }

View File

@ -39,8 +39,8 @@
public static BlockState extractProduce(Entity entity, BlockState state, Level level, BlockPos pos) { public static BlockState extractProduce(Entity entity, BlockState state, Level level, BlockPos pos) {
+ // CraftBukkit start + // CraftBukkit start
+ if (entity != null && !(entity instanceof Player)) { + if (entity != null && !(entity instanceof Player)) {
+ BlockState iblockdata1 = ComposterBlock.empty(entity, state, org.bukkit.craftbukkit.util.DummyGeneratorAccess.INSTANCE, pos); + BlockState emptyState = ComposterBlock.empty(entity, state, org.bukkit.craftbukkit.util.DummyGeneratorAccess.INSTANCE, pos);
+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(entity, pos, iblockdata1)) { + if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(entity, pos, emptyState)) {
+ return state; + return state;
+ } + }
+ } + }
@ -100,9 +100,9 @@
public static class EmptyContainer extends SimpleContainer implements WorldlyContainer { public static class EmptyContainer extends SimpleContainer implements WorldlyContainer {
- public EmptyContainer() { - public EmptyContainer() {
+ public EmptyContainer(LevelAccessor generatoraccess, BlockPos blockposition) { // CraftBukkit + public EmptyContainer(LevelAccessor levelAccessor, BlockPos blockPos) { // CraftBukkit
super(0); super(0);
+ this.bukkitOwner = new org.bukkit.craftbukkit.inventory.CraftBlockInventoryHolder(generatoraccess, blockposition, this); // CraftBukkit + this.bukkitOwner = new org.bukkit.craftbukkit.inventory.CraftBlockInventoryHolder(levelAccessor, blockPos, this); // CraftBukkit
} }
@Override @Override

View File

@ -31,8 +31,8 @@
+ +
+ org.bukkit.inventory.Inventory destinationInventory; + org.bukkit.inventory.Inventory destinationInventory;
+ // Have to special case large chests as they work oddly + // Have to special case large chests as they work oddly
+ if (containerAt instanceof CompoundContainer) { + if (containerAt instanceof CompoundContainer compoundContainer) {
+ destinationInventory = new org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest((CompoundContainer) containerAt); + destinationInventory = new org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest(compoundContainer);
+ } else { + } else {
+ destinationInventory = containerAt.getOwner().getInventory(); + destinationInventory = containerAt.getOwner().getInventory();
+ } + }
@ -57,8 +57,8 @@
+ +
+ org.bukkit.inventory.Inventory destinationInventory; + org.bukkit.inventory.Inventory destinationInventory;
+ // Have to special case large chests as they work oddly + // Have to special case large chests as they work oddly
+ if (containerAt instanceof CompoundContainer) { + if (containerAt instanceof CompoundContainer compoundContainer) {
+ destinationInventory = new org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest((CompoundContainer) containerAt); + destinationInventory = new org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest(compoundContainer);
+ } else { + } else {
+ destinationInventory = containerAt.getOwner().getInventory(); + destinationInventory = containerAt.getOwner().getInventory();
+ } + }

View File

@ -4,16 +4,15 @@
@Override @Override
protected void spawnAfterBreak(BlockState state, ServerLevel level, BlockPos pos, ItemStack stack, boolean dropExperience) { protected void spawnAfterBreak(BlockState state, ServerLevel level, BlockPos pos, ItemStack stack, boolean dropExperience) {
super.spawnAfterBreak(state, level, pos, stack, dropExperience); super.spawnAfterBreak(state, level, pos, stack, dropExperience);
- if (dropExperience) {
- this.tryDropExperience(level, pos, stack, this.xpRange);
- }
+ // CraftBukkit start - Delegate to getExpDrop + // CraftBukkit start - Delegate to getExpDrop
+ } + }
+ +
+ @Override + @Override
+ public int getExpDrop(BlockState iblockdata, ServerLevel worldserver, BlockPos blockposition, ItemStack itemstack, boolean flag) { + public int getExpDrop(BlockState state, ServerLevel level, BlockPos pos, ItemStack stack, boolean dropExperience) {
+ if (flag) { if (dropExperience) {
+ return this.tryDropExperience(worldserver, blockposition, itemstack, this.xpRange); - this.tryDropExperience(level, pos, stack, this.xpRange);
- }
+ return this.tryDropExperience(level, pos, stack, this.xpRange);
+ } + }
+ +
+ return 0; + return 0;

View File

@ -39,8 +39,8 @@
+ +
+ org.bukkit.inventory.Inventory destinationInventory; + org.bukkit.inventory.Inventory destinationInventory;
+ // Have to special case large chests as they work oddly + // Have to special case large chests as they work oddly
+ if (containerAt instanceof CompoundContainer) { + if (containerAt instanceof CompoundContainer compoundContainer) {
+ destinationInventory = new org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest((CompoundContainer) containerAt); + destinationInventory = new org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest(compoundContainer);
+ } else { + } else {
+ destinationInventory = containerAt.getOwner().getInventory(); + destinationInventory = containerAt.getOwner().getInventory();
+ } + }

Some files were not shown because too many files have changed in this diff Show More