3
0
Mirror von https://github.com/GeyserMC/Geyser.git synchronisiert 2024-11-19 22:40:18 +01:00

Merge branch 'master' of https://github.com/GeyserMC/Geyser into feature/configurate

Dieser Commit ist enthalten in:
Camotoy 2024-11-18 20:48:02 -05:00
Commit 6c5c45176b
Es konnte kein GPG-Schlüssel zu dieser Signatur gefunden werden
GPG-Schlüssel-ID: 7EEFB66FE798081F
233 geänderte Dateien mit 29730 neuen und 5668 gelöschten Zeilen

Datei anzeigen

@ -15,7 +15,7 @@ The ultimate goal of this project is to allow Minecraft: Bedrock Edition users t
Special thanks to the DragonProxy project for being a trailblazer in protocol translation and for all the team members who have joined us here! Special thanks to the DragonProxy project for being a trailblazer in protocol translation and for all the team members who have joined us here!
## Supported Versions ## Supported Versions
Geyser is currently supporting Minecraft Bedrock 1.20.80 - 1.21.30 and Minecraft Java 1.21/1.21.1. For more information, please see [here](https://geysermc.org/wiki/geyser/supported-versions/). Geyser is currently supporting Minecraft Bedrock 1.20.80 - 1.21.44 and Minecraft Java 1.21.2/1.21.3. For more information, please see [here](https://geysermc.org/wiki/geyser/supported-versions/).
## Setting Up ## Setting Up
Take a look [here](https://geysermc.org/wiki/geyser/setup/) for how to set up Geyser. Take a look [here](https://geysermc.org/wiki/geyser/setup/) for how to set up Geyser.

Datei anzeigen

@ -70,6 +70,11 @@ public interface GeyserConnection extends Connection, CommandSource {
*/ */
void closeForm(); void closeForm();
/**
* Gets the Bedrock protocol version of the player.
*/
int protocolVersion();
/** /**
* @param javaId the Java entity ID to look up. * @param javaId the Java entity ID to look up.
* @return a {@link GeyserEntity} if present in this connection's entity tracker. * @return a {@link GeyserEntity} if present in this connection's entity tracker.

Datei anzeigen

@ -32,7 +32,7 @@ import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents;
import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents; import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents;
import net.fabricmc.loader.api.FabricLoader; import net.fabricmc.loader.api.FabricLoader;
import net.minecraft.commands.CommandSourceStack; import net.minecraft.commands.CommandSourceStack;
import net.minecraft.world.entity.player.Player; import net.minecraft.server.level.ServerPlayer;
import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.command.CommandRegistry; import org.geysermc.geyser.command.CommandRegistry;
import org.geysermc.geyser.command.CommandSourceConverter; import org.geysermc.geyser.command.CommandSourceConverter;
@ -80,7 +80,7 @@ public class GeyserFabricBootstrap extends GeyserModBootstrap implements ModInit
var sourceConverter = CommandSourceConverter.layered( var sourceConverter = CommandSourceConverter.layered(
CommandSourceStack.class, CommandSourceStack.class,
id -> getServer().getPlayerList().getPlayer(id), id -> getServer().getPlayerList().getPlayer(id),
Player::createCommandSourceStack, ServerPlayer::createCommandSourceStack,
() -> getServer().createCommandSourceStack(), // NPE if method reference is used, since server is not available yet () -> getServer().createCommandSourceStack(), // NPE if method reference is used, since server is not available yet
ModCommandSource::new ModCommandSource::new
); );

Datei anzeigen

@ -23,8 +23,8 @@
"geyser.mixins.json" "geyser.mixins.json"
], ],
"depends": { "depends": {
"fabricloader": ">=0.15.11", "fabricloader": ">=0.16.7",
"fabric": "*", "fabric": "*",
"minecraft": ">=1.21" "minecraft": ">=1.21.2"
} }
} }

Datei anzeigen

@ -13,6 +13,9 @@ architectury {
provided("org.cloudburstmc.math", "api") provided("org.cloudburstmc.math", "api")
provided("com.google.errorprone", "error_prone_annotations") provided("com.google.errorprone", "error_prone_annotations")
// Jackson shipped by Minecraft is too old, so we shade & relocate our newer version
relocate("com.fasterxml.jackson")
val includeTransitive: Configuration = configurations.getByName("includeTransitive") val includeTransitive: Configuration = configurations.getByName("includeTransitive")
dependencies { dependencies {
@ -31,6 +34,12 @@ dependencies {
} }
shadow(projects.core) { isTransitive = false } shadow(projects.core) { isTransitive = false }
// Minecraft (1.21.2+) includes jackson. But an old version!
shadow(libs.jackson.core) { isTransitive = false }
shadow(libs.jackson.databind) { isTransitive = false }
shadow(libs.jackson.dataformat.yaml) { isTransitive = false }
shadow(libs.jackson.annotations) { isTransitive = false }
// Let's shade in our own api // Let's shade in our own api
shadow(projects.api) { isTransitive = false } shadow(projects.api) { isTransitive = false }
@ -56,6 +65,11 @@ tasks {
remapModrinthJar { remapModrinthJar {
archiveBaseName.set("geyser-neoforge") archiveBaseName.set("geyser-neoforge")
} }
shadowJar {
// Without this, jackson's service files are not relocated
mergeServiceFiles()
}
} }
modrinth { modrinth {

Datei anzeigen

@ -26,7 +26,7 @@
package org.geysermc.geyser.platform.neoforge; package org.geysermc.geyser.platform.neoforge;
import net.minecraft.commands.CommandSourceStack; import net.minecraft.commands.CommandSourceStack;
import net.minecraft.world.entity.player.Player; import net.minecraft.server.level.ServerPlayer;
import net.neoforged.bus.api.EventPriority; import net.neoforged.bus.api.EventPriority;
import net.neoforged.fml.ModContainer; import net.neoforged.fml.ModContainer;
import net.neoforged.fml.common.Mod; import net.neoforged.fml.common.Mod;
@ -72,7 +72,7 @@ public class GeyserNeoForgeBootstrap extends GeyserModBootstrap {
var sourceConverter = CommandSourceConverter.layered( var sourceConverter = CommandSourceConverter.layered(
CommandSourceStack.class, CommandSourceStack.class,
id -> getServer().getPlayerList().getPlayer(id), id -> getServer().getPlayerList().getPlayer(id),
Player::createCommandSourceStack, ServerPlayer::createCommandSourceStack,
() -> getServer().createCommandSourceStack(), () -> getServer().createCommandSourceStack(),
ModCommandSource::new ModCommandSource::new
); );
@ -104,7 +104,9 @@ public class GeyserNeoForgeBootstrap extends GeyserModBootstrap {
} }
private void onPlayerJoin(PlayerEvent.PlayerLoggedInEvent event) { private void onPlayerJoin(PlayerEvent.PlayerLoggedInEvent event) {
GeyserModUpdateListener.onPlayReady(event.getEntity()); if (event.getEntity() instanceof ServerPlayer player) {
GeyserModUpdateListener.onPlayReady(player);
}
} }
@Override @Override

Datei anzeigen

@ -28,8 +28,8 @@ package org.geysermc.geyser.platform.mod;
import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelOutboundHandlerAdapter; import io.netty.channel.ChannelOutboundHandlerAdapter;
import io.netty.channel.ChannelPromise; import io.netty.channel.ChannelPromise;
import net.minecraft.network.protocol.login.ClientboundGameProfilePacket;
import net.minecraft.network.protocol.login.ClientboundLoginCompressionPacket; import net.minecraft.network.protocol.login.ClientboundLoginCompressionPacket;
import net.minecraft.network.protocol.login.ClientboundLoginFinishedPacket;
/** /**
* Disables the compression packet (and the compression handlers from being added to the pipeline) for Geyser clients * Disables the compression packet (and the compression handlers from being added to the pipeline) for Geyser clients
@ -45,7 +45,7 @@ public class GeyserModCompressionDisabler extends ChannelOutboundHandlerAdapter
Class<?> msgClass = msg.getClass(); Class<?> msgClass = msg.getClass();
// Don't let any compression packet get through // Don't let any compression packet get through
if (!ClientboundLoginCompressionPacket.class.isAssignableFrom(msgClass)) { if (!ClientboundLoginCompressionPacket.class.isAssignableFrom(msgClass)) {
if (ClientboundGameProfilePacket.class.isAssignableFrom(msgClass)) { if (ClientboundLoginFinishedPacket.class.isAssignableFrom(msgClass)) {
// We're past the point that a compression packet can be sent, so we can safely yeet ourselves away // We're past the point that a compression packet can be sent, so we can safely yeet ourselves away
ctx.channel().pipeline().remove(this); ctx.channel().pipeline().remove(this);

Datei anzeigen

@ -25,13 +25,13 @@
package org.geysermc.geyser.platform.mod; package org.geysermc.geyser.platform.mod;
import net.minecraft.world.entity.player.Player; import net.minecraft.server.level.ServerPlayer;
import org.geysermc.geyser.Permissions; import org.geysermc.geyser.Permissions;
import org.geysermc.geyser.platform.mod.command.ModCommandSource; import org.geysermc.geyser.platform.mod.command.ModCommandSource;
import org.geysermc.geyser.util.VersionCheckUtils; import org.geysermc.geyser.util.VersionCheckUtils;
public final class GeyserModUpdateListener { public final class GeyserModUpdateListener {
public static void onPlayReady(Player player) { public static void onPlayReady(ServerPlayer player) {
// Should be creating this in the supplier, but we need it for the permission check. // Should be creating this in the supplier, but we need it for the permission check.
// Not a big deal currently because ModCommandSource doesn't load locale, so don't need to try to wait for it. // Not a big deal currently because ModCommandSource doesn't load locale, so don't need to try to wait for it.
ModCommandSource source = new ModCommandSource(player.createCommandSourceStack()); ModCommandSource source = new ModCommandSource(player.createCommandSourceStack());

Datei anzeigen

@ -33,8 +33,10 @@ import net.minecraft.core.component.DataComponents;
import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
import net.minecraft.server.MinecraftServer; import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerChunkCache;
import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.entity.BannerBlockEntity; import net.minecraft.world.level.block.entity.BannerBlockEntity;
@ -43,7 +45,6 @@ import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.DecoratedPotBlockEntity; import net.minecraft.world.level.block.entity.DecoratedPotBlockEntity;
import net.minecraft.world.level.chunk.ChunkAccess; import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.LevelChunkSection; import net.minecraft.world.level.chunk.LevelChunkSection;
import net.minecraft.world.level.chunk.status.ChunkStatus;
import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.NonNull;
import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.math.vector.Vector3i;
import org.geysermc.geyser.level.GeyserWorldManager; import org.geysermc.geyser.level.GeyserWorldManager;
@ -84,16 +85,17 @@ public class GeyserModWorldManager extends GeyserWorldManager {
} }
Level level = player.level(); Level level = player.level();
if (y < level.getMinBuildHeight()) { if (y < level.getMinY()) {
return 0; return 0;
} }
ChunkAccess chunk = level.getChunkSource().getChunk(x >> 4, z >> 4, ChunkStatus.FULL, false); // Only loads active chunks, and doesn't delegate to main thread
ChunkAccess chunk = ((ServerChunkCache) level.getChunkSource()).chunkMap.getChunkToSend(ChunkPos.asLong(x >> 4, z >> 4));
if (chunk == null) { if (chunk == null) {
return 0; return 0;
} }
int worldOffset = level.getMinBuildHeight() >> 4; int worldOffset = level.getMinY() >> 4;
int chunkOffset = (y >> 4) - worldOffset; int chunkOffset = (y >> 4) - worldOffset;
if (chunkOffset < chunk.getSections().length) { if (chunkOffset < chunk.getSections().length) {
LevelChunkSection section = chunk.getSections()[chunkOffset]; LevelChunkSection section = chunk.getSections()[chunkOffset];

Datei anzeigen

@ -34,10 +34,24 @@ import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.GeyserLogger; import org.geysermc.geyser.GeyserLogger;
import org.geysermc.geyser.command.GeyserCommandSource; import org.geysermc.geyser.command.GeyserCommandSource;
import org.geysermc.geyser.text.ChatColor; import org.geysermc.geyser.text.ChatColor;
import org.jline.reader.Candidate;
import org.jline.reader.LineReader;
import org.jline.reader.LineReaderBuilder;
@Slf4j @Slf4j
public class GeyserStandaloneLogger extends SimpleTerminalConsole implements GeyserLogger, GeyserCommandSource { public class GeyserStandaloneLogger extends SimpleTerminalConsole implements GeyserLogger, GeyserCommandSource {
@Override
protected LineReader buildReader(LineReaderBuilder builder) {
builder.completer((reader, line, candidates) -> {
var suggestions = GeyserImpl.getInstance().commandRegistry().suggestionsFor(this, line.line());
for (var suggestion : suggestions.list()) {
candidates.add(new Candidate(suggestion.suggestion()));
}
});
return super.buildReader(builder);
}
@Override @Override
protected boolean isRunning() { protected boolean isRunning() {
return !GeyserImpl.getInstance().isShuttingDown(); return !GeyserImpl.getInstance().isShuttingDown();

Datei anzeigen

@ -20,6 +20,9 @@
<AppenderRef ref="TerminalConsole"/> <AppenderRef ref="TerminalConsole"/>
<AppenderRef ref="Console"/> <AppenderRef ref="Console"/>
<AppenderRef ref="File"/> <AppenderRef ref="File"/>
<filters>
<MarkerFilter marker="packet_logging" onMatch="DENY" onMismatch="ACCEPT" />
</filters>
</Root> </Root>
</Loggers> </Loggers>
</Configuration> </Configuration>

Datei anzeigen

@ -31,8 +31,10 @@ import com.velocitypowered.api.network.ProtocolVersion;
import com.velocitypowered.api.proxy.InboundConnection; import com.velocitypowered.api.proxy.InboundConnection;
import com.velocitypowered.api.proxy.ProxyServer; import com.velocitypowered.api.proxy.ProxyServer;
import com.velocitypowered.api.proxy.server.ServerPing; import com.velocitypowered.api.proxy.server.ServerPing;
import com.velocitypowered.api.proxy.server.ServerPing.Version;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
import org.geysermc.geyser.network.GameProtocol;
import org.geysermc.geyser.ping.GeyserPingInfo; import org.geysermc.geyser.ping.GeyserPingInfo;
import org.geysermc.geyser.ping.IGeyserPingPassthrough; import org.geysermc.geyser.ping.IGeyserPingPassthrough;
@ -51,7 +53,9 @@ public class GeyserVelocityPingPassthrough implements IGeyserPingPassthrough {
try { try {
event = server.getEventManager().fire(new ProxyPingEvent(new GeyserInboundConnection(inetSocketAddress), ServerPing.builder() event = server.getEventManager().fire(new ProxyPingEvent(new GeyserInboundConnection(inetSocketAddress), ServerPing.builder()
.description(server.getConfiguration().getMotd()).onlinePlayers(server.getPlayerCount()) .description(server.getConfiguration().getMotd()).onlinePlayers(server.getPlayerCount())
.maximumPlayers(server.getConfiguration().getShowMaxPlayers()).build())).get(); .maximumPlayers(server.getConfiguration().getShowMaxPlayers())
.version(new Version(GameProtocol.getJavaProtocolVersion(), GameProtocol.getJavaMinecraftVersion()))
.build())).get();
} catch (ExecutionException | InterruptedException e) { } catch (ExecutionException | InterruptedException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }

Datei anzeigen

@ -7,12 +7,13 @@ tasks.modrinth.get().dependsOn(tasks.modrinthSyncBody)
modrinth { modrinth {
token.set(System.getenv("MODRINTH_TOKEN") ?: "") // Even though this is the default value, apparently this prevents GitHub Actions caching the token? token.set(System.getenv("MODRINTH_TOKEN") ?: "") // Even though this is the default value, apparently this prevents GitHub Actions caching the token?
debugMode.set(System.getenv("MODRINTH_TOKEN") == null)
projectId.set("geyser") projectId.set("geyser")
versionName.set(versionName(project)) versionName.set(versionName(project))
versionNumber.set(projectVersion(project)) versionNumber.set(projectVersion(project))
versionType.set("beta") versionType.set("beta")
changelog.set(System.getenv("CHANGELOG") ?: "") changelog.set(System.getenv("CHANGELOG") ?: "")
gameVersions.addAll("1.21", libs.minecraft.get().version as String) gameVersions.addAll("1.21.2", libs.minecraft.get().version as String)
failSilently.set(true) failSilently.set(true)
syncBodyFrom.set(rootProject.file("README.md").readText()) syncBodyFrom.set(rootProject.file("README.md").readText())

Datei anzeigen

@ -70,6 +70,7 @@ dependencies {
// Test // Test
testImplementation(libs.junit) testImplementation(libs.junit)
testImplementation(libs.gson.runtime) // Record support testImplementation(libs.gson.runtime) // Record support
testImplementation(libs.mockito)
// Annotation Processors // Annotation Processors
compileOnly(projects.ap) compileOnly(projects.ap)

Datei anzeigen

@ -79,6 +79,7 @@ import org.geysermc.geyser.erosion.UnixSocketClientListener;
import org.geysermc.geyser.event.GeyserEventBus; import org.geysermc.geyser.event.GeyserEventBus;
import org.geysermc.geyser.extension.GeyserExtensionManager; import org.geysermc.geyser.extension.GeyserExtensionManager;
import org.geysermc.geyser.impl.MinecraftVersionImpl; import org.geysermc.geyser.impl.MinecraftVersionImpl;
import org.geysermc.geyser.level.BedrockDimension;
import org.geysermc.geyser.level.WorldManager; import org.geysermc.geyser.level.WorldManager;
import org.geysermc.geyser.network.GameProtocol; import org.geysermc.geyser.network.GameProtocol;
import org.geysermc.geyser.network.netty.GeyserServer; import org.geysermc.geyser.network.netty.GeyserServer;
@ -97,7 +98,6 @@ import org.geysermc.geyser.text.GeyserLocale;
import org.geysermc.geyser.text.MinecraftLocale; import org.geysermc.geyser.text.MinecraftLocale;
import org.geysermc.geyser.translator.text.MessageTranslator; import org.geysermc.geyser.translator.text.MessageTranslator;
import org.geysermc.geyser.util.AssetUtils; import org.geysermc.geyser.util.AssetUtils;
import org.geysermc.geyser.util.DimensionUtils;
import org.geysermc.geyser.util.JsonUtils; import org.geysermc.geyser.util.JsonUtils;
import org.geysermc.geyser.util.MinecraftAuthLogger; import org.geysermc.geyser.util.MinecraftAuthLogger;
import org.geysermc.geyser.util.NewsHandler; import org.geysermc.geyser.util.NewsHandler;
@ -229,9 +229,14 @@ public class GeyserImpl implements GeyserApi, EventRegistrar {
} }
logger.info("******************************************"); logger.info("******************************************");
/* Initialize registries */ /*
Registries.init(); First load the registries and then populate them.
BlockRegistries.init(); Both the block registries and the common registries depend on each other,
so maintaining this order is crucial for Geyser to load.
*/
Registries.load();
BlockRegistries.populate();
Registries.populate();
RegistryCache.init(); RegistryCache.init();
@ -424,7 +429,7 @@ public class GeyserImpl implements GeyserApi, EventRegistrar {
logger.debug("Epoll is not available; Erosion's Unix socket handling will not work."); logger.debug("Epoll is not available; Erosion's Unix socket handling will not work.");
} }
DimensionUtils.changeBedrockNetherId(config.aboveBedrockNetherBuilding()); // Apply End dimension ID workaround to Nether BedrockDimension.changeBedrockNetherId(config.aboveBedrockNetherBuilding()); // Apply End dimension ID workaround to Nether
Integer bedrockThreadCount = Integer.getInteger("Geyser.BedrockNetworkThreads"); Integer bedrockThreadCount = Integer.getInteger("Geyser.BedrockNetworkThreads");
if (bedrockThreadCount == null) { if (bedrockThreadCount == null) {
@ -747,7 +752,9 @@ public class GeyserImpl implements GeyserApi, EventRegistrar {
runIfNonNull(newsHandler, NewsHandler::shutdown); runIfNonNull(newsHandler, NewsHandler::shutdown);
runIfNonNull(erosionUnixListener, UnixSocketClientListener::close); runIfNonNull(erosionUnixListener, UnixSocketClientListener::close);
Registries.RESOURCE_PACKS.get().clear(); if (Registries.RESOURCE_PACKS.loaded()) {
Registries.RESOURCE_PACKS.get().clear();
}
this.setEnabled(false); this.setEnabled(false);
} }

Datei anzeigen

@ -27,6 +27,13 @@ package org.geysermc.geyser.command;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.NonNull;
import org.cloudburstmc.protocol.bedrock.data.command.CommandData;
import org.cloudburstmc.protocol.bedrock.data.command.CommandEnumConstraint;
import org.cloudburstmc.protocol.bedrock.data.command.CommandEnumData;
import org.cloudburstmc.protocol.bedrock.data.command.CommandOverloadData;
import org.cloudburstmc.protocol.bedrock.data.command.CommandParam;
import org.cloudburstmc.protocol.bedrock.data.command.CommandParamData;
import org.cloudburstmc.protocol.bedrock.data.command.CommandPermission;
import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.api.command.Command; import org.geysermc.geyser.api.command.Command;
import org.geysermc.geyser.api.event.EventRegistrar; import org.geysermc.geyser.api.event.EventRegistrar;
@ -51,14 +58,29 @@ import org.geysermc.geyser.command.defaults.StopCommand;
import org.geysermc.geyser.command.defaults.VersionCommand; import org.geysermc.geyser.command.defaults.VersionCommand;
import org.geysermc.geyser.event.type.GeyserDefineCommandsEventImpl; import org.geysermc.geyser.event.type.GeyserDefineCommandsEventImpl;
import org.geysermc.geyser.extension.command.GeyserExtensionCommand; import org.geysermc.geyser.extension.command.GeyserExtensionCommand;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.text.GeyserLocale; import org.geysermc.geyser.text.GeyserLocale;
import org.incendo.cloud.Command.Builder; import org.incendo.cloud.Command.Builder;
import org.incendo.cloud.CommandManager; import org.incendo.cloud.CommandManager;
import org.incendo.cloud.execution.ExecutionCoordinator; import org.incendo.cloud.execution.ExecutionCoordinator;
import org.incendo.cloud.internal.CommandNode;
import org.incendo.cloud.parser.standard.EnumParser;
import org.incendo.cloud.parser.standard.IntegerParser;
import org.incendo.cloud.parser.standard.LiteralParser;
import org.incendo.cloud.parser.standard.StringArrayParser;
import org.incendo.cloud.suggestion.Suggestion;
import org.incendo.cloud.suggestion.Suggestions;
import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashMap; import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.Set;
import static org.geysermc.geyser.command.GeyserCommand.DEFAULT_ROOT_COMMAND; import static org.geysermc.geyser.command.GeyserCommand.DEFAULT_ROOT_COMMAND;
@ -299,4 +321,90 @@ public class CommandRegistry implements EventRegistrar {
public void runCommand(@NonNull GeyserCommandSource source, @NonNull String command) { public void runCommand(@NonNull GeyserCommandSource source, @NonNull String command) {
cloud.commandExecutor().executeCommand(source, command); cloud.commandExecutor().executeCommand(source, command);
} }
public Suggestions<GeyserCommandSource, ? extends Suggestion> suggestionsFor(GeyserCommandSource source, String input) {
return cloud.suggestionFactory().suggestImmediately(source, input);
}
public void export(GeyserSession session, List<CommandData> bedrockCommands, Set<String> knownAliases) {
cloud.commandTree().rootNodes().forEach(commandTree -> {
var command = commandTree.command();
// Command null happens if you register an extension command with custom Cloud parameters...
if (command == null || session.hasPermission(command.commandPermission().permissionString())) {
var rootComponent = commandTree.component();
String name = rootComponent.name();
if (!knownAliases.add(name)) {
// If the server already defined the command, let's not crash.
return;
}
LinkedHashMap<String, Set<CommandEnumConstraint>> values = new LinkedHashMap<>();
for (String s : rootComponent.aliases()) {
values.put(s, EnumSet.of(CommandEnumConstraint.ALLOW_ALIASES));
}
CommandEnumData aliases = new CommandEnumData(name + "Aliases", values, false);
List<CommandOverloadData> data = new ArrayList<>();
for (var node : commandTree.children()) {
List<List<CommandParamData>> params = createParamData(session, node);
params.forEach(param -> data.add(new CommandOverloadData(false, param.toArray(CommandParamData[]::new))));
}
CommandData bedrockCommand = new CommandData(name, rootComponent.description().textDescription(),
Set.of(CommandData.Flag.NOT_CHEAT), CommandPermission.ANY, aliases,
Collections.emptyList(), data.toArray(new CommandOverloadData[0]));
bedrockCommands.add(bedrockCommand);
}
});
}
private List<List<CommandParamData>> createParamData(GeyserSession session, CommandNode<GeyserCommandSource> node) {
var command = node.command();
if (command != null && !session.hasPermission(command.commandPermission().permissionString())) {
// Triggers with subcommands like Geyser dump, stop, etc.
return Collections.emptyList();
}
CommandParamData data = new CommandParamData();
var component = node.component();
data.setName(component.name());
data.setOptional(component.optional());
var suggestionProvider = component.suggestionProvider();
if (suggestionProvider instanceof LiteralParser<GeyserCommandSource> parser) {
Map<String, Set<CommandEnumConstraint>> values = new LinkedHashMap<>();
for (String alias : parser.aliases()) {
values.put(alias, Set.of());
}
data.setEnumData(new CommandEnumData(component.name(), values, false));
} else if (suggestionProvider instanceof IntegerParser<GeyserCommandSource>) {
data.setType(CommandParam.INT);
} else if (suggestionProvider instanceof EnumParser<?,?> parser) {
LinkedHashMap<String, Set<CommandEnumConstraint>> map = new LinkedHashMap<>();
for (Enum<?> e : parser.acceptedValues()) {
map.put(e.name().toLowerCase(Locale.ROOT), Set.of());
}
data.setEnumData(new CommandEnumData(component.name().toLowerCase(Locale.ROOT), map, false));
} else if (component.parser() instanceof StringArrayParser<?>) {
data.setType(CommandParam.TEXT);
} else {
data.setType(CommandParam.STRING);
}
var children = node.children();
if (children.isEmpty()) {
List<CommandParamData> list = new ArrayList<>(); // Must be mutable; parents will be added to list.
list.add(data);
return Collections.singletonList(list); // Safe to do; will be consumed in an addAll call.
}
List<List<CommandParamData>> collectiveData = new ArrayList<>();
// If a node has multiple children, this will need to be represented
// by creating a new list/branch for each and cloning this node down each line.
for (var child : children) {
collectiveData.addAll(createParamData(session, child));
}
collectiveData.forEach(list -> list.add(0, data));
return collectiveData;
}
} }

Datei anzeigen

@ -25,10 +25,10 @@
package org.geysermc.geyser.entity; package org.geysermc.geyser.entity;
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.EntityMetadata;
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.MetadataType;
import org.geysermc.mcprotocollib.protocol.data.game.entity.type.EntityType;
import it.unimi.dsi.fastutil.objects.ObjectArrayList; import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import java.util.List;
import java.util.Locale;
import java.util.function.BiConsumer;
import lombok.Setter; import lombok.Setter;
import lombok.experimental.Accessors; import lombok.experimental.Accessors;
import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.GeyserImpl;
@ -37,10 +37,9 @@ import org.geysermc.geyser.entity.properties.GeyserEntityProperties;
import org.geysermc.geyser.entity.type.Entity; import org.geysermc.geyser.entity.type.Entity;
import org.geysermc.geyser.registry.Registries; import org.geysermc.geyser.registry.Registries;
import org.geysermc.geyser.translator.entity.EntityMetadataTranslator; import org.geysermc.geyser.translator.entity.EntityMetadataTranslator;
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.EntityMetadata;
import java.util.List; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.MetadataType;
import java.util.Locale; import org.geysermc.mcprotocollib.protocol.data.game.entity.type.EntityType;
import java.util.function.BiConsumer;
/** /**
* Represents data for an entity. This includes properties such as height and width, as well as the list of entity * Represents data for an entity. This includes properties such as height and width, as well as the list of entity

Datei anzeigen

@ -25,59 +25,163 @@
package org.geysermc.geyser.entity; package org.geysermc.geyser.entity;
import org.geysermc.geyser.entity.type.AbstractWindChargeEntity;
import org.geysermc.geyser.entity.factory.EntityFactory;
import org.geysermc.geyser.entity.type.living.monster.raid.RavagerEntity;
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.MetadataType;
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.BooleanEntityMetadata;
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.FloatEntityMetadata;
import org.geysermc.mcprotocollib.protocol.data.game.entity.type.EntityType;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
import org.geysermc.geyser.entity.factory.EntityFactory;
import org.geysermc.geyser.entity.properties.GeyserEntityProperties; import org.geysermc.geyser.entity.properties.GeyserEntityProperties;
import org.geysermc.geyser.entity.type.*; import org.geysermc.geyser.entity.type.AbstractArrowEntity;
import org.geysermc.geyser.entity.type.living.*; import org.geysermc.geyser.entity.type.AbstractWindChargeEntity;
import org.geysermc.geyser.entity.type.living.animal.*; import org.geysermc.geyser.entity.type.AreaEffectCloudEntity;
import org.geysermc.geyser.entity.type.living.animal.horse.*; import org.geysermc.geyser.entity.type.ArrowEntity;
import org.geysermc.geyser.entity.type.BoatEntity;
import org.geysermc.geyser.entity.type.ChestBoatEntity;
import org.geysermc.geyser.entity.type.CommandBlockMinecartEntity;
import org.geysermc.geyser.entity.type.DisplayBaseEntity;
import org.geysermc.geyser.entity.type.EnderCrystalEntity;
import org.geysermc.geyser.entity.type.Entity;
import org.geysermc.geyser.entity.type.EvokerFangsEntity;
import org.geysermc.geyser.entity.type.ExpOrbEntity;
import org.geysermc.geyser.entity.type.FallingBlockEntity;
import org.geysermc.geyser.entity.type.FireballEntity;
import org.geysermc.geyser.entity.type.FireworkEntity;
import org.geysermc.geyser.entity.type.FishingHookEntity;
import org.geysermc.geyser.entity.type.FurnaceMinecartEntity;
import org.geysermc.geyser.entity.type.InteractionEntity;
import org.geysermc.geyser.entity.type.ItemEntity;
import org.geysermc.geyser.entity.type.ItemFrameEntity;
import org.geysermc.geyser.entity.type.LeashKnotEntity;
import org.geysermc.geyser.entity.type.LightningEntity;
import org.geysermc.geyser.entity.type.LivingEntity;
import org.geysermc.geyser.entity.type.MinecartEntity;
import org.geysermc.geyser.entity.type.PaintingEntity;
import org.geysermc.geyser.entity.type.SpawnerMinecartEntity;
import org.geysermc.geyser.entity.type.TNTEntity;
import org.geysermc.geyser.entity.type.TextDisplayEntity;
import org.geysermc.geyser.entity.type.ThrowableEntity;
import org.geysermc.geyser.entity.type.ThrowableItemEntity;
import org.geysermc.geyser.entity.type.ThrownPotionEntity;
import org.geysermc.geyser.entity.type.TridentEntity;
import org.geysermc.geyser.entity.type.WitherSkullEntity;
import org.geysermc.geyser.entity.type.living.AbstractFishEntity;
import org.geysermc.geyser.entity.type.living.AgeableEntity;
import org.geysermc.geyser.entity.type.living.AllayEntity;
import org.geysermc.geyser.entity.type.living.ArmorStandEntity;
import org.geysermc.geyser.entity.type.living.BatEntity;
import org.geysermc.geyser.entity.type.living.DolphinEntity;
import org.geysermc.geyser.entity.type.living.GlowSquidEntity;
import org.geysermc.geyser.entity.type.living.IronGolemEntity;
import org.geysermc.geyser.entity.type.living.MagmaCubeEntity;
import org.geysermc.geyser.entity.type.living.MobEntity;
import org.geysermc.geyser.entity.type.living.SlimeEntity;
import org.geysermc.geyser.entity.type.living.SnowGolemEntity;
import org.geysermc.geyser.entity.type.living.SquidEntity;
import org.geysermc.geyser.entity.type.living.TadpoleEntity;
import org.geysermc.geyser.entity.type.living.animal.ArmadilloEntity;
import org.geysermc.geyser.entity.type.living.animal.AxolotlEntity;
import org.geysermc.geyser.entity.type.living.animal.BeeEntity;
import org.geysermc.geyser.entity.type.living.animal.ChickenEntity;
import org.geysermc.geyser.entity.type.living.animal.CowEntity;
import org.geysermc.geyser.entity.type.living.animal.FoxEntity;
import org.geysermc.geyser.entity.type.living.animal.FrogEntity;
import org.geysermc.geyser.entity.type.living.animal.GoatEntity;
import org.geysermc.geyser.entity.type.living.animal.HoglinEntity;
import org.geysermc.geyser.entity.type.living.animal.MooshroomEntity;
import org.geysermc.geyser.entity.type.living.animal.OcelotEntity;
import org.geysermc.geyser.entity.type.living.animal.PandaEntity;
import org.geysermc.geyser.entity.type.living.animal.PigEntity;
import org.geysermc.geyser.entity.type.living.animal.PolarBearEntity;
import org.geysermc.geyser.entity.type.living.animal.PufferFishEntity;
import org.geysermc.geyser.entity.type.living.animal.RabbitEntity;
import org.geysermc.geyser.entity.type.living.animal.SheepEntity;
import org.geysermc.geyser.entity.type.living.animal.SnifferEntity;
import org.geysermc.geyser.entity.type.living.animal.StriderEntity;
import org.geysermc.geyser.entity.type.living.animal.TropicalFishEntity;
import org.geysermc.geyser.entity.type.living.animal.TurtleEntity;
import org.geysermc.geyser.entity.type.living.animal.horse.AbstractHorseEntity;
import org.geysermc.geyser.entity.type.living.animal.horse.CamelEntity;
import org.geysermc.geyser.entity.type.living.animal.horse.ChestedHorseEntity;
import org.geysermc.geyser.entity.type.living.animal.horse.HorseEntity;
import org.geysermc.geyser.entity.type.living.animal.horse.LlamaEntity;
import org.geysermc.geyser.entity.type.living.animal.horse.SkeletonHorseEntity;
import org.geysermc.geyser.entity.type.living.animal.horse.TraderLlamaEntity;
import org.geysermc.geyser.entity.type.living.animal.horse.ZombieHorseEntity;
import org.geysermc.geyser.entity.type.living.animal.tameable.CatEntity; import org.geysermc.geyser.entity.type.living.animal.tameable.CatEntity;
import org.geysermc.geyser.entity.type.living.animal.tameable.ParrotEntity; import org.geysermc.geyser.entity.type.living.animal.tameable.ParrotEntity;
import org.geysermc.geyser.entity.type.living.animal.tameable.TameableEntity; import org.geysermc.geyser.entity.type.living.animal.tameable.TameableEntity;
import org.geysermc.geyser.entity.type.living.animal.tameable.WolfEntity; import org.geysermc.geyser.entity.type.living.animal.tameable.WolfEntity;
import org.geysermc.geyser.entity.type.living.merchant.AbstractMerchantEntity; import org.geysermc.geyser.entity.type.living.merchant.AbstractMerchantEntity;
import org.geysermc.geyser.entity.type.living.merchant.VillagerEntity; import org.geysermc.geyser.entity.type.living.merchant.VillagerEntity;
import org.geysermc.geyser.entity.type.living.monster.*; import org.geysermc.geyser.entity.type.living.monster.AbstractSkeletonEntity;
import org.geysermc.geyser.entity.type.living.monster.BasePiglinEntity;
import org.geysermc.geyser.entity.type.living.monster.BlazeEntity;
import org.geysermc.geyser.entity.type.living.monster.BoggedEntity;
import org.geysermc.geyser.entity.type.living.monster.BreezeEntity;
import org.geysermc.geyser.entity.type.living.monster.CreeperEntity;
import org.geysermc.geyser.entity.type.living.monster.ElderGuardianEntity;
import org.geysermc.geyser.entity.type.living.monster.EnderDragonEntity;
import org.geysermc.geyser.entity.type.living.monster.EnderDragonPartEntity;
import org.geysermc.geyser.entity.type.living.monster.EndermanEntity;
import org.geysermc.geyser.entity.type.living.monster.GhastEntity;
import org.geysermc.geyser.entity.type.living.monster.GiantEntity;
import org.geysermc.geyser.entity.type.living.monster.GuardianEntity;
import org.geysermc.geyser.entity.type.living.monster.MonsterEntity;
import org.geysermc.geyser.entity.type.living.monster.PhantomEntity;
import org.geysermc.geyser.entity.type.living.monster.PiglinEntity;
import org.geysermc.geyser.entity.type.living.monster.ShulkerEntity;
import org.geysermc.geyser.entity.type.living.monster.SkeletonEntity;
import org.geysermc.geyser.entity.type.living.monster.SpiderEntity;
import org.geysermc.geyser.entity.type.living.monster.VexEntity;
import org.geysermc.geyser.entity.type.living.monster.WardenEntity;
import org.geysermc.geyser.entity.type.living.monster.WitherEntity;
import org.geysermc.geyser.entity.type.living.monster.ZoglinEntity;
import org.geysermc.geyser.entity.type.living.monster.ZombieEntity;
import org.geysermc.geyser.entity.type.living.monster.ZombieVillagerEntity;
import org.geysermc.geyser.entity.type.living.monster.ZombifiedPiglinEntity;
import org.geysermc.geyser.entity.type.living.monster.raid.PillagerEntity; import org.geysermc.geyser.entity.type.living.monster.raid.PillagerEntity;
import org.geysermc.geyser.entity.type.living.monster.raid.RaidParticipantEntity; import org.geysermc.geyser.entity.type.living.monster.raid.RaidParticipantEntity;
import org.geysermc.geyser.entity.type.living.monster.raid.RavagerEntity;
import org.geysermc.geyser.entity.type.living.monster.raid.SpellcasterIllagerEntity; import org.geysermc.geyser.entity.type.living.monster.raid.SpellcasterIllagerEntity;
import org.geysermc.geyser.entity.type.living.monster.raid.VindicatorEntity; import org.geysermc.geyser.entity.type.living.monster.raid.VindicatorEntity;
import org.geysermc.geyser.entity.type.player.PlayerEntity; import org.geysermc.geyser.entity.type.player.PlayerEntity;
import org.geysermc.geyser.registry.Registries; import org.geysermc.geyser.registry.Registries;
import org.geysermc.geyser.translator.text.MessageTranslator; import org.geysermc.geyser.translator.text.MessageTranslator;
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.MetadataType;
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.BooleanEntityMetadata;
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.FloatEntityMetadata;
import org.geysermc.mcprotocollib.protocol.data.game.entity.type.EntityType;
public final class EntityDefinitions { public final class EntityDefinitions {
public static final EntityDefinition<BoatEntity> ACACIA_BOAT;
public static final EntityDefinition<ChestBoatEntity> ACACIA_CHEST_BOAT;
public static final EntityDefinition<AllayEntity> ALLAY; public static final EntityDefinition<AllayEntity> ALLAY;
public static final EntityDefinition<AreaEffectCloudEntity> AREA_EFFECT_CLOUD; public static final EntityDefinition<AreaEffectCloudEntity> AREA_EFFECT_CLOUD;
public static final EntityDefinition<ArmadilloEntity> ARMADILLO; public static final EntityDefinition<ArmadilloEntity> ARMADILLO;
public static final EntityDefinition<ArmorStandEntity> ARMOR_STAND; public static final EntityDefinition<ArmorStandEntity> ARMOR_STAND;
public static final EntityDefinition<ArrowEntity> ARROW; public static final EntityDefinition<ArrowEntity> ARROW;
public static final EntityDefinition<AxolotlEntity> AXOLOTL; public static final EntityDefinition<AxolotlEntity> AXOLOTL;
public static final EntityDefinition<BoatEntity> BAMBOO_RAFT;
public static final EntityDefinition<ChestBoatEntity> BAMBOO_CHEST_RAFT;
public static final EntityDefinition<BatEntity> BAT; public static final EntityDefinition<BatEntity> BAT;
public static final EntityDefinition<BeeEntity> BEE; public static final EntityDefinition<BeeEntity> BEE;
public static final EntityDefinition<BoatEntity> BIRCH_BOAT;
public static final EntityDefinition<ChestBoatEntity> BIRCH_CHEST_BOAT;
public static final EntityDefinition<BlazeEntity> BLAZE; public static final EntityDefinition<BlazeEntity> BLAZE;
public static final EntityDefinition<BoatEntity> BOAT;
public static final EntityDefinition<BoggedEntity> BOGGED; public static final EntityDefinition<BoggedEntity> BOGGED;
public static final EntityDefinition<BreezeEntity> BREEZE; public static final EntityDefinition<BreezeEntity> BREEZE;
public static final EntityDefinition<AbstractWindChargeEntity> BREEZE_WIND_CHARGE; public static final EntityDefinition<AbstractWindChargeEntity> BREEZE_WIND_CHARGE;
public static final EntityDefinition<CamelEntity> CAMEL; public static final EntityDefinition<CamelEntity> CAMEL;
public static final EntityDefinition<CatEntity> CAT; public static final EntityDefinition<CatEntity> CAT;
public static final EntityDefinition<SpiderEntity> CAVE_SPIDER; public static final EntityDefinition<SpiderEntity> CAVE_SPIDER;
public static final EntityDefinition<BoatEntity> CHERRY_BOAT;
public static final EntityDefinition<ChestBoatEntity> CHERRY_CHEST_BOAT;
public static final EntityDefinition<MinecartEntity> CHEST_MINECART; public static final EntityDefinition<MinecartEntity> CHEST_MINECART;
public static final EntityDefinition<ChickenEntity> CHICKEN; public static final EntityDefinition<ChickenEntity> CHICKEN;
public static final EntityDefinition<ChestBoatEntity> CHEST_BOAT;
public static final EntityDefinition<AbstractFishEntity> COD; public static final EntityDefinition<AbstractFishEntity> COD;
public static final EntityDefinition<CommandBlockMinecartEntity> COMMAND_BLOCK_MINECART; public static final EntityDefinition<CommandBlockMinecartEntity> COMMAND_BLOCK_MINECART;
public static final EntityDefinition<CowEntity> COW; public static final EntityDefinition<CowEntity> COW;
public static final EntityDefinition<CreeperEntity> CREEPER; public static final EntityDefinition<CreeperEntity> CREEPER;
public static final EntityDefinition<BoatEntity> DARK_OAK_BOAT;
public static final EntityDefinition<ChestBoatEntity> DARK_OAK_CHEST_BOAT;
public static final EntityDefinition<DolphinEntity> DOLPHIN; public static final EntityDefinition<DolphinEntity> DOLPHIN;
public static final EntityDefinition<ChestedHorseEntity> DONKEY; public static final EntityDefinition<ChestedHorseEntity> DONKEY;
public static final EntityDefinition<FireballEntity> DRAGON_FIREBALL; public static final EntityDefinition<FireballEntity> DRAGON_FIREBALL;
@ -116,14 +220,20 @@ public final class EntityDefinitions {
public static final EntityDefinition<IronGolemEntity> IRON_GOLEM; public static final EntityDefinition<IronGolemEntity> IRON_GOLEM;
public static final EntityDefinition<ItemEntity> ITEM; public static final EntityDefinition<ItemEntity> ITEM;
public static final EntityDefinition<ItemFrameEntity> ITEM_FRAME; public static final EntityDefinition<ItemFrameEntity> ITEM_FRAME;
public static final EntityDefinition<BoatEntity> JUNGLE_BOAT;
public static final EntityDefinition<ChestBoatEntity> JUNGLE_CHEST_BOAT;
public static final EntityDefinition<LeashKnotEntity> LEASH_KNOT; public static final EntityDefinition<LeashKnotEntity> LEASH_KNOT;
public static final EntityDefinition<LightningEntity> LIGHTNING_BOLT; public static final EntityDefinition<LightningEntity> LIGHTNING_BOLT;
public static final EntityDefinition<LlamaEntity> LLAMA; public static final EntityDefinition<LlamaEntity> LLAMA;
public static final EntityDefinition<ThrowableEntity> LLAMA_SPIT; public static final EntityDefinition<ThrowableEntity> LLAMA_SPIT;
public static final EntityDefinition<MagmaCubeEntity> MAGMA_CUBE; public static final EntityDefinition<MagmaCubeEntity> MAGMA_CUBE;
public static final EntityDefinition<BoatEntity> MANGROVE_BOAT;
public static final EntityDefinition<ChestBoatEntity> MANGROVE_CHEST_BOAT;
public static final EntityDefinition<MinecartEntity> MINECART; public static final EntityDefinition<MinecartEntity> MINECART;
public static final EntityDefinition<MooshroomEntity> MOOSHROOM; public static final EntityDefinition<MooshroomEntity> MOOSHROOM;
public static final EntityDefinition<ChestedHorseEntity> MULE; public static final EntityDefinition<ChestedHorseEntity> MULE;
public static final EntityDefinition<BoatEntity> OAK_BOAT;
public static final EntityDefinition<ChestBoatEntity> OAK_CHEST_BOAT;
public static final EntityDefinition<OcelotEntity> OCELOT; public static final EntityDefinition<OcelotEntity> OCELOT;
public static final EntityDefinition<PaintingEntity> PAINTING; public static final EntityDefinition<PaintingEntity> PAINTING;
public static final EntityDefinition<PandaEntity> PANDA; public static final EntityDefinition<PandaEntity> PANDA;
@ -154,6 +264,8 @@ public final class EntityDefinitions {
public static final EntityDefinition<SpawnerMinecartEntity> SPAWNER_MINECART; // Not present on Bedrock public static final EntityDefinition<SpawnerMinecartEntity> SPAWNER_MINECART; // Not present on Bedrock
public static final EntityDefinition<AbstractArrowEntity> SPECTRAL_ARROW; public static final EntityDefinition<AbstractArrowEntity> SPECTRAL_ARROW;
public static final EntityDefinition<SpiderEntity> SPIDER; public static final EntityDefinition<SpiderEntity> SPIDER;
public static final EntityDefinition<BoatEntity> SPRUCE_BOAT;
public static final EntityDefinition<ChestBoatEntity> SPRUCE_CHEST_BOAT;
public static final EntityDefinition<SquidEntity> SQUID; public static final EntityDefinition<SquidEntity> SQUID;
public static final EntityDefinition<AbstractSkeletonEntity> STRAY; public static final EntityDefinition<AbstractSkeletonEntity> STRAY;
public static final EntityDefinition<StriderEntity> STRIDER; public static final EntityDefinition<StriderEntity> STRIDER;
@ -212,23 +324,6 @@ public final class EntityDefinitions {
.addTranslator(null) // Waiting .addTranslator(null) // Waiting
.addTranslator(MetadataType.PARTICLE, AreaEffectCloudEntity::setParticle) .addTranslator(MetadataType.PARTICLE, AreaEffectCloudEntity::setParticle)
.build(); .build();
BOAT = EntityDefinition.inherited(BoatEntity::new, entityBase)
.type(EntityType.BOAT)
.height(0.6f).width(1.6f)
.offset(0.35f)
.addTranslator(MetadataType.INT, (boatEntity, entityMetadata) -> boatEntity.getDirtyMetadata().put(EntityDataTypes.HURT_TICKS, entityMetadata.getValue())) // Time since last hit
.addTranslator(MetadataType.INT, (boatEntity, entityMetadata) -> boatEntity.getDirtyMetadata().put(EntityDataTypes.HURT_DIRECTION, entityMetadata.getValue())) // Rocking direction
.addTranslator(MetadataType.FLOAT, (boatEntity, entityMetadata) ->
// 'Health' in Bedrock, damage taken in Java - it makes motion in Bedrock
boatEntity.getDirtyMetadata().put(EntityDataTypes.STRUCTURAL_INTEGRITY, 40 - ((int) ((FloatEntityMetadata) entityMetadata).getPrimitiveValue())))
.addTranslator(MetadataType.INT, BoatEntity::setVariant)
.addTranslator(MetadataType.BOOLEAN, BoatEntity::setPaddlingLeft)
.addTranslator(MetadataType.BOOLEAN, BoatEntity::setPaddlingRight)
.addTranslator(MetadataType.INT, (boatEntity, entityMetadata) -> boatEntity.getDirtyMetadata().put(EntityDataTypes.BOAT_BUBBLE_TIME, entityMetadata.getValue())) // May not actually do anything
.build();
CHEST_BOAT = EntityDefinition.inherited(ChestBoatEntity::new, BOAT)
.type(EntityType.CHEST_BOAT)
.build();
DRAGON_FIREBALL = EntityDefinition.inherited(FireballEntity::new, entityBase) DRAGON_FIREBALL = EntityDefinition.inherited(FireballEntity::new, entityBase)
.type(EntityType.DRAGON_FIREBALL) .type(EntityType.DRAGON_FIREBALL)
.heightAndWidth(1.0f) .heightAndWidth(1.0f)
@ -397,6 +492,7 @@ public final class EntityDefinitions {
EntityDefinition<AbstractArrowEntity> abstractArrowBase = EntityDefinition.inherited(AbstractArrowEntity::new, entityBase) EntityDefinition<AbstractArrowEntity> abstractArrowBase = EntityDefinition.inherited(AbstractArrowEntity::new, entityBase)
.addTranslator(MetadataType.BYTE, AbstractArrowEntity::setArrowFlags) .addTranslator(MetadataType.BYTE, AbstractArrowEntity::setArrowFlags)
.addTranslator(null) // "Piercing level" .addTranslator(null) // "Piercing level"
.addTranslator(null) // If the arrow is in the ground
.build(); .build();
ARROW = EntityDefinition.inherited(ArrowEntity::new, abstractArrowBase) ARROW = EntityDefinition.inherited(ArrowEntity::new, abstractArrowBase)
.type(EntityType.ARROW) .type(EntityType.ARROW)
@ -471,6 +567,45 @@ public final class EntityDefinitions {
.build(false); .build(false);
} }
// Boats
{
EntityDefinition<BoatEntity> boatBase = EntityDefinition.<BoatEntity>inherited(null, entityBase)
.height(0.6f).width(1.6f)
.offset(0.35f)
.addTranslator(MetadataType.INT, (boatEntity, entityMetadata) -> boatEntity.getDirtyMetadata().put(EntityDataTypes.HURT_TICKS, entityMetadata.getValue())) // Time since last hit
.addTranslator(MetadataType.INT, (boatEntity, entityMetadata) -> boatEntity.getDirtyMetadata().put(EntityDataTypes.HURT_DIRECTION, entityMetadata.getValue())) // Rocking direction
.addTranslator(MetadataType.FLOAT, (boatEntity, entityMetadata) ->
// 'Health' in Bedrock, damage taken in Java - it makes motion in Bedrock
boatEntity.getDirtyMetadata().put(EntityDataTypes.STRUCTURAL_INTEGRITY, 40 - ((int) ((FloatEntityMetadata) entityMetadata).getPrimitiveValue())))
.addTranslator(MetadataType.BOOLEAN, BoatEntity::setPaddlingLeft)
.addTranslator(MetadataType.BOOLEAN, BoatEntity::setPaddlingRight)
.addTranslator(MetadataType.INT, (boatEntity, entityMetadata) -> boatEntity.getDirtyMetadata().put(EntityDataTypes.BOAT_BUBBLE_TIME, entityMetadata.getValue())) // May not actually do anything
.build();
ACACIA_BOAT = buildBoat(boatBase, EntityType.ACACIA_BOAT, BoatEntity.BoatVariant.ACACIA);
BAMBOO_RAFT = buildBoat(boatBase, EntityType.BAMBOO_RAFT, BoatEntity.BoatVariant.BAMBOO);
BIRCH_BOAT = buildBoat(boatBase, EntityType.BIRCH_BOAT, BoatEntity.BoatVariant.BIRCH);
CHERRY_BOAT = buildBoat(boatBase, EntityType.CHERRY_BOAT, BoatEntity.BoatVariant.CHERRY);
DARK_OAK_BOAT = buildBoat(boatBase, EntityType.DARK_OAK_BOAT, BoatEntity.BoatVariant.DARK_OAK);
JUNGLE_BOAT = buildBoat(boatBase, EntityType.JUNGLE_BOAT, BoatEntity.BoatVariant.JUNGLE);
MANGROVE_BOAT = buildBoat(boatBase, EntityType.MANGROVE_BOAT, BoatEntity.BoatVariant.MANGROVE);
OAK_BOAT = buildBoat(boatBase, EntityType.OAK_BOAT, BoatEntity.BoatVariant.OAK);
SPRUCE_BOAT = buildBoat(boatBase, EntityType.SPRUCE_BOAT, BoatEntity.BoatVariant.SPRUCE);
EntityDefinition<ChestBoatEntity> chestBoatBase = EntityDefinition.<ChestBoatEntity>inherited(null, boatBase)
.build();
ACACIA_CHEST_BOAT = buildChestBoat(chestBoatBase, EntityType.ACACIA_CHEST_BOAT, BoatEntity.BoatVariant.ACACIA);
BAMBOO_CHEST_RAFT = buildChestBoat(chestBoatBase, EntityType.BAMBOO_CHEST_RAFT, BoatEntity.BoatVariant.BAMBOO);
BIRCH_CHEST_BOAT = buildChestBoat(chestBoatBase, EntityType.BIRCH_CHEST_BOAT, BoatEntity.BoatVariant.BIRCH);
CHERRY_CHEST_BOAT = buildChestBoat(chestBoatBase, EntityType.CHERRY_CHEST_BOAT, BoatEntity.BoatVariant.CHERRY);
DARK_OAK_CHEST_BOAT = buildChestBoat(chestBoatBase, EntityType.DARK_OAK_CHEST_BOAT, BoatEntity.BoatVariant.DARK_OAK);
JUNGLE_CHEST_BOAT = buildChestBoat(chestBoatBase, EntityType.JUNGLE_CHEST_BOAT, BoatEntity.BoatVariant.JUNGLE);
MANGROVE_CHEST_BOAT = buildChestBoat(chestBoatBase, EntityType.MANGROVE_CHEST_BOAT, BoatEntity.BoatVariant.MANGROVE);
OAK_CHEST_BOAT = buildChestBoat(chestBoatBase, EntityType.OAK_CHEST_BOAT, BoatEntity.BoatVariant.OAK);
SPRUCE_CHEST_BOAT = buildChestBoat(chestBoatBase, EntityType.SPRUCE_CHEST_BOAT, BoatEntity.BoatVariant.SPRUCE);
}
EntityDefinition<LivingEntity> livingEntityBase = EntityDefinition.inherited(LivingEntity::new, entityBase) EntityDefinition<LivingEntity> livingEntityBase = EntityDefinition.inherited(LivingEntity::new, entityBase)
.addTranslator(MetadataType.BYTE, LivingEntity::setLivingEntityFlags) .addTranslator(MetadataType.BYTE, LivingEntity::setLivingEntityFlags)
.addTranslator(MetadataType.FLOAT, LivingEntity::setHealth) .addTranslator(MetadataType.FLOAT, LivingEntity::setHealth)
@ -544,14 +679,6 @@ public final class EntityDefinitions {
.addTranslator(MetadataType.BOOLEAN, (entity, entityMetadata) -> entity.setFlag(EntityFlag.POWERED, ((BooleanEntityMetadata) entityMetadata).getPrimitiveValue())) .addTranslator(MetadataType.BOOLEAN, (entity, entityMetadata) -> entity.setFlag(EntityFlag.POWERED, ((BooleanEntityMetadata) entityMetadata).getPrimitiveValue()))
.addTranslator(MetadataType.BOOLEAN, CreeperEntity::setIgnited) .addTranslator(MetadataType.BOOLEAN, CreeperEntity::setIgnited)
.build(); .build();
DOLPHIN = EntityDefinition.inherited(DolphinEntity::new, mobEntityBase)
.type(EntityType.DOLPHIN)
.height(0.6f).width(0.9f)
//TODO check
.addTranslator(null) // treasure position
.addTranslator(null) // "got fish"
.addTranslator(null) // "moistness level"
.build();
ENDERMAN = EntityDefinition.inherited(EndermanEntity::new, mobEntityBase) ENDERMAN = EntityDefinition.inherited(EndermanEntity::new, mobEntityBase)
.type(EntityType.ENDERMAN) .type(EntityType.ENDERMAN)
.height(2.9f).width(0.6f) .height(2.9f).width(0.6f)
@ -621,10 +748,6 @@ public final class EntityDefinitions {
.type(EntityType.CAVE_SPIDER) .type(EntityType.CAVE_SPIDER)
.height(0.5f).width(0.7f) .height(0.5f).width(0.7f)
.build(); .build();
SQUID = EntityDefinition.inherited(SquidEntity::new, mobEntityBase)
.type(EntityType.SQUID)
.heightAndWidth(0.8f)
.build();
STRAY = EntityDefinition.inherited(AbstractSkeletonEntity::new, mobEntityBase) STRAY = EntityDefinition.inherited(AbstractSkeletonEntity::new, mobEntityBase)
.type(EntityType.STRAY) .type(EntityType.STRAY)
.height(1.8f).width(0.6f) .height(1.8f).width(0.6f)
@ -723,6 +846,7 @@ public final class EntityDefinitions {
SALMON = EntityDefinition.inherited(abstractFishEntityBase.factory(), abstractFishEntityBase) SALMON = EntityDefinition.inherited(abstractFishEntityBase.factory(), abstractFishEntityBase)
.type(EntityType.SALMON) .type(EntityType.SALMON)
.height(0.5f).width(0.7f) .height(0.5f).width(0.7f)
.addTranslator(null) // Scale/variant - TODO
.build(); .build();
TADPOLE = EntityDefinition.inherited(TadpoleEntity::new, abstractFishEntityBase) TADPOLE = EntityDefinition.inherited(TadpoleEntity::new, abstractFishEntityBase)
.type(EntityType.TADPOLE) .type(EntityType.TADPOLE)
@ -750,11 +874,6 @@ public final class EntityDefinitions {
.height(1.95f).width(0.6f) .height(1.95f).width(0.6f)
.build(); .build();
GLOW_SQUID = EntityDefinition.inherited(GlowSquidEntity::new, SQUID)
.type(EntityType.GLOW_SQUID)
.addTranslator(null) // Set dark ticks remaining, possible TODO
.build();
EntityDefinition<RaidParticipantEntity> raidParticipantEntityBase = EntityDefinition.inherited(RaidParticipantEntity::new, mobEntityBase) EntityDefinition<RaidParticipantEntity> raidParticipantEntityBase = EntityDefinition.inherited(RaidParticipantEntity::new, mobEntityBase)
.addTranslator(null) // Celebrating //TODO .addTranslator(null) // Celebrating //TODO
.build(); .build();
@ -946,6 +1065,26 @@ public final class EntityDefinitions {
.build(); .build();
} }
// Water creatures (AgeableWaterCreature)
{
DOLPHIN = EntityDefinition.inherited(DolphinEntity::new, ageableEntityBase)
.type(EntityType.DOLPHIN)
.height(0.6f).width(0.9f)
//TODO check
.addTranslator(null) // treasure position
.addTranslator(null) // "got fish"
.addTranslator(null) // "moistness level"
.build();
SQUID = EntityDefinition.inherited(SquidEntity::new, ageableEntityBase)
.type(EntityType.SQUID)
.heightAndWidth(0.8f)
.build();
GLOW_SQUID = EntityDefinition.inherited(GlowSquidEntity::new, SQUID)
.type(EntityType.GLOW_SQUID)
.addTranslator(null) // Set dark ticks remaining, possible TODO
.build();
}
// Horses // Horses
{ {
EntityDefinition<AbstractHorseEntity> abstractHorseEntityBase = EntityDefinition.inherited(AbstractHorseEntity::new, ageableEntityBase) EntityDefinition<AbstractHorseEntity> abstractHorseEntityBase = EntityDefinition.inherited(AbstractHorseEntity::new, ageableEntityBase)
@ -1028,6 +1167,22 @@ public final class EntityDefinitions {
Registries.JAVA_ENTITY_IDENTIFIERS.get().put("minecraft:marker", null); // We don't need an entity definition for this as it is never sent over the network Registries.JAVA_ENTITY_IDENTIFIERS.get().put("minecraft:marker", null); // We don't need an entity definition for this as it is never sent over the network
} }
private static EntityDefinition<BoatEntity> buildBoat(EntityDefinition<BoatEntity> base, EntityType entityType, BoatEntity.BoatVariant variant) {
return EntityDefinition.inherited((session, javaId, bedrockId, uuid, definition, position, motion, yaw, pitch, headYaw) ->
new BoatEntity(session, javaId, bedrockId, uuid, definition, position, motion, yaw, variant), base)
.type(entityType)
.identifier("minecraft:boat")
.build();
}
private static EntityDefinition<ChestBoatEntity> buildChestBoat(EntityDefinition<ChestBoatEntity> base, EntityType entityType, BoatEntity.BoatVariant variant) {
return EntityDefinition.inherited((session, javaId, bedrockId, uuid, definition, position, motion, yaw, pitch, headYaw) ->
new ChestBoatEntity(session, javaId, bedrockId, uuid, definition, position, motion, yaw, variant), base)
.type(entityType)
.identifier("minecraft:chest_boat")
.build();
}
public static void init() { public static void init() {
// no-op // no-op
} }

Datei anzeigen

@ -32,7 +32,7 @@ import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataType;
import java.util.Map; import java.util.Map;
/** /**
* A write-only wrapper for temporarily storing entity metadata that will be sent to Bedrock. * A wrapper for temporarily storing entity metadata that will be sent to Bedrock.
*/ */
public final class GeyserDirtyMetadata { public final class GeyserDirtyMetadata {
private final Map<EntityDataType<?>, Object> metadata = new Object2ObjectLinkedOpenHashMap<>(); private final Map<EntityDataType<?>, Object> metadata = new Object2ObjectLinkedOpenHashMap<>();
@ -53,6 +53,14 @@ public final class GeyserDirtyMetadata {
return !metadata.isEmpty(); return !metadata.isEmpty();
} }
/**
* Intended for testing purposes only
*/
public <T> T get(EntityDataType<T> entityData) {
//noinspection unchecked
return (T) metadata.get(entityData);
}
@Override @Override
public String toString() { public String toString() {
return metadata.toString(); return metadata.toString();

Datei anzeigen

@ -32,12 +32,14 @@ import org.cloudburstmc.protocol.bedrock.packet.AnimatePacket;
import org.cloudburstmc.protocol.bedrock.packet.MoveEntityAbsolutePacket; import org.cloudburstmc.protocol.bedrock.packet.MoveEntityAbsolutePacket;
import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.entity.EntityDefinitions; import org.geysermc.geyser.entity.EntityDefinitions;
import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.item.type.Item;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.util.InteractionResult; import org.geysermc.geyser.util.InteractionResult;
import org.geysermc.geyser.util.InteractiveTag; import org.geysermc.geyser.util.InteractiveTag;
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.BooleanEntityMetadata;
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.IntEntityMetadata;
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand; import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand;
import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.level.ServerboundPaddleBoatPacket;
import java.util.UUID; import java.util.UUID;
@ -63,16 +65,19 @@ public class BoatEntity extends Entity implements Leashable, Tickable {
* Saved for using the "pick" functionality on a boat. * Saved for using the "pick" functionality on a boat.
*/ */
@Getter @Getter
private int variant; protected final BoatVariant variant;
private long leashHolderBedrockId = -1; private long leashHolderBedrockId = -1;
// Looks too fast and too choppy with 0.1f, which is how I believe the Microsoftian client handles it // Looks too fast and too choppy with 0.1f, which is how I believe the Microsoftian client handles it
private final float ROWING_SPEED = 0.1f; private final float ROWING_SPEED = 0.1f;
public BoatEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) { public BoatEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, BoatVariant variant) {
// Initial rotation is incorrect // Initial rotation is incorrect
super(session, entityId, geyserId, uuid, definition, position.add(0d, definition.offset(), 0d), motion, yaw + 90, 0, yaw + 90); super(session, entityId, geyserId, uuid, definition, position.add(0d, definition.offset(), 0d), motion, yaw + 90, 0, yaw + 90);
this.variant = variant;
dirtyMetadata.put(EntityDataTypes.VARIANT, variant.ordinal());
// Required to be able to move on land 1.16.200+ or apply gravity not in the water 1.16.100+ // Required to be able to move on land 1.16.200+ or apply gravity not in the water 1.16.100+
dirtyMetadata.put(EntityDataTypes.IS_BUOYANT, true); dirtyMetadata.put(EntityDataTypes.IS_BUOYANT, true);
@ -124,15 +129,6 @@ public class BoatEntity extends Entity implements Leashable, Tickable {
moveRelative(0, 0, 0, yaw + 90, 0, 0, isOnGround); moveRelative(0, 0, 0, yaw + 90, 0, 0, isOnGround);
} }
public void setVariant(IntEntityMetadata entityMetadata) {
variant = entityMetadata.getPrimitiveValue();
dirtyMetadata.put(EntityDataTypes.VARIANT, switch (variant) {
case 6, 7, 8 -> variant - 1; // dark_oak, mangrove, bamboo
case 5 -> 8; // cherry
default -> variant;
});
}
public void setPaddlingLeft(BooleanEntityMetadata entityMetadata) { public void setPaddlingLeft(BooleanEntityMetadata entityMetadata) {
isPaddlingLeft = entityMetadata.getPrimitiveValue(); isPaddlingLeft = entityMetadata.getPrimitiveValue();
if (!isPaddlingLeft) { if (!isPaddlingLeft) {
@ -187,6 +183,12 @@ public class BoatEntity extends Entity implements Leashable, Tickable {
@Override @Override
public void tick() { public void tick() {
// Java sends simply "true" and "false" (is_paddling_left), Bedrock keeps sending packets as you're rowing // Java sends simply "true" and "false" (is_paddling_left), Bedrock keeps sending packets as you're rowing
if (session.getPlayerEntity().getVehicle() == this) {
// For packet timing accuracy, we'll send the packets here, as that's what Java Edition 1.21.3 does.
ServerboundPaddleBoatPacket steerPacket = new ServerboundPaddleBoatPacket(session.isSteeringLeft(), session.isSteeringRight());
session.sendDownstreamGamePacket(steerPacket);
return;
}
doTick = !doTick; // Run every 100 ms doTick = !doTick; // Run every 100 ms
if (!doTick || passengers.isEmpty()) { if (!doTick || passengers.isEmpty()) {
return; return;
@ -212,6 +214,10 @@ public class BoatEntity extends Entity implements Leashable, Tickable {
return leashHolderBedrockId; return leashHolderBedrockId;
} }
public Item getPickItem() {
return variant.pickItem;
}
private void sendAnimationPacket(GeyserSession session, Entity rower, AnimatePacket.Action action, float rowTime) { private void sendAnimationPacket(GeyserSession session, Entity rower, AnimatePacket.Action action, float rowTime) {
AnimatePacket packet = new AnimatePacket(); AnimatePacket packet = new AnimatePacket();
packet.setRuntimeEntityId(rower.getGeyserId()); packet.setRuntimeEntityId(rower.getGeyserId());
@ -219,4 +225,27 @@ public class BoatEntity extends Entity implements Leashable, Tickable {
packet.setRowingTime(rowTime); packet.setRowingTime(rowTime);
session.sendUpstreamPacket(packet); session.sendUpstreamPacket(packet);
} }
/**
* Ordered by Bedrock ordinal
*/
public enum BoatVariant {
OAK(Items.OAK_BOAT, Items.OAK_CHEST_BOAT),
SPRUCE(Items.SPRUCE_BOAT, Items.SPRUCE_CHEST_BOAT),
BIRCH(Items.BIRCH_BOAT, Items.BIRCH_CHEST_BOAT),
JUNGLE(Items.JUNGLE_BOAT, Items.JUNGLE_CHEST_BOAT),
ACACIA(Items.ACACIA_BOAT, Items.ACACIA_CHEST_BOAT),
DARK_OAK(Items.DARK_OAK_BOAT, Items.DARK_OAK_CHEST_BOAT),
MANGROVE(Items.MANGROVE_BOAT, Items.MANGROVE_CHEST_BOAT),
BAMBOO(Items.BAMBOO_RAFT, Items.BAMBOO_CHEST_RAFT),
CHERRY(Items.CHERRY_BOAT, Items.CHERRY_CHEST_BOAT);
private final Item pickItem;
final Item chestPickItem;
BoatVariant(Item pickItem, Item chestPickItem) {
this.pickItem = pickItem;
this.chestPickItem = chestPickItem;
}
}
} }

Datei anzeigen

@ -27,6 +27,7 @@ package org.geysermc.geyser.entity.type;
import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.math.vector.Vector3f;
import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.item.type.Item;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.util.InteractionResult; import org.geysermc.geyser.util.InteractionResult;
import org.geysermc.geyser.util.InteractiveTag; import org.geysermc.geyser.util.InteractiveTag;
@ -35,8 +36,8 @@ import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand;
import java.util.UUID; import java.util.UUID;
public class ChestBoatEntity extends BoatEntity { public class ChestBoatEntity extends BoatEntity {
public ChestBoatEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) { public ChestBoatEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, BoatVariant variant) {
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw); super(session, entityId, geyserId, uuid, definition, position, motion, yaw, variant);
} }
@Override @Override
@ -48,4 +49,9 @@ public class ChestBoatEntity extends BoatEntity {
public InteractionResult interact(Hand hand) { public InteractionResult interact(Hand hand) {
return passengers.isEmpty() && !session.isSneaking() ? super.interact(hand) : InteractionResult.SUCCESS; return passengers.isEmpty() && !session.isSneaking() ? super.interact(hand) : InteractionResult.SUCCESS;
} }
@Override
public Item getPickItem() {
return this.variant.chestPickItem;
}
} }

Datei anzeigen

@ -35,12 +35,18 @@ import org.cloudburstmc.math.vector.Vector3f;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityEventType; import org.cloudburstmc.protocol.bedrock.data.entity.EntityEventType;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
import org.cloudburstmc.protocol.bedrock.packet.*; import org.cloudburstmc.protocol.bedrock.packet.AddEntityPacket;
import org.cloudburstmc.protocol.bedrock.packet.EntityEventPacket;
import org.cloudburstmc.protocol.bedrock.packet.MoveEntityAbsolutePacket;
import org.cloudburstmc.protocol.bedrock.packet.MoveEntityDeltaPacket;
import org.cloudburstmc.protocol.bedrock.packet.RemoveEntityPacket;
import org.cloudburstmc.protocol.bedrock.packet.SetEntityDataPacket;
import org.geysermc.geyser.api.entity.type.GeyserEntity; import org.geysermc.geyser.api.entity.type.GeyserEntity;
import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.entity.GeyserDirtyMetadata; import org.geysermc.geyser.entity.GeyserDirtyMetadata;
import org.geysermc.geyser.entity.properties.GeyserEntityPropertyManager; import org.geysermc.geyser.entity.properties.GeyserEntityPropertyManager;
import org.geysermc.geyser.item.Items; import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.scoreboard.Team;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.text.MessageTranslator; import org.geysermc.geyser.translator.text.MessageTranslator;
import org.geysermc.geyser.util.EntityUtils; import org.geysermc.geyser.util.EntityUtils;
@ -55,12 +61,16 @@ import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.IntEnt
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand; import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand;
import org.geysermc.mcprotocollib.protocol.data.game.entity.type.EntityType; import org.geysermc.mcprotocollib.protocol.data.game.entity.type.EntityType;
import java.util.*; import java.util.Collections;
import java.util.EnumSet;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.UUID;
@Getter @Getter
@Setter @Setter
public class Entity implements GeyserEntity { public class Entity implements GeyserEntity {
private static final boolean PRINT_ENTITY_SPAWN_DEBUG = Boolean.parseBoolean(System.getProperty("Geyser.PrintEntitySpawnDebug", "false")); private static final boolean PRINT_ENTITY_SPAWN_DEBUG = Boolean.parseBoolean(System.getProperty("Geyser.PrintEntitySpawnDebug", "false"));
protected final GeyserSession session; protected final GeyserSession session;
@ -68,12 +78,19 @@ public class Entity implements GeyserEntity {
protected int entityId; protected int entityId;
protected final long geyserId; protected final long geyserId;
protected UUID uuid; protected UUID uuid;
/**
* Do not call this setter directly!
* This will bypass the scoreboard and setting the metadata
*/
@Setter(AccessLevel.NONE)
protected String nametag = "";
protected Vector3f position; protected Vector3f position;
protected Vector3f motion; protected Vector3f motion;
/** /**
* x = Yaw, y = Pitch, z = HeadYaw * x = Yaw, y = Pitch, z = HeadYaw
* Java: Y = Yaw, X = Pitch
*/ */
protected float yaw; protected float yaw;
protected float pitch; protected float pitch;
@ -97,7 +114,7 @@ public class Entity implements GeyserEntity {
@Setter(AccessLevel.NONE) @Setter(AccessLevel.NONE)
private float boundingBoxWidth; private float boundingBoxWidth;
@Setter(AccessLevel.NONE) @Setter(AccessLevel.NONE)
protected String nametag = ""; private String displayName;
@Setter(AccessLevel.NONE) @Setter(AccessLevel.NONE)
protected boolean silent = false; protected boolean silent = false;
/* Metadata end */ /* Metadata end */
@ -126,11 +143,12 @@ public class Entity implements GeyserEntity {
public Entity(GeyserSession session, int entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) { public Entity(GeyserSession session, int entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
this.session = session; this.session = session;
this.definition = definition;
this.displayName = standardDisplayName();
this.entityId = entityId; this.entityId = entityId;
this.geyserId = geyserId; this.geyserId = geyserId;
this.uuid = uuid; this.uuid = uuid;
this.definition = definition;
this.motion = motion; this.motion = motion;
this.yaw = yaw; this.yaw = yaw;
this.pitch = pitch; this.pitch = pitch;
@ -341,7 +359,7 @@ public class Entity implements GeyserEntity {
* Sends the Bedrock metadata to the client * Sends the Bedrock metadata to the client
*/ */
public void updateBedrockMetadata() { public void updateBedrockMetadata() {
if (!valid) { if (!isValid()) {
return; return;
} }
@ -410,17 +428,84 @@ public class Entity implements GeyserEntity {
return 300; return 300;
} }
public String teamIdentifier() {
// experience orbs are the only known entities that do not send an uuid (even though they do have one),
// but to be safe in the future it's done in the entity class itself instead of the entity specific one.
// All entities without an uuid cannot show up in the scoreboard!
return uuid != null ? uuid.toString() : null;
}
public void setDisplayName(EntityMetadata<Optional<Component>, ?> entityMetadata) { public void setDisplayName(EntityMetadata<Optional<Component>, ?> entityMetadata) {
// displayName is shown when always display name is enabled. Either with or without team.
// That's why there are both a displayName and a nametag variable.
// Displayname is ignored for players, and is always their username.
Optional<Component> name = entityMetadata.getValue(); Optional<Component> name = entityMetadata.getValue();
if (name.isPresent()) { if (name.isPresent()) {
nametag = MessageTranslator.convertMessage(name.get(), session.locale()); String displayName = MessageTranslator.convertMessage(name.get(), session.locale());
dirtyMetadata.put(EntityDataTypes.NAME, nametag); this.displayName = displayName;
} else if (!nametag.isEmpty()) { setNametag(displayName, true);
// Clear nametag return;
dirtyMetadata.put(EntityDataTypes.NAME, "");
} }
// if no displayName is set, use entity name (ENDER_DRAGON -> Ender Dragon)
// maybe we can/should use a translatable here instead?
this.displayName = standardDisplayName();
setNametag(null, true);
} }
protected String standardDisplayName() {
return EntityUtils.translatedEntityName(definition.entityType(), session);
}
protected void setNametag(@Nullable String nametag, boolean fromDisplayName) {
// ensure that the team format is used when nametag changes
if (nametag != null && fromDisplayName) {
var team = session.getWorldCache().getScoreboard().getTeamFor(teamIdentifier());
if (team != null) {
updateNametag(team);
return;
}
}
if (nametag == null) {
nametag = "";
}
boolean changed = !Objects.equals(this.nametag, nametag);
this.nametag = nametag;
// we only update metadata if the value has changed
if (!changed) {
return;
}
dirtyMetadata.put(EntityDataTypes.NAME, nametag);
// if nametag (player with team) is hidden for player, so should the score (belowname)
scoreVisibility(!nametag.isEmpty());
}
public void updateNametag(@Nullable Team team) {
// allow LivingEntity+ to have a different visibility check
updateNametag(team, true);
}
protected void updateNametag(@Nullable Team team, boolean visible) {
if (team != null) {
String newNametag;
// (team) visibility is LivingEntity+, team displayName is Entity+
if (visible) {
newNametag = team.displayName(getDisplayName());
} else {
// The name is not visible to the session player; clear name
newNametag = "";
}
setNametag(newNametag, false);
return;
}
// The name has reset, if it was previously something else
setNametag(null, false);
}
protected void scoreVisibility(boolean show) {}
public void setDisplayNameVisible(BooleanEntityMetadata entityMetadata) { public void setDisplayNameVisible(BooleanEntityMetadata entityMetadata) {
dirtyMetadata.put(EntityDataTypes.NAMETAG_ALWAYS_SHOW, (byte) (entityMetadata.getPrimitiveValue() ? 1 : 0)); dirtyMetadata.put(EntityDataTypes.NAMETAG_ALWAYS_SHOW, (byte) (entityMetadata.getPrimitiveValue() ? 1 : 0));
} }
@ -616,9 +701,4 @@ public class Entity implements GeyserEntity {
packet.setData(data); packet.setData(data);
session.sendUpstreamPacket(packet); session.sendUpstreamPacket(packet);
} }
@SuppressWarnings("unchecked")
public <I extends Entity> @Nullable I as(Class<I> entityClass) {
return entityClass.isInstance(this) ? (I) this : null;
}
} }

Datei anzeigen

@ -45,6 +45,7 @@ import org.geysermc.geyser.entity.vehicle.ClientVehicle;
import org.geysermc.geyser.inventory.GeyserItemStack; import org.geysermc.geyser.inventory.GeyserItemStack;
import org.geysermc.geyser.item.Items; import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.scoreboard.Team;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.item.ItemTranslator; import org.geysermc.geyser.translator.item.ItemTranslator;
import org.geysermc.geyser.util.AttributeUtils; import org.geysermc.geyser.util.AttributeUtils;
@ -65,12 +66,15 @@ import org.geysermc.mcprotocollib.protocol.data.game.level.particle.EntityEffect
import org.geysermc.mcprotocollib.protocol.data.game.level.particle.Particle; import org.geysermc.mcprotocollib.protocol.data.game.level.particle.Particle;
import org.geysermc.mcprotocollib.protocol.data.game.level.particle.ParticleType; import org.geysermc.mcprotocollib.protocol.data.game.level.particle.ParticleType;
import java.util.*; import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
@Getter @Getter
@Setter @Setter
public class LivingEntity extends Entity { public class LivingEntity extends Entity {
protected ItemData helmet = ItemData.AIR; protected ItemData helmet = ItemData.AIR;
protected ItemData chestplate = ItemData.AIR; protected ItemData chestplate = ItemData.AIR;
protected ItemData leggings = ItemData.AIR; protected ItemData leggings = ItemData.AIR;
@ -150,6 +154,16 @@ public class LivingEntity extends Entity {
dirtyMetadata.put(EntityDataTypes.STRUCTURAL_INTEGRITY, 1); dirtyMetadata.put(EntityDataTypes.STRUCTURAL_INTEGRITY, 1);
} }
@Override
public void updateNametag(@Nullable Team team) {
// if name not visible, don't mark it as visible
updateNametag(team, team == null || team.isVisibleFor(session.getPlayerEntity().getUsername()));
}
public void hideNametag() {
setNametag("", false);
}
public void setLivingEntityFlags(ByteEntityMetadata entityMetadata) { public void setLivingEntityFlags(ByteEntityMetadata entityMetadata) {
byte xd = entityMetadata.getPrimitiveValue(); byte xd = entityMetadata.getPrimitiveValue();
@ -432,35 +446,35 @@ public class LivingEntity extends Entity {
protected void updateAttribute(Attribute javaAttribute, List<AttributeData> newAttributes) { protected void updateAttribute(Attribute javaAttribute, List<AttributeData> newAttributes) {
if (javaAttribute.getType() instanceof AttributeType.Builtin type) { if (javaAttribute.getType() instanceof AttributeType.Builtin type) {
switch (type) { switch (type) {
case GENERIC_MAX_HEALTH -> { case MAX_HEALTH -> {
// Since 1.18.0, setting the max health to 0 or below causes the entity to die on Bedrock but not on Java // Since 1.18.0, setting the max health to 0 or below causes the entity to die on Bedrock but not on Java
// See https://github.com/GeyserMC/Geyser/issues/2971 // See https://github.com/GeyserMC/Geyser/issues/2971
this.maxHealth = Math.max((float) AttributeUtils.calculateValue(javaAttribute), 1f); this.maxHealth = Math.max((float) AttributeUtils.calculateValue(javaAttribute), 1f);
newAttributes.add(createHealthAttribute()); newAttributes.add(createHealthAttribute());
} }
case GENERIC_MOVEMENT_SPEED -> { case MOVEMENT_SPEED -> {
AttributeData attributeData = calculateAttribute(javaAttribute, GeyserAttributeType.MOVEMENT_SPEED); AttributeData attributeData = calculateAttribute(javaAttribute, GeyserAttributeType.MOVEMENT_SPEED);
newAttributes.add(attributeData); newAttributes.add(attributeData);
if (this instanceof ClientVehicle clientVehicle) { if (this instanceof ClientVehicle clientVehicle) {
clientVehicle.getVehicleComponent().setMoveSpeed(attributeData.getValue()); clientVehicle.getVehicleComponent().setMoveSpeed(attributeData.getValue());
} }
} }
case GENERIC_STEP_HEIGHT -> { case STEP_HEIGHT -> {
if (this instanceof ClientVehicle clientVehicle) { if (this instanceof ClientVehicle clientVehicle) {
clientVehicle.getVehicleComponent().setStepHeight((float) AttributeUtils.calculateValue(javaAttribute)); clientVehicle.getVehicleComponent().setStepHeight((float) AttributeUtils.calculateValue(javaAttribute));
} }
} }
case GENERIC_GRAVITY -> { case GRAVITY -> {
if (this instanceof ClientVehicle clientVehicle) { if (this instanceof ClientVehicle clientVehicle) {
clientVehicle.getVehicleComponent().setGravity(AttributeUtils.calculateValue(javaAttribute)); clientVehicle.getVehicleComponent().setGravity(AttributeUtils.calculateValue(javaAttribute));
} }
} }
case GENERIC_ATTACK_DAMAGE -> newAttributes.add(calculateAttribute(javaAttribute, GeyserAttributeType.ATTACK_DAMAGE)); case ATTACK_DAMAGE -> newAttributes.add(calculateAttribute(javaAttribute, GeyserAttributeType.ATTACK_DAMAGE));
case GENERIC_FLYING_SPEED -> newAttributes.add(calculateAttribute(javaAttribute, GeyserAttributeType.FLYING_SPEED)); case FLYING_SPEED -> newAttributes.add(calculateAttribute(javaAttribute, GeyserAttributeType.FLYING_SPEED));
case GENERIC_FOLLOW_RANGE -> newAttributes.add(calculateAttribute(javaAttribute, GeyserAttributeType.FOLLOW_RANGE)); case FOLLOW_RANGE -> newAttributes.add(calculateAttribute(javaAttribute, GeyserAttributeType.FOLLOW_RANGE));
case GENERIC_KNOCKBACK_RESISTANCE -> newAttributes.add(calculateAttribute(javaAttribute, GeyserAttributeType.KNOCKBACK_RESISTANCE)); case KNOCKBACK_RESISTANCE -> newAttributes.add(calculateAttribute(javaAttribute, GeyserAttributeType.KNOCKBACK_RESISTANCE));
case GENERIC_JUMP_STRENGTH -> newAttributes.add(calculateAttribute(javaAttribute, GeyserAttributeType.HORSE_JUMP_STRENGTH)); case JUMP_STRENGTH -> newAttributes.add(calculateAttribute(javaAttribute, GeyserAttributeType.HORSE_JUMP_STRENGTH));
case GENERIC_SCALE -> { case SCALE -> {
// Attribute on Java, entity data on Bedrock // Attribute on Java, entity data on Bedrock
setAttributeScale((float) AttributeUtils.calculateValue(javaAttribute)); setAttributeScale((float) AttributeUtils.calculateValue(javaAttribute));
updateBedrockMetadata(); updateBedrockMetadata();

Datei anzeigen

@ -0,0 +1,43 @@
/*
* Copyright (c) 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.entity.type.living;
import org.cloudburstmc.math.vector.Vector3f;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.session.GeyserSession;
import java.util.UUID;
public abstract class AgeableWaterEntity extends AgeableEntity {
public AgeableWaterEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
}
@Override
public boolean canBeLeashed() {
return false;
}
}

Datei anzeigen

@ -27,6 +27,7 @@ package org.geysermc.geyser.entity.type.living;
import lombok.Getter; import lombok.Getter;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.math.vector.Vector3f;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataType; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataType;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
@ -36,6 +37,7 @@ import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.entity.EntityDefinitions; import org.geysermc.geyser.entity.EntityDefinitions;
import org.geysermc.geyser.entity.type.LivingEntity; import org.geysermc.geyser.entity.type.LivingEntity;
import org.geysermc.geyser.item.Items; import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.scoreboard.Team;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.util.InteractionResult; import org.geysermc.geyser.util.InteractionResult;
import org.geysermc.geyser.util.MathUtils; import org.geysermc.geyser.util.MathUtils;
@ -123,6 +125,12 @@ public class ArmorStandEntity extends LivingEntity {
this.position = position; this.position = position;
} }
@Override
public void updateNametag(@Nullable Team team) {
// unlike all other LivingEntities, armor stands are not affected by team nametag visibility
super.updateNametag(team, true);
}
@Override @Override
public void setDisplayName(EntityMetadata<Optional<Component>, ?> entityMetadata) { public void setDisplayName(EntityMetadata<Optional<Component>, ?> entityMetadata) {
super.setDisplayName(entityMetadata); super.setDisplayName(entityMetadata);

Datei anzeigen

@ -37,7 +37,7 @@ import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand;
import java.util.UUID; import java.util.UUID;
public class DolphinEntity extends WaterEntity { public class DolphinEntity extends AgeableWaterEntity {
public DolphinEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) { public DolphinEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw); super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
} }

Datei anzeigen

@ -36,7 +36,7 @@ import org.geysermc.geyser.session.GeyserSession;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
public class SquidEntity extends WaterEntity implements Tickable { public class SquidEntity extends AgeableWaterEntity implements Tickable {
private float targetPitch; private float targetPitch;
private float targetYaw; private float targetYaw;

Datei anzeigen

@ -33,8 +33,9 @@ import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.entity.type.living.AgeableEntity; import org.geysermc.geyser.entity.type.living.AgeableEntity;
import org.geysermc.geyser.inventory.GeyserItemStack; import org.geysermc.geyser.inventory.GeyserItemStack;
import org.geysermc.geyser.item.type.Item;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.session.cache.tags.ItemTag; import org.geysermc.geyser.session.cache.tags.Tag;
import org.geysermc.geyser.util.InteractionResult; import org.geysermc.geyser.util.InteractionResult;
import org.geysermc.geyser.util.InteractiveTag; import org.geysermc.geyser.util.InteractiveTag;
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand; import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand;
@ -48,7 +49,7 @@ public abstract class AnimalEntity extends AgeableEntity {
} }
protected final boolean canEat(GeyserItemStack itemStack) { protected final boolean canEat(GeyserItemStack itemStack) {
ItemTag tag = getFoodTag(); Tag<Item> tag = getFoodTag();
if (tag == null) { if (tag == null) {
return false; return false;
} }
@ -58,7 +59,7 @@ public abstract class AnimalEntity extends AgeableEntity {
/** /**
* @return the tag associated with this animal for eating food. Null for nothing or different behavior. * @return the tag associated with this animal for eating food. Null for nothing or different behavior.
*/ */
protected abstract @Nullable ItemTag getFoodTag(); protected abstract @Nullable Tag<Item> getFoodTag();
@NonNull @NonNull
@Override @Override

Datei anzeigen

@ -28,8 +28,10 @@ package org.geysermc.geyser.entity.type.living.animal;
import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.Nullable;
import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.math.vector.Vector3f;
import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.item.type.Item;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.session.cache.tags.ItemTag; import org.geysermc.geyser.session.cache.tags.ItemTag;
import org.geysermc.geyser.session.cache.tags.Tag;
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.ArmadilloState; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.ArmadilloState;
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.ObjectEntityMetadata; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.ObjectEntityMetadata;
@ -75,7 +77,7 @@ public class ArmadilloEntity extends AnimalEntity {
@Override @Override
@Nullable @Nullable
protected ItemTag getFoodTag() { protected Tag<Item> getFoodTag() {
return ItemTag.ARMADILLO_FOOD; return ItemTag.ARMADILLO_FOOD;
} }
} }

Datei anzeigen

@ -32,8 +32,10 @@ import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.inventory.GeyserItemStack; import org.geysermc.geyser.inventory.GeyserItemStack;
import org.geysermc.geyser.item.type.Item;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.session.cache.tags.ItemTag; import org.geysermc.geyser.session.cache.tags.ItemTag;
import org.geysermc.geyser.session.cache.tags.Tag;
import org.geysermc.geyser.util.EntityUtils; import org.geysermc.geyser.util.EntityUtils;
import org.geysermc.geyser.util.InteractionResult; import org.geysermc.geyser.util.InteractionResult;
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.BooleanEntityMetadata;
@ -62,7 +64,7 @@ public class AxolotlEntity extends AnimalEntity {
@Override @Override
@Nullable @Nullable
protected ItemTag getFoodTag() { protected Tag<Item> getFoodTag() {
return ItemTag.AXOLOTL_FOOD; return ItemTag.AXOLOTL_FOOD;
} }

Datei anzeigen

@ -32,8 +32,10 @@ import org.cloudburstmc.protocol.bedrock.data.entity.EntityEventType;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
import org.cloudburstmc.protocol.bedrock.packet.EntityEventPacket; import org.cloudburstmc.protocol.bedrock.packet.EntityEventPacket;
import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.item.type.Item;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.session.cache.tags.ItemTag; import org.geysermc.geyser.session.cache.tags.ItemTag;
import org.geysermc.geyser.session.cache.tags.Tag;
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.ByteEntityMetadata; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.ByteEntityMetadata;
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.IntEntityMetadata; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.IntEntityMetadata;
@ -69,7 +71,7 @@ public class BeeEntity extends AnimalEntity {
@Override @Override
@Nullable @Nullable
protected ItemTag getFoodTag() { protected Tag<Item> getFoodTag() {
return ItemTag.BEE_FOOD; return ItemTag.BEE_FOOD;
} }
} }

Datei anzeigen

@ -28,8 +28,10 @@ package org.geysermc.geyser.entity.type.living.animal;
import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.Nullable;
import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.math.vector.Vector3f;
import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.item.type.Item;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.session.cache.tags.ItemTag; import org.geysermc.geyser.session.cache.tags.ItemTag;
import org.geysermc.geyser.session.cache.tags.Tag;
import java.util.UUID; import java.util.UUID;
@ -41,7 +43,7 @@ public class ChickenEntity extends AnimalEntity {
@Override @Override
@Nullable @Nullable
protected ItemTag getFoodTag() { protected Tag<Item> getFoodTag() {
return ItemTag.CHICKEN_FOOD; return ItemTag.CHICKEN_FOOD;
} }
} }

Datei anzeigen

@ -33,8 +33,10 @@ import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.inventory.GeyserItemStack; import org.geysermc.geyser.inventory.GeyserItemStack;
import org.geysermc.geyser.item.Items; import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.item.type.Item;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.session.cache.tags.ItemTag; import org.geysermc.geyser.session.cache.tags.ItemTag;
import org.geysermc.geyser.session.cache.tags.Tag;
import org.geysermc.geyser.util.InteractionResult; import org.geysermc.geyser.util.InteractionResult;
import org.geysermc.geyser.util.InteractiveTag; import org.geysermc.geyser.util.InteractiveTag;
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand; import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand;
@ -69,7 +71,7 @@ public class CowEntity extends AnimalEntity {
@Override @Override
@Nullable @Nullable
protected ItemTag getFoodTag() { protected Tag<Item> getFoodTag() {
return ItemTag.COW_FOOD; return ItemTag.COW_FOOD;
} }
} }

Datei anzeigen

@ -30,8 +30,10 @@ import org.cloudburstmc.math.vector.Vector3f;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.item.type.Item;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.session.cache.tags.ItemTag; import org.geysermc.geyser.session.cache.tags.ItemTag;
import org.geysermc.geyser.session.cache.tags.Tag;
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.ByteEntityMetadata; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.ByteEntityMetadata;
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.IntEntityMetadata; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.IntEntityMetadata;
@ -57,7 +59,7 @@ public class FoxEntity extends AnimalEntity {
@Override @Override
@Nullable @Nullable
protected ItemTag getFoodTag() { protected Tag<Item> getFoodTag() {
return ItemTag.FOX_FOOD; return ItemTag.FOX_FOOD;
} }
} }

Datei anzeigen

@ -31,8 +31,10 @@ import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.entity.type.Entity; import org.geysermc.geyser.entity.type.Entity;
import org.geysermc.geyser.item.type.Item;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.session.cache.tags.ItemTag; import org.geysermc.geyser.session.cache.tags.ItemTag;
import org.geysermc.geyser.session.cache.tags.Tag;
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.Pose; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.Pose;
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.IntEntityMetadata; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.IntEntityMetadata;
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.ObjectEntityMetadata; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.ObjectEntityMetadata;
@ -77,7 +79,7 @@ public class FrogEntity extends AnimalEntity {
@Override @Override
@Nullable @Nullable
protected ItemTag getFoodTag() { protected Tag<Item> getFoodTag() {
return ItemTag.FROG_FOOD; return ItemTag.FROG_FOOD;
} }
} }

Datei anzeigen

@ -34,8 +34,10 @@ import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.inventory.GeyserItemStack; import org.geysermc.geyser.inventory.GeyserItemStack;
import org.geysermc.geyser.item.Items; import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.item.type.Item;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.session.cache.tags.ItemTag; import org.geysermc.geyser.session.cache.tags.ItemTag;
import org.geysermc.geyser.session.cache.tags.Tag;
import org.geysermc.geyser.util.InteractionResult; import org.geysermc.geyser.util.InteractionResult;
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.Pose; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.Pose;
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.BooleanEntityMetadata;
@ -99,7 +101,7 @@ public class GoatEntity extends AnimalEntity {
@Override @Override
@Nullable @Nullable
protected ItemTag getFoodTag() { protected Tag<Item> getFoodTag() {
return ItemTag.GOAT_FOOD; return ItemTag.GOAT_FOOD;
} }
} }

Datei anzeigen

@ -30,8 +30,10 @@ import org.cloudburstmc.math.vector.Vector3f;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.item.type.Item;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.session.cache.tags.ItemTag; import org.geysermc.geyser.session.cache.tags.ItemTag;
import org.geysermc.geyser.session.cache.tags.Tag;
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.BooleanEntityMetadata;
import java.util.UUID; import java.util.UUID;
@ -58,7 +60,7 @@ public class HoglinEntity extends AnimalEntity {
@Override @Override
@Nullable @Nullable
protected ItemTag getFoodTag() { protected Tag<Item> getFoodTag() {
return ItemTag.HOGLIN_FOOD; return ItemTag.HOGLIN_FOOD;
} }

Datei anzeigen

@ -31,8 +31,10 @@ import org.cloudburstmc.math.vector.Vector3f;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.inventory.GeyserItemStack; import org.geysermc.geyser.inventory.GeyserItemStack;
import org.geysermc.geyser.item.type.Item;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.session.cache.tags.ItemTag; import org.geysermc.geyser.session.cache.tags.ItemTag;
import org.geysermc.geyser.session.cache.tags.Tag;
import org.geysermc.geyser.util.InteractionResult; import org.geysermc.geyser.util.InteractionResult;
import org.geysermc.geyser.util.InteractiveTag; import org.geysermc.geyser.util.InteractiveTag;
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand; import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand;
@ -47,7 +49,7 @@ public class OcelotEntity extends AnimalEntity {
@Override @Override
@Nullable @Nullable
protected ItemTag getFoodTag() { protected Tag<Item> getFoodTag() {
return ItemTag.OCELOT_FOOD; return ItemTag.OCELOT_FOOD;
} }

Datei anzeigen

@ -34,8 +34,10 @@ import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
import org.cloudburstmc.protocol.bedrock.packet.EntityEventPacket; import org.cloudburstmc.protocol.bedrock.packet.EntityEventPacket;
import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.inventory.GeyserItemStack; import org.geysermc.geyser.inventory.GeyserItemStack;
import org.geysermc.geyser.item.type.Item;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.session.cache.tags.ItemTag; import org.geysermc.geyser.session.cache.tags.ItemTag;
import org.geysermc.geyser.session.cache.tags.Tag;
import org.geysermc.geyser.util.InteractionResult; import org.geysermc.geyser.util.InteractionResult;
import org.geysermc.geyser.util.InteractiveTag; import org.geysermc.geyser.util.InteractiveTag;
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.ByteEntityMetadata; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.ByteEntityMetadata;
@ -90,7 +92,7 @@ public class PandaEntity extends AnimalEntity {
@Override @Override
@Nullable @Nullable
protected ItemTag getFoodTag() { protected Tag<Item> getFoodTag() {
return ItemTag.PANDA_FOOD; return ItemTag.PANDA_FOOD;
} }

Datei anzeigen

@ -38,9 +38,11 @@ import org.geysermc.geyser.entity.vehicle.BoostableVehicleComponent;
import org.geysermc.geyser.entity.vehicle.ClientVehicle; import org.geysermc.geyser.entity.vehicle.ClientVehicle;
import org.geysermc.geyser.entity.vehicle.VehicleComponent; import org.geysermc.geyser.entity.vehicle.VehicleComponent;
import org.geysermc.geyser.inventory.GeyserItemStack; import org.geysermc.geyser.inventory.GeyserItemStack;
import org.geysermc.geyser.item.type.Item;
import org.geysermc.geyser.item.Items; import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.session.cache.tags.ItemTag; import org.geysermc.geyser.session.cache.tags.ItemTag;
import org.geysermc.geyser.session.cache.tags.Tag;
import org.geysermc.geyser.util.EntityUtils; import org.geysermc.geyser.util.EntityUtils;
import org.geysermc.geyser.util.InteractionResult; import org.geysermc.geyser.util.InteractionResult;
import org.geysermc.geyser.util.InteractiveTag; import org.geysermc.geyser.util.InteractiveTag;
@ -58,7 +60,7 @@ public class PigEntity extends AnimalEntity implements Tickable, ClientVehicle {
@Override @Override
@Nullable @Nullable
protected ItemTag getFoodTag() { protected Tag<Item> getFoodTag() {
return ItemTag.PIG_FOOD; return ItemTag.PIG_FOOD;
} }

Datei anzeigen

@ -28,8 +28,9 @@ package org.geysermc.geyser.entity.type.living.animal;
import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.Nullable;
import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.math.vector.Vector3f;
import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.item.type.Item;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.session.cache.tags.ItemTag; import org.geysermc.geyser.session.cache.tags.Tag;
import java.util.UUID; import java.util.UUID;
@ -41,7 +42,7 @@ public class PolarBearEntity extends AnimalEntity {
@Override @Override
@Nullable @Nullable
protected ItemTag getFoodTag() { protected Tag<Item> getFoodTag() {
return null; return null;
} }
} }

Datei anzeigen

@ -25,18 +25,23 @@
package org.geysermc.geyser.entity.type.living.animal; package org.geysermc.geyser.entity.type.living.animal;
import net.kyori.adventure.key.Key;
import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.Nullable;
import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.math.vector.Vector3f;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.item.type.Item;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.session.cache.tags.ItemTag; import org.geysermc.geyser.session.cache.tags.ItemTag;
import org.geysermc.geyser.session.cache.tags.Tag;
import org.geysermc.geyser.util.EntityUtils;
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.IntEntityMetadata; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.IntEntityMetadata;
import java.util.UUID; import java.util.UUID;
public class RabbitEntity extends AnimalEntity { public class RabbitEntity extends AnimalEntity {
private boolean isKillerBunny;
public RabbitEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) { public RabbitEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw); super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
@ -46,7 +51,7 @@ public class RabbitEntity extends AnimalEntity {
int variant = entityMetadata.getPrimitiveValue(); int variant = entityMetadata.getPrimitiveValue();
// Change the killer bunny to display as white since it only exists on Java Edition // Change the killer bunny to display as white since it only exists on Java Edition
boolean isKillerBunny = variant == 99; isKillerBunny = variant == 99;
if (isKillerBunny) { if (isKillerBunny) {
variant = 1; variant = 1;
} }
@ -56,6 +61,14 @@ public class RabbitEntity extends AnimalEntity {
dirtyMetadata.put(EntityDataTypes.VARIANT, variant); dirtyMetadata.put(EntityDataTypes.VARIANT, variant);
} }
@Override
protected String standardDisplayName() {
if (isKillerBunny) {
return EntityUtils.translatedEntityName(Key.key("killer_bunny"), session);
}
return super.standardDisplayName();
}
@Override @Override
protected float getAdultSize() { protected float getAdultSize() {
return 0.55f; return 0.55f;
@ -68,7 +81,7 @@ public class RabbitEntity extends AnimalEntity {
@Override @Override
@Nullable @Nullable
protected ItemTag getFoodTag() { protected Tag<Item> getFoodTag() {
return ItemTag.RABBIT_FOOD; return ItemTag.RABBIT_FOOD;
} }
} }

Datei anzeigen

@ -34,8 +34,10 @@ import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.inventory.GeyserItemStack; import org.geysermc.geyser.inventory.GeyserItemStack;
import org.geysermc.geyser.item.Items; import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.item.type.DyeItem; import org.geysermc.geyser.item.type.DyeItem;
import org.geysermc.geyser.item.type.Item;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.session.cache.tags.ItemTag; import org.geysermc.geyser.session.cache.tags.ItemTag;
import org.geysermc.geyser.session.cache.tags.Tag;
import org.geysermc.geyser.util.InteractionResult; import org.geysermc.geyser.util.InteractionResult;
import org.geysermc.geyser.util.InteractiveTag; import org.geysermc.geyser.util.InteractiveTag;
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.ByteEntityMetadata; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.ByteEntityMetadata;
@ -59,7 +61,7 @@ public class SheepEntity extends AnimalEntity {
@Override @Override
@Nullable @Nullable
protected ItemTag getFoodTag() { protected Tag<Item> getFoodTag() {
return ItemTag.SHEEP_FOOD; return ItemTag.SHEEP_FOOD;
} }

Datei anzeigen

@ -35,8 +35,10 @@ import org.cloudburstmc.protocol.bedrock.packet.LevelSoundEventPacket;
import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.entity.EntityDefinitions; import org.geysermc.geyser.entity.EntityDefinitions;
import org.geysermc.geyser.entity.type.Tickable; import org.geysermc.geyser.entity.type.Tickable;
import org.geysermc.geyser.item.type.Item;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.session.cache.tags.ItemTag; import org.geysermc.geyser.session.cache.tags.ItemTag;
import org.geysermc.geyser.session.cache.tags.Tag;
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.Pose; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.Pose;
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.SnifferState; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.SnifferState;
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.ObjectEntityMetadata; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.ObjectEntityMetadata;
@ -73,7 +75,7 @@ public class SnifferEntity extends AnimalEntity implements Tickable {
@Override @Override
@Nullable @Nullable
protected ItemTag getFoodTag() { protected Tag<Item> getFoodTag() {
return ItemTag.SNIFFER_FOOD; return ItemTag.SNIFFER_FOOD;
} }

Datei anzeigen

@ -39,9 +39,11 @@ import org.geysermc.geyser.entity.vehicle.BoostableVehicleComponent;
import org.geysermc.geyser.entity.vehicle.ClientVehicle; import org.geysermc.geyser.entity.vehicle.ClientVehicle;
import org.geysermc.geyser.entity.vehicle.VehicleComponent; import org.geysermc.geyser.entity.vehicle.VehicleComponent;
import org.geysermc.geyser.inventory.GeyserItemStack; import org.geysermc.geyser.inventory.GeyserItemStack;
import org.geysermc.geyser.item.type.Item;
import org.geysermc.geyser.item.Items; import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.session.cache.tags.ItemTag; import org.geysermc.geyser.session.cache.tags.ItemTag;
import org.geysermc.geyser.session.cache.tags.Tag;
import org.geysermc.geyser.util.EntityUtils; import org.geysermc.geyser.util.EntityUtils;
import org.geysermc.geyser.util.InteractionResult; import org.geysermc.geyser.util.InteractionResult;
import org.geysermc.geyser.util.InteractiveTag; import org.geysermc.geyser.util.InteractiveTag;
@ -105,7 +107,7 @@ public class StriderEntity extends AnimalEntity implements Tickable, ClientVehic
@Override @Override
@Nullable @Nullable
protected ItemTag getFoodTag() { protected Tag<Item> getFoodTag() {
return ItemTag.STRIDER_FOOD; return ItemTag.STRIDER_FOOD;
} }

Datei anzeigen

@ -29,8 +29,10 @@ import org.checkerframework.checker.nullness.qual.Nullable;
import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.math.vector.Vector3f;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.item.type.Item;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.session.cache.tags.ItemTag; import org.geysermc.geyser.session.cache.tags.ItemTag;
import org.geysermc.geyser.session.cache.tags.Tag;
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.BooleanEntityMetadata;
import java.util.UUID; import java.util.UUID;
@ -51,10 +53,21 @@ public class TurtleEntity extends AnimalEntity {
@Override @Override
@Nullable @Nullable
protected ItemTag getFoodTag() { protected Tag<Item> getFoodTag() {
return ItemTag.TURTLE_FOOD; return ItemTag.TURTLE_FOOD;
} }
@Override
protected float getAdultSize() {
return super.getAdultSize() * 0.7f;
}
@Override
protected float getBabySize() {
// 0.3f is Java scale, plus Bedrock difference
return 0.3f * 0.5f;
}
@Override @Override
public boolean canBeLeashed() { public boolean canBeLeashed() {
return false; return false;

Datei anzeigen

@ -39,8 +39,10 @@ import org.geysermc.geyser.entity.attribute.GeyserAttributeType;
import org.geysermc.geyser.entity.type.living.animal.AnimalEntity; import org.geysermc.geyser.entity.type.living.animal.AnimalEntity;
import org.geysermc.geyser.inventory.GeyserItemStack; import org.geysermc.geyser.inventory.GeyserItemStack;
import org.geysermc.geyser.item.Items; import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.item.type.Item;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.session.cache.tags.ItemTag; import org.geysermc.geyser.session.cache.tags.ItemTag;
import org.geysermc.geyser.session.cache.tags.Tag;
import org.geysermc.geyser.util.InteractionResult; import org.geysermc.geyser.util.InteractionResult;
import org.geysermc.geyser.util.InteractiveTag; import org.geysermc.geyser.util.InteractiveTag;
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.ByteEntityMetadata; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.ByteEntityMetadata;
@ -119,7 +121,7 @@ public class AbstractHorseEntity extends AnimalEntity {
@Override @Override
@Nullable @Nullable
protected ItemTag getFoodTag() { protected Tag<Item> getFoodTag() {
return ItemTag.HORSE_FOOD; return ItemTag.HORSE_FOOD;
} }

Datei anzeigen

@ -35,12 +35,14 @@ import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType; import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType;
import org.cloudburstmc.protocol.bedrock.packet.EntityEventPacket; import org.cloudburstmc.protocol.bedrock.packet.EntityEventPacket;
import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.item.type.Item;
import org.geysermc.geyser.entity.attribute.GeyserAttributeType; import org.geysermc.geyser.entity.attribute.GeyserAttributeType;
import org.geysermc.geyser.entity.vehicle.CamelVehicleComponent; import org.geysermc.geyser.entity.vehicle.CamelVehicleComponent;
import org.geysermc.geyser.entity.vehicle.ClientVehicle; import org.geysermc.geyser.entity.vehicle.ClientVehicle;
import org.geysermc.geyser.entity.vehicle.VehicleComponent; import org.geysermc.geyser.entity.vehicle.VehicleComponent;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.session.cache.tags.ItemTag; import org.geysermc.geyser.session.cache.tags.ItemTag;
import org.geysermc.geyser.session.cache.tags.Tag;
import org.geysermc.mcprotocollib.protocol.data.game.entity.attribute.Attribute; import org.geysermc.mcprotocollib.protocol.data.game.entity.attribute.Attribute;
import org.geysermc.mcprotocollib.protocol.data.game.entity.attribute.AttributeType; import org.geysermc.mcprotocollib.protocol.data.game.entity.attribute.AttributeType;
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.Pose; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.Pose;
@ -100,7 +102,7 @@ public class CamelEntity extends AbstractHorseEntity implements ClientVehicle {
} }
@Override @Override
protected @Nullable ItemTag getFoodTag() { protected @Nullable Tag<Item> getFoodTag() {
return ItemTag.CAMEL_FOOD; return ItemTag.CAMEL_FOOD;
} }
@ -141,7 +143,7 @@ public class CamelEntity extends AbstractHorseEntity implements ClientVehicle {
@Override @Override
protected AttributeData calculateAttribute(Attribute javaAttribute, GeyserAttributeType type) { protected AttributeData calculateAttribute(Attribute javaAttribute, GeyserAttributeType type) {
AttributeData attributeData = super.calculateAttribute(javaAttribute, type); AttributeData attributeData = super.calculateAttribute(javaAttribute, type);
if (javaAttribute.getType() == AttributeType.Builtin.GENERIC_JUMP_STRENGTH) { if (javaAttribute.getType() == AttributeType.Builtin.JUMP_STRENGTH) {
vehicleComponent.setHorseJumpStrength(attributeData.getValue()); vehicleComponent.setHorseJumpStrength(attributeData.getValue());
} }
return attributeData; return attributeData;

Datei anzeigen

@ -30,8 +30,10 @@ import org.checkerframework.checker.nullness.qual.Nullable;
import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.math.vector.Vector3f;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.item.type.Item;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.session.cache.tags.ItemTag; import org.geysermc.geyser.session.cache.tags.ItemTag;
import org.geysermc.geyser.session.cache.tags.Tag;
import org.geysermc.geyser.util.MathUtils; import org.geysermc.geyser.util.MathUtils;
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.IntEntityMetadata; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.IntEntityMetadata;
@ -56,7 +58,7 @@ public class LlamaEntity extends ChestedHorseEntity {
} }
@Override @Override
protected @Nullable ItemTag getFoodTag() { protected @Nullable Tag<Item> getFoodTag() {
return ItemTag.LLAMA_FOOD; return ItemTag.LLAMA_FOOD;
} }
} }

Datei anzeigen

@ -32,8 +32,10 @@ import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.inventory.GeyserItemStack; import org.geysermc.geyser.inventory.GeyserItemStack;
import org.geysermc.geyser.item.type.Item;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.session.cache.tags.ItemTag; import org.geysermc.geyser.session.cache.tags.ItemTag;
import org.geysermc.geyser.session.cache.tags.Tag;
import org.geysermc.geyser.util.InteractionResult; import org.geysermc.geyser.util.InteractionResult;
import org.geysermc.geyser.util.InteractiveTag; import org.geysermc.geyser.util.InteractiveTag;
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.BooleanEntityMetadata;
@ -109,7 +111,7 @@ public class CatEntity extends TameableEntity {
} }
@Override @Override
protected @Nullable ItemTag getFoodTag() { protected @Nullable Tag<Item> getFoodTag() {
return ItemTag.CAT_FOOD; return ItemTag.CAT_FOOD;
} }

Datei anzeigen

@ -34,6 +34,7 @@ import org.geysermc.geyser.inventory.GeyserItemStack;
import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.item.type.Item;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.session.cache.tags.ItemTag; import org.geysermc.geyser.session.cache.tags.ItemTag;
import org.geysermc.geyser.session.cache.tags.Tag;
import org.geysermc.geyser.util.InteractionResult; import org.geysermc.geyser.util.InteractionResult;
import org.geysermc.geyser.util.InteractiveTag; import org.geysermc.geyser.util.InteractiveTag;
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand; import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand;
@ -47,7 +48,7 @@ public class ParrotEntity extends TameableEntity {
@Override @Override
@Nullable @Nullable
protected ItemTag getFoodTag() { protected Tag<Item> getFoodTag() {
return null; return null;
} }

Datei anzeigen

@ -36,8 +36,10 @@ import org.geysermc.geyser.inventory.GeyserItemStack;
import org.geysermc.geyser.item.Items; import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.item.enchantment.EnchantmentComponent; import org.geysermc.geyser.item.enchantment.EnchantmentComponent;
import org.geysermc.geyser.item.type.DyeItem; import org.geysermc.geyser.item.type.DyeItem;
import org.geysermc.geyser.item.type.Item;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.session.cache.tags.ItemTag; import org.geysermc.geyser.session.cache.tags.ItemTag;
import org.geysermc.geyser.session.cache.tags.Tag;
import org.geysermc.geyser.util.InteractionResult; import org.geysermc.geyser.util.InteractionResult;
import org.geysermc.geyser.util.InteractiveTag; import org.geysermc.geyser.util.InteractiveTag;
import org.geysermc.geyser.util.ItemUtils; import org.geysermc.geyser.util.ItemUtils;
@ -116,7 +118,7 @@ public class WolfEntity extends TameableEntity {
@Override @Override
@Nullable @Nullable
protected ItemTag getFoodTag() { protected Tag<Item> getFoodTag() {
return ItemTag.WOLF_FOOD; return ItemTag.WOLF_FOOD;
} }

Datei anzeigen

@ -32,7 +32,6 @@ import org.checkerframework.checker.nullness.qual.Nullable;
import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.math.vector.Vector3f;
import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.math.vector.Vector3i;
import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMap;
import org.cloudburstmc.nbt.NbtMapBuilder;
import org.cloudburstmc.protocol.bedrock.data.Ability; import org.cloudburstmc.protocol.bedrock.data.Ability;
import org.cloudburstmc.protocol.bedrock.data.AbilityLayer; import org.cloudburstmc.protocol.bedrock.data.AbilityLayer;
import org.cloudburstmc.protocol.bedrock.data.GameType; import org.cloudburstmc.protocol.bedrock.data.GameType;
@ -44,7 +43,6 @@ import org.cloudburstmc.protocol.bedrock.data.entity.EntityLinkData;
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
import org.cloudburstmc.protocol.bedrock.packet.AddPlayerPacket; import org.cloudburstmc.protocol.bedrock.packet.AddPlayerPacket;
import org.cloudburstmc.protocol.bedrock.packet.MovePlayerPacket; 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.SetEntityLinkPacket;
import org.cloudburstmc.protocol.bedrock.packet.UpdateAttributesPacket; import org.cloudburstmc.protocol.bedrock.packet.UpdateAttributesPacket;
import org.geysermc.geyser.api.entity.type.player.GeyserPlayerEntity; import org.geysermc.geyser.api.entity.type.player.GeyserPlayerEntity;
@ -53,29 +51,17 @@ import org.geysermc.geyser.entity.attribute.GeyserAttributeType;
import org.geysermc.geyser.entity.type.Entity; import org.geysermc.geyser.entity.type.Entity;
import org.geysermc.geyser.entity.type.LivingEntity; import org.geysermc.geyser.entity.type.LivingEntity;
import org.geysermc.geyser.entity.type.living.animal.tameable.ParrotEntity; import org.geysermc.geyser.entity.type.living.animal.tameable.ParrotEntity;
import org.geysermc.geyser.scoreboard.Objective;
import org.geysermc.geyser.scoreboard.Score;
import org.geysermc.geyser.scoreboard.Team;
import org.geysermc.geyser.scoreboard.UpdateType;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.text.ChatColor;
import org.geysermc.geyser.translator.text.MessageTranslator;
import org.geysermc.geyser.util.ChunkUtils; import org.geysermc.geyser.util.ChunkUtils;
import org.geysermc.mcprotocollib.protocol.codec.NbtComponentSerializer;
import org.geysermc.mcprotocollib.protocol.data.game.chat.numbers.BlankFormat;
import org.geysermc.mcprotocollib.protocol.data.game.chat.numbers.FixedFormat;
import org.geysermc.mcprotocollib.protocol.data.game.chat.numbers.NumberFormat;
import org.geysermc.mcprotocollib.protocol.data.game.chat.numbers.StyledFormat;
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.EntityMetadata; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.EntityMetadata;
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.Pose; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.Pose;
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.BooleanEntityMetadata;
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.ByteEntityMetadata; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.ByteEntityMetadata;
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.FloatEntityMetadata; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.FloatEntityMetadata;
import org.geysermc.mcprotocollib.protocol.data.game.scoreboard.ScoreboardPosition;
import org.geysermc.mcprotocollib.protocol.data.game.scoreboard.TeamColor;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Objects;
import java.util.Optional; import java.util.Optional;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@ -96,6 +82,9 @@ public class PlayerEntity extends LivingEntity implements GeyserPlayerEntity {
private String username; private String username;
private String cachedScore = "";
private boolean scoreVisible = true;
/** /**
* The textures property from the GameProfile. * The textures property from the GameProfile.
*/ */
@ -132,17 +121,6 @@ public class PlayerEntity extends LivingEntity implements GeyserPlayerEntity {
@Override @Override
public void spawnEntity() { public void spawnEntity() {
// Check to see if the player should have a belowname counterpart added
Objective objective = session.getWorldCache().getScoreboard().getObjectiveSlots().get(ScoreboardPosition.BELOW_NAME);
if (objective != null) {
setBelowNameText(objective);
}
// Update in case this entity has been despawned, then respawned
this.nametag = this.username;
// The name can't be updated later (the entity metadata for it is ignored), so we need to check for this now
updateDisplayName(session.getWorldCache().getScoreboard().getTeamFor(username));
AddPlayerPacket addPlayerPacket = new AddPlayerPacket(); AddPlayerPacket addPlayerPacket = new AddPlayerPacket();
addPlayerPacket.setUuid(uuid); addPlayerPacket.setUuid(uuid);
addPlayerPacket.setUsername(username); addPlayerPacket.setUsername(username);
@ -177,6 +155,7 @@ public class PlayerEntity extends LivingEntity implements GeyserPlayerEntity {
// Since we re-use player entities: Clear flags, held item, etc // Since we re-use player entities: Clear flags, held item, etc
this.resetMetadata(); this.resetMetadata();
this.nametag = username;
this.hand = ItemData.AIR; this.hand = ItemData.AIR;
this.offhand = ItemData.AIR; this.offhand = ItemData.AIR;
this.boots = ItemData.AIR; this.boots = ItemData.AIR;
@ -200,11 +179,7 @@ public class PlayerEntity extends LivingEntity implements GeyserPlayerEntity {
if (session.getEntityCache().getPlayerEntity(uuid) == null) if (session.getEntityCache().getPlayerEntity(uuid) == null)
return; return;
if (session.getEntityCache().getEntityByGeyserId(geyserId) == null) { session.getEntityCache().spawnEntity(this);
session.getEntityCache().spawnEntity(this);
} else {
spawnEntity();
}
} }
@Override @Override
@ -276,10 +251,6 @@ public class PlayerEntity extends LivingEntity implements GeyserPlayerEntity {
} }
} }
public void updateRotation(float yaw, float pitch, float headYaw, boolean isOnGround) {
moveRelative(0, 0, 0, yaw, pitch, headYaw, isOnGround);
}
@Override @Override
public void setPosition(Vector3f position) { public void setPosition(Vector3f position) {
if (this.bedPosition != null) { if (this.bedPosition != null) {
@ -386,38 +357,30 @@ public class PlayerEntity extends LivingEntity implements GeyserPlayerEntity {
} }
} }
@Override
public String getDisplayName() {
return username;
}
@Override @Override
public void setDisplayName(EntityMetadata<Optional<Component>, ?> entityMetadata) { public void setDisplayName(EntityMetadata<Optional<Component>, ?> entityMetadata) {
// Doesn't do anything for players // Doesn't do anything for players
} }
//todo this will become common entity logic once UUID support is implemented for them @Override
public void updateDisplayName(@Nullable Team team) { public String teamIdentifier() {
boolean needsUpdate; return username;
if (team != null) { }
String newDisplayName;
if (team.isVisibleFor(session.getPlayerEntity().getUsername())) {
TeamColor color = team.getColor();
String chatColor = MessageTranslator.toChatColor(color);
// We have to emulate what modern Java text already does for us and add the color to each section
String prefix = team.getCurrentData().getPrefix();
String suffix = team.getCurrentData().getSuffix();
newDisplayName = chatColor + prefix + chatColor + this.username + chatColor + suffix;
} else {
// The name is not visible to the session player; clear name
newDisplayName = "";
}
needsUpdate = !newDisplayName.equals(this.nametag);
this.nametag = newDisplayName;
} else {
// The name has reset, if it was previously something else
needsUpdate = !this.nametag.equals(this.username);
this.nametag = this.username;
}
if (needsUpdate) { @Override
dirtyMetadata.put(EntityDataTypes.NAME, this.nametag); protected void setNametag(@Nullable String nametag, boolean fromDisplayName) {
// when fromDisplayName, LivingEntity will call scoreboard code. After that
// setNametag is called again with fromDisplayName on false
if (nametag == null && !fromDisplayName) {
// nametag = null means reset, so reset it back to username
nametag = username;
} }
super.setNametag(nametag, fromDisplayName);
} }
@Override @Override
@ -425,6 +388,33 @@ public class PlayerEntity extends LivingEntity implements GeyserPlayerEntity {
// Doesn't do anything for players // Doesn't do anything for players
} }
public void setBelowNameText(String text) {
if (text == null) {
text = "";
}
boolean changed = !Objects.equals(cachedScore, text);
cachedScore = text;
if (isScoreVisible() && changed) {
dirtyMetadata.put(EntityDataTypes.SCORE, text);
}
}
@Override
protected void scoreVisibility(boolean show) {
boolean visibilityChanged = scoreVisible != show;
scoreVisible = show;
if (!visibilityChanged) {
return;
}
// if the player has no cachedScore, we never have to change the score.
// hide = set to "" (does nothing), show = change from "" (does nothing)
if (cachedScore.isEmpty()) {
return;
}
dirtyMetadata.put(EntityDataTypes.SCORE, show ? cachedScore : "");
}
@Override @Override
protected void setDimensions(Pose pose) { protected void setDimensions(Pose pose) {
float height; float height;
@ -451,64 +441,6 @@ public class PlayerEntity extends LivingEntity implements GeyserPlayerEntity {
setBoundingBoxHeight(height); setBoundingBoxHeight(height);
} }
public void setBelowNameText(Objective objective) {
if (objective != null && objective.getUpdateType() != UpdateType.REMOVE) {
Score score = objective.getScores().get(username);
String numberString;
NumberFormat numberFormat;
int amount;
if (score != null) {
amount = score.getScore();
numberFormat = score.getNumberFormat();
if (numberFormat == null) {
numberFormat = objective.getNumberFormat();
}
} else {
amount = 0;
numberFormat = objective.getNumberFormat();
}
if (numberFormat instanceof BlankFormat) {
numberString = "";
} else if (numberFormat instanceof FixedFormat fixedFormat) {
numberString = MessageTranslator.convertMessage(fixedFormat.getValue());
} else if (numberFormat instanceof StyledFormat styledFormat) {
NbtMapBuilder styledAmount = styledFormat.getStyle().toBuilder();
styledAmount.putString("text", String.valueOf(amount));
numberString = MessageTranslator.convertJsonMessage(
NbtComponentSerializer.tagComponentToJson(styledAmount.build()).toString(), session.locale());
} else {
numberString = String.valueOf(amount);
}
String displayString = numberString + " " + ChatColor.RESET + objective.getDisplayName();
if (valid) {
// Already spawned - we still need to run the rest of this code because the spawn packet will be
// providing the information
SetEntityDataPacket packet = new SetEntityDataPacket();
packet.setRuntimeEntityId(geyserId);
packet.getMetadata().put(EntityDataTypes.SCORE, displayString);
session.sendUpstreamPacket(packet);
} else {
// Not spawned yet, store score value in dirtyMetadata to be picked up by #spawnEntity
dirtyMetadata.put(EntityDataTypes.SCORE, displayString);
}
} else {
if (valid) {
SetEntityDataPacket packet = new SetEntityDataPacket();
packet.setRuntimeEntityId(geyserId);
packet.getMetadata().put(EntityDataTypes.SCORE, "");
session.sendUpstreamPacket(packet);
} else {
// Not spawned yet, store score value in dirtyMetadata to be picked up by #spawnEntity
dirtyMetadata.put(EntityDataTypes.SCORE, "");
}
}
}
/** /**
* @return the UUID that should be used when dealing with Bedrock's tab list. * @return the UUID that should be used when dealing with Bedrock's tab list.
*/ */

Datei anzeigen

@ -38,8 +38,8 @@ import org.cloudburstmc.protocol.bedrock.packet.MovePlayerPacket;
import org.cloudburstmc.protocol.bedrock.packet.UpdateAttributesPacket; import org.cloudburstmc.protocol.bedrock.packet.UpdateAttributesPacket;
import org.geysermc.geyser.entity.attribute.GeyserAttributeType; import org.geysermc.geyser.entity.attribute.GeyserAttributeType;
import org.geysermc.geyser.item.Items; import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.network.GameProtocol;
import org.geysermc.geyser.level.BedrockDimension; import org.geysermc.geyser.level.BedrockDimension;
import org.geysermc.geyser.network.GameProtocol;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.util.AttributeUtils; import org.geysermc.geyser.util.AttributeUtils;
import org.geysermc.geyser.util.DimensionUtils; import org.geysermc.geyser.util.DimensionUtils;
@ -143,9 +143,32 @@ public class SessionPlayerEntity extends PlayerEntity {
this.position = position.add(0, definition.offset(), 0); this.position = position.add(0, definition.offset(), 0);
} }
/**
* Special method used only when updating the session player's rotation.
* For some reason, Mode#NORMAL ignored rotation. Yay.
* @param yaw the new yaw
* @param pitch the new pitch
* @param headYaw the head yaw
*/
public void updateOwnRotation(float yaw, float pitch, float headYaw) {
setYaw(yaw);
setPitch(pitch);
setHeadYaw(headYaw);
MovePlayerPacket movePlayerPacket = new MovePlayerPacket();
movePlayerPacket.setRuntimeEntityId(geyserId);
movePlayerPacket.setPosition(position);
movePlayerPacket.setRotation(getBedrockRotation());
movePlayerPacket.setOnGround(isOnGround());
movePlayerPacket.setMode(MovePlayerPacket.Mode.TELEPORT);
movePlayerPacket.setTeleportationCause(MovePlayerPacket.TeleportationCause.BEHAVIOR);
session.sendUpstreamPacket(movePlayerPacket);
}
/** /**
* Set the player's position without applying an offset or moving the bounding box * Set the player's position without applying an offset or moving the bounding box
* This is used in BedrockMovePlayerTranslator which receives the player's position * This is used in BedrockMovePlayer which receives the player's position
* with the offset pre-applied * with the offset pre-applied
* *
* @param position the new position of the Bedrock player * @param position the new position of the Bedrock player
@ -247,9 +270,9 @@ public class SessionPlayerEntity extends PlayerEntity {
@Override @Override
protected void updateAttribute(Attribute javaAttribute, List<AttributeData> newAttributes) { protected void updateAttribute(Attribute javaAttribute, List<AttributeData> newAttributes) {
if (javaAttribute.getType() == AttributeType.Builtin.GENERIC_ATTACK_SPEED) { if (javaAttribute.getType() == AttributeType.Builtin.ATTACK_SPEED) {
session.setAttackSpeed(AttributeUtils.calculateValue(javaAttribute)); session.setAttackSpeed(AttributeUtils.calculateValue(javaAttribute));
} else if (javaAttribute.getType() == AttributeType.Builtin.PLAYER_BLOCK_INTERACTION_RANGE) { } else if (javaAttribute.getType() == AttributeType.Builtin.BLOCK_INTERACTION_RANGE) {
this.blockInteractionRange = AttributeUtils.calculateValue(javaAttribute); this.blockInteractionRange = AttributeUtils.calculateValue(javaAttribute);
} else { } else {
super.updateAttribute(javaAttribute, newAttributes); super.updateAttribute(javaAttribute, newAttributes);

Datei anzeigen

@ -76,8 +76,8 @@ public class VehicleComponent<T extends LivingEntity & ClientVehicle> {
public VehicleComponent(T vehicle, float stepHeight) { public VehicleComponent(T vehicle, float stepHeight) {
this.vehicle = vehicle; this.vehicle = vehicle;
this.stepHeight = stepHeight; this.stepHeight = stepHeight;
this.moveSpeed = (float) AttributeType.Builtin.GENERIC_MOVEMENT_SPEED.getDef(); this.moveSpeed = (float) AttributeType.Builtin.MOVEMENT_SPEED.getDef();
this.gravity = AttributeType.Builtin.GENERIC_GRAVITY.getDef(); this.gravity = AttributeType.Builtin.GRAVITY.getDef();
double width = vehicle.getBoundingBoxWidth(); double width = vehicle.getBoundingBoxWidth();
double height = vehicle.getBoundingBoxHeight(); double height = vehicle.getBoundingBoxHeight();
@ -758,7 +758,6 @@ public class VehicleComponent<T extends LivingEntity & ClientVehicle> {
ServerboundMoveVehiclePacket moveVehiclePacket = new ServerboundMoveVehiclePacket(javaPos.getX(), javaPos.getY(), javaPos.getZ(), rotation.getX(), rotation.getY()); ServerboundMoveVehiclePacket moveVehiclePacket = new ServerboundMoveVehiclePacket(javaPos.getX(), javaPos.getY(), javaPos.getZ(), rotation.getX(), rotation.getY());
vehicle.getSession().sendDownstreamPacket(moveVehiclePacket); vehicle.getSession().sendDownstreamPacket(moveVehiclePacket);
vehicle.getSession().setLastVehicleMoveTimestamp(System.currentTimeMillis());
} }
protected double getGravity() { protected double getGravity() {

Datei anzeigen

@ -38,6 +38,7 @@ import org.geysermc.geyser.command.GeyserCommandSource;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
import org.incendo.cloud.CommandManager; import org.incendo.cloud.CommandManager;
import org.incendo.cloud.context.CommandContext; import org.incendo.cloud.context.CommandContext;
import org.incendo.cloud.description.CommandDescription;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -193,11 +194,17 @@ public abstract class GeyserExtensionCommand extends GeyserCommand {
.handler(this::execute)); .handler(this::execute));
} }
@Override
protected org.incendo.cloud.Command.Builder.Applicable<GeyserCommandSource> meta() {
// We don't want to localize the extension command description
return builder -> builder.commandDescription(CommandDescription.commandDescription(description));
}
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@Override @Override
public void execute(CommandContext<GeyserCommandSource> context) { public void execute(CommandContext<GeyserCommandSource> context) {
GeyserCommandSource source = context.sender(); GeyserCommandSource source = context.sender();
String[] args = context.getOrDefault("args", "").split(" "); String[] args = context.getOrDefault("args", " ").split(" ");
if (sourceType.isInstance(source)) { if (sourceType.isInstance(source)) {
executor.execute((T) source, this, args); executor.execute((T) source, this, args);

Datei anzeigen

@ -43,13 +43,13 @@ public class CameraDefinitions {
static { static {
CAMERA_PRESETS = List.of( CAMERA_PRESETS = List.of(
new CameraPreset(CameraPerspective.FIRST_PERSON.id(), "", null, null, null, null, null, null, OptionalBoolean.empty(), null, OptionalBoolean.empty(), null), new CameraPreset(CameraPerspective.FIRST_PERSON.id(), "", null, null, null, null, null, null, OptionalBoolean.empty(), null, OptionalBoolean.empty(), null, null, null, OptionalBoolean.empty(), OptionalBoolean.empty()),
new CameraPreset(CameraPerspective.FREE.id(), "", null, null, null, null, null, null, OptionalBoolean.empty(), null, OptionalBoolean.empty(), null), new CameraPreset(CameraPerspective.FREE.id(), "", null, null, null, null, null, null, OptionalBoolean.empty(), null, OptionalBoolean.empty(), null, null, null, OptionalBoolean.empty(), OptionalBoolean.empty()),
new CameraPreset(CameraPerspective.THIRD_PERSON.id(), "", null, null, null, null, null, null, OptionalBoolean.empty(), null, OptionalBoolean.empty(), null), new CameraPreset(CameraPerspective.THIRD_PERSON.id(), "", null, null, null, null, null, null, OptionalBoolean.empty(), null, OptionalBoolean.empty(), null, null, null, OptionalBoolean.empty(), OptionalBoolean.empty()),
new CameraPreset(CameraPerspective.THIRD_PERSON_FRONT.id(), "", null, null, null, null, null, null, OptionalBoolean.empty(), null, OptionalBoolean.empty(), null), new CameraPreset(CameraPerspective.THIRD_PERSON_FRONT.id(), "", null, null, null, null, null, null, OptionalBoolean.empty(), null, OptionalBoolean.empty(), null, null, null, OptionalBoolean.empty(), OptionalBoolean.empty()),
new CameraPreset("geyser:free_audio", "minecraft:free", null, null, null, null, null, CameraAudioListener.PLAYER, OptionalBoolean.empty(), null, OptionalBoolean.of(false), null), new CameraPreset("geyser:free_audio", "minecraft:free", null, null, null, null, null, CameraAudioListener.PLAYER, OptionalBoolean.empty(), null, OptionalBoolean.of(false), null, null, null, OptionalBoolean.empty(), OptionalBoolean.empty()),
new CameraPreset("geyser:free_effects", "minecraft:free", null, null, null, null, null, CameraAudioListener.CAMERA, OptionalBoolean.empty(), null, OptionalBoolean.of(true), null), new CameraPreset("geyser:free_effects", "minecraft:free", null, null, null, null, null, CameraAudioListener.CAMERA, OptionalBoolean.empty(), null, OptionalBoolean.of(true), null, null, null, OptionalBoolean.empty(), OptionalBoolean.empty()),
new CameraPreset("geyser:free_audio_effects", "minecraft:free", null, null, null, null, null, CameraAudioListener.PLAYER, OptionalBoolean.empty(), null, OptionalBoolean.of(true), null)); new CameraPreset("geyser:free_audio_effects", "minecraft:free", null, null, null, null, null, CameraAudioListener.PLAYER, OptionalBoolean.empty(), null, OptionalBoolean.of(true), null, null, null, OptionalBoolean.empty(), OptionalBoolean.empty()));
SimpleDefinitionRegistry.Builder<NamedDefinition> builder = SimpleDefinitionRegistry.builder(); SimpleDefinitionRegistry.Builder<NamedDefinition> builder = SimpleDefinitionRegistry.builder();
for (int i = 0; i < CAMERA_PRESETS.size(); i++) { for (int i = 0; i < CAMERA_PRESETS.size(); i++) {

Datei anzeigen

@ -29,6 +29,7 @@ import lombok.*;
import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.Nullable;
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.item.Items; import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.item.type.Item;
import org.geysermc.geyser.registry.Registries; import org.geysermc.geyser.registry.Registries;
@ -38,6 +39,10 @@ import org.geysermc.geyser.translator.item.ItemTranslator;
import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack; import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType; import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents; import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents;
import org.geysermc.mcprotocollib.protocol.data.game.recipe.display.slot.EmptySlotDisplay;
import org.geysermc.mcprotocollib.protocol.data.game.recipe.display.slot.ItemSlotDisplay;
import org.geysermc.mcprotocollib.protocol.data.game.recipe.display.slot.ItemStackSlotDisplay;
import org.geysermc.mcprotocollib.protocol.data.game.recipe.display.slot.SlotDisplay;
import java.util.HashMap; import java.util.HashMap;
@ -77,6 +82,20 @@ public class GeyserItemStack {
return itemStack == null ? EMPTY : new GeyserItemStack(itemStack.getId(), itemStack.getAmount(), itemStack.getDataComponents()); return itemStack == null ? EMPTY : new GeyserItemStack(itemStack.getId(), itemStack.getAmount(), itemStack.getDataComponents());
} }
public static @NonNull GeyserItemStack from(@NonNull SlotDisplay slotDisplay) {
if (slotDisplay instanceof EmptySlotDisplay) {
return GeyserItemStack.EMPTY;
}
if (slotDisplay instanceof ItemSlotDisplay itemSlotDisplay) {
return GeyserItemStack.of(itemSlotDisplay.item(), 1);
}
if (slotDisplay instanceof ItemStackSlotDisplay itemStackSlotDisplay) {
return GeyserItemStack.from(itemStackSlotDisplay.itemStack());
}
GeyserImpl.getInstance().getLogger().warning("Unsure how to convert to ItemStack: " + slotDisplay);
return GeyserItemStack.EMPTY;
}
public int getJavaId() { public int getJavaId() {
return isEmpty() ? 0 : javaId; return isEmpty() ? 0 : javaId;
} }
@ -163,7 +182,17 @@ public class GeyserItemStack {
return session.getItemMappings().getMapping(this.javaId); return session.getItemMappings().getMapping(this.javaId);
} }
public SlotDisplay asSlotDisplay() {
if (isEmpty()) {
return EmptySlotDisplay.INSTANCE;
}
return new ItemStackSlotDisplay(this.getItemStack());
}
public Item asItem() { public Item asItem() {
if (isEmpty()) {
return Items.AIR;
}
if (item == null) { if (item == null) {
return (item = Registries.JAVA_ITEMS.get().get(javaId)); return (item = Registries.JAVA_ITEMS.get().get(javaId));
} }

Datei anzeigen

@ -0,0 +1,166 @@
/*
* Copyright (c) 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.inventory.item;
import net.kyori.adventure.key.Key;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.cloudburstmc.nbt.NbtMap;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.session.cache.registry.JavaRegistry;
import org.geysermc.geyser.session.cache.registry.RegistryEntryContext;
import org.geysermc.geyser.translator.text.MessageTranslator;
import org.geysermc.geyser.util.MinecraftKey;
import org.geysermc.geyser.util.SoundUtils;
import org.geysermc.mcprotocollib.protocol.data.game.Holder;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.Instrument;
import org.geysermc.mcprotocollib.protocol.data.game.level.sound.BuiltinSound;
import java.util.Locale;
public interface GeyserInstrument {
static GeyserInstrument read(RegistryEntryContext context) {
NbtMap data = context.data();
String soundEvent = SoundUtils.readSoundEvent(data, "instrument " + context.id());
float range = data.getFloat("range");
String description = MessageTranslator.deserializeDescriptionForTooltip(context.session(), data);
BedrockInstrument bedrockInstrument = BedrockInstrument.getByJavaIdentifier(context.id());
return new GeyserInstrument.Impl(soundEvent, range, description, bedrockInstrument);
}
String soundEvent();
float range();
/**
* In Bedrock format
*/
String description();
BedrockInstrument bedrockInstrument();
/**
* @return the ID of the Bedrock counterpart for this instrument. If there is none ({@link #bedrockInstrument()} is null), then -1 is returned.
*/
default int bedrockId() {
BedrockInstrument bedrockInstrument = bedrockInstrument();
if (bedrockInstrument != null) {
return bedrockInstrument.ordinal();
}
return -1;
}
/**
* @return the ID of the Java counterpart for the given Bedrock ID. If an invalid Bedrock ID was given, or there is no counterpart, -1 is returned.
*/
static int bedrockIdToJava(GeyserSession session, int id) {
JavaRegistry<GeyserInstrument> instruments = session.getRegistryCache().instruments();
BedrockInstrument bedrockInstrument = BedrockInstrument.getByBedrockId(id);
if (bedrockInstrument != null) {
for (int i = 0; i < instruments.values().size(); i++) {
GeyserInstrument instrument = instruments.byId(i);
if (instrument.bedrockInstrument() == bedrockInstrument) {
return i;
}
}
}
return -1;
}
static GeyserInstrument fromHolder(GeyserSession session, Holder<Instrument> holder) {
if (holder.isId()) {
return session.getRegistryCache().instruments().byId(holder.id());
}
Instrument custom = holder.custom();
return new Wrapper(custom, session.locale());
}
record Wrapper(Instrument instrument, String locale) implements GeyserInstrument {
@Override
public String soundEvent() {
return instrument.getSoundEvent().getName();
}
@Override
public float range() {
return instrument.getRange();
}
@Override
public String description() {
return MessageTranslator.convertMessageForTooltip(instrument.getDescription(), locale);
}
@Override
public BedrockInstrument bedrockInstrument() {
if (instrument.getSoundEvent() instanceof BuiltinSound) {
return BedrockInstrument.getByJavaIdentifier(MinecraftKey.key(instrument.getSoundEvent().getName()));
}
// Probably custom
return null;
}
}
record Impl(String soundEvent, float range, String description, @Nullable BedrockInstrument bedrockInstrument) implements GeyserInstrument {
}
/**
* Each vanilla instrument on Bedrock, ordered in their network IDs.
*/
enum BedrockInstrument {
PONDER,
SING,
SEEK,
FEEL,
ADMIRE,
CALL,
YEARN,
DREAM;
private static final BedrockInstrument[] VALUES = values();
private final Key javaIdentifier;
BedrockInstrument() {
this.javaIdentifier = MinecraftKey.key(this.name().toLowerCase(Locale.ENGLISH) + "_goat_horn");
}
public static @Nullable BedrockInstrument getByJavaIdentifier(Key javaIdentifier) {
for (BedrockInstrument instrument : VALUES) {
if (instrument.javaIdentifier.equals(javaIdentifier)) {
return instrument;
}
}
return null;
}
public static @Nullable BedrockInstrument getByBedrockId(int bedrockId) {
if (bedrockId >= 0 && bedrockId < VALUES.length) {
return VALUES[bedrockId];
}
return null;
}
}
}

Datei anzeigen

@ -99,7 +99,7 @@ public enum Potion {
} }
public PotionContents toComponent() { public PotionContents toComponent() {
return new PotionContents(this.ordinal(), -1, Collections.emptyList()); return new PotionContents(this.ordinal(), -1, Collections.emptyList(), null);
} }
public static Potion getByJavaIdentifier(String javaIdentifier) { public static Potion getByJavaIdentifier(String javaIdentifier) {

Datei anzeigen

@ -25,11 +25,10 @@
package org.geysermc.geyser.inventory.recipe; package org.geysermc.geyser.inventory.recipe;
import org.checkerframework.checker.nullness.qual.Nullable; import org.geysermc.mcprotocollib.protocol.data.game.recipe.display.slot.SlotDisplay;
import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack;
/** /**
* A more compact version of {@link org.geysermc.mcprotocollib.protocol.data.game.recipe.Recipe}. * A more compact version of {@link org.geysermc.mcprotocollib.protocol.data.game.recipe.display.RecipeDisplay}.
*/ */
public interface GeyserRecipe { public interface GeyserRecipe {
/** /**
@ -37,6 +36,5 @@ public interface GeyserRecipe {
*/ */
boolean isShaped(); boolean isShaped();
@Nullable SlotDisplay result();
ItemStack result();
} }

Datei anzeigen

@ -25,15 +25,15 @@
package org.geysermc.geyser.inventory.recipe; package org.geysermc.geyser.inventory.recipe;
import org.checkerframework.checker.nullness.qual.Nullable; import org.geysermc.mcprotocollib.protocol.data.game.recipe.display.ShapedCraftingRecipeDisplay;
import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack; import org.geysermc.mcprotocollib.protocol.data.game.recipe.display.slot.SlotDisplay;
import org.geysermc.mcprotocollib.protocol.data.game.recipe.Ingredient;
import org.geysermc.mcprotocollib.protocol.data.game.recipe.data.ShapedRecipeData;
public record GeyserShapedRecipe(int width, int height, Ingredient[] ingredients, @Nullable ItemStack result) implements GeyserRecipe { import java.util.List;
public GeyserShapedRecipe(ShapedRecipeData data) { public record GeyserShapedRecipe(int width, int height, List<SlotDisplay> ingredients, SlotDisplay result) implements GeyserRecipe {
this(data.getWidth(), data.getHeight(), data.getIngredients(), data.getResult());
public GeyserShapedRecipe(ShapedCraftingRecipeDisplay data) {
this(data.width(), data.height(), data.ingredients(), data.result());
} }
@Override @Override

Datei anzeigen

@ -25,15 +25,15 @@
package org.geysermc.geyser.inventory.recipe; package org.geysermc.geyser.inventory.recipe;
import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack; import org.geysermc.mcprotocollib.protocol.data.game.recipe.display.ShapelessCraftingRecipeDisplay;
import org.geysermc.mcprotocollib.protocol.data.game.recipe.Ingredient; import org.geysermc.mcprotocollib.protocol.data.game.recipe.display.slot.SlotDisplay;
import org.geysermc.mcprotocollib.protocol.data.game.recipe.data.ShapelessRecipeData;
import org.checkerframework.checker.nullness.qual.Nullable;
public record GeyserShapelessRecipe(Ingredient[] ingredients, @Nullable ItemStack result) implements GeyserRecipe { import java.util.List;
public GeyserShapelessRecipe(ShapelessRecipeData data) { public record GeyserShapelessRecipe(List<SlotDisplay> ingredients, SlotDisplay result) implements GeyserRecipe {
this(data.getIngredients(), data.getResult());
public GeyserShapelessRecipe(ShapelessCraftingRecipeDisplay data) {
this(data.ingredients(), data.result());
} }
@Override @Override

Datei anzeigen

@ -0,0 +1,43 @@
/*
* Copyright (c) 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.inventory.recipe;
import org.geysermc.mcprotocollib.protocol.data.game.recipe.display.SmithingRecipeDisplay;
import org.geysermc.mcprotocollib.protocol.data.game.recipe.display.slot.SlotDisplay;
public record GeyserSmithingRecipe(SlotDisplay template,
SlotDisplay base,
SlotDisplay addition,
SlotDisplay result) implements GeyserRecipe {
public GeyserSmithingRecipe(SmithingRecipeDisplay display) {
this(display.template(), display.base(), display.addition(), display.result());
}
@Override
public boolean isShaped() {
return false;
}
}

Datei anzeigen

@ -27,13 +27,10 @@ package org.geysermc.geyser.inventory.updater;
import it.unimi.dsi.fastutil.objects.Object2IntMap; import it.unimi.dsi.fastutil.objects.Object2IntMap;
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
import java.util.stream.IntStream;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMap;
import org.cloudburstmc.nbt.NbtMapBuilder; import org.cloudburstmc.nbt.NbtMapBuilder;
import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerId; import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerId;
import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerSlotType;
import org.cloudburstmc.protocol.bedrock.data.inventory.FullContainerName;
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
import org.cloudburstmc.protocol.bedrock.packet.InventorySlotPacket; import org.cloudburstmc.protocol.bedrock.packet.InventorySlotPacket;
import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.GeyserImpl;
@ -41,22 +38,21 @@ import org.geysermc.geyser.inventory.AnvilContainer;
import org.geysermc.geyser.inventory.GeyserItemStack; import org.geysermc.geyser.inventory.GeyserItemStack;
import org.geysermc.geyser.inventory.Inventory; import org.geysermc.geyser.inventory.Inventory;
import org.geysermc.geyser.inventory.item.BedrockEnchantment; import org.geysermc.geyser.inventory.item.BedrockEnchantment;
import org.geysermc.geyser.item.enchantment.Enchantment;
import org.geysermc.geyser.item.Items; import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.item.enchantment.Enchantment;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.session.cache.tags.EnchantmentTag;
import org.geysermc.geyser.session.cache.tags.ItemTag;
import org.geysermc.geyser.translator.inventory.InventoryTranslator; import org.geysermc.geyser.translator.inventory.InventoryTranslator;
import org.geysermc.geyser.translator.text.MessageTranslator; import org.geysermc.geyser.translator.text.MessageTranslator;
import org.geysermc.geyser.util.ItemUtils; import org.geysermc.geyser.util.ItemUtils;
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.GameMode; import org.geysermc.mcprotocollib.protocol.data.game.entity.player.GameMode;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType; import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.HolderSet;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.ItemEnchantments; import org.geysermc.mcprotocollib.protocol.data.game.item.component.ItemEnchantments;
import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory.ServerboundRenameItemPacket; import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory.ServerboundRenameItemPacket;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.stream.IntStream;
public class AnvilInventoryUpdater extends InventoryUpdater { public class AnvilInventoryUpdater extends InventoryUpdater {
public static final AnvilInventoryUpdater INSTANCE = new AnvilInventoryUpdater(); public static final AnvilInventoryUpdater INSTANCE = new AnvilInventoryUpdater();
@ -80,7 +76,6 @@ public class AnvilInventoryUpdater extends InventoryUpdater {
slotPacket.setContainerId(ContainerId.UI); slotPacket.setContainerId(ContainerId.UI);
slotPacket.setSlot(bedrockSlot); slotPacket.setSlot(bedrockSlot);
slotPacket.setItem(inventory.getItem(i).getItemData(session)); slotPacket.setItem(inventory.getItem(i).getItemData(session));
slotPacket.setContainerNameData(new FullContainerName(ContainerSlotType.ANVIL_INPUT, null));
session.sendUpstreamPacket(slotPacket); session.sendUpstreamPacket(slotPacket);
} }
} }
@ -101,7 +96,6 @@ public class AnvilInventoryUpdater extends InventoryUpdater {
slotPacket.setContainerId(ContainerId.UI); slotPacket.setContainerId(ContainerId.UI);
slotPacket.setSlot(translator.javaSlotToBedrock(javaSlot)); slotPacket.setSlot(translator.javaSlotToBedrock(javaSlot));
slotPacket.setItem(inventory.getItem(javaSlot).getItemData(session)); slotPacket.setItem(inventory.getItem(javaSlot).getItemData(session));
slotPacket.setContainerNameData(new FullContainerName(ContainerSlotType.ANVIL_INPUT, null));
session.sendUpstreamPacket(slotPacket); session.sendUpstreamPacket(slotPacket);
} else if (lastTargetSlot != javaSlot) { } else if (lastTargetSlot != javaSlot) {
// Update the previous target slot to remove repair cost changes // Update the previous target slot to remove repair cost changes
@ -109,7 +103,6 @@ public class AnvilInventoryUpdater extends InventoryUpdater {
slotPacket.setContainerId(ContainerId.UI); slotPacket.setContainerId(ContainerId.UI);
slotPacket.setSlot(translator.javaSlotToBedrock(lastTargetSlot)); slotPacket.setSlot(translator.javaSlotToBedrock(lastTargetSlot));
slotPacket.setItem(inventory.getItem(lastTargetSlot).getItemData(session)); slotPacket.setItem(inventory.getItem(lastTargetSlot).getItemData(session));
slotPacket.setContainerNameData(new FullContainerName(ContainerSlotType.ANVIL_INPUT, null));
session.sendUpstreamPacket(slotPacket); session.sendUpstreamPacket(slotPacket);
} }
@ -173,7 +166,6 @@ public class AnvilInventoryUpdater extends InventoryUpdater {
slotPacket.setContainerId(ContainerId.UI); slotPacket.setContainerId(ContainerId.UI);
slotPacket.setSlot(translator.javaSlotToBedrock(slot)); slotPacket.setSlot(translator.javaSlotToBedrock(slot));
slotPacket.setItem(itemData); slotPacket.setItem(itemData);
slotPacket.setContainerNameData(new FullContainerName(ContainerSlotType.ANVIL_INPUT, null));
session.sendUpstreamPacket(slotPacket); session.sendUpstreamPacket(slotPacket);
} }
@ -320,14 +312,10 @@ public class AnvilInventoryUpdater extends InventoryUpdater {
for (Object2IntMap.Entry<Enchantment> entry : getEnchantments(session, material).object2IntEntrySet()) { for (Object2IntMap.Entry<Enchantment> entry : getEnchantments(session, material).object2IntEntrySet()) {
Enchantment enchantment = entry.getKey(); Enchantment enchantment = entry.getKey();
HolderSet supportedItems = enchantment.supportedItems(); boolean canApply = isEnchantedBook(input) || session.getTagCache().is(enchantment.supportedItems(), input.asItem());
int[] supportedItemIds = supportedItems.resolve(tagId -> session.getTagCache().get(ItemTag.ALL_ITEM_TAGS.get(tagId)));
boolean canApply = isEnchantedBook(input) || IntStream.of(supportedItemIds).anyMatch(id -> id == input.getJavaId());
HolderSet exclusiveSet = enchantment.exclusiveSet(); List<Enchantment> incompatibleEnchantments = enchantment.exclusiveSet().resolve(session);
int[] incompatibleEnchantments = exclusiveSet.resolve(tagId -> session.getTagCache().get(EnchantmentTag.ALL_ENCHANTMENT_TAGS.get(tagId))); for (Enchantment incompatible : incompatibleEnchantments) {
for (int i : incompatibleEnchantments) {
Enchantment incompatible = session.getRegistryCache().enchantments().byId(i);
if (combinedEnchantments.containsKey(incompatible)) { if (combinedEnchantments.containsKey(incompatible)) {
canApply = false; canApply = false;
if (!bedrock) { if (!bedrock) {

Datei anzeigen

@ -25,12 +25,10 @@
package org.geysermc.geyser.inventory.updater; package org.geysermc.geyser.inventory.updater;
import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerSlotType; import lombok.AllArgsConstructor;
import org.cloudburstmc.protocol.bedrock.data.inventory.FullContainerName;
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
import org.cloudburstmc.protocol.bedrock.packet.InventoryContentPacket; import org.cloudburstmc.protocol.bedrock.packet.InventoryContentPacket;
import org.cloudburstmc.protocol.bedrock.packet.InventorySlotPacket; import org.cloudburstmc.protocol.bedrock.packet.InventorySlotPacket;
import lombok.AllArgsConstructor;
import org.geysermc.geyser.inventory.Inventory; import org.geysermc.geyser.inventory.Inventory;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.text.GeyserLocale; import org.geysermc.geyser.text.GeyserLocale;
@ -63,7 +61,6 @@ public class ChestInventoryUpdater extends InventoryUpdater {
InventoryContentPacket contentPacket = new InventoryContentPacket(); InventoryContentPacket contentPacket = new InventoryContentPacket();
contentPacket.setContainerId(inventory.getBedrockId()); contentPacket.setContainerId(inventory.getBedrockId());
contentPacket.setContents(bedrockItems); contentPacket.setContents(bedrockItems);
contentPacket.setContainerNameData(new FullContainerName(ContainerSlotType.ANVIL_INPUT, null));
session.sendUpstreamPacket(contentPacket); session.sendUpstreamPacket(contentPacket);
} }
@ -76,7 +73,6 @@ public class ChestInventoryUpdater extends InventoryUpdater {
slotPacket.setContainerId(inventory.getBedrockId()); slotPacket.setContainerId(inventory.getBedrockId());
slotPacket.setSlot(translator.javaSlotToBedrock(javaSlot)); slotPacket.setSlot(translator.javaSlotToBedrock(javaSlot));
slotPacket.setItem(inventory.getItem(javaSlot).getItemData(session)); slotPacket.setItem(inventory.getItem(javaSlot).getItemData(session));
slotPacket.setContainerNameData(new FullContainerName(ContainerSlotType.ANVIL_INPUT, null));
session.sendUpstreamPacket(slotPacket); session.sendUpstreamPacket(slotPacket);
return true; return true;
} }

Datei anzeigen

@ -25,8 +25,6 @@
package org.geysermc.geyser.inventory.updater; package org.geysermc.geyser.inventory.updater;
import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerSlotType;
import org.cloudburstmc.protocol.bedrock.data.inventory.FullContainerName;
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
import org.cloudburstmc.protocol.bedrock.packet.InventoryContentPacket; import org.cloudburstmc.protocol.bedrock.packet.InventoryContentPacket;
import org.cloudburstmc.protocol.bedrock.packet.InventorySlotPacket; import org.cloudburstmc.protocol.bedrock.packet.InventorySlotPacket;
@ -51,7 +49,6 @@ public class ContainerInventoryUpdater extends InventoryUpdater {
InventoryContentPacket contentPacket = new InventoryContentPacket(); InventoryContentPacket contentPacket = new InventoryContentPacket();
contentPacket.setContainerId(inventory.getBedrockId()); contentPacket.setContainerId(inventory.getBedrockId());
contentPacket.setContents(Arrays.asList(bedrockItems)); contentPacket.setContents(Arrays.asList(bedrockItems));
contentPacket.setContainerNameData(new FullContainerName(ContainerSlotType.ANVIL_INPUT, null));
session.sendUpstreamPacket(contentPacket); session.sendUpstreamPacket(contentPacket);
} }
@ -64,7 +61,6 @@ public class ContainerInventoryUpdater extends InventoryUpdater {
slotPacket.setContainerId(inventory.getBedrockId()); slotPacket.setContainerId(inventory.getBedrockId());
slotPacket.setSlot(translator.javaSlotToBedrock(javaSlot)); slotPacket.setSlot(translator.javaSlotToBedrock(javaSlot));
slotPacket.setItem(inventory.getItem(javaSlot).getItemData(session)); slotPacket.setItem(inventory.getItem(javaSlot).getItemData(session));
slotPacket.setContainerNameData(new FullContainerName(ContainerSlotType.ANVIL_INPUT, null));
session.sendUpstreamPacket(slotPacket); session.sendUpstreamPacket(slotPacket);
return true; return true;
} }

Datei anzeigen

@ -26,8 +26,6 @@
package org.geysermc.geyser.inventory.updater; package org.geysermc.geyser.inventory.updater;
import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerId; import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerId;
import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerSlotType;
import org.cloudburstmc.protocol.bedrock.data.inventory.FullContainerName;
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
import org.cloudburstmc.protocol.bedrock.packet.InventoryContentPacket; import org.cloudburstmc.protocol.bedrock.packet.InventoryContentPacket;
import org.cloudburstmc.protocol.bedrock.packet.InventorySlotPacket; import org.cloudburstmc.protocol.bedrock.packet.InventorySlotPacket;
@ -58,7 +56,6 @@ public class CrafterInventoryUpdater extends InventoryUpdater {
contentPacket = new InventoryContentPacket(); contentPacket = new InventoryContentPacket();
contentPacket.setContainerId(inventory.getBedrockId()); contentPacket.setContainerId(inventory.getBedrockId());
contentPacket.setContents(Arrays.asList(bedrockItems)); contentPacket.setContents(Arrays.asList(bedrockItems));
contentPacket.setContainerNameData(new FullContainerName(ContainerSlotType.ANVIL_INPUT, null));
session.sendUpstreamPacket(contentPacket); session.sendUpstreamPacket(contentPacket);
// inventory and hotbar // inventory and hotbar
@ -70,7 +67,6 @@ public class CrafterInventoryUpdater extends InventoryUpdater {
contentPacket = new InventoryContentPacket(); contentPacket = new InventoryContentPacket();
contentPacket.setContainerId(ContainerId.INVENTORY); contentPacket.setContainerId(ContainerId.INVENTORY);
contentPacket.setContents(Arrays.asList(bedrockItems)); contentPacket.setContents(Arrays.asList(bedrockItems));
contentPacket.setContainerNameData(new FullContainerName(ContainerSlotType.ANVIL_INPUT, null));
session.sendUpstreamPacket(contentPacket); session.sendUpstreamPacket(contentPacket);
// Crafter result - it doesn't come after the grid, as explained elsewhere. // Crafter result - it doesn't come after the grid, as explained elsewhere.
@ -92,7 +88,6 @@ public class CrafterInventoryUpdater extends InventoryUpdater {
packet.setContainerId(containerId); packet.setContainerId(containerId);
packet.setSlot(translator.javaSlotToBedrock(javaSlot)); packet.setSlot(translator.javaSlotToBedrock(javaSlot));
packet.setItem(inventory.getItem(javaSlot).getItemData(session)); packet.setItem(inventory.getItem(javaSlot).getItemData(session));
packet.setContainerNameData(new FullContainerName(ContainerSlotType.ANVIL_INPUT, null));
session.sendUpstreamPacket(packet); session.sendUpstreamPacket(packet);
return true; return true;
} }

Datei anzeigen

@ -25,8 +25,6 @@
package org.geysermc.geyser.inventory.updater; package org.geysermc.geyser.inventory.updater;
import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerSlotType;
import org.cloudburstmc.protocol.bedrock.data.inventory.FullContainerName;
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
import org.cloudburstmc.protocol.bedrock.packet.InventoryContentPacket; import org.cloudburstmc.protocol.bedrock.packet.InventoryContentPacket;
import org.cloudburstmc.protocol.bedrock.packet.InventorySlotPacket; import org.cloudburstmc.protocol.bedrock.packet.InventorySlotPacket;
@ -51,7 +49,6 @@ public class HorseInventoryUpdater extends InventoryUpdater {
InventoryContentPacket contentPacket = new InventoryContentPacket(); InventoryContentPacket contentPacket = new InventoryContentPacket();
contentPacket.setContainerId(inventory.getBedrockId()); contentPacket.setContainerId(inventory.getBedrockId());
contentPacket.setContents(Arrays.asList(bedrockItems)); contentPacket.setContents(Arrays.asList(bedrockItems));
contentPacket.setContainerNameData(new FullContainerName(ContainerSlotType.ANVIL_INPUT, null));
session.sendUpstreamPacket(contentPacket); session.sendUpstreamPacket(contentPacket);
} }
@ -64,7 +61,6 @@ public class HorseInventoryUpdater extends InventoryUpdater {
slotPacket.setContainerId(4); // Horse GUI? slotPacket.setContainerId(4); // Horse GUI?
slotPacket.setSlot(translator.javaSlotToBedrock(javaSlot)); slotPacket.setSlot(translator.javaSlotToBedrock(javaSlot));
slotPacket.setItem(inventory.getItem(javaSlot).getItemData(session)); slotPacket.setItem(inventory.getItem(javaSlot).getItemData(session));
slotPacket.setContainerNameData(new FullContainerName(ContainerSlotType.ANVIL_INPUT, null));
session.sendUpstreamPacket(slotPacket); session.sendUpstreamPacket(slotPacket);
return true; return true;
} }

Datei anzeigen

@ -26,8 +26,6 @@
package org.geysermc.geyser.inventory.updater; package org.geysermc.geyser.inventory.updater;
import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerId; import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerId;
import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerSlotType;
import org.cloudburstmc.protocol.bedrock.data.inventory.FullContainerName;
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
import org.cloudburstmc.protocol.bedrock.packet.InventoryContentPacket; import org.cloudburstmc.protocol.bedrock.packet.InventoryContentPacket;
import org.cloudburstmc.protocol.bedrock.packet.InventorySlotPacket; import org.cloudburstmc.protocol.bedrock.packet.InventorySlotPacket;
@ -47,7 +45,6 @@ public class InventoryUpdater {
InventoryContentPacket contentPacket = new InventoryContentPacket(); InventoryContentPacket contentPacket = new InventoryContentPacket();
contentPacket.setContainerId(ContainerId.INVENTORY); contentPacket.setContainerId(ContainerId.INVENTORY);
contentPacket.setContents(Arrays.asList(bedrockItems)); contentPacket.setContents(Arrays.asList(bedrockItems));
contentPacket.setContainerNameData(new FullContainerName(ContainerSlotType.ANVIL_INPUT, null));
session.sendUpstreamPacket(contentPacket); session.sendUpstreamPacket(contentPacket);
} }
@ -57,7 +54,6 @@ public class InventoryUpdater {
slotPacket.setContainerId(ContainerId.INVENTORY); slotPacket.setContainerId(ContainerId.INVENTORY);
slotPacket.setSlot(translator.javaSlotToBedrock(javaSlot)); slotPacket.setSlot(translator.javaSlotToBedrock(javaSlot));
slotPacket.setItem(inventory.getItem(javaSlot).getItemData(session)); slotPacket.setItem(inventory.getItem(javaSlot).getItemData(session));
slotPacket.setContainerNameData(new FullContainerName(ContainerSlotType.ANVIL_INPUT, null));
session.sendUpstreamPacket(slotPacket); session.sendUpstreamPacket(slotPacket);
return true; return true;
} }

Datei anzeigen

@ -26,8 +26,6 @@
package org.geysermc.geyser.inventory.updater; package org.geysermc.geyser.inventory.updater;
import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerId; import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerId;
import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerSlotType;
import org.cloudburstmc.protocol.bedrock.data.inventory.FullContainerName;
import org.cloudburstmc.protocol.bedrock.packet.InventorySlotPacket; import org.cloudburstmc.protocol.bedrock.packet.InventorySlotPacket;
import org.geysermc.geyser.inventory.Inventory; import org.geysermc.geyser.inventory.Inventory;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
@ -48,7 +46,6 @@ public class UIInventoryUpdater extends InventoryUpdater {
slotPacket.setContainerId(ContainerId.UI); slotPacket.setContainerId(ContainerId.UI);
slotPacket.setSlot(bedrockSlot); slotPacket.setSlot(bedrockSlot);
slotPacket.setItem(inventory.getItem(i).getItemData(session)); slotPacket.setItem(inventory.getItem(i).getItemData(session));
slotPacket.setContainerNameData(new FullContainerName(ContainerSlotType.ANVIL_INPUT, null));
session.sendUpstreamPacket(slotPacket); session.sendUpstreamPacket(slotPacket);
} }
} }
@ -62,7 +59,6 @@ public class UIInventoryUpdater extends InventoryUpdater {
slotPacket.setContainerId(ContainerId.UI); slotPacket.setContainerId(ContainerId.UI);
slotPacket.setSlot(translator.javaSlotToBedrock(javaSlot)); slotPacket.setSlot(translator.javaSlotToBedrock(javaSlot));
slotPacket.setItem(inventory.getItem(javaSlot).getItemData(session)); slotPacket.setItem(inventory.getItem(javaSlot).getItemData(session));
slotPacket.setContainerNameData(new FullContainerName(ContainerSlotType.ANVIL_INPUT, null));
session.sendUpstreamPacket(slotPacket); session.sendUpstreamPacket(slotPacket);
return true; return true;
} }

Datei anzeigen

@ -25,9 +25,41 @@
package org.geysermc.geyser.item; package org.geysermc.geyser.item;
import org.geysermc.geyser.item.components.Rarity;
import org.geysermc.geyser.item.components.ToolTier; import org.geysermc.geyser.item.components.ToolTier;
import org.geysermc.geyser.item.type.*; import org.geysermc.geyser.item.type.ArmorItem;
import org.geysermc.geyser.item.type.ArrowItem;
import org.geysermc.geyser.item.type.AxolotlBucketItem;
import org.geysermc.geyser.item.type.BannerItem;
import org.geysermc.geyser.item.type.BlockItem;
import org.geysermc.geyser.item.type.BoatItem;
import org.geysermc.geyser.item.type.CompassItem;
import org.geysermc.geyser.item.type.CrossbowItem;
import org.geysermc.geyser.item.type.DecoratedPotItem;
import org.geysermc.geyser.item.type.DyeItem;
import org.geysermc.geyser.item.type.DyeableArmorItem;
import org.geysermc.geyser.item.type.ElytraItem;
import org.geysermc.geyser.item.type.EnchantedBookItem;
import org.geysermc.geyser.item.type.FilledMapItem;
import org.geysermc.geyser.item.type.FireworkRocketItem;
import org.geysermc.geyser.item.type.FireworkStarItem;
import org.geysermc.geyser.item.type.FishingRodItem;
import org.geysermc.geyser.item.type.GoatHornItem;
import org.geysermc.geyser.item.type.Item;
import org.geysermc.geyser.item.type.LightItem;
import org.geysermc.geyser.item.type.MaceItem;
import org.geysermc.geyser.item.type.MapItem;
import org.geysermc.geyser.item.type.OminousBottleItem;
import org.geysermc.geyser.item.type.PlayerHeadItem;
import org.geysermc.geyser.item.type.PotionItem;
import org.geysermc.geyser.item.type.ShieldItem;
import org.geysermc.geyser.item.type.ShulkerBoxItem;
import org.geysermc.geyser.item.type.SpawnEggItem;
import org.geysermc.geyser.item.type.TieredItem;
import org.geysermc.geyser.item.type.TippedArrowItem;
import org.geysermc.geyser.item.type.TropicalFishBucketItem;
import org.geysermc.geyser.item.type.WolfArmorItem;
import org.geysermc.geyser.item.type.WritableBookItem;
import org.geysermc.geyser.item.type.WrittenBookItem;
import org.geysermc.geyser.level.block.Blocks; import org.geysermc.geyser.level.block.Blocks;
import org.geysermc.geyser.registry.Registries; import org.geysermc.geyser.registry.Registries;
@ -81,6 +113,7 @@ public final class Items {
public static final Item ACACIA_PLANKS = register(new BlockItem(builder(), Blocks.ACACIA_PLANKS)); public static final Item ACACIA_PLANKS = register(new BlockItem(builder(), Blocks.ACACIA_PLANKS));
public static final Item CHERRY_PLANKS = register(new BlockItem(builder(), Blocks.CHERRY_PLANKS)); public static final Item CHERRY_PLANKS = register(new BlockItem(builder(), Blocks.CHERRY_PLANKS));
public static final Item DARK_OAK_PLANKS = register(new BlockItem(builder(), Blocks.DARK_OAK_PLANKS)); public static final Item DARK_OAK_PLANKS = register(new BlockItem(builder(), Blocks.DARK_OAK_PLANKS));
public static final Item PALE_OAK_PLANKS = register(new BlockItem(builder(), Blocks.PALE_OAK_PLANKS));
public static final Item MANGROVE_PLANKS = register(new BlockItem(builder(), Blocks.MANGROVE_PLANKS)); public static final Item MANGROVE_PLANKS = register(new BlockItem(builder(), Blocks.MANGROVE_PLANKS));
public static final Item BAMBOO_PLANKS = register(new BlockItem(builder(), Blocks.BAMBOO_PLANKS)); public static final Item BAMBOO_PLANKS = register(new BlockItem(builder(), Blocks.BAMBOO_PLANKS));
public static final Item CRIMSON_PLANKS = register(new BlockItem(builder(), Blocks.CRIMSON_PLANKS)); public static final Item CRIMSON_PLANKS = register(new BlockItem(builder(), Blocks.CRIMSON_PLANKS));
@ -93,6 +126,7 @@ public final class Items {
public static final Item ACACIA_SAPLING = register(new BlockItem(builder(), Blocks.ACACIA_SAPLING)); public static final Item ACACIA_SAPLING = register(new BlockItem(builder(), Blocks.ACACIA_SAPLING));
public static final Item CHERRY_SAPLING = register(new BlockItem(builder(), Blocks.CHERRY_SAPLING)); public static final Item CHERRY_SAPLING = register(new BlockItem(builder(), Blocks.CHERRY_SAPLING));
public static final Item DARK_OAK_SAPLING = register(new BlockItem(builder(), Blocks.DARK_OAK_SAPLING)); public static final Item DARK_OAK_SAPLING = register(new BlockItem(builder(), Blocks.DARK_OAK_SAPLING));
public static final Item PALE_OAK_SAPLING = register(new BlockItem(builder(), Blocks.PALE_OAK_SAPLING));
public static final Item MANGROVE_PROPAGULE = register(new BlockItem(builder(), Blocks.MANGROVE_PROPAGULE)); public static final Item MANGROVE_PROPAGULE = register(new BlockItem(builder(), Blocks.MANGROVE_PROPAGULE));
public static final Item BEDROCK = register(new BlockItem(builder(), Blocks.BEDROCK)); public static final Item BEDROCK = register(new BlockItem(builder(), Blocks.BEDROCK));
public static final Item SAND = register(new BlockItem(builder(), Blocks.SAND)); public static final Item SAND = register(new BlockItem(builder(), Blocks.SAND));
@ -123,7 +157,7 @@ public final class Items {
public static final Item RAW_IRON_BLOCK = register(new BlockItem(builder(), Blocks.RAW_IRON_BLOCK)); public static final Item RAW_IRON_BLOCK = register(new BlockItem(builder(), Blocks.RAW_IRON_BLOCK));
public static final Item RAW_COPPER_BLOCK = register(new BlockItem(builder(), Blocks.RAW_COPPER_BLOCK)); public static final Item RAW_COPPER_BLOCK = register(new BlockItem(builder(), Blocks.RAW_COPPER_BLOCK));
public static final Item RAW_GOLD_BLOCK = register(new BlockItem(builder(), Blocks.RAW_GOLD_BLOCK)); public static final Item RAW_GOLD_BLOCK = register(new BlockItem(builder(), Blocks.RAW_GOLD_BLOCK));
public static final Item HEAVY_CORE = register(new BlockItem(builder().rarity(Rarity.EPIC), Blocks.HEAVY_CORE)); public static final Item HEAVY_CORE = register(new BlockItem(builder(), Blocks.HEAVY_CORE));
public static final Item AMETHYST_BLOCK = register(new BlockItem(builder(), Blocks.AMETHYST_BLOCK)); public static final Item AMETHYST_BLOCK = register(new BlockItem(builder(), Blocks.AMETHYST_BLOCK));
public static final Item BUDDING_AMETHYST = register(new BlockItem(builder(), Blocks.BUDDING_AMETHYST)); public static final Item BUDDING_AMETHYST = register(new BlockItem(builder(), Blocks.BUDDING_AMETHYST));
public static final Item IRON_BLOCK = register(new BlockItem(builder(), Blocks.IRON_BLOCK)); public static final Item IRON_BLOCK = register(new BlockItem(builder(), Blocks.IRON_BLOCK));
@ -176,6 +210,7 @@ public final class Items {
public static final Item JUNGLE_LOG = register(new BlockItem(builder(), Blocks.JUNGLE_LOG)); public static final Item JUNGLE_LOG = register(new BlockItem(builder(), Blocks.JUNGLE_LOG));
public static final Item ACACIA_LOG = register(new BlockItem(builder(), Blocks.ACACIA_LOG)); public static final Item ACACIA_LOG = register(new BlockItem(builder(), Blocks.ACACIA_LOG));
public static final Item CHERRY_LOG = register(new BlockItem(builder(), Blocks.CHERRY_LOG)); public static final Item CHERRY_LOG = register(new BlockItem(builder(), Blocks.CHERRY_LOG));
public static final Item PALE_OAK_LOG = register(new BlockItem(builder(), Blocks.PALE_OAK_LOG));
public static final Item DARK_OAK_LOG = register(new BlockItem(builder(), Blocks.DARK_OAK_LOG)); public static final Item DARK_OAK_LOG = register(new BlockItem(builder(), Blocks.DARK_OAK_LOG));
public static final Item MANGROVE_LOG = register(new BlockItem(builder(), Blocks.MANGROVE_LOG)); public static final Item MANGROVE_LOG = register(new BlockItem(builder(), Blocks.MANGROVE_LOG));
public static final Item MANGROVE_ROOTS = register(new BlockItem(builder(), Blocks.MANGROVE_ROOTS)); public static final Item MANGROVE_ROOTS = register(new BlockItem(builder(), Blocks.MANGROVE_ROOTS));
@ -190,6 +225,7 @@ public final class Items {
public static final Item STRIPPED_ACACIA_LOG = register(new BlockItem(builder(), Blocks.STRIPPED_ACACIA_LOG)); public static final Item STRIPPED_ACACIA_LOG = register(new BlockItem(builder(), Blocks.STRIPPED_ACACIA_LOG));
public static final Item STRIPPED_CHERRY_LOG = register(new BlockItem(builder(), Blocks.STRIPPED_CHERRY_LOG)); public static final Item STRIPPED_CHERRY_LOG = register(new BlockItem(builder(), Blocks.STRIPPED_CHERRY_LOG));
public static final Item STRIPPED_DARK_OAK_LOG = register(new BlockItem(builder(), Blocks.STRIPPED_DARK_OAK_LOG)); public static final Item STRIPPED_DARK_OAK_LOG = register(new BlockItem(builder(), Blocks.STRIPPED_DARK_OAK_LOG));
public static final Item STRIPPED_PALE_OAK_LOG = register(new BlockItem(builder(), Blocks.STRIPPED_PALE_OAK_LOG));
public static final Item STRIPPED_MANGROVE_LOG = register(new BlockItem(builder(), Blocks.STRIPPED_MANGROVE_LOG)); public static final Item STRIPPED_MANGROVE_LOG = register(new BlockItem(builder(), Blocks.STRIPPED_MANGROVE_LOG));
public static final Item STRIPPED_CRIMSON_STEM = register(new BlockItem(builder(), Blocks.STRIPPED_CRIMSON_STEM)); public static final Item STRIPPED_CRIMSON_STEM = register(new BlockItem(builder(), Blocks.STRIPPED_CRIMSON_STEM));
public static final Item STRIPPED_WARPED_STEM = register(new BlockItem(builder(), Blocks.STRIPPED_WARPED_STEM)); public static final Item STRIPPED_WARPED_STEM = register(new BlockItem(builder(), Blocks.STRIPPED_WARPED_STEM));
@ -200,6 +236,7 @@ public final class Items {
public static final Item STRIPPED_ACACIA_WOOD = register(new BlockItem(builder(), Blocks.STRIPPED_ACACIA_WOOD)); public static final Item STRIPPED_ACACIA_WOOD = register(new BlockItem(builder(), Blocks.STRIPPED_ACACIA_WOOD));
public static final Item STRIPPED_CHERRY_WOOD = register(new BlockItem(builder(), Blocks.STRIPPED_CHERRY_WOOD)); public static final Item STRIPPED_CHERRY_WOOD = register(new BlockItem(builder(), Blocks.STRIPPED_CHERRY_WOOD));
public static final Item STRIPPED_DARK_OAK_WOOD = register(new BlockItem(builder(), Blocks.STRIPPED_DARK_OAK_WOOD)); public static final Item STRIPPED_DARK_OAK_WOOD = register(new BlockItem(builder(), Blocks.STRIPPED_DARK_OAK_WOOD));
public static final Item STRIPPED_PALE_OAK_WOOD = register(new BlockItem(builder(), Blocks.STRIPPED_PALE_OAK_WOOD));
public static final Item STRIPPED_MANGROVE_WOOD = register(new BlockItem(builder(), Blocks.STRIPPED_MANGROVE_WOOD)); public static final Item STRIPPED_MANGROVE_WOOD = register(new BlockItem(builder(), Blocks.STRIPPED_MANGROVE_WOOD));
public static final Item STRIPPED_CRIMSON_HYPHAE = register(new BlockItem(builder(), Blocks.STRIPPED_CRIMSON_HYPHAE)); public static final Item STRIPPED_CRIMSON_HYPHAE = register(new BlockItem(builder(), Blocks.STRIPPED_CRIMSON_HYPHAE));
public static final Item STRIPPED_WARPED_HYPHAE = register(new BlockItem(builder(), Blocks.STRIPPED_WARPED_HYPHAE)); public static final Item STRIPPED_WARPED_HYPHAE = register(new BlockItem(builder(), Blocks.STRIPPED_WARPED_HYPHAE));
@ -210,6 +247,7 @@ public final class Items {
public static final Item JUNGLE_WOOD = register(new BlockItem(builder(), Blocks.JUNGLE_WOOD)); public static final Item JUNGLE_WOOD = register(new BlockItem(builder(), Blocks.JUNGLE_WOOD));
public static final Item ACACIA_WOOD = register(new BlockItem(builder(), Blocks.ACACIA_WOOD)); public static final Item ACACIA_WOOD = register(new BlockItem(builder(), Blocks.ACACIA_WOOD));
public static final Item CHERRY_WOOD = register(new BlockItem(builder(), Blocks.CHERRY_WOOD)); public static final Item CHERRY_WOOD = register(new BlockItem(builder(), Blocks.CHERRY_WOOD));
public static final Item PALE_OAK_WOOD = register(new BlockItem(builder(), Blocks.PALE_OAK_WOOD));
public static final Item DARK_OAK_WOOD = register(new BlockItem(builder(), Blocks.DARK_OAK_WOOD)); public static final Item DARK_OAK_WOOD = register(new BlockItem(builder(), Blocks.DARK_OAK_WOOD));
public static final Item MANGROVE_WOOD = register(new BlockItem(builder(), Blocks.MANGROVE_WOOD)); public static final Item MANGROVE_WOOD = register(new BlockItem(builder(), Blocks.MANGROVE_WOOD));
public static final Item CRIMSON_HYPHAE = register(new BlockItem(builder(), Blocks.CRIMSON_HYPHAE)); public static final Item CRIMSON_HYPHAE = register(new BlockItem(builder(), Blocks.CRIMSON_HYPHAE));
@ -221,6 +259,7 @@ public final class Items {
public static final Item ACACIA_LEAVES = register(new BlockItem(builder(), Blocks.ACACIA_LEAVES)); public static final Item ACACIA_LEAVES = register(new BlockItem(builder(), Blocks.ACACIA_LEAVES));
public static final Item CHERRY_LEAVES = register(new BlockItem(builder(), Blocks.CHERRY_LEAVES)); public static final Item CHERRY_LEAVES = register(new BlockItem(builder(), Blocks.CHERRY_LEAVES));
public static final Item DARK_OAK_LEAVES = register(new BlockItem(builder(), Blocks.DARK_OAK_LEAVES)); public static final Item DARK_OAK_LEAVES = register(new BlockItem(builder(), Blocks.DARK_OAK_LEAVES));
public static final Item PALE_OAK_LEAVES = register(new BlockItem(builder(), Blocks.PALE_OAK_LEAVES));
public static final Item MANGROVE_LEAVES = register(new BlockItem(builder(), Blocks.MANGROVE_LEAVES)); public static final Item MANGROVE_LEAVES = register(new BlockItem(builder(), Blocks.MANGROVE_LEAVES));
public static final Item AZALEA_LEAVES = register(new BlockItem(builder(), Blocks.AZALEA_LEAVES)); public static final Item AZALEA_LEAVES = register(new BlockItem(builder(), Blocks.AZALEA_LEAVES));
public static final Item FLOWERING_AZALEA_LEAVES = register(new BlockItem(builder(), Blocks.FLOWERING_AZALEA_LEAVES)); public static final Item FLOWERING_AZALEA_LEAVES = register(new BlockItem(builder(), Blocks.FLOWERING_AZALEA_LEAVES));
@ -283,9 +322,12 @@ public final class Items {
public static final Item TWISTING_VINES = register(new BlockItem(builder(), Blocks.TWISTING_VINES)); public static final Item TWISTING_VINES = register(new BlockItem(builder(), Blocks.TWISTING_VINES));
public static final Item SUGAR_CANE = register(new BlockItem(builder(), Blocks.SUGAR_CANE)); public static final Item SUGAR_CANE = register(new BlockItem(builder(), Blocks.SUGAR_CANE));
public static final Item KELP = register(new BlockItem(builder(), Blocks.KELP)); public static final Item KELP = register(new BlockItem(builder(), Blocks.KELP));
public static final Item MOSS_CARPET = register(new BlockItem(builder(), Blocks.MOSS_CARPET));
public static final Item PINK_PETALS = register(new BlockItem(builder(), Blocks.PINK_PETALS)); public static final Item PINK_PETALS = register(new BlockItem(builder(), Blocks.PINK_PETALS));
public static final Item MOSS_CARPET = register(new BlockItem(builder(), Blocks.MOSS_CARPET));
public static final Item MOSS_BLOCK = register(new BlockItem(builder(), Blocks.MOSS_BLOCK)); public static final Item MOSS_BLOCK = register(new BlockItem(builder(), Blocks.MOSS_BLOCK));
public static final Item PALE_MOSS_CARPET = register(new BlockItem(builder(), Blocks.PALE_MOSS_CARPET));
public static final Item PALE_HANGING_MOSS = register(new BlockItem(builder(), Blocks.PALE_HANGING_MOSS));
public static final Item PALE_MOSS_BLOCK = register(new BlockItem(builder(), Blocks.PALE_MOSS_BLOCK));
public static final Item HANGING_ROOTS = register(new BlockItem(builder(), Blocks.HANGING_ROOTS)); public static final Item HANGING_ROOTS = register(new BlockItem(builder(), Blocks.HANGING_ROOTS));
public static final Item BIG_DRIPLEAF = register(new BlockItem(builder(), Blocks.BIG_DRIPLEAF, Blocks.BIG_DRIPLEAF_STEM)); public static final Item BIG_DRIPLEAF = register(new BlockItem(builder(), Blocks.BIG_DRIPLEAF, Blocks.BIG_DRIPLEAF_STEM));
public static final Item SMALL_DRIPLEAF = register(new BlockItem(builder(), Blocks.SMALL_DRIPLEAF)); public static final Item SMALL_DRIPLEAF = register(new BlockItem(builder(), Blocks.SMALL_DRIPLEAF));
@ -297,6 +339,7 @@ public final class Items {
public static final Item ACACIA_SLAB = register(new BlockItem(builder(), Blocks.ACACIA_SLAB)); public static final Item ACACIA_SLAB = register(new BlockItem(builder(), Blocks.ACACIA_SLAB));
public static final Item CHERRY_SLAB = register(new BlockItem(builder(), Blocks.CHERRY_SLAB)); public static final Item CHERRY_SLAB = register(new BlockItem(builder(), Blocks.CHERRY_SLAB));
public static final Item DARK_OAK_SLAB = register(new BlockItem(builder(), Blocks.DARK_OAK_SLAB)); public static final Item DARK_OAK_SLAB = register(new BlockItem(builder(), Blocks.DARK_OAK_SLAB));
public static final Item PALE_OAK_SLAB = register(new BlockItem(builder(), Blocks.PALE_OAK_SLAB));
public static final Item MANGROVE_SLAB = register(new BlockItem(builder(), Blocks.MANGROVE_SLAB)); public static final Item MANGROVE_SLAB = register(new BlockItem(builder(), Blocks.MANGROVE_SLAB));
public static final Item BAMBOO_SLAB = register(new BlockItem(builder(), Blocks.BAMBOO_SLAB)); public static final Item BAMBOO_SLAB = register(new BlockItem(builder(), Blocks.BAMBOO_SLAB));
public static final Item BAMBOO_MOSAIC_SLAB = register(new BlockItem(builder(), Blocks.BAMBOO_MOSAIC_SLAB)); public static final Item BAMBOO_MOSAIC_SLAB = register(new BlockItem(builder(), Blocks.BAMBOO_MOSAIC_SLAB));
@ -337,6 +380,7 @@ public final class Items {
public static final Item PURPUR_PILLAR = register(new BlockItem(builder(), Blocks.PURPUR_PILLAR)); public static final Item PURPUR_PILLAR = register(new BlockItem(builder(), Blocks.PURPUR_PILLAR));
public static final Item PURPUR_STAIRS = register(new BlockItem(builder(), Blocks.PURPUR_STAIRS)); public static final Item PURPUR_STAIRS = register(new BlockItem(builder(), Blocks.PURPUR_STAIRS));
public static final Item SPAWNER = register(new BlockItem(builder(), Blocks.SPAWNER)); public static final Item SPAWNER = register(new BlockItem(builder(), Blocks.SPAWNER));
public static final Item CREAKING_HEART = register(new BlockItem(builder(), Blocks.CREAKING_HEART));
public static final Item CHEST = register(new BlockItem(builder(), Blocks.CHEST)); public static final Item CHEST = register(new BlockItem(builder(), Blocks.CHEST));
public static final Item CRAFTING_TABLE = register(new BlockItem(builder(), Blocks.CRAFTING_TABLE)); public static final Item CRAFTING_TABLE = register(new BlockItem(builder(), Blocks.CRAFTING_TABLE));
public static final Item FARMLAND = register(new BlockItem(builder(), Blocks.FARMLAND)); public static final Item FARMLAND = register(new BlockItem(builder(), Blocks.FARMLAND));
@ -356,6 +400,7 @@ public final class Items {
public static final Item ACACIA_FENCE = register(new BlockItem(builder(), Blocks.ACACIA_FENCE)); public static final Item ACACIA_FENCE = register(new BlockItem(builder(), Blocks.ACACIA_FENCE));
public static final Item CHERRY_FENCE = register(new BlockItem(builder(), Blocks.CHERRY_FENCE)); public static final Item CHERRY_FENCE = register(new BlockItem(builder(), Blocks.CHERRY_FENCE));
public static final Item DARK_OAK_FENCE = register(new BlockItem(builder(), Blocks.DARK_OAK_FENCE)); public static final Item DARK_OAK_FENCE = register(new BlockItem(builder(), Blocks.DARK_OAK_FENCE));
public static final Item PALE_OAK_FENCE = register(new BlockItem(builder(), Blocks.PALE_OAK_FENCE));
public static final Item MANGROVE_FENCE = register(new BlockItem(builder(), Blocks.MANGROVE_FENCE)); public static final Item MANGROVE_FENCE = register(new BlockItem(builder(), Blocks.MANGROVE_FENCE));
public static final Item BAMBOO_FENCE = register(new BlockItem(builder(), Blocks.BAMBOO_FENCE)); public static final Item BAMBOO_FENCE = register(new BlockItem(builder(), Blocks.BAMBOO_FENCE));
public static final Item CRIMSON_FENCE = register(new BlockItem(builder(), Blocks.CRIMSON_FENCE)); public static final Item CRIMSON_FENCE = register(new BlockItem(builder(), Blocks.CRIMSON_FENCE));
@ -417,7 +462,7 @@ public final class Items {
public static final Item END_PORTAL_FRAME = register(new BlockItem(builder(), Blocks.END_PORTAL_FRAME)); public static final Item END_PORTAL_FRAME = register(new BlockItem(builder(), Blocks.END_PORTAL_FRAME));
public static final Item END_STONE = register(new BlockItem(builder(), Blocks.END_STONE)); public static final Item END_STONE = register(new BlockItem(builder(), Blocks.END_STONE));
public static final Item END_STONE_BRICKS = register(new BlockItem(builder(), Blocks.END_STONE_BRICKS)); public static final Item END_STONE_BRICKS = register(new BlockItem(builder(), Blocks.END_STONE_BRICKS));
public static final Item DRAGON_EGG = register(new BlockItem(builder().rarity(Rarity.EPIC), Blocks.DRAGON_EGG)); public static final Item DRAGON_EGG = register(new BlockItem(builder(), Blocks.DRAGON_EGG));
public static final Item SANDSTONE_STAIRS = register(new BlockItem(builder(), Blocks.SANDSTONE_STAIRS)); public static final Item SANDSTONE_STAIRS = register(new BlockItem(builder(), Blocks.SANDSTONE_STAIRS));
public static final Item ENDER_CHEST = register(new BlockItem(builder(), Blocks.ENDER_CHEST)); public static final Item ENDER_CHEST = register(new BlockItem(builder(), Blocks.ENDER_CHEST));
public static final Item EMERALD_BLOCK = register(new BlockItem(builder(), Blocks.EMERALD_BLOCK)); public static final Item EMERALD_BLOCK = register(new BlockItem(builder(), Blocks.EMERALD_BLOCK));
@ -428,13 +473,14 @@ public final class Items {
public static final Item ACACIA_STAIRS = register(new BlockItem(builder(), Blocks.ACACIA_STAIRS)); public static final Item ACACIA_STAIRS = register(new BlockItem(builder(), Blocks.ACACIA_STAIRS));
public static final Item CHERRY_STAIRS = register(new BlockItem(builder(), Blocks.CHERRY_STAIRS)); public static final Item CHERRY_STAIRS = register(new BlockItem(builder(), Blocks.CHERRY_STAIRS));
public static final Item DARK_OAK_STAIRS = register(new BlockItem(builder(), Blocks.DARK_OAK_STAIRS)); public static final Item DARK_OAK_STAIRS = register(new BlockItem(builder(), Blocks.DARK_OAK_STAIRS));
public static final Item PALE_OAK_STAIRS = register(new BlockItem(builder(), Blocks.PALE_OAK_STAIRS));
public static final Item MANGROVE_STAIRS = register(new BlockItem(builder(), Blocks.MANGROVE_STAIRS)); public static final Item MANGROVE_STAIRS = register(new BlockItem(builder(), Blocks.MANGROVE_STAIRS));
public static final Item BAMBOO_STAIRS = register(new BlockItem(builder(), Blocks.BAMBOO_STAIRS)); public static final Item BAMBOO_STAIRS = register(new BlockItem(builder(), Blocks.BAMBOO_STAIRS));
public static final Item BAMBOO_MOSAIC_STAIRS = register(new BlockItem(builder(), Blocks.BAMBOO_MOSAIC_STAIRS)); public static final Item BAMBOO_MOSAIC_STAIRS = register(new BlockItem(builder(), Blocks.BAMBOO_MOSAIC_STAIRS));
public static final Item CRIMSON_STAIRS = register(new BlockItem(builder(), Blocks.CRIMSON_STAIRS)); public static final Item CRIMSON_STAIRS = register(new BlockItem(builder(), Blocks.CRIMSON_STAIRS));
public static final Item WARPED_STAIRS = register(new BlockItem(builder(), Blocks.WARPED_STAIRS)); public static final Item WARPED_STAIRS = register(new BlockItem(builder(), Blocks.WARPED_STAIRS));
public static final Item COMMAND_BLOCK = register(new BlockItem(builder().rarity(Rarity.EPIC), Blocks.COMMAND_BLOCK)); public static final Item COMMAND_BLOCK = register(new BlockItem(builder(), Blocks.COMMAND_BLOCK));
public static final Item BEACON = register(new BlockItem(builder().rarity(Rarity.RARE), Blocks.BEACON)); public static final Item BEACON = register(new BlockItem(builder(), Blocks.BEACON));
public static final Item COBBLESTONE_WALL = register(new BlockItem(builder(), Blocks.COBBLESTONE_WALL)); public static final Item COBBLESTONE_WALL = register(new BlockItem(builder(), Blocks.COBBLESTONE_WALL));
public static final Item MOSSY_COBBLESTONE_WALL = register(new BlockItem(builder(), Blocks.MOSSY_COBBLESTONE_WALL)); public static final Item MOSSY_COBBLESTONE_WALL = register(new BlockItem(builder(), Blocks.MOSSY_COBBLESTONE_WALL));
public static final Item BRICK_WALL = register(new BlockItem(builder(), Blocks.BRICK_WALL)); public static final Item BRICK_WALL = register(new BlockItem(builder(), Blocks.BRICK_WALL));
@ -481,8 +527,8 @@ public final class Items {
public static final Item GREEN_TERRACOTTA = register(new BlockItem(builder(), Blocks.GREEN_TERRACOTTA)); public static final Item GREEN_TERRACOTTA = register(new BlockItem(builder(), Blocks.GREEN_TERRACOTTA));
public static final Item RED_TERRACOTTA = register(new BlockItem(builder(), Blocks.RED_TERRACOTTA)); public static final Item RED_TERRACOTTA = register(new BlockItem(builder(), Blocks.RED_TERRACOTTA));
public static final Item BLACK_TERRACOTTA = register(new BlockItem(builder(), Blocks.BLACK_TERRACOTTA)); public static final Item BLACK_TERRACOTTA = register(new BlockItem(builder(), Blocks.BLACK_TERRACOTTA));
public static final Item BARRIER = register(new BlockItem(builder().rarity(Rarity.EPIC), Blocks.BARRIER)); public static final Item BARRIER = register(new BlockItem(builder(), Blocks.BARRIER));
public static final Item LIGHT = register(new BlockItem(builder().rarity(Rarity.EPIC), Blocks.LIGHT)); public static final Item LIGHT = register(new LightItem(builder(), Blocks.LIGHT));
public static final Item HAY_BLOCK = register(new BlockItem(builder(), Blocks.HAY_BLOCK)); public static final Item HAY_BLOCK = register(new BlockItem(builder(), Blocks.HAY_BLOCK));
public static final Item WHITE_CARPET = register(new BlockItem(builder(), Blocks.WHITE_CARPET)); public static final Item WHITE_CARPET = register(new BlockItem(builder(), Blocks.WHITE_CARPET));
public static final Item ORANGE_CARPET = register(new BlockItem(builder(), Blocks.ORANGE_CARPET)); public static final Item ORANGE_CARPET = register(new BlockItem(builder(), Blocks.ORANGE_CARPET));
@ -552,14 +598,14 @@ public final class Items {
public static final Item CHISELED_RED_SANDSTONE = register(new BlockItem(builder(), Blocks.CHISELED_RED_SANDSTONE)); public static final Item CHISELED_RED_SANDSTONE = register(new BlockItem(builder(), Blocks.CHISELED_RED_SANDSTONE));
public static final Item CUT_RED_SANDSTONE = register(new BlockItem(builder(), Blocks.CUT_RED_SANDSTONE)); public static final Item CUT_RED_SANDSTONE = register(new BlockItem(builder(), Blocks.CUT_RED_SANDSTONE));
public static final Item RED_SANDSTONE_STAIRS = register(new BlockItem(builder(), Blocks.RED_SANDSTONE_STAIRS)); public static final Item RED_SANDSTONE_STAIRS = register(new BlockItem(builder(), Blocks.RED_SANDSTONE_STAIRS));
public static final Item REPEATING_COMMAND_BLOCK = register(new BlockItem(builder().rarity(Rarity.EPIC), Blocks.REPEATING_COMMAND_BLOCK)); public static final Item REPEATING_COMMAND_BLOCK = register(new BlockItem(builder(), Blocks.REPEATING_COMMAND_BLOCK));
public static final Item CHAIN_COMMAND_BLOCK = register(new BlockItem(builder().rarity(Rarity.EPIC), Blocks.CHAIN_COMMAND_BLOCK)); public static final Item CHAIN_COMMAND_BLOCK = register(new BlockItem(builder(), Blocks.CHAIN_COMMAND_BLOCK));
public static final Item MAGMA_BLOCK = register(new BlockItem(builder(), Blocks.MAGMA_BLOCK)); public static final Item MAGMA_BLOCK = register(new BlockItem(builder(), Blocks.MAGMA_BLOCK));
public static final Item NETHER_WART_BLOCK = register(new BlockItem(builder(), Blocks.NETHER_WART_BLOCK)); public static final Item NETHER_WART_BLOCK = register(new BlockItem(builder(), Blocks.NETHER_WART_BLOCK));
public static final Item WARPED_WART_BLOCK = register(new BlockItem(builder(), Blocks.WARPED_WART_BLOCK)); public static final Item WARPED_WART_BLOCK = register(new BlockItem(builder(), Blocks.WARPED_WART_BLOCK));
public static final Item RED_NETHER_BRICKS = register(new BlockItem(builder(), Blocks.RED_NETHER_BRICKS)); public static final Item RED_NETHER_BRICKS = register(new BlockItem(builder(), Blocks.RED_NETHER_BRICKS));
public static final Item BONE_BLOCK = register(new BlockItem(builder(), Blocks.BONE_BLOCK)); public static final Item BONE_BLOCK = register(new BlockItem(builder(), Blocks.BONE_BLOCK));
public static final Item STRUCTURE_VOID = register(new BlockItem(builder().rarity(Rarity.EPIC), Blocks.STRUCTURE_VOID)); public static final Item STRUCTURE_VOID = register(new BlockItem(builder(), Blocks.STRUCTURE_VOID));
public static final Item SHULKER_BOX = register(new ShulkerBoxItem(builder().stackSize(1), Blocks.SHULKER_BOX)); public static final Item SHULKER_BOX = register(new ShulkerBoxItem(builder().stackSize(1), Blocks.SHULKER_BOX));
public static final Item WHITE_SHULKER_BOX = register(new ShulkerBoxItem(builder().stackSize(1), Blocks.WHITE_SHULKER_BOX)); public static final Item WHITE_SHULKER_BOX = register(new ShulkerBoxItem(builder().stackSize(1), Blocks.WHITE_SHULKER_BOX));
public static final Item ORANGE_SHULKER_BOX = register(new ShulkerBoxItem(builder().stackSize(1), Blocks.ORANGE_SHULKER_BOX)); public static final Item ORANGE_SHULKER_BOX = register(new ShulkerBoxItem(builder().stackSize(1), Blocks.ORANGE_SHULKER_BOX));
@ -658,7 +704,7 @@ public final class Items {
public static final Item DEAD_FIRE_CORAL_FAN = register(new BlockItem(builder(), Blocks.DEAD_FIRE_CORAL_FAN, Blocks.DEAD_FIRE_CORAL_WALL_FAN)); public static final Item DEAD_FIRE_CORAL_FAN = register(new BlockItem(builder(), Blocks.DEAD_FIRE_CORAL_FAN, Blocks.DEAD_FIRE_CORAL_WALL_FAN));
public static final Item DEAD_HORN_CORAL_FAN = register(new BlockItem(builder(), Blocks.DEAD_HORN_CORAL_FAN, Blocks.DEAD_HORN_CORAL_WALL_FAN)); public static final Item DEAD_HORN_CORAL_FAN = register(new BlockItem(builder(), Blocks.DEAD_HORN_CORAL_FAN, Blocks.DEAD_HORN_CORAL_WALL_FAN));
public static final Item BLUE_ICE = register(new BlockItem(builder(), Blocks.BLUE_ICE)); public static final Item BLUE_ICE = register(new BlockItem(builder(), Blocks.BLUE_ICE));
public static final Item CONDUIT = register(new BlockItem(builder().rarity(Rarity.RARE), Blocks.CONDUIT)); public static final Item CONDUIT = register(new BlockItem(builder(), Blocks.CONDUIT));
public static final Item POLISHED_GRANITE_STAIRS = register(new BlockItem(builder(), Blocks.POLISHED_GRANITE_STAIRS)); public static final Item POLISHED_GRANITE_STAIRS = register(new BlockItem(builder(), Blocks.POLISHED_GRANITE_STAIRS));
public static final Item SMOOTH_RED_SANDSTONE_STAIRS = register(new BlockItem(builder(), Blocks.SMOOTH_RED_SANDSTONE_STAIRS)); public static final Item SMOOTH_RED_SANDSTONE_STAIRS = register(new BlockItem(builder(), Blocks.SMOOTH_RED_SANDSTONE_STAIRS));
public static final Item MOSSY_STONE_BRICK_STAIRS = register(new BlockItem(builder(), Blocks.MOSSY_STONE_BRICK_STAIRS)); public static final Item MOSSY_STONE_BRICK_STAIRS = register(new BlockItem(builder(), Blocks.MOSSY_STONE_BRICK_STAIRS));
@ -729,6 +775,7 @@ public final class Items {
public static final Item ACACIA_BUTTON = register(new BlockItem(builder(), Blocks.ACACIA_BUTTON)); public static final Item ACACIA_BUTTON = register(new BlockItem(builder(), Blocks.ACACIA_BUTTON));
public static final Item CHERRY_BUTTON = register(new BlockItem(builder(), Blocks.CHERRY_BUTTON)); public static final Item CHERRY_BUTTON = register(new BlockItem(builder(), Blocks.CHERRY_BUTTON));
public static final Item DARK_OAK_BUTTON = register(new BlockItem(builder(), Blocks.DARK_OAK_BUTTON)); public static final Item DARK_OAK_BUTTON = register(new BlockItem(builder(), Blocks.DARK_OAK_BUTTON));
public static final Item PALE_OAK_BUTTON = register(new BlockItem(builder(), Blocks.PALE_OAK_BUTTON));
public static final Item MANGROVE_BUTTON = register(new BlockItem(builder(), Blocks.MANGROVE_BUTTON)); public static final Item MANGROVE_BUTTON = register(new BlockItem(builder(), Blocks.MANGROVE_BUTTON));
public static final Item BAMBOO_BUTTON = register(new BlockItem(builder(), Blocks.BAMBOO_BUTTON)); public static final Item BAMBOO_BUTTON = register(new BlockItem(builder(), Blocks.BAMBOO_BUTTON));
public static final Item CRIMSON_BUTTON = register(new BlockItem(builder(), Blocks.CRIMSON_BUTTON)); public static final Item CRIMSON_BUTTON = register(new BlockItem(builder(), Blocks.CRIMSON_BUTTON));
@ -744,6 +791,7 @@ public final class Items {
public static final Item ACACIA_PRESSURE_PLATE = register(new BlockItem(builder(), Blocks.ACACIA_PRESSURE_PLATE)); public static final Item ACACIA_PRESSURE_PLATE = register(new BlockItem(builder(), Blocks.ACACIA_PRESSURE_PLATE));
public static final Item CHERRY_PRESSURE_PLATE = register(new BlockItem(builder(), Blocks.CHERRY_PRESSURE_PLATE)); public static final Item CHERRY_PRESSURE_PLATE = register(new BlockItem(builder(), Blocks.CHERRY_PRESSURE_PLATE));
public static final Item DARK_OAK_PRESSURE_PLATE = register(new BlockItem(builder(), Blocks.DARK_OAK_PRESSURE_PLATE)); public static final Item DARK_OAK_PRESSURE_PLATE = register(new BlockItem(builder(), Blocks.DARK_OAK_PRESSURE_PLATE));
public static final Item PALE_OAK_PRESSURE_PLATE = register(new BlockItem(builder(), Blocks.PALE_OAK_PRESSURE_PLATE));
public static final Item MANGROVE_PRESSURE_PLATE = register(new BlockItem(builder(), Blocks.MANGROVE_PRESSURE_PLATE)); public static final Item MANGROVE_PRESSURE_PLATE = register(new BlockItem(builder(), Blocks.MANGROVE_PRESSURE_PLATE));
public static final Item BAMBOO_PRESSURE_PLATE = register(new BlockItem(builder(), Blocks.BAMBOO_PRESSURE_PLATE)); public static final Item BAMBOO_PRESSURE_PLATE = register(new BlockItem(builder(), Blocks.BAMBOO_PRESSURE_PLATE));
public static final Item CRIMSON_PRESSURE_PLATE = register(new BlockItem(builder(), Blocks.CRIMSON_PRESSURE_PLATE)); public static final Item CRIMSON_PRESSURE_PLATE = register(new BlockItem(builder(), Blocks.CRIMSON_PRESSURE_PLATE));
@ -756,6 +804,7 @@ public final class Items {
public static final Item ACACIA_DOOR = register(new BlockItem(builder(), Blocks.ACACIA_DOOR)); public static final Item ACACIA_DOOR = register(new BlockItem(builder(), Blocks.ACACIA_DOOR));
public static final Item CHERRY_DOOR = register(new BlockItem(builder(), Blocks.CHERRY_DOOR)); public static final Item CHERRY_DOOR = register(new BlockItem(builder(), Blocks.CHERRY_DOOR));
public static final Item DARK_OAK_DOOR = register(new BlockItem(builder(), Blocks.DARK_OAK_DOOR)); public static final Item DARK_OAK_DOOR = register(new BlockItem(builder(), Blocks.DARK_OAK_DOOR));
public static final Item PALE_OAK_DOOR = register(new BlockItem(builder(), Blocks.PALE_OAK_DOOR));
public static final Item MANGROVE_DOOR = register(new BlockItem(builder(), Blocks.MANGROVE_DOOR)); public static final Item MANGROVE_DOOR = register(new BlockItem(builder(), Blocks.MANGROVE_DOOR));
public static final Item BAMBOO_DOOR = register(new BlockItem(builder(), Blocks.BAMBOO_DOOR)); public static final Item BAMBOO_DOOR = register(new BlockItem(builder(), Blocks.BAMBOO_DOOR));
public static final Item CRIMSON_DOOR = register(new BlockItem(builder(), Blocks.CRIMSON_DOOR)); public static final Item CRIMSON_DOOR = register(new BlockItem(builder(), Blocks.CRIMSON_DOOR));
@ -776,6 +825,7 @@ public final class Items {
public static final Item ACACIA_TRAPDOOR = register(new BlockItem(builder(), Blocks.ACACIA_TRAPDOOR)); public static final Item ACACIA_TRAPDOOR = register(new BlockItem(builder(), Blocks.ACACIA_TRAPDOOR));
public static final Item CHERRY_TRAPDOOR = register(new BlockItem(builder(), Blocks.CHERRY_TRAPDOOR)); public static final Item CHERRY_TRAPDOOR = register(new BlockItem(builder(), Blocks.CHERRY_TRAPDOOR));
public static final Item DARK_OAK_TRAPDOOR = register(new BlockItem(builder(), Blocks.DARK_OAK_TRAPDOOR)); public static final Item DARK_OAK_TRAPDOOR = register(new BlockItem(builder(), Blocks.DARK_OAK_TRAPDOOR));
public static final Item PALE_OAK_TRAPDOOR = register(new BlockItem(builder(), Blocks.PALE_OAK_TRAPDOOR));
public static final Item MANGROVE_TRAPDOOR = register(new BlockItem(builder(), Blocks.MANGROVE_TRAPDOOR)); public static final Item MANGROVE_TRAPDOOR = register(new BlockItem(builder(), Blocks.MANGROVE_TRAPDOOR));
public static final Item BAMBOO_TRAPDOOR = register(new BlockItem(builder(), Blocks.BAMBOO_TRAPDOOR)); public static final Item BAMBOO_TRAPDOOR = register(new BlockItem(builder(), Blocks.BAMBOO_TRAPDOOR));
public static final Item CRIMSON_TRAPDOOR = register(new BlockItem(builder(), Blocks.CRIMSON_TRAPDOOR)); public static final Item CRIMSON_TRAPDOOR = register(new BlockItem(builder(), Blocks.CRIMSON_TRAPDOOR));
@ -795,6 +845,7 @@ public final class Items {
public static final Item ACACIA_FENCE_GATE = register(new BlockItem(builder(), Blocks.ACACIA_FENCE_GATE)); public static final Item ACACIA_FENCE_GATE = register(new BlockItem(builder(), Blocks.ACACIA_FENCE_GATE));
public static final Item CHERRY_FENCE_GATE = register(new BlockItem(builder(), Blocks.CHERRY_FENCE_GATE)); public static final Item CHERRY_FENCE_GATE = register(new BlockItem(builder(), Blocks.CHERRY_FENCE_GATE));
public static final Item DARK_OAK_FENCE_GATE = register(new BlockItem(builder(), Blocks.DARK_OAK_FENCE_GATE)); public static final Item DARK_OAK_FENCE_GATE = register(new BlockItem(builder(), Blocks.DARK_OAK_FENCE_GATE));
public static final Item PALE_OAK_FENCE_GATE = register(new BlockItem(builder(), Blocks.PALE_OAK_FENCE_GATE));
public static final Item MANGROVE_FENCE_GATE = register(new BlockItem(builder(), Blocks.MANGROVE_FENCE_GATE)); public static final Item MANGROVE_FENCE_GATE = register(new BlockItem(builder(), Blocks.MANGROVE_FENCE_GATE));
public static final Item BAMBOO_FENCE_GATE = register(new BlockItem(builder(), Blocks.BAMBOO_FENCE_GATE)); public static final Item BAMBOO_FENCE_GATE = register(new BlockItem(builder(), Blocks.BAMBOO_FENCE_GATE));
public static final Item CRIMSON_FENCE_GATE = register(new BlockItem(builder(), Blocks.CRIMSON_FENCE_GATE)); public static final Item CRIMSON_FENCE_GATE = register(new BlockItem(builder(), Blocks.CRIMSON_FENCE_GATE));
@ -811,7 +862,8 @@ public final class Items {
public static final Item HOPPER_MINECART = register(new Item("hopper_minecart", builder().stackSize(1))); public static final Item HOPPER_MINECART = register(new Item("hopper_minecart", builder().stackSize(1)));
public static final Item CARROT_ON_A_STICK = register(new Item("carrot_on_a_stick", builder().stackSize(1).maxDamage(25))); public static final Item CARROT_ON_A_STICK = register(new Item("carrot_on_a_stick", builder().stackSize(1).maxDamage(25)));
public static final Item WARPED_FUNGUS_ON_A_STICK = register(new Item("warped_fungus_on_a_stick", builder().stackSize(1).maxDamage(100))); public static final Item WARPED_FUNGUS_ON_A_STICK = register(new Item("warped_fungus_on_a_stick", builder().stackSize(1).maxDamage(100)));
public static final Item ELYTRA = register(new ElytraItem("elytra", builder().stackSize(1).maxDamage(432).rarity(Rarity.UNCOMMON))); public static final Item PHANTOM_MEMBRANE = register(new Item("phantom_membrane", builder()));
public static final Item ELYTRA = register(new ElytraItem("elytra", builder().stackSize(1).maxDamage(432)));
public static final Item OAK_BOAT = register(new BoatItem("oak_boat", builder().stackSize(1))); public static final Item OAK_BOAT = register(new BoatItem("oak_boat", builder().stackSize(1)));
public static final Item OAK_CHEST_BOAT = register(new BoatItem("oak_chest_boat", builder().stackSize(1))); public static final Item OAK_CHEST_BOAT = register(new BoatItem("oak_chest_boat", builder().stackSize(1)));
public static final Item SPRUCE_BOAT = register(new BoatItem("spruce_boat", builder().stackSize(1))); public static final Item SPRUCE_BOAT = register(new BoatItem("spruce_boat", builder().stackSize(1)));
@ -826,12 +878,14 @@ public final class Items {
public static final Item CHERRY_CHEST_BOAT = register(new BoatItem("cherry_chest_boat", builder().stackSize(1))); public static final Item CHERRY_CHEST_BOAT = register(new BoatItem("cherry_chest_boat", builder().stackSize(1)));
public static final Item DARK_OAK_BOAT = register(new BoatItem("dark_oak_boat", builder().stackSize(1))); public static final Item DARK_OAK_BOAT = register(new BoatItem("dark_oak_boat", builder().stackSize(1)));
public static final Item DARK_OAK_CHEST_BOAT = register(new BoatItem("dark_oak_chest_boat", builder().stackSize(1))); public static final Item DARK_OAK_CHEST_BOAT = register(new BoatItem("dark_oak_chest_boat", builder().stackSize(1)));
public static final Item PALE_OAK_BOAT = register(new BoatItem("pale_oak_boat", builder().stackSize(1)));
public static final Item PALE_OAK_CHEST_BOAT = register(new BoatItem("pale_oak_chest_boat", builder().stackSize(1)));
public static final Item MANGROVE_BOAT = register(new BoatItem("mangrove_boat", builder().stackSize(1))); public static final Item MANGROVE_BOAT = register(new BoatItem("mangrove_boat", builder().stackSize(1)));
public static final Item MANGROVE_CHEST_BOAT = register(new BoatItem("mangrove_chest_boat", builder().stackSize(1))); public static final Item MANGROVE_CHEST_BOAT = register(new BoatItem("mangrove_chest_boat", builder().stackSize(1)));
public static final Item BAMBOO_RAFT = register(new BoatItem("bamboo_raft", builder().stackSize(1))); public static final Item BAMBOO_RAFT = register(new BoatItem("bamboo_raft", builder().stackSize(1)));
public static final Item BAMBOO_CHEST_RAFT = register(new BoatItem("bamboo_chest_raft", builder().stackSize(1))); public static final Item BAMBOO_CHEST_RAFT = register(new BoatItem("bamboo_chest_raft", builder().stackSize(1)));
public static final Item STRUCTURE_BLOCK = register(new BlockItem(builder().rarity(Rarity.EPIC), Blocks.STRUCTURE_BLOCK)); public static final Item STRUCTURE_BLOCK = register(new BlockItem(builder(), Blocks.STRUCTURE_BLOCK));
public static final Item JIGSAW = register(new BlockItem(builder().rarity(Rarity.EPIC), Blocks.JIGSAW)); public static final Item JIGSAW = register(new BlockItem(builder(), Blocks.JIGSAW));
public static final Item TURTLE_HELMET = register(new ArmorItem("turtle_helmet", ArmorMaterial.TURTLE, builder().stackSize(1).maxDamage(275))); public static final Item TURTLE_HELMET = register(new ArmorItem("turtle_helmet", ArmorMaterial.TURTLE, builder().stackSize(1).maxDamage(275)));
public static final Item TURTLE_SCUTE = register(new Item("turtle_scute", builder())); public static final Item TURTLE_SCUTE = register(new Item("turtle_scute", builder()));
public static final Item ARMADILLO_SCUTE = register(new Item("armadillo_scute", builder())); public static final Item ARMADILLO_SCUTE = register(new Item("armadillo_scute", builder()));
@ -922,8 +976,8 @@ public final class Items {
public static final Item PORKCHOP = register(new Item("porkchop", builder())); public static final Item PORKCHOP = register(new Item("porkchop", builder()));
public static final Item COOKED_PORKCHOP = register(new Item("cooked_porkchop", builder())); public static final Item COOKED_PORKCHOP = register(new Item("cooked_porkchop", builder()));
public static final Item PAINTING = register(new Item("painting", builder())); public static final Item PAINTING = register(new Item("painting", builder()));
public static final Item GOLDEN_APPLE = register(new Item("golden_apple", builder().rarity(Rarity.RARE))); public static final Item GOLDEN_APPLE = register(new Item("golden_apple", builder()));
public static final Item ENCHANTED_GOLDEN_APPLE = register(new Item("enchanted_golden_apple", builder().rarity(Rarity.EPIC))); public static final Item ENCHANTED_GOLDEN_APPLE = register(new Item("enchanted_golden_apple", builder()));
public static final Item OAK_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.OAK_SIGN, Blocks.OAK_WALL_SIGN)); public static final Item OAK_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.OAK_SIGN, Blocks.OAK_WALL_SIGN));
public static final Item SPRUCE_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.SPRUCE_SIGN, Blocks.SPRUCE_WALL_SIGN)); public static final Item SPRUCE_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.SPRUCE_SIGN, Blocks.SPRUCE_WALL_SIGN));
public static final Item BIRCH_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.BIRCH_SIGN, Blocks.BIRCH_WALL_SIGN)); public static final Item BIRCH_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.BIRCH_SIGN, Blocks.BIRCH_WALL_SIGN));
@ -931,6 +985,7 @@ public final class Items {
public static final Item ACACIA_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.ACACIA_SIGN, Blocks.ACACIA_WALL_SIGN)); public static final Item ACACIA_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.ACACIA_SIGN, Blocks.ACACIA_WALL_SIGN));
public static final Item CHERRY_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.CHERRY_SIGN, Blocks.CHERRY_WALL_SIGN)); public static final Item CHERRY_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.CHERRY_SIGN, Blocks.CHERRY_WALL_SIGN));
public static final Item DARK_OAK_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.DARK_OAK_SIGN, Blocks.DARK_OAK_WALL_SIGN)); public static final Item DARK_OAK_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.DARK_OAK_SIGN, Blocks.DARK_OAK_WALL_SIGN));
public static final Item PALE_OAK_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.PALE_OAK_SIGN, Blocks.PALE_OAK_WALL_SIGN));
public static final Item MANGROVE_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.MANGROVE_SIGN, Blocks.MANGROVE_WALL_SIGN)); public static final Item MANGROVE_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.MANGROVE_SIGN, Blocks.MANGROVE_WALL_SIGN));
public static final Item BAMBOO_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.BAMBOO_SIGN, Blocks.BAMBOO_WALL_SIGN)); public static final Item BAMBOO_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.BAMBOO_SIGN, Blocks.BAMBOO_WALL_SIGN));
public static final Item CRIMSON_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.CRIMSON_SIGN, Blocks.CRIMSON_WALL_SIGN)); public static final Item CRIMSON_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.CRIMSON_SIGN, Blocks.CRIMSON_WALL_SIGN));
@ -942,6 +997,7 @@ public final class Items {
public static final Item ACACIA_HANGING_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.ACACIA_HANGING_SIGN, Blocks.ACACIA_WALL_HANGING_SIGN)); public static final Item ACACIA_HANGING_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.ACACIA_HANGING_SIGN, Blocks.ACACIA_WALL_HANGING_SIGN));
public static final Item CHERRY_HANGING_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.CHERRY_HANGING_SIGN, Blocks.CHERRY_WALL_HANGING_SIGN)); public static final Item CHERRY_HANGING_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.CHERRY_HANGING_SIGN, Blocks.CHERRY_WALL_HANGING_SIGN));
public static final Item DARK_OAK_HANGING_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.DARK_OAK_HANGING_SIGN, Blocks.DARK_OAK_WALL_HANGING_SIGN)); public static final Item DARK_OAK_HANGING_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.DARK_OAK_HANGING_SIGN, Blocks.DARK_OAK_WALL_HANGING_SIGN));
public static final Item PALE_OAK_HANGING_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.PALE_OAK_HANGING_SIGN, Blocks.PALE_OAK_WALL_HANGING_SIGN));
public static final Item MANGROVE_HANGING_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.MANGROVE_HANGING_SIGN, Blocks.MANGROVE_WALL_HANGING_SIGN)); public static final Item MANGROVE_HANGING_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.MANGROVE_HANGING_SIGN, Blocks.MANGROVE_WALL_HANGING_SIGN));
public static final Item BAMBOO_HANGING_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.BAMBOO_HANGING_SIGN, Blocks.BAMBOO_WALL_HANGING_SIGN)); public static final Item BAMBOO_HANGING_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.BAMBOO_HANGING_SIGN, Blocks.BAMBOO_WALL_HANGING_SIGN));
public static final Item CRIMSON_HANGING_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.CRIMSON_HANGING_SIGN, Blocks.CRIMSON_WALL_HANGING_SIGN)); public static final Item CRIMSON_HANGING_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.CRIMSON_HANGING_SIGN, Blocks.CRIMSON_WALL_HANGING_SIGN));
@ -969,6 +1025,22 @@ public final class Items {
public static final Item COMPASS = register(new CompassItem("compass", builder())); public static final Item COMPASS = register(new CompassItem("compass", builder()));
public static final Item RECOVERY_COMPASS = register(new Item("recovery_compass", builder())); public static final Item RECOVERY_COMPASS = register(new Item("recovery_compass", builder()));
public static final Item BUNDLE = register(new Item("bundle", builder().stackSize(1))); public static final Item BUNDLE = register(new Item("bundle", builder().stackSize(1)));
public static final Item WHITE_BUNDLE = register(new Item("white_bundle", builder().stackSize(1)));
public static final Item ORANGE_BUNDLE = register(new Item("orange_bundle", builder().stackSize(1)));
public static final Item MAGENTA_BUNDLE = register(new Item("magenta_bundle", builder().stackSize(1)));
public static final Item LIGHT_BLUE_BUNDLE = register(new Item("light_blue_bundle", builder().stackSize(1)));
public static final Item YELLOW_BUNDLE = register(new Item("yellow_bundle", builder().stackSize(1)));
public static final Item LIME_BUNDLE = register(new Item("lime_bundle", builder().stackSize(1)));
public static final Item PINK_BUNDLE = register(new Item("pink_bundle", builder().stackSize(1)));
public static final Item GRAY_BUNDLE = register(new Item("gray_bundle", builder().stackSize(1)));
public static final Item LIGHT_GRAY_BUNDLE = register(new Item("light_gray_bundle", builder().stackSize(1)));
public static final Item CYAN_BUNDLE = register(new Item("cyan_bundle", builder().stackSize(1)));
public static final Item PURPLE_BUNDLE = register(new Item("purple_bundle", builder().stackSize(1)));
public static final Item BLUE_BUNDLE = register(new Item("blue_bundle", builder().stackSize(1)));
public static final Item BROWN_BUNDLE = register(new Item("brown_bundle", builder().stackSize(1)));
public static final Item GREEN_BUNDLE = register(new Item("green_bundle", builder().stackSize(1)));
public static final Item RED_BUNDLE = register(new Item("red_bundle", builder().stackSize(1)));
public static final Item BLACK_BUNDLE = register(new Item("black_bundle", builder().stackSize(1)));
public static final Item FISHING_ROD = register(new FishingRodItem("fishing_rod", builder().stackSize(1).maxDamage(64))); public static final Item FISHING_ROD = register(new FishingRodItem("fishing_rod", builder().stackSize(1).maxDamage(64)));
public static final Item CLOCK = register(new Item("clock", builder())); public static final Item CLOCK = register(new Item("clock", builder()));
public static final Item SPYGLASS = register(new Item("spyglass", builder().stackSize(1))); public static final Item SPYGLASS = register(new Item("spyglass", builder().stackSize(1)));
@ -1036,14 +1108,14 @@ public final class Items {
public static final Item GHAST_TEAR = register(new Item("ghast_tear", builder())); public static final Item GHAST_TEAR = register(new Item("ghast_tear", builder()));
public static final Item GOLD_NUGGET = register(new Item("gold_nugget", builder())); public static final Item GOLD_NUGGET = register(new Item("gold_nugget", builder()));
public static final Item NETHER_WART = register(new BlockItem(builder(), Blocks.NETHER_WART)); public static final Item NETHER_WART = register(new BlockItem(builder(), Blocks.NETHER_WART));
public static final Item POTION = register(new PotionItem("potion", builder().stackSize(1)));
public static final Item GLASS_BOTTLE = register(new Item("glass_bottle", builder())); public static final Item GLASS_BOTTLE = register(new Item("glass_bottle", builder()));
public static final Item POTION = register(new PotionItem("potion", builder().stackSize(1)));
public static final Item SPIDER_EYE = register(new Item("spider_eye", builder())); public static final Item SPIDER_EYE = register(new Item("spider_eye", builder()));
public static final Item FERMENTED_SPIDER_EYE = register(new Item("fermented_spider_eye", builder())); public static final Item FERMENTED_SPIDER_EYE = register(new Item("fermented_spider_eye", builder()));
public static final Item BLAZE_POWDER = register(new Item("blaze_powder", builder())); public static final Item BLAZE_POWDER = register(new Item("blaze_powder", builder()));
public static final Item MAGMA_CREAM = register(new Item("magma_cream", builder())); public static final Item MAGMA_CREAM = register(new Item("magma_cream", builder()));
public static final Item BREWING_STAND = register(new BlockItem(builder(), Blocks.BREWING_STAND)); public static final Item BREWING_STAND = register(new BlockItem(builder(), Blocks.BREWING_STAND));
public static final Item CAULDRON = register(new BlockItem(builder(), Blocks.CAULDRON, Blocks.WATER_CAULDRON, Blocks.POWDER_SNOW_CAULDRON, Blocks.LAVA_CAULDRON)); public static final Item CAULDRON = register(new BlockItem(builder(), Blocks.CAULDRON, Blocks.LAVA_CAULDRON, Blocks.WATER_CAULDRON, Blocks.POWDER_SNOW_CAULDRON));
public static final Item ENDER_EYE = register(new Item("ender_eye", builder())); public static final Item ENDER_EYE = register(new Item("ender_eye", builder()));
public static final Item GLISTERING_MELON_SLICE = register(new Item("glistering_melon_slice", builder())); public static final Item GLISTERING_MELON_SLICE = register(new Item("glistering_melon_slice", builder()));
public static final Item ARMADILLO_SPAWN_EGG = register(new SpawnEggItem("armadillo_spawn_egg", builder())); public static final Item ARMADILLO_SPAWN_EGG = register(new SpawnEggItem("armadillo_spawn_egg", builder()));
@ -1122,16 +1194,18 @@ public final class Items {
public static final Item WITHER_SKELETON_SPAWN_EGG = register(new SpawnEggItem("wither_skeleton_spawn_egg", builder())); public static final Item WITHER_SKELETON_SPAWN_EGG = register(new SpawnEggItem("wither_skeleton_spawn_egg", builder()));
public static final Item WOLF_SPAWN_EGG = register(new SpawnEggItem("wolf_spawn_egg", builder())); public static final Item WOLF_SPAWN_EGG = register(new SpawnEggItem("wolf_spawn_egg", builder()));
public static final Item ZOGLIN_SPAWN_EGG = register(new SpawnEggItem("zoglin_spawn_egg", builder())); public static final Item ZOGLIN_SPAWN_EGG = register(new SpawnEggItem("zoglin_spawn_egg", builder()));
public static final Item CREAKING_SPAWN_EGG = register(new SpawnEggItem("creaking_spawn_egg", builder()));
public static final Item ZOMBIE_SPAWN_EGG = register(new SpawnEggItem("zombie_spawn_egg", builder())); public static final Item ZOMBIE_SPAWN_EGG = register(new SpawnEggItem("zombie_spawn_egg", builder()));
public static final Item ZOMBIE_HORSE_SPAWN_EGG = register(new SpawnEggItem("zombie_horse_spawn_egg", builder())); public static final Item ZOMBIE_HORSE_SPAWN_EGG = register(new SpawnEggItem("zombie_horse_spawn_egg", builder()));
public static final Item ZOMBIE_VILLAGER_SPAWN_EGG = register(new SpawnEggItem("zombie_villager_spawn_egg", builder())); public static final Item ZOMBIE_VILLAGER_SPAWN_EGG = register(new SpawnEggItem("zombie_villager_spawn_egg", builder()));
public static final Item ZOMBIFIED_PIGLIN_SPAWN_EGG = register(new SpawnEggItem("zombified_piglin_spawn_egg", builder())); public static final Item ZOMBIFIED_PIGLIN_SPAWN_EGG = register(new SpawnEggItem("zombified_piglin_spawn_egg", builder()));
public static final Item EXPERIENCE_BOTTLE = register(new Item("experience_bottle", builder().rarity(Rarity.UNCOMMON))); public static final Item EXPERIENCE_BOTTLE = register(new Item("experience_bottle", builder()));
public static final Item FIRE_CHARGE = register(new Item("fire_charge", builder())); public static final Item FIRE_CHARGE = register(new Item("fire_charge", builder()));
public static final Item WIND_CHARGE = register(new Item("wind_charge", builder())); public static final Item WIND_CHARGE = register(new Item("wind_charge", builder()));
public static final Item WRITABLE_BOOK = register(new WritableBookItem("writable_book", builder().stackSize(1))); public static final Item WRITABLE_BOOK = register(new WritableBookItem("writable_book", builder().stackSize(1)));
public static final Item WRITTEN_BOOK = register(new WrittenBookItem("written_book", builder().stackSize(16))); public static final Item WRITTEN_BOOK = register(new WrittenBookItem("written_book", builder().stackSize(16)));
public static final Item MACE = register(new MaceItem("mace", builder().stackSize(1).maxDamage(500).rarity(Rarity.EPIC))); public static final Item BREEZE_ROD = register(new Item("breeze_rod", builder()));
public static final Item MACE = register(new MaceItem("mace", builder().stackSize(1).maxDamage(500)));
public static final Item ITEM_FRAME = register(new Item("item_frame", builder())); public static final Item ITEM_FRAME = register(new Item("item_frame", builder()));
public static final Item GLOW_ITEM_FRAME = register(new Item("glow_item_frame", builder())); public static final Item GLOW_ITEM_FRAME = register(new Item("glow_item_frame", builder()));
public static final Item FLOWER_POT = register(new BlockItem(builder(), Blocks.FLOWER_POT)); public static final Item FLOWER_POT = register(new BlockItem(builder(), Blocks.FLOWER_POT));
@ -1141,18 +1215,18 @@ public final class Items {
public static final Item POISONOUS_POTATO = register(new Item("poisonous_potato", builder())); public static final Item POISONOUS_POTATO = register(new Item("poisonous_potato", builder()));
public static final Item MAP = register(new MapItem("map", builder())); public static final Item MAP = register(new MapItem("map", builder()));
public static final Item GOLDEN_CARROT = register(new Item("golden_carrot", builder())); public static final Item GOLDEN_CARROT = register(new Item("golden_carrot", builder()));
public static final Item SKELETON_SKULL = register(new BlockItem(builder().rarity(Rarity.UNCOMMON), Blocks.SKELETON_SKULL, Blocks.SKELETON_WALL_SKULL)); public static final Item SKELETON_SKULL = register(new BlockItem(builder(), Blocks.SKELETON_SKULL, Blocks.SKELETON_WALL_SKULL));
public static final Item WITHER_SKELETON_SKULL = register(new BlockItem(builder().rarity(Rarity.UNCOMMON), Blocks.WITHER_SKELETON_SKULL, Blocks.WITHER_SKELETON_WALL_SKULL)); public static final Item WITHER_SKELETON_SKULL = register(new BlockItem(builder(), Blocks.WITHER_SKELETON_SKULL, Blocks.WITHER_SKELETON_WALL_SKULL));
public static final Item PLAYER_HEAD = register(new PlayerHeadItem(builder().rarity(Rarity.UNCOMMON), Blocks.PLAYER_HEAD, Blocks.PLAYER_WALL_HEAD)); public static final Item PLAYER_HEAD = register(new PlayerHeadItem(builder(), Blocks.PLAYER_HEAD, Blocks.PLAYER_WALL_HEAD));
public static final Item ZOMBIE_HEAD = register(new BlockItem(builder().rarity(Rarity.UNCOMMON), Blocks.ZOMBIE_HEAD, Blocks.ZOMBIE_WALL_HEAD)); public static final Item ZOMBIE_HEAD = register(new BlockItem(builder(), Blocks.ZOMBIE_HEAD, Blocks.ZOMBIE_WALL_HEAD));
public static final Item CREEPER_HEAD = register(new BlockItem(builder().rarity(Rarity.UNCOMMON), Blocks.CREEPER_HEAD, Blocks.CREEPER_WALL_HEAD)); public static final Item CREEPER_HEAD = register(new BlockItem(builder(), Blocks.CREEPER_HEAD, Blocks.CREEPER_WALL_HEAD));
public static final Item DRAGON_HEAD = register(new BlockItem(builder().rarity(Rarity.UNCOMMON), Blocks.DRAGON_HEAD, Blocks.DRAGON_WALL_HEAD)); public static final Item DRAGON_HEAD = register(new BlockItem(builder(), Blocks.DRAGON_HEAD, Blocks.DRAGON_WALL_HEAD));
public static final Item PIGLIN_HEAD = register(new BlockItem(builder().rarity(Rarity.UNCOMMON), Blocks.PIGLIN_HEAD, Blocks.PIGLIN_WALL_HEAD)); public static final Item PIGLIN_HEAD = register(new BlockItem(builder(), Blocks.PIGLIN_HEAD, Blocks.PIGLIN_WALL_HEAD));
public static final Item NETHER_STAR = register(new Item("nether_star", builder().rarity(Rarity.UNCOMMON))); public static final Item NETHER_STAR = register(new Item("nether_star", builder()));
public static final Item PUMPKIN_PIE = register(new Item("pumpkin_pie", builder())); public static final Item PUMPKIN_PIE = register(new Item("pumpkin_pie", builder()));
public static final Item FIREWORK_ROCKET = register(new FireworkRocketItem("firework_rocket", builder())); public static final Item FIREWORK_ROCKET = register(new FireworkRocketItem("firework_rocket", builder()));
public static final Item FIREWORK_STAR = register(new FireworkStarItem("firework_star", builder())); public static final Item FIREWORK_STAR = register(new FireworkStarItem("firework_star", builder()));
public static final Item ENCHANTED_BOOK = register(new EnchantedBookItem("enchanted_book", builder().stackSize(1).rarity(Rarity.UNCOMMON))); public static final Item ENCHANTED_BOOK = register(new EnchantedBookItem("enchanted_book", builder().stackSize(1)));
public static final Item NETHER_BRICK = register(new Item("nether_brick", builder())); public static final Item NETHER_BRICK = register(new Item("nether_brick", builder()));
public static final Item PRISMARINE_SHARD = register(new Item("prismarine_shard", builder())); public static final Item PRISMARINE_SHARD = register(new Item("prismarine_shard", builder()));
public static final Item PRISMARINE_CRYSTALS = register(new Item("prismarine_crystals", builder())); public static final Item PRISMARINE_CRYSTALS = register(new Item("prismarine_crystals", builder()));
@ -1162,13 +1236,13 @@ public final class Items {
public static final Item RABBIT_FOOT = register(new Item("rabbit_foot", builder())); public static final Item RABBIT_FOOT = register(new Item("rabbit_foot", builder()));
public static final Item RABBIT_HIDE = register(new Item("rabbit_hide", builder())); public static final Item RABBIT_HIDE = register(new Item("rabbit_hide", builder()));
public static final Item ARMOR_STAND = register(new Item("armor_stand", builder().stackSize(16))); public static final Item ARMOR_STAND = register(new Item("armor_stand", builder().stackSize(16)));
public static final Item IRON_HORSE_ARMOR = register(new ArmorItem("iron_horse_armor", ArmorMaterial.IRON, builder().stackSize(1))); public static final Item IRON_HORSE_ARMOR = register(new Item("iron_horse_armor", builder().stackSize(1)));
public static final Item GOLDEN_HORSE_ARMOR = register(new ArmorItem("golden_horse_armor", ArmorMaterial.GOLD, builder().stackSize(1))); public static final Item GOLDEN_HORSE_ARMOR = register(new Item("golden_horse_armor", builder().stackSize(1)));
public static final Item DIAMOND_HORSE_ARMOR = register(new ArmorItem("diamond_horse_armor", ArmorMaterial.DIAMOND, builder().stackSize(1))); public static final Item DIAMOND_HORSE_ARMOR = register(new Item("diamond_horse_armor", builder().stackSize(1)));
public static final Item LEATHER_HORSE_ARMOR = register(new DyeableArmorItem("leather_horse_armor", ArmorMaterial.LEATHER, builder().stackSize(1))); public static final Item LEATHER_HORSE_ARMOR = register(new DyeableArmorItem("leather_horse_armor", ArmorMaterial.LEATHER, builder().stackSize(1)));
public static final Item LEAD = register(new Item("lead", builder())); public static final Item LEAD = register(new Item("lead", builder()));
public static final Item NAME_TAG = register(new Item("name_tag", builder())); public static final Item NAME_TAG = register(new Item("name_tag", builder()));
public static final Item COMMAND_BLOCK_MINECART = register(new Item("command_block_minecart", builder().stackSize(1).rarity(Rarity.EPIC))); public static final Item COMMAND_BLOCK_MINECART = register(new Item("command_block_minecart", builder().stackSize(1)));
public static final Item MUTTON = register(new Item("mutton", builder())); public static final Item MUTTON = register(new Item("mutton", builder()));
public static final Item COOKED_MUTTON = register(new Item("cooked_mutton", builder())); public static final Item COOKED_MUTTON = register(new Item("cooked_mutton", builder()));
public static final Item WHITE_BANNER = register(new BannerItem(builder().stackSize(16), Blocks.WHITE_BANNER, Blocks.WHITE_WALL_BANNER)); public static final Item WHITE_BANNER = register(new BannerItem(builder().stackSize(16), Blocks.WHITE_BANNER, Blocks.WHITE_WALL_BANNER));
@ -1187,7 +1261,7 @@ public final class Items {
public static final Item GREEN_BANNER = register(new BannerItem(builder().stackSize(16), Blocks.GREEN_BANNER, Blocks.GREEN_WALL_BANNER)); public static final Item GREEN_BANNER = register(new BannerItem(builder().stackSize(16), Blocks.GREEN_BANNER, Blocks.GREEN_WALL_BANNER));
public static final Item RED_BANNER = register(new BannerItem(builder().stackSize(16), Blocks.RED_BANNER, Blocks.RED_WALL_BANNER)); public static final Item RED_BANNER = register(new BannerItem(builder().stackSize(16), Blocks.RED_BANNER, Blocks.RED_WALL_BANNER));
public static final Item BLACK_BANNER = register(new BannerItem(builder().stackSize(16), Blocks.BLACK_BANNER, Blocks.BLACK_WALL_BANNER)); public static final Item BLACK_BANNER = register(new BannerItem(builder().stackSize(16), Blocks.BLACK_BANNER, Blocks.BLACK_WALL_BANNER));
public static final Item END_CRYSTAL = register(new Item("end_crystal", builder().rarity(Rarity.RARE))); public static final Item END_CRYSTAL = register(new Item("end_crystal", builder()));
public static final Item CHORUS_FRUIT = register(new Item("chorus_fruit", builder())); public static final Item CHORUS_FRUIT = register(new Item("chorus_fruit", builder()));
public static final Item POPPED_CHORUS_FRUIT = register(new Item("popped_chorus_fruit", builder())); public static final Item POPPED_CHORUS_FRUIT = register(new Item("popped_chorus_fruit", builder()));
public static final Item TORCHFLOWER_SEEDS = register(new BlockItem("torchflower_seeds", builder(), Blocks.TORCHFLOWER_CROP)); public static final Item TORCHFLOWER_SEEDS = register(new BlockItem("torchflower_seeds", builder(), Blocks.TORCHFLOWER_CROP));
@ -1195,52 +1269,53 @@ public final class Items {
public static final Item BEETROOT = register(new Item("beetroot", builder())); public static final Item BEETROOT = register(new Item("beetroot", builder()));
public static final Item BEETROOT_SEEDS = register(new BlockItem("beetroot_seeds", builder(), Blocks.BEETROOTS)); public static final Item BEETROOT_SEEDS = register(new BlockItem("beetroot_seeds", builder(), Blocks.BEETROOTS));
public static final Item BEETROOT_SOUP = register(new Item("beetroot_soup", builder().stackSize(1))); public static final Item BEETROOT_SOUP = register(new Item("beetroot_soup", builder().stackSize(1)));
public static final Item DRAGON_BREATH = register(new Item("dragon_breath", builder().rarity(Rarity.UNCOMMON))); public static final Item DRAGON_BREATH = register(new Item("dragon_breath", builder()));
public static final Item SPLASH_POTION = register(new PotionItem("splash_potion", builder().stackSize(1))); public static final Item SPLASH_POTION = register(new PotionItem("splash_potion", builder().stackSize(1)));
public static final Item SPECTRAL_ARROW = register(new Item("spectral_arrow", builder())); public static final Item SPECTRAL_ARROW = register(new Item("spectral_arrow", builder()));
public static final Item TIPPED_ARROW = register(new TippedArrowItem("tipped_arrow", builder())); public static final Item TIPPED_ARROW = register(new TippedArrowItem("tipped_arrow", builder()));
public static final Item LINGERING_POTION = register(new PotionItem("lingering_potion", builder().stackSize(1))); public static final Item LINGERING_POTION = register(new PotionItem("lingering_potion", builder().stackSize(1)));
public static final Item SHIELD = register(new ShieldItem("shield", builder().stackSize(1).maxDamage(336))); public static final Item SHIELD = register(new ShieldItem("shield", builder().stackSize(1).maxDamage(336)));
public static final Item TOTEM_OF_UNDYING = register(new Item("totem_of_undying", builder().stackSize(1).rarity(Rarity.UNCOMMON))); public static final Item TOTEM_OF_UNDYING = register(new Item("totem_of_undying", builder().stackSize(1)));
public static final Item SHULKER_SHELL = register(new Item("shulker_shell", builder())); public static final Item SHULKER_SHELL = register(new Item("shulker_shell", builder()));
public static final Item IRON_NUGGET = register(new Item("iron_nugget", builder())); public static final Item IRON_NUGGET = register(new Item("iron_nugget", builder()));
public static final Item KNOWLEDGE_BOOK = register(new Item("knowledge_book", builder().stackSize(1).rarity(Rarity.EPIC))); public static final Item KNOWLEDGE_BOOK = register(new Item("knowledge_book", builder().stackSize(1)));
public static final Item DEBUG_STICK = register(new Item("debug_stick", builder().stackSize(1).rarity(Rarity.EPIC).glint(true))); public static final Item DEBUG_STICK = register(new Item("debug_stick", builder().stackSize(1)));
public static final Item MUSIC_DISC_13 = register(new Item("music_disc_13", builder().stackSize(1).rarity(Rarity.RARE))); public static final Item MUSIC_DISC_13 = register(new Item("music_disc_13", builder().stackSize(1)));
public static final Item MUSIC_DISC_CAT = register(new Item("music_disc_cat", builder().stackSize(1).rarity(Rarity.RARE))); public static final Item MUSIC_DISC_CAT = register(new Item("music_disc_cat", builder().stackSize(1)));
public static final Item MUSIC_DISC_BLOCKS = register(new Item("music_disc_blocks", builder().stackSize(1).rarity(Rarity.RARE))); public static final Item MUSIC_DISC_BLOCKS = register(new Item("music_disc_blocks", builder().stackSize(1)));
public static final Item MUSIC_DISC_CHIRP = register(new Item("music_disc_chirp", builder().stackSize(1).rarity(Rarity.RARE))); public static final Item MUSIC_DISC_CHIRP = register(new Item("music_disc_chirp", builder().stackSize(1)));
public static final Item MUSIC_DISC_CREATOR = register(new Item("music_disc_creator", builder().stackSize(1).rarity(Rarity.RARE))); public static final Item MUSIC_DISC_CREATOR = register(new Item("music_disc_creator", builder().stackSize(1)));
public static final Item MUSIC_DISC_CREATOR_MUSIC_BOX = register(new Item("music_disc_creator_music_box", builder().stackSize(1).rarity(Rarity.RARE))); public static final Item MUSIC_DISC_CREATOR_MUSIC_BOX = register(new Item("music_disc_creator_music_box", builder().stackSize(1)));
public static final Item MUSIC_DISC_FAR = register(new Item("music_disc_far", builder().stackSize(1).rarity(Rarity.RARE))); public static final Item MUSIC_DISC_FAR = register(new Item("music_disc_far", builder().stackSize(1)));
public static final Item MUSIC_DISC_MALL = register(new Item("music_disc_mall", builder().stackSize(1).rarity(Rarity.RARE))); public static final Item MUSIC_DISC_MALL = register(new Item("music_disc_mall", builder().stackSize(1)));
public static final Item MUSIC_DISC_MELLOHI = register(new Item("music_disc_mellohi", builder().stackSize(1).rarity(Rarity.RARE))); public static final Item MUSIC_DISC_MELLOHI = register(new Item("music_disc_mellohi", builder().stackSize(1)));
public static final Item MUSIC_DISC_STAL = register(new Item("music_disc_stal", builder().stackSize(1).rarity(Rarity.RARE))); public static final Item MUSIC_DISC_STAL = register(new Item("music_disc_stal", builder().stackSize(1)));
public static final Item MUSIC_DISC_STRAD = register(new Item("music_disc_strad", builder().stackSize(1).rarity(Rarity.RARE))); public static final Item MUSIC_DISC_STRAD = register(new Item("music_disc_strad", builder().stackSize(1)));
public static final Item MUSIC_DISC_WARD = register(new Item("music_disc_ward", builder().stackSize(1).rarity(Rarity.RARE))); public static final Item MUSIC_DISC_WARD = register(new Item("music_disc_ward", builder().stackSize(1)));
public static final Item MUSIC_DISC_11 = register(new Item("music_disc_11", builder().stackSize(1).rarity(Rarity.RARE))); public static final Item MUSIC_DISC_11 = register(new Item("music_disc_11", builder().stackSize(1)));
public static final Item MUSIC_DISC_WAIT = register(new Item("music_disc_wait", builder().stackSize(1).rarity(Rarity.RARE))); public static final Item MUSIC_DISC_WAIT = register(new Item("music_disc_wait", builder().stackSize(1)));
public static final Item MUSIC_DISC_OTHERSIDE = register(new Item("music_disc_otherside", builder().stackSize(1).rarity(Rarity.RARE))); public static final Item MUSIC_DISC_OTHERSIDE = register(new Item("music_disc_otherside", builder().stackSize(1)));
public static final Item MUSIC_DISC_RELIC = register(new Item("music_disc_relic", builder().stackSize(1).rarity(Rarity.RARE))); public static final Item MUSIC_DISC_RELIC = register(new Item("music_disc_relic", builder().stackSize(1)));
public static final Item MUSIC_DISC_5 = register(new Item("music_disc_5", builder().stackSize(1).rarity(Rarity.RARE))); public static final Item MUSIC_DISC_5 = register(new Item("music_disc_5", builder().stackSize(1)));
public static final Item MUSIC_DISC_PIGSTEP = register(new Item("music_disc_pigstep", builder().stackSize(1).rarity(Rarity.RARE))); public static final Item MUSIC_DISC_PIGSTEP = register(new Item("music_disc_pigstep", builder().stackSize(1)));
public static final Item MUSIC_DISC_PRECIPICE = register(new Item("music_disc_precipice", builder().stackSize(1).rarity(Rarity.RARE))); public static final Item MUSIC_DISC_PRECIPICE = register(new Item("music_disc_precipice", builder().stackSize(1)));
public static final Item DISC_FRAGMENT_5 = register(new Item("disc_fragment_5", builder())); public static final Item DISC_FRAGMENT_5 = register(new Item("disc_fragment_5", builder()));
public static final Item TRIDENT = register(new Item("trident", builder().stackSize(1).maxDamage(250).attackDamage(9.0).rarity(Rarity.EPIC))); public static final Item TRIDENT = register(new Item("trident", builder().stackSize(1).maxDamage(250).attackDamage(9.0)));
public static final Item PHANTOM_MEMBRANE = register(new Item("phantom_membrane", builder()));
public static final Item NAUTILUS_SHELL = register(new Item("nautilus_shell", builder())); public static final Item NAUTILUS_SHELL = register(new Item("nautilus_shell", builder()));
public static final Item HEART_OF_THE_SEA = register(new Item("heart_of_the_sea", builder().rarity(Rarity.UNCOMMON))); public static final Item HEART_OF_THE_SEA = register(new Item("heart_of_the_sea", builder()));
public static final Item CROSSBOW = register(new CrossbowItem("crossbow", builder().stackSize(1).maxDamage(465))); public static final Item CROSSBOW = register(new CrossbowItem("crossbow", builder().stackSize(1).maxDamage(465)));
public static final Item SUSPICIOUS_STEW = register(new Item("suspicious_stew", builder().stackSize(1))); public static final Item SUSPICIOUS_STEW = register(new Item("suspicious_stew", builder().stackSize(1)));
public static final Item LOOM = register(new BlockItem(builder(), Blocks.LOOM)); public static final Item LOOM = register(new BlockItem(builder(), Blocks.LOOM));
public static final Item FLOWER_BANNER_PATTERN = register(new Item("flower_banner_pattern", builder().stackSize(1))); public static final Item FLOWER_BANNER_PATTERN = register(new Item("flower_banner_pattern", builder().stackSize(1)));
public static final Item CREEPER_BANNER_PATTERN = register(new Item("creeper_banner_pattern", builder().stackSize(1).rarity(Rarity.UNCOMMON))); public static final Item CREEPER_BANNER_PATTERN = register(new Item("creeper_banner_pattern", builder().stackSize(1)));
public static final Item SKULL_BANNER_PATTERN = register(new Item("skull_banner_pattern", builder().stackSize(1).rarity(Rarity.UNCOMMON))); public static final Item SKULL_BANNER_PATTERN = register(new Item("skull_banner_pattern", builder().stackSize(1)));
public static final Item MOJANG_BANNER_PATTERN = register(new Item("mojang_banner_pattern", builder().stackSize(1).rarity(Rarity.EPIC))); public static final Item MOJANG_BANNER_PATTERN = register(new Item("mojang_banner_pattern", builder().stackSize(1)));
public static final Item GLOBE_BANNER_PATTERN = register(new Item("globe_banner_pattern", builder().stackSize(1))); public static final Item GLOBE_BANNER_PATTERN = register(new Item("globe_banner_pattern", builder().stackSize(1)));
public static final Item PIGLIN_BANNER_PATTERN = register(new Item("piglin_banner_pattern", builder().stackSize(1).rarity(Rarity.UNCOMMON))); public static final Item PIGLIN_BANNER_PATTERN = register(new Item("piglin_banner_pattern", builder().stackSize(1)));
public static final Item FLOW_BANNER_PATTERN = register(new Item("flow_banner_pattern", builder().stackSize(1).rarity(Rarity.RARE))); public static final Item FLOW_BANNER_PATTERN = register(new Item("flow_banner_pattern", builder().stackSize(1)));
public static final Item GUSTER_BANNER_PATTERN = register(new Item("guster_banner_pattern", builder().stackSize(1).rarity(Rarity.RARE))); public static final Item GUSTER_BANNER_PATTERN = register(new Item("guster_banner_pattern", builder().stackSize(1)));
public static final Item FIELD_MASONED_BANNER_PATTERN = register(new Item("field_masoned_banner_pattern", builder().stackSize(1)));
public static final Item BORDURE_INDENTED_BANNER_PATTERN = register(new Item("bordure_indented_banner_pattern", builder().stackSize(1)));
public static final Item GOAT_HORN = register(new GoatHornItem("goat_horn", builder().stackSize(1))); public static final Item GOAT_HORN = register(new GoatHornItem("goat_horn", builder().stackSize(1)));
public static final Item COMPOSTER = register(new BlockItem(builder(), Blocks.COMPOSTER)); public static final Item COMPOSTER = register(new BlockItem(builder(), Blocks.COMPOSTER));
public static final Item BARREL = register(new BlockItem(builder(), Blocks.BARREL)); public static final Item BARREL = register(new BlockItem(builder(), Blocks.BARREL));
@ -1370,7 +1445,6 @@ public final class Items {
public static final Item OMINOUS_TRIAL_KEY = register(new Item("ominous_trial_key", builder())); public static final Item OMINOUS_TRIAL_KEY = register(new Item("ominous_trial_key", builder()));
public static final Item VAULT = register(new BlockItem(builder(), Blocks.VAULT)); public static final Item VAULT = register(new BlockItem(builder(), Blocks.VAULT));
public static final Item OMINOUS_BOTTLE = register(new OminousBottleItem("ominous_bottle", builder())); public static final Item OMINOUS_BOTTLE = register(new OminousBottleItem("ominous_bottle", builder()));
public static final Item BREEZE_ROD = register(new Item("breeze_rod", builder()));
public static final int AIR_ID = AIR.javaId(); public static final int AIR_ID = AIR.javaId();

Datei anzeigen

@ -25,52 +25,47 @@
package org.geysermc.geyser.item.enchantment; package org.geysermc.geyser.item.enchantment;
import it.unimi.dsi.fastutil.ints.IntArrays;
import net.kyori.adventure.key.Key;
import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.Nullable;
import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMap;
import org.geysermc.geyser.inventory.item.BedrockEnchantment; import org.geysermc.geyser.inventory.item.BedrockEnchantment;
import org.geysermc.geyser.item.Items; import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.item.type.Item;
import org.geysermc.geyser.registry.Registries; import org.geysermc.geyser.registry.Registries;
import org.geysermc.geyser.session.cache.registry.JavaRegistries;
import org.geysermc.geyser.session.cache.registry.RegistryEntryContext; import org.geysermc.geyser.session.cache.registry.RegistryEntryContext;
import org.geysermc.geyser.session.cache.tags.GeyserHolderSet;
import org.geysermc.geyser.translator.text.MessageTranslator; import org.geysermc.geyser.translator.text.MessageTranslator;
import org.geysermc.geyser.util.MinecraftKey;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.HolderSet;
import java.util.HashSet; import java.util.HashSet;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.function.ToIntFunction;
/** /**
* @param description only populated if {@link #bedrockEnchantment()} is not null. * @param description only populated if {@link #bedrockEnchantment()} is null.
* @param anvilCost also as a rarity multiplier * @param anvilCost also as a rarity multiplier
*/ */
public record Enchantment(String identifier, public record Enchantment(String identifier,
Set<EnchantmentComponent> effects, Set<EnchantmentComponent> effects,
HolderSet supportedItems, GeyserHolderSet<Item> supportedItems,
int maxLevel, int maxLevel,
String description, String description,
int anvilCost, int anvilCost,
HolderSet exclusiveSet, GeyserHolderSet<Enchantment> exclusiveSet,
@Nullable BedrockEnchantment bedrockEnchantment) { @Nullable BedrockEnchantment bedrockEnchantment) {
public static Enchantment read(RegistryEntryContext context) { public static Enchantment read(RegistryEntryContext context) {
NbtMap data = context.data(); NbtMap data = context.data();
Set<EnchantmentComponent> effects = readEnchantmentComponents(data.getCompound("effects")); Set<EnchantmentComponent> effects = readEnchantmentComponents(data.getCompound("effects"));
HolderSet supportedItems = readHolderSet(data.get("supported_items"), itemId -> Registries.JAVA_ITEM_IDENTIFIERS.getOrDefault(itemId.asString(), Items.AIR).javaId()); GeyserHolderSet<Item> supportedItems = GeyserHolderSet.readHolderSet(context.session(), JavaRegistries.ITEM, data.get("supported_items"), itemId -> Registries.JAVA_ITEM_IDENTIFIERS.getOrDefault(itemId.asString(), Items.AIR).javaId());
int maxLevel = data.getInt("max_level"); int maxLevel = data.getInt("max_level");
int anvilCost = data.getInt("anvil_cost"); int anvilCost = data.getInt("anvil_cost");
HolderSet exclusiveSet = readHolderSet(data.getOrDefault("exclusive_set", null), context::getNetworkId); GeyserHolderSet<Enchantment> exclusiveSet = GeyserHolderSet.readHolderSet(context.session(), JavaRegistries.ENCHANTMENT, data.get("exclusive_set"), context::getNetworkId);
BedrockEnchantment bedrockEnchantment = BedrockEnchantment.getByJavaIdentifier(context.id().asString()); BedrockEnchantment bedrockEnchantment = BedrockEnchantment.getByJavaIdentifier(context.id().asString());
// TODO - description is a component. So if a hardcoded literal string is given, this will display normally on Java,
// but Geyser will attempt to lookup the literal string as translation - and will fail, displaying an empty string as enchantment name.
String description = bedrockEnchantment == null ? MessageTranslator.deserializeDescription(context.session(), data) : null; String description = bedrockEnchantment == null ? MessageTranslator.deserializeDescription(context.session(), data) : null;
return new Enchantment(context.id().asString(), effects, supportedItems, maxLevel, return new Enchantment(context.id().asString(), effects, supportedItems, maxLevel,
@ -86,24 +81,4 @@ public record Enchantment(String identifier,
} }
return Set.copyOf(components); // Also ensures any empty sets are consolidated return Set.copyOf(components); // Also ensures any empty sets are consolidated
} }
// TODO holder set util?
private static HolderSet readHolderSet(@Nullable Object holderSet, ToIntFunction<Key> keyIdMapping) {
if (holderSet == null) {
return new HolderSet(IntArrays.EMPTY_ARRAY);
}
if (holderSet instanceof String stringTag) {
// Tag
if (stringTag.startsWith("#")) {
return new HolderSet(MinecraftKey.key(stringTag.substring(1))); // Remove '#' at beginning that indicates tag
} else {
return new HolderSet(new int[]{keyIdMapping.applyAsInt(MinecraftKey.key(stringTag))});
}
} else if (holderSet instanceof List<?> list) {
// Assume the list is a list of strings
return new HolderSet(list.stream().map(o -> (String) o).map(Key::key).mapToInt(keyIdMapping).toArray());
}
throw new IllegalArgumentException("Holder set must either be a tag, a string ID or a list of string IDs");
}
} }

Datei anzeigen

@ -32,6 +32,7 @@ import org.geysermc.geyser.inventory.item.Potion;
import org.geysermc.geyser.item.Items; import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.registry.type.ItemMappings; import org.geysermc.geyser.registry.type.ItemMappings;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType; import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.PotionContents; import org.geysermc.mcprotocollib.protocol.data.game.item.component.PotionContents;
@ -41,9 +42,9 @@ public class ArrowItem extends Item {
} }
@Override @Override
public @NonNull GeyserItemStack translateToJava(@NonNull ItemData itemData, @NonNull ItemMapping mapping, @NonNull ItemMappings mappings) { public @NonNull GeyserItemStack translateToJava(GeyserSession session, @NonNull ItemData itemData, @NonNull ItemMapping mapping, @NonNull ItemMappings mappings) {
Potion potion = Potion.getByTippedArrowDamage(itemData.getDamage()); Potion potion = Potion.getByTippedArrowDamage(itemData.getDamage());
GeyserItemStack itemStack = super.translateToJava(itemData, mapping, mappings); GeyserItemStack itemStack = super.translateToJava(session, itemData, mapping, mappings);
if (potion != null) { if (potion != null) {
itemStack = Items.TIPPED_ARROW.newItemStack(itemStack.getAmount(), itemStack.getComponents()); itemStack = Items.TIPPED_ARROW.newItemStack(itemStack.getAmount(), itemStack.getComponents());
PotionContents contents = potion.toComponent(); PotionContents contents = potion.toComponent();

Datei anzeigen

@ -43,11 +43,11 @@ public class CompassItem extends Item {
} }
@Override @Override
public ItemData.Builder translateToBedrock(int count, DataComponents components, ItemMapping mapping, ItemMappings mappings) { public ItemData.Builder translateToBedrock(GeyserSession session, int count, DataComponents components, ItemMapping mapping, ItemMappings mappings) {
if (isLodestoneCompass(components)) { if (isLodestoneCompass(components)) {
return super.translateToBedrock(count, components, mappings.getLodestoneCompass(), mappings); return super.translateToBedrock(session, count, components, mappings.getLodestoneCompass(), mappings);
} }
return super.translateToBedrock(count, components, mapping, mappings); return super.translateToBedrock(session, count, components, mapping, mappings);
} }
@Override @Override
@ -78,12 +78,12 @@ public class CompassItem extends Item {
} }
@Override @Override
public @NonNull GeyserItemStack translateToJava(@NonNull ItemData itemData, @NonNull ItemMapping mapping, @NonNull ItemMappings mappings) { public @NonNull GeyserItemStack translateToJava(GeyserSession session, @NonNull ItemData itemData, @NonNull ItemMapping mapping, @NonNull ItemMappings mappings) {
if (mapping.getBedrockIdentifier().equals("minecraft:lodestone_compass")) { if (mapping.getBedrockIdentifier().equals("minecraft:lodestone_compass")) {
// Revert the entry back to the compass // Revert the entry back to the compass
mapping = mappings.getStoredItems().compass(); mapping = mappings.getStoredItems().compass();
} }
return super.translateToJava(itemData, mapping, mappings); return super.translateToJava(session, itemData, mapping, mappings);
} }
} }

Datei anzeigen

@ -28,6 +28,7 @@ package org.geysermc.geyser.item.type;
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.registry.type.ItemMappings; import org.geysermc.geyser.registry.type.ItemMappings;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType; import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents; import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents;
@ -37,8 +38,8 @@ public class FilledMapItem extends MapItem {
} }
@Override @Override
public ItemData.Builder translateToBedrock(int count, DataComponents components, ItemMapping mapping, ItemMappings mappings) { public ItemData.Builder translateToBedrock(GeyserSession session, int count, DataComponents components, ItemMapping mapping, ItemMappings mappings) {
ItemData.Builder builder = super.translateToBedrock(count, components, mapping, mappings); ItemData.Builder builder = super.translateToBedrock(session, count, components, mapping, mappings);
if (components == null) { if (components == null) {
// This is a fallback for maps with no nbt (Change added back in June 2020; is it needed in 2023?) // This is a fallback for maps with no nbt (Change added back in June 2020; is it needed in 2023?)
//return builder.tag(NbtMap.builder().putInt("map", 0).build()); TODO if this is *still* broken, let's move it to translateComponentsToBedrock //return builder.tag(NbtMap.builder().putInt("map", 0).build()); TODO if this is *still* broken, let's move it to translateComponentsToBedrock

Datei anzeigen

@ -28,8 +28,11 @@ package org.geysermc.geyser.item.type;
import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.NonNull;
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
import org.geysermc.geyser.inventory.GeyserItemStack; import org.geysermc.geyser.inventory.GeyserItemStack;
import org.geysermc.geyser.inventory.item.GeyserInstrument;
import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.registry.type.ItemMappings; import org.geysermc.geyser.registry.type.ItemMappings;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.item.BedrockItemBuilder;
import org.geysermc.mcprotocollib.protocol.data.game.Holder; import org.geysermc.mcprotocollib.protocol.data.game.Holder;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType; import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents; import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents;
@ -41,24 +44,45 @@ public class GoatHornItem extends Item {
} }
@Override @Override
public ItemData.Builder translateToBedrock(int count, DataComponents components, ItemMapping mapping, ItemMappings mappings) { public ItemData.Builder translateToBedrock(GeyserSession session, int count, DataComponents components, ItemMapping mapping, ItemMappings mappings) {
ItemData.Builder builder = super.translateToBedrock(count, components, mapping, mappings); ItemData.Builder builder = super.translateToBedrock(session, count, components, mapping, mappings);
if (components == null) { if (components == null) {
return builder; return builder;
} }
Holder<Instrument> instrument = components.get(DataComponentType.INSTRUMENT);
if (instrument != null && instrument.isId()) { Holder<Instrument> holder = components.get(DataComponentType.INSTRUMENT);
builder.damage(instrument.id()); if (holder != null) {
GeyserInstrument instrument = GeyserInstrument.fromHolder(session, holder);
int bedrockId = instrument.bedrockId();
if (bedrockId >= 0) {
builder.damage(bedrockId);
}
} }
return builder; return builder;
} }
@Override @Override
public @NonNull GeyserItemStack translateToJava(@NonNull ItemData itemData, @NonNull ItemMapping mapping, @NonNull ItemMappings mappings) { public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull BedrockItemBuilder builder) {
GeyserItemStack itemStack = super.translateToJava(itemData, mapping, mappings); super.translateComponentsToBedrock(session, components, builder);
Holder<Instrument> holder = components.get(DataComponentType.INSTRUMENT);
if (holder != null && components.get(DataComponentType.HIDE_TOOLTIP) == null
&& components.get(DataComponentType.HIDE_ADDITIONAL_TOOLTIP) == null) {
GeyserInstrument instrument = GeyserInstrument.fromHolder(session, holder);
if (instrument.bedrockInstrument() == null) {
builder.getOrCreateLore().add(instrument.description());
}
}
}
@Override
public @NonNull GeyserItemStack translateToJava(GeyserSession session, @NonNull ItemData itemData, @NonNull ItemMapping mapping, @NonNull ItemMappings mappings) {
GeyserItemStack itemStack = super.translateToJava(session, itemData, mapping, mappings);
int damage = itemData.getDamage(); int damage = itemData.getDamage();
itemStack.getOrCreateComponents().put(DataComponentType.INSTRUMENT, Holder.ofId(damage)); // This could cause an issue since -1 is returned for non-vanilla goat horns
itemStack.getOrCreateComponents().put(DataComponentType.INSTRUMENT, Holder.ofId(GeyserInstrument.bedrockIdToJava(session, damage)));
return itemStack; return itemStack;
} }

Datei anzeigen

@ -115,7 +115,7 @@ public class Item {
/* Translation methods to Bedrock and back */ /* Translation methods to Bedrock and back */
public ItemData.Builder translateToBedrock(int count, DataComponents components, ItemMapping mapping, ItemMappings mappings) { public ItemData.Builder translateToBedrock(GeyserSession session, int count, DataComponents components, ItemMapping mapping, ItemMappings mappings) {
if (this == Items.AIR || count <= 0) { if (this == Items.AIR || count <= 0) {
// Return, essentially, air // Return, essentially, air
return ItemData.builder(); return ItemData.builder();
@ -130,7 +130,7 @@ public class Item {
return builder; return builder;
} }
public @NonNull GeyserItemStack translateToJava(@NonNull ItemData itemData, @NonNull ItemMapping mapping, @NonNull ItemMappings mappings) { public @NonNull GeyserItemStack translateToJava(GeyserSession session, @NonNull ItemData itemData, @NonNull ItemMapping mapping, @NonNull ItemMappings mappings) {
return GeyserItemStack.of(javaId, itemData.getCount()); return GeyserItemStack.of(javaId, itemData.getCount());
} }

Datei anzeigen

@ -0,0 +1,79 @@
/*
* Copyright (c) 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.item.type;
import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition;
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
import org.geysermc.geyser.level.block.property.Properties;
import org.geysermc.geyser.level.block.type.Block;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.registry.type.ItemMappings;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.BlockStateProperties;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents;
public class LightItem extends BlockItem {
public LightItem(Builder builder, Block block, Block... otherBlocks) {
super(builder, block, otherBlocks);
}
@Override
public ItemData.Builder translateToBedrock(GeyserSession session, int count, DataComponents components, ItemMapping mapping, ItemMappings mappings) {
ItemMapping lightLevelMapping = getLightLevelMapping(components, mappings);
if (lightLevelMapping != null) {
return super.translateToBedrock(session, count, components, lightLevelMapping, mappings);
}
return super.translateToBedrock(session, count, components, mapping, mappings);
}
@Override
public ItemMapping toBedrockDefinition(DataComponents components, ItemMappings mappings) {
ItemMapping lightLevelMapping = getLightLevelMapping(components, mappings);
if (lightLevelMapping != null) {
return lightLevelMapping;
}
return super.toBedrockDefinition(components, mappings);
}
private static ItemMapping getLightLevelMapping(DataComponents components, ItemMappings mappings) {
String lightLevel = "15";
if (components != null) {
BlockStateProperties blockStateProperties = components.get(DataComponentType.BLOCK_STATE);
if (blockStateProperties != null) {
lightLevel = blockStateProperties.getProperties().get(Properties.LEVEL.name());
}
}
ItemDefinition definition = mappings.getDefinition("minecraft:light_block_" + lightLevel);
if (definition != null) {
return mappings.getLightBlocks().get(definition.getRuntimeId());
}
return null;
}
}

Datei anzeigen

@ -31,6 +31,7 @@ import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
import org.geysermc.geyser.inventory.GeyserItemStack; import org.geysermc.geyser.inventory.GeyserItemStack;
import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.registry.type.ItemMappings; import org.geysermc.geyser.registry.type.ItemMappings;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType; import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents; import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents;
@ -40,8 +41,8 @@ public class OminousBottleItem extends Item {
} }
@Override @Override
public ItemData.Builder translateToBedrock(int count, @Nullable DataComponents components, ItemMapping mapping, ItemMappings mappings) { public ItemData.Builder translateToBedrock(GeyserSession session, int count, @Nullable DataComponents components, ItemMapping mapping, ItemMappings mappings) {
var builder = super.translateToBedrock(count, components, mapping, mappings); var builder = super.translateToBedrock(session, count, components, mapping, mappings);
if (components == null) { if (components == null) {
// Level 1 ominous bottle is null components - Java 1.21. // Level 1 ominous bottle is null components - Java 1.21.
return builder; return builder;
@ -54,9 +55,9 @@ public class OminousBottleItem extends Item {
} }
@Override @Override
public @NonNull GeyserItemStack translateToJava(@NonNull ItemData itemData, @NonNull ItemMapping mapping, @NonNull ItemMappings mappings) { public @NonNull GeyserItemStack translateToJava(GeyserSession session, @NonNull ItemData itemData, @NonNull ItemMapping mapping, @NonNull ItemMappings mappings) {
// This item can be pulled from the creative inventory with amplifiers. // This item can be pulled from the creative inventory with amplifiers.
GeyserItemStack itemStack = super.translateToJava(itemData, mapping, mappings); GeyserItemStack itemStack = super.translateToJava(session, itemData, mapping, mappings);
int damage = itemData.getDamage(); int damage = itemData.getDamage();
if (damage == 0) { if (damage == 0) {
return itemStack; return itemStack;

Datei anzeigen

@ -33,6 +33,7 @@ import org.geysermc.geyser.inventory.GeyserItemStack;
import org.geysermc.geyser.inventory.item.Potion; import org.geysermc.geyser.inventory.item.Potion;
import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.registry.type.ItemMappings; import org.geysermc.geyser.registry.type.ItemMappings;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.item.CustomItemTranslator; import org.geysermc.geyser.translator.item.CustomItemTranslator;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType; import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents; import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents;
@ -44,8 +45,8 @@ public class PotionItem extends Item {
} }
@Override @Override
public ItemData.Builder translateToBedrock(int count, DataComponents components, ItemMapping mapping, ItemMappings mappings) { public ItemData.Builder translateToBedrock(GeyserSession session, int count, DataComponents components, ItemMapping mapping, ItemMappings mappings) {
if (components == null) return super.translateToBedrock(count, components, mapping, mappings); if (components == null) return super.translateToBedrock(session, count, components, mapping, mappings);
PotionContents potionContents = components.get(DataComponentType.POTION_CONTENTS); PotionContents potionContents = components.get(DataComponentType.POTION_CONTENTS);
if (potionContents != null) { if (potionContents != null) {
ItemDefinition customItemDefinition = CustomItemTranslator.getCustomItem(components, mapping); ItemDefinition customItemDefinition = CustomItemTranslator.getCustomItem(components, mapping);
@ -64,13 +65,13 @@ public class PotionItem extends Item {
.count(count); .count(count);
} }
} }
return super.translateToBedrock(count, components, mapping, mappings); return super.translateToBedrock(session, count, components, mapping, mappings);
} }
@Override @Override
public @NonNull GeyserItemStack translateToJava(@NonNull ItemData itemData, @NonNull ItemMapping mapping, @NonNull ItemMappings mappings) { public @NonNull GeyserItemStack translateToJava(GeyserSession session, @NonNull ItemData itemData, @NonNull ItemMapping mapping, @NonNull ItemMappings mappings) {
Potion potion = Potion.getByBedrockId(itemData.getDamage()); Potion potion = Potion.getByBedrockId(itemData.getDamage());
GeyserItemStack itemStack = super.translateToJava(itemData, mapping, mappings); GeyserItemStack itemStack = super.translateToJava(session, itemData, mapping, mappings);
if (potion != null) { if (potion != null) {
itemStack.getOrCreateComponents().put(DataComponentType.POTION_CONTENTS, potion.toComponent()); itemStack.getOrCreateComponents().put(DataComponentType.POTION_CONTENTS, potion.toComponent());
} }

Datei anzeigen

@ -30,6 +30,7 @@ import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.inventory.item.Potion; import org.geysermc.geyser.inventory.item.Potion;
import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.registry.type.ItemMappings; import org.geysermc.geyser.registry.type.ItemMappings;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType; import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents; import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.PotionContents; import org.geysermc.mcprotocollib.protocol.data.game.item.component.PotionContents;
@ -40,7 +41,7 @@ public class TippedArrowItem extends ArrowItem {
} }
@Override @Override
public ItemData.Builder translateToBedrock(int count, DataComponents components, ItemMapping mapping, ItemMappings mappings) { public ItemData.Builder translateToBedrock(GeyserSession session, int count, DataComponents components, ItemMapping mapping, ItemMappings mappings) {
if (components != null) { if (components != null) {
PotionContents potionContents = components.get(DataComponentType.POTION_CONTENTS); PotionContents potionContents = components.get(DataComponentType.POTION_CONTENTS);
if (potionContents != null) { if (potionContents != null) {
@ -54,6 +55,6 @@ public class TippedArrowItem extends ArrowItem {
GeyserImpl.getInstance().getLogger().debug("Unknown Java potion (tipped arrow): " + potionContents.getPotionId()); GeyserImpl.getInstance().getLogger().debug("Unknown Java potion (tipped arrow): " + potionContents.getPotionId());
} }
} }
return super.translateToBedrock(count, components, mapping, mappings); return super.translateToBedrock(session, count, components, mapping, mappings);
} }
} }

Datei anzeigen

@ -25,17 +25,84 @@
package org.geysermc.geyser.level; package org.geysermc.geyser.level;
import lombok.ToString;
/** /**
* A data structure to represent what Bedrock believes are the height requirements for a specific dimension. * A data structure to represent what Bedrock believes are the height requirements for a specific dimension.
* As of 1.18.30, biome count is representative of the height of the world, and out-of-bounds chunks can crash * As of 1.18.30, biome count is representative of the height of the world, and out-of-bounds chunks can crash
* the client. * the client.
*
* @param minY The minimum height Bedrock Edition will accept.
* @param height The maximum chunk height Bedrock Edition will accept, from the lowest point to the highest.
* @param doUpperHeightWarn whether to warn in the console if the Java dimension height exceeds Bedrock's.
*/ */
public record BedrockDimension(int minY, int height, boolean doUpperHeightWarn) { @ToString
public static final BedrockDimension OVERWORLD = new BedrockDimension(-64, 384, true); public class BedrockDimension {
public static final BedrockDimension THE_NETHER = new BedrockDimension(0, 128, false);
public static final BedrockDimension THE_END = new BedrockDimension(0, 256, true); public static final int OVERWORLD_ID = 0;
public static final int DEFAULT_NETHER_ID = 1;
public static final int END_ID = 2;
// Changes if the above-bedrock Nether building workaround is applied
public static int BEDROCK_NETHER_ID = DEFAULT_NETHER_ID;
public static final BedrockDimension OVERWORLD = new BedrockDimension(-64, 384, true, OVERWORLD_ID);
public static final BedrockDimension THE_NETHER = new BedrockDimension(0, 128, false, -1) {
@Override
public int bedrockId() {
return BEDROCK_NETHER_ID;
}
};
public static final BedrockDimension THE_END = new BedrockDimension(0, 256, true, END_ID);
public static final String NETHER_IDENTIFIER = "minecraft:the_nether";
private final int minY;
private final int height;
private final boolean doUpperHeightWarn;
private final int bedrockId;
/**
* @param minY The minimum height Bedrock Edition will accept.
* @param height The maximum chunk height Bedrock Edition will accept, from the lowest point to the highest.
* @param doUpperHeightWarn whether to warn in the console if the Java dimension height exceeds Bedrock's.
* @param bedrockId the Bedrock dimension ID of this dimension.
*/
public BedrockDimension(int minY, int height, boolean doUpperHeightWarn, int bedrockId) {
this.minY = minY;
this.height = height;
this.doUpperHeightWarn = doUpperHeightWarn;
this.bedrockId = bedrockId;
}
/**
* The Nether dimension in Bedrock does not permit building above Y128 - the Bedrock above the dimension.
* This workaround sets the Nether as the End dimension to ignore this limit.
*
* @param isAboveNetherBedrockBuilding true if we should apply The End workaround
*/
public static void changeBedrockNetherId(boolean isAboveNetherBedrockBuilding) {
// Change dimension ID to the End to allow for building above Bedrock
BEDROCK_NETHER_ID = isAboveNetherBedrockBuilding ? END_ID : DEFAULT_NETHER_ID;
}
public static boolean isCustomBedrockNetherId() {
return BEDROCK_NETHER_ID == END_ID;
}
public int maxY() {
return minY + height;
}
public int minY() {
return minY;
}
public int height() {
return height;
}
public boolean doUpperHeightWarn() {
return doUpperHeightWarn;
}
public int bedrockId() {
return bedrockId;
}
} }

Datei anzeigen

@ -63,12 +63,19 @@ public record JavaDimension(int minY, int maxY, boolean piglinSafe, boolean ultr
if ("minecraft".equals(id.namespace())) { if ("minecraft".equals(id.namespace())) {
String identifier = id.asString(); String identifier = id.asString();
bedrockId = DimensionUtils.javaToBedrock(identifier); bedrockId = DimensionUtils.javaToBedrock(identifier);
isNetherLike = DimensionUtils.NETHER_IDENTIFIER.equals(identifier); isNetherLike = BedrockDimension.NETHER_IDENTIFIER.equals(identifier);
} else { } else {
// Effects should give is a clue on how this (custom) dimension is supposed to look like // Effects should give is a clue on how this (custom) dimension is supposed to look like
String effects = dimension.getString("effects"); String effects = dimension.getString("effects");
bedrockId = DimensionUtils.javaToBedrock(effects); bedrockId = DimensionUtils.javaToBedrock(effects);
isNetherLike = DimensionUtils.NETHER_IDENTIFIER.equals(effects); isNetherLike = BedrockDimension.NETHER_IDENTIFIER.equals(effects);
}
if (minY % 16 != 0) {
throw new RuntimeException("Minimum Y must be a multiple of 16!");
}
if (maxY % 16 != 0) {
throw new RuntimeException("Maximum Y must be a multiple of 16!");
} }
return new JavaDimension(minY, maxY, piglinSafe, ultrawarm, coordinateScale, bedrockId, isNetherLike); return new JavaDimension(minY, maxY, piglinSafe, ultrawarm, coordinateScale, bedrockId, isNetherLike);

Datei anzeigen

@ -26,24 +26,15 @@
package org.geysermc.geyser.level; package org.geysermc.geyser.level;
import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMap;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.session.cache.registry.RegistryEntryContext; import org.geysermc.geyser.session.cache.registry.RegistryEntryContext;
import org.geysermc.geyser.translator.text.MessageTranslator; import org.geysermc.geyser.translator.text.MessageTranslator;
import org.geysermc.geyser.util.SoundUtils;
public record JukeboxSong(String soundEvent, String description) { public record JukeboxSong(String soundEvent, String description) {
public static JukeboxSong read(RegistryEntryContext context) { public static JukeboxSong read(RegistryEntryContext context) {
NbtMap data = context.data(); NbtMap data = context.data();
Object soundEventObject = data.get("sound_event"); String soundEvent = SoundUtils.readSoundEvent(data, "jukebox song " + context.id());
String soundEvent;
if (soundEventObject instanceof NbtMap map) {
soundEvent = map.getString("sound_id");
} else if (soundEventObject instanceof String string) {
soundEvent = string;
} else {
soundEvent = "";
GeyserImpl.getInstance().getLogger().debug("Sound event for " + context.id() + " was of an unexpected type! Expected string or NBT map, got " + soundEventObject);
}
String description = MessageTranslator.deserializeDescription(context.session(), data); String description = MessageTranslator.deserializeDescription(context.session(), data);
return new JukeboxSong(soundEvent, description); return new JukeboxSong(soundEvent, description);
} }

Datei anzeigen

@ -47,6 +47,7 @@ public final class Properties {
public static final BooleanProperty INVERTED = BooleanProperty.create("inverted"); public static final BooleanProperty INVERTED = BooleanProperty.create("inverted");
public static final BooleanProperty IN_WALL = BooleanProperty.create("in_wall"); public static final BooleanProperty IN_WALL = BooleanProperty.create("in_wall");
public static final BooleanProperty LIT = BooleanProperty.create("lit"); public static final BooleanProperty LIT = BooleanProperty.create("lit");
public static final BooleanProperty TIP = BooleanProperty.create("tip");
public static final BooleanProperty LOCKED = BooleanProperty.create("locked"); public static final BooleanProperty LOCKED = BooleanProperty.create("locked");
public static final BooleanProperty OCCUPIED = BooleanProperty.create("occupied"); public static final BooleanProperty OCCUPIED = BooleanProperty.create("occupied");
public static final BooleanProperty OPEN = BooleanProperty.create("open"); public static final BooleanProperty OPEN = BooleanProperty.create("open");
@ -142,5 +143,6 @@ public final class Properties {
public static final BooleanProperty CRAFTING = BooleanProperty.create("crafting"); public static final BooleanProperty CRAFTING = BooleanProperty.create("crafting");
public static final BasicEnumProperty TRIAL_SPAWNER_STATE = BasicEnumProperty.create("trial_spawner_state", "inactive", "waiting_for_players", "active", "waiting_for_reward_ejection", "ejecting_reward", "cooldown"); public static final BasicEnumProperty TRIAL_SPAWNER_STATE = BasicEnumProperty.create("trial_spawner_state", "inactive", "waiting_for_players", "active", "waiting_for_reward_ejection", "ejecting_reward", "cooldown");
public static final BasicEnumProperty VAULT_STATE = BasicEnumProperty.create("vault_state", "inactive", "active", "unlocking", "ejecting"); public static final BasicEnumProperty VAULT_STATE = BasicEnumProperty.create("vault_state", "inactive", "active", "unlocking", "ejecting");
public static final BasicEnumProperty CREAKING = BasicEnumProperty.create("creaking", "disabled", "dormant", "active");
public static final BooleanProperty OMINOUS = BooleanProperty.create("ominous"); public static final BooleanProperty OMINOUS = BooleanProperty.create("ominous");
} }

Datei anzeigen

@ -63,7 +63,7 @@ public final class BlockState {
return null; return null;
} }
//noinspection unchecked //noinspection unchecked
return (T) get(property); return (T) value;
} }
public <T extends Comparable<T>> T getValue(Property<T> property, T def) { public <T extends Comparable<T>> T getValue(Property<T> property, T def) {

Datei anzeigen

@ -27,6 +27,7 @@ package org.geysermc.geyser.level.physics;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import net.kyori.adventure.util.TriState;
import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.Nullable;
import org.cloudburstmc.math.GenericMath; import org.cloudburstmc.math.GenericMath;
import org.cloudburstmc.math.vector.Vector3d; import org.cloudburstmc.math.vector.Vector3d;
@ -157,7 +158,7 @@ public class CollisionManager {
* @param teleported whether the Bedrock player has teleported to a new position. If true, movement correction is skipped. * @param teleported whether the Bedrock player has teleported to a new position. If true, movement correction is skipped.
* @return the position to send to the Java server, or null to cancel sending the packet * @return the position to send to the Java server, or null to cancel sending the packet
*/ */
public @Nullable Vector3d adjustBedrockPosition(Vector3f bedrockPosition, boolean onGround, boolean teleported) { public @Nullable CollisionResult adjustBedrockPosition(Vector3f bedrockPosition, boolean onGround, boolean teleported) {
PistonCache pistonCache = session.getPistonCache(); PistonCache pistonCache = session.getPistonCache();
// Bedrock clients tend to fall off of honey blocks, so we need to teleport them to the new position // Bedrock clients tend to fall off of honey blocks, so we need to teleport them to the new position
if (pistonCache.isPlayerAttachedToHoney()) { if (pistonCache.isPlayerAttachedToHoney()) {
@ -176,7 +177,7 @@ public class CollisionManager {
playerBoundingBox.setMiddleY(position.getY() + playerBoundingBox.getSizeY() / 2); playerBoundingBox.setMiddleY(position.getY() + playerBoundingBox.getSizeY() / 2);
playerBoundingBox.setMiddleZ(position.getZ()); playerBoundingBox.setMiddleZ(position.getZ());
return playerBoundingBox.getBottomCenter(); return new CollisionResult(playerBoundingBox.getBottomCenter(), TriState.NOT_SET);
} }
Vector3d startingPos = playerBoundingBox.getBottomCenter(); Vector3d startingPos = playerBoundingBox.getBottomCenter();
@ -204,16 +205,16 @@ public class CollisionManager {
PlayerEntity playerEntity = session.getPlayerEntity(); PlayerEntity playerEntity = session.getPlayerEntity();
// Client will dismount if on a vehicle // Client will dismount if on a vehicle
if (playerEntity.getVehicle() == null && pistonCache.getPlayerMotion().equals(Vector3f.ZERO) && !pistonCache.isPlayerSlimeCollision()) { if (playerEntity.getVehicle() == null && pistonCache.getPlayerMotion().equals(Vector3f.ZERO) && !pistonCache.isPlayerSlimeCollision()) {
playerEntity.moveAbsolute(position.toFloat(), playerEntity.getYaw(), playerEntity.getPitch(), playerEntity.getHeadYaw(), newOnGround, true); playerEntity.moveAbsolute(position.toFloat(), playerEntity.getYaw(), playerEntity.getPitch(), playerEntity.getHeadYaw(), onGround, true);
} }
} }
if (!onGround) { if (!newOnGround) {
// Trim the position to prevent rounding errors that make Java think we are clipping into a block // Trim the position to prevent rounding errors that make Java think we are clipping into a block
position = Vector3d.from(position.getX(), Double.parseDouble(DECIMAL_FORMAT.format(position.getY())), position.getZ()); position = Vector3d.from(position.getX(), Double.parseDouble(DECIMAL_FORMAT.format(position.getY())), position.getZ());
} }
return position; return new CollisionResult(position, TriState.byBoolean(onGround));
} }
// TODO: This makes the player look upwards for some reason, rotation values must be wrong // TODO: This makes the player look upwards for some reason, rotation values must be wrong
@ -415,44 +416,38 @@ public class CollisionManager {
return BlockUtils.getCollision(blockId); return BlockUtils.getCollision(blockId);
} }
/** public boolean isOnGround() {
* @return true if the block located at the player's floor position plus 1 would intersect with the player, // Temporary until pre-1.21.30 support is dropped.
* were they not sneaking Vector3d bottomCenter = playerBoundingBox.getBottomCenter();
*/ Vector3i groundPos = Vector3i.from(bottomCenter.getX(), bottomCenter.getY() - 1, bottomCenter.getZ());
public boolean mustPlayerSneakHere() { BlockCollision collision = BlockUtils.getCollisionAt(session, groundPos);
return checkPose(EntityDefinitions.PLAYER.height()); if (collision == null) {
} return false; // Probably air.
/**
* @return true if the block located at the player's floor position plus 1 would intersect with the player,
* were they not crawling
*/
public boolean mustPlayerCrawlHere() {
return checkPose(PlayerEntity.SNEAKING_POSE_HEIGHT);
}
/**
* @param height check and see if this height is invalid in the current player position
*/
private boolean checkPose(float height) {
Vector3i position = session.getPlayerEntity().getPosition().toInt();
BlockCollision collision = BlockUtils.getCollisionAt(session, position);
if (collision != null) {
// Determine, if the player's bounding box *were* at full height, if it would intersect with the block
// at the current location.
double originalY = playerBoundingBox.getMiddleY();
double originalHeight = playerBoundingBox.getSizeY();
double standingY = originalY - (originalHeight / 2.0) + (height / 2.0);
playerBoundingBox.setSizeY(EntityDefinitions.PLAYER.height());
playerBoundingBox.setMiddleY(standingY);
boolean result = collision.checkIntersection(position, playerBoundingBox);
result |= session.getPistonCache().checkCollision(position, playerBoundingBox);
playerBoundingBox.setSizeY(originalHeight);
playerBoundingBox.setMiddleY(originalY);
return result;
} }
return false;
// Hack to not check below the player
playerBoundingBox.setSizeY(playerBoundingBox.getSizeY() - 0.001);
playerBoundingBox.setMiddleY(playerBoundingBox.getMiddleY() + 0.002);
boolean intersected = collision.checkIntersection(groundPos.getX(), groundPos.getY(), groundPos.getZ(), playerBoundingBox);
playerBoundingBox.setSizeY(playerBoundingBox.getSizeY() + 0.001);
playerBoundingBox.setMiddleY(playerBoundingBox.getMiddleY() - 0.002);
boolean result;
if (intersected) {
result = true;
} else {
// Hack to check slightly below the player
playerBoundingBox.setSizeY(playerBoundingBox.getSizeY() + 0.001);
playerBoundingBox.setMiddleY(playerBoundingBox.getMiddleY() - 0.002);
result = collision.checkIntersection(groundPos.getX(), groundPos.getY(), groundPos.getZ(), playerBoundingBox);
playerBoundingBox.setSizeY(playerBoundingBox.getSizeY() - 0.001);
playerBoundingBox.setMiddleY(playerBoundingBox.getMiddleY() + 0.002);
}
return result;
} }
/** /**

Datei anzeigen

@ -23,11 +23,13 @@
* @link https://github.com/GeyserMC/Geyser * @link https://github.com/GeyserMC/Geyser
*/ */
package org.geysermc.geyser.util; package org.geysermc.geyser.level.physics;
import net.kyori.adventure.util.TriState;
import org.cloudburstmc.math.vector.Vector3d;
/** /**
* Represents anything that could be tracked like a enum, without also creating a name and enum-wide array. * Holds the result of a collision check.
*/ */
public interface Ordered { public record CollisionResult(Vector3d correctedMovement, TriState onGround) {
int ordinal();
} }

Datei anzeigen

@ -31,11 +31,13 @@ import org.cloudburstmc.protocol.bedrock.codec.BedrockCodecHelper;
import org.cloudburstmc.protocol.bedrock.codec.BedrockPacketSerializer; import org.cloudburstmc.protocol.bedrock.codec.BedrockPacketSerializer;
import org.cloudburstmc.protocol.bedrock.codec.v291.serializer.MobArmorEquipmentSerializer_v291; import org.cloudburstmc.protocol.bedrock.codec.v291.serializer.MobArmorEquipmentSerializer_v291;
import org.cloudburstmc.protocol.bedrock.codec.v291.serializer.MobEquipmentSerializer_v291; import org.cloudburstmc.protocol.bedrock.codec.v291.serializer.MobEquipmentSerializer_v291;
import org.cloudburstmc.protocol.bedrock.codec.v291.serializer.MoveEntityAbsoluteSerializer_v291;
import org.cloudburstmc.protocol.bedrock.codec.v291.serializer.PlayerHotbarSerializer_v291; import org.cloudburstmc.protocol.bedrock.codec.v291.serializer.PlayerHotbarSerializer_v291;
import org.cloudburstmc.protocol.bedrock.codec.v291.serializer.SetEntityLinkSerializer_v291; import org.cloudburstmc.protocol.bedrock.codec.v291.serializer.SetEntityLinkSerializer_v291;
import org.cloudburstmc.protocol.bedrock.codec.v390.serializer.PlayerSkinSerializer_v390; import org.cloudburstmc.protocol.bedrock.codec.v390.serializer.PlayerSkinSerializer_v390;
import org.cloudburstmc.protocol.bedrock.codec.v407.serializer.InventoryContentSerializer_v407; import org.cloudburstmc.protocol.bedrock.codec.v407.serializer.InventoryContentSerializer_v407;
import org.cloudburstmc.protocol.bedrock.codec.v407.serializer.InventorySlotSerializer_v407; import org.cloudburstmc.protocol.bedrock.codec.v407.serializer.InventorySlotSerializer_v407;
import org.cloudburstmc.protocol.bedrock.codec.v419.serializer.MovePlayerSerializer_v419;
import org.cloudburstmc.protocol.bedrock.codec.v486.serializer.BossEventSerializer_v486; import org.cloudburstmc.protocol.bedrock.codec.v486.serializer.BossEventSerializer_v486;
import org.cloudburstmc.protocol.bedrock.codec.v557.serializer.SetEntityDataSerializer_v557; import org.cloudburstmc.protocol.bedrock.codec.v557.serializer.SetEntityDataSerializer_v557;
import org.cloudburstmc.protocol.bedrock.codec.v662.serializer.SetEntityMotionSerializer_v662; import org.cloudburstmc.protocol.bedrock.codec.v662.serializer.SetEntityMotionSerializer_v662;
@ -44,6 +46,8 @@ import org.cloudburstmc.protocol.bedrock.codec.v712.serializer.InventorySlotSeri
import org.cloudburstmc.protocol.bedrock.codec.v712.serializer.MobArmorEquipmentSerializer_v712; import org.cloudburstmc.protocol.bedrock.codec.v712.serializer.MobArmorEquipmentSerializer_v712;
import org.cloudburstmc.protocol.bedrock.codec.v729.serializer.InventoryContentSerializer_v729; import org.cloudburstmc.protocol.bedrock.codec.v729.serializer.InventoryContentSerializer_v729;
import org.cloudburstmc.protocol.bedrock.codec.v729.serializer.InventorySlotSerializer_v729; import org.cloudburstmc.protocol.bedrock.codec.v729.serializer.InventorySlotSerializer_v729;
import org.cloudburstmc.protocol.bedrock.codec.v748.serializer.InventoryContentSerializer_v748;
import org.cloudburstmc.protocol.bedrock.codec.v748.serializer.InventorySlotSerializer_v748;
import org.cloudburstmc.protocol.bedrock.packet.AnvilDamagePacket; import org.cloudburstmc.protocol.bedrock.packet.AnvilDamagePacket;
import org.cloudburstmc.protocol.bedrock.packet.BedrockPacket; import org.cloudburstmc.protocol.bedrock.packet.BedrockPacket;
import org.cloudburstmc.protocol.bedrock.packet.BossEventPacket; import org.cloudburstmc.protocol.bedrock.packet.BossEventPacket;
@ -65,15 +69,18 @@ import org.cloudburstmc.protocol.bedrock.packet.MapCreateLockedCopyPacket;
import org.cloudburstmc.protocol.bedrock.packet.MapInfoRequestPacket; import org.cloudburstmc.protocol.bedrock.packet.MapInfoRequestPacket;
import org.cloudburstmc.protocol.bedrock.packet.MobArmorEquipmentPacket; import org.cloudburstmc.protocol.bedrock.packet.MobArmorEquipmentPacket;
import org.cloudburstmc.protocol.bedrock.packet.MobEquipmentPacket; import org.cloudburstmc.protocol.bedrock.packet.MobEquipmentPacket;
import org.cloudburstmc.protocol.bedrock.packet.MoveEntityAbsolutePacket;
import org.cloudburstmc.protocol.bedrock.packet.MovePlayerPacket;
import org.cloudburstmc.protocol.bedrock.packet.MultiplayerSettingsPacket; import org.cloudburstmc.protocol.bedrock.packet.MultiplayerSettingsPacket;
import org.cloudburstmc.protocol.bedrock.packet.NpcRequestPacket; import org.cloudburstmc.protocol.bedrock.packet.NpcRequestPacket;
import org.cloudburstmc.protocol.bedrock.packet.PhotoInfoRequestPacket; import org.cloudburstmc.protocol.bedrock.packet.PhotoInfoRequestPacket;
import org.cloudburstmc.protocol.bedrock.packet.PhotoTransferPacket; import org.cloudburstmc.protocol.bedrock.packet.PhotoTransferPacket;
import org.cloudburstmc.protocol.bedrock.packet.PlayerAuthInputPacket;
import org.cloudburstmc.protocol.bedrock.packet.PlayerHotbarPacket; import org.cloudburstmc.protocol.bedrock.packet.PlayerHotbarPacket;
import org.cloudburstmc.protocol.bedrock.packet.PlayerInputPacket;
import org.cloudburstmc.protocol.bedrock.packet.PlayerSkinPacket; import org.cloudburstmc.protocol.bedrock.packet.PlayerSkinPacket;
import org.cloudburstmc.protocol.bedrock.packet.PurchaseReceiptPacket; import org.cloudburstmc.protocol.bedrock.packet.PurchaseReceiptPacket;
import org.cloudburstmc.protocol.bedrock.packet.RefreshEntitlementsPacket; import org.cloudburstmc.protocol.bedrock.packet.RefreshEntitlementsPacket;
import org.cloudburstmc.protocol.bedrock.packet.RiderJumpPacket;
import org.cloudburstmc.protocol.bedrock.packet.ScriptMessagePacket; import org.cloudburstmc.protocol.bedrock.packet.ScriptMessagePacket;
import org.cloudburstmc.protocol.bedrock.packet.SetEntityDataPacket; import org.cloudburstmc.protocol.bedrock.packet.SetEntityDataPacket;
import org.cloudburstmc.protocol.bedrock.packet.SetEntityLinkPacket; import org.cloudburstmc.protocol.bedrock.packet.SetEntityLinkPacket;
@ -140,6 +147,13 @@ class CodecProcessor {
} }
}; };
private static final BedrockPacketSerializer<InventoryContentPacket> INVENTORY_CONTENT_SERIALIZER_V748 = new InventoryContentSerializer_v748() {
@Override
public void deserialize(ByteBuf buffer, BedrockCodecHelper helper, InventoryContentPacket packet) {
throw new IllegalArgumentException("Client cannot send InventoryContentPacket in server-auth inventory environment!");
}
};
private static final BedrockPacketSerializer<InventoryContentPacket> INVENTORY_CONTENT_SERIALIZER_V729 = new InventoryContentSerializer_v729() { private static final BedrockPacketSerializer<InventoryContentPacket> INVENTORY_CONTENT_SERIALIZER_V729 = new InventoryContentSerializer_v729() {
@Override @Override
public void deserialize(ByteBuf buffer, BedrockCodecHelper helper, InventoryContentPacket packet) { public void deserialize(ByteBuf buffer, BedrockCodecHelper helper, InventoryContentPacket packet) {
@ -174,6 +188,27 @@ class CodecProcessor {
} }
}; };
private static final BedrockPacketSerializer<InventorySlotPacket> INVENTORY_SLOT_SERIALIZER_V748 = new InventorySlotSerializer_v748() {
@Override
public void deserialize(ByteBuf buffer, BedrockCodecHelper helper, InventorySlotPacket packet) {
throw new IllegalArgumentException("Client cannot send InventorySlotPacket in server-auth inventory environment!");
}
};
private static final BedrockPacketSerializer<MovePlayerPacket> MOVE_PLAYER_SERIALIZER = new MovePlayerSerializer_v419() {
@Override
public void deserialize(ByteBuf buffer, BedrockCodecHelper helper, MovePlayerPacket packet) {
throw new IllegalArgumentException("Client cannot send MovePlayerPacket in server-auth movement environment!");
}
};
private static final BedrockPacketSerializer<MoveEntityAbsolutePacket> MOVE_ENTITY_SERIALIZER = new MoveEntityAbsoluteSerializer_v291() {
@Override
public void deserialize(ByteBuf buffer, BedrockCodecHelper helper, MoveEntityAbsolutePacket packet) {
throw new IllegalArgumentException("Client cannot send MoveEntityAbsolutePacket in server-auth movement environment!");
}
};
/** /**
* Serializer that does nothing when trying to deserialize BossEventPacket since it is not used from the client. * Serializer that does nothing when trying to deserialize BossEventPacket since it is not used from the client.
*/ */
@ -262,11 +297,14 @@ class CodecProcessor {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
static BedrockCodec processCodec(BedrockCodec codec) { static BedrockCodec processCodec(BedrockCodec codec) {
boolean is748OrAbove = codec.getProtocolVersion() >= 748;
boolean is729OrAbove = codec.getProtocolVersion() >= 729; boolean is729OrAbove = codec.getProtocolVersion() >= 729;
boolean is712OrAbove = codec.getProtocolVersion() >= 712; boolean is712OrAbove = codec.getProtocolVersion() >= 712;
BedrockPacketSerializer<InventoryContentPacket> inventoryContentSerializer; BedrockPacketSerializer<InventoryContentPacket> inventoryContentSerializer;
if (is729OrAbove) { if (is748OrAbove) {
inventoryContentSerializer = INVENTORY_CONTENT_SERIALIZER_V748;
} else if (is729OrAbove) {
inventoryContentSerializer = INVENTORY_CONTENT_SERIALIZER_V729; inventoryContentSerializer = INVENTORY_CONTENT_SERIALIZER_V729;
} else if (is712OrAbove) { } else if (is712OrAbove) {
inventoryContentSerializer = INVENTORY_CONTENT_SERIALIZER_V712; inventoryContentSerializer = INVENTORY_CONTENT_SERIALIZER_V712;
@ -275,7 +313,9 @@ class CodecProcessor {
} }
BedrockPacketSerializer<InventorySlotPacket> inventorySlotSerializer; BedrockPacketSerializer<InventorySlotPacket> inventorySlotSerializer;
if (is729OrAbove) { if (is748OrAbove) {
inventorySlotSerializer = INVENTORY_SLOT_SERIALIZER_V748;
} else if (is729OrAbove) {
inventorySlotSerializer = INVENTORY_SLOT_SERIALIZER_V729; inventorySlotSerializer = INVENTORY_SLOT_SERIALIZER_V729;
} else if (is712OrAbove) { } else if (is712OrAbove) {
inventorySlotSerializer = INVENTORY_SLOT_SERIALIZER_V712; inventorySlotSerializer = INVENTORY_SLOT_SERIALIZER_V712;
@ -297,7 +337,6 @@ class CodecProcessor {
.updateSerializer(ClientCheatAbilityPacket.class, ILLEGAL_SERIALIZER) .updateSerializer(ClientCheatAbilityPacket.class, ILLEGAL_SERIALIZER)
.updateSerializer(CraftingEventPacket.class, ILLEGAL_SERIALIZER) .updateSerializer(CraftingEventPacket.class, ILLEGAL_SERIALIZER)
// Illegal unusued serverbound packets that relate to unused features // Illegal unusued serverbound packets that relate to unused features
.updateSerializer(PlayerAuthInputPacket.class, ILLEGAL_SERIALIZER)
.updateSerializer(ClientCacheBlobStatusPacket.class, ILLEGAL_SERIALIZER) .updateSerializer(ClientCacheBlobStatusPacket.class, ILLEGAL_SERIALIZER)
.updateSerializer(SubClientLoginPacket.class, ILLEGAL_SERIALIZER) .updateSerializer(SubClientLoginPacket.class, ILLEGAL_SERIALIZER)
.updateSerializer(SubChunkRequestPacket.class, ILLEGAL_SERIALIZER) .updateSerializer(SubChunkRequestPacket.class, ILLEGAL_SERIALIZER)
@ -313,6 +352,10 @@ class CodecProcessor {
// Illegal when serverbound due to Geyser specific setup // Illegal when serverbound due to Geyser specific setup
.updateSerializer(InventoryContentPacket.class, inventoryContentSerializer) .updateSerializer(InventoryContentPacket.class, inventoryContentSerializer)
.updateSerializer(InventorySlotPacket.class, inventorySlotSerializer) .updateSerializer(InventorySlotPacket.class, inventorySlotSerializer)
.updateSerializer(MovePlayerPacket.class, MOVE_PLAYER_SERIALIZER)
.updateSerializer(MoveEntityAbsolutePacket.class, MOVE_ENTITY_SERIALIZER)
.updateSerializer(RiderJumpPacket.class, ILLEGAL_SERIALIZER)
.updateSerializer(PlayerInputPacket.class, ILLEGAL_SERIALIZER)
// Ignored only when serverbound // Ignored only when serverbound
.updateSerializer(BossEventPacket.class, BOSS_EVENT_SERIALIZER) .updateSerializer(BossEventPacket.class, BOSS_EVENT_SERIALIZER)
.updateSerializer(MobArmorEquipmentPacket.class, is712OrAbove ? MOB_ARMOR_EQUIPMENT_SERIALIZER_V712 : MOB_ARMOR_EQUIPMENT_SERIALIZER_V291) .updateSerializer(MobArmorEquipmentPacket.class, is712OrAbove ? MOB_ARMOR_EQUIPMENT_SERIALIZER_V712 : MOB_ARMOR_EQUIPMENT_SERIALIZER_V291)

Datei anzeigen

@ -32,6 +32,7 @@ import org.cloudburstmc.protocol.bedrock.codec.v685.Bedrock_v685;
import org.cloudburstmc.protocol.bedrock.codec.v686.Bedrock_v686; import org.cloudburstmc.protocol.bedrock.codec.v686.Bedrock_v686;
import org.cloudburstmc.protocol.bedrock.codec.v712.Bedrock_v712; import org.cloudburstmc.protocol.bedrock.codec.v712.Bedrock_v712;
import org.cloudburstmc.protocol.bedrock.codec.v729.Bedrock_v729; import org.cloudburstmc.protocol.bedrock.codec.v729.Bedrock_v729;
import org.cloudburstmc.protocol.bedrock.codec.v748.Bedrock_v748;
import org.cloudburstmc.protocol.bedrock.netty.codec.packet.BedrockPacketCodec; import org.cloudburstmc.protocol.bedrock.netty.codec.packet.BedrockPacketCodec;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.mcprotocollib.protocol.codec.MinecraftCodec; import org.geysermc.mcprotocollib.protocol.codec.MinecraftCodec;
@ -50,8 +51,8 @@ public final class GameProtocol {
* Default Bedrock codec that should act as a fallback. Should represent the latest available * Default Bedrock codec that should act as a fallback. Should represent the latest available
* release of the game that Geyser supports. * release of the game that Geyser supports.
*/ */
public static final BedrockCodec DEFAULT_BEDROCK_CODEC = CodecProcessor.processCodec(Bedrock_v729.CODEC.toBuilder() public static final BedrockCodec DEFAULT_BEDROCK_CODEC = CodecProcessor.processCodec(Bedrock_v748.CODEC.toBuilder()
.minecraftVersion("1.21.30") .minecraftVersion("1.21.44")
.build()); .build());
/** /**
@ -78,7 +79,12 @@ public final class GameProtocol {
SUPPORTED_BEDROCK_CODECS.add(CodecProcessor.processCodec(Bedrock_v712.CODEC.toBuilder() SUPPORTED_BEDROCK_CODECS.add(CodecProcessor.processCodec(Bedrock_v712.CODEC.toBuilder()
.minecraftVersion("1.21.20 - 1.21.23") .minecraftVersion("1.21.20 - 1.21.23")
.build())); .build()));
SUPPORTED_BEDROCK_CODECS.add(DEFAULT_BEDROCK_CODEC); SUPPORTED_BEDROCK_CODECS.add(CodecProcessor.processCodec(Bedrock_v729.CODEC.toBuilder()
.minecraftVersion("1.21.30/1.21.31")
.build()));
SUPPORTED_BEDROCK_CODECS.add(DEFAULT_BEDROCK_CODEC.toBuilder()
.minecraftVersion("1.21.40 - 1.21.44")
.build());
} }
/** /**
@ -105,6 +111,14 @@ public final class GameProtocol {
return session.getUpstream().getProtocolVersion() < Bedrock_v686.CODEC.getProtocolVersion(); return session.getUpstream().getProtocolVersion() < Bedrock_v686.CODEC.getProtocolVersion();
} }
public static boolean isPre1_21_30(GeyserSession session) {
return session.getUpstream().getProtocolVersion() < Bedrock_v729.CODEC.getProtocolVersion();
}
public static boolean isPre1_21_40(GeyserSession session) {
return session.getUpstream().getProtocolVersion() < Bedrock_v748.CODEC.getProtocolVersion();
}
/** /**
* Gets the {@link PacketCodec} for Minecraft: Java Edition. * Gets the {@link PacketCodec} for Minecraft: Java Edition.
* *

Datei anzeigen

@ -26,6 +26,7 @@
package org.geysermc.geyser.network; package org.geysermc.geyser.network;
import io.netty.buffer.Unpooled; import io.netty.buffer.Unpooled;
import org.cloudburstmc.math.vector.Vector2f;
import org.cloudburstmc.protocol.bedrock.BedrockDisconnectReasons; import org.cloudburstmc.protocol.bedrock.BedrockDisconnectReasons;
import org.cloudburstmc.protocol.bedrock.codec.BedrockCodec; import org.cloudburstmc.protocol.bedrock.codec.BedrockCodec;
import org.cloudburstmc.protocol.bedrock.codec.compat.BedrockCompat; import org.cloudburstmc.protocol.bedrock.codec.compat.BedrockCompat;
@ -38,9 +39,9 @@ import org.cloudburstmc.protocol.bedrock.netty.codec.compression.ZlibCompression
import org.cloudburstmc.protocol.bedrock.packet.BedrockPacket; import org.cloudburstmc.protocol.bedrock.packet.BedrockPacket;
import org.cloudburstmc.protocol.bedrock.packet.LoginPacket; import org.cloudburstmc.protocol.bedrock.packet.LoginPacket;
import org.cloudburstmc.protocol.bedrock.packet.ModalFormResponsePacket; import org.cloudburstmc.protocol.bedrock.packet.ModalFormResponsePacket;
import org.cloudburstmc.protocol.bedrock.packet.MovePlayerPacket;
import org.cloudburstmc.protocol.bedrock.packet.NetworkSettingsPacket; import org.cloudburstmc.protocol.bedrock.packet.NetworkSettingsPacket;
import org.cloudburstmc.protocol.bedrock.packet.PlayStatusPacket; import org.cloudburstmc.protocol.bedrock.packet.PlayStatusPacket;
import org.cloudburstmc.protocol.bedrock.packet.PlayerAuthInputPacket;
import org.cloudburstmc.protocol.bedrock.packet.RequestNetworkSettingsPacket; import org.cloudburstmc.protocol.bedrock.packet.RequestNetworkSettingsPacket;
import org.cloudburstmc.protocol.bedrock.packet.ResourcePackChunkDataPacket; import org.cloudburstmc.protocol.bedrock.packet.ResourcePackChunkDataPacket;
import org.cloudburstmc.protocol.bedrock.packet.ResourcePackChunkRequestPacket; import org.cloudburstmc.protocol.bedrock.packet.ResourcePackChunkRequestPacket;
@ -209,7 +210,7 @@ public class UpstreamPacketHandler extends LoggingPacketHandler {
ResourcePackManifest.Header header = pack.manifest().header(); ResourcePackManifest.Header header = pack.manifest().header();
resourcePacksInfo.getResourcePackInfos().add(new ResourcePacksInfoPacket.Entry( resourcePacksInfo.getResourcePackInfos().add(new ResourcePacksInfoPacket.Entry(
header.uuid().toString(), header.version().toString(), codec.size(), pack.contentKey(), header.uuid().toString(), header.version().toString(), codec.size(), pack.contentKey(),
"", header.uuid().toString(), false, false, false)); "", header.uuid().toString(), false, false, false, ""));
} }
resourcePacksInfo.setForcedToAccept(GeyserImpl.getInstance().config().forceResourcePacks()); resourcePacksInfo.setForcedToAccept(GeyserImpl.getInstance().config().forceResourcePacks());
session.sendUpstreamPacket(resourcePacksInfo); session.sendUpstreamPacket(resourcePacksInfo);
@ -290,8 +291,9 @@ public class UpstreamPacketHandler extends LoggingPacketHandler {
} }
@Override @Override
public PacketSignal handle(MovePlayerPacket packet) { public PacketSignal handle(PlayerAuthInputPacket packet) {
if (session.isLoggingIn()) { // This doesn't catch rotation, but for a niche case I don't exactly want to cache rotation...
if (session.isLoggingIn() && !packet.getMotion().equals(Vector2f.ZERO)) {
SetTitlePacket titlePacket = new SetTitlePacket(); SetTitlePacket titlePacket = new SetTitlePacket();
titlePacket.setType(SetTitlePacket.Type.ACTIONBAR); titlePacket.setType(SetTitlePacket.Type.ACTIONBAR);
titlePacket.setText(GeyserLocale.getPlayerLocaleString("geyser.auth.login.wait", session.locale())); titlePacket.setText(GeyserLocale.getPlayerLocaleString("geyser.auth.login.wait", session.locale()));

Datei anzeigen

@ -27,15 +27,30 @@ package org.geysermc.geyser.network.netty;
import io.netty.bootstrap.Bootstrap; import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.ByteBufAllocator; import io.netty.buffer.ByteBufAllocator;
import io.netty.channel.*; import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.DefaultEventLoopGroup;
import io.netty.channel.unix.PreferredDirectByteBufAllocator; import io.netty.channel.unix.PreferredDirectByteBufAllocator;
import io.netty.handler.codec.haproxy.*; import io.netty.handler.codec.haproxy.HAProxyCommand;
import io.netty.handler.codec.haproxy.HAProxyMessage;
import io.netty.handler.codec.haproxy.HAProxyMessageEncoder;
import io.netty.handler.codec.haproxy.HAProxyProtocolVersion;
import io.netty.handler.codec.haproxy.HAProxyProxiedProtocol;
import io.netty.handler.timeout.ReadTimeoutHandler;
import io.netty.handler.timeout.WriteTimeoutHandler;
import io.netty.util.concurrent.DefaultThreadFactory; import io.netty.util.concurrent.DefaultThreadFactory;
import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.NonNull;
import org.geysermc.mcprotocollib.network.BuiltinFlags; import org.geysermc.mcprotocollib.network.BuiltinFlags;
import org.geysermc.mcprotocollib.network.codec.PacketCodecHelper; import org.geysermc.mcprotocollib.network.codec.PacketCodecHelper;
import org.geysermc.mcprotocollib.network.packet.PacketProtocol; import org.geysermc.mcprotocollib.network.packet.PacketProtocol;
import org.geysermc.mcprotocollib.network.tcp.FlushHandler;
import org.geysermc.mcprotocollib.network.tcp.TcpFlowControlHandler;
import org.geysermc.mcprotocollib.network.tcp.TcpPacketCodec; import org.geysermc.mcprotocollib.network.tcp.TcpPacketCodec;
import org.geysermc.mcprotocollib.network.tcp.TcpPacketCompression;
import org.geysermc.mcprotocollib.network.tcp.TcpPacketEncryptor;
import org.geysermc.mcprotocollib.network.tcp.TcpPacketSizer; import org.geysermc.mcprotocollib.network.tcp.TcpPacketSizer;
import org.geysermc.mcprotocollib.network.tcp.TcpSession; import org.geysermc.mcprotocollib.network.tcp.TcpSession;
import org.geysermc.mcprotocollib.protocol.codec.MinecraftCodecHelper; import org.geysermc.mcprotocollib.protocol.codec.MinecraftCodecHelper;
@ -43,6 +58,7 @@ import org.geysermc.mcprotocollib.protocol.codec.MinecraftCodecHelper;
import java.net.Inet4Address; import java.net.Inet4Address;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.net.SocketAddress; import java.net.SocketAddress;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
/** /**
@ -72,44 +88,53 @@ public final class LocalSession extends TcpSession {
if (DEFAULT_EVENT_LOOP_GROUP == null) { if (DEFAULT_EVENT_LOOP_GROUP == null) {
DEFAULT_EVENT_LOOP_GROUP = new DefaultEventLoopGroup(new DefaultThreadFactory(this.getClass(), true)); DEFAULT_EVENT_LOOP_GROUP = new DefaultEventLoopGroup(new DefaultThreadFactory(this.getClass(), true));
Runtime.getRuntime().addShutdownHook(new Thread( Runtime.getRuntime().addShutdownHook(new Thread(
() -> DEFAULT_EVENT_LOOP_GROUP.shutdownGracefully(100, 500, TimeUnit.MILLISECONDS))); () -> DEFAULT_EVENT_LOOP_GROUP.shutdownGracefully(100, 500, TimeUnit.MILLISECONDS)));
} }
try { final Bootstrap bootstrap = new Bootstrap();
final Bootstrap bootstrap = new Bootstrap(); bootstrap.channel(LocalChannelWithRemoteAddress.class);
bootstrap.channel(LocalChannelWithRemoteAddress.class); bootstrap.handler(new ChannelInitializer<LocalChannelWithRemoteAddress>() {
bootstrap.handler(new ChannelInitializer<LocalChannelWithRemoteAddress>() { @Override
@Override public void initChannel(@NonNull LocalChannelWithRemoteAddress channel) {
public void initChannel(@NonNull LocalChannelWithRemoteAddress channel) { channel.spoofedRemoteAddress(new InetSocketAddress(clientIp, 0));
channel.spoofedRemoteAddress(new InetSocketAddress(clientIp, 0)); PacketProtocol protocol = getPacketProtocol();
PacketProtocol protocol = getPacketProtocol(); protocol.newClientSession(LocalSession.this, transferring);
protocol.newClientSession(LocalSession.this, transferring);
refreshReadTimeoutHandler(channel); ChannelPipeline pipeline = channel.pipeline();
refreshWriteTimeoutHandler(channel);
ChannelPipeline pipeline = channel.pipeline(); addHAProxySupport(pipeline);
pipeline.addLast("sizer", new TcpPacketSizer(LocalSession.this, protocol.getPacketHeader().getLengthSize()));
pipeline.addLast("codec", new TcpPacketCodec(LocalSession.this, true));
pipeline.addLast("manager", LocalSession.this);
addHAProxySupport(pipeline); pipeline.addLast("read-timeout", new ReadTimeoutHandler(getFlag(BuiltinFlags.READ_TIMEOUT, 30)));
} pipeline.addLast("write-timeout", new WriteTimeoutHandler(getFlag(BuiltinFlags.WRITE_TIMEOUT, 0)));
}).group(DEFAULT_EVENT_LOOP_GROUP).option(ChannelOption.CONNECT_TIMEOUT_MILLIS, getConnectTimeout() * 1000);
if (PREFERRED_DIRECT_BYTE_BUF_ALLOCATOR != null) { pipeline.addLast("encryption", new TcpPacketEncryptor());
bootstrap.option(ChannelOption.ALLOCATOR, PREFERRED_DIRECT_BYTE_BUF_ALLOCATOR); pipeline.addLast("sizer", new TcpPacketSizer(protocol.getPacketHeader(), getCodecHelper()));
pipeline.addLast("compression", new TcpPacketCompression(getCodecHelper()));
pipeline.addLast("flow-control", new TcpFlowControlHandler());
pipeline.addLast("codec", new TcpPacketCodec(LocalSession.this, true));
pipeline.addLast("flush-handler", new FlushHandler());
pipeline.addLast("manager", LocalSession.this);
}
}).group(DEFAULT_EVENT_LOOP_GROUP).option(ChannelOption.CONNECT_TIMEOUT_MILLIS, getFlag(BuiltinFlags.CLIENT_CONNECT_TIMEOUT, 30) * 1000);
if (PREFERRED_DIRECT_BYTE_BUF_ALLOCATOR != null) {
bootstrap.option(ChannelOption.ALLOCATOR, PREFERRED_DIRECT_BYTE_BUF_ALLOCATOR);
}
bootstrap.remoteAddress(targetAddress);
CompletableFuture<Void> handleFuture = new CompletableFuture<>();
bootstrap.connect().addListener((futureListener) -> {
if (!futureListener.isSuccess()) {
exceptionCaught(null, futureListener.cause());
} }
bootstrap.remoteAddress(targetAddress); handleFuture.complete(null);
});
bootstrap.connect().addListener((future) -> { if (wait) {
if (!future.isSuccess()) { handleFuture.join();
exceptionCaught(null, future.cause());
}
});
} catch (Throwable t) {
exceptionCaught(null, t);
} }
} }
@ -121,7 +146,7 @@ public final class LocalSession extends TcpSession {
// TODO duplicate code // TODO duplicate code
private void addHAProxySupport(ChannelPipeline pipeline) { private void addHAProxySupport(ChannelPipeline pipeline) {
InetSocketAddress clientAddress = getFlag(BuiltinFlags.CLIENT_PROXIED_ADDRESS); InetSocketAddress clientAddress = getFlag(BuiltinFlags.CLIENT_PROXIED_ADDRESS);
if (getFlag(BuiltinFlags.ENABLE_CLIENT_PROXY_PROTOCOL, false) && clientAddress != null) { if (clientAddress != null) {
pipeline.addFirst("proxy-protocol-packet-sender", new ChannelInboundHandlerAdapter() { pipeline.addFirst("proxy-protocol-packet-sender", new ChannelInboundHandlerAdapter() {
@Override @Override
public void channelActive(@NonNull ChannelHandlerContext ctx) throws Exception { public void channelActive(@NonNull ChannelHandlerContext ctx) throws Exception {
@ -133,9 +158,9 @@ public final class LocalSession extends TcpSession {
remoteAddress = new InetSocketAddress(host, port); remoteAddress = new InetSocketAddress(host, port);
} }
ctx.channel().writeAndFlush(new HAProxyMessage( ctx.channel().writeAndFlush(new HAProxyMessage(
HAProxyProtocolVersion.V2, HAProxyCommand.PROXY, proxiedProtocol, HAProxyProtocolVersion.V2, HAProxyCommand.PROXY, proxiedProtocol,
clientAddress.getAddress().getHostAddress(), remoteAddress.getAddress().getHostAddress(), clientAddress.getAddress().getHostAddress(), remoteAddress.getAddress().getHostAddress(),
clientAddress.getPort(), remoteAddress.getPort() clientAddress.getPort(), remoteAddress.getPort()
)); ));
ctx.pipeline().remove(this); ctx.pipeline().remove(this);
ctx.pipeline().remove("proxy-protocol-encoder"); ctx.pipeline().remove("proxy-protocol-encoder");
@ -144,7 +169,7 @@ public final class LocalSession extends TcpSession {
}); });
pipeline.addFirst("proxy-protocol-encoder", HAProxyMessageEncoder.INSTANCE); pipeline.addFirst("proxy-protocol-encoder", HAProxyMessageEncoder.INSTANCE);
} }
} }
/** /**
* Should only be called when direct ByteBufs should be preferred. At this moment, this should only be called on BungeeCord. * Should only be called when direct ByteBufs should be preferred. At this moment, this should only be called on BungeeCord.

Datei anzeigen

@ -0,0 +1,103 @@
/*
* Copyright (c) 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.registry;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.geysermc.geyser.registry.loader.RegistryLoader;
import java.util.Map;
import java.util.Optional;
import java.util.function.Function;
import java.util.function.Supplier;
public abstract class AbstractMappedDeferredRegistry<K, V, M extends Map<K, V>, R extends AbstractMappedRegistry<K, V, M>> extends DeferredRegistry<M, R> {
protected <I> AbstractMappedDeferredRegistry(Function<RegistryLoader<I, M>, R> registryLoader, RegistryLoader<I, M> deferredLoader) {
super(registryLoader, deferredLoader);
}
protected <I> AbstractMappedDeferredRegistry(Function<RegistryLoader<I, M>, R> registryLoader, Supplier<RegistryLoader<I, M>> deferredLoader) {
super(registryLoader, deferredLoader);
}
protected <I> AbstractMappedDeferredRegistry(I input, RegistryInitializer<M, R> registryInitializer, RegistryLoader<I, M> deferredLoader) {
super(input, registryInitializer, deferredLoader);
}
protected <I> AbstractMappedDeferredRegistry(I input, RegistryInitializer<M, R> registryInitializer, Supplier<RegistryLoader<I, M>> deferredLoader) {
super(input, registryInitializer, deferredLoader);
}
/**
* Returns the value registered by the given key.
*
* @param key the key
* @return the value registered by the given key.
*/
public @Nullable V get(K key) {
return get().get(key);
}
/**
* Returns and maps the value by the given key if present.
*
* @param key the key
* @param mapper the mapper
* @param <U> the type
* @return the mapped value from the given key if present
*/
public <U> Optional<U> map(K key, Function<? super V, ? extends U> mapper) {
V value = this.get(key);
if (value == null) {
return Optional.empty();
} else {
return Optional.ofNullable(mapper.apply(value));
}
}
/**
* Returns the value registered by the given key or the default value
* specified if null.
*
* @param key the key
* @param defaultValue the default value
* @return the value registered by the given key or the default value
* specified if null.
*/
public V getOrDefault(K key, V defaultValue) {
return get().getOrDefault(key, defaultValue);
}
/**
* Registers a new value into this registry with the given key.
*
* @param key the key
* @param value the value
* @return a new value into this registry with the given key.
*/
public V register(K key, V value) {
return get().put(key, value);
}
}

Datei anzeigen

@ -69,7 +69,7 @@ public class BlockRegistries {
/** /**
* A mapped registry containing which holds block IDs to its {@link BlockCollision}. * A mapped registry containing which holds block IDs to its {@link BlockCollision}.
*/ */
public static final ListRegistry<BlockCollision> COLLISIONS; public static final ListDeferredRegistry<BlockCollision> COLLISIONS = ListDeferredRegistry.create(Pair.of("org.geysermc.geyser.translator.collision.CollisionRemapper", "mappings/collisions.nbt"), CollisionRegistryLoader::new);
/** /**
* A registry which stores Java IDs to {@link Block}, containing miscellaneous information about * A registry which stores Java IDs to {@link Block}, containing miscellaneous information about
@ -130,22 +130,17 @@ public class BlockRegistries {
*/ */
public static final SimpleMappedRegistry<String, CustomSkull> CUSTOM_SKULLS = SimpleMappedRegistry.create(RegistryLoaders.empty(Object2ObjectOpenHashMap::new)); public static final SimpleMappedRegistry<String, CustomSkull> CUSTOM_SKULLS = SimpleMappedRegistry.create(RegistryLoaders.empty(Object2ObjectOpenHashMap::new));
static { public static void populate() {
Blocks.VAULT.javaId(); // FIXME Blocks.VAULT.javaId(); // FIXME
CustomSkullRegistryPopulator.populate(); CustomSkullRegistryPopulator.populate();
BlockRegistryPopulator.populate(BlockRegistryPopulator.Stage.PRE_INIT); BlockRegistryPopulator.populate(BlockRegistryPopulator.Stage.PRE_INIT);
CustomBlockRegistryPopulator.populate(CustomBlockRegistryPopulator.Stage.DEFINITION); CustomBlockRegistryPopulator.populate(CustomBlockRegistryPopulator.Stage.DEFINITION);
CustomBlockRegistryPopulator.populate(CustomBlockRegistryPopulator.Stage.NON_VANILLA_REGISTRATION); CustomBlockRegistryPopulator.populate(CustomBlockRegistryPopulator.Stage.NON_VANILLA_REGISTRATION);
BlockRegistryPopulator.populate(BlockRegistryPopulator.Stage.INIT_JAVA); BlockRegistryPopulator.populate(BlockRegistryPopulator.Stage.INIT_JAVA);
COLLISIONS = ListRegistry.create(Pair.of("org.geysermc.geyser.translator.collision.CollisionRemapper", "mappings/collisions.nbt"), CollisionRegistryLoader::new); COLLISIONS.load();
CustomBlockRegistryPopulator.populate(CustomBlockRegistryPopulator.Stage.VANILLA_REGISTRATION); CustomBlockRegistryPopulator.populate(CustomBlockRegistryPopulator.Stage.VANILLA_REGISTRATION);
CustomBlockRegistryPopulator.populate(CustomBlockRegistryPopulator.Stage.CUSTOM_REGISTRATION); CustomBlockRegistryPopulator.populate(CustomBlockRegistryPopulator.Stage.CUSTOM_REGISTRATION);
BlockRegistryPopulator.populate(BlockRegistryPopulator.Stage.INIT_BEDROCK); BlockRegistryPopulator.populate(BlockRegistryPopulator.Stage.INIT_BEDROCK);
BlockRegistryPopulator.populate(BlockRegistryPopulator.Stage.POST_INIT); BlockRegistryPopulator.populate(BlockRegistryPopulator.Stage.POST_INIT);
} }
public static void init() {
// no-op
}
} }

Datei anzeigen

@ -43,32 +43,36 @@ import java.util.function.Supplier;
* *
* @param <M> the value being held by the registry * @param <M> the value being held by the registry
*/ */
public final class DeferredRegistry<M> implements IRegistry<M> { class DeferredRegistry<M, R extends IRegistry<M>> implements IRegistry<M> {
private final Registry<M> backingRegistry; private final R backingRegistry;
private final Supplier<M> loader; private final Supplier<M> loader;
private boolean loaded; private boolean loaded;
private <I> DeferredRegistry(Function<RegistryLoader<I, M>, Registry<M>> registryLoader, RegistryLoader<I, M> deferredLoader) { protected <I> DeferredRegistry(Function<RegistryLoader<I, M>, R> registryLoader, RegistryLoader<I, M> deferredLoader) {
this.backingRegistry = registryLoader.apply(RegistryLoaders.uninitialized()); this.backingRegistry = registryLoader.apply(RegistryLoaders.uninitialized());
this.loader = () -> deferredLoader.load(null); this.loader = () -> deferredLoader.load(null);
} }
private <I> DeferredRegistry(Function<RegistryLoader<I, M>, Registry<M>> registryLoader, Supplier<RegistryLoader<I, M>> deferredLoader) { protected <I> DeferredRegistry(Function<RegistryLoader<I, M>, R> registryLoader, Supplier<RegistryLoader<I, M>> deferredLoader) {
this.backingRegistry = registryLoader.apply(RegistryLoaders.uninitialized()); this.backingRegistry = registryLoader.apply(RegistryLoaders.uninitialized());
this.loader = () -> deferredLoader.get().load(null); this.loader = () -> deferredLoader.get().load(null);
} }
private <I> DeferredRegistry(I input, RegistryInitializer<M> registryInitializer, RegistryLoader<I, M> deferredLoader) { protected <I> DeferredRegistry(I input, RegistryInitializer<M, R> registryInitializer, RegistryLoader<I, M> deferredLoader) {
this.backingRegistry = registryInitializer.initialize(input, RegistryLoaders.uninitialized()); this.backingRegistry = registryInitializer.initialize(input, RegistryLoaders.uninitialized());
this.loader = () -> deferredLoader.load(input); this.loader = () -> deferredLoader.load(input);
} }
private <I> DeferredRegistry(I input, RegistryInitializer<M> registryInitializer, Supplier<RegistryLoader<I, M>> deferredLoader) { protected <I> DeferredRegistry(I input, RegistryInitializer<M, R> registryInitializer, Supplier<RegistryLoader<I, M>> deferredLoader) {
this.backingRegistry = registryInitializer.initialize(input, RegistryLoaders.uninitialized()); this.backingRegistry = registryInitializer.initialize(input, RegistryLoaders.uninitialized());
this.loader = () -> deferredLoader.get().load(input); this.loader = () -> deferredLoader.get().load(input);
} }
protected R backingRegistry() {
return this.backingRegistry;
}
/** /**
* Gets the underlying value held by this registry. * Gets the underlying value held by this registry.
* *
@ -113,55 +117,10 @@ public final class DeferredRegistry<M> implements IRegistry<M> {
} }
/** /**
* Creates a new deferred registry. * Whether this registry was loaded.
*
* @param registryLoader the registry loader
* @param deferredLoader the deferred loader
* @param <I> the input type
* @param <M> the registry type
* @return the new deferred registry
*/ */
public static <I, M> DeferredRegistry<M> create(Function<RegistryLoader<I, M>, Registry<M>> registryLoader, RegistryLoader<I, M> deferredLoader) { public boolean loaded() {
return new DeferredRegistry<>(registryLoader, deferredLoader); return this.loaded;
}
/**
* Creates a new deferred registry.
*
* @param registryLoader the registry loader
* @param deferredLoader the deferred loader
* @param <I> the input type
* @param <M> the registry type
* @return the new deferred registry
*/
public static <I, M> DeferredRegistry<M> create(Function<RegistryLoader<I, M>, Registry<M>> registryLoader, Supplier<RegistryLoader<I, M>> deferredLoader) {
return new DeferredRegistry<>(registryLoader, deferredLoader);
}
/**
* Creates a new deferred registry.
*
* @param registryInitializer the registry initializer
* @param deferredLoader the deferred loader
* @param <I> the input type
* @param <M> the registry type
* @return the new deferred registry
*/
public static <I, M> DeferredRegistry<M> create(I input, RegistryInitializer<M> registryInitializer, RegistryLoader<I, M> deferredLoader) {
return new DeferredRegistry<>(input, registryInitializer, deferredLoader);
}
/**
* Creates a new deferred registry.
*
* @param registryInitializer the registry initializer
* @param deferredLoader the deferred loader
* @param <I> the input type
* @param <M> the registry type
* @return the new deferred registry
*/
public static <I, M> DeferredRegistry<M> create(I input, RegistryInitializer<M> registryInitializer, Supplier<RegistryLoader<I, M>> deferredLoader) {
return new DeferredRegistry<>(input, registryInitializer, deferredLoader);
} }
/** /**
@ -169,7 +128,7 @@ public final class DeferredRegistry<M> implements IRegistry<M> {
* *
* @param <M> the registry type * @param <M> the registry type
*/ */
interface RegistryInitializer<M> { public interface RegistryInitializer<M, R extends IRegistry<M>> {
/** /**
* Initializes the registry. * Initializes the registry.
@ -179,6 +138,6 @@ public final class DeferredRegistry<M> implements IRegistry<M> {
* @param <I> the input type * @param <I> the input type
* @return the initialized registry * @return the initialized registry
*/ */
<I> Registry<M> initialize(I input, RegistryLoader<I, M> registryLoader); <I> R initialize(I input, RegistryLoader<I, M> registryLoader);
} }
} }

Datei anzeigen

@ -0,0 +1,175 @@
/*
* Copyright (c) 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.registry;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.geysermc.geyser.registry.loader.RegistryLoader;
import java.util.List;
import java.util.function.Function;
import java.util.function.Supplier;
public class ListDeferredRegistry<V> extends DeferredRegistry<List<V>, ListRegistry<V>> {
protected <I> ListDeferredRegistry(Function<RegistryLoader<I, List<V>>, ListRegistry<V>> registryLoader, RegistryLoader<I, List<V>> deferredLoader) {
super(registryLoader, deferredLoader);
}
protected <I> ListDeferredRegistry(Function<RegistryLoader<I, List<V>>, ListRegistry<V>> registryLoader, Supplier<RegistryLoader<I, List<V>>> deferredLoader) {
super(registryLoader, deferredLoader);
}
protected <I> ListDeferredRegistry(I input, RegistryInitializer<List<V>, ListRegistry<V>> registryInitializer, RegistryLoader<I, List<V>> deferredLoader) {
super(input, registryInitializer, deferredLoader);
}
protected <I> ListDeferredRegistry(I input, RegistryInitializer<List<V>, ListRegistry<V>> registryInitializer, Supplier<RegistryLoader<I, List<V>>> deferredLoader) {
super(input, registryInitializer, deferredLoader);
}
/**
* Returns the value registered by the given index.
*
* @param index the index
* @return the value registered by the given index.
*/
@Nullable
public V get(int index) {
return backingRegistry().get(index);
}
/**
* Returns the value registered by the given index or the default value
* specified if null.
*
* @param index the index
* @param defaultValue the default value
* @return the value registered by the given key or the default value
* specified if null.
*/
public V getOrDefault(int index, V defaultValue) {
return backingRegistry().getOrDefault(index, defaultValue);
}
/**
* Registers a new value into this registry with the given index.
*
* @param index the index
* @param value the value
* @return a new value into this registry with the given index.
*/
public V register(int index, V value) {
return backingRegistry().register(index, value);
}
/**
* Registers a new value into this registry with the given index, even if this value would normally be outside
* the range of a list.
*
* @param index the index
* @param value the value
* @param defaultValue the default value to fill empty spaces in the registry with.
* @return a new value into this registry with the given index.
*/
public V registerWithAnyIndex(int index, V value, V defaultValue) {
return backingRegistry().registerWithAnyIndex(index, value, defaultValue);
}
/**
* Mark this registry as unsuitable for new additions. The backing list will then be optimized for storage.
*/
public void freeze() {
backingRegistry().freeze();
}
/**
* Creates a new deferred registry.
*
* @param registryLoader the registry loader
* @param deferredLoader the deferred loader
* @param <I> the input type
* @return the new deferred registry
*/
public static <I, V> ListDeferredRegistry<V> create(Function<RegistryLoader<I, List<V>>, ListRegistry<V>> registryLoader, RegistryLoader<I, List<V>> deferredLoader) {
return new ListDeferredRegistry<>(registryLoader, deferredLoader);
}
/**
* Creates a new deferred registry.
*
* @param registryLoader the registry loader
* @param deferredLoader the deferred loader
* @param <I> the input type
* @return the new deferred registry
*/
public static <I, V> ListDeferredRegistry<V> create(Function<RegistryLoader<I, List<V>>, ListRegistry<V>> registryLoader, Supplier<RegistryLoader<I, List<V>>> deferredLoader) {
return new ListDeferredRegistry<>(registryLoader, deferredLoader);
}
/**
* Creates a new deferred registry.
*
* @param registryInitializer the registry initializer
* @param deferredLoader the deferred loader
* @param <I> the input type
* @return the new deferred registry
*/
public static <I, V> ListDeferredRegistry<V> create(I input, RegistryInitializer<List<V>, ListRegistry<V>> registryInitializer, RegistryLoader<I, List<V>> deferredLoader) {
return new ListDeferredRegistry<>(input, registryInitializer, deferredLoader);
}
/**
* Creates a new deferred registry.
*
* @param registryInitializer the registry initializer
* @param deferredLoader the deferred loader
* @param <I> the input type
* @return the new deferred registry
*/
public static <I, V> ListDeferredRegistry<V> create(I input, RegistryInitializer<List<V>, ListRegistry<V>> registryInitializer, Supplier<RegistryLoader<I, List<V>>> deferredLoader) {
return new ListDeferredRegistry<>(input, registryInitializer, deferredLoader);
}
/**
* Creates a new deferred registry.
*
* @param deferredLoader the deferred loader
* @param <I> the input type
* @return the new deferred registry
*/
public static <I, V> ListDeferredRegistry<V> create(I input, RegistryLoader<I, List<V>> deferredLoader) {
return create(input, ListRegistry::create, deferredLoader);
}
/**
* Creates a new deferred registry.
*
* @param deferredLoader the deferred loader
* @param <I> the input type
* @return the new deferred registry
*/
public static <I, V> ListDeferredRegistry<V> create(I input, Supplier<RegistryLoader<I, List<V>>> deferredLoader) {
return create(input, ListRegistry::create, deferredLoader);
}
}

Datei anzeigen

@ -140,6 +140,18 @@ public class ListRegistry<M> extends Registry<List<M>> {
return new ListRegistry<>(null, registryLoader); return new ListRegistry<>(null, registryLoader);
} }
/**
* Creates a new integer mapped registry with the given {@link RegistryLoader} and input.
*
* @param registryLoader the registry loader
* @param <I> the input
* @param <M> the type value
* @return a new registry with the given RegistryLoader
*/
public static <I, M> ListRegistry<M> create(I input, RegistryLoader<I, List<M>> registryLoader) {
return new ListRegistry<>(input, registryLoader);
}
/** /**
* Creates a new integer mapped registry with the given {@link RegistryLoader} and input. * Creates a new integer mapped registry with the given {@link RegistryLoader} and input.
* *

Datei anzeigen

@ -27,6 +27,7 @@ package org.geysermc.geyser.registry;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.objects.Object2IntMap; import it.unimi.dsi.fastutil.objects.Object2IntMap;
import it.unimi.dsi.fastutil.objects.Object2ObjectMap;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMap;
import org.cloudburstmc.nbt.NbtMapBuilder; import org.cloudburstmc.nbt.NbtMapBuilder;
@ -37,10 +38,18 @@ import org.geysermc.geyser.api.pack.ResourcePack;
import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.inventory.recipe.GeyserRecipe; import org.geysermc.geyser.inventory.recipe.GeyserRecipe;
import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.item.type.Item;
import org.geysermc.geyser.registry.loader.*; import org.geysermc.geyser.registry.loader.BiomeIdentifierRegistryLoader;
import org.geysermc.geyser.registry.loader.BlockEntityRegistryLoader;
import org.geysermc.geyser.registry.loader.ParticleTypesRegistryLoader;
import org.geysermc.geyser.registry.loader.PotionMixRegistryLoader;
import org.geysermc.geyser.registry.loader.ProviderRegistryLoader;
import org.geysermc.geyser.registry.loader.RegistryLoaders;
import org.geysermc.geyser.registry.loader.SoundEventsRegistryLoader;
import org.geysermc.geyser.registry.loader.SoundRegistryLoader;
import org.geysermc.geyser.registry.loader.SoundTranslatorRegistryLoader;
import org.geysermc.geyser.registry.populator.ItemRegistryPopulator; import org.geysermc.geyser.registry.populator.ItemRegistryPopulator;
import org.geysermc.geyser.registry.populator.PacketRegistryPopulator; import org.geysermc.geyser.registry.populator.PacketRegistryPopulator;
import org.geysermc.geyser.registry.loader.RecipeRegistryLoader; import org.geysermc.geyser.registry.populator.TagRegistryPopulator;
import org.geysermc.geyser.registry.provider.ProviderSupplier; import org.geysermc.geyser.registry.provider.ProviderSupplier;
import org.geysermc.geyser.registry.type.ItemMappings; import org.geysermc.geyser.registry.type.ItemMappings;
import org.geysermc.geyser.registry.type.ParticleMapping; import org.geysermc.geyser.registry.type.ParticleMapping;
@ -54,14 +63,20 @@ import org.geysermc.mcprotocollib.protocol.data.game.entity.type.EntityType;
import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType; import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType;
import org.geysermc.mcprotocollib.protocol.data.game.level.event.LevelEvent; import org.geysermc.mcprotocollib.protocol.data.game.level.event.LevelEvent;
import org.geysermc.mcprotocollib.protocol.data.game.level.particle.ParticleType; import org.geysermc.mcprotocollib.protocol.data.game.level.particle.ParticleType;
import org.geysermc.mcprotocollib.protocol.data.game.recipe.RecipeType;
import java.util.*; import java.util.ArrayList;
import java.util.EnumMap;
import java.util.HashSet;
import java.util.IdentityHashMap;
import java.util.Map;
import java.util.Set;
/** /**
* Holds all the common registries in Geyser. * Holds all the common registries in Geyser.
*/ */
public final class Registries { public final class Registries {
private static boolean loaded = false;
/** /**
* A registry holding all the providers. * A registry holding all the providers.
* This has to be initialized first to allow extensions to access providers during other registry events. * This has to be initialized first to allow extensions to access providers during other registry events.
@ -69,9 +84,9 @@ public final class Registries {
public static final SimpleMappedRegistry<Class<?>, ProviderSupplier> PROVIDERS = SimpleMappedRegistry.create(new IdentityHashMap<>(), ProviderRegistryLoader::new); public static final SimpleMappedRegistry<Class<?>, ProviderSupplier> PROVIDERS = SimpleMappedRegistry.create(new IdentityHashMap<>(), ProviderRegistryLoader::new);
/** /**
* A registry holding a CompoundTag of the known entity identifiers. * A registry holding a NbtMap of the known entity identifiers.
*/ */
public static final SimpleRegistry<NbtMap> BEDROCK_ENTITY_IDENTIFIERS = SimpleRegistry.create("bedrock/entity_identifiers.dat", RegistryLoaders.NBT); public static final SimpleDeferredRegistry<NbtMap> BEDROCK_ENTITY_IDENTIFIERS = SimpleDeferredRegistry.create("bedrock/entity_identifiers.dat", RegistryLoaders.NBT);
/** /**
* A registry containing all the Bedrock packet translators. * A registry containing all the Bedrock packet translators.
@ -79,19 +94,19 @@ public final class Registries {
public static final PacketTranslatorRegistry<BedrockPacket> BEDROCK_PACKET_TRANSLATORS = PacketTranslatorRegistry.create(); public static final PacketTranslatorRegistry<BedrockPacket> BEDROCK_PACKET_TRANSLATORS = PacketTranslatorRegistry.create();
/** /**
* A registry holding a CompoundTag of all the known biomes. * A registry holding a NbtMap of all the known biomes.
*/ */
public static final SimpleRegistry<NbtMap> BIOMES_NBT = SimpleRegistry.create("bedrock/biome_definitions.dat", RegistryLoaders.NBT); public static final SimpleDeferredRegistry<NbtMap> BIOMES_NBT = SimpleDeferredRegistry.create("bedrock/biome_definitions.dat", RegistryLoaders.NBT);
/** /**
* A mapped registry which stores Java biome identifiers and their Bedrock biome identifier. * A mapped registry which stores Java biome identifiers and their Bedrock biome identifier.
*/ */
public static final SimpleRegistry<Object2IntMap<String>> BIOME_IDENTIFIERS = SimpleRegistry.create("mappings/biomes.json", BiomeIdentifierRegistryLoader::new); public static final SimpleDeferredRegistry<Object2IntMap<String>> BIOME_IDENTIFIERS = SimpleDeferredRegistry.create("mappings/biomes.json", BiomeIdentifierRegistryLoader::new);
/** /**
* A mapped registry which stores a block entity identifier to its {@link BlockEntityTranslator}. * A mapped registry which stores a block entity identifier to its {@link BlockEntityTranslator}.
*/ */
public static final SimpleMappedRegistry<BlockEntityType, BlockEntityTranslator> BLOCK_ENTITIES = SimpleMappedRegistry.create("org.geysermc.geyser.translator.level.block.entity.BlockEntity", BlockEntityRegistryLoader::new); public static final SimpleMappedDeferredRegistry<BlockEntityType, BlockEntityTranslator> BLOCK_ENTITIES = SimpleMappedDeferredRegistry.create("org.geysermc.geyser.translator.level.block.entity.BlockEntity", BlockEntityRegistryLoader::new);
/** /**
* A map containing all entity types and their respective Geyser definitions * A map containing all entity types and their respective Geyser definitions
@ -118,6 +133,9 @@ public final class Registries {
*/ */
public static final ListRegistry<Item> JAVA_ITEMS = ListRegistry.create(RegistryLoaders.empty(ArrayList::new)); public static final ListRegistry<Item> JAVA_ITEMS = ListRegistry.create(RegistryLoaders.empty(ArrayList::new));
/**
* A registry containing item identifiers.
*/
public static final SimpleMappedRegistry<String, Item> JAVA_ITEM_IDENTIFIERS = SimpleMappedRegistry.create(RegistryLoaders.empty(Object2ObjectOpenHashMap::new)); public static final SimpleMappedRegistry<String, Item> JAVA_ITEM_IDENTIFIERS = SimpleMappedRegistry.create(RegistryLoaders.empty(Object2ObjectOpenHashMap::new));
/** /**
@ -130,48 +148,71 @@ public final class Registries {
* A mapped registry holding the {@link ParticleType} to a corresponding {@link ParticleMapping}, containing various pieces of * A mapped registry holding the {@link ParticleType} to a corresponding {@link ParticleMapping}, containing various pieces of
* data primarily for how Bedrock should handle the particle. * data primarily for how Bedrock should handle the particle.
*/ */
public static final SimpleMappedRegistry<ParticleType, ParticleMapping> PARTICLES = SimpleMappedRegistry.create("mappings/particles.json", ParticleTypesRegistryLoader::new); public static final SimpleMappedDeferredRegistry<ParticleType, ParticleMapping> PARTICLES = SimpleMappedDeferredRegistry.create("mappings/particles.json", ParticleTypesRegistryLoader::new);
/** /**
* A registry holding all the potion mixes. * A registry holding all the potion mixes.
*/ */
public static final VersionedRegistry<Set<PotionMixData>> POTION_MIXES; public static final VersionedDeferredRegistry<Set<PotionMixData>> POTION_MIXES = VersionedDeferredRegistry.create(VersionedRegistry::create, PotionMixRegistryLoader::new);
/** /**
* A versioned registry holding all the recipes, with the net ID being the key, and {@link GeyserRecipe} as the value. * A versioned registry holding all the recipes, with the net ID being the key, and {@link GeyserRecipe} as the value.
*/ */
public static final SimpleMappedRegistry<RecipeType, List<GeyserRecipe>> RECIPES = SimpleMappedRegistry.create("mappings/recipes.nbt", RecipeRegistryLoader::new); //public static final SimpleMappedDeferredRegistry<RecipeType, List<GeyserRecipe>> RECIPES = SimpleMappedDeferredRegistry.create("mappings/recipes.nbt", RecipeRegistryLoader::new);
/** /**
* A mapped registry holding {@link ResourcePack}'s with the pack uuid as keys. * A mapped registry holding {@link ResourcePack}'s with the pack uuid as keys.
*/ */
public static final DeferredRegistry<Map<String, ResourcePack>> RESOURCE_PACKS = DeferredRegistry.create(GeyserImpl.getInstance().packDirectory(), SimpleMappedRegistry::create, RegistryLoaders.RESOURCE_PACKS); public static final SimpleMappedDeferredRegistry<String, ResourcePack> RESOURCE_PACKS = SimpleMappedDeferredRegistry.create(GeyserImpl.getInstance().packDirectory(), RegistryLoaders.RESOURCE_PACKS);
/**
* A versioned registry holding most Bedrock tags, with the Java item list (sorted) being the key, and the tag name as the value.
*/
public static final VersionedRegistry<Object2ObjectMap<int[], String>> TAGS = VersionedRegistry.create(RegistryLoaders.empty(Int2ObjectOpenHashMap::new));
/** /**
* A mapped registry holding sound identifiers to their corresponding {@link SoundMapping}. * A mapped registry holding sound identifiers to their corresponding {@link SoundMapping}.
*/ */
public static final SimpleMappedRegistry<String, SoundMapping> SOUNDS = SimpleMappedRegistry.create("mappings/sounds.json", SoundRegistryLoader::new); public static final SimpleMappedDeferredRegistry<String, SoundMapping> SOUNDS = SimpleMappedDeferredRegistry.create("mappings/sounds.json", SoundRegistryLoader::new);
/** /**
* A mapped registry holding {@link LevelEvent}s to their corresponding {@link LevelEventTranslator}. * A mapped registry holding {@link LevelEvent}s to their corresponding {@link LevelEventTranslator}.
*/ */
public static final SimpleMappedRegistry<LevelEvent, LevelEventTranslator> SOUND_LEVEL_EVENTS = SimpleMappedRegistry.create("mappings/effects.json", SoundEventsRegistryLoader::new); public static final SimpleMappedDeferredRegistry<LevelEvent, LevelEventTranslator> SOUND_LEVEL_EVENTS = SimpleMappedDeferredRegistry.create("mappings/effects.json", SoundEventsRegistryLoader::new);
/** /**
* A mapped registry holding {@link SoundTranslator}s to their corresponding {@link SoundInteractionTranslator}. * A mapped registry holding {@link SoundTranslator}s to their corresponding {@link SoundInteractionTranslator}.
*/ */
public static final SimpleMappedRegistry<SoundTranslator, SoundInteractionTranslator<?>> SOUND_TRANSLATORS = SimpleMappedRegistry.create("org.geysermc.geyser.translator.sound.SoundTranslator", SoundTranslatorRegistryLoader::new); public static final SimpleMappedDeferredRegistry<SoundTranslator, SoundInteractionTranslator<?>> SOUND_TRANSLATORS = SimpleMappedDeferredRegistry.create("org.geysermc.geyser.translator.sound.SoundTranslator", SoundTranslatorRegistryLoader::new);
public static void init() { public static void load() {
// no-op if (loaded) return;
loaded = true;
// the following registries are registries that are more complicated than initializing as an empty collection.
// They generally have in common that they either depend on loading a resource file directly or indirectly
// (by using the Items or Blocks class, which loads all the blocks)
BEDROCK_ENTITY_IDENTIFIERS.load();
BIOMES_NBT.load();
BIOME_IDENTIFIERS.load();
BLOCK_ENTITIES.load();
PARTICLES.load();
// load potion mixes later
//RECIPES.load();
RESOURCE_PACKS.load();
SOUNDS.load();
SOUND_LEVEL_EVENTS.load();
SOUND_TRANSLATORS.load();
} }
static { public static void populate() {
PacketRegistryPopulator.populate(); PacketRegistryPopulator.populate();
ItemRegistryPopulator.populate(); ItemRegistryPopulator.populate();
TagRegistryPopulator.populate();
// Create registries that require other registries to load first // potion mixes depend on other registries
POTION_MIXES = VersionedRegistry.create(PotionMixRegistryLoader::new); POTION_MIXES.load();
// Remove unneeded client generation data from NbtMapBuilder // Remove unneeded client generation data from NbtMapBuilder
NbtMapBuilder biomesNbt = NbtMap.builder(); NbtMapBuilder biomesNbt = NbtMap.builder();

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