2019-08-03 03:38:09 +00:00
/ *
2021-01-01 15:10:36 +00:00
* Copyright ( c ) 2019 - 2021 GeyserMC . http : //geysermc.org
2019-08-03 03:38:09 +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
* /
package org.geysermc.connector.entity ;
2019-11-28 01:30:30 +00:00
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata ;
2020-05-23 21:09:11 +00:00
import com.github.steveice10.mc.protocol.data.game.entity.metadata.Pose ;
2021-11-18 03:02:38 +00:00
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanEntityMetadata ;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata ;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata ;
2019-10-09 18:39:38 +00:00
import com.nukkitx.math.vector.Vector3f ;
2020-06-23 00:11:09 +00:00
import com.nukkitx.protocol.bedrock.data.entity.EntityData ;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag ;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlags ;
2021-07-08 02:44:53 +00:00
import com.nukkitx.protocol.bedrock.packet.AddEntityPacket ;
import com.nukkitx.protocol.bedrock.packet.MoveEntityAbsolutePacket ;
import com.nukkitx.protocol.bedrock.packet.RemoveEntityPacket ;
import com.nukkitx.protocol.bedrock.packet.SetEntityDataPacket ;
2019-11-30 19:26:51 +00:00
import it.unimi.dsi.fastutil.longs.LongOpenHashSet ;
2021-11-18 03:02:38 +00:00
import lombok.AccessLevel ;
2019-08-03 03:38:09 +00:00
import lombok.Getter ;
import lombok.Setter ;
2020-11-27 23:28:08 +00:00
import net.kyori.adventure.text.Component ;
2019-08-03 03:38:09 +00:00
import org.geysermc.connector.network.session.GeyserSession ;
2020-11-16 23:57:57 +00:00
import org.geysermc.connector.network.translators.chat.MessageTranslator ;
2021-07-20 16:08:48 +00:00
import org.geysermc.connector.utils.MathUtils ;
2019-08-03 03:38:09 +00:00
2021-11-18 03:02:38 +00:00
import java.util.UUID ;
2019-08-03 03:38:09 +00:00
@Getter
@Setter
public class Entity {
2021-11-18 03:02:38 +00:00
protected final GeyserSession session ;
2019-08-03 03:38:09 +00:00
protected long entityId ;
2021-10-10 18:54:06 +00:00
protected final long geyserId ;
2021-11-18 03:02:38 +00:00
protected UUID uuid ;
2019-08-03 03:38:09 +00:00
protected Vector3f position ;
protected Vector3f motion ;
2019-08-03 06:51:05 +00:00
2019-10-02 20:45:29 +00:00
/ * *
* x = Yaw , y = Pitch , z = HeadYaw
* /
2021-11-18 03:02:38 +00:00
protected float yaw ;
protected float pitch ;
protected float headYaw ;
2019-08-03 03:38:09 +00:00
2020-06-16 23:58:06 +00:00
/ * *
* Saves if the entity should be on the ground . Otherwise entities like parrots are flapping when rotating
* /
protected boolean onGround ;
2021-11-18 03:02:38 +00:00
protected EntityDefinition < ? > definition ;
2019-08-03 03:38:09 +00:00
protected boolean valid ;
2021-11-18 03:02:38 +00:00
/* Metadata about this specific entity */
@Setter ( AccessLevel . NONE )
protected float boundingBoxHeight ;
@Setter ( AccessLevel . NONE )
protected float boundingBoxWidth ;
2021-11-19 01:44:03 +00:00
@Setter ( AccessLevel . NONE )
protected String nametag = " " ;
2021-11-18 03:02:38 +00:00
/* Metadata end */
2020-05-23 21:39:17 +00:00
protected LongOpenHashSet passengers = new LongOpenHashSet ( ) ;
2021-11-18 03:02:38 +00:00
/ * *
* A container to store temporary metadata before it ' s sent to Bedrock .
* /
2021-11-19 01:44:03 +00:00
protected final GeyserDirtyMetadata dirtyMetadata = new GeyserDirtyMetadata ( ) ;
2021-11-18 03:02:38 +00:00
/ * *
* The entity flags for the Bedrock entity .
* These must always be saved - if flags are updated and the other values aren ' t present , the Bedrock client will
* think they are set to false .
* /
@Getter ( AccessLevel . NONE )
protected final EntityFlags flags = new EntityFlags ( ) ;
/ * *
* Indicates if flags have been updated and need to be sent to the client .
* /
@Getter ( AccessLevel . NONE )
@Setter ( AccessLevel . PROTECTED ) // For players
private boolean flagsDirty = false ;
public Entity ( GeyserSession session , long entityId , long geyserId , UUID uuid , EntityDefinition < ? > definition , Vector3f position , Vector3f motion , float yaw , float pitch , float headYaw ) {
this . session = session ;
2019-08-03 03:38:09 +00:00
this . entityId = entityId ;
this . geyserId = geyserId ;
2021-11-18 03:02:38 +00:00
this . uuid = uuid ;
this . definition = definition ;
2019-08-03 03:38:09 +00:00
this . motion = motion ;
2021-11-18 03:02:38 +00:00
this . yaw = yaw ;
this . pitch = pitch ;
this . headYaw = headYaw ;
2019-08-03 03:38:09 +00:00
this . valid = false ;
2019-10-18 07:54:20 +00:00
2020-02-15 23:39:34 +00:00
setPosition ( position ) ;
2021-07-20 16:08:48 +00:00
setAir ( getMaxAir ( ) ) ;
2020-02-15 23:39:34 +00:00
2021-11-18 03:02:38 +00:00
initializeMetadata ( ) ;
}
/ * *
* Called on entity spawn . Used to populate the entity metadata and flags with default values .
* /
protected void initializeMetadata ( ) {
dirtyMetadata . put ( EntityData . SCALE , 1f ) ;
dirtyMetadata . put ( EntityData . COLOR , 0 ) ;
dirtyMetadata . put ( EntityData . MAX_AIR_SUPPLY , getMaxAir ( ) ) ;
setDimensions ( Pose . STANDING ) ;
setFlag ( EntityFlag . HAS_GRAVITY , true ) ;
setFlag ( EntityFlag . HAS_COLLISION , true ) ;
setFlag ( EntityFlag . CAN_SHOW_NAME , true ) ;
setFlag ( EntityFlag . CAN_CLIMB , true ) ;
2019-08-03 03:38:09 +00:00
}
2021-11-18 03:02:38 +00:00
public void spawnEntity ( ) {
2019-08-03 03:38:09 +00:00
AddEntityPacket addEntityPacket = new AddEntityPacket ( ) ;
2021-11-18 03:02:38 +00:00
addEntityPacket . setIdentifier ( definition . identifier ( ) ) ;
2019-08-03 03:38:09 +00:00
addEntityPacket . setRuntimeEntityId ( geyserId ) ;
2019-08-03 06:51:05 +00:00
addEntityPacket . setUniqueEntityId ( geyserId ) ;
2019-08-03 03:38:09 +00:00
addEntityPacket . setPosition ( position ) ;
addEntityPacket . setMotion ( motion ) ;
2019-10-02 20:45:29 +00:00
addEntityPacket . setRotation ( getBedrockRotation ( ) ) ;
2021-11-19 01:44:03 +00:00
addEntityPacket . getMetadata ( ) . putFlags ( flags ) ;
dirtyMetadata . apply ( addEntityPacket . getMetadata ( ) ) ;
2021-07-08 02:44:53 +00:00
addAdditionalSpawnData ( addEntityPacket ) ;
2019-08-03 03:38:09 +00:00
valid = true ;
2020-05-05 15:51:43 +00:00
session . sendUpstreamPacket ( addEntityPacket ) ;
2019-08-03 06:51:05 +00:00
2021-11-18 03:02:38 +00:00
flagsDirty = false ;
session . getConnector ( ) . getLogger ( ) . debug ( " Spawned entity " + getClass ( ) . getName ( ) + " at location " + position + " with id " + geyserId + " (java id " + entityId + " ) " ) ;
2019-08-03 03:38:09 +00:00
}
2021-07-08 02:44:53 +00:00
/ * *
* To be overridden in other entity classes , if additional things need to be done to the spawn entity packet .
* /
public void addAdditionalSpawnData ( AddEntityPacket addEntityPacket ) {
}
2019-10-02 20:45:29 +00:00
/ * *
2020-04-22 06:03:46 +00:00
* Despawns the entity
*
2019-10-02 20:45:29 +00:00
* @return can be deleted
* /
2021-11-18 03:02:38 +00:00
public boolean despawnEntity ( ) {
2019-10-02 20:45:29 +00:00
if ( ! valid ) return true ;
2019-08-03 03:38:09 +00:00
2020-07-04 14:26:32 +00:00
for ( long passenger : passengers ) { // Make sure all passengers on the despawned entity are updated
2020-07-03 21:55:54 +00:00
Entity entity = session . getEntityCache ( ) . getEntityByJavaId ( passenger ) ;
2020-07-04 14:26:32 +00:00
if ( entity = = null ) continue ;
2021-11-18 03:02:38 +00:00
entity . setFlag ( EntityFlag . RIDING , false ) ;
entity . updateBedrockMetadata ( ) ;
2020-07-03 21:55:54 +00:00
}
2019-08-03 03:38:09 +00:00
RemoveEntityPacket removeEntityPacket = new RemoveEntityPacket ( ) ;
2019-08-03 06:51:05 +00:00
removeEntityPacket . setUniqueEntityId ( geyserId ) ;
2020-05-05 15:51:43 +00:00
session . sendUpstreamPacket ( removeEntityPacket ) ;
2019-09-15 04:19:13 +00:00
valid = false ;
2019-10-02 20:45:29 +00:00
return true ;
2019-08-03 03:38:09 +00:00
}
2021-11-18 03:02:38 +00:00
public void moveRelative ( double relX , double relY , double relZ , float yaw , float pitch , boolean isOnGround ) {
moveRelative ( relX , relY , relZ , yaw , pitch , this . headYaw , isOnGround ) ;
2019-08-03 06:51:05 +00:00
}
2019-08-03 03:38:09 +00:00
2021-11-18 03:02:38 +00:00
public void moveRelative ( double relX , double relY , double relZ , float yaw , float pitch , float headYaw , boolean isOnGround ) {
setYaw ( yaw ) ;
setPitch ( pitch ) ;
setHeadYaw ( headYaw ) ;
2020-06-16 23:58:06 +00:00
setOnGround ( isOnGround ) ;
2019-10-09 18:39:38 +00:00
this . position = Vector3f . from ( position . getX ( ) + relX , position . getY ( ) + relY , position . getZ ( ) + relZ ) ;
2020-02-15 23:39:34 +00:00
MoveEntityAbsolutePacket moveEntityPacket = new MoveEntityAbsolutePacket ( ) ;
moveEntityPacket . setRuntimeEntityId ( geyserId ) ;
moveEntityPacket . setPosition ( position ) ;
moveEntityPacket . setRotation ( getBedrockRotation ( ) ) ;
moveEntityPacket . setOnGround ( isOnGround ) ;
moveEntityPacket . setTeleported ( false ) ;
2020-05-05 15:51:43 +00:00
session . sendUpstreamPacket ( moveEntityPacket ) ;
2019-08-03 03:38:09 +00:00
}
2021-11-18 03:02:38 +00:00
public void moveAbsolute ( Vector3f position , float yaw , float pitch , boolean isOnGround , boolean teleported ) {
moveAbsolute ( position , yaw , pitch , this . headYaw , isOnGround , teleported ) ;
2019-08-03 06:51:05 +00:00
}
2021-11-18 03:02:38 +00:00
public void moveAbsolute ( Vector3f position , float yaw , float pitch , float headYaw , boolean isOnGround , boolean teleported ) {
2019-09-25 21:52:28 +00:00
setPosition ( position ) ;
2021-11-18 03:02:38 +00:00
// Setters are intentional so it can be overridden in places like AbstractArrowEntity
setYaw ( yaw ) ;
setPitch ( pitch ) ;
setHeadYaw ( headYaw ) ;
2020-06-16 23:58:06 +00:00
setOnGround ( isOnGround ) ;
2019-10-16 02:47:28 +00:00
2020-02-15 23:39:34 +00:00
MoveEntityAbsolutePacket moveEntityPacket = new MoveEntityAbsolutePacket ( ) ;
moveEntityPacket . setRuntimeEntityId ( geyserId ) ;
moveEntityPacket . setPosition ( position ) ;
moveEntityPacket . setRotation ( getBedrockRotation ( ) ) ;
moveEntityPacket . setOnGround ( isOnGround ) ;
2020-04-29 16:06:25 +00:00
moveEntityPacket . setTeleported ( teleported ) ;
2020-02-15 23:39:34 +00:00
2020-05-05 15:51:43 +00:00
session . sendUpstreamPacket ( moveEntityPacket ) ;
2019-08-03 03:38:09 +00:00
}
2020-06-16 23:58:06 +00:00
/ * *
2021-11-13 04:01:45 +00:00
* Teleports an entity to a new location . Used in JavaTeleportEntityTranslator .
2020-06-16 23:58:06 +00:00
* @param position The new position of the entity .
* @param yaw The new yaw of the entity .
* @param pitch The new pitch of the entity .
* @param isOnGround Whether the entity is currently on the ground .
* /
2021-11-18 03:02:38 +00:00
public void teleport ( Vector3f position , float yaw , float pitch , boolean isOnGround ) {
moveAbsolute ( position , yaw , pitch , isOnGround , false ) ;
2020-06-16 23:58:06 +00:00
}
/ * *
2021-11-13 04:01:45 +00:00
* Updates an entity ' s head position . Used in JavaRotateHeadTranslator .
2020-06-16 23:58:06 +00:00
* @param headYaw The new head rotation of the entity .
* /
2021-11-18 03:02:38 +00:00
public void updateHeadLookRotation ( float headYaw ) {
moveRelative ( 0 , 0 , 0 , headYaw , pitch , this . headYaw , onGround ) ;
2020-06-16 23:58:06 +00:00
}
/ * *
2021-11-13 04:01:45 +00:00
* Updates an entity ' s position and rotation . Used in JavaMoveEntityPosRotTranslator .
2020-06-16 23:58:06 +00:00
* @param moveX The new X offset of the current position .
* @param moveY The new Y offset of the current position .
* @param moveZ The new Z offset of the current position .
* @param yaw The new yaw of the entity .
* @param pitch The new pitch of the entity .
* @param isOnGround Whether the entity is currently on the ground .
* /
2021-11-18 03:02:38 +00:00
public void updatePositionAndRotation ( double moveX , double moveY , double moveZ , float yaw , float pitch , boolean isOnGround ) {
moveRelative ( moveX , moveY , moveZ , this . yaw , pitch , yaw , isOnGround ) ;
2020-06-16 23:58:06 +00:00
}
/ * *
2021-11-13 04:01:45 +00:00
* Updates an entity ' s rotation . Used in JavaMoveEntityRotTranslator .
2020-06-16 23:58:06 +00:00
* @param yaw The new yaw of the entity .
* @param pitch The new pitch of the entity .
* @param isOnGround Whether the entity is currently on the ground .
* /
2021-11-18 03:02:38 +00:00
public void updateRotation ( float yaw , float pitch , boolean isOnGround ) {
updatePositionAndRotation ( 0 , 0 , 0 , yaw , pitch , isOnGround ) ;
}
public final boolean getFlag ( EntityFlag flag ) {
return flags . getFlag ( flag ) ;
2020-06-16 23:58:06 +00:00
}
2020-07-30 20:15:07 +00:00
/ * *
2021-11-18 03:02:38 +00:00
* Updates a flag value and determines if the flags would need synced with the Bedrock client .
2020-07-30 20:15:07 +00:00
* /
2021-11-18 03:02:38 +00:00
public final void setFlag ( EntityFlag flag , boolean value ) {
flagsDirty | = flags . setFlag ( flag , value ) ;
2020-02-14 02:04:22 +00:00
}
2020-07-30 20:15:07 +00:00
/ * *
* Sends the Bedrock metadata to the client
* /
2021-11-18 03:02:38 +00:00
public void updateBedrockMetadata ( ) {
if ( ! valid ) {
return ;
}
2021-11-19 01:44:03 +00:00
if ( dirtyMetadata . hasEntries ( ) | | flagsDirty ) {
2021-11-18 03:02:38 +00:00
SetEntityDataPacket entityDataPacket = new SetEntityDataPacket ( ) ;
entityDataPacket . setRuntimeEntityId ( geyserId ) ;
2021-11-19 01:44:03 +00:00
if ( flagsDirty ) {
entityDataPacket . getMetadata ( ) . putFlags ( flags ) ;
flagsDirty = false ;
}
dirtyMetadata . apply ( entityDataPacket . getMetadata ( ) ) ;
2021-11-18 03:02:38 +00:00
session . sendUpstreamPacket ( entityDataPacket ) ;
}
}
public void setFlags ( EntityMetadata < Byte > entityMetadata ) {
byte xd = ( ( ByteEntityMetadata ) entityMetadata ) . getPrimitiveValue ( ) ;
setFlag ( EntityFlag . ON_FIRE , ( ( xd & 0x01 ) = = 0x01 ) & & ! getFlag ( EntityFlag . FIRE_IMMUNE ) ) ; // Otherwise immune entities sometimes flicker onfire
setFlag ( EntityFlag . SNEAKING , ( xd & 0x02 ) = = 0x02 ) ;
setFlag ( EntityFlag . SPRINTING , ( xd & 0x08 ) = = 0x08 ) ;
// Swimming is ignored here and instead we rely on the pose
setFlag ( EntityFlag . GLIDING , ( xd & 0x80 ) = = 0x80 ) ;
2020-02-14 02:04:22 +00:00
2021-11-18 03:02:38 +00:00
setInvisible ( ( xd & 0x20 ) = = 0x20 ) ;
2019-08-06 06:38:03 +00:00
}
2021-06-18 23:09:18 +00:00
/ * *
2021-11-18 03:02:38 +00:00
* Set a boolean - whether the entity is invisible or visible
2021-06-18 23:09:18 +00:00
*
2021-11-18 03:02:38 +00:00
* @param value true if the entity is invisible
2021-06-18 23:09:18 +00:00
* /
2021-11-18 03:02:38 +00:00
protected void setInvisible ( boolean value ) {
setFlag ( EntityFlag . INVISIBLE , value ) ;
2021-06-18 23:09:18 +00:00
}
2021-11-18 03:02:38 +00:00
/ * *
* Set an int from 0 - this entity ' s maximum air - ( air / maxAir ) represents the percentage of bubbles left
* /
public final void setAir ( EntityMetadata < ? > entityMetadata ) {
setAir ( ( ( IntEntityMetadata ) entityMetadata ) . getPrimitiveValue ( ) ) ;
}
protected void setAir ( int amount ) {
dirtyMetadata . put ( EntityData . AIR_SUPPLY , ( short ) MathUtils . constrain ( amount , 0 , getMaxAir ( ) ) ) ;
}
protected int getMaxAir ( ) {
return 300 ;
}
public void setDisplayName ( EntityMetadata < Component > entityMetadata ) {
Component name = entityMetadata . getValue ( ) ;
2021-10-05 21:06:15 +00:00
if ( name ! = null ) {
2021-11-19 01:44:03 +00:00
nametag = MessageTranslator . convertMessage ( name , session . getLocale ( ) ) ;
dirtyMetadata . put ( EntityData . NAMETAG , nametag ) ;
} else if ( ! nametag . isEmpty ( ) ) {
2021-10-05 21:06:15 +00:00
// Clear nametag
2021-11-18 03:02:38 +00:00
dirtyMetadata . put ( EntityData . NAMETAG , " " ) ;
2021-10-05 21:06:15 +00:00
}
2021-10-10 18:54:06 +00:00
}
2021-11-18 03:02:38 +00:00
public void setDisplayNameVisible ( EntityMetadata < Boolean > entityMetadata ) {
dirtyMetadata . put ( EntityData . NAMETAG_ALWAYS_SHOW , ( byte ) ( ( ( BooleanEntityMetadata ) entityMetadata ) . getPrimitiveValue ( ) ? 1 : 0 ) ) ;
2021-10-05 21:06:15 +00:00
}
2021-11-18 03:02:38 +00:00
public void setGravity ( EntityMetadata < Boolean > entityMetadata ) {
setFlag ( EntityFlag . HAS_GRAVITY , ! ( ( BooleanEntityMetadata ) entityMetadata ) . getPrimitiveValue ( ) ) ;
2021-06-05 02:26:29 +00:00
}
2021-06-18 23:09:18 +00:00
/ * *
2021-11-18 03:02:38 +00:00
* Usually used for bounding box and not animation .
2021-06-18 23:09:18 +00:00
* /
2021-11-18 03:02:38 +00:00
public void setPose ( EntityMetadata < Pose > entityMetadata ) {
Pose pose = entityMetadata . getValue ( ) ;
setFlag ( EntityFlag . SLEEPING , pose . equals ( Pose . SLEEPING ) ) ;
// Triggered when crawling
setFlag ( EntityFlag . SWIMMING , pose . equals ( Pose . SWIMMING ) ) ;
setDimensions ( pose ) ;
2021-06-18 23:09:18 +00:00
}
2021-07-20 16:08:48 +00:00
/ * *
2021-11-18 03:02:38 +00:00
* Set the height and width of the entity ' s bounding box
2021-07-20 16:08:48 +00:00
* /
2021-11-18 03:02:38 +00:00
protected void setDimensions ( Pose pose ) {
// No flexibility options for basic entities
2021-11-19 01:44:03 +00:00
setBoundingBoxHeight ( definition . height ( ) ) ;
setBoundingBoxWidth ( definition . width ( ) ) ;
}
public void setBoundingBoxHeight ( float height ) {
if ( height ! = boundingBoxHeight ) {
boundingBoxHeight = height ;
2021-11-18 03:02:38 +00:00
dirtyMetadata . put ( EntityData . BOUNDING_BOX_HEIGHT , boundingBoxHeight ) ;
}
2021-07-20 16:08:48 +00:00
}
2021-11-19 01:44:03 +00:00
public void setBoundingBoxWidth ( float width ) {
if ( width ! = boundingBoxWidth ) {
boundingBoxWidth = width ;
dirtyMetadata . put ( EntityData . BOUNDING_BOX_WIDTH , boundingBoxWidth ) ;
}
}
2021-11-18 03:02:38 +00:00
/ * *
* Set a float from 0 - 1 - how strong the " frozen " overlay should be on screen .
* /
public float setFreezing ( EntityMetadata < Integer > entityMetadata ) {
// The value that Java edition gives us is in ticks, but Bedrock uses a float percentage of the strength 0.0 -> 1.0
// The Java client caps its freezing tick percentage at 140
int freezingTicks = Math . min ( ( ( IntEntityMetadata ) entityMetadata ) . getPrimitiveValue ( ) , 140 ) ;
float freezingPercentage = freezingTicks / 140f ;
dirtyMetadata . put ( EntityData . FREEZING_EFFECT_STRENGTH , freezingPercentage ) ;
return freezingPercentage ;
2021-07-20 16:08:48 +00:00
}
2021-11-19 01:44:03 +00:00
public void setRiderSeatPosition ( Vector3f position ) {
dirtyMetadata . put ( EntityData . RIDER_SEAT_POSITION , position ) ;
}
2021-08-18 02:44:33 +00:00
/ * *
2021-11-18 03:02:38 +00:00
* If true , the entity should be shaking on the client ' s end .
2021-08-18 02:44:33 +00:00
*
2021-11-18 03:02:38 +00:00
* @return whether { @link EntityFlag # SHAKING } should be set to true .
2021-08-18 02:44:33 +00:00
* /
2021-11-18 03:02:38 +00:00
protected boolean isShaking ( ) {
return false ;
2021-08-18 02:44:33 +00:00
}
2019-10-02 20:45:29 +00:00
/ * *
* x = Pitch , y = HeadYaw , z = Yaw
2020-05-11 05:09:16 +00:00
*
2020-04-22 06:03:46 +00:00
* @return the bedrock rotation
2019-10-02 20:45:29 +00:00
* /
public Vector3f getBedrockRotation ( ) {
2021-11-18 03:02:38 +00:00
return Vector3f . from ( pitch , headYaw , yaw ) ;
2019-10-02 20:45:29 +00:00
}
2019-09-25 21:52:28 +00:00
@SuppressWarnings ( " unchecked " )
public < I extends Entity > I as ( Class < I > entityClass ) {
return entityClass . isInstance ( this ) ? ( I ) this : null ;
}
public < I extends Entity > boolean is ( Class < I > entityClass ) {
return entityClass . isInstance ( this ) ;
}
2019-08-03 03:38:09 +00:00
}