mirror of
https://github.com/GeyserMC/Geyser.git
synced 2024-08-14 23:57:35 +00:00
Merge remote-tracking branch 'origin/feature/1.19-bedrock' into feature/floodgate-packet
# Conflicts: # core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaCustomPayloadTranslator.java # core/src/main/java/org/geysermc/geyser/util/PluginMessageUtils.java
This commit is contained in:
commit
d8b63b9310
715 changed files with 11058 additions and 25431 deletions
36
core/pom.xml
36
core/pom.xml
|
@ -6,14 +6,14 @@
|
|||
<parent>
|
||||
<groupId>org.geysermc</groupId>
|
||||
<artifactId>geyser-parent</artifactId>
|
||||
<version>2.0.0-SNAPSHOT</version>
|
||||
<version>2.0.3-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>core</artifactId>
|
||||
|
||||
<properties>
|
||||
<adventure.version>4.9.3</adventure.version>
|
||||
<fastutil.version>8.5.2</fastutil.version>
|
||||
<jackson.version>2.12.4</jackson.version>
|
||||
<jackson.version>2.13.2</jackson.version>
|
||||
<netty.version>4.1.66.Final</netty.version>
|
||||
</properties>
|
||||
|
||||
|
@ -21,19 +21,19 @@
|
|||
<dependency>
|
||||
<groupId>org.geysermc</groupId>
|
||||
<artifactId>ap</artifactId>
|
||||
<version>2.0.0-SNAPSHOT</version>
|
||||
<version>2.0.3-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.geysermc</groupId>
|
||||
<artifactId>geyser-api</artifactId>
|
||||
<version>2.0.0-SNAPSHOT</version>
|
||||
<version>2.0.3-SNAPSHOT</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.geysermc</groupId>
|
||||
<artifactId>common</artifactId>
|
||||
<version>2.0.0-SNAPSHOT</version>
|
||||
<version>2.0.3-SNAPSHOT</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<!-- Jackson JSON and YAML serialization -->
|
||||
|
@ -52,7 +52,7 @@
|
|||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
<version>${jackson.version}</version>
|
||||
<version>${jackson.version}.1</version> <!-- Extra .1 as databind is a slightly different version -->
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
@ -72,7 +72,7 @@
|
|||
<groupId>com.nukkitx</groupId>
|
||||
<artifactId>nbt</artifactId>
|
||||
<!-- Used for key/value interning -->
|
||||
<version>2.1.0</version>
|
||||
<version>2.2.1</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
@ -83,7 +83,7 @@
|
|||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.nukkitx.fastutil</groupId>
|
||||
<artifactId>fastutil-long-long-maps</artifactId>
|
||||
<artifactId>fastutil-int-long-maps</artifactId>
|
||||
<version>${fastutil.version}</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
@ -120,8 +120,8 @@
|
|||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.CloudburstMC.Protocol</groupId>
|
||||
<artifactId>bedrock-v475</artifactId>
|
||||
<version>c22aa595</version>
|
||||
<artifactId>bedrock-beta</artifactId>
|
||||
<version>be0cc73</version>
|
||||
<scope>compile</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
|
@ -147,23 +147,23 @@
|
|||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.RednedEpic</groupId>
|
||||
<groupId>com.github.GeyserMC</groupId>
|
||||
<artifactId>MCAuthLib</artifactId>
|
||||
<version>6c99331</version>
|
||||
<version>d9d773e</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.GeyserMC</groupId>
|
||||
<artifactId>MCProtocolLib</artifactId>
|
||||
<version>c247b1f</version>
|
||||
<groupId>com.github.steveice10</groupId>
|
||||
<artifactId>mcprotocollib</artifactId>
|
||||
<version>1.19-SNAPSHOT</version>
|
||||
<scope>compile</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>com.github.steveice10</groupId>
|
||||
<groupId>com.github.GeyserMC</groupId>
|
||||
<artifactId>packetlib</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>com.github.steveice10</groupId>
|
||||
<groupId>com.github.GeyserMC</groupId>
|
||||
<artifactId>mcauthlib</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
|
@ -171,7 +171,7 @@
|
|||
<dependency>
|
||||
<groupId>com.github.steveice10</groupId>
|
||||
<artifactId>packetlib</artifactId>
|
||||
<version>2.1-SNAPSHOT</version>
|
||||
<version>3.0</version>
|
||||
<scope>compile</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
* 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
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
* 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
|
||||
|
@ -64,7 +64,7 @@ public class GeyserSession {
|
|||
}
|
||||
|
||||
public int getRenderDistance() {
|
||||
return this.handle.getRenderDistance();
|
||||
return this.handle.getServerRenderDistance();
|
||||
}
|
||||
|
||||
public boolean isSentSpawnPacket() {
|
||||
|
@ -100,7 +100,7 @@ public class GeyserSession {
|
|||
}
|
||||
|
||||
public void login() {
|
||||
this.handle.login();
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public void authenticate(String username) {
|
||||
|
@ -120,7 +120,7 @@ public class GeyserSession {
|
|||
}
|
||||
|
||||
public void close() {
|
||||
this.handle.close();
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public void executeInEventLoop(Runnable runnable) {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
* 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
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
* 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
|
||||
|
@ -37,6 +37,8 @@ public final class Constants {
|
|||
|
||||
public static final String FLOODGATE_DOWNLOAD_LOCATION = "https://ci.opencollab.dev/job/GeyserMC/job/Floodgate/job/master/";
|
||||
|
||||
static final String SAVED_REFRESH_TOKEN_FILE = "saved-refresh-tokens.json";
|
||||
|
||||
static {
|
||||
URI wsUri = null;
|
||||
try {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
* 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
|
||||
|
@ -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());
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
* 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
|
||||
|
@ -97,6 +97,13 @@ public interface GeyserBootstrap {
|
|||
*/
|
||||
Path getConfigFolder();
|
||||
|
||||
/**
|
||||
* @return the folder where user tokens are saved. This should always point to the location of the config.
|
||||
*/
|
||||
default Path getSavedUserLoginsFolder() {
|
||||
return getConfigFolder();
|
||||
}
|
||||
|
||||
/**
|
||||
* Information used for the bootstrap section of the debug dump
|
||||
*
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
* 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
|
||||
|
@ -26,6 +26,7 @@
|
|||
package org.geysermc.geyser;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.github.steveice10.packetlib.tcp.TcpSession;
|
||||
|
@ -37,6 +38,7 @@ import io.netty.channel.kqueue.KQueue;
|
|||
import io.netty.util.NettyRuntime;
|
||||
import io.netty.util.concurrent.DefaultThreadFactory;
|
||||
import io.netty.util.internal.SystemPropertyUtil;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
|
@ -59,9 +61,12 @@ import org.geysermc.geyser.registry.BlockRegistries;
|
|||
import org.geysermc.geyser.registry.Registries;
|
||||
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.session.auth.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;
|
||||
|
@ -70,6 +75,9 @@ import org.geysermc.geyser.util.*;
|
|||
|
||||
import javax.naming.directory.Attribute;
|
||||
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;
|
||||
|
@ -77,6 +85,7 @@ import java.net.UnknownHostException;
|
|||
import java.security.Key;
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.regex.Matcher;
|
||||
|
@ -112,35 +121,36 @@ public class GeyserImpl implements GeyserApi {
|
|||
|
||||
private FloodgateCipher cipher;
|
||||
private FloodgateSkinUploader skinUploader;
|
||||
private final NewsHandler newsHandler;
|
||||
private NewsHandler newsHandler;
|
||||
|
||||
private volatile boolean shuttingDown = false;
|
||||
|
||||
private final ScheduledExecutorService scheduledThread;
|
||||
private ScheduledExecutorService scheduledThread;
|
||||
|
||||
private final BedrockServer bedrockServer;
|
||||
private BedrockServer bedrockServer;
|
||||
private final PlatformType platformType;
|
||||
private final GeyserBootstrap bootstrap;
|
||||
|
||||
private final Metrics metrics;
|
||||
private Metrics metrics;
|
||||
|
||||
private PendingMicrosoftAuthentication pendingMicrosoftAuthentication;
|
||||
@Getter(AccessLevel.NONE)
|
||||
private Map<String, String> savedRefreshTokens;
|
||||
|
||||
private static GeyserImpl instance;
|
||||
|
||||
private GeyserImpl(PlatformType platformType, GeyserBootstrap bootstrap) {
|
||||
long startupTime = System.currentTimeMillis();
|
||||
|
||||
this.bootstrap = bootstrap;
|
||||
|
||||
instance = this;
|
||||
|
||||
Geyser.set(this);
|
||||
|
||||
GeyserLogger logger = bootstrap.getGeyserLogger();
|
||||
GeyserConfiguration config = bootstrap.getGeyserConfig();
|
||||
|
||||
this.platformType = platformType;
|
||||
this.bootstrap = bootstrap;
|
||||
|
||||
long startupTime = System.currentTimeMillis();
|
||||
|
||||
GeyserLocale.finalizeDefaultLocale(this);
|
||||
GeyserLogger logger = bootstrap.getGeyserLogger();
|
||||
|
||||
logger.info("******************************************");
|
||||
logger.info("");
|
||||
|
@ -148,10 +158,6 @@ public class GeyserImpl implements GeyserApi {
|
|||
logger.info("");
|
||||
logger.info("******************************************");
|
||||
|
||||
this.scheduledThread = Executors.newSingleThreadScheduledExecutor(new DefaultThreadFactory("Geyser Scheduled Thread"));
|
||||
|
||||
logger.setDebug(config.isDebugMode());
|
||||
|
||||
/* Initialize translators and registries */
|
||||
BlockRegistries.init();
|
||||
Registries.init();
|
||||
|
@ -160,8 +166,49 @@ public class GeyserImpl implements GeyserApi {
|
|||
ItemTranslator.init();
|
||||
MessageTranslator.init();
|
||||
MinecraftLocale.init();
|
||||
|
||||
start();
|
||||
|
||||
GeyserConfiguration config = bootstrap.getGeyserConfig();
|
||||
|
||||
boolean isGui = false;
|
||||
// This will check if we are in standalone and get the 'useGui' variable from there
|
||||
if (platformType == PlatformType.STANDALONE) {
|
||||
try {
|
||||
Class<?> cls = Class.forName("org.geysermc.geyser.platform.standalone.GeyserStandaloneBootstrap");
|
||||
isGui = (boolean) cls.getMethod("isUseGui").invoke(cls.cast(bootstrap));
|
||||
} catch (Exception e) {
|
||||
logger.debug("Failed detecting if standalone is using a GUI; if this is a GeyserConnect instance this can be safely ignored.");
|
||||
}
|
||||
}
|
||||
|
||||
double completeTime = (System.currentTimeMillis() - startupTime) / 1000D;
|
||||
String message = GeyserLocale.getLocaleStringLog("geyser.core.finish.done", new DecimalFormat("#.###").format(completeTime)) + " ";
|
||||
if (isGui) {
|
||||
message += GeyserLocale.getLocaleStringLog("geyser.core.finish.gui");
|
||||
} else {
|
||||
message += GeyserLocale.getLocaleStringLog("geyser.core.finish.console");
|
||||
}
|
||||
|
||||
logger.info(message);
|
||||
|
||||
if (platformType == PlatformType.STANDALONE) {
|
||||
logger.warning(GeyserLocale.getLocaleStringLog("geyser.core.movement_warn"));
|
||||
} else if (config.getRemote().getAuthType() == AuthType.FLOODGATE) {
|
||||
VersionCheckUtils.checkForOutdatedFloodgate(logger);
|
||||
}
|
||||
}
|
||||
|
||||
private void start() {
|
||||
this.scheduledThread = Executors.newSingleThreadScheduledExecutor(new DefaultThreadFactory("Geyser Scheduled Thread"));
|
||||
|
||||
GeyserLogger logger = bootstrap.getGeyserLogger();
|
||||
GeyserConfiguration config = bootstrap.getGeyserConfig();
|
||||
|
||||
ScoreboardUpdater.init();
|
||||
|
||||
SkinProvider.registerCacheImageTask(this);
|
||||
|
||||
ResourcePack.loadPacks();
|
||||
|
||||
if (platformType != PlatformType.STANDALONE && config.getRemote().getAddress().equals("auto")) {
|
||||
|
@ -202,18 +249,6 @@ 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.productionEnvironment()) {
|
||||
|
@ -231,7 +266,10 @@ public class GeyserImpl implements GeyserApi {
|
|||
} else {
|
||||
logger.debug("Not getting git properties for the news handler as we are in a development environment.");
|
||||
}
|
||||
newsHandler = new NewsHandler(branch, buildNumber);
|
||||
|
||||
pendingMicrosoftAuthentication = new PendingMicrosoftAuthentication(config.getPendingAuthenticationTimeout());
|
||||
|
||||
this.newsHandler = new NewsHandler(branch, buildNumber);
|
||||
|
||||
CooldownUtils.setDefaultShowCooldown(config.getShowCooldown());
|
||||
DimensionUtils.changeBedrockNetherId(config.isAboveBedrockNetherBuilding()); // Apply End dimension ID workaround to Nether
|
||||
|
@ -271,19 +309,39 @@ 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));
|
||||
// Prevent unwanted words best we can
|
||||
metrics.addCustomChart(new Metrics.SimplePie("authMode", () -> config.getRemote().getAuthType().toString().toLowerCase()));
|
||||
metrics.addCustomChart(new Metrics.SimplePie("authMode", () -> config.getRemote().getAuthType().toString().toLowerCase(Locale.ROOT)));
|
||||
metrics.addCustomChart(new Metrics.SimplePie("platform", platformType::getPlatformName));
|
||||
metrics.addCustomChart(new Metrics.SimplePie("defaultLocale", GeyserLocale::getDefaultLocale));
|
||||
metrics.addCustomChart(new Metrics.SimplePie("version", () -> GeyserImpl.VERSION));
|
||||
|
@ -367,30 +425,45 @@ public class GeyserImpl implements GeyserApi {
|
|||
metrics = null;
|
||||
}
|
||||
|
||||
boolean isGui = false;
|
||||
// This will check if we are in standalone and get the 'useGui' variable from there
|
||||
if (platformType == PlatformType.STANDALONE) {
|
||||
try {
|
||||
Class<?> cls = Class.forName("org.geysermc.geyser.platform.standalone.GeyserStandaloneBootstrap");
|
||||
isGui = (boolean) cls.getMethod("isUseGui").invoke(cls.cast(bootstrap));
|
||||
} catch (Exception e) {
|
||||
logger.debug("Failed detecting if standalone is using a GUI; if this is a GeyserConnect instance this can be safely ignored.");
|
||||
if (config.getRemote().getAuthType() == AuthType.ONLINE) {
|
||||
if (config.getUserAuths() != null && !config.getUserAuths().isEmpty()) {
|
||||
getLogger().warning("The 'userAuths' config section is now deprecated, and will be removed in the near future! " +
|
||||
"Please migrate to the new 'saved-user-logins' config option: " +
|
||||
"https://wiki.geysermc.org/geyser/understanding-the-config/");
|
||||
}
|
||||
}
|
||||
|
||||
double completeTime = (System.currentTimeMillis() - startupTime) / 1000D;
|
||||
String message = GeyserLocale.getLocaleStringLog("geyser.core.finish.done", new DecimalFormat("#.###").format(completeTime)) + " ";
|
||||
if (isGui) {
|
||||
message += GeyserLocale.getLocaleStringLog("geyser.core.finish.gui");
|
||||
// May be written/read to on multiple threads from each GeyserSession as well as writing the config
|
||||
savedRefreshTokens = new ConcurrentHashMap<>();
|
||||
|
||||
File tokensFile = bootstrap.getSavedUserLoginsFolder().resolve(Constants.SAVED_REFRESH_TOKEN_FILE).toFile();
|
||||
if (tokensFile.exists()) {
|
||||
TypeReference<Map<String, String>> type = new TypeReference<>() { };
|
||||
|
||||
Map<String, String> refreshTokenFile = null;
|
||||
try {
|
||||
refreshTokenFile = JSON_MAPPER.readValue(tokensFile, type);
|
||||
} catch (IOException e) {
|
||||
logger.error("Cannot load saved user tokens!", e);
|
||||
}
|
||||
if (refreshTokenFile != null) {
|
||||
List<String> validUsers = config.getSavedUserLogins();
|
||||
boolean doWrite = false;
|
||||
for (Map.Entry<String, String> entry : refreshTokenFile.entrySet()) {
|
||||
String user = entry.getKey();
|
||||
if (!validUsers.contains(user)) {
|
||||
// Perform a write to this file to purge the now-unused name
|
||||
doWrite = true;
|
||||
continue;
|
||||
}
|
||||
savedRefreshTokens.put(user, entry.getValue());
|
||||
}
|
||||
if (doWrite) {
|
||||
scheduleRefreshTokensWrite();
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
message += GeyserLocale.getLocaleStringLog("geyser.core.finish.console");
|
||||
}
|
||||
logger.info(message);
|
||||
|
||||
if (platformType == PlatformType.STANDALONE) {
|
||||
logger.warning(GeyserLocale.getLocaleStringLog("geyser.core.movement_warn"));
|
||||
} else if (config.getRemote().getAuthType() == AuthType.FLOODGATE) {
|
||||
VersionCheckUtils.checkForOutdatedFloodgate(logger);
|
||||
savedRefreshTokens = null;
|
||||
}
|
||||
|
||||
newsHandler.handleNews(null, NewsItemAction.ON_SERVER_STARTED);
|
||||
|
@ -447,6 +520,8 @@ public class GeyserImpl implements GeyserApi {
|
|||
newsHandler.shutdown();
|
||||
this.getCommandManager().getCommands().clear();
|
||||
|
||||
ResourcePack.PACKS.clear();
|
||||
|
||||
bootstrap.getGeyserLogger().info(GeyserLocale.getLocaleStringLog("geyser.core.shutdown.done"));
|
||||
}
|
||||
|
||||
|
@ -469,7 +544,17 @@ public class GeyserImpl implements GeyserApi {
|
|||
}
|
||||
|
||||
public static GeyserImpl start(PlatformType platformType, GeyserBootstrap bootstrap) {
|
||||
return new GeyserImpl(platformType, bootstrap);
|
||||
if (instance == null) {
|
||||
return new GeyserImpl(platformType, bootstrap);
|
||||
}
|
||||
|
||||
// We've been reloaded
|
||||
if (instance.isShuttingDown()) {
|
||||
instance.shuttingDown = false;
|
||||
instance.start();
|
||||
}
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
public GeyserLogger getLogger() {
|
||||
|
@ -488,6 +573,39 @@ public class GeyserImpl implements GeyserApi {
|
|||
return bootstrap.getWorldManager();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String refreshTokenFor(@NonNull String bedrockName) {
|
||||
return savedRefreshTokens.get(bedrockName);
|
||||
}
|
||||
|
||||
public void saveRefreshToken(@NonNull String bedrockName, @NonNull String refreshToken) {
|
||||
if (!getConfig().getSavedUserLogins().contains(bedrockName)) {
|
||||
// Do not save this login
|
||||
return;
|
||||
}
|
||||
|
||||
// We can safely overwrite old instances because MsaAuthenticationService#getLoginResponseFromRefreshToken
|
||||
// refreshes the token for us
|
||||
if (!Objects.equals(refreshToken, savedRefreshTokens.put(bedrockName, refreshToken))) {
|
||||
scheduleRefreshTokensWrite();
|
||||
}
|
||||
}
|
||||
|
||||
private void scheduleRefreshTokensWrite() {
|
||||
scheduledThread.execute(() -> {
|
||||
// Ensure all writes are handled on the same thread
|
||||
File savedTokens = getBootstrap().getSavedUserLoginsFolder().resolve(Constants.SAVED_REFRESH_TOKEN_FILE).toFile();
|
||||
TypeReference<Map<String, String>> type = new TypeReference<>() { };
|
||||
try (FileWriter writer = new FileWriter(savedTokens)) {
|
||||
JSON_MAPPER.writerFor(type)
|
||||
.withDefaultPrettyPrinter()
|
||||
.writeValue(writer, savedRefreshTokens);
|
||||
} catch (IOException e) {
|
||||
getLogger().error("Unable to write saved refresh tokens!", e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static GeyserImpl getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
* 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
|
||||
|
@ -25,6 +25,8 @@
|
|||
|
||||
package org.geysermc.geyser;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public interface GeyserLogger {
|
||||
|
||||
/**
|
||||
|
@ -78,6 +80,15 @@ public interface GeyserLogger {
|
|||
*/
|
||||
void debug(String message);
|
||||
|
||||
/**
|
||||
* Logs an object to console if debug mode is enabled
|
||||
*
|
||||
* @param object the object to log
|
||||
*/
|
||||
default void debug(@Nullable Object object) {
|
||||
debug(String.valueOf(object));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets if the logger should print debug messages
|
||||
*
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
* 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
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
* 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
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
* 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
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
* 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
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
* 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
|
||||
|
@ -86,4 +86,13 @@ public abstract class GeyserCommand {
|
|||
public boolean isBedrockOnly() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used for permission defaults on server implementations.
|
||||
*
|
||||
* @return if this command is designated to be used only by server operators.
|
||||
*/
|
||||
public boolean isSuggestedOpOnly() {
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
* 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
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
* 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
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
* 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
|
||||
|
@ -145,4 +145,9 @@ public class DumpCommand extends GeyserCommand {
|
|||
public List<String> getSubCommands() {
|
||||
return Arrays.asList("offline", "full", "logs");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSuggestedOpOnly() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
* 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
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
* 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
|
||||
|
@ -51,4 +51,9 @@ public class ListCommand extends GeyserCommand {
|
|||
|
||||
sender.sendMessage(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSuggestedOpOnly() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
* 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
|
||||
|
@ -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.CommandSender;
|
||||
import org.geysermc.geyser.command.GeyserCommand;
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
* 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
|
||||
|
@ -54,4 +54,9 @@ public class ReloadCommand extends GeyserCommand {
|
|||
geyser.getSessionManager().disconnectAll("geyser.commands.reload.kick");
|
||||
geyser.reload();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSuggestedOpOnly() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
* 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
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
* 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
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
* 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
|
||||
|
@ -54,4 +54,9 @@ public class StopCommand extends GeyserCommand {
|
|||
|
||||
geyser.getBootstrap().onDisable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSuggestedOpOnly() {
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
* 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
|
||||
|
@ -100,4 +100,9 @@ public class VersionCommand extends GeyserCommand {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSuggestedOpOnly() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
* 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
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
* 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
|
||||
|
@ -44,6 +44,9 @@ public interface GeyserConfiguration {
|
|||
|
||||
IRemoteConfiguration getRemote();
|
||||
|
||||
List<String> getSavedUserLogins();
|
||||
|
||||
@Deprecated
|
||||
Map<String, ? extends IUserAuthenticationInfo> getUserAuths();
|
||||
|
||||
boolean isCommandSuggestions();
|
||||
|
@ -76,6 +79,10 @@ public interface GeyserConfiguration {
|
|||
|
||||
boolean isShowCoordinates();
|
||||
|
||||
boolean isDisableBedrockScaffolding();
|
||||
|
||||
boolean isAlwaysQuickChangeArmor();
|
||||
|
||||
EmoteOffhandWorkaroundOption getEmoteOffhandWorkaround();
|
||||
|
||||
String getDefaultLocale();
|
||||
|
@ -94,8 +101,14 @@ public interface GeyserConfiguration {
|
|||
|
||||
boolean isAllowCustomSkulls();
|
||||
|
||||
int getMaxVisibleCustomSkulls();
|
||||
|
||||
int getCustomSkullRenderDistance();
|
||||
|
||||
IMetricsInfo getMetrics();
|
||||
|
||||
int getPendingAuthenticationTimeout();
|
||||
|
||||
interface IBedrockConfiguration {
|
||||
|
||||
String getAddress();
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
* 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
|
||||
|
@ -35,9 +35,9 @@ import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
|
|||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.network.CIDRMatcher;
|
||||
import org.geysermc.geyser.session.auth.AuthType;
|
||||
import org.geysermc.geyser.text.AsteriskSerializer;
|
||||
import org.geysermc.geyser.network.CIDRMatcher;
|
||||
import org.geysermc.geyser.text.GeyserLocale;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -62,6 +62,9 @@ public abstract class GeyserJacksonConfiguration implements GeyserConfiguration
|
|||
private BedrockConfiguration bedrock = new BedrockConfiguration();
|
||||
private RemoteConfiguration remote = new RemoteConfiguration();
|
||||
|
||||
@JsonProperty("saved-user-logins")
|
||||
private List<String> savedUserLogins = Collections.emptyList();
|
||||
|
||||
@JsonProperty("floodgate-key-file")
|
||||
private String floodgateKeyFile = "key.pem";
|
||||
|
||||
|
@ -105,6 +108,12 @@ public abstract class GeyserJacksonConfiguration implements GeyserConfiguration
|
|||
@JsonProperty("show-coordinates")
|
||||
private boolean showCoordinates = true;
|
||||
|
||||
@JsonProperty("disable-bedrock-scaffolding")
|
||||
private boolean disableBedrockScaffolding = false;
|
||||
|
||||
@JsonProperty("always-quick-change-armor")
|
||||
private boolean alwaysQuickChangeArmor = false;
|
||||
|
||||
@JsonDeserialize(using = EmoteOffhandWorkaroundOption.Deserializer.class)
|
||||
@JsonProperty("emote-offhand-workaround")
|
||||
private EmoteOffhandWorkaroundOption emoteOffhandWorkaround = EmoteOffhandWorkaroundOption.DISABLED;
|
||||
|
@ -121,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;
|
||||
|
||||
|
@ -135,6 +150,9 @@ public abstract class GeyserJacksonConfiguration implements GeyserConfiguration
|
|||
|
||||
private MetricsInfo metrics = new MetricsInfo();
|
||||
|
||||
@JsonProperty("pending-authentication-timeout")
|
||||
private int pendingAuthenticationTimeout = 120;
|
||||
|
||||
@Getter
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public static class BedrockConfiguration implements IBedrockConfiguration {
|
||||
|
@ -228,8 +246,21 @@ public abstract class GeyserJacksonConfiguration implements GeyserConfiguration
|
|||
public static class MetricsInfo implements IMetricsInfo {
|
||||
private boolean enabled = true;
|
||||
|
||||
@JsonDeserialize(using = MetricsIdDeserializer.class)
|
||||
@JsonProperty("uuid")
|
||||
private String uniqueId = UUID.randomUUID().toString();
|
||||
|
||||
private static class MetricsIdDeserializer extends JsonDeserializer<String> {
|
||||
@Override
|
||||
public String deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
|
||||
String uuid = p.getValueAsString();
|
||||
if ("generateduuid".equals(uuid)) {
|
||||
// Compensate for configs not copied from the jar
|
||||
return UUID.randomUUID().toString();
|
||||
}
|
||||
return uuid;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@JsonProperty("scoreboard-packet-threshold")
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
* 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
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
* 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
|
||||
|
@ -40,6 +40,7 @@ import org.geysermc.geyser.text.AsteriskSerializer;
|
|||
import org.geysermc.geyser.configuration.GeyserConfiguration;
|
||||
import org.geysermc.geyser.network.MinecraftProtocol;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.util.CpuUtils;
|
||||
import org.geysermc.geyser.util.FileUtils;
|
||||
import org.geysermc.geyser.util.WebUtils;
|
||||
import org.geysermc.floodgate.util.DeviceOs;
|
||||
|
@ -54,10 +55,7 @@ import java.net.InetSocketAddress;
|
|||
import java.net.Socket;
|
||||
import java.net.UnknownHostException;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Getter
|
||||
|
@ -67,6 +65,9 @@ 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;
|
||||
private final GeyserConfiguration config;
|
||||
private final Floodgate floodgate;
|
||||
|
@ -81,6 +82,9 @@ 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");
|
||||
|
||||
try (InputStream stream = GeyserImpl.getInstance().getBootstrap().getResource("git.properties")) {
|
||||
this.gitInfo = new Properties();
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
* 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
|
||||
|
@ -32,7 +32,6 @@ import it.unimi.dsi.fastutil.objects.ObjectArrayList;
|
|||
import lombok.Setter;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.entity.factory.BaseEntityFactory;
|
||||
import org.geysermc.geyser.entity.factory.EntityFactory;
|
||||
import org.geysermc.geyser.entity.type.Entity;
|
||||
import org.geysermc.geyser.registry.Registries;
|
||||
|
@ -52,10 +51,6 @@ import java.util.function.BiConsumer;
|
|||
public record EntityDefinition<T extends Entity>(EntityFactory<T> factory, EntityType entityType, String identifier,
|
||||
float width, float height, float offset, List<EntityMetadataTranslator<? super T, ?, ?>> translators) {
|
||||
|
||||
public static <T extends Entity> Builder<T> inherited(BaseEntityFactory<T> factory, EntityDefinition<? super T> parent) {
|
||||
return inherited((EntityFactory<T>) factory, parent);
|
||||
}
|
||||
|
||||
public static <T extends Entity> Builder<T> inherited(EntityFactory<T> factory, EntityDefinition<? super T> parent) {
|
||||
return new Builder<>(factory, parent.entityType, parent.identifier, parent.width, parent.height, parent.offset, new ObjectArrayList<>(parent.translators));
|
||||
}
|
||||
|
@ -64,7 +59,6 @@ public record EntityDefinition<T extends Entity>(EntityFactory<T> factory, Entit
|
|||
return new Builder<>(factory);
|
||||
}
|
||||
|
||||
|
||||
public <M> void translateMetadata(T entity, EntityMetadata<M, ? extends MetadataType<M>> metadata) {
|
||||
EntityMetadataTranslator<? super T, M, EntityMetadata<M, ? extends MetadataType<M>>> translator = (EntityMetadataTranslator<? super T, M, EntityMetadata<M, ? extends MetadataType<M>>>) this.translators.get(metadata.getId());
|
||||
if (translator == null) {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
* 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
|
||||
|
@ -31,9 +31,6 @@ import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.FloatEnt
|
|||
import com.github.steveice10.mc.protocol.data.game.entity.type.EntityType;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
|
||||
import org.geysermc.geyser.entity.factory.BaseEntityFactory;
|
||||
import org.geysermc.geyser.entity.factory.ExperienceOrbEntityFactory;
|
||||
import org.geysermc.geyser.entity.factory.PaintingEntityFactory;
|
||||
import org.geysermc.geyser.entity.type.*;
|
||||
import org.geysermc.geyser.entity.type.living.*;
|
||||
import org.geysermc.geyser.entity.type.living.animal.*;
|
||||
|
@ -50,10 +47,11 @@ import org.geysermc.geyser.entity.type.living.monster.raid.RaidParticipantEntity
|
|||
import org.geysermc.geyser.entity.type.living.monster.raid.SpellcasterIllagerEntity;
|
||||
import org.geysermc.geyser.entity.type.living.monster.raid.VindicatorEntity;
|
||||
import org.geysermc.geyser.entity.type.player.PlayerEntity;
|
||||
import org.geysermc.geyser.translator.text.MessageTranslator;
|
||||
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;
|
||||
|
@ -66,11 +64,12 @@ 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<AnimalEntity> COW;
|
||||
public static final EntityDefinition<CowEntity> COW;
|
||||
public static final EntityDefinition<CreeperEntity> CREEPER;
|
||||
public static final EntityDefinition<WaterEntity> DOLPHIN;
|
||||
public static final EntityDefinition<DolphinEntity> DOLPHIN;
|
||||
public static final EntityDefinition<ChestedHorseEntity> DONKEY;
|
||||
public static final EntityDefinition<FireballEntity> DRAGON_FIREBALL;
|
||||
public static final EntityDefinition<ZombieEntity> DROWNED;
|
||||
|
@ -82,7 +81,7 @@ public final class EntityDefinitions {
|
|||
public static final EntityDefinition<ThrowableItemEntity> ENDER_PEARL;
|
||||
public static final EntityDefinition<EnderCrystalEntity> END_CRYSTAL;
|
||||
public static final EntityDefinition<SpellcasterIllagerEntity> EVOKER;
|
||||
public static final EntityDefinition<Entity> EVOKER_FANGS;
|
||||
public static final EntityDefinition<EvokerFangsEntity> EVOKER_FANGS;
|
||||
public static final EntityDefinition<ThrowableItemEntity> EXPERIENCE_BOTTLE;
|
||||
public static final EntityDefinition<ExpOrbEntity> EXPERIENCE_ORB;
|
||||
public static final EntityDefinition<Entity> EYE_OF_ENDER;
|
||||
|
@ -91,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;
|
||||
|
@ -135,7 +135,7 @@ public final class EntityDefinitions {
|
|||
public static final EntityDefinition<ThrowableEntity> SHULKER_BULLET;
|
||||
public static final EntityDefinition<MonsterEntity> SILVERFISH;
|
||||
public static final EntityDefinition<SkeletonEntity> SKELETON;
|
||||
public static final EntityDefinition<AbstractHorseEntity> SKELETON_HORSE;
|
||||
public static final EntityDefinition<SkeletonHorseEntity> SKELETON_HORSE;
|
||||
public static final EntityDefinition<SlimeEntity> SLIME;
|
||||
public static final EntityDefinition<FireballEntity> SMALL_FIREBALL;
|
||||
public static final EntityDefinition<ThrowableItemEntity> SNOWBALL;
|
||||
|
@ -146,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;
|
||||
|
@ -156,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;
|
||||
|
@ -163,7 +165,7 @@ public final class EntityDefinitions {
|
|||
public static final EntityDefinition<WolfEntity> WOLF;
|
||||
public static final EntityDefinition<ZoglinEntity> ZOGLIN;
|
||||
public static final EntityDefinition<ZombieEntity> ZOMBIE;
|
||||
public static final EntityDefinition<AbstractHorseEntity> ZOMBIE_HORSE;
|
||||
public static final EntityDefinition<ZombieHorseEntity> ZOMBIE_HORSE;
|
||||
public static final EntityDefinition<ZombieVillagerEntity> ZOMBIE_VILLAGER;
|
||||
public static final EntityDefinition<ZombifiedPiglinEntity> ZOMBIFIED_PIGLIN;
|
||||
|
||||
|
@ -177,14 +179,14 @@ public final class EntityDefinitions {
|
|||
public static final EntityDefinition<WitherSkullEntity> WITHER_SKULL_DANGEROUS;
|
||||
|
||||
static {
|
||||
EntityDefinition<Entity> entityBase = EntityDefinition.builder((BaseEntityFactory<Entity>) Entity::new)
|
||||
EntityDefinition<Entity> entityBase = EntityDefinition.builder(Entity::new)
|
||||
.addTranslator(MetadataType.BYTE, Entity::setFlags)
|
||||
.addTranslator(MetadataType.INT, Entity::setAir) // Air/bubbles
|
||||
.addTranslator(MetadataType.OPTIONAL_CHAT, Entity::setDisplayName)
|
||||
.addTranslator(MetadataType.BOOLEAN, Entity::setDisplayNameVisible)
|
||||
.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::setPose)
|
||||
.addTranslator(MetadataType.POSE, (entity, entityMetadata) -> entity.setPose(entityMetadata.getValue()))
|
||||
.addTranslator(MetadataType.INT, Entity::setFreezing)
|
||||
.build();
|
||||
|
||||
|
@ -212,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)
|
||||
|
@ -224,11 +229,11 @@ public final class EntityDefinitions {
|
|||
.addTranslator(MetadataType.BOOLEAN,
|
||||
(enderCrystalEntity, entityMetadata) -> enderCrystalEntity.setFlag(EntityFlag.SHOW_BOTTOM, ((BooleanEntityMetadata) entityMetadata).getPrimitiveValue())) // There is a base located on the ender crystal
|
||||
.build();
|
||||
EXPERIENCE_ORB = EntityDefinition.inherited((ExperienceOrbEntityFactory) ExpOrbEntity::new, entityBase)
|
||||
EXPERIENCE_ORB = EntityDefinition.<ExpOrbEntity>inherited(null, entityBase)
|
||||
.type(EntityType.EXPERIENCE_ORB)
|
||||
.identifier("minecraft:xp_orb")
|
||||
.build();
|
||||
EVOKER_FANGS = EntityDefinition.inherited(entityBase.factory(), entityBase)
|
||||
EVOKER_FANGS = EntityDefinition.builder(EvokerFangsEntity::new) // No entity metadata to listen to as of 1.18.1
|
||||
.type(EntityType.EVOKER_FANGS)
|
||||
.height(0.8f).width(0.5f)
|
||||
.identifier("minecraft:evocation_fang")
|
||||
|
@ -275,8 +280,9 @@ public final class EntityDefinitions {
|
|||
.type(EntityType.LLAMA_SPIT)
|
||||
.heightAndWidth(0.25f)
|
||||
.build();
|
||||
PAINTING = EntityDefinition.inherited((PaintingEntityFactory) PaintingEntity::new, entityBase)
|
||||
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)
|
||||
|
@ -444,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)
|
||||
|
@ -462,7 +472,7 @@ public final class EntityDefinitions {
|
|||
.addTranslator(MetadataType.BOOLEAN, (entity, entityMetadata) -> entity.setFlag(EntityFlag.POWERED, ((BooleanEntityMetadata) entityMetadata).getPrimitiveValue()))
|
||||
.addTranslator(MetadataType.BOOLEAN, CreeperEntity::setIgnited)
|
||||
.build();
|
||||
DOLPHIN = EntityDefinition.inherited(WaterEntity::new, mobEntityBase)
|
||||
DOLPHIN = EntityDefinition.inherited(DolphinEntity::new, mobEntityBase)
|
||||
.type(EntityType.DOLPHIN)
|
||||
.height(0.6f).width(0.9f)
|
||||
//TODO check
|
||||
|
@ -553,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)
|
||||
|
@ -637,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)
|
||||
|
@ -726,7 +745,7 @@ public final class EntityDefinitions {
|
|||
.type(EntityType.CHICKEN)
|
||||
.height(0.7f).width(0.4f)
|
||||
.build();
|
||||
COW = EntityDefinition.inherited(AnimalEntity::new, ageableEntityBase)
|
||||
COW = EntityDefinition.inherited(CowEntity::new, ageableEntityBase)
|
||||
.type(EntityType.COW)
|
||||
.height(1.4f).width(0.9f)
|
||||
.build();
|
||||
|
@ -738,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)
|
||||
|
@ -748,14 +773,14 @@ public final class EntityDefinitions {
|
|||
.height(1.3f).width(0.9f)
|
||||
.addTranslator(MetadataType.BOOLEAN, GoatEntity::setScreamer)
|
||||
.build();
|
||||
MOOSHROOM = EntityDefinition.inherited(MooshroomEntity::new, ageableEntityBase) // TODO remove class
|
||||
MOOSHROOM = EntityDefinition.inherited(MooshroomEntity::new, ageableEntityBase)
|
||||
.type(EntityType.MOOSHROOM)
|
||||
.height(1.4f).width(0.9f)
|
||||
.addTranslator(MetadataType.STRING, (entity, entityMetadata) -> entity.getDirtyMetadata().put(EntityData.VARIANT, entityMetadata.getValue().equals("brown") ? 1 : 0))
|
||||
.addTranslator(MetadataType.STRING, MooshroomEntity::setVariant)
|
||||
.build();
|
||||
OCELOT = EntityDefinition.inherited(OcelotEntity::new, ageableEntityBase)
|
||||
.type(EntityType.OCELOT)
|
||||
.height(0.35f).width(0.3f)
|
||||
.height(0.7f).width(0.6f)
|
||||
.addTranslator(MetadataType.BOOLEAN, (ocelotEntity, entityMetadata) -> ocelotEntity.setFlag(EntityFlag.TRUSTING, ((BooleanEntityMetadata) entityMetadata).getPrimitiveValue()))
|
||||
.build();
|
||||
PANDA = EntityDefinition.inherited(PandaEntity::new, ageableEntityBase)
|
||||
|
@ -786,7 +811,7 @@ public final class EntityDefinitions {
|
|||
.build();
|
||||
SHEEP = EntityDefinition.inherited(SheepEntity::new, ageableEntityBase)
|
||||
.type(EntityType.SHEEP)
|
||||
.heightAndWidth(0.9f)
|
||||
.height(1.3f).width(0.9f)
|
||||
.addTranslator(MetadataType.BYTE, SheepEntity::setSheepFlags)
|
||||
.build();
|
||||
STRIDER = EntityDefinition.inherited(StriderEntity::new, ageableEntityBase)
|
||||
|
@ -835,11 +860,11 @@ public final class EntityDefinitions {
|
|||
.height(1.6f).width(1.3965f)
|
||||
.addTranslator(MetadataType.INT, HorseEntity::setHorseVariant)
|
||||
.build();
|
||||
SKELETON_HORSE = EntityDefinition.inherited(abstractHorseEntityBase.factory(), abstractHorseEntityBase)
|
||||
SKELETON_HORSE = EntityDefinition.inherited(SkeletonHorseEntity::new, abstractHorseEntityBase)
|
||||
.type(EntityType.SKELETON_HORSE)
|
||||
.height(1.6f).width(1.3965f)
|
||||
.build();
|
||||
ZOMBIE_HORSE = EntityDefinition.inherited(abstractHorseEntityBase.factory(), abstractHorseEntityBase)
|
||||
ZOMBIE_HORSE = EntityDefinition.inherited(ZombieHorseEntity::new, abstractHorseEntityBase)
|
||||
.type(EntityType.ZOMBIE_HORSE)
|
||||
.height(1.6f).width(1.3965f)
|
||||
.build();
|
||||
|
@ -874,7 +899,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)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
* 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
|
||||
|
@ -34,7 +34,7 @@ import java.util.Map;
|
|||
/**
|
||||
* A write-only wrapper for temporarily storing entity metadata that will be sent to Bedrock.
|
||||
*/
|
||||
public class GeyserDirtyMetadata {
|
||||
public final class GeyserDirtyMetadata {
|
||||
private final Map<EntityData, Object> metadata = new Object2ObjectLinkedOpenHashMap<>();
|
||||
|
||||
public void put(EntityData entityData, Object value) {
|
||||
|
@ -52,4 +52,9 @@ public class GeyserDirtyMetadata {
|
|||
public boolean hasEntries() {
|
||||
return !metadata.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return metadata.toString();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,293 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.entity;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.type.EntityType;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
|
||||
import lombok.Getter;
|
||||
import org.geysermc.geyser.entity.type.Entity;
|
||||
import org.geysermc.geyser.entity.type.living.MobEntity;
|
||||
import org.geysermc.geyser.entity.type.living.animal.AnimalEntity;
|
||||
import org.geysermc.geyser.entity.type.living.animal.horse.HorseEntity;
|
||||
import org.geysermc.geyser.entity.type.living.animal.tameable.CatEntity;
|
||||
import org.geysermc.geyser.entity.type.living.animal.tameable.WolfEntity;
|
||||
import org.geysermc.geyser.entity.type.living.merchant.VillagerEntity;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.registry.type.ItemMapping;
|
||||
|
||||
import java.util.EnumSet;
|
||||
import java.util.Set;
|
||||
|
||||
public class InteractiveTagManager {
|
||||
/**
|
||||
* All entity types that can be leashed on Java Edition
|
||||
*/
|
||||
private static final Set<EntityType> LEASHABLE_MOB_TYPES = EnumSet.of(EntityType.AXOLOTL, EntityType.BEE, EntityType.CAT, EntityType.CHICKEN,
|
||||
EntityType.COW, EntityType.DOLPHIN, EntityType.DONKEY, EntityType.FOX, EntityType.GOAT, EntityType.GLOW_SQUID, EntityType.HOGLIN,
|
||||
EntityType.HORSE, EntityType.SKELETON_HORSE, EntityType.ZOMBIE_HORSE, EntityType.IRON_GOLEM, EntityType.LLAMA,
|
||||
EntityType.TRADER_LLAMA, EntityType.MOOSHROOM, EntityType.MULE, EntityType.OCELOT, EntityType.PARROT, EntityType.PIG,
|
||||
EntityType.POLAR_BEAR, EntityType.RABBIT, EntityType.SHEEP, EntityType.SNOW_GOLEM, EntityType.SQUID, EntityType.STRIDER,
|
||||
EntityType.WOLF, EntityType.ZOGLIN);
|
||||
|
||||
private static final Set<EntityType> SADDLEABLE_WHEN_TAMED_MOB_TYPES = EnumSet.of(EntityType.DONKEY, EntityType.HORSE,
|
||||
EntityType.ZOMBIE_HORSE, EntityType.MULE);
|
||||
|
||||
/**
|
||||
* Update the suggestion that the client currently has on their screen for this entity (for example, "Feed" or "Ride")
|
||||
*
|
||||
* @param session the Bedrock client session
|
||||
* @param interactEntity the entity that the client is currently facing.
|
||||
*/
|
||||
public static void updateTag(GeyserSession session, Entity interactEntity) {
|
||||
ItemMapping mapping = session.getPlayerInventory().getItemInHand().getMapping(session);
|
||||
String javaIdentifierStripped = mapping.getJavaIdentifier().replace("minecraft:", "");
|
||||
EntityType entityType = interactEntity.getDefinition().entityType();
|
||||
if (entityType == null) {
|
||||
// Likely a technical entity; we don't need to worry about this
|
||||
return;
|
||||
}
|
||||
|
||||
InteractiveTag interactiveTag = InteractiveTag.NONE;
|
||||
|
||||
if (interactEntity instanceof MobEntity mobEntity && mobEntity.getLeashHolderBedrockId() == session.getPlayerEntity().getGeyserId()) {
|
||||
// Unleash the entity
|
||||
interactiveTag = InteractiveTag.REMOVE_LEASH;
|
||||
} else if (javaIdentifierStripped.equals("saddle") && !interactEntity.getFlag(EntityFlag.SADDLED) &&
|
||||
((SADDLEABLE_WHEN_TAMED_MOB_TYPES.contains(entityType) && interactEntity.getFlag(EntityFlag.TAMED) && !session.isSneaking()) ||
|
||||
entityType == EntityType.PIG || entityType == EntityType.STRIDER)) {
|
||||
// Entity can be saddled and the conditions meet (entity can be saddled and, if needed, is tamed)
|
||||
interactiveTag = InteractiveTag.SADDLE;
|
||||
} else if (javaIdentifierStripped.equals("name_tag") && session.getPlayerInventory().getItemInHand().getNbt() != null &&
|
||||
session.getPlayerInventory().getItemInHand().getNbt().contains("display")) {
|
||||
// Holding a named name tag
|
||||
interactiveTag = InteractiveTag.NAME;
|
||||
} else if (interactEntity instanceof MobEntity mobEntity &&javaIdentifierStripped.equals("lead")
|
||||
&& LEASHABLE_MOB_TYPES.contains(entityType) && mobEntity.getLeashHolderBedrockId() == -1L) {
|
||||
// Holding a leash and the mob is leashable for sure
|
||||
// (Plugins can change this behavior so that's something to look into in the far far future)
|
||||
interactiveTag = InteractiveTag.LEASH;
|
||||
} else if (interactEntity instanceof AnimalEntity && ((AnimalEntity) interactEntity).canEat(javaIdentifierStripped, mapping)) {
|
||||
// This animal can be fed
|
||||
interactiveTag = InteractiveTag.FEED;
|
||||
} else {
|
||||
switch (entityType) {
|
||||
case BOAT:
|
||||
if (interactEntity.getPassengers().size() < 2) {
|
||||
interactiveTag = InteractiveTag.BOARD_BOAT;
|
||||
}
|
||||
break;
|
||||
case CAT:
|
||||
if (interactEntity.getFlag(EntityFlag.TAMED) &&
|
||||
((CatEntity) interactEntity).getOwnerBedrockId() == session.getPlayerEntity().getGeyserId()) {
|
||||
// Tamed and owned by player - can sit/stand
|
||||
interactiveTag = interactEntity.getFlag(EntityFlag.SITTING) ? InteractiveTag.STAND : InteractiveTag.SIT;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case MOOSHROOM:
|
||||
// Shear the mooshroom
|
||||
if (javaIdentifierStripped.equals("shears")) {
|
||||
interactiveTag = InteractiveTag.MOOSHROOM_SHEAR;
|
||||
break;
|
||||
}
|
||||
// Bowls are acceptable here
|
||||
else if (javaIdentifierStripped.equals("bowl")) {
|
||||
interactiveTag = InteractiveTag.MOOSHROOM_MILK_STEW;
|
||||
break;
|
||||
}
|
||||
// Fall down to COW as this works on mooshrooms
|
||||
case COW:
|
||||
if (javaIdentifierStripped.equals("bucket")) {
|
||||
// Milk the cow
|
||||
interactiveTag = InteractiveTag.MILK;
|
||||
}
|
||||
break;
|
||||
case CREEPER:
|
||||
if (javaIdentifierStripped.equals("flint_and_steel")) {
|
||||
// Today I learned that you can ignite a creeper with flint and steel! Huh.
|
||||
interactiveTag = InteractiveTag.IGNITE_CREEPER;
|
||||
}
|
||||
break;
|
||||
case DONKEY:
|
||||
case LLAMA:
|
||||
case MULE:
|
||||
if (interactEntity.getFlag(EntityFlag.TAMED) && !interactEntity.getFlag(EntityFlag.CHESTED)
|
||||
&& javaIdentifierStripped.equals("chest")) {
|
||||
// Can attach a chest
|
||||
interactiveTag = InteractiveTag.ATTACH_CHEST;
|
||||
break;
|
||||
}
|
||||
// Intentional fall-through
|
||||
case HORSE:
|
||||
case SKELETON_HORSE:
|
||||
case TRADER_LLAMA:
|
||||
case ZOMBIE_HORSE:
|
||||
boolean tamed = interactEntity.getFlag(EntityFlag.TAMED);
|
||||
if (session.isSneaking() && tamed && (interactEntity instanceof HorseEntity || interactEntity.getFlag(EntityFlag.CHESTED))) {
|
||||
interactiveTag = InteractiveTag.OPEN_CONTAINER;
|
||||
break;
|
||||
}
|
||||
if (!interactEntity.getFlag(EntityFlag.BABY)) {
|
||||
// Can't ride a baby
|
||||
if (tamed) {
|
||||
interactiveTag = InteractiveTag.RIDE_HORSE;
|
||||
} else if (mapping.getJavaId() == 0) {
|
||||
// Can't hide an untamed entity without having your hand empty
|
||||
interactiveTag = InteractiveTag.MOUNT;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MINECART:
|
||||
if (interactEntity.getPassengers().isEmpty()) {
|
||||
interactiveTag = InteractiveTag.RIDE_MINECART;
|
||||
}
|
||||
break;
|
||||
case CHEST_MINECART:
|
||||
case COMMAND_BLOCK_MINECART:
|
||||
case HOPPER_MINECART:
|
||||
interactiveTag = InteractiveTag.OPEN_CONTAINER;
|
||||
break;
|
||||
case PIG:
|
||||
if (interactEntity.getFlag(EntityFlag.SADDLED)) {
|
||||
interactiveTag = InteractiveTag.MOUNT;
|
||||
}
|
||||
break;
|
||||
case PIGLIN:
|
||||
if (!interactEntity.getFlag(EntityFlag.BABY) && javaIdentifierStripped.equals("gold_ingot")) {
|
||||
interactiveTag = InteractiveTag.BARTER;
|
||||
}
|
||||
break;
|
||||
case SHEEP:
|
||||
if (!interactEntity.getFlag(EntityFlag.SHEARED)) {
|
||||
if (javaIdentifierStripped.equals("shears")) {
|
||||
// Shear the sheep
|
||||
interactiveTag = InteractiveTag.SHEAR;
|
||||
} else if (javaIdentifierStripped.contains("_dye")) {
|
||||
// Dye the sheep
|
||||
interactiveTag = InteractiveTag.DYE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case STRIDER:
|
||||
if (interactEntity.getFlag(EntityFlag.SADDLED)) {
|
||||
interactiveTag = InteractiveTag.RIDE_STRIDER;
|
||||
}
|
||||
break;
|
||||
case VILLAGER:
|
||||
VillagerEntity villager = (VillagerEntity) interactEntity;
|
||||
if (villager.isCanTradeWith() && !villager.isBaby()) { // Not a nitwit, has a profession and is not a baby
|
||||
interactiveTag = InteractiveTag.TRADE;
|
||||
}
|
||||
break;
|
||||
case WANDERING_TRADER:
|
||||
interactiveTag = InteractiveTag.TRADE; // Since you can always trade with a wandering villager, presumably.
|
||||
break;
|
||||
case WOLF:
|
||||
if (javaIdentifierStripped.equals("bone") && !interactEntity.getFlag(EntityFlag.TAMED)) {
|
||||
// Bone and untamed - can tame
|
||||
interactiveTag = InteractiveTag.TAME;
|
||||
} else if (interactEntity.getFlag(EntityFlag.TAMED) &&
|
||||
((WolfEntity) interactEntity).getOwnerBedrockId() == session.getPlayerEntity().getGeyserId()) {
|
||||
// Tamed and owned by player - can sit/stand
|
||||
interactiveTag = interactEntity.getFlag(EntityFlag.SITTING) ? InteractiveTag.STAND : InteractiveTag.SIT;
|
||||
}
|
||||
break;
|
||||
case ZOMBIE_VILLAGER:
|
||||
// We can't guarantee the existence of the weakness effect so we just always show it.
|
||||
if (javaIdentifierStripped.equals("golden_apple")) {
|
||||
interactiveTag = InteractiveTag.CURE;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
session.getPlayerEntity().getDirtyMetadata().put(EntityData.INTERACTIVE_TAG, interactiveTag.getValue());
|
||||
session.getPlayerEntity().updateBedrockMetadata();
|
||||
}
|
||||
|
||||
/**
|
||||
* All interactive tags in enum form. For potential API usage.
|
||||
*/
|
||||
public enum InteractiveTag {
|
||||
NONE((Void) null),
|
||||
IGNITE_CREEPER("creeper"),
|
||||
EDIT,
|
||||
LEAVE_BOAT("exit.boat"),
|
||||
FEED,
|
||||
FISH("fishing"),
|
||||
MILK,
|
||||
MOOSHROOM_SHEAR("mooshear"),
|
||||
MOOSHROOM_MILK_STEW("moostew"),
|
||||
BOARD_BOAT("ride.boat"),
|
||||
RIDE_MINECART("ride.minecart"),
|
||||
RIDE_HORSE("ride.horse"),
|
||||
RIDE_STRIDER("ride.strider"),
|
||||
SHEAR,
|
||||
SIT,
|
||||
STAND,
|
||||
TALK,
|
||||
TAME,
|
||||
DYE,
|
||||
CURE,
|
||||
OPEN_CONTAINER("opencontainer"),
|
||||
CREATE_MAP("createMap"),
|
||||
TAKE_PICTURE("takepicture"),
|
||||
SADDLE,
|
||||
MOUNT,
|
||||
BOOST,
|
||||
WRITE,
|
||||
LEASH,
|
||||
REMOVE_LEASH("unleash"),
|
||||
NAME,
|
||||
ATTACH_CHEST("attachchest"),
|
||||
TRADE,
|
||||
POSE_ARMOR_STAND("armorstand.pose"),
|
||||
EQUIP_ARMOR_STAND("armorstand.equip"),
|
||||
READ,
|
||||
WAKE_VILLAGER("wakevillager"),
|
||||
BARTER;
|
||||
|
||||
/**
|
||||
* The full string that should be passed on to the client.
|
||||
*/
|
||||
@Getter
|
||||
private final String value;
|
||||
|
||||
InteractiveTag(Void isNone) {
|
||||
this.value = "";
|
||||
}
|
||||
|
||||
InteractiveTag(String value) {
|
||||
this.value = "action.interact." + value;
|
||||
}
|
||||
|
||||
InteractiveTag() {
|
||||
this.value = "action.interact." + name().toLowerCase();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
* 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
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
* 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
|
||||
|
@ -25,7 +25,17 @@
|
|||
|
||||
package org.geysermc.geyser.entity.factory;
|
||||
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import org.geysermc.geyser.entity.EntityDefinition;
|
||||
import org.geysermc.geyser.entity.type.Entity;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Represents a constructor to create an entity.
|
||||
*/
|
||||
public interface EntityFactory<T extends Entity> {
|
||||
|
||||
T create(GeyserSession session, int javaId, long bedrockId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
* 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
|
||||
|
@ -36,7 +36,7 @@ import java.util.UUID;
|
|||
|
||||
public class AbstractArrowEntity extends Entity {
|
||||
|
||||
public AbstractArrowEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
public AbstractArrowEntity(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);
|
||||
|
||||
// Set the correct texture if using the resource pack
|
||||
|
@ -70,8 +70,8 @@ public class AbstractArrowEntity extends Entity {
|
|||
super.setMotion(motion);
|
||||
|
||||
double horizontalSpeed = Math.sqrt(motion.getX() * motion.getX() + motion.getZ() * motion.getZ());
|
||||
this.yaw = (float) Math.toDegrees(Math.atan2(motion.getX(), motion.getZ()));
|
||||
this.pitch = (float) Math.toDegrees(Math.atan2(motion.getY(), horizontalSpeed));
|
||||
this.headYaw = yaw;
|
||||
setYaw((float) Math.toDegrees(Math.atan2(motion.getX(), motion.getZ())));
|
||||
setPitch((float) Math.toDegrees(Math.atan2(motion.getY(), horizontalSpeed)));
|
||||
setHeadYaw(getYaw());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
* 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
|
||||
|
@ -39,7 +39,7 @@ import java.util.UUID;
|
|||
|
||||
public class AreaEffectCloudEntity extends Entity {
|
||||
|
||||
public AreaEffectCloudEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
public AreaEffectCloudEntity(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);
|
||||
}
|
||||
|
||||
|
@ -47,18 +47,19 @@ public class AreaEffectCloudEntity extends Entity {
|
|||
protected void initializeMetadata() {
|
||||
super.initializeMetadata();
|
||||
// Without this the cloud doesn't appear,
|
||||
dirtyMetadata.put(EntityData.AREA_EFFECT_CLOUD_DURATION, 600);
|
||||
dirtyMetadata.put(EntityData.AREA_EFFECT_CLOUD_DURATION, Integer.MAX_VALUE);
|
||||
|
||||
// This disabled client side shrink of the cloud
|
||||
dirtyMetadata.put(EntityData.AREA_EFFECT_CLOUD_RADIUS, 0.0f);
|
||||
dirtyMetadata.put(EntityData.AREA_EFFECT_CLOUD_CHANGE_RATE, -0.005f);
|
||||
dirtyMetadata.put(EntityData.AREA_EFFECT_CLOUD_CHANGE_ON_PICKUP, -0.5f);
|
||||
dirtyMetadata.put(EntityData.AREA_EFFECT_CLOUD_CHANGE_RATE, Float.MIN_VALUE);
|
||||
dirtyMetadata.put(EntityData.AREA_EFFECT_CLOUD_CHANGE_ON_PICKUP, Float.MIN_VALUE);
|
||||
|
||||
setFlag(EntityFlag.FIRE_IMMUNE, true);
|
||||
}
|
||||
|
||||
public void setRadius(FloatEntityMetadata entityMetadata) {
|
||||
float value = entityMetadata.getPrimitiveValue();
|
||||
// Anything less than 0.5 will cause the cloud to despawn
|
||||
float value = Math.max(entityMetadata.getPrimitiveValue(), 0.5f);
|
||||
dirtyMetadata.put(EntityData.AREA_EFFECT_CLOUD_RADIUS, value);
|
||||
dirtyMetadata.put(EntityData.BOUNDING_BOX_WIDTH, 2.0f * value);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
* 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
|
||||
|
@ -27,6 +27,7 @@ package org.geysermc.geyser.entity.type;
|
|||
|
||||
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.packet.AnimatePacket;
|
||||
|
@ -35,6 +36,8 @@ import lombok.Getter;
|
|||
import org.geysermc.geyser.entity.EntityDefinition;
|
||||
import org.geysermc.geyser.entity.EntityDefinitions;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.util.InteractionResult;
|
||||
import org.geysermc.geyser.util.InteractiveTag;
|
||||
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
@ -65,7 +68,7 @@ public class BoatEntity extends Entity {
|
|||
// Looks too fast and too choppy with 0.1f, which is how I believe the Microsoftian client handles it
|
||||
private final float ROWING_SPEED = 0.05f;
|
||||
|
||||
public BoatEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
public BoatEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
// Initial rotation is incorrect
|
||||
super(session, entityId, geyserId, uuid, definition, position.add(0d, definition.offset(), 0d), motion, yaw + 90, 0, yaw + 90);
|
||||
|
||||
|
@ -78,14 +81,18 @@ public class BoatEntity extends Entity {
|
|||
public void moveAbsolute(Vector3f position, float yaw, float pitch, float headYaw, boolean isOnGround, boolean teleported) {
|
||||
// We don't include the rotation (y) as it causes the boat to appear sideways
|
||||
setPosition(position.add(0d, this.definition.offset(), 0d));
|
||||
this.yaw = yaw + 90;
|
||||
this.headYaw = yaw + 90;
|
||||
setYaw(yaw + 90);
|
||||
setHeadYaw(yaw + 90);
|
||||
setOnGround(isOnGround);
|
||||
|
||||
MoveEntityAbsolutePacket moveEntityPacket = new MoveEntityAbsolutePacket();
|
||||
moveEntityPacket.setRuntimeEntityId(geyserId);
|
||||
// Minimal glitching when ClientboundMoveVehiclePacket is sent
|
||||
moveEntityPacket.setPosition(session.getRidingVehicleEntity() == this ? position.up(EntityDefinitions.PLAYER.offset() - this.definition.offset()) : this.position);
|
||||
if (session.getPlayerEntity().getVehicle() == this && session.getPlayerEntity().isRidingInFront()) {
|
||||
// Minimal glitching when ClientboundMoveVehiclePacket is sent
|
||||
moveEntityPacket.setPosition(position.up(EntityDefinitions.PLAYER.offset() - this.definition.offset()));
|
||||
} else {
|
||||
moveEntityPacket.setPosition(this.position);
|
||||
}
|
||||
moveEntityPacket.setRotation(getBedrockRotation());
|
||||
moveEntityPacket.setOnGround(isOnGround);
|
||||
moveEntityPacket.setTeleported(teleported);
|
||||
|
@ -128,7 +135,7 @@ public class BoatEntity extends Entity {
|
|||
paddleTimeLeft = 0f;
|
||||
if (!this.passengers.isEmpty()) {
|
||||
// Get the entity by the first stored passenger and convey motion in this manner
|
||||
Entity entity = session.getEntityCache().getEntityByJavaId(this.passengers.iterator().nextLong());
|
||||
Entity entity = this.passengers.get(0);
|
||||
if (entity != null) {
|
||||
updateLeftPaddle(session, entity);
|
||||
}
|
||||
|
@ -144,7 +151,7 @@ public class BoatEntity extends Entity {
|
|||
if (isPaddlingRight) {
|
||||
paddleTimeRight = 0f;
|
||||
if (!this.passengers.isEmpty()) {
|
||||
Entity entity = session.getEntityCache().getEntityByJavaId(this.passengers.iterator().nextLong());
|
||||
Entity entity = this.passengers.get(0);
|
||||
if (entity != null) {
|
||||
updateRightPaddle(session, entity);
|
||||
}
|
||||
|
@ -154,6 +161,27 @@ public class BoatEntity extends Entity {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected InteractiveTag testInteraction(Hand hand) {
|
||||
if (session.isSneaking()) {
|
||||
return InteractiveTag.NONE;
|
||||
} else if (passengers.size() < 2) {
|
||||
return InteractiveTag.BOARD_BOAT;
|
||||
} else {
|
||||
return InteractiveTag.NONE;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public InteractionResult interact(Hand hand) {
|
||||
if (session.isSneaking()) {
|
||||
return InteractionResult.PASS;
|
||||
} else {
|
||||
// TODO: the client also checks for "out of control" ticks
|
||||
return InteractionResult.SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
private void updateLeftPaddle(GeyserSession session, Entity rower) {
|
||||
if (isPaddlingLeft) {
|
||||
paddleTimeLeft += ROWING_SPEED;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
* 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
|
||||
|
@ -25,16 +25,22 @@
|
|||
|
||||
package org.geysermc.geyser.entity.type;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.math.vector.Vector3i;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
|
||||
import com.nukkitx.protocol.bedrock.data.inventory.ContainerType;
|
||||
import com.nukkitx.protocol.bedrock.packet.ContainerOpenPacket;
|
||||
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 CommandBlockMinecartEntity extends DefaultBlockMinecartEntity {
|
||||
|
||||
public CommandBlockMinecartEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
public CommandBlockMinecartEntity(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);
|
||||
}
|
||||
|
||||
|
@ -55,4 +61,30 @@ public class CommandBlockMinecartEntity extends DefaultBlockMinecartEntity {
|
|||
dirtyMetadata.put(EntityData.DISPLAY_ITEM, session.getBlockMappings().getCommandBlockRuntimeId());
|
||||
dirtyMetadata.put(EntityData.DISPLAY_OFFSET, 6);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected InteractiveTag testInteraction(Hand hand) {
|
||||
if (session.canUseCommandBlocks()) {
|
||||
return InteractiveTag.OPEN_CONTAINER;
|
||||
} else {
|
||||
return InteractiveTag.NONE;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public InteractionResult interact(Hand hand) {
|
||||
if (session.canUseCommandBlocks()) {
|
||||
// Client-side GUI required
|
||||
ContainerOpenPacket openPacket = new ContainerOpenPacket();
|
||||
openPacket.setBlockPosition(Vector3i.ZERO);
|
||||
openPacket.setId((byte) 1);
|
||||
openPacket.setType(ContainerType.COMMAND_BLOCK);
|
||||
openPacket.setUniqueEntityId(geyserId);
|
||||
session.sendUpstreamPacket(openPacket);
|
||||
|
||||
return InteractionResult.SUCCESS;
|
||||
} else {
|
||||
return InteractionResult.PASS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
* 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
|
||||
|
@ -43,7 +43,7 @@ public class DefaultBlockMinecartEntity extends MinecartEntity {
|
|||
public int customBlockOffset = 0;
|
||||
public boolean showCustomBlock = false;
|
||||
|
||||
public DefaultBlockMinecartEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
public DefaultBlockMinecartEntity(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);
|
||||
|
||||
dirtyMetadata.put(EntityData.CUSTOM_DISPLAY, (byte) 1);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
* 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
|
||||
|
@ -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;
|
||||
|
@ -39,7 +38,7 @@ import java.util.UUID;
|
|||
|
||||
public class EnderCrystalEntity extends Entity {
|
||||
|
||||
public EnderCrystalEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
public EnderCrystalEntity(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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
* 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
|
||||
|
@ -30,16 +30,14 @@ import com.github.steveice10.mc.protocol.data.game.entity.metadata.Pose;
|
|||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanEntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.type.EntityType;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityEventType;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityFlags;
|
||||
import com.nukkitx.protocol.bedrock.packet.AddEntityPacket;
|
||||
import com.nukkitx.protocol.bedrock.packet.MoveEntityAbsolutePacket;
|
||||
import com.nukkitx.protocol.bedrock.packet.RemoveEntityPacket;
|
||||
import com.nukkitx.protocol.bedrock.packet.SetEntityDataPacket;
|
||||
import it.unimi.dsi.fastutil.longs.LongOpenHashSet;
|
||||
import com.nukkitx.protocol.bedrock.packet.*;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
@ -48,8 +46,13 @@ import org.geysermc.geyser.entity.EntityDefinition;
|
|||
import org.geysermc.geyser.entity.GeyserDirtyMetadata;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.translator.text.MessageTranslator;
|
||||
import org.geysermc.geyser.util.EntityUtils;
|
||||
import org.geysermc.geyser.util.InteractionResult;
|
||||
import org.geysermc.geyser.util.InteractiveTag;
|
||||
import org.geysermc.geyser.util.MathUtils;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
|
@ -58,7 +61,7 @@ import java.util.UUID;
|
|||
public class Entity {
|
||||
protected final GeyserSession session;
|
||||
|
||||
protected long entityId;
|
||||
protected int entityId;
|
||||
protected final long geyserId;
|
||||
protected UUID uuid;
|
||||
|
||||
|
@ -79,6 +82,9 @@ public class Entity {
|
|||
|
||||
protected EntityDefinition<?> definition;
|
||||
|
||||
/**
|
||||
* Indicates if the entity has been initialized and spawned
|
||||
*/
|
||||
protected boolean valid;
|
||||
|
||||
/* Metadata about this specific entity */
|
||||
|
@ -88,9 +94,12 @@ public class Entity {
|
|||
private float boundingBoxWidth;
|
||||
@Setter(AccessLevel.NONE)
|
||||
protected String nametag = "";
|
||||
@Setter(AccessLevel.NONE)
|
||||
protected boolean silent = false;
|
||||
/* Metadata end */
|
||||
|
||||
protected LongOpenHashSet passengers = new LongOpenHashSet();
|
||||
protected List<Entity> passengers = Collections.emptyList();
|
||||
protected Entity vehicle;
|
||||
/**
|
||||
* A container to store temporary metadata before it's sent to Bedrock.
|
||||
*/
|
||||
|
@ -109,7 +118,7 @@ public class Entity {
|
|||
@Setter(AccessLevel.PROTECTED) // For players
|
||||
private boolean flagsDirty = false;
|
||||
|
||||
public Entity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
public Entity(GeyserSession session, int entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
this.session = session;
|
||||
|
||||
this.entityId = entityId;
|
||||
|
@ -134,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() {
|
||||
|
@ -181,11 +196,11 @@ public class Entity {
|
|||
public boolean despawnEntity() {
|
||||
if (!valid) return true;
|
||||
|
||||
for (long passenger : passengers) { // Make sure all passengers on the despawned entity are updated
|
||||
Entity entity = session.getEntityCache().getEntityByJavaId(passenger);
|
||||
if (entity == null) continue;
|
||||
entity.setFlag(EntityFlag.RIDING, false);
|
||||
entity.updateBedrockMetadata();
|
||||
for (Entity passenger : passengers) { // Make sure all passengers on the despawned entity are updated
|
||||
if (passenger == null) continue;
|
||||
passenger.setVehicle(null);
|
||||
passenger.setFlag(EntityFlag.RIDING, false);
|
||||
passenger.updateBedrockMetadata();
|
||||
}
|
||||
|
||||
RemoveEntityPacket removeEntityPacket = new RemoveEntityPacket();
|
||||
|
@ -197,7 +212,7 @@ public class Entity {
|
|||
}
|
||||
|
||||
public void moveRelative(double relX, double relY, double relZ, float yaw, float pitch, boolean isOnGround) {
|
||||
moveRelative(relX, relY, relZ, yaw, pitch, this.headYaw, isOnGround);
|
||||
moveRelative(relX, relY, relZ, yaw, pitch, getHeadYaw(), isOnGround);
|
||||
}
|
||||
|
||||
public void moveRelative(double relX, double relY, double relZ, float yaw, float pitch, float headYaw, boolean isOnGround) {
|
||||
|
@ -218,7 +233,7 @@ public class Entity {
|
|||
}
|
||||
|
||||
public void moveAbsolute(Vector3f position, float yaw, float pitch, boolean isOnGround, boolean teleported) {
|
||||
moveAbsolute(position, yaw, pitch, this.headYaw, isOnGround, teleported);
|
||||
moveAbsolute(position, yaw, pitch, getHeadYaw(), isOnGround, teleported);
|
||||
}
|
||||
|
||||
public void moveAbsolute(Vector3f position, float yaw, float pitch, float headYaw, boolean isOnGround, boolean teleported) {
|
||||
|
@ -247,7 +262,8 @@ public class Entity {
|
|||
* @param isOnGround Whether the entity is currently on the ground.
|
||||
*/
|
||||
public void teleport(Vector3f position, float yaw, float pitch, boolean isOnGround) {
|
||||
moveAbsolute(position, yaw, pitch, isOnGround, false);
|
||||
// teleport will always set the headYaw to yaw
|
||||
moveAbsolute(position, yaw, pitch, yaw, isOnGround, false);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -255,7 +271,7 @@ public class Entity {
|
|||
* @param headYaw The new head rotation of the entity.
|
||||
*/
|
||||
public void updateHeadLookRotation(float headYaw) {
|
||||
moveRelative(0, 0, 0, headYaw, pitch, this.headYaw, onGround);
|
||||
moveRelative(0, 0, 0, getYaw(), getPitch(), headYaw, isOnGround());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -268,7 +284,7 @@ public class Entity {
|
|||
* @param isOnGround Whether the entity is currently on the ground.
|
||||
*/
|
||||
public void updatePositionAndRotation(double moveX, double moveY, double moveZ, float yaw, float pitch, boolean isOnGround) {
|
||||
moveRelative(moveX, moveY, moveZ, this.yaw, pitch, yaw, isOnGround);
|
||||
moveRelative(moveX, moveY, moveZ, yaw, pitch, getHeadYaw(), isOnGround);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -343,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;
|
||||
}
|
||||
|
||||
|
@ -362,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());
|
||||
}
|
||||
|
@ -369,9 +389,7 @@ public class Entity {
|
|||
/**
|
||||
* Usually used for bounding box and not animation.
|
||||
*/
|
||||
public void setPose(EntityMetadata<Pose, ?> entityMetadata) {
|
||||
Pose pose = entityMetadata.getValue();
|
||||
|
||||
public void setPose(Pose pose) {
|
||||
setFlag(EntityFlag.SLEEPING, pose.equals(Pose.SLEEPING));
|
||||
// Triggered when crawling
|
||||
setFlag(EntityFlag.SWIMMING, pose.equals(Pose.SWIMMING));
|
||||
|
@ -387,11 +405,15 @@ public class Entity {
|
|||
setBoundingBoxWidth(definition.width());
|
||||
}
|
||||
|
||||
public void setBoundingBoxHeight(float height) {
|
||||
public boolean setBoundingBoxHeight(float height) {
|
||||
if (height != boundingBoxHeight) {
|
||||
boundingBoxHeight = height;
|
||||
dirtyMetadata.put(EntityData.BOUNDING_BOX_HEIGHT, boundingBoxHeight);
|
||||
|
||||
updatePassengerOffsets();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void setBoundingBoxWidth(float width) {
|
||||
|
@ -427,20 +449,100 @@ public class Entity {
|
|||
}
|
||||
|
||||
/**
|
||||
* x = Pitch, y = HeadYaw, z = Yaw
|
||||
* x = Pitch, y = Yaw, z = HeadYaw
|
||||
*
|
||||
* @return the bedrock rotation
|
||||
*/
|
||||
public Vector3f getBedrockRotation() {
|
||||
return Vector3f.from(pitch, headYaw, yaw);
|
||||
return Vector3f.from(getPitch(), getYaw(), getHeadYaw());
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the mount offsets of each passenger on this vehicle
|
||||
*/
|
||||
protected void updatePassengerOffsets() {
|
||||
for (Entity passenger : passengers) {
|
||||
if (passenger != null) {
|
||||
boolean rider = passengers.get(0) == this;
|
||||
EntityUtils.updateMountOffset(passenger, this, rider, true, passengers.size() > 1);
|
||||
passenger.updateBedrockMetadata();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update this entity's mount offset
|
||||
*/
|
||||
protected void updateMountOffset() {
|
||||
if (vehicle != null) {
|
||||
boolean rider = vehicle.getPassengers().get(0) == this;
|
||||
EntityUtils.updateMountOffset(this, vehicle, rider, true, vehicle.getPassengers().size() > 1);
|
||||
updateBedrockMetadata();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isAlive() {
|
||||
return this.valid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the suggestion that the client currently has on their screen for this entity (for example, "Feed" or "Ride")
|
||||
*/
|
||||
public final void updateInteractiveTag() {
|
||||
InteractiveTag tag = InteractiveTag.NONE;
|
||||
for (Hand hand: EntityUtils.HANDS) {
|
||||
tag = testInteraction(hand);
|
||||
if (tag != InteractiveTag.NONE) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
session.getPlayerEntity().getDirtyMetadata().put(EntityData.INTERACTIVE_TAG, tag.getValue());
|
||||
session.getPlayerEntity().updateBedrockMetadata();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test interacting with the given hand to see if we should send a tag to the Bedrock client.
|
||||
* Should usually mirror {@link #interact(Hand)} without any side effects.
|
||||
*/
|
||||
protected InteractiveTag testInteraction(Hand hand) {
|
||||
return InteractiveTag.NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Simulates interacting with an entity. The code here should mirror Java Edition code to the best of its ability,
|
||||
* to ensure packet parity as well as functionality parity (such as sound effect responses).
|
||||
*/
|
||||
public InteractionResult interact(Hand hand) {
|
||||
return InteractionResult.PASS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Simulates interacting with this entity at a specific click point. As of Java Edition 1.18.1, this is only used for armor stands.
|
||||
*/
|
||||
public InteractionResult interactAt(Hand hand) {
|
||||
return InteractionResult.PASS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send an entity event of the specified type to the Bedrock player from this entity.
|
||||
*/
|
||||
public final void playEntityEvent(EntityEventType type) {
|
||||
playEntityEvent(type, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send an entity event of the specified type with the specified data to the Bedrock player from this entity.
|
||||
*/
|
||||
public final void playEntityEvent(EntityEventType type, int data) {
|
||||
EntityEventPacket packet = new EntityEventPacket();
|
||||
packet.setRuntimeEntityId(geyserId);
|
||||
packet.setType(type);
|
||||
packet.setData(data);
|
||||
session.sendUpstreamPacket(packet);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <I extends Entity> I as(Class<I> entityClass) {
|
||||
return entityClass.isInstance(this) ? (I) this : null;
|
||||
}
|
||||
|
||||
public <I extends Entity> boolean is(Class<I> entityClass) {
|
||||
return entityClass.isInstance(this);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
|
||||
import com.nukkitx.protocol.bedrock.packet.PlaySoundPacket;
|
||||
import org.geysermc.geyser.entity.EntityDefinition;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
public class EvokerFangsEntity extends Entity implements Tickable {
|
||||
private int limitedLife = 22;
|
||||
private boolean attackStarted = false;
|
||||
|
||||
public EvokerFangsEntity(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);
|
||||
// As of 1.18.2 Bedrock, this line is required for the entity to be visible
|
||||
// 22 is the starting number on Java Edition
|
||||
dirtyMetadata.put(EntityData.LIMITED_LIFE, this.limitedLife);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
if (attackStarted) {
|
||||
if (--this.limitedLife > 0 && this.limitedLife % 2 == 0) { // Matches Bedrock behavior
|
||||
dirtyMetadata.put(EntityData.LIMITED_LIFE, this.limitedLife);
|
||||
updateBedrockMetadata();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setAttackStarted() {
|
||||
this.attackStarted = true;
|
||||
if (!silent) {
|
||||
// Play the chomp sound
|
||||
PlaySoundPacket packet = new PlaySoundPacket();
|
||||
packet.setPosition(this.position);
|
||||
packet.setSound("mob.evocation_fangs.attack");
|
||||
packet.setVolume(1.0f);
|
||||
packet.setPitch(ThreadLocalRandom.current().nextFloat() * 0.2f + 0.85f);
|
||||
session.sendUpstreamPacket(packet);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
* 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
|
||||
|
@ -32,7 +32,7 @@ import org.geysermc.geyser.session.GeyserSession;
|
|||
|
||||
public class ExpOrbEntity extends Entity {
|
||||
|
||||
public ExpOrbEntity(GeyserSession session, int amount, long entityId, long geyserId, Vector3f position) {
|
||||
public ExpOrbEntity(GeyserSession session, int amount, int entityId, long geyserId, Vector3f position) {
|
||||
super(session, entityId, geyserId, null, EntityDefinitions.EXPERIENCE_ORB, position, Vector3f.ZERO, 0, 0, 0);
|
||||
|
||||
this.dirtyMetadata.put(EntityData.EXPERIENCE_VALUE, amount);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
* 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
|
||||
|
@ -36,8 +36,8 @@ import java.util.UUID;
|
|||
|
||||
public class FallingBlockEntity extends Entity {
|
||||
|
||||
public FallingBlockEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, Vector3f position, Vector3f motion, float yaw, float pitch, int javaId) {
|
||||
super(session, entityId, geyserId, uuid, EntityDefinitions.FALLING_BLOCK, position, motion, yaw, pitch, 0f);
|
||||
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));
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
* 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
|
||||
|
@ -39,7 +39,7 @@ public class FireballEntity extends ThrowableEntity {
|
|||
*/
|
||||
protected int futureTicks = 3;
|
||||
|
||||
public FireballEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
public FireballEntity(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, Vector3f.ZERO, yaw, pitch, headYaw);
|
||||
|
||||
float magnitude = motion.length();
|
||||
|
@ -72,6 +72,6 @@ public class FireballEntity extends ThrowableEntity {
|
|||
|
||||
@Override
|
||||
public void tick() {
|
||||
moveAbsoluteImmediate(tickMovement(position), yaw, pitch, headYaw, false, false);
|
||||
moveAbsoluteImmediate(tickMovement(position), getYaw(), getPitch(), getHeadYaw(), false, false);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
* 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
|
||||
|
@ -50,7 +50,7 @@ import java.util.UUID;
|
|||
|
||||
public class FireworkEntity extends Entity {
|
||||
|
||||
public FireworkEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
public FireworkEntity(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);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
* 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
|
||||
|
@ -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;
|
||||
|
@ -50,13 +49,13 @@ public class FishingHookEntity extends ThrowableEntity {
|
|||
private boolean inWater = false;
|
||||
|
||||
@Getter
|
||||
private final boolean isOwnerSessionPlayer;
|
||||
private final long bedrockOwnerId;
|
||||
@Getter
|
||||
private long bedrockTargetId;
|
||||
|
||||
private final BoundingBox boundingBox;
|
||||
|
||||
public FishingHookEntity(GeyserSession session, long 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);
|
||||
|
@ -66,25 +65,13 @@ public class FishingHookEntity extends ThrowableEntity {
|
|||
// so that it can be handled by moveAbsoluteImmediate.
|
||||
setBoundingBoxHeight(128);
|
||||
|
||||
isOwnerSessionPlayer = owner.getGeyserId() == session.getPlayerEntity().getGeyserId();
|
||||
this.dirtyMetadata.put(EntityData.OWNER_EID, owner.getGeyserId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void spawnEntity() {
|
||||
|
||||
super.spawnEntity();
|
||||
this.bedrockOwnerId = owner.getGeyserId();
|
||||
this.dirtyMetadata.put(EntityData.OWNER_EID, this.bedrockOwnerId);
|
||||
}
|
||||
|
||||
public void setHookedEntity(IntEntityMetadata entityMetadata) {
|
||||
int hookedEntityId = entityMetadata.getPrimitiveValue() - 1;
|
||||
Entity entity;
|
||||
if (session.getPlayerEntity().getEntityId() == hookedEntityId) {
|
||||
entity = session.getPlayerEntity();
|
||||
} else {
|
||||
entity = session.getEntityCache().getEntityByJavaId(hookedEntityId);
|
||||
}
|
||||
|
||||
Entity entity = session.getEntityCache().getEntityByJavaId(hookedEntityId);
|
||||
if (entity != null) {
|
||||
bedrockTargetId = entity.getGeyserId();
|
||||
dirtyMetadata.put(EntityData.TARGET_EID, bedrockTargetId);
|
||||
|
@ -141,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;
|
||||
|
@ -164,7 +151,7 @@ public class FishingHookEntity extends ThrowableEntity {
|
|||
float gravity = getGravity();
|
||||
motion = motion.down(gravity);
|
||||
|
||||
moveAbsoluteImmediate(position.add(motion), yaw, pitch, headYaw, onGround, false);
|
||||
moveAbsoluteImmediate(position.add(motion), getYaw(), getPitch(), getHeadYaw(), isOnGround(), false);
|
||||
|
||||
float drag = getDrag();
|
||||
motion = motion.mul(drag);
|
||||
|
@ -172,7 +159,7 @@ public class FishingHookEntity extends ThrowableEntity {
|
|||
|
||||
@Override
|
||||
protected float getGravity() {
|
||||
if (!isInWater() && !onGround) {
|
||||
if (!isInWater() && !isOnGround()) {
|
||||
return 0.03f;
|
||||
}
|
||||
return 0;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
* 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
|
||||
|
@ -26,22 +26,25 @@
|
|||
package org.geysermc.geyser.entity.type;
|
||||
|
||||
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 org.geysermc.geyser.entity.EntityDefinition;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.level.block.BlockStateValues;
|
||||
import org.geysermc.geyser.util.InteractionResult;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class FurnaceMinecartEntity extends DefaultBlockMinecartEntity {
|
||||
private boolean hasFuel = false;
|
||||
|
||||
public FurnaceMinecartEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
public FurnaceMinecartEntity(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);
|
||||
}
|
||||
|
||||
public void setHasFuel(BooleanEntityMetadata entityMetadata) {
|
||||
// Note: Java ticks this entity and gives it particles if it has fuel
|
||||
hasFuel = entityMetadata.getPrimitiveValue();
|
||||
updateDefaultBlockMetadata();
|
||||
}
|
||||
|
@ -51,4 +54,10 @@ public class FurnaceMinecartEntity extends DefaultBlockMinecartEntity {
|
|||
dirtyMetadata.put(EntityData.DISPLAY_ITEM, session.getBlockMappings().getBedrockBlockId(hasFuel ? BlockStateValues.JAVA_FURNACE_LIT_ID : BlockStateValues.JAVA_FURNACE_ID));
|
||||
dirtyMetadata.put(EntityData.DISPLAY_OFFSET, 6);
|
||||
}
|
||||
|
||||
@Override
|
||||
public InteractionResult interact(Hand hand) {
|
||||
// Always works since you can "push" it this way
|
||||
return InteractionResult.SUCCESS;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
* 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
|
||||
|
@ -46,7 +46,7 @@ public class ItemEntity extends ThrowableEntity {
|
|||
|
||||
private int waterLevel = -1;
|
||||
|
||||
public ItemEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
public ItemEntity(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);
|
||||
}
|
||||
|
||||
|
@ -76,10 +76,10 @@ public class ItemEntity extends ThrowableEntity {
|
|||
if (isInWater()) {
|
||||
return;
|
||||
}
|
||||
if (!onGround || (motion.getX() * motion.getX() + motion.getZ() * motion.getZ()) > 0.00001) {
|
||||
if (!isOnGround() || (motion.getX() * motion.getX() + motion.getZ() * motion.getZ()) > 0.00001) {
|
||||
float gravity = getGravity();
|
||||
motion = motion.down(gravity);
|
||||
moveAbsoluteImmediate(position.add(motion), yaw, pitch, headYaw, onGround, false);
|
||||
moveAbsoluteImmediate(position.add(motion), getYaw(), getPitch(), getHeadYaw(), isOnGround(), false);
|
||||
float drag = getDrag();
|
||||
motion = motion.mul(drag, 0.98f, drag);
|
||||
}
|
||||
|
@ -124,7 +124,7 @@ public class ItemEntity extends ThrowableEntity {
|
|||
|
||||
@Override
|
||||
protected float getGravity() {
|
||||
if (getFlag(EntityFlag.HAS_GRAVITY) && !onGround && !isInWater()) {
|
||||
if (getFlag(EntityFlag.HAS_GRAVITY) && !isOnGround() && !isInWater()) {
|
||||
// Gravity can change if the item is in water/lava, but
|
||||
// the server calculates the motion & position for us
|
||||
return 0.04f;
|
||||
|
@ -134,7 +134,7 @@ public class ItemEntity extends ThrowableEntity {
|
|||
|
||||
@Override
|
||||
protected float getDrag() {
|
||||
if (onGround) {
|
||||
if (isOnGround()) {
|
||||
Vector3i groundBlockPos = position.toInt().down(1);
|
||||
int blockState = session.getGeyser().getWorldManager().getBlockAt(session, groundBlockPos);
|
||||
return BlockStateValues.getSlipperiness(blockState) * 0.98f;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
* 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
|
||||
|
@ -29,6 +29,7 @@ import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadat
|
|||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.object.Direction;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.type.EntityType;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.math.vector.Vector3i;
|
||||
|
@ -37,12 +38,13 @@ import com.nukkitx.nbt.NbtMapBuilder;
|
|||
import com.nukkitx.protocol.bedrock.data.inventory.ItemData;
|
||||
import com.nukkitx.protocol.bedrock.packet.BlockEntityDataPacket;
|
||||
import com.nukkitx.protocol.bedrock.packet.UpdateBlockPacket;
|
||||
import com.nukkitx.protocol.bedrock.v465.Bedrock_v465;
|
||||
import lombok.Getter;
|
||||
import org.geysermc.geyser.entity.EntityDefinition;
|
||||
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 org.geysermc.geyser.util.InteractionResult;
|
||||
import org.geysermc.geyser.util.InventoryUtils;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
|
@ -77,18 +79,16 @@ public class ItemFrameEntity extends Entity {
|
|||
*/
|
||||
private boolean changed = true;
|
||||
|
||||
public ItemFrameEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, Direction direction) {
|
||||
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, 0f);
|
||||
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")
|
||||
.putInt("version", session.getBlockMappings().getBlockStateVersion());
|
||||
NbtMapBuilder statesBuilder = NbtMap.builder()
|
||||
.putInt("facing_direction", direction.ordinal())
|
||||
.putByte("item_frame_map_bit", (byte) 0);
|
||||
if (session.getUpstream().getProtocolVersion() >= Bedrock_v465.V465_CODEC.getProtocolVersion()) {
|
||||
statesBuilder.putByte("item_frame_photo_bit", (byte) 0);
|
||||
}
|
||||
.putByte("item_frame_map_bit", (byte) 0)
|
||||
.putByte("item_frame_photo_bit", (byte) 0);
|
||||
blockBuilder.put("states", statesBuilder.build());
|
||||
|
||||
bedrockRuntimeId = session.getBlockMappings().getItemFrame(blockBuilder.build());
|
||||
|
@ -208,6 +208,11 @@ public class ItemFrameEntity extends Entity {
|
|||
changed = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InteractionResult interact(Hand hand) {
|
||||
return InventoryUtils.isEmpty(heldItem) && session.getPlayerInventory().getItemInHand(hand).isEmpty() ? InteractionResult.PASS : InteractionResult.SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the Java entity ID of an item frame from its Bedrock position.
|
||||
* @param position position of item frame in Bedrock.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
* 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
|
||||
|
@ -25,17 +25,24 @@
|
|||
|
||||
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 java.util.UUID;
|
||||
|
||||
public class LeashKnotEntity extends Entity {
|
||||
|
||||
public LeashKnotEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
public LeashKnotEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
// Position is incorrect by default
|
||||
super(session, entityId, geyserId, uuid, definition, position.add(0.5f, 0.25f, 0.5f), motion, yaw, pitch, headYaw);
|
||||
}
|
||||
|
||||
@Override
|
||||
public InteractionResult interact(Hand hand) {
|
||||
// Un-leashing the knot
|
||||
return InteractionResult.SUCCESS;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
* 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
|
||||
|
@ -35,7 +35,7 @@ import java.util.concurrent.ThreadLocalRandom;
|
|||
|
||||
public class LightningEntity extends Entity {
|
||||
|
||||
public LightningEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
public LightningEntity(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);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
* 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
|
||||
|
@ -29,10 +29,12 @@ 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;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
|
||||
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
|
||||
import com.github.steveice10.opennbt.tag.builtin.StringTag;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.math.vector.Vector3i;
|
||||
import com.nukkitx.protocol.bedrock.data.AttributeData;
|
||||
|
@ -48,16 +50,14 @@ import lombok.Getter;
|
|||
import lombok.Setter;
|
||||
import org.geysermc.geyser.entity.EntityDefinition;
|
||||
import org.geysermc.geyser.entity.attribute.GeyserAttributeType;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.inventory.GeyserItemStack;
|
||||
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
|
||||
|
@ -80,7 +80,7 @@ public class LivingEntity extends Entity {
|
|||
*/
|
||||
private boolean isMaxFrozenState = false;
|
||||
|
||||
public LivingEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
public LivingEntity(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);
|
||||
}
|
||||
|
||||
|
@ -94,13 +94,15 @@ public class LivingEntity extends Entity {
|
|||
public void setLivingEntityFlags(ByteEntityMetadata entityMetadata) {
|
||||
byte xd = entityMetadata.getPrimitiveValue();
|
||||
|
||||
// Blocking gets triggered when using a bow, but if we set USING_ITEM for all items, it may look like
|
||||
// you're "mining" with ex. a shield.
|
||||
boolean isUsingItem = (xd & 0x01) == 0x01;
|
||||
boolean isUsingOffhand = (xd & 0x02) == 0x02;
|
||||
|
||||
ItemMapping shield = session.getItemMappings().getStoredItems().shield();
|
||||
boolean isUsingShield = (getHand().getId() == shield.getBedrockId() ||
|
||||
getHand().equals(ItemData.AIR) && getOffHand().getId() == shield.getBedrockId());
|
||||
setFlag(EntityFlag.USING_ITEM, (xd & 0x01) == 0x01 && !isUsingShield);
|
||||
setFlag(EntityFlag.BLOCKING, (xd & 0x01) == 0x01);
|
||||
boolean isUsingShield = hasShield(isUsingOffhand, shield);
|
||||
|
||||
setFlag(EntityFlag.USING_ITEM, isUsingItem && !isUsingShield);
|
||||
// Override the blocking
|
||||
setFlag(EntityFlag.BLOCKING, isUsingItem && isUsingShield);
|
||||
|
||||
// Riptide spin attack
|
||||
setFlag(EntityFlag.DAMAGE_NEARBY_MOBS, (xd & 0x04) == 0x04);
|
||||
|
@ -116,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);
|
||||
|
@ -129,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);
|
||||
|
@ -137,6 +138,14 @@ public class LivingEntity extends Entity {
|
|||
}
|
||||
}
|
||||
|
||||
protected boolean hasShield(boolean offhand, ItemMapping shieldMapping) {
|
||||
if (offhand) {
|
||||
return offHand.getId() == shieldMapping.getBedrockId();
|
||||
} else {
|
||||
return hand.getId() == shieldMapping.getBedrockId();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isShaking() {
|
||||
return isMaxFrozenState;
|
||||
|
@ -169,6 +178,36 @@ public class LivingEntity extends Entity {
|
|||
return new AttributeData(GeyserAttributeType.HEALTH.getBedrockIdentifier(), 0f, this.maxHealth, (float) Math.ceil(this.health), this.maxHealth);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAlive() {
|
||||
return this.valid && health > 0f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InteractionResult interact(Hand hand) {
|
||||
GeyserItemStack itemStack = session.getPlayerInventory().getItemInHand(hand);
|
||||
if (itemStack.getJavaId() == session.getItemMappings().getStoredItems().nameTag()) {
|
||||
InteractionResult result = checkInteractWithNameTag(itemStack);
|
||||
if (result.consumesAction()) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return super.interact(hand);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see if a nametag interaction would go through.
|
||||
*/
|
||||
protected final InteractionResult checkInteractWithNameTag(GeyserItemStack itemStack) {
|
||||
CompoundTag nbt = itemStack.getNbt();
|
||||
if (nbt != null && nbt.get("display") instanceof CompoundTag displayTag && displayTag.get("Name") instanceof StringTag) {
|
||||
// The mob shall be named
|
||||
return InteractionResult.SUCCESS;
|
||||
}
|
||||
return InteractionResult.PASS;
|
||||
}
|
||||
|
||||
public void updateArmor(GeyserSession session) {
|
||||
if (!valid) return;
|
||||
|
||||
|
@ -255,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));
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
* 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
|
||||
|
@ -27,16 +27,20 @@ package org.geysermc.geyser.entity.type;
|
|||
|
||||
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 org.geysermc.geyser.entity.EntityDefinition;
|
||||
import org.geysermc.geyser.entity.EntityDefinitions;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.util.InteractionResult;
|
||||
import org.geysermc.geyser.util.InteractiveTag;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class MinecartEntity extends Entity {
|
||||
|
||||
public MinecartEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
public MinecartEntity(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.add(0d, definition.offset(), 0d), motion, yaw, pitch, headYaw);
|
||||
}
|
||||
|
||||
|
@ -62,6 +66,41 @@ public class MinecartEntity extends Entity {
|
|||
@Override
|
||||
public Vector3f getBedrockRotation() {
|
||||
// Note: minecart rotation on rails does not care about the actual rotation value
|
||||
return Vector3f.from(0, yaw, 0);
|
||||
return Vector3f.from(0, getYaw(), 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected InteractiveTag testInteraction(Hand hand) {
|
||||
if (definition == EntityDefinitions.CHEST_MINECART || definition == EntityDefinitions.HOPPER_MINECART) {
|
||||
return InteractiveTag.OPEN_CONTAINER;
|
||||
} else {
|
||||
if (session.isSneaking()) {
|
||||
return InteractiveTag.NONE;
|
||||
} else if (!passengers.isEmpty()) {
|
||||
// Can't enter if someone is inside
|
||||
return InteractiveTag.NONE;
|
||||
} else {
|
||||
// Attempt to enter
|
||||
return InteractiveTag.RIDE_MINECART;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public InteractionResult interact(Hand hand) {
|
||||
if (definition == EntityDefinitions.CHEST_MINECART || definition == EntityDefinitions.HOPPER_MINECART) {
|
||||
// Opening the UI of this minecart
|
||||
return InteractionResult.SUCCESS;
|
||||
} else {
|
||||
if (session.isSneaking()) {
|
||||
return InteractionResult.PASS;
|
||||
} else if (!passengers.isEmpty()) {
|
||||
// Can't enter if someone is inside
|
||||
return InteractionResult.PASS;
|
||||
} else {
|
||||
// Attempt to enter
|
||||
return InteractionResult.SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
* 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
|
||||
|
@ -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, long entityId, long geyserId, UUID uuid, Vector3f position, PaintingType paintingName, int direction) {
|
||||
super(session, entityId, geyserId, uuid, EntityDefinitions.PAINTING, position, Vector3f.ZERO, 0f, 0f, 0f);
|
||||
this.paintingName = paintingName;
|
||||
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;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
* 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
|
||||
|
@ -35,7 +35,7 @@ import java.util.UUID;
|
|||
|
||||
public class SpawnerMinecartEntity extends DefaultBlockMinecartEntity {
|
||||
|
||||
public SpawnerMinecartEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
public SpawnerMinecartEntity(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);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
* 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
|
||||
|
@ -38,7 +38,7 @@ import java.util.UUID;
|
|||
public class TNTEntity extends Entity implements Tickable {
|
||||
private int currentTick;
|
||||
|
||||
public TNTEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
public TNTEntity(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);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
* 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
|
||||
|
@ -44,7 +44,7 @@ public class ThrowableEntity extends Entity implements Tickable {
|
|||
|
||||
protected Vector3f lastJavaPosition;
|
||||
|
||||
public ThrowableEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
public ThrowableEntity(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);
|
||||
this.lastJavaPosition = position;
|
||||
}
|
||||
|
@ -56,7 +56,7 @@ public class ThrowableEntity extends Entity implements Tickable {
|
|||
*/
|
||||
@Override
|
||||
public void tick() {
|
||||
moveAbsoluteImmediate(position.add(motion), yaw, pitch, headYaw, onGround, false);
|
||||
moveAbsoluteImmediate(position.add(motion), getYaw(), getPitch(), getHeadYaw(), isOnGround(), false);
|
||||
float drag = getDrag();
|
||||
float gravity = getGravity();
|
||||
motion = motion.mul(drag).down(gravity);
|
||||
|
@ -89,20 +89,20 @@ public class ThrowableEntity extends Entity implements Tickable {
|
|||
}
|
||||
setPosition(position);
|
||||
|
||||
if (this.yaw != yaw) {
|
||||
if (getYaw() != yaw) {
|
||||
moveEntityDeltaPacket.getFlags().add(MoveEntityDeltaPacket.Flag.HAS_YAW);
|
||||
moveEntityDeltaPacket.setYaw(yaw);
|
||||
this.yaw = yaw;
|
||||
setYaw(yaw);
|
||||
}
|
||||
if (this.pitch != pitch) {
|
||||
if (getPitch() != pitch) {
|
||||
moveEntityDeltaPacket.getFlags().add(MoveEntityDeltaPacket.Flag.HAS_PITCH);
|
||||
moveEntityDeltaPacket.setPitch(pitch);
|
||||
this.pitch = pitch;
|
||||
setPitch(pitch);
|
||||
}
|
||||
if (this.headYaw != headYaw) {
|
||||
if (getHeadYaw() != headYaw) {
|
||||
moveEntityDeltaPacket.getFlags().add(MoveEntityDeltaPacket.Flag.HAS_HEAD_YAW);
|
||||
moveEntityDeltaPacket.setHeadYaw(headYaw);
|
||||
this.headYaw = headYaw;
|
||||
setHeadYaw(headYaw);
|
||||
}
|
||||
|
||||
if (!moveEntityDeltaPacket.getFlags().isEmpty()) {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
* 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
|
||||
|
@ -44,7 +44,7 @@ public class ThrowableItemEntity extends ThrowableEntity {
|
|||
private int age;
|
||||
private boolean invisible;
|
||||
|
||||
public ThrowableItemEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
public ThrowableItemEntity(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);
|
||||
setFlag(EntityFlag.INVISIBLE, true);
|
||||
invisible = false;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
* 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
|
||||
|
@ -44,7 +44,7 @@ import java.util.UUID;
|
|||
public class ThrownPotionEntity extends ThrowableItemEntity {
|
||||
private static final EnumSet<Potion> NON_ENCHANTED_POTIONS = EnumSet.of(Potion.WATER, Potion.MUNDANE, Potion.THICK, Potion.AWKWARD);
|
||||
|
||||
public ThrownPotionEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
public ThrownPotionEntity(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);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
* 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
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
* 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
|
||||
|
@ -39,7 +39,7 @@ import java.util.UUID;
|
|||
*/
|
||||
public class TippedArrowEntity extends AbstractArrowEntity {
|
||||
|
||||
public TippedArrowEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
public TippedArrowEntity(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);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
* 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
|
||||
|
@ -33,7 +33,7 @@ import java.util.UUID;
|
|||
|
||||
public class TridentEntity extends AbstractArrowEntity {
|
||||
|
||||
public TridentEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
public TridentEntity(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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
* 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
|
||||
|
@ -36,7 +36,7 @@ import java.util.UUID;
|
|||
public class WitherSkullEntity extends FireballEntity {
|
||||
private boolean isCharged;
|
||||
|
||||
public WitherSkullEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
public WitherSkullEntity(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);
|
||||
|
||||
this.futureTicks = 1;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
* 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
|
||||
|
@ -25,16 +25,21 @@
|
|||
|
||||
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;
|
||||
import org.geysermc.geyser.inventory.GeyserItemStack;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.util.EntityUtils;
|
||||
import org.geysermc.geyser.util.InteractionResult;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.UUID;
|
||||
|
||||
public class AbstractFishEntity extends WaterEntity {
|
||||
|
||||
public AbstractFishEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
public AbstractFishEntity(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);
|
||||
|
||||
setFlag(EntityFlag.CAN_SWIM, true);
|
||||
|
@ -42,4 +47,14 @@ public class AbstractFishEntity extends WaterEntity {
|
|||
setFlag(EntityFlag.CAN_CLIMB, false);
|
||||
setFlag(EntityFlag.HAS_GRAVITY, false);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) {
|
||||
if (EntityUtils.attemptToBucket(session, itemInHand)) {
|
||||
return InteractionResult.SUCCESS;
|
||||
} else {
|
||||
return super.mobInteract(hand, itemInHand);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
* 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
|
||||
|
@ -36,7 +36,7 @@ import java.util.UUID;
|
|||
|
||||
public class AgeableEntity extends CreatureEntity {
|
||||
|
||||
public AgeableEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
public AgeableEntity(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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
* 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
|
||||
|
@ -33,7 +33,12 @@ import java.util.UUID;
|
|||
|
||||
public class AmbientEntity extends MobEntity {
|
||||
|
||||
public AmbientEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
public AmbientEntity(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 boolean canBeLeashed() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
* 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
|
||||
|
@ -26,8 +26,8 @@
|
|||
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.Hand;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
|
||||
|
@ -39,6 +39,8 @@ import org.geysermc.geyser.entity.EntityDefinition;
|
|||
import org.geysermc.geyser.entity.EntityDefinitions;
|
||||
import org.geysermc.geyser.entity.type.LivingEntity;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.util.InteractionResult;
|
||||
import org.geysermc.geyser.util.MathUtils;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
@ -78,14 +80,12 @@ public class ArmorStandEntity extends LivingEntity {
|
|||
*/
|
||||
private boolean positionUpdateRequired = false;
|
||||
|
||||
public ArmorStandEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
public ArmorStandEntity(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 spawnEntity() {
|
||||
this.pitch = yaw;
|
||||
this.headYaw = yaw;
|
||||
super.spawnEntity();
|
||||
}
|
||||
|
||||
|
@ -136,7 +136,7 @@ public class ArmorStandEntity extends LivingEntity {
|
|||
}
|
||||
|
||||
isSmall = newIsSmall;
|
||||
if (!isMarker) {
|
||||
if (!isMarker && !isInvisible) { // Addition for isInvisible check caused by https://github.com/GeyserMC/Geyser/issues/2780
|
||||
toggleSmallStatus();
|
||||
}
|
||||
}
|
||||
|
@ -146,13 +146,14 @@ public class ArmorStandEntity extends LivingEntity {
|
|||
isMarker = (xd & 0x10) == 0x10;
|
||||
if (oldIsMarker != isMarker) {
|
||||
if (isMarker) {
|
||||
dirtyMetadata.put(EntityData.BOUNDING_BOX_WIDTH, 0.0f);
|
||||
dirtyMetadata.put(EntityData.BOUNDING_BOX_HEIGHT, 0.0f);
|
||||
setBoundingBoxWidth(0.0f);
|
||||
setBoundingBoxHeight(0.0f);
|
||||
dirtyMetadata.put(EntityData.SCALE, 0f);
|
||||
} else {
|
||||
toggleSmallStatus();
|
||||
}
|
||||
|
||||
updateMountOffset();
|
||||
updateSecondEntityStatus(false);
|
||||
}
|
||||
|
||||
|
@ -162,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());
|
||||
}
|
||||
|
||||
|
@ -197,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 = getRotation(rotation.getPitch());
|
||||
int rotationY = getRotation(rotation.getYaw());
|
||||
int rotationZ = getRotation(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);
|
||||
|
@ -236,6 +237,16 @@ public class ArmorStandEntity extends LivingEntity {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public InteractionResult interactAt(Hand hand) {
|
||||
if (!isMarker && session.getPlayerInventory().getItemInHand(hand).getJavaId() != session.getItemMappings().getStoredItems().nameTag()) {
|
||||
// Java Edition returns SUCCESS if in spectator mode, but this is overrided with an earlier check on the client
|
||||
return InteractionResult.CONSUME;
|
||||
} else {
|
||||
return InteractionResult.PASS;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setHelmet(ItemData helmet) {
|
||||
super.setHelmet(helmet);
|
||||
|
@ -305,7 +316,7 @@ public class ArmorStandEntity extends LivingEntity {
|
|||
// Create the second entity. It doesn't need to worry about the items, but it does need to worry about
|
||||
// the metadata as it will hold the name tag.
|
||||
secondEntity = new ArmorStandEntity(session, 0, session.getEntityCache().getNextEntityId().incrementAndGet(), null,
|
||||
EntityDefinitions.ARMOR_STAND, position, motion, yaw, pitch, headYaw);
|
||||
EntityDefinitions.ARMOR_STAND, position, motion, getYaw(), getPitch(), getHeadYaw());
|
||||
secondEntity.primaryEntity = false;
|
||||
if (!this.positionRequiresOffset) {
|
||||
// Ensure the offset is applied for the 0 scale
|
||||
|
@ -361,23 +372,12 @@ public class ArmorStandEntity extends LivingEntity {
|
|||
}
|
||||
}
|
||||
|
||||
private int getRotation(float rotation) {
|
||||
rotation = rotation % 360f;
|
||||
if (rotation < -180f) {
|
||||
rotation += 360f;
|
||||
} else if (rotation >= 180f) {
|
||||
// 181 -> -179
|
||||
rotation = -(180 - (rotation - 180));
|
||||
}
|
||||
return (int) rotation;
|
||||
}
|
||||
|
||||
/**
|
||||
* If this armor stand is not a marker, set its bounding box size and scale.
|
||||
*/
|
||||
private void toggleSmallStatus() {
|
||||
dirtyMetadata.put(EntityData.BOUNDING_BOX_WIDTH, isSmall ? 0.25f : definition.width());
|
||||
dirtyMetadata.put(EntityData.BOUNDING_BOX_HEIGHT, isSmall ? 0.9875f : definition.height());
|
||||
setBoundingBoxWidth(isSmall ? 0.25f : definition.width());
|
||||
setBoundingBoxHeight(isSmall ? 0.9875f : definition.height());
|
||||
dirtyMetadata.put(EntityData.SCALE, isSmall ? 0.55f : 1f);
|
||||
}
|
||||
|
||||
|
@ -425,9 +425,14 @@ public class ArmorStandEntity extends LivingEntity {
|
|||
MoveEntityAbsolutePacket moveEntityPacket = new MoveEntityAbsolutePacket();
|
||||
moveEntityPacket.setRuntimeEntityId(geyserId);
|
||||
moveEntityPacket.setPosition(position);
|
||||
moveEntityPacket.setRotation(Vector3f.from(yaw, yaw, yaw));
|
||||
moveEntityPacket.setOnGround(onGround);
|
||||
moveEntityPacket.setRotation(getBedrockRotation());
|
||||
moveEntityPacket.setOnGround(isOnGround());
|
||||
moveEntityPacket.setTeleported(false);
|
||||
session.sendUpstreamPacket(moveEntityPacket);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vector3f getBedrockRotation() {
|
||||
return Vector3f.from(getYaw(), getYaw(), getYaw());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
* 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
|
||||
|
@ -35,7 +35,7 @@ import java.util.UUID;
|
|||
|
||||
public class BatEntity extends AmbientEntity {
|
||||
|
||||
public BatEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
public BatEntity(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);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
* 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
|
||||
|
@ -33,7 +33,7 @@ import java.util.UUID;
|
|||
|
||||
public class CreatureEntity extends MobEntity {
|
||||
|
||||
public CreatureEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
public CreatureEntity(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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* 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 DolphinEntity extends WaterEntity {
|
||||
public DolphinEntity(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 boolean canBeLeashed() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
protected InteractiveTag testMobInteraction(Hand hand, @Nonnull GeyserItemStack itemInHand) {
|
||||
if (!itemInHand.isEmpty() && session.getTagCache().isFish(itemInHand)) {
|
||||
return InteractiveTag.FEED;
|
||||
}
|
||||
return super.testMobInteraction(hand, itemInHand);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) {
|
||||
if (!itemInHand.isEmpty() && session.getTagCache().isFish(itemInHand)) {
|
||||
// Feed
|
||||
return InteractionResult.SUCCESS;
|
||||
}
|
||||
return super.mobInteract(hand, itemInHand);
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
* 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
|
||||
|
@ -33,7 +33,7 @@ import java.util.UUID;
|
|||
|
||||
public class FlyingEntity extends MobEntity {
|
||||
|
||||
public FlyingEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
public FlyingEntity(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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
* 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
|
||||
|
@ -32,7 +32,7 @@ import org.geysermc.geyser.session.GeyserSession;
|
|||
import java.util.UUID;
|
||||
|
||||
public class GlowSquidEntity extends SquidEntity {
|
||||
public GlowSquidEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
public GlowSquidEntity(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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
* 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
|
||||
|
@ -33,7 +33,7 @@ import java.util.UUID;
|
|||
|
||||
public class GolemEntity extends CreatureEntity {
|
||||
|
||||
public GolemEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
public GolemEntity(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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
* 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
|
||||
|
@ -25,21 +25,39 @@
|
|||
|
||||
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;
|
||||
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 javax.annotation.Nonnull;
|
||||
import java.util.UUID;
|
||||
|
||||
public class IronGolemEntity extends GolemEntity {
|
||||
|
||||
public IronGolemEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
public IronGolemEntity(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);
|
||||
// Indicate that we should show cracks through a resource pack
|
||||
setFlag(EntityFlag.BRIBED, true);
|
||||
// Required, or else the overlay is black
|
||||
dirtyMetadata.put(EntityData.COLOR_2, (byte) 0);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) {
|
||||
if (itemInHand.getJavaId() == session.getItemMappings().getStoredItems().ironIngot()) {
|
||||
if (health < maxHealth) {
|
||||
// Healing the iron golem
|
||||
return InteractionResult.SUCCESS;
|
||||
} else {
|
||||
return InteractionResult.PASS;
|
||||
}
|
||||
}
|
||||
return super.mobInteract(hand, itemInHand);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
* 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
|
||||
|
@ -34,7 +34,7 @@ import java.util.UUID;
|
|||
|
||||
public class MagmaCubeEntity extends SlimeEntity {
|
||||
|
||||
public MagmaCubeEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
public MagmaCubeEntity(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);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
* 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
|
||||
|
@ -26,14 +26,21 @@
|
|||
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.EntityData;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
|
||||
import lombok.Getter;
|
||||
import org.geysermc.geyser.entity.EntityDefinition;
|
||||
import org.geysermc.geyser.entity.type.LivingEntity;
|
||||
import org.geysermc.geyser.inventory.GeyserItemStack;
|
||||
import org.geysermc.geyser.inventory.item.StoredItemMappings;
|
||||
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 javax.annotation.Nonnull;
|
||||
import java.util.UUID;
|
||||
|
||||
public class MobEntity extends LivingEntity {
|
||||
|
@ -43,7 +50,7 @@ public class MobEntity extends LivingEntity {
|
|||
@Getter
|
||||
private long leashHolderBedrockId;
|
||||
|
||||
public MobEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
public MobEntity(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);
|
||||
}
|
||||
|
||||
|
@ -62,4 +69,95 @@ public class MobEntity extends LivingEntity {
|
|||
this.leashHolderBedrockId = bedrockId;
|
||||
dirtyMetadata.put(EntityData.LEASH_HOLDER_EID, bedrockId);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final InteractiveTag testInteraction(Hand hand) {
|
||||
if (!isAlive()) {
|
||||
// dead lol
|
||||
return InteractiveTag.NONE;
|
||||
} else if (leashHolderBedrockId == session.getPlayerEntity().getGeyserId()) {
|
||||
return InteractiveTag.REMOVE_LEASH;
|
||||
} else {
|
||||
GeyserItemStack itemStack = session.getPlayerInventory().getItemInHand(hand);
|
||||
StoredItemMappings storedItems = session.getItemMappings().getStoredItems();
|
||||
if (itemStack.getJavaId() == storedItems.lead() && canBeLeashed()) {
|
||||
// We shall leash
|
||||
return InteractiveTag.LEASH;
|
||||
} else if (itemStack.getJavaId() == storedItems.nameTag()) {
|
||||
InteractionResult result = checkInteractWithNameTag(itemStack);
|
||||
if (result.consumesAction()) {
|
||||
return InteractiveTag.NAME;
|
||||
}
|
||||
}
|
||||
|
||||
InteractiveTag tag = testMobInteraction(hand, itemStack);
|
||||
return tag != InteractiveTag.NONE ? tag : super.testInteraction(hand);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final InteractionResult interact(Hand hand) {
|
||||
if (!isAlive()) {
|
||||
// dead lol
|
||||
return InteractionResult.PASS;
|
||||
} else if (leashHolderBedrockId == session.getPlayerEntity().getGeyserId()) {
|
||||
// TODO looks like the client assumes it will go through and removes the attachment itself?
|
||||
return InteractionResult.SUCCESS;
|
||||
} else {
|
||||
GeyserItemStack itemInHand = session.getPlayerInventory().getItemInHand(hand);
|
||||
InteractionResult result = checkPriorityInteractions(itemInHand);
|
||||
if (result.consumesAction()) {
|
||||
return result;
|
||||
} else {
|
||||
InteractionResult mobResult = mobInteract(hand, itemInHand);
|
||||
return mobResult.consumesAction() ? mobResult : super.interact(hand);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private InteractionResult checkPriorityInteractions(GeyserItemStack itemInHand) {
|
||||
StoredItemMappings storedItems = session.getItemMappings().getStoredItems();
|
||||
if (itemInHand.getJavaId() == storedItems.lead() && canBeLeashed()) {
|
||||
// We shall leash
|
||||
return InteractionResult.SUCCESS;
|
||||
} else if (itemInHand.getJavaId() == storedItems.nameTag()) {
|
||||
InteractionResult result = checkInteractWithNameTag(itemInHand);
|
||||
if (result.consumesAction()) {
|
||||
return result;
|
||||
}
|
||||
} else {
|
||||
ItemMapping mapping = itemInHand.getMapping(session);
|
||||
if (mapping.getJavaIdentifier().endsWith("_spawn_egg")) {
|
||||
// Using the spawn egg on this entity to create a child
|
||||
return InteractionResult.CONSUME;
|
||||
}
|
||||
}
|
||||
|
||||
return InteractionResult.PASS;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
protected InteractiveTag testMobInteraction(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
|
||||
return InteractiveTag.NONE;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
protected InteractionResult mobInteract(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
|
||||
return InteractionResult.PASS;
|
||||
}
|
||||
|
||||
protected boolean canBeLeashed() {
|
||||
return isNotLeashed() && !isEnemy();
|
||||
}
|
||||
|
||||
protected final boolean isNotLeashed() {
|
||||
return leashHolderBedrockId == -1L;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if the entity is hostile. Used to determine if it can be leashed.
|
||||
*/
|
||||
protected boolean isEnemy() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
* 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
|
||||
|
@ -35,11 +35,16 @@ import java.util.UUID;
|
|||
|
||||
public class SlimeEntity extends MobEntity {
|
||||
|
||||
public SlimeEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
public SlimeEntity(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);
|
||||
}
|
||||
|
||||
public void setScale(IntEntityMetadata entityMetadata) {
|
||||
dirtyMetadata.put(EntityData.SCALE, 0.10f + entityMetadata.getPrimitiveValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isEnemy() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
* 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
|
||||
|
@ -26,16 +26,21 @@
|
|||
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;
|
||||
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 SnowGolemEntity extends GolemEntity {
|
||||
|
||||
public SnowGolemEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
public SnowGolemEntity(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);
|
||||
}
|
||||
|
||||
|
@ -44,4 +49,24 @@ public class SnowGolemEntity extends GolemEntity {
|
|||
// Handle the visibility of the pumpkin
|
||||
setFlag(EntityFlag.SHEARED, (xd & 0x10) != 0x10);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
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;
|
||||
}
|
||||
return InteractiveTag.NONE;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
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;
|
||||
}
|
||||
return InteractionResult.PASS;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
* 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
|
||||
|
@ -41,7 +41,7 @@ public class SquidEntity extends WaterEntity implements Tickable {
|
|||
|
||||
private boolean inWater;
|
||||
|
||||
public SquidEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
public SquidEntity(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);
|
||||
}
|
||||
|
||||
|
@ -117,7 +117,12 @@ public class SquidEntity extends WaterEntity implements Tickable {
|
|||
|
||||
@Override
|
||||
public Vector3f getBedrockRotation() {
|
||||
return Vector3f.from(pitch, yaw, yaw);
|
||||
return Vector3f.from(getPitch(), getYaw(), getYaw());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean canBeLeashed() {
|
||||
return isNotLeashed();
|
||||
}
|
||||
|
||||
private void checkInWater() {
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
* 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
|
||||
|
@ -33,7 +33,12 @@ import java.util.UUID;
|
|||
|
||||
public class WaterEntity extends CreatureEntity {
|
||||
|
||||
public WaterEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
public WaterEntity(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 boolean canBeLeashed() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
* 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
|
||||
|
@ -25,20 +25,33 @@
|
|||
|
||||
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.util.InteractionResult;
|
||||
import org.geysermc.geyser.util.InteractiveTag;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.UUID;
|
||||
|
||||
public class AnimalEntity extends AgeableEntity {
|
||||
|
||||
public AnimalEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
public AnimalEntity(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);
|
||||
}
|
||||
|
||||
public final boolean canEat(GeyserItemStack itemStack) {
|
||||
ItemMapping mapping = itemStack.getMapping(session);
|
||||
String handIdentifier = mapping.getJavaIdentifier();
|
||||
return canEat(handIdentifier.replace("minecraft:", ""), mapping);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param javaIdentifierStripped the stripped Java identifier of the item that is potential breeding food. For example,
|
||||
* <code>wheat</code>.
|
||||
|
@ -48,4 +61,28 @@ public class AnimalEntity extends AgeableEntity {
|
|||
// This is what it defaults to. OK.
|
||||
return javaIdentifierStripped.equals("wheat");
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
protected InteractiveTag testMobInteraction(Hand hand, @Nonnull GeyserItemStack itemInHand) {
|
||||
if (canEat(itemInHand)) {
|
||||
return InteractiveTag.FEED;
|
||||
}
|
||||
return super.testMobInteraction(hand, itemInHand);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) {
|
||||
if (canEat(itemInHand)) {
|
||||
// FEED
|
||||
if (getFlag(EntityFlag.BABY)) {
|
||||
playEntityEvent(EntityEventType.BABY_ANIMAL_FEED);
|
||||
return InteractionResult.SUCCESS;
|
||||
} else {
|
||||
return InteractionResult.CONSUME;
|
||||
}
|
||||
}
|
||||
return super.mobInteract(hand, itemInHand);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
* 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
|
||||
|
@ -27,17 +27,22 @@ 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.util.EntityUtils;
|
||||
import org.geysermc.geyser.util.InteractionResult;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.UUID;
|
||||
|
||||
public class AxolotlEntity extends AnimalEntity {
|
||||
public AxolotlEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
public AxolotlEntity(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);
|
||||
}
|
||||
|
||||
|
@ -56,11 +61,26 @@ public class AxolotlEntity extends AnimalEntity {
|
|||
|
||||
@Override
|
||||
public boolean canEat(String javaIdentifierStripped, ItemMapping mapping) {
|
||||
return javaIdentifierStripped.equals("tropical_fish_bucket");
|
||||
return session.getTagCache().isAxolotlTemptItem(mapping);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getMaxAir() {
|
||||
protected short getMaxAir() {
|
||||
return 6000;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean canBeLeashed() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) {
|
||||
if (EntityUtils.attemptToBucket(session, itemInHand)) {
|
||||
return InteractionResult.SUCCESS;
|
||||
} else {
|
||||
return super.mobInteract(hand, itemInHand);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
* 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
|
||||
|
@ -40,7 +40,7 @@ import java.util.UUID;
|
|||
|
||||
public class BeeEntity extends AnimalEntity {
|
||||
|
||||
public BeeEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
public BeeEntity(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);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
* 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
|
||||
|
@ -34,7 +34,7 @@ import java.util.UUID;
|
|||
|
||||
public class ChickenEntity extends AnimalEntity {
|
||||
|
||||
public ChickenEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
public ChickenEntity(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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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.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;
|
||||
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 CowEntity extends AnimalEntity {
|
||||
public CowEntity(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(Hand hand, @Nonnull GeyserItemStack itemInHand) {
|
||||
if (getFlag(EntityFlag.BABY) || !itemInHand.getMapping(session).getJavaIdentifier().equals("minecraft:bucket")) {
|
||||
return super.testMobInteraction(hand, itemInHand);
|
||||
}
|
||||
|
||||
return InteractiveTag.MILK;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) {
|
||||
if (getFlag(EntityFlag.BABY) || !itemInHand.getMapping(session).getJavaIdentifier().equals("minecraft:bucket")) {
|
||||
return super.mobInteract(hand, itemInHand);
|
||||
}
|
||||
|
||||
session.playSoundEvent(SoundEvent.MILK, position);
|
||||
return InteractionResult.SUCCESS;
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
* 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
|
||||
|
@ -38,7 +38,7 @@ import java.util.UUID;
|
|||
|
||||
public class FoxEntity extends AnimalEntity {
|
||||
|
||||
public FoxEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
public FoxEntity(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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
* 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
|
||||
|
@ -27,21 +27,25 @@ 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 lombok.Getter;
|
||||
import com.nukkitx.protocol.bedrock.data.SoundEvent;
|
||||
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.util.InteractionResult;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.UUID;
|
||||
|
||||
public class GoatEntity extends AnimalEntity {
|
||||
private static final float LONG_JUMPING_HEIGHT = 1.3f * 0.7f;
|
||||
private static final float LONG_JUMPING_WIDTH = 0.9f * 0.7f;
|
||||
|
||||
@Getter
|
||||
private boolean isScreamer;
|
||||
|
||||
public GoatEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -59,4 +63,15 @@ public class GoatEntity extends AnimalEntity {
|
|||
super.setDimensions(pose);
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
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(hand, itemInHand);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
* 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
|
||||
|
@ -29,16 +29,15 @@ 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.util.DimensionUtils;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class HoglinEntity extends AnimalEntity {
|
||||
private boolean isImmuneToZombification;
|
||||
|
||||
public HoglinEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
public HoglinEntity(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);
|
||||
}
|
||||
|
||||
|
@ -50,11 +49,21 @@ public class HoglinEntity extends AnimalEntity {
|
|||
|
||||
@Override
|
||||
protected boolean isShaking() {
|
||||
return (!isImmuneToZombification && !session.getDimension().equals(DimensionUtils.NETHER)) || super.isShaking();
|
||||
return (!isImmuneToZombification && !session.getDimensionType().piglinSafe()) || super.isShaking();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canEat(String javaIdentifierStripped, ItemMapping mapping) {
|
||||
return javaIdentifierStripped.equals("crimson_fungus");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean canBeLeashed() {
|
||||
return isNotLeashed();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isEnemy() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
* 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
|
||||
|
@ -25,15 +25,63 @@
|
|||
|
||||
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;
|
||||
import org.geysermc.geyser.inventory.GeyserItemStack;
|
||||
import org.geysermc.geyser.inventory.item.StoredItemMappings;
|
||||
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 MooshroomEntity extends AnimalEntity {
|
||||
private boolean isBrown = false;
|
||||
|
||||
public MooshroomEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
public MooshroomEntity(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);
|
||||
}
|
||||
|
||||
public void setVariant(ObjectEntityMetadata<String> entityMetadata) {
|
||||
isBrown = entityMetadata.getValue().equals("brown");
|
||||
dirtyMetadata.put(EntityData.VARIANT, isBrown ? 1 : 0);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
protected InteractiveTag testMobInteraction(Hand hand, @Nonnull GeyserItemStack itemInHand) {
|
||||
StoredItemMappings storedItems = session.getItemMappings().getStoredItems();
|
||||
if (!isBaby()) {
|
||||
if (itemInHand.getJavaId() == storedItems.bowl()) {
|
||||
// Stew
|
||||
return InteractiveTag.MOOSHROOM_MILK_STEW;
|
||||
} else if (isAlive() && itemInHand.getJavaId() == storedItems.shears()) {
|
||||
// Shear items
|
||||
return InteractiveTag.MOOSHROOM_SHEAR;
|
||||
}
|
||||
}
|
||||
return super.testMobInteraction(hand, itemInHand);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) {
|
||||
StoredItemMappings storedItems = session.getItemMappings().getStoredItems();
|
||||
boolean isBaby = isBaby();
|
||||
if (!isBaby && itemInHand.getJavaId() == storedItems.bowl()) {
|
||||
// Stew
|
||||
return InteractionResult.SUCCESS;
|
||||
} else if (!isBaby && isAlive() && itemInHand.getJavaId() == storedItems.shears()) {
|
||||
// Shear items
|
||||
return InteractionResult.SUCCESS;
|
||||
} else if (isBrown && session.getTagCache().isSmallFlower(itemInHand) && itemInHand.getMapping(session).isHasSuspiciousStewEffect()) {
|
||||
// ?
|
||||
return InteractionResult.SUCCESS;
|
||||
}
|
||||
return super.mobInteract(hand, itemInHand);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
* 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
|
||||
|
@ -25,16 +25,22 @@
|
|||
|
||||
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.util.InteractionResult;
|
||||
import org.geysermc.geyser.util.InteractiveTag;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.UUID;
|
||||
|
||||
public class OcelotEntity extends AnimalEntity {
|
||||
|
||||
public OcelotEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
public OcelotEntity(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);
|
||||
}
|
||||
|
||||
|
@ -42,4 +48,26 @@ public class OcelotEntity extends AnimalEntity {
|
|||
public boolean canEat(String javaIdentifierStripped, ItemMapping mapping) {
|
||||
return javaIdentifierStripped.equals("cod") || javaIdentifierStripped.equals("salmon");
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
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(hand, itemInHand);
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
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(hand, itemInHand);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
* 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
|
||||
|
@ -27,22 +27,28 @@ 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;
|
||||
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.util.InteractionResult;
|
||||
import org.geysermc.geyser.util.InteractiveTag;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.UUID;
|
||||
|
||||
public class PandaEntity extends AnimalEntity {
|
||||
private int mainGene;
|
||||
private int hiddenGene;
|
||||
private Gene mainGene = Gene.NORMAL;
|
||||
private Gene hiddenGene = Gene.NORMAL;
|
||||
|
||||
public PandaEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
public PandaEntity(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);
|
||||
}
|
||||
|
||||
|
@ -61,12 +67,12 @@ public class PandaEntity extends AnimalEntity {
|
|||
}
|
||||
|
||||
public void setMainGene(ByteEntityMetadata entityMetadata) {
|
||||
mainGene = entityMetadata.getPrimitiveValue();
|
||||
mainGene = Gene.fromId(entityMetadata.getPrimitiveValue());
|
||||
updateAppearance();
|
||||
}
|
||||
|
||||
public void setHiddenGene(ByteEntityMetadata entityMetadata) {
|
||||
hiddenGene = entityMetadata.getPrimitiveValue();
|
||||
hiddenGene = Gene.fromId(entityMetadata.getPrimitiveValue());
|
||||
updateAppearance();
|
||||
}
|
||||
|
||||
|
@ -86,23 +92,81 @@ public class PandaEntity extends AnimalEntity {
|
|||
return javaIdentifierStripped.equals("bamboo");
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
protected InteractiveTag testMobInteraction(Hand hand, @Nonnull GeyserItemStack itemInHand) {
|
||||
if (mainGene == Gene.WORRIED && session.isThunder()) {
|
||||
return InteractiveTag.NONE;
|
||||
}
|
||||
return super.testMobInteraction(hand, itemInHand);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) {
|
||||
if (mainGene == Gene.WORRIED && session.isThunder()) {
|
||||
// Huh!
|
||||
return InteractionResult.PASS;
|
||||
} else if (getFlag(EntityFlag.LAYING_DOWN)) {
|
||||
// Stop the panda from laying down
|
||||
// TODO laying up is client-side?
|
||||
return InteractionResult.SUCCESS;
|
||||
} else if (canEat(itemInHand)) {
|
||||
if (getFlag(EntityFlag.BABY)) {
|
||||
playEntityEvent(EntityEventType.BABY_ANIMAL_FEED);
|
||||
}
|
||||
return InteractionResult.SUCCESS;
|
||||
}
|
||||
return InteractionResult.PASS;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean canBeLeashed() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the panda's appearance, and take into consideration the recessive brown and weak traits that only show up
|
||||
* when both main and hidden genes match
|
||||
*/
|
||||
private void updateAppearance() {
|
||||
if (mainGene == 4 || mainGene == 5) {
|
||||
// Main gene is a recessive trait
|
||||
if (mainGene.isRecessive) {
|
||||
if (mainGene == hiddenGene) {
|
||||
// Main and hidden genes match; this is what the panda looks like.
|
||||
dirtyMetadata.put(EntityData.VARIANT, mainGene);
|
||||
dirtyMetadata.put(EntityData.VARIANT, mainGene.ordinal());
|
||||
} else {
|
||||
// Genes have no effect on appearance
|
||||
dirtyMetadata.put(EntityData.VARIANT, 0);
|
||||
dirtyMetadata.put(EntityData.VARIANT, Gene.NORMAL.ordinal());
|
||||
}
|
||||
} else {
|
||||
// No need to worry about hidden gene
|
||||
dirtyMetadata.put(EntityData.VARIANT, mainGene);
|
||||
dirtyMetadata.put(EntityData.VARIANT, mainGene.ordinal());
|
||||
}
|
||||
}
|
||||
|
||||
enum Gene {
|
||||
NORMAL(false),
|
||||
LAZY(false),
|
||||
WORRIED(false),
|
||||
PLAYFUL(false),
|
||||
BROWN(true),
|
||||
WEAK(true),
|
||||
AGGRESSIVE(false);
|
||||
|
||||
private static final Gene[] VALUES = values();
|
||||
|
||||
private final boolean isRecessive;
|
||||
|
||||
Gene(boolean isRecessive) {
|
||||
this.isRecessive = isRecessive;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static Gene fromId(int id) {
|
||||
if (id < 0 || id >= VALUES.length) {
|
||||
return NORMAL;
|
||||
}
|
||||
return VALUES[id];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
* 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
|
||||
|
@ -25,16 +25,23 @@
|
|||
|
||||
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.util.EntityUtils;
|
||||
import org.geysermc.geyser.util.InteractionResult;
|
||||
import org.geysermc.geyser.util.InteractiveTag;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.UUID;
|
||||
|
||||
public class PigEntity extends AnimalEntity {
|
||||
|
||||
public PigEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
public PigEntity(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);
|
||||
}
|
||||
|
||||
|
@ -42,4 +49,37 @@ public class PigEntity extends AnimalEntity {
|
|||
public boolean canEat(String javaIdentifierStripped, ItemMapping mapping) {
|
||||
return javaIdentifierStripped.equals("carrot") || javaIdentifierStripped.equals("potato") || javaIdentifierStripped.equals("beetroot");
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
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(hand, itemInHand);
|
||||
if (superTag != InteractiveTag.NONE) {
|
||||
return superTag;
|
||||
} else {
|
||||
return EntityUtils.attemptToSaddle(session, this, itemInHand).consumesAction()
|
||||
? InteractiveTag.SADDLE : InteractiveTag.NONE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
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(hand, itemInHand);
|
||||
if (superResult.consumesAction()) {
|
||||
return superResult;
|
||||
} else {
|
||||
return EntityUtils.attemptToSaddle(session, this, itemInHand);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||
* 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
|
||||
|
@ -34,7 +34,7 @@ import java.util.UUID;
|
|||
|
||||
public class PolarBearEntity extends AnimalEntity {
|
||||
|
||||
public PolarBearEntity(GeyserSession session, long entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
public PolarBearEntity(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);
|
||||
}
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue