mirror of
https://github.com/PaperMC/Paper.git
synced 2025-04-18 03:19:34 +02:00
Merge remote-tracking branch 'up/main' into update/1.21.5
# Conflicts: # paper-api/src/main/java/io/papermc/paper/registry/RegistryKey.java # paper-api/src/main/java/org/bukkit/event/block/BlockBurnEvent.java # paper-api/src/main/java/org/bukkit/event/block/BlockCanBuildEvent.java # paper-api/src/main/java/org/bukkit/event/block/BlockCookEvent.java # paper-api/src/main/java/org/bukkit/event/block/BlockMultiPlaceEvent.java # paper-api/src/main/java/org/bukkit/event/block/BlockPhysicsEvent.java # paper-api/src/main/java/org/bukkit/event/block/BlockPistonExtendEvent.java # paper-api/src/main/java/org/bukkit/event/block/BlockPlaceEvent.java # paper-api/src/main/java/org/bukkit/event/block/SignChangeEvent.java # paper-api/src/main/java/org/bukkit/event/entity/EntityCombustByBlockEvent.java # paper-api/src/main/java/org/bukkit/event/entity/EntityCombustByEntityEvent.java # paper-api/src/main/java/org/bukkit/event/entity/EntityCombustEvent.java # paper-api/src/main/java/org/bukkit/event/entity/EntityDamageByEntityEvent.java # paper-api/src/main/java/org/bukkit/event/entity/EntityPlaceEvent.java # paper-api/src/main/java/org/bukkit/event/entity/EntityResurrectEvent.java # paper-api/src/main/java/org/bukkit/event/entity/EntityShootBowEvent.java # paper-api/src/main/java/org/bukkit/event/entity/EntityUnleashEvent.java # paper-api/src/main/java/org/bukkit/event/entity/ExpBottleEvent.java # paper-api/src/main/java/org/bukkit/event/entity/ItemSpawnEvent.java # paper-api/src/main/java/org/bukkit/event/entity/LingeringPotionSplashEvent.java # paper-api/src/main/java/org/bukkit/event/entity/PlayerDeathEvent.java # paper-api/src/main/java/org/bukkit/event/entity/PlayerLeashEntityEvent.java # paper-api/src/main/java/org/bukkit/event/entity/PotionSplashEvent.java # paper-api/src/main/java/org/bukkit/event/entity/ProjectileHitEvent.java # paper-api/src/main/java/org/bukkit/event/entity/SheepDyeWoolEvent.java # paper-api/src/main/java/org/bukkit/event/inventory/FurnaceSmeltEvent.java # paper-api/src/main/java/org/bukkit/event/inventory/FurnaceStartSmeltEvent.java # paper-api/src/main/java/org/bukkit/event/player/AsyncPlayerPreLoginEvent.java # paper-api/src/main/java/org/bukkit/event/player/PlayerAnimationEvent.java # paper-api/src/main/java/org/bukkit/event/player/PlayerArmorStandManipulateEvent.java # paper-api/src/main/java/org/bukkit/event/player/PlayerAttemptPickupItemEvent.java # paper-api/src/main/java/org/bukkit/event/player/PlayerBedEnterEvent.java # paper-api/src/main/java/org/bukkit/event/player/PlayerBucketEmptyEvent.java # paper-api/src/main/java/org/bukkit/event/player/PlayerBucketEvent.java # paper-api/src/main/java/org/bukkit/event/player/PlayerBucketFillEvent.java # paper-api/src/main/java/org/bukkit/event/player/PlayerGameModeChangeEvent.java # paper-api/src/main/java/org/bukkit/event/player/PlayerHarvestBlockEvent.java # paper-api/src/main/java/org/bukkit/event/player/PlayerItemConsumeEvent.java # paper-api/src/main/java/org/bukkit/event/player/PlayerItemDamageEvent.java # paper-api/src/main/java/org/bukkit/event/player/PlayerItemMendEvent.java # paper-api/src/main/java/org/bukkit/event/player/PlayerJoinEvent.java # paper-api/src/main/java/org/bukkit/event/player/PlayerKickEvent.java # paper-api/src/main/java/org/bukkit/event/player/PlayerLoginEvent.java # paper-api/src/main/java/org/bukkit/event/player/PlayerPortalEvent.java # paper-api/src/main/java/org/bukkit/event/player/PlayerPreLoginEvent.java # paper-api/src/main/java/org/bukkit/event/player/PlayerQuitEvent.java # paper-api/src/main/java/org/bukkit/event/player/PlayerRespawnEvent.java # paper-api/src/main/java/org/bukkit/event/player/PlayerRiptideEvent.java # paper-api/src/main/java/org/bukkit/event/player/PlayerShearEntityEvent.java # paper-api/src/main/java/org/bukkit/event/player/PlayerUnleashEntityEvent.java # paper-api/src/main/java/org/bukkit/event/server/BroadcastMessageEvent.java # paper-api/src/main/java/org/bukkit/event/server/ServerListPingEvent.java # paper-api/src/main/java/org/bukkit/event/vehicle/VehicleBlockCollisionEvent.java # paper-api/src/main/java/org/bukkit/event/weather/LightningStrikeEvent.java # paper-api/src/main/java/org/bukkit/event/weather/ThunderChangeEvent.java # paper-api/src/main/java/org/bukkit/event/weather/WeatherChangeEvent.java # paper-api/src/main/java/org/bukkit/event/world/PortalCreateEvent.java # paper-server/patches/features/0003-Entity-Activation-Range-2.0.patch # paper-server/patches/sources/net/minecraft/server/level/ServerPlayer.java.patch # paper-server/patches/sources/net/minecraft/server/network/ServerGamePacketListenerImpl.java.patch # paper-server/patches/sources/net/minecraft/server/players/PlayerList.java.patch # paper-server/patches/sources/net/minecraft/world/inventory/AbstractContainerMenu.java.patch # paper-server/patches/sources/net/minecraft/world/inventory/ContainerSynchronizer.java.patch # paper-server/src/main/java/org/bukkit/craftbukkit/entity/CraftHumanEntity.java # paper-server/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemFactory.java # paper-server/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java
This commit is contained in:
commit
eafb6c2905
43 changed files with 409 additions and 95 deletions
CONTRIBUTING.md
build-data
build.gradle.ktspaper-api/src/main/java/org/bukkit
paper-server
patches
features
0003-Entity-Activation-Range-2.0.patch0016-Moonrise-optimisation-patches.patch0026-Optional-per-player-mob-spawns.patch0027-Improve-cancelling-PreCreatureSpawnEvent-with-per-pl.patch
sources/net/minecraft
src/main/java
io/papermc/paper
configuration
registry
org
|
@ -264,6 +264,40 @@ are assumed to be non-null by default. For less obvious placing such as on gener
|
|||
**For other classes**: Keep using both `@Nullable` and `@NotNull` from `org.jetbrains.annotations`. These
|
||||
will be replaced later.
|
||||
|
||||
### API checks
|
||||
|
||||
When performing API-related checks where an exception needs to be thrown under specific conditions, you should use the `Preconditions` class.
|
||||
|
||||
#### Checking Method Arguments
|
||||
To validate method arguments, use `Preconditions#checkArgument`. This will throw an `IllegalArgumentException` if the condition is not met.
|
||||
> Don't use Preconditions#checkNotNull, as it throws a NullPointerException, which makes it harder to determine whether the error was caused by an internal issue or invalid arguments.
|
||||
|
||||
ex:
|
||||
```java
|
||||
@Override
|
||||
public void sendMessage(Player player, Component message) {
|
||||
Preconditions.checkArgument(player != null, "player cannot be null");
|
||||
Preconditions.checkArgument(player.isOnline(), "player %s must be online", player.getName());
|
||||
Preconditions.checkArgument(message != null, "message cannot be null");
|
||||
// rest of code
|
||||
}
|
||||
```
|
||||
|
||||
#### Checking Object State
|
||||
To validate the state of an object inside a method, use `Preconditions#checkState`. This will throw an `IllegalStateException` if the condition is not met.
|
||||
ex:
|
||||
```java
|
||||
private Player player;
|
||||
|
||||
@Override
|
||||
public void sendMessage(Component message) {
|
||||
Preconditions.checkArgument(message != null, "message cannot be null");
|
||||
Preconditions.checkState(this.player != null, "player cannot be null");
|
||||
Preconditions.checkState(this.player.isOnline(), "player %s must be online", this.player.getName());
|
||||
// rest of code
|
||||
}
|
||||
```
|
||||
|
||||
## Access Transformers
|
||||
Sometimes, Vanilla code already contains a field, method, or type you want to access
|
||||
but the visibility is too low (e.g. a private field in an entity class). Paper can use access transformers
|
||||
|
|
|
@ -535,6 +535,7 @@ public net.minecraft.world.inventory.DispenserMenu dispenser
|
|||
public net.minecraft.world.inventory.HorseInventoryMenu SLOT_BODY_ARMOR
|
||||
public net.minecraft.world.inventory.HorseInventoryMenu SLOT_HORSE_INVENTORY_START
|
||||
public net.minecraft.world.inventory.HorseInventoryMenu SLOT_SADDLE
|
||||
public net.minecraft.world.inventory.HorseInventoryMenu horse
|
||||
public net.minecraft.world.inventory.MerchantContainer selectionHint
|
||||
public net.minecraft.world.inventory.Slot slot
|
||||
public net.minecraft.world.item.AdventureModePredicate predicates
|
||||
|
@ -652,6 +653,7 @@ public net.minecraft.world.level.block.entity.SculkSensorBlockEntity lastVibrati
|
|||
public net.minecraft.world.level.block.entity.SculkShriekerBlockEntity warningLevel
|
||||
public net.minecraft.world.level.block.entity.ShulkerBoxBlockEntity openCount
|
||||
public net.minecraft.world.level.block.entity.SignBlockEntity playerWhoMayEdit
|
||||
public net.minecraft.world.level.block.entity.SkullBlockEntity customName
|
||||
public net.minecraft.world.level.block.entity.SkullBlockEntity noteBlockSound
|
||||
public net.minecraft.world.level.block.entity.SkullBlockEntity owner
|
||||
public net.minecraft.world.level.block.entity.StructureBlockEntity author
|
||||
|
|
|
@ -38,6 +38,7 @@ subprojects {
|
|||
options.encoding = Charsets.UTF_8.name()
|
||||
options.release = 21
|
||||
options.isFork = true
|
||||
options.compilerArgs.addAll(listOf("-Xlint:-deprecation", "-Xlint:-removal"))
|
||||
}
|
||||
tasks.withType<Javadoc> {
|
||||
options.encoding = Charsets.UTF_8.name()
|
||||
|
|
|
@ -1117,20 +1117,24 @@ public final class Bukkit {
|
|||
|
||||
/**
|
||||
* Adds a recipe to the crafting manager.
|
||||
* Recipes added with this method won't be sent to the client automatically.
|
||||
* <p>
|
||||
* Players still have to discover recipes via {@link Player#discoverRecipe(NamespacedKey)}
|
||||
* before seeing them in their recipe book.
|
||||
*
|
||||
* @param recipe the recipe to add
|
||||
* @return true if the recipe was added, false if it wasn't for some
|
||||
* reason
|
||||
* @return true if the recipe was added, false if it wasn't for some reason
|
||||
* @see #addRecipe(Recipe, boolean)
|
||||
*/
|
||||
@Contract("null -> false")
|
||||
public static boolean addRecipe(@Nullable Recipe recipe) {
|
||||
return server.addRecipe(recipe);
|
||||
}
|
||||
|
||||
// Paper start - method to send recipes immediately
|
||||
/**
|
||||
* Adds a recipe to the crafting manager.
|
||||
*
|
||||
* @apiNote resendRecipes is ignored at the moment for stability reasons, recipes will always be updated
|
||||
* @param recipe the recipe to add
|
||||
* @param resendRecipes true to update the client with the full set of recipes
|
||||
* @return true if the recipe was added, false if it wasn't for some reason
|
||||
|
@ -1139,7 +1143,6 @@ public final class Bukkit {
|
|||
public static boolean addRecipe(@Nullable Recipe recipe, boolean resendRecipes) {
|
||||
return server.addRecipe(recipe, resendRecipes);
|
||||
}
|
||||
// Paper end - method to send recipes immediately
|
||||
|
||||
/**
|
||||
* Get a list of all recipes for a given item. The stack size is ignored
|
||||
|
|
|
@ -83,14 +83,12 @@ public final class NamespacedKey implements net.kyori.adventure.key.Key, com.des
|
|||
* @see #NamespacedKey(Plugin, String)
|
||||
*/
|
||||
public NamespacedKey(@NotNull String namespace, @NotNull String key) {
|
||||
Preconditions.checkArgument(namespace != null && isValidNamespace(namespace), "Invalid namespace. Must be [a-z0-9._-]: %s", namespace);
|
||||
Preconditions.checkArgument(key != null && isValidKey(key), "Invalid key. Must be [a-z0-9/._-]: %s", key);
|
||||
|
||||
Preconditions.checkArgument(namespace != null, "Namespace cannot be null");
|
||||
Preconditions.checkArgument(key != null, "Key cannot be null");
|
||||
this.namespace = namespace;
|
||||
this.key = key;
|
||||
|
||||
String string = toString();
|
||||
Preconditions.checkArgument(string.length() <= Short.MAX_VALUE, "NamespacedKey must be less than 32768 characters", string); // Paper - Fix improper length validation
|
||||
this.validate();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -108,16 +106,17 @@ public final class NamespacedKey implements net.kyori.adventure.key.Key, com.des
|
|||
public NamespacedKey(@NotNull Plugin plugin, @NotNull String key) {
|
||||
Preconditions.checkArgument(plugin != null, "Plugin cannot be null");
|
||||
Preconditions.checkArgument(key != null, "Key cannot be null");
|
||||
|
||||
this.namespace = plugin.getName().toLowerCase(Locale.ROOT);
|
||||
this.key = key.toLowerCase(Locale.ROOT);
|
||||
|
||||
// Check validity after normalization
|
||||
this.validate();
|
||||
}
|
||||
|
||||
private void validate() {
|
||||
Preconditions.checkArgument(this.namespace.length() + 1 + this.key.length() <= Short.MAX_VALUE, "NamespacedKey must be less than 32768 characters");
|
||||
Preconditions.checkArgument(isValidNamespace(this.namespace), "Invalid namespace. Must be [a-z0-9._-]: %s", this.namespace);
|
||||
Preconditions.checkArgument(isValidKey(this.key), "Invalid key. Must be [a-z0-9/._-]: %s", this.key);
|
||||
|
||||
String string = toString();
|
||||
Preconditions.checkArgument(string.length() <= Short.MAX_VALUE, "NamespacedKey must be less than 32768 characters", string); // Paper - Fix improper length validation
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
|
|
@ -64,7 +64,7 @@ public interface Registry<T extends Keyed> extends Iterable<T> {
|
|||
@SuppressWarnings("removal")
|
||||
@Deprecated(forRemoval = true, since = "1.21.4")
|
||||
private static <A extends Keyed> Registry<A> legacyRegistryFor(final Class<A> clazz) {
|
||||
return Objects.requireNonNull(RegistryAccess.registryAccess().getRegistry(clazz), "No registry present for " + clazz.getSimpleName() + ". This is a bug.");
|
||||
return Objects.requireNonNull(RegistryAccess.registryAccess().getRegistry(clazz), () -> "No registry present for " + clazz.getSimpleName() + ". This is a bug.");
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -990,26 +990,24 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi
|
|||
public boolean dispatchCommand(@NotNull CommandSender sender, @NotNull String commandLine) throws CommandException;
|
||||
|
||||
/**
|
||||
* Adds a recipe to the crafting manager. Recipes added with
|
||||
* this method won't be sent to the client automatically. Use
|
||||
* {@link #updateRecipes()} or {@link #updateResources()} to
|
||||
* update clients to new recipes added.
|
||||
* Adds a recipe to the crafting manager.
|
||||
* Recipes added with this method won't be sent to the client automatically.
|
||||
* <p>
|
||||
* Player's still have to discover recipes via {@link Player#discoverRecipe(NamespacedKey)}
|
||||
* Players still have to discover recipes via {@link Player#discoverRecipe(NamespacedKey)}
|
||||
* before seeing them in their recipe book.
|
||||
*
|
||||
* @param recipe the recipe to add
|
||||
* @return true if the recipe was added, false if it wasn't for some
|
||||
* reason
|
||||
* @return true if the recipe was added, false if it wasn't for some reason
|
||||
* @see #addRecipe(Recipe, boolean)
|
||||
*/
|
||||
@Contract("null -> false")
|
||||
public boolean addRecipe(@Nullable Recipe recipe);
|
||||
boolean addRecipe(@Nullable Recipe recipe);
|
||||
|
||||
// Paper start - method to send recipes immediately
|
||||
/**
|
||||
* Adds a recipe to the crafting manager.
|
||||
*
|
||||
* @apiNote resendRecipes is ignored for now for stability reasons, recipes will always be updated
|
||||
* @param recipe the recipe to add
|
||||
* @param resendRecipes true to update the client with the full set of recipes
|
||||
* @return true if the recipe was added, false if it wasn't for some reason
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
package org.bukkit;
|
||||
|
||||
import java.io.File;
|
||||
import io.papermc.paper.raytracing.PositionedRayTraceConfigurationBuilder;
|
||||
import org.bukkit.generator.ChunkGenerator;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
|
@ -2410,9 +2408,17 @@ public interface World extends RegionAccessor, WorldInfo, PluginMessageRecipient
|
|||
public BiomeProvider getBiomeProvider();
|
||||
|
||||
/**
|
||||
* Saves world to disk
|
||||
* Saves the world to disk
|
||||
*/
|
||||
public void save();
|
||||
default void save() {
|
||||
save(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the world to disk
|
||||
* @param flush Whether to wait for the chunk writer to finish
|
||||
*/
|
||||
void save(boolean flush);
|
||||
|
||||
/**
|
||||
* Gets a list of all applied {@link BlockPopulator}s for this World
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package org.bukkit.block;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
|
@ -168,4 +169,24 @@ public interface Skull extends TileState {
|
|||
@Deprecated(since = "1.13", forRemoval = true)
|
||||
@Contract("_ -> fail")
|
||||
public void setSkullType(SkullType skullType);
|
||||
|
||||
/**
|
||||
* Get the custom name of skull.
|
||||
* <p>This name is set when placing a skull item that has a custom name.
|
||||
* This name is only carried back to the item when broken for player heads
|
||||
* (skeleton/creeper heads will not retain the name).</p>
|
||||
*
|
||||
* @return Custom name of skull
|
||||
*/
|
||||
public @Nullable Component customName();
|
||||
|
||||
/**
|
||||
* Set the custom name of skull.
|
||||
* <p>This name is set when placing a skull item that has a custom name.
|
||||
* This name is only carried back to the item when broken for player heads
|
||||
* (skeleton/creeper heads will not retain the name).</p>
|
||||
*
|
||||
* @param customName Custom name of skull
|
||||
*/
|
||||
public void customName(@Nullable Component customName);
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ import org.bukkit.block.data.BlockData;
|
|||
import org.bukkit.material.MaterialData;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.annotations.Range;
|
||||
|
||||
/**
|
||||
* A chunk generator is responsible for the initial shaping of an entire
|
||||
|
@ -777,5 +778,18 @@ public abstract class ChunkGenerator {
|
|||
*/
|
||||
@Deprecated(since = "1.8.8")
|
||||
public byte getData(int x, int y, int z);
|
||||
|
||||
/**
|
||||
* Get the current height of a position in the chunk data.
|
||||
* <p>This will differ based on which state generation of the chunk is currently at.
|
||||
* If for example the chunk is in the generate surface stage,
|
||||
* this will return what was already generated in the noise stage.</p>
|
||||
*
|
||||
* @param heightMap Heightmap to determine where to grab height
|
||||
* @param x the x location in the chunk from 0-15 inclusive
|
||||
* @param z the z location in the chunk from 0-15 inclusive
|
||||
* @return Y coordinate at highest position
|
||||
*/
|
||||
int getHeight(@NotNull HeightMap heightMap, @Range(from = 0L, to = 15L) int x, @Range(from = 0L, to = 15L) int z);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,6 @@ import java.util.Collections;
|
|||
import org.bukkit.Material;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.material.MaterialData;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
|
@ -41,7 +40,6 @@ public class FurnaceRecipe extends CookingRecipe<FurnaceRecipe> {
|
|||
* @param experience The experience given by this recipe
|
||||
* @param cookingTime The cooking time (in ticks)
|
||||
*/
|
||||
@ApiStatus.Internal
|
||||
public FurnaceRecipe(@NotNull NamespacedKey key, @NotNull ItemStack result, @NotNull Material source, float experience, int cookingTime) {
|
||||
this(key, result, source, 0, experience, cookingTime);
|
||||
}
|
||||
|
@ -60,7 +58,6 @@ public class FurnaceRecipe extends CookingRecipe<FurnaceRecipe> {
|
|||
* @param experience The experience given by this recipe
|
||||
* @param cookingTime The cooking time (in ticks)
|
||||
*/
|
||||
@ApiStatus.Internal
|
||||
public FurnaceRecipe(@NotNull NamespacedKey key, @NotNull ItemStack result, @NotNull RecipeChoice input, float experience, int cookingTime) {
|
||||
super(key, result, input, experience, cookingTime);
|
||||
}
|
||||
|
|
|
@ -242,6 +242,11 @@ public interface InventoryView {
|
|||
@NotNull
|
||||
public InventoryType.SlotType getSlotType(int slot);
|
||||
|
||||
/**
|
||||
* Opens the inventory view.
|
||||
*/
|
||||
void open();
|
||||
|
||||
/**
|
||||
* Closes the inventory view.
|
||||
*/
|
||||
|
|
|
@ -6,6 +6,7 @@ import java.util.LinkedHashMap;
|
|||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Predicate;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
|
@ -57,7 +58,7 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, Translat
|
|||
*/
|
||||
@org.jetbrains.annotations.Contract(value = "_, _ -> new", pure = true)
|
||||
public static @NotNull ItemStack of(final @NotNull Material type, final int amount) {
|
||||
Preconditions.checkArgument(type.asItemType() != null, type + " isn't an item");
|
||||
Preconditions.checkArgument(type.asItemType() != null, "%s isn't an item", type);
|
||||
Preconditions.checkArgument(amount > 0, "amount must be greater than 0");
|
||||
return java.util.Objects.requireNonNull(type.asItemType(), type + " is not an item").createItemStack(amount); // Paper - delegate
|
||||
}
|
||||
|
@ -1306,6 +1307,31 @@ public class ItemStack implements Cloneable, ConfigurationSerializable, Translat
|
|||
this.craftDelegate.resetData(type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies component values and component removals from the provided ItemStack.
|
||||
* <p>
|
||||
* Example:
|
||||
* <pre>{@code
|
||||
* Set<DataComponentType> types = Set.of(
|
||||
* DataComponentTypes.CONSUMABLE,
|
||||
* DataComponentTypes.ENCHANTMENT_GLINT_OVERRIDE,
|
||||
* DataComponentTypes.RARITY
|
||||
* );
|
||||
*
|
||||
* ItemStack source = ItemStack.of(Material.ENCHANTED_GOLDEN_APPLE);
|
||||
* ItemStack target = ItemStack.of(Material.GOLDEN_CARROT);
|
||||
*
|
||||
* target.copyDataFrom(source, types::contains);
|
||||
* }</pre>
|
||||
*
|
||||
* @param source the item stack to copy from
|
||||
* @param filter predicate for which components to copy
|
||||
*/
|
||||
@org.jetbrains.annotations.ApiStatus.Experimental
|
||||
public void copyDataFrom(final @NotNull ItemStack source, final @NotNull Predicate<io.papermc.paper.datacomponent.@NotNull DataComponentType> filter) {
|
||||
this.craftDelegate.copyDataFrom(source, filter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the data component type is overridden from the default for the
|
||||
* item type.
|
||||
|
|
|
@ -770,11 +770,11 @@ index 34b5839cf0c6b705c3f329dd26cb36fa333f5f1e..8800d1440073d0abf1d78f58e8396c87
|
|||
+ public void inactiveTick() {
|
||||
+ this.life++;
|
||||
+ if (this.life > this.lifetime && this.level() instanceof ServerLevel serverLevel) {
|
||||
+ // CraftBukkit start
|
||||
+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callFireworkExplodeEvent(this).isCancelled()) {
|
||||
+ // Paper start - Call FireworkExplodeEvent
|
||||
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callFireworkExplodeEvent(this)) {
|
||||
+ this.explode(serverLevel);
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+ // Paper end - Call FireworkExplodeEvent
|
||||
+ }
|
||||
+ super.inactiveTick();
|
||||
+ }
|
||||
|
|
|
@ -23751,7 +23751,7 @@ index 841a41485af62470d833aba578069b19a0bd1e8d..409c1134327bfcc338c3ac5e658a83cc
|
|||
// CraftBukkit start
|
||||
public boolean isDebugging() {
|
||||
diff --git a/net/minecraft/server/dedicated/DedicatedServer.java b/net/minecraft/server/dedicated/DedicatedServer.java
|
||||
index f8c81d795b19e73d56d6e0196c75e441ab4c2bef..97a294d2f5c1ddf0af7ffec3e1425eb329c5751b 100644
|
||||
index ac7bc193f7ea63cbbba73df49f54a17ef7cdec40..d2db6e3a4af13984b0a790fb38e83c253914a973 100644
|
||||
--- a/net/minecraft/server/dedicated/DedicatedServer.java
|
||||
+++ b/net/minecraft/server/dedicated/DedicatedServer.java
|
||||
@@ -433,7 +433,33 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface
|
||||
|
@ -26735,7 +26735,7 @@ index da793ad12565c36fffb26eb771ff68c76632caf7..db06f966077928419bfe469260f04d7d
|
|||
if (!passengers.equals(this.lastPassengers)) {
|
||||
this.broadcastAndSend(new ClientboundSetPassengersPacket(this.entity)); // CraftBukkit
|
||||
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
|
||||
index 400b56657414177cd76a7b94c426dc7c886aa957..a275b17d0852d9d9bc850614713244e580ae81f1 100644
|
||||
index d1f235ebd835f58cf0c703c3a64d29825d98e183..080091efc19bc768bb9a660f366c42e831225505 100644
|
||||
--- a/net/minecraft/server/level/ServerLevel.java
|
||||
+++ b/net/minecraft/server/level/ServerLevel.java
|
||||
@@ -170,7 +170,7 @@ import net.minecraft.world.phys.shapes.VoxelShape;
|
||||
|
@ -27496,7 +27496,7 @@ index 400b56657414177cd76a7b94c426dc7c886aa957..a275b17d0852d9d9bc850614713244e5
|
|||
}
|
||||
|
||||
diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
|
||||
index f054ea710108e5017bc48fdda5f180a04f5b55e2..f44600604a7bf68c990cd74a1ac2d7900ff6e88e 100644
|
||||
index 0bb610f12e3ddda649ecb5ad62ffdc7bfd243223..19428343b37c9b739b3d28984d52e257f85f253f 100644
|
||||
--- a/net/minecraft/server/level/ServerPlayer.java
|
||||
+++ b/net/minecraft/server/level/ServerPlayer.java
|
||||
@@ -178,7 +178,7 @@ import net.minecraft.world.scores.Team;
|
||||
|
@ -27508,7 +27508,7 @@ index f054ea710108e5017bc48fdda5f180a04f5b55e2..f44600604a7bf68c990cd74a1ac2d790
|
|||
private static final Logger LOGGER = LogUtils.getLogger();
|
||||
private static final int NEUTRAL_MOB_DEATH_NOTIFICATION_RADII_XZ = 32;
|
||||
private static final int NEUTRAL_MOB_DEATH_NOTIFICATION_RADII_Y = 10;
|
||||
@@ -388,6 +388,36 @@ public class ServerPlayer extends Player {
|
||||
@@ -395,6 +395,36 @@ public class ServerPlayer extends Player {
|
||||
public @Nullable String clientBrandName = null; // Paper - Brand support
|
||||
public org.bukkit.event.player.PlayerQuitEvent.QuitReason quitReason = null; // Paper - Add API for quit reason; there are a lot of changes to do if we change all methods leading to the event
|
||||
|
||||
|
@ -27976,10 +27976,10 @@ index 4eb040006f5d41b47e5ac9df5d9f19c4315d6343..7fa41dea184b01891f45d8e404bc1cba
|
|||
this.generatingStep = generatingStep;
|
||||
this.cache = cache;
|
||||
diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java
|
||||
index 5d88b2790710a885957ffcffc02fb99c917123c5..7d1d4abfb04829d8c4722e326c6c6b8fb2ab91f4 100644
|
||||
index 7eebb494e38b57e81b4f92f0a96d3a4c610d86df..065f4c810439dde464529b54ae300ecfcb1c2c31 100644
|
||||
--- a/net/minecraft/server/players/PlayerList.java
|
||||
+++ b/net/minecraft/server/players/PlayerList.java
|
||||
@@ -1312,7 +1312,7 @@ public abstract class PlayerList {
|
||||
@@ -1317,7 +1317,7 @@ public abstract class PlayerList {
|
||||
|
||||
public void setViewDistance(int viewDistance) {
|
||||
this.viewDistance = viewDistance;
|
||||
|
@ -27988,7 +27988,7 @@ index 5d88b2790710a885957ffcffc02fb99c917123c5..7d1d4abfb04829d8c4722e326c6c6b8f
|
|||
|
||||
for (ServerLevel serverLevel : this.server.getAllLevels()) {
|
||||
if (serverLevel != null) {
|
||||
@@ -1323,7 +1323,7 @@ public abstract class PlayerList {
|
||||
@@ -1328,7 +1328,7 @@ public abstract class PlayerList {
|
||||
|
||||
public void setSimulationDistance(int simulationDistance) {
|
||||
this.simulationDistance = simulationDistance;
|
||||
|
@ -28372,7 +28372,7 @@ index 8cc5c0716392ba06501542ff5cbe71ee43979e5d..09fd99c9cbd23b5f3c899bfb00c9b896
|
|||
+ // Paper end - block counting
|
||||
}
|
||||
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
|
||||
index 994791a83ca6712db3e74ca9aba4bfcd95a0ec6d..1b54cf07616a10d93e9336dbd299ba5f09678a28 100644
|
||||
index 9b3b770f6986dd132da78fdc3626d334166ec52a..b2b61203438bb1fad1ee807729781718d2467155 100644
|
||||
--- a/net/minecraft/world/entity/Entity.java
|
||||
+++ b/net/minecraft/world/entity/Entity.java
|
||||
@@ -135,7 +135,7 @@ import net.minecraft.world.scores.ScoreHolder;
|
||||
|
|
|
@ -78,10 +78,10 @@ index 87d4291a3944f706a694536da6de0f28c548ab8d..5576bf1d1d70ab7a010653d3207909b5
|
|||
profiler.popPush("spawnAndTick");
|
||||
boolean _boolean = this.level.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING) && !this.level.players().isEmpty(); // CraftBukkit
|
||||
diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
|
||||
index 1fe212e8584c177b49e83f29b1a869b534914348..cd6b5176f34248f844f0e591875701bd08f455ce 100644
|
||||
index 02fb30a3adf92de0795aee213caf94a228b01ca0..67f6e40216e0be063a3cfb61427f095f7c74d785 100644
|
||||
--- a/net/minecraft/server/level/ServerPlayer.java
|
||||
+++ b/net/minecraft/server/level/ServerPlayer.java
|
||||
@@ -368,6 +368,10 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
|
||||
@@ -375,6 +375,10 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
|
||||
public boolean queueHealthUpdatePacket;
|
||||
public net.minecraft.network.protocol.game.ClientboundSetHealthPacket queuedHealthUpdatePacket;
|
||||
// Paper end - cancellable death event
|
||||
|
|
|
@ -60,10 +60,10 @@ index 5576bf1d1d70ab7a010653d3207909b5de867e70..6540b2d6a1062d883811ce240c49d30d
|
|||
spawnState = NaturalSpawner.createState(naturalSpawnChunkCount, this.level.getAllEntities(), this::getFullChunk, null, true);
|
||||
} else {
|
||||
diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
|
||||
index cd6b5176f34248f844f0e591875701bd08f455ce..f347ff8d863f4bcef46604c757de112cb3fe445c 100644
|
||||
index 67f6e40216e0be063a3cfb61427f095f7c74d785..3de65c4025be91d938a350c884975cb6edc234d3 100644
|
||||
--- a/net/minecraft/server/level/ServerPlayer.java
|
||||
+++ b/net/minecraft/server/level/ServerPlayer.java
|
||||
@@ -372,6 +372,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
|
||||
@@ -379,6 +379,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
|
||||
public static final int MOBCATEGORY_TOTAL_ENUMS = net.minecraft.world.entity.MobCategory.values().length;
|
||||
public final int[] mobCounts = new int[MOBCATEGORY_TOTAL_ENUMS];
|
||||
// Paper end - Optional per player mob spawns
|
||||
|
|
|
@ -67,3 +67,12 @@
|
|||
}
|
||||
});
|
||||
}
|
||||
@@ -247,7 +_,7 @@
|
||||
public void flushDirty(ServerPlayer player, boolean showAdvancements) {
|
||||
if (this.isFirstPacket || !this.rootsToUpdate.isEmpty() || !this.progressChanged.isEmpty()) {
|
||||
Map<ResourceLocation, AdvancementProgress> map = new HashMap<>();
|
||||
- Set<AdvancementHolder> set = new HashSet<>();
|
||||
+ Set<AdvancementHolder> set = new java.util.TreeSet<>(java.util.Comparator.comparing(adv -> adv.id().toString())); // Paper - Changed from HashSet to TreeSet ordered alphabetically.
|
||||
Set<ResourceLocation> set1 = new HashSet<>();
|
||||
|
||||
for (AdvancementNode advancementNode : this.rootsToUpdate) {
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
--- a/net/minecraft/server/commands/RideCommand.java
|
||||
+++ b/net/minecraft/server/commands/RideCommand.java
|
||||
@@ -58,7 +_,7 @@
|
||||
Entity vehicle1 = target.getVehicle();
|
||||
if (vehicle1 != null) {
|
||||
throw ERROR_ALREADY_RIDING.create(target.getDisplayName(), vehicle1.getDisplayName());
|
||||
- } else if (vehicle.getType() == EntityType.PLAYER) {
|
||||
+ } else if (vehicle.getType() == EntityType.PLAYER && !io.papermc.paper.configuration.GlobalConfiguration.get().commands.rideCommandAllowPlayerAsVehicle) { // Paper - allow player as vehicle
|
||||
throw ERROR_MOUNTING_PLAYER.create();
|
||||
} else if (target.getSelfAndPassengers().anyMatch(passenger -> passenger == vehicle)) {
|
||||
throw ERROR_MOUNTING_LOOP.create();
|
|
@ -10,7 +10,7 @@
|
|||
@Nullable
|
||||
private Vec3 startingToFallPosition;
|
||||
@Nullable
|
||||
@@ -281,6 +_,13 @@
|
||||
@@ -281,6 +_,20 @@
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -20,6 +20,13 @@
|
|||
+ ServerPlayer.this.connection.send(new ClientboundContainerSetSlotPacket(ServerPlayer.this.inventoryMenu.containerId, ServerPlayer.this.inventoryMenu.incrementStateId(), net.minecraft.world.inventory.InventoryMenu.SHIELD_SLOT, ServerPlayer.this.inventoryMenu.getSlot(net.minecraft.world.inventory.InventoryMenu.SHIELD_SLOT).getItem().copy()));
|
||||
+ }
|
||||
+ // Paper end - Sync offhand slot in menus
|
||||
+
|
||||
+ // Paper start - add flag to simplify remote matching logic
|
||||
+ @Override
|
||||
+ public ServerPlayer player() {
|
||||
+ return ServerPlayer.this;
|
||||
+ }
|
||||
+ // Paper end - add flag to simplify remote matching logic
|
||||
+
|
||||
@Override
|
||||
public void sendSlotChange(AbstractContainerMenu container, int slot, ItemStack itemStack) {
|
||||
|
|
|
@ -558,7 +558,7 @@
|
|||
|
||||
this.player.connection.send(new ClientboundSetHeldSlotPacket(inventory.getSelectedSlot()));
|
||||
this.player.inventoryMenu.broadcastChanges();
|
||||
+ this.player.detectEquipmentUpdates(); // Paper - Force update attributes.
|
||||
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.updateEquipmentOnPlayerActions) this.player.detectEquipmentUpdates(); // Paper - Force update attributes.
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1093,7 +1093,7 @@
|
|||
+ }
|
||||
+ // CraftBukkit end
|
||||
this.player.stopUsingItem();
|
||||
+ this.player.detectEquipmentUpdates(); // Paper - Force update attributes.
|
||||
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.updateEquipmentOnPlayerActions) this.player.detectEquipmentUpdates(); // Paper - Force update attributes.
|
||||
}
|
||||
|
||||
return;
|
||||
|
@ -1115,21 +1115,21 @@
|
|||
+ }
|
||||
+ // CraftBukkit end
|
||||
this.player.drop(false);
|
||||
+ this.player.detectEquipmentUpdates(); // Paper - Force update attributes.
|
||||
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.updateEquipmentOnPlayerActions) this.player.detectEquipmentUpdates(); // Paper - Force update attributes.
|
||||
}
|
||||
|
||||
return;
|
||||
case DROP_ALL_ITEMS:
|
||||
if (!this.player.isSpectator()) {
|
||||
this.player.drop(true);
|
||||
+ this.player.detectEquipmentUpdates(); // Paper - Force update attributes.
|
||||
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.updateEquipmentOnPlayerActions) this.player.detectEquipmentUpdates(); // Paper - Force update attributes.
|
||||
}
|
||||
|
||||
return;
|
||||
case RELEASE_USE_ITEM:
|
||||
- this.player.releaseUsingItem();
|
||||
+ if (this.player.getUseItem() == this.player.getItemInHand(this.player.getUsedItemHand())) this.player.releaseUsingItem(); // Paper - validate use item before processing release
|
||||
+ this.player.detectEquipmentUpdates(); // Paper - Force update attributes.
|
||||
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.updateEquipmentOnPlayerActions) this.player.detectEquipmentUpdates(); // Paper - Force update attributes.
|
||||
return;
|
||||
case START_DESTROY_BLOCK:
|
||||
case ABORT_DESTROY_BLOCK:
|
||||
|
@ -1162,7 +1162,7 @@
|
|||
+ }
|
||||
+ }
|
||||
+ // Paper end - Send block entities after destroy prediction
|
||||
+ this.player.detectEquipmentUpdates(); // Paper - Force update attributes.
|
||||
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.updateEquipmentOnPlayerActions) this.player.detectEquipmentUpdates(); // Paper - Force update attributes.
|
||||
return;
|
||||
default:
|
||||
throw new IllegalArgumentException("Invalid player action");
|
||||
|
@ -1237,7 +1237,7 @@
|
|||
|
||||
this.player.connection.send(new ClientboundBlockUpdatePacket(serverLevel, blockPos));
|
||||
this.player.connection.send(new ClientboundBlockUpdatePacket(serverLevel, blockPos.relative(direction)));
|
||||
+ this.player.detectEquipmentUpdates(); // Paper - Force update attributes.
|
||||
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.updateEquipmentOnPlayerActions) this.player.detectEquipmentUpdates(); // Paper - Force update attributes.
|
||||
} else {
|
||||
LOGGER.warn(
|
||||
"Rejecting UseItemOnPacket from {}: Location {} too far away from hit block {}.",
|
||||
|
@ -1387,7 +1387,7 @@
|
|||
|
||||
this.player.getInventory().setSelectedSlot(packet.getSlot());
|
||||
this.player.resetLastActionTime();
|
||||
+ this.player.detectEquipmentUpdates(); // Paper - Force update attributes.
|
||||
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.updateEquipmentOnPlayerActions) this.player.detectEquipmentUpdates(); // Paper - Force update attributes.
|
||||
} else {
|
||||
LOGGER.warn("{} tried to set an invalid carried item", this.player.getName().getString());
|
||||
+ this.disconnect(Component.literal("Invalid hotbar selection (Hacking?)"), org.bukkit.event.player.PlayerKickEvent.Cause.ILLEGAL_ACTION); // CraftBukkit // Paper - kick event cause
|
||||
|
@ -1553,7 +1553,7 @@
|
|||
return Optional.empty();
|
||||
}
|
||||
|
||||
@@ -1538,22 +_,79 @@
|
||||
@@ -1538,22 +_,81 @@
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1623,9 +1623,11 @@
|
|||
+ // Spigot start - spam exclusions
|
||||
+ private void detectRateSpam(String message) {
|
||||
+ // CraftBukkit start - replaced with thread safe throttle
|
||||
+ for (String exclude : org.spigotmc.SpigotConfig.spamExclusions) {
|
||||
+ if (exclude != null && message.startsWith(exclude)) {
|
||||
+ return;
|
||||
+ if (org.spigotmc.SpigotConfig.enableSpamExclusions) {
|
||||
+ for (String exclude : org.spigotmc.SpigotConfig.spamExclusions) {
|
||||
+ if (exclude != null && message.startsWith(exclude)) {
|
||||
+ return;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ // Spigot end
|
||||
|
@ -1920,7 +1922,7 @@
|
|||
+ });
|
||||
+ }
|
||||
+ // Paper end - PlayerUseUnknownEntityEvent
|
||||
+ this.player.detectEquipmentUpdates(); // Paper - Force update attributes.
|
||||
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.updateEquipmentOnPlayerActions) this.player.detectEquipmentUpdates(); // Paper - Force update attributes.
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2018,7 +2020,7 @@
|
|||
+ ItemStack cursor = this.player.containerMenu.getCarried();
|
||||
+ if (clickedItem.isEmpty()) {
|
||||
+ if (!cursor.isEmpty()) {
|
||||
+ if (cursor.getItem() instanceof net.minecraft.world.item.BundleItem && packet.buttonNum() != 0) {
|
||||
+ if (cursor.getItem() instanceof net.minecraft.world.item.BundleItem && cursor.has(DataComponents.BUNDLE_CONTENTS) && packet.buttonNum() != 0) {
|
||||
+ action = cursor.get(DataComponents.BUNDLE_CONTENTS).isEmpty() ? InventoryAction.NOTHING : InventoryAction.PLACE_FROM_BUNDLE;
|
||||
+ } else {
|
||||
+ action = packet.buttonNum() == 0 ? InventoryAction.PLACE_ALL : InventoryAction.PLACE_ONE;
|
||||
|
@ -2026,7 +2028,7 @@
|
|||
+ }
|
||||
+ } else if (slot.mayPickup(this.player)) {
|
||||
+ if (cursor.isEmpty()) {
|
||||
+ if (slot.getItem().getItem() instanceof net.minecraft.world.item.BundleItem && packet.buttonNum() != 0) {
|
||||
+ if (slot.getItem().getItem() instanceof net.minecraft.world.item.BundleItem && slot.getItem().has(DataComponents.BUNDLE_CONTENTS) && packet.buttonNum() != 0) {
|
||||
+ action = slot.getItem().get(DataComponents.BUNDLE_CONTENTS).isEmpty() ? InventoryAction.NOTHING : InventoryAction.PICKUP_FROM_BUNDLE;
|
||||
+ } else {
|
||||
+ action = packet.buttonNum() == 0 ? InventoryAction.PICKUP_ALL : InventoryAction.PICKUP_HALF;
|
||||
|
@ -2046,7 +2048,7 @@
|
|||
+ action = InventoryAction.PLACE_SOME;
|
||||
+ }
|
||||
+ } else if (cursor.getCount() <= slot.getMaxStackSize()) {
|
||||
+ if (cursor.getItem() instanceof net.minecraft.world.item.BundleItem && packet.buttonNum() == 0) {
|
||||
+ if (cursor.getItem() instanceof net.minecraft.world.item.BundleItem && cursor.has(DataComponents.BUNDLE_CONTENTS) && packet.buttonNum() == 0) {
|
||||
+ int toPickup = cursor.get(DataComponents.BUNDLE_CONTENTS).getMaxAmountToAdd(slot.getItem());
|
||||
+ if (toPickup >= slot.getItem().getCount()) {
|
||||
+ action = InventoryAction.PICKUP_ALL_INTO_BUNDLE;
|
||||
|
@ -2055,7 +2057,7 @@
|
|||
+ } else {
|
||||
+ action = InventoryAction.PICKUP_SOME_INTO_BUNDLE;
|
||||
+ }
|
||||
+ } else if (slot.getItem().getItem() instanceof net.minecraft.world.item.BundleItem && packet.buttonNum() == 0) {
|
||||
+ } else if (slot.getItem().getItem() instanceof net.minecraft.world.item.BundleItem && slot.getItem().has(DataComponents.BUNDLE_CONTENTS) && packet.buttonNum() == 0) {
|
||||
+ int toPickup = slot.getItem().get(DataComponents.BUNDLE_CONTENTS).getMaxAmountToAdd(cursor);
|
||||
+ if (toPickup >= cursor.getCount()) {
|
||||
+ action = InventoryAction.PLACE_ALL_INTO_BUNDLE;
|
||||
|
@ -2325,7 +2327,7 @@
|
|||
} else {
|
||||
this.player.containerMenu.broadcastChanges();
|
||||
}
|
||||
+ this.player.detectEquipmentUpdates(); // Paper - Force update attributes.
|
||||
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.updateEquipmentOnPlayerActions) this.player.detectEquipmentUpdates(); // Paper - Force update attributes.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2402,7 +2404,7 @@
|
|||
if (flag) {
|
||||
this.player.containerMenu.broadcastChanges();
|
||||
}
|
||||
+ this.player.detectEquipmentUpdates(); // Paper - Force update attributes.
|
||||
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.updateEquipmentOnPlayerActions) this.player.detectEquipmentUpdates(); // Paper - Force update attributes.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2451,7 +2453,7 @@
|
|||
this.player.inventoryMenu.getSlot(packet.slotNum()).setByPlayer(itemStack);
|
||||
this.player.inventoryMenu.setRemoteSlot(packet.slotNum(), itemStack);
|
||||
this.player.inventoryMenu.broadcastChanges();
|
||||
+ this.player.detectEquipmentUpdates(); // Paper - Force update attributes.
|
||||
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.updateEquipmentOnPlayerActions) this.player.detectEquipmentUpdates(); // Paper - Force update attributes.
|
||||
} else if (flag && flag2) {
|
||||
if (this.dropSpamThrottler.isUnderThreshold()) {
|
||||
this.dropSpamThrottler.increment();
|
||||
|
|
|
@ -931,13 +931,18 @@
|
|||
}
|
||||
|
||||
player.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.LEVEL_CHUNKS_LOAD_START, 0.0F));
|
||||
@@ -677,8 +_,16 @@
|
||||
@@ -677,8 +_,21 @@
|
||||
|
||||
public void sendAllPlayerInfo(ServerPlayer player) {
|
||||
player.inventoryMenu.sendAllDataToRemote();
|
||||
- player.resetSentInfo();
|
||||
+ // entityplayer.resetSentInfo();
|
||||
+ player.getBukkitEntity().updateScaledHealth(); // CraftBukkit - Update scaled health on respawn and worldchange
|
||||
+ // Paper start - send all attributes
|
||||
+ // needs to be done because the ServerPlayer instance is being reused on respawn instead of getting replaced like on vanilla
|
||||
+ java.util.Collection<net.minecraft.world.entity.ai.attributes.AttributeInstance> syncableAttributes = player.getAttributes().getSyncableAttributes();
|
||||
+ player.getBukkitEntity().injectScaledMaxHealth(syncableAttributes, true);
|
||||
+ player.connection.send(new net.minecraft.network.protocol.game.ClientboundUpdateAttributesPacket(player.getId(), syncableAttributes));
|
||||
+ // Paper end - send all attributes
|
||||
+ player.refreshEntityData(player); // CraftBukkit - SPIGOT-7218: sync metadata
|
||||
player.connection.send(new ClientboundSetHeldSlotPacket(player.getInventory().getSelectedSlot()));
|
||||
+ // CraftBukkit start - from GameRules
|
||||
|
|
|
@ -22,11 +22,11 @@
|
|||
|
||||
if (this.life > this.lifetime && this.level() instanceof ServerLevel serverLevel) {
|
||||
- this.explode(serverLevel);
|
||||
+ // CraftBukkit start
|
||||
+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callFireworkExplodeEvent(this).isCancelled()) {
|
||||
+ // Paper start - Call FireworkExplodeEvent
|
||||
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callFireworkExplodeEvent(this)) {
|
||||
+ this.explode(serverLevel);
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+ // Paper end - Call FireworkExplodeEvent
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -43,11 +43,11 @@
|
|||
super.onHitEntity(result);
|
||||
if (this.level() instanceof ServerLevel serverLevel) {
|
||||
- this.explode(serverLevel);
|
||||
+ // CraftBukkit start
|
||||
+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callFireworkExplodeEvent(this).isCancelled()) {
|
||||
+ // Paper start - Call FireworkExplodeEvent
|
||||
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callFireworkExplodeEvent(this)) {
|
||||
+ this.explode(serverLevel);
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+ // Paper end - Call FireworkExplodeEvent
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -56,11 +56,11 @@
|
|||
this.level().getBlockState(blockPos).entityInside(this.level(), blockPos, this, InsideBlockEffectApplier.NOOP);
|
||||
if (this.level() instanceof ServerLevel serverLevel && this.hasExplosion()) {
|
||||
- this.explode(serverLevel);
|
||||
+ // CraftBukkit start
|
||||
+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callFireworkExplodeEvent(this).isCancelled()) {
|
||||
+ // Paper start - Call FireworkExplodeEvent
|
||||
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callFireworkExplodeEvent(this)) {
|
||||
+ this.explode(serverLevel);
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+ // Paper end - Call FireworkExplodeEvent
|
||||
}
|
||||
|
||||
super.onHitBlock(result);
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
--- a/net/minecraft/world/entity/projectile/windcharge/BreezeWindCharge.java
|
||||
+++ b/net/minecraft/world/entity/projectile/windcharge/BreezeWindCharge.java
|
||||
@@ -20,6 +_,12 @@
|
||||
|
||||
@Override
|
||||
public void explode(Vec3 pos) {
|
||||
+ // Paper start - Fire event for WindCharge explosions
|
||||
+ org.bukkit.event.entity.ExplosionPrimeEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callExplosionPrimeEvent(this, RADIUS, false);
|
||||
+ if (event.isCancelled()) {
|
||||
+ return;
|
||||
+ }
|
||||
+ // Paper end - Fire event for WindCharge explosions
|
||||
this.level()
|
||||
.explode(
|
||||
this,
|
||||
@@ -28,8 +_,8 @@
|
||||
pos.x(),
|
||||
pos.y(),
|
||||
pos.z(),
|
||||
- 3.0F,
|
||||
- false,
|
||||
+ event.getRadius(), // Paper - Fire event for WindCharge explosions
|
||||
+ event.getFire(), // Paper - Fire event for WindCharge explosions
|
||||
Level.ExplosionInteraction.TRIGGER,
|
||||
ParticleTypes.GUST_EMITTER_SMALL,
|
||||
ParticleTypes.GUST_EMITTER_LARGE,
|
|
@ -0,0 +1,26 @@
|
|||
--- a/net/minecraft/world/entity/projectile/windcharge/WindCharge.java
|
||||
+++ b/net/minecraft/world/entity/projectile/windcharge/WindCharge.java
|
||||
@@ -52,6 +_,12 @@
|
||||
|
||||
@Override
|
||||
public void explode(Vec3 pos) {
|
||||
+ // Paper start - Fire event for WindCharge explosions
|
||||
+ org.bukkit.event.entity.ExplosionPrimeEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callExplosionPrimeEvent(this, RADIUS, false);
|
||||
+ if (event.isCancelled()) {
|
||||
+ return;
|
||||
+ }
|
||||
+ // Paper end - Fire event for WindCharge explosions
|
||||
this.level()
|
||||
.explode(
|
||||
this,
|
||||
@@ -60,8 +_,8 @@
|
||||
pos.x(),
|
||||
pos.y(),
|
||||
pos.z(),
|
||||
- 1.2F,
|
||||
- false,
|
||||
+ event.getRadius(), // Paper - Fire event for WindCharge explosions
|
||||
+ event.getFire(), // Paper - Fire event for WindCharge explosions
|
||||
Level.ExplosionInteraction.TRIGGER,
|
||||
ParticleTypes.GUST_EMITTER_SMALL,
|
||||
ParticleTypes.GUST_EMITTER_LARGE,
|
|
@ -1,9 +1,15 @@
|
|||
--- a/net/minecraft/world/inventory/ContainerSynchronizer.java
|
||||
+++ b/net/minecraft/world/inventory/ContainerSynchronizer.java
|
||||
@@ -13,4 +_,6 @@
|
||||
@@ -13,4 +_,12 @@
|
||||
void sendDataChange(AbstractContainerMenu container, int id, int value);
|
||||
|
||||
RemoteSlot createSlot();
|
||||
+
|
||||
+ default void sendOffHandSlotChange() {} // Paper - Sync offhand slot in menus
|
||||
+
|
||||
+ // Paper start - add flag to simplify remote matching logic
|
||||
+ default net.minecraft.server.level.@org.jspecify.annotations.Nullable ServerPlayer player() {
|
||||
+ return null;
|
||||
+ }
|
||||
+ // Paper end - add flag to simplify remote matching logic
|
||||
}
|
||||
|
|
|
@ -15,3 +15,12 @@
|
|||
ServerLevel serverLevel = (ServerLevel)attacker.level();
|
||||
attacker.setDeltaMovement(attacker.getDeltaMovement().with(Direction.Axis.Y, 0.01F));
|
||||
if (attacker instanceof ServerPlayer serverPlayer) {
|
||||
@@ -127,7 +_,7 @@
|
||||
double knockbackPower = getKnockbackPower(attacker, livingEntity, vec3);
|
||||
Vec3 vec31 = vec3.normalize().scale(knockbackPower);
|
||||
if (knockbackPower > 0.0) {
|
||||
- livingEntity.push(vec31.x, 0.7F, vec31.z);
|
||||
+ livingEntity.push(vec31.x, 0.7F, vec31.z, attacker); // Paper - Add EntityKnockbackByEntityEvent and EntityPushedByEntityAttackEvent
|
||||
if (livingEntity instanceof ServerPlayer serverPlayer) {
|
||||
serverPlayer.connection.send(new ClientboundSetEntityMotionPacket(serverPlayer));
|
||||
}
|
||||
|
|
|
@ -183,6 +183,10 @@ public class GlobalConfiguration extends ConfigurationPart {
|
|||
public boolean skipVanillaDamageTickWhenShieldBlocked = false;
|
||||
@Comment("This setting controls what compression format is used for region files.")
|
||||
public CompressionFormat compressionFormat = CompressionFormat.ZLIB;
|
||||
@Comment("This setting controls if equipment should be updated when handling certain player actions.")
|
||||
public boolean updateEquipmentOnPlayerActions = true;
|
||||
@Comment("Only checks an item's amount and type instead of its full data during inventory desync checks.")
|
||||
public boolean simplifyRemoteItemMatching = false;
|
||||
|
||||
public enum CompressionFormat {
|
||||
GZIP,
|
||||
|
@ -197,6 +201,8 @@ public class GlobalConfiguration extends ConfigurationPart {
|
|||
public class Commands extends ConfigurationPart {
|
||||
public boolean suggestPlayerNamesWhenNullTabCompletions = true;
|
||||
public boolean timeCommandAffectsAllWorlds = false;
|
||||
@Comment("Allow mounting entities to a player in the Vanilla '/ride' command.")
|
||||
public boolean rideCommandAllowPlayerAsVehicle = false;
|
||||
}
|
||||
|
||||
public Logging logging;
|
||||
|
|
|
@ -162,12 +162,12 @@ public final class PaperRegistries {
|
|||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <M, T> RegistryKey<T> registryFromNms(final ResourceKey<? extends Registry<M>> registryResourceKey) {
|
||||
return (RegistryKey<T>) Objects.requireNonNull(BY_RESOURCE_KEY.get(registryResourceKey), registryResourceKey + " doesn't have an api RegistryKey").apiKey();
|
||||
return (RegistryKey<T>) Objects.requireNonNull(BY_RESOURCE_KEY.get(registryResourceKey), () -> registryResourceKey + " doesn't have an api RegistryKey").apiKey();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <M, T> ResourceKey<? extends Registry<M>> registryToNms(final RegistryKey<T> registryKey) {
|
||||
return (ResourceKey<? extends Registry<M>>) Objects.requireNonNull(BY_REGISTRY_KEY.get(registryKey), registryKey + " doesn't have an mc registry ResourceKey").mcKey();
|
||||
return (ResourceKey<? extends Registry<M>>) Objects.requireNonNull(BY_REGISTRY_KEY.get(registryKey), () -> registryKey + " doesn't have an mc registry ResourceKey").mcKey();
|
||||
}
|
||||
|
||||
public static <M, T> TypedKey<T> fromNms(final ResourceKey<M> resourceKey) {
|
||||
|
|
|
@ -60,7 +60,7 @@ public sealed interface RegistryEntryMeta<M, A extends Keyed> permits RegistryEn
|
|||
) implements ServerSide<M, A> { // TODO remove Keyed
|
||||
|
||||
public Craft {
|
||||
Preconditions.checkArgument(!classToPreload.getPackageName().startsWith("net.minecraft"), classToPreload + " should not be in the net.minecraft package as the class-to-preload");
|
||||
Preconditions.checkArgument(!classToPreload.getPackageName().startsWith("net.minecraft"), "%s should not be in the net.minecraft package as the class-to-preload", classToPreload);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@ public final class RegistryEventMap {
|
|||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T, E extends LifecycleEvent> LifecycleEventType<BootstrapContext, E, ?> getEventType(final RegistryKey<T> registryKey) {
|
||||
return (LifecycleEventType<BootstrapContext, E, ?>) Objects.requireNonNull(this.eventTypes.get(registryKey), "No hook for " + registryKey);
|
||||
return (LifecycleEventType<BootstrapContext, E, ?>) Objects.requireNonNull(this.eventTypes.get(registryKey), () -> "No hook for " + registryKey);
|
||||
}
|
||||
|
||||
public boolean hasHandlers(final RegistryKey<?> registryKey) {
|
||||
|
|
|
@ -1265,13 +1265,13 @@ public class CraftWorld extends CraftRegionAccessor implements World {
|
|||
// Paper end
|
||||
|
||||
@Override
|
||||
public void save() {
|
||||
public void save(boolean flush) {
|
||||
org.spigotmc.AsyncCatcher.catchOp("world save"); // Spigot
|
||||
this.server.checkSaveState();
|
||||
boolean oldSave = this.world.noSave;
|
||||
|
||||
this.world.noSave = false;
|
||||
this.world.save(null, false, false);
|
||||
this.world.save(null, flush, false);
|
||||
|
||||
this.world.noSave = oldSave;
|
||||
}
|
||||
|
|
|
@ -2,6 +2,8 @@ package org.bukkit.craftbukkit.block;
|
|||
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import io.papermc.paper.adventure.PaperAdventure;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.minecraft.Util;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
|
@ -216,4 +218,16 @@ public class CraftSkull extends CraftBlockEntityState<SkullBlockEntity> implemen
|
|||
public CraftSkull copy(Location location) {
|
||||
return new CraftSkull(this, location);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Component customName() {
|
||||
SkullBlockEntity snapshot = getSnapshot();
|
||||
return snapshot.customName == null ? null : PaperAdventure.asAdventure(snapshot.customName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void customName(@Nullable Component customName) {
|
||||
SkullBlockEntity snapshot = getSnapshot();
|
||||
snapshot.customName = customName == null ? null : PaperAdventure.asVanilla(customName);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ import java.util.function.Consumer;
|
|||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.protocol.game.ClientboundHorseScreenOpenPacket;
|
||||
import net.minecraft.network.protocol.game.ClientboundOpenScreenPacket;
|
||||
import net.minecraft.network.protocol.game.ServerboundContainerClosePacket;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
@ -24,6 +25,8 @@ import net.minecraft.world.entity.item.ItemEntity;
|
|||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.entity.projectile.FireworkRocketEntity;
|
||||
import net.minecraft.world.inventory.AbstractContainerMenu;
|
||||
import net.minecraft.world.inventory.HorseInventoryMenu;
|
||||
import net.minecraft.world.inventory.InventoryMenu;
|
||||
import net.minecraft.world.inventory.MenuType;
|
||||
import net.minecraft.world.inventory.MerchantMenu;
|
||||
import net.minecraft.world.item.ItemCooldowns;
|
||||
|
@ -446,6 +449,7 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity {
|
|||
AbstractContainerMenu container;
|
||||
if (inventory instanceof CraftInventoryView) {
|
||||
container = ((CraftInventoryView) inventory).getHandle();
|
||||
Preconditions.checkArgument(!(container instanceof InventoryMenu), "Can not open player's InventoryView");
|
||||
} else {
|
||||
container = new CraftContainer(inventory, this.getHandle(), player.nextContainerCounter());
|
||||
}
|
||||
|
@ -470,8 +474,13 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity {
|
|||
net.kyori.adventure.text.Component adventure$title = inventory.title(); // Paper
|
||||
if (adventure$title == null) adventure$title = net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(inventory.getTitle()); // Paper
|
||||
if (result.getFirst() != null) adventure$title = result.getFirst(); // Paper - Add titleOverride to InventoryOpenEvent
|
||||
|
||||
if (!player.isImmobile()) player.connection.send(new ClientboundOpenScreenPacket(container.containerId, windowType, io.papermc.paper.adventure.PaperAdventure.asVanilla(adventure$title))); // Paper - Prevent opening inventories when frozen
|
||||
if (!player.isImmobile()) {
|
||||
if (container instanceof HorseInventoryMenu horse) {
|
||||
player.connection.send(new ClientboundHorseScreenOpenPacket(horse.containerId, horse.horse.getInventoryColumns(), horse.horse.getId()));
|
||||
} else {
|
||||
player.connection.send(new ClientboundOpenScreenPacket(container.containerId, windowType, io.papermc.paper.adventure.PaperAdventure.asVanilla(adventure$title)));
|
||||
}
|
||||
}
|
||||
player.containerMenu = container;
|
||||
player.initMenu(container);
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ import com.mojang.authlib.GameProfile;
|
|||
import com.mojang.datafixers.util.Pair;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.papermc.paper.FeatureHooks;
|
||||
import io.papermc.paper.configuration.GlobalConfiguration;
|
||||
import io.papermc.paper.entity.LookAnchor;
|
||||
import io.papermc.paper.entity.PaperPlayerGiveResult;
|
||||
import io.papermc.paper.entity.PlayerGiveResult;
|
||||
|
@ -223,6 +224,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
|
|||
private BorderChangeListener clientWorldBorderListener = this.createWorldBorderListener();
|
||||
public org.bukkit.event.player.PlayerResourcePackStatusEvent.Status resourcePackStatus; // Paper - more resource pack API
|
||||
private static final boolean DISABLE_CHANNEL_LIMIT = System.getProperty("paper.disableChannelLimit") != null; // Paper - add a flag to disable the channel limit
|
||||
private boolean simplifyContainerDesyncCheck = GlobalConfiguration.get().unsupportedSettings.simplifyRemoteItemMatching;
|
||||
private long lastSaveTime; // Paper - getLastPlayed replacement API
|
||||
|
||||
public CraftPlayer(CraftServer server, ServerPlayer entity) {
|
||||
|
@ -3576,4 +3578,20 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
|
|||
public void setDeathScreenScore(final int score) {
|
||||
getHandle().setScore(score);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether container desync checks should skip the full item comparison of remote carried and changed slots
|
||||
* and should instead only check their type and amount.
|
||||
* <p>
|
||||
* This is useful if the client is not able to produce the same item stack (or as of 1.21.5, its data hashes) as the server.
|
||||
*
|
||||
* @return whether to simplify container desync checks
|
||||
*/
|
||||
public boolean simplifyContainerDesyncCheck() {
|
||||
return simplifyContainerDesyncCheck;
|
||||
}
|
||||
|
||||
public void setSimplifyContainerDesyncCheck(final boolean simplifyContainerDesyncCheck) {
|
||||
this.simplifyContainerDesyncCheck = simplifyContainerDesyncCheck;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1570,10 +1570,13 @@ public class CraftEventFactory {
|
|||
return (Cancellable) event;
|
||||
}
|
||||
|
||||
public static FireworkExplodeEvent callFireworkExplodeEvent(FireworkRocketEntity firework) {
|
||||
public static boolean callFireworkExplodeEvent(FireworkRocketEntity firework) {
|
||||
FireworkExplodeEvent event = new FireworkExplodeEvent((Firework) firework.getBukkitEntity());
|
||||
firework.level().getCraftServer().getPluginManager().callEvent(event);
|
||||
return event;
|
||||
if (!event.callEvent()) {
|
||||
firework.discard(null);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static PrepareAnvilEvent callPrepareAnvilEvent(AnvilView view, ItemStack item) {
|
||||
|
|
|
@ -8,10 +8,12 @@ import net.minecraft.world.level.block.EntityBlock;
|
|||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||
import org.bukkit.HeightMap;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Biome;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.craftbukkit.CraftHeightMap;
|
||||
import org.bukkit.craftbukkit.block.CraftBiome;
|
||||
import org.bukkit.craftbukkit.block.data.CraftBlockData;
|
||||
import org.bukkit.craftbukkit.util.CraftMagicNumbers;
|
||||
|
@ -179,4 +181,12 @@ public final class CraftChunkData implements ChunkGenerator.ChunkData {
|
|||
access.removeBlockEntity(pos);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHeight(final HeightMap heightMap, final int x, final int z) {
|
||||
Preconditions.checkArgument(heightMap != null, "HeightMap cannot be null");
|
||||
Preconditions.checkArgument(x >= 0 && x <= 15 && z >= 0 && z <= 15, "Cannot get height outside of a chunks bounds, must be between 0 and 15, got x: %s, z: %s", x, z);
|
||||
|
||||
return getHandle().getHeight(CraftHeightMap.toNMS(heightMap), x, z);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ import net.minecraft.core.Registry;
|
|||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.chunk.LevelChunkSection;
|
||||
import org.bukkit.HeightMap;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Biome;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
|
@ -199,4 +200,9 @@ public final class OldCraftChunkData implements ChunkGenerator.ChunkData {
|
|||
Set<BlockPos> getLights() {
|
||||
return this.lights;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHeight(HeightMap heightMap, final int x, final int z) {
|
||||
throw new UnsupportedOperationException("Unsupported, in older chunk generator api");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -208,6 +208,11 @@ public abstract class CraftAbstractInventoryView implements InventoryView {
|
|||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void open() {
|
||||
getPlayer().openInventory(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
this.getPlayer().closeInventory();
|
||||
|
|
|
@ -153,7 +153,9 @@ public final class CraftItemFactory implements ItemFactory {
|
|||
@Override
|
||||
public ItemStack createItemStack(String input) throws IllegalArgumentException {
|
||||
try {
|
||||
ItemParser.ItemResult arg = new ItemParser(CraftRegistry.getMinecraftRegistry()).parse(new StringReader(input));
|
||||
StringReader reader = new StringReader(input);
|
||||
ItemParser.ItemResult arg = new ItemParser(MinecraftServer.getMinecraftRegistry()).parse(reader);
|
||||
Preconditions.checkArgument(!reader.canRead(), "Trailing input found when parsing ItemStack: %s", input);
|
||||
|
||||
Item item = arg.item().value();
|
||||
net.minecraft.world.item.ItemStack nmsItemStack = new net.minecraft.world.item.ItemStack(item);
|
||||
|
|
|
@ -7,6 +7,7 @@ import java.util.Collections;
|
|||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Predicate;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.minecraft.advancements.critereon.DataComponentMatchers;
|
||||
import net.minecraft.advancements.critereon.ItemPredicate;
|
||||
|
@ -16,6 +17,7 @@ import net.minecraft.core.HolderSet;
|
|||
import net.minecraft.core.component.DataComponentExactPredicate;
|
||||
import net.minecraft.core.component.DataComponentMap;
|
||||
import net.minecraft.core.component.DataComponentPatch;
|
||||
import net.minecraft.core.component.DataComponentType;
|
||||
import net.minecraft.core.component.DataComponents;
|
||||
import net.minecraft.core.component.PatchedDataComponentMap;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
|
@ -72,7 +74,7 @@ public final class CraftItemStack extends ItemStack {
|
|||
|
||||
@Override
|
||||
public boolean equals(final Object obj) {
|
||||
if (!(obj instanceof final org.bukkit.inventory.ItemStack bukkit)) return false;
|
||||
if (!(obj instanceof final ItemStack bukkit)) return false;
|
||||
final CraftItemStack craftStack = getCraftStack(bukkit);
|
||||
if (this.handle == craftStack.handle) return true;
|
||||
if (this.handle == null || craftStack.handle == null) return false;
|
||||
|
@ -604,14 +606,32 @@ public final class CraftItemStack extends ItemStack {
|
|||
this.handle.set(nms, nmsValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void copyDataFrom(final ItemStack source, final Predicate<io.papermc.paper.datacomponent.DataComponentType> filter) {
|
||||
Preconditions.checkArgument(source != null, "source cannot be null");
|
||||
Preconditions.checkArgument(filter != null, "filter cannot be null");
|
||||
if (this.isEmpty() || source.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
final Predicate<DataComponentType<?>> nmsFilter = nms -> filter.test(io.papermc.paper.datacomponent.PaperDataComponentType.minecraftToBukkit(nms));
|
||||
net.minecraft.world.item.ItemStack sourceNmsStack = getCraftStack(source).handle;
|
||||
this.handle.applyComponents(sourceNmsStack.getPrototype().filter(nmsType -> {
|
||||
return !sourceNmsStack.hasNonDefault(nmsType) && nmsFilter.test(nmsType);
|
||||
}));
|
||||
|
||||
final DataComponentPatch.SplitResult split = sourceNmsStack.getComponentsPatch().split();
|
||||
this.handle.applyComponents(split.added().filter(nmsFilter));
|
||||
split.removed().stream().filter(nmsFilter).forEach(this.handle::remove);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDataOverridden(final io.papermc.paper.datacomponent.DataComponentType type) {
|
||||
if (this.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
final net.minecraft.core.component.DataComponentType<?> nms = io.papermc.paper.datacomponent.PaperDataComponentType.bukkitToMinecraft(type);
|
||||
// maybe a more efficient way is to expose the "patch" map in PatchedDataComponentMap and just check if the type exists as a key
|
||||
return !java.util.Objects.equals(this.handle.get(nms), this.handle.getPrototype().get(nms));
|
||||
return this.handle.hasNonDefault(nms);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -30,6 +30,6 @@ public class CraftGameEventTag extends CraftTag<net.minecraft.world.level.gameev
|
|||
|
||||
@Override
|
||||
public @NotNull Set<GameEvent> getValues() {
|
||||
return getHandle().stream().map((nms) -> Objects.requireNonNull(GameEvent.getByKey(CraftNamespacedKey.fromMinecraft(BuiltInRegistries.GAME_EVENT.getKey(nms.value()))), nms + " is not a recognized game event")).collect(Collectors.toUnmodifiableSet());
|
||||
return getHandle().stream().map((nms) -> Objects.requireNonNull(GameEvent.getByKey(CraftNamespacedKey.fromMinecraft(BuiltInRegistries.GAME_EVENT.getKey(nms.value()))), () -> nms + " is not a recognized game event")).collect(Collectors.toUnmodifiableSet());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -242,9 +242,23 @@ public class SpigotConfig {
|
|||
SpigotConfig.playerShuffle = SpigotConfig.getInt("settings.player-shuffle", 0);
|
||||
}
|
||||
|
||||
public static boolean enableSpamExclusions = false;
|
||||
public static List<String> spamExclusions;
|
||||
private static void spamExclusions() {
|
||||
SpigotConfig.spamExclusions = SpigotConfig.getList("commands.spam-exclusions", List.of("/skill"));
|
||||
Object enabled = SpigotConfig.config.get("commands.enable-spam-exclusions");
|
||||
if (enabled instanceof Boolean value) {
|
||||
SpigotConfig.enableSpamExclusions = value;
|
||||
} else {
|
||||
if (spamExclusions.size() == 1 && spamExclusions.getFirst().equals("/skill")) {
|
||||
SpigotConfig.enableSpamExclusions = false;
|
||||
SpigotConfig.set("commands.enable-spam-exclusions", false);
|
||||
} else {
|
||||
SpigotConfig.enableSpamExclusions = true;
|
||||
SpigotConfig.set("commands.enable-spam-exclusions", true);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static boolean silentCommandBlocks;
|
||||
|
|
Loading…
Add table
Reference in a new issue