Some fixes, start updating CustomModelData API
This commit is contained in:
@@ -1,53 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Doc <nachito94@msn.com>
|
||||
Date: Sun, 6 Oct 2024 16:46:36 -0300
|
||||
Subject: [PATCH] Add AnvilView#bypassEnchantmentLevelRestriction
|
||||
|
||||
Anvils, by default, limit applied enchantment levels to their respective
|
||||
maximum level. The added API enables plugins to disable this behaviour,
|
||||
allowing enchantments that are overleveled to be applied via the anvil.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/inventory/AnvilMenu.java b/src/main/java/net/minecraft/world/inventory/AnvilMenu.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/world/inventory/AnvilMenu.java
|
||||
+++ b/src/main/java/net/minecraft/world/inventory/AnvilMenu.java
|
||||
@@ -0,0 +0,0 @@ public class AnvilMenu extends ItemCombinerMenu {
|
||||
public int maximumRepairCost = 40;
|
||||
private CraftAnvilView bukkitEntity;
|
||||
// CraftBukkit end
|
||||
+ public boolean bypassEnchantmentLevelRestriction = false; // Paper - bypass anvil level restrictions
|
||||
|
||||
public AnvilMenu(int syncId, Inventory inventory) {
|
||||
this(syncId, inventory, ContainerLevelAccess.NULL);
|
||||
@@ -0,0 +0,0 @@ public class AnvilMenu extends ItemCombinerMenu {
|
||||
flag2 = true;
|
||||
} else {
|
||||
flag1 = true;
|
||||
- if (i2 > enchantment.getMaxLevel()) {
|
||||
+ if (i2 > enchantment.getMaxLevel() && !this.bypassEnchantmentLevelRestriction) { // Paper - bypass anvil level restrictions
|
||||
i2 = enchantment.getMaxLevel();
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/view/CraftAnvilView.java b/src/main/java/org/bukkit/craftbukkit/inventory/view/CraftAnvilView.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/inventory/view/CraftAnvilView.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/view/CraftAnvilView.java
|
||||
@@ -0,0 +0,0 @@ public class CraftAnvilView extends CraftInventoryView<AnvilMenu, AnvilInventory
|
||||
this.container.maximumRepairCost = cost;
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ @Override
|
||||
+ public boolean bypassesEnchantmentLevelRestriction() {
|
||||
+ return this.container.bypassEnchantmentLevelRestriction;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void bypassEnchantmentLevelRestriction(final boolean bypassEnchantmentLevelRestriction) {
|
||||
+ this.container.bypassEnchantmentLevelRestriction = bypassEnchantmentLevelRestriction;
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
public void updateFromLegacy(CraftInventoryAnvil legacy) {
|
||||
if (legacy.isRepairCostSet()) {
|
||||
this.setRepairCost(legacy.getRepairCost());
|
||||
@@ -1,430 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
Date: Wed, 29 May 2024 19:50:21 -0700
|
||||
Subject: [PATCH] Add FeatureFlag API
|
||||
|
||||
|
||||
diff --git a/src/main/java/io/papermc/paper/world/flag/PaperFeatureDependent.java b/src/main/java/io/papermc/paper/world/flag/PaperFeatureDependent.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/world/flag/PaperFeatureDependent.java
|
||||
@@ -0,0 +0,0 @@
|
||||
+package io.papermc.paper.world.flag;
|
||||
+
|
||||
+import java.util.Set;
|
||||
+import net.minecraft.world.flag.FeatureElement;
|
||||
+import org.bukkit.FeatureFlag;
|
||||
+import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
+import org.jetbrains.annotations.Unmodifiable;
|
||||
+
|
||||
+public interface PaperFeatureDependent extends FeatureDependant {
|
||||
+
|
||||
+ <M extends FeatureElement> M getHandle();
|
||||
+
|
||||
+ @Override
|
||||
+ default @Unmodifiable @NonNull Set<FeatureFlag> requiredFeatures() {
|
||||
+ return PaperFeatureFlagProviderImpl.fromNms(this.getHandle().requiredFeatures());
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/io/papermc/paper/world/flag/PaperFeatureFlagProviderImpl.java b/src/main/java/io/papermc/paper/world/flag/PaperFeatureFlagProviderImpl.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/world/flag/PaperFeatureFlagProviderImpl.java
|
||||
@@ -0,0 +0,0 @@
|
||||
+package io.papermc.paper.world.flag;
|
||||
+
|
||||
+import com.google.common.collect.BiMap;
|
||||
+import com.google.common.collect.ImmutableBiMap;
|
||||
+import java.util.Collections;
|
||||
+import java.util.HashSet;
|
||||
+import java.util.Set;
|
||||
+import net.minecraft.world.flag.FeatureElement;
|
||||
+import net.minecraft.world.flag.FeatureFlagSet;
|
||||
+import net.minecraft.world.flag.FeatureFlags;
|
||||
+import org.bukkit.FeatureFlag;
|
||||
+import org.bukkit.craftbukkit.entity.CraftEntityType;
|
||||
+import org.bukkit.craftbukkit.entity.CraftEntityTypes;
|
||||
+import org.bukkit.craftbukkit.potion.CraftPotionType;
|
||||
+import org.bukkit.craftbukkit.util.CraftMagicNumbers;
|
||||
+import org.bukkit.entity.EntityType;
|
||||
+import org.bukkit.potion.PotionType;
|
||||
+
|
||||
+public class PaperFeatureFlagProviderImpl implements FeatureFlagProvider {
|
||||
+
|
||||
+ public static final BiMap<FeatureFlag, net.minecraft.world.flag.FeatureFlag> FLAGS = ImmutableBiMap.of(
|
||||
+ FeatureFlag.VANILLA, FeatureFlags.VANILLA,
|
||||
+ FeatureFlag.TRADE_REBALANCE, FeatureFlags.TRADE_REBALANCE,
|
||||
+ FeatureFlag.MINECART_IMPROVEMENTS, FeatureFlags.MINECART_IMPROVEMENTS,
|
||||
+ FeatureFlag.REDSTONE_EXPERIMENTS, FeatureFlags.REDSTONE_EXPERIMENTS,
|
||||
+ FeatureFlag.WINTER_DROP, FeatureFlags.WINTER_DROP
|
||||
+ );
|
||||
+
|
||||
+ @Override
|
||||
+ public Set<FeatureFlag> requiredFeatures(final FeatureDependant dependant) {
|
||||
+ final FeatureFlagSet requiredFeatures = getFeatureElement(dependant).requiredFeatures();
|
||||
+ return fromNms(requiredFeatures);
|
||||
+ }
|
||||
+
|
||||
+ public static Set<FeatureFlag> fromNms(final FeatureFlagSet flagSet) {
|
||||
+ final Set<FeatureFlag> flags = new HashSet<>();
|
||||
+ for (final net.minecraft.world.flag.FeatureFlag nmsFlag : FeatureFlags.REGISTRY.names.values()) {
|
||||
+ if (flagSet.contains(nmsFlag)) {
|
||||
+ flags.add(FLAGS.inverse().get(nmsFlag));
|
||||
+ }
|
||||
+ }
|
||||
+ return Collections.unmodifiableSet(flags);
|
||||
+ }
|
||||
+
|
||||
+ static FeatureElement getFeatureElement(final FeatureDependant dependant) {
|
||||
+ if (dependant instanceof final EntityType entityType) {
|
||||
+ // TODO remove when EntityType is server-backed
|
||||
+ return CraftEntityType.bukkitToMinecraft(entityType);
|
||||
+ } else if (dependant instanceof final PotionType potionType) {
|
||||
+ return CraftPotionType.bukkitToMinecraft(potionType);
|
||||
+ } else {
|
||||
+ throw new IllegalArgumentException(dependant + " is not a valid feature dependant");
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftFeatureFlag.java b/src/main/java/org/bukkit/craftbukkit/CraftFeatureFlag.java
|
||||
deleted file mode 100644
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftFeatureFlag.java
|
||||
+++ /dev/null
|
||||
@@ -0,0 +0,0 @@
|
||||
-package org.bukkit.craftbukkit;
|
||||
-
|
||||
-import java.util.HashSet;
|
||||
-import java.util.Set;
|
||||
-import net.minecraft.resources.ResourceLocation;
|
||||
-import net.minecraft.world.flag.FeatureFlagSet;
|
||||
-import net.minecraft.world.flag.FeatureFlags;
|
||||
-import org.bukkit.FeatureFlag;
|
||||
-import org.bukkit.NamespacedKey;
|
||||
-import org.bukkit.craftbukkit.util.CraftNamespacedKey;
|
||||
-import org.jetbrains.annotations.NotNull;
|
||||
-
|
||||
-public class CraftFeatureFlag implements FeatureFlag {
|
||||
-
|
||||
- private final NamespacedKey namespacedKey;
|
||||
- private final net.minecraft.world.flag.FeatureFlag featureFlag;
|
||||
-
|
||||
- public CraftFeatureFlag(ResourceLocation minecraftKey, net.minecraft.world.flag.FeatureFlag featureFlag) {
|
||||
- this.namespacedKey = CraftNamespacedKey.fromMinecraft(minecraftKey);
|
||||
- this.featureFlag = featureFlag;
|
||||
- }
|
||||
-
|
||||
- public net.minecraft.world.flag.FeatureFlag getHandle() {
|
||||
- return this.featureFlag;
|
||||
- }
|
||||
-
|
||||
- @NotNull
|
||||
- @Override
|
||||
- public NamespacedKey getKey() {
|
||||
- return this.namespacedKey;
|
||||
- }
|
||||
-
|
||||
- @Override
|
||||
- public String toString() {
|
||||
- return "CraftFeatureFlag{key=" + this.getKey() + ",keyUniverse=" + this.getHandle().universe.toString() + "}";
|
||||
- }
|
||||
-
|
||||
- public static Set<CraftFeatureFlag> getFromNMS(FeatureFlagSet featureFlagSet) {
|
||||
- Set<CraftFeatureFlag> set = new HashSet<>();
|
||||
- FeatureFlags.REGISTRY.names.forEach((minecraftkey, featureflag) -> {
|
||||
- if (featureFlagSet.contains(featureflag)) {
|
||||
- set.add(new CraftFeatureFlag(minecraftkey, featureflag));
|
||||
- }
|
||||
- });
|
||||
- return set;
|
||||
- }
|
||||
-
|
||||
- public static CraftFeatureFlag getFromNMS(NamespacedKey namespacedKey) {
|
||||
- return FeatureFlags.REGISTRY.names.entrySet().stream().filter(entry -> CraftNamespacedKey.fromMinecraft(entry.getKey()).equals(namespacedKey)).findFirst().map(entry -> new CraftFeatureFlag(entry.getKey(), entry.getValue())).orElse(null);
|
||||
- }
|
||||
-}
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftRegionAccessor.java b/src/main/java/org/bukkit/craftbukkit/CraftRegionAccessor.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftRegionAccessor.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftRegionAccessor.java
|
||||
@@ -0,0 +0,0 @@ public abstract class CraftRegionAccessor implements RegionAccessor {
|
||||
return !this.getHandle().noCollision(aabb);
|
||||
}
|
||||
// Paper end
|
||||
+
|
||||
+ // Paper start - feature flag API
|
||||
+ @Override
|
||||
+ public java.util.Set<org.bukkit.FeatureFlag> getFeatureFlags() {
|
||||
+ return io.papermc.paper.world.flag.PaperFeatureFlagProviderImpl.fromNms(this.getHandle().enabledFeatures());
|
||||
+ }
|
||||
+ // Paper end - feature flag API
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
||||
@@ -0,0 +0,0 @@ public class CraftWorld extends CraftRegionAccessor implements World {
|
||||
return this.persistentDataContainer;
|
||||
}
|
||||
|
||||
- @Override
|
||||
- public Set<FeatureFlag> getFeatureFlags() {
|
||||
- return CraftFeatureFlag.getFromNMS(this.getHandle().enabledFeatures()).stream().map(FeatureFlag.class::cast).collect(Collectors.toUnmodifiableSet());
|
||||
- }
|
||||
+ // Paper - replace feature flag API
|
||||
|
||||
public void storeBukkitValues(CompoundTag c) {
|
||||
if (!this.persistentDataContainer.isEmpty()) {
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockType.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockType.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockType.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockType.java
|
||||
@@ -0,0 +0,0 @@ import org.bukkit.craftbukkit.util.Handleable;
|
||||
import org.bukkit.inventory.ItemType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
-public class CraftBlockType<B extends BlockData> implements BlockType.Typed<B>, Handleable<Block> {
|
||||
+public class CraftBlockType<B extends BlockData> implements BlockType.Typed<B>, Handleable<Block>, io.papermc.paper.world.flag.PaperFeatureDependent { // Paper - feature flag API
|
||||
|
||||
private final NamespacedKey key;
|
||||
private final Block block;
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/generator/CraftWorldInfo.java b/src/main/java/org/bukkit/craftbukkit/generator/CraftWorldInfo.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/generator/CraftWorldInfo.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/generator/CraftWorldInfo.java
|
||||
@@ -0,0 +0,0 @@ public class CraftWorldInfo implements WorldInfo {
|
||||
private final long seed;
|
||||
private final int minHeight;
|
||||
private final int maxHeight;
|
||||
+ private final net.minecraft.world.flag.FeatureFlagSet enabledFeatures; // Paper - feature flag API
|
||||
// Paper start
|
||||
private final net.minecraft.world.level.chunk.ChunkGenerator vanillaChunkGenerator;
|
||||
private final net.minecraft.core.RegistryAccess.Frozen registryAccess;
|
||||
@@ -0,0 +0,0 @@ public class CraftWorldInfo implements WorldInfo {
|
||||
this.seed = ((PrimaryLevelData) worldDataServer).worldGenOptions().seed();
|
||||
this.minHeight = dimensionManager.minY();
|
||||
this.maxHeight = dimensionManager.minY() + dimensionManager.height();
|
||||
+ this.enabledFeatures = worldDataServer.enabledFeatures(); // Paper - feature flag API
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -0,0 +0,0 @@ public class CraftWorldInfo implements WorldInfo {
|
||||
};
|
||||
}
|
||||
// Paper end
|
||||
+
|
||||
+ // Paper start - feature flag API
|
||||
+ @Override
|
||||
+ public java.util.Set<org.bukkit.FeatureFlag> getFeatureFlags() {
|
||||
+ return io.papermc.paper.world.flag.PaperFeatureFlagProviderImpl.fromNms(this.enabledFeatures);
|
||||
+ }
|
||||
+ // Paper end - feature flag API
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemType.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemType.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemType.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemType.java
|
||||
@@ -0,0 +0,0 @@ import org.bukkit.inventory.meta.ItemMeta;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
-public class CraftItemType<M extends ItemMeta> implements ItemType.Typed<M>, Handleable<Item> {
|
||||
+public class CraftItemType<M extends ItemMeta> implements ItemType.Typed<M>, Handleable<Item>, io.papermc.paper.world.flag.PaperFeatureDependent { // Paper - feature flag API
|
||||
|
||||
private final NamespacedKey key;
|
||||
private final Item item;
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMenuType.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMenuType.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMenuType.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMenuType.java
|
||||
@@ -0,0 +0,0 @@ import org.bukkit.entity.HumanEntity;
|
||||
import org.bukkit.inventory.InventoryView;
|
||||
import org.bukkit.inventory.MenuType;
|
||||
|
||||
-public class CraftMenuType<V extends InventoryView> implements MenuType.Typed<V>, Handleable<net.minecraft.world.inventory.MenuType<?>> {
|
||||
+public class CraftMenuType<V extends InventoryView> implements MenuType.Typed<V>, Handleable<net.minecraft.world.inventory.MenuType<?>>, io.papermc.paper.world.flag.PaperFeatureDependent { // Paper - make FeatureDependant
|
||||
|
||||
private final NamespacedKey key;
|
||||
private final net.minecraft.world.inventory.MenuType<?> handle;
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/packs/CraftDataPack.java b/src/main/java/org/bukkit/craftbukkit/packs/CraftDataPack.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/packs/CraftDataPack.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/packs/CraftDataPack.java
|
||||
@@ -0,0 +0,0 @@ import net.minecraft.util.InclusiveRange;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.FeatureFlag;
|
||||
import org.bukkit.NamespacedKey;
|
||||
-import org.bukkit.craftbukkit.CraftFeatureFlag;
|
||||
+// import org.bukkit.craftbukkit.CraftFeatureFlag; // Paper - replace feature flag API
|
||||
import org.bukkit.craftbukkit.CraftServer;
|
||||
import org.bukkit.craftbukkit.util.CraftChatMessage;
|
||||
import org.bukkit.packs.DataPack;
|
||||
@@ -0,0 +0,0 @@ public class CraftDataPack implements DataPack {
|
||||
|
||||
@Override
|
||||
public Set<FeatureFlag> getRequestedFeatures() {
|
||||
- return CraftFeatureFlag.getFromNMS(this.getHandle().getRequestedFeatures()).stream().map(FeatureFlag.class::cast).collect(Collectors.toUnmodifiableSet());
|
||||
+ return io.papermc.paper.world.flag.PaperFeatureFlagProviderImpl.fromNms(this.getHandle().getRequestedFeatures()); // Paper - replace feature flag API
|
||||
}
|
||||
|
||||
@Override
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/potion/CraftPotionEffectType.java b/src/main/java/org/bukkit/craftbukkit/potion/CraftPotionEffectType.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/potion/CraftPotionEffectType.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/potion/CraftPotionEffectType.java
|
||||
@@ -0,0 +0,0 @@ import org.bukkit.potion.PotionEffectType;
|
||||
import org.bukkit.potion.PotionEffectTypeCategory;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
-public class CraftPotionEffectType extends PotionEffectType implements Handleable<MobEffect> {
|
||||
+public class CraftPotionEffectType extends PotionEffectType implements Handleable<MobEffect>, io.papermc.paper.world.flag.PaperFeatureDependent { // Paper - feature flag API
|
||||
|
||||
public static PotionEffectType minecraftHolderToBukkit(Holder<MobEffect> minecraft) {
|
||||
return CraftPotionEffectType.minecraftToBukkit(minecraft.value());
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
|
||||
@@ -0,0 +0,0 @@ import org.bukkit.attribute.Attribute;
|
||||
import org.bukkit.attribute.AttributeModifier;
|
||||
import org.bukkit.block.Biome;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
-import org.bukkit.craftbukkit.CraftFeatureFlag;
|
||||
+// import org.bukkit.craftbukkit.CraftFeatureFlag; // Paper
|
||||
import org.bukkit.craftbukkit.CraftRegistry;
|
||||
import org.bukkit.craftbukkit.CraftServer;
|
||||
import org.bukkit.craftbukkit.block.CraftBiome;
|
||||
@@ -0,0 +0,0 @@ public final class CraftMagicNumbers implements UnsafeValues {
|
||||
return attribute.getTranslationKey();
|
||||
}
|
||||
|
||||
- @Override
|
||||
- public FeatureFlag getFeatureFlag(NamespacedKey namespacedKey) {
|
||||
- Preconditions.checkArgument(namespacedKey != null, "NamespaceKey cannot be null");
|
||||
- return CraftFeatureFlag.getFromNMS(namespacedKey);
|
||||
- }
|
||||
+ // Paper - replace feature flag API
|
||||
|
||||
@Override
|
||||
public PotionType.InternalPotionData getInternalPotionData(NamespacedKey namespacedKey) {
|
||||
diff --git a/src/main/resources/META-INF/services/io.papermc.paper.world.flag.FeatureFlagProvider b/src/main/resources/META-INF/services/io.papermc.paper.world.flag.FeatureFlagProvider
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
||||
--- /dev/null
|
||||
+++ b/src/main/resources/META-INF/services/io.papermc.paper.world.flag.FeatureFlagProvider
|
||||
@@ -0,0 +1 @@
|
||||
+io.papermc.paper.world.flag.PaperFeatureFlagProviderImpl
|
||||
diff --git a/src/main/resources/META-INF/services/io.papermc.paper.world.flag.FeatureFlags$FeatureFlagProvider b/src/main/resources/META-INF/services/io.papermc.paper.world.flag.FeatureFlags$FeatureFlagProvider
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
||||
--- /dev/null
|
||||
+++ b/src/main/resources/META-INF/services/io.papermc.paper.world.flag.FeatureFlags$FeatureFlagProvider
|
||||
@@ -0,0 +1 @@
|
||||
+io.papermc.paper.world.flag.PaperFeatureFlagProviderImpl
|
||||
diff --git a/src/test/java/io/papermc/paper/world/flag/FeatureFlagTest.java b/src/test/java/io/papermc/paper/world/flag/FeatureFlagTest.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
||||
--- /dev/null
|
||||
+++ b/src/test/java/io/papermc/paper/world/flag/FeatureFlagTest.java
|
||||
@@ -0,0 +0,0 @@
|
||||
+package io.papermc.paper.world.flag;
|
||||
+
|
||||
+import io.papermc.paper.adventure.PaperAdventure;
|
||||
+import io.papermc.paper.registry.PaperRegistries;
|
||||
+import io.papermc.paper.registry.RegistryAccess;
|
||||
+import io.papermc.paper.registry.RegistryKey;
|
||||
+import io.papermc.paper.registry.entry.RegistryEntry;
|
||||
+import java.util.HashSet;
|
||||
+import java.util.Set;
|
||||
+import java.util.stream.Stream;
|
||||
+import net.kyori.adventure.key.Key;
|
||||
+import net.minecraft.resources.ResourceKey;
|
||||
+import net.minecraft.resources.ResourceLocation;
|
||||
+import net.minecraft.world.flag.FeatureElement;
|
||||
+import net.minecraft.world.flag.FeatureFlagSet;
|
||||
+import net.minecraft.world.flag.FeatureFlags;
|
||||
+import org.bukkit.FeatureFlag;
|
||||
+import org.bukkit.Keyed;
|
||||
+import org.bukkit.support.RegistryHelper;
|
||||
+import org.bukkit.support.environment.AllFeatures;
|
||||
+import org.junit.jupiter.api.Test;
|
||||
+import org.junit.jupiter.params.ParameterizedTest;
|
||||
+import org.junit.jupiter.params.provider.MethodSource;
|
||||
+
|
||||
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
||||
+import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
+import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
+import static org.junit.jupiter.api.Assertions.assertInstanceOf;
|
||||
+import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
+import static org.junit.jupiter.api.Assertions.fail;
|
||||
+
|
||||
+@AllFeatures
|
||||
+class FeatureFlagTest {
|
||||
+
|
||||
+ @Test
|
||||
+ void testFeatureFlagParity() {
|
||||
+ final Set<ResourceLocation> locations = new HashSet<>();
|
||||
+ for (final FeatureFlag flag : FeatureFlag.ALL_FLAGS.values()) {
|
||||
+ locations.add(PaperAdventure.asVanilla(flag.getKey()));
|
||||
+ }
|
||||
+ FeatureFlags.REGISTRY.fromNames(locations, unknown -> {
|
||||
+ fail("Unknown api feature flag: " + unknown);
|
||||
+ });
|
||||
+
|
||||
+ for (final ResourceLocation nmsFlag : allNames()) {
|
||||
+ assertNotNull(FeatureFlag.ALL_FLAGS.value(Key.key(nmsFlag.toString())), "can't find api flag for " + nmsFlag);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ @Test
|
||||
+ void testFeatureFlagConversion() {
|
||||
+ assertEquals(allNames().size(), PaperFeatureFlagProviderImpl.FLAGS.size());
|
||||
+ for (final FeatureFlag featureFlag : PaperFeatureFlagProviderImpl.FLAGS.keySet()) {
|
||||
+ final net.minecraft.world.flag.FeatureFlag nmsFlag = PaperFeatureFlagProviderImpl.FLAGS.get(featureFlag);
|
||||
+ final ResourceLocation nmsFlagName = FeatureFlags.REGISTRY.toNames(FeatureFlagSet.of(nmsFlag)).iterator().next();
|
||||
+ assertEquals(nmsFlagName.toString(), featureFlag.key().asString());
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ static Set<ResourceLocation> allNames() {
|
||||
+ return FeatureFlags.REGISTRY.toNames(FeatureFlags.REGISTRY.allFlags());
|
||||
+ }
|
||||
+
|
||||
+ @SuppressWarnings({"rawtypes", "unchecked"})
|
||||
+ static Set<RegistryKey<?>> featureFilteredRegistries() {
|
||||
+ final Set<RegistryKey<?>> registryKeys = new HashSet<>();
|
||||
+ for (final ResourceKey filteredRegistry : FeatureElement.FILTERED_REGISTRIES) {
|
||||
+ registryKeys.add(PaperRegistries.registryFromNms(filteredRegistry));
|
||||
+ }
|
||||
+ return registryKeys;
|
||||
+ }
|
||||
+
|
||||
+ @MethodSource("featureFilteredRegistries")
|
||||
+ @ParameterizedTest
|
||||
+ <T extends Keyed> void testApiImplementsFeatureDependant(final RegistryKey<T> registryKey) {
|
||||
+ final org.bukkit.Registry<T> registry = RegistryAccess.registryAccess().getRegistry(registryKey);
|
||||
+ final T anyElement = registry.iterator().next();
|
||||
+ assertInstanceOf(FeatureDependant.class, anyElement, "Registry " + registryKey + " doesn't have feature dependent elements");
|
||||
+ final FeatureDependant dependant = ((FeatureDependant) anyElement);
|
||||
+ assertDoesNotThrow(dependant::requiredFeatures, "Failed to get required features for " + anyElement + " in " + registryKey);
|
||||
+ }
|
||||
+
|
||||
+ static Stream<RegistryKey<?>> nonFeatureFilteredRegistries() {
|
||||
+ return RegistryHelper.getRegistry().registries().filter(r -> {
|
||||
+ final RegistryEntry<?, ?> entry = PaperRegistries.getEntry(r.key());
|
||||
+ // has an API registry and isn't a filtered registry
|
||||
+ return entry != null && !FeatureElement.FILTERED_REGISTRIES.contains(r.key());
|
||||
+ }).map(r -> PaperRegistries.getEntry(r.key()).apiKey());
|
||||
+ }
|
||||
+
|
||||
+
|
||||
+ @MethodSource("nonFeatureFilteredRegistries")
|
||||
+ @ParameterizedTest
|
||||
+ <T extends Keyed> void testApiDoesntImplementFeatureDependant(final RegistryKey<T> registryKey) {
|
||||
+ final org.bukkit.Registry<T> registry = RegistryAccess.registryAccess().getRegistry(registryKey);
|
||||
+ final T anyElement = registry.iterator().next();
|
||||
+ assertFalse(anyElement instanceof FeatureDependant, "Registry " + registryKey + " has feature dependent elements");
|
||||
+ }
|
||||
+}
|
||||
@@ -1,45 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Lulu13022002 <41980282+Lulu13022002@users.noreply.github.com>
|
||||
Date: Sat, 9 Jul 2022 17:28:42 +0200
|
||||
Subject: [PATCH] Add Offline PDC API
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java b/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftOfflinePlayer.java
|
||||
@@ -0,0 +0,0 @@ public class CraftOfflinePlayer implements OfflinePlayer, ConfigurationSerializa
|
||||
}
|
||||
// Paper end
|
||||
|
||||
+ // Paper start - Add Offline PDC API
|
||||
+ private static final org.bukkit.craftbukkit.persistence.CraftPersistentDataTypeRegistry DATA_TYPE_REGISTRY = new org.bukkit.craftbukkit.persistence.CraftPersistentDataTypeRegistry();
|
||||
+ private io.papermc.paper.persistence.@org.checkerframework.checker.nullness.qual.MonotonicNonNull PersistentDataContainerView persistentDataContainerView;
|
||||
+
|
||||
+ @Override
|
||||
+ public io.papermc.paper.persistence.PersistentDataContainerView getPersistentDataContainer() {
|
||||
+ if (this.persistentDataContainerView == null) {
|
||||
+ this.persistentDataContainerView = new io.papermc.paper.persistence.PaperPersistentDataContainerView(DATA_TYPE_REGISTRY) {
|
||||
+
|
||||
+ private CompoundTag getPersistentTag() {
|
||||
+ return net.minecraft.Optionull.map(CraftOfflinePlayer.this.getData(), data -> data.getCompound("BukkitValues"));
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public CompoundTag toTagCompound() {
|
||||
+ return java.util.Objects.requireNonNullElseGet(this.getPersistentTag(), CompoundTag::new);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public net.minecraft.nbt.Tag getTag(String key) {
|
||||
+ return net.minecraft.Optionull.map(this.getPersistentTag(), tag -> tag.get(key));
|
||||
+ }
|
||||
+ };
|
||||
+ }
|
||||
+ return this.persistentDataContainerView;
|
||||
+ }
|
||||
+ // Paper end - Add Offline PDC API
|
||||
+
|
||||
@Override
|
||||
public Location getLastDeathLocation() {
|
||||
if (this.getData().contains("LastDeathLocation", 10)) {
|
||||
@@ -1,36 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Mariell Hoversholm <proximyst@proximyst.com>
|
||||
Date: Sun, 29 Sep 2024 16:21:26 +0200
|
||||
Subject: [PATCH] Add PlayerInsertLecternBookEvent
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/LecternBlock.java b/src/main/java/net/minecraft/world/level/block/LecternBlock.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/LecternBlock.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/LecternBlock.java
|
||||
@@ -0,0 +0,0 @@ public class LecternBlock extends BaseEntityBlock {
|
||||
BlockEntity tileentity = world.getBlockEntity(pos);
|
||||
|
||||
if (tileentity instanceof LecternBlockEntity tileentitylectern) {
|
||||
- tileentitylectern.setBook(stack.consumeAndReturn(1, user));
|
||||
+ // Paper start - Add PlayerInsertLecternBookEvent
|
||||
+ ItemStack eventSourcedBookStack = null;
|
||||
+ if (user instanceof final net.minecraft.server.level.ServerPlayer serverPlayer) {
|
||||
+ final io.papermc.paper.event.player.PlayerInsertLecternBookEvent event = new io.papermc.paper.event.player.PlayerInsertLecternBookEvent(
|
||||
+ serverPlayer.getBukkitEntity(),
|
||||
+ org.bukkit.craftbukkit.block.CraftBlock.at(world, pos),
|
||||
+ org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(stack.copyWithCount(1))
|
||||
+ );
|
||||
+ if (!event.callEvent()) return;
|
||||
+ eventSourcedBookStack = org.bukkit.craftbukkit.inventory.CraftItemStack.unwrap(event.getBook());
|
||||
+ }
|
||||
+ if (eventSourcedBookStack == null) {
|
||||
+ eventSourcedBookStack = stack.consumeAndReturn(1, user);
|
||||
+ } else {
|
||||
+ stack.consume(1, user);
|
||||
+ }
|
||||
+ tileentitylectern.setBook(eventSourcedBookStack);
|
||||
+ // Paper end - Add PlayerInsertLecternBookEvent
|
||||
LecternBlock.resetBookState(user, world, pos, state, true);
|
||||
world.playSound((Player) null, pos, SoundEvents.BOOK_PUT, SoundSource.BLOCKS, 1.0F, 1.0F);
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: masmc05 <masmc05@gmail.com>
|
||||
Date: Wed, 25 Sep 2024 16:26:04 +0300
|
||||
Subject: [PATCH] Add enchantWithLevels with enchantment registry set
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java
|
||||
@@ -0,0 +0,0 @@ public final class CraftItemFactory implements ItemFactory {
|
||||
);
|
||||
}
|
||||
|
||||
+ @Override
|
||||
+ public ItemStack enchantWithLevels(ItemStack itemStack, int levels, io.papermc.paper.registry.set.RegistryKeySet<org.bukkit.enchantments.Enchantment> keySet, java.util.Random random) {
|
||||
+ return enchantWithLevels(
|
||||
+ itemStack,
|
||||
+ levels,
|
||||
+ Optional.of(
|
||||
+ io.papermc.paper.registry.set.PaperRegistrySets.convertToNms(
|
||||
+ Registries.ENCHANTMENT,
|
||||
+ net.minecraft.server.MinecraftServer.getServer().registryAccess().createSerializationContext(net.minecraft.nbt.NbtOps.INSTANCE).lookupProvider,
|
||||
+ keySet
|
||||
+ )
|
||||
+ ),
|
||||
+ random
|
||||
+ );
|
||||
+ }
|
||||
+
|
||||
@SuppressWarnings("OptionalUsedAsFieldOrParameterType")
|
||||
private ItemStack enchantWithLevels(
|
||||
ItemStack itemStack,
|
||||
@@ -1,39 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: okx-code <okx@okx.sh>
|
||||
Date: Sat, 17 Aug 2024 13:02:45 +0100
|
||||
Subject: [PATCH] Add enchantment seed update API
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/inventory/EnchantmentMenu.java b/src/main/java/net/minecraft/world/inventory/EnchantmentMenu.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/world/inventory/EnchantmentMenu.java
|
||||
+++ b/src/main/java/net/minecraft/world/inventory/EnchantmentMenu.java
|
||||
@@ -0,0 +0,0 @@ public class EnchantmentMenu extends AbstractContainerMenu {
|
||||
return this.bukkitEntity;
|
||||
}
|
||||
// CraftBukkit end
|
||||
+
|
||||
+ // Paper start - add enchantment seed update API
|
||||
+ public void setEnchantmentSeed(int seed) {
|
||||
+ this.enchantmentSeed.set(seed);
|
||||
+ }
|
||||
+ // Paper end - add enchantment seed update API
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/view/CraftEnchantmentView.java b/src/main/java/org/bukkit/craftbukkit/inventory/view/CraftEnchantmentView.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/inventory/view/CraftEnchantmentView.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/view/CraftEnchantmentView.java
|
||||
@@ -0,0 +0,0 @@ public class CraftEnchantmentView extends CraftInventoryView<EnchantmentMenu, En
|
||||
return this.container.getEnchantmentSeed();
|
||||
}
|
||||
|
||||
+ // Paper start - add enchantment seed update API
|
||||
+ @Override
|
||||
+ public void setEnchantmentSeed(int seed) {
|
||||
+ this.container.setEnchantmentSeed(seed);
|
||||
+ }
|
||||
+ // Paper end - add enchantment seed update API
|
||||
+
|
||||
@NotNull
|
||||
@Override
|
||||
public EnchantmentOffer[] getOffers() {
|
||||
@@ -1,168 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
|
||||
Date: Wed, 16 Oct 2024 06:41:32 -0700
|
||||
Subject: [PATCH] Add proper async player disconnections
|
||||
|
||||
Blocking can cause performance problems
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/network/Connection.java b/src/main/java/net/minecraft/network/Connection.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/network/Connection.java
|
||||
+++ b/src/main/java/net/minecraft/network/Connection.java
|
||||
@@ -0,0 +0,0 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
|
||||
|
||||
}
|
||||
|
||||
+ // Paper start - add proper async disconnect
|
||||
+ public void enableAutoRead() {
|
||||
+ if (this.channel != null) {
|
||||
+ this.channel.config().setAutoRead(true);
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end - add proper async disconnect
|
||||
+
|
||||
public void setupCompression(int compressionThreshold, boolean rejectsBadPackets) {
|
||||
if (compressionThreshold >= 0) {
|
||||
com.velocitypowered.natives.compression.VelocityCompressor compressor = com.velocitypowered.natives.util.Natives.compress.get().create(io.papermc.paper.configuration.GlobalConfiguration.get().misc.compressionLevel.or(-1)); // Paper - Use Velocity cipher
|
||||
diff --git a/src/main/java/net/minecraft/server/network/ServerCommonPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerCommonPacketListenerImpl.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/server/network/ServerCommonPacketListenerImpl.java
|
||||
+++ b/src/main/java/net/minecraft/server/network/ServerCommonPacketListenerImpl.java
|
||||
@@ -0,0 +0,0 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack
|
||||
this.latency = (this.latency * 3 + i) / 4;
|
||||
this.keepAlivePending = false;
|
||||
} else if (!this.isSingleplayerOwner()) {
|
||||
- // Paper start - This needs to be handled on the main thread for plugins
|
||||
- server.submit(() -> {
|
||||
- this.disconnect(ServerCommonPacketListenerImpl.TIMEOUT_DISCONNECTION_MESSAGE, PlayerKickEvent.Cause.TIMEOUT); // Paper - kick event cause
|
||||
- });
|
||||
- // Paper end - This needs to be handled on the main thread for plugins
|
||||
+ this.disconnectAsync(ServerCommonPacketListenerImpl.TIMEOUT_DISCONNECTION_MESSAGE, PlayerKickEvent.Cause.TIMEOUT); // Paper - add proper async disconnect
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +0,0 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack
|
||||
minecraftserver.scheduleOnMain(networkmanager::handleDisconnection); // Paper
|
||||
}
|
||||
|
||||
+ // Paper start - add proper async disconnect
|
||||
+ public void disconnectAsync(net.kyori.adventure.text.Component reason, PlayerKickEvent.Cause cause) {
|
||||
+ this.disconnectAsync(io.papermc.paper.adventure.PaperAdventure.asVanilla(reason), cause);
|
||||
+ }
|
||||
+
|
||||
+ public void disconnectAsync(Component reason, PlayerKickEvent.Cause cause) {
|
||||
+ this.disconnectAsync(new DisconnectionDetails(reason), cause);
|
||||
+ }
|
||||
+
|
||||
+ public void disconnectAsync(DisconnectionDetails disconnectionInfo, PlayerKickEvent.Cause cause) {
|
||||
+ if (this.cserver.isPrimaryThread()) {
|
||||
+ this.disconnect(disconnectionInfo, cause);
|
||||
+ return;
|
||||
+ }
|
||||
+ this.connection.setReadOnly();
|
||||
+ this.server.scheduleOnMain(() -> {
|
||||
+ ServerCommonPacketListenerImpl.this.disconnect(disconnectionInfo, cause);
|
||||
+ if (ServerCommonPacketListenerImpl.this.player.quitReason == null) {
|
||||
+ // cancelled
|
||||
+ ServerCommonPacketListenerImpl.this.connection.enableAutoRead();
|
||||
+ }
|
||||
+ });
|
||||
+ }
|
||||
+ // Paper end - add proper async disconnect
|
||||
+
|
||||
protected boolean isSingleplayerOwner() {
|
||||
return this.server.isSingleplayerOwner(this.playerProfile());
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
|
||||
// PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); // Paper - AsyncTabCompleteEvent; run this async
|
||||
// CraftBukkit start
|
||||
if (!this.tabSpamThrottler.isIncrementAndUnderThreshold() && !this.server.getPlayerList().isOp(this.player.getGameProfile()) && !this.server.isSingleplayerOwner(this.player.getGameProfile())) { // Paper - configurable tab spam limits
|
||||
- this.disconnect(Component.translatable("disconnect.spam"), org.bukkit.event.player.PlayerKickEvent.Cause.SPAM); // Paper - Kick event cause
|
||||
+ this.disconnectAsync(Component.translatable("disconnect.spam"), org.bukkit.event.player.PlayerKickEvent.Cause.SPAM); // Paper - Kick event cause // Paper - add proper async disconnect
|
||||
return;
|
||||
}
|
||||
// CraftBukkit end
|
||||
@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
|
||||
// Paper start
|
||||
final int index;
|
||||
if (packet.getCommand().length() > 64 && ((index = packet.getCommand().indexOf(' ')) == -1 || index >= 64)) {
|
||||
- this.disconnect(Component.translatable("disconnect.spam"), org.bukkit.event.player.PlayerKickEvent.Cause.SPAM);
|
||||
+ this.disconnectAsync(Component.translatable("disconnect.spam"), org.bukkit.event.player.PlayerKickEvent.Cause.SPAM); // Paper - add proper async disconnect
|
||||
return;
|
||||
}
|
||||
// Paper end
|
||||
@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
|
||||
|
||||
if (byteTotal > byteAllowed) {
|
||||
ServerGamePacketListenerImpl.LOGGER.warn("{} tried to send a book too large. Book size: {} - Allowed: {} - Pages: {}", this.player.getScoreboardName(), byteTotal, byteAllowed, pageList.size());
|
||||
- this.disconnect(Component.literal("Book too large!"), org.bukkit.event.player.PlayerKickEvent.Cause.ILLEGAL_ACTION); // Paper - kick event cause
|
||||
+ this.disconnectAsync(Component.literal("Book too large!"), org.bukkit.event.player.PlayerKickEvent.Cause.ILLEGAL_ACTION); // Paper - kick event cause // Paper - add proper async disconnect
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Paper end - Book size limits
|
||||
// CraftBukkit start
|
||||
if (this.lastBookTick + 20 > MinecraftServer.currentTick) {
|
||||
- this.disconnect(Component.literal("Book edited too quickly!"), org.bukkit.event.player.PlayerKickEvent.Cause.ILLEGAL_ACTION); // Paper - kick event cause
|
||||
+ this.disconnectAsync(Component.literal("Book edited too quickly!"), org.bukkit.event.player.PlayerKickEvent.Cause.ILLEGAL_ACTION); // Paper - kick event cause // Paper - add proper async disconnect
|
||||
return;
|
||||
}
|
||||
this.lastBookTick = MinecraftServer.currentTick;
|
||||
@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
|
||||
|
||||
private void tryHandleChat(String s, Runnable runnable, boolean sync) { // CraftBukkit
|
||||
if (ServerGamePacketListenerImpl.isChatMessageIllegal(s)) {
|
||||
- this.disconnect((Component) Component.translatable("multiplayer.disconnect.illegal_characters"), org.bukkit.event.player.PlayerKickEvent.Cause.ILLEGAL_CHARACTERS); // Paper
|
||||
+ this.disconnectAsync((Component) Component.translatable("multiplayer.disconnect.illegal_characters"), org.bukkit.event.player.PlayerKickEvent.Cause.ILLEGAL_CHARACTERS); // Paper // Paper - add proper async disconnect
|
||||
} else if (this.player.isRemoved() || this.player.getChatVisibility() == ChatVisiblity.HIDDEN) { // CraftBukkit - dead men tell no tales
|
||||
this.send(new ClientboundSystemChatPacket(Component.translatable("chat.disabled.options").withStyle(ChatFormatting.RED), false));
|
||||
} else {
|
||||
@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
|
||||
|
||||
if (optional.isEmpty()) {
|
||||
ServerGamePacketListenerImpl.LOGGER.warn("Failed to validate message acknowledgements from {}", this.player.getName().getString());
|
||||
- this.disconnect(ServerGamePacketListenerImpl.CHAT_VALIDATION_FAILED, org.bukkit.event.player.PlayerKickEvent.Cause.CHAT_VALIDATION_FAILED); // Paper - kick event causes
|
||||
+ this.disconnectAsync(ServerGamePacketListenerImpl.CHAT_VALIDATION_FAILED, org.bukkit.event.player.PlayerKickEvent.Cause.CHAT_VALIDATION_FAILED); // Paper - kick event causes // Paper - add proper async disconnect
|
||||
}
|
||||
|
||||
return optional;
|
||||
@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
|
||||
// this.chatSpamThrottler.increment();
|
||||
if (!this.chatSpamThrottler.isIncrementAndUnderThreshold() && !this.server.getPlayerList().isOp(this.player.getGameProfile()) && !this.server.isSingleplayerOwner(this.player.getGameProfile())) {
|
||||
// CraftBukkit end
|
||||
- this.disconnect((Component) Component.translatable("disconnect.spam"), org.bukkit.event.player.PlayerKickEvent.Cause.SPAM); // Paper - kick event cause
|
||||
+ this.disconnectAsync((Component) Component.translatable("disconnect.spam"), org.bukkit.event.player.PlayerKickEvent.Cause.SPAM); // Paper - kick event cause // Paper - add proper async disconnect
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
|
||||
synchronized (this.lastSeenMessages) {
|
||||
if (!this.lastSeenMessages.applyOffset(packet.offset())) {
|
||||
ServerGamePacketListenerImpl.LOGGER.warn("Failed to validate message acknowledgements from {}", this.player.getName().getString());
|
||||
- this.disconnect(ServerGamePacketListenerImpl.CHAT_VALIDATION_FAILED, org.bukkit.event.player.PlayerKickEvent.Cause.CHAT_VALIDATION_FAILED); // Paper - kick event causes
|
||||
+ this.disconnectAsync(ServerGamePacketListenerImpl.CHAT_VALIDATION_FAILED, org.bukkit.event.player.PlayerKickEvent.Cause.CHAT_VALIDATION_FAILED); // Paper - kick event causes // Paper - add proper async disconnect
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
|
||||
}
|
||||
|
||||
if (i > 4096) {
|
||||
- this.disconnect((Component) Component.translatable("multiplayer.disconnect.too_many_pending_chats"), org.bukkit.event.player.PlayerKickEvent.Cause.TOO_MANY_PENDING_CHATS); // Paper - kick event cause
|
||||
+ this.disconnectAsync((Component) Component.translatable("multiplayer.disconnect.too_many_pending_chats"), org.bukkit.event.player.PlayerKickEvent.Cause.TOO_MANY_PENDING_CHATS); // Paper - kick event cause // Paper - add proper async disconnect
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
|
||||
// Paper start - auto recipe limit
|
||||
if (!org.bukkit.Bukkit.isPrimaryThread()) {
|
||||
if (!this.recipeSpamPackets.isIncrementAndUnderThreshold()) {
|
||||
- this.disconnect(net.minecraft.network.chat.Component.translatable("disconnect.spam"), org.bukkit.event.player.PlayerKickEvent.Cause.SPAM); // Paper - kick event cause
|
||||
+ this.disconnectAsync(net.minecraft.network.chat.Component.translatable("disconnect.spam"), org.bukkit.event.player.PlayerKickEvent.Cause.SPAM); // Paper - kick event cause // Paper - add proper async disconnect
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -1,181 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Tamion <70228790+notTamion@users.noreply.github.com>
|
||||
Date: Sun, 15 Sep 2024 19:17:12 +0200
|
||||
Subject: [PATCH] Add recipeBrewTime
|
||||
|
||||
== AT ==
|
||||
public net.minecraft.world.inventory.BrewingStandMenu brewingStandData
|
||||
|
||||
diff --git a/src/main/java/io/papermc/paper/inventory/BrewingSimpleContainerData.java b/src/main/java/io/papermc/paper/inventory/BrewingSimpleContainerData.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/inventory/BrewingSimpleContainerData.java
|
||||
@@ -0,0 +0,0 @@
|
||||
+package io.papermc.paper.inventory;
|
||||
+
|
||||
+import net.minecraft.world.inventory.SimpleContainerData;
|
||||
+
|
||||
+public class BrewingSimpleContainerData extends SimpleContainerData {
|
||||
+
|
||||
+ public BrewingSimpleContainerData() {
|
||||
+ super(3);
|
||||
+ this.set(2, 400);
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/net/minecraft/world/inventory/BrewingStandMenu.java b/src/main/java/net/minecraft/world/inventory/BrewingStandMenu.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/world/inventory/BrewingStandMenu.java
|
||||
+++ b/src/main/java/net/minecraft/world/inventory/BrewingStandMenu.java
|
||||
@@ -0,0 +0,0 @@ public class BrewingStandMenu extends AbstractContainerMenu {
|
||||
// CraftBukkit end
|
||||
|
||||
public BrewingStandMenu(int syncId, Inventory playerInventory) {
|
||||
- this(syncId, playerInventory, new SimpleContainer(5), new SimpleContainerData(2));
|
||||
+ this(syncId, playerInventory, new SimpleContainer(5), new io.papermc.paper.inventory.BrewingSimpleContainerData()); // Paper - Add totalBrewTime
|
||||
}
|
||||
|
||||
public BrewingStandMenu(int syncId, Inventory playerInventory, Container inventory, ContainerData propertyDelegate) {
|
||||
super(MenuType.BREWING_STAND, syncId);
|
||||
this.player = playerInventory; // CraftBukkit
|
||||
checkContainerSize(inventory, 5);
|
||||
- checkContainerDataCount(propertyDelegate, 2);
|
||||
+ checkContainerDataCount(propertyDelegate, 3); // Paper - Add recipeBrewTime
|
||||
this.brewingStand = inventory;
|
||||
this.brewingStandData = propertyDelegate;
|
||||
PotionBrewing potionbrewer = playerInventory.player.level().potionBrewing();
|
||||
@@ -0,0 +0,0 @@ public class BrewingStandMenu extends AbstractContainerMenu {
|
||||
// Paper end - custom potion mixes
|
||||
this.ingredientSlot = this.addSlot(new BrewingStandMenu.IngredientsSlot(potionbrewer, inventory, 3, 79, 17));
|
||||
this.addSlot(new BrewingStandMenu.FuelSlot(inventory, 4, 17, 17));
|
||||
- this.addDataSlots(propertyDelegate);
|
||||
+ // Paper start - Add recipeBrewTime
|
||||
+ this.addDataSlots(new SimpleContainerData(2) {
|
||||
+ @Override
|
||||
+ public int get(final int index) {
|
||||
+ if (index == 0) return 400 * propertyDelegate.get(index) / propertyDelegate.get(2);
|
||||
+ return propertyDelegate.get(index);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void set(final int index, final int value) {
|
||||
+ propertyDelegate.set(index, value);
|
||||
+ }
|
||||
+ });
|
||||
+ // Paper end - Add recipeBrewTime
|
||||
this.addStandardInventorySlots(playerInventory, 8, 84);
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/entity/BrewingStandBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BrewingStandBlockEntity.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/entity/BrewingStandBlockEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/entity/BrewingStandBlockEntity.java
|
||||
@@ -0,0 +0,0 @@ public class BrewingStandBlockEntity extends BaseContainerBlockEntity implements
|
||||
public static final int NUM_DATA_VALUES = 2;
|
||||
private NonNullList<ItemStack> items;
|
||||
public int brewTime;
|
||||
+ public int recipeBrewTime = 400; // Paper - Add recipeBrewTime
|
||||
private boolean[] lastPotionCount;
|
||||
private Item ingredient;
|
||||
public int fuel;
|
||||
@@ -0,0 +0,0 @@ public class BrewingStandBlockEntity extends BaseContainerBlockEntity implements
|
||||
case 1:
|
||||
j = BrewingStandBlockEntity.this.fuel;
|
||||
break;
|
||||
+ // Paper start - Add recipeBrewTime
|
||||
+ case 2:
|
||||
+ j = BrewingStandBlockEntity.this.recipeBrewTime;
|
||||
+ break;
|
||||
+ // Paper end - Add recipeBrewTime
|
||||
default:
|
||||
j = 0;
|
||||
}
|
||||
@@ -0,0 +0,0 @@ public class BrewingStandBlockEntity extends BaseContainerBlockEntity implements
|
||||
break;
|
||||
case 1:
|
||||
BrewingStandBlockEntity.this.fuel = value;
|
||||
+ // Paper start - Add recipeBrewTime
|
||||
+ case 2:
|
||||
+ BrewingStandBlockEntity.this.recipeBrewTime = value;
|
||||
+ break;
|
||||
+ // Paper end - Add recipeBrewTime
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
- return 2;
|
||||
+ return 3; // Paper - Add recipeBrewTime
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -0,0 +0,0 @@ public class BrewingStandBlockEntity extends BaseContainerBlockEntity implements
|
||||
// CraftBukkit start
|
||||
BrewingStartEvent event = new BrewingStartEvent(CraftBlock.at(world, pos), CraftItemStack.asCraftMirror(itemstack1), 400);
|
||||
world.getCraftServer().getPluginManager().callEvent(event);
|
||||
- blockEntity.brewTime = event.getTotalBrewTime(); // 400 -> event.getTotalBrewTime()
|
||||
+ blockEntity.recipeBrewTime = event.getRecipeBrewTime(); // Paper - use recipe brew time from event
|
||||
+ blockEntity.brewTime = event.getBrewingTime(); // 400 -> event.getTotalBrewTime() // Paper - use brewing time from event
|
||||
// CraftBukkit end
|
||||
blockEntity.ingredient = itemstack1.getItem();
|
||||
setChanged(world, pos, state);
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBrewingStand.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBrewingStand.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBrewingStand.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBrewingStand.java
|
||||
@@ -0,0 +0,0 @@ public class CraftBrewingStand extends CraftContainer<BrewingStandBlockEntity> i
|
||||
this.getSnapshot().brewTime = brewTime;
|
||||
}
|
||||
|
||||
+ // Paper start - Add recipeBrewTime
|
||||
+ @Override
|
||||
+ public void setRecipeBrewTime(int recipeBrewTime) {
|
||||
+ com.google.common.base.Preconditions.checkArgument(recipeBrewTime > 0, "recipeBrewTime must be positive");
|
||||
+ this.getSnapshot().recipeBrewTime = recipeBrewTime;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public int getRecipeBrewTime() {
|
||||
+ return this.getSnapshot().recipeBrewTime;
|
||||
+ }
|
||||
+ // Paper end - Add recipeBrewTime
|
||||
+
|
||||
@Override
|
||||
public int getFuelLevel() {
|
||||
return this.getSnapshot().fuel;
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftContainer.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftContainer.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftContainer.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftContainer.java
|
||||
@@ -0,0 +0,0 @@ public class CraftContainer extends AbstractContainerMenu {
|
||||
this.delegate = new EnchantmentMenu(windowId, bottom);
|
||||
break;
|
||||
case BREWING:
|
||||
- this.delegate = new BrewingStandMenu(windowId, bottom, top, new SimpleContainerData(2));
|
||||
+ this.delegate = new BrewingStandMenu(windowId, bottom, top, new io.papermc.paper.inventory.BrewingSimpleContainerData()); // Paper - Add recipeBrewTime
|
||||
break;
|
||||
case HOPPER:
|
||||
this.delegate = new HopperMenu(windowId, bottom, top);
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/view/CraftBrewingStandView.java b/src/main/java/org/bukkit/craftbukkit/inventory/view/CraftBrewingStandView.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/inventory/view/CraftBrewingStandView.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/view/CraftBrewingStandView.java
|
||||
@@ -0,0 +0,0 @@ public class CraftBrewingStandView extends CraftInventoryView<BrewingStandMenu,
|
||||
Preconditions.checkArgument(brewingTicks > 0, "The given brewing ticks must be greater than 0");
|
||||
this.container.setData(BrewingStandBlockEntity.DATA_BREW_TIME, brewingTicks);
|
||||
}
|
||||
+
|
||||
+ // Paper start - Add recipeBrewTime
|
||||
+ @Override
|
||||
+ public void setRecipeBrewTime(int recipeBrewTime) {
|
||||
+ com.google.common.base.Preconditions.checkArgument(recipeBrewTime > 0, "recipeBrewTime must be positive");
|
||||
+ this.container.brewingStandData.set(2, recipeBrewTime);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public int getRecipeBrewTime() {
|
||||
+ return this.container.brewingStandData.get(2);
|
||||
+ }
|
||||
+ // Paper end - Add recipeBrewTime
|
||||
}
|
||||
@@ -1,203 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
Date: Sun, 16 Jan 2022 10:13:33 -0800
|
||||
Subject: [PATCH] Call bucket events for cauldrons
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/core/cauldron/CauldronInteraction.java b/src/main/java/net/minecraft/core/cauldron/CauldronInteraction.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/core/cauldron/CauldronInteraction.java
|
||||
+++ b/src/main/java/net/minecraft/core/cauldron/CauldronInteraction.java
|
||||
@@ -0,0 +0,0 @@ public interface CauldronInteraction {
|
||||
static CauldronInteraction.InteractionMap newInteractionMap(String name) {
|
||||
Object2ObjectOpenHashMap<Item, CauldronInteraction> object2objectopenhashmap = new Object2ObjectOpenHashMap();
|
||||
|
||||
- object2objectopenhashmap.defaultReturnValue((iblockdata, world, blockposition, entityhuman, enumhand, itemstack) -> {
|
||||
+ object2objectopenhashmap.defaultReturnValue((iblockdata, world, blockposition, entityhuman, enumhand, itemstack, hitDirection) -> { // Paper - add hitDirection
|
||||
return InteractionResult.TRY_WITH_EMPTY_HAND;
|
||||
});
|
||||
CauldronInteraction.InteractionMap cauldroninteraction_a = new CauldronInteraction.InteractionMap(name, object2objectopenhashmap);
|
||||
@@ -0,0 +0,0 @@ public interface CauldronInteraction {
|
||||
return cauldroninteraction_a;
|
||||
}
|
||||
|
||||
- InteractionResult interact(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, ItemStack stack);
|
||||
+ InteractionResult interact(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, ItemStack stack, final net.minecraft.core.Direction hitDirection); // Paper - add hitDirection
|
||||
|
||||
static void bootStrap() {
|
||||
Map<Item, CauldronInteraction> map = CauldronInteraction.EMPTY.map();
|
||||
|
||||
CauldronInteraction.addDefaultInteractions(map);
|
||||
- map.put(Items.POTION, (iblockdata, world, blockposition, entityhuman, enumhand, itemstack) -> {
|
||||
+ map.put(Items.POTION, (iblockdata, world, blockposition, entityhuman, enumhand, itemstack, hitDirection) -> { // Paper - add hitDirection
|
||||
PotionContents potioncontents = (PotionContents) itemstack.get(DataComponents.POTION_CONTENTS);
|
||||
|
||||
if (potioncontents != null && potioncontents.is(Potions.WATER)) {
|
||||
@@ -0,0 +0,0 @@ public interface CauldronInteraction {
|
||||
Map<Item, CauldronInteraction> map1 = CauldronInteraction.WATER.map();
|
||||
|
||||
CauldronInteraction.addDefaultInteractions(map1);
|
||||
- map1.put(Items.BUCKET, (iblockdata, world, blockposition, entityhuman, enumhand, itemstack) -> {
|
||||
+ map1.put(Items.BUCKET, (iblockdata, world, blockposition, entityhuman, enumhand, itemstack, hitDirection) -> { // Paper - add hitDirection
|
||||
return CauldronInteraction.fillBucket(iblockdata, world, blockposition, entityhuman, enumhand, itemstack, new ItemStack(Items.WATER_BUCKET), (iblockdata1) -> {
|
||||
return (Integer) iblockdata1.getValue(LayeredCauldronBlock.LEVEL) == 3;
|
||||
- }, SoundEvents.BUCKET_FILL);
|
||||
+ }, SoundEvents.BUCKET_FILL, hitDirection); // Paper - add hitDirection
|
||||
});
|
||||
- map1.put(Items.GLASS_BOTTLE, (iblockdata, world, blockposition, entityhuman, enumhand, itemstack) -> {
|
||||
+ map1.put(Items.GLASS_BOTTLE, (iblockdata, world, blockposition, entityhuman, enumhand, itemstack, hitDirection) -> { // Paper - add hitDirection
|
||||
if (!world.isClientSide) {
|
||||
// CraftBukkit start
|
||||
if (!LayeredCauldronBlock.lowerFillLevel(iblockdata, world, blockposition, entityhuman, CauldronLevelChangeEvent.ChangeReason.BOTTLE_FILL)) {
|
||||
@@ -0,0 +0,0 @@ public interface CauldronInteraction {
|
||||
|
||||
return InteractionResult.SUCCESS;
|
||||
});
|
||||
- map1.put(Items.POTION, (iblockdata, world, blockposition, entityhuman, enumhand, itemstack) -> {
|
||||
+ map1.put(Items.POTION, (iblockdata, world, blockposition, entityhuman, enumhand, itemstack, hitDirection) -> { // Paper - add hitDirection
|
||||
if ((Integer) iblockdata.getValue(LayeredCauldronBlock.LEVEL) == 3) {
|
||||
return InteractionResult.TRY_WITH_EMPTY_HAND;
|
||||
} else {
|
||||
@@ -0,0 +0,0 @@ public interface CauldronInteraction {
|
||||
map1.put(Items.YELLOW_SHULKER_BOX, CauldronInteraction::shulkerBoxInteraction);
|
||||
Map<Item, CauldronInteraction> map2 = CauldronInteraction.LAVA.map();
|
||||
|
||||
- map2.put(Items.BUCKET, (iblockdata, world, blockposition, entityhuman, enumhand, itemstack) -> {
|
||||
+ map2.put(Items.BUCKET, (iblockdata, world, blockposition, entityhuman, enumhand, itemstack, hitDirection) -> { // Paper - add hitDirection
|
||||
return CauldronInteraction.fillBucket(iblockdata, world, blockposition, entityhuman, enumhand, itemstack, new ItemStack(Items.LAVA_BUCKET), (iblockdata1) -> {
|
||||
return true;
|
||||
- }, SoundEvents.BUCKET_FILL_LAVA);
|
||||
+ }, SoundEvents.BUCKET_FILL_LAVA, hitDirection); // Paper - add hitDirection
|
||||
});
|
||||
CauldronInteraction.addDefaultInteractions(map2);
|
||||
Map<Item, CauldronInteraction> map3 = CauldronInteraction.POWDER_SNOW.map();
|
||||
|
||||
- map3.put(Items.BUCKET, (iblockdata, world, blockposition, entityhuman, enumhand, itemstack) -> {
|
||||
+ map3.put(Items.BUCKET, (iblockdata, world, blockposition, entityhuman, enumhand, itemstack, hitDirection) -> { // Paper - add hitDirection
|
||||
return CauldronInteraction.fillBucket(iblockdata, world, blockposition, entityhuman, enumhand, itemstack, new ItemStack(Items.POWDER_SNOW_BUCKET), (iblockdata1) -> {
|
||||
return (Integer) iblockdata1.getValue(LayeredCauldronBlock.LEVEL) == 3;
|
||||
- }, SoundEvents.BUCKET_FILL_POWDER_SNOW);
|
||||
+ }, SoundEvents.BUCKET_FILL_POWDER_SNOW, hitDirection); // Paper - add hitDirection
|
||||
});
|
||||
CauldronInteraction.addDefaultInteractions(map3);
|
||||
}
|
||||
@@ -0,0 +0,0 @@ public interface CauldronInteraction {
|
||||
}
|
||||
|
||||
static InteractionResult fillBucket(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, ItemStack stack, ItemStack output, Predicate<BlockState> fullPredicate, SoundEvent soundEvent) {
|
||||
+ // Paper start - add hitDirection
|
||||
+ return fillBucket(state, world, pos, player, hand, stack, output, fullPredicate, soundEvent, null); // Paper - add hitDirection
|
||||
+ }
|
||||
+ static InteractionResult fillBucket(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, ItemStack stack, ItemStack output, Predicate<BlockState> fullPredicate, SoundEvent soundEvent, @javax.annotation.Nullable net.minecraft.core.Direction hitDirection) {
|
||||
+ // Paper end - add hitDirection
|
||||
if (!fullPredicate.test(state)) {
|
||||
return InteractionResult.TRY_WITH_EMPTY_HAND;
|
||||
} else {
|
||||
if (!world.isClientSide) {
|
||||
+ // Paper start - fire PlayerBucketFillEvent
|
||||
+ if (hitDirection != null) {
|
||||
+ org.bukkit.event.player.PlayerBucketEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerBucketFillEvent((net.minecraft.server.level.ServerLevel) world, player, pos, pos, hitDirection, stack, output.getItem(), hand);
|
||||
+ if (event.isCancelled()) {
|
||||
+ return InteractionResult.PASS;
|
||||
+ }
|
||||
+ output = event.getItemStack() != null ? org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItemStack()) : ItemStack.EMPTY;
|
||||
+ }
|
||||
+ // Paper end - fire PlayerBucketFillEvent
|
||||
// CraftBukkit start
|
||||
if (!LayeredCauldronBlock.changeLevel(state, world, pos, Blocks.CAULDRON.defaultBlockState(), player, CauldronLevelChangeEvent.ChangeReason.BUCKET_FILL, false)) { // Paper - Call CauldronLevelChangeEvent
|
||||
return InteractionResult.SUCCESS;
|
||||
@@ -0,0 +0,0 @@ public interface CauldronInteraction {
|
||||
}
|
||||
|
||||
static InteractionResult emptyBucket(Level world, BlockPos pos, Player player, InteractionHand hand, ItemStack stack, BlockState state, SoundEvent soundEvent) {
|
||||
+ // Paper start - add hitDirection
|
||||
+ return emptyBucket(world, pos, player, hand, stack, state, soundEvent, null);
|
||||
+ }
|
||||
+ static InteractionResult emptyBucket(Level world, BlockPos pos, Player player, InteractionHand hand, ItemStack stack, BlockState state, SoundEvent soundEvent, @javax.annotation.Nullable net.minecraft.core.Direction hitDirection) {
|
||||
+ // Paper end - add hitDirection
|
||||
if (!world.isClientSide) {
|
||||
+ // Paper start - fire PlayerBucketEmptyEvent
|
||||
+ ItemStack output = new ItemStack(Items.BUCKET);
|
||||
+ if (hitDirection != null) {
|
||||
+ org.bukkit.event.player.PlayerBucketEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerBucketEmptyEvent((net.minecraft.server.level.ServerLevel) world, player, pos, pos, hitDirection, stack, hand);
|
||||
+ if (event.isCancelled()) {
|
||||
+ return InteractionResult.PASS;
|
||||
+ }
|
||||
+ output = event.getItemStack() != null ? org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(event.getItemStack()) : ItemStack.EMPTY;
|
||||
+ }
|
||||
+ // Paper end - fire PlayerBucketEmptyEvent
|
||||
// CraftBukkit start
|
||||
if (!LayeredCauldronBlock.changeLevel(state, world, pos, state, player, CauldronLevelChangeEvent.ChangeReason.BUCKET_EMPTY, false)) { // Paper - Call CauldronLevelChangeEvent
|
||||
return InteractionResult.SUCCESS;
|
||||
@@ -0,0 +0,0 @@ public interface CauldronInteraction {
|
||||
// CraftBukkit end
|
||||
Item item = stack.getItem();
|
||||
|
||||
- player.setItemInHand(hand, ItemUtils.createFilledResult(stack, player, new ItemStack(Items.BUCKET)));
|
||||
+ player.setItemInHand(hand, ItemUtils.createFilledResult(stack, player, output)); // Paper
|
||||
player.awardStat(Stats.FILL_CAULDRON);
|
||||
player.awardStat(Stats.ITEM_USED.get(item));
|
||||
// world.setBlockAndUpdate(blockposition, iblockdata); // CraftBukkit
|
||||
@@ -0,0 +0,0 @@ public interface CauldronInteraction {
|
||||
return InteractionResult.SUCCESS;
|
||||
}
|
||||
|
||||
- private static InteractionResult fillWaterInteraction(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, ItemStack stack) {
|
||||
- return CauldronInteraction.emptyBucket(world, pos, player, hand, stack, (BlockState) Blocks.WATER_CAULDRON.defaultBlockState().setValue(LayeredCauldronBlock.LEVEL, 3), SoundEvents.BUCKET_EMPTY);
|
||||
+ private static InteractionResult fillWaterInteraction(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, ItemStack stack, final net.minecraft.core.Direction hitDirection) { // Paper - add hitDirection
|
||||
+ return CauldronInteraction.emptyBucket(world, pos, player, hand, stack, (BlockState) Blocks.WATER_CAULDRON.defaultBlockState().setValue(LayeredCauldronBlock.LEVEL, 3), SoundEvents.BUCKET_EMPTY, hitDirection); // Paper - add hitDirection
|
||||
}
|
||||
|
||||
- private static InteractionResult fillLavaInteraction(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, ItemStack stack) {
|
||||
- return (InteractionResult) (CauldronInteraction.isUnderWater(world, pos) ? InteractionResult.CONSUME : CauldronInteraction.emptyBucket(world, pos, player, hand, stack, Blocks.LAVA_CAULDRON.defaultBlockState(), SoundEvents.BUCKET_EMPTY_LAVA));
|
||||
+ private static InteractionResult fillLavaInteraction(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, ItemStack stack, final net.minecraft.core.Direction hitDirection) { // Paper - add hitDirection
|
||||
+ return (InteractionResult) (CauldronInteraction.isUnderWater(world, pos) ? InteractionResult.CONSUME : CauldronInteraction.emptyBucket(world, pos, player, hand, stack, Blocks.LAVA_CAULDRON.defaultBlockState(), SoundEvents.BUCKET_EMPTY_LAVA, hitDirection)); // Paper - add hitDirection
|
||||
}
|
||||
|
||||
- private static InteractionResult fillPowderSnowInteraction(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, ItemStack stack) {
|
||||
- return (InteractionResult) (CauldronInteraction.isUnderWater(world, pos) ? InteractionResult.CONSUME : CauldronInteraction.emptyBucket(world, pos, player, hand, stack, (BlockState) Blocks.POWDER_SNOW_CAULDRON.defaultBlockState().setValue(LayeredCauldronBlock.LEVEL, 3), SoundEvents.BUCKET_EMPTY_POWDER_SNOW));
|
||||
+ private static InteractionResult fillPowderSnowInteraction(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, ItemStack stack, final net.minecraft.core.Direction hitDirection) { // Paper - add hitDirection
|
||||
+ return (InteractionResult) (CauldronInteraction.isUnderWater(world, pos) ? InteractionResult.CONSUME : CauldronInteraction.emptyBucket(world, pos, player, hand, stack, (BlockState) Blocks.POWDER_SNOW_CAULDRON.defaultBlockState().setValue(LayeredCauldronBlock.LEVEL, 3), SoundEvents.BUCKET_EMPTY_POWDER_SNOW, hitDirection)); // Paper - add hitDirection
|
||||
}
|
||||
|
||||
- private static InteractionResult shulkerBoxInteraction(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, ItemStack stack) {
|
||||
+ private static InteractionResult shulkerBoxInteraction(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, ItemStack stack, final net.minecraft.core.Direction hitDirection) { // Paper - add hitDirection
|
||||
Block block = Block.byItem(stack.getItem());
|
||||
|
||||
if (!(block instanceof ShulkerBoxBlock)) {
|
||||
@@ -0,0 +0,0 @@ public interface CauldronInteraction {
|
||||
player.awardStat(Stats.CLEAN_SHULKER_BOX);
|
||||
// LayeredCauldronBlock.lowerFillLevel(iblockdata, world, blockposition); // CraftBukkit
|
||||
}
|
||||
-
|
||||
return InteractionResult.SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
- private static InteractionResult bannerInteraction(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, ItemStack stack) {
|
||||
+ private static InteractionResult bannerInteraction(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, ItemStack stack, final net.minecraft.core.Direction hitDirection) { // Paper - add hitDirection
|
||||
BannerPatternLayers bannerpatternlayers = (BannerPatternLayers) stack.getOrDefault(DataComponents.BANNER_PATTERNS, BannerPatternLayers.EMPTY);
|
||||
|
||||
if (bannerpatternlayers.layers().isEmpty()) {
|
||||
@@ -0,0 +0,0 @@ public interface CauldronInteraction {
|
||||
}
|
||||
}
|
||||
|
||||
- private static InteractionResult dyedItemIteration(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, ItemStack stack) {
|
||||
+ private static InteractionResult dyedItemIteration(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, ItemStack stack, final net.minecraft.core.Direction hitDirection) { // Paper - add hitDirection
|
||||
if (!stack.is(ItemTags.DYEABLE)) {
|
||||
return InteractionResult.TRY_WITH_EMPTY_HAND;
|
||||
} else if (!stack.has(DataComponents.DYED_COLOR)) {
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/AbstractCauldronBlock.java b/src/main/java/net/minecraft/world/level/block/AbstractCauldronBlock.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/AbstractCauldronBlock.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/AbstractCauldronBlock.java
|
||||
@@ -0,0 +0,0 @@ public abstract class AbstractCauldronBlock extends Block {
|
||||
@Override
|
||||
protected InteractionResult useItemOn(ItemStack stack, BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) {
|
||||
CauldronInteraction cauldronInteraction = this.interactions.map().get(stack.getItem());
|
||||
- return cauldronInteraction.interact(state, world, pos, player, hand, stack);
|
||||
+ return cauldronInteraction.interact(state, world, pos, player, hand, stack, hit.getDirection()); // Paper - pass hit direction
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1,29 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Newwind <support@newwindserver.com>
|
||||
Date: Mon, 26 Aug 2024 14:01:37 +0200
|
||||
Subject: [PATCH] Check dead flag in isAlive()
|
||||
|
||||
If a plugin sets the health of a living entity above 0 after it has already died, the entity will be "revived".
|
||||
It will behave the exact same as before, except with the internal "dead" flag set, resulting in 2 behavior changes,
|
||||
A: it's completely invulnerable to all damage
|
||||
B: it's unable to pickup items
|
||||
|
||||
isValid() for these bugged entities will return true, isDead() will return false, despite the dead flag.
|
||||
This patch checks that the mob isn't dead before saying its alive.
|
||||
|
||||
Also, even if the plugin is responsibly checking !isDead() before modifying health, on very rare circumstances
|
||||
I am currently unable to replicate, these "revived" entities can still appear
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity implements Attackable {
|
||||
|
||||
@Override
|
||||
public boolean isAlive() {
|
||||
- return !this.isRemoved() && this.getHealth() > 0.0F;
|
||||
+ return !this.isRemoved() && this.getHealth() > 0.0F && !this.dead; // Paper - Check this.dead
|
||||
}
|
||||
|
||||
public boolean isLookingAtMe(LivingEntity entity, double d0, boolean flag, boolean visualShape, Predicate<LivingEntity> predicate, DoubleSupplier... entityYChecks) {
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,22 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Newwind <support@newwindserver.com>
|
||||
Date: Fri, 20 Sep 2024 14:17:37 +0200
|
||||
Subject: [PATCH] Disable pretty printing for advancement saving
|
||||
|
||||
Reduces json size by about 25%
|
||||
Not sure why advancements even had pretty printing enabled.
|
||||
My best guess was by accident on mojang's part, especially since stats json files don't have pretty printing.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/PlayerAdvancements.java b/src/main/java/net/minecraft/server/PlayerAdvancements.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/server/PlayerAdvancements.java
|
||||
+++ b/src/main/java/net/minecraft/server/PlayerAdvancements.java
|
||||
@@ -0,0 +0,0 @@ import org.slf4j.Logger;
|
||||
public class PlayerAdvancements {
|
||||
|
||||
private static final Logger LOGGER = LogUtils.getLogger();
|
||||
- private static final Gson GSON = (new GsonBuilder()).setPrettyPrinting().create();
|
||||
+ private static final Gson GSON = (new GsonBuilder()).create(); // Paper - Remove pretty printing from advancements
|
||||
private final PlayerList playerList;
|
||||
private final Path playerSavePath;
|
||||
private AdvancementTree tree;
|
||||
@@ -1,23 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Nathan <nathanmaestas21@cnm.edu>
|
||||
Date: Sat, 31 Aug 2024 18:09:55 -0600
|
||||
Subject: [PATCH] Fire BlockExpEvent on grindstone use
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.java b/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.java
|
||||
+++ b/src/main/java/net/minecraft/world/inventory/GrindstoneMenu.java
|
||||
@@ -0,0 +0,0 @@ public class GrindstoneMenu extends AbstractContainerMenu {
|
||||
public void onTake(net.minecraft.world.entity.player.Player player, ItemStack stack) {
|
||||
context.execute((world, blockposition) -> {
|
||||
if (world instanceof ServerLevel) {
|
||||
- ExperienceOrb.award((ServerLevel) world, Vec3.atCenterOf(blockposition), this.getExperienceAmount(world), org.bukkit.entity.ExperienceOrb.SpawnReason.GRINDSTONE, player); // Paper
|
||||
+ // Paper start - Fire BlockExpEvent on grindstone use
|
||||
+ org.bukkit.event.block.BlockExpEvent event = new org.bukkit.event.block.BlockExpEvent(org.bukkit.craftbukkit.block.CraftBlock.at(world, blockposition), this.getExperienceAmount(world));
|
||||
+ event.callEvent();
|
||||
+ ExperienceOrb.award((ServerLevel) world, Vec3.atCenterOf(blockposition), event.getExpToDrop(), org.bukkit.entity.ExperienceOrb.SpawnReason.GRINDSTONE, player);
|
||||
+ // Paper end - Fire BlockExpEvent on grindstone use
|
||||
}
|
||||
|
||||
world.levelEvent(1042, blockposition, 0);
|
||||
@@ -1,54 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Tamion <70228790+notTamion@users.noreply.github.com>
|
||||
Date: Sun, 26 May 2024 22:20:21 +0200
|
||||
Subject: [PATCH] Fix CraftBukkit drag system
|
||||
|
||||
== AT ==
|
||||
public net.minecraft.world.inventory.AbstractContainerMenu quickcraftSlots
|
||||
public net.minecraft.world.inventory.AbstractContainerMenu quickcraftStatus
|
||||
public net.minecraft.world.inventory.AbstractContainerMenu quickcraftType
|
||||
public net.minecraft.world.inventory.AbstractContainerMenu resetQuickCraft()V
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
|
||||
}
|
||||
break;
|
||||
case QUICK_CRAFT:
|
||||
+ // Paper start - Fix CraftBukkit drag system
|
||||
+ AbstractContainerMenu containerMenu = this.player.containerMenu;
|
||||
+ int currentStatus = this.player.containerMenu.quickcraftStatus;
|
||||
+ int newStatus = AbstractContainerMenu.getQuickcraftHeader(packet.getButtonNum());
|
||||
+ if ((currentStatus != 1 || newStatus != 2 && currentStatus != newStatus)) {
|
||||
+ } else if (containerMenu.getCarried().isEmpty()) {
|
||||
+ } else if (newStatus == 0) {
|
||||
+ } else if (newStatus == 1) {
|
||||
+ } else if (newStatus == 2) {
|
||||
+ if (!this.player.containerMenu.quickcraftSlots.isEmpty()) {
|
||||
+ if (this.player.containerMenu.quickcraftSlots.size() == 1) {
|
||||
+ int index = containerMenu.quickcraftSlots.iterator().next().index;
|
||||
+ containerMenu.resetQuickCraft();
|
||||
+ this.handleContainerClick(new ServerboundContainerClickPacket(packet.getContainerId(), packet.getStateId(), index, containerMenu.quickcraftType, net.minecraft.world.inventory.ClickType.PICKUP, packet.getCarriedItem(), packet.getChangedSlots()));
|
||||
+ return;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end - Fix CraftBukkit drag system
|
||||
this.player.containerMenu.clicked(packet.getSlotNum(), packet.getButtonNum(), packet.getClickType(), this.player);
|
||||
break;
|
||||
case PICKUP_ALL:
|
||||
diff --git a/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java b/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java
|
||||
+++ b/src/main/java/net/minecraft/world/inventory/AbstractContainerMenu.java
|
||||
@@ -0,0 +0,0 @@ public abstract class AbstractContainerMenu {
|
||||
}
|
||||
} else if (this.quickcraftStatus == 2) {
|
||||
if (!this.quickcraftSlots.isEmpty()) {
|
||||
- if (false && this.quickcraftSlots.size() == 1) { // CraftBukkit - treat everything as a drag since we are unable to easily call InventoryClickEvent instead
|
||||
+ if (this.quickcraftSlots.size() == 1) { // Paper - Fix CraftBukkit drag system
|
||||
k = ((Slot) this.quickcraftSlots.iterator().next()).index;
|
||||
this.resetQuickCraft();
|
||||
this.doClick(k, this.quickcraftType, ClickType.PICKUP, player);
|
||||
@@ -1,353 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Tamion <70228790+notTamion@users.noreply.github.com>
|
||||
Date: Mon, 19 Aug 2024 18:05:26 +0200
|
||||
Subject: [PATCH] Fix InventoryOpenEvent cancellation
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
@@ -0,0 +0,0 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player {
|
||||
} else if (factory instanceof ChestBlock.DoubleInventory) {
|
||||
// SPIGOT-5355 - double chests too :(
|
||||
((ChestBlock.DoubleInventory) factory).inventorylargechest.stopOpen(this);
|
||||
+ // Paper start - Fix InventoryOpenEvent cancellation
|
||||
+ } else if (!this.enderChestInventory.isActiveChest(null)) {
|
||||
+ this.enderChestInventory.stopOpen(this);
|
||||
+ // Paper end - Fix InventoryOpenEvent cancellation
|
||||
}
|
||||
return OptionalInt.empty();
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java
|
||||
@@ -0,0 +0,0 @@ public class ServerPlayerGameMode {
|
||||
} else if (this.gameModeForPlayer == GameType.SPECTATOR) {
|
||||
MenuProvider itileinventory = iblockdata.getMenuProvider(world, blockposition);
|
||||
|
||||
- if (itileinventory != null) {
|
||||
- player.openMenu(itileinventory);
|
||||
+ if (itileinventory != null && player.openMenu(itileinventory).isPresent()) { // Paper - Fix InventoryOpenEvent cancellation
|
||||
return InteractionResult.CONSUME;
|
||||
} else {
|
||||
return InteractionResult.PASS;
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/vehicle/AbstractChestBoat.java b/src/main/java/net/minecraft/world/entity/vehicle/AbstractChestBoat.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/vehicle/AbstractChestBoat.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/vehicle/AbstractChestBoat.java
|
||||
@@ -0,0 +0,0 @@ public abstract class AbstractChestBoat extends AbstractBoat implements HasCusto
|
||||
|
||||
@Override
|
||||
public void openCustomInventoryScreen(Player player) {
|
||||
- player.openMenu(this);
|
||||
+ // Paper - fix inventory open cancel - moved into below if
|
||||
Level world = player.level();
|
||||
|
||||
- if (world instanceof ServerLevel worldserver) {
|
||||
+ if (world instanceof ServerLevel worldserver && player.openMenu(this).isPresent()) { // Paper - Fix InventoryOpenEvent cancellation
|
||||
this.gameEvent(GameEvent.CONTAINER_OPEN, player);
|
||||
PiglinAi.angerNearbyPiglins(worldserver, player, true);
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/vehicle/ContainerEntity.java b/src/main/java/net/minecraft/world/entity/vehicle/ContainerEntity.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/vehicle/ContainerEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/vehicle/ContainerEntity.java
|
||||
@@ -0,0 +0,0 @@ public interface ContainerEntity extends Container, MenuProvider {
|
||||
}
|
||||
|
||||
default InteractionResult interactWithContainerVehicle(Player player) {
|
||||
- player.openMenu(this);
|
||||
+ // Paper start - Fix InventoryOpenEvent cancellation
|
||||
+ if (player.openMenu(this).isEmpty()) {
|
||||
+ return InteractionResult.PASS;
|
||||
+ }
|
||||
+ // Paper end - Fix InventoryOpenEvent cancellation
|
||||
return InteractionResult.SUCCESS;
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/AnvilBlock.java b/src/main/java/net/minecraft/world/level/block/AnvilBlock.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/AnvilBlock.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/AnvilBlock.java
|
||||
@@ -0,0 +0,0 @@ public class AnvilBlock extends FallingBlock {
|
||||
@Override
|
||||
protected InteractionResult useWithoutItem(BlockState state, Level world, BlockPos pos, Player player, BlockHitResult hit) {
|
||||
if (!world.isClientSide) {
|
||||
- player.openMenu(state.getMenuProvider(world, pos));
|
||||
+ if (player.openMenu(state.getMenuProvider(world, pos)).isPresent()) { // Paper - Fix InventoryOpenEvent cancellation
|
||||
player.awardStat(Stats.INTERACT_WITH_ANVIL);
|
||||
+ } // Paper - Fix InventoryOpenEvent cancellation
|
||||
}
|
||||
|
||||
return InteractionResult.SUCCESS;
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/BarrelBlock.java b/src/main/java/net/minecraft/world/level/block/BarrelBlock.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/BarrelBlock.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/BarrelBlock.java
|
||||
@@ -0,0 +0,0 @@ public class BarrelBlock extends BaseEntityBlock {
|
||||
|
||||
@Override
|
||||
protected InteractionResult useWithoutItem(BlockState state, Level world, BlockPos pos, Player player, BlockHitResult hit) {
|
||||
- if (world instanceof ServerLevel serverLevel && world.getBlockEntity(pos) instanceof BarrelBlockEntity barrelBlockEntity) {
|
||||
- player.openMenu(barrelBlockEntity);
|
||||
+ if (world instanceof ServerLevel serverLevel && world.getBlockEntity(pos) instanceof BarrelBlockEntity barrelBlockEntity && player.openMenu(barrelBlockEntity).isPresent()) { // Paper - Fix InventoryOpenEvent cancellation
|
||||
player.awardStat(Stats.OPEN_BARREL);
|
||||
PiglinAi.angerNearbyPiglins(serverLevel, player, true);
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/BeaconBlock.java b/src/main/java/net/minecraft/world/level/block/BeaconBlock.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/BeaconBlock.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/BeaconBlock.java
|
||||
@@ -0,0 +0,0 @@ public class BeaconBlock extends BaseEntityBlock implements BeaconBeamBlock {
|
||||
|
||||
@Override
|
||||
protected InteractionResult useWithoutItem(BlockState state, Level world, BlockPos pos, Player player, BlockHitResult hit) {
|
||||
- if (!world.isClientSide && world.getBlockEntity(pos) instanceof BeaconBlockEntity beaconBlockEntity) {
|
||||
- player.openMenu(beaconBlockEntity);
|
||||
+ if (!world.isClientSide && world.getBlockEntity(pos) instanceof BeaconBlockEntity beaconBlockEntity && player.openMenu(beaconBlockEntity).isPresent()) { // Paper - Fix InventoryOpenEvent cancellation
|
||||
player.awardStat(Stats.INTERACT_WITH_BEACON);
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/BlastFurnaceBlock.java b/src/main/java/net/minecraft/world/level/block/BlastFurnaceBlock.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/BlastFurnaceBlock.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/BlastFurnaceBlock.java
|
||||
@@ -0,0 +0,0 @@ public class BlastFurnaceBlock extends AbstractFurnaceBlock {
|
||||
@Override
|
||||
protected void openContainer(Level world, BlockPos pos, Player player) {
|
||||
BlockEntity blockEntity = world.getBlockEntity(pos);
|
||||
- if (blockEntity instanceof BlastFurnaceBlockEntity) {
|
||||
- player.openMenu((MenuProvider)blockEntity);
|
||||
+ if (blockEntity instanceof BlastFurnaceBlockEntity && player.openMenu((MenuProvider)blockEntity).isPresent()) { // Paper - Fix InventoryOpenEvent cancellation
|
||||
player.awardStat(Stats.INTERACT_WITH_BLAST_FURNACE);
|
||||
}
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/BrewingStandBlock.java b/src/main/java/net/minecraft/world/level/block/BrewingStandBlock.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/BrewingStandBlock.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/BrewingStandBlock.java
|
||||
@@ -0,0 +0,0 @@ public class BrewingStandBlock extends BaseEntityBlock {
|
||||
|
||||
@Override
|
||||
protected InteractionResult useWithoutItem(BlockState state, Level world, BlockPos pos, Player player, BlockHitResult hit) {
|
||||
- if (!world.isClientSide && world.getBlockEntity(pos) instanceof BrewingStandBlockEntity brewingStandBlockEntity) {
|
||||
- player.openMenu(brewingStandBlockEntity);
|
||||
+ if (!world.isClientSide && world.getBlockEntity(pos) instanceof BrewingStandBlockEntity brewingStandBlockEntity && player.openMenu(brewingStandBlockEntity).isPresent()) { // Paper - Fix InventoryOpenEvent cancellation
|
||||
player.awardStat(Stats.INTERACT_WITH_BREWINGSTAND);
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/CartographyTableBlock.java b/src/main/java/net/minecraft/world/level/block/CartographyTableBlock.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/CartographyTableBlock.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/CartographyTableBlock.java
|
||||
@@ -0,0 +0,0 @@ public class CartographyTableBlock extends Block {
|
||||
@Override
|
||||
protected InteractionResult useWithoutItem(BlockState state, Level world, BlockPos pos, Player player, BlockHitResult hit) {
|
||||
if (!world.isClientSide) {
|
||||
- player.openMenu(state.getMenuProvider(world, pos));
|
||||
+ if (player.openMenu(state.getMenuProvider(world, pos)).isPresent()) { // Paper - Fix InventoryOpenEvent cancellation
|
||||
player.awardStat(Stats.INTERACT_WITH_CARTOGRAPHY_TABLE);
|
||||
+ } // Paper - Fix InventoryOpenEvent cancellation
|
||||
}
|
||||
|
||||
return InteractionResult.SUCCESS;
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/ChestBlock.java b/src/main/java/net/minecraft/world/level/block/ChestBlock.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/ChestBlock.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/ChestBlock.java
|
||||
@@ -0,0 +0,0 @@ public class ChestBlock extends AbstractChestBlock<ChestBlockEntity> implements
|
||||
if (world instanceof ServerLevel worldserver) {
|
||||
MenuProvider itileinventory = this.getMenuProvider(state, world, pos);
|
||||
|
||||
- if (itileinventory != null) {
|
||||
- player.openMenu(itileinventory);
|
||||
+ if (itileinventory != null && player.openMenu(itileinventory).isPresent()) { // Paper - Fix InventoryOpenEvent cancellation
|
||||
player.awardStat(this.getOpenChestStat());
|
||||
PiglinAi.angerNearbyPiglins(worldserver, player, true);
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/CraftingTableBlock.java b/src/main/java/net/minecraft/world/level/block/CraftingTableBlock.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/CraftingTableBlock.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/CraftingTableBlock.java
|
||||
@@ -0,0 +0,0 @@ public class CraftingTableBlock extends Block {
|
||||
@Override
|
||||
protected InteractionResult useWithoutItem(BlockState state, Level world, BlockPos pos, Player player, BlockHitResult hit) {
|
||||
if (!world.isClientSide) {
|
||||
- player.openMenu(state.getMenuProvider(world, pos));
|
||||
+ if (player.openMenu(state.getMenuProvider(world, pos)).isPresent()) { // Paper - Fix InventoryOpenEvent cancellation
|
||||
player.awardStat(Stats.INTERACT_WITH_CRAFTING_TABLE);
|
||||
+ } // Paper - Fix InventoryOpenEvent cancellation
|
||||
}
|
||||
|
||||
return InteractionResult.SUCCESS;
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/DispenserBlock.java b/src/main/java/net/minecraft/world/level/block/DispenserBlock.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/DispenserBlock.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/DispenserBlock.java
|
||||
@@ -0,0 +0,0 @@ public class DispenserBlock extends BaseEntityBlock {
|
||||
if (tileentity instanceof DispenserBlockEntity) {
|
||||
DispenserBlockEntity tileentitydispenser = (DispenserBlockEntity) tileentity;
|
||||
|
||||
- player.openMenu(tileentitydispenser);
|
||||
+ if (player.openMenu(tileentitydispenser).isPresent()) { // Paper - Fix InventoryOpenEvent cancellation
|
||||
player.awardStat(tileentitydispenser instanceof DropperBlockEntity ? Stats.INSPECT_DROPPER : Stats.INSPECT_DISPENSER);
|
||||
+ } // Paper - Fix InventoryOpenEvent cancellation
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/EnderChestBlock.java b/src/main/java/net/minecraft/world/level/block/EnderChestBlock.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/EnderChestBlock.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/EnderChestBlock.java
|
||||
@@ -0,0 +0,0 @@ public class EnderChestBlock extends AbstractChestBlock<EnderChestBlockEntity> i
|
||||
if (world.getBlockState(blockPos).isRedstoneConductor(world, blockPos)) { // Paper - diff on change; make sure that EnderChest#isBlocked uses the same logic
|
||||
return InteractionResult.SUCCESS;
|
||||
} else {
|
||||
- if (world instanceof ServerLevel serverLevel) {
|
||||
- playerEnderChestContainer.setActiveChest(enderChestBlockEntity);
|
||||
- player.openMenu(
|
||||
- new SimpleMenuProvider((i, inventory, playerx) -> ChestMenu.threeRows(i, inventory, playerEnderChestContainer), CONTAINER_TITLE)
|
||||
- );
|
||||
+ // Paper start - Fix InventoryOpenEvent cancellation - moved up;
|
||||
+ playerEnderChestContainer.setActiveChest(enderChestBlockEntity); // Needs to happen before ChestMenu.threeRows as it is required for opening animations
|
||||
+ if (world instanceof ServerLevel serverLevel && player.openMenu(
|
||||
+ new SimpleMenuProvider((i, inventory, playerx) -> ChestMenu.threeRows(i, inventory, playerEnderChestContainer), CONTAINER_TITLE)
|
||||
+ ).isPresent()) {
|
||||
+ // Paper end - Fix InventoryOpenEvent cancellation - moved up;
|
||||
+ // Paper - Fix InventoryOpenEvent cancellation - moved up;
|
||||
player.awardStat(Stats.OPEN_ENDERCHEST);
|
||||
PiglinAi.angerNearbyPiglins(serverLevel, player, true);
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/FurnaceBlock.java b/src/main/java/net/minecraft/world/level/block/FurnaceBlock.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/FurnaceBlock.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/FurnaceBlock.java
|
||||
@@ -0,0 +0,0 @@ public class FurnaceBlock extends AbstractFurnaceBlock {
|
||||
@Override
|
||||
protected void openContainer(Level world, BlockPos pos, Player player) {
|
||||
BlockEntity blockEntity = world.getBlockEntity(pos);
|
||||
- if (blockEntity instanceof FurnaceBlockEntity) {
|
||||
- player.openMenu((MenuProvider)blockEntity);
|
||||
+ if (blockEntity instanceof FurnaceBlockEntity && player.openMenu((MenuProvider)blockEntity).isPresent()) { // Paper - Fix InventoryOpenEvent cancellation
|
||||
player.awardStat(Stats.INTERACT_WITH_FURNACE);
|
||||
}
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/GrindstoneBlock.java b/src/main/java/net/minecraft/world/level/block/GrindstoneBlock.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/GrindstoneBlock.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/GrindstoneBlock.java
|
||||
@@ -0,0 +0,0 @@ public class GrindstoneBlock extends FaceAttachedHorizontalDirectionalBlock {
|
||||
@Override
|
||||
protected InteractionResult useWithoutItem(BlockState state, Level world, BlockPos pos, Player player, BlockHitResult hit) {
|
||||
if (!world.isClientSide) {
|
||||
- player.openMenu(state.getMenuProvider(world, pos));
|
||||
+ if (player.openMenu(state.getMenuProvider(world, pos)).isPresent()) { // Paper - Fix InventoryOpenEvent cancellation
|
||||
player.awardStat(Stats.INTERACT_WITH_GRINDSTONE);
|
||||
+ } // Paper - Fix InventoryOpenEvent cancellation
|
||||
}
|
||||
|
||||
return InteractionResult.SUCCESS;
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/HopperBlock.java b/src/main/java/net/minecraft/world/level/block/HopperBlock.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/HopperBlock.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/HopperBlock.java
|
||||
@@ -0,0 +0,0 @@ public class HopperBlock extends BaseEntityBlock {
|
||||
|
||||
@Override
|
||||
protected InteractionResult useWithoutItem(BlockState state, Level world, BlockPos pos, Player player, BlockHitResult hit) {
|
||||
- if (!world.isClientSide && world.getBlockEntity(pos) instanceof HopperBlockEntity hopperBlockEntity) {
|
||||
- player.openMenu(hopperBlockEntity);
|
||||
+ if (!world.isClientSide && world.getBlockEntity(pos) instanceof HopperBlockEntity hopperBlockEntity && player.openMenu(hopperBlockEntity).isPresent()) { // Paper - Fix InventoryOpenEvent cancellation
|
||||
player.awardStat(Stats.INSPECT_HOPPER);
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/LecternBlock.java b/src/main/java/net/minecraft/world/level/block/LecternBlock.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/LecternBlock.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/LecternBlock.java
|
||||
@@ -0,0 +0,0 @@ public class LecternBlock extends BaseEntityBlock {
|
||||
private void openScreen(Level world, BlockPos pos, Player player) {
|
||||
BlockEntity tileentity = world.getBlockEntity(pos);
|
||||
|
||||
- if (tileentity instanceof LecternBlockEntity) {
|
||||
- player.openMenu((LecternBlockEntity) tileentity);
|
||||
+ if (tileentity instanceof LecternBlockEntity && player.openMenu((LecternBlockEntity) tileentity).isPresent()) { // Paper - Fix InventoryOpenEvent cancellation
|
||||
player.awardStat(Stats.INTERACT_WITH_LECTERN);
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/LoomBlock.java b/src/main/java/net/minecraft/world/level/block/LoomBlock.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/LoomBlock.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/LoomBlock.java
|
||||
@@ -0,0 +0,0 @@ public class LoomBlock extends HorizontalDirectionalBlock {
|
||||
@Override
|
||||
protected InteractionResult useWithoutItem(BlockState state, Level world, BlockPos pos, Player player, BlockHitResult hit) {
|
||||
if (!world.isClientSide) {
|
||||
- player.openMenu(state.getMenuProvider(world, pos));
|
||||
+ if (player.openMenu(state.getMenuProvider(world, pos)).isPresent()) { // Paper - Fix InventoryOpenEvent cancellation
|
||||
player.awardStat(Stats.INTERACT_WITH_LOOM);
|
||||
+ } // Paper - Fix InventoryOpenEvent cancellation
|
||||
}
|
||||
|
||||
return InteractionResult.SUCCESS;
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/ShulkerBoxBlock.java b/src/main/java/net/minecraft/world/level/block/ShulkerBoxBlock.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/ShulkerBoxBlock.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/ShulkerBoxBlock.java
|
||||
@@ -0,0 +0,0 @@ public class ShulkerBoxBlock extends BaseEntityBlock {
|
||||
protected InteractionResult useWithoutItem(BlockState state, Level world, BlockPos pos, Player player, BlockHitResult hit) {
|
||||
if (world instanceof ServerLevel serverLevel
|
||||
&& world.getBlockEntity(pos) instanceof ShulkerBoxBlockEntity shulkerBoxBlockEntity
|
||||
- && canOpen(state, world, pos, shulkerBoxBlockEntity)) {
|
||||
- player.openMenu(shulkerBoxBlockEntity);
|
||||
+ && canOpen(state, world, pos, shulkerBoxBlockEntity) // Paper - Fix InventoryOpenEvent cancellation - expand if for belows check
|
||||
+ && player.openMenu(shulkerBoxBlockEntity).isPresent()) { // Paper - Fix InventoryOpenEvent cancellation
|
||||
player.awardStat(Stats.OPEN_SHULKER_BOX);
|
||||
PiglinAi.angerNearbyPiglins(serverLevel, player, true);
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/SmithingTableBlock.java b/src/main/java/net/minecraft/world/level/block/SmithingTableBlock.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/SmithingTableBlock.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/SmithingTableBlock.java
|
||||
@@ -0,0 +0,0 @@ public class SmithingTableBlock extends CraftingTableBlock {
|
||||
@Override
|
||||
protected InteractionResult useWithoutItem(BlockState state, Level world, BlockPos pos, Player player, BlockHitResult hit) {
|
||||
if (!world.isClientSide) {
|
||||
- player.openMenu(state.getMenuProvider(world, pos));
|
||||
+ if (player.openMenu(state.getMenuProvider(world, pos)).isPresent()) { // Paper - Fix InventoryOpenEvent cancellation
|
||||
player.awardStat(Stats.INTERACT_WITH_SMITHING_TABLE);
|
||||
+ } // Paper - Fix InventoryOpenEvent cancellation
|
||||
}
|
||||
|
||||
return InteractionResult.SUCCESS;
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/SmokerBlock.java b/src/main/java/net/minecraft/world/level/block/SmokerBlock.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/SmokerBlock.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/SmokerBlock.java
|
||||
@@ -0,0 +0,0 @@ public class SmokerBlock extends AbstractFurnaceBlock {
|
||||
@Override
|
||||
protected void openContainer(Level world, BlockPos pos, Player player) {
|
||||
BlockEntity blockEntity = world.getBlockEntity(pos);
|
||||
- if (blockEntity instanceof SmokerBlockEntity) {
|
||||
- player.openMenu((MenuProvider)blockEntity);
|
||||
+ if (blockEntity instanceof SmokerBlockEntity && player.openMenu((MenuProvider)blockEntity).isPresent()) { // Paper - Fix InventoryOpenEvent cancellation
|
||||
player.awardStat(Stats.INTERACT_WITH_SMOKER);
|
||||
}
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/StonecutterBlock.java b/src/main/java/net/minecraft/world/level/block/StonecutterBlock.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/StonecutterBlock.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/StonecutterBlock.java
|
||||
@@ -0,0 +0,0 @@ public class StonecutterBlock extends Block {
|
||||
@Override
|
||||
protected InteractionResult useWithoutItem(BlockState state, Level world, BlockPos pos, Player player, BlockHitResult hit) {
|
||||
if (!world.isClientSide) {
|
||||
- player.openMenu(state.getMenuProvider(world, pos));
|
||||
+ if (player.openMenu(state.getMenuProvider(world, pos)).isPresent()) { // Paper - Fix InventoryOpenEvent cancellation
|
||||
player.awardStat(Stats.INTERACT_WITH_STONECUTTER);
|
||||
+ } // Paper - Fix InventoryOpenEvent cancellation
|
||||
}
|
||||
|
||||
return InteractionResult.SUCCESS;
|
||||
@@ -1,52 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Nassim Jahnke <nassim@njahnke.dev>
|
||||
Date: Sat, 21 Sep 2024 22:01:52 +0200
|
||||
Subject: [PATCH] Fix PlayerCommandPreprocessEvent on signed commands
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
|
||||
|
||||
PlayerCommandPreprocessEvent event = new PlayerCommandPreprocessEvent(this.getCraftPlayer(), command, new LazyPlayerSet(this.server));
|
||||
this.cserver.getPluginManager().callEvent(event);
|
||||
-
|
||||
- if (event.isCancelled()) {
|
||||
- return;
|
||||
- }
|
||||
command = event.getMessage().substring(1);
|
||||
|
||||
- ParseResults<CommandSourceStack> parseresults = this.parseCommand(command);
|
||||
- // CraftBukkit end
|
||||
-
|
||||
- Map map;
|
||||
+ // Paper start - Fix cancellation and message changing
|
||||
+ ParseResults<CommandSourceStack> parseresults = this.parseCommand(packet.command());
|
||||
|
||||
+ Map<String, PlayerChatMessage> map;
|
||||
try {
|
||||
- map = (packet.command().equals(command)) ? this.collectSignedArguments(packet, SignableCommand.of(parseresults), lastSeenMessages) : Collections.emptyMap(); // CraftBukkit
|
||||
+ // Always parse the original command to add to the chat chain
|
||||
+ map = this.collectSignedArguments(packet, SignableCommand.of(parseresults), lastSeenMessages);
|
||||
} catch (SignedMessageChain.DecodeException signedmessagechain_a) {
|
||||
this.handleMessageDecodeFailure(signedmessagechain_a);
|
||||
return;
|
||||
}
|
||||
|
||||
+ if (event.isCancelled()) {
|
||||
+ // Only now are we actually good to return
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ // Remove signed parts if the command was changed
|
||||
+ if (!command.equals(packet.command())) {
|
||||
+ parseresults = this.parseCommand(command);
|
||||
+ map = Collections.emptyMap();
|
||||
+ }
|
||||
+ // Paper end - Fix cancellation and message changing
|
||||
+
|
||||
CommandSigningContext.SignedArguments commandsigningcontext_a = new CommandSigningContext.SignedArguments(map);
|
||||
|
||||
parseresults = Commands.<CommandSourceStack>mapSource(parseresults, (commandlistenerwrapper) -> { // CraftBukkit - decompile error
|
||||
@@ -1,39 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
Date: Mon, 19 Aug 2024 13:43:06 -0700
|
||||
Subject: [PATCH] Fix SculkBloomEvent firing for block entity loading
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/SculkSpreader.java b/src/main/java/net/minecraft/world/level/block/SculkSpreader.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/SculkSpreader.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/SculkSpreader.java
|
||||
@@ -0,0 +0,0 @@ public class SculkSpreader {
|
||||
int i = Math.min(list.size(), 32);
|
||||
|
||||
for (int j = 0; j < i; ++j) {
|
||||
- this.addCursor((SculkSpreader.ChargeCursor) list.get(j));
|
||||
+ this.addCursor((SculkSpreader.ChargeCursor) list.get(j), false); // Paper - don't fire event for block entity loading
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +0,0 @@ public class SculkSpreader {
|
||||
while (charge > 0) {
|
||||
int j = Math.min(charge, 1000);
|
||||
|
||||
- this.addCursor(new SculkSpreader.ChargeCursor(pos, j));
|
||||
+ this.addCursor(new SculkSpreader.ChargeCursor(pos, j), true); // Paper - allow firing event for other causes
|
||||
charge -= j;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
- private void addCursor(SculkSpreader.ChargeCursor cursor) {
|
||||
+ private void addCursor(SculkSpreader.ChargeCursor cursor, boolean fireEvent) { // Paper - add boolean to conditionally fire SculkBloomEvent
|
||||
if (this.cursors.size() < 32) {
|
||||
// CraftBukkit start
|
||||
- if (!this.isWorldGeneration()) { // CraftBukkit - SPIGOT-7475: Don't call event during world generation
|
||||
+ if (!this.isWorldGeneration() && fireEvent) { // CraftBukkit - SPIGOT-7475: Don't call event during world generation // Paper - add boolean to conditionally fire SculkBloomEvent
|
||||
CraftBlock bukkitBlock = CraftBlock.at(this.level, cursor.pos);
|
||||
SculkBloomEvent event = new SculkBloomEvent(bukkitBlock, cursor.getCharge());
|
||||
Bukkit.getPluginManager().callEvent(event);
|
||||
@@ -1,27 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Gegy <gegy.dev@gmail.com>
|
||||
Date: Mon, 26 Aug 2024 19:45:07 +0200
|
||||
Subject: [PATCH] Fix: synchronise sending chat to client with updating message
|
||||
signature cache
|
||||
|
||||
In the case where multiple messages from different players are being processed in parallel, there was a potential race condition where the messages would be sent to the client in a different order than the message signature cache was updated. However, the cache relies on the fact that the client and server get the exact same updates in the same order. This race condition would cause the caches to become corrupted, and any future message received by the client would fail to validate.
|
||||
|
||||
This also applies to the last seen state of the server, which becomes inconsistent in the same way as the message signature cache and would cause any messages sent to be rejected by the server too.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
|
||||
return;
|
||||
}
|
||||
// CraftBukkit end
|
||||
+ // Paper start - Ensure that client receives chat packets in the same order that we add into the message signature cache
|
||||
+ synchronized (this.messageSignatureCache) {
|
||||
this.send(new ClientboundPlayerChatPacket(message.link().sender(), message.link().index(), message.signature(), message.signedBody().pack(this.messageSignatureCache), message.unsignedContent(), message.filterMask(), params));
|
||||
this.addPendingMessage(message);
|
||||
+ }
|
||||
+ // Paper end - Ensure that client receives chat packets in the same order that we add into the message signature cache
|
||||
}
|
||||
|
||||
public void sendDisguisedChatMessage(Component message, ChatType.Bound params) {
|
||||
@@ -1,154 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
Date: Fri, 27 Sep 2024 17:13:16 -0700
|
||||
Subject: [PATCH] Improve entity effect API
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
|
||||
@@ -0,0 +0,0 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
|
||||
return this.getHandle().getScoreboardName();
|
||||
}
|
||||
// Paper end - entity scoreboard name
|
||||
+
|
||||
+ // Paper start - broadcast hurt animation
|
||||
+ @Override
|
||||
+ public void broadcastHurtAnimation(java.util.Collection<Player> players) {
|
||||
+ //noinspection SuspiciousMethodCalls
|
||||
+ Preconditions.checkArgument(!players.contains(this), "Cannot broadcast hurt animation to self without a yaw");
|
||||
+ for (final org.bukkit.entity.Player player : players) {
|
||||
+ ((CraftPlayer) player).sendHurtAnimation(0, this);
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end - broadcast hurt animation
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
@@ -0,0 +0,0 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
|
||||
|
||||
@Override
|
||||
public void sendHurtAnimation(float yaw) {
|
||||
+ // Paper start - Add target entity to sendHurtAnimation
|
||||
+ this.sendHurtAnimation(yaw, this);
|
||||
+ }
|
||||
+ public void sendHurtAnimation(float yaw, org.bukkit.entity.Entity target) {
|
||||
+ // Paper end - Add target entity to sendHurtAnimation
|
||||
if (this.getHandle().connection == null) {
|
||||
return;
|
||||
}
|
||||
@@ -0,0 +0,0 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
|
||||
* This makes no sense. We'll add 90 to it so that 0 = front, clockwise from there.
|
||||
*/
|
||||
float actualYaw = yaw + 90;
|
||||
- this.getHandle().connection.send(new ClientboundHurtAnimationPacket(this.getEntityId(), actualYaw));
|
||||
+ this.getHandle().connection.send(new ClientboundHurtAnimationPacket(target.getEntityId(), actualYaw)); // Paper - Add target entity to sendHurtAnimation
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -0,0 +0,0 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
|
||||
public void setSendViewDistance(final int viewDistance) {
|
||||
throw new UnsupportedOperationException("Not implemented yet");
|
||||
}
|
||||
+
|
||||
+ // Paper start - entity effect API
|
||||
+ @Override
|
||||
+ public void sendEntityEffect(final org.bukkit.EntityEffect effect, final org.bukkit.entity.Entity target) {
|
||||
+ if (this.getHandle().connection == null || !effect.isApplicableTo(target)) {
|
||||
+ return;
|
||||
+ }
|
||||
+ this.getHandle().connection.send(new net.minecraft.network.protocol.game.ClientboundEntityEventPacket(((CraftEntity) target).getHandle(), effect.getData()));
|
||||
+ }
|
||||
+ // Paper end - entity effect API
|
||||
}
|
||||
diff --git a/src/test/java/org/bukkit/EntityEffectTest.java b/src/test/java/org/bukkit/EntityEffectTest.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
||||
--- /dev/null
|
||||
+++ b/src/test/java/org/bukkit/EntityEffectTest.java
|
||||
@@ -0,0 +0,0 @@
|
||||
+package org.bukkit;
|
||||
+
|
||||
+import com.google.common.base.Joiner;
|
||||
+import java.lang.reflect.Field;
|
||||
+import java.lang.reflect.Modifier;
|
||||
+import java.util.ArrayList;
|
||||
+import java.util.HashMap;
|
||||
+import java.util.HashSet;
|
||||
+import java.util.List;
|
||||
+import java.util.Map;
|
||||
+import java.util.Set;
|
||||
+import net.minecraft.world.entity.EntityEvent;
|
||||
+import org.bukkit.support.environment.Normal;
|
||||
+import org.junit.jupiter.api.Test;
|
||||
+
|
||||
+import static org.junit.jupiter.api.Assertions.fail;
|
||||
+
|
||||
+@Normal
|
||||
+public class EntityEffectTest {
|
||||
+
|
||||
+ private static List<Byte> collectNmsLevelEvents() throws ReflectiveOperationException {
|
||||
+ final List<Byte> events = new ArrayList<>();
|
||||
+ for (final Field field : EntityEvent.class.getFields()) {
|
||||
+ if (Modifier.isStatic(field.getModifiers()) && Modifier.isFinal(field.getModifiers()) && field.getType() == byte.class) {
|
||||
+ events.add((byte) field.get(null));
|
||||
+ }
|
||||
+ }
|
||||
+ for (int i = 22; i <= 28; i++) {
|
||||
+ events.remove(Byte.valueOf((byte) i)); // all have existing API (debug info and op level)
|
||||
+ }
|
||||
+ events.remove(Byte.valueOf(EntityEvent.STOP_ATTACKING)); // not used on client anywhere
|
||||
+ events.remove(Byte.valueOf(EntityEvent.USE_ITEM_COMPLETE)); // not suitable for API (complete using item on Player)
|
||||
+ events.remove(Byte.valueOf(EntityEvent.FISHING_ROD_REEL_IN)); // not suitable for API (fishing rod reel in on FishingHook)
|
||||
+ events.add((byte) 0); // handled on Arrow (for some reason it's not in the EntityEvent nms file as a constant)
|
||||
+ return events;
|
||||
+ }
|
||||
+
|
||||
+ private static boolean isNotDeprecated(EntityEffect effect) throws ReflectiveOperationException {
|
||||
+ return !EntityEffect.class.getDeclaredField(effect.name()).isAnnotationPresent(Deprecated.class);
|
||||
+ }
|
||||
+
|
||||
+ @Test
|
||||
+ public void checkAllApiExists() throws ReflectiveOperationException {
|
||||
+ Map<Byte, EntityEffect> toId = new HashMap<>();
|
||||
+ for (final EntityEffect effect : EntityEffect.values()) {
|
||||
+ if (isNotDeprecated(effect)) {
|
||||
+ toId.put(effect.getData(), effect);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ final Set<Byte> missingEvents = new HashSet<>();
|
||||
+ for (final Byte event : collectNmsLevelEvents()) {
|
||||
+ if (toId.get(event) == null) {
|
||||
+ missingEvents.add(event);
|
||||
+ }
|
||||
+ }
|
||||
+ if (!missingEvents.isEmpty()) {
|
||||
+ fail("Missing API EntityEffects:\n" + Joiner.on("\n").join(missingEvents));
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ @Test
|
||||
+ public void checkNoExtraApi() throws ReflectiveOperationException {
|
||||
+ Map<Byte, EntityEffect> toId = new HashMap<>();
|
||||
+ for (final EntityEffect effect : EntityEffect.values()) {
|
||||
+ if (isNotDeprecated(effect)) {
|
||||
+ toId.put(effect.getData(), effect);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ final List<Byte> nmsEvents = collectNmsLevelEvents();
|
||||
+ final Set<EntityEffect> extraApiEffects = new HashSet<>();
|
||||
+ for (final Map.Entry<Byte, EntityEffect> entry : toId.entrySet()) {
|
||||
+ if (!nmsEvents.contains(entry.getKey())) {
|
||||
+ extraApiEffects.add(entry.getValue());
|
||||
+ }
|
||||
+ }
|
||||
+ if (!extraApiEffects.isEmpty()) {
|
||||
+ fail("Extra API EntityEffects:\n" + Joiner.on("\n").join(extraApiEffects));
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
@@ -1,73 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: masmc05 <masmc05@gmail.com>
|
||||
Date: Sun, 11 Aug 2024 03:01:52 +0300
|
||||
Subject: [PATCH] Item serialization as json
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/item/component/CustomData.java b/src/main/java/net/minecraft/world/item/component/CustomData.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/world/item/component/CustomData.java
|
||||
+++ b/src/main/java/net/minecraft/world/item/component/CustomData.java
|
||||
@@ -0,0 +0,0 @@ import org.slf4j.Logger;
|
||||
public final class CustomData {
|
||||
private static final Logger LOGGER = LogUtils.getLogger();
|
||||
public static final CustomData EMPTY = new CustomData(new CompoundTag());
|
||||
- public static final Codec<CustomData> CODEC = Codec.withAlternative(CompoundTag.CODEC, TagParser.AS_CODEC)
|
||||
+ // Paper start - Item serialization as json
|
||||
+ public static ThreadLocal<Boolean> SERIALIZE_CUSTOM_AS_SNBT = ThreadLocal.withInitial(() -> false);
|
||||
+ public static final Codec<CustomData> CODEC = Codec.either(CompoundTag.CODEC, TagParser.AS_CODEC)
|
||||
+ .xmap(com.mojang.datafixers.util.Either::unwrap, data -> { // Both will be used for deserialization, but we decide which one to use for serialization
|
||||
+ if (!SERIALIZE_CUSTOM_AS_SNBT.get()) {
|
||||
+ return com.mojang.datafixers.util.Either.left(data); // First codec
|
||||
+ } else {
|
||||
+ return com.mojang.datafixers.util.Either.right(data); // Second codec
|
||||
+ }
|
||||
+ })
|
||||
+ // Paper end - Item serialization as json
|
||||
.xmap(CustomData::new, component -> component.tag);
|
||||
public static final Codec<CustomData> CODEC_WITH_ID = CODEC.validate(
|
||||
component -> component.getUnsafe().contains("id", 8) ? DataResult.success(component) : DataResult.error(() -> "Missing id for entity in: " + component)
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
|
||||
@@ -0,0 +0,0 @@ public final class CraftMagicNumbers implements UnsafeValues {
|
||||
return CraftItemStack.asCraftMirror(net.minecraft.world.item.ItemStack.parse(MinecraftServer.getServer().registryAccess(), compound).orElseThrow());
|
||||
}
|
||||
|
||||
+ @Override
|
||||
+ public com.google.gson.JsonObject serializeItemAsJson(ItemStack itemStack) {
|
||||
+ Preconditions.checkNotNull(itemStack, "Cannot serialize empty ItemStack");
|
||||
+ Preconditions.checkArgument(!itemStack.isEmpty(), "Cannot serialize empty ItemStack");
|
||||
+
|
||||
+ net.minecraft.core.RegistryAccess.Frozen reg = net.minecraft.server.MinecraftServer.getServer().registryAccess();
|
||||
+ com.mojang.serialization.DynamicOps<com.google.gson.JsonElement> ops = reg.createSerializationContext(com.mojang.serialization.JsonOps.INSTANCE);
|
||||
+ com.google.gson.JsonObject item;
|
||||
+ // Serialize as SNBT to preserve exact NBT types; vanilla codecs already can handle such deserialization.
|
||||
+ net.minecraft.world.item.component.CustomData.SERIALIZE_CUSTOM_AS_SNBT.set(true);
|
||||
+ try {
|
||||
+ item = net.minecraft.world.item.ItemStack.CODEC.encodeStart(ops, CraftItemStack.unwrap(itemStack)).getOrThrow().getAsJsonObject();
|
||||
+ } finally {
|
||||
+ net.minecraft.world.item.component.CustomData.SERIALIZE_CUSTOM_AS_SNBT.set(false);
|
||||
+ }
|
||||
+ item.addProperty("DataVersion", this.getDataVersion());
|
||||
+ return item;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public ItemStack deserializeItemFromJson(com.google.gson.JsonObject data) throws IllegalArgumentException {
|
||||
+ Preconditions.checkNotNull(data, "null cannot be deserialized");
|
||||
+
|
||||
+ final int dataVersion = data.get("DataVersion").getAsInt();
|
||||
+ final int currentVersion = org.bukkit.craftbukkit.util.CraftMagicNumbers.INSTANCE.getDataVersion();
|
||||
+ data = ca.spottedleaf.dataconverter.minecraft.MCDataConverter.convertJson(
|
||||
+ ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry.ITEM_STACK,
|
||||
+ data, false, dataVersion, currentVersion
|
||||
+ );
|
||||
+ com.mojang.serialization.DynamicOps<com.google.gson.JsonElement> ops = MinecraftServer.getServer().registryAccess().createSerializationContext(com.mojang.serialization.JsonOps.INSTANCE);
|
||||
+ return CraftItemStack.asCraftMirror(net.minecraft.world.item.ItemStack.CODEC.parse(ops, data).getOrThrow(IllegalArgumentException::new));
|
||||
+ }
|
||||
+
|
||||
@Override
|
||||
public byte[] serializeEntity(org.bukkit.entity.Entity entity) {
|
||||
Preconditions.checkNotNull(entity, "null cannot be serialized");
|
||||
@@ -1,41 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Newwind <support@newwindserver.com>
|
||||
Date: Thu, 22 Aug 2024 22:55:37 +0200
|
||||
Subject: [PATCH] Remove set damage lootable item function from compasses
|
||||
|
||||
In VanillaChestLoot, compasses accidentally have a setdamage loot
|
||||
function on them, but compasses don't take durability, resulting in a warning.
|
||||
This patch simply removes attempting to add damage to the compass item.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/data/loot/packs/VanillaChestLoot.java b/src/main/java/net/minecraft/data/loot/packs/VanillaChestLoot.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/data/loot/packs/VanillaChestLoot.java
|
||||
+++ b/src/main/java/net/minecraft/data/loot/packs/VanillaChestLoot.java
|
||||
@@ -0,0 +0,0 @@ public record VanillaChestLoot(HolderLookup.Provider registries) implements Loot
|
||||
.add(
|
||||
LootItem.lootTableItem(Items.COMPASS)
|
||||
.apply(SetItemCountFunction.setCount(ConstantValue.exactly(1.0F)))
|
||||
- .apply(SetItemDamageFunction.setDamage(UniformGenerator.between(0.15F, 0.8F)))
|
||||
.setWeight(1)
|
||||
)
|
||||
.add(LootItem.lootTableItem(Items.BUCKET).apply(SetItemCountFunction.setCount(UniformGenerator.between(1.0F, 2.0F))).setWeight(1))
|
||||
diff --git a/src/main/resources/data/minecraft/loot_table/chests/trial_chambers/intersection_barrel.json b/src/main/resources/data/minecraft/loot_table/chests/trial_chambers/intersection_barrel.json
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/resources/data/minecraft/loot_table/chests/trial_chambers/intersection_barrel.json
|
||||
+++ b/src/main/resources/data/minecraft/loot_table/chests/trial_chambers/intersection_barrel.json
|
||||
@@ -0,0 +0,0 @@
|
||||
"add": false,
|
||||
"count": 1.0,
|
||||
"function": "minecraft:set_count"
|
||||
- },
|
||||
- {
|
||||
- "add": false,
|
||||
- "damage": {
|
||||
- "type": "minecraft:uniform",
|
||||
- "max": 0.8,
|
||||
- "min": 0.15
|
||||
- },
|
||||
- "function": "minecraft:set_damage"
|
||||
}
|
||||
],
|
||||
"name": "minecraft:compass"
|
||||
@@ -1,163 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Bjarne Koll <git@lynxplay.dev>
|
||||
Date: Mon, 16 Sep 2024 23:07:29 +0200
|
||||
Subject: [PATCH] Remove wall-time / unused skip tick protection
|
||||
|
||||
Spigot still maintains some partial implementation of "tick skipping", a
|
||||
practice in which the MinecraftServer.currentTick field is updated not
|
||||
by an increment of one per actual tick, but instead set to
|
||||
System.currentTimeMillis() / 50. This behaviour means that the tracked
|
||||
tick may "skip" a tick value in case a previous tick took more than the
|
||||
expected 50ms.
|
||||
|
||||
To compensate for this in important paths, spigot/craftbukkit
|
||||
implements "wall-time". Instead of incrementing/decrementing ticks on
|
||||
block entities/entities by one for each call to their tick() method,
|
||||
they instead increment/decrement important values, like
|
||||
an ItemEntity's age or pickupDelay, by the difference of
|
||||
`currentTick - lastTick`, where `lastTick` is the value of
|
||||
`currentTick` during the last tick() call.
|
||||
|
||||
These "fixes" however do not play nicely with minecraft's simulation
|
||||
distance as entities/block entities implementing the above behaviour
|
||||
would "catch up" their values when moving from a non-ticking chunk to a
|
||||
ticking one as their `lastTick` value remains stuck on the last tick in
|
||||
a ticking chunk and hence lead to a large "catch up" once ticked again.
|
||||
|
||||
Paper completely removes the "tick skipping" behaviour (See patch
|
||||
"Further-improve-server-tick-loop"), making the above precautions
|
||||
completely unnecessary, which also rids paper of the previous described
|
||||
incompatibility with non-ticking chunks.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/item/ItemEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/item/ItemEntity.java
|
||||
@@ -0,0 +0,0 @@ public class ItemEntity extends Entity implements TraceableEntity {
|
||||
@Nullable
|
||||
public UUID target;
|
||||
public final float bobOffs;
|
||||
- private int lastTick = MinecraftServer.currentTick - 1; // CraftBukkit
|
||||
+ // private int lastTick = MinecraftServer.currentTick - 1; // CraftBukkit // Paper - remove anti tick skipping measures / wall time
|
||||
public boolean canMobPickup = true; // Paper - Item#canEntityPickup
|
||||
private int despawnRate = -1; // Paper - Alternative item-despawn-rate
|
||||
public net.kyori.adventure.util.TriState frictionState = net.kyori.adventure.util.TriState.NOT_SET; // Paper - Friction API
|
||||
@@ -0,0 +0,0 @@ public class ItemEntity extends Entity implements TraceableEntity {
|
||||
this.discard(EntityRemoveEvent.Cause.DESPAWN); // CraftBukkit - add Bukkit remove cause
|
||||
} else {
|
||||
super.tick();
|
||||
- // CraftBukkit start - Use wall time for pickup and despawn timers
|
||||
- int elapsedTicks = MinecraftServer.currentTick - this.lastTick;
|
||||
- if (this.pickupDelay != 32767) this.pickupDelay -= elapsedTicks;
|
||||
- if (this.age != -32768) this.age += elapsedTicks;
|
||||
- this.lastTick = MinecraftServer.currentTick;
|
||||
- // CraftBukkit end
|
||||
+ // Paper start - remove anti tick skipping measures / wall time - revert to vanilla
|
||||
+ if (this.pickupDelay > 0 && this.pickupDelay != 32767) {
|
||||
+ --this.pickupDelay;
|
||||
+ }
|
||||
+ // Paper end - remove anti tick skipping measures / wall time - revert to vanilla
|
||||
|
||||
this.xo = this.getX();
|
||||
this.yo = this.getY();
|
||||
@@ -0,0 +0,0 @@ public class ItemEntity extends Entity implements TraceableEntity {
|
||||
this.mergeWithNeighbours();
|
||||
}
|
||||
|
||||
- /* CraftBukkit start - moved up
|
||||
+ // Paper - remove anti tick skipping measures / wall time - revert to vanilla /* CraftBukkit start - moved up
|
||||
if (this.age != -32768) {
|
||||
++this.age;
|
||||
}
|
||||
@@ -0,0 +0,0 @@ public class ItemEntity extends Entity implements TraceableEntity {
|
||||
// Spigot start - copied from above
|
||||
@Override
|
||||
public void inactiveTick() {
|
||||
- // CraftBukkit start - Use wall time for pickup and despawn timers
|
||||
- int elapsedTicks = MinecraftServer.currentTick - this.lastTick;
|
||||
- if (this.pickupDelay != 32767) this.pickupDelay -= elapsedTicks;
|
||||
- if (this.age != -32768) this.age += elapsedTicks;
|
||||
- this.lastTick = MinecraftServer.currentTick;
|
||||
- // CraftBukkit end
|
||||
+ // Paper start - remove anti tick skipping measures / wall time - copied from above
|
||||
+ if (this.pickupDelay > 0 && this.pickupDelay != 32767) {
|
||||
+ --this.pickupDelay;
|
||||
+ }
|
||||
+ if (this.age != -32768) {
|
||||
+ ++this.age;
|
||||
+ }
|
||||
+ // Paper end - remove anti tick skipping measures / wall time - copied from above
|
||||
|
||||
if (!this.level().isClientSide && this.age >= this.despawnRate) { // Spigot // Paper - Alternative item-despawn-rate
|
||||
// CraftBukkit start - fire ItemDespawnEvent
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/monster/Zombie.java b/src/main/java/net/minecraft/world/entity/monster/Zombie.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/monster/Zombie.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/monster/Zombie.java
|
||||
@@ -0,0 +0,0 @@ public class Zombie extends Monster {
|
||||
private boolean canBreakDoors;
|
||||
private int inWaterTime;
|
||||
public int conversionTime;
|
||||
- private int lastTick = MinecraftServer.currentTick; // CraftBukkit - add field
|
||||
+ // private int lastTick = MinecraftServer.currentTick; // CraftBukkit - add field // Paper - remove anti tick skipping measures / wall time
|
||||
private boolean shouldBurnInDay = true; // Paper - Add more Zombie API
|
||||
|
||||
public Zombie(EntityType<? extends Zombie> type, Level world) {
|
||||
@@ -0,0 +0,0 @@ public class Zombie extends Monster {
|
||||
public void tick() {
|
||||
if (!this.level().isClientSide && this.isAlive() && !this.isNoAi()) {
|
||||
if (this.isUnderWaterConverting()) {
|
||||
- // CraftBukkit start - Use wall time instead of ticks for conversion
|
||||
- int elapsedTicks = MinecraftServer.currentTick - this.lastTick;
|
||||
- this.conversionTime -= elapsedTicks;
|
||||
- // CraftBukkit end
|
||||
+ --this.conversionTime; // Paper - remove anti tick skipping measures / wall time
|
||||
if (this.conversionTime < 0) {
|
||||
this.doUnderWaterConversion();
|
||||
}
|
||||
@@ -0,0 +0,0 @@ public class Zombie extends Monster {
|
||||
}
|
||||
|
||||
super.tick();
|
||||
- this.lastTick = MinecraftServer.currentTick; // CraftBukkit
|
||||
+ // this.lastTick = MinecraftServer.currentTick; // CraftBukkit // Paper - remove anti tick skipping measures / wall time
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -0,0 +0,0 @@ public class Zombie extends Monster {
|
||||
}
|
||||
// Paper end - Add more Zombie API
|
||||
public void startUnderWaterConversion(int ticksUntilWaterConversion) {
|
||||
- this.lastTick = MinecraftServer.currentTick; // CraftBukkit
|
||||
+ // this.lastTick = MinecraftServer.currentTick; // CraftBukkit // Paper - remove anti tick skipping measures / wall time
|
||||
this.conversionTime = ticksUntilWaterConversion;
|
||||
this.getEntityData().set(Zombie.DATA_DROWNED_CONVERSION_ID, true);
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/entity/BrewingStandBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BrewingStandBlockEntity.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/entity/BrewingStandBlockEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/entity/BrewingStandBlockEntity.java
|
||||
@@ -0,0 +0,0 @@ public class BrewingStandBlockEntity extends BaseContainerBlockEntity implements
|
||||
public int fuel;
|
||||
protected final ContainerData dataAccess;
|
||||
// CraftBukkit start - add fields and methods
|
||||
- private int lastTick = MinecraftServer.currentTick;
|
||||
+ // private int lastTick = MinecraftServer.currentTick; // Paper - remove anti tick skipping measures / wall time
|
||||
public List<HumanEntity> transaction = new java.util.ArrayList<HumanEntity>();
|
||||
private int maxStack = MAX_STACK;
|
||||
|
||||
@@ -0,0 +0,0 @@ public class BrewingStandBlockEntity extends BaseContainerBlockEntity implements
|
||||
boolean flag1 = blockEntity.brewTime > 0;
|
||||
ItemStack itemstack1 = (ItemStack) blockEntity.items.get(3);
|
||||
|
||||
- // CraftBukkit start - Use wall time instead of ticks for brewing
|
||||
- int elapsedTicks = MinecraftServer.currentTick - blockEntity.lastTick;
|
||||
- blockEntity.lastTick = MinecraftServer.currentTick;
|
||||
+ // Paper - remove anti tick skipping measures / wall time
|
||||
|
||||
if (flag1) {
|
||||
- blockEntity.brewTime -= elapsedTicks;
|
||||
+ --blockEntity.brewTime; // Paper - remove anti tick skipping measures / wall time - revert to vanilla
|
||||
boolean flag2 = blockEntity.brewTime <= 0; // == -> <=
|
||||
// CraftBukkit end
|
||||
|
||||
@@ -1,595 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
Date: Thu, 20 Jun 2024 09:40:57 -0700
|
||||
Subject: [PATCH] Tag Lifecycle Events
|
||||
|
||||
== AT ==
|
||||
public net/minecraft/tags/TagEntry id
|
||||
public net/minecraft/tags/TagEntry tag
|
||||
public net/minecraft/tags/TagEntry required
|
||||
|
||||
diff --git a/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/LifecycleEventTypeProviderImpl.java b/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/LifecycleEventTypeProviderImpl.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/LifecycleEventTypeProviderImpl.java
|
||||
+++ b/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/LifecycleEventTypeProviderImpl.java
|
||||
@@ -0,0 +0,0 @@ public final class LifecycleEventTypeProviderImpl implements LifecycleEventTypeP
|
||||
return (LifecycleEventTypeProviderImpl) LifecycleEventTypeProvider.provider();
|
||||
}
|
||||
|
||||
+ private final PaperTagEventTypeProvider provider = new PaperTagEventTypeProvider();
|
||||
+
|
||||
@Override
|
||||
public <O extends LifecycleEventOwner, E extends LifecycleEvent> LifecycleEventType.Monitorable<O, E> monitor(final String name, final Class<? extends O> ownerType) {
|
||||
return new MonitorableLifecycleEventType<>(name, ownerType);
|
||||
@@ -0,0 +0,0 @@ public final class LifecycleEventTypeProviderImpl implements LifecycleEventTypeP
|
||||
public <O extends LifecycleEventOwner, E extends LifecycleEvent> LifecycleEventType.Prioritizable<O, E> prioritized(final String name, final Class<? extends O> ownerType) {
|
||||
return new PrioritizableLifecycleEventType.Simple<>(name, ownerType);
|
||||
}
|
||||
+
|
||||
+ @Override
|
||||
+ public PaperTagEventTypeProvider tagProvider() {
|
||||
+ return this.provider;
|
||||
+ }
|
||||
}
|
||||
diff --git a/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/PaperTagEventTypeProvider.java b/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/PaperTagEventTypeProvider.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/plugin/lifecycle/event/types/PaperTagEventTypeProvider.java
|
||||
@@ -0,0 +0,0 @@
|
||||
+package io.papermc.paper.plugin.lifecycle.event.types;
|
||||
+
|
||||
+import io.papermc.paper.plugin.bootstrap.BootstrapContext;
|
||||
+import io.papermc.paper.plugin.lifecycle.event.registrar.ReloadableRegistrarEvent;
|
||||
+import io.papermc.paper.registry.RegistryKey;
|
||||
+import io.papermc.paper.tag.PaperTagListenerManager;
|
||||
+import io.papermc.paper.tag.PostFlattenTagRegistrar;
|
||||
+import io.papermc.paper.tag.PreFlattenTagRegistrar;
|
||||
+import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
+import org.checkerframework.framework.qual.DefaultQualifier;
|
||||
+
|
||||
+@DefaultQualifier(NonNull.class)
|
||||
+public class PaperTagEventTypeProvider implements TagEventTypeProvider {
|
||||
+
|
||||
+ @Override
|
||||
+ public <T> PrioritizableLifecycleEventType.Simple<BootstrapContext, ReloadableRegistrarEvent<PreFlattenTagRegistrar<T>>> preFlatten(final RegistryKey<T> registryKey) {
|
||||
+ return PaperTagListenerManager.INSTANCE.getPreFlattenType(registryKey);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public <T> PrioritizableLifecycleEventType.Simple<BootstrapContext, ReloadableRegistrarEvent<PostFlattenTagRegistrar<T>>> postFlatten(final RegistryKey<T> registryKey) {
|
||||
+ return PaperTagListenerManager.INSTANCE.getPostFlattenType(registryKey);
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/io/papermc/paper/tag/PaperPostFlattenTagRegistrar.java b/src/main/java/io/papermc/paper/tag/PaperPostFlattenTagRegistrar.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/tag/PaperPostFlattenTagRegistrar.java
|
||||
@@ -0,0 +0,0 @@
|
||||
+package io.papermc.paper.tag;
|
||||
+
|
||||
+import com.google.common.collect.Collections2;
|
||||
+import com.google.common.collect.ImmutableMap;
|
||||
+import com.google.common.collect.Lists;
|
||||
+import io.papermc.paper.adventure.PaperAdventure;
|
||||
+import io.papermc.paper.plugin.bootstrap.BootstrapContext;
|
||||
+import io.papermc.paper.plugin.lifecycle.event.registrar.PaperRegistrar;
|
||||
+import io.papermc.paper.registry.RegistryKey;
|
||||
+import io.papermc.paper.registry.TypedKey;
|
||||
+import io.papermc.paper.registry.tag.TagKey;
|
||||
+import java.util.ArrayList;
|
||||
+import java.util.Collection;
|
||||
+import java.util.Collections;
|
||||
+import java.util.List;
|
||||
+import java.util.Map;
|
||||
+import java.util.NoSuchElementException;
|
||||
+import java.util.Optional;
|
||||
+import java.util.function.Function;
|
||||
+import net.minecraft.resources.ResourceLocation;
|
||||
+import org.bukkit.craftbukkit.util.CraftNamespacedKey;
|
||||
+import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
+import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
+import org.checkerframework.framework.qual.DefaultQualifier;
|
||||
+
|
||||
+@SuppressWarnings("BoundedWildcard")
|
||||
+@DefaultQualifier(NonNull.class)
|
||||
+public class PaperPostFlattenTagRegistrar<M, T> implements PaperRegistrar<BootstrapContext>, PostFlattenTagRegistrar<T> {
|
||||
+
|
||||
+ public final Map<ResourceLocation, List<M>> tags;
|
||||
+ private final Function<ResourceLocation, Optional<? extends M>> fromIdConverter;
|
||||
+ private final Function<M, ResourceLocation> toIdConverter;
|
||||
+ private final RegistryKey<T> registryKey;
|
||||
+
|
||||
+ public PaperPostFlattenTagRegistrar(
|
||||
+ final Map<ResourceLocation, List<M>> tags,
|
||||
+ final TagEventConfig<M, T> config
|
||||
+ ) {
|
||||
+ this.tags = tags;
|
||||
+ this.fromIdConverter = config.fromIdConverter();
|
||||
+ this.toIdConverter = config.toIdConverter();
|
||||
+ this.registryKey = config.apiRegistryKey();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setCurrentContext(final @Nullable BootstrapContext owner) {
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public RegistryKey<T> registryKey() {
|
||||
+ return this.registryKey;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public Map<TagKey<T>, Collection<TypedKey<T>>> getAllTags() {
|
||||
+ final ImmutableMap.Builder<TagKey<T>, Collection<TypedKey<T>>> tags = ImmutableMap.builderWithExpectedSize(this.tags.size());
|
||||
+ for (final Map.Entry<ResourceLocation, List<M>> entry : this.tags.entrySet()) {
|
||||
+ final TagKey<T> key = TagKey.create(this.registryKey, CraftNamespacedKey.fromMinecraft(entry.getKey()));
|
||||
+ tags.put(key, this.convert(entry.getValue()));
|
||||
+ }
|
||||
+ return tags.build();
|
||||
+ }
|
||||
+
|
||||
+ private List<TypedKey<T>> convert(final List<M> nms) {
|
||||
+ return Collections.unmodifiableList(
|
||||
+ Lists.transform(nms, m -> this.convert(this.toIdConverter.apply(m)))
|
||||
+ );
|
||||
+ }
|
||||
+
|
||||
+ private TypedKey<T> convert(final ResourceLocation location) {
|
||||
+ return TypedKey.create(this.registryKey, CraftNamespacedKey.fromMinecraft(location));
|
||||
+ }
|
||||
+
|
||||
+ private M convert(final TypedKey<T> key) {
|
||||
+ final Optional<? extends M> optional = this.fromIdConverter.apply(PaperAdventure.asVanilla(key.key()));
|
||||
+ if (optional.isEmpty()) {
|
||||
+ throw new IllegalArgumentException(key + " doesn't exist");
|
||||
+ }
|
||||
+ return optional.get();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean hasTag(final TagKey<T> tagKey) {
|
||||
+ return this.tags.containsKey(PaperAdventure.asVanilla(tagKey.key()));
|
||||
+ }
|
||||
+
|
||||
+ private List<M> getNmsTag(final TagKey<T> tagKey, final boolean create) {
|
||||
+ final ResourceLocation vanillaKey = PaperAdventure.asVanilla(tagKey.key());
|
||||
+ List<M> tag = this.tags.get(vanillaKey);
|
||||
+ if (tag == null) {
|
||||
+ if (create) {
|
||||
+ tag = this.tags.computeIfAbsent(vanillaKey, k -> new ArrayList<>());
|
||||
+ } else {
|
||||
+ throw new NoSuchElementException("Tag " + tagKey + " is not present");
|
||||
+ }
|
||||
+ }
|
||||
+ return tag;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public Collection<TypedKey<T>> getTag(final TagKey<T> tagKey) {
|
||||
+ return this.convert(this.getNmsTag(tagKey, false));
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void addToTag(final TagKey<T> tagKey, final Collection<TypedKey<T>> values) {
|
||||
+ final List<M> nmsTag = new ArrayList<>(this.getNmsTag(tagKey, true));
|
||||
+ for (final TypedKey<T> key : values) {
|
||||
+ nmsTag.add(this.convert(key));
|
||||
+ }
|
||||
+ this.tags.put(PaperAdventure.asVanilla(tagKey.key()), nmsTag);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setTag(final TagKey<T> tagKey, final Collection<TypedKey<T>> values) {
|
||||
+ final List<M> newList = List.copyOf(Collections2.transform(values, this::convert));
|
||||
+ this.tags.put(PaperAdventure.asVanilla(tagKey.key()), newList);
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/io/papermc/paper/tag/PaperPreFlattenTagRegistrar.java b/src/main/java/io/papermc/paper/tag/PaperPreFlattenTagRegistrar.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/tag/PaperPreFlattenTagRegistrar.java
|
||||
@@ -0,0 +0,0 @@
|
||||
+package io.papermc.paper.tag;
|
||||
+
|
||||
+import com.google.common.base.Preconditions;
|
||||
+import com.google.common.collect.Collections2;
|
||||
+import com.google.common.collect.ImmutableMap;
|
||||
+import com.google.common.collect.Lists;
|
||||
+import io.papermc.paper.adventure.PaperAdventure;
|
||||
+import io.papermc.paper.plugin.bootstrap.BootstrapContext;
|
||||
+import io.papermc.paper.plugin.lifecycle.event.registrar.PaperRegistrar;
|
||||
+import io.papermc.paper.registry.RegistryKey;
|
||||
+import io.papermc.paper.registry.tag.TagKey;
|
||||
+import java.util.ArrayList;
|
||||
+import java.util.Collection;
|
||||
+import java.util.Collections;
|
||||
+import java.util.HashMap;
|
||||
+import java.util.List;
|
||||
+import java.util.Map;
|
||||
+import java.util.NoSuchElementException;
|
||||
+import net.minecraft.resources.ResourceLocation;
|
||||
+import net.minecraft.tags.TagLoader;
|
||||
+import org.bukkit.craftbukkit.util.CraftNamespacedKey;
|
||||
+import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
+import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
+import org.checkerframework.framework.qual.DefaultQualifier;
|
||||
+
|
||||
+@SuppressWarnings("BoundedWildcard")
|
||||
+@DefaultQualifier(NonNull.class)
|
||||
+public class PaperPreFlattenTagRegistrar<T> implements PaperRegistrar<BootstrapContext>, PreFlattenTagRegistrar<T> {
|
||||
+
|
||||
+ public final Map<ResourceLocation, List<TagLoader.EntryWithSource>> tags;
|
||||
+ private final RegistryKey<T> registryKey;
|
||||
+
|
||||
+ private @Nullable BootstrapContext owner;
|
||||
+
|
||||
+ public PaperPreFlattenTagRegistrar(
|
||||
+ final Map<ResourceLocation, List<TagLoader.EntryWithSource>> tags,
|
||||
+ final TagEventConfig<?, T> config
|
||||
+ ) {
|
||||
+ this.tags = new HashMap<>(tags);
|
||||
+ this.registryKey = config.apiRegistryKey();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setCurrentContext(final @Nullable BootstrapContext owner) {
|
||||
+ this.owner = owner;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public RegistryKey<T> registryKey() {
|
||||
+ return this.registryKey;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public Map<TagKey<T>, Collection<TagEntry<T>>> getAllTags() {
|
||||
+ final ImmutableMap.Builder<TagKey<T>, Collection<io.papermc.paper.tag.TagEntry<T>>> builder = ImmutableMap.builderWithExpectedSize(this.tags.size());
|
||||
+ for (final Map.Entry<ResourceLocation, List<TagLoader.EntryWithSource>> entry : this.tags.entrySet()) {
|
||||
+ final TagKey<T> key = TagKey.create(this.registryKey, CraftNamespacedKey.fromMinecraft(entry.getKey()));
|
||||
+ builder.put(key, convert(entry.getValue()));
|
||||
+ }
|
||||
+ return builder.build();
|
||||
+ }
|
||||
+
|
||||
+ private static <T> List<io.papermc.paper.tag.TagEntry<T>> convert(final List<TagLoader.EntryWithSource> nmsEntries) {
|
||||
+ return Collections.unmodifiableList(Lists.transform(nmsEntries, PaperPreFlattenTagRegistrar::convert));
|
||||
+ }
|
||||
+
|
||||
+ private static <T> io.papermc.paper.tag.TagEntry<T> convert(final TagLoader.EntryWithSource nmsEntry) {
|
||||
+ return new TagEntryImpl<>(CraftNamespacedKey.fromMinecraft(nmsEntry.entry().id), nmsEntry.entry().tag, nmsEntry.entry().required);
|
||||
+ }
|
||||
+
|
||||
+ private TagLoader.EntryWithSource convert(final TagEntry<T> entry) {
|
||||
+ Preconditions.checkState(this.owner != null, "Owner is not set");
|
||||
+ final ResourceLocation vanilla = PaperAdventure.asVanilla(entry.key());
|
||||
+ final net.minecraft.tags.TagEntry nmsEntry;
|
||||
+ if (entry.isTag()) {
|
||||
+ if (entry.isRequired()) {
|
||||
+ nmsEntry = net.minecraft.tags.TagEntry.tag(vanilla);
|
||||
+ } else {
|
||||
+ nmsEntry = net.minecraft.tags.TagEntry.optionalTag(vanilla);
|
||||
+ }
|
||||
+ } else {
|
||||
+ if (entry.isRequired()) {
|
||||
+ nmsEntry = net.minecraft.tags.TagEntry.element(vanilla);
|
||||
+ } else {
|
||||
+ nmsEntry = net.minecraft.tags.TagEntry.optionalElement(vanilla);
|
||||
+ }
|
||||
+ }
|
||||
+ return new TagLoader.EntryWithSource(nmsEntry, this.owner.getPluginMeta().getDisplayName());
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean hasTag(final TagKey<T> tagKey) {
|
||||
+ return this.tags.containsKey(PaperAdventure.asVanilla(tagKey.key()));
|
||||
+ }
|
||||
+
|
||||
+ private List<TagLoader.EntryWithSource> getNmsTag(final TagKey<T> tagKey, boolean create) {
|
||||
+ final ResourceLocation vanillaKey = PaperAdventure.asVanilla(tagKey.key());
|
||||
+ List<TagLoader.EntryWithSource> tag = this.tags.get(vanillaKey);
|
||||
+ if (tag == null) {
|
||||
+ if (create) {
|
||||
+ tag = this.tags.computeIfAbsent(vanillaKey, k -> new ArrayList<>());
|
||||
+ } else {
|
||||
+ throw new NoSuchElementException("Tag " + tagKey + " is not present");
|
||||
+ }
|
||||
+ }
|
||||
+ return tag;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public List<TagEntry<T>> getTag(final TagKey<T> tagKey) {
|
||||
+ return convert(this.getNmsTag(tagKey, false));
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void addToTag(final TagKey<T> tagKey, final Collection<TagEntry<T>> entries) {
|
||||
+ final List<TagLoader.EntryWithSource> nmsTag = new ArrayList<>(this.getNmsTag(tagKey, true));
|
||||
+ for (final TagEntry<T> tagEntry : entries) {
|
||||
+ nmsTag.add(this.convert(tagEntry));
|
||||
+ }
|
||||
+ this.tags.put(PaperAdventure.asVanilla(tagKey.key()), nmsTag);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setTag(final TagKey<T> tagKey, final Collection<TagEntry<T>> entries) {
|
||||
+ final List<TagLoader.EntryWithSource> newList = List.copyOf(Collections2.transform(entries, this::convert));
|
||||
+ this.tags.put(PaperAdventure.asVanilla(tagKey.key()), newList);
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/io/papermc/paper/tag/PaperTagListenerManager.java b/src/main/java/io/papermc/paper/tag/PaperTagListenerManager.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/tag/PaperTagListenerManager.java
|
||||
@@ -0,0 +0,0 @@
|
||||
+package io.papermc.paper.tag;
|
||||
+
|
||||
+import io.papermc.paper.plugin.bootstrap.BootstrapContext;
|
||||
+import io.papermc.paper.plugin.lifecycle.event.LifecycleEventRunner;
|
||||
+import io.papermc.paper.plugin.lifecycle.event.registrar.ReloadableRegistrarEvent;
|
||||
+import io.papermc.paper.plugin.lifecycle.event.types.AbstractLifecycleEventType;
|
||||
+import io.papermc.paper.plugin.lifecycle.event.types.PrioritizableLifecycleEventType;
|
||||
+import io.papermc.paper.registry.PaperRegistries;
|
||||
+import io.papermc.paper.registry.RegistryKey;
|
||||
+import io.papermc.paper.registry.event.RegistryEventMap;
|
||||
+import java.util.Collection;
|
||||
+import java.util.List;
|
||||
+import java.util.Map;
|
||||
+import net.minecraft.core.Holder;
|
||||
+import net.minecraft.core.Registry;
|
||||
+import net.minecraft.resources.ResourceLocation;
|
||||
+import net.minecraft.tags.TagLoader;
|
||||
+import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
+import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
+import org.checkerframework.framework.qual.DefaultQualifier;
|
||||
+
|
||||
+@DefaultQualifier(NonNull.class)
|
||||
+public class PaperTagListenerManager {
|
||||
+
|
||||
+ public static final String PRE_FLATTEN_EVENT_NAME = "pre-flatten";
|
||||
+ public static final String POST_FLATTEN_EVENT_NAME = "post-flatten";
|
||||
+
|
||||
+ public static final PaperTagListenerManager INSTANCE = new PaperTagListenerManager();
|
||||
+
|
||||
+ public final RegistryEventMap preFlatten = new RegistryEventMap(PRE_FLATTEN_EVENT_NAME);
|
||||
+ public final RegistryEventMap postFlatten = new RegistryEventMap(POST_FLATTEN_EVENT_NAME);
|
||||
+
|
||||
+ private PaperTagListenerManager() {
|
||||
+ }
|
||||
+
|
||||
+ public <A> Map<ResourceLocation, List<TagLoader.EntryWithSource>> firePreFlattenEvent(
|
||||
+ final Map<ResourceLocation, List<TagLoader.EntryWithSource>> initial,
|
||||
+ final @Nullable TagEventConfig<?, A> config
|
||||
+ ) {
|
||||
+ if (config == null || config.preFlatten() == null || !config.preFlatten().hasHandlers()) {
|
||||
+ return initial;
|
||||
+ }
|
||||
+ final PaperPreFlattenTagRegistrar<A> registrar = new PaperPreFlattenTagRegistrar<>(initial, config);
|
||||
+ LifecycleEventRunner.INSTANCE.callReloadableRegistrarEvent(
|
||||
+ config.preFlatten(),
|
||||
+ registrar,
|
||||
+ BootstrapContext.class,
|
||||
+ config.cause()
|
||||
+ );
|
||||
+ return Map.copyOf(registrar.tags);
|
||||
+ }
|
||||
+
|
||||
+ public <M, A> Map<ResourceLocation, List<M>> firePostFlattenEvent(
|
||||
+ final Map<ResourceLocation, List<M>> initial,
|
||||
+ final @Nullable TagEventConfig<M, A> config
|
||||
+ ) {
|
||||
+ if (config == null || config.postFlatten() == null || !config.postFlatten().hasHandlers()) {
|
||||
+ return initial;
|
||||
+ }
|
||||
+ final PaperPostFlattenTagRegistrar<M, A> registrar = new PaperPostFlattenTagRegistrar<>(initial, config);
|
||||
+ LifecycleEventRunner.INSTANCE.callReloadableRegistrarEvent(
|
||||
+ config.postFlatten(),
|
||||
+ registrar,
|
||||
+ BootstrapContext.class,
|
||||
+ config.cause()
|
||||
+ );
|
||||
+ return Map.copyOf(registrar.tags);
|
||||
+ }
|
||||
+
|
||||
+ public <M, B> @Nullable TagEventConfig<Holder<M>, B> createEventConfig(final Registry<M> registry, final ReloadableRegistrarEvent.Cause cause) {
|
||||
+ if (PaperRegistries.getEntry(registry.key()) == null) {
|
||||
+ // TODO probably should be able to modify every registry
|
||||
+ return null;
|
||||
+ }
|
||||
+ final RegistryKey<B> registryKey = PaperRegistries.registryFromNms(registry.key());
|
||||
+ @Nullable AbstractLifecycleEventType<BootstrapContext, ReloadableRegistrarEvent<PreFlattenTagRegistrar<B>>, ?> preFlatten = null;
|
||||
+ if (this.preFlatten.hasHandlers(registryKey)) {
|
||||
+ preFlatten = (AbstractLifecycleEventType<BootstrapContext, ReloadableRegistrarEvent<PreFlattenTagRegistrar<B>>, ?>) this.preFlatten.<B, ReloadableRegistrarEvent<PreFlattenTagRegistrar<B>>>getEventType(registryKey);
|
||||
+ }
|
||||
+ @Nullable AbstractLifecycleEventType<BootstrapContext, ReloadableRegistrarEvent<PostFlattenTagRegistrar<B>>, ?> postFlatten = null;
|
||||
+ if (this.postFlatten.hasHandlers(registryKey)) {
|
||||
+ postFlatten = (AbstractLifecycleEventType<BootstrapContext, ReloadableRegistrarEvent<PostFlattenTagRegistrar<B>>, ?>) this.postFlatten.<B, ReloadableRegistrarEvent<PostFlattenTagRegistrar<B>>>getEventType(registryKey);
|
||||
+ }
|
||||
+ return new TagEventConfig<>(
|
||||
+ preFlatten,
|
||||
+ postFlatten,
|
||||
+ cause,
|
||||
+ registry::get,
|
||||
+ h -> ((Holder.Reference<M>) h).key().location(),
|
||||
+ PaperRegistries.registryFromNms(registry.key())
|
||||
+ );
|
||||
+ }
|
||||
+
|
||||
+ public <T> PrioritizableLifecycleEventType.Simple<BootstrapContext, ReloadableRegistrarEvent<PreFlattenTagRegistrar<T>>> getPreFlattenType(final RegistryKey<T> registryKey) {
|
||||
+ return this.preFlatten.getOrCreate(registryKey, (ignored, name) -> {
|
||||
+ return new PrioritizableLifecycleEventType.Simple<>(name, BootstrapContext.class);
|
||||
+ });
|
||||
+ }
|
||||
+
|
||||
+ public <T> PrioritizableLifecycleEventType.Simple<BootstrapContext, ReloadableRegistrarEvent<PostFlattenTagRegistrar<T>>> getPostFlattenType(final RegistryKey<T> registryKey) {
|
||||
+ return this.postFlatten.getOrCreate(registryKey, (ignored, name) -> {
|
||||
+ return new PrioritizableLifecycleEventType.Simple<>(name, BootstrapContext.class);
|
||||
+ });
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/io/papermc/paper/tag/TagEventConfig.java b/src/main/java/io/papermc/paper/tag/TagEventConfig.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/tag/TagEventConfig.java
|
||||
@@ -0,0 +0,0 @@
|
||||
+package io.papermc.paper.tag;
|
||||
+
|
||||
+import io.papermc.paper.plugin.bootstrap.BootstrapContext;
|
||||
+import io.papermc.paper.plugin.lifecycle.event.registrar.ReloadableRegistrarEvent;
|
||||
+import io.papermc.paper.plugin.lifecycle.event.types.AbstractLifecycleEventType;
|
||||
+import io.papermc.paper.registry.RegistryKey;
|
||||
+import java.util.Optional;
|
||||
+import java.util.function.Function;
|
||||
+import net.minecraft.resources.ResourceLocation;
|
||||
+import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
+import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
+import org.checkerframework.framework.qual.DefaultQualifier;
|
||||
+
|
||||
+@DefaultQualifier(NonNull.class)
|
||||
+public record TagEventConfig<M, A>(
|
||||
+ @Nullable AbstractLifecycleEventType<BootstrapContext, ? extends ReloadableRegistrarEvent<PreFlattenTagRegistrar<A>>, ?> preFlatten,
|
||||
+ @Nullable AbstractLifecycleEventType<BootstrapContext, ? extends ReloadableRegistrarEvent<PostFlattenTagRegistrar<A>>, ?> postFlatten,
|
||||
+ ReloadableRegistrarEvent.Cause cause,
|
||||
+ Function<ResourceLocation, Optional<? extends M>> fromIdConverter,
|
||||
+ Function<M, ResourceLocation> toIdConverter,
|
||||
+ RegistryKey<A> apiRegistryKey
|
||||
+) {
|
||||
+}
|
||||
diff --git a/src/main/java/net/minecraft/resources/RegistryDataLoader.java b/src/main/java/net/minecraft/resources/RegistryDataLoader.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/resources/RegistryDataLoader.java
|
||||
+++ b/src/main/java/net/minecraft/resources/RegistryDataLoader.java
|
||||
@@ -0,0 +0,0 @@ public class RegistryDataLoader {
|
||||
}
|
||||
|
||||
io.papermc.paper.registry.PaperRegistryListenerManager.INSTANCE.runFreezeListeners(registry.key(), conversions); // Paper - run pre-freeze listeners
|
||||
- TagLoader.loadTagsForRegistry(resourceManager, registry);
|
||||
+ TagLoader.loadTagsForRegistry(resourceManager, registry, io.papermc.paper.plugin.lifecycle.event.registrar.ReloadableRegistrarEvent.Cause.INITIAL); // Paper - tag lifecycle - add cause
|
||||
}
|
||||
|
||||
static <E> void loadContentsFromNetwork(
|
||||
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
return stream.<Pack>map(resourcepackrepository::getPack).filter(Objects::nonNull).map(Pack::open).collect(ImmutableList.toImmutableList()); // CraftBukkit - decompile error // Paper - decompile error // todo: is this needed anymore?
|
||||
}, this).thenCompose((immutablelist) -> {
|
||||
MultiPackResourceManager resourcemanager = new MultiPackResourceManager(PackType.SERVER_DATA, immutablelist);
|
||||
- List<Registry.PendingTags<?>> list = TagLoader.loadTagsForExistingRegistries(resourcemanager, this.registries.compositeAccess());
|
||||
+ List<Registry.PendingTags<?>> list = TagLoader.loadTagsForExistingRegistries(resourcemanager, this.registries.compositeAccess(), io.papermc.paper.plugin.lifecycle.event.registrar.ReloadableRegistrarEvent.Cause.RELOAD); // Paper - tag lifecycle - add cause
|
||||
|
||||
return ReloadableServerResources.loadResources(resourcemanager, this.registries, list, this.worldData.enabledFeatures(), this.isDedicatedServer() ? Commands.CommandSelection.DEDICATED : Commands.CommandSelection.INTEGRATED, this.getFunctionCompilationLevel(), this.executor, this).whenComplete((datapackresources, throwable) -> {
|
||||
if (throwable != null) {
|
||||
diff --git a/src/main/java/net/minecraft/server/ReloadableServerRegistries.java b/src/main/java/net/minecraft/server/ReloadableServerRegistries.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/server/ReloadableServerRegistries.java
|
||||
+++ b/src/main/java/net/minecraft/server/ReloadableServerRegistries.java
|
||||
@@ -0,0 +0,0 @@ public class ReloadableServerRegistries {
|
||||
String string = Registries.elementsDirPath(type.registryKey());
|
||||
SimpleJsonResourceReloadListener.scanDirectory(resourceManager, string, ops, type.codec(), map);
|
||||
map.forEach((id, value) -> io.papermc.paper.registry.PaperRegistryListenerManager.INSTANCE.registerWithListeners(writableRegistry, ResourceKey.create(type.registryKey(), id), value, DEFAULT_REGISTRATION_INFO, conversions)); // Paper - register with listeners
|
||||
- TagLoader.loadTagsForRegistry(resourceManager, writableRegistry);
|
||||
+ TagLoader.loadTagsForRegistry(resourceManager, writableRegistry, io.papermc.paper.plugin.lifecycle.event.registrar.ReloadableRegistrarEvent.Cause.RELOAD); // Paper - tag life cycle - reload
|
||||
return writableRegistry;
|
||||
}, prepareExecutor);
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/server/ServerFunctionLibrary.java b/src/main/java/net/minecraft/server/ServerFunctionLibrary.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/server/ServerFunctionLibrary.java
|
||||
+++ b/src/main/java/net/minecraft/server/ServerFunctionLibrary.java
|
||||
@@ -0,0 +0,0 @@ public class ServerFunctionLibrary implements PreparableReloadListener {
|
||||
return null;
|
||||
}).join());
|
||||
this.functions = builder.build();
|
||||
- this.tags = this.tagsLoader.build((Map<ResourceLocation, List<TagLoader.EntryWithSource>>)intermediate.getFirst());
|
||||
+ this.tags = this.tagsLoader.build((Map<ResourceLocation, List<TagLoader.EntryWithSource>>)intermediate.getFirst(), null); // Paper - command function tags are not implemented yet
|
||||
},
|
||||
applyExecutor
|
||||
);
|
||||
diff --git a/src/main/java/net/minecraft/server/WorldLoader.java b/src/main/java/net/minecraft/server/WorldLoader.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/server/WorldLoader.java
|
||||
+++ b/src/main/java/net/minecraft/server/WorldLoader.java
|
||||
@@ -0,0 +0,0 @@ public class WorldLoader {
|
||||
CloseableResourceManager closeableResourceManager = pair.getSecond();
|
||||
LayeredRegistryAccess<RegistryLayer> layeredRegistryAccess = RegistryLayer.createRegistryAccess();
|
||||
List<Registry.PendingTags<?>> list = TagLoader.loadTagsForExistingRegistries(
|
||||
- closeableResourceManager, layeredRegistryAccess.getLayer(RegistryLayer.STATIC)
|
||||
+ closeableResourceManager, layeredRegistryAccess.getLayer(RegistryLayer.STATIC), io.papermc.paper.plugin.lifecycle.event.registrar.ReloadableRegistrarEvent.Cause.INITIAL // Paper - tag lifecycle - add cause
|
||||
);
|
||||
RegistryAccess.Frozen frozen = layeredRegistryAccess.getAccessForLoading(RegistryLayer.WORLDGEN);
|
||||
List<HolderLookup.RegistryLookup<?>> list2 = TagLoader.buildUpdatedLookups(frozen, list);
|
||||
diff --git a/src/main/java/net/minecraft/tags/TagLoader.java b/src/main/java/net/minecraft/tags/TagLoader.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/tags/TagLoader.java
|
||||
+++ b/src/main/java/net/minecraft/tags/TagLoader.java
|
||||
@@ -0,0 +0,0 @@ public class TagLoader<T> {
|
||||
return list.isEmpty() ? Either.right(List.copyOf(sequencedSet)) : Either.left(list);
|
||||
}
|
||||
|
||||
- public Map<ResourceLocation, List<T>> build(Map<ResourceLocation, List<TagLoader.EntryWithSource>> tags) {
|
||||
+ // Paper start - fire tag registrar events
|
||||
+ public Map<ResourceLocation, List<T>> build(Map<ResourceLocation, List<TagLoader.EntryWithSource>> tags, @Nullable io.papermc.paper.tag.TagEventConfig<T, ?> eventConfig) {
|
||||
+ tags = io.papermc.paper.tag.PaperTagListenerManager.INSTANCE.firePreFlattenEvent(tags, eventConfig);
|
||||
+ // Paper end - fire tag registrar event
|
||||
final Map<ResourceLocation, List<T>> map = new HashMap<>();
|
||||
TagEntry.Lookup<T> lookup = new TagEntry.Lookup<T>() {
|
||||
@Nullable
|
||||
@@ -0,0 +0,0 @@ public class TagLoader<T> {
|
||||
)
|
||||
.ifRight(values -> map.put(id, (List<T>)values))
|
||||
);
|
||||
- return map;
|
||||
+ return io.papermc.paper.tag.PaperTagListenerManager.INSTANCE.firePostFlattenEvent(map, eventConfig); // Paper - fire tag registrar events
|
||||
}
|
||||
|
||||
public static <T> void loadTagsFromNetwork(TagNetworkSerialization.NetworkPayload tags, WritableRegistry<T> registry) {
|
||||
@@ -0,0 +0,0 @@ public class TagLoader<T> {
|
||||
}
|
||||
|
||||
public static List<Registry.PendingTags<?>> loadTagsForExistingRegistries(ResourceManager resourceManager, RegistryAccess registryManager) {
|
||||
+ // Paper start - tag lifecycle - add cause
|
||||
+ return loadTagsForExistingRegistries(resourceManager, registryManager, io.papermc.paper.plugin.lifecycle.event.registrar.ReloadableRegistrarEvent.Cause.INITIAL);
|
||||
+ }
|
||||
+ public static List<Registry.PendingTags<?>> loadTagsForExistingRegistries(ResourceManager resourceManager, RegistryAccess registryManager, io.papermc.paper.plugin.lifecycle.event.registrar.ReloadableRegistrarEvent.Cause cause) {
|
||||
+ // Paper end - tag lifecycle - add cause
|
||||
return registryManager.registries()
|
||||
- .map(registry -> loadPendingTags(resourceManager, registry.value()))
|
||||
+ .map(registry -> loadPendingTags(resourceManager, registry.value(), cause)) // Paper - tag lifecycle - add cause
|
||||
.flatMap(Optional::stream)
|
||||
.collect(Collectors.toUnmodifiableList());
|
||||
}
|
||||
|
||||
public static <T> void loadTagsForRegistry(ResourceManager resourceManager, WritableRegistry<T> registry) {
|
||||
+ // Paper start - tag lifecycle - add registrar event cause
|
||||
+ loadTagsForRegistry(resourceManager, registry, io.papermc.paper.plugin.lifecycle.event.registrar.ReloadableRegistrarEvent.Cause.INITIAL);
|
||||
+ }
|
||||
+ public static <T> void loadTagsForRegistry(ResourceManager resourceManager, WritableRegistry<T> registry, io.papermc.paper.plugin.lifecycle.event.registrar.ReloadableRegistrarEvent.Cause cause) {
|
||||
+ // Paper end - tag lifecycle - add registrar event cause
|
||||
ResourceKey<? extends Registry<T>> resourceKey = registry.key();
|
||||
TagLoader<Holder<T>> tagLoader = new TagLoader<>(TagLoader.ElementLookup.fromWritableRegistry(registry), Registries.tagsDirPath(resourceKey));
|
||||
- tagLoader.build(tagLoader.load(resourceManager)).forEach((id, entries) -> registry.bindTag(TagKey.create(resourceKey, id), (List<Holder<T>>)entries));
|
||||
+ tagLoader.build(tagLoader.load(resourceManager), io.papermc.paper.tag.PaperTagListenerManager.INSTANCE.createEventConfig(registry, cause)).forEach((id, entries) -> registry.bindTag(TagKey.create(resourceKey, id), (List<Holder<T>>)entries)); // Paper - tag lifecycle - add registrar event cause
|
||||
}
|
||||
|
||||
private static <T> Map<TagKey<T>, List<Holder<T>>> wrapTags(ResourceKey<? extends Registry<T>> registryRef, Map<ResourceLocation, List<Holder<T>>> tags) {
|
||||
return tags.entrySet().stream().collect(Collectors.toUnmodifiableMap(entry -> TagKey.create(registryRef, entry.getKey()), Entry::getValue));
|
||||
}
|
||||
|
||||
- private static <T> Optional<Registry.PendingTags<T>> loadPendingTags(ResourceManager resourceManager, Registry<T> registry) {
|
||||
+ private static <T> Optional<Registry.PendingTags<T>> loadPendingTags(ResourceManager resourceManager, Registry<T> registry, io.papermc.paper.plugin.lifecycle.event.registrar.ReloadableRegistrarEvent.Cause cause) { // Paper - add registrar event cause
|
||||
ResourceKey<? extends Registry<T>> resourceKey = registry.key();
|
||||
TagLoader<Holder<T>> tagLoader = new TagLoader<>(
|
||||
(TagLoader.ElementLookup<Holder<T>>)TagLoader.ElementLookup.fromFrozenRegistry(registry), Registries.tagsDirPath(resourceKey)
|
||||
);
|
||||
- TagLoader.LoadResult<T> loadResult = new TagLoader.LoadResult<>(resourceKey, wrapTags(registry.key(), tagLoader.build(tagLoader.load(resourceManager))));
|
||||
+ TagLoader.LoadResult<T> loadResult = new TagLoader.LoadResult<>(resourceKey, wrapTags(registry.key(), tagLoader.build(tagLoader.load(resourceManager), io.papermc.paper.tag.PaperTagListenerManager.INSTANCE.createEventConfig(registry, cause)))); // Paper - add registrar event cause
|
||||
return loadResult.tags().isEmpty() ? Optional.empty() : Optional.of(registry.prepareTagReload(loadResult));
|
||||
}
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: strnq <dev@aruus.uk>
|
||||
Date: Sat, 14 Sep 2024 12:53:13 +0300
|
||||
Subject: [PATCH] Validate slot in PlayerInventory#setSlot
|
||||
|
||||
The CraftPlayerInventory implementation sends a container_set_slot
|
||||
packet to the client which will error if an invalid slot is passed to
|
||||
the setSlot method, making a validation necessary over simply silently
|
||||
ignoring invalid slot values.
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryPlayer.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryPlayer.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryPlayer.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryPlayer.java
|
||||
@@ -0,0 +0,0 @@ public class CraftInventoryPlayer extends CraftInventory implements org.bukkit.i
|
||||
|
||||
@Override
|
||||
public void setItem(int index, ItemStack item) {
|
||||
+ // Paper start - Validate setItem index
|
||||
+ if (index < 0 || index > 40) {
|
||||
+ throw new ArrayIndexOutOfBoundsException("Index must be between 0 and 40");
|
||||
+ }
|
||||
+ // Paper end - Validate setItem index
|
||||
super.setItem(index, item);
|
||||
if (this.getHolder() == null) return;
|
||||
ServerPlayer player = ((CraftPlayer) this.getHolder()).getHandle();
|
||||
@@ -1,93 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Axionize <154778082+Axionize@users.noreply.github.com>
|
||||
Date: Sun, 29 Sep 2024 14:20:42 -0700
|
||||
Subject: [PATCH] Void damage configuration API
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
@@ -0,0 +0,0 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
|
||||
}
|
||||
|
||||
public void checkBelowWorld() {
|
||||
+ if (!this.level.getWorld().isVoidDamageEnabled()) return; // Paper - check if void damage is enabled on the world
|
||||
// Paper start - Configurable nether ceiling damage
|
||||
- if (this.getY() < (double) (this.level.getMinY() - 64) || (this.level.getWorld().getEnvironment() == org.bukkit.World.Environment.NETHER
|
||||
+ if (this.getY() < (double) (this.level.getMinY() + this.level.getWorld().getVoidDamageMinBuildHeightOffset()) || (this.level.getWorld().getEnvironment() == org.bukkit.World.Environment.NETHER // Paper - use configured min build height offset
|
||||
&& this.level.paperConfig().environment.netherCeilingVoidDamageHeight.test(v -> this.getY() >= v)
|
||||
&& (!(this instanceof Player player) || !player.getAbilities().invulnerable))) {
|
||||
// Paper end - Configurable nether ceiling damage
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity implements Attackable {
|
||||
|
||||
@Override
|
||||
protected void onBelowWorld() {
|
||||
- this.hurt(this.damageSources().fellOutOfWorld(), 4.0F);
|
||||
+ this.hurt(this.damageSources().fellOutOfWorld(), this.level().getWorld().getVoidDamageAmount()); // Paper - use configured void damage amount
|
||||
}
|
||||
|
||||
protected void updateSwingTime() {
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
||||
@@ -0,0 +0,0 @@ public class CraftWorld extends CraftRegionAccessor implements World {
|
||||
private final Object2IntOpenHashMap<SpawnCategory> spawnCategoryLimit = new Object2IntOpenHashMap<>();
|
||||
private final CraftPersistentDataContainer persistentDataContainer = new CraftPersistentDataContainer(CraftWorld.DATA_TYPE_REGISTRY);
|
||||
private net.kyori.adventure.pointer.Pointers adventure$pointers; // Paper - implement pointers
|
||||
+ // Paper start - void damage configuration
|
||||
+ private boolean voidDamageEnabled;
|
||||
+ private float voidDamageAmount;
|
||||
+ private double voidDamageMinBuildHeightOffset;
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean isVoidDamageEnabled() {
|
||||
+ return this.voidDamageEnabled;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setVoidDamageEnabled(final boolean enabled) {
|
||||
+ this.voidDamageEnabled = enabled;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public float getVoidDamageAmount() {
|
||||
+ return this.voidDamageAmount;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setVoidDamageAmount(float voidDamageAmount) {
|
||||
+ this.voidDamageAmount = voidDamageAmount;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public double getVoidDamageMinBuildHeightOffset() {
|
||||
+ return this.voidDamageMinBuildHeightOffset;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setVoidDamageMinBuildHeightOffset(double minBuildHeightOffset) {
|
||||
+ this.voidDamageMinBuildHeightOffset = minBuildHeightOffset;
|
||||
+ }
|
||||
+ // Paper end - void damage configuration
|
||||
|
||||
// Paper start - Provide fast information methods
|
||||
@Override
|
||||
@@ -0,0 +0,0 @@ public class CraftWorld extends CraftRegionAccessor implements World {
|
||||
}
|
||||
}
|
||||
// Paper end - per world spawn limits
|
||||
+
|
||||
+ // Paper start - per world void damage height
|
||||
+ this.voidDamageEnabled = this.world.paperConfig().environment.voidDamageAmount.enabled();
|
||||
+ this.voidDamageMinBuildHeightOffset = this.world.paperConfig().environment.voidDamageMinBuildHeightOffset;
|
||||
+ this.voidDamageAmount = (float) this.world.paperConfig().environment.voidDamageAmount.or(0);
|
||||
+ // Paper end - per world void damage height
|
||||
}
|
||||
|
||||
@Override
|
||||
Reference in New Issue
Block a user