mirror of
https://github.com/GeyserMC/Geyser.git
synced 2024-08-14 23:57:35 +00:00
Fix some regressions in custom item handling
This commit is contained in:
parent
f59e33d749
commit
8bf8b22d6b
2 changed files with 82 additions and 32 deletions
|
@ -51,8 +51,9 @@ final class CustomItemTranslator {
|
||||||
}
|
}
|
||||||
|
|
||||||
int customModelData = nbt.get("CustomModelData") instanceof IntTag customModelDataTag ? customModelDataTag.getValue() : 0;
|
int customModelData = nbt.get("CustomModelData") instanceof IntTag customModelDataTag ? customModelDataTag.getValue() : 0;
|
||||||
int damage = nbt.get("Damage") instanceof IntTag damageTag ? damageTag.getValue() : 0;
|
boolean checkDamage = mapping.getMaxDamage() > 0;
|
||||||
boolean unbreakable = !isDamaged(mapping, nbt, damage);
|
int damage = !checkDamage ? 0 : nbt.get("Damage") instanceof IntTag damageTag ? damageTag.getValue() : 0;
|
||||||
|
boolean unbreakable = checkDamage && !isDamaged(nbt, damage);
|
||||||
|
|
||||||
for (ObjectIntPair<CustomItemOptions> mappingTypes : customMappings) {
|
for (ObjectIntPair<CustomItemOptions> mappingTypes : customMappings) {
|
||||||
CustomItemOptions options = mappingTypes.key();
|
CustomItemOptions options = mappingTypes.key();
|
||||||
|
@ -67,12 +68,8 @@ final class CustomItemTranslator {
|
||||||
// The same behavior exists for Damage (in fraction form instead of whole numbers),
|
// The same behavior exists for Damage (in fraction form instead of whole numbers),
|
||||||
// and Damaged/Unbreakable handles no damage as 0f and damaged as 1f.
|
// and Damaged/Unbreakable handles no damage as 0f and damaged as 1f.
|
||||||
|
|
||||||
if (unbreakable && options.unbreakable() != TriState.TRUE) {
|
if (checkDamage) {
|
||||||
continue;
|
if (unbreakable && options.unbreakable() == TriState.FALSE) {
|
||||||
}
|
|
||||||
|
|
||||||
OptionalInt customModelDataOption = options.customModelData();
|
|
||||||
if (customModelDataOption.isPresent() && customModelData < customModelDataOption.getAsInt()) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,6 +77,18 @@ final class CustomItemTranslator {
|
||||||
if (damagePredicate.isPresent() && damage < damagePredicate.getAsInt()) {
|
if (damagePredicate.isPresent() && damage < damagePredicate.getAsInt()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if (options.unbreakable() != TriState.NOT_SET || options.damagePredicate().isPresent()) {
|
||||||
|
// These will never match on this item. 1.19.2 behavior
|
||||||
|
// Maybe move this to CustomItemRegistryPopulator since it'll be the same for every item? If so, add a test.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
OptionalInt customModelDataOption = options.customModelData();
|
||||||
|
if (customModelDataOption.isPresent() && customModelData < customModelDataOption.getAsInt()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
return mappingTypes.valueInt();
|
return mappingTypes.valueInt();
|
||||||
}
|
}
|
||||||
|
@ -88,16 +97,15 @@ final class CustomItemTranslator {
|
||||||
|
|
||||||
/* These two functions are based off their Mojmap equivalents from 1.19.2 */
|
/* These two functions are based off their Mojmap equivalents from 1.19.2 */
|
||||||
|
|
||||||
private static boolean isDamaged(ItemMapping mapping, CompoundTag nbt, int damage) {
|
private static boolean isDamaged(CompoundTag nbt, int damage) {
|
||||||
return isDamagableItem(mapping, nbt) && damage > 0;
|
return isDamagableItem(nbt) && damage > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isDamagableItem(ItemMapping mapping, CompoundTag nbt) {
|
private static boolean isDamagableItem(CompoundTag nbt) {
|
||||||
if (mapping.getMaxDamage() > 0) {
|
// mapping.getMaxDamage > 0 should also be checked (return false if not true) but we already check prior to this function
|
||||||
Tag unbreakableTag = nbt.get("Unbreakable");
|
Tag unbreakableTag = nbt.get("Unbreakable");
|
||||||
return unbreakableTag != null && unbreakableTag.getValue() instanceof Number number && number.byteValue() == 0;
|
// Tag must either not be present or be set to false
|
||||||
}
|
return unbreakableTag == null || !(unbreakableTag.getValue() instanceof Number number) || number.byteValue() == 0;
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private CustomItemTranslator() {
|
private CustomItemTranslator() {
|
||||||
|
|
|
@ -40,11 +40,14 @@ import org.junit.Assert;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
import java.util.OptionalInt;
|
import java.util.OptionalInt;
|
||||||
|
|
||||||
public class CustomItemsTest {
|
public class CustomItemsTest {
|
||||||
private ItemMapping testMappingWithDamage;
|
private ItemMapping testMappingWithDamage;
|
||||||
private Object2IntMap<CompoundTag> tagToCustomItemWithDamage;
|
private Object2IntMap<CompoundTag> tagToCustomItemWithDamage;
|
||||||
|
private ItemMapping testMappingWithNoDamage;
|
||||||
|
private Object2IntMap<CompoundTag> tagToCustomItemWithNoDamage;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setup() {
|
public void setup() {
|
||||||
|
@ -54,9 +57,11 @@ public class CustomItemsTest {
|
||||||
CustomItemOptions d = new GeyserCustomItemOptions(TriState.TRUE, OptionalInt.empty(), OptionalInt.of(8));
|
CustomItemOptions d = new GeyserCustomItemOptions(TriState.TRUE, OptionalInt.empty(), OptionalInt.of(8));
|
||||||
CustomItemOptions e = new GeyserCustomItemOptions(TriState.FALSE, OptionalInt.empty(), OptionalInt.of(12));
|
CustomItemOptions e = new GeyserCustomItemOptions(TriState.FALSE, OptionalInt.empty(), OptionalInt.of(12));
|
||||||
CustomItemOptions f = new GeyserCustomItemOptions(TriState.FALSE, OptionalInt.of(8), OptionalInt.of(6));
|
CustomItemOptions f = new GeyserCustomItemOptions(TriState.FALSE, OptionalInt.of(8), OptionalInt.of(6));
|
||||||
|
CustomItemOptions g = new GeyserCustomItemOptions(TriState.NOT_SET, OptionalInt.of(20), OptionalInt.empty());
|
||||||
|
|
||||||
Object2IntMap<CustomItemOptions> optionsToId = new Object2IntArrayMap<>();
|
Object2IntMap<CustomItemOptions> optionsToId = new Object2IntArrayMap<>();
|
||||||
// Order here is important, hence why we're using an array map
|
// Order here is important, hence why we're using an array map
|
||||||
|
optionsToId.put(g, 7);
|
||||||
optionsToId.put(f, 6);
|
optionsToId.put(f, 6);
|
||||||
optionsToId.put(e, 5);
|
optionsToId.put(e, 5);
|
||||||
optionsToId.put(d, 4);
|
optionsToId.put(d, 4);
|
||||||
|
@ -72,38 +77,70 @@ public class CustomItemsTest {
|
||||||
tagToCustomItemWithDamage.put(tag, optionsToId.getInt(a));
|
tagToCustomItemWithDamage.put(tag, optionsToId.getInt(a));
|
||||||
|
|
||||||
tag = new CompoundTag("");
|
tag = new CompoundTag("");
|
||||||
tag.put(new IntTag("CustomModelData", 3));
|
addCustomModelData(20, tag);
|
||||||
tag.put(new ByteTag("Unbreakable", (byte) 1));
|
// Test that an unbreakable item isn't tested for Damaged if there is no damaged predicate
|
||||||
|
tagToCustomItemWithDamage.put(tag, optionsToId.getInt(g));
|
||||||
|
|
||||||
|
tag = new CompoundTag("");
|
||||||
|
addCustomModelData(3, tag);
|
||||||
|
setUnbreakable(true, tag);
|
||||||
tagToCustomItemWithDamage.put(tag, optionsToId.getInt(a));
|
tagToCustomItemWithDamage.put(tag, optionsToId.getInt(a));
|
||||||
|
|
||||||
tag = new CompoundTag("");
|
tag = new CompoundTag("");
|
||||||
tag.put(new IntTag("Damage", 16));
|
addDamage(16, tag);
|
||||||
tag.put(new ByteTag("Unbreakable", (byte) 0));
|
setUnbreakable(false, tag);
|
||||||
tagToCustomItemWithDamage.put(tag, optionsToId.getInt(e));
|
tagToCustomItemWithDamage.put(tag, optionsToId.getInt(e));
|
||||||
|
|
||||||
tag = new CompoundTag("");
|
tag = new CompoundTag("");
|
||||||
tag.put(new IntTag("CustomModelData", 7));
|
addCustomModelData(7, tag);
|
||||||
tag.put(new IntTag("Damage", 6));
|
addDamage(6, tag);
|
||||||
tag.put(new ByteTag("Unbreakable", (byte) 0));
|
setUnbreakable(false, tag);
|
||||||
tagToCustomItemWithDamage.put(tag, optionsToId.getInt(c));
|
tagToCustomItemWithDamage.put(tag, optionsToId.getInt(c));
|
||||||
|
|
||||||
tag = new CompoundTag("");
|
tag = new CompoundTag("");
|
||||||
tag.put(new IntTag("CustomModelData", 8));
|
addCustomModelData(9, tag);
|
||||||
tag.put(new IntTag("Damage", 6));
|
addDamage(6, tag);
|
||||||
tag.put(new ByteTag("Unbreakable", (byte) 1));
|
setUnbreakable(true, tag);
|
||||||
tagToCustomItemWithDamage.put(tag, optionsToId.getInt(a));
|
tagToCustomItemWithDamage.put(tag, optionsToId.getInt(a));
|
||||||
|
|
||||||
tag = new CompoundTag("");
|
tag = new CompoundTag("");
|
||||||
tag.put(new IntTag("CustomModelData", 9));
|
addCustomModelData(9, tag);
|
||||||
tag.put(new IntTag("Damage", 6));
|
addDamage(6, tag);
|
||||||
tag.put(new ByteTag("Unbreakable", (byte) 0));
|
setUnbreakable(false, tag);
|
||||||
tagToCustomItemWithDamage.put(tag, optionsToId.getInt(f));
|
tagToCustomItemWithDamage.put(tag, optionsToId.getInt(f));
|
||||||
|
|
||||||
|
List<ObjectIntPair<CustomItemOptions>> customItemOptions = optionsToId.object2IntEntrySet().stream().map(entry -> ObjectIntPair.of(entry.getKey(), entry.getIntValue())).toList();
|
||||||
|
|
||||||
testMappingWithDamage = ItemMapping.builder()
|
testMappingWithDamage = ItemMapping.builder()
|
||||||
.customItemOptions(optionsToId.object2IntEntrySet().stream().map(entry -> ObjectIntPair.of(entry.getKey(), entry.getIntValue())).toList())
|
.customItemOptions(customItemOptions)
|
||||||
.maxDamage(100)
|
.maxDamage(100)
|
||||||
.build();
|
.build();
|
||||||
// Later, possibly add a condition with a mapping with no damage
|
|
||||||
|
// Test differences with items with no max damage
|
||||||
|
|
||||||
|
tagToCustomItemWithNoDamage = new Object2IntOpenHashMap<>();
|
||||||
|
|
||||||
|
tag = new CompoundTag("");
|
||||||
|
tag.put(new IntTag("CustomModelData", 2));
|
||||||
|
// Damage predicates existing mean an item will never match if the item mapping has no max damage
|
||||||
|
tagToCustomItemWithNoDamage.put(tag, -1);
|
||||||
|
|
||||||
|
testMappingWithNoDamage = ItemMapping.builder()
|
||||||
|
.customItemOptions(customItemOptions)
|
||||||
|
.maxDamage(0)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addCustomModelData(int value, CompoundTag tag) {
|
||||||
|
tag.put(new IntTag("CustomModelData", value));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addDamage(int value, CompoundTag tag) {
|
||||||
|
tag.put(new IntTag("Damage", value));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setUnbreakable(boolean value, CompoundTag tag) {
|
||||||
|
tag.put(new ByteTag("Unbreakable", (byte) (value ? 1 : 0)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -112,5 +149,10 @@ public class CustomItemsTest {
|
||||||
int id = CustomItemTranslator.getCustomItem(entry.getKey(), this.testMappingWithDamage);
|
int id = CustomItemTranslator.getCustomItem(entry.getKey(), this.testMappingWithDamage);
|
||||||
Assert.assertEquals(entry.getKey() + " did not produce the correct custom item", entry.getIntValue(), id);
|
Assert.assertEquals(entry.getKey() + " did not produce the correct custom item", entry.getIntValue(), id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (Object2IntMap.Entry<CompoundTag> entry : this.tagToCustomItemWithNoDamage.object2IntEntrySet()) {
|
||||||
|
int id = CustomItemTranslator.getCustomItem(entry.getKey(), this.testMappingWithNoDamage);
|
||||||
|
Assert.assertEquals(entry.getKey() + " did not produce the correct custom item", entry.getIntValue(), id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue