2019-09-30 16:44:25 +00:00
/ *
2020-01-09 03:05:42 +00:00
* Copyright ( c ) 2019 - 2020 GeyserMC . http : //geysermc.org
2019-09-30 16:44:25 +00:00
*
* 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
* /
2020-08-08 22:41:12 +00:00
package org.geysermc.connector.network.translators.bedrock.entity.player ;
2019-09-30 16:44:25 +00:00
2020-11-12 00:28:45 +00:00
import com.github.steveice10.mc.protocol.data.game.entity.player.Hand ;
import com.github.steveice10.mc.protocol.data.game.entity.player.InteractAction ;
import com.github.steveice10.mc.protocol.data.game.entity.player.PlayerState ;
import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerInteractEntityPacket ;
import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerStatePacket ;
2020-06-23 00:11:09 +00:00
import com.nukkitx.protocol.bedrock.data.entity.EntityData ;
import com.nukkitx.protocol.bedrock.data.entity.EntityDataMap ;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag ;
2020-06-27 02:51:09 +00:00
import com.nukkitx.protocol.bedrock.data.inventory.ContainerType ;
import com.nukkitx.protocol.bedrock.packet.ContainerOpenPacket ;
2020-11-12 00:28:45 +00:00
import com.nukkitx.protocol.bedrock.packet.InteractPacket ;
import lombok.Getter ;
2020-03-24 04:24:17 +00:00
import org.geysermc.connector.entity.Entity ;
2020-12-26 17:20:59 +00:00
import org.geysermc.connector.entity.living.animal.horse.AbstractHorseEntity ;
2020-11-12 00:28:45 +00:00
import org.geysermc.connector.entity.type.EntityType ;
2020-12-09 06:12:02 +00:00
import org.geysermc.connector.inventory.GeyserItemStack ;
2020-03-24 04:24:17 +00:00
import org.geysermc.connector.network.session.GeyserSession ;
import org.geysermc.connector.network.translators.PacketTranslator ;
import org.geysermc.connector.network.translators.Translator ;
2020-11-12 00:28:45 +00:00
import org.geysermc.connector.network.translators.item.ItemEntry ;
2020-05-25 01:07:05 +00:00
import org.geysermc.connector.network.translators.item.ItemRegistry ;
2019-09-30 16:44:25 +00:00
2020-11-12 00:28:45 +00:00
import java.util.Arrays ;
import java.util.List ;
2020-03-24 04:24:17 +00:00
@Translator ( packet = InteractPacket . class )
2019-09-30 16:44:25 +00:00
public class BedrockInteractTranslator extends PacketTranslator < InteractPacket > {
2020-11-12 00:28:45 +00:00
/ * *
* A list of all foods a horse / donkey can eat on Java Edition .
* Used to display interactive tag if needed .
* /
private static final List < String > DONKEY_AND_HORSE_FOODS = Arrays . asList ( " golden_apple " , " enchanted_golden_apple " ,
" golden_carrot " , " sugar " , " apple " , " wheat " , " hay_block " ) ;
/ * *
* A list of all flowers . Used for feeding bees .
* /
private static final List < String > FLOWERS = Arrays . asList ( " dandelion " , " poppy " , " blue_orchid " , " allium " , " azure_bluet " ,
" red_tulip " , " pink_tulip " , " white_tulip " , " orange_tulip " , " cornflower " , " lily_of_the_valley " , " wither_rose " ,
" sunflower " , " lilac " , " rose_bush " , " peony " ) ;
/ * *
* All entity types that can be leashed on Java Edition
* /
private static final List < EntityType > LEASHABLE_MOB_TYPES = Arrays . asList ( EntityType . BEE , EntityType . CAT , EntityType . CHICKEN ,
EntityType . COW , EntityType . DOLPHIN , EntityType . DONKEY , EntityType . FOX , EntityType . HOGLIN , EntityType . HORSE , EntityType . SKELETON_HORSE ,
EntityType . ZOMBIE_HORSE , EntityType . IRON_GOLEM , EntityType . LLAMA , EntityType . TRADER_LLAMA , EntityType . MOOSHROOM ,
EntityType . MULE , EntityType . OCELOT , EntityType . PARROT , EntityType . PIG , EntityType . POLAR_BEAR , EntityType . RABBIT ,
EntityType . SHEEP , EntityType . SNOW_GOLEM , EntityType . STRIDER , EntityType . WOLF , EntityType . ZOGLIN ) ;
private static final List < EntityType > SADDLEABLE_WHEN_TAMED_MOB_TYPES = Arrays . asList ( EntityType . DONKEY , EntityType . HORSE ,
EntityType . ZOMBIE_HORSE , EntityType . MULE ) ;
/ * *
* A list of all foods a wolf can eat on Java Edition .
* Used to display interactive tag if needed .
* /
private static final List < String > WOLF_FOODS = Arrays . asList ( " pufferfish " , " tropical_fish " , " chicken " , " cooked_chicken " ,
" porkchop " , " beef " , " rabbit " , " cooked_porkchop " , " cooked_beef " , " rotten_flesh " , " mutton " , " cooked_mutton " ,
" cooked_rabbit " ) ;
2019-09-30 16:44:25 +00:00
@Override
public void translate ( InteractPacket packet , GeyserSession session ) {
2020-06-27 02:51:09 +00:00
Entity entity ;
if ( packet . getRuntimeEntityId ( ) = = session . getPlayerEntity ( ) . getGeyserId ( ) ) {
//Player is not in entity cache
entity = session . getPlayerEntity ( ) ;
} else {
entity = session . getEntityCache ( ) . getEntityByGeyserId ( packet . getRuntimeEntityId ( ) ) ;
}
2019-10-16 20:32:53 +00:00
if ( entity = = null )
return ;
2019-09-30 16:44:25 +00:00
2019-10-16 20:32:53 +00:00
switch ( packet . getAction ( ) ) {
2020-02-16 19:07:35 +00:00
case INTERACT :
2020-10-16 23:25:05 +00:00
if ( session . getPlayerInventory ( ) . getItemInHand ( ) . getId ( ) = = ItemRegistry . SHIELD . getJavaId ( ) ) {
2020-04-25 03:11:28 +00:00
break ;
}
2019-10-16 20:32:53 +00:00
ClientPlayerInteractEntityPacket interactPacket = new ClientPlayerInteractEntityPacket ( ( int ) entity . getEntityId ( ) ,
2020-06-21 02:24:45 +00:00
InteractAction . INTERACT , Hand . MAIN_HAND , session . isSneaking ( ) ) ;
2020-05-05 15:51:43 +00:00
session . sendDownstreamPacket ( interactPacket ) ;
2019-10-16 20:32:53 +00:00
break ;
2020-02-14 23:27:08 +00:00
case DAMAGE :
2019-10-16 20:32:53 +00:00
ClientPlayerInteractEntityPacket attackPacket = new ClientPlayerInteractEntityPacket ( ( int ) entity . getEntityId ( ) ,
2020-06-21 02:24:45 +00:00
InteractAction . ATTACK , Hand . MAIN_HAND , session . isSneaking ( ) ) ;
2020-05-05 15:51:43 +00:00
session . sendDownstreamPacket ( attackPacket ) ;
2019-10-16 20:32:53 +00:00
break ;
2020-05-23 21:39:17 +00:00
case LEAVE_VEHICLE :
ClientPlayerStatePacket sneakPacket = new ClientPlayerStatePacket ( ( int ) entity . getEntityId ( ) , PlayerState . START_SNEAKING ) ;
session . sendDownstreamPacket ( sneakPacket ) ;
session . setRidingVehicleEntity ( null ) ;
break ;
case MOUSEOVER :
// Handle the buttons for mobile - "Mount", etc; and the suggestions for console - "ZL: Mount", etc
if ( packet . getRuntimeEntityId ( ) ! = 0 ) {
Entity interactEntity = session . getEntityCache ( ) . getEntityByGeyserId ( packet . getRuntimeEntityId ( ) ) ;
if ( interactEntity = = null )
return ;
2020-06-20 17:44:40 +00:00
EntityDataMap entityMetadata = interactEntity . getMetadata ( ) ;
2020-12-09 06:12:02 +00:00
ItemEntry itemEntry = session . getPlayerInventory ( ) . getItemInHand ( ) = = GeyserItemStack . EMPTY ? ItemEntry . AIR : ItemRegistry . getItem ( session . getPlayerInventory ( ) . getItemInHand ( ) . getItemStack ( ) ) ;
2020-11-12 00:28:45 +00:00
String javaIdentifierStripped = itemEntry . getJavaIdentifier ( ) . replace ( " minecraft: " , " " ) ;
2020-05-23 21:39:17 +00:00
2020-11-12 00:28:45 +00:00
// TODO - in the future, update these in the metadata? So the client doesn't have to wiggle their cursor around for it to happen
// TODO - also, might be good to abstract out the eating thing. I know there will need to be food tracked for https://github.com/GeyserMC/Geyser/issues/1005 but not all food is breeding food
InteractiveTag interactiveTag = InteractiveTag . NONE ;
if ( entityMetadata . getLong ( EntityData . LEASH_HOLDER_EID ) = = session . getPlayerEntity ( ) . getGeyserId ( ) ) {
// Unleash the entity
interactiveTag = InteractiveTag . REMOVE_LEASH ;
} else if ( javaIdentifierStripped . equals ( " saddle " ) & & ! entityMetadata . getFlags ( ) . getFlag ( EntityFlag . SADDLED ) & &
( ( SADDLEABLE_WHEN_TAMED_MOB_TYPES . contains ( interactEntity . getEntityType ( ) ) & & entityMetadata . getFlags ( ) . getFlag ( EntityFlag . TAMED ) ) | |
interactEntity . getEntityType ( ) = = EntityType . PIG | | interactEntity . getEntityType ( ) = = EntityType . STRIDER ) ) {
// Entity can be saddled and the conditions meet (entity can be saddled and, if needed, is tamed)
interactiveTag = InteractiveTag . SADDLE ;
2020-12-09 06:12:02 +00:00
} else if ( javaIdentifierStripped . equals ( " name_tag " ) & & session . getPlayerInventory ( ) . getItemInHand ( ) . getNbt ( ) ! = null & &
session . getPlayerInventory ( ) . getItemInHand ( ) . getNbt ( ) . contains ( " display " ) ) {
2020-11-12 00:28:45 +00:00
// Holding a named name tag
interactiveTag = InteractiveTag . NAME ;
} else if ( javaIdentifierStripped . equals ( " lead " ) & & LEASHABLE_MOB_TYPES . contains ( interactEntity . getEntityType ( ) ) & &
entityMetadata . getLong ( EntityData . LEASH_HOLDER_EID ) = = - 1L ) {
// Holding a leash and the mob is leashable for sure
// (Plugins can change this behavior so that's something to look into in the far far future)
interactiveTag = InteractiveTag . LEASH ;
} else {
switch ( interactEntity . getEntityType ( ) ) {
case BEE :
if ( FLOWERS . contains ( javaIdentifierStripped ) ) {
interactiveTag = InteractiveTag . FEED ;
}
break ;
case BOAT :
interactiveTag = InteractiveTag . BOARD_BOAT ;
break ;
case CAT :
if ( javaIdentifierStripped . equals ( " cod " ) | | javaIdentifierStripped . equals ( " salmon " ) ) {
interactiveTag = InteractiveTag . FEED ;
} else if ( entityMetadata . getFlags ( ) . getFlag ( EntityFlag . TAMED ) & &
entityMetadata . getLong ( EntityData . OWNER_EID ) = = session . getPlayerEntity ( ) . getGeyserId ( ) ) {
// Tamed and owned by player - can sit/stand
interactiveTag = entityMetadata . getFlags ( ) . getFlag ( EntityFlag . SITTING ) ? InteractiveTag . STAND : InteractiveTag . SIT ;
break ;
}
break ;
case CHICKEN :
if ( javaIdentifierStripped . contains ( " seeds " ) ) {
interactiveTag = InteractiveTag . FEED ;
}
break ;
case MOOSHROOM :
// Shear the mooshroom
if ( javaIdentifierStripped . equals ( " shears " ) ) {
interactiveTag = InteractiveTag . MOOSHROOM_SHEAR ;
break ;
}
// Bowls are acceptable here
else if ( javaIdentifierStripped . equals ( " bowl " ) ) {
interactiveTag = InteractiveTag . MOOSHROOM_MILK_STEW ;
break ;
}
// Fall down to COW as this works on mooshrooms
case COW :
if ( javaIdentifierStripped . equals ( " wheat " ) ) {
interactiveTag = InteractiveTag . FEED ;
} else if ( javaIdentifierStripped . equals ( " bucket " ) ) {
// Milk the cow
interactiveTag = InteractiveTag . MILK ;
}
break ;
case CREEPER :
if ( javaIdentifierStripped . equals ( " flint_and_steel " ) ) {
// Today I learned that you can ignite a creeper with flint and steel! Huh.
interactiveTag = InteractiveTag . IGNITE_CREEPER ;
}
break ;
case DONKEY :
case LLAMA :
case MULE :
if ( entityMetadata . getFlags ( ) . getFlag ( EntityFlag . TAMED ) & & ! entityMetadata . getFlags ( ) . getFlag ( EntityFlag . CHESTED )
& & javaIdentifierStripped . equals ( " chest " ) ) {
// Can attach a chest
interactiveTag = InteractiveTag . ATTACH_CHEST ;
break ;
}
// Intentional fall-through
case HORSE :
case SKELETON_HORSE :
case TRADER_LLAMA :
case ZOMBIE_HORSE :
// have another switch statement as, while these share mount attributes they don't share food
switch ( interactEntity . getEntityType ( ) ) {
case LLAMA :
case TRADER_LLAMA :
if ( javaIdentifierStripped . equals ( " wheat " ) | | javaIdentifierStripped . equals ( " hay_block " ) ) {
interactiveTag = InteractiveTag . FEED ;
break ;
}
case DONKEY :
case HORSE :
// Undead can't eat
if ( DONKEY_AND_HORSE_FOODS . contains ( javaIdentifierStripped ) ) {
interactiveTag = InteractiveTag . FEED ;
break ;
}
}
if ( ! entityMetadata . getFlags ( ) . getFlag ( EntityFlag . BABY ) ) {
// Can't ride a baby
if ( entityMetadata . getFlags ( ) . getFlag ( EntityFlag . TAMED ) ) {
interactiveTag = InteractiveTag . RIDE_HORSE ;
} else if ( ! entityMetadata . getFlags ( ) . getFlag ( EntityFlag . TAMED ) & & itemEntry . equals ( ItemEntry . AIR ) ) {
// Can't hide an untamed entity without having your hand empty
interactiveTag = InteractiveTag . MOUNT ;
}
}
break ;
case FOX :
if ( javaIdentifierStripped . equals ( " sweet_berries " ) ) {
interactiveTag = InteractiveTag . FEED ;
}
break ;
case HOGLIN :
if ( javaIdentifierStripped . equals ( " crimson_fungus " ) ) {
interactiveTag = InteractiveTag . FEED ;
}
break ;
case MINECART :
interactiveTag = InteractiveTag . RIDE_MINECART ;
break ;
case MINECART_CHEST :
case MINECART_COMMAND_BLOCK :
case MINECART_HOPPER :
interactiveTag = InteractiveTag . OPEN_CONTAINER ;
break ;
case OCELOT :
if ( javaIdentifierStripped . equals ( " cod " ) | | javaIdentifierStripped . equals ( " salmon " ) ) {
interactiveTag = InteractiveTag . FEED ;
}
break ;
case PANDA :
if ( javaIdentifierStripped . equals ( " bamboo " ) ) {
interactiveTag = InteractiveTag . FEED ;
}
break ;
case PARROT :
if ( javaIdentifierStripped . contains ( " seeds " ) | | javaIdentifierStripped . equals ( " cookie " ) ) {
interactiveTag = InteractiveTag . FEED ;
}
break ;
case PIG :
if ( javaIdentifierStripped . equals ( " carrot " ) | | javaIdentifierStripped . equals ( " potato " ) | | javaIdentifierStripped . equals ( " beetroot " ) ) {
interactiveTag = InteractiveTag . FEED ;
} else if ( entityMetadata . getFlags ( ) . getFlag ( EntityFlag . SADDLED ) ) {
interactiveTag = InteractiveTag . MOUNT ;
}
break ;
case PIGLIN :
if ( ! entityMetadata . getFlags ( ) . getFlag ( EntityFlag . BABY ) & & javaIdentifierStripped . equals ( " gold_ingot " ) ) {
interactiveTag = InteractiveTag . BARTER ;
}
break ;
case RABBIT :
if ( javaIdentifierStripped . equals ( " dandelion " ) | | javaIdentifierStripped . equals ( " carrot " ) | | javaIdentifierStripped . equals ( " golden_carrot " ) ) {
interactiveTag = InteractiveTag . FEED ;
}
break ;
case SHEEP :
if ( javaIdentifierStripped . equals ( " wheat " ) ) {
interactiveTag = InteractiveTag . FEED ;
} else if ( ! entityMetadata . getFlags ( ) . getFlag ( EntityFlag . SHEARED ) ) {
if ( javaIdentifierStripped . equals ( " shears " ) ) {
// Shear the sheep
interactiveTag = InteractiveTag . SHEAR ;
} else if ( javaIdentifierStripped . contains ( " _dye " ) ) {
// Dye the sheep
interactiveTag = InteractiveTag . DYE ;
}
}
break ;
case STRIDER :
if ( javaIdentifierStripped . equals ( " warped_fungus " ) ) {
interactiveTag = InteractiveTag . FEED ;
} else if ( entityMetadata . getFlags ( ) . getFlag ( EntityFlag . SADDLED ) ) {
interactiveTag = InteractiveTag . RIDE_STRIDER ;
}
break ;
case TURTLE :
if ( javaIdentifierStripped . equals ( " seagrass " ) ) {
interactiveTag = InteractiveTag . FEED ;
}
break ;
case VILLAGER :
if ( entityMetadata . getInt ( EntityData . VARIANT ) ! = 14 & & entityMetadata . getInt ( EntityData . VARIANT ) ! = 0
& & entityMetadata . getFloat ( EntityData . SCALE ) > = 0 . 75f ) { // Not a nitwit, has a profession and is not a baby
interactiveTag = InteractiveTag . TRADE ;
}
break ;
case WANDERING_TRADER :
interactiveTag = InteractiveTag . TRADE ; // Since you can always trade with a wandering villager, presumably.
break ;
case WOLF :
if ( javaIdentifierStripped . equals ( " bone " ) & & ! entityMetadata . getFlags ( ) . getFlag ( EntityFlag . TAMED ) ) {
// Bone and untamed - can tame
interactiveTag = InteractiveTag . TAME ;
} else if ( WOLF_FOODS . contains ( javaIdentifierStripped ) ) {
// Compatible food in hand - feed
// Sometimes just sits/stands when the wolf isn't hungry - there doesn't appear to be a way to fix this
interactiveTag = InteractiveTag . FEED ;
} else if ( entityMetadata . getFlags ( ) . getFlag ( EntityFlag . TAMED ) & &
entityMetadata . getLong ( EntityData . OWNER_EID ) = = session . getPlayerEntity ( ) . getGeyserId ( ) ) {
// Tamed and owned by player - can sit/stand
interactiveTag = entityMetadata . getFlags ( ) . getFlag ( EntityFlag . SITTING ) ? InteractiveTag . STAND : InteractiveTag . SIT ;
}
break ;
case ZOMBIE_VILLAGER :
// We can't guarantee the existence of the weakness effect so we just always show it.
if ( javaIdentifierStripped . equals ( " golden_apple " ) ) {
interactiveTag = InteractiveTag . CURE ;
}
break ;
default :
break ;
}
2020-05-23 21:39:17 +00:00
}
2020-11-12 00:28:45 +00:00
session . getPlayerEntity ( ) . getMetadata ( ) . put ( EntityData . INTERACTIVE_TAG , interactiveTag . getValue ( ) ) ;
2020-05-23 21:39:17 +00:00
session . getPlayerEntity ( ) . updateBedrockMetadata ( session ) ;
} else {
2020-11-12 00:28:45 +00:00
if ( ! session . getPlayerEntity ( ) . getMetadata ( ) . getString ( EntityData . INTERACTIVE_TAG ) . isEmpty ( ) ) {
2020-05-23 21:39:17 +00:00
// No interactive tag should be sent
session . getPlayerEntity ( ) . getMetadata ( ) . remove ( EntityData . INTERACTIVE_TAG ) ;
session . getPlayerEntity ( ) . updateBedrockMetadata ( session ) ;
}
}
break ;
2020-06-27 02:51:09 +00:00
case OPEN_INVENTORY :
2020-10-16 23:25:05 +00:00
if ( session . getOpenInventory ( ) = = null ) {
2020-12-26 17:20:59 +00:00
Entity ridingEntity = session . getRidingVehicleEntity ( ) ;
if ( ridingEntity instanceof AbstractHorseEntity ) {
if ( ridingEntity . getMetadata ( ) . getFlags ( ) . getFlag ( EntityFlag . TAMED ) ) {
// We should request to open the horse inventory instead
ClientPlayerStatePacket openHorseWindowPacket = new ClientPlayerStatePacket ( ( int ) session . getPlayerEntity ( ) . getEntityId ( ) , PlayerState . OPEN_HORSE_INVENTORY ) ;
session . sendDownstreamPacket ( openHorseWindowPacket ) ;
}
} else {
session . setOpenInventory ( session . getPlayerInventory ( ) ) ;
2020-10-16 23:25:05 +00:00
2020-12-26 17:20:59 +00:00
ContainerOpenPacket containerOpenPacket = new ContainerOpenPacket ( ) ;
containerOpenPacket . setId ( ( byte ) 0 ) ;
containerOpenPacket . setType ( ContainerType . INVENTORY ) ;
containerOpenPacket . setUniqueEntityId ( - 1 ) ;
containerOpenPacket . setBlockPosition ( entity . getPosition ( ) . toInt ( ) ) ;
session . sendUpstreamPacket ( containerOpenPacket ) ;
}
2020-07-27 15:17:55 +00:00
}
2020-06-27 02:51:09 +00:00
break ;
2019-09-30 16:44:25 +00:00
}
}
2020-11-12 00:28:45 +00:00
/ * *
* All interactive tags in enum form . For potential API usage .
* /
public enum InteractiveTag {
NONE ( true ) ,
IGNITE_CREEPER ( " creeper " ) ,
EDIT ,
LEAVE_BOAT ( " exit.boat " ) ,
FEED ,
FISH ( " fishing " ) ,
MILK ,
MOOSHROOM_SHEAR ( " mooshear " ) ,
MOOSHROOM_MILK_STEW ( " moostew " ) ,
BOARD_BOAT ( " ride.boat " ) ,
RIDE_MINECART ( " ride.minecart " ) ,
RIDE_HORSE ( " ride.horse " ) ,
RIDE_STRIDER ( " ride.strider " ) ,
SHEAR ,
SIT ,
STAND ,
TALK ,
TAME ,
DYE ,
CURE ,
OPEN_CONTAINER ( " opencontainer " ) ,
CREATE_MAP ( " createMap " ) ,
TAKE_PICTURE ( " takepicture " ) ,
SADDLE ,
MOUNT ,
BOOST ,
WRITE ,
LEASH ,
REMOVE_LEASH ( " unleash " ) ,
NAME ,
ATTACH_CHEST ( " attachchest " ) ,
TRADE ,
POSE_ARMOR_STAND ( " armorstand.pose " ) ,
EQUIP_ARMOR_STAND ( " armorstand.equip " ) ,
READ ,
WAKE_VILLAGER ( " wakevillager " ) ,
BARTER ;
/ * *
* The full string that should be passed on to the client .
* /
@Getter
private final String value ;
InteractiveTag ( boolean isNone ) {
this . value = " " ;
}
InteractiveTag ( String value ) {
this . value = " action.interact. " + value ;
}
InteractiveTag ( ) {
this . value = " action.interact. " + name ( ) . toLowerCase ( ) ;
}
}
2019-09-30 16:44:25 +00:00
}