963
This commit is contained in:
parent
b2375286c9
commit
fc05430719
20 changed files with 260 additions and 325 deletions
2100
patches/server/0954-General-ItemMeta-fixes.patch
Normal file
2100
patches/server/0954-General-ItemMeta-fixes.patch
Normal file
File diff suppressed because it is too large
Load diff
73
patches/server/0955-More-Chest-Block-API.patch
Normal file
73
patches/server/0955-More-Chest-Block-API.patch
Normal file
|
@ -0,0 +1,73 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: SoSeDiK <mrsosedik@gmail.com>
|
||||
Date: Wed, 1 May 2024 08:22:13 +0300
|
||||
Subject: [PATCH] More Chest Block API
|
||||
|
||||
== AT ==
|
||||
public net.minecraft.world.level.block.ChestBlock isBlockedChestByBlock(Lnet/minecraft/world/level/BlockGetter;Lnet/minecraft/core/BlockPos;)Z
|
||||
|
||||
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 b376f7d3b632d6aaea5c4d93382238074559d56a..ef0d469176ee74b6bb5f9e9cc508735145fda5b8 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/EnderChestBlock.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/EnderChestBlock.java
|
||||
@@ -83,7 +83,7 @@ public class EnderChestBlock extends AbstractChestBlock<EnderChestBlockEntity> i
|
||||
PlayerEnderChestContainer playerEnderChestContainer = player.getEnderChestInventory();
|
||||
if (playerEnderChestContainer != null && world.getBlockEntity(pos) instanceof EnderChestBlockEntity enderChestBlockEntity) {
|
||||
BlockPos blockPos = pos.above();
|
||||
- if (world.getBlockState(blockPos).isRedstoneConductor(world, blockPos)) {
|
||||
+ 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) {
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java b/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java
|
||||
index 6e98a00d526b734992ce39b15768c5820dce4ca8..cc7bf4d39b834fba472bc163226a01a0cd4b6010 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftChest.java
|
||||
@@ -99,4 +99,29 @@ public class CraftChest extends CraftLootable<ChestBlockEntity> implements Chest
|
||||
return getTileEntity().openersCounter.opened;
|
||||
}
|
||||
// Paper end - More Lidded Block API
|
||||
+
|
||||
+ // Paper start - More Chest Block API
|
||||
+ @Override
|
||||
+ public boolean isBlocked() {
|
||||
+ // Method mimics vanilla logic in ChestBlock and DoubleBlockCombiner when trying to open chest's container
|
||||
+ if (!isPlaced()) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ net.minecraft.world.level.LevelAccessor world = getWorldHandle();
|
||||
+ if (ChestBlock.isChestBlockedAt(world, getPosition())) {
|
||||
+ return true;
|
||||
+ }
|
||||
+ if (ChestBlock.getBlockType(this.data) == net.minecraft.world.level.block.DoubleBlockCombiner.BlockType.SINGLE) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ net.minecraft.core.Direction direction = ChestBlock.getConnectedDirection(this.data);
|
||||
+ net.minecraft.core.BlockPos neighbourBlockPos = getPosition().relative(direction);
|
||||
+ BlockState neighbourBlockState = world.getBlockStateIfLoaded(neighbourBlockPos);
|
||||
+ return neighbourBlockState != null
|
||||
+ && neighbourBlockState.is(this.data.getBlock())
|
||||
+ && ChestBlock.getBlockType(neighbourBlockState) != net.minecraft.world.level.block.DoubleBlockCombiner.BlockType.SINGLE
|
||||
+ && ChestBlock.getConnectedDirection(neighbourBlockState) == direction.getOpposite()
|
||||
+ && ChestBlock.isChestBlockedAt(world, neighbourBlockPos);
|
||||
+ }
|
||||
+ // Paper end - More Chest Block API
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftEnderChest.java b/src/main/java/org/bukkit/craftbukkit/block/CraftEnderChest.java
|
||||
index b64adbba3e52d32d439e64a243cb74f3fbca2ce3..f45ee675a10729845bf376fa95e648b23b9aac12 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftEnderChest.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftEnderChest.java
|
||||
@@ -58,4 +58,13 @@ public class CraftEnderChest extends CraftBlockEntityState<EnderChestBlockEntity
|
||||
return getTileEntity().openersCounter.opened;
|
||||
}
|
||||
// Paper end - More Lidded Block API
|
||||
+
|
||||
+ // Paper start - More Chest Block API
|
||||
+ @Override
|
||||
+ public boolean isBlocked() {
|
||||
+ // Uses the same logic as EnderChestBlock's check for opening container
|
||||
+ final net.minecraft.core.BlockPos abovePos = this.getPosition().above();
|
||||
+ return this.isPlaced() && this.getWorldHandle().getBlockState(abovePos).isRedstoneConductor(this.getWorldHandle(), abovePos);
|
||||
+ }
|
||||
+ // Paper end - More Chest Block API
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Nassim Jahnke <nassim@njahnke.dev>
|
||||
Date: Thu, 9 May 2024 15:11:34 +0200
|
||||
Subject: [PATCH] Print data component type on encoding error
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/core/component/DataComponentPatch.java b/src/main/java/net/minecraft/core/component/DataComponentPatch.java
|
||||
index 9de958d769a52a8df794988781f8601a4e6a73a4..9dec1c74d10f82636b7176e8f725b8acd1b52e4f 100644
|
||||
--- a/src/main/java/net/minecraft/core/component/DataComponentPatch.java
|
||||
+++ b/src/main/java/net/minecraft/core/component/DataComponentPatch.java
|
||||
@@ -144,7 +144,13 @@ public final class DataComponentPatch {
|
||||
}
|
||||
|
||||
private static <T> void encodeComponent(RegistryFriendlyByteBuf buf, DataComponentType<T> type, Object value) {
|
||||
+ // Paper start - codec errors of random anonymous classes are useless
|
||||
+ try {
|
||||
type.streamCodec().encode(buf, (T) value); // CraftBukkit - decompile error
|
||||
+ } catch (final Exception e) {
|
||||
+ throw new RuntimeException("Error encoding component " + type, e);
|
||||
+ }
|
||||
+ // Paper end - codec errors of random anonymous classes are useless
|
||||
}
|
||||
};
|
||||
private static final String REMOVED_PREFIX = "!";
|
2831
patches/server/0957-Brigadier-based-command-API.patch
Normal file
2831
patches/server/0957-Brigadier-based-command-API.patch
Normal file
File diff suppressed because it is too large
Load diff
94
patches/server/0958-Fix-issues-with-Recipe-API.patch
Normal file
94
patches/server/0958-Fix-issues-with-Recipe-API.patch
Normal file
|
@ -0,0 +1,94 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
Date: Sun, 12 May 2024 15:49:36 -0700
|
||||
Subject: [PATCH] Fix issues with Recipe API
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/item/crafting/ShapedRecipe.java b/src/main/java/net/minecraft/world/item/crafting/ShapedRecipe.java
|
||||
index dd02af6574dd97404bc9c02c9ead84e1dd537efe..980fea65899ef5f37808506b822fd3de5830d2c7 100644
|
||||
--- a/src/main/java/net/minecraft/world/item/crafting/ShapedRecipe.java
|
||||
+++ b/src/main/java/net/minecraft/world/item/crafting/ShapedRecipe.java
|
||||
@@ -98,7 +98,7 @@ public class ShapedRecipe implements CraftingRecipe {
|
||||
char c = 'a';
|
||||
for (Optional<Ingredient> list : this.pattern.ingredients()) {
|
||||
RecipeChoice choice = CraftRecipe.toBukkit(list);
|
||||
- if (choice != null) {
|
||||
+ if (choice != RecipeChoice.empty()) { // Paper
|
||||
recipe.setIngredient(c, choice);
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftRecipe.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftRecipe.java
|
||||
index a68e036a12b354c4f04b6596dfb9cd6e7663718b..d8af6522f7516de93e33cb9da8490f5ec14e7553 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftRecipe.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftRecipe.java
|
||||
@@ -38,6 +38,10 @@ public interface CraftRecipe extends Recipe {
|
||||
stack = Ingredient.of(((RecipeChoice.MaterialChoice) bukkit).getChoices().stream().map((mat) -> CraftItemType.bukkitToMinecraft(mat)));
|
||||
} else if (bukkit instanceof RecipeChoice.ExactChoice) {
|
||||
stack = Ingredient.ofStacks(((RecipeChoice.ExactChoice) bukkit).getChoices().stream().map((mat) -> CraftItemStack.asNMSCopy(mat)));
|
||||
+ // Paper start - support "empty" choices
|
||||
+ } else if (bukkit == RecipeChoice.empty()) {
|
||||
+ stack = Ingredient.of();
|
||||
+ // Paper end
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unknown recipe stack instance " + bukkit);
|
||||
}
|
||||
@@ -58,7 +62,7 @@ public interface CraftRecipe extends Recipe {
|
||||
List<Holder<Item>> items = list.items();
|
||||
|
||||
if (items.isEmpty()) {
|
||||
- return null;
|
||||
+ return RecipeChoice.empty(); // Paper - null breaks API contracts
|
||||
}
|
||||
|
||||
if (list.isExact()) {
|
||||
diff --git a/src/test/java/io/papermc/paper/inventory/recipe/TestRecipeChoice.java b/src/test/java/io/papermc/paper/inventory/recipe/TestRecipeChoice.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..45ab2b6d32b29cb663df848534e1aa68293dd613
|
||||
--- /dev/null
|
||||
+++ b/src/test/java/io/papermc/paper/inventory/recipe/TestRecipeChoice.java
|
||||
@@ -0,0 +1,25 @@
|
||||
+package io.papermc.paper.inventory.recipe;
|
||||
+
|
||||
+import java.util.Iterator;
|
||||
+import org.bukkit.Bukkit;
|
||||
+import org.bukkit.inventory.Recipe;
|
||||
+import org.bukkit.support.environment.AllFeatures;
|
||||
+import org.junit.jupiter.api.Test;
|
||||
+
|
||||
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
||||
+import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
+
|
||||
+@AllFeatures
|
||||
+class TestRecipeChoice {
|
||||
+
|
||||
+ @Test
|
||||
+ void testRecipeChoices() {
|
||||
+ final Iterator<Recipe> iter = Bukkit.recipeIterator();
|
||||
+ boolean foundRecipes = false;
|
||||
+ while (iter.hasNext()) {
|
||||
+ foundRecipes = true;
|
||||
+ assertDoesNotThrow(iter::next, "Failed to convert a recipe to Bukkit recipe!");
|
||||
+ }
|
||||
+ assertTrue(foundRecipes, "No recipes found!");
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/test/java/org/bukkit/support/DummyServerHelper.java b/src/test/java/org/bukkit/support/DummyServerHelper.java
|
||||
index 55c05c16a80c489cdda2fd03c943921d38d978e9..6855816ec5fd232b53622c316e45b3c081297085 100644
|
||||
--- a/src/test/java/org/bukkit/support/DummyServerHelper.java
|
||||
+++ b/src/test/java/org/bukkit/support/DummyServerHelper.java
|
||||
@@ -92,6 +92,15 @@ public final class DummyServerHelper {
|
||||
// Paper end - testing additions
|
||||
|
||||
io.papermc.paper.configuration.GlobalConfigTestingBase.setupGlobalConfigForTest(); // Paper - configuration files - setup global configuration test base
|
||||
+
|
||||
+ // Paper start - add test for recipe conversion
|
||||
+ when(instance.recipeIterator()).thenAnswer(ignored ->
|
||||
+ com.google.common.collect.Iterators.transform(
|
||||
+ RegistryHelper.getDataPack().getRecipeManager().byType.entries().iterator(),
|
||||
+ input -> input.getValue().toBukkitRecipe()
|
||||
+ )
|
||||
+ );
|
||||
+ // Paper end - add test for recipe conversion
|
||||
return instance;
|
||||
}
|
||||
}
|
136
patches/server/0959-Fix-equipment-slot-and-group-API.patch
Normal file
136
patches/server/0959-Fix-equipment-slot-and-group-API.patch
Normal file
|
@ -0,0 +1,136 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
Date: Wed, 22 May 2024 10:01:19 -0700
|
||||
Subject: [PATCH] Fix equipment slot and group API
|
||||
|
||||
Adds the following:
|
||||
- Add test for EquipmentSlotGroup
|
||||
- Expose LivingEntity#canUseSlot
|
||||
|
||||
Co-authored-by: SoSeDiK <mrsosedik@gmail.com>
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
|
||||
index a62d17b72c675120b447e625cb3dc437681bdf20..f16067b674118a47735ad22797988d50b4415040 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java
|
||||
@@ -1230,4 +1230,11 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity {
|
||||
this.getHandle().setYBodyRot(bodyYaw);
|
||||
}
|
||||
// Paper end - body yaw API
|
||||
+
|
||||
+ // Paper start - Expose canUseSlot
|
||||
+ @Override
|
||||
+ public boolean canUseEquipmentSlot(org.bukkit.inventory.EquipmentSlot slot) {
|
||||
+ return this.getHandle().canUseSlot(org.bukkit.craftbukkit.CraftEquipmentSlot.getNMS(slot));
|
||||
+ }
|
||||
+ // Paper end - Expose canUseSlot
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryPlayer.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryPlayer.java
|
||||
index 46d0b324498510c73a8439611f44269edee62313..69982103d8ea31e9b83b18c4c03a7b021bb983b9 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryPlayer.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryPlayer.java
|
||||
@@ -135,6 +135,10 @@ public class CraftInventoryPlayer extends CraftInventory implements org.bukkit.i
|
||||
case HEAD:
|
||||
this.setHelmet(item);
|
||||
break;
|
||||
+ // Paper start
|
||||
+ case BODY:
|
||||
+ throw new IllegalArgumentException("BODY is not valid for players!");
|
||||
+ // Paper end
|
||||
default:
|
||||
throw new IllegalArgumentException("Not implemented. This is a bug");
|
||||
}
|
||||
@@ -162,6 +166,10 @@ public class CraftInventoryPlayer extends CraftInventory implements org.bukkit.i
|
||||
return java.util.Objects.requireNonNullElseGet(this.getChestplate(), () -> new ItemStack(org.bukkit.Material.AIR)); // Paper - make nonnull
|
||||
case HEAD:
|
||||
return java.util.Objects.requireNonNullElseGet(this.getHelmet(), () -> new ItemStack(org.bukkit.Material.AIR)); // Paper - make nonnull
|
||||
+ // Paper start
|
||||
+ case BODY:
|
||||
+ throw new IllegalArgumentException("BODY is not valid for players!");
|
||||
+ // Paper end
|
||||
default:
|
||||
throw new IllegalArgumentException("Not implemented. This is a bug");
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java
|
||||
index 63567251d101b5e50ffd7e2825b1411fcb433c8c..450c5aa14b4195eb7123492c7a111ec6f40ce412 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaItem.java
|
||||
@@ -1702,7 +1702,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
|
||||
if (this.attributeModifiers == null) return LinkedHashMultimap.create(); // Paper - don't change the components
|
||||
SetMultimap<Attribute, AttributeModifier> result = LinkedHashMultimap.create();
|
||||
for (Map.Entry<Attribute, AttributeModifier> entry : this.attributeModifiers.entries()) {
|
||||
- if (entry.getValue().getSlot() == null || entry.getValue().getSlot() == slot) {
|
||||
+ if (entry.getValue().getSlotGroup().test(slot)) { // Paper - correctly test slot against group
|
||||
result.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
@@ -1776,9 +1776,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
|
||||
|
||||
while (iter.hasNext()) {
|
||||
Map.Entry<Attribute, AttributeModifier> entry = iter.next();
|
||||
- // Explicitly match against null because (as of MC 1.13) AttributeModifiers without a -
|
||||
- // set slot are active in any slot.
|
||||
- if (entry.getValue().getSlot() == null || entry.getValue().getSlot() == slot) {
|
||||
+ if (entry.getValue().getSlotGroup().test(slot)) { // Paper - correctly test slot against group
|
||||
iter.remove();
|
||||
++removed;
|
||||
}
|
||||
diff --git a/src/test/java/io/papermc/paper/inventory/item/EquipmentSlotGroupTest.java b/src/test/java/io/papermc/paper/inventory/item/EquipmentSlotGroupTest.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..a26dc8f4787276468417196440cb8f73670a56c7
|
||||
--- /dev/null
|
||||
+++ b/src/test/java/io/papermc/paper/inventory/item/EquipmentSlotGroupTest.java
|
||||
@@ -0,0 +1,53 @@
|
||||
+package io.papermc.paper.inventory.item;
|
||||
+
|
||||
+import java.lang.reflect.Field;
|
||||
+import java.lang.reflect.Modifier;
|
||||
+import java.util.ArrayList;
|
||||
+import java.util.List;
|
||||
+import net.minecraft.world.entity.EquipmentSlot;
|
||||
+import org.bukkit.craftbukkit.CraftEquipmentSlot;
|
||||
+import org.bukkit.inventory.EquipmentSlotGroup;
|
||||
+import org.bukkit.support.environment.Normal;
|
||||
+import org.junit.jupiter.params.ParameterizedTest;
|
||||
+import org.junit.jupiter.params.provider.EnumSource;
|
||||
+import org.junit.jupiter.params.provider.MethodSource;
|
||||
+
|
||||
+import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
+import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
+
|
||||
+@Normal
|
||||
+class EquipmentSlotGroupTest {
|
||||
+
|
||||
+ static List<EquipmentSlotGroup> apiValues() throws ReflectiveOperationException {
|
||||
+ final List<EquipmentSlotGroup> apiValues = new ArrayList<>();
|
||||
+ for (final Field field : EquipmentSlotGroup.class.getDeclaredFields()) {
|
||||
+ if (!Modifier.isStatic(field.getModifiers()) || !Modifier.isFinal(field.getModifiers()) || !field.getType().equals(EquipmentSlotGroup.class)) {
|
||||
+ continue;
|
||||
+ }
|
||||
+ apiValues.add((EquipmentSlotGroup) field.get(null));
|
||||
+ }
|
||||
+ if (apiValues.isEmpty()) {
|
||||
+ throw new RuntimeException("Didn't find any api " + EquipmentSlotGroup.class.getSimpleName());
|
||||
+ }
|
||||
+ return apiValues;
|
||||
+ }
|
||||
+
|
||||
+ @ParameterizedTest
|
||||
+ @MethodSource("apiValues")
|
||||
+ void testBukkitToNms(final EquipmentSlotGroup slotGroup) {
|
||||
+ final net.minecraft.world.entity.EquipmentSlotGroup nmsGroup = CraftEquipmentSlot.getNMSGroup(slotGroup);
|
||||
+ assertNotNull(nmsGroup, "No nms slot group found for " + slotGroup);
|
||||
+ assertEquals(nmsGroup.getSerializedName(), slotGroup.toString(), "slot group name mismatch");
|
||||
+ for (final EquipmentSlot slot : EquipmentSlot.values()) {
|
||||
+ assertEquals(nmsGroup.test(slot), slotGroup.test(CraftEquipmentSlot.getSlot(slot)));
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ @ParameterizedTest
|
||||
+ @EnumSource(net.minecraft.world.entity.EquipmentSlotGroup.class)
|
||||
+ void testNmsToBukkit(final net.minecraft.world.entity.EquipmentSlotGroup slotGroup) {
|
||||
+ final EquipmentSlotGroup apiGroup = CraftEquipmentSlot.getSlot(slotGroup);
|
||||
+ assertNotNull(apiGroup, "No api slot group found for " + slotGroup);
|
||||
+ assertEquals(apiGroup.toString(), slotGroup.getSerializedName(), "slot group name mismatch");
|
||||
+ }
|
||||
+}
|
|
@ -0,0 +1,130 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jason Penilla <11360596+jpenilla@users.noreply.github.com>
|
||||
Date: Tue, 21 May 2024 13:18:15 -0700
|
||||
Subject: [PATCH] Allow Bukkit plugin to use Paper PluginLoader API
|
||||
|
||||
|
||||
diff --git a/src/main/java/io/papermc/paper/plugin/loader/PaperClasspathBuilder.java b/src/main/java/io/papermc/paper/plugin/loader/PaperClasspathBuilder.java
|
||||
index f871a329eb52da077f58d0ceaaabd3349f84cad0..21a0a4e29c0eb1b4f7dc89ad3df481ca89dbf1a4 100644
|
||||
--- a/src/main/java/io/papermc/paper/plugin/loader/PaperClasspathBuilder.java
|
||||
+++ b/src/main/java/io/papermc/paper/plugin/loader/PaperClasspathBuilder.java
|
||||
@@ -41,15 +41,7 @@ public class PaperClasspathBuilder implements PluginClasspathBuilder {
|
||||
}
|
||||
|
||||
public PaperPluginClassLoader buildClassLoader(Logger logger, Path source, JarFile jarFile, PaperPluginMeta configuration) {
|
||||
- PaperLibraryStore paperLibraryStore = new PaperLibraryStore();
|
||||
- for (ClassPathLibrary library : this.libraries) {
|
||||
- library.register(paperLibraryStore);
|
||||
- }
|
||||
-
|
||||
- List<Path> paths = paperLibraryStore.getPaths();
|
||||
- if (PluginInitializerManager.instance().pluginRemapper != null) {
|
||||
- paths = PluginInitializerManager.instance().pluginRemapper.remapLibraries(paths);
|
||||
- }
|
||||
+ List<Path> paths = this.buildLibraryPaths(true);
|
||||
URL[] urls = new URL[paths.size()];
|
||||
for (int i = 0; i < paths.size(); i++) {
|
||||
Path path = paths.get(i);
|
||||
@@ -69,4 +61,17 @@ public class PaperClasspathBuilder implements PluginClasspathBuilder {
|
||||
throw new RuntimeException(exception);
|
||||
}
|
||||
}
|
||||
+
|
||||
+ public List<Path> buildLibraryPaths(final boolean remap) {
|
||||
+ PaperLibraryStore paperLibraryStore = new PaperLibraryStore();
|
||||
+ for (ClassPathLibrary library : this.libraries) {
|
||||
+ library.register(paperLibraryStore);
|
||||
+ }
|
||||
+
|
||||
+ List<Path> paths = paperLibraryStore.getPaths();
|
||||
+ if (remap && PluginInitializerManager.instance().pluginRemapper != null) {
|
||||
+ paths = PluginInitializerManager.instance().pluginRemapper.remapLibraries(paths);
|
||||
+ }
|
||||
+ return paths;
|
||||
+ }
|
||||
}
|
||||
diff --git a/src/main/java/io/papermc/paper/plugin/provider/type/spigot/SpigotPluginProvider.java b/src/main/java/io/papermc/paper/plugin/provider/type/spigot/SpigotPluginProvider.java
|
||||
index 75a2b687d58d76b94f8bec111df8613f120ff74b..0fd1040ed376f19c6d5326767baaf3048ce1bfb4 100644
|
||||
--- a/src/main/java/io/papermc/paper/plugin/provider/type/spigot/SpigotPluginProvider.java
|
||||
+++ b/src/main/java/io/papermc/paper/plugin/provider/type/spigot/SpigotPluginProvider.java
|
||||
@@ -40,15 +40,17 @@ public class SpigotPluginProvider implements PluginProvider<JavaPlugin>, Provide
|
||||
private final PluginDescriptionFile description;
|
||||
private final JarFile jarFile;
|
||||
private final Logger logger;
|
||||
+ private final List<Path> paperLibraryPaths;
|
||||
private final ComponentLogger componentLogger;
|
||||
private ProviderStatus status;
|
||||
private DependencyContext dependencyContext;
|
||||
|
||||
- SpigotPluginProvider(Path path, JarFile file, PluginDescriptionFile description) {
|
||||
+ SpigotPluginProvider(Path path, JarFile file, PluginDescriptionFile description, List<Path> paperLibraryPaths) {
|
||||
this.path = path;
|
||||
this.jarFile = file;
|
||||
this.description = description;
|
||||
this.logger = PaperPluginLogger.getLogger(description);
|
||||
+ this.paperLibraryPaths = paperLibraryPaths;
|
||||
this.componentLogger = ComponentLogger.logger(this.logger.getName());
|
||||
}
|
||||
|
||||
@@ -120,7 +122,7 @@ public class SpigotPluginProvider implements PluginProvider<JavaPlugin>, Provide
|
||||
|
||||
final PluginClassLoader loader;
|
||||
try {
|
||||
- loader = new PluginClassLoader(this.getClass().getClassLoader(), this.description, dataFolder, this.path.toFile(), LIBRARY_LOADER.createLoader(this.description), this.jarFile, this.dependencyContext); // Paper
|
||||
+ loader = new PluginClassLoader(this.getClass().getClassLoader(), this.description, dataFolder, this.path.toFile(), LIBRARY_LOADER.createLoader(this.description, this.paperLibraryPaths), this.jarFile, this.dependencyContext); // Paper
|
||||
} catch (InvalidPluginException ex) {
|
||||
throw ex;
|
||||
} catch (Throwable ex) {
|
||||
diff --git a/src/main/java/io/papermc/paper/plugin/provider/type/spigot/SpigotPluginProviderFactory.java b/src/main/java/io/papermc/paper/plugin/provider/type/spigot/SpigotPluginProviderFactory.java
|
||||
index 1bf0fa1530b8e5f94d726d0313b7a00f675b500c..9edf79dffd2836b40d41da4437c18d6145853f89 100644
|
||||
--- a/src/main/java/io/papermc/paper/plugin/provider/type/spigot/SpigotPluginProviderFactory.java
|
||||
+++ b/src/main/java/io/papermc/paper/plugin/provider/type/spigot/SpigotPluginProviderFactory.java
|
||||
@@ -1,9 +1,18 @@
|
||||
package io.papermc.paper.plugin.provider.type.spigot;
|
||||
|
||||
+import com.destroystokyo.paper.utils.PaperPluginLogger;
|
||||
+import io.papermc.paper.plugin.bootstrap.PluginProviderContextImpl;
|
||||
import io.papermc.paper.plugin.entrypoint.classloader.BytecodeModifyingURLClassLoader;
|
||||
+import io.papermc.paper.plugin.entrypoint.classloader.PaperSimplePluginClassLoader;
|
||||
+import io.papermc.paper.plugin.loader.PaperClasspathBuilder;
|
||||
+import io.papermc.paper.plugin.loader.PluginLoader;
|
||||
import io.papermc.paper.plugin.provider.configuration.serializer.constraints.PluginConfigConstraints;
|
||||
import io.papermc.paper.plugin.provider.type.PluginTypeFactory;
|
||||
+import io.papermc.paper.plugin.provider.util.ProviderUtil;
|
||||
import io.papermc.paper.util.MappingEnvironment;
|
||||
+import java.util.List;
|
||||
+import java.util.logging.Logger;
|
||||
+import net.kyori.adventure.text.logger.slf4j.ComponentLogger;
|
||||
import org.bukkit.plugin.InvalidDescriptionException;
|
||||
import org.bukkit.plugin.PluginDescriptionFile;
|
||||
import org.bukkit.plugin.java.LibraryLoader;
|
||||
@@ -36,7 +45,28 @@ class SpigotPluginProviderFactory implements PluginTypeFactory<SpigotPluginProvi
|
||||
throw new InvalidDescriptionException("Restricted name, cannot use 0x20 (space character) in a plugin name.");
|
||||
}
|
||||
|
||||
- return new SpigotPluginProvider(source, file, configuration);
|
||||
+ final List<Path> paperLibraryPaths;
|
||||
+ if (configuration.getPaperPluginLoader() != null) {
|
||||
+ final Logger logger = PaperPluginLogger.getLogger(configuration);
|
||||
+ PaperClasspathBuilder builder = new PaperClasspathBuilder(PluginProviderContextImpl.create(
|
||||
+ configuration, ComponentLogger.logger(logger.getName()), source
|
||||
+ ));
|
||||
+
|
||||
+ try (
|
||||
+ PaperSimplePluginClassLoader simplePluginClassLoader = new PaperSimplePluginClassLoader(source, file, configuration, this.getClass().getClassLoader())
|
||||
+ ) {
|
||||
+ PluginLoader loader = ProviderUtil.loadClass(configuration.getPaperPluginLoader(), PluginLoader.class, simplePluginClassLoader);
|
||||
+ loader.classloader(builder);
|
||||
+ } catch (IOException e) {
|
||||
+ throw new RuntimeException(e);
|
||||
+ }
|
||||
+
|
||||
+ paperLibraryPaths = builder.buildLibraryPaths(false);
|
||||
+ } else {
|
||||
+ paperLibraryPaths = null;
|
||||
+ }
|
||||
+
|
||||
+ return new SpigotPluginProvider(source, file, configuration, paperLibraryPaths);
|
||||
}
|
||||
|
||||
@Override
|
|
@ -0,0 +1,236 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Nassim Jahnke <nassim@njahnke.dev>
|
||||
Date: Wed, 1 Dec 2021 12:36:25 +0100
|
||||
Subject: [PATCH] Prevent sending oversized item data in equipment and metadata
|
||||
|
||||
Co-authored-by: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
|
||||
diff --git a/src/main/java/io/papermc/paper/util/DataSanitizationUtil.java b/src/main/java/io/papermc/paper/util/DataSanitizationUtil.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..72483dedd3b1864fca3463d3ba3f6fad22680b97
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/util/DataSanitizationUtil.java
|
||||
@@ -0,0 +1,108 @@
|
||||
+package io.papermc.paper.util;
|
||||
+
|
||||
+import java.util.List;
|
||||
+import java.util.concurrent.atomic.AtomicBoolean;
|
||||
+import java.util.function.UnaryOperator;
|
||||
+import it.unimi.dsi.fastutil.objects.ObjectArrayList;
|
||||
+import net.minecraft.network.RegistryFriendlyByteBuf;
|
||||
+import net.minecraft.network.codec.StreamCodec;
|
||||
+import net.minecraft.util.Mth;
|
||||
+import net.minecraft.world.item.ItemStack;
|
||||
+import net.minecraft.world.item.Items;
|
||||
+import net.minecraft.world.item.component.BundleContents;
|
||||
+import net.minecraft.world.item.component.ChargedProjectiles;
|
||||
+import net.minecraft.world.item.component.ItemContainerContents;
|
||||
+import org.apache.commons.lang3.math.Fraction;
|
||||
+import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
+import org.checkerframework.framework.qual.DefaultQualifier;
|
||||
+
|
||||
+@DefaultQualifier(NonNull.class)
|
||||
+public final class DataSanitizationUtil {
|
||||
+
|
||||
+ private static final ThreadLocal<DataSanitizer> DATA_SANITIZER = ThreadLocal.withInitial(DataSanitizer::new);
|
||||
+
|
||||
+ public static DataSanitizer start(final boolean sanitize) {
|
||||
+ final DataSanitizer sanitizer = DATA_SANITIZER.get();
|
||||
+ if (sanitize) {
|
||||
+ sanitizer.start();
|
||||
+ }
|
||||
+ return sanitizer;
|
||||
+ }
|
||||
+
|
||||
+ public static final StreamCodec<RegistryFriendlyByteBuf, ChargedProjectiles> CHARGED_PROJECTILES = codec(ChargedProjectiles.STREAM_CODEC, DataSanitizationUtil::sanitizeChargedProjectiles);
|
||||
+ public static final StreamCodec<RegistryFriendlyByteBuf, BundleContents> BUNDLE_CONTENTS = codec(BundleContents.STREAM_CODEC, DataSanitizationUtil::sanitizeBundleContents);
|
||||
+ public static final StreamCodec<RegistryFriendlyByteBuf, ItemContainerContents> CONTAINER = codec(ItemContainerContents.STREAM_CODEC, contents -> ItemContainerContents.EMPTY);
|
||||
+
|
||||
+ private static ChargedProjectiles sanitizeChargedProjectiles(final ChargedProjectiles projectiles) {
|
||||
+ if (projectiles.isEmpty()) {
|
||||
+ return projectiles;
|
||||
+ }
|
||||
+
|
||||
+ return ChargedProjectiles.of(List.of(
|
||||
+ new ItemStack(projectiles.contains(Items.FIREWORK_ROCKET) ? Items.FIREWORK_ROCKET : Items.ARROW)
|
||||
+ ));
|
||||
+ }
|
||||
+
|
||||
+ private static BundleContents sanitizeBundleContents(final BundleContents contents) {
|
||||
+ if (contents.isEmpty()) {
|
||||
+ return contents;
|
||||
+ }
|
||||
+
|
||||
+ // Bundles change their texture based on their fullness.
|
||||
+ // A bundles content weight may be anywhere from 0 to, basically, infinity.
|
||||
+ // A weight of 1 is the usual maximum case
|
||||
+ int sizeUsed = Mth.mulAndTruncate(contents.weight(), 64);
|
||||
+ // Early out, *most* bundles should not be overfilled above a weight of one.
|
||||
+ if (sizeUsed <= 64) return new BundleContents(List.of(new ItemStack(Items.PAPER, Math.max(1, sizeUsed))));
|
||||
+
|
||||
+ final List<ItemStack> sanitizedRepresentation = new ObjectArrayList<>(sizeUsed / 64 + 1);
|
||||
+ while (sizeUsed > 0) {
|
||||
+ final int stackCount = Math.min(64, sizeUsed);
|
||||
+ sanitizedRepresentation.add(new ItemStack(Items.PAPER, stackCount));
|
||||
+ sizeUsed -= stackCount;
|
||||
+ }
|
||||
+ // Now we add a single fake item that uses the same amount of slots as all other items.
|
||||
+ // Ensure that potentially overstacked bundles are not represented by empty (count=0) itemstacks.
|
||||
+ return new BundleContents(sanitizedRepresentation);
|
||||
+ }
|
||||
+
|
||||
+ private static <B, A> StreamCodec<B, A> codec(final StreamCodec<B, A> delegate, final UnaryOperator<A> sanitizer) {
|
||||
+ return new DataSanitizationCodec<>(delegate, sanitizer);
|
||||
+ }
|
||||
+
|
||||
+ private record DataSanitizationCodec<B, A>(StreamCodec<B, A> delegate, UnaryOperator<A> sanitizer) implements StreamCodec<B, A> {
|
||||
+
|
||||
+ @Override
|
||||
+ public @NonNull A decode(final @NonNull B buf) {
|
||||
+ return this.delegate.decode(buf);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void encode(final @NonNull B buf, final @NonNull A value) {
|
||||
+ if (!DATA_SANITIZER.get().value().get()) {
|
||||
+ this.delegate.encode(buf, value);
|
||||
+ } else {
|
||||
+ this.delegate.encode(buf, this.sanitizer.apply(value));
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ public record DataSanitizer(AtomicBoolean value) implements AutoCloseable {
|
||||
+
|
||||
+ public DataSanitizer() {
|
||||
+ this(new AtomicBoolean(false));
|
||||
+ }
|
||||
+
|
||||
+ public void start() {
|
||||
+ this.value.compareAndSet(false, true);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void close() {
|
||||
+ this.value.compareAndSet(true, false);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ private DataSanitizationUtil() {
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/net/minecraft/core/component/DataComponents.java b/src/main/java/net/minecraft/core/component/DataComponents.java
|
||||
index a7f6a53cd1168bfc53b616cb0586a546fb9793e7..5e3bfd4a06b4a547a5f813f3d0c533fb7f4451f3 100644
|
||||
--- a/src/main/java/net/minecraft/core/component/DataComponents.java
|
||||
+++ b/src/main/java/net/minecraft/core/component/DataComponents.java
|
||||
@@ -180,10 +180,10 @@ public class DataComponents {
|
||||
"map_post_processing", builder -> builder.networkSynchronized(MapPostProcessing.STREAM_CODEC)
|
||||
);
|
||||
public static final DataComponentType<ChargedProjectiles> CHARGED_PROJECTILES = register(
|
||||
- "charged_projectiles", builder -> builder.persistent(ChargedProjectiles.CODEC).networkSynchronized(ChargedProjectiles.STREAM_CODEC).cacheEncoding()
|
||||
+ "charged_projectiles", builder -> builder.persistent(ChargedProjectiles.CODEC).networkSynchronized(io.papermc.paper.util.DataSanitizationUtil.CHARGED_PROJECTILES).cacheEncoding() // Paper - sanitize charged projectiles
|
||||
);
|
||||
public static final DataComponentType<BundleContents> BUNDLE_CONTENTS = register(
|
||||
- "bundle_contents", builder -> builder.persistent(BundleContents.CODEC).networkSynchronized(BundleContents.STREAM_CODEC).cacheEncoding()
|
||||
+ "bundle_contents", builder -> builder.persistent(BundleContents.CODEC).networkSynchronized(io.papermc.paper.util.DataSanitizationUtil.BUNDLE_CONTENTS).cacheEncoding() // Paper - sanitize bundle contents
|
||||
);
|
||||
public static final DataComponentType<PotionContents> POTION_CONTENTS = register(
|
||||
"potion_contents", builder -> builder.persistent(PotionContents.CODEC).networkSynchronized(PotionContents.STREAM_CODEC).cacheEncoding()
|
||||
@@ -250,7 +250,7 @@ public class DataComponents {
|
||||
"pot_decorations", builder -> builder.persistent(PotDecorations.CODEC).networkSynchronized(PotDecorations.STREAM_CODEC).cacheEncoding()
|
||||
);
|
||||
public static final DataComponentType<ItemContainerContents> CONTAINER = register(
|
||||
- "container", builder -> builder.persistent(ItemContainerContents.CODEC).networkSynchronized(ItemContainerContents.STREAM_CODEC).cacheEncoding()
|
||||
+ "container", builder -> builder.persistent(ItemContainerContents.CODEC).networkSynchronized(io.papermc.paper.util.DataSanitizationUtil.CONTAINER).cacheEncoding() // Paper - sanitize container contents
|
||||
);
|
||||
public static final DataComponentType<BlockItemStateProperties> BLOCK_STATE = register(
|
||||
"block_state", builder -> builder.persistent(BlockItemStateProperties.CODEC).networkSynchronized(BlockItemStateProperties.STREAM_CODEC).cacheEncoding()
|
||||
diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundSetEntityDataPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundSetEntityDataPacket.java
|
||||
index 59c1c103545f04fd35e6932df64a9910a1d74cd7..56bde49e6b7790155b032d0be40961d566ab89e9 100644
|
||||
--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundSetEntityDataPacket.java
|
||||
+++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundSetEntityDataPacket.java
|
||||
@@ -19,9 +19,11 @@ public record ClientboundSetEntityDataPacket(int id, List<SynchedEntityData.Data
|
||||
}
|
||||
|
||||
private static void pack(List<SynchedEntityData.DataValue<?>> trackedValues, RegistryFriendlyByteBuf buf) {
|
||||
+ try (var ignored = io.papermc.paper.util.DataSanitizationUtil.start(true)) { // Paper - data sanitization
|
||||
for (SynchedEntityData.DataValue<?> dataValue : trackedValues) {
|
||||
dataValue.write(buf);
|
||||
}
|
||||
+ } // Paper - data sanitization
|
||||
|
||||
buf.writeByte(255);
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundSetEquipmentPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundSetEquipmentPacket.java
|
||||
index e46030178b3b54168a3532def308a08b10888723..830bd76916e26a3a54954d3cf7b7520af52a2258 100644
|
||||
--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundSetEquipmentPacket.java
|
||||
+++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundSetEquipmentPacket.java
|
||||
@@ -19,6 +19,13 @@ public class ClientboundSetEquipmentPacket implements Packet<ClientGamePacketLis
|
||||
private final List<Pair<EquipmentSlot, ItemStack>> slots;
|
||||
|
||||
public ClientboundSetEquipmentPacket(int entityId, List<Pair<EquipmentSlot, ItemStack>> equipmentList) {
|
||||
+ // Paper start - data sanitization
|
||||
+ this(entityId, equipmentList, false);
|
||||
+ }
|
||||
+ private boolean sanitize;
|
||||
+ public ClientboundSetEquipmentPacket(int entityId, List<Pair<EquipmentSlot, ItemStack>> equipmentList, boolean sanitize) {
|
||||
+ this.sanitize = sanitize;
|
||||
+ // Paper end - data sanitization
|
||||
this.entity = entityId;
|
||||
this.slots = equipmentList;
|
||||
}
|
||||
@@ -40,6 +47,7 @@ public class ClientboundSetEquipmentPacket implements Packet<ClientGamePacketLis
|
||||
buf.writeVarInt(this.entity);
|
||||
int i = this.slots.size();
|
||||
|
||||
+ try (var ignored = io.papermc.paper.util.DataSanitizationUtil.start(this.sanitize)) { // Paper - data sanitization
|
||||
for (int j = 0; j < i; j++) {
|
||||
Pair<EquipmentSlot, ItemStack> pair = this.slots.get(j);
|
||||
EquipmentSlot equipmentSlot = pair.getFirst();
|
||||
@@ -48,6 +56,7 @@ public class ClientboundSetEquipmentPacket implements Packet<ClientGamePacketLis
|
||||
buf.writeByte(bl ? k | -128 : k);
|
||||
ItemStack.OPTIONAL_STREAM_CODEC.encode(buf, pair.getSecond());
|
||||
}
|
||||
+ } // Paper - data sanitization
|
||||
}
|
||||
|
||||
@Override
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerEntity.java b/src/main/java/net/minecraft/server/level/ServerEntity.java
|
||||
index f3456aeeab7eee5b6d0383a4bf1338dd8cc95bb3..b2fd3e936559c8fcb8b02ae3ef63c4f3bd0edb08 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerEntity.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerEntity.java
|
||||
@@ -388,7 +388,7 @@ public class ServerEntity {
|
||||
}
|
||||
|
||||
if (!list.isEmpty()) {
|
||||
- sender.accept(new ClientboundSetEquipmentPacket(this.entity.getId(), list));
|
||||
+ sender.accept(new ClientboundSetEquipmentPacket(this.entity.getId(), list, true)); // Paper - data sanitization
|
||||
}
|
||||
((LivingEntity) this.entity).detectEquipmentUpdatesPublic(); // CraftBukkit - SPIGOT-3789: sync again immediately after sending
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
index 7508434475ea93f9153f3976c5fa95c7678807e9..dc8f2d0bc3adc87088e7289a90c9186483e21cf4 100644
|
||||
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
@@ -2743,7 +2743,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
|
||||
entity.refreshEntityData(ServerGamePacketListenerImpl.this.player);
|
||||
// SPIGOT-7136 - Allays
|
||||
if (entity instanceof Allay || entity instanceof net.minecraft.world.entity.animal.horse.AbstractHorse) { // Paper - Fix horse armor desync
|
||||
- ServerGamePacketListenerImpl.this.send(new ClientboundSetEquipmentPacket(entity.getId(), Arrays.stream(net.minecraft.world.entity.EquipmentSlot.values()).map((slot) -> Pair.of(slot, ((LivingEntity) entity).getItemBySlot(slot).copy())).collect(Collectors.toList())));
|
||||
+ ServerGamePacketListenerImpl.this.send(new ClientboundSetEquipmentPacket(entity.getId(), Arrays.stream(net.minecraft.world.entity.EquipmentSlot.values()).map((slot) -> Pair.of(slot, ((LivingEntity) entity).getItemBySlot(slot).copy())).collect(Collectors.toList()), true)); // Paper - sanitize
|
||||
}
|
||||
|
||||
ServerGamePacketListenerImpl.this.player.containerMenu.sendAllDataToRemote(); // Paper - fix slot desync - always refresh player inventory
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
index 6f9c4a5a87bdfb8ce32ce40c4a34997695d15ce3..5a992419f9847480ca6e431b5402d99ac411c15e 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
@@ -3462,7 +3462,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
|
||||
}
|
||||
|
||||
});
|
||||
- ((ServerLevel) this.level()).getChunkSource().broadcast(this, new ClientboundSetEquipmentPacket(this.getId(), list));
|
||||
+ ((ServerLevel) this.level()).getChunkSource().broadcast(this, new ClientboundSetEquipmentPacket(this.getId(), list, true)); // Paper - data sanitization
|
||||
}
|
||||
|
||||
private ItemStack getLastArmorItem(EquipmentSlot slot) {
|
|
@ -0,0 +1,24 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
Date: Sun, 12 May 2024 21:57:23 -0700
|
||||
Subject: [PATCH] Prevent NPE if hooked entity was cleared
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java b/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java
|
||||
index 5b49b11d2d88b33731df582b119ef7a680d862e9..762deff3bef8ec478d83139e8193aba35e39807d 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java
|
||||
@@ -509,11 +509,13 @@ public class FishingHook extends Projectile {
|
||||
if (playerFishEvent.isCancelled()) {
|
||||
return 0;
|
||||
}
|
||||
+ if (this.hookedIn != null) { // Paper - re-check to see if there is a hooked entity
|
||||
// CraftBukkit end
|
||||
this.pullEntity(this.hookedIn);
|
||||
CriteriaTriggers.FISHING_ROD_HOOKED.trigger((ServerPlayer) entityhuman, usedItem, this, Collections.emptyList());
|
||||
this.level().broadcastEntityEvent(this, (byte) 31);
|
||||
i = this.hookedIn instanceof ItemEntity ? 3 : 5;
|
||||
+ } // Paper - re-check to see if there is a hooked entity
|
||||
} else if (this.nibble > 0) {
|
||||
LootParams lootparams = (new LootParams.Builder((ServerLevel) this.level())).withParameter(LootContextParams.ORIGIN, this.position()).withParameter(LootContextParams.TOOL, usedItem).withParameter(LootContextParams.THIS_ENTITY, this).withLuck((float) this.luck + entityhuman.getLuck()).create(LootContextParamSets.FISHING);
|
||||
LootTable loottable = this.level().getServer().reloadableRegistries().getLootTable(BuiltInLootTables.FISHING);
|
|
@ -0,0 +1,47 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Tamion <70228790+notTamion@users.noreply.github.com>
|
||||
Date: Thu, 23 May 2024 11:02:20 +0200
|
||||
Subject: [PATCH] Fix cancelling BlockPlaceEvent calling onRemove
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java
|
||||
index 62529e61c8751433a8b6abe6cfb2cc414c8c3cf2..4f20e5bb143e152e19e5fb57f66d0344001ffbd9 100644
|
||||
--- a/src/main/java/net/minecraft/world/item/ItemStack.java
|
||||
+++ b/src/main/java/net/minecraft/world/item/ItemStack.java
|
||||
@@ -500,9 +500,11 @@ public final class ItemStack implements DataComponentHolder {
|
||||
world.capturedTileEntities.clear(); // Paper - Allow chests to be placed with NBT data; clear out block entities as chests and such will pop loot
|
||||
// revert back all captured blocks
|
||||
world.preventPoiUpdated = true; // CraftBukkit - SPIGOT-5710
|
||||
+ world.isBlockPlaceCancelled = true; // Paper - prevent calling cleanup logic when undoing a block place upon a cancelled BlockPlaceEvent
|
||||
for (BlockState blockstate : blocks) {
|
||||
blockstate.update(true, false);
|
||||
}
|
||||
+ world.isBlockPlaceCancelled = false; // Paper - prevent calling cleanup logic when undoing a block place upon a cancelled BlockPlaceEvent
|
||||
world.preventPoiUpdated = false;
|
||||
|
||||
// Brute force all possible updates
|
||||
diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
|
||||
index 35b9a6d382e420844fc21c88b7d8044e3b8b8368..1b899473c6deeaa1aef9007d8b7bcec98580e61c 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/Level.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/Level.java
|
||||
@@ -152,6 +152,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
|
||||
public boolean preventPoiUpdated = false; // CraftBukkit - SPIGOT-5710
|
||||
public boolean captureBlockStates = false;
|
||||
public boolean captureTreeGeneration = false;
|
||||
+ public boolean isBlockPlaceCancelled = false; // Paper - prevent calling cleanup logic when undoing a block place upon a cancelled BlockPlaceEvent
|
||||
public Map<BlockPos, org.bukkit.craftbukkit.block.CraftBlockState> capturedBlockStates = new java.util.LinkedHashMap<>(); // Paper
|
||||
public Map<BlockPos, BlockEntity> capturedTileEntities = new java.util.LinkedHashMap<>(); // Paper - Retain block place order when capturing blockstates
|
||||
public List<ItemEntity> captureDrops;
|
||||
diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
index 5dd1df0da1f954778aebe0f40611ae0f3a7866ab..325d1e38a72a4b30f30261267e9adfb8a8726b11 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
@@ -369,7 +369,7 @@ public class LevelChunk extends ChunkAccess {
|
||||
|
||||
boolean flag3 = iblockdata1.hasBlockEntity();
|
||||
|
||||
- if (!this.level.isClientSide) {
|
||||
+ if (!this.level.isClientSide && !this.level.isBlockPlaceCancelled) { // Paper - prevent calling cleanup logic when undoing a block place upon a cancelled BlockPlaceEvent
|
||||
iblockdata1.onRemove(this.level, blockposition, iblockdata, flag);
|
||||
} else if (!iblockdata1.is(block) && flag3) {
|
||||
this.removeBlockEntity(blockposition);
|
26
patches/server/0964-Add-missing-fishing-event-state.patch
Normal file
26
patches/server/0964-Add-missing-fishing-event-state.patch
Normal file
|
@ -0,0 +1,26 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: SoSeDiK <mrsosedik@gmail.com>
|
||||
Date: Wed, 1 May 2024 07:44:50 +0300
|
||||
Subject: [PATCH] Add missing fishing event state
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java b/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java
|
||||
index 762deff3bef8ec478d83139e8193aba35e39807d..4daa69c6be6d48563e30343a7e40e4da9ec7e5ad 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/projectile/FishingHook.java
|
||||
@@ -416,6 +416,15 @@ public class FishingHook extends Projectile {
|
||||
this.fishAngle = Mth.nextFloat(this.random, this.minLureAngle, this.maxLureAngle);
|
||||
this.timeUntilHooked = Mth.nextInt(this.random, this.minLureTime, this.maxLureTime);
|
||||
// CraftBukkit end
|
||||
+ // Paper start - Add missing fishing event state
|
||||
+ if (this.getPlayerOwner() != null) {
|
||||
+ PlayerFishEvent playerFishEvent = new PlayerFishEvent((Player) this.getPlayerOwner().getBukkitEntity(), null, (FishHook) this.getBukkitEntity(), PlayerFishEvent.State.LURED);
|
||||
+ if (!playerFishEvent.callEvent()) {
|
||||
+ this.timeUntilHooked = 0;
|
||||
+ return;
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end - Add missing fishing event state
|
||||
}
|
||||
} else {
|
||||
// CraftBukkit start - logic to modify fishing wait time
|
|
@ -0,0 +1,26 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
Date: Sat, 25 May 2024 09:51:13 -0700
|
||||
Subject: [PATCH] Deprecate InvAction#HOTBAR_MOVE_AND_READD
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
index dc8f2d0bc3adc87088e7289a90c9186483e21cf4..2533c0a54e74666a55a8478c7d4da12d26e31fd4 100644
|
||||
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
@@ -3014,14 +3014,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
|
||||
Slot clickedSlot = this.player.containerMenu.getSlot(packet.getSlotNum());
|
||||
if (clickedSlot.mayPickup(this.player)) {
|
||||
ItemStack hotbar = this.player.getInventory().getItem(packet.getButtonNum());
|
||||
- boolean canCleanSwap = hotbar.isEmpty() || (clickedSlot.container == this.player.getInventory() && clickedSlot.mayPlace(hotbar)); // the slot will accept the hotbar item
|
||||
- if (clickedSlot.hasItem()) {
|
||||
- if (canCleanSwap) {
|
||||
- action = InventoryAction.HOTBAR_SWAP;
|
||||
- } else {
|
||||
- action = InventoryAction.HOTBAR_MOVE_AND_READD;
|
||||
- }
|
||||
- } else if (!clickedSlot.hasItem() && !hotbar.isEmpty() && clickedSlot.mayPlace(hotbar)) {
|
||||
+ if ((!hotbar.isEmpty() && clickedSlot.mayPlace(hotbar)) || (hotbar.isEmpty() && clickedSlot.hasItem())) { // Paper - modernify this logic (no such thing as a "hotbar move and readd"
|
||||
action = InventoryAction.HOTBAR_SWAP;
|
||||
} else {
|
||||
action = InventoryAction.NOTHING;
|
|
@ -0,0 +1,21 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Shane Freeder <theboyetronic@gmail.com>
|
||||
Date: Thu, 30 May 2024 18:46:15 +0100
|
||||
Subject: [PATCH] Fix sending disconnect packet in phases where it doesn't
|
||||
exist
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/network/Connection.java b/src/main/java/net/minecraft/network/Connection.java
|
||||
index 4b9da6e2140b14f1e56056f5e9e94b2169d85501..55848fa832d0f4d2d03f99df51e10c5fdfcd2ded 100644
|
||||
--- a/src/main/java/net/minecraft/network/Connection.java
|
||||
+++ b/src/main/java/net/minecraft/network/Connection.java
|
||||
@@ -218,7 +218,8 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
|
||||
if (player != null) player.quitReason = org.bukkit.event.player.PlayerQuitEvent.QuitReason.ERRONEOUS_STATE; // Paper - Add API for quit reason
|
||||
if (flag) {
|
||||
Connection.LOGGER.debug("Failed to sent packet", throwable);
|
||||
- if (this.getSending() == PacketFlow.CLIENTBOUND) {
|
||||
+ boolean doesDisconnectExist = this.packetListener.protocol() != ConnectionProtocol.STATUS && this.packetListener.protocol() != ConnectionProtocol.HANDSHAKING; // Paper
|
||||
+ if (this.getSending() == PacketFlow.CLIENTBOUND && doesDisconnectExist) { // Paper
|
||||
Packet<?> packet = this.sendLoginDisconnect ? new ClientboundLoginDisconnectPacket(ichatmutablecomponent) : new ClientboundDisconnectPacket(ichatmutablecomponent);
|
||||
|
||||
this.send((Packet) packet, PacketSendListener.thenRun(() -> {
|
134
patches/server/0967-Adopt-MaterialRerouting.patch
Normal file
134
patches/server/0967-Adopt-MaterialRerouting.patch
Normal file
|
@ -0,0 +1,134 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Bjarne Koll <lynxplay101@gmail.com>
|
||||
Date: Thu, 13 Jun 2024 11:02:36 +0200
|
||||
Subject: [PATCH] Adopt MaterialRerouting
|
||||
|
||||
Adopts the paper-api to the material rerouting infrastructure introduced
|
||||
by upstream.
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/legacy/MaterialRerouting.java b/src/main/java/org/bukkit/craftbukkit/legacy/MaterialRerouting.java
|
||||
index 3ff0f0e34356cee4c510fdd60af723b1c5df156a..6cc9d7a9e6d4bfdc27e52fc581b2bb832616f121 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/legacy/MaterialRerouting.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/legacy/MaterialRerouting.java
|
||||
@@ -600,4 +600,82 @@ public class MaterialRerouting {
|
||||
public static void setBlocks(ToolComponent.ToolRule toolRule, Collection<Material> blocks) {
|
||||
toolRule.setBlocks(blocks.stream().map(MaterialRerouting::transformToBlockType).toList());
|
||||
}
|
||||
+
|
||||
+ // Paper start - register paper API specific material consumers in rerouting
|
||||
+ // A lot of these methods do *not* run through MaterialRerouting to avoid the overhead of a system that
|
||||
+ // currently is an effective noop.
|
||||
+ // The only downside is that upstream moved the handling of legacy materials into transformFromXType methods.
|
||||
+ // As such, methods introduced prior to 1.13 need to run through the transformation to make sure legacy material
|
||||
+ // constants still work.
|
||||
+
|
||||
+ // Utility method for constructing a set from an existing one after mapping each element.
|
||||
+ private static <I, O> Set<O> mapSet(final Set<I> input, final java.util.function.Function<I,O> mapper) {
|
||||
+ final Set<O> output = new it.unimi.dsi.fastutil.objects.ObjectOpenHashSet<>(input.size());
|
||||
+ for (final I i : input) {
|
||||
+ output.add(mapper.apply(i));
|
||||
+ }
|
||||
+ return output;
|
||||
+ }
|
||||
+
|
||||
+ // Method added post-1.13, noop (https://github.com/PaperMC/Paper/pull/4965)
|
||||
+ public static org.bukkit.Material getMinecartMaterial(org.bukkit.entity.Minecart minecart, @InjectPluginVersion ApiVersion version) {
|
||||
+ return minecart.getMinecartMaterial();
|
||||
+ }
|
||||
+
|
||||
+ // Method added post-1.13, noop (https://github.com/PaperMC/Paper/pull/4965)
|
||||
+ public static Material getBoatMaterial(Boat boat, @InjectPluginVersion ApiVersion version) {
|
||||
+ return boat.getBoatMaterial();
|
||||
+ }
|
||||
+
|
||||
+ // Method added post-1.13, noop (https://github.com/PaperMC/Paper/pull/3807)
|
||||
+ public static Material getType(io.papermc.paper.event.player.PlayerItemCooldownEvent event, @InjectPluginVersion ApiVersion version) {
|
||||
+ return event.getType();
|
||||
+ }
|
||||
+
|
||||
+ // Method added post-1.13, noop (https://github.com/PaperMC/Paper/pull/3850)
|
||||
+ public static Collection<Material> getInfiniburn(World world, @InjectPluginVersion ApiVersion version) {
|
||||
+ return world.getInfiniburn();
|
||||
+ }
|
||||
+
|
||||
+ // Method added pre-1.13, needs legacy rerouting (https://github.com/PaperMC/Paper/commit/3438e96192)
|
||||
+ public static Set<Material> getTypes(
|
||||
+ final com.destroystokyo.paper.event.player.PlayerArmorChangeEvent.SlotType slotType,
|
||||
+ @InjectPluginVersion final ApiVersion apiVersion
|
||||
+ ) {
|
||||
+ if (apiVersion.isNewerThanOrSameAs(ApiVersion.FLATTENING)) return slotType.getTypes();
|
||||
+ else return mapSet(slotType.getTypes(), MaterialRerouting::transformToItemType); // Needed as pre-flattening is hanled by transformToItemType
|
||||
+ }
|
||||
+
|
||||
+ // Method added pre-1.13, needs legacy rerouting (https://github.com/PaperMC/Paper/commit/3438e96192)
|
||||
+ @RerouteStatic("com/destroystokyo/paper/event/player/PlayerArmorChangeEvent$SlotType")
|
||||
+ public static com.destroystokyo.paper.event.player.PlayerArmorChangeEvent.SlotType getByMaterial(
|
||||
+ final Material material
|
||||
+ ) {
|
||||
+ return com.destroystokyo.paper.event.player.PlayerArmorChangeEvent.SlotType.getByMaterial(MaterialRerouting.transformToItemType(material));
|
||||
+ }
|
||||
+
|
||||
+ // Method added pre-1.13, needs legacy rerouting (https://github.com/PaperMC/Paper/commit/3438e96192)
|
||||
+ @RerouteStatic("com/destroystokyo/paper/event/player/PlayerArmorChangeEvent$SlotType")
|
||||
+ public static boolean isEquipable(final Material material) {
|
||||
+ return com.destroystokyo.paper.event.player.PlayerArmorChangeEvent.SlotType.isEquipable(MaterialRerouting.transformToItemType(material));
|
||||
+ }
|
||||
+
|
||||
+ // Method added post 1.13, no-op (https://github.com/PaperMC/Paper/pull/1244)
|
||||
+ public static Material getMaterial(final com.destroystokyo.paper.event.block.AnvilDamagedEvent.DamageState damageState) {
|
||||
+ return damageState.getMaterial();
|
||||
+ }
|
||||
+
|
||||
+ // Method added post 1.13, no-op (https://github.com/PaperMC/Paper/pull/1244)
|
||||
+ @RerouteStatic("com/destroystokyo/paper/event/block/AnvilDamagedEvent$DamageState")
|
||||
+ public static com.destroystokyo.paper.event.block.AnvilDamagedEvent.DamageState getState(
|
||||
+ final Material material
|
||||
+ ) {
|
||||
+ return com.destroystokyo.paper.event.block.AnvilDamagedEvent.DamageState.getState(material);
|
||||
+ }
|
||||
+
|
||||
+ // Method added post 1.13, no-op (https://github.com/PaperMC/Paper/pull/10290)
|
||||
+ public static ItemStack withType(final ItemStack itemStack, final Material material) {
|
||||
+ return itemStack.withType(material);
|
||||
+ }
|
||||
+ // Paper end - register paper API specific material consumers in rerouting
|
||||
}
|
||||
diff --git a/src/test/java/org/bukkit/craftbukkit/legacy/MaterialReroutingTest.java b/src/test/java/org/bukkit/craftbukkit/legacy/MaterialReroutingTest.java
|
||||
index cd03ea1f726894161ca786e7e7d00d04716405d3..329eeb174180b5d90b071247dac5459e4ffe3be3 100644
|
||||
--- a/src/test/java/org/bukkit/craftbukkit/legacy/MaterialReroutingTest.java
|
||||
+++ b/src/test/java/org/bukkit/craftbukkit/legacy/MaterialReroutingTest.java
|
||||
@@ -56,6 +56,9 @@ public class MaterialReroutingTest {
|
||||
.filter(entry -> !entry.getName().endsWith("ItemType.class"))
|
||||
.filter(entry -> !entry.getName().endsWith("Registry.class"))
|
||||
.filter(entry -> !entry.getName().startsWith("org/bukkit/material"))
|
||||
+ // Paper start - types that cannot be translated to ItemType/BlockType
|
||||
+ .filter(entry -> !entry.getName().equals("com/destroystokyo/paper/MaterialSetTag.class"))
|
||||
+ // Paper end - types that cannot be translated to ItemType/BlockType
|
||||
.map(entry -> {
|
||||
try {
|
||||
return MaterialReroutingTest.jarFile.getInputStream(entry);
|
||||
@@ -93,6 +96,10 @@ public class MaterialReroutingTest {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
+ // Paper start - filter out more methods from rerouting test
|
||||
+ if (methodNode.name.startsWith("lambda$")) continue;
|
||||
+ if (isInternal(methodNode.invisibleAnnotations)) continue;
|
||||
+ // Paper end - filter out more methods from rerouting test
|
||||
|
||||
if (!Commodore.rerouteMethods(ApiVersion.CURRENT, MaterialReroutingTest.MATERIAL_METHOD_REROUTE, (methodNode.access & Opcodes.ACC_STATIC) != 0, classNode.name, methodNode.name, methodNode.desc, a -> { })) {
|
||||
missingReroute.add(methodNode.name + " " + methodNode.desc + " " + methodNode.signature);
|
||||
@@ -109,6 +116,13 @@ public class MaterialReroutingTest {
|
||||
}
|
||||
}
|
||||
|
||||
+ // Paper start - filter out more methods from rerouting test
|
||||
+ private static boolean isInternal(final List<org.objectweb.asm.tree.AnnotationNode> annotationNodes) {
|
||||
+ return annotationNodes != null
|
||||
+ && annotationNodes.stream().anyMatch(a -> a.desc.equals("Lorg/jetbrains/annotations/ApiStatus$Internal;"));
|
||||
+ }
|
||||
+ // Paper end - filter out more methods from rerouting test
|
||||
+
|
||||
@AfterAll
|
||||
public static void clear() throws IOException {
|
||||
if (MaterialReroutingTest.jarFile != null) {
|
231
patches/server/0968-Suspicious-Effect-Entry-API.patch
Normal file
231
patches/server/0968-Suspicious-Effect-Entry-API.patch
Normal file
|
@ -0,0 +1,231 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com>
|
||||
Date: Sun, 3 Mar 2024 19:43:40 +0100
|
||||
Subject: [PATCH] Suspicious Effect Entry API
|
||||
|
||||
Exposes a new suspicious effect entry type that properly represents
|
||||
storable effects in the context of suspicious effects as they only
|
||||
define the potion effect type and duration.
|
||||
|
||||
This differentiates them from the existing PotionEffect API found in
|
||||
bukkit and hence clarifies that storable values in the parts of the API
|
||||
in which it replaces PotionEffect.
|
||||
|
||||
Co-authored-by: Yannick Lamprecht <yannicklamprecht@live.de>
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMushroomCow.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMushroomCow.java
|
||||
index bfe39c7a9d2910bee9b40cf5ab4c154711d5cbb0..596146ad7899c21645df8834ce5f0afd6c1b0604 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMushroomCow.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMushroomCow.java
|
||||
@@ -37,16 +37,24 @@ public class CraftMushroomCow extends CraftCow implements MushroomCow, io.paperm
|
||||
@Override
|
||||
public boolean addEffectToNextStew(PotionEffect potionEffect, boolean overwrite) {
|
||||
Preconditions.checkArgument(potionEffect != null, "PotionEffect cannot be null");
|
||||
- MobEffectInstance minecraftPotionEffect = CraftPotionUtil.fromBukkit(potionEffect);
|
||||
- if (!overwrite && this.hasEffectForNextStew(potionEffect.getType())) {
|
||||
+ // Paper start - add overloads to use suspicious effect entry to mushroom cow and suspicious stew meta
|
||||
+ return this.addEffectToNextStew(io.papermc.paper.potion.SuspiciousEffectEntry.create(potionEffect.getType(), potionEffect.getDuration()), overwrite);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean addEffectToNextStew(io.papermc.paper.potion.SuspiciousEffectEntry suspiciousEffectEntry, boolean overwrite) {
|
||||
+ Preconditions.checkArgument(suspiciousEffectEntry != null, "SuspiciousEffectEntry cannot be null");
|
||||
+ Holder<MobEffect> minecraftPotionEffect = CraftPotionEffectType.bukkitToMinecraftHolder(suspiciousEffectEntry.effect());
|
||||
+ // Paper end - add overloads to use suspicious effect entry to mushroom cow and suspicious stew meta
|
||||
+ if (!overwrite && this.hasEffectForNextStew(suspiciousEffectEntry.effect())) {
|
||||
return false;
|
||||
}
|
||||
SuspiciousStewEffects stewEffects = this.getHandle().stewEffects;
|
||||
if (stewEffects == null) {
|
||||
stewEffects = SuspiciousStewEffects.EMPTY;
|
||||
}
|
||||
- SuspiciousStewEffects.Entry recordSuspiciousEffect = new SuspiciousStewEffects.Entry(minecraftPotionEffect.getEffect(), minecraftPotionEffect.getDuration());
|
||||
- this.removeEffectFromNextStew(potionEffect.getType()); // Avoid duplicates of effects
|
||||
+ SuspiciousStewEffects.Entry recordSuspiciousEffect = new SuspiciousStewEffects.Entry(minecraftPotionEffect, suspiciousEffectEntry.duration()); // Paper - sus effect entry API
|
||||
+ this.removeEffectFromNextStew(suspiciousEffectEntry.effect()); // Avoid duplicates of effects // Paper - sus effect entry API
|
||||
this.getHandle().stewEffects = stewEffects.withEffectAdded(recordSuspiciousEffect);
|
||||
return true;
|
||||
}
|
||||
@@ -101,6 +109,43 @@ public class CraftMushroomCow extends CraftCow implements MushroomCow, io.paperm
|
||||
this.getHandle().setVariant(net.minecraft.world.entity.animal.MushroomCow.Variant.values()[variant.ordinal()]);
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ @Override
|
||||
+ public List<io.papermc.paper.potion.SuspiciousEffectEntry> getStewEffects() {
|
||||
+ if (this.getHandle().stewEffects == null) {
|
||||
+ return List.of();
|
||||
+ }
|
||||
+
|
||||
+ final List<io.papermc.paper.potion.SuspiciousEffectEntry> effectEntries = new java.util.ArrayList<>(this.getHandle().stewEffects.effects().size());
|
||||
+ for (final SuspiciousStewEffects.Entry effect : this.getHandle().stewEffects.effects()) {
|
||||
+ effectEntries.add(io.papermc.paper.potion.SuspiciousEffectEntry.create(
|
||||
+ org.bukkit.craftbukkit.potion.CraftPotionEffectType.minecraftHolderToBukkit(effect.effect()),
|
||||
+ effect.duration()
|
||||
+ ));
|
||||
+ }
|
||||
+
|
||||
+ return java.util.Collections.unmodifiableList(effectEntries);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setStewEffects(final List<io.papermc.paper.potion.SuspiciousEffectEntry> effects) {
|
||||
+ if (effects.isEmpty()) {
|
||||
+ this.getHandle().stewEffects = null;
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ List<SuspiciousStewEffects.Entry> nmsPairs = new java.util.ArrayList<>(effects.size());
|
||||
+ for (final io.papermc.paper.potion.SuspiciousEffectEntry effect : effects) {
|
||||
+ nmsPairs.add(new SuspiciousStewEffects.Entry(
|
||||
+ org.bukkit.craftbukkit.potion.CraftPotionEffectType.bukkitToMinecraftHolder(effect.effect()),
|
||||
+ effect.duration()
|
||||
+ ));
|
||||
+ }
|
||||
+
|
||||
+ this.getHandle().stewEffects = new SuspiciousStewEffects(nmsPairs);
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
@Override
|
||||
public String toString() {
|
||||
return "CraftMushroomCow";
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSuspiciousStew.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSuspiciousStew.java
|
||||
index 7a43e326e51300306b9c5c23a16ffae92030bd2b..192cd33f6276ea4928e29ac2cd4e45bf8bf82dcb 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSuspiciousStew.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaSuspiciousStew.java
|
||||
@@ -21,7 +21,7 @@ public class CraftMetaSuspiciousStew extends CraftMetaItem implements Suspicious
|
||||
|
||||
static final ItemMetaKeyType<SuspiciousStewEffects> EFFECTS = new ItemMetaKeyType<>(DataComponents.SUSPICIOUS_STEW_EFFECTS, "effects");
|
||||
|
||||
- private List<PotionEffect> customEffects;
|
||||
+ private List<io.papermc.paper.potion.SuspiciousEffectEntry> customEffects; // Paper - add overloads to use suspicious effect entry to mushroom cow and suspicious stew meta
|
||||
|
||||
CraftMetaSuspiciousStew(CraftMetaItem meta) {
|
||||
super(meta);
|
||||
@@ -47,7 +47,7 @@ public class CraftMetaSuspiciousStew extends CraftMetaItem implements Suspicious
|
||||
continue;
|
||||
}
|
||||
int duration = effect.duration();
|
||||
- this.customEffects.add(new PotionEffect(type, duration, 0));
|
||||
+ this.customEffects.add(io.papermc.paper.potion.SuspiciousEffectEntry.create(type, duration)); // Paper - use suspicious effect entry for suspicious stew meta
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -73,8 +73,8 @@ public class CraftMetaSuspiciousStew extends CraftMetaItem implements Suspicious
|
||||
if (this.customEffects != null) {
|
||||
List<SuspiciousStewEffects.Entry> effectList = new ArrayList<>();
|
||||
|
||||
- for (PotionEffect effect : this.customEffects) {
|
||||
- effectList.add(new net.minecraft.world.item.component.SuspiciousStewEffects.Entry(CraftPotionEffectType.bukkitToMinecraftHolder(effect.getType()), effect.getDuration()));
|
||||
+ for (io.papermc.paper.potion.SuspiciousEffectEntry effect : this.customEffects) {
|
||||
+ effectList.add(new net.minecraft.world.item.component.SuspiciousStewEffects.Entry(CraftPotionEffectType.bukkitToMinecraftHolder(effect.effect()), effect.duration())); // Paper - add overloads to use suspicious effect entry to mushroom cow and suspicious stew meta
|
||||
}
|
||||
tag.put(CraftMetaSuspiciousStew.EFFECTS, new SuspiciousStewEffects(effectList));
|
||||
}
|
||||
@@ -106,7 +106,7 @@ public class CraftMetaSuspiciousStew extends CraftMetaItem implements Suspicious
|
||||
@Override
|
||||
public List<PotionEffect> getCustomEffects() {
|
||||
if (this.hasCustomEffects()) {
|
||||
- return ImmutableList.copyOf(this.customEffects);
|
||||
+ return this.customEffects.stream().map(suspiciousEffectEntry -> suspiciousEffectEntry.effect().createEffect(suspiciousEffectEntry.duration(), 0)).toList(); // Paper - add overloads to use suspicious effect entry to mushroom cow and suspicious stew meta
|
||||
}
|
||||
return ImmutableList.of();
|
||||
}
|
||||
@@ -114,27 +114,47 @@ public class CraftMetaSuspiciousStew extends CraftMetaItem implements Suspicious
|
||||
@Override
|
||||
public boolean addCustomEffect(PotionEffect effect, boolean overwrite) {
|
||||
Preconditions.checkArgument(effect != null, "Potion effect cannot be null");
|
||||
+ return addCustomEffect(io.papermc.paper.potion.SuspiciousEffectEntry.create(effect.getType(), effect.getDuration()), overwrite); // Paper - add overloads to use suspicious effect entry to mushroom cow and suspicious stew meta
|
||||
+ }
|
||||
|
||||
- int index = this.indexOfEffect(effect.getType());
|
||||
- if (index != -1) {
|
||||
- if (overwrite) {
|
||||
- PotionEffect old = this.customEffects.get(index);
|
||||
- if (old.getDuration() == effect.getDuration()) {
|
||||
+ // Paper start - add overloads to use suspicious effect entry to mushroom cow and suspicious stew meta
|
||||
+ @Override
|
||||
+ public boolean addCustomEffect(final io.papermc.paper.potion.SuspiciousEffectEntry suspiciousEffectEntry, final boolean overwrite) {
|
||||
+ Preconditions.checkArgument(suspiciousEffectEntry != null, "Suspicious effect entry cannot be null");
|
||||
+ if (this.hasCustomEffects()) {
|
||||
+ final List<io.papermc.paper.potion.SuspiciousEffectEntry> matchingEffects = this.customEffects.stream().filter(
|
||||
+ entry -> entry.effect() == suspiciousEffectEntry.effect()
|
||||
+ ).toList();
|
||||
+ if (!matchingEffects.isEmpty()) {
|
||||
+ if (overwrite) {
|
||||
+ boolean foundMatchingDuration = false;
|
||||
+ boolean mutated = false;
|
||||
+ for (final io.papermc.paper.potion.SuspiciousEffectEntry matchingEffect : matchingEffects) {
|
||||
+ if (matchingEffect.duration() != suspiciousEffectEntry.duration()) {
|
||||
+ this.customEffects.remove(suspiciousEffectEntry);
|
||||
+ mutated = true;
|
||||
+ } else {
|
||||
+ foundMatchingDuration = true;
|
||||
+ }
|
||||
+ }
|
||||
+ if (foundMatchingDuration && !mutated) {
|
||||
+ return false;
|
||||
+ } else if (!foundMatchingDuration) {
|
||||
+ this.customEffects.add(suspiciousEffectEntry);
|
||||
+ }
|
||||
+ return true;
|
||||
+ } else {
|
||||
return false;
|
||||
}
|
||||
- this.customEffects.set(index, effect);
|
||||
- return true;
|
||||
- } else {
|
||||
- return false;
|
||||
}
|
||||
- } else {
|
||||
- if (this.customEffects == null) {
|
||||
- this.customEffects = new ArrayList<>();
|
||||
- }
|
||||
- this.customEffects.add(effect);
|
||||
- return true;
|
||||
}
|
||||
+ if (this.customEffects == null) {
|
||||
+ this.customEffects = new ArrayList<>();
|
||||
+ }
|
||||
+ this.customEffects.add(suspiciousEffectEntry);
|
||||
+ return true;
|
||||
}
|
||||
+ // Paper end - add overloads to use suspicious effect entry to mushroom cow and suspicious stew meta
|
||||
|
||||
@Override
|
||||
public boolean removeCustomEffect(PotionEffectType type) {
|
||||
@@ -145,10 +165,12 @@ public class CraftMetaSuspiciousStew extends CraftMetaItem implements Suspicious
|
||||
}
|
||||
|
||||
boolean changed = false;
|
||||
- Iterator<PotionEffect> iterator = this.customEffects.iterator();
|
||||
+ // Paper start - add overloads to use suspicious effect entry to mushroom cow and suspicious stew meta
|
||||
+ Iterator<io.papermc.paper.potion.SuspiciousEffectEntry> iterator = this.customEffects.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
- PotionEffect effect = iterator.next();
|
||||
- if (type.equals(effect.getType())) {
|
||||
+ io.papermc.paper.potion.SuspiciousEffectEntry effect = iterator.next();
|
||||
+ if (type.equals(effect.effect())) {
|
||||
+ // Paper end - add overloads to use suspicious effect entry to mushroom cow and suspicious stew meta
|
||||
iterator.remove();
|
||||
changed = true;
|
||||
}
|
||||
@@ -171,7 +193,7 @@ public class CraftMetaSuspiciousStew extends CraftMetaItem implements Suspicious
|
||||
}
|
||||
|
||||
for (int i = 0; i < this.customEffects.size(); i++) {
|
||||
- if (this.customEffects.get(i).getType().equals(type)) {
|
||||
+ if (this.customEffects.get(i).effect().equals(type)) { // Paper - add overloads to use suspicious effect entry to mushroom cow and suspicious stew meta
|
||||
return i;
|
||||
}
|
||||
}
|
||||
@@ -216,7 +238,7 @@ public class CraftMetaSuspiciousStew extends CraftMetaItem implements Suspicious
|
||||
super.serialize(builder);
|
||||
|
||||
if (this.hasCustomEffects()) {
|
||||
- builder.put(CraftMetaSuspiciousStew.EFFECTS.BUKKIT, ImmutableList.copyOf(this.customEffects));
|
||||
+ builder.put(CraftMetaSuspiciousStew.EFFECTS.BUKKIT, ImmutableList.copyOf(com.google.common.collect.Lists.transform(this.customEffects, s -> new PotionEffect(s.effect(), s.duration(), 0)))); // Paper - add overloads to use suspicious effect entry to mushroom cow and suspicious stew meta - convert back to potion effect for bukkit legacy item serialisation to maintain backwards compatibility for the written format.
|
||||
}
|
||||
|
||||
return builder;
|
|
@ -0,0 +1,19 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: granny <contact@granny.dev>
|
||||
Date: Sat, 24 Feb 2024 19:33:01 -0800
|
||||
Subject: [PATCH] check if itemstack is stackable first
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/player/Inventory.java b/src/main/java/net/minecraft/world/entity/player/Inventory.java
|
||||
index aaff1592876ac4a967e4fd47e4b6619a17d57867..ad82e5aeb565b23c3ec565fa60e1f31d1710bd4e 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/player/Inventory.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/player/Inventory.java
|
||||
@@ -110,7 +110,7 @@ public class Inventory implements Container, Nameable {
|
||||
}
|
||||
|
||||
private boolean hasRemainingSpaceForItem(ItemStack existingStack, ItemStack stack) {
|
||||
- return !existingStack.isEmpty() && ItemStack.isSameItemSameComponents(existingStack, stack) && existingStack.isStackable() && existingStack.getCount() < this.getMaxStackSize(existingStack);
|
||||
+ return !existingStack.isEmpty() && existingStack.isStackable() && existingStack.getCount() < this.getMaxStackSize(existingStack) && ItemStack.isSameItemSameComponents(existingStack, stack); // Paper - check if itemstack is stackable first
|
||||
}
|
||||
|
||||
// CraftBukkit start - Watch method above! :D
|
|
@ -0,0 +1,41 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake <jake.m.potrebic@gmail.com>
|
||||
Date: Sat, 15 Jun 2024 18:50:18 +0100
|
||||
Subject: [PATCH] Fix removing recipes from RecipeIterator
|
||||
|
||||
== AT ==
|
||||
public net.minecraft.world.item.crafting.RecipeManager byName
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/RecipeIterator.java b/src/main/java/org/bukkit/craftbukkit/inventory/RecipeIterator.java
|
||||
index 4e0f7564f04d5d566660a2623fb1b325e3b4e67c..39d2d67bf478beb4c72e41e6f59337893cf47e69 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/inventory/RecipeIterator.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/RecipeIterator.java
|
||||
@@ -9,6 +9,7 @@ import org.bukkit.inventory.Recipe;
|
||||
|
||||
public class RecipeIterator implements Iterator<Recipe> {
|
||||
private final Iterator<Map.Entry<RecipeType<?>, RecipeHolder<?>>> recipes;
|
||||
+ private Recipe currentRecipe; // Paper - fix removing recipes from RecipeIterator
|
||||
|
||||
public RecipeIterator() {
|
||||
this.recipes = MinecraftServer.getServer().getRecipeManager().recipes.byType.entries().iterator();
|
||||
@@ -21,11 +22,19 @@ public class RecipeIterator implements Iterator<Recipe> {
|
||||
|
||||
@Override
|
||||
public Recipe next() {
|
||||
- return this.recipes.next().getValue().toBukkitRecipe();
|
||||
+ // Paper start - fix removing recipes from RecipeIterator
|
||||
+ this.currentRecipe = this.recipes.next().getValue().toBukkitRecipe();
|
||||
+ return this.currentRecipe;
|
||||
+ // Paper end - fix removing recipes from RecipeIterator
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
+ // Paper start - fix removing recipes from RecipeIterator
|
||||
+ if (this.currentRecipe instanceof org.bukkit.Keyed keyed) {
|
||||
+ MinecraftServer.getServer().getRecipeManager().byName.remove(org.bukkit.craftbukkit.util.CraftNamespacedKey.toMinecraft(keyed.getKey()));
|
||||
+ }
|
||||
+ // Paper end - fix removing recipes from RecipeIterator
|
||||
this.recipes.remove();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Bjarne Koll <lynxplay101@gmail.com>
|
||||
Date: Thu, 13 Jun 2024 17:16:01 +0200
|
||||
Subject: [PATCH] Configurable damage tick when blocking with shield
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
index 5a992419f9847480ca6e431b5402d99ac411c15e..6195b207159c638e98a33c3142ed6b0720c8e14d 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
@@ -2488,7 +2488,7 @@ public abstract class LivingEntity extends Entity implements Attackable {
|
||||
CriteriaTriggers.PLAYER_HURT_ENTITY.trigger((ServerPlayer) damagesource.getEntity(), this, damagesource, originalDamage, f, true); // Paper - fix taken/dealt param order
|
||||
}
|
||||
|
||||
- return true;
|
||||
+ return !io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.skipVanillaDamageTickWhenShieldBlocked; // Paper - this should always return true, however expose an unsupported setting to flip this to false to enable "shield stunning".
|
||||
} else {
|
||||
return true; // Paper - return false ONLY if event was cancelled
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
Date: Thu, 8 Jun 2023 14:45:18 -0700
|
||||
Subject: [PATCH] Properly remove the experimental smithing inventory type
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftAbstractInventoryView.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftAbstractInventoryView.java
|
||||
index 149825642976124e852be9aef54a3cb4a8ac193d..71d3a5e5dc5630007cf46f4be3d39da4145dd431 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftAbstractInventoryView.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftAbstractInventoryView.java
|
||||
@@ -160,7 +160,6 @@ public abstract class CraftAbstractInventoryView implements InventoryView {
|
||||
type = InventoryType.SlotType.CRAFTING;
|
||||
break;
|
||||
case ANVIL:
|
||||
- case SMITHING:
|
||||
case CARTOGRAPHY:
|
||||
case GRINDSTONE:
|
||||
case MERCHANT:
|
||||
@@ -178,6 +177,7 @@ public abstract class CraftAbstractInventoryView implements InventoryView {
|
||||
}
|
||||
break;
|
||||
case LOOM:
|
||||
+ case SMITHING: // Paper - properly remove experimental smithing inventory
|
||||
case SMITHING_NEW:
|
||||
if (slot == 3) {
|
||||
type = InventoryType.SlotType.RESULT;
|
Loading…
Add table
Add a link
Reference in a new issue