2019-08-03 03:38:09 +00:00
/ *
2020-01-09 03:05:42 +00:00
* Copyright ( c ) 2019 - 2020 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 ;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.MetadataType ;
2020-05-23 21:09:11 +00:00
import com.github.steveice10.mc.protocol.data.game.entity.metadata.Pose ;
2020-04-25 03:11:28 +00:00
import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position ;
import com.github.steveice10.mc.protocol.data.game.entity.player.Hand ;
import com.github.steveice10.mc.protocol.data.game.entity.player.PlayerAction ;
import com.github.steveice10.mc.protocol.data.game.world.block.BlockFace ;
2019-11-28 01:30:30 +00:00
import com.github.steveice10.mc.protocol.data.message.TextMessage ;
2020-06-02 14:45:33 +00:00
import com.github.steveice10.mc.protocol.data.message.TranslationMessage ;
2020-04-25 03:11:28 +00:00
import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerActionPacket ;
import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerUseItemPacket ;
2019-10-09 18:39:38 +00:00
import com.nukkitx.math.vector.Vector3f ;
2020-05-23 21:09:11 +00:00
import com.nukkitx.math.vector.Vector3i ;
2020-06-23 00:11:09 +00:00
import com.nukkitx.protocol.bedrock.data.AttributeData ;
import com.nukkitx.protocol.bedrock.data.entity.EntityData ;
import com.nukkitx.protocol.bedrock.data.entity.EntityDataMap ;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag ;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlags ;
2019-11-28 01:30:30 +00:00
import com.nukkitx.protocol.bedrock.packet.* ;
2019-11-30 19:26:51 +00:00
import it.unimi.dsi.fastutil.longs.LongOpenHashSet ;
2019-08-03 03:38:09 +00:00
import lombok.Getter ;
import lombok.Setter ;
2019-08-06 06:38:03 +00:00
import org.geysermc.connector.entity.attribute.Attribute ;
import org.geysermc.connector.entity.attribute.AttributeType ;
2020-05-11 05:09:16 +00:00
import org.geysermc.connector.entity.living.ArmorStandEntity ;
2019-08-03 03:38:09 +00:00
import org.geysermc.connector.entity.type.EntityType ;
import org.geysermc.connector.network.session.GeyserSession ;
2020-05-25 01:07:05 +00:00
import org.geysermc.connector.network.translators.item.ItemRegistry ;
2019-08-06 06:38:03 +00:00
import org.geysermc.connector.utils.AttributeUtils ;
2020-05-23 21:09:11 +00:00
import org.geysermc.connector.utils.ChunkUtils ;
2019-11-28 01:30:30 +00:00
import org.geysermc.connector.utils.MessageUtils ;
2019-08-03 03:38:09 +00:00
2020-05-11 05:09:16 +00:00
import java.util.ArrayList ;
import java.util.HashMap ;
import java.util.List ;
import java.util.Map ;
2019-08-03 03:38:09 +00:00
@Getter
@Setter
public class Entity {
protected long entityId ;
protected long geyserId ;
2020-06-21 02:24:45 +00:00
protected String dimension ;
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
* /
2019-08-03 03:38:09 +00:00
protected Vector3f rotation ;
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 ;
2019-12-01 00:19:03 +00:00
protected float scale = 1 ;
2019-08-03 03:38:09 +00:00
protected EntityType entityType ;
protected boolean valid ;
2020-05-23 21:39:17 +00:00
protected LongOpenHashSet passengers = new LongOpenHashSet ( ) ;
2019-09-21 07:42:44 +00:00
protected Map < AttributeType , Attribute > attributes = new HashMap < > ( ) ;
2020-02-06 00:55:34 +00:00
protected EntityDataMap metadata = new EntityDataMap ( ) ;
2019-08-03 03:38:09 +00:00
public Entity ( long entityId , long geyserId , EntityType entityType , Vector3f position , Vector3f motion , Vector3f rotation ) {
this . entityId = entityId ;
this . geyserId = geyserId ;
this . entityType = entityType ;
this . motion = motion ;
this . rotation = rotation ;
this . valid = false ;
2020-06-21 02:24:45 +00:00
this . dimension = " minecraft:overworld " ;
2019-10-18 07:54:20 +00:00
2020-02-15 23:39:34 +00:00
setPosition ( position ) ;
2019-10-18 07:54:20 +00:00
metadata . put ( EntityData . SCALE , 1f ) ;
2020-05-05 03:01:34 +00:00
metadata . put ( EntityData . COLOR , 0 ) ;
2020-06-23 00:11:09 +00:00
metadata . put ( EntityData . MAX_AIR_SUPPLY , ( short ) 300 ) ;
metadata . put ( EntityData . AIR_SUPPLY , ( short ) 0 ) ;
metadata . put ( EntityData . LEASH_HOLDER_EID , - 1L ) ;
2019-10-18 07:54:20 +00:00
metadata . put ( EntityData . BOUNDING_BOX_HEIGHT , entityType . getHeight ( ) ) ;
metadata . put ( EntityData . BOUNDING_BOX_WIDTH , entityType . getWidth ( ) ) ;
EntityFlags flags = new EntityFlags ( ) ;
flags . setFlag ( EntityFlag . HAS_GRAVITY , true ) ;
flags . setFlag ( EntityFlag . HAS_COLLISION , true ) ;
flags . setFlag ( EntityFlag . CAN_SHOW_NAME , true ) ;
flags . setFlag ( EntityFlag . CAN_CLIMB , true ) ;
metadata . putFlags ( flags ) ;
2019-08-03 03:38:09 +00:00
}
public void spawnEntity ( GeyserSession session ) {
AddEntityPacket addEntityPacket = new AddEntityPacket ( ) ;
2020-05-05 05:09:36 +00:00
addEntityPacket . setIdentifier ( entityType . getIdentifier ( ) ) ;
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 ( ) ) ;
2019-08-03 03:38:09 +00:00
addEntityPacket . setEntityType ( entityType . getType ( ) ) ;
2019-10-18 07:54:20 +00:00
addEntityPacket . getMetadata ( ) . putAll ( metadata ) ;
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
2019-12-21 17:35:48 +00:00
session . getConnector ( ) . getLogger ( ) . debug ( " Spawned entity " + entityType + " at location " + position + " with id " + geyserId + " (java id " + entityId + " ) " ) ;
2019-08-03 03:38:09 +00:00
}
2019-10-02 20:45:29 +00:00
/ * *
2020-04-22 06:03:46 +00:00
* Despawns the entity
*
* @param session The GeyserSession
2019-10-02 20:45:29 +00:00
* @return can be deleted
* /
public boolean despawnEntity ( GeyserSession session ) {
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 ;
entity . getMetadata ( ) . getOrCreateFlags ( ) . setFlag ( EntityFlag . RIDING , false ) ;
2020-07-03 21:55:54 +00:00
entity . updateBedrockMetadata ( session ) ;
}
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
}
2020-02-15 23:39:34 +00:00
public void moveRelative ( GeyserSession session , double relX , double relY , double relZ , float yaw , float pitch , boolean isOnGround ) {
2020-06-16 23:58:06 +00:00
moveRelative ( session , relX , relY , relZ , Vector3f . from ( yaw , pitch , this . rotation . getZ ( ) ) , isOnGround ) ;
2019-08-03 06:51:05 +00:00
}
2019-08-03 03:38:09 +00:00
2020-02-15 23:39:34 +00:00
public void moveRelative ( GeyserSession session , double relX , double relY , double relZ , Vector3f rotation , boolean isOnGround ) {
2019-10-02 20:45:29 +00:00
setRotation ( rotation ) ;
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
}
2020-04-29 16:06:25 +00:00
public void moveAbsolute ( GeyserSession session , Vector3f position , float yaw , float pitch , boolean isOnGround , boolean teleported ) {
2020-06-16 23:58:06 +00:00
moveAbsolute ( session , position , Vector3f . from ( yaw , pitch , this . rotation . getZ ( ) ) , isOnGround , teleported ) ;
2019-08-03 06:51:05 +00:00
}
2020-04-29 16:06:25 +00:00
public void moveAbsolute ( GeyserSession session , Vector3f position , Vector3f rotation , boolean isOnGround , boolean teleported ) {
2019-09-25 21:52:28 +00:00
setPosition ( position ) ;
2019-10-02 20:45:29 +00:00
setRotation ( rotation ) ;
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
/ * *
* Teleports an entity to a new location . Used in JavaEntityTeleportTranslator .
* @param session GeyserSession .
* @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 .
* /
public void teleport ( GeyserSession session , Vector3f position , float yaw , float pitch , boolean isOnGround ) {
moveAbsolute ( session , position , yaw , pitch , isOnGround , false ) ;
}
/ * *
* Updates an entity ' s head position . Used in JavaEntityHeadLookTranslator .
* @param session GeyserSession .
* @param headYaw The new head rotation of the entity .
* /
public void updateHeadLookRotation ( GeyserSession session , float headYaw ) {
moveRelative ( session , 0 , 0 , 0 , Vector3f . from ( headYaw , rotation . getY ( ) , rotation . getZ ( ) ) , onGround ) ;
}
/ * *
* Updates an entity ' s position and rotation . Used in JavaEntityPositionRotationTranslator .
* @param session GeyserSession
* @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 .
* /
public void updatePositionAndRotation ( GeyserSession session , double moveX , double moveY , double moveZ , float yaw , float pitch , boolean isOnGround ) {
moveRelative ( session , moveX , moveY , moveZ , Vector3f . from ( rotation . getX ( ) , pitch , yaw ) , isOnGround ) ;
}
/ * *
* Updates an entity ' s rotation . Used in JavaEntityRotationTranslator .
* @param session GeyserSession .
* @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 .
* /
public void updateRotation ( GeyserSession session , float yaw , float pitch , boolean isOnGround ) {
updatePositionAndRotation ( session , 0 , 0 , 0 , yaw , pitch , isOnGround ) ;
}
2019-08-06 06:38:03 +00:00
public void updateBedrockAttributes ( GeyserSession session ) {
2020-02-14 02:04:22 +00:00
if ( ! valid ) return ;
2020-06-23 00:11:09 +00:00
List < AttributeData > attributes = new ArrayList < > ( ) ;
2019-08-06 06:38:03 +00:00
for ( Map . Entry < AttributeType , Attribute > entry : this . attributes . entrySet ( ) ) {
if ( ! entry . getValue ( ) . getType ( ) . isBedrockAttribute ( ) )
continue ;
attributes . add ( AttributeUtils . getBedrockAttribute ( entry . getValue ( ) ) ) ;
}
UpdateAttributesPacket updateAttributesPacket = new UpdateAttributesPacket ( ) ;
updateAttributesPacket . setRuntimeEntityId ( geyserId ) ;
updateAttributesPacket . setAttributes ( attributes ) ;
2020-05-05 15:51:43 +00:00
session . sendUpstreamPacket ( updateAttributesPacket ) ;
2019-11-28 01:30:30 +00:00
}
2020-07-30 20:15:07 +00:00
/ * *
* Applies the Java metadata to the local Bedrock metadata copy
* @param entityMetadata the Java entity metadata
* @param session GeyserSession
* /
2019-11-28 01:30:30 +00:00
public void updateBedrockMetadata ( EntityMetadata entityMetadata , GeyserSession session ) {
switch ( entityMetadata . getId ( ) ) {
case 0 :
if ( entityMetadata . getType ( ) = = MetadataType . BYTE ) {
byte xd = ( byte ) entityMetadata . getValue ( ) ;
2020-06-30 12:20:03 +00:00
metadata . getFlags ( ) . setFlag ( EntityFlag . ON_FIRE , ( ( xd & 0x01 ) = = 0x01 ) & & ! metadata . getFlags ( ) . getFlag ( EntityFlag . FIRE_IMMUNE ) ) ; // Otherwise immune entities sometimes flicker onfire
2019-11-28 01:30:30 +00:00
metadata . getFlags ( ) . setFlag ( EntityFlag . SNEAKING , ( xd & 0x02 ) = = 0x02 ) ;
metadata . getFlags ( ) . setFlag ( EntityFlag . SPRINTING , ( xd & 0x08 ) = = 0x08 ) ;
2020-06-10 22:52:36 +00:00
metadata . getFlags ( ) . setFlag ( EntityFlag . SWIMMING , ( ( xd & 0x10 ) = = 0x10 ) & & metadata . getFlags ( ) . getFlag ( EntityFlag . SPRINTING ) ) ; // Otherwise swimming is enabled on older servers
2019-11-28 01:30:30 +00:00
metadata . getFlags ( ) . setFlag ( EntityFlag . GLIDING , ( xd & 0x80 ) = = 0x80 ) ;
2020-04-25 03:11:28 +00:00
2020-05-11 05:09:16 +00:00
if ( ( xd & 0x20 ) = = 0x20 ) {
2020-06-03 20:12:16 +00:00
// Armour stands are handled in their own class
if ( ! this . is ( ArmorStandEntity . class ) ) {
2020-05-11 05:09:16 +00:00
metadata . getFlags ( ) . setFlag ( EntityFlag . INVISIBLE , true ) ;
}
2020-05-12 04:44:30 +00:00
} else {
metadata . getFlags ( ) . setFlag ( EntityFlag . INVISIBLE , false ) ;
2020-05-11 05:09:16 +00:00
}
2020-04-25 03:11:28 +00:00
// Shield code
if ( session . getPlayerEntity ( ) . getEntityId ( ) = = entityId & & metadata . getFlags ( ) . getFlag ( EntityFlag . SNEAKING ) ) {
2020-07-07 20:40:19 +00:00
if ( ( session . getInventory ( ) . getItemInHand ( ) ! = null & & session . getInventory ( ) . getItemInHand ( ) . getId ( ) = = ItemRegistry . SHIELD . getJavaId ( ) ) | |
( session . getInventoryCache ( ) . getPlayerInventory ( ) . getItem ( 45 ) ! = null & & session . getInventoryCache ( ) . getPlayerInventory ( ) . getItem ( 45 ) . getId ( ) = = ItemRegistry . SHIELD . getJavaId ( ) ) ) {
2020-04-25 03:11:28 +00:00
ClientPlayerUseItemPacket useItemPacket ;
metadata . getFlags ( ) . setFlag ( EntityFlag . BLOCKING , true ) ;
2020-07-07 20:40:19 +00:00
if ( session . getInventory ( ) . getItemInHand ( ) ! = null & & session . getInventory ( ) . getItemInHand ( ) . getId ( ) = = ItemRegistry . SHIELD . getJavaId ( ) ) {
2020-04-25 03:11:28 +00:00
useItemPacket = new ClientPlayerUseItemPacket ( Hand . MAIN_HAND ) ;
}
// Else we just assume it's the offhand, to simplify logic and to assure the packet gets sent
else {
useItemPacket = new ClientPlayerUseItemPacket ( Hand . OFF_HAND ) ;
}
2020-05-05 15:51:43 +00:00
session . sendDownstreamPacket ( useItemPacket ) ;
2020-04-25 03:11:28 +00:00
}
} else if ( session . getPlayerEntity ( ) . getEntityId ( ) = = entityId & & ! metadata . getFlags ( ) . getFlag ( EntityFlag . SNEAKING ) & & metadata . getFlags ( ) . getFlag ( EntityFlag . BLOCKING ) ) {
2020-05-11 05:09:16 +00:00
metadata . getFlags ( ) . setFlag ( EntityFlag . BLOCKING , false ) ;
2020-07-08 16:36:26 +00:00
metadata . getFlags ( ) . setFlag ( EntityFlag . IS_AVOIDING_BLOCK , true ) ;
2020-05-11 05:09:16 +00:00
ClientPlayerActionPacket releaseItemPacket = new ClientPlayerActionPacket ( PlayerAction . RELEASE_USE_ITEM , new Position ( 0 , 0 , 0 ) , BlockFace . DOWN ) ;
session . sendDownstreamPacket ( releaseItemPacket ) ;
}
2019-11-28 01:30:30 +00:00
}
2020-05-15 20:29:54 +00:00
break ;
case 1 : // Air/bubbles
if ( ( int ) entityMetadata . getValue ( ) = = 300 ) {
2020-06-23 00:11:09 +00:00
metadata . put ( EntityData . AIR_SUPPLY , ( short ) 0 ) ; // Otherwise the bubble counter remains in the UI
2020-05-15 20:29:54 +00:00
} else {
2020-06-23 00:11:09 +00:00
metadata . put ( EntityData . AIR_SUPPLY , ( short ) ( int ) entityMetadata . getValue ( ) ) ;
2020-05-15 20:29:54 +00:00
}
2019-11-28 01:30:30 +00:00
break ;
case 2 : // custom name
2020-06-02 14:45:33 +00:00
if ( entityMetadata . getValue ( ) instanceof TextMessage ) {
TextMessage name = ( TextMessage ) entityMetadata . getValue ( ) ;
if ( name ! = null )
metadata . put ( EntityData . NAMETAG , MessageUtils . getBedrockMessage ( name ) ) ;
} else if ( entityMetadata . getValue ( ) instanceof TranslationMessage ) {
TranslationMessage message = ( TranslationMessage ) entityMetadata . getValue ( ) ;
if ( message ! = null )
metadata . put ( EntityData . NAMETAG , MessageUtils . getTranslatedBedrockMessage ( message , session . getClientData ( ) . getLanguageCode ( ) , true ) ) ;
}
2019-11-28 01:30:30 +00:00
break ;
case 3 : // is custom name visible
2020-02-14 02:04:22 +00:00
if ( ! this . is ( PlayerEntity . class ) )
2020-06-23 00:11:09 +00:00
metadata . put ( EntityData . NAMETAG_ALWAYS_SHOW , ( byte ) ( ( boolean ) entityMetadata . getValue ( ) ? 1 : 0 ) ) ;
2019-11-28 01:30:30 +00:00
break ;
case 4 : // silent
metadata . getFlags ( ) . setFlag ( EntityFlag . SILENT , ( boolean ) entityMetadata . getValue ( ) ) ;
break ;
case 5 : // no gravity
metadata . getFlags ( ) . setFlag ( EntityFlag . HAS_GRAVITY , ! ( boolean ) entityMetadata . getValue ( ) ) ;
break ;
2020-05-23 21:09:11 +00:00
case 6 : // Pose change
if ( entityMetadata . getValue ( ) . equals ( Pose . SLEEPING ) ) {
metadata . getFlags ( ) . setFlag ( EntityFlag . SLEEPING , true ) ;
// Has to be a byte or it does not work
2020-07-08 16:36:26 +00:00
metadata . put ( EntityData . PLAYER_FLAGS , ( byte ) 2 ) ;
2020-05-23 21:09:11 +00:00
if ( entityId = = session . getPlayerEntity ( ) . getEntityId ( ) ) {
Vector3i lastInteractionPos = session . getLastInteractionPosition ( ) ;
2020-06-23 00:11:09 +00:00
metadata . put ( EntityData . BED_POSITION , lastInteractionPos ) ;
2020-05-23 21:09:11 +00:00
if ( session . getConnector ( ) . getConfig ( ) . isCacheChunks ( ) ) {
2020-06-19 01:44:50 +00:00
int bed = session . getConnector ( ) . getWorldManager ( ) . getBlockAt ( session , lastInteractionPos . getX ( ) ,
2020-05-23 21:09:11 +00:00
lastInteractionPos . getY ( ) , lastInteractionPos . getZ ( ) ) ;
// Bed has to be updated, or else player is floating in the air
ChunkUtils . updateBlock ( session , bed , lastInteractionPos ) ;
}
} else {
2020-06-23 00:11:09 +00:00
metadata . put ( EntityData . BED_POSITION , Vector3i . from ( position . getFloorX ( ) , position . getFloorY ( ) - 2 , position . getFloorZ ( ) ) ) ;
2020-05-23 21:09:11 +00:00
}
metadata . put ( EntityData . BOUNDING_BOX_WIDTH , 0 . 2f ) ;
metadata . put ( EntityData . BOUNDING_BOX_HEIGHT , 0 . 2f ) ;
} else if ( metadata . getFlags ( ) . getFlag ( EntityFlag . SLEEPING ) ) {
metadata . getFlags ( ) . setFlag ( EntityFlag . SLEEPING , false ) ;
metadata . put ( EntityData . BOUNDING_BOX_WIDTH , getEntityType ( ) . getWidth ( ) ) ;
metadata . put ( EntityData . BOUNDING_BOX_HEIGHT , getEntityType ( ) . getHeight ( ) ) ;
2020-06-23 00:11:09 +00:00
metadata . put ( EntityData . PLAYER_FLAGS , ( byte ) 0 ) ;
2020-05-23 21:09:11 +00:00
}
break ;
2019-11-28 01:30:30 +00:00
}
2020-02-14 02:04:22 +00:00
}
2020-07-30 20:15:07 +00:00
/ * *
* Sends the Bedrock metadata to the client
* @param session GeyserSession
* /
2020-02-14 02:04:22 +00:00
public void updateBedrockMetadata ( GeyserSession session ) {
if ( ! valid ) return ;
2019-09-16 01:25:16 +00:00
SetEntityDataPacket entityDataPacket = new SetEntityDataPacket ( ) ;
entityDataPacket . setRuntimeEntityId ( geyserId ) ;
2019-10-18 07:54:20 +00:00
entityDataPacket . getMetadata ( ) . putAll ( metadata ) ;
2020-05-05 15:51:43 +00:00
session . sendUpstreamPacket ( entityDataPacket ) ;
2019-08-06 06:38:03 +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 ( ) {
2019-10-09 18:39:38 +00:00
return Vector3f . from ( rotation . getY ( ) , rotation . getZ ( ) , rotation . getX ( ) ) ;
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
}