Updated to 1.19

This commit is contained in:
ImDaBigBoss 2022-06-08 14:09:14 +02:00
commit 4e2f74481b
313 changed files with 4130 additions and 21680 deletions

View file

@ -1,5 +1,5 @@
import net.kyori.indra.git.IndraGitExtension
import net.kyori.blossom.BlossomExtension
import net.kyori.indra.git.IndraGitExtension
plugins {
id("net.kyori.blossom")
@ -31,7 +31,7 @@ dependencies {
// Network libraries
implementation("org.java-websocket", "Java-WebSocket", Versions.websocketVersion)
api("com.github.CloudburstMC.Protocol", "bedrock-v503", Versions.protocolVersion) {
api("com.github.CloudburstMC.Protocol", "bedrock-v527", Versions.protocolVersion) {
exclude("com.nukkitx.network", "raknet")
exclude("com.nukkitx", "nbt")
}

View file

@ -26,10 +26,10 @@
package org.geysermc.connector;
import com.nukkitx.protocol.bedrock.BedrockServer;
import org.geysermc.api.Geyser;
import org.geysermc.common.PlatformType;
import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.api.Geyser;
import java.util.UUID;

View file

@ -25,8 +25,8 @@
package org.geysermc.geyser;
import org.geysermc.geyser.configuration.GeyserJacksonConfiguration;
import org.geysermc.geyser.api.network.AuthType;
import org.geysermc.geyser.configuration.GeyserJacksonConfiguration;
import org.geysermc.geyser.text.GeyserLocale;
import java.nio.file.Files;
@ -43,7 +43,7 @@ public class FloodgateKeyLoader {
if (floodgateDataFolder != null) {
Path autoKey = floodgateDataFolder.resolve("key.pem");
if (Files.exists(autoKey)) {
logger.info(GeyserLocale.getLocaleStringLog("geyser.bootstrap.floodgate.auto_loaded"));
logger.debug(GeyserLocale.getLocaleStringLog("geyser.bootstrap.floodgate.auto_loaded"));
return autoKey;
} else {
logger.error(GeyserLocale.getLocaleStringLog("geyser.bootstrap.floodgate.missing_key"));
@ -52,7 +52,7 @@ public class FloodgateKeyLoader {
Path floodgateKey;
if (config.getFloodgateKeyFile().equals("public-key.pem")) {
logger.info("Floodgate 2.0 doesn't use a public/private key system anymore. We'll search for key.pem instead");
logger.debug("Floodgate 2.0 doesn't use a public/private key system anymore. We'll search for key.pem instead");
floodgateKey = geyserDataFolder.resolve("key.pem");
} else {
floodgateKey = geyserDataFolder.resolve(config.getFloodgateKeyFile());

View file

@ -55,6 +55,7 @@ import org.geysermc.geyser.api.event.EventBus;
import org.geysermc.geyser.api.event.lifecycle.GeyserPostInitializeEvent;
import org.geysermc.geyser.api.event.lifecycle.GeyserPreInitializeEvent;
import org.geysermc.geyser.api.event.lifecycle.GeyserShutdownEvent;
import org.geysermc.geyser.api.network.AuthType;
import org.geysermc.geyser.api.network.BedrockListener;
import org.geysermc.geyser.api.network.RemoteServer;
import org.geysermc.geyser.command.GeyserCommandManager;
@ -75,9 +76,9 @@ import org.geysermc.geyser.scoreboard.ScoreboardUpdater;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.session.PendingMicrosoftAuthentication;
import org.geysermc.geyser.session.SessionManager;
import org.geysermc.geyser.api.network.AuthType;
import org.geysermc.geyser.skin.FloodgateSkinUploader;
import org.geysermc.geyser.skin.SkinProvider;
import org.geysermc.geyser.text.ChatColor;
import org.geysermc.geyser.text.GeyserLocale;
import org.geysermc.geyser.text.MinecraftLocale;
import org.geysermc.geyser.translator.inventory.item.ItemTranslator;
@ -89,6 +90,7 @@ import javax.naming.directory.InitialDirContext;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.UnknownHostException;
@ -247,7 +249,6 @@ public class GeyserImpl implements GeyserApi {
GeyserLogger logger = bootstrap.getGeyserLogger();
GeyserConfiguration config = bootstrap.getGeyserConfig();
logger.setDebug(config.isDebugMode());
ScoreboardUpdater.init();
@ -295,16 +296,22 @@ public class GeyserImpl implements GeyserApi {
// Ensure that PacketLib does not create an event loop for handling packets; we'll do that ourselves
TcpSession.USE_EVENT_LOOP_FOR_PACKETS = false;
if (config.getRemote().getAuthType() == AuthType.FLOODGATE) {
try {
Key key = new AesKeyProducer().produceFrom(config.getFloodgateKeyPath());
cipher = new AesCipher(new Base64Topping());
cipher.init(key);
logger.info(GeyserLocale.getLocaleStringLog("geyser.auth.floodgate.loaded_key"));
skinUploader = new FloodgateSkinUploader(this).start();
} catch (Exception exception) {
logger.severe(GeyserLocale.getLocaleStringLog("geyser.auth.floodgate.bad_key"), exception);
String branch = "unknown";
int buildNumber = -1;
if (this.isProductionEnvironment()) {
try (InputStream stream = bootstrap.getResource("git.properties")) {
Properties gitProperties = new Properties();
gitProperties.load(stream);
branch = gitProperties.getProperty("git.branch");
String build = gitProperties.getProperty("git.build.number");
if (build != null) {
buildNumber = Integer.parseInt(build);
}
} catch (Throwable e) {
logger.error("Failed to read git.properties", e);
}
} else {
logger.debug("Not getting git properties for the news handler as we are in a development environment.");
}
pendingMicrosoftAuthentication = new PendingMicrosoftAuthentication(config.getPendingAuthenticationTimeout());
@ -349,14 +356,34 @@ public class GeyserImpl implements GeyserApi {
if (shouldStartListener) {
bedrockServer.bind().whenComplete((avoid, throwable) -> {
if (throwable == null) {
logger.info(GeyserLocale.getLocaleStringLog("geyser.core.start", config.getBedrock().getAddress(), String.valueOf(config.getBedrock().getPort())));
logger.info(GeyserLocale.getLocaleStringLog("geyser.core.start", config.getBedrock().getAddress(),
String.valueOf(config.getBedrock().getPort())));
} else {
logger.severe(GeyserLocale.getLocaleStringLog("geyser.core.fail", config.getBedrock().getAddress(), String.valueOf(config.getBedrock().getPort())));
throwable.printStackTrace();
String address = config.getBedrock().getAddress();
int port = config.getBedrock().getPort();
logger.severe(GeyserLocale.getLocaleStringLog("geyser.core.fail", address, String.valueOf(port)));
if (!"0.0.0.0".equals(address)) {
logger.info(ChatColor.GREEN + "Suggestion: try setting `address` under `bedrock` in the Geyser config back to 0.0.0.0");
logger.info(ChatColor.GREEN + "Then, restart this server.");
}
}
}).join();
}
if (config.getRemote().getAuthType() == AuthType.FLOODGATE) {
try {
Key key = new AesKeyProducer().produceFrom(config.getFloodgateKeyPath());
cipher = new AesCipher(new Base64Topping());
cipher.init(key);
logger.debug(GeyserLocale.getLocaleStringLog("geyser.auth.floodgate.loaded_key"));
// Note: this is positioned after the bind so the skin uploader doesn't try to run if Geyser fails
// to load successfully. Spigot complains about class loader if the plugin is disabled.
skinUploader = new FloodgateSkinUploader(this).start();
} catch (Exception exception) {
logger.severe(GeyserLocale.getLocaleStringLog("geyser.auth.floodgate.bad_key"), exception);
}
}
if (config.getMetrics().isEnabled()) {
metrics = new Metrics(this, "GeyserMC", config.getMetrics().getUniqueId(), false, java.util.logging.Logger.getLogger(""));
metrics.addCustomChart(new Metrics.SingleLineChart("players", sessionManager::size));

View file

@ -86,4 +86,14 @@ public abstract class GeyserCommand implements Command {
public void setAliases(List<String> aliases) {
this.aliases = aliases;
}
/**
* Used for permission defaults on server implementations.
*
* @return if this command is designated to be used only by server operators.
*/
@Override
public boolean isSuggestedOpOnly() {
return false;
}
}

View file

@ -26,7 +26,6 @@
package org.geysermc.geyser.command;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.geysermc.common.PlatformType;
@ -42,7 +41,10 @@ import org.geysermc.geyser.text.GeyserLocale;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.*;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@RequiredArgsConstructor
public abstract class GeyserCommandManager extends CommandManager {
@ -155,6 +157,7 @@ public abstract class GeyserCommandManager extends CommandManager {
private String description = "";
private String permission = "";
private List<String> aliases;
private boolean suggestedOpOnly = false;
private boolean executableOnConsole = true;
private List<String> subCommands;
private boolean bedrockOnly;
@ -180,6 +183,12 @@ public abstract class GeyserCommandManager extends CommandManager {
return this;
}
@Override
public Command.Builder<T> suggestedOpOnly(boolean suggestedOpOnly) {
this.suggestedOpOnly = suggestedOpOnly;
return this;
}
public CommandBuilder<T> executableOnConsole(boolean executableOnConsole) {
this.executableOnConsole = executableOnConsole;
return this;
@ -231,6 +240,11 @@ public abstract class GeyserCommandManager extends CommandManager {
return CommandBuilder.this.aliases == null ? Collections.emptyList() : CommandBuilder.this.aliases;
}
@Override
public boolean isSuggestedOpOnly() {
return CommandBuilder.this.suggestedOpOnly;
}
@NonNull
@Override
public List<String> subCommands() {

View file

@ -25,8 +25,8 @@
package org.geysermc.geyser.command.defaults;
import org.geysermc.geyser.command.GeyserCommandSource;
import org.geysermc.geyser.command.GeyserCommand;
import org.geysermc.geyser.command.GeyserCommandSource;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.text.MinecraftLocale;

View file

@ -25,8 +25,8 @@
package org.geysermc.geyser.command.defaults;
import org.geysermc.geyser.command.GeyserCommandSource;
import org.geysermc.geyser.command.GeyserCommand;
import org.geysermc.geyser.command.GeyserCommandSource;
import org.geysermc.geyser.session.GeyserSession;
public class AdvancementsCommand extends GeyserCommand {

View file

@ -32,12 +32,12 @@ import com.fasterxml.jackson.databind.ObjectMapper;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.geysermc.common.PlatformType;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.command.GeyserCommandSource;
import org.geysermc.geyser.command.GeyserCommand;
import org.geysermc.geyser.text.ChatColor;
import org.geysermc.geyser.text.AsteriskSerializer;
import org.geysermc.geyser.command.GeyserCommandSource;
import org.geysermc.geyser.dump.DumpInfo;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.text.AsteriskSerializer;
import org.geysermc.geyser.text.ChatColor;
import org.geysermc.geyser.text.GeyserLocale;
import org.geysermc.geyser.util.WebUtils;
@ -147,4 +147,9 @@ public class DumpCommand extends GeyserCommand {
public List<String> subCommands() {
return Arrays.asList("offline", "full", "logs");
}
@Override
public boolean isSuggestedOpOnly() {
return true;
}
}

View file

@ -28,10 +28,10 @@ package org.geysermc.geyser.command.defaults;
import org.geysermc.common.PlatformType;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.api.command.Command;
import org.geysermc.geyser.command.GeyserCommandSource;
import org.geysermc.geyser.command.GeyserCommand;
import org.geysermc.geyser.text.ChatColor;
import org.geysermc.geyser.command.GeyserCommandSource;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.text.ChatColor;
import org.geysermc.geyser.text.GeyserLocale;
import java.util.Collections;

View file

@ -26,8 +26,8 @@
package org.geysermc.geyser.command.defaults;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.command.GeyserCommandSource;
import org.geysermc.geyser.command.GeyserCommand;
import org.geysermc.geyser.command.GeyserCommandSource;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.text.GeyserLocale;
@ -51,4 +51,9 @@ public class ListCommand extends GeyserCommand {
sender.sendMessage(message);
}
@Override
public boolean isSuggestedOpOnly() {
return true;
}
}

View file

@ -28,11 +28,11 @@ package org.geysermc.geyser.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.packet.ingame.serverbound.player.ServerboundPlayerActionPacket;
import com.nukkitx.math.vector.Vector3i;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.command.GeyserCommandSource;
import org.geysermc.geyser.command.GeyserCommand;
import org.geysermc.geyser.command.GeyserCommandSource;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.util.BlockUtils;
public class OffhandCommand extends GeyserCommand {
@ -46,8 +46,8 @@ public class OffhandCommand extends GeyserCommand {
return;
}
ServerboundPlayerActionPacket releaseItemPacket = new ServerboundPlayerActionPacket(PlayerAction.SWAP_HANDS, BlockUtils.POSITION_ZERO,
Direction.DOWN);
ServerboundPlayerActionPacket releaseItemPacket = new ServerboundPlayerActionPacket(PlayerAction.SWAP_HANDS, Vector3i.ZERO,
Direction.DOWN, session.getNextSequence());
session.sendDownstreamPacket(releaseItemPacket);
}

View file

@ -27,8 +27,8 @@ package org.geysermc.geyser.command.defaults;
import org.geysermc.common.PlatformType;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.command.GeyserCommandSource;
import org.geysermc.geyser.command.GeyserCommand;
import org.geysermc.geyser.command.GeyserCommandSource;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.text.GeyserLocale;
@ -54,4 +54,9 @@ public class ReloadCommand extends GeyserCommand {
geyser.getSessionManager().disconnectAll("geyser.commands.reload.kick");
geyser.reload();
}
@Override
public boolean isSuggestedOpOnly() {
return true;
}
}

View file

@ -26,8 +26,8 @@
package org.geysermc.geyser.command.defaults;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.command.GeyserCommandSource;
import org.geysermc.geyser.command.GeyserCommand;
import org.geysermc.geyser.command.GeyserCommandSource;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.util.SettingsUtils;

View file

@ -28,8 +28,8 @@ package org.geysermc.geyser.command.defaults;
import com.github.steveice10.mc.protocol.data.game.ClientCommand;
import com.github.steveice10.mc.protocol.packet.ingame.serverbound.ServerboundClientCommandPacket;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.command.GeyserCommandSource;
import org.geysermc.geyser.command.GeyserCommand;
import org.geysermc.geyser.command.GeyserCommandSource;
import org.geysermc.geyser.session.GeyserSession;
public class StatisticsCommand extends GeyserCommand {

View file

@ -27,8 +27,8 @@ package org.geysermc.geyser.command.defaults;
import org.geysermc.common.PlatformType;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.command.GeyserCommandSource;
import org.geysermc.geyser.command.GeyserCommand;
import org.geysermc.geyser.command.GeyserCommandSource;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.text.GeyserLocale;
@ -54,4 +54,9 @@ public class StopCommand extends GeyserCommand {
geyser.getBootstrap().onDisable();
}
@Override
public boolean isSuggestedOpOnly() {
return true;
}
}

View file

@ -28,8 +28,8 @@ package org.geysermc.geyser.command.defaults;
import com.nukkitx.protocol.bedrock.BedrockPacketCodec;
import org.geysermc.common.PlatformType;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.command.GeyserCommandSource;
import org.geysermc.geyser.command.GeyserCommand;
import org.geysermc.geyser.command.GeyserCommandSource;
import org.geysermc.geyser.network.GameProtocol;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.text.ChatColor;
@ -95,4 +95,9 @@ public class VersionCommand extends GeyserCommand {
}
}
}
@Override
public boolean isSuggestedOpOnly() {
return true;
}
}

View file

@ -101,6 +101,10 @@ public interface GeyserConfiguration {
boolean isAllowCustomSkulls();
int getMaxVisibleCustomSkulls();
int getCustomSkullRenderDistance();
IMetricsInfo getMetrics();
int getPendingAuthenticationTimeout();

View file

@ -130,6 +130,12 @@ public abstract class GeyserJacksonConfiguration implements GeyserConfiguration
@JsonProperty("allow-custom-skulls")
private boolean allowCustomSkulls = true;
@JsonProperty("max-visible-custom-skulls")
private int maxVisibleCustomSkulls = 128;
@JsonProperty("custom-skull-render-distance")
private int customSkullRenderDistance = 32;
@JsonProperty("add-non-bedrock-items")
private boolean addNonBedrockItems = true;

View file

@ -35,17 +35,18 @@ import it.unimi.dsi.fastutil.objects.Object2IntMap;
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.geysermc.floodgate.util.DeviceOs;
import org.geysermc.floodgate.util.FloodgateInfoHolder;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.api.GeyserApi;
import org.geysermc.geyser.api.extension.Extension;
import org.geysermc.geyser.text.AsteriskSerializer;
import org.geysermc.geyser.configuration.GeyserConfiguration;
import org.geysermc.geyser.network.GameProtocol;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.text.AsteriskSerializer;
import org.geysermc.geyser.util.CpuUtils;
import org.geysermc.geyser.util.FileUtils;
import org.geysermc.geyser.util.WebUtils;
import org.geysermc.floodgate.util.DeviceOs;
import org.geysermc.floodgate.util.FloodgateInfoHolder;
import java.io.File;
import java.io.IOException;
@ -66,6 +67,7 @@ public class DumpInfo {
private final DumpInfo.VersionInfo versionInfo;
private final int cpuCount;
private final String cpuName;
private final Locale systemLocale;
private final String systemEncoding;
private Properties gitInfo;
@ -83,6 +85,7 @@ public class DumpInfo {
this.versionInfo = new VersionInfo();
this.cpuCount = Runtime.getRuntime().availableProcessors();
this.cpuName = CpuUtils.tryGetProcessorName();
this.systemLocale = Locale.getDefault();
this.systemEncoding = System.getProperty("file.encoding");

View file

@ -51,6 +51,7 @@ import org.geysermc.geyser.registry.Registries;
import org.geysermc.geyser.translator.text.MessageTranslator;
public final class EntityDefinitions {
public static final EntityDefinition<AllayEntity> ALLAY;
public static final EntityDefinition<AreaEffectCloudEntity> AREA_EFFECT_CLOUD;
public static final EntityDefinition<ArmorStandEntity> ARMOR_STAND;
public static final EntityDefinition<TippedArrowEntity> ARROW;
@ -63,6 +64,7 @@ public final class EntityDefinitions {
public static final EntityDefinition<SpiderEntity> CAVE_SPIDER;
public static final EntityDefinition<MinecartEntity> CHEST_MINECART;
public static final EntityDefinition<ChickenEntity> CHICKEN;
public static final EntityDefinition<ChestBoatEntity> CHEST_BOAT;
public static final EntityDefinition<AbstractFishEntity> COD;
public static final EntityDefinition<CommandBlockMinecartEntity> COMMAND_BLOCK_MINECART;
public static final EntityDefinition<CowEntity> COW;
@ -88,6 +90,7 @@ public final class EntityDefinitions {
public static final EntityDefinition<FireworkEntity> FIREWORK_ROCKET;
public static final EntityDefinition<FishingHookEntity> FISHING_BOBBER;
public static final EntityDefinition<FoxEntity> FOX;
public static final EntityDefinition<FrogEntity> FROG;
public static final EntityDefinition<FurnaceMinecartEntity> FURNACE_MINECART; // Not present on Bedrock
public static final EntityDefinition<GhastEntity> GHAST;
public static final EntityDefinition<GiantEntity> GIANT;
@ -143,6 +146,7 @@ public final class EntityDefinitions {
public static final EntityDefinition<SquidEntity> SQUID;
public static final EntityDefinition<AbstractSkeletonEntity> STRAY;
public static final EntityDefinition<StriderEntity> STRIDER;
public static final EntityDefinition<TadpoleEntity> TADPOLE;
public static final EntityDefinition<TNTEntity> TNT;
public static final EntityDefinition<MinecartEntity> TNT_MINECART;
public static final EntityDefinition<TraderLlamaEntity> TRADER_LLAMA;
@ -153,6 +157,7 @@ public final class EntityDefinitions {
public static final EntityDefinition<VillagerEntity> VILLAGER;
public static final EntityDefinition<VindicatorEntity> VINDICATOR;
public static final EntityDefinition<AbstractMerchantEntity> WANDERING_TRADER;
public static final EntityDefinition<WardenEntity> WARDEN;
public static final EntityDefinition<RaidParticipantEntity> WITCH;
public static final EntityDefinition<WitherEntity> WITHER;
public static final EntityDefinition<AbstractSkeletonEntity> WITHER_SKELETON;
@ -179,7 +184,7 @@ public final class EntityDefinitions {
.addTranslator(MetadataType.INT, Entity::setAir) // Air/bubbles
.addTranslator(MetadataType.OPTIONAL_CHAT, Entity::setDisplayName)
.addTranslator(MetadataType.BOOLEAN, Entity::setDisplayNameVisible)
.addTranslator(MetadataType.BOOLEAN, (entity, entityMetadata) -> entity.setFlag(EntityFlag.SILENT, ((BooleanEntityMetadata) entityMetadata).getPrimitiveValue()))
.addTranslator(MetadataType.BOOLEAN, Entity::setSilent)
.addTranslator(MetadataType.BOOLEAN, Entity::setGravity)
.addTranslator(MetadataType.POSE, (entity, entityMetadata) -> entity.setPose(entityMetadata.getValue()))
.addTranslator(MetadataType.INT, Entity::setFreezing)
@ -209,6 +214,9 @@ public final class EntityDefinitions {
.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();
CHEST_BOAT = EntityDefinition.inherited(ChestBoatEntity::new, BOAT)
.type(EntityType.CHEST_BOAT)
.build();
DRAGON_FIREBALL = EntityDefinition.inherited(FireballEntity::new, entityBase)
.type(EntityType.DRAGON_FIREBALL)
.heightAndWidth(1.0f)
@ -274,6 +282,7 @@ public final class EntityDefinitions {
.build();
PAINTING = EntityDefinition.<PaintingEntity>inherited(null, entityBase)
.type(EntityType.PAINTING)
.addTranslator(MetadataType.PAINTING_VARIANT, PaintingEntity::setPaintingType)
.build();
SHULKER_BULLET = EntityDefinition.inherited(ThrowableEntity::new, entityBase)
.type(EntityType.SHULKER_BULLET)
@ -441,6 +450,10 @@ public final class EntityDefinitions {
// Extends mob
{
ALLAY = EntityDefinition.inherited(AllayEntity::new, mobEntityBase)
.type(EntityType.ALLAY)
.height(0.6f).width(0.35f)
.build();
BAT = EntityDefinition.inherited(BatEntity::new, mobEntityBase)
.type(EntityType.BAT)
.height(0.9f).width(0.5f)
@ -550,6 +563,11 @@ public final class EntityDefinitions {
.height(0.8f).width(0.4f)
.addTranslator(MetadataType.BYTE, VexEntity::setVexFlags)
.build();
WARDEN = EntityDefinition.inherited(WardenEntity::new, mobEntityBase)
.type(EntityType.WARDEN)
.height(2.9f).width(0.9f)
.addTranslator(MetadataType.INT, WardenEntity::setAngerLevel)
.build();
WITHER = EntityDefinition.inherited(WitherEntity::new, mobEntityBase)
.type(EntityType.WITHER)
.height(3.5f).width(0.9f)
@ -634,6 +652,10 @@ public final class EntityDefinitions {
.type(EntityType.SALMON)
.height(0.5f).width(0.7f)
.build();
TADPOLE = EntityDefinition.inherited(TadpoleEntity::new, abstractFishEntityBase)
.type(EntityType.TADPOLE)
.height(0.3f).width(0.4f)
.build();
TROPICAL_FISH = EntityDefinition.inherited(TropicalFishEntity::new, abstractFishEntityBase)
.type(EntityType.TROPICAL_FISH)
.heightAndWidth(0.6f)
@ -735,6 +757,12 @@ public final class EntityDefinitions {
.addTranslator(null) // Trusted player 1
.addTranslator(null) // Trusted player 2
.build();
FROG = EntityDefinition.inherited(FrogEntity::new, ageableEntityBase)
.type(EntityType.FROG)
.heightAndWidth(0.5f)
.addTranslator(MetadataType.FROG_VARIANT, FrogEntity::setFrogVariant)
.addTranslator(MetadataType.OPTIONAL_VARINT, FrogEntity::setTongueTarget)
.build();
HOGLIN = EntityDefinition.inherited(HoglinEntity::new, ageableEntityBase)
.type(EntityType.HOGLIN)
.height(1.4f).width(1.3965f)
@ -744,6 +772,8 @@ public final class EntityDefinitions {
.type(EntityType.GOAT)
.height(1.3f).width(0.9f)
.addTranslator(MetadataType.BOOLEAN, GoatEntity::setScreamer)
.addTranslator(MetadataType.BOOLEAN, GoatEntity::setHasLeftHorn)
.addTranslator(MetadataType.BOOLEAN, GoatEntity::setHasRightHorn)
.build();
MOOSHROOM = EntityDefinition.inherited(MooshroomEntity::new, ageableEntityBase)
.type(EntityType.MOOSHROOM)
@ -871,7 +901,7 @@ public final class EntityDefinitions {
CAT = EntityDefinition.inherited(CatEntity::new, tameableEntityBase)
.type(EntityType.CAT)
.height(0.35f).width(0.3f)
.addTranslator(MetadataType.INT, CatEntity::setCatVariant)
.addTranslator(MetadataType.CAT_VARIANT, CatEntity::setCatVariant)
.addTranslator(MetadataType.BOOLEAN, CatEntity::setResting)
.addTranslator(null) // "resting state one" //TODO
.addTranslator(MetadataType.INT, CatEntity::setCollarColor)

View file

@ -52,4 +52,9 @@ public final class GeyserDirtyMetadata {
public boolean hasEntries() {
return !metadata.isEmpty();
}
@Override
public String toString() {
return metadata.toString();
}
}

View file

@ -32,8 +32,8 @@ import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.registry.Registries;
import org.geysermc.geyser.session.GeyserSession;
import java.util.UUID;

View file

@ -0,0 +1,51 @@
/*
* Copyright (c) 2019-2022 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.geyser.entity.type;
import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
import com.nukkitx.math.vector.Vector3f;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.util.InteractionResult;
import org.geysermc.geyser.util.InteractiveTag;
import java.util.UUID;
public class ChestBoatEntity extends BoatEntity {
public ChestBoatEntity(GeyserSession session, int 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 InteractiveTag testInteraction(Hand hand) {
return passengers.isEmpty() && !session.isSneaking() ? super.testInteraction(hand) : InteractiveTag.OPEN_CONTAINER;
}
@Override
public InteractionResult interact(Hand hand) {
return passengers.isEmpty() && !session.isSneaking() ? super.interact(hand) : InteractionResult.SUCCESS;
}
}

View file

@ -26,7 +26,6 @@
package org.geysermc.geyser.entity.type;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position;
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.math.vector.Vector3i;
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
@ -50,13 +49,12 @@ public class EnderCrystalEntity extends Entity {
setFlag(EntityFlag.FIRE_IMMUNE, true);
}
public void setBlockTarget(EntityMetadata<Optional<Position>, ?> entityMetadata) {
public void setBlockTarget(EntityMetadata<Optional<Vector3i>, ?> entityMetadata) {
// Show beam
// Usually performed client-side on Bedrock except for Ender Dragon respawn event
Optional<Position> optionalPos = entityMetadata.getValue();
Optional<Vector3i> optionalPos = entityMetadata.getValue();
if (optionalPos.isPresent()) {
Position pos = optionalPos.get();
dirtyMetadata.put(EntityData.BLOCK_TARGET, Vector3i.from(pos.getX(), pos.getY(), pos.getZ()));
dirtyMetadata.put(EntityData.BLOCK_TARGET, optionalPos.get());
} else {
dirtyMetadata.put(EntityData.BLOCK_TARGET, Vector3i.ZERO);
}

View file

@ -94,6 +94,8 @@ public class Entity {
private float boundingBoxWidth;
@Setter(AccessLevel.NONE)
protected String nametag = "";
@Setter(AccessLevel.NONE)
protected boolean silent = false;
/* Metadata end */
protected List<Entity> passengers = Collections.emptyList();
@ -141,13 +143,19 @@ public class Entity {
*/
protected void initializeMetadata() {
dirtyMetadata.put(EntityData.SCALE, 1f);
dirtyMetadata.put(EntityData.COLOR, 0);
dirtyMetadata.put(EntityData.COLOR, (byte) 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);
// Let the Java server (or us) supply all sounds for an entity
setClientSideSilent();
}
protected void setClientSideSilent() {
setFlag(EntityFlag.SILENT, true);
}
public void spawnEntity() {
@ -351,7 +359,7 @@ public class Entity {
dirtyMetadata.put(EntityData.AIR_SUPPLY, (short) MathUtils.constrain(amount, 0, getMaxAir()));
}
protected int getMaxAir() {
protected short getMaxAir() {
return 300;
}
@ -370,6 +378,10 @@ public class Entity {
dirtyMetadata.put(EntityData.NAMETAG_ALWAYS_SHOW, (byte) (entityMetadata.getPrimitiveValue() ? 1 : 0));
}
public final void setSilent(BooleanEntityMetadata entityMetadata) {
silent = entityMetadata.getPrimitiveValue();
}
public void setGravity(BooleanEntityMetadata entityMetadata) {
setFlag(EntityFlag.HAS_GRAVITY, !entityMetadata.getPrimitiveValue());
}

View file

@ -27,7 +27,6 @@ package org.geysermc.geyser.entity.type;
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
import com.nukkitx.protocol.bedrock.packet.PlaySoundPacket;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.session.GeyserSession;
@ -58,7 +57,7 @@ public class EvokerFangsEntity extends Entity implements Tickable {
public void setAttackStarted() {
this.attackStarted = true;
if (!getFlag(EntityFlag.SILENT)) {
if (!silent) {
// Play the chomp sound
PlaySoundPacket packet = new PlaySoundPacket();
packet.setPosition(this.position);

View file

@ -36,8 +36,8 @@ import java.util.UUID;
public class FallingBlockEntity extends Entity {
public FallingBlockEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, Vector3f position, Vector3f motion, float yaw, float pitch, int javaId) {
super(session, entityId, geyserId, uuid, EntityDefinitions.FALLING_BLOCK, position, motion, yaw, pitch, 0f);
public FallingBlockEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw, int javaId) {
super(session, entityId, geyserId, uuid, EntityDefinitions.FALLING_BLOCK, position, motion, yaw, pitch, headYaw);
this.dirtyMetadata.put(EntityData.VARIANT, session.getBlockMappings().getBedrockBlockId(javaId));
}

View file

@ -36,12 +36,12 @@ import com.nukkitx.nbt.NbtMapBuilder;
import com.nukkitx.nbt.NbtType;
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
import com.nukkitx.protocol.bedrock.packet.SetEntityMotionPacket;
import org.geysermc.floodgate.util.DeviceOs;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.entity.type.player.PlayerEntity;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.level.FireworkColor;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.util.MathUtils;
import org.geysermc.floodgate.util.DeviceOs;
import java.util.ArrayList;
import java.util.List;

View file

@ -28,17 +28,16 @@ package org.geysermc.geyser.entity.type;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata;
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
import com.nukkitx.protocol.bedrock.packet.PlaySoundPacket;
import lombok.Getter;
import org.geysermc.geyser.entity.EntityDefinitions;
import org.geysermc.geyser.entity.type.player.PlayerEntity;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.level.physics.BoundingBox;
import org.geysermc.geyser.translator.collision.BlockCollision;
import org.geysermc.geyser.level.block.BlockStateValues;
import org.geysermc.geyser.registry.BlockRegistries;
import org.geysermc.geyser.level.block.BlockPositionIterator;
import org.geysermc.geyser.level.block.BlockStateValues;
import org.geysermc.geyser.level.physics.BoundingBox;
import org.geysermc.geyser.registry.BlockRegistries;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.collision.BlockCollision;
import org.geysermc.geyser.util.BlockUtils;
import java.util.UUID;
@ -56,7 +55,7 @@ public class FishingHookEntity extends ThrowableEntity {
private final BoundingBox boundingBox;
public FishingHookEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, Vector3f position, Vector3f motion, float yaw, float pitch, PlayerEntity owner) {
public FishingHookEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw, PlayerEntity owner) {
super(session, entityId, geyserId, uuid, EntityDefinitions.FISHING_BOBBER, position, motion, yaw, pitch, 0f);
this.boundingBox = new BoundingBox(0.125, 0.125, 0.125, 0.25, 0.25, 0.25);
@ -129,7 +128,7 @@ public class FishingHookEntity extends ThrowableEntity {
}
private void sendSplashSound(GeyserSession session) {
if (!getFlag(EntityFlag.SILENT)) {
if (!silent) {
float volume = (float) (0.2f * Math.sqrt(0.2 * (motion.getX() * motion.getX() + motion.getZ() * motion.getZ()) + motion.getY() * motion.getY()));
if (volume > 1) {
volume = 1;

View file

@ -30,8 +30,8 @@ import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.level.block.BlockStateValues;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.util.InteractionResult;
import java.util.UUID;

View file

@ -35,9 +35,9 @@ import com.nukkitx.protocol.bedrock.data.inventory.ItemData;
import com.nukkitx.protocol.bedrock.packet.AddItemEntityPacket;
import com.nukkitx.protocol.bedrock.packet.EntityEventPacket;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.level.block.BlockStateValues;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.inventory.item.ItemTranslator;
import org.geysermc.geyser.level.block.BlockStateValues;
import java.util.UUID;

View file

@ -79,8 +79,8 @@ public class ItemFrameEntity extends Entity {
*/
private boolean changed = true;
public ItemFrameEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, Direction direction) {
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, 0f);
public ItemFrameEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw, Direction direction) {
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
NbtMapBuilder blockBuilder = NbtMap.builder()
.putString("name", this.definition.entityType() == EntityType.GLOW_ITEM_FRAME ? "minecraft:glow_frame" : "minecraft:frame")

View file

@ -29,7 +29,6 @@ import com.github.steveice10.mc.protocol.data.game.entity.attribute.Attribute;
import com.github.steveice10.mc.protocol.data.game.entity.attribute.AttributeType;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.Pose;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.FloatEntityMetadata;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata;
@ -52,17 +51,13 @@ import lombok.Setter;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.entity.attribute.GeyserAttributeType;
import org.geysermc.geyser.inventory.GeyserItemStack;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.util.AttributeUtils;
import org.geysermc.geyser.util.ChunkUtils;
import org.geysermc.geyser.util.InteractionResult;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
import java.util.*;
@Getter
@Setter
@ -123,12 +118,11 @@ public class LivingEntity extends Entity {
session.sendUpstreamPacket(attributesPacket);
}
public Vector3i setBedPosition(EntityMetadata<Optional<Position>, ?> entityMetadata) {
Optional<Position> optionalPos = entityMetadata.getValue();
public Vector3i setBedPosition(EntityMetadata<Optional<Vector3i>, ?> entityMetadata) {
Optional<Vector3i> optionalPos = entityMetadata.getValue();
if (optionalPos.isPresent()) {
Position bedPosition = optionalPos.get();
Vector3i vector = Vector3i.from(bedPosition.getX(), bedPosition.getY(), bedPosition.getZ());
dirtyMetadata.put(EntityData.BED_POSITION, vector);
Vector3i bedPosition = optionalPos.get();
dirtyMetadata.put(EntityData.BED_POSITION, bedPosition);
int bed = session.getGeyser().getWorldManager().getBlockAt(session, bedPosition);
// Bed has to be updated, or else player is floating in the air
ChunkUtils.updateBlock(session, bed, bedPosition);
@ -136,7 +130,7 @@ public class LivingEntity extends Entity {
// Has to be a byte or it does not work
// (Bed position is what actually triggers sleep - "pose" is only optional)
dirtyMetadata.put(EntityData.PLAYER_FLAGS, (byte) 2);
return vector;
return bedPosition;
} else {
// Player is no longer sleeping
dirtyMetadata.put(EntityData.PLAYER_FLAGS, (byte) 0);
@ -300,7 +294,9 @@ public class LivingEntity extends Entity {
if (javaAttribute.getType() instanceof AttributeType.Builtin type) {
switch (type) {
case GENERIC_MAX_HEALTH -> {
this.maxHealth = (float) AttributeUtils.calculateValue(javaAttribute);
// Since 1.18.0, setting the max health to 0 or below causes the entity to die on Bedrock but not on Java
// See https://github.com/GeyserMC/Geyser/issues/2971
this.maxHealth = Math.max((float) AttributeUtils.calculateValue(javaAttribute), 1f);
newAttributes.add(createHealthAttribute());
}
case GENERIC_ATTACK_DAMAGE -> newAttributes.add(calculateAttribute(javaAttribute, GeyserAttributeType.ATTACK_DAMAGE));

View file

@ -25,33 +25,45 @@
package org.geysermc.geyser.entity.type;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ObjectEntityMetadata;
import com.github.steveice10.mc.protocol.data.game.entity.object.Direction;
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.packet.AddPaintingPacket;
import org.geysermc.geyser.entity.EntityDefinitions;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.level.PaintingType;
import org.geysermc.geyser.session.GeyserSession;
import java.util.UUID;
public class PaintingEntity extends Entity {
private static final double OFFSET = -0.46875;
private final PaintingType paintingName;
private final int direction;
private final Direction direction;
public PaintingEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, Vector3f position, PaintingType paintingName, int direction) {
super(session, entityId, geyserId, uuid, EntityDefinitions.PAINTING, position, Vector3f.ZERO, 0f, 0f, 0f);
this.paintingName = paintingName;
public PaintingEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw, Direction direction) {
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
this.direction = direction;
}
@Override
public void spawnEntity() {
// Wait until we get the metadata needed
}
public void setPaintingType(ObjectEntityMetadata<com.github.steveice10.mc.protocol.data.game.entity.type.PaintingType> entityMetadata) {
PaintingType type = PaintingType.getByPaintingType(entityMetadata.getValue());
AddPaintingPacket addPaintingPacket = new AddPaintingPacket();
addPaintingPacket.setUniqueEntityId(geyserId);
addPaintingPacket.setRuntimeEntityId(geyserId);
addPaintingPacket.setMotive(paintingName.getBedrockName());
addPaintingPacket.setPosition(fixOffset());
addPaintingPacket.setDirection(direction);
addPaintingPacket.setMotive(type.getBedrockName());
addPaintingPacket.setPosition(fixOffset(type));
addPaintingPacket.setDirection(switch (direction) {
//TODO this doesn't seem right. Why did it work fine before?
case SOUTH -> 0;
case WEST -> 1;
case NORTH -> 2;
case EAST -> 3;
default -> 0;
});
session.sendUpstreamPacket(addPaintingPacket);
valid = true;
@ -64,17 +76,17 @@ public class PaintingEntity extends Entity {
// Do nothing, as head look messes up paintings
}
private Vector3f fixOffset() {
private Vector3f fixOffset(PaintingType paintingName) {
Vector3f position = super.position;
position = position.add(0.5, 0.5, 0.5);
double widthOffset = paintingName.getWidth() > 1 ? 0.5 : 0;
double heightOffset = paintingName.getHeight() > 1 && paintingName.getHeight() != 3 ? 0.5 : 0;
return switch (direction) {
case 0 -> position.add(widthOffset, heightOffset, OFFSET);
case 1 -> position.add(-OFFSET, heightOffset, widthOffset);
case 2 -> position.add(-widthOffset, heightOffset, -OFFSET);
case 3 -> position.add(OFFSET, heightOffset, -widthOffset);
case SOUTH -> position.add(widthOffset, heightOffset, OFFSET);
case WEST -> position.add(-OFFSET, heightOffset, widthOffset);
case NORTH -> position.add(-widthOffset, heightOffset, -OFFSET);
case EAST -> position.add(OFFSET, heightOffset, -widthOffset);
default -> position;
};
}

View file

@ -28,8 +28,8 @@ package org.geysermc.geyser.entity.type;
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.level.block.BlockStateValues;
import org.geysermc.geyser.session.GeyserSession;
import java.util.UUID;

View file

@ -32,8 +32,8 @@ import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
import com.nukkitx.protocol.bedrock.packet.LevelEventPacket;
import com.nukkitx.protocol.bedrock.packet.MoveEntityDeltaPacket;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.level.block.BlockStateValues;
import org.geysermc.geyser.session.GeyserSession;
import java.util.UUID;

View file

@ -34,9 +34,9 @@ import com.nukkitx.protocol.bedrock.data.entity.EntityData;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.inventory.item.Potion;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.session.GeyserSession;
import java.util.EnumSet;
import java.util.UUID;

View file

@ -29,8 +29,8 @@ import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntit
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.inventory.item.TippedArrowPotion;
import org.geysermc.geyser.session.GeyserSession;
import java.util.UUID;

View file

@ -25,6 +25,7 @@
package org.geysermc.geyser.entity.type.living;
import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
import org.geysermc.geyser.entity.EntityDefinition;
@ -49,11 +50,11 @@ public class AbstractFishEntity extends WaterEntity {
@Nonnull
@Override
protected InteractionResult mobInteract(@Nonnull GeyserItemStack itemInHand) {
protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) {
if (EntityUtils.attemptToBucket(session, itemInHand)) {
return InteractionResult.SUCCESS;
} else {
return super.mobInteract(itemInHand);
return super.mobInteract(hand, itemInHand);
}
}
}

View file

@ -0,0 +1,70 @@
/*
* Copyright (c) 2019-2022 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.geyser.entity.type.living;
import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
import com.nukkitx.math.vector.Vector3f;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.inventory.GeyserItemStack;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.util.InteractionResult;
import org.geysermc.geyser.util.InteractiveTag;
import javax.annotation.Nonnull;
import java.util.UUID;
public class AllayEntity extends MobEntity {
public AllayEntity(GeyserSession session, int 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);
}
@Nonnull
@Override
protected InteractiveTag testMobInteraction(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
if (!this.hand.isValid() && !itemInHand.isEmpty()) {
return InteractiveTag.GIVE_ITEM_TO_ALLAY;
} else if (this.hand.isValid() && hand == Hand.MAIN_HAND && itemInHand.isEmpty()) {
// Seems like there isn't a good tag for this yet
return InteractiveTag.GIVE_ITEM_TO_ALLAY;
} else {
return super.testMobInteraction(hand, itemInHand);
}
}
@Nonnull
@Override
protected InteractionResult mobInteract(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
if (!this.hand.isValid() && !itemInHand.isEmpty()) {
//TODO play sound?
return InteractionResult.SUCCESS;
} else if (this.hand.isValid() && hand == Hand.MAIN_HAND && itemInHand.isEmpty()) {
//TOCHECK also play sound here?
return InteractionResult.SUCCESS;
} else {
return super.mobInteract(hand, itemInHand);
}
}
}

View file

@ -26,9 +26,7 @@
package org.geysermc.geyser.entity.type.living;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
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.github.steveice10.mc.protocol.data.game.entity.player.GameMode;
import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
@ -165,27 +163,27 @@ public class ArmorStandEntity extends LivingEntity {
setFlag(EntityFlag.ADMIRING, (xd & 0x08) == 0x08); // Has no baseplate
}
public void setHeadRotation(EntityMetadata<Rotation, ?> entityMetadata) {
public void setHeadRotation(EntityMetadata<Vector3f, ?> entityMetadata) {
onRotationUpdate(EntityData.MARK_VARIANT, EntityFlag.INTERESTED, EntityFlag.CHARGED, EntityFlag.POWERED, entityMetadata.getValue());
}
public void setBodyRotation(EntityMetadata<Rotation, ?> entityMetadata) {
public void setBodyRotation(EntityMetadata<Vector3f, ?> entityMetadata) {
onRotationUpdate(EntityData.VARIANT, EntityFlag.IN_LOVE, EntityFlag.CELEBRATING, EntityFlag.CELEBRATING_SPECIAL, entityMetadata.getValue());
}
public void setLeftArmRotation(EntityMetadata<Rotation, ?> entityMetadata) {
public void setLeftArmRotation(EntityMetadata<Vector3f, ?> entityMetadata) {
onRotationUpdate(EntityData.TRADE_TIER, EntityFlag.CHARGING, EntityFlag.CRITICAL, EntityFlag.DANCING, entityMetadata.getValue());
}
public void setRightArmRotation(EntityMetadata<Rotation, ?> entityMetadata) {
public void setRightArmRotation(EntityMetadata<Vector3f, ?> entityMetadata) {
onRotationUpdate(EntityData.MAX_TRADE_TIER, EntityFlag.ELDER, EntityFlag.EMOTING, EntityFlag.IDLING, entityMetadata.getValue());
}
public void setLeftLegRotation(EntityMetadata<Rotation, ?> entityMetadata) {
public void setLeftLegRotation(EntityMetadata<Vector3f, ?> entityMetadata) {
onRotationUpdate(EntityData.SKIN_ID, EntityFlag.IS_ILLAGER_CAPTAIN, EntityFlag.IS_IN_UI, EntityFlag.LINGERING, entityMetadata.getValue());
}
public void setRightLegRotation(EntityMetadata<Rotation, ?> entityMetadata) {
public void setRightLegRotation(EntityMetadata<Vector3f, ?> entityMetadata) {
onRotationUpdate(EntityData.HURT_DIRECTION, EntityFlag.IS_PREGNANT, EntityFlag.SHEARED, EntityFlag.STALKING, entityMetadata.getValue());
}
@ -200,13 +198,13 @@ public class ArmorStandEntity extends LivingEntity {
* @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) {
private void onRotationUpdate(EntityData dataLeech, EntityFlag negativeXToggle, EntityFlag negativeYToggle, EntityFlag negativeZToggle, Vector3f rotation) {
// Indicate that rotation should be checked
setFlag(EntityFlag.BRIBED, true);
int rotationX = MathUtils.wrapDegreesToInt(rotation.getPitch());
int rotationY = MathUtils.wrapDegreesToInt(rotation.getYaw());
int rotationZ = MathUtils.wrapDegreesToInt(rotation.getRoll());
int rotationX = MathUtils.wrapDegreesToInt(rotation.getX());
int rotationY = MathUtils.wrapDegreesToInt(rotation.getY());
int rotationZ = MathUtils.wrapDegreesToInt(rotation.getZ());
// 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);

View file

@ -25,6 +25,7 @@
package org.geysermc.geyser.entity.type.living;
import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
import com.nukkitx.math.vector.Vector3f;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.inventory.GeyserItemStack;
@ -47,20 +48,20 @@ public class DolphinEntity extends WaterEntity {
@Nonnull
@Override
protected InteractiveTag testMobInteraction(@Nonnull GeyserItemStack itemInHand) {
protected InteractiveTag testMobInteraction(Hand hand, @Nonnull GeyserItemStack itemInHand) {
if (!itemInHand.isEmpty() && session.getTagCache().isFish(itemInHand)) {
return InteractiveTag.FEED;
}
return super.testMobInteraction(itemInHand);
return super.testMobInteraction(hand, itemInHand);
}
@Nonnull
@Override
protected InteractionResult mobInteract(@Nonnull GeyserItemStack itemInHand) {
protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) {
if (!itemInHand.isEmpty() && session.getTagCache().isFish(itemInHand)) {
// Feed
return InteractionResult.SUCCESS;
}
return super.mobInteract(itemInHand);
return super.mobInteract(hand, itemInHand);
}
}

View file

@ -25,6 +25,7 @@
package org.geysermc.geyser.entity.type.living;
import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
@ -48,7 +49,7 @@ public class IronGolemEntity extends GolemEntity {
@Nonnull
@Override
protected InteractionResult mobInteract(@Nonnull GeyserItemStack itemInHand) {
protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) {
if (itemInHand.getJavaId() == session.getItemMappings().getStoredItems().ironIngot()) {
if (health < maxHealth) {
// Healing the iron golem
@ -57,6 +58,6 @@ public class IronGolemEntity extends GolemEntity {
return InteractionResult.PASS;
}
}
return super.mobInteract(itemInHand);
return super.mobInteract(hand, itemInHand);
}
}

View file

@ -90,7 +90,7 @@ public class MobEntity extends LivingEntity {
}
}
InteractiveTag tag = testMobInteraction(itemStack);
InteractiveTag tag = testMobInteraction(hand, itemStack);
return tag != InteractiveTag.NONE ? tag : super.testInteraction(hand);
}
}
@ -109,7 +109,7 @@ public class MobEntity extends LivingEntity {
if (result.consumesAction()) {
return result;
} else {
InteractionResult mobResult = mobInteract(itemInHand);
InteractionResult mobResult = mobInteract(hand, itemInHand);
return mobResult.consumesAction() ? mobResult : super.interact(hand);
}
}
@ -137,12 +137,12 @@ public class MobEntity extends LivingEntity {
}
@Nonnull
protected InteractiveTag testMobInteraction(@Nonnull GeyserItemStack itemInHand) {
protected InteractiveTag testMobInteraction(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
return InteractiveTag.NONE;
}
@Nonnull
protected InteractionResult mobInteract(@Nonnull GeyserItemStack itemInHand) {
protected InteractionResult mobInteract(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
return InteractionResult.PASS;
}

View file

@ -26,6 +26,7 @@
package org.geysermc.geyser.entity.type.living;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata;
import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
import org.geysermc.geyser.entity.EntityDefinition;
@ -51,7 +52,7 @@ public class SnowGolemEntity extends GolemEntity {
@Nonnull
@Override
protected InteractiveTag testMobInteraction(@Nonnull GeyserItemStack itemInHand) {
protected InteractiveTag testMobInteraction(Hand hand, @Nonnull GeyserItemStack itemInHand) {
if (session.getItemMappings().getStoredItems().shears() == itemInHand.getJavaId() && isAlive() && !getFlag(EntityFlag.SHEARED)) {
// Shearing the snow golem
return InteractiveTag.SHEAR;
@ -61,7 +62,7 @@ public class SnowGolemEntity extends GolemEntity {
@Nonnull
@Override
protected InteractionResult mobInteract(@Nonnull GeyserItemStack itemInHand) {
protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) {
if (session.getItemMappings().getStoredItems().shears() == itemInHand.getJavaId() && isAlive() && !getFlag(EntityFlag.SHEARED)) {
// Shearing the snow golem
return InteractionResult.SUCCESS;

View file

@ -30,8 +30,8 @@ import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
import com.nukkitx.protocol.bedrock.packet.MoveEntityDeltaPacket;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.entity.type.Tickable;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.level.block.BlockStateValues;
import org.geysermc.geyser.session.GeyserSession;
import java.util.UUID;

View file

@ -0,0 +1,66 @@
/*
* Copyright (c) 2019-2022 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.geyser.entity.type.living;
import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
import com.nukkitx.math.vector.Vector3f;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.inventory.GeyserItemStack;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.util.InteractionResult;
import org.geysermc.geyser.util.InteractiveTag;
import javax.annotation.Nonnull;
import java.util.UUID;
public class TadpoleEntity extends AbstractFishEntity {
public TadpoleEntity(GeyserSession session, int 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);
}
@Nonnull
@Override
protected InteractiveTag testMobInteraction(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
if (isFood(itemInHand)) {
return InteractiveTag.FEED;
}
return super.testMobInteraction(hand, itemInHand);
}
@Nonnull
@Override
protected InteractionResult mobInteract(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
if (isFood(itemInHand)) {
//TODO particles
return InteractionResult.SUCCESS;
}
return super.mobInteract(hand, itemInHand);
}
private boolean isFood(GeyserItemStack itemStack) {
return itemStack.getJavaId() == session.getItemMappings().getStoredItems().slimeBall();
}
}

View file

@ -25,14 +25,15 @@
package org.geysermc.geyser.entity.type.living.animal;
import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityEventType;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.entity.type.living.AgeableEntity;
import org.geysermc.geyser.inventory.GeyserItemStack;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.util.InteractionResult;
import org.geysermc.geyser.util.InteractiveTag;
@ -63,16 +64,16 @@ public class AnimalEntity extends AgeableEntity {
@Nonnull
@Override
protected InteractiveTag testMobInteraction(@Nonnull GeyserItemStack itemInHand) {
protected InteractiveTag testMobInteraction(Hand hand, @Nonnull GeyserItemStack itemInHand) {
if (canEat(itemInHand)) {
return InteractiveTag.FEED;
}
return super.testMobInteraction(itemInHand);
return super.testMobInteraction(hand, itemInHand);
}
@Nonnull
@Override
protected InteractionResult mobInteract(@Nonnull GeyserItemStack itemInHand) {
protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) {
if (canEat(itemInHand)) {
// FEED
if (getFlag(EntityFlag.BABY)) {
@ -82,6 +83,6 @@ public class AnimalEntity extends AgeableEntity {
return InteractionResult.CONSUME;
}
}
return super.mobInteract(itemInHand);
return super.mobInteract(hand, itemInHand);
}
}

View file

@ -27,13 +27,14 @@ package org.geysermc.geyser.entity.type.living.animal;
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.github.steveice10.mc.protocol.data.game.entity.player.Hand;
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.inventory.GeyserItemStack;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.util.EntityUtils;
import org.geysermc.geyser.util.InteractionResult;
@ -64,7 +65,7 @@ public class AxolotlEntity extends AnimalEntity {
}
@Override
protected int getMaxAir() {
protected short getMaxAir() {
return 6000;
}
@ -75,11 +76,11 @@ public class AxolotlEntity extends AnimalEntity {
@Nonnull
@Override
protected InteractionResult mobInteract(@Nonnull GeyserItemStack itemInHand) {
protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) {
if (EntityUtils.attemptToBucket(session, itemInHand)) {
return InteractionResult.SUCCESS;
} else {
return super.mobInteract(itemInHand);
return super.mobInteract(hand, itemInHand);
}
}
}

View file

@ -33,8 +33,8 @@ import com.nukkitx.protocol.bedrock.data.entity.EntityEventType;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
import com.nukkitx.protocol.bedrock.packet.EntityEventPacket;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.session.GeyserSession;
import java.util.UUID;

View file

@ -27,8 +27,8 @@ package org.geysermc.geyser.entity.type.living.animal;
import com.nukkitx.math.vector.Vector3f;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.session.GeyserSession;
import java.util.UUID;

View file

@ -25,6 +25,7 @@
package org.geysermc.geyser.entity.type.living.animal;
import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.SoundEvent;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
@ -44,9 +45,9 @@ public class CowEntity extends AnimalEntity {
@Nonnull
@Override
protected InteractiveTag testMobInteraction(@Nonnull GeyserItemStack itemInHand) {
protected InteractiveTag testMobInteraction(Hand hand, @Nonnull GeyserItemStack itemInHand) {
if (getFlag(EntityFlag.BABY) || !itemInHand.getMapping(session).getJavaIdentifier().equals("minecraft:bucket")) {
return super.testMobInteraction(itemInHand);
return super.testMobInteraction(hand, itemInHand);
}
return InteractiveTag.MILK;
@ -54,9 +55,9 @@ public class CowEntity extends AnimalEntity {
@Nonnull
@Override
protected InteractionResult mobInteract(@Nonnull GeyserItemStack itemInHand) {
protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) {
if (getFlag(EntityFlag.BABY) || !itemInHand.getMapping(session).getJavaIdentifier().equals("minecraft:bucket")) {
return super.mobInteract(itemInHand);
return super.mobInteract(hand, itemInHand);
}
session.playSoundEvent(SoundEvent.MILK, position);

View file

@ -31,8 +31,8 @@ import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.session.GeyserSession;
import java.util.UUID;

View file

@ -0,0 +1,81 @@
/*
* Copyright (c) 2019-2022 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.geyser.entity.type.living.animal;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.Pose;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ObjectEntityMetadata;
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.entity.type.Entity;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.session.GeyserSession;
import java.util.OptionalInt;
import java.util.UUID;
public class FrogEntity extends AnimalEntity {
public FrogEntity(GeyserSession session, int 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 setPose(Pose pose) {
setFlag(EntityFlag.JUMP_GOAL_JUMP, pose == Pose.LONG_JUMPING);
setFlag(EntityFlag.CROAKING, pose == Pose.CROAKING);
setFlag(EntityFlag.EAT_MOB, pose == Pose.USING_TONGUE);
super.setPose(pose);
}
public void setFrogVariant(IntEntityMetadata entityMetadata) {
int variant = entityMetadata.getPrimitiveValue();
dirtyMetadata.put(EntityData.VARIANT, switch (variant) {
case 1 -> 2; // White
case 2 -> 1; // Green
default -> variant;
});
}
public void setTongueTarget(ObjectEntityMetadata<OptionalInt> entityMetadata) {
OptionalInt entityId = entityMetadata.getValue();
if (entityId.isPresent()) {
Entity entity = session.getEntityCache().getEntityByJavaId(entityId.getAsInt());
if (entity != null) {
dirtyMetadata.put(EntityData.TARGET_EID, entity.getGeyserId());
}
} else {
dirtyMetadata.put(EntityData.TARGET_EID, 0L);
}
}
@Override
public boolean canEat(String javaIdentifierStripped, ItemMapping mapping) {
return mapping.getJavaId() == session.getItemMappings().getStoredItems().slimeBall();
}
}

View file

@ -27,8 +27,10 @@ package org.geysermc.geyser.entity.type.living.animal;
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.player.Hand;
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.SoundEvent;
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.inventory.GeyserItemStack;
@ -43,6 +45,8 @@ public class GoatEntity extends AnimalEntity {
private static final float LONG_JUMPING_WIDTH = 0.9f * 0.7f;
private boolean isScreamer;
private boolean hasLeftHorn;
private boolean hasRightHorn;
public GoatEntity(GeyserSession session, int 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);
@ -65,12 +69,26 @@ public class GoatEntity extends AnimalEntity {
@Nonnull
@Override
protected InteractionResult mobInteract(@Nonnull GeyserItemStack itemInHand) {
protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) {
if (!getFlag(EntityFlag.BABY) && itemInHand.getMapping(session).getJavaIdentifier().equals("minecraft:bucket")) {
session.playSoundEvent(isScreamer ? SoundEvent.MILK_SCREAMER : SoundEvent.MILK, position);
return InteractionResult.SUCCESS;
} else {
return super.mobInteract(itemInHand);
return super.mobInteract(hand, itemInHand);
}
}
public void setHasLeftHorn(BooleanEntityMetadata entityMetadata) {
hasLeftHorn = entityMetadata.getPrimitiveValue();
setHornCount();
}
public void setHasRightHorn(BooleanEntityMetadata entityMetadata) {
hasRightHorn = entityMetadata.getPrimitiveValue();
setHornCount();
}
private void setHornCount() {
dirtyMetadata.put(EntityData.GOAT_HORN_COUNT, (hasLeftHorn ? 1 : 0) + (hasRightHorn ? 1 : 0));
}
}

View file

@ -49,7 +49,7 @@ public class HoglinEntity extends AnimalEntity {
@Override
protected boolean isShaking() {
return (!isImmuneToZombification && !session.isDimensionPiglinSafe()) || super.isShaking();
return (!isImmuneToZombification && !session.getDimensionType().piglinSafe()) || super.isShaking();
}
@Override

View file

@ -26,6 +26,7 @@
package org.geysermc.geyser.entity.type.living.animal;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ObjectEntityMetadata;
import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
import org.geysermc.geyser.entity.EntityDefinition;
@ -52,7 +53,7 @@ public class MooshroomEntity extends AnimalEntity {
@Nonnull
@Override
protected InteractiveTag testMobInteraction(@Nonnull GeyserItemStack itemInHand) {
protected InteractiveTag testMobInteraction(Hand hand, @Nonnull GeyserItemStack itemInHand) {
StoredItemMappings storedItems = session.getItemMappings().getStoredItems();
if (!isBaby()) {
if (itemInHand.getJavaId() == storedItems.bowl()) {
@ -63,12 +64,12 @@ public class MooshroomEntity extends AnimalEntity {
return InteractiveTag.MOOSHROOM_SHEAR;
}
}
return super.testMobInteraction(itemInHand);
return super.testMobInteraction(hand, itemInHand);
}
@Nonnull
@Override
protected InteractionResult mobInteract(@Nonnull GeyserItemStack itemInHand) {
protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) {
StoredItemMappings storedItems = session.getItemMappings().getStoredItems();
boolean isBaby = isBaby();
if (!isBaby && itemInHand.getJavaId() == storedItems.bowl()) {
@ -81,6 +82,6 @@ public class MooshroomEntity extends AnimalEntity {
// ?
return InteractionResult.SUCCESS;
}
return super.mobInteract(itemInHand);
return super.mobInteract(hand, itemInHand);
}
}

View file

@ -25,12 +25,13 @@
package org.geysermc.geyser.entity.type.living.animal;
import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.inventory.GeyserItemStack;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.util.InteractionResult;
import org.geysermc.geyser.util.InteractiveTag;
@ -50,23 +51,23 @@ public class OcelotEntity extends AnimalEntity {
@Nonnull
@Override
protected InteractiveTag testMobInteraction(@Nonnull GeyserItemStack itemInHand) {
protected InteractiveTag testMobInteraction(Hand hand, @Nonnull GeyserItemStack itemInHand) {
if (!getFlag(EntityFlag.TRUSTING) && canEat(itemInHand) && session.getPlayerEntity().getPosition().distanceSquared(position) < 9f) {
// Attempt to feed
return InteractiveTag.FEED;
} else {
return super.testMobInteraction(itemInHand);
return super.testMobInteraction(hand, itemInHand);
}
}
@Nonnull
@Override
protected InteractionResult mobInteract(@Nonnull GeyserItemStack itemInHand) {
protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) {
if (!getFlag(EntityFlag.TRUSTING) && canEat(itemInHand) && session.getPlayerEntity().getPosition().distanceSquared(position) < 9f) {
// Attempt to feed
return InteractionResult.SUCCESS;
} else {
return super.mobInteract(itemInHand);
return super.mobInteract(hand, itemInHand);
}
}
}

View file

@ -27,6 +27,7 @@ package org.geysermc.geyser.entity.type.living.animal;
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.github.steveice10.mc.protocol.data.game.entity.player.Hand;
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
import com.nukkitx.protocol.bedrock.data.entity.EntityEventType;
@ -34,8 +35,8 @@ import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
import com.nukkitx.protocol.bedrock.packet.EntityEventPacket;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.inventory.GeyserItemStack;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.util.InteractionResult;
import org.geysermc.geyser.util.InteractiveTag;
@ -93,16 +94,16 @@ public class PandaEntity extends AnimalEntity {
@Nonnull
@Override
protected InteractiveTag testMobInteraction(@Nonnull GeyserItemStack itemInHand) {
protected InteractiveTag testMobInteraction(Hand hand, @Nonnull GeyserItemStack itemInHand) {
if (mainGene == Gene.WORRIED && session.isThunder()) {
return InteractiveTag.NONE;
}
return super.testMobInteraction(itemInHand);
return super.testMobInteraction(hand, itemInHand);
}
@Nonnull
@Override
protected InteractionResult mobInteract(@Nonnull GeyserItemStack itemInHand) {
protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) {
if (mainGene == Gene.WORRIED && session.isThunder()) {
// Huh!
return InteractionResult.PASS;

View file

@ -25,12 +25,13 @@
package org.geysermc.geyser.entity.type.living.animal;
import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.inventory.GeyserItemStack;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.util.EntityUtils;
import org.geysermc.geyser.util.InteractionResult;
import org.geysermc.geyser.util.InteractiveTag;
@ -51,12 +52,12 @@ public class PigEntity extends AnimalEntity {
@Nonnull
@Override
protected InteractiveTag testMobInteraction(@Nonnull GeyserItemStack itemInHand) {
protected InteractiveTag testMobInteraction(Hand hand, @Nonnull GeyserItemStack itemInHand) {
if (!canEat(itemInHand) && getFlag(EntityFlag.SADDLED) && passengers.isEmpty() && !session.isSneaking()) {
// Mount
return InteractiveTag.MOUNT;
} else {
InteractiveTag superTag = super.testMobInteraction(itemInHand);
InteractiveTag superTag = super.testMobInteraction(hand, itemInHand);
if (superTag != InteractiveTag.NONE) {
return superTag;
} else {
@ -68,12 +69,12 @@ public class PigEntity extends AnimalEntity {
@Nonnull
@Override
protected InteractionResult mobInteract(@Nonnull GeyserItemStack itemInHand) {
protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) {
if (!canEat(itemInHand) && getFlag(EntityFlag.SADDLED) && passengers.isEmpty() && !session.isSneaking()) {
// Mount
return InteractionResult.SUCCESS;
} else {
InteractionResult superResult = super.mobInteract(itemInHand);
InteractionResult superResult = super.mobInteract(hand, itemInHand);
if (superResult.consumesAction()) {
return superResult;
} else {

View file

@ -27,8 +27,8 @@ package org.geysermc.geyser.entity.type.living.animal;
import com.nukkitx.math.vector.Vector3f;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.session.GeyserSession;
import java.util.UUID;

View file

@ -31,8 +31,8 @@ import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.session.GeyserSession;
import java.util.UUID;

View file

@ -26,6 +26,7 @@
package org.geysermc.geyser.entity.type.living.animal;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata;
import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
@ -55,11 +56,11 @@ public class SheepEntity extends AnimalEntity {
@Nonnull
@Override
protected InteractiveTag testMobInteraction(@Nonnull GeyserItemStack itemInHand) {
protected InteractiveTag testMobInteraction(Hand hand, @Nonnull GeyserItemStack itemInHand) {
if (itemInHand.getJavaId() == session.getItemMappings().getStoredItems().shears()) {
return InteractiveTag.SHEAR;
} else {
InteractiveTag tag = super.testMobInteraction(itemInHand);
InteractiveTag tag = super.testMobInteraction(hand, itemInHand);
if (tag != InteractiveTag.NONE) {
return tag;
} else {
@ -74,11 +75,11 @@ public class SheepEntity extends AnimalEntity {
@Nonnull
@Override
protected InteractionResult mobInteract(@Nonnull GeyserItemStack itemInHand) {
protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) {
if (itemInHand.getJavaId() == session.getItemMappings().getStoredItems().shears()) {
return InteractionResult.CONSUME;
} else {
InteractionResult superResult = super.mobInteract(itemInHand);
InteractionResult superResult = super.mobInteract(hand, itemInHand);
if (superResult.consumesAction()) {
return superResult;
} else {

View file

@ -26,13 +26,14 @@
package org.geysermc.geyser.entity.type.living.animal;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanEntityMetadata;
import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
import org.geysermc.geyser.entity.type.Entity;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.entity.type.Entity;
import org.geysermc.geyser.inventory.GeyserItemStack;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.util.EntityUtils;
import org.geysermc.geyser.util.InteractionResult;
import org.geysermc.geyser.util.InteractiveTag;
@ -98,12 +99,12 @@ public class StriderEntity extends AnimalEntity {
@Nonnull
@Override
protected InteractiveTag testMobInteraction(@Nonnull GeyserItemStack itemInHand) {
protected InteractiveTag testMobInteraction(Hand hand, @Nonnull GeyserItemStack itemInHand) {
if (!canEat(itemInHand) && getFlag(EntityFlag.SADDLED) && passengers.isEmpty() && !session.isSneaking()) {
// Mount Strider
return InteractiveTag.RIDE_STRIDER;
} else {
InteractiveTag tag = super.testMobInteraction(itemInHand);
InteractiveTag tag = super.testMobInteraction(hand, itemInHand);
if (tag != InteractiveTag.NONE) {
return tag;
} else {
@ -115,12 +116,12 @@ public class StriderEntity extends AnimalEntity {
@Nonnull
@Override
protected InteractionResult mobInteract(@Nonnull GeyserItemStack itemInHand) {
protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) {
if (!canEat(itemInHand) && getFlag(EntityFlag.SADDLED) && passengers.isEmpty() && !session.isSneaking()) {
// Mount Strider
return InteractionResult.SUCCESS;
} else {
InteractionResult superResult = super.mobInteract(itemInHand);
InteractionResult superResult = super.mobInteract(hand, itemInHand);
if (superResult.consumesAction()) {
return superResult;
} else {

View file

@ -29,8 +29,8 @@ import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanE
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.session.GeyserSession;
import java.util.UUID;

View file

@ -26,6 +26,7 @@
package org.geysermc.geyser.entity.type.living.animal.horse;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata;
import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
import com.google.common.collect.ImmutableSet;
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
@ -129,12 +130,12 @@ public class AbstractHorseEntity extends AnimalEntity {
@Nonnull
@Override
protected InteractiveTag testMobInteraction(@Nonnull GeyserItemStack itemInHand) {
return testHorseInteraction(itemInHand);
protected InteractiveTag testMobInteraction(Hand hand, @Nonnull GeyserItemStack itemInHand) {
return testHorseInteraction(hand, itemInHand);
}
@Nonnull
protected final InteractiveTag testHorseInteraction(@Nonnull GeyserItemStack itemInHand) {
protected final InteractiveTag testHorseInteraction(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
boolean isBaby = isBaby();
if (!isBaby) {
if (getFlag(EntityFlag.TAMED) && session.isSneaking()) {
@ -142,7 +143,7 @@ public class AbstractHorseEntity extends AnimalEntity {
}
if (!passengers.isEmpty()) {
return super.testMobInteraction(itemInHand);
return super.testMobInteraction(hand, itemInHand);
}
}
@ -171,7 +172,7 @@ public class AbstractHorseEntity extends AnimalEntity {
}
if (isBaby) {
return super.testMobInteraction(itemInHand);
return super.testMobInteraction(hand, itemInHand);
} else {
return InteractiveTag.MOUNT;
}
@ -179,12 +180,12 @@ public class AbstractHorseEntity extends AnimalEntity {
@Nonnull
@Override
protected InteractionResult mobInteract(@Nonnull GeyserItemStack itemInHand) {
return mobHorseInteract(itemInHand);
protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) {
return mobHorseInteract(hand, itemInHand);
}
@Nonnull
protected final InteractionResult mobHorseInteract(@Nonnull GeyserItemStack itemInHand) {
protected final InteractionResult mobHorseInteract(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
boolean isBaby = isBaby();
if (!isBaby) {
if (getFlag(EntityFlag.TAMED) && session.isSneaking()) {
@ -193,7 +194,7 @@ public class AbstractHorseEntity extends AnimalEntity {
}
if (!passengers.isEmpty()) {
return super.mobInteract(itemInHand);
return super.mobInteract(hand, itemInHand);
}
}
@ -227,7 +228,7 @@ public class AbstractHorseEntity extends AnimalEntity {
}
if (isBaby) {
return super.mobInteract(itemInHand);
return super.mobInteract(hand, itemInHand);
} else {
// Attempt to mount
// TODO client-set flags sitting standing?
@ -249,15 +250,15 @@ public class AbstractHorseEntity extends AnimalEntity {
/* Just a place to stuff common code for the undead variants without having duplicate code */
protected final InteractiveTag testUndeadHorseInteraction(@Nonnull GeyserItemStack itemInHand) {
protected final InteractiveTag testUndeadHorseInteraction(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
if (!getFlag(EntityFlag.TAMED)) {
return InteractiveTag.NONE;
} else if (isBaby()) {
return testHorseInteraction(itemInHand);
return testHorseInteraction(hand, itemInHand);
} else if (session.isSneaking()) {
return InteractiveTag.OPEN_CONTAINER;
} else if (!passengers.isEmpty()) {
return testHorseInteraction(itemInHand);
return testHorseInteraction(hand, itemInHand);
} else {
if (session.getItemMappings().getStoredItems().saddle() == itemInHand.getJavaId()) {
return InteractiveTag.OPEN_CONTAINER;
@ -271,16 +272,16 @@ public class AbstractHorseEntity extends AnimalEntity {
}
}
protected final InteractionResult undeadHorseInteract(@Nonnull GeyserItemStack itemInHand) {
protected final InteractionResult undeadHorseInteract(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
if (!getFlag(EntityFlag.TAMED)) {
return InteractionResult.PASS;
} else if (isBaby()) {
return mobHorseInteract(itemInHand);
return mobHorseInteract(hand, itemInHand);
} else if (session.isSneaking()) {
// Opens inventory
return InteractionResult.SUCCESS;
} else if (!passengers.isEmpty()) {
return mobHorseInteract(itemInHand);
return mobHorseInteract(hand, itemInHand);
} else {
// The client tests for saddle but it doesn't matter for us at this point.
return InteractionResult.SUCCESS;

View file

@ -25,6 +25,7 @@
package org.geysermc.geyser.entity.type.living.animal.horse;
import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
import com.nukkitx.math.vector.Vector3f;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.inventory.GeyserItemStack;
@ -42,13 +43,13 @@ public class SkeletonHorseEntity extends AbstractHorseEntity {
@Nonnull
@Override
protected InteractiveTag testMobInteraction(@Nonnull GeyserItemStack itemInHand) {
return testUndeadHorseInteraction(itemInHand);
protected InteractiveTag testMobInteraction(Hand hand, @Nonnull GeyserItemStack itemInHand) {
return testUndeadHorseInteraction(hand, itemInHand);
}
@Nonnull
@Override
protected InteractionResult mobInteract(@Nonnull GeyserItemStack itemInHand) {
return undeadHorseInteract(itemInHand);
protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) {
return undeadHorseInteract(hand, itemInHand);
}
}

View file

@ -25,6 +25,7 @@
package org.geysermc.geyser.entity.type.living.animal.horse;
import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
import com.nukkitx.math.vector.Vector3f;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.inventory.GeyserItemStack;
@ -42,13 +43,13 @@ public class ZombieHorseEntity extends AbstractHorseEntity {
@Nonnull
@Override
protected InteractiveTag testMobInteraction(@Nonnull GeyserItemStack itemInHand) {
return testUndeadHorseInteraction(itemInHand);
protected InteractiveTag testMobInteraction(Hand hand, @Nonnull GeyserItemStack itemInHand) {
return testUndeadHorseInteraction(hand, itemInHand);
}
@Nonnull
@Override
protected InteractionResult mobInteract(@Nonnull GeyserItemStack itemInHand) {
return undeadHorseInteract(itemInHand);
protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) {
return undeadHorseInteract(hand, itemInHand);
}
}

View file

@ -28,13 +28,14 @@ package org.geysermc.geyser.entity.type.living.animal.tameable;
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.github.steveice10.mc.protocol.data.game.entity.player.Hand;
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.inventory.GeyserItemStack;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.util.InteractionResult;
import org.geysermc.geyser.util.InteractiveTag;
@ -105,7 +106,7 @@ public class CatEntity extends TameableEntity {
@Nonnull
@Override
protected InteractiveTag testMobInteraction(@Nonnull GeyserItemStack itemInHand) {
protected InteractiveTag testMobInteraction(Hand hand, @Nonnull GeyserItemStack itemInHand) {
boolean tamed = getFlag(EntityFlag.TAMED);
if (tamed && ownerBedrockId == session.getPlayerEntity().getGeyserId()) {
// Toggle sitting
@ -117,7 +118,7 @@ public class CatEntity extends TameableEntity {
@Nonnull
@Override
protected InteractionResult mobInteract(@Nonnull GeyserItemStack itemInHand) {
protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) {
boolean tamed = getFlag(EntityFlag.TAMED);
if (tamed && ownerBedrockId == session.getPlayerEntity().getGeyserId()) {
return InteractionResult.SUCCESS;

View file

@ -25,12 +25,13 @@
package org.geysermc.geyser.entity.type.living.animal.tameable;
import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.inventory.GeyserItemStack;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.util.InteractionResult;
import org.geysermc.geyser.util.InteractiveTag;
@ -58,7 +59,7 @@ public class ParrotEntity extends TameableEntity {
@Nonnull
@Override
protected InteractiveTag testMobInteraction(@Nonnull GeyserItemStack itemInHand) {
protected InteractiveTag testMobInteraction(Hand hand, @Nonnull GeyserItemStack itemInHand) {
String javaIdentifierStripped = itemInHand.getMapping(session).getJavaIdentifier().replace("minecraft:", "");
boolean tame = getFlag(EntityFlag.TAMED);
if (!tame && isTameFood(javaIdentifierStripped)) {
@ -69,12 +70,12 @@ public class ParrotEntity extends TameableEntity {
// Sitting/standing
return getFlag(EntityFlag.SITTING) ? InteractiveTag.STAND : InteractiveTag.SIT;
}
return super.testMobInteraction(itemInHand);
return super.testMobInteraction(hand, itemInHand);
}
@Nonnull
@Override
protected InteractionResult mobInteract(@Nonnull GeyserItemStack itemInHand) {
protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) {
String javaIdentifierStripped = itemInHand.getMapping(session).getJavaIdentifier().replace("minecraft:", "");
boolean tame = getFlag(EntityFlag.TAMED);
if (!tame && isTameFood(javaIdentifierStripped)) {
@ -85,6 +86,6 @@ public class ParrotEntity extends TameableEntity {
// Sitting/standing
return InteractionResult.SUCCESS;
}
return super.mobInteract(itemInHand);
return super.mobInteract(hand, itemInHand);
}
}

View file

@ -31,8 +31,8 @@ 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.geyser.entity.type.Entity;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.entity.type.Entity;
import org.geysermc.geyser.entity.type.living.animal.AnimalEntity;
import org.geysermc.geyser.session.GeyserSession;

View file

@ -27,14 +27,15 @@ package org.geysermc.geyser.entity.type.living.animal.tameable;
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.github.steveice10.mc.protocol.data.game.entity.player.Hand;
import com.google.common.collect.ImmutableSet;
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.inventory.GeyserItemStack;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.util.InteractionResult;
import org.geysermc.geyser.util.InteractiveTag;
import org.geysermc.geyser.util.ItemUtils;
@ -103,7 +104,7 @@ public class WolfEntity extends TameableEntity {
@Nonnull
@Override
protected InteractiveTag testMobInteraction(@Nonnull GeyserItemStack itemInHand) {
protected InteractiveTag testMobInteraction(Hand hand, @Nonnull GeyserItemStack itemInHand) {
if (getFlag(EntityFlag.ANGRY)) {
return InteractiveTag.NONE;
}
@ -122,12 +123,12 @@ public class WolfEntity extends TameableEntity {
return getFlag(EntityFlag.SITTING) ? InteractiveTag.STAND : InteractiveTag.SIT;
}
}
return super.testMobInteraction(itemInHand);
return super.testMobInteraction(hand, itemInHand);
}
@Nonnull
@Override
protected InteractionResult mobInteract(@Nonnull GeyserItemStack itemInHand) {
protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) {
if (ownerBedrockId == session.getPlayerEntity().getGeyserId() || getFlag(EntityFlag.TAMED)
|| itemInHand.getMapping(session).getJavaIdentifier().equals("minecraft:bone") && !getFlag(EntityFlag.ANGRY)) {
// Sitting toggle or feeding; not angry

View file

@ -25,6 +25,7 @@
package org.geysermc.geyser.entity.type.living.merchant;
import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
import org.geysermc.geyser.entity.EntityDefinition;
@ -51,7 +52,7 @@ public class AbstractMerchantEntity extends AgeableEntity {
@Nonnull
@Override
protected InteractiveTag testMobInteraction(@Nonnull GeyserItemStack itemInHand) {
protected InteractiveTag testMobInteraction(Hand hand, @Nonnull GeyserItemStack itemInHand) {
String javaIdentifier = itemInHand.getMapping(session).getJavaIdentifier();
if (!javaIdentifier.equals("minecraft:villager_spawn_egg")
&& (definition != EntityDefinitions.VILLAGER || !getFlag(EntityFlag.SLEEPING) && ((VillagerEntity) this).isCanTradeWith())) {
@ -60,12 +61,12 @@ public class AbstractMerchantEntity extends AgeableEntity {
return InteractiveTag.TRADE;
}
}
return super.testMobInteraction(itemInHand);
return super.testMobInteraction(hand, itemInHand);
}
@Nonnull
@Override
protected InteractionResult mobInteract(@Nonnull GeyserItemStack itemInHand) {
protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) {
String javaIdentifier = itemInHand.getMapping(session).getJavaIdentifier();
if (!javaIdentifier.equals("minecraft:villager_spawn_egg")
&& (definition != EntityDefinitions.VILLAGER || !getFlag(EntityFlag.SLEEPING))
@ -73,7 +74,7 @@ public class AbstractMerchantEntity extends AgeableEntity {
// Trading time
return InteractionResult.SUCCESS;
} else {
return super.mobInteract(itemInHand);
return super.mobInteract(hand, itemInHand);
}
}
}

View file

@ -26,7 +26,6 @@
package org.geysermc.geyser.entity.type.living.merchant;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.VillagerData;
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.math.vector.Vector3i;
@ -103,7 +102,7 @@ public class VillagerEntity extends AbstractMerchantEntity {
}
@Override
public Vector3i setBedPosition(EntityMetadata<Optional<Position>, ?> entityMetadata) {
public Vector3i setBedPosition(EntityMetadata<Optional<Vector3i>, ?> entityMetadata) {
return bedPosition = super.setBedPosition(entityMetadata);
}

View file

@ -48,6 +48,6 @@ public class BasePiglinEntity extends MonsterEntity {
@Override
protected boolean isShaking() {
return (!isImmuneToZombification && !session.isDimensionPiglinSafe()) || super.isShaking();
return (!isImmuneToZombification && !session.getDimensionType().piglinSafe()) || super.isShaking();
}
}

View file

@ -27,6 +27,7 @@ package org.geysermc.geyser.entity.type.living.monster;
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.github.steveice10.mc.protocol.data.game.entity.player.Hand;
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.SoundEvent;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
@ -63,23 +64,23 @@ public class CreeperEntity extends MonsterEntity {
@Nonnull
@Override
protected InteractiveTag testMobInteraction(@Nonnull GeyserItemStack itemInHand) {
protected InteractiveTag testMobInteraction(Hand hand, @Nonnull GeyserItemStack itemInHand) {
if (itemInHand.getJavaId() == session.getItemMappings().getStoredItems().flintAndSteel()) {
return InteractiveTag.IGNITE_CREEPER;
} else {
return super.testMobInteraction(itemInHand);
return super.testMobInteraction(hand, itemInHand);
}
}
@Nonnull
@Override
protected InteractionResult mobInteract(@Nonnull GeyserItemStack itemInHand) {
protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) {
if (itemInHand.getJavaId() == session.getItemMappings().getStoredItems().flintAndSteel()) {
// Ignite creeper
session.playSoundEvent(SoundEvent.IGNITE, position);
return InteractionResult.SUCCESS;
} else {
return super.mobInteract(itemInHand);
return super.mobInteract(hand, itemInHand);
}
}
}

View file

@ -39,6 +39,7 @@ import org.geysermc.geyser.entity.type.living.MobEntity;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.util.DimensionUtils;
import java.util.Optional;
import java.util.Random;
import java.util.UUID;
import java.util.concurrent.ThreadLocalRandom;
@ -212,7 +213,7 @@ public class EnderDragonEntity extends MobEntity implements Tickable {
*/
private void effectTick() {
Random random = ThreadLocalRandom.current();
if (!getFlag(EntityFlag.SILENT)) {
if (!silent) {
if (Math.cos(wingPosition * 2f * Math.PI) <= -0.3f && Math.cos(lastWingPosition * 2f * Math.PI) >= -0.3f) {
PlaySoundPacket playSoundPacket = new PlaySoundPacket();
playSoundPacket.setSound("mob.enderdragon.flap");
@ -262,6 +263,7 @@ public class EnderDragonEntity extends MobEntity implements Tickable {
spawnParticleEffectPacket.setDimensionId(DimensionUtils.javaToBedrock(session.getDimension()));
spawnParticleEffectPacket.setPosition(head.getPosition().add(random.nextGaussian() / 2f, random.nextGaussian() / 2f, random.nextGaussian() / 2f));
spawnParticleEffectPacket.setIdentifier("minecraft:dragon_breath_fire");
spawnParticleEffectPacket.setMolangVariablesJson(Optional.empty());
session.sendUpstreamPacket(spawnParticleEffectPacket);
}
}

View file

@ -28,8 +28,8 @@ package org.geysermc.geyser.entity.type.living.monster;
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
import org.geysermc.geyser.entity.type.Entity;
import org.geysermc.geyser.entity.EntityDefinitions;
import org.geysermc.geyser.entity.type.Entity;
import org.geysermc.geyser.session.GeyserSession;
public class EnderDragonPartEntity extends Entity {

View file

@ -28,8 +28,8 @@ package org.geysermc.geyser.entity.type.living.monster;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata;
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
import org.geysermc.geyser.entity.type.Entity;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.entity.type.Entity;
import org.geysermc.geyser.session.GeyserSession;
import java.util.UUID;

View file

@ -26,6 +26,7 @@
package org.geysermc.geyser.entity.type.living.monster;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanEntityMetadata;
import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
@ -71,8 +72,8 @@ public class PiglinEntity extends BasePiglinEntity {
@Nonnull
@Override
protected InteractiveTag testMobInteraction(@Nonnull GeyserItemStack itemInHand) {
InteractiveTag tag = super.testMobInteraction(itemInHand);
protected InteractiveTag testMobInteraction(Hand hand, @Nonnull GeyserItemStack itemInHand) {
InteractiveTag tag = super.testMobInteraction(hand, itemInHand);
if (tag != InteractiveTag.NONE) {
return tag;
} else {
@ -82,8 +83,8 @@ public class PiglinEntity extends BasePiglinEntity {
@Nonnull
@Override
protected InteractionResult mobInteract(@Nonnull GeyserItemStack itemInHand) {
InteractionResult superResult = super.mobInteract(itemInHand);
protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) {
InteractionResult superResult = super.mobInteract(hand, itemInHand);
if (superResult.consumesAction()) {
return superResult;
} else {

View file

@ -0,0 +1,98 @@
/*
* Copyright (c) 2019-2022 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.geyser.entity.type.living.monster;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.Pose;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata;
import com.nukkitx.math.GenericMath;
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
import com.nukkitx.protocol.bedrock.packet.PlaySoundPacket;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.entity.type.Tickable;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.util.MathUtils;
import java.util.UUID;
import java.util.concurrent.ThreadLocalRandom;
public class WardenEntity extends MonsterEntity implements Tickable {
private int heartBeatDelay;
private int tickCount;
private int sonicBoomTickDuration;
public WardenEntity(GeyserSession session, int 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 setPose(Pose pose) {
setFlag(EntityFlag.DIGGING, pose == Pose.DIGGING);
setFlag(EntityFlag.EMERGING, pose == Pose.EMERGING);
setFlag(EntityFlag.ROARING, pose == Pose.ROARING);
setFlag(EntityFlag.SNIFFING, pose == Pose.SNIFFING);
super.setPose(pose);
}
public void setAngerLevel(IntEntityMetadata entityMetadata) {
float anger = (float) entityMetadata.getPrimitiveValue() / 80f;
heartBeatDelay = 40 - GenericMath.floor(MathUtils.clamp(anger, 0.0F, 1.0F) * 30F);
dirtyMetadata.put(EntityData.HEARTBEAT_INTERVAL_TICKS, heartBeatDelay);
}
@Override
public void tick() {
if (++tickCount % heartBeatDelay == 0 && !silent) {
// We have to do these calculations because they're clientside on Java Edition but we mute entities
// to prevent hearing their step sounds
ThreadLocalRandom random = ThreadLocalRandom.current();
PlaySoundPacket packet = new PlaySoundPacket();
packet.setSound("mob.warden.heartbeat");
packet.setPosition(position);
packet.setPitch((random.nextFloat() - random.nextFloat()) * 0.2f + 1.0f);
packet.setVolume(1.0f);
session.sendUpstreamPacket(packet);
}
if (sonicBoomTickDuration > 0) {
sonicBoomTickDuration--;
if (sonicBoomTickDuration == 0) {
setFlag(EntityFlag.SONIC_BOOM, false);
updateBedrockMetadata();
}
}
}
public void onSonicBoom() {
setFlag(EntityFlag.SONIC_BOOM, true);
updateBedrockMetadata();
sonicBoomTickDuration = 3 * 20;
}
}

View file

@ -28,8 +28,8 @@ package org.geysermc.geyser.entity.type.living.monster;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata;
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
import org.geysermc.geyser.entity.type.Entity;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.entity.type.Entity;
import org.geysermc.geyser.session.GeyserSession;
import java.util.UUID;

View file

@ -28,6 +28,7 @@ package org.geysermc.geyser.entity.type.living.monster;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.VillagerData;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanEntityMetadata;
import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
@ -67,22 +68,22 @@ public class ZombieVillagerEntity extends ZombieEntity {
@Nonnull
@Override
protected InteractiveTag testMobInteraction(@Nonnull GeyserItemStack itemInHand) {
protected InteractiveTag testMobInteraction(Hand hand, @Nonnull GeyserItemStack itemInHand) {
if (itemInHand.getJavaId() == session.getItemMappings().getStoredItems().goldenApple()) {
return InteractiveTag.CURE;
} else {
return super.testMobInteraction(itemInHand);
return super.testMobInteraction(hand, itemInHand);
}
}
@Nonnull
@Override
protected InteractionResult mobInteract(@Nonnull GeyserItemStack itemInHand) {
protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) {
if (itemInHand.getJavaId() == session.getItemMappings().getStoredItems().goldenApple()) {
// The client doesn't know if the entity has weakness as that's not usually sent over the network
return InteractionResult.CONSUME;
} else {
return super.mobInteract(itemInHand);
return super.mobInteract(hand, itemInHand);
}
}
}

View file

@ -28,8 +28,8 @@ package org.geysermc.geyser.entity.type.living.monster.raid;
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.session.GeyserSession;
import java.util.UUID;

View file

@ -27,7 +27,6 @@ package org.geysermc.geyser.entity.type.player;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.Pose;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanEntityMetadata;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.FloatEntityMetadata;
@ -169,6 +168,12 @@ public class PlayerEntity extends LivingEntity {
}
session.sendUpstreamPacket(movePlayerPacket);
if (teleported) {
// As of 1.19.0, head yaw seems to be ignored during teleports.
updateHeadLookRotation(headYaw);
}
if (leftParrot != null) {
leftParrot.moveAbsolute(position, yaw, pitch, headYaw, true, teleported);
}
@ -211,52 +216,8 @@ public class PlayerEntity extends LivingEntity {
}
}
@Override
public void updateHeadLookRotation(float headYaw) {
moveRelative(0, 0, 0, getYaw(), getPitch(), headYaw, isOnGround());
MovePlayerPacket movePlayerPacket = new MovePlayerPacket();
movePlayerPacket.setRuntimeEntityId(geyserId);
movePlayerPacket.setPosition(position);
movePlayerPacket.setRotation(getBedrockRotation());
movePlayerPacket.setMode(MovePlayerPacket.Mode.HEAD_ROTATION);
session.sendUpstreamPacket(movePlayerPacket);
}
@Override
public void updatePositionAndRotation(double moveX, double moveY, double moveZ, float yaw, float pitch, boolean isOnGround) {
moveRelative(moveX, moveY, moveZ, yaw, pitch, isOnGround);
if (leftParrot != null) {
leftParrot.moveRelative(moveX, moveY, moveZ, yaw, pitch, isOnGround);
}
if (rightParrot != null) {
rightParrot.moveRelative(moveX, moveY, moveZ, yaw, pitch, isOnGround);
}
}
public void updateRotation(float yaw, float pitch, float headYaw, boolean isOnGround) {
// the method below is called by super.updateRotation(yaw, pitch, isOnGround).
// but we have to be able to set the headYaw, so we call the method below directly.
super.moveRelative(0, 0, 0, yaw, pitch, headYaw, isOnGround);
// Both packets need to be sent or else player head rotation isn't correctly updated
MovePlayerPacket movePlayerPacket = new MovePlayerPacket();
movePlayerPacket.setRuntimeEntityId(geyserId);
movePlayerPacket.setPosition(position);
movePlayerPacket.setRotation(getBedrockRotation());
movePlayerPacket.setOnGround(isOnGround);
movePlayerPacket.setMode(MovePlayerPacket.Mode.HEAD_ROTATION);
session.sendUpstreamPacket(movePlayerPacket);
if (leftParrot != null) {
leftParrot.updateRotation(yaw, pitch, isOnGround);
}
if (rightParrot != null) {
rightParrot.updateRotation(yaw, pitch, isOnGround);
}
}
@Override
public void updateRotation(float yaw, float pitch, boolean isOnGround) {
updateRotation(yaw, pitch, getHeadYaw(), isOnGround);
moveRelative(0, 0, 0, yaw, pitch, headYaw, isOnGround);
}
@Override
@ -265,7 +226,7 @@ public class PlayerEntity extends LivingEntity {
}
@Override
public Vector3i setBedPosition(EntityMetadata<Optional<Position>, ?> entityMetadata) {
public Vector3i setBedPosition(EntityMetadata<Optional<Vector3i>, ?> entityMetadata) {
return bedPosition = super.setBedPosition(entityMetadata);
}

View file

@ -27,6 +27,7 @@ package org.geysermc.geyser.entity.type.player;
import com.github.steveice10.mc.protocol.data.game.entity.attribute.Attribute;
import com.github.steveice10.mc.protocol.data.game.entity.attribute.AttributeType;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.GlobalPos;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.Pose;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata;
import com.nukkitx.math.vector.Vector3f;
@ -40,7 +41,9 @@ import org.geysermc.geyser.entity.attribute.GeyserAttributeType;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.util.AttributeUtils;
import org.geysermc.geyser.util.DimensionUtils;
import javax.annotation.Nullable;
import java.util.Collections;
import java.util.List;
import java.util.Map;
@ -75,6 +78,11 @@ public class SessionPlayerEntity extends PlayerEntity {
valid = true;
}
@Override
protected void setClientSideSilent() {
// Do nothing, since we want the session player to hear their own footstep sounds for example.
}
@Override
public void spawnEntity() {
// Already logged in
@ -134,6 +142,10 @@ public class SessionPlayerEntity extends PlayerEntity {
return maxHealth;
}
public float getHealth() {
return this.health;
}
public void setHealth(float health) {
this.health = health;
}
@ -218,4 +230,14 @@ public class SessionPlayerEntity extends PlayerEntity {
this.attributes.put(type, attributeData);
return attributeData;
}
public void setLastDeathPosition(@Nullable GlobalPos pos) {
if (pos != null) {
dirtyMetadata.put(EntityData.PLAYER_LAST_DEATH_POS, pos.getPosition());
dirtyMetadata.put(EntityData.PLAYER_LAST_DEATH_DIMENSION, DimensionUtils.javaToBedrock(pos.getDimension()));
dirtyMetadata.put(EntityData.PLAYER_HAS_DIED, (byte) 1);
} else {
dirtyMetadata.put(EntityData.PLAYER_HAS_DIED, (byte) 0);
}
}
}

View file

@ -26,33 +26,28 @@
package org.geysermc.geyser.entity.type.player;
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.math.vector.Vector3i;
import com.nukkitx.protocol.bedrock.data.GameType;
import com.nukkitx.protocol.bedrock.data.PlayerPermission;
import com.nukkitx.protocol.bedrock.data.command.CommandPermission;
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
import com.nukkitx.protocol.bedrock.packet.AddPlayerPacket;
import lombok.Getter;
import org.geysermc.geyser.level.block.BlockStateValues;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.session.cache.SkullCache;
import org.geysermc.geyser.skin.SkullSkinManager;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
/**
* A wrapper to handle skulls more effectively - skulls have to be treated as entities since there are no
* custom player skulls in Bedrock.
*/
public class SkullPlayerEntity extends PlayerEntity {
/**
* Stores the block state that the skull is associated with. Used to determine if the block in the skull's position
* has changed
*/
@Getter
private final int blockState;
public SkullPlayerEntity(GeyserSession session, long geyserId, Vector3f position, float rotation, int blockState, String texturesProperty) {
super(session, 0, geyserId, UUID.randomUUID(), position, Vector3f.ZERO, rotation, 0, rotation, "", texturesProperty);
this.blockState = blockState;
public SkullPlayerEntity(GeyserSession session, long geyserId) {
super(session, 0, geyserId, UUID.randomUUID(), Vector3f.ZERO, Vector3f.ZERO, 0, 0, 0, "", null);
setPlayerList(false);
}
@ -95,8 +90,57 @@ public class SkullPlayerEntity extends PlayerEntity {
session.sendUpstreamPacket(addPlayerPacket);
}
public void despawnEntity(Vector3i position) {
this.despawnEntity();
session.getSkullCache().remove(position, this);
/**
* Hide the player entity so that it can be reused for a different skull.
*/
public void free() {
setFlag(EntityFlag.INVISIBLE, true);
updateBedrockMetadata();
// Move skull entity out of the way
moveAbsolute(session.getPlayerEntity().getPosition().up(128), 0, 0, 0, false, true);
}
public void updateSkull(SkullCache.Skull skull) {
if (!skull.getTexturesProperty().equals(getTexturesProperty())) {
// Make skull invisible as we change skins
setFlag(EntityFlag.INVISIBLE, true);
updateBedrockMetadata();
setTexturesProperty(skull.getTexturesProperty());
SkullSkinManager.requestAndHandleSkin(this, session, (skin -> session.scheduleInEventLoop(() -> {
// Delay to minimize split-second "player" pop-in
setFlag(EntityFlag.INVISIBLE, false);
updateBedrockMetadata();
}, 250, TimeUnit.MILLISECONDS)));
} else {
// Just a rotation/position change
setFlag(EntityFlag.INVISIBLE, false);
updateBedrockMetadata();
}
float x = skull.getPosition().getX() + .5f;
float y = skull.getPosition().getY() - .01f;
float z = skull.getPosition().getZ() + .5f;
float rotation;
int blockState = skull.getBlockState();
byte floorRotation = BlockStateValues.getSkullRotation(blockState);
if (floorRotation == -1) {
// Wall skull
y += 0.25f;
rotation = BlockStateValues.getSkullWallDirections().get(blockState);
switch ((int) rotation) {
case 180 -> z += 0.24f; // North
case 0 -> z -= 0.24f; // South
case 90 -> x += 0.24f; // West
case 270 -> x -= 0.24f; // East
}
} else {
rotation = (180f + (floorRotation * 22.5f)) % 360;
}
moveAbsolute(Vector3f.from(x, y, z), rotation, 0, rotation, true, true);
}
}

View file

@ -30,13 +30,12 @@ import it.unimi.dsi.fastutil.objects.Object2ReferenceOpenHashMap;
import org.geysermc.geyser.api.extension.Extension;
import org.geysermc.geyser.api.extension.ExtensionDescription;
import org.geysermc.geyser.api.extension.exception.InvalidExtensionException;
import java.lang.reflect.InvocationTargetException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.Map;
public class GeyserExtensionClassLoader extends URLClassLoader {
private final GeyserExtensionLoader loader;

View file

@ -29,6 +29,7 @@ import org.geysermc.geyser.api.extension.ExtensionDescription;
import org.geysermc.geyser.api.extension.exception.InvalidDescriptionException;
import org.yaml.snakeyaml.DumperOptions;
import org.yaml.snakeyaml.Yaml;
import java.io.Reader;
import java.util.*;

View file

@ -31,23 +31,14 @@ import lombok.RequiredArgsConstructor;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.api.event.ExtensionEventBus;
import org.geysermc.geyser.api.extension.Extension;
import org.geysermc.geyser.api.extension.ExtensionDescription;
import org.geysermc.geyser.api.extension.ExtensionLoader;
import org.geysermc.geyser.api.extension.ExtensionLogger;
import org.geysermc.geyser.api.extension.ExtensionManager;
import org.geysermc.geyser.api.extension.*;
import org.geysermc.geyser.api.extension.exception.InvalidDescriptionException;
import org.geysermc.geyser.api.extension.exception.InvalidExtensionException;
import org.geysermc.geyser.extension.event.GeyserExtensionEventBus;
import org.geysermc.geyser.text.GeyserLocale;
import java.io.IOException;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.*;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

View file

@ -30,12 +30,15 @@ import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.api.extension.Extension;
import org.geysermc.geyser.api.extension.ExtensionManager;
import org.geysermc.geyser.api.extension.ExtensionLoader;
import org.geysermc.geyser.api.extension.ExtensionManager;
import org.geysermc.geyser.registry.Registries;
import org.geysermc.geyser.text.GeyserLocale;
import java.util.*;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.stream.Collectors;
public class GeyserExtensionManager extends ExtensionManager {

View file

@ -46,7 +46,7 @@ public class GeyserEnchantOption {
*/
private static final List<String> ENCHANT_NAMES = Arrays.asList("tougher armor", "lukeeey", "fall better",
"explode less", "camo toy", "breathe better", "rtm five one six", "armor stab", "water walk", "you are elsa",
"tim two zero three", "fast walk nether", "oof ouch owie", "enemy on fire", "spider sad", "aj ferguson", "redned",
"tim two zero three", "fast walk nether", "davchoo", "oof ouch owie", "enemy on fire", "spider sad", "aj ferguson", "redned",
"more items thx", "long sword reach", "fast tool", "give me block", "less breaky break", "cube craft",
"strong arrow", "fist arrow", "spicy arrow", "many many arrows", "geyser", "come here fish", "i like this",
"stabby stab", "supreme mortal", "avatar i guess", "more arrows", "fly finder seventeen", "in and out",

View file

@ -29,9 +29,9 @@ import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack;
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
import com.nukkitx.protocol.bedrock.data.inventory.ItemData;
import lombok.Data;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.inventory.item.ItemTranslator;
import org.geysermc.geyser.registry.type.ItemMapping;
import javax.annotation.Nonnull;

View file

@ -25,8 +25,8 @@
package org.geysermc.geyser.inventory;
import com.github.steveice10.mc.protocol.data.game.inventory.VillagerTrade;
import com.github.steveice10.mc.protocol.data.game.inventory.ContainerType;
import com.github.steveice10.mc.protocol.data.game.inventory.VillagerTrade;
import com.github.steveice10.mc.protocol.packet.ingame.clientbound.inventory.ClientboundMerchantOffersPacket;
import lombok.Getter;
import lombok.Setter;

View file

@ -25,8 +25,6 @@
package org.geysermc.geyser.inventory.click;
import com.github.steveice10.mc.protocol.data.game.inventory.ClickItemAction;
import com.github.steveice10.mc.protocol.data.game.inventory.ContainerActionType;
import com.github.steveice10.mc.protocol.data.game.inventory.*;
import lombok.AllArgsConstructor;

View file

@ -25,7 +25,6 @@
package org.geysermc.geyser.inventory.holder;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position;
import com.google.common.collect.ImmutableSet;
import com.nukkitx.math.vector.Vector3i;
import com.nukkitx.nbt.NbtMap;
@ -36,9 +35,9 @@ import com.nukkitx.protocol.bedrock.packet.ContainerOpenPacket;
import com.nukkitx.protocol.bedrock.packet.UpdateBlockPacket;
import org.geysermc.geyser.inventory.Container;
import org.geysermc.geyser.inventory.Inventory;
import org.geysermc.geyser.registry.BlockRegistries;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.inventory.InventoryTranslator;
import org.geysermc.geyser.registry.BlockRegistries;
import org.geysermc.geyser.util.BlockUtils;
import java.util.Collections;
@ -154,8 +153,7 @@ public class BlockInventoryHolder extends InventoryHolder {
}
Vector3i holderPos = inventory.getHolderPosition();
Position pos = new Position(holderPos.getX(), holderPos.getY(), holderPos.getZ());
int realBlock = session.getGeyser().getWorldManager().getBlockAt(session, pos.getX(), pos.getY(), pos.getZ());
int realBlock = session.getGeyser().getWorldManager().getBlockAt(session, holderPos.getX(), holderPos.getY(), holderPos.getZ());
UpdateBlockPacket blockPacket = new UpdateBlockPacket();
blockPacket.setDataLayer(0);
blockPacket.setBlockPosition(holderPos);

View file

@ -67,7 +67,8 @@ public enum Enchantment {
MULTISHOT,
PIERCING,
QUICK_CHARGE,
SOUL_SPEED;
SOUL_SPEED,
SWIFT_SNEAK;
private static final Enchantment[] VALUES = values();
@ -109,6 +110,7 @@ public enum Enchantment {
FROST_WALKER,
BINDING_CURSE,
SOUL_SPEED,
SWIFT_SNEAK,
SHARPNESS,
SMITE,
BANE_OF_ARTHROPODS,

View file

@ -60,6 +60,7 @@ public class StoredItemMappings {
private final int saddle;
private final int shears;
private final ItemMapping shield;
private final int slimeBall;
private final int waterBucket;
private final ItemMapping wheat;
private final ItemMapping writableBook;
@ -87,6 +88,7 @@ public class StoredItemMappings {
this.saddle = load(itemMappings, "saddle").getJavaId();
this.shears = load(itemMappings, "shears").getJavaId();
this.shield = load(itemMappings, "shield");
this.slimeBall = load(itemMappings, "slime_ball").getJavaId();
this.waterBucket = load(itemMappings, "water_bucket").getJavaId();
this.wheat = load(itemMappings, "wheat");
this.writableBook = load(itemMappings, "writable_book");

View file

@ -27,7 +27,6 @@ package org.geysermc.geyser.inventory.recipe;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack;
import com.github.steveice10.mc.protocol.data.game.recipe.Ingredient;
import com.github.steveice10.mc.protocol.data.game.recipe.RecipeType;
import com.github.steveice10.mc.protocol.data.game.recipe.data.ShapedRecipeData;
public record GeyserShapedRecipe(int width, int height, Ingredient[] ingredients, ItemStack result) implements GeyserRecipe {

Some files were not shown because too many files have changed in this diff Show more