2020-01-09 03:05:42 +00:00
|
|
|
/*
|
2022-01-01 19:03:05 +00:00
|
|
|
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
|
2020-01-09 03:05:42 +00:00
|
|
|
*
|
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
|
* of this software and associated documentation files (the "Software"), to deal
|
|
|
|
* in the Software without restriction, including without limitation the rights
|
|
|
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
|
|
* copies of the Software, and to permit persons to whom the Software is
|
|
|
|
* furnished to do so, subject to the following conditions:
|
|
|
|
*
|
|
|
|
* The above copyright notice and this permission notice shall be included in
|
|
|
|
* all copies or substantial portions of the Software.
|
|
|
|
*
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
|
|
* THE SOFTWARE.
|
|
|
|
*
|
|
|
|
* @author GeyserMC
|
|
|
|
* @link https://github.com/GeyserMC/Geyser
|
|
|
|
*/
|
|
|
|
|
2021-11-20 23:29:46 +00:00
|
|
|
package org.geysermc.geyser.util;
|
2019-08-03 03:38:09 +00:00
|
|
|
|
2020-03-11 00:40:51 +00:00
|
|
|
import com.github.steveice10.mc.protocol.data.game.entity.Effect;
|
2021-11-18 03:02:38 +00:00
|
|
|
import com.github.steveice10.mc.protocol.data.game.entity.type.EntityType;
|
2021-06-06 15:58:03 +00:00
|
|
|
import com.nukkitx.math.vector.Vector3f;
|
2021-12-18 16:43:57 +00:00
|
|
|
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
|
2021-06-06 15:58:03 +00:00
|
|
|
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
|
2021-11-20 23:29:46 +00:00
|
|
|
import org.geysermc.geyser.entity.type.Entity;
|
2021-11-20 21:34:30 +00:00
|
|
|
import org.geysermc.geyser.entity.EntityDefinitions;
|
2021-11-20 23:29:46 +00:00
|
|
|
import org.geysermc.geyser.entity.type.living.ArmorStandEntity;
|
|
|
|
import org.geysermc.geyser.entity.type.living.animal.AnimalEntity;
|
2019-08-03 03:38:09 +00:00
|
|
|
|
2021-10-12 01:14:06 +00:00
|
|
|
import java.util.Locale;
|
|
|
|
|
2021-06-06 15:58:03 +00:00
|
|
|
public final class EntityUtils {
|
2019-08-03 03:38:09 +00:00
|
|
|
|
2021-10-12 01:14:06 +00:00
|
|
|
/**
|
2021-10-12 01:16:17 +00:00
|
|
|
* @return a new String array of all known effect identifiers
|
2021-10-12 01:14:06 +00:00
|
|
|
*/
|
2021-10-12 01:16:17 +00:00
|
|
|
public static String[] getAllEffectIdentifiers() {
|
2021-10-12 01:14:06 +00:00
|
|
|
String[] identifiers = new String[Effect.VALUES.length];
|
|
|
|
for (int i = 0; i < Effect.VALUES.length; i++) {
|
|
|
|
identifiers[i] = "minecraft:" + Effect.VALUES[i].name().toLowerCase(Locale.ROOT);
|
|
|
|
}
|
|
|
|
|
|
|
|
return identifiers;
|
|
|
|
}
|
|
|
|
|
2020-04-21 05:28:44 +00:00
|
|
|
/**
|
|
|
|
* Convert Java edition effect IDs to Bedrock edition
|
|
|
|
*
|
|
|
|
* @param effect Effect to convert
|
|
|
|
* @return The numeric ID for the Bedrock edition effect
|
|
|
|
*/
|
2020-03-11 00:40:51 +00:00
|
|
|
public static int toBedrockEffectId(Effect effect) {
|
2021-09-10 18:10:56 +00:00
|
|
|
return switch (effect) {
|
|
|
|
case GLOWING, LUCK, UNLUCK, DOLPHINS_GRACE -> 0; // All Java-exclusive effects as of 1.16.2
|
|
|
|
case LEVITATION -> 24;
|
|
|
|
case CONDUIT_POWER -> 26;
|
|
|
|
case SLOW_FALLING -> 27;
|
|
|
|
case BAD_OMEN -> 28;
|
|
|
|
case HERO_OF_THE_VILLAGE -> 29;
|
|
|
|
default -> effect.ordinal() + 1;
|
|
|
|
};
|
2019-08-03 03:38:09 +00:00
|
|
|
}
|
2020-04-21 05:28:44 +00:00
|
|
|
|
2021-06-06 15:58:03 +00:00
|
|
|
private static float getMountedHeightOffset(Entity mount) {
|
2021-11-19 01:44:03 +00:00
|
|
|
float height = mount.getBoundingBoxHeight();
|
2021-06-06 15:58:03 +00:00
|
|
|
float mountedHeightOffset = height * 0.75f;
|
2021-11-18 03:02:38 +00:00
|
|
|
switch (mount.getDefinition().entityType()) {
|
2021-09-10 18:10:56 +00:00
|
|
|
case CHICKEN, SPIDER -> mountedHeightOffset = height * 0.5f;
|
|
|
|
case DONKEY, MULE -> mountedHeightOffset -= 0.25f;
|
2021-12-18 16:43:57 +00:00
|
|
|
case TRADER_LLAMA, LLAMA -> mountedHeightOffset = height * 0.6f;
|
2021-11-27 04:03:46 +00:00
|
|
|
case MINECART, HOPPER_MINECART, TNT_MINECART, CHEST_MINECART, FURNACE_MINECART, SPAWNER_MINECART,
|
|
|
|
COMMAND_BLOCK_MINECART -> mountedHeightOffset = 0;
|
2021-09-10 18:10:56 +00:00
|
|
|
case BOAT -> mountedHeightOffset = -0.1f;
|
|
|
|
case HOGLIN, ZOGLIN -> {
|
2021-11-19 01:44:03 +00:00
|
|
|
boolean isBaby = mount.getFlag(EntityFlag.BABY);
|
2021-06-06 15:58:03 +00:00
|
|
|
mountedHeightOffset = height - (isBaby ? 0.2f : 0.15f);
|
2021-09-10 18:10:56 +00:00
|
|
|
}
|
|
|
|
case PIGLIN -> mountedHeightOffset = height * 0.92f;
|
|
|
|
case RAVAGER -> mountedHeightOffset = 2.1f;
|
|
|
|
case SKELETON_HORSE -> mountedHeightOffset -= 0.1875f;
|
|
|
|
case STRIDER -> mountedHeightOffset = height - 0.19f;
|
2021-06-06 15:58:03 +00:00
|
|
|
}
|
|
|
|
return mountedHeightOffset;
|
|
|
|
}
|
|
|
|
|
|
|
|
private static float getHeightOffset(Entity passenger) {
|
|
|
|
boolean isBaby;
|
2021-11-18 03:02:38 +00:00
|
|
|
switch (passenger.getDefinition().entityType()) {
|
2021-06-06 15:58:03 +00:00
|
|
|
case SKELETON:
|
|
|
|
case STRAY:
|
|
|
|
case WITHER_SKELETON:
|
|
|
|
return -0.6f;
|
|
|
|
case ARMOR_STAND:
|
|
|
|
if (((ArmorStandEntity) passenger).isMarker()) {
|
|
|
|
return 0.0f;
|
|
|
|
} else {
|
|
|
|
return 0.1f;
|
|
|
|
}
|
|
|
|
case ENDERMITE:
|
|
|
|
case SILVERFISH:
|
|
|
|
return 0.1f;
|
|
|
|
case PIGLIN:
|
|
|
|
case PIGLIN_BRUTE:
|
|
|
|
case ZOMBIFIED_PIGLIN:
|
2021-11-19 01:44:03 +00:00
|
|
|
isBaby = passenger.getFlag(EntityFlag.BABY);
|
2021-06-06 15:58:03 +00:00
|
|
|
return isBaby ? -0.05f : -0.45f;
|
|
|
|
case ZOMBIE:
|
2021-11-19 01:44:03 +00:00
|
|
|
isBaby = passenger.getFlag(EntityFlag.BABY);
|
2021-06-06 15:58:03 +00:00
|
|
|
return isBaby ? 0.0f : -0.45f;
|
|
|
|
case EVOKER:
|
|
|
|
case ILLUSIONER:
|
|
|
|
case PILLAGER:
|
|
|
|
case RAVAGER:
|
|
|
|
case VINDICATOR:
|
|
|
|
case WITCH:
|
|
|
|
return -0.45f;
|
|
|
|
case PLAYER:
|
|
|
|
return -0.35f;
|
|
|
|
}
|
|
|
|
if (passenger instanceof AnimalEntity) {
|
|
|
|
return 0.14f;
|
|
|
|
}
|
|
|
|
return 0f;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Adjust an entity's height if they have mounted/dismounted an entity.
|
|
|
|
*/
|
2021-11-18 03:02:38 +00:00
|
|
|
public static void updateMountOffset(Entity passenger, Entity mount, boolean rider, boolean riding, boolean moreThanOneEntity) {
|
|
|
|
passenger.setFlag(EntityFlag.RIDING, riding);
|
2021-06-06 15:58:03 +00:00
|
|
|
if (riding) {
|
|
|
|
// Without the Y offset, Bedrock players will find themselves in the floor when mounting
|
|
|
|
float mountedHeightOffset = getMountedHeightOffset(mount);
|
|
|
|
float heightOffset = getHeightOffset(passenger);
|
|
|
|
|
|
|
|
float xOffset = 0;
|
|
|
|
float yOffset = mountedHeightOffset + heightOffset;
|
|
|
|
float zOffset = 0;
|
2021-11-18 03:02:38 +00:00
|
|
|
switch (mount.getDefinition().entityType()) {
|
2021-12-18 16:43:57 +00:00
|
|
|
case BOAT -> {
|
2021-06-06 15:58:03 +00:00
|
|
|
// Without the X offset, more than one entity on a boat is stacked on top of each other
|
|
|
|
if (rider && moreThanOneEntity) {
|
|
|
|
xOffset = 0.2f;
|
|
|
|
} else if (moreThanOneEntity) {
|
|
|
|
xOffset = -0.6f;
|
|
|
|
}
|
2021-12-18 16:43:57 +00:00
|
|
|
}
|
|
|
|
case CHICKEN -> zOffset = -0.1f;
|
|
|
|
case TRADER_LLAMA, LLAMA -> zOffset = -0.3f;
|
|
|
|
}
|
|
|
|
if (passenger.getDefinition().entityType() == EntityType.SHULKER) {
|
|
|
|
switch (mount.getDefinition().entityType()) {
|
|
|
|
case MINECART, HOPPER_MINECART, TNT_MINECART, CHEST_MINECART, FURNACE_MINECART, SPAWNER_MINECART,
|
|
|
|
COMMAND_BLOCK_MINECART, BOAT -> yOffset = 0.1875f;
|
|
|
|
}
|
2021-06-06 15:58:03 +00:00
|
|
|
}
|
|
|
|
/*
|
|
|
|
* Bedrock Differences
|
|
|
|
* Zoglin & Hoglin seem to be taller in Bedrock edition
|
|
|
|
* Horses are tinier
|
|
|
|
* Players, Minecarts, and Boats have different origins
|
|
|
|
*/
|
2021-12-18 16:43:57 +00:00
|
|
|
if (passenger.getDefinition().entityType() == EntityType.PLAYER) {
|
|
|
|
if (mount.getDefinition().entityType() != EntityType.PLAYER && mount.getDefinition().entityType() != EntityType.AREA_EFFECT_CLOUD) {
|
|
|
|
yOffset += EntityDefinitions.PLAYER.offset();
|
|
|
|
}
|
2021-06-06 15:58:03 +00:00
|
|
|
}
|
2021-11-18 03:02:38 +00:00
|
|
|
switch (mount.getDefinition().entityType()) {
|
2021-11-27 04:03:46 +00:00
|
|
|
case MINECART, HOPPER_MINECART, TNT_MINECART, CHEST_MINECART, FURNACE_MINECART, SPAWNER_MINECART,
|
|
|
|
COMMAND_BLOCK_MINECART, BOAT -> yOffset -= mount.getDefinition().height() * 0.5f;
|
2021-06-06 15:58:03 +00:00
|
|
|
}
|
|
|
|
Vector3f offset = Vector3f.from(xOffset, yOffset, zOffset);
|
2021-11-19 01:44:03 +00:00
|
|
|
passenger.setRiderSeatPosition(offset);
|
2021-06-06 15:58:03 +00:00
|
|
|
}
|
2021-12-18 16:43:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public static void updateRiderRotationLock(Entity passenger, Entity mount, boolean isRiding) {
|
|
|
|
if (isRiding && mount.getDefinition() == EntityDefinitions.BOAT) {
|
|
|
|
// Head rotation is locked while riding in a boat
|
|
|
|
passenger.getDirtyMetadata().put(EntityData.RIDER_ROTATION_LOCKED, (byte) 1);
|
|
|
|
passenger.getDirtyMetadata().put(EntityData.RIDER_MAX_ROTATION, 90f);
|
|
|
|
passenger.getDirtyMetadata().put(EntityData.RIDER_MIN_ROTATION, 1f);
|
|
|
|
passenger.getDirtyMetadata().put(EntityData.RIDER_ROTATION_OFFSET, -90f);
|
|
|
|
} else {
|
|
|
|
passenger.getDirtyMetadata().put(EntityData.RIDER_ROTATION_LOCKED, (byte) 0);
|
|
|
|
passenger.getDirtyMetadata().put(EntityData.RIDER_MAX_ROTATION, 0f);
|
|
|
|
passenger.getDirtyMetadata().put(EntityData.RIDER_MIN_ROTATION, 0f);
|
|
|
|
passenger.getDirtyMetadata().put(EntityData.RIDER_ROTATION_OFFSET, 0f);
|
|
|
|
}
|
2021-06-06 15:58:03 +00:00
|
|
|
}
|
2021-10-12 01:14:06 +00:00
|
|
|
|
|
|
|
private EntityUtils() {
|
|
|
|
}
|
2019-08-03 03:38:09 +00:00
|
|
|
}
|