Merge remote-tracking branch 'origin/master' into feature/floodgate-merge

# Conflicts:
#	bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeePlugin.java
#	bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/GeyserFabricMod.java
#	bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotPlugin.java
#	bootstrap/standalone/src/main/java/org/geysermc/geyser/platform/standalone/GeyserStandaloneBootstrap.java
#	bootstrap/velocity/src/main/java/org/geysermc/geyser/platform/velocity/GeyserVelocityPlugin.java
#	bootstrap/velocity/src/main/java/org/geysermc/geyser/platform/velocity/floodgate/FloodgateModule.java
#	common/src/main/java/org/geysermc/floodgate/crypto/AesKeyProducer.java
#	common/src/main/java/org/geysermc/floodgate/crypto/FloodgateCipher.java
#	common/src/main/java/org/geysermc/floodgate/news/NewsItem.java
#	common/src/main/java/org/geysermc/floodgate/news/NewsItemMessage.java
#	common/src/main/java/org/geysermc/floodgate/news/NewsType.java
#	common/src/main/java/org/geysermc/floodgate/news/data/BuildSpecificData.java
#	common/src/main/java/org/geysermc/floodgate/news/data/ConfigSpecificData.java
#	common/src/main/java/org/geysermc/floodgate/util/BedrockData.java
#	common/src/main/java/org/geysermc/floodgate/util/LinkedPlayer.java
#	common/src/main/java/org/geysermc/floodgate/util/WebsocketEventType.java
#	core/src/main/java/org/geysermc/geyser/GeyserBootstrap.java
#	core/src/main/java/org/geysermc/geyser/GeyserImpl.java
#	core/src/main/java/org/geysermc/geyser/floodgate/FloodgateProvider.java
#	core/src/main/java/org/geysermc/geyser/floodgate/GeyserLoadStage.java
#	core/src/main/java/org/geysermc/geyser/floodgate/NoFloodgateProvider.java
#	core/src/main/java/org/geysermc/geyser/network/netty/LocalSession.java
#	core/src/main/java/org/geysermc/geyser/session/GeyserSession.java
#	gradle.properties
This commit is contained in:
Tim203 2024-02-18 16:37:26 +01:00
commit c8fd024e4a
No known key found for this signature in database
371 changed files with 15591 additions and 11773 deletions

View file

@ -25,6 +25,8 @@
package org.geysermc.geyser;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.geysermc.floodgate.core.skin.SkinApplier;
import org.geysermc.geyser.command.GeyserCommandManager;
import org.geysermc.geyser.configuration.GeyserConfiguration;
@ -33,8 +35,6 @@ import org.geysermc.geyser.level.GeyserWorldManager;
import org.geysermc.geyser.level.WorldManager;
import org.geysermc.geyser.ping.IGeyserPingPassthrough;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.io.InputStream;
import java.net.SocketAddress;
import java.nio.file.Path;
@ -45,14 +45,28 @@ public interface GeyserBootstrap {
GeyserWorldManager DEFAULT_CHUNK_MANAGER = new GeyserWorldManager();
/**
* Called when the GeyserBootstrap is enabled
* Called when the GeyserBootstrap is initialized.
* This will only be called once, when Geyser is loading. Calling this must
* happen before {@link #onGeyserEnable()}, since this "sets up" Geyser.
*/
void onEnable();
void onGeyserInitialize();
/**
* Called when the GeyserBootstrap is disabled
* Called when the GeyserBootstrap is enabled/reloaded.
* This starts Geyser, after which, Geyser is in a player-accepting state.
*/
void onDisable();
void onGeyserEnable();
/**
* Called when the GeyserBootstrap is disabled - either before a reload,
* of before fully shutting down.
*/
void onGeyserDisable();
/**
* Called when the GeyserBootstrap is shutting down.
*/
void onGeyserShutdown();
/**
* Returns the current GeyserConfiguration
@ -80,6 +94,7 @@ public interface GeyserBootstrap {
*
* @return The current PingPassthrough manager
*/
@Nullable
IGeyserPingPassthrough getGeyserPingPassthrough();
/**
@ -159,7 +174,7 @@ public interface GeyserBootstrap {
* @param resource Resource to get
* @return InputStream of the given resource
*/
default @Nonnull InputStream getResource(String resource) {
default @NonNull InputStream getResourceOrThrow(@NonNull String resource) {
InputStream stream = getResourceOrNull(resource);
if (stream == null) {
throw new AssertionError("Unable to find resource: " + resource);
@ -170,7 +185,7 @@ public interface GeyserBootstrap {
/**
* @return the bind address being used by the Java server.
*/
@Nonnull
@NonNull
String getServerBindAddress();
/**

View file

@ -42,7 +42,11 @@ import net.kyori.adventure.text.format.NamedTextColor;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.cloudburstmc.protocol.bedrock.codec.BedrockCodec;
import org.geysermc.api.Geyser;
import org.geysermc.geyser.api.command.CommandSource;
import org.geysermc.geyser.api.util.MinecraftVersion;
import org.geysermc.geyser.api.util.PlatformType;
import org.geysermc.cumulus.form.Form;
import org.geysermc.cumulus.form.util.FormBuilder;
import org.geysermc.erosion.packet.Packets;
@ -51,13 +55,10 @@ import org.geysermc.floodgate.news.NewsItemAction;
import org.geysermc.geyser.api.GeyserApi;
import org.geysermc.geyser.api.event.EventBus;
import org.geysermc.geyser.api.event.EventRegistrar;
import org.geysermc.geyser.api.event.lifecycle.GeyserPostInitializeEvent;
import org.geysermc.geyser.api.event.lifecycle.GeyserPreInitializeEvent;
import org.geysermc.geyser.api.event.lifecycle.GeyserShutdownEvent;
import org.geysermc.geyser.api.event.lifecycle.*;
import org.geysermc.geyser.api.network.AuthType;
import org.geysermc.geyser.api.network.BedrockListener;
import org.geysermc.geyser.api.network.RemoteServer;
import org.geysermc.geyser.api.util.PlatformType;
import org.geysermc.geyser.command.GeyserCommandManager;
import org.geysermc.geyser.configuration.GeyserConfiguration;
import org.geysermc.geyser.entity.EntityDefinitions;
@ -68,10 +69,13 @@ import org.geysermc.geyser.floodgate.FloodgateProvider;
import org.geysermc.geyser.floodgate.IntegratedFloodgateProvider;
import org.geysermc.geyser.floodgate.NoFloodgateProvider;
import org.geysermc.geyser.floodgate.ProxyFloodgateProvider;
import org.geysermc.geyser.impl.MinecraftVersionImpl;
import org.geysermc.geyser.level.WorldManager;
import org.geysermc.geyser.network.GameProtocol;
import org.geysermc.geyser.network.netty.GeyserServer;
import org.geysermc.geyser.registry.BlockRegistries;
import org.geysermc.geyser.registry.Registries;
import org.geysermc.geyser.registry.provider.ProviderSupplier;
import org.geysermc.geyser.scoreboard.ScoreboardUpdater;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.session.PendingMicrosoftAuthentication;
@ -110,8 +114,8 @@ public class GeyserImpl implements GeyserApi {
.enable(JsonParser.Feature.ALLOW_SINGLE_QUOTES);
public static final String NAME = "Geyser";
public static final String GIT_VERSION = "${gitVersion}"; // A fallback for running in IDEs
public static final String VERSION = "${version}"; // A fallback for running in IDEs
public static final String GIT_VERSION = "${gitVersion}";
public static final String VERSION = "${version}";
public static final String BUILD_NUMBER = "${buildNumber}";
public static final String BRANCH = "${branch}";
@ -139,6 +143,7 @@ public class GeyserImpl implements GeyserApi {
private UnixSocketClientListener erosionUnixListener;
@Setter
private volatile boolean shuttingDown = false;
private ScheduledExecutorService scheduledThread;
@ -156,9 +161,15 @@ public class GeyserImpl implements GeyserApi {
@Getter(AccessLevel.NONE)
private Map<String, String> savedRefreshTokens;
@Getter
private static GeyserImpl instance;
/**
* Determines if we're currently reloading. Replaces per-bootstrap reload checks
*/
private volatile boolean isReloading;
private GeyserImpl(PlatformType platformType, GeyserBootstrap bootstrap, FloodgatePlatform floodgatePlatform) {
instance = this;
@ -180,13 +191,16 @@ public class GeyserImpl implements GeyserApi {
this.platformType = platformType;
this.bootstrap = bootstrap;
GeyserLocale.finalizeDefaultLocale(this);
/* Initialize event bus */
this.eventBus = new GeyserEventBus();
/* Load Extensions */
/* Create Extension Manager */
this.extensionManager = new GeyserExtensionManager();
/* Finalize locale loading now that we know the default locale from the config */
GeyserLocale.finalizeDefaultLocale(this);
/* Load Extensions */
this.extensionManager.init();
this.eventBus.fire(new GeyserPreInitializeEvent(this.extensionManager, this.eventBus));
}
@ -244,11 +258,17 @@ public class GeyserImpl implements GeyserApi {
} else if (config.getRemote().authType() == AuthType.FLOODGATE) {
VersionCheckUtils.checkForOutdatedFloodgate(logger);
}
VersionCheckUtils.checkForOutdatedJava(logger);
}
private void startInstance() {
this.scheduledThread = Executors.newSingleThreadScheduledExecutor(new DefaultThreadFactory("Geyser Scheduled Thread"));
if (isReloading) {
// If we're reloading, the default locale in the config might have changed.
GeyserLocale.finalizeDefaultLocale(this);
}
GeyserLogger logger = bootstrap.getGeyserLogger();
GeyserConfiguration config = bootstrap.getGeyserConfig();
@ -322,6 +342,22 @@ public class GeyserImpl implements GeyserApi {
}
}
String broadcastPort = System.getProperty("geyserBroadcastPort", "");
if (!broadcastPort.isEmpty()) {
int parsedPort;
try {
parsedPort = Integer.parseInt(broadcastPort);
if (parsedPort < 1 || parsedPort > 65535) {
throw new NumberFormatException("The broadcast port must be between 1 and 65535 inclusive!");
}
} catch (NumberFormatException e) {
logger.error(String.format("Invalid broadcast port: %s! Defaulting to configured port.", broadcastPort + " (" + e.getMessage() + ")"));
parsedPort = config.getBedrock().port();
}
config.getBedrock().setBroadcastPort(parsedPort);
logger.info("Broadcast port set from system property: " + parsedPort);
}
boolean floodgatePresent = bootstrap.testFloodgatePluginPresent() || floodgateProvider != null; //todo
if (config.getRemote().authType() == AuthType.FLOODGATE && !floodgatePresent) {
logger.severe(GeyserLocale.getLocaleStringLog("geyser.bootstrap.floodgate.not_installed") + " "
@ -526,12 +562,15 @@ public class GeyserImpl implements GeyserApi {
newsHandler.handleNews(null, NewsItemAction.ON_SERVER_STARTED);
this.eventBus.fire(new GeyserPostInitializeEvent(this.extensionManager, this.eventBus));
if (isReloading) {
this.eventBus.fire(new GeyserPostReloadEvent(this.extensionManager, this.eventBus));
} else {
this.eventBus.fire(new GeyserPostInitializeEvent(this.extensionManager, this.eventBus));
}
if (config.isNotifyOnNewBedrockUpdate()) {
VersionCheckUtils.checkForGeyserUpdate(this::getLogger);
}
VersionCheckUtils.checkForOutdatedJava(logger);
}
@Override
@ -590,9 +629,8 @@ public class GeyserImpl implements GeyserApi {
return session.transfer(address, port);
}
public void shutdown() {
public void disable() {
bootstrap.getGeyserLogger().info(GeyserLocale.getLocaleStringLog("geyser.core.shutdown"));
shuttingDown = true;
if (sessionManager.size() >= 1) {
bootstrap.getGeyserLogger().info(GeyserLocale.getLocaleStringLog("geyser.core.shutdown.kick.log", sessionManager.size()));
@ -606,7 +644,6 @@ public class GeyserImpl implements GeyserApi {
skinUploader.close();
}
newsHandler.shutdown();
this.commandManager().getCommands().clear();
if (this.erosionUnixListener != null) {
this.erosionUnixListener.close();
@ -614,16 +651,29 @@ public class GeyserImpl implements GeyserApi {
Registries.RESOURCE_PACKS.get().clear();
bootstrap.getGeyserLogger().info(GeyserLocale.getLocaleStringLog("geyser.core.shutdown.done"));
}
public void shutdown() {
shuttingDown = true;
this.disable();
this.commandManager().getCommands().clear();
// Disable extensions, fire the shutdown event
this.eventBus.fire(new GeyserShutdownEvent(this.extensionManager, this.eventBus));
this.extensionManager.disableExtensions();
bootstrap.getGeyserLogger().info(GeyserLocale.getLocaleStringLog("geyser.core.shutdown.done"));
}
public void reload() {
shutdown();
this.extensionManager.enableExtensions();
bootstrap.onEnable();
public void reloadGeyser() {
isReloading = true;
this.eventBus.fire(new GeyserPreReloadEvent(this.extensionManager, this.eventBus));
bootstrap.onGeyserDisable();
bootstrap.onGeyserEnable();
isReloading = false;
}
/**
@ -634,7 +684,7 @@ public class GeyserImpl implements GeyserApi {
*/
public boolean isProductionEnvironment() {
// First is if Blossom runs, second is if Blossom doesn't run
// noinspection ConstantConditions - changes in production
//noinspection ConstantConditions,MismatchedStringCase - changes in production
return !("git-local/dev-0000000".equals(GeyserImpl.GIT_VERSION) || "${gitVersion}".equals(GeyserImpl.GIT_VERSION));
}
@ -650,8 +700,13 @@ public class GeyserImpl implements GeyserApi {
}
@Override
@SuppressWarnings("unchecked")
public <R extends T, T> @NonNull R provider(@NonNull Class<T> apiClass, @Nullable Object... args) {
return (R) Registries.PROVIDERS.get(apiClass).create(args);
ProviderSupplier provider = Registries.PROVIDERS.get(apiClass);
if (provider == null) {
throw new IllegalArgumentException("No provider found for " + apiClass);
}
return (R) provider.create(args);
}
@Override
@ -689,6 +744,25 @@ public class GeyserImpl implements GeyserApi {
return platformType;
}
@Override
public @NonNull MinecraftVersion supportedJavaVersion() {
return new MinecraftVersionImpl(GameProtocol.getJavaMinecraftVersion(), GameProtocol.getJavaProtocolVersion());
}
@Override
public @NonNull List<MinecraftVersion> supportedBedrockVersions() {
ArrayList<MinecraftVersion> versions = new ArrayList<>();
for (BedrockCodec codec : GameProtocol.SUPPORTED_BEDROCK_CODECS) {
versions.add(new MinecraftVersionImpl(codec.getMinecraftVersion(), codec.getProtocolVersion()));
}
return Collections.unmodifiableList(versions);
}
@Override
public @NonNull CommandSource consoleCommandSource() {
return getLogger();
}
public int buildNumber() {
if (!this.isProductionEnvironment()) {
return 0;
@ -710,9 +784,7 @@ public class GeyserImpl implements GeyserApi {
throw new RuntimeException("Geyser has not been loaded yet!");
}
// We've been reloaded
if (instance.isShuttingDown()) {
instance.shuttingDown = false;
if (getInstance().isReloading()) {
instance.startInstance();
} else {
instance.initialize();
@ -763,8 +835,4 @@ public class GeyserImpl implements GeyserApi {
}
});
}
public static GeyserImpl getInstance() {
return instance;
}
}

View file

@ -26,9 +26,10 @@
package org.geysermc.geyser;
import net.kyori.adventure.text.Component;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.geysermc.geyser.command.GeyserCommandSource;
import javax.annotation.Nullable;
public interface GeyserLogger extends GeyserCommandSource {
@ -119,7 +120,7 @@ public interface GeyserLogger extends GeyserCommandSource {
}
@Override
default void sendMessage(String message) {
default void sendMessage(@NonNull String message) {
info(message);
}

View file

@ -30,6 +30,7 @@ import java.io.InputStream;
import java.lang.reflect.Method;
import java.nio.charset.StandardCharsets;
import java.util.Locale;
import java.util.Objects;
import java.util.Scanner;
public class GeyserMain {
@ -61,8 +62,8 @@ public class GeyserMain {
helpStream = GeyserMain.class.getClassLoader().getResourceAsStream("languages/run-help/en_US.txt");
}
Scanner help = new Scanner(helpStream, StandardCharsets.UTF_8).useDelimiter("\\Z");
String line = "";
Scanner help = new Scanner(Objects.requireNonNull(helpStream), StandardCharsets.UTF_8).useDelimiter("\\Z");
String line;
while (help.hasNext()) {
line = help.next();

View file

@ -29,10 +29,10 @@ import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.experimental.Accessors;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.geysermc.geyser.api.command.Command;
import org.geysermc.geyser.session.GeyserSession;
import javax.annotation.Nullable;
import java.util.Collections;
import java.util.List;
@ -73,15 +73,6 @@ public abstract class GeyserCommand implements Command {
return Collections.emptyList();
}
/**
* Shortcut to {@link #subCommands()} ()}{@code .isEmpty()}.
*
* @return true if there are subcommand present for this command.
*/
public boolean hasSubCommands() {
return !this.subCommands().isEmpty();
}
public void setAliases(List<String> aliases) {
this.aliases = aliases;
}

View file

@ -26,11 +26,11 @@
package org.geysermc.geyser.command;
import lombok.AllArgsConstructor;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.api.command.Command;
import org.geysermc.geyser.session.GeyserSession;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

View file

@ -29,6 +29,7 @@ import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.geysermc.geyser.api.util.PlatformType;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.api.command.Command;
@ -53,8 +54,6 @@ import org.geysermc.geyser.event.type.GeyserDefineCommandsEventImpl;
import org.geysermc.geyser.extension.command.GeyserExtensionCommand;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.text.GeyserLocale;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collections;
import java.util.HashMap;
@ -87,7 +86,7 @@ public class GeyserCommandManager {
registerBuiltInCommand(new StopCommand(geyser, "stop", "geyser.commands.stop.desc", "geyser.command.stop"));
}
if (this.geyser.extensionManager().extensions().size() > 0) {
if (!this.geyser.extensionManager().extensions().isEmpty()) {
registerBuiltInCommand(new ExtensionsCommand(this.geyser, "extensions", "geyser.commands.extensions.desc", "geyser.command.extensions"));
}
@ -136,12 +135,12 @@ public class GeyserCommandManager {
}
}
@NotNull
@NonNull
public Map<String, Command> commands() {
return Collections.unmodifiableMap(this.commands);
}
@NotNull
@NonNull
public Map<Extension, Map<String, Command>> extensionCommands() {
return Collections.unmodifiableMap(this.extensionCommands);
}

View file

@ -26,16 +26,19 @@
package org.geysermc.geyser.command.defaults;
import com.fasterxml.jackson.databind.JsonNode;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.api.util.PlatformType;
import org.geysermc.geyser.command.GeyserCommand;
import org.geysermc.geyser.command.GeyserCommandSource;
import org.geysermc.geyser.configuration.GeyserConfiguration;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.text.GeyserLocale;
import org.geysermc.geyser.util.LoopbackUtil;
import org.geysermc.geyser.util.WebUtils;
import org.jetbrains.annotations.Nullable;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Random;
import java.util.concurrent.CompletableFuture;
@ -82,7 +85,7 @@ public class ConnectionTestCommand extends GeyserCommand {
return;
}
} else {
port = 19132;
port = geyser.getConfig().getBedrock().broadcastPort();
}
String ip = fullAddress[0];
@ -104,30 +107,47 @@ public class ConnectionTestCommand extends GeyserCommand {
return;
}
// Issue: do the ports not line up?
if (port != geyser.getConfig().getBedrock().port()) {
if (fullAddress.length == 2) {
sender.sendMessage("The port you are testing with (" + port + ") is not the same as you set in your Geyser configuration ("
+ geyser.getConfig().getBedrock().port() + ")");
sender.sendMessage("Re-run the command with the port in the config, or change the `bedrock` `port` in the config.");
if (geyser.getConfig().getBedrock().isCloneRemotePort()) {
sender.sendMessage("You have `clone-remote-port` enabled. This option ignores the `bedrock` `port` in the config, and uses the Java server port instead.");
// Issue: port out of bounds
if (port <= 0 || port >= 65535) {
sender.sendMessage("The port you specified is invalid! Please specify a valid port.");
return;
}
GeyserConfiguration config = geyser.getConfig();
// Issue: do the ports not line up? We only check this if players don't override the broadcast port - if they do, they (hopefully) know what they're doing
if (config.getBedrock().broadcastPort() == config.getBedrock().port()) {
if (port != config.getBedrock().port()) {
if (fullAddress.length == 2) {
sender.sendMessage("The port you are testing with (" + port + ") is not the same as you set in your Geyser configuration ("
+ config.getBedrock().port() + ")");
sender.sendMessage("Re-run the command with the port in the config, or change the `bedrock` `port` in the config.");
if (config.getBedrock().isCloneRemotePort()) {
sender.sendMessage("You have `clone-remote-port` enabled. This option ignores the `bedrock` `port` in the config, and uses the Java server port instead.");
}
} else {
sender.sendMessage("You did not specify the port to check (add it with \":<port>\"), " +
"and the default port 19132 does not match the port in your Geyser configuration ("
+ config.getBedrock().port() + ")!");
sender.sendMessage("Re-run the command with that port, or change the port in the config under `bedrock` `port`.");
}
} else {
sender.sendMessage("You did not specify the port to check (add it with \":<port>\"), " +
"and the default port 19132 does not match the port in your Geyser configuration ("
+ geyser.getConfig().getBedrock().port() + ")!");
sender.sendMessage("Re-run the command with that port, or change the port in the config under `bedrock` `port`.");
}
} else {
if (config.getBedrock().broadcastPort() != port) {
sender.sendMessage("The port you are testing with (" + port + ") is not the same as the broadcast port set in your Geyser configuration ("
+ config.getBedrock().broadcastPort() + "). ");
sender.sendMessage("You ONLY need to change the broadcast port if clients connects with a port different from the port Geyser is running on.");
sender.sendMessage("Re-run the command with the port in the config, or change the `bedrock` `broadcast-port` in the config.");
}
}
// Issue: is the `bedrock` `address` in the config different?
if (!geyser.getConfig().getBedrock().address().equals("0.0.0.0")) {
if (!config.getBedrock().address().equals("0.0.0.0")) {
sender.sendMessage("The address specified in `bedrock` `address` is not \"0.0.0.0\" - this may cause issues unless this is deliberate and intentional.");
}
// Issue: did someone turn on enable-proxy-protocol, and they didn't mean it?
if (geyser.getConfig().getBedrock().isEnableProxyProtocol()) {
if (config.getBedrock().isEnableProxyProtocol()) {
sender.sendMessage("You have the `enable-proxy-protocol` setting enabled. " +
"Unless you're deliberately using additional software that REQUIRES this setting, you may not need it enabled.");
}
@ -158,23 +178,24 @@ public class ConnectionTestCommand extends GeyserCommand {
String connectionTestMotd = "Geyser Connection Test " + randomStr;
CONNECTION_TEST_MOTD = connectionTestMotd;
sender.sendMessage("Testing server connection now. Please wait...");
sender.sendMessage("Testing server connection to " + ip + " with port: " + port + " now. Please wait...");
JsonNode output;
try {
output = WebUtils.getJson("https://checker.geysermc.org/ping?hostname=" + ip + "&port=" + port);
String hostname = URLEncoder.encode(ip, StandardCharsets.UTF_8);
output = WebUtils.getJson("https://checker.geysermc.org/ping?hostname=" + hostname + "&port=" + port);
} finally {
CONNECTION_TEST_MOTD = null;
}
JsonNode cache = output.get("cache");
String when;
if (cache.get("fromCache").asBoolean()) {
when = cache.get("secondsSince").asInt() + " seconds ago";
} else {
when = "now";
}
if (output.get("success").asBoolean()) {
JsonNode cache = output.get("cache");
String when;
if (cache.get("fromCache").asBoolean()) {
when = cache.get("secondsSince").asInt() + " seconds ago";
} else {
when = "now";
}
JsonNode ping = output.get("ping");
JsonNode pong = ping.get("pong");
String remoteMotd = pong.get("motd").asText();
@ -196,7 +217,11 @@ public class ConnectionTestCommand extends GeyserCommand {
return;
}
sender.sendMessage("Your server is likely unreachable from outside the network as of " + when + ".");
sender.sendMessage("Your server is likely unreachable from outside the network!");
JsonNode message = output.get("message");
if (message != null && !message.asText().isEmpty()) {
sender.sendMessage("Got the error message: " + message.asText());
}
sendLinks(sender);
} catch (Exception e) {
sender.sendMessage("An error occurred while trying to check your connection! Check the console for more information.");

View file

@ -98,7 +98,7 @@ public class DumpCommand extends GeyserCommand {
return;
}
String uploadedDumpUrl = "";
String uploadedDumpUrl;
if (offlineDump) {
sender.sendMessage(GeyserLocale.getPlayerLocaleString("geyser.commands.dump.writing", sender.locale()));

View file

@ -25,6 +25,7 @@
package org.geysermc.geyser.command.defaults;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.api.extension.Extension;
import org.geysermc.geyser.command.GeyserCommand;
@ -32,7 +33,6 @@ import org.geysermc.geyser.command.GeyserCommandSource;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.text.ChatColor;
import org.geysermc.geyser.text.GeyserLocale;
import org.jetbrains.annotations.Nullable;
import java.util.Comparator;
import java.util.List;

View file

@ -32,6 +32,8 @@ import org.geysermc.geyser.command.GeyserCommandSource;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.text.GeyserLocale;
import java.util.concurrent.TimeUnit;
public class ReloadCommand extends GeyserCommand {
private final GeyserImpl geyser;
@ -52,7 +54,8 @@ public class ReloadCommand extends GeyserCommand {
sender.sendMessage(message);
geyser.getSessionManager().disconnectAll("geyser.commands.reload.kick");
geyser.reload();
//FIXME Without the tiny wait, players do not get kicked - same happens when Geyser tries to disconnect all sessions on shutdown
geyser.getScheduledThread().schedule(geyser::reloadGeyser, 10, TimeUnit.MILLISECONDS);
}
@Override

View file

@ -52,7 +52,7 @@ public class StopCommand extends GeyserCommand {
return;
}
geyser.getBootstrap().onDisable();
geyser.getBootstrap().onGeyserShutdown();
}
@Override

View file

@ -27,8 +27,8 @@ package org.geysermc.geyser.command.defaults;
import org.cloudburstmc.protocol.bedrock.codec.BedrockCodec;
import org.geysermc.geyser.Constants;
import org.geysermc.geyser.api.util.PlatformType;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.api.util.PlatformType;
import org.geysermc.geyser.command.GeyserCommand;
import org.geysermc.geyser.command.GeyserCommandSource;
import org.geysermc.geyser.network.GameProtocol;
@ -37,7 +37,6 @@ import org.geysermc.geyser.text.ChatColor;
import org.geysermc.geyser.text.GeyserLocale;
import org.geysermc.geyser.util.WebUtils;
import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.List;
@ -77,7 +76,7 @@ public class VersionCommand extends GeyserCommand {
sender.sendMessage(GeyserLocale.getPlayerLocaleString("geyser.commands.version.checking", sender.locale()));
try {
String buildXML = WebUtils.getBody("https://ci.opencollab.dev/job/GeyserMC/job/Geyser/job/" +
URLEncoder.encode(GeyserImpl.BRANCH, StandardCharsets.UTF_8.toString()) + "/lastSuccessfulBuild/api/xml?xpath=//buildNumber");
URLEncoder.encode(GeyserImpl.BRANCH, StandardCharsets.UTF_8) + "/lastSuccessfulBuild/api/xml?xpath=//buildNumber");
if (buildXML.startsWith("<buildNumber>")) {
int latestBuildNum = Integer.parseInt(buildXML.replaceAll("<(\\\\)?(/)?buildNumber>", "").trim());
int buildNum = this.geyser.buildNumber();
@ -90,7 +89,7 @@ public class VersionCommand extends GeyserCommand {
} else {
throw new AssertionError("buildNumber missing");
}
} catch (IOException e) {
} catch (Exception e) {
GeyserImpl.getInstance().getLogger().error(GeyserLocale.getLocaleStringLog("geyser.commands.version.failed"), e);
sender.sendMessage(ChatColor.RED + GeyserLocale.getPlayerLocaleString("geyser.commands.version.failed", sender.locale()));
}

View file

@ -54,14 +54,12 @@ public interface GeyserConfiguration {
List<String> getSavedUserLogins();
@SuppressWarnings("BooleanMethodIsAlwaysInverted")
boolean isCommandSuggestions();
@JsonIgnore
boolean isPassthroughMotd();
@JsonIgnore
boolean isPassthroughProtocolName();
@JsonIgnore
boolean isPassthroughPlayerCounts();
@ -98,6 +96,7 @@ public interface GeyserConfiguration {
boolean isForceResourcePacks();
@SuppressWarnings("BooleanMethodIsAlwaysInverted")
boolean isXboxAchievementsEnabled();
int getCacheImages();
@ -125,6 +124,8 @@ public interface GeyserConfiguration {
void setPort(int port);
void setBroadcastPort(int broadcastPort);
boolean isCloneRemotePort();
int getCompressionLevel();

View file

@ -34,6 +34,7 @@ import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import lombok.Getter;
import lombok.Setter;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.api.network.AuthType;
import org.geysermc.geyser.network.CIDRMatcher;
@ -87,9 +88,6 @@ public abstract class GeyserJacksonConfiguration implements GeyserConfiguration
@JsonProperty("passthrough-player-counts")
private boolean isPassthroughPlayerCounts = false;
@JsonProperty("passthrough-protocol-name")
private boolean isPassthroughProtocolName = false;
@JsonProperty("legacy-ping-passthrough")
private boolean isLegacyPingPassthrough = false;
@ -173,7 +171,7 @@ public abstract class GeyserJacksonConfiguration implements GeyserConfiguration
private String address = "0.0.0.0";
@Override
public String address() {
public @NonNull String address() {
return address;
}
@ -186,6 +184,15 @@ public abstract class GeyserJacksonConfiguration implements GeyserConfiguration
return port;
}
@Setter
@JsonProperty("broadcast-port")
private int broadcastPort = 0;
@Override
public int broadcastPort() {
return broadcastPort;
}
@Getter
@JsonProperty("clone-remote-port")
private boolean cloneRemotePort = false;
@ -275,7 +282,7 @@ public abstract class GeyserJacksonConfiguration implements GeyserConfiguration
private AuthType authType = AuthType.ONLINE;
@Override
public AuthType authType() {
public @NonNull AuthType authType() {
return authType;
}

View file

@ -33,7 +33,6 @@ import com.google.common.io.ByteSource;
import com.google.common.io.Files;
import it.unimi.dsi.fastutil.objects.Object2IntMap;
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.cloudburstmc.protocol.bedrock.codec.BedrockCodec;
import org.geysermc.api.util.BedrockPlatform;
@ -105,8 +104,8 @@ public class DumpInfo {
// https://stackoverflow.com/questions/304268/getting-a-files-md5-checksum-in-java
File file = new File(DumpInfo.class.getProtectionDomain().getCodeSource().getLocation().toURI());
ByteSource byteSource = Files.asByteSource(file);
// Jenkins uses MD5 for its hash
//noinspection UnstableApiUsage
// Jenkins uses MD5 for its hash - TODO remove
//noinspection UnstableApiUsage,deprecation
md5Hash = byteSource.hash(Hashing.md5()).toString();
//noinspection UnstableApiUsage
sha256Hash = byteSource.hash(Hashing.sha256()).toString();
@ -117,7 +116,7 @@ public class DumpInfo {
}
this.hashInfo = new HashInfo(md5Hash, sha256Hash);
this.ramInfo = new DumpInfo.RamInfo();
this.ramInfo = new RamInfo();
if (addLog) {
this.logsInfo = new LogsInfo();
@ -201,7 +200,7 @@ public class DumpInfo {
private boolean checkDockerBasic() {
try {
String OS = System.getProperty("os.name").toLowerCase();
if (OS.indexOf("nix") >= 0 || OS.indexOf("nux") >= 0 || OS.indexOf("aix") > 0) {
if (OS.contains("nix") || OS.contains("nux") || OS.indexOf("aix") > 0) {
String output = new String(java.nio.file.Files.readAllBytes(Paths.get("/proc/1/cgroup")));
if (output.contains("docker")) {
@ -261,60 +260,30 @@ public class DumpInfo {
}
}
@AllArgsConstructor
@Getter
public static class HashInfo {
private final String md5Hash;
private final String sha256Hash;
public record HashInfo(String md5Hash, String sha256Hash) {
}
@Getter
public static class RamInfo {
private final long free;
private final long total;
private final long max;
RamInfo() {
this.free = Runtime.getRuntime().freeMemory() / MEGABYTE;
this.total = Runtime.getRuntime().totalMemory() / MEGABYTE;
this.max = Runtime.getRuntime().maxMemory() / MEGABYTE;
public record RamInfo(long free, long total, long max) {
public RamInfo() {
this(Runtime.getRuntime().freeMemory() / MEGABYTE,
Runtime.getRuntime().totalMemory() / MEGABYTE,
Runtime.getRuntime().maxMemory() / MEGABYTE);
}
}
/**
* E.G. `-Xmx1024M` - all runtime JVM flags on this machine
*/
@Getter
public static class FlagsInfo {
private final List<String> flags;
FlagsInfo() {
this.flags = ManagementFactory.getRuntimeMXBean().getInputArguments();
public record FlagsInfo(List<String> flags) {
public FlagsInfo() {
this(ManagementFactory.getRuntimeMXBean().getInputArguments());
}
}
@Getter
@AllArgsConstructor
public static class ExtensionInfo {
public boolean enabled;
public String name;
public String version;
public String apiVersion;
public String main;
public List<String> authors;
public record ExtensionInfo(boolean enabled, String name, String version, String apiVersion, String main, List<String> authors) {
}
@Getter
@AllArgsConstructor
public static class GitInfo {
private final String buildNumber;
@JsonProperty("git.commit.id.abbrev")
private final String commitHashAbbrev;
@JsonProperty("git.commit.id")
private final String commitHash;
@JsonProperty("git.branch")
private final String branchName;
@JsonProperty("git.remote.origin.url")
private final String originUrl;
public record GitInfo(String buildNumber, @JsonProperty("git.commit.id.abbrev") String commitHashAbbrev, @JsonProperty("git.commit.id") String commitHash,
@JsonProperty("git.branch") String branchName, @JsonProperty("git.remote.origin.url") String originUrl) {
}
}

View file

@ -59,6 +59,7 @@ public record EntityDefinition<T extends Entity>(EntityFactory<T> factory, Entit
return new Builder<>(factory);
}
@SuppressWarnings("unchecked")
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) {

View file

@ -299,8 +299,9 @@ public final class EntityDefinitions {
.build();
EntityDefinition<Entity> displayBase = EntityDefinition.inherited(entityBase.factory(), entityBase)
.addTranslator(null) // Interpolation start ticks
.addTranslator(null) // Interpolation duration ID
.addTranslator(null) // Interpolation delay
.addTranslator(null) // Transformation interpolation duration
.addTranslator(null) // Position/Rotation interpolation duration
.addTranslator(null) // Translation
.addTranslator(null) // Scale
.addTranslator(null) // Left rotation
@ -318,6 +319,10 @@ public final class EntityDefinitions {
.type(EntityType.TEXT_DISPLAY)
.identifier("minecraft:armor_stand")
.addTranslator(MetadataType.CHAT, TextDisplayEntity::setText)
.addTranslator(null) // Line width
.addTranslator(null) // Background color
.addTranslator(null) // Text opacity
.addTranslator(null) // Bit mask
.build();
INTERACTION = EntityDefinition.inherited(InteractionEntity::new, entityBase)

View file

@ -0,0 +1,99 @@
/*
* Copyright (c) 2019-2023 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 org.checkerframework.checker.index.qual.NonNegative;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.cloudburstmc.protocol.bedrock.packet.EmotePacket;
import org.geysermc.geyser.api.entity.EntityData;
import org.geysermc.geyser.api.entity.type.GeyserEntity;
import org.geysermc.geyser.api.entity.type.player.GeyserPlayerEntity;
import org.geysermc.geyser.entity.type.Entity;
import org.geysermc.geyser.session.GeyserSession;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
public class GeyserEntityData implements EntityData {
private final GeyserSession session;
private final Set<UUID> movementLockOwners = new HashSet<>();
public GeyserEntityData(GeyserSession session) {
this.session = session;
}
@Override
public @NonNull CompletableFuture<@Nullable GeyserEntity> entityByJavaId(@NonNegative int javaId) {
CompletableFuture<GeyserEntity> future = new CompletableFuture<>();
session.ensureInEventLoop(() -> future.complete(session.getEntityCache().getEntityByJavaId(javaId)));
return future;
}
@Override
public void showEmote(@NonNull GeyserPlayerEntity emoter, @NonNull String emoteId) {
Objects.requireNonNull(emoter, "emoter must not be null!");
Entity entity = (Entity) emoter;
if (entity.getSession() != session) {
throw new IllegalStateException("Given entity must be from this session!");
}
EmotePacket packet = new EmotePacket();
packet.setRuntimeEntityId(entity.getGeyserId());
packet.setXuid("");
packet.setPlatformId(""); // BDS sends empty
packet.setEmoteId(emoteId);
session.sendUpstreamPacket(packet);
}
@Override
public @NonNull GeyserPlayerEntity playerEntity() {
return session.getPlayerEntity();
}
@Override
public boolean lockMovement(boolean lock, @NonNull UUID owner) {
Objects.requireNonNull(owner, "owner must not be null!");
if (lock) {
movementLockOwners.add(owner);
} else {
movementLockOwners.remove(owner);
}
session.lockInputs(session.camera().isCameraLocked(), isMovementLocked());
return isMovementLocked();
}
@Override
public boolean isMovementLocked() {
return !movementLockOwners.isEmpty();
}
}

View file

@ -25,6 +25,7 @@
package org.geysermc.geyser.entity.attribute;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.cloudburstmc.protocol.bedrock.data.AttributeData;
import lombok.AllArgsConstructor;
import lombok.Getter;
@ -69,7 +70,7 @@ public enum GeyserAttributeType {
return getAttribute(value, maximum);
}
public AttributeData getAttribute(float value, float maximum) {
public @Nullable AttributeData getAttribute(float value, float maximum) {
if (bedrockIdentifier == null) {
return null;
}

View file

@ -34,7 +34,6 @@ import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.registry.Registries;
import org.geysermc.geyser.registry.type.ParticleMapping;
import org.geysermc.geyser.session.GeyserSession;
import java.util.UUID;

View file

@ -36,6 +36,7 @@ import lombok.AccessLevel;
import lombok.Getter;
import lombok.Setter;
import net.kyori.adventure.text.Component;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.cloudburstmc.math.vector.Vector2f;
import org.cloudburstmc.math.vector.Vector3f;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
@ -580,7 +581,7 @@ public class Entity implements GeyserEntity {
}
@SuppressWarnings("unchecked")
public <I extends Entity> I as(Class<I> entityClass) {
public <I extends Entity> @Nullable I as(Class<I> entityClass) {
return entityClass.isInstance(this) ? (I) this : null;
}
}

View file

@ -38,6 +38,7 @@ import com.github.steveice10.opennbt.tag.builtin.StringTag;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.Setter;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.cloudburstmc.math.vector.Vector3f;
import org.cloudburstmc.math.vector.Vector3i;
import org.cloudburstmc.protocol.bedrock.data.AttributeData;
@ -120,7 +121,7 @@ public class LivingEntity extends Entity {
session.sendUpstreamPacket(attributesPacket);
}
public Vector3i setBedPosition(EntityMetadata<Optional<Vector3i>, ?> entityMetadata) {
public @Nullable Vector3i setBedPosition(EntityMetadata<Optional<Vector3i>, ?> entityMetadata) {
Optional<Vector3i> optionalPos = entityMetadata.getValue();
if (optionalPos.isPresent()) {
Vector3i bedPosition = optionalPos.get();

View file

@ -26,6 +26,7 @@
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.type.BooleanEntityMetadata;
import net.kyori.adventure.text.Component;
import org.cloudburstmc.math.vector.Vector3f;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
@ -33,6 +34,7 @@ import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.text.MessageTranslator;
import java.util.Optional;
import java.util.UUID;
// Note: 1.19.4 requires that the billboard is set to something in order to show, on Java Edition
@ -49,6 +51,18 @@ public class TextDisplayEntity extends Entity {
this.dirtyMetadata.put(EntityDataTypes.NAMETAG_ALWAYS_SHOW, (byte) 1);
}
@Override
public void setDisplayNameVisible(BooleanEntityMetadata entityMetadata) {
// Don't allow the display name to be hidden - messes with our armor stand.
// On JE: Hiding the display name still shows the display entity text.
}
@Override
public void setDisplayName(EntityMetadata<Optional<Component>, ?> entityMetadata) {
// This would usually set EntityDataTypes.NAME, but we are instead using NAME for the text display.
// On JE: custom name does not override text display.
}
public void setText(EntityMetadata<Component, ?> entityMetadata) {
this.dirtyMetadata.put(EntityDataTypes.NAME, MessageTranslator.convertMessage(entityMetadata.getValue()));
}

View file

@ -51,7 +51,6 @@ public class ThrowableEntity extends Entity implements Tickable {
/**
* Updates the position for the Bedrock client.
*
* Java clients assume the next positions of moving items. Bedrock needs to be explicitly told positions
*/
@Override

View file

@ -26,6 +26,7 @@
package org.geysermc.geyser.entity.type.living;
import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.cloudburstmc.math.vector.Vector3f;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
import org.geysermc.geyser.entity.EntityDefinition;
@ -34,7 +35,6 @@ 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 {
@ -48,9 +48,9 @@ public class AbstractFishEntity extends WaterEntity {
setFlag(EntityFlag.HAS_GRAVITY, false);
}
@Nonnull
@NonNull
@Override
protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) {
protected InteractionResult mobInteract(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) {
if (EntityUtils.attemptToBucket(itemInHand)) {
return InteractionResult.SUCCESS;
} else {

View file

@ -27,6 +27,7 @@ package org.geysermc.geyser.entity.type.living;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanEntityMetadata;
import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.cloudburstmc.math.vector.Vector3f;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
import org.geysermc.geyser.entity.EntityDefinition;
@ -36,7 +37,6 @@ 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 {
@ -54,9 +54,9 @@ public class AllayEntity extends MobEntity {
this.canDuplicate = entityMetadata.getPrimitiveValue();
}
@Nonnull
@NonNull
@Override
protected InteractiveTag testMobInteraction(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
protected InteractiveTag testMobInteraction(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) {
if (this.canDuplicate && getFlag(EntityFlag.DANCING) && isDuplicationItem(itemInHand)) {
// Maybe better as another tag?
return InteractiveTag.GIVE_ITEM_TO_ALLAY;
@ -70,9 +70,9 @@ public class AllayEntity extends MobEntity {
}
}
@Nonnull
@NonNull
@Override
protected InteractionResult mobInteract(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
protected InteractionResult mobInteract(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) {
if (this.canDuplicate && getFlag(EntityFlag.DANCING) && isDuplicationItem(itemInHand)) {
//TOCHECK sound
return InteractionResult.SUCCESS;

View file

@ -70,7 +70,7 @@ public class ArmorStandEntity extends LivingEntity {
private boolean primaryEntity = true;
/**
* Whether the entity's position must be updated to included the offset.
*
* <p>
* This should be true when the Java server marks the armor stand as invisible, but we shrink the entity
* to allow the nametag to appear. Basically:
* - Is visible: this is irrelevant (false)
@ -207,7 +207,7 @@ 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(EntityDataType dataLeech, EntityFlag negativeXToggle, EntityFlag negativeYToggle, EntityFlag negativeZToggle, Vector3f rotation) {
private void onRotationUpdate(EntityDataType<Integer> dataLeech, EntityFlag negativeXToggle, EntityFlag negativeYToggle, EntityFlag negativeZToggle, Vector3f rotation) {
// Indicate that rotation should be checked
setFlag(EntityFlag.BRIBED, true);

View file

@ -26,6 +26,7 @@
package org.geysermc.geyser.entity.type.living;
import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.cloudburstmc.math.vector.Vector3f;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.inventory.GeyserItemStack;
@ -33,7 +34,6 @@ 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 {
@ -46,18 +46,18 @@ public class DolphinEntity extends WaterEntity {
return true;
}
@Nonnull
@NonNull
@Override
protected InteractiveTag testMobInteraction(Hand hand, @Nonnull GeyserItemStack itemInHand) {
protected InteractiveTag testMobInteraction(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) {
if (!itemInHand.isEmpty() && session.getTagCache().isFish(itemInHand)) {
return InteractiveTag.FEED;
}
return super.testMobInteraction(hand, itemInHand);
}
@Nonnull
@NonNull
@Override
protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) {
protected InteractionResult mobInteract(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) {
if (!itemInHand.isEmpty() && session.getTagCache().isFish(itemInHand)) {
// Feed
return InteractionResult.SUCCESS;

View file

@ -26,6 +26,7 @@
package org.geysermc.geyser.entity.type.living;
import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.cloudburstmc.math.vector.Vector3f;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
@ -35,7 +36,6 @@ import org.geysermc.geyser.item.Items;
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 {
@ -51,9 +51,9 @@ public class IronGolemEntity extends GolemEntity {
maxHealth = 100f;
}
@Nonnull
@NonNull
@Override
protected InteractionResult mobInteract(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
protected InteractionResult mobInteract(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) {
if (itemInHand.asItem() == Items.IRON_INGOT) {
if (health < maxHealth) {
// Healing the iron golem

View file

@ -28,6 +28,7 @@ package org.geysermc.geyser.entity.type.living;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata;
import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
import lombok.Getter;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.cloudburstmc.math.vector.Vector3f;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
@ -40,7 +41,6 @@ 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 {
@ -133,13 +133,13 @@ public class MobEntity extends LivingEntity {
return InteractionResult.PASS;
}
@Nonnull
protected InteractiveTag testMobInteraction(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
@NonNull
protected InteractiveTag testMobInteraction(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) {
return InteractiveTag.NONE;
}
@Nonnull
protected InteractionResult mobInteract(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
@NonNull
protected InteractionResult mobInteract(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) {
return InteractionResult.PASS;
}

View file

@ -27,6 +27,7 @@ package org.geysermc.geyser.entity.type.living;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata;
import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.cloudburstmc.math.vector.Vector3f;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
import org.geysermc.geyser.entity.EntityDefinition;
@ -36,7 +37,6 @@ 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 {
@ -51,9 +51,9 @@ public class SnowGolemEntity extends GolemEntity {
setFlag(EntityFlag.SHEARED, (xd & 0x10) != 0x10);
}
@Nonnull
@NonNull
@Override
protected InteractiveTag testMobInteraction(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
protected InteractiveTag testMobInteraction(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) {
if (Items.SHEARS == itemInHand.asItem() && isAlive() && !getFlag(EntityFlag.SHEARED)) {
// Shearing the snow golem
return InteractiveTag.SHEAR;
@ -61,9 +61,9 @@ public class SnowGolemEntity extends GolemEntity {
return InteractiveTag.NONE;
}
@Nonnull
@NonNull
@Override
protected InteractionResult mobInteract(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
protected InteractionResult mobInteract(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) {
if (Items.SHEARS == itemInHand.asItem() && isAlive() && !getFlag(EntityFlag.SHEARED)) {
// Shearing the snow golem
return InteractionResult.SUCCESS;

View file

@ -26,6 +26,7 @@
package org.geysermc.geyser.entity.type.living;
import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.cloudburstmc.math.vector.Vector3f;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.inventory.GeyserItemStack;
@ -34,7 +35,6 @@ 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 {
@ -42,18 +42,18 @@ public class TadpoleEntity extends AbstractFishEntity {
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
}
@Nonnull
@NonNull
@Override
protected InteractiveTag testMobInteraction(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
protected InteractiveTag testMobInteraction(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) {
if (isFood(itemInHand)) {
return InteractiveTag.FEED;
}
return super.testMobInteraction(hand, itemInHand);
}
@Nonnull
@NonNull
@Override
protected InteractionResult mobInteract(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
protected InteractionResult mobInteract(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) {
if (isFood(itemInHand)) {
//TODO particles
return InteractionResult.SUCCESS;

View file

@ -26,6 +26,7 @@
package org.geysermc.geyser.entity.type.living.animal;
import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.cloudburstmc.math.vector.Vector3f;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityEventType;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
@ -38,7 +39,6 @@ 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 AnimalEntity extends AgeableEntity {
@ -59,18 +59,18 @@ public class AnimalEntity extends AgeableEntity {
return item == Items.WHEAT;
}
@Nonnull
@NonNull
@Override
protected InteractiveTag testMobInteraction(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
protected InteractiveTag testMobInteraction(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) {
if (canEat(itemInHand)) {
return InteractiveTag.FEED;
}
return super.testMobInteraction(hand, itemInHand);
}
@Nonnull
@NonNull
@Override
protected InteractionResult mobInteract(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
protected InteractionResult mobInteract(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) {
if (canEat(itemInHand)) {
// FEED
if (getFlag(EntityFlag.BABY)) {

View file

@ -28,6 +28,7 @@ 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 org.checkerframework.checker.nullness.qual.NonNull;
import org.cloudburstmc.math.vector.Vector3f;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
@ -38,7 +39,6 @@ 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 AxolotlEntity extends AnimalEntity {
@ -74,9 +74,9 @@ public class AxolotlEntity extends AnimalEntity {
return true;
}
@Nonnull
@NonNull
@Override
protected InteractionResult mobInteract(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
protected InteractionResult mobInteract(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) {
if (EntityUtils.attemptToBucket(itemInHand)) {
return InteractionResult.SUCCESS;
} else {

View file

@ -26,6 +26,7 @@
package org.geysermc.geyser.entity.type.living.animal;
import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.cloudburstmc.math.vector.Vector3f;
import org.cloudburstmc.protocol.bedrock.data.SoundEvent;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
@ -36,7 +37,6 @@ 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 {
@ -44,9 +44,9 @@ public class CowEntity extends AnimalEntity {
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
}
@Nonnull
@NonNull
@Override
protected InteractiveTag testMobInteraction(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
protected InteractiveTag testMobInteraction(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) {
if (getFlag(EntityFlag.BABY) || itemInHand.asItem() != Items.BUCKET) {
return super.testMobInteraction(hand, itemInHand);
}
@ -54,9 +54,9 @@ public class CowEntity extends AnimalEntity {
return InteractiveTag.MILK;
}
@Nonnull
@NonNull
@Override
protected InteractionResult mobInteract(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
protected InteractionResult mobInteract(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) {
if (getFlag(EntityFlag.BABY) || itemInHand.asItem() != Items.BUCKET) {
return super.mobInteract(hand, itemInHand);
}

View file

@ -28,6 +28,7 @@ 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 org.checkerframework.checker.nullness.qual.NonNull;
import org.cloudburstmc.math.vector.Vector3f;
import org.cloudburstmc.protocol.bedrock.data.SoundEvent;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
@ -38,7 +39,6 @@ import org.geysermc.geyser.item.Items;
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 {
@ -70,9 +70,9 @@ public class GoatEntity extends AnimalEntity {
// TODO testMobInteraction?
@Nonnull
@NonNull
@Override
protected InteractionResult mobInteract(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
protected InteractionResult mobInteract(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) {
if (!getFlag(EntityFlag.BABY) && itemInHand.asItem() == Items.BUCKET) {
session.playSoundEvent(isScreamer ? SoundEvent.MILK_SCREAMER : SoundEvent.MILK, position);
return InteractionResult.SUCCESS;

View file

@ -27,6 +27,7 @@ package org.geysermc.geyser.entity.type.living.animal;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ObjectEntityMetadata;
import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.cloudburstmc.math.vector.Vector3f;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
import org.geysermc.geyser.entity.EntityDefinition;
@ -37,7 +38,6 @@ 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 {
@ -52,9 +52,9 @@ public class MooshroomEntity extends AnimalEntity {
dirtyMetadata.put(EntityDataTypes.VARIANT, isBrown ? 1 : 0);
}
@Nonnull
@NonNull
@Override
protected InteractiveTag testMobInteraction(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
protected InteractiveTag testMobInteraction(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) {
if (!isBaby()) {
if (itemInHand.asItem() == Items.BOWL) {
// Stew
@ -67,9 +67,9 @@ public class MooshroomEntity extends AnimalEntity {
return super.testMobInteraction(hand, itemInHand);
}
@Nonnull
@NonNull
@Override
protected InteractionResult mobInteract(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
protected InteractionResult mobInteract(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) {
boolean isBaby = isBaby();
if (!isBaby && itemInHand.asItem() == Items.BOWL) {
// Stew

View file

@ -26,6 +26,7 @@
package org.geysermc.geyser.entity.type.living.animal;
import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.cloudburstmc.math.vector.Vector3f;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
import org.geysermc.geyser.entity.EntityDefinition;
@ -36,7 +37,6 @@ 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 OcelotEntity extends AnimalEntity {
@ -50,9 +50,9 @@ public class OcelotEntity extends AnimalEntity {
return item == Items.COD || item == Items.SALMON;
}
@Nonnull
@NonNull
@Override
protected InteractiveTag testMobInteraction(Hand hand, @Nonnull GeyserItemStack itemInHand) {
protected InteractiveTag testMobInteraction(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) {
if (!getFlag(EntityFlag.TRUSTING) && canEat(itemInHand) && session.getPlayerEntity().getPosition().distanceSquared(position) < 9f) {
// Attempt to feed
return InteractiveTag.FEED;
@ -61,9 +61,9 @@ public class OcelotEntity extends AnimalEntity {
}
}
@Nonnull
@NonNull
@Override
protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) {
protected InteractionResult mobInteract(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) {
if (!getFlag(EntityFlag.TRUSTING) && canEat(itemInHand) && session.getPlayerEntity().getPosition().distanceSquared(position) < 9f) {
// Attempt to feed
return InteractionResult.SUCCESS;

View file

@ -28,6 +28,8 @@ 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 org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.cloudburstmc.math.vector.Vector3f;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityEventType;
@ -41,8 +43,6 @@ import org.geysermc.geyser.session.GeyserSession;
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 {
@ -93,18 +93,18 @@ public class PandaEntity extends AnimalEntity {
return item == Items.BAMBOO;
}
@Nonnull
@NonNull
@Override
protected InteractiveTag testMobInteraction(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
protected InteractiveTag testMobInteraction(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) {
if (mainGene == Gene.WORRIED && session.isThunder()) {
return InteractiveTag.NONE;
}
return super.testMobInteraction(hand, itemInHand);
}
@Nonnull
@NonNull
@Override
protected InteractionResult mobInteract(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
protected InteractionResult mobInteract(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) {
if (mainGene == Gene.WORRIED && session.isThunder()) {
// Huh!
return InteractionResult.PASS;

View file

@ -26,6 +26,7 @@
package org.geysermc.geyser.entity.type.living.animal;
import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.cloudburstmc.math.vector.Vector3f;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
import org.geysermc.geyser.entity.EntityDefinition;
@ -37,7 +38,6 @@ 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 {
@ -51,9 +51,9 @@ public class PigEntity extends AnimalEntity {
return item == Items.CARROT || item == Items.POTATO || item == Items.BEETROOT;
}
@Nonnull
@NonNull
@Override
protected InteractiveTag testMobInteraction(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
protected InteractiveTag testMobInteraction(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) {
if (!canEat(itemInHand) && getFlag(EntityFlag.SADDLED) && passengers.isEmpty() && !session.isSneaking()) {
// Mount
return InteractiveTag.MOUNT;
@ -68,9 +68,9 @@ public class PigEntity extends AnimalEntity {
}
}
@Nonnull
@NonNull
@Override
protected InteractionResult mobInteract(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
protected InteractionResult mobInteract(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) {
if (!canEat(itemInHand) && getFlag(EntityFlag.SADDLED) && passengers.isEmpty() && !session.isSneaking()) {
// Mount
return InteractionResult.SUCCESS;

View file

@ -27,6 +27,7 @@ package org.geysermc.geyser.entity.type.living.animal;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata;
import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.cloudburstmc.math.vector.Vector3f;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
@ -38,7 +39,6 @@ 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 SheepEntity extends AnimalEntity {
@ -55,9 +55,9 @@ public class SheepEntity extends AnimalEntity {
dirtyMetadata.put(EntityDataTypes.COLOR, (byte) color);
}
@Nonnull
@NonNull
@Override
protected InteractiveTag testMobInteraction(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
protected InteractiveTag testMobInteraction(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) {
if (itemInHand.asItem() == Items.SHEARS) {
return InteractiveTag.SHEAR;
} else {
@ -73,9 +73,9 @@ public class SheepEntity extends AnimalEntity {
}
}
@Nonnull
@NonNull
@Override
protected InteractionResult mobInteract(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
protected InteractionResult mobInteract(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) {
if (itemInHand.asItem() == Items.SHEARS) {
return InteractionResult.CONSUME;
} else {

View file

@ -27,6 +27,7 @@ package org.geysermc.geyser.entity.type.living.animal;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanEntityMetadata;
import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.cloudburstmc.math.vector.Vector3f;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
import org.geysermc.geyser.entity.EntityDefinition;
@ -39,7 +40,6 @@ 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 StriderEntity extends AnimalEntity {
@ -98,9 +98,9 @@ public class StriderEntity extends AnimalEntity {
return item == Items.WARPED_FUNGUS;
}
@Nonnull
@NonNull
@Override
protected InteractiveTag testMobInteraction(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
protected InteractiveTag testMobInteraction(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) {
if (!canEat(itemInHand) && getFlag(EntityFlag.SADDLED) && passengers.isEmpty() && !session.isSneaking()) {
// Mount Strider
return InteractiveTag.RIDE_STRIDER;
@ -115,9 +115,9 @@ public class StriderEntity extends AnimalEntity {
}
}
@Nonnull
@NonNull
@Override
protected InteractionResult mobInteract(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
protected InteractionResult mobInteract(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) {
if (!canEat(itemInHand) && getFlag(EntityFlag.SADDLED) && passengers.isEmpty() && !session.isSneaking()) {
// Mount Strider
return InteractionResult.SUCCESS;

View file

@ -27,6 +27,7 @@ package org.geysermc.geyser.entity.type.living.animal.horse;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata;
import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.cloudburstmc.math.vector.Vector3f;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityEventType;
@ -44,7 +45,6 @@ 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.Set;
import java.util.UUID;
@ -128,14 +128,14 @@ public class AbstractHorseEntity extends AnimalEntity {
return DONKEY_AND_HORSE_FOODS.contains(item);
}
@Nonnull
@NonNull
@Override
protected InteractiveTag testMobInteraction(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
protected InteractiveTag testMobInteraction(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) {
return testHorseInteraction(hand, itemInHand);
}
@Nonnull
protected final InteractiveTag testHorseInteraction(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
@NonNull
protected final InteractiveTag testHorseInteraction(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) {
boolean isBaby = isBaby();
if (!isBaby) {
if (getFlag(EntityFlag.TAMED) && session.isSneaking()) {
@ -178,14 +178,14 @@ public class AbstractHorseEntity extends AnimalEntity {
}
}
@Nonnull
@NonNull
@Override
protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) {
protected InteractionResult mobInteract(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) {
return mobHorseInteract(hand, itemInHand);
}
@Nonnull
protected final InteractionResult mobHorseInteract(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
@NonNull
protected final InteractionResult mobHorseInteract(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) {
boolean isBaby = isBaby();
if (!isBaby) {
if (getFlag(EntityFlag.TAMED) && session.isSneaking()) {
@ -236,21 +236,21 @@ public class AbstractHorseEntity extends AnimalEntity {
}
}
protected boolean testSaddle(@Nonnull GeyserItemStack itemInHand) {
protected boolean testSaddle(@NonNull GeyserItemStack itemInHand) {
return isAlive() && !getFlag(EntityFlag.BABY) && getFlag(EntityFlag.TAMED);
}
protected boolean testForChest(@Nonnull GeyserItemStack itemInHand) {
protected boolean testForChest(@NonNull GeyserItemStack itemInHand) {
return false;
}
protected boolean additionalTestForInventoryOpen(@Nonnull GeyserItemStack itemInHand) {
protected boolean additionalTestForInventoryOpen(@NonNull GeyserItemStack itemInHand) {
return itemInHand.asItem().javaIdentifier().endsWith("_horse_armor");
}
/* Just a place to stuff common code for the undead variants without having duplicate code */
protected final InteractiveTag testUndeadHorseInteraction(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
protected final InteractiveTag testUndeadHorseInteraction(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) {
if (!getFlag(EntityFlag.TAMED)) {
return InteractiveTag.NONE;
} else if (isBaby()) {
@ -272,7 +272,7 @@ public class AbstractHorseEntity extends AnimalEntity {
}
}
protected final InteractionResult undeadHorseInteract(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
protected final InteractionResult undeadHorseInteract(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) {
if (!getFlag(EntityFlag.TAMED)) {
return InteractionResult.PASS;
} else if (isBaby()) {

View file

@ -111,6 +111,5 @@ public class CamelEntity extends AbstractHorseEntity {
}
public void setDashing(BooleanEntityMetadata entityMetadata) {
}
}

View file

@ -25,6 +25,7 @@
package org.geysermc.geyser.entity.type.living.animal.horse;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.cloudburstmc.math.vector.Vector3f;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
import org.geysermc.geyser.entity.EntityDefinition;
@ -32,7 +33,6 @@ import org.geysermc.geyser.inventory.GeyserItemStack;
import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.session.GeyserSession;
import javax.annotation.Nonnull;
import java.util.UUID;
public class ChestedHorseEntity extends AbstractHorseEntity {
@ -47,18 +47,18 @@ public class ChestedHorseEntity extends AbstractHorseEntity {
}
@Override
protected boolean testSaddle(@Nonnull GeyserItemStack itemInHand) {
protected boolean testSaddle(@NonNull GeyserItemStack itemInHand) {
// Not checked here
return false;
}
@Override
protected boolean testForChest(@Nonnull GeyserItemStack itemInHand) {
protected boolean testForChest(@NonNull GeyserItemStack itemInHand) {
return itemInHand.asItem() == Items.CHEST && !getFlag(EntityFlag.CHESTED);
}
@Override
protected boolean additionalTestForInventoryOpen(@Nonnull GeyserItemStack itemInHand) {
protected boolean additionalTestForInventoryOpen(@NonNull GeyserItemStack itemInHand) {
// Armor won't work on these
return false;
}

View file

@ -26,6 +26,7 @@
package org.geysermc.geyser.entity.type.living.animal.horse;
import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.cloudburstmc.math.vector.Vector3f;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.inventory.GeyserItemStack;
@ -33,7 +34,6 @@ 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 SkeletonHorseEntity extends AbstractHorseEntity {
@ -41,15 +41,15 @@ public class SkeletonHorseEntity extends AbstractHorseEntity {
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
}
@Nonnull
@NonNull
@Override
protected InteractiveTag testMobInteraction(Hand hand, @Nonnull GeyserItemStack itemInHand) {
protected InteractiveTag testMobInteraction(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) {
return testUndeadHorseInteraction(hand, itemInHand);
}
@Nonnull
@NonNull
@Override
protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) {
protected InteractionResult mobInteract(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) {
return undeadHorseInteract(hand, itemInHand);
}
}

View file

@ -26,6 +26,7 @@
package org.geysermc.geyser.entity.type.living.animal.horse;
import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.cloudburstmc.math.vector.Vector3f;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.inventory.GeyserItemStack;
@ -33,7 +34,6 @@ 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 ZombieHorseEntity extends AbstractHorseEntity {
@ -41,15 +41,15 @@ public class ZombieHorseEntity extends AbstractHorseEntity {
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
}
@Nonnull
@NonNull
@Override
protected InteractiveTag testMobInteraction(Hand hand, @Nonnull GeyserItemStack itemInHand) {
protected InteractiveTag testMobInteraction(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) {
return testUndeadHorseInteraction(hand, itemInHand);
}
@Nonnull
@NonNull
@Override
protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) {
protected InteractionResult mobInteract(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) {
return undeadHorseInteract(hand, itemInHand);
}
}

View file

@ -29,6 +29,7 @@ import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanE
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 org.checkerframework.checker.nullness.qual.NonNull;
import org.cloudburstmc.math.vector.Vector3f;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
@ -40,7 +41,6 @@ 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 CatEntity extends TameableEntity {
@ -112,9 +112,9 @@ public class CatEntity extends TameableEntity {
return item == Items.COD || item == Items.SALMON;
}
@Nonnull
@NonNull
@Override
protected InteractiveTag testMobInteraction(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
protected InteractiveTag testMobInteraction(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) {
boolean tamed = getFlag(EntityFlag.TAMED);
if (tamed && ownerBedrockId == session.getPlayerEntity().getGeyserId()) {
// Toggle sitting
@ -124,9 +124,9 @@ public class CatEntity extends TameableEntity {
}
}
@Nonnull
@NonNull
@Override
protected InteractionResult mobInteract(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
protected InteractionResult mobInteract(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) {
boolean tamed = getFlag(EntityFlag.TAMED);
if (tamed && ownerBedrockId == session.getPlayerEntity().getGeyserId()) {
return InteractionResult.SUCCESS;

View file

@ -26,6 +26,7 @@
package org.geysermc.geyser.entity.type.living.animal.tameable;
import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.cloudburstmc.math.vector.Vector3f;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
import org.geysermc.geyser.entity.EntityDefinition;
@ -36,7 +37,6 @@ 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.Set;
import java.util.UUID;
@ -61,9 +61,9 @@ public class ParrotEntity extends TameableEntity {
return item == Items.COOKIE;
}
@Nonnull
@NonNull
@Override
protected InteractiveTag testMobInteraction(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
protected InteractiveTag testMobInteraction(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) {
boolean tame = getFlag(EntityFlag.TAMED);
if (!tame && isTameFood(itemInHand.asItem())) {
return InteractiveTag.FEED;
@ -76,9 +76,9 @@ public class ParrotEntity extends TameableEntity {
return super.testMobInteraction(hand, itemInHand);
}
@Nonnull
@NonNull
@Override
protected InteractionResult mobInteract(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
protected InteractionResult mobInteract(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) {
boolean tame = getFlag(EntityFlag.TAMED);
if (!tame && isTameFood(itemInHand.asItem())) {
return InteractionResult.SUCCESS;

View file

@ -28,6 +28,7 @@ package org.geysermc.geyser.entity.type.living.animal.tameable;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata;
import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.cloudburstmc.math.vector.Vector3f;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
@ -40,7 +41,6 @@ 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.Set;
import java.util.UUID;
@ -103,9 +103,9 @@ public class WolfEntity extends TameableEntity {
return !getFlag(EntityFlag.ANGRY) && super.canBeLeashed();
}
@Nonnull
@NonNull
@Override
protected InteractiveTag testMobInteraction(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
protected InteractiveTag testMobInteraction(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) {
if (getFlag(EntityFlag.ANGRY)) {
return InteractiveTag.NONE;
}
@ -126,9 +126,9 @@ public class WolfEntity extends TameableEntity {
return super.testMobInteraction(hand, itemInHand);
}
@Nonnull
@NonNull
@Override
protected InteractionResult mobInteract(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
protected InteractionResult mobInteract(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) {
if (ownerBedrockId == session.getPlayerEntity().getGeyserId() || getFlag(EntityFlag.TAMED)
|| itemInHand.asItem() == Items.BONE && !getFlag(EntityFlag.ANGRY)) {
// Sitting toggle or feeding; not angry

View file

@ -26,6 +26,7 @@
package org.geysermc.geyser.entity.type.living.merchant;
import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.cloudburstmc.math.vector.Vector3f;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
import org.geysermc.geyser.entity.EntityDefinition;
@ -37,7 +38,6 @@ 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 AbstractMerchantEntity extends AgeableEntity {
@ -51,9 +51,9 @@ public class AbstractMerchantEntity extends AgeableEntity {
return false;
}
@Nonnull
@NonNull
@Override
protected InteractiveTag testMobInteraction(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
protected InteractiveTag testMobInteraction(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) {
if (itemInHand.asItem() != Items.VILLAGER_SPAWN_EGG
&& (definition != EntityDefinitions.VILLAGER || !getFlag(EntityFlag.SLEEPING) && ((VillagerEntity) this).isCanTradeWith())) {
// An additional check we know cannot work
@ -64,9 +64,9 @@ public class AbstractMerchantEntity extends AgeableEntity {
return super.testMobInteraction(hand, itemInHand);
}
@Nonnull
@NonNull
@Override
protected InteractionResult mobInteract(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
protected InteractionResult mobInteract(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) {
if (itemInHand.asItem() != Items.VILLAGER_SPAWN_EGG
&& (definition != EntityDefinitions.VILLAGER || !getFlag(EntityFlag.SLEEPING))
&& (definition != EntityDefinitions.WANDERING_TRADER || !getFlag(EntityFlag.BABY))) {

View file

@ -28,6 +28,7 @@ package org.geysermc.geyser.entity.type.living.merchant;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.VillagerData;
import lombok.Getter;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.cloudburstmc.math.vector.Vector3f;
import org.cloudburstmc.math.vector.Vector3i;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
@ -78,6 +79,7 @@ public class VillagerEntity extends AbstractMerchantEntity {
VILLAGER_REGIONS[6] = 6;
}
@Nullable
private Vector3i bedPosition;
/**
* Used in the interactive tag manager
@ -103,7 +105,7 @@ public class VillagerEntity extends AbstractMerchantEntity {
}
@Override
public Vector3i setBedPosition(EntityMetadata<Optional<Vector3i>, ?> entityMetadata) {
public @Nullable Vector3i setBedPosition(EntityMetadata<Optional<Vector3i>, ?> entityMetadata) {
return bedPosition = super.setBedPosition(entityMetadata);
}

View file

@ -28,6 +28,7 @@ package org.geysermc.geyser.entity.type.living.monster;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanEntityMetadata;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata;
import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.cloudburstmc.math.vector.Vector3f;
import org.cloudburstmc.protocol.bedrock.data.SoundEvent;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
@ -37,7 +38,6 @@ 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 CreeperEntity extends MonsterEntity {
@ -62,9 +62,9 @@ public class CreeperEntity extends MonsterEntity {
setFlag(EntityFlag.IGNITED, ignitedByFlintAndSteel);
}
@Nonnull
@NonNull
@Override
protected InteractiveTag testMobInteraction(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
protected InteractiveTag testMobInteraction(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) {
if (session.getTagCache().isCreeperIgniter(itemInHand.asItem())) {
return InteractiveTag.IGNITE_CREEPER;
} else {
@ -72,9 +72,9 @@ public class CreeperEntity extends MonsterEntity {
}
}
@Nonnull
@NonNull
@Override
protected InteractionResult mobInteract(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
protected InteractionResult mobInteract(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) {
if (session.getTagCache().isCreeperIgniter(itemInHand.asItem())) {
// Ignite creeper - as of 1.19.3
session.playSoundEvent(SoundEvent.IGNITE, position);

View file

@ -27,6 +27,7 @@ package org.geysermc.geyser.entity.type.living.monster;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanEntityMetadata;
import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.cloudburstmc.math.vector.Vector3f;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
@ -37,7 +38,6 @@ 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 PiglinEntity extends BasePiglinEntity {
@ -71,9 +71,9 @@ public class PiglinEntity extends BasePiglinEntity {
super.updateOffHand(session);
}
@Nonnull
@NonNull
@Override
protected InteractiveTag testMobInteraction(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
protected InteractiveTag testMobInteraction(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) {
InteractiveTag tag = super.testMobInteraction(hand, itemInHand);
if (tag != InteractiveTag.NONE) {
return tag;
@ -82,9 +82,9 @@ public class PiglinEntity extends BasePiglinEntity {
}
}
@Nonnull
@NonNull
@Override
protected InteractionResult mobInteract(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
protected InteractionResult mobInteract(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) {
InteractionResult superResult = super.mobInteract(hand, itemInHand);
if (superResult.consumesAction()) {
return superResult;
@ -93,7 +93,7 @@ public class PiglinEntity extends BasePiglinEntity {
}
}
private boolean canGiveGoldTo(@Nonnull GeyserItemStack itemInHand) {
private boolean canGiveGoldTo(@NonNull GeyserItemStack itemInHand) {
return !getFlag(EntityFlag.BABY) && itemInHand.asItem() == Items.GOLD_INGOT && !getFlag(EntityFlag.ADMIRING);
}
}

View file

@ -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.VillagerData;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanEntityMetadata;
import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.cloudburstmc.math.vector.Vector3f;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
@ -40,7 +41,6 @@ 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 ZombieVillagerEntity extends ZombieEntity {
@ -67,9 +67,9 @@ public class ZombieVillagerEntity extends ZombieEntity {
return getFlag(EntityFlag.IS_TRANSFORMING) || super.isShaking();
}
@Nonnull
@NonNull
@Override
protected InteractiveTag testMobInteraction(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
protected InteractiveTag testMobInteraction(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) {
if (itemInHand.asItem() == Items.GOLDEN_APPLE) {
return InteractiveTag.CURE;
} else {
@ -77,9 +77,9 @@ public class ZombieVillagerEntity extends ZombieEntity {
}
}
@Nonnull
@NonNull
@Override
protected InteractionResult mobInteract(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
protected InteractionResult mobInteract(@NonNull Hand hand, @NonNull GeyserItemStack itemInHand) {
if (itemInHand.asItem() == Items.GOLDEN_APPLE) {
// The client doesn't know if the entity has weakness as that's not usually sent over the network
return InteractionResult.CONSUME;

View file

@ -36,14 +36,23 @@ import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
import lombok.Getter;
import lombok.Setter;
import net.kyori.adventure.text.Component;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.cloudburstmc.math.vector.Vector3f;
import org.cloudburstmc.math.vector.Vector3i;
import org.cloudburstmc.protocol.bedrock.data.*;
import org.cloudburstmc.protocol.bedrock.data.Ability;
import org.cloudburstmc.protocol.bedrock.data.AbilityLayer;
import org.cloudburstmc.protocol.bedrock.data.AttributeData;
import org.cloudburstmc.protocol.bedrock.data.GameType;
import org.cloudburstmc.protocol.bedrock.data.PlayerPermission;
import org.cloudburstmc.protocol.bedrock.data.command.CommandPermission;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityLinkData;
import org.cloudburstmc.protocol.bedrock.packet.*;
import org.cloudburstmc.protocol.bedrock.packet.AddPlayerPacket;
import org.cloudburstmc.protocol.bedrock.packet.MovePlayerPacket;
import org.cloudburstmc.protocol.bedrock.packet.SetEntityDataPacket;
import org.cloudburstmc.protocol.bedrock.packet.SetEntityLinkPacket;
import org.cloudburstmc.protocol.bedrock.packet.UpdateAttributesPacket;
import org.geysermc.geyser.api.entity.type.player.GeyserPlayerEntity;
import org.geysermc.geyser.entity.EntityDefinitions;
import org.geysermc.geyser.entity.type.Entity;
@ -57,7 +66,6 @@ import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.text.MessageTranslator;
import org.geysermc.geyser.util.ChunkUtils;
import javax.annotation.Nullable;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
@ -86,6 +94,7 @@ public class PlayerEntity extends LivingEntity implements GeyserPlayerEntity {
@Nullable
private String texturesProperty;
@Nullable
private Vector3i bedPosition;
/**
@ -142,6 +151,10 @@ public class PlayerEntity extends LivingEntity implements GeyserPlayerEntity {
addPlayerPacket.setGameType(GameType.SURVIVAL); //TODO
addPlayerPacket.setAbilityLayers(BASE_ABILITY_LAYER); // Recommended to be added since 1.19.10, but only needed here for permissions viewing
addPlayerPacket.getMetadata().putFlags(flags);
// Since 1.20.60, the nametag does not show properly if this is not set :/
// The nametag does disappear properly when the player is invisible though.
dirtyMetadata.put(EntityDataTypes.NAMETAG_ALWAYS_SHOW, (byte) 1);
dirtyMetadata.apply(addPlayerPacket.getMetadata());
setFlagsDirty(false);
@ -240,7 +253,7 @@ public class PlayerEntity extends LivingEntity implements GeyserPlayerEntity {
}
@Override
public Vector3i setBedPosition(EntityMetadata<Optional<Vector3i>, ?> entityMetadata) {
public @Nullable Vector3i setBedPosition(EntityMetadata<Optional<Vector3i>, ?> entityMetadata) {
bedPosition = super.setBedPosition(entityMetadata);
if (bedPosition != null) {
// Required to sync position of entity to bed
@ -432,4 +445,9 @@ public class PlayerEntity extends LivingEntity implements GeyserPlayerEntity {
public UUID getTabListUuid() {
return getUuid();
}
@Override
public Vector3f position() {
return this.position.clone();
}
}

View file

@ -33,6 +33,7 @@ import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEnti
import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import lombok.Getter;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.cloudburstmc.math.vector.Vector3f;
import org.cloudburstmc.protocol.bedrock.data.AttributeData;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
@ -44,7 +45,6 @@ import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.util.AttributeUtils;
import org.geysermc.geyser.util.DimensionUtils;
import javax.annotation.Nullable;
import java.util.Collections;
import java.util.List;
import java.util.Map;
@ -112,7 +112,7 @@ public class SessionPlayerEntity extends PlayerEntity {
/**
* Sending any updated flags (sprinting, onFire, etc.) to the client while in spectator is not needed
* Also "fixes" https://github.com/GeyserMC/Geyser/issues/3318
* Also "fixes" <a href="https://github.com/GeyserMC/Geyser/issues/3318">issue 3318</a>
*/
@Override
public void setFlags(ByteEntityMetadata entityMetadata) {
@ -126,7 +126,7 @@ public class SessionPlayerEntity extends PlayerEntity {
/**
* Since 1.19.40, the client must be re-informed of its bounding box on respawn
* See https://github.com/GeyserMC/Geyser/issues/3370
* See <a href="https://github.com/GeyserMC/Geyser/issues/3370">issue 3370</a>
*/
public void updateBoundingBox() {
dirtyMetadata.put(EntityDataTypes.HEIGHT, getBoundingBoxHeight());
@ -254,4 +254,17 @@ public class SessionPlayerEntity extends PlayerEntity {
public UUID getTabListUuid() {
return session.identity();
}
public void resetMetadata() {
// Reset all metadata to their default values
// This is used when a player respawns
this.initializeMetadata();
// Reset air
this.resetAir();
}
public void resetAir() {
this.setAirSupply(getMaxAir());
}
}

View file

@ -25,9 +25,9 @@
package org.geysermc.geyser.erosion;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.geysermc.erosion.packet.geyserbound.*;
import org.geysermc.geyser.session.GeyserSession;
import org.jetbrains.annotations.Nullable;
public abstract class AbstractGeyserboundPacketHandler implements GeyserboundPacketHandler {
protected final GeyserSession session;

View file

@ -26,11 +26,11 @@
package org.geysermc.geyser.erosion;
import io.netty.channel.Channel;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.geysermc.erosion.netty.NettyPacketSender;
import org.geysermc.erosion.packet.ErosionPacketHandler;
import org.geysermc.erosion.packet.geyserbound.GeyserboundHandshakePacket;
import org.geysermc.geyser.session.GeyserSession;
import org.jetbrains.annotations.Nullable;
public final class GeyserboundHandshakePacketHandler extends AbstractGeyserboundPacketHandler {
@ -66,7 +66,7 @@ public final class GeyserboundHandshakePacketHandler extends AbstractGeyserbound
}
@Override
public ErosionPacketHandler setChannel(Channel channel) {
public @Nullable ErosionPacketHandler setChannel(Channel channel) {
return null;
}
}

View file

@ -31,6 +31,7 @@ import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.epoll.EpollDomainSocketChannel;
import io.netty.channel.epoll.EpollEventLoopGroup;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.geysermc.erosion.netty.impl.AbstractUnixSocketListener;
import org.geysermc.erosion.packet.geyserbound.GeyserboundPacketHandler;
@ -49,9 +50,9 @@ public final class UnixSocketClientListener extends AbstractUnixSocketListener {
initializeEventLoopGroup();
(new Bootstrap()
.channel(EpollDomainSocketChannel.class)
.handler(new ChannelInitializer<Channel>() {
.handler(new ChannelInitializer<>() {
@Override
protected void initChannel(Channel ch) {
protected void initChannel(@NonNull Channel ch) {
initPipeline(ch, handler);
}
})

View file

@ -31,7 +31,6 @@ import org.geysermc.event.PostOrder;
import org.geysermc.event.subscribe.impl.OwnedSubscriberImpl;
import org.geysermc.geyser.api.event.EventRegistrar;
import org.geysermc.geyser.api.event.ExtensionEventSubscriber;
import org.geysermc.geyser.api.extension.Extension;
import java.util.function.BiConsumer;
import java.util.function.Consumer;

View file

@ -26,12 +26,11 @@
package org.geysermc.geyser.event.type;
import org.checkerframework.checker.index.qual.NonNegative;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.cloudburstmc.protocol.bedrock.BedrockPong;
import org.geysermc.geyser.api.event.connection.GeyserBedrockPingEvent;
import org.jetbrains.annotations.NotNull;
import javax.annotation.Nonnull;
import java.net.InetSocketAddress;
import java.util.Objects;
@ -45,12 +44,12 @@ public class GeyserBedrockPingEventImpl implements GeyserBedrockPingEvent {
}
@Override
public void primaryMotd(@Nonnull String primary) {
public void primaryMotd(@NonNull String primary) {
pong.motd(Objects.requireNonNull(primary, "Primary MOTD cannot be null"));
}
@Override
public void secondaryMotd(@Nonnull String secondary) {
public void secondaryMotd(@NonNull String secondary) {
pong.subMotd(Objects.requireNonNull(secondary, "Secondary MOTD cannot be null"));
}
@ -87,7 +86,7 @@ public class GeyserBedrockPingEventImpl implements GeyserBedrockPingEvent {
}
@Override
public @NotNull InetSocketAddress address() {
public @NonNull InetSocketAddress address() {
return address;
}
}

View file

@ -51,7 +51,7 @@ public abstract class GeyserDefineCustomItemsEventImpl implements GeyserDefineCu
* @return a multimap of all the already registered custom items
*/
@Override
public Map<String, Collection<CustomItemData>> getExistingCustomItems() {
public @NonNull Map<String, Collection<CustomItemData>> getExistingCustomItems() {
return Collections.unmodifiableMap(this.customItems.asMap());
}
@ -61,7 +61,7 @@ public abstract class GeyserDefineCustomItemsEventImpl implements GeyserDefineCu
* @return the list of the already registered non-vanilla custom items
*/
@Override
public List<NonVanillaCustomItemData> getExistingNonVanillaCustomItems() {
public @NonNull List<NonVanillaCustomItemData> getExistingNonVanillaCustomItems() {
return Collections.unmodifiableList(this.nonVanillaCustomItems);
}

View file

@ -56,7 +56,7 @@ public class GeyserExtensionLoader extends ExtensionLoader {
private final Map<Extension, GeyserExtensionContainer> extensionContainers = new HashMap<>();
private final Path extensionsDirectory = GeyserImpl.getInstance().getBootstrap().getConfigFolder().resolve("extensions");
public GeyserExtensionContainer loadExtension(Path path, GeyserExtensionDescription description) throws InvalidExtensionException {
public GeyserExtensionContainer loadExtension(Path path, GeyserExtensionDescription description) throws Throwable {
if (path == null) {
throw new InvalidExtensionException("Path is null");
}
@ -92,8 +92,14 @@ public class GeyserExtensionLoader extends ExtensionLoader {
this.classLoaders.put(description.id(), loader);
final Extension extension = loader.load();
return this.setup(extension, description, dataFolder, new GeyserExtensionEventBus(GeyserImpl.getInstance().eventBus(), extension));
try {
final Extension extension = loader.load();
return this.setup(extension, description, dataFolder, new GeyserExtensionEventBus(GeyserImpl.getInstance().eventBus(), extension));
} catch (Throwable e) {
// if the extension failed to load, remove its classloader and close it.
this.classLoaders.remove(description.id()).close();
throw e;
}
}
private GeyserExtensionContainer setup(Extension extension, GeyserExtensionDescription description, Path dataFolder, ExtensionEventBus eventBus) {
@ -182,9 +188,10 @@ public class GeyserExtensionLoader extends ExtensionLoader {
return;
}
GeyserExtensionContainer container = this.loadExtension(path, description);
extensions.put(id, path);
loadedExtensions.put(id, this.loadExtension(path, description));
} catch (Exception e) {
loadedExtensions.put(id, container);
} catch (Throwable e) {
GeyserImpl.getInstance().getLogger().error(GeyserLocale.getLocaleStringLog("geyser.extensions.load.failed_with_name", path.getFileName(), path.toAbsolutePath()), e);
}
});

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
* Copyright (c) 2019-2024 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
@ -23,16 +23,9 @@
* @link https://github.com/GeyserMC/Geyser
*/
package org.geysermc.geyser.translator.collision;
package org.geysermc.geyser.impl;
import lombok.EqualsAndHashCode;
import org.geysermc.geyser.api.util.MinecraftVersion;
@EqualsAndHashCode(callSuper = true)
@CollisionRemapper(regex = "^spawner$")
public class SpawnerCollision extends SolidCollision {
public SpawnerCollision(String params) {
super(params);
// Increase pushAwayTolerance to work around https://bugs.mojang.com/browse/MCPE-41996
pushAwayTolerance = 0.0002;
}
public record MinecraftVersionImpl(String versionString, int protocolVersion) implements MinecraftVersion {
}

View file

@ -0,0 +1,96 @@
/*
* Copyright (c) 2019-2024 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.impl.camera;
import org.cloudburstmc.protocol.bedrock.data.camera.CameraAudioListener;
import org.cloudburstmc.protocol.bedrock.data.camera.CameraPreset;
import org.cloudburstmc.protocol.common.DefinitionRegistry;
import org.cloudburstmc.protocol.common.NamedDefinition;
import org.cloudburstmc.protocol.common.SimpleDefinitionRegistry;
import org.cloudburstmc.protocol.common.util.OptionalBoolean;
import org.geysermc.geyser.api.bedrock.camera.CameraPerspective;
import java.util.List;
public class CameraDefinitions {
public static final DefinitionRegistry<NamedDefinition> CAMERA_DEFINITIONS;
public static final List<CameraPreset> CAMERA_PRESETS;
static {
CAMERA_PRESETS = List.of(
new CameraPreset(CameraPerspective.FIRST_PERSON.id(), "", null, null, null, null, OptionalBoolean.empty()),
new CameraPreset(CameraPerspective.FREE.id(), "", null, null, null, null, OptionalBoolean.empty()),
new CameraPreset(CameraPerspective.THIRD_PERSON.id(), "", null, null, null, null, OptionalBoolean.empty()),
new CameraPreset(CameraPerspective.THIRD_PERSON_FRONT.id(), "", null, null, null, null, OptionalBoolean.empty()),
new CameraPreset("geyser:free_audio", "minecraft:free", null, null, null, CameraAudioListener.PLAYER, OptionalBoolean.of(false)),
new CameraPreset("geyser:free_effects", "minecraft:free", null, null, null, CameraAudioListener.CAMERA, OptionalBoolean.of(true)),
new CameraPreset("geyser:free_audio_effects", "minecraft:free", null, null, null, CameraAudioListener.PLAYER, OptionalBoolean.of(true)));
SimpleDefinitionRegistry.Builder<NamedDefinition> builder = SimpleDefinitionRegistry.builder();
for (int i = 0; i < CAMERA_PRESETS.size(); i++) {
builder.add(CameraDefinition.of(CAMERA_PRESETS.get(i).getIdentifier(), i));
}
CAMERA_DEFINITIONS = builder.build();
}
public static NamedDefinition getById(int id) {
return CAMERA_DEFINITIONS.getDefinition(id);
}
public static NamedDefinition getByFunctionality(boolean audio, boolean effects) {
if (!audio && !effects) {
return getById(1); // FREE
}
if (audio) {
if (effects) {
return getById(6); // FREE_AUDIO_EFFECTS
} else {
return getById(4); // FREE_AUDIO
}
} else {
return getById(5); // FREE_EFFECTS
}
}
public record CameraDefinition(String identifier, int runtimeId) implements NamedDefinition {
@Override
public String getIdentifier() {
return identifier;
}
@Override
public int getRuntimeId() {
return runtimeId;
}
public static CameraDefinition of(String identifier, int runtimeId) {
return new CameraDefinition(identifier, runtimeId);
}
}
}

View file

@ -0,0 +1,235 @@
/*
* Copyright (c) 2019-2024 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.impl.camera;
import lombok.Getter;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.cloudburstmc.math.vector.Vector2f;
import org.cloudburstmc.math.vector.Vector3f;
import org.cloudburstmc.protocol.bedrock.data.CameraShakeAction;
import org.cloudburstmc.protocol.bedrock.data.CameraShakeType;
import org.cloudburstmc.protocol.bedrock.data.camera.CameraEase;
import org.cloudburstmc.protocol.bedrock.data.camera.CameraFadeInstruction;
import org.cloudburstmc.protocol.bedrock.data.camera.CameraSetInstruction;
import org.cloudburstmc.protocol.bedrock.packet.CameraInstructionPacket;
import org.cloudburstmc.protocol.bedrock.packet.CameraShakePacket;
import org.cloudburstmc.protocol.bedrock.packet.PlayerFogPacket;
import org.geysermc.geyser.api.bedrock.camera.CameraEaseType;
import org.geysermc.geyser.api.bedrock.camera.CameraData;
import org.geysermc.geyser.api.bedrock.camera.CameraFade;
import org.geysermc.geyser.api.bedrock.camera.CameraPerspective;
import org.geysermc.geyser.api.bedrock.camera.CameraPosition;
import org.geysermc.geyser.api.bedrock.camera.CameraShake;
import org.geysermc.geyser.session.GeyserSession;
import java.util.Collections;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
import java.util.UUID;
public class GeyserCameraData implements CameraData {
private final GeyserSession session;
@Getter
private CameraPerspective cameraPerspective;
/**
* All fog effects that are currently applied to the client.
*/
private final Set<String> appliedFog = new HashSet<>();
private final Set<UUID> cameraLockOwners = new HashSet<>();
public GeyserCameraData(GeyserSession session) {
this.session = session;
}
@Override
public void clearCameraInstructions() {
this.cameraPerspective = null;
CameraInstructionPacket packet = new CameraInstructionPacket();
packet.setClear(true);
session.sendUpstreamPacket(packet);
}
@Override
public void forceCameraPerspective(@NonNull CameraPerspective perspective) {
Objects.requireNonNull(perspective, "perspective cannot be null!");
if (perspective == cameraPerspective) {
return; // nothing to do
}
this.cameraPerspective = perspective;
CameraInstructionPacket packet = new CameraInstructionPacket();
CameraSetInstruction setInstruction = new CameraSetInstruction();
if (perspective == CameraPerspective.FREE) {
throw new IllegalArgumentException("Cannot force a stationary camera (CameraPerspective#FREE) on the player!" +
"Send a CameraPosition with an exact position instead");
}
setInstruction.setPreset(CameraDefinitions.getById(perspective.ordinal()));
packet.setSetInstruction(setInstruction);
session.sendUpstreamPacket(packet);
}
@Override
public @Nullable CameraPerspective forcedCameraPerspective() {
return this.cameraPerspective;
}
@Override
public void sendCameraFade(@NonNull CameraFade fade) {
Objects.requireNonNull(fade, "fade cannot be null!");
CameraFadeInstruction fadeInstruction = new CameraFadeInstruction();
fadeInstruction.setColor(fade.color());
fadeInstruction.setTimeData(
new CameraFadeInstruction.TimeData(
fade.fadeInSeconds(),
fade.fadeHoldSeconds(),
fade.fadeOutSeconds()
)
);
CameraInstructionPacket packet = new CameraInstructionPacket();
packet.setFadeInstruction(fadeInstruction);
session.sendUpstreamPacket(packet);
}
@Override
public void sendCameraPosition(@NonNull CameraPosition movement) {
Objects.requireNonNull(movement, "movement cannot be null!");
this.cameraPerspective = CameraPerspective.FREE; // Movements only work with the free preset
CameraSetInstruction setInstruction = new CameraSetInstruction();
CameraEaseType easeType = movement.easeType();
if (easeType != null) {
setInstruction.setEase(new CameraSetInstruction.EaseData(
CameraEase.fromName(easeType.id()),
movement.easeSeconds()
));
}
Vector3f facingPosition = movement.facingPosition();
if (facingPosition != null) {
setInstruction.setFacing(facingPosition);
}
setInstruction.setPos(movement.position());
setInstruction.setRot(Vector2f.from(movement.rotationX(), movement.rotationY()));
setInstruction.setPreset(CameraDefinitions.getByFunctionality(movement.playerPositionForAudio(), movement.renderPlayerEffects()));
CameraInstructionPacket packet = new CameraInstructionPacket();
packet.setSetInstruction(setInstruction);
// If present, also send the fade
CameraFade fade = movement.cameraFade();
if (fade != null) {
CameraFadeInstruction fadeInstruction = new CameraFadeInstruction();
fadeInstruction.setColor(fade.color());
fadeInstruction.setTimeData(
new CameraFadeInstruction.TimeData(
fade.fadeInSeconds(),
fade.fadeHoldSeconds(),
fade.fadeOutSeconds()
)
);
packet.setFadeInstruction(fadeInstruction);
}
session.sendUpstreamPacket(packet);
}
@Override
public void shakeCamera(float intensity, float duration, @NonNull CameraShake type) {
Objects.requireNonNull(type, "camera shake type must be non null!");
CameraShakePacket packet = new CameraShakePacket();
packet.setIntensity(intensity);
packet.setDuration(duration);
packet.setShakeType(type == CameraShake.POSITIONAL ? CameraShakeType.POSITIONAL : CameraShakeType.ROTATIONAL);
packet.setShakeAction(CameraShakeAction.ADD);
session.sendUpstreamPacket(packet);
}
@Override
public void stopCameraShake() {
CameraShakePacket packet = new CameraShakePacket();
// CameraShakeAction.STOP removes all types regardless of the given type, but regardless it can't be null
packet.setShakeType(CameraShakeType.POSITIONAL);
packet.setShakeAction(CameraShakeAction.STOP);
session.sendUpstreamPacket(packet);
}
@Override
public void sendFog(String... fogNameSpaces) {
Collections.addAll(this.appliedFog, fogNameSpaces);
PlayerFogPacket packet = new PlayerFogPacket();
packet.getFogStack().addAll(this.appliedFog);
session.sendUpstreamPacket(packet);
}
@Override
public void removeFog(String... fogNameSpaces) {
if (fogNameSpaces.length == 0) {
this.appliedFog.clear();
} else {
for (String id : fogNameSpaces) {
this.appliedFog.remove(id);
}
}
PlayerFogPacket packet = new PlayerFogPacket();
packet.getFogStack().addAll(this.appliedFog);
session.sendUpstreamPacket(packet);
}
@Override
public @NonNull Set<String> fogEffects() {
// Use a copy so that sendFog/removeFog can be called while iterating the returned set (avoid CME)
return Set.copyOf(this.appliedFog);
}
@Override
public boolean lockCamera(boolean lock, @NonNull UUID owner) {
Objects.requireNonNull(owner, "owner cannot be null!");
if (lock) {
this.cameraLockOwners.add(owner);
} else {
this.cameraLockOwners.remove(owner);
}
session.lockInputs(isCameraLocked(), session.entities().isMovementLocked());
return isCameraLocked();
}
@Override
public boolean isCameraLocked() {
return !this.cameraLockOwners.isEmpty();
}
}

View file

@ -0,0 +1,104 @@
/*
* Copyright (c) 2019-2024 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.impl.camera;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.common.value.qual.IntRange;
import org.geysermc.geyser.api.bedrock.camera.CameraFade;
import java.awt.Color;
import java.util.Objects;
public record GeyserCameraFade(
Color color,
float fadeInSeconds,
float fadeHoldSeconds,
float fadeOutSeconds
) implements CameraFade {
public static class Builder implements CameraFade.Builder {
private Color color;
private float fadeInSeconds;
private float fadeHoldSeconds;
private float fadeOutSeconds;
@Override
public CameraFade.Builder color(@NonNull Color color) {
Objects.requireNonNull(color, "color cannot be null!");
this.color = color;
return this;
}
@Override
public CameraFade.Builder fadeInSeconds(@IntRange(from = 0, to = 10) float fadeInSeconds) {
if (fadeInSeconds < 0f) {
throw new IllegalArgumentException("Fade in seconds must be at least 0 seconds");
}
if (fadeInSeconds > 10f) {
throw new IllegalArgumentException("Fade in seconds must be at most 10 seconds");
}
this.fadeInSeconds = fadeInSeconds;
return this;
}
@Override
public CameraFade.Builder fadeHoldSeconds(@IntRange(from = 0, to = 10) float fadeHoldSeconds) {
if (fadeHoldSeconds < 0f) {
throw new IllegalArgumentException("Fade hold seconds must be at least 0 seconds");
}
if (fadeHoldSeconds > 10f) {
throw new IllegalArgumentException("Fade hold seconds must be at most 10 seconds");
}
this.fadeHoldSeconds = fadeHoldSeconds;
return this;
}
@Override
public CameraFade.Builder fadeOutSeconds(@IntRange(from = 0, to = 10) float fadeOutSeconds) {
if (fadeOutSeconds < 0f) {
throw new IllegalArgumentException("Fade out seconds must be at least 0 seconds");
}
if (fadeOutSeconds > 10f) {
throw new IllegalArgumentException("Fade out seconds must be at most 10 seconds");
}
this.fadeOutSeconds = fadeOutSeconds;
return this;
}
@Override
public CameraFade build() {
Objects.requireNonNull(color, "color must be non null!");
if (fadeInSeconds + fadeHoldSeconds + fadeOutSeconds < 0.5f) {
throw new IllegalArgumentException("Total fade time (in, hold, out) must be at least 0.5 seconds");
}
return new GeyserCameraFade(color, fadeInSeconds, fadeHoldSeconds, fadeOutSeconds);
}
}
}

View file

@ -0,0 +1,131 @@
/*
* Copyright (c) 2019-2024 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.impl.camera;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.checkerframework.common.value.qual.IntRange;
import org.cloudburstmc.math.vector.Vector3f;
import org.geysermc.geyser.api.bedrock.camera.CameraEaseType;
import org.geysermc.geyser.api.bedrock.camera.CameraFade;
import org.geysermc.geyser.api.bedrock.camera.CameraPosition;
import java.util.Objects;
public record GeyserCameraPosition(CameraFade cameraFade,
boolean renderPlayerEffects,
boolean playerPositionForAudio,
CameraEaseType easeType,
float easeSeconds,
Vector3f position,
@IntRange(from = -90, to = 90) int rotationX,
int rotationY,
Vector3f facingPosition
) implements CameraPosition {
public static class Builder implements CameraPosition.Builder {
private CameraFade cameraFade;
private boolean renderPlayerEffects;
private boolean playerPositionForAudio;
private CameraEaseType easeType;
private float easeSeconds;
private Vector3f position;
private @IntRange(from = -90, to = 90) int rotationX;
private int rotationY;
private Vector3f facingPosition;
@Override
public CameraPosition.Builder cameraFade(@Nullable CameraFade cameraFade) {
this.cameraFade = cameraFade;
return this;
}
@Override
public CameraPosition.Builder renderPlayerEffects(boolean renderPlayerEffects) {
this.renderPlayerEffects = renderPlayerEffects;
return this;
}
@Override
public CameraPosition.Builder playerPositionForAudio(boolean playerPositionForAudio) {
this.playerPositionForAudio = playerPositionForAudio;
return this;
}
@Override
public CameraPosition.Builder easeType(@Nullable CameraEaseType easeType) {
this.easeType = easeType;
return this;
}
@Override
public CameraPosition.Builder easeSeconds(float easeSeconds) {
if (easeSeconds < 0) {
throw new IllegalArgumentException("Camera ease duration cannot be negative!");
}
this.easeSeconds = easeSeconds;
return this;
}
@Override
public CameraPosition.Builder position(@NonNull Vector3f position) {
Objects.requireNonNull(position, "camera position cannot be null!");
this.position = position;
return this;
}
@Override
public CameraPosition.Builder rotationX(int rotationX) {
if (rotationX < -90 || rotationX > 90) {
throw new IllegalArgumentException("x-axis rotation needs to be between -90 and 90 degrees.");
}
this.rotationX = rotationX;
return this;
}
@Override
public CameraPosition.Builder rotationY(int rotationY) {
this.rotationY = rotationY;
return this;
}
@Override
public CameraPosition.Builder facingPosition(@Nullable Vector3f facingPosition) {
this.facingPosition = facingPosition;
return this;
}
@Override
public CameraPosition build() {
if (easeSeconds > 0 && easeType == null) {
throw new IllegalArgumentException("Camera ease type cannot be null if ease duration is greater than 0");
}
Objects.requireNonNull(position, "camera position must be non null!");
return new GeyserCameraPosition(cameraFade, renderPlayerEffects, playerPositionForAudio, easeType, easeSeconds, position, rotationX, rotationY, facingPosition);
}
}
}

View file

@ -29,12 +29,11 @@ import com.github.steveice10.mc.protocol.data.game.inventory.ContainerType;
import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.ServerboundRenameItemPacket;
import lombok.Getter;
import lombok.Setter;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.text.MessageTranslator;
import org.geysermc.geyser.util.ItemUtils;
import javax.annotation.Nullable;
/**
* Used to determine if rename packets should be sent and stores
* the expected level cost for AnvilInventoryUpdater

View file

@ -27,12 +27,11 @@ package org.geysermc.geyser.inventory;
import com.github.steveice10.mc.protocol.data.game.inventory.ContainerType;
import lombok.Getter;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.inventory.InventoryTranslator;
import org.jetbrains.annotations.Range;
import javax.annotation.Nonnull;
/**
* Combination of {@link Inventory} and {@link PlayerInventory}
*/
@ -67,7 +66,7 @@ public class Container extends Inventory {
}
@Override
public void setItem(int slot, @Nonnull GeyserItemStack newItem, GeyserSession session) {
public void setItem(int slot, @NonNull GeyserItemStack newItem, GeyserSession session) {
if (slot < this.size) {
super.setItem(slot, newItem, session);
} else {

View file

@ -0,0 +1,61 @@
/*
* Copyright (c) 2019-2023 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.inventory;
import com.github.steveice10.mc.protocol.data.game.inventory.ContainerType;
import lombok.Getter;
import lombok.Setter;
import org.geysermc.geyser.GeyserImpl;
@Getter
public class CrafterContainer extends Container {
@Setter
private boolean triggered = false;
/**
* Bedrock Edition bitmask of the *disabled* slots.
* Disabled slots are 1, enabled slots are 0 - same as Java Edition
*/
private short disabledSlotsMask = 0;
public CrafterContainer(String title, int id, int size, ContainerType containerType, PlayerInventory playerInventory) {
super(title, id, size, containerType, playerInventory);
}
public void setSlot(int slot, boolean enabled) {
if (slot < 0 || slot > 8) {
GeyserImpl.getInstance().getLogger().warning("Crafter slot out of bounds: " + slot);
return;
}
if (enabled) {
disabledSlotsMask = (short) (disabledSlotsMask & ~(1 << slot));
} else {
disabledSlotsMask = (short) (disabledSlotsMask | (1 << slot));
}
}
}

View file

@ -33,7 +33,7 @@ import org.geysermc.geyser.translator.inventory.Generic3X3InventoryTranslator;
public class Generic3X3Container extends Container {
/**
* Whether we need to set the container type as {@link org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType#DROPPER}.
*
* <p>
* Used at {@link Generic3X3InventoryTranslator#openInventory(GeyserSession, Inventory)}
*/
@Getter

View file

@ -40,7 +40,7 @@ import java.util.List;
public class GeyserEnchantOption {
private static final List<EnchantData> EMPTY = Collections.emptyList();
/**
* This: https://cdn.discordapp.com/attachments/613168850925649981/791030657169227816/unknown.png
* This <a href="https://cdn.discordapp.com/attachments/613168850925649981/791030657169227816/unknown.png">text</a>
* is controlled by the server.
* So, of course, we have to throw in some easter eggs. ;)
*/

View file

@ -28,21 +28,22 @@ package org.geysermc.geyser.inventory;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack;
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
import lombok.AccessLevel;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
import lombok.Data;
import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.item.type.Item;
import org.geysermc.geyser.registry.Registries;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.inventory.item.ItemTranslator;
import javax.annotation.Nonnull;
@Data
public class GeyserItemStack {
public static final GeyserItemStack EMPTY = new GeyserItemStack(0, 0, null);
public static final GeyserItemStack EMPTY = new GeyserItemStack(Items.AIR_ID, 0, null);
private final int javaId;
private int amount;
@ -64,7 +65,7 @@ public class GeyserItemStack {
this.netId = netId;
}
public static @Nonnull GeyserItemStack from(ItemStack itemStack) {
public static @NonNull GeyserItemStack from(@Nullable ItemStack itemStack) {
return itemStack == null ? EMPTY : new GeyserItemStack(itemStack.getId(), itemStack.getAmount(), itemStack.getNbt());
}
@ -76,7 +77,7 @@ public class GeyserItemStack {
return isEmpty() ? 0 : amount;
}
public CompoundTag getNbt() {
public @Nullable CompoundTag getNbt() {
return isEmpty() ? null : nbt;
}
@ -96,7 +97,7 @@ public class GeyserItemStack {
return getItemStack(amount);
}
public ItemStack getItemStack(int newAmount) {
public @Nullable ItemStack getItemStack(int newAmount) {
return isEmpty() ? null : new ItemStack(javaId, newAmount, nbt);
}
@ -122,7 +123,7 @@ public class GeyserItemStack {
}
public boolean isEmpty() {
return amount <= 0 || javaId == 0;
return amount <= 0 || javaId == Items.AIR_ID;
}
public GeyserItemStack copy() {

View file

@ -29,6 +29,7 @@ import com.github.steveice10.mc.protocol.data.game.inventory.ContainerType;
import com.github.steveice10.opennbt.tag.builtin.ByteTag;
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
import com.github.steveice10.opennbt.tag.builtin.Tag;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.cloudburstmc.math.vector.Vector3i;
import lombok.Getter;
import lombok.Setter;
@ -40,7 +41,6 @@ import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.inventory.item.ItemTranslator;
import org.jetbrains.annotations.Range;
import javax.annotation.Nonnull;
import java.util.Arrays;
@ToString
@ -126,7 +126,7 @@ public abstract class Inventory {
public abstract int getOffsetForHotbar(@Range(from = 0, to = 8) int slot);
public void setItem(int slot, @Nonnull GeyserItemStack newItem, GeyserSession session) {
public void setItem(int slot, @NonNull GeyserItemStack newItem, GeyserSession session) {
if (slot > this.size) {
session.getGeyser().getLogger().debug("Tried to set an item out of bounds! " + this);
return;

View file

@ -28,12 +28,11 @@ package org.geysermc.geyser.inventory;
import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
import lombok.Getter;
import lombok.Setter;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.session.GeyserSession;
import org.jetbrains.annotations.Range;
import javax.annotation.Nonnull;
public class PlayerInventory extends Inventory {
/**
* Stores the held item slot, starting at index 0.
@ -44,7 +43,7 @@ public class PlayerInventory extends Inventory {
private int heldItemSlot;
@Getter
@Nonnull
@NonNull
private GeyserItemStack cursor = GeyserItemStack.EMPTY;
public PlayerInventory() {
@ -57,12 +56,12 @@ public class PlayerInventory extends Inventory {
return slot + 36;
}
public void setCursor(@Nonnull GeyserItemStack newCursor, GeyserSession session) {
public void setCursor(@NonNull GeyserItemStack newCursor, GeyserSession session) {
updateItemNetId(cursor, newCursor, session);
cursor = newCursor;
}
public GeyserItemStack getItemInHand(@Nonnull Hand hand) {
public GeyserItemStack getItemInHand(@NonNull Hand hand) {
return hand == Hand.OFF_HAND ? getOffhand() : getItemInHand();
}
@ -74,7 +73,7 @@ public class PlayerInventory extends Inventory {
return items[36 + heldItemSlot];
}
public void setItemInHand(@Nonnull GeyserItemStack item) {
public void setItemInHand(@NonNull GeyserItemStack item) {
if (36 + heldItemSlot > this.size) {
GeyserImpl.getInstance().getLogger().debug("Held item slot was larger than expected!");
return;

View file

@ -27,8 +27,8 @@ package org.geysermc.geyser.inventory;
import com.github.steveice10.mc.protocol.data.game.inventory.ContainerType;
import lombok.Getter;
import lombok.NonNull;
import lombok.Setter;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.geysermc.geyser.session.GeyserSession;
public class StonecutterContainer extends Container {

View file

@ -26,6 +26,7 @@
package org.geysermc.geyser.inventory.item;
import lombok.Getter;
import org.checkerframework.checker.nullness.qual.Nullable;
import java.util.Locale;
@ -78,7 +79,7 @@ public enum Enchantment {
this.javaIdentifier = "minecraft:" + this.name().toLowerCase(Locale.ENGLISH);
}
public static Enchantment getByJavaIdentifier(String javaIdentifier) {
public static @Nullable Enchantment getByJavaIdentifier(String javaIdentifier) {
for (Enchantment enchantment : VALUES) {
if (enchantment.javaIdentifier.equals(javaIdentifier) || enchantment.name().toLowerCase(Locale.ENGLISH).equalsIgnoreCase(javaIdentifier)) {
return enchantment;
@ -87,7 +88,7 @@ public enum Enchantment {
return null;
}
public static Enchantment getByBedrockId(int bedrockId) {
public static @Nullable Enchantment getByBedrockId(int bedrockId) {
if (bedrockId >= 0 && bedrockId < VALUES.length) {
return VALUES[bedrockId];
}
@ -149,7 +150,7 @@ public enum Enchantment {
*/
public static final String[] ALL_JAVA_IDENTIFIERS;
public static JavaEnchantment getByJavaIdentifier(String javaIdentifier) {
public static @Nullable JavaEnchantment getByJavaIdentifier(String javaIdentifier) {
if (!javaIdentifier.startsWith("minecraft:")) {
javaIdentifier = "minecraft:" + javaIdentifier;
}

View file

@ -26,6 +26,7 @@
package org.geysermc.geyser.inventory.item;
import lombok.Getter;
import org.checkerframework.checker.nullness.qual.Nullable;
import java.util.Locale;
@ -84,7 +85,7 @@ public enum Potion {
this.bedrockId = (short) bedrockId;
}
public static Potion getByJavaIdentifier(String javaIdentifier) {
public static @Nullable Potion getByJavaIdentifier(String javaIdentifier) {
for (Potion potion : VALUES) {
if (potion.javaIdentifier.equals(javaIdentifier)) {
return potion;
@ -93,7 +94,7 @@ public enum Potion {
return null;
}
public static Potion getByBedrockId(int bedrockId) {
public static @Nullable Potion getByBedrockId(int bedrockId) {
for (Potion potion : VALUES) {
if (potion.bedrockId == bedrockId) {
return potion;

View file

@ -27,11 +27,11 @@ package org.geysermc.geyser.inventory.item;
import lombok.Getter;
import lombok.experimental.Accessors;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.item.type.Item;
import org.geysermc.geyser.registry.type.ItemMapping;
import javax.annotation.Nonnull;
import java.util.Map;
/**
@ -70,7 +70,7 @@ public class StoredItemMappings {
this.writableBook = load(itemMappings, Items.WRITABLE_BOOK);
}
@Nonnull
@NonNull
private ItemMapping load(Map<Item, ItemMapping> itemMappings, Item item) {
ItemMapping mapping = itemMappings.get(item);
if (mapping == null) {

View file

@ -26,12 +26,13 @@
package org.geysermc.geyser.inventory.item;
import lombok.Getter;
import org.checkerframework.checker.nullness.qual.Nullable;
import java.util.Locale;
/**
* Potion identifiers and their respective Bedrock IDs used with arrows.
* https://minecraft.wiki/w/Arrow#Data_values
* <a href="https://minecraft.wiki/w/Arrow#Data_values">See here</a>
*/
@Getter
public enum TippedArrowPotion {
@ -93,7 +94,7 @@ public enum TippedArrowPotion {
this.javaColor = arrowParticleColor.getColor();
}
public static TippedArrowPotion getByJavaIdentifier(String javaIdentifier) {
public static @Nullable TippedArrowPotion getByJavaIdentifier(String javaIdentifier) {
for (TippedArrowPotion potion : VALUES) {
if (potion.javaIdentifier.equals(javaIdentifier)) {
return potion;
@ -102,7 +103,7 @@ public enum TippedArrowPotion {
return null;
}
public static TippedArrowPotion getByBedrockId(int bedrockId) {
public static @Nullable TippedArrowPotion getByBedrockId(int bedrockId) {
for (TippedArrowPotion potion : VALUES) {
if (potion.bedrockId == bedrockId) {
return potion;
@ -115,7 +116,7 @@ public enum TippedArrowPotion {
* @param color the potion color to look up
* @return the tipped arrow potion that most closely resembles that color.
*/
public static TippedArrowPotion getByJavaColor(int color) {
public static @Nullable TippedArrowPotion getByJavaColor(int color) {
for (TippedArrowPotion potion : VALUES) {
if (potion.javaColor == color) {
return potion;

View file

@ -28,8 +28,9 @@ package org.geysermc.geyser.inventory.recipe;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack;
import com.github.steveice10.mc.protocol.data.game.recipe.Ingredient;
import com.github.steveice10.mc.protocol.data.game.recipe.data.ShapedRecipeData;
import org.checkerframework.checker.nullness.qual.Nullable;
public record GeyserShapedRecipe(int width, int height, Ingredient[] ingredients, ItemStack result) implements GeyserRecipe {
public record GeyserShapedRecipe(int width, int height, Ingredient[] ingredients, @Nullable ItemStack result) implements GeyserRecipe {
public GeyserShapedRecipe(ShapedRecipeData data) {
this(data.getWidth(), data.getHeight(), data.getIngredients(), data.getResult());

View file

@ -28,8 +28,9 @@ package org.geysermc.geyser.inventory.recipe;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack;
import com.github.steveice10.mc.protocol.data.game.recipe.Ingredient;
import com.github.steveice10.mc.protocol.data.game.recipe.data.ShapelessRecipeData;
import org.checkerframework.checker.nullness.qual.Nullable;
public record GeyserShapelessRecipe(Ingredient[] ingredients, ItemStack result) implements GeyserRecipe {
public record GeyserShapelessRecipe(Ingredient[] ingredients, @Nullable ItemStack result) implements GeyserRecipe {
public GeyserShapelessRecipe(ShapelessRecipeData data) {
this(data.getIngredients(), data.getResult());

View file

@ -26,10 +26,11 @@
package org.geysermc.geyser.inventory.recipe;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack;
import org.checkerframework.checker.nullness.qual.Nullable;
/**
* @param buttonId the button that needs to be pressed for Java Edition to accept this item.
* @param output the expected output of this item when cut.
*/
public record GeyserStonecutterData(int buttonId, ItemStack output) {
public record GeyserStonecutterData(int buttonId, @Nullable ItemStack output) {
}

View file

@ -64,7 +64,7 @@ public class AnvilInventoryUpdater extends InventoryUpdater {
super.updateInventory(translator, session, inventory);
AnvilContainer anvilContainer = (AnvilContainer) inventory;
updateInventoryState(session, anvilContainer);
int targetSlot = getTargetSlot(session, anvilContainer);
int targetSlot = getTargetSlot(anvilContainer);
for (int i = 0; i < translator.size; i++) {
final int bedrockSlot = translator.javaSlotToBedrock(i);
if (bedrockSlot == 50)
@ -89,7 +89,7 @@ public class AnvilInventoryUpdater extends InventoryUpdater {
updateInventoryState(session, anvilContainer);
int lastTargetSlot = anvilContainer.getLastTargetSlot();
int targetSlot = getTargetSlot(session, anvilContainer);
int targetSlot = getTargetSlot(anvilContainer);
if (targetSlot != javaSlot) {
// Update the requested slot
InventorySlotPacket slotPacket = new InventorySlotPacket();
@ -136,7 +136,7 @@ public class AnvilInventoryUpdater extends InventoryUpdater {
* @param anvilContainer the anvil inventory
* @return the slot to change the repair cost
*/
private int getTargetSlot(GeyserSession session, AnvilContainer anvilContainer) {
private int getTargetSlot(AnvilContainer anvilContainer) {
GeyserItemStack input = anvilContainer.getInput();
GeyserItemStack material = anvilContainer.getMaterial();
@ -433,6 +433,7 @@ public class AnvilInventoryUpdater extends InventoryUpdater {
return !Objects.equals(originalName, ItemUtils.getCustomName(anvilContainer.getResult().getNbt()));
}
@SuppressWarnings("SameParameterValue")
private int getTagIntValueOr(GeyserItemStack itemStack, String tagName, int defaultValue) {
if (itemStack.getNbt() != null) {
Tag tag = itemStack.getNbt().get(tagName);

View file

@ -0,0 +1,94 @@
/*
* Copyright (c) 2019-2023 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.inventory.updater;
import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerId;
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
import org.cloudburstmc.protocol.bedrock.packet.InventoryContentPacket;
import org.cloudburstmc.protocol.bedrock.packet.InventorySlotPacket;
import org.geysermc.geyser.inventory.Inventory;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.inventory.CrafterInventoryTranslator;
import org.geysermc.geyser.translator.inventory.InventoryTranslator;
import java.util.Arrays;
/**
* Read {@link CrafterInventoryTranslator} for context on the complete custom implementation here
*/
public class CrafterInventoryUpdater extends InventoryUpdater {
public static final CrafterInventoryUpdater INSTANCE = new CrafterInventoryUpdater();
@Override
public void updateInventory(InventoryTranslator translator, GeyserSession session, Inventory inventory) {
ItemData[] bedrockItems;
InventoryContentPacket contentPacket;
// crafter grid - but excluding the result slot
bedrockItems = new ItemData[CrafterInventoryTranslator.GRID_SIZE];
for (int i = 0; i < bedrockItems.length; i++) {
bedrockItems[translator.javaSlotToBedrock(i)] = inventory.getItem(i).getItemData(session);
}
contentPacket = new InventoryContentPacket();
contentPacket.setContainerId(inventory.getBedrockId());
contentPacket.setContents(Arrays.asList(bedrockItems));
session.sendUpstreamPacket(contentPacket);
// inventory and hotbar
bedrockItems = new ItemData[36];
for (int i = 0; i < 36; i++) {
final int offset = i < 9 ? 27 : -9;
bedrockItems[i] = inventory.getItem(CrafterInventoryTranslator.GRID_SIZE + i + offset).getItemData(session);
}
contentPacket = new InventoryContentPacket();
contentPacket.setContainerId(ContainerId.INVENTORY);
contentPacket.setContents(Arrays.asList(bedrockItems));
session.sendUpstreamPacket(contentPacket);
// Crafter result - it doesn't come after the grid, as explained elsewhere.
updateSlot(translator, session, inventory, CrafterInventoryTranslator.JAVA_RESULT_SLOT);
}
@Override
public boolean updateSlot(InventoryTranslator translator, GeyserSession session, Inventory inventory, int javaSlot) {
int containerId;
if (javaSlot < CrafterInventoryTranslator.GRID_SIZE || javaSlot == CrafterInventoryTranslator.JAVA_RESULT_SLOT) {
// Parts of the Crafter UI
// It doesn't seem like BDS sends the result slot, but sending it as slot 50 does actually work (it doesn't seem to show otherwise)
containerId = inventory.getBedrockId();
} else {
containerId = ContainerId.INVENTORY;
}
InventorySlotPacket packet = new InventorySlotPacket();
packet.setContainerId(containerId);
packet.setSlot(translator.javaSlotToBedrock(javaSlot));
packet.setItem(inventory.getItem(javaSlot).getItemData(session));
session.sendUpstreamPacket(packet);
return true;
}
}

View file

@ -28,10 +28,14 @@ package org.geysermc.geyser.item;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.geysermc.geyser.api.item.custom.CustomItemData;
import org.geysermc.geyser.api.item.custom.CustomItemOptions;
import org.geysermc.geyser.api.item.custom.CustomRenderOffsets;
import org.jetbrains.annotations.NotNull;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
@EqualsAndHashCode
@ToString
@ -44,6 +48,7 @@ public class GeyserCustomItemData implements CustomItemData {
private final boolean displayHandheld;
private final int textureSize;
private final CustomRenderOffsets renderOffsets;
private final Set<String> tags;
public GeyserCustomItemData(String name,
CustomItemOptions customItemOptions,
@ -52,7 +57,8 @@ public class GeyserCustomItemData implements CustomItemData {
boolean allowOffhand,
boolean displayHandheld,
int textureSize,
CustomRenderOffsets renderOffsets) {
CustomRenderOffsets renderOffsets,
Set<String> tags) {
this.name = name;
this.customItemOptions = customItemOptions;
this.displayName = displayName;
@ -61,10 +67,11 @@ public class GeyserCustomItemData implements CustomItemData {
this.displayHandheld = displayHandheld;
this.textureSize = textureSize;
this.renderOffsets = renderOffsets;
this.tags = tags;
}
@Override
public @NotNull String name() {
public @NonNull String name() {
return name;
}
@ -74,12 +81,12 @@ public class GeyserCustomItemData implements CustomItemData {
}
@Override
public @NotNull String displayName() {
public @NonNull String displayName() {
return displayName;
}
@Override
public @NotNull String icon() {
public @NonNull String icon() {
return icon;
}
@ -103,7 +110,12 @@ public class GeyserCustomItemData implements CustomItemData {
return renderOffsets;
}
public static class CustomItemDataBuilder implements Builder {
@Override
public @NonNull Set<String> tags() {
return tags;
}
public static class Builder implements CustomItemData.Builder {
protected String name = null;
protected CustomItemOptions customItemOptions = null;
@ -113,6 +125,7 @@ public class GeyserCustomItemData implements CustomItemData {
protected boolean displayHandheld = false;
protected int textureSize = 16;
protected CustomRenderOffsets renderOffsets = null;
protected Set<String> tags = new HashSet<>();
@Override
public Builder name(@NonNull String name) {
@ -162,6 +175,12 @@ public class GeyserCustomItemData implements CustomItemData {
return this;
}
@Override
public Builder tags(@Nullable Set<String> tags) {
this.tags = Objects.requireNonNullElseGet(tags, Set::of);
return this;
}
@Override
public CustomItemData build() {
if (this.name == null || this.customItemOptions == null) {
@ -174,7 +193,7 @@ public class GeyserCustomItemData implements CustomItemData {
if (this.icon == null) {
this.icon = this.name;
}
return new GeyserCustomItemData(this.name, this.customItemOptions, this.displayName, this.icon, this.allowOffhand, this.displayHandheld, this.textureSize, this.renderOffsets);
return new GeyserCustomItemData(this.name, this.customItemOptions, this.displayName, this.icon, this.allowOffhand, this.displayHandheld, this.textureSize, this.renderOffsets, this.tags);
}
}
}

View file

@ -30,16 +30,14 @@ import org.geysermc.geyser.api.util.TriState;
import java.util.OptionalInt;
@SuppressWarnings("OptionalUsedAsFieldOrParameterType")
public record GeyserCustomItemOptions(TriState unbreakable,
OptionalInt customModelData,
OptionalInt damagePredicate,
boolean defaultItem) implements CustomItemOptions {
public GeyserCustomItemOptions(TriState unbreakable, OptionalInt customModelData, OptionalInt damagePredicate) {
this(unbreakable, customModelData, damagePredicate, false);
}
public static class CustomItemOptionsBuilder implements CustomItemOptions.Builder {
@SuppressWarnings("OptionalUsedAsFieldOrParameterType")
public static class Builder implements CustomItemOptions.Builder {
private TriState unbreakable = TriState.NOT_SET;
private OptionalInt customModelData = OptionalInt.empty();
private OptionalInt damagePredicate = OptionalInt.empty();

View file

@ -27,7 +27,6 @@ package org.geysermc.geyser.item;
import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition;
import org.cloudburstmc.protocol.bedrock.data.inventory.ComponentItemData;
import org.cloudburstmc.protocol.bedrock.packet.StartGamePacket;
public record GeyserCustomMappingData(ComponentItemData componentItemData, ItemDefinition itemDefinition, String stringId, int integerId) {
}

View file

@ -32,11 +32,11 @@ import org.checkerframework.checker.nullness.qual.Nullable;
import org.geysermc.geyser.api.item.custom.CustomItemOptions;
import org.geysermc.geyser.api.item.custom.CustomRenderOffsets;
import org.geysermc.geyser.api.item.custom.NonVanillaCustomItemData;
import org.jetbrains.annotations.NotNull;
import java.util.OptionalInt;
import java.util.Set;
@SuppressWarnings("OptionalUsedAsFieldOrParameterType")
@EqualsAndHashCode(callSuper = true)
@ToString
public final class GeyserNonVanillaCustomItemData extends GeyserCustomItemData implements NonVanillaCustomItemData {
@ -59,9 +59,9 @@ public final class GeyserNonVanillaCustomItemData extends GeyserCustomItemData i
private final boolean canAlwaysEat;
private final boolean isChargeable;
public GeyserNonVanillaCustomItemData(NonVanillaCustomItemDataBuilder builder) {
public GeyserNonVanillaCustomItemData(Builder builder) {
super(builder.name, builder.customItemOptions, builder.displayName, builder.icon, builder.allowOffhand,
builder.displayHandheld, builder.textureSize, builder.renderOffsets);
builder.displayHandheld, builder.textureSize, builder.renderOffsets, builder.tags);
this.identifier = builder.identifier;
this.javaId = builder.javaId;
@ -84,7 +84,7 @@ public final class GeyserNonVanillaCustomItemData extends GeyserCustomItemData i
}
@Override
public @NotNull String identifier() {
public @NonNull String identifier() {
return identifier;
}
@ -134,7 +134,7 @@ public final class GeyserNonVanillaCustomItemData extends GeyserCustomItemData i
}
@Override
public @NotNull OptionalInt creativeCategory() {
public @NonNull OptionalInt creativeCategory() {
return creativeCategory;
}
@ -168,7 +168,7 @@ public final class GeyserNonVanillaCustomItemData extends GeyserCustomItemData i
return isChargeable;
}
public static class NonVanillaCustomItemDataBuilder extends GeyserCustomItemData.CustomItemDataBuilder implements NonVanillaCustomItemData.Builder {
public static class Builder extends GeyserCustomItemData.Builder implements NonVanillaCustomItemData.Builder {
private String identifier = null;
private int javaId = -1;
@ -197,44 +197,49 @@ public final class GeyserNonVanillaCustomItemData extends GeyserCustomItemData i
private boolean chargeable = false;
@Override
public NonVanillaCustomItemData.Builder name(@NonNull String name) {
return (NonVanillaCustomItemData.Builder) super.name(name);
public Builder name(@NonNull String name) {
return (Builder) super.name(name);
}
@Override
public NonVanillaCustomItemData.Builder customItemOptions(@NonNull CustomItemOptions customItemOptions) {
public Builder customItemOptions(@NonNull CustomItemOptions customItemOptions) {
//Do nothing, as that value won't be read
return this;
}
@Override
public NonVanillaCustomItemData.Builder allowOffhand(boolean allowOffhand) {
return (NonVanillaCustomItemData.Builder) super.allowOffhand(allowOffhand);
public Builder allowOffhand(boolean allowOffhand) {
return (Builder) super.allowOffhand(allowOffhand);
}
@Override
public NonVanillaCustomItemData.Builder displayHandheld(boolean displayHandheld) {
return (NonVanillaCustomItemData.Builder) super.displayHandheld(displayHandheld);
public Builder displayHandheld(boolean displayHandheld) {
return (Builder) super.displayHandheld(displayHandheld);
}
@Override
public NonVanillaCustomItemData.Builder displayName(@NonNull String displayName) {
return (NonVanillaCustomItemData.Builder) super.displayName(displayName);
public Builder displayName(@NonNull String displayName) {
return (Builder) super.displayName(displayName);
}
@Override
public NonVanillaCustomItemData.Builder icon(@NonNull String icon) {
return (NonVanillaCustomItemData.Builder) super.icon(icon);
public Builder icon(@NonNull String icon) {
return (Builder) super.icon(icon);
}
@Override
public NonVanillaCustomItemData.Builder textureSize(int textureSize) {
return (NonVanillaCustomItemData.Builder) super.textureSize(textureSize);
public Builder textureSize(int textureSize) {
return (Builder) super.textureSize(textureSize);
}
@Override
public NonVanillaCustomItemData.Builder renderOffsets(CustomRenderOffsets renderOffsets) {
return (NonVanillaCustomItemData.Builder) super.renderOffsets(renderOffsets);
public Builder renderOffsets(CustomRenderOffsets renderOffsets) {
return (Builder) super.renderOffsets(renderOffsets);
}
@Override
public Builder tags(@Nullable Set<String> tags) {
return (Builder) super.tags(tags);
}
@Override

View file

@ -51,6 +51,19 @@ public final class Items {
public static final Item POLISHED_DEEPSLATE = register(new BlockItem("polished_deepslate", builder()));
public static final Item CALCITE = register(new BlockItem("calcite", builder()));
public static final Item TUFF = register(new BlockItem("tuff", builder()));
public static final Item TUFF_SLAB = register(new BlockItem("tuff_slab", builder()));
public static final Item TUFF_STAIRS = register(new BlockItem("tuff_stairs", builder()));
public static final Item TUFF_WALL = register(new BlockItem("tuff_wall", builder()));
public static final Item CHISELED_TUFF = register(new BlockItem("chiseled_tuff", builder()));
public static final Item POLISHED_TUFF = register(new BlockItem("polished_tuff", builder()));
public static final Item POLISHED_TUFF_SLAB = register(new BlockItem("polished_tuff_slab", builder()));
public static final Item POLISHED_TUFF_STAIRS = register(new BlockItem("polished_tuff_stairs", builder()));
public static final Item POLISHED_TUFF_WALL = register(new BlockItem("polished_tuff_wall", builder()));
public static final Item TUFF_BRICKS = register(new BlockItem("tuff_bricks", builder()));
public static final Item TUFF_BRICK_SLAB = register(new BlockItem("tuff_brick_slab", builder()));
public static final Item TUFF_BRICK_STAIRS = register(new BlockItem("tuff_brick_stairs", builder()));
public static final Item TUFF_BRICK_WALL = register(new BlockItem("tuff_brick_wall", builder()));
public static final Item CHISELED_TUFF_BRICKS = register(new BlockItem("chiseled_tuff_bricks", builder()));
public static final Item DRIPSTONE_BLOCK = register(new BlockItem("dripstone_block", builder()));
public static final Item GRASS_BLOCK = register(new BlockItem("grass_block", builder()));
public static final Item DIRT = register(new BlockItem("dirt", builder()));
@ -120,6 +133,10 @@ public final class Items {
public static final Item EXPOSED_COPPER = register(new BlockItem("exposed_copper", builder()));
public static final Item WEATHERED_COPPER = register(new BlockItem("weathered_copper", builder()));
public static final Item OXIDIZED_COPPER = register(new BlockItem("oxidized_copper", builder()));
public static final Item CHISELED_COPPER = register(new BlockItem("chiseled_copper", builder()));
public static final Item EXPOSED_CHISELED_COPPER = register(new BlockItem("exposed_chiseled_copper", builder()));
public static final Item WEATHERED_CHISELED_COPPER = register(new BlockItem("weathered_chiseled_copper", builder()));
public static final Item OXIDIZED_CHISELED_COPPER = register(new BlockItem("oxidized_chiseled_copper", builder()));
public static final Item CUT_COPPER = register(new BlockItem("cut_copper", builder()));
public static final Item EXPOSED_CUT_COPPER = register(new BlockItem("exposed_cut_copper", builder()));
public static final Item WEATHERED_CUT_COPPER = register(new BlockItem("weathered_cut_copper", builder()));
@ -136,6 +153,10 @@ public final class Items {
public static final Item WAXED_EXPOSED_COPPER = register(new BlockItem("waxed_exposed_copper", builder()));
public static final Item WAXED_WEATHERED_COPPER = register(new BlockItem("waxed_weathered_copper", builder()));
public static final Item WAXED_OXIDIZED_COPPER = register(new BlockItem("waxed_oxidized_copper", builder()));
public static final Item WAXED_CHISELED_COPPER = register(new BlockItem("waxed_chiseled_copper", builder()));
public static final Item WAXED_EXPOSED_CHISELED_COPPER = register(new BlockItem("waxed_exposed_chiseled_copper", builder()));
public static final Item WAXED_WEATHERED_CHISELED_COPPER = register(new BlockItem("waxed_weathered_chiseled_copper", builder()));
public static final Item WAXED_OXIDIZED_CHISELED_COPPER = register(new BlockItem("waxed_oxidized_chiseled_copper", builder()));
public static final Item WAXED_CUT_COPPER = register(new BlockItem("waxed_cut_copper", builder()));
public static final Item WAXED_EXPOSED_CUT_COPPER = register(new BlockItem("waxed_exposed_cut_copper", builder()));
public static final Item WAXED_WEATHERED_CUT_COPPER = register(new BlockItem("waxed_weathered_cut_copper", builder()));
@ -211,7 +232,7 @@ public final class Items {
public static final Item CHISELED_SANDSTONE = register(new BlockItem("chiseled_sandstone", builder()));
public static final Item CUT_SANDSTONE = register(new BlockItem("cut_sandstone", builder()));
public static final Item COBWEB = register(new BlockItem("cobweb", builder()));
public static final Item GRASS = register(new BlockItem("grass", builder()));
public static final Item SHORT_GRASS = register(new BlockItem("short_grass", builder()));
public static final Item FERN = register(new BlockItem("fern", builder()));
public static final Item AZALEA = register(new BlockItem("azalea", builder()));
public static final Item FLOWERING_AZALEA = register(new BlockItem("flowering_azalea", builder()));
@ -304,7 +325,7 @@ public final class Items {
public static final Item BRICKS = register(new BlockItem("bricks", builder()));
public static final Item BOOKSHELF = register(new BlockItem("bookshelf", builder()));
public static final Item CHISELED_BOOKSHELF = register(new BlockItem("chiseled_bookshelf", builder()));
public static final Item DECORATED_POT = register(new DecoratedPotItem("decorated_pot", builder().stackSize(1)));
public static final Item DECORATED_POT = register(new DecoratedPotItem("decorated_pot", builder()));
public static final Item MOSSY_COBBLESTONE = register(new BlockItem("mossy_cobblestone", builder()));
public static final Item OBSIDIAN = register(new BlockItem("obsidian", builder()));
public static final Item TORCH = register(new BlockItem("torch", builder()));
@ -738,6 +759,14 @@ public final class Items {
public static final Item BAMBOO_DOOR = register(new BlockItem("bamboo_door", builder()));
public static final Item CRIMSON_DOOR = register(new BlockItem("crimson_door", builder()));
public static final Item WARPED_DOOR = register(new BlockItem("warped_door", builder()));
public static final Item COPPER_DOOR = register(new BlockItem("copper_door", builder()));
public static final Item EXPOSED_COPPER_DOOR = register(new BlockItem("exposed_copper_door", builder()));
public static final Item WEATHERED_COPPER_DOOR = register(new BlockItem("weathered_copper_door", builder()));
public static final Item OXIDIZED_COPPER_DOOR = register(new BlockItem("oxidized_copper_door", builder()));
public static final Item WAXED_COPPER_DOOR = register(new BlockItem("waxed_copper_door", builder()));
public static final Item WAXED_EXPOSED_COPPER_DOOR = register(new BlockItem("waxed_exposed_copper_door", builder()));
public static final Item WAXED_WEATHERED_COPPER_DOOR = register(new BlockItem("waxed_weathered_copper_door", builder()));
public static final Item WAXED_OXIDIZED_COPPER_DOOR = register(new BlockItem("waxed_oxidized_copper_door", builder()));
public static final Item IRON_TRAPDOOR = register(new BlockItem("iron_trapdoor", builder()));
public static final Item OAK_TRAPDOOR = register(new BlockItem("oak_trapdoor", builder()));
public static final Item SPRUCE_TRAPDOOR = register(new BlockItem("spruce_trapdoor", builder()));
@ -750,6 +779,14 @@ public final class Items {
public static final Item BAMBOO_TRAPDOOR = register(new BlockItem("bamboo_trapdoor", builder()));
public static final Item CRIMSON_TRAPDOOR = register(new BlockItem("crimson_trapdoor", builder()));
public static final Item WARPED_TRAPDOOR = register(new BlockItem("warped_trapdoor", builder()));
public static final Item COPPER_TRAPDOOR = register(new BlockItem("copper_trapdoor", builder()));
public static final Item EXPOSED_COPPER_TRAPDOOR = register(new BlockItem("exposed_copper_trapdoor", builder()));
public static final Item WEATHERED_COPPER_TRAPDOOR = register(new BlockItem("weathered_copper_trapdoor", builder()));
public static final Item OXIDIZED_COPPER_TRAPDOOR = register(new BlockItem("oxidized_copper_trapdoor", builder()));
public static final Item WAXED_COPPER_TRAPDOOR = register(new BlockItem("waxed_copper_trapdoor", builder()));
public static final Item WAXED_EXPOSED_COPPER_TRAPDOOR = register(new BlockItem("waxed_exposed_copper_trapdoor", builder()));
public static final Item WAXED_WEATHERED_COPPER_TRAPDOOR = register(new BlockItem("waxed_weathered_copper_trapdoor", builder()));
public static final Item WAXED_OXIDIZED_COPPER_TRAPDOOR = register(new BlockItem("waxed_oxidized_copper_trapdoor", builder()));
public static final Item OAK_FENCE_GATE = register(new BlockItem("oak_fence_gate", builder()));
public static final Item SPRUCE_FENCE_GATE = register(new BlockItem("spruce_fence_gate", builder()));
public static final Item BIRCH_FENCE_GATE = register(new BlockItem("birch_fence_gate", builder()));
@ -979,6 +1016,7 @@ public final class Items {
public static final Item RED_BED = register(new BlockItem("red_bed", builder().stackSize(1)));
public static final Item BLACK_BED = register(new BlockItem("black_bed", builder().stackSize(1)));
public static final Item COOKIE = register(new Item("cookie", builder()));
public static final Item CRAFTER = register(new BlockItem("crafter", builder()));
public static final Item FILLED_MAP = register(new FilledMapItem("filled_map", builder()));
public static final Item SHEARS = register(new Item("shears", builder().stackSize(1).maxDamage(238)));
public static final Item MELON_SLICE = register(new Item("melon_slice", builder()));
@ -1010,6 +1048,7 @@ public final class Items {
public static final Item BAT_SPAWN_EGG = register(new SpawnEggItem("bat_spawn_egg", builder()));
public static final Item BEE_SPAWN_EGG = register(new SpawnEggItem("bee_spawn_egg", builder()));
public static final Item BLAZE_SPAWN_EGG = register(new SpawnEggItem("blaze_spawn_egg", builder()));
public static final Item BREEZE_SPAWN_EGG = register(new SpawnEggItem("breeze_spawn_egg", builder()));
public static final Item CAT_SPAWN_EGG = register(new SpawnEggItem("cat_spawn_egg", builder()));
public static final Item CAMEL_SPAWN_EGG = register(new SpawnEggItem("camel_spawn_egg", builder()));
public static final Item CAVE_SPIDER_SPAWN_EGG = register(new SpawnEggItem("cave_spider_spawn_egg", builder()));
@ -1293,6 +1332,26 @@ public final class Items {
public static final Item SHELTER_POTTERY_SHERD = register(new Item("shelter_pottery_sherd", builder()));
public static final Item SKULL_POTTERY_SHERD = register(new Item("skull_pottery_sherd", builder()));
public static final Item SNORT_POTTERY_SHERD = register(new Item("snort_pottery_sherd", builder()));
public static final Item COPPER_GRATE = register(new BlockItem("copper_grate", builder()));
public static final Item EXPOSED_COPPER_GRATE = register(new BlockItem("exposed_copper_grate", builder()));
public static final Item WEATHERED_COPPER_GRATE = register(new BlockItem("weathered_copper_grate", builder()));
public static final Item OXIDIZED_COPPER_GRATE = register(new BlockItem("oxidized_copper_grate", builder()));
public static final Item WAXED_COPPER_GRATE = register(new BlockItem("waxed_copper_grate", builder()));
public static final Item WAXED_EXPOSED_COPPER_GRATE = register(new BlockItem("waxed_exposed_copper_grate", builder()));
public static final Item WAXED_WEATHERED_COPPER_GRATE = register(new BlockItem("waxed_weathered_copper_grate", builder()));
public static final Item WAXED_OXIDIZED_COPPER_GRATE = register(new BlockItem("waxed_oxidized_copper_grate", builder()));
public static final Item COPPER_BULB = register(new BlockItem("copper_bulb", builder()));
public static final Item EXPOSED_COPPER_BULB = register(new BlockItem("exposed_copper_bulb", builder()));
public static final Item WEATHERED_COPPER_BULB = register(new BlockItem("weathered_copper_bulb", builder()));
public static final Item OXIDIZED_COPPER_BULB = register(new BlockItem("oxidized_copper_bulb", builder()));
public static final Item WAXED_COPPER_BULB = register(new BlockItem("waxed_copper_bulb", builder()));
public static final Item WAXED_EXPOSED_COPPER_BULB = register(new BlockItem("waxed_exposed_copper_bulb", builder()));
public static final Item WAXED_WEATHERED_COPPER_BULB = register(new BlockItem("waxed_weathered_copper_bulb", builder()));
public static final Item WAXED_OXIDIZED_COPPER_BULB = register(new BlockItem("waxed_oxidized_copper_bulb", builder()));
public static final Item TRIAL_SPAWNER = register(new BlockItem("trial_spawner", builder()));
public static final Item TRIAL_KEY = register(new Item("trial_key", builder()));
public static final int AIR_ID = AIR.javaId();
private static <T extends Item> T register(T item) {
return register(item, Registries.JAVA_ITEMS.get().size());

View file

@ -1,174 +0,0 @@
/*
* 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.item.components;
import org.cloudburstmc.nbt.NbtMap;
import org.cloudburstmc.nbt.NbtType;
import java.util.ArrayList;
import java.util.List;
public class ToolBreakSpeedsUtils {
public static int toolTierToSpeed(String toolTier) {
ToolTier tier = ToolTier.getByName(toolTier);
if (tier != null) {
return tier.getSpeed();
}
return 0;
}
private static NbtMap createTagBreakSpeed(int speed, String... tags) {
StringBuilder builder = new StringBuilder("query.any_tag('");
builder.append(tags[0]);
for (int i = 1; i < tags.length; i++) {
builder.append("', '").append(tags[i]);
}
builder.append("')");
return NbtMap.builder()
.putCompound("block", NbtMap.builder()
.putString("tags", builder.toString())
.build())
.putCompound("on_dig", NbtMap.builder()
.putCompound("condition", NbtMap.builder()
.putString("expression", "")
.putInt("version", -1)
.build())
.putString("event", "tool_durability")
.putString("target", "self")
.build())
.putInt("speed", speed)
.build();
}
private static NbtMap createBreakSpeed(int speed, String block) {
return NbtMap.builder()
.putCompound("block", NbtMap.builder()
.putString("name", block).build())
.putCompound("on_dig", NbtMap.builder()
.putCompound("condition", NbtMap.builder()
.putString("expression", "")
.putInt("version", -1)
.build())
.putString("event", "tool_durability")
.putString("target", "self")
.build())
.putInt("speed", speed)
.build();
}
private static NbtMap createDigger(List<NbtMap> speeds) {
return NbtMap.builder()
.putList("destroy_speeds", NbtType.COMPOUND, speeds)
.putCompound("on_dig", NbtMap.builder()
.putCompound("condition", NbtMap.builder()
.putString("expression", "")
.putInt("version", -1)
.build())
.putString("event", "tool_durability")
.putString("target", "self")
.build())
.putBoolean("use_efficiency", true)
.build();
}
public static NbtMap getAxeDigger(int speed) {
List<NbtMap> speeds = new ArrayList<>();
speeds.add(createTagBreakSpeed(speed, "wood", "pumpkin", "plant"));
return createDigger(speeds);
}
public static NbtMap getPickaxeDigger(int speed, String toolTier) {
List<NbtMap> speeds = new ArrayList<>();
if (toolTier.equals(ToolTier.DIAMOND.toString()) || toolTier.equals(ToolTier.NETHERITE.toString())) {
speeds.add(createTagBreakSpeed(speed, "iron_pick_diggable", "diamond_pick_diggable"));
} else {
speeds.add(createTagBreakSpeed(speed, "iron_pick_diggable"));
}
speeds.add(createTagBreakSpeed(speed, "stone", "metal", "rail", "mob_spawner"));
return createDigger(speeds);
}
public static NbtMap getShovelDigger(int speed) {
List<NbtMap> speeds = new ArrayList<>();
speeds.add(createTagBreakSpeed(speed, "dirt", "sand", "gravel", "grass", "snow"));
return createDigger(speeds);
}
public static NbtMap getSwordDigger(int speed) {
List<NbtMap> speeds = new ArrayList<>();
speeds.add(createBreakSpeed(speed, "minecraft:web"));
speeds.add(createBreakSpeed(speed, "minecraft:bamboo"));
return createDigger(speeds);
}
public static NbtMap getHoeDigger(int speed) {
List<NbtMap> speeds = new ArrayList<>();
speeds.add(createBreakSpeed(speed, "minecraft:leaves"));
speeds.add(createBreakSpeed(speed, "minecraft:leaves2"));
speeds.add(createBreakSpeed(speed, "minecraft:azalea_leaves"));
speeds.add(createBreakSpeed(speed, "minecraft:azalea_leaves_flowered"));
speeds.add(createBreakSpeed(speed, "minecraft:sculk"));
speeds.add(createBreakSpeed(speed, "minecraft:sculk_catalyst"));
speeds.add(createBreakSpeed(speed, "minecraft:sculk_sensor"));
speeds.add(createBreakSpeed(speed, "minecraft:sculk_shrieker"));
speeds.add(createBreakSpeed(speed, "minecraft:sculk_vein"));
speeds.add(createBreakSpeed(speed, "minecraft:nether_wart_block"));
speeds.add(createBreakSpeed(speed, "minecraft:warped_wart_block"));
speeds.add(createBreakSpeed(speed, "minecraft:hay_block"));
speeds.add(createBreakSpeed(speed, "minecraft:moss_block"));
speeds.add(createBreakSpeed(speed, "minecraft:shroomlight"));
speeds.add(createBreakSpeed(speed, "minecraft:sponge"));
speeds.add(createBreakSpeed(speed, "minecraft:target"));
return createDigger(speeds);
}
public static NbtMap getShearsDigger(int speed) {
List<NbtMap> speeds = new ArrayList<>();
speeds.add(createBreakSpeed(speed, "minecraft:web"));
speeds.add(createBreakSpeed(speed, "minecraft:leaves"));
speeds.add(createBreakSpeed(speed, "minecraft:leaves2"));
speeds.add(createBreakSpeed(speed, "minecraft:azalea_leaves"));
speeds.add(createBreakSpeed(speed, "minecraft:azalea_leaves_flowered"));
speeds.add(createBreakSpeed(speed, "minecraft:wool"));
speeds.add(createBreakSpeed(speed, "minecraft:glow_lichen"));
speeds.add(createBreakSpeed(speed, "minecraft:vine"));
return createDigger(speeds);
}
}

View file

@ -26,7 +26,6 @@
package org.geysermc.geyser.item.components;
import com.google.common.base.Suppliers;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.item.type.Item;
@ -66,14 +65,4 @@ public enum ToolTier {
public String toString() {
return this.name().toLowerCase(Locale.ROOT);
}
public static ToolTier getByName(@NonNull String name) {
String upperCase = name.toUpperCase(Locale.ROOT);
for (ToolTier tier : VALUES) {
if (tier.name().equals(upperCase)) {
return tier;
}
}
return null;
}
}

View file

@ -25,16 +25,14 @@
package org.geysermc.geyser.item.exception;
import java.io.Serial;
public class InvalidCustomMappingsFileException extends Exception {
public InvalidCustomMappingsFileException(Throwable cause) {
super(cause);
}
@Serial
private static final long serialVersionUID = 1L;
public InvalidCustomMappingsFileException(String message) {
super(message);
}
public InvalidCustomMappingsFileException(String message, Throwable cause) {
super(message, cause);
}
}

View file

@ -27,6 +27,7 @@ package org.geysermc.geyser.item.type;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack;
import com.github.steveice10.opennbt.tag.builtin.StringTag;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
import org.geysermc.geyser.inventory.item.TippedArrowPotion;
import org.geysermc.geyser.item.Items;
@ -38,7 +39,8 @@ public class ArrowItem extends Item {
super(javaIdentifier, builder);
}
public ItemStack translateToJava(ItemData itemData, ItemMapping mapping, ItemMappings mappings) {
@Override
public @NonNull ItemStack translateToJava(@NonNull ItemData itemData, @NonNull ItemMapping mapping, @NonNull ItemMappings mappings) {
TippedArrowPotion tippedArrowPotion = TippedArrowPotion.getByBedrockId(itemData.getDamage());
ItemStack itemStack = super.translateToJava(itemData, mapping, mappings);
if (tippedArrowPotion != null) {

View file

@ -28,9 +28,9 @@ package org.geysermc.geyser.item.type;
import com.github.steveice10.opennbt.tag.builtin.ByteTag;
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
import com.github.steveice10.opennbt.tag.builtin.StringTag;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.text.MinecraftLocale;
import org.jetbrains.annotations.NotNull;
public class AxolotlBucketItem extends Item {
public AxolotlBucketItem(String javaIdentifier, Builder builder) {
@ -38,7 +38,7 @@ public class AxolotlBucketItem extends Item {
}
@Override
public void translateNbtToBedrock(@NotNull GeyserSession session, @NotNull CompoundTag tag) {
public void translateNbtToBedrock(@NonNull GeyserSession session, @NonNull CompoundTag tag) {
super.translateNbtToBedrock(session, tag);
// Bedrock Edition displays the properties of the axolotl. Java does not.

View file

@ -29,14 +29,13 @@ import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
import com.github.steveice10.opennbt.tag.builtin.IntTag;
import com.github.steveice10.opennbt.tag.builtin.ListTag;
import com.github.steveice10.opennbt.tag.builtin.Tag;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.cloudburstmc.nbt.NbtList;
import org.cloudburstmc.nbt.NbtMap;
import org.cloudburstmc.nbt.NbtType;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.session.GeyserSession;
import org.jetbrains.annotations.NotNull;
import javax.annotation.Nonnull;
import java.util.ArrayList;
import java.util.List;
@ -45,7 +44,7 @@ import static org.geysermc.erosion.util.BannerUtils.getJavaPatternTag;
public class BannerItem extends BlockItem {
/**
* Holds what a Java ominous banner pattern looks like.
*
* <p>
* Translating the patterns over to Bedrock does not work effectively, but Bedrock has a dedicated type for
* ominous banners that we set instead. This variable is used to detect Java ominous banner patterns, and apply
* the correct ominous banner pattern if Bedrock pulls the item from creative.
@ -86,7 +85,7 @@ public class BannerItem extends BlockItem {
* @param pattern Java edition pattern nbt
* @return The Bedrock edition format pattern nbt
*/
@Nonnull
@NonNull
private static NbtMap getBedrockBannerPattern(CompoundTag pattern) {
return NbtMap.builder()
.putInt("Color", 15 - (int) pattern.get("Color").getValue())
@ -121,7 +120,7 @@ public class BannerItem extends BlockItem {
}
@Override
public void translateNbtToBedrock(@NotNull GeyserSession session, @NotNull CompoundTag tag) {
public void translateNbtToBedrock(@NonNull GeyserSession session, @NonNull CompoundTag tag) {
super.translateNbtToBedrock(session, tag);
CompoundTag blockEntityTag = tag.remove("BlockEntityTag");
@ -137,7 +136,7 @@ public class BannerItem extends BlockItem {
}
@Override
public void translateNbtToJava(@NotNull CompoundTag tag, @NotNull ItemMapping mapping) {
public void translateNbtToJava(@NonNull CompoundTag tag, @NonNull ItemMapping mapping) {
super.translateNbtToJava(tag, mapping);
if (tag.get("Type") instanceof IntTag type && type.getValue() == 1) {

View file

@ -30,6 +30,7 @@ import com.github.steveice10.opennbt.tag.builtin.ByteTag;
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
import com.github.steveice10.opennbt.tag.builtin.IntTag;
import com.github.steveice10.opennbt.tag.builtin.Tag;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.registry.type.ItemMappings;
@ -57,7 +58,7 @@ public class CompassItem extends Item {
}
@Override
public void translateNbtToBedrock(GeyserSession session, CompoundTag tag) {
public void translateNbtToBedrock(@NonNull GeyserSession session, @NonNull CompoundTag tag) {
super.translateNbtToBedrock(session, tag);
Tag lodestoneTag = tag.get("LodestoneTracked");
@ -77,7 +78,7 @@ public class CompassItem extends Item {
}
@Override
public ItemStack translateToJava(ItemData itemData, ItemMapping mapping, ItemMappings mappings) {
public @NonNull ItemStack translateToJava(@NonNull ItemData itemData, @NonNull ItemMapping mapping, @NonNull ItemMappings mappings) {
if (mapping.getBedrockIdentifier().equals("minecraft:lodestone_compass")) {
// Revert the entry back to the compass
mapping = mappings.getStoredItems().compass();

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