This commit is contained in:
Eclipse 2024-08-13 20:11:24 +00:00 committed by GitHub
commit 2de5f0b3bf
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 479 additions and 319 deletions

View file

@ -25,6 +25,8 @@
package org.geysermc.geyser.api.item.custom;
import org.checkerframework.checker.index.qual.NonNegative;
import org.checkerframework.checker.index.qual.Positive;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.geysermc.geyser.api.GeyserApi;
@ -114,6 +116,88 @@ public interface CustomItemData {
*/
@NonNull Set<String> tags();
/**
* Gets the stack size of the item.
*
* <p>Returns 0 if not set. When not set, Geyser defaults to the stack count of the Java item when based on a vanilla item, or 64 when registering a non-vanilla item.</p>
*
* <p>Note that, to copy Java behaviour, setting the stack size of an item to a value above 1 will set the max damage to 0. If a max damage value above 0 was explicitly set, an exception will be thrown.</p>
*
* @return the stack size of the item
*/
@NonNegative int stackSize();
/**
* Gets the max damage of the item.
*
* <p>Returns -1 if not set. When not set, Geyser defaults to the maximum damage of the Java item when based on a vanilla item, or uses 0 when registering a non-vanilla item.</p>
*
* <p>Note that, to copy Java behaviour, setting the max damage value of an item to a value above 0 will set the stack size to 1. If a stack size above 1 was explicitly set, an exception will be thrown.</p>
*
* @return the max damage of the item
*/
int maxDamage();
/**
* Gets the attack damage of the item.
* This is purely visual, and only applied to tools
*
* <p>Returns -1 if not set. When not set, Geyser takes the Java item attack damage when based on a vanilla item, or uses 0 when porting a modded item.</p>
*
* @return the attack damage of the item
*/
int attackDamage();
/**
* Gets the armor type of the item.
*
* <p>This can be "boots", "leggings", "chestplate", or "helmet", and makes the item able to be equipped into its respective equipment slot.
* This should only be set if the Java item can be placed into the specified equipment slot.</p>
*
* @return the armor type of the item
*/
@Nullable String armorType();
/**
* Gets the armor protection value of the item.
*
* <p>Only has a function when {@link CustomItemData#armorType} is set, or when the Java item is an armor item (when based on a vanilla item).</p>
*
* <p>Returns -1 if not set. When not set, Geyser takes the Java item protection value when based on a vanilla item, or uses 0 when porting a modded item.</p>
*
* @return the armor protection value of the item
*/
int protectionValue();
/**
* Gets if the item is a hat. This is used to determine if the item should be rendered on the player's head, and
* normally allow the player to equip it. This is not meant for armor.
*
* @return if the item is a hat
*/
boolean isHat();
/**
* Gets if the item is a foil. This is used to determine if the item should be rendered with an enchantment glint effect.
*
* @return if the item is a foil
*/
boolean isFoil();
/**
* Gets if the item is edible.
*
* @return if the item is edible
*/
boolean isEdible();
/**
* Gets if the food item can always be eaten.
*
* @return if the item is allowed to be eaten all the time
*/
boolean canAlwaysEat();
static CustomItemData.Builder builder() {
return GeyserApi.api().provider(CustomItemData.Builder.class);
}
@ -144,6 +228,24 @@ public interface CustomItemData {
Builder tags(@Nullable Set<String> tags);
Builder stackSize(@Positive int stackSize);
Builder maxDamage(@NonNegative int maxDamage);
Builder attackDamage(@NonNegative int attackDamage);
Builder armorType(@Nullable String armorType);
Builder protectionValue(@NonNegative int protectionValue);
Builder hat(boolean isHat);
Builder foil(boolean isFoil);
Builder edible(boolean isEdible);
Builder canAlwaysEat(boolean canAlwaysEat);
CustomItemData build();
}
}

View file

@ -26,6 +26,7 @@
package org.geysermc.geyser.api.item.custom;
import org.checkerframework.checker.index.qual.NonNegative;
import org.checkerframework.checker.index.qual.Positive;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.geysermc.geyser.api.GeyserApi;
@ -43,35 +44,6 @@ public interface NonVanillaCustomItemData extends CustomItemData {
*/
@NonNull String identifier();
/**
* Gets the java item id of the item.
*
* @return the java item id of the item
*/
@NonNegative int javaId();
/**
* Gets the stack size of the item.
*
* @return the stack size of the item
*/
@NonNegative int stackSize();
/**
* Gets the max damage of the item.
*
* @return the max damage of the item
*/
int maxDamage();
/**
* Gets the attack damage of the item.
* This is purely visual, and only applied to tools
*
* @return the attack damage of the item
*/
int attackDamage();
/**
* Gets the tool type of the item.
*
@ -87,18 +59,11 @@ public interface NonVanillaCustomItemData extends CustomItemData {
@Nullable String toolTier();
/**
* Gets the armor type of the item.
* Gets the java item id of the item.
*
* @return the armor type of the item
* @return the java item id of the item
*/
@Nullable String armorType();
/**
* Gets the armor protection value of the item.
*
* @return the armor protection value of the item
*/
int protectionValue();
@NonNegative int javaId();
/**
* Gets the item's translation string.
@ -114,35 +79,6 @@ public interface NonVanillaCustomItemData extends CustomItemData {
*/
@Nullable Set<String> repairMaterials();
/**
* Gets if the item is a hat. This is used to determine if the item should be rendered on the player's head, and
* normally allow the player to equip it. This is not meant for armor.
*
* @return if the item is a hat
*/
boolean isHat();
/**
* Gets if the item is a foil. This is used to determine if the item should be rendered with an enchantment glint effect.
*
* @return if the item is a foil
*/
boolean isFoil();
/**
* Gets if the item is edible.
*
* @return if the item is edible
*/
boolean isEdible();
/**
* Gets if the food item can always be eaten.
*
* @return if the item is allowed to be eaten all the time
*/
boolean canAlwaysEat();
/**
* Gets if the item is chargable, like a bow.
*
@ -150,6 +86,13 @@ public interface NonVanillaCustomItemData extends CustomItemData {
*/
boolean isChargeable();
/**
* Gets the block the item places.
*
* @return the block the item places
*/
String block();
/**
* @deprecated Use {@link #displayHandheld()} instead.
* Gets if the item is a tool. This is used to set the render type of the item, if the item is handheld.
@ -161,13 +104,6 @@ public interface NonVanillaCustomItemData extends CustomItemData {
return displayHandheld();
}
/**
* Gets the block the item places.
*
* @return the block the item places
*/
String block();
static NonVanillaCustomItemData.Builder builder() {
return GeyserApi.api().provider(NonVanillaCustomItemData.Builder.class);
}
@ -176,54 +112,6 @@ public interface NonVanillaCustomItemData extends CustomItemData {
@Override
Builder name(@NonNull String name);
Builder identifier(@NonNull String identifier);
Builder javaId(@NonNegative int javaId);
Builder stackSize(@NonNegative int stackSize);
Builder maxDamage(int maxDamage);
Builder attackDamage(int attackDamage);
Builder toolType(@Nullable String toolType);
Builder toolTier(@Nullable String toolTier);
Builder armorType(@Nullable String armorType);
Builder protectionValue(int protectionValue);
Builder translationString(@Nullable String translationString);
Builder repairMaterials(@Nullable Set<String> repairMaterials);
Builder hat(boolean isHat);
Builder foil(boolean isFoil);
Builder edible(boolean isEdible);
Builder canAlwaysEat(boolean canAlwaysEat);
Builder chargeable(boolean isChargeable);
Builder block(String block);
/**
* @deprecated Use {@link #displayHandheld(boolean)} instead.
*/
@Deprecated
default Builder tool(boolean isTool) {
return displayHandheld(isTool);
}
@Override
Builder creativeCategory(int creativeCategory);
@Override
Builder creativeGroup(@Nullable String creativeGroup);
@Override
Builder customItemOptions(@NonNull CustomItemOptions customItemOptions);
@ -239,6 +127,12 @@ public interface NonVanillaCustomItemData extends CustomItemData {
@Override
Builder displayHandheld(boolean displayHandheld);
@Override
Builder creativeCategory(int creativeCategory);
@Override
Builder creativeGroup(@Nullable String creativeGroup);
@Override
Builder textureSize(int textureSize);
@ -248,6 +142,57 @@ public interface NonVanillaCustomItemData extends CustomItemData {
@Override
Builder tags(@Nullable Set<String> tags);
@Override
Builder stackSize(@Positive int stackSize);
@Override
Builder maxDamage(@NonNegative int maxDamage);
@Override
Builder attackDamage(@NonNegative int attackDamage);
@Override
Builder armorType(@Nullable String armorType);
@Override
Builder protectionValue(@NonNegative int protectionValue);
@Override
Builder hat(boolean isHat);
@Override
Builder foil(boolean isFoil);
@Override
Builder edible(boolean isEdible);
@Override
Builder canAlwaysEat(boolean canAlwaysEat);
/**
* @deprecated Use {@link #displayHandheld(boolean)} instead.
*/
@Deprecated
default Builder tool(boolean isTool) {
return displayHandheld(isTool);
}
Builder identifier(@NonNull String identifier);
Builder javaId(@NonNegative int javaId);
Builder toolType(@Nullable String toolType);
Builder toolTier(@Nullable String toolTier);
Builder translationString(@Nullable String translationString);
Builder repairMaterials(@Nullable Set<String> repairMaterials);
Builder chargeable(boolean isChargeable);
Builder block(String block);
NonVanillaCustomItemData build();
}
}

View file

@ -25,8 +25,11 @@
package org.geysermc.geyser.item;
import java.util.List;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.checkerframework.checker.index.qual.NonNegative;
import org.checkerframework.checker.index.qual.Positive;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.geysermc.geyser.api.item.custom.CustomItemData;
@ -41,6 +44,8 @@ import java.util.Set;
@EqualsAndHashCode
@ToString
public class GeyserCustomItemData implements CustomItemData {
private static final List<String> VALID_ARMOR_TYPES = List.of("boots", "leggings", "chestplate", "helmet");
private final String name;
private final CustomItemOptions customItemOptions;
private final String displayName;
@ -52,29 +57,37 @@ public class GeyserCustomItemData implements CustomItemData {
private final int textureSize;
private final CustomRenderOffsets renderOffsets;
private final Set<String> tags;
private final int stackSize;
private final int maxDamage;
private final int attackDamage;
private final String armorType;
private final int protectionValue;
private final boolean isHat;
private final boolean isFoil;
private final boolean isEdible;
private final boolean canAlwaysEat;
public GeyserCustomItemData(String name,
CustomItemOptions customItemOptions,
String displayName,
String icon,
boolean allowOffhand,
boolean displayHandheld,
OptionalInt creativeCategory,
String creativeGroup,
int textureSize,
CustomRenderOffsets renderOffsets,
Set<String> tags) {
this.name = name;
this.customItemOptions = customItemOptions;
this.displayName = displayName;
this.icon = icon;
this.allowOffhand = allowOffhand;
this.displayHandheld = displayHandheld;
this.creativeCategory = creativeCategory;
this.creativeGroup = creativeGroup;
this.textureSize = textureSize;
this.renderOffsets = renderOffsets;
this.tags = tags;
public GeyserCustomItemData(Builder builder) {
this.name = builder.name;
this.customItemOptions = builder.customItemOptions;
this.displayName = builder.displayName;
this.icon = builder.icon;
this.allowOffhand = builder.allowOffhand;
this.displayHandheld = builder.displayHandheld;
this.creativeCategory = builder.creativeCategory;
this.creativeGroup = builder.creativeGroup;
this.textureSize = builder.textureSize;
this.renderOffsets = builder.renderOffsets;
this.tags = builder.tags;
this.stackSize = builder.stackSize;
this.maxDamage = builder.maxDamage;
this.attackDamage = builder.attackDamage;
this.armorType = builder.armorType;
this.protectionValue = builder.protectionValue;
this.isHat = builder.hat;
this.isFoil = builder.foil;
this.isEdible = builder.edible;
this.canAlwaysEat = builder.canAlwaysEat;
}
@Override
@ -132,6 +145,51 @@ public class GeyserCustomItemData implements CustomItemData {
return tags;
}
@Override
public int stackSize() {
return stackSize;
}
@Override
public int maxDamage() {
return maxDamage;
}
@Override
public int attackDamage() {
return attackDamage;
}
@Override
public @Nullable String armorType() {
return armorType;
}
@Override
public int protectionValue() {
return protectionValue;
}
@Override
public boolean isHat() {
return isHat;
}
@Override
public boolean isFoil() {
return isFoil;
}
@Override
public boolean isEdible() {
return isEdible;
}
@Override
public boolean canAlwaysEat() {
return canAlwaysEat;
}
public static class Builder implements CustomItemData.Builder {
protected String name = null;
protected CustomItemOptions customItemOptions = null;
@ -144,6 +202,15 @@ public class GeyserCustomItemData implements CustomItemData {
protected int textureSize = 16;
protected CustomRenderOffsets renderOffsets = null;
protected Set<String> tags = new HashSet<>();
private int stackSize = 0;
private int maxDamage = -1;
private int attackDamage = -1;
private String armorType = null;
private int protectionValue = -1;
private boolean hat = false;
private boolean foil = false;
private boolean edible = false;
private boolean canAlwaysEat = false;
@Override
public Builder name(@NonNull String name) {
@ -211,6 +278,89 @@ public class GeyserCustomItemData implements CustomItemData {
return this;
}
@Override
public Builder stackSize(@Positive int stackSize) {
if (stackSize < 1) {
throw new IllegalArgumentException("Stack size cannot be below 1 (" + stackSize + " was given)");
} else if (stackSize > 1) {
if (this.maxDamage > 0) {
throw new IllegalArgumentException("Stack size cannot be above 1 when max damage is above 0 (" + stackSize + " was given)");
}
// Explicitly set max damage to 0 instead of falling back to the Java vanilla item value
this.maxDamage = 0;
}
this.stackSize = stackSize;
return this;
}
@Override
public Builder maxDamage(@NonNegative int maxDamage) {
if (maxDamage < 0) {
throw new IllegalArgumentException("Max damage cannot be below 0 (" + maxDamage + " was given)");
} else if (maxDamage > 0) {
if (this.stackSize > 1) {
throw new IllegalArgumentException("Max damage cannot be above 0 when stack size is above 1 (" + maxDamage + " was given)");
}
// Explicitly set stack size to 1 instead of falling back to the Java vanilla item value
this.stackSize = 1;
}
this.maxDamage = maxDamage;
return this;
}
@Override
public Builder attackDamage(@NonNegative int attackDamage) {
if (attackDamage < 0) {
throw new IllegalArgumentException("Protection value cannot be below 0 (" + attackDamage + " was given)");
}
this.attackDamage = attackDamage;
return this;
}
@Override
public Builder armorType(@Nullable String armorType) {
if (!VALID_ARMOR_TYPES.contains(armorType)) {
throw new IllegalArgumentException("Invalid armor type " + armorType + "! Can be \"boots\", \"leggings\", \"chestplate\", or \"helmet\"");
}
this.armorType = armorType;
return this;
}
@Override
public Builder protectionValue(@NonNegative int protectionValue) {
if (protectionValue < 0) {
throw new IllegalArgumentException("Protection value cannot be below 0 (" + protectionValue + " was given)");
}
this.protectionValue = protectionValue;
return this;
}
@Override
public Builder hat(boolean isHat) {
this.hat = isHat;
return this;
}
@Override
public Builder foil(boolean isFoil) {
this.foil = isFoil;
return this;
}
@Override
public Builder edible(boolean isEdible) {
this.edible = isEdible;
return this;
}
@Override
public Builder canAlwaysEat(boolean canAlwaysEat) {
this.canAlwaysEat = canAlwaysEat;
return this;
}
@Override
public CustomItemData build() {
if (this.name == null || this.customItemOptions == null) {
@ -223,8 +373,8 @@ public class GeyserCustomItemData implements CustomItemData {
if (this.icon == null) {
this.icon = this.name;
}
return new GeyserCustomItemData(this.name, this.customItemOptions, this.displayName, this.icon, this.allowOffhand,
this.displayHandheld, this.creativeCategory, this.creativeGroup, this.textureSize, this.renderOffsets, this.tags);
return new GeyserCustomItemData(this);
}
}
}

View file

@ -27,6 +27,8 @@ package org.geysermc.geyser.item;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.checkerframework.checker.index.qual.NonNegative;
import org.checkerframework.checker.index.qual.Positive;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.geysermc.geyser.api.item.custom.CustomItemOptions;
@ -40,44 +42,22 @@ import java.util.Set;
public final class GeyserNonVanillaCustomItemData extends GeyserCustomItemData implements NonVanillaCustomItemData {
private final String identifier;
private final int javaId;
private final int stackSize;
private final int maxDamage;
private final int attackDamage;
private final String toolType;
private final String toolTier;
private final String armorType;
private final int protectionValue;
private final String translationString;
private final Set<String> repairMaterials;
private final boolean isHat;
private final boolean isFoil;
private final boolean isTool;
private final boolean isEdible;
private final boolean canAlwaysEat;
private final boolean isChargeable;
private final String block;
public GeyserNonVanillaCustomItemData(Builder builder) {
super(builder.name, builder.customItemOptions, builder.displayName, builder.icon, builder.allowOffhand,
builder.displayHandheld, builder.creativeCategory, builder.creativeGroup,
builder.textureSize, builder.renderOffsets, builder.tags);
super(builder);
this.identifier = builder.identifier;
this.javaId = builder.javaId;
this.stackSize = builder.stackSize;
this.maxDamage = builder.maxDamage;
this.attackDamage = builder.attackDamage;
this.toolType = builder.toolType;
this.toolTier = builder.toolTier;
this.armorType = builder.armorType;
this.protectionValue = builder.protectionValue;
this.translationString = builder.translationString;
this.repairMaterials = builder.repairMaterials;
this.isHat = builder.hat;
this.isFoil = builder.foil;
this.isTool = builder.tool;
this.isEdible = builder.edible;
this.canAlwaysEat = builder.canAlwaysEat;
this.isChargeable = builder.chargeable;
this.block = builder.block;
}
@ -92,21 +72,6 @@ public final class GeyserNonVanillaCustomItemData extends GeyserCustomItemData i
return javaId;
}
@Override
public int stackSize() {
return stackSize;
}
@Override
public int maxDamage() {
return maxDamage;
}
@Override
public int attackDamage() {
return attackDamage;
}
@Override
public String toolType() {
return toolType;
@ -117,16 +82,6 @@ public final class GeyserNonVanillaCustomItemData extends GeyserCustomItemData i
return toolTier;
}
@Override
public @Nullable String armorType() {
return armorType;
}
@Override
public int protectionValue() {
return protectionValue;
}
@Override
public String translationString() {
return translationString;
@ -137,26 +92,6 @@ public final class GeyserNonVanillaCustomItemData extends GeyserCustomItemData i
return repairMaterials;
}
@Override
public boolean isHat() {
return isHat;
}
@Override
public boolean isFoil() {
return isFoil;
}
@Override
public boolean isEdible() {
return isEdible;
}
@Override
public boolean canAlwaysEat() {
return canAlwaysEat;
}
@Override
public boolean isChargeable() {
return isChargeable;
@ -170,28 +105,10 @@ public final class GeyserNonVanillaCustomItemData extends GeyserCustomItemData i
public static class Builder extends GeyserCustomItemData.Builder implements NonVanillaCustomItemData.Builder {
private String identifier = null;
private int javaId = -1;
private int stackSize = 64;
private int maxDamage = 0;
private int attackDamage = 0;
private String toolType = null;
private String toolTier = null;
private String armorType = null;
private int protectionValue = 0;
private String translationString;
private Set<String> repairMaterials;
private boolean hat = false;
private boolean foil = false;
private boolean tool = false;
private boolean edible = false;
private boolean canAlwaysEat = false;
private boolean chargeable = false;
private String block = null;
@ -206,6 +123,16 @@ public final class GeyserNonVanillaCustomItemData extends GeyserCustomItemData i
return this;
}
@Override
public Builder displayName(@NonNull String displayName) {
return (Builder) super.displayName(displayName);
}
@Override
public Builder icon(@NonNull String icon) {
return (Builder) super.icon(icon);
}
@Override
public Builder allowOffhand(boolean allowOffhand) {
return (Builder) super.allowOffhand(allowOffhand);
@ -217,13 +144,13 @@ public final class GeyserNonVanillaCustomItemData extends GeyserCustomItemData i
}
@Override
public Builder displayName(@NonNull String displayName) {
return (Builder) super.displayName(displayName);
public Builder creativeCategory(int creativeCategory) {
return (Builder) super.creativeCategory(creativeCategory);
}
@Override
public Builder icon(@NonNull String icon) {
return (Builder) super.icon(icon);
public Builder creativeGroup(@Nullable String creativeGroup) {
return (Builder) super.creativeGroup(creativeGroup);
}
@Override
@ -241,6 +168,51 @@ public final class GeyserNonVanillaCustomItemData extends GeyserCustomItemData i
return (Builder) super.tags(tags);
}
@Override
public Builder stackSize(@Positive int stackSize) {
return (Builder) super.stackSize(stackSize);
}
@Override
public Builder maxDamage(@NonNegative int maxDamage) {
return (Builder) super.maxDamage(maxDamage);
}
@Override
public Builder attackDamage(@NonNegative int attackDamage) {
return (Builder) super.attackDamage(attackDamage);
}
@Override
public Builder armorType(@Nullable String armorType) {
return (Builder) super.armorType(armorType);
}
@Override
public Builder protectionValue(@NonNegative int protectionValue) {
return (Builder) super.protectionValue(protectionValue);
}
@Override
public Builder hat(boolean isHat) {
return (Builder) super.hat(isHat);
}
@Override
public Builder foil(boolean isFoil) {
return (Builder) super.foil(isFoil);
}
@Override
public Builder edible(boolean isEdible) {
return (Builder) super.edible(isEdible);
}
@Override
public Builder canAlwaysEat(boolean canAlwaysEat) {
return (Builder) super.canAlwaysEat(canAlwaysEat);
}
@Override
public Builder identifier(@NonNull String identifier) {
this.identifier = identifier;
@ -253,24 +225,6 @@ public final class GeyserNonVanillaCustomItemData extends GeyserCustomItemData i
return this;
}
@Override
public Builder stackSize(int stackSize) {
this.stackSize = stackSize;
return this;
}
@Override
public Builder maxDamage(int maxDamage) {
this.maxDamage = maxDamage;
return this;
}
@Override
public NonVanillaCustomItemData.Builder attackDamage(int attackDamage) {
this.attackDamage = attackDamage;
return this;
}
@Override
public Builder toolType(@Nullable String toolType) {
this.toolType = toolType;
@ -283,18 +237,6 @@ public final class GeyserNonVanillaCustomItemData extends GeyserCustomItemData i
return this;
}
@Override
public Builder armorType(@Nullable String armorType) {
this.armorType = armorType;
return this;
}
@Override
public Builder protectionValue(int protectionValue) {
this.protectionValue = protectionValue;
return this;
}
@Override
public Builder translationString(@Nullable String translationString) {
this.translationString = translationString;
@ -307,40 +249,6 @@ public final class GeyserNonVanillaCustomItemData extends GeyserCustomItemData i
return this;
}
@Override
public Builder creativeCategory(int creativeCategory) {
return (Builder) super.creativeCategory(creativeCategory);
}
@Override
public Builder creativeGroup(@Nullable String creativeGroup) {
return (Builder) super.creativeGroup(creativeGroup);
}
@Override
public Builder hat(boolean isHat) {
this.hat = isHat;
return this;
}
@Override
public Builder foil(boolean isFoil) {
this.foil = isFoil;
return this;
}
@Override
public Builder edible(boolean isEdible) {
this.edible = isEdible;
return this;
}
@Override
public Builder canAlwaysEat(boolean canAlwaysEat) {
this.canAlwaysEat = canAlwaysEat;
return this;
}
@Override
public Builder chargeable(boolean isChargeable) {
this.chargeable = isChargeable;

View file

@ -213,6 +213,42 @@ public class MappingsReader_v1 extends MappingsReader {
customItemData.tags(tagsSet);
}
if (node.has("stack_size")) {
customItemData.stackSize(node.get("stack_size").asInt());
}
if (node.has("max_damage")) {
customItemData.maxDamage(node.get("max_damage").asInt());
}
if (node.has("attack_damage")) {
customItemData.attackDamage(node.get("attack_damage").asInt());
}
if (node.has("armor_type")) {
customItemData.armorType(node.get("armor_type").asText());
}
if (node.has("protection_value")) {
customItemData.protectionValue(node.get("protection_value").asInt());
}
if (node.has("hat")) {
customItemData.hat(node.get("hat").asBoolean());
}
if (node.has("foil")) {
customItemData.foil(node.get("foil").asBoolean());
}
if (node.has("edible")) {
customItemData.edible(node.get("edible").asBoolean());
}
if (node.has("can_always_eat")) {
customItemData.canAlwaysEat(node.get("can_always_eat").asBoolean());
}
return customItemData.build();
}

View file

@ -130,8 +130,8 @@ public class CustomItemRegistryPopulator {
Set<String> repairMaterials = customItemData.repairMaterials();
Item.Builder itemBuilder = Item.builder()
.stackSize(customItemData.stackSize())
.maxDamage(customItemData.maxDamage());
.stackSize(customItemData.stackSize() == 0 ? 64 : customItemData.stackSize())
.maxDamage(Math.max(customItemData.maxDamage(), 0));
Item item = new Item(customIdentifier, itemBuilder) {
@Override
public boolean isValidRepairItem(Item other) {
@ -151,8 +151,7 @@ public class CustomItemRegistryPopulator {
.javaItem(item)
.build();
NbtMapBuilder builder = createComponentNbt(customItemData, customItemData.identifier(), customItemId,
customItemData.isHat(), customItemData.displayHandheld(), protocolVersion);
NbtMapBuilder builder = createComponentNbt(customItemData, customItemId, protocolVersion);
ComponentItemData componentItemData = new ComponentItemData(customIdentifier, builder.build());
return new NonVanillaItemRegistration(componentItemData, item, customItemMapping);
@ -167,30 +166,50 @@ public class CustomItemRegistryPopulator {
NbtMapBuilder itemProperties = NbtMap.builder();
NbtMapBuilder componentBuilder = NbtMap.builder();
setupBasicItemInfo(javaItem.maxDamage(), javaItem.maxStackSize(), mapping.getToolType() != null || customItemData.displayHandheld(), customItemData, itemProperties, componentBuilder, protocolVersion);
setupBasicItemInfo(customItemData.maxDamage() < 0 ? javaItem.maxDamage() : customItemData.maxDamage(),
customItemData.stackSize() == 0 ? javaItem.maxStackSize() : customItemData.stackSize(),
mapping.getToolType() != null || customItemData.displayHandheld(),
customItemData, itemProperties, componentBuilder, protocolVersion);
boolean canDestroyInCreative = true;
if (mapping.getToolType() != null) { // This is not using the isTool boolean because it is not just a render type here.
canDestroyInCreative = computeToolProperties(mapping.getToolType(), itemProperties, componentBuilder, javaItem.attackDamage());
if (mapping.getToolType() != null) {
canDestroyInCreative = computeToolProperties(mapping.getToolType(), itemProperties, componentBuilder,
customItemData.attackDamage() == 0 ? javaItem.attackDamage() : customItemData.attackDamage());
}
itemProperties.putBoolean("can_destroy_in_creative", canDestroyInCreative);
String armorType = null;
int protectionValue = 0;
if (mapping.getArmorType() != null) {
computeArmorProperties(mapping.getArmorType(), mapping.getProtectionValue(), itemProperties, componentBuilder);
armorType = mapping.getArmorType();
protectionValue = customItemData.protectionValue() == -1 ? mapping.getProtectionValue() : customItemData.protectionValue();
} else if (customItemData.armorType() != null) {
armorType = customItemData.armorType();
// Using 0 as fallback here because the Java item doesn't have an armor type - so its protection value would be 0
protectionValue = customItemData.protectionValue() == -1 ? 0 : customItemData.protectionValue();
}
if (armorType != null) {
computeArmorProperties(armorType, protectionValue, itemProperties, componentBuilder);
}
if (mapping.getFirstBlockRuntimeId() != null) {
computeBlockItemProperties(mapping.getBedrockIdentifier(), componentBuilder);
}
if (mapping.isEdible()) {
computeConsumableProperties(itemProperties, componentBuilder, 1, false);
if (mapping.isEdible() || customItemData.isEdible()) {
computeConsumableProperties(itemProperties, componentBuilder, 1,
customItemData.canAlwaysEat());
}
if (mapping.isEntityPlacer()) {
computeEntityPlacerProperties(componentBuilder);
}
if (customItemData.isFoil()) {
itemProperties.putBoolean("foil", true);
}
switch (mapping.getBedrockIdentifier()) {
case "minecraft:fire_charge", "minecraft:flint_and_steel" -> computeBlockItemProperties("minecraft:fire", componentBuilder);
case "minecraft:bow", "minecraft:crossbow", "minecraft:trident" -> computeChargeableProperties(itemProperties, componentBuilder, mapping.getBedrockIdentifier(), protocolVersion);
@ -200,7 +219,7 @@ public class CustomItemRegistryPopulator {
}
// Hardcoded on Java, and should extend to the custom item
boolean isHat = (javaItem.equals(Items.SKELETON_SKULL) || javaItem.equals(Items.WITHER_SKELETON_SKULL)
boolean isHat = (customItemData.isHat() || javaItem.equals(Items.SKELETON_SKULL) || javaItem.equals(Items.WITHER_SKELETON_SKULL)
|| javaItem.equals(Items.CARVED_PUMPKIN) || javaItem.equals(Items.ZOMBIE_HEAD)
|| javaItem.equals(Items.PIGLIN_HEAD) || javaItem.equals(Items.DRAGON_HEAD)
|| javaItem.equals(Items.CREEPER_HEAD) || javaItem.equals(Items.PLAYER_HEAD)
@ -213,26 +232,26 @@ public class CustomItemRegistryPopulator {
return builder;
}
private static NbtMapBuilder createComponentNbt(NonVanillaCustomItemData customItemData, String customItemName,
int customItemId, boolean isHat, boolean displayHandheld, int protocolVersion) {
private static NbtMapBuilder createComponentNbt(NonVanillaCustomItemData customItemData, int customItemId, int protocolVersion) {
NbtMapBuilder builder = NbtMap.builder();
builder.putString("name", customItemName)
builder.putString("name", customItemData.identifier())
.putInt("id", customItemId);
NbtMapBuilder itemProperties = NbtMap.builder();
NbtMapBuilder componentBuilder = NbtMap.builder();
setupBasicItemInfo(customItemData.maxDamage(), customItemData.stackSize(), displayHandheld, customItemData, itemProperties, componentBuilder, protocolVersion);
setupBasicItemInfo(Math.max(customItemData.maxDamage(), 0), customItemData.stackSize() == 0 ? 64 : customItemData.stackSize(),
customItemData.displayHandheld(), customItemData, itemProperties, componentBuilder, protocolVersion);
boolean canDestroyInCreative = true;
if (customItemData.toolType() != null) { // This is not using the isTool boolean because it is not just a render type here.
canDestroyInCreative = computeToolProperties(Objects.requireNonNull(customItemData.toolType()), itemProperties, componentBuilder, customItemData.attackDamage());
canDestroyInCreative = computeToolProperties(Objects.requireNonNull(customItemData.toolType()), itemProperties, componentBuilder, Math.max(0, customItemData.attackDamage()));
}
itemProperties.putBoolean("can_destroy_in_creative", canDestroyInCreative);
String armorType = customItemData.armorType();
if (armorType != null) {
computeArmorProperties(armorType, customItemData.protectionValue(), itemProperties, componentBuilder);
computeArmorProperties(armorType, Math.max(0, customItemData.protectionValue()), itemProperties, componentBuilder);
}
if (customItemData.isEdible()) {
@ -247,7 +266,7 @@ public class CustomItemRegistryPopulator {
computeChargeableProperties(itemProperties, componentBuilder, "minecraft:" + tooltype, protocolVersion);
}
computeRenderOffsets(isHat, customItemData, componentBuilder);
computeRenderOffsets(customItemData.isHat(), customItemData, componentBuilder);
if (customItemData.isFoil()) {
itemProperties.putBoolean("foil", true);