mirror of
https://github.com/PaperMC/Paper.git
synced 2024-12-27 15:00:13 +01:00
Finish block entity
This commit is contained in:
parent
368d2116ba
commit
f25c1a33a0
41 changed files with 1904 additions and 2396 deletions
|
@ -0,0 +1,295 @@
|
|||
--- a/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java
|
||||
+++ b/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java
|
||||
@@ -20,7 +_,6 @@
|
||||
import net.minecraft.world.ContainerHelper;
|
||||
import net.minecraft.world.WorldlyContainer;
|
||||
import net.minecraft.world.entity.ExperienceOrb;
|
||||
-import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.entity.player.StackedItemContents;
|
||||
import net.minecraft.world.inventory.ContainerData;
|
||||
import net.minecraft.world.inventory.RecipeCraftingHolder;
|
||||
@@ -99,11 +_,44 @@
|
||||
};
|
||||
public final Reference2IntOpenHashMap<ResourceKey<Recipe<?>>> recipesUsed = new Reference2IntOpenHashMap<>();
|
||||
private final RecipeManager.CachedCheck<SingleRecipeInput, ? extends AbstractCookingRecipe> quickCheck;
|
||||
+ public final RecipeType<? extends AbstractCookingRecipe> recipeType; // Paper - cook speed multiplier API
|
||||
+ public double cookSpeedMultiplier = 1.0; // Paper - cook speed multiplier API
|
||||
|
||||
protected AbstractFurnaceBlockEntity(BlockEntityType<?> type, BlockPos pos, BlockState blockState, RecipeType<? extends AbstractCookingRecipe> recipeType) {
|
||||
super(type, pos, blockState);
|
||||
this.quickCheck = RecipeManager.createCheck(recipeType);
|
||||
- }
|
||||
+ this.recipeType = recipeType; // Paper - cook speed multiplier API
|
||||
+ }
|
||||
+
|
||||
+ // CraftBukkit start - add fields and methods
|
||||
+ private int maxStack = MAX_STACK;
|
||||
+ public List<org.bukkit.entity.HumanEntity> transaction = new java.util.ArrayList<>();
|
||||
+
|
||||
+ public List<ItemStack> getContents() {
|
||||
+ return this.items;
|
||||
+ }
|
||||
+
|
||||
+ public void onOpen(org.bukkit.craftbukkit.entity.CraftHumanEntity who) {
|
||||
+ this.transaction.add(who);
|
||||
+ }
|
||||
+
|
||||
+ public void onClose(org.bukkit.craftbukkit.entity.CraftHumanEntity who) {
|
||||
+ this.transaction.remove(who);
|
||||
+ }
|
||||
+
|
||||
+ public List<org.bukkit.entity.HumanEntity> getViewers() {
|
||||
+ return this.transaction;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public int getMaxStackSize() {
|
||||
+ return this.maxStack;
|
||||
+ }
|
||||
+
|
||||
+ public void setMaxStackSize(int size) {
|
||||
+ this.maxStack = size;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
|
||||
private boolean isLit() {
|
||||
return this.litTimeRemaining > 0;
|
||||
@@ -121,8 +_,19 @@
|
||||
CompoundTag compound = tag.getCompound("RecipesUsed");
|
||||
|
||||
for (String string : compound.getAllKeys()) {
|
||||
- this.recipesUsed.put(ResourceKey.create(Registries.RECIPE, ResourceLocation.parse(string)), compound.getInt(string));
|
||||
- }
|
||||
+ // Paper start - Validate ResourceLocation
|
||||
+ final ResourceLocation resourceLocation = ResourceLocation.tryParse(string);
|
||||
+ if (resourceLocation != null) {
|
||||
+ this.recipesUsed.put(ResourceKey.create(Registries.RECIPE, resourceLocation), tag.getInt(string));
|
||||
+ }
|
||||
+ // Paper end - Validate ResourceLocation
|
||||
+ }
|
||||
+
|
||||
+ // Paper start - cook speed multiplier API
|
||||
+ if (tag.contains("Paper.CookSpeedMultiplier")) {
|
||||
+ this.cookSpeedMultiplier = tag.getDouble("Paper.CookSpeedMultiplier");
|
||||
+ }
|
||||
+ // Paper end - cook speed multiplier API
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -132,6 +_,7 @@
|
||||
tag.putShort("cooking_total_time", (short)this.cookingTotalTime);
|
||||
tag.putShort("lit_time_remaining", (short)this.litTimeRemaining);
|
||||
tag.putShort("lit_total_time", (short)this.litTotalTime);
|
||||
+ tag.putDouble("Paper.CookSpeedMultiplier", this.cookSpeedMultiplier); // Paper - cook speed multiplier API
|
||||
ContainerHelper.saveAllItems(tag, this.items, registries);
|
||||
CompoundTag compoundTag = new CompoundTag();
|
||||
this.recipesUsed.forEach((recipe, count) -> compoundTag.putInt(recipe.location().toString(), count));
|
||||
@@ -160,11 +_,22 @@
|
||||
|
||||
int maxStackSize = furnace.getMaxStackSize();
|
||||
if (!furnace.isLit() && canBurn(level.registryAccess(), recipeHolder, singleRecipeInput, furnace.items, maxStackSize)) {
|
||||
- furnace.litTimeRemaining = furnace.getBurnDuration(level.fuelValues(), itemStack);
|
||||
+ // CraftBukkit start
|
||||
+ org.bukkit.craftbukkit.inventory.CraftItemStack fuel = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemStack);
|
||||
+
|
||||
+ org.bukkit.event.inventory.FurnaceBurnEvent furnaceBurnEvent = new org.bukkit.event.inventory.FurnaceBurnEvent(
|
||||
+ org.bukkit.craftbukkit.block.CraftBlock.at(level, pos),
|
||||
+ fuel,
|
||||
+ furnace.getBurnDuration(level.fuelValues(), itemStack)
|
||||
+ );
|
||||
+ if (!furnaceBurnEvent.callEvent()) return;
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
+ furnace.litTimeRemaining = furnaceBurnEvent.getBurnTime(); // CraftBukkit - respect event output
|
||||
furnace.litTotalTime = furnace.litTimeRemaining;
|
||||
- if (furnace.isLit()) {
|
||||
+ if (furnace.isLit() && furnaceBurnEvent.isBurning()) { // CraftBukkit - respect event output
|
||||
flag = true;
|
||||
- if (flag2) {
|
||||
+ if (flag2 && furnaceBurnEvent.willConsumeFuel()) { // Paper - add consumeFuel to FurnaceBurnEvent
|
||||
Item item = itemStack.getItem();
|
||||
itemStack.shrink(1);
|
||||
if (itemStack.isEmpty()) {
|
||||
@@ -175,11 +_,28 @@
|
||||
}
|
||||
|
||||
if (furnace.isLit() && canBurn(level.registryAccess(), recipeHolder, singleRecipeInput, furnace.items, maxStackSize)) {
|
||||
+ // CraftBukkit start
|
||||
+ if (recipeHolder != null && furnace.cookingTimer == 0) {
|
||||
+ org.bukkit.craftbukkit.inventory.CraftItemStack source = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(furnace.items.get(0));
|
||||
+ org.bukkit.inventory.CookingRecipe<?> recipe = (org.bukkit.inventory.CookingRecipe<?>) recipeHolder.toBukkitRecipe();
|
||||
+
|
||||
+ org.bukkit.event.inventory.FurnaceStartSmeltEvent event = new org.bukkit.event.inventory.FurnaceStartSmeltEvent(
|
||||
+ org.bukkit.craftbukkit.block.CraftBlock.at(level, pos),
|
||||
+ source,
|
||||
+ recipe,
|
||||
+ getTotalCookTime(level, furnace, furnace.recipeType, furnace.cookSpeedMultiplier) // Paper - cook speed multiplier API
|
||||
+ );
|
||||
+ event.callEvent();
|
||||
+
|
||||
+ furnace.cookingTotalTime = event.getTotalCookTime();
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
furnace.cookingTimer++;
|
||||
- if (furnace.cookingTimer == furnace.cookingTotalTime) {
|
||||
+ if (furnace.cookingTimer >= furnace.cookingTotalTime) { // Paper - cook speed multiplier API
|
||||
furnace.cookingTimer = 0;
|
||||
- furnace.cookingTotalTime = getTotalCookTime(level, furnace);
|
||||
- if (burn(level.registryAccess(), recipeHolder, singleRecipeInput, furnace.items, maxStackSize)) {
|
||||
+ furnace.cookingTotalTime = getTotalCookTime(level, furnace, furnace.recipeType, furnace.cookSpeedMultiplier); // Paper - cook speed multiplier API
|
||||
+ if (burn(level.registryAccess(), recipeHolder, singleRecipeInput, furnace.items, maxStackSize, level, furnace.worldPosition)) { // CraftBukkit
|
||||
furnace.setRecipeUsed(recipeHolder);
|
||||
}
|
||||
|
||||
@@ -233,17 +_,47 @@
|
||||
@Nullable RecipeHolder<? extends AbstractCookingRecipe> recipe,
|
||||
SingleRecipeInput recipeInput,
|
||||
NonNullList<ItemStack> items,
|
||||
- int maxStackSize
|
||||
+ int maxStackSize,
|
||||
+ net.minecraft.world.level.Level level, // CraftBukkit
|
||||
+ BlockPos blockPos // CraftBukkit
|
||||
) {
|
||||
if (recipe != null && canBurn(registryAccess, recipe, recipeInput, items, maxStackSize)) {
|
||||
- ItemStack itemStack = items.get(0);
|
||||
- ItemStack itemStack1 = recipe.value().assemble(recipeInput, registryAccess);
|
||||
- ItemStack itemStack2 = items.get(2);
|
||||
+ ItemStack itemStack = items.get(0); final ItemStack ingredient = itemStack; // Paper - OBFHELPER
|
||||
+ ItemStack itemStack1 = recipe.value().assemble(recipeInput, registryAccess); ItemStack result = itemStack1; // Paper - OBFHELPER
|
||||
+ ItemStack itemStack2 = items.get(2); final ItemStack existingResults = itemStack2; // Paper - OBFHELPER
|
||||
+ // CraftBukkit start - fire FurnaceSmeltEvent
|
||||
+ org.bukkit.craftbukkit.inventory.CraftItemStack apiIngredient = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(ingredient);
|
||||
+ org.bukkit.inventory.ItemStack apiResult = org.bukkit.craftbukkit.inventory.CraftItemStack.asBukkitCopy(result);
|
||||
+
|
||||
+ org.bukkit.event.inventory.FurnaceSmeltEvent furnaceSmeltEvent = new org.bukkit.event.inventory.FurnaceSmeltEvent(
|
||||
+ org.bukkit.craftbukkit.block.CraftBlock.at(level, blockPos),
|
||||
+ apiIngredient,
|
||||
+ apiResult,
|
||||
+ (org.bukkit.inventory.CookingRecipe<?>) recipe.toBukkitRecipe() // Paper - Add recipe to cook events
|
||||
+ );
|
||||
+ if (!furnaceSmeltEvent.callEvent()) return false;
|
||||
+
|
||||
+ apiResult = furnaceSmeltEvent.getResult();
|
||||
+ itemStack1 = result = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(apiResult);
|
||||
+
|
||||
+ if (!result.isEmpty()) {
|
||||
+ if (existingResults.isEmpty()) {
|
||||
+ items.set(2, result.copy());
|
||||
+ } else if (org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(existingResults).isSimilar(apiResult)) {
|
||||
+ existingResults.grow(result.getCount());
|
||||
+ } else {
|
||||
+ return false;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
if (itemStack2.isEmpty()) {
|
||||
items.set(2, itemStack1.copy());
|
||||
} else if (ItemStack.isSameItemSameComponents(itemStack2, itemStack1)) {
|
||||
itemStack2.grow(1);
|
||||
}
|
||||
+ */
|
||||
+ // CraftBukkit end
|
||||
|
||||
if (itemStack.is(Blocks.WET_SPONGE.asItem()) && !items.get(1).isEmpty() && items.get(1).is(Items.BUCKET)) {
|
||||
items.set(1, new ItemStack(Items.WATER_BUCKET));
|
||||
@@ -260,9 +_,16 @@
|
||||
return fuelValues.burnDuration(stack);
|
||||
}
|
||||
|
||||
- public static int getTotalCookTime(ServerLevel level, AbstractFurnaceBlockEntity furnace) {
|
||||
+ private static int getTotalCookTime(@Nullable ServerLevel level, AbstractFurnaceBlockEntity furnace, RecipeType<? extends AbstractCookingRecipe> recipeType, double cookSpeedMultiplier) { // Paper - cook speed multiplier API
|
||||
SingleRecipeInput singleRecipeInput = new SingleRecipeInput(furnace.getItem(0));
|
||||
- return furnace.quickCheck.getRecipeFor(singleRecipeInput, level).map(recipe -> recipe.value().cookingTime()).orElse(200);
|
||||
+ // Paper start - cook speed multiplier API
|
||||
+ /* Scale the recipe's cooking time to the current cookSpeedMultiplier */
|
||||
+ int cookTime = level != null
|
||||
+ ? furnace.quickCheck.getRecipeFor(singleRecipeInput, level).map(holder -> holder.value().cookingTime()).orElse(200)
|
||||
+ /* passing a null level here is safe. world is only used for map extending recipes which won't happen here */
|
||||
+ : (net.minecraft.server.MinecraftServer.getServer().getRecipeManager().getRecipeFor(recipeType, singleRecipeInput, level).map(holder -> holder.value().cookingTime()).orElse(200));
|
||||
+ return (int) Math.ceil (cookTime / cookSpeedMultiplier);
|
||||
+ // Paper end - cook speed multiplier AP
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -306,7 +_,7 @@
|
||||
this.items.set(index, stack);
|
||||
stack.limitSize(this.getMaxStackSize(stack));
|
||||
if (index == 0 && !flag && this.level instanceof ServerLevel serverLevel) {
|
||||
- this.cookingTotalTime = getTotalCookTime(serverLevel, this);
|
||||
+ this.cookingTotalTime = getTotalCookTime(serverLevel, this, this.recipeType, this.cookSpeedMultiplier); // Paper - cook speed multiplier API
|
||||
this.cookingTimer = 0;
|
||||
this.setChanged();
|
||||
}
|
||||
@@ -339,11 +_,11 @@
|
||||
}
|
||||
|
||||
@Override
|
||||
- public void awardUsedRecipes(Player player, List<ItemStack> items) {
|
||||
+ public void awardUsedRecipes(net.minecraft.world.entity.player.Player player, List<ItemStack> items) {
|
||||
}
|
||||
|
||||
- public void awardUsedRecipesAndPopExperience(ServerPlayer player) {
|
||||
- List<RecipeHolder<?>> recipesToAwardAndPopExperience = this.getRecipesToAwardAndPopExperience(player.serverLevel(), player.position());
|
||||
+ public void awardUsedRecipesAndPopExperience(ServerPlayer player, ItemStack itemstack, int amount) { // CraftBukkit
|
||||
+ List<RecipeHolder<?>> recipesToAwardAndPopExperience = this.getRecipesToAwardAndPopExperience(player.serverLevel(), player.position(), this.worldPosition, player, itemstack, amount); // CraftBukkit - overload for exp spawn events
|
||||
player.awardRecipes(recipesToAwardAndPopExperience);
|
||||
|
||||
for (RecipeHolder<?> recipeHolder : recipesToAwardAndPopExperience) {
|
||||
@@ -356,26 +_,52 @@
|
||||
}
|
||||
|
||||
public List<RecipeHolder<?>> getRecipesToAwardAndPopExperience(ServerLevel level, Vec3 popVec) {
|
||||
+ // CraftBukkit start
|
||||
+ return this.getRecipesToAwardAndPopExperience(level, popVec, this.worldPosition, null, null, 0);
|
||||
+ }
|
||||
+ public List<RecipeHolder<?>> getRecipesToAwardAndPopExperience(ServerLevel level, Vec3 popVec, BlockPos blockPos, ServerPlayer serverPlayer, ItemStack itemStack, int amount) {
|
||||
+ // CraftBukkit end
|
||||
List<RecipeHolder<?>> list = Lists.newArrayList();
|
||||
|
||||
for (Entry<ResourceKey<Recipe<?>>> entry : this.recipesUsed.reference2IntEntrySet()) {
|
||||
level.recipeAccess().byKey(entry.getKey()).ifPresent(recipe -> {
|
||||
+ if (!(recipe.value() instanceof AbstractCookingRecipe)) return; // Paper - don't process non-cooking recipes
|
||||
list.add((RecipeHolder<?>)recipe);
|
||||
- createExperience(level, popVec, entry.getIntValue(), ((AbstractCookingRecipe)recipe.value()).experience());
|
||||
+ createExperience(level, popVec, entry.getIntValue(), ((AbstractCookingRecipe)recipe.value()).experience(), blockPos, serverPlayer, itemStack, amount);
|
||||
});
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
- private static void createExperience(ServerLevel level, Vec3 popVec, int recipeIndex, float experience) {
|
||||
+ private static void createExperience(ServerLevel level, Vec3 popVec, int recipeIndex, float experience, BlockPos blockPos, ServerPlayer serverPlayer, ItemStack itemStack, int amount) { // CraftBukkit
|
||||
int floor = Mth.floor(recipeIndex * experience);
|
||||
float fraction = Mth.frac(recipeIndex * experience);
|
||||
if (fraction != 0.0F && Math.random() < fraction) {
|
||||
floor++;
|
||||
}
|
||||
|
||||
- ExperienceOrb.award(level, popVec, floor);
|
||||
+ // CraftBukkit start - fire FurnaceExtractEvent / BlockExpEvent
|
||||
+ org.bukkit.event.block.BlockExpEvent event;
|
||||
+ if (amount != 0) {
|
||||
+ event = new org.bukkit.event.inventory.FurnaceExtractEvent(
|
||||
+ serverPlayer.getBukkitEntity(),
|
||||
+ org.bukkit.craftbukkit.block.CraftBlock.at(level, blockPos),
|
||||
+ org.bukkit.craftbukkit.inventory.CraftItemType.minecraftToBukkit(itemStack.getItem()),
|
||||
+ amount,
|
||||
+ floor
|
||||
+ );
|
||||
+ } else {
|
||||
+ event = new org.bukkit.event.block.BlockExpEvent(
|
||||
+ org.bukkit.craftbukkit.block.CraftBlock.at(level, blockPos),
|
||||
+ floor
|
||||
+ );
|
||||
+ }
|
||||
+ event.callEvent();
|
||||
+ floor = event.getExpToDrop();
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
+ ExperienceOrb.award(level, popVec, floor, org.bukkit.entity.ExperienceOrb.SpawnReason.FURNACE, serverPlayer); // Paper
|
||||
}
|
||||
|
||||
@Override
|
|
@ -0,0 +1,71 @@
|
|||
--- a/net/minecraft/world/level/block/entity/BannerBlockEntity.java
|
||||
+++ b/net/minecraft/world/level/block/entity/BannerBlockEntity.java
|
||||
@@ -23,7 +_,7 @@
|
||||
public static final int MAX_PATTERNS = 6;
|
||||
private static final String TAG_PATTERNS = "patterns";
|
||||
@Nullable
|
||||
- private Component name;
|
||||
+ public Component name; // Paper - AT public
|
||||
public DyeColor baseColor;
|
||||
private BannerPatternLayers patterns = BannerPatternLayers.EMPTY;
|
||||
|
||||
@@ -50,7 +_,7 @@
|
||||
@Override
|
||||
protected void saveAdditional(CompoundTag tag, HolderLookup.Provider registries) {
|
||||
super.saveAdditional(tag, registries);
|
||||
- if (!this.patterns.equals(BannerPatternLayers.EMPTY)) {
|
||||
+ if (!this.patterns.equals(BannerPatternLayers.EMPTY) || serialisingForNetwork.get()) { // Paper - always send patterns to client
|
||||
tag.put("patterns", BannerPatternLayers.CODEC.encodeStart(registries.createSerializationContext(NbtOps.INSTANCE), this.patterns).getOrThrow());
|
||||
}
|
||||
|
||||
@@ -70,7 +_,7 @@
|
||||
BannerPatternLayers.CODEC
|
||||
.parse(registries.createSerializationContext(NbtOps.INSTANCE), tag.get("patterns"))
|
||||
.resultOrPartial(string -> LOGGER.error("Failed to parse banner patterns: '{}'", string))
|
||||
- .ifPresent(bannerPatternLayers -> this.patterns = bannerPatternLayers);
|
||||
+ .ifPresent(bannerPatternLayers -> this.setPatterns(bannerPatternLayers)); // CraftBukkit - apply limits
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,9 +_,18 @@
|
||||
return ClientboundBlockEntityDataPacket.create(this);
|
||||
}
|
||||
|
||||
+ // Paper start - always send patterns to client
|
||||
+ ThreadLocal<Boolean> serialisingForNetwork = ThreadLocal.withInitial(() -> Boolean.FALSE);
|
||||
@Override
|
||||
public CompoundTag getUpdateTag(HolderLookup.Provider registries) {
|
||||
+ final Boolean wasSerialisingForNetwork = serialisingForNetwork.get();
|
||||
+ try {
|
||||
+ serialisingForNetwork.set(Boolean.TRUE);
|
||||
return this.saveWithoutMetadata(registries);
|
||||
+ } finally {
|
||||
+ serialisingForNetwork.set(wasSerialisingForNetwork);
|
||||
+ }
|
||||
+ // Paper end - always send patterns to client
|
||||
}
|
||||
|
||||
public BannerPatternLayers getPatterns() {
|
||||
@@ -101,7 +_,7 @@
|
||||
@Override
|
||||
protected void applyImplicitComponents(BlockEntity.DataComponentInput componentInput) {
|
||||
super.applyImplicitComponents(componentInput);
|
||||
- this.patterns = componentInput.getOrDefault(DataComponents.BANNER_PATTERNS, BannerPatternLayers.EMPTY);
|
||||
+ this.setPatterns(componentInput.getOrDefault(DataComponents.BANNER_PATTERNS, BannerPatternLayers.EMPTY)); // CraftBukkit - apply limits
|
||||
this.name = componentInput.get(DataComponents.CUSTOM_NAME);
|
||||
}
|
||||
|
||||
@@ -117,4 +_,13 @@
|
||||
tag.remove("patterns");
|
||||
tag.remove("CustomName");
|
||||
}
|
||||
+
|
||||
+ // CraftBukkit start
|
||||
+ public void setPatterns(BannerPatternLayers bannerpatternlayers) {
|
||||
+ if (bannerpatternlayers.layers().size() > 20) {
|
||||
+ bannerpatternlayers = new BannerPatternLayers(java.util.List.copyOf(bannerpatternlayers.layers().subList(0, 20)));
|
||||
+ }
|
||||
+ this.patterns = bannerpatternlayers;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
}
|
|
@ -24,7 +24,7 @@
|
|||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public java.util.List<org.bukkit.entity.HumanEntity> getViewers() {
|
||||
+ public List<HumanEntity> getViewers() {
|
||||
+ return this.transaction;
|
||||
+ }
|
||||
+
|
||||
|
|
|
@ -0,0 +1,242 @@
|
|||
--- a/net/minecraft/world/level/block/entity/BeaconBlockEntity.java
|
||||
+++ b/net/minecraft/world/level/block/entity/BeaconBlockEntity.java
|
||||
@@ -106,6 +_,51 @@
|
||||
return 3;
|
||||
}
|
||||
};
|
||||
+ // CraftBukkit start - add fields and methods
|
||||
+ public org.bukkit.potion.PotionEffect getPrimaryEffect() {
|
||||
+ return (this.primaryPower != null)
|
||||
+ ? org.bukkit.craftbukkit.potion.CraftPotionUtil.toBukkit(new MobEffectInstance(
|
||||
+ this.primaryPower,
|
||||
+ BeaconBlockEntity.getLevel(this.levels),
|
||||
+ BeaconBlockEntity.getAmplification(this.levels, this.primaryPower, this.secondaryPower),
|
||||
+ true,
|
||||
+ true
|
||||
+ ))
|
||||
+ : null;
|
||||
+ }
|
||||
+
|
||||
+ public org.bukkit.potion.PotionEffect getSecondaryEffect() {
|
||||
+ return (BeaconBlockEntity.hasSecondaryEffect(this.levels, this.primaryPower, this.secondaryPower))
|
||||
+ ? org.bukkit.craftbukkit.potion.CraftPotionUtil.toBukkit(new MobEffectInstance(
|
||||
+ this.secondaryPower,
|
||||
+ BeaconBlockEntity.getLevel(this.levels),
|
||||
+ BeaconBlockEntity.getAmplification(this.levels, this.primaryPower, this.secondaryPower),
|
||||
+ true,
|
||||
+ true
|
||||
+ ))
|
||||
+ : null;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+ // Paper start - Custom beacon ranges
|
||||
+ private final String PAPER_RANGE_TAG = "Paper.Range";
|
||||
+ private double effectRange = -1;
|
||||
+
|
||||
+ public double getEffectRange() {
|
||||
+ if (this.effectRange < 0) {
|
||||
+ return this.levels * 10 + 10;
|
||||
+ } else {
|
||||
+ return effectRange;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ public void setEffectRange(double range) {
|
||||
+ this.effectRange = range;
|
||||
+ }
|
||||
+
|
||||
+ public void resetEffectRange() {
|
||||
+ this.effectRange = -1;
|
||||
+ }
|
||||
+ // Paper end - Custom beacon ranges
|
||||
|
||||
@Nullable
|
||||
static Holder<MobEffect> filterEffect(@Nullable Holder<MobEffect> effect) {
|
||||
@@ -163,17 +_,26 @@
|
||||
blockEntity.lastCheckY++;
|
||||
}
|
||||
|
||||
- int i = blockEntity.levels;
|
||||
+ int i = blockEntity.levels; final int originalLevels = i; // Paper - OBFHELPER
|
||||
if (level.getGameTime() % 80L == 0L) {
|
||||
if (!blockEntity.beamSections.isEmpty()) {
|
||||
blockEntity.levels = updateBase(level, x, y, z);
|
||||
}
|
||||
|
||||
if (blockEntity.levels > 0 && !blockEntity.beamSections.isEmpty()) {
|
||||
- applyEffects(level, pos, blockEntity.levels, blockEntity.primaryPower, blockEntity.secondaryPower);
|
||||
+ applyEffects(level, pos, blockEntity.levels, blockEntity.primaryPower, blockEntity.secondaryPower, blockEntity); // Paper - Custom beacon ranges
|
||||
playSound(level, pos, SoundEvents.BEACON_AMBIENT);
|
||||
}
|
||||
}
|
||||
+ // Paper start - beacon activation/deactivation events
|
||||
+ if (originalLevels <= 0 && blockEntity.levels > 0) {
|
||||
+ org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(level, pos);
|
||||
+ new io.papermc.paper.event.block.BeaconActivatedEvent(block).callEvent();
|
||||
+ } else if (originalLevels > 0 && blockEntity.levels <= 0) {
|
||||
+ org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(level, pos);
|
||||
+ new io.papermc.paper.event.block.BeaconDeactivatedEvent(block).callEvent();
|
||||
+ }
|
||||
+ // Paper end - beacon activation/deactivation events
|
||||
|
||||
if (blockEntity.lastCheckY >= height) {
|
||||
blockEntity.lastCheckY = level.getMinY() - 1;
|
||||
@@ -224,36 +_,99 @@
|
||||
|
||||
@Override
|
||||
public void setRemoved() {
|
||||
+ // Paper start - beacon activation/deactivation events
|
||||
+ org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(level, worldPosition);
|
||||
+ new io.papermc.paper.event.block.BeaconDeactivatedEvent(block).callEvent();
|
||||
+ // Paper end - beacon activation/deactivation events
|
||||
+ // Paper start - fix MC-153086
|
||||
+ if (this.levels > 0 && !this.beamSections.isEmpty()) {
|
||||
playSound(this.level, this.worldPosition, SoundEvents.BEACON_DEACTIVATE);
|
||||
+ }
|
||||
+ // Paper end
|
||||
super.setRemoved();
|
||||
}
|
||||
|
||||
+ @io.papermc.paper.annotation.DoNotUse // Paper - pass beacon block entity
|
||||
private static void applyEffects(
|
||||
Level level, BlockPos pos, int beaconLevel, @Nullable Holder<MobEffect> primaryEffect, @Nullable Holder<MobEffect> secondaryEffect
|
||||
) {
|
||||
+ // Paper start - pass beacon block entity
|
||||
+ applyEffects(level, pos, beaconLevel, primaryEffect, secondaryEffect, null);
|
||||
+ }
|
||||
+ private static void applyEffects(
|
||||
+ Level level, BlockPos pos, int beaconLevel, @Nullable Holder<MobEffect> primaryEffect, @Nullable Holder<MobEffect> secondaryEffect, @Nullable BeaconBlockEntity blockEntity
|
||||
+ ) {
|
||||
+ // Paper emd - pass beacon block entity
|
||||
if (!level.isClientSide && primaryEffect != null) {
|
||||
- double d = beaconLevel * 10 + 10;
|
||||
- int i = 0;
|
||||
- if (beaconLevel >= 4 && Objects.equals(primaryEffect, secondaryEffect)) {
|
||||
- i = 1;
|
||||
- }
|
||||
-
|
||||
- int i1 = (9 + beaconLevel * 2) * 20;
|
||||
- AABB aabb = new AABB(pos).inflate(d).expandTowards(0.0, level.getHeight(), 0.0);
|
||||
- List<Player> entitiesOfClass = level.getEntitiesOfClass(Player.class, aabb);
|
||||
-
|
||||
- for (Player player : entitiesOfClass) {
|
||||
- player.addEffect(new MobEffectInstance(primaryEffect, i1, i, true, true));
|
||||
- }
|
||||
-
|
||||
- if (beaconLevel >= 4 && !Objects.equals(primaryEffect, secondaryEffect) && secondaryEffect != null) {
|
||||
- for (Player player : entitiesOfClass) {
|
||||
- player.addEffect(new MobEffectInstance(secondaryEffect, i1, 0, true, true));
|
||||
+ double d = computeBeaconRange(beaconLevel); // Paper - diff out applyEffects logic components - see below
|
||||
+ int i = computeEffectAmplifier(beaconLevel, primaryEffect, secondaryEffect); // Paper - diff out applyEffects logic components - see below
|
||||
+
|
||||
+ int i1 = computeEffectDuration(beaconLevel); // Paper - diff out applyEffects logic components - see below
|
||||
+ List<Player> entitiesOfClass = getHumansInRange(level, pos, beaconLevel, blockEntity); // Paper - diff out applyEffects logic components - see below
|
||||
+
|
||||
+ applyEffectsAndCallEvent(level, pos, entitiesOfClass, new MobEffectInstance(primaryEffect, i1, i, true, true), true); // Paper - BeaconEffectEvent
|
||||
+
|
||||
+ if (hasSecondaryEffect(beaconLevel, primaryEffect, secondaryEffect)) { // Paper - diff out applyEffects logic components - see below
|
||||
+ applyEffectsAndCallEvent(level, pos, entitiesOfClass, new MobEffectInstance(secondaryEffect, i1, 0, true, true), false); // Paper - BeaconEffectEvent
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ // Paper start - diff out applyEffects logic components
|
||||
+ // Generally smarter than spigot trying to split the logic up, as that diff is giant.
|
||||
+ private static int computeEffectDuration(final int beaconLevel) {
|
||||
+ return (9 + beaconLevel * 2) * 20; // Diff from applyEffects
|
||||
+ }
|
||||
+
|
||||
+ private static int computeEffectAmplifier(final int beaconLevel, @Nullable Holder<MobEffect> primaryEffect, @Nullable Holder<MobEffect> secondaryEffect) {
|
||||
+ int i = 0;
|
||||
+ if (beaconLevel >= 4 && Objects.equals(primaryEffect, secondaryEffect)) {
|
||||
+ i = 1;
|
||||
+ }
|
||||
+ return i;
|
||||
+ }
|
||||
+
|
||||
+ private static double computeBeaconRange(final int beaconLevel) {
|
||||
+ return beaconLevel * 10 + 10; // Diff from applyEffects
|
||||
+ }
|
||||
+
|
||||
+ public static List<Player> getHumansInRange(final Level level, final BlockPos pos, final int beaconLevel, final @Nullable BeaconBlockEntity blockEntity) {
|
||||
+ final double d = blockEntity != null ? blockEntity.getEffectRange() : computeBeaconRange(beaconLevel);
|
||||
+ AABB aabb = new AABB(pos).inflate(d).expandTowards(0.0, level.getHeight(), 0.0); // Diff from applyEffects
|
||||
+ // Improve performance of human lookup by switching to a global player iteration when searching over 128 blocks
|
||||
+ List<Player> list;
|
||||
+ if (d <= 128.0) {
|
||||
+ list = level.getEntitiesOfClass(Player.class, aabb); // Diff from applyEffect
|
||||
+ } else {
|
||||
+ list = new java.util.ArrayList<>();
|
||||
+ for (final Player player : level.players()) {
|
||||
+ if (!net.minecraft.world.entity.EntitySelector.NO_SPECTATORS.test(player)) continue;
|
||||
+ if (player.getBoundingBox().intersects(aabb)) {
|
||||
+ list.add(player);
|
||||
}
|
||||
}
|
||||
}
|
||||
- }
|
||||
-
|
||||
+ return list;
|
||||
+ }
|
||||
+
|
||||
+ private static boolean hasSecondaryEffect(final int beaconLevel, final Holder<MobEffect> primaryEffect, final @Nullable Holder<MobEffect> secondaryEffect) {
|
||||
+ return beaconLevel >= 4 && !Objects.equals(primaryEffect, secondaryEffect) && secondaryEffect != null;
|
||||
+ }
|
||||
+ // Paper end - diff out applyEffects logic components
|
||||
+
|
||||
+ // Paper start - BeaconEffectEvent
|
||||
+ private static void applyEffectsAndCallEvent(final Level level, final BlockPos position, final List<Player> players, final MobEffectInstance mobEffectInstance, final boolean isPrimary) {
|
||||
+ final org.bukkit.potion.PotionEffect apiEffect = org.bukkit.craftbukkit.potion.CraftPotionUtil.toBukkit(mobEffectInstance);
|
||||
+ final org.bukkit.craftbukkit.block.CraftBlock apiBlock = org.bukkit.craftbukkit.block.CraftBlock.at(level, position);
|
||||
+ for (final Player player : players) {
|
||||
+ final com.destroystokyo.paper.event.block.BeaconEffectEvent event = new com.destroystokyo.paper.event.block.BeaconEffectEvent(
|
||||
+ apiBlock, apiEffect, (org.bukkit.entity.Player) player.getBukkitEntity(), isPrimary
|
||||
+ );
|
||||
+ if (!event.callEvent()) continue;
|
||||
+ player.addEffect(org.bukkit.craftbukkit.potion.CraftPotionUtil.fromBukkit(event.getEffect()));
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end - BeaconEffectEvent
|
||||
public static void playSound(Level level, BlockPos pos, SoundEvent sound) {
|
||||
level.playSound(null, pos, sound, SoundSource.BLOCKS, 1.0F, 1.0F);
|
||||
}
|
||||
@@ -282,7 +_,7 @@
|
||||
private static Holder<MobEffect> loadEffect(CompoundTag tag, String key) {
|
||||
if (tag.contains(key, 8)) {
|
||||
ResourceLocation resourceLocation = ResourceLocation.tryParse(tag.getString(key));
|
||||
- return resourceLocation == null ? null : BuiltInRegistries.MOB_EFFECT.get(resourceLocation).map(BeaconBlockEntity::filterEffect).orElse(null);
|
||||
+ return resourceLocation == null ? null : BuiltInRegistries.MOB_EFFECT.get(resourceLocation).orElse(null); // CraftBukkit - persist manually set non-default beacon effects (SPIGOT-3598)
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
@@ -293,11 +_,13 @@
|
||||
super.loadAdditional(tag, registries);
|
||||
this.primaryPower = loadEffect(tag, "primary_effect");
|
||||
this.secondaryPower = loadEffect(tag, "secondary_effect");
|
||||
+ this.levels = tag.getInt("Levels"); // CraftBukkit - SPIGOT-5053, use where available
|
||||
if (tag.contains("CustomName", 8)) {
|
||||
this.name = parseCustomNameSafe(tag.getString("CustomName"), registries);
|
||||
}
|
||||
|
||||
this.lockKey = LockCode.fromTag(tag, registries);
|
||||
+ this.effectRange = tag.contains(PAPER_RANGE_TAG, 6) ? tag.getDouble(PAPER_RANGE_TAG) : -1; // Paper - Custom beacon ranges
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -311,6 +_,7 @@
|
||||
}
|
||||
|
||||
this.lockKey.addToTag(tag, registries);
|
||||
+ tag.putDouble(PAPER_RANGE_TAG, this.effectRange); // Paper - Custom beacon ranges
|
||||
}
|
||||
|
||||
public void setCustomName(@Nullable Component name) {
|
||||
@@ -326,7 +_,7 @@
|
||||
@Nullable
|
||||
@Override
|
||||
public AbstractContainerMenu createMenu(int containerId, Inventory playerInventory, Player player) {
|
||||
- return BaseContainerBlockEntity.canUnlock(player, this.lockKey, this.getDisplayName())
|
||||
+ return BaseContainerBlockEntity.canUnlock(player, this.lockKey, this.getDisplayName(), this) // Paper - Add BlockLockCheckEvent
|
||||
? new BeaconMenu(containerId, playerInventory, this.dataAccess, ContainerLevelAccess.create(this.level, this.getBlockPos()))
|
||||
: null;
|
||||
}
|
|
@ -0,0 +1,244 @@
|
|||
--- a/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java
|
||||
+++ b/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java
|
||||
@@ -83,6 +_,7 @@
|
||||
private List<BeehiveBlockEntity.BeeData> stored = Lists.newArrayList();
|
||||
@Nullable
|
||||
public BlockPos savedFlowerPos;
|
||||
+ public int maxBees = 3; // CraftBukkit - allow setting max amount of bees a hive can hold
|
||||
|
||||
public BeehiveBlockEntity(BlockPos pos, BlockState blockState) {
|
||||
super(BlockEntityType.BEEHIVE, pos, blockState);
|
||||
@@ -116,7 +_,7 @@
|
||||
}
|
||||
|
||||
public boolean isFull() {
|
||||
- return this.stored.size() == 3;
|
||||
+ return this.stored.size() == this.maxBees; // CraftBukkit
|
||||
}
|
||||
|
||||
public void emptyAllLivingFromHive(@Nullable Player player, BlockState state, BeehiveBlockEntity.BeeReleaseStatus releaseStatus) {
|
||||
@@ -127,7 +_,7 @@
|
||||
Bee bee = (Bee)entity;
|
||||
if (player.position().distanceToSqr(entity.position()) <= 16.0) {
|
||||
if (!this.isSedated()) {
|
||||
- bee.setTarget(player);
|
||||
+ bee.setTarget(player, org.bukkit.event.entity.EntityTargetEvent.TargetReason.CLOSEST_PLAYER, true); // CraftBukkit
|
||||
} else {
|
||||
bee.setStayOutOfHiveCountdown(400);
|
||||
}
|
||||
@@ -138,8 +_,14 @@
|
||||
}
|
||||
|
||||
private List<Entity> releaseAllOccupants(BlockState state, BeehiveBlockEntity.BeeReleaseStatus releaseStatus) {
|
||||
+ // CraftBukkit start - This allows us to bypass the night/rain/emergency check
|
||||
+ return this.releaseBees(state, releaseStatus, false);
|
||||
+ }
|
||||
+
|
||||
+ public List<Entity> releaseBees(BlockState state, BeehiveBlockEntity.BeeReleaseStatus releaseStatus, boolean force) {
|
||||
+ // CraftBukkit end - This allows us to bypass t he night/rain/emergecny check
|
||||
List<Entity> list = Lists.newArrayList();
|
||||
- this.stored.removeIf(data -> releaseOccupant(this.level, this.worldPosition, state, data.toOccupant(), list, releaseStatus, this.savedFlowerPos));
|
||||
+ this.stored.removeIf(data -> releaseOccupant(this.level, this.worldPosition, state, data.toOccupant(), list, releaseStatus, this.savedFlowerPos, force)); // CraftBukkit - This allows us to bypass t he night/rain/emergecny check
|
||||
if (!list.isEmpty()) {
|
||||
super.setChanged();
|
||||
}
|
||||
@@ -152,6 +_,11 @@
|
||||
return this.stored.size();
|
||||
}
|
||||
|
||||
+ // Paper start - Add EntityBlockStorage clearEntities
|
||||
+ public void clearBees() {
|
||||
+ this.stored.clear();
|
||||
+ }
|
||||
+ // Paper end - Add EntityBlockStorage clearEntities
|
||||
public static int getHoneyLevel(BlockState state) {
|
||||
return state.getValue(BeehiveBlock.HONEY_LEVEL);
|
||||
}
|
||||
@@ -162,7 +_,16 @@
|
||||
}
|
||||
|
||||
public void addOccupant(Bee bee) {
|
||||
- if (this.stored.size() < 3) {
|
||||
+ if (this.stored.size() < this.maxBees) { // CraftBukkit
|
||||
+ // CraftBukkit start
|
||||
+ if (this.level != null) {
|
||||
+ org.bukkit.event.entity.EntityEnterBlockEvent event = new org.bukkit.event.entity.EntityEnterBlockEvent(bee.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(this.level, this.getBlockPos()));
|
||||
+ if (!event.callEvent()) {
|
||||
+ bee.setStayOutOfHiveCountdown(400);
|
||||
+ return;
|
||||
+ }
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
bee.stopRiding();
|
||||
bee.ejectPassengers();
|
||||
bee.dropLeash();
|
||||
@@ -187,7 +_,7 @@
|
||||
this.level.gameEvent(GameEvent.BLOCK_CHANGE, blockPos, GameEvent.Context.of(bee, this.getBlockState()));
|
||||
}
|
||||
|
||||
- bee.discard();
|
||||
+ bee.discard(org.bukkit.event.entity.EntityRemoveEvent.Cause.ENTER_BLOCK); // CraftBukkit - add Bukkit remove cause
|
||||
super.setChanged();
|
||||
}
|
||||
}
|
||||
@@ -205,7 +_,21 @@
|
||||
BeehiveBlockEntity.BeeReleaseStatus releaseStatus,
|
||||
@Nullable BlockPos storedFlowerPos
|
||||
) {
|
||||
- if (Bee.isNightOrRaining(level) && releaseStatus != BeehiveBlockEntity.BeeReleaseStatus.EMERGENCY) {
|
||||
+ // CraftBukkit start
|
||||
+ return releaseOccupant(level, pos, state, occupant, storedInHives, releaseStatus, storedFlowerPos, false);
|
||||
+ }
|
||||
+ private static boolean releaseOccupant(
|
||||
+ Level level,
|
||||
+ BlockPos pos,
|
||||
+ BlockState state,
|
||||
+ BeehiveBlockEntity.Occupant occupant,
|
||||
+ @Nullable List<Entity> storedInHives,
|
||||
+ BeehiveBlockEntity.BeeReleaseStatus releaseStatus,
|
||||
+ @Nullable BlockPos storedFlowerPos,
|
||||
+ boolean force
|
||||
+ ) {
|
||||
+ if (!force && Bee.isNightOrRaining(level) && releaseStatus != BeehiveBlockEntity.BeeReleaseStatus.EMERGENCY) {
|
||||
+ // CraftBukkit end
|
||||
return false;
|
||||
} else {
|
||||
Direction direction = state.getValue(BeehiveBlock.FACING);
|
||||
@@ -216,6 +_,17 @@
|
||||
} else {
|
||||
Entity entity = occupant.createEntity(level, pos);
|
||||
if (entity != null) {
|
||||
+ // CraftBukkit start
|
||||
+ if (entity instanceof Bee) {
|
||||
+ float bbWidth = entity.getBbWidth();
|
||||
+ double d = flag ? 0.0 : 0.55 + bbWidth / 2.0F;
|
||||
+ double d1 = pos.getX() + 0.5 + d * direction.getStepX();
|
||||
+ double d2 = pos.getY() + 0.5 - entity.getBbHeight() / 2.0F;
|
||||
+ double d3 = pos.getZ() + 0.5 + d * direction.getStepZ();
|
||||
+ entity.moveTo(d1, d2, d3, entity.getYRot(), entity.getXRot());
|
||||
+ }
|
||||
+ if (!level.addFreshEntity(entity, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.BEEHIVE)) return false; // CraftBukkit - SpawnReason, moved from below
|
||||
+ // CraftBukkit end
|
||||
if (entity instanceof Bee bee) {
|
||||
if (storedFlowerPos != null && !bee.hasSavedFlowerPos() && level.random.nextFloat() < 0.9F) {
|
||||
bee.setSavedFlowerPos(storedFlowerPos);
|
||||
@@ -231,7 +_,13 @@
|
||||
i--;
|
||||
}
|
||||
|
||||
- level.setBlockAndUpdate(pos, state.setValue(BeehiveBlock.HONEY_LEVEL, Integer.valueOf(honeyLevel + i)));
|
||||
+ // Paper start - Fire EntityChangeBlockEvent in more places
|
||||
+ BlockState newBlockState = state.setValue(BeehiveBlock.HONEY_LEVEL, Integer.valueOf(honeyLevel + i));
|
||||
+
|
||||
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(entity, pos, newBlockState)) {
|
||||
+ level.setBlockAndUpdate(pos, newBlockState);
|
||||
+ }
|
||||
+ // Paper end - Fire EntityChangeBlockEvent in more places
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -240,17 +_,19 @@
|
||||
storedInHives.add(bee);
|
||||
}
|
||||
|
||||
+ /* CraftBukkit start - move up
|
||||
float bbWidth = entity.getBbWidth();
|
||||
double d = flag ? 0.0 : 0.55 + bbWidth / 2.0F;
|
||||
double d1 = pos.getX() + 0.5 + d * direction.getStepX();
|
||||
double d2 = pos.getY() + 0.5 - entity.getBbHeight() / 2.0F;
|
||||
double d3 = pos.getZ() + 0.5 + d * direction.getStepZ();
|
||||
entity.moveTo(d1, d2, d3, entity.getYRot(), entity.getXRot());
|
||||
+ */ // CraftBukkit end
|
||||
}
|
||||
|
||||
level.playSound(null, pos, SoundEvents.BEEHIVE_EXIT, SoundSource.BLOCKS, 1.0F, 1.0F);
|
||||
level.gameEvent(GameEvent.BLOCK_CHANGE, pos, GameEvent.Context.of(entity, level.getBlockState(pos)));
|
||||
- return level.addFreshEntity(entity);
|
||||
+ return true; // CraftBukkit - moved up
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
@@ -276,6 +_,11 @@
|
||||
flag = true;
|
||||
iterator.remove();
|
||||
}
|
||||
+ // Paper start - Fix bees aging inside; use exitTickCounter to keep actual bee life
|
||||
+ else {
|
||||
+ beeData.exitTickCounter = beeData.occupant.minTicksInHive / 2;
|
||||
+ }
|
||||
+ // Paper end - Fix bees aging inside; use exitTickCounter to keep actual bee life
|
||||
}
|
||||
}
|
||||
|
||||
@@ -299,7 +_,7 @@
|
||||
@Override
|
||||
protected void loadAdditional(CompoundTag tag, HolderLookup.Provider registries) {
|
||||
super.loadAdditional(tag, registries);
|
||||
- this.stored.clear();
|
||||
+ this.stored = Lists.newArrayList(); // CraftBukkit - SPIGOT-7790: create new copy (may be modified in physics event triggered by honey change)
|
||||
if (tag.contains("bees")) {
|
||||
BeehiveBlockEntity.Occupant.LIST_CODEC
|
||||
.parse(NbtOps.INSTANCE, tag.get("bees"))
|
||||
@@ -308,6 +_,11 @@
|
||||
}
|
||||
|
||||
this.savedFlowerPos = NbtUtils.readBlockPos(tag, "flower_pos").orElse(null);
|
||||
+ // CraftBukkit start
|
||||
+ if (tag.contains("Bukkit.MaxEntities")) {
|
||||
+ this.maxBees = tag.getInt("Bukkit.MaxEntities");
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -317,12 +_,13 @@
|
||||
if (this.hasSavedFlowerPos()) {
|
||||
tag.put("flower_pos", NbtUtils.writeBlockPos(this.savedFlowerPos));
|
||||
}
|
||||
+ tag.putInt("Bukkit.MaxEntities", this.maxBees); // CraftBukkit
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void applyImplicitComponents(BlockEntity.DataComponentInput componentInput) {
|
||||
super.applyImplicitComponents(componentInput);
|
||||
- this.stored.clear();
|
||||
+ this.stored = Lists.newArrayList(); // CraftBukkit - SPIGOT-7790: create new copy (may be modified in physics event triggered by honey change)
|
||||
List<BeehiveBlockEntity.Occupant> list = componentInput.getOrDefault(DataComponents.BEES, List.of());
|
||||
list.forEach(this::storeBee);
|
||||
}
|
||||
@@ -345,15 +_,18 @@
|
||||
|
||||
static class BeeData {
|
||||
private final BeehiveBlockEntity.Occupant occupant;
|
||||
+ private int exitTickCounter; // Paper - Fix bees aging inside hives; separate counter for checking if bee should exit to reduce exit attempts
|
||||
private int ticksInHive;
|
||||
|
||||
BeeData(BeehiveBlockEntity.Occupant occupant) {
|
||||
this.occupant = occupant;
|
||||
this.ticksInHive = occupant.ticksInHive();
|
||||
+ this.exitTickCounter = this.ticksInHive; // Paper - Fix bees aging inside hives
|
||||
}
|
||||
|
||||
public boolean tick() {
|
||||
- return this.ticksInHive++ > this.occupant.minTicksInHive;
|
||||
+ this.ticksInHive++; // Paper - Fix bees aging inside hives
|
||||
+ return this.exitTickCounter++ > this.occupant.minTicksInHive; // Paper - Fix bees aging inside hives
|
||||
}
|
||||
|
||||
public BeehiveBlockEntity.Occupant toOccupant() {
|
||||
@@ -424,6 +_,7 @@
|
||||
}
|
||||
|
||||
private static void setBeeReleaseData(int ticksInHive, Bee bee) {
|
||||
+ if (!bee.ageLocked) { // Paper - Honor ageLock
|
||||
int age = bee.getAge();
|
||||
if (age < 0) {
|
||||
bee.setAge(Math.min(0, age + ticksInHive));
|
||||
@@ -432,6 +_,7 @@
|
||||
}
|
||||
|
||||
bee.setInLoveTime(Math.max(0, bee.getInLoveTime() - ticksInHive));
|
||||
+ } // Paper - Honor ageLock
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,133 @@
|
|||
--- a/net/minecraft/world/level/block/entity/BlockEntity.java
|
||||
+++ b/net/minecraft/world/level/block/entity/BlockEntity.java
|
||||
@@ -26,6 +_,10 @@
|
||||
import org.slf4j.Logger;
|
||||
|
||||
public abstract class BlockEntity {
|
||||
+ // CraftBukkit start - data containers
|
||||
+ private static final org.bukkit.craftbukkit.persistence.CraftPersistentDataTypeRegistry DATA_TYPE_REGISTRY = new org.bukkit.craftbukkit.persistence.CraftPersistentDataTypeRegistry();
|
||||
+ public org.bukkit.craftbukkit.persistence.CraftPersistentDataContainer persistentDataContainer;
|
||||
+ // CraftBukkit end
|
||||
private static final Logger LOGGER = LogUtils.getLogger();
|
||||
private final BlockEntityType<?> type;
|
||||
@Nullable
|
||||
@@ -40,6 +_,7 @@
|
||||
this.worldPosition = pos.immutable();
|
||||
this.validateBlockState(blockState);
|
||||
this.blockState = blockState;
|
||||
+ this.persistentDataContainer = new org.bukkit.craftbukkit.persistence.CraftPersistentDataContainer(DATA_TYPE_REGISTRY); // Paper - always init
|
||||
}
|
||||
|
||||
private void validateBlockState(BlockState state) {
|
||||
@@ -70,6 +_,14 @@
|
||||
}
|
||||
|
||||
protected void loadAdditional(CompoundTag tag, HolderLookup.Provider registries) {
|
||||
+ // Paper start - read persistent data container
|
||||
+ this.persistentDataContainer.clear(); // Paper - clear instead of init
|
||||
+
|
||||
+ net.minecraft.nbt.Tag persistentDataTag = tag.get("PublicBukkitValues");
|
||||
+ if (persistentDataTag instanceof CompoundTag) {
|
||||
+ this.persistentDataContainer.putAll((CompoundTag) persistentDataTag);
|
||||
+ }
|
||||
+ // Paper end - read persistent data container
|
||||
}
|
||||
|
||||
public final void loadWithComponents(CompoundTag tag, HolderLookup.Provider registries) {
|
||||
@@ -106,12 +_,22 @@
|
||||
.encodeStart(registries.createSerializationContext(NbtOps.INSTANCE), this.components)
|
||||
.resultOrPartial(string -> LOGGER.warn("Failed to save components: {}", string))
|
||||
.ifPresent(tag -> compoundTag.merge((CompoundTag)tag));
|
||||
+ // CraftBukkit start - store container
|
||||
+ if (this.persistentDataContainer != null && !this.persistentDataContainer.isEmpty()) {
|
||||
+ compoundTag.put("PublicBukkitValues", this.persistentDataContainer.toTagCompound());
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
return compoundTag;
|
||||
}
|
||||
|
||||
public final CompoundTag saveCustomOnly(HolderLookup.Provider registries) {
|
||||
CompoundTag compoundTag = new CompoundTag();
|
||||
this.saveAdditional(compoundTag, registries);
|
||||
+ // Paper start - store PDC here as well
|
||||
+ if (this.persistentDataContainer != null && !this.persistentDataContainer.isEmpty()) {
|
||||
+ compoundTag.put("PublicBukkitValues", this.persistentDataContainer.toTagCompound());
|
||||
+ }
|
||||
+ // Paper end
|
||||
return compoundTag;
|
||||
}
|
||||
|
||||
@@ -220,7 +_,12 @@
|
||||
public void fillCrashReportCategory(CrashReportCategory reportCategory) {
|
||||
reportCategory.setDetail("Name", this::getNameForReporting);
|
||||
if (this.level != null) {
|
||||
- CrashReportCategory.populateBlockDetails(reportCategory, this.level, this.worldPosition, this.getBlockState());
|
||||
+ // Paper start - Prevent block entity and entity crashes
|
||||
+ BlockState block = this.getBlockState();
|
||||
+ if (block != null) {
|
||||
+ CrashReportCategory.populateBlockDetails(reportCategory, this.level, this.worldPosition, block);
|
||||
+ }
|
||||
+ // Paper end - Prevent block entity and entity crashes
|
||||
CrashReportCategory.populateBlockDetails(reportCategory, this.level, this.worldPosition, this.level.getBlockState(this.worldPosition));
|
||||
}
|
||||
}
|
||||
@@ -247,10 +_,16 @@
|
||||
}
|
||||
|
||||
public final void applyComponents(DataComponentMap components, DataComponentPatch patch) {
|
||||
+ // CraftBukkit start
|
||||
+ this.applyComponentsSet(components, patch);
|
||||
+ }
|
||||
+
|
||||
+ public final Set<DataComponentType<?>> applyComponentsSet(DataComponentMap components, DataComponentPatch patch) {
|
||||
+ // CraftBukkit end
|
||||
final Set<DataComponentType<?>> set = new HashSet<>();
|
||||
set.add(DataComponents.BLOCK_ENTITY_DATA);
|
||||
set.add(DataComponents.BLOCK_STATE);
|
||||
- final DataComponentMap dataComponentMap = PatchedDataComponentMap.fromPatch(components, patch);
|
||||
+ final PatchedDataComponentMap dataComponentMap = PatchedDataComponentMap.fromPatch(components, patch);
|
||||
this.applyImplicitComponents(new BlockEntity.DataComponentInput() {
|
||||
@Nullable
|
||||
@Override
|
||||
@@ -267,6 +_,10 @@
|
||||
});
|
||||
DataComponentPatch dataComponentPatch = patch.forget(set::contains);
|
||||
this.components = dataComponentPatch.split().added();
|
||||
+ // CraftBukkit start
|
||||
+ set.remove(DataComponents.BLOCK_ENTITY_DATA); // Remove as never actually added by applyImplicitComponents
|
||||
+ return set;
|
||||
+ // CraftBukkit end
|
||||
}
|
||||
|
||||
protected void collectImplicitComponents(DataComponentMap.Builder components) {
|
||||
@@ -300,6 +_,30 @@
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+
|
||||
+ // CraftBukkit start - add method
|
||||
+ public org.bukkit.inventory.InventoryHolder getOwner() {
|
||||
+ // Paper start
|
||||
+ return getOwner(true);
|
||||
+ }
|
||||
+ public org.bukkit.inventory.InventoryHolder getOwner(boolean useSnapshot) {
|
||||
+ // 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; // Paper - actually get the tile entity if it still exists
|
||||
+ org.bukkit.block.BlockState state = block.getState(useSnapshot); // Paper
|
||||
+ return state instanceof final org.bukkit.inventory.InventoryHolder inventoryHolder ? inventoryHolder : null;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
+ // Paper start - Sanitize sent data
|
||||
+ public CompoundTag sanitizeSentNbt(CompoundTag tag) {
|
||||
+ tag.remove("PublicBukkitValues");
|
||||
+
|
||||
+ return tag;
|
||||
+ }
|
||||
+ // Paper end - Sanitize sent data
|
||||
+
|
||||
|
||||
static class ComponentHelper {
|
||||
public static final Codec<DataComponentMap> COMPONENTS_CODEC = DataComponentMap.CODEC.optionalFieldOf("components", DataComponentMap.EMPTY).codec();
|
|
@ -0,0 +1,186 @@
|
|||
--- a/net/minecraft/world/level/block/entity/BrewingStandBlockEntity.java
|
||||
+++ b/net/minecraft/world/level/block/entity/BrewingStandBlockEntity.java
|
||||
@@ -8,7 +_,6 @@
|
||||
import net.minecraft.core.NonNullList;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.chat.Component;
|
||||
-import net.minecraft.tags.ItemTags;
|
||||
import net.minecraft.world.ContainerHelper;
|
||||
import net.minecraft.world.Containers;
|
||||
import net.minecraft.world.WorldlyContainer;
|
||||
@@ -36,6 +_,7 @@
|
||||
public static final int NUM_DATA_VALUES = 2;
|
||||
private NonNullList<ItemStack> items = NonNullList.withSize(5, ItemStack.EMPTY);
|
||||
public int brewTime;
|
||||
+ public int recipeBrewTime = 400; // Paper - Add recipeBrewTime
|
||||
private boolean[] lastPotionCount;
|
||||
private Item ingredient;
|
||||
public int fuel;
|
||||
@@ -45,6 +_,7 @@
|
||||
return switch (index) {
|
||||
case 0 -> BrewingStandBlockEntity.this.brewTime;
|
||||
case 1 -> BrewingStandBlockEntity.this.fuel;
|
||||
+ case 2 -> BrewingStandBlockEntity.this.recipeBrewTime; // Paper - Add recipeBrewTime
|
||||
default -> 0;
|
||||
};
|
||||
}
|
||||
@@ -57,14 +_,50 @@
|
||||
break;
|
||||
case 1:
|
||||
BrewingStandBlockEntity.this.fuel = value;
|
||||
+ // Paper start - Add recipeBrewTime
|
||||
+ break;
|
||||
+ case 2:
|
||||
+ BrewingStandBlockEntity.this.recipeBrewTime = value;
|
||||
+ break;
|
||||
+ // Paper end - Add recipeBrewTime
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
- return 2;
|
||||
+ return 3; // Paper - Add recipeBrewTime
|
||||
}
|
||||
};
|
||||
+ // CraftBukkit start - add fields and methods
|
||||
+ // private int lastTick = MinecraftServer.currentTick; // Paper - remove anti tick skipping measures / wall time
|
||||
+ public java.util.List<org.bukkit.entity.HumanEntity> transaction = new java.util.ArrayList<>();
|
||||
+ private int maxStack = MAX_STACK;
|
||||
+
|
||||
+ public void onOpen(org.bukkit.craftbukkit.entity.CraftHumanEntity who) {
|
||||
+ this.transaction.add(who);
|
||||
+ }
|
||||
+
|
||||
+ public void onClose(org.bukkit.craftbukkit.entity.CraftHumanEntity who) {
|
||||
+ this.transaction.remove(who);
|
||||
+ }
|
||||
+
|
||||
+ public List<HumanEntity> getViewers() {
|
||||
+ return this.transaction;
|
||||
+ }
|
||||
+
|
||||
+ public java.util.List<net.minecraft.world.item.ItemStack> getContents() {
|
||||
+ return this.items;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public int getMaxStackSize() {
|
||||
+ return this.maxStack;
|
||||
+ }
|
||||
+
|
||||
+ public void setMaxStackSize(int size) {
|
||||
+ this.maxStack = size;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
|
||||
public BrewingStandBlockEntity(BlockPos pos, BlockState state) {
|
||||
super(BlockEntityType.BREWING_STAND, pos, state);
|
||||
@@ -92,9 +_,22 @@
|
||||
|
||||
public static void serverTick(Level level, BlockPos pos, BlockState state, BrewingStandBlockEntity blockEntity) {
|
||||
ItemStack itemStack = blockEntity.items.get(4);
|
||||
- if (blockEntity.fuel <= 0 && itemStack.is(ItemTags.BREWING_FUEL)) {
|
||||
- blockEntity.fuel = 20;
|
||||
- itemStack.shrink(1);
|
||||
+ if (blockEntity.fuel <= 0 && itemStack.is(net.minecraft.tags.ItemTags.BREWING_FUEL)) {
|
||||
+ // CraftBukkit start
|
||||
+ org.bukkit.event.inventory.BrewingStandFuelEvent event = new org.bukkit.event.inventory.BrewingStandFuelEvent(
|
||||
+ org.bukkit.craftbukkit.block.CraftBlock.at(level, pos),
|
||||
+ org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemStack),
|
||||
+ 20
|
||||
+ );
|
||||
+ if (!event.callEvent()) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ blockEntity.fuel = event.getFuelPower();
|
||||
+ if (blockEntity.fuel > 0 && event.isConsuming()) {
|
||||
+ itemStack.shrink(1);
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
setChanged(level, pos, state);
|
||||
}
|
||||
|
||||
@@ -105,7 +_,7 @@
|
||||
blockEntity.brewTime--;
|
||||
boolean flag1 = blockEntity.brewTime == 0;
|
||||
if (flag1 && isBrewable) {
|
||||
- doBrew(level, pos, blockEntity.items);
|
||||
+ doBrew(level, pos, blockEntity.items, blockEntity); // CraftBukkit
|
||||
} else if (!isBrewable || !itemStack1.is(blockEntity.ingredient)) {
|
||||
blockEntity.brewTime = 0;
|
||||
}
|
||||
@@ -114,6 +_,14 @@
|
||||
} else if (isBrewable && blockEntity.fuel > 0) {
|
||||
blockEntity.fuel--;
|
||||
blockEntity.brewTime = 400;
|
||||
+ // CraftBukkit start
|
||||
+ org.bukkit.event.block.BrewingStartEvent event = new org.bukkit.event.block.BrewingStartEvent(
|
||||
+ org.bukkit.craftbukkit.block.CraftBlock.at(level, pos),
|
||||
+ org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemStack1), 400);
|
||||
+ event.callEvent();
|
||||
+ blockEntity.recipeBrewTime = event.getRecipeBrewTime(); // Paper - use recipe brew time from event
|
||||
+ blockEntity.brewTime = event.getBrewingTime(); // 400 -> event.getTotalBrewTime() // Paper - use brewing time from event
|
||||
+ // CraftBukkit end
|
||||
blockEntity.ingredient = itemStack1.getItem();
|
||||
setChanged(level, pos, state);
|
||||
}
|
||||
@@ -164,13 +_,37 @@
|
||||
}
|
||||
}
|
||||
|
||||
- private static void doBrew(Level level, BlockPos pos, NonNullList<ItemStack> items) {
|
||||
+ private static void doBrew(Level level, BlockPos pos, NonNullList<ItemStack> items, BrewingStandBlockEntity brewingStandBlockEntity) { // CraftBukkit
|
||||
ItemStack itemStack = items.get(3);
|
||||
PotionBrewing potionBrewing = level.potionBrewing();
|
||||
|
||||
+ // CraftBukkit start
|
||||
+ org.bukkit.inventory.InventoryHolder owner = brewingStandBlockEntity.getOwner();
|
||||
+ java.util.List<org.bukkit.inventory.ItemStack> brewResults = new java.util.ArrayList<>(3);
|
||||
for (int i = 0; i < 3; i++) {
|
||||
- items.set(i, potionBrewing.mix(itemStack, items.get(i)));
|
||||
- }
|
||||
+ brewResults.add(i, org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(potionBrewing.mix(itemStack, items.get(i))));
|
||||
+ }
|
||||
+
|
||||
+ if (owner != null) {
|
||||
+ org.bukkit.event.inventory.BrewEvent event = new org.bukkit.event.inventory.BrewEvent(
|
||||
+ org.bukkit.craftbukkit.block.CraftBlock.at(level, pos),
|
||||
+ (org.bukkit.inventory.BrewerInventory) owner.getInventory(),
|
||||
+ brewResults,
|
||||
+ brewingStandBlockEntity.fuel
|
||||
+ );
|
||||
+ if (!event.callEvent()) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ for (int i = 0; i < 3; i++) {
|
||||
+ if (i < brewResults.size()) {
|
||||
+ items.set(i, org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(brewResults.get(i)));
|
||||
+ } else {
|
||||
+ items.set(i, ItemStack.EMPTY);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
|
||||
itemStack.shrink(1);
|
||||
ItemStack craftingRemainder = itemStack.getItem().getCraftingRemainder();
|
||||
@@ -209,13 +_,13 @@
|
||||
|
||||
@Override
|
||||
public boolean canPlaceItem(int index, ItemStack stack) {
|
||||
+ PotionBrewing potionBrewing = this.level != null ? this.level.potionBrewing() : PotionBrewing.EMPTY; // Paper - move up
|
||||
if (index == 3) {
|
||||
- PotionBrewing potionBrewing = this.level != null ? this.level.potionBrewing() : PotionBrewing.EMPTY;
|
||||
return potionBrewing.isIngredient(stack);
|
||||
} else {
|
||||
return index == 4
|
||||
- ? stack.is(ItemTags.BREWING_FUEL)
|
||||
- : (stack.is(Items.POTION) || stack.is(Items.SPLASH_POTION) || stack.is(Items.LINGERING_POTION) || stack.is(Items.GLASS_BOTTLE))
|
||||
+ ? stack.is(net.minecraft.tags.ItemTags.BREWING_FUEL)
|
||||
+ : (stack.is(Items.POTION) || stack.is(Items.SPLASH_POTION) || stack.is(Items.LINGERING_POTION) || stack.is(Items.GLASS_BOTTLE) || potionBrewing.isCustomInput(stack)) // Paper - Custom Potion Mixes
|
||||
&& this.getItem(index).isEmpty();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
--- a/net/minecraft/world/level/block/entity/BrushableBlockEntity.java
|
||||
+++ b/net/minecraft/world/level/block/entity/BrushableBlockEntity.java
|
||||
@@ -138,7 +_,10 @@
|
||||
double d5 = blockPos.getZ() + 0.5 * d1 + d2;
|
||||
ItemEntity itemEntity = new ItemEntity(level, d3, d4, d5, this.item.split(level.random.nextInt(21) + 10));
|
||||
itemEntity.setDeltaMovement(Vec3.ZERO);
|
||||
- level.addFreshEntity(itemEntity);
|
||||
+ // CraftBukkit start
|
||||
+ org.bukkit.block.Block bblock = org.bukkit.craftbukkit.block.CraftBlock.at(this.level, this.worldPosition);
|
||||
+ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockDropItemEvent(bblock, bblock.getState(), (ServerPlayer) player, java.util.List.of(itemEntity));
|
||||
+ // CraftBukkit end
|
||||
this.item = ItemStack.EMPTY;
|
||||
}
|
||||
}
|
||||
@@ -167,7 +_,7 @@
|
||||
|
||||
private boolean tryLoadLootTable(CompoundTag tag) {
|
||||
if (tag.contains("LootTable", 8)) {
|
||||
- this.lootTable = ResourceKey.create(Registries.LOOT_TABLE, ResourceLocation.parse(tag.getString("LootTable")));
|
||||
+ this.lootTable = net.minecraft.Optionull.map(ResourceLocation.tryParse(tag.getString("LootTable")), rl -> ResourceKey.create(Registries.LOOT_TABLE, rl)); // Paper - Validate ResourceLocation
|
||||
this.lootTableSeed = tag.getLong("LootTableSeed");
|
||||
return true;
|
||||
} else {
|
|
@ -1,6 +1,6 @@
|
|||
--- a/net/minecraft/world/level/block/entity/CalibratedSculkSensorBlockEntity.java
|
||||
+++ b/net/minecraft/world/level/block/entity/CalibratedSculkSensorBlockEntity.java
|
||||
@@ -20,6 +20,12 @@
|
||||
@@ -20,6 +_,12 @@
|
||||
public VibrationSystem.User createVibrationUser() {
|
||||
return new CalibratedSculkSensorBlockEntity.VibrationUser(this.getBlockPos());
|
||||
}
|
||||
|
@ -12,8 +12,8 @@
|
|||
+ // Paper end - Configurable sculk sensor listener range
|
||||
|
||||
protected class VibrationUser extends SculkSensorBlockEntity.VibrationUser {
|
||||
public VibrationUser(final BlockPos pos) {
|
||||
@@ -28,6 +34,7 @@
|
||||
public VibrationUser(final BlockPos pos1) {
|
||||
@@ -28,6 +_,7 @@
|
||||
|
||||
@Override
|
||||
public int getListenerRadius() {
|
|
@ -0,0 +1,104 @@
|
|||
--- a/net/minecraft/world/level/block/entity/CampfireBlockEntity.java
|
||||
+++ b/net/minecraft/world/level/block/entity/CampfireBlockEntity.java
|
||||
@@ -36,6 +_,7 @@
|
||||
private final NonNullList<ItemStack> items = NonNullList.withSize(4, ItemStack.EMPTY);
|
||||
public final int[] cookingProgress = new int[4];
|
||||
public final int[] cookingTime = new int[4];
|
||||
+ public final boolean[] stopCooking = new boolean[4]; // Paper - Add more Campfire API
|
||||
|
||||
public CampfireBlockEntity(BlockPos pos, BlockState blockState) {
|
||||
super(BlockEntityType.CAMPFIRE, pos, blockState);
|
||||
@@ -54,14 +_,42 @@
|
||||
ItemStack itemStack = campfire.items.get(i);
|
||||
if (!itemStack.isEmpty()) {
|
||||
flag = true;
|
||||
+ if (!campfire.stopCooking[i]) { // Paper - Add more Campfire API
|
||||
campfire.cookingProgress[i]++;
|
||||
+ } // Paper - Add more Campfire API
|
||||
if (campfire.cookingProgress[i] >= campfire.cookingTime[i]) {
|
||||
SingleRecipeInput singleRecipeInput = new SingleRecipeInput(itemStack);
|
||||
- ItemStack itemStack1 = check.getRecipeFor(singleRecipeInput, level)
|
||||
+ final var optionalCookingRecipe = check.getRecipeFor(singleRecipeInput, level);
|
||||
+ ItemStack itemStack1 = optionalCookingRecipe
|
||||
.map(recipe -> recipe.value().assemble(singleRecipeInput, level.registryAccess()))
|
||||
.orElse(itemStack);
|
||||
if (itemStack1.isItemEnabled(level.enabledFeatures())) {
|
||||
- Containers.dropItemStack(level, pos.getX(), pos.getY(), pos.getZ(), itemStack1);
|
||||
+ // CraftBukkit start - fire BlockCookEvent
|
||||
+ org.bukkit.craftbukkit.inventory.CraftItemStack source = org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemStack);
|
||||
+ org.bukkit.inventory.ItemStack result = org.bukkit.craftbukkit.inventory.CraftItemStack.asBukkitCopy(itemStack1);
|
||||
+
|
||||
+ org.bukkit.event.block.BlockCookEvent blockCookEvent = new org.bukkit.event.block.BlockCookEvent(
|
||||
+ org.bukkit.craftbukkit.block.CraftBlock.at(level, pos),
|
||||
+ source,
|
||||
+ result,
|
||||
+ (org.bukkit.inventory.CookingRecipe<?>) optionalCookingRecipe.map(RecipeHolder::toBukkitRecipe).orElse(null) // Paper -Add recipe to cook events
|
||||
+ );
|
||||
+
|
||||
+ if (!blockCookEvent.callEvent()) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ result = blockCookEvent.getResult();
|
||||
+ itemStack1 = org.bukkit.craftbukkit.inventory.CraftItemStack.asNMSCopy(result);
|
||||
+ // CraftBukkit end
|
||||
+ // Paper start - Fix item locations dropped from campfires
|
||||
+ double deviation = 0.05F * RandomSource.GAUSSIAN_SPREAD_FACTOR;
|
||||
+ while (!itemStack1.isEmpty()) {
|
||||
+ net.minecraft.world.entity.item.ItemEntity droppedItem = new net.minecraft.world.entity.item.ItemEntity(level, pos.getX() + 0.5D, pos.getY() + 0.5D, pos.getZ() + 0.5D, itemStack1.split(level.random.nextInt(21) + 10));
|
||||
+ droppedItem.setDeltaMovement(level.random.triangle(0.0D, deviation), level.random.triangle(0.2D, deviation), level.random.triangle(0.0D, deviation));
|
||||
+ level.addFreshEntity(droppedItem);
|
||||
+ }
|
||||
+ // Paper end - Fix item locations dropped from campfires
|
||||
campfire.items.set(i, ItemStack.EMPTY);
|
||||
level.sendBlockUpdated(pos, state, state, 3);
|
||||
level.gameEvent(GameEvent.BLOCK_CHANGE, pos, GameEvent.Context.of(state));
|
||||
@@ -133,6 +_,17 @@
|
||||
int[] intArray = tag.getIntArray("CookingTotalTimes");
|
||||
System.arraycopy(intArray, 0, this.cookingTime, 0, Math.min(this.cookingTime.length, intArray.length));
|
||||
}
|
||||
+
|
||||
+ // Paper start - Add more Campfire API
|
||||
+ if (tag.contains("Paper.StopCooking", org.bukkit.craftbukkit.util.CraftMagicNumbers.NBT.TAG_BYTE_ARRAY)) {
|
||||
+ byte[] abyte = tag.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
|
||||
@@ -141,6 +_,13 @@
|
||||
ContainerHelper.saveAllItems(tag, this.items, true, registries);
|
||||
tag.putIntArray("CookingTimes", this.cookingProgress);
|
||||
tag.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);
|
||||
+ }
|
||||
+ tag.putByteArray("Paper.StopCooking", cookingState);
|
||||
+ // Paper end - Add more Campfire API
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -165,7 +_,15 @@
|
||||
return false;
|
||||
}
|
||||
|
||||
- this.cookingTime[i] = recipeFor.get().value().cookingTime();
|
||||
+ // CraftBukkit start
|
||||
+ org.bukkit.event.block.CampfireStartEvent event = new org.bukkit.event.block.CampfireStartEvent(
|
||||
+ org.bukkit.craftbukkit.block.CraftBlock.at(this.level,this.worldPosition),
|
||||
+ org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(stack),
|
||||
+ (org.bukkit.inventory.CampfireRecipe) recipeFor.get().toBukkitRecipe()
|
||||
+ );
|
||||
+ this.level.getCraftServer().getPluginManager().callEvent(event);
|
||||
+ this.cookingTime[i] = event.getTotalCookTime(); // i -> event.getTotalCookTime()
|
||||
+ // CraftBukkit end
|
||||
this.cookingProgress[i] = 0;
|
||||
this.items.set(i, stack.consumeAndReturn(1, entity));
|
||||
level.gameEvent(GameEvent.BLOCK_CHANGE, this.getBlockPos(), GameEvent.Context.of(entity, this.getBlockState()));
|
|
@ -20,7 +20,7 @@
|
|||
+ this.transaction.remove(who);
|
||||
+ }
|
||||
+
|
||||
+ public java.util.List<org.bukkit.entity.HumanEntity> getViewers() {
|
||||
+ public List<HumanEntity> getViewers() {
|
||||
+ return this.transaction;
|
||||
+ }
|
||||
+
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public java.util.List<org.bukkit.entity.HumanEntity> getViewers() {
|
||||
+ public List<HumanEntity> getViewers() {
|
||||
+ return this.transaction;
|
||||
+ }
|
||||
+
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
--- a/net/minecraft/world/level/block/entity/ConduitBlockEntity.java
|
||||
+++ b/net/minecraft/world/level/block/entity/ConduitBlockEntity.java
|
||||
@@ -9,6 +_,7 @@
|
||||
import net.minecraft.core.particles.ParticleTypes;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket;
|
||||
+import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.sounds.SoundEvent;
|
||||
import net.minecraft.sounds.SoundEvents;
|
||||
import net.minecraft.sounds.SoundSource;
|
||||
@@ -168,8 +_,20 @@
|
||||
}
|
||||
|
||||
private static void applyEffects(Level level, BlockPos pos, List<BlockPos> positions) {
|
||||
+ // CraftBukkit start
|
||||
+ ConduitBlockEntity.applyEffects(level, pos, ConduitBlockEntity.getRange(positions));
|
||||
+ }
|
||||
+
|
||||
+ public static int getRange(List<BlockPos> positions) {
|
||||
+ // CraftBukkit end
|
||||
int size = positions.size();
|
||||
int i = size / 7 * 16;
|
||||
+ // CraftBukkit start
|
||||
+ return i;
|
||||
+ }
|
||||
+
|
||||
+ private static void applyEffects(Level level, BlockPos pos, int i) { // i = effect range in blocks
|
||||
+ // CraftBukkit end
|
||||
int x = pos.getX();
|
||||
int y = pos.getY();
|
||||
int z = pos.getZ();
|
||||
@@ -185,6 +_,12 @@
|
||||
}
|
||||
|
||||
private static void updateDestroyTarget(Level level, BlockPos pos, BlockState state, List<BlockPos> positions, ConduitBlockEntity blockEntity) {
|
||||
+ // CraftBukkit start - add "damageTarget" boolean
|
||||
+ ConduitBlockEntity.updateDestroyTarget(level, pos, state, positions, blockEntity, true);
|
||||
+ }
|
||||
+
|
||||
+ public static void updateDestroyTarget(Level level, BlockPos pos, BlockState state, List<BlockPos> positions, ConduitBlockEntity blockEntity, boolean damageTarget) {
|
||||
+ // CraftBukkit end
|
||||
LivingEntity livingEntity = blockEntity.destroyTarget;
|
||||
int size = positions.size();
|
||||
if (size < 42) {
|
||||
@@ -203,7 +_,8 @@
|
||||
blockEntity.destroyTarget = null;
|
||||
}
|
||||
|
||||
- if (blockEntity.destroyTarget != null) {
|
||||
+ if (damageTarget && blockEntity.destroyTarget != null) { // CraftBukkit
|
||||
+ if (blockEntity.destroyTarget.hurtServer((net.minecraft.server.level.ServerLevel) level, level.damageSources().magic(), 4.0F)) // CraftBukkit
|
||||
level.playSound(
|
||||
null,
|
||||
blockEntity.destroyTarget.getX(),
|
||||
@@ -214,7 +_,6 @@
|
||||
1.0F,
|
||||
1.0F
|
||||
);
|
||||
- blockEntity.destroyTarget.hurt(level.damageSources().magic(), 4.0F);
|
||||
}
|
||||
|
||||
if (livingEntity != blockEntity.destroyTarget) {
|
|
@ -1,76 +1,76 @@
|
|||
--- a/net/minecraft/world/level/block/entity/ContainerOpenersCounter.java
|
||||
+++ b/net/minecraft/world/level/block/entity/ContainerOpenersCounter.java
|
||||
@@ -17,6 +17,7 @@
|
||||
@@ -13,6 +_,7 @@
|
||||
private static final int CHECK_TICK_DELAY = 5;
|
||||
private int openCount;
|
||||
private double maxInteractionRange;
|
||||
+ public boolean opened; // CraftBukkit
|
||||
+ public boolean opened; // CraftBukki
|
||||
|
||||
public ContainerOpenersCounter() {}
|
||||
protected abstract void onOpen(Level level, BlockPos pos, BlockState state);
|
||||
|
||||
@@ -26,11 +27,36 @@
|
||||
@@ -20,10 +_,36 @@
|
||||
|
||||
protected abstract void openerCountChanged(Level world, BlockPos pos, BlockState state, int oldViewerCount, int newViewerCount);
|
||||
protected abstract void openerCountChanged(Level level, BlockPos pos, BlockState state, int count, int openCount);
|
||||
|
||||
+ // CraftBukkit start
|
||||
+ public void onAPIOpen(Level world, BlockPos blockposition, BlockState iblockdata) {
|
||||
+ this.onOpen(world, blockposition, iblockdata);
|
||||
+ public void onAPIOpen(Level level, BlockPos blockPos, BlockState blockState) {
|
||||
+ this.onOpen(level, blockPos, blockState);
|
||||
+ }
|
||||
+
|
||||
+ public void onAPIClose(Level world, BlockPos blockposition, BlockState iblockdata) {
|
||||
+ this.onClose(world, blockposition, iblockdata);
|
||||
+ public void onAPIClose(Level level, BlockPos blockPos, BlockState blockState) {
|
||||
+ this.onClose(level, blockPos, blockState);
|
||||
+ }
|
||||
+
|
||||
+ public void openerAPICountChanged(Level world, BlockPos blockposition, BlockState iblockdata, int i, int j) {
|
||||
+ this.openerCountChanged(world, blockposition, iblockdata, i, j);
|
||||
+ public void openerAPICountChanged(Level world, BlockPos blockPos, BlockState blockState, int count, int openCount) {
|
||||
+ this.openerCountChanged(world, blockPos, blockState, count, openCount);
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+ // CraftBukkit en
|
||||
+
|
||||
protected abstract boolean isOwnContainer(Player player);
|
||||
|
||||
public void incrementOpeners(Player player, Level world, BlockPos pos, BlockState state) {
|
||||
public void incrementOpeners(Player player, Level level, BlockPos pos, BlockState state) {
|
||||
+ int oldPower = Math.max(0, Math.min(15, this.openCount)); // CraftBukkit - Get power before new viewer is added
|
||||
int i = this.openCount++;
|
||||
|
||||
+
|
||||
+ // CraftBukkit start - Call redstone event
|
||||
+ if (world.getBlockState(pos).is(net.minecraft.world.level.block.Blocks.TRAPPED_CHEST)) {
|
||||
+ if (level.getBlockState(pos).is(net.minecraft.world.level.block.Blocks.TRAPPED_CHEST)) {
|
||||
+ int newPower = Math.max(0, Math.min(15, this.openCount));
|
||||
+
|
||||
+ if (oldPower != newPower) {
|
||||
+ org.bukkit.craftbukkit.event.CraftEventFactory.callRedstoneChange(world, pos, oldPower, newPower);
|
||||
+ org.bukkit.craftbukkit.event.CraftEventFactory.callRedstoneChange(level, pos, oldPower, newPower);
|
||||
+ }
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+ // CraftBukkit en
|
||||
+
|
||||
if (i == 0) {
|
||||
this.onOpen(world, pos, state);
|
||||
world.gameEvent((Entity) player, (Holder) GameEvent.CONTAINER_OPEN, pos);
|
||||
@@ -42,8 +68,20 @@
|
||||
this.onOpen(level, pos, state);
|
||||
level.gameEvent(player, GameEvent.CONTAINER_OPEN, pos);
|
||||
@@ -35,7 +_,20 @@
|
||||
}
|
||||
|
||||
public void decrementOpeners(Player player, Level world, BlockPos pos, BlockState state) {
|
||||
public void decrementOpeners(Player player, Level level, 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
|
||||
+ if (world.getBlockState(pos).is(net.minecraft.world.level.block.Blocks.TRAPPED_CHEST)) {
|
||||
+ if (level.getBlockState(pos).is(net.minecraft.world.level.block.Blocks.TRAPPED_CHEST)) {
|
||||
+ int newPower = Math.max(0, Math.min(15, this.openCount));
|
||||
+
|
||||
+ if (oldPower != newPower) {
|
||||
+ org.bukkit.craftbukkit.event.CraftEventFactory.callRedstoneChange(world, pos, oldPower, newPower);
|
||||
+ org.bukkit.craftbukkit.event.CraftEventFactory.callRedstoneChange(level, pos, oldPower, newPower);
|
||||
+ }
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
if (this.openCount == 0) {
|
||||
this.onClose(world, pos, state);
|
||||
world.gameEvent((Entity) player, (Holder) GameEvent.CONTAINER_CLOSE, pos);
|
||||
@@ -72,6 +110,7 @@
|
||||
this.onClose(level, pos, state);
|
||||
level.gameEvent(player, GameEvent.CONTAINER_CLOSE, pos);
|
||||
@@ -60,6 +_,7 @@
|
||||
}
|
||||
|
||||
int i = list.size();
|
||||
+ if (this.opened) i++; // CraftBukkit - add dummy count from API
|
||||
int j = this.openCount;
|
||||
|
||||
if (j != i) {
|
||||
int size = playersWithContainerOpen.size();
|
||||
+ if (this.opened) size++; // CraftBukkit - add dummy count from API
|
||||
int i = this.openCount;
|
||||
if (i != size) {
|
||||
boolean flag = size != 0;
|
|
@ -0,0 +1,50 @@
|
|||
--- a/net/minecraft/world/level/block/entity/CrafterBlockEntity.java
|
||||
+++ b/net/minecraft/world/level/block/entity/CrafterBlockEntity.java
|
||||
@@ -56,6 +_,47 @@
|
||||
}
|
||||
};
|
||||
|
||||
+ // CraftBukkit start - add fields and methods
|
||||
+ public java.util.List<org.bukkit.entity.HumanEntity> transaction = new java.util.ArrayList<>();
|
||||
+ private int maxStack = MAX_STACK;
|
||||
+
|
||||
+ @Override
|
||||
+ public java.util.List<net.minecraft.world.item.ItemStack> getContents() {
|
||||
+ return this.items;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void onOpen(org.bukkit.craftbukkit.entity.CraftHumanEntity who) {
|
||||
+ this.transaction.add(who);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void onClose(org.bukkit.craftbukkit.entity.CraftHumanEntity who) {
|
||||
+ this.transaction.remove(who);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public java.util.List<org.bukkit.entity.HumanEntity> getViewers() {
|
||||
+ return this.transaction;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public int getMaxStackSize() {
|
||||
+ return this.maxStack;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setMaxStackSize(int size) {
|
||||
+ this.maxStack = size;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public org.bukkit.Location getLocation() {
|
||||
+ if (this.level == null) return null;
|
||||
+ return io.papermc.paper.util.MCUtil.toLocation(this.level, this.worldPosition);
|
||||
+ }
|
||||
+ // CraftBukkit en
|
||||
+
|
||||
public CrafterBlockEntity(BlockPos pos, BlockState state) {
|
||||
super(BlockEntityType.CRAFTER, pos, state);
|
||||
}
|
|
@ -1,48 +1,37 @@
|
|||
--- a/net/minecraft/world/level/block/entity/DecoratedPotBlockEntity.java
|
||||
+++ b/net/minecraft/world/level/block/entity/DecoratedPotBlockEntity.java
|
||||
@@ -20,8 +20,59 @@
|
||||
import net.minecraft.world.level.storage.loot.LootTable;
|
||||
@@ -20,6 +_,48 @@
|
||||
import net.minecraft.world.ticks.ContainerSingleItem;
|
||||
|
||||
+// CraftBukkit start
|
||||
+import java.util.ArrayList;
|
||||
+import java.util.Arrays;
|
||||
+import java.util.List;
|
||||
+import org.bukkit.Location;
|
||||
+import org.bukkit.craftbukkit.entity.CraftHumanEntity;
|
||||
+import org.bukkit.craftbukkit.util.CraftLocation;
|
||||
+import org.bukkit.entity.HumanEntity;
|
||||
+// CraftBukkit end
|
||||
+
|
||||
public class DecoratedPotBlockEntity extends BlockEntity implements RandomizableContainer, ContainerSingleItem.BlockContainerSingleItem {
|
||||
|
||||
+
|
||||
+ // CraftBukkit start - add fields and methods
|
||||
+ public List<HumanEntity> transaction = new ArrayList<>();
|
||||
+ public List<org.bukkit.entity.HumanEntity> transaction = new java.util.ArrayList<>();
|
||||
+ private int maxStack = MAX_STACK;
|
||||
+
|
||||
+ @Override
|
||||
+ public List<ItemStack> getContents() {
|
||||
+ return Arrays.asList(this.item);
|
||||
+ return java.util.List.of(this.item);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void onOpen(CraftHumanEntity who) {
|
||||
+ public void onOpen(org.bukkit.craftbukkit.entity.CraftHumanEntity who) {
|
||||
+ this.transaction.add(who);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void onClose(CraftHumanEntity who) {
|
||||
+ public void onClose(org.bukkit.craftbukkit.entity.CraftHumanEntity who) {
|
||||
+ this.transaction.remove(who);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public List<HumanEntity> getViewers() {
|
||||
+ public java.util.List<HumanEntity> getViewers() {
|
||||
+ return this.transaction;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public int getMaxStackSize() {
|
||||
+ return this.maxStack;
|
||||
+ return this.maxStack;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
|
@ -51,9 +40,9 @@
|
|||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public Location getLocation() {
|
||||
+ public org.bukkit.Location getLocation() {
|
||||
+ if (this.level == null) return null;
|
||||
+ return CraftLocation.toBukkit(this.worldPosition, this.level.getWorld());
|
||||
+ return org.bukkit.craftbukkit.util.CraftLocation.toBukkit(this.worldPosition, this.level.getWorld());
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+
|
|
@ -0,0 +1,39 @@
|
|||
--- a/net/minecraft/world/level/block/entity/DispenserBlockEntity.java
|
||||
+++ b/net/minecraft/world/level/block/entity/DispenserBlockEntity.java
|
||||
@@ -17,6 +_,36 @@
|
||||
public static final int CONTAINER_SIZE = 9;
|
||||
private NonNullList<ItemStack> items = NonNullList.withSize(9, ItemStack.EMPTY);
|
||||
|
||||
+ // CraftBukkit start - add fields and methods
|
||||
+ public java.util.List<org.bukkit.entity.HumanEntity> transaction = new java.util.ArrayList<>();
|
||||
+ private int maxStack = MAX_STACK;
|
||||
+
|
||||
+ public java.util.List<net.minecraft.world.item.ItemStack> getContents() {
|
||||
+ return this.items;
|
||||
+ }
|
||||
+
|
||||
+ public void onOpen(org.bukkit.craftbukkit.entity.CraftHumanEntity who) {
|
||||
+ this.transaction.add(who);
|
||||
+ }
|
||||
+
|
||||
+ public void onClose(org.bukkit.craftbukkit.entity.CraftHumanEntity who) {
|
||||
+ this.transaction.remove(who);
|
||||
+ }
|
||||
+
|
||||
+ public List<HumanEntity> getViewers() {
|
||||
+ return this.transaction;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public int getMaxStackSize() {
|
||||
+ return this.maxStack;
|
||||
+ }
|
||||
+
|
||||
+ public void setMaxStackSize(int size) {
|
||||
+ this.maxStack = size;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
protected DispenserBlockEntity(BlockEntityType<?> type, BlockPos pos, BlockState blockState) {
|
||||
super(type, pos, blockState);
|
||||
}
|
|
@ -20,7 +20,7 @@
|
|||
+ this.transaction.remove(who);
|
||||
+ }
|
||||
+
|
||||
+ public List<org.bukkit.entity.HumanEntity> getViewers() {
|
||||
+ public java.util.List<HumanEntity> getViewers() {
|
||||
+ return this.transaction;
|
||||
+ }
|
||||
+
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
--- a/net/minecraft/world/level/block/entity/JigsawBlockEntity.java
|
||||
+++ b/net/minecraft/world/level/block/entity/JigsawBlockEntity.java
|
||||
@@ -131,7 +131,12 @@
|
||||
public void generate(ServerLevel world, int maxDepth, boolean keepJigsaws) {
|
||||
@@ -131,7 +_,12 @@
|
||||
public void generate(ServerLevel level, int maxDepth, boolean keepJigsaws) {
|
||||
BlockPos blockPos = this.getBlockPos().relative(this.getBlockState().getValue(JigsawBlock.ORIENTATION).front());
|
||||
Registry<StructureTemplatePool> registry = world.registryAccess().lookupOrThrow(Registries.TEMPLATE_POOL);
|
||||
- Holder<StructureTemplatePool> holder = registry.getOrThrow(this.pool);
|
||||
Registry<StructureTemplatePool> registry = level.registryAccess().lookupOrThrow(Registries.TEMPLATE_POOL);
|
||||
- Holder<StructureTemplatePool> orThrow = registry.getOrThrow(this.pool);
|
||||
+ // Paper start - Replace getHolderOrThrow with a null check
|
||||
+ Holder<StructureTemplatePool> holder = registry.get(this.pool).orElse(null);
|
||||
+ if (holder == null) {
|
||||
+ Holder<StructureTemplatePool> orThrow = registry.get(this.pool).orElse(null);
|
||||
+ if (orThrow == null) {
|
||||
+ return;
|
||||
+ }
|
||||
+ // Paper end - Replace getHolderOrThrow with a null check
|
||||
JigsawPlacement.generateJigsaw(world, holder, this.target, maxDepth, blockPos, keepJigsaws);
|
||||
JigsawPlacement.generateJigsaw(level, orThrow, this.target, maxDepth, blockPos, keepJigsaws);
|
||||
}
|
||||
|
|
@ -1,40 +1,27 @@
|
|||
--- a/net/minecraft/world/level/block/entity/JukeboxBlockEntity.java
|
||||
+++ b/net/minecraft/world/level/block/entity/JukeboxBlockEntity.java
|
||||
@@ -19,13 +19,57 @@
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
@@ -20,6 +_,44 @@
|
||||
import net.minecraft.world.ticks.ContainerSingleItem;
|
||||
|
||||
+// CraftBukkit start
|
||||
+import java.util.Collections;
|
||||
+import java.util.List;
|
||||
+import org.bukkit.Location;
|
||||
+import org.bukkit.craftbukkit.entity.CraftHumanEntity;
|
||||
+import org.bukkit.entity.HumanEntity;
|
||||
+// CraftBukkit end
|
||||
+
|
||||
public class JukeboxBlockEntity extends BlockEntity implements ContainerSingleItem.BlockContainerSingleItem {
|
||||
|
||||
public static final String SONG_ITEM_TAG_ID = "RecordItem";
|
||||
public static final String TICKS_SINCE_SONG_STARTED_TAG_ID = "ticks_since_song_started";
|
||||
private ItemStack item;
|
||||
private final JukeboxSongPlayer jukeboxSongPlayer;
|
||||
+
|
||||
+ // CraftBukkit start - add fields and methods
|
||||
+ public List<HumanEntity> transaction = new java.util.ArrayList<HumanEntity>();
|
||||
+ public java.util.List<org.bukkit.entity.HumanEntity> transaction = new java.util.ArrayList<>();
|
||||
+ private int maxStack = MAX_STACK;
|
||||
+ public boolean opened;
|
||||
|
||||
+
|
||||
+ @Override
|
||||
+ public List<ItemStack> getContents() {
|
||||
+ public java.util.List<net.minecraft.world.item.ItemStack> getContents() {
|
||||
+ return Collections.singletonList(this.item);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void onOpen(CraftHumanEntity who) {
|
||||
+ public void onOpen(org.bukkit.craftbukkit.entity.CraftHumanEntity who) {
|
||||
+ this.transaction.add(who);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void onClose(CraftHumanEntity who) {
|
||||
+ public void onClose(org.bukkit.craftbukkit.entity.CraftHumanEntity who) {
|
||||
+ this.transaction.remove(who);
|
||||
+ }
|
||||
+
|
||||
|
@ -49,16 +36,16 @@
|
|||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public Location getLocation() {
|
||||
+ public org.bukkit.Location getLocation() {
|
||||
+ if (this.level == null) return null;
|
||||
+ return new org.bukkit.Location(this.level.getWorld(), this.worldPosition.getX(), this.worldPosition.getY(), this.worldPosition.getZ());
|
||||
+ return io.papermc.paper.util.MCUtil.toLocation(this.level, this.worldPosition);
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
public JukeboxBlockEntity(BlockPos pos, BlockState state) {
|
||||
super(BlockEntityType.JUKEBOX, pos, state);
|
||||
this.item = ItemStack.EMPTY;
|
||||
@@ -137,7 +181,7 @@
|
||||
public static final String SONG_ITEM_TAG_ID = "RecordItem";
|
||||
public static final String TICKS_SINCE_SONG_STARTED_TAG_ID = "ticks_since_song_started";
|
||||
private ItemStack item = ItemStack.EMPTY;
|
||||
@@ -126,7 +_,7 @@
|
||||
|
||||
@Override
|
||||
public int getMaxStackSize() {
|
||||
|
@ -67,20 +54,14 @@
|
|||
}
|
||||
|
||||
@Override
|
||||
@@ -156,12 +200,17 @@
|
||||
}
|
||||
|
||||
@@ -147,9 +_,14 @@
|
||||
@VisibleForTesting
|
||||
- public void setSongItemWithoutPlaying(ItemStack stack) {
|
||||
- this.item = stack;
|
||||
- JukeboxSong.fromStack(this.level.registryAccess(), stack).ifPresent((holder) -> {
|
||||
- this.jukeboxSongPlayer.setSongWithoutPlaying(holder, 0L);
|
||||
+ public void setSongItemWithoutPlaying(ItemStack itemstack, long ticksSinceSongStarted) { // CraftBukkit - add argument
|
||||
+ this.item = itemstack;
|
||||
public void setSongItemWithoutPlaying(ItemStack stack) {
|
||||
this.item = stack;
|
||||
- JukeboxSong.fromStack(this.level.registryAccess(), stack)
|
||||
+ this.jukeboxSongPlayer.song = null; // CraftBukkit - reset
|
||||
+ JukeboxSong.fromStack(this.level != null ? this.level.registryAccess() : org.bukkit.craftbukkit.CraftRegistry.getMinecraftRegistry(), itemstack).ifPresent((holder) -> { // Paper - fallback to other RegistyrAccess if no level
|
||||
+ this.jukeboxSongPlayer.setSongWithoutPlaying(holder, ticksSinceSongStarted); // CraftBukkit - add argument
|
||||
});
|
||||
+ JukeboxSong.fromStack(this.level != null ? this.level.registryAccess() : org.bukkit.craftbukkit.CraftRegistry.getMinecraftRegistry(), stack) // Paper - fallback to other RegistyrAccess if no level
|
||||
.ifPresent(holder -> this.jukeboxSongPlayer.setSongWithoutPlaying((Holder<JukeboxSong>)holder, 0L));
|
||||
- this.level.updateNeighborsAt(this.getBlockPos(), this.getBlockState().getBlock());
|
||||
+ // CraftBukkit start - add null check for level
|
||||
+ if (this.level != null) {
|
|
@ -0,0 +1,139 @@
|
|||
--- a/net/minecraft/world/level/block/entity/LecternBlockEntity.java
|
||||
+++ b/net/minecraft/world/level/block/entity/LecternBlockEntity.java
|
||||
@@ -33,6 +_,51 @@
|
||||
public static final int SLOT_BOOK = 0;
|
||||
public static final int NUM_SLOTS = 1;
|
||||
public final Container bookAccess = new Container() {
|
||||
+ // CraftBukkit start - add fields and methods
|
||||
+ public java.util.List<org.bukkit.entity.HumanEntity> transaction = new java.util.ArrayList<>();
|
||||
+ private int maxStack = 1;
|
||||
+
|
||||
+ @Override
|
||||
+ public java.util.List<net.minecraft.world.item.ItemStack> getContents() {
|
||||
+ return java.util.List.of(LecternBlockEntity.this.book);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void onOpen(org.bukkit.craftbukkit.entity.CraftHumanEntity who) {
|
||||
+ this.transaction.add(who);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void onClose(org.bukkit.craftbukkit.entity.CraftHumanEntity who) {
|
||||
+ this.transaction.remove(who);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public java.util.List<org.bukkit.entity.HumanEntity> getViewers() {
|
||||
+ return this.transaction;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setMaxStackSize(int i) {
|
||||
+ this.maxStack = i;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public org.bukkit.Location getLocation() {
|
||||
+ if (LecternBlockEntity.this.level == null) return null;
|
||||
+ return io.papermc.paper.util.MCUtil.toLocation(LecternBlockEntity.this.level, LecternBlockEntity.this.worldPosition);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public org.bukkit.inventory.InventoryHolder getOwner() {
|
||||
+ return LecternBlockEntity.this.getOwner();
|
||||
+ }
|
||||
+
|
||||
+ public LecternBlockEntity getLectern() {
|
||||
+ return LecternBlockEntity.this;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
@Override
|
||||
public int getContainerSize() {
|
||||
return 1;
|
||||
@@ -76,11 +_,19 @@
|
||||
|
||||
@Override
|
||||
public void setItem(int slot, ItemStack stack) {
|
||||
+ // CraftBukkit start
|
||||
+ if (slot == 0) {
|
||||
+ LecternBlockEntity.this.setBook(stack);
|
||||
+ if (LecternBlockEntity.this.getLevel() != null) {
|
||||
+ LecternBlock.resetBookState(null, LecternBlockEntity.this.getLevel(), LecternBlockEntity.this.getBlockPos(), LecternBlockEntity.this.getBlockState(), LecternBlockEntity.this.hasBook());
|
||||
+ }
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxStackSize() {
|
||||
- return 1;
|
||||
+ return maxStack;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -158,7 +_,7 @@
|
||||
if (i != this.page) {
|
||||
this.page = i;
|
||||
this.setChanged();
|
||||
- LecternBlock.signalPageChange(this.getLevel(), this.getBlockPos(), this.getBlockState());
|
||||
+ if (this.level != null) LecternBlock.signalPageChange(this.getLevel(), this.getBlockPos(), this.getBlockState()); // CraftBukkit
|
||||
}
|
||||
}
|
||||
|
||||
@@ -179,6 +_,36 @@
|
||||
return stack;
|
||||
}
|
||||
|
||||
+ // CraftBukkit start
|
||||
+ private final CommandSource commandSource = new CommandSource() {
|
||||
+
|
||||
+ @Override
|
||||
+ public void sendSystemMessage(Component message) {
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public org.bukkit.command.CommandSender getBukkitSender(CommandSourceStack commandSourceStack) {
|
||||
+ return commandSourceStack.getEntity() != null
|
||||
+ ? commandSourceStack.getEntity().getBukkitEntity()
|
||||
+ : new org.bukkit.craftbukkit.command.CraftBlockCommandSender(commandSourceStack, LecternBlockEntity.this);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean acceptsSuccess() {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean acceptsFailure() {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean shouldInformAdmins() {
|
||||
+ return false;
|
||||
+ }
|
||||
+ };
|
||||
+ // CraftBukkit end
|
||||
private CommandSourceStack createCommandSourceStack(@Nullable Player player, ServerLevel level) {
|
||||
String string;
|
||||
Component component;
|
||||
@@ -191,7 +_,7 @@
|
||||
}
|
||||
|
||||
Vec3 vec3 = Vec3.atCenterOf(this.worldPosition);
|
||||
- return new CommandSourceStack(CommandSource.NULL, vec3, Vec2.ZERO, level, 2, string, component, level.getServer(), player);
|
||||
+ return new CommandSourceStack(this.commandSource, vec3, Vec2.ZERO, level, 2, string, component, level.getServer(), player); // CraftBukkit - commandSource
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -223,7 +_,7 @@
|
||||
|
||||
@Override
|
||||
public AbstractContainerMenu createMenu(int containerId, Inventory playerInventory, Player player) {
|
||||
- return new LecternMenu(containerId, this.bookAccess, this.dataAccess);
|
||||
+ return new LecternMenu(containerId, this.bookAccess, this.dataAccess, playerInventory); // CraftBukkit
|
||||
}
|
||||
|
||||
@Override
|
|
@ -1,8 +1,8 @@
|
|||
--- a/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java
|
||||
+++ b/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java
|
||||
@@ -115,4 +115,13 @@
|
||||
nbt.remove("LootTable");
|
||||
nbt.remove("LootTableSeed");
|
||||
@@ -115,4 +_,13 @@
|
||||
tag.remove("LootTable");
|
||||
tag.remove("LootTableSeed");
|
||||
}
|
||||
+
|
||||
+ // Paper start - LootTable API
|
|
@ -1,20 +1,20 @@
|
|||
--- a/net/minecraft/world/level/block/entity/SculkSensorBlockEntity.java
|
||||
+++ b/net/minecraft/world/level/block/entity/SculkSensorBlockEntity.java
|
||||
@@ -26,6 +26,7 @@
|
||||
@@ -26,6 +_,7 @@
|
||||
private final VibrationSystem.Listener vibrationListener;
|
||||
private final VibrationSystem.User vibrationUser = this.createVibrationUser();
|
||||
public int lastVibrationFrequency;
|
||||
+ @Nullable public Integer rangeOverride = null; // Paper - Configurable sculk sensor listener range
|
||||
|
||||
protected SculkSensorBlockEntity(BlockEntityType<?> type, BlockPos pos, BlockState state) {
|
||||
super(type, pos, state);
|
||||
@@ -52,8 +53,16 @@
|
||||
protected SculkSensorBlockEntity(BlockEntityType<?> type, BlockPos pos, BlockState blockState) {
|
||||
super(type, pos, blockState);
|
||||
@@ -52,8 +_,16 @@
|
||||
.resultOrPartial(string -> LOGGER.error("Failed to parse vibration listener for Sculk Sensor: '{}'", string))
|
||||
.ifPresent(listener -> this.vibrationData = listener);
|
||||
.ifPresent(data -> this.vibrationData = data);
|
||||
}
|
||||
+ // Paper start - Configurable sculk sensor listener range
|
||||
+ if (nbt.contains(PAPER_LISTENER_RANGE_NBT_KEY)) {
|
||||
+ this.rangeOverride = nbt.getInt(PAPER_LISTENER_RANGE_NBT_KEY);
|
||||
+ if (tag.contains(PAPER_LISTENER_RANGE_NBT_KEY)) {
|
||||
+ this.rangeOverride = tag.getInt(PAPER_LISTENER_RANGE_NBT_KEY);
|
||||
+ } else {
|
||||
+ this.rangeOverride = null;
|
||||
+ }
|
||||
|
@ -23,23 +23,24 @@
|
|||
|
||||
+ protected static final String PAPER_LISTENER_RANGE_NBT_KEY = "Paper.ListenerRange"; // Paper - Configurable sculk sensor listener range
|
||||
@Override
|
||||
protected void saveAdditional(CompoundTag nbt, HolderLookup.Provider registries) {
|
||||
super.saveAdditional(nbt, registries);
|
||||
@@ -63,7 +72,13 @@
|
||||
protected void saveAdditional(CompoundTag tag, HolderLookup.Provider registries) {
|
||||
super.saveAdditional(tag, registries);
|
||||
@@ -63,7 +_,13 @@
|
||||
.encodeStart(registryOps, this.vibrationData)
|
||||
.resultOrPartial(string -> LOGGER.error("Failed to encode vibration listener for Sculk Sensor: '{}'", string))
|
||||
.ifPresent(listenerNbt -> nbt.put("listener", listenerNbt));
|
||||
+ this.saveRangeOverride(nbt); // Paper - Configurable sculk sensor listener range
|
||||
}
|
||||
.ifPresent(tag1 -> tag.put("listener", tag1));
|
||||
- }
|
||||
+ this.saveRangeOverride(tag); // Paper - Configurable sculk sensor listener range
|
||||
+ }
|
||||
+ // Paper start - Configurable sculk sensor listener range
|
||||
+ protected void saveRangeOverride(CompoundTag nbt) {
|
||||
+ if (this.rangeOverride != null && this.rangeOverride != VibrationUser.LISTENER_RANGE) nbt.putInt(PAPER_LISTENER_RANGE_NBT_KEY, this.rangeOverride); // only save if it's different from the default
|
||||
+ protected void saveRangeOverride(CompoundTag tag) {
|
||||
+ if (this.rangeOverride != null && this.rangeOverride != VibrationUser.LISTENER_RANGE) tag.putInt(PAPER_LISTENER_RANGE_NBT_KEY, this.rangeOverride); // only save if it's different from the default
|
||||
+ }
|
||||
+ // Paper end - Configurable sculk sensor listener range
|
||||
|
||||
@Override
|
||||
public VibrationSystem.Data getVibrationData() {
|
||||
@@ -100,6 +115,7 @@
|
||||
@@ -100,6 +_,7 @@
|
||||
|
||||
@Override
|
||||
public int getListenerRadius() {
|
|
@ -1,6 +1,6 @@
|
|||
--- a/net/minecraft/world/level/block/entity/SculkShriekerBlockEntity.java
|
||||
+++ b/net/minecraft/world/level/block/entity/SculkShriekerBlockEntity.java
|
||||
@@ -105,6 +105,13 @@
|
||||
@@ -105,6 +_,13 @@
|
||||
|
||||
@Nullable
|
||||
public static ServerPlayer tryGetPlayer(@Nullable Entity entity) {
|
||||
|
@ -14,12 +14,12 @@
|
|||
if (entity instanceof ServerPlayer) {
|
||||
return (ServerPlayer)entity;
|
||||
} else {
|
||||
@@ -190,7 +197,7 @@
|
||||
private boolean trySummonWarden(ServerLevel world) {
|
||||
@@ -190,7 +_,7 @@
|
||||
private boolean trySummonWarden(ServerLevel level) {
|
||||
return this.warningLevel >= 4
|
||||
&& SpawnUtil.trySpawnMob(
|
||||
- EntityType.WARDEN, EntitySpawnReason.TRIGGERED, world, this.getBlockPos(), 20, 5, 6, SpawnUtil.Strategy.ON_TOP_OF_COLLIDER, false
|
||||
+ EntityType.WARDEN, EntitySpawnReason.TRIGGERED, world, this.getBlockPos(), 20, 5, 6, SpawnUtil.Strategy.ON_TOP_OF_COLLIDER, false, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NATURAL, null // Paper - Entity#getEntitySpawnReason
|
||||
- EntityType.WARDEN, EntitySpawnReason.TRIGGERED, level, this.getBlockPos(), 20, 5, 6, SpawnUtil.Strategy.ON_TOP_OF_COLLIDER, false
|
||||
+ EntityType.WARDEN, EntitySpawnReason.TRIGGERED, level, this.getBlockPos(), 20, 5, 6, SpawnUtil.Strategy.ON_TOP_OF_COLLIDER, false, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NATURAL, null // Paper - Entity#getEntitySpawnReason
|
||||
)
|
||||
.isPresent();
|
||||
}
|
|
@ -1,22 +1,11 @@
|
|||
--- a/net/minecraft/world/level/block/entity/ShulkerBoxBlockEntity.java
|
||||
+++ b/net/minecraft/world/level/block/entity/ShulkerBoxBlockEntity.java
|
||||
@@ -33,6 +33,10 @@
|
||||
import net.minecraft.world.level.material.PushReaction;
|
||||
import net.minecraft.world.phys.AABB;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
+// CraftBukkit start
|
||||
+import org.bukkit.craftbukkit.entity.CraftHumanEntity;
|
||||
+import org.bukkit.entity.HumanEntity;
|
||||
+// CraftBukkit end
|
||||
|
||||
public class ShulkerBoxBlockEntity extends RandomizableContainerBlockEntity implements WorldlyContainer {
|
||||
|
||||
@@ -52,6 +56,37 @@
|
||||
@@ -49,6 +_,37 @@
|
||||
@Nullable
|
||||
private final DyeColor color;
|
||||
|
||||
+ // CraftBukkit start - add fields and methods
|
||||
+ public List<HumanEntity> transaction = new java.util.ArrayList<HumanEntity>();
|
||||
+ public List<org.bukkit.entity.HumanEntity> transaction = new java.util.ArrayList<>();
|
||||
+ private int maxStack = MAX_STACK;
|
||||
+ public boolean opened;
|
||||
+
|
||||
|
@ -24,15 +13,15 @@
|
|||
+ return this.itemStacks;
|
||||
+ }
|
||||
+
|
||||
+ public void onOpen(CraftHumanEntity who) {
|
||||
+ public void onOpen(org.bukkit.craftbukkit.entity.CraftHumanEntity who) {
|
||||
+ this.transaction.add(who);
|
||||
+ }
|
||||
+
|
||||
+ public void onClose(CraftHumanEntity who) {
|
||||
+ public void onClose(org.bukkit.craftbukkit.entity.CraftHumanEntity who) {
|
||||
+ this.transaction.remove(who);
|
||||
+ }
|
||||
+
|
||||
+ public List<HumanEntity> getViewers() {
|
||||
+ public List<org.bukkit.entity.HumanEntity> getViewers() {
|
||||
+ return this.transaction;
|
||||
+ }
|
||||
+
|
||||
|
@ -46,22 +35,22 @@
|
|||
+ }
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
public ShulkerBoxBlockEntity(@Nullable DyeColor color, BlockPos pos, BlockState state) {
|
||||
super(BlockEntityType.SHULKER_BOX, pos, state);
|
||||
this.itemStacks = NonNullList.withSize(27, ItemStack.EMPTY);
|
||||
@@ -184,6 +219,7 @@
|
||||
public ShulkerBoxBlockEntity(@Nullable DyeColor color, BlockPos pos, BlockState blockState) {
|
||||
super(BlockEntityType.SHULKER_BOX, pos, blockState);
|
||||
this.color = color;
|
||||
@@ -167,6 +_,7 @@
|
||||
}
|
||||
|
||||
++this.openCount;
|
||||
+ if (this.opened) return; // CraftBukkit - only animate if the ShulkerBox hasn't been forced open already by an API call.
|
||||
this.openCount++;
|
||||
+ if (this.opened) return; // CraftBukkit - only animate if the ShulkerBox hasn't been forced open already by an API call
|
||||
this.level.blockEvent(this.worldPosition, this.getBlockState().getBlock(), 1, this.openCount);
|
||||
if (this.openCount == 1) {
|
||||
this.level.gameEvent((Entity) player, (Holder) GameEvent.CONTAINER_OPEN, this.worldPosition);
|
||||
@@ -197,6 +233,7 @@
|
||||
this.level.gameEvent(player, GameEvent.CONTAINER_OPEN, this.worldPosition);
|
||||
@@ -180,6 +_,7 @@
|
||||
public void stopOpen(Player player) {
|
||||
if (!this.remove && !player.isSpectator()) {
|
||||
--this.openCount;
|
||||
this.openCount--;
|
||||
+ if (this.opened) return; // CraftBukkit - only animate if the ShulkerBox hasn't been forced open already by an API call.
|
||||
this.level.blockEvent(this.worldPosition, this.getBlockState().getBlock(), 1, this.openCount);
|
||||
if (this.openCount <= 0) {
|
||||
this.level.gameEvent((Entity) player, (Holder) GameEvent.CONTAINER_CLOSE, this.worldPosition);
|
||||
this.level.gameEvent(player, GameEvent.CONTAINER_CLOSE, this.worldPosition);
|
|
@ -0,0 +1,183 @@
|
|||
--- a/net/minecraft/world/level/block/entity/SignBlockEntity.java
|
||||
+++ b/net/minecraft/world/level/block/entity/SignBlockEntity.java
|
||||
@@ -54,11 +_,16 @@
|
||||
return new SignText();
|
||||
}
|
||||
|
||||
- public boolean isFacingFrontText(Player player) {
|
||||
+ public boolean isFacingFrontText(net.minecraft.world.entity.player.Player player) {
|
||||
+ // Paper start - More Sign Block API
|
||||
+ return this.isFacingFrontText(player.getX(), player.getZ());
|
||||
+ }
|
||||
+ public boolean isFacingFrontText(double x, double z) {
|
||||
+ // Paper end - More Sign Block API
|
||||
if (this.getBlockState().getBlock() instanceof SignBlock signBlock) {
|
||||
Vec3 signHitboxCenterPosition = signBlock.getSignHitboxCenterPosition(this.getBlockState());
|
||||
- double d = player.getX() - (this.getBlockPos().getX() + signHitboxCenterPosition.x);
|
||||
- double d1 = player.getZ() - (this.getBlockPos().getZ() + signHitboxCenterPosition.z);
|
||||
+ double d = x - ((double) this.getBlockPos().getX() + signHitboxCenterPosition.x); // Paper - More Sign Block API
|
||||
+ double d1 = z - ((double) this.getBlockPos().getZ() + signHitboxCenterPosition.z); // Paper - More Sign Block AP
|
||||
float yRotationDegrees = signBlock.getYRotationDegrees(this.getBlockState());
|
||||
float f = (float)(Mth.atan2(d1, d) * 180.0F / (float)Math.PI) - 90.0F;
|
||||
return Mth.degreesDifferenceAbs(yRotationDegrees, f) <= 90.0F;
|
||||
@@ -143,11 +_,13 @@
|
||||
|
||||
public void updateSignText(Player player, boolean isFrontText, List<FilteredText> filteredText) {
|
||||
if (!this.isWaxed() && player.getUUID().equals(this.getPlayerWhoMayEdit()) && this.level != null) {
|
||||
- this.updateText(signText -> this.setMessages(player, filteredText, signText), isFrontText);
|
||||
+ this.updateText(signText -> this.setMessages(player, filteredText, signText, isFrontText), isFrontText); // CraftBukkit
|
||||
this.setAllowedPlayerEditor(null);
|
||||
this.level.sendBlockUpdated(this.getBlockPos(), this.getBlockState(), this.getBlockState(), 3);
|
||||
} else {
|
||||
LOGGER.warn("Player {} just tried to change non-editable sign", player.getName().getString());
|
||||
+ if (player.distanceToSqr(this.getBlockPos().getX(), this.getBlockPos().getY(), this.getBlockPos().getZ()) < 32 * 32) // Paper - Dont send far away sign update
|
||||
+ ((net.minecraft.server.level.ServerPlayer) player).connection.send(this.getUpdatePacket()); // CraftBukkit
|
||||
}
|
||||
}
|
||||
|
||||
@@ -156,18 +_,40 @@
|
||||
return this.setText(updater.apply(text), isFrontText);
|
||||
}
|
||||
|
||||
- private SignText setMessages(Player player, List<FilteredText> filteredText, SignText text) {
|
||||
+ private SignText setMessages(Player player, List<FilteredText> filteredText, SignText text, boolean front) { // CraftBukkit
|
||||
+ SignText originalText = text; // CraftBukkit
|
||||
for (int i = 0; i < filteredText.size(); i++) {
|
||||
FilteredText filteredText1 = filteredText.get(i);
|
||||
Style style = text.getMessage(i, player.isTextFilteringEnabled()).getStyle();
|
||||
if (player.isTextFilteringEnabled()) {
|
||||
- text = text.setMessage(i, Component.literal(filteredText1.filteredOrEmpty()).setStyle(style));
|
||||
+ text = text.setMessage(i, Component.literal(net.minecraft.util.StringUtil.filterText(filteredText1.filteredOrEmpty())).setStyle(style)); // Paper - filter sign text to chat only
|
||||
} else {
|
||||
text = text.setMessage(
|
||||
- i, Component.literal(filteredText1.raw()).setStyle(style), Component.literal(filteredText1.filteredOrEmpty()).setStyle(style)
|
||||
+ i, Component.literal(filteredText1.raw()).setStyle(style), Component.literal(net.minecraft.util.StringUtil.filterText(filteredText1.filteredOrEmpty())).setStyle(style) // Paper - filter sign text to chat only
|
||||
);
|
||||
}
|
||||
}
|
||||
+
|
||||
+ // CraftBukkit start
|
||||
+ org.bukkit.entity.Player apiPlayer = ((net.minecraft.server.level.ServerPlayer) player).getBukkitEntity();
|
||||
+ List<net.kyori.adventure.text.Component> lines = new java.util.ArrayList<>(); // Paper - adventure
|
||||
+
|
||||
+ for (int i = 0; i < filteredText.size(); ++i) {
|
||||
+ lines.add(io.papermc.paper.adventure.PaperAdventure.asAdventure(text.getMessage(i, player.isTextFilteringEnabled()))); // Paper - Adventure
|
||||
+ }
|
||||
+
|
||||
+ org.bukkit.event.block.SignChangeEvent event = new org.bukkit.event.block.SignChangeEvent(org.bukkit.craftbukkit.block.CraftBlock.at(this.level, this.worldPosition), apiPlayer, new java.util.ArrayList<>(lines), (front) ? org.bukkit.block.sign.Side.FRONT : org.bukkit.block.sign.Side.BACK); // Paper - Adventure
|
||||
+ if (!event.callEvent()) {
|
||||
+ return originalText;
|
||||
+ }
|
||||
+
|
||||
+ Component[] components = org.bukkit.craftbukkit.block.CraftSign.sanitizeLines(event.lines()); // Paper - Adventure
|
||||
+ for (int i = 0; i < components.length; i++) {
|
||||
+ if (!java.util.Objects.equals(lines.get(i), event.line(i))) { // Paper - Adventure
|
||||
+ text = text.setMessage(i, components[i]);
|
||||
+ }
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
|
||||
return text;
|
||||
}
|
||||
@@ -207,7 +_,23 @@
|
||||
Style style = component.getStyle();
|
||||
ClickEvent clickEvent = style.getClickEvent();
|
||||
if (clickEvent != null && clickEvent.getAction() == ClickEvent.Action.RUN_COMMAND) {
|
||||
- player.getServer().getCommands().performPrefixedCommand(createCommandSourceStack(player, level, pos), clickEvent.getValue());
|
||||
+ // Paper start - Fix commands from signs not firing command events
|
||||
+ String command = clickEvent.getValue().startsWith("/") ? clickEvent.getValue() : "/" + clickEvent.getValue();
|
||||
+ if (org.spigotmc.SpigotConfig.logCommands) {
|
||||
+ LOGGER.info("{} issued server command: {}", player.getScoreboardName(), command);
|
||||
+ }
|
||||
+ io.papermc.paper.event.player.PlayerSignCommandPreprocessEvent event = new io.papermc.paper.event.player.PlayerSignCommandPreprocessEvent(
|
||||
+ (org.bukkit.entity.Player) player.getBukkitEntity(),
|
||||
+ command,
|
||||
+ new org.bukkit.craftbukkit.util.LazyPlayerSet(player.getServer()),
|
||||
+ (org.bukkit.block.Sign) org.bukkit.craftbukkit.block.CraftBlock.at(this.level, this.worldPosition).getState(),
|
||||
+ frontText ? org.bukkit.block.sign.Side.FRONT : org.bukkit.block.sign.Side.BACK
|
||||
+ );
|
||||
+ if (!event.callEvent()) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ player.getServer().getCommands().performPrefixedCommand(this.createCommandSourceStack(((org.bukkit.craftbukkit.entity.CraftPlayer) event.getPlayer()).getHandle(), level, pos), event.getMessage());
|
||||
+ // Paper end - Fix commands from signs not firing command events
|
||||
flag = true;
|
||||
}
|
||||
}
|
||||
@@ -215,10 +_,55 @@
|
||||
return flag;
|
||||
}
|
||||
|
||||
- private static CommandSourceStack createCommandSourceStack(@Nullable Player player, Level level, BlockPos pos) {
|
||||
+ // CraftBukkit start
|
||||
+ private final CommandSource commandSource = new CommandSource() {
|
||||
+
|
||||
+ @Override
|
||||
+ public void sendSystemMessage(Component message) {}
|
||||
+
|
||||
+ @Override
|
||||
+ public org.bukkit.command.CommandSender getBukkitSender(CommandSourceStack commandSourceStack) {
|
||||
+ return commandSourceStack.getEntity() != null ? commandSourceStack.getEntity().getBukkitEntity() : new org.bukkit.craftbukkit.command.CraftBlockCommandSender(commandSourceStack, SignBlockEntity.this);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean acceptsSuccess() {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean acceptsFailure() {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean shouldInformAdmins() {
|
||||
+ return false;
|
||||
+ }
|
||||
+ };
|
||||
+
|
||||
+ private CommandSourceStack createCommandSourceStack(@Nullable Player player, Level world, BlockPos pos) {
|
||||
+ // CraftBukkit end
|
||||
String string = player == null ? "Sign" : player.getName().getString();
|
||||
Component component = (Component)(player == null ? Component.literal("Sign") : player.getDisplayName());
|
||||
- return new CommandSourceStack(CommandSource.NULL, Vec3.atCenterOf(pos), Vec2.ZERO, (ServerLevel)level, 2, string, component, level.getServer(), player);
|
||||
+
|
||||
+ // Paper start - Fix commands from signs not firing command events
|
||||
+ CommandSource commandSource = world.paperConfig().misc.showSignClickCommandFailureMsgsToPlayer ? new io.papermc.paper.commands.DelegatingCommandSource(this.commandSource) {
|
||||
+ @Override
|
||||
+ public void sendSystemMessage(Component message) {
|
||||
+ if (player instanceof final net.minecraft.server.level.ServerPlayer serverPlayer) {
|
||||
+ serverPlayer.sendSystemMessage(message);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean acceptsFailure() {
|
||||
+ return true;
|
||||
+ }
|
||||
+ } : this.commandSource;
|
||||
+ // Paper end - Fix commands from signs not firing command events
|
||||
+ // CraftBukkit - this
|
||||
+ return new CommandSourceStack(commandSource, Vec3.atCenterOf(pos), Vec2.ZERO, (ServerLevel) world, 2, string, (Component) component, world.getServer(), player); // Paper - Fix commands from signs not firing command events
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -237,12 +_,17 @@
|
||||
|
||||
@Nullable
|
||||
public UUID getPlayerWhoMayEdit() {
|
||||
+ // CraftBukkit start - unnecessary sign ticking removed, so do this lazily
|
||||
+ if (this.level != null && this.playerWhoMayEdit != null) {
|
||||
+ this.clearInvalidPlayerWhoMayEdit(this, this.level, this.playerWhoMayEdit);
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
return this.playerWhoMayEdit;
|
||||
}
|
||||
|
||||
private void markUpdated() {
|
||||
this.setChanged();
|
||||
- this.level.sendBlockUpdated(this.getBlockPos(), this.getBlockState(), this.getBlockState(), 3);
|
||||
+ if (this.level != null) this.level.sendBlockUpdated(this.getBlockPos(), this.getBlockState(), this.getBlockState(), 3); // CraftBukkit - skip notify if world is null (SPIGOT-5122)
|
||||
}
|
||||
|
||||
public boolean isWaxed() {
|
|
@ -1,6 +1,6 @@
|
|||
--- a/net/minecraft/world/level/block/entity/SkullBlockEntity.java
|
||||
+++ b/net/minecraft/world/level/block/entity/SkullBlockEntity.java
|
||||
@@ -41,7 +41,7 @@
|
||||
@@ -41,7 +_,7 @@
|
||||
@Nullable
|
||||
private static LoadingCache<String, CompletableFuture<Optional<GameProfile>>> profileCacheByName;
|
||||
@Nullable
|
||||
|
@ -9,45 +9,45 @@
|
|||
public static final Executor CHECKED_MAIN_THREAD_EXECUTOR = runnable -> {
|
||||
Executor executor = mainThreadExecutor;
|
||||
if (executor != null) {
|
||||
@@ -76,9 +76,9 @@
|
||||
@@ -76,9 +_,9 @@
|
||||
profileCacheById = CacheBuilder.newBuilder()
|
||||
.expireAfterAccess(Duration.ofMinutes(10L))
|
||||
.maximumSize(256L)
|
||||
- .build(new CacheLoader<UUID, CompletableFuture<Optional<GameProfile>>>() {
|
||||
+ .build(new CacheLoader<>() { // Paper - player profile events
|
||||
@Override
|
||||
- public CompletableFuture<Optional<GameProfile>> load(UUID uUID) {
|
||||
+ public CompletableFuture<Optional<GameProfile>> load(com.mojang.datafixers.util.Pair<java.util.UUID, @org.jetbrains.annotations.Nullable GameProfile> uUID) { // Paper - player profile events
|
||||
return SkullBlockEntity.fetchProfileById(uUID, apiServices, booleanSupplier);
|
||||
- public CompletableFuture<Optional<GameProfile>> load(UUID id) {
|
||||
+ public CompletableFuture<Optional<GameProfile>> load(com.mojang.datafixers.util.Pair<java.util.UUID, @org.jetbrains.annotations.Nullable GameProfile> id) { // Paper - player profile events
|
||||
return SkullBlockEntity.fetchProfileById(id, services, booleanSupplier);
|
||||
}
|
||||
});
|
||||
@@ -89,23 +89,29 @@
|
||||
@@ -89,23 +_,29 @@
|
||||
.getAsync(name)
|
||||
.thenCompose(
|
||||
optional -> {
|
||||
- LoadingCache<UUID, CompletableFuture<Optional<GameProfile>>> loadingCache = profileCacheById;
|
||||
+ LoadingCache<com.mojang.datafixers.util.Pair<java.util.UUID, @org.jetbrains.annotations.Nullable GameProfile>, CompletableFuture<Optional<GameProfile>>> loadingCache = profileCacheById; // Paper - player profile events
|
||||
return loadingCache != null && !optional.isEmpty()
|
||||
- ? loadingCache.getUnchecked(optional.get().getId()).thenApply(optional2 -> optional2.or(() -> optional))
|
||||
+ ? loadingCache.getUnchecked(new com.mojang.datafixers.util.Pair<>(optional.get().getId(), optional.get())).thenApply(optional2 -> optional2.or(() -> optional)) // Paper - player profile events
|
||||
- ? loadingCache.getUnchecked(optional.get().getId()).thenApply(optional1 -> optional1.or(() -> optional))
|
||||
+ ? loadingCache.getUnchecked(new com.mojang.datafixers.util.Pair<>(optional.get().getId(), optional.get())).thenApply(optional1 -> optional1.or(() -> optional)) // Paper - player profile events
|
||||
: CompletableFuture.completedFuture(Optional.empty());
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
- static CompletableFuture<Optional<GameProfile>> fetchProfileById(UUID uuid, Services apiServices, BooleanSupplier booleanSupplier) {
|
||||
+ static CompletableFuture<Optional<GameProfile>> fetchProfileById(com.mojang.datafixers.util.Pair<java.util.UUID, @org.jetbrains.annotations.Nullable GameProfile> pair, Services apiServices, BooleanSupplier booleanSupplier) { // Paper
|
||||
- static CompletableFuture<Optional<GameProfile>> fetchProfileById(UUID id, Services services, BooleanSupplier cacheUninitialized) {
|
||||
+ static CompletableFuture<Optional<GameProfile>> fetchProfileById(com.mojang.datafixers.util.Pair<java.util.UUID, @org.jetbrains.annotations.Nullable GameProfile> id, Services services, BooleanSupplier cacheUninitialized) { // Pape
|
||||
return CompletableFuture.supplyAsync(() -> {
|
||||
if (booleanSupplier.getAsBoolean()) {
|
||||
if (cacheUninitialized.getAsBoolean()) {
|
||||
return Optional.empty();
|
||||
} else {
|
||||
- ProfileResult profileResult = apiServices.sessionService().fetchProfile(uuid, true);
|
||||
- ProfileResult profileResult = services.sessionService().fetchProfile(id, true);
|
||||
+ // Paper start - fill player profile events
|
||||
+ if (apiServices.sessionService() instanceof com.destroystokyo.paper.profile.PaperMinecraftSessionService paperService) {
|
||||
+ final GameProfile profile = pair.getSecond() != null ? pair.getSecond() : new com.mojang.authlib.GameProfile(pair.getFirst(), "");
|
||||
+ if (services.sessionService() instanceof com.destroystokyo.paper.profile.PaperMinecraftSessionService paperService) {
|
||||
+ final GameProfile profile = id.getSecond() != null ? id.getSecond() : new com.mojang.authlib.GameProfile(id.getFirst(), "");
|
||||
+ return Optional.ofNullable(paperService.fetchProfile(profile, true)).map(ProfileResult::profile);
|
||||
+ }
|
||||
+ ProfileResult profileResult = apiServices.sessionService().fetchProfile(pair.getFirst(), true);
|
||||
+ ProfileResult profileResult = services.sessionService().fetchProfile(id.getFirst(), true);
|
||||
+ // Paper end - fill player profile events
|
||||
return Optional.ofNullable(profileResult).map(ProfileResult::profile);
|
||||
}
|
||||
|
@ -56,13 +56,13 @@
|
|||
}
|
||||
|
||||
public static void clear() {
|
||||
@@ -210,9 +216,11 @@
|
||||
@@ -210,9 +_,11 @@
|
||||
: CompletableFuture.completedFuture(Optional.empty());
|
||||
}
|
||||
|
||||
- public static CompletableFuture<Optional<GameProfile>> fetchGameProfile(UUID uuid) {
|
||||
- public static CompletableFuture<Optional<GameProfile>> fetchGameProfile(UUID profileUuid) {
|
||||
- LoadingCache<UUID, CompletableFuture<Optional<GameProfile>>> loadingCache = profileCacheById;
|
||||
- return loadingCache != null ? loadingCache.getUnchecked(uuid) : CompletableFuture.completedFuture(Optional.empty());
|
||||
- return loadingCache != null ? loadingCache.getUnchecked(profileUuid) : CompletableFuture.completedFuture(Optional.empty());
|
||||
+ // Paper start - player profile events
|
||||
+ public static CompletableFuture<Optional<GameProfile>> fetchGameProfile(UUID uuid, @Nullable String name) {
|
||||
+ LoadingCache<com.mojang.datafixers.util.Pair<java.util.UUID, @org.jetbrains.annotations.Nullable GameProfile>, CompletableFuture<Optional<GameProfile>>> loadingCache = profileCacheById;
|
|
@ -1,356 +0,0 @@
|
|||
--- a/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java
|
||||
+++ b/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java
|
||||
@@ -22,7 +22,6 @@
|
||||
import net.minecraft.world.ContainerHelper;
|
||||
import net.minecraft.world.WorldlyContainer;
|
||||
import net.minecraft.world.entity.ExperienceOrb;
|
||||
-import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.entity.player.StackedItemContents;
|
||||
import net.minecraft.world.inventory.ContainerData;
|
||||
import net.minecraft.world.inventory.RecipeCraftingHolder;
|
||||
@@ -41,6 +40,20 @@
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
+// CraftBukkit start
|
||||
+import org.bukkit.craftbukkit.block.CraftBlock;
|
||||
+import org.bukkit.craftbukkit.entity.CraftHumanEntity;
|
||||
+import org.bukkit.craftbukkit.inventory.CraftItemStack;
|
||||
+import org.bukkit.craftbukkit.inventory.CraftItemType;
|
||||
+import org.bukkit.entity.HumanEntity;
|
||||
+import org.bukkit.entity.Player;
|
||||
+import org.bukkit.event.block.BlockExpEvent;
|
||||
+import org.bukkit.event.inventory.FurnaceBurnEvent;
|
||||
+import org.bukkit.event.inventory.FurnaceExtractEvent;
|
||||
+import org.bukkit.event.inventory.FurnaceSmeltEvent;
|
||||
+import org.bukkit.event.inventory.FurnaceStartSmeltEvent;
|
||||
+import org.bukkit.inventory.CookingRecipe;
|
||||
+// CraftBukkit end
|
||||
|
||||
public abstract class AbstractFurnaceBlockEntity extends BaseContainerBlockEntity implements WorldlyContainer, RecipeCraftingHolder, StackedContentsCompatible {
|
||||
|
||||
@@ -65,6 +78,8 @@
|
||||
protected final ContainerData dataAccess;
|
||||
public final Reference2IntOpenHashMap<ResourceKey<Recipe<?>>> recipesUsed;
|
||||
private final RecipeManager.CachedCheck<SingleRecipeInput, ? extends AbstractCookingRecipe> quickCheck;
|
||||
+ public final RecipeType<? extends AbstractCookingRecipe> recipeType; // Paper - cook speed multiplier API
|
||||
+ public double cookSpeedMultiplier = 1.0; // Paper - cook speed multiplier API
|
||||
|
||||
protected AbstractFurnaceBlockEntity(BlockEntityType<?> blockEntityType, BlockPos pos, BlockState state, RecipeType<? extends AbstractCookingRecipe> recipeType) {
|
||||
super(blockEntityType, pos, state);
|
||||
@@ -110,9 +125,40 @@
|
||||
}
|
||||
};
|
||||
this.recipesUsed = new Reference2IntOpenHashMap();
|
||||
- this.quickCheck = RecipeManager.createCheck(recipeType);
|
||||
+ this.quickCheck = RecipeManager.createCheck((RecipeType<AbstractCookingRecipe>) recipeType); // CraftBukkit - decompile error // Eclipse fail
|
||||
+ this.recipeType = recipeType; // Paper - cook speed multiplier API
|
||||
}
|
||||
|
||||
+ // CraftBukkit start - add fields and methods
|
||||
+ private int maxStack = MAX_STACK;
|
||||
+ public List<HumanEntity> transaction = new java.util.ArrayList<HumanEntity>();
|
||||
+
|
||||
+ public List<ItemStack> getContents() {
|
||||
+ return this.items;
|
||||
+ }
|
||||
+
|
||||
+ public void onOpen(CraftHumanEntity who) {
|
||||
+ this.transaction.add(who);
|
||||
+ }
|
||||
+
|
||||
+ public void onClose(CraftHumanEntity who) {
|
||||
+ this.transaction.remove(who);
|
||||
+ }
|
||||
+
|
||||
+ public List<HumanEntity> getViewers() {
|
||||
+ return this.transaction;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public int getMaxStackSize() {
|
||||
+ return this.maxStack;
|
||||
+ }
|
||||
+
|
||||
+ public void setMaxStackSize(int size) {
|
||||
+ this.maxStack = size;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
private boolean isLit() {
|
||||
return this.litTimeRemaining > 0;
|
||||
}
|
||||
@@ -132,9 +178,18 @@
|
||||
while (iterator.hasNext()) {
|
||||
String s = (String) iterator.next();
|
||||
|
||||
- this.recipesUsed.put(ResourceKey.create(Registries.RECIPE, ResourceLocation.parse(s)), nbttagcompound1.getInt(s));
|
||||
+ // Paper start - Validate ResourceLocation
|
||||
+ final ResourceLocation resourceLocation = ResourceLocation.tryParse(s);
|
||||
+ if (resourceLocation != null) {
|
||||
+ this.recipesUsed.put(ResourceKey.create(Registries.RECIPE, resourceLocation), nbttagcompound1.getInt(s));
|
||||
+ }
|
||||
}
|
||||
|
||||
+ // Paper start - cook speed multiplier API
|
||||
+ if (nbt.contains("Paper.CookSpeedMultiplier")) {
|
||||
+ this.cookSpeedMultiplier = nbt.getDouble("Paper.CookSpeedMultiplier");
|
||||
+ }
|
||||
+ // Paper end - cook speed multiplier API
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -144,6 +199,7 @@
|
||||
nbt.putShort("cooking_total_time", (short) this.cookingTotalTime);
|
||||
nbt.putShort("lit_time_remaining", (short) this.litTimeRemaining);
|
||||
nbt.putShort("lit_total_time", (short) this.litTotalTime);
|
||||
+ nbt.putDouble("Paper.CookSpeedMultiplier", this.cookSpeedMultiplier); // Paper - cook speed multiplier API
|
||||
ContainerHelper.saveAllItems(nbt, this.items, registries);
|
||||
CompoundTag nbttagcompound1 = new CompoundTag();
|
||||
|
||||
@@ -175,7 +231,7 @@
|
||||
RecipeHolder recipeholder;
|
||||
|
||||
if (flag2) {
|
||||
- recipeholder = (RecipeHolder) blockEntity.quickCheck.getRecipeFor(singlerecipeinput, world).orElse((Object) null);
|
||||
+ recipeholder = (RecipeHolder) blockEntity.quickCheck.getRecipeFor(singlerecipeinput, world).orElse(null); // CraftBukkit - decompile error
|
||||
} else {
|
||||
recipeholder = null;
|
||||
}
|
||||
@@ -183,11 +239,22 @@
|
||||
int i = blockEntity.getMaxStackSize();
|
||||
|
||||
if (!blockEntity.isLit() && AbstractFurnaceBlockEntity.canBurn(world.registryAccess(), recipeholder, singlerecipeinput, blockEntity.items, i)) {
|
||||
- blockEntity.litTimeRemaining = blockEntity.getBurnDuration(world.fuelValues(), itemstack);
|
||||
+ // CraftBukkit start
|
||||
+ CraftItemStack fuel = CraftItemStack.asCraftMirror(itemstack);
|
||||
+
|
||||
+ FurnaceBurnEvent furnaceBurnEvent = new FurnaceBurnEvent(CraftBlock.at(world, pos), fuel, blockEntity.getBurnDuration(world.fuelValues(), itemstack));
|
||||
+ world.getCraftServer().getPluginManager().callEvent(furnaceBurnEvent);
|
||||
+
|
||||
+ if (furnaceBurnEvent.isCancelled()) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ blockEntity.litTimeRemaining = furnaceBurnEvent.getBurnTime();
|
||||
blockEntity.litTotalTime = blockEntity.litTimeRemaining;
|
||||
- if (blockEntity.isLit()) {
|
||||
+ if (blockEntity.isLit() && furnaceBurnEvent.isBurning()) {
|
||||
+ // CraftBukkit end
|
||||
flag1 = true;
|
||||
- if (flag3) {
|
||||
+ if (flag3 && furnaceBurnEvent.willConsumeFuel()) { // Paper - add consumeFuel to FurnaceBurnEvent
|
||||
Item item = itemstack.getItem();
|
||||
|
||||
itemstack.shrink(1);
|
||||
@@ -199,11 +266,23 @@
|
||||
}
|
||||
|
||||
if (blockEntity.isLit() && AbstractFurnaceBlockEntity.canBurn(world.registryAccess(), recipeholder, singlerecipeinput, blockEntity.items, i)) {
|
||||
+ // CraftBukkit start
|
||||
+ if (recipeholder != null && blockEntity.cookingTimer == 0) {
|
||||
+ CraftItemStack source = CraftItemStack.asCraftMirror(blockEntity.items.get(0));
|
||||
+ CookingRecipe<?> recipe = (CookingRecipe<?>) recipeholder.toBukkitRecipe();
|
||||
+
|
||||
+ FurnaceStartSmeltEvent event = new FurnaceStartSmeltEvent(CraftBlock.at(world, pos), source, recipe, AbstractFurnaceBlockEntity.getTotalCookTime(world, blockEntity, blockEntity.recipeType, blockEntity.cookSpeedMultiplier)); // Paper - cook speed multiplier API
|
||||
+ world.getCraftServer().getPluginManager().callEvent(event);
|
||||
+
|
||||
+ blockEntity.cookingTotalTime = event.getTotalCookTime();
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
++blockEntity.cookingTimer;
|
||||
- if (blockEntity.cookingTimer == blockEntity.cookingTotalTime) {
|
||||
+ if (blockEntity.cookingTimer >= blockEntity.cookingTotalTime) { // Paper - cook speed multiplier API
|
||||
blockEntity.cookingTimer = 0;
|
||||
- blockEntity.cookingTotalTime = AbstractFurnaceBlockEntity.getTotalCookTime(world, blockEntity);
|
||||
- if (AbstractFurnaceBlockEntity.burn(world.registryAccess(), recipeholder, singlerecipeinput, blockEntity.items, i)) {
|
||||
+ blockEntity.cookingTotalTime = AbstractFurnaceBlockEntity.getTotalCookTime(world, blockEntity, blockEntity.recipeType, blockEntity.cookSpeedMultiplier); // Paper - cook speed multiplier API
|
||||
+ if (AbstractFurnaceBlockEntity.burn(blockEntity.level, blockEntity.worldPosition, world.registryAccess(), recipeholder, singlerecipeinput, blockEntity.items, i)) { // CraftBukkit
|
||||
blockEntity.setRecipeUsed(recipeholder);
|
||||
}
|
||||
|
||||
@@ -242,20 +321,47 @@
|
||||
}
|
||||
}
|
||||
|
||||
- private static boolean burn(RegistryAccess dynamicRegistryManager, @Nullable RecipeHolder<? extends AbstractCookingRecipe> recipe, SingleRecipeInput input, NonNullList<ItemStack> inventory, int maxCount) {
|
||||
- if (recipe != null && AbstractFurnaceBlockEntity.canBurn(dynamicRegistryManager, recipe, input, inventory, maxCount)) {
|
||||
- ItemStack itemstack = (ItemStack) inventory.get(0);
|
||||
- ItemStack itemstack1 = ((AbstractCookingRecipe) recipe.value()).assemble(input, dynamicRegistryManager);
|
||||
- ItemStack itemstack2 = (ItemStack) inventory.get(2);
|
||||
+ private static boolean burn(Level world, BlockPos blockposition, RegistryAccess iregistrycustom, @Nullable RecipeHolder<? extends AbstractCookingRecipe> recipeholder, SingleRecipeInput singlerecipeinput, NonNullList<ItemStack> nonnulllist, int i) { // CraftBukkit
|
||||
+ if (recipeholder != null && AbstractFurnaceBlockEntity.canBurn(iregistrycustom, recipeholder, singlerecipeinput, nonnulllist, i)) {
|
||||
+ ItemStack itemstack = (ItemStack) nonnulllist.get(0);
|
||||
+ ItemStack itemstack1 = ((AbstractCookingRecipe) recipeholder.value()).assemble(singlerecipeinput, iregistrycustom);
|
||||
+ ItemStack itemstack2 = (ItemStack) nonnulllist.get(2);
|
||||
|
||||
+ // CraftBukkit start - fire FurnaceSmeltEvent
|
||||
+ CraftItemStack source = CraftItemStack.asCraftMirror(itemstack);
|
||||
+ org.bukkit.inventory.ItemStack result = CraftItemStack.asBukkitCopy(itemstack1);
|
||||
+
|
||||
+ FurnaceSmeltEvent furnaceSmeltEvent = new FurnaceSmeltEvent(CraftBlock.at(world, blockposition), source, result, (org.bukkit.inventory.CookingRecipe<?>) recipeholder.toBukkitRecipe()); // Paper - Add recipe to cook events
|
||||
+ world.getCraftServer().getPluginManager().callEvent(furnaceSmeltEvent);
|
||||
+
|
||||
+ if (furnaceSmeltEvent.isCancelled()) {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ result = furnaceSmeltEvent.getResult();
|
||||
+ itemstack1 = CraftItemStack.asNMSCopy(result);
|
||||
+
|
||||
+ if (!itemstack1.isEmpty()) {
|
||||
+ if (itemstack2.isEmpty()) {
|
||||
+ nonnulllist.set(2, itemstack1.copy());
|
||||
+ } else if (CraftItemStack.asCraftMirror(itemstack2).isSimilar(result)) {
|
||||
+ itemstack2.grow(itemstack1.getCount());
|
||||
+ } else {
|
||||
+ return false;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
if (itemstack2.isEmpty()) {
|
||||
- inventory.set(2, itemstack1.copy());
|
||||
+ nonnulllist.set(2, itemstack1.copy());
|
||||
} else if (ItemStack.isSameItemSameComponents(itemstack2, itemstack1)) {
|
||||
itemstack2.grow(1);
|
||||
}
|
||||
+ */
|
||||
+ // CraftBukkit end
|
||||
|
||||
- if (itemstack.is(Blocks.WET_SPONGE.asItem()) && !((ItemStack) inventory.get(1)).isEmpty() && ((ItemStack) inventory.get(1)).is(Items.BUCKET)) {
|
||||
- inventory.set(1, new ItemStack(Items.WATER_BUCKET));
|
||||
+ if (itemstack.is(Blocks.WET_SPONGE.asItem()) && !((ItemStack) nonnulllist.get(1)).isEmpty() && ((ItemStack) nonnulllist.get(1)).is(Items.BUCKET)) {
|
||||
+ nonnulllist.set(1, new ItemStack(Items.WATER_BUCKET));
|
||||
}
|
||||
|
||||
itemstack.shrink(1);
|
||||
@@ -269,12 +375,14 @@
|
||||
return fuelRegistry.burnDuration(stack);
|
||||
}
|
||||
|
||||
- public static int getTotalCookTime(ServerLevel world, AbstractFurnaceBlockEntity furnace) {
|
||||
+ public static int getTotalCookTime(@Nullable ServerLevel world, AbstractFurnaceBlockEntity furnace, RecipeType<? extends AbstractCookingRecipe> recipeType, double cookSpeedMultiplier) { // Paper - cook speed multiplier API
|
||||
SingleRecipeInput singlerecipeinput = new SingleRecipeInput(furnace.getItem(0));
|
||||
|
||||
- return (Integer) furnace.quickCheck.getRecipeFor(singlerecipeinput, world).map((recipeholder) -> {
|
||||
- return ((AbstractCookingRecipe) recipeholder.value()).cookingTime();
|
||||
- }).orElse(200);
|
||||
+ // Paper start - cook speed multiplier API
|
||||
+ /* Scale the recipe's cooking time to the current cookSpeedMultiplier */
|
||||
+ int cookTime = world != null ? furnace.quickCheck.getRecipeFor(singlerecipeinput, world).map(holder -> holder.value().cookingTime()).orElse(200) : (net.minecraft.server.MinecraftServer.getServer().getRecipeManager().getRecipeFor(recipeType, singlerecipeinput, world /* passing a null level here is safe. world is only used for map extending recipes which won't happen here */).map(holder -> holder.value().cookingTime()).orElse(200));
|
||||
+ return (int) Math.ceil (cookTime / cookSpeedMultiplier);
|
||||
+ // Paper end - cook speed multiplier API
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -320,12 +428,11 @@
|
||||
if (world instanceof ServerLevel) {
|
||||
ServerLevel worldserver = (ServerLevel) world;
|
||||
|
||||
- this.cookingTotalTime = AbstractFurnaceBlockEntity.getTotalCookTime(worldserver, this);
|
||||
+ this.cookingTotalTime = AbstractFurnaceBlockEntity.getTotalCookTime(worldserver, this, this.recipeType, this.cookSpeedMultiplier); // Paper - cook speed multiplier API
|
||||
this.cookingTimer = 0;
|
||||
this.setChanged();
|
||||
}
|
||||
}
|
||||
-
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -358,19 +465,19 @@
|
||||
}
|
||||
|
||||
@Override
|
||||
- public void awardUsedRecipes(Player player, List<ItemStack> ingredients) {}
|
||||
+ public void awardUsedRecipes(net.minecraft.world.entity.player.Player player, List<ItemStack> ingredients) {}
|
||||
|
||||
- public void awardUsedRecipesAndPopExperience(ServerPlayer player) {
|
||||
- List<RecipeHolder<?>> list = this.getRecipesToAwardAndPopExperience(player.serverLevel(), player.position());
|
||||
+ public void awardUsedRecipesAndPopExperience(ServerPlayer entityplayer, ItemStack itemstack, int amount) { // CraftBukkit
|
||||
+ List<RecipeHolder<?>> list = this.getRecipesToAwardAndPopExperience(entityplayer.serverLevel(), entityplayer.position(), this.worldPosition, entityplayer, itemstack, amount); // CraftBukkit
|
||||
|
||||
- player.awardRecipes(list);
|
||||
+ entityplayer.awardRecipes(list);
|
||||
Iterator iterator = list.iterator();
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
RecipeHolder<?> recipeholder = (RecipeHolder) iterator.next();
|
||||
|
||||
if (recipeholder != null) {
|
||||
- player.triggerRecipeCrafted(recipeholder, this.items);
|
||||
+ entityplayer.triggerRecipeCrafted(recipeholder, this.items);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -378,41 +485,56 @@
|
||||
}
|
||||
|
||||
public List<RecipeHolder<?>> getRecipesToAwardAndPopExperience(ServerLevel world, Vec3 pos) {
|
||||
+ // CraftBukkit start
|
||||
+ return this.getRecipesToAwardAndPopExperience(world, pos, this.worldPosition, null, null, 0);
|
||||
+ }
|
||||
+
|
||||
+ public List<RecipeHolder<?>> getRecipesToAwardAndPopExperience(ServerLevel worldserver, Vec3 vec3d, BlockPos blockposition, ServerPlayer entityplayer, ItemStack itemstack, int amount) {
|
||||
+ // CraftBukkit end
|
||||
List<RecipeHolder<?>> list = Lists.newArrayList();
|
||||
ObjectIterator objectiterator = this.recipesUsed.reference2IntEntrySet().iterator();
|
||||
|
||||
while (objectiterator.hasNext()) {
|
||||
Entry<ResourceKey<Recipe<?>>> entry = (Entry) objectiterator.next();
|
||||
|
||||
- world.recipeAccess().byKey((ResourceKey) entry.getKey()).ifPresent((recipeholder) -> {
|
||||
+ worldserver.recipeAccess().byKey(entry.getKey()).ifPresent((recipeholder) -> { // CraftBukkit - decompile error
|
||||
+ if (!(recipeholder.value() instanceof AbstractCookingRecipe)) return; // Paper - don't process non-cooking recipes
|
||||
list.add(recipeholder);
|
||||
- AbstractFurnaceBlockEntity.createExperience(world, pos, entry.getIntValue(), ((AbstractCookingRecipe) recipeholder.value()).experience());
|
||||
+ AbstractFurnaceBlockEntity.createExperience(worldserver, vec3d, entry.getIntValue(), ((AbstractCookingRecipe) recipeholder.value()).experience(), blockposition, entityplayer, itemstack, amount); // CraftBukkit
|
||||
});
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
- private static void createExperience(ServerLevel world, Vec3 pos, int multiplier, float experience) {
|
||||
- int j = Mth.floor((float) multiplier * experience);
|
||||
- float f1 = Mth.frac((float) multiplier * experience);
|
||||
+ private static void createExperience(ServerLevel worldserver, Vec3 vec3d, int i, float f, BlockPos blockposition, net.minecraft.world.entity.player.Player entityhuman, ItemStack itemstack, int amount) { // CraftBukkit
|
||||
+ int j = Mth.floor((float) i * f);
|
||||
+ float f1 = Mth.frac((float) i * f);
|
||||
|
||||
if (f1 != 0.0F && Math.random() < (double) f1) {
|
||||
++j;
|
||||
}
|
||||
|
||||
- ExperienceOrb.award(world, pos, j);
|
||||
+ // CraftBukkit start - fire FurnaceExtractEvent / BlockExpEvent
|
||||
+ BlockExpEvent event;
|
||||
+ if (amount != 0) {
|
||||
+ event = new FurnaceExtractEvent((Player) entityhuman.getBukkitEntity(), CraftBlock.at(worldserver, blockposition), CraftItemType.minecraftToBukkit(itemstack.getItem()), amount, j);
|
||||
+ } else {
|
||||
+ event = new BlockExpEvent(CraftBlock.at(worldserver, blockposition), j);
|
||||
+ }
|
||||
+ worldserver.getCraftServer().getPluginManager().callEvent(event);
|
||||
+ j = event.getExpToDrop();
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
+ ExperienceOrb.award(worldserver, vec3d, j, org.bukkit.entity.ExperienceOrb.SpawnReason.FURNACE, entityhuman); // Paper
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fillStackedContents(StackedItemContents finder) {
|
||||
- Iterator iterator = this.items.iterator();
|
||||
+ // Paper start - don't account fuel stack (fixes MC-243057)
|
||||
+ finder.accountStack(this.items.get(SLOT_INPUT));
|
||||
+ finder.accountStack(this.items.get(SLOT_RESULT));
|
||||
+ // Paper end
|
||||
|
||||
- while (iterator.hasNext()) {
|
||||
- ItemStack itemstack = (ItemStack) iterator.next();
|
||||
-
|
||||
- finder.accountStack(itemstack);
|
||||
- }
|
||||
-
|
||||
}
|
||||
}
|
|
@ -1,81 +0,0 @@
|
|||
--- a/net/minecraft/world/level/block/entity/BannerBlockEntity.java
|
||||
+++ b/net/minecraft/world/level/block/entity/BannerBlockEntity.java
|
||||
@@ -19,13 +19,17 @@
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
+// CraftBukkit start
|
||||
+import java.util.List;
|
||||
+// CraftBukkit end
|
||||
+
|
||||
public class BannerBlockEntity extends BlockEntity implements Nameable {
|
||||
|
||||
private static final Logger LOGGER = LogUtils.getLogger();
|
||||
public static final int MAX_PATTERNS = 6;
|
||||
private static final String TAG_PATTERNS = "patterns";
|
||||
@Nullable
|
||||
- private Component name;
|
||||
+ public Component name; // Paper - public
|
||||
public DyeColor baseColor;
|
||||
private BannerPatternLayers patterns;
|
||||
|
||||
@@ -53,7 +57,7 @@
|
||||
@Override
|
||||
protected void saveAdditional(CompoundTag nbt, HolderLookup.Provider registries) {
|
||||
super.saveAdditional(nbt, registries);
|
||||
- if (!this.patterns.equals(BannerPatternLayers.EMPTY)) {
|
||||
+ if (!this.patterns.equals(BannerPatternLayers.EMPTY) || serialisingForNetwork.get()) { // Paper - always send patterns to client
|
||||
nbt.put("patterns", (Tag) BannerPatternLayers.CODEC.encodeStart(registries.createSerializationContext(NbtOps.INSTANCE), this.patterns).getOrThrow());
|
||||
}
|
||||
|
||||
@@ -74,7 +78,7 @@
|
||||
BannerPatternLayers.CODEC.parse(registries.createSerializationContext(NbtOps.INSTANCE), nbt.get("patterns")).resultOrPartial((s) -> {
|
||||
BannerBlockEntity.LOGGER.error("Failed to parse banner patterns: '{}'", s);
|
||||
}).ifPresent((bannerpatternlayers) -> {
|
||||
- this.patterns = bannerpatternlayers;
|
||||
+ this.setPatterns(bannerpatternlayers); // CraftBukkit - apply limits
|
||||
});
|
||||
}
|
||||
|
||||
@@ -85,9 +89,18 @@
|
||||
return ClientboundBlockEntityDataPacket.create(this);
|
||||
}
|
||||
|
||||
+ // Paper start - always send patterns to client
|
||||
+ ThreadLocal<Boolean> serialisingForNetwork = ThreadLocal.withInitial(() -> Boolean.FALSE);
|
||||
@Override
|
||||
public CompoundTag getUpdateTag(HolderLookup.Provider registries) {
|
||||
+ final Boolean wasSerialisingForNetwork = serialisingForNetwork.get();
|
||||
+ try {
|
||||
+ serialisingForNetwork.set(Boolean.TRUE);
|
||||
return this.saveWithoutMetadata(registries);
|
||||
+ } finally {
|
||||
+ serialisingForNetwork.set(wasSerialisingForNetwork);
|
||||
+ }
|
||||
+ // Paper end - always send patterns to client
|
||||
}
|
||||
|
||||
public BannerPatternLayers getPatterns() {
|
||||
@@ -108,7 +121,7 @@
|
||||
@Override
|
||||
protected void applyImplicitComponents(BlockEntity.DataComponentInput components) {
|
||||
super.applyImplicitComponents(components);
|
||||
- this.patterns = (BannerPatternLayers) components.getOrDefault(DataComponents.BANNER_PATTERNS, BannerPatternLayers.EMPTY);
|
||||
+ this.setPatterns((BannerPatternLayers) components.getOrDefault(DataComponents.BANNER_PATTERNS, BannerPatternLayers.EMPTY)); // CraftBukkit - apply limits
|
||||
this.name = (Component) components.get(DataComponents.CUSTOM_NAME);
|
||||
}
|
||||
|
||||
@@ -124,4 +137,13 @@
|
||||
nbt.remove("patterns");
|
||||
nbt.remove("CustomName");
|
||||
}
|
||||
+
|
||||
+ // CraftBukkit start
|
||||
+ public void setPatterns(BannerPatternLayers bannerpatternlayers) {
|
||||
+ if (bannerpatternlayers.layers().size() > 20) {
|
||||
+ bannerpatternlayers = new BannerPatternLayers(List.copyOf(bannerpatternlayers.layers().subList(0, 20)));
|
||||
+ }
|
||||
+ this.patterns = bannerpatternlayers;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
}
|
|
@ -1,259 +0,0 @@
|
|||
--- a/net/minecraft/world/level/block/entity/BeaconBlockEntity.java
|
||||
+++ b/net/minecraft/world/level/block/entity/BeaconBlockEntity.java
|
||||
@@ -1,5 +1,6 @@
|
||||
package net.minecraft.world.level.block.entity;
|
||||
|
||||
+import com.destroystokyo.paper.event.block.BeaconEffectEvent;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Lists;
|
||||
import java.util.Collection;
|
||||
@@ -45,6 +46,11 @@
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.levelgen.Heightmap;
|
||||
import net.minecraft.world.phys.AABB;
|
||||
+// CraftBukkit start
|
||||
+import org.bukkit.craftbukkit.event.CraftEventFactory;
|
||||
+import org.bukkit.craftbukkit.potion.CraftPotionUtil;
|
||||
+import org.bukkit.potion.PotionEffect;
|
||||
+// CraftBukkit end
|
||||
|
||||
public class BeaconBlockEntity extends BlockEntity implements MenuProvider, Nameable {
|
||||
|
||||
@@ -71,7 +77,36 @@
|
||||
public Component name;
|
||||
public LockCode lockKey;
|
||||
private final ContainerData dataAccess;
|
||||
+ // CraftBukkit start - add fields and methods
|
||||
+ public PotionEffect getPrimaryEffect() {
|
||||
+ return (this.primaryPower != null) ? CraftPotionUtil.toBukkit(new MobEffectInstance(this.primaryPower, BeaconBlockEntity.getLevel(this.levels), BeaconBlockEntity.getAmplification(this.levels, this.primaryPower, this.secondaryPower), true, true)) : null;
|
||||
+ }
|
||||
|
||||
+ public PotionEffect getSecondaryEffect() {
|
||||
+ return (BeaconBlockEntity.hasSecondaryEffect(this.levels, this.primaryPower, this.secondaryPower)) ? CraftPotionUtil.toBukkit(new MobEffectInstance(this.secondaryPower, BeaconBlockEntity.getLevel(this.levels), BeaconBlockEntity.getAmplification(this.levels, this.primaryPower, this.secondaryPower), true, true)) : null;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+ // Paper start - Custom beacon ranges
|
||||
+ private final String PAPER_RANGE_TAG = "Paper.Range";
|
||||
+ private double effectRange = -1;
|
||||
+
|
||||
+ public double getEffectRange() {
|
||||
+ if (this.effectRange < 0) {
|
||||
+ return this.levels * 10 + 10;
|
||||
+ } else {
|
||||
+ return effectRange;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ public void setEffectRange(double range) {
|
||||
+ this.effectRange = range;
|
||||
+ }
|
||||
+
|
||||
+ public void resetEffectRange() {
|
||||
+ this.effectRange = -1;
|
||||
+ }
|
||||
+ // Paper end - Custom beacon ranges
|
||||
+
|
||||
@Nullable
|
||||
static Holder<MobEffect> filterEffect(@Nullable Holder<MobEffect> effect) {
|
||||
return BeaconBlockEntity.VALID_EFFECTS.contains(effect) ? effect : null;
|
||||
@@ -186,10 +221,19 @@
|
||||
}
|
||||
|
||||
if (blockEntity.levels > 0 && !blockEntity.beamSections.isEmpty()) {
|
||||
- BeaconBlockEntity.applyEffects(world, pos, blockEntity.levels, blockEntity.primaryPower, blockEntity.secondaryPower);
|
||||
+ BeaconBlockEntity.applyEffects(world, pos, blockEntity.levels, blockEntity.primaryPower, blockEntity.secondaryPower, blockEntity); // Paper - Custom beacon ranges
|
||||
BeaconBlockEntity.playSound(world, pos, SoundEvents.BEACON_AMBIENT);
|
||||
}
|
||||
}
|
||||
+ // Paper start - beacon activation/deactivation events
|
||||
+ if (i1 <= 0 && blockEntity.levels > 0) {
|
||||
+ org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(world, pos);
|
||||
+ new io.papermc.paper.event.block.BeaconActivatedEvent(block).callEvent();
|
||||
+ } else if (i1 > 0 && blockEntity.levels <= 0) {
|
||||
+ org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(world, pos);
|
||||
+ new io.papermc.paper.event.block.BeaconDeactivatedEvent(block).callEvent();
|
||||
+ }
|
||||
+ // Paper end - beacon activation/deactivation events
|
||||
|
||||
if (blockEntity.lastCheckY >= l) {
|
||||
blockEntity.lastCheckY = world.getMinY() - 1;
|
||||
@@ -247,43 +291,123 @@
|
||||
|
||||
@Override
|
||||
public void setRemoved() {
|
||||
+ // Paper start - beacon activation/deactivation events
|
||||
+ org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(level, worldPosition);
|
||||
+ new io.papermc.paper.event.block.BeaconDeactivatedEvent(block).callEvent();
|
||||
+ // Paper end - beacon activation/deactivation events
|
||||
+ // Paper start - fix MC-153086
|
||||
+ if (this.levels > 0 && !this.beamSections.isEmpty()) {
|
||||
BeaconBlockEntity.playSound(this.level, this.worldPosition, SoundEvents.BEACON_DEACTIVATE);
|
||||
+ }
|
||||
+ // Paper end
|
||||
super.setRemoved();
|
||||
}
|
||||
|
||||
- private static void applyEffects(Level world, BlockPos pos, int beaconLevel, @Nullable Holder<MobEffect> primaryEffect, @Nullable Holder<MobEffect> secondaryEffect) {
|
||||
- if (!world.isClientSide && primaryEffect != null) {
|
||||
- double d0 = (double) (beaconLevel * 10 + 10);
|
||||
+ // CraftBukkit start - split into components
|
||||
+ private static byte getAmplification(int i, @Nullable Holder<MobEffect> holder, @Nullable Holder<MobEffect> holder1) {
|
||||
+ {
|
||||
byte b0 = 0;
|
||||
|
||||
- if (beaconLevel >= 4 && Objects.equals(primaryEffect, secondaryEffect)) {
|
||||
+ if (i >= 4 && Objects.equals(holder, holder1)) {
|
||||
b0 = 1;
|
||||
}
|
||||
|
||||
- int j = (9 + beaconLevel * 2) * 20;
|
||||
- AABB axisalignedbb = (new AABB(pos)).inflate(d0).expandTowards(0.0D, (double) world.getHeight(), 0.0D);
|
||||
- List<Player> list = world.getEntitiesOfClass(Player.class, axisalignedbb);
|
||||
+ return b0;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ private static int getLevel(int i) {
|
||||
+ {
|
||||
+ int j = (9 + i * 2) * 20;
|
||||
+ return j;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ public static List getHumansInRange(Level world, BlockPos blockposition, int i) {
|
||||
+ // Paper start - Custom beacon ranges
|
||||
+ return BeaconBlockEntity.getHumansInRange(world, blockposition, i, null);
|
||||
+ }
|
||||
+ public static List getHumansInRange(Level world, BlockPos blockposition, int i, @Nullable BeaconBlockEntity blockEntity) {
|
||||
+ // Paper end - Custom beacon ranges
|
||||
+ {
|
||||
+ double d0 = blockEntity != null ? blockEntity.getEffectRange() : (i * 10 + 10); // Paper - Custom beacon ranges
|
||||
+
|
||||
+ AABB axisalignedbb = (new AABB(blockposition)).inflate(d0).expandTowards(0.0D, (double) world.getHeight(), 0.0D);
|
||||
+ // Paper start - Perf: optimize player lookup for beacons
|
||||
+ List<Player> list;
|
||||
+ if (d0 <= 128.0) {
|
||||
+ list = world.getEntitiesOfClass(Player.class, axisalignedbb);
|
||||
+ } else {
|
||||
+ list = new java.util.ArrayList<>();
|
||||
+ for (Player player : world.players()) {
|
||||
+ if (player.isSpectator()) {
|
||||
+ continue;
|
||||
+ }
|
||||
+ if (player.getBoundingBox().intersects(axisalignedbb)) {
|
||||
+ list.add(player);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end - Perf: optimize player lookup for beacons
|
||||
+
|
||||
+ return list;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ private static void applyEffect(List list, @Nullable Holder<MobEffect> holder, int j, int b0, boolean isPrimary, BlockPos worldPosition) { // Paper - BeaconEffectEvent
|
||||
+ if (!list.isEmpty()) { // Paper - BeaconEffectEvent
|
||||
Iterator iterator = list.iterator();
|
||||
|
||||
Player entityhuman;
|
||||
+ // Paper start - BeaconEffectEvent
|
||||
+ org.bukkit.block.Block block = org.bukkit.craftbukkit.block.CraftBlock.at(((Player) list.get(0)).level(), worldPosition);
|
||||
+ PotionEffect effect = CraftPotionUtil.toBukkit(new MobEffectInstance(holder, j, b0, true, true));
|
||||
+ // Paper end - BeaconEffectEvent
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
- entityhuman = (Player) iterator.next();
|
||||
- entityhuman.addEffect(new MobEffectInstance(primaryEffect, j, b0, true, true));
|
||||
+ // Paper start - BeaconEffectEvent
|
||||
+ entityhuman = (ServerPlayer) iterator.next();
|
||||
+ BeaconEffectEvent event = new BeaconEffectEvent(block, effect, (org.bukkit.entity.Player) entityhuman.getBukkitEntity(), isPrimary);
|
||||
+ if (CraftEventFactory.callEvent(event).isCancelled()) continue;
|
||||
+ entityhuman.addEffect(new MobEffectInstance(CraftPotionUtil.fromBukkit(event.getEffect())), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.BEACON);
|
||||
+ // Paper end - BeaconEffectEvent
|
||||
}
|
||||
+ }
|
||||
+ }
|
||||
|
||||
- if (beaconLevel >= 4 && !Objects.equals(primaryEffect, secondaryEffect) && secondaryEffect != null) {
|
||||
- iterator = list.iterator();
|
||||
-
|
||||
- while (iterator.hasNext()) {
|
||||
- entityhuman = (Player) iterator.next();
|
||||
- entityhuman.addEffect(new MobEffectInstance(secondaryEffect, j, 0, true, true));
|
||||
- }
|
||||
+ private static boolean hasSecondaryEffect(int i, @Nullable Holder<MobEffect> holder, @Nullable Holder<MobEffect> holder1) {
|
||||
+ {
|
||||
+ if (i >= 4 && !Objects.equals(holder, holder1) && holder1 != null) {
|
||||
+ return true;
|
||||
}
|
||||
|
||||
+ return false;
|
||||
}
|
||||
}
|
||||
|
||||
+ private static void applyEffects(Level world, BlockPos pos, int beaconLevel, @Nullable Holder<MobEffect> primaryEffect, @Nullable Holder<MobEffect> secondaryEffect) {
|
||||
+ // Paper start - Custom beacon ranges
|
||||
+ BeaconBlockEntity.applyEffects(world, pos, beaconLevel, primaryEffect, secondaryEffect, null);
|
||||
+ }
|
||||
+ private static void applyEffects(Level world, BlockPos pos, int beaconLevel, @Nullable Holder<MobEffect> primaryEffect, @Nullable Holder<MobEffect> secondaryEffect, @Nullable BeaconBlockEntity blockEntity) {
|
||||
+ // Paper end - Custom beacon ranges
|
||||
+ if (!world.isClientSide && primaryEffect != null) {
|
||||
+ double d0 = (double) (beaconLevel * 10 + 10);
|
||||
+ byte b0 = BeaconBlockEntity.getAmplification(beaconLevel, primaryEffect, secondaryEffect);
|
||||
+
|
||||
+ int j = BeaconBlockEntity.getLevel(beaconLevel);
|
||||
+ List list = BeaconBlockEntity.getHumansInRange(world, pos, beaconLevel, blockEntity); // Paper - Custom beacon ranges
|
||||
+
|
||||
+ BeaconBlockEntity.applyEffect(list, primaryEffect, j, b0, true, pos); // Paper - BeaconEffectEvent
|
||||
+
|
||||
+ if (BeaconBlockEntity.hasSecondaryEffect(beaconLevel, primaryEffect, secondaryEffect)) {
|
||||
+ BeaconBlockEntity.applyEffect(list, secondaryEffect, j, 0, false, pos); // Paper - BeaconEffectEvent
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
public static void playSound(Level world, BlockPos pos, SoundEvent sound) {
|
||||
world.playSound((Player) null, pos, sound, SoundSource.BLOCKS, 1.0F, 1.0F);
|
||||
}
|
||||
@@ -316,7 +440,7 @@
|
||||
if (nbt.contains(key, 8)) {
|
||||
ResourceLocation minecraftkey = ResourceLocation.tryParse(nbt.getString(key));
|
||||
|
||||
- return minecraftkey == null ? null : (Holder) BuiltInRegistries.MOB_EFFECT.get(minecraftkey).map(BeaconBlockEntity::filterEffect).orElse((Object) null);
|
||||
+ return minecraftkey == null ? null : (Holder) BuiltInRegistries.MOB_EFFECT.get(minecraftkey).orElse(null); // CraftBukkit - persist manually set non-default beacon effects (SPIGOT-3598)
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
@@ -327,11 +451,13 @@
|
||||
super.loadAdditional(nbt, registries);
|
||||
this.primaryPower = BeaconBlockEntity.loadEffect(nbt, "primary_effect");
|
||||
this.secondaryPower = BeaconBlockEntity.loadEffect(nbt, "secondary_effect");
|
||||
+ this.levels = nbt.getInt("Levels"); // CraftBukkit - SPIGOT-5053, use where available
|
||||
if (nbt.contains("CustomName", 8)) {
|
||||
this.name = parseCustomNameSafe(nbt.getString("CustomName"), registries);
|
||||
}
|
||||
|
||||
this.lockKey = LockCode.fromTag(nbt, registries);
|
||||
+ this.effectRange = nbt.contains(PAPER_RANGE_TAG, 6) ? nbt.getDouble(PAPER_RANGE_TAG) : -1; // Paper - Custom beacon ranges
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -345,6 +471,7 @@
|
||||
}
|
||||
|
||||
this.lockKey.addToTag(nbt, registries);
|
||||
+ nbt.putDouble(PAPER_RANGE_TAG, this.effectRange); // Paper - Custom beacon ranges
|
||||
}
|
||||
|
||||
public void setCustomName(@Nullable Component customName) {
|
||||
@@ -360,7 +487,7 @@
|
||||
@Nullable
|
||||
@Override
|
||||
public AbstractContainerMenu createMenu(int syncId, Inventory playerInventory, Player player) {
|
||||
- return BaseContainerBlockEntity.canUnlock(player, this.lockKey, this.getDisplayName()) ? new BeaconMenu(syncId, playerInventory, this.dataAccess, ContainerLevelAccess.create(this.level, this.getBlockPos())) : null;
|
||||
+ return BaseContainerBlockEntity.canUnlock(player, this.lockKey, this.getDisplayName(), this) ? new BeaconMenu(syncId, playerInventory, this.dataAccess, ContainerLevelAccess.create(this.level, this.getBlockPos())) : null; // Paper - Add BlockLockCheckEvent
|
||||
}
|
||||
|
||||
@Override
|
|
@ -1,306 +0,0 @@
|
|||
--- a/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java
|
||||
+++ b/net/minecraft/world/level/block/entity/BeehiveBlockEntity.java
|
||||
@@ -43,6 +43,10 @@
|
||||
import net.minecraft.world.level.gameevent.GameEvent;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
+// CraftBukkit start
|
||||
+import org.bukkit.event.entity.EntityRemoveEvent;
|
||||
+// CraftBukkit end
|
||||
+
|
||||
public class BeehiveBlockEntity extends BlockEntity {
|
||||
|
||||
private static final Logger LOGGER = LogUtils.getLogger();
|
||||
@@ -56,6 +60,7 @@
|
||||
private List<BeehiveBlockEntity.BeeData> stored = Lists.newArrayList();
|
||||
@Nullable
|
||||
public BlockPos savedFlowerPos;
|
||||
+ public int maxBees = 3; // CraftBukkit - allow setting max amount of bees a hive can hold
|
||||
|
||||
public BeehiveBlockEntity(BlockPos pos, BlockState state) {
|
||||
super(BlockEntityType.BEEHIVE, pos, state);
|
||||
@@ -95,7 +100,7 @@
|
||||
}
|
||||
|
||||
public boolean isFull() {
|
||||
- return this.stored.size() == 3;
|
||||
+ return this.stored.size() == this.maxBees; // CraftBukkit
|
||||
}
|
||||
|
||||
public void emptyAllLivingFromHive(@Nullable Player player, BlockState state, BeehiveBlockEntity.BeeReleaseStatus beeState) {
|
||||
@@ -112,7 +117,7 @@
|
||||
|
||||
if (player.position().distanceToSqr(entity.position()) <= 16.0D) {
|
||||
if (!this.isSedated()) {
|
||||
- entitybee.setTarget(player);
|
||||
+ entitybee.setTarget(player, org.bukkit.event.entity.EntityTargetEvent.TargetReason.CLOSEST_PLAYER, true); // CraftBukkit
|
||||
} else {
|
||||
entitybee.setStayOutOfHiveCountdown(400);
|
||||
}
|
||||
@@ -124,10 +129,16 @@
|
||||
}
|
||||
|
||||
private List<Entity> releaseAllOccupants(BlockState state, BeehiveBlockEntity.BeeReleaseStatus beeState) {
|
||||
+ // CraftBukkit start - This allows us to bypass the night/rain/emergency check
|
||||
+ return this.releaseBees(state, beeState, false);
|
||||
+ }
|
||||
+
|
||||
+ public List<Entity> releaseBees(BlockState iblockdata, BeehiveBlockEntity.BeeReleaseStatus tileentitybeehive_releasestatus, boolean force) {
|
||||
List<Entity> list = Lists.newArrayList();
|
||||
|
||||
this.stored.removeIf((tileentitybeehive_hivebee) -> {
|
||||
- return BeehiveBlockEntity.releaseOccupant(this.level, this.worldPosition, state, tileentitybeehive_hivebee.toOccupant(), list, beeState, this.savedFlowerPos);
|
||||
+ return BeehiveBlockEntity.releaseOccupant(this.level, this.worldPosition, iblockdata, tileentitybeehive_hivebee.toOccupant(), list, tileentitybeehive_releasestatus, this.savedFlowerPos, force);
|
||||
+ // CraftBukkit end
|
||||
});
|
||||
if (!list.isEmpty()) {
|
||||
super.setChanged();
|
||||
@@ -141,6 +152,11 @@
|
||||
return this.stored.size();
|
||||
}
|
||||
|
||||
+ // Paper start - Add EntityBlockStorage clearEntities
|
||||
+ public void clearBees() {
|
||||
+ this.stored.clear();
|
||||
+ }
|
||||
+ // Paper end - Add EntityBlockStorage clearEntities
|
||||
public static int getHoneyLevel(BlockState state) {
|
||||
return (Integer) state.getValue(BeehiveBlock.HONEY_LEVEL);
|
||||
}
|
||||
@@ -151,7 +167,17 @@
|
||||
}
|
||||
|
||||
public void addOccupant(Bee entity) {
|
||||
- if (this.stored.size() < 3) {
|
||||
+ if (this.stored.size() < this.maxBees) { // CraftBukkit
|
||||
+ // CraftBukkit start
|
||||
+ if (this.level != null) {
|
||||
+ org.bukkit.event.entity.EntityEnterBlockEvent event = new org.bukkit.event.entity.EntityEnterBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(this.level, this.getBlockPos()));
|
||||
+ org.bukkit.Bukkit.getPluginManager().callEvent(event);
|
||||
+ if (event.isCancelled()) {
|
||||
+ entity.setStayOutOfHiveCountdown(400);
|
||||
+ return;
|
||||
+ }
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
entity.stopRiding();
|
||||
entity.ejectPassengers();
|
||||
entity.dropLeash();
|
||||
@@ -167,7 +193,7 @@
|
||||
this.level.gameEvent((Holder) GameEvent.BLOCK_CHANGE, blockposition, GameEvent.Context.of(entity, this.getBlockState()));
|
||||
}
|
||||
|
||||
- entity.discard();
|
||||
+ entity.discard(EntityRemoveEvent.Cause.ENTER_BLOCK); // CraftBukkit - add Bukkit remove cause
|
||||
super.setChanged();
|
||||
}
|
||||
}
|
||||
@@ -177,32 +203,50 @@
|
||||
}
|
||||
|
||||
private static boolean releaseOccupant(Level world, BlockPos pos, BlockState state, BeehiveBlockEntity.Occupant bee, @Nullable List<Entity> entities, BeehiveBlockEntity.BeeReleaseStatus beeState, @Nullable BlockPos flowerPos) {
|
||||
- if (Bee.isNightOrRaining(world) && beeState != BeehiveBlockEntity.BeeReleaseStatus.EMERGENCY) {
|
||||
+ // CraftBukkit start - This allows us to bypass the night/rain/emergency check
|
||||
+ return BeehiveBlockEntity.releaseOccupant(world, pos, state, bee, entities, beeState, flowerPos, false);
|
||||
+ }
|
||||
+
|
||||
+ private static boolean releaseOccupant(Level world, BlockPos blockposition, BlockState iblockdata, BeehiveBlockEntity.Occupant tileentitybeehive_c, @Nullable List<Entity> list, BeehiveBlockEntity.BeeReleaseStatus tileentitybeehive_releasestatus, @Nullable BlockPos blockposition1, boolean force) {
|
||||
+ if (!force && Bee.isNightOrRaining(world) && tileentitybeehive_releasestatus != BeehiveBlockEntity.BeeReleaseStatus.EMERGENCY) {
|
||||
+ // CraftBukkit end
|
||||
return false;
|
||||
} else {
|
||||
- Direction enumdirection = (Direction) state.getValue(BeehiveBlock.FACING);
|
||||
- BlockPos blockposition2 = pos.relative(enumdirection);
|
||||
+ Direction enumdirection = (Direction) iblockdata.getValue(BeehiveBlock.FACING);
|
||||
+ BlockPos blockposition2 = blockposition.relative(enumdirection);
|
||||
boolean flag = !world.getBlockState(blockposition2).getCollisionShape(world, blockposition2).isEmpty();
|
||||
|
||||
- if (flag && beeState != BeehiveBlockEntity.BeeReleaseStatus.EMERGENCY) {
|
||||
+ if (flag && tileentitybeehive_releasestatus != BeehiveBlockEntity.BeeReleaseStatus.EMERGENCY) {
|
||||
return false;
|
||||
} else {
|
||||
- Entity entity = bee.createEntity(world, pos);
|
||||
+ Entity entity = tileentitybeehive_c.createEntity(world, blockposition);
|
||||
|
||||
if (entity != null) {
|
||||
+ // CraftBukkit start
|
||||
if (entity instanceof Bee) {
|
||||
+ float f = entity.getBbWidth();
|
||||
+ double d0 = flag ? 0.0D : 0.55D + (double) (f / 2.0F);
|
||||
+ double d1 = (double) blockposition.getX() + 0.5D + d0 * (double) enumdirection.getStepX();
|
||||
+ double d2 = (double) blockposition.getY() + 0.5D - (double) (entity.getBbHeight() / 2.0F);
|
||||
+ double d3 = (double) blockposition.getZ() + 0.5D + d0 * (double) enumdirection.getStepZ();
|
||||
+
|
||||
+ entity.moveTo(d1, d2, d3, entity.getYRot(), entity.getXRot());
|
||||
+ }
|
||||
+ if (!world.addFreshEntity(entity, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.BEEHIVE)) return false; // CraftBukkit - SpawnReason, moved from below
|
||||
+ // CraftBukkit end
|
||||
+ if (entity instanceof Bee) {
|
||||
Bee entitybee = (Bee) entity;
|
||||
|
||||
- if (flowerPos != null && !entitybee.hasSavedFlowerPos() && world.random.nextFloat() < 0.9F) {
|
||||
- entitybee.setSavedFlowerPos(flowerPos);
|
||||
+ if (blockposition1 != null && !entitybee.hasSavedFlowerPos() && world.random.nextFloat() < 0.9F) {
|
||||
+ entitybee.setSavedFlowerPos(blockposition1);
|
||||
}
|
||||
|
||||
- if (beeState == BeehiveBlockEntity.BeeReleaseStatus.HONEY_DELIVERED) {
|
||||
+ if (tileentitybeehive_releasestatus == BeehiveBlockEntity.BeeReleaseStatus.HONEY_DELIVERED) {
|
||||
entitybee.dropOffNectar();
|
||||
- if (state.is(BlockTags.BEEHIVES, (blockbase_blockdata) -> {
|
||||
+ if (iblockdata.is(BlockTags.BEEHIVES, (blockbase_blockdata) -> {
|
||||
return blockbase_blockdata.hasProperty(BeehiveBlock.HONEY_LEVEL);
|
||||
})) {
|
||||
- int i = BeehiveBlockEntity.getHoneyLevel(state);
|
||||
+ int i = BeehiveBlockEntity.getHoneyLevel(iblockdata);
|
||||
|
||||
if (i < 5) {
|
||||
int j = world.random.nextInt(100) == 0 ? 2 : 1;
|
||||
@@ -211,27 +255,35 @@
|
||||
--j;
|
||||
}
|
||||
|
||||
- world.setBlockAndUpdate(pos, (BlockState) state.setValue(BeehiveBlock.HONEY_LEVEL, i + j));
|
||||
+ // Paper start - Fire EntityChangeBlockEvent in more places
|
||||
+ BlockState newBlockState = iblockdata.setValue(BeehiveBlock.HONEY_LEVEL, i + j);
|
||||
+
|
||||
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(entitybee, blockposition, newBlockState)) {
|
||||
+ world.setBlockAndUpdate(blockposition, newBlockState);
|
||||
+ }
|
||||
+ // Paper end - Fire EntityChangeBlockEvent in more places
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- if (entities != null) {
|
||||
- entities.add(entitybee);
|
||||
+ if (list != null) {
|
||||
+ list.add(entitybee);
|
||||
}
|
||||
|
||||
+ /* // CraftBukkit start
|
||||
float f = entity.getBbWidth();
|
||||
double d0 = flag ? 0.0D : 0.55D + (double) (f / 2.0F);
|
||||
- double d1 = (double) pos.getX() + 0.5D + d0 * (double) enumdirection.getStepX();
|
||||
- double d2 = (double) pos.getY() + 0.5D - (double) (entity.getBbHeight() / 2.0F);
|
||||
- double d3 = (double) pos.getZ() + 0.5D + d0 * (double) enumdirection.getStepZ();
|
||||
+ double d1 = (double) blockposition.getX() + 0.5D + d0 * (double) enumdirection.getStepX();
|
||||
+ double d2 = (double) blockposition.getY() + 0.5D - (double) (entity.getBbHeight() / 2.0F);
|
||||
+ double d3 = (double) blockposition.getZ() + 0.5D + d0 * (double) enumdirection.getStepZ();
|
||||
|
||||
entity.moveTo(d1, d2, d3, entity.getYRot(), entity.getXRot());
|
||||
+ */ // CraftBukkit end
|
||||
}
|
||||
|
||||
- world.playSound((Player) null, pos, SoundEvents.BEEHIVE_EXIT, SoundSource.BLOCKS, 1.0F, 1.0F);
|
||||
- world.gameEvent((Holder) GameEvent.BLOCK_CHANGE, pos, GameEvent.Context.of(entity, world.getBlockState(pos)));
|
||||
- return world.addFreshEntity(entity);
|
||||
+ world.playSound((Player) null, blockposition, SoundEvents.BEEHIVE_EXIT, SoundSource.BLOCKS, 1.0F, 1.0F);
|
||||
+ world.gameEvent((Holder) GameEvent.BLOCK_CHANGE, blockposition, GameEvent.Context.of(entity, world.getBlockState(blockposition)));
|
||||
+ return true; // return this.world.addFreshEntity(entity); // CraftBukkit - moved up
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
@@ -256,6 +308,10 @@
|
||||
if (BeehiveBlockEntity.releaseOccupant(world, pos, state, tileentitybeehive_hivebee.toOccupant(), (List) null, tileentitybeehive_releasestatus, flowerPos)) {
|
||||
flag = true;
|
||||
iterator.remove();
|
||||
+ // CraftBukkit start
|
||||
+ } else {
|
||||
+ tileentitybeehive_hivebee.exitTickCounter = tileentitybeehive_hivebee.occupant.minTicksInHive / 2; // Not strictly Vanilla behaviour in cases where bees cannot spawn but still reasonable // Paper - Fix bees aging inside hives; use exitTickCounter to keep actual bee life
|
||||
+ // CraftBukkit end
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -282,7 +338,7 @@
|
||||
@Override
|
||||
protected void loadAdditional(CompoundTag nbt, HolderLookup.Provider registries) {
|
||||
super.loadAdditional(nbt, registries);
|
||||
- this.stored.clear();
|
||||
+ this.stored = Lists.newArrayList(); // CraftBukkit - SPIGOT-7790: create new copy (may be modified in physics event triggered by honey change)
|
||||
if (nbt.contains("bees")) {
|
||||
BeehiveBlockEntity.Occupant.LIST_CODEC.parse(NbtOps.INSTANCE, nbt.get("bees")).resultOrPartial((s) -> {
|
||||
BeehiveBlockEntity.LOGGER.error("Failed to parse bees: '{}'", s);
|
||||
@@ -291,7 +347,12 @@
|
||||
});
|
||||
}
|
||||
|
||||
- this.savedFlowerPos = (BlockPos) NbtUtils.readBlockPos(nbt, "flower_pos").orElse((Object) null);
|
||||
+ this.savedFlowerPos = (BlockPos) NbtUtils.readBlockPos(nbt, "flower_pos").orElse(null); // CraftBukkit - decompile error
|
||||
+ // CraftBukkit start
|
||||
+ if (nbt.contains("Bukkit.MaxEntities")) {
|
||||
+ this.maxBees = nbt.getInt("Bukkit.MaxEntities");
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -301,13 +362,14 @@
|
||||
if (this.hasSavedFlowerPos()) {
|
||||
nbt.put("flower_pos", NbtUtils.writeBlockPos(this.savedFlowerPos));
|
||||
}
|
||||
+ nbt.putInt("Bukkit.MaxEntities", this.maxBees); // CraftBukkit
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void applyImplicitComponents(BlockEntity.DataComponentInput components) {
|
||||
super.applyImplicitComponents(components);
|
||||
- this.stored.clear();
|
||||
+ this.stored = Lists.newArrayList(); // CraftBukkit - SPIGOT-7790: create new copy (may be modified in physics event triggered by honey change)
|
||||
List<BeehiveBlockEntity.Occupant> list = (List) components.getOrDefault(DataComponents.BEES, List.of());
|
||||
|
||||
list.forEach(this::storeBee);
|
||||
@@ -348,7 +410,7 @@
|
||||
CompoundTag nbttagcompound = new CompoundTag();
|
||||
|
||||
entity.save(nbttagcompound);
|
||||
- List list = BeehiveBlockEntity.IGNORED_BEE_TAGS;
|
||||
+ List<String> list = BeehiveBlockEntity.IGNORED_BEE_TAGS; // CraftBukkit - decompile error
|
||||
|
||||
Objects.requireNonNull(nbttagcompound);
|
||||
list.forEach(nbttagcompound::remove);
|
||||
@@ -367,7 +429,7 @@
|
||||
@Nullable
|
||||
public Entity createEntity(Level world, BlockPos pos) {
|
||||
CompoundTag nbttagcompound = this.entityData.copyTag();
|
||||
- List list = BeehiveBlockEntity.IGNORED_BEE_TAGS;
|
||||
+ List<String> list = BeehiveBlockEntity.IGNORED_BEE_TAGS; // CraftBukkit - decompile error
|
||||
|
||||
Objects.requireNonNull(nbttagcompound);
|
||||
list.forEach(nbttagcompound::remove);
|
||||
@@ -391,6 +453,7 @@
|
||||
}
|
||||
|
||||
private static void setBeeReleaseData(int ticksInHive, Bee beeEntity) {
|
||||
+ if (!beeEntity.ageLocked) { // Paper - Honor ageLock
|
||||
int j = beeEntity.getAge();
|
||||
|
||||
if (j < 0) {
|
||||
@@ -400,21 +463,25 @@
|
||||
}
|
||||
|
||||
beeEntity.setInLoveTime(Math.max(0, beeEntity.getInLoveTime() - ticksInHive));
|
||||
+ } // Paper - Honor ageLock
|
||||
}
|
||||
}
|
||||
|
||||
private static class BeeData {
|
||||
|
||||
private final BeehiveBlockEntity.Occupant occupant;
|
||||
+ private int exitTickCounter; // Paper - Fix bees aging inside hives; separate counter for checking if bee should exit to reduce exit attempts
|
||||
private int ticksInHive;
|
||||
|
||||
BeeData(BeehiveBlockEntity.Occupant data) {
|
||||
this.occupant = data;
|
||||
this.ticksInHive = data.ticksInHive();
|
||||
+ this.exitTickCounter = this.ticksInHive; // Paper - Fix bees aging inside hives
|
||||
}
|
||||
|
||||
public boolean tick() {
|
||||
- return this.ticksInHive++ > this.occupant.minTicksInHive;
|
||||
+ this.ticksInHive++; // Paper - Fix bees aging inside hives
|
||||
+ return this.exitTickCounter++ > this.occupant.minTicksInHive; // Paper - Fix bees aging inside hives
|
||||
}
|
||||
|
||||
public BeehiveBlockEntity.Occupant toOccupant() {
|
|
@ -1,153 +0,0 @@
|
|||
--- a/net/minecraft/world/level/block/entity/BlockEntity.java
|
||||
+++ b/net/minecraft/world/level/block/entity/BlockEntity.java
|
||||
@@ -26,8 +26,18 @@
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
+// CraftBukkit start
|
||||
+import org.bukkit.craftbukkit.persistence.CraftPersistentDataContainer;
|
||||
+import org.bukkit.craftbukkit.persistence.CraftPersistentDataTypeRegistry;
|
||||
+import org.bukkit.inventory.InventoryHolder;
|
||||
+// CraftBukkit end
|
||||
+
|
||||
public abstract class BlockEntity {
|
||||
|
||||
+ // CraftBukkit start - data containers
|
||||
+ private static final CraftPersistentDataTypeRegistry DATA_TYPE_REGISTRY = new CraftPersistentDataTypeRegistry();
|
||||
+ public CraftPersistentDataContainer persistentDataContainer;
|
||||
+ // CraftBukkit end
|
||||
private static final Logger LOGGER = LogUtils.getLogger();
|
||||
private final BlockEntityType<?> type;
|
||||
@Nullable
|
||||
@@ -43,6 +53,7 @@
|
||||
this.worldPosition = pos.immutable();
|
||||
this.validateBlockState(state);
|
||||
this.blockState = state;
|
||||
+ this.persistentDataContainer = new CraftPersistentDataContainer(DATA_TYPE_REGISTRY); // Paper - always init
|
||||
}
|
||||
|
||||
private void validateBlockState(BlockState state) {
|
||||
@@ -74,7 +85,16 @@
|
||||
return this.level != null;
|
||||
}
|
||||
|
||||
- protected void loadAdditional(CompoundTag nbt, HolderLookup.Provider registries) {}
|
||||
+ // CraftBukkit start - read container
|
||||
+ protected void loadAdditional(CompoundTag nbt, HolderLookup.Provider registries) {
|
||||
+ this.persistentDataContainer.clear(); // Paper - clear instead of init
|
||||
+
|
||||
+ net.minecraft.nbt.Tag persistentDataTag = nbt.get("PublicBukkitValues");
|
||||
+ if (persistentDataTag instanceof CompoundTag) {
|
||||
+ this.persistentDataContainer.putAll((CompoundTag) persistentDataTag);
|
||||
+ }
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
|
||||
public final void loadWithComponents(CompoundTag nbt, HolderLookup.Provider registries) {
|
||||
this.loadAdditional(nbt, registries);
|
||||
@@ -114,6 +134,11 @@
|
||||
}).ifPresent((nbtbase) -> {
|
||||
nbttagcompound.merge((CompoundTag) nbtbase);
|
||||
});
|
||||
+ // CraftBukkit start - store container
|
||||
+ if (this.persistentDataContainer != null && !this.persistentDataContainer.isEmpty()) {
|
||||
+ nbttagcompound.put("PublicBukkitValues", this.persistentDataContainer.toTagCompound());
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
return nbttagcompound;
|
||||
}
|
||||
|
||||
@@ -121,6 +146,11 @@
|
||||
CompoundTag nbttagcompound = new CompoundTag();
|
||||
|
||||
this.saveAdditional(nbttagcompound, registries);
|
||||
+ // Paper start - store PDC here as well
|
||||
+ if (this.persistentDataContainer != null && !this.persistentDataContainer.isEmpty()) {
|
||||
+ nbttagcompound.put("PublicBukkitValues", this.persistentDataContainer.toTagCompound());
|
||||
+ }
|
||||
+ // Paper end
|
||||
return nbttagcompound;
|
||||
}
|
||||
|
||||
@@ -234,7 +264,12 @@
|
||||
public void fillCrashReportCategory(CrashReportCategory crashReportSection) {
|
||||
crashReportSection.setDetail("Name", this::getNameForReporting);
|
||||
if (this.level != null) {
|
||||
- CrashReportCategory.populateBlockDetails(crashReportSection, this.level, this.worldPosition, this.getBlockState());
|
||||
+ // Paper start - Prevent block entity and entity crashes
|
||||
+ BlockState block = this.getBlockState();
|
||||
+ if (block != null) {
|
||||
+ CrashReportCategory.populateBlockDetails(crashReportSection, this.level, this.worldPosition, block);
|
||||
+ }
|
||||
+ // Paper end - Prevent block entity and entity crashes
|
||||
CrashReportCategory.populateBlockDetails(crashReportSection, this.level, this.worldPosition, this.level.getBlockState(this.worldPosition));
|
||||
}
|
||||
}
|
||||
@@ -263,13 +298,19 @@
|
||||
}
|
||||
|
||||
public final void applyComponents(DataComponentMap defaultComponents, DataComponentPatch components) {
|
||||
+ // CraftBukkit start
|
||||
+ this.applyComponentsSet(defaultComponents, components);
|
||||
+ }
|
||||
+
|
||||
+ public final Set<DataComponentType<?>> applyComponentsSet(DataComponentMap datacomponentmap, DataComponentPatch datacomponentpatch) {
|
||||
+ // CraftBukkit end
|
||||
final Set<DataComponentType<?>> set = new HashSet();
|
||||
|
||||
set.add(DataComponents.BLOCK_ENTITY_DATA);
|
||||
set.add(DataComponents.BLOCK_STATE);
|
||||
- final PatchedDataComponentMap patcheddatacomponentmap = PatchedDataComponentMap.fromPatch(defaultComponents, components);
|
||||
+ final PatchedDataComponentMap patcheddatacomponentmap = PatchedDataComponentMap.fromPatch(datacomponentmap, datacomponentpatch);
|
||||
|
||||
- this.applyImplicitComponents(new BlockEntity.DataComponentInput(this) {
|
||||
+ this.applyImplicitComponents(new BlockEntity.DataComponentInput() { // CraftBukkit - decompile error
|
||||
@Nullable
|
||||
@Override
|
||||
public <T> T get(DataComponentType<T> type) {
|
||||
@@ -284,9 +325,13 @@
|
||||
}
|
||||
});
|
||||
Objects.requireNonNull(set);
|
||||
- DataComponentPatch datacomponentpatch1 = components.forget(set::contains);
|
||||
+ DataComponentPatch datacomponentpatch1 = datacomponentpatch.forget(set::contains);
|
||||
|
||||
this.components = datacomponentpatch1.split().added();
|
||||
+ // CraftBukkit start
|
||||
+ set.remove(DataComponents.BLOCK_ENTITY_DATA); // Remove as never actually added by applyImplicitComponents
|
||||
+ return set;
|
||||
+ // CraftBukkit end
|
||||
}
|
||||
|
||||
protected void collectImplicitComponents(DataComponentMap.Builder builder) {}
|
||||
@@ -321,6 +366,30 @@
|
||||
}
|
||||
}
|
||||
|
||||
+ // CraftBukkit start - add method
|
||||
+ public InventoryHolder getOwner() {
|
||||
+ // Paper start
|
||||
+ return getOwner(true);
|
||||
+ }
|
||||
+ public InventoryHolder getOwner(boolean useSnapshot) {
|
||||
+ // 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; // 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;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
+ // Paper start - Sanitize sent data
|
||||
+ public CompoundTag sanitizeSentNbt(CompoundTag tag) {
|
||||
+ tag.remove("PublicBukkitValues");
|
||||
+
|
||||
+ return tag;
|
||||
+ }
|
||||
+ // Paper end - Sanitize sent data
|
||||
+
|
||||
private static class ComponentHelper {
|
||||
|
||||
public static final Codec<DataComponentMap> COMPONENTS_CODEC = DataComponentMap.CODEC.optionalFieldOf("components", DataComponentMap.EMPTY).codec();
|
|
@ -1,20 +0,0 @@
|
|||
--- a/net/minecraft/world/level/block/entity/BlockEntityType.java
|
||||
+++ b/net/minecraft/world/level/block/entity/BlockEntityType.java
|
||||
@@ -66,7 +66,7 @@
|
||||
public static final BlockEntityType<CrafterBlockEntity> CRAFTER = BlockEntityType.register("crafter", CrafterBlockEntity::new, Blocks.CRAFTER);
|
||||
public static final BlockEntityType<TrialSpawnerBlockEntity> TRIAL_SPAWNER = BlockEntityType.register("trial_spawner", TrialSpawnerBlockEntity::new, Blocks.TRIAL_SPAWNER);
|
||||
public static final BlockEntityType<VaultBlockEntity> VAULT = BlockEntityType.register("vault", VaultBlockEntity::new, Blocks.VAULT);
|
||||
- private static final Set<BlockEntityType<?>> OP_ONLY_CUSTOM_DATA = Set.of(BlockEntityType.COMMAND_BLOCK, BlockEntityType.LECTERN, BlockEntityType.SIGN, BlockEntityType.HANGING_SIGN, BlockEntityType.MOB_SPAWNER, BlockEntityType.TRIAL_SPAWNER);
|
||||
+ private static final Set<BlockEntityType<?>> OP_ONLY_CUSTOM_DATA = Set.of(BlockEntityType.COMMAND_BLOCK, BlockEntityType.LECTERN, BlockEntityType.SIGN, BlockEntityType.HANGING_SIGN, BlockEntityType.MOB_SPAWNER, BlockEntityType.TRIAL_SPAWNER); // CraftBukkit // Paper - Allow chests to be placed with NBT data
|
||||
private final BlockEntityType.BlockEntitySupplier<? extends T> factory;
|
||||
public final Set<Block> validBlocks;
|
||||
private final Holder.Reference<BlockEntityType<?>> builtInRegistryHolder;
|
||||
@@ -110,7 +110,7 @@
|
||||
public T getBlockEntity(BlockGetter world, BlockPos pos) {
|
||||
BlockEntity tileentity = world.getBlockEntity(pos);
|
||||
|
||||
- return tileentity != null && tileentity.getType() == this ? tileentity : null;
|
||||
+ return tileentity != null && tileentity.getType() == this ? (T) tileentity : null; // CraftBukkit - decompile error
|
||||
}
|
||||
|
||||
public boolean onlyOpCanSetNbt() {
|
|
@ -1,232 +0,0 @@
|
|||
--- a/net/minecraft/world/level/block/entity/BrewingStandBlockEntity.java
|
||||
+++ b/net/minecraft/world/level/block/entity/BrewingStandBlockEntity.java
|
||||
@@ -8,7 +8,6 @@
|
||||
import net.minecraft.core.NonNullList;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.chat.Component;
|
||||
-import net.minecraft.tags.ItemTags;
|
||||
import net.minecraft.world.ContainerHelper;
|
||||
import net.minecraft.world.Containers;
|
||||
import net.minecraft.world.WorldlyContainer;
|
||||
@@ -23,6 +22,20 @@
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.BrewingStandBlock;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
+// CraftBukkit start
|
||||
+import java.util.ArrayList;
|
||||
+import java.util.List;
|
||||
+import net.minecraft.server.MinecraftServer;
|
||||
+import net.minecraft.tags.ItemTags;
|
||||
+import org.bukkit.craftbukkit.block.CraftBlock;
|
||||
+import org.bukkit.craftbukkit.entity.CraftHumanEntity;
|
||||
+import org.bukkit.craftbukkit.inventory.CraftItemStack;
|
||||
+import org.bukkit.entity.HumanEntity;
|
||||
+import org.bukkit.event.block.BrewingStartEvent;
|
||||
+import org.bukkit.event.inventory.BrewEvent;
|
||||
+import org.bukkit.event.inventory.BrewingStandFuelEvent;
|
||||
+import org.bukkit.inventory.InventoryHolder;
|
||||
+// CraftBukkit end
|
||||
|
||||
public class BrewingStandBlockEntity extends BaseContainerBlockEntity implements WorldlyContainer {
|
||||
|
||||
@@ -37,11 +50,42 @@
|
||||
public static final int NUM_DATA_VALUES = 2;
|
||||
private NonNullList<ItemStack> items;
|
||||
public int brewTime;
|
||||
+ public int recipeBrewTime = 400; // Paper - Add recipeBrewTime
|
||||
private boolean[] lastPotionCount;
|
||||
private Item ingredient;
|
||||
public int fuel;
|
||||
protected final ContainerData dataAccess;
|
||||
+ // CraftBukkit start - add fields and methods
|
||||
+ // private int lastTick = MinecraftServer.currentTick; // Paper - remove anti tick skipping measures / wall time
|
||||
+ public List<HumanEntity> transaction = new java.util.ArrayList<HumanEntity>();
|
||||
+ private int maxStack = MAX_STACK;
|
||||
|
||||
+ public void onOpen(CraftHumanEntity who) {
|
||||
+ this.transaction.add(who);
|
||||
+ }
|
||||
+
|
||||
+ public void onClose(CraftHumanEntity who) {
|
||||
+ this.transaction.remove(who);
|
||||
+ }
|
||||
+
|
||||
+ public List<HumanEntity> getViewers() {
|
||||
+ return this.transaction;
|
||||
+ }
|
||||
+
|
||||
+ public List<ItemStack> getContents() {
|
||||
+ return this.items;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public int getMaxStackSize() {
|
||||
+ return this.maxStack;
|
||||
+ }
|
||||
+
|
||||
+ public void setMaxStackSize(int size) {
|
||||
+ this.maxStack = size;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
public BrewingStandBlockEntity(BlockPos pos, BlockState state) {
|
||||
super(BlockEntityType.BREWING_STAND, pos, state);
|
||||
this.items = NonNullList.withSize(5, ItemStack.EMPTY);
|
||||
@@ -57,6 +101,11 @@
|
||||
case 1:
|
||||
j = BrewingStandBlockEntity.this.fuel;
|
||||
break;
|
||||
+ // Paper start - Add recipeBrewTime
|
||||
+ case 2:
|
||||
+ j = BrewingStandBlockEntity.this.recipeBrewTime;
|
||||
+ break;
|
||||
+ // Paper end - Add recipeBrewTime
|
||||
default:
|
||||
j = 0;
|
||||
}
|
||||
@@ -72,13 +121,18 @@
|
||||
break;
|
||||
case 1:
|
||||
BrewingStandBlockEntity.this.fuel = value;
|
||||
+ // Paper start - Add recipeBrewTime
|
||||
+ case 2:
|
||||
+ BrewingStandBlockEntity.this.recipeBrewTime = value;
|
||||
+ break;
|
||||
+ // Paper end - Add recipeBrewTime
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
- return 2;
|
||||
+ return 3; // Paper - Add recipeBrewTime
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -107,8 +161,19 @@
|
||||
ItemStack itemstack = (ItemStack) blockEntity.items.get(4);
|
||||
|
||||
if (blockEntity.fuel <= 0 && itemstack.is(ItemTags.BREWING_FUEL)) {
|
||||
- blockEntity.fuel = 20;
|
||||
- itemstack.shrink(1);
|
||||
+ // CraftBukkit start
|
||||
+ BrewingStandFuelEvent event = new BrewingStandFuelEvent(CraftBlock.at(world, pos), CraftItemStack.asCraftMirror(itemstack), 20);
|
||||
+ world.getCraftServer().getPluginManager().callEvent(event);
|
||||
+
|
||||
+ if (event.isCancelled()) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ blockEntity.fuel = event.getFuelPower();
|
||||
+ if (blockEntity.fuel > 0 && event.isConsuming()) {
|
||||
+ itemstack.shrink(1);
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
setChanged(world, pos, state);
|
||||
}
|
||||
|
||||
@@ -116,12 +181,15 @@
|
||||
boolean flag1 = blockEntity.brewTime > 0;
|
||||
ItemStack itemstack1 = (ItemStack) blockEntity.items.get(3);
|
||||
|
||||
+ // Paper - remove anti tick skipping measures / wall time
|
||||
+
|
||||
if (flag1) {
|
||||
- --blockEntity.brewTime;
|
||||
- boolean flag2 = blockEntity.brewTime == 0;
|
||||
+ --blockEntity.brewTime; // Paper - remove anti tick skipping measures / wall time - revert to vanilla
|
||||
+ boolean flag2 = blockEntity.brewTime <= 0; // == -> <=
|
||||
+ // CraftBukkit end
|
||||
|
||||
if (flag2 && flag) {
|
||||
- BrewingStandBlockEntity.doBrew(world, pos, blockEntity.items);
|
||||
+ BrewingStandBlockEntity.doBrew(world, pos, blockEntity.items, blockEntity); // CraftBukkit
|
||||
} else if (!flag || !itemstack1.is(blockEntity.ingredient)) {
|
||||
blockEntity.brewTime = 0;
|
||||
}
|
||||
@@ -129,7 +197,12 @@
|
||||
setChanged(world, pos, state);
|
||||
} else if (flag && blockEntity.fuel > 0) {
|
||||
--blockEntity.fuel;
|
||||
- blockEntity.brewTime = 400;
|
||||
+ // CraftBukkit start
|
||||
+ BrewingStartEvent event = new BrewingStartEvent(CraftBlock.at(world, pos), CraftItemStack.asCraftMirror(itemstack1), 400);
|
||||
+ world.getCraftServer().getPluginManager().callEvent(event);
|
||||
+ blockEntity.recipeBrewTime = event.getRecipeBrewTime(); // Paper - use recipe brew time from event
|
||||
+ blockEntity.brewTime = event.getBrewingTime(); // 400 -> event.getTotalBrewTime() // Paper - use brewing time from event
|
||||
+ // CraftBukkit end
|
||||
blockEntity.ingredient = itemstack1.getItem();
|
||||
setChanged(world, pos, state);
|
||||
}
|
||||
@@ -185,14 +258,36 @@
|
||||
}
|
||||
}
|
||||
|
||||
- private static void doBrew(Level world, BlockPos pos, NonNullList<ItemStack> slots) {
|
||||
- ItemStack itemstack = (ItemStack) slots.get(3);
|
||||
+ private static void doBrew(Level world, BlockPos blockposition, NonNullList<ItemStack> nonnulllist, BrewingStandBlockEntity tileentitybrewingstand) { // CraftBukkit
|
||||
+ ItemStack itemstack = (ItemStack) nonnulllist.get(3);
|
||||
PotionBrewing potionbrewer = world.potionBrewing();
|
||||
|
||||
+ // CraftBukkit start
|
||||
+ InventoryHolder owner = tileentitybrewingstand.getOwner();
|
||||
+ List<org.bukkit.inventory.ItemStack> brewResults = new ArrayList<>(3);
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
- slots.set(i, potionbrewer.mix(itemstack, (ItemStack) slots.get(i)));
|
||||
+ brewResults.add(i, CraftItemStack.asCraftMirror(potionbrewer.mix(itemstack, (ItemStack) nonnulllist.get(i))));
|
||||
}
|
||||
|
||||
+ if (owner != null) {
|
||||
+ BrewEvent event = new BrewEvent(CraftBlock.at(world, blockposition), (org.bukkit.inventory.BrewerInventory) owner.getInventory(), brewResults, tileentitybrewingstand.fuel);
|
||||
+ org.bukkit.Bukkit.getPluginManager().callEvent(event);
|
||||
+ if (event.isCancelled()) {
|
||||
+ return;
|
||||
+ }
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
+ for (int i = 0; i < 3; ++i) {
|
||||
+ // CraftBukkit start - validate index in case it is cleared by plugins
|
||||
+ if (i < brewResults.size()) {
|
||||
+ nonnulllist.set(i, CraftItemStack.asNMSCopy(brewResults.get(i)));
|
||||
+ } else {
|
||||
+ nonnulllist.set(i, ItemStack.EMPTY);
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+ }
|
||||
+
|
||||
itemstack.shrink(1);
|
||||
ItemStack itemstack1 = itemstack.getItem().getCraftingRemainder();
|
||||
|
||||
@@ -200,12 +295,12 @@
|
||||
if (itemstack.isEmpty()) {
|
||||
itemstack = itemstack1;
|
||||
} else {
|
||||
- Containers.dropItemStack(world, (double) pos.getX(), (double) pos.getY(), (double) pos.getZ(), itemstack1);
|
||||
+ Containers.dropItemStack(world, (double) blockposition.getX(), (double) blockposition.getY(), (double) blockposition.getZ(), itemstack1);
|
||||
}
|
||||
}
|
||||
|
||||
- slots.set(3, itemstack);
|
||||
- world.levelEvent(1035, pos, 0);
|
||||
+ nonnulllist.set(3, itemstack);
|
||||
+ world.levelEvent(1035, blockposition, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -231,12 +326,12 @@
|
||||
|
||||
@Override
|
||||
public boolean canPlaceItem(int slot, ItemStack stack) {
|
||||
+ PotionBrewing potionbrewer = this.level != null ? this.level.potionBrewing() : PotionBrewing.EMPTY; // Paper - move up
|
||||
if (slot == 3) {
|
||||
- PotionBrewing potionbrewer = this.level != null ? this.level.potionBrewing() : PotionBrewing.EMPTY;
|
||||
|
||||
return potionbrewer.isIngredient(stack);
|
||||
} else {
|
||||
- return slot == 4 ? stack.is(ItemTags.BREWING_FUEL) : (stack.is(Items.POTION) || stack.is(Items.SPLASH_POTION) || stack.is(Items.LINGERING_POTION) || stack.is(Items.GLASS_BOTTLE)) && this.getItem(slot).isEmpty();
|
||||
+ return slot == 4 ? stack.is(ItemTags.BREWING_FUEL) : (stack.is(Items.POTION) || stack.is(Items.SPLASH_POTION) || stack.is(Items.LINGERING_POTION) || stack.is(Items.GLASS_BOTTLE) || potionbrewer.isCustomInput(stack)) && this.getItem(slot).isEmpty(); // Paper - Custom Potion Mixes
|
||||
}
|
||||
}
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
--- a/net/minecraft/world/level/block/entity/BrushableBlockEntity.java
|
||||
+++ b/net/minecraft/world/level/block/entity/BrushableBlockEntity.java
|
||||
@@ -31,6 +31,12 @@
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
+// CraftBukkit start
|
||||
+import java.util.Arrays;
|
||||
+import org.bukkit.craftbukkit.block.CraftBlock;
|
||||
+import org.bukkit.craftbukkit.event.CraftEventFactory;
|
||||
+// CraftBukkit end
|
||||
+
|
||||
public class BrushableBlockEntity extends BlockEntity {
|
||||
|
||||
private static final Logger LOGGER = LogUtils.getLogger();
|
||||
@@ -151,7 +157,10 @@
|
||||
ItemEntity entityitem = new ItemEntity(world, d3, d4, d5, this.item.split(world.random.nextInt(21) + 10));
|
||||
|
||||
entityitem.setDeltaMovement(Vec3.ZERO);
|
||||
- world.addFreshEntity(entityitem);
|
||||
+ // CraftBukkit start
|
||||
+ org.bukkit.block.Block bblock = CraftBlock.at(this.level, this.worldPosition);
|
||||
+ CraftEventFactory.handleBlockDropItemEvent(bblock, bblock.getState(), (ServerPlayer) player, Arrays.asList(entityitem));
|
||||
+ // CraftBukkit end
|
||||
this.item = ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
@@ -185,7 +194,7 @@
|
||||
|
||||
private boolean tryLoadLootTable(CompoundTag nbt) {
|
||||
if (nbt.contains("LootTable", 8)) {
|
||||
- this.lootTable = ResourceKey.create(Registries.LOOT_TABLE, ResourceLocation.parse(nbt.getString("LootTable")));
|
||||
+ this.lootTable = net.minecraft.Optionull.map(ResourceLocation.tryParse(nbt.getString("LootTable")), rl -> ResourceKey.create(Registries.LOOT_TABLE, rl)); // Paper - Validate ResourceLocation
|
||||
this.lootTableSeed = nbt.getLong("LootTableSeed");
|
||||
return true;
|
||||
} else {
|
|
@ -1,121 +0,0 @@
|
|||
--- a/net/minecraft/world/level/block/entity/CampfireBlockEntity.java
|
||||
+++ b/net/minecraft/world/level/block/entity/CampfireBlockEntity.java
|
||||
@@ -31,6 +31,14 @@
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.gameevent.GameEvent;
|
||||
|
||||
+// CraftBukkit start
|
||||
+import org.bukkit.craftbukkit.block.CraftBlock;
|
||||
+import org.bukkit.craftbukkit.inventory.CraftItemStack;
|
||||
+import org.bukkit.event.block.BlockCookEvent;
|
||||
+import org.bukkit.event.block.CampfireStartEvent;
|
||||
+import org.bukkit.inventory.CampfireRecipe;
|
||||
+// CraftBukkit end
|
||||
+
|
||||
public class CampfireBlockEntity extends BlockEntity implements Clearable {
|
||||
|
||||
private static final int BURN_COOL_SPEED = 2;
|
||||
@@ -38,12 +46,14 @@
|
||||
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) {
|
||||
@@ -54,16 +64,42 @@
|
||||
|
||||
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);
|
||||
- ItemStack itemstack1 = (ItemStack) recipeMatchGetter.getRecipeFor(singlerecipeinput, world).map((recipeholder) -> {
|
||||
+ // Paper start - add recipe to cook events
|
||||
+ final Optional<RecipeHolder<CampfireCookingRecipe>> recipeHolderOptional = recipeMatchGetter.getRecipeFor(singlerecipeinput, world);
|
||||
+ ItemStack itemstack1 = (ItemStack) recipeHolderOptional.map((recipeholder) -> {
|
||||
+ // Paper end - add recipe to cook events
|
||||
return ((CampfireCookingRecipe) recipeholder.value()).assemble(singlerecipeinput, world.registryAccess());
|
||||
}).orElse(itemstack);
|
||||
|
||||
if (itemstack1.isItemEnabled(world.enabledFeatures())) {
|
||||
- Containers.dropItemStack(world, (double) pos.getX(), (double) pos.getY(), (double) pos.getZ(), itemstack1);
|
||||
+ // CraftBukkit start - fire BlockCookEvent
|
||||
+ CraftItemStack source = CraftItemStack.asCraftMirror(itemstack);
|
||||
+ org.bukkit.inventory.ItemStack result = CraftItemStack.asBukkitCopy(itemstack1);
|
||||
+
|
||||
+ BlockCookEvent blockCookEvent = new BlockCookEvent(CraftBlock.at(world, pos), source, result, (org.bukkit.inventory.CookingRecipe<?>) recipeHolderOptional.map(RecipeHolder::toBukkitRecipe).orElse(null)); // Paper - Add recipe to cook events
|
||||
+ world.getCraftServer().getPluginManager().callEvent(blockCookEvent);
|
||||
+
|
||||
+ if (blockCookEvent.isCancelled()) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ result = blockCookEvent.getResult();
|
||||
+ itemstack1 = CraftItemStack.asNMSCopy(result);
|
||||
+ // CraftBukkit end
|
||||
+ // Paper start - Fix item locations dropped from campfires
|
||||
+ double deviation = 0.05F * RandomSource.GAUSSIAN_SPREAD_FACTOR;
|
||||
+ while (!itemstack1.isEmpty()) {
|
||||
+ net.minecraft.world.entity.item.ItemEntity droppedItem = new net.minecraft.world.entity.item.ItemEntity(world, pos.getX() + 0.5D, pos.getY() + 0.5D, pos.getZ() + 0.5D, itemstack1.split(world.random.nextInt(21) + 10));
|
||||
+ droppedItem.setDeltaMovement(world.random.triangle(0.0D, deviation), world.random.triangle(0.2D, deviation), world.random.triangle(0.0D, deviation));
|
||||
+ world.addFreshEntity(droppedItem);
|
||||
+ }
|
||||
+ // Paper end - Fix item locations dropped from campfires
|
||||
blockEntity.items.set(i, ItemStack.EMPTY);
|
||||
world.sendBlockUpdated(pos, state, state, 3);
|
||||
world.gameEvent((Holder) GameEvent.BLOCK_CHANGE, pos, GameEvent.Context.of(state));
|
||||
@@ -143,6 +179,16 @@
|
||||
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
|
||||
@@ -151,6 +197,13 @@
|
||||
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
|
||||
@@ -177,7 +230,11 @@
|
||||
return false;
|
||||
}
|
||||
|
||||
- this.cookingTime[i] = ((CampfireCookingRecipe) ((RecipeHolder) optional.get()).value()).cookingTime();
|
||||
+ // CraftBukkit start
|
||||
+ CampfireStartEvent event = new CampfireStartEvent(CraftBlock.at(this.level,this.worldPosition), CraftItemStack.asCraftMirror(stack), (CampfireRecipe) optional.get().toBukkitRecipe());
|
||||
+ this.level.getCraftServer().getPluginManager().callEvent(event);
|
||||
+ this.cookingTime[i] = event.getTotalCookTime(); // i -> event.getTotalCookTime()
|
||||
+ // CraftBukkit end
|
||||
this.cookingProgress[i] = 0;
|
||||
this.items.set(i, stack.consumeAndReturn(1, entity));
|
||||
world.gameEvent((Holder) GameEvent.BLOCK_CHANGE, this.getBlockPos(), GameEvent.Context.of(entity, this.getBlockState()));
|
|
@ -1,108 +0,0 @@
|
|||
--- a/net/minecraft/world/level/block/entity/ConduitBlockEntity.java
|
||||
+++ b/net/minecraft/world/level/block/entity/ConduitBlockEntity.java
|
||||
@@ -10,6 +10,7 @@
|
||||
import net.minecraft.core.particles.ParticleTypes;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket;
|
||||
+import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.sounds.SoundEvent;
|
||||
import net.minecraft.sounds.SoundEvents;
|
||||
import net.minecraft.sounds.SoundSource;
|
||||
@@ -187,11 +188,23 @@
|
||||
}
|
||||
|
||||
private static void applyEffects(Level world, BlockPos pos, List<BlockPos> activatingBlocks) {
|
||||
- int i = activatingBlocks.size();
|
||||
+ // CraftBukkit start
|
||||
+ ConduitBlockEntity.applyEffects(world, pos, ConduitBlockEntity.getRange(activatingBlocks));
|
||||
+ }
|
||||
+
|
||||
+ public static int getRange(List<BlockPos> list) {
|
||||
+ // CraftBukkit end
|
||||
+ int i = list.size();
|
||||
int j = i / 7 * 16;
|
||||
- int k = pos.getX();
|
||||
- int l = pos.getY();
|
||||
- int i1 = pos.getZ();
|
||||
+ // CraftBukkit start
|
||||
+ return j;
|
||||
+ }
|
||||
+
|
||||
+ private static void applyEffects(Level world, BlockPos blockposition, int j) { // j = effect range in blocks
|
||||
+ // CraftBukkit end
|
||||
+ int k = blockposition.getX();
|
||||
+ int l = blockposition.getY();
|
||||
+ int i1 = blockposition.getZ();
|
||||
AABB axisalignedbb = (new AABB((double) k, (double) l, (double) i1, (double) (k + 1), (double) (l + 1), (double) (i1 + 1))).inflate((double) j).expandTowards(0.0D, (double) world.getHeight(), 0.0D);
|
||||
List<Player> list1 = world.getEntitiesOfClass(Player.class, axisalignedbb);
|
||||
|
||||
@@ -201,8 +214,8 @@
|
||||
while (iterator.hasNext()) {
|
||||
Player entityhuman = (Player) iterator.next();
|
||||
|
||||
- if (pos.closerThan(entityhuman.blockPosition(), (double) j) && entityhuman.isInWaterOrRain()) {
|
||||
- entityhuman.addEffect(new MobEffectInstance(MobEffects.CONDUIT_POWER, 260, 0, true, true));
|
||||
+ if (blockposition.closerThan(entityhuman.blockPosition(), (double) j) && entityhuman.isInWaterOrRain()) {
|
||||
+ entityhuman.addEffect(new MobEffectInstance(MobEffects.CONDUIT_POWER, 260, 0, true, true), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.CONDUIT); // CraftBukkit
|
||||
}
|
||||
}
|
||||
|
||||
@@ -210,33 +223,42 @@
|
||||
}
|
||||
|
||||
private static void updateDestroyTarget(Level world, BlockPos pos, BlockState state, List<BlockPos> activatingBlocks, ConduitBlockEntity blockEntity) {
|
||||
- LivingEntity entityliving = blockEntity.destroyTarget;
|
||||
- int i = activatingBlocks.size();
|
||||
+ // CraftBukkit start - add "damageTarget" boolean
|
||||
+ ConduitBlockEntity.updateDestroyTarget(world, pos, state, activatingBlocks, blockEntity, true);
|
||||
+ }
|
||||
|
||||
+ public static void updateDestroyTarget(Level world, BlockPos blockposition, BlockState iblockdata, List<BlockPos> list, ConduitBlockEntity tileentityconduit, boolean damageTarget) {
|
||||
+ // CraftBukkit end
|
||||
+ LivingEntity entityliving = tileentityconduit.destroyTarget;
|
||||
+ int i = list.size();
|
||||
+
|
||||
if (i < 42) {
|
||||
- blockEntity.destroyTarget = null;
|
||||
- } else if (blockEntity.destroyTarget == null && blockEntity.destroyTargetUUID != null) {
|
||||
- blockEntity.destroyTarget = ConduitBlockEntity.findDestroyTarget(world, pos, blockEntity.destroyTargetUUID);
|
||||
- blockEntity.destroyTargetUUID = null;
|
||||
- } else if (blockEntity.destroyTarget == null) {
|
||||
- List<LivingEntity> list1 = world.getEntitiesOfClass(LivingEntity.class, ConduitBlockEntity.getDestroyRangeAABB(pos), (entityliving1) -> {
|
||||
+ tileentityconduit.destroyTarget = null;
|
||||
+ } else if (tileentityconduit.destroyTarget == null && tileentityconduit.destroyTargetUUID != null) {
|
||||
+ tileentityconduit.destroyTarget = ConduitBlockEntity.findDestroyTarget(world, blockposition, tileentityconduit.destroyTargetUUID);
|
||||
+ tileentityconduit.destroyTargetUUID = null;
|
||||
+ } else if (tileentityconduit.destroyTarget == null) {
|
||||
+ List<LivingEntity> list1 = world.getEntitiesOfClass(LivingEntity.class, ConduitBlockEntity.getDestroyRangeAABB(blockposition), (entityliving1) -> {
|
||||
return entityliving1 instanceof Enemy && entityliving1.isInWaterOrRain();
|
||||
});
|
||||
|
||||
if (!list1.isEmpty()) {
|
||||
- blockEntity.destroyTarget = (LivingEntity) list1.get(world.random.nextInt(list1.size()));
|
||||
+ tileentityconduit.destroyTarget = (LivingEntity) list1.get(world.random.nextInt(list1.size()));
|
||||
}
|
||||
- } else if (!blockEntity.destroyTarget.isAlive() || !pos.closerThan(blockEntity.destroyTarget.blockPosition(), 8.0D)) {
|
||||
- blockEntity.destroyTarget = null;
|
||||
+ } else if (!tileentityconduit.destroyTarget.isAlive() || !blockposition.closerThan(tileentityconduit.destroyTarget.blockPosition(), 8.0D)) {
|
||||
+ tileentityconduit.destroyTarget = null;
|
||||
}
|
||||
|
||||
- if (blockEntity.destroyTarget != null) {
|
||||
- world.playSound((Player) null, blockEntity.destroyTarget.getX(), blockEntity.destroyTarget.getY(), blockEntity.destroyTarget.getZ(), SoundEvents.CONDUIT_ATTACK_TARGET, SoundSource.BLOCKS, 1.0F, 1.0F);
|
||||
- blockEntity.destroyTarget.hurt(world.damageSources().magic(), 4.0F);
|
||||
+ // CraftBukkit start
|
||||
+ if (damageTarget && tileentityconduit.destroyTarget != null) {
|
||||
+ if (tileentityconduit.destroyTarget.hurtServer((ServerLevel) world, world.damageSources().magic().directBlock(world, blockposition), 4.0F)) {
|
||||
+ world.playSound(null, tileentityconduit.destroyTarget.getX(), tileentityconduit.destroyTarget.getY(), tileentityconduit.destroyTarget.getZ(), SoundEvents.CONDUIT_ATTACK_TARGET, SoundSource.BLOCKS, 1.0F, 1.0F);
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
}
|
||||
|
||||
- if (entityliving != blockEntity.destroyTarget) {
|
||||
- world.sendBlockUpdated(pos, state, state, 2);
|
||||
+ if (entityliving != tileentityconduit.destroyTarget) {
|
||||
+ world.sendBlockUpdated(blockposition, iblockdata, iblockdata, 2);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,68 +0,0 @@
|
|||
--- a/net/minecraft/world/level/block/entity/CrafterBlockEntity.java
|
||||
+++ b/net/minecraft/world/level/block/entity/CrafterBlockEntity.java
|
||||
@@ -22,6 +22,11 @@
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.CrafterBlock;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
+// CraftBukkit start
|
||||
+import org.bukkit.Location;
|
||||
+import org.bukkit.craftbukkit.entity.CraftHumanEntity;
|
||||
+import org.bukkit.entity.HumanEntity;
|
||||
+// CraftBukkit end
|
||||
|
||||
public class CrafterBlockEntity extends RandomizableContainerBlockEntity implements CraftingContainer {
|
||||
|
||||
@@ -35,12 +40,52 @@
|
||||
private NonNullList<ItemStack> items;
|
||||
public int craftingTicksRemaining;
|
||||
protected final ContainerData containerData;
|
||||
+ // CraftBukkit start - add fields and methods
|
||||
+ public List<HumanEntity> transaction = new java.util.ArrayList<>();
|
||||
+ private int maxStack = MAX_STACK;
|
||||
|
||||
+ @Override
|
||||
+ public List<ItemStack> getContents() {
|
||||
+ return this.items;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void onOpen(CraftHumanEntity who) {
|
||||
+ this.transaction.add(who);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void onClose(CraftHumanEntity who) {
|
||||
+ this.transaction.remove(who);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public List<HumanEntity> getViewers() {
|
||||
+ return this.transaction;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public int getMaxStackSize() {
|
||||
+ return this.maxStack;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setMaxStackSize(int size) {
|
||||
+ this.maxStack = size;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public Location getLocation() {
|
||||
+ if (this.level == null) return null;
|
||||
+ return new org.bukkit.Location(this.level.getWorld(), this.worldPosition.getX(), this.worldPosition.getY(), this.worldPosition.getZ());
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
public CrafterBlockEntity(BlockPos pos, BlockState state) {
|
||||
super(BlockEntityType.CRAFTER, pos, state);
|
||||
this.items = NonNullList.withSize(9, ItemStack.EMPTY);
|
||||
this.craftingTicksRemaining = 0;
|
||||
- this.containerData = new ContainerData(this) {
|
||||
+ this.containerData = new ContainerData() { // CraftBukkit - decompile error
|
||||
private final int[] slotStates = new int[9];
|
||||
private int triggered = 0;
|
||||
|
|
@ -1,50 +0,0 @@
|
|||
--- a/net/minecraft/world/level/block/entity/DispenserBlockEntity.java
|
||||
+++ b/net/minecraft/world/level/block/entity/DispenserBlockEntity.java
|
||||
@@ -13,12 +13,47 @@
|
||||
import net.minecraft.world.inventory.DispenserMenu;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
+// CraftBukkit start
|
||||
+import java.util.List;
|
||||
+import org.bukkit.craftbukkit.entity.CraftHumanEntity;
|
||||
+import org.bukkit.entity.HumanEntity;
|
||||
+// CraftBukkit end
|
||||
|
||||
public class DispenserBlockEntity extends RandomizableContainerBlockEntity {
|
||||
|
||||
public static final int CONTAINER_SIZE = 9;
|
||||
private NonNullList<ItemStack> items;
|
||||
|
||||
+ // CraftBukkit start - add fields and methods
|
||||
+ public List<HumanEntity> transaction = new java.util.ArrayList<HumanEntity>();
|
||||
+ private int maxStack = MAX_STACK;
|
||||
+
|
||||
+ public List<ItemStack> getContents() {
|
||||
+ return this.items;
|
||||
+ }
|
||||
+
|
||||
+ public void onOpen(CraftHumanEntity who) {
|
||||
+ this.transaction.add(who);
|
||||
+ }
|
||||
+
|
||||
+ public void onClose(CraftHumanEntity who) {
|
||||
+ this.transaction.remove(who);
|
||||
+ }
|
||||
+
|
||||
+ public List<HumanEntity> getViewers() {
|
||||
+ return this.transaction;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public int getMaxStackSize() {
|
||||
+ return this.maxStack;
|
||||
+ }
|
||||
+
|
||||
+ public void setMaxStackSize(int size) {
|
||||
+ this.maxStack = size;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
protected DispenserBlockEntity(BlockEntityType<?> type, BlockPos pos, BlockState state) {
|
||||
super(type, pos, state);
|
||||
this.items = NonNullList.withSize(9, ItemStack.EMPTY);
|
|
@ -1,164 +0,0 @@
|
|||
--- a/net/minecraft/world/level/block/entity/LecternBlockEntity.java
|
||||
+++ b/net/minecraft/world/level/block/entity/LecternBlockEntity.java
|
||||
@@ -28,6 +28,17 @@
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.phys.Vec2;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
+// CraftBukkit start
|
||||
+import java.util.ArrayList;
|
||||
+import java.util.Arrays;
|
||||
+import java.util.List;
|
||||
+import org.bukkit.Location;
|
||||
+import org.bukkit.block.Lectern;
|
||||
+import org.bukkit.craftbukkit.entity.CraftHumanEntity;
|
||||
+import org.bukkit.craftbukkit.util.CraftLocation;
|
||||
+import org.bukkit.entity.HumanEntity;
|
||||
+import org.bukkit.inventory.InventoryHolder;
|
||||
+// CraftBukkit end
|
||||
|
||||
public class LecternBlockEntity extends BlockEntity implements Clearable, MenuProvider {
|
||||
|
||||
@@ -35,8 +46,55 @@
|
||||
public static final int NUM_DATA = 1;
|
||||
public static final int SLOT_BOOK = 0;
|
||||
public static final int NUM_SLOTS = 1;
|
||||
- public final Container bookAccess = new Container() {
|
||||
+ // CraftBukkit start - add fields and methods
|
||||
+ public final Container bookAccess = new LecternInventory();
|
||||
+ public class LecternInventory implements Container {
|
||||
+
|
||||
+ public List<HumanEntity> transaction = new ArrayList<>();
|
||||
+ private int maxStack = 1;
|
||||
+
|
||||
@Override
|
||||
+ public List<ItemStack> getContents() {
|
||||
+ return Arrays.asList(LecternBlockEntity.this.book);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void onOpen(CraftHumanEntity who) {
|
||||
+ this.transaction.add(who);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void onClose(CraftHumanEntity who) {
|
||||
+ this.transaction.remove(who);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public List<HumanEntity> getViewers() {
|
||||
+ return this.transaction;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setMaxStackSize(int i) {
|
||||
+ this.maxStack = i;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public Location getLocation() {
|
||||
+ if (LecternBlockEntity.this.level == null) return null;
|
||||
+ return CraftLocation.toBukkit(LecternBlockEntity.this.worldPosition, LecternBlockEntity.this.level.getWorld());
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public InventoryHolder getOwner() {
|
||||
+ return (Lectern) LecternBlockEntity.this.getOwner();
|
||||
+ }
|
||||
+
|
||||
+ public LecternBlockEntity getLectern() {
|
||||
+ return LecternBlockEntity.this;
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
+ @Override
|
||||
public int getContainerSize() {
|
||||
return 1;
|
||||
}
|
||||
@@ -80,11 +138,20 @@
|
||||
}
|
||||
|
||||
@Override
|
||||
- public void setItem(int slot, ItemStack stack) {}
|
||||
+ // CraftBukkit start
|
||||
+ public void setItem(int slot, ItemStack stack) {
|
||||
+ if (slot == 0) {
|
||||
+ LecternBlockEntity.this.setBook(stack);
|
||||
+ if (LecternBlockEntity.this.getLevel() != null) {
|
||||
+ LecternBlock.resetBookState(null, LecternBlockEntity.this.getLevel(), LecternBlockEntity.this.getBlockPos(), LecternBlockEntity.this.getBlockState(), LecternBlockEntity.this.hasBook());
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
|
||||
@Override
|
||||
public int getMaxStackSize() {
|
||||
- return 1;
|
||||
+ return this.maxStack; // CraftBukkit
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -164,7 +231,7 @@
|
||||
if (j != this.page) {
|
||||
this.page = j;
|
||||
this.setChanged();
|
||||
- LecternBlock.signalPageChange(this.getLevel(), this.getBlockPos(), this.getBlockState());
|
||||
+ if (this.level != null) LecternBlock.signalPageChange(this.getLevel(), this.getBlockPos(), this.getBlockState()); // CraftBukkit
|
||||
}
|
||||
|
||||
}
|
||||
@@ -189,6 +256,35 @@
|
||||
return book;
|
||||
}
|
||||
|
||||
+ // CraftBukkit start
|
||||
+ private final CommandSource commandSource = new CommandSource() {
|
||||
+
|
||||
+ @Override
|
||||
+ public void sendSystemMessage(Component message) {
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public org.bukkit.command.CommandSender getBukkitSender(CommandSourceStack wrapper) {
|
||||
+ return wrapper.getEntity() != null ? wrapper.getEntity().getBukkitEntity() : new org.bukkit.craftbukkit.command.CraftBlockCommandSender(wrapper, LecternBlockEntity.this);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean acceptsSuccess() {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean acceptsFailure() {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean shouldInformAdmins() {
|
||||
+ return false;
|
||||
+ }
|
||||
+ };
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
private CommandSourceStack createCommandSourceStack(@Nullable Player player, ServerLevel world) {
|
||||
String s;
|
||||
Object object;
|
||||
@@ -203,7 +299,8 @@
|
||||
|
||||
Vec3 vec3d = Vec3.atCenterOf(this.worldPosition);
|
||||
|
||||
- return new CommandSourceStack(CommandSource.NULL, vec3d, Vec2.ZERO, world, 2, s, (Component) object, world.getServer(), player);
|
||||
+ // CraftBukkit - commandSource
|
||||
+ return new CommandSourceStack(this.commandSource, vec3d, Vec2.ZERO, world, 2, s, (Component) object, world.getServer(), player);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -236,7 +333,7 @@
|
||||
|
||||
@Override
|
||||
public AbstractContainerMenu createMenu(int syncId, Inventory playerInventory, Player player) {
|
||||
- return new LecternMenu(syncId, this.bookAccess, this.dataAccess);
|
||||
+ return new LecternMenu(syncId, this.bookAccess, this.dataAccess, playerInventory); // CraftBukkit
|
||||
}
|
||||
|
||||
@Override
|
|
@ -1,269 +0,0 @@
|
|||
--- a/net/minecraft/world/level/block/entity/SignBlockEntity.java
|
||||
+++ b/net/minecraft/world/level/block/entity/SignBlockEntity.java
|
||||
@@ -22,12 +22,12 @@
|
||||
import net.minecraft.network.chat.Style;
|
||||
import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
+import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.server.network.FilteredText;
|
||||
import net.minecraft.sounds.SoundEvent;
|
||||
import net.minecraft.sounds.SoundEvents;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
-import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.SignBlock;
|
||||
@@ -35,6 +35,12 @@
|
||||
import net.minecraft.world.phys.Vec2;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import org.slf4j.Logger;
|
||||
+import org.bukkit.block.sign.Side;
|
||||
+import org.bukkit.craftbukkit.block.CraftBlock;
|
||||
+import org.bukkit.craftbukkit.util.CraftChatMessage;
|
||||
+import org.bukkit.entity.Player;
|
||||
+import org.bukkit.event.block.SignChangeEvent;
|
||||
+// CraftBukkit end
|
||||
|
||||
public class SignBlockEntity extends BlockEntity {
|
||||
|
||||
@@ -61,13 +67,18 @@
|
||||
return new SignText();
|
||||
}
|
||||
|
||||
- public boolean isFacingFrontText(Player player) {
|
||||
+ public boolean isFacingFrontText(net.minecraft.world.entity.player.Player player) {
|
||||
+ // Paper start - More Sign Block API
|
||||
+ return this.isFacingFrontText(player.getX(), player.getZ());
|
||||
+ }
|
||||
+ public boolean isFacingFrontText(double x, double z) {
|
||||
+ // Paper end - More Sign Block API
|
||||
Block block = this.getBlockState().getBlock();
|
||||
|
||||
if (block instanceof SignBlock blocksign) {
|
||||
Vec3 vec3d = blocksign.getSignHitboxCenterPosition(this.getBlockState());
|
||||
- double d0 = player.getX() - ((double) this.getBlockPos().getX() + vec3d.x);
|
||||
- double d1 = player.getZ() - ((double) this.getBlockPos().getZ() + vec3d.z);
|
||||
+ double d0 = x - ((double) this.getBlockPos().getX() + vec3d.x); // Paper - More Sign Block API
|
||||
+ double d1 = z - ((double) this.getBlockPos().getZ() + vec3d.z); // Paper - More Sign Block API
|
||||
float f = blocksign.getYRotationDegrees(this.getBlockState());
|
||||
float f1 = (float) (Mth.atan2(d1, d0) * 57.2957763671875D) - 90.0F;
|
||||
|
||||
@@ -101,7 +112,7 @@
|
||||
protected void saveAdditional(CompoundTag nbt, HolderLookup.Provider registries) {
|
||||
super.saveAdditional(nbt, registries);
|
||||
DynamicOps<Tag> dynamicops = registries.createSerializationContext(NbtOps.INSTANCE);
|
||||
- DataResult dataresult = SignText.DIRECT_CODEC.encodeStart(dynamicops, this.frontText);
|
||||
+ DataResult<Tag> dataresult = SignText.DIRECT_CODEC.encodeStart(dynamicops, this.frontText); // CraftBukkit - decompile error
|
||||
Logger logger = SignBlockEntity.LOGGER;
|
||||
|
||||
Objects.requireNonNull(logger);
|
||||
@@ -121,7 +132,7 @@
|
||||
protected void loadAdditional(CompoundTag nbt, HolderLookup.Provider registries) {
|
||||
super.loadAdditional(nbt, registries);
|
||||
DynamicOps<Tag> dynamicops = registries.createSerializationContext(NbtOps.INSTANCE);
|
||||
- DataResult dataresult;
|
||||
+ DataResult<SignText> dataresult; // CraftBukkit - decompile error
|
||||
Logger logger;
|
||||
|
||||
if (nbt.contains("front_text")) {
|
||||
@@ -161,7 +172,7 @@
|
||||
|
||||
if (world instanceof ServerLevel worldserver) {
|
||||
try {
|
||||
- return ComponentUtils.updateForEntity(SignBlockEntity.createCommandSourceStack((Player) null, worldserver, this.worldPosition), text, (Entity) null, 0);
|
||||
+ return ComponentUtils.updateForEntity(this.createCommandSourceStack((net.minecraft.world.entity.player.Player) null, worldserver, this.worldPosition), text, (Entity) null, 0);
|
||||
} catch (CommandSyntaxException commandsyntaxexception) {
|
||||
;
|
||||
}
|
||||
@@ -170,15 +181,17 @@
|
||||
return text;
|
||||
}
|
||||
|
||||
- public void updateSignText(Player player, boolean front, List<FilteredText> messages) {
|
||||
+ public void updateSignText(net.minecraft.world.entity.player.Player player, boolean front, List<FilteredText> messages) {
|
||||
if (!this.isWaxed() && player.getUUID().equals(this.getPlayerWhoMayEdit()) && this.level != null) {
|
||||
this.updateText((signtext) -> {
|
||||
- return this.setMessages(player, messages, signtext);
|
||||
+ return this.setMessages(player, messages, signtext, front); // CraftBukkit
|
||||
}, front);
|
||||
this.setAllowedPlayerEditor((UUID) null);
|
||||
this.level.sendBlockUpdated(this.getBlockPos(), this.getBlockState(), this.getBlockState(), 3);
|
||||
} else {
|
||||
SignBlockEntity.LOGGER.warn("Player {} just tried to change non-editable sign", player.getName().getString());
|
||||
+ if (player.distanceToSqr(this.getBlockPos().getX(), this.getBlockPos().getY(), this.getBlockPos().getZ()) < 32 * 32) // Paper - Dont send far away sign update
|
||||
+ ((ServerPlayer) player).connection.send(this.getUpdatePacket()); // CraftBukkit
|
||||
}
|
||||
}
|
||||
|
||||
@@ -188,19 +201,43 @@
|
||||
return this.setText((SignText) textChanger.apply(signtext), front);
|
||||
}
|
||||
|
||||
- private SignText setMessages(Player player, List<FilteredText> messages, SignText text) {
|
||||
- for (int i = 0; i < messages.size(); ++i) {
|
||||
- FilteredText filteredtext = (FilteredText) messages.get(i);
|
||||
- Style chatmodifier = text.getMessage(i, player.isTextFilteringEnabled()).getStyle();
|
||||
+ private SignText setMessages(net.minecraft.world.entity.player.Player entityhuman, List<FilteredText> list, SignText signtext, boolean front) { // CraftBukkit
|
||||
+ SignText originalText = signtext; // CraftBukkit
|
||||
+ for (int i = 0; i < list.size(); ++i) {
|
||||
+ FilteredText filteredtext = (FilteredText) list.get(i);
|
||||
+ Style chatmodifier = signtext.getMessage(i, entityhuman.isTextFilteringEnabled()).getStyle();
|
||||
|
||||
- if (player.isTextFilteringEnabled()) {
|
||||
- text = text.setMessage(i, Component.literal(filteredtext.filteredOrEmpty()).setStyle(chatmodifier));
|
||||
+ if (entityhuman.isTextFilteringEnabled()) {
|
||||
+ signtext = signtext.setMessage(i, Component.literal(net.minecraft.util.StringUtil.filterText(filteredtext.filteredOrEmpty())).setStyle(chatmodifier)); // Paper - filter sign text to chat only
|
||||
} else {
|
||||
- text = text.setMessage(i, Component.literal(filteredtext.raw()).setStyle(chatmodifier), Component.literal(filteredtext.filteredOrEmpty()).setStyle(chatmodifier));
|
||||
+ signtext = signtext.setMessage(i, Component.literal(net.minecraft.util.StringUtil.filterText(filteredtext.raw())).setStyle(chatmodifier), Component.literal(net.minecraft.util.StringUtil.filterText(filteredtext.filteredOrEmpty())).setStyle(chatmodifier)); // Paper - filter sign text to chat only
|
||||
}
|
||||
}
|
||||
|
||||
- return text;
|
||||
+ // CraftBukkit start
|
||||
+ Player player = ((ServerPlayer) entityhuman).getBukkitEntity();
|
||||
+ List<net.kyori.adventure.text.Component> lines = new java.util.ArrayList<>(); // Paper - adventure
|
||||
+
|
||||
+ for (int i = 0; i < list.size(); ++i) {
|
||||
+ lines.add(io.papermc.paper.adventure.PaperAdventure.asAdventure(signtext.getMessage(i, entityhuman.isTextFilteringEnabled()))); // Paper - Adventure
|
||||
+ }
|
||||
+
|
||||
+ SignChangeEvent event = new SignChangeEvent(CraftBlock.at(this.level, this.worldPosition), player, new java.util.ArrayList<>(lines), (front) ? Side.FRONT : Side.BACK); // Paper - Adventure
|
||||
+ entityhuman.level().getCraftServer().getPluginManager().callEvent(event);
|
||||
+
|
||||
+ if (event.isCancelled()) {
|
||||
+ return originalText;
|
||||
+ }
|
||||
+
|
||||
+ Component[] components = org.bukkit.craftbukkit.block.CraftSign.sanitizeLines(event.lines()); // Paper - Adventure
|
||||
+ for (int i = 0; i < components.length; i++) {
|
||||
+ if (!Objects.equals(lines.get(i), event.line(i))) { // Paper - Adventure
|
||||
+ signtext = signtext.setMessage(i, components[i]);
|
||||
+ }
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
+ return signtext;
|
||||
}
|
||||
|
||||
public boolean setText(SignText text, boolean front) {
|
||||
@@ -227,11 +264,11 @@
|
||||
}
|
||||
}
|
||||
|
||||
- public boolean canExecuteClickCommands(boolean front, Player player) {
|
||||
+ public boolean canExecuteClickCommands(boolean front, net.minecraft.world.entity.player.Player player) {
|
||||
return this.isWaxed() && this.getText(front).hasAnyClickCommands(player);
|
||||
}
|
||||
|
||||
- public boolean executeClickCommandsIfPresent(Player player, Level world, BlockPos pos, boolean front) {
|
||||
+ public boolean executeClickCommandsIfPresent(net.minecraft.world.entity.player.Player player, Level world, BlockPos pos, boolean front) {
|
||||
boolean flag1 = false;
|
||||
Component[] aichatbasecomponent = this.getText(front).getMessages(player.isTextFilteringEnabled());
|
||||
int i = aichatbasecomponent.length;
|
||||
@@ -242,7 +279,17 @@
|
||||
ClickEvent chatclickable = chatmodifier.getClickEvent();
|
||||
|
||||
if (chatclickable != null && chatclickable.getAction() == ClickEvent.Action.RUN_COMMAND) {
|
||||
- player.getServer().getCommands().performPrefixedCommand(SignBlockEntity.createCommandSourceStack(player, world, pos), chatclickable.getValue());
|
||||
+ // Paper start - Fix commands from signs not firing command events
|
||||
+ String command = chatclickable.getValue().startsWith("/") ? chatclickable.getValue() : "/" + chatclickable.getValue();
|
||||
+ if (org.spigotmc.SpigotConfig.logCommands) {
|
||||
+ LOGGER.info("{} issued server command: {}", player.getScoreboardName(), command);
|
||||
+ }
|
||||
+ io.papermc.paper.event.player.PlayerSignCommandPreprocessEvent event = new io.papermc.paper.event.player.PlayerSignCommandPreprocessEvent((org.bukkit.entity.Player) player.getBukkitEntity(), command, new org.bukkit.craftbukkit.util.LazyPlayerSet(player.getServer()), (org.bukkit.block.Sign) CraftBlock.at(this.level, this.worldPosition).getState(), front ? Side.FRONT : Side.BACK);
|
||||
+ if (!event.callEvent()) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ player.getServer().getCommands().performPrefixedCommand(this.createCommandSourceStack(((org.bukkit.craftbukkit.entity.CraftPlayer) event.getPlayer()).getHandle(), world, pos), event.getMessage());
|
||||
+ // Paper end - Fix commands from signs not firing command events
|
||||
flag1 = true;
|
||||
}
|
||||
}
|
||||
@@ -250,11 +297,55 @@
|
||||
return flag1;
|
||||
}
|
||||
|
||||
- private static CommandSourceStack createCommandSourceStack(@Nullable Player player, Level world, BlockPos pos) {
|
||||
+ // CraftBukkit start
|
||||
+ private final CommandSource commandSource = new CommandSource() {
|
||||
+
|
||||
+ @Override
|
||||
+ public void sendSystemMessage(Component message) {}
|
||||
+
|
||||
+ @Override
|
||||
+ public org.bukkit.command.CommandSender getBukkitSender(CommandSourceStack wrapper) {
|
||||
+ return wrapper.getEntity() != null ? wrapper.getEntity().getBukkitEntity() : new org.bukkit.craftbukkit.command.CraftBlockCommandSender(wrapper, SignBlockEntity.this);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean acceptsSuccess() {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean acceptsFailure() {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean shouldInformAdmins() {
|
||||
+ return false;
|
||||
+ }
|
||||
+ };
|
||||
+
|
||||
+ private CommandSourceStack createCommandSourceStack(@Nullable net.minecraft.world.entity.player.Player player, Level world, BlockPos pos) {
|
||||
+ // CraftBukkit end
|
||||
String s = player == null ? "Sign" : player.getName().getString();
|
||||
Object object = player == null ? Component.literal("Sign") : player.getDisplayName();
|
||||
|
||||
- return new CommandSourceStack(CommandSource.NULL, Vec3.atCenterOf(pos), Vec2.ZERO, (ServerLevel) world, 2, s, (Component) object, world.getServer(), player);
|
||||
+ // Paper start - Fix commands from signs not firing command events
|
||||
+ CommandSource commandSource = this.level.paperConfig().misc.showSignClickCommandFailureMsgsToPlayer ? new io.papermc.paper.commands.DelegatingCommandSource(this.commandSource) {
|
||||
+ @Override
|
||||
+ public void sendSystemMessage(Component message) {
|
||||
+ if (player instanceof final ServerPlayer serverPlayer) {
|
||||
+ serverPlayer.sendSystemMessage(message);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean acceptsFailure() {
|
||||
+ return true;
|
||||
+ }
|
||||
+ } : this.commandSource;
|
||||
+ // Paper end - Fix commands from signs not firing command events
|
||||
+ // CraftBukkit - this
|
||||
+ return new CommandSourceStack(commandSource, Vec3.atCenterOf(pos), Vec2.ZERO, (ServerLevel) world, 2, s, (Component) object, world.getServer(), player); // Paper - Fix commands from signs not firing command events
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -273,12 +364,17 @@
|
||||
|
||||
@Nullable
|
||||
public UUID getPlayerWhoMayEdit() {
|
||||
+ // CraftBukkit start - unnecessary sign ticking removed, so do this lazily
|
||||
+ if (this.level != null && this.playerWhoMayEdit != null) {
|
||||
+ this.clearInvalidPlayerWhoMayEdit(this, this.level, this.playerWhoMayEdit);
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
return this.playerWhoMayEdit;
|
||||
}
|
||||
|
||||
private void markUpdated() {
|
||||
this.setChanged();
|
||||
- this.level.sendBlockUpdated(this.getBlockPos(), this.getBlockState(), this.getBlockState(), 3);
|
||||
+ if (this.level != null) this.level.sendBlockUpdated(this.getBlockPos(), this.getBlockState(), this.getBlockState(), 3); // CraftBukkit - skip notify if world is null (SPIGOT-5122)
|
||||
}
|
||||
|
||||
public boolean isWaxed() {
|
||||
@@ -296,7 +392,7 @@
|
||||
}
|
||||
|
||||
public boolean playerIsTooFarAwayToEdit(UUID uuid) {
|
||||
- Player entityhuman = this.level.getPlayerByUUID(uuid);
|
||||
+ net.minecraft.world.entity.player.Player entityhuman = this.level.getPlayerByUUID(uuid);
|
||||
|
||||
return entityhuman == null || !entityhuman.canInteractWithBlock(this.getBlockPos(), 4.0D);
|
||||
}
|
Loading…
Reference in a new issue