mirror of
https://github.com/PaperMC/Paper.git
synced 2026-11-04 17:00:09 -05:00
Compare commits
3
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b2427de904 | ||
|
|
54bca1973c | ||
|
|
ec466edd5f |
No files matched your search
@@ -6,9 +6,11 @@ import io.papermc.paper.datacomponent.item.AttackRange;
|
||||
import io.papermc.paper.datacomponent.item.BannerPatternLayers;
|
||||
import io.papermc.paper.datacomponent.item.BlockItemDataProperties;
|
||||
import io.papermc.paper.datacomponent.item.BlocksAttacks;
|
||||
import io.papermc.paper.datacomponent.item.BrewingFuel;
|
||||
import io.papermc.paper.datacomponent.item.BundleContents;
|
||||
import io.papermc.paper.datacomponent.item.ChargedProjectiles;
|
||||
import io.papermc.paper.datacomponent.item.Consumable;
|
||||
import io.papermc.paper.datacomponent.item.CookingFuel;
|
||||
import io.papermc.paper.datacomponent.item.CustomModelData;
|
||||
import io.papermc.paper.datacomponent.item.DamageResistant;
|
||||
import io.papermc.paper.datacomponent.item.DeathProtection;
|
||||
@@ -401,6 +403,14 @@ public final class DataComponentTypes {
|
||||
public static final DataComponentType.Valued<SignText> SIGN_TEXT_BACK = valued("sign_text_back");
|
||||
public static final DataComponentType.NonValued WAXED = unvalued("waxed");
|
||||
public static final DataComponentType.Valued<DyeColor> CUSHION_COLOR = valued("cushion/color");
|
||||
/**
|
||||
* Describes an item that can be used as fuel for a furnace, smoker or blast furnace.
|
||||
*/
|
||||
public static final DataComponentType.Valued<CookingFuel> COOKING_FUEL = valued("cooking_fuel");
|
||||
/**
|
||||
* Describes an item that can be used as fuel for a brewing stand.
|
||||
*/
|
||||
public static final DataComponentType.Valued<BrewingFuel> BREWING_FUEL = valued("brewing_fuel");
|
||||
|
||||
private static DataComponentType.NonValued unvalued(@KeyPattern.Value final String key) {
|
||||
final DataComponentType dataComponentType = Registry.DATA_COMPONENT_TYPE.getOrThrow(Key.key(Key.MINECRAFT_NAMESPACE, key));
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
package io.papermc.paper.datacomponent.item;
|
||||
|
||||
import io.papermc.paper.datacomponent.DataComponentBuilder;
|
||||
import io.papermc.paper.loot.number.ResolvableFloat;
|
||||
import io.papermc.paper.loot.number.ResolvableInt;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
|
||||
/**
|
||||
* Describes an item that can be used as fuel for a brewing stand.
|
||||
*
|
||||
* @see io.papermc.paper.datacomponent.DataComponentTypes#BREWING_FUEL
|
||||
*/
|
||||
@ApiStatus.NonExtendable
|
||||
public interface BrewingFuel {
|
||||
|
||||
@Contract(value = "-> new", pure = true)
|
||||
static BrewingFuel.Builder brewingFuel() {
|
||||
return ItemComponentTypesBridge.bridge().brewingFuel();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the number of times this fuel will brew before being consumed
|
||||
*/
|
||||
@Contract(pure = true)
|
||||
ResolvableInt uses();
|
||||
|
||||
/**
|
||||
* @return the speed of the brewing
|
||||
*/
|
||||
@Contract(pure = true)
|
||||
ResolvableFloat speedMultiplier();
|
||||
|
||||
/**
|
||||
* Builder for {@link BrewingFuel}.
|
||||
*/
|
||||
@ApiStatus.NonExtendable
|
||||
interface Builder extends DataComponentBuilder<BrewingFuel> {
|
||||
|
||||
/**
|
||||
* @param uses the number of times this fuel will brew before being consumed
|
||||
* @return the builder for chaining
|
||||
* @see #uses()
|
||||
*/
|
||||
@Contract(value = "_ -> this", mutates = "this")
|
||||
Builder uses(int uses);
|
||||
|
||||
/**
|
||||
* @param speedMultiplier the speed of the brewing
|
||||
* @return the builder for chaining
|
||||
* @see #speedMultiplier()
|
||||
*/
|
||||
@Contract(value = "_ -> this", mutates = "this")
|
||||
Builder speedMultiplier(float speedMultiplier);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package io.papermc.paper.datacomponent.item;
|
||||
|
||||
import io.papermc.paper.datacomponent.DataComponentBuilder;
|
||||
import io.papermc.paper.loot.number.ResolvableFloat;
|
||||
import io.papermc.paper.loot.number.ResolvableInt;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
|
||||
/**
|
||||
* Describes an item that can be used as fuel for a furnace, smoker or blast furnace.
|
||||
*
|
||||
* @see io.papermc.paper.datacomponent.DataComponentTypes#COOKING_FUEL
|
||||
*/
|
||||
@ApiStatus.NonExtendable
|
||||
public interface CookingFuel {
|
||||
|
||||
@Contract(value = "-> new", pure = true)
|
||||
static CookingFuel.Builder cookingFuel() {
|
||||
return ItemComponentTypesBridge.bridge().cookingFuel();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the time, in ticks, for which this fuel will burn
|
||||
*/
|
||||
@Contract(pure = true)
|
||||
ResolvableInt burnTime();
|
||||
|
||||
/**
|
||||
* @return the speed of the cooking/smelting
|
||||
*/
|
||||
@Contract(pure = true)
|
||||
ResolvableFloat speedMultiplier();
|
||||
|
||||
/**
|
||||
* Builder for {@link CookingFuel}.
|
||||
*/
|
||||
@ApiStatus.NonExtendable
|
||||
interface Builder extends DataComponentBuilder<CookingFuel> {
|
||||
|
||||
/**
|
||||
* @param speedMultiplier the speed of the cooking/smelting
|
||||
* @return the builder for chaining
|
||||
* @see #speedMultiplier()
|
||||
*/
|
||||
@Contract(value = "_ -> this", mutates = "this")
|
||||
Builder speedMultiplier(float speedMultiplier);
|
||||
|
||||
/**
|
||||
* @param burnTime the time, in ticks, for which this fuel will burn
|
||||
* @return the builder for chaining
|
||||
* @see #speedMultiplier()
|
||||
*/
|
||||
@Contract(value = "_ -> this", mutates = "this")
|
||||
Builder burnTime(int burnTime);
|
||||
}
|
||||
}
|
||||
+4
@@ -131,4 +131,8 @@ interface ItemComponentTypesBridge {
|
||||
VillagerFood villagerFood(int nutrition);
|
||||
|
||||
SignText.Builder signText();
|
||||
|
||||
BrewingFuel.Builder brewingFuel();
|
||||
|
||||
CookingFuel.Builder cookingFuel();
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package io.papermc.paper.loot.number;
|
||||
|
||||
import org.bukkit.loot.LootContext;
|
||||
|
||||
/**
|
||||
* Represents a floating point number that can be resolved against a {@link LootContext}.
|
||||
*/
|
||||
public interface ResolvableFloat {
|
||||
|
||||
/**
|
||||
* Resolves this floating point number against the given loot context.
|
||||
*
|
||||
* @param context the loot context to resolve against.
|
||||
* @param defaultValue the default value
|
||||
* @return the resolved number
|
||||
*/
|
||||
float resolve(LootContext context, float defaultValue);
|
||||
|
||||
/**
|
||||
* Represents a constant {@link ResolvableFloat}.
|
||||
*/
|
||||
interface Constant extends ResolvableFloat {
|
||||
|
||||
/**
|
||||
* @return the constant value
|
||||
*/
|
||||
float getValue();
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
default float resolve(LootContext context, float defaultValue) {
|
||||
return this.getValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package io.papermc.paper.loot.number;
|
||||
|
||||
import org.bukkit.loot.LootContext;
|
||||
|
||||
/**
|
||||
* Represents an integer number that can be resolved against a {@link LootContext}.
|
||||
*/
|
||||
public interface ResolvableInt {
|
||||
|
||||
/**
|
||||
* Resolves this integer number against the given loot context.
|
||||
*
|
||||
* @param context the loot context to resolve against.
|
||||
* @param defaultValue the default value
|
||||
* @return the resolved number
|
||||
*/
|
||||
int resolve(LootContext context, int defaultValue);
|
||||
|
||||
/**
|
||||
* Represents a constant {@link ResolvableInt}.
|
||||
*/
|
||||
interface Constant extends ResolvableInt {
|
||||
|
||||
/**
|
||||
* @return the constant value
|
||||
*/
|
||||
int getValue();
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
default int resolve(LootContext context, int defaultValue) {
|
||||
return this.getValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
/**
|
||||
* Package containing maths-related API, including position API.
|
||||
*/
|
||||
@NullMarked
|
||||
@ApiStatus.Experimental
|
||||
package io.papermc.paper.loot.number;
|
||||
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
--- a/net/minecraft/world/level/storage/loot/parameters/LootContextParamSets.java
|
||||
+++ b/net/minecraft/world/level/storage/loot/parameters/LootContextParamSets.java
|
||||
@@ -35,6 +_,27 @@
|
||||
.required(LootContextParams.ENCHANTMENT_ACTIVE)
|
||||
.required(LootContextParams.ENCHANTMENT_LEVEL)
|
||||
);
|
||||
+ // Paper start
|
||||
+ public static final ContextKeySet ALL_PARAMS_OPTIONAL = register(
|
||||
+ "generic_optional",
|
||||
+ builder -> builder.optional(LootContextParams.THIS_ENTITY)
|
||||
+ .optional(LootContextParams.LAST_DAMAGE_PLAYER)
|
||||
+ .optional(LootContextParams.DAMAGE_SOURCE)
|
||||
+ .optional(LootContextParams.ATTACKING_ENTITY)
|
||||
+ .optional(LootContextParams.DIRECT_ATTACKING_ENTITY)
|
||||
+ .optional(LootContextParams.ORIGIN)
|
||||
+ .optional(LootContextParams.BLOCK_STATE)
|
||||
+ .optional(LootContextParams.BLOCK_ENTITY)
|
||||
+ .optional(LootContextParams.TOOL)
|
||||
+ .optional(LootContextParams.EXPLOSION_RADIUS)
|
||||
+ .optional(LootContextParams.ADDITIONAL_COST_COMPONENT_ALLOWED)
|
||||
+ .optional(LootContextParams.CONTAINER)
|
||||
+ .optional(LootContextParams.INTERACTING_ENTITY)
|
||||
+ .optional(LootContextParams.TARGET_ENTITY)
|
||||
+ .optional(LootContextParams.ENCHANTMENT_ACTIVE)
|
||||
+ .optional(LootContextParams.ENCHANTMENT_LEVEL)
|
||||
+ );
|
||||
+ // Paper end
|
||||
public static final ContextKeySet CHEST = register("chest", builder -> builder.required(LootContextParams.ORIGIN).optional(LootContextParams.THIS_ENTITY));
|
||||
public static final ContextKeySet COMMAND = register(
|
||||
"command", builder -> builder.required(LootContextParams.ORIGIN).optional(LootContextParams.THIS_ENTITY)
|
||||
@@ -194,5 +_,11 @@
|
||||
if (!missingFromAllParams.isEmpty()) {
|
||||
throw new IllegalStateException("Missing parameters from 'all_params': " + missingFromAllParams);
|
||||
}
|
||||
+ // Paper start
|
||||
+ Set<ContextKey<?>> missingFromAllParamsOptional = Sets.difference(allParams, ALL_PARAMS_OPTIONAL.allowed());
|
||||
+ if (!missingFromAllParamsOptional.isEmpty()) {
|
||||
+ throw new IllegalStateException("Missing parameters from 'all_params_optional': " + missingFromAllParamsOptional);
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
||||
}
|
||||
@@ -6,9 +6,11 @@ import io.papermc.paper.datacomponent.item.PaperAttackRange;
|
||||
import io.papermc.paper.datacomponent.item.PaperBannerPatternLayers;
|
||||
import io.papermc.paper.datacomponent.item.PaperBlockItemDataProperties;
|
||||
import io.papermc.paper.datacomponent.item.PaperBlocksAttacks;
|
||||
import io.papermc.paper.datacomponent.item.PaperBrewingFuel;
|
||||
import io.papermc.paper.datacomponent.item.PaperBundleContents;
|
||||
import io.papermc.paper.datacomponent.item.PaperChargedProjectiles;
|
||||
import io.papermc.paper.datacomponent.item.PaperConsumable;
|
||||
import io.papermc.paper.datacomponent.item.PaperCookingFuel;
|
||||
import io.papermc.paper.datacomponent.item.PaperCustomModelData;
|
||||
import io.papermc.paper.datacomponent.item.PaperDamageResistant;
|
||||
import io.papermc.paper.datacomponent.item.PaperDeathProtection;
|
||||
@@ -226,6 +228,8 @@ public final class DataComponentAdapters {
|
||||
register(DataComponents.SIGN_TEXT_BACK, PaperSignText::new);
|
||||
registerUntyped(DataComponents.WAXED);
|
||||
register(DataComponents.CUSHION_COLOR, nms -> DyeColor.getByWoolData((byte) nms.getId()), api -> net.minecraft.world.item.DyeColor.byId(api.getWoolData()));
|
||||
register(DataComponents.COOKING_FUEL, PaperCookingFuel::new);
|
||||
register(DataComponents.BREWING_FUEL, PaperBrewingFuel::new);
|
||||
|
||||
for (final ResourceKey<DataComponentType<?>> key : BuiltInRegistries.DATA_COMPONENT_TYPE.registryKeySet()) {
|
||||
if (!ADAPTERS.containsKey(key)) {
|
||||
|
||||
+9
@@ -307,4 +307,13 @@ public final class ItemComponentTypesBridgesImpl implements ItemComponentTypesBr
|
||||
public SignText.Builder signText() {
|
||||
return new PaperSignText.BuilderImpl();
|
||||
}
|
||||
@Override
|
||||
public BrewingFuel.Builder brewingFuel() {
|
||||
return new PaperBrewingFuel.BuilderImpl();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CookingFuel.Builder cookingFuel() {
|
||||
return new PaperCookingFuel.BuilderImpl();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package io.papermc.paper.datacomponent.item;
|
||||
|
||||
import io.papermc.paper.loot.number.PaperResolvableFloat;
|
||||
import io.papermc.paper.loot.number.PaperResolvableInt;
|
||||
import net.minecraft.world.level.storage.loot.providers.number.floats.ResolvableFloat;
|
||||
import net.minecraft.world.level.storage.loot.providers.number.ints.ResolvableInt;
|
||||
import org.bukkit.craftbukkit.util.Handleable;
|
||||
|
||||
public record PaperBrewingFuel(
|
||||
net.minecraft.world.item.component.BrewingFuel impl
|
||||
) implements BrewingFuel, Handleable<net.minecraft.world.item.component.BrewingFuel> {
|
||||
|
||||
@Override
|
||||
public net.minecraft.world.item.component.BrewingFuel getHandle() {
|
||||
return this.impl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public io.papermc.paper.loot.number.ResolvableInt uses() {
|
||||
return PaperResolvableInt.fromVanilla(this.impl.uses());
|
||||
}
|
||||
|
||||
@Override
|
||||
public io.papermc.paper.loot.number.ResolvableFloat speedMultiplier() {
|
||||
return PaperResolvableFloat.fromVanilla(this.impl.speedMultiplier());
|
||||
}
|
||||
|
||||
static final class BuilderImpl implements BrewingFuel.Builder {
|
||||
|
||||
private int uses = 0;
|
||||
private float speedMultiplier = 1.0F;
|
||||
|
||||
@Override
|
||||
public Builder uses(int uses) {
|
||||
this.uses = uses;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder speedMultiplier(float speedMultiplier) {
|
||||
this.speedMultiplier = speedMultiplier;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BrewingFuel build() {
|
||||
return new PaperBrewingFuel(
|
||||
new net.minecraft.world.item.component.BrewingFuel(
|
||||
new ResolvableInt.Constant(this.uses),
|
||||
new ResolvableFloat.Constant(this.speedMultiplier)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package io.papermc.paper.datacomponent.item;
|
||||
|
||||
import io.papermc.paper.loot.number.PaperResolvableFloat;
|
||||
import io.papermc.paper.loot.number.PaperResolvableInt;
|
||||
import net.minecraft.world.level.storage.loot.providers.number.floats.ResolvableFloat;
|
||||
import net.minecraft.world.level.storage.loot.providers.number.ints.ResolvableInt;
|
||||
import org.bukkit.craftbukkit.util.Handleable;
|
||||
|
||||
public record PaperCookingFuel(
|
||||
net.minecraft.world.item.component.CookingFuel impl
|
||||
) implements CookingFuel, Handleable<net.minecraft.world.item.component.CookingFuel> {
|
||||
|
||||
@Override
|
||||
public net.minecraft.world.item.component.CookingFuel getHandle() {
|
||||
return this.impl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public io.papermc.paper.loot.number.ResolvableInt burnTime() {
|
||||
return PaperResolvableInt.fromVanilla(this.impl.burnTime());
|
||||
}
|
||||
|
||||
@Override
|
||||
public io.papermc.paper.loot.number.ResolvableFloat speedMultiplier() {
|
||||
return PaperResolvableFloat.fromVanilla(this.impl.speedMultiplier());
|
||||
}
|
||||
|
||||
static final class BuilderImpl implements CookingFuel.Builder {
|
||||
|
||||
private int burnTime = 0;
|
||||
private float speedMultiplier = 1.0F;
|
||||
|
||||
@Override
|
||||
public Builder burnTime(final int burnTime) {
|
||||
this.burnTime = burnTime;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder speedMultiplier(final float speedMultiplier) {
|
||||
this.speedMultiplier = speedMultiplier;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CookingFuel build() {
|
||||
return new PaperCookingFuel(
|
||||
new net.minecraft.world.item.component.CookingFuel(
|
||||
new ResolvableInt.Constant(this.burnTime),
|
||||
new ResolvableFloat.Constant(this.speedMultiplier)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package io.papermc.paper.loot.number;
|
||||
|
||||
import java.util.Optional;
|
||||
import net.minecraft.world.level.storage.loot.LootParams;
|
||||
import net.minecraft.world.level.storage.loot.parameters.LootContextParamSets;
|
||||
import org.bukkit.craftbukkit.CraftLootContext;
|
||||
import org.bukkit.craftbukkit.util.Handleable;
|
||||
import org.bukkit.loot.LootContext;
|
||||
|
||||
public record PaperResolvableFloat(
|
||||
net.minecraft.world.level.storage.loot.providers.number.floats.ResolvableFloat impl
|
||||
) implements ResolvableFloat, Handleable<net.minecraft.world.level.storage.loot.providers.number.floats.ResolvableFloat> {
|
||||
|
||||
@Override
|
||||
public float resolve(final LootContext context, final float defaultValue) {
|
||||
LootParams lootParams = CraftLootContext.createLootParams(context, LootContextParamSets.ALL_PARAMS_OPTIONAL, false);
|
||||
net.minecraft.world.level.storage.loot.LootContext vanillaContext = new net.minecraft.world.level.storage.loot.LootContext.Builder(lootParams).create(Optional.empty());
|
||||
return this.impl.get(vanillaContext, defaultValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public net.minecraft.world.level.storage.loot.providers.number.floats.ResolvableFloat getHandle() {
|
||||
return this.impl;
|
||||
}
|
||||
|
||||
public static ResolvableFloat fromVanilla(net.minecraft.world.level.storage.loot.providers.number.floats.ResolvableFloat vanilla) {
|
||||
if (vanilla instanceof net.minecraft.world.level.storage.loot.providers.number.floats.ResolvableFloat.Constant(
|
||||
float value
|
||||
)) {
|
||||
return new PaperResolvableFloat.Constant(value);
|
||||
}
|
||||
return new PaperResolvableFloat(vanilla);
|
||||
}
|
||||
|
||||
record Constant(float value) implements ResolvableFloat.Constant {
|
||||
@Override
|
||||
public float getValue() {
|
||||
return this.value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package io.papermc.paper.loot.number;
|
||||
|
||||
import java.util.Optional;
|
||||
import net.minecraft.world.level.storage.loot.LootParams;
|
||||
import net.minecraft.world.level.storage.loot.parameters.LootContextParamSets;
|
||||
import org.bukkit.craftbukkit.CraftLootContext;
|
||||
import org.bukkit.craftbukkit.util.Handleable;
|
||||
import org.bukkit.loot.LootContext;
|
||||
|
||||
public record PaperResolvableInt(
|
||||
net.minecraft.world.level.storage.loot.providers.number.ints.ResolvableInt impl
|
||||
) implements ResolvableInt, Handleable<net.minecraft.world.level.storage.loot.providers.number.ints.ResolvableInt> {
|
||||
|
||||
@Override
|
||||
public int resolve(final LootContext context, final int defaultValue) {
|
||||
LootParams lootParams = CraftLootContext.createLootParams(context, LootContextParamSets.ALL_PARAMS_OPTIONAL, false);
|
||||
net.minecraft.world.level.storage.loot.LootContext vanillaContext = new net.minecraft.world.level.storage.loot.LootContext.Builder(lootParams).create(Optional.empty());
|
||||
return this.impl.get(vanillaContext, defaultValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public net.minecraft.world.level.storage.loot.providers.number.ints.ResolvableInt getHandle() {
|
||||
return this.impl;
|
||||
}
|
||||
|
||||
public static ResolvableInt fromVanilla(net.minecraft.world.level.storage.loot.providers.number.ints.ResolvableInt vanilla) {
|
||||
if (vanilla instanceof net.minecraft.world.level.storage.loot.providers.number.ints.ResolvableInt.Constant(
|
||||
int value
|
||||
)) {
|
||||
return new Constant(value);
|
||||
}
|
||||
return new PaperResolvableInt(vanilla);
|
||||
}
|
||||
|
||||
public record Constant(int value) implements ResolvableInt.Constant {
|
||||
@Override
|
||||
public int getValue() {
|
||||
return this.value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
@NullMarked
|
||||
package io.papermc.paper.loot.number;
|
||||
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
@@ -0,0 +1,106 @@
|
||||
package org.bukkit.craftbukkit;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.util.context.ContextKey;
|
||||
import net.minecraft.util.context.ContextKeySet;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.storage.loot.LootParams;
|
||||
import net.minecraft.world.level.storage.loot.parameters.LootContextParams;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.craftbukkit.block.CraftBlockState;
|
||||
import org.bukkit.craftbukkit.entity.CraftEntity;
|
||||
import org.bukkit.craftbukkit.entity.CraftHumanEntity;
|
||||
import org.bukkit.craftbukkit.util.CraftLocation;
|
||||
import org.bukkit.loot.LootContext;
|
||||
|
||||
public final class CraftLootContext {
|
||||
|
||||
public static LootParams createLootParams(final LootContext context, final ContextKeySet paramSet, final boolean empty) {
|
||||
Preconditions.checkArgument(context != null, "LootContext cannot be null");
|
||||
final Location loc = context.getLocation();
|
||||
Preconditions.checkArgument(loc.getWorld() != null, "LootContext.getLocation#getWorld cannot be null");
|
||||
final ServerLevel handle = ((CraftWorld) loc.getWorld()).getHandle();
|
||||
|
||||
final LootParams.Builder builder = new LootParams.Builder(handle);
|
||||
setMaybe(builder, paramSet, LootContextParams.ORIGIN, CraftLocation.toVec3(loc));
|
||||
|
||||
final BlockState blockState = ((CraftBlockState) loc.getBlock().getState()).getHandle();
|
||||
setMaybe(builder, paramSet, LootContextParams.BLOCK_STATE, blockState);
|
||||
if (blockState.hasBlockEntity()) {
|
||||
setMaybe(builder, paramSet, LootContextParams.BLOCK_ENTITY, handle.getBlockEntity(CraftLocation.toBlockPos(loc)));
|
||||
}
|
||||
|
||||
if (!empty) {
|
||||
builder.withLuck(context.getLuck());
|
||||
|
||||
if (context.getLootedEntity() instanceof CraftEntity craftLootedEntity) {
|
||||
Entity nmsLootedEntity = craftLootedEntity.getHandle();
|
||||
setMaybe(builder, paramSet, LootContextParams.THIS_ENTITY, nmsLootedEntity);
|
||||
setMaybe(builder, paramSet, LootContextParams.DAMAGE_SOURCE, handle.damageSources().generic());
|
||||
setMaybe(builder, paramSet, LootContextParams.ORIGIN, nmsLootedEntity.position());
|
||||
}
|
||||
|
||||
if (context.getKiller() instanceof CraftHumanEntity craftHumanKiller) {
|
||||
Player nmsKiller = craftHumanKiller.getHandle();
|
||||
setMaybe(builder, paramSet, LootContextParams.ATTACKING_ENTITY, nmsKiller);
|
||||
// If there is a player killer, damage source should reflect that in case loot tables use that information
|
||||
setMaybe(builder, paramSet, LootContextParams.DAMAGE_SOURCE, handle.damageSources().playerAttack(nmsKiller));
|
||||
setMaybe(builder, paramSet, LootContextParams.LAST_DAMAGE_PLAYER, nmsKiller); // SPIGOT-5603 - Set minecraft:killed_by_player
|
||||
setMaybe(builder, paramSet, LootContextParams.TOOL, nmsKiller.getUseItem()); // SPIGOT-6925 - Set minecraft:match_tool
|
||||
}
|
||||
}
|
||||
|
||||
// SPIGOT-5603 - Avoid IllegalArgumentException in ContextKeySet.Builder#create
|
||||
final ContextKeySet.Builder nmsBuilder = new ContextKeySet.Builder();
|
||||
for (final ContextKey<?> param : paramSet.required()) {
|
||||
nmsBuilder.required(param);
|
||||
}
|
||||
for (final ContextKey<?> param : paramSet.allowed()) {
|
||||
if (!paramSet.required().contains(param)) {
|
||||
nmsBuilder.optional(param);
|
||||
}
|
||||
}
|
||||
|
||||
return builder.create(paramSet);
|
||||
}
|
||||
|
||||
private static <T> void setMaybe(final LootParams.Builder builder, final ContextKeySet paramSet, final ContextKey<T> param, final T value) {
|
||||
if (paramSet.required().contains(param) || paramSet.allowed().contains(param)) {
|
||||
builder.withParameter(param, value);
|
||||
}
|
||||
}
|
||||
|
||||
public static LootContext toBukkit(final net.minecraft.world.level.storage.loot.LootContext info) {
|
||||
final Entity entity = info.getOptional(LootContextParams.THIS_ENTITY);
|
||||
|
||||
Vec3 position = info.getOptional(LootContextParams.ORIGIN);
|
||||
// Every vanilla context has origin or this_entity, see LootContextParamSets but can be Optional so need to check for null
|
||||
if (position == null && entity != null) {
|
||||
position = entity.position();
|
||||
}
|
||||
final Location location = CraftLocation.toBukkit(position, info.getLevel());
|
||||
|
||||
final LootContext.Builder contextBuilder = new LootContext.Builder(location);
|
||||
|
||||
final Entity killer = info.getOptional(LootContextParams.ATTACKING_ENTITY);
|
||||
if (killer != null && killer.getBukkitEntity() instanceof CraftHumanEntity craftHumanKiller) {
|
||||
contextBuilder.killer(craftHumanKiller);
|
||||
}
|
||||
|
||||
if (entity != null) {
|
||||
contextBuilder.lootedEntity(entity.getBukkitEntity());
|
||||
}
|
||||
|
||||
contextBuilder.luck(info.getLuck());
|
||||
return contextBuilder.build();
|
||||
}
|
||||
|
||||
private CraftLootContext() {
|
||||
throw new UnsupportedOperationException("Cannot instantiate");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -8,24 +8,13 @@ import java.util.Random;
|
||||
import net.minecraft.core.registries.Registries;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.resources.Identifier;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.util.context.ContextKey;
|
||||
import net.minecraft.util.context.ContextKeySet;
|
||||
import net.minecraft.world.Container;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.level.storage.loot.LootParams;
|
||||
import net.minecraft.world.level.storage.loot.LootTable;
|
||||
import net.minecraft.world.level.storage.loot.parameters.LootContextParams;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.craftbukkit.entity.CraftEntity;
|
||||
import org.bukkit.craftbukkit.entity.CraftHumanEntity;
|
||||
import org.bukkit.craftbukkit.inventory.CraftInventory;
|
||||
import org.bukkit.craftbukkit.inventory.CraftItemStack;
|
||||
import org.bukkit.craftbukkit.util.CraftLocation;
|
||||
import org.bukkit.craftbukkit.util.CraftNamespacedKey;
|
||||
import org.bukkit.craftbukkit.util.RandomSourceWrapper;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
@@ -69,7 +58,7 @@ public class CraftLootTable implements org.bukkit.loot.LootTable {
|
||||
@Override
|
||||
public Collection<ItemStack> populateLoot(Random random, LootContext context) {
|
||||
Preconditions.checkArgument(context != null, "LootContext cannot be null");
|
||||
LootParams nmsContext = this.convertContext(context);
|
||||
LootParams nmsContext = CraftLootContext.createLootParams(context, this.getHandle().getParamSet(), this.getHandle() == LootTable.EMPTY);
|
||||
List<net.minecraft.world.item.ItemStack> nmsItems = this.handle.getRandomItems(nmsContext, random == null ? null : new RandomSourceWrapper(random));
|
||||
Collection<ItemStack> bukkit = new ArrayList<>(nmsItems.size());
|
||||
|
||||
@@ -87,7 +76,7 @@ public class CraftLootTable implements org.bukkit.loot.LootTable {
|
||||
public void fillInventory(Inventory inventory, Random random, LootContext context) {
|
||||
Preconditions.checkArgument(inventory != null, "Inventory cannot be null");
|
||||
Preconditions.checkArgument(context != null, "LootContext cannot be null");
|
||||
LootParams nmsContext = this.convertContext(context);
|
||||
LootParams nmsContext = CraftLootContext.createLootParams(context, this.getHandle().getParamSet(), this.getHandle() == LootTable.EMPTY);
|
||||
CraftInventory craftInventory = (CraftInventory) inventory;
|
||||
Container handle = craftInventory.getInventory();
|
||||
|
||||
@@ -100,77 +89,6 @@ public class CraftLootTable implements org.bukkit.loot.LootTable {
|
||||
return this.key;
|
||||
}
|
||||
|
||||
private LootParams convertContext(LootContext context) {
|
||||
Preconditions.checkArgument(context != null, "LootContext cannot be null");
|
||||
Location loc = context.getLocation();
|
||||
Preconditions.checkArgument(loc.getWorld() != null, "LootContext.getLocation#getWorld cannot be null");
|
||||
ServerLevel handle = ((CraftWorld) loc.getWorld()).getHandle();
|
||||
|
||||
LootParams.Builder builder = new LootParams.Builder(handle);
|
||||
this.setMaybe(builder, LootContextParams.ORIGIN, CraftLocation.toVec3(loc));
|
||||
if (this.getHandle() != LootTable.EMPTY) {
|
||||
builder.withLuck(context.getLuck());
|
||||
|
||||
if (context.getLootedEntity() != null) {
|
||||
Entity nmsLootedEntity = ((CraftEntity) context.getLootedEntity()).getHandle();
|
||||
this.setMaybe(builder, LootContextParams.THIS_ENTITY, nmsLootedEntity);
|
||||
this.setMaybe(builder, LootContextParams.DAMAGE_SOURCE, handle.damageSources().generic());
|
||||
this.setMaybe(builder, LootContextParams.ORIGIN, nmsLootedEntity.position());
|
||||
}
|
||||
|
||||
if (context.getKiller() != null) {
|
||||
Player nmsKiller = ((CraftHumanEntity) context.getKiller()).getHandle();
|
||||
this.setMaybe(builder, LootContextParams.ATTACKING_ENTITY, nmsKiller);
|
||||
// If there is a player killer, damage source should reflect that in case loot tables use that information
|
||||
this.setMaybe(builder, LootContextParams.DAMAGE_SOURCE, handle.damageSources().playerAttack(nmsKiller));
|
||||
this.setMaybe(builder, LootContextParams.LAST_DAMAGE_PLAYER, nmsKiller); // SPIGOT-5603 - Set minecraft:killed_by_player
|
||||
this.setMaybe(builder, LootContextParams.TOOL, nmsKiller.getUseItem()); // SPIGOT-6925 - Set minecraft:match_tool
|
||||
}
|
||||
}
|
||||
|
||||
// SPIGOT-5603 - Avoid IllegalArgumentException in ContextKeySet.Builder#create
|
||||
ContextKeySet.Builder nmsBuilder = new ContextKeySet.Builder();
|
||||
for (ContextKey<?> param : this.getHandle().getParamSet().required()) {
|
||||
nmsBuilder.required(param);
|
||||
}
|
||||
for (ContextKey<?> param : this.getHandle().getParamSet().allowed()) {
|
||||
if (!this.getHandle().getParamSet().required().contains(param)) {
|
||||
nmsBuilder.optional(param);
|
||||
}
|
||||
}
|
||||
|
||||
return builder.create(this.getHandle().getParamSet());
|
||||
}
|
||||
|
||||
private <T> void setMaybe(LootParams.Builder builder, ContextKey<T> param, T value) {
|
||||
if (this.getHandle().getParamSet().required().contains(param) || this.getHandle().getParamSet().allowed().contains(param)) {
|
||||
builder.withParameter(param, value);
|
||||
}
|
||||
}
|
||||
|
||||
public static LootContext convertContext(net.minecraft.world.level.storage.loot.LootContext info) {
|
||||
Vec3 position = info.getOptional(LootContextParams.ORIGIN);
|
||||
if (position == null) {
|
||||
position = info.getOptional(LootContextParams.THIS_ENTITY).position(); // Every vanilla context has origin or this_entity, see LootContextParamSets
|
||||
}
|
||||
Location location = CraftLocation.toBukkit(position, info.getLevel());
|
||||
LootContext.Builder contextBuilder = new LootContext.Builder(location);
|
||||
|
||||
if (info.hasParameter(LootContextParams.ATTACKING_ENTITY)) {
|
||||
CraftEntity killer = info.getOptional(LootContextParams.ATTACKING_ENTITY).getBukkitEntity();
|
||||
if (killer instanceof CraftHumanEntity) {
|
||||
contextBuilder.killer((CraftHumanEntity) killer);
|
||||
}
|
||||
}
|
||||
|
||||
if (info.hasParameter(LootContextParams.THIS_ENTITY)) {
|
||||
contextBuilder.lootedEntity(info.getOptional(LootContextParams.THIS_ENTITY).getBukkitEntity());
|
||||
}
|
||||
|
||||
contextBuilder.luck(info.getLuck());
|
||||
return contextBuilder.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.key.toString();
|
||||
|
||||
@@ -98,7 +98,7 @@ import org.bukkit.craftbukkit.CraftChunk;
|
||||
import org.bukkit.craftbukkit.CraftEquipmentSlot;
|
||||
import org.bukkit.craftbukkit.CraftExplosionResult;
|
||||
import org.bukkit.craftbukkit.CraftGameRule;
|
||||
import org.bukkit.craftbukkit.CraftLootTable;
|
||||
import org.bukkit.craftbukkit.CraftLootContext;
|
||||
import org.bukkit.craftbukkit.CraftRaid;
|
||||
import org.bukkit.craftbukkit.CraftServer;
|
||||
import org.bukkit.craftbukkit.CraftStatistic;
|
||||
@@ -1996,7 +1996,7 @@ public class CraftEventFactory {
|
||||
Entity entity = lootInfo.getOptional(LootContextParams.THIS_ENTITY);
|
||||
List<org.bukkit.inventory.ItemStack> bukkitLoot = loot.stream().map(CraftItemStack::asBukkitMirror).collect(Collectors.toCollection(ArrayList::new));
|
||||
|
||||
LootGenerateEvent event = new LootGenerateEvent(world, (entity != null ? entity.getBukkitEntity() : null), inventory.getOwner(), lootTable.craftLootTable, CraftLootTable.convertContext(lootInfo), bukkitLoot, plugin);
|
||||
LootGenerateEvent event = new LootGenerateEvent(world, (entity != null ? entity.getBukkitEntity() : null), inventory.getOwner(), lootTable.craftLootTable, CraftLootContext.toBukkit(lootInfo), bukkitLoot, plugin);
|
||||
Bukkit.getPluginManager().callEvent(event);
|
||||
return event;
|
||||
}
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
package org.bukkit.craftbukkit.inventory;
|
||||
|
||||
import net.minecraft.core.component.DataComponents;
|
||||
import io.papermc.paper.datacomponent.DataComponentTypes;
|
||||
import net.minecraft.world.item.crafting.SingleRecipeInput;
|
||||
import net.minecraft.world.level.block.entity.AbstractFurnaceBlockEntity;
|
||||
import org.bukkit.block.Furnace;
|
||||
@@ -44,7 +44,7 @@ public class CraftInventoryFurnace extends CraftInventory implements FurnaceInve
|
||||
|
||||
@Override
|
||||
public boolean isFuel(ItemStack stack) {
|
||||
return stack != null && !stack.isEmpty() && CraftItemStack.asNMSCopy(stack).has(DataComponents.COOKING_FUEL);
|
||||
return stack != null && !stack.isEmpty() && stack.hasData(DataComponentTypes.COOKING_FUEL);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -59,9 +59,7 @@ public class RegistryConstantsTest {
|
||||
DataComponents.CREATIVE_SLOT_LOCK,
|
||||
DataComponents.ADDITIONAL_TRADE_COST,
|
||||
DataComponents.BLOCK_TRANSFORMER,
|
||||
DataComponents.COMPOSTABLE,
|
||||
DataComponents.COOKING_FUEL,
|
||||
DataComponents.BREWING_FUEL
|
||||
DataComponents.COMPOSTABLE
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user