mirror of
https://github.com/GeyserMC/Geyser.git
synced 2024-08-14 23:57:35 +00:00
* Mapping option for handheld display and fix for #3346 * Fix custom items
This commit is contained in:
parent
d22ee51633
commit
98dceee5e3
9 changed files with 106 additions and 26 deletions
|
@ -68,6 +68,13 @@ public interface CustomItemData {
|
|||
*/
|
||||
boolean allowOffhand();
|
||||
|
||||
/**
|
||||
* Gets if the item should be displayed as handheld, like a tool.
|
||||
*
|
||||
* @return true if the item should be displayed as handheld, false otherwise
|
||||
*/
|
||||
boolean displayHandheld();
|
||||
|
||||
/**
|
||||
* Gets the item's texture size. This is to resize the item if the texture is not 16x16.
|
||||
*
|
||||
|
@ -100,6 +107,8 @@ public interface CustomItemData {
|
|||
|
||||
Builder allowOffhand(boolean allowOffhand);
|
||||
|
||||
Builder displayHandheld(boolean displayHandheld);
|
||||
|
||||
Builder textureSize(int textureSize);
|
||||
|
||||
Builder renderOffsets(@Nullable CustomRenderOffsets renderOffsets);
|
||||
|
|
|
@ -56,6 +56,14 @@ public interface CustomItemOptions {
|
|||
*/
|
||||
@NonNull OptionalInt damagePredicate();
|
||||
|
||||
/**
|
||||
* Gets if this mapping should just translate to the default item.
|
||||
* This is used for the damage predicate of damaged 1 damage 0 that is required to allow the default item to exist.
|
||||
*
|
||||
* @return true if this mapping should just translate to the default item, false otherwise
|
||||
*/
|
||||
boolean defaultItem();
|
||||
|
||||
/**
|
||||
* Checks if the item has at least one option set
|
||||
*
|
||||
|
@ -78,6 +86,8 @@ public interface CustomItemOptions {
|
|||
|
||||
Builder damagePredicate(int damagePredicate);
|
||||
|
||||
Builder defaultItem(boolean defaultItem);
|
||||
|
||||
CustomItemOptions build();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -130,17 +130,22 @@ public interface NonVanillaCustomItemData extends CustomItemData {
|
|||
boolean isHat();
|
||||
|
||||
/**
|
||||
* @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.
|
||||
*
|
||||
* @return if the item is a tool
|
||||
*/
|
||||
boolean isTool();
|
||||
@Deprecated
|
||||
default boolean isTool() {
|
||||
return displayHandheld();
|
||||
}
|
||||
|
||||
static NonVanillaCustomItemData.Builder builder() {
|
||||
return GeyserApi.api().provider(NonVanillaCustomItemData.Builder.class);
|
||||
}
|
||||
|
||||
interface Builder extends CustomItemData.Builder {
|
||||
@Override
|
||||
Builder name(@NonNull String name);
|
||||
|
||||
Builder identifier(@NonNull String identifier);
|
||||
|
@ -169,14 +174,29 @@ public interface NonVanillaCustomItemData extends CustomItemData {
|
|||
|
||||
Builder hat(boolean isHat);
|
||||
|
||||
Builder tool(boolean isTool);
|
||||
/**
|
||||
* @deprecated Use {@link #displayHandheld(boolean)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
default Builder tool(boolean isTool) {
|
||||
return displayHandheld(isTool);
|
||||
}
|
||||
|
||||
@Override
|
||||
Builder customItemOptions(@NonNull CustomItemOptions customItemOptions);
|
||||
|
||||
@Override
|
||||
Builder displayName(@NonNull String displayName);
|
||||
|
||||
@Override
|
||||
Builder icon(@NonNull String icon);
|
||||
|
||||
@Override
|
||||
Builder allowOffhand(boolean allowOffhand);
|
||||
|
||||
@Override
|
||||
Builder displayHandheld(boolean displayHandheld);
|
||||
|
||||
@Override
|
||||
Builder textureSize(int textureSize);
|
||||
|
||||
|
|
|
@ -41,6 +41,7 @@ public class GeyserCustomItemData implements CustomItemData {
|
|||
private final String displayName;
|
||||
private final String icon;
|
||||
private final boolean allowOffhand;
|
||||
private final boolean displayHandheld;
|
||||
private final int textureSize;
|
||||
private final CustomRenderOffsets renderOffsets;
|
||||
|
||||
|
@ -49,6 +50,7 @@ public class GeyserCustomItemData implements CustomItemData {
|
|||
String displayName,
|
||||
String icon,
|
||||
boolean allowOffhand,
|
||||
boolean displayHandheld,
|
||||
int textureSize,
|
||||
CustomRenderOffsets renderOffsets) {
|
||||
this.name = name;
|
||||
|
@ -56,34 +58,47 @@ public class GeyserCustomItemData implements CustomItemData {
|
|||
this.displayName = displayName;
|
||||
this.icon = icon;
|
||||
this.allowOffhand = allowOffhand;
|
||||
this.displayHandheld = displayHandheld;
|
||||
this.textureSize = textureSize;
|
||||
this.renderOffsets = renderOffsets;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String name() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CustomItemOptions customItemOptions() {
|
||||
return customItemOptions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String displayName() {
|
||||
return displayName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String icon() {
|
||||
return icon;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean allowOffhand() {
|
||||
return allowOffhand;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean displayHandheld() {
|
||||
return this.displayHandheld;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int textureSize() {
|
||||
return textureSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CustomRenderOffsets renderOffsets() {
|
||||
return renderOffsets;
|
||||
}
|
||||
|
@ -95,6 +110,7 @@ public class GeyserCustomItemData implements CustomItemData {
|
|||
protected String displayName = null;
|
||||
protected String icon = null;
|
||||
protected boolean allowOffhand = true; // Bedrock doesn't give items offhand allowance unless they serve gameplay purpose, but we want to be friendly with Java
|
||||
protected boolean displayHandheld = false;
|
||||
protected int textureSize = 16;
|
||||
protected CustomRenderOffsets renderOffsets = null;
|
||||
|
||||
|
@ -128,6 +144,12 @@ public class GeyserCustomItemData implements CustomItemData {
|
|||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder displayHandheld(boolean displayHandheld) {
|
||||
this.displayHandheld = displayHandheld;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder textureSize(int textureSize) {
|
||||
this.textureSize = textureSize;
|
||||
|
@ -152,7 +174,7 @@ 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.textureSize, this.renderOffsets);
|
||||
return new GeyserCustomItemData(this.name, this.customItemOptions, this.displayName, this.icon, this.allowOffhand, this.displayHandheld, this.textureSize, this.renderOffsets);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,12 +32,18 @@ import java.util.OptionalInt;
|
|||
|
||||
public record GeyserCustomItemOptions(TriState unbreakable,
|
||||
OptionalInt customModelData,
|
||||
OptionalInt damagePredicate) implements CustomItemOptions {
|
||||
OptionalInt damagePredicate,
|
||||
boolean defaultItem) implements CustomItemOptions {
|
||||
|
||||
public GeyserCustomItemOptions(TriState unbreakable, OptionalInt customModelData, OptionalInt damagePredicate) {
|
||||
this(unbreakable, customModelData, damagePredicate, false);
|
||||
}
|
||||
|
||||
public static class CustomItemOptionsBuilder implements CustomItemOptions.Builder {
|
||||
private TriState unbreakable = TriState.NOT_SET;
|
||||
private OptionalInt customModelData = OptionalInt.empty();
|
||||
private OptionalInt damagePredicate = OptionalInt.empty();
|
||||
private boolean defaultItem = false;
|
||||
|
||||
@Override
|
||||
public Builder unbreakable(boolean unbreakable) {
|
||||
|
@ -61,9 +67,15 @@ public record GeyserCustomItemOptions(TriState unbreakable,
|
|||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder defaultItem(boolean defaultItem) {
|
||||
this.defaultItem = defaultItem;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CustomItemOptions build() {
|
||||
return new GeyserCustomItemOptions(unbreakable, customModelData, damagePredicate);
|
||||
return new GeyserCustomItemOptions(this.unbreakable, this.customModelData, this.damagePredicate, this.defaultItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,7 +57,7 @@ public final class GeyserNonVanillaCustomItemData extends GeyserCustomItemData i
|
|||
|
||||
public GeyserNonVanillaCustomItemData(NonVanillaCustomItemDataBuilder builder) {
|
||||
super(builder.name, builder.customItemOptions, builder.displayName, builder.icon, builder.allowOffhand,
|
||||
builder.textureSize, builder.renderOffsets);
|
||||
builder.displayHandheld, builder.textureSize, builder.renderOffsets);
|
||||
|
||||
this.identifier = builder.identifier;
|
||||
this.javaId = builder.javaId;
|
||||
|
@ -140,11 +140,6 @@ public final class GeyserNonVanillaCustomItemData extends GeyserCustomItemData i
|
|||
return isHat;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTool() {
|
||||
return isTool;
|
||||
}
|
||||
|
||||
public static class NonVanillaCustomItemDataBuilder extends GeyserCustomItemData.CustomItemDataBuilder implements NonVanillaCustomItemData.Builder {
|
||||
private String identifier = null;
|
||||
private int javaId = -1;
|
||||
|
@ -185,6 +180,11 @@ public final class GeyserNonVanillaCustomItemData extends GeyserCustomItemData i
|
|||
return (NonVanillaCustomItemData.Builder) super.allowOffhand(allowOffhand);
|
||||
}
|
||||
|
||||
@Override
|
||||
public NonVanillaCustomItemData.Builder displayHandheld(boolean displayHandheld) {
|
||||
return (NonVanillaCustomItemData.Builder) super.displayHandheld(displayHandheld);
|
||||
}
|
||||
|
||||
@Override
|
||||
public NonVanillaCustomItemData.Builder displayName(@NonNull String displayName) {
|
||||
return (NonVanillaCustomItemData.Builder) super.displayName(displayName);
|
||||
|
@ -283,12 +283,6 @@ public final class GeyserNonVanillaCustomItemData extends GeyserCustomItemData i
|
|||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NonVanillaCustomItemData.Builder tool(boolean isTool) {
|
||||
this.tool = isTool;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NonVanillaCustomItemData build() {
|
||||
if (identifier == null || javaId == -1) {
|
||||
|
|
|
@ -77,6 +77,11 @@ public class MappingsReader_v1 extends MappingsReader {
|
|||
customItemOptions.unbreakable(unbreakable.asBoolean());
|
||||
}
|
||||
|
||||
JsonNode defaultItem = node.get("default");
|
||||
if (defaultItem != null && defaultItem.isBoolean()) {
|
||||
customItemOptions.defaultItem(defaultItem.asBoolean());
|
||||
}
|
||||
|
||||
return customItemOptions.build();
|
||||
}
|
||||
|
||||
|
@ -86,13 +91,13 @@ public class MappingsReader_v1 extends MappingsReader {
|
|||
throw new InvalidCustomMappingsFileException("Invalid item mappings entry");
|
||||
}
|
||||
|
||||
String name = node.get("name").asText();
|
||||
if (name == null || name.isEmpty()) {
|
||||
JsonNode name = node.get("name");
|
||||
if (name == null || !name.isTextual() || name.asText().isEmpty()) {
|
||||
throw new InvalidCustomMappingsFileException("An item entry has no name");
|
||||
}
|
||||
|
||||
CustomItemData.Builder customItemData = CustomItemData.builder()
|
||||
.name(name)
|
||||
.name(name.asText())
|
||||
.customItemOptions(this.readItemCustomItemOptions(node));
|
||||
|
||||
//The next entries are optional
|
||||
|
@ -108,6 +113,10 @@ public class MappingsReader_v1 extends MappingsReader {
|
|||
customItemData.allowOffhand(node.get("allow_offhand").asBoolean());
|
||||
}
|
||||
|
||||
if (node.has("display_handheld")) {
|
||||
customItemData.displayHandheld(node.get("display_handheld").asBoolean());
|
||||
}
|
||||
|
||||
if (node.has("texture_size")) {
|
||||
customItemData.textureSize(node.get("texture_size").asInt());
|
||||
}
|
||||
|
|
|
@ -153,7 +153,7 @@ public class CustomItemRegistryPopulator {
|
|||
.build();
|
||||
|
||||
NbtMapBuilder builder = createComponentNbt(customItemData, customItemData.identifier(), customItemId,
|
||||
customItemData.creativeCategory(), customItemData.creativeGroup(), customItemData.isHat(), customItemData.isTool());
|
||||
customItemData.creativeCategory(), customItemData.creativeGroup(), customItemData.isHat(), customItemData.displayHandheld());
|
||||
ComponentItemData componentItemData = new ComponentItemData(customIdentifier, builder.build());
|
||||
|
||||
return new NonVanillaItemRegistration(componentItemData, item, customItemMapping);
|
||||
|
@ -168,7 +168,7 @@ public class CustomItemRegistryPopulator {
|
|||
NbtMapBuilder itemProperties = NbtMap.builder();
|
||||
NbtMapBuilder componentBuilder = NbtMap.builder();
|
||||
|
||||
setupBasicItemInfo(mapping.getMaxDamage(), mapping.getStackSize(), mapping.getToolType() != null, customItemData, itemProperties, componentBuilder);
|
||||
setupBasicItemInfo(mapping.getMaxDamage(), mapping.getStackSize(), mapping.getToolType() != null || customItemData.displayHandheld(), customItemData, itemProperties, componentBuilder);
|
||||
|
||||
boolean canDestroyInCreative = true;
|
||||
if (mapping.getToolType() != null) { // This is not using the isTool boolean because it is not just a render type here.
|
||||
|
@ -217,7 +217,7 @@ public class CustomItemRegistryPopulator {
|
|||
|
||||
private static NbtMapBuilder createComponentNbt(NonVanillaCustomItemData customItemData, String customItemName,
|
||||
int customItemId, OptionalInt creativeCategory,
|
||||
String creativeGroup, boolean isHat, boolean isTool) {
|
||||
String creativeGroup, boolean isHat, boolean displayHandheld) {
|
||||
NbtMapBuilder builder = NbtMap.builder();
|
||||
builder.putString("name", customItemName)
|
||||
.putInt("id", customItemId);
|
||||
|
@ -225,7 +225,7 @@ public class CustomItemRegistryPopulator {
|
|||
NbtMapBuilder itemProperties = NbtMap.builder();
|
||||
NbtMapBuilder componentBuilder = NbtMap.builder();
|
||||
|
||||
setupBasicItemInfo(customItemData.maxDamage(), customItemData.stackSize(), isTool, customItemData, itemProperties, componentBuilder);
|
||||
setupBasicItemInfo(customItemData.maxDamage(), customItemData.stackSize(), displayHandheld, customItemData, itemProperties, componentBuilder);
|
||||
|
||||
boolean canDestroyInCreative = true;
|
||||
if (customItemData.toolType() != null) { // This is not using the isTool boolean because it is not just a render type here.
|
||||
|
@ -253,14 +253,14 @@ public class CustomItemRegistryPopulator {
|
|||
return builder;
|
||||
}
|
||||
|
||||
private static void setupBasicItemInfo(int maxDamage, int stackSize, boolean isTool, CustomItemData customItemData, NbtMapBuilder itemProperties, NbtMapBuilder componentBuilder) {
|
||||
private static void setupBasicItemInfo(int maxDamage, int stackSize, boolean displayHandheld, CustomItemData customItemData, NbtMapBuilder itemProperties, NbtMapBuilder componentBuilder) {
|
||||
itemProperties.putCompound("minecraft:icon", NbtMap.builder()
|
||||
.putString("texture", customItemData.icon())
|
||||
.build());
|
||||
componentBuilder.putCompound("minecraft:display_name", NbtMap.builder().putString("value", customItemData.displayName()).build());
|
||||
|
||||
itemProperties.putBoolean("allow_off_hand", customItemData.allowOffhand());
|
||||
itemProperties.putBoolean("hand_equipped", isTool);
|
||||
itemProperties.putBoolean("hand_equipped", displayHandheld);
|
||||
itemProperties.putInt("max_stack_size", stackSize);
|
||||
// Ignore durability if the item's predicate requires that it be unbreakable
|
||||
if (maxDamage > 0 && customItemData.customItemOptions().unbreakable() != TriState.TRUE) {
|
||||
|
|
|
@ -93,6 +93,10 @@ public final class CustomItemTranslator {
|
|||
continue;
|
||||
}
|
||||
|
||||
if (options.defaultItem()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return mappingTypes.value();
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue