forked from GeyserMC/Geyser
Tipped arrow translation (#1331)
* Tipped arrow translation - Tipped arrow items are now properly translated both ways - Tipped arrow particle effects are also translated, by having a list of all colors Java could send us and their Bedrock ID * Remove a whitespace
This commit is contained in:
parent
aee9ccc7d2
commit
3c4cde9677
8 changed files with 273 additions and 6 deletions
|
@ -25,12 +25,39 @@
|
||||||
|
|
||||||
package org.geysermc.connector.entity;
|
package org.geysermc.connector.entity;
|
||||||
|
|
||||||
|
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
|
||||||
import com.nukkitx.math.vector.Vector3f;
|
import com.nukkitx.math.vector.Vector3f;
|
||||||
|
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
|
||||||
import org.geysermc.connector.entity.type.EntityType;
|
import org.geysermc.connector.entity.type.EntityType;
|
||||||
|
import org.geysermc.connector.network.session.GeyserSession;
|
||||||
|
import org.geysermc.connector.network.translators.item.TippedArrowPotion;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Internally this is known as TippedArrowEntity but is used with tipped arrows and normal arrows
|
||||||
|
*/
|
||||||
public class TippedArrowEntity extends AbstractArrowEntity {
|
public class TippedArrowEntity extends AbstractArrowEntity {
|
||||||
|
|
||||||
public TippedArrowEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
public TippedArrowEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
||||||
super(entityId, geyserId, entityType, position, motion, rotation);
|
super(entityId, geyserId, entityType, position, motion, rotation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
|
||||||
|
// Arrow potion effect color
|
||||||
|
if (entityMetadata.getId() == 9) {
|
||||||
|
int potionColor = (int) entityMetadata.getValue();
|
||||||
|
// -1 means no color
|
||||||
|
if (potionColor == -1) {
|
||||||
|
metadata.remove(EntityData.CUSTOM_DISPLAY);
|
||||||
|
} else {
|
||||||
|
TippedArrowPotion potion = TippedArrowPotion.getByJavaColor(potionColor);
|
||||||
|
if (potion != null && potion.getJavaColor() != -1) {
|
||||||
|
metadata.put(EntityData.CUSTOM_DISPLAY, (byte) potion.getBedrockId());
|
||||||
|
} else {
|
||||||
|
metadata.remove(EntityData.CUSTOM_DISPLAY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
super.updateBedrockMetadata(entityMetadata, session);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -197,7 +197,9 @@ public class ItemRegistry {
|
||||||
*/
|
*/
|
||||||
public static ItemEntry getItem(ItemData data) {
|
public static ItemEntry getItem(ItemData data) {
|
||||||
for (ItemEntry itemEntry : ITEM_ENTRIES.values()) {
|
for (ItemEntry itemEntry : ITEM_ENTRIES.values()) {
|
||||||
if (itemEntry.getBedrockId() == data.getId() && (itemEntry.getBedrockData() == data.getDamage() || itemEntry.getJavaIdentifier().endsWith("potion"))) {
|
if (itemEntry.getBedrockId() == data.getId() && (itemEntry.getBedrockData() == data.getDamage() ||
|
||||||
|
// Make exceptions for potions and tipped arrows, whose damage values can vary
|
||||||
|
(itemEntry.getJavaIdentifier().endsWith("potion") || itemEntry.getJavaIdentifier().equals("minecraft:arrow")))) {
|
||||||
return itemEntry;
|
return itemEntry;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,7 +48,7 @@ public enum Potion {
|
||||||
STRONG_SWIFTNESS(16),
|
STRONG_SWIFTNESS(16),
|
||||||
LONG_SWIFTNESS(15),
|
LONG_SWIFTNESS(15),
|
||||||
SLOWNESS(17),
|
SLOWNESS(17),
|
||||||
STRONG_SLOWNESS(18), //does not exist
|
STRONG_SLOWNESS(42),
|
||||||
LONG_SLOWNESS(18),
|
LONG_SLOWNESS(18),
|
||||||
WATER_BREATHING(19),
|
WATER_BREATHING(19),
|
||||||
LONG_WATER_BREATHING(20),
|
LONG_WATER_BREATHING(20),
|
||||||
|
|
|
@ -0,0 +1,151 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2019-2020 GeyserMC. http://geysermc.org
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* @author GeyserMC
|
||||||
|
* @link https://github.com/GeyserMC/Geyser
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.geysermc.connector.network.translators.item;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Potion identifiers and their respective Bedrock IDs used with arrows.
|
||||||
|
* https://minecraft.gamepedia.com/Arrow#Item_Data
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
public enum TippedArrowPotion {
|
||||||
|
MUNDANE(2, ArrowParticleColors.NONE), // 3 is extended?
|
||||||
|
THICK(4, ArrowParticleColors.NONE),
|
||||||
|
AWKWARD(5, ArrowParticleColors.NONE),
|
||||||
|
NIGHT_VISION(6, ArrowParticleColors.NIGHT_VISION),
|
||||||
|
LONG_NIGHT_VISION(7, ArrowParticleColors.NIGHT_VISION),
|
||||||
|
INVISIBILITY(8, ArrowParticleColors.INVISIBILITY),
|
||||||
|
LONG_INVISIBILITY(9, ArrowParticleColors.INVISIBILITY),
|
||||||
|
LEAPING(10, ArrowParticleColors.LEAPING),
|
||||||
|
LONG_LEAPING(11, ArrowParticleColors.LEAPING),
|
||||||
|
STRONG_LEAPING(12, ArrowParticleColors.LEAPING),
|
||||||
|
FIRE_RESISTANCE(13, ArrowParticleColors.FIRE_RESISTANCE),
|
||||||
|
LONG_FIRE_RESISTANCE(14, ArrowParticleColors.FIRE_RESISTANCE),
|
||||||
|
SWIFTNESS(15, ArrowParticleColors.SWIFTNESS),
|
||||||
|
LONG_SWIFTNESS(16, ArrowParticleColors.SWIFTNESS),
|
||||||
|
STRONG_SWIFTNESS(17, ArrowParticleColors.SWIFTNESS),
|
||||||
|
SLOWNESS(18, ArrowParticleColors.SLOWNESS),
|
||||||
|
LONG_SLOWNESS(19, ArrowParticleColors.SLOWNESS),
|
||||||
|
STRONG_SLOWNESS(43, ArrowParticleColors.SLOWNESS),
|
||||||
|
WATER_BREATHING(20, ArrowParticleColors.WATER_BREATHING),
|
||||||
|
LONG_WATER_BREATHING(21, ArrowParticleColors.WATER_BREATHING),
|
||||||
|
HEALING(22, ArrowParticleColors.HEALING),
|
||||||
|
STRONG_HEALING(23, ArrowParticleColors.HEALING),
|
||||||
|
HARMING(24, ArrowParticleColors.HARMING),
|
||||||
|
STRONG_HARMING(25, ArrowParticleColors.HARMING),
|
||||||
|
POISON(26, ArrowParticleColors.POISON),
|
||||||
|
LONG_POISON(27, ArrowParticleColors.POISON),
|
||||||
|
STRONG_POISON(28, ArrowParticleColors.POISON),
|
||||||
|
REGENERATION(29, ArrowParticleColors.REGENERATION),
|
||||||
|
LONG_REGENERATION(30, ArrowParticleColors.REGENERATION),
|
||||||
|
STRONG_REGENERATION(31, ArrowParticleColors.REGENERATION),
|
||||||
|
STRENGTH(32, ArrowParticleColors.STRENGTH),
|
||||||
|
LONG_STRENGTH(33, ArrowParticleColors.STRENGTH),
|
||||||
|
STRONG_STRENGTH(34, ArrowParticleColors.STRENGTH),
|
||||||
|
WEAKNESS(35, ArrowParticleColors.WEAKNESS),
|
||||||
|
LONG_WEAKNESS(36, ArrowParticleColors.WEAKNESS),
|
||||||
|
LUCK(2, ArrowParticleColors.NONE), // does not exist in Bedrock
|
||||||
|
TURTLE_MASTER(38, ArrowParticleColors.TURTLE_MASTER),
|
||||||
|
LONG_TURTLE_MASTER(39, ArrowParticleColors.TURTLE_MASTER),
|
||||||
|
STRONG_TURTLE_MASTER(40, ArrowParticleColors.TURTLE_MASTER),
|
||||||
|
SLOW_FALLING(41, ArrowParticleColors.SLOW_FALLING),
|
||||||
|
LONG_SLOW_FALLING(42, ArrowParticleColors.SLOW_FALLING);
|
||||||
|
|
||||||
|
private final String javaIdentifier;
|
||||||
|
private final short bedrockId;
|
||||||
|
/**
|
||||||
|
* The Java color associated with this ID.
|
||||||
|
* Used for looking up Java arrow color entity metadata as Bedrock potion IDs, which is what is used for entities in Bedrock
|
||||||
|
*/
|
||||||
|
private final int javaColor;
|
||||||
|
|
||||||
|
TippedArrowPotion(int bedrockId, ArrowParticleColors arrowParticleColor) {
|
||||||
|
this.javaIdentifier = "minecraft:" + this.name().toLowerCase(Locale.ENGLISH);
|
||||||
|
this.bedrockId = (short) bedrockId;
|
||||||
|
this.javaColor = arrowParticleColor.getColor();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TippedArrowPotion getByJavaIdentifier(String javaIdentifier) {
|
||||||
|
for (TippedArrowPotion potion : TippedArrowPotion.values()) {
|
||||||
|
if (potion.javaIdentifier.equals(javaIdentifier)) {
|
||||||
|
return potion;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TippedArrowPotion getByBedrockId(short bedrockId) {
|
||||||
|
for (TippedArrowPotion potion : TippedArrowPotion.values()) {
|
||||||
|
if (potion.bedrockId == bedrockId) {
|
||||||
|
return potion;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param color the potion color to look up
|
||||||
|
* @return the tipped arrow potion that most closely resembles that color.
|
||||||
|
*/
|
||||||
|
public static TippedArrowPotion getByJavaColor(int color) {
|
||||||
|
for (TippedArrowPotion potion : TippedArrowPotion.values()) {
|
||||||
|
if (potion.javaColor == color) {
|
||||||
|
return potion;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private enum ArrowParticleColors {
|
||||||
|
NONE(-1),
|
||||||
|
NIGHT_VISION(2039713),
|
||||||
|
INVISIBILITY(8356754),
|
||||||
|
LEAPING(2293580),
|
||||||
|
FIRE_RESISTANCE(14981690),
|
||||||
|
SWIFTNESS(8171462),
|
||||||
|
SLOWNESS(5926017),
|
||||||
|
TURTLE_MASTER(7691106),
|
||||||
|
WATER_BREATHING(3035801),
|
||||||
|
HEALING(16262179),
|
||||||
|
HARMING(4393481),
|
||||||
|
POISON(5149489),
|
||||||
|
REGENERATION(13458603),
|
||||||
|
STRENGTH(9643043),
|
||||||
|
WEAKNESS(4738376),
|
||||||
|
LUCK(3381504),
|
||||||
|
SLOW_FALLING(16773073);
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
private final int color;
|
||||||
|
|
||||||
|
ArrowParticleColors(int color) {
|
||||||
|
this.color = color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -50,7 +50,7 @@ import java.util.stream.Collectors;
|
||||||
@ItemRemapper
|
@ItemRemapper
|
||||||
public class BannerTranslator extends ItemTranslator {
|
public class BannerTranslator extends ItemTranslator {
|
||||||
|
|
||||||
private List<ItemEntry> appliedItems;
|
private final List<ItemEntry> appliedItems;
|
||||||
|
|
||||||
public BannerTranslator() {
|
public BannerTranslator() {
|
||||||
appliedItems = ItemRegistry.ITEM_ENTRIES.values().stream().filter(entry -> entry.getJavaIdentifier().endsWith("banner")).collect(Collectors.toList());
|
appliedItems = ItemRegistry.ITEM_ENTRIES.values().stream().filter(entry -> entry.getJavaIdentifier().endsWith("banner")).collect(Collectors.toList());
|
||||||
|
|
|
@ -40,7 +40,7 @@ import java.util.stream.Collectors;
|
||||||
@ItemRemapper
|
@ItemRemapper
|
||||||
public class CompassTranslator extends ItemTranslator {
|
public class CompassTranslator extends ItemTranslator {
|
||||||
|
|
||||||
private List<ItemEntry> appliedItems;
|
private final List<ItemEntry> appliedItems;
|
||||||
|
|
||||||
public CompassTranslator() {
|
public CompassTranslator() {
|
||||||
appliedItems = ItemRegistry.ITEM_ENTRIES.values().stream().filter(entry -> entry.getJavaIdentifier().endsWith("compass")).collect(Collectors.toList());
|
appliedItems = ItemRegistry.ITEM_ENTRIES.values().stream().filter(entry -> entry.getJavaIdentifier().endsWith("compass")).collect(Collectors.toList());
|
||||||
|
|
|
@ -42,7 +42,7 @@ import java.util.stream.Collectors;
|
||||||
@ItemRemapper
|
@ItemRemapper
|
||||||
public class PotionTranslator extends ItemTranslator {
|
public class PotionTranslator extends ItemTranslator {
|
||||||
|
|
||||||
private List<ItemEntry> appliedItems;
|
private final List<ItemEntry> appliedItems;
|
||||||
|
|
||||||
public PotionTranslator() {
|
public PotionTranslator() {
|
||||||
appliedItems = ItemRegistry.ITEM_ENTRIES.values().stream().filter(entry -> entry.getJavaIdentifier().endsWith("potion")).collect(Collectors.toList());
|
appliedItems = ItemRegistry.ITEM_ENTRIES.values().stream().filter(entry -> entry.getJavaIdentifier().endsWith("potion")).collect(Collectors.toList());
|
||||||
|
@ -57,7 +57,7 @@ public class PotionTranslator extends ItemTranslator {
|
||||||
if (potion != null) {
|
if (potion != null) {
|
||||||
return ItemData.of(itemEntry.getBedrockId(), potion.getBedrockId(), itemStack.getAmount(), translateNbtToBedrock(itemStack.getNbt()));
|
return ItemData.of(itemEntry.getBedrockId(), potion.getBedrockId(), itemStack.getAmount(), translateNbtToBedrock(itemStack.getNbt()));
|
||||||
}
|
}
|
||||||
GeyserConnector.getInstance().getLogger().debug("Unknown java potion: " + potionTag.getValue());
|
GeyserConnector.getInstance().getLogger().debug("Unknown Java potion: " + potionTag.getValue());
|
||||||
}
|
}
|
||||||
return super.translateToBedrock(itemStack, itemEntry);
|
return super.translateToBedrock(itemStack, itemEntry);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,87 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2019-2020 GeyserMC. http://geysermc.org
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* @author GeyserMC
|
||||||
|
* @link https://github.com/GeyserMC/Geyser
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.geysermc.connector.network.translators.item.translators;
|
||||||
|
|
||||||
|
import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack;
|
||||||
|
import com.github.steveice10.opennbt.tag.builtin.StringTag;
|
||||||
|
import com.github.steveice10.opennbt.tag.builtin.Tag;
|
||||||
|
import com.nukkitx.protocol.bedrock.data.inventory.ItemData;
|
||||||
|
import org.geysermc.connector.GeyserConnector;
|
||||||
|
import org.geysermc.connector.network.translators.ItemRemapper;
|
||||||
|
import org.geysermc.connector.network.translators.item.ItemEntry;
|
||||||
|
import org.geysermc.connector.network.translators.item.ItemRegistry;
|
||||||
|
import org.geysermc.connector.network.translators.item.ItemTranslator;
|
||||||
|
import org.geysermc.connector.network.translators.item.TippedArrowPotion;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@ItemRemapper
|
||||||
|
public class TippedArrowTranslator extends ItemTranslator {
|
||||||
|
|
||||||
|
private final List<ItemEntry> appliedItems;
|
||||||
|
|
||||||
|
private static final int TIPPED_ARROW_JAVA_ID = ItemRegistry.getItemEntry("minecraft:tipped_arrow").getJavaId();
|
||||||
|
|
||||||
|
public TippedArrowTranslator() {
|
||||||
|
appliedItems = ItemRegistry.ITEM_ENTRIES.values().stream().filter(entry ->
|
||||||
|
entry.getJavaIdentifier().contains("arrow") && !entry.getJavaIdentifier().contains("spectral")).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ItemData translateToBedrock(ItemStack itemStack, ItemEntry itemEntry) {
|
||||||
|
if (!itemEntry.getJavaIdentifier().equals("minecraft:tipped_arrow") || itemStack.getNbt() == null) {
|
||||||
|
// We're only concerned about minecraft:arrow when translating Bedrock -> Java
|
||||||
|
return super.translateToBedrock(itemStack, itemEntry);
|
||||||
|
}
|
||||||
|
Tag potionTag = itemStack.getNbt().get("Potion");
|
||||||
|
if (potionTag instanceof StringTag) {
|
||||||
|
TippedArrowPotion tippedArrowPotion = TippedArrowPotion.getByJavaIdentifier(((StringTag) potionTag).getValue());
|
||||||
|
if (tippedArrowPotion != null) {
|
||||||
|
return ItemData.of(itemEntry.getBedrockId(), tippedArrowPotion.getBedrockId(), itemStack.getAmount(), translateNbtToBedrock(itemStack.getNbt()));
|
||||||
|
}
|
||||||
|
GeyserConnector.getInstance().getLogger().debug("Unknown Java potion (tipped arrow): " + potionTag.getValue());
|
||||||
|
}
|
||||||
|
return super.translateToBedrock(itemStack, itemEntry);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ItemStack translateToJava(ItemData itemData, ItemEntry itemEntry) {
|
||||||
|
TippedArrowPotion tippedArrowPotion = TippedArrowPotion.getByBedrockId(itemData.getDamage());
|
||||||
|
ItemStack itemStack = super.translateToJava(itemData, itemEntry);
|
||||||
|
if (tippedArrowPotion != null) {
|
||||||
|
itemStack = new ItemStack(TIPPED_ARROW_JAVA_ID, itemStack.getAmount(), itemStack.getNbt());
|
||||||
|
StringTag potionTag = new StringTag("Potion", tippedArrowPotion.getJavaIdentifier());
|
||||||
|
itemStack.getNbt().put(potionTag);
|
||||||
|
}
|
||||||
|
return itemStack;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<ItemEntry> getAppliedItems() {
|
||||||
|
return appliedItems;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue