mirror of
https://github.com/Minestom/Minestom.git
synced 2025-02-09 08:51:38 +01:00
Added item attributes
This commit is contained in:
parent
068a0889c8
commit
619c680f1b
@ -37,4 +37,12 @@ public enum Attribute {
|
||||
public float getMaxVanillaValue() {
|
||||
return maxVanillaValue;
|
||||
}
|
||||
|
||||
public static Attribute fromKey(String key) {
|
||||
for (Attribute attribute : values()) {
|
||||
if (attribute.getKey().equals(key))
|
||||
return attribute;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ package net.minestom.server.item;
|
||||
|
||||
import net.minestom.server.data.Data;
|
||||
import net.minestom.server.data.DataContainer;
|
||||
import net.minestom.server.item.attribute.ItemAttribute;
|
||||
import net.minestom.server.item.rule.VanillaStackingRule;
|
||||
import net.minestom.server.potion.PotionType;
|
||||
import net.minestom.server.utils.validate.Check;
|
||||
@ -19,7 +20,6 @@ public class ItemStack implements DataContainer {
|
||||
private static StackingRule defaultStackingRule;
|
||||
|
||||
private short materialId;
|
||||
private Set<PotionType> potionTypes;
|
||||
|
||||
private byte amount;
|
||||
private short damage;
|
||||
@ -29,6 +29,8 @@ public class ItemStack implements DataContainer {
|
||||
private ArrayList<String> lore;
|
||||
|
||||
private Map<Enchantment, Short> enchantmentMap;
|
||||
private List<ItemAttribute> attributes;
|
||||
private Set<PotionType> potionTypes;
|
||||
|
||||
{
|
||||
if (defaultStackingRule == null)
|
||||
@ -47,6 +49,7 @@ public class ItemStack implements DataContainer {
|
||||
this.lore = new ArrayList<>();
|
||||
|
||||
this.enchantmentMap = new HashMap<>();
|
||||
this.attributes = new ArrayList<>();
|
||||
this.potionTypes = new HashSet<>();
|
||||
|
||||
this.stackingRule = defaultStackingRule;
|
||||
@ -150,6 +153,14 @@ public class ItemStack implements DataContainer {
|
||||
return this.enchantmentMap.getOrDefault(enchantment, (short) 0);
|
||||
}
|
||||
|
||||
public List<ItemAttribute> getAttributes() {
|
||||
return Collections.unmodifiableList(attributes);
|
||||
}
|
||||
|
||||
public void addAttribute(ItemAttribute itemAttribute) {
|
||||
this.attributes.add(itemAttribute);
|
||||
}
|
||||
|
||||
public Set<PotionType> getPotionTypes() {
|
||||
return Collections.unmodifiableSet(potionTypes);
|
||||
}
|
||||
@ -200,7 +211,8 @@ public class ItemStack implements DataContainer {
|
||||
}
|
||||
|
||||
public boolean hasNbtTag() {
|
||||
return hasDisplayName() || hasLore() || isUnbreakable() || !getEnchantmentMap().isEmpty() || !potionTypes.isEmpty();
|
||||
return hasDisplayName() || hasLore() || isUnbreakable() ||
|
||||
!getEnchantmentMap().isEmpty() || !attributes.isEmpty() || !potionTypes.isEmpty();
|
||||
}
|
||||
|
||||
public ItemStack clone() {
|
||||
|
@ -0,0 +1,26 @@
|
||||
package net.minestom.server.item.attribute;
|
||||
|
||||
public enum AttributeOperation {
|
||||
ADDITION(0),
|
||||
MULTIPLY_BASE(1),
|
||||
MULTIPLY_TOTAL(2);
|
||||
|
||||
private static final AttributeOperation[] VALUES = new AttributeOperation[]{ADDITION, MULTIPLY_BASE, MULTIPLY_TOTAL};
|
||||
private final int id;
|
||||
|
||||
AttributeOperation(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public static AttributeOperation byId(int id) {
|
||||
if (id >= 0 && id < VALUES.length) {
|
||||
return VALUES[id];
|
||||
} else {
|
||||
throw new IllegalArgumentException("No operation with value " + id);
|
||||
}
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return this.id;
|
||||
}
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
package net.minestom.server.item.attribute;
|
||||
|
||||
public enum AttributeSlot {
|
||||
MAINHAND,
|
||||
OFFHAND,
|
||||
FEET,
|
||||
LEGS,
|
||||
CHEST,
|
||||
HEAD
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
package net.minestom.server.item.attribute;
|
||||
|
||||
import net.minestom.server.entity.property.Attribute;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class ItemAttribute {
|
||||
|
||||
private UUID uuid;
|
||||
private String internalName;
|
||||
private Attribute attribute;
|
||||
private AttributeOperation operation;
|
||||
private double value;
|
||||
private AttributeSlot slot;
|
||||
|
||||
public ItemAttribute(UUID uuid, String internalName, Attribute attribute, AttributeOperation operation, double value, AttributeSlot slot) {
|
||||
this.uuid = uuid;
|
||||
this.internalName = internalName;
|
||||
this.attribute = attribute;
|
||||
this.operation = operation;
|
||||
this.value = value;
|
||||
this.slot = slot;
|
||||
}
|
||||
|
||||
public UUID getUuid() {
|
||||
return uuid;
|
||||
}
|
||||
|
||||
public String getInternalName() {
|
||||
return internalName;
|
||||
}
|
||||
|
||||
public Attribute getAttribute() {
|
||||
return attribute;
|
||||
}
|
||||
|
||||
public AttributeOperation getOperation() {
|
||||
return operation;
|
||||
}
|
||||
|
||||
public double getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public AttributeSlot getSlot() {
|
||||
return slot;
|
||||
}
|
||||
}
|
@ -5,15 +5,14 @@ import net.minestom.server.chat.Chat;
|
||||
import net.minestom.server.instance.Chunk;
|
||||
import net.minestom.server.item.Enchantment;
|
||||
import net.minestom.server.item.ItemStack;
|
||||
import net.minestom.server.item.attribute.ItemAttribute;
|
||||
import net.minestom.server.network.packet.PacketReader;
|
||||
import net.minestom.server.network.packet.PacketWriter;
|
||||
import net.minestom.server.potion.PotionType;
|
||||
import net.minestom.server.utils.buffer.BufferWrapper;
|
||||
import net.minestom.server.utils.item.NbtReaderUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
|
||||
public class Utils {
|
||||
|
||||
@ -184,6 +183,52 @@ public class Utils {
|
||||
}
|
||||
// End enchantment
|
||||
|
||||
// Start attribute
|
||||
{
|
||||
List<ItemAttribute> itemAttributes = itemStack.getAttributes();
|
||||
if (!itemAttributes.isEmpty()) {
|
||||
packet.writeByte((byte) 0x09); // Type id (list)
|
||||
packet.writeShortSizedString("AttributeModifiers");
|
||||
|
||||
packet.writeByte((byte) 0x0A); // Compound
|
||||
packet.writeInt(itemAttributes.size());
|
||||
|
||||
for (ItemAttribute itemAttribute : itemAttributes) {
|
||||
UUID uuid = itemAttribute.getUuid();
|
||||
|
||||
packet.writeByte((byte) 0x04); // Type id (long)
|
||||
packet.writeShortSizedString("UUIDMost");
|
||||
packet.writeLong(uuid.getMostSignificantBits());
|
||||
|
||||
packet.writeByte((byte) 0x04); // Type id (long)
|
||||
packet.writeShortSizedString("UUIDLeast");
|
||||
packet.writeLong(uuid.getLeastSignificantBits());
|
||||
|
||||
packet.writeByte((byte) 0x06); // Type id (double)
|
||||
packet.writeShortSizedString("Amount");
|
||||
packet.writeDouble(itemAttribute.getValue());
|
||||
|
||||
packet.writeByte((byte) 0x08); // Type id (string)
|
||||
packet.writeShortSizedString("Slot");
|
||||
packet.writeShortSizedString(itemAttribute.getSlot().name().toLowerCase());
|
||||
|
||||
packet.writeByte((byte) 0x08); // Type id (string)
|
||||
packet.writeShortSizedString("AttributeName");
|
||||
packet.writeShortSizedString(itemAttribute.getAttribute().getKey());
|
||||
|
||||
packet.writeByte((byte) 0x03); // Type id (int)
|
||||
packet.writeShortSizedString("Operation");
|
||||
packet.writeInt(itemAttribute.getOperation().getId());
|
||||
|
||||
packet.writeByte((byte) 0x08); // Type id (string)
|
||||
packet.writeShortSizedString("Name");
|
||||
packet.writeShortSizedString(itemAttribute.getInternalName());
|
||||
}
|
||||
packet.writeByte((byte) 0x00); // End compound
|
||||
}
|
||||
}
|
||||
// End attribute
|
||||
|
||||
// Start potion
|
||||
{
|
||||
Set<PotionType> potionTypes = itemStack.getPotionTypes();
|
||||
|
@ -2,12 +2,17 @@ package net.minestom.server.utils.item;
|
||||
|
||||
import net.kyori.text.Component;
|
||||
import net.minestom.server.chat.Chat;
|
||||
import net.minestom.server.entity.property.Attribute;
|
||||
import net.minestom.server.item.Enchantment;
|
||||
import net.minestom.server.item.ItemStack;
|
||||
import net.minestom.server.item.attribute.AttributeOperation;
|
||||
import net.minestom.server.item.attribute.AttributeSlot;
|
||||
import net.minestom.server.item.attribute.ItemAttribute;
|
||||
import net.minestom.server.network.packet.PacketReader;
|
||||
import net.minestom.server.potion.PotionType;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.UUID;
|
||||
|
||||
public class NbtReaderUtils {
|
||||
|
||||
@ -15,7 +20,7 @@ public class NbtReaderUtils {
|
||||
|
||||
byte typeId = reader.readByte();
|
||||
|
||||
//System.out.println("DEBUG TYPE: " + typeId);
|
||||
System.out.println("DEBUG TYPE: " + typeId);
|
||||
switch (typeId) {
|
||||
case 0x00: // TAG_End
|
||||
// End of item NBT
|
||||
@ -82,9 +87,9 @@ public class NbtReaderUtils {
|
||||
|
||||
if (listName.equals("StoredEnchantments")) {
|
||||
reader.readByte(); // Should be a compound (0x0A)
|
||||
int size = reader.readInteger(); // Enchants count
|
||||
int size = reader.readInteger(); // Enchantments count
|
||||
|
||||
for (int ench = 0; ench < size; ench++) {
|
||||
for (int i = 0; i < size; i++) {
|
||||
reader.readByte(); // Type id (short)
|
||||
reader.readShortSizedString(); // Constant "lvl"
|
||||
short lvl = reader.readShort();
|
||||
@ -102,6 +107,63 @@ public class NbtReaderUtils {
|
||||
|
||||
reader.readByte(); // Compound end
|
||||
|
||||
readItemStackNBT(reader, item);
|
||||
|
||||
} else if (listName.equals("AttributeModifiers")) {
|
||||
reader.readByte(); // Should be a compound (0x0A);
|
||||
int size = reader.readInteger(); // Attributes count
|
||||
for (int i = 0; i < size; i++) {
|
||||
reader.readByte(); // Type id (long)
|
||||
reader.readShortSizedString(); // Constant "UUIDMost"
|
||||
long uuidMost = reader.readLong();
|
||||
|
||||
reader.readByte(); // Type id (long)
|
||||
reader.readShortSizedString(); // Constant "UUIDLeast"
|
||||
long uuidLeast = reader.readLong();
|
||||
|
||||
final UUID uuid = new UUID(uuidMost, uuidLeast);
|
||||
|
||||
reader.readByte(); // Type id (double)
|
||||
reader.readShortSizedString(); // Constant "Amount"
|
||||
final double value = reader.readDouble();
|
||||
|
||||
reader.readByte(); // Type id (string)
|
||||
reader.readShortSizedString(); // Constant "Slot"
|
||||
final String slot = reader.readShortSizedString();
|
||||
|
||||
reader.readByte(); // Type id (string)
|
||||
reader.readShortSizedString(); // Constant "AttributeName"
|
||||
final String attributeName = reader.readShortSizedString();
|
||||
|
||||
reader.readByte(); // Type id (int)
|
||||
reader.readShortSizedString(); // Constant "Operation"
|
||||
final int operation = reader.readInteger();
|
||||
|
||||
reader.readByte(); // Type id (string)
|
||||
reader.readShortSizedString(); // Constant "Name"
|
||||
final String name = reader.readShortSizedString();
|
||||
|
||||
final Attribute attribute = Attribute.fromKey(attributeName);
|
||||
// Wrong attribute name, stop here
|
||||
if (attribute == null)
|
||||
break;
|
||||
final AttributeOperation attributeOperation = AttributeOperation.byId(operation);
|
||||
// Wrong attribute operation, stop here
|
||||
if (attributeOperation == null)
|
||||
break;
|
||||
final AttributeSlot attributeSlot = AttributeSlot.valueOf(slot.toUpperCase());
|
||||
// Wrong attribute slot, stop here
|
||||
if (attributeSlot == null)
|
||||
break;
|
||||
|
||||
// Add attribute
|
||||
final ItemAttribute itemAttribute =
|
||||
new ItemAttribute(uuid, name, attribute, attributeOperation, value, attributeSlot);
|
||||
item.addAttribute(itemAttribute);
|
||||
}
|
||||
|
||||
reader.readByte(); // Compound end
|
||||
|
||||
readItemStackNBT(reader, item);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user