Mirror von
https://github.com/GeyserMC/Geyser.git
synchronisiert 2024-11-20 06:50:09 +01:00
Entity refactory aaaaaaAAAAAAA
Dieser Commit ist enthalten in:
Ursprung
951b616f98
Commit
11997ed82b
@ -44,6 +44,7 @@ import org.geysermc.connector.bootstrap.GeyserBootstrap;
|
||||
import org.geysermc.connector.command.CommandManager;
|
||||
import org.geysermc.connector.common.AuthType;
|
||||
import org.geysermc.connector.configuration.GeyserConfiguration;
|
||||
import org.geysermc.connector.entity.EntityDefinitions;
|
||||
import org.geysermc.connector.metrics.Metrics;
|
||||
import org.geysermc.connector.network.ConnectorServerEventHandler;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
@ -153,6 +154,7 @@ public class GeyserConnector {
|
||||
BlockRegistries.init();
|
||||
Registries.init();
|
||||
|
||||
EntityDefinitions.init();
|
||||
ItemTranslator.init();
|
||||
MessageTranslator.init();
|
||||
LocaleUtils.init();
|
||||
|
@ -25,8 +25,8 @@
|
||||
|
||||
package org.geysermc.connector.command.defaults;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.object.Direction;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.player.PlayerAction;
|
||||
import com.github.steveice10.mc.protocol.data.game.level.block.BlockFace;
|
||||
import com.github.steveice10.mc.protocol.packet.ingame.serverbound.player.ServerboundPlayerActionPacket;
|
||||
import org.geysermc.connector.GeyserConnector;
|
||||
import org.geysermc.connector.command.CommandSender;
|
||||
@ -47,7 +47,7 @@ public class OffhandCommand extends GeyserCommand {
|
||||
}
|
||||
|
||||
ServerboundPlayerActionPacket releaseItemPacket = new ServerboundPlayerActionPacket(PlayerAction.SWAP_HANDS, BlockUtils.POSITION_ZERO,
|
||||
BlockFace.DOWN);
|
||||
Direction.DOWN);
|
||||
session.sendDownstreamPacket(releaseItemPacket);
|
||||
}
|
||||
|
||||
|
@ -26,37 +26,43 @@
|
||||
package org.geysermc.connector.entity;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.type.EntityType;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
|
||||
import org.geysermc.connector.entity.type.EntityType;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class AbstractArrowEntity extends Entity {
|
||||
|
||||
public AbstractArrowEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
||||
super(entityId, geyserId, entityType, position, motion, rotation);
|
||||
public AbstractArrowEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
|
||||
|
||||
// Set the correct texture if using the resource pack
|
||||
metadata.getFlags().setFlag(EntityFlag.BRIBED, entityType == EntityType.SPECTRAL_ARROW);
|
||||
dirtyMetadata.getFlags().setFlag(EntityFlag.BRIBED, definition.entityType() == EntityType.SPECTRAL_ARROW);
|
||||
|
||||
setMotion(motion);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
|
||||
if (entityMetadata.getId() == 8) {
|
||||
byte data = (byte) entityMetadata.getValue();
|
||||
public void setArrowFlags(EntityMetadata<Byte> entityMetadata) {
|
||||
byte data = ((ByteEntityMetadata) entityMetadata).getPrimitiveValue();
|
||||
|
||||
metadata.getFlags().setFlag(EntityFlag.CRITICAL, (data & 0x01) == 0x01);
|
||||
setFlag(EntityFlag.CRITICAL, (data & 0x01) == 0x01);
|
||||
}
|
||||
|
||||
super.updateBedrockMetadata(entityMetadata, session);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRotation(Vector3f rotation) {
|
||||
// Ignore the rotation sent by the Java server since the
|
||||
// Java client calculates the rotation from the motion
|
||||
@Override
|
||||
public void setYaw(float yaw) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPitch(float pitch) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setHeadYaw(float headYaw) {
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -64,8 +70,8 @@ public class AbstractArrowEntity extends Entity {
|
||||
super.setMotion(motion);
|
||||
|
||||
double horizontalSpeed = Math.sqrt(motion.getX() * motion.getX() + motion.getZ() * motion.getZ());
|
||||
float yaw = (float) Math.toDegrees(Math.atan2(motion.getX(), motion.getZ()));
|
||||
float pitch = (float) Math.toDegrees(Math.atan2(motion.getY(), horizontalSpeed));
|
||||
rotation = Vector3f.from(yaw, pitch, yaw);
|
||||
this.yaw = (float) Math.toDegrees(Math.atan2(motion.getX(), motion.getZ()));
|
||||
this.pitch = (float) Math.toDegrees(Math.atan2(motion.getY(), horizontalSpeed));
|
||||
this.headYaw = yaw;
|
||||
}
|
||||
}
|
||||
|
@ -26,44 +26,47 @@
|
||||
package org.geysermc.connector.entity;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.FloatEntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.level.particle.Particle;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
|
||||
import org.geysermc.connector.entity.type.EntityType;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
import org.geysermc.connector.utils.EffectUtils;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class AreaEffectCloudEntity extends Entity {
|
||||
|
||||
public AreaEffectCloudEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
||||
super(entityId, geyserId, entityType, position, motion, rotation);
|
||||
|
||||
// Without this the cloud doesn't appear,
|
||||
metadata.put(EntityData.AREA_EFFECT_CLOUD_DURATION, 600);
|
||||
|
||||
// This disabled client side shrink of the cloud
|
||||
metadata.put(EntityData.AREA_EFFECT_CLOUD_RADIUS, 0.0f);
|
||||
metadata.put(EntityData.AREA_EFFECT_CLOUD_CHANGE_RATE, -0.005f);
|
||||
metadata.put(EntityData.AREA_EFFECT_CLOUD_CHANGE_ON_PICKUP, -0.5f);
|
||||
|
||||
metadata.getFlags().setFlag(EntityFlag.FIRE_IMMUNE, true);
|
||||
public AreaEffectCloudEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
|
||||
if (entityMetadata.getId() == 8) {
|
||||
metadata.put(EntityData.AREA_EFFECT_CLOUD_RADIUS, entityMetadata.getValue());
|
||||
metadata.put(EntityData.BOUNDING_BOX_WIDTH, 2.0f * (float) entityMetadata.getValue());
|
||||
} else if (entityMetadata.getId() == 9) {
|
||||
metadata.put(EntityData.EFFECT_COLOR, entityMetadata.getValue());
|
||||
} else if (entityMetadata.getId() == 11) {
|
||||
Particle particle = (Particle) entityMetadata.getValue();
|
||||
protected void initializeMetadata() {
|
||||
super.initializeMetadata();
|
||||
// Without this the cloud doesn't appear,
|
||||
dirtyMetadata.put(EntityData.AREA_EFFECT_CLOUD_DURATION, 600);
|
||||
|
||||
// This disabled client side shrink of the cloud
|
||||
dirtyMetadata.put(EntityData.AREA_EFFECT_CLOUD_RADIUS, 0.0f);
|
||||
dirtyMetadata.put(EntityData.AREA_EFFECT_CLOUD_CHANGE_RATE, -0.005f);
|
||||
dirtyMetadata.put(EntityData.AREA_EFFECT_CLOUD_CHANGE_ON_PICKUP, -0.5f);
|
||||
|
||||
setFlag(EntityFlag.FIRE_IMMUNE, true);
|
||||
}
|
||||
|
||||
public void setRadius(EntityMetadata<Float> entityMetadata) {
|
||||
float value = ((FloatEntityMetadata) entityMetadata).getPrimitiveValue();
|
||||
dirtyMetadata.put(EntityData.AREA_EFFECT_CLOUD_RADIUS, value);
|
||||
dirtyMetadata.put(EntityData.BOUNDING_BOX_WIDTH, 2.0f * value);
|
||||
}
|
||||
|
||||
public void setParticle(EntityMetadata<Particle> entityMetadata) {
|
||||
Particle particle = entityMetadata.getValue();
|
||||
int particleId = EffectUtils.getParticleId(session, particle.getType());
|
||||
if (particleId != -1) {
|
||||
metadata.put(EntityData.AREA_EFFECT_CLOUD_PARTICLE_ID, particleId);
|
||||
dirtyMetadata.put(EntityData.AREA_EFFECT_CLOUD_PARTICLE_ID, particleId);
|
||||
}
|
||||
}
|
||||
super.updateBedrockMetadata(entityMetadata, session);
|
||||
}
|
||||
}
|
||||
|
@ -26,13 +26,16 @@
|
||||
package org.geysermc.connector.entity;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanEntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
|
||||
import com.nukkitx.protocol.bedrock.packet.AnimatePacket;
|
||||
import com.nukkitx.protocol.bedrock.packet.MoveEntityAbsolutePacket;
|
||||
import org.geysermc.connector.entity.type.EntityType;
|
||||
import lombok.Getter;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class BoatEntity extends Entity {
|
||||
@ -52,28 +55,36 @@ public class BoatEntity extends Entity {
|
||||
private boolean isPaddlingRight;
|
||||
private float paddleTimeRight;
|
||||
|
||||
/**
|
||||
* Saved for using the "pick" functionality on a boat.
|
||||
*/
|
||||
@Getter
|
||||
private int variant;
|
||||
|
||||
// Looks too fast and too choppy with 0.1f, which is how I believe the Microsoftian client handles it
|
||||
private final float ROWING_SPEED = 0.05f;
|
||||
|
||||
public BoatEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
||||
super(entityId, geyserId, entityType, position.add(0d, entityType.getOffset(), 0d), motion, rotation.add(90, 0, 90));
|
||||
public BoatEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
// Initial rotation is incorrect
|
||||
super(session, entityId, geyserId, uuid, definition, position.add(0d, definition.offset(), 0d), motion, yaw + 90, 0, yaw + 90);
|
||||
|
||||
// Required to be able to move on land 1.16.200+ or apply gravity not in the water 1.16.100+
|
||||
metadata.put(EntityData.IS_BUOYANT, (byte) 1);
|
||||
metadata.put(EntityData.BUOYANCY_DATA, BUOYANCY_DATA);
|
||||
dirtyMetadata.put(EntityData.IS_BUOYANT, (byte) 1);
|
||||
dirtyMetadata.put(EntityData.BUOYANCY_DATA, BUOYANCY_DATA);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void moveAbsolute(GeyserSession session, Vector3f position, Vector3f rotation, boolean isOnGround, boolean teleported) {
|
||||
public void moveAbsolute(Vector3f position, float yaw, float pitch, float headYaw, boolean isOnGround, boolean teleported) {
|
||||
// We don't include the rotation (y) as it causes the boat to appear sideways
|
||||
setPosition(position.add(0d, this.entityType.getOffset(), 0d));
|
||||
setRotation(Vector3f.from(rotation.getX() + 90, 0, rotation.getX() + 90));
|
||||
setPosition(position.add(0d, this.definition.offset(), 0d));
|
||||
this.yaw = yaw + 90;
|
||||
this.headYaw = yaw + 90;
|
||||
setOnGround(isOnGround);
|
||||
|
||||
MoveEntityAbsolutePacket moveEntityPacket = new MoveEntityAbsolutePacket();
|
||||
moveEntityPacket.setRuntimeEntityId(geyserId);
|
||||
// Minimal glitching when ClientboundMoveVehiclePacket is sent
|
||||
moveEntityPacket.setPosition(session.getRidingVehicleEntity() == this ? position.up(EntityType.PLAYER.getOffset() - this.entityType.getOffset()) : this.position);
|
||||
moveEntityPacket.setPosition(session.getRidingVehicleEntity() == this ? position.up(EntityDefinitions.PLAYER.offset() - this.definition.offset()) : this.position);
|
||||
moveEntityPacket.setRotation(getBedrockRotation());
|
||||
moveEntityPacket.setOnGround(isOnGround);
|
||||
moveEntityPacket.setTeleported(teleported);
|
||||
@ -84,47 +95,32 @@ public class BoatEntity extends Entity {
|
||||
/**
|
||||
* Move the boat without making the adjustments needed to translate from Java
|
||||
*/
|
||||
public void moveAbsoluteWithoutAdjustments(GeyserSession session, Vector3f position, Vector3f rotation, boolean isOnGround, boolean teleported) {
|
||||
super.moveAbsolute(session, position, Vector3f.from(rotation.getX(), 0, rotation.getX()), isOnGround, teleported);
|
||||
public void moveAbsoluteWithoutAdjustments(Vector3f position, float yaw, boolean isOnGround, boolean teleported) {
|
||||
super.moveAbsolute(position, yaw, 0, yaw, isOnGround, teleported);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void moveRelative(GeyserSession session, double relX, double relY, double relZ, Vector3f rotation, boolean isOnGround) {
|
||||
super.moveRelative(session, relX, relY, relZ, Vector3f.from(rotation.getX(), 0, rotation.getX()), isOnGround);
|
||||
public void moveRelative(double relX, double relY, double relZ, float yaw, float pitch, float headYaw, boolean isOnGround) {
|
||||
super.moveRelative(relX, relY, relZ, yaw, 0, yaw, isOnGround);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updatePositionAndRotation(GeyserSession session, double moveX, double moveY, double moveZ, float yaw, float pitch, boolean isOnGround) {
|
||||
moveRelative(session, moveX, moveY, moveZ, yaw + 90, pitch, isOnGround);
|
||||
public void updatePositionAndRotation(double moveX, double moveY, double moveZ, float yaw, float pitch, boolean isOnGround) {
|
||||
moveRelative(moveX, moveY, moveZ, yaw + 90, pitch, isOnGround);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateRotation(GeyserSession session, float yaw, float pitch, boolean isOnGround) {
|
||||
moveRelative(session, 0, 0, 0, Vector3f.from(yaw + 90, 0, 0), isOnGround);
|
||||
public void updateRotation(float yaw, float pitch, boolean isOnGround) {
|
||||
moveRelative(0, 0, 0, yaw + 90, 0, 0, isOnGround);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
|
||||
// Time since last hit
|
||||
if (entityMetadata.getId() == 8) {
|
||||
metadata.put(EntityData.HURT_TIME, entityMetadata.getValue());
|
||||
public void setVariant(EntityMetadata<Integer> entityMetadata) {
|
||||
variant = ((IntEntityMetadata) entityMetadata).getPrimitiveValue();
|
||||
dirtyMetadata.put(EntityData.VARIANT, variant);
|
||||
}
|
||||
|
||||
// Rocking direction
|
||||
if (entityMetadata.getId() == 9) {
|
||||
metadata.put(EntityData.HURT_DIRECTION, entityMetadata.getValue());
|
||||
}
|
||||
|
||||
// 'Health' in Bedrock, damage taken in Java
|
||||
if (entityMetadata.getId() == 10) {
|
||||
// Not exactly health but it makes motion in Bedrock
|
||||
metadata.put(EntityData.HEALTH, 40 - ((int) (float) entityMetadata.getValue()));
|
||||
}
|
||||
|
||||
if (entityMetadata.getId() == 11) {
|
||||
metadata.put(EntityData.VARIANT, entityMetadata.getValue());
|
||||
} else if (entityMetadata.getId() == 12) {
|
||||
isPaddlingLeft = (boolean) entityMetadata.getValue();
|
||||
public void setPaddlingLeft(EntityMetadata<Boolean> entityMetadata) {
|
||||
isPaddlingLeft = ((BooleanEntityMetadata) entityMetadata).getPrimitiveValue();
|
||||
if (isPaddlingLeft) {
|
||||
// Java sends simply "true" and "false" (is_paddling_left), Bedrock keeps sending packets as you're rowing
|
||||
// This is an asynchronous method that emulates Bedrock rowing until "false" is sent.
|
||||
@ -138,11 +134,12 @@ public class BoatEntity extends Entity {
|
||||
}
|
||||
} else {
|
||||
// Indicate that the row position should be reset
|
||||
metadata.put(EntityData.ROW_TIME_LEFT, 0.0f);
|
||||
dirtyMetadata.put(EntityData.ROW_TIME_LEFT, 0.0f);
|
||||
}
|
||||
}
|
||||
else if (entityMetadata.getId() == 13) {
|
||||
isPaddlingRight = (boolean) entityMetadata.getValue();
|
||||
|
||||
public void setPaddlingRight(EntityMetadata<Boolean> entityMetadata) {
|
||||
isPaddlingRight = ((BooleanEntityMetadata) entityMetadata).getPrimitiveValue();
|
||||
if (isPaddlingRight) {
|
||||
paddleTimeRight = 0f;
|
||||
if (!this.passengers.isEmpty()) {
|
||||
@ -152,23 +149,8 @@ public class BoatEntity extends Entity {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
metadata.put(EntityData.ROW_TIME_RIGHT, 0.0f);
|
||||
dirtyMetadata.put(EntityData.ROW_TIME_RIGHT, 0.0f);
|
||||
}
|
||||
} else if (entityMetadata.getId() == 14) {
|
||||
// Possibly - I don't think this does anything?
|
||||
metadata.put(EntityData.BOAT_BUBBLE_TIME, entityMetadata.getValue());
|
||||
}
|
||||
|
||||
super.updateBedrockMetadata(entityMetadata, session);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateBedrockMetadata(GeyserSession session) {
|
||||
super.updateBedrockMetadata(session);
|
||||
|
||||
// As these indicate to reset rowing, remove them until it is time to send them out again.
|
||||
metadata.remove(EntityData.ROW_TIME_LEFT);
|
||||
metadata.remove(EntityData.ROW_TIME_RIGHT);
|
||||
}
|
||||
|
||||
private void updateLeftPaddle(GeyserSession session, Entity rower) {
|
||||
|
@ -25,42 +25,33 @@
|
||||
|
||||
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.protocol.bedrock.data.entity.EntityData;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.geysermc.connector.entity.type.EntityType;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
import org.geysermc.connector.network.translators.chat.MessageTranslator;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class CommandBlockMinecartEntity extends DefaultBlockMinecartEntity {
|
||||
|
||||
public CommandBlockMinecartEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
||||
super(entityId, geyserId, entityType, position, motion, rotation);
|
||||
// Required, or else the GUI will not open
|
||||
metadata.put(EntityData.CONTAINER_TYPE, (byte) 16);
|
||||
metadata.put(EntityData.CONTAINER_BASE_SIZE, 1);
|
||||
// Required, or else the client does not bother to send a packet back with the new information
|
||||
metadata.put(EntityData.COMMAND_BLOCK_ENABLED, (byte) 1);
|
||||
public CommandBlockMinecartEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
|
||||
if (entityMetadata.getId() == 14) {
|
||||
metadata.put(EntityData.COMMAND_BLOCK_COMMAND, entityMetadata.getValue());
|
||||
}
|
||||
if (entityMetadata.getId() == 15) {
|
||||
metadata.put(EntityData.COMMAND_BLOCK_LAST_OUTPUT, MessageTranslator.convertMessage((Component) entityMetadata.getValue()));
|
||||
}
|
||||
super.updateBedrockMetadata(entityMetadata, session);
|
||||
protected void initializeMetadata() {
|
||||
// Required, or else the GUI will not open
|
||||
dirtyMetadata.put(EntityData.CONTAINER_TYPE, (byte) 16);
|
||||
dirtyMetadata.put(EntityData.CONTAINER_BASE_SIZE, 1);
|
||||
// Required, or else the client does not bother to send a packet back with the new information
|
||||
dirtyMetadata.put(EntityData.COMMAND_BLOCK_ENABLED, (byte) 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* By default, the command block shown is purple on Bedrock, which does not match Java Edition's orange.
|
||||
*/
|
||||
@Override
|
||||
public void updateDefaultBlockMetadata(GeyserSession session) {
|
||||
metadata.put(EntityData.DISPLAY_ITEM, session.getBlockMappings().getCommandBlockRuntimeId());
|
||||
metadata.put(EntityData.DISPLAY_OFFSET, 6);
|
||||
public void updateDefaultBlockMetadata() {
|
||||
dirtyMetadata.put(EntityData.DISPLAY_ITEM, session.getBlockMappings().getCommandBlockRuntimeId());
|
||||
dirtyMetadata.put(EntityData.DISPLAY_OFFSET, 6);
|
||||
}
|
||||
}
|
||||
|
@ -26,11 +26,14 @@
|
||||
package org.geysermc.connector.entity;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanEntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata;
|
||||
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.network.session.GeyserSession;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* This class is used as a base for minecarts with a default block to display like furnaces and spawners
|
||||
*/
|
||||
@ -40,53 +43,48 @@ public class DefaultBlockMinecartEntity extends MinecartEntity {
|
||||
public int customBlockOffset = 0;
|
||||
public boolean showCustomBlock = false;
|
||||
|
||||
public DefaultBlockMinecartEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
||||
super(entityId, geyserId, entityType, position, motion, rotation);
|
||||
public DefaultBlockMinecartEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
|
||||
|
||||
metadata.put(EntityData.CUSTOM_DISPLAY, (byte) 1);
|
||||
dirtyMetadata.put(EntityData.CUSTOM_DISPLAY, (byte) 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void spawnEntity(GeyserSession session) {
|
||||
updateDefaultBlockMetadata(session);
|
||||
super.spawnEntity(session);
|
||||
public void spawnEntity() {
|
||||
updateDefaultBlockMetadata();
|
||||
super.spawnEntity();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
|
||||
|
||||
// Custom block
|
||||
if (entityMetadata.getId() == 11) {
|
||||
customBlock = (int) entityMetadata.getValue();
|
||||
public void setCustomBlock(EntityMetadata<Integer> entityMetadata) {
|
||||
customBlock = ((IntEntityMetadata) entityMetadata).getPrimitiveValue();
|
||||
|
||||
if (showCustomBlock) {
|
||||
metadata.put(EntityData.DISPLAY_ITEM, session.getBlockMappings().getBedrockBlockId(customBlock));
|
||||
dirtyMetadata.put(EntityData.DISPLAY_ITEM, session.getBlockMappings().getBedrockBlockId(customBlock));
|
||||
}
|
||||
}
|
||||
|
||||
// Custom block offset
|
||||
if (entityMetadata.getId() == 12) {
|
||||
customBlockOffset = (int) entityMetadata.getValue();
|
||||
@Override
|
||||
public void setCustomBlockOffset(EntityMetadata<Integer> entityMetadata) {
|
||||
customBlockOffset = ((IntEntityMetadata) entityMetadata).getPrimitiveValue();
|
||||
|
||||
if (showCustomBlock) {
|
||||
metadata.put(EntityData.DISPLAY_OFFSET, customBlockOffset);
|
||||
dirtyMetadata.put(EntityData.DISPLAY_OFFSET, customBlockOffset);
|
||||
}
|
||||
}
|
||||
|
||||
// If the custom block should be enabled
|
||||
if (entityMetadata.getId() == 13) {
|
||||
if ((boolean) entityMetadata.getValue()) {
|
||||
@Override
|
||||
public void setShowCustomBlock(EntityMetadata<Boolean> entityMetadata) {
|
||||
if (((BooleanEntityMetadata) entityMetadata).getPrimitiveValue()) {
|
||||
showCustomBlock = true;
|
||||
metadata.put(EntityData.DISPLAY_ITEM, session.getBlockMappings().getBedrockBlockId(customBlock));
|
||||
metadata.put(EntityData.DISPLAY_OFFSET, customBlockOffset);
|
||||
dirtyMetadata.put(EntityData.DISPLAY_ITEM, session.getBlockMappings().getBedrockBlockId(customBlock));
|
||||
dirtyMetadata.put(EntityData.DISPLAY_OFFSET, customBlockOffset);
|
||||
} else {
|
||||
showCustomBlock = false;
|
||||
updateDefaultBlockMetadata(session);
|
||||
updateDefaultBlockMetadata();
|
||||
}
|
||||
}
|
||||
|
||||
super.updateBedrockMetadata(entityMetadata, session);
|
||||
public void updateDefaultBlockMetadata() {
|
||||
}
|
||||
|
||||
public void updateDefaultBlockMetadata(GeyserSession session) { }
|
||||
}
|
||||
|
@ -31,33 +31,31 @@ import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.math.vector.Vector3i;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
|
||||
import org.geysermc.connector.entity.type.EntityType;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class EnderCrystalEntity extends Entity {
|
||||
|
||||
public EnderCrystalEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
||||
super(entityId, geyserId, entityType, position, motion, rotation);
|
||||
|
||||
// Bedrock 1.16.100+ - prevents the entity from appearing on fire itself when fire is underneath it
|
||||
metadata.getFlags().setFlag(EntityFlag.FIRE_IMMUNE, true);
|
||||
public EnderCrystalEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
|
||||
protected void initializeMetadata() {
|
||||
super.initializeMetadata();
|
||||
// Bedrock 1.16.100+ - prevents the entity from appearing on fire itself when fire is underneath it
|
||||
dirtyMetadata.getFlags().setFlag(EntityFlag.FIRE_IMMUNE, true);
|
||||
}
|
||||
|
||||
public void setBlockTarget(EntityMetadata<Position> entityMetadata) {
|
||||
// Show beam
|
||||
// Usually performed client-side on Bedrock except for Ender Dragon respawn event
|
||||
if (entityMetadata.getId() == 8) {
|
||||
if (entityMetadata.getValue() instanceof Position pos) {
|
||||
metadata.put(EntityData.BLOCK_TARGET, Vector3i.from(pos.getX(), pos.getY(), pos.getZ()));
|
||||
Position position = entityMetadata.getValue();
|
||||
if (position != null) {
|
||||
dirtyMetadata.put(EntityData.BLOCK_TARGET, Vector3i.from(position.getX(), position.getY(), position.getZ()));
|
||||
} else {
|
||||
metadata.put(EntityData.BLOCK_TARGET, Vector3i.ZERO);
|
||||
dirtyMetadata.put(EntityData.BLOCK_TARGET, Vector3i.ZERO);
|
||||
}
|
||||
}
|
||||
// There is a base located on the ender crystal
|
||||
if (entityMetadata.getId() == 9) {
|
||||
metadata.getFlags().setFlag(EntityFlag.SHOW_BOTTOM, (boolean) entityMetadata.getValue());
|
||||
}
|
||||
super.updateBedrockMetadata(entityMetadata, session);
|
||||
}
|
||||
}
|
||||
|
@ -26,8 +26,10 @@
|
||||
package org.geysermc.connector.entity;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.MetadataType;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.Pose;
|
||||
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;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityDataMap;
|
||||
@ -38,19 +40,24 @@ import com.nukkitx.protocol.bedrock.packet.MoveEntityAbsolutePacket;
|
||||
import com.nukkitx.protocol.bedrock.packet.RemoveEntityPacket;
|
||||
import com.nukkitx.protocol.bedrock.packet.SetEntityDataPacket;
|
||||
import it.unimi.dsi.fastutil.longs.LongOpenHashSet;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.geysermc.connector.entity.type.EntityType;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
import org.geysermc.connector.network.translators.chat.MessageTranslator;
|
||||
import org.geysermc.connector.utils.MathUtils;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class Entity {
|
||||
protected final GeyserSession session;
|
||||
|
||||
protected long entityId;
|
||||
protected final long geyserId;
|
||||
protected UUID uuid;
|
||||
|
||||
protected Vector3f position;
|
||||
protected Vector3f motion;
|
||||
@ -58,85 +65,120 @@ public class Entity {
|
||||
/**
|
||||
* x = Yaw, y = Pitch, z = HeadYaw
|
||||
*/
|
||||
protected Vector3f rotation;
|
||||
protected float yaw;
|
||||
protected float pitch;
|
||||
protected float headYaw;
|
||||
|
||||
/**
|
||||
* Saves if the entity should be on the ground. Otherwise entities like parrots are flapping when rotating
|
||||
*/
|
||||
protected boolean onGround;
|
||||
|
||||
protected EntityType entityType;
|
||||
protected EntityDefinition<?> definition;
|
||||
|
||||
protected boolean valid;
|
||||
|
||||
protected LongOpenHashSet passengers = new LongOpenHashSet();
|
||||
protected EntityDataMap metadata = new EntityDataMap();
|
||||
/* Metadata about this specific entity */
|
||||
@Setter(AccessLevel.NONE)
|
||||
protected float boundingBoxHeight;
|
||||
@Setter(AccessLevel.NONE)
|
||||
protected float boundingBoxWidth;
|
||||
/* Metadata end */
|
||||
|
||||
protected LongOpenHashSet passengers = new LongOpenHashSet();
|
||||
/**
|
||||
* A container to store temporary metadata before it's sent to Bedrock.
|
||||
*/
|
||||
protected final EntityDataMap dirtyMetadata = new EntityDataMap();
|
||||
/**
|
||||
* 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;
|
||||
|
||||
public Entity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
||||
this.entityId = entityId;
|
||||
this.geyserId = geyserId;
|
||||
this.entityType = entityType;
|
||||
this.uuid = uuid;
|
||||
this.definition = definition;
|
||||
this.motion = motion;
|
||||
this.rotation = rotation;
|
||||
this.yaw = yaw;
|
||||
this.pitch = pitch;
|
||||
this.headYaw = headYaw;
|
||||
|
||||
this.valid = false;
|
||||
|
||||
setPosition(position);
|
||||
setAir(getMaxAir());
|
||||
|
||||
metadata.put(EntityData.SCALE, 1f);
|
||||
metadata.put(EntityData.COLOR, 0);
|
||||
metadata.put(EntityData.MAX_AIR_SUPPLY, getMaxAir());
|
||||
metadata.put(EntityData.LEASH_HOLDER_EID, -1L);
|
||||
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);
|
||||
initializeMetadata();
|
||||
}
|
||||
|
||||
public void spawnEntity(GeyserSession session) {
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
|
||||
public void spawnEntity() {
|
||||
AddEntityPacket addEntityPacket = new AddEntityPacket();
|
||||
addEntityPacket.setIdentifier(entityType.getIdentifier());
|
||||
addEntityPacket.setIdentifier(definition.identifier());
|
||||
addEntityPacket.setRuntimeEntityId(geyserId);
|
||||
addEntityPacket.setUniqueEntityId(geyserId);
|
||||
addEntityPacket.setPosition(position);
|
||||
addEntityPacket.setMotion(motion);
|
||||
addEntityPacket.setRotation(getBedrockRotation());
|
||||
addEntityPacket.setEntityType(entityType.getType());
|
||||
addEntityPacket.getMetadata().putAll(metadata);
|
||||
addEntityPacket.setEntityType(definition.bedrockId());
|
||||
addEntityPacket.getMetadata().putFlags(flags)
|
||||
.putAll(dirtyMetadata);
|
||||
addAdditionalSpawnData(addEntityPacket);
|
||||
|
||||
valid = true;
|
||||
session.sendUpstreamPacket(addEntityPacket);
|
||||
|
||||
session.getConnector().getLogger().debug("Spawned entity " + entityType + " at location " + position + " with id " + geyserId + " (java id " + entityId + ")");
|
||||
dirtyMetadata.clear();
|
||||
flagsDirty = false;
|
||||
|
||||
session.getConnector().getLogger().debug("Spawned entity " + getClass().getName() + " at location " + position + " with id " + geyserId + " (java id " + entityId + ")");
|
||||
}
|
||||
|
||||
/**
|
||||
* To be overridden in other entity classes, if additional things need to be done to the spawn entity packet.
|
||||
*/
|
||||
public void addAdditionalSpawnData(AddEntityPacket addEntityPacket) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Despawns the entity
|
||||
*
|
||||
* @param session The GeyserSession
|
||||
* @return can be deleted
|
||||
*/
|
||||
public boolean despawnEntity(GeyserSession session) {
|
||||
public boolean despawnEntity() {
|
||||
if (!valid) return true;
|
||||
|
||||
for (long passenger : passengers) { // Make sure all passengers on the despawned entity are updated
|
||||
Entity entity = session.getEntityCache().getEntityByJavaId(passenger);
|
||||
if (entity == null) continue;
|
||||
entity.getMetadata().getOrCreateFlags().setFlag(EntityFlag.RIDING, false);
|
||||
entity.updateBedrockMetadata(session);
|
||||
entity.setFlag(EntityFlag.RIDING, false);
|
||||
entity.updateBedrockMetadata();
|
||||
}
|
||||
|
||||
RemoveEntityPacket removeEntityPacket = new RemoveEntityPacket();
|
||||
@ -147,12 +189,14 @@ public class Entity {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void moveRelative(GeyserSession session, double relX, double relY, double relZ, float yaw, float pitch, boolean isOnGround) {
|
||||
moveRelative(session, relX, relY, relZ, Vector3f.from(yaw, pitch, this.rotation.getZ()), isOnGround);
|
||||
public void moveRelative(double relX, double relY, double relZ, float yaw, float pitch, boolean isOnGround) {
|
||||
moveRelative(relX, relY, relZ, yaw, pitch, this.headYaw, isOnGround);
|
||||
}
|
||||
|
||||
public void moveRelative(GeyserSession session, double relX, double relY, double relZ, Vector3f rotation, boolean isOnGround) {
|
||||
setRotation(rotation);
|
||||
public void moveRelative(double relX, double relY, double relZ, float yaw, float pitch, float headYaw, boolean isOnGround) {
|
||||
setYaw(yaw);
|
||||
setPitch(pitch);
|
||||
setHeadYaw(headYaw);
|
||||
setOnGround(isOnGround);
|
||||
this.position = Vector3f.from(position.getX() + relX, position.getY() + relY, position.getZ() + relZ);
|
||||
|
||||
@ -166,13 +210,16 @@ public class Entity {
|
||||
session.sendUpstreamPacket(moveEntityPacket);
|
||||
}
|
||||
|
||||
public void moveAbsolute(GeyserSession session, Vector3f position, float yaw, float pitch, boolean isOnGround, boolean teleported) {
|
||||
moveAbsolute(session, position, Vector3f.from(yaw, pitch, this.rotation.getZ()), isOnGround, teleported);
|
||||
public void moveAbsolute(Vector3f position, float yaw, float pitch, boolean isOnGround, boolean teleported) {
|
||||
moveAbsolute(position, yaw, pitch, this.headYaw, isOnGround, teleported);
|
||||
}
|
||||
|
||||
public void moveAbsolute(GeyserSession session, Vector3f position, Vector3f rotation, boolean isOnGround, boolean teleported) {
|
||||
public void moveAbsolute(Vector3f position, float yaw, float pitch, float headYaw, boolean isOnGround, boolean teleported) {
|
||||
setPosition(position);
|
||||
setRotation(rotation);
|
||||
// Setters are intentional so it can be overridden in places like AbstractArrowEntity
|
||||
setYaw(yaw);
|
||||
setPitch(pitch);
|
||||
setHeadYaw(headYaw);
|
||||
setOnGround(isOnGround);
|
||||
|
||||
MoveEntityAbsolutePacket moveEntityPacket = new MoveEntityAbsolutePacket();
|
||||
@ -187,28 +234,25 @@ public class Entity {
|
||||
|
||||
/**
|
||||
* Teleports an entity to a new location. Used in JavaTeleportEntityTranslator.
|
||||
* @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);
|
||||
public void teleport(Vector3f position, float yaw, float pitch, boolean isOnGround) {
|
||||
moveAbsolute(position, yaw, pitch, isOnGround, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates an entity's head position. Used in JavaRotateHeadTranslator.
|
||||
* @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);
|
||||
public void updateHeadLookRotation(float headYaw) {
|
||||
moveRelative(0, 0, 0, headYaw, pitch, this.headYaw, onGround);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates an entity's position and rotation. Used in JavaMoveEntityPosRotTranslator.
|
||||
* @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.
|
||||
@ -216,106 +260,115 @@ public class 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);
|
||||
public void updatePositionAndRotation(double moveX, double moveY, double moveZ, float yaw, float pitch, boolean isOnGround) {
|
||||
moveRelative(moveX, moveY, moveZ, this.yaw, pitch, yaw, isOnGround);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates an entity's rotation. Used in JavaMoveEntityRotTranslator.
|
||||
* @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);
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the Java metadata to the local Bedrock metadata copy
|
||||
* @param entityMetadata the Java entity metadata
|
||||
* @param session GeyserSession
|
||||
* Updates a flag value and determines if the flags would need synced with the Bedrock client.
|
||||
*/
|
||||
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
|
||||
switch (entityMetadata.getId()) {
|
||||
case 0:
|
||||
if (entityMetadata.getType() == MetadataType.BYTE) {
|
||||
byte xd = (byte) entityMetadata.getValue();
|
||||
metadata.getFlags().setFlag(EntityFlag.ON_FIRE, ((xd & 0x01) == 0x01) && !metadata.getFlags().getFlag(EntityFlag.FIRE_IMMUNE)); // Otherwise immune entities sometimes flicker onfire
|
||||
metadata.getFlags().setFlag(EntityFlag.SNEAKING, (xd & 0x02) == 0x02);
|
||||
metadata.getFlags().setFlag(EntityFlag.SPRINTING, (xd & 0x08) == 0x08);
|
||||
// Swimming is ignored here and instead we rely on the pose
|
||||
metadata.getFlags().setFlag(EntityFlag.GLIDING, (xd & 0x80) == 0x80);
|
||||
|
||||
setInvisible(session, (xd & 0x20) == 0x20);
|
||||
}
|
||||
break;
|
||||
case 1: // Air/bubbles
|
||||
setAir((int) entityMetadata.getValue());
|
||||
break;
|
||||
case 2: // custom name
|
||||
setDisplayName(session, (Component) entityMetadata.getValue());
|
||||
break;
|
||||
case 3: // is custom name visible
|
||||
setDisplayNameVisible(entityMetadata);
|
||||
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;
|
||||
case 6: // Pose change - typically used for bounding box and not animation
|
||||
Pose pose = (Pose) entityMetadata.getValue();
|
||||
|
||||
metadata.getFlags().setFlag(EntityFlag.SLEEPING, pose.equals(Pose.SLEEPING));
|
||||
// Triggered when crawling
|
||||
metadata.getFlags().setFlag(EntityFlag.SWIMMING, pose.equals(Pose.SWIMMING));
|
||||
setDimensions(pose);
|
||||
break;
|
||||
case 7: // Freezing ticks
|
||||
// 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((int) entityMetadata.getValue(), 140);
|
||||
setFreezing(session, freezingTicks / 140f);
|
||||
break;
|
||||
}
|
||||
public final void setFlag(EntityFlag flag, boolean value) {
|
||||
flagsDirty |= flags.setFlag(flag, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the Bedrock metadata to the client
|
||||
* @param session GeyserSession
|
||||
*/
|
||||
public void updateBedrockMetadata(GeyserSession session) {
|
||||
if (!valid) return;
|
||||
public void updateBedrockMetadata() {
|
||||
if (!valid) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!dirtyMetadata.isEmpty() || flagsDirty) {
|
||||
SetEntityDataPacket entityDataPacket = new SetEntityDataPacket();
|
||||
entityDataPacket.setRuntimeEntityId(geyserId);
|
||||
entityDataPacket.getMetadata().putAll(metadata);
|
||||
entityDataPacket.getMetadata().putFlags(flags);
|
||||
entityDataPacket.getMetadata().putAll(dirtyMetadata);
|
||||
session.sendUpstreamPacket(entityDataPacket);
|
||||
|
||||
dirtyMetadata.clear();
|
||||
flagsDirty = false;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
setInvisible((xd & 0x20) == 0x20);
|
||||
}
|
||||
|
||||
/**
|
||||
* If true, the entity should be shaking on the client's end.
|
||||
* Set a boolean - whether the entity is invisible or visible
|
||||
*
|
||||
* @return whether {@link EntityFlag#SHAKING} should be set to true.
|
||||
* @param value true if the entity is invisible
|
||||
*/
|
||||
protected boolean isShaking(GeyserSession session) {
|
||||
return false;
|
||||
protected void setInvisible(boolean value) {
|
||||
setFlag(EntityFlag.INVISIBLE, value);
|
||||
}
|
||||
|
||||
protected void setDisplayName(GeyserSession session, Component name) {
|
||||
/**
|
||||
* 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();
|
||||
if (name != null) {
|
||||
String displayName = MessageTranslator.convertMessage(name, session.getLocale());
|
||||
metadata.put(EntityData.NAMETAG, displayName);
|
||||
} else if (!metadata.getString(EntityData.NAMETAG).isEmpty()) {
|
||||
dirtyMetadata.put(EntityData.NAMETAG, displayName);
|
||||
} else if (!dirtyMetadata.getString(EntityData.NAMETAG).isEmpty()) { //TODO
|
||||
// Clear nametag
|
||||
metadata.put(EntityData.NAMETAG, "");
|
||||
dirtyMetadata.put(EntityData.NAMETAG, "");
|
||||
}
|
||||
}
|
||||
|
||||
protected void setDisplayNameVisible(EntityMetadata entityMetadata) {
|
||||
metadata.put(EntityData.NAMETAG_ALWAYS_SHOW, (byte) ((boolean) entityMetadata.getValue() ? 1 : 0));
|
||||
public void setDisplayNameVisible(EntityMetadata<Boolean> entityMetadata) {
|
||||
dirtyMetadata.put(EntityData.NAMETAG_ALWAYS_SHOW, (byte) (((BooleanEntityMetadata) entityMetadata).getPrimitiveValue() ? 1 : 0));
|
||||
}
|
||||
|
||||
public void setGravity(EntityMetadata<Boolean> entityMetadata) {
|
||||
setFlag(EntityFlag.HAS_GRAVITY, !((BooleanEntityMetadata) entityMetadata).getPrimitiveValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* Usually used for bounding box and not animation.
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -323,38 +376,33 @@ public class Entity {
|
||||
*/
|
||||
protected void setDimensions(Pose pose) {
|
||||
// No flexibility options for basic entities
|
||||
//TODO don't even set this for basic entities since we already set it on entity initialization
|
||||
metadata.put(EntityData.BOUNDING_BOX_WIDTH, entityType.getWidth());
|
||||
metadata.put(EntityData.BOUNDING_BOX_HEIGHT, entityType.getHeight());
|
||||
if (boundingBoxHeight != definition.height() || boundingBoxWidth != definition.width()) {
|
||||
boundingBoxWidth = definition.width();
|
||||
boundingBoxHeight = definition.height();
|
||||
dirtyMetadata.put(EntityData.BOUNDING_BOX_WIDTH, boundingBoxWidth);
|
||||
dirtyMetadata.put(EntityData.BOUNDING_BOX_HEIGHT, boundingBoxHeight);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a float from 0-1 - how strong the "frozen" overlay should be on screen.
|
||||
*/
|
||||
protected void setFreezing(GeyserSession session, float amount) {
|
||||
metadata.put(EntityData.FREEZING_EFFECT_STRENGTH, amount);
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set an int from 0 - this entity's maximum air - (air / maxAir) represents the percentage of bubbles left
|
||||
* @param amount the amount of air
|
||||
*/
|
||||
protected void setAir(int amount) {
|
||||
metadata.put(EntityData.AIR_SUPPLY, (short) MathUtils.constrain(amount, 0, getMaxAir()));
|
||||
}
|
||||
|
||||
protected int getMaxAir() {
|
||||
return 300;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a boolean - whether the entity is invisible or visible
|
||||
* If true, the entity should be shaking on the client's end.
|
||||
*
|
||||
* @param session the Geyser session
|
||||
* @param value true if the entity is invisible
|
||||
* @return whether {@link EntityFlag#SHAKING} should be set to true.
|
||||
*/
|
||||
protected void setInvisible(GeyserSession session, boolean value) {
|
||||
metadata.getFlags().setFlag(EntityFlag.INVISIBLE, value);
|
||||
protected boolean isShaking() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -363,7 +411,7 @@ public class Entity {
|
||||
* @return the bedrock rotation
|
||||
*/
|
||||
public Vector3f getBedrockRotation() {
|
||||
return Vector3f.from(rotation.getY(), rotation.getZ(), rotation.getX());
|
||||
return Vector3f.from(pitch, headYaw, yaw);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
|
@ -0,0 +1,140 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2021 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.entity;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.MetadataType;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.type.EntityType;
|
||||
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
|
||||
import lombok.Setter;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.geysermc.connector.entity.factory.BaseEntityFactory;
|
||||
import org.geysermc.connector.entity.factory.EntityFactory;
|
||||
import org.geysermc.connector.registry.Registries;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.function.BiConsumer;
|
||||
|
||||
/**
|
||||
* Represents data for an entity. This includes properties such as height and width, as well as the list of entity
|
||||
* metadata translators needed to translate the properties sent from the server. The translators are structured in such
|
||||
* a way that inserting a new one (for example in version updates) is convenient.
|
||||
*
|
||||
* @param <T> the entity type this definition represents
|
||||
*/
|
||||
public record EntityDefinition<T extends Entity>(EntityFactory<T> factory, EntityType entityType, int bedrockId, String identifier,
|
||||
float width, float height, float offset, List<EntityMetadataTranslator<? super T, ?>> translators) {
|
||||
|
||||
public static <T extends Entity> Builder<T> inherited(BaseEntityFactory<T> factory, EntityDefinition<? super T> parent) {
|
||||
return inherited((EntityFactory<T>) factory, parent);
|
||||
}
|
||||
|
||||
public static <T extends Entity> Builder<T> inherited(EntityFactory<T> factory, EntityDefinition<? super T> parent) {
|
||||
return new Builder<>(factory, parent.entityType, parent.bedrockId, parent.identifier, parent.width, parent.height, parent.offset, new ObjectArrayList<>(parent.translators));
|
||||
}
|
||||
|
||||
public static <T extends Entity> Builder<T> builder(EntityFactory<T> factory) {
|
||||
return new Builder<>(factory);
|
||||
}
|
||||
|
||||
@Setter
|
||||
@Accessors(fluent = true, chain = true)
|
||||
public static class Builder<T extends Entity> {
|
||||
private final EntityFactory<T> factory;
|
||||
private EntityType type;
|
||||
private int bedrockId;
|
||||
private String identifier;
|
||||
private float width;
|
||||
private float height;
|
||||
private float offset;
|
||||
private final List<EntityMetadataTranslator<? super T, ?>> translators;
|
||||
|
||||
private Builder(EntityFactory<T> factory) {
|
||||
this.factory = factory;
|
||||
translators = new ObjectArrayList<>();
|
||||
}
|
||||
|
||||
public Builder(EntityFactory<T> factory, EntityType type, int bedrockId, String identifier, float width, float height, float offset, List<EntityMetadataTranslator<? super T, ?>> translators) {
|
||||
this.factory = factory;
|
||||
this.type = type;
|
||||
this.bedrockId = bedrockId;
|
||||
this.identifier = identifier;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.offset = offset;
|
||||
this.translators = translators;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the height and width as one value
|
||||
*/
|
||||
public Builder<T> heightAndWidth(float value) {
|
||||
height = value;
|
||||
width = value;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the identifier as well
|
||||
*/
|
||||
public Builder<T> type(EntityType type) {
|
||||
this.type = type;
|
||||
identifier = null;
|
||||
return this;
|
||||
}
|
||||
|
||||
public <U> Builder<T> addTranslator(MetadataType type, BiConsumer<T, EntityMetadata<U>> translateFunction) {
|
||||
translators.add(new EntityMetadataTranslator<>(type, translateFunction));
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<T> addTranslator(EntityMetadataTranslator<T, ?> translator) {
|
||||
translators.add(translator);
|
||||
return this;
|
||||
}
|
||||
|
||||
public EntityDefinition<T> build() {
|
||||
return build(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param register whether to register this entity in the Registries for entity types. Generally this should be
|
||||
* set to false if we're not expecting this entity to spawn from the network.
|
||||
*/
|
||||
public EntityDefinition<T> build(boolean register) {
|
||||
if (identifier == null && type != null) {
|
||||
identifier = "minecraft:" + type.name().toLowerCase(Locale.ROOT);
|
||||
}
|
||||
EntityDefinition<T> definition = new EntityDefinition<>(factory, type, bedrockId, identifier, width, height, offset, translators);
|
||||
if (register && definition.entityType() != null) {
|
||||
Registries.ENTITY_DEFINITIONS.get().putIfAbsent(definition.entityType(), definition);
|
||||
Registries.JAVA_ENTITY_IDENTIFIERS.get().putIfAbsent(definition.identifier(), definition);
|
||||
}
|
||||
return definition;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,999 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2021 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.entity;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.MetadataType;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanEntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.FloatEntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.type.EntityType;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.geysermc.connector.entity.factory.BaseEntityFactory;
|
||||
import org.geysermc.connector.entity.factory.EntityFactory;
|
||||
import org.geysermc.connector.entity.factory.ExperienceOrbEntityFactory;
|
||||
import org.geysermc.connector.entity.factory.PaintingEntityFactory;
|
||||
import org.geysermc.connector.entity.living.*;
|
||||
import org.geysermc.connector.entity.living.animal.*;
|
||||
import org.geysermc.connector.entity.living.animal.horse.*;
|
||||
import org.geysermc.connector.entity.living.animal.tameable.CatEntity;
|
||||
import org.geysermc.connector.entity.living.animal.tameable.ParrotEntity;
|
||||
import org.geysermc.connector.entity.living.animal.tameable.TameableEntity;
|
||||
import org.geysermc.connector.entity.living.animal.tameable.WolfEntity;
|
||||
import org.geysermc.connector.entity.living.merchant.AbstractMerchantEntity;
|
||||
import org.geysermc.connector.entity.living.merchant.VillagerEntity;
|
||||
import org.geysermc.connector.entity.living.monster.*;
|
||||
import org.geysermc.connector.entity.living.monster.raid.PillagerEntity;
|
||||
import org.geysermc.connector.entity.living.monster.raid.RaidParticipantEntity;
|
||||
import org.geysermc.connector.entity.living.monster.raid.SpellcasterIllagerEntity;
|
||||
import org.geysermc.connector.entity.living.monster.raid.VindicatorEntity;
|
||||
import org.geysermc.connector.entity.player.PlayerEntity;
|
||||
import org.geysermc.connector.network.translators.chat.MessageTranslator;
|
||||
|
||||
public final class EntityDefinitions {
|
||||
public static final EntityDefinition<AreaEffectCloudEntity> AREA_EFFECT_CLOUD;
|
||||
public static final EntityDefinition<ArmorStandEntity> ARMOR_STAND;
|
||||
public static final EntityDefinition<TippedArrowEntity> ARROW;
|
||||
public static final EntityDefinition<AxolotlEntity> AXOLOTL;
|
||||
public static final EntityDefinition<BatEntity> BAT;
|
||||
public static final EntityDefinition<BeeEntity> BEE;
|
||||
public static final EntityDefinition<BlazeEntity> BLAZE;
|
||||
public static final EntityDefinition<BoatEntity> BOAT;
|
||||
public static final EntityDefinition<CatEntity> CAT;
|
||||
public static final EntityDefinition<MonsterEntity> CAVE_SPIDER;
|
||||
public static final EntityDefinition<ChickenEntity> CHICKEN;
|
||||
public static final EntityDefinition<CreeperEntity> CREEPER;
|
||||
public static final EntityDefinition<AbstractFishEntity> COD;
|
||||
public static final EntityDefinition<AnimalEntity> COW;
|
||||
public static final EntityDefinition<ChestedHorseEntity> DONKEY;
|
||||
public static final EntityDefinition<WaterEntity> DOLPHIN;
|
||||
public static final EntityDefinition<ItemedFireballEntity> DRAGON_FIREBALL;
|
||||
public static final EntityDefinition<ZombieEntity> DROWNED;
|
||||
public static final EntityDefinition<ElderGuardianEntity> ELDER_GUARDIAN;
|
||||
public static final EntityDefinition<EndermanEntity> ENDERMAN;
|
||||
public static final EntityDefinition<MonsterEntity> ENDERMITE;
|
||||
public static final EntityDefinition<EnderDragonEntity> ENDER_DRAGON;
|
||||
public static final EntityDefinition<EnderCrystalEntity> END_CRYSTAL;
|
||||
public static final EntityDefinition<SpellcasterIllagerEntity> EVOKER;
|
||||
public static final EntityDefinition<Entity> EVOKER_FANGS;
|
||||
public static final EntityDefinition<ExpOrbEntity> EXPERIENCE_ORB;
|
||||
public static final EntityDefinition<Entity> EYE_OF_ENDER;
|
||||
public static final EntityDefinition<FallingBlockEntity> FALLING_BLOCK;
|
||||
public static final EntityDefinition<ItemedFireballEntity> FIREBALL;
|
||||
public static final EntityDefinition<FishingHookEntity> FISHING_BOBBER;
|
||||
public static final EntityDefinition<FireworkEntity> FIREWORK_ROCKET;
|
||||
public static final EntityDefinition<FoxEntity> FOX;
|
||||
public static final EntityDefinition<GiantEntity> GIANT;
|
||||
public static final EntityDefinition<GhastEntity> GHAST;
|
||||
public static final EntityDefinition<ItemFrameEntity> GLOW_ITEM_FRAME;
|
||||
public static final EntityDefinition<GlowSquidEntity> GLOW_SQUID;
|
||||
public static final EntityDefinition<GoatEntity> GOAT;
|
||||
public static final EntityDefinition<GuardianEntity> GUARDIAN;
|
||||
public static final EntityDefinition<HoglinEntity> HOGLIN;
|
||||
public static final EntityDefinition<HorseEntity> HORSE;
|
||||
public static final EntityDefinition<ZombieEntity> HUSK;
|
||||
public static final EntityDefinition<SpellcasterIllagerEntity> ILLUSIONER; // Not present on Bedrock
|
||||
public static final EntityDefinition<IronGolemEntity> IRON_GOLEM;
|
||||
public static final EntityDefinition<ItemEntity> ITEM;
|
||||
public static final EntityDefinition<ItemFrameEntity> ITEM_FRAME;
|
||||
public static final EntityDefinition<LeashKnotEntity> LEASH_KNOT;
|
||||
public static final EntityDefinition<LightningEntity> LIGHTNING_BOLT;
|
||||
public static final EntityDefinition<LlamaEntity> LLAMA;
|
||||
public static final EntityDefinition<ThrowableEntity> LLAMA_SPIT;
|
||||
public static final EntityDefinition<MagmaCubeEntity> MAGMA_CUBE;
|
||||
public static final EntityDefinition<MinecartEntity> MINECART;
|
||||
public static final EntityDefinition<MinecartEntity> MINECART_CHEST;
|
||||
public static final EntityDefinition<CommandBlockMinecartEntity> MINECART_COMMAND_BLOCK;
|
||||
public static final EntityDefinition<MinecartEntity> MINECART_HOPPER;
|
||||
public static final EntityDefinition<FurnaceMinecartEntity> MINECART_FURNACE; // Not present on Bedrock
|
||||
public static final EntityDefinition<SpawnerMinecartEntity> MINECART_SPAWNER; // Not present on Bedrock
|
||||
public static final EntityDefinition<MinecartEntity> MINECART_TNT;
|
||||
public static final EntityDefinition<MooshroomEntity> MOOSHROOM;
|
||||
public static final EntityDefinition<ChestedHorseEntity> MULE;
|
||||
public static final EntityDefinition<OcelotEntity> OCELOT;
|
||||
public static final EntityDefinition<PaintingEntity> PAINTING;
|
||||
public static final EntityDefinition<PandaEntity> PANDA;
|
||||
public static final EntityDefinition<ParrotEntity> PARROT;
|
||||
public static final EntityDefinition<PhantomEntity> PHANTOM;
|
||||
public static final EntityDefinition<PigEntity> PIG;
|
||||
public static final EntityDefinition<PiglinEntity> PIGLIN;
|
||||
public static final EntityDefinition<BasePiglinEntity> PIGLIN_BRUTE;
|
||||
public static final EntityDefinition<PillagerEntity> PILLAGER;
|
||||
public static final EntityDefinition<PlayerEntity> PLAYER;
|
||||
public static final EntityDefinition<PolarBearEntity> POLAR_BEAR;
|
||||
public static final EntityDefinition<TNTEntity> PRIMED_TNT;
|
||||
public static final EntityDefinition<PufferFishEntity> PUFFERFISH;
|
||||
public static final EntityDefinition<RabbitEntity> RABBIT;
|
||||
public static final EntityDefinition<RaidParticipantEntity> RAVAGER;
|
||||
public static final EntityDefinition<AbstractFishEntity> SALMON;
|
||||
public static final EntityDefinition<SheepEntity> SHEEP;
|
||||
public static final EntityDefinition<ShulkerEntity> SHULKER;
|
||||
public static final EntityDefinition<ThrowableEntity> SHULKER_BULLET;
|
||||
public static final EntityDefinition<MonsterEntity> SILVERFISH;
|
||||
public static final EntityDefinition<SkeletonEntity> SKELETON;
|
||||
public static final EntityDefinition<AbstractHorseEntity> SKELETON_HORSE;
|
||||
public static final EntityDefinition<SlimeEntity> SLIME;
|
||||
public static final EntityDefinition<ItemedFireballEntity> SMALL_FIREBALL;
|
||||
public static final EntityDefinition<ThrowableItemEntity> SNOWBALL;
|
||||
public static final EntityDefinition<SnowGolemEntity> SNOW_GOLEM;
|
||||
public static final EntityDefinition<AbstractArrowEntity> SPECTRAL_ARROW;
|
||||
public static final EntityDefinition<SpiderEntity> SPIDER;
|
||||
public static final EntityDefinition<SquidEntity> SQUID;
|
||||
public static final EntityDefinition<AbstractSkeletonEntity> STRAY;
|
||||
public static final EntityDefinition<StriderEntity> STRIDER;
|
||||
public static final EntityDefinition<ThrowableItemEntity> THROWN_EGG;
|
||||
public static final EntityDefinition<ThrowableItemEntity> THROWN_ENDERPEARL;
|
||||
public static final EntityDefinition<ThrowableItemEntity> THROWN_EXP_BOTTLE;
|
||||
public static final EntityDefinition<ThrownPotionEntity> THROWN_POTION;
|
||||
public static final EntityDefinition<TropicalFishEntity> TROPICAL_FISH;
|
||||
public static final EntityDefinition<TurtleEntity> TURTLE;
|
||||
public static final EntityDefinition<TraderLlamaEntity> TRADER_LLAMA;
|
||||
public static final EntityDefinition<TridentEntity> TRIDENT;
|
||||
public static final EntityDefinition<AbstractMerchantEntity> WANDERING_TRADER;
|
||||
public static final EntityDefinition<RaidParticipantEntity> WITCH;
|
||||
public static final EntityDefinition<WitherEntity> WITHER;
|
||||
public static final EntityDefinition<AbstractSkeletonEntity> WITHER_SKELETON;
|
||||
public static final EntityDefinition<WitherSkullEntity> WITHER_SKULL;
|
||||
public static final EntityDefinition<WolfEntity> WOLF;
|
||||
public static final EntityDefinition<VillagerEntity> VILLAGER;
|
||||
public static final EntityDefinition<VindicatorEntity> VINDICATOR;
|
||||
public static final EntityDefinition<VexEntity> VEX;
|
||||
public static final EntityDefinition<ZoglinEntity> ZOGLIN;
|
||||
public static final EntityDefinition<ZombieEntity> ZOMBIE;
|
||||
public static final EntityDefinition<AbstractHorseEntity> ZOMBIE_HORSE;
|
||||
public static final EntityDefinition<ZombieVillagerEntity> ZOMBIE_VILLAGER;
|
||||
public static final EntityDefinition<ZombifiedPiglinEntity> ZOMBIFIED_PIGLIN;
|
||||
|
||||
/**
|
||||
* Is not sent over the network
|
||||
*/
|
||||
public static final EntityDefinition<EnderDragonPartEntity> ENDER_DRAGON_PART;
|
||||
/**
|
||||
* Special Bedrock type
|
||||
*/
|
||||
public static final EntityDefinition<WitherSkullEntity> WITHER_SKULL_DANGEROUS;
|
||||
|
||||
static {
|
||||
EntityDefinition<Entity> entityBase = EntityDefinition.builder((BaseEntityFactory<Entity>) Entity::new)
|
||||
.addTranslator(MetadataType.BYTE, Entity::setFlags)
|
||||
.addTranslator(MetadataType.INT, Entity::setAir) // Air/bubbles
|
||||
.addTranslator(MetadataType.OPTIONAL_CHAT, Entity::setDisplayName)
|
||||
.addTranslator(MetadataType.BOOLEAN, Entity::setDisplayNameVisible)
|
||||
.<Boolean>addTranslator(MetadataType.BOOLEAN, (entity, entityMetadata) -> entity.setFlag(EntityFlag.SILENT, ((BooleanEntityMetadata) entityMetadata).getPrimitiveValue()))
|
||||
.addTranslator(MetadataType.BOOLEAN, Entity::setGravity)
|
||||
.addTranslator(MetadataType.POSE, Entity::setPose)
|
||||
.addTranslator(MetadataType.INT, Entity::setFreezing)
|
||||
.build();
|
||||
|
||||
// Extends entity
|
||||
{
|
||||
AREA_EFFECT_CLOUD = EntityDefinition.inherited(AreaEffectCloudEntity::new, entityBase)
|
||||
.type(EntityType.AREA_EFFECT_CLOUD)
|
||||
.bedrockId(95)
|
||||
.height(0.5f).width(1.0f)
|
||||
.addTranslator(MetadataType.FLOAT, AreaEffectCloudEntity::setRadius)
|
||||
.addTranslator(MetadataType.INT, (entity, entityMetadata) -> entity.getDirtyMetadata().put(EntityData.EFFECT_COLOR, entityMetadata.getValue()))
|
||||
.addTranslator(null) // Waiting
|
||||
.addTranslator(MetadataType.PARTICLE, AreaEffectCloudEntity::setParticle)
|
||||
.build();
|
||||
BOAT = EntityDefinition.inherited(BoatEntity::new, entityBase)
|
||||
.type(EntityType.BOAT)
|
||||
.bedrockId(90)
|
||||
.height(0.6f).width(1.6f)
|
||||
.offset(0.35f)
|
||||
.addTranslator(MetadataType.INT, (boatEntity, entityMetadata) -> boatEntity.getDirtyMetadata().put(EntityData.HURT_TIME, entityMetadata.getValue())) // Time since last hit
|
||||
.addTranslator(MetadataType.INT, (boatEntity, entityMetadata) -> boatEntity.getDirtyMetadata().put(EntityData.HURT_DIRECTION, entityMetadata.getValue())) // Rocking direction
|
||||
.<Float>addTranslator(MetadataType.FLOAT, (boatEntity, entityMetadata) ->
|
||||
// 'Health' in Bedrock, damage taken in Java - it makes motion in Bedrock
|
||||
boatEntity.getDirtyMetadata().put(EntityData.HEALTH, 40 - ((int) ((FloatEntityMetadata) entityMetadata).getPrimitiveValue())))
|
||||
.addTranslator(MetadataType.INT, BoatEntity::setVariant)
|
||||
.addTranslator(MetadataType.BOOLEAN, BoatEntity::setPaddlingLeft)
|
||||
.addTranslator(MetadataType.BOOLEAN, BoatEntity::setPaddlingRight)
|
||||
.addTranslator(MetadataType.INT, (boatEntity, entityMetadata) -> boatEntity.getDirtyMetadata().put(EntityData.BOAT_BUBBLE_TIME, entityMetadata.getValue())) // May not actually do anything
|
||||
.build();
|
||||
DRAGON_FIREBALL = EntityDefinition.inherited(ItemedFireballEntity::new, entityBase)
|
||||
.type(EntityType.DRAGON_FIREBALL)
|
||||
.bedrockId(79)
|
||||
.heightAndWidth(1.0f)
|
||||
.build();
|
||||
END_CRYSTAL = EntityDefinition.inherited(EnderCrystalEntity::new, entityBase)
|
||||
.type(EntityType.END_CRYSTAL)
|
||||
.bedrockId(71)
|
||||
.heightAndWidth(2.0f)
|
||||
.addTranslator(MetadataType.OPTIONAL_POSITION, EnderCrystalEntity::setBlockTarget)
|
||||
.<Boolean>addTranslator(MetadataType.BOOLEAN,
|
||||
(enderCrystalEntity, entityMetadata) -> enderCrystalEntity.setFlag(EntityFlag.SHOW_BOTTOM, ((BooleanEntityMetadata) entityMetadata).getPrimitiveValue())) // There is a base located on the ender crystal
|
||||
.build();
|
||||
EXPERIENCE_ORB = EntityDefinition.inherited((ExperienceOrbEntityFactory) ExpOrbEntity::new, entityBase)
|
||||
.type(EntityType.EXPERIENCE_ORB)
|
||||
.bedrockId(69)
|
||||
.identifier("minecraft:xp_orb")
|
||||
.build();
|
||||
EVOKER_FANGS = EntityDefinition.inherited(entityBase.factory(), entityBase)
|
||||
.type(EntityType.EVOKER_FANGS)
|
||||
.bedrockId(103)
|
||||
.height(0.8f).width(0.5f)
|
||||
.identifier("minecraft:evocation_fang")
|
||||
.build();
|
||||
EYE_OF_ENDER = EntityDefinition.inherited(Entity::new, entityBase)
|
||||
.type(EntityType.EYE_OF_ENDER)
|
||||
.bedrockId(70)
|
||||
.heightAndWidth(0.25f)
|
||||
.identifier("minecraft:eye_of_ender_signal")
|
||||
.build();
|
||||
FALLING_BLOCK = EntityDefinition.inherited(new EntityFactory<FallingBlockEntity>() {
|
||||
}, entityBase) // TODO
|
||||
.type(EntityType.FALLING_BLOCK)
|
||||
.bedrockId(66)
|
||||
.heightAndWidth(0.98f)
|
||||
.build();
|
||||
FIREBALL = EntityDefinition.inherited(ItemedFireballEntity::new, entityBase)
|
||||
.type(EntityType.FIREBALL)
|
||||
.bedrockId(85)
|
||||
.heightAndWidth(1.0f)
|
||||
.build();
|
||||
FIREWORK_ROCKET = EntityDefinition.inherited(FireworkEntity::new, entityBase)
|
||||
.type(EntityType.FIREWORK_ROCKET)
|
||||
.bedrockId(72)
|
||||
.heightAndWidth(0.25f)
|
||||
.identifier("minecraft:fireworks_rocket")
|
||||
.addTranslator(MetadataType.ITEM, FireworkEntity::setFireworkItem)
|
||||
.addTranslator(MetadataType.OPTIONAL_VARINT, FireworkEntity::setPlayerGliding)
|
||||
.build();
|
||||
FISHING_BOBBER = EntityDefinition.inherited(new EntityFactory<FishingHookEntity>() {
|
||||
}, entityBase) //TODO
|
||||
.type(EntityType.FISHING_BOBBER)
|
||||
.bedrockId(77)
|
||||
.identifier("minecraft:fishing_book")
|
||||
.addTranslator(MetadataType.INT, FishingHookEntity::setHookedEntity)
|
||||
.build();
|
||||
ITEM = EntityDefinition.inherited(ItemEntity::new, entityBase)
|
||||
.type(EntityType.ITEM)
|
||||
.bedrockId(64)
|
||||
.heightAndWidth(0.25f)
|
||||
.offset(0.125f)
|
||||
.addTranslator(MetadataType.ITEM, ItemEntity::setItem)
|
||||
.build();
|
||||
LEASH_KNOT = EntityDefinition.inherited(LeashKnotEntity::new, entityBase)
|
||||
.type(EntityType.LEASH_KNOT)
|
||||
.bedrockId(88)
|
||||
.height(0.5f).width(0.375f)
|
||||
.build();
|
||||
LIGHTNING_BOLT = EntityDefinition.inherited(LightningEntity::new, entityBase)
|
||||
.type(EntityType.LIGHTNING_BOLT)
|
||||
.bedrockId(93)
|
||||
.build();
|
||||
LLAMA_SPIT = EntityDefinition.inherited(ThrowableEntity::new, entityBase)
|
||||
.type(EntityType.LLAMA_SPIT)
|
||||
.bedrockId(102)
|
||||
.heightAndWidth(0.25f)
|
||||
.build();
|
||||
PAINTING = EntityDefinition.inherited((PaintingEntityFactory) PaintingEntity::new, entityBase)
|
||||
.type(EntityType.PAINTING)
|
||||
.bedrockId(83)
|
||||
.build();
|
||||
PRIMED_TNT = EntityDefinition.inherited(TNTEntity::new, entityBase)
|
||||
.type(EntityType.PRIMED_TNT)
|
||||
.bedrockId(65)
|
||||
.heightAndWidth(0.98f)
|
||||
.identifier("minecraft:tnt")
|
||||
.addTranslator(MetadataType.INT, TNTEntity::setFuseLength)
|
||||
.build();
|
||||
SHULKER_BULLET = EntityDefinition.inherited(ThrowableEntity::new, entityBase)
|
||||
.type(EntityType.SHULKER_BULLET)
|
||||
.bedrockId(76)
|
||||
.heightAndWidth(0.3125f)
|
||||
.build();
|
||||
SMALL_FIREBALL = EntityDefinition.inherited(ItemedFireballEntity::new, entityBase)
|
||||
.type(EntityType.SMALL_FIREBALL)
|
||||
.bedrockId(94)
|
||||
.heightAndWidth(0.3125f)
|
||||
.build();
|
||||
SNOWBALL = EntityDefinition.inherited(ThrowableItemEntity::new, entityBase)
|
||||
.type(EntityType.SNOWBALL)
|
||||
.bedrockId(81)
|
||||
.heightAndWidth(0.25f)
|
||||
.build();
|
||||
THROWN_ENDERPEARL = EntityDefinition.inherited(ThrowableItemEntity::new, entityBase)
|
||||
.type(EntityType.THROWN_ENDERPEARL)
|
||||
.bedrockId(87)
|
||||
.heightAndWidth(0.25f)
|
||||
.identifier("minecraft:ender_pearl")
|
||||
.build();
|
||||
THROWN_EGG = EntityDefinition.inherited(ThrowableItemEntity::new, entityBase)
|
||||
.type(EntityType.THROWN_EGG)
|
||||
.bedrockId(82)
|
||||
.heightAndWidth(0.25f)
|
||||
.identifier("minecraft:egg")
|
||||
.build();
|
||||
THROWN_EXP_BOTTLE = EntityDefinition.inherited(ThrowableItemEntity::new, entityBase)
|
||||
.type(EntityType.THROWN_EXP_BOTTLE)
|
||||
.bedrockId(68)
|
||||
.heightAndWidth(0.25f)
|
||||
.identifier("minecraft:xp_bottle")
|
||||
.build();
|
||||
THROWN_POTION = EntityDefinition.inherited(ThrownPotionEntity::new, entityBase)
|
||||
.type(EntityType.THROWN_POTION)
|
||||
.bedrockId(86)
|
||||
.heightAndWidth(0.25f)
|
||||
.identifier("minecraft:splash_potion")
|
||||
.addTranslator(MetadataType.ITEM, ThrownPotionEntity::setPotion)
|
||||
.build();
|
||||
|
||||
EntityDefinition<AbstractArrowEntity> abstractArrowBase = EntityDefinition.inherited(AbstractArrowEntity::new, entityBase)
|
||||
.addTranslator(MetadataType.BYTE, AbstractArrowEntity::setArrowFlags)
|
||||
.addTranslator(null) // "Piercing level"
|
||||
.build();
|
||||
ARROW = EntityDefinition.inherited(TippedArrowEntity::new, abstractArrowBase)
|
||||
.type(EntityType.ARROW)
|
||||
.bedrockId(80)
|
||||
.heightAndWidth(0.25f)
|
||||
.addTranslator(MetadataType.INT, TippedArrowEntity::setPotionEffectColor)
|
||||
.build();
|
||||
SPECTRAL_ARROW = EntityDefinition.inherited(abstractArrowBase.factory(), abstractArrowBase)
|
||||
.type(EntityType.SPECTRAL_ARROW)
|
||||
.bedrockId(80)
|
||||
.heightAndWidth(0.25f)
|
||||
.identifier("minecraft:arrow")
|
||||
.build();
|
||||
TRIDENT = EntityDefinition.inherited(TridentEntity::new, abstractArrowBase) // TODO remove class
|
||||
.type(EntityType.TRIDENT)
|
||||
.bedrockId(73)
|
||||
.identifier("minecraft:thrown_trident")
|
||||
.addTranslator(null) // Loyalty
|
||||
.<Boolean>addTranslator(MetadataType.BOOLEAN, (tridentEntity, entityMetadata) -> tridentEntity.setFlag(EntityFlag.ENCHANTED, ((BooleanEntityMetadata) entityMetadata).getPrimitiveValue()))
|
||||
.build();
|
||||
|
||||
// Item frames are handled differently as they are blocks, not items, in Bedrock
|
||||
ITEM_FRAME = EntityDefinition.inherited(new EntityFactory<ItemFrameEntity>() {
|
||||
}, entityBase) // TODO
|
||||
.type(EntityType.ITEM_FRAME)
|
||||
.addTranslator(MetadataType.ITEM, ItemFrameEntity::setItemInFrame)
|
||||
.addTranslator(MetadataType.ITEM, ItemFrameEntity::setItemRotation)
|
||||
.build();
|
||||
GLOW_ITEM_FRAME = EntityDefinition.inherited(ITEM_FRAME.factory(), ITEM_FRAME)
|
||||
.type(EntityType.GLOW_ITEM_FRAME)
|
||||
.build();
|
||||
|
||||
MINECART = EntityDefinition.inherited(MinecartEntity::new, entityBase)
|
||||
.type(EntityType.MINECART)
|
||||
.bedrockId(84)
|
||||
.height(0.7f).width(0.98f)
|
||||
.offset(0.35f)
|
||||
.addTranslator(MetadataType.INT, (minecartEntity, entityMetadata) -> minecartEntity.getDirtyMetadata().put(EntityData.HEALTH, entityMetadata.getValue()))
|
||||
.addTranslator(MetadataType.INT, (minecartEntity, entityMetadata) -> minecartEntity.getDirtyMetadata().put(EntityData.HURT_DIRECTION, entityMetadata.getValue())) // Direction in which the minecart is shaking
|
||||
.<Float>addTranslator(MetadataType.FLOAT, (minecartEntity, entityMetadata) ->
|
||||
// Power in Java, time in Bedrock
|
||||
minecartEntity.getDirtyMetadata().put(EntityData.HURT_TIME, Math.min((int) ((FloatEntityMetadata) entityMetadata).getPrimitiveValue(), 15)))
|
||||
.addTranslator(MetadataType.BLOCK_STATE, MinecartEntity::setCustomBlock)
|
||||
.addTranslator(MetadataType.INT, MinecartEntity::setCustomBlockOffset)
|
||||
.addTranslator(MetadataType.BOOLEAN, MinecartEntity::setShowCustomBlock)
|
||||
.build();
|
||||
MINECART_CHEST = EntityDefinition.inherited(MINECART.factory(), MINECART)
|
||||
.type(EntityType.MINECART_CHEST)
|
||||
.identifier("minecraft:chest_minecart")
|
||||
.build();
|
||||
MINECART_COMMAND_BLOCK = EntityDefinition.inherited(CommandBlockMinecartEntity::new, MINECART)
|
||||
.type(EntityType.MINECART_COMMAND_BLOCK)
|
||||
.bedrockId(100)
|
||||
.identifier("minecraft:command_block_minecart")
|
||||
.addTranslator(MetadataType.STRING, (entity, entityMetadata) -> entity.getDirtyMetadata().put(EntityData.COMMAND_BLOCK_COMMAND, entityMetadata.getValue()))
|
||||
.<Component>addTranslator(MetadataType.CHAT, (entity, entityMetadata) -> entity.getDirtyMetadata().put(EntityData.COMMAND_BLOCK_LAST_OUTPUT, MessageTranslator.convertMessage(entityMetadata.getValue())))
|
||||
.build();
|
||||
MINECART_FURNACE = EntityDefinition.inherited(FurnaceMinecartEntity::new, MINECART)
|
||||
.type(EntityType.MINECART_FURNACE)
|
||||
.identifier("minecraft:minecart")
|
||||
.addTranslator(MetadataType.BOOLEAN, FurnaceMinecartEntity::setHasFuel)
|
||||
.build();
|
||||
MINECART_HOPPER = EntityDefinition.inherited(MINECART.factory(), MINECART)
|
||||
.type(EntityType.MINECART_HOPPER)
|
||||
.identifier("minecraft:hopper_minecart")
|
||||
.build();
|
||||
MINECART_SPAWNER = EntityDefinition.inherited(SpawnerMinecartEntity::new, MINECART)
|
||||
.type(EntityType.MINECART_SPAWNER)
|
||||
.identifier("minecraft:minecart")
|
||||
.build();
|
||||
MINECART_TNT = EntityDefinition.inherited(MINECART.factory(), MINECART)
|
||||
.type(EntityType.MINECART_TNT)
|
||||
.identifier("minecraft:tnt_minecart")
|
||||
.build();
|
||||
|
||||
WITHER_SKULL = EntityDefinition.inherited(WitherSkullEntity::new, entityBase)
|
||||
.type(EntityType.WITHER_SKULL)
|
||||
.bedrockId(89)
|
||||
.heightAndWidth(0.3125f)
|
||||
.addTranslator(MetadataType.BOOLEAN, WitherSkullEntity::setDangerous)
|
||||
.build();
|
||||
WITHER_SKULL_DANGEROUS = EntityDefinition.inherited(WITHER_SKULL.factory(), WITHER_SKULL)
|
||||
.bedrockId(91)
|
||||
.build(false);
|
||||
}
|
||||
|
||||
EntityDefinition<LivingEntity> livingEntityBase = EntityDefinition.inherited(LivingEntity::new, entityBase)
|
||||
.addTranslator(MetadataType.BYTE, LivingEntity::setLivingEntityFlags)
|
||||
.addTranslator(MetadataType.FLOAT, LivingEntity::setHealth)
|
||||
.<Float>addTranslator(MetadataType.FLOAT,
|
||||
(livingEntity, entityMetadata) -> livingEntity.getDirtyMetadata().put(EntityData.EFFECT_COLOR, entityMetadata.getValue()))
|
||||
.<Boolean>addTranslator(MetadataType.BOOLEAN,
|
||||
(livingEntity, entityMetadata) -> livingEntity.getDirtyMetadata().put(EntityData.EFFECT_AMBIENT, (byte) (((BooleanEntityMetadata) entityMetadata).getPrimitiveValue() ? 1 : 0)))
|
||||
.addTranslator(null) // Arrow count
|
||||
.addTranslator(null) // Stinger count
|
||||
.addTranslator(MetadataType.POSITION, LivingEntity::setBedPosition)
|
||||
.build();
|
||||
|
||||
ARMOR_STAND = EntityDefinition.inherited(ArmorStandEntity::new, livingEntityBase)
|
||||
.type(EntityType.ARMOR_STAND)
|
||||
.bedrockId(61)
|
||||
.height(1.975f).width(0.5f)
|
||||
.addTranslator(MetadataType.BYTE, ArmorStandEntity::setArmorStandFlags)
|
||||
.addTranslator(MetadataType.ROTATION, ArmorStandEntity::setHeadRotation)
|
||||
.addTranslator(MetadataType.ROTATION, ArmorStandEntity::setBodyRotation)
|
||||
.addTranslator(MetadataType.ROTATION, ArmorStandEntity::setLeftArmRotation)
|
||||
.addTranslator(MetadataType.ROTATION, ArmorStandEntity::setRightArmRotation)
|
||||
.addTranslator(MetadataType.ROTATION, ArmorStandEntity::setLeftLegRotation)
|
||||
.addTranslator(MetadataType.ROTATION, ArmorStandEntity::setRightLegRotation)
|
||||
.build();
|
||||
PLAYER = EntityDefinition.<PlayerEntity>inherited(null, livingEntityBase)
|
||||
.type(EntityType.PLAYER)
|
||||
.bedrockId(63)
|
||||
.height(1.8f).width(0.6f)
|
||||
.offset(1.62f)
|
||||
.addTranslator(MetadataType.FLOAT, PlayerEntity::setAbsorptionHearts)
|
||||
.addTranslator(null) // Player score
|
||||
.addTranslator(MetadataType.BYTE, PlayerEntity::setSkinVisibility)
|
||||
.addTranslator(null) // Player main hand
|
||||
.addTranslator(MetadataType.NBT_TAG, PlayerEntity::setLeftParrot)
|
||||
.addTranslator(MetadataType.NBT_TAG, PlayerEntity::setRightParrot)
|
||||
.build();
|
||||
|
||||
EntityDefinition<MobEntity> mobEntityBase = EntityDefinition.inherited(MobEntity::new, livingEntityBase)
|
||||
.addTranslator(MetadataType.BYTE, MobEntity::setMobFlags)
|
||||
.build();
|
||||
|
||||
// Extends mob
|
||||
{
|
||||
BAT = EntityDefinition.inherited(BatEntity::new, mobEntityBase)
|
||||
.type(EntityType.BAT)
|
||||
.bedrockId(19)
|
||||
.height(0.9f).width(0.5f)
|
||||
.addTranslator(MetadataType.BYTE, BatEntity::setBatFlags)
|
||||
.build();
|
||||
BLAZE = EntityDefinition.inherited(BlazeEntity::new, mobEntityBase)
|
||||
.type(EntityType.BLAZE)
|
||||
.bedrockId(43)
|
||||
.height(1.8f).width(0.6f)
|
||||
.addTranslator(MetadataType.BYTE, BlazeEntity::setBlazeFlags)
|
||||
.build();
|
||||
CAVE_SPIDER = EntityDefinition.inherited(MonsterEntity::new, mobEntityBase)
|
||||
.type(EntityType.CAVE_SPIDER)
|
||||
.bedrockId(40)
|
||||
.height(0.5f).width(0.7f)
|
||||
.build();
|
||||
CREEPER = EntityDefinition.inherited(CreeperEntity::new, mobEntityBase)
|
||||
.type(EntityType.CREEPER)
|
||||
.bedrockId(33)
|
||||
.height(1.7f).width(0.6f)
|
||||
.offset(1.62f)
|
||||
.addTranslator(MetadataType.INT, CreeperEntity::setSwelling)
|
||||
.<Boolean>addTranslator(MetadataType.BOOLEAN, (entity, entityMetadata) -> entity.setFlag(EntityFlag.POWERED, ((BooleanEntityMetadata) entityMetadata).getPrimitiveValue()))
|
||||
.addTranslator(MetadataType.BOOLEAN, CreeperEntity::setIgnited)
|
||||
.build();
|
||||
DOLPHIN = EntityDefinition.inherited(WaterEntity::new, mobEntityBase)
|
||||
.type(EntityType.DOLPHIN)
|
||||
.bedrockId(31)
|
||||
.height(0.6f).width(0.9f)
|
||||
//TODO check
|
||||
.addTranslator(null) // treasure position
|
||||
.addTranslator(null) // "got fish"
|
||||
.addTranslator(null) // "moistness level"
|
||||
.build();
|
||||
ENDERMAN = EntityDefinition.inherited(EndermanEntity::new, mobEntityBase)
|
||||
.type(EntityType.ENDERMAN)
|
||||
.bedrockId(38)
|
||||
.height(2.9f).width(0.6f)
|
||||
.addTranslator(MetadataType.BLOCK_STATE, EndermanEntity::setCarriedBlock)
|
||||
.addTranslator(MetadataType.BOOLEAN, EndermanEntity::setScreaming)
|
||||
.addTranslator(MetadataType.BOOLEAN, EndermanEntity::setAngry)
|
||||
.build();
|
||||
ENDERMITE = EntityDefinition.inherited(MonsterEntity::new, mobEntityBase)
|
||||
.type(EntityType.ENDERMITE)
|
||||
.bedrockId(55)
|
||||
.height(0.3f).width(0.4f)
|
||||
.build();
|
||||
ENDER_DRAGON = EntityDefinition.inherited(EnderDragonEntity::new, mobEntityBase)
|
||||
.type(EntityType.ENDER_DRAGON)
|
||||
.bedrockId(53)
|
||||
.addTranslator(MetadataType.INT, EnderDragonEntity::setPhase)
|
||||
.build();
|
||||
GHAST = EntityDefinition.inherited(GhastEntity::new, mobEntityBase)
|
||||
.type(EntityType.GHAST)
|
||||
.bedrockId(41)
|
||||
.heightAndWidth(4.0f)
|
||||
.addTranslator(MetadataType.BOOLEAN, GhastEntity::setGhastAttacking)
|
||||
.build();
|
||||
GIANT = EntityDefinition.inherited(GiantEntity::new, mobEntityBase)
|
||||
.type(EntityType.GIANT)
|
||||
.bedrockId(32)
|
||||
.height(1.8f).width(1.6f)
|
||||
.offset(1.62f)
|
||||
.identifier("minecraft:zombie")
|
||||
.build();
|
||||
IRON_GOLEM = EntityDefinition.inherited(IronGolemEntity::new, mobEntityBase)
|
||||
.type(EntityType.IRON_GOLEM)
|
||||
.bedrockId(20)
|
||||
.height(2.7f).width(1.4f)
|
||||
.build();
|
||||
PHANTOM = EntityDefinition.inherited(PhantomEntity::new, mobEntityBase)
|
||||
.type(EntityType.PHANTOM)
|
||||
.bedrockId(58)
|
||||
.height(0.5f).width(0.9f)
|
||||
.offset(0.6f)
|
||||
.addTranslator(MetadataType.INT, PhantomEntity::setPhantomScale)
|
||||
.build();
|
||||
SILVERFISH = EntityDefinition.inherited(MonsterEntity::new, mobEntityBase)
|
||||
.type(EntityType.SILVERFISH)
|
||||
.bedrockId(39)
|
||||
.height(0.3f).width(0.4f)
|
||||
.build();
|
||||
SHULKER = EntityDefinition.inherited(ShulkerEntity::new, mobEntityBase)
|
||||
.type(EntityType.SHULKER)
|
||||
.bedrockId(54)
|
||||
.heightAndWidth(1f)
|
||||
.addTranslator(MetadataType.DIRECTION, ShulkerEntity::setAttachedFace)
|
||||
.addTranslator(MetadataType.BYTE, ShulkerEntity::setShulkerHeight)
|
||||
.addTranslator(MetadataType.BYTE, ShulkerEntity::setShulkerColor)
|
||||
.build();
|
||||
SKELETON = EntityDefinition.inherited(SkeletonEntity::new, mobEntityBase)
|
||||
.type(EntityType.SKELETON)
|
||||
.bedrockId(34)
|
||||
.height(1.8f).width(0.6f)
|
||||
.offset(1.62f)
|
||||
.addTranslator(MetadataType.BOOLEAN, SkeletonEntity::setConvertingToStray)
|
||||
.build();
|
||||
SNOW_GOLEM = EntityDefinition.inherited(SnowGolemEntity::new, mobEntityBase)
|
||||
.type(EntityType.SNOW_GOLEM)
|
||||
.bedrockId(21)
|
||||
.height(1.9f).width(0.7f)
|
||||
.addTranslator(MetadataType.BYTE, SnowGolemEntity::setSnowGolemFlags)
|
||||
.build();
|
||||
SPIDER = EntityDefinition.inherited(SpiderEntity::new, mobEntityBase)
|
||||
.type(EntityType.SPIDER)
|
||||
.bedrockId(35)
|
||||
.height(0.9f).width(1.4f)
|
||||
.offset(1f)
|
||||
.addTranslator(MetadataType.BYTE, SpiderEntity::setSpiderFlags)
|
||||
.build();
|
||||
SQUID = EntityDefinition.inherited(SquidEntity::new, mobEntityBase)
|
||||
.type(EntityType.SQUID)
|
||||
.bedrockId(17)
|
||||
.heightAndWidth(0.8f)
|
||||
.build();
|
||||
STRAY = EntityDefinition.inherited(AbstractSkeletonEntity::new, mobEntityBase)
|
||||
.type(EntityType.STRAY)
|
||||
.bedrockId(46)
|
||||
.height(1.8f).width(0.6f)
|
||||
.offset(1.62f)
|
||||
.build();
|
||||
VEX = EntityDefinition.inherited(VexEntity::new, mobEntityBase)
|
||||
.type(EntityType.VEX)
|
||||
.bedrockId(105)
|
||||
.height(0.8f).width(0.4f)
|
||||
.addTranslator(MetadataType.BYTE, VexEntity::setVexFlags)
|
||||
.build();
|
||||
WITHER = EntityDefinition.inherited(WitherEntity::new, mobEntityBase)
|
||||
.type(EntityType.WITHER)
|
||||
.bedrockId(52)
|
||||
.height(3.5f).width(0.9f)
|
||||
.addTranslator(MetadataType.INT, WitherEntity::setTarget1)
|
||||
.addTranslator(MetadataType.INT, WitherEntity::setTarget2)
|
||||
.addTranslator(MetadataType.INT, WitherEntity::setTarget3)
|
||||
.addTranslator(MetadataType.INT, WitherEntity::setInvulnerableTicks)
|
||||
.build();
|
||||
WITHER_SKELETON = EntityDefinition.inherited(AbstractSkeletonEntity::new, mobEntityBase)
|
||||
.type(EntityType.WITHER_SKELETON)
|
||||
.bedrockId(48)
|
||||
.height(2.4f).width(0.7f)
|
||||
.build();
|
||||
ZOGLIN = EntityDefinition.inherited(ZoglinEntity::new, mobEntityBase)
|
||||
.type(EntityType.ZOGLIN)
|
||||
.bedrockId(126)
|
||||
.height(1.4f).width(1.3965f)
|
||||
.addTranslator(MetadataType.BOOLEAN, ZoglinEntity::setBaby)
|
||||
.build();
|
||||
ZOMBIE = EntityDefinition.inherited(ZombieEntity::new, mobEntityBase)
|
||||
.type(EntityType.ZOMBIE)
|
||||
.bedrockId(32)
|
||||
.height(1.8f).width(0.6f)
|
||||
.offset(1.62f)
|
||||
.addTranslator(MetadataType.BOOLEAN, ZombieEntity::setZombieBaby)
|
||||
.addTranslator(null) // "set special type", doesn't do anything
|
||||
.addTranslator(MetadataType.BOOLEAN, ZombieEntity::setConvertingToDrowned)
|
||||
.build();
|
||||
ZOMBIE_VILLAGER = EntityDefinition.inherited(ZombieVillagerEntity::new, ZOMBIE)
|
||||
.type(EntityType.ZOMBIE_VILLAGER)
|
||||
.bedrockId(44)
|
||||
.height(1.8f).width(0.6f)
|
||||
.offset(1.62f)
|
||||
.identifier("minecraft:zombie_villager_v2")
|
||||
.addTranslator(MetadataType.BOOLEAN, ZombieVillagerEntity::setTransforming)
|
||||
.addTranslator(MetadataType.VILLAGER_DATA, ZombieVillagerEntity::setZombieVillagerData)
|
||||
.build();
|
||||
ZOMBIFIED_PIGLIN = EntityDefinition.inherited(ZombifiedPiglinEntity::new, ZOMBIE) //TODO test how zombie entity metadata is handled?
|
||||
.type(EntityType.ZOMBIFIED_PIGLIN)
|
||||
.bedrockId(36)
|
||||
.height(1.95f).width(0.6f)
|
||||
.offset(1.62f)
|
||||
.identifier("minecraft:zombie_pigman")
|
||||
.build();
|
||||
|
||||
DROWNED = EntityDefinition.inherited(ZOMBIE.factory(), ZOMBIE)
|
||||
.type(EntityType.DROWNED)
|
||||
.bedrockId(110)
|
||||
.height(1.95f).width(0.6f)
|
||||
.build();
|
||||
HUSK = EntityDefinition.inherited(ZOMBIE.factory(), ZOMBIE)
|
||||
.type(EntityType.HUSK)
|
||||
.bedrockId(47)
|
||||
.build();
|
||||
|
||||
GUARDIAN = EntityDefinition.inherited(GuardianEntity::new, mobEntityBase)
|
||||
.type(EntityType.GUARDIAN)
|
||||
.bedrockId(49)
|
||||
.heightAndWidth(0.85f)
|
||||
.addTranslator(null) // Moving //TODO
|
||||
.addTranslator(MetadataType.INT, GuardianEntity::setGuardianTarget)
|
||||
.build();
|
||||
ELDER_GUARDIAN = EntityDefinition.inherited(ElderGuardianEntity::new, GUARDIAN)
|
||||
.type(EntityType.ELDER_GUARDIAN)
|
||||
.bedrockId(50)
|
||||
.heightAndWidth(1.9975f)
|
||||
.build();
|
||||
|
||||
SLIME = EntityDefinition.inherited(SlimeEntity::new, mobEntityBase)
|
||||
.type(EntityType.SLIME)
|
||||
.bedrockId(37)
|
||||
.heightAndWidth(0.51f)
|
||||
.addTranslator(MetadataType.INT, SlimeEntity::setScale)
|
||||
.build();
|
||||
MAGMA_CUBE = EntityDefinition.inherited(MagmaCubeEntity::new, SLIME)
|
||||
.type(EntityType.MAGMA_CUBE)
|
||||
.bedrockId(42)
|
||||
.build();
|
||||
|
||||
EntityDefinition<AbstractFishEntity> abstractFishEntityBase = EntityDefinition.inherited(AbstractFishEntity::new, mobEntityBase)
|
||||
.addTranslator(null) // From bucket
|
||||
.build();
|
||||
COD = EntityDefinition.inherited(abstractFishEntityBase.factory(), abstractFishEntityBase)
|
||||
.type(EntityType.COD)
|
||||
.bedrockId(112)
|
||||
.height(0.25f).width(0.5f)
|
||||
.build();
|
||||
PUFFERFISH = EntityDefinition.inherited(PufferFishEntity::new, abstractFishEntityBase)
|
||||
.type(EntityType.PUFFERFISH)
|
||||
.bedrockId(108)
|
||||
.heightAndWidth(0.7f)
|
||||
.addTranslator(MetadataType.INT, PufferFishEntity::setPufferfishSize)
|
||||
.build();
|
||||
SALMON = EntityDefinition.inherited(abstractFishEntityBase.factory(), abstractFishEntityBase)
|
||||
.type(EntityType.SALMON)
|
||||
.bedrockId(109)
|
||||
.height(0.5f).width(0.7f)
|
||||
.build();
|
||||
TROPICAL_FISH = EntityDefinition.inherited(TropicalFishEntity::new, abstractFishEntityBase)
|
||||
.type(EntityType.TROPICAL_FISH)
|
||||
.bedrockId(111)
|
||||
.heightAndWidth(0.6f)
|
||||
.identifier("minecraft:tropicalfish")
|
||||
.build();
|
||||
|
||||
EntityDefinition<BasePiglinEntity> abstractPiglinEntityBase = EntityDefinition.inherited(BasePiglinEntity::new, mobEntityBase)
|
||||
.addTranslator(MetadataType.BOOLEAN, BasePiglinEntity::setImmuneToZombification)
|
||||
.build();
|
||||
PIGLIN = EntityDefinition.inherited(PiglinEntity::new, abstractPiglinEntityBase)
|
||||
.type(EntityType.PIGLIN)
|
||||
.bedrockId(123)
|
||||
.height(1.95f).width(0.6f)
|
||||
.addTranslator(MetadataType.BOOLEAN, PiglinEntity::setBaby)
|
||||
.addTranslator(MetadataType.BOOLEAN, PiglinEntity::setChargingCrossbow)
|
||||
.addTranslator(MetadataType.BOOLEAN, PiglinEntity::setDancing)
|
||||
.build();
|
||||
PIGLIN_BRUTE = EntityDefinition.inherited(abstractPiglinEntityBase.factory(), abstractPiglinEntityBase)
|
||||
.type(EntityType.PIGLIN_BRUTE)
|
||||
.bedrockId(127)
|
||||
.height(1.95f).width(0.6f)
|
||||
.build();
|
||||
|
||||
GLOW_SQUID = EntityDefinition.inherited(GlowSquidEntity::new, SQUID)
|
||||
.type(EntityType.GLOW_SQUID)
|
||||
.addTranslator(null) // Set dark ticks remaining, possible TODO
|
||||
.build();
|
||||
|
||||
EntityDefinition<RaidParticipantEntity> raidParticipantEntityBase = EntityDefinition.inherited(RaidParticipantEntity::new, mobEntityBase)
|
||||
.addTranslator(null) // Celebrating //TODO
|
||||
.build();
|
||||
EntityDefinition<SpellcasterIllagerEntity> spellcasterEntityBase = EntityDefinition.inherited(SpellcasterIllagerEntity::new, raidParticipantEntityBase)
|
||||
.addTranslator(MetadataType.BYTE, SpellcasterIllagerEntity::setSpellType)
|
||||
.build();
|
||||
EVOKER = EntityDefinition.inherited(spellcasterEntityBase.factory(), spellcasterEntityBase)
|
||||
.type(EntityType.EVOKER)
|
||||
.bedrockId(104)
|
||||
.height(1.95f).width(0.6f)
|
||||
.identifier("minecraft:evocation_illager")
|
||||
.build();
|
||||
ILLUSIONER = EntityDefinition.inherited(spellcasterEntityBase.factory(), spellcasterEntityBase)
|
||||
.type(EntityType.ILLUSIONER)
|
||||
.bedrockId(104)
|
||||
.height(1.95f).width(0.6f)
|
||||
.identifier("minecraft:evocation_illager")
|
||||
.build();
|
||||
PILLAGER = EntityDefinition.inherited(PillagerEntity::new, raidParticipantEntityBase)
|
||||
.type(EntityType.PILLAGER)
|
||||
.bedrockId(114)
|
||||
.height(1.8f).width(0.6f)
|
||||
.offset(1.62f)
|
||||
.addTranslator(null) // Charging; doesn't have an equivalent on Bedrock //TODO check
|
||||
.build();
|
||||
RAVAGER = EntityDefinition.inherited(raidParticipantEntityBase.factory(), raidParticipantEntityBase)
|
||||
.type(EntityType.RAVAGER)
|
||||
.bedrockId(59)
|
||||
.height(1.9f).width(1.2f)
|
||||
.build();
|
||||
VINDICATOR = EntityDefinition.inherited(VindicatorEntity::new, raidParticipantEntityBase)
|
||||
.type(EntityType.VINDICATOR)
|
||||
.bedrockId(57)
|
||||
.height(1.8f).width(0.6f)
|
||||
.offset(1.62f)
|
||||
.build();
|
||||
WITCH = EntityDefinition.inherited(raidParticipantEntityBase.factory(), raidParticipantEntityBase)
|
||||
.type(EntityType.WITCH)
|
||||
.bedrockId(45)
|
||||
.height(1.8f).width(0.6f)
|
||||
.offset(1.62f)
|
||||
.build();
|
||||
}
|
||||
|
||||
EntityDefinition<AgeableEntity> ageableEntityBase = EntityDefinition.inherited(AgeableEntity::new, mobEntityBase)
|
||||
.addTranslator(MetadataType.BOOLEAN, AgeableEntity::setBaby)
|
||||
.build();
|
||||
|
||||
// Extends ageable
|
||||
{
|
||||
AXOLOTL = EntityDefinition.inherited(AxolotlEntity::new, ageableEntityBase)
|
||||
.type(EntityType.AXOLOTL)
|
||||
.height(0.42f).width(0.7f)
|
||||
.addTranslator(MetadataType.INT, AxolotlEntity::setVariant)
|
||||
.addTranslator(MetadataType.BOOLEAN, AxolotlEntity::setPlayingDead)
|
||||
.build();
|
||||
BEE = EntityDefinition.inherited(BeeEntity::new, ageableEntityBase)
|
||||
.type(EntityType.BEE)
|
||||
.bedrockId(122)
|
||||
.heightAndWidth(0.6f)
|
||||
.addTranslator(MetadataType.BYTE, BeeEntity::setBeeFlags)
|
||||
.addTranslator(MetadataType.INT, BeeEntity::setAngerTime)
|
||||
.build();
|
||||
CHICKEN = EntityDefinition.inherited(ChickenEntity::new, ageableEntityBase)
|
||||
.type(EntityType.CHICKEN)
|
||||
.bedrockId(10)
|
||||
.height(0.7f).width(0.4f)
|
||||
.build();
|
||||
COW = EntityDefinition.inherited(AnimalEntity::new, ageableEntityBase)
|
||||
.type(EntityType.COW)
|
||||
.bedrockId(11)
|
||||
.height(1.4f).width(0.9f)
|
||||
.build();
|
||||
FOX = EntityDefinition.inherited(FoxEntity::new, ageableEntityBase)
|
||||
.type(EntityType.FOX)
|
||||
.bedrockId(121)
|
||||
.height(0.5f).width(1.25f)
|
||||
.addTranslator(MetadataType.INT, FoxEntity::setFoxVariant)
|
||||
.addTranslator(MetadataType.BYTE, FoxEntity::setFoxFlags)
|
||||
.build();
|
||||
HOGLIN = EntityDefinition.inherited(HoglinEntity::new, ageableEntityBase)
|
||||
.type(EntityType.HOGLIN)
|
||||
.bedrockId(124)
|
||||
.height(1.4f).width(1.3965f)
|
||||
.addTranslator(MetadataType.BOOLEAN, HoglinEntity::setImmuneToZombification)
|
||||
.build();
|
||||
GOAT = EntityDefinition.inherited(GoatEntity::new, ageableEntityBase)
|
||||
.type(EntityType.GOAT)
|
||||
.height(1.3f).width(0.9f)
|
||||
.addTranslator(MetadataType.BOOLEAN, GoatEntity::setScreamer)
|
||||
.build();
|
||||
MOOSHROOM = EntityDefinition.inherited(MooshroomEntity::new, ageableEntityBase) // TODO remove class
|
||||
.type(EntityType.MOOSHROOM)
|
||||
.bedrockId(16)
|
||||
.height(1.4f).width(0.9f)
|
||||
.<String>addTranslator(MetadataType.STRING, (entity, entityMetadata) -> entity.getDirtyMetadata().put(EntityData.VARIANT, entityMetadata.getValue().equals("brown") ? 1 : 0))
|
||||
.build();
|
||||
OCELOT = EntityDefinition.inherited(OcelotEntity::new, ageableEntityBase)
|
||||
.type(EntityType.OCELOT)
|
||||
.bedrockId(22)
|
||||
.height(0.35f).width(0.3f)
|
||||
.<Boolean>addTranslator(MetadataType.BOOLEAN, (ocelotEntity, entityMetadata) -> ocelotEntity.setFlag(EntityFlag.TRUSTING, ((BooleanEntityMetadata) entityMetadata).getPrimitiveValue()))
|
||||
.build();
|
||||
PANDA = EntityDefinition.inherited(PandaEntity::new, ageableEntityBase)
|
||||
.type(EntityType.PANDA)
|
||||
.bedrockId(113)
|
||||
.height(1.25f).width(1.125f)
|
||||
.addTranslator(null) // Unhappy counter
|
||||
.addTranslator(null) // Sneeze counter
|
||||
.addTranslator(MetadataType.INT, PandaEntity::setEatingCounter)
|
||||
.addTranslator(MetadataType.BYTE, PandaEntity::setMainGene)
|
||||
.addTranslator(MetadataType.BYTE, PandaEntity::setHiddenGene)
|
||||
.addTranslator(MetadataType.BYTE, PandaEntity::setPandaFlags)
|
||||
.build();
|
||||
PIG = EntityDefinition.inherited(PigEntity::new, ageableEntityBase)
|
||||
.type(EntityType.PIG)
|
||||
.bedrockId(12)
|
||||
.heightAndWidth(0.9f)
|
||||
.<Boolean>addTranslator(MetadataType.BOOLEAN, (pigEntity, entityMetadata) -> pigEntity.setFlag(EntityFlag.SADDLED, ((BooleanEntityMetadata) entityMetadata).getPrimitiveValue()))
|
||||
.addTranslator(null) // Boost time
|
||||
.build();
|
||||
POLAR_BEAR = EntityDefinition.inherited(PolarBearEntity::new, ageableEntityBase)
|
||||
.type(EntityType.POLAR_BEAR)
|
||||
.bedrockId(28)
|
||||
.height(1.4f).width(1.3f)
|
||||
.<Boolean>addTranslator(MetadataType.BOOLEAN, (entity, entityMetadata) -> entity.setFlag(EntityFlag.STANDING, ((BooleanEntityMetadata) entityMetadata).getPrimitiveValue()))
|
||||
.build();
|
||||
RABBIT = EntityDefinition.inherited(RabbitEntity::new, ageableEntityBase)
|
||||
.type(EntityType.RABBIT)
|
||||
.bedrockId(18)
|
||||
.height(0.5f).width(0.4f)
|
||||
.addTranslator(MetadataType.INT, RabbitEntity::setRabbitVariant)
|
||||
.build();
|
||||
SHEEP = EntityDefinition.inherited(SheepEntity::new, ageableEntityBase)
|
||||
.type(EntityType.SHEEP)
|
||||
.bedrockId(13)
|
||||
.heightAndWidth(0.9f)
|
||||
.addTranslator(MetadataType.BYTE, SheepEntity::setSheepFlags)
|
||||
.build();
|
||||
STRIDER = EntityDefinition.inherited(StriderEntity::new, ageableEntityBase)
|
||||
.type(EntityType.STRIDER)
|
||||
.bedrockId(125)
|
||||
.height(1.7f).width(0.9f)
|
||||
.addTranslator(null) // Boost time
|
||||
.addTranslator(MetadataType.BOOLEAN, StriderEntity::setCold)
|
||||
.addTranslator(MetadataType.BOOLEAN, StriderEntity::setSaddled)
|
||||
.build();
|
||||
TURTLE = EntityDefinition.inherited(TurtleEntity::new, ageableEntityBase)
|
||||
.type(EntityType.TURTLE)
|
||||
.bedrockId(74)
|
||||
.height(0.4f).width(1.2f)
|
||||
.addTranslator(MetadataType.BOOLEAN, TurtleEntity::setPregnant)
|
||||
.addTranslator(MetadataType.BOOLEAN, TurtleEntity::setLayingEgg)
|
||||
.build();
|
||||
|
||||
EntityDefinition<AbstractMerchantEntity> abstractVillagerEntityBase = EntityDefinition.inherited(AbstractMerchantEntity::new, ageableEntityBase)
|
||||
.addTranslator(null) // Unhappy ticks
|
||||
.build();
|
||||
VILLAGER = EntityDefinition.inherited(VillagerEntity::new, abstractVillagerEntityBase)
|
||||
.type(EntityType.VILLAGER)
|
||||
.bedrockId(15)
|
||||
.height(1.8f).width(0.6f)
|
||||
.offset(1.62f)
|
||||
.identifier("minecraft:villager_v2")
|
||||
.addTranslator(MetadataType.VILLAGER_DATA, VillagerEntity::setVillagerData)
|
||||
.build();
|
||||
WANDERING_TRADER = EntityDefinition.inherited(abstractVillagerEntityBase.factory(), abstractVillagerEntityBase)
|
||||
.type(EntityType.WANDERING_TRADER)
|
||||
.bedrockId(118)
|
||||
.height(1.8f).width(0.6f)
|
||||
.offset(1.62f)
|
||||
.build();
|
||||
}
|
||||
|
||||
// Horses
|
||||
{
|
||||
EntityDefinition<AbstractHorseEntity> abstractHorseEntityBase = EntityDefinition.inherited(AbstractHorseEntity::new, ageableEntityBase)
|
||||
.addTranslator(MetadataType.BYTE, AbstractHorseEntity::setHorseFlags)
|
||||
.addTranslator(null) // UUID of owner
|
||||
.build();
|
||||
HORSE = EntityDefinition.inherited(HorseEntity::new, abstractHorseEntityBase)
|
||||
.type(EntityType.HORSE)
|
||||
.bedrockId(23)
|
||||
.height(1.6f).width(1.3965f)
|
||||
.addTranslator(MetadataType.BYTE, HorseEntity::setHorseVariant)
|
||||
.build();
|
||||
SKELETON_HORSE = EntityDefinition.inherited(abstractHorseEntityBase.factory(), abstractHorseEntityBase)
|
||||
.type(EntityType.SKELETON_HORSE)
|
||||
.bedrockId(26)
|
||||
.height(1.6f).width(1.3965f)
|
||||
.build();
|
||||
ZOMBIE_HORSE = EntityDefinition.inherited(abstractHorseEntityBase.factory(), abstractHorseEntityBase)
|
||||
.type(EntityType.ZOMBIE_HORSE)
|
||||
.bedrockId(27)
|
||||
.height(1.6f).width(1.3965f)
|
||||
.build();
|
||||
EntityDefinition<ChestedHorseEntity> chestedHorseEntityBase = EntityDefinition.inherited(ChestedHorseEntity::new, abstractHorseEntityBase)
|
||||
.<Boolean>addTranslator(MetadataType.BOOLEAN, (horseEntity, entityMetadata) -> horseEntity.setFlag(EntityFlag.CHESTED, ((BooleanEntityMetadata) entityMetadata).getPrimitiveValue()))
|
||||
.build();
|
||||
DONKEY = EntityDefinition.inherited(chestedHorseEntityBase.factory(), chestedHorseEntityBase)
|
||||
.type(EntityType.DONKEY)
|
||||
.bedrockId(24)
|
||||
.height(1.6f).width(1.3965f)
|
||||
.build();
|
||||
MULE = EntityDefinition.inherited(chestedHorseEntityBase.factory(), chestedHorseEntityBase)
|
||||
.type(EntityType.MULE)
|
||||
.bedrockId(25)
|
||||
.height(1.6f).width(1.3965f)
|
||||
.build();
|
||||
LLAMA = EntityDefinition.inherited(LlamaEntity::new, chestedHorseEntityBase)
|
||||
.type(EntityType.LLAMA)
|
||||
.bedrockId(29)
|
||||
.height(1.87f).width(0.9f)
|
||||
.<Integer>addTranslator(MetadataType.INT, (entity, entityMetadata) -> entity.getDirtyMetadata().put(EntityData.STRENGTH, entityMetadata.getValue()))
|
||||
.addTranslator(MetadataType.INT, LlamaEntity::setCarpetedColor)
|
||||
.addTranslator(MetadataType.INT, (entity, entityMetadata) -> entity.getDirtyMetadata().put(EntityData.VARIANT, entityMetadata.getValue()))
|
||||
.build();
|
||||
TRADER_LLAMA = EntityDefinition.inherited(TraderLlamaEntity::new, LLAMA)
|
||||
.type(EntityType.TRADER_LLAMA)
|
||||
.identifier("minecraft:llama")
|
||||
.build();
|
||||
}
|
||||
|
||||
EntityDefinition<TameableEntity> tameableEntityBase = EntityDefinition.inherited(TameableEntity::new, ageableEntityBase)
|
||||
.addTranslator(MetadataType.BYTE, TameableEntity::setTameableFlags)
|
||||
.addTranslator(MetadataType.OPTIONAL_UUID, TameableEntity::setOwner)
|
||||
.build();
|
||||
CAT = EntityDefinition.inherited(CatEntity::new, tameableEntityBase)
|
||||
.type(EntityType.CAT)
|
||||
.bedrockId(75)
|
||||
.height(0.35f).width(0.3f)
|
||||
.addTranslator(MetadataType.INT, CatEntity::setCatVariant)
|
||||
.addTranslator(MetadataType.BOOLEAN, CatEntity::setResting)
|
||||
.addTranslator(null) // "resting state one" //TODO
|
||||
.addTranslator(MetadataType.INT, CatEntity::setCollarColor)
|
||||
.build();
|
||||
PARROT = EntityDefinition.inherited(ParrotEntity::new, tameableEntityBase)
|
||||
.type(EntityType.PARROT)
|
||||
.bedrockId(30)
|
||||
.height(0.9f).width(0.5f)
|
||||
.addTranslator(MetadataType.INT, (parrotEntity, entityMetadata) -> parrotEntity.getDirtyMetadata().put(EntityData.VARIANT, entityMetadata.getValue())) // Parrot color
|
||||
.build();
|
||||
WOLF = EntityDefinition.inherited(WolfEntity::new, tameableEntityBase)
|
||||
.type(EntityType.WOLF)
|
||||
.bedrockId(14)
|
||||
.height(0.85f).width(0.6f)
|
||||
// "Begging" on wiki.vg, "Interested" in Nukkit - the tilt of the head
|
||||
.<Boolean>addTranslator(MetadataType.BOOLEAN, (wolfEntity, entityMetadata) -> wolfEntity.setFlag(EntityFlag.INTERESTED, ((BooleanEntityMetadata) entityMetadata).getPrimitiveValue()))
|
||||
.addTranslator(MetadataType.INT, WolfEntity::setCollarColor)
|
||||
.addTranslator(MetadataType.INT, WolfEntity::setWolfAngerTime)
|
||||
.build();
|
||||
|
||||
// As of 1.18 these don't track entity data at all
|
||||
ENDER_DRAGON_PART = EntityDefinition.<EnderDragonPartEntity>builder(null)
|
||||
.bedrockId(32)
|
||||
.identifier("minecraft:armor_stand") // Emulated
|
||||
.build();
|
||||
}
|
||||
|
||||
public static void init() {
|
||||
// no-op
|
||||
}
|
||||
|
||||
private EntityDefinitions() {
|
||||
}
|
||||
}
|
@ -23,29 +23,18 @@
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.connector.entity.living;
|
||||
package org.geysermc.connector.entity;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.MetadataType;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
|
||||
import org.geysermc.connector.entity.LivingEntity;
|
||||
import org.geysermc.connector.entity.type.EntityType;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
|
||||
public class InsentientEntity extends LivingEntity {
|
||||
import java.util.function.BiConsumer;
|
||||
|
||||
public InsentientEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
||||
super(entityId, geyserId, entityType, position, motion, rotation);
|
||||
}
|
||||
/**
|
||||
* Translates a given Java {@link EntityMetadata} into a similar/same construct for Bedrock
|
||||
*/
|
||||
|
||||
@Override
|
||||
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
|
||||
if (entityMetadata.getId() == 15 && entityMetadata.getType() == MetadataType.BYTE) {
|
||||
byte xd = (byte) entityMetadata.getValue();
|
||||
metadata.getFlags().setFlag(EntityFlag.NO_AI, (xd & 0x01) == 0x01);
|
||||
}
|
||||
|
||||
super.updateBedrockMetadata(entityMetadata, session);
|
||||
}
|
||||
public record EntityMetadataTranslator<E extends Entity, T>(
|
||||
MetadataType acceptedType,
|
||||
BiConsumer<E, EntityMetadata<T>> translateFunction) {
|
||||
}
|
@ -27,22 +27,21 @@ package org.geysermc.connector.entity;
|
||||
|
||||
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.network.session.GeyserSession;
|
||||
|
||||
public class ExpOrbEntity extends Entity {
|
||||
|
||||
private final int amount;
|
||||
|
||||
public ExpOrbEntity(int amount, long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
||||
super(entityId, geyserId, entityType, position, motion, rotation);
|
||||
public ExpOrbEntity(GeyserSession session, int amount, long entityId, long geyserId, Vector3f position) {
|
||||
super(session, entityId, geyserId, null, EntityDefinitions.EXPERIENCE_ORB, position, Vector3f.ZERO, 0, 0, 0);
|
||||
|
||||
this.amount = amount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void spawnEntity(GeyserSession session) {
|
||||
this.metadata.put(EntityData.EXPERIENCE_VALUE, amount);
|
||||
super.spawnEntity(session);
|
||||
protected void initializeMetadata() {
|
||||
super.initializeMetadata();
|
||||
this.dirtyMetadata.put(EntityData.EXPERIENCE_VALUE, amount);
|
||||
}
|
||||
}
|
||||
|
@ -26,31 +26,32 @@
|
||||
package org.geysermc.connector.entity;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanEntityMetadata;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
|
||||
import org.geysermc.connector.entity.type.EntityType;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class FallingBlockEntity extends Entity {
|
||||
private final int javaId;
|
||||
|
||||
public FallingBlockEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation, int javaId) {
|
||||
super(entityId, geyserId, entityType, position, motion, rotation);
|
||||
public FallingBlockEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, Vector3f position, Vector3f motion, float yaw, float pitch, int javaId) {
|
||||
super(session, entityId, geyserId, uuid, EntityDefinitions.FALLING_BLOCK, position, motion, yaw, pitch, 0f);
|
||||
this.javaId = javaId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void spawnEntity(GeyserSession session) {
|
||||
this.metadata.put(EntityData.VARIANT, session.getBlockMappings().getBedrockBlockId(javaId));
|
||||
super.spawnEntity(session);
|
||||
protected void initializeMetadata() {
|
||||
super.initializeMetadata();
|
||||
this.dirtyMetadata.put(EntityData.VARIANT, session.getBlockMappings().getBedrockBlockId(javaId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
|
||||
public void setGravity(EntityMetadata<Boolean> entityMetadata) {
|
||||
super.setGravity(entityMetadata);
|
||||
// Set the NO_AI flag based on the no gravity flag to prevent movement
|
||||
if (entityMetadata.getId() == 5) {
|
||||
this.metadata.getFlags().setFlag(EntityFlag.NO_AI, (boolean) entityMetadata.getValue());
|
||||
}
|
||||
setFlag(EntityFlag.NO_AI, ((BooleanEntityMetadata) entityMetadata).getPrimitiveValue());
|
||||
}
|
||||
}
|
||||
|
@ -37,7 +37,6 @@ import com.nukkitx.nbt.NbtType;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
|
||||
import com.nukkitx.protocol.bedrock.packet.SetEntityMotionPacket;
|
||||
import org.geysermc.connector.entity.player.PlayerEntity;
|
||||
import org.geysermc.connector.entity.type.EntityType;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
import org.geysermc.connector.utils.FireworkColor;
|
||||
import org.geysermc.connector.utils.MathUtils;
|
||||
@ -46,17 +45,16 @@ import org.geysermc.floodgate.util.DeviceOs;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.OptionalInt;
|
||||
import java.util.UUID;
|
||||
|
||||
public class FireworkEntity extends Entity {
|
||||
|
||||
public FireworkEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
||||
super(entityId, geyserId, entityType, position, motion, rotation);
|
||||
public FireworkEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
|
||||
if (entityMetadata.getId() == 8) {
|
||||
ItemStack item = (ItemStack) entityMetadata.getValue();
|
||||
public void setFireworkItem(EntityMetadata<ItemStack> entityMetadata) {
|
||||
ItemStack item = entityMetadata.getValue();
|
||||
if (item == null) {
|
||||
return;
|
||||
}
|
||||
@ -134,16 +132,18 @@ public class FireworkEntity extends Entity {
|
||||
|
||||
NbtMapBuilder builder = NbtMap.builder();
|
||||
builder.put("Fireworks", fireworksBuilder.build());
|
||||
metadata.put(EntityData.DISPLAY_ITEM, builder.build());
|
||||
} else if (entityMetadata.getId() == 9) {
|
||||
OptionalInt optional = (OptionalInt) entityMetadata.getValue();
|
||||
dirtyMetadata.put(EntityData.DISPLAY_ITEM, builder.build());
|
||||
}
|
||||
|
||||
public void setPlayerGliding(EntityMetadata<OptionalInt> entityMetadata) {
|
||||
OptionalInt optional = entityMetadata.getValue();
|
||||
// Checks if the firework has an entity ID (used when a player is gliding)
|
||||
// and checks to make sure the player that is gliding is the one getting sent the packet
|
||||
// or else every player near the gliding player will boost too.
|
||||
if (optional.isPresent() && optional.getAsInt() == session.getPlayerEntity().getEntityId()) {
|
||||
PlayerEntity entity = session.getPlayerEntity();
|
||||
float yaw = entity.getRotation().getX();
|
||||
float pitch = entity.getRotation().getY();
|
||||
float yaw = entity.getYaw();
|
||||
float pitch = entity.getPitch();
|
||||
// Uses math from NukkitX
|
||||
entity.setMotion(Vector3f.from(
|
||||
-Math.sin(Math.toRadians(yaw)) * Math.cos(Math.toRadians(pitch)) * 2,
|
||||
@ -157,7 +157,4 @@ public class FireworkEntity extends Entity {
|
||||
session.sendUpstreamPacket(entityMotionPacket);
|
||||
}
|
||||
}
|
||||
|
||||
super.updateBedrockMetadata(entityMetadata, session);
|
||||
}
|
||||
}
|
||||
|
@ -26,12 +26,12 @@
|
||||
package org.geysermc.connector.entity;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
|
||||
import com.nukkitx.protocol.bedrock.packet.PlaySoundPacket;
|
||||
import org.geysermc.connector.entity.player.PlayerEntity;
|
||||
import org.geysermc.connector.entity.type.EntityType;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
import org.geysermc.connector.network.translators.collision.BoundingBox;
|
||||
import org.geysermc.connector.network.translators.collision.translators.BlockCollision;
|
||||
@ -40,6 +40,7 @@ import org.geysermc.connector.registry.BlockRegistries;
|
||||
import org.geysermc.connector.utils.BlockPositionIterator;
|
||||
import org.geysermc.connector.utils.BlockUtils;
|
||||
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
public class FishingHookEntity extends ThrowableEntity {
|
||||
@ -50,41 +51,44 @@ public class FishingHookEntity extends ThrowableEntity {
|
||||
|
||||
private boolean inWater = false;
|
||||
|
||||
public FishingHookEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation, PlayerEntity owner) {
|
||||
super(entityId, geyserId, entityType, position, motion, rotation);
|
||||
public FishingHookEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, Vector3f position, Vector3f motion, float yaw, float pitch, PlayerEntity owner) {
|
||||
super(session, entityId, geyserId, uuid, EntityDefinitions.FISHING_BOBBER, position, motion, yaw, pitch, 0f);
|
||||
|
||||
this.boundingBox = new BoundingBox(0.125, 0.125, 0.125, 0.25, 0.25, 0.25);
|
||||
|
||||
// In Java, the splash sound depends on the entity's velocity, but in Bedrock the volume doesn't change.
|
||||
// This splash can be confused with the sound from catching a fish. This silences the splash from Bedrock,
|
||||
// so that it can be handled by moveAbsoluteImmediate.
|
||||
this.metadata.putFloat(EntityData.BOUNDING_BOX_HEIGHT, 128);
|
||||
this.dirtyMetadata.putFloat(EntityData.BOUNDING_BOX_HEIGHT, 128);
|
||||
|
||||
this.metadata.put(EntityData.OWNER_EID, owner.getGeyserId());
|
||||
this.dirtyMetadata.put(EntityData.OWNER_EID, owner.getGeyserId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
|
||||
if (entityMetadata.getId() == 8) { // Hooked entity
|
||||
int hookedEntityId = (int) entityMetadata.getValue() - 1;
|
||||
Entity entity = session.getEntityCache().getEntityByJavaId(hookedEntityId);
|
||||
if (entity == null && session.getPlayerEntity().getEntityId() == hookedEntityId) {
|
||||
public void spawnEntity() {
|
||||
|
||||
super.spawnEntity();
|
||||
}
|
||||
|
||||
public void setHookedEntity(EntityMetadata<Integer> entityMetadata) {
|
||||
int hookedEntityId = ((IntEntityMetadata) entityMetadata).getPrimitiveValue() - 1;
|
||||
Entity entity;
|
||||
if (session.getPlayerEntity().getEntityId() == hookedEntityId) {
|
||||
entity = session.getPlayerEntity();
|
||||
} else {
|
||||
entity = session.getEntityCache().getEntityByJavaId(hookedEntityId);
|
||||
}
|
||||
|
||||
if (entity != null) {
|
||||
metadata.put(EntityData.TARGET_EID, entity.getGeyserId());
|
||||
dirtyMetadata.put(EntityData.TARGET_EID, entity.getGeyserId());
|
||||
hooked = true;
|
||||
} else {
|
||||
hooked = false;
|
||||
}
|
||||
}
|
||||
|
||||
super.updateBedrockMetadata(entityMetadata, session);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void moveAbsoluteImmediate(GeyserSession session, Vector3f position, Vector3f rotation, boolean isOnGround, boolean teleported) {
|
||||
protected void moveAbsoluteImmediate(Vector3f position, float yaw, float pitch, float headYaw, boolean isOnGround, boolean teleported) {
|
||||
boundingBox.setMiddleX(position.getX());
|
||||
boundingBox.setMiddleY(position.getY() + boundingBox.getSizeY() / 2);
|
||||
boundingBox.setMiddleZ(position.getZ());
|
||||
@ -123,14 +127,14 @@ public class FishingHookEntity extends ThrowableEntity {
|
||||
inWater = touchingWater;
|
||||
|
||||
if (!collided) {
|
||||
super.moveAbsoluteImmediate(session, position, rotation, isOnGround, teleported);
|
||||
super.moveAbsoluteImmediate(position, yaw, pitch, headYaw, isOnGround, teleported);
|
||||
} else {
|
||||
super.moveAbsoluteImmediate(session, this.position, rotation, true, true);
|
||||
super.moveAbsoluteImmediate(this.position, yaw, pitch, headYaw, true, true);
|
||||
}
|
||||
}
|
||||
|
||||
private void sendSplashSound(GeyserSession session) {
|
||||
if (!metadata.getFlags().getFlag(EntityFlag.SILENT)) {
|
||||
if (!getFlag(EntityFlag.SILENT)) {
|
||||
float volume = (float) (0.2f * Math.sqrt(0.2 * (motion.getX() * motion.getX() + motion.getZ() * motion.getZ()) + motion.getY() * motion.getY()));
|
||||
if (volume > 1) {
|
||||
volume = 1;
|
||||
@ -145,39 +149,38 @@ public class FishingHookEntity extends ThrowableEntity {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick(GeyserSession session) {
|
||||
if (hooked || !isInAir(session) && !isInWater(session) || isOnGround()) {
|
||||
public void tick() {
|
||||
if (hooked || !isInAir() && !isInWater() || isOnGround()) {
|
||||
motion = Vector3f.ZERO;
|
||||
return;
|
||||
}
|
||||
float gravity = getGravity(session);
|
||||
float gravity = getGravity();
|
||||
motion = motion.down(gravity);
|
||||
|
||||
moveAbsoluteImmediate(session, position.add(motion), rotation, onGround, false);
|
||||
moveAbsoluteImmediate(position.add(motion), yaw, pitch, headYaw, onGround, false);
|
||||
|
||||
float drag = getDrag(session);
|
||||
float drag = getDrag();
|
||||
motion = motion.mul(drag);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected float getGravity(GeyserSession session) {
|
||||
if (!isInWater(session) && !onGround) {
|
||||
protected float getGravity() {
|
||||
if (!isInWater() && !onGround) {
|
||||
return 0.03f;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param session the session of the Bedrock client.
|
||||
* @return true if this entity is currently in air.
|
||||
*/
|
||||
protected boolean isInAir(GeyserSession session) {
|
||||
protected boolean isInAir() {
|
||||
int block = session.getConnector().getWorldManager().getBlockAt(session, position.toInt());
|
||||
return block == BlockStateValues.JAVA_AIR_ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected float getDrag(GeyserSession session) {
|
||||
protected float getDrag() {
|
||||
return 0.92f;
|
||||
}
|
||||
}
|
||||
|
@ -26,33 +26,29 @@
|
||||
package org.geysermc.connector.entity;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanEntityMetadata;
|
||||
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.network.session.GeyserSession;
|
||||
import org.geysermc.connector.network.translators.world.block.BlockStateValues;
|
||||
|
||||
public class FurnaceMinecartEntity extends DefaultBlockMinecartEntity {
|
||||
import java.util.UUID;
|
||||
|
||||
public class FurnaceMinecartEntity extends DefaultBlockMinecartEntity {
|
||||
private boolean hasFuel = false;
|
||||
|
||||
public FurnaceMinecartEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
||||
super(entityId, geyserId, entityType, position, motion, rotation);
|
||||
public FurnaceMinecartEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
|
||||
}
|
||||
|
||||
public void setHasFuel(EntityMetadata<Boolean> entityMetadata) {
|
||||
hasFuel = ((BooleanEntityMetadata) entityMetadata).getPrimitiveValue();
|
||||
updateDefaultBlockMetadata();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
|
||||
if (entityMetadata.getId() == 14 && !showCustomBlock) {
|
||||
hasFuel = (boolean) entityMetadata.getValue();
|
||||
updateDefaultBlockMetadata(session);
|
||||
}
|
||||
|
||||
super.updateBedrockMetadata(entityMetadata, session);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateDefaultBlockMetadata(GeyserSession session) {
|
||||
metadata.put(EntityData.DISPLAY_ITEM, session.getBlockMappings().getBedrockBlockId(hasFuel ? BlockStateValues.JAVA_FURNACE_LIT_ID : BlockStateValues.JAVA_FURNACE_ID));
|
||||
metadata.put(EntityData.DISPLAY_OFFSET, 6);
|
||||
public void updateDefaultBlockMetadata() {
|
||||
dirtyMetadata.put(EntityData.DISPLAY_ITEM, session.getBlockMappings().getBedrockBlockId(hasFuel ? BlockStateValues.JAVA_FURNACE_LIT_ID : BlockStateValues.JAVA_FURNACE_ID));
|
||||
dirtyMetadata.put(EntityData.DISPLAY_OFFSET, 6);
|
||||
}
|
||||
}
|
||||
|
@ -34,23 +34,24 @@ import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
|
||||
import com.nukkitx.protocol.bedrock.data.inventory.ItemData;
|
||||
import com.nukkitx.protocol.bedrock.packet.AddItemEntityPacket;
|
||||
import com.nukkitx.protocol.bedrock.packet.EntityEventPacket;
|
||||
import org.geysermc.connector.entity.type.EntityType;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
import org.geysermc.connector.network.translators.item.ItemTranslator;
|
||||
import org.geysermc.connector.network.translators.world.block.BlockStateValues;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class ItemEntity extends ThrowableEntity {
|
||||
|
||||
protected ItemData item;
|
||||
|
||||
private int waterLevel = -1;
|
||||
|
||||
public ItemEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
||||
super(entityId, geyserId, entityType, position, motion, rotation);
|
||||
public ItemEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void spawnEntity(GeyserSession session) {
|
||||
public void spawnEntity() {
|
||||
if (item == null) {
|
||||
return;
|
||||
}
|
||||
@ -58,69 +59,33 @@ public class ItemEntity extends ThrowableEntity {
|
||||
AddItemEntityPacket itemPacket = new AddItemEntityPacket();
|
||||
itemPacket.setRuntimeEntityId(geyserId);
|
||||
itemPacket.setUniqueEntityId(geyserId);
|
||||
itemPacket.setPosition(position.add(0d, this.entityType.getOffset(), 0d));
|
||||
itemPacket.setPosition(position.add(0d, this.definition.offset(), 0d));
|
||||
itemPacket.setMotion(motion);
|
||||
itemPacket.setFromFishing(false);
|
||||
itemPacket.setItemInHand(item);
|
||||
itemPacket.getMetadata().putAll(metadata);
|
||||
itemPacket.getMetadata().putAll(dirtyMetadata);
|
||||
session.sendUpstreamPacket(itemPacket);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick(GeyserSession session) {
|
||||
if (isInWater(session)) {
|
||||
public void tick() {
|
||||
if (isInWater()) {
|
||||
return;
|
||||
}
|
||||
if (!onGround || (motion.getX() * motion.getX() + motion.getZ() * motion.getZ()) > 0.00001) {
|
||||
float gravity = getGravity(session);
|
||||
float gravity = getGravity();
|
||||
motion = motion.down(gravity);
|
||||
moveAbsoluteImmediate(session, position.add(motion), rotation, onGround, false);
|
||||
float drag = getDrag(session);
|
||||
moveAbsoluteImmediate(position.add(motion), yaw, pitch, headYaw, onGround, false);
|
||||
float drag = getDrag();
|
||||
motion = motion.mul(drag, 0.98f, drag);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void moveAbsoluteImmediate(GeyserSession session, Vector3f position, Vector3f rotation, boolean isOnGround, boolean teleported) {
|
||||
float offset = entityType.getOffset();
|
||||
if (waterLevel == 0) { // Item is in a full block of water
|
||||
// Move the item entity down so it doesn't float above the water
|
||||
offset = -entityType.getOffset();
|
||||
}
|
||||
super.moveAbsoluteImmediate(session, position.add(0, offset, 0), Vector3f.ZERO, isOnGround, teleported);
|
||||
this.position = position;
|
||||
|
||||
int block = session.getConnector().getWorldManager().getBlockAt(session, position.toInt());
|
||||
waterLevel = BlockStateValues.getWaterLevel(block);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected float getGravity(GeyserSession session) {
|
||||
if (metadata.getFlags().getFlag(EntityFlag.HAS_GRAVITY) && !onGround && !isInWater(session)) {
|
||||
// Gravity can change if the item is in water/lava, but
|
||||
// the server calculates the motion & position for us
|
||||
return 0.04f;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected float getDrag(GeyserSession session) {
|
||||
if (onGround) {
|
||||
Vector3i groundBlockPos = position.toInt().down(1);
|
||||
int blockState = session.getConnector().getWorldManager().getBlockAt(session, groundBlockPos);
|
||||
return BlockStateValues.getSlipperiness(blockState) * 0.98f;
|
||||
}
|
||||
return 0.98f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
|
||||
if (entityMetadata.getId() == 8) {
|
||||
ItemData item = ItemTranslator.translateToBedrock(session, (ItemStack) entityMetadata.getValue());
|
||||
public void setItem(EntityMetadata<ItemStack> entityMetadata) {
|
||||
ItemData item = ItemTranslator.translateToBedrock(session, entityMetadata.getValue());
|
||||
if (this.item == null) {
|
||||
this.item = item;
|
||||
spawnEntity(session);
|
||||
spawnEntity();
|
||||
} else if (item.equals(this.item, false, true, true)) {
|
||||
// Don't bother respawning the entity if items are equal
|
||||
if (this.item.getCount() != item.getCount()) {
|
||||
@ -134,16 +99,47 @@ public class ItemEntity extends ThrowableEntity {
|
||||
}
|
||||
} else {
|
||||
this.item = item;
|
||||
despawnEntity(session);
|
||||
spawnEntity(session);
|
||||
despawnEntity();
|
||||
spawnEntity();
|
||||
}
|
||||
}
|
||||
|
||||
super.updateBedrockMetadata(entityMetadata, session);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isInWater(GeyserSession session) {
|
||||
protected void moveAbsoluteImmediate(Vector3f position, float yaw, float pitch, float headYaw, boolean isOnGround, boolean teleported) {
|
||||
float offset = definition.offset();
|
||||
if (waterLevel == 0) { // Item is in a full block of water
|
||||
// Move the item entity down so it doesn't float above the water
|
||||
offset = -definition.offset();
|
||||
}
|
||||
super.moveAbsoluteImmediate(position.add(0, offset, 0), 0, 0, 0, isOnGround, teleported);
|
||||
this.position = position;
|
||||
|
||||
int block = session.getConnector().getWorldManager().getBlockAt(session, position.toInt());
|
||||
waterLevel = BlockStateValues.getWaterLevel(block);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected float getGravity() {
|
||||
if (getFlag(EntityFlag.HAS_GRAVITY) && !onGround && !isInWater()) {
|
||||
// Gravity can change if the item is in water/lava, but
|
||||
// the server calculates the motion & position for us
|
||||
return 0.04f;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected float getDrag() {
|
||||
if (onGround) {
|
||||
Vector3i groundBlockPos = position.toInt().down(1);
|
||||
int blockState = session.getConnector().getWorldManager().getBlockAt(session, groundBlockPos);
|
||||
return BlockStateValues.getSlipperiness(blockState) * 0.98f;
|
||||
}
|
||||
return 0.98f;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isInWater() {
|
||||
return waterLevel != -1;
|
||||
}
|
||||
}
|
||||
|
@ -27,7 +27,9 @@ package org.geysermc.connector.entity;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.object.HangingDirection;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.object.Direction;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.type.EntityType;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.math.vector.Vector3i;
|
||||
import com.nukkitx.nbt.NbtMap;
|
||||
@ -37,29 +39,25 @@ import com.nukkitx.protocol.bedrock.packet.BlockEntityDataPacket;
|
||||
import com.nukkitx.protocol.bedrock.packet.UpdateBlockPacket;
|
||||
import com.nukkitx.protocol.bedrock.v465.Bedrock_v465;
|
||||
import lombok.Getter;
|
||||
import org.geysermc.connector.entity.type.EntityType;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
import org.geysermc.connector.network.translators.item.ItemTranslator;
|
||||
import org.geysermc.connector.registry.type.ItemMapping;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Item frames are an entity in Java but a block entity in Bedrock.
|
||||
*/
|
||||
public class ItemFrameEntity extends Entity {
|
||||
|
||||
/**
|
||||
* Used to construct the block entity tag on spawning.
|
||||
*/
|
||||
private final HangingDirection direction;
|
||||
/**
|
||||
* Used for getting the Bedrock block position.
|
||||
* Blocks deal with integers whereas entities deal with floats.
|
||||
*/
|
||||
private Vector3i bedrockPosition;
|
||||
private final Vector3i bedrockPosition;
|
||||
/**
|
||||
* Specific block 'state' we are emulating in Bedrock.
|
||||
*/
|
||||
private int bedrockRuntimeId;
|
||||
private final int bedrockRuntimeId;
|
||||
/**
|
||||
* Rotation of item in frame.
|
||||
*/
|
||||
@ -73,16 +71,16 @@ public class ItemFrameEntity extends Entity {
|
||||
*/
|
||||
@Getter
|
||||
private ItemStack heldItem = null;
|
||||
/**
|
||||
* Determines if this entity needs updated on the client end/
|
||||
*/
|
||||
private boolean changed = true;
|
||||
|
||||
public ItemFrameEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation, HangingDirection direction) {
|
||||
super(entityId, geyserId, entityType, position, motion, rotation);
|
||||
this.direction = direction;
|
||||
}
|
||||
public ItemFrameEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, Direction direction) {
|
||||
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, 0f);
|
||||
|
||||
@Override
|
||||
public void spawnEntity(GeyserSession session) {
|
||||
NbtMapBuilder blockBuilder = NbtMap.builder()
|
||||
.putString("name", this.entityType == EntityType.GLOW_ITEM_FRAME ? "minecraft:glow_frame" : "minecraft:frame")
|
||||
.putString("name", this.definition.entityType() == EntityType.GLOW_ITEM_FRAME ? "minecraft:glow_frame" : "minecraft:frame")
|
||||
.putInt("version", session.getBlockMappings().getBlockStateVersion());
|
||||
NbtMapBuilder statesBuilder = NbtMap.builder()
|
||||
.putInt("facing_direction", direction.ordinal())
|
||||
@ -96,18 +94,26 @@ public class ItemFrameEntity extends Entity {
|
||||
bedrockPosition = Vector3i.from(position.getFloorX(), position.getFloorY(), position.getFloorZ());
|
||||
|
||||
session.getItemFrameCache().put(bedrockPosition, this);
|
||||
}
|
||||
|
||||
updateBlock(session);
|
||||
@Override
|
||||
protected void initializeMetadata() {
|
||||
// lol nah don't do anything
|
||||
// This isn't a real entity for Bedrock so it isn't going to do anything
|
||||
}
|
||||
|
||||
@Override
|
||||
public void spawnEntity() {
|
||||
updateBlock();
|
||||
session.getConnector().getLogger().debug("Spawned item frame at location " + bedrockPosition + " with java id " + entityId);
|
||||
valid = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
|
||||
if (entityMetadata.getId() == 8 && entityMetadata.getValue() != null) {
|
||||
this.heldItem = (ItemStack) entityMetadata.getValue();
|
||||
public void setItemInFrame(EntityMetadata<ItemStack> entityMetadata) {
|
||||
if (entityMetadata.getValue() != null) {
|
||||
this.heldItem = entityMetadata.getValue();
|
||||
ItemData itemData = ItemTranslator.translateToBedrock(session, heldItem);
|
||||
ItemMapping mapping = session.getItemMappings().getMapping((ItemStack) entityMetadata.getValue());
|
||||
ItemMapping mapping = session.getItemMappings().getMapping(entityMetadata.getValue());
|
||||
NbtMapBuilder builder = NbtMap.builder();
|
||||
|
||||
builder.putByte("Count", (byte) itemData.getCount());
|
||||
@ -121,34 +127,30 @@ public class ItemFrameEntity extends Entity {
|
||||
tag.putFloat("ItemDropChance", 1.0f);
|
||||
tag.putFloat("ItemRotation", rotation);
|
||||
cachedTag = tag.build();
|
||||
updateBlock(session);
|
||||
}
|
||||
else if (entityMetadata.getId() == 8 && entityMetadata.getValue() == null && cachedTag != null) {
|
||||
changed = true;
|
||||
} else if (cachedTag != null) {
|
||||
cachedTag = getDefaultTag();
|
||||
updateBlock(session);
|
||||
changed = true;
|
||||
}
|
||||
else if (entityMetadata.getId() == 9) {
|
||||
rotation = ((int) entityMetadata.getValue()) * 45;
|
||||
}
|
||||
|
||||
public void setItemRotation(EntityMetadata<Integer> entityMetadata) {
|
||||
rotation = ((IntEntityMetadata) entityMetadata).getPrimitiveValue() * 45;
|
||||
if (cachedTag == null) {
|
||||
updateBlock(session);
|
||||
return;
|
||||
}
|
||||
NbtMapBuilder builder = cachedTag.toBuilder();
|
||||
builder.putFloat("ItemRotation", rotation);
|
||||
cachedTag = builder.build();
|
||||
updateBlock(session);
|
||||
}
|
||||
else {
|
||||
updateBlock(session);
|
||||
}
|
||||
changed = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean despawnEntity(GeyserSession session) {
|
||||
public boolean despawnEntity() {
|
||||
UpdateBlockPacket updateBlockPacket = new UpdateBlockPacket();
|
||||
updateBlockPacket.setDataLayer(0);
|
||||
updateBlockPacket.setBlockPosition(bedrockPosition);
|
||||
updateBlockPacket.setRuntimeId(session.getBlockMappings().getBedrockAirId());
|
||||
updateBlockPacket.setRuntimeId(session.getBlockMappings().getBedrockAirId()); //TODO maybe set this to the world block or another item frame?
|
||||
updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.PRIORITY);
|
||||
updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NETWORK);
|
||||
updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NEIGHBORS);
|
||||
@ -166,15 +168,23 @@ public class ItemFrameEntity extends Entity {
|
||||
builder.putInt("y", bedrockPosition.getY());
|
||||
builder.putInt("z", bedrockPosition.getZ());
|
||||
builder.putByte("isMovable", (byte) 1);
|
||||
builder.putString("id", this.entityType == EntityType.GLOW_ITEM_FRAME ? "GlowItemFrame" : "ItemFrame");
|
||||
builder.putString("id", this.definition.entityType() == EntityType.GLOW_ITEM_FRAME ? "GlowItemFrame" : "ItemFrame");
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateBedrockMetadata() {
|
||||
updateBlock();
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the item frame as a block
|
||||
* @param session GeyserSession.
|
||||
*/
|
||||
public void updateBlock(GeyserSession session) {
|
||||
public void updateBlock() {
|
||||
if (!changed) {
|
||||
// Don't send a block update packet - nothing changed
|
||||
return;
|
||||
}
|
||||
UpdateBlockPacket updateBlockPacket = new UpdateBlockPacket();
|
||||
updateBlockPacket.setDataLayer(0);
|
||||
updateBlockPacket.setBlockPosition(bedrockPosition);
|
||||
@ -193,6 +203,8 @@ public class ItemFrameEntity extends Entity {
|
||||
}
|
||||
|
||||
session.sendUpstreamPacket(blockEntityDataPacket);
|
||||
|
||||
changed = false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -26,9 +26,10 @@
|
||||
package org.geysermc.connector.entity;
|
||||
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import org.geysermc.connector.entity.type.EntityType;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class ItemedFireballEntity extends ThrowableEntity {
|
||||
private final Vector3f acceleration;
|
||||
|
||||
@ -37,8 +38,8 @@ public class ItemedFireballEntity extends ThrowableEntity {
|
||||
*/
|
||||
protected int futureTicks = 3;
|
||||
|
||||
public ItemedFireballEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
||||
super(entityId, geyserId, entityType, position, Vector3f.ZERO, rotation);
|
||||
public ItemedFireballEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
super(session, entityId, geyserId, uuid, definition, position, Vector3f.ZERO, yaw, pitch, headYaw);
|
||||
|
||||
float magnitude = motion.length();
|
||||
if (magnitude != 0) {
|
||||
@ -48,28 +49,28 @@ public class ItemedFireballEntity extends ThrowableEntity {
|
||||
}
|
||||
}
|
||||
|
||||
private Vector3f tickMovement(GeyserSession session, Vector3f position) {
|
||||
private Vector3f tickMovement(Vector3f position) {
|
||||
position = position.add(motion);
|
||||
float drag = getDrag(session);
|
||||
float drag = getDrag();
|
||||
motion = motion.add(acceleration).mul(drag);
|
||||
return position;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void moveAbsoluteImmediate(GeyserSession session, Vector3f position, Vector3f rotation, boolean isOnGround, boolean teleported) {
|
||||
protected void moveAbsoluteImmediate(Vector3f position, float yaw, float pitch, float headYaw, boolean isOnGround, boolean teleported) {
|
||||
// Advance the position by a few ticks before sending it to Bedrock
|
||||
Vector3f lastMotion = motion;
|
||||
Vector3f newPosition = position;
|
||||
for (int i = 0; i < futureTicks; i++) {
|
||||
newPosition = tickMovement(session, newPosition);
|
||||
newPosition = tickMovement(newPosition);
|
||||
}
|
||||
super.moveAbsoluteImmediate(session, newPosition, rotation, isOnGround, teleported);
|
||||
super.moveAbsoluteImmediate(newPosition, yaw, pitch, headYaw, isOnGround, teleported);
|
||||
this.position = position;
|
||||
this.motion = lastMotion;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick(GeyserSession session) {
|
||||
moveAbsoluteImmediate(session, tickMovement(session, position), rotation, false, false);
|
||||
public void tick() {
|
||||
moveAbsoluteImmediate(tickMovement(position), yaw, pitch, headYaw, false, false);
|
||||
}
|
||||
}
|
||||
|
@ -26,13 +26,15 @@
|
||||
package org.geysermc.connector.entity;
|
||||
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import org.geysermc.connector.entity.type.EntityType;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class LeashKnotEntity extends Entity {
|
||||
|
||||
public LeashKnotEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
||||
public LeashKnotEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
// Position is incorrect by default
|
||||
super(entityId, geyserId, entityType, position.add(0.5f, 0.25f, 0.5f), motion, rotation);
|
||||
super(session, entityId, geyserId, uuid, definition, position.add(0.5f, 0.25f, 0.5f), motion, yaw, pitch, headYaw);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -27,20 +27,20 @@ package org.geysermc.connector.entity;
|
||||
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.protocol.bedrock.packet.PlaySoundPacket;
|
||||
import org.geysermc.connector.entity.type.EntityType;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
public class LightningEntity extends Entity {
|
||||
|
||||
public LightningEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
||||
super(entityId, geyserId, entityType, position, motion, rotation);
|
||||
public LightningEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void spawnEntity(GeyserSession session) {
|
||||
super.spawnEntity(session);
|
||||
public void spawnEntity() {
|
||||
super.spawnEntity();
|
||||
|
||||
// Add these two sound effects - they're done completely clientside on Java Edition as of 1.17.1
|
||||
ThreadLocalRandom random = ThreadLocalRandom.current();
|
||||
|
@ -29,6 +29,8 @@ import com.github.steveice10.mc.protocol.data.game.entity.attribute.Attribute;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.Pose;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.FloatEntityMetadata;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.math.vector.Vector3i;
|
||||
import com.nukkitx.protocol.bedrock.data.AttributeData;
|
||||
@ -43,7 +45,6 @@ import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.geysermc.connector.entity.attribute.GeyserAttributeType;
|
||||
import org.geysermc.connector.entity.type.EntityType;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
import org.geysermc.connector.registry.type.ItemMapping;
|
||||
import org.geysermc.connector.utils.AttributeUtils;
|
||||
@ -52,6 +53,7 @@ import org.geysermc.connector.utils.ChunkUtils;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@ -74,32 +76,34 @@ public class LivingEntity extends Entity {
|
||||
*/
|
||||
private boolean isMaxFrozenState = false;
|
||||
|
||||
public LivingEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
||||
super(entityId, geyserId, entityType, position, motion, rotation);
|
||||
|
||||
// Matches Bedrock behavior; is always set to this
|
||||
metadata.put(EntityData.HEALTH, 1);
|
||||
public LivingEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
|
||||
switch (entityMetadata.getId()) {
|
||||
case 8 -> { // blocking
|
||||
byte xd = (byte) entityMetadata.getValue();
|
||||
protected void initializeMetadata() {
|
||||
super.initializeMetadata();
|
||||
// Matches Bedrock behavior; is always set to this
|
||||
dirtyMetadata.put(EntityData.HEALTH, 1);
|
||||
}
|
||||
|
||||
//blocking gets triggered when using a bow, but if we set USING_ITEM for all items, it may look like
|
||||
public void setLivingEntityFlags(EntityMetadata<Byte> entityMetadata) {
|
||||
byte xd = ((ByteEntityMetadata) entityMetadata).getPrimitiveValue();
|
||||
|
||||
// Blocking gets triggered when using a bow, but if we set USING_ITEM for all items, it may look like
|
||||
// you're "mining" with ex. a shield.
|
||||
ItemMapping shield = session.getItemMappings().getStoredItems().shield();
|
||||
boolean isUsingShield = (getHand().getId() == shield.getBedrockId() ||
|
||||
getHand().equals(ItemData.AIR) && getOffHand().getId() == shield.getBedrockId());
|
||||
metadata.getFlags().setFlag(EntityFlag.USING_ITEM, (xd & 0x01) == 0x01 && !isUsingShield);
|
||||
metadata.getFlags().setFlag(EntityFlag.BLOCKING, (xd & 0x01) == 0x01);
|
||||
setFlag(EntityFlag.USING_ITEM, (xd & 0x01) == 0x01 && !isUsingShield);
|
||||
setFlag(EntityFlag.BLOCKING, (xd & 0x01) == 0x01);
|
||||
|
||||
// Riptide spin attack
|
||||
metadata.getFlags().setFlag(EntityFlag.DAMAGE_NEARBY_MOBS, (xd & 0x04) == 0x04);
|
||||
setFlag(EntityFlag.DAMAGE_NEARBY_MOBS, (xd & 0x04) == 0x04);
|
||||
}
|
||||
case 9 -> {
|
||||
this.health = (float) entityMetadata.getValue();
|
||||
|
||||
public void setHealth(EntityMetadata<Float> entityMetadata) {
|
||||
this.health = ((FloatEntityMetadata) entityMetadata).getPrimitiveValue();
|
||||
|
||||
AttributeData healthData = createHealthAttribute();
|
||||
UpdateAttributesPacket attributesPacket = new UpdateAttributesPacket();
|
||||
@ -107,49 +111,52 @@ public class LivingEntity extends Entity {
|
||||
attributesPacket.setAttributes(Collections.singletonList(healthData));
|
||||
session.sendUpstreamPacket(attributesPacket);
|
||||
}
|
||||
case 10 -> metadata.put(EntityData.EFFECT_COLOR, entityMetadata.getValue());
|
||||
case 11 -> metadata.put(EntityData.EFFECT_AMBIENT, (byte) ((boolean) entityMetadata.getValue() ? 1 : 0));
|
||||
case 14 -> { // Bed Position
|
||||
Position bedPosition = (Position) entityMetadata.getValue();
|
||||
|
||||
public Vector3i setBedPosition(EntityMetadata<Position> entityMetadata) {
|
||||
Position bedPosition = entityMetadata.getValue();
|
||||
if (bedPosition != null) {
|
||||
metadata.put(EntityData.BED_POSITION, Vector3i.from(bedPosition.getX(), bedPosition.getY(), bedPosition.getZ()));
|
||||
Vector3i vector = Vector3i.from(bedPosition.getX(), bedPosition.getY(), bedPosition.getZ());
|
||||
dirtyMetadata.put(EntityData.BED_POSITION, vector);
|
||||
int bed = session.getConnector().getWorldManager().getBlockAt(session, bedPosition);
|
||||
// Bed has to be updated, or else player is floating in the air
|
||||
ChunkUtils.updateBlock(session, bed, bedPosition);
|
||||
// Indicate that the player should enter the sleep cycle
|
||||
// Has to be a byte or it does not work
|
||||
// (Bed position is what actually triggers sleep - "pose" is only optional)
|
||||
metadata.put(EntityData.PLAYER_FLAGS, (byte) 2);
|
||||
dirtyMetadata.put(EntityData.PLAYER_FLAGS, (byte) 2);
|
||||
return vector;
|
||||
} else {
|
||||
// Player is no longer sleeping
|
||||
metadata.put(EntityData.PLAYER_FLAGS, (byte) 0);
|
||||
dirtyMetadata.put(EntityData.PLAYER_FLAGS, (byte) 0);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
super.updateBedrockMetadata(entityMetadata, session);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isShaking(GeyserSession session) {
|
||||
protected boolean isShaking() {
|
||||
return isMaxFrozenState;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setDimensions(Pose pose) {
|
||||
if (pose == Pose.SLEEPING) {
|
||||
metadata.put(EntityData.BOUNDING_BOX_WIDTH, 0.2f);
|
||||
metadata.put(EntityData.BOUNDING_BOX_HEIGHT, 0.2f);
|
||||
boundingBoxWidth = 0.2f;
|
||||
boundingBoxHeight = 0.2f;
|
||||
if (boundingBoxWidth != definition.width() || boundingBoxHeight != definition.height()) {
|
||||
dirtyMetadata.put(EntityData.BOUNDING_BOX_WIDTH, boundingBoxWidth);
|
||||
dirtyMetadata.put(EntityData.BOUNDING_BOX_HEIGHT, boundingBoxHeight);
|
||||
}
|
||||
} else {
|
||||
super.setDimensions(pose);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setFreezing(GeyserSession session, float amount) {
|
||||
super.setFreezing(session, amount);
|
||||
this.isMaxFrozenState = amount >= 1.0f;
|
||||
metadata.getFlags().setFlag(EntityFlag.SHAKING, isShaking(session));
|
||||
public float setFreezing(EntityMetadata<Integer> entityMetadata) {
|
||||
float freezingPercentage = super.setFreezing(entityMetadata);
|
||||
this.isMaxFrozenState = freezingPercentage >= 1.0f;
|
||||
setFlag(EntityFlag.SHAKING, isShaking());
|
||||
return freezingPercentage;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -26,63 +26,42 @@
|
||||
package org.geysermc.connector.entity;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanEntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata;
|
||||
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.network.session.GeyserSession;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class MinecartEntity extends Entity {
|
||||
|
||||
public MinecartEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
||||
super(entityId, geyserId, entityType, position.add(0d, entityType.getOffset(), 0d), motion, rotation);
|
||||
public MinecartEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
super(session, entityId, geyserId, uuid, definition, position.add(0d, definition.offset(), 0d), motion, yaw, pitch, headYaw);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
|
||||
|
||||
if (entityMetadata.getId() == 8) {
|
||||
metadata.put(EntityData.HEALTH, entityMetadata.getValue());
|
||||
public void setCustomBlock(EntityMetadata<Integer> entityMetadata) {
|
||||
dirtyMetadata.put(EntityData.DISPLAY_ITEM, session.getBlockMappings().getBedrockBlockId(((IntEntityMetadata) entityMetadata).getPrimitiveValue()));
|
||||
}
|
||||
|
||||
// Direction in which the minecart is shaking
|
||||
if (entityMetadata.getId() == 9) {
|
||||
metadata.put(EntityData.HURT_DIRECTION, entityMetadata.getValue());
|
||||
}
|
||||
|
||||
// Power in Java, time in Bedrock
|
||||
if (entityMetadata.getId() == 10) {
|
||||
metadata.put(EntityData.HURT_TIME, Math.min((int) (float) entityMetadata.getValue(), 15));
|
||||
}
|
||||
|
||||
if (!(this instanceof DefaultBlockMinecartEntity)) { // Handled in the DefaultBlockMinecartEntity class
|
||||
// Custom block
|
||||
if (entityMetadata.getId() == 11) {
|
||||
metadata.put(EntityData.DISPLAY_ITEM, session.getBlockMappings().getBedrockBlockId((int) entityMetadata.getValue()));
|
||||
}
|
||||
|
||||
// Custom block offset
|
||||
if (entityMetadata.getId() == 12) {
|
||||
metadata.put(EntityData.DISPLAY_OFFSET, entityMetadata.getValue());
|
||||
public void setCustomBlockOffset(EntityMetadata<Integer> entityMetadata) {
|
||||
dirtyMetadata.put(EntityData.DISPLAY_OFFSET, entityMetadata.getValue());
|
||||
}
|
||||
|
||||
public void setShowCustomBlock(EntityMetadata<Boolean> entityMetadata) {
|
||||
// If the custom block should be enabled
|
||||
if (entityMetadata.getId() == 13) {
|
||||
// Needs a byte based off of Java's boolean
|
||||
metadata.put(EntityData.CUSTOM_DISPLAY, (byte) ((boolean) entityMetadata.getValue() ? 1 : 0));
|
||||
}
|
||||
}
|
||||
|
||||
super.updateBedrockMetadata(entityMetadata, session);
|
||||
dirtyMetadata.put(EntityData.CUSTOM_DISPLAY, (byte) (((BooleanEntityMetadata) entityMetadata).getPrimitiveValue() ? 1 : 0));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void moveAbsolute(GeyserSession session, Vector3f position, Vector3f rotation, boolean isOnGround, boolean teleported) {
|
||||
super.moveAbsolute(session, position.add(0d, this.entityType.getOffset(), 0d), rotation, isOnGround, teleported);
|
||||
public void moveAbsolute(Vector3f position, float yaw, float pitch, float headYaw, boolean isOnGround, boolean teleported) {
|
||||
super.moveAbsolute(position.add(0d, this.definition.offset(), 0d), yaw, pitch, headYaw, isOnGround, teleported);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vector3f getBedrockRotation() {
|
||||
// Note: minecart rotation on rails does not care about the actual rotation value
|
||||
return Vector3f.from(0, rotation.getX(), 0);
|
||||
return Vector3f.from(0, yaw, 0);
|
||||
}
|
||||
}
|
||||
|
@ -27,23 +27,24 @@ package org.geysermc.connector.entity;
|
||||
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.protocol.bedrock.packet.AddPaintingPacket;
|
||||
import org.geysermc.connector.entity.type.EntityType;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
import org.geysermc.connector.utils.PaintingType;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class PaintingEntity extends Entity {
|
||||
private static final double OFFSET = -0.46875;
|
||||
private final PaintingType paintingName;
|
||||
private final int direction;
|
||||
|
||||
public PaintingEntity(long entityId, long geyserId, Vector3f position, PaintingType paintingName, int direction) {
|
||||
super(entityId, geyserId, EntityType.PAINTING, position, Vector3f.ZERO, Vector3f.ZERO);
|
||||
public PaintingEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, Vector3f position, PaintingType paintingName, int direction) {
|
||||
super(session, entityId, geyserId, uuid, EntityDefinitions.PAINTING, position, Vector3f.ZERO, 0f, 0f, 0f);
|
||||
this.paintingName = paintingName;
|
||||
this.direction = direction;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void spawnEntity(GeyserSession session) {
|
||||
public void spawnEntity() {
|
||||
AddPaintingPacket addPaintingPacket = new AddPaintingPacket();
|
||||
addPaintingPacket.setUniqueEntityId(geyserId);
|
||||
addPaintingPacket.setRuntimeEntityId(geyserId);
|
||||
@ -58,7 +59,7 @@ public class PaintingEntity extends Entity {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateHeadLookRotation(GeyserSession session, float headYaw) {
|
||||
public void updateHeadLookRotation(float headYaw) {
|
||||
// Do nothing, as head look messes up paintings
|
||||
}
|
||||
|
||||
|
@ -27,19 +27,20 @@ package org.geysermc.connector.entity;
|
||||
|
||||
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.network.session.GeyserSession;
|
||||
import org.geysermc.connector.network.translators.world.block.BlockStateValues;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class SpawnerMinecartEntity extends DefaultBlockMinecartEntity {
|
||||
|
||||
public SpawnerMinecartEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
||||
super(entityId, geyserId, entityType, position, motion, rotation);
|
||||
public SpawnerMinecartEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateDefaultBlockMetadata(GeyserSession session) {
|
||||
metadata.put(EntityData.DISPLAY_ITEM, session.getBlockMappings().getBedrockBlockId(BlockStateValues.JAVA_SPAWNER_ID));
|
||||
metadata.put(EntityData.DISPLAY_OFFSET, 6);
|
||||
public void updateDefaultBlockMetadata() {
|
||||
dirtyMetadata.put(EntityData.DISPLAY_ITEM, session.getBlockMappings().getBedrockBlockId(BlockStateValues.JAVA_SPAWNER_ID));
|
||||
dirtyMetadata.put(EntityData.DISPLAY_OFFSET, 6);
|
||||
}
|
||||
}
|
||||
|
@ -26,41 +26,37 @@
|
||||
package org.geysermc.connector.entity;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
|
||||
import com.nukkitx.protocol.bedrock.packet.SetEntityDataPacket;
|
||||
import org.geysermc.connector.entity.type.EntityType;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
|
||||
public class TNTEntity extends Entity implements Tickable {
|
||||
import java.util.UUID;
|
||||
|
||||
public class TNTEntity extends Entity implements Tickable {
|
||||
private int currentTick;
|
||||
|
||||
public TNTEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
||||
super(entityId, geyserId, entityType, position, motion, rotation);
|
||||
public TNTEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
|
||||
}
|
||||
|
||||
public void setFuseLength(EntityMetadata<Integer> entityMetadata) {
|
||||
currentTick = ((IntEntityMetadata) entityMetadata).getPrimitiveValue();
|
||||
setFlag(EntityFlag.IGNITED, true);
|
||||
dirtyMetadata.put(EntityData.FUSE_LENGTH, currentTick);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
|
||||
if (entityMetadata.getId() == 8) {
|
||||
currentTick = (int) entityMetadata.getValue();
|
||||
metadata.getFlags().setFlag(EntityFlag.IGNITED, true);
|
||||
metadata.put(EntityData.FUSE_LENGTH, currentTick);
|
||||
}
|
||||
|
||||
super.updateBedrockMetadata(entityMetadata, session);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick(GeyserSession session) {
|
||||
public void tick() {
|
||||
if (currentTick == 0) {
|
||||
// No need to update the fuse when there is none
|
||||
return;
|
||||
}
|
||||
|
||||
if (currentTick % 5 == 0) {
|
||||
metadata.put(EntityData.FUSE_LENGTH, currentTick);
|
||||
dirtyMetadata.put(EntityData.FUSE_LENGTH, currentTick);
|
||||
|
||||
SetEntityDataPacket packet = new SetEntityDataPacket();
|
||||
packet.setRuntimeEntityId(geyserId);
|
||||
|
@ -25,15 +25,17 @@
|
||||
|
||||
package org.geysermc.connector.entity;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.type.EntityType;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.protocol.bedrock.data.LevelEventType;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
|
||||
import com.nukkitx.protocol.bedrock.packet.LevelEventPacket;
|
||||
import com.nukkitx.protocol.bedrock.packet.MoveEntityDeltaPacket;
|
||||
import org.geysermc.connector.entity.type.EntityType;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
import org.geysermc.connector.network.translators.world.block.BlockStateValues;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Used as a class for any object-like entity that moves as a projectile
|
||||
*/
|
||||
@ -41,8 +43,8 @@ public class ThrowableEntity extends Entity implements Tickable {
|
||||
|
||||
protected Vector3f lastJavaPosition;
|
||||
|
||||
public ThrowableEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
||||
super(entityId, geyserId, entityType, position, motion, rotation);
|
||||
public ThrowableEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
|
||||
this.lastJavaPosition = position;
|
||||
}
|
||||
|
||||
@ -52,14 +54,14 @@ public class ThrowableEntity extends Entity implements Tickable {
|
||||
* Java clients assume the next positions of moving items. Bedrock needs to be explicitly told positions
|
||||
*/
|
||||
@Override
|
||||
public void tick(GeyserSession session) {
|
||||
moveAbsoluteImmediate(session, position.add(motion), rotation, onGround, false);
|
||||
float drag = getDrag(session);
|
||||
float gravity = getGravity(session);
|
||||
public void tick() {
|
||||
moveAbsoluteImmediate(position.add(motion), yaw, pitch, headYaw, onGround, false);
|
||||
float drag = getDrag();
|
||||
float gravity = getGravity();
|
||||
motion = motion.mul(drag).down(gravity);
|
||||
}
|
||||
|
||||
protected void moveAbsoluteImmediate(GeyserSession session, Vector3f position, Vector3f rotation, boolean isOnGround, boolean teleported) {
|
||||
protected void moveAbsoluteImmediate(Vector3f position, float yaw, float pitch, float headYaw, boolean isOnGround, boolean teleported) {
|
||||
MoveEntityDeltaPacket moveEntityDeltaPacket = new MoveEntityDeltaPacket();
|
||||
moveEntityDeltaPacket.setRuntimeEntityId(geyserId);
|
||||
|
||||
@ -86,19 +88,21 @@ public class ThrowableEntity extends Entity implements Tickable {
|
||||
}
|
||||
setPosition(position);
|
||||
|
||||
if (this.rotation.getX() != rotation.getX()) {
|
||||
if (this.yaw != yaw) {
|
||||
moveEntityDeltaPacket.getFlags().add(MoveEntityDeltaPacket.Flag.HAS_YAW);
|
||||
moveEntityDeltaPacket.setYaw(rotation.getX());
|
||||
moveEntityDeltaPacket.setYaw(yaw);
|
||||
this.yaw = yaw;
|
||||
}
|
||||
if (this.rotation.getY() != rotation.getY()) {
|
||||
if (this.pitch != pitch) {
|
||||
moveEntityDeltaPacket.getFlags().add(MoveEntityDeltaPacket.Flag.HAS_PITCH);
|
||||
moveEntityDeltaPacket.setPitch(rotation.getY());
|
||||
moveEntityDeltaPacket.setPitch(pitch);
|
||||
this.pitch = pitch;
|
||||
}
|
||||
if (this.rotation.getZ() != rotation.getZ()) {
|
||||
if (this.headYaw != headYaw) {
|
||||
moveEntityDeltaPacket.getFlags().add(MoveEntityDeltaPacket.Flag.HAS_HEAD_YAW);
|
||||
moveEntityDeltaPacket.setHeadYaw(rotation.getZ());
|
||||
moveEntityDeltaPacket.setHeadYaw(headYaw);
|
||||
this.headYaw = headYaw;
|
||||
}
|
||||
setRotation(rotation);
|
||||
|
||||
if (!moveEntityDeltaPacket.getFlags().isEmpty()) {
|
||||
session.sendUpstreamPacket(moveEntityDeltaPacket);
|
||||
@ -108,14 +112,12 @@ public class ThrowableEntity extends Entity implements Tickable {
|
||||
/**
|
||||
* Get the gravity of this entity type. Used for applying gravity while the entity is in motion.
|
||||
*
|
||||
* @param session the session of the Bedrock client.
|
||||
* @return the amount of gravity to apply to this entity while in motion.
|
||||
*/
|
||||
protected float getGravity(GeyserSession session) {
|
||||
if (metadata.getFlags().getFlag(EntityFlag.HAS_GRAVITY)) {
|
||||
switch (entityType) {
|
||||
protected float getGravity() {
|
||||
if (getFlag(EntityFlag.HAS_GRAVITY)) {
|
||||
switch (definition.entityType()) {
|
||||
case THROWN_POTION:
|
||||
case LINGERING_POTION:
|
||||
return 0.05f;
|
||||
case THROWN_EXP_BOTTLE:
|
||||
return 0.07f;
|
||||
@ -134,16 +136,14 @@ public class ThrowableEntity extends Entity implements Tickable {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param session the session of the Bedrock client.
|
||||
* @return the drag that should be multiplied to the entity's motion
|
||||
*/
|
||||
protected float getDrag(GeyserSession session) {
|
||||
if (isInWater(session)) {
|
||||
protected float getDrag() {
|
||||
if (isInWater()) {
|
||||
return 0.8f;
|
||||
} else {
|
||||
switch (entityType) {
|
||||
switch (definition.entityType()) {
|
||||
case THROWN_POTION:
|
||||
case LINGERING_POTION:
|
||||
case THROWN_EXP_BOTTLE:
|
||||
case SNOWBALL:
|
||||
case THROWN_EGG:
|
||||
@ -162,34 +162,33 @@ public class ThrowableEntity extends Entity implements Tickable {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param session the session of the Bedrock client.
|
||||
* @return true if this entity is currently in water.
|
||||
*/
|
||||
protected boolean isInWater(GeyserSession session) {
|
||||
protected boolean isInWater() {
|
||||
int block = session.getConnector().getWorldManager().getBlockAt(session, position.toInt());
|
||||
return BlockStateValues.getWaterLevel(block) != -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean despawnEntity(GeyserSession session) {
|
||||
if (entityType == EntityType.THROWN_ENDERPEARL) {
|
||||
public boolean despawnEntity() {
|
||||
if (definition.entityType() == EntityType.THROWN_ENDERPEARL) {
|
||||
LevelEventPacket particlePacket = new LevelEventPacket();
|
||||
particlePacket.setType(LevelEventType.PARTICLE_TELEPORT);
|
||||
particlePacket.setPosition(position);
|
||||
session.sendUpstreamPacket(particlePacket);
|
||||
}
|
||||
return super.despawnEntity(session);
|
||||
return super.despawnEntity();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void moveRelative(GeyserSession session, double relX, double relY, double relZ, Vector3f rotation, boolean isOnGround) {
|
||||
moveAbsoluteImmediate(session, lastJavaPosition.add(relX, relY, relZ), rotation, isOnGround, false);
|
||||
public void moveRelative(double relX, double relY, double relZ, float yaw, float pitch, float headYaw, boolean isOnGround) {
|
||||
moveAbsoluteImmediate(lastJavaPosition.add(relX, relY, relZ), yaw, pitch, headYaw, isOnGround, false);
|
||||
lastJavaPosition = position;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void moveAbsolute(GeyserSession session, Vector3f position, Vector3f rotation, boolean isOnGround, boolean teleported) {
|
||||
moveAbsoluteImmediate(session, position, rotation, isOnGround, teleported);
|
||||
public void moveAbsolute(Vector3f position, float yaw, float pitch, float headYaw, boolean isOnGround, boolean teleported) {
|
||||
moveAbsoluteImmediate(position, yaw, pitch, headYaw, isOnGround, teleported);
|
||||
lastJavaPosition = position;
|
||||
}
|
||||
}
|
||||
|
@ -27,9 +27,10 @@ package org.geysermc.connector.entity;
|
||||
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
|
||||
import org.geysermc.connector.entity.type.EntityType;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Used as a class for any projectile entity that looks like an item
|
||||
*/
|
||||
@ -40,37 +41,37 @@ public class ThrowableItemEntity extends ThrowableEntity {
|
||||
private int age;
|
||||
private boolean invisible;
|
||||
|
||||
public ThrowableItemEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
||||
super(entityId, geyserId, entityType, position, motion, rotation);
|
||||
metadata.getFlags().setFlag(EntityFlag.INVISIBLE, true);
|
||||
public ThrowableItemEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
|
||||
setFlag(EntityFlag.INVISIBLE, true);
|
||||
invisible = false;
|
||||
}
|
||||
|
||||
private void checkVisibility(GeyserSession session) {
|
||||
if (invisible != metadata.getFlags().getFlag(EntityFlag.INVISIBLE)) {
|
||||
private void checkVisibility() {
|
||||
if (invisible != getFlag(EntityFlag.INVISIBLE)) {
|
||||
if (!invisible) {
|
||||
Vector3f playerPos = session.getPlayerEntity().getPosition();
|
||||
// Prevent projectiles from blocking the player's screen
|
||||
if (age >= 4 || position.distanceSquared(playerPos) > 16) {
|
||||
metadata.getFlags().setFlag(EntityFlag.INVISIBLE, false);
|
||||
updateBedrockMetadata(session);
|
||||
setFlag(EntityFlag.INVISIBLE, false);
|
||||
updateBedrockMetadata();
|
||||
}
|
||||
} else {
|
||||
metadata.getFlags().setFlag(EntityFlag.INVISIBLE, true);
|
||||
updateBedrockMetadata(session);
|
||||
setFlag(EntityFlag.INVISIBLE, true);
|
||||
updateBedrockMetadata();
|
||||
}
|
||||
}
|
||||
age++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick(GeyserSession session) {
|
||||
checkVisibility(session);
|
||||
super.tick(session);
|
||||
public void tick() {
|
||||
checkVisibility();
|
||||
super.tick();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setInvisible(GeyserSession session, boolean value) {
|
||||
protected void setInvisible(boolean value) {
|
||||
invisible = value;
|
||||
}
|
||||
}
|
||||
|
@ -27,50 +27,44 @@ package org.geysermc.connector.entity;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.MetadataType;
|
||||
import com.github.steveice10.opennbt.tag.builtin.StringTag;
|
||||
import com.github.steveice10.opennbt.tag.builtin.Tag;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
|
||||
import org.geysermc.connector.GeyserConnector;
|
||||
import org.geysermc.connector.entity.type.EntityType;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
import org.geysermc.connector.network.translators.item.Potion;
|
||||
import org.geysermc.connector.registry.type.ItemMapping;
|
||||
|
||||
import java.util.EnumSet;
|
||||
import java.util.UUID;
|
||||
|
||||
public class ThrownPotionEntity extends ThrowableItemEntity {
|
||||
private static final EnumSet<Potion> NON_ENCHANTED_POTIONS = EnumSet.of(Potion.WATER, Potion.MUNDANE, Potion.THICK, Potion.AWKWARD);
|
||||
|
||||
public ThrownPotionEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
||||
super(entityId, geyserId, entityType, position, motion, rotation);
|
||||
public ThrownPotionEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
|
||||
if (entityMetadata.getId() == 8 && entityMetadata.getType() == MetadataType.ITEM) {
|
||||
ItemStack itemStack = (ItemStack) entityMetadata.getValue();
|
||||
public void setPotion(EntityMetadata<ItemStack> entityMetadata) {
|
||||
ItemStack itemStack = entityMetadata.getValue();
|
||||
ItemMapping mapping = session.getItemMappings().getMapping(itemStack);
|
||||
if (mapping.getJavaIdentifier().endsWith("potion") && itemStack.getNbt() != null) {
|
||||
Tag potionTag = itemStack.getNbt().get("Potion");
|
||||
if (potionTag instanceof StringTag) {
|
||||
Potion potion = Potion.getByJavaIdentifier(((StringTag) potionTag).getValue());
|
||||
if (potion != null) {
|
||||
metadata.put(EntityData.POTION_AUX_VALUE, potion.getBedrockId());
|
||||
metadata.getFlags().setFlag(EntityFlag.ENCHANTED, !NON_ENCHANTED_POTIONS.contains(potion));
|
||||
dirtyMetadata.put(EntityData.POTION_AUX_VALUE, potion.getBedrockId());
|
||||
setFlag(EntityFlag.ENCHANTED, !NON_ENCHANTED_POTIONS.contains(potion));
|
||||
} else {
|
||||
metadata.put(EntityData.POTION_AUX_VALUE, 0);
|
||||
dirtyMetadata.put(EntityData.POTION_AUX_VALUE, 0);
|
||||
GeyserConnector.getInstance().getLogger().debug("Unknown java potion: " + potionTag.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
boolean isLingering = mapping.getJavaIdentifier().equals("minecraft:lingering_potion");
|
||||
metadata.getFlags().setFlag(EntityFlag.LINGERING, isLingering);
|
||||
setFlag(EntityFlag.LINGERING, isLingering);
|
||||
}
|
||||
}
|
||||
|
||||
super.updateBedrockMetadata(entityMetadata, session);
|
||||
}
|
||||
}
|
||||
|
@ -25,11 +25,9 @@
|
||||
|
||||
package org.geysermc.connector.entity;
|
||||
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
|
||||
/**
|
||||
* Implemented onto anything that should have code ran every Minecraft tick - 50 milliseconds.
|
||||
*/
|
||||
public interface Tickable {
|
||||
void tick(GeyserSession session);
|
||||
void tick();
|
||||
}
|
||||
|
@ -26,38 +26,35 @@
|
||||
package org.geysermc.connector.entity;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata;
|
||||
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.network.session.GeyserSession;
|
||||
import org.geysermc.connector.network.translators.item.TippedArrowPotion;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Internally this is known as TippedArrowEntity but is used with tipped arrows and normal arrows
|
||||
*/
|
||||
public class TippedArrowEntity extends AbstractArrowEntity {
|
||||
|
||||
public TippedArrowEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
||||
super(entityId, geyserId, entityType, position, motion, rotation);
|
||||
public TippedArrowEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
|
||||
// Arrow potion effect color
|
||||
if (entityMetadata.getId() == 10) {
|
||||
int potionColor = (int) entityMetadata.getValue();
|
||||
public void setPotionEffectColor(EntityMetadata<Integer> entityMetadata) {
|
||||
int potionColor = ((IntEntityMetadata) entityMetadata).getPrimitiveValue();
|
||||
// -1 means no color
|
||||
if (potionColor == -1) {
|
||||
metadata.put(EntityData.CUSTOM_DISPLAY, 0);
|
||||
dirtyMetadata.put(EntityData.CUSTOM_DISPLAY, 0);
|
||||
} else {
|
||||
TippedArrowPotion potion = TippedArrowPotion.getByJavaColor(potionColor);
|
||||
if (potion != null && potion.getJavaColor() != -1) {
|
||||
metadata.put(EntityData.CUSTOM_DISPLAY, (byte) potion.getBedrockId());
|
||||
dirtyMetadata.put(EntityData.CUSTOM_DISPLAY, (byte) potion.getBedrockId());
|
||||
} else {
|
||||
metadata.put(EntityData.CUSTOM_DISPLAY, 0);
|
||||
dirtyMetadata.put(EntityData.CUSTOM_DISPLAY, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
super.updateBedrockMetadata(entityMetadata, session);
|
||||
}
|
||||
}
|
||||
|
@ -25,24 +25,14 @@
|
||||
|
||||
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.protocol.bedrock.data.entity.EntityFlag;
|
||||
import org.geysermc.connector.entity.type.EntityType;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class TridentEntity extends AbstractArrowEntity {
|
||||
|
||||
public TridentEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
||||
super(entityId, geyserId, entityType, position, motion, rotation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
|
||||
if (entityMetadata.getId() == 11) {
|
||||
metadata.getFlags().setFlag(EntityFlag.ENCHANTED, (boolean) entityMetadata.getValue());
|
||||
}
|
||||
|
||||
super.updateBedrockMetadata(entityMetadata, session);
|
||||
public TridentEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
|
||||
}
|
||||
}
|
||||
|
@ -26,35 +26,34 @@
|
||||
package org.geysermc.connector.entity;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanEntityMetadata;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import org.geysermc.connector.entity.type.EntityType;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class WitherSkullEntity extends ItemedFireballEntity {
|
||||
private boolean isCharged;
|
||||
|
||||
public WitherSkullEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
||||
super(entityId, geyserId, entityType, position, motion, rotation);
|
||||
public WitherSkullEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
|
||||
|
||||
this.futureTicks = 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected float getDrag(GeyserSession session) {
|
||||
return isCharged ? 0.73f : super.getDrag(session);
|
||||
public void setDangerous(EntityMetadata<Boolean> entityMetadata) {
|
||||
boolean newDangerous = ((BooleanEntityMetadata) entityMetadata).getPrimitiveValue();
|
||||
if (newDangerous != isCharged) {
|
||||
isCharged = newDangerous;
|
||||
// Is an entirely new entity in Bedrock but just a metadata type in Java
|
||||
definition = isCharged ? EntityDefinitions.WITHER_SKULL_DANGEROUS : EntityDefinitions.WITHER_SKULL;
|
||||
despawnEntity();
|
||||
spawnEntity();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
|
||||
if (entityMetadata.getId() == 8) {
|
||||
boolean newIsCharged = (boolean) entityMetadata.getValue();
|
||||
if (newIsCharged != isCharged) {
|
||||
isCharged = newIsCharged;
|
||||
entityType = isCharged ? EntityType.WITHER_SKULL_DANGEROUS : EntityType.WITHER_SKULL;
|
||||
despawnEntity(session);
|
||||
spawnEntity(session);
|
||||
}
|
||||
}
|
||||
super.updateBedrockMetadata(entityMetadata, session);
|
||||
protected float getDrag() {
|
||||
return isCharged ? 0.73f : super.getDrag();
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2021 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.entity.factory;
|
||||
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import org.geysermc.connector.entity.Entity;
|
||||
import org.geysermc.connector.entity.EntityDefinition;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface BaseEntityFactory<T extends Entity> extends EntityFactory<T> {
|
||||
|
||||
T create(GeyserSession session, long javaId, long bedrockId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw);
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2021 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.entity.factory;
|
||||
|
||||
import org.geysermc.connector.entity.Entity;
|
||||
|
||||
public interface EntityFactory<T extends Entity> {
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2021 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.entity.factory;
|
||||
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import org.geysermc.connector.entity.ExpOrbEntity;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface ExperienceOrbEntityFactory extends EntityFactory<ExpOrbEntity> {
|
||||
|
||||
ExpOrbEntity create(GeyserSession session, int amount, long entityId, long geyserId, Vector3f position);
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2021 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.entity.factory;
|
||||
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import org.geysermc.connector.entity.PaintingEntity;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
import org.geysermc.connector.utils.PaintingType;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public interface PaintingEntityFactory extends EntityFactory<PaintingEntity> {
|
||||
|
||||
PaintingEntity create(GeyserSession session, long entityId, long geyserId, UUID uuid, Vector3f position, PaintingType paintingName, int direction);
|
||||
}
|
@ -27,16 +27,19 @@ package org.geysermc.connector.entity.living;
|
||||
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
|
||||
import org.geysermc.connector.entity.type.EntityType;
|
||||
import org.geysermc.connector.entity.EntityDefinition;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class AbstractFishEntity extends WaterEntity {
|
||||
|
||||
public AbstractFishEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
||||
super(entityId, geyserId, entityType, position, motion, rotation);
|
||||
public AbstractFishEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
|
||||
|
||||
metadata.getFlags().setFlag(EntityFlag.CAN_SWIM, true);
|
||||
metadata.getFlags().setFlag(EntityFlag.BREATHING, true);
|
||||
metadata.getFlags().setFlag(EntityFlag.CAN_CLIMB, false);
|
||||
metadata.getFlags().setFlag(EntityFlag.HAS_GRAVITY, false);
|
||||
setFlag(EntityFlag.CAN_SWIM, true);
|
||||
setFlag(EntityFlag.BREATHING, true);
|
||||
setFlag(EntityFlag.CAN_CLIMB, false);
|
||||
setFlag(EntityFlag.HAS_GRAVITY, false);
|
||||
}
|
||||
}
|
||||
|
@ -26,29 +26,46 @@
|
||||
package org.geysermc.connector.entity.living;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanEntityMetadata;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
|
||||
import org.geysermc.connector.entity.type.EntityType;
|
||||
import org.geysermc.connector.entity.EntityDefinition;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class AgeableEntity extends CreatureEntity {
|
||||
|
||||
public AgeableEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
||||
super(entityId, geyserId, entityType, position, motion, rotation);
|
||||
public AgeableEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
|
||||
if (entityMetadata.getId() == 16) {
|
||||
boolean isBaby = (boolean) entityMetadata.getValue();
|
||||
metadata.put(EntityData.SCALE, isBaby ? .55f : 1f);
|
||||
metadata.getFlags().setFlag(EntityFlag.BABY, isBaby);
|
||||
public void setBaby(EntityMetadata<Boolean> entityMetadata) {
|
||||
boolean isBaby = ((BooleanEntityMetadata) entityMetadata).getPrimitiveValue();
|
||||
dirtyMetadata.put(EntityData.SCALE, isBaby ? getBabySize() : getAdultSize());
|
||||
setFlag(EntityFlag.BABY, isBaby);
|
||||
|
||||
metadata.put(EntityData.BOUNDING_BOX_HEIGHT, entityType.getHeight() * (isBaby ? 0.55f : 1f));
|
||||
metadata.put(EntityData.BOUNDING_BOX_WIDTH, entityType.getWidth() * (isBaby ? 0.55f : 1f));
|
||||
// TODO save this?
|
||||
dirtyMetadata.put(EntityData.BOUNDING_BOX_HEIGHT, definition.height() * (isBaby ? getBabySize() : getAdultSize()));
|
||||
dirtyMetadata.put(EntityData.BOUNDING_BOX_WIDTH, definition.width() * (isBaby ? getBabySize() : getAdultSize()));
|
||||
}
|
||||
|
||||
super.updateBedrockMetadata(entityMetadata, session);
|
||||
/**
|
||||
* The scale that should be used when this entity is not a baby.
|
||||
*/
|
||||
protected float getAdultSize() {
|
||||
return 1f;
|
||||
}
|
||||
|
||||
/**
|
||||
* The scale that should be used when this entity is a baby.
|
||||
*/
|
||||
protected float getBabySize() {
|
||||
return 0.55f;
|
||||
}
|
||||
|
||||
public boolean isBaby() {
|
||||
return getFlag(EntityFlag.BABY);
|
||||
}
|
||||
}
|
||||
|
@ -26,11 +26,14 @@
|
||||
package org.geysermc.connector.entity.living;
|
||||
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import org.geysermc.connector.entity.type.EntityType;
|
||||
import org.geysermc.connector.entity.EntityDefinition;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
|
||||
public class AmbientEntity extends InsentientEntity {
|
||||
import java.util.UUID;
|
||||
|
||||
public AmbientEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
||||
super(entityId, geyserId, entityType, position, motion, rotation);
|
||||
public class AmbientEntity extends MobEntity {
|
||||
|
||||
public AmbientEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
|
||||
}
|
||||
}
|
||||
|
@ -26,18 +26,22 @@
|
||||
package org.geysermc.connector.entity.living;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.MetadataType;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.Rotation;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
|
||||
import com.nukkitx.protocol.bedrock.data.inventory.ItemData;
|
||||
import com.nukkitx.protocol.bedrock.packet.MoveEntityAbsolutePacket;
|
||||
import lombok.Getter;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.geysermc.connector.entity.EntityDefinition;
|
||||
import org.geysermc.connector.entity.EntityDefinitions;
|
||||
import org.geysermc.connector.entity.LivingEntity;
|
||||
import org.geysermc.connector.entity.type.EntityType;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class ArmorStandEntity extends LivingEntity {
|
||||
|
||||
// These are used to store the state of the armour stand for use when handling invisibility
|
||||
@ -72,54 +76,54 @@ public class ArmorStandEntity extends LivingEntity {
|
||||
* Whether we should update the position of this armor stand after metadata updates.
|
||||
*/
|
||||
private boolean positionUpdateRequired = false;
|
||||
private GeyserSession session;
|
||||
|
||||
public ArmorStandEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
||||
super(entityId, geyserId, entityType, position, motion, rotation);
|
||||
public ArmorStandEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void spawnEntity(GeyserSession session) {
|
||||
this.session = session;
|
||||
this.rotation = Vector3f.from(rotation.getX(), rotation.getX(), rotation.getX());
|
||||
super.spawnEntity(session);
|
||||
public void spawnEntity() {
|
||||
this.pitch = yaw;
|
||||
this.headYaw = yaw;
|
||||
super.spawnEntity();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean despawnEntity(GeyserSession session) {
|
||||
public boolean despawnEntity() {
|
||||
if (secondEntity != null) {
|
||||
secondEntity.despawnEntity(session);
|
||||
secondEntity.despawnEntity();
|
||||
}
|
||||
return super.despawnEntity(session);
|
||||
return super.despawnEntity();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void moveRelative(GeyserSession session, double relX, double relY, double relZ, Vector3f rotation, boolean isOnGround) {
|
||||
public void moveRelative(double relX, double relY, double relZ, float yaw, float pitch, float headYaw, boolean isOnGround) {
|
||||
if (secondEntity != null) {
|
||||
secondEntity.moveRelative(session, relX, relY, relZ, rotation, isOnGround);
|
||||
secondEntity.moveRelative(relX, relY, relZ, yaw, pitch, headYaw, isOnGround);
|
||||
}
|
||||
super.moveRelative(session, relX, relY, relZ, rotation, isOnGround);
|
||||
super.moveRelative(relX, relY, relZ, yaw, pitch, headYaw, isOnGround);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void moveAbsolute(GeyserSession session, Vector3f position, Vector3f rotation, boolean isOnGround, boolean teleported) {
|
||||
public void moveAbsolute(Vector3f position, float yaw, float pitch, float headYaw, boolean isOnGround, boolean teleported) {
|
||||
if (secondEntity != null) {
|
||||
secondEntity.moveAbsolute(session, applyOffsetToPosition(position), rotation, isOnGround, teleported);
|
||||
secondEntity.moveAbsolute(applyOffsetToPosition(position), yaw, pitch, headYaw, isOnGround, teleported);
|
||||
} else if (positionRequiresOffset) {
|
||||
// Fake the height to be above where it is so the nametag appears in the right location for invisible non-marker armour stands
|
||||
position = applyOffsetToPosition(position);
|
||||
}
|
||||
|
||||
super.moveAbsolute(session, position, Vector3f.from(rotation.getX(), rotation.getX(), rotation.getX()), isOnGround, teleported);
|
||||
super.moveAbsolute(position, yaw, yaw, yaw, isOnGround, teleported);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
|
||||
super.updateBedrockMetadata(entityMetadata, session);
|
||||
if (entityMetadata.getId() == 2) {
|
||||
public void setDisplayName(EntityMetadata<Component> entityMetadata) {
|
||||
super.setDisplayName(entityMetadata);
|
||||
updateSecondEntityStatus(false);
|
||||
} else if (entityMetadata.getId() == 15 && entityMetadata.getType() == MetadataType.BYTE) {
|
||||
byte xd = (byte) entityMetadata.getValue();
|
||||
}
|
||||
|
||||
public void setArmorStandFlags(EntityMetadata<Byte> entityMetadata) {
|
||||
byte xd = ((ByteEntityMetadata) entityMetadata).getPrimitiveValue();
|
||||
|
||||
// isSmall
|
||||
boolean newIsSmall = (xd & 0x01) == 0x01;
|
||||
@ -141,9 +145,9 @@ public class ArmorStandEntity extends LivingEntity {
|
||||
isMarker = (xd & 0x10) == 0x10;
|
||||
if (oldIsMarker != isMarker) {
|
||||
if (isMarker) {
|
||||
metadata.put(EntityData.BOUNDING_BOX_WIDTH, 0.0f);
|
||||
metadata.put(EntityData.BOUNDING_BOX_HEIGHT, 0.0f);
|
||||
metadata.put(EntityData.SCALE, 0f);
|
||||
dirtyMetadata.put(EntityData.BOUNDING_BOX_WIDTH, 0.0f);
|
||||
dirtyMetadata.put(EntityData.BOUNDING_BOX_HEIGHT, 0.0f);
|
||||
dirtyMetadata.put(EntityData.SCALE, 0f);
|
||||
} else {
|
||||
toggleSmallStatus();
|
||||
}
|
||||
@ -153,56 +157,49 @@ public class ArmorStandEntity extends LivingEntity {
|
||||
|
||||
// The following values don't do anything on normal Bedrock.
|
||||
// But if given a resource pack, then we can use these values to control armor stand visual properties
|
||||
metadata.getFlags().setFlag(EntityFlag.ANGRY, (xd & 0x04) != 0x04); // Has arms
|
||||
metadata.getFlags().setFlag(EntityFlag.ADMIRING, (xd & 0x08) == 0x08); // Has no baseplate
|
||||
} else {
|
||||
EntityData dataLeech = null;
|
||||
EntityFlag negativeXToggle = null;
|
||||
EntityFlag negativeYToggle = null;
|
||||
EntityFlag negativeZToggle = null;
|
||||
switch (entityMetadata.getId()) {
|
||||
case 16 -> { // Head
|
||||
dataLeech = EntityData.MARK_VARIANT;
|
||||
negativeXToggle = EntityFlag.INTERESTED;
|
||||
negativeYToggle = EntityFlag.CHARGED;
|
||||
negativeZToggle = EntityFlag.POWERED;
|
||||
setFlag(EntityFlag.ANGRY, (xd & 0x04) != 0x04); // Has arms
|
||||
setFlag(EntityFlag.ADMIRING, (xd & 0x08) == 0x08); // Has no baseplate
|
||||
}
|
||||
case 17 -> { // Body
|
||||
dataLeech = EntityData.VARIANT;
|
||||
negativeXToggle = EntityFlag.IN_LOVE;
|
||||
negativeYToggle = EntityFlag.CELEBRATING;
|
||||
negativeZToggle = EntityFlag.CELEBRATING_SPECIAL;
|
||||
}
|
||||
case 18 -> { // Left arm
|
||||
dataLeech = EntityData.TRADE_TIER;
|
||||
negativeXToggle = EntityFlag.CHARGING;
|
||||
negativeYToggle = EntityFlag.CRITICAL;
|
||||
negativeZToggle = EntityFlag.DANCING;
|
||||
}
|
||||
case 19 -> { // Right arm
|
||||
dataLeech = EntityData.MAX_TRADE_TIER;
|
||||
negativeXToggle = EntityFlag.ELDER;
|
||||
negativeYToggle = EntityFlag.EMOTING;
|
||||
negativeZToggle = EntityFlag.IDLING;
|
||||
}
|
||||
case 20 -> { // Left leg
|
||||
dataLeech = EntityData.SKIN_ID;
|
||||
negativeXToggle = EntityFlag.IS_ILLAGER_CAPTAIN;
|
||||
negativeYToggle = EntityFlag.IS_IN_UI;
|
||||
negativeZToggle = EntityFlag.LINGERING;
|
||||
}
|
||||
case 21 -> { // Right leg
|
||||
dataLeech = EntityData.HURT_DIRECTION;
|
||||
negativeXToggle = EntityFlag.IS_PREGNANT;
|
||||
negativeYToggle = EntityFlag.SHEARED;
|
||||
negativeZToggle = EntityFlag.STALKING;
|
||||
}
|
||||
}
|
||||
if (dataLeech != null) {
|
||||
// Indicate that rotation should be checked
|
||||
metadata.getFlags().setFlag(EntityFlag.BRIBED, true);
|
||||
|
||||
Rotation rotation = (Rotation) entityMetadata.getValue();
|
||||
public void setHeadRotation(EntityMetadata<Rotation> entityMetadata) {
|
||||
onRotationUpdate(EntityData.MARK_VARIANT, EntityFlag.INTERESTED, EntityFlag.CHARGED, EntityFlag.POWERED, entityMetadata.getValue());
|
||||
}
|
||||
|
||||
public void setBodyRotation(EntityMetadata<Rotation> entityMetadata) {
|
||||
onRotationUpdate(EntityData.VARIANT, EntityFlag.IN_LOVE, EntityFlag.CELEBRATING, EntityFlag.CELEBRATING_SPECIAL, entityMetadata.getValue());
|
||||
}
|
||||
|
||||
public void setLeftArmRotation(EntityMetadata<Rotation> entityMetadata) {
|
||||
onRotationUpdate(EntityData.TRADE_TIER, EntityFlag.CHARGING, EntityFlag.CRITICAL, EntityFlag.DANCING, entityMetadata.getValue());
|
||||
}
|
||||
|
||||
public void setRightArmRotation(EntityMetadata<Rotation> entityMetadata) {
|
||||
onRotationUpdate(EntityData.MAX_TRADE_TIER, EntityFlag.ELDER, EntityFlag.EMOTING, EntityFlag.IDLING, entityMetadata.getValue());
|
||||
}
|
||||
|
||||
public void setLeftLegRotation(EntityMetadata<Rotation> entityMetadata) {
|
||||
onRotationUpdate(EntityData.SKIN_ID, EntityFlag.IS_ILLAGER_CAPTAIN, EntityFlag.IS_IN_UI, EntityFlag.LINGERING, entityMetadata.getValue());
|
||||
}
|
||||
|
||||
public void setRightLegRotation(EntityMetadata<Rotation> entityMetadata) {
|
||||
onRotationUpdate(EntityData.HURT_DIRECTION, EntityFlag.IS_PREGNANT, EntityFlag.SHEARED, EntityFlag.STALKING, entityMetadata.getValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates rotation on the armor stand by hijacking other unused Bedrock entity data/flags.
|
||||
* Do note: as of recent Bedrock versions there is a custom entity data system that can be replaced with this,
|
||||
* but at this time there is no need to implement this.
|
||||
*
|
||||
* @param dataLeech the entity data to "leech" off of that stores a compressed version of the rotation
|
||||
* @param negativeXToggle the flag to set true if the X value of rotation is negative
|
||||
* @param negativeYToggle the flag to set true if the Y value of rotation is negative
|
||||
* @param negativeZToggle the flag to set true if the Z value of rotation is negative
|
||||
* @param rotation the Java rotation value
|
||||
*/
|
||||
private void onRotationUpdate(EntityData dataLeech, EntityFlag negativeXToggle, EntityFlag negativeYToggle, EntityFlag negativeZToggle, Rotation rotation) {
|
||||
// Indicate that rotation should be checked
|
||||
setFlag(EntityFlag.BRIBED, true);
|
||||
|
||||
int rotationX = getRotation(rotation.getPitch());
|
||||
int rotationY = getRotation(rotation.getYaw());
|
||||
int rotationZ = getRotation(rotation.getRoll());
|
||||
@ -210,24 +207,19 @@ public class ArmorStandEntity extends LivingEntity {
|
||||
// We don't do this for the negative values out of concerns of the number being too big
|
||||
int topBit = (Math.abs(rotationX) >= 100 ? 4 : 0) + (Math.abs(rotationY) >= 100 ? 2 : 0) + (Math.abs(rotationZ) >= 100 ? 1 : 0);
|
||||
int value = (topBit * 1000000) + ((Math.abs(rotationX) % 100) * 10000) + ((Math.abs(rotationY) % 100) * 100) + (Math.abs(rotationZ) % 100);
|
||||
metadata.put(dataLeech, value);
|
||||
dirtyMetadata.put(dataLeech, value);
|
||||
// Set the entity flags if a value is negative
|
||||
metadata.getFlags().setFlag(negativeXToggle, rotationX < 0);
|
||||
metadata.getFlags().setFlag(negativeYToggle, rotationY < 0);
|
||||
metadata.getFlags().setFlag(negativeZToggle, rotationZ < 0);
|
||||
}
|
||||
}
|
||||
if (secondEntity != null) {
|
||||
secondEntity.updateBedrockMetadata(entityMetadata, session);
|
||||
}
|
||||
setFlag(negativeXToggle, rotationX < 0);
|
||||
setFlag(negativeYToggle, rotationY < 0);
|
||||
setFlag(negativeZToggle, rotationZ < 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateBedrockMetadata(GeyserSession session) {
|
||||
public void updateBedrockMetadata() {
|
||||
if (secondEntity != null) {
|
||||
secondEntity.updateBedrockMetadata(session);
|
||||
secondEntity.updateBedrockMetadata();
|
||||
}
|
||||
super.updateBedrockMetadata(session);
|
||||
super.updateBedrockMetadata();
|
||||
if (positionUpdateRequired) {
|
||||
positionUpdateRequired = false;
|
||||
updatePosition();
|
||||
@ -235,7 +227,7 @@ public class ArmorStandEntity extends LivingEntity {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setInvisible(GeyserSession session, boolean value) {
|
||||
protected void setInvisible(boolean value) {
|
||||
// Check if the armour stand is invisible and store accordingly
|
||||
if (primaryEntity) {
|
||||
isInvisible = value;
|
||||
@ -289,7 +281,7 @@ public class ArmorStandEntity extends LivingEntity {
|
||||
if (!primaryEntity) return;
|
||||
if (!isInvisible || isMarker) {
|
||||
// It is either impossible to show armor, or the armor stand isn't invisible. We good.
|
||||
metadata.getFlags().setFlag(EntityFlag.INVISIBLE, false);
|
||||
setFlag(EntityFlag.INVISIBLE, false);
|
||||
updateOffsetRequirement(false);
|
||||
if (positionUpdateRequired) {
|
||||
positionUpdateRequired = false;
|
||||
@ -297,13 +289,13 @@ public class ArmorStandEntity extends LivingEntity {
|
||||
}
|
||||
|
||||
if (secondEntity != null) {
|
||||
secondEntity.despawnEntity(session);
|
||||
secondEntity.despawnEntity();
|
||||
secondEntity = null;
|
||||
}
|
||||
return;
|
||||
}
|
||||
//boolean isNametagEmpty = metadata.getString(EntityData.NAMETAG).isEmpty() || metadata.getByte(EntityData.NAMETAG_ALWAYS_SHOW, (byte) -1) == (byte) 0; - may not be necessary?
|
||||
boolean isNametagEmpty = metadata.getString(EntityData.NAMETAG).isEmpty();
|
||||
boolean isNametagEmpty = dirtyMetadata.getString(EntityData.NAMETAG).isEmpty(); // TODO
|
||||
if (!isNametagEmpty && (!helmet.equals(ItemData.AIR) || !chestplate.equals(ItemData.AIR) || !leggings.equals(ItemData.AIR)
|
||||
|| !boots.equals(ItemData.AIR) || !hand.equals(ItemData.AIR) || !offHand.equals(ItemData.AIR))) {
|
||||
// If the second entity exists, no need to recreate it.
|
||||
@ -312,8 +304,8 @@ public class ArmorStandEntity extends LivingEntity {
|
||||
|
||||
// Create the second entity. It doesn't need to worry about the items, but it does need to worry about
|
||||
// the metadata as it will hold the name tag.
|
||||
secondEntity = new ArmorStandEntity(0, session.getEntityCache().getNextEntityId().incrementAndGet(),
|
||||
EntityType.ARMOR_STAND, position, motion, rotation);
|
||||
secondEntity = new ArmorStandEntity(session, 0, session.getEntityCache().getNextEntityId().incrementAndGet(), null,
|
||||
EntityDefinitions.ARMOR_STAND, position, motion, yaw, pitch, headYaw);
|
||||
secondEntity.primaryEntity = false;
|
||||
if (!this.positionRequiresOffset) {
|
||||
// Ensure the offset is applied for the 0 scale
|
||||
@ -321,52 +313,51 @@ public class ArmorStandEntity extends LivingEntity {
|
||||
}
|
||||
// Copy metadata
|
||||
secondEntity.isSmall = isSmall;
|
||||
secondEntity.getMetadata().putAll(metadata);
|
||||
// Copy the flags so they aren't the same object in memory
|
||||
secondEntity.getMetadata().putFlags(metadata.getFlags().copy());
|
||||
secondEntity.getDirtyMetadata().putAll(dirtyMetadata); //TODO check
|
||||
secondEntity.flags.merge(this.flags);
|
||||
// Guarantee this copy is NOT invisible
|
||||
secondEntity.getMetadata().getFlags().setFlag(EntityFlag.INVISIBLE, false);
|
||||
secondEntity.setFlag(EntityFlag.INVISIBLE, false);
|
||||
// Scale to 0 to show nametag
|
||||
secondEntity.getMetadata().put(EntityData.SCALE, 0.0f);
|
||||
secondEntity.getDirtyMetadata().put(EntityData.SCALE, 0.0f);
|
||||
// No bounding box as we don't want to interact with this entity
|
||||
secondEntity.getMetadata().put(EntityData.BOUNDING_BOX_WIDTH, 0.0f);
|
||||
secondEntity.getMetadata().put(EntityData.BOUNDING_BOX_HEIGHT, 0.0f);
|
||||
secondEntity.spawnEntity(session);
|
||||
secondEntity.getDirtyMetadata().put(EntityData.BOUNDING_BOX_WIDTH, 0.0f);
|
||||
secondEntity.getDirtyMetadata().put(EntityData.BOUNDING_BOX_HEIGHT, 0.0f);
|
||||
secondEntity.spawnEntity();
|
||||
|
||||
// Reset scale of the proper armor stand
|
||||
this.metadata.put(EntityData.SCALE, isSmall ? 0.55f : 1f);
|
||||
this.dirtyMetadata.put(EntityData.SCALE, isSmall ? 0.55f : 1f);
|
||||
// Set the proper armor stand to invisible to show armor
|
||||
this.metadata.getFlags().setFlag(EntityFlag.INVISIBLE, true);
|
||||
setFlag(EntityFlag.INVISIBLE, true);
|
||||
// Update the position of the armor stand
|
||||
updateOffsetRequirement(false);
|
||||
} else if (isNametagEmpty) {
|
||||
// We can just make an invisible entity
|
||||
// Reset scale of the proper armor stand
|
||||
metadata.put(EntityData.SCALE, isSmall ? 0.55f : 1f);
|
||||
dirtyMetadata.put(EntityData.SCALE, isSmall ? 0.55f : 1f);
|
||||
// Set the proper armor stand to invisible to show armor
|
||||
metadata.getFlags().setFlag(EntityFlag.INVISIBLE, true);
|
||||
setFlag(EntityFlag.INVISIBLE, true);
|
||||
// Update offset
|
||||
updateOffsetRequirement(false);
|
||||
|
||||
if (secondEntity != null) {
|
||||
secondEntity.despawnEntity(session);
|
||||
secondEntity.despawnEntity();
|
||||
secondEntity = null;
|
||||
}
|
||||
} else {
|
||||
// Nametag is not empty and there is no armor
|
||||
// We don't need to make a new entity
|
||||
metadata.getFlags().setFlag(EntityFlag.INVISIBLE, false);
|
||||
metadata.put(EntityData.SCALE, 0.0f);
|
||||
setFlag(EntityFlag.INVISIBLE, false);
|
||||
dirtyMetadata.put(EntityData.SCALE, 0.0f);
|
||||
// As the above is applied, we need an offset
|
||||
updateOffsetRequirement(true);
|
||||
|
||||
if (secondEntity != null) {
|
||||
secondEntity.despawnEntity(session);
|
||||
secondEntity.despawnEntity();
|
||||
secondEntity = null;
|
||||
}
|
||||
}
|
||||
if (sendMetadata) {
|
||||
this.updateBedrockMetadata(session);
|
||||
this.updateBedrockMetadata();
|
||||
}
|
||||
}
|
||||
|
||||
@ -385,16 +376,16 @@ public class ArmorStandEntity extends LivingEntity {
|
||||
* If this armor stand is not a marker, set its bounding box size and scale.
|
||||
*/
|
||||
private void toggleSmallStatus() {
|
||||
metadata.put(EntityData.BOUNDING_BOX_WIDTH, isSmall ? 0.25f : entityType.getWidth());
|
||||
metadata.put(EntityData.BOUNDING_BOX_HEIGHT, isSmall ? 0.9875f : entityType.getHeight());
|
||||
metadata.put(EntityData.SCALE, isSmall ? 0.55f : 1f);
|
||||
dirtyMetadata.put(EntityData.BOUNDING_BOX_WIDTH, isSmall ? 0.25f : definition.width());
|
||||
dirtyMetadata.put(EntityData.BOUNDING_BOX_HEIGHT, isSmall ? 0.9875f : definition.height());
|
||||
dirtyMetadata.put(EntityData.SCALE, isSmall ? 0.55f : 1f);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the selected position with the position offset applied.
|
||||
*/
|
||||
private Vector3f applyOffsetToPosition(Vector3f position) {
|
||||
return position.add(0d, entityType.getHeight() * (isSmall ? 0.55d : 1d), 0d);
|
||||
return position.add(0d, definition.height() * (isSmall ? 0.55d : 1d), 0d);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -402,14 +393,14 @@ public class ArmorStandEntity extends LivingEntity {
|
||||
*/
|
||||
private Vector3f fixOffsetForSize(Vector3f position, boolean isNowSmall) {
|
||||
position = removeOffsetFromPosition(position);
|
||||
return position.add(0d, entityType.getHeight() * (isNowSmall ? 0.55d : 1d), 0d);
|
||||
return position.add(0d, definition.height() * (isNowSmall ? 0.55d : 1d), 0d);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the selected position with the position offset removed.
|
||||
*/
|
||||
private Vector3f removeOffsetFromPosition(Vector3f position) {
|
||||
return position.sub(0d, entityType.getHeight() * (isSmall ? 0.55d : 1d), 0d);
|
||||
return position.sub(0d, definition.height() * (isSmall ? 0.55d : 1d), 0d);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -434,7 +425,7 @@ public class ArmorStandEntity extends LivingEntity {
|
||||
MoveEntityAbsolutePacket moveEntityPacket = new MoveEntityAbsolutePacket();
|
||||
moveEntityPacket.setRuntimeEntityId(geyserId);
|
||||
moveEntityPacket.setPosition(position);
|
||||
moveEntityPacket.setRotation(Vector3f.from(rotation.getX(), rotation.getX(), rotation.getX()));
|
||||
moveEntityPacket.setRotation(Vector3f.from(yaw, yaw, yaw));
|
||||
moveEntityPacket.setOnGround(onGround);
|
||||
moveEntityPacket.setTeleported(false);
|
||||
session.sendUpstreamPacket(moveEntityPacket);
|
||||
|
@ -26,23 +26,22 @@
|
||||
package org.geysermc.connector.entity.living;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
|
||||
import org.geysermc.connector.entity.type.EntityType;
|
||||
import org.geysermc.connector.entity.EntityDefinition;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class BatEntity extends AmbientEntity {
|
||||
|
||||
public BatEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
||||
super(entityId, geyserId, entityType, position, motion, rotation);
|
||||
public BatEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
|
||||
if (entityMetadata.getId() == 16) {
|
||||
byte xd = (byte) entityMetadata.getValue();
|
||||
metadata.getFlags().setFlag(EntityFlag.RESTING, (xd & 0x01) == 0x01);
|
||||
}
|
||||
super.updateBedrockMetadata(entityMetadata, session);
|
||||
public void setBatFlags(EntityMetadata<Byte> entityMetadata) {
|
||||
byte xd = ((ByteEntityMetadata) entityMetadata).getPrimitiveValue();
|
||||
setFlag(EntityFlag.RESTING, (xd & 0x01) == 0x01);
|
||||
}
|
||||
}
|
||||
|
@ -26,11 +26,14 @@
|
||||
package org.geysermc.connector.entity.living;
|
||||
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import org.geysermc.connector.entity.type.EntityType;
|
||||
import org.geysermc.connector.entity.EntityDefinition;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
|
||||
public class CreatureEntity extends InsentientEntity {
|
||||
import java.util.UUID;
|
||||
|
||||
public CreatureEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
||||
super(entityId, geyserId, entityType, position, motion, rotation);
|
||||
public class CreatureEntity extends MobEntity {
|
||||
|
||||
public CreatureEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
|
||||
}
|
||||
}
|
||||
|
@ -26,11 +26,14 @@
|
||||
package org.geysermc.connector.entity.living;
|
||||
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import org.geysermc.connector.entity.type.EntityType;
|
||||
import org.geysermc.connector.entity.EntityDefinition;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
|
||||
public class FlyingEntity extends InsentientEntity {
|
||||
import java.util.UUID;
|
||||
|
||||
public FlyingEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
||||
super(entityId, geyserId, entityType, position, motion, rotation);
|
||||
public class FlyingEntity extends MobEntity {
|
||||
|
||||
public FlyingEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
|
||||
}
|
||||
}
|
||||
|
@ -25,19 +25,14 @@
|
||||
|
||||
package org.geysermc.connector.entity.living;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import org.geysermc.connector.entity.type.EntityType;
|
||||
import org.geysermc.connector.entity.EntityDefinition;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
|
||||
public class GlowSquidEntity extends SquidEntity {
|
||||
public GlowSquidEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
||||
super(entityId, geyserId, entityType, position, motion, rotation);
|
||||
}
|
||||
import java.util.UUID;
|
||||
|
||||
@Override
|
||||
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
|
||||
super.updateBedrockMetadata(entityMetadata, session);
|
||||
// TODO "dark ticks remaining" ??? does this have a Bedrock equivalent?
|
||||
public class GlowSquidEntity extends SquidEntity {
|
||||
public GlowSquidEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
|
||||
}
|
||||
}
|
||||
|
@ -26,11 +26,14 @@
|
||||
package org.geysermc.connector.entity.living;
|
||||
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import org.geysermc.connector.entity.type.EntityType;
|
||||
import org.geysermc.connector.entity.EntityDefinition;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class GolemEntity extends CreatureEntity {
|
||||
|
||||
public GolemEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
||||
super(entityId, geyserId, entityType, position, motion, rotation);
|
||||
public GolemEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
|
||||
}
|
||||
}
|
||||
|
@ -28,15 +28,18 @@ package org.geysermc.connector.entity.living;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
|
||||
import org.geysermc.connector.entity.type.EntityType;
|
||||
import org.geysermc.connector.entity.EntityDefinition;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class IronGolemEntity extends GolemEntity {
|
||||
|
||||
public IronGolemEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
||||
super(entityId, geyserId, entityType, position, motion, rotation);
|
||||
public IronGolemEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
|
||||
// Indicate that we should show cracks through a resource pack
|
||||
metadata.getFlags().setFlag(EntityFlag.BRIBED, true);
|
||||
setFlag(EntityFlag.BRIBED, true);
|
||||
// Required, or else the overlay is black
|
||||
metadata.put(EntityData.COLOR_2, (byte) 0);
|
||||
dirtyMetadata.put(EntityData.COLOR_2, (byte) 0);
|
||||
}
|
||||
}
|
||||
|
@ -27,32 +27,34 @@ package org.geysermc.connector.entity.living;
|
||||
|
||||
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.EntityDefinition;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class MagmaCubeEntity extends SlimeEntity {
|
||||
|
||||
public MagmaCubeEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
||||
super(entityId, geyserId, entityType, position, motion, rotation);
|
||||
public MagmaCubeEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void moveRelative(GeyserSession session, double relX, double relY, double relZ, Vector3f rotation, boolean isOnGround) {
|
||||
updateJump(session, isOnGround);
|
||||
super.moveRelative(session, relX, relY, relZ, rotation, isOnGround);
|
||||
public void moveRelative(double relX, double relY, double relZ, float yaw, float pitch, float headYaw, boolean isOnGround) {
|
||||
updateJump(isOnGround);
|
||||
super.moveRelative(relX, relY, relZ, yaw, pitch, headYaw, isOnGround);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void moveAbsolute(GeyserSession session, Vector3f position, Vector3f rotation, boolean isOnGround, boolean teleported) {
|
||||
updateJump(session, isOnGround);
|
||||
super.moveAbsolute(session, position, rotation, isOnGround, teleported);
|
||||
public void moveAbsolute(Vector3f position, float yaw, float pitch, float headYaw, boolean isOnGround, boolean teleported) {
|
||||
updateJump(isOnGround);
|
||||
super.moveAbsolute(position, yaw, pitch, headYaw, isOnGround, teleported);
|
||||
}
|
||||
|
||||
public void updateJump(GeyserSession session, boolean newOnGround) {
|
||||
public void updateJump(boolean newOnGround) {
|
||||
if (newOnGround != onGround) {
|
||||
// Add the jumping effect to the magma cube
|
||||
metadata.put(EntityData.CLIENT_EVENT, (byte) (newOnGround ? 1 : 2));
|
||||
updateBedrockMetadata(session);
|
||||
dirtyMetadata.put(EntityData.CLIENT_EVENT, (byte) (newOnGround ? 1 : 2));
|
||||
updateBedrockMetadata();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2021 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.entity.living;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
|
||||
import lombok.Getter;
|
||||
import org.geysermc.connector.entity.EntityDefinition;
|
||||
import org.geysermc.connector.entity.LivingEntity;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class MobEntity extends LivingEntity {
|
||||
/**
|
||||
* If another mob is holding this mob by a leash, this variable tracks their Bedrock entity ID.
|
||||
*/
|
||||
@Getter
|
||||
private long leashHolderBedrockId;
|
||||
|
||||
public MobEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initializeMetadata() {
|
||||
super.initializeMetadata();
|
||||
setLeashHolderBedrockId(-1);
|
||||
}
|
||||
|
||||
public void setMobFlags(EntityMetadata<Byte> entityMetadata) {
|
||||
byte xd = ((ByteEntityMetadata) entityMetadata).getPrimitiveValue();
|
||||
setFlag(EntityFlag.NO_AI, (xd & 0x01) == 0x01);
|
||||
}
|
||||
|
||||
public void setLeashHolderBedrockId(long bedrockId) {
|
||||
this.leashHolderBedrockId = bedrockId;
|
||||
dirtyMetadata.put(EntityData.LEASH_HOLDER_EID, bedrockId);
|
||||
}
|
||||
}
|
@ -26,22 +26,21 @@
|
||||
package org.geysermc.connector.entity.living;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata;
|
||||
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.EntityDefinition;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
|
||||
public class SlimeEntity extends InsentientEntity {
|
||||
import java.util.UUID;
|
||||
|
||||
public SlimeEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
||||
super(entityId, geyserId, entityType, position, motion, rotation);
|
||||
public class SlimeEntity extends MobEntity {
|
||||
|
||||
public SlimeEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
|
||||
if (entityMetadata.getId() == 16) {
|
||||
this.metadata.put(EntityData.SCALE, 0.10f + (int) entityMetadata.getValue());
|
||||
}
|
||||
super.updateBedrockMetadata(entityMetadata, session);
|
||||
public void setScale(EntityMetadata<Integer> entityMetadata) {
|
||||
dirtyMetadata.put(EntityData.SCALE, 0.10f + ((IntEntityMetadata) entityMetadata).getPrimitiveValue());
|
||||
}
|
||||
}
|
||||
|
@ -26,24 +26,23 @@
|
||||
package org.geysermc.connector.entity.living;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
|
||||
import org.geysermc.connector.entity.type.EntityType;
|
||||
import org.geysermc.connector.entity.EntityDefinition;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class SnowGolemEntity extends GolemEntity {
|
||||
|
||||
public SnowGolemEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
||||
super(entityId, geyserId, entityType, position, motion, rotation);
|
||||
public SnowGolemEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
|
||||
if (entityMetadata.getId() == 16) {
|
||||
byte xd = (byte) entityMetadata.getValue();
|
||||
public void setSnowGolemFlags(EntityMetadata<Byte> entityMetadata) {
|
||||
byte xd = ((ByteEntityMetadata) entityMetadata).getPrimitiveValue();
|
||||
// Handle the visibility of the pumpkin
|
||||
metadata.getFlags().setFlag(EntityFlag.SHEARED, (xd & 0x10) != 0x10);
|
||||
}
|
||||
super.updateBedrockMetadata(entityMetadata, session);
|
||||
setFlag(EntityFlag.SHEARED, (xd & 0x10) != 0x10);
|
||||
}
|
||||
}
|
||||
|
@ -28,28 +28,25 @@ package org.geysermc.connector.entity.living;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
|
||||
import com.nukkitx.protocol.bedrock.packet.MoveEntityDeltaPacket;
|
||||
import org.geysermc.connector.entity.EntityDefinition;
|
||||
import org.geysermc.connector.entity.Tickable;
|
||||
import org.geysermc.connector.entity.type.EntityType;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
import org.geysermc.connector.network.translators.world.block.BlockStateValues;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class SquidEntity extends WaterEntity implements Tickable {
|
||||
|
||||
private float pitch;
|
||||
private float yaw;
|
||||
|
||||
private float targetPitch;
|
||||
private float targetYaw;
|
||||
|
||||
private boolean inWater;
|
||||
|
||||
public SquidEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
||||
super(entityId, geyserId, entityType, position, motion, rotation);
|
||||
this.yaw = rotation.getX();
|
||||
public SquidEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick(GeyserSession session) {
|
||||
public void tick() {
|
||||
boolean pitchChanged;
|
||||
boolean yawChanged;
|
||||
float oldPitch = pitch;
|
||||
@ -82,25 +79,33 @@ public class SquidEntity extends WaterEntity implements Tickable {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void moveRelative(GeyserSession session, double relX, double relY, double relZ, Vector3f rotation, boolean isOnGround) {
|
||||
super.moveRelative(session, relX, relY, relZ, rotation, isOnGround);
|
||||
checkInWater(session);
|
||||
public void moveRelative(double relX, double relY, double relZ, float yaw, float pitch, float headYaw, boolean isOnGround) {
|
||||
super.moveRelative(relX, relY, relZ, yaw, pitch, headYaw, isOnGround);
|
||||
checkInWater();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void moveAbsolute(GeyserSession session, Vector3f position, Vector3f rotation, boolean isOnGround, boolean teleported) {
|
||||
super.moveAbsolute(session, position, rotation, isOnGround, teleported);
|
||||
checkInWater(session);
|
||||
public void moveAbsolute(Vector3f position, float yaw, float pitch, float headYaw, boolean isOnGround, boolean teleported) {
|
||||
super.moveAbsolute(position, yaw, pitch, headYaw, isOnGround, teleported);
|
||||
checkInWater();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRotation(Vector3f rotation) {
|
||||
public void setYaw(float yaw) {
|
||||
// Let the Java server control yaw when the squid is out of water
|
||||
if (!inWater) {
|
||||
yaw = rotation.getX();
|
||||
this.yaw = yaw;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPitch(float pitch) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setHeadYaw(float headYaw) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMotion(Vector3f motion) {
|
||||
super.setMotion(motion);
|
||||
@ -115,8 +120,8 @@ public class SquidEntity extends WaterEntity implements Tickable {
|
||||
return Vector3f.from(pitch, yaw, yaw);
|
||||
}
|
||||
|
||||
private void checkInWater(GeyserSession session) {
|
||||
if (getMetadata().getFlags().getFlag(EntityFlag.RIDING)) {
|
||||
private void checkInWater() {
|
||||
if (getFlag(EntityFlag.RIDING)) {
|
||||
inWater = false;
|
||||
} else {
|
||||
int block = session.getConnector().getWorldManager().getBlockAt(session, position.toInt());
|
||||
|
@ -26,11 +26,14 @@
|
||||
package org.geysermc.connector.entity.living;
|
||||
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import org.geysermc.connector.entity.type.EntityType;
|
||||
import org.geysermc.connector.entity.EntityDefinition;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class WaterEntity extends CreatureEntity {
|
||||
|
||||
public WaterEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
||||
super(entityId, geyserId, entityType, position, motion, rotation);
|
||||
public WaterEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
|
||||
}
|
||||
}
|
||||
|
@ -26,15 +26,17 @@
|
||||
package org.geysermc.connector.entity.living.animal;
|
||||
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import org.geysermc.connector.entity.EntityDefinition;
|
||||
import org.geysermc.connector.entity.living.AgeableEntity;
|
||||
import org.geysermc.connector.entity.type.EntityType;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
import org.geysermc.connector.registry.type.ItemMapping;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class AnimalEntity extends AgeableEntity {
|
||||
|
||||
public AnimalEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
||||
super(entityId, geyserId, entityType, position, motion, rotation);
|
||||
public AnimalEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -26,32 +26,33 @@
|
||||
package org.geysermc.connector.entity.living.animal;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanEntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
|
||||
import org.geysermc.connector.entity.type.EntityType;
|
||||
import org.geysermc.connector.entity.EntityDefinition;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
import org.geysermc.connector.registry.type.ItemMapping;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class AxolotlEntity extends AnimalEntity {
|
||||
public AxolotlEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
||||
super(entityId, geyserId, entityType, position, motion, rotation);
|
||||
public AxolotlEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
|
||||
super.updateBedrockMetadata(entityMetadata, session);
|
||||
if (entityMetadata.getId() == 17) {
|
||||
int variant = (int) entityMetadata.getValue();
|
||||
public void setVariant(EntityMetadata<Integer> entityMetadata) {
|
||||
int variant = ((IntEntityMetadata) entityMetadata).getPrimitiveValue();
|
||||
switch (variant) {
|
||||
case 1 -> variant = 3; // Java - "Wild" (brown)
|
||||
case 3 -> variant = 1; // Java - cyan
|
||||
}
|
||||
metadata.put(EntityData.VARIANT, variant);
|
||||
}
|
||||
else if (entityMetadata.getId() == 18) {
|
||||
metadata.getFlags().setFlag(EntityFlag.PLAYING_DEAD, (boolean) entityMetadata.getValue());
|
||||
dirtyMetadata.put(EntityData.VARIANT, variant);
|
||||
}
|
||||
|
||||
public void setPlayingDead(EntityMetadata<Boolean> entityMetadata) {
|
||||
setFlag(EntityFlag.PLAYING_DEAD, ((BooleanEntityMetadata) entityMetadata).getPrimitiveValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -26,25 +26,27 @@
|
||||
package org.geysermc.connector.entity.living.animal;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityEventType;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
|
||||
import com.nukkitx.protocol.bedrock.packet.EntityEventPacket;
|
||||
import org.geysermc.connector.entity.type.EntityType;
|
||||
import org.geysermc.connector.entity.EntityDefinition;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
import org.geysermc.connector.registry.type.ItemMapping;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class BeeEntity extends AnimalEntity {
|
||||
|
||||
public BeeEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
||||
super(entityId, geyserId, entityType, position, motion, rotation);
|
||||
public BeeEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
|
||||
if (entityMetadata.getId() == 17) {
|
||||
byte xd = (byte) entityMetadata.getValue();
|
||||
public void setBeeFlags(EntityMetadata<Byte> entityMetadata) {
|
||||
byte xd = ((ByteEntityMetadata) entityMetadata).getPrimitiveValue();
|
||||
// Bee is performing sting attack; trigger animation
|
||||
if ((xd & 0x02) == 0x02) {
|
||||
EntityEventPacket packet = new EntityEventPacket();
|
||||
@ -54,15 +56,14 @@ public class BeeEntity extends AnimalEntity {
|
||||
session.sendUpstreamPacket(packet);
|
||||
}
|
||||
// If the bee has stung
|
||||
metadata.put(EntityData.MARK_VARIANT, (xd & 0x04) == 0x04 ? 1 : 0);
|
||||
dirtyMetadata.put(EntityData.MARK_VARIANT, (xd & 0x04) == 0x04 ? 1 : 0);
|
||||
// If the bee has nectar or not
|
||||
metadata.getFlags().setFlag(EntityFlag.POWERED, (xd & 0x08) == 0x08);
|
||||
setFlag(EntityFlag.POWERED, (xd & 0x08) == 0x08);
|
||||
}
|
||||
if (entityMetadata.getId() == 18) {
|
||||
|
||||
public void setAngerTime(EntityMetadata<Integer> entityMetadata) {
|
||||
// Converting "anger time" to a boolean
|
||||
metadata.getFlags().setFlag(EntityFlag.ANGRY, (int) entityMetadata.getValue() > 0);
|
||||
}
|
||||
super.updateBedrockMetadata(entityMetadata, session);
|
||||
setFlag(EntityFlag.ANGRY, ((IntEntityMetadata) entityMetadata).getPrimitiveValue() > 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -26,14 +26,16 @@
|
||||
package org.geysermc.connector.entity.living.animal;
|
||||
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import org.geysermc.connector.entity.type.EntityType;
|
||||
import org.geysermc.connector.entity.EntityDefinition;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
import org.geysermc.connector.registry.type.ItemMapping;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class ChickenEntity extends AnimalEntity {
|
||||
|
||||
public ChickenEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
||||
super(entityId, geyserId, entityType, position, motion, rotation);
|
||||
public ChickenEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -26,32 +26,32 @@
|
||||
package org.geysermc.connector.entity.living.animal;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
|
||||
import org.geysermc.connector.entity.type.EntityType;
|
||||
import org.geysermc.connector.entity.EntityDefinition;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
import org.geysermc.connector.registry.type.ItemMapping;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class FoxEntity extends AnimalEntity {
|
||||
|
||||
public FoxEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
||||
super(entityId, geyserId, entityType, position, motion, rotation);
|
||||
public FoxEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
|
||||
if (entityMetadata.getId() == 17) {
|
||||
metadata.put(EntityData.VARIANT, entityMetadata.getValue());
|
||||
public void setFoxVariant(EntityMetadata<Integer> entityMetadata) {
|
||||
dirtyMetadata.put(EntityData.VARIANT, entityMetadata.getValue());
|
||||
}
|
||||
if (entityMetadata.getId() == 18) {
|
||||
byte xd = (byte) entityMetadata.getValue();
|
||||
metadata.getFlags().setFlag(EntityFlag.SITTING, (xd & 0x01) == 0x01);
|
||||
metadata.getFlags().setFlag(EntityFlag.SNEAKING, (xd & 0x04) == 0x04);
|
||||
metadata.getFlags().setFlag(EntityFlag.INTERESTED, (xd & 0x08) == 0x08);
|
||||
metadata.getFlags().setFlag(EntityFlag.SLEEPING, (xd & 0x20) == 0x20);
|
||||
}
|
||||
super.updateBedrockMetadata(entityMetadata, session);
|
||||
|
||||
public void setFoxFlags(EntityMetadata<Byte> entityMetadata) {
|
||||
byte xd = ((ByteEntityMetadata) entityMetadata).getPrimitiveValue();
|
||||
setFlag(EntityFlag.SITTING, (xd & 0x01) == 0x01);
|
||||
setFlag(EntityFlag.SNEAKING, (xd & 0x04) == 0x04);
|
||||
setFlag(EntityFlag.INTERESTED, (xd & 0x08) == 0x08);
|
||||
setFlag(EntityFlag.SLEEPING, (xd & 0x20) == 0x20);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -27,12 +27,15 @@ package org.geysermc.connector.entity.living.animal;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.Pose;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanEntityMetadata;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
|
||||
import lombok.Getter;
|
||||
import org.geysermc.connector.entity.type.EntityType;
|
||||
import org.geysermc.connector.entity.EntityDefinition;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class GoatEntity extends AnimalEntity {
|
||||
private static final float LONG_JUMPING_HEIGHT = 1.3f * 0.7f;
|
||||
private static final float LONG_JUMPING_WIDTH = 0.9f * 0.7f;
|
||||
@ -40,24 +43,20 @@ public class GoatEntity extends AnimalEntity {
|
||||
@Getter
|
||||
private boolean isScreamer;
|
||||
|
||||
public GoatEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
||||
super(entityId, geyserId, entityType, position, motion, rotation);
|
||||
public GoatEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
|
||||
super.updateBedrockMetadata(entityMetadata, session);
|
||||
if (entityMetadata.getId() == 17) {
|
||||
// Not used in Bedrock Edition
|
||||
isScreamer = (boolean) entityMetadata.getValue();
|
||||
}
|
||||
public void setScreamer(EntityMetadata<Boolean> entityMetadata) {
|
||||
// Metadata not used in Bedrock Edition
|
||||
isScreamer = ((BooleanEntityMetadata) entityMetadata).getPrimitiveValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setDimensions(Pose pose) {
|
||||
if (pose == Pose.LONG_JUMPING) {
|
||||
metadata.put(EntityData.BOUNDING_BOX_WIDTH, LONG_JUMPING_WIDTH);
|
||||
metadata.put(EntityData.BOUNDING_BOX_HEIGHT, LONG_JUMPING_HEIGHT);
|
||||
dirtyMetadata.put(EntityData.BOUNDING_BOX_WIDTH, LONG_JUMPING_WIDTH);
|
||||
dirtyMetadata.put(EntityData.BOUNDING_BOX_HEIGHT, LONG_JUMPING_HEIGHT);
|
||||
} else {
|
||||
super.setDimensions(pose);
|
||||
}
|
||||
|
@ -26,34 +26,32 @@
|
||||
package org.geysermc.connector.entity.living.animal;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanEntityMetadata;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
|
||||
import org.geysermc.connector.entity.type.EntityType;
|
||||
import org.geysermc.connector.entity.EntityDefinition;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
import org.geysermc.connector.registry.type.ItemMapping;
|
||||
import org.geysermc.connector.utils.DimensionUtils;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class HoglinEntity extends AnimalEntity {
|
||||
private boolean isImmuneToZombification;
|
||||
|
||||
public HoglinEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
||||
super(entityId, geyserId, entityType, position, motion, rotation);
|
||||
public HoglinEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
|
||||
if (entityMetadata.getId() == 17) {
|
||||
// Immune to zombification?
|
||||
public void setImmuneToZombification(EntityMetadata<Boolean> entityMetadata) {
|
||||
// Apply shaking effect if not in the nether and zombification is possible
|
||||
this.isImmuneToZombification = (boolean) entityMetadata.getValue();
|
||||
metadata.getFlags().setFlag(EntityFlag.SHAKING, isShaking(session));
|
||||
}
|
||||
super.updateBedrockMetadata(entityMetadata, session);
|
||||
this.isImmuneToZombification = ((BooleanEntityMetadata) entityMetadata).getPrimitiveValue();
|
||||
setFlag(EntityFlag.SHAKING, isShaking());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isShaking(GeyserSession session) {
|
||||
return (!isImmuneToZombification && !session.getDimension().equals(DimensionUtils.NETHER)) || super.isShaking(session);
|
||||
protected boolean isShaking() {
|
||||
return (!isImmuneToZombification && !session.getDimension().equals(DimensionUtils.NETHER)) || super.isShaking();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -25,23 +25,15 @@
|
||||
|
||||
package org.geysermc.connector.entity.living.animal;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
|
||||
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.EntityDefinition;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class MooshroomEntity extends AnimalEntity {
|
||||
|
||||
public MooshroomEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
||||
super(entityId, geyserId, entityType, position, motion, rotation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
|
||||
if (entityMetadata.getId() == 17) {
|
||||
metadata.put(EntityData.VARIANT, entityMetadata.getValue().equals("brown") ? 1 : 0);
|
||||
}
|
||||
super.updateBedrockMetadata(entityMetadata, session);
|
||||
public MooshroomEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
|
||||
}
|
||||
}
|
||||
|
@ -25,25 +25,17 @@
|
||||
|
||||
package org.geysermc.connector.entity.living.animal;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
|
||||
import org.geysermc.connector.entity.type.EntityType;
|
||||
import org.geysermc.connector.entity.EntityDefinition;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
import org.geysermc.connector.registry.type.ItemMapping;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class OcelotEntity extends AnimalEntity {
|
||||
|
||||
public OcelotEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
||||
super(entityId, geyserId, entityType, position, motion, rotation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
|
||||
if (entityMetadata.getId() == 17) {
|
||||
metadata.getFlags().setFlag(EntityFlag.TRUSTING, (boolean) entityMetadata.getValue());
|
||||
}
|
||||
super.updateBedrockMetadata(entityMetadata, session);
|
||||
public OcelotEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -26,30 +26,32 @@
|
||||
package org.geysermc.connector.entity.living.animal;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityEventType;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
|
||||
import com.nukkitx.protocol.bedrock.packet.EntityEventPacket;
|
||||
import org.geysermc.connector.entity.type.EntityType;
|
||||
import org.geysermc.connector.entity.EntityDefinition;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
import org.geysermc.connector.registry.type.ItemMapping;
|
||||
|
||||
public class PandaEntity extends AnimalEntity {
|
||||
import java.util.UUID;
|
||||
|
||||
public class PandaEntity extends AnimalEntity {
|
||||
private int mainGene;
|
||||
private int hiddenGene;
|
||||
|
||||
public PandaEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
||||
super(entityId, geyserId, entityType, position, motion, rotation);
|
||||
public PandaEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
|
||||
if (entityMetadata.getId() == 19) {
|
||||
metadata.getFlags().setFlag(EntityFlag.EATING, (int) entityMetadata.getValue() > 0);
|
||||
metadata.put(EntityData.EATING_COUNTER, entityMetadata.getValue());
|
||||
if ((int) entityMetadata.getValue() != 0) {
|
||||
public void setEatingCounter(EntityMetadata<Integer> entityMetadata) {
|
||||
int count = ((IntEntityMetadata) entityMetadata).getPrimitiveValue();
|
||||
setFlag(EntityFlag.EATING, count > 0);
|
||||
dirtyMetadata.put(EntityData.EATING_COUNTER, count);
|
||||
if (count != 0) {
|
||||
// Particles and sound
|
||||
EntityEventPacket packet = new EntityEventPacket();
|
||||
packet.setRuntimeEntityId(geyserId);
|
||||
@ -58,25 +60,26 @@ public class PandaEntity extends AnimalEntity {
|
||||
session.sendUpstreamPacket(packet);
|
||||
}
|
||||
}
|
||||
if (entityMetadata.getId() == 20) {
|
||||
mainGene = (int) (byte) entityMetadata.getValue();
|
||||
|
||||
public void setMainGene(EntityMetadata<Byte> entityMetadata) {
|
||||
mainGene = ((ByteEntityMetadata) entityMetadata).getPrimitiveValue();
|
||||
updateAppearance();
|
||||
}
|
||||
if (entityMetadata.getId() == 21) {
|
||||
hiddenGene = (int) (byte) entityMetadata.getValue();
|
||||
|
||||
public void setHiddenGene(EntityMetadata<Byte> entityMetadata) {
|
||||
hiddenGene = ((ByteEntityMetadata) entityMetadata).getPrimitiveValue();
|
||||
updateAppearance();
|
||||
}
|
||||
if (entityMetadata.getId() == 22) {
|
||||
byte xd = (byte) entityMetadata.getValue();
|
||||
metadata.getFlags().setFlag(EntityFlag.SNEEZING, (xd & 0x02) == 0x02);
|
||||
metadata.getFlags().setFlag(EntityFlag.ROLLING, (xd & 0x04) == 0x04);
|
||||
metadata.getFlags().setFlag(EntityFlag.SITTING, (xd & 0x08) == 0x08);
|
||||
|
||||
public void setPandaFlags(EntityMetadata<Byte> entityMetadata) {
|
||||
byte xd = ((ByteEntityMetadata) entityMetadata).getPrimitiveValue();
|
||||
setFlag(EntityFlag.SNEEZING, (xd & 0x02) == 0x02);
|
||||
setFlag(EntityFlag.ROLLING, (xd & 0x04) == 0x04);
|
||||
setFlag(EntityFlag.SITTING, (xd & 0x08) == 0x08);
|
||||
// Required to put these both for sitting to actually show
|
||||
metadata.put(EntityData.SITTING_AMOUNT, (xd & 0x08) == 0x08 ? 1f : 0f);
|
||||
metadata.put(EntityData.SITTING_AMOUNT_PREVIOUS, (xd & 0x08) == 0x08 ? 1f : 0f);
|
||||
metadata.getFlags().setFlag(EntityFlag.LAYING_DOWN, (xd & 0x10) == 0x10);
|
||||
}
|
||||
super.updateBedrockMetadata(entityMetadata, session);
|
||||
dirtyMetadata.put(EntityData.SITTING_AMOUNT, (xd & 0x08) == 0x08 ? 1f : 0f);
|
||||
dirtyMetadata.put(EntityData.SITTING_AMOUNT_PREVIOUS, (xd & 0x08) == 0x08 ? 1f : 0f);
|
||||
setFlag(EntityFlag.LAYING_DOWN, (xd & 0x10) == 0x10);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -93,14 +96,14 @@ public class PandaEntity extends AnimalEntity {
|
||||
// Main gene is a recessive trait
|
||||
if (mainGene == hiddenGene) {
|
||||
// Main and hidden genes match; this is what the panda looks like.
|
||||
metadata.put(EntityData.VARIANT, mainGene);
|
||||
dirtyMetadata.put(EntityData.VARIANT, mainGene);
|
||||
} else {
|
||||
// Genes have no effect on appearance
|
||||
metadata.put(EntityData.VARIANT, 0);
|
||||
dirtyMetadata.put(EntityData.VARIANT, 0);
|
||||
}
|
||||
} else {
|
||||
// No need to worry about hidden gene
|
||||
metadata.put(EntityData.VARIANT, mainGene);
|
||||
dirtyMetadata.put(EntityData.VARIANT, mainGene);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -25,25 +25,17 @@
|
||||
|
||||
package org.geysermc.connector.entity.living.animal;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
|
||||
import org.geysermc.connector.entity.type.EntityType;
|
||||
import org.geysermc.connector.entity.EntityDefinition;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
import org.geysermc.connector.registry.type.ItemMapping;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class PigEntity extends AnimalEntity {
|
||||
|
||||
public PigEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
||||
super(entityId, geyserId, entityType, position, motion, rotation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
|
||||
if (entityMetadata.getId() == 17) {
|
||||
metadata.getFlags().setFlag(EntityFlag.SADDLED, (boolean) entityMetadata.getValue());
|
||||
}
|
||||
super.updateBedrockMetadata(entityMetadata, session);
|
||||
public PigEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -25,25 +25,17 @@
|
||||
|
||||
package org.geysermc.connector.entity.living.animal;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
|
||||
import org.geysermc.connector.entity.type.EntityType;
|
||||
import org.geysermc.connector.entity.EntityDefinition;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
import org.geysermc.connector.registry.type.ItemMapping;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class PolarBearEntity extends AnimalEntity {
|
||||
|
||||
public PolarBearEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
||||
super(entityId, geyserId, entityType, position, motion, rotation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
|
||||
if (entityMetadata.getId() == 17) {
|
||||
metadata.getFlags().setFlag(EntityFlag.STANDING, (boolean) entityMetadata.getValue());
|
||||
}
|
||||
super.updateBedrockMetadata(entityMetadata, session);
|
||||
public PolarBearEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -26,25 +26,24 @@
|
||||
package org.geysermc.connector.entity.living.animal;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
|
||||
import org.geysermc.connector.entity.EntityDefinition;
|
||||
import org.geysermc.connector.entity.living.AbstractFishEntity;
|
||||
import org.geysermc.connector.entity.type.EntityType;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class PufferFishEntity extends AbstractFishEntity {
|
||||
|
||||
public PufferFishEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
||||
super(entityId, geyserId, entityType, position, motion, rotation);
|
||||
public PufferFishEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
|
||||
if (entityMetadata.getId() == 17) {
|
||||
int puffsize = (int) entityMetadata.getValue();
|
||||
metadata.put(EntityData.PUFFERFISH_SIZE, (byte) puffsize);
|
||||
metadata.put(EntityData.VARIANT, puffsize);
|
||||
}
|
||||
super.updateBedrockMetadata(entityMetadata, session);
|
||||
public void setPufferfishSize(EntityMetadata<Integer> entityMetadata) {
|
||||
int puffsize = ((IntEntityMetadata) entityMetadata).getPrimitiveValue();
|
||||
dirtyMetadata.put(EntityData.PUFFERFISH_SIZE, (byte) puffsize);
|
||||
dirtyMetadata.put(EntityData.VARIANT, puffsize);
|
||||
}
|
||||
}
|
||||
|
@ -26,31 +26,29 @@
|
||||
package org.geysermc.connector.entity.living.animal;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
|
||||
import org.geysermc.connector.entity.type.EntityType;
|
||||
import org.geysermc.connector.entity.EntityDefinition;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
import org.geysermc.connector.registry.type.ItemMapping;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class RabbitEntity extends AnimalEntity {
|
||||
|
||||
public RabbitEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
||||
super(entityId, geyserId, entityType, position, motion, rotation);
|
||||
public RabbitEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
|
||||
super.updateBedrockMetadata(entityMetadata, session);
|
||||
if (entityMetadata.getId() == 16) {
|
||||
metadata.put(EntityData.SCALE, .55f);
|
||||
boolean isBaby = (boolean) entityMetadata.getValue();
|
||||
if (isBaby) {
|
||||
metadata.put(EntityData.SCALE, .35f);
|
||||
metadata.getFlags().setFlag(EntityFlag.BABY, true);
|
||||
public void setBaby(EntityMetadata<Boolean> entityMetadata) {
|
||||
super.setBaby(entityMetadata);
|
||||
}
|
||||
} else if (entityMetadata.getId() == 17) {
|
||||
int variant = (int) entityMetadata.getValue();
|
||||
|
||||
public void setRabbitVariant(EntityMetadata<Integer> entityMetadata) {
|
||||
int variant = ((IntEntityMetadata) entityMetadata).getPrimitiveValue();
|
||||
|
||||
// Change the killer bunny to display as white since it only exists on Java Edition
|
||||
boolean isKillerBunny = variant == 99;
|
||||
@ -58,10 +56,19 @@ public class RabbitEntity extends AnimalEntity {
|
||||
variant = 1;
|
||||
}
|
||||
// Allow the resource pack to adjust to the killer bunny
|
||||
metadata.getFlags().setFlag(EntityFlag.BRIBED, isKillerBunny);
|
||||
setFlag(EntityFlag.BRIBED, isKillerBunny);
|
||||
|
||||
metadata.put(EntityData.VARIANT, variant);
|
||||
dirtyMetadata.put(EntityData.VARIANT, variant);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected float getAdultSize() {
|
||||
return 0.55f;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected float getBabySize() {
|
||||
return 0.35f;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -26,26 +26,24 @@
|
||||
package org.geysermc.connector.entity.living.animal;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
|
||||
import org.geysermc.connector.entity.type.EntityType;
|
||||
import org.geysermc.connector.entity.EntityDefinition;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class SheepEntity extends AnimalEntity {
|
||||
|
||||
public SheepEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
||||
super(entityId, geyserId, entityType, position, motion, rotation);
|
||||
public SheepEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
|
||||
if (entityMetadata.getId() == 17) {
|
||||
byte xd = (byte) entityMetadata.getValue();
|
||||
metadata.getFlags().setFlag(EntityFlag.SHEARED, (xd & 0x10) == 0x10);
|
||||
metadata.put(EntityData.COLOR, xd);
|
||||
}
|
||||
|
||||
super.updateBedrockMetadata(entityMetadata, session);
|
||||
public void setSheepFlags(EntityMetadata<Byte> entityMetadata) {
|
||||
byte xd = ((ByteEntityMetadata) entityMetadata).getPrimitiveValue();
|
||||
setFlag(EntityFlag.SHEARED, (xd & 0x10) == 0x10);
|
||||
dirtyMetadata.put(EntityData.COLOR, xd);
|
||||
}
|
||||
}
|
@ -26,70 +26,70 @@
|
||||
package org.geysermc.connector.entity.living.animal;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanEntityMetadata;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
|
||||
import org.geysermc.connector.entity.Entity;
|
||||
import org.geysermc.connector.entity.type.EntityType;
|
||||
import org.geysermc.connector.entity.EntityDefinition;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
import org.geysermc.connector.registry.type.ItemMapping;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class StriderEntity extends AnimalEntity {
|
||||
|
||||
private boolean isCold = false;
|
||||
|
||||
public StriderEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
||||
super(entityId, geyserId, entityType, position, motion, rotation);
|
||||
public StriderEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
|
||||
|
||||
metadata.getFlags().setFlag(EntityFlag.FIRE_IMMUNE, true);
|
||||
metadata.getFlags().setFlag(EntityFlag.BREATHING, true);
|
||||
setFlag(EntityFlag.FIRE_IMMUNE, true);
|
||||
setFlag(EntityFlag.BREATHING, true);
|
||||
}
|
||||
|
||||
public void setCold(EntityMetadata<Boolean> entityMetadata) {
|
||||
isCold = ((BooleanEntityMetadata) entityMetadata).getPrimitiveValue();
|
||||
}
|
||||
|
||||
public void setSaddled(EntityMetadata<Boolean> entityMetadata) {
|
||||
setFlag(EntityFlag.SADDLED, ((BooleanEntityMetadata) entityMetadata).getPrimitiveValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
|
||||
if (entityMetadata.getId() == 18) {
|
||||
isCold = (boolean) entityMetadata.getValue();
|
||||
}
|
||||
if (entityMetadata.getId() == 19) {
|
||||
metadata.getFlags().setFlag(EntityFlag.SADDLED, (boolean) entityMetadata.getValue());
|
||||
}
|
||||
|
||||
super.updateBedrockMetadata(entityMetadata, session);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateBedrockMetadata(GeyserSession session) {
|
||||
public void updateBedrockMetadata() {
|
||||
// Make sure they are not shaking when riding another entity
|
||||
// Needs to copy the parent state
|
||||
if (metadata.getFlags().getFlag(EntityFlag.RIDING)) {
|
||||
if (getFlag(EntityFlag.RIDING)) {
|
||||
boolean parentShaking = false;
|
||||
//TODO optimize
|
||||
for (Entity ent : session.getEntityCache().getEntities().values()) {
|
||||
if (ent.getPassengers().contains(entityId) && ent instanceof StriderEntity) {
|
||||
parentShaking = ent.getMetadata().getFlags().getFlag(EntityFlag.SHAKING);
|
||||
parentShaking = ent.getFlag(EntityFlag.SHAKING);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
metadata.getFlags().setFlag(EntityFlag.BREATHING, !parentShaking);
|
||||
metadata.getFlags().setFlag(EntityFlag.SHAKING, parentShaking);
|
||||
setFlag(EntityFlag.BREATHING, !parentShaking);
|
||||
setFlag(EntityFlag.SHAKING, parentShaking);
|
||||
} else {
|
||||
metadata.getFlags().setFlag(EntityFlag.BREATHING, !isCold);
|
||||
metadata.getFlags().setFlag(EntityFlag.SHAKING, isShaking(session));
|
||||
setFlag(EntityFlag.BREATHING, !isCold);
|
||||
setFlag(EntityFlag.SHAKING, isShaking());
|
||||
}
|
||||
|
||||
// Update the passengers if we have any
|
||||
for (long passenger : passengers) {
|
||||
Entity passengerEntity = session.getEntityCache().getEntityByJavaId(passenger);
|
||||
if (passengerEntity != null) {
|
||||
passengerEntity.updateBedrockMetadata(session);
|
||||
passengerEntity.updateBedrockMetadata();
|
||||
}
|
||||
}
|
||||
|
||||
super.updateBedrockMetadata(session);
|
||||
super.updateBedrockMetadata();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isShaking(GeyserSession session) {
|
||||
return isCold || super.isShaking(session);
|
||||
protected boolean isShaking() {
|
||||
return isCold || super.isShaking();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -26,15 +26,17 @@
|
||||
package org.geysermc.connector.entity.living.animal;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
|
||||
import it.unimi.dsi.fastutil.ints.IntList;
|
||||
import org.geysermc.connector.entity.EntityDefinition;
|
||||
import org.geysermc.connector.entity.living.AbstractFishEntity;
|
||||
import org.geysermc.connector.entity.type.EntityType;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
public class TropicalFishEntity extends AbstractFishEntity {
|
||||
|
||||
@ -47,21 +49,17 @@ public class TropicalFishEntity extends AbstractFishEntity {
|
||||
private static final List<String> VARIANT_NAMES = ImmutableList.of("kob", "sunstreak", "snooper", "dasher", "brinely", "spotty", "flopper", "stripey", "glitter", "blockfish", "betty", "clayfish");
|
||||
private static final List<String> COLOR_NAMES = ImmutableList.of("white", "orange", "magenta", "light_blue", "yellow", "lime", "pink", "gray", "light_gray", "cyan", "purple", "blue", "brown", "green", "red", "black");
|
||||
|
||||
public TropicalFishEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
||||
super(entityId, geyserId, entityType, position, motion, rotation);
|
||||
public TropicalFishEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
|
||||
if (entityMetadata.getId() == 17) {
|
||||
int varNumber = (int) entityMetadata.getValue();
|
||||
public void setFishVariant(EntityMetadata<Integer> entityMetadata) {
|
||||
int varNumber = ((IntEntityMetadata) entityMetadata).getPrimitiveValue();
|
||||
|
||||
metadata.put(EntityData.VARIANT, getShape(varNumber)); // Shape 0-1
|
||||
metadata.put(EntityData.MARK_VARIANT, getPattern(varNumber)); // Pattern 0-5
|
||||
metadata.put(EntityData.COLOR, getBaseColor(varNumber)); // Base color 0-15
|
||||
metadata.put(EntityData.COLOR_2, getPatternColor(varNumber)); // Pattern color 0-15
|
||||
}
|
||||
super.updateBedrockMetadata(entityMetadata, session);
|
||||
dirtyMetadata.put(EntityData.VARIANT, getShape(varNumber)); // Shape 0-1
|
||||
dirtyMetadata.put(EntityData.MARK_VARIANT, getPattern(varNumber)); // Pattern 0-5
|
||||
dirtyMetadata.put(EntityData.COLOR, getBaseColor(varNumber)); // Base color 0-15
|
||||
dirtyMetadata.put(EntityData.COLOR_2, getPatternColor(varNumber)); // Pattern color 0-15
|
||||
}
|
||||
|
||||
public static int getShape(int variant) {
|
||||
|
@ -26,26 +26,27 @@
|
||||
package org.geysermc.connector.entity.living.animal;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanEntityMetadata;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
|
||||
import org.geysermc.connector.entity.type.EntityType;
|
||||
import org.geysermc.connector.entity.EntityDefinition;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
import org.geysermc.connector.registry.type.ItemMapping;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class TurtleEntity extends AnimalEntity {
|
||||
|
||||
public TurtleEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
||||
super(entityId, geyserId, entityType, position, motion, rotation);
|
||||
public TurtleEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
|
||||
if (entityMetadata.getId() == 18) {
|
||||
metadata.getFlags().setFlag(EntityFlag.IS_PREGNANT, (boolean) entityMetadata.getValue());
|
||||
} else if (entityMetadata.getId() == 19) {
|
||||
metadata.getFlags().setFlag(EntityFlag.LAYING_EGG, (boolean) entityMetadata.getValue());
|
||||
public void setPregnant(EntityMetadata<Boolean> entityMetadata) {
|
||||
setFlag(EntityFlag.IS_PREGNANT, ((BooleanEntityMetadata) entityMetadata).getPrimitiveValue());
|
||||
}
|
||||
super.updateBedrockMetadata(entityMetadata, session);
|
||||
|
||||
public void setLayingEgg(EntityMetadata<Boolean> entityMetadata) {
|
||||
setFlag(EntityFlag.LAYING_EGG, ((BooleanEntityMetadata) entityMetadata).getPrimitiveValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -26,6 +26,7 @@
|
||||
package org.geysermc.connector.entity.living.animal.horse;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
|
||||
@ -34,13 +35,14 @@ import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
|
||||
import com.nukkitx.protocol.bedrock.data.inventory.ContainerType;
|
||||
import com.nukkitx.protocol.bedrock.packet.EntityEventPacket;
|
||||
import com.nukkitx.protocol.bedrock.packet.UpdateAttributesPacket;
|
||||
import org.geysermc.connector.entity.EntityDefinition;
|
||||
import org.geysermc.connector.entity.attribute.GeyserAttributeType;
|
||||
import org.geysermc.connector.entity.living.animal.AnimalEntity;
|
||||
import org.geysermc.connector.entity.type.EntityType;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
import org.geysermc.connector.registry.type.ItemMapping;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
public class AbstractHorseEntity extends AnimalEntity {
|
||||
/**
|
||||
@ -50,18 +52,22 @@ public class AbstractHorseEntity extends AnimalEntity {
|
||||
private static final Set<String> DONKEY_AND_HORSE_FOODS = ImmutableSet.of("golden_apple", "enchanted_golden_apple",
|
||||
"golden_carrot", "sugar", "apple", "wheat", "hay_block");
|
||||
|
||||
public AbstractHorseEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
||||
super(entityId, geyserId, entityType, position, motion, rotation);
|
||||
public AbstractHorseEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
|
||||
|
||||
// Specifies the size of the entity's inventory. Required to place slots in the entity.
|
||||
metadata.put(EntityData.CONTAINER_BASE_SIZE, 2);
|
||||
dirtyMetadata.put(EntityData.CONTAINER_BASE_SIZE, getContainerBaseSize());
|
||||
|
||||
metadata.getFlags().setFlag(EntityFlag.WASD_CONTROLLED, true);
|
||||
setFlag(EntityFlag.WASD_CONTROLLED, true);
|
||||
}
|
||||
|
||||
protected int getContainerBaseSize() {
|
||||
return 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void spawnEntity(GeyserSession session) {
|
||||
super.spawnEntity(session);
|
||||
public void spawnEntity() {
|
||||
super.spawnEntity();
|
||||
|
||||
// Add horse jump strength attribute to allow donkeys and mules to jump, if they don't send the attribute themselves.
|
||||
// Confirmed broken without this code by making a new donkey in vanilla 1.17.1
|
||||
@ -73,16 +79,14 @@ public class AbstractHorseEntity extends AnimalEntity {
|
||||
session.sendUpstreamPacket(attributesPacket);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
|
||||
if (entityMetadata.getId() == 17) {
|
||||
byte xd = (byte) entityMetadata.getValue();
|
||||
public void setHorseFlags(EntityMetadata<Byte> entityMetadata) {
|
||||
byte xd = ((ByteEntityMetadata) entityMetadata).getPrimitiveValue();
|
||||
boolean tamed = (xd & 0x02) == 0x02;
|
||||
boolean saddled = (xd & 0x04) == 0x04;
|
||||
metadata.getFlags().setFlag(EntityFlag.TAMED, tamed);
|
||||
metadata.getFlags().setFlag(EntityFlag.SADDLED, saddled);
|
||||
metadata.getFlags().setFlag(EntityFlag.EATING, (xd & 0x10) == 0x10);
|
||||
metadata.getFlags().setFlag(EntityFlag.STANDING, (xd & 0x20) == 0x20);
|
||||
setFlag(EntityFlag.TAMED, tamed);
|
||||
setFlag(EntityFlag.SADDLED, saddled);
|
||||
setFlag(EntityFlag.EATING, (xd & 0x10) == 0x10);
|
||||
setFlag(EntityFlag.STANDING, (xd & 0x20) == 0x20);
|
||||
|
||||
// HorseFlags
|
||||
// Bred 0x10
|
||||
@ -95,7 +99,7 @@ public class AbstractHorseEntity extends AnimalEntity {
|
||||
horseFlags = (xd & 0x10) == 0x10 && (xd & 0x40) != 0x40 ? horseFlags | 0x20 : horseFlags;
|
||||
|
||||
// Set the flags into the display item
|
||||
metadata.put(EntityData.DISPLAY_ITEM, horseFlags);
|
||||
dirtyMetadata.put(EntityData.DISPLAY_ITEM, horseFlags);
|
||||
|
||||
// Send the eating particles
|
||||
// We use the wheat metadata as static particles since Java
|
||||
@ -109,13 +113,10 @@ public class AbstractHorseEntity extends AnimalEntity {
|
||||
}
|
||||
|
||||
// Set container type if tamed
|
||||
metadata.put(EntityData.CONTAINER_TYPE, tamed ? (byte) ContainerType.HORSE.getId() : (byte) 0);
|
||||
dirtyMetadata.put(EntityData.CONTAINER_TYPE, tamed ? (byte) ContainerType.HORSE.getId() : (byte) 0);
|
||||
|
||||
// Shows the jump meter
|
||||
metadata.getFlags().setFlag(EntityFlag.CAN_POWER_JUMP, saddled);
|
||||
}
|
||||
|
||||
super.updateBedrockMetadata(entityMetadata, session);
|
||||
setFlag(EntityFlag.CAN_POWER_JUMP, saddled);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -25,26 +25,20 @@
|
||||
|
||||
package org.geysermc.connector.entity.living.animal.horse;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
|
||||
import org.geysermc.connector.entity.type.EntityType;
|
||||
import org.geysermc.connector.entity.EntityDefinition;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class ChestedHorseEntity extends AbstractHorseEntity {
|
||||
|
||||
public ChestedHorseEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
||||
super(entityId, geyserId, entityType, position, motion, rotation);
|
||||
|
||||
metadata.put(EntityData.CONTAINER_BASE_SIZE, 16);
|
||||
public ChestedHorseEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
|
||||
if (entityMetadata.getId() == 19) {
|
||||
metadata.getFlags().setFlag(EntityFlag.CHESTED, (boolean) entityMetadata.getValue());
|
||||
}
|
||||
super.updateBedrockMetadata(entityMetadata, session);
|
||||
protected int getContainerBaseSize() {
|
||||
return 16;
|
||||
}
|
||||
}
|
||||
|
@ -26,24 +26,23 @@
|
||||
package org.geysermc.connector.entity.living.animal.horse;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata;
|
||||
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.EntityDefinition;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class HorseEntity extends AbstractHorseEntity {
|
||||
|
||||
public HorseEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
||||
super(entityId, geyserId, entityType, position, motion, rotation);
|
||||
public HorseEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
|
||||
if (entityMetadata.getId() == 19) {
|
||||
metadata.put(EntityData.VARIANT, ((int) entityMetadata.getValue()) & 255);
|
||||
metadata.put(EntityData.MARK_VARIANT, (((int) entityMetadata.getValue()) >> 8) % 5);
|
||||
public void setHorseVariant(EntityMetadata<Integer> entityMetadata) {
|
||||
int value = ((IntEntityMetadata) entityMetadata).getPrimitiveValue();
|
||||
dirtyMetadata.put(EntityData.VARIANT, value & 255);
|
||||
dirtyMetadata.put(EntityData.MARK_VARIANT, (value >> 8) % 5);
|
||||
}
|
||||
super.updateBedrockMetadata(entityMetadata, session);
|
||||
}
|
||||
|
||||
}
|
@ -26,35 +26,34 @@
|
||||
package org.geysermc.connector.entity.living.animal.horse;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
|
||||
import com.nukkitx.protocol.bedrock.data.inventory.ItemData;
|
||||
import com.nukkitx.protocol.bedrock.packet.MobArmorEquipmentPacket;
|
||||
import org.geysermc.connector.entity.type.EntityType;
|
||||
import org.geysermc.connector.entity.EntityDefinition;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
import org.geysermc.connector.registry.type.ItemMapping;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class LlamaEntity extends ChestedHorseEntity {
|
||||
|
||||
public LlamaEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
||||
super(entityId, geyserId, entityType, position, motion, rotation);
|
||||
public LlamaEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
|
||||
|
||||
metadata.put(EntityData.CONTAINER_STRENGTH_MODIFIER, 3); // Presumably 3 slots for every 1 strength
|
||||
dirtyMetadata.put(EntityData.CONTAINER_STRENGTH_MODIFIER, 3); // Presumably 3 slots for every 1 strength
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
|
||||
// Strength
|
||||
if (entityMetadata.getId() == 20) {
|
||||
metadata.put(EntityData.STRENGTH, entityMetadata.getValue());
|
||||
}
|
||||
// Color equipped on the llama
|
||||
if (entityMetadata.getId() == 21) {
|
||||
/**
|
||||
* Color equipped on the llama
|
||||
*/
|
||||
public void setCarpetedColor(EntityMetadata<Integer> entityMetadata) {
|
||||
// Bedrock treats llama decoration as armor
|
||||
MobArmorEquipmentPacket equipmentPacket = new MobArmorEquipmentPacket();
|
||||
equipmentPacket.setRuntimeEntityId(geyserId);
|
||||
// -1 means no armor
|
||||
int carpetIndex = (int) entityMetadata.getValue();
|
||||
int carpetIndex = ((IntEntityMetadata) entityMetadata).getPrimitiveValue();
|
||||
if (carpetIndex > -1 && carpetIndex <= 15) {
|
||||
// The damage value is the dye color that Java sends us, for pre-1.16.220
|
||||
// The item is always going to be a carpet
|
||||
@ -69,12 +68,6 @@ public class LlamaEntity extends ChestedHorseEntity {
|
||||
|
||||
session.sendUpstreamPacket(equipmentPacket);
|
||||
}
|
||||
// Color of the llama
|
||||
if (entityMetadata.getId() == 22) {
|
||||
metadata.put(EntityData.VARIANT, entityMetadata.getValue());
|
||||
}
|
||||
super.updateBedrockMetadata(entityMetadata, session);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canEat(GeyserSession session, String javaIdentifierStripped, ItemMapping mapping) {
|
||||
|
@ -27,18 +27,20 @@ package org.geysermc.connector.entity.living.animal.horse;
|
||||
|
||||
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.EntityDefinition;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class TraderLlamaEntity extends LlamaEntity {
|
||||
|
||||
public TraderLlamaEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
||||
super(entityId, geyserId, entityType, position, motion, rotation);
|
||||
public TraderLlamaEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void spawnEntity(GeyserSession session) {
|
||||
this.metadata.put(EntityData.MARK_VARIANT, 1);
|
||||
super.spawnEntity(session);
|
||||
protected void initializeMetadata() {
|
||||
super.initializeMetadata();
|
||||
this.dirtyMetadata.put(EntityData.MARK_VARIANT, 1);
|
||||
}
|
||||
}
|
||||
|
@ -26,40 +26,52 @@
|
||||
package org.geysermc.connector.entity.living.animal.tameable;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanEntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
|
||||
import org.geysermc.connector.entity.type.EntityType;
|
||||
import org.geysermc.connector.entity.EntityDefinition;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
import org.geysermc.connector.registry.type.ItemMapping;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class CatEntity extends TameableEntity {
|
||||
|
||||
private byte collarColor;
|
||||
|
||||
public CatEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
||||
super(entityId, geyserId, entityType, position, motion, rotation);
|
||||
public CatEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateRotation(GeyserSession session, float yaw, float pitch, boolean isOnGround) {
|
||||
moveRelative(session, 0, 0, 0, Vector3f.from(this.rotation.getX(), pitch, yaw), isOnGround);
|
||||
public void updateRotation(float yaw, float pitch, boolean isOnGround) {
|
||||
moveRelative(0, 0, 0, yaw, pitch, yaw, isOnGround);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
|
||||
super.updateBedrockMetadata(entityMetadata, session);
|
||||
if (entityMetadata.getId() == 16) {
|
||||
metadata.put(EntityData.SCALE, (boolean) entityMetadata.getValue() ? 0.4f : 0.8f);
|
||||
} else if (entityMetadata.getId() == 17) {
|
||||
protected float getAdultSize() {
|
||||
return 0.8f;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected float getBabySize() {
|
||||
return 0.4f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTameableFlags(EntityMetadata<Byte> entityMetadata) {
|
||||
super.setTameableFlags(entityMetadata);
|
||||
// Update collar color if tamed
|
||||
if (metadata.getFlags().getFlag(EntityFlag.TAMED)) {
|
||||
metadata.put(EntityData.COLOR, collarColor);
|
||||
if (getFlag(EntityFlag.TAMED)) {
|
||||
dirtyMetadata.put(EntityData.COLOR, collarColor);
|
||||
}
|
||||
}
|
||||
if (entityMetadata.getId() == 19) {
|
||||
|
||||
public void setCatVariant(EntityMetadata<Integer> entityMetadata) {
|
||||
// Different colors in Java and Bedrock for some reason
|
||||
int metadataValue = (int) entityMetadata.getValue();
|
||||
int metadataValue = ((IntEntityMetadata) entityMetadata).getPrimitiveValue();
|
||||
int variantColor = switch (metadataValue) {
|
||||
case 0 -> 8;
|
||||
case 8 -> 0;
|
||||
@ -67,17 +79,18 @@ public class CatEntity extends TameableEntity {
|
||||
case 10 -> 9;
|
||||
default -> metadataValue;
|
||||
};
|
||||
metadata.put(EntityData.VARIANT, variantColor);
|
||||
dirtyMetadata.put(EntityData.VARIANT, variantColor);
|
||||
}
|
||||
if (entityMetadata.getId() == 20) {
|
||||
metadata.getFlags().setFlag(EntityFlag.RESTING, (boolean) entityMetadata.getValue());
|
||||
|
||||
public void setResting(EntityMetadata<Boolean> entityMetadata) {
|
||||
setFlag(EntityFlag.RESTING, ((BooleanEntityMetadata) entityMetadata).getPrimitiveValue());
|
||||
}
|
||||
if (entityMetadata.getId() == 22) {
|
||||
collarColor = (byte) (int) entityMetadata.getValue();
|
||||
|
||||
public void setCollarColor(EntityMetadata<Integer> entityMetadata) {
|
||||
collarColor = (byte) ((IntEntityMetadata) entityMetadata).getPrimitiveValue();
|
||||
// Needed or else wild cats are a red color
|
||||
if (metadata.getFlags().getFlag(EntityFlag.TAMED)) {
|
||||
metadata.put(EntityData.COLOR, collarColor);
|
||||
}
|
||||
if (getFlag(EntityFlag.TAMED)) {
|
||||
dirtyMetadata.put(EntityData.COLOR, collarColor);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -25,26 +25,17 @@
|
||||
|
||||
package org.geysermc.connector.entity.living.animal.tameable;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
|
||||
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.EntityDefinition;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
import org.geysermc.connector.registry.type.ItemMapping;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class ParrotEntity extends TameableEntity {
|
||||
|
||||
public ParrotEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
||||
super(entityId, geyserId, entityType, position, motion, rotation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
|
||||
// Parrot color
|
||||
if (entityMetadata.getId() == 19) {
|
||||
metadata.put(EntityData.VARIANT, entityMetadata.getValue());
|
||||
}
|
||||
super.updateBedrockMetadata(entityMetadata, session);
|
||||
public ParrotEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -26,46 +26,51 @@
|
||||
package org.geysermc.connector.entity.living.animal.tameable;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
|
||||
import lombok.Getter;
|
||||
import org.geysermc.connector.entity.Entity;
|
||||
import org.geysermc.connector.entity.EntityDefinition;
|
||||
import org.geysermc.connector.entity.living.animal.AnimalEntity;
|
||||
import org.geysermc.connector.entity.type.EntityType;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class TameableEntity extends AnimalEntity {
|
||||
/**
|
||||
* Used in the interactive tag manager to track if the session player owns this entity
|
||||
*/
|
||||
@Getter
|
||||
protected long ownerBedrockId;
|
||||
|
||||
public TameableEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
||||
super(entityId, geyserId, entityType, position, motion, rotation);
|
||||
public TameableEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
|
||||
if (entityMetadata.getId() == 17) {
|
||||
byte xd = (byte) entityMetadata.getValue();
|
||||
metadata.getFlags().setFlag(EntityFlag.SITTING, (xd & 0x01) == 0x01);
|
||||
metadata.getFlags().setFlag(EntityFlag.ANGRY, (xd & 0x02) == 0x02);
|
||||
metadata.getFlags().setFlag(EntityFlag.TAMED, (xd & 0x04) == 0x04);
|
||||
public void setTameableFlags(EntityMetadata<Byte> entityMetadata) {
|
||||
byte xd = ((ByteEntityMetadata) entityMetadata).getPrimitiveValue();
|
||||
setFlag(EntityFlag.SITTING, (xd & 0x01) == 0x01);
|
||||
setFlag(EntityFlag.ANGRY, (xd & 0x02) == 0x02);
|
||||
setFlag(EntityFlag.TAMED, (xd & 0x04) == 0x04);
|
||||
}
|
||||
|
||||
public void setOwner(EntityMetadata<UUID> entityMetadata) {
|
||||
// Note: Must be set for wolf collar color to work
|
||||
if (entityMetadata.getId() == 18) {
|
||||
if (entityMetadata.getValue() != null) {
|
||||
// Owner UUID of entity
|
||||
Entity entity = session.getEntityCache().getPlayerEntity((UUID) entityMetadata.getValue());
|
||||
Entity entity = session.getEntityCache().getPlayerEntity(entityMetadata.getValue());
|
||||
// Used as both a check since the player isn't in the entity cache and a normal fallback
|
||||
if (entity == null) {
|
||||
entity = session.getPlayerEntity();
|
||||
}
|
||||
// Translate to entity ID
|
||||
metadata.put(EntityData.OWNER_EID, entity.getGeyserId());
|
||||
ownerBedrockId = entity.getGeyserId();
|
||||
} else {
|
||||
metadata.put(EntityData.OWNER_EID, 0L); // Reset
|
||||
}
|
||||
}
|
||||
super.updateBedrockMetadata(entityMetadata, session);
|
||||
// Reset
|
||||
ownerBedrockId = 0L;
|
||||
}
|
||||
dirtyMetadata.put(EntityData.OWNER_EID, ownerBedrockId);
|
||||
}
|
||||
}
|
||||
|
@ -26,15 +26,18 @@
|
||||
package org.geysermc.connector.entity.living.animal.tameable;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
|
||||
import org.geysermc.connector.entity.type.EntityType;
|
||||
import org.geysermc.connector.entity.EntityDefinition;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
import org.geysermc.connector.registry.type.ItemMapping;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
public class WolfEntity extends TameableEntity {
|
||||
/**
|
||||
@ -47,49 +50,45 @@ public class WolfEntity extends TameableEntity {
|
||||
|
||||
private byte collarColor;
|
||||
|
||||
public WolfEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
||||
super(entityId, geyserId, entityType, position, motion, rotation);
|
||||
public WolfEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
|
||||
public void setTameableFlags(EntityMetadata<Byte> entityMetadata) {
|
||||
super.setFlags(entityMetadata);
|
||||
// Reset wolf color
|
||||
if (entityMetadata.getId() == 17) {
|
||||
byte xd = (byte) entityMetadata.getValue();
|
||||
byte xd = ((ByteEntityMetadata) entityMetadata).getPrimitiveValue();
|
||||
boolean angry = (xd & 0x02) == 0x02;
|
||||
if (angry) {
|
||||
metadata.put(EntityData.COLOR, (byte) 0);
|
||||
dirtyMetadata.put(EntityData.COLOR, (byte) 0);
|
||||
}
|
||||
}
|
||||
|
||||
// "Begging" on wiki.vg, "Interested" in Nukkit - the tilt of the head
|
||||
if (entityMetadata.getId() == 19) {
|
||||
metadata.getFlags().setFlag(EntityFlag.INTERESTED, (boolean) entityMetadata.getValue());
|
||||
public void setCollarColor(EntityMetadata<Integer> entityMetadata) {
|
||||
collarColor = (byte) ((IntEntityMetadata) entityMetadata).getPrimitiveValue();
|
||||
if (getFlag(EntityFlag.ANGRY)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Wolf collar color
|
||||
// Relies on EntityData.OWNER_EID being set in TameableEntity.java
|
||||
if (entityMetadata.getId() == 20 && !metadata.getFlags().getFlag(EntityFlag.ANGRY)) {
|
||||
metadata.put(EntityData.COLOR, collarColor = (byte) (int) entityMetadata.getValue());
|
||||
if (!metadata.containsKey(EntityData.OWNER_EID)) {
|
||||
dirtyMetadata.put(EntityData.COLOR, collarColor);
|
||||
if (ownerBedrockId == 0) {
|
||||
// If a color is set and there is no owner entity ID, set one.
|
||||
// Otherwise, the entire wolf is set to that color: https://user-images.githubusercontent.com/9083212/99209989-92691200-2792-11eb-911d-9a315c955be9.png
|
||||
metadata.put(EntityData.OWNER_EID, session.getPlayerEntity().getGeyserId());
|
||||
dirtyMetadata.put(EntityData.OWNER_EID, session.getPlayerEntity().getGeyserId());
|
||||
}
|
||||
}
|
||||
|
||||
// Wolf anger (1.16+)
|
||||
if (entityMetadata.getId() == 21) {
|
||||
metadata.getFlags().setFlag(EntityFlag.ANGRY, (int) entityMetadata.getValue() != 0);
|
||||
metadata.put(EntityData.COLOR, (int) entityMetadata.getValue() != 0 ? (byte) 0 : collarColor);
|
||||
}
|
||||
|
||||
super.updateBedrockMetadata(entityMetadata, session);
|
||||
// 1.16+
|
||||
public void setWolfAngerTime(EntityMetadata<Integer> entityMetadata) {
|
||||
int time = ((IntEntityMetadata) entityMetadata).getPrimitiveValue();
|
||||
setFlag(EntityFlag.ANGRY, time != 0);
|
||||
dirtyMetadata.put(EntityData.COLOR, time != 0 ? (byte) 0 : collarColor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canEat(GeyserSession session, String javaIdentifierStripped, ItemMapping mapping) {
|
||||
// Cannot be a baby to eat these foods
|
||||
return WOLF_FOODS.contains(javaIdentifierStripped) && !metadata.getFlags().getFlag(EntityFlag.BABY);
|
||||
return WOLF_FOODS.contains(javaIdentifierStripped) && !getFlag(EntityFlag.BABY);
|
||||
}
|
||||
}
|
||||
|
@ -26,18 +26,15 @@
|
||||
package org.geysermc.connector.entity.living.merchant;
|
||||
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import org.geysermc.connector.entity.EntityDefinition;
|
||||
import org.geysermc.connector.entity.living.AgeableEntity;
|
||||
import org.geysermc.connector.entity.type.EntityType;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class AbstractMerchantEntity extends AgeableEntity {
|
||||
|
||||
public AbstractMerchantEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
||||
super(entityId, geyserId, entityType, position, motion, rotation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void teleport(GeyserSession session, Vector3f position, float yaw, float pitch, boolean isOnGround) {
|
||||
super.teleport(session, position, yaw - 180, pitch, isOnGround);
|
||||
public AbstractMerchantEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
|
||||
}
|
||||
}
|
||||
|
@ -26,6 +26,7 @@
|
||||
package org.geysermc.connector.entity.living.merchant;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.VillagerData;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.math.vector.Vector3i;
|
||||
@ -34,12 +35,12 @@ import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
|
||||
import com.nukkitx.protocol.bedrock.packet.MoveEntityAbsolutePacket;
|
||||
import it.unimi.dsi.fastutil.ints.Int2IntMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
|
||||
import org.geysermc.connector.entity.type.EntityType;
|
||||
import lombok.Getter;
|
||||
import org.geysermc.connector.entity.EntityDefinition;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
import org.geysermc.connector.registry.BlockRegistries;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.UUID;
|
||||
|
||||
public class VillagerEntity extends AbstractMerchantEntity {
|
||||
|
||||
@ -79,32 +80,41 @@ public class VillagerEntity extends AbstractMerchantEntity {
|
||||
VILLAGER_REGIONS.put(6, 6);
|
||||
}
|
||||
|
||||
public VillagerEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
||||
super(entityId, geyserId, entityType, position, motion, rotation);
|
||||
private Vector3i bedPosition;
|
||||
/**
|
||||
* Used in the interactive tag manager
|
||||
*/
|
||||
@Getter
|
||||
private boolean canTradeWith;
|
||||
|
||||
public VillagerEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
|
||||
if (entityMetadata.getId() == 18) {
|
||||
VillagerData villagerData = (VillagerData) entityMetadata.getValue();
|
||||
public void setVillagerData(EntityMetadata<VillagerData> entityMetadata) {
|
||||
VillagerData villagerData = entityMetadata.getValue();
|
||||
// Profession
|
||||
metadata.put(EntityData.VARIANT, VILLAGER_PROFESSIONS.get(villagerData.getProfession()));
|
||||
int profession = VILLAGER_PROFESSIONS.get(villagerData.getProfession());
|
||||
canTradeWith = profession != 14 && profession != 0; // Not a notwit and not professionless
|
||||
dirtyMetadata.put(EntityData.VARIANT, profession);
|
||||
//metadata.put(EntityData.SKIN_ID, villagerData.getType()); Looks like this is modified but for any reason?
|
||||
// Region
|
||||
metadata.put(EntityData.MARK_VARIANT, VILLAGER_REGIONS.get(villagerData.getType()));
|
||||
dirtyMetadata.put(EntityData.MARK_VARIANT, VILLAGER_REGIONS.get(villagerData.getType()));
|
||||
// Trade tier - different indexing in Bedrock
|
||||
metadata.put(EntityData.TRADE_TIER, villagerData.getLevel() - 1);
|
||||
}
|
||||
super.updateBedrockMetadata(entityMetadata, session);
|
||||
dirtyMetadata.put(EntityData.TRADE_TIER, villagerData.getLevel() - 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void moveRelative(GeyserSession session, double relX, double relY, double relZ, Vector3f rotation, boolean isOnGround) {
|
||||
public Vector3i setBedPosition(EntityMetadata<Position> entityMetadata) {
|
||||
return bedPosition = super.setBedPosition(entityMetadata);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void moveRelative(double relX, double relY, double relZ, float yaw, float pitch, float headYaw, boolean isOnGround) {
|
||||
// The bed block position, if it exists
|
||||
Vector3i bedPosition;
|
||||
if (!metadata.getFlags().getFlag(EntityFlag.SLEEPING) || (bedPosition = metadata.getPos(EntityData.BED_POSITION, null)) == null) {
|
||||
if (!getFlag(EntityFlag.SLEEPING) || bedPosition == null) {
|
||||
// No need to worry about extra processing to compensate for sleeping
|
||||
super.moveRelative(session, relX, relY, relZ, rotation, isOnGround);
|
||||
super.moveRelative(relX, relY, relZ, yaw, pitch, headYaw, isOnGround);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -133,7 +143,9 @@ public class VillagerEntity extends AbstractMerchantEntity {
|
||||
zOffset = .5f;
|
||||
}
|
||||
|
||||
setRotation(rotation);
|
||||
setYaw(yaw);
|
||||
setPitch(pitch);
|
||||
setHeadYaw(headYaw);
|
||||
setOnGround(isOnGround);
|
||||
this.position = Vector3f.from(position.getX() + relX, position.getY() + relY, position.getZ() + relZ);
|
||||
|
||||
|
@ -26,24 +26,25 @@
|
||||
package org.geysermc.connector.entity.living.monster;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata;
|
||||
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.EntityDefinition;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class AbstractSkeletonEntity extends MonsterEntity {
|
||||
|
||||
public AbstractSkeletonEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
||||
super(entityId, geyserId, entityType, position, motion, rotation);
|
||||
public AbstractSkeletonEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
|
||||
if (entityMetadata.getId() == 15) {
|
||||
byte xd = (byte) entityMetadata.getValue();
|
||||
public void setMobFlags(EntityMetadata<Byte> entityMetadata) {
|
||||
super.setMobFlags(entityMetadata);
|
||||
byte xd = ((ByteEntityMetadata) entityMetadata).getPrimitiveValue();
|
||||
// A bit of a loophole so the hands get raised - set the target ID to its own ID
|
||||
metadata.put(EntityData.TARGET_EID, ((xd & 4) == 4) ? geyserId : 0);
|
||||
}
|
||||
super.updateBedrockMetadata(entityMetadata, session);
|
||||
dirtyMetadata.put(EntityData.TARGET_EID, ((xd & 4) == 4) ? geyserId : 0);
|
||||
}
|
||||
}
|
||||
|
@ -26,32 +26,30 @@
|
||||
package org.geysermc.connector.entity.living.monster;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanEntityMetadata;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
|
||||
import org.geysermc.connector.entity.type.EntityType;
|
||||
import org.geysermc.connector.entity.EntityDefinition;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
import org.geysermc.connector.utils.DimensionUtils;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class BasePiglinEntity extends MonsterEntity {
|
||||
private boolean isImmuneToZombification;
|
||||
|
||||
public BasePiglinEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
||||
super(entityId, geyserId, entityType, position, motion, rotation);
|
||||
public BasePiglinEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
|
||||
if (entityMetadata.getId() == 16) {
|
||||
// Immune to zombification?
|
||||
public void setImmuneToZombification(EntityMetadata<Boolean> entityMetadata) {
|
||||
// Apply shaking effect if not in the nether and zombification is possible
|
||||
this.isImmuneToZombification = (boolean) entityMetadata.getValue();
|
||||
metadata.getFlags().setFlag(EntityFlag.SHAKING, isShaking(session));
|
||||
}
|
||||
super.updateBedrockMetadata(entityMetadata, session);
|
||||
this.isImmuneToZombification = ((BooleanEntityMetadata) entityMetadata).getPrimitiveValue();
|
||||
setFlag(EntityFlag.SHAKING, isShaking());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isShaking(GeyserSession session) {
|
||||
return (!isImmuneToZombification && !session.getDimension().equals(DimensionUtils.NETHER)) || super.isShaking(session);
|
||||
protected boolean isShaking() {
|
||||
return (!isImmuneToZombification && !session.getDimension().equals(DimensionUtils.NETHER)) || super.isShaking();
|
||||
}
|
||||
}
|
||||
|
@ -26,24 +26,22 @@
|
||||
package org.geysermc.connector.entity.living.monster;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
|
||||
import org.geysermc.connector.entity.type.EntityType;
|
||||
import org.geysermc.connector.entity.EntityDefinition;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class BlazeEntity extends MonsterEntity {
|
||||
|
||||
public BlazeEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
||||
super(entityId, geyserId, entityType, position, motion, rotation);
|
||||
public BlazeEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
|
||||
if (entityMetadata.getId() == 16) {
|
||||
byte xd = (byte) entityMetadata.getValue();
|
||||
metadata.getFlags().setFlag(EntityFlag.ON_FIRE, (xd & 0x01) == 0x01);
|
||||
}
|
||||
|
||||
super.updateBedrockMetadata(entityMetadata, session);
|
||||
public void setBlazeFlags(EntityMetadata<Byte> entityMetadata) {
|
||||
byte xd = ((ByteEntityMetadata) entityMetadata).getPrimitiveValue();
|
||||
setFlag(EntityFlag.ON_FIRE, (xd & 0x01) == 0x01);
|
||||
}
|
||||
}
|
||||
|
@ -26,38 +26,34 @@
|
||||
package org.geysermc.connector.entity.living.monster;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanEntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
|
||||
import org.geysermc.connector.entity.type.EntityType;
|
||||
import org.geysermc.connector.entity.EntityDefinition;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
|
||||
public class CreeperEntity extends MonsterEntity {
|
||||
import java.util.UUID;
|
||||
|
||||
public class CreeperEntity extends MonsterEntity {
|
||||
/**
|
||||
* Whether the creeper has been ignited and is using ID 17.
|
||||
* In this instance we ignore ID 15 since it's sending us -1 which confuses poor Bedrock.
|
||||
* Whether the creeper has been ignited and is using {@link #setIgnited(EntityMetadata)}.
|
||||
* In this instance we ignore {@link #setSwelling(EntityMetadata)} since it's sending us -1 which confuses poor Bedrock.
|
||||
*/
|
||||
private boolean ignitedByFlintAndSteel = false;
|
||||
|
||||
public CreeperEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
||||
super(entityId, geyserId, entityType, position, motion, rotation);
|
||||
public CreeperEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
|
||||
if (entityMetadata.getId() == 16) {
|
||||
public void setSwelling(EntityMetadata<Integer> entityMetadata) {
|
||||
if (!ignitedByFlintAndSteel) {
|
||||
metadata.getFlags().setFlag(EntityFlag.IGNITED, (int) entityMetadata.getValue() == 1);
|
||||
setFlag(EntityFlag.IGNITED, ((IntEntityMetadata) entityMetadata).getPrimitiveValue() == 1);
|
||||
}
|
||||
}
|
||||
if (entityMetadata.getId() == 17) {
|
||||
metadata.getFlags().setFlag(EntityFlag.POWERED, (boolean) entityMetadata.getValue());
|
||||
}
|
||||
if (entityMetadata.getId() == 18) {
|
||||
ignitedByFlintAndSteel = (boolean) entityMetadata.getValue();
|
||||
metadata.getFlags().setFlag(EntityFlag.IGNITED, ignitedByFlintAndSteel);
|
||||
}
|
||||
|
||||
super.updateBedrockMetadata(entityMetadata, session);
|
||||
public void setIgnited(EntityMetadata<Boolean> entityMetadata) {
|
||||
ignitedByFlintAndSteel = ((BooleanEntityMetadata) entityMetadata).getPrimitiveValue();
|
||||
setFlag(EntityFlag.IGNITED, ignitedByFlintAndSteel);
|
||||
}
|
||||
}
|
||||
|
@ -27,14 +27,21 @@ package org.geysermc.connector.entity.living.monster;
|
||||
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
|
||||
import org.geysermc.connector.entity.type.EntityType;
|
||||
import org.geysermc.connector.entity.EntityDefinition;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class ElderGuardianEntity extends GuardianEntity {
|
||||
|
||||
public ElderGuardianEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
||||
super(entityId, geyserId, entityType, position, motion, rotation);
|
||||
// Otherwise it just looks like a normal guardian but bigger
|
||||
metadata.getFlags().setFlag(EntityFlag.ELDER, true);
|
||||
public ElderGuardianEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initializeMetadata() {
|
||||
super.initializeMetadata();
|
||||
// Otherwise it just looks like a normal guardian but bigger
|
||||
setFlag(EntityFlag.ELDER, true);
|
||||
}
|
||||
}
|
||||
|
@ -26,6 +26,7 @@
|
||||
package org.geysermc.connector.entity.living.monster;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.protocol.bedrock.data.LevelEventType;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
|
||||
@ -33,17 +34,18 @@ import com.nukkitx.protocol.bedrock.data.entity.EntityEventType;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
|
||||
import com.nukkitx.protocol.bedrock.packet.*;
|
||||
import lombok.Data;
|
||||
import org.geysermc.connector.entity.EntityDefinition;
|
||||
import org.geysermc.connector.entity.Tickable;
|
||||
import org.geysermc.connector.entity.living.InsentientEntity;
|
||||
import org.geysermc.connector.entity.type.EntityType;
|
||||
import org.geysermc.connector.entity.living.MobEntity;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
import org.geysermc.connector.utils.DimensionUtils;
|
||||
|
||||
import java.util.Random;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
public class EnderDragonEntity extends InsentientEntity implements Tickable {
|
||||
public class EnderDragonEntity extends MobEntity implements Tickable {
|
||||
/**
|
||||
* The Ender Dragon has multiple hit boxes, which
|
||||
* are each its own invisible entity
|
||||
@ -78,23 +80,19 @@ public class EnderDragonEntity extends InsentientEntity implements Tickable {
|
||||
private float wingPosition;
|
||||
private float lastWingPosition;
|
||||
|
||||
public EnderDragonEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
||||
super(entityId, geyserId, entityType, position, motion, rotation);
|
||||
|
||||
metadata.getFlags().setFlag(EntityFlag.FIRE_IMMUNE, true);
|
||||
public EnderDragonEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
|
||||
if (entityMetadata.getId() == 16) { // Phase
|
||||
phase = (int) entityMetadata.getValue();
|
||||
phaseTicks = 0;
|
||||
metadata.getFlags().setFlag(EntityFlag.SITTING, isSitting());
|
||||
protected void initializeMetadata() {
|
||||
super.initializeMetadata();
|
||||
setFlag(EntityFlag.FIRE_IMMUNE, true);
|
||||
}
|
||||
|
||||
super.updateBedrockMetadata(entityMetadata, session);
|
||||
|
||||
if (entityMetadata.getId() == 9) {
|
||||
@Override
|
||||
public void setHealth(EntityMetadata<Float> entityMetadata) {
|
||||
super.setHealth(entityMetadata);
|
||||
if (phase == 9 && this.health <= 0) { // Dying phase
|
||||
EntityEventPacket entityEventPacket = new EntityEventPacket();
|
||||
entityEventPacket.setType(EntityEventType.ENDER_DRAGON_DEATH);
|
||||
@ -103,21 +101,26 @@ public class EnderDragonEntity extends InsentientEntity implements Tickable {
|
||||
session.sendUpstreamPacket(entityEventPacket);
|
||||
}
|
||||
}
|
||||
|
||||
public void setPhase(EntityMetadata<Integer> entityMetadata) {
|
||||
phase = ((IntEntityMetadata) entityMetadata).getPrimitiveValue();
|
||||
phaseTicks = 0;
|
||||
setFlag(EntityFlag.SITTING, isSitting());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void spawnEntity(GeyserSession session) {
|
||||
super.spawnEntity(session);
|
||||
public void spawnEntity() {
|
||||
super.spawnEntity();
|
||||
|
||||
AtomicLong nextEntityId = session.getEntityCache().getNextEntityId();
|
||||
head = new EnderDragonPartEntity(entityId + 1, nextEntityId.incrementAndGet(), EntityType.ENDER_DRAGON_PART, 1, 1);
|
||||
neck = new EnderDragonPartEntity(entityId + 2, nextEntityId.incrementAndGet(), EntityType.ENDER_DRAGON_PART, 3, 3);
|
||||
body = new EnderDragonPartEntity(entityId + 3, nextEntityId.incrementAndGet(), EntityType.ENDER_DRAGON_PART, 5, 3);
|
||||
leftWing = new EnderDragonPartEntity(entityId + 4, nextEntityId.incrementAndGet(), EntityType.ENDER_DRAGON_PART, 4, 2);
|
||||
rightWing = new EnderDragonPartEntity(entityId + 5, nextEntityId.incrementAndGet(), EntityType.ENDER_DRAGON_PART, 4, 2);
|
||||
head = new EnderDragonPartEntity(session, entityId + 1, nextEntityId.incrementAndGet(), 1, 1);
|
||||
neck = new EnderDragonPartEntity(session, entityId + 2, nextEntityId.incrementAndGet(), 3, 3);
|
||||
body = new EnderDragonPartEntity(session, entityId + 3, nextEntityId.incrementAndGet(), 5, 3);
|
||||
leftWing = new EnderDragonPartEntity(session, entityId + 4, nextEntityId.incrementAndGet(), 4, 2);
|
||||
rightWing = new EnderDragonPartEntity(session, entityId + 5, nextEntityId.incrementAndGet(), 4, 2);
|
||||
tail = new EnderDragonPartEntity[3];
|
||||
for (int i = 0; i < 3; i++) {
|
||||
tail[i] = new EnderDragonPartEntity(entityId + 6 + i, nextEntityId.incrementAndGet(), EntityType.ENDER_DRAGON_PART, 2, 2);
|
||||
tail[i] = new EnderDragonPartEntity(session, entityId + 6 + i, nextEntityId.incrementAndGet(), 2, 2);
|
||||
}
|
||||
|
||||
allParts = new EnderDragonPartEntity[]{head, neck, body, leftWing, rightWing, tail[0], tail[1], tail[2]};
|
||||
@ -128,7 +131,7 @@ public class EnderDragonEntity extends InsentientEntity implements Tickable {
|
||||
|
||||
for (int i = 0; i < segmentHistory.length; i++) {
|
||||
segmentHistory[i] = new Segment();
|
||||
segmentHistory[i].yaw = rotation.getZ();
|
||||
segmentHistory[i].yaw = headYaw;
|
||||
segmentHistory[i].y = position.getY();
|
||||
}
|
||||
}
|
||||
@ -141,29 +144,27 @@ public class EnderDragonEntity extends InsentientEntity implements Tickable {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean despawnEntity(GeyserSession session) {
|
||||
public boolean despawnEntity() {
|
||||
for (EnderDragonPartEntity part : allParts) {
|
||||
part.despawnEntity(session);
|
||||
part.despawnEntity();
|
||||
}
|
||||
return super.despawnEntity(session);
|
||||
return super.despawnEntity();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick(GeyserSession session) {
|
||||
effectTick(session);
|
||||
if (!metadata.getFlags().getFlag(EntityFlag.NO_AI) && isAlive()) {
|
||||
public void tick() {
|
||||
effectTick();
|
||||
if (!getFlag(EntityFlag.NO_AI) && isAlive()) {
|
||||
pushSegment();
|
||||
updateBoundingBoxes(session);
|
||||
updateBoundingBoxes();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the positions of the Ender Dragon's multiple bounding boxes
|
||||
*
|
||||
* @param session GeyserSession.
|
||||
*/
|
||||
private void updateBoundingBoxes(GeyserSession session) {
|
||||
Vector3f facingDir = Vector3f.createDirectionDeg(0, rotation.getZ());
|
||||
private void updateBoundingBoxes() {
|
||||
Vector3f facingDir = Vector3f.createDirectionDeg(0, headYaw);
|
||||
Segment baseSegment = getSegment(5);
|
||||
// Used to angle the head, neck, and tail when the dragon flies up/down
|
||||
float pitch = (float) Math.toRadians(10 * (baseSegment.getY() - getSegment(10).getY()));
|
||||
@ -182,7 +183,7 @@ public class EnderDragonEntity extends InsentientEntity implements Tickable {
|
||||
neck.setPosition(facingDir.up(pitchY).mul(pitchXZ, 1, -pitchXZ).mul(5.5f).up(headDuck));
|
||||
body.setPosition(facingDir.mul(0.5f, 0f, -0.5f));
|
||||
|
||||
Vector3f wingPos = Vector3f.createDirectionDeg(0, 90f - rotation.getZ()).mul(4.5f).up(2f);
|
||||
Vector3f wingPos = Vector3f.createDirectionDeg(0, 90f - headYaw).mul(4.5f).up(2f);
|
||||
rightWing.setPosition(wingPos);
|
||||
leftWing.setPosition(wingPos.mul(-1, 1, -1)); // Mirror horizontally
|
||||
|
||||
@ -191,24 +192,23 @@ public class EnderDragonEntity extends InsentientEntity implements Tickable {
|
||||
float distance = (i + 1) * 2f;
|
||||
// Curls the tail when the dragon turns
|
||||
Segment targetSegment = getSegment(12 + 2 * i);
|
||||
float angle = rotation.getZ() + targetSegment.yaw - baseSegment.yaw;
|
||||
float angle = headYaw + targetSegment.yaw - baseSegment.yaw;
|
||||
|
||||
float tailYOffset = targetSegment.y - baseSegment.y - (distance + 1.5f) * pitchY + 1.5f;
|
||||
tail[i].setPosition(Vector3f.createDirectionDeg(0, angle).mul(distance).add(tailBase).mul(-pitchXZ, 1, pitchXZ).up(tailYOffset));
|
||||
}
|
||||
// Send updated positions
|
||||
for (EnderDragonPartEntity part : allParts) {
|
||||
part.moveAbsolute(session, part.getPosition().add(position), Vector3f.ZERO, false, false);
|
||||
part.moveAbsolute(part.getPosition().add(position), 0, 0, 0, false, false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the particles and sounds of the Ender Dragon
|
||||
* @param session GeyserSession.
|
||||
*/
|
||||
private void effectTick(GeyserSession session) {
|
||||
private void effectTick() {
|
||||
Random random = ThreadLocalRandom.current();
|
||||
if (!metadata.getFlags().getFlag(EntityFlag.SILENT)) {
|
||||
if (!getFlag(EntityFlag.SILENT)) {
|
||||
if (Math.cos(wingPosition * 2f * Math.PI) <= -0.3f && Math.cos(lastWingPosition * 2f * Math.PI) >= -0.3f) {
|
||||
PlaySoundPacket playSoundPacket = new PlaySoundPacket();
|
||||
playSoundPacket.setSound("mob.enderdragon.flap");
|
||||
@ -219,14 +219,14 @@ public class EnderDragonEntity extends InsentientEntity implements Tickable {
|
||||
}
|
||||
|
||||
if (!isSitting() && !isHovering() && ticksTillNextGrowl-- == 0) {
|
||||
playGrowlSound(session);
|
||||
playGrowlSound();
|
||||
ticksTillNextGrowl = 200 + random.nextInt(200);
|
||||
}
|
||||
|
||||
lastWingPosition = wingPosition;
|
||||
}
|
||||
if (isAlive()) {
|
||||
if (metadata.getFlags().getFlag(EntityFlag.NO_AI)) {
|
||||
if (getFlag(EntityFlag.NO_AI)) {
|
||||
wingPosition = 0.5f;
|
||||
} else if (isHovering() || isSitting()) {
|
||||
wingPosition += 0.1f;
|
||||
@ -237,7 +237,7 @@ public class EnderDragonEntity extends InsentientEntity implements Tickable {
|
||||
|
||||
phaseTicks++;
|
||||
if (phase == 3) { // Landing Phase
|
||||
float headHeight = head.getMetadata().getFloat(EntityData.BOUNDING_BOX_HEIGHT);
|
||||
float headHeight = head.getDirtyMetadata().getFloat(EntityData.BOUNDING_BOX_HEIGHT); //TODO
|
||||
Vector3f headCenter = head.getPosition().up(headHeight * 0.5f);
|
||||
|
||||
for (int i = 0; i < 8; i++) {
|
||||
@ -262,7 +262,7 @@ public class EnderDragonEntity extends InsentientEntity implements Tickable {
|
||||
}
|
||||
}
|
||||
} else if (phase == 7) { // Sitting Attacking Phase
|
||||
playGrowlSound(session);
|
||||
playGrowlSound();
|
||||
} else if (phase == 9) { // Dying Phase
|
||||
// Send explosion particles as the dragon move towards the end portal
|
||||
if (phaseTicks % 10 == 0) {
|
||||
@ -279,7 +279,7 @@ public class EnderDragonEntity extends InsentientEntity implements Tickable {
|
||||
}
|
||||
}
|
||||
|
||||
private void playGrowlSound(GeyserSession session) {
|
||||
private void playGrowlSound() {
|
||||
Random random = ThreadLocalRandom.current();
|
||||
PlaySoundPacket playSoundPacket = new PlaySoundPacket();
|
||||
playSoundPacket.setSound("mob.enderdragon.growl");
|
||||
@ -306,7 +306,7 @@ public class EnderDragonEntity extends InsentientEntity implements Tickable {
|
||||
*/
|
||||
private void pushSegment() {
|
||||
latestSegment = (latestSegment + 1) % segmentHistory.length;
|
||||
segmentHistory[latestSegment].yaw = rotation.getZ();
|
||||
segmentHistory[latestSegment].yaw = headYaw;
|
||||
segmentHistory[latestSegment].y = position.getY();
|
||||
}
|
||||
|
||||
|
@ -29,15 +29,17 @@ import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
|
||||
import org.geysermc.connector.entity.Entity;
|
||||
import org.geysermc.connector.entity.type.EntityType;
|
||||
import org.geysermc.connector.entity.EntityDefinitions;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
|
||||
public class EnderDragonPartEntity extends Entity {
|
||||
public EnderDragonPartEntity(long entityId, long geyserId, EntityType entityType, float width, float height) {
|
||||
super(entityId, geyserId, entityType, Vector3f.ZERO, Vector3f.ZERO, Vector3f.ZERO);
|
||||
|
||||
metadata.put(EntityData.BOUNDING_BOX_WIDTH, width);
|
||||
metadata.put(EntityData.BOUNDING_BOX_HEIGHT, height);
|
||||
metadata.getFlags().setFlag(EntityFlag.INVISIBLE, true);
|
||||
metadata.getFlags().setFlag(EntityFlag.FIRE_IMMUNE, true);
|
||||
public EnderDragonPartEntity(GeyserSession session, long entityId, long geyserId, float width, float height) {
|
||||
super(session, entityId, geyserId, null, EntityDefinitions.ENDER_DRAGON_PART, Vector3f.ZERO, Vector3f.ZERO, 0, 0, 0);
|
||||
|
||||
dirtyMetadata.put(EntityData.BOUNDING_BOX_WIDTH, width);
|
||||
dirtyMetadata.put(EntityData.BOUNDING_BOX_HEIGHT, height);
|
||||
setFlag(EntityFlag.INVISIBLE, true);
|
||||
setFlag(EntityFlag.FIRE_IMMUNE, true);
|
||||
}
|
||||
}
|
||||
|
@ -26,29 +26,35 @@
|
||||
package org.geysermc.connector.entity.living.monster;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanEntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.protocol.bedrock.data.SoundEvent;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
|
||||
import com.nukkitx.protocol.bedrock.packet.LevelSoundEvent2Packet;
|
||||
import org.geysermc.connector.entity.type.EntityType;
|
||||
import org.geysermc.connector.entity.EntityDefinition;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class EndermanEntity extends MonsterEntity {
|
||||
|
||||
public EndermanEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
||||
super(entityId, geyserId, entityType, position, motion, rotation);
|
||||
public EndermanEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
|
||||
// Held block
|
||||
if (entityMetadata.getId() == 16) {
|
||||
metadata.put(EntityData.CARRIED_BLOCK, session.getBlockMappings().getBedrockBlockId((int) entityMetadata.getValue()));
|
||||
public void setCarriedBlock(EntityMetadata<Integer> entityMetadata) {
|
||||
dirtyMetadata.put(EntityData.CARRIED_BLOCK, session.getBlockMappings().getBedrockBlockId(((IntEntityMetadata) entityMetadata).getPrimitiveValue()));
|
||||
}
|
||||
// "Is screaming" - controls sound
|
||||
if (entityMetadata.getId() == 17) {
|
||||
if ((boolean) entityMetadata.getValue()) {
|
||||
|
||||
/**
|
||||
* Controls the screaming sound
|
||||
*/
|
||||
public void setScreaming(EntityMetadata<Boolean> entityMetadata) {
|
||||
//TODO see if Bedrock controls this differently
|
||||
// Java Edition this controls which ambient sound is used
|
||||
if (((BooleanEntityMetadata) entityMetadata).getPrimitiveValue()) {
|
||||
LevelSoundEvent2Packet packet = new LevelSoundEvent2Packet();
|
||||
packet.setSound(SoundEvent.STARE);
|
||||
packet.setPosition(this.position);
|
||||
@ -57,10 +63,9 @@ public class EndermanEntity extends MonsterEntity {
|
||||
session.sendUpstreamPacket(packet);
|
||||
}
|
||||
}
|
||||
|
||||
public void setAngry(EntityMetadata<Boolean> entityMetadata) {
|
||||
// "Is staring/provoked" - controls visuals
|
||||
if (entityMetadata.getId() == 18) {
|
||||
metadata.getFlags().setFlag(EntityFlag.ANGRY, (boolean) entityMetadata.getValue());
|
||||
}
|
||||
super.updateBedrockMetadata(entityMetadata, session);
|
||||
setFlag(EntityFlag.ANGRY, ((BooleanEntityMetadata) entityMetadata).getPrimitiveValue());
|
||||
}
|
||||
}
|
||||
|
@ -26,24 +26,23 @@
|
||||
package org.geysermc.connector.entity.living.monster;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanEntityMetadata;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
|
||||
import org.geysermc.connector.entity.EntityDefinition;
|
||||
import org.geysermc.connector.entity.living.FlyingEntity;
|
||||
import org.geysermc.connector.entity.type.EntityType;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class GhastEntity extends FlyingEntity {
|
||||
|
||||
public GhastEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
||||
super(entityId, geyserId, entityType, position, motion, rotation);
|
||||
public GhastEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
|
||||
if (entityMetadata.getId() == 16) {
|
||||
public void setGhastAttacking(EntityMetadata<Boolean> entityMetadata) {
|
||||
// If the ghast is attacking
|
||||
metadata.put(EntityData.CHARGE_AMOUNT, (byte) ((boolean) entityMetadata.getValue() ? 1 : 0));
|
||||
}
|
||||
super.updateBedrockMetadata(entityMetadata, session);
|
||||
dirtyMetadata.put(EntityData.CHARGE_AMOUNT, (byte) (((BooleanEntityMetadata) entityMetadata).getPrimitiveValue() ? 1 : 0));
|
||||
}
|
||||
}
|
||||
|
@ -27,13 +27,16 @@ package org.geysermc.connector.entity.living.monster;
|
||||
|
||||
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.EntityDefinition;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class GiantEntity extends MonsterEntity {
|
||||
|
||||
public GiantEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
||||
super(entityId, geyserId, entityType, position, motion, rotation);
|
||||
public GiantEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
|
||||
|
||||
metadata.put(EntityData.SCALE, 6f);
|
||||
dirtyMetadata.put(EntityData.SCALE, 6f);
|
||||
}
|
||||
}
|
||||
|
@ -26,33 +26,34 @@
|
||||
package org.geysermc.connector.entity.living.monster;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
|
||||
import org.geysermc.connector.entity.Entity;
|
||||
import org.geysermc.connector.entity.type.EntityType;
|
||||
import org.geysermc.connector.entity.EntityDefinition;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class GuardianEntity extends MonsterEntity {
|
||||
|
||||
public GuardianEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
||||
super(entityId, geyserId, entityType, position, motion, rotation);
|
||||
public GuardianEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
|
||||
if (entityMetadata.getId() == 17) {
|
||||
Entity entity = session.getEntityCache().getEntityByJavaId((int) entityMetadata.getValue());
|
||||
if (entity == null && session.getPlayerEntity().getEntityId() == (Integer) entityMetadata.getValue()) {
|
||||
public void setGuardianTarget(EntityMetadata<Integer> entityMetadata) {
|
||||
int entityId = ((IntEntityMetadata) entityMetadata).getPrimitiveValue();
|
||||
Entity entity;
|
||||
if (session.getPlayerEntity().getEntityId() == entityId) {
|
||||
entity = session.getPlayerEntity();
|
||||
} else {
|
||||
entity = session.getEntityCache().getEntityByJavaId(entityId);
|
||||
}
|
||||
|
||||
if (entity != null) {
|
||||
metadata.put(EntityData.TARGET_EID, entity.getGeyserId());
|
||||
dirtyMetadata.put(EntityData.TARGET_EID, entity.getGeyserId());
|
||||
} else {
|
||||
metadata.put(EntityData.TARGET_EID, (long) 0);
|
||||
dirtyMetadata.put(EntityData.TARGET_EID, (long) 0);
|
||||
}
|
||||
}
|
||||
|
||||
super.updateBedrockMetadata(entityMetadata, session);
|
||||
}
|
||||
}
|
||||
|
@ -26,12 +26,15 @@
|
||||
package org.geysermc.connector.entity.living.monster;
|
||||
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import org.geysermc.connector.entity.EntityDefinition;
|
||||
import org.geysermc.connector.entity.living.CreatureEntity;
|
||||
import org.geysermc.connector.entity.type.EntityType;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class MonsterEntity extends CreatureEntity {
|
||||
|
||||
public MonsterEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
||||
super(entityId, geyserId, entityType, position, motion, rotation);
|
||||
public MonsterEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
|
||||
}
|
||||
}
|
||||
|
@ -26,28 +26,27 @@
|
||||
package org.geysermc.connector.entity.living.monster;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
|
||||
import org.geysermc.connector.entity.EntityDefinition;
|
||||
import org.geysermc.connector.entity.living.FlyingEntity;
|
||||
import org.geysermc.connector.entity.type.EntityType;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class PhantomEntity extends FlyingEntity {
|
||||
public PhantomEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
||||
super(entityId, geyserId, entityType, position, motion, rotation);
|
||||
public PhantomEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
|
||||
if (entityMetadata.getId() == 16) { // Size
|
||||
int size = (int) entityMetadata.getValue();
|
||||
public void setPhantomScale(EntityMetadata<Integer> entityMetadata) {
|
||||
int size = ((IntEntityMetadata) entityMetadata).getPrimitiveValue();
|
||||
float modelScale = 1f + 0.15f * size;
|
||||
float boundsScale = (1f + (0.2f * size) / EntityType.PHANTOM.getWidth()) / modelScale;
|
||||
float boundsScale = (1f + (0.2f * size) / definition.width()) / modelScale;
|
||||
|
||||
metadata.put(EntityData.BOUNDING_BOX_WIDTH, boundsScale * EntityType.PHANTOM.getWidth());
|
||||
metadata.put(EntityData.BOUNDING_BOX_HEIGHT, boundsScale * EntityType.PHANTOM.getHeight());
|
||||
metadata.put(EntityData.SCALE, modelScale);
|
||||
}
|
||||
super.updateBedrockMetadata(entityMetadata, session);
|
||||
dirtyMetadata.put(EntityData.BOUNDING_BOX_WIDTH, boundsScale * definition.width());
|
||||
dirtyMetadata.put(EntityData.BOUNDING_BOX_HEIGHT, boundsScale * definition.height());
|
||||
dirtyMetadata.put(EntityData.SCALE, modelScale);
|
||||
}
|
||||
}
|
||||
|
@ -26,44 +26,40 @@
|
||||
package org.geysermc.connector.entity.living.monster;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanEntityMetadata;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
|
||||
import org.geysermc.connector.entity.type.EntityType;
|
||||
import org.geysermc.connector.entity.EntityDefinition;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class PiglinEntity extends BasePiglinEntity {
|
||||
|
||||
public PiglinEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
||||
super(entityId, geyserId, entityType, position, motion, rotation);
|
||||
public PiglinEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
|
||||
if (entityMetadata.getId() == 17) {
|
||||
boolean isBaby = (boolean) entityMetadata.getValue();
|
||||
if (isBaby) {
|
||||
metadata.put(EntityData.SCALE, .55f);
|
||||
metadata.getFlags().setFlag(EntityFlag.BABY, true);
|
||||
}
|
||||
}
|
||||
if (entityMetadata.getId() == 18) {
|
||||
metadata.getFlags().setFlag(EntityFlag.CHARGING, (boolean) entityMetadata.getValue());
|
||||
}
|
||||
if (entityMetadata.getId() == 19) {
|
||||
metadata.getFlags().setFlag(EntityFlag.DANCING, (boolean) entityMetadata.getValue());
|
||||
public void setBaby(EntityMetadata<Boolean> entityMetadata) {
|
||||
boolean isBaby = ((BooleanEntityMetadata) entityMetadata).getPrimitiveValue();
|
||||
dirtyMetadata.put(EntityData.SCALE, isBaby? .55f : 1f);
|
||||
setFlag(EntityFlag.BABY, isBaby);
|
||||
}
|
||||
|
||||
super.updateBedrockMetadata(entityMetadata, session);
|
||||
public void setChargingCrossbow(EntityMetadata<Boolean> entityMetadata) {
|
||||
setFlag(EntityFlag.CHARGING, ((BooleanEntityMetadata) entityMetadata).getPrimitiveValue());
|
||||
}
|
||||
|
||||
public void setDancing(EntityMetadata<Boolean> entityMetadata) {
|
||||
setFlag(EntityFlag.DANCING, ((BooleanEntityMetadata) entityMetadata).getPrimitiveValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateOffHand(GeyserSession session) {
|
||||
// Check if the Piglin is holding Gold and set the ADMIRING flag accordingly so its pose updates
|
||||
boolean changed = metadata.getFlags().setFlag(EntityFlag.ADMIRING, session.getTagCache().shouldPiglinAdmire(session.getItemMappings().getMapping(this.offHand)));
|
||||
if (changed) {
|
||||
super.updateBedrockMetadata(session);
|
||||
}
|
||||
setFlag(EntityFlag.ADMIRING, session.getTagCache().shouldPiglinAdmire(session.getItemMappings().getMapping(this.offHand)));
|
||||
super.updateBedrockMetadata();
|
||||
|
||||
super.updateOffHand(session);
|
||||
}
|
||||
|
@ -26,44 +26,43 @@
|
||||
package org.geysermc.connector.entity.living.monster;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.level.block.BlockFace;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
|
||||
import org.geysermc.connector.entity.EntityDefinition;
|
||||
import org.geysermc.connector.entity.living.GolemEntity;
|
||||
import org.geysermc.connector.entity.type.EntityType;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
import org.geysermc.connector.utils.Direction;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class ShulkerEntity extends GolemEntity {
|
||||
|
||||
public ShulkerEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
||||
super(entityId, geyserId, entityType, position, motion, rotation);
|
||||
public ShulkerEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
|
||||
// Indicate that invisibility should be fixed through the resource pack
|
||||
metadata.getFlags().setFlag(EntityFlag.BRIBED, true);
|
||||
setFlag(EntityFlag.BRIBED, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
|
||||
if (entityMetadata.getId() == 16) {
|
||||
BlockFace blockFace = (BlockFace) entityMetadata.getValue();
|
||||
metadata.put(EntityData.SHULKER_ATTACH_FACE, (byte) blockFace.ordinal());
|
||||
public void setAttachedFace(EntityMetadata<Direction> entityMetadata) {
|
||||
Direction direction = entityMetadata.getValue();
|
||||
dirtyMetadata.put(EntityData.SHULKER_ATTACH_FACE, (byte) direction.ordinal());
|
||||
}
|
||||
|
||||
if (entityMetadata.getId() == 17) {
|
||||
int height = (byte) entityMetadata.getValue();
|
||||
metadata.put(EntityData.SHULKER_PEEK_ID, height);
|
||||
public void setShulkerHeight(EntityMetadata<Byte> entityMetadata) {
|
||||
int height = ((ByteEntityMetadata) entityMetadata).getPrimitiveValue();
|
||||
dirtyMetadata.put(EntityData.SHULKER_PEEK_ID, height);
|
||||
}
|
||||
|
||||
if (entityMetadata.getId() == 18) {
|
||||
byte color = (byte) entityMetadata.getValue();
|
||||
public void setShulkerColor(EntityMetadata<Byte> entityMetadata) {
|
||||
byte color = ((ByteEntityMetadata) entityMetadata).getPrimitiveValue();
|
||||
if (color == 16) {
|
||||
// 16 is default on both editions
|
||||
metadata.put(EntityData.VARIANT, 16);
|
||||
dirtyMetadata.put(EntityData.VARIANT, 16);
|
||||
} else {
|
||||
// Every other shulker color is offset 15 in bedrock edition
|
||||
metadata.put(EntityData.VARIANT, Math.abs(color - 15));
|
||||
dirtyMetadata.put(EntityData.VARIANT, Math.abs(color - 15));
|
||||
}
|
||||
}
|
||||
super.updateBedrockMetadata(entityMetadata, session);
|
||||
}
|
||||
}
|
||||
|
@ -26,29 +26,28 @@
|
||||
package org.geysermc.connector.entity.living.monster;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanEntityMetadata;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
|
||||
import org.geysermc.connector.entity.type.EntityType;
|
||||
import org.geysermc.connector.entity.EntityDefinition;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class SkeletonEntity extends AbstractSkeletonEntity {
|
||||
private boolean convertingToStray = false;
|
||||
|
||||
public SkeletonEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
||||
super(entityId, geyserId, entityType, position, motion, rotation);
|
||||
public SkeletonEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
|
||||
}
|
||||
|
||||
public void setConvertingToStray(EntityMetadata<Boolean> entityMetadata) {
|
||||
this.convertingToStray = ((BooleanEntityMetadata) entityMetadata).getPrimitiveValue();
|
||||
setFlag(EntityFlag.SHAKING, isShaking());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
|
||||
super.updateBedrockMetadata(entityMetadata, session);
|
||||
if (entityMetadata.getId() == 16) {
|
||||
this.convertingToStray = (boolean) entityMetadata.getValue();
|
||||
metadata.getFlags().setFlag(EntityFlag.SHAKING, isShaking(session));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isShaking(GeyserSession session) {
|
||||
protected boolean isShaking() {
|
||||
return convertingToStray;
|
||||
}
|
||||
}
|
||||
|
@ -26,24 +26,22 @@
|
||||
package org.geysermc.connector.entity.living.monster;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
|
||||
import org.geysermc.connector.entity.type.EntityType;
|
||||
import org.geysermc.connector.entity.EntityDefinition;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class SpiderEntity extends MonsterEntity {
|
||||
|
||||
public SpiderEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
||||
super(entityId, geyserId, entityType, position, motion, rotation);
|
||||
public SpiderEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
|
||||
if (entityMetadata.getId() == 16) {
|
||||
byte xd = (byte) entityMetadata.getValue();
|
||||
metadata.getFlags().setFlag(EntityFlag.WALL_CLIMBING, (xd & 0x01) == 0x01);
|
||||
}
|
||||
|
||||
super.updateBedrockMetadata(entityMetadata, session);
|
||||
public void setSpiderFlags(EntityMetadata<Byte> entityMetadata) {
|
||||
byte xd = ((ByteEntityMetadata) entityMetadata).getPrimitiveValue();
|
||||
setFlag(EntityFlag.WALL_CLIMBING, (xd & 0x01) == 0x01);
|
||||
}
|
||||
}
|
||||
|
Einige Dateien werden nicht angezeigt, da zu viele Dateien in diesem Diff geändert wurden Mehr anzeigen
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren