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:
Commit
6c5c45176b
@ -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!
|
||||
|
||||
## 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
|
||||
Take a look [here](https://geysermc.org/wiki/geyser/setup/) for how to set up Geyser.
|
||||
|
@ -70,6 +70,11 @@ public interface GeyserConnection extends Connection, CommandSource {
|
||||
*/
|
||||
void closeForm();
|
||||
|
||||
/**
|
||||
* Gets the Bedrock protocol version of the player.
|
||||
*/
|
||||
int protocolVersion();
|
||||
|
||||
/**
|
||||
* @param javaId the Java entity ID to look up.
|
||||
* @return a {@link GeyserEntity} if present in this connection's entity tracker.
|
||||
|
@ -32,7 +32,7 @@ import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents;
|
||||
import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents;
|
||||
import net.fabricmc.loader.api.FabricLoader;
|
||||
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.command.CommandRegistry;
|
||||
import org.geysermc.geyser.command.CommandSourceConverter;
|
||||
@ -80,7 +80,7 @@ public class GeyserFabricBootstrap extends GeyserModBootstrap implements ModInit
|
||||
var sourceConverter = CommandSourceConverter.layered(
|
||||
CommandSourceStack.class,
|
||||
id -> getServer().getPlayerList().getPlayer(id),
|
||||
Player::createCommandSourceStack,
|
||||
ServerPlayer::createCommandSourceStack,
|
||||
() -> getServer().createCommandSourceStack(), // NPE if method reference is used, since server is not available yet
|
||||
ModCommandSource::new
|
||||
);
|
||||
|
@ -23,8 +23,8 @@
|
||||
"geyser.mixins.json"
|
||||
],
|
||||
"depends": {
|
||||
"fabricloader": ">=0.15.11",
|
||||
"fabricloader": ">=0.16.7",
|
||||
"fabric": "*",
|
||||
"minecraft": ">=1.21"
|
||||
"minecraft": ">=1.21.2"
|
||||
}
|
||||
}
|
||||
|
@ -13,6 +13,9 @@ architectury {
|
||||
provided("org.cloudburstmc.math", "api")
|
||||
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")
|
||||
|
||||
dependencies {
|
||||
@ -31,6 +34,12 @@ dependencies {
|
||||
}
|
||||
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
|
||||
shadow(projects.api) { isTransitive = false }
|
||||
|
||||
@ -56,6 +65,11 @@ tasks {
|
||||
remapModrinthJar {
|
||||
archiveBaseName.set("geyser-neoforge")
|
||||
}
|
||||
|
||||
shadowJar {
|
||||
// Without this, jackson's service files are not relocated
|
||||
mergeServiceFiles()
|
||||
}
|
||||
}
|
||||
|
||||
modrinth {
|
||||
|
@ -26,7 +26,7 @@
|
||||
package org.geysermc.geyser.platform.neoforge;
|
||||
|
||||
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.fml.ModContainer;
|
||||
import net.neoforged.fml.common.Mod;
|
||||
@ -72,7 +72,7 @@ public class GeyserNeoForgeBootstrap extends GeyserModBootstrap {
|
||||
var sourceConverter = CommandSourceConverter.layered(
|
||||
CommandSourceStack.class,
|
||||
id -> getServer().getPlayerList().getPlayer(id),
|
||||
Player::createCommandSourceStack,
|
||||
ServerPlayer::createCommandSourceStack,
|
||||
() -> getServer().createCommandSourceStack(),
|
||||
ModCommandSource::new
|
||||
);
|
||||
@ -104,7 +104,9 @@ public class GeyserNeoForgeBootstrap extends GeyserModBootstrap {
|
||||
}
|
||||
|
||||
private void onPlayerJoin(PlayerEvent.PlayerLoggedInEvent event) {
|
||||
GeyserModUpdateListener.onPlayReady(event.getEntity());
|
||||
if (event.getEntity() instanceof ServerPlayer player) {
|
||||
GeyserModUpdateListener.onPlayReady(player);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -28,8 +28,8 @@ package org.geysermc.geyser.platform.mod;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelOutboundHandlerAdapter;
|
||||
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.ClientboundLoginFinishedPacket;
|
||||
|
||||
/**
|
||||
* 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();
|
||||
// Don't let any compression packet get through
|
||||
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
|
||||
ctx.channel().pipeline().remove(this);
|
||||
|
@ -25,13 +25,13 @@
|
||||
|
||||
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.platform.mod.command.ModCommandSource;
|
||||
import org.geysermc.geyser.util.VersionCheckUtils;
|
||||
|
||||
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.
|
||||
// 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());
|
||||
|
@ -33,8 +33,10 @@ import net.minecraft.core.component.DataComponents;
|
||||
import net.minecraft.core.registries.BuiltInRegistries;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.level.ServerChunkCache;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.ChunkPos;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
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.chunk.ChunkAccess;
|
||||
import net.minecraft.world.level.chunk.LevelChunkSection;
|
||||
import net.minecraft.world.level.chunk.status.ChunkStatus;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.cloudburstmc.math.vector.Vector3i;
|
||||
import org.geysermc.geyser.level.GeyserWorldManager;
|
||||
@ -84,16 +85,17 @@ public class GeyserModWorldManager extends GeyserWorldManager {
|
||||
}
|
||||
|
||||
Level level = player.level();
|
||||
if (y < level.getMinBuildHeight()) {
|
||||
if (y < level.getMinY()) {
|
||||
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) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int worldOffset = level.getMinBuildHeight() >> 4;
|
||||
int worldOffset = level.getMinY() >> 4;
|
||||
int chunkOffset = (y >> 4) - worldOffset;
|
||||
if (chunkOffset < chunk.getSections().length) {
|
||||
LevelChunkSection section = chunk.getSections()[chunkOffset];
|
||||
|
@ -34,10 +34,24 @@ import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.GeyserLogger;
|
||||
import org.geysermc.geyser.command.GeyserCommandSource;
|
||||
import org.geysermc.geyser.text.ChatColor;
|
||||
import org.jline.reader.Candidate;
|
||||
import org.jline.reader.LineReader;
|
||||
import org.jline.reader.LineReaderBuilder;
|
||||
|
||||
@Slf4j
|
||||
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
|
||||
protected boolean isRunning() {
|
||||
return !GeyserImpl.getInstance().isShuttingDown();
|
||||
|
@ -20,6 +20,9 @@
|
||||
<AppenderRef ref="TerminalConsole"/>
|
||||
<AppenderRef ref="Console"/>
|
||||
<AppenderRef ref="File"/>
|
||||
<filters>
|
||||
<MarkerFilter marker="packet_logging" onMatch="DENY" onMismatch="ACCEPT" />
|
||||
</filters>
|
||||
</Root>
|
||||
</Loggers>
|
||||
</Configuration>
|
@ -31,8 +31,10 @@ import com.velocitypowered.api.network.ProtocolVersion;
|
||||
import com.velocitypowered.api.proxy.InboundConnection;
|
||||
import com.velocitypowered.api.proxy.ProxyServer;
|
||||
import com.velocitypowered.api.proxy.server.ServerPing;
|
||||
import com.velocitypowered.api.proxy.server.ServerPing.Version;
|
||||
import lombok.AllArgsConstructor;
|
||||
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.IGeyserPingPassthrough;
|
||||
|
||||
@ -51,7 +53,9 @@ public class GeyserVelocityPingPassthrough implements IGeyserPingPassthrough {
|
||||
try {
|
||||
event = server.getEventManager().fire(new ProxyPingEvent(new GeyserInboundConnection(inetSocketAddress), ServerPing.builder()
|
||||
.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) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
@ -7,12 +7,13 @@ tasks.modrinth.get().dependsOn(tasks.modrinthSyncBody)
|
||||
|
||||
modrinth {
|
||||
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")
|
||||
versionName.set(versionName(project))
|
||||
versionNumber.set(projectVersion(project))
|
||||
versionType.set("beta")
|
||||
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)
|
||||
|
||||
syncBodyFrom.set(rootProject.file("README.md").readText())
|
||||
|
@ -70,6 +70,7 @@ dependencies {
|
||||
// Test
|
||||
testImplementation(libs.junit)
|
||||
testImplementation(libs.gson.runtime) // Record support
|
||||
testImplementation(libs.mockito)
|
||||
|
||||
// Annotation Processors
|
||||
compileOnly(projects.ap)
|
||||
|
@ -79,6 +79,7 @@ import org.geysermc.geyser.erosion.UnixSocketClientListener;
|
||||
import org.geysermc.geyser.event.GeyserEventBus;
|
||||
import org.geysermc.geyser.extension.GeyserExtensionManager;
|
||||
import org.geysermc.geyser.impl.MinecraftVersionImpl;
|
||||
import org.geysermc.geyser.level.BedrockDimension;
|
||||
import org.geysermc.geyser.level.WorldManager;
|
||||
import org.geysermc.geyser.network.GameProtocol;
|
||||
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.translator.text.MessageTranslator;
|
||||
import org.geysermc.geyser.util.AssetUtils;
|
||||
import org.geysermc.geyser.util.DimensionUtils;
|
||||
import org.geysermc.geyser.util.JsonUtils;
|
||||
import org.geysermc.geyser.util.MinecraftAuthLogger;
|
||||
import org.geysermc.geyser.util.NewsHandler;
|
||||
@ -229,9 +229,14 @@ public class GeyserImpl implements GeyserApi, EventRegistrar {
|
||||
}
|
||||
logger.info("******************************************");
|
||||
|
||||
/* Initialize registries */
|
||||
Registries.init();
|
||||
BlockRegistries.init();
|
||||
/*
|
||||
First load the registries and then populate them.
|
||||
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();
|
||||
|
||||
@ -424,7 +429,7 @@ public class GeyserImpl implements GeyserApi, EventRegistrar {
|
||||
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");
|
||||
if (bedrockThreadCount == null) {
|
||||
@ -747,7 +752,9 @@ public class GeyserImpl implements GeyserApi, EventRegistrar {
|
||||
runIfNonNull(newsHandler, NewsHandler::shutdown);
|
||||
runIfNonNull(erosionUnixListener, UnixSocketClientListener::close);
|
||||
|
||||
if (Registries.RESOURCE_PACKS.loaded()) {
|
||||
Registries.RESOURCE_PACKS.get().clear();
|
||||
}
|
||||
|
||||
this.setEnabled(false);
|
||||
}
|
||||
|
@ -27,6 +27,13 @@ package org.geysermc.geyser.command;
|
||||
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
|
||||
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.api.command.Command;
|
||||
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.event.type.GeyserDefineCommandsEventImpl;
|
||||
import org.geysermc.geyser.extension.command.GeyserExtensionCommand;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.text.GeyserLocale;
|
||||
import org.incendo.cloud.Command.Builder;
|
||||
import org.incendo.cloud.CommandManager;
|
||||
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.Collections;
|
||||
import java.util.EnumSet;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
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) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -25,10 +25,10 @@
|
||||
|
||||
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 java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.function.BiConsumer;
|
||||
import lombok.Setter;
|
||||
import lombok.experimental.Accessors;
|
||||
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.registry.Registries;
|
||||
import org.geysermc.geyser.translator.entity.EntityMetadataTranslator;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.function.BiConsumer;
|
||||
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;
|
||||
|
||||
/**
|
||||
* Represents data for an entity. This includes properties such as height and width, as well as the list of entity
|
||||
|
@ -25,59 +25,163 @@
|
||||
|
||||
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.EntityFlag;
|
||||
import org.geysermc.geyser.entity.factory.EntityFactory;
|
||||
import org.geysermc.geyser.entity.properties.GeyserEntityProperties;
|
||||
import org.geysermc.geyser.entity.type.*;
|
||||
import org.geysermc.geyser.entity.type.living.*;
|
||||
import org.geysermc.geyser.entity.type.living.animal.*;
|
||||
import org.geysermc.geyser.entity.type.living.animal.horse.*;
|
||||
import org.geysermc.geyser.entity.type.AbstractArrowEntity;
|
||||
import org.geysermc.geyser.entity.type.AbstractWindChargeEntity;
|
||||
import org.geysermc.geyser.entity.type.AreaEffectCloudEntity;
|
||||
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.ParrotEntity;
|
||||
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.merchant.AbstractMerchantEntity;
|
||||
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.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.VindicatorEntity;
|
||||
import org.geysermc.geyser.entity.type.player.PlayerEntity;
|
||||
import org.geysermc.geyser.registry.Registries;
|
||||
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 static final EntityDefinition<BoatEntity> ACACIA_BOAT;
|
||||
public static final EntityDefinition<ChestBoatEntity> ACACIA_CHEST_BOAT;
|
||||
public static final EntityDefinition<AllayEntity> ALLAY;
|
||||
public static final EntityDefinition<AreaEffectCloudEntity> AREA_EFFECT_CLOUD;
|
||||
public static final EntityDefinition<ArmadilloEntity> ARMADILLO;
|
||||
public static final EntityDefinition<ArmorStandEntity> ARMOR_STAND;
|
||||
public static final EntityDefinition<ArrowEntity> ARROW;
|
||||
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<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<BoatEntity> BOAT;
|
||||
public static final EntityDefinition<BoggedEntity> BOGGED;
|
||||
public static final EntityDefinition<BreezeEntity> BREEZE;
|
||||
public static final EntityDefinition<AbstractWindChargeEntity> BREEZE_WIND_CHARGE;
|
||||
public static final EntityDefinition<CamelEntity> CAMEL;
|
||||
public static final EntityDefinition<CatEntity> CAT;
|
||||
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<ChickenEntity> CHICKEN;
|
||||
public static final EntityDefinition<ChestBoatEntity> CHEST_BOAT;
|
||||
public static final EntityDefinition<AbstractFishEntity> COD;
|
||||
public static final EntityDefinition<CommandBlockMinecartEntity> COMMAND_BLOCK_MINECART;
|
||||
public static final EntityDefinition<CowEntity> COW;
|
||||
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<ChestedHorseEntity> DONKEY;
|
||||
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<ItemEntity> ITEM;
|
||||
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<LightningEntity> LIGHTNING_BOLT;
|
||||
public static final EntityDefinition<LlamaEntity> LLAMA;
|
||||
public static final EntityDefinition<ThrowableEntity> LLAMA_SPIT;
|
||||
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<MooshroomEntity> MOOSHROOM;
|
||||
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<PaintingEntity> PAINTING;
|
||||
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<AbstractArrowEntity> SPECTRAL_ARROW;
|
||||
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<AbstractSkeletonEntity> STRAY;
|
||||
public static final EntityDefinition<StriderEntity> STRIDER;
|
||||
@ -212,23 +324,6 @@ public final class EntityDefinitions {
|
||||
.addTranslator(null) // Waiting
|
||||
.addTranslator(MetadataType.PARTICLE, AreaEffectCloudEntity::setParticle)
|
||||
.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)
|
||||
.type(EntityType.DRAGON_FIREBALL)
|
||||
.heightAndWidth(1.0f)
|
||||
@ -397,6 +492,7 @@ public final class EntityDefinitions {
|
||||
EntityDefinition<AbstractArrowEntity> abstractArrowBase = EntityDefinition.inherited(AbstractArrowEntity::new, entityBase)
|
||||
.addTranslator(MetadataType.BYTE, AbstractArrowEntity::setArrowFlags)
|
||||
.addTranslator(null) // "Piercing level"
|
||||
.addTranslator(null) // If the arrow is in the ground
|
||||
.build();
|
||||
ARROW = EntityDefinition.inherited(ArrowEntity::new, abstractArrowBase)
|
||||
.type(EntityType.ARROW)
|
||||
@ -471,6 +567,45 @@ public final class EntityDefinitions {
|
||||
.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)
|
||||
.addTranslator(MetadataType.BYTE, LivingEntity::setLivingEntityFlags)
|
||||
.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, CreeperEntity::setIgnited)
|
||||
.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)
|
||||
.type(EntityType.ENDERMAN)
|
||||
.height(2.9f).width(0.6f)
|
||||
@ -621,10 +748,6 @@ public final class EntityDefinitions {
|
||||
.type(EntityType.CAVE_SPIDER)
|
||||
.height(0.5f).width(0.7f)
|
||||
.build();
|
||||
SQUID = EntityDefinition.inherited(SquidEntity::new, mobEntityBase)
|
||||
.type(EntityType.SQUID)
|
||||
.heightAndWidth(0.8f)
|
||||
.build();
|
||||
STRAY = EntityDefinition.inherited(AbstractSkeletonEntity::new, mobEntityBase)
|
||||
.type(EntityType.STRAY)
|
||||
.height(1.8f).width(0.6f)
|
||||
@ -723,6 +846,7 @@ public final class EntityDefinitions {
|
||||
SALMON = EntityDefinition.inherited(abstractFishEntityBase.factory(), abstractFishEntityBase)
|
||||
.type(EntityType.SALMON)
|
||||
.height(0.5f).width(0.7f)
|
||||
.addTranslator(null) // Scale/variant - TODO
|
||||
.build();
|
||||
TADPOLE = EntityDefinition.inherited(TadpoleEntity::new, abstractFishEntityBase)
|
||||
.type(EntityType.TADPOLE)
|
||||
@ -750,11 +874,6 @@ public final class EntityDefinitions {
|
||||
.height(1.95f).width(0.6f)
|
||||
.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)
|
||||
.addTranslator(null) // Celebrating //TODO
|
||||
.build();
|
||||
@ -946,6 +1065,26 @@ public final class EntityDefinitions {
|
||||
.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
|
||||
{
|
||||
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
|
||||
}
|
||||
|
||||
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() {
|
||||
// no-op
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataType;
|
||||
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 {
|
||||
private final Map<EntityDataType<?>, Object> metadata = new Object2ObjectLinkedOpenHashMap<>();
|
||||
@ -53,6 +53,14 @@ public final class GeyserDirtyMetadata {
|
||||
return !metadata.isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Intended for testing purposes only
|
||||
*/
|
||||
public <T> T get(EntityDataType<T> entityData) {
|
||||
//noinspection unchecked
|
||||
return (T) metadata.get(entityData);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return metadata.toString();
|
||||
|
@ -32,12 +32,14 @@ import org.cloudburstmc.protocol.bedrock.packet.AnimatePacket;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.MoveEntityAbsolutePacket;
|
||||
import org.geysermc.geyser.entity.EntityDefinition;
|
||||
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.util.InteractionResult;
|
||||
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.IntEntityMetadata;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.level.ServerboundPaddleBoatPacket;
|
||||
|
||||
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.
|
||||
*/
|
||||
@Getter
|
||||
private int variant;
|
||||
protected final BoatVariant variant;
|
||||
|
||||
private long leashHolderBedrockId = -1;
|
||||
|
||||
// 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;
|
||||
|
||||
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
|
||||
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+
|
||||
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);
|
||||
}
|
||||
|
||||
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) {
|
||||
isPaddlingLeft = entityMetadata.getPrimitiveValue();
|
||||
if (!isPaddlingLeft) {
|
||||
@ -187,6 +183,12 @@ public class BoatEntity extends Entity implements Leashable, Tickable {
|
||||
@Override
|
||||
public void tick() {
|
||||
// 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
|
||||
if (!doTick || passengers.isEmpty()) {
|
||||
return;
|
||||
@ -212,6 +214,10 @@ public class BoatEntity extends Entity implements Leashable, Tickable {
|
||||
return leashHolderBedrockId;
|
||||
}
|
||||
|
||||
public Item getPickItem() {
|
||||
return variant.pickItem;
|
||||
}
|
||||
|
||||
private void sendAnimationPacket(GeyserSession session, Entity rower, AnimatePacket.Action action, float rowTime) {
|
||||
AnimatePacket packet = new AnimatePacket();
|
||||
packet.setRuntimeEntityId(rower.getGeyserId());
|
||||
@ -219,4 +225,27 @@ public class BoatEntity extends Entity implements Leashable, Tickable {
|
||||
packet.setRowingTime(rowTime);
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -27,6 +27,7 @@ package org.geysermc.geyser.entity.type;
|
||||
|
||||
import org.cloudburstmc.math.vector.Vector3f;
|
||||
import org.geysermc.geyser.entity.EntityDefinition;
|
||||
import org.geysermc.geyser.item.type.Item;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.util.InteractionResult;
|
||||
import org.geysermc.geyser.util.InteractiveTag;
|
||||
@ -35,8 +36,8 @@ import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand;
|
||||
import java.util.UUID;
|
||||
|
||||
public class ChestBoatEntity extends BoatEntity {
|
||||
public ChestBoatEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
|
||||
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, variant);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -48,4 +49,9 @@ public class ChestBoatEntity extends BoatEntity {
|
||||
public InteractionResult interact(Hand hand) {
|
||||
return passengers.isEmpty() && !session.isSneaking() ? super.interact(hand) : InteractionResult.SUCCESS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item getPickItem() {
|
||||
return this.variant.chestPickItem;
|
||||
}
|
||||
}
|
||||
|
@ -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.EntityEventType;
|
||||
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.entity.EntityDefinition;
|
||||
import org.geysermc.geyser.entity.GeyserDirtyMetadata;
|
||||
import org.geysermc.geyser.entity.properties.GeyserEntityPropertyManager;
|
||||
import org.geysermc.geyser.item.Items;
|
||||
import org.geysermc.geyser.scoreboard.Team;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.translator.text.MessageTranslator;
|
||||
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.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
|
||||
@Setter
|
||||
public class Entity implements GeyserEntity {
|
||||
|
||||
private static final boolean PRINT_ENTITY_SPAWN_DEBUG = Boolean.parseBoolean(System.getProperty("Geyser.PrintEntitySpawnDebug", "false"));
|
||||
|
||||
protected final GeyserSession session;
|
||||
@ -68,12 +78,19 @@ public class Entity implements GeyserEntity {
|
||||
protected int entityId;
|
||||
protected final long geyserId;
|
||||
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 motion;
|
||||
|
||||
/**
|
||||
* x = Yaw, y = Pitch, z = HeadYaw
|
||||
* Java: Y = Yaw, X = Pitch
|
||||
*/
|
||||
protected float yaw;
|
||||
protected float pitch;
|
||||
@ -97,7 +114,7 @@ public class Entity implements GeyserEntity {
|
||||
@Setter(AccessLevel.NONE)
|
||||
private float boundingBoxWidth;
|
||||
@Setter(AccessLevel.NONE)
|
||||
protected String nametag = "";
|
||||
private String displayName;
|
||||
@Setter(AccessLevel.NONE)
|
||||
protected boolean silent = false;
|
||||
/* 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) {
|
||||
this.session = session;
|
||||
this.definition = definition;
|
||||
this.displayName = standardDisplayName();
|
||||
|
||||
this.entityId = entityId;
|
||||
this.geyserId = geyserId;
|
||||
this.uuid = uuid;
|
||||
this.definition = definition;
|
||||
this.motion = motion;
|
||||
this.yaw = yaw;
|
||||
this.pitch = pitch;
|
||||
@ -341,7 +359,7 @@ public class Entity implements GeyserEntity {
|
||||
* Sends the Bedrock metadata to the client
|
||||
*/
|
||||
public void updateBedrockMetadata() {
|
||||
if (!valid) {
|
||||
if (!isValid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -410,17 +428,84 @@ public class Entity implements GeyserEntity {
|
||||
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) {
|
||||
// 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();
|
||||
if (name.isPresent()) {
|
||||
nametag = MessageTranslator.convertMessage(name.get(), session.locale());
|
||||
String displayName = MessageTranslator.convertMessage(name.get(), session.locale());
|
||||
this.displayName = displayName;
|
||||
setNametag(displayName, true);
|
||||
return;
|
||||
}
|
||||
|
||||
// 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);
|
||||
} else if (!nametag.isEmpty()) {
|
||||
// Clear nametag
|
||||
dirtyMetadata.put(EntityDataTypes.NAME, "");
|
||||
// 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) {
|
||||
dirtyMetadata.put(EntityDataTypes.NAMETAG_ALWAYS_SHOW, (byte) (entityMetadata.getPrimitiveValue() ? 1 : 0));
|
||||
}
|
||||
@ -616,9 +701,4 @@ public class Entity implements GeyserEntity {
|
||||
packet.setData(data);
|
||||
session.sendUpstreamPacket(packet);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <I extends Entity> @Nullable I as(Class<I> entityClass) {
|
||||
return entityClass.isInstance(this) ? (I) this : null;
|
||||
}
|
||||
}
|
||||
|
@ -45,6 +45,7 @@ import org.geysermc.geyser.entity.vehicle.ClientVehicle;
|
||||
import org.geysermc.geyser.inventory.GeyserItemStack;
|
||||
import org.geysermc.geyser.item.Items;
|
||||
import org.geysermc.geyser.registry.type.ItemMapping;
|
||||
import org.geysermc.geyser.scoreboard.Team;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.translator.item.ItemTranslator;
|
||||
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.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
|
||||
@Setter
|
||||
public class LivingEntity extends Entity {
|
||||
|
||||
protected ItemData helmet = ItemData.AIR;
|
||||
protected ItemData chestplate = ItemData.AIR;
|
||||
protected ItemData leggings = ItemData.AIR;
|
||||
@ -150,6 +154,16 @@ public class LivingEntity extends Entity {
|
||||
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) {
|
||||
byte xd = entityMetadata.getPrimitiveValue();
|
||||
|
||||
@ -432,35 +446,35 @@ public class LivingEntity extends Entity {
|
||||
protected void updateAttribute(Attribute javaAttribute, List<AttributeData> newAttributes) {
|
||||
if (javaAttribute.getType() instanceof AttributeType.Builtin 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
|
||||
// See https://github.com/GeyserMC/Geyser/issues/2971
|
||||
this.maxHealth = Math.max((float) AttributeUtils.calculateValue(javaAttribute), 1f);
|
||||
newAttributes.add(createHealthAttribute());
|
||||
}
|
||||
case GENERIC_MOVEMENT_SPEED -> {
|
||||
case MOVEMENT_SPEED -> {
|
||||
AttributeData attributeData = calculateAttribute(javaAttribute, GeyserAttributeType.MOVEMENT_SPEED);
|
||||
newAttributes.add(attributeData);
|
||||
if (this instanceof ClientVehicle clientVehicle) {
|
||||
clientVehicle.getVehicleComponent().setMoveSpeed(attributeData.getValue());
|
||||
}
|
||||
}
|
||||
case GENERIC_STEP_HEIGHT -> {
|
||||
case STEP_HEIGHT -> {
|
||||
if (this instanceof ClientVehicle clientVehicle) {
|
||||
clientVehicle.getVehicleComponent().setStepHeight((float) AttributeUtils.calculateValue(javaAttribute));
|
||||
}
|
||||
}
|
||||
case GENERIC_GRAVITY -> {
|
||||
case GRAVITY -> {
|
||||
if (this instanceof ClientVehicle clientVehicle) {
|
||||
clientVehicle.getVehicleComponent().setGravity(AttributeUtils.calculateValue(javaAttribute));
|
||||
}
|
||||
}
|
||||
case GENERIC_ATTACK_DAMAGE -> newAttributes.add(calculateAttribute(javaAttribute, GeyserAttributeType.ATTACK_DAMAGE));
|
||||
case GENERIC_FLYING_SPEED -> newAttributes.add(calculateAttribute(javaAttribute, GeyserAttributeType.FLYING_SPEED));
|
||||
case GENERIC_FOLLOW_RANGE -> newAttributes.add(calculateAttribute(javaAttribute, GeyserAttributeType.FOLLOW_RANGE));
|
||||
case GENERIC_KNOCKBACK_RESISTANCE -> newAttributes.add(calculateAttribute(javaAttribute, GeyserAttributeType.KNOCKBACK_RESISTANCE));
|
||||
case GENERIC_JUMP_STRENGTH -> newAttributes.add(calculateAttribute(javaAttribute, GeyserAttributeType.HORSE_JUMP_STRENGTH));
|
||||
case GENERIC_SCALE -> {
|
||||
case ATTACK_DAMAGE -> newAttributes.add(calculateAttribute(javaAttribute, GeyserAttributeType.ATTACK_DAMAGE));
|
||||
case FLYING_SPEED -> newAttributes.add(calculateAttribute(javaAttribute, GeyserAttributeType.FLYING_SPEED));
|
||||
case FOLLOW_RANGE -> newAttributes.add(calculateAttribute(javaAttribute, GeyserAttributeType.FOLLOW_RANGE));
|
||||
case KNOCKBACK_RESISTANCE -> newAttributes.add(calculateAttribute(javaAttribute, GeyserAttributeType.KNOCKBACK_RESISTANCE));
|
||||
case JUMP_STRENGTH -> newAttributes.add(calculateAttribute(javaAttribute, GeyserAttributeType.HORSE_JUMP_STRENGTH));
|
||||
case SCALE -> {
|
||||
// Attribute on Java, entity data on Bedrock
|
||||
setAttributeScale((float) AttributeUtils.calculateValue(javaAttribute));
|
||||
updateBedrockMetadata();
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -27,6 +27,7 @@ package org.geysermc.geyser.entity.type.living;
|
||||
|
||||
import lombok.Getter;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.cloudburstmc.math.vector.Vector3f;
|
||||
import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataType;
|
||||
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.type.LivingEntity;
|
||||
import org.geysermc.geyser.item.Items;
|
||||
import org.geysermc.geyser.scoreboard.Team;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.util.InteractionResult;
|
||||
import org.geysermc.geyser.util.MathUtils;
|
||||
@ -123,6 +125,12 @@ public class ArmorStandEntity extends LivingEntity {
|
||||
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
|
||||
public void setDisplayName(EntityMetadata<Optional<Component>, ?> entityMetadata) {
|
||||
super.setDisplayName(entityMetadata);
|
||||
|
@ -37,7 +37,7 @@ import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand;
|
||||
|
||||
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) {
|
||||
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ import org.geysermc.geyser.session.GeyserSession;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public class SquidEntity extends WaterEntity implements Tickable {
|
||||
public class SquidEntity extends AgeableWaterEntity implements Tickable {
|
||||
private float targetPitch;
|
||||
private float targetYaw;
|
||||
|
||||
|
@ -33,8 +33,9 @@ import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
|
||||
import org.geysermc.geyser.entity.EntityDefinition;
|
||||
import org.geysermc.geyser.entity.type.living.AgeableEntity;
|
||||
import org.geysermc.geyser.inventory.GeyserItemStack;
|
||||
import org.geysermc.geyser.item.type.Item;
|
||||
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.InteractiveTag;
|
||||
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) {
|
||||
ItemTag tag = getFoodTag();
|
||||
Tag<Item> tag = getFoodTag();
|
||||
if (tag == null) {
|
||||
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.
|
||||
*/
|
||||
protected abstract @Nullable ItemTag getFoodTag();
|
||||
protected abstract @Nullable Tag<Item> getFoodTag();
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
|
@ -28,8 +28,10 @@ package org.geysermc.geyser.entity.type.living.animal;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.cloudburstmc.math.vector.Vector3f;
|
||||
import org.geysermc.geyser.entity.EntityDefinition;
|
||||
import org.geysermc.geyser.item.type.Item;
|
||||
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.mcprotocollib.protocol.data.game.entity.metadata.ArmadilloState;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.ObjectEntityMetadata;
|
||||
|
||||
@ -75,7 +77,7 @@ public class ArmadilloEntity extends AnimalEntity {
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
protected ItemTag getFoodTag() {
|
||||
protected Tag<Item> getFoodTag() {
|
||||
return ItemTag.ARMADILLO_FOOD;
|
||||
}
|
||||
}
|
||||
|
@ -32,8 +32,10 @@ import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
|
||||
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
|
||||
import org.geysermc.geyser.entity.EntityDefinition;
|
||||
import org.geysermc.geyser.inventory.GeyserItemStack;
|
||||
import org.geysermc.geyser.item.type.Item;
|
||||
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.EntityUtils;
|
||||
import org.geysermc.geyser.util.InteractionResult;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.BooleanEntityMetadata;
|
||||
@ -62,7 +64,7 @@ public class AxolotlEntity extends AnimalEntity {
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
protected ItemTag getFoodTag() {
|
||||
protected Tag<Item> getFoodTag() {
|
||||
return ItemTag.AXOLOTL_FOOD;
|
||||
}
|
||||
|
||||
|
@ -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.packet.EntityEventPacket;
|
||||
import org.geysermc.geyser.entity.EntityDefinition;
|
||||
import org.geysermc.geyser.item.type.Item;
|
||||
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.mcprotocollib.protocol.data.game.entity.metadata.type.ByteEntityMetadata;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.IntEntityMetadata;
|
||||
|
||||
@ -69,7 +71,7 @@ public class BeeEntity extends AnimalEntity {
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
protected ItemTag getFoodTag() {
|
||||
protected Tag<Item> getFoodTag() {
|
||||
return ItemTag.BEE_FOOD;
|
||||
}
|
||||
}
|
||||
|
@ -28,8 +28,10 @@ package org.geysermc.geyser.entity.type.living.animal;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.cloudburstmc.math.vector.Vector3f;
|
||||
import org.geysermc.geyser.entity.EntityDefinition;
|
||||
import org.geysermc.geyser.item.type.Item;
|
||||
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;
|
||||
|
||||
@ -41,7 +43,7 @@ public class ChickenEntity extends AnimalEntity {
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
protected ItemTag getFoodTag() {
|
||||
protected Tag<Item> getFoodTag() {
|
||||
return ItemTag.CHICKEN_FOOD;
|
||||
}
|
||||
}
|
||||
|
@ -33,8 +33,10 @@ import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
|
||||
import org.geysermc.geyser.entity.EntityDefinition;
|
||||
import org.geysermc.geyser.inventory.GeyserItemStack;
|
||||
import org.geysermc.geyser.item.Items;
|
||||
import org.geysermc.geyser.item.type.Item;
|
||||
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.InteractiveTag;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand;
|
||||
@ -69,7 +71,7 @@ public class CowEntity extends AnimalEntity {
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
protected ItemTag getFoodTag() {
|
||||
protected Tag<Item> getFoodTag() {
|
||||
return ItemTag.COW_FOOD;
|
||||
}
|
||||
}
|
||||
|
@ -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.EntityFlag;
|
||||
import org.geysermc.geyser.entity.EntityDefinition;
|
||||
import org.geysermc.geyser.item.type.Item;
|
||||
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.mcprotocollib.protocol.data.game.entity.metadata.type.ByteEntityMetadata;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.IntEntityMetadata;
|
||||
|
||||
@ -57,7 +59,7 @@ public class FoxEntity extends AnimalEntity {
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
protected ItemTag getFoodTag() {
|
||||
protected Tag<Item> getFoodTag() {
|
||||
return ItemTag.FOX_FOOD;
|
||||
}
|
||||
}
|
||||
|
@ -31,8 +31,10 @@ import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
|
||||
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
|
||||
import org.geysermc.geyser.entity.EntityDefinition;
|
||||
import org.geysermc.geyser.entity.type.Entity;
|
||||
import org.geysermc.geyser.item.type.Item;
|
||||
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.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.ObjectEntityMetadata;
|
||||
@ -77,7 +79,7 @@ public class FrogEntity extends AnimalEntity {
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
protected ItemTag getFoodTag() {
|
||||
protected Tag<Item> getFoodTag() {
|
||||
return ItemTag.FROG_FOOD;
|
||||
}
|
||||
}
|
||||
|
@ -34,8 +34,10 @@ import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
|
||||
import org.geysermc.geyser.entity.EntityDefinition;
|
||||
import org.geysermc.geyser.inventory.GeyserItemStack;
|
||||
import org.geysermc.geyser.item.Items;
|
||||
import org.geysermc.geyser.item.type.Item;
|
||||
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.mcprotocollib.protocol.data.game.entity.metadata.Pose;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.BooleanEntityMetadata;
|
||||
@ -99,7 +101,7 @@ public class GoatEntity extends AnimalEntity {
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
protected ItemTag getFoodTag() {
|
||||
protected Tag<Item> getFoodTag() {
|
||||
return ItemTag.GOAT_FOOD;
|
||||
}
|
||||
}
|
||||
|
@ -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.EntityFlag;
|
||||
import org.geysermc.geyser.entity.EntityDefinition;
|
||||
import org.geysermc.geyser.item.type.Item;
|
||||
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.mcprotocollib.protocol.data.game.entity.metadata.type.BooleanEntityMetadata;
|
||||
|
||||
import java.util.UUID;
|
||||
@ -58,7 +60,7 @@ public class HoglinEntity extends AnimalEntity {
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
protected ItemTag getFoodTag() {
|
||||
protected Tag<Item> getFoodTag() {
|
||||
return ItemTag.HOGLIN_FOOD;
|
||||
}
|
||||
|
||||
|
@ -31,8 +31,10 @@ import org.cloudburstmc.math.vector.Vector3f;
|
||||
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
|
||||
import org.geysermc.geyser.entity.EntityDefinition;
|
||||
import org.geysermc.geyser.inventory.GeyserItemStack;
|
||||
import org.geysermc.geyser.item.type.Item;
|
||||
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.InteractiveTag;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand;
|
||||
@ -47,7 +49,7 @@ public class OcelotEntity extends AnimalEntity {
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
protected ItemTag getFoodTag() {
|
||||
protected Tag<Item> getFoodTag() {
|
||||
return ItemTag.OCELOT_FOOD;
|
||||
}
|
||||
|
||||
|
@ -34,8 +34,10 @@ import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.EntityEventPacket;
|
||||
import org.geysermc.geyser.entity.EntityDefinition;
|
||||
import org.geysermc.geyser.inventory.GeyserItemStack;
|
||||
import org.geysermc.geyser.item.type.Item;
|
||||
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.InteractiveTag;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.ByteEntityMetadata;
|
||||
@ -90,7 +92,7 @@ public class PandaEntity extends AnimalEntity {
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
protected ItemTag getFoodTag() {
|
||||
protected Tag<Item> getFoodTag() {
|
||||
return ItemTag.PANDA_FOOD;
|
||||
}
|
||||
|
||||
|
@ -38,9 +38,11 @@ import org.geysermc.geyser.entity.vehicle.BoostableVehicleComponent;
|
||||
import org.geysermc.geyser.entity.vehicle.ClientVehicle;
|
||||
import org.geysermc.geyser.entity.vehicle.VehicleComponent;
|
||||
import org.geysermc.geyser.inventory.GeyserItemStack;
|
||||
import org.geysermc.geyser.item.type.Item;
|
||||
import org.geysermc.geyser.item.Items;
|
||||
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.EntityUtils;
|
||||
import org.geysermc.geyser.util.InteractionResult;
|
||||
import org.geysermc.geyser.util.InteractiveTag;
|
||||
@ -58,7 +60,7 @@ public class PigEntity extends AnimalEntity implements Tickable, ClientVehicle {
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
protected ItemTag getFoodTag() {
|
||||
protected Tag<Item> getFoodTag() {
|
||||
return ItemTag.PIG_FOOD;
|
||||
}
|
||||
|
||||
|
@ -28,8 +28,9 @@ package org.geysermc.geyser.entity.type.living.animal;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.cloudburstmc.math.vector.Vector3f;
|
||||
import org.geysermc.geyser.entity.EntityDefinition;
|
||||
import org.geysermc.geyser.item.type.Item;
|
||||
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;
|
||||
|
||||
@ -41,7 +42,7 @@ public class PolarBearEntity extends AnimalEntity {
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
protected ItemTag getFoodTag() {
|
||||
protected Tag<Item> getFoodTag() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -25,18 +25,23 @@
|
||||
|
||||
package org.geysermc.geyser.entity.type.living.animal;
|
||||
|
||||
import net.kyori.adventure.key.Key;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.cloudburstmc.math.vector.Vector3f;
|
||||
import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
|
||||
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
|
||||
import org.geysermc.geyser.entity.EntityDefinition;
|
||||
import org.geysermc.geyser.item.type.Item;
|
||||
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.EntityUtils;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.IntEntityMetadata;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
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) {
|
||||
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
|
||||
@ -46,7 +51,7 @@ public class RabbitEntity extends AnimalEntity {
|
||||
int variant = entityMetadata.getPrimitiveValue();
|
||||
|
||||
// Change the killer bunny to display as white since it only exists on Java Edition
|
||||
boolean isKillerBunny = variant == 99;
|
||||
isKillerBunny = variant == 99;
|
||||
if (isKillerBunny) {
|
||||
variant = 1;
|
||||
}
|
||||
@ -56,6 +61,14 @@ public class RabbitEntity extends AnimalEntity {
|
||||
dirtyMetadata.put(EntityDataTypes.VARIANT, variant);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String standardDisplayName() {
|
||||
if (isKillerBunny) {
|
||||
return EntityUtils.translatedEntityName(Key.key("killer_bunny"), session);
|
||||
}
|
||||
return super.standardDisplayName();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected float getAdultSize() {
|
||||
return 0.55f;
|
||||
@ -68,7 +81,7 @@ public class RabbitEntity extends AnimalEntity {
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
protected ItemTag getFoodTag() {
|
||||
protected Tag<Item> getFoodTag() {
|
||||
return ItemTag.RABBIT_FOOD;
|
||||
}
|
||||
}
|
@ -34,8 +34,10 @@ import org.geysermc.geyser.entity.EntityDefinition;
|
||||
import org.geysermc.geyser.inventory.GeyserItemStack;
|
||||
import org.geysermc.geyser.item.Items;
|
||||
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.cache.tags.ItemTag;
|
||||
import org.geysermc.geyser.session.cache.tags.Tag;
|
||||
import org.geysermc.geyser.util.InteractionResult;
|
||||
import org.geysermc.geyser.util.InteractiveTag;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.ByteEntityMetadata;
|
||||
@ -59,7 +61,7 @@ public class SheepEntity extends AnimalEntity {
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
protected ItemTag getFoodTag() {
|
||||
protected Tag<Item> getFoodTag() {
|
||||
return ItemTag.SHEEP_FOOD;
|
||||
}
|
||||
|
||||
|
@ -35,8 +35,10 @@ import org.cloudburstmc.protocol.bedrock.packet.LevelSoundEventPacket;
|
||||
import org.geysermc.geyser.entity.EntityDefinition;
|
||||
import org.geysermc.geyser.entity.EntityDefinitions;
|
||||
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.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.SnifferState;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.ObjectEntityMetadata;
|
||||
@ -73,7 +75,7 @@ public class SnifferEntity extends AnimalEntity implements Tickable {
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
protected ItemTag getFoodTag() {
|
||||
protected Tag<Item> getFoodTag() {
|
||||
return ItemTag.SNIFFER_FOOD;
|
||||
}
|
||||
|
||||
|
@ -39,9 +39,11 @@ import org.geysermc.geyser.entity.vehicle.BoostableVehicleComponent;
|
||||
import org.geysermc.geyser.entity.vehicle.ClientVehicle;
|
||||
import org.geysermc.geyser.entity.vehicle.VehicleComponent;
|
||||
import org.geysermc.geyser.inventory.GeyserItemStack;
|
||||
import org.geysermc.geyser.item.type.Item;
|
||||
import org.geysermc.geyser.item.Items;
|
||||
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.EntityUtils;
|
||||
import org.geysermc.geyser.util.InteractionResult;
|
||||
import org.geysermc.geyser.util.InteractiveTag;
|
||||
@ -105,7 +107,7 @@ public class StriderEntity extends AnimalEntity implements Tickable, ClientVehic
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
protected ItemTag getFoodTag() {
|
||||
protected Tag<Item> getFoodTag() {
|
||||
return ItemTag.STRIDER_FOOD;
|
||||
}
|
||||
|
||||
|
@ -29,8 +29,10 @@ import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.cloudburstmc.math.vector.Vector3f;
|
||||
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
|
||||
import org.geysermc.geyser.entity.EntityDefinition;
|
||||
import org.geysermc.geyser.item.type.Item;
|
||||
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.mcprotocollib.protocol.data.game.entity.metadata.type.BooleanEntityMetadata;
|
||||
|
||||
import java.util.UUID;
|
||||
@ -51,10 +53,21 @@ public class TurtleEntity extends AnimalEntity {
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
protected ItemTag getFoodTag() {
|
||||
protected Tag<Item> getFoodTag() {
|
||||
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
|
||||
public boolean canBeLeashed() {
|
||||
return false;
|
||||
|
@ -39,8 +39,10 @@ import org.geysermc.geyser.entity.attribute.GeyserAttributeType;
|
||||
import org.geysermc.geyser.entity.type.living.animal.AnimalEntity;
|
||||
import org.geysermc.geyser.inventory.GeyserItemStack;
|
||||
import org.geysermc.geyser.item.Items;
|
||||
import org.geysermc.geyser.item.type.Item;
|
||||
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.InteractiveTag;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.ByteEntityMetadata;
|
||||
@ -119,7 +121,7 @@ public class AbstractHorseEntity extends AnimalEntity {
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
protected ItemTag getFoodTag() {
|
||||
protected Tag<Item> getFoodTag() {
|
||||
return ItemTag.HORSE_FOOD;
|
||||
}
|
||||
|
||||
|
@ -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.packet.EntityEventPacket;
|
||||
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.vehicle.CamelVehicleComponent;
|
||||
import org.geysermc.geyser.entity.vehicle.ClientVehicle;
|
||||
import org.geysermc.geyser.entity.vehicle.VehicleComponent;
|
||||
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.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.metadata.Pose;
|
||||
@ -100,7 +102,7 @@ public class CamelEntity extends AbstractHorseEntity implements ClientVehicle {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @Nullable ItemTag getFoodTag() {
|
||||
protected @Nullable Tag<Item> getFoodTag() {
|
||||
return ItemTag.CAMEL_FOOD;
|
||||
}
|
||||
|
||||
@ -141,7 +143,7 @@ public class CamelEntity extends AbstractHorseEntity implements ClientVehicle {
|
||||
@Override
|
||||
protected AttributeData calculateAttribute(Attribute javaAttribute, GeyserAttributeType 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());
|
||||
}
|
||||
return attributeData;
|
||||
|
@ -30,8 +30,10 @@ import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.cloudburstmc.math.vector.Vector3f;
|
||||
import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
|
||||
import org.geysermc.geyser.entity.EntityDefinition;
|
||||
import org.geysermc.geyser.item.type.Item;
|
||||
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.MathUtils;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.IntEntityMetadata;
|
||||
|
||||
@ -56,7 +58,7 @@ public class LlamaEntity extends ChestedHorseEntity {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @Nullable ItemTag getFoodTag() {
|
||||
protected @Nullable Tag<Item> getFoodTag() {
|
||||
return ItemTag.LLAMA_FOOD;
|
||||
}
|
||||
}
|
||||
|
@ -32,8 +32,10 @@ import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
|
||||
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
|
||||
import org.geysermc.geyser.entity.EntityDefinition;
|
||||
import org.geysermc.geyser.inventory.GeyserItemStack;
|
||||
import org.geysermc.geyser.item.type.Item;
|
||||
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.InteractiveTag;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.BooleanEntityMetadata;
|
||||
@ -109,7 +111,7 @@ public class CatEntity extends TameableEntity {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @Nullable ItemTag getFoodTag() {
|
||||
protected @Nullable Tag<Item> getFoodTag() {
|
||||
return ItemTag.CAT_FOOD;
|
||||
}
|
||||
|
||||
|
@ -34,6 +34,7 @@ import org.geysermc.geyser.inventory.GeyserItemStack;
|
||||
import org.geysermc.geyser.item.type.Item;
|
||||
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.InteractiveTag;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand;
|
||||
@ -47,7 +48,7 @@ public class ParrotEntity extends TameableEntity {
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
protected ItemTag getFoodTag() {
|
||||
protected Tag<Item> getFoodTag() {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -36,8 +36,10 @@ import org.geysermc.geyser.inventory.GeyserItemStack;
|
||||
import org.geysermc.geyser.item.Items;
|
||||
import org.geysermc.geyser.item.enchantment.EnchantmentComponent;
|
||||
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.cache.tags.ItemTag;
|
||||
import org.geysermc.geyser.session.cache.tags.Tag;
|
||||
import org.geysermc.geyser.util.InteractionResult;
|
||||
import org.geysermc.geyser.util.InteractiveTag;
|
||||
import org.geysermc.geyser.util.ItemUtils;
|
||||
@ -116,7 +118,7 @@ public class WolfEntity extends TameableEntity {
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
protected ItemTag getFoodTag() {
|
||||
protected Tag<Item> getFoodTag() {
|
||||
return ItemTag.WOLF_FOOD;
|
||||
}
|
||||
|
||||
|
@ -32,7 +32,6 @@ import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.cloudburstmc.math.vector.Vector3f;
|
||||
import org.cloudburstmc.math.vector.Vector3i;
|
||||
import org.cloudburstmc.nbt.NbtMap;
|
||||
import org.cloudburstmc.nbt.NbtMapBuilder;
|
||||
import org.cloudburstmc.protocol.bedrock.data.Ability;
|
||||
import org.cloudburstmc.protocol.bedrock.data.AbilityLayer;
|
||||
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.packet.AddPlayerPacket;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.MovePlayerPacket;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.SetEntityDataPacket;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.SetEntityLinkPacket;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.UpdateAttributesPacket;
|
||||
import org.geysermc.geyser.api.entity.type.player.GeyserPlayerEntity;
|
||||
@ -53,29 +51,17 @@ import org.geysermc.geyser.entity.attribute.GeyserAttributeType;
|
||||
import org.geysermc.geyser.entity.type.Entity;
|
||||
import org.geysermc.geyser.entity.type.LivingEntity;
|
||||
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.text.ChatColor;
|
||||
import org.geysermc.geyser.translator.text.MessageTranslator;
|
||||
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.Pose;
|
||||
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.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.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
@ -96,6 +82,9 @@ public class PlayerEntity extends LivingEntity implements GeyserPlayerEntity {
|
||||
|
||||
private String username;
|
||||
|
||||
private String cachedScore = "";
|
||||
private boolean scoreVisible = true;
|
||||
|
||||
/**
|
||||
* The textures property from the GameProfile.
|
||||
*/
|
||||
@ -132,17 +121,6 @@ public class PlayerEntity extends LivingEntity implements GeyserPlayerEntity {
|
||||
|
||||
@Override
|
||||
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.setUuid(uuid);
|
||||
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
|
||||
this.resetMetadata();
|
||||
this.nametag = username;
|
||||
this.hand = ItemData.AIR;
|
||||
this.offhand = ItemData.AIR;
|
||||
this.boots = ItemData.AIR;
|
||||
@ -200,11 +179,7 @@ public class PlayerEntity extends LivingEntity implements GeyserPlayerEntity {
|
||||
if (session.getEntityCache().getPlayerEntity(uuid) == null)
|
||||
return;
|
||||
|
||||
if (session.getEntityCache().getEntityByGeyserId(geyserId) == null) {
|
||||
session.getEntityCache().spawnEntity(this);
|
||||
} else {
|
||||
spawnEntity();
|
||||
}
|
||||
}
|
||||
|
||||
@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
|
||||
public void setPosition(Vector3f position) {
|
||||
if (this.bedPosition != null) {
|
||||
@ -386,38 +357,30 @@ public class PlayerEntity extends LivingEntity implements GeyserPlayerEntity {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplayName() {
|
||||
return username;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDisplayName(EntityMetadata<Optional<Component>, ?> entityMetadata) {
|
||||
// Doesn't do anything for players
|
||||
}
|
||||
|
||||
//todo this will become common entity logic once UUID support is implemented for them
|
||||
public void updateDisplayName(@Nullable Team team) {
|
||||
boolean needsUpdate;
|
||||
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;
|
||||
@Override
|
||||
public String teamIdentifier() {
|
||||
return username;
|
||||
}
|
||||
|
||||
if (needsUpdate) {
|
||||
dirtyMetadata.put(EntityDataTypes.NAME, this.nametag);
|
||||
@Override
|
||||
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
|
||||
@ -425,6 +388,33 @@ public class PlayerEntity extends LivingEntity implements GeyserPlayerEntity {
|
||||
// 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
|
||||
protected void setDimensions(Pose pose) {
|
||||
float height;
|
||||
@ -451,64 +441,6 @@ public class PlayerEntity extends LivingEntity implements GeyserPlayerEntity {
|
||||
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.
|
||||
*/
|
||||
|
@ -38,8 +38,8 @@ import org.cloudburstmc.protocol.bedrock.packet.MovePlayerPacket;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.UpdateAttributesPacket;
|
||||
import org.geysermc.geyser.entity.attribute.GeyserAttributeType;
|
||||
import org.geysermc.geyser.item.Items;
|
||||
import org.geysermc.geyser.network.GameProtocol;
|
||||
import org.geysermc.geyser.level.BedrockDimension;
|
||||
import org.geysermc.geyser.network.GameProtocol;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.util.AttributeUtils;
|
||||
import org.geysermc.geyser.util.DimensionUtils;
|
||||
@ -143,9 +143,32 @@ public class SessionPlayerEntity extends PlayerEntity {
|
||||
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
|
||||
* 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
|
||||
*
|
||||
* @param position the new position of the Bedrock player
|
||||
@ -247,9 +270,9 @@ public class SessionPlayerEntity extends PlayerEntity {
|
||||
|
||||
@Override
|
||||
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));
|
||||
} else if (javaAttribute.getType() == AttributeType.Builtin.PLAYER_BLOCK_INTERACTION_RANGE) {
|
||||
} else if (javaAttribute.getType() == AttributeType.Builtin.BLOCK_INTERACTION_RANGE) {
|
||||
this.blockInteractionRange = AttributeUtils.calculateValue(javaAttribute);
|
||||
} else {
|
||||
super.updateAttribute(javaAttribute, newAttributes);
|
||||
|
@ -76,8 +76,8 @@ public class VehicleComponent<T extends LivingEntity & ClientVehicle> {
|
||||
public VehicleComponent(T vehicle, float stepHeight) {
|
||||
this.vehicle = vehicle;
|
||||
this.stepHeight = stepHeight;
|
||||
this.moveSpeed = (float) AttributeType.Builtin.GENERIC_MOVEMENT_SPEED.getDef();
|
||||
this.gravity = AttributeType.Builtin.GENERIC_GRAVITY.getDef();
|
||||
this.moveSpeed = (float) AttributeType.Builtin.MOVEMENT_SPEED.getDef();
|
||||
this.gravity = AttributeType.Builtin.GRAVITY.getDef();
|
||||
|
||||
double width = vehicle.getBoundingBoxWidth();
|
||||
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());
|
||||
vehicle.getSession().sendDownstreamPacket(moveVehiclePacket);
|
||||
vehicle.getSession().setLastVehicleMoveTimestamp(System.currentTimeMillis());
|
||||
}
|
||||
|
||||
protected double getGravity() {
|
||||
|
@ -38,6 +38,7 @@ import org.geysermc.geyser.command.GeyserCommandSource;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.incendo.cloud.CommandManager;
|
||||
import org.incendo.cloud.context.CommandContext;
|
||||
import org.incendo.cloud.description.CommandDescription;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@ -193,6 +194,12 @@ public abstract class GeyserExtensionCommand extends GeyserCommand {
|
||||
.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")
|
||||
@Override
|
||||
public void execute(CommandContext<GeyserCommandSource> context) {
|
||||
|
@ -43,13 +43,13 @@ public class CameraDefinitions {
|
||||
|
||||
static {
|
||||
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.FREE.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),
|
||||
new CameraPreset(CameraPerspective.THIRD_PERSON_FRONT.id(), "", null, null, null, null, null, null, OptionalBoolean.empty(), null, OptionalBoolean.empty(), null),
|
||||
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_effects", "minecraft:free", null, null, null, null, null, CameraAudioListener.CAMERA, 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));
|
||||
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, null, null, OptionalBoolean.empty(), OptionalBoolean.empty()),
|
||||
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, 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, 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, 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, null, null, OptionalBoolean.empty(), OptionalBoolean.empty()));
|
||||
|
||||
SimpleDefinitionRegistry.Builder<NamedDefinition> builder = SimpleDefinitionRegistry.builder();
|
||||
for (int i = 0; i < CAMERA_PRESETS.size(); i++) {
|
||||
|
@ -29,6 +29,7 @@ import lombok.*;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.item.Items;
|
||||
import org.geysermc.geyser.item.type.Item;
|
||||
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.component.DataComponentType;
|
||||
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;
|
||||
|
||||
@ -77,6 +82,20 @@ public class GeyserItemStack {
|
||||
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() {
|
||||
return isEmpty() ? 0 : javaId;
|
||||
}
|
||||
@ -163,7 +182,17 @@ public class GeyserItemStack {
|
||||
return session.getItemMappings().getMapping(this.javaId);
|
||||
}
|
||||
|
||||
public SlotDisplay asSlotDisplay() {
|
||||
if (isEmpty()) {
|
||||
return EmptySlotDisplay.INSTANCE;
|
||||
}
|
||||
return new ItemStackSlotDisplay(this.getItemStack());
|
||||
}
|
||||
|
||||
public Item asItem() {
|
||||
if (isEmpty()) {
|
||||
return Items.AIR;
|
||||
}
|
||||
if (item == null) {
|
||||
return (item = Registries.JAVA_ITEMS.get().get(javaId));
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -99,7 +99,7 @@ public enum Potion {
|
||||
}
|
||||
|
||||
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) {
|
||||
|
@ -25,11 +25,10 @@
|
||||
|
||||
package org.geysermc.geyser.inventory.recipe;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.recipe.display.slot.SlotDisplay;
|
||||
|
||||
/**
|
||||
* 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 {
|
||||
/**
|
||||
@ -37,6 +36,5 @@ public interface GeyserRecipe {
|
||||
*/
|
||||
boolean isShaped();
|
||||
|
||||
@Nullable
|
||||
ItemStack result();
|
||||
SlotDisplay result();
|
||||
}
|
||||
|
@ -25,15 +25,15 @@
|
||||
|
||||
package org.geysermc.geyser.inventory.recipe;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.recipe.Ingredient;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.recipe.data.ShapedRecipeData;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.recipe.display.ShapedCraftingRecipeDisplay;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.recipe.display.slot.SlotDisplay;
|
||||
|
||||
public record GeyserShapedRecipe(int width, int height, Ingredient[] ingredients, @Nullable ItemStack result) implements GeyserRecipe {
|
||||
import java.util.List;
|
||||
|
||||
public GeyserShapedRecipe(ShapedRecipeData data) {
|
||||
this(data.getWidth(), data.getHeight(), data.getIngredients(), data.getResult());
|
||||
public record GeyserShapedRecipe(int width, int height, List<SlotDisplay> ingredients, SlotDisplay result) implements GeyserRecipe {
|
||||
|
||||
public GeyserShapedRecipe(ShapedCraftingRecipeDisplay data) {
|
||||
this(data.width(), data.height(), data.ingredients(), data.result());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -25,15 +25,15 @@
|
||||
|
||||
package org.geysermc.geyser.inventory.recipe;
|
||||
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.recipe.Ingredient;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.recipe.data.ShapelessRecipeData;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.recipe.display.ShapelessCraftingRecipeDisplay;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.recipe.display.slot.SlotDisplay;
|
||||
|
||||
public record GeyserShapelessRecipe(Ingredient[] ingredients, @Nullable ItemStack result) implements GeyserRecipe {
|
||||
import java.util.List;
|
||||
|
||||
public GeyserShapelessRecipe(ShapelessRecipeData data) {
|
||||
this(data.getIngredients(), data.getResult());
|
||||
public record GeyserShapelessRecipe(List<SlotDisplay> ingredients, SlotDisplay result) implements GeyserRecipe {
|
||||
|
||||
public GeyserShapelessRecipe(ShapelessCraftingRecipeDisplay data) {
|
||||
this(data.ingredients(), data.result());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -27,13 +27,10 @@ package org.geysermc.geyser.inventory.updater;
|
||||
|
||||
import it.unimi.dsi.fastutil.objects.Object2IntMap;
|
||||
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
|
||||
import java.util.stream.IntStream;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.cloudburstmc.nbt.NbtMap;
|
||||
import org.cloudburstmc.nbt.NbtMapBuilder;
|
||||
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.packet.InventorySlotPacket;
|
||||
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.Inventory;
|
||||
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.enchantment.Enchantment;
|
||||
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.text.MessageTranslator;
|
||||
import org.geysermc.geyser.util.ItemUtils;
|
||||
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.HolderSet;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.item.component.ItemEnchantments;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory.ServerboundRenameItemPacket;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
public class AnvilInventoryUpdater extends InventoryUpdater {
|
||||
public static final AnvilInventoryUpdater INSTANCE = new AnvilInventoryUpdater();
|
||||
@ -80,7 +76,6 @@ public class AnvilInventoryUpdater extends InventoryUpdater {
|
||||
slotPacket.setContainerId(ContainerId.UI);
|
||||
slotPacket.setSlot(bedrockSlot);
|
||||
slotPacket.setItem(inventory.getItem(i).getItemData(session));
|
||||
slotPacket.setContainerNameData(new FullContainerName(ContainerSlotType.ANVIL_INPUT, null));
|
||||
session.sendUpstreamPacket(slotPacket);
|
||||
}
|
||||
}
|
||||
@ -101,7 +96,6 @@ public class AnvilInventoryUpdater extends InventoryUpdater {
|
||||
slotPacket.setContainerId(ContainerId.UI);
|
||||
slotPacket.setSlot(translator.javaSlotToBedrock(javaSlot));
|
||||
slotPacket.setItem(inventory.getItem(javaSlot).getItemData(session));
|
||||
slotPacket.setContainerNameData(new FullContainerName(ContainerSlotType.ANVIL_INPUT, null));
|
||||
session.sendUpstreamPacket(slotPacket);
|
||||
} else if (lastTargetSlot != javaSlot) {
|
||||
// Update the previous target slot to remove repair cost changes
|
||||
@ -109,7 +103,6 @@ public class AnvilInventoryUpdater extends InventoryUpdater {
|
||||
slotPacket.setContainerId(ContainerId.UI);
|
||||
slotPacket.setSlot(translator.javaSlotToBedrock(lastTargetSlot));
|
||||
slotPacket.setItem(inventory.getItem(lastTargetSlot).getItemData(session));
|
||||
slotPacket.setContainerNameData(new FullContainerName(ContainerSlotType.ANVIL_INPUT, null));
|
||||
session.sendUpstreamPacket(slotPacket);
|
||||
}
|
||||
|
||||
@ -173,7 +166,6 @@ public class AnvilInventoryUpdater extends InventoryUpdater {
|
||||
slotPacket.setContainerId(ContainerId.UI);
|
||||
slotPacket.setSlot(translator.javaSlotToBedrock(slot));
|
||||
slotPacket.setItem(itemData);
|
||||
slotPacket.setContainerNameData(new FullContainerName(ContainerSlotType.ANVIL_INPUT, null));
|
||||
session.sendUpstreamPacket(slotPacket);
|
||||
}
|
||||
|
||||
@ -320,14 +312,10 @@ public class AnvilInventoryUpdater extends InventoryUpdater {
|
||||
for (Object2IntMap.Entry<Enchantment> entry : getEnchantments(session, material).object2IntEntrySet()) {
|
||||
Enchantment enchantment = entry.getKey();
|
||||
|
||||
HolderSet supportedItems = enchantment.supportedItems();
|
||||
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());
|
||||
boolean canApply = isEnchantedBook(input) || session.getTagCache().is(enchantment.supportedItems(), input.asItem());
|
||||
|
||||
HolderSet exclusiveSet = enchantment.exclusiveSet();
|
||||
int[] incompatibleEnchantments = exclusiveSet.resolve(tagId -> session.getTagCache().get(EnchantmentTag.ALL_ENCHANTMENT_TAGS.get(tagId)));
|
||||
for (int i : incompatibleEnchantments) {
|
||||
Enchantment incompatible = session.getRegistryCache().enchantments().byId(i);
|
||||
List<Enchantment> incompatibleEnchantments = enchantment.exclusiveSet().resolve(session);
|
||||
for (Enchantment incompatible : incompatibleEnchantments) {
|
||||
if (combinedEnchantments.containsKey(incompatible)) {
|
||||
canApply = false;
|
||||
if (!bedrock) {
|
||||
|
@ -25,12 +25,10 @@
|
||||
|
||||
package org.geysermc.geyser.inventory.updater;
|
||||
|
||||
import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerSlotType;
|
||||
import org.cloudburstmc.protocol.bedrock.data.inventory.FullContainerName;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.InventoryContentPacket;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.InventorySlotPacket;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.geysermc.geyser.inventory.Inventory;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.text.GeyserLocale;
|
||||
@ -63,7 +61,6 @@ public class ChestInventoryUpdater extends InventoryUpdater {
|
||||
InventoryContentPacket contentPacket = new InventoryContentPacket();
|
||||
contentPacket.setContainerId(inventory.getBedrockId());
|
||||
contentPacket.setContents(bedrockItems);
|
||||
contentPacket.setContainerNameData(new FullContainerName(ContainerSlotType.ANVIL_INPUT, null));
|
||||
session.sendUpstreamPacket(contentPacket);
|
||||
}
|
||||
|
||||
@ -76,7 +73,6 @@ public class ChestInventoryUpdater extends InventoryUpdater {
|
||||
slotPacket.setContainerId(inventory.getBedrockId());
|
||||
slotPacket.setSlot(translator.javaSlotToBedrock(javaSlot));
|
||||
slotPacket.setItem(inventory.getItem(javaSlot).getItemData(session));
|
||||
slotPacket.setContainerNameData(new FullContainerName(ContainerSlotType.ANVIL_INPUT, null));
|
||||
session.sendUpstreamPacket(slotPacket);
|
||||
return true;
|
||||
}
|
||||
|
@ -25,8 +25,6 @@
|
||||
|
||||
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.packet.InventoryContentPacket;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.InventorySlotPacket;
|
||||
@ -51,7 +49,6 @@ public class ContainerInventoryUpdater extends InventoryUpdater {
|
||||
InventoryContentPacket contentPacket = new InventoryContentPacket();
|
||||
contentPacket.setContainerId(inventory.getBedrockId());
|
||||
contentPacket.setContents(Arrays.asList(bedrockItems));
|
||||
contentPacket.setContainerNameData(new FullContainerName(ContainerSlotType.ANVIL_INPUT, null));
|
||||
session.sendUpstreamPacket(contentPacket);
|
||||
}
|
||||
|
||||
@ -64,7 +61,6 @@ public class ContainerInventoryUpdater extends InventoryUpdater {
|
||||
slotPacket.setContainerId(inventory.getBedrockId());
|
||||
slotPacket.setSlot(translator.javaSlotToBedrock(javaSlot));
|
||||
slotPacket.setItem(inventory.getItem(javaSlot).getItemData(session));
|
||||
slotPacket.setContainerNameData(new FullContainerName(ContainerSlotType.ANVIL_INPUT, null));
|
||||
session.sendUpstreamPacket(slotPacket);
|
||||
return true;
|
||||
}
|
||||
|
@ -26,8 +26,6 @@
|
||||
package org.geysermc.geyser.inventory.updater;
|
||||
|
||||
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.packet.InventoryContentPacket;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.InventorySlotPacket;
|
||||
@ -58,7 +56,6 @@ public class CrafterInventoryUpdater extends InventoryUpdater {
|
||||
contentPacket = new InventoryContentPacket();
|
||||
contentPacket.setContainerId(inventory.getBedrockId());
|
||||
contentPacket.setContents(Arrays.asList(bedrockItems));
|
||||
contentPacket.setContainerNameData(new FullContainerName(ContainerSlotType.ANVIL_INPUT, null));
|
||||
session.sendUpstreamPacket(contentPacket);
|
||||
|
||||
// inventory and hotbar
|
||||
@ -70,7 +67,6 @@ public class CrafterInventoryUpdater extends InventoryUpdater {
|
||||
contentPacket = new InventoryContentPacket();
|
||||
contentPacket.setContainerId(ContainerId.INVENTORY);
|
||||
contentPacket.setContents(Arrays.asList(bedrockItems));
|
||||
contentPacket.setContainerNameData(new FullContainerName(ContainerSlotType.ANVIL_INPUT, null));
|
||||
session.sendUpstreamPacket(contentPacket);
|
||||
|
||||
// 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.setSlot(translator.javaSlotToBedrock(javaSlot));
|
||||
packet.setItem(inventory.getItem(javaSlot).getItemData(session));
|
||||
packet.setContainerNameData(new FullContainerName(ContainerSlotType.ANVIL_INPUT, null));
|
||||
session.sendUpstreamPacket(packet);
|
||||
return true;
|
||||
}
|
||||
|
@ -25,8 +25,6 @@
|
||||
|
||||
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.packet.InventoryContentPacket;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.InventorySlotPacket;
|
||||
@ -51,7 +49,6 @@ public class HorseInventoryUpdater extends InventoryUpdater {
|
||||
InventoryContentPacket contentPacket = new InventoryContentPacket();
|
||||
contentPacket.setContainerId(inventory.getBedrockId());
|
||||
contentPacket.setContents(Arrays.asList(bedrockItems));
|
||||
contentPacket.setContainerNameData(new FullContainerName(ContainerSlotType.ANVIL_INPUT, null));
|
||||
session.sendUpstreamPacket(contentPacket);
|
||||
}
|
||||
|
||||
@ -64,7 +61,6 @@ public class HorseInventoryUpdater extends InventoryUpdater {
|
||||
slotPacket.setContainerId(4); // Horse GUI?
|
||||
slotPacket.setSlot(translator.javaSlotToBedrock(javaSlot));
|
||||
slotPacket.setItem(inventory.getItem(javaSlot).getItemData(session));
|
||||
slotPacket.setContainerNameData(new FullContainerName(ContainerSlotType.ANVIL_INPUT, null));
|
||||
session.sendUpstreamPacket(slotPacket);
|
||||
return true;
|
||||
}
|
||||
|
@ -26,8 +26,6 @@
|
||||
package org.geysermc.geyser.inventory.updater;
|
||||
|
||||
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.packet.InventoryContentPacket;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.InventorySlotPacket;
|
||||
@ -47,7 +45,6 @@ public class InventoryUpdater {
|
||||
InventoryContentPacket contentPacket = new InventoryContentPacket();
|
||||
contentPacket.setContainerId(ContainerId.INVENTORY);
|
||||
contentPacket.setContents(Arrays.asList(bedrockItems));
|
||||
contentPacket.setContainerNameData(new FullContainerName(ContainerSlotType.ANVIL_INPUT, null));
|
||||
session.sendUpstreamPacket(contentPacket);
|
||||
}
|
||||
|
||||
@ -57,7 +54,6 @@ public class InventoryUpdater {
|
||||
slotPacket.setContainerId(ContainerId.INVENTORY);
|
||||
slotPacket.setSlot(translator.javaSlotToBedrock(javaSlot));
|
||||
slotPacket.setItem(inventory.getItem(javaSlot).getItemData(session));
|
||||
slotPacket.setContainerNameData(new FullContainerName(ContainerSlotType.ANVIL_INPUT, null));
|
||||
session.sendUpstreamPacket(slotPacket);
|
||||
return true;
|
||||
}
|
||||
|
@ -26,8 +26,6 @@
|
||||
package org.geysermc.geyser.inventory.updater;
|
||||
|
||||
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.geysermc.geyser.inventory.Inventory;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
@ -48,7 +46,6 @@ public class UIInventoryUpdater extends InventoryUpdater {
|
||||
slotPacket.setContainerId(ContainerId.UI);
|
||||
slotPacket.setSlot(bedrockSlot);
|
||||
slotPacket.setItem(inventory.getItem(i).getItemData(session));
|
||||
slotPacket.setContainerNameData(new FullContainerName(ContainerSlotType.ANVIL_INPUT, null));
|
||||
session.sendUpstreamPacket(slotPacket);
|
||||
}
|
||||
}
|
||||
@ -62,7 +59,6 @@ public class UIInventoryUpdater extends InventoryUpdater {
|
||||
slotPacket.setContainerId(ContainerId.UI);
|
||||
slotPacket.setSlot(translator.javaSlotToBedrock(javaSlot));
|
||||
slotPacket.setItem(inventory.getItem(javaSlot).getItemData(session));
|
||||
slotPacket.setContainerNameData(new FullContainerName(ContainerSlotType.ANVIL_INPUT, null));
|
||||
session.sendUpstreamPacket(slotPacket);
|
||||
return true;
|
||||
}
|
||||
|
@ -25,9 +25,41 @@
|
||||
|
||||
package org.geysermc.geyser.item;
|
||||
|
||||
import org.geysermc.geyser.item.components.Rarity;
|
||||
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.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 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 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 BAMBOO_PLANKS = register(new BlockItem(builder(), Blocks.BAMBOO_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 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 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 BEDROCK = register(new BlockItem(builder(), Blocks.BEDROCK));
|
||||
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_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 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 BUDDING_AMETHYST = register(new BlockItem(builder(), Blocks.BUDDING_AMETHYST));
|
||||
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 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 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 MANGROVE_LOG = register(new BlockItem(builder(), Blocks.MANGROVE_LOG));
|
||||
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_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_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_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));
|
||||
@ -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_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_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_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));
|
||||
@ -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 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 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 MANGROVE_WOOD = register(new BlockItem(builder(), Blocks.MANGROVE_WOOD));
|
||||
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 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 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 AZALEA_LEAVES = register(new BlockItem(builder(), Blocks.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 SUGAR_CANE = register(new BlockItem(builder(), Blocks.SUGAR_CANE));
|
||||
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 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 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 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));
|
||||
@ -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 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 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 BAMBOO_SLAB = register(new BlockItem(builder(), Blocks.BAMBOO_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_STAIRS = register(new BlockItem(builder(), Blocks.PURPUR_STAIRS));
|
||||
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 CRAFTING_TABLE = register(new BlockItem(builder(), Blocks.CRAFTING_TABLE));
|
||||
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 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 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 BAMBOO_FENCE = register(new BlockItem(builder(), Blocks.BAMBOO_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_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 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 ENDER_CHEST = register(new BlockItem(builder(), Blocks.ENDER_CHEST));
|
||||
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 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 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 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 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 COMMAND_BLOCK = register(new BlockItem(builder().rarity(Rarity.EPIC), Blocks.COMMAND_BLOCK));
|
||||
public static final Item BEACON = register(new BlockItem(builder().rarity(Rarity.RARE), Blocks.BEACON));
|
||||
public static final Item COMMAND_BLOCK = register(new BlockItem(builder(), Blocks.COMMAND_BLOCK));
|
||||
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 MOSSY_COBBLESTONE_WALL = register(new BlockItem(builder(), Blocks.MOSSY_COBBLESTONE_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 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 BARRIER = register(new BlockItem(builder().rarity(Rarity.EPIC), Blocks.BARRIER));
|
||||
public static final Item LIGHT = register(new BlockItem(builder().rarity(Rarity.EPIC), Blocks.LIGHT));
|
||||
public static final Item BARRIER = register(new BlockItem(builder(), Blocks.BARRIER));
|
||||
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 WHITE_CARPET = register(new BlockItem(builder(), Blocks.WHITE_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 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 REPEATING_COMMAND_BLOCK = register(new BlockItem(builder().rarity(Rarity.EPIC), 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 REPEATING_COMMAND_BLOCK = register(new BlockItem(builder(), Blocks.REPEATING_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 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 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 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 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));
|
||||
@ -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_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 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 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));
|
||||
@ -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 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 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 BAMBOO_BUTTON = register(new BlockItem(builder(), Blocks.BAMBOO_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 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 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 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));
|
||||
@ -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 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 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 BAMBOO_DOOR = register(new BlockItem(builder(), Blocks.BAMBOO_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 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 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 BAMBOO_TRAPDOOR = register(new BlockItem(builder(), Blocks.BAMBOO_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 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 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 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));
|
||||
@ -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 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 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_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)));
|
||||
@ -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 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 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_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_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 JIGSAW = register(new BlockItem(builder().rarity(Rarity.EPIC), Blocks.JIGSAW));
|
||||
public static final Item STRUCTURE_BLOCK = register(new BlockItem(builder(), Blocks.STRUCTURE_BLOCK));
|
||||
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_SCUTE = register(new Item("turtle_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 COOKED_PORKCHOP = register(new Item("cooked_porkchop", 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 ENCHANTED_GOLDEN_APPLE = register(new Item("enchanted_golden_apple", builder().rarity(Rarity.EPIC)));
|
||||
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()));
|
||||
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 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 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 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 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));
|
||||
@ -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 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 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 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));
|
||||
@ -969,6 +1025,22 @@ public final class Items {
|
||||
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 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 CLOCK = register(new Item("clock", builder()));
|
||||
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 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 POTION = register(new PotionItem("potion", builder().stackSize(1)));
|
||||
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 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 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 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 GLISTERING_MELON_SLICE = register(new Item("glistering_melon_slice", 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 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 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_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 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 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 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 GLOW_ITEM_FRAME = register(new Item("glow_item_frame", builder()));
|
||||
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 MAP = register(new MapItem("map", 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 WITHER_SKELETON_SKULL = register(new BlockItem(builder().rarity(Rarity.UNCOMMON), 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 ZOMBIE_HEAD = register(new BlockItem(builder().rarity(Rarity.UNCOMMON), 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 DRAGON_HEAD = register(new BlockItem(builder().rarity(Rarity.UNCOMMON), 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 NETHER_STAR = register(new Item("nether_star", builder().rarity(Rarity.UNCOMMON)));
|
||||
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(), Blocks.WITHER_SKELETON_SKULL, Blocks.WITHER_SKELETON_WALL_SKULL));
|
||||
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(), Blocks.ZOMBIE_HEAD, Blocks.ZOMBIE_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(), Blocks.DRAGON_HEAD, Blocks.DRAGON_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()));
|
||||
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_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 PRISMARINE_SHARD = register(new Item("prismarine_shard", 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_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 IRON_HORSE_ARMOR = register(new ArmorItem("iron_horse_armor", ArmorMaterial.IRON, 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 DIAMOND_HORSE_ARMOR = register(new ArmorItem("diamond_horse_armor", ArmorMaterial.DIAMOND, 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 Item("golden_horse_armor", 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 LEAD = register(new Item("lead", 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 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));
|
||||
@ -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 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 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 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));
|
||||
@ -1195,52 +1269,53 @@ public final class Items {
|
||||
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_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 SPECTRAL_ARROW = register(new Item("spectral_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 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 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 DEBUG_STICK = register(new Item("debug_stick", builder().stackSize(1).rarity(Rarity.EPIC).glint(true)));
|
||||
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_CAT = register(new Item("music_disc_cat", builder().stackSize(1).rarity(Rarity.RARE)));
|
||||
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_CHIRP = register(new Item("music_disc_chirp", builder().stackSize(1).rarity(Rarity.RARE)));
|
||||
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_MUSIC_BOX = register(new Item("music_disc_creator_music_box", builder().stackSize(1).rarity(Rarity.RARE)));
|
||||
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_MALL = register(new Item("music_disc_mall", builder().stackSize(1).rarity(Rarity.RARE)));
|
||||
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_STAL = register(new Item("music_disc_stal", builder().stackSize(1).rarity(Rarity.RARE)));
|
||||
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_WARD = register(new Item("music_disc_ward", builder().stackSize(1).rarity(Rarity.RARE)));
|
||||
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_WAIT = register(new Item("music_disc_wait", builder().stackSize(1).rarity(Rarity.RARE)));
|
||||
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_RELIC = register(new Item("music_disc_relic", builder().stackSize(1).rarity(Rarity.RARE)));
|
||||
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_PIGSTEP = register(new Item("music_disc_pigstep", builder().stackSize(1).rarity(Rarity.RARE)));
|
||||
public static final Item MUSIC_DISC_PRECIPICE = register(new Item("music_disc_precipice", builder().stackSize(1).rarity(Rarity.RARE)));
|
||||
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)));
|
||||
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)));
|
||||
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)));
|
||||
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)));
|
||||
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)));
|
||||
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)));
|
||||
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)));
|
||||
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)));
|
||||
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)));
|
||||
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)));
|
||||
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 TRIDENT = register(new Item("trident", builder().stackSize(1).maxDamage(250).attackDamage(9.0).rarity(Rarity.EPIC)));
|
||||
public static final Item PHANTOM_MEMBRANE = register(new Item("phantom_membrane", builder()));
|
||||
public static final Item TRIDENT = register(new Item("trident", builder().stackSize(1).maxDamage(250).attackDamage(9.0)));
|
||||
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 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 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 SKULL_BANNER_PATTERN = register(new Item("skull_banner_pattern", builder().stackSize(1).rarity(Rarity.UNCOMMON)));
|
||||
public static final Item MOJANG_BANNER_PATTERN = register(new Item("mojang_banner_pattern", builder().stackSize(1).rarity(Rarity.EPIC)));
|
||||
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)));
|
||||
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 PIGLIN_BANNER_PATTERN = register(new Item("piglin_banner_pattern", builder().stackSize(1).rarity(Rarity.UNCOMMON)));
|
||||
public static final Item FLOW_BANNER_PATTERN = register(new Item("flow_banner_pattern", builder().stackSize(1).rarity(Rarity.RARE)));
|
||||
public static final Item GUSTER_BANNER_PATTERN = register(new Item("guster_banner_pattern", builder().stackSize(1).rarity(Rarity.RARE)));
|
||||
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)));
|
||||
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 COMPOSTER = register(new BlockItem(builder(), Blocks.COMPOSTER));
|
||||
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 VAULT = register(new BlockItem(builder(), Blocks.VAULT));
|
||||
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();
|
||||
|
||||
|
@ -25,52 +25,47 @@
|
||||
|
||||
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.cloudburstmc.nbt.NbtMap;
|
||||
import org.geysermc.geyser.inventory.item.BedrockEnchantment;
|
||||
import org.geysermc.geyser.item.Items;
|
||||
import org.geysermc.geyser.item.type.Item;
|
||||
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.tags.GeyserHolderSet;
|
||||
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.List;
|
||||
import java.util.Map;
|
||||
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
|
||||
*/
|
||||
public record Enchantment(String identifier,
|
||||
Set<EnchantmentComponent> effects,
|
||||
HolderSet supportedItems,
|
||||
GeyserHolderSet<Item> supportedItems,
|
||||
int maxLevel,
|
||||
String description,
|
||||
int anvilCost,
|
||||
HolderSet exclusiveSet,
|
||||
GeyserHolderSet<Enchantment> exclusiveSet,
|
||||
@Nullable BedrockEnchantment bedrockEnchantment) {
|
||||
|
||||
public static Enchantment read(RegistryEntryContext context) {
|
||||
NbtMap data = context.data();
|
||||
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 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());
|
||||
|
||||
// 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;
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
// 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");
|
||||
}
|
||||
}
|
||||
|
@ -32,6 +32,7 @@ import org.geysermc.geyser.inventory.item.Potion;
|
||||
import org.geysermc.geyser.item.Items;
|
||||
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.DataComponentType;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.item.component.PotionContents;
|
||||
|
||||
@ -41,9 +42,9 @@ public class ArrowItem extends Item {
|
||||
}
|
||||
|
||||
@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());
|
||||
GeyserItemStack itemStack = super.translateToJava(itemData, mapping, mappings);
|
||||
GeyserItemStack itemStack = super.translateToJava(session, itemData, mapping, mappings);
|
||||
if (potion != null) {
|
||||
itemStack = Items.TIPPED_ARROW.newItemStack(itemStack.getAmount(), itemStack.getComponents());
|
||||
PotionContents contents = potion.toComponent();
|
||||
|
@ -43,11 +43,11 @@ public class CompassItem extends Item {
|
||||
}
|
||||
|
||||
@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)) {
|
||||
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
|
||||
@ -78,12 +78,12 @@ public class CompassItem extends Item {
|
||||
}
|
||||
|
||||
@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")) {
|
||||
// Revert the entry back to the compass
|
||||
mapping = mappings.getStoredItems().compass();
|
||||
}
|
||||
|
||||
return super.translateToJava(itemData, mapping, mappings);
|
||||
return super.translateToJava(session, itemData, mapping, mappings);
|
||||
}
|
||||
}
|
||||
|
@ -28,6 +28,7 @@ package org.geysermc.geyser.item.type;
|
||||
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
|
||||
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.DataComponentType;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents;
|
||||
|
||||
@ -37,8 +38,8 @@ public class FilledMapItem extends MapItem {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemData.Builder translateToBedrock(int count, DataComponents components, ItemMapping mapping, ItemMappings mappings) {
|
||||
ItemData.Builder builder = super.translateToBedrock(count, components, mapping, mappings);
|
||||
public ItemData.Builder translateToBedrock(GeyserSession session, int count, DataComponents components, ItemMapping mapping, ItemMappings mappings) {
|
||||
ItemData.Builder builder = super.translateToBedrock(session, count, components, mapping, mappings);
|
||||
if (components == null) {
|
||||
// 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
|
||||
|
@ -28,8 +28,11 @@ package org.geysermc.geyser.item.type;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
|
||||
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.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.item.component.DataComponentType;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents;
|
||||
@ -41,24 +44,45 @@ public class GoatHornItem extends Item {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemData.Builder translateToBedrock(int count, DataComponents components, ItemMapping mapping, ItemMappings mappings) {
|
||||
ItemData.Builder builder = super.translateToBedrock(count, components, mapping, mappings);
|
||||
public ItemData.Builder translateToBedrock(GeyserSession session, int count, DataComponents components, ItemMapping mapping, ItemMappings mappings) {
|
||||
ItemData.Builder builder = super.translateToBedrock(session, count, components, mapping, mappings);
|
||||
if (components == null) {
|
||||
return builder;
|
||||
}
|
||||
Holder<Instrument> instrument = components.get(DataComponentType.INSTRUMENT);
|
||||
if (instrument != null && instrument.isId()) {
|
||||
builder.damage(instrument.id());
|
||||
|
||||
Holder<Instrument> holder = components.get(DataComponentType.INSTRUMENT);
|
||||
if (holder != null) {
|
||||
GeyserInstrument instrument = GeyserInstrument.fromHolder(session, holder);
|
||||
int bedrockId = instrument.bedrockId();
|
||||
if (bedrockId >= 0) {
|
||||
builder.damage(bedrockId);
|
||||
}
|
||||
}
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull GeyserItemStack translateToJava(@NonNull ItemData itemData, @NonNull ItemMapping mapping, @NonNull ItemMappings mappings) {
|
||||
GeyserItemStack itemStack = super.translateToJava(itemData, mapping, mappings);
|
||||
public void translateComponentsToBedrock(@NonNull GeyserSession session, @NonNull DataComponents components, @NonNull BedrockItemBuilder builder) {
|
||||
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();
|
||||
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;
|
||||
}
|
||||
|
@ -115,7 +115,7 @@ public class Item {
|
||||
|
||||
/* 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) {
|
||||
// Return, essentially, air
|
||||
return ItemData.builder();
|
||||
@ -130,7 +130,7 @@ public class Item {
|
||||
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());
|
||||
}
|
||||
|
||||
|
79
core/src/main/java/org/geysermc/geyser/item/type/LightItem.java
Normale Datei
79
core/src/main/java/org/geysermc/geyser/item/type/LightItem.java
Normale Datei
@ -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;
|
||||
}
|
||||
}
|
@ -31,6 +31,7 @@ import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
|
||||
import org.geysermc.geyser.inventory.GeyserItemStack;
|
||||
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.DataComponentType;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents;
|
||||
|
||||
@ -40,8 +41,8 @@ public class OminousBottleItem extends Item {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemData.Builder translateToBedrock(int count, @Nullable DataComponents components, ItemMapping mapping, ItemMappings mappings) {
|
||||
var builder = super.translateToBedrock(count, components, mapping, mappings);
|
||||
public ItemData.Builder translateToBedrock(GeyserSession session, int count, @Nullable DataComponents components, ItemMapping mapping, ItemMappings mappings) {
|
||||
var builder = super.translateToBedrock(session, count, components, mapping, mappings);
|
||||
if (components == null) {
|
||||
// Level 1 ominous bottle is null components - Java 1.21.
|
||||
return builder;
|
||||
@ -54,9 +55,9 @@ public class OminousBottleItem extends Item {
|
||||
}
|
||||
|
||||
@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.
|
||||
GeyserItemStack itemStack = super.translateToJava(itemData, mapping, mappings);
|
||||
GeyserItemStack itemStack = super.translateToJava(session, itemData, mapping, mappings);
|
||||
int damage = itemData.getDamage();
|
||||
if (damage == 0) {
|
||||
return itemStack;
|
||||
|
@ -33,6 +33,7 @@ import org.geysermc.geyser.inventory.GeyserItemStack;
|
||||
import org.geysermc.geyser.inventory.item.Potion;
|
||||
import org.geysermc.geyser.registry.type.ItemMapping;
|
||||
import org.geysermc.geyser.registry.type.ItemMappings;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
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.DataComponents;
|
||||
@ -44,8 +45,8 @@ public class PotionItem extends Item {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemData.Builder translateToBedrock(int count, DataComponents components, ItemMapping mapping, ItemMappings mappings) {
|
||||
if (components == null) return super.translateToBedrock(count, components, mapping, mappings);
|
||||
public ItemData.Builder translateToBedrock(GeyserSession session, int count, DataComponents components, ItemMapping mapping, ItemMappings mappings) {
|
||||
if (components == null) return super.translateToBedrock(session, count, components, mapping, mappings);
|
||||
PotionContents potionContents = components.get(DataComponentType.POTION_CONTENTS);
|
||||
if (potionContents != null) {
|
||||
ItemDefinition customItemDefinition = CustomItemTranslator.getCustomItem(components, mapping);
|
||||
@ -64,13 +65,13 @@ public class PotionItem extends Item {
|
||||
.count(count);
|
||||
}
|
||||
}
|
||||
return super.translateToBedrock(count, components, mapping, mappings);
|
||||
return super.translateToBedrock(session, count, components, mapping, mappings);
|
||||
}
|
||||
|
||||
@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());
|
||||
GeyserItemStack itemStack = super.translateToJava(itemData, mapping, mappings);
|
||||
GeyserItemStack itemStack = super.translateToJava(session, itemData, mapping, mappings);
|
||||
if (potion != null) {
|
||||
itemStack.getOrCreateComponents().put(DataComponentType.POTION_CONTENTS, potion.toComponent());
|
||||
}
|
||||
|
@ -30,6 +30,7 @@ import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.inventory.item.Potion;
|
||||
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.DataComponentType;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.item.component.PotionContents;
|
||||
@ -40,7 +41,7 @@ public class TippedArrowItem extends ArrowItem {
|
||||
}
|
||||
|
||||
@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) {
|
||||
PotionContents potionContents = components.get(DataComponentType.POTION_CONTENTS);
|
||||
if (potionContents != null) {
|
||||
@ -54,6 +55,6 @@ public class TippedArrowItem extends ArrowItem {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -25,17 +25,84 @@
|
||||
|
||||
package org.geysermc.geyser.level;
|
||||
|
||||
import lombok.ToString;
|
||||
|
||||
/**
|
||||
* 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
|
||||
* the client.
|
||||
*
|
||||
*/
|
||||
@ToString
|
||||
public class BedrockDimension {
|
||||
|
||||
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 record BedrockDimension(int minY, int height, boolean doUpperHeightWarn) {
|
||||
public static final BedrockDimension OVERWORLD = new BedrockDimension(-64, 384, true);
|
||||
public static final BedrockDimension THE_NETHER = new BedrockDimension(0, 128, false);
|
||||
public static final BedrockDimension THE_END = new BedrockDimension(0, 256, true);
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -63,12 +63,19 @@ public record JavaDimension(int minY, int maxY, boolean piglinSafe, boolean ultr
|
||||
if ("minecraft".equals(id.namespace())) {
|
||||
String identifier = id.asString();
|
||||
bedrockId = DimensionUtils.javaToBedrock(identifier);
|
||||
isNetherLike = DimensionUtils.NETHER_IDENTIFIER.equals(identifier);
|
||||
isNetherLike = BedrockDimension.NETHER_IDENTIFIER.equals(identifier);
|
||||
} else {
|
||||
// Effects should give is a clue on how this (custom) dimension is supposed to look like
|
||||
String effects = dimension.getString("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);
|
||||
|
@ -26,24 +26,15 @@
|
||||
package org.geysermc.geyser.level;
|
||||
|
||||
import org.cloudburstmc.nbt.NbtMap;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.session.cache.registry.RegistryEntryContext;
|
||||
import org.geysermc.geyser.translator.text.MessageTranslator;
|
||||
import org.geysermc.geyser.util.SoundUtils;
|
||||
|
||||
public record JukeboxSong(String soundEvent, String description) {
|
||||
|
||||
public static JukeboxSong read(RegistryEntryContext context) {
|
||||
NbtMap data = context.data();
|
||||
Object soundEventObject = data.get("sound_event");
|
||||
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 soundEvent = SoundUtils.readSoundEvent(data, "jukebox song " + context.id());
|
||||
String description = MessageTranslator.deserializeDescription(context.session(), data);
|
||||
return new JukeboxSong(soundEvent, description);
|
||||
}
|
||||
|
@ -62,6 +62,9 @@ public final class Blocks {
|
||||
public static final Block ACACIA_PLANKS = register(new Block("acacia_planks", builder().destroyTime(2.0f)));
|
||||
public static final Block CHERRY_PLANKS = register(new Block("cherry_planks", builder().destroyTime(2.0f)));
|
||||
public static final Block DARK_OAK_PLANKS = register(new Block("dark_oak_planks", builder().destroyTime(2.0f)));
|
||||
public static final Block PALE_OAK_WOOD = register(new Block("pale_oak_wood", builder().destroyTime(2.0f)
|
||||
.enumState(AXIS, Axis.VALUES)));
|
||||
public static final Block PALE_OAK_PLANKS = register(new Block("pale_oak_planks", builder().destroyTime(2.0f)));
|
||||
public static final Block MANGROVE_PLANKS = register(new Block("mangrove_planks", builder().destroyTime(2.0f)));
|
||||
public static final Block BAMBOO_PLANKS = register(new Block("bamboo_planks", builder().destroyTime(2.0f)));
|
||||
public static final Block BAMBOO_MOSAIC = register(new Block("bamboo_mosaic", builder().destroyTime(2.0f)));
|
||||
@ -79,6 +82,8 @@ public final class Blocks {
|
||||
.intState(STAGE)));
|
||||
public static final Block DARK_OAK_SAPLING = register(new Block("dark_oak_sapling", builder().pushReaction(PistonBehavior.DESTROY)
|
||||
.intState(STAGE)));
|
||||
public static final Block PALE_OAK_SAPLING = register(new Block("pale_oak_sapling", builder().pushReaction(PistonBehavior.DESTROY)
|
||||
.intState(STAGE)));
|
||||
public static final Block MANGROVE_PROPAGULE = register(new Block("mangrove_propagule", builder().pushReaction(PistonBehavior.DESTROY)
|
||||
.intState(AGE_4)
|
||||
.booleanState(HANGING)
|
||||
@ -117,6 +122,8 @@ public final class Blocks {
|
||||
.enumState(AXIS, Axis.VALUES)));
|
||||
public static final Block DARK_OAK_LOG = register(new Block("dark_oak_log", builder().destroyTime(2.0f)
|
||||
.enumState(AXIS, Axis.VALUES)));
|
||||
public static final Block PALE_OAK_LOG = register(new Block("pale_oak_log", builder().destroyTime(2.0f)
|
||||
.enumState(AXIS, Axis.VALUES)));
|
||||
public static final Block MANGROVE_LOG = register(new Block("mangrove_log", builder().destroyTime(2.0f)
|
||||
.enumState(AXIS, Axis.VALUES)));
|
||||
public static final Block MANGROVE_ROOTS = register(new Block("mangrove_roots", builder().destroyTime(0.7f)
|
||||
@ -137,6 +144,8 @@ public final class Blocks {
|
||||
.enumState(AXIS, Axis.VALUES)));
|
||||
public static final Block STRIPPED_DARK_OAK_LOG = register(new Block("stripped_dark_oak_log", builder().destroyTime(2.0f)
|
||||
.enumState(AXIS, Axis.VALUES)));
|
||||
public static final Block STRIPPED_PALE_OAK_LOG = register(new Block("stripped_pale_oak_log", builder().destroyTime(2.0f)
|
||||
.enumState(AXIS, Axis.VALUES)));
|
||||
public static final Block STRIPPED_OAK_LOG = register(new Block("stripped_oak_log", builder().destroyTime(2.0f)
|
||||
.enumState(AXIS, Axis.VALUES)));
|
||||
public static final Block STRIPPED_MANGROVE_LOG = register(new Block("stripped_mangrove_log", builder().destroyTime(2.0f)
|
||||
@ -173,6 +182,8 @@ public final class Blocks {
|
||||
.enumState(AXIS, Axis.VALUES)));
|
||||
public static final Block STRIPPED_DARK_OAK_WOOD = register(new Block("stripped_dark_oak_wood", builder().destroyTime(2.0f)
|
||||
.enumState(AXIS, Axis.VALUES)));
|
||||
public static final Block STRIPPED_PALE_OAK_WOOD = register(new Block("stripped_pale_oak_wood", builder().destroyTime(2.0f)
|
||||
.enumState(AXIS, Axis.VALUES)));
|
||||
public static final Block STRIPPED_MANGROVE_WOOD = register(new Block("stripped_mangrove_wood", builder().destroyTime(2.0f)
|
||||
.enumState(AXIS, Axis.VALUES)));
|
||||
public static final Block OAK_LEAVES = register(new Block("oak_leaves", builder().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY)
|
||||
@ -203,6 +214,10 @@ public final class Blocks {
|
||||
.intState(DISTANCE)
|
||||
.booleanState(PERSISTENT)
|
||||
.booleanState(WATERLOGGED)));
|
||||
public static final Block PALE_OAK_LEAVES = register(new Block("pale_oak_leaves", builder().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY)
|
||||
.intState(DISTANCE)
|
||||
.booleanState(PERSISTENT)
|
||||
.booleanState(WATERLOGGED)));
|
||||
public static final Block MANGROVE_LEAVES = register(new Block("mangrove_leaves", builder().destroyTime(0.2f).pushReaction(PistonBehavior.DESTROY)
|
||||
.intState(DISTANCE)
|
||||
.booleanState(PERSISTENT)
|
||||
@ -383,6 +398,9 @@ public final class Blocks {
|
||||
.booleanState(WEST)));
|
||||
public static final Block SOUL_FIRE = register(new Block("soul_fire", builder().pushReaction(PistonBehavior.DESTROY)));
|
||||
public static final Block SPAWNER = register(new SpawnerBlock("spawner", builder().setBlockEntity(BlockEntityType.MOB_SPAWNER).requiresCorrectToolForDrops().destroyTime(5.0f)));
|
||||
public static final Block CREAKING_HEART = register(new Block("creaking_heart", builder().setBlockEntity(BlockEntityType.CREAKING_HEART).destroyTime(5.0f)
|
||||
.enumState(AXIS, Axis.VALUES)
|
||||
.enumState(CREAKING)));
|
||||
public static final Block OAK_STAIRS = register(new Block("oak_stairs", builder().destroyTime(2.0f)
|
||||
.enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
|
||||
.enumState(HALF)
|
||||
@ -430,6 +448,9 @@ public final class Blocks {
|
||||
public static final Block DARK_OAK_SIGN = register(new Block("dark_oak_sign", builder().setBlockEntity(BlockEntityType.SIGN).destroyTime(1.0f)
|
||||
.intState(ROTATION_16)
|
||||
.booleanState(WATERLOGGED)));
|
||||
public static final Block PALE_OAK_SIGN = register(new Block("pale_oak_sign", builder().setBlockEntity(BlockEntityType.SIGN).destroyTime(1.0f)
|
||||
.intState(ROTATION_16)
|
||||
.booleanState(WATERLOGGED)));
|
||||
public static final Block MANGROVE_SIGN = register(new Block("mangrove_sign", builder().setBlockEntity(BlockEntityType.SIGN).destroyTime(1.0f)
|
||||
.intState(ROTATION_16)
|
||||
.booleanState(WATERLOGGED)));
|
||||
@ -474,6 +495,9 @@ public final class Blocks {
|
||||
public static final Block DARK_OAK_WALL_SIGN = register(new Block("dark_oak_wall_sign", builder().setBlockEntity(BlockEntityType.SIGN).destroyTime(1.0f)
|
||||
.enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
|
||||
.booleanState(WATERLOGGED)));
|
||||
public static final Block PALE_OAK_WALL_SIGN = register(new Block("pale_oak_wall_sign", builder().setBlockEntity(BlockEntityType.SIGN).destroyTime(1.0f)
|
||||
.enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
|
||||
.booleanState(WATERLOGGED)));
|
||||
public static final Block MANGROVE_WALL_SIGN = register(new Block("mangrove_wall_sign", builder().setBlockEntity(BlockEntityType.SIGN).destroyTime(1.0f)
|
||||
.enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
|
||||
.booleanState(WATERLOGGED)));
|
||||
@ -508,6 +532,10 @@ public final class Blocks {
|
||||
.booleanState(ATTACHED)
|
||||
.intState(ROTATION_16)
|
||||
.booleanState(WATERLOGGED)));
|
||||
public static final Block PALE_OAK_HANGING_SIGN = register(new Block("pale_oak_hanging_sign", builder().setBlockEntity(BlockEntityType.HANGING_SIGN).destroyTime(1.0f)
|
||||
.booleanState(ATTACHED)
|
||||
.intState(ROTATION_16)
|
||||
.booleanState(WATERLOGGED)));
|
||||
public static final Block CRIMSON_HANGING_SIGN = register(new Block("crimson_hanging_sign", builder().setBlockEntity(BlockEntityType.HANGING_SIGN).destroyTime(1.0f)
|
||||
.booleanState(ATTACHED)
|
||||
.intState(ROTATION_16)
|
||||
@ -545,6 +573,9 @@ public final class Blocks {
|
||||
public static final Block DARK_OAK_WALL_HANGING_SIGN = register(new Block("dark_oak_wall_hanging_sign", builder().setBlockEntity(BlockEntityType.HANGING_SIGN).destroyTime(1.0f)
|
||||
.enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
|
||||
.booleanState(WATERLOGGED)));
|
||||
public static final Block PALE_OAK_WALL_HANGING_SIGN = register(new Block("pale_oak_wall_hanging_sign", builder().setBlockEntity(BlockEntityType.HANGING_SIGN).destroyTime(1.0f)
|
||||
.enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
|
||||
.booleanState(WATERLOGGED)));
|
||||
public static final Block MANGROVE_WALL_HANGING_SIGN = register(new Block("mangrove_wall_hanging_sign", builder().setBlockEntity(BlockEntityType.HANGING_SIGN).destroyTime(1.0f)
|
||||
.enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
|
||||
.booleanState(WATERLOGGED)));
|
||||
@ -583,6 +614,8 @@ public final class Blocks {
|
||||
.booleanState(POWERED)));
|
||||
public static final Block DARK_OAK_PRESSURE_PLATE = register(new Block("dark_oak_pressure_plate", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY)
|
||||
.booleanState(POWERED)));
|
||||
public static final Block PALE_OAK_PRESSURE_PLATE = register(new Block("pale_oak_pressure_plate", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY)
|
||||
.booleanState(POWERED)));
|
||||
public static final Block MANGROVE_PRESSURE_PLATE = register(new Block("mangrove_pressure_plate", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY)
|
||||
.booleanState(POWERED)));
|
||||
public static final Block BAMBOO_PRESSURE_PLATE = register(new Block("bamboo_pressure_plate", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY)
|
||||
@ -699,6 +732,12 @@ public final class Blocks {
|
||||
.booleanState(OPEN)
|
||||
.booleanState(POWERED)
|
||||
.booleanState(WATERLOGGED)));
|
||||
public static final Block PALE_OAK_TRAPDOOR = register(new TrapDoorBlock("pale_oak_trapdoor", builder().destroyTime(3.0f)
|
||||
.enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
|
||||
.enumState(HALF)
|
||||
.booleanState(OPEN)
|
||||
.booleanState(POWERED)
|
||||
.booleanState(WATERLOGGED)));
|
||||
public static final Block MANGROVE_TRAPDOOR = register(new TrapDoorBlock("mangrove_trapdoor", builder().destroyTime(3.0f)
|
||||
.enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
|
||||
.enumState(HALF)
|
||||
@ -907,6 +946,7 @@ public final class Blocks {
|
||||
public static final Block POTTED_ACACIA_SAPLING = register(new FlowerPotBlock("potted_acacia_sapling", ACACIA_SAPLING, builder().pushReaction(PistonBehavior.DESTROY)));
|
||||
public static final Block POTTED_CHERRY_SAPLING = register(new FlowerPotBlock("potted_cherry_sapling", CHERRY_SAPLING, builder().pushReaction(PistonBehavior.DESTROY)));
|
||||
public static final Block POTTED_DARK_OAK_SAPLING = register(new FlowerPotBlock("potted_dark_oak_sapling", DARK_OAK_SAPLING, builder().pushReaction(PistonBehavior.DESTROY)));
|
||||
public static final Block POTTED_PALE_OAK_SAPLING = register(new FlowerPotBlock("potted_pale_oak_sapling", PALE_OAK_SAPLING, builder().pushReaction(PistonBehavior.DESTROY)));
|
||||
public static final Block POTTED_MANGROVE_PROPAGULE = register(new FlowerPotBlock("potted_mangrove_propagule", MANGROVE_PROPAGULE, builder().pushReaction(PistonBehavior.DESTROY)));
|
||||
public static final Block POTTED_FERN = register(new FlowerPotBlock("potted_fern", FERN, builder().pushReaction(PistonBehavior.DESTROY)));
|
||||
public static final Block POTTED_DANDELION = register(new FlowerPotBlock("potted_dandelion", DANDELION, builder().pushReaction(PistonBehavior.DESTROY)));
|
||||
@ -958,6 +998,10 @@ public final class Blocks {
|
||||
.enumState(ATTACH_FACE)
|
||||
.enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
|
||||
.booleanState(POWERED)));
|
||||
public static final Block PALE_OAK_BUTTON = register(new Block("pale_oak_button", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY)
|
||||
.enumState(ATTACH_FACE)
|
||||
.enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
|
||||
.booleanState(POWERED)));
|
||||
public static final Block MANGROVE_BUTTON = register(new Block("mangrove_button", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY)
|
||||
.enumState(ATTACH_FACE)
|
||||
.enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
|
||||
@ -1177,6 +1221,11 @@ public final class Blocks {
|
||||
.enumState(HALF)
|
||||
.enumState(STAIRS_SHAPE)
|
||||
.booleanState(WATERLOGGED)));
|
||||
public static final Block PALE_OAK_STAIRS = register(new Block("pale_oak_stairs", builder().destroyTime(2.0f)
|
||||
.enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
|
||||
.enumState(HALF)
|
||||
.enumState(STAIRS_SHAPE)
|
||||
.booleanState(WATERLOGGED)));
|
||||
public static final Block MANGROVE_STAIRS = register(new Block("mangrove_stairs", builder().destroyTime(2.0f)
|
||||
.enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
|
||||
.enumState(HALF)
|
||||
@ -1358,6 +1407,9 @@ public final class Blocks {
|
||||
public static final Block DARK_OAK_SLAB = register(new Block("dark_oak_slab", builder().destroyTime(2.0f)
|
||||
.enumState(SLAB_TYPE)
|
||||
.booleanState(WATERLOGGED)));
|
||||
public static final Block PALE_OAK_SLAB = register(new Block("pale_oak_slab", builder().destroyTime(2.0f)
|
||||
.enumState(SLAB_TYPE)
|
||||
.booleanState(WATERLOGGED)));
|
||||
public static final Block MANGROVE_SLAB = register(new Block("mangrove_slab", builder().destroyTime(2.0f)
|
||||
.enumState(SLAB_TYPE)
|
||||
.booleanState(WATERLOGGED)));
|
||||
@ -1443,6 +1495,11 @@ public final class Blocks {
|
||||
.booleanState(IN_WALL)
|
||||
.booleanState(OPEN)
|
||||
.booleanState(POWERED)));
|
||||
public static final Block PALE_OAK_FENCE_GATE = register(new Block("pale_oak_fence_gate", builder().destroyTime(2.0f)
|
||||
.enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
|
||||
.booleanState(IN_WALL)
|
||||
.booleanState(OPEN)
|
||||
.booleanState(POWERED)));
|
||||
public static final Block MANGROVE_FENCE_GATE = register(new Block("mangrove_fence_gate", builder().destroyTime(2.0f)
|
||||
.enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
|
||||
.booleanState(IN_WALL)
|
||||
@ -1489,6 +1546,12 @@ public final class Blocks {
|
||||
.booleanState(SOUTH)
|
||||
.booleanState(WATERLOGGED)
|
||||
.booleanState(WEST)));
|
||||
public static final Block PALE_OAK_FENCE = register(new Block("pale_oak_fence", builder().destroyTime(2.0f)
|
||||
.booleanState(EAST)
|
||||
.booleanState(NORTH)
|
||||
.booleanState(SOUTH)
|
||||
.booleanState(WATERLOGGED)
|
||||
.booleanState(WEST)));
|
||||
public static final Block MANGROVE_FENCE = register(new Block("mangrove_fence", builder().destroyTime(2.0f)
|
||||
.booleanState(EAST)
|
||||
.booleanState(NORTH)
|
||||
@ -1537,6 +1600,12 @@ public final class Blocks {
|
||||
.enumState(DOOR_HINGE)
|
||||
.booleanState(OPEN)
|
||||
.booleanState(POWERED)));
|
||||
public static final Block PALE_OAK_DOOR = register(new DoorBlock("pale_oak_door", builder().destroyTime(3.0f).pushReaction(PistonBehavior.DESTROY)
|
||||
.enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
|
||||
.enumState(DOUBLE_BLOCK_HALF)
|
||||
.enumState(DOOR_HINGE)
|
||||
.booleanState(OPEN)
|
||||
.booleanState(POWERED)));
|
||||
public static final Block MANGROVE_DOOR = register(new DoorBlock("mangrove_door", builder().destroyTime(3.0f).pushReaction(PistonBehavior.DESTROY)
|
||||
.enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
|
||||
.enumState(DOUBLE_BLOCK_HALF)
|
||||
@ -2812,6 +2881,15 @@ public final class Blocks {
|
||||
.enumState(VAULT_STATE)));
|
||||
public static final Block HEAVY_CORE = register(new Block("heavy_core", builder().destroyTime(10.0f)
|
||||
.booleanState(WATERLOGGED)));
|
||||
public static final Block PALE_MOSS_BLOCK = register(new Block("pale_moss_block", builder().destroyTime(0.1f).pushReaction(PistonBehavior.DESTROY)));
|
||||
public static final Block PALE_MOSS_CARPET = register(new Block("pale_moss_carpet", builder().destroyTime(0.1f).pushReaction(PistonBehavior.DESTROY)
|
||||
.booleanState(BOTTOM)
|
||||
.enumState(EAST_WALL)
|
||||
.enumState(NORTH_WALL)
|
||||
.enumState(SOUTH_WALL)
|
||||
.enumState(WEST_WALL)));
|
||||
public static final Block PALE_HANGING_MOSS = register(new Block("pale_hanging_moss", builder().destroyTime(0.1f).pushReaction(PistonBehavior.DESTROY)
|
||||
.booleanState(TIP)));
|
||||
|
||||
private static <T extends Block> T register(T block) {
|
||||
block.setJavaId(BlockRegistries.JAVA_BLOCKS.get().size());
|
||||
|
@ -47,6 +47,7 @@ public final class Properties {
|
||||
public static final BooleanProperty INVERTED = BooleanProperty.create("inverted");
|
||||
public static final BooleanProperty IN_WALL = BooleanProperty.create("in_wall");
|
||||
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 OCCUPIED = BooleanProperty.create("occupied");
|
||||
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 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 CREAKING = BasicEnumProperty.create("creaking", "disabled", "dormant", "active");
|
||||
public static final BooleanProperty OMINOUS = BooleanProperty.create("ominous");
|
||||
}
|
||||
|
@ -63,7 +63,7 @@ public final class BlockState {
|
||||
return null;
|
||||
}
|
||||
//noinspection unchecked
|
||||
return (T) get(property);
|
||||
return (T) value;
|
||||
}
|
||||
|
||||
public <T extends Comparable<T>> T getValue(Property<T> property, T def) {
|
||||
|
@ -27,6 +27,7 @@ package org.geysermc.geyser.level.physics;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import net.kyori.adventure.util.TriState;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.cloudburstmc.math.GenericMath;
|
||||
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.
|
||||
* @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();
|
||||
// Bedrock clients tend to fall off of honey blocks, so we need to teleport them to the new position
|
||||
if (pistonCache.isPlayerAttachedToHoney()) {
|
||||
@ -176,7 +177,7 @@ public class CollisionManager {
|
||||
playerBoundingBox.setMiddleY(position.getY() + playerBoundingBox.getSizeY() / 2);
|
||||
playerBoundingBox.setMiddleZ(position.getZ());
|
||||
|
||||
return playerBoundingBox.getBottomCenter();
|
||||
return new CollisionResult(playerBoundingBox.getBottomCenter(), TriState.NOT_SET);
|
||||
}
|
||||
|
||||
Vector3d startingPos = playerBoundingBox.getBottomCenter();
|
||||
@ -204,16 +205,16 @@ public class CollisionManager {
|
||||
PlayerEntity playerEntity = session.getPlayerEntity();
|
||||
// Client will dismount if on a vehicle
|
||||
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
|
||||
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
|
||||
@ -415,45 +416,39 @@ public class CollisionManager {
|
||||
return BlockUtils.getCollision(blockId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if the block located at the player's floor position plus 1 would intersect with the player,
|
||||
* were they not sneaking
|
||||
*/
|
||||
public boolean mustPlayerSneakHere() {
|
||||
return checkPose(EntityDefinitions.PLAYER.height());
|
||||
public boolean isOnGround() {
|
||||
// Temporary until pre-1.21.30 support is dropped.
|
||||
Vector3d bottomCenter = playerBoundingBox.getBottomCenter();
|
||||
Vector3i groundPos = Vector3i.from(bottomCenter.getX(), bottomCenter.getY() - 1, bottomCenter.getZ());
|
||||
BlockCollision collision = BlockUtils.getCollisionAt(session, groundPos);
|
||||
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);
|
||||
// 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* @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;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return if the player is currently in a water block
|
||||
|
@ -23,11 +23,13 @@
|
||||
* @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 {
|
||||
int ordinal();
|
||||
public record CollisionResult(Vector3d correctedMovement, TriState onGround) {
|
||||
}
|
@ -31,11 +31,13 @@ import org.cloudburstmc.protocol.bedrock.codec.BedrockCodecHelper;
|
||||
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.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.SetEntityLinkSerializer_v291;
|
||||
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.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.v557.serializer.SetEntityDataSerializer_v557;
|
||||
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.v729.serializer.InventoryContentSerializer_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.BedrockPacket;
|
||||
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.MobArmorEquipmentPacket;
|
||||
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.NpcRequestPacket;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.PhotoInfoRequestPacket;
|
||||
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.PlayerInputPacket;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.PlayerSkinPacket;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.PurchaseReceiptPacket;
|
||||
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.SetEntityDataPacket;
|
||||
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() {
|
||||
@Override
|
||||
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.
|
||||
*/
|
||||
@ -262,11 +297,14 @@ class CodecProcessor {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
static BedrockCodec processCodec(BedrockCodec codec) {
|
||||
boolean is748OrAbove = codec.getProtocolVersion() >= 748;
|
||||
boolean is729OrAbove = codec.getProtocolVersion() >= 729;
|
||||
boolean is712OrAbove = codec.getProtocolVersion() >= 712;
|
||||
|
||||
BedrockPacketSerializer<InventoryContentPacket> inventoryContentSerializer;
|
||||
if (is729OrAbove) {
|
||||
if (is748OrAbove) {
|
||||
inventoryContentSerializer = INVENTORY_CONTENT_SERIALIZER_V748;
|
||||
} else if (is729OrAbove) {
|
||||
inventoryContentSerializer = INVENTORY_CONTENT_SERIALIZER_V729;
|
||||
} else if (is712OrAbove) {
|
||||
inventoryContentSerializer = INVENTORY_CONTENT_SERIALIZER_V712;
|
||||
@ -275,7 +313,9 @@ class CodecProcessor {
|
||||
}
|
||||
|
||||
BedrockPacketSerializer<InventorySlotPacket> inventorySlotSerializer;
|
||||
if (is729OrAbove) {
|
||||
if (is748OrAbove) {
|
||||
inventorySlotSerializer = INVENTORY_SLOT_SERIALIZER_V748;
|
||||
} else if (is729OrAbove) {
|
||||
inventorySlotSerializer = INVENTORY_SLOT_SERIALIZER_V729;
|
||||
} else if (is712OrAbove) {
|
||||
inventorySlotSerializer = INVENTORY_SLOT_SERIALIZER_V712;
|
||||
@ -297,7 +337,6 @@ class CodecProcessor {
|
||||
.updateSerializer(ClientCheatAbilityPacket.class, ILLEGAL_SERIALIZER)
|
||||
.updateSerializer(CraftingEventPacket.class, ILLEGAL_SERIALIZER)
|
||||
// Illegal unusued serverbound packets that relate to unused features
|
||||
.updateSerializer(PlayerAuthInputPacket.class, ILLEGAL_SERIALIZER)
|
||||
.updateSerializer(ClientCacheBlobStatusPacket.class, ILLEGAL_SERIALIZER)
|
||||
.updateSerializer(SubClientLoginPacket.class, ILLEGAL_SERIALIZER)
|
||||
.updateSerializer(SubChunkRequestPacket.class, ILLEGAL_SERIALIZER)
|
||||
@ -313,6 +352,10 @@ class CodecProcessor {
|
||||
// Illegal when serverbound due to Geyser specific setup
|
||||
.updateSerializer(InventoryContentPacket.class, inventoryContentSerializer)
|
||||
.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
|
||||
.updateSerializer(BossEventPacket.class, BOSS_EVENT_SERIALIZER)
|
||||
.updateSerializer(MobArmorEquipmentPacket.class, is712OrAbove ? MOB_ARMOR_EQUIPMENT_SERIALIZER_V712 : MOB_ARMOR_EQUIPMENT_SERIALIZER_V291)
|
||||
|
@ -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.v712.Bedrock_v712;
|
||||
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.geysermc.geyser.session.GeyserSession;
|
||||
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
|
||||
* release of the game that Geyser supports.
|
||||
*/
|
||||
public static final BedrockCodec DEFAULT_BEDROCK_CODEC = CodecProcessor.processCodec(Bedrock_v729.CODEC.toBuilder()
|
||||
.minecraftVersion("1.21.30")
|
||||
public static final BedrockCodec DEFAULT_BEDROCK_CODEC = CodecProcessor.processCodec(Bedrock_v748.CODEC.toBuilder()
|
||||
.minecraftVersion("1.21.44")
|
||||
.build());
|
||||
|
||||
/**
|
||||
@ -78,7 +79,12 @@ public final class GameProtocol {
|
||||
SUPPORTED_BEDROCK_CODECS.add(CodecProcessor.processCodec(Bedrock_v712.CODEC.toBuilder()
|
||||
.minecraftVersion("1.21.20 - 1.21.23")
|
||||
.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();
|
||||
}
|
||||
|
||||
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.
|
||||
*
|
||||
|
@ -26,6 +26,7 @@
|
||||
package org.geysermc.geyser.network;
|
||||
|
||||
import io.netty.buffer.Unpooled;
|
||||
import org.cloudburstmc.math.vector.Vector2f;
|
||||
import org.cloudburstmc.protocol.bedrock.BedrockDisconnectReasons;
|
||||
import org.cloudburstmc.protocol.bedrock.codec.BedrockCodec;
|
||||
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.LoginPacket;
|
||||
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.PlayStatusPacket;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.PlayerAuthInputPacket;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.RequestNetworkSettingsPacket;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.ResourcePackChunkDataPacket;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.ResourcePackChunkRequestPacket;
|
||||
@ -209,7 +210,7 @@ public class UpstreamPacketHandler extends LoggingPacketHandler {
|
||||
ResourcePackManifest.Header header = pack.manifest().header();
|
||||
resourcePacksInfo.getResourcePackInfos().add(new ResourcePacksInfoPacket.Entry(
|
||||
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());
|
||||
session.sendUpstreamPacket(resourcePacksInfo);
|
||||
@ -290,8 +291,9 @@ public class UpstreamPacketHandler extends LoggingPacketHandler {
|
||||
}
|
||||
|
||||
@Override
|
||||
public PacketSignal handle(MovePlayerPacket packet) {
|
||||
if (session.isLoggingIn()) {
|
||||
public PacketSignal handle(PlayerAuthInputPacket packet) {
|
||||
// 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();
|
||||
titlePacket.setType(SetTitlePacket.Type.ACTIONBAR);
|
||||
titlePacket.setText(GeyserLocale.getPlayerLocaleString("geyser.auth.login.wait", session.locale()));
|
||||
|
@ -27,15 +27,30 @@ package org.geysermc.geyser.network.netty;
|
||||
|
||||
import io.netty.bootstrap.Bootstrap;
|
||||
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.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 org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.geysermc.mcprotocollib.network.BuiltinFlags;
|
||||
import org.geysermc.mcprotocollib.network.codec.PacketCodecHelper;
|
||||
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.TcpPacketCompression;
|
||||
import org.geysermc.mcprotocollib.network.tcp.TcpPacketEncryptor;
|
||||
import org.geysermc.mcprotocollib.network.tcp.TcpPacketSizer;
|
||||
import org.geysermc.mcprotocollib.network.tcp.TcpSession;
|
||||
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.InetSocketAddress;
|
||||
import java.net.SocketAddress;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
@ -75,7 +91,6 @@ public final class LocalSession extends TcpSession {
|
||||
() -> DEFAULT_EVENT_LOOP_GROUP.shutdownGracefully(100, 500, TimeUnit.MILLISECONDS)));
|
||||
}
|
||||
|
||||
try {
|
||||
final Bootstrap bootstrap = new Bootstrap();
|
||||
bootstrap.channel(LocalChannelWithRemoteAddress.class);
|
||||
bootstrap.handler(new ChannelInitializer<LocalChannelWithRemoteAddress>() {
|
||||
@ -85,17 +100,23 @@ public final class LocalSession extends TcpSession {
|
||||
PacketProtocol protocol = getPacketProtocol();
|
||||
protocol.newClientSession(LocalSession.this, transferring);
|
||||
|
||||
refreshReadTimeoutHandler(channel);
|
||||
refreshWriteTimeoutHandler(channel);
|
||||
|
||||
ChannelPipeline pipeline = channel.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)));
|
||||
|
||||
pipeline.addLast("encryption", new TcpPacketEncryptor());
|
||||
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, getConnectTimeout() * 1000);
|
||||
}).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);
|
||||
@ -103,13 +124,17 @@ public final class LocalSession extends TcpSession {
|
||||
|
||||
bootstrap.remoteAddress(targetAddress);
|
||||
|
||||
bootstrap.connect().addListener((future) -> {
|
||||
if (!future.isSuccess()) {
|
||||
exceptionCaught(null, future.cause());
|
||||
CompletableFuture<Void> handleFuture = new CompletableFuture<>();
|
||||
bootstrap.connect().addListener((futureListener) -> {
|
||||
if (!futureListener.isSuccess()) {
|
||||
exceptionCaught(null, futureListener.cause());
|
||||
}
|
||||
|
||||
handleFuture.complete(null);
|
||||
});
|
||||
} catch (Throwable t) {
|
||||
exceptionCaught(null, t);
|
||||
|
||||
if (wait) {
|
||||
handleFuture.join();
|
||||
}
|
||||
}
|
||||
|
||||
@ -121,7 +146,7 @@ public final class LocalSession extends TcpSession {
|
||||
// TODO duplicate code
|
||||
private void addHAProxySupport(ChannelPipeline pipeline) {
|
||||
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() {
|
||||
@Override
|
||||
public void channelActive(@NonNull ChannelHandlerContext ctx) throws Exception {
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -69,7 +69,7 @@ public class BlockRegistries {
|
||||
/**
|
||||
* 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
|
||||
@ -130,22 +130,17 @@ public class BlockRegistries {
|
||||
*/
|
||||
public static final SimpleMappedRegistry<String, CustomSkull> CUSTOM_SKULLS = SimpleMappedRegistry.create(RegistryLoaders.empty(Object2ObjectOpenHashMap::new));
|
||||
|
||||
static {
|
||||
public static void populate() {
|
||||
Blocks.VAULT.javaId(); // FIXME
|
||||
CustomSkullRegistryPopulator.populate();
|
||||
BlockRegistryPopulator.populate(BlockRegistryPopulator.Stage.PRE_INIT);
|
||||
CustomBlockRegistryPopulator.populate(CustomBlockRegistryPopulator.Stage.DEFINITION);
|
||||
CustomBlockRegistryPopulator.populate(CustomBlockRegistryPopulator.Stage.NON_VANILLA_REGISTRATION);
|
||||
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.CUSTOM_REGISTRATION);
|
||||
BlockRegistryPopulator.populate(BlockRegistryPopulator.Stage.INIT_BEDROCK);
|
||||
BlockRegistryPopulator.populate(BlockRegistryPopulator.Stage.POST_INIT);
|
||||
}
|
||||
|
||||
public static void init() {
|
||||
// no-op
|
||||
}
|
||||
|
||||
}
|
@ -43,32 +43,36 @@ import java.util.function.Supplier;
|
||||
*
|
||||
* @param <M> the value being held by the registry
|
||||
*/
|
||||
public final class DeferredRegistry<M> implements IRegistry<M> {
|
||||
private final Registry<M> backingRegistry;
|
||||
class DeferredRegistry<M, R extends IRegistry<M>> implements IRegistry<M> {
|
||||
private final R backingRegistry;
|
||||
private final Supplier<M> loader;
|
||||
|
||||
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.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.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.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.loader = () -> deferredLoader.get().load(input);
|
||||
}
|
||||
|
||||
protected R backingRegistry() {
|
||||
return this.backingRegistry;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @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
|
||||
* Whether this registry was loaded.
|
||||
*/
|
||||
public static <I, M> DeferredRegistry<M> create(Function<RegistryLoader<I, M>, Registry<M>> registryLoader, RegistryLoader<I, M> deferredLoader) {
|
||||
return new DeferredRegistry<>(registryLoader, deferredLoader);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
public boolean loaded() {
|
||||
return this.loaded;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -169,7 +128,7 @@ public final class DeferredRegistry<M> implements IRegistry<M> {
|
||||
*
|
||||
* @param <M> the registry type
|
||||
*/
|
||||
interface RegistryInitializer<M> {
|
||||
public interface RegistryInitializer<M, R extends IRegistry<M>> {
|
||||
|
||||
/**
|
||||
* Initializes the registry.
|
||||
@ -179,6 +138,6 @@ public final class DeferredRegistry<M> implements IRegistry<M> {
|
||||
* @param <I> the input type
|
||||
* @return the initialized registry
|
||||
*/
|
||||
<I> Registry<M> initialize(I input, RegistryLoader<I, M> registryLoader);
|
||||
<I> R initialize(I input, RegistryLoader<I, M> registryLoader);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -140,6 +140,18 @@ public class ListRegistry<M> extends Registry<List<M>> {
|
||||
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.
|
||||
*
|
||||
|
@ -27,6 +27,7 @@ package org.geysermc.geyser.registry;
|
||||
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
import it.unimi.dsi.fastutil.objects.Object2IntMap;
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
|
||||
import org.cloudburstmc.nbt.NbtMap;
|
||||
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.inventory.recipe.GeyserRecipe;
|
||||
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.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.type.ItemMappings;
|
||||
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.event.LevelEvent;
|
||||
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.
|
||||
*/
|
||||
public final class Registries {
|
||||
private static boolean loaded = false;
|
||||
|
||||
/**
|
||||
* A registry holding all the providers.
|
||||
* 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);
|
||||
|
||||
/**
|
||||
* 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.
|
||||
@ -79,19 +94,19 @@ public final class Registries {
|
||||
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.
|
||||
*/
|
||||
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}.
|
||||
*/
|
||||
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
|
||||
@ -118,6 +133,9 @@ public final class Registries {
|
||||
*/
|
||||
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));
|
||||
|
||||
/**
|
||||
@ -130,48 +148,71 @@ public final class Registries {
|
||||
* 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.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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}.
|
||||
*/
|
||||
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}.
|
||||
*/
|
||||
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}.
|
||||
*/
|
||||
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() {
|
||||
// no-op
|
||||
public static void load() {
|
||||
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();
|
||||
ItemRegistryPopulator.populate();
|
||||
TagRegistryPopulator.populate();
|
||||
|
||||
// Create registries that require other registries to load first
|
||||
POTION_MIXES = VersionedRegistry.create(PotionMixRegistryLoader::new);
|
||||
// potion mixes depend on other registries
|
||||
POTION_MIXES.load();
|
||||
|
||||
// Remove unneeded client generation data from NbtMapBuilder
|
||||
NbtMapBuilder biomesNbt = NbtMap.builder();
|
||||
|
Einige Dateien werden nicht angezeigt, da zu viele Dateien in diesem Diff geändert wurden Mehr anzeigen
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren