A bunch more 637
This commit is contained in:
parent
cbf64163ba
commit
6456b5dea8
42 changed files with 128 additions and 128 deletions
|
@ -5,16 +5,17 @@ Subject: [PATCH] Option to prevent data components copy in smithing recipes
|
|||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/item/crafting/SmithingTransformRecipe.java b/src/main/java/net/minecraft/world/item/crafting/SmithingTransformRecipe.java
|
||||
index fa003ce16020eaab554bfd833ace779c8cefc617..d432b91b4051036d8b339a6418cdbce5c371bc1b 100644
|
||||
index fa003ce16020eaab554bfd833ace779c8cefc617..017748b26590364d846a5cddaa3490b2293ad276 100644
|
||||
--- a/src/main/java/net/minecraft/world/item/crafting/SmithingTransformRecipe.java
|
||||
+++ b/src/main/java/net/minecraft/world/item/crafting/SmithingTransformRecipe.java
|
||||
@@ -30,8 +30,14 @@ public class SmithingTransformRecipe implements SmithingRecipe {
|
||||
@@ -30,8 +30,15 @@ public class SmithingTransformRecipe implements SmithingRecipe {
|
||||
final ItemStack result;
|
||||
@Nullable
|
||||
private PlacementInfo placementInfo;
|
||||
+ final boolean copyDataComponents; // Paper - Option to prevent data components copy
|
||||
|
||||
public SmithingTransformRecipe(Optional<Ingredient> template, Optional<Ingredient> base, Optional<Ingredient> addition, ItemStack result) {
|
||||
+ // Paper start - Option to prevent data components copy
|
||||
+ this(template, base, addition, result, true);
|
||||
+ }
|
||||
+ public SmithingTransformRecipe(Optional<Ingredient> template, Optional<Ingredient> base, Optional<Ingredient> addition, ItemStack result, boolean copyDataComponents) {
|
||||
|
@ -23,7 +24,7 @@ index fa003ce16020eaab554bfd833ace779c8cefc617..d432b91b4051036d8b339a6418cdbce5
|
|||
this.template = template;
|
||||
this.base = base;
|
||||
this.addition = addition;
|
||||
@@ -41,7 +47,9 @@ public class SmithingTransformRecipe implements SmithingRecipe {
|
||||
@@ -41,7 +48,9 @@ public class SmithingTransformRecipe implements SmithingRecipe {
|
||||
public ItemStack assemble(SmithingRecipeInput input, HolderLookup.Provider registries) {
|
||||
ItemStack itemstack = input.base().transmuteCopy(this.result.getItem(), this.result.getCount());
|
||||
|
||||
|
@ -33,7 +34,7 @@ index fa003ce16020eaab554bfd833ace779c8cefc617..d432b91b4051036d8b339a6418cdbce5
|
|||
return itemstack;
|
||||
}
|
||||
|
||||
@@ -84,7 +92,7 @@ public class SmithingTransformRecipe implements SmithingRecipe {
|
||||
@@ -84,7 +93,7 @@ public class SmithingTransformRecipe implements SmithingRecipe {
|
||||
public Recipe toBukkitRecipe(NamespacedKey id) {
|
||||
CraftItemStack result = CraftItemStack.asCraftMirror(this.result);
|
||||
|
||||
|
|
|
@ -5,19 +5,10 @@ Subject: [PATCH] Fix issues with mob conversion
|
|||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/monster/Skeleton.java b/src/main/java/net/minecraft/world/entity/monster/Skeleton.java
|
||||
index 6f6454bcec7e0d1cefbf818fc2fc6eb90adeec83..6d176ab1eee654411918e0ee64306d280c7ae816 100644
|
||||
index 6f6454bcec7e0d1cefbf818fc2fc6eb90adeec83..3972e2ed0554e2550519e994888e068df0a151e5 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/monster/Skeleton.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/monster/Skeleton.java
|
||||
@@ -16,6 +16,8 @@ import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.Items;
|
||||
import net.minecraft.world.level.ItemLike;
|
||||
import net.minecraft.world.level.Level;
|
||||
+import org.bukkit.event.entity.CreatureSpawnEvent;
|
||||
+import org.bukkit.event.entity.EntityTransformEvent;
|
||||
|
||||
public class Skeleton extends AbstractSkeleton {
|
||||
|
||||
@@ -94,12 +96,19 @@ public class Skeleton extends AbstractSkeleton {
|
||||
@@ -94,12 +94,19 @@ public class Skeleton extends AbstractSkeleton {
|
||||
}
|
||||
|
||||
protected void doFreezeConversion() {
|
||||
|
@ -28,7 +19,7 @@ index 6f6454bcec7e0d1cefbf818fc2fc6eb90adeec83..6d176ab1eee654411918e0ee64306d28
|
|||
}
|
||||
|
||||
- }, org.bukkit.event.entity.EntityTransformEvent.TransformReason.FROZEN, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.FROZEN); // CraftBukkit - add spawn and transform reasons
|
||||
+ }, EntityTransformEvent.TransformReason.FROZEN, CreatureSpawnEvent.SpawnReason.FROZEN);// CraftBukkit - add spawn and transform reasons
|
||||
+ }, org.bukkit.event.entity.EntityTransformEvent.TransformReason.FROZEN, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.FROZEN);// CraftBukkit - add spawn and transform reasons
|
||||
+
|
||||
+ // Paper start - Fix issues with mob conversion; reset conversion time to prevent event spam
|
||||
+ if (stray == null) {
|
||||
|
|
|
@ -0,0 +1,343 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jason Penilla <11360596+jpenilla@users.noreply.github.com>
|
||||
Date: Mon, 16 Aug 2021 01:31:54 -0500
|
||||
Subject: [PATCH] Add '/paper mobcaps' and '/paper playermobcaps'
|
||||
|
||||
Add commands to get the mobcaps for a world, as well as the mobcaps for
|
||||
each player when per-player mob spawning is enabled.
|
||||
|
||||
Also has a hover text on each mob category listing what entity types are
|
||||
in said category
|
||||
|
||||
diff --git a/src/main/java/io/papermc/paper/command/PaperCommand.java b/src/main/java/io/papermc/paper/command/PaperCommand.java
|
||||
index cdad0fd5257ae842f83b9c1c98b4565b468d4f54..fd4f37711989431f997d77fb0917f8a9232ce53f 100644
|
||||
--- a/src/main/java/io/papermc/paper/command/PaperCommand.java
|
||||
+++ b/src/main/java/io/papermc/paper/command/PaperCommand.java
|
||||
@@ -40,6 +40,7 @@ public final class PaperCommand extends Command {
|
||||
commands.put(Set.of("dumpplugins"), new DumpPluginsCommand());
|
||||
commands.put(Set.of("syncloadinfo"), new SyncLoadInfoCommand());
|
||||
commands.put(Set.of("dumpitem"), new DumpItemCommand());
|
||||
+ commands.put(Set.of("mobcaps", "playermobcaps"), new MobcapsCommand());
|
||||
|
||||
return commands.entrySet().stream()
|
||||
.flatMap(entry -> entry.getKey().stream().map(s -> Map.entry(s, entry.getValue())))
|
||||
diff --git a/src/main/java/io/papermc/paper/command/subcommands/MobcapsCommand.java b/src/main/java/io/papermc/paper/command/subcommands/MobcapsCommand.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..d3b39d88a72ca25057fd8574d32f28db0d420818
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/command/subcommands/MobcapsCommand.java
|
||||
@@ -0,0 +1,229 @@
|
||||
+package io.papermc.paper.command.subcommands;
|
||||
+
|
||||
+import com.google.common.collect.ImmutableMap;
|
||||
+import io.papermc.paper.command.CommandUtil;
|
||||
+import io.papermc.paper.command.PaperSubcommand;
|
||||
+import java.util.ArrayList;
|
||||
+import java.util.Collections;
|
||||
+import java.util.List;
|
||||
+import java.util.Map;
|
||||
+import java.util.function.ToIntFunction;
|
||||
+import net.kyori.adventure.text.Component;
|
||||
+import net.kyori.adventure.text.ComponentLike;
|
||||
+import net.kyori.adventure.text.JoinConfiguration;
|
||||
+import net.kyori.adventure.text.TextComponent;
|
||||
+import net.kyori.adventure.text.format.NamedTextColor;
|
||||
+import net.kyori.adventure.text.format.TextColor;
|
||||
+import net.minecraft.core.registries.BuiltInRegistries;
|
||||
+import net.minecraft.server.level.ServerLevel;
|
||||
+import net.minecraft.server.level.ServerPlayer;
|
||||
+import net.minecraft.world.entity.MobCategory;
|
||||
+import net.minecraft.world.level.NaturalSpawner;
|
||||
+import org.bukkit.Bukkit;
|
||||
+import org.bukkit.World;
|
||||
+import org.bukkit.command.CommandSender;
|
||||
+import org.bukkit.craftbukkit.CraftWorld;
|
||||
+import org.bukkit.craftbukkit.entity.CraftPlayer;
|
||||
+import org.bukkit.entity.Player;
|
||||
+import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
+import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
+import org.checkerframework.framework.qual.DefaultQualifier;
|
||||
+
|
||||
+@DefaultQualifier(NonNull.class)
|
||||
+public final class MobcapsCommand implements PaperSubcommand {
|
||||
+ static final Map<MobCategory, TextColor> MOB_CATEGORY_COLORS = ImmutableMap.<MobCategory, TextColor>builder()
|
||||
+ .put(MobCategory.MONSTER, NamedTextColor.RED)
|
||||
+ .put(MobCategory.CREATURE, NamedTextColor.GREEN)
|
||||
+ .put(MobCategory.AMBIENT, NamedTextColor.GRAY)
|
||||
+ .put(MobCategory.AXOLOTLS, TextColor.color(0x7324FF))
|
||||
+ .put(MobCategory.UNDERGROUND_WATER_CREATURE, TextColor.color(0x3541E6))
|
||||
+ .put(MobCategory.WATER_CREATURE, TextColor.color(0x006EFF))
|
||||
+ .put(MobCategory.WATER_AMBIENT, TextColor.color(0x00B3FF))
|
||||
+ .put(MobCategory.MISC, TextColor.color(0x636363))
|
||||
+ .build();
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean execute(final CommandSender sender, final String subCommand, final String[] args) {
|
||||
+ switch (subCommand) {
|
||||
+ case "mobcaps" -> this.printMobcaps(sender, args);
|
||||
+ case "playermobcaps" -> this.printPlayerMobcaps(sender, args);
|
||||
+ }
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public List<String> tabComplete(final CommandSender sender, final String subCommand, final String[] args) {
|
||||
+ return switch (subCommand) {
|
||||
+ case "mobcaps" -> CommandUtil.getListMatchingLast(sender, args, this.suggestMobcaps(args));
|
||||
+ case "playermobcaps" -> CommandUtil.getListMatchingLast(sender, args, this.suggestPlayerMobcaps(sender, args));
|
||||
+ default -> throw new IllegalArgumentException();
|
||||
+ };
|
||||
+ }
|
||||
+
|
||||
+ private List<String> suggestMobcaps(final String[] args) {
|
||||
+ if (args.length == 1) {
|
||||
+ final List<String> worlds = new ArrayList<>(Bukkit.getWorlds().stream().map(World::getName).toList());
|
||||
+ worlds.add("*");
|
||||
+ return worlds;
|
||||
+ }
|
||||
+
|
||||
+ return Collections.emptyList();
|
||||
+ }
|
||||
+
|
||||
+ private List<String> suggestPlayerMobcaps(final CommandSender sender, final String[] args) {
|
||||
+ if (args.length == 1) {
|
||||
+ final List<String> list = new ArrayList<>();
|
||||
+ for (final Player player : Bukkit.getOnlinePlayers()) {
|
||||
+ if (!(sender instanceof Player senderPlayer) || senderPlayer.canSee(player)) {
|
||||
+ list.add(player.getName());
|
||||
+ }
|
||||
+ }
|
||||
+ return list;
|
||||
+ }
|
||||
+
|
||||
+ return Collections.emptyList();
|
||||
+ }
|
||||
+
|
||||
+ private void printMobcaps(final CommandSender sender, final String[] args) {
|
||||
+ final List<World> worlds;
|
||||
+ if (args.length == 0) {
|
||||
+ if (sender instanceof Player player) {
|
||||
+ worlds = List.of(player.getWorld());
|
||||
+ } else {
|
||||
+ sender.sendMessage(Component.text("Must specify a world! ex: '/paper mobcaps world'", NamedTextColor.RED));
|
||||
+ return;
|
||||
+ }
|
||||
+ } else if (args.length == 1) {
|
||||
+ final String input = args[0];
|
||||
+ if (input.equals("*")) {
|
||||
+ worlds = Bukkit.getWorlds();
|
||||
+ } else {
|
||||
+ final @Nullable World world = Bukkit.getWorld(input);
|
||||
+ if (world == null) {
|
||||
+ sender.sendMessage(Component.text("'" + input + "' is not a valid world!", NamedTextColor.RED));
|
||||
+ return;
|
||||
+ } else {
|
||||
+ worlds = List.of(world);
|
||||
+ }
|
||||
+ }
|
||||
+ } else {
|
||||
+ sender.sendMessage(Component.text("Too many arguments!", NamedTextColor.RED));
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ for (final World world : worlds) {
|
||||
+ final ServerLevel level = ((CraftWorld) world).getHandle();
|
||||
+ final NaturalSpawner.@Nullable SpawnState state = level.getChunkSource().getLastSpawnState();
|
||||
+
|
||||
+ final int chunks;
|
||||
+ if (state == null) {
|
||||
+ chunks = 0;
|
||||
+ } else {
|
||||
+ chunks = state.getSpawnableChunkCount();
|
||||
+ }
|
||||
+ sender.sendMessage(Component.join(JoinConfiguration.noSeparators(),
|
||||
+ Component.text("Mobcaps for world: "),
|
||||
+ Component.text(world.getName(), NamedTextColor.AQUA),
|
||||
+ Component.text(" (" + chunks + " spawnable chunks)")
|
||||
+ ));
|
||||
+
|
||||
+ sender.sendMessage(createMobcapsComponent(
|
||||
+ category -> {
|
||||
+ if (state == null) {
|
||||
+ return 0;
|
||||
+ } else {
|
||||
+ return state.getMobCategoryCounts().getOrDefault(category, 0);
|
||||
+ }
|
||||
+ },
|
||||
+ category -> NaturalSpawner.globalLimitForCategory(level, category, chunks)
|
||||
+ ));
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ private void printPlayerMobcaps(final CommandSender sender, final String[] args) {
|
||||
+ final @Nullable Player player;
|
||||
+ if (args.length == 0) {
|
||||
+ if (sender instanceof Player pl) {
|
||||
+ player = pl;
|
||||
+ } else {
|
||||
+ sender.sendMessage(Component.text("Must specify a player! ex: '/paper playermobcount playerName'", NamedTextColor.RED));
|
||||
+ return;
|
||||
+ }
|
||||
+ } else if (args.length == 1) {
|
||||
+ final String input = args[0];
|
||||
+ player = Bukkit.getPlayerExact(input);
|
||||
+ if (player == null) {
|
||||
+ sender.sendMessage(Component.text("Could not find player named '" + input + "'", NamedTextColor.RED));
|
||||
+ return;
|
||||
+ }
|
||||
+ } else {
|
||||
+ sender.sendMessage(Component.text("Too many arguments!", NamedTextColor.RED));
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ final ServerPlayer serverPlayer = ((CraftPlayer) player).getHandle();
|
||||
+ final ServerLevel level = serverPlayer.serverLevel();
|
||||
+
|
||||
+ if (!level.paperConfig().entities.spawning.perPlayerMobSpawns) {
|
||||
+ sender.sendMessage(Component.text("Use '/paper mobcaps' for worlds where per-player mob spawning is disabled.", NamedTextColor.RED));
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ sender.sendMessage(Component.join(JoinConfiguration.noSeparators(), Component.text("Mobcaps for player: "), Component.text(player.getName(), NamedTextColor.GREEN)));
|
||||
+ sender.sendMessage(createMobcapsComponent(
|
||||
+ category -> level.chunkSource.chunkMap.getMobCountNear(serverPlayer, category),
|
||||
+ category -> level.getWorld().getSpawnLimitUnsafe(org.bukkit.craftbukkit.util.CraftSpawnCategory.toBukkit(category))
|
||||
+ ));
|
||||
+ }
|
||||
+
|
||||
+ private static Component createMobcapsComponent(final ToIntFunction<MobCategory> countGetter, final ToIntFunction<MobCategory> limitGetter) {
|
||||
+ return MOB_CATEGORY_COLORS.entrySet().stream()
|
||||
+ .map(entry -> {
|
||||
+ final MobCategory category = entry.getKey();
|
||||
+ final TextColor color = entry.getValue();
|
||||
+
|
||||
+ final Component categoryHover = Component.join(JoinConfiguration.noSeparators(),
|
||||
+ Component.text("Entity types in category ", TextColor.color(0xE0E0E0)),
|
||||
+ Component.text(category.getName(), color),
|
||||
+ Component.text(':', NamedTextColor.GRAY),
|
||||
+ Component.newline(),
|
||||
+ Component.newline(),
|
||||
+ BuiltInRegistries.ENTITY_TYPE.entrySet().stream()
|
||||
+ .filter(it -> it.getValue().getCategory() == category)
|
||||
+ .map(it -> Component.translatable(it.getValue().getDescriptionId()))
|
||||
+ .collect(Component.toComponent(Component.text(", ", NamedTextColor.GRAY)))
|
||||
+ );
|
||||
+
|
||||
+ final Component categoryComponent = Component.text()
|
||||
+ .content(" " + category.getName())
|
||||
+ .color(color)
|
||||
+ .hoverEvent(categoryHover)
|
||||
+ .build();
|
||||
+
|
||||
+ final TextComponent.Builder builder = Component.text()
|
||||
+ .append(
|
||||
+ categoryComponent,
|
||||
+ Component.text(": ", NamedTextColor.GRAY)
|
||||
+ );
|
||||
+ final int limit = limitGetter.applyAsInt(category);
|
||||
+ if (limit != -1) {
|
||||
+ builder.append(
|
||||
+ Component.text(countGetter.applyAsInt(category)),
|
||||
+ Component.text("/", NamedTextColor.GRAY),
|
||||
+ Component.text(limit)
|
||||
+ );
|
||||
+ } else {
|
||||
+ builder.append(Component.text()
|
||||
+ .append(
|
||||
+ Component.text('n'),
|
||||
+ Component.text("/", NamedTextColor.GRAY),
|
||||
+ Component.text('a')
|
||||
+ )
|
||||
+ .hoverEvent(Component.text("This category does not naturally spawn.")));
|
||||
+ }
|
||||
+ return builder;
|
||||
+ })
|
||||
+ .map(ComponentLike::asComponent)
|
||||
+ .collect(Component.toComponent(Component.newline()));
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/net/minecraft/world/level/NaturalSpawner.java b/src/main/java/net/minecraft/world/level/NaturalSpawner.java
|
||||
index 485c6044d603f15878f9413a644a538dab68db3e..6eb69ebe688c1c52d5a5986dfc63cdd42e66687e 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/NaturalSpawner.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/NaturalSpawner.java
|
||||
@@ -174,6 +174,16 @@ public final class NaturalSpawner {
|
||||
gameprofilerfiller.pop();
|
||||
}
|
||||
|
||||
+ // Paper start - Add mobcaps commands
|
||||
+ public static int globalLimitForCategory(final ServerLevel level, final MobCategory category, final int spawnableChunkCount) {
|
||||
+ final int categoryLimit = level.getWorld().getSpawnLimitUnsafe(CraftSpawnCategory.toBukkit(category));
|
||||
+ if (categoryLimit < 1) {
|
||||
+ return categoryLimit;
|
||||
+ }
|
||||
+ return categoryLimit * spawnableChunkCount / NaturalSpawner.MAGIC_NUMBER;
|
||||
+ }
|
||||
+ // Paper end - Add mobcaps commands
|
||||
+
|
||||
public static void spawnCategoryForChunk(MobCategory group, ServerLevel world, LevelChunk chunk, NaturalSpawner.SpawnPredicate checker, NaturalSpawner.AfterSpawnCallback runner) {
|
||||
BlockPos blockposition = NaturalSpawner.getRandomPosWithin(world, chunk);
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
index 35e5a3dc58f93b85f93ec5301cc9b5c7505503bc..f69504676d2f48f3778f489ec1e08e2b3dec85cc 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
@@ -2335,6 +2335,11 @@ public final class CraftServer implements Server {
|
||||
|
||||
@Override
|
||||
public int getSpawnLimit(SpawnCategory spawnCategory) {
|
||||
+ // Paper start - Add mobcaps commands
|
||||
+ return this.getSpawnLimitUnsafe(spawnCategory);
|
||||
+ }
|
||||
+ public int getSpawnLimitUnsafe(final SpawnCategory spawnCategory) {
|
||||
+ // Paper end - Add mobcaps commands
|
||||
return this.spawnCategoryLimit.getOrDefault(spawnCategory, -1);
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
||||
index 890d3b648b1b991e351538088c06ed93686e35f5..0e5b673cee93525c1ba87d5b5e48def351ce8db8 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
||||
@@ -1728,9 +1728,14 @@ public class CraftWorld extends CraftRegionAccessor implements World {
|
||||
Preconditions.checkArgument(spawnCategory != null, "SpawnCategory cannot be null");
|
||||
Preconditions.checkArgument(CraftSpawnCategory.isValidForLimits(spawnCategory), "SpawnCategory.%s are not supported", spawnCategory);
|
||||
|
||||
+ // Paper start - Add mobcaps commands
|
||||
+ return this.getSpawnLimitUnsafe(spawnCategory);
|
||||
+ }
|
||||
+ public final int getSpawnLimitUnsafe(final SpawnCategory spawnCategory) {
|
||||
int limit = this.spawnCategoryLimit.getOrDefault(spawnCategory, -1);
|
||||
if (limit < 0) {
|
||||
- limit = this.server.getSpawnLimit(spawnCategory);
|
||||
+ limit = this.server.getSpawnLimitUnsafe(spawnCategory);
|
||||
+ // Paper end - Add mobcaps commands
|
||||
}
|
||||
return limit;
|
||||
}
|
||||
diff --git a/src/test/java/io/papermc/paper/command/subcommands/MobcapsCommandTest.java b/src/test/java/io/papermc/paper/command/subcommands/MobcapsCommandTest.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..6fdc77caa74845786c78a6ba087062b4d698cb82
|
||||
--- /dev/null
|
||||
+++ b/src/test/java/io/papermc/paper/command/subcommands/MobcapsCommandTest.java
|
||||
@@ -0,0 +1,22 @@
|
||||
+package io.papermc.paper.command.subcommands;
|
||||
+
|
||||
+import java.util.HashSet;
|
||||
+import java.util.Set;
|
||||
+import net.minecraft.world.entity.MobCategory;
|
||||
+import org.bukkit.support.environment.Normal;
|
||||
+import org.junit.jupiter.api.Assertions;
|
||||
+import org.junit.jupiter.api.Test;
|
||||
+
|
||||
+@Normal
|
||||
+public class MobcapsCommandTest {
|
||||
+ @Test
|
||||
+ public void testMobCategoryColors() {
|
||||
+ final Set<String> missing = new HashSet<>();
|
||||
+ for (final MobCategory value : MobCategory.values()) {
|
||||
+ if (!MobcapsCommand.MOB_CATEGORY_COLORS.containsKey(value)) {
|
||||
+ missing.add(value.getName());
|
||||
+ }
|
||||
+ }
|
||||
+ Assertions.assertTrue(missing.isEmpty(), "MobcapsCommand.MOB_CATEGORY_COLORS map missing TextColors for [" + String.join(", ", missing + "]"));
|
||||
+ }
|
||||
+}
|
|
@ -0,0 +1,28 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Nassim Jahnke <nassim@njahnke.dev>
|
||||
Date: Thu, 26 Aug 2021 12:09:47 +0200
|
||||
Subject: [PATCH] Sanitize ResourceLocation error logging
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/resources/ResourceLocation.java b/src/main/java/net/minecraft/resources/ResourceLocation.java
|
||||
index 262660d115a5d5cbecfbae995955a24283e666b0..87afe84791af2d5e9f869cd4c09eed4bb5fee75b 100644
|
||||
--- a/src/main/java/net/minecraft/resources/ResourceLocation.java
|
||||
+++ b/src/main/java/net/minecraft/resources/ResourceLocation.java
|
||||
@@ -247,7 +247,7 @@ public final class ResourceLocation implements Comparable<ResourceLocation> {
|
||||
|
||||
private static String assertValidNamespace(String namespace, String path) {
|
||||
if (!isValidNamespace(namespace)) {
|
||||
- throw new ResourceLocationException("Non [a-z0-9_.-] character in namespace of location: " + namespace + ":" + path);
|
||||
+ throw new ResourceLocationException("Non [a-z0-9_.-] character in namespace of location: " + org.apache.commons.lang3.StringUtils.normalizeSpace(namespace) + ":" + org.apache.commons.lang3.StringUtils.normalizeSpace(path)); // Paper - Sanitize ResourceLocation error logging
|
||||
} else {
|
||||
return namespace;
|
||||
}
|
||||
@@ -268,7 +268,7 @@ public final class ResourceLocation implements Comparable<ResourceLocation> {
|
||||
|
||||
private static String assertValidPath(String namespace, String path) {
|
||||
if (!isValidPath(path)) {
|
||||
- throw new ResourceLocationException("Non [a-z0-9/._-] character in path of location: " + namespace + ":" + path);
|
||||
+ throw new ResourceLocationException("Non [a-z0-9/._-] character in path of location: " + namespace + ":" + org.apache.commons.lang3.StringUtils.normalizeSpace(path)); // Paper - Sanitize ResourceLocation error logging
|
||||
} else {
|
||||
return path;
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
|
||||
Date: Mon, 6 Jul 2020 22:48:48 -0700
|
||||
Subject: [PATCH] Manually inline methods in BlockPosition
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/core/BlockPos.java b/src/main/java/net/minecraft/core/BlockPos.java
|
||||
index eea8bea0f40db8d36c59e628babf788fa920df94..0d51fb4be8b49e3b57c3c55aff6bcf13d5c78ddd 100644
|
||||
--- a/src/main/java/net/minecraft/core/BlockPos.java
|
||||
+++ b/src/main/java/net/minecraft/core/BlockPos.java
|
||||
@@ -576,9 +576,9 @@ public class BlockPos extends Vec3i {
|
||||
}
|
||||
|
||||
public BlockPos.MutableBlockPos set(int x, int y, int z) {
|
||||
- this.setX(x);
|
||||
- this.setY(y);
|
||||
- this.setZ(z);
|
||||
+ this.x = x; // Paper - Perf: Manually inline methods in BlockPosition
|
||||
+ this.y = y; // Paper - Perf: Manually inline methods in BlockPosition
|
||||
+ this.z = z; // Paper - Perf: Manually inline methods in BlockPosition
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -643,19 +643,19 @@ public class BlockPos extends Vec3i {
|
||||
|
||||
@Override
|
||||
public BlockPos.MutableBlockPos setX(int i) {
|
||||
- super.setX(i);
|
||||
+ this.x = i; // Paper - Perf: Manually inline methods in BlockPosition
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockPos.MutableBlockPos setY(int i) {
|
||||
- super.setY(i);
|
||||
+ this.y = i; // Paper - Perf: Manually inline methods in BlockPosition
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockPos.MutableBlockPos setZ(int i) {
|
||||
- super.setZ(i);
|
||||
+ this.z = i; // Paper - Perf: Manually inline methods in BlockPosition
|
||||
return this;
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/core/Vec3i.java b/src/main/java/net/minecraft/core/Vec3i.java
|
||||
index 7d5f99cac756c54e5922bf85d5d359edcc21f1e8..2f2bcc1b9b32e58bf70ae6c171177ceb333ed6cd 100644
|
||||
--- a/src/main/java/net/minecraft/core/Vec3i.java
|
||||
+++ b/src/main/java/net/minecraft/core/Vec3i.java
|
||||
@@ -16,9 +16,9 @@ public class Vec3i implements Comparable<Vec3i> {
|
||||
vec -> IntStream.of(vec.getX(), vec.getY(), vec.getZ())
|
||||
);
|
||||
public static final Vec3i ZERO = new Vec3i(0, 0, 0);
|
||||
- private int x;
|
||||
- private int y;
|
||||
- private int z;
|
||||
+ protected int x; // Paper - Perf: Manually inline methods in BlockPosition; protected
|
||||
+ protected int y; // Paper - Perf: Manually inline methods in BlockPosition; protected
|
||||
+ protected int z; // Paper - Perf: Manually inline methods in BlockPosition; protected
|
||||
|
||||
public static Codec<Vec3i> offsetCodec(int maxAbsValue) {
|
||||
return CODEC.validate(
|
|
@ -0,0 +1,33 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
|
||||
Date: Sun, 19 Jul 2020 15:17:01 -0700
|
||||
Subject: [PATCH] Name craft scheduler threads according to the plugin using
|
||||
them
|
||||
|
||||
Provides quick access to culprits running far more threads than
|
||||
they should be
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftAsyncTask.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftAsyncTask.java
|
||||
index 365b7e7c665bec357fb76d1479bf17da6f603590..e97f6b76ef2fe21c7c2eca8d4a707e5866d70de9 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftAsyncTask.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftAsyncTask.java
|
||||
@@ -25,7 +25,10 @@ class CraftAsyncTask extends CraftTask {
|
||||
@Override
|
||||
public void run() {
|
||||
final Thread thread = Thread.currentThread();
|
||||
- synchronized (this.workers) {
|
||||
+ // Paper start - name threads according to running plugin
|
||||
+ final String nameBefore = thread.getName();
|
||||
+ thread.setName(nameBefore + " - " + this.getOwner().getName());
|
||||
+ try { synchronized (this.workers) { // Paper end - name threads according to running plugin
|
||||
if (this.getPeriod() == CraftTask.CANCEL) {
|
||||
// Never continue running after cancelled.
|
||||
// Checking this with the lock is important!
|
||||
@@ -92,6 +95,7 @@ class CraftAsyncTask extends CraftTask {
|
||||
}
|
||||
}
|
||||
}
|
||||
+ } finally { thread.setName(nameBefore); } // Paper - name threads according to running plugin
|
||||
}
|
||||
|
||||
LinkedList<BukkitWorker> getWorkers() {
|
|
@ -0,0 +1,31 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
|
||||
Date: Sun, 20 Sep 2020 16:10:49 -0700
|
||||
Subject: [PATCH] Make sure inlined getChunkAt has inlined logic for loaded
|
||||
chunks
|
||||
|
||||
Tux did some profiling some time ago and showed that the
|
||||
previous getChunkAt method which had inlined logic for loaded
|
||||
chunks did get inlined, but the standard CPS.getChunkAt
|
||||
method was not inlined.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
|
||||
index 560777a99b58c4f82cc0e8fb087de04a564163b5..8269bf24f5e17f9e3936659aa0cbc9d4f95fb665 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/Level.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/Level.java
|
||||
@@ -352,7 +352,14 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
|
||||
|
||||
@Override
|
||||
public final LevelChunk getChunk(int chunkX, int chunkZ) { // Paper - final to help inline
|
||||
- return (LevelChunk) this.getChunk(chunkX, chunkZ, ChunkStatus.FULL, true); // Paper - avoid a method jump
|
||||
+ // Paper start - Perf: make sure loaded chunks get the inlined variant of this function
|
||||
+ net.minecraft.server.level.ServerChunkCache cps = ((ServerLevel)this).getChunkSource();
|
||||
+ LevelChunk ifLoaded = cps.getChunkAtIfLoadedImmediately(chunkX, chunkZ);
|
||||
+ if (ifLoaded != null) {
|
||||
+ return ifLoaded;
|
||||
+ }
|
||||
+ return (LevelChunk) cps.getChunk(chunkX, chunkZ, ChunkStatus.FULL, true); // Paper - avoid a method jump
|
||||
+ // Paper end - Perf: make sure loaded chunks get the inlined variant of this function
|
||||
}
|
||||
|
||||
// Paper start - if loaded
|
|
@ -0,0 +1,21 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
|
||||
Date: Sun, 11 Apr 2021 02:58:48 -0700
|
||||
Subject: [PATCH] Don't read neighbour chunk data off disk when converting
|
||||
chunks
|
||||
|
||||
Lighting is purged on update anyways, so let's not add more
|
||||
into the conversion process
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java
|
||||
index 909acbf5b8c6edcb4529647c11464d911d6f8c15..7d5e2e6e96ea9017334dddade54a9dcb37518642 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java
|
||||
@@ -47,6 +47,7 @@ public class ChunkStorage implements AutoCloseable {
|
||||
|
||||
// CraftBukkit start
|
||||
private boolean check(ServerChunkCache cps, int x, int z) {
|
||||
+ if (true) return true; // Paper - Perf: this isn't even needed anymore, light is purged updating to 1.14+, why are we holding up the conversion process reading chunk data off disk - return true, we need to set light populated to true so the converter recognizes the chunk as being "full"
|
||||
ChunkPos pos = new ChunkPos(x, z);
|
||||
if (cps != null) {
|
||||
com.google.common.base.Preconditions.checkState(org.bukkit.Bukkit.isPrimaryThread(), "primary thread");
|
|
@ -0,0 +1,26 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
|
||||
Date: Fri, 28 Aug 2020 12:33:47 -0700
|
||||
Subject: [PATCH] Don't lookup fluid state when raytracing, skip air blocks
|
||||
|
||||
Just use the iblockdata already retrieved, removes a getType call.
|
||||
|
||||
Also save approx. 5% for the raytrace call, as most (expensive)
|
||||
raytracing tends to go through air and returning early is an
|
||||
easy win. The remaining problems with this function
|
||||
are mostly with the block getting itself.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/BlockGetter.java b/src/main/java/net/minecraft/world/level/BlockGetter.java
|
||||
index 8e58efd0d8010a3499a1eb1add9fa976aa2b0a3e..cc9ae2122b563d7b583c7335d0a8ce227f9b1af4 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/BlockGetter.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/BlockGetter.java
|
||||
@@ -80,7 +80,8 @@ public interface BlockGetter extends LevelHeightAccessor {
|
||||
return BlockHitResult.miss(raytrace1.getTo(), Direction.getNearest(vec3d.x, vec3d.y, vec3d.z), BlockPos.containing(raytrace1.getTo()));
|
||||
}
|
||||
// Paper end - Prevent raytrace from loading chunks
|
||||
- FluidState fluid = this.getFluidState(blockposition);
|
||||
+ if (iblockdata.isAir()) return null; // Paper - Perf: optimise air cases
|
||||
+ FluidState fluid = iblockdata.getFluidState(); // Paper - Perf: don't need to go to world state again
|
||||
Vec3 vec3d = raytrace1.getFrom();
|
||||
Vec3 vec3d1 = raytrace1.getTo();
|
||||
VoxelShape voxelshape = raytrace1.getBlockShape(iblockdata, this, blockposition);
|
43
patches/server/0601-Time-scoreboard-search.patch
Normal file
43
patches/server/0601-Time-scoreboard-search.patch
Normal file
|
@ -0,0 +1,43 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
|
||||
Date: Tue, 21 Apr 2020 01:53:22 -0700
|
||||
Subject: [PATCH] Time scoreboard search
|
||||
|
||||
Plugins leaking scoreboards will make this very expensive,
|
||||
let server owners debug it easily
|
||||
|
||||
diff --git a/src/main/java/co/aikar/timings/MinecraftTimings.java b/src/main/java/co/aikar/timings/MinecraftTimings.java
|
||||
index e2764186bd6b838ed5cd86c15597a08d079ef984..6b3cde6d4d1e63bec01f502f2027ee9fddac08aa 100644
|
||||
--- a/src/main/java/co/aikar/timings/MinecraftTimings.java
|
||||
+++ b/src/main/java/co/aikar/timings/MinecraftTimings.java
|
||||
@@ -46,6 +46,7 @@ public final class MinecraftTimings {
|
||||
|
||||
public static final Timing antiXrayUpdateTimer = Timings.ofSafe("anti-xray - update");
|
||||
public static final Timing antiXrayObfuscateTimer = Timings.ofSafe("anti-xray - obfuscate");
|
||||
+ public static final Timing scoreboardScoreSearch = Timings.ofSafe("Scoreboard score search"); // Paper - add timings for scoreboard search
|
||||
|
||||
private static final Map<Class<?>, String> taskNameCache = new MapMaker().weakKeys().makeMap();
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboardManager.java b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboardManager.java
|
||||
index c7ca6210d6ae37fe95068c9baa5fb654f95307e0..cad42a0f3c016bf65181e50d139ae4e2fb9158a5 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboardManager.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboardManager.java
|
||||
@@ -113,9 +113,18 @@ public final class CraftScoreboardManager implements ScoreboardManager {
|
||||
|
||||
// CraftBukkit method
|
||||
public void forAllObjectives(ObjectiveCriteria criteria, ScoreHolder holder, Consumer<ScoreAccess> consumer) {
|
||||
+ // Paper start - add timings for scoreboard search
|
||||
+ // plugins leaking scoreboards will make this very expensive, let server owners debug it easily
|
||||
+ co.aikar.timings.MinecraftTimings.scoreboardScoreSearch.startTimingIfSync();
|
||||
+ try {
|
||||
+ // Paper end - add timings for scoreboard search
|
||||
for (CraftScoreboard scoreboard : this.scoreboards) {
|
||||
Scoreboard board = scoreboard.board;
|
||||
board.forAllObjectives(criteria, holder, (score) -> consumer.accept(score));
|
||||
}
|
||||
+ } finally { // Paper start - add timings for scoreboard search
|
||||
+ co.aikar.timings.MinecraftTimings.scoreboardScoreSearch.stopTimingIfSync();
|
||||
+ }
|
||||
+ // Paper end - add timings for scoreboard search
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
|
||||
Date: Fri, 19 Feb 2021 22:51:52 -0800
|
||||
Subject: [PATCH] Oprimise map impl for tracked players
|
||||
|
||||
Reference2BooleanOpenHashMap is going to have
|
||||
better lookups than HashMap.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
index 8121f7f5fb4dadb1c929b3d81121e3649981bfac..7f18146c0dea654c62b3e01e6848fd1c05f87946 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
@@ -1520,7 +1520,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
final Entity entity;
|
||||
private final int range;
|
||||
SectionPos lastSectionPos;
|
||||
- public final Set<ServerPlayerConnection> seenBy = Sets.newIdentityHashSet();
|
||||
+ public final Set<ServerPlayerConnection> seenBy = new it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet<>(); // Paper - Perf: optimise map impl
|
||||
|
||||
public TrackedEntity(final Entity entity, final int i, final int j, final boolean flag) {
|
||||
this.serverEntity = new ServerEntity(ChunkMap.this.level, entity, j, flag, this::broadcast, this.seenBy); // CraftBukkit
|
22
patches/server/0603-Add-missing-InventoryType.patch
Normal file
22
patches/server/0603-Add-missing-InventoryType.patch
Normal file
|
@ -0,0 +1,22 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
Date: Wed, 27 Dec 2023 16:46:07 -0800
|
||||
Subject: [PATCH] Add missing InventoryType
|
||||
|
||||
Upstream did not add a DECORATED_POT inventory type
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java
|
||||
index 3b0d3e9a067fccb10122c273aaf658ba240aa716..af1ae3dacb628da23f7d2988c6e76d3fb2d64103 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventory.java
|
||||
@@ -541,6 +541,10 @@ public class CraftInventory implements Inventory {
|
||||
return InventoryType.COMPOSTER;
|
||||
} else if (this.inventory instanceof JukeboxBlockEntity) {
|
||||
return InventoryType.JUKEBOX;
|
||||
+ // Paper start
|
||||
+ } else if (this.inventory instanceof net.minecraft.world.level.block.entity.DecoratedPotBlockEntity) {
|
||||
+ return org.bukkit.event.inventory.InventoryType.DECORATED_POT;
|
||||
+ // Paper end
|
||||
} else {
|
||||
return InventoryType.CHEST;
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
|
||||
Date: Thu, 10 Jun 2021 14:36:00 -0700
|
||||
Subject: [PATCH] Optimise BlockSoil nearby water lookup
|
||||
|
||||
Apparently the abstract block iteration was taking about
|
||||
75% of the method call.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/FarmBlock.java b/src/main/java/net/minecraft/world/level/block/FarmBlock.java
|
||||
index a87f8345aa5520a867a8dd769b43526b20b8c16a..c3dba0c2c94f3804338f86621dc42405e380a6b3 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/FarmBlock.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/FarmBlock.java
|
||||
@@ -154,19 +154,28 @@ public class FarmBlock extends Block {
|
||||
}
|
||||
|
||||
private static boolean isNearWater(LevelReader world, BlockPos pos) {
|
||||
- Iterator iterator = BlockPos.betweenClosed(pos.offset(-4, 0, -4), pos.offset(4, 1, 4)).iterator();
|
||||
-
|
||||
- BlockPos blockposition1;
|
||||
-
|
||||
- do {
|
||||
- if (!iterator.hasNext()) {
|
||||
- return false;
|
||||
+ // Paper start - Perf: remove abstract block iteration
|
||||
+ int xOff = pos.getX();
|
||||
+ int yOff = pos.getY();
|
||||
+ int zOff = pos.getZ();
|
||||
+
|
||||
+ for (int dz = -4; dz <= 4; ++dz) {
|
||||
+ int z = dz + zOff;
|
||||
+ for (int dx = -4; dx <= 4; ++dx) {
|
||||
+ int x = xOff + dx;
|
||||
+ for (int dy = 0; dy <= 1; ++dy) {
|
||||
+ int y = dy + yOff;
|
||||
+ net.minecraft.world.level.chunk.LevelChunk chunk = (net.minecraft.world.level.chunk.LevelChunk)world.getChunk(x >> 4, z >> 4);
|
||||
+ net.minecraft.world.level.material.FluidState fluid = chunk.getBlockStateFinal(x, y, z).getFluidState();
|
||||
+ if (fluid.is(FluidTags.WATER)) {
|
||||
+ return true;
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
+ }
|
||||
|
||||
- blockposition1 = (BlockPos) iterator.next();
|
||||
- } while (!world.getFluidState(blockposition1).is(FluidTags.WATER));
|
||||
-
|
||||
- return true;
|
||||
+ return false;
|
||||
+ // Paper end - Perf: remove abstract block iteration
|
||||
}
|
||||
|
||||
@Override
|
|
@ -0,0 +1,22 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
Date: Thu, 2 Sep 2021 00:24:06 -0700
|
||||
Subject: [PATCH] Fix merchant inventory not closing on entity removal
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
index cf2b5de61eae020513c50e0903637c55b711fd1b..0fbd077c1d3dddc97c8c99effa936470562b02a4 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
@@ -2328,6 +2328,11 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
||||
// Spigot end
|
||||
// Spigot Start
|
||||
if (entity.getBukkitEntity() instanceof org.bukkit.inventory.InventoryHolder && (!(entity instanceof ServerPlayer) || entity.getRemovalReason() != Entity.RemovalReason.KILLED)) { // SPIGOT-6876: closeInventory clears death message
|
||||
+ // Paper start - Fix merchant inventory not closing on entity removal
|
||||
+ if (entity.getBukkitEntity() instanceof org.bukkit.inventory.Merchant merchant && merchant.getTrader() != null) {
|
||||
+ merchant.getTrader().closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.UNLOADED);
|
||||
+ }
|
||||
+ // Paper end - Fix merchant inventory not closing on entity removal
|
||||
for (org.bukkit.entity.HumanEntity h : Lists.newArrayList(((org.bukkit.inventory.InventoryHolder) entity.getBukkitEntity()).getInventory().getViewers())) {
|
||||
h.closeInventory(org.bukkit.event.inventory.InventoryCloseEvent.Reason.UNLOADED); // Paper - Inventory close reason
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: stonar96 <minecraft.stonar96@gmail.com>
|
||||
Date: Sun, 12 Sep 2021 00:14:21 +0200
|
||||
Subject: [PATCH] Check requirement before suggesting root nodes
|
||||
|
||||
Child nodes are handled by CommandDispatcher#parse checking
|
||||
requirements.
|
||||
|
||||
Vanilla clients only send ServerboundCommandSuggestionPacket when
|
||||
encountering a command node with ASK_SERVER suggestions, however a
|
||||
modified client can send this packet whenever it wants.
|
||||
|
||||
diff --git a/src/main/java/com/mojang/brigadier/CommandDispatcher.java b/src/main/java/com/mojang/brigadier/CommandDispatcher.java
|
||||
index 858e41fba7dc285dd21a93f3918cc5de3887df5f..92848b64a78fce7a92e1657c2da6fc5ee53eea44 100644
|
||||
--- a/src/main/java/com/mojang/brigadier/CommandDispatcher.java
|
||||
+++ b/src/main/java/com/mojang/brigadier/CommandDispatcher.java
|
||||
@@ -538,10 +538,14 @@ public class CommandDispatcher<S> {
|
||||
int i = 0;
|
||||
for (final CommandNode<S> node : parent.getChildren()) {
|
||||
CompletableFuture<Suggestions> future = Suggestions.empty();
|
||||
+ // Paper start - Don't suggest if the requirement isn't met
|
||||
+ if (parent != this.root || node.canUse(context.getSource())) {
|
||||
try {
|
||||
- if (node.canUse(parse.getContext().getSource())) future = node.listSuggestions(context.build(truncatedInput), new SuggestionsBuilder(truncatedInput, truncatedInputLowerCase, start)); // CraftBukkit
|
||||
+ future = node.listSuggestions(context.build(truncatedInput), new SuggestionsBuilder(truncatedInput, truncatedInputLowerCase, start)); // CraftBukkit
|
||||
} catch (final CommandSyntaxException ignored) {
|
||||
}
|
||||
+ }
|
||||
+ // Paper end - Don't suggest if the requirement isn't met
|
||||
futures[i++] = future;
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: stonar96 <minecraft.stonar96@gmail.com>
|
||||
Date: Sun, 12 Sep 2021 00:14:21 +0200
|
||||
Subject: [PATCH] Don't respond to ServerboundCommandSuggestionPacket when
|
||||
tab-complete is disabled
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
index 020aed78c0eb1fdb9fd0d633bf2fe45bb9eb7532..7b858178ce7d0e33fec17311f1710bead5f0837d 100644
|
||||
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
@@ -752,6 +752,11 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
|
||||
return;
|
||||
}
|
||||
// CraftBukkit end
|
||||
+ // Paper start - Don't suggest if tab-complete is disabled
|
||||
+ if (org.spigotmc.SpigotConfig.tabComplete < 0) {
|
||||
+ return;
|
||||
+ }
|
||||
+ // Paper end - Don't suggest if tab-complete is disabled
|
||||
// Paper start - AsyncTabCompleteEvent
|
||||
TAB_COMPLETE_EXECUTOR.execute(() -> this.handleCustomCommandSuggestions0(packet));
|
||||
}
|
108
patches/server/0608-Add-packet-limiter-config.patch
Normal file
108
patches/server/0608-Add-packet-limiter-config.patch
Normal file
|
@ -0,0 +1,108 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
|
||||
Date: Fri, 30 Oct 2020 22:37:16 -0700
|
||||
Subject: [PATCH] Add packet limiter config
|
||||
|
||||
Example config:
|
||||
packet-limiter:
|
||||
kick-message: '&cSent too many packets'
|
||||
limits:
|
||||
all:
|
||||
interval: 7.0
|
||||
max-packet-rate: 500.0
|
||||
ServerboundPlaceRecipePacket:
|
||||
interval: 4.0
|
||||
max-packet-rate: 5.0
|
||||
action: DROP
|
||||
|
||||
all section refers to all incoming packets, the action for all is
|
||||
hard coded to KICK.
|
||||
|
||||
For specific limits, the section name is the class's name,
|
||||
and an action can be defined: DROP or KICK
|
||||
|
||||
If interval or rate are less-than 0, the limit is ignored
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/network/Connection.java b/src/main/java/net/minecraft/network/Connection.java
|
||||
index 2b86415e4ea197c5c44c23072c9a1cda595544a8..4d9f1fc884050993287adfa4578a87da710623fb 100644
|
||||
--- a/src/main/java/net/minecraft/network/Connection.java
|
||||
+++ b/src/main/java/net/minecraft/network/Connection.java
|
||||
@@ -137,6 +137,22 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
|
||||
return null;
|
||||
}
|
||||
// Paper end - add utility methods
|
||||
+ // Paper start - packet limiter
|
||||
+ protected final Object PACKET_LIMIT_LOCK = new Object();
|
||||
+ protected final @Nullable io.papermc.paper.util.IntervalledCounter allPacketCounts = io.papermc.paper.configuration.GlobalConfiguration.get().packetLimiter.allPackets.isEnabled() ? new io.papermc.paper.util.IntervalledCounter(
|
||||
+ (long)(io.papermc.paper.configuration.GlobalConfiguration.get().packetLimiter.allPackets.interval() * 1.0e9)
|
||||
+ ) : null;
|
||||
+ protected final java.util.Map<Class<? extends net.minecraft.network.protocol.Packet<?>>, io.papermc.paper.util.IntervalledCounter> packetSpecificLimits = new java.util.HashMap<>();
|
||||
+
|
||||
+ private boolean stopReadingPackets;
|
||||
+ private void killForPacketSpam() {
|
||||
+ this.sendPacket(new ClientboundDisconnectPacket(io.papermc.paper.adventure.PaperAdventure.asVanilla(io.papermc.paper.configuration.GlobalConfiguration.get().packetLimiter.kickMessage)), PacketSendListener.thenRun(() -> {
|
||||
+ this.disconnect(io.papermc.paper.adventure.PaperAdventure.asVanilla(io.papermc.paper.configuration.GlobalConfiguration.get().packetLimiter.kickMessage));
|
||||
+ }), true);
|
||||
+ this.setReadOnly();
|
||||
+ this.stopReadingPackets = true;
|
||||
+ }
|
||||
+ // Paper end - packet limiter
|
||||
|
||||
public Connection(PacketFlow side) {
|
||||
this.receiving = side;
|
||||
@@ -215,6 +231,55 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
|
||||
if (packetlistener == null) {
|
||||
throw new IllegalStateException("Received a packet before the packet listener was initialized");
|
||||
} else {
|
||||
+ // Paper start - packet limiter
|
||||
+ if (this.stopReadingPackets) {
|
||||
+ return;
|
||||
+ }
|
||||
+ if (this.allPacketCounts != null ||
|
||||
+ io.papermc.paper.configuration.GlobalConfiguration.get().packetLimiter.overrides.containsKey(packet.getClass())) {
|
||||
+ long time = System.nanoTime();
|
||||
+ synchronized (PACKET_LIMIT_LOCK) {
|
||||
+ if (this.allPacketCounts != null) {
|
||||
+ this.allPacketCounts.updateAndAdd(1, time);
|
||||
+ if (this.allPacketCounts.getRate() >= io.papermc.paper.configuration.GlobalConfiguration.get().packetLimiter.allPackets.maxPacketRate()) {
|
||||
+ this.killForPacketSpam();
|
||||
+ return;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ for (Class<?> check = packet.getClass(); check != Object.class; check = check.getSuperclass()) {
|
||||
+ io.papermc.paper.configuration.GlobalConfiguration.PacketLimiter.PacketLimit packetSpecificLimit =
|
||||
+ io.papermc.paper.configuration.GlobalConfiguration.get().packetLimiter.overrides.get(check);
|
||||
+ if (packetSpecificLimit == null || !packetSpecificLimit.isEnabled()) {
|
||||
+ continue;
|
||||
+ }
|
||||
+ io.papermc.paper.util.IntervalledCounter counter = this.packetSpecificLimits.computeIfAbsent((Class)check, (clazz) -> {
|
||||
+ return new io.papermc.paper.util.IntervalledCounter((long)(packetSpecificLimit.interval() * 1.0e9));
|
||||
+ });
|
||||
+ counter.updateAndAdd(1, time);
|
||||
+ if (counter.getRate() >= packetSpecificLimit.maxPacketRate()) {
|
||||
+ switch (packetSpecificLimit.action()) {
|
||||
+ case DROP:
|
||||
+ return;
|
||||
+ case KICK:
|
||||
+ String deobfedPacketName = io.papermc.paper.util.ObfHelper.INSTANCE.deobfClassName(check.getName());
|
||||
+
|
||||
+ String playerName;
|
||||
+ if (this.packetListener instanceof net.minecraft.server.network.ServerCommonPacketListenerImpl impl) {
|
||||
+ playerName = impl.getOwner().getName();
|
||||
+ } else {
|
||||
+ playerName = this.getLoggableAddress(net.minecraft.server.MinecraftServer.getServer().logIPs());
|
||||
+ }
|
||||
+
|
||||
+ Connection.LOGGER.warn("{} kicked for packet spamming: {}", playerName, deobfedPacketName.substring(deobfedPacketName.lastIndexOf(".") + 1));
|
||||
+ this.killForPacketSpam();
|
||||
+ return;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end - packet limiter
|
||||
if (packetlistener.shouldHandleMessage(packet)) {
|
||||
try {
|
||||
Connection.genericsFtw(packet, packetlistener);
|
|
@ -0,0 +1,72 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Bjarne Koll <lynxplay101@gmail.com>
|
||||
Date: Sat, 6 Nov 2021 23:15:20 +0100
|
||||
Subject: [PATCH] Fix setPatternColor on tropical fish bucket meta
|
||||
|
||||
Prior to this commit, the tropical fish bucket meta would set the body
|
||||
color to the previous metas pattern colour when updating the pattern
|
||||
colour.
|
||||
|
||||
This commit hence simply fixes this by using the proper body colour
|
||||
value when updating the pattern color.
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaTropicalFishBucket.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaTropicalFishBucket.java
|
||||
index 8169d08c1bccf7c9896bb083eba388f918fac6c9..a514fe98d3d2b65d2cfd029079c69189bcb99c01 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaTropicalFishBucket.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaTropicalFishBucket.java
|
||||
@@ -128,7 +128,7 @@ class CraftMetaTropicalFishBucket extends CraftMetaItem implements TropicalFishB
|
||||
if (this.variant == null) {
|
||||
this.variant = 0;
|
||||
}
|
||||
- this.variant = CraftTropicalFish.getData(color, this.getPatternColor(), this.getPattern());
|
||||
+ this.variant = CraftTropicalFish.getData(color, this.getBodyColor(), this.getPattern()); // Paper - properly set tropical fish pattern color without mutating body color
|
||||
}
|
||||
|
||||
@Override
|
||||
diff --git a/src/test/java/io/papermc/paper/inventory/CraftMetaTropicalFishBucketTest.java b/src/test/java/io/papermc/paper/inventory/CraftMetaTropicalFishBucketTest.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..68a557cedbffb41f27ba21096e2ae5eebbf13f5c
|
||||
--- /dev/null
|
||||
+++ b/src/test/java/io/papermc/paper/inventory/CraftMetaTropicalFishBucketTest.java
|
||||
@@ -0,0 +1,41 @@
|
||||
+package io.papermc.paper.inventory;
|
||||
+
|
||||
+import org.bukkit.DyeColor;
|
||||
+import org.bukkit.Material;
|
||||
+import org.bukkit.entity.TropicalFish;
|
||||
+import org.bukkit.inventory.ItemStack;
|
||||
+import org.bukkit.inventory.meta.TropicalFishBucketMeta;
|
||||
+import org.bukkit.support.environment.AllFeatures;
|
||||
+import org.junit.jupiter.api.Assertions;
|
||||
+import org.junit.jupiter.api.Test;
|
||||
+
|
||||
+@AllFeatures
|
||||
+public class CraftMetaTropicalFishBucketTest {
|
||||
+
|
||||
+ @Test
|
||||
+ public void testAllCombinations() {
|
||||
+ final var rawMeta = new ItemStack(Material.TROPICAL_FISH_BUCKET).getItemMeta();
|
||||
+ Assertions.assertTrue(rawMeta instanceof TropicalFishBucketMeta, "Meta was not a tropical fish bucket");
|
||||
+
|
||||
+ final var meta = (TropicalFishBucketMeta) rawMeta;
|
||||
+
|
||||
+ for (final var bodyColor : DyeColor.values()) {
|
||||
+ for (final var pattern : TropicalFish.Pattern.values()) {
|
||||
+ for (final var patternColor : DyeColor.values()) {
|
||||
+ meta.setBodyColor(bodyColor);
|
||||
+ Assertions.assertEquals(bodyColor, meta.getBodyColor(), "Body color did not match post body color!");
|
||||
+
|
||||
+ meta.setPattern(pattern);
|
||||
+ Assertions.assertEquals(pattern, meta.getPattern(), "Pattern did not match post pattern!");
|
||||
+ Assertions.assertEquals(bodyColor, meta.getBodyColor(), "Body color did not match post pattern!");
|
||||
+
|
||||
+ meta.setPatternColor(patternColor);
|
||||
+ Assertions.assertEquals(pattern, meta.getPattern(), "Pattern did not match post pattern color!");
|
||||
+ Assertions.assertEquals(bodyColor, meta.getBodyColor(), "Body color did not match post pattern color!");
|
||||
+ Assertions.assertEquals(patternColor, meta.getPatternColor(), "Pattern color did not match post pattern color!");
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+}
|
19
patches/server/0610-Ensure-valid-vehicle-status.patch
Normal file
19
patches/server/0610-Ensure-valid-vehicle-status.patch
Normal file
|
@ -0,0 +1,19 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Nassim Jahnke <nassim@njahnke.dev>
|
||||
Date: Tue, 28 Sep 2021 09:47:47 +0200
|
||||
Subject: [PATCH] Ensure valid vehicle status
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
index d2fbbdbb451d6c54d847b4ba125397ad41c4f7b4..f72ab5e4e743cb0758ebca28e81f97c143c91b42 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
@@ -698,7 +698,7 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player {
|
||||
}
|
||||
}
|
||||
|
||||
- if (persistVehicle && entity1 != null && entity != this && entity.hasExactlyOnePlayerPassenger()) {
|
||||
+ if (persistVehicle && entity1 != null && entity != this && entity.hasExactlyOnePlayerPassenger() && !entity.isRemoved()) { // Paper - Ensure valid vehicle status
|
||||
// CraftBukkit end
|
||||
CompoundTag nbttagcompound1 = new CompoundTag();
|
||||
CompoundTag nbttagcompound2 = new CompoundTag();
|
|
@ -0,0 +1,22 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Noah van der Aa <ndvdaa@gmail.com>
|
||||
Date: Mon, 30 Aug 2021 15:22:18 +0200
|
||||
Subject: [PATCH] Prevent softlocked end exit portal generation
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java
|
||||
index 3d1a49d865e17a61ff74c6fe0efbd908447ee730..8d0014b0db5ab42321150938fef98458fee84b17 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/dimension/end/EndDragonFight.java
|
||||
@@ -469,6 +469,11 @@ public class EndDragonFight {
|
||||
}
|
||||
}
|
||||
|
||||
+ // Paper start - Prevent "softlocked" exit portal generation
|
||||
+ if (this.portalLocation.getY() <= this.level.getMinBuildHeight()) {
|
||||
+ this.portalLocation = this.portalLocation.atY(this.level.getMinBuildHeight() + 1);
|
||||
+ }
|
||||
+ // Paper end - Prevent "softlocked" exit portal generation
|
||||
if (worldgenendtrophy.place(FeatureConfiguration.NONE, this.level, this.level.getChunkSource().getGenerator(), RandomSource.create(), this.portalLocation)) {
|
||||
int i = Mth.positiveCeilDiv(4, 16);
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Shane Freeder <theboyetronic@gmail.com>
|
||||
Date: Tue, 7 Sep 2021 21:29:38 +0100
|
||||
Subject: [PATCH] Fix CocaoDecorator causing a crash when trying to generate
|
||||
without logs
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/levelgen/feature/treedecorators/CocoaDecorator.java b/src/main/java/net/minecraft/world/level/levelgen/feature/treedecorators/CocoaDecorator.java
|
||||
index 1b59f530840a2a490e295f73db90ab266b27712f..f924f09aaf5d8fd643f86d826ab053dbe861369e 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/levelgen/feature/treedecorators/CocoaDecorator.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/levelgen/feature/treedecorators/CocoaDecorator.java
|
||||
@@ -26,6 +26,7 @@ public class CocoaDecorator extends TreeDecorator {
|
||||
|
||||
@Override
|
||||
public void place(TreeDecorator.Context generator) {
|
||||
+ if (generator.logs().isEmpty()) return; // Paper - Fix crash when trying to generate without logs
|
||||
RandomSource randomSource = generator.random();
|
||||
if (!(randomSource.nextFloat() >= this.probability)) {
|
||||
List<BlockPos> list = generator.logs();
|
|
@ -0,0 +1,19 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Noah van der Aa <ndvdaa@gmail.com>
|
||||
Date: Tue, 14 Sep 2021 16:24:45 +0200
|
||||
Subject: [PATCH] Don't log debug logging being disabled
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/spigotmc/SpigotConfig.java b/src/main/java/org/spigotmc/SpigotConfig.java
|
||||
index 85f3433860abd91a89961907940a807a8b190a46..4dbb109d0526afee99b9190fc256585121aac9b5 100644
|
||||
--- a/src/main/java/org/spigotmc/SpigotConfig.java
|
||||
+++ b/src/main/java/org/spigotmc/SpigotConfig.java
|
||||
@@ -381,7 +381,7 @@ public class SpigotConfig
|
||||
Bukkit.getLogger().info( "Debug logging is enabled" );
|
||||
} else
|
||||
{
|
||||
- Bukkit.getLogger().info( "Debug logging is disabled" );
|
||||
+ // Bukkit.getLogger().info( "Debug logging is disabled" ); // Paper - Don't log if debug logging isn't enabled.
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
Date: Sun, 11 Jul 2021 12:52:56 -0700
|
||||
Subject: [PATCH] fix various menus with empty level accesses
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/inventory/ContainerLevelAccess.java b/src/main/java/net/minecraft/world/inventory/ContainerLevelAccess.java
|
||||
index c96b04f045dda384cdee9254a1765ef97e5f7f03..85e336637db8643fc5aca1dba724c9b341cbf46f 100644
|
||||
--- a/src/main/java/net/minecraft/world/inventory/ContainerLevelAccess.java
|
||||
+++ b/src/main/java/net/minecraft/world/inventory/ContainerLevelAccess.java
|
||||
@@ -27,6 +27,12 @@ public interface ContainerLevelAccess {
|
||||
public <T> Optional<T> evaluate(BiFunction<Level, BlockPos, T> getter) {
|
||||
return Optional.empty();
|
||||
}
|
||||
+ // Paper start - fix menus with empty level accesses
|
||||
+ @Override
|
||||
+ public org.bukkit.Location getLocation() {
|
||||
+ return null;
|
||||
+ }
|
||||
+ // Paper end - fix menus with empty level accesses
|
||||
};
|
||||
|
||||
static ContainerLevelAccess create(final Level world, final BlockPos pos) {
|
27
patches/server/0615-Preserve-overstacked-loot.patch
Normal file
27
patches/server/0615-Preserve-overstacked-loot.patch
Normal file
|
@ -0,0 +1,27 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: lexikiq <noellekiq@gmail.com>
|
||||
Date: Mon, 21 Jun 2021 23:21:58 -0400
|
||||
Subject: [PATCH] Preserve overstacked loot
|
||||
|
||||
Preserves overstacked items in loot tables, such as shulker box drops, to prevent the items
|
||||
from being deleted (as they'd overflow past the bounds of the container)-- or worse, causing
|
||||
chunk bans via the large amount of NBT created by unstacking the items.
|
||||
|
||||
Fixes GH-5140 and GH-4748.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/storage/loot/LootTable.java b/src/main/java/net/minecraft/world/level/storage/loot/LootTable.java
|
||||
index 4d4d413b8527e1a109276928611b8c857ad6f6aa..c2bded5094097f5615a2ddb0718942486ede93b5 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/storage/loot/LootTable.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/storage/loot/LootTable.java
|
||||
@@ -72,9 +72,10 @@ public class LootTable {
|
||||
}
|
||||
|
||||
public static Consumer<ItemStack> createStackSplitter(ServerLevel world, Consumer<ItemStack> consumer) {
|
||||
+ boolean skipSplitter = world != null && !world.paperConfig().fixes.splitOverstackedLoot; // Paper - preserve overstacked items
|
||||
return (itemstack) -> {
|
||||
if (itemstack.isItemEnabled(world.enabledFeatures())) {
|
||||
- if (itemstack.getCount() < itemstack.getMaxStackSize()) {
|
||||
+ if (skipSplitter || itemstack.getCount() < itemstack.getMaxStackSize()) { // Paper - preserve overstacked items
|
||||
consumer.accept(itemstack);
|
||||
} else {
|
||||
int i = itemstack.getCount();
|
|
@ -0,0 +1,29 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com>
|
||||
Date: Mon, 21 Jun 2021 21:55:23 -0400
|
||||
Subject: [PATCH] Update head rotation in missing places
|
||||
|
||||
In certain areas the player's head rotation could be desynced when teleported/moved.
|
||||
This is because bukkit uses a separate head rotation field for yaw.
|
||||
This issue only applies to players.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
index 92c743a354e95c8e12fc21673ee172aed07fe1fb..b54dcebbd5d2f920efcf91ff2de485493dd2f487 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
@@ -1914,6 +1914,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
|
||||
this.setXRot(Mth.clamp(pitch, -90.0F, 90.0F) % 360.0F);
|
||||
this.yRotO = this.getYRot();
|
||||
this.xRotO = this.getXRot();
|
||||
+ this.setYHeadRot(yaw); // Paper - Update head rotation
|
||||
}
|
||||
|
||||
public void absMoveTo(double x, double y, double z) {
|
||||
@@ -1956,6 +1957,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
|
||||
this.setXRot(pitch);
|
||||
this.setOldPosAndRot();
|
||||
this.reapplyPosition();
|
||||
+ this.setYHeadRot(yaw); // Paper - Update head rotation
|
||||
}
|
||||
|
||||
public final void setOldPosAndRot() {
|
|
@ -0,0 +1,25 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
Date: Mon, 13 Sep 2021 18:55:45 -0700
|
||||
Subject: [PATCH] prevent unintended light block manipulation
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/LightBlock.java b/src/main/java/net/minecraft/world/level/block/LightBlock.java
|
||||
index 6c3ca57a29d3c5ad1add1cf2f707b930dfc422ea..71a1a152dca41ba9100bd38efd6758a42bab9f5d 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/LightBlock.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/LightBlock.java
|
||||
@@ -50,6 +50,14 @@ public class LightBlock extends Block implements SimpleWaterloggedBlock {
|
||||
builder.add(LEVEL, WATERLOGGED);
|
||||
}
|
||||
|
||||
+ // Paper start - prevent unintended light block manipulation
|
||||
+ @Override
|
||||
+ protected net.minecraft.world.ItemInteractionResult useItemOn(final ItemStack stack, final BlockState state, final Level world, final BlockPos pos, final Player player, final net.minecraft.world.InteractionHand hand, final BlockHitResult hit) {
|
||||
+ if (player.getItemInHand(hand).getItem() != Items.LIGHT || !player.mayInteract(world, pos) || !player.mayUseItemAt(pos, hit.getDirection(), player.getItemInHand(hand))) { return net.minecraft.world.ItemInteractionResult.SKIP_DEFAULT_BLOCK_INTERACTION; } // Paper - Prevent unintended light block manipulation
|
||||
+ return super.useItemOn(stack, state, world, pos, player, hand, hit);
|
||||
+ }
|
||||
+ // Paper end - prevent unintended light block manipulation
|
||||
+
|
||||
@Override
|
||||
protected InteractionResult useWithoutItem(BlockState state, Level world, BlockPos pos, Player player, BlockHitResult hit) {
|
||||
if (!world.isClientSide && player.canUseGameMasterBlocks()) {
|
19
patches/server/0618-Fix-CraftCriteria-defaults-map.patch
Normal file
19
patches/server/0618-Fix-CraftCriteria-defaults-map.patch
Normal file
|
@ -0,0 +1,19 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
Date: Mon, 4 Oct 2021 22:31:51 -0700
|
||||
Subject: [PATCH] Fix CraftCriteria defaults map
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftCriteria.java b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftCriteria.java
|
||||
index 441e2122f837712a21328eb7659cc9925ff9b6f8..8464531a4ee400834d25c23b1eb723f49be8689e 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftCriteria.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftCriteria.java
|
||||
@@ -54,7 +54,7 @@ public final class CraftCriteria implements Criteria {
|
||||
}
|
||||
|
||||
static CraftCriteria getFromNMS(Objective objective) {
|
||||
- return CraftCriteria.DEFAULTS.get(objective.getCriteria().getName());
|
||||
+ return java.util.Objects.requireNonNullElseGet(CraftCriteria.DEFAULTS.get(objective.getCriteria().getName()), () -> new CraftCriteria(objective.getCriteria())); // Paper
|
||||
}
|
||||
|
||||
public static CraftCriteria getFromBukkit(String name) {
|
491
patches/server/0619-Fix-upstreams-block-state-factories.patch
Normal file
491
patches/server/0619-Fix-upstreams-block-state-factories.patch
Normal file
|
@ -0,0 +1,491 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
Date: Wed, 6 Oct 2021 20:50:48 -0700
|
||||
Subject: [PATCH] Fix upstreams block state factories
|
||||
|
||||
Sometimes, blocks are changed and then logic is called before the associated
|
||||
tile entity is removed. When this happens, the factories were relying on the
|
||||
block at the position, not the tile entity. This change prioritizes using the
|
||||
tile entity type to determine the block state factory and falls back on
|
||||
the material type of the block at that location.
|
||||
|
||||
== AT ==
|
||||
public net.minecraft.world.level.block.entity.BlockEntityType validBlocks
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java
|
||||
index 46a831f86b512f4228be8ccee40fb0f7bf0d6df6..3de01d92e1c97e287a1f0d1f8de81b4f530b4a84 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java
|
||||
@@ -388,7 +388,7 @@ public abstract class BlockEntity {
|
||||
// Paper end
|
||||
if (this.level == null) return null;
|
||||
org.bukkit.block.Block block = this.level.getWorld().getBlockAt(this.worldPosition.getX(), this.worldPosition.getY(), this.worldPosition.getZ());
|
||||
- if (block.getType() == org.bukkit.Material.AIR) return null;
|
||||
+ // if (block.getType() == org.bukkit.Material.AIR) return null; // Paper - actually get the tile entity if it still exists
|
||||
org.bukkit.block.BlockState state = block.getState(useSnapshot); // Paper
|
||||
if (state instanceof InventoryHolder) return (InventoryHolder) state;
|
||||
return null;
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java
|
||||
index 80bd6e8a6dadb74356a9fa9aa394efbd31c49c37..fe7e3e0628783d8d1be9635b689da8a9cb46c5d7 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockEntityState.java
|
||||
@@ -20,7 +20,7 @@ import org.bukkit.persistence.PersistentDataContainer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
-public class CraftBlockEntityState<T extends BlockEntity> extends CraftBlockState implements TileState {
|
||||
+public abstract class CraftBlockEntityState<T extends BlockEntity> extends CraftBlockState implements TileState { // Paper - revert upstream's revert of the block state changes
|
||||
|
||||
private final T tileEntity;
|
||||
private final T snapshot;
|
||||
@@ -196,14 +196,10 @@ public class CraftBlockEntityState<T extends BlockEntity> extends CraftBlockStat
|
||||
}
|
||||
|
||||
@Override
|
||||
- public CraftBlockEntityState<T> copy() {
|
||||
- return new CraftBlockEntityState<>(this, null);
|
||||
- }
|
||||
+ public abstract CraftBlockEntityState<T> copy(); // Paper - make abstract
|
||||
|
||||
@Override
|
||||
- public CraftBlockEntityState<T> copy(Location location) {
|
||||
- return new CraftBlockEntityState<>(this, location);
|
||||
- }
|
||||
+ public abstract CraftBlockEntityState<T> copy(Location location); // Paper - make abstract
|
||||
|
||||
// Paper start
|
||||
@Override
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockStates.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockStates.java
|
||||
index 1a8dcde39a252a45046866349b848d79e1b13260..56453454cbd4b9e9270fc833f8ab38d5fa7a3763 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockStates.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockStates.java
|
||||
@@ -22,6 +22,7 @@ import net.minecraft.world.level.block.entity.BeehiveBlockEntity;
|
||||
import net.minecraft.world.level.block.entity.BellBlockEntity;
|
||||
import net.minecraft.world.level.block.entity.BlastFurnaceBlockEntity;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
+import net.minecraft.world.level.block.entity.BlockEntityType; // Paper
|
||||
import net.minecraft.world.level.block.entity.BrewingStandBlockEntity;
|
||||
import net.minecraft.world.level.block.entity.BrushableBlockEntity;
|
||||
import net.minecraft.world.level.block.entity.CalibratedSculkSensorBlockEntity;
|
||||
@@ -88,9 +89,9 @@ public final class CraftBlockStates {
|
||||
private static class BlockEntityStateFactory<T extends BlockEntity, B extends CraftBlockEntityState<T>> extends BlockStateFactory<B> {
|
||||
|
||||
private final BiFunction<World, T, B> blockStateConstructor;
|
||||
- private final BiFunction<BlockPos, net.minecraft.world.level.block.state.BlockState, T> tileEntityConstructor;
|
||||
+ private final BlockEntityType<? extends T> tileEntityConstructor; // Paper
|
||||
|
||||
- protected BlockEntityStateFactory(Class<B> blockStateType, BiFunction<World, T, B> blockStateConstructor, BiFunction<BlockPos, net.minecraft.world.level.block.state.BlockState, T> tileEntityConstructor) {
|
||||
+ protected BlockEntityStateFactory(Class<B> blockStateType, BiFunction<World, T, B> blockStateConstructor, BlockEntityType<? extends T> tileEntityConstructor) { // Paper
|
||||
super(blockStateType);
|
||||
this.blockStateConstructor = blockStateConstructor;
|
||||
this.tileEntityConstructor = tileEntityConstructor;
|
||||
@@ -107,7 +108,7 @@ public final class CraftBlockStates {
|
||||
}
|
||||
|
||||
private T createTileEntity(BlockPos blockPosition, net.minecraft.world.level.block.state.BlockState blockData) {
|
||||
- return this.tileEntityConstructor.apply(blockPosition, blockData);
|
||||
+ return this.tileEntityConstructor.create(blockPosition, blockData); // Paper
|
||||
}
|
||||
|
||||
private B createBlockState(World world, T tileEntity) {
|
||||
@@ -119,233 +120,66 @@ public final class CraftBlockStates {
|
||||
private static final BlockStateFactory<?> DEFAULT_FACTORY = new BlockStateFactory<CraftBlockState>(CraftBlockState.class) {
|
||||
@Override
|
||||
public CraftBlockState createBlockState(World world, BlockPos blockPosition, net.minecraft.world.level.block.state.BlockState blockData, BlockEntity tileEntity) {
|
||||
- // SPIGOT-6754, SPIGOT-6817: Restore previous behaviour for tile entities with removed blocks (loot generation post-destroy)
|
||||
- if (tileEntity != null) {
|
||||
- // block with unhandled TileEntity:
|
||||
- return new CraftBlockEntityState<>(world, tileEntity);
|
||||
- }
|
||||
+ // Paper - revert upstream's revert of the block state changes. Block entities that have already had the block type set to AIR are still valid, upstream decided to ignore them
|
||||
Preconditions.checkState(tileEntity == null, "Unexpected BlockState for %s", CraftBlockType.minecraftToBukkit(blockData.getBlock()));
|
||||
return new CraftBlockState(world, blockPosition, blockData);
|
||||
}
|
||||
};
|
||||
+ // Paper start
|
||||
+ private static final Map<BlockEntityType<?>, BlockStateFactory<?>> FACTORIES_BY_BLOCK_ENTITY_TYPE = new HashMap<>();
|
||||
+ private static void register(BlockEntityType<?> type, BlockStateFactory<?> factory) {
|
||||
+ FACTORIES_BY_BLOCK_ENTITY_TYPE.put(type, factory);
|
||||
+ }
|
||||
+ // Paper end
|
||||
|
||||
static {
|
||||
- register(
|
||||
- Arrays.asList(
|
||||
- Material.ACACIA_SIGN,
|
||||
- Material.ACACIA_WALL_SIGN,
|
||||
- Material.BAMBOO_SIGN,
|
||||
- Material.BAMBOO_WALL_SIGN,
|
||||
- Material.BIRCH_SIGN,
|
||||
- Material.BIRCH_WALL_SIGN,
|
||||
- Material.CHERRY_SIGN,
|
||||
- Material.CHERRY_WALL_SIGN,
|
||||
- Material.CRIMSON_SIGN,
|
||||
- Material.CRIMSON_WALL_SIGN,
|
||||
- Material.DARK_OAK_SIGN,
|
||||
- Material.DARK_OAK_WALL_SIGN,
|
||||
- Material.JUNGLE_SIGN,
|
||||
- Material.JUNGLE_WALL_SIGN,
|
||||
- Material.MANGROVE_SIGN,
|
||||
- Material.MANGROVE_WALL_SIGN,
|
||||
- Material.OAK_SIGN,
|
||||
- Material.OAK_WALL_SIGN,
|
||||
- Material.PALE_OAK_SIGN,
|
||||
- Material.PALE_OAK_WALL_SIGN,
|
||||
- Material.SPRUCE_SIGN,
|
||||
- Material.SPRUCE_WALL_SIGN,
|
||||
- Material.WARPED_SIGN,
|
||||
- Material.WARPED_WALL_SIGN
|
||||
- ), CraftSign.class, CraftSign::new, SignBlockEntity::new
|
||||
- );
|
||||
-
|
||||
- register(
|
||||
- Arrays.asList(
|
||||
- Material.ACACIA_HANGING_SIGN,
|
||||
- Material.ACACIA_WALL_HANGING_SIGN,
|
||||
- Material.BAMBOO_HANGING_SIGN,
|
||||
- Material.BAMBOO_WALL_HANGING_SIGN,
|
||||
- Material.BIRCH_HANGING_SIGN,
|
||||
- Material.BIRCH_WALL_HANGING_SIGN,
|
||||
- Material.CHERRY_HANGING_SIGN,
|
||||
- Material.CHERRY_WALL_HANGING_SIGN,
|
||||
- Material.CRIMSON_HANGING_SIGN,
|
||||
- Material.CRIMSON_WALL_HANGING_SIGN,
|
||||
- Material.DARK_OAK_HANGING_SIGN,
|
||||
- Material.DARK_OAK_WALL_HANGING_SIGN,
|
||||
- Material.JUNGLE_HANGING_SIGN,
|
||||
- Material.JUNGLE_WALL_HANGING_SIGN,
|
||||
- Material.MANGROVE_HANGING_SIGN,
|
||||
- Material.MANGROVE_WALL_HANGING_SIGN,
|
||||
- Material.OAK_HANGING_SIGN,
|
||||
- Material.OAK_WALL_HANGING_SIGN,
|
||||
- Material.PALE_OAK_HANGING_SIGN,
|
||||
- Material.PALE_OAK_WALL_HANGING_SIGN,
|
||||
- Material.SPRUCE_HANGING_SIGN,
|
||||
- Material.SPRUCE_WALL_HANGING_SIGN,
|
||||
- Material.WARPED_HANGING_SIGN,
|
||||
- Material.WARPED_WALL_HANGING_SIGN
|
||||
- ), CraftHangingSign.class, CraftHangingSign::new, HangingSignBlockEntity::new
|
||||
- );
|
||||
-
|
||||
- register(
|
||||
- Arrays.asList(
|
||||
- Material.CREEPER_HEAD,
|
||||
- Material.CREEPER_WALL_HEAD,
|
||||
- Material.DRAGON_HEAD,
|
||||
- Material.DRAGON_WALL_HEAD,
|
||||
- Material.PIGLIN_HEAD,
|
||||
- Material.PIGLIN_WALL_HEAD,
|
||||
- Material.PLAYER_HEAD,
|
||||
- Material.PLAYER_WALL_HEAD,
|
||||
- Material.SKELETON_SKULL,
|
||||
- Material.SKELETON_WALL_SKULL,
|
||||
- Material.WITHER_SKELETON_SKULL,
|
||||
- Material.WITHER_SKELETON_WALL_SKULL,
|
||||
- Material.ZOMBIE_HEAD,
|
||||
- Material.ZOMBIE_WALL_HEAD
|
||||
- ), CraftSkull.class, CraftSkull::new, SkullBlockEntity::new
|
||||
- );
|
||||
-
|
||||
- register(
|
||||
- Arrays.asList(
|
||||
- Material.COMMAND_BLOCK,
|
||||
- Material.REPEATING_COMMAND_BLOCK,
|
||||
- Material.CHAIN_COMMAND_BLOCK
|
||||
- ), CraftCommandBlock.class, CraftCommandBlock::new, CommandBlockEntity::new
|
||||
- );
|
||||
-
|
||||
- register(
|
||||
- Arrays.asList(
|
||||
- Material.BLACK_BANNER,
|
||||
- Material.BLACK_WALL_BANNER,
|
||||
- Material.BLUE_BANNER,
|
||||
- Material.BLUE_WALL_BANNER,
|
||||
- Material.BROWN_BANNER,
|
||||
- Material.BROWN_WALL_BANNER,
|
||||
- Material.CYAN_BANNER,
|
||||
- Material.CYAN_WALL_BANNER,
|
||||
- Material.GRAY_BANNER,
|
||||
- Material.GRAY_WALL_BANNER,
|
||||
- Material.GREEN_BANNER,
|
||||
- Material.GREEN_WALL_BANNER,
|
||||
- Material.LIGHT_BLUE_BANNER,
|
||||
- Material.LIGHT_BLUE_WALL_BANNER,
|
||||
- Material.LIGHT_GRAY_BANNER,
|
||||
- Material.LIGHT_GRAY_WALL_BANNER,
|
||||
- Material.LIME_BANNER,
|
||||
- Material.LIME_WALL_BANNER,
|
||||
- Material.MAGENTA_BANNER,
|
||||
- Material.MAGENTA_WALL_BANNER,
|
||||
- Material.ORANGE_BANNER,
|
||||
- Material.ORANGE_WALL_BANNER,
|
||||
- Material.PINK_BANNER,
|
||||
- Material.PINK_WALL_BANNER,
|
||||
- Material.PURPLE_BANNER,
|
||||
- Material.PURPLE_WALL_BANNER,
|
||||
- Material.RED_BANNER,
|
||||
- Material.RED_WALL_BANNER,
|
||||
- Material.WHITE_BANNER,
|
||||
- Material.WHITE_WALL_BANNER,
|
||||
- Material.YELLOW_BANNER,
|
||||
- Material.YELLOW_WALL_BANNER
|
||||
- ), CraftBanner.class, CraftBanner::new, BannerBlockEntity::new
|
||||
- );
|
||||
-
|
||||
- register(
|
||||
- Arrays.asList(
|
||||
- Material.SHULKER_BOX,
|
||||
- Material.WHITE_SHULKER_BOX,
|
||||
- Material.ORANGE_SHULKER_BOX,
|
||||
- Material.MAGENTA_SHULKER_BOX,
|
||||
- Material.LIGHT_BLUE_SHULKER_BOX,
|
||||
- Material.YELLOW_SHULKER_BOX,
|
||||
- Material.LIME_SHULKER_BOX,
|
||||
- Material.PINK_SHULKER_BOX,
|
||||
- Material.GRAY_SHULKER_BOX,
|
||||
- Material.LIGHT_GRAY_SHULKER_BOX,
|
||||
- Material.CYAN_SHULKER_BOX,
|
||||
- Material.PURPLE_SHULKER_BOX,
|
||||
- Material.BLUE_SHULKER_BOX,
|
||||
- Material.BROWN_SHULKER_BOX,
|
||||
- Material.GREEN_SHULKER_BOX,
|
||||
- Material.RED_SHULKER_BOX,
|
||||
- Material.BLACK_SHULKER_BOX
|
||||
- ), CraftShulkerBox.class, CraftShulkerBox::new, ShulkerBoxBlockEntity::new
|
||||
- );
|
||||
-
|
||||
- register(
|
||||
- Arrays.asList(
|
||||
- Material.BLACK_BED,
|
||||
- Material.BLUE_BED,
|
||||
- Material.BROWN_BED,
|
||||
- Material.CYAN_BED,
|
||||
- Material.GRAY_BED,
|
||||
- Material.GREEN_BED,
|
||||
- Material.LIGHT_BLUE_BED,
|
||||
- Material.LIGHT_GRAY_BED,
|
||||
- Material.LIME_BED,
|
||||
- Material.MAGENTA_BED,
|
||||
- Material.ORANGE_BED,
|
||||
- Material.PINK_BED,
|
||||
- Material.PURPLE_BED,
|
||||
- Material.RED_BED,
|
||||
- Material.WHITE_BED,
|
||||
- Material.YELLOW_BED
|
||||
- ), CraftBed.class, CraftBed::new, BedBlockEntity::new
|
||||
- );
|
||||
-
|
||||
- register(
|
||||
- Arrays.asList(
|
||||
- Material.BEEHIVE,
|
||||
- Material.BEE_NEST
|
||||
- ), CraftBeehive.class, CraftBeehive::new, BeehiveBlockEntity::new
|
||||
- );
|
||||
-
|
||||
- register(
|
||||
- Arrays.asList(
|
||||
- Material.CAMPFIRE,
|
||||
- Material.SOUL_CAMPFIRE
|
||||
- ), CraftCampfire.class, CraftCampfire::new, CampfireBlockEntity::new
|
||||
- );
|
||||
-
|
||||
- register(Material.BARREL, CraftBarrel.class, CraftBarrel::new, BarrelBlockEntity::new);
|
||||
- register(Material.BEACON, CraftBeacon.class, CraftBeacon::new, BeaconBlockEntity::new);
|
||||
- register(Material.BELL, CraftBell.class, CraftBell::new, BellBlockEntity::new);
|
||||
- register(Material.BLAST_FURNACE, CraftBlastFurnace.class, CraftBlastFurnace::new, BlastFurnaceBlockEntity::new);
|
||||
- register(Material.BREWING_STAND, CraftBrewingStand.class, CraftBrewingStand::new, BrewingStandBlockEntity::new);
|
||||
- register(Material.CHEST, CraftChest.class, CraftChest::new, ChestBlockEntity::new);
|
||||
- register(Material.CHISELED_BOOKSHELF, CraftChiseledBookshelf.class, CraftChiseledBookshelf::new, ChiseledBookShelfBlockEntity::new);
|
||||
- register(Material.COMPARATOR, CraftComparator.class, CraftComparator::new, ComparatorBlockEntity::new);
|
||||
- register(Material.CONDUIT, CraftConduit.class, CraftConduit::new, ConduitBlockEntity::new);
|
||||
- register(Material.CREAKING_HEART, CraftCreakingHeart.class, CraftCreakingHeart::new, CreakingHeartBlockEntity::new);
|
||||
- register(Material.DAYLIGHT_DETECTOR, CraftDaylightDetector.class, CraftDaylightDetector::new, DaylightDetectorBlockEntity::new);
|
||||
- register(Material.DECORATED_POT, CraftDecoratedPot.class, CraftDecoratedPot::new, DecoratedPotBlockEntity::new);
|
||||
- register(Material.DISPENSER, CraftDispenser.class, CraftDispenser::new, DispenserBlockEntity::new);
|
||||
- register(Material.DROPPER, CraftDropper.class, CraftDropper::new, DropperBlockEntity::new);
|
||||
- register(Material.ENCHANTING_TABLE, CraftEnchantingTable.class, CraftEnchantingTable::new, EnchantingTableBlockEntity::new);
|
||||
- register(Material.ENDER_CHEST, CraftEnderChest.class, CraftEnderChest::new, EnderChestBlockEntity::new);
|
||||
- register(Material.END_GATEWAY, CraftEndGateway.class, CraftEndGateway::new, TheEndGatewayBlockEntity::new);
|
||||
- register(Material.END_PORTAL, CraftEndPortal.class, CraftEndPortal::new, TheEndPortalBlockEntity::new);
|
||||
- register(Material.FURNACE, CraftFurnaceFurnace.class, CraftFurnaceFurnace::new, FurnaceBlockEntity::new);
|
||||
- register(Material.HOPPER, CraftHopper.class, CraftHopper::new, HopperBlockEntity::new);
|
||||
- register(Material.JIGSAW, CraftJigsaw.class, CraftJigsaw::new, JigsawBlockEntity::new);
|
||||
- register(Material.JUKEBOX, CraftJukebox.class, CraftJukebox::new, JukeboxBlockEntity::new);
|
||||
- register(Material.LECTERN, CraftLectern.class, CraftLectern::new, LecternBlockEntity::new);
|
||||
- register(Material.MOVING_PISTON, CraftMovingPiston.class, CraftMovingPiston::new, PistonMovingBlockEntity::new);
|
||||
- register(Material.SCULK_CATALYST, CraftSculkCatalyst.class, CraftSculkCatalyst::new, SculkCatalystBlockEntity::new);
|
||||
- register(Material.CALIBRATED_SCULK_SENSOR, CraftCalibratedSculkSensor.class, CraftCalibratedSculkSensor::new, CalibratedSculkSensorBlockEntity::new);
|
||||
- register(Material.SCULK_SENSOR, CraftSculkSensor.class, CraftSculkSensor::new, SculkSensorBlockEntity::new);
|
||||
- register(Material.SCULK_SHRIEKER, CraftSculkShrieker.class, CraftSculkShrieker::new, SculkShriekerBlockEntity::new);
|
||||
- register(Material.SMOKER, CraftSmoker.class, CraftSmoker::new, SmokerBlockEntity::new);
|
||||
- register(Material.SPAWNER, CraftCreatureSpawner.class, CraftCreatureSpawner::new, SpawnerBlockEntity::new);
|
||||
- register(Material.STRUCTURE_BLOCK, CraftStructureBlock.class, CraftStructureBlock::new, StructureBlockEntity::new);
|
||||
- register(Material.SUSPICIOUS_SAND, CraftSuspiciousSand.class, CraftSuspiciousSand::new, BrushableBlockEntity::new);
|
||||
- register(Material.SUSPICIOUS_GRAVEL, CraftBrushableBlock.class, CraftBrushableBlock::new, BrushableBlockEntity::new);
|
||||
- register(Material.TRAPPED_CHEST, CraftChest.class, CraftChest::new, TrappedChestBlockEntity::new);
|
||||
- register(Material.CRAFTER, CraftCrafter.class, CraftCrafter::new, CrafterBlockEntity::new);
|
||||
- register(Material.TRIAL_SPAWNER, CraftTrialSpawner.class, CraftTrialSpawner::new, TrialSpawnerBlockEntity::new);
|
||||
- register(Material.VAULT, CraftVault.class, CraftVault::new, VaultBlockEntity::new);
|
||||
+ // Paper start - simplify
|
||||
+ register(BlockEntityType.SIGN, CraftSign.class, CraftSign::new);
|
||||
+ register(BlockEntityType.HANGING_SIGN, CraftHangingSign.class, CraftHangingSign::new);
|
||||
+ register(BlockEntityType.SKULL, CraftSkull.class, CraftSkull::new);
|
||||
+ register(BlockEntityType.COMMAND_BLOCK, CraftCommandBlock.class, CraftCommandBlock::new);
|
||||
+ register(BlockEntityType.BANNER, CraftBanner.class, CraftBanner::new);
|
||||
+ register(BlockEntityType.SHULKER_BOX, CraftShulkerBox.class, CraftShulkerBox::new);
|
||||
+ register(BlockEntityType.BED, CraftBed.class, CraftBed::new);
|
||||
+ register(BlockEntityType.BEEHIVE, CraftBeehive.class, CraftBeehive::new);
|
||||
+ register(BlockEntityType.CAMPFIRE, CraftCampfire.class, CraftCampfire::new);
|
||||
+ register(BlockEntityType.BARREL, CraftBarrel.class, CraftBarrel::new);
|
||||
+ register(BlockEntityType.BEACON, CraftBeacon.class, CraftBeacon::new);
|
||||
+ register(BlockEntityType.BELL, CraftBell.class, CraftBell::new);
|
||||
+ register(BlockEntityType.BLAST_FURNACE, CraftBlastFurnace.class, CraftBlastFurnace::new);
|
||||
+ register(BlockEntityType.BREWING_STAND, CraftBrewingStand.class, CraftBrewingStand::new);
|
||||
+ register(BlockEntityType.CHEST, CraftChest.class, CraftChest::new);
|
||||
+ register(BlockEntityType.CHISELED_BOOKSHELF, CraftChiseledBookshelf.class, CraftChiseledBookshelf::new);
|
||||
+ register(BlockEntityType.COMPARATOR, CraftComparator.class, CraftComparator::new);
|
||||
+ register(BlockEntityType.CONDUIT, CraftConduit.class, CraftConduit::new);
|
||||
+ register(BlockEntityType.CREAKING_HEART, CraftCreakingHeart.class, CraftCreakingHeart::new);
|
||||
+ register(BlockEntityType.DAYLIGHT_DETECTOR, CraftDaylightDetector.class, CraftDaylightDetector::new);
|
||||
+ register(BlockEntityType.DECORATED_POT, CraftDecoratedPot.class, CraftDecoratedPot::new);
|
||||
+ register(BlockEntityType.DISPENSER, CraftDispenser.class, CraftDispenser::new);
|
||||
+ register(BlockEntityType.DROPPER, CraftDropper.class, CraftDropper::new);
|
||||
+ register(BlockEntityType.ENCHANTING_TABLE, CraftEnchantingTable.class, CraftEnchantingTable::new);
|
||||
+ register(BlockEntityType.ENDER_CHEST, CraftEnderChest.class, CraftEnderChest::new);
|
||||
+ register(BlockEntityType.END_GATEWAY, CraftEndGateway.class, CraftEndGateway::new);
|
||||
+ register(BlockEntityType.END_PORTAL, CraftEndPortal.class, CraftEndPortal::new);
|
||||
+ register(BlockEntityType.FURNACE, CraftFurnaceFurnace.class, CraftFurnaceFurnace::new);
|
||||
+ register(BlockEntityType.HOPPER, CraftHopper.class, CraftHopper::new);
|
||||
+ register(BlockEntityType.JIGSAW, CraftJigsaw.class, CraftJigsaw::new);
|
||||
+ register(BlockEntityType.JUKEBOX, CraftJukebox.class, CraftJukebox::new);
|
||||
+ register(BlockEntityType.LECTERN, CraftLectern.class, CraftLectern::new);
|
||||
+ register(BlockEntityType.PISTON, CraftMovingPiston.class, CraftMovingPiston::new);
|
||||
+ register(BlockEntityType.SCULK_CATALYST, CraftSculkCatalyst.class, CraftSculkCatalyst::new);
|
||||
+ register(BlockEntityType.SCULK_SENSOR, CraftSculkSensor.class, CraftSculkSensor::new);
|
||||
+ register(BlockEntityType.SCULK_SHRIEKER, CraftSculkShrieker.class, CraftSculkShrieker::new);
|
||||
+ register(BlockEntityType.CALIBRATED_SCULK_SENSOR, CraftCalibratedSculkSensor.class, CraftCalibratedSculkSensor::new);
|
||||
+ register(BlockEntityType.SMOKER, CraftSmoker.class, CraftSmoker::new);
|
||||
+ register(BlockEntityType.MOB_SPAWNER, CraftCreatureSpawner.class, CraftCreatureSpawner::new);
|
||||
+ register(BlockEntityType.STRUCTURE_BLOCK, CraftStructureBlock.class, CraftStructureBlock::new);
|
||||
+ register(BlockEntityType.BRUSHABLE_BLOCK, CraftBrushableBlock.class, CraftBrushableBlock::new); // note: spigot still uses CraftSuspiciousSand impl for that block type
|
||||
+ register(BlockEntityType.TRAPPED_CHEST, CraftChest.class, CraftChest::new);
|
||||
+ register(BlockEntityType.CRAFTER, CraftCrafter.class, CraftCrafter::new);
|
||||
+ register(BlockEntityType.TRIAL_SPAWNER, CraftTrialSpawner.class, CraftTrialSpawner::new);
|
||||
+ register(BlockEntityType.VAULT, CraftVault.class, CraftVault::new);
|
||||
+ // Paper end
|
||||
}
|
||||
|
||||
private static void register(Material blockType, BlockStateFactory<?> factory) {
|
||||
@@ -353,30 +187,33 @@ public final class CraftBlockStates {
|
||||
}
|
||||
|
||||
private static <T extends BlockEntity, B extends CraftBlockEntityState<T>> void register(
|
||||
- Material blockType,
|
||||
+ net.minecraft.world.level.block.entity.BlockEntityType<? extends T> blockEntityType, // Paper
|
||||
Class<B> blockStateType,
|
||||
- BiFunction<World, T, B> blockStateConstructor,
|
||||
- BiFunction<BlockPos, net.minecraft.world.level.block.state.BlockState, T> tileEntityConstructor
|
||||
+ BiFunction<World, T, B> blockStateConstructor // Paper
|
||||
) {
|
||||
- CraftBlockStates.register(Collections.singletonList(blockType), blockStateType, blockStateConstructor, tileEntityConstructor);
|
||||
- }
|
||||
-
|
||||
- private static <T extends BlockEntity, B extends CraftBlockEntityState<T>> void register(
|
||||
- List<Material> blockTypes,
|
||||
- Class<B> blockStateType,
|
||||
- BiFunction<World, T, B> blockStateConstructor,
|
||||
- BiFunction<BlockPos, net.minecraft.world.level.block.state.BlockState, T> tileEntityConstructor
|
||||
- ) {
|
||||
- BlockStateFactory<B> factory = new BlockEntityStateFactory<>(blockStateType, blockStateConstructor, tileEntityConstructor);
|
||||
- for (Material blockType : blockTypes) {
|
||||
- CraftBlockStates.register(blockType, factory);
|
||||
+ // Paper start
|
||||
+ BlockStateFactory<B> factory = new BlockEntityStateFactory<>(blockStateType, blockStateConstructor, blockEntityType); // Paper
|
||||
+ for (net.minecraft.world.level.block.Block block : blockEntityType.validBlocks) {
|
||||
+ CraftBlockStates.register(CraftBlockType.minecraftToBukkit(block), factory);
|
||||
}
|
||||
+ CraftBlockStates.register(blockEntityType, factory);
|
||||
+ // Paper end
|
||||
}
|
||||
|
||||
private static BlockStateFactory<?> getFactory(Material material) {
|
||||
return CraftBlockStates.FACTORIES.getOrDefault(material, CraftBlockStates.DEFAULT_FACTORY);
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ private static BlockStateFactory<?> getFactory(Material material, BlockEntityType<?> type) {
|
||||
+ if (type != null) {
|
||||
+ return CraftBlockStates.FACTORIES_BY_BLOCK_ENTITY_TYPE.getOrDefault(type, getFactory(material));
|
||||
+ } else {
|
||||
+ return getFactory(material);
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
public static Class<? extends CraftBlockState> getBlockStateType(Material material) {
|
||||
Preconditions.checkNotNull(material, "material is null");
|
||||
return CraftBlockStates.getFactory(material).blockStateType;
|
||||
@@ -392,6 +229,13 @@ public final class CraftBlockStates {
|
||||
return null;
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ public static Class<? extends CraftBlockState> getBlockStateType(BlockEntityType<?> blockEntityType) {
|
||||
+ Preconditions.checkNotNull(blockEntityType, "blockEntityType is null");
|
||||
+ return CraftBlockStates.getFactory(null, blockEntityType).blockStateType;
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
public static BlockState getBlockState(Block block) {
|
||||
// Paper start
|
||||
return CraftBlockStates.getBlockState(block, true);
|
||||
@@ -459,7 +303,7 @@ public final class CraftBlockStates {
|
||||
if (world != null && tileEntity == null && CraftBlockStates.isTileEntityOptional(material)) {
|
||||
factory = CraftBlockStates.DEFAULT_FACTORY;
|
||||
} else {
|
||||
- factory = CraftBlockStates.getFactory(material);
|
||||
+ factory = CraftBlockStates.getFactory(material, tileEntity != null ? tileEntity.getType() : null); // Paper
|
||||
}
|
||||
return factory.createBlockState(world, blockPosition, blockData, tileEntity);
|
||||
}
|
||||
@@ -478,6 +322,14 @@ public final class CraftBlockStates {
|
||||
return new CraftBlockState(CraftBlock.at(world, pos), flag);
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ @Nullable
|
||||
+ public static BlockEntityType<?> getBlockEntityType(final Material material) {
|
||||
+ final BlockStateFactory<?> factory = org.bukkit.craftbukkit.block.CraftBlockStates.FACTORIES.get(material);
|
||||
+ return factory instanceof final BlockEntityStateFactory<?,?> blockEntityStateFactory ? blockEntityStateFactory.tileEntityConstructor : null;
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
private CraftBlockStates() {
|
||||
}
|
||||
}
|
||||
diff --git a/src/test/java/org/bukkit/craftbukkit/block/BlockStateTest.java b/src/test/java/org/bukkit/craftbukkit/block/BlockStateTest.java
|
||||
index c032daa6957df2ad8b621379e415ad925f5cc162..a9810c88e05ebc1af60c051faa45e50ee183924f 100644
|
||||
--- a/src/test/java/org/bukkit/craftbukkit/block/BlockStateTest.java
|
||||
+++ b/src/test/java/org/bukkit/craftbukkit/block/BlockStateTest.java
|
||||
@@ -7,6 +7,7 @@ import net.minecraft.core.registries.BuiltInRegistries;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.EntityBlock;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
+import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.support.environment.AllFeatures;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@@ -42,4 +43,13 @@ public class BlockStateTest {
|
||||
}
|
||||
}
|
||||
}
|
||||
+
|
||||
+ // Paper start
|
||||
+ @Test
|
||||
+ public void testBlockEntityTypes() {
|
||||
+ for (var blockEntityType : BuiltInRegistries.BLOCK_ENTITY_TYPE) {
|
||||
+ org.junit.jupiter.api.Assertions.assertNotNull(CraftBlockStates.getBlockStateType(blockEntityType));
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
40
patches/server/0620-Configurable-feature-seeds.patch
Normal file
40
patches/server/0620-Configurable-feature-seeds.patch
Normal file
|
@ -0,0 +1,40 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Nassim Jahnke <nassim@njahnke.dev>
|
||||
Date: Tue, 31 Aug 2021 17:05:27 +0200
|
||||
Subject: [PATCH] Configurable feature seeds
|
||||
|
||||
Co-authored-by: Thonk <30448663+ExcessiveAmountsOfZombies@users.noreply.github.com>
|
||||
|
||||
diff --git a/src/main/java/co/aikar/timings/TimingsExport.java b/src/main/java/co/aikar/timings/TimingsExport.java
|
||||
index 49028463ba47e760281545c2f7597e3db8d6c453..7620c72a4c243cbeea245203ce03a97cbfa7d922 100644
|
||||
--- a/src/main/java/co/aikar/timings/TimingsExport.java
|
||||
+++ b/src/main/java/co/aikar/timings/TimingsExport.java
|
||||
@@ -286,7 +286,7 @@ public class TimingsExport extends Thread {
|
||||
JSONObject object = new JSONObject();
|
||||
for (String key : config.getKeys(false)) {
|
||||
String fullKey = (parentKey != null ? parentKey + "." + key : key);
|
||||
- if (fullKey.equals("database") || fullKey.equals("settings.bungeecord-addresses") || TimingsManager.hiddenConfigs.contains(fullKey) || key.startsWith("seed-") || key.equals("worldeditregentempworld")) {
|
||||
+ if (fullKey.equals("database") || fullKey.equals("settings.bungeecord-addresses") || TimingsManager.hiddenConfigs.contains(fullKey) || key.startsWith("seed-") || key.equals("worldeditregentempworld") || key.equals("feature-seeds")) {
|
||||
continue;
|
||||
}
|
||||
final Object val = config.get(key);
|
||||
diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java b/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java
|
||||
index fd2dd6d25b8d6f3066c60a7f30a58a72cb418b85..575fa665ff9c8f52056a0e7305540ec5c3da4785 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java
|
||||
@@ -436,7 +436,14 @@ public abstract class ChunkGenerator {
|
||||
return (String) optional.orElseGet(placedfeature::toString);
|
||||
};
|
||||
|
||||
- seededrandom.setFeatureSeed(i, l1, l);
|
||||
+ // Paper start - Configurable feature seeds; change populationSeed used in random
|
||||
+ long featurePopulationSeed = i;
|
||||
+ final long configFeatureSeed = generatoraccessseed.getMinecraftWorld().paperConfig().featureSeeds.features.getLong(placedfeature.feature());
|
||||
+ if (configFeatureSeed != -1) {
|
||||
+ featurePopulationSeed = seededrandom.setDecorationSeed(configFeatureSeed, blockposition.getX(), blockposition.getZ()); // See seededrandom.setDecorationSeed from above
|
||||
+ }
|
||||
+ seededrandom.setFeatureSeed(featurePopulationSeed, l1, l);
|
||||
+ // Paper end - Configurable feature seeds
|
||||
|
||||
try {
|
||||
generatoraccessseed.setCurrentlyGenerating(supplier1);
|
62
patches/server/0621-Add-root-admin-user-detection.patch
Normal file
62
patches/server/0621-Add-root-admin-user-detection.patch
Normal file
|
@ -0,0 +1,62 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: egg82 <eggys82@gmail.com>
|
||||
Date: Sat, 11 Sep 2021 22:55:14 +0200
|
||||
Subject: [PATCH] Add root/admin user detection
|
||||
|
||||
This patch detects whether or not the server is currently executing as a privileged user and spits out a warning.
|
||||
The warning serves as a sort-of PSA for newer server admins who don't understand the risks of running as root.
|
||||
We've seen plenty of bad/malicious plugins hit markets, and there's been a few close-calls with exploits in the past.
|
||||
Hopefully this helps mitigate some potential damage to servers, even if it is just a warning.
|
||||
|
||||
Co-authored-by: Noah van der Aa <ndvdaa@gmail.com>
|
||||
|
||||
diff --git a/src/main/java/io/papermc/paper/util/ServerEnvironment.java b/src/main/java/io/papermc/paper/util/ServerEnvironment.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..68098dfe716e93aafcca4d8d5b5a81d8648b3654
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/util/ServerEnvironment.java
|
||||
@@ -0,0 +1,23 @@
|
||||
+package io.papermc.paper.util;
|
||||
+
|
||||
+import com.sun.security.auth.module.NTSystem;
|
||||
+import com.sun.security.auth.module.UnixSystem;
|
||||
+import java.util.Set;
|
||||
+import org.apache.commons.lang.SystemUtils;
|
||||
+
|
||||
+public class ServerEnvironment {
|
||||
+ private static final boolean RUNNING_AS_ROOT_OR_ADMIN;
|
||||
+ private static final String WINDOWS_HIGH_INTEGRITY_LEVEL = "S-1-16-12288";
|
||||
+
|
||||
+ static {
|
||||
+ if (SystemUtils.IS_OS_WINDOWS) {
|
||||
+ RUNNING_AS_ROOT_OR_ADMIN = Set.of(new NTSystem().getGroupIDs()).contains(WINDOWS_HIGH_INTEGRITY_LEVEL);
|
||||
+ } else {
|
||||
+ RUNNING_AS_ROOT_OR_ADMIN = new UnixSystem().getUid() == 0;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ public static boolean userIsRootOrAdmin() {
|
||||
+ return RUNNING_AS_ROOT_OR_ADMIN;
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
|
||||
index e30a5ad17d7ba8bcec8911a72281830c419b0288..3c3be48b29fcd38c5dea1bfca8d8690850aa948e 100644
|
||||
--- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
|
||||
+++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
|
||||
@@ -195,6 +195,16 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface
|
||||
DedicatedServer.LOGGER.warn("To start the server with more ram, launch it as \"java -Xmx1024M -Xms1024M -jar minecraft_server.jar\"");
|
||||
}
|
||||
|
||||
+ // Paper start - detect running as root
|
||||
+ if (io.papermc.paper.util.ServerEnvironment.userIsRootOrAdmin()) {
|
||||
+ DedicatedServer.LOGGER.warn("****************************");
|
||||
+ DedicatedServer.LOGGER.warn("YOU ARE RUNNING THIS SERVER AS AN ADMINISTRATIVE OR ROOT USER. THIS IS NOT ADVISED.");
|
||||
+ DedicatedServer.LOGGER.warn("YOU ARE OPENING YOURSELF UP TO POTENTIAL RISKS WHEN DOING THIS.");
|
||||
+ DedicatedServer.LOGGER.warn("FOR MORE INFORMATION, SEE https://madelinemiller.dev/blog/root-minecraft-server/");
|
||||
+ DedicatedServer.LOGGER.warn("****************************");
|
||||
+ }
|
||||
+ // Paper end - detect running as root
|
||||
+
|
||||
DedicatedServer.LOGGER.info("Loading properties");
|
||||
DedicatedServerProperties dedicatedserverproperties = this.settings.getProperties();
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: sulu5890 <sulu@sulu.me>
|
||||
Date: Sun, 24 Oct 2021 22:48:14 -0500
|
||||
Subject: [PATCH] don't attempt to teleport dead entities
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
index b54dcebbd5d2f920efcf91ff2de485493dd2f487..e311601d8e39e7ea632bc4805260da6d7d6d6776 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
@@ -713,7 +713,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
|
||||
// CraftBukkit start
|
||||
public void postTick() {
|
||||
// No clean way to break out of ticking once the entity has been copied to a new world, so instead we move the portalling later in the tick cycle
|
||||
- if (!(this instanceof ServerPlayer)) {
|
||||
+ if (!(this instanceof ServerPlayer) && this.isAlive()) { // Paper - don't attempt to teleport dead entities
|
||||
this.handlePortal();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Nassim Jahnke <nassim@njahnke.dev>
|
||||
Date: Thu, 25 Nov 2021 10:25:09 +0100
|
||||
Subject: [PATCH] Prevent excessive velocity through repeated crits
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
index f7e14d9668c74e20bc327b05cf84c8203e4e590b..4db8ac288e59c5f14b260686e55a7d48e2f2791d 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
@@ -2865,17 +2865,29 @@ public abstract class LivingEntity extends Entity implements Attackable {
|
||||
return this.hasEffect(MobEffects.JUMP) ? 0.1F * ((float) this.getEffect(MobEffects.JUMP).getAmplifier() + 1.0F) : 0.0F;
|
||||
}
|
||||
|
||||
+ protected long lastJumpTime = 0L; // Paper - Prevent excessive velocity through repeated crits
|
||||
@VisibleForTesting
|
||||
public void jumpFromGround() {
|
||||
float f = this.getJumpPower();
|
||||
|
||||
if (f > 1.0E-5F) {
|
||||
Vec3 vec3d = this.getDeltaMovement();
|
||||
+ // Paper start - Prevent excessive velocity through repeated crits
|
||||
+ long time = System.nanoTime();
|
||||
+ boolean canCrit = true;
|
||||
+ if (this instanceof net.minecraft.world.entity.player.Player) {
|
||||
+ canCrit = false;
|
||||
+ if (time - this.lastJumpTime > (long)(0.250e9)) {
|
||||
+ this.lastJumpTime = time;
|
||||
+ canCrit = true;
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end - Prevent excessive velocity through repeated crits
|
||||
|
||||
this.setDeltaMovement(vec3d.x, Math.max((double) f, vec3d.y), vec3d.z);
|
||||
if (this.isSprinting()) {
|
||||
float f1 = this.getYRot() * 0.017453292F;
|
||||
-
|
||||
+ if (canCrit) // Paper - Prevent excessive velocity through repeated crits
|
||||
this.addDeltaMovement(new Vec3((double) (-Mth.sin(f1)) * 0.2D, 0.0D, (double) Mth.cos(f1) * 0.2D));
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jason Penilla <11360596+jpenilla@users.noreply.github.com>
|
||||
Date: Fri, 26 Nov 2021 15:09:58 -0800
|
||||
Subject: [PATCH] Remove client-side code using deprecated for removal
|
||||
AccessController
|
||||
|
||||
Fixes warnings on build
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/Util.java b/src/main/java/net/minecraft/Util.java
|
||||
index 0fbe4ea495a8101f6bc1b9830ce3f47af2aa5be4..60e523f4de1cbafc2c58a5d568fe3989b7b07c34 100644
|
||||
--- a/src/main/java/net/minecraft/Util.java
|
||||
+++ b/src/main/java/net/minecraft/Util.java
|
||||
@@ -1082,16 +1082,7 @@ public class Util {
|
||||
}
|
||||
|
||||
public void openUri(URI uri) {
|
||||
- try {
|
||||
- Process process = AccessController.doPrivileged(
|
||||
- (PrivilegedExceptionAction<Process>)(() -> Runtime.getRuntime().exec(this.getOpenUriArguments(uri)))
|
||||
- );
|
||||
- process.getInputStream().close();
|
||||
- process.getErrorStream().close();
|
||||
- process.getOutputStream().close();
|
||||
- } catch (IOException | PrivilegedActionException var3) {
|
||||
- Util.LOGGER.error("Couldn't open location '{}'", uri, var3);
|
||||
- }
|
||||
+ throw new IllegalStateException("This method is not useful on dedicated servers."); // Paper - Fix warnings on build by removing client-only code
|
||||
}
|
||||
|
||||
public void openFile(File file) {
|
141
patches/server/0625-Fix-Spigot-growth-modifiers.patch
Normal file
141
patches/server/0625-Fix-Spigot-growth-modifiers.patch
Normal file
|
@ -0,0 +1,141 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jason Penilla <11360596+jpenilla@users.noreply.github.com>
|
||||
Date: Fri, 3 Dec 2021 17:09:24 -0800
|
||||
Subject: [PATCH] Fix Spigot growth modifiers
|
||||
|
||||
Fixes kelp modifier changing growth for other crops
|
||||
Also add growth modifiers for glow berries, mangrove propagules,
|
||||
torchflower crops and pitcher plant crops
|
||||
Also fix above-mentioned modifiers from having the reverse effect
|
||||
|
||||
Co-authored-by: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
Co-authored-by: Noah van der Aa <ndvdaa@gmail.com>
|
||||
Co-authored-by: Lulu13022002 <41980282+Lulu13022002@users.noreply.github.com>
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/CaveVinesBlock.java b/src/main/java/net/minecraft/world/level/block/CaveVinesBlock.java
|
||||
index 437be546cf03b6af0856adabfeaf67bc33ff75d6..c4473c2a778116d48bc3e4796afd901f455070e6 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/CaveVinesBlock.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/CaveVinesBlock.java
|
||||
@@ -50,9 +50,18 @@ public class CaveVinesBlock extends GrowingPlantHeadBlock implements CaveVines {
|
||||
return to.setValue(BERRIES, from.getValue(BERRIES));
|
||||
}
|
||||
|
||||
+ // Paper start - Fix Spigot growth modifiers
|
||||
+ @Override
|
||||
+ protected BlockState getGrowIntoState(BlockState state, RandomSource random, @javax.annotation.Nullable Level level) {
|
||||
+ final boolean value = random.nextFloat() < (level != null ? (0.11F * (level.spigotConfig.glowBerryModifier / 100.0F)) : 0.11F);
|
||||
+ return (BlockState) super.getGrowIntoState(state, random).setValue(CaveVinesBlock.BERRIES, value);
|
||||
+ }
|
||||
+ // Paper end - Fix Spigot growth modifiers
|
||||
+
|
||||
@Override
|
||||
protected BlockState getGrowIntoState(BlockState state, RandomSource random) {
|
||||
- return super.getGrowIntoState(state, random).setValue(BERRIES, Boolean.valueOf(random.nextFloat() < 0.11F));
|
||||
+ // Paper start - Fix Spigot growth modifiers
|
||||
+ return this.getGrowIntoState(state, random, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/CropBlock.java b/src/main/java/net/minecraft/world/level/block/CropBlock.java
|
||||
index 79ebc37a779bf6cba66a34a7604f819e95fd86a2..1ada5ed825501666addacf527a513ab7bd4a3a58 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/CropBlock.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/CropBlock.java
|
||||
@@ -91,6 +91,10 @@ public class CropBlock extends BushBlock implements BonemealableBlock {
|
||||
modifier = world.spigotConfig.carrotModifier;
|
||||
} else if (this == Blocks.POTATOES) {
|
||||
modifier = world.spigotConfig.potatoModifier;
|
||||
+ // Paper start - Fix Spigot growth modifiers
|
||||
+ } else if (this == Blocks.TORCHFLOWER_CROP) {
|
||||
+ modifier = world.spigotConfig.torchFlowerModifier;
|
||||
+ // Paper end - Fix Spigot growth modifiers
|
||||
} else {
|
||||
modifier = world.spigotConfig.wheatModifier;
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/GrowingPlantHeadBlock.java b/src/main/java/net/minecraft/world/level/block/GrowingPlantHeadBlock.java
|
||||
index c527f2d8f594d711d047a2a149efe37caaeb0308..9b424d7661fedf8ee1eb9f3167c62e563f04d4d1 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/GrowingPlantHeadBlock.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/GrowingPlantHeadBlock.java
|
||||
@@ -60,12 +60,18 @@ public abstract class GrowingPlantHeadBlock extends GrowingPlantBlock implements
|
||||
BlockPos blockposition1 = pos.relative(this.growthDirection);
|
||||
|
||||
if (this.canGrowInto(world.getBlockState(blockposition1))) {
|
||||
- org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(world, pos, blockposition1, this.getGrowIntoState(state, world.random)); // CraftBukkit
|
||||
+ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockSpreadEvent(world, pos, blockposition1, this.getGrowIntoState(state, world.random, world)); // CraftBukkit // Paper - Fix Spigot growth modifiers
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+ // Paper start - Fix Spigot growth modifiers
|
||||
+ protected BlockState getGrowIntoState(BlockState state, RandomSource random, @javax.annotation.Nullable Level level) {
|
||||
+ return this.getGrowIntoState(state, random);
|
||||
+ }
|
||||
+ // Paper end - Fix Spigot growth modifiers
|
||||
+
|
||||
protected BlockState getGrowIntoState(BlockState state, RandomSource random) {
|
||||
return (BlockState) state.cycle(GrowingPlantHeadBlock.AGE);
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/MangrovePropaguleBlock.java b/src/main/java/net/minecraft/world/level/block/MangrovePropaguleBlock.java
|
||||
index 10e2b80b0b6010982258548b5084b9591177b558..6b18db68c8b95480992199126c6063ea728d2314 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/MangrovePropaguleBlock.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/MangrovePropaguleBlock.java
|
||||
@@ -123,7 +123,7 @@ public class MangrovePropaguleBlock extends SaplingBlock implements SimpleWaterl
|
||||
@Override
|
||||
protected void randomTick(BlockState state, ServerLevel world, BlockPos pos, RandomSource random) {
|
||||
if (!isHanging(state)) {
|
||||
- if (random.nextInt(7) == 0) {
|
||||
+ if (random.nextFloat() < (world.spigotConfig.saplingModifier / (100.0F * 7))) { // Paper - Fix Spigot growth modifiers
|
||||
this.advanceTree(world, pos, state, random);
|
||||
}
|
||||
} else {
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/PitcherCropBlock.java b/src/main/java/net/minecraft/world/level/block/PitcherCropBlock.java
|
||||
index 972d8833127090c01d620cab10b3eca3d3601710..ea6135edc76c06b7cd55930b620dfb05f939e4f6 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/PitcherCropBlock.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/PitcherCropBlock.java
|
||||
@@ -132,7 +132,7 @@ public class PitcherCropBlock extends DoublePlantBlock implements BonemealableBl
|
||||
@Override
|
||||
public void randomTick(BlockState state, ServerLevel world, BlockPos pos, RandomSource random) {
|
||||
float f = CropBlock.getGrowthSpeed(this, world, pos);
|
||||
- boolean bl = random.nextInt((int)(25.0F / f) + 1) == 0;
|
||||
+ boolean bl = random.nextFloat() < (world.spigotConfig.pitcherPlantModifier / (100.0F * (Math.floor(25.0F / f) + 1))); // Paper - Fix Spigot growth modifiers
|
||||
if (bl) {
|
||||
this.grow(world, state, pos, 1);
|
||||
}
|
||||
diff --git a/src/main/java/org/spigotmc/SpigotWorldConfig.java b/src/main/java/org/spigotmc/SpigotWorldConfig.java
|
||||
index 491dd55b2870093184a606efabd251c68cc24719..e76f96a5c48d1eda2f9bbb3e11dd79f23f9ab75c 100644
|
||||
--- a/src/main/java/org/spigotmc/SpigotWorldConfig.java
|
||||
+++ b/src/main/java/org/spigotmc/SpigotWorldConfig.java
|
||||
@@ -96,6 +96,7 @@ public class SpigotWorldConfig
|
||||
public int beetrootModifier;
|
||||
public int carrotModifier;
|
||||
public int potatoModifier;
|
||||
+ public int torchFlowerModifier; // Paper
|
||||
public int wheatModifier;
|
||||
public int wartModifier;
|
||||
public int vineModifier;
|
||||
@@ -106,6 +107,8 @@ public class SpigotWorldConfig
|
||||
public int twistingVinesModifier;
|
||||
public int weepingVinesModifier;
|
||||
public int caveVinesModifier;
|
||||
+ public int glowBerryModifier; // Paper
|
||||
+ public int pitcherPlantModifier; // Paper
|
||||
private int getAndValidateGrowth(String crop)
|
||||
{
|
||||
int modifier = this.getInt( "growth." + crop.toLowerCase(java.util.Locale.ENGLISH) + "-modifier", 100 );
|
||||
@@ -129,6 +132,7 @@ public class SpigotWorldConfig
|
||||
this.beetrootModifier = this.getAndValidateGrowth( "Beetroot" );
|
||||
this.carrotModifier = this.getAndValidateGrowth( "Carrot" );
|
||||
this.potatoModifier = this.getAndValidateGrowth( "Potato" );
|
||||
+ this.torchFlowerModifier = this.getAndValidateGrowth("TorchFlower"); // Paper
|
||||
this.wheatModifier = this.getAndValidateGrowth( "Wheat" );
|
||||
this.wartModifier = this.getAndValidateGrowth( "NetherWart" );
|
||||
this.vineModifier = this.getAndValidateGrowth( "Vine" );
|
||||
@@ -139,6 +143,8 @@ public class SpigotWorldConfig
|
||||
this.twistingVinesModifier = this.getAndValidateGrowth( "TwistingVines" );
|
||||
this.weepingVinesModifier = this.getAndValidateGrowth( "WeepingVines" );
|
||||
this.caveVinesModifier = this.getAndValidateGrowth( "CaveVines" );
|
||||
+ this.glowBerryModifier = this.getAndValidateGrowth("GlowBerry"); // Paper
|
||||
+ this.pitcherPlantModifier = this.getAndValidateGrowth("PitcherPlant"); // Paper
|
||||
}
|
||||
|
||||
public double itemMerge;
|
|
@ -0,0 +1,18 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Shane Freeder <theboyetronic@gmail.com>
|
||||
Date: Tue, 30 Nov 2021 05:30:35 +0000
|
||||
Subject: [PATCH] Prevent ContainerOpenersCounter openCount from going negative
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/entity/ContainerOpenersCounter.java b/src/main/java/net/minecraft/world/level/block/entity/ContainerOpenersCounter.java
|
||||
index 43e4e893f0e7eed1959e6ccfa43c39ff00f083b3..86dce6796f92a5b0ae2b1bd837267c4e3f6754d0 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/entity/ContainerOpenersCounter.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/entity/ContainerOpenersCounter.java
|
||||
@@ -69,6 +69,7 @@ public abstract class ContainerOpenersCounter {
|
||||
|
||||
public void decrementOpeners(Player player, Level world, BlockPos pos, BlockState state) {
|
||||
int oldPower = Math.max(0, Math.min(15, this.openCount)); // CraftBukkit - Get power before new viewer is added
|
||||
+ if (this.openCount == 0) return; // Paper - Prevent ContainerOpenersCounter openCount from going negative
|
||||
int i = this.openCount--;
|
||||
|
||||
// CraftBukkit start - Call redstone event
|
61
patches/server/0627-Add-PlayerItemFrameChangeEvent.patch
Normal file
61
patches/server/0627-Add-PlayerItemFrameChangeEvent.patch
Normal file
|
@ -0,0 +1,61 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: SamB440 <sam@islandearth.net>
|
||||
Date: Mon, 15 Nov 2021 18:10:10 +0000
|
||||
Subject: [PATCH] Add PlayerItemFrameChangeEvent
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/decoration/ItemFrame.java b/src/main/java/net/minecraft/world/entity/decoration/ItemFrame.java
|
||||
index c0deabf9d86d086fbd8cbaac5a02badf5c01c870..30af4cbb17148c247a46c0346419d6c838dbc9d2 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/decoration/ItemFrame.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/decoration/ItemFrame.java
|
||||
@@ -1,6 +1,7 @@
|
||||
package net.minecraft.world.entity.decoration;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
+import io.papermc.paper.event.player.PlayerItemFrameChangeEvent; // Paper - Add PlayerItemFrameChangeEvent
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.core.component.DataComponents;
|
||||
@@ -166,6 +167,13 @@ public class ItemFrame extends HangingEntity {
|
||||
return true;
|
||||
}
|
||||
// CraftBukkit end
|
||||
+ // Paper start - Add PlayerItemFrameChangeEvent
|
||||
+ if (source.getEntity() instanceof Player player) {
|
||||
+ var event = new PlayerItemFrameChangeEvent((org.bukkit.entity.Player) player.getBukkitEntity(), (org.bukkit.entity.ItemFrame) this.getBukkitEntity(), this.getItem().asBukkitCopy(), PlayerItemFrameChangeEvent.ItemFrameChangeAction.REMOVE);
|
||||
+ if (!event.callEvent()) return true; // return true here because you aren't cancelling the damage, just the change
|
||||
+ this.setItem(ItemStack.fromBukkitCopy(event.getItemStack()), false);
|
||||
+ }
|
||||
+ // Paper end - Add PlayerItemFrameChangeEvent
|
||||
this.dropItem(world, source.getEntity(), false);
|
||||
this.gameEvent(GameEvent.BLOCK_CHANGE, source.getEntity());
|
||||
this.playSound(this.getRemoveItemSound(), 1.0F, 1.0F);
|
||||
@@ -403,7 +411,13 @@ public class ItemFrame extends HangingEntity {
|
||||
if (worldmap != null && worldmap.isTrackedCountOverLimit(256)) {
|
||||
return InteractionResult.FAIL;
|
||||
} else {
|
||||
- this.setItem(itemstack);
|
||||
+ // Paper start - Add PlayerItemFrameChangeEvent
|
||||
+ PlayerItemFrameChangeEvent event = new PlayerItemFrameChangeEvent((org.bukkit.entity.Player) player.getBukkitEntity(), (org.bukkit.entity.ItemFrame) this.getBukkitEntity(), itemstack.asBukkitCopy(), PlayerItemFrameChangeEvent.ItemFrameChangeAction.PLACE);
|
||||
+ if (!event.callEvent()) {
|
||||
+ return InteractionResult.FAIL;
|
||||
+ }
|
||||
+ this.setItem(ItemStack.fromBukkitCopy(event.getItemStack()));
|
||||
+ // Paper end - Add PlayerItemFrameChangeEvent
|
||||
this.gameEvent(GameEvent.BLOCK_CHANGE, player);
|
||||
itemstack.consume(1, player);
|
||||
return InteractionResult.SUCCESS;
|
||||
@@ -412,6 +426,13 @@ public class ItemFrame extends HangingEntity {
|
||||
return InteractionResult.PASS;
|
||||
}
|
||||
} else {
|
||||
+ // Paper start - Add PlayerItemFrameChangeEvent
|
||||
+ PlayerItemFrameChangeEvent event = new PlayerItemFrameChangeEvent((org.bukkit.entity.Player) player.getBukkitEntity(), (org.bukkit.entity.ItemFrame) this.getBukkitEntity(), this.getItem().asBukkitCopy(), PlayerItemFrameChangeEvent.ItemFrameChangeAction.ROTATE);
|
||||
+ if (!event.callEvent()) {
|
||||
+ return InteractionResult.FAIL;
|
||||
+ }
|
||||
+ setItem(ItemStack.fromBukkitCopy(event.getItemStack()), false, false);
|
||||
+ // Paper end - Add PlayerItemFrameChangeEvent
|
||||
this.playSound(this.getRotateItemSound(), 1.0F, 1.0F);
|
||||
this.setRotation(this.getRotation() + 1);
|
||||
this.gameEvent(GameEvent.BLOCK_CHANGE, player);
|
57
patches/server/0628-Optimize-HashMapPalette.patch
Normal file
57
patches/server/0628-Optimize-HashMapPalette.patch
Normal file
|
@ -0,0 +1,57 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: stonar96 <minecraft.stonar96@gmail.com>
|
||||
Date: Sun, 17 Jan 2021 01:11:36 +0100
|
||||
Subject: [PATCH] Optimize HashMapPalette
|
||||
|
||||
HashMapPalette uses an instance of CrudeIncrementalIntIdentityHashBiMap
|
||||
internally. A Palette has a preset maximum size = 1 << bits.
|
||||
CrudeIncrementalIntIdentityHashBiMap has an initial size but is
|
||||
automatically resized. The CrudeIncrementalIntIdentityHashBiMap is created
|
||||
with the maximum size in the constructor of HashMapPalette, with the aim
|
||||
that it doesn't need to be resized anymore. However, there are two things
|
||||
that I think Mojang hasn't considered here:
|
||||
1) The CrudeIncrementalIntIdentityHashBiMap is resized, when its initial
|
||||
size is reached and not the next time, when a further object is added.
|
||||
2) HashMapPalette adds objects (unnecessarily) before checking if the
|
||||
initial size of CrudeIncrementalIntIdentityHashBiMap is reached.
|
||||
This means to actually avoid resize operations in
|
||||
CrudeIncrementalIntIdentityHashBiMap, one has to add 2 to the initial size
|
||||
or add 1 and check the size before adding objects. This commit implements
|
||||
the second approach. Note that this isn't only an optimization but also
|
||||
makes async reads of Palettes fail-safe. An async read while the
|
||||
CrudeIncrementalIntIdentityHashBiMap is resized is fatal and can even lead
|
||||
to corrupted data. This is also something that Anti-Xray is currently
|
||||
relying on.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/chunk/HashMapPalette.java b/src/main/java/net/minecraft/world/level/chunk/HashMapPalette.java
|
||||
index ac673cb38755852eef37e915f157f6a702117306..98dbeaf8bde15940e5b5d5d1f13fd4bb32f0a10d 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/chunk/HashMapPalette.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/chunk/HashMapPalette.java
|
||||
@@ -20,7 +20,7 @@ public class HashMapPalette<T> implements Palette<T> {
|
||||
}
|
||||
|
||||
public HashMapPalette(IdMap<T> idList, int indexBits, PaletteResize<T> listener) {
|
||||
- this(idList, indexBits, listener, CrudeIncrementalIntIdentityHashBiMap.create(1 << indexBits));
|
||||
+ this(idList, indexBits, listener, CrudeIncrementalIntIdentityHashBiMap.create((1 << indexBits) + 1)); // Paper - Perf: Avoid unnecessary resize operation in CrudeIncrementalIntIdentityHashBiMap
|
||||
}
|
||||
|
||||
private HashMapPalette(IdMap<T> idList, int indexBits, PaletteResize<T> listener, CrudeIncrementalIntIdentityHashBiMap<T> map) {
|
||||
@@ -38,10 +38,16 @@ public class HashMapPalette<T> implements Palette<T> {
|
||||
public int idFor(T object) {
|
||||
int i = this.values.getId(object);
|
||||
if (i == -1) {
|
||||
- i = this.values.add(object);
|
||||
- if (i >= 1 << this.bits) {
|
||||
+ // Paper start - Perf: Avoid unnecessary resize operation in CrudeIncrementalIntIdentityHashBiMap and optimize
|
||||
+ // We use size() instead of the result from add(K)
|
||||
+ // This avoids adding another object unnecessarily
|
||||
+ // Without this change, + 2 would be required in the constructor
|
||||
+ if (this.values.size() >= 1 << this.bits) {
|
||||
i = this.resizeHandler.onResize(this.bits + 1, object);
|
||||
+ } else {
|
||||
+ i = this.values.add(object);
|
||||
}
|
||||
+ // Paper end - Perf: Avoid unnecessary resize operation in CrudeIncrementalIntIdentityHashBiMap and optimize
|
||||
}
|
||||
|
||||
return i;
|
|
@ -0,0 +1,44 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jason Penilla <11360596+jpenilla@users.noreply.github.com>
|
||||
Date: Thu, 9 Dec 2021 00:08:11 -0800
|
||||
Subject: [PATCH] Fix ChunkSnapshot#isSectionEmpty(int) and optimize
|
||||
PalettedContainer copying by not using codecs
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftChunk.java b/src/main/java/org/bukkit/craftbukkit/CraftChunk.java
|
||||
index b2d85abb6c9c725955d972cd6895440849213fdf..887a17a0833064eb5701222e5fb6f5ccf9511588 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftChunk.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftChunk.java
|
||||
@@ -338,14 +338,17 @@ public class CraftChunk implements Chunk {
|
||||
PalettedContainerRO<Holder<net.minecraft.world.level.biome.Biome>>[] biome = (includeBiome || includeBiomeTempRain) ? new PalettedContainer[cs.length] : null;
|
||||
|
||||
Registry<net.minecraft.world.level.biome.Biome> iregistry = this.worldServer.registryAccess().lookupOrThrow(Registries.BIOME);
|
||||
- Codec<PalettedContainerRO<Holder<net.minecraft.world.level.biome.Biome>>> biomeCodec = PalettedContainer.codecRO(iregistry.asHolderIdMap(), iregistry.holderByNameCodec(), PalettedContainer.Strategy.SECTION_BIOMES, iregistry.getOrThrow(Biomes.PLAINS));
|
||||
|
||||
for (int i = 0; i < cs.length; i++) {
|
||||
- CompoundTag data = new CompoundTag();
|
||||
|
||||
- data.put("block_states", SerializableChunkData.BLOCK_STATE_CODEC.encodeStart(NbtOps.INSTANCE, cs[i].getStates()).getOrThrow());
|
||||
- sectionBlockIDs[i] = SerializableChunkData.BLOCK_STATE_CODEC.parse(NbtOps.INSTANCE, data.getCompound("block_states")).getOrThrow(SerializableChunkData.ChunkReadException::new);
|
||||
- sectionEmpty[i] = cs[i].hasOnlyAir();
|
||||
+ // Paper start - Fix ChunkSnapshot#isSectionEmpty(int); and remove codec usage
|
||||
+ sectionEmpty[i] = cs[i].hasOnlyAir(); // fix sectionEmpty array not being filled
|
||||
+ if (!sectionEmpty[i]) {
|
||||
+ sectionBlockIDs[i] = cs[i].getStates().copy(); // use copy instead of round tripping with codecs
|
||||
+ } else {
|
||||
+ sectionBlockIDs[i] = CraftChunk.emptyBlockIDs; // use cached instance for empty block sections
|
||||
+ }
|
||||
+ // Paper end - Fix ChunkSnapshot#isSectionEmpty(int)
|
||||
|
||||
LevelLightEngine lightengine = this.worldServer.getLightEngine();
|
||||
DataLayer skyLightArray = lightengine.getLayerListener(LightLayer.SKY).getDataLayerData(SectionPos.of(this.x, chunk.getSectionYFromSectionIndex(i), this.z)); // SPIGOT-7498: Convert section index
|
||||
@@ -364,8 +367,7 @@ public class CraftChunk implements Chunk {
|
||||
}
|
||||
|
||||
if (biome != null) {
|
||||
- data.put("biomes", biomeCodec.encodeStart(NbtOps.INSTANCE, cs[i].getBiomes()).getOrThrow());
|
||||
- biome[i] = biomeCodec.parse(NbtOps.INSTANCE, data.getCompound("biomes")).getOrThrow(SerializableChunkData.ChunkReadException::new);
|
||||
+ biome[i] = ((PalettedContainer<Holder<net.minecraft.world.level.biome.Biome>>) cs[i].getBiomes()).copy(); // Paper - Perf: use copy instead of round tripping with codecs
|
||||
}
|
||||
}
|
||||
|
111
patches/server/0630-Add-more-Campfire-API.patch
Normal file
111
patches/server/0630-Add-more-Campfire-API.patch
Normal file
|
@ -0,0 +1,111 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: LemonCaramel <admin@caramel.moe>
|
||||
Date: Fri, 16 Jul 2021 00:39:03 +0900
|
||||
Subject: [PATCH] Add more Campfire API
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/entity/CampfireBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/CampfireBlockEntity.java
|
||||
index 7fa1aea7942a1bc4d9779a9f8ab020ccd5566923..94072a9b65f69dfc3337907f8573081989467662 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/entity/CampfireBlockEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/entity/CampfireBlockEntity.java
|
||||
@@ -46,12 +46,14 @@ public class CampfireBlockEntity extends BlockEntity implements Clearable {
|
||||
private final NonNullList<ItemStack> items;
|
||||
public final int[] cookingProgress;
|
||||
public final int[] cookingTime;
|
||||
+ public final boolean[] stopCooking; // Paper - Add more Campfire API
|
||||
|
||||
public CampfireBlockEntity(BlockPos pos, BlockState state) {
|
||||
super(BlockEntityType.CAMPFIRE, pos, state);
|
||||
this.items = NonNullList.withSize(4, ItemStack.EMPTY);
|
||||
this.cookingProgress = new int[4];
|
||||
this.cookingTime = new int[4];
|
||||
+ this.stopCooking = new boolean[4]; // Paper - Add more Campfire API
|
||||
}
|
||||
|
||||
public static void cookTick(ServerLevel world, BlockPos pos, BlockState state, CampfireBlockEntity blockEntity, RecipeManager.CachedCheck<SingleRecipeInput, CampfireCookingRecipe> recipeMatchGetter) {
|
||||
@@ -62,7 +64,9 @@ public class CampfireBlockEntity extends BlockEntity implements Clearable {
|
||||
|
||||
if (!itemstack.isEmpty()) {
|
||||
flag = true;
|
||||
+ if (!blockEntity.stopCooking[i]) { // Paper - Add more Campfire API
|
||||
int j = blockEntity.cookingProgress[i]++;
|
||||
+ } // Paper - Add more Campfire API
|
||||
|
||||
if (blockEntity.cookingProgress[i] >= blockEntity.cookingTime[i]) {
|
||||
SingleRecipeInput singlerecipeinput = new SingleRecipeInput(itemstack);
|
||||
@@ -175,6 +179,16 @@ public class CampfireBlockEntity extends BlockEntity implements Clearable {
|
||||
System.arraycopy(aint, 0, this.cookingTime, 0, Math.min(this.cookingTime.length, aint.length));
|
||||
}
|
||||
|
||||
+ // Paper start - Add more Campfire API
|
||||
+ if (nbt.contains("Paper.StopCooking", org.bukkit.craftbukkit.util.CraftMagicNumbers.NBT.TAG_BYTE_ARRAY)) {
|
||||
+ byte[] abyte = nbt.getByteArray("Paper.StopCooking");
|
||||
+ boolean[] cookingState = new boolean[4];
|
||||
+ for (int index = 0; index < abyte.length; index++) {
|
||||
+ cookingState[index] = abyte[index] == 1;
|
||||
+ }
|
||||
+ System.arraycopy(cookingState, 0, this.stopCooking, 0, Math.min(this.stopCooking.length, abyte.length));
|
||||
+ }
|
||||
+ // Paper end - Add more Campfire API
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -183,6 +197,13 @@ public class CampfireBlockEntity extends BlockEntity implements Clearable {
|
||||
ContainerHelper.saveAllItems(nbt, this.items, true, registries);
|
||||
nbt.putIntArray("CookingTimes", this.cookingProgress);
|
||||
nbt.putIntArray("CookingTotalTimes", this.cookingTime);
|
||||
+ // Paper start - Add more Campfire API
|
||||
+ byte[] cookingState = new byte[4];
|
||||
+ for (int index = 0; index < cookingState.length; index++) {
|
||||
+ cookingState[index] = (byte) (this.stopCooking[index] ? 1 : 0);
|
||||
+ }
|
||||
+ nbt.putByteArray("Paper.StopCooking", cookingState);
|
||||
+ // Paper end - Add more Campfire API
|
||||
}
|
||||
|
||||
@Override
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftCampfire.java b/src/main/java/org/bukkit/craftbukkit/block/CraftCampfire.java
|
||||
index 4850cbf2c326f1155e04a204abed2d200c02342d..a776bba2ec51c6aecce98a3abceb2c235522d99d 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftCampfire.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftCampfire.java
|
||||
@@ -62,4 +62,40 @@ public class CraftCampfire extends CraftBlockEntityState<CampfireBlockEntity> im
|
||||
public CraftCampfire copy(Location location) {
|
||||
return new CraftCampfire(this, location);
|
||||
}
|
||||
+
|
||||
+ // Paper start
|
||||
+ @Override
|
||||
+ public void stopCooking() {
|
||||
+ for (int i = 0; i < getSnapshot().stopCooking.length; ++i)
|
||||
+ this.stopCooking(i);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void startCooking() {
|
||||
+ for (int i = 0; i < getSnapshot().stopCooking.length; ++i)
|
||||
+ this.startCooking(i);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean stopCooking(int index) {
|
||||
+ org.apache.commons.lang.Validate.isTrue(-1 < index && index < 4, "Slot index must be between 0 (incl) to 3 (incl)");
|
||||
+ boolean previous = this.isCookingDisabled(index);
|
||||
+ getSnapshot().stopCooking[index] = true;
|
||||
+ return previous;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean startCooking(int index) {
|
||||
+ org.apache.commons.lang.Validate.isTrue(-1 < index && index < 4, "Slot index must be between 0 (incl) to 3 (incl)");
|
||||
+ boolean previous = this.isCookingDisabled(index);
|
||||
+ getSnapshot().stopCooking[index] = false;
|
||||
+ return previous;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean isCookingDisabled(int index) {
|
||||
+ org.apache.commons.lang.Validate.isTrue(-1 < index && index < 4, "Slot index must be between 0 (incl) to 3 (incl)");
|
||||
+ return getSnapshot().stopCooking[index];
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
|
@ -0,0 +1,94 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
|
||||
Date: Sun, 19 Dec 2021 09:13:41 -0800
|
||||
Subject: [PATCH] Only write chunk data to disk if it serializes without
|
||||
throwing
|
||||
|
||||
This ensures at least a valid version of the chunk exists
|
||||
on disk, even if outdated
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java
|
||||
index 12b7d50f49a2184aaf220a4a50a137b217c57124..f1237f6fd6414900ffbad0caee31aa83310eeef4 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java
|
||||
@@ -442,6 +442,7 @@ public class RegionFile implements AutoCloseable {
|
||||
|
||||
}
|
||||
|
||||
+ public static final int MAX_CHUNK_SIZE = 500 * 1024 * 1024; // Paper - don't write garbage data to disk if writing serialization fails
|
||||
private class ChunkBuffer extends ByteArrayOutputStream {
|
||||
|
||||
private final ChunkPos pos;
|
||||
@@ -455,6 +456,23 @@ public class RegionFile implements AutoCloseable {
|
||||
super.write(RegionFile.this.version.getId());
|
||||
this.pos = chunkcoordintpair;
|
||||
}
|
||||
+ // Paper start - don't write garbage data to disk if writing serialization fails
|
||||
+ @Override
|
||||
+ public void write(final int b) {
|
||||
+ if (this.count > MAX_CHUNK_SIZE) {
|
||||
+ throw new RegionFileStorage.RegionFileSizeException("Region file too large: " + this.count);
|
||||
+ }
|
||||
+ super.write(b);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void write(final byte[] b, final int off, final int len) {
|
||||
+ if (this.count + len > MAX_CHUNK_SIZE) {
|
||||
+ throw new RegionFileStorage.RegionFileSizeException("Region file too large: " + (this.count + len));
|
||||
+ }
|
||||
+ super.write(b, off, len);
|
||||
+ }
|
||||
+ // Paper end - don't write garbage data to disk if writing serialization fails
|
||||
|
||||
public void close() throws IOException {
|
||||
ByteBuffer bytebuffer = ByteBuffer.wrap(this.buf, 0, this.count);
|
||||
diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java
|
||||
index 491035aaefff4ee96435ec5d3f9417e28eae0796..4c1212c6ef48594e766fa9e35a6e15916602d587 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java
|
||||
@@ -147,10 +147,17 @@ public final class RegionFileStorage implements AutoCloseable {
|
||||
|
||||
try {
|
||||
NbtIo.write(nbt, (DataOutput) dataoutputstream);
|
||||
+ // Paper start - don't write garbage data to disk if writing serialization fails
|
||||
+ dataoutputstream.close(); // Only write if successful
|
||||
+ } catch (final RegionFileSizeException e) {
|
||||
+ attempts = 5; // Don't retry
|
||||
+ regionfile.clear(pos);
|
||||
+ throw e;
|
||||
+ // Paper end - don't write garbage data to disk if writing serialization fails
|
||||
} catch (Throwable throwable) {
|
||||
if (dataoutputstream != null) {
|
||||
try {
|
||||
- dataoutputstream.close();
|
||||
+ //dataoutputstream.close(); // Paper - don't write garbage data to disk if writing serialization fails
|
||||
} catch (Throwable throwable1) {
|
||||
throwable.addSuppressed(throwable1);
|
||||
}
|
||||
@@ -158,10 +165,7 @@ public final class RegionFileStorage implements AutoCloseable {
|
||||
|
||||
throw throwable;
|
||||
}
|
||||
-
|
||||
- if (dataoutputstream != null) {
|
||||
- dataoutputstream.close();
|
||||
- }
|
||||
+ // Paper - don't write garbage data to disk if writing serialization fails; move into try block to only write if successfully serialized
|
||||
}
|
||||
// Paper start - Chunk save reattempt
|
||||
return;
|
||||
@@ -208,4 +212,13 @@ public final class RegionFileStorage implements AutoCloseable {
|
||||
public RegionStorageInfo info() {
|
||||
return this.info;
|
||||
}
|
||||
+
|
||||
+ // Paper start - don't write garbage data to disk if writing serialization fails
|
||||
+ public static final class RegionFileSizeException extends RuntimeException {
|
||||
+
|
||||
+ public RegionFileSizeException(String message) {
|
||||
+ super(message);
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end - don't write garbage data to disk if writing serialization fails
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
Date: Sat, 4 Dec 2021 17:04:47 -0800
|
||||
Subject: [PATCH] Forward CraftEntity in teleport command
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
index e311601d8e39e7ea632bc4805260da6d7d6d6776..1497c3b79e6dc9ecc270c0fd2003e606f967a56e 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
@@ -3480,6 +3480,13 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
|
||||
}
|
||||
|
||||
public void restoreFrom(Entity original) {
|
||||
+ // Paper start - Forward CraftEntity in teleport command
|
||||
+ CraftEntity bukkitEntity = original.bukkitEntity;
|
||||
+ if (bukkitEntity != null) {
|
||||
+ bukkitEntity.setHandle(this);
|
||||
+ this.bukkitEntity = bukkitEntity;
|
||||
+ }
|
||||
+ // Paper end - Forward CraftEntity in teleport command
|
||||
CompoundTag nbttagcompound = original.saveWithoutId(new CompoundTag());
|
||||
|
||||
nbttagcompound.remove("Dimension");
|
||||
@@ -3615,8 +3622,8 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
|
||||
entity.restoreFrom(this);
|
||||
this.removeAfterChangingDimensions();
|
||||
// CraftBukkit start - Forward the CraftEntity to the new entity
|
||||
- this.getBukkitEntity().setHandle(entity);
|
||||
- entity.bukkitEntity = this.getBukkitEntity();
|
||||
+ //this.getBukkitEntity().setHandle(entity);
|
||||
+ //entity.bukkitEntity = this.getBukkitEntity(); // Paper - forward CraftEntity in teleport command; moved to Entity#restoreFrom
|
||||
// CraftBukkit end
|
||||
entity.teleportSetPosition(PositionMoveRotation.of(teleportTarget), teleportTarget.relatives());
|
||||
if (this.inWorld) world.addDuringTeleport(entity); // CraftBukkit - Don't spawn the new entity if the current entity isn't spawned
|
88
patches/server/0633-Improve-scoreboard-entries.patch
Normal file
88
patches/server/0633-Improve-scoreboard-entries.patch
Normal file
|
@ -0,0 +1,88 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jake Potrebic <jake.m.potrebic@gmail.com>
|
||||
Date: Thu, 4 Nov 2021 12:31:24 -0700
|
||||
Subject: [PATCH] Improve scoreboard entries
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftObjective.java b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftObjective.java
|
||||
index da1e4496d78a2c1b258ff8bb316414cb8a662ba2..b36e5574c10e6d70a399e2ac0704fd4f43dbb444 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftObjective.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftObjective.java
|
||||
@@ -144,6 +144,15 @@ final class CraftObjective extends CraftScoreboardComponent implements Objective
|
||||
return new CraftScore(this, CraftScoreboard.getScoreHolder(entry));
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ @Override
|
||||
+ public Score getScoreFor(org.bukkit.entity.Entity entity) throws IllegalArgumentException, IllegalStateException {
|
||||
+ Preconditions.checkArgument(entity != null, "Entity cannot be null");
|
||||
+ this.checkState();
|
||||
+ return new CraftScore(this, ((org.bukkit.craftbukkit.entity.CraftEntity) entity).getHandle());
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
@Override
|
||||
public void unregister() {
|
||||
CraftScoreboard scoreboard = this.checkState();
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboard.java b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboard.java
|
||||
index c650fc3712de01184509a03f1d1b388859e163d7..253574890a9ed23d38a84680ba1eb221dc72b310 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboard.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboard.java
|
||||
@@ -235,6 +235,26 @@ public final class CraftScoreboard implements org.bukkit.scoreboard.Scoreboard {
|
||||
this.board.setDisplayObjective(CraftScoreboardTranslations.fromBukkitSlot(slot), null);
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ @Override
|
||||
+ public ImmutableSet<Score> getScoresFor(org.bukkit.entity.Entity entity) throws IllegalArgumentException {
|
||||
+ Preconditions.checkArgument(entity != null, "Entity cannot be null");
|
||||
+ return this.getScores(((org.bukkit.craftbukkit.entity.CraftEntity) entity).getHandle());
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void resetScoresFor(org.bukkit.entity.Entity entity) throws IllegalArgumentException {
|
||||
+ Preconditions.checkArgument(entity != null, "Entity cannot be null");
|
||||
+ this.resetScores(((org.bukkit.craftbukkit.entity.CraftEntity) entity).getHandle());
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public Team getEntityTeam(org.bukkit.entity.Entity entity) throws IllegalArgumentException {
|
||||
+ Preconditions.checkArgument(entity != null, "Entity cannot be null");
|
||||
+ return this.getEntryTeam(((org.bukkit.craftbukkit.entity.CraftEntity) entity).getHandle().getScoreboardName());
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
// CraftBukkit method
|
||||
public Scoreboard getHandle() {
|
||||
return this.board;
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java
|
||||
index 7900adb0b158bc17dd792dd082c338547bc1aa0a..27219bf2f16aed64c78623d44c3cc84aa9f47065 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftTeam.java
|
||||
@@ -304,6 +304,26 @@ final class CraftTeam extends CraftScoreboardComponent implements Team {
|
||||
}
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ @Override
|
||||
+ public void addEntity(org.bukkit.entity.Entity entity) throws IllegalStateException, IllegalArgumentException {
|
||||
+ Preconditions.checkArgument(entity != null, "Entity cannot be null");
|
||||
+ this.addEntry(((org.bukkit.craftbukkit.entity.CraftEntity) entity).getHandle().getScoreboardName());
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean removeEntity(org.bukkit.entity.Entity entity) throws IllegalStateException, IllegalArgumentException {
|
||||
+ Preconditions.checkArgument(entity != null, "Entity cannot be null");
|
||||
+ return this.removeEntry(((org.bukkit.craftbukkit.entity.CraftEntity) entity).getHandle().getScoreboardName());
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean hasEntity(org.bukkit.entity.Entity entity) throws IllegalStateException, IllegalArgumentException {
|
||||
+ Preconditions.checkArgument(entity != null, "Entity cannot be null");
|
||||
+ return this.hasEntry(((org.bukkit.craftbukkit.entity.CraftEntity) entity).getHandle().getScoreboardName());
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
public static Visibility bukkitToNotch(NameTagVisibility visibility) {
|
||||
switch (visibility) {
|
||||
case ALWAYS:
|
Loading…
Add table
Add a link
Reference in a new issue