3
0
Mirror von https://github.com/GeyserMC/Geyser.git synchronisiert 2024-10-03 08:21:06 +02:00

Entity refactory aaaaaaAAAAAAA

Dieser Commit ist enthalten in:
Camotoy 2021-11-17 22:02:38 -05:00
Ursprung 951b616f98
Commit 11997ed82b
Es konnte kein GPG-Schlüssel zu dieser Signatur gefunden werden
GPG-Schlüssel-ID: 7EEFB66FE798081F
170 geänderte Dateien mit 4003 neuen und 2836 gelöschten Zeilen

Datei anzeigen

@ -44,6 +44,7 @@ import org.geysermc.connector.bootstrap.GeyserBootstrap;
import org.geysermc.connector.command.CommandManager; import org.geysermc.connector.command.CommandManager;
import org.geysermc.connector.common.AuthType; import org.geysermc.connector.common.AuthType;
import org.geysermc.connector.configuration.GeyserConfiguration; import org.geysermc.connector.configuration.GeyserConfiguration;
import org.geysermc.connector.entity.EntityDefinitions;
import org.geysermc.connector.metrics.Metrics; import org.geysermc.connector.metrics.Metrics;
import org.geysermc.connector.network.ConnectorServerEventHandler; import org.geysermc.connector.network.ConnectorServerEventHandler;
import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.session.GeyserSession;
@ -153,6 +154,7 @@ public class GeyserConnector {
BlockRegistries.init(); BlockRegistries.init();
Registries.init(); Registries.init();
EntityDefinitions.init();
ItemTranslator.init(); ItemTranslator.init();
MessageTranslator.init(); MessageTranslator.init();
LocaleUtils.init(); LocaleUtils.init();

Datei anzeigen

@ -25,8 +25,8 @@
package org.geysermc.connector.command.defaults; 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.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 com.github.steveice10.mc.protocol.packet.ingame.serverbound.player.ServerboundPlayerActionPacket;
import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.GeyserConnector;
import org.geysermc.connector.command.CommandSender; 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, ServerboundPlayerActionPacket releaseItemPacket = new ServerboundPlayerActionPacket(PlayerAction.SWAP_HANDS, BlockUtils.POSITION_ZERO,
BlockFace.DOWN); Direction.DOWN);
session.sendDownstreamPacket(releaseItemPacket); session.sendDownstreamPacket(releaseItemPacket);
} }

Datei anzeigen

@ -26,37 +26,43 @@
package org.geysermc.connector.entity; 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.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.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag; 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.network.session.GeyserSession;
import java.util.UUID;
public class AbstractArrowEntity extends Entity { public class AbstractArrowEntity extends Entity {
public AbstractArrowEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { public AbstractArrowEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
super(entityId, geyserId, entityType, position, motion, rotation); super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
// Set the correct texture if using the resource pack // 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); setMotion(motion);
} }
public void setArrowFlags(EntityMetadata<Byte> entityMetadata) {
byte data = ((ByteEntityMetadata) entityMetadata).getPrimitiveValue();
setFlag(EntityFlag.CRITICAL, (data & 0x01) == 0x01);
}
// Ignore the rotation sent by the Java server since the
// Java client calculates the rotation from the motion
@Override @Override
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { public void setYaw(float yaw) {
if (entityMetadata.getId() == 8) {
byte data = (byte) entityMetadata.getValue();
metadata.getFlags().setFlag(EntityFlag.CRITICAL, (data & 0x01) == 0x01);
}
super.updateBedrockMetadata(entityMetadata, session);
} }
@Override @Override
public void setRotation(Vector3f rotation) { public void setPitch(float pitch) {
// Ignore the rotation sent by the Java server since the }
// Java client calculates the rotation from the motion
@Override
public void setHeadYaw(float headYaw) {
} }
@Override @Override
@ -64,8 +70,8 @@ public class AbstractArrowEntity extends Entity {
super.setMotion(motion); super.setMotion(motion);
double horizontalSpeed = Math.sqrt(motion.getX() * motion.getX() + motion.getZ() * motion.getZ()); double horizontalSpeed = Math.sqrt(motion.getX() * motion.getX() + motion.getZ() * motion.getZ());
float yaw = (float) Math.toDegrees(Math.atan2(motion.getX(), motion.getZ())); this.yaw = (float) Math.toDegrees(Math.atan2(motion.getX(), motion.getZ()));
float pitch = (float) Math.toDegrees(Math.atan2(motion.getY(), horizontalSpeed)); this.pitch = (float) Math.toDegrees(Math.atan2(motion.getY(), horizontalSpeed));
rotation = Vector3f.from(yaw, pitch, yaw); this.headYaw = yaw;
} }
} }

Datei anzeigen

@ -26,44 +26,47 @@
package org.geysermc.connector.entity; 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.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.github.steveice10.mc.protocol.data.game.level.particle.Particle;
import com.nukkitx.math.vector.Vector3f; import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityData; import com.nukkitx.protocol.bedrock.data.entity.EntityData;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag; 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.network.session.GeyserSession;
import org.geysermc.connector.utils.EffectUtils; import org.geysermc.connector.utils.EffectUtils;
import java.util.UUID;
public class AreaEffectCloudEntity extends Entity { public class AreaEffectCloudEntity extends Entity {
public AreaEffectCloudEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { public AreaEffectCloudEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
super(entityId, geyserId, entityType, position, motion, rotation); super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
// 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);
} }
@Override @Override
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { protected void initializeMetadata() {
if (entityMetadata.getId() == 8) { super.initializeMetadata();
metadata.put(EntityData.AREA_EFFECT_CLOUD_RADIUS, entityMetadata.getValue()); // Without this the cloud doesn't appear,
metadata.put(EntityData.BOUNDING_BOX_WIDTH, 2.0f * (float) entityMetadata.getValue()); dirtyMetadata.put(EntityData.AREA_EFFECT_CLOUD_DURATION, 600);
} else if (entityMetadata.getId() == 9) {
metadata.put(EntityData.EFFECT_COLOR, entityMetadata.getValue()); // This disabled client side shrink of the cloud
} else if (entityMetadata.getId() == 11) { dirtyMetadata.put(EntityData.AREA_EFFECT_CLOUD_RADIUS, 0.0f);
Particle particle = (Particle) entityMetadata.getValue(); dirtyMetadata.put(EntityData.AREA_EFFECT_CLOUD_CHANGE_RATE, -0.005f);
int particleId = EffectUtils.getParticleId(session, particle.getType()); dirtyMetadata.put(EntityData.AREA_EFFECT_CLOUD_CHANGE_ON_PICKUP, -0.5f);
if (particleId != -1) {
metadata.put(EntityData.AREA_EFFECT_CLOUD_PARTICLE_ID, particleId); 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) {
dirtyMetadata.put(EntityData.AREA_EFFECT_CLOUD_PARTICLE_ID, particleId);
} }
super.updateBedrockMetadata(entityMetadata, session);
} }
} }

Datei anzeigen

@ -26,13 +26,16 @@
package org.geysermc.connector.entity; 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.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.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityData; import com.nukkitx.protocol.bedrock.data.entity.EntityData;
import com.nukkitx.protocol.bedrock.packet.AnimatePacket; import com.nukkitx.protocol.bedrock.packet.AnimatePacket;
import com.nukkitx.protocol.bedrock.packet.MoveEntityAbsolutePacket; 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 org.geysermc.connector.network.session.GeyserSession;
import java.util.UUID;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
public class BoatEntity extends Entity { public class BoatEntity extends Entity {
@ -52,28 +55,36 @@ public class BoatEntity extends Entity {
private boolean isPaddlingRight; private boolean isPaddlingRight;
private float paddleTimeRight; 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 // 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; private final float ROWING_SPEED = 0.05f;
public BoatEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { public BoatEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
super(entityId, geyserId, entityType, position.add(0d, entityType.getOffset(), 0d), motion, rotation.add(90, 0, 90)); // 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+ // 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); dirtyMetadata.put(EntityData.IS_BUOYANT, (byte) 1);
metadata.put(EntityData.BUOYANCY_DATA, BUOYANCY_DATA); dirtyMetadata.put(EntityData.BUOYANCY_DATA, BUOYANCY_DATA);
} }
@Override @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 // We don't include the rotation (y) as it causes the boat to appear sideways
setPosition(position.add(0d, this.entityType.getOffset(), 0d)); setPosition(position.add(0d, this.definition.offset(), 0d));
setRotation(Vector3f.from(rotation.getX() + 90, 0, rotation.getX() + 90)); this.yaw = yaw + 90;
this.headYaw = yaw + 90;
setOnGround(isOnGround); setOnGround(isOnGround);
MoveEntityAbsolutePacket moveEntityPacket = new MoveEntityAbsolutePacket(); MoveEntityAbsolutePacket moveEntityPacket = new MoveEntityAbsolutePacket();
moveEntityPacket.setRuntimeEntityId(geyserId); moveEntityPacket.setRuntimeEntityId(geyserId);
// Minimal glitching when ClientboundMoveVehiclePacket is sent // 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.setRotation(getBedrockRotation());
moveEntityPacket.setOnGround(isOnGround); moveEntityPacket.setOnGround(isOnGround);
moveEntityPacket.setTeleported(teleported); moveEntityPacket.setTeleported(teleported);
@ -84,91 +95,62 @@ public class BoatEntity extends Entity {
/** /**
* Move the boat without making the adjustments needed to translate from Java * 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) { public void moveAbsoluteWithoutAdjustments(Vector3f position, float yaw, boolean isOnGround, boolean teleported) {
super.moveAbsolute(session, position, Vector3f.from(rotation.getX(), 0, rotation.getX()), isOnGround, teleported); super.moveAbsolute(position, yaw, 0, yaw, isOnGround, teleported);
} }
@Override @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) {
super.moveRelative(session, relX, relY, relZ, Vector3f.from(rotation.getX(), 0, rotation.getX()), isOnGround); super.moveRelative(relX, relY, relZ, yaw, 0, yaw, isOnGround);
} }
@Override @Override
public void updatePositionAndRotation(GeyserSession session, double moveX, double moveY, double moveZ, float yaw, float pitch, boolean isOnGround) { public void updatePositionAndRotation(double moveX, double moveY, double moveZ, float yaw, float pitch, boolean isOnGround) {
moveRelative(session, moveX, moveY, moveZ, yaw + 90, pitch, isOnGround); moveRelative(moveX, moveY, moveZ, yaw + 90, pitch, isOnGround);
} }
@Override @Override
public void updateRotation(GeyserSession session, float yaw, float pitch, boolean isOnGround) { public void updateRotation(float yaw, float pitch, boolean isOnGround) {
moveRelative(session, 0, 0, 0, Vector3f.from(yaw + 90, 0, 0), isOnGround); moveRelative(0, 0, 0, yaw + 90, 0, 0, isOnGround);
} }
@Override public void setVariant(EntityMetadata<Integer> entityMetadata) {
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { variant = ((IntEntityMetadata) entityMetadata).getPrimitiveValue();
// Time since last hit dirtyMetadata.put(EntityData.VARIANT, variant);
if (entityMetadata.getId() == 8) { }
metadata.put(EntityData.HURT_TIME, entityMetadata.getValue());
}
// Rocking direction public void setPaddlingLeft(EntityMetadata<Boolean> entityMetadata) {
if (entityMetadata.getId() == 9) { isPaddlingLeft = ((BooleanEntityMetadata) entityMetadata).getPrimitiveValue();
metadata.put(EntityData.HURT_DIRECTION, entityMetadata.getValue()); 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.
// 'Health' in Bedrock, damage taken in Java paddleTimeLeft = 0f;
if (entityMetadata.getId() == 10) { if (!this.passengers.isEmpty()) {
// Not exactly health but it makes motion in Bedrock // Get the entity by the first stored passenger and convey motion in this manner
metadata.put(EntityData.HEALTH, 40 - ((int) (float) entityMetadata.getValue())); Entity entity = session.getEntityCache().getEntityByJavaId(this.passengers.iterator().nextLong());
} if (entity != null) {
updateLeftPaddle(session, entity);
if (entityMetadata.getId() == 11) {
metadata.put(EntityData.VARIANT, entityMetadata.getValue());
} else if (entityMetadata.getId() == 12) {
isPaddlingLeft = (boolean) entityMetadata.getValue();
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.
paddleTimeLeft = 0f;
if (!this.passengers.isEmpty()) {
// Get the entity by the first stored passenger and convey motion in this manner
Entity entity = session.getEntityCache().getEntityByJavaId(this.passengers.iterator().nextLong());
if (entity != null) {
updateLeftPaddle(session, entity);
}
} }
} else {
// Indicate that the row position should be reset
metadata.put(EntityData.ROW_TIME_LEFT, 0.0f);
} }
} else {
// Indicate that the row position should be reset
dirtyMetadata.put(EntityData.ROW_TIME_LEFT, 0.0f);
} }
else if (entityMetadata.getId() == 13) {
isPaddlingRight = (boolean) entityMetadata.getValue();
if (isPaddlingRight) {
paddleTimeRight = 0f;
if (!this.passengers.isEmpty()) {
Entity entity = session.getEntityCache().getEntityByJavaId(this.passengers.iterator().nextLong());
if (entity != null) {
updateRightPaddle(session, entity);
}
}
} else {
metadata.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 setPaddlingRight(EntityMetadata<Boolean> entityMetadata) {
public void updateBedrockMetadata(GeyserSession session) { isPaddlingRight = ((BooleanEntityMetadata) entityMetadata).getPrimitiveValue();
super.updateBedrockMetadata(session); if (isPaddlingRight) {
paddleTimeRight = 0f;
// As these indicate to reset rowing, remove them until it is time to send them out again. if (!this.passengers.isEmpty()) {
metadata.remove(EntityData.ROW_TIME_LEFT); Entity entity = session.getEntityCache().getEntityByJavaId(this.passengers.iterator().nextLong());
metadata.remove(EntityData.ROW_TIME_RIGHT); if (entity != null) {
updateRightPaddle(session, entity);
}
}
} else {
dirtyMetadata.put(EntityData.ROW_TIME_RIGHT, 0.0f);
}
} }
private void updateLeftPaddle(GeyserSession session, Entity rower) { private void updateLeftPaddle(GeyserSession session, Entity rower) {

Datei anzeigen

@ -25,42 +25,33 @@
package org.geysermc.connector.entity; package org.geysermc.connector.entity;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
import com.nukkitx.math.vector.Vector3f; import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityData; import 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.session.GeyserSession;
import org.geysermc.connector.network.translators.chat.MessageTranslator;
import java.util.UUID;
public class CommandBlockMinecartEntity extends DefaultBlockMinecartEntity { public class CommandBlockMinecartEntity extends DefaultBlockMinecartEntity {
public CommandBlockMinecartEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { public CommandBlockMinecartEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
super(entityId, geyserId, entityType, position, motion, rotation); super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
// 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);
} }
@Override @Override
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { protected void initializeMetadata() {
if (entityMetadata.getId() == 14) { // Required, or else the GUI will not open
metadata.put(EntityData.COMMAND_BLOCK_COMMAND, entityMetadata.getValue()); dirtyMetadata.put(EntityData.CONTAINER_TYPE, (byte) 16);
} dirtyMetadata.put(EntityData.CONTAINER_BASE_SIZE, 1);
if (entityMetadata.getId() == 15) { // Required, or else the client does not bother to send a packet back with the new information
metadata.put(EntityData.COMMAND_BLOCK_LAST_OUTPUT, MessageTranslator.convertMessage((Component) entityMetadata.getValue())); dirtyMetadata.put(EntityData.COMMAND_BLOCK_ENABLED, (byte) 1);
}
super.updateBedrockMetadata(entityMetadata, session);
} }
/** /**
* By default, the command block shown is purple on Bedrock, which does not match Java Edition's orange. * By default, the command block shown is purple on Bedrock, which does not match Java Edition's orange.
*/ */
@Override @Override
public void updateDefaultBlockMetadata(GeyserSession session) { public void updateDefaultBlockMetadata() {
metadata.put(EntityData.DISPLAY_ITEM, session.getBlockMappings().getCommandBlockRuntimeId()); dirtyMetadata.put(EntityData.DISPLAY_ITEM, session.getBlockMappings().getCommandBlockRuntimeId());
metadata.put(EntityData.DISPLAY_OFFSET, 6); dirtyMetadata.put(EntityData.DISPLAY_OFFSET, 6);
} }
} }

Datei anzeigen

@ -26,11 +26,14 @@
package org.geysermc.connector.entity; 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.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.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityData; 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.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 * 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 int customBlockOffset = 0;
public boolean showCustomBlock = false; public boolean showCustomBlock = false;
public DefaultBlockMinecartEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { public DefaultBlockMinecartEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
super(entityId, geyserId, entityType, position, motion, rotation); 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 @Override
public void spawnEntity(GeyserSession session) { public void spawnEntity() {
updateDefaultBlockMetadata(session); updateDefaultBlockMetadata();
super.spawnEntity(session); super.spawnEntity();
} }
@Override @Override
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { public void setCustomBlock(EntityMetadata<Integer> entityMetadata) {
customBlock = ((IntEntityMetadata) entityMetadata).getPrimitiveValue();
// Custom block if (showCustomBlock) {
if (entityMetadata.getId() == 11) { dirtyMetadata.put(EntityData.DISPLAY_ITEM, session.getBlockMappings().getBedrockBlockId(customBlock));
customBlock = (int) entityMetadata.getValue();
if (showCustomBlock) {
metadata.put(EntityData.DISPLAY_ITEM, session.getBlockMappings().getBedrockBlockId(customBlock));
}
} }
// Custom block offset
if (entityMetadata.getId() == 12) {
customBlockOffset = (int) entityMetadata.getValue();
if (showCustomBlock) {
metadata.put(EntityData.DISPLAY_OFFSET, customBlockOffset);
}
}
// If the custom block should be enabled
if (entityMetadata.getId() == 13) {
if ((boolean) entityMetadata.getValue()) {
showCustomBlock = true;
metadata.put(EntityData.DISPLAY_ITEM, session.getBlockMappings().getBedrockBlockId(customBlock));
metadata.put(EntityData.DISPLAY_OFFSET, customBlockOffset);
} else {
showCustomBlock = false;
updateDefaultBlockMetadata(session);
}
}
super.updateBedrockMetadata(entityMetadata, session);
} }
public void updateDefaultBlockMetadata(GeyserSession session) { } @Override
public void setCustomBlockOffset(EntityMetadata<Integer> entityMetadata) {
customBlockOffset = ((IntEntityMetadata) entityMetadata).getPrimitiveValue();
if (showCustomBlock) {
dirtyMetadata.put(EntityData.DISPLAY_OFFSET, customBlockOffset);
}
}
@Override
public void setShowCustomBlock(EntityMetadata<Boolean> entityMetadata) {
if (((BooleanEntityMetadata) entityMetadata).getPrimitiveValue()) {
showCustomBlock = true;
dirtyMetadata.put(EntityData.DISPLAY_ITEM, session.getBlockMappings().getBedrockBlockId(customBlock));
dirtyMetadata.put(EntityData.DISPLAY_OFFSET, customBlockOffset);
} else {
showCustomBlock = false;
updateDefaultBlockMetadata();
}
}
public void updateDefaultBlockMetadata() {
}
} }

Datei anzeigen

@ -31,33 +31,31 @@ import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.math.vector.Vector3i; import com.nukkitx.math.vector.Vector3i;
import com.nukkitx.protocol.bedrock.data.entity.EntityData; import com.nukkitx.protocol.bedrock.data.entity.EntityData;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag; 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.network.session.GeyserSession;
import java.util.UUID;
public class EnderCrystalEntity extends Entity { public class EnderCrystalEntity extends Entity {
public EnderCrystalEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { public EnderCrystalEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
super(entityId, geyserId, entityType, position, motion, rotation); super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
// Bedrock 1.16.100+ - prevents the entity from appearing on fire itself when fire is underneath it
metadata.getFlags().setFlag(EntityFlag.FIRE_IMMUNE, true);
} }
@Override @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 // Show beam
// Usually performed client-side on Bedrock except for Ender Dragon respawn event // Usually performed client-side on Bedrock except for Ender Dragon respawn event
if (entityMetadata.getId() == 8) { Position position = entityMetadata.getValue();
if (entityMetadata.getValue() instanceof Position pos) { if (position != null) {
metadata.put(EntityData.BLOCK_TARGET, Vector3i.from(pos.getX(), pos.getY(), pos.getZ())); dirtyMetadata.put(EntityData.BLOCK_TARGET, Vector3i.from(position.getX(), position.getY(), position.getZ()));
} else { } 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);
} }
} }

Datei anzeigen

@ -26,8 +26,10 @@
package org.geysermc.connector.entity; 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.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.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.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityData; import com.nukkitx.protocol.bedrock.data.entity.EntityData;
import com.nukkitx.protocol.bedrock.data.entity.EntityDataMap; 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.RemoveEntityPacket;
import com.nukkitx.protocol.bedrock.packet.SetEntityDataPacket; import com.nukkitx.protocol.bedrock.packet.SetEntityDataPacket;
import it.unimi.dsi.fastutil.longs.LongOpenHashSet; import it.unimi.dsi.fastutil.longs.LongOpenHashSet;
import lombok.AccessLevel;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import net.kyori.adventure.text.Component; 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.session.GeyserSession;
import org.geysermc.connector.network.translators.chat.MessageTranslator; import org.geysermc.connector.network.translators.chat.MessageTranslator;
import org.geysermc.connector.utils.MathUtils; import org.geysermc.connector.utils.MathUtils;
import java.util.UUID;
@Getter @Getter
@Setter @Setter
public class Entity { public class Entity {
protected final GeyserSession session;
protected long entityId; protected long entityId;
protected final long geyserId; protected final long geyserId;
protected UUID uuid;
protected Vector3f position; protected Vector3f position;
protected Vector3f motion; protected Vector3f motion;
@ -58,85 +65,120 @@ public class Entity {
/** /**
* x = Yaw, y = Pitch, z = HeadYaw * 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 * Saves if the entity should be on the ground. Otherwise entities like parrots are flapping when rotating
*/ */
protected boolean onGround; protected boolean onGround;
protected EntityType entityType; protected EntityDefinition<?> definition;
protected boolean valid; protected boolean valid;
protected LongOpenHashSet passengers = new LongOpenHashSet(); /* Metadata about this specific entity */
protected EntityDataMap metadata = new EntityDataMap(); @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.entityId = entityId;
this.geyserId = geyserId; this.geyserId = geyserId;
this.entityType = entityType; this.uuid = uuid;
this.definition = definition;
this.motion = motion; this.motion = motion;
this.rotation = rotation; this.yaw = yaw;
this.pitch = pitch;
this.headYaw = headYaw;
this.valid = false; this.valid = false;
setPosition(position); setPosition(position);
setAir(getMaxAir()); setAir(getMaxAir());
metadata.put(EntityData.SCALE, 1f); initializeMetadata();
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);
} }
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 addEntityPacket = new AddEntityPacket();
addEntityPacket.setIdentifier(entityType.getIdentifier()); addEntityPacket.setIdentifier(definition.identifier());
addEntityPacket.setRuntimeEntityId(geyserId); addEntityPacket.setRuntimeEntityId(geyserId);
addEntityPacket.setUniqueEntityId(geyserId); addEntityPacket.setUniqueEntityId(geyserId);
addEntityPacket.setPosition(position); addEntityPacket.setPosition(position);
addEntityPacket.setMotion(motion); addEntityPacket.setMotion(motion);
addEntityPacket.setRotation(getBedrockRotation()); addEntityPacket.setRotation(getBedrockRotation());
addEntityPacket.setEntityType(entityType.getType()); addEntityPacket.setEntityType(definition.bedrockId());
addEntityPacket.getMetadata().putAll(metadata); addEntityPacket.getMetadata().putFlags(flags)
.putAll(dirtyMetadata);
addAdditionalSpawnData(addEntityPacket); addAdditionalSpawnData(addEntityPacket);
valid = true; valid = true;
session.sendUpstreamPacket(addEntityPacket); 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. * To be overridden in other entity classes, if additional things need to be done to the spawn entity packet.
*/ */
public void addAdditionalSpawnData(AddEntityPacket addEntityPacket) { public void addAdditionalSpawnData(AddEntityPacket addEntityPacket) {
} }
/** /**
* Despawns the entity * Despawns the entity
* *
* @param session The GeyserSession
* @return can be deleted * @return can be deleted
*/ */
public boolean despawnEntity(GeyserSession session) { public boolean despawnEntity() {
if (!valid) return true; if (!valid) return true;
for (long passenger : passengers) { // Make sure all passengers on the despawned entity are updated for (long passenger : passengers) { // Make sure all passengers on the despawned entity are updated
Entity entity = session.getEntityCache().getEntityByJavaId(passenger); Entity entity = session.getEntityCache().getEntityByJavaId(passenger);
if (entity == null) continue; if (entity == null) continue;
entity.getMetadata().getOrCreateFlags().setFlag(EntityFlag.RIDING, false); entity.setFlag(EntityFlag.RIDING, false);
entity.updateBedrockMetadata(session); entity.updateBedrockMetadata();
} }
RemoveEntityPacket removeEntityPacket = new RemoveEntityPacket(); RemoveEntityPacket removeEntityPacket = new RemoveEntityPacket();
@ -147,12 +189,14 @@ public class Entity {
return true; return true;
} }
public void moveRelative(GeyserSession session, double relX, double relY, double relZ, float yaw, float pitch, boolean isOnGround) { public void moveRelative(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); moveRelative(relX, relY, relZ, yaw, pitch, this.headYaw, isOnGround);
} }
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) {
setRotation(rotation); setYaw(yaw);
setPitch(pitch);
setHeadYaw(headYaw);
setOnGround(isOnGround); setOnGround(isOnGround);
this.position = Vector3f.from(position.getX() + relX, position.getY() + relY, position.getZ() + relZ); this.position = Vector3f.from(position.getX() + relX, position.getY() + relY, position.getZ() + relZ);
@ -166,13 +210,16 @@ public class Entity {
session.sendUpstreamPacket(moveEntityPacket); session.sendUpstreamPacket(moveEntityPacket);
} }
public void moveAbsolute(GeyserSession session, Vector3f position, float yaw, float pitch, boolean isOnGround, boolean teleported) { public void moveAbsolute(Vector3f position, float yaw, float pitch, boolean isOnGround, boolean teleported) {
moveAbsolute(session, position, Vector3f.from(yaw, pitch, this.rotation.getZ()), isOnGround, 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); setPosition(position);
setRotation(rotation); // Setters are intentional so it can be overridden in places like AbstractArrowEntity
setYaw(yaw);
setPitch(pitch);
setHeadYaw(headYaw);
setOnGround(isOnGround); setOnGround(isOnGround);
MoveEntityAbsolutePacket moveEntityPacket = new MoveEntityAbsolutePacket(); MoveEntityAbsolutePacket moveEntityPacket = new MoveEntityAbsolutePacket();
@ -187,28 +234,25 @@ public class Entity {
/** /**
* Teleports an entity to a new location. Used in JavaTeleportEntityTranslator. * Teleports an entity to a new location. Used in JavaTeleportEntityTranslator.
* @param session GeyserSession.
* @param position The new position of the entity. * @param position The new position of the entity.
* @param yaw The new yaw of the entity. * @param yaw The new yaw of the entity.
* @param pitch The new pitch of the entity. * @param pitch The new pitch of the entity.
* @param isOnGround Whether the entity is currently on the ground. * @param isOnGround Whether the entity is currently on the ground.
*/ */
public void teleport(GeyserSession session, Vector3f position, float yaw, float pitch, boolean isOnGround) { public void teleport(Vector3f position, float yaw, float pitch, boolean isOnGround) {
moveAbsolute(session, position, yaw, pitch, isOnGround, false); moveAbsolute(position, yaw, pitch, isOnGround, false);
} }
/** /**
* Updates an entity's head position. Used in JavaRotateHeadTranslator. * Updates an entity's head position. Used in JavaRotateHeadTranslator.
* @param session GeyserSession.
* @param headYaw The new head rotation of the entity. * @param headYaw The new head rotation of the entity.
*/ */
public void updateHeadLookRotation(GeyserSession session, float headYaw) { public void updateHeadLookRotation(float headYaw) {
moveRelative(session, 0, 0, 0, Vector3f.from(headYaw, rotation.getY(), rotation.getZ()), onGround); moveRelative(0, 0, 0, headYaw, pitch, this.headYaw, onGround);
} }
/** /**
* Updates an entity's position and rotation. Used in JavaMoveEntityPosRotTranslator. * Updates an entity's position and rotation. Used in JavaMoveEntityPosRotTranslator.
* @param session GeyserSession
* @param moveX The new X offset of the current position. * @param moveX The new X offset of the current position.
* @param moveY The new Y offset of the current position. * @param moveY The new Y offset of the current position.
* @param moveZ The new Z offset of the current position. * @param 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 pitch The new pitch of the entity.
* @param isOnGround Whether the entity is currently on the ground. * @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) { public void updatePositionAndRotation(double moveX, double moveY, double moveZ, float yaw, float pitch, boolean isOnGround) {
moveRelative(session, moveX, moveY, moveZ, Vector3f.from(rotation.getX(), pitch, yaw), isOnGround); moveRelative(moveX, moveY, moveZ, this.yaw, pitch, yaw, isOnGround);
} }
/** /**
* Updates an entity's rotation. Used in JavaMoveEntityRotTranslator. * Updates an entity's rotation. Used in JavaMoveEntityRotTranslator.
* @param session GeyserSession.
* @param yaw The new yaw of the entity. * @param yaw The new yaw of the entity.
* @param pitch The new pitch of the entity. * @param pitch The new pitch of the entity.
* @param isOnGround Whether the entity is currently on the ground. * @param isOnGround Whether the entity is currently on the ground.
*/ */
public void updateRotation(GeyserSession session, float yaw, float pitch, boolean isOnGround) { public void updateRotation(float yaw, float pitch, boolean isOnGround) {
updatePositionAndRotation(session, 0, 0, 0, yaw, pitch, 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 * Updates a flag value and determines if the flags would need synced with the Bedrock client.
* @param entityMetadata the Java entity metadata
* @param session GeyserSession
*/ */
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { public final void setFlag(EntityFlag flag, boolean value) {
switch (entityMetadata.getId()) { flagsDirty |= flags.setFlag(flag, value);
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;
}
} }
/** /**
* Sends the Bedrock metadata to the client * Sends the Bedrock metadata to the client
* @param session GeyserSession
*/ */
public void updateBedrockMetadata(GeyserSession session) { public void updateBedrockMetadata() {
if (!valid) return; if (!valid) {
return;
}
SetEntityDataPacket entityDataPacket = new SetEntityDataPacket(); if (!dirtyMetadata.isEmpty() || flagsDirty) {
entityDataPacket.setRuntimeEntityId(geyserId); SetEntityDataPacket entityDataPacket = new SetEntityDataPacket();
entityDataPacket.getMetadata().putAll(metadata); entityDataPacket.setRuntimeEntityId(geyserId);
session.sendUpstreamPacket(entityDataPacket); entityDataPacket.getMetadata().putFlags(flags);
} entityDataPacket.getMetadata().putAll(dirtyMetadata);
session.sendUpstreamPacket(entityDataPacket);
/** dirtyMetadata.clear();
* If true, the entity should be shaking on the client's end. flagsDirty = false;
*
* @return whether {@link EntityFlag#SHAKING} should be set to true.
*/
protected boolean isShaking(GeyserSession session) {
return false;
}
protected void setDisplayName(GeyserSession session, Component name) {
if (name != null) {
String displayName = MessageTranslator.convertMessage(name, session.getLocale());
metadata.put(EntityData.NAMETAG, displayName);
} else if (!metadata.getString(EntityData.NAMETAG).isEmpty()) {
// Clear nametag
metadata.put(EntityData.NAMETAG, "");
} }
} }
protected void setDisplayNameVisible(EntityMetadata entityMetadata) { public void setFlags(EntityMetadata<Byte> entityMetadata) {
metadata.put(EntityData.NAMETAG_ALWAYS_SHOW, (byte) ((boolean) entityMetadata.getValue() ? 1 : 0)); 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);
}
/**
* Set a boolean - whether the entity is invisible or visible
*
* @param value true if the entity is invisible
*/
protected void setInvisible(boolean value) {
setFlag(EntityFlag.INVISIBLE, value);
}
/**
* 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());
dirtyMetadata.put(EntityData.NAMETAG, displayName);
} else if (!dirtyMetadata.getString(EntityData.NAMETAG).isEmpty()) { //TODO
// Clear nametag
dirtyMetadata.put(EntityData.NAMETAG, "");
}
}
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) { protected void setDimensions(Pose pose) {
// No flexibility options for basic entities // No flexibility options for basic entities
//TODO don't even set this for basic entities since we already set it on entity initialization if (boundingBoxHeight != definition.height() || boundingBoxWidth != definition.width()) {
metadata.put(EntityData.BOUNDING_BOX_WIDTH, entityType.getWidth()); boundingBoxWidth = definition.width();
metadata.put(EntityData.BOUNDING_BOX_HEIGHT, entityType.getHeight()); 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. * Set a float from 0-1 - how strong the "frozen" overlay should be on screen.
*/ */
protected void setFreezing(GeyserSession session, float amount) { public float setFreezing(EntityMetadata<Integer> entityMetadata) {
metadata.put(EntityData.FREEZING_EFFECT_STRENGTH, amount); // 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 * If true, the entity should be shaking on the client's end.
* @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
* *
* @param session the Geyser session * @return whether {@link EntityFlag#SHAKING} should be set to true.
* @param value true if the entity is invisible
*/ */
protected void setInvisible(GeyserSession session, boolean value) { protected boolean isShaking() {
metadata.getFlags().setFlag(EntityFlag.INVISIBLE, value); return false;
} }
/** /**
@ -363,7 +411,7 @@ public class Entity {
* @return the bedrock rotation * @return the bedrock rotation
*/ */
public Vector3f getBedrockRotation() { public Vector3f getBedrockRotation() {
return Vector3f.from(rotation.getY(), rotation.getZ(), rotation.getX()); return Vector3f.from(pitch, headYaw, yaw);
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")

Datei anzeigen

@ -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;
}
}
}

Datei anzeigen

@ -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() {
}
}

Datei anzeigen

@ -23,29 +23,18 @@
* @link https://github.com/GeyserMC/Geyser * @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.EntityMetadata;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.MetadataType; 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 record EntityMetadataTranslator<E extends Entity, T>(
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { MetadataType acceptedType,
if (entityMetadata.getId() == 15 && entityMetadata.getType() == MetadataType.BYTE) { BiConsumer<E, EntityMetadata<T>> translateFunction) {
byte xd = (byte) entityMetadata.getValue();
metadata.getFlags().setFlag(EntityFlag.NO_AI, (xd & 0x01) == 0x01);
}
super.updateBedrockMetadata(entityMetadata, session);
}
} }

Datei anzeigen

@ -27,22 +27,21 @@ package org.geysermc.connector.entity;
import com.nukkitx.math.vector.Vector3f; import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityData; 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.session.GeyserSession;
public class ExpOrbEntity extends Entity { public class ExpOrbEntity extends Entity {
private final int amount; private final int amount;
public ExpOrbEntity(int amount, long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { public ExpOrbEntity(GeyserSession session, int amount, long entityId, long geyserId, Vector3f position) {
super(entityId, geyserId, entityType, position, motion, rotation); super(session, entityId, geyserId, null, EntityDefinitions.EXPERIENCE_ORB, position, Vector3f.ZERO, 0, 0, 0);
this.amount = amount; this.amount = amount;
} }
@Override @Override
public void spawnEntity(GeyserSession session) { protected void initializeMetadata() {
this.metadata.put(EntityData.EXPERIENCE_VALUE, amount); super.initializeMetadata();
super.spawnEntity(session); this.dirtyMetadata.put(EntityData.EXPERIENCE_VALUE, amount);
} }
} }

Datei anzeigen

@ -26,31 +26,32 @@
package org.geysermc.connector.entity; 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.EntityMetadata;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanEntityMetadata;
import com.nukkitx.math.vector.Vector3f; import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityData; import com.nukkitx.protocol.bedrock.data.entity.EntityData;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag; 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.network.session.GeyserSession;
import java.util.UUID;
public class FallingBlockEntity extends Entity { public class FallingBlockEntity extends Entity {
private final int javaId; private final int javaId;
public FallingBlockEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation, int javaId) { public FallingBlockEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, Vector3f position, Vector3f motion, float yaw, float pitch, int javaId) {
super(entityId, geyserId, entityType, position, motion, rotation); super(session, entityId, geyserId, uuid, EntityDefinitions.FALLING_BLOCK, position, motion, yaw, pitch, 0f);
this.javaId = javaId; this.javaId = javaId;
} }
@Override @Override
public void spawnEntity(GeyserSession session) { protected void initializeMetadata() {
this.metadata.put(EntityData.VARIANT, session.getBlockMappings().getBedrockBlockId(javaId)); super.initializeMetadata();
super.spawnEntity(session); this.dirtyMetadata.put(EntityData.VARIANT, session.getBlockMappings().getBedrockBlockId(javaId));
} }
@Override @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 // Set the NO_AI flag based on the no gravity flag to prevent movement
if (entityMetadata.getId() == 5) { setFlag(EntityFlag.NO_AI, ((BooleanEntityMetadata) entityMetadata).getPrimitiveValue());
this.metadata.getFlags().setFlag(EntityFlag.NO_AI, (boolean) entityMetadata.getValue());
}
} }
} }

Datei anzeigen

@ -37,7 +37,6 @@ import com.nukkitx.nbt.NbtType;
import com.nukkitx.protocol.bedrock.data.entity.EntityData; import com.nukkitx.protocol.bedrock.data.entity.EntityData;
import com.nukkitx.protocol.bedrock.packet.SetEntityMotionPacket; import com.nukkitx.protocol.bedrock.packet.SetEntityMotionPacket;
import org.geysermc.connector.entity.player.PlayerEntity; 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.session.GeyserSession;
import org.geysermc.connector.utils.FireworkColor; import org.geysermc.connector.utils.FireworkColor;
import org.geysermc.connector.utils.MathUtils; import org.geysermc.connector.utils.MathUtils;
@ -46,118 +45,116 @@ import org.geysermc.floodgate.util.DeviceOs;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.OptionalInt; import java.util.OptionalInt;
import java.util.UUID;
public class FireworkEntity extends Entity { public class FireworkEntity extends Entity {
public FireworkEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { public FireworkEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
super(entityId, geyserId, entityType, position, motion, rotation); super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
} }
@Override public void setFireworkItem(EntityMetadata<ItemStack> entityMetadata) {
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { ItemStack item = entityMetadata.getValue();
if (entityMetadata.getId() == 8) { if (item == null) {
ItemStack item = (ItemStack) entityMetadata.getValue(); return;
if (item == null) { }
return; CompoundTag tag = item.getNbt();
}
CompoundTag tag = item.getNbt();
if (tag == null) { if (tag == null) {
return; return;
} }
// TODO: Remove once Mojang fixes bugs with fireworks crashing clients on these specific devices. // TODO: Remove once Mojang fixes bugs with fireworks crashing clients on these specific devices.
// https://bugs.mojang.com/browse/MCPE-89115 // https://bugs.mojang.com/browse/MCPE-89115
if (session.getClientData().getDeviceOs() == DeviceOs.XBOX if (session.getClientData().getDeviceOs() == DeviceOs.XBOX
|| session.getClientData().getDeviceOs() == DeviceOs.PS4) { || session.getClientData().getDeviceOs() == DeviceOs.PS4) {
return; return;
} }
CompoundTag fireworks = tag.get("Fireworks"); CompoundTag fireworks = tag.get("Fireworks");
if (fireworks == null) { if (fireworks == null) {
// Thank you Mineplex very cool // Thank you Mineplex very cool
return; return;
} }
NbtMapBuilder fireworksBuilder = NbtMap.builder(); NbtMapBuilder fireworksBuilder = NbtMap.builder();
if (fireworks.get("Flight") != null) { if (fireworks.get("Flight") != null) {
fireworksBuilder.putByte("Flight", MathUtils.getNbtByte(fireworks.get("Flight").getValue())); fireworksBuilder.putByte("Flight", MathUtils.getNbtByte(fireworks.get("Flight").getValue()));
} }
List<NbtMap> explosions = new ArrayList<>(); List<NbtMap> explosions = new ArrayList<>();
if (fireworks.get("Explosions") != null) { if (fireworks.get("Explosions") != null) {
for (Tag effect : ((ListTag) fireworks.get("Explosions")).getValue()) { for (Tag effect : ((ListTag) fireworks.get("Explosions")).getValue()) {
CompoundTag effectData = (CompoundTag) effect; CompoundTag effectData = (CompoundTag) effect;
NbtMapBuilder effectBuilder = NbtMap.builder(); NbtMapBuilder effectBuilder = NbtMap.builder();
if (effectData.get("Type") != null) { if (effectData.get("Type") != null) {
effectBuilder.putByte("FireworkType", MathUtils.getNbtByte(effectData.get("Type").getValue())); effectBuilder.putByte("FireworkType", MathUtils.getNbtByte(effectData.get("Type").getValue()));
}
if (effectData.get("Colors") != null) {
int[] oldColors = (int[]) effectData.get("Colors").getValue();
byte[] colors = new byte[oldColors.length];
int i = 0;
for (int color : oldColors) {
colors[i++] = FireworkColor.fromJavaRGB(color);
}
effectBuilder.putByteArray("FireworkColor", colors);
}
if (effectData.get("FadeColors") != null) {
int[] oldColors = (int[]) effectData.get("FadeColors").getValue();
byte[] colors = new byte[oldColors.length];
int i = 0;
for (int color : oldColors) {
colors[i++] = FireworkColor.fromJavaRGB(color);
}
effectBuilder.putByteArray("FireworkFade", colors);
}
if (effectData.get("Trail") != null) {
effectBuilder.putByte("FireworkTrail", MathUtils.getNbtByte(effectData.get("Trail").getValue()));
}
if (effectData.get("Flicker") != null) {
effectBuilder.putByte("FireworkFlicker", MathUtils.getNbtByte(effectData.get("Flicker").getValue()));
}
explosions.add(effectBuilder.build());
} }
}
fireworksBuilder.putList("Explosions", NbtType.COMPOUND, explosions); if (effectData.get("Colors") != null) {
int[] oldColors = (int[]) effectData.get("Colors").getValue();
byte[] colors = new byte[oldColors.length];
NbtMapBuilder builder = NbtMap.builder(); int i = 0;
builder.put("Fireworks", fireworksBuilder.build()); for (int color : oldColors) {
metadata.put(EntityData.DISPLAY_ITEM, builder.build()); colors[i++] = FireworkColor.fromJavaRGB(color);
} else if (entityMetadata.getId() == 9) { }
OptionalInt optional = (OptionalInt) 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();
// Uses math from NukkitX
entity.setMotion(Vector3f.from(
-Math.sin(Math.toRadians(yaw)) * Math.cos(Math.toRadians(pitch)) * 2,
-Math.sin(Math.toRadians(pitch)) * 2,
Math.cos(Math.toRadians(yaw)) * Math.cos(Math.toRadians(pitch)) * 2));
// Need to update the EntityMotionPacket or else the player won't boost
SetEntityMotionPacket entityMotionPacket = new SetEntityMotionPacket();
entityMotionPacket.setRuntimeEntityId(entity.getGeyserId());
entityMotionPacket.setMotion(entity.getMotion());
session.sendUpstreamPacket(entityMotionPacket); effectBuilder.putByteArray("FireworkColor", colors);
}
if (effectData.get("FadeColors") != null) {
int[] oldColors = (int[]) effectData.get("FadeColors").getValue();
byte[] colors = new byte[oldColors.length];
int i = 0;
for (int color : oldColors) {
colors[i++] = FireworkColor.fromJavaRGB(color);
}
effectBuilder.putByteArray("FireworkFade", colors);
}
if (effectData.get("Trail") != null) {
effectBuilder.putByte("FireworkTrail", MathUtils.getNbtByte(effectData.get("Trail").getValue()));
}
if (effectData.get("Flicker") != null) {
effectBuilder.putByte("FireworkFlicker", MathUtils.getNbtByte(effectData.get("Flicker").getValue()));
}
explosions.add(effectBuilder.build());
} }
} }
super.updateBedrockMetadata(entityMetadata, session); fireworksBuilder.putList("Explosions", NbtType.COMPOUND, explosions);
NbtMapBuilder builder = NbtMap.builder();
builder.put("Fireworks", fireworksBuilder.build());
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.getYaw();
float pitch = entity.getPitch();
// Uses math from NukkitX
entity.setMotion(Vector3f.from(
-Math.sin(Math.toRadians(yaw)) * Math.cos(Math.toRadians(pitch)) * 2,
-Math.sin(Math.toRadians(pitch)) * 2,
Math.cos(Math.toRadians(yaw)) * Math.cos(Math.toRadians(pitch)) * 2));
// Need to update the EntityMotionPacket or else the player won't boost
SetEntityMotionPacket entityMotionPacket = new SetEntityMotionPacket();
entityMotionPacket.setRuntimeEntityId(entity.getGeyserId());
entityMotionPacket.setMotion(entity.getMotion());
session.sendUpstreamPacket(entityMotionPacket);
}
} }
} }

Datei anzeigen

@ -26,12 +26,12 @@
package org.geysermc.connector.entity; 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.EntityMetadata;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata;
import com.nukkitx.math.vector.Vector3f; import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityData; import com.nukkitx.protocol.bedrock.data.entity.EntityData;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag; import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
import com.nukkitx.protocol.bedrock.packet.PlaySoundPacket; import com.nukkitx.protocol.bedrock.packet.PlaySoundPacket;
import org.geysermc.connector.entity.player.PlayerEntity; 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.session.GeyserSession;
import org.geysermc.connector.network.translators.collision.BoundingBox; import org.geysermc.connector.network.translators.collision.BoundingBox;
import org.geysermc.connector.network.translators.collision.translators.BlockCollision; 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.BlockPositionIterator;
import org.geysermc.connector.utils.BlockUtils; import org.geysermc.connector.utils.BlockUtils;
import java.util.UUID;
import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.ThreadLocalRandom;
public class FishingHookEntity extends ThrowableEntity { public class FishingHookEntity extends ThrowableEntity {
@ -50,41 +51,44 @@ public class FishingHookEntity extends ThrowableEntity {
private boolean inWater = false; private boolean inWater = false;
public FishingHookEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation, PlayerEntity owner) { public FishingHookEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, Vector3f position, Vector3f motion, float yaw, float pitch, PlayerEntity owner) {
super(entityId, geyserId, entityType, position, motion, rotation); 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); 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. // 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, // 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. // 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 @Override
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { public void spawnEntity() {
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) {
entity = session.getPlayerEntity();
}
if (entity != null) { super.spawnEntity();
metadata.put(EntityData.TARGET_EID, entity.getGeyserId()); }
hooked = true;
} else { public void setHookedEntity(EntityMetadata<Integer> entityMetadata) {
hooked = false; int hookedEntityId = ((IntEntityMetadata) entityMetadata).getPrimitiveValue() - 1;
} Entity entity;
if (session.getPlayerEntity().getEntityId() == hookedEntityId) {
entity = session.getPlayerEntity();
} else {
entity = session.getEntityCache().getEntityByJavaId(hookedEntityId);
} }
super.updateBedrockMetadata(entityMetadata, session); if (entity != null) {
dirtyMetadata.put(EntityData.TARGET_EID, entity.getGeyserId());
hooked = true;
} else {
hooked = false;
}
} }
@Override @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.setMiddleX(position.getX());
boundingBox.setMiddleY(position.getY() + boundingBox.getSizeY() / 2); boundingBox.setMiddleY(position.getY() + boundingBox.getSizeY() / 2);
boundingBox.setMiddleZ(position.getZ()); boundingBox.setMiddleZ(position.getZ());
@ -123,14 +127,14 @@ public class FishingHookEntity extends ThrowableEntity {
inWater = touchingWater; inWater = touchingWater;
if (!collided) { if (!collided) {
super.moveAbsoluteImmediate(session, position, rotation, isOnGround, teleported); super.moveAbsoluteImmediate(position, yaw, pitch, headYaw, isOnGround, teleported);
} else { } else {
super.moveAbsoluteImmediate(session, this.position, rotation, true, true); super.moveAbsoluteImmediate(this.position, yaw, pitch, headYaw, true, true);
} }
} }
private void sendSplashSound(GeyserSession session) { 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())); float volume = (float) (0.2f * Math.sqrt(0.2 * (motion.getX() * motion.getX() + motion.getZ() * motion.getZ()) + motion.getY() * motion.getY()));
if (volume > 1) { if (volume > 1) {
volume = 1; volume = 1;
@ -145,39 +149,38 @@ public class FishingHookEntity extends ThrowableEntity {
} }
@Override @Override
public void tick(GeyserSession session) { public void tick() {
if (hooked || !isInAir(session) && !isInWater(session) || isOnGround()) { if (hooked || !isInAir() && !isInWater() || isOnGround()) {
motion = Vector3f.ZERO; motion = Vector3f.ZERO;
return; return;
} }
float gravity = getGravity(session); float gravity = getGravity();
motion = motion.down(gravity); 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); motion = motion.mul(drag);
} }
@Override @Override
protected float getGravity(GeyserSession session) { protected float getGravity() {
if (!isInWater(session) && !onGround) { if (!isInWater() && !onGround) {
return 0.03f; return 0.03f;
} }
return 0; return 0;
} }
/** /**
* @param session the session of the Bedrock client.
* @return true if this entity is currently in air. * @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()); int block = session.getConnector().getWorldManager().getBlockAt(session, position.toInt());
return block == BlockStateValues.JAVA_AIR_ID; return block == BlockStateValues.JAVA_AIR_ID;
} }
@Override @Override
protected float getDrag(GeyserSession session) { protected float getDrag() {
return 0.92f; return 0.92f;
} }
} }

Datei anzeigen

@ -26,33 +26,29 @@
package org.geysermc.connector.entity; 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.EntityMetadata;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanEntityMetadata;
import com.nukkitx.math.vector.Vector3f; import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityData; 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.session.GeyserSession;
import org.geysermc.connector.network.translators.world.block.BlockStateValues; 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; private boolean hasFuel = false;
public FurnaceMinecartEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { public FurnaceMinecartEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
super(entityId, geyserId, entityType, position, motion, rotation); super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
}
public void setHasFuel(EntityMetadata<Boolean> entityMetadata) {
hasFuel = ((BooleanEntityMetadata) entityMetadata).getPrimitiveValue();
updateDefaultBlockMetadata();
} }
@Override @Override
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { public void updateDefaultBlockMetadata() {
if (entityMetadata.getId() == 14 && !showCustomBlock) { dirtyMetadata.put(EntityData.DISPLAY_ITEM, session.getBlockMappings().getBedrockBlockId(hasFuel ? BlockStateValues.JAVA_FURNACE_LIT_ID : BlockStateValues.JAVA_FURNACE_ID));
hasFuel = (boolean) entityMetadata.getValue(); dirtyMetadata.put(EntityData.DISPLAY_OFFSET, 6);
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);
} }
} }

Datei anzeigen

@ -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.data.inventory.ItemData;
import com.nukkitx.protocol.bedrock.packet.AddItemEntityPacket; import com.nukkitx.protocol.bedrock.packet.AddItemEntityPacket;
import com.nukkitx.protocol.bedrock.packet.EntityEventPacket; 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.session.GeyserSession;
import org.geysermc.connector.network.translators.item.ItemTranslator; import org.geysermc.connector.network.translators.item.ItemTranslator;
import org.geysermc.connector.network.translators.world.block.BlockStateValues; import org.geysermc.connector.network.translators.world.block.BlockStateValues;
import java.util.UUID;
public class ItemEntity extends ThrowableEntity { public class ItemEntity extends ThrowableEntity {
protected ItemData item; protected ItemData item;
private int waterLevel = -1; private int waterLevel = -1;
public ItemEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { public ItemEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
super(entityId, geyserId, entityType, position, motion, rotation); super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
} }
@Override @Override
public void spawnEntity(GeyserSession session) { public void spawnEntity() {
if (item == null) { if (item == null) {
return; return;
} }
@ -58,36 +59,59 @@ public class ItemEntity extends ThrowableEntity {
AddItemEntityPacket itemPacket = new AddItemEntityPacket(); AddItemEntityPacket itemPacket = new AddItemEntityPacket();
itemPacket.setRuntimeEntityId(geyserId); itemPacket.setRuntimeEntityId(geyserId);
itemPacket.setUniqueEntityId(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.setMotion(motion);
itemPacket.setFromFishing(false); itemPacket.setFromFishing(false);
itemPacket.setItemInHand(item); itemPacket.setItemInHand(item);
itemPacket.getMetadata().putAll(metadata); itemPacket.getMetadata().putAll(dirtyMetadata);
session.sendUpstreamPacket(itemPacket); session.sendUpstreamPacket(itemPacket);
} }
@Override @Override
public void tick(GeyserSession session) { public void tick() {
if (isInWater(session)) { if (isInWater()) {
return; return;
} }
if (!onGround || (motion.getX() * motion.getX() + motion.getZ() * motion.getZ()) > 0.00001) { if (!onGround || (motion.getX() * motion.getX() + motion.getZ() * motion.getZ()) > 0.00001) {
float gravity = getGravity(session); float gravity = getGravity();
motion = motion.down(gravity); 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, 0.98f, drag); motion = motion.mul(drag, 0.98f, drag);
} }
} }
public void setItem(EntityMetadata<ItemStack> entityMetadata) {
ItemData item = ItemTranslator.translateToBedrock(session, entityMetadata.getValue());
if (this.item == null) {
this.item = item;
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()) {
// Just item count updated; let's make this easy
this.item = item;
EntityEventPacket packet = new EntityEventPacket();
packet.setRuntimeEntityId(geyserId);
packet.setType(EntityEventType.UPDATE_ITEM_STACK_SIZE);
packet.setData(this.item.getCount());
session.sendUpstreamPacket(packet);
}
} else {
this.item = item;
despawnEntity();
spawnEntity();
}
}
@Override @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) {
float offset = entityType.getOffset(); float offset = definition.offset();
if (waterLevel == 0) { // Item is in a full block of water if (waterLevel == 0) { // Item is in a full block of water
// Move the item entity down so it doesn't float above the water // Move the item entity down so it doesn't float above the water
offset = -entityType.getOffset(); offset = -definition.offset();
} }
super.moveAbsoluteImmediate(session, position.add(0, offset, 0), Vector3f.ZERO, isOnGround, teleported); super.moveAbsoluteImmediate(position.add(0, offset, 0), 0, 0, 0, isOnGround, teleported);
this.position = position; this.position = position;
int block = session.getConnector().getWorldManager().getBlockAt(session, position.toInt()); int block = session.getConnector().getWorldManager().getBlockAt(session, position.toInt());
@ -95,8 +119,8 @@ public class ItemEntity extends ThrowableEntity {
} }
@Override @Override
protected float getGravity(GeyserSession session) { protected float getGravity() {
if (metadata.getFlags().getFlag(EntityFlag.HAS_GRAVITY) && !onGround && !isInWater(session)) { if (getFlag(EntityFlag.HAS_GRAVITY) && !onGround && !isInWater()) {
// Gravity can change if the item is in water/lava, but // Gravity can change if the item is in water/lava, but
// the server calculates the motion & position for us // the server calculates the motion & position for us
return 0.04f; return 0.04f;
@ -105,7 +129,7 @@ public class ItemEntity extends ThrowableEntity {
} }
@Override @Override
protected float getDrag(GeyserSession session) { protected float getDrag() {
if (onGround) { if (onGround) {
Vector3i groundBlockPos = position.toInt().down(1); Vector3i groundBlockPos = position.toInt().down(1);
int blockState = session.getConnector().getWorldManager().getBlockAt(session, groundBlockPos); int blockState = session.getConnector().getWorldManager().getBlockAt(session, groundBlockPos);
@ -115,35 +139,7 @@ public class ItemEntity extends ThrowableEntity {
} }
@Override @Override
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { protected boolean isInWater() {
if (entityMetadata.getId() == 8) {
ItemData item = ItemTranslator.translateToBedrock(session, (ItemStack) entityMetadata.getValue());
if (this.item == null) {
this.item = item;
spawnEntity(session);
} 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()) {
// Just item count updated; let's make this easy
this.item = item;
EntityEventPacket packet = new EntityEventPacket();
packet.setRuntimeEntityId(geyserId);
packet.setType(EntityEventType.UPDATE_ITEM_STACK_SIZE);
packet.setData(this.item.getCount());
session.sendUpstreamPacket(packet);
}
} else {
this.item = item;
despawnEntity(session);
spawnEntity(session);
}
}
super.updateBedrockMetadata(entityMetadata, session);
}
@Override
protected boolean isInWater(GeyserSession session) {
return waterLevel != -1; return waterLevel != -1;
} }
} }

Datei anzeigen

@ -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.EntityMetadata;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; 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.Vector3f;
import com.nukkitx.math.vector.Vector3i; import com.nukkitx.math.vector.Vector3i;
import com.nukkitx.nbt.NbtMap; 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.packet.UpdateBlockPacket;
import com.nukkitx.protocol.bedrock.v465.Bedrock_v465; import com.nukkitx.protocol.bedrock.v465.Bedrock_v465;
import lombok.Getter; import lombok.Getter;
import org.geysermc.connector.entity.type.EntityType;
import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.connector.network.translators.item.ItemTranslator; import org.geysermc.connector.network.translators.item.ItemTranslator;
import org.geysermc.connector.registry.type.ItemMapping; import org.geysermc.connector.registry.type.ItemMapping;
import java.util.UUID;
/** /**
* Item frames are an entity in Java but a block entity in Bedrock. * Item frames are an entity in Java but a block entity in Bedrock.
*/ */
public class ItemFrameEntity extends Entity { 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. * Used for getting the Bedrock block position.
* Blocks deal with integers whereas entities deal with floats. * Blocks deal with integers whereas entities deal with floats.
*/ */
private Vector3i bedrockPosition; private final Vector3i bedrockPosition;
/** /**
* Specific block 'state' we are emulating in Bedrock. * Specific block 'state' we are emulating in Bedrock.
*/ */
private int bedrockRuntimeId; private final int bedrockRuntimeId;
/** /**
* Rotation of item in frame. * Rotation of item in frame.
*/ */
@ -73,16 +71,16 @@ public class ItemFrameEntity extends Entity {
*/ */
@Getter @Getter
private ItemStack heldItem = null; 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) { public ItemFrameEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, Direction direction) {
super(entityId, geyserId, entityType, position, motion, rotation); super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, 0f);
this.direction = direction;
}
@Override
public void spawnEntity(GeyserSession session) {
NbtMapBuilder blockBuilder = NbtMap.builder() 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()); .putInt("version", session.getBlockMappings().getBlockStateVersion());
NbtMapBuilder statesBuilder = NbtMap.builder() NbtMapBuilder statesBuilder = NbtMap.builder()
.putInt("facing_direction", direction.ordinal()) .putInt("facing_direction", direction.ordinal())
@ -96,18 +94,26 @@ public class ItemFrameEntity extends Entity {
bedrockPosition = Vector3i.from(position.getFloorX(), position.getFloorY(), position.getFloorZ()); bedrockPosition = Vector3i.from(position.getFloorX(), position.getFloorY(), position.getFloorZ());
session.getItemFrameCache().put(bedrockPosition, this); 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); session.getConnector().getLogger().debug("Spawned item frame at location " + bedrockPosition + " with java id " + entityId);
valid = true; valid = true;
} }
@Override public void setItemInFrame(EntityMetadata<ItemStack> entityMetadata) {
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { if (entityMetadata.getValue() != null) {
if (entityMetadata.getId() == 8 && entityMetadata.getValue() != null) { this.heldItem = entityMetadata.getValue();
this.heldItem = (ItemStack) entityMetadata.getValue();
ItemData itemData = ItemTranslator.translateToBedrock(session, heldItem); 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(); NbtMapBuilder builder = NbtMap.builder();
builder.putByte("Count", (byte) itemData.getCount()); builder.putByte("Count", (byte) itemData.getCount());
@ -121,34 +127,30 @@ public class ItemFrameEntity extends Entity {
tag.putFloat("ItemDropChance", 1.0f); tag.putFloat("ItemDropChance", 1.0f);
tag.putFloat("ItemRotation", rotation); tag.putFloat("ItemRotation", rotation);
cachedTag = tag.build(); cachedTag = tag.build();
updateBlock(session); changed = true;
} } else if (cachedTag != null) {
else if (entityMetadata.getId() == 8 && entityMetadata.getValue() == null && cachedTag != null) {
cachedTag = getDefaultTag(); cachedTag = getDefaultTag();
updateBlock(session); changed = true;
}
else if (entityMetadata.getId() == 9) {
rotation = ((int) entityMetadata.getValue()) * 45;
if (cachedTag == null) {
updateBlock(session);
return;
}
NbtMapBuilder builder = cachedTag.toBuilder();
builder.putFloat("ItemRotation", rotation);
cachedTag = builder.build();
updateBlock(session);
}
else {
updateBlock(session);
} }
} }
public void setItemRotation(EntityMetadata<Integer> entityMetadata) {
rotation = ((IntEntityMetadata) entityMetadata).getPrimitiveValue() * 45;
if (cachedTag == null) {
return;
}
NbtMapBuilder builder = cachedTag.toBuilder();
builder.putFloat("ItemRotation", rotation);
cachedTag = builder.build();
changed = true;
}
@Override @Override
public boolean despawnEntity(GeyserSession session) { public boolean despawnEntity() {
UpdateBlockPacket updateBlockPacket = new UpdateBlockPacket(); UpdateBlockPacket updateBlockPacket = new UpdateBlockPacket();
updateBlockPacket.setDataLayer(0); updateBlockPacket.setDataLayer(0);
updateBlockPacket.setBlockPosition(bedrockPosition); 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.PRIORITY);
updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NETWORK); updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NETWORK);
updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NEIGHBORS); updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NEIGHBORS);
@ -166,15 +168,23 @@ public class ItemFrameEntity extends Entity {
builder.putInt("y", bedrockPosition.getY()); builder.putInt("y", bedrockPosition.getY());
builder.putInt("z", bedrockPosition.getZ()); builder.putInt("z", bedrockPosition.getZ());
builder.putByte("isMovable", (byte) 1); 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(); return builder.build();
} }
@Override
public void updateBedrockMetadata() {
updateBlock();
}
/** /**
* Updates the item frame as a block * 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 updateBlockPacket = new UpdateBlockPacket();
updateBlockPacket.setDataLayer(0); updateBlockPacket.setDataLayer(0);
updateBlockPacket.setBlockPosition(bedrockPosition); updateBlockPacket.setBlockPosition(bedrockPosition);
@ -193,6 +203,8 @@ public class ItemFrameEntity extends Entity {
} }
session.sendUpstreamPacket(blockEntityDataPacket); session.sendUpstreamPacket(blockEntityDataPacket);
changed = false;
} }
/** /**

Datei anzeigen

@ -26,9 +26,10 @@
package org.geysermc.connector.entity; package org.geysermc.connector.entity;
import com.nukkitx.math.vector.Vector3f; import com.nukkitx.math.vector.Vector3f;
import org.geysermc.connector.entity.type.EntityType;
import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.session.GeyserSession;
import java.util.UUID;
public class ItemedFireballEntity extends ThrowableEntity { public class ItemedFireballEntity extends ThrowableEntity {
private final Vector3f acceleration; private final Vector3f acceleration;
@ -37,8 +38,8 @@ public class ItemedFireballEntity extends ThrowableEntity {
*/ */
protected int futureTicks = 3; protected int futureTicks = 3;
public ItemedFireballEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { public ItemedFireballEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
super(entityId, geyserId, entityType, position, Vector3f.ZERO, rotation); super(session, entityId, geyserId, uuid, definition, position, Vector3f.ZERO, yaw, pitch, headYaw);
float magnitude = motion.length(); float magnitude = motion.length();
if (magnitude != 0) { 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); position = position.add(motion);
float drag = getDrag(session); float drag = getDrag();
motion = motion.add(acceleration).mul(drag); motion = motion.add(acceleration).mul(drag);
return position; return position;
} }
@Override @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 // Advance the position by a few ticks before sending it to Bedrock
Vector3f lastMotion = motion; Vector3f lastMotion = motion;
Vector3f newPosition = position; Vector3f newPosition = position;
for (int i = 0; i < futureTicks; i++) { 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.position = position;
this.motion = lastMotion; this.motion = lastMotion;
} }
@Override @Override
public void tick(GeyserSession session) { public void tick() {
moveAbsoluteImmediate(session, tickMovement(session, position), rotation, false, false); moveAbsoluteImmediate(tickMovement(position), yaw, pitch, headYaw, false, false);
} }
} }

Datei anzeigen

@ -26,13 +26,15 @@
package org.geysermc.connector.entity; package org.geysermc.connector.entity;
import com.nukkitx.math.vector.Vector3f; 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 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 // 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);
} }
} }

Datei anzeigen

@ -27,20 +27,20 @@ package org.geysermc.connector.entity;
import com.nukkitx.math.vector.Vector3f; import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.packet.PlaySoundPacket; import com.nukkitx.protocol.bedrock.packet.PlaySoundPacket;
import org.geysermc.connector.entity.type.EntityType;
import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.session.GeyserSession;
import java.util.UUID;
import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.ThreadLocalRandom;
public class LightningEntity extends Entity { public class LightningEntity extends Entity {
public LightningEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { public LightningEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
super(entityId, geyserId, entityType, position, motion, rotation); super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
} }
@Override @Override
public void spawnEntity(GeyserSession session) { public void spawnEntity() {
super.spawnEntity(session); super.spawnEntity();
// Add these two sound effects - they're done completely clientside on Java Edition as of 1.17.1 // Add these two sound effects - they're done completely clientside on Java Edition as of 1.17.1
ThreadLocalRandom random = ThreadLocalRandom.current(); ThreadLocalRandom random = ThreadLocalRandom.current();

Datei anzeigen

@ -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.EntityMetadata;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.Pose; 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.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.Vector3f;
import com.nukkitx.math.vector.Vector3i; import com.nukkitx.math.vector.Vector3i;
import com.nukkitx.protocol.bedrock.data.AttributeData; import com.nukkitx.protocol.bedrock.data.AttributeData;
@ -43,7 +45,6 @@ import lombok.AccessLevel;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import org.geysermc.connector.entity.attribute.GeyserAttributeType; 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.network.session.GeyserSession;
import org.geysermc.connector.registry.type.ItemMapping; import org.geysermc.connector.registry.type.ItemMapping;
import org.geysermc.connector.utils.AttributeUtils; import org.geysermc.connector.utils.AttributeUtils;
@ -52,6 +53,7 @@ import org.geysermc.connector.utils.ChunkUtils;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.UUID;
@Getter @Getter
@Setter @Setter
@ -74,82 +76,87 @@ public class LivingEntity extends Entity {
*/ */
private boolean isMaxFrozenState = false; private boolean isMaxFrozenState = false;
public LivingEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { public LivingEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
super(entityId, geyserId, entityType, position, motion, rotation); super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
}
@Override
protected void initializeMetadata() {
super.initializeMetadata();
// Matches Bedrock behavior; is always set to this // Matches Bedrock behavior; is always set to this
metadata.put(EntityData.HEALTH, 1); dirtyMetadata.put(EntityData.HEALTH, 1);
} }
@Override public void setLivingEntityFlags(EntityMetadata<Byte> entityMetadata) {
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { byte xd = ((ByteEntityMetadata) entityMetadata).getPrimitiveValue();
switch (entityMetadata.getId()) {
case 8 -> { // blocking
byte xd = (byte) entityMetadata.getValue();
//blocking gets triggered when using a bow, but if we set USING_ITEM for all items, it may look like // 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. // you're "mining" with ex. a shield.
ItemMapping shield = session.getItemMappings().getStoredItems().shield(); ItemMapping shield = session.getItemMappings().getStoredItems().shield();
boolean isUsingShield = (getHand().getId() == shield.getBedrockId() || boolean isUsingShield = (getHand().getId() == shield.getBedrockId() ||
getHand().equals(ItemData.AIR) && getOffHand().getId() == shield.getBedrockId()); getHand().equals(ItemData.AIR) && getOffHand().getId() == shield.getBedrockId());
metadata.getFlags().setFlag(EntityFlag.USING_ITEM, (xd & 0x01) == 0x01 && !isUsingShield); setFlag(EntityFlag.USING_ITEM, (xd & 0x01) == 0x01 && !isUsingShield);
metadata.getFlags().setFlag(EntityFlag.BLOCKING, (xd & 0x01) == 0x01); setFlag(EntityFlag.BLOCKING, (xd & 0x01) == 0x01);
// Riptide spin attack // 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();
AttributeData healthData = createHealthAttribute(); public void setHealth(EntityMetadata<Float> entityMetadata) {
UpdateAttributesPacket attributesPacket = new UpdateAttributesPacket(); this.health = ((FloatEntityMetadata) entityMetadata).getPrimitiveValue();
attributesPacket.setRuntimeEntityId(geyserId);
attributesPacket.setAttributes(Collections.singletonList(healthData)); AttributeData healthData = createHealthAttribute();
session.sendUpstreamPacket(attributesPacket); UpdateAttributesPacket attributesPacket = new UpdateAttributesPacket();
} attributesPacket.setRuntimeEntityId(geyserId);
case 10 -> metadata.put(EntityData.EFFECT_COLOR, entityMetadata.getValue()); attributesPacket.setAttributes(Collections.singletonList(healthData));
case 11 -> metadata.put(EntityData.EFFECT_AMBIENT, (byte) ((boolean) entityMetadata.getValue() ? 1 : 0)); session.sendUpstreamPacket(attributesPacket);
case 14 -> { // Bed Position }
Position bedPosition = (Position) entityMetadata.getValue();
if (bedPosition != null) { public Vector3i setBedPosition(EntityMetadata<Position> entityMetadata) {
metadata.put(EntityData.BED_POSITION, Vector3i.from(bedPosition.getX(), bedPosition.getY(), bedPosition.getZ())); Position bedPosition = entityMetadata.getValue();
int bed = session.getConnector().getWorldManager().getBlockAt(session, bedPosition); if (bedPosition != null) {
// Bed has to be updated, or else player is floating in the air Vector3i vector = Vector3i.from(bedPosition.getX(), bedPosition.getY(), bedPosition.getZ());
ChunkUtils.updateBlock(session, bed, bedPosition); dirtyMetadata.put(EntityData.BED_POSITION, vector);
// Indicate that the player should enter the sleep cycle int bed = session.getConnector().getWorldManager().getBlockAt(session, bedPosition);
// Has to be a byte or it does not work // Bed has to be updated, or else player is floating in the air
// (Bed position is what actually triggers sleep - "pose" is only optional) ChunkUtils.updateBlock(session, bed, bedPosition);
metadata.put(EntityData.PLAYER_FLAGS, (byte) 2); // Indicate that the player should enter the sleep cycle
} else { // Has to be a byte or it does not work
// Player is no longer sleeping // (Bed position is what actually triggers sleep - "pose" is only optional)
metadata.put(EntityData.PLAYER_FLAGS, (byte) 0); dirtyMetadata.put(EntityData.PLAYER_FLAGS, (byte) 2);
} return vector;
} } else {
// Player is no longer sleeping
dirtyMetadata.put(EntityData.PLAYER_FLAGS, (byte) 0);
return null;
} }
super.updateBedrockMetadata(entityMetadata, session);
} }
@Override @Override
protected boolean isShaking(GeyserSession session) { protected boolean isShaking() {
return isMaxFrozenState; return isMaxFrozenState;
} }
@Override @Override
protected void setDimensions(Pose pose) { protected void setDimensions(Pose pose) {
if (pose == Pose.SLEEPING) { if (pose == Pose.SLEEPING) {
metadata.put(EntityData.BOUNDING_BOX_WIDTH, 0.2f); boundingBoxWidth = 0.2f;
metadata.put(EntityData.BOUNDING_BOX_HEIGHT, 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 { } else {
super.setDimensions(pose); super.setDimensions(pose);
} }
} }
@Override @Override
protected void setFreezing(GeyserSession session, float amount) { public float setFreezing(EntityMetadata<Integer> entityMetadata) {
super.setFreezing(session, amount); float freezingPercentage = super.setFreezing(entityMetadata);
this.isMaxFrozenState = amount >= 1.0f; this.isMaxFrozenState = freezingPercentage >= 1.0f;
metadata.getFlags().setFlag(EntityFlag.SHAKING, isShaking(session)); setFlag(EntityFlag.SHAKING, isShaking());
return freezingPercentage;
} }
/** /**

Datei anzeigen

@ -26,63 +26,42 @@
package org.geysermc.connector.entity; 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.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.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityData; 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.session.GeyserSession;
import java.util.UUID;
public class MinecartEntity extends Entity { public class MinecartEntity extends Entity {
public MinecartEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { public MinecartEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
super(entityId, geyserId, entityType, position.add(0d, entityType.getOffset(), 0d), motion, rotation); super(session, entityId, geyserId, uuid, definition, position.add(0d, definition.offset(), 0d), motion, yaw, pitch, headYaw);
}
public void setCustomBlock(EntityMetadata<Integer> entityMetadata) {
dirtyMetadata.put(EntityData.DISPLAY_ITEM, session.getBlockMappings().getBedrockBlockId(((IntEntityMetadata) entityMetadata).getPrimitiveValue()));
}
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
// Needs a byte based off of Java's boolean
dirtyMetadata.put(EntityData.CUSTOM_DISPLAY, (byte) (((BooleanEntityMetadata) entityMetadata).getPrimitiveValue() ? 1 : 0));
} }
@Override @Override
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { 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);
if (entityMetadata.getId() == 8) {
metadata.put(EntityData.HEALTH, entityMetadata.getValue());
}
// 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());
}
// 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);
}
@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);
} }
@Override @Override
public Vector3f getBedrockRotation() { public Vector3f getBedrockRotation() {
// Note: minecart rotation on rails does not care about the actual rotation value // 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);
} }
} }

Datei anzeigen

@ -27,23 +27,24 @@ package org.geysermc.connector.entity;
import com.nukkitx.math.vector.Vector3f; import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.packet.AddPaintingPacket; 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.network.session.GeyserSession;
import org.geysermc.connector.utils.PaintingType; import org.geysermc.connector.utils.PaintingType;
import java.util.UUID;
public class PaintingEntity extends Entity { public class PaintingEntity extends Entity {
private static final double OFFSET = -0.46875; private static final double OFFSET = -0.46875;
private final PaintingType paintingName; private final PaintingType paintingName;
private final int direction; private final int direction;
public PaintingEntity(long entityId, long geyserId, Vector3f position, PaintingType paintingName, int direction) { public PaintingEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, Vector3f position, PaintingType paintingName, int direction) {
super(entityId, geyserId, EntityType.PAINTING, position, Vector3f.ZERO, Vector3f.ZERO); super(session, entityId, geyserId, uuid, EntityDefinitions.PAINTING, position, Vector3f.ZERO, 0f, 0f, 0f);
this.paintingName = paintingName; this.paintingName = paintingName;
this.direction = direction; this.direction = direction;
} }
@Override @Override
public void spawnEntity(GeyserSession session) { public void spawnEntity() {
AddPaintingPacket addPaintingPacket = new AddPaintingPacket(); AddPaintingPacket addPaintingPacket = new AddPaintingPacket();
addPaintingPacket.setUniqueEntityId(geyserId); addPaintingPacket.setUniqueEntityId(geyserId);
addPaintingPacket.setRuntimeEntityId(geyserId); addPaintingPacket.setRuntimeEntityId(geyserId);
@ -58,7 +59,7 @@ public class PaintingEntity extends Entity {
} }
@Override @Override
public void updateHeadLookRotation(GeyserSession session, float headYaw) { public void updateHeadLookRotation(float headYaw) {
// Do nothing, as head look messes up paintings // Do nothing, as head look messes up paintings
} }

Datei anzeigen

@ -27,19 +27,20 @@ package org.geysermc.connector.entity;
import com.nukkitx.math.vector.Vector3f; import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityData; 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.session.GeyserSession;
import org.geysermc.connector.network.translators.world.block.BlockStateValues; import org.geysermc.connector.network.translators.world.block.BlockStateValues;
import java.util.UUID;
public class SpawnerMinecartEntity extends DefaultBlockMinecartEntity { public class SpawnerMinecartEntity extends DefaultBlockMinecartEntity {
public SpawnerMinecartEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { public SpawnerMinecartEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
super(entityId, geyserId, entityType, position, motion, rotation); super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
} }
@Override @Override
public void updateDefaultBlockMetadata(GeyserSession session) { public void updateDefaultBlockMetadata() {
metadata.put(EntityData.DISPLAY_ITEM, session.getBlockMappings().getBedrockBlockId(BlockStateValues.JAVA_SPAWNER_ID)); dirtyMetadata.put(EntityData.DISPLAY_ITEM, session.getBlockMappings().getBedrockBlockId(BlockStateValues.JAVA_SPAWNER_ID));
metadata.put(EntityData.DISPLAY_OFFSET, 6); dirtyMetadata.put(EntityData.DISPLAY_OFFSET, 6);
} }
} }

Datei anzeigen

@ -26,41 +26,37 @@
package org.geysermc.connector.entity; 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.EntityMetadata;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata;
import com.nukkitx.math.vector.Vector3f; import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityData; import com.nukkitx.protocol.bedrock.data.entity.EntityData;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag; import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
import com.nukkitx.protocol.bedrock.packet.SetEntityDataPacket; import com.nukkitx.protocol.bedrock.packet.SetEntityDataPacket;
import org.geysermc.connector.entity.type.EntityType;
import org.geysermc.connector.network.session.GeyserSession; 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; private int currentTick;
public TNTEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { public TNTEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
super(entityId, geyserId, entityType, position, motion, rotation); 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 @Override
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { public void tick() {
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) {
if (currentTick == 0) { if (currentTick == 0) {
// No need to update the fuse when there is none // No need to update the fuse when there is none
return; return;
} }
if (currentTick % 5 == 0) { if (currentTick % 5 == 0) {
metadata.put(EntityData.FUSE_LENGTH, currentTick); dirtyMetadata.put(EntityData.FUSE_LENGTH, currentTick);
SetEntityDataPacket packet = new SetEntityDataPacket(); SetEntityDataPacket packet = new SetEntityDataPacket();
packet.setRuntimeEntityId(geyserId); packet.setRuntimeEntityId(geyserId);

Datei anzeigen

@ -25,15 +25,17 @@
package org.geysermc.connector.entity; 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.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.LevelEventType; import com.nukkitx.protocol.bedrock.data.LevelEventType;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag; import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
import com.nukkitx.protocol.bedrock.packet.LevelEventPacket; import com.nukkitx.protocol.bedrock.packet.LevelEventPacket;
import com.nukkitx.protocol.bedrock.packet.MoveEntityDeltaPacket; 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.session.GeyserSession;
import org.geysermc.connector.network.translators.world.block.BlockStateValues; 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 * 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; protected Vector3f lastJavaPosition;
public ThrowableEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { public ThrowableEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
super(entityId, geyserId, entityType, position, motion, rotation); super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
this.lastJavaPosition = position; 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 * Java clients assume the next positions of moving items. Bedrock needs to be explicitly told positions
*/ */
@Override @Override
public void tick(GeyserSession session) { public void tick() {
moveAbsoluteImmediate(session, position.add(motion), rotation, onGround, false); moveAbsoluteImmediate(position.add(motion), yaw, pitch, headYaw, onGround, false);
float drag = getDrag(session); float drag = getDrag();
float gravity = getGravity(session); float gravity = getGravity();
motion = motion.mul(drag).down(gravity); 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 moveEntityDeltaPacket = new MoveEntityDeltaPacket();
moveEntityDeltaPacket.setRuntimeEntityId(geyserId); moveEntityDeltaPacket.setRuntimeEntityId(geyserId);
@ -86,19 +88,21 @@ public class ThrowableEntity extends Entity implements Tickable {
} }
setPosition(position); setPosition(position);
if (this.rotation.getX() != rotation.getX()) { if (this.yaw != yaw) {
moveEntityDeltaPacket.getFlags().add(MoveEntityDeltaPacket.Flag.HAS_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.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.getFlags().add(MoveEntityDeltaPacket.Flag.HAS_HEAD_YAW);
moveEntityDeltaPacket.setHeadYaw(rotation.getZ()); moveEntityDeltaPacket.setHeadYaw(headYaw);
this.headYaw = headYaw;
} }
setRotation(rotation);
if (!moveEntityDeltaPacket.getFlags().isEmpty()) { if (!moveEntityDeltaPacket.getFlags().isEmpty()) {
session.sendUpstreamPacket(moveEntityDeltaPacket); 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. * 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. * @return the amount of gravity to apply to this entity while in motion.
*/ */
protected float getGravity(GeyserSession session) { protected float getGravity() {
if (metadata.getFlags().getFlag(EntityFlag.HAS_GRAVITY)) { if (getFlag(EntityFlag.HAS_GRAVITY)) {
switch (entityType) { switch (definition.entityType()) {
case THROWN_POTION: case THROWN_POTION:
case LINGERING_POTION:
return 0.05f; return 0.05f;
case THROWN_EXP_BOTTLE: case THROWN_EXP_BOTTLE:
return 0.07f; 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 * @return the drag that should be multiplied to the entity's motion
*/ */
protected float getDrag(GeyserSession session) { protected float getDrag() {
if (isInWater(session)) { if (isInWater()) {
return 0.8f; return 0.8f;
} else { } else {
switch (entityType) { switch (definition.entityType()) {
case THROWN_POTION: case THROWN_POTION:
case LINGERING_POTION:
case THROWN_EXP_BOTTLE: case THROWN_EXP_BOTTLE:
case SNOWBALL: case SNOWBALL:
case THROWN_EGG: 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. * @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()); int block = session.getConnector().getWorldManager().getBlockAt(session, position.toInt());
return BlockStateValues.getWaterLevel(block) != -1; return BlockStateValues.getWaterLevel(block) != -1;
} }
@Override @Override
public boolean despawnEntity(GeyserSession session) { public boolean despawnEntity() {
if (entityType == EntityType.THROWN_ENDERPEARL) { if (definition.entityType() == EntityType.THROWN_ENDERPEARL) {
LevelEventPacket particlePacket = new LevelEventPacket(); LevelEventPacket particlePacket = new LevelEventPacket();
particlePacket.setType(LevelEventType.PARTICLE_TELEPORT); particlePacket.setType(LevelEventType.PARTICLE_TELEPORT);
particlePacket.setPosition(position); particlePacket.setPosition(position);
session.sendUpstreamPacket(particlePacket); session.sendUpstreamPacket(particlePacket);
} }
return super.despawnEntity(session); return super.despawnEntity();
} }
@Override @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) {
moveAbsoluteImmediate(session, lastJavaPosition.add(relX, relY, relZ), rotation, isOnGround, false); moveAbsoluteImmediate(lastJavaPosition.add(relX, relY, relZ), yaw, pitch, headYaw, isOnGround, false);
lastJavaPosition = position; lastJavaPosition = position;
} }
@Override @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) {
moveAbsoluteImmediate(session, position, rotation, isOnGround, teleported); moveAbsoluteImmediate(position, yaw, pitch, headYaw, isOnGround, teleported);
lastJavaPosition = position; lastJavaPosition = position;
} }
} }

Datei anzeigen

@ -27,9 +27,10 @@ package org.geysermc.connector.entity;
import com.nukkitx.math.vector.Vector3f; import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag; 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.network.session.GeyserSession;
import java.util.UUID;
/** /**
* Used as a class for any projectile entity that looks like an item * 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 int age;
private boolean invisible; private boolean invisible;
public ThrowableItemEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { public ThrowableItemEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
super(entityId, geyserId, entityType, position, motion, rotation); super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
metadata.getFlags().setFlag(EntityFlag.INVISIBLE, true); setFlag(EntityFlag.INVISIBLE, true);
invisible = false; invisible = false;
} }
private void checkVisibility(GeyserSession session) { private void checkVisibility() {
if (invisible != metadata.getFlags().getFlag(EntityFlag.INVISIBLE)) { if (invisible != getFlag(EntityFlag.INVISIBLE)) {
if (!invisible) { if (!invisible) {
Vector3f playerPos = session.getPlayerEntity().getPosition(); Vector3f playerPos = session.getPlayerEntity().getPosition();
// Prevent projectiles from blocking the player's screen // Prevent projectiles from blocking the player's screen
if (age >= 4 || position.distanceSquared(playerPos) > 16) { if (age >= 4 || position.distanceSquared(playerPos) > 16) {
metadata.getFlags().setFlag(EntityFlag.INVISIBLE, false); setFlag(EntityFlag.INVISIBLE, false);
updateBedrockMetadata(session); updateBedrockMetadata();
} }
} else { } else {
metadata.getFlags().setFlag(EntityFlag.INVISIBLE, true); setFlag(EntityFlag.INVISIBLE, true);
updateBedrockMetadata(session); updateBedrockMetadata();
} }
} }
age++; age++;
} }
@Override @Override
public void tick(GeyserSession session) { public void tick() {
checkVisibility(session); checkVisibility();
super.tick(session); super.tick();
} }
@Override @Override
protected void setInvisible(GeyserSession session, boolean value) { protected void setInvisible(boolean value) {
invisible = value; invisible = value;
} }
} }

Datei anzeigen

@ -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.EntityMetadata;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; 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.StringTag;
import com.github.steveice10.opennbt.tag.builtin.Tag; import com.github.steveice10.opennbt.tag.builtin.Tag;
import com.nukkitx.math.vector.Vector3f; import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityData; import com.nukkitx.protocol.bedrock.data.entity.EntityData;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag; import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.GeyserConnector;
import org.geysermc.connector.entity.type.EntityType;
import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.connector.network.translators.item.Potion; import org.geysermc.connector.network.translators.item.Potion;
import org.geysermc.connector.registry.type.ItemMapping; import org.geysermc.connector.registry.type.ItemMapping;
import java.util.EnumSet; import java.util.EnumSet;
import java.util.UUID;
public class ThrownPotionEntity extends ThrowableItemEntity { public class ThrownPotionEntity extends ThrowableItemEntity {
private static final EnumSet<Potion> NON_ENCHANTED_POTIONS = EnumSet.of(Potion.WATER, Potion.MUNDANE, Potion.THICK, Potion.AWKWARD); 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) { public ThrownPotionEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
super(entityId, geyserId, entityType, position, motion, rotation); super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
} }
@Override public void setPotion(EntityMetadata<ItemStack> entityMetadata) {
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { ItemStack itemStack = entityMetadata.getValue();
if (entityMetadata.getId() == 8 && entityMetadata.getType() == MetadataType.ITEM) { ItemMapping mapping = session.getItemMappings().getMapping(itemStack);
ItemStack itemStack = (ItemStack) entityMetadata.getValue(); if (mapping.getJavaIdentifier().endsWith("potion") && itemStack.getNbt() != null) {
ItemMapping mapping = session.getItemMappings().getMapping(itemStack); Tag potionTag = itemStack.getNbt().get("Potion");
if (mapping.getJavaIdentifier().endsWith("potion") && itemStack.getNbt() != null) { if (potionTag instanceof StringTag) {
Tag potionTag = itemStack.getNbt().get("Potion"); Potion potion = Potion.getByJavaIdentifier(((StringTag) potionTag).getValue());
if (potionTag instanceof StringTag) { if (potion != null) {
Potion potion = Potion.getByJavaIdentifier(((StringTag) potionTag).getValue()); dirtyMetadata.put(EntityData.POTION_AUX_VALUE, potion.getBedrockId());
if (potion != null) { setFlag(EntityFlag.ENCHANTED, !NON_ENCHANTED_POTIONS.contains(potion));
metadata.put(EntityData.POTION_AUX_VALUE, potion.getBedrockId()); } else {
metadata.getFlags().setFlag(EntityFlag.ENCHANTED, !NON_ENCHANTED_POTIONS.contains(potion)); dirtyMetadata.put(EntityData.POTION_AUX_VALUE, 0);
} else { GeyserConnector.getInstance().getLogger().debug("Unknown java potion: " + potionTag.getValue());
metadata.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);
} }
}
super.updateBedrockMetadata(entityMetadata, session); boolean isLingering = mapping.getJavaIdentifier().equals("minecraft:lingering_potion");
setFlag(EntityFlag.LINGERING, isLingering);
}
} }
} }

Datei anzeigen

@ -25,11 +25,9 @@
package org.geysermc.connector.entity; 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. * Implemented onto anything that should have code ran every Minecraft tick - 50 milliseconds.
*/ */
public interface Tickable { public interface Tickable {
void tick(GeyserSession session); void tick();
} }

Datei anzeigen

@ -26,38 +26,35 @@
package org.geysermc.connector.entity; 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.EntityMetadata;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata;
import com.nukkitx.math.vector.Vector3f; import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityData; 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.session.GeyserSession;
import org.geysermc.connector.network.translators.item.TippedArrowPotion; 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 * Internally this is known as TippedArrowEntity but is used with tipped arrows and normal arrows
*/ */
public class TippedArrowEntity extends AbstractArrowEntity { public class TippedArrowEntity extends AbstractArrowEntity {
public TippedArrowEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { public TippedArrowEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
super(entityId, geyserId, entityType, position, motion, rotation); super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
} }
@Override public void setPotionEffectColor(EntityMetadata<Integer> entityMetadata) {
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { int potionColor = ((IntEntityMetadata) entityMetadata).getPrimitiveValue();
// Arrow potion effect color // -1 means no color
if (entityMetadata.getId() == 10) { if (potionColor == -1) {
int potionColor = (int) entityMetadata.getValue(); dirtyMetadata.put(EntityData.CUSTOM_DISPLAY, 0);
// -1 means no color } else {
if (potionColor == -1) { TippedArrowPotion potion = TippedArrowPotion.getByJavaColor(potionColor);
metadata.put(EntityData.CUSTOM_DISPLAY, 0); if (potion != null && potion.getJavaColor() != -1) {
dirtyMetadata.put(EntityData.CUSTOM_DISPLAY, (byte) potion.getBedrockId());
} else { } else {
TippedArrowPotion potion = TippedArrowPotion.getByJavaColor(potionColor); dirtyMetadata.put(EntityData.CUSTOM_DISPLAY, 0);
if (potion != null && potion.getJavaColor() != -1) {
metadata.put(EntityData.CUSTOM_DISPLAY, (byte) potion.getBedrockId());
} else {
metadata.put(EntityData.CUSTOM_DISPLAY, 0);
}
} }
} }
super.updateBedrockMetadata(entityMetadata, session);
} }
} }

Datei anzeigen

@ -25,24 +25,14 @@
package org.geysermc.connector.entity; package org.geysermc.connector.entity;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
import com.nukkitx.math.vector.Vector3f; import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
import org.geysermc.connector.entity.type.EntityType;
import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.session.GeyserSession;
import java.util.UUID;
public class TridentEntity extends AbstractArrowEntity { public class TridentEntity extends AbstractArrowEntity {
public TridentEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { public TridentEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
super(entityId, geyserId, entityType, position, motion, rotation); super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
}
@Override
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
if (entityMetadata.getId() == 11) {
metadata.getFlags().setFlag(EntityFlag.ENCHANTED, (boolean) entityMetadata.getValue());
}
super.updateBedrockMetadata(entityMetadata, session);
} }
} }

Datei anzeigen

@ -26,35 +26,34 @@
package org.geysermc.connector.entity; 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.EntityMetadata;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanEntityMetadata;
import com.nukkitx.math.vector.Vector3f; import com.nukkitx.math.vector.Vector3f;
import org.geysermc.connector.entity.type.EntityType;
import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.session.GeyserSession;
import java.util.UUID;
public class WitherSkullEntity extends ItemedFireballEntity { public class WitherSkullEntity extends ItemedFireballEntity {
private boolean isCharged; private boolean isCharged;
public WitherSkullEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { public WitherSkullEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
super(entityId, geyserId, entityType, position, motion, rotation); super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
this.futureTicks = 1; this.futureTicks = 1;
} }
@Override public void setDangerous(EntityMetadata<Boolean> entityMetadata) {
protected float getDrag(GeyserSession session) { boolean newDangerous = ((BooleanEntityMetadata) entityMetadata).getPrimitiveValue();
return isCharged ? 0.73f : super.getDrag(session); 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 @Override
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { protected float getDrag() {
if (entityMetadata.getId() == 8) { return isCharged ? 0.73f : super.getDrag();
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);
} }
} }

Datei anzeigen

@ -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);
}

Datei anzeigen

@ -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> {
}

Datei anzeigen

@ -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);
}

Datei anzeigen

@ -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);
}

Datei anzeigen

@ -27,16 +27,19 @@ package org.geysermc.connector.entity.living;
import com.nukkitx.math.vector.Vector3f; import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag; 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 class AbstractFishEntity extends WaterEntity {
public AbstractFishEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { public AbstractFishEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
super(entityId, geyserId, entityType, position, motion, rotation); super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
metadata.getFlags().setFlag(EntityFlag.CAN_SWIM, true); setFlag(EntityFlag.CAN_SWIM, true);
metadata.getFlags().setFlag(EntityFlag.BREATHING, true); setFlag(EntityFlag.BREATHING, true);
metadata.getFlags().setFlag(EntityFlag.CAN_CLIMB, false); setFlag(EntityFlag.CAN_CLIMB, false);
metadata.getFlags().setFlag(EntityFlag.HAS_GRAVITY, false); setFlag(EntityFlag.HAS_GRAVITY, false);
} }
} }

Datei anzeigen

@ -26,29 +26,46 @@
package org.geysermc.connector.entity.living; 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.EntityMetadata;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanEntityMetadata;
import com.nukkitx.math.vector.Vector3f; import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityData; import com.nukkitx.protocol.bedrock.data.entity.EntityData;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag; 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.network.session.GeyserSession;
import java.util.UUID;
public class AgeableEntity extends CreatureEntity { public class AgeableEntity extends CreatureEntity {
public AgeableEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { public AgeableEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
super(entityId, geyserId, entityType, position, motion, rotation); super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
} }
@Override public void setBaby(EntityMetadata<Boolean> entityMetadata) {
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { boolean isBaby = ((BooleanEntityMetadata) entityMetadata).getPrimitiveValue();
if (entityMetadata.getId() == 16) { dirtyMetadata.put(EntityData.SCALE, isBaby ? getBabySize() : getAdultSize());
boolean isBaby = (boolean) entityMetadata.getValue(); setFlag(EntityFlag.BABY, isBaby);
metadata.put(EntityData.SCALE, isBaby ? .55f : 1f);
metadata.getFlags().setFlag(EntityFlag.BABY, isBaby);
metadata.put(EntityData.BOUNDING_BOX_HEIGHT, entityType.getHeight() * (isBaby ? 0.55f : 1f)); // TODO save this?
metadata.put(EntityData.BOUNDING_BOX_WIDTH, entityType.getWidth() * (isBaby ? 0.55f : 1f)); 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);
} }
} }

Datei anzeigen

@ -26,11 +26,14 @@
package org.geysermc.connector.entity.living; package org.geysermc.connector.entity.living;
import com.nukkitx.math.vector.Vector3f; 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) { public class AmbientEntity extends MobEntity {
super(entityId, geyserId, entityType, position, motion, rotation);
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);
} }
} }

Datei anzeigen

@ -26,18 +26,22 @@
package org.geysermc.connector.entity.living; 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.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.Rotation;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata;
import com.nukkitx.math.vector.Vector3f; import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityData; import com.nukkitx.protocol.bedrock.data.entity.EntityData;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag; import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
import com.nukkitx.protocol.bedrock.data.inventory.ItemData; import com.nukkitx.protocol.bedrock.data.inventory.ItemData;
import com.nukkitx.protocol.bedrock.packet.MoveEntityAbsolutePacket; import com.nukkitx.protocol.bedrock.packet.MoveEntityAbsolutePacket;
import lombok.Getter; 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.LivingEntity;
import org.geysermc.connector.entity.type.EntityType;
import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.session.GeyserSession;
import java.util.UUID;
public class ArmorStandEntity extends LivingEntity { public class ArmorStandEntity extends LivingEntity {
// These are used to store the state of the armour stand for use when handling invisibility // These are used to store the state of the armour stand for use when handling invisibility
@ -72,162 +76,150 @@ public class ArmorStandEntity extends LivingEntity {
* Whether we should update the position of this armor stand after metadata updates. * Whether we should update the position of this armor stand after metadata updates.
*/ */
private boolean positionUpdateRequired = false; private boolean positionUpdateRequired = false;
private GeyserSession session;
public ArmorStandEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { public ArmorStandEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
super(entityId, geyserId, entityType, position, motion, rotation); super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
} }
@Override @Override
public void spawnEntity(GeyserSession session) { public void spawnEntity() {
this.session = session; this.pitch = yaw;
this.rotation = Vector3f.from(rotation.getX(), rotation.getX(), rotation.getX()); this.headYaw = yaw;
super.spawnEntity(session); super.spawnEntity();
} }
@Override @Override
public boolean despawnEntity(GeyserSession session) { public boolean despawnEntity() {
if (secondEntity != null) { if (secondEntity != null) {
secondEntity.despawnEntity(session); secondEntity.despawnEntity();
} }
return super.despawnEntity(session); return super.despawnEntity();
} }
@Override @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) { 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 @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) { if (secondEntity != null) {
secondEntity.moveAbsolute(session, applyOffsetToPosition(position), rotation, isOnGround, teleported); secondEntity.moveAbsolute(applyOffsetToPosition(position), yaw, pitch, headYaw, isOnGround, teleported);
} else if (positionRequiresOffset) { } 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 // 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); 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 @Override
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { public void setDisplayName(EntityMetadata<Component> entityMetadata) {
super.updateBedrockMetadata(entityMetadata, session); super.setDisplayName(entityMetadata);
if (entityMetadata.getId() == 2) { updateSecondEntityStatus(false);
}
public void setArmorStandFlags(EntityMetadata<Byte> entityMetadata) {
byte xd = ((ByteEntityMetadata) entityMetadata).getPrimitiveValue();
// isSmall
boolean newIsSmall = (xd & 0x01) == 0x01;
if (newIsSmall != isSmall) {
if (positionRequiresOffset) {
// Fix new inconsistency with offset
this.position = fixOffsetForSize(position, newIsSmall);
positionUpdateRequired = true;
}
isSmall = newIsSmall;
if (!isMarker) {
toggleSmallStatus();
}
}
// setMarker
boolean oldIsMarker = isMarker;
isMarker = (xd & 0x10) == 0x10;
if (oldIsMarker != isMarker) {
if (isMarker) {
dirtyMetadata.put(EntityData.BOUNDING_BOX_WIDTH, 0.0f);
dirtyMetadata.put(EntityData.BOUNDING_BOX_HEIGHT, 0.0f);
dirtyMetadata.put(EntityData.SCALE, 0f);
} else {
toggleSmallStatus();
}
updateSecondEntityStatus(false); updateSecondEntityStatus(false);
} else if (entityMetadata.getId() == 15 && entityMetadata.getType() == MetadataType.BYTE) {
byte xd = (byte) entityMetadata.getValue();
// isSmall
boolean newIsSmall = (xd & 0x01) == 0x01;
if (newIsSmall != isSmall) {
if (positionRequiresOffset) {
// Fix new inconsistency with offset
this.position = fixOffsetForSize(position, newIsSmall);
positionUpdateRequired = true;
}
isSmall = newIsSmall;
if (!isMarker) {
toggleSmallStatus();
}
}
// setMarker
boolean oldIsMarker = isMarker;
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);
} else {
toggleSmallStatus();
}
updateSecondEntityStatus(false);
}
// 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;
}
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();
int rotationX = getRotation(rotation.getPitch());
int rotationY = getRotation(rotation.getYaw());
int rotationZ = getRotation(rotation.getRoll());
// The top bit acts like binary and determines if each rotation goes above 100
// 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);
// 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);
} }
// 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
setFlag(EntityFlag.ANGRY, (xd & 0x04) != 0x04); // Has arms
setFlag(EntityFlag.ADMIRING, (xd & 0x08) == 0x08); // Has no baseplate
}
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());
// The top bit acts like binary and determines if each rotation goes above 100
// 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);
dirtyMetadata.put(dataLeech, value);
// Set the entity flags if a value is negative
setFlag(negativeXToggle, rotationX < 0);
setFlag(negativeYToggle, rotationY < 0);
setFlag(negativeZToggle, rotationZ < 0);
} }
@Override @Override
public void updateBedrockMetadata(GeyserSession session) { public void updateBedrockMetadata() {
if (secondEntity != null) { if (secondEntity != null) {
secondEntity.updateBedrockMetadata(session); secondEntity.updateBedrockMetadata();
} }
super.updateBedrockMetadata(session); super.updateBedrockMetadata();
if (positionUpdateRequired) { if (positionUpdateRequired) {
positionUpdateRequired = false; positionUpdateRequired = false;
updatePosition(); updatePosition();
@ -235,7 +227,7 @@ public class ArmorStandEntity extends LivingEntity {
} }
@Override @Override
protected void setInvisible(GeyserSession session, boolean value) { protected void setInvisible(boolean value) {
// Check if the armour stand is invisible and store accordingly // Check if the armour stand is invisible and store accordingly
if (primaryEntity) { if (primaryEntity) {
isInvisible = value; isInvisible = value;
@ -289,7 +281,7 @@ public class ArmorStandEntity extends LivingEntity {
if (!primaryEntity) return; if (!primaryEntity) return;
if (!isInvisible || isMarker) { if (!isInvisible || isMarker) {
// It is either impossible to show armor, or the armor stand isn't invisible. We good. // 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); updateOffsetRequirement(false);
if (positionUpdateRequired) { if (positionUpdateRequired) {
positionUpdateRequired = false; positionUpdateRequired = false;
@ -297,13 +289,13 @@ public class ArmorStandEntity extends LivingEntity {
} }
if (secondEntity != null) { if (secondEntity != null) {
secondEntity.despawnEntity(session); secondEntity.despawnEntity();
secondEntity = null; secondEntity = null;
} }
return; 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() || 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) 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))) { || !boots.equals(ItemData.AIR) || !hand.equals(ItemData.AIR) || !offHand.equals(ItemData.AIR))) {
// If the second entity exists, no need to recreate it. // 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 // 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. // the metadata as it will hold the name tag.
secondEntity = new ArmorStandEntity(0, session.getEntityCache().getNextEntityId().incrementAndGet(), secondEntity = new ArmorStandEntity(session, 0, session.getEntityCache().getNextEntityId().incrementAndGet(), null,
EntityType.ARMOR_STAND, position, motion, rotation); EntityDefinitions.ARMOR_STAND, position, motion, yaw, pitch, headYaw);
secondEntity.primaryEntity = false; secondEntity.primaryEntity = false;
if (!this.positionRequiresOffset) { if (!this.positionRequiresOffset) {
// Ensure the offset is applied for the 0 scale // Ensure the offset is applied for the 0 scale
@ -321,52 +313,51 @@ public class ArmorStandEntity extends LivingEntity {
} }
// Copy metadata // Copy metadata
secondEntity.isSmall = isSmall; secondEntity.isSmall = isSmall;
secondEntity.getMetadata().putAll(metadata); secondEntity.getDirtyMetadata().putAll(dirtyMetadata); //TODO check
// Copy the flags so they aren't the same object in memory secondEntity.flags.merge(this.flags);
secondEntity.getMetadata().putFlags(metadata.getFlags().copy());
// Guarantee this copy is NOT invisible // Guarantee this copy is NOT invisible
secondEntity.getMetadata().getFlags().setFlag(EntityFlag.INVISIBLE, false); secondEntity.setFlag(EntityFlag.INVISIBLE, false);
// Scale to 0 to show nametag // 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 // No bounding box as we don't want to interact with this entity
secondEntity.getMetadata().put(EntityData.BOUNDING_BOX_WIDTH, 0.0f); secondEntity.getDirtyMetadata().put(EntityData.BOUNDING_BOX_WIDTH, 0.0f);
secondEntity.getMetadata().put(EntityData.BOUNDING_BOX_HEIGHT, 0.0f); secondEntity.getDirtyMetadata().put(EntityData.BOUNDING_BOX_HEIGHT, 0.0f);
secondEntity.spawnEntity(session); secondEntity.spawnEntity();
// Reset scale of the proper armor stand // 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 // 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 // Update the position of the armor stand
updateOffsetRequirement(false); updateOffsetRequirement(false);
} else if (isNametagEmpty) { } else if (isNametagEmpty) {
// We can just make an invisible entity // We can just make an invisible entity
// Reset scale of the proper armor stand // 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 // Set the proper armor stand to invisible to show armor
metadata.getFlags().setFlag(EntityFlag.INVISIBLE, true); setFlag(EntityFlag.INVISIBLE, true);
// Update offset // Update offset
updateOffsetRequirement(false); updateOffsetRequirement(false);
if (secondEntity != null) { if (secondEntity != null) {
secondEntity.despawnEntity(session); secondEntity.despawnEntity();
secondEntity = null; secondEntity = null;
} }
} else { } else {
// Nametag is not empty and there is no armor // Nametag is not empty and there is no armor
// We don't need to make a new entity // We don't need to make a new entity
metadata.getFlags().setFlag(EntityFlag.INVISIBLE, false); setFlag(EntityFlag.INVISIBLE, false);
metadata.put(EntityData.SCALE, 0.0f); dirtyMetadata.put(EntityData.SCALE, 0.0f);
// As the above is applied, we need an offset // As the above is applied, we need an offset
updateOffsetRequirement(true); updateOffsetRequirement(true);
if (secondEntity != null) { if (secondEntity != null) {
secondEntity.despawnEntity(session); secondEntity.despawnEntity();
secondEntity = null; secondEntity = null;
} }
} }
if (sendMetadata) { 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. * If this armor stand is not a marker, set its bounding box size and scale.
*/ */
private void toggleSmallStatus() { private void toggleSmallStatus() {
metadata.put(EntityData.BOUNDING_BOX_WIDTH, isSmall ? 0.25f : entityType.getWidth()); dirtyMetadata.put(EntityData.BOUNDING_BOX_WIDTH, isSmall ? 0.25f : definition.width());
metadata.put(EntityData.BOUNDING_BOX_HEIGHT, isSmall ? 0.9875f : entityType.getHeight()); dirtyMetadata.put(EntityData.BOUNDING_BOX_HEIGHT, isSmall ? 0.9875f : definition.height());
metadata.put(EntityData.SCALE, isSmall ? 0.55f : 1f); dirtyMetadata.put(EntityData.SCALE, isSmall ? 0.55f : 1f);
} }
/** /**
* @return the selected position with the position offset applied. * @return the selected position with the position offset applied.
*/ */
private Vector3f applyOffsetToPosition(Vector3f position) { 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) { private Vector3f fixOffsetForSize(Vector3f position, boolean isNowSmall) {
position = removeOffsetFromPosition(position); 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. * @return the selected position with the position offset removed.
*/ */
private Vector3f removeOffsetFromPosition(Vector3f position) { 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(); MoveEntityAbsolutePacket moveEntityPacket = new MoveEntityAbsolutePacket();
moveEntityPacket.setRuntimeEntityId(geyserId); moveEntityPacket.setRuntimeEntityId(geyserId);
moveEntityPacket.setPosition(position); moveEntityPacket.setPosition(position);
moveEntityPacket.setRotation(Vector3f.from(rotation.getX(), rotation.getX(), rotation.getX())); moveEntityPacket.setRotation(Vector3f.from(yaw, yaw, yaw));
moveEntityPacket.setOnGround(onGround); moveEntityPacket.setOnGround(onGround);
moveEntityPacket.setTeleported(false); moveEntityPacket.setTeleported(false);
session.sendUpstreamPacket(moveEntityPacket); session.sendUpstreamPacket(moveEntityPacket);

Datei anzeigen

@ -26,23 +26,22 @@
package org.geysermc.connector.entity.living; 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.EntityMetadata;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata;
import com.nukkitx.math.vector.Vector3f; import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag; 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.network.session.GeyserSession;
import java.util.UUID;
public class BatEntity extends AmbientEntity { public class BatEntity extends AmbientEntity {
public BatEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { public BatEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
super(entityId, geyserId, entityType, position, motion, rotation); super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
} }
@Override public void setBatFlags(EntityMetadata<Byte> entityMetadata) {
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { byte xd = ((ByteEntityMetadata) entityMetadata).getPrimitiveValue();
if (entityMetadata.getId() == 16) { setFlag(EntityFlag.RESTING, (xd & 0x01) == 0x01);
byte xd = (byte) entityMetadata.getValue();
metadata.getFlags().setFlag(EntityFlag.RESTING, (xd & 0x01) == 0x01);
}
super.updateBedrockMetadata(entityMetadata, session);
} }
} }

Datei anzeigen

@ -26,11 +26,14 @@
package org.geysermc.connector.entity.living; package org.geysermc.connector.entity.living;
import com.nukkitx.math.vector.Vector3f; 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) { public class CreatureEntity extends MobEntity {
super(entityId, geyserId, entityType, position, motion, rotation);
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);
} }
} }

Datei anzeigen

@ -26,11 +26,14 @@
package org.geysermc.connector.entity.living; package org.geysermc.connector.entity.living;
import com.nukkitx.math.vector.Vector3f; 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) { public class FlyingEntity extends MobEntity {
super(entityId, geyserId, entityType, position, motion, rotation);
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);
} }
} }

Datei anzeigen

@ -25,19 +25,14 @@
package org.geysermc.connector.entity.living; package org.geysermc.connector.entity.living;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
import com.nukkitx.math.vector.Vector3f; 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.network.session.GeyserSession;
public class GlowSquidEntity extends SquidEntity { import java.util.UUID;
public GlowSquidEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
super(entityId, geyserId, entityType, position, motion, rotation);
}
@Override public class GlowSquidEntity extends SquidEntity {
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { public GlowSquidEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
super.updateBedrockMetadata(entityMetadata, session); super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
// TODO "dark ticks remaining" ??? does this have a Bedrock equivalent?
} }
} }

Datei anzeigen

@ -26,11 +26,14 @@
package org.geysermc.connector.entity.living; package org.geysermc.connector.entity.living;
import com.nukkitx.math.vector.Vector3f; 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 class GolemEntity extends CreatureEntity {
public GolemEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { public GolemEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
super(entityId, geyserId, entityType, position, motion, rotation); super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
} }
} }

Datei anzeigen

@ -28,15 +28,18 @@ package org.geysermc.connector.entity.living;
import com.nukkitx.math.vector.Vector3f; import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityData; import com.nukkitx.protocol.bedrock.data.entity.EntityData;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag; 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 class IronGolemEntity extends GolemEntity {
public IronGolemEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { public IronGolemEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
super(entityId, geyserId, entityType, position, motion, rotation); super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
// Indicate that we should show cracks through a resource pack // 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 // Required, or else the overlay is black
metadata.put(EntityData.COLOR_2, (byte) 0); dirtyMetadata.put(EntityData.COLOR_2, (byte) 0);
} }
} }

Datei anzeigen

@ -27,32 +27,34 @@ package org.geysermc.connector.entity.living;
import com.nukkitx.math.vector.Vector3f; import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityData; 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.network.session.GeyserSession;
import java.util.UUID;
public class MagmaCubeEntity extends SlimeEntity { public class MagmaCubeEntity extends SlimeEntity {
public MagmaCubeEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { public MagmaCubeEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
super(entityId, geyserId, entityType, position, motion, rotation); super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
} }
@Override @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) {
updateJump(session, isOnGround); updateJump(isOnGround);
super.moveRelative(session, relX, relY, relZ, rotation, isOnGround); super.moveRelative(relX, relY, relZ, yaw, pitch, headYaw, isOnGround);
} }
@Override @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) {
updateJump(session, isOnGround); updateJump(isOnGround);
super.moveAbsolute(session, position, rotation, isOnGround, teleported); super.moveAbsolute(position, yaw, pitch, headYaw, isOnGround, teleported);
} }
public void updateJump(GeyserSession session, boolean newOnGround) { public void updateJump(boolean newOnGround) {
if (newOnGround != onGround) { if (newOnGround != onGround) {
// Add the jumping effect to the magma cube // Add the jumping effect to the magma cube
metadata.put(EntityData.CLIENT_EVENT, (byte) (newOnGround ? 1 : 2)); dirtyMetadata.put(EntityData.CLIENT_EVENT, (byte) (newOnGround ? 1 : 2));
updateBedrockMetadata(session); updateBedrockMetadata();
} }
} }
} }

Datei anzeigen

@ -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);
}
}

Datei anzeigen

@ -26,22 +26,21 @@
package org.geysermc.connector.entity.living; 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.EntityMetadata;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata;
import com.nukkitx.math.vector.Vector3f; import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityData; 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.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) { public class SlimeEntity extends MobEntity {
super(entityId, geyserId, entityType, position, motion, rotation);
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 setScale(EntityMetadata<Integer> entityMetadata) {
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { dirtyMetadata.put(EntityData.SCALE, 0.10f + ((IntEntityMetadata) entityMetadata).getPrimitiveValue());
if (entityMetadata.getId() == 16) {
this.metadata.put(EntityData.SCALE, 0.10f + (int) entityMetadata.getValue());
}
super.updateBedrockMetadata(entityMetadata, session);
} }
} }

Datei anzeigen

@ -26,24 +26,23 @@
package org.geysermc.connector.entity.living; 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.EntityMetadata;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata;
import com.nukkitx.math.vector.Vector3f; import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag; 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.network.session.GeyserSession;
import java.util.UUID;
public class SnowGolemEntity extends GolemEntity { public class SnowGolemEntity extends GolemEntity {
public SnowGolemEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { public SnowGolemEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
super(entityId, geyserId, entityType, position, motion, rotation); super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
} }
@Override public void setSnowGolemFlags(EntityMetadata<Byte> entityMetadata) {
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { byte xd = ((ByteEntityMetadata) entityMetadata).getPrimitiveValue();
if (entityMetadata.getId() == 16) { // Handle the visibility of the pumpkin
byte xd = (byte) entityMetadata.getValue(); setFlag(EntityFlag.SHEARED, (xd & 0x10) != 0x10);
// Handle the visibility of the pumpkin
metadata.getFlags().setFlag(EntityFlag.SHEARED, (xd & 0x10) != 0x10);
}
super.updateBedrockMetadata(entityMetadata, session);
} }
} }

Datei anzeigen

@ -28,28 +28,25 @@ package org.geysermc.connector.entity.living;
import com.nukkitx.math.vector.Vector3f; import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag; import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
import com.nukkitx.protocol.bedrock.packet.MoveEntityDeltaPacket; import com.nukkitx.protocol.bedrock.packet.MoveEntityDeltaPacket;
import org.geysermc.connector.entity.EntityDefinition;
import org.geysermc.connector.entity.Tickable; 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.session.GeyserSession;
import org.geysermc.connector.network.translators.world.block.BlockStateValues; import org.geysermc.connector.network.translators.world.block.BlockStateValues;
import java.util.UUID;
public class SquidEntity extends WaterEntity implements Tickable { public class SquidEntity extends WaterEntity implements Tickable {
private float pitch;
private float yaw;
private float targetPitch; private float targetPitch;
private float targetYaw; private float targetYaw;
private boolean inWater; private boolean inWater;
public SquidEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { public SquidEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
super(entityId, geyserId, entityType, position, motion, rotation); super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
this.yaw = rotation.getX();
} }
@Override @Override
public void tick(GeyserSession session) { public void tick() {
boolean pitchChanged; boolean pitchChanged;
boolean yawChanged; boolean yawChanged;
float oldPitch = pitch; float oldPitch = pitch;
@ -82,25 +79,33 @@ public class SquidEntity extends WaterEntity implements Tickable {
} }
@Override @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) {
super.moveRelative(session, relX, relY, relZ, rotation, isOnGround); super.moveRelative(relX, relY, relZ, yaw, pitch, headYaw, isOnGround);
checkInWater(session); checkInWater();
} }
@Override @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) {
super.moveAbsolute(session, position, rotation, isOnGround, teleported); super.moveAbsolute(position, yaw, pitch, headYaw, isOnGround, teleported);
checkInWater(session); checkInWater();
} }
@Override @Override
public void setRotation(Vector3f rotation) { public void setYaw(float yaw) {
// Let the Java server control yaw when the squid is out of water // Let the Java server control yaw when the squid is out of water
if (!inWater) { if (!inWater) {
yaw = rotation.getX(); this.yaw = yaw;
} }
} }
@Override
public void setPitch(float pitch) {
}
@Override
public void setHeadYaw(float headYaw) {
}
@Override @Override
public void setMotion(Vector3f motion) { public void setMotion(Vector3f motion) {
super.setMotion(motion); super.setMotion(motion);
@ -115,8 +120,8 @@ public class SquidEntity extends WaterEntity implements Tickable {
return Vector3f.from(pitch, yaw, yaw); return Vector3f.from(pitch, yaw, yaw);
} }
private void checkInWater(GeyserSession session) { private void checkInWater() {
if (getMetadata().getFlags().getFlag(EntityFlag.RIDING)) { if (getFlag(EntityFlag.RIDING)) {
inWater = false; inWater = false;
} else { } else {
int block = session.getConnector().getWorldManager().getBlockAt(session, position.toInt()); int block = session.getConnector().getWorldManager().getBlockAt(session, position.toInt());

Datei anzeigen

@ -26,11 +26,14 @@
package org.geysermc.connector.entity.living; package org.geysermc.connector.entity.living;
import com.nukkitx.math.vector.Vector3f; 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 class WaterEntity extends CreatureEntity {
public WaterEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { public WaterEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
super(entityId, geyserId, entityType, position, motion, rotation); super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
} }
} }

Datei anzeigen

@ -26,15 +26,17 @@
package org.geysermc.connector.entity.living.animal; package org.geysermc.connector.entity.living.animal;
import com.nukkitx.math.vector.Vector3f; import com.nukkitx.math.vector.Vector3f;
import org.geysermc.connector.entity.EntityDefinition;
import org.geysermc.connector.entity.living.AgeableEntity; 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.network.session.GeyserSession;
import org.geysermc.connector.registry.type.ItemMapping; import org.geysermc.connector.registry.type.ItemMapping;
import java.util.UUID;
public class AnimalEntity extends AgeableEntity { public class AnimalEntity extends AgeableEntity {
public AnimalEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { public AnimalEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
super(entityId, geyserId, entityType, position, motion, rotation); super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
} }
/** /**

Datei anzeigen

@ -26,32 +26,33 @@
package org.geysermc.connector.entity.living.animal; 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.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.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityData; import com.nukkitx.protocol.bedrock.data.entity.EntityData;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag; 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.network.session.GeyserSession;
import org.geysermc.connector.registry.type.ItemMapping; import org.geysermc.connector.registry.type.ItemMapping;
import java.util.UUID;
public class AxolotlEntity extends AnimalEntity { public class AxolotlEntity extends AnimalEntity {
public AxolotlEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { public AxolotlEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
super(entityId, geyserId, entityType, position, motion, rotation); super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
} }
@Override public void setVariant(EntityMetadata<Integer> entityMetadata) {
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { int variant = ((IntEntityMetadata) entityMetadata).getPrimitiveValue();
super.updateBedrockMetadata(entityMetadata, session); switch (variant) {
if (entityMetadata.getId() == 17) { case 1 -> variant = 3; // Java - "Wild" (brown)
int variant = (int) entityMetadata.getValue(); case 3 -> variant = 1; // Java - cyan
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 @Override

Datei anzeigen

@ -26,43 +26,44 @@
package org.geysermc.connector.entity.living.animal; 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.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.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityData; import com.nukkitx.protocol.bedrock.data.entity.EntityData;
import com.nukkitx.protocol.bedrock.data.entity.EntityEventType; import com.nukkitx.protocol.bedrock.data.entity.EntityEventType;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag; import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
import com.nukkitx.protocol.bedrock.packet.EntityEventPacket; 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.network.session.GeyserSession;
import org.geysermc.connector.registry.type.ItemMapping; import org.geysermc.connector.registry.type.ItemMapping;
import java.util.UUID;
public class BeeEntity extends AnimalEntity { public class BeeEntity extends AnimalEntity {
public BeeEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { public BeeEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
super(entityId, geyserId, entityType, position, motion, rotation); super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
} }
@Override public void setBeeFlags(EntityMetadata<Byte> entityMetadata) {
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { byte xd = ((ByteEntityMetadata) entityMetadata).getPrimitiveValue();
if (entityMetadata.getId() == 17) { // Bee is performing sting attack; trigger animation
byte xd = (byte) entityMetadata.getValue(); if ((xd & 0x02) == 0x02) {
// Bee is performing sting attack; trigger animation EntityEventPacket packet = new EntityEventPacket();
if ((xd & 0x02) == 0x02) { packet.setRuntimeEntityId(geyserId);
EntityEventPacket packet = new EntityEventPacket(); packet.setType(EntityEventType.ATTACK_START);
packet.setRuntimeEntityId(geyserId); packet.setData(0);
packet.setType(EntityEventType.ATTACK_START); session.sendUpstreamPacket(packet);
packet.setData(0);
session.sendUpstreamPacket(packet);
}
// If the bee has stung
metadata.put(EntityData.MARK_VARIANT, (xd & 0x04) == 0x04 ? 1 : 0);
// If the bee has nectar or not
metadata.getFlags().setFlag(EntityFlag.POWERED, (xd & 0x08) == 0x08);
} }
if (entityMetadata.getId() == 18) { // If the bee has stung
// Converting "anger time" to a boolean dirtyMetadata.put(EntityData.MARK_VARIANT, (xd & 0x04) == 0x04 ? 1 : 0);
metadata.getFlags().setFlag(EntityFlag.ANGRY, (int) entityMetadata.getValue() > 0); // If the bee has nectar or not
} setFlag(EntityFlag.POWERED, (xd & 0x08) == 0x08);
super.updateBedrockMetadata(entityMetadata, session); }
public void setAngerTime(EntityMetadata<Integer> entityMetadata) {
// Converting "anger time" to a boolean
setFlag(EntityFlag.ANGRY, ((IntEntityMetadata) entityMetadata).getPrimitiveValue() > 0);
} }
@Override @Override

Datei anzeigen

@ -26,14 +26,16 @@
package org.geysermc.connector.entity.living.animal; package org.geysermc.connector.entity.living.animal;
import com.nukkitx.math.vector.Vector3f; 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.network.session.GeyserSession;
import org.geysermc.connector.registry.type.ItemMapping; import org.geysermc.connector.registry.type.ItemMapping;
import java.util.UUID;
public class ChickenEntity extends AnimalEntity { public class ChickenEntity extends AnimalEntity {
public ChickenEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { public ChickenEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
super(entityId, geyserId, entityType, position, motion, rotation); super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
} }
@Override @Override

Datei anzeigen

@ -26,32 +26,32 @@
package org.geysermc.connector.entity.living.animal; 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.EntityMetadata;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata;
import com.nukkitx.math.vector.Vector3f; import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityData; import com.nukkitx.protocol.bedrock.data.entity.EntityData;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag; 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.network.session.GeyserSession;
import org.geysermc.connector.registry.type.ItemMapping; import org.geysermc.connector.registry.type.ItemMapping;
import java.util.UUID;
public class FoxEntity extends AnimalEntity { public class FoxEntity extends AnimalEntity {
public FoxEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { public FoxEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
super(entityId, geyserId, entityType, position, motion, rotation); super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
} }
@Override public void setFoxVariant(EntityMetadata<Integer> entityMetadata) {
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { dirtyMetadata.put(EntityData.VARIANT, entityMetadata.getValue());
if (entityMetadata.getId() == 17) { }
metadata.put(EntityData.VARIANT, entityMetadata.getValue());
} public void setFoxFlags(EntityMetadata<Byte> entityMetadata) {
if (entityMetadata.getId() == 18) { byte xd = ((ByteEntityMetadata) entityMetadata).getPrimitiveValue();
byte xd = (byte) entityMetadata.getValue(); setFlag(EntityFlag.SITTING, (xd & 0x01) == 0x01);
metadata.getFlags().setFlag(EntityFlag.SITTING, (xd & 0x01) == 0x01); setFlag(EntityFlag.SNEAKING, (xd & 0x04) == 0x04);
metadata.getFlags().setFlag(EntityFlag.SNEAKING, (xd & 0x04) == 0x04); setFlag(EntityFlag.INTERESTED, (xd & 0x08) == 0x08);
metadata.getFlags().setFlag(EntityFlag.INTERESTED, (xd & 0x08) == 0x08); setFlag(EntityFlag.SLEEPING, (xd & 0x20) == 0x20);
metadata.getFlags().setFlag(EntityFlag.SLEEPING, (xd & 0x20) == 0x20);
}
super.updateBedrockMetadata(entityMetadata, session);
} }
@Override @Override

Datei anzeigen

@ -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.EntityMetadata;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.Pose; 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.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityData; import com.nukkitx.protocol.bedrock.data.entity.EntityData;
import lombok.Getter; import lombok.Getter;
import org.geysermc.connector.entity.type.EntityType; import org.geysermc.connector.entity.EntityDefinition;
import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.session.GeyserSession;
import java.util.UUID;
public class GoatEntity extends AnimalEntity { public class GoatEntity extends AnimalEntity {
private static final float LONG_JUMPING_HEIGHT = 1.3f * 0.7f; private static final float LONG_JUMPING_HEIGHT = 1.3f * 0.7f;
private static final float LONG_JUMPING_WIDTH = 0.9f * 0.7f; private static final float LONG_JUMPING_WIDTH = 0.9f * 0.7f;
@ -40,24 +43,20 @@ public class GoatEntity extends AnimalEntity {
@Getter @Getter
private boolean isScreamer; private boolean isScreamer;
public GoatEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { public GoatEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
super(entityId, geyserId, entityType, position, motion, rotation); super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
} }
@Override public void setScreamer(EntityMetadata<Boolean> entityMetadata) {
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { // Metadata not used in Bedrock Edition
super.updateBedrockMetadata(entityMetadata, session); isScreamer = ((BooleanEntityMetadata) entityMetadata).getPrimitiveValue();
if (entityMetadata.getId() == 17) {
// Not used in Bedrock Edition
isScreamer = (boolean) entityMetadata.getValue();
}
} }
@Override @Override
protected void setDimensions(Pose pose) { protected void setDimensions(Pose pose) {
if (pose == Pose.LONG_JUMPING) { if (pose == Pose.LONG_JUMPING) {
metadata.put(EntityData.BOUNDING_BOX_WIDTH, LONG_JUMPING_WIDTH); dirtyMetadata.put(EntityData.BOUNDING_BOX_WIDTH, LONG_JUMPING_WIDTH);
metadata.put(EntityData.BOUNDING_BOX_HEIGHT, LONG_JUMPING_HEIGHT); dirtyMetadata.put(EntityData.BOUNDING_BOX_HEIGHT, LONG_JUMPING_HEIGHT);
} else { } else {
super.setDimensions(pose); super.setDimensions(pose);
} }

Datei anzeigen

@ -26,34 +26,32 @@
package org.geysermc.connector.entity.living.animal; 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.EntityMetadata;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanEntityMetadata;
import com.nukkitx.math.vector.Vector3f; import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag; 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.network.session.GeyserSession;
import org.geysermc.connector.registry.type.ItemMapping; import org.geysermc.connector.registry.type.ItemMapping;
import org.geysermc.connector.utils.DimensionUtils; import org.geysermc.connector.utils.DimensionUtils;
import java.util.UUID;
public class HoglinEntity extends AnimalEntity { public class HoglinEntity extends AnimalEntity {
private boolean isImmuneToZombification; private boolean isImmuneToZombification;
public HoglinEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { public HoglinEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
super(entityId, geyserId, entityType, position, motion, rotation); super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
}
public void setImmuneToZombification(EntityMetadata<Boolean> entityMetadata) {
// Apply shaking effect if not in the nether and zombification is possible
this.isImmuneToZombification = ((BooleanEntityMetadata) entityMetadata).getPrimitiveValue();
setFlag(EntityFlag.SHAKING, isShaking());
} }
@Override @Override
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { protected boolean isShaking() {
if (entityMetadata.getId() == 17) { return (!isImmuneToZombification && !session.getDimension().equals(DimensionUtils.NETHER)) || super.isShaking();
// Immune to zombification?
// 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);
}
@Override
protected boolean isShaking(GeyserSession session) {
return (!isImmuneToZombification && !session.getDimension().equals(DimensionUtils.NETHER)) || super.isShaking(session);
} }
@Override @Override

Datei anzeigen

@ -25,23 +25,15 @@
package org.geysermc.connector.entity.living.animal; 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.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityData; import org.geysermc.connector.entity.EntityDefinition;
import org.geysermc.connector.entity.type.EntityType;
import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.session.GeyserSession;
import java.util.UUID;
public class MooshroomEntity extends AnimalEntity { public class MooshroomEntity extends AnimalEntity {
public MooshroomEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { public MooshroomEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
super(entityId, geyserId, entityType, position, motion, rotation); 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().equals("brown") ? 1 : 0);
}
super.updateBedrockMetadata(entityMetadata, session);
} }
} }

Datei anzeigen

@ -25,25 +25,17 @@
package org.geysermc.connector.entity.living.animal; 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.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag; import org.geysermc.connector.entity.EntityDefinition;
import org.geysermc.connector.entity.type.EntityType;
import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.connector.registry.type.ItemMapping; import org.geysermc.connector.registry.type.ItemMapping;
import java.util.UUID;
public class OcelotEntity extends AnimalEntity { public class OcelotEntity extends AnimalEntity {
public OcelotEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { public OcelotEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
super(entityId, geyserId, entityType, position, motion, rotation); super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
}
@Override
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
if (entityMetadata.getId() == 17) {
metadata.getFlags().setFlag(EntityFlag.TRUSTING, (boolean) entityMetadata.getValue());
}
super.updateBedrockMetadata(entityMetadata, session);
} }
@Override @Override

Datei anzeigen

@ -26,57 +26,60 @@
package org.geysermc.connector.entity.living.animal; 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.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.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityData; import com.nukkitx.protocol.bedrock.data.entity.EntityData;
import com.nukkitx.protocol.bedrock.data.entity.EntityEventType; import com.nukkitx.protocol.bedrock.data.entity.EntityEventType;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag; import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
import com.nukkitx.protocol.bedrock.packet.EntityEventPacket; 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.network.session.GeyserSession;
import org.geysermc.connector.registry.type.ItemMapping; 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 mainGene;
private int hiddenGene; private int hiddenGene;
public PandaEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { public PandaEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
super(entityId, geyserId, entityType, position, motion, rotation); super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
} }
@Override public void setEatingCounter(EntityMetadata<Integer> entityMetadata) {
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { int count = ((IntEntityMetadata) entityMetadata).getPrimitiveValue();
if (entityMetadata.getId() == 19) { setFlag(EntityFlag.EATING, count > 0);
metadata.getFlags().setFlag(EntityFlag.EATING, (int) entityMetadata.getValue() > 0); dirtyMetadata.put(EntityData.EATING_COUNTER, count);
metadata.put(EntityData.EATING_COUNTER, entityMetadata.getValue()); if (count != 0) {
if ((int) entityMetadata.getValue() != 0) { // Particles and sound
// Particles and sound EntityEventPacket packet = new EntityEventPacket();
EntityEventPacket packet = new EntityEventPacket(); packet.setRuntimeEntityId(geyserId);
packet.setRuntimeEntityId(geyserId); packet.setType(EntityEventType.EATING_ITEM);
packet.setType(EntityEventType.EATING_ITEM); packet.setData(session.getItemMappings().getStoredItems().bamboo().getBedrockId() << 16);
packet.setData(session.getItemMappings().getStoredItems().bamboo().getBedrockId() << 16); session.sendUpstreamPacket(packet);
session.sendUpstreamPacket(packet);
}
} }
if (entityMetadata.getId() == 20) { }
mainGene = (int) (byte) entityMetadata.getValue();
updateAppearance(); public void setMainGene(EntityMetadata<Byte> entityMetadata) {
} mainGene = ((ByteEntityMetadata) entityMetadata).getPrimitiveValue();
if (entityMetadata.getId() == 21) { updateAppearance();
hiddenGene = (int) (byte) entityMetadata.getValue(); }
updateAppearance();
} public void setHiddenGene(EntityMetadata<Byte> entityMetadata) {
if (entityMetadata.getId() == 22) { hiddenGene = ((ByteEntityMetadata) entityMetadata).getPrimitiveValue();
byte xd = (byte) entityMetadata.getValue(); updateAppearance();
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) {
// Required to put these both for sitting to actually show byte xd = ((ByteEntityMetadata) entityMetadata).getPrimitiveValue();
metadata.put(EntityData.SITTING_AMOUNT, (xd & 0x08) == 0x08 ? 1f : 0f); setFlag(EntityFlag.SNEEZING, (xd & 0x02) == 0x02);
metadata.put(EntityData.SITTING_AMOUNT_PREVIOUS, (xd & 0x08) == 0x08 ? 1f : 0f); setFlag(EntityFlag.ROLLING, (xd & 0x04) == 0x04);
metadata.getFlags().setFlag(EntityFlag.LAYING_DOWN, (xd & 0x10) == 0x10); setFlag(EntityFlag.SITTING, (xd & 0x08) == 0x08);
} // Required to put these both for sitting to actually show
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 @Override
@ -93,14 +96,14 @@ public class PandaEntity extends AnimalEntity {
// Main gene is a recessive trait // Main gene is a recessive trait
if (mainGene == hiddenGene) { if (mainGene == hiddenGene) {
// Main and hidden genes match; this is what the panda looks like. // Main and hidden genes match; this is what the panda looks like.
metadata.put(EntityData.VARIANT, mainGene); dirtyMetadata.put(EntityData.VARIANT, mainGene);
} else { } else {
// Genes have no effect on appearance // Genes have no effect on appearance
metadata.put(EntityData.VARIANT, 0); dirtyMetadata.put(EntityData.VARIANT, 0);
} }
} else { } else {
// No need to worry about hidden gene // No need to worry about hidden gene
metadata.put(EntityData.VARIANT, mainGene); dirtyMetadata.put(EntityData.VARIANT, mainGene);
} }
} }
} }

Datei anzeigen

@ -25,25 +25,17 @@
package org.geysermc.connector.entity.living.animal; 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.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag; import org.geysermc.connector.entity.EntityDefinition;
import org.geysermc.connector.entity.type.EntityType;
import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.connector.registry.type.ItemMapping; import org.geysermc.connector.registry.type.ItemMapping;
import java.util.UUID;
public class PigEntity extends AnimalEntity { public class PigEntity extends AnimalEntity {
public PigEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { public PigEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
super(entityId, geyserId, entityType, position, motion, rotation); super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
}
@Override
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
if (entityMetadata.getId() == 17) {
metadata.getFlags().setFlag(EntityFlag.SADDLED, (boolean) entityMetadata.getValue());
}
super.updateBedrockMetadata(entityMetadata, session);
} }
@Override @Override

Datei anzeigen

@ -25,25 +25,17 @@
package org.geysermc.connector.entity.living.animal; 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.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag; import org.geysermc.connector.entity.EntityDefinition;
import org.geysermc.connector.entity.type.EntityType;
import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.connector.registry.type.ItemMapping; import org.geysermc.connector.registry.type.ItemMapping;
import java.util.UUID;
public class PolarBearEntity extends AnimalEntity { public class PolarBearEntity extends AnimalEntity {
public PolarBearEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { public PolarBearEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
super(entityId, geyserId, entityType, position, motion, rotation); super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
}
@Override
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
if (entityMetadata.getId() == 17) {
metadata.getFlags().setFlag(EntityFlag.STANDING, (boolean) entityMetadata.getValue());
}
super.updateBedrockMetadata(entityMetadata, session);
} }
@Override @Override

Datei anzeigen

@ -26,25 +26,24 @@
package org.geysermc.connector.entity.living.animal; 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.EntityMetadata;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata;
import com.nukkitx.math.vector.Vector3f; import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityData; 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.living.AbstractFishEntity;
import org.geysermc.connector.entity.type.EntityType;
import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.session.GeyserSession;
import java.util.UUID;
public class PufferFishEntity extends AbstractFishEntity { public class PufferFishEntity extends AbstractFishEntity {
public PufferFishEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { public PufferFishEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
super(entityId, geyserId, entityType, position, motion, rotation); super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
} }
@Override public void setPufferfishSize(EntityMetadata<Integer> entityMetadata) {
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { int puffsize = ((IntEntityMetadata) entityMetadata).getPrimitiveValue();
if (entityMetadata.getId() == 17) { dirtyMetadata.put(EntityData.PUFFERFISH_SIZE, (byte) puffsize);
int puffsize = (int) entityMetadata.getValue(); dirtyMetadata.put(EntityData.VARIANT, puffsize);
metadata.put(EntityData.PUFFERFISH_SIZE, (byte) puffsize);
metadata.put(EntityData.VARIANT, puffsize);
}
super.updateBedrockMetadata(entityMetadata, session);
} }
} }

Datei anzeigen

@ -26,42 +26,49 @@
package org.geysermc.connector.entity.living.animal; 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.EntityMetadata;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata;
import com.nukkitx.math.vector.Vector3f; import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityData; import com.nukkitx.protocol.bedrock.data.entity.EntityData;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag; 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.network.session.GeyserSession;
import org.geysermc.connector.registry.type.ItemMapping; import org.geysermc.connector.registry.type.ItemMapping;
import java.util.UUID;
public class RabbitEntity extends AnimalEntity { public class RabbitEntity extends AnimalEntity {
public RabbitEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { public RabbitEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
super(entityId, geyserId, entityType, position, motion, rotation); super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
} }
@Override @Override
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { public void setBaby(EntityMetadata<Boolean> entityMetadata) {
super.updateBedrockMetadata(entityMetadata, session); super.setBaby(entityMetadata);
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);
}
} else if (entityMetadata.getId() == 17) {
int variant = (int) entityMetadata.getValue();
// Change the killer bunny to display as white since it only exists on Java Edition public void setRabbitVariant(EntityMetadata<Integer> entityMetadata) {
boolean isKillerBunny = variant == 99; int variant = ((IntEntityMetadata) entityMetadata).getPrimitiveValue();
if (isKillerBunny) {
variant = 1;
}
// Allow the resource pack to adjust to the killer bunny
metadata.getFlags().setFlag(EntityFlag.BRIBED, isKillerBunny);
metadata.put(EntityData.VARIANT, variant); // Change the killer bunny to display as white since it only exists on Java Edition
boolean isKillerBunny = variant == 99;
if (isKillerBunny) {
variant = 1;
} }
// Allow the resource pack to adjust to the killer bunny
setFlag(EntityFlag.BRIBED, isKillerBunny);
dirtyMetadata.put(EntityData.VARIANT, variant);
}
@Override
protected float getAdultSize() {
return 0.55f;
}
@Override
protected float getBabySize() {
return 0.35f;
} }
@Override @Override

Datei anzeigen

@ -26,26 +26,24 @@
package org.geysermc.connector.entity.living.animal; 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.EntityMetadata;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata;
import com.nukkitx.math.vector.Vector3f; import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityData; import com.nukkitx.protocol.bedrock.data.entity.EntityData;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag; 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.network.session.GeyserSession;
import java.util.UUID;
public class SheepEntity extends AnimalEntity { public class SheepEntity extends AnimalEntity {
public SheepEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { public SheepEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
super(entityId, geyserId, entityType, position, motion, rotation); super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
} }
@Override public void setSheepFlags(EntityMetadata<Byte> entityMetadata) {
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { byte xd = ((ByteEntityMetadata) entityMetadata).getPrimitiveValue();
if (entityMetadata.getId() == 17) { setFlag(EntityFlag.SHEARED, (xd & 0x10) == 0x10);
byte xd = (byte) entityMetadata.getValue(); dirtyMetadata.put(EntityData.COLOR, xd);
metadata.getFlags().setFlag(EntityFlag.SHEARED, (xd & 0x10) == 0x10);
metadata.put(EntityData.COLOR, xd);
}
super.updateBedrockMetadata(entityMetadata, session);
} }
} }

Datei anzeigen

@ -26,70 +26,70 @@
package org.geysermc.connector.entity.living.animal; 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.EntityMetadata;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanEntityMetadata;
import com.nukkitx.math.vector.Vector3f; import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag; import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
import org.geysermc.connector.entity.Entity; 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.network.session.GeyserSession;
import org.geysermc.connector.registry.type.ItemMapping; import org.geysermc.connector.registry.type.ItemMapping;
import java.util.UUID;
public class StriderEntity extends AnimalEntity { public class StriderEntity extends AnimalEntity {
private boolean isCold = false; private boolean isCold = false;
public StriderEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { public StriderEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
super(entityId, geyserId, entityType, position, motion, rotation); super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
metadata.getFlags().setFlag(EntityFlag.FIRE_IMMUNE, true); setFlag(EntityFlag.FIRE_IMMUNE, true);
metadata.getFlags().setFlag(EntityFlag.BREATHING, 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 @Override
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { public void updateBedrockMetadata() {
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) {
// Make sure they are not shaking when riding another entity // Make sure they are not shaking when riding another entity
// Needs to copy the parent state // Needs to copy the parent state
if (metadata.getFlags().getFlag(EntityFlag.RIDING)) { if (getFlag(EntityFlag.RIDING)) {
boolean parentShaking = false; boolean parentShaking = false;
//TODO optimize
for (Entity ent : session.getEntityCache().getEntities().values()) { for (Entity ent : session.getEntityCache().getEntities().values()) {
if (ent.getPassengers().contains(entityId) && ent instanceof StriderEntity) { if (ent.getPassengers().contains(entityId) && ent instanceof StriderEntity) {
parentShaking = ent.getMetadata().getFlags().getFlag(EntityFlag.SHAKING); parentShaking = ent.getFlag(EntityFlag.SHAKING);
break; break;
} }
} }
metadata.getFlags().setFlag(EntityFlag.BREATHING, !parentShaking); setFlag(EntityFlag.BREATHING, !parentShaking);
metadata.getFlags().setFlag(EntityFlag.SHAKING, parentShaking); setFlag(EntityFlag.SHAKING, parentShaking);
} else { } else {
metadata.getFlags().setFlag(EntityFlag.BREATHING, !isCold); setFlag(EntityFlag.BREATHING, !isCold);
metadata.getFlags().setFlag(EntityFlag.SHAKING, isShaking(session)); setFlag(EntityFlag.SHAKING, isShaking());
} }
// Update the passengers if we have any // Update the passengers if we have any
for (long passenger : passengers) { for (long passenger : passengers) {
Entity passengerEntity = session.getEntityCache().getEntityByJavaId(passenger); Entity passengerEntity = session.getEntityCache().getEntityByJavaId(passenger);
if (passengerEntity != null) { if (passengerEntity != null) {
passengerEntity.updateBedrockMetadata(session); passengerEntity.updateBedrockMetadata();
} }
} }
super.updateBedrockMetadata(session); super.updateBedrockMetadata();
} }
@Override @Override
protected boolean isShaking(GeyserSession session) { protected boolean isShaking() {
return isCold || super.isShaking(session); return isCold || super.isShaking();
} }
@Override @Override

Datei anzeigen

@ -26,15 +26,17 @@
package org.geysermc.connector.entity.living.animal; 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.EntityMetadata;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.nukkitx.math.vector.Vector3f; import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityData; import com.nukkitx.protocol.bedrock.data.entity.EntityData;
import it.unimi.dsi.fastutil.ints.IntList; 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.living.AbstractFishEntity;
import org.geysermc.connector.entity.type.EntityType;
import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.session.GeyserSession;
import java.util.List; import java.util.List;
import java.util.UUID;
public class TropicalFishEntity extends AbstractFishEntity { 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> 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"); 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) { public TropicalFishEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
super(entityId, geyserId, entityType, position, motion, rotation); super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
} }
@Override public void setFishVariant(EntityMetadata<Integer> entityMetadata) {
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { int varNumber = ((IntEntityMetadata) entityMetadata).getPrimitiveValue();
if (entityMetadata.getId() == 17) {
int varNumber = (int) entityMetadata.getValue();
metadata.put(EntityData.VARIANT, getShape(varNumber)); // Shape 0-1 dirtyMetadata.put(EntityData.VARIANT, getShape(varNumber)); // Shape 0-1
metadata.put(EntityData.MARK_VARIANT, getPattern(varNumber)); // Pattern 0-5 dirtyMetadata.put(EntityData.MARK_VARIANT, getPattern(varNumber)); // Pattern 0-5
metadata.put(EntityData.COLOR, getBaseColor(varNumber)); // Base color 0-15 dirtyMetadata.put(EntityData.COLOR, getBaseColor(varNumber)); // Base color 0-15
metadata.put(EntityData.COLOR_2, getPatternColor(varNumber)); // Pattern color 0-15 dirtyMetadata.put(EntityData.COLOR_2, getPatternColor(varNumber)); // Pattern color 0-15
}
super.updateBedrockMetadata(entityMetadata, session);
} }
public static int getShape(int variant) { public static int getShape(int variant) {

Datei anzeigen

@ -26,26 +26,27 @@
package org.geysermc.connector.entity.living.animal; 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.EntityMetadata;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanEntityMetadata;
import com.nukkitx.math.vector.Vector3f; import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag; 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.network.session.GeyserSession;
import org.geysermc.connector.registry.type.ItemMapping; import org.geysermc.connector.registry.type.ItemMapping;
import java.util.UUID;
public class TurtleEntity extends AnimalEntity { public class TurtleEntity extends AnimalEntity {
public TurtleEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { public TurtleEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
super(entityId, geyserId, entityType, position, motion, rotation); super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
} }
@Override public void setPregnant(EntityMetadata<Boolean> entityMetadata) {
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { setFlag(EntityFlag.IS_PREGNANT, ((BooleanEntityMetadata) entityMetadata).getPrimitiveValue());
if (entityMetadata.getId() == 18) { }
metadata.getFlags().setFlag(EntityFlag.IS_PREGNANT, (boolean) entityMetadata.getValue());
} else if (entityMetadata.getId() == 19) { public void setLayingEgg(EntityMetadata<Boolean> entityMetadata) {
metadata.getFlags().setFlag(EntityFlag.LAYING_EGG, (boolean) entityMetadata.getValue()); setFlag(EntityFlag.LAYING_EGG, ((BooleanEntityMetadata) entityMetadata).getPrimitiveValue());
}
super.updateBedrockMetadata(entityMetadata, session);
} }
@Override @Override

Datei anzeigen

@ -26,6 +26,7 @@
package org.geysermc.connector.entity.living.animal.horse; 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.EntityMetadata;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.nukkitx.math.vector.Vector3f; import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityData; 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.data.inventory.ContainerType;
import com.nukkitx.protocol.bedrock.packet.EntityEventPacket; import com.nukkitx.protocol.bedrock.packet.EntityEventPacket;
import com.nukkitx.protocol.bedrock.packet.UpdateAttributesPacket; 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.attribute.GeyserAttributeType;
import org.geysermc.connector.entity.living.animal.AnimalEntity; 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.network.session.GeyserSession;
import org.geysermc.connector.registry.type.ItemMapping; import org.geysermc.connector.registry.type.ItemMapping;
import java.util.Set; import java.util.Set;
import java.util.UUID;
public class AbstractHorseEntity extends AnimalEntity { 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", private static final Set<String> DONKEY_AND_HORSE_FOODS = ImmutableSet.of("golden_apple", "enchanted_golden_apple",
"golden_carrot", "sugar", "apple", "wheat", "hay_block"); "golden_carrot", "sugar", "apple", "wheat", "hay_block");
public AbstractHorseEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { public AbstractHorseEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
super(entityId, geyserId, entityType, position, motion, rotation); 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. // 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 @Override
public void spawnEntity(GeyserSession session) { public void spawnEntity() {
super.spawnEntity(session); super.spawnEntity();
// Add horse jump strength attribute to allow donkeys and mules to jump, if they don't send the attribute themselves. // 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 // Confirmed broken without this code by making a new donkey in vanilla 1.17.1
@ -73,49 +79,44 @@ public class AbstractHorseEntity extends AnimalEntity {
session.sendUpstreamPacket(attributesPacket); session.sendUpstreamPacket(attributesPacket);
} }
@Override public void setHorseFlags(EntityMetadata<Byte> entityMetadata) {
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { byte xd = ((ByteEntityMetadata) entityMetadata).getPrimitiveValue();
if (entityMetadata.getId() == 17) { boolean tamed = (xd & 0x02) == 0x02;
byte xd = (byte) entityMetadata.getValue(); boolean saddled = (xd & 0x04) == 0x04;
boolean tamed = (xd & 0x02) == 0x02; setFlag(EntityFlag.TAMED, tamed);
boolean saddled = (xd & 0x04) == 0x04; setFlag(EntityFlag.SADDLED, saddled);
metadata.getFlags().setFlag(EntityFlag.TAMED, tamed); setFlag(EntityFlag.EATING, (xd & 0x10) == 0x10);
metadata.getFlags().setFlag(EntityFlag.SADDLED, saddled); setFlag(EntityFlag.STANDING, (xd & 0x20) == 0x20);
metadata.getFlags().setFlag(EntityFlag.EATING, (xd & 0x10) == 0x10);
metadata.getFlags().setFlag(EntityFlag.STANDING, (xd & 0x20) == 0x20);
// HorseFlags // HorseFlags
// Bred 0x10 // Bred 0x10
// Eating 0x20 // Eating 0x20
// Open mouth 0x80 // Open mouth 0x80
int horseFlags = 0x0; int horseFlags = 0x0;
horseFlags = (xd & 0x40) == 0x40 ? horseFlags | 0x80 : horseFlags; horseFlags = (xd & 0x40) == 0x40 ? horseFlags | 0x80 : horseFlags;
// Only set eating when we don't have mouth open so a player interaction doesn't trigger the eating animation // Only set eating when we don't have mouth open so a player interaction doesn't trigger the eating animation
horseFlags = (xd & 0x10) == 0x10 && (xd & 0x40) != 0x40 ? horseFlags | 0x20 : horseFlags; horseFlags = (xd & 0x10) == 0x10 && (xd & 0x40) != 0x40 ? horseFlags | 0x20 : horseFlags;
// Set the flags into the display item // Set the flags into the display item
metadata.put(EntityData.DISPLAY_ITEM, horseFlags); dirtyMetadata.put(EntityData.DISPLAY_ITEM, horseFlags);
// Send the eating particles // Send the eating particles
// We use the wheat metadata as static particles since Java // We use the wheat metadata as static particles since Java
// doesn't send over what item was used to feed the horse // doesn't send over what item was used to feed the horse
if ((xd & 0x40) == 0x40) { if ((xd & 0x40) == 0x40) {
EntityEventPacket entityEventPacket = new EntityEventPacket(); EntityEventPacket entityEventPacket = new EntityEventPacket();
entityEventPacket.setRuntimeEntityId(geyserId); entityEventPacket.setRuntimeEntityId(geyserId);
entityEventPacket.setType(EntityEventType.EATING_ITEM); entityEventPacket.setType(EntityEventType.EATING_ITEM);
entityEventPacket.setData(session.getItemMappings().getStoredItems().wheat().getBedrockId() << 16); entityEventPacket.setData(session.getItemMappings().getStoredItems().wheat().getBedrockId() << 16);
session.sendUpstreamPacket(entityEventPacket); session.sendUpstreamPacket(entityEventPacket);
}
// Set container type if tamed
metadata.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); // Set container type if tamed
dirtyMetadata.put(EntityData.CONTAINER_TYPE, tamed ? (byte) ContainerType.HORSE.getId() : (byte) 0);
// Shows the jump meter
setFlag(EntityFlag.CAN_POWER_JUMP, saddled);
} }
@Override @Override

Datei anzeigen

@ -25,26 +25,20 @@
package org.geysermc.connector.entity.living.animal.horse; 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.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityData; import org.geysermc.connector.entity.EntityDefinition;
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.network.session.GeyserSession;
import java.util.UUID;
public class ChestedHorseEntity extends AbstractHorseEntity { public class ChestedHorseEntity extends AbstractHorseEntity {
public ChestedHorseEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { public ChestedHorseEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
super(entityId, geyserId, entityType, position, motion, rotation); super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
metadata.put(EntityData.CONTAINER_BASE_SIZE, 16);
} }
@Override @Override
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { protected int getContainerBaseSize() {
if (entityMetadata.getId() == 19) { return 16;
metadata.getFlags().setFlag(EntityFlag.CHESTED, (boolean) entityMetadata.getValue());
}
super.updateBedrockMetadata(entityMetadata, session);
} }
} }

Datei anzeigen

@ -26,24 +26,23 @@
package org.geysermc.connector.entity.living.animal.horse; 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.EntityMetadata;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata;
import com.nukkitx.math.vector.Vector3f; import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityData; 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.network.session.GeyserSession;
import java.util.UUID;
public class HorseEntity extends AbstractHorseEntity { public class HorseEntity extends AbstractHorseEntity {
public HorseEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { public HorseEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
super(entityId, geyserId, entityType, position, motion, rotation); super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
} }
@Override public void setHorseVariant(EntityMetadata<Integer> entityMetadata) {
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { int value = ((IntEntityMetadata) entityMetadata).getPrimitiveValue();
if (entityMetadata.getId() == 19) { dirtyMetadata.put(EntityData.VARIANT, value & 255);
metadata.put(EntityData.VARIANT, ((int) entityMetadata.getValue()) & 255); dirtyMetadata.put(EntityData.MARK_VARIANT, (value >> 8) % 5);
metadata.put(EntityData.MARK_VARIANT, (((int) entityMetadata.getValue()) >> 8) % 5);
}
super.updateBedrockMetadata(entityMetadata, session);
} }
} }

Datei anzeigen

@ -26,54 +26,47 @@
package org.geysermc.connector.entity.living.animal.horse; 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.EntityMetadata;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata;
import com.nukkitx.math.vector.Vector3f; import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityData; import com.nukkitx.protocol.bedrock.data.entity.EntityData;
import com.nukkitx.protocol.bedrock.data.inventory.ItemData; import com.nukkitx.protocol.bedrock.data.inventory.ItemData;
import com.nukkitx.protocol.bedrock.packet.MobArmorEquipmentPacket; 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.network.session.GeyserSession;
import org.geysermc.connector.registry.type.ItemMapping; import org.geysermc.connector.registry.type.ItemMapping;
import java.util.UUID;
public class LlamaEntity extends ChestedHorseEntity { public class LlamaEntity extends ChestedHorseEntity {
public LlamaEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { public LlamaEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
super(entityId, geyserId, entityType, position, motion, rotation); 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) { * Color equipped on the llama
// Strength */
if (entityMetadata.getId() == 20) { public void setCarpetedColor(EntityMetadata<Integer> entityMetadata) {
metadata.put(EntityData.STRENGTH, entityMetadata.getValue()); // Bedrock treats llama decoration as armor
MobArmorEquipmentPacket equipmentPacket = new MobArmorEquipmentPacket();
equipmentPacket.setRuntimeEntityId(geyserId);
// -1 means no armor
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
equipmentPacket.setChestplate(session.getItemMappings().getCarpets().get(carpetIndex));
} else {
equipmentPacket.setChestplate(ItemData.AIR);
} }
// Color equipped on the llama // Required to fill out the rest of the equipment or Bedrock ignores it, including above else statement if removing armor
if (entityMetadata.getId() == 21) { equipmentPacket.setBoots(ItemData.AIR);
// Bedrock treats llama decoration as armor equipmentPacket.setHelmet(ItemData.AIR);
MobArmorEquipmentPacket equipmentPacket = new MobArmorEquipmentPacket(); equipmentPacket.setLeggings(ItemData.AIR);
equipmentPacket.setRuntimeEntityId(geyserId);
// -1 means no armor
int carpetIndex = (int) entityMetadata.getValue();
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
equipmentPacket.setChestplate(session.getItemMappings().getCarpets().get(carpetIndex));
} else {
equipmentPacket.setChestplate(ItemData.AIR);
}
// Required to fill out the rest of the equipment or Bedrock ignores it, including above else statement if removing armor
equipmentPacket.setBoots(ItemData.AIR);
equipmentPacket.setHelmet(ItemData.AIR);
equipmentPacket.setLeggings(ItemData.AIR);
session.sendUpstreamPacket(equipmentPacket); session.sendUpstreamPacket(equipmentPacket);
}
// Color of the llama
if (entityMetadata.getId() == 22) {
metadata.put(EntityData.VARIANT, entityMetadata.getValue());
}
super.updateBedrockMetadata(entityMetadata, session);
} }
@Override @Override

Datei anzeigen

@ -27,18 +27,20 @@ package org.geysermc.connector.entity.living.animal.horse;
import com.nukkitx.math.vector.Vector3f; import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityData; 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.network.session.GeyserSession;
import java.util.UUID;
public class TraderLlamaEntity extends LlamaEntity { public class TraderLlamaEntity extends LlamaEntity {
public TraderLlamaEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { public TraderLlamaEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
super(entityId, geyserId, entityType, position, motion, rotation); super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
} }
@Override @Override
public void spawnEntity(GeyserSession session) { protected void initializeMetadata() {
this.metadata.put(EntityData.MARK_VARIANT, 1); super.initializeMetadata();
super.spawnEntity(session); this.dirtyMetadata.put(EntityData.MARK_VARIANT, 1);
} }
} }

Datei anzeigen

@ -26,58 +26,71 @@
package org.geysermc.connector.entity.living.animal.tameable; 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.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.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityData; import com.nukkitx.protocol.bedrock.data.entity.EntityData;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag; 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.network.session.GeyserSession;
import org.geysermc.connector.registry.type.ItemMapping; import org.geysermc.connector.registry.type.ItemMapping;
import java.util.UUID;
public class CatEntity extends TameableEntity { public class CatEntity extends TameableEntity {
private byte collarColor; private byte collarColor;
public CatEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { public CatEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
super(entityId, geyserId, entityType, position, motion, rotation); super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
} }
@Override @Override
public void updateRotation(GeyserSession session, float yaw, float pitch, boolean isOnGround) { public void updateRotation(float yaw, float pitch, boolean isOnGround) {
moveRelative(session, 0, 0, 0, Vector3f.from(this.rotation.getX(), pitch, yaw), isOnGround); moveRelative(0, 0, 0, yaw, pitch, yaw, isOnGround);
} }
@Override @Override
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { protected float getAdultSize() {
super.updateBedrockMetadata(entityMetadata, session); return 0.8f;
if (entityMetadata.getId() == 16) { }
metadata.put(EntityData.SCALE, (boolean) entityMetadata.getValue() ? 0.4f : 0.8f);
} else if (entityMetadata.getId() == 17) { @Override
// Update collar color if tamed protected float getBabySize() {
if (metadata.getFlags().getFlag(EntityFlag.TAMED)) { return 0.4f;
metadata.put(EntityData.COLOR, collarColor); }
}
@Override
public void setTameableFlags(EntityMetadata<Byte> entityMetadata) {
super.setTameableFlags(entityMetadata);
// Update collar color if tamed
if (getFlag(EntityFlag.TAMED)) {
dirtyMetadata.put(EntityData.COLOR, collarColor);
} }
if (entityMetadata.getId() == 19) { }
// Different colors in Java and Bedrock for some reason
int metadataValue = (int) entityMetadata.getValue(); public void setCatVariant(EntityMetadata<Integer> entityMetadata) {
int variantColor = switch (metadataValue) { // Different colors in Java and Bedrock for some reason
case 0 -> 8; int metadataValue = ((IntEntityMetadata) entityMetadata).getPrimitiveValue();
case 8 -> 0; int variantColor = switch (metadataValue) {
case 9 -> 10; case 0 -> 8;
case 10 -> 9; case 8 -> 0;
default -> metadataValue; case 9 -> 10;
}; case 10 -> 9;
metadata.put(EntityData.VARIANT, variantColor); default -> metadataValue;
} };
if (entityMetadata.getId() == 20) { dirtyMetadata.put(EntityData.VARIANT, variantColor);
metadata.getFlags().setFlag(EntityFlag.RESTING, (boolean) entityMetadata.getValue()); }
}
if (entityMetadata.getId() == 22) { public void setResting(EntityMetadata<Boolean> entityMetadata) {
collarColor = (byte) (int) entityMetadata.getValue(); setFlag(EntityFlag.RESTING, ((BooleanEntityMetadata) entityMetadata).getPrimitiveValue());
// Needed or else wild cats are a red color }
if (metadata.getFlags().getFlag(EntityFlag.TAMED)) {
metadata.put(EntityData.COLOR, collarColor); public void setCollarColor(EntityMetadata<Integer> entityMetadata) {
} collarColor = (byte) ((IntEntityMetadata) entityMetadata).getPrimitiveValue();
// Needed or else wild cats are a red color
if (getFlag(EntityFlag.TAMED)) {
dirtyMetadata.put(EntityData.COLOR, collarColor);
} }
} }

Datei anzeigen

@ -25,26 +25,17 @@
package org.geysermc.connector.entity.living.animal.tameable; 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.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityData; import org.geysermc.connector.entity.EntityDefinition;
import org.geysermc.connector.entity.type.EntityType;
import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.connector.registry.type.ItemMapping; import org.geysermc.connector.registry.type.ItemMapping;
import java.util.UUID;
public class ParrotEntity extends TameableEntity { public class ParrotEntity extends TameableEntity {
public ParrotEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { public ParrotEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
super(entityId, geyserId, entityType, position, motion, rotation); super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
}
@Override
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
// Parrot color
if (entityMetadata.getId() == 19) {
metadata.put(EntityData.VARIANT, entityMetadata.getValue());
}
super.updateBedrockMetadata(entityMetadata, session);
} }
@Override @Override

Datei anzeigen

@ -26,46 +26,51 @@
package org.geysermc.connector.entity.living.animal.tameable; 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.EntityMetadata;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata;
import com.nukkitx.math.vector.Vector3f; import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityData; import com.nukkitx.protocol.bedrock.data.entity.EntityData;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag; import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
import lombok.Getter;
import org.geysermc.connector.entity.Entity; 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.living.animal.AnimalEntity;
import org.geysermc.connector.entity.type.EntityType;
import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.session.GeyserSession;
import java.util.UUID; import java.util.UUID;
public class TameableEntity extends AnimalEntity { 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) { public TameableEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
super(entityId, geyserId, entityType, position, motion, rotation); super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
} }
@Override public void setTameableFlags(EntityMetadata<Byte> entityMetadata) {
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { byte xd = ((ByteEntityMetadata) entityMetadata).getPrimitiveValue();
if (entityMetadata.getId() == 17) { setFlag(EntityFlag.SITTING, (xd & 0x01) == 0x01);
byte xd = (byte) entityMetadata.getValue(); setFlag(EntityFlag.ANGRY, (xd & 0x02) == 0x02);
metadata.getFlags().setFlag(EntityFlag.SITTING, (xd & 0x01) == 0x01); setFlag(EntityFlag.TAMED, (xd & 0x04) == 0x04);
metadata.getFlags().setFlag(EntityFlag.ANGRY, (xd & 0x02) == 0x02); }
metadata.getFlags().setFlag(EntityFlag.TAMED, (xd & 0x04) == 0x04);
}
public void setOwner(EntityMetadata<UUID> entityMetadata) {
// Note: Must be set for wolf collar color to work // Note: Must be set for wolf collar color to work
if (entityMetadata.getId() == 18) { if (entityMetadata.getValue() != null) {
if (entityMetadata.getValue() != null) { // Owner UUID of entity
// Owner UUID of entity Entity entity = session.getEntityCache().getPlayerEntity(entityMetadata.getValue());
Entity entity = session.getEntityCache().getPlayerEntity((UUID) entityMetadata.getValue()); // Used as both a check since the player isn't in the entity cache and a normal fallback
// Used as both a check since the player isn't in the entity cache and a normal fallback if (entity == null) {
if (entity == null) { entity = session.getPlayerEntity();
entity = session.getPlayerEntity();
}
// Translate to entity ID
metadata.put(EntityData.OWNER_EID, entity.getGeyserId());
} else {
metadata.put(EntityData.OWNER_EID, 0L); // Reset
} }
// Translate to entity ID
ownerBedrockId = entity.getGeyserId();
} else {
// Reset
ownerBedrockId = 0L;
} }
super.updateBedrockMetadata(entityMetadata, session); dirtyMetadata.put(EntityData.OWNER_EID, ownerBedrockId);
} }
} }

Datei anzeigen

@ -26,15 +26,18 @@
package org.geysermc.connector.entity.living.animal.tameable; 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.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.google.common.collect.ImmutableSet;
import com.nukkitx.math.vector.Vector3f; import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityData; import com.nukkitx.protocol.bedrock.data.entity.EntityData;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag; 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.network.session.GeyserSession;
import org.geysermc.connector.registry.type.ItemMapping; import org.geysermc.connector.registry.type.ItemMapping;
import java.util.Set; import java.util.Set;
import java.util.UUID;
public class WolfEntity extends TameableEntity { public class WolfEntity extends TameableEntity {
/** /**
@ -47,49 +50,45 @@ public class WolfEntity extends TameableEntity {
private byte collarColor; private byte collarColor;
public WolfEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { public WolfEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
super(entityId, geyserId, entityType, position, motion, rotation); super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
} }
@Override @Override
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { public void setTameableFlags(EntityMetadata<Byte> entityMetadata) {
//Reset wolf color super.setFlags(entityMetadata);
if (entityMetadata.getId() == 17) { // Reset wolf color
byte xd = (byte) entityMetadata.getValue(); byte xd = ((ByteEntityMetadata) entityMetadata).getPrimitiveValue();
boolean angry = (xd & 0x02) == 0x02; boolean angry = (xd & 0x02) == 0x02;
if (angry) { if (angry) {
metadata.put(EntityData.COLOR, (byte) 0); dirtyMetadata.put(EntityData.COLOR, (byte) 0);
} }
}
public void setCollarColor(EntityMetadata<Integer> entityMetadata) {
collarColor = (byte) ((IntEntityMetadata) entityMetadata).getPrimitiveValue();
if (getFlag(EntityFlag.ANGRY)) {
return;
} }
// "Begging" on wiki.vg, "Interested" in Nukkit - the tilt of the head dirtyMetadata.put(EntityData.COLOR, collarColor);
if (entityMetadata.getId() == 19) { if (ownerBedrockId == 0) {
metadata.getFlags().setFlag(EntityFlag.INTERESTED, (boolean) entityMetadata.getValue()); // 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
dirtyMetadata.put(EntityData.OWNER_EID, session.getPlayerEntity().getGeyserId());
} }
}
// Wolf collar color // 1.16+
// Relies on EntityData.OWNER_EID being set in TameableEntity.java public void setWolfAngerTime(EntityMetadata<Integer> entityMetadata) {
if (entityMetadata.getId() == 20 && !metadata.getFlags().getFlag(EntityFlag.ANGRY)) { int time = ((IntEntityMetadata) entityMetadata).getPrimitiveValue();
metadata.put(EntityData.COLOR, collarColor = (byte) (int) entityMetadata.getValue()); setFlag(EntityFlag.ANGRY, time != 0);
if (!metadata.containsKey(EntityData.OWNER_EID)) { dirtyMetadata.put(EntityData.COLOR, time != 0 ? (byte) 0 : collarColor);
// 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());
}
}
// 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);
} }
@Override @Override
public boolean canEat(GeyserSession session, String javaIdentifierStripped, ItemMapping mapping) { public boolean canEat(GeyserSession session, String javaIdentifierStripped, ItemMapping mapping) {
// Cannot be a baby to eat these foods // 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);
} }
} }

Datei anzeigen

@ -26,18 +26,15 @@
package org.geysermc.connector.entity.living.merchant; package org.geysermc.connector.entity.living.merchant;
import com.nukkitx.math.vector.Vector3f; import com.nukkitx.math.vector.Vector3f;
import org.geysermc.connector.entity.EntityDefinition;
import org.geysermc.connector.entity.living.AgeableEntity; 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.network.session.GeyserSession;
import java.util.UUID;
public class AbstractMerchantEntity extends AgeableEntity { public class AbstractMerchantEntity extends AgeableEntity {
public AbstractMerchantEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { public AbstractMerchantEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
super(entityId, geyserId, entityType, position, motion, rotation); super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
}
@Override
public void teleport(GeyserSession session, Vector3f position, float yaw, float pitch, boolean isOnGround) {
super.teleport(session, position, yaw - 180, pitch, isOnGround);
} }
} }

Datei anzeigen

@ -26,6 +26,7 @@
package org.geysermc.connector.entity.living.merchant; 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.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.github.steveice10.mc.protocol.data.game.entity.metadata.VillagerData;
import com.nukkitx.math.vector.Vector3f; import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.math.vector.Vector3i; 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 com.nukkitx.protocol.bedrock.packet.MoveEntityAbsolutePacket;
import it.unimi.dsi.fastutil.ints.Int2IntMap; import it.unimi.dsi.fastutil.ints.Int2IntMap;
import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap; 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.network.session.GeyserSession;
import org.geysermc.connector.registry.BlockRegistries; import org.geysermc.connector.registry.BlockRegistries;
import java.util.regex.Matcher; import java.util.UUID;
import java.util.regex.Pattern;
public class VillagerEntity extends AbstractMerchantEntity { public class VillagerEntity extends AbstractMerchantEntity {
@ -79,32 +80,41 @@ public class VillagerEntity extends AbstractMerchantEntity {
VILLAGER_REGIONS.put(6, 6); VILLAGER_REGIONS.put(6, 6);
} }
public VillagerEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { private Vector3i bedPosition;
super(entityId, geyserId, entityType, position, motion, rotation); /**
* 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);
}
public void setVillagerData(EntityMetadata<VillagerData> entityMetadata) {
VillagerData villagerData = entityMetadata.getValue();
// Profession
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
dirtyMetadata.put(EntityData.MARK_VARIANT, VILLAGER_REGIONS.get(villagerData.getType()));
// Trade tier - different indexing in Bedrock
dirtyMetadata.put(EntityData.TRADE_TIER, villagerData.getLevel() - 1);
} }
@Override @Override
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { public Vector3i setBedPosition(EntityMetadata<Position> entityMetadata) {
if (entityMetadata.getId() == 18) { return bedPosition = super.setBedPosition(entityMetadata);
VillagerData villagerData = (VillagerData) entityMetadata.getValue();
// Profession
metadata.put(EntityData.VARIANT, VILLAGER_PROFESSIONS.get(villagerData.getProfession()));
//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()));
// Trade tier - different indexing in Bedrock
metadata.put(EntityData.TRADE_TIER, villagerData.getLevel() - 1);
}
super.updateBedrockMetadata(entityMetadata, session);
} }
@Override @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) {
// The bed block position, if it exists // The bed block position, if it exists
Vector3i bedPosition; if (!getFlag(EntityFlag.SLEEPING) || bedPosition == null) {
if (!metadata.getFlags().getFlag(EntityFlag.SLEEPING) || (bedPosition = metadata.getPos(EntityData.BED_POSITION, null)) == null) {
// No need to worry about extra processing to compensate for sleeping // 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; return;
} }
@ -133,7 +143,9 @@ public class VillagerEntity extends AbstractMerchantEntity {
zOffset = .5f; zOffset = .5f;
} }
setRotation(rotation); setYaw(yaw);
setPitch(pitch);
setHeadYaw(headYaw);
setOnGround(isOnGround); setOnGround(isOnGround);
this.position = Vector3f.from(position.getX() + relX, position.getY() + relY, position.getZ() + relZ); this.position = Vector3f.from(position.getX() + relX, position.getY() + relY, position.getZ() + relZ);

Datei anzeigen

@ -26,24 +26,25 @@
package org.geysermc.connector.entity.living.monster; 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.EntityMetadata;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata;
import com.nukkitx.math.vector.Vector3f; import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityData; 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.network.session.GeyserSession;
import java.util.UUID;
public class AbstractSkeletonEntity extends MonsterEntity { public class AbstractSkeletonEntity extends MonsterEntity {
public AbstractSkeletonEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { public AbstractSkeletonEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
super(entityId, geyserId, entityType, position, motion, rotation); super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
} }
@Override @Override
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { public void setMobFlags(EntityMetadata<Byte> entityMetadata) {
if (entityMetadata.getId() == 15) { super.setMobFlags(entityMetadata);
byte xd = (byte) entityMetadata.getValue(); byte xd = ((ByteEntityMetadata) entityMetadata).getPrimitiveValue();
// A bit of a loophole so the hands get raised - set the target ID to its own ID // 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); dirtyMetadata.put(EntityData.TARGET_EID, ((xd & 4) == 4) ? geyserId : 0);
}
super.updateBedrockMetadata(entityMetadata, session);
} }
} }

Datei anzeigen

@ -26,32 +26,30 @@
package org.geysermc.connector.entity.living.monster; 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.EntityMetadata;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanEntityMetadata;
import com.nukkitx.math.vector.Vector3f; import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag; 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.network.session.GeyserSession;
import org.geysermc.connector.utils.DimensionUtils; import org.geysermc.connector.utils.DimensionUtils;
import java.util.UUID;
public class BasePiglinEntity extends MonsterEntity { public class BasePiglinEntity extends MonsterEntity {
private boolean isImmuneToZombification; private boolean isImmuneToZombification;
public BasePiglinEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { public BasePiglinEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
super(entityId, geyserId, entityType, position, motion, rotation); super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
}
public void setImmuneToZombification(EntityMetadata<Boolean> entityMetadata) {
// Apply shaking effect if not in the nether and zombification is possible
this.isImmuneToZombification = ((BooleanEntityMetadata) entityMetadata).getPrimitiveValue();
setFlag(EntityFlag.SHAKING, isShaking());
} }
@Override @Override
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { protected boolean isShaking() {
if (entityMetadata.getId() == 16) { return (!isImmuneToZombification && !session.getDimension().equals(DimensionUtils.NETHER)) || super.isShaking();
// Immune to zombification?
// 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);
}
@Override
protected boolean isShaking(GeyserSession session) {
return (!isImmuneToZombification && !session.getDimension().equals(DimensionUtils.NETHER)) || super.isShaking(session);
} }
} }

Datei anzeigen

@ -26,24 +26,22 @@
package org.geysermc.connector.entity.living.monster; 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.EntityMetadata;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata;
import com.nukkitx.math.vector.Vector3f; import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag; 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.network.session.GeyserSession;
import java.util.UUID;
public class BlazeEntity extends MonsterEntity { public class BlazeEntity extends MonsterEntity {
public BlazeEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { public BlazeEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
super(entityId, geyserId, entityType, position, motion, rotation); super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
} }
@Override public void setBlazeFlags(EntityMetadata<Byte> entityMetadata) {
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { byte xd = ((ByteEntityMetadata) entityMetadata).getPrimitiveValue();
if (entityMetadata.getId() == 16) { setFlag(EntityFlag.ON_FIRE, (xd & 0x01) == 0x01);
byte xd = (byte) entityMetadata.getValue();
metadata.getFlags().setFlag(EntityFlag.ON_FIRE, (xd & 0x01) == 0x01);
}
super.updateBedrockMetadata(entityMetadata, session);
} }
} }

Datei anzeigen

@ -26,38 +26,34 @@
package org.geysermc.connector.entity.living.monster; 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.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.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag; 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.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. * Whether the creeper has been ignited and is using {@link #setIgnited(EntityMetadata)}.
* In this instance we ignore ID 15 since it's sending us -1 which confuses poor Bedrock. * In this instance we ignore {@link #setSwelling(EntityMetadata)} since it's sending us -1 which confuses poor Bedrock.
*/ */
private boolean ignitedByFlintAndSteel = false; private boolean ignitedByFlintAndSteel = false;
public CreeperEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { public CreeperEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
super(entityId, geyserId, entityType, position, motion, rotation); super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
} }
@Override public void setSwelling(EntityMetadata<Integer> entityMetadata) {
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { if (!ignitedByFlintAndSteel) {
if (entityMetadata.getId() == 16) { setFlag(EntityFlag.IGNITED, ((IntEntityMetadata) entityMetadata).getPrimitiveValue() == 1);
if (!ignitedByFlintAndSteel) {
metadata.getFlags().setFlag(EntityFlag.IGNITED, (int) entityMetadata.getValue() == 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);
} }
} }

Datei anzeigen

@ -27,14 +27,21 @@ package org.geysermc.connector.entity.living.monster;
import com.nukkitx.math.vector.Vector3f; import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag; 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 class ElderGuardianEntity extends GuardianEntity {
public ElderGuardianEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { public ElderGuardianEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
super(entityId, geyserId, entityType, position, motion, rotation); super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
// Otherwise it just looks like a normal guardian but bigger
metadata.getFlags().setFlag(EntityFlag.ELDER, true);
} }
@Override
protected void initializeMetadata() {
super.initializeMetadata();
// Otherwise it just looks like a normal guardian but bigger
setFlag(EntityFlag.ELDER, true);
}
} }

Datei anzeigen

@ -26,6 +26,7 @@
package org.geysermc.connector.entity.living.monster; 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.EntityMetadata;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata;
import com.nukkitx.math.vector.Vector3f; import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.LevelEventType; import com.nukkitx.protocol.bedrock.data.LevelEventType;
import com.nukkitx.protocol.bedrock.data.entity.EntityData; 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.data.entity.EntityFlag;
import com.nukkitx.protocol.bedrock.packet.*; import com.nukkitx.protocol.bedrock.packet.*;
import lombok.Data; import lombok.Data;
import org.geysermc.connector.entity.EntityDefinition;
import org.geysermc.connector.entity.Tickable; import org.geysermc.connector.entity.Tickable;
import org.geysermc.connector.entity.living.InsentientEntity; import org.geysermc.connector.entity.living.MobEntity;
import org.geysermc.connector.entity.type.EntityType;
import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.connector.utils.DimensionUtils; import org.geysermc.connector.utils.DimensionUtils;
import java.util.Random; import java.util.Random;
import java.util.UUID;
import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.atomic.AtomicLong; 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 * The Ender Dragon has multiple hit boxes, which
* are each its own invisible entity * are each its own invisible entity
@ -78,46 +80,47 @@ public class EnderDragonEntity extends InsentientEntity implements Tickable {
private float wingPosition; private float wingPosition;
private float lastWingPosition; private float lastWingPosition;
public EnderDragonEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { public EnderDragonEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
super(entityId, geyserId, entityType, position, motion, rotation); super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
metadata.getFlags().setFlag(EntityFlag.FIRE_IMMUNE, true);
} }
@Override @Override
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { protected void initializeMetadata() {
if (entityMetadata.getId() == 16) { // Phase super.initializeMetadata();
phase = (int) entityMetadata.getValue(); setFlag(EntityFlag.FIRE_IMMUNE, true);
phaseTicks = 0;
metadata.getFlags().setFlag(EntityFlag.SITTING, isSitting());
}
super.updateBedrockMetadata(entityMetadata, session);
if (entityMetadata.getId() == 9) {
if (phase == 9 && this.health <= 0) { // Dying phase
EntityEventPacket entityEventPacket = new EntityEventPacket();
entityEventPacket.setType(EntityEventType.ENDER_DRAGON_DEATH);
entityEventPacket.setRuntimeEntityId(geyserId);
entityEventPacket.setData(0);
session.sendUpstreamPacket(entityEventPacket);
}
}
} }
@Override @Override
public void spawnEntity(GeyserSession session) { public void setHealth(EntityMetadata<Float> entityMetadata) {
super.spawnEntity(session); super.setHealth(entityMetadata);
if (phase == 9 && this.health <= 0) { // Dying phase
EntityEventPacket entityEventPacket = new EntityEventPacket();
entityEventPacket.setType(EntityEventType.ENDER_DRAGON_DEATH);
entityEventPacket.setRuntimeEntityId(geyserId);
entityEventPacket.setData(0);
session.sendUpstreamPacket(entityEventPacket);
}
}
public void setPhase(EntityMetadata<Integer> entityMetadata) {
phase = ((IntEntityMetadata) entityMetadata).getPrimitiveValue();
phaseTicks = 0;
setFlag(EntityFlag.SITTING, isSitting());
}
@Override
public void spawnEntity() {
super.spawnEntity();
AtomicLong nextEntityId = session.getEntityCache().getNextEntityId(); AtomicLong nextEntityId = session.getEntityCache().getNextEntityId();
head = new EnderDragonPartEntity(entityId + 1, nextEntityId.incrementAndGet(), EntityType.ENDER_DRAGON_PART, 1, 1); head = new EnderDragonPartEntity(session, entityId + 1, nextEntityId.incrementAndGet(), 1, 1);
neck = new EnderDragonPartEntity(entityId + 2, nextEntityId.incrementAndGet(), EntityType.ENDER_DRAGON_PART, 3, 3); neck = new EnderDragonPartEntity(session, entityId + 2, nextEntityId.incrementAndGet(), 3, 3);
body = new EnderDragonPartEntity(entityId + 3, nextEntityId.incrementAndGet(), EntityType.ENDER_DRAGON_PART, 5, 3); body = new EnderDragonPartEntity(session, entityId + 3, nextEntityId.incrementAndGet(), 5, 3);
leftWing = new EnderDragonPartEntity(entityId + 4, nextEntityId.incrementAndGet(), EntityType.ENDER_DRAGON_PART, 4, 2); leftWing = new EnderDragonPartEntity(session, entityId + 4, nextEntityId.incrementAndGet(), 4, 2);
rightWing = new EnderDragonPartEntity(entityId + 5, nextEntityId.incrementAndGet(), EntityType.ENDER_DRAGON_PART, 4, 2); rightWing = new EnderDragonPartEntity(session, entityId + 5, nextEntityId.incrementAndGet(), 4, 2);
tail = new EnderDragonPartEntity[3]; tail = new EnderDragonPartEntity[3];
for (int i = 0; i < 3; i++) { 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]}; 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++) { for (int i = 0; i < segmentHistory.length; i++) {
segmentHistory[i] = new Segment(); segmentHistory[i] = new Segment();
segmentHistory[i].yaw = rotation.getZ(); segmentHistory[i].yaw = headYaw;
segmentHistory[i].y = position.getY(); segmentHistory[i].y = position.getY();
} }
} }
@ -141,29 +144,27 @@ public class EnderDragonEntity extends InsentientEntity implements Tickable {
} }
@Override @Override
public boolean despawnEntity(GeyserSession session) { public boolean despawnEntity() {
for (EnderDragonPartEntity part : allParts) { for (EnderDragonPartEntity part : allParts) {
part.despawnEntity(session); part.despawnEntity();
} }
return super.despawnEntity(session); return super.despawnEntity();
} }
@Override @Override
public void tick(GeyserSession session) { public void tick() {
effectTick(session); effectTick();
if (!metadata.getFlags().getFlag(EntityFlag.NO_AI) && isAlive()) { if (!getFlag(EntityFlag.NO_AI) && isAlive()) {
pushSegment(); pushSegment();
updateBoundingBoxes(session); updateBoundingBoxes();
} }
} }
/** /**
* Updates the positions of the Ender Dragon's multiple bounding boxes * Updates the positions of the Ender Dragon's multiple bounding boxes
*
* @param session GeyserSession.
*/ */
private void updateBoundingBoxes(GeyserSession session) { private void updateBoundingBoxes() {
Vector3f facingDir = Vector3f.createDirectionDeg(0, rotation.getZ()); Vector3f facingDir = Vector3f.createDirectionDeg(0, headYaw);
Segment baseSegment = getSegment(5); Segment baseSegment = getSegment(5);
// Used to angle the head, neck, and tail when the dragon flies up/down // 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())); 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)); neck.setPosition(facingDir.up(pitchY).mul(pitchXZ, 1, -pitchXZ).mul(5.5f).up(headDuck));
body.setPosition(facingDir.mul(0.5f, 0f, -0.5f)); 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); rightWing.setPosition(wingPos);
leftWing.setPosition(wingPos.mul(-1, 1, -1)); // Mirror horizontally 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; float distance = (i + 1) * 2f;
// Curls the tail when the dragon turns // Curls the tail when the dragon turns
Segment targetSegment = getSegment(12 + 2 * i); 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; 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)); tail[i].setPosition(Vector3f.createDirectionDeg(0, angle).mul(distance).add(tailBase).mul(-pitchXZ, 1, pitchXZ).up(tailYOffset));
} }
// Send updated positions // Send updated positions
for (EnderDragonPartEntity part : allParts) { 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 * Handles the particles and sounds of the Ender Dragon
* @param session GeyserSession.
*/ */
private void effectTick(GeyserSession session) { private void effectTick() {
Random random = ThreadLocalRandom.current(); 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) { if (Math.cos(wingPosition * 2f * Math.PI) <= -0.3f && Math.cos(lastWingPosition * 2f * Math.PI) >= -0.3f) {
PlaySoundPacket playSoundPacket = new PlaySoundPacket(); PlaySoundPacket playSoundPacket = new PlaySoundPacket();
playSoundPacket.setSound("mob.enderdragon.flap"); playSoundPacket.setSound("mob.enderdragon.flap");
@ -219,14 +219,14 @@ public class EnderDragonEntity extends InsentientEntity implements Tickable {
} }
if (!isSitting() && !isHovering() && ticksTillNextGrowl-- == 0) { if (!isSitting() && !isHovering() && ticksTillNextGrowl-- == 0) {
playGrowlSound(session); playGrowlSound();
ticksTillNextGrowl = 200 + random.nextInt(200); ticksTillNextGrowl = 200 + random.nextInt(200);
} }
lastWingPosition = wingPosition; lastWingPosition = wingPosition;
} }
if (isAlive()) { if (isAlive()) {
if (metadata.getFlags().getFlag(EntityFlag.NO_AI)) { if (getFlag(EntityFlag.NO_AI)) {
wingPosition = 0.5f; wingPosition = 0.5f;
} else if (isHovering() || isSitting()) { } else if (isHovering() || isSitting()) {
wingPosition += 0.1f; wingPosition += 0.1f;
@ -237,7 +237,7 @@ public class EnderDragonEntity extends InsentientEntity implements Tickable {
phaseTicks++; phaseTicks++;
if (phase == 3) { // Landing Phase 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); Vector3f headCenter = head.getPosition().up(headHeight * 0.5f);
for (int i = 0; i < 8; i++) { 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 } else if (phase == 7) { // Sitting Attacking Phase
playGrowlSound(session); playGrowlSound();
} else if (phase == 9) { // Dying Phase } else if (phase == 9) { // Dying Phase
// Send explosion particles as the dragon move towards the end portal // Send explosion particles as the dragon move towards the end portal
if (phaseTicks % 10 == 0) { 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(); Random random = ThreadLocalRandom.current();
PlaySoundPacket playSoundPacket = new PlaySoundPacket(); PlaySoundPacket playSoundPacket = new PlaySoundPacket();
playSoundPacket.setSound("mob.enderdragon.growl"); playSoundPacket.setSound("mob.enderdragon.growl");
@ -306,7 +306,7 @@ public class EnderDragonEntity extends InsentientEntity implements Tickable {
*/ */
private void pushSegment() { private void pushSegment() {
latestSegment = (latestSegment + 1) % segmentHistory.length; latestSegment = (latestSegment + 1) % segmentHistory.length;
segmentHistory[latestSegment].yaw = rotation.getZ(); segmentHistory[latestSegment].yaw = headYaw;
segmentHistory[latestSegment].y = position.getY(); segmentHistory[latestSegment].y = position.getY();
} }

Datei anzeigen

@ -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.EntityData;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag; import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
import org.geysermc.connector.entity.Entity; 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 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); public EnderDragonPartEntity(GeyserSession session, long entityId, long geyserId, float width, float height) {
metadata.put(EntityData.BOUNDING_BOX_HEIGHT, height); super(session, entityId, geyserId, null, EntityDefinitions.ENDER_DRAGON_PART, Vector3f.ZERO, Vector3f.ZERO, 0, 0, 0);
metadata.getFlags().setFlag(EntityFlag.INVISIBLE, true);
metadata.getFlags().setFlag(EntityFlag.FIRE_IMMUNE, true); dirtyMetadata.put(EntityData.BOUNDING_BOX_WIDTH, width);
dirtyMetadata.put(EntityData.BOUNDING_BOX_HEIGHT, height);
setFlag(EntityFlag.INVISIBLE, true);
setFlag(EntityFlag.FIRE_IMMUNE, true);
} }
} }

Datei anzeigen

@ -26,41 +26,46 @@
package org.geysermc.connector.entity.living.monster; 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.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.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.SoundEvent; import com.nukkitx.protocol.bedrock.data.SoundEvent;
import com.nukkitx.protocol.bedrock.data.entity.EntityData; import com.nukkitx.protocol.bedrock.data.entity.EntityData;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag; import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
import com.nukkitx.protocol.bedrock.packet.LevelSoundEvent2Packet; 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 org.geysermc.connector.network.session.GeyserSession;
import java.util.UUID;
public class EndermanEntity extends MonsterEntity { public class EndermanEntity extends MonsterEntity {
public EndermanEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { public EndermanEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
super(entityId, geyserId, entityType, position, motion, rotation); super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
} }
@Override public void setCarriedBlock(EntityMetadata<Integer> entityMetadata) {
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { dirtyMetadata.put(EntityData.CARRIED_BLOCK, session.getBlockMappings().getBedrockBlockId(((IntEntityMetadata) entityMetadata).getPrimitiveValue()));
// Held block }
if (entityMetadata.getId() == 16) {
metadata.put(EntityData.CARRIED_BLOCK, session.getBlockMappings().getBedrockBlockId((int) entityMetadata.getValue())); /**
} * Controls the screaming sound
// "Is screaming" - controls sound */
if (entityMetadata.getId() == 17) { public void setScreaming(EntityMetadata<Boolean> entityMetadata) {
if ((boolean) entityMetadata.getValue()) { //TODO see if Bedrock controls this differently
LevelSoundEvent2Packet packet = new LevelSoundEvent2Packet(); // Java Edition this controls which ambient sound is used
packet.setSound(SoundEvent.STARE); if (((BooleanEntityMetadata) entityMetadata).getPrimitiveValue()) {
packet.setPosition(this.position); LevelSoundEvent2Packet packet = new LevelSoundEvent2Packet();
packet.setExtraData(-1); packet.setSound(SoundEvent.STARE);
packet.setIdentifier("minecraft:enderman"); packet.setPosition(this.position);
session.sendUpstreamPacket(packet); packet.setExtraData(-1);
} packet.setIdentifier("minecraft:enderman");
session.sendUpstreamPacket(packet);
} }
}
public void setAngry(EntityMetadata<Boolean> entityMetadata) {
// "Is staring/provoked" - controls visuals // "Is staring/provoked" - controls visuals
if (entityMetadata.getId() == 18) { setFlag(EntityFlag.ANGRY, ((BooleanEntityMetadata) entityMetadata).getPrimitiveValue());
metadata.getFlags().setFlag(EntityFlag.ANGRY, (boolean) entityMetadata.getValue());
}
super.updateBedrockMetadata(entityMetadata, session);
} }
} }

Datei anzeigen

@ -26,24 +26,23 @@
package org.geysermc.connector.entity.living.monster; 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.EntityMetadata;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanEntityMetadata;
import com.nukkitx.math.vector.Vector3f; import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityData; 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.living.FlyingEntity;
import org.geysermc.connector.entity.type.EntityType;
import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.session.GeyserSession;
import java.util.UUID;
public class GhastEntity extends FlyingEntity { public class GhastEntity extends FlyingEntity {
public GhastEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { public GhastEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
super(entityId, geyserId, entityType, position, motion, rotation); super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
} }
@Override public void setGhastAttacking(EntityMetadata<Boolean> entityMetadata) {
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { // If the ghast is attacking
if (entityMetadata.getId() == 16) { dirtyMetadata.put(EntityData.CHARGE_AMOUNT, (byte) (((BooleanEntityMetadata) entityMetadata).getPrimitiveValue() ? 1 : 0));
// If the ghast is attacking
metadata.put(EntityData.CHARGE_AMOUNT, (byte) ((boolean) entityMetadata.getValue() ? 1 : 0));
}
super.updateBedrockMetadata(entityMetadata, session);
} }
} }

Datei anzeigen

@ -27,13 +27,16 @@ package org.geysermc.connector.entity.living.monster;
import com.nukkitx.math.vector.Vector3f; import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityData; 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 class GiantEntity extends MonsterEntity {
public GiantEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { public GiantEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
super(entityId, geyserId, entityType, position, motion, rotation); super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
metadata.put(EntityData.SCALE, 6f); dirtyMetadata.put(EntityData.SCALE, 6f);
} }
} }

Datei anzeigen

@ -26,33 +26,34 @@
package org.geysermc.connector.entity.living.monster; 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.EntityMetadata;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata;
import com.nukkitx.math.vector.Vector3f; import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityData; import com.nukkitx.protocol.bedrock.data.entity.EntityData;
import org.geysermc.connector.entity.Entity; 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.network.session.GeyserSession;
import java.util.UUID;
public class GuardianEntity extends MonsterEntity { public class GuardianEntity extends MonsterEntity {
public GuardianEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { public GuardianEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
super(entityId, geyserId, entityType, position, motion, rotation); super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
} }
@Override public void setGuardianTarget(EntityMetadata<Integer> entityMetadata) {
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { int entityId = ((IntEntityMetadata) entityMetadata).getPrimitiveValue();
if (entityMetadata.getId() == 17) { Entity entity;
Entity entity = session.getEntityCache().getEntityByJavaId((int) entityMetadata.getValue()); if (session.getPlayerEntity().getEntityId() == entityId) {
if (entity == null && session.getPlayerEntity().getEntityId() == (Integer) entityMetadata.getValue()) { entity = session.getPlayerEntity();
entity = session.getPlayerEntity(); } else {
} entity = session.getEntityCache().getEntityByJavaId(entityId);
if (entity != null) {
metadata.put(EntityData.TARGET_EID, entity.getGeyserId());
} else {
metadata.put(EntityData.TARGET_EID, (long) 0);
}
} }
super.updateBedrockMetadata(entityMetadata, session); if (entity != null) {
dirtyMetadata.put(EntityData.TARGET_EID, entity.getGeyserId());
} else {
dirtyMetadata.put(EntityData.TARGET_EID, (long) 0);
}
} }
} }

Datei anzeigen

@ -26,12 +26,15 @@
package org.geysermc.connector.entity.living.monster; package org.geysermc.connector.entity.living.monster;
import com.nukkitx.math.vector.Vector3f; import com.nukkitx.math.vector.Vector3f;
import org.geysermc.connector.entity.EntityDefinition;
import org.geysermc.connector.entity.living.CreatureEntity; 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 class MonsterEntity extends CreatureEntity {
public MonsterEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { public MonsterEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
super(entityId, geyserId, entityType, position, motion, rotation); super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
} }
} }

Datei anzeigen

@ -26,28 +26,27 @@
package org.geysermc.connector.entity.living.monster; 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.EntityMetadata;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata;
import com.nukkitx.math.vector.Vector3f; import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityData; 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.living.FlyingEntity;
import org.geysermc.connector.entity.type.EntityType;
import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.session.GeyserSession;
import java.util.UUID;
public class PhantomEntity extends FlyingEntity { public class PhantomEntity extends FlyingEntity {
public PhantomEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { public PhantomEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
super(entityId, geyserId, entityType, position, motion, rotation); super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
} }
@Override public void setPhantomScale(EntityMetadata<Integer> entityMetadata) {
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { int size = ((IntEntityMetadata) entityMetadata).getPrimitiveValue();
if (entityMetadata.getId() == 16) { // Size float modelScale = 1f + 0.15f * size;
int size = (int) entityMetadata.getValue(); float boundsScale = (1f + (0.2f * size) / definition.width()) / modelScale;
float modelScale = 1f + 0.15f * size;
float boundsScale = (1f + (0.2f * size) / EntityType.PHANTOM.getWidth()) / modelScale;
metadata.put(EntityData.BOUNDING_BOX_WIDTH, boundsScale * EntityType.PHANTOM.getWidth()); dirtyMetadata.put(EntityData.BOUNDING_BOX_WIDTH, boundsScale * definition.width());
metadata.put(EntityData.BOUNDING_BOX_HEIGHT, boundsScale * EntityType.PHANTOM.getHeight()); dirtyMetadata.put(EntityData.BOUNDING_BOX_HEIGHT, boundsScale * definition.height());
metadata.put(EntityData.SCALE, modelScale); dirtyMetadata.put(EntityData.SCALE, modelScale);
}
super.updateBedrockMetadata(entityMetadata, session);
} }
} }

Datei anzeigen

@ -26,44 +26,40 @@
package org.geysermc.connector.entity.living.monster; 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.EntityMetadata;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanEntityMetadata;
import com.nukkitx.math.vector.Vector3f; import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityData; import com.nukkitx.protocol.bedrock.data.entity.EntityData;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag; 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.network.session.GeyserSession;
import java.util.UUID;
public class PiglinEntity extends BasePiglinEntity { public class PiglinEntity extends BasePiglinEntity {
public PiglinEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { public PiglinEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
super(entityId, geyserId, entityType, position, motion, rotation); super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
} }
@Override public void setBaby(EntityMetadata<Boolean> entityMetadata) {
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { boolean isBaby = ((BooleanEntityMetadata) entityMetadata).getPrimitiveValue();
if (entityMetadata.getId() == 17) { dirtyMetadata.put(EntityData.SCALE, isBaby? .55f : 1f);
boolean isBaby = (boolean) entityMetadata.getValue(); setFlag(EntityFlag.BABY, isBaby);
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());
}
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 @Override
public void updateOffHand(GeyserSession session) { public void updateOffHand(GeyserSession session) {
// Check if the Piglin is holding Gold and set the ADMIRING flag accordingly so its pose updates // 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))); setFlag(EntityFlag.ADMIRING, session.getTagCache().shouldPiglinAdmire(session.getItemMappings().getMapping(this.offHand)));
if (changed) { super.updateBedrockMetadata();
super.updateBedrockMetadata(session);
}
super.updateOffHand(session); super.updateOffHand(session);
} }

Datei anzeigen

@ -26,44 +26,43 @@
package org.geysermc.connector.entity.living.monster; 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.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.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityData; import com.nukkitx.protocol.bedrock.data.entity.EntityData;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag; 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.living.GolemEntity;
import org.geysermc.connector.entity.type.EntityType;
import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.connector.utils.Direction;
import java.util.UUID;
public class ShulkerEntity extends GolemEntity { public class ShulkerEntity extends GolemEntity {
public ShulkerEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { public ShulkerEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
super(entityId, geyserId, entityType, position, motion, rotation); super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
// Indicate that invisibility should be fixed through the resource pack // Indicate that invisibility should be fixed through the resource pack
metadata.getFlags().setFlag(EntityFlag.BRIBED, true); setFlag(EntityFlag.BRIBED, true);
} }
@Override public void setAttachedFace(EntityMetadata<Direction> entityMetadata) {
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { Direction direction = entityMetadata.getValue();
if (entityMetadata.getId() == 16) { dirtyMetadata.put(EntityData.SHULKER_ATTACH_FACE, (byte) direction.ordinal());
BlockFace blockFace = (BlockFace) entityMetadata.getValue(); }
metadata.put(EntityData.SHULKER_ATTACH_FACE, (byte) blockFace.ordinal());
}
if (entityMetadata.getId() == 17) { public void setShulkerHeight(EntityMetadata<Byte> entityMetadata) {
int height = (byte) entityMetadata.getValue(); int height = ((ByteEntityMetadata) entityMetadata).getPrimitiveValue();
metadata.put(EntityData.SHULKER_PEEK_ID, height); dirtyMetadata.put(EntityData.SHULKER_PEEK_ID, height);
} }
if (entityMetadata.getId() == 18) { public void setShulkerColor(EntityMetadata<Byte> entityMetadata) {
byte color = (byte) entityMetadata.getValue(); byte color = ((ByteEntityMetadata) entityMetadata).getPrimitiveValue();
if (color == 16) { if (color == 16) {
// 16 is default on both editions // 16 is default on both editions
metadata.put(EntityData.VARIANT, 16); dirtyMetadata.put(EntityData.VARIANT, 16);
} else { } else {
// Every other shulker color is offset 15 in bedrock edition // 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);
} }
} }

Datei anzeigen

@ -26,29 +26,28 @@
package org.geysermc.connector.entity.living.monster; 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.EntityMetadata;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanEntityMetadata;
import com.nukkitx.math.vector.Vector3f; import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag; 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.network.session.GeyserSession;
import java.util.UUID;
public class SkeletonEntity extends AbstractSkeletonEntity { public class SkeletonEntity extends AbstractSkeletonEntity {
private boolean convertingToStray = false; private boolean convertingToStray = false;
public SkeletonEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { public SkeletonEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
super(entityId, geyserId, entityType, position, motion, rotation); 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 @Override
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { protected boolean isShaking() {
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) {
return convertingToStray; return convertingToStray;
} }
} }

Datei anzeigen

@ -26,24 +26,22 @@
package org.geysermc.connector.entity.living.monster; 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.EntityMetadata;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata;
import com.nukkitx.math.vector.Vector3f; import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag; 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.network.session.GeyserSession;
import java.util.UUID;
public class SpiderEntity extends MonsterEntity { public class SpiderEntity extends MonsterEntity {
public SpiderEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { public SpiderEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
super(entityId, geyserId, entityType, position, motion, rotation); super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
} }
@Override public void setSpiderFlags(EntityMetadata<Byte> entityMetadata) {
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { byte xd = ((ByteEntityMetadata) entityMetadata).getPrimitiveValue();
if (entityMetadata.getId() == 16) { setFlag(EntityFlag.WALL_CLIMBING, (xd & 0x01) == 0x01);
byte xd = (byte) entityMetadata.getValue();
metadata.getFlags().setFlag(EntityFlag.WALL_CLIMBING, (xd & 0x01) == 0x01);
}
super.updateBedrockMetadata(entityMetadata, session);
} }
} }

Einige Dateien werden nicht angezeigt, da zu viele Dateien in diesem Diff geändert wurden Mehr anzeigen