1.21.4 support

This commit is contained in:
chris 2024-12-12 10:10:03 +08:00 committed by GitHub
commit ba5b4224d8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
106 changed files with 21596 additions and 1779 deletions

View file

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

View file

@ -80,10 +80,9 @@ public interface NonVanillaCustomItemData extends CustomItemData {
@Nullable String toolType(); @Nullable String toolType();
/** /**
* Gets the tool tier of the item. * @deprecated no longer used
*
* @return the tool tier of the item
*/ */
@Deprecated(forRemoval = true)
@Nullable String toolTier(); @Nullable String toolTier();
/** /**
@ -108,10 +107,9 @@ public interface NonVanillaCustomItemData extends CustomItemData {
@Nullable String translationString(); @Nullable String translationString();
/** /**
* Gets the repair materials of the item. * @deprecated No longer used.
*
* @return the repair materials of the item
*/ */
@Deprecated(forRemoval = true)
@Nullable Set<String> repairMaterials(); @Nullable Set<String> repairMaterials();
/** /**

View file

@ -41,6 +41,7 @@ import org.geysermc.geyser.command.CommandSourceConverter;
import org.geysermc.geyser.command.GeyserCommandSource; import org.geysermc.geyser.command.GeyserCommandSource;
import org.geysermc.geyser.configuration.GeyserConfiguration; import org.geysermc.geyser.configuration.GeyserConfiguration;
import org.geysermc.geyser.dump.BootstrapDumpInfo; import org.geysermc.geyser.dump.BootstrapDumpInfo;
import org.geysermc.geyser.network.GameProtocol;
import org.geysermc.geyser.ping.GeyserLegacyPingPassthrough; import org.geysermc.geyser.ping.GeyserLegacyPingPassthrough;
import org.geysermc.geyser.ping.IGeyserPingPassthrough; import org.geysermc.geyser.ping.IGeyserPingPassthrough;
import org.geysermc.geyser.platform.bungeecord.command.BungeeCommandSource; import org.geysermc.geyser.platform.bungeecord.command.BungeeCommandSource;
@ -58,6 +59,7 @@ import java.net.SocketAddress;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.util.Collection; import java.util.Collection;
import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@ -80,18 +82,19 @@ public class GeyserBungeePlugin extends Plugin implements GeyserBootstrap {
public void onGeyserInitialize() { public void onGeyserInitialize() {
GeyserLocale.init(this); GeyserLocale.init(this);
// Copied from ViaVersion.
// https://github.com/ViaVersion/ViaVersion/blob/b8072aad86695cc8ec6f5e4103e43baf3abf6cc5/bungee/src/main/java/us/myles/ViaVersion/BungeePlugin.java#L43
try { try {
ProtocolConstants.class.getField("MINECRAFT_1_21"); List<Integer> supportedProtocols = ProtocolConstants.SUPPORTED_VERSION_IDS;
} catch (NoSuchFieldException e) { if (!supportedProtocols.contains(GameProtocol.getJavaProtocolVersion())) {
geyserLogger.error(" / \\"); geyserLogger.error(" / \\");
geyserLogger.error(" / \\"); geyserLogger.error(" / \\");
geyserLogger.error(" / | \\"); geyserLogger.error(" / | \\");
geyserLogger.error(" / | \\ " + GeyserLocale.getLocaleStringLog("geyser.bootstrap.unsupported_proxy", getProxy().getName())); geyserLogger.error(" / | \\ " + GeyserLocale.getLocaleStringLog("geyser.bootstrap.unsupported_proxy", getProxy().getName()));
geyserLogger.error(" / \\ " + GeyserLocale.getLocaleStringLog("geyser.may_not_work_as_intended_all_caps")); geyserLogger.error(" / \\ " + GeyserLocale.getLocaleStringLog("geyser.may_not_work_as_intended_all_caps"));
geyserLogger.error(" / o \\"); geyserLogger.error(" / o \\");
geyserLogger.error("/_____________\\"); geyserLogger.error("/_____________\\");
}
} catch (Throwable e) {
geyserLogger.warning("Unable to check the versions supported by this proxy! " + e.getMessage());
} }
if (!this.loadConfig()) { if (!this.loadConfig()) {

View file

@ -25,6 +25,6 @@
"depends": { "depends": {
"fabricloader": ">=0.16.7", "fabricloader": ">=0.16.7",
"fabric": "*", "fabric": "*",
"minecraft": ">=1.21.2" "minecraft": ">=1.21.4"
} }
} }

View file

@ -28,37 +28,24 @@ package org.geysermc.geyser.platform.mod.world;
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
import net.minecraft.SharedConstants; import net.minecraft.SharedConstants;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.RegistryAccess;
import net.minecraft.core.component.DataComponents;
import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.network.chat.Component;
import net.minecraft.server.MinecraftServer; import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerChunkCache; import net.minecraft.server.level.ServerChunkCache;
import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.ChunkPos; import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.entity.BannerBlockEntity;
import net.minecraft.world.level.block.entity.BannerPatternLayers;
import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.DecoratedPotBlockEntity; import net.minecraft.world.level.block.entity.DecoratedPotBlockEntity;
import net.minecraft.world.level.chunk.ChunkAccess; import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.LevelChunkSection; import net.minecraft.world.level.chunk.LevelChunkSection;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.math.vector.Vector3i;
import org.geysermc.geyser.level.GeyserWorldManager; import org.geysermc.geyser.level.GeyserWorldManager;
import org.geysermc.geyser.network.GameProtocol; import org.geysermc.geyser.network.GameProtocol;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.util.MinecraftKey;
import org.geysermc.mcprotocollib.protocol.data.game.Holder;
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.GameMode; import org.geysermc.mcprotocollib.protocol.data.game.entity.player.GameMode;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.BannerPatternLayer;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.function.Consumer; import java.util.function.Consumer;
public class GeyserModWorldManager extends GeyserWorldManager { public class GeyserModWorldManager extends GeyserWorldManager {
@ -117,49 +104,6 @@ public class GeyserModWorldManager extends GeyserWorldManager {
return GameMode.byId(server.getDefaultGameType().getId()); return GameMode.byId(server.getDefaultGameType().getId());
} }
@NonNull
@Override
public CompletableFuture<org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents> getPickItemComponents(GeyserSession session, int x, int y, int z, boolean addNbtData) {
CompletableFuture<org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents> future = new CompletableFuture<>();
server.execute(() -> {
ServerPlayer player = getPlayer(session);
if (player == null) {
future.complete(null);
return;
}
BlockPos pos = new BlockPos(x, y, z);
// Don't create a new block entity if invalid
//noinspection resource - level() is just a getter
BlockEntity blockEntity = player.level().getChunkAt(pos).getBlockEntity(pos);
if (blockEntity instanceof BannerBlockEntity banner) {
// Potentially exposes other NBT data? But we need to get the NBT data for the banner patterns *and*
// the banner might have a custom name, both of which a Java client knows and caches
ItemStack itemStack = banner.getItem();
org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents components =
new org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents(new HashMap<>());
components.put(DataComponentType.DAMAGE, itemStack.getDamageValue());
Component customName = itemStack.getComponents().get(DataComponents.CUSTOM_NAME);
if (customName != null) {
components.put(DataComponentType.CUSTOM_NAME, toKyoriComponent(customName));
}
BannerPatternLayers pattern = itemStack.get(DataComponents.BANNER_PATTERNS);
if (pattern != null) {
components.put(DataComponentType.BANNER_PATTERNS, toPatternList(pattern));
}
future.complete(components);
return;
}
future.complete(null);
});
return future;
}
@Override @Override
public void getDecoratedPotData(GeyserSession session, Vector3i pos, Consumer<List<String>> apply) { public void getDecoratedPotData(GeyserSession session, Vector3i pos, Consumer<List<String>> apply) {
server.execute(() -> { server.execute(() -> {
@ -184,20 +128,4 @@ public class GeyserModWorldManager extends GeyserWorldManager {
private ServerPlayer getPlayer(GeyserSession session) { private ServerPlayer getPlayer(GeyserSession session) {
return server.getPlayerList().getPlayer(session.getPlayerEntity().getUuid()); return server.getPlayerList().getPlayer(session.getPlayerEntity().getUuid());
} }
private static net.kyori.adventure.text.Component toKyoriComponent(Component component) {
String json = Component.Serializer.toJson(component, RegistryAccess.EMPTY);
return GSON_SERIALIZER.deserializeOr(json, net.kyori.adventure.text.Component.empty());
}
private static List<BannerPatternLayer> toPatternList(BannerPatternLayers patternLayers) {
return patternLayers.layers().stream()
.map(layer -> {
BannerPatternLayer.BannerPattern pattern = new BannerPatternLayer.BannerPattern(
MinecraftKey.key(layer.pattern().value().assetId().toString()), layer.pattern().value().translationKey()
);
return new BannerPatternLayer(Holder.ofCustom(pattern), layer.color().getId());
})
.toList();
}
} }

View file

@ -33,7 +33,6 @@ import org.checkerframework.checker.nullness.qual.Nullable;
import org.geysermc.geyser.adapters.WorldAdapter; import org.geysermc.geyser.adapters.WorldAdapter;
import org.geysermc.geyser.adapters.paper.PaperAdapters; import org.geysermc.geyser.adapters.paper.PaperAdapters;
import org.geysermc.geyser.adapters.spigot.SpigotAdapters; import org.geysermc.geyser.adapters.spigot.SpigotAdapters;
import org.geysermc.geyser.level.block.BlockStateValues;
import org.geysermc.geyser.level.block.type.Block; import org.geysermc.geyser.level.block.type.Block;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;

View file

@ -25,18 +25,14 @@
package org.geysermc.geyser.platform.spigot.world.manager; package org.geysermc.geyser.platform.spigot.world.manager;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.block.Block; import org.bukkit.block.Block;
import org.bukkit.block.DecoratedPot; import org.bukkit.block.DecoratedPot;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin; import org.bukkit.plugin.Plugin;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.math.vector.Vector3i;
import org.geysermc.erosion.bukkit.BukkitUtils; import org.geysermc.erosion.bukkit.BukkitUtils;
import org.geysermc.erosion.bukkit.PickBlockUtils;
import org.geysermc.erosion.bukkit.SchedulerUtils; import org.geysermc.erosion.bukkit.SchedulerUtils;
import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.level.GameRule; import org.geysermc.geyser.level.GameRule;
@ -44,7 +40,6 @@ import org.geysermc.geyser.level.WorldManager;
import org.geysermc.geyser.registry.BlockRegistries; import org.geysermc.geyser.registry.BlockRegistries;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.GameMode; import org.geysermc.mcprotocollib.protocol.data.game.entity.player.GameMode;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
@ -128,20 +123,6 @@ public class GeyserSpigotWorldManager extends WorldManager {
return GameMode.byId(Bukkit.getDefaultGameMode().ordinal()); return GameMode.byId(Bukkit.getDefaultGameMode().ordinal());
} }
@Override
public @NonNull CompletableFuture<@Nullable DataComponents> getPickItemComponents(GeyserSession session, int x, int y, int z, boolean addNbtData) {
Player bukkitPlayer;
if ((bukkitPlayer = Bukkit.getPlayer(session.getPlayerEntity().getUuid())) == null) {
return CompletableFuture.completedFuture(null);
}
CompletableFuture<Int2ObjectMap<byte[]>> future = new CompletableFuture<>();
Block block = bukkitPlayer.getWorld().getBlockAt(x, y, z);
// Paper 1.19.3 complains about async access otherwise.
// java.lang.IllegalStateException: Tile is null, asynchronous access?
SchedulerUtils.runTask(this.plugin, () -> future.complete(PickBlockUtils.pickBlock(block)), block);
return future.thenApply(RAW_TRANSFORMER);
}
public void getDecoratedPotData(GeyserSession session, Vector3i pos, Consumer<List<String>> apply) { public void getDecoratedPotData(GeyserSession session, Vector3i pos, Consumer<List<String>> apply) {
Player bukkitPlayer; Player bukkitPlayer;
if ((bukkitPlayer = Bukkit.getPlayer(session.getPlayerEntity().getUuid())) == null) { if ((bukkitPlayer = Bukkit.getPlayer(session.getPlayerEntity().getUuid())) == null) {

View file

@ -13,7 +13,7 @@ modrinth {
versionNumber.set(projectVersion(project)) versionNumber.set(projectVersion(project))
versionType.set("beta") versionType.set("beta")
changelog.set(System.getenv("CHANGELOG") ?: "") changelog.set(System.getenv("CHANGELOG") ?: "")
gameVersions.addAll("1.21.2", libs.minecraft.get().version as String) gameVersions.add(libs.minecraft.get().version as String)
failSilently.set(true) failSilently.set(true)
syncBodyFrom.set(rootProject.file("README.md").readText()) syncBodyFrom.set(rootProject.file("README.md").readText())

View file

@ -117,6 +117,7 @@ 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.BlazeEntity;
import org.geysermc.geyser.entity.type.living.monster.BoggedEntity; 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.BreezeEntity;
import org.geysermc.geyser.entity.type.living.monster.CreakingEntity;
import org.geysermc.geyser.entity.type.living.monster.CreeperEntity; 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.ElderGuardianEntity;
import org.geysermc.geyser.entity.type.living.monster.EnderDragonEntity; import org.geysermc.geyser.entity.type.living.monster.EnderDragonEntity;
@ -180,6 +181,7 @@ public final class EntityDefinitions {
public static final EntityDefinition<AbstractFishEntity> COD; public static final EntityDefinition<AbstractFishEntity> COD;
public static final EntityDefinition<CommandBlockMinecartEntity> COMMAND_BLOCK_MINECART; public static final EntityDefinition<CommandBlockMinecartEntity> COMMAND_BLOCK_MINECART;
public static final EntityDefinition<CowEntity> COW; public static final EntityDefinition<CowEntity> COW;
public static final EntityDefinition<CreakingEntity> CREAKING;
public static final EntityDefinition<CreeperEntity> CREEPER; public static final EntityDefinition<CreeperEntity> CREEPER;
public static final EntityDefinition<BoatEntity> DARK_OAK_BOAT; public static final EntityDefinition<BoatEntity> DARK_OAK_BOAT;
public static final EntityDefinition<ChestBoatEntity> DARK_OAK_CHEST_BOAT; public static final EntityDefinition<ChestBoatEntity> DARK_OAK_CHEST_BOAT;
@ -237,6 +239,8 @@ public final class EntityDefinitions {
public static final EntityDefinition<ChestBoatEntity> OAK_CHEST_BOAT; public static final EntityDefinition<ChestBoatEntity> OAK_CHEST_BOAT;
public static final EntityDefinition<OcelotEntity> OCELOT; public static final EntityDefinition<OcelotEntity> OCELOT;
public static final EntityDefinition<PaintingEntity> PAINTING; public static final EntityDefinition<PaintingEntity> PAINTING;
public static final EntityDefinition<BoatEntity> PALE_OAK_BOAT;
public static final EntityDefinition<ChestBoatEntity> PALE_OAK_CHEST_BOAT;
public static final EntityDefinition<PandaEntity> PANDA; public static final EntityDefinition<PandaEntity> PANDA;
public static final EntityDefinition<ParrotEntity> PARROT; public static final EntityDefinition<ParrotEntity> PARROT;
public static final EntityDefinition<PhantomEntity> PHANTOM; public static final EntityDefinition<PhantomEntity> PHANTOM;
@ -592,6 +596,7 @@ public final class EntityDefinitions {
MANGROVE_BOAT = buildBoat(boatBase, EntityType.MANGROVE_BOAT, BoatEntity.BoatVariant.MANGROVE); MANGROVE_BOAT = buildBoat(boatBase, EntityType.MANGROVE_BOAT, BoatEntity.BoatVariant.MANGROVE);
OAK_BOAT = buildBoat(boatBase, EntityType.OAK_BOAT, BoatEntity.BoatVariant.OAK); OAK_BOAT = buildBoat(boatBase, EntityType.OAK_BOAT, BoatEntity.BoatVariant.OAK);
SPRUCE_BOAT = buildBoat(boatBase, EntityType.SPRUCE_BOAT, BoatEntity.BoatVariant.SPRUCE); SPRUCE_BOAT = buildBoat(boatBase, EntityType.SPRUCE_BOAT, BoatEntity.BoatVariant.SPRUCE);
PALE_OAK_BOAT = buildBoat(boatBase, EntityType.PALE_OAK_BOAT, BoatEntity.BoatVariant.PALE_OAK);
EntityDefinition<ChestBoatEntity> chestBoatBase = EntityDefinition.<ChestBoatEntity>inherited(null, boatBase) EntityDefinition<ChestBoatEntity> chestBoatBase = EntityDefinition.<ChestBoatEntity>inherited(null, boatBase)
.build(); .build();
@ -605,6 +610,7 @@ public final class EntityDefinitions {
MANGROVE_CHEST_BOAT = buildChestBoat(chestBoatBase, EntityType.MANGROVE_CHEST_BOAT, BoatEntity.BoatVariant.MANGROVE); MANGROVE_CHEST_BOAT = buildChestBoat(chestBoatBase, EntityType.MANGROVE_CHEST_BOAT, BoatEntity.BoatVariant.MANGROVE);
OAK_CHEST_BOAT = buildChestBoat(chestBoatBase, EntityType.OAK_CHEST_BOAT, BoatEntity.BoatVariant.OAK); OAK_CHEST_BOAT = buildChestBoat(chestBoatBase, EntityType.OAK_CHEST_BOAT, BoatEntity.BoatVariant.OAK);
SPRUCE_CHEST_BOAT = buildChestBoat(chestBoatBase, EntityType.SPRUCE_CHEST_BOAT, BoatEntity.BoatVariant.SPRUCE); SPRUCE_CHEST_BOAT = buildChestBoat(chestBoatBase, EntityType.SPRUCE_CHEST_BOAT, BoatEntity.BoatVariant.SPRUCE);
PALE_OAK_CHEST_BOAT = buildChestBoat(chestBoatBase, EntityType.PALE_OAK_CHEST_BOAT, BoatEntity.BoatVariant.PALE_OAK);
} }
EntityDefinition<LivingEntity> livingEntityBase = EntityDefinition.inherited(LivingEntity::new, entityBase) EntityDefinition<LivingEntity> livingEntityBase = EntityDefinition.inherited(LivingEntity::new, entityBase)
@ -672,6 +678,23 @@ public final class EntityDefinitions {
.type(EntityType.BREEZE) .type(EntityType.BREEZE)
.height(1.77f).width(0.6f) .height(1.77f).width(0.6f)
.build(); .build();
CREAKING = EntityDefinition.inherited(CreakingEntity::new, mobEntityBase)
.type(EntityType.CREAKING)
.height(2.7f).width(0.9f)
.addTranslator(MetadataType.BOOLEAN, CreakingEntity::setCanMove)
.addTranslator(MetadataType.BOOLEAN, CreakingEntity::setActive)
.addTranslator(MetadataType.BOOLEAN, CreakingEntity::setIsTearingDown)
.addTranslator(MetadataType.OPTIONAL_POSITION, CreakingEntity::setHomePos)
.properties(new GeyserEntityProperties.Builder()
.addEnum(CreakingEntity.CREAKING_STATE,
"neutral",
"hostile_observed",
"hostile_unobserved",
"twitching",
"crumbling")
.addInt(CreakingEntity.CREAKING_SWAYING_TICKS, 0, 6)
.build())
.build();
CREEPER = EntityDefinition.inherited(CreeperEntity::new, mobEntityBase) CREEPER = EntityDefinition.inherited(CreeperEntity::new, mobEntityBase)
.type(EntityType.CREEPER) .type(EntityType.CREEPER)
.height(1.7f).width(0.6f) .height(1.7f).width(0.6f)

View file

@ -51,6 +51,9 @@ public enum GeyserAttributeType {
MAX_HEALTH("minecraft:generic.max_health", null, 0f, 1024f, 20f), MAX_HEALTH("minecraft:generic.max_health", null, 0f, 1024f, 20f),
SCALE("minecraft:generic.scale", null, 0.0625f, 16f, 1f), SCALE("minecraft:generic.scale", null, 0.0625f, 16f, 1f),
BLOCK_INTERACTION_RANGE("minecraft:player.block_interaction_range", null, 0.0f, 64f, 4.5f), BLOCK_INTERACTION_RANGE("minecraft:player.block_interaction_range", null, 0.0f, 64f, 4.5f),
MINING_EFFICIENCY("minecraft:mining_efficiency", null, 0f, 1024f, 0f),
BLOCK_BREAK_SPEED("minecraft:block_break_speed", null, 0f, 1024f, 1f),
SUBMERGED_MINING_SPEED("minecraft:submerged_mining_speed", null, 0f, 20f, 0.2f),
// Bedrock Attributes // Bedrock Attributes
ABSORPTION(null, "minecraft:absorption", 0f, 1024f, 0f), ABSORPTION(null, "minecraft:absorption", 0f, 1024f, 0f),

View file

@ -34,6 +34,7 @@ import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.entity.EntityDefinitions; import org.geysermc.geyser.entity.EntityDefinitions;
import org.geysermc.geyser.item.Items; import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.item.type.Item;
import org.geysermc.geyser.network.GameProtocol;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.util.InteractionResult; import org.geysermc.geyser.util.InteractionResult;
import org.geysermc.geyser.util.InteractiveTag; import org.geysermc.geyser.util.InteractiveTag;
@ -77,6 +78,11 @@ public class BoatEntity extends Entity implements Leashable, Tickable {
super(session, entityId, geyserId, uuid, definition, position.add(0d, definition.offset(), 0d), motion, yaw + 90, 0, yaw + 90); super(session, entityId, geyserId, uuid, definition, position.add(0d, definition.offset(), 0d), motion, yaw + 90, 0, yaw + 90);
this.variant = variant; this.variant = variant;
// TODO remove once 1.21.40 is dropped
if (variant == BoatVariant.PALE_OAK && GameProtocol.isPreWinterDrop(session)) {
variant = BoatVariant.BIRCH;
}
dirtyMetadata.put(EntityDataTypes.VARIANT, variant.ordinal()); dirtyMetadata.put(EntityDataTypes.VARIANT, variant.ordinal());
// Required to be able to move on land 1.16.200+ or apply gravity not in the water 1.16.100+ // Required to be able to move on land 1.16.200+ or apply gravity not in the water 1.16.100+
@ -238,7 +244,8 @@ public class BoatEntity extends Entity implements Leashable, Tickable {
DARK_OAK(Items.DARK_OAK_BOAT, Items.DARK_OAK_CHEST_BOAT), DARK_OAK(Items.DARK_OAK_BOAT, Items.DARK_OAK_CHEST_BOAT),
MANGROVE(Items.MANGROVE_BOAT, Items.MANGROVE_CHEST_BOAT), MANGROVE(Items.MANGROVE_BOAT, Items.MANGROVE_CHEST_BOAT),
BAMBOO(Items.BAMBOO_RAFT, Items.BAMBOO_CHEST_RAFT), BAMBOO(Items.BAMBOO_RAFT, Items.BAMBOO_CHEST_RAFT),
CHERRY(Items.CHERRY_BOAT, Items.CHERRY_CHEST_BOAT); CHERRY(Items.CHERRY_BOAT, Items.CHERRY_CHEST_BOAT),
PALE_OAK(Items.PALE_OAK_BOAT, Items.PALE_OAK_CHEST_BOAT);
private final Item pickItem; private final Item pickItem;
final Item chestPickItem; final Item chestPickItem;

View file

@ -51,6 +51,8 @@ import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.Object
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.GameMode; import org.geysermc.mcprotocollib.protocol.data.game.entity.player.GameMode;
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand; import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand;
import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack; import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.HolderSet;
import java.util.Collections; import java.util.Collections;
import java.util.Locale; import java.util.Locale;
@ -58,7 +60,7 @@ import java.util.UUID;
public class WolfEntity extends TameableEntity { public class WolfEntity extends TameableEntity {
private byte collarColor = 14; // Red - default private byte collarColor = 14; // Red - default
private HolderSet repairableItems = null;
private boolean isCurseOfBinding = false; private boolean isCurseOfBinding = false;
public WolfEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) { public WolfEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
@ -123,9 +125,11 @@ public class WolfEntity extends TameableEntity {
} }
@Override @Override
public void setChestplate(ItemStack stack) { public void setBody(ItemStack stack) {
super.setChestplate(stack); super.setBody(stack);
isCurseOfBinding = ItemUtils.hasEffect(session, stack, EnchantmentComponent.PREVENT_ARMOR_CHANGE); // TODO test isCurseOfBinding = ItemUtils.hasEffect(session, stack, EnchantmentComponent.PREVENT_ARMOR_CHANGE);
// Not using ItemStack#getDataComponents as that wouldn't include default item components
repairableItems = GeyserItemStack.from(stack).getComponent(DataComponentType.REPAIRABLE);
} }
@Override @Override
@ -152,16 +156,17 @@ public class WolfEntity extends TameableEntity {
return super.testMobInteraction(hand, itemInHand); return super.testMobInteraction(hand, itemInHand);
} }
} }
if (itemInHand.asItem() == Items.WOLF_ARMOR && !this.chestplate.isValid() && !getFlag(EntityFlag.BABY)) { if (itemInHand.asItem() == Items.WOLF_ARMOR && !this.body.isValid() && !getFlag(EntityFlag.BABY)) {
return InteractiveTag.EQUIP_WOLF_ARMOR; return InteractiveTag.EQUIP_WOLF_ARMOR;
} }
if (itemInHand.asItem() == Items.SHEARS && this.chestplate.isValid() if (itemInHand.asItem() == Items.SHEARS && this.body.isValid()
&& (!isCurseOfBinding || session.getGameMode().equals(GameMode.CREATIVE))) { && (!isCurseOfBinding || session.getGameMode().equals(GameMode.CREATIVE))) {
return InteractiveTag.REMOVE_WOLF_ARMOR; return InteractiveTag.REMOVE_WOLF_ARMOR;
} }
if (Items.WOLF_ARMOR.isValidRepairItem(itemInHand.asItem()) && getFlag(EntityFlag.SITTING) && if (getFlag(EntityFlag.SITTING) &&
this.chestplate.isValid() && this.chestplate.getTag() != null && session.getTagCache().isItem(repairableItems, itemInHand.asItem()) &&
this.chestplate.getTag().getInt("Damage") > 0) { this.body.isValid() && this.body.getTag() != null &&
this.body.getTag().getInt("Damage") > 0) {
return InteractiveTag.REPAIR_WOLF_ARMOR; return InteractiveTag.REPAIR_WOLF_ARMOR;
} }
// Tamed and owned by player - can sit/stand // Tamed and owned by player - can sit/stand

View file

@ -0,0 +1,119 @@
/*
* 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.monster;
import org.cloudburstmc.math.vector.Vector3f;
import org.cloudburstmc.math.vector.Vector3i;
import org.cloudburstmc.nbt.NbtMap;
import org.cloudburstmc.protocol.bedrock.data.LevelEvent;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
import org.cloudburstmc.protocol.bedrock.packet.AddEntityPacket;
import org.cloudburstmc.protocol.bedrock.packet.LevelEventGenericPacket;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.EntityMetadata;
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.MetadataType;
import java.util.Optional;
import java.util.UUID;
public class CreakingEntity extends MonsterEntity {
public static final String CREAKING_STATE = "minecraft:creaking_state";
public static final String CREAKING_SWAYING_TICKS = "minecraft:creaking_swaying_ticks";
private Vector3i homePosition;
public CreakingEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
}
@Override
protected void initializeMetadata() {
super.initializeMetadata();
setFlag(EntityFlag.HIDDEN_WHEN_INVISIBLE, true);
setFlag(EntityFlag.FIRE_IMMUNE, true);
}
@Override
public void addAdditionalSpawnData(AddEntityPacket addEntityPacket) {
propertyManager.add(CREAKING_STATE, "neutral");
// also, the creaking seems to have this minecraft:creaking_swaying_ticks thingy
// which i guess is responsible for some animation?
// it's sent over the network, all 6 "stages" 50ms in between of each other.
// no clue what it's used for tbh, so i'm not gonna bother implementing it
// - chris
propertyManager.add(CREAKING_SWAYING_TICKS, 0);
propertyManager.applyIntProperties(addEntityPacket.getProperties().getIntProperties());
}
public void setCanMove(EntityMetadata<Boolean,? extends MetadataType<Boolean>> booleanEntityMetadata) {
setFlag(EntityFlag.BODY_ROTATION_BLOCKED, !booleanEntityMetadata.getValue());
propertyManager.add(CREAKING_STATE, booleanEntityMetadata.getValue() ? "hostile_unobserved" : "hostile_observed");
updateBedrockEntityProperties();
}
public void setActive(EntityMetadata<Boolean,? extends MetadataType<Boolean>> booleanEntityMetadata) {
if (!booleanEntityMetadata.getValue()) {
propertyManager.add(CREAKING_STATE, "neutral");
}
}
public void setIsTearingDown(EntityMetadata<Boolean,? extends MetadataType<Boolean>> booleanEntityMetadata) {
if (booleanEntityMetadata.getValue()) {
propertyManager.add(CREAKING_STATE, "crumbling");
updateBedrockEntityProperties();
}
}
public void setHomePos(EntityMetadata<Optional<Vector3i>,? extends MetadataType<Optional<Vector3i>>> optionalEntityMetadata) {
if (optionalEntityMetadata.getValue().isPresent()) {
this.homePosition = optionalEntityMetadata.getValue().get();
} else {
this.homePosition = null;
}
}
public void createParticleBeam() {
if (this.homePosition != null) {
LevelEventGenericPacket levelEventGenericPacket = new LevelEventGenericPacket();
levelEventGenericPacket.setType(LevelEvent.PARTICLE_CREAKING_HEART_TRIAL);
levelEventGenericPacket.setTag(
NbtMap.builder()
.putInt("CreakingAmount", 20)
.putFloat("CreakingX", position.getX())
.putFloat("CreakingY", position.getY())
.putFloat("CreakingZ", position.getZ())
.putInt("HeartAmount", 20)
.putFloat("HeartX", homePosition.getX())
.putFloat("HeartY", homePosition.getY())
.putFloat("HeartZ", homePosition.getZ())
.build()
);
session.sendUpstreamPacket(levelEventGenericPacket);
}
}
}

View file

@ -335,7 +335,7 @@ public class PlayerEntity extends LivingEntity implements GeyserPlayerEntity {
parrot.updateBedrockMetadata(); parrot.updateBedrockMetadata();
SetEntityLinkPacket linkPacket = new SetEntityLinkPacket(); SetEntityLinkPacket linkPacket = new SetEntityLinkPacket();
EntityLinkData.Type type = isLeft ? EntityLinkData.Type.RIDER : EntityLinkData.Type.PASSENGER; EntityLinkData.Type type = isLeft ? EntityLinkData.Type.RIDER : EntityLinkData.Type.PASSENGER;
linkPacket.setEntityLink(new EntityLinkData(geyserId, parrot.getGeyserId(), type, false, false)); linkPacket.setEntityLink(new EntityLinkData(geyserId, parrot.getGeyserId(), type, false, false, 0f));
// Delay, or else spawned-in players won't get the link // Delay, or else spawned-in players won't get the link
// TODO: Find a better solution. // TODO: Find a better solution.
session.scheduleInEventLoop(() -> session.sendUpstreamPacket(linkPacket), 500, TimeUnit.MILLISECONDS); session.scheduleInEventLoop(() -> session.sendUpstreamPacket(linkPacket), 500, TimeUnit.MILLISECONDS);

View file

@ -280,6 +280,15 @@ public class SessionPlayerEntity extends PlayerEntity {
return attributeData; return attributeData;
} }
public float attributeOrDefault(GeyserAttributeType type) {
var attribute = this.attributes.get(type);
if (attribute == null) {
return type.getDefaultValue();
}
return attribute.getValue();
}
public void setLastDeathPosition(@Nullable GlobalPos pos) { public void setLastDeathPosition(@Nullable GlobalPos pos) {
if (pos != null) { if (pos != null) {
dirtyMetadata.put(EntityDataTypes.PLAYER_LAST_DEATH_POS, pos.getPosition()); dirtyMetadata.put(EntityDataTypes.PLAYER_LAST_DEATH_POS, pos.getPosition());

View file

@ -105,6 +105,10 @@ public class VehicleComponent<T extends LivingEntity & ClientVehicle> {
boundingBox.setMiddleZ(z); boundingBox.setMiddleZ(z);
} }
public void moveAbsolute(Vector3d vec) {
moveAbsolute(vec.getX(), vec.getY(), vec.getZ());
}
public void moveRelative(double x, double y, double z) { public void moveRelative(double x, double y, double z) {
boundingBox.translate(x, y, z); boundingBox.translate(x, y, z);
} }
@ -756,7 +760,7 @@ public class VehicleComponent<T extends LivingEntity & ClientVehicle> {
vehicle.getSession().sendUpstreamPacket(moveEntityDeltaPacket); vehicle.getSession().sendUpstreamPacket(moveEntityDeltaPacket);
} }
ServerboundMoveVehiclePacket moveVehiclePacket = new ServerboundMoveVehiclePacket(javaPos.getX(), javaPos.getY(), javaPos.getZ(), rotation.getX(), rotation.getY()); ServerboundMoveVehiclePacket moveVehiclePacket = new ServerboundMoveVehiclePacket(javaPos, rotation.getX(), rotation.getY(), vehicle.isOnGround());
vehicle.getSession().sendDownstreamPacket(moveVehiclePacket); vehicle.getSession().sendDownstreamPacket(moveVehiclePacket);
} }

View file

@ -25,15 +25,15 @@
package org.geysermc.geyser.inventory; package org.geysermc.geyser.inventory;
import net.kyori.adventure.text.Component;
import org.geysermc.mcprotocollib.protocol.data.game.inventory.ContainerType;
import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory.ServerboundRenameItemPacket;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import net.kyori.adventure.text.Component;
import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.Nullable;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.text.MessageTranslator; import org.geysermc.geyser.translator.text.MessageTranslator;
import org.geysermc.geyser.util.ItemUtils; import org.geysermc.mcprotocollib.protocol.data.game.inventory.ContainerType;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType;
import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory.ServerboundRenameItemPacket;
/** /**
* Used to determine if rename packets should be sent and stores * Used to determine if rename packets should be sent and stores
@ -73,7 +73,7 @@ public class AnvilContainer extends Container {
String correctRename; String correctRename;
newName = rename; newName = rename;
Component originalName = ItemUtils.getCustomName(getInput().getComponents()); Component originalName = getInput().getComponent(DataComponentType.CUSTOM_NAME);
String plainOriginalName = MessageTranslator.convertToPlainText(originalName, session.locale()); String plainOriginalName = MessageTranslator.convertToPlainText(originalName, session.locale());
String plainNewName = MessageTranslator.convertToPlainText(rename); String plainNewName = MessageTranslator.convertToPlainText(rename);

View file

@ -25,7 +25,11 @@
package org.geysermc.geyser.inventory; package org.geysermc.geyser.inventory;
import lombok.*; import lombok.AccessLevel;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.Nullable;
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
@ -104,10 +108,31 @@ public class GeyserItemStack {
return isEmpty() ? 0 : amount; return isEmpty() ? 0 : amount;
} }
/**
* Returns all components of this item - base and additional components sent over the network.
* These are NOT modifiable! To add components, use {@link #getOrCreateComponents()}.
*
* @return the item's base data components and the "additional" ones that may exist.
*/
public @Nullable DataComponents getAllComponents() {
return isEmpty() ? null : asItem().gatherComponents(components);
}
/**
* @return the {@link DataComponents} that aren't the base/default components.
*/
public @Nullable DataComponents getComponents() { public @Nullable DataComponents getComponents() {
return isEmpty() ? null : components; return isEmpty() ? null : components;
} }
/**
* @return whether this GeyserItemStack has any additional components on top of
* the base item components.
*/
public boolean hasNonBaseComponents() {
return components != null;
}
@NonNull @NonNull
public DataComponents getOrCreateComponents() { public DataComponents getOrCreateComponents() {
if (components == null) { if (components == null) {
@ -116,36 +141,32 @@ public class GeyserItemStack {
return components; return components;
} }
/**
* Returns the stored data component for a given {@link DataComponentType}, or null.
* <p>
* This method will first check the additional components that may exist,
* and fallback to the item's default (or, "base") components if need be.
* @param type the {@link DataComponentType} to query
* @return the value for said type, or null.
* @param <T> the value's type
*/
@Nullable @Nullable
public <T> T getComponent(@NonNull DataComponentType<T> type) { public <T> T getComponent(@NonNull DataComponentType<T> type) {
if (components == null) { if (components == null) {
return null; return asItem().getComponent(type);
} }
return components.get(type);
T value = components.get(type);
if (value == null) {
return asItem().getComponent(type);
}
return value;
} }
public <T extends Boolean> boolean getComponent(@NonNull DataComponentType<T> type, boolean def) { public <T> T getComponentOrFallback(@NonNull DataComponentType<T> type, T def) {
if (components == null) { T value = getComponent(type);
return def; return value == null ? def : value;
}
Boolean result = components.get(type);
if (result != null) {
return result;
}
return def;
}
public <T extends Integer> int getComponent(@NonNull DataComponentType<T> type, int def) {
if (components == null) {
return def;
}
Integer result = components.get(type);
if (result != null) {
return result;
}
return def;
} }
public int getNetId() { public int getNetId() {

View file

@ -43,16 +43,15 @@ import org.geysermc.geyser.item.enchantment.Enchantment;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.inventory.InventoryTranslator; import org.geysermc.geyser.translator.inventory.InventoryTranslator;
import org.geysermc.geyser.translator.text.MessageTranslator; import org.geysermc.geyser.translator.text.MessageTranslator;
import org.geysermc.geyser.util.ItemUtils;
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.GameMode; import org.geysermc.mcprotocollib.protocol.data.game.entity.player.GameMode;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType; import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.HolderSet;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.ItemEnchantments; import org.geysermc.mcprotocollib.protocol.data.game.item.component.ItemEnchantments;
import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory.ServerboundRenameItemPacket; import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory.ServerboundRenameItemPacket;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.stream.IntStream;
public class AnvilInventoryUpdater extends InventoryUpdater { public class AnvilInventoryUpdater extends InventoryUpdater {
public static final AnvilInventoryUpdater INSTANCE = new AnvilInventoryUpdater(); public static final AnvilInventoryUpdater INSTANCE = new AnvilInventoryUpdater();
@ -64,7 +63,7 @@ public class AnvilInventoryUpdater extends InventoryUpdater {
super.updateInventory(translator, session, inventory); super.updateInventory(translator, session, inventory);
AnvilContainer anvilContainer = (AnvilContainer) inventory; AnvilContainer anvilContainer = (AnvilContainer) inventory;
updateInventoryState(session, anvilContainer); updateInventoryState(session, anvilContainer);
int targetSlot = getTargetSlot(anvilContainer); int targetSlot = getTargetSlot(anvilContainer, session);
for (int i = 0; i < translator.size; i++) { for (int i = 0; i < translator.size; i++) {
final int bedrockSlot = translator.javaSlotToBedrock(i); final int bedrockSlot = translator.javaSlotToBedrock(i);
if (bedrockSlot == 50) if (bedrockSlot == 50)
@ -89,7 +88,7 @@ public class AnvilInventoryUpdater extends InventoryUpdater {
updateInventoryState(session, anvilContainer); updateInventoryState(session, anvilContainer);
int lastTargetSlot = anvilContainer.getLastTargetSlot(); int lastTargetSlot = anvilContainer.getLastTargetSlot();
int targetSlot = getTargetSlot(anvilContainer); int targetSlot = getTargetSlot(anvilContainer, session);
if (targetSlot != javaSlot) { if (targetSlot != javaSlot) {
// Update the requested slot // Update the requested slot
InventorySlotPacket slotPacket = new InventorySlotPacket(); InventorySlotPacket slotPacket = new InventorySlotPacket();
@ -118,7 +117,7 @@ public class AnvilInventoryUpdater extends InventoryUpdater {
// Changing the item in the input slot resets the name field on Bedrock, but // Changing the item in the input slot resets the name field on Bedrock, but
// does not result in a FilterTextPacket // does not result in a FilterTextPacket
String originalName = MessageTranslator.convertToPlainText(ItemUtils.getCustomName(input.getComponents()), session.locale()); String originalName = MessageTranslator.convertToPlainText(input.getComponent(DataComponentType.CUSTOM_NAME), session.locale());
ServerboundRenameItemPacket renameItemPacket = new ServerboundRenameItemPacket(originalName); ServerboundRenameItemPacket renameItemPacket = new ServerboundRenameItemPacket(originalName);
session.sendDownstreamGamePacket(renameItemPacket); session.sendDownstreamGamePacket(renameItemPacket);
@ -136,12 +135,12 @@ public class AnvilInventoryUpdater extends InventoryUpdater {
* @param anvilContainer the anvil inventory * @param anvilContainer the anvil inventory
* @return the slot to change the repair cost * @return the slot to change the repair cost
*/ */
private int getTargetSlot(AnvilContainer anvilContainer) { private int getTargetSlot(AnvilContainer anvilContainer, GeyserSession session) {
GeyserItemStack input = anvilContainer.getInput(); GeyserItemStack input = anvilContainer.getInput();
GeyserItemStack material = anvilContainer.getMaterial(); GeyserItemStack material = anvilContainer.getMaterial();
if (!material.isEmpty()) { if (!material.isEmpty()) {
if (!input.isEmpty() && isRepairing(input, material)) { if (!input.isEmpty() && isRepairing(input, material, session)) {
// Changing the repair cost on the material item makes it non-stackable // Changing the repair cost on the material item makes it non-stackable
return 0; return 0;
} }
@ -234,7 +233,7 @@ public class AnvilInventoryUpdater extends InventoryUpdater {
// Can't repair or merge enchantments // Can't repair or merge enchantments
return -1; return -1;
} }
} else if (hasDurability(input) && isRepairing(input, material)) { } else if (hasDurability(input) && isRepairing(input, material, session)) {
cost = calcRepairLevelCost(input, material); cost = calcRepairLevelCost(input, material);
if (cost == -1) { if (cost == -1) {
// No damage to repair // No damage to repair
@ -266,14 +265,14 @@ public class AnvilInventoryUpdater extends InventoryUpdater {
*/ */
private int calcRepairLevelCost(GeyserItemStack input, GeyserItemStack material) { private int calcRepairLevelCost(GeyserItemStack input, GeyserItemStack material) {
int newDamage = getDamage(input); int newDamage = getDamage(input);
int unitRepair = Math.min(newDamage, input.asItem().maxDamage() / 4); int unitRepair = Math.min(newDamage, input.asItem().defaultMaxDamage() / 4);
if (unitRepair <= 0) { if (unitRepair <= 0) {
// No damage to repair // No damage to repair
return -1; return -1;
} }
for (int i = 0; i < material.getAmount(); i++) { for (int i = 0; i < material.getAmount(); i++) {
newDamage -= unitRepair; newDamage -= unitRepair;
unitRepair = Math.min(newDamage, input.asItem().maxDamage() / 4); unitRepair = Math.min(newDamage, input.asItem().defaultMaxDamage() / 4);
if (unitRepair <= 0) { if (unitRepair <= 0) {
return i + 1; return i + 1;
} }
@ -290,7 +289,7 @@ public class AnvilInventoryUpdater extends InventoryUpdater {
*/ */
private int calcMergeRepairCost(GeyserItemStack input, GeyserItemStack material) { private int calcMergeRepairCost(GeyserItemStack input, GeyserItemStack material) {
// If the material item is damaged 112% or more, then the input item will not be repaired // If the material item is damaged 112% or more, then the input item will not be repaired
if (getDamage(input) > 0 && getDamage(material) < (material.asItem().maxDamage() * 112 / 100)) { if (getDamage(input) > 0 && getDamage(material) < (material.asItem().defaultMaxDamage() * 112 / 100)) {
return 2; return 2;
} }
return 0; return 0;
@ -395,8 +394,13 @@ public class AnvilInventoryUpdater extends InventoryUpdater {
return isEnchantedBook(material) || (input.getJavaId() == material.getJavaId() && hasDurability(input)); return isEnchantedBook(material) || (input.getJavaId() == material.getJavaId() && hasDurability(input));
} }
private boolean isRepairing(GeyserItemStack input, GeyserItemStack material) { private boolean isRepairing(GeyserItemStack input, GeyserItemStack material, GeyserSession session) {
return input.asItem().isValidRepairItem(material.asItem()); HolderSet repairable = input.getComponent(DataComponentType.REPAIRABLE);
if (repairable == null) {
return false;
}
return session.getTagCache().isItem(repairable, material.asItem());
} }
private boolean isRenaming(GeyserSession session, AnvilContainer anvilContainer, boolean bedrock) { private boolean isRenaming(GeyserSession session, AnvilContainer anvilContainer, boolean bedrock) {
@ -405,27 +409,27 @@ public class AnvilInventoryUpdater extends InventoryUpdater {
} }
// This should really check the name field in all cases, but that requires the localized name // This should really check the name field in all cases, but that requires the localized name
// of the item which can change depending on NBT and Minecraft Edition // of the item which can change depending on NBT and Minecraft Edition
Component originalName = ItemUtils.getCustomName(anvilContainer.getInput().getComponents()); Component originalName = anvilContainer.getInput().getComponent(DataComponentType.CUSTOM_NAME);
if (bedrock && originalName != null && anvilContainer.getNewName() != null) { if (bedrock && originalName != null && anvilContainer.getNewName() != null) {
// Check text and formatting // Check text and formatting
String legacyOriginalName = MessageTranslator.convertMessage(originalName, session.locale()); String legacyOriginalName = MessageTranslator.convertMessage(originalName, session.locale());
return !legacyOriginalName.equals(anvilContainer.getNewName()); return !legacyOriginalName.equals(anvilContainer.getNewName());
} }
return !Objects.equals(originalName, ItemUtils.getCustomName(anvilContainer.getResult().getComponents())); return !Objects.equals(originalName, anvilContainer.getResult().getComponent(DataComponentType.CUSTOM_NAME));
} }
private int getRepairCost(GeyserItemStack itemStack) { private int getRepairCost(GeyserItemStack itemStack) {
return itemStack.getComponent(DataComponentType.REPAIR_COST, 0); return itemStack.getComponentOrFallback(DataComponentType.REPAIR_COST, 0);
} }
private boolean hasDurability(GeyserItemStack itemStack) { private boolean hasDurability(GeyserItemStack itemStack) {
if (itemStack.asItem().maxDamage() > 0) { if (itemStack.asItem().defaultMaxDamage() > 0) {
return itemStack.getComponent(DataComponentType.UNBREAKABLE, false); return itemStack.getComponentOrFallback(DataComponentType.UNBREAKABLE, false);
} }
return false; return false;
} }
private int getDamage(GeyserItemStack itemStack) { private int getDamage(GeyserItemStack itemStack) {
return itemStack.getComponent(DataComponentType.DAMAGE, 0); return itemStack.getComponentOrFallback(DataComponentType.DAMAGE, 0);
} }
} }

View file

@ -112,6 +112,7 @@ public final class GeyserNonVanillaCustomItemData extends GeyserCustomItemData i
return toolType; return toolType;
} }
@SuppressWarnings("removal")
@Override @Override
public String toolTier() { public String toolTier() {
return toolTier; return toolTier;
@ -132,6 +133,7 @@ public final class GeyserNonVanillaCustomItemData extends GeyserCustomItemData i
return translationString; return translationString;
} }
@SuppressWarnings("removal")
@Override @Override
public Set<String> repairMaterials() { public Set<String> repairMaterials() {
return repairMaterials; return repairMaterials;

View file

@ -25,7 +25,6 @@
package org.geysermc.geyser.item; package org.geysermc.geyser.item;
import org.geysermc.geyser.item.components.ToolTier;
import org.geysermc.geyser.item.type.ArmorItem; import org.geysermc.geyser.item.type.ArmorItem;
import org.geysermc.geyser.item.type.ArrowItem; import org.geysermc.geyser.item.type.ArrowItem;
import org.geysermc.geyser.item.type.AxolotlBucketItem; import org.geysermc.geyser.item.type.AxolotlBucketItem;
@ -37,7 +36,6 @@ import org.geysermc.geyser.item.type.CrossbowItem;
import org.geysermc.geyser.item.type.DecoratedPotItem; import org.geysermc.geyser.item.type.DecoratedPotItem;
import org.geysermc.geyser.item.type.DyeItem; import org.geysermc.geyser.item.type.DyeItem;
import org.geysermc.geyser.item.type.DyeableArmorItem; 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.EnchantedBookItem;
import org.geysermc.geyser.item.type.FilledMapItem; import org.geysermc.geyser.item.type.FilledMapItem;
import org.geysermc.geyser.item.type.FireworkRocketItem; import org.geysermc.geyser.item.type.FireworkRocketItem;
@ -46,7 +44,6 @@ import org.geysermc.geyser.item.type.FishingRodItem;
import org.geysermc.geyser.item.type.GoatHornItem; import org.geysermc.geyser.item.type.GoatHornItem;
import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.item.type.Item;
import org.geysermc.geyser.item.type.LightItem; 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.MapItem;
import org.geysermc.geyser.item.type.OminousBottleItem; import org.geysermc.geyser.item.type.OminousBottleItem;
import org.geysermc.geyser.item.type.PlayerHeadItem; import org.geysermc.geyser.item.type.PlayerHeadItem;
@ -54,7 +51,6 @@ import org.geysermc.geyser.item.type.PotionItem;
import org.geysermc.geyser.item.type.ShieldItem; import org.geysermc.geyser.item.type.ShieldItem;
import org.geysermc.geyser.item.type.ShulkerBoxItem; import org.geysermc.geyser.item.type.ShulkerBoxItem;
import org.geysermc.geyser.item.type.SpawnEggItem; 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.TippedArrowItem;
import org.geysermc.geyser.item.type.TropicalFishBucketItem; import org.geysermc.geyser.item.type.TropicalFishBucketItem;
import org.geysermc.geyser.item.type.WolfArmorItem; import org.geysermc.geyser.item.type.WolfArmorItem;
@ -296,6 +292,8 @@ public final class Items {
public static final Item RED_WOOL = register(new BlockItem(builder(), Blocks.RED_WOOL)); public static final Item RED_WOOL = register(new BlockItem(builder(), Blocks.RED_WOOL));
public static final Item BLACK_WOOL = register(new BlockItem(builder(), Blocks.BLACK_WOOL)); public static final Item BLACK_WOOL = register(new BlockItem(builder(), Blocks.BLACK_WOOL));
public static final Item DANDELION = register(new BlockItem(builder(), Blocks.DANDELION)); public static final Item DANDELION = register(new BlockItem(builder(), Blocks.DANDELION));
public static final Item OPEN_EYEBLOSSOM = register(new BlockItem(builder(), Blocks.OPEN_EYEBLOSSOM));
public static final Item CLOSED_EYEBLOSSOM = register(new BlockItem(builder(), Blocks.CLOSED_EYEBLOSSOM));
public static final Item POPPY = register(new BlockItem(builder(), Blocks.POPPY)); public static final Item POPPY = register(new BlockItem(builder(), Blocks.POPPY));
public static final Item BLUE_ORCHID = register(new BlockItem(builder(), Blocks.BLUE_ORCHID)); public static final Item BLUE_ORCHID = register(new BlockItem(builder(), Blocks.BLUE_ORCHID));
public static final Item ALLIUM = register(new BlockItem(builder(), Blocks.ALLIUM)); public static final Item ALLIUM = register(new BlockItem(builder(), Blocks.ALLIUM));
@ -444,6 +442,13 @@ public final class Items {
public static final Item MELON = register(new BlockItem(builder(), Blocks.MELON)); public static final Item MELON = register(new BlockItem(builder(), Blocks.MELON));
public static final Item VINE = register(new BlockItem(builder(), Blocks.VINE)); public static final Item VINE = register(new BlockItem(builder(), Blocks.VINE));
public static final Item GLOW_LICHEN = register(new BlockItem(builder(), Blocks.GLOW_LICHEN)); public static final Item GLOW_LICHEN = register(new BlockItem(builder(), Blocks.GLOW_LICHEN));
public static final Item RESIN_CLUMP = register(new BlockItem(builder(), Blocks.RESIN_CLUMP));
public static final Item RESIN_BLOCK = register(new BlockItem(builder(), Blocks.RESIN_BLOCK));
public static final Item RESIN_BRICKS = register(new BlockItem(builder(), Blocks.RESIN_BRICKS));
public static final Item RESIN_BRICK_STAIRS = register(new BlockItem(builder(), Blocks.RESIN_BRICK_STAIRS));
public static final Item RESIN_BRICK_SLAB = register(new BlockItem(builder(), Blocks.RESIN_BRICK_SLAB));
public static final Item RESIN_BRICK_WALL = register(new BlockItem(builder(), Blocks.RESIN_BRICK_WALL));
public static final Item CHISELED_RESIN_BRICKS = register(new BlockItem(builder(), Blocks.CHISELED_RESIN_BRICKS));
public static final Item BRICK_STAIRS = register(new BlockItem(builder(), Blocks.BRICK_STAIRS)); public static final Item BRICK_STAIRS = register(new BlockItem(builder(), Blocks.BRICK_STAIRS));
public static final Item STONE_BRICK_STAIRS = register(new BlockItem(builder(), Blocks.STONE_BRICK_STAIRS)); public static final Item STONE_BRICK_STAIRS = register(new BlockItem(builder(), Blocks.STONE_BRICK_STAIRS));
public static final Item MUD_BRICK_STAIRS = register(new BlockItem(builder(), Blocks.MUD_BRICK_STAIRS)); public static final Item MUD_BRICK_STAIRS = register(new BlockItem(builder(), Blocks.MUD_BRICK_STAIRS));
@ -606,23 +611,23 @@ public final class Items {
public static final Item RED_NETHER_BRICKS = register(new BlockItem(builder(), Blocks.RED_NETHER_BRICKS)); public static final Item RED_NETHER_BRICKS = register(new BlockItem(builder(), Blocks.RED_NETHER_BRICKS));
public static final Item BONE_BLOCK = register(new BlockItem(builder(), Blocks.BONE_BLOCK)); public static final Item BONE_BLOCK = register(new BlockItem(builder(), Blocks.BONE_BLOCK));
public static final Item STRUCTURE_VOID = register(new BlockItem(builder(), Blocks.STRUCTURE_VOID)); public static final Item STRUCTURE_VOID = register(new BlockItem(builder(), Blocks.STRUCTURE_VOID));
public static final Item SHULKER_BOX = register(new ShulkerBoxItem(builder().stackSize(1), Blocks.SHULKER_BOX)); public static final Item SHULKER_BOX = register(new ShulkerBoxItem(builder(), Blocks.SHULKER_BOX));
public static final Item WHITE_SHULKER_BOX = register(new ShulkerBoxItem(builder().stackSize(1), Blocks.WHITE_SHULKER_BOX)); public static final Item WHITE_SHULKER_BOX = register(new ShulkerBoxItem(builder(), Blocks.WHITE_SHULKER_BOX));
public static final Item ORANGE_SHULKER_BOX = register(new ShulkerBoxItem(builder().stackSize(1), Blocks.ORANGE_SHULKER_BOX)); public static final Item ORANGE_SHULKER_BOX = register(new ShulkerBoxItem(builder(), Blocks.ORANGE_SHULKER_BOX));
public static final Item MAGENTA_SHULKER_BOX = register(new ShulkerBoxItem(builder().stackSize(1), Blocks.MAGENTA_SHULKER_BOX)); public static final Item MAGENTA_SHULKER_BOX = register(new ShulkerBoxItem(builder(), Blocks.MAGENTA_SHULKER_BOX));
public static final Item LIGHT_BLUE_SHULKER_BOX = register(new ShulkerBoxItem(builder().stackSize(1), Blocks.LIGHT_BLUE_SHULKER_BOX)); public static final Item LIGHT_BLUE_SHULKER_BOX = register(new ShulkerBoxItem(builder(), Blocks.LIGHT_BLUE_SHULKER_BOX));
public static final Item YELLOW_SHULKER_BOX = register(new ShulkerBoxItem(builder().stackSize(1), Blocks.YELLOW_SHULKER_BOX)); public static final Item YELLOW_SHULKER_BOX = register(new ShulkerBoxItem(builder(), Blocks.YELLOW_SHULKER_BOX));
public static final Item LIME_SHULKER_BOX = register(new ShulkerBoxItem(builder().stackSize(1), Blocks.LIME_SHULKER_BOX)); public static final Item LIME_SHULKER_BOX = register(new ShulkerBoxItem(builder(), Blocks.LIME_SHULKER_BOX));
public static final Item PINK_SHULKER_BOX = register(new ShulkerBoxItem(builder().stackSize(1), Blocks.PINK_SHULKER_BOX)); public static final Item PINK_SHULKER_BOX = register(new ShulkerBoxItem(builder(), Blocks.PINK_SHULKER_BOX));
public static final Item GRAY_SHULKER_BOX = register(new ShulkerBoxItem(builder().stackSize(1), Blocks.GRAY_SHULKER_BOX)); public static final Item GRAY_SHULKER_BOX = register(new ShulkerBoxItem(builder(), Blocks.GRAY_SHULKER_BOX));
public static final Item LIGHT_GRAY_SHULKER_BOX = register(new ShulkerBoxItem(builder().stackSize(1), Blocks.LIGHT_GRAY_SHULKER_BOX)); public static final Item LIGHT_GRAY_SHULKER_BOX = register(new ShulkerBoxItem(builder(), Blocks.LIGHT_GRAY_SHULKER_BOX));
public static final Item CYAN_SHULKER_BOX = register(new ShulkerBoxItem(builder().stackSize(1), Blocks.CYAN_SHULKER_BOX)); public static final Item CYAN_SHULKER_BOX = register(new ShulkerBoxItem(builder(), Blocks.CYAN_SHULKER_BOX));
public static final Item PURPLE_SHULKER_BOX = register(new ShulkerBoxItem(builder().stackSize(1), Blocks.PURPLE_SHULKER_BOX)); public static final Item PURPLE_SHULKER_BOX = register(new ShulkerBoxItem(builder(), Blocks.PURPLE_SHULKER_BOX));
public static final Item BLUE_SHULKER_BOX = register(new ShulkerBoxItem(builder().stackSize(1), Blocks.BLUE_SHULKER_BOX)); public static final Item BLUE_SHULKER_BOX = register(new ShulkerBoxItem(builder(), Blocks.BLUE_SHULKER_BOX));
public static final Item BROWN_SHULKER_BOX = register(new ShulkerBoxItem(builder().stackSize(1), Blocks.BROWN_SHULKER_BOX)); public static final Item BROWN_SHULKER_BOX = register(new ShulkerBoxItem(builder(), Blocks.BROWN_SHULKER_BOX));
public static final Item GREEN_SHULKER_BOX = register(new ShulkerBoxItem(builder().stackSize(1), Blocks.GREEN_SHULKER_BOX)); public static final Item GREEN_SHULKER_BOX = register(new ShulkerBoxItem(builder(), Blocks.GREEN_SHULKER_BOX));
public static final Item RED_SHULKER_BOX = register(new ShulkerBoxItem(builder().stackSize(1), Blocks.RED_SHULKER_BOX)); public static final Item RED_SHULKER_BOX = register(new ShulkerBoxItem(builder(), Blocks.RED_SHULKER_BOX));
public static final Item BLACK_SHULKER_BOX = register(new ShulkerBoxItem(builder().stackSize(1), Blocks.BLACK_SHULKER_BOX)); public static final Item BLACK_SHULKER_BOX = register(new ShulkerBoxItem(builder(), Blocks.BLACK_SHULKER_BOX));
public static final Item WHITE_GLAZED_TERRACOTTA = register(new BlockItem(builder(), Blocks.WHITE_GLAZED_TERRACOTTA)); public static final Item WHITE_GLAZED_TERRACOTTA = register(new BlockItem(builder(), Blocks.WHITE_GLAZED_TERRACOTTA));
public static final Item ORANGE_GLAZED_TERRACOTTA = register(new BlockItem(builder(), Blocks.ORANGE_GLAZED_TERRACOTTA)); public static final Item ORANGE_GLAZED_TERRACOTTA = register(new BlockItem(builder(), Blocks.ORANGE_GLAZED_TERRACOTTA));
public static final Item MAGENTA_GLAZED_TERRACOTTA = register(new BlockItem(builder(), Blocks.MAGENTA_GLAZED_TERRACOTTA)); public static final Item MAGENTA_GLAZED_TERRACOTTA = register(new BlockItem(builder(), Blocks.MAGENTA_GLAZED_TERRACOTTA));
@ -854,46 +859,46 @@ public final class Items {
public static final Item DETECTOR_RAIL = register(new BlockItem(builder(), Blocks.DETECTOR_RAIL)); public static final Item DETECTOR_RAIL = register(new BlockItem(builder(), Blocks.DETECTOR_RAIL));
public static final Item RAIL = register(new BlockItem(builder(), Blocks.RAIL)); public static final Item RAIL = register(new BlockItem(builder(), Blocks.RAIL));
public static final Item ACTIVATOR_RAIL = register(new BlockItem(builder(), Blocks.ACTIVATOR_RAIL)); public static final Item ACTIVATOR_RAIL = register(new BlockItem(builder(), Blocks.ACTIVATOR_RAIL));
public static final Item SADDLE = register(new Item("saddle", builder().stackSize(1))); public static final Item SADDLE = register(new Item("saddle", builder()));
public static final Item MINECART = register(new Item("minecart", builder().stackSize(1))); public static final Item MINECART = register(new Item("minecart", builder()));
public static final Item CHEST_MINECART = register(new Item("chest_minecart", builder().stackSize(1))); public static final Item CHEST_MINECART = register(new Item("chest_minecart", builder()));
public static final Item FURNACE_MINECART = register(new Item("furnace_minecart", builder().stackSize(1))); public static final Item FURNACE_MINECART = register(new Item("furnace_minecart", builder()));
public static final Item TNT_MINECART = register(new Item("tnt_minecart", builder().stackSize(1))); public static final Item TNT_MINECART = register(new Item("tnt_minecart", builder()));
public static final Item HOPPER_MINECART = register(new Item("hopper_minecart", builder().stackSize(1))); public static final Item HOPPER_MINECART = register(new Item("hopper_minecart", builder()));
public static final Item CARROT_ON_A_STICK = register(new Item("carrot_on_a_stick", builder().stackSize(1).maxDamage(25))); public static final Item CARROT_ON_A_STICK = register(new Item("carrot_on_a_stick", builder()));
public static final Item WARPED_FUNGUS_ON_A_STICK = register(new Item("warped_fungus_on_a_stick", builder().stackSize(1).maxDamage(100))); public static final Item WARPED_FUNGUS_ON_A_STICK = register(new Item("warped_fungus_on_a_stick", builder()));
public static final Item PHANTOM_MEMBRANE = register(new Item("phantom_membrane", builder())); 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 ELYTRA = register(new Item("elytra", builder()));
public static final Item OAK_BOAT = register(new BoatItem("oak_boat", builder().stackSize(1))); public static final Item OAK_BOAT = register(new BoatItem("oak_boat", builder()));
public static final Item OAK_CHEST_BOAT = register(new BoatItem("oak_chest_boat", builder().stackSize(1))); public static final Item OAK_CHEST_BOAT = register(new BoatItem("oak_chest_boat", builder()));
public static final Item SPRUCE_BOAT = register(new BoatItem("spruce_boat", builder().stackSize(1))); public static final Item SPRUCE_BOAT = register(new BoatItem("spruce_boat", builder()));
public static final Item SPRUCE_CHEST_BOAT = register(new BoatItem("spruce_chest_boat", builder().stackSize(1))); public static final Item SPRUCE_CHEST_BOAT = register(new BoatItem("spruce_chest_boat", builder()));
public static final Item BIRCH_BOAT = register(new BoatItem("birch_boat", builder().stackSize(1))); public static final Item BIRCH_BOAT = register(new BoatItem("birch_boat", builder()));
public static final Item BIRCH_CHEST_BOAT = register(new BoatItem("birch_chest_boat", builder().stackSize(1))); public static final Item BIRCH_CHEST_BOAT = register(new BoatItem("birch_chest_boat", builder()));
public static final Item JUNGLE_BOAT = register(new BoatItem("jungle_boat", builder().stackSize(1))); public static final Item JUNGLE_BOAT = register(new BoatItem("jungle_boat", builder()));
public static final Item JUNGLE_CHEST_BOAT = register(new BoatItem("jungle_chest_boat", builder().stackSize(1))); public static final Item JUNGLE_CHEST_BOAT = register(new BoatItem("jungle_chest_boat", builder()));
public static final Item ACACIA_BOAT = register(new BoatItem("acacia_boat", builder().stackSize(1))); public static final Item ACACIA_BOAT = register(new BoatItem("acacia_boat", builder()));
public static final Item ACACIA_CHEST_BOAT = register(new BoatItem("acacia_chest_boat", builder().stackSize(1))); public static final Item ACACIA_CHEST_BOAT = register(new BoatItem("acacia_chest_boat", builder()));
public static final Item CHERRY_BOAT = register(new BoatItem("cherry_boat", builder().stackSize(1))); public static final Item CHERRY_BOAT = register(new BoatItem("cherry_boat", builder()));
public static final Item CHERRY_CHEST_BOAT = register(new BoatItem("cherry_chest_boat", builder().stackSize(1))); public static final Item CHERRY_CHEST_BOAT = register(new BoatItem("cherry_chest_boat", builder()));
public static final Item DARK_OAK_BOAT = register(new BoatItem("dark_oak_boat", builder().stackSize(1))); public static final Item DARK_OAK_BOAT = register(new BoatItem("dark_oak_boat", builder()));
public static final Item DARK_OAK_CHEST_BOAT = register(new BoatItem("dark_oak_chest_boat", builder().stackSize(1))); public static final Item DARK_OAK_CHEST_BOAT = register(new BoatItem("dark_oak_chest_boat", builder()));
public static final Item PALE_OAK_BOAT = register(new BoatItem("pale_oak_boat", builder().stackSize(1))); public static final Item PALE_OAK_BOAT = register(new BoatItem("pale_oak_boat", builder()));
public static final Item PALE_OAK_CHEST_BOAT = register(new BoatItem("pale_oak_chest_boat", builder().stackSize(1))); public static final Item PALE_OAK_CHEST_BOAT = register(new BoatItem("pale_oak_chest_boat", builder()));
public static final Item MANGROVE_BOAT = register(new BoatItem("mangrove_boat", builder().stackSize(1))); public static final Item MANGROVE_BOAT = register(new BoatItem("mangrove_boat", builder()));
public static final Item MANGROVE_CHEST_BOAT = register(new BoatItem("mangrove_chest_boat", builder().stackSize(1))); public static final Item MANGROVE_CHEST_BOAT = register(new BoatItem("mangrove_chest_boat", builder()));
public static final Item BAMBOO_RAFT = register(new BoatItem("bamboo_raft", builder().stackSize(1))); public static final Item BAMBOO_RAFT = register(new BoatItem("bamboo_raft", builder()));
public static final Item BAMBOO_CHEST_RAFT = register(new BoatItem("bamboo_chest_raft", builder().stackSize(1))); public static final Item BAMBOO_CHEST_RAFT = register(new BoatItem("bamboo_chest_raft", builder()));
public static final Item STRUCTURE_BLOCK = register(new BlockItem(builder(), Blocks.STRUCTURE_BLOCK)); public static final Item STRUCTURE_BLOCK = register(new BlockItem(builder(), Blocks.STRUCTURE_BLOCK));
public static final Item JIGSAW = register(new BlockItem(builder(), Blocks.JIGSAW)); public static final Item JIGSAW = register(new BlockItem(builder(), Blocks.JIGSAW));
public static final Item TURTLE_HELMET = register(new ArmorItem("turtle_helmet", ArmorMaterial.TURTLE, builder().stackSize(1).maxDamage(275))); public static final Item TURTLE_HELMET = register(new ArmorItem("turtle_helmet", builder()));
public static final Item TURTLE_SCUTE = register(new Item("turtle_scute", builder())); public static final Item TURTLE_SCUTE = register(new Item("turtle_scute", builder()));
public static final Item ARMADILLO_SCUTE = register(new Item("armadillo_scute", builder())); public static final Item ARMADILLO_SCUTE = register(new Item("armadillo_scute", builder()));
public static final Item WOLF_ARMOR = register(new WolfArmorItem("wolf_armor", ArmorMaterial.ARMADILLO, builder().stackSize(1).maxDamage(64))); public static final Item WOLF_ARMOR = register(new WolfArmorItem("wolf_armor", builder()));
public static final Item FLINT_AND_STEEL = register(new Item("flint_and_steel", builder().stackSize(1).maxDamage(64))); public static final Item FLINT_AND_STEEL = register(new Item("flint_and_steel", builder()));
public static final Item BOWL = register(new Item("bowl", builder())); public static final Item BOWL = register(new Item("bowl", builder()));
public static final Item APPLE = register(new Item("apple", builder())); public static final Item APPLE = register(new Item("apple", builder()));
public static final Item BOW = register(new Item("bow", builder().stackSize(1).maxDamage(384))); public static final Item BOW = register(new Item("bow", builder()));
public static final Item ARROW = register(new ArrowItem("arrow", builder())); public static final Item ARROW = register(new ArrowItem("arrow", builder()));
public static final Item COAL = register(new Item("coal", builder())); public static final Item COAL = register(new Item("coal", builder()));
public static final Item CHARCOAL = register(new Item("charcoal", builder())); public static final Item CHARCOAL = register(new Item("charcoal", builder()));
@ -910,140 +915,140 @@ public final class Items {
public static final Item GOLD_INGOT = register(new Item("gold_ingot", builder())); public static final Item GOLD_INGOT = register(new Item("gold_ingot", builder()));
public static final Item NETHERITE_INGOT = register(new Item("netherite_ingot", builder())); public static final Item NETHERITE_INGOT = register(new Item("netherite_ingot", builder()));
public static final Item NETHERITE_SCRAP = register(new Item("netherite_scrap", builder())); public static final Item NETHERITE_SCRAP = register(new Item("netherite_scrap", builder()));
public static final Item WOODEN_SWORD = register(new TieredItem("wooden_sword", ToolTier.WOODEN, builder().stackSize(1).maxDamage(59).attackDamage(4.0))); public static final Item WOODEN_SWORD = register(new Item("wooden_sword", builder().attackDamage(4.0)));
public static final Item WOODEN_SHOVEL = register(new TieredItem("wooden_shovel", ToolTier.WOODEN, builder().stackSize(1).maxDamage(59).attackDamage(2.5))); public static final Item WOODEN_SHOVEL = register(new Item("wooden_shovel", builder().attackDamage(2.5)));
public static final Item WOODEN_PICKAXE = register(new TieredItem("wooden_pickaxe", ToolTier.WOODEN, builder().stackSize(1).maxDamage(59).attackDamage(2.0))); public static final Item WOODEN_PICKAXE = register(new Item("wooden_pickaxe", builder().attackDamage(2.0)));
public static final Item WOODEN_AXE = register(new TieredItem("wooden_axe", ToolTier.WOODEN, builder().stackSize(1).maxDamage(59).attackDamage(7.0))); public static final Item WOODEN_AXE = register(new Item("wooden_axe", builder().attackDamage(7.0)));
public static final Item WOODEN_HOE = register(new TieredItem("wooden_hoe", ToolTier.WOODEN, builder().stackSize(1).maxDamage(59).attackDamage(1.0))); public static final Item WOODEN_HOE = register(new Item("wooden_hoe", builder().attackDamage(1.0)));
public static final Item STONE_SWORD = register(new TieredItem("stone_sword", ToolTier.STONE, builder().stackSize(1).maxDamage(131).attackDamage(5.0))); public static final Item STONE_SWORD = register(new Item("stone_sword", builder().attackDamage(5.0)));
public static final Item STONE_SHOVEL = register(new TieredItem("stone_shovel", ToolTier.STONE, builder().stackSize(1).maxDamage(131).attackDamage(3.5))); public static final Item STONE_SHOVEL = register(new Item("stone_shovel", builder().attackDamage(3.5)));
public static final Item STONE_PICKAXE = register(new TieredItem("stone_pickaxe", ToolTier.STONE, builder().stackSize(1).maxDamage(131).attackDamage(3.0))); public static final Item STONE_PICKAXE = register(new Item("stone_pickaxe", builder().attackDamage(3.0)));
public static final Item STONE_AXE = register(new TieredItem("stone_axe", ToolTier.STONE, builder().stackSize(1).maxDamage(131).attackDamage(9.0))); public static final Item STONE_AXE = register(new Item("stone_axe", builder().attackDamage(9.0)));
public static final Item STONE_HOE = register(new TieredItem("stone_hoe", ToolTier.STONE, builder().stackSize(1).maxDamage(131).attackDamage(1.0))); public static final Item STONE_HOE = register(new Item("stone_hoe", builder().attackDamage(1.0)));
public static final Item GOLDEN_SWORD = register(new TieredItem("golden_sword", ToolTier.GOLDEN, builder().stackSize(1).maxDamage(32).attackDamage(4.0))); public static final Item GOLDEN_SWORD = register(new Item("golden_sword", builder().attackDamage(4.0)));
public static final Item GOLDEN_SHOVEL = register(new TieredItem("golden_shovel", ToolTier.GOLDEN, builder().stackSize(1).maxDamage(32).attackDamage(2.5))); public static final Item GOLDEN_SHOVEL = register(new Item("golden_shovel", builder().attackDamage(2.5)));
public static final Item GOLDEN_PICKAXE = register(new TieredItem("golden_pickaxe", ToolTier.GOLDEN, builder().stackSize(1).maxDamage(32).attackDamage(2.0))); public static final Item GOLDEN_PICKAXE = register(new Item("golden_pickaxe", builder().attackDamage(2.0)));
public static final Item GOLDEN_AXE = register(new TieredItem("golden_axe", ToolTier.GOLDEN, builder().stackSize(1).maxDamage(32).attackDamage(7.0))); public static final Item GOLDEN_AXE = register(new Item("golden_axe", builder().attackDamage(7.0)));
public static final Item GOLDEN_HOE = register(new TieredItem("golden_hoe", ToolTier.GOLDEN, builder().stackSize(1).maxDamage(32).attackDamage(1.0))); public static final Item GOLDEN_HOE = register(new Item("golden_hoe", builder().attackDamage(1.0)));
public static final Item IRON_SWORD = register(new TieredItem("iron_sword", ToolTier.IRON, builder().stackSize(1).maxDamage(250).attackDamage(6.0))); public static final Item IRON_SWORD = register(new Item("iron_sword", builder().attackDamage(6.0)));
public static final Item IRON_SHOVEL = register(new TieredItem("iron_shovel", ToolTier.IRON, builder().stackSize(1).maxDamage(250).attackDamage(4.5))); public static final Item IRON_SHOVEL = register(new Item("iron_shovel", builder().attackDamage(4.5)));
public static final Item IRON_PICKAXE = register(new TieredItem("iron_pickaxe", ToolTier.IRON, builder().stackSize(1).maxDamage(250).attackDamage(4.0))); public static final Item IRON_PICKAXE = register(new Item("iron_pickaxe", builder().attackDamage(4.0)));
public static final Item IRON_AXE = register(new TieredItem("iron_axe", ToolTier.IRON, builder().stackSize(1).maxDamage(250).attackDamage(9.0))); public static final Item IRON_AXE = register(new Item("iron_axe", builder().attackDamage(9.0)));
public static final Item IRON_HOE = register(new TieredItem("iron_hoe", ToolTier.IRON, builder().stackSize(1).maxDamage(250).attackDamage(1.0))); public static final Item IRON_HOE = register(new Item("iron_hoe", builder().attackDamage(1.0)));
public static final Item DIAMOND_SWORD = register(new TieredItem("diamond_sword", ToolTier.DIAMOND, builder().stackSize(1).maxDamage(1561).attackDamage(7.0))); public static final Item DIAMOND_SWORD = register(new Item("diamond_sword", builder().attackDamage(7.0)));
public static final Item DIAMOND_SHOVEL = register(new TieredItem("diamond_shovel", ToolTier.DIAMOND, builder().stackSize(1).maxDamage(1561).attackDamage(5.5))); public static final Item DIAMOND_SHOVEL = register(new Item("diamond_shovel", builder().attackDamage(5.5)));
public static final Item DIAMOND_PICKAXE = register(new TieredItem("diamond_pickaxe", ToolTier.DIAMOND, builder().stackSize(1).maxDamage(1561).attackDamage(5.0))); public static final Item DIAMOND_PICKAXE = register(new Item("diamond_pickaxe", builder().attackDamage(5.0)));
public static final Item DIAMOND_AXE = register(new TieredItem("diamond_axe", ToolTier.DIAMOND, builder().stackSize(1).maxDamage(1561).attackDamage(9.0))); public static final Item DIAMOND_AXE = register(new Item("diamond_axe", builder().attackDamage(9.0)));
public static final Item DIAMOND_HOE = register(new TieredItem("diamond_hoe", ToolTier.DIAMOND, builder().stackSize(1).maxDamage(1561).attackDamage(1.0))); public static final Item DIAMOND_HOE = register(new Item("diamond_hoe", builder().attackDamage(1.0)));
public static final Item NETHERITE_SWORD = register(new TieredItem("netherite_sword", ToolTier.NETHERITE, builder().stackSize(1).maxDamage(2031).attackDamage(8.0))); public static final Item NETHERITE_SWORD = register(new Item("netherite_sword", builder().attackDamage(8.0)));
public static final Item NETHERITE_SHOVEL = register(new TieredItem("netherite_shovel", ToolTier.NETHERITE, builder().stackSize(1).maxDamage(2031).attackDamage(6.5))); public static final Item NETHERITE_SHOVEL = register(new Item("netherite_shovel", builder().attackDamage(6.5)));
public static final Item NETHERITE_PICKAXE = register(new TieredItem("netherite_pickaxe", ToolTier.NETHERITE, builder().stackSize(1).maxDamage(2031).attackDamage(6.0))); public static final Item NETHERITE_PICKAXE = register(new Item("netherite_pickaxe", builder().attackDamage(6.0)));
public static final Item NETHERITE_AXE = register(new TieredItem("netherite_axe", ToolTier.NETHERITE, builder().stackSize(1).maxDamage(2031).attackDamage(10.0))); public static final Item NETHERITE_AXE = register(new Item("netherite_axe", builder().attackDamage(10.0)));
public static final Item NETHERITE_HOE = register(new TieredItem("netherite_hoe", ToolTier.NETHERITE, builder().stackSize(1).maxDamage(2031).attackDamage(1.0))); public static final Item NETHERITE_HOE = register(new Item("netherite_hoe", builder().attackDamage(1.0)));
public static final Item STICK = register(new Item("stick", builder())); public static final Item STICK = register(new Item("stick", builder()));
public static final Item MUSHROOM_STEW = register(new Item("mushroom_stew", builder().stackSize(1))); public static final Item MUSHROOM_STEW = register(new Item("mushroom_stew", builder()));
public static final Item STRING = register(new BlockItem("string", builder(), Blocks.TRIPWIRE)); public static final Item STRING = register(new BlockItem("string", builder(), Blocks.TRIPWIRE));
public static final Item FEATHER = register(new Item("feather", builder())); public static final Item FEATHER = register(new Item("feather", builder()));
public static final Item GUNPOWDER = register(new Item("gunpowder", builder())); public static final Item GUNPOWDER = register(new Item("gunpowder", builder()));
public static final Item WHEAT_SEEDS = register(new BlockItem("wheat_seeds", builder(), Blocks.WHEAT)); public static final Item WHEAT_SEEDS = register(new BlockItem("wheat_seeds", builder(), Blocks.WHEAT));
public static final Item WHEAT = register(new Item("wheat", builder())); public static final Item WHEAT = register(new Item("wheat", builder()));
public static final Item BREAD = register(new Item("bread", builder())); public static final Item BREAD = register(new Item("bread", builder()));
public static final Item LEATHER_HELMET = register(new DyeableArmorItem("leather_helmet", ArmorMaterial.LEATHER, builder().stackSize(1).maxDamage(55))); public static final Item LEATHER_HELMET = register(new DyeableArmorItem("leather_helmet", builder()));
public static final Item LEATHER_CHESTPLATE = register(new DyeableArmorItem("leather_chestplate", ArmorMaterial.LEATHER, builder().stackSize(1).maxDamage(80))); public static final Item LEATHER_CHESTPLATE = register(new DyeableArmorItem("leather_chestplate", builder()));
public static final Item LEATHER_LEGGINGS = register(new DyeableArmorItem("leather_leggings", ArmorMaterial.LEATHER, builder().stackSize(1).maxDamage(75))); public static final Item LEATHER_LEGGINGS = register(new DyeableArmorItem("leather_leggings", builder()));
public static final Item LEATHER_BOOTS = register(new DyeableArmorItem("leather_boots", ArmorMaterial.LEATHER, builder().stackSize(1).maxDamage(65))); public static final Item LEATHER_BOOTS = register(new DyeableArmorItem("leather_boots", builder()));
public static final Item CHAINMAIL_HELMET = register(new ArmorItem("chainmail_helmet", ArmorMaterial.CHAINMAIL, builder().stackSize(1).maxDamage(165))); public static final Item CHAINMAIL_HELMET = register(new ArmorItem("chainmail_helmet", builder()));
public static final Item CHAINMAIL_CHESTPLATE = register(new ArmorItem("chainmail_chestplate", ArmorMaterial.CHAINMAIL, builder().stackSize(1).maxDamage(240))); public static final Item CHAINMAIL_CHESTPLATE = register(new ArmorItem("chainmail_chestplate", builder()));
public static final Item CHAINMAIL_LEGGINGS = register(new ArmorItem("chainmail_leggings", ArmorMaterial.CHAINMAIL, builder().stackSize(1).maxDamage(225))); public static final Item CHAINMAIL_LEGGINGS = register(new ArmorItem("chainmail_leggings", builder()));
public static final Item CHAINMAIL_BOOTS = register(new ArmorItem("chainmail_boots", ArmorMaterial.CHAINMAIL, builder().stackSize(1).maxDamage(195))); public static final Item CHAINMAIL_BOOTS = register(new ArmorItem("chainmail_boots", builder()));
public static final Item IRON_HELMET = register(new ArmorItem("iron_helmet", ArmorMaterial.IRON, builder().stackSize(1).maxDamage(165))); public static final Item IRON_HELMET = register(new ArmorItem("iron_helmet", builder()));
public static final Item IRON_CHESTPLATE = register(new ArmorItem("iron_chestplate", ArmorMaterial.IRON, builder().stackSize(1).maxDamage(240))); public static final Item IRON_CHESTPLATE = register(new ArmorItem("iron_chestplate", builder()));
public static final Item IRON_LEGGINGS = register(new ArmorItem("iron_leggings", ArmorMaterial.IRON, builder().stackSize(1).maxDamage(225))); public static final Item IRON_LEGGINGS = register(new ArmorItem("iron_leggings", builder()));
public static final Item IRON_BOOTS = register(new ArmorItem("iron_boots", ArmorMaterial.IRON, builder().stackSize(1).maxDamage(195))); public static final Item IRON_BOOTS = register(new ArmorItem("iron_boots", builder()));
public static final Item DIAMOND_HELMET = register(new ArmorItem("diamond_helmet", ArmorMaterial.DIAMOND, builder().stackSize(1).maxDamage(363))); public static final Item DIAMOND_HELMET = register(new ArmorItem("diamond_helmet", builder()));
public static final Item DIAMOND_CHESTPLATE = register(new ArmorItem("diamond_chestplate", ArmorMaterial.DIAMOND, builder().stackSize(1).maxDamage(528))); public static final Item DIAMOND_CHESTPLATE = register(new ArmorItem("diamond_chestplate", builder()));
public static final Item DIAMOND_LEGGINGS = register(new ArmorItem("diamond_leggings", ArmorMaterial.DIAMOND, builder().stackSize(1).maxDamage(495))); public static final Item DIAMOND_LEGGINGS = register(new ArmorItem("diamond_leggings", builder()));
public static final Item DIAMOND_BOOTS = register(new ArmorItem("diamond_boots", ArmorMaterial.DIAMOND, builder().stackSize(1).maxDamage(429))); public static final Item DIAMOND_BOOTS = register(new ArmorItem("diamond_boots", builder()));
public static final Item GOLDEN_HELMET = register(new ArmorItem("golden_helmet", ArmorMaterial.GOLD, builder().stackSize(1).maxDamage(77))); public static final Item GOLDEN_HELMET = register(new ArmorItem("golden_helmet", builder()));
public static final Item GOLDEN_CHESTPLATE = register(new ArmorItem("golden_chestplate", ArmorMaterial.GOLD, builder().stackSize(1).maxDamage(112))); public static final Item GOLDEN_CHESTPLATE = register(new ArmorItem("golden_chestplate", builder()));
public static final Item GOLDEN_LEGGINGS = register(new ArmorItem("golden_leggings", ArmorMaterial.GOLD, builder().stackSize(1).maxDamage(105))); public static final Item GOLDEN_LEGGINGS = register(new ArmorItem("golden_leggings", builder()));
public static final Item GOLDEN_BOOTS = register(new ArmorItem("golden_boots", ArmorMaterial.GOLD, builder().stackSize(1).maxDamage(91))); public static final Item GOLDEN_BOOTS = register(new ArmorItem("golden_boots", builder()));
public static final Item NETHERITE_HELMET = register(new ArmorItem("netherite_helmet", ArmorMaterial.NETHERITE, builder().stackSize(1).maxDamage(407))); public static final Item NETHERITE_HELMET = register(new ArmorItem("netherite_helmet", builder()));
public static final Item NETHERITE_CHESTPLATE = register(new ArmorItem("netherite_chestplate", ArmorMaterial.NETHERITE, builder().stackSize(1).maxDamage(592))); public static final Item NETHERITE_CHESTPLATE = register(new ArmorItem("netherite_chestplate", builder()));
public static final Item NETHERITE_LEGGINGS = register(new ArmorItem("netherite_leggings", ArmorMaterial.NETHERITE, builder().stackSize(1).maxDamage(555))); public static final Item NETHERITE_LEGGINGS = register(new ArmorItem("netherite_leggings", builder()));
public static final Item NETHERITE_BOOTS = register(new ArmorItem("netherite_boots", ArmorMaterial.NETHERITE, builder().stackSize(1).maxDamage(481))); public static final Item NETHERITE_BOOTS = register(new ArmorItem("netherite_boots", builder()));
public static final Item FLINT = register(new Item("flint", builder())); public static final Item FLINT = register(new Item("flint", builder()));
public static final Item PORKCHOP = register(new Item("porkchop", builder())); public static final Item PORKCHOP = register(new Item("porkchop", builder()));
public static final Item COOKED_PORKCHOP = register(new Item("cooked_porkchop", builder())); public static final Item COOKED_PORKCHOP = register(new Item("cooked_porkchop", builder()));
public static final Item PAINTING = register(new Item("painting", builder())); public static final Item PAINTING = register(new Item("painting", builder()));
public static final Item GOLDEN_APPLE = register(new Item("golden_apple", builder())); 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 ENCHANTED_GOLDEN_APPLE = register(new Item("enchanted_golden_apple", builder()));
public static final Item OAK_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.OAK_SIGN, Blocks.OAK_WALL_SIGN)); public static final Item OAK_SIGN = register(new BlockItem(builder(), Blocks.OAK_SIGN, Blocks.OAK_WALL_SIGN));
public static final Item SPRUCE_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.SPRUCE_SIGN, Blocks.SPRUCE_WALL_SIGN)); public static final Item SPRUCE_SIGN = register(new BlockItem(builder(), Blocks.SPRUCE_SIGN, Blocks.SPRUCE_WALL_SIGN));
public static final Item BIRCH_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.BIRCH_SIGN, Blocks.BIRCH_WALL_SIGN)); public static final Item BIRCH_SIGN = register(new BlockItem(builder(), Blocks.BIRCH_SIGN, Blocks.BIRCH_WALL_SIGN));
public static final Item JUNGLE_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.JUNGLE_SIGN, Blocks.JUNGLE_WALL_SIGN)); public static final Item JUNGLE_SIGN = register(new BlockItem(builder(), Blocks.JUNGLE_SIGN, Blocks.JUNGLE_WALL_SIGN));
public static final Item ACACIA_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.ACACIA_SIGN, Blocks.ACACIA_WALL_SIGN)); public static final Item ACACIA_SIGN = register(new BlockItem(builder(), Blocks.ACACIA_SIGN, Blocks.ACACIA_WALL_SIGN));
public static final Item CHERRY_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.CHERRY_SIGN, Blocks.CHERRY_WALL_SIGN)); public static final Item CHERRY_SIGN = register(new BlockItem(builder(), Blocks.CHERRY_SIGN, Blocks.CHERRY_WALL_SIGN));
public static final Item DARK_OAK_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.DARK_OAK_SIGN, Blocks.DARK_OAK_WALL_SIGN)); public static final Item DARK_OAK_SIGN = register(new BlockItem(builder(), 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 PALE_OAK_SIGN = register(new BlockItem(builder(), Blocks.PALE_OAK_SIGN, Blocks.PALE_OAK_WALL_SIGN));
public static final Item MANGROVE_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.MANGROVE_SIGN, Blocks.MANGROVE_WALL_SIGN)); public static final Item MANGROVE_SIGN = register(new BlockItem(builder(), Blocks.MANGROVE_SIGN, Blocks.MANGROVE_WALL_SIGN));
public static final Item BAMBOO_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.BAMBOO_SIGN, Blocks.BAMBOO_WALL_SIGN)); public static final Item BAMBOO_SIGN = register(new BlockItem(builder(), Blocks.BAMBOO_SIGN, Blocks.BAMBOO_WALL_SIGN));
public static final Item CRIMSON_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.CRIMSON_SIGN, Blocks.CRIMSON_WALL_SIGN)); public static final Item CRIMSON_SIGN = register(new BlockItem(builder(), Blocks.CRIMSON_SIGN, Blocks.CRIMSON_WALL_SIGN));
public static final Item WARPED_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.WARPED_SIGN, Blocks.WARPED_WALL_SIGN)); public static final Item WARPED_SIGN = register(new BlockItem(builder(), Blocks.WARPED_SIGN, Blocks.WARPED_WALL_SIGN));
public static final Item OAK_HANGING_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.OAK_HANGING_SIGN, Blocks.OAK_WALL_HANGING_SIGN)); public static final Item OAK_HANGING_SIGN = register(new BlockItem(builder(), Blocks.OAK_HANGING_SIGN, Blocks.OAK_WALL_HANGING_SIGN));
public static final Item SPRUCE_HANGING_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.SPRUCE_HANGING_SIGN, Blocks.SPRUCE_WALL_HANGING_SIGN)); public static final Item SPRUCE_HANGING_SIGN = register(new BlockItem(builder(), Blocks.SPRUCE_HANGING_SIGN, Blocks.SPRUCE_WALL_HANGING_SIGN));
public static final Item BIRCH_HANGING_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.BIRCH_HANGING_SIGN, Blocks.BIRCH_WALL_HANGING_SIGN)); public static final Item BIRCH_HANGING_SIGN = register(new BlockItem(builder(), Blocks.BIRCH_HANGING_SIGN, Blocks.BIRCH_WALL_HANGING_SIGN));
public static final Item JUNGLE_HANGING_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.JUNGLE_HANGING_SIGN, Blocks.JUNGLE_WALL_HANGING_SIGN)); public static final Item JUNGLE_HANGING_SIGN = register(new BlockItem(builder(), Blocks.JUNGLE_HANGING_SIGN, Blocks.JUNGLE_WALL_HANGING_SIGN));
public static final Item ACACIA_HANGING_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.ACACIA_HANGING_SIGN, Blocks.ACACIA_WALL_HANGING_SIGN)); public static final Item ACACIA_HANGING_SIGN = register(new BlockItem(builder(), Blocks.ACACIA_HANGING_SIGN, Blocks.ACACIA_WALL_HANGING_SIGN));
public static final Item CHERRY_HANGING_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.CHERRY_HANGING_SIGN, Blocks.CHERRY_WALL_HANGING_SIGN)); public static final Item CHERRY_HANGING_SIGN = register(new BlockItem(builder(), Blocks.CHERRY_HANGING_SIGN, Blocks.CHERRY_WALL_HANGING_SIGN));
public static final Item DARK_OAK_HANGING_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.DARK_OAK_HANGING_SIGN, Blocks.DARK_OAK_WALL_HANGING_SIGN)); public static final Item DARK_OAK_HANGING_SIGN = register(new BlockItem(builder(), 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 PALE_OAK_HANGING_SIGN = register(new BlockItem(builder(), Blocks.PALE_OAK_HANGING_SIGN, Blocks.PALE_OAK_WALL_HANGING_SIGN));
public static final Item MANGROVE_HANGING_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.MANGROVE_HANGING_SIGN, Blocks.MANGROVE_WALL_HANGING_SIGN)); public static final Item MANGROVE_HANGING_SIGN = register(new BlockItem(builder(), Blocks.MANGROVE_HANGING_SIGN, Blocks.MANGROVE_WALL_HANGING_SIGN));
public static final Item BAMBOO_HANGING_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.BAMBOO_HANGING_SIGN, Blocks.BAMBOO_WALL_HANGING_SIGN)); public static final Item BAMBOO_HANGING_SIGN = register(new BlockItem(builder(), Blocks.BAMBOO_HANGING_SIGN, Blocks.BAMBOO_WALL_HANGING_SIGN));
public static final Item CRIMSON_HANGING_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.CRIMSON_HANGING_SIGN, Blocks.CRIMSON_WALL_HANGING_SIGN)); public static final Item CRIMSON_HANGING_SIGN = register(new BlockItem(builder(), Blocks.CRIMSON_HANGING_SIGN, Blocks.CRIMSON_WALL_HANGING_SIGN));
public static final Item WARPED_HANGING_SIGN = register(new BlockItem(builder().stackSize(16), Blocks.WARPED_HANGING_SIGN, Blocks.WARPED_WALL_HANGING_SIGN)); public static final Item WARPED_HANGING_SIGN = register(new BlockItem(builder(), Blocks.WARPED_HANGING_SIGN, Blocks.WARPED_WALL_HANGING_SIGN));
public static final Item BUCKET = register(new Item("bucket", builder().stackSize(16))); public static final Item BUCKET = register(new Item("bucket", builder()));
public static final Item WATER_BUCKET = register(new Item("water_bucket", builder().stackSize(1))); public static final Item WATER_BUCKET = register(new Item("water_bucket", builder()));
public static final Item LAVA_BUCKET = register(new Item("lava_bucket", builder().stackSize(1))); public static final Item LAVA_BUCKET = register(new Item("lava_bucket", builder()));
public static final Item POWDER_SNOW_BUCKET = register(new BlockItem("powder_snow_bucket", builder().stackSize(1), Blocks.POWDER_SNOW)); public static final Item POWDER_SNOW_BUCKET = register(new BlockItem("powder_snow_bucket", builder(), Blocks.POWDER_SNOW));
public static final Item SNOWBALL = register(new Item("snowball", builder().stackSize(16))); public static final Item SNOWBALL = register(new Item("snowball", builder()));
public static final Item LEATHER = register(new Item("leather", builder())); public static final Item LEATHER = register(new Item("leather", builder()));
public static final Item MILK_BUCKET = register(new Item("milk_bucket", builder().stackSize(1))); public static final Item MILK_BUCKET = register(new Item("milk_bucket", builder()));
public static final Item PUFFERFISH_BUCKET = register(new Item("pufferfish_bucket", builder().stackSize(1))); public static final Item PUFFERFISH_BUCKET = register(new Item("pufferfish_bucket", builder()));
public static final Item SALMON_BUCKET = register(new Item("salmon_bucket", builder().stackSize(1))); public static final Item SALMON_BUCKET = register(new Item("salmon_bucket", builder()));
public static final Item COD_BUCKET = register(new Item("cod_bucket", builder().stackSize(1))); public static final Item COD_BUCKET = register(new Item("cod_bucket", builder()));
public static final Item TROPICAL_FISH_BUCKET = register(new TropicalFishBucketItem("tropical_fish_bucket", builder().stackSize(1))); public static final Item TROPICAL_FISH_BUCKET = register(new TropicalFishBucketItem("tropical_fish_bucket", builder()));
public static final Item AXOLOTL_BUCKET = register(new AxolotlBucketItem("axolotl_bucket", builder().stackSize(1))); public static final Item AXOLOTL_BUCKET = register(new AxolotlBucketItem("axolotl_bucket", builder()));
public static final Item TADPOLE_BUCKET = register(new Item("tadpole_bucket", builder().stackSize(1))); public static final Item TADPOLE_BUCKET = register(new Item("tadpole_bucket", builder()));
public static final Item BRICK = register(new Item("brick", builder())); public static final Item BRICK = register(new Item("brick", builder()));
public static final Item CLAY_BALL = register(new Item("clay_ball", builder())); public static final Item CLAY_BALL = register(new Item("clay_ball", builder()));
public static final Item DRIED_KELP_BLOCK = register(new BlockItem(builder(), Blocks.DRIED_KELP_BLOCK)); public static final Item DRIED_KELP_BLOCK = register(new BlockItem(builder(), Blocks.DRIED_KELP_BLOCK));
public static final Item PAPER = register(new Item("paper", builder())); public static final Item PAPER = register(new Item("paper", builder()));
public static final Item BOOK = register(new Item("book", builder())); public static final Item BOOK = register(new Item("book", builder()));
public static final Item SLIME_BALL = register(new Item("slime_ball", builder())); public static final Item SLIME_BALL = register(new Item("slime_ball", builder()));
public static final Item EGG = register(new Item("egg", builder().stackSize(16))); public static final Item EGG = register(new Item("egg", builder()));
public static final Item COMPASS = register(new CompassItem("compass", builder())); public static final Item COMPASS = register(new CompassItem("compass", builder()));
public static final Item RECOVERY_COMPASS = register(new Item("recovery_compass", builder())); public static final Item RECOVERY_COMPASS = register(new Item("recovery_compass", builder()));
public static final Item BUNDLE = register(new Item("bundle", builder().stackSize(1))); public static final Item BUNDLE = register(new Item("bundle", builder()));
public static final Item WHITE_BUNDLE = register(new Item("white_bundle", builder().stackSize(1))); public static final Item WHITE_BUNDLE = register(new Item("white_bundle", builder()));
public static final Item ORANGE_BUNDLE = register(new Item("orange_bundle", builder().stackSize(1))); public static final Item ORANGE_BUNDLE = register(new Item("orange_bundle", builder()));
public static final Item MAGENTA_BUNDLE = register(new Item("magenta_bundle", builder().stackSize(1))); public static final Item MAGENTA_BUNDLE = register(new Item("magenta_bundle", builder()));
public static final Item LIGHT_BLUE_BUNDLE = register(new Item("light_blue_bundle", builder().stackSize(1))); public static final Item LIGHT_BLUE_BUNDLE = register(new Item("light_blue_bundle", builder()));
public static final Item YELLOW_BUNDLE = register(new Item("yellow_bundle", builder().stackSize(1))); public static final Item YELLOW_BUNDLE = register(new Item("yellow_bundle", builder()));
public static final Item LIME_BUNDLE = register(new Item("lime_bundle", builder().stackSize(1))); public static final Item LIME_BUNDLE = register(new Item("lime_bundle", builder()));
public static final Item PINK_BUNDLE = register(new Item("pink_bundle", builder().stackSize(1))); public static final Item PINK_BUNDLE = register(new Item("pink_bundle", builder()));
public static final Item GRAY_BUNDLE = register(new Item("gray_bundle", builder().stackSize(1))); public static final Item GRAY_BUNDLE = register(new Item("gray_bundle", builder()));
public static final Item LIGHT_GRAY_BUNDLE = register(new Item("light_gray_bundle", builder().stackSize(1))); public static final Item LIGHT_GRAY_BUNDLE = register(new Item("light_gray_bundle", builder()));
public static final Item CYAN_BUNDLE = register(new Item("cyan_bundle", builder().stackSize(1))); public static final Item CYAN_BUNDLE = register(new Item("cyan_bundle", builder()));
public static final Item PURPLE_BUNDLE = register(new Item("purple_bundle", builder().stackSize(1))); public static final Item PURPLE_BUNDLE = register(new Item("purple_bundle", builder()));
public static final Item BLUE_BUNDLE = register(new Item("blue_bundle", builder().stackSize(1))); public static final Item BLUE_BUNDLE = register(new Item("blue_bundle", builder()));
public static final Item BROWN_BUNDLE = register(new Item("brown_bundle", builder().stackSize(1))); public static final Item BROWN_BUNDLE = register(new Item("brown_bundle", builder()));
public static final Item GREEN_BUNDLE = register(new Item("green_bundle", builder().stackSize(1))); public static final Item GREEN_BUNDLE = register(new Item("green_bundle", builder()));
public static final Item RED_BUNDLE = register(new Item("red_bundle", builder().stackSize(1))); public static final Item RED_BUNDLE = register(new Item("red_bundle", builder()));
public static final Item BLACK_BUNDLE = register(new Item("black_bundle", builder().stackSize(1))); public static final Item BLACK_BUNDLE = register(new Item("black_bundle", builder()));
public static final Item FISHING_ROD = register(new FishingRodItem("fishing_rod", builder().stackSize(1).maxDamage(64))); public static final Item FISHING_ROD = register(new FishingRodItem("fishing_rod", builder()));
public static final Item CLOCK = register(new Item("clock", builder())); public static final Item CLOCK = register(new Item("clock", builder()));
public static final Item SPYGLASS = register(new Item("spyglass", builder().stackSize(1))); public static final Item SPYGLASS = register(new Item("spyglass", builder()));
public static final Item GLOWSTONE_DUST = register(new Item("glowstone_dust", builder())); public static final Item GLOWSTONE_DUST = register(new Item("glowstone_dust", builder()));
public static final Item COD = register(new Item("cod", builder())); public static final Item COD = register(new Item("cod", builder()));
public static final Item SALMON = register(new Item("salmon", builder())); public static final Item SALMON = register(new Item("salmon", builder()));
@ -1073,27 +1078,27 @@ public final class Items {
public static final Item BONE_MEAL = register(new Item("bone_meal", builder())); public static final Item BONE_MEAL = register(new Item("bone_meal", builder()));
public static final Item BONE = register(new Item("bone", builder())); public static final Item BONE = register(new Item("bone", builder()));
public static final Item SUGAR = register(new Item("sugar", builder())); public static final Item SUGAR = register(new Item("sugar", builder()));
public static final Item CAKE = register(new BlockItem(builder().stackSize(1), Blocks.CAKE)); public static final Item CAKE = register(new BlockItem(builder(), Blocks.CAKE));
public static final Item WHITE_BED = register(new BlockItem(builder().stackSize(1), Blocks.WHITE_BED)); public static final Item WHITE_BED = register(new BlockItem(builder(), Blocks.WHITE_BED));
public static final Item ORANGE_BED = register(new BlockItem(builder().stackSize(1), Blocks.ORANGE_BED)); public static final Item ORANGE_BED = register(new BlockItem(builder(), Blocks.ORANGE_BED));
public static final Item MAGENTA_BED = register(new BlockItem(builder().stackSize(1), Blocks.MAGENTA_BED)); public static final Item MAGENTA_BED = register(new BlockItem(builder(), Blocks.MAGENTA_BED));
public static final Item LIGHT_BLUE_BED = register(new BlockItem(builder().stackSize(1), Blocks.LIGHT_BLUE_BED)); public static final Item LIGHT_BLUE_BED = register(new BlockItem(builder(), Blocks.LIGHT_BLUE_BED));
public static final Item YELLOW_BED = register(new BlockItem(builder().stackSize(1), Blocks.YELLOW_BED)); public static final Item YELLOW_BED = register(new BlockItem(builder(), Blocks.YELLOW_BED));
public static final Item LIME_BED = register(new BlockItem(builder().stackSize(1), Blocks.LIME_BED)); public static final Item LIME_BED = register(new BlockItem(builder(), Blocks.LIME_BED));
public static final Item PINK_BED = register(new BlockItem(builder().stackSize(1), Blocks.PINK_BED)); public static final Item PINK_BED = register(new BlockItem(builder(), Blocks.PINK_BED));
public static final Item GRAY_BED = register(new BlockItem(builder().stackSize(1), Blocks.GRAY_BED)); public static final Item GRAY_BED = register(new BlockItem(builder(), Blocks.GRAY_BED));
public static final Item LIGHT_GRAY_BED = register(new BlockItem(builder().stackSize(1), Blocks.LIGHT_GRAY_BED)); public static final Item LIGHT_GRAY_BED = register(new BlockItem(builder(), Blocks.LIGHT_GRAY_BED));
public static final Item CYAN_BED = register(new BlockItem(builder().stackSize(1), Blocks.CYAN_BED)); public static final Item CYAN_BED = register(new BlockItem(builder(), Blocks.CYAN_BED));
public static final Item PURPLE_BED = register(new BlockItem(builder().stackSize(1), Blocks.PURPLE_BED)); public static final Item PURPLE_BED = register(new BlockItem(builder(), Blocks.PURPLE_BED));
public static final Item BLUE_BED = register(new BlockItem(builder().stackSize(1), Blocks.BLUE_BED)); public static final Item BLUE_BED = register(new BlockItem(builder(), Blocks.BLUE_BED));
public static final Item BROWN_BED = register(new BlockItem(builder().stackSize(1), Blocks.BROWN_BED)); public static final Item BROWN_BED = register(new BlockItem(builder(), Blocks.BROWN_BED));
public static final Item GREEN_BED = register(new BlockItem(builder().stackSize(1), Blocks.GREEN_BED)); public static final Item GREEN_BED = register(new BlockItem(builder(), Blocks.GREEN_BED));
public static final Item RED_BED = register(new BlockItem(builder().stackSize(1), Blocks.RED_BED)); public static final Item RED_BED = register(new BlockItem(builder(), Blocks.RED_BED));
public static final Item BLACK_BED = register(new BlockItem(builder().stackSize(1), Blocks.BLACK_BED)); public static final Item BLACK_BED = register(new BlockItem(builder(), Blocks.BLACK_BED));
public static final Item COOKIE = register(new Item("cookie", builder())); public static final Item COOKIE = register(new Item("cookie", builder()));
public static final Item CRAFTER = register(new BlockItem(builder(), Blocks.CRAFTER)); public static final Item CRAFTER = register(new BlockItem(builder(), Blocks.CRAFTER));
public static final Item FILLED_MAP = register(new FilledMapItem("filled_map", builder())); public static final Item FILLED_MAP = register(new FilledMapItem("filled_map", builder()));
public static final Item SHEARS = register(new Item("shears", builder().stackSize(1).maxDamage(238))); public static final Item SHEARS = register(new Item("shears", builder()));
public static final Item MELON_SLICE = register(new Item("melon_slice", builder())); public static final Item MELON_SLICE = register(new Item("melon_slice", builder()));
public static final Item DRIED_KELP = register(new Item("dried_kelp", builder())); public static final Item DRIED_KELP = register(new Item("dried_kelp", builder()));
public static final Item PUMPKIN_SEEDS = register(new BlockItem("pumpkin_seeds", builder(), Blocks.PUMPKIN_STEM)); public static final Item PUMPKIN_SEEDS = register(new BlockItem("pumpkin_seeds", builder(), Blocks.PUMPKIN_STEM));
@ -1103,19 +1108,19 @@ public final class Items {
public static final Item CHICKEN = register(new Item("chicken", builder())); public static final Item CHICKEN = register(new Item("chicken", builder()));
public static final Item COOKED_CHICKEN = register(new Item("cooked_chicken", builder())); public static final Item COOKED_CHICKEN = register(new Item("cooked_chicken", builder()));
public static final Item ROTTEN_FLESH = register(new Item("rotten_flesh", builder())); public static final Item ROTTEN_FLESH = register(new Item("rotten_flesh", builder()));
public static final Item ENDER_PEARL = register(new Item("ender_pearl", builder().stackSize(16))); public static final Item ENDER_PEARL = register(new Item("ender_pearl", builder()));
public static final Item BLAZE_ROD = register(new Item("blaze_rod", builder())); public static final Item BLAZE_ROD = register(new Item("blaze_rod", builder()));
public static final Item GHAST_TEAR = register(new Item("ghast_tear", builder())); public static final Item GHAST_TEAR = register(new Item("ghast_tear", builder()));
public static final Item GOLD_NUGGET = register(new Item("gold_nugget", builder())); public static final Item GOLD_NUGGET = register(new Item("gold_nugget", builder()));
public static final Item NETHER_WART = register(new BlockItem(builder(), Blocks.NETHER_WART)); public static final Item NETHER_WART = register(new BlockItem(builder(), Blocks.NETHER_WART));
public static final Item GLASS_BOTTLE = register(new Item("glass_bottle", builder())); public static final Item GLASS_BOTTLE = register(new Item("glass_bottle", builder()));
public static final Item POTION = register(new PotionItem("potion", builder().stackSize(1))); public static final Item POTION = register(new PotionItem("potion", builder()));
public static final Item SPIDER_EYE = register(new Item("spider_eye", builder())); public static final Item SPIDER_EYE = register(new Item("spider_eye", builder()));
public static final Item FERMENTED_SPIDER_EYE = register(new Item("fermented_spider_eye", builder())); public static final Item FERMENTED_SPIDER_EYE = register(new Item("fermented_spider_eye", builder()));
public static final Item BLAZE_POWDER = register(new Item("blaze_powder", builder())); public static final Item BLAZE_POWDER = register(new Item("blaze_powder", builder()));
public static final Item MAGMA_CREAM = register(new Item("magma_cream", builder())); public static final Item MAGMA_CREAM = register(new Item("magma_cream", builder()));
public static final Item BREWING_STAND = register(new BlockItem(builder(), Blocks.BREWING_STAND)); public static final Item BREWING_STAND = register(new BlockItem(builder(), Blocks.BREWING_STAND));
public static final Item CAULDRON = register(new BlockItem(builder(), Blocks.CAULDRON, Blocks.LAVA_CAULDRON, Blocks.WATER_CAULDRON, Blocks.POWDER_SNOW_CAULDRON)); public static final Item CAULDRON = register(new BlockItem(builder(), Blocks.CAULDRON, Blocks.POWDER_SNOW_CAULDRON, Blocks.LAVA_CAULDRON, Blocks.WATER_CAULDRON));
public static final Item ENDER_EYE = register(new Item("ender_eye", builder())); public static final Item ENDER_EYE = register(new Item("ender_eye", builder()));
public static final Item GLISTERING_MELON_SLICE = register(new Item("glistering_melon_slice", builder())); public static final Item GLISTERING_MELON_SLICE = register(new Item("glistering_melon_slice", builder()));
public static final Item ARMADILLO_SPAWN_EGG = register(new SpawnEggItem("armadillo_spawn_egg", builder())); public static final Item ARMADILLO_SPAWN_EGG = register(new SpawnEggItem("armadillo_spawn_egg", builder()));
@ -1202,10 +1207,10 @@ public final class Items {
public static final Item EXPERIENCE_BOTTLE = register(new Item("experience_bottle", builder())); public static final Item EXPERIENCE_BOTTLE = register(new Item("experience_bottle", builder()));
public static final Item FIRE_CHARGE = register(new Item("fire_charge", builder())); public static final Item FIRE_CHARGE = register(new Item("fire_charge", builder()));
public static final Item WIND_CHARGE = register(new Item("wind_charge", builder())); public static final Item WIND_CHARGE = register(new Item("wind_charge", builder()));
public static final Item WRITABLE_BOOK = register(new WritableBookItem("writable_book", builder().stackSize(1))); public static final Item WRITABLE_BOOK = register(new WritableBookItem("writable_book", builder()));
public static final Item WRITTEN_BOOK = register(new WrittenBookItem("written_book", builder().stackSize(16))); public static final Item WRITTEN_BOOK = register(new WrittenBookItem("written_book", builder()));
public static final Item BREEZE_ROD = register(new Item("breeze_rod", builder())); 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 MACE = register(new Item("mace", builder()));
public static final Item ITEM_FRAME = register(new Item("item_frame", builder())); public static final Item ITEM_FRAME = register(new Item("item_frame", builder()));
public static final Item GLOW_ITEM_FRAME = register(new Item("glow_item_frame", builder())); public static final Item GLOW_ITEM_FRAME = register(new Item("glow_item_frame", builder()));
public static final Item FLOWER_POT = register(new BlockItem(builder(), Blocks.FLOWER_POT)); public static final Item FLOWER_POT = register(new BlockItem(builder(), Blocks.FLOWER_POT));
@ -1226,41 +1231,42 @@ public final class Items {
public static final Item PUMPKIN_PIE = register(new Item("pumpkin_pie", builder())); public static final Item PUMPKIN_PIE = register(new Item("pumpkin_pie", builder()));
public static final Item FIREWORK_ROCKET = register(new FireworkRocketItem("firework_rocket", builder())); public static final Item FIREWORK_ROCKET = register(new FireworkRocketItem("firework_rocket", builder()));
public static final Item FIREWORK_STAR = register(new FireworkStarItem("firework_star", builder())); public static final Item FIREWORK_STAR = register(new FireworkStarItem("firework_star", builder()));
public static final Item ENCHANTED_BOOK = register(new EnchantedBookItem("enchanted_book", builder().stackSize(1))); public static final Item ENCHANTED_BOOK = register(new EnchantedBookItem("enchanted_book", builder()));
public static final Item NETHER_BRICK = register(new Item("nether_brick", builder())); public static final Item NETHER_BRICK = register(new Item("nether_brick", builder()));
public static final Item RESIN_BRICK = register(new Item("resin_brick", builder()));
public static final Item PRISMARINE_SHARD = register(new Item("prismarine_shard", builder())); public static final Item PRISMARINE_SHARD = register(new Item("prismarine_shard", builder()));
public static final Item PRISMARINE_CRYSTALS = register(new Item("prismarine_crystals", builder())); public static final Item PRISMARINE_CRYSTALS = register(new Item("prismarine_crystals", builder()));
public static final Item RABBIT = register(new Item("rabbit", builder())); public static final Item RABBIT = register(new Item("rabbit", builder()));
public static final Item COOKED_RABBIT = register(new Item("cooked_rabbit", builder())); public static final Item COOKED_RABBIT = register(new Item("cooked_rabbit", builder()));
public static final Item RABBIT_STEW = register(new Item("rabbit_stew", builder().stackSize(1))); public static final Item RABBIT_STEW = register(new Item("rabbit_stew", builder()));
public static final Item RABBIT_FOOT = register(new Item("rabbit_foot", builder())); public static final Item RABBIT_FOOT = register(new Item("rabbit_foot", builder()));
public static final Item RABBIT_HIDE = register(new Item("rabbit_hide", builder())); public static final Item RABBIT_HIDE = register(new Item("rabbit_hide", builder()));
public static final Item ARMOR_STAND = register(new Item("armor_stand", builder().stackSize(16))); public static final Item ARMOR_STAND = register(new Item("armor_stand", builder()));
public static final Item IRON_HORSE_ARMOR = register(new Item("iron_horse_armor", builder().stackSize(1))); public static final Item IRON_HORSE_ARMOR = register(new Item("iron_horse_armor", builder()));
public static final Item GOLDEN_HORSE_ARMOR = register(new Item("golden_horse_armor", builder().stackSize(1))); public static final Item GOLDEN_HORSE_ARMOR = register(new Item("golden_horse_armor", builder()));
public static final Item DIAMOND_HORSE_ARMOR = register(new Item("diamond_horse_armor", builder().stackSize(1))); public static final Item DIAMOND_HORSE_ARMOR = register(new Item("diamond_horse_armor", builder()));
public static final Item LEATHER_HORSE_ARMOR = register(new DyeableArmorItem("leather_horse_armor", ArmorMaterial.LEATHER, builder().stackSize(1))); public static final Item LEATHER_HORSE_ARMOR = register(new DyeableArmorItem("leather_horse_armor", builder()));
public static final Item LEAD = register(new Item("lead", builder())); public static final Item LEAD = register(new Item("lead", builder()));
public static final Item NAME_TAG = register(new Item("name_tag", builder())); public static final Item NAME_TAG = register(new Item("name_tag", builder()));
public static final Item COMMAND_BLOCK_MINECART = register(new Item("command_block_minecart", builder().stackSize(1))); public static final Item COMMAND_BLOCK_MINECART = register(new Item("command_block_minecart", builder()));
public static final Item MUTTON = register(new Item("mutton", builder())); public static final Item MUTTON = register(new Item("mutton", builder()));
public static final Item COOKED_MUTTON = register(new Item("cooked_mutton", builder())); public static final Item COOKED_MUTTON = register(new Item("cooked_mutton", builder()));
public static final Item WHITE_BANNER = register(new BannerItem(builder().stackSize(16), Blocks.WHITE_BANNER, Blocks.WHITE_WALL_BANNER)); public static final Item WHITE_BANNER = register(new BannerItem(builder(), Blocks.WHITE_BANNER, Blocks.WHITE_WALL_BANNER));
public static final Item ORANGE_BANNER = register(new BannerItem(builder().stackSize(16), Blocks.ORANGE_BANNER, Blocks.ORANGE_WALL_BANNER)); public static final Item ORANGE_BANNER = register(new BannerItem(builder(), Blocks.ORANGE_BANNER, Blocks.ORANGE_WALL_BANNER));
public static final Item MAGENTA_BANNER = register(new BannerItem(builder().stackSize(16), Blocks.MAGENTA_BANNER, Blocks.MAGENTA_WALL_BANNER)); public static final Item MAGENTA_BANNER = register(new BannerItem(builder(), Blocks.MAGENTA_BANNER, Blocks.MAGENTA_WALL_BANNER));
public static final Item LIGHT_BLUE_BANNER = register(new BannerItem(builder().stackSize(16), Blocks.LIGHT_BLUE_BANNER, Blocks.LIGHT_BLUE_WALL_BANNER)); public static final Item LIGHT_BLUE_BANNER = register(new BannerItem(builder(), Blocks.LIGHT_BLUE_BANNER, Blocks.LIGHT_BLUE_WALL_BANNER));
public static final Item YELLOW_BANNER = register(new BannerItem(builder().stackSize(16), Blocks.YELLOW_BANNER, Blocks.YELLOW_WALL_BANNER)); public static final Item YELLOW_BANNER = register(new BannerItem(builder(), Blocks.YELLOW_BANNER, Blocks.YELLOW_WALL_BANNER));
public static final Item LIME_BANNER = register(new BannerItem(builder().stackSize(16), Blocks.LIME_BANNER, Blocks.LIME_WALL_BANNER)); public static final Item LIME_BANNER = register(new BannerItem(builder(), Blocks.LIME_BANNER, Blocks.LIME_WALL_BANNER));
public static final Item PINK_BANNER = register(new BannerItem(builder().stackSize(16), Blocks.PINK_BANNER, Blocks.PINK_WALL_BANNER)); public static final Item PINK_BANNER = register(new BannerItem(builder(), Blocks.PINK_BANNER, Blocks.PINK_WALL_BANNER));
public static final Item GRAY_BANNER = register(new BannerItem(builder().stackSize(16), Blocks.GRAY_BANNER, Blocks.GRAY_WALL_BANNER)); public static final Item GRAY_BANNER = register(new BannerItem(builder(), Blocks.GRAY_BANNER, Blocks.GRAY_WALL_BANNER));
public static final Item LIGHT_GRAY_BANNER = register(new BannerItem(builder().stackSize(16), Blocks.LIGHT_GRAY_BANNER, Blocks.LIGHT_GRAY_WALL_BANNER)); public static final Item LIGHT_GRAY_BANNER = register(new BannerItem(builder(), Blocks.LIGHT_GRAY_BANNER, Blocks.LIGHT_GRAY_WALL_BANNER));
public static final Item CYAN_BANNER = register(new BannerItem(builder().stackSize(16), Blocks.CYAN_BANNER, Blocks.CYAN_WALL_BANNER)); public static final Item CYAN_BANNER = register(new BannerItem(builder(), Blocks.CYAN_BANNER, Blocks.CYAN_WALL_BANNER));
public static final Item PURPLE_BANNER = register(new BannerItem(builder().stackSize(16), Blocks.PURPLE_BANNER, Blocks.PURPLE_WALL_BANNER)); public static final Item PURPLE_BANNER = register(new BannerItem(builder(), Blocks.PURPLE_BANNER, Blocks.PURPLE_WALL_BANNER));
public static final Item BLUE_BANNER = register(new BannerItem(builder().stackSize(16), Blocks.BLUE_BANNER, Blocks.BLUE_WALL_BANNER)); public static final Item BLUE_BANNER = register(new BannerItem(builder(), Blocks.BLUE_BANNER, Blocks.BLUE_WALL_BANNER));
public static final Item BROWN_BANNER = register(new BannerItem(builder().stackSize(16), Blocks.BROWN_BANNER, Blocks.BROWN_WALL_BANNER)); public static final Item BROWN_BANNER = register(new BannerItem(builder(), Blocks.BROWN_BANNER, Blocks.BROWN_WALL_BANNER));
public static final Item GREEN_BANNER = register(new BannerItem(builder().stackSize(16), Blocks.GREEN_BANNER, Blocks.GREEN_WALL_BANNER)); public static final Item GREEN_BANNER = register(new BannerItem(builder(), Blocks.GREEN_BANNER, Blocks.GREEN_WALL_BANNER));
public static final Item RED_BANNER = register(new BannerItem(builder().stackSize(16), Blocks.RED_BANNER, Blocks.RED_WALL_BANNER)); public static final Item RED_BANNER = register(new BannerItem(builder(), Blocks.RED_BANNER, Blocks.RED_WALL_BANNER));
public static final Item BLACK_BANNER = register(new BannerItem(builder().stackSize(16), Blocks.BLACK_BANNER, Blocks.BLACK_WALL_BANNER)); public static final Item BLACK_BANNER = register(new BannerItem(builder(), Blocks.BLACK_BANNER, Blocks.BLACK_WALL_BANNER));
public static final Item END_CRYSTAL = register(new Item("end_crystal", builder())); public static final Item END_CRYSTAL = register(new Item("end_crystal", builder()));
public static final Item CHORUS_FRUIT = register(new Item("chorus_fruit", builder())); public static final Item CHORUS_FRUIT = register(new Item("chorus_fruit", builder()));
public static final Item POPPED_CHORUS_FRUIT = register(new Item("popped_chorus_fruit", builder())); public static final Item POPPED_CHORUS_FRUIT = register(new Item("popped_chorus_fruit", builder()));
@ -1268,55 +1274,55 @@ public final class Items {
public static final Item PITCHER_POD = register(new BlockItem("pitcher_pod", builder(), Blocks.PITCHER_CROP)); public static final Item PITCHER_POD = register(new BlockItem("pitcher_pod", builder(), Blocks.PITCHER_CROP));
public static final Item BEETROOT = register(new Item("beetroot", builder())); public static final Item BEETROOT = register(new Item("beetroot", builder()));
public static final Item BEETROOT_SEEDS = register(new BlockItem("beetroot_seeds", builder(), Blocks.BEETROOTS)); public static final Item BEETROOT_SEEDS = register(new BlockItem("beetroot_seeds", builder(), Blocks.BEETROOTS));
public static final Item BEETROOT_SOUP = register(new Item("beetroot_soup", builder().stackSize(1))); public static final Item BEETROOT_SOUP = register(new Item("beetroot_soup", builder()));
public static final Item DRAGON_BREATH = register(new Item("dragon_breath", builder())); public static final Item DRAGON_BREATH = register(new Item("dragon_breath", builder()));
public static final Item SPLASH_POTION = register(new PotionItem("splash_potion", builder().stackSize(1))); public static final Item SPLASH_POTION = register(new PotionItem("splash_potion", builder()));
public static final Item SPECTRAL_ARROW = register(new Item("spectral_arrow", builder())); public static final Item SPECTRAL_ARROW = register(new Item("spectral_arrow", builder()));
public static final Item TIPPED_ARROW = register(new TippedArrowItem("tipped_arrow", builder())); public static final Item TIPPED_ARROW = register(new TippedArrowItem("tipped_arrow", builder()));
public static final Item LINGERING_POTION = register(new PotionItem("lingering_potion", builder().stackSize(1))); public static final Item LINGERING_POTION = register(new PotionItem("lingering_potion", builder()));
public static final Item SHIELD = register(new ShieldItem("shield", builder().stackSize(1).maxDamage(336))); public static final Item SHIELD = register(new ShieldItem("shield", builder()));
public static final Item TOTEM_OF_UNDYING = register(new Item("totem_of_undying", builder().stackSize(1))); public static final Item TOTEM_OF_UNDYING = register(new Item("totem_of_undying", builder()));
public static final Item SHULKER_SHELL = register(new Item("shulker_shell", builder())); public static final Item SHULKER_SHELL = register(new Item("shulker_shell", builder()));
public static final Item IRON_NUGGET = register(new Item("iron_nugget", builder())); public static final Item IRON_NUGGET = register(new Item("iron_nugget", builder()));
public static final Item KNOWLEDGE_BOOK = register(new Item("knowledge_book", builder().stackSize(1))); public static final Item KNOWLEDGE_BOOK = register(new Item("knowledge_book", builder()));
public static final Item DEBUG_STICK = register(new Item("debug_stick", builder().stackSize(1))); public static final Item DEBUG_STICK = register(new Item("debug_stick", builder()));
public static final Item MUSIC_DISC_13 = register(new Item("music_disc_13", builder().stackSize(1))); public static final Item MUSIC_DISC_13 = register(new Item("music_disc_13", builder()));
public static final Item MUSIC_DISC_CAT = register(new Item("music_disc_cat", builder().stackSize(1))); public static final Item MUSIC_DISC_CAT = register(new Item("music_disc_cat", builder()));
public static final Item MUSIC_DISC_BLOCKS = register(new Item("music_disc_blocks", builder().stackSize(1))); public static final Item MUSIC_DISC_BLOCKS = register(new Item("music_disc_blocks", builder()));
public static final Item MUSIC_DISC_CHIRP = register(new Item("music_disc_chirp", builder().stackSize(1))); public static final Item MUSIC_DISC_CHIRP = register(new Item("music_disc_chirp", builder()));
public static final Item MUSIC_DISC_CREATOR = register(new Item("music_disc_creator", builder().stackSize(1))); public static final Item MUSIC_DISC_CREATOR = register(new Item("music_disc_creator", builder()));
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_CREATOR_MUSIC_BOX = register(new Item("music_disc_creator_music_box", builder()));
public static final Item MUSIC_DISC_FAR = register(new Item("music_disc_far", builder().stackSize(1))); public static final Item MUSIC_DISC_FAR = register(new Item("music_disc_far", builder()));
public static final Item MUSIC_DISC_MALL = register(new Item("music_disc_mall", builder().stackSize(1))); public static final Item MUSIC_DISC_MALL = register(new Item("music_disc_mall", builder()));
public static final Item MUSIC_DISC_MELLOHI = register(new Item("music_disc_mellohi", builder().stackSize(1))); public static final Item MUSIC_DISC_MELLOHI = register(new Item("music_disc_mellohi", builder()));
public static final Item MUSIC_DISC_STAL = register(new Item("music_disc_stal", builder().stackSize(1))); public static final Item MUSIC_DISC_STAL = register(new Item("music_disc_stal", builder()));
public static final Item MUSIC_DISC_STRAD = register(new Item("music_disc_strad", builder().stackSize(1))); public static final Item MUSIC_DISC_STRAD = register(new Item("music_disc_strad", builder()));
public static final Item MUSIC_DISC_WARD = register(new Item("music_disc_ward", builder().stackSize(1))); public static final Item MUSIC_DISC_WARD = register(new Item("music_disc_ward", builder()));
public static final Item MUSIC_DISC_11 = register(new Item("music_disc_11", builder().stackSize(1))); public static final Item MUSIC_DISC_11 = register(new Item("music_disc_11", builder()));
public static final Item MUSIC_DISC_WAIT = register(new Item("music_disc_wait", builder().stackSize(1))); public static final Item MUSIC_DISC_WAIT = register(new Item("music_disc_wait", builder()));
public static final Item MUSIC_DISC_OTHERSIDE = register(new Item("music_disc_otherside", builder().stackSize(1))); public static final Item MUSIC_DISC_OTHERSIDE = register(new Item("music_disc_otherside", builder()));
public static final Item MUSIC_DISC_RELIC = register(new Item("music_disc_relic", builder().stackSize(1))); public static final Item MUSIC_DISC_RELIC = register(new Item("music_disc_relic", builder()));
public static final Item MUSIC_DISC_5 = register(new Item("music_disc_5", builder().stackSize(1))); public static final Item MUSIC_DISC_5 = register(new Item("music_disc_5", builder()));
public static final Item MUSIC_DISC_PIGSTEP = register(new Item("music_disc_pigstep", builder().stackSize(1))); public static final Item MUSIC_DISC_PIGSTEP = register(new Item("music_disc_pigstep", builder()));
public static final Item MUSIC_DISC_PRECIPICE = register(new Item("music_disc_precipice", builder().stackSize(1))); public static final Item MUSIC_DISC_PRECIPICE = register(new Item("music_disc_precipice", builder()));
public static final Item DISC_FRAGMENT_5 = register(new Item("disc_fragment_5", builder())); public static final Item DISC_FRAGMENT_5 = register(new Item("disc_fragment_5", builder()));
public static final Item TRIDENT = register(new Item("trident", builder().stackSize(1).maxDamage(250).attackDamage(9.0))); public static final Item TRIDENT = register(new Item("trident", builder().attackDamage(9.0)));
public static final Item NAUTILUS_SHELL = register(new Item("nautilus_shell", builder())); public static final Item NAUTILUS_SHELL = register(new Item("nautilus_shell", builder()));
public static final Item HEART_OF_THE_SEA = register(new Item("heart_of_the_sea", builder())); public static final Item HEART_OF_THE_SEA = register(new Item("heart_of_the_sea", builder()));
public static final Item CROSSBOW = register(new CrossbowItem("crossbow", builder().stackSize(1).maxDamage(465))); public static final Item CROSSBOW = register(new CrossbowItem("crossbow", builder()));
public static final Item SUSPICIOUS_STEW = register(new Item("suspicious_stew", builder().stackSize(1))); public static final Item SUSPICIOUS_STEW = register(new Item("suspicious_stew", builder()));
public static final Item LOOM = register(new BlockItem(builder(), Blocks.LOOM)); public static final Item LOOM = register(new BlockItem(builder(), Blocks.LOOM));
public static final Item FLOWER_BANNER_PATTERN = register(new Item("flower_banner_pattern", builder().stackSize(1))); public static final Item FLOWER_BANNER_PATTERN = register(new Item("flower_banner_pattern", builder()));
public static final Item CREEPER_BANNER_PATTERN = register(new Item("creeper_banner_pattern", builder().stackSize(1))); public static final Item CREEPER_BANNER_PATTERN = register(new Item("creeper_banner_pattern", builder()));
public static final Item SKULL_BANNER_PATTERN = register(new Item("skull_banner_pattern", builder().stackSize(1))); public static final Item SKULL_BANNER_PATTERN = register(new Item("skull_banner_pattern", builder()));
public static final Item MOJANG_BANNER_PATTERN = register(new Item("mojang_banner_pattern", builder().stackSize(1))); public static final Item MOJANG_BANNER_PATTERN = register(new Item("mojang_banner_pattern", builder()));
public static final Item GLOBE_BANNER_PATTERN = register(new Item("globe_banner_pattern", builder().stackSize(1))); public static final Item GLOBE_BANNER_PATTERN = register(new Item("globe_banner_pattern", builder()));
public static final Item PIGLIN_BANNER_PATTERN = register(new Item("piglin_banner_pattern", builder().stackSize(1))); public static final Item PIGLIN_BANNER_PATTERN = register(new Item("piglin_banner_pattern", builder()));
public static final Item FLOW_BANNER_PATTERN = register(new Item("flow_banner_pattern", builder().stackSize(1))); public static final Item FLOW_BANNER_PATTERN = register(new Item("flow_banner_pattern", builder()));
public static final Item GUSTER_BANNER_PATTERN = register(new Item("guster_banner_pattern", builder().stackSize(1))); public static final Item GUSTER_BANNER_PATTERN = register(new Item("guster_banner_pattern", builder()));
public static final Item FIELD_MASONED_BANNER_PATTERN = register(new Item("field_masoned_banner_pattern", builder().stackSize(1))); public static final Item FIELD_MASONED_BANNER_PATTERN = register(new Item("field_masoned_banner_pattern", builder()));
public static final Item BORDURE_INDENTED_BANNER_PATTERN = register(new Item("bordure_indented_banner_pattern", builder().stackSize(1))); public static final Item BORDURE_INDENTED_BANNER_PATTERN = register(new Item("bordure_indented_banner_pattern", builder()));
public static final Item GOAT_HORN = register(new GoatHornItem("goat_horn", builder().stackSize(1))); public static final Item GOAT_HORN = register(new GoatHornItem("goat_horn", builder()));
public static final Item COMPOSTER = register(new BlockItem(builder(), Blocks.COMPOSTER)); public static final Item COMPOSTER = register(new BlockItem(builder(), Blocks.COMPOSTER));
public static final Item BARREL = register(new BlockItem(builder(), Blocks.BARREL)); public static final Item BARREL = register(new BlockItem(builder(), Blocks.BARREL));
public static final Item SMOKER = register(new BlockItem(builder(), Blocks.SMOKER)); public static final Item SMOKER = register(new BlockItem(builder(), Blocks.SMOKER));
@ -1337,7 +1343,7 @@ public final class Items {
public static final Item HONEYCOMB = register(new Item("honeycomb", builder())); public static final Item HONEYCOMB = register(new Item("honeycomb", builder()));
public static final Item BEE_NEST = register(new BlockItem(builder(), Blocks.BEE_NEST)); public static final Item BEE_NEST = register(new BlockItem(builder(), Blocks.BEE_NEST));
public static final Item BEEHIVE = register(new BlockItem(builder(), Blocks.BEEHIVE)); public static final Item BEEHIVE = register(new BlockItem(builder(), Blocks.BEEHIVE));
public static final Item HONEY_BOTTLE = register(new Item("honey_bottle", builder().stackSize(16))); public static final Item HONEY_BOTTLE = register(new Item("honey_bottle", builder()));
public static final Item HONEYCOMB_BLOCK = register(new BlockItem(builder(), Blocks.HONEYCOMB_BLOCK)); public static final Item HONEYCOMB_BLOCK = register(new BlockItem(builder(), Blocks.HONEYCOMB_BLOCK));
public static final Item LODESTONE = register(new BlockItem(builder(), Blocks.LODESTONE)); public static final Item LODESTONE = register(new BlockItem(builder(), Blocks.LODESTONE));
public static final Item CRYING_OBSIDIAN = register(new BlockItem(builder(), Blocks.CRYING_OBSIDIAN)); public static final Item CRYING_OBSIDIAN = register(new BlockItem(builder(), Blocks.CRYING_OBSIDIAN));
@ -1381,7 +1387,7 @@ public final class Items {
public static final Item PEARLESCENT_FROGLIGHT = register(new BlockItem(builder(), Blocks.PEARLESCENT_FROGLIGHT)); public static final Item PEARLESCENT_FROGLIGHT = register(new BlockItem(builder(), Blocks.PEARLESCENT_FROGLIGHT));
public static final Item FROGSPAWN = register(new BlockItem(builder(), Blocks.FROGSPAWN)); public static final Item FROGSPAWN = register(new BlockItem(builder(), Blocks.FROGSPAWN));
public static final Item ECHO_SHARD = register(new Item("echo_shard", builder())); public static final Item ECHO_SHARD = register(new Item("echo_shard", builder()));
public static final Item BRUSH = register(new Item("brush", builder().stackSize(1).maxDamage(64))); public static final Item BRUSH = register(new Item("brush", builder()));
public static final Item NETHERITE_UPGRADE_SMITHING_TEMPLATE = register(new Item("netherite_upgrade_smithing_template", builder())); public static final Item NETHERITE_UPGRADE_SMITHING_TEMPLATE = register(new Item("netherite_upgrade_smithing_template", builder()));
public static final Item SENTRY_ARMOR_TRIM_SMITHING_TEMPLATE = register(new Item("sentry_armor_trim_smithing_template", builder())); public static final Item SENTRY_ARMOR_TRIM_SMITHING_TEMPLATE = register(new Item("sentry_armor_trim_smithing_template", builder()));
public static final Item DUNE_ARMOR_TRIM_SMITHING_TEMPLATE = register(new Item("dune_armor_trim_smithing_template", builder())); public static final Item DUNE_ARMOR_TRIM_SMITHING_TEMPLATE = register(new Item("dune_armor_trim_smithing_template", builder()));

View file

@ -1,64 +0,0 @@
/*
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author GeyserMC
* @link https://github.com/GeyserMC/Geyser
*/
package org.geysermc.geyser.item.components;
import com.google.common.base.Suppliers;
import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.item.type.Item;
import java.util.Collections;
import java.util.Locale;
import java.util.Set;
import java.util.function.Supplier;
public enum ToolTier {
WOODEN(2, () -> Set.of(Items.OAK_PLANKS, Items.SPRUCE_PLANKS, Items.BIRCH_PLANKS, Items.JUNGLE_PLANKS, Items.ACACIA_PLANKS, Items.DARK_OAK_PLANKS, Items.CRIMSON_PLANKS, Items.WARPED_PLANKS, Items.MANGROVE_PLANKS)), // PLANKS tag // TODO ?
STONE(4, () -> Set.of(Items.COBBLESTONE, Items.BLACKSTONE, Items.COBBLED_DEEPSLATE)), // STONE_TOOL_MATERIALS tag
IRON(6, () -> Collections.singleton(Items.IRON_INGOT)),
GOLDEN(12, () -> Collections.singleton(Items.GOLD_INGOT)),
DIAMOND(8, () -> Collections.singleton(Items.DIAMOND)),
NETHERITE(9, () -> Collections.singleton(Items.NETHERITE_INGOT));
private static final ToolTier[] VALUES = values();
private final int speed;
private final Supplier<Set<Item>> repairIngredients;
ToolTier(int speed, Supplier<Set<Item>> repairIngredients) {
this.speed = speed;
// Lazily initialize as this will likely be called as items are loading
this.repairIngredients = Suppliers.memoize(repairIngredients::get);
}
public Set<Item> getRepairIngredients() {
return repairIngredients.get();
}
@Override
public String toString() {
return this.name().toLowerCase(Locale.ROOT);
}
}

View file

@ -30,7 +30,6 @@ import org.cloudburstmc.nbt.NbtMap;
import org.cloudburstmc.nbt.NbtMapBuilder; import org.cloudburstmc.nbt.NbtMapBuilder;
import org.cloudburstmc.protocol.bedrock.data.TrimMaterial; import org.cloudburstmc.protocol.bedrock.data.TrimMaterial;
import org.cloudburstmc.protocol.bedrock.data.TrimPattern; import org.cloudburstmc.protocol.bedrock.data.TrimPattern;
import org.geysermc.geyser.item.ArmorMaterial;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.item.BedrockItemBuilder; import org.geysermc.geyser.translator.item.BedrockItemBuilder;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.ArmorTrim; import org.geysermc.mcprotocollib.protocol.data.game.item.component.ArmorTrim;
@ -38,11 +37,9 @@ import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponen
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents; import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents;
public class ArmorItem extends Item { public class ArmorItem extends Item {
private final ArmorMaterial material;
public ArmorItem(String javaIdentifier, ArmorMaterial material, Builder builder) { public ArmorItem(String javaIdentifier, Builder builder) {
super(javaIdentifier, builder); super(javaIdentifier, builder);
this.material = material;
} }
@Override @Override
@ -68,11 +65,6 @@ public class ArmorItem extends Item {
} }
} }
@Override
public boolean isValidRepairItem(Item other) {
return material.getRepairIngredient() == other;
}
// TODO maybe some kind of namespace util? // TODO maybe some kind of namespace util?
private static String getNamespace(String identifier) { private static String getNamespace(String identifier) {
int i = identifier.indexOf(':'); int i = identifier.indexOf(':');

View file

@ -25,12 +25,6 @@
package org.geysermc.geyser.item.type; package org.geysermc.geyser.item.type;
import org.checkerframework.checker.nullness.qual.Nullable; // Whether this item should have its NBT data kept in the recipe book.
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.item.BedrockItemBuilder;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents;
public interface BedrockRequiresTagItem { public interface BedrockRequiresTagItem {
void addRequiredNbt(GeyserSession session, @Nullable DataComponents components, BedrockItemBuilder builder);
} }

View file

@ -26,14 +26,13 @@
package org.geysermc.geyser.item.type; package org.geysermc.geyser.item.type;
import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.NonNull;
import org.geysermc.geyser.item.ArmorMaterial;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.item.BedrockItemBuilder; import org.geysermc.geyser.translator.item.BedrockItemBuilder;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents; import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents;
public class DyeableArmorItem extends ArmorItem { public class DyeableArmorItem extends ArmorItem {
public DyeableArmorItem(String javaIdentifier, ArmorMaterial material, Builder builder) { public DyeableArmorItem(String javaIdentifier, Builder builder) {
super(javaIdentifier, material, builder); super(javaIdentifier, builder);
} }
@Override @Override

View file

@ -1,39 +0,0 @@
/*
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author GeyserMC
* @link https://github.com/GeyserMC/Geyser
*/
package org.geysermc.geyser.item.type;
import org.geysermc.geyser.item.Items;
public class ElytraItem extends Item {
public ElytraItem(String javaIdentifier, Builder builder) {
super(javaIdentifier, builder);
}
@Override
public boolean isValidRepairItem(Item other) {
return other == Items.PHANTOM_MEMBRANE;
}
}

View file

@ -27,7 +27,6 @@ package org.geysermc.geyser.item.type;
import it.unimi.dsi.fastutil.ints.IntArrays; import it.unimi.dsi.fastutil.ints.IntArrays;
import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.cloudburstmc.nbt.NbtList; import org.cloudburstmc.nbt.NbtList;
import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMap;
import org.cloudburstmc.nbt.NbtMapBuilder; import org.cloudburstmc.nbt.NbtMapBuilder;
@ -142,20 +141,4 @@ public class FireworkRocketItem extends Item implements BedrockRequiresTagItem {
return null; return null;
} }
} }
@Override
public void addRequiredNbt(GeyserSession session, @Nullable DataComponents components, BedrockItemBuilder builder) {
if (components != null) {
Fireworks fireworks = components.get(DataComponentType.FIREWORKS);
if (fireworks != null) {
// Already translated
return;
}
}
NbtMapBuilder fireworksNbt = NbtMap.builder();
fireworksNbt.putByte("Flight", (byte) 1);
fireworksNbt.put("Explosions", NbtList.EMPTY);
builder.putCompound("Fireworks", fireworksNbt.build());
}
} }

View file

@ -25,6 +25,7 @@
package org.geysermc.geyser.item.type; package org.geysermc.geyser.item.type;
import com.google.common.collect.ImmutableMap;
import net.kyori.adventure.key.Key; import net.kyori.adventure.key.Key;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.NonNull;
@ -39,19 +40,20 @@ import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.item.components.Rarity; import org.geysermc.geyser.item.components.Rarity;
import org.geysermc.geyser.item.enchantment.Enchantment; import org.geysermc.geyser.item.enchantment.Enchantment;
import org.geysermc.geyser.level.block.type.Block; import org.geysermc.geyser.level.block.type.Block;
import org.geysermc.geyser.registry.Registries;
import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.registry.type.ItemMappings; import org.geysermc.geyser.registry.type.ItemMappings;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.text.ChatColor; import org.geysermc.geyser.text.ChatColor;
import org.geysermc.geyser.text.MinecraftLocale; import org.geysermc.geyser.text.MinecraftLocale;
import org.geysermc.geyser.translator.item.BedrockItemBuilder; import org.geysermc.geyser.translator.item.BedrockItemBuilder;
import org.geysermc.geyser.translator.item.ItemTranslator;
import org.geysermc.geyser.translator.text.MessageTranslator; import org.geysermc.geyser.translator.text.MessageTranslator;
import org.geysermc.geyser.util.MinecraftKey; import org.geysermc.geyser.util.MinecraftKey;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType; import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents; import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DyedItemColor; import org.geysermc.mcprotocollib.protocol.data.game.item.component.DyedItemColor;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.ItemEnchantments; import org.geysermc.mcprotocollib.protocol.data.game.item.component.ItemEnchantments;
import org.jetbrains.annotations.UnmodifiableView;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
@ -62,19 +64,15 @@ public class Item {
private static final Map<Block, Item> BLOCK_TO_ITEM = new HashMap<>(); private static final Map<Block, Item> BLOCK_TO_ITEM = new HashMap<>();
protected final Key javaIdentifier; protected final Key javaIdentifier;
private int javaId = -1; private int javaId = -1;
private final int stackSize;
private final int attackDamage; private final int attackDamage;
private final int maxDamage; private DataComponents baseComponents; // unmodifiable
private final Rarity rarity;
private final boolean glint;
public Item(String javaIdentifier, Builder builder) { public Item(String javaIdentifier, Builder builder) {
this.javaIdentifier = MinecraftKey.key(javaIdentifier); this.javaIdentifier = MinecraftKey.key(javaIdentifier);
this.stackSize = builder.stackSize; if (builder.components != null) {
this.maxDamage = builder.maxDamage; this.baseComponents = builder.components;
}
this.attackDamage = builder.attackDamage; this.attackDamage = builder.attackDamage;
this.rarity = builder.rarity;
this.glint = builder.glint;
} }
public String javaIdentifier() { public String javaIdentifier() {
@ -85,28 +83,53 @@ public class Item {
return javaId; return javaId;
} }
public int maxDamage() { public int defaultMaxDamage() {
return maxDamage; return baseComponents.getOrDefault(DataComponentType.MAX_DAMAGE, 0);
} }
public int attackDamage() { public int defaultAttackDamage() {
return attackDamage; return attackDamage;
} }
public int maxStackSize() { public int defaultMaxStackSize() {
return stackSize; return baseComponents.getOrDefault(DataComponentType.MAX_STACK_SIZE, 1);
} }
public Rarity rarity() { public Rarity defaultRarity() {
return rarity; return Rarity.fromId(baseComponents.getOrDefault(DataComponentType.RARITY, 0));
} }
public boolean glint() { /**
return glint; * Returns an unmodifiable {@link DataComponents} view containing known data components.
* Optionally, additional components can be provided to replace (or add to)
* the items' base components.
* To add data components, use {@link GeyserItemStack#getOrCreateComponents()}.
*/
@NonNull
@UnmodifiableView
public DataComponents gatherComponents(@Nullable DataComponents others) {
if (others == null) {
return baseComponents;
}
// Start with the base components that always exist
DataComponents components = baseComponents.clone();
// Add all additional components; these can override base components!
// e.g. custom stack size
components.getDataComponents().putAll(others.getDataComponents());
// Return an unmodified map of the merged components
return new DataComponents(ImmutableMap.copyOf(components.getDataComponents()));
} }
public boolean isValidRepairItem(Item other) { /**
return false; * Returns this items value (or null) for a specific {@link DataComponentType}.
* Prefer using {@link GeyserItemStack#getComponent(DataComponentType)}
* to also query additional components that would override the default ones.
*/
@Nullable
public <T> T getComponent(@NonNull DataComponentType<T> type) {
return baseComponents.get(type);
} }
public String translationKey() { public String translationKey() {
@ -120,14 +143,11 @@ public class Item {
// Return, essentially, air // Return, essentially, air
return ItemData.builder(); return ItemData.builder();
} }
ItemData.Builder builder = ItemData.builder()
return ItemData.builder()
.definition(mapping.getBedrockDefinition()) .definition(mapping.getBedrockDefinition())
.damage(mapping.getBedrockData()) .damage(mapping.getBedrockData())
.count(count); .count(count);
ItemTranslator.translateCustomItem(components, builder, mapping);
return builder;
} }
public @NonNull GeyserItemStack translateToJava(GeyserSession session, @NonNull ItemData itemData, @NonNull ItemMapping mapping, @NonNull ItemMappings mappings) { public @NonNull GeyserItemStack translateToJava(GeyserSession session, @NonNull ItemData itemData, @NonNull ItemMapping mapping, @NonNull ItemMappings mappings) {
@ -268,6 +288,9 @@ public class Item {
throw new RuntimeException("Item ID has already been set!"); throw new RuntimeException("Item ID has already been set!");
} }
this.javaId = javaId; this.javaId = javaId;
if (this.baseComponents == null) {
this.baseComponents = Registries.DEFAULT_DATA_COMPONENTS.get(javaId);
}
} }
@Override @Override
@ -295,35 +318,17 @@ public class Item {
} }
public static final class Builder { public static final class Builder {
private int stackSize = 64; private DataComponents components;
private int maxDamage;
private int attackDamage; private int attackDamage;
private Rarity rarity = Rarity.COMMON;
private boolean glint = false;
public Builder stackSize(int stackSize) {
this.stackSize = stackSize;
return this;
}
public Builder attackDamage(double attackDamage) { public Builder attackDamage(double attackDamage) {
// TODO properly store/send a double value once Bedrock supports it.. pls // Bedrock edition does not support attack damage being a double
this.attackDamage = (int) attackDamage; this.attackDamage = (int) attackDamage;
return this; return this;
} }
public Builder maxDamage(int maxDamage) { public Builder components(DataComponents components) {
this.maxDamage = maxDamage; this.components = components;
return this;
}
public Builder rarity(Rarity rarity) {
this.rarity = rarity;
return this;
}
public Builder glint(boolean glintOverride) {
this.glint = glintOverride;
return this; return this;
} }

View file

@ -60,7 +60,6 @@ public class LightItem extends BlockItem {
return super.toBedrockDefinition(components, mappings); return super.toBedrockDefinition(components, mappings);
} }
private static ItemMapping getLightLevelMapping(DataComponents components, ItemMappings mappings) { private static ItemMapping getLightLevelMapping(DataComponents components, ItemMappings mappings) {
String lightLevel = "15"; String lightLevel = "15";
if (components != null) { if (components != null) {

View file

@ -1,39 +0,0 @@
/*
* Copyright (c) 2019-2024 GeyserMC. http://geysermc.org
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author GeyserMC
* @link https://github.com/GeyserMC/Geyser
*/
package org.geysermc.geyser.item.type;
import org.geysermc.geyser.item.Items;
public class MaceItem extends Item {
public MaceItem(String javaIdentifier, Builder builder) {
super(javaIdentifier, builder);
}
@Override
public boolean isValidRepairItem(Item other) {
return other == Items.BREEZE_ROD;
}
}

View file

@ -26,7 +26,6 @@
package org.geysermc.geyser.item.type; package org.geysermc.geyser.item.type;
import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.NonNull;
import org.geysermc.geyser.item.components.ToolTier;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.item.BedrockItemBuilder; import org.geysermc.geyser.translator.item.BedrockItemBuilder;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.BannerPatternLayer; import org.geysermc.mcprotocollib.protocol.data.game.item.component.BannerPatternLayer;
@ -54,10 +53,4 @@ public class ShieldItem extends Item {
builder.putInt("Base", 15 - baseColor); builder.putInt("Base", 15 - baseColor);
} }
} }
@Override
public boolean isValidRepairItem(Item other) {
// Java Edition 1.19.3 checks the tag, but TODO check to see if we want it or are simulating what Bedrock is doing
return ToolTier.WOODEN.getRepairIngredients().contains(other);
}
} }

View file

@ -1,46 +0,0 @@
/*
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author GeyserMC
* @link https://github.com/GeyserMC/Geyser
*/
package org.geysermc.geyser.item.type;
import org.geysermc.geyser.item.components.ToolTier;
public class TieredItem extends Item {
private final ToolTier tier;
public TieredItem(String javaIdentifier, ToolTier tier, Builder builder) {
super(javaIdentifier, builder);
this.tier = tier;
}
public ToolTier tier() {
return tier;
}
@Override
public boolean isValidRepairItem(Item other) {
return tier.getRepairIngredients().contains(other);
}
}

View file

@ -26,14 +26,13 @@
package org.geysermc.geyser.item.type; package org.geysermc.geyser.item.type;
import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.NonNull;
import org.geysermc.geyser.item.ArmorMaterial;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.item.BedrockItemBuilder; import org.geysermc.geyser.translator.item.BedrockItemBuilder;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents; import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents;
public class WolfArmorItem extends ArmorItem { public class WolfArmorItem extends Item {
public WolfArmorItem(String javaIdentifier, ArmorMaterial material, Builder builder) { public WolfArmorItem(String javaIdentifier, Builder builder) {
super(javaIdentifier, material, builder); super(javaIdentifier, builder);
} }
@Override @Override

View file

@ -25,20 +25,15 @@
package org.geysermc.geyser.level; package org.geysermc.geyser.level;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.objects.Object2ObjectMap; import it.unimi.dsi.fastutil.objects.Object2ObjectMap;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.math.vector.Vector3i;
import org.geysermc.erosion.packet.backendbound.BackendboundBatchBlockRequestPacket; import org.geysermc.erosion.packet.backendbound.BackendboundBatchBlockRequestPacket;
import org.geysermc.erosion.packet.backendbound.BackendboundBlockRequestPacket; import org.geysermc.erosion.packet.backendbound.BackendboundBlockRequestPacket;
import org.geysermc.erosion.packet.backendbound.BackendboundPickBlockPacket;
import org.geysermc.erosion.util.BlockPositionIterator; import org.geysermc.erosion.util.BlockPositionIterator;
import org.geysermc.geyser.erosion.ErosionCancellationException; import org.geysermc.geyser.erosion.ErosionCancellationException;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.GameMode; import org.geysermc.mcprotocollib.protocol.data.game.entity.player.GameMode;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
@ -124,19 +119,4 @@ public class GeyserWorldManager extends WorldManager {
public GameMode getDefaultGameMode(GeyserSession session) { public GameMode getDefaultGameMode(GeyserSession session) {
return GameMode.SURVIVAL; return GameMode.SURVIVAL;
} }
@NonNull
@Override
public CompletableFuture<@Nullable DataComponents> getPickItemComponents(GeyserSession session, int x, int y, int z, boolean addNbtData) {
var erosionHandler = session.getErosionHandler().getAsActive();
if (erosionHandler == null) {
return super.getPickItemComponents(session, x, y, z, addNbtData);
} else if (session.isClosed()) {
return CompletableFuture.failedFuture(new ErosionCancellationException());
}
CompletableFuture<Int2ObjectMap<byte[]>> future = new CompletableFuture<>();
erosionHandler.setPickBlockLookup(future);
erosionHandler.sendPacket(new BackendboundPickBlockPacket(Vector3i.from(x, y, z)));
return future.thenApply(RAW_TRANSFORMER);
}
} }

View file

@ -30,26 +30,26 @@ public enum MapColor {
COLOR_1(-1, -1, -1), COLOR_1(-1, -1, -1),
COLOR_2(-1, -1, -1), COLOR_2(-1, -1, -1),
COLOR_3(-1, -1, -1), COLOR_3(-1, -1, -1),
COLOR_4(39, 125, 89), COLOR_4(89, 125, 39),
COLOR_5(48, 153, 109), COLOR_5(109, 153, 48),
COLOR_6(56, 178, 127), COLOR_6(127, 178, 56),
COLOR_7(29, 94, 67), COLOR_7(67, 94, 29),
COLOR_8(115, 164, 174), COLOR_8(174, 164, 115),
COLOR_9(140, 201, 213), COLOR_9(213, 201, 140),
COLOR_10(163, 233, 247), COLOR_10(247, 233, 163),
COLOR_11(86, 123, 130), COLOR_11(130, 123, 86),
COLOR_12(140, 140, 140), COLOR_12(140, 140, 140),
COLOR_13(171, 171, 171), COLOR_13(171, 171, 171),
COLOR_14(199, 199, 199), COLOR_14(199, 199, 199),
COLOR_15(105, 105, 105), COLOR_15(105, 105, 105),
COLOR_16(0, 0, 180), COLOR_16(180, 0, 0),
COLOR_17(0, 0, 220), COLOR_17(220, 0, 0),
COLOR_18(0, 0, 255), COLOR_18(255, 0, 0),
COLOR_19(0, 0, 135), COLOR_19(135, 0, 0),
COLOR_20(180, 112, 112), COLOR_20(112, 112, 180),
COLOR_21(220, 138, 138), COLOR_21(138, 138, 220),
COLOR_22(255, 160, 160), COLOR_22(160, 160, 255),
COLOR_23(135, 84, 84), COLOR_23(84, 84, 135),
COLOR_24(117, 117, 117), COLOR_24(117, 117, 117),
COLOR_25(144, 144, 144), COLOR_25(144, 144, 144),
COLOR_26(167, 167, 167), COLOR_26(167, 167, 167),
@ -62,54 +62,54 @@ public enum MapColor {
COLOR_33(220, 220, 220), COLOR_33(220, 220, 220),
COLOR_34(255, 255, 255), COLOR_34(255, 255, 255),
COLOR_35(135, 135, 135), COLOR_35(135, 135, 135),
COLOR_36(129, 118, 115), COLOR_36(115, 118, 129),
COLOR_37(158, 144, 141), COLOR_37(141, 144, 158),
COLOR_38(184, 168, 164), COLOR_38(164, 168, 184),
COLOR_39(97, 88, 86), COLOR_39(86, 88, 97),
COLOR_40(54, 76, 106), COLOR_40(106, 76, 54),
COLOR_41(66, 94, 130), COLOR_41(130, 94, 66),
COLOR_42(77, 109, 151), COLOR_42(151, 109, 77),
COLOR_43(40, 57, 79), COLOR_43(79, 57, 40),
COLOR_44(79, 79, 79), COLOR_44(79, 79, 79),
COLOR_45(96, 96, 96), COLOR_45(96, 96, 96),
COLOR_46(112, 112, 112), COLOR_46(112, 112, 112),
COLOR_47(59, 59, 59), COLOR_47(59, 59, 59),
COLOR_48(180, 45, 45), COLOR_48(45, 45, 180),
COLOR_49(220, 55, 55), COLOR_49(55, 55, 220),
COLOR_50(255, 64, 64), COLOR_50(64, 64, 255),
COLOR_51(135, 33, 33), COLOR_51(33, 33, 135),
COLOR_52(50, 84, 100), COLOR_52(100, 84, 50),
COLOR_53(62, 102, 123), COLOR_53(123, 102, 62),
COLOR_54(72, 119, 143), COLOR_54(143, 119, 72),
COLOR_55(38, 63, 75), COLOR_55(75, 63, 38),
COLOR_56(172, 177, 180), COLOR_56(180, 177, 172),
COLOR_57(211, 217, 220), COLOR_57(220, 217, 211),
COLOR_58(245, 252, 255), COLOR_58(255, 252, 245),
COLOR_59(129, 133, 135), COLOR_59(135, 133, 129),
COLOR_60(36, 89, 152), COLOR_60(152, 89, 36),
COLOR_61(44, 109, 186), COLOR_61(186, 109, 44),
COLOR_62(51, 127, 216), COLOR_62(216, 127, 51),
COLOR_63(27, 67, 114), COLOR_63(114, 67, 27),
COLOR_64(152, 53, 125), COLOR_64(125, 53, 152),
COLOR_65(186, 65, 153), COLOR_65(153, 65, 186),
COLOR_66(216, 76, 178), COLOR_66(178, 76, 216),
COLOR_67(114, 40, 94), COLOR_67(94, 40, 114),
COLOR_68(152, 108, 72), COLOR_68(72, 108, 152),
COLOR_69(186, 132, 88), COLOR_69(88, 132, 186),
COLOR_70(216, 153, 102), COLOR_70(102, 153, 216),
COLOR_71(114, 81, 54), COLOR_71(54, 81, 114),
COLOR_72(36, 161, 161), COLOR_72(161, 161, 36),
COLOR_73(44, 197, 197), COLOR_73(197, 197, 44),
COLOR_74(51, 229, 229), COLOR_74(229, 229, 51),
COLOR_75(27, 121, 121), COLOR_75(121, 121, 27),
COLOR_76(17, 144, 89), COLOR_76(89, 144, 17),
COLOR_77(21, 176, 109), COLOR_77(109, 176, 21),
COLOR_78(25, 204, 127), COLOR_78(127, 204, 25),
COLOR_79(13, 108, 67), COLOR_79(67, 108, 13),
COLOR_80(116, 89, 170), COLOR_80(170, 89, 116),
COLOR_81(142, 109, 208), COLOR_81(208, 109, 142),
COLOR_82(165, 127, 242), COLOR_82(242, 127, 165),
COLOR_83(87, 67, 128), COLOR_83(128, 67, 87),
COLOR_84(53, 53, 53), COLOR_84(53, 53, 53),
COLOR_85(65, 65, 65), COLOR_85(65, 65, 65),
COLOR_86(76, 76, 76), COLOR_86(76, 76, 76),
@ -118,162 +118,162 @@ public enum MapColor {
COLOR_89(132, 132, 132), COLOR_89(132, 132, 132),
COLOR_90(153, 153, 153), COLOR_90(153, 153, 153),
COLOR_91(81, 81, 81), COLOR_91(81, 81, 81),
COLOR_92(108, 89, 53), COLOR_92(53, 89, 108),
COLOR_93(132, 109, 65), COLOR_93(65, 109, 132),
COLOR_94(153, 127, 76), COLOR_94(76, 127, 153),
COLOR_95(81, 67, 40), COLOR_95(40, 67, 81),
COLOR_96(125, 44, 89), COLOR_96(89, 44, 125),
COLOR_97(153, 54, 109), COLOR_97(109, 54, 153),
COLOR_98(178, 63, 127), COLOR_98(127, 63, 178),
COLOR_99(94, 33, 67), COLOR_99(67, 33, 94),
COLOR_100(125, 53, 36), COLOR_100(36, 53, 125),
COLOR_101(153, 65, 44), COLOR_101(44, 65, 153),
COLOR_102(178, 76, 51), COLOR_102(51, 76, 178),
COLOR_103(94, 40, 27), COLOR_103(27, 40, 94),
COLOR_104(36, 53, 72), COLOR_104(72, 53, 36),
COLOR_105(44, 65, 88), COLOR_105(88, 65, 44),
COLOR_106(51, 76, 102), COLOR_106(102, 76, 51),
COLOR_107(27, 40, 54), COLOR_107(54, 40, 27),
COLOR_108(36, 89, 72), COLOR_108(72, 89, 36),
COLOR_109(44, 109, 88), COLOR_109(88, 109, 44),
COLOR_110(51, 127, 102), COLOR_110(102, 127, 51),
COLOR_111(27, 67, 54), COLOR_111(54, 67, 27),
COLOR_112(36, 36, 108), COLOR_112(108, 36, 36),
COLOR_113(44, 44, 132), COLOR_113(132, 44, 44),
COLOR_114(51, 51, 153), COLOR_114(153, 51, 51),
COLOR_115(27, 27, 81), COLOR_115(81, 27, 27),
COLOR_116(17, 17, 17), COLOR_116(17, 17, 17),
COLOR_117(21, 21, 21), COLOR_117(21, 21, 21),
COLOR_118(25, 25, 25), COLOR_118(25, 25, 25),
COLOR_119(13, 13, 13), COLOR_119(13, 13, 13),
COLOR_120(54, 168, 176), COLOR_120(176, 168, 54),
COLOR_121(66, 205, 215), COLOR_121(215, 205, 66),
COLOR_122(77, 238, 250), COLOR_122(250, 238, 77),
COLOR_123(40, 126, 132), COLOR_123(132, 126, 40),
COLOR_124(150, 154, 64), COLOR_124(64, 154, 150),
COLOR_125(183, 188, 79), COLOR_125(79, 188, 183),
COLOR_126(213, 219, 92), COLOR_126(92, 219, 213),
COLOR_127(112, 115, 48), COLOR_127(48, 115, 112),
COLOR_128(180, 90, 52), COLOR_128(52, 90, 180),
COLOR_129(220, 110, 63), COLOR_129(63, 110, 220),
COLOR_130(255, 128, 74), COLOR_130(74, 128, 255),
COLOR_131(135, 67, 39), COLOR_131(39, 67, 135),
COLOR_132(40, 153, 0), COLOR_132(0, 153, 40),
COLOR_133(50, 187, 0), COLOR_133(0, 187, 50),
COLOR_134(58, 217, 0), COLOR_134(0, 217, 58),
COLOR_135(30, 114, 0), COLOR_135(0, 114, 30),
COLOR_136(34, 60, 91), COLOR_136(91, 60, 34),
COLOR_137(42, 74, 111), COLOR_137(111, 74, 42),
COLOR_138(49, 86, 129), COLOR_138(129, 86, 49),
COLOR_139(25, 45, 68), COLOR_139(68, 45, 25),
COLOR_140(0, 1, 79), COLOR_140(79, 1, 0),
COLOR_141(0, 1, 96), COLOR_141(96, 1, 0),
COLOR_142(0, 2, 112), COLOR_142(112, 2, 0),
COLOR_143(0, 1, 59), COLOR_143(59, 1, 0),
COLOR_144(113, 124, 147), COLOR_144(147, 124, 113),
COLOR_145(138, 152, 180), COLOR_145(180, 152, 138),
COLOR_146(161, 177, 209), COLOR_146(209, 177, 161),
COLOR_147(85, 93, 110), COLOR_147(110, 93, 85),
COLOR_148(25, 57, 112), COLOR_148(112, 57, 25),
COLOR_149(31, 70, 137), COLOR_149(137, 70, 31),
COLOR_150(36, 82, 159), COLOR_150(159, 82, 36),
COLOR_151(19, 43, 84), COLOR_151(84, 43, 19),
COLOR_152(76, 61, 105), COLOR_152(105, 61, 76),
COLOR_153(93, 75, 128), COLOR_153(128, 75, 93),
COLOR_154(108, 87, 149), COLOR_154(149, 87, 108),
COLOR_155(57, 46, 78), COLOR_155(78, 46, 57),
COLOR_156(97, 76, 79), COLOR_156(79, 76, 97),
COLOR_157(119, 93, 96), COLOR_157(96, 93, 119),
COLOR_158(138, 108, 112), COLOR_158(112, 108, 138),
COLOR_159(73, 57, 59), COLOR_159(59, 57, 73),
COLOR_160(25, 93, 131), COLOR_160(131, 93, 25),
COLOR_161(31, 114, 160), COLOR_161(160, 114, 31),
COLOR_162(36, 133, 186), COLOR_162(186, 133, 36),
COLOR_163(19, 70, 98), COLOR_163(98, 70, 19),
COLOR_164(37, 82, 72), COLOR_164(72, 82, 37),
COLOR_165(45, 100, 88), COLOR_165(88, 100, 45),
COLOR_166(53, 117, 103), COLOR_166(103, 117, 53),
COLOR_167(28, 61, 54), COLOR_167(54, 61, 28),
COLOR_168(55, 54, 112), COLOR_168(112, 54, 55),
COLOR_169(67, 66, 138), COLOR_169(138, 66, 67),
COLOR_170(78, 77, 160), COLOR_170(160, 77, 78),
COLOR_171(41, 40, 84), COLOR_171(84, 40, 41),
COLOR_172(24, 28, 40), COLOR_172(40, 28, 24),
COLOR_173(30, 35, 49), COLOR_173(49, 35, 30),
COLOR_174(35, 41, 57), COLOR_174(57, 41, 35),
COLOR_175(18, 21, 30), COLOR_175(30, 21, 18),
COLOR_176(69, 75, 95), COLOR_176(95, 75, 69),
COLOR_177(84, 92, 116), COLOR_177(116, 92, 84),
COLOR_178(98, 107, 135), COLOR_178(135, 107, 98),
COLOR_179(51, 56, 71), COLOR_179(71, 56, 51),
COLOR_180(64, 64, 61), COLOR_180(61, 64, 64),
COLOR_181(79, 79, 75), COLOR_181(75, 79, 79),
COLOR_182(92, 92, 87), COLOR_182(87, 92, 92),
COLOR_183(48, 48, 46), COLOR_183(46, 48, 48),
COLOR_184(62, 51, 86), COLOR_184(86, 51, 62),
COLOR_185(75, 62, 105), COLOR_185(105, 62, 75),
COLOR_186(88, 73, 122), COLOR_186(122, 73, 88),
COLOR_187(46, 38, 64), COLOR_187(64, 38, 46),
COLOR_188(64, 43, 53), COLOR_188(53, 43, 64),
COLOR_189(79, 53, 65), COLOR_189(65, 53, 79),
COLOR_190(92, 62, 76), COLOR_190(76, 62, 92),
COLOR_191(48, 32, 40), COLOR_191(40, 32, 48),
COLOR_192(24, 35, 53), COLOR_192(53, 35, 24),
COLOR_193(30, 43, 65), COLOR_193(65, 43, 30),
COLOR_194(35, 50, 76), COLOR_194(76, 50, 35),
COLOR_195(18, 26, 40), COLOR_195(40, 26, 18),
COLOR_196(29, 57, 53), COLOR_196(53, 57, 29),
COLOR_197(36, 70, 65), COLOR_197(65, 70, 36),
COLOR_198(42, 82, 76), COLOR_198(76, 82, 42),
COLOR_199(22, 43, 40), COLOR_199(40, 43, 22),
COLOR_200(32, 42, 100), COLOR_200(100, 42, 32),
COLOR_201(39, 51, 122), COLOR_201(122, 51, 39),
COLOR_202(46, 60, 142), COLOR_202(142, 60, 46),
COLOR_203(24, 31, 75), COLOR_203(75, 31, 24),
COLOR_204(11, 15, 26), COLOR_204(26, 15, 11),
COLOR_205(13, 18, 31), COLOR_205(31, 18, 13),
COLOR_206(16, 22, 37), COLOR_206(37, 22, 16),
COLOR_207(8, 11, 19), COLOR_207(19, 11, 8),
COLOR_208(34, 33, 133), COLOR_208(133, 33, 34),
COLOR_209(42, 41, 163), COLOR_209(163, 41, 42),
COLOR_210(49, 48, 189), COLOR_210(189, 48, 49),
COLOR_211(25, 25, 100), COLOR_211(100, 25, 25),
COLOR_212(68, 44, 104), COLOR_212(104, 44, 68),
COLOR_213(83, 54, 127), COLOR_213(127, 54, 83),
COLOR_214(97, 63, 148), COLOR_214(148, 63, 97),
COLOR_215(51, 33, 78), COLOR_215(78, 33, 51),
COLOR_216(20, 17, 64), COLOR_216(64, 17, 20),
COLOR_217(25, 21, 79), COLOR_217(79, 21, 25),
COLOR_218(29, 25, 92), COLOR_218(92, 25, 29),
COLOR_219(15, 13, 48), COLOR_219(48, 13, 15),
COLOR_220(94, 88, 15), COLOR_220(15, 88, 94),
COLOR_221(115, 108, 18), COLOR_221(18, 108, 115),
COLOR_222(134, 126, 22), COLOR_222(22, 126, 134),
COLOR_223(70, 66, 11), COLOR_223(11, 66, 70),
COLOR_224(98, 100, 40), COLOR_224(40, 100, 98),
COLOR_225(120, 122, 50), COLOR_225(50, 122, 120),
COLOR_226(140, 142, 58), COLOR_226(58, 142, 140),
COLOR_227(74, 75, 30), COLOR_227(30, 75, 74),
COLOR_228(43, 31, 60), COLOR_228(60, 31, 43),
COLOR_229(53, 37, 74), COLOR_229(74, 37, 53),
COLOR_230(62, 44, 86), COLOR_230(86, 44, 62),
COLOR_231(32, 23, 45), COLOR_231(45, 23, 32),
COLOR_232(93, 127, 14), COLOR_232(14, 127, 93),
COLOR_233(114, 155, 17), COLOR_233(17, 155, 114),
COLOR_234(133, 180, 20), COLOR_234(20, 180, 133),
COLOR_235(70, 95, 10), COLOR_235(10, 95, 70),
COLOR_236(70, 70, 70), COLOR_236(70, 70, 70),
COLOR_237(86, 86, 86), COLOR_237(86, 86, 86),
COLOR_238(100, 100, 100), COLOR_238(100, 100, 100),
COLOR_239(52, 52, 52), COLOR_239(52, 52, 52),
COLOR_240(103, 123, 152), COLOR_240(152, 123, 103),
COLOR_241(126, 150, 186), COLOR_241(186, 150, 126),
COLOR_242(147, 175, 216), COLOR_242(216, 175, 147),
COLOR_243(77, 92, 114), COLOR_243(114, 92, 77),
COLOR_244(105, 117, 89), COLOR_244(89, 117, 105),
COLOR_245(129, 144, 109), COLOR_245(109, 144, 129),
COLOR_246(150, 167, 127), COLOR_246(127, 167, 150),
COLOR_247(79, 88, 67); COLOR_247(67, 88, 79);
private static final MapColor[] VALUES = values(); private static final MapColor[] VALUES = values();
@ -285,9 +285,9 @@ public enum MapColor {
alpha = 0; // transparent alpha = 0; // transparent
this.value = ((alpha & 0xFF) << 24) | this.value = ((alpha & 0xFF) << 24) |
((red & 0xFF) << 16) | ((red & 0xFF) << 16) |
((green & 0xFF) << 8) | ((green & 0xFF) << 8) |
(blue & 0xFF); (blue & 0xFF);
} }
public static MapColor fromId(int id) { public static MapColor fromId(int id) {
@ -297,4 +297,4 @@ public enum MapColor {
public int getARGB() { public int getARGB() {
return value; return value;
} }
} }

View file

@ -192,16 +192,6 @@ public abstract class WorldManager {
return null; return null;
} }
/**
* Used for pick block, so we don't need to cache more data than necessary.
*
* @return expected NBT for this item.
*/
@NonNull
public CompletableFuture<@Nullable DataComponents> getPickItemComponents(GeyserSession session, int x, int y, int z, boolean addExtraData) {
return CompletableFuture.completedFuture(null);
}
/** /**
* Retrieves decorated pot sherds from the server. Used to ensure the data is not erased on animation sent * Retrieves decorated pot sherds from the server. Used to ensure the data is not erased on animation sent
* through the BlockEntityDataPacket. * through the BlockEntityDataPacket.

View file

@ -398,9 +398,10 @@ public final class Blocks {
.booleanState(WEST))); .booleanState(WEST)));
public static final Block SOUL_FIRE = register(new Block("soul_fire", builder().pushReaction(PistonBehavior.DESTROY))); 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 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) public static final Block CREAKING_HEART = register(new Block("creaking_heart", builder().setBlockEntity(BlockEntityType.CREAKING_HEART).destroyTime(10.0f)
.booleanState(ACTIVE)
.enumState(AXIS, Axis.VALUES) .enumState(AXIS, Axis.VALUES)
.enumState(CREAKING))); .booleanState(NATURAL)));
public static final Block OAK_STAIRS = register(new Block("oak_stairs", builder().destroyTime(2.0f) 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(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
.enumState(HALF) .enumState(HALF)
@ -592,9 +593,9 @@ public final class Blocks {
.enumState(ATTACH_FACE) .enumState(ATTACH_FACE)
.enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
.booleanState(POWERED))); .booleanState(POWERED)));
public static final Block STONE_PRESSURE_PLATE = register(new Block("stone_pressure_plate", builder().requiresCorrectToolForDrops().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) public static final Block STONE_PRESSURE_PLATE = register(new Block("stone_pressure_plate", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY)
.booleanState(POWERED))); .booleanState(POWERED)));
public static final Block IRON_DOOR = register(new DoorBlock("iron_door", builder().requiresCorrectToolForDrops().destroyTime(5.0f).pushReaction(PistonBehavior.DESTROY) public static final Block IRON_DOOR = register(new DoorBlock("iron_door", builder().destroyTime(5.0f).pushReaction(PistonBehavior.DESTROY)
.enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
.enumState(DOUBLE_BLOCK_HALF) .enumState(DOUBLE_BLOCK_HALF)
.enumState(DOOR_HINGE) .enumState(DOOR_HINGE)
@ -822,6 +823,14 @@ public final class Blocks {
.booleanState(UP) .booleanState(UP)
.booleanState(WATERLOGGED) .booleanState(WATERLOGGED)
.booleanState(WEST))); .booleanState(WEST)));
public static final Block RESIN_CLUMP = register(new Block("resin_clump", builder().pushReaction(PistonBehavior.DESTROY)
.booleanState(DOWN)
.booleanState(EAST)
.booleanState(NORTH)
.booleanState(SOUTH)
.booleanState(UP)
.booleanState(WATERLOGGED)
.booleanState(WEST)));
public static final Block OAK_FENCE_GATE = register(new Block("oak_fence_gate", builder().destroyTime(2.0f) public static final Block OAK_FENCE_GATE = register(new Block("oak_fence_gate", builder().destroyTime(2.0f)
.enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
.booleanState(IN_WALL) .booleanState(IN_WALL)
@ -845,6 +854,24 @@ public final class Blocks {
public static final Block MYCELIUM = register(new Block("mycelium", builder().destroyTime(0.6f) public static final Block MYCELIUM = register(new Block("mycelium", builder().destroyTime(0.6f)
.booleanState(SNOWY))); .booleanState(SNOWY)));
public static final Block LILY_PAD = register(new Block("lily_pad", builder().pushReaction(PistonBehavior.DESTROY))); public static final Block LILY_PAD = register(new Block("lily_pad", builder().pushReaction(PistonBehavior.DESTROY)));
public static final Block RESIN_BLOCK = register(new Block("resin_block", builder()));
public static final Block RESIN_BRICKS = register(new Block("resin_bricks", builder().requiresCorrectToolForDrops().destroyTime(1.5f)));
public static final Block RESIN_BRICK_STAIRS = register(new Block("resin_brick_stairs", builder().requiresCorrectToolForDrops().destroyTime(1.5f)
.enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
.enumState(HALF)
.enumState(STAIRS_SHAPE)
.booleanState(WATERLOGGED)));
public static final Block RESIN_BRICK_SLAB = register(new Block("resin_brick_slab", builder().requiresCorrectToolForDrops().destroyTime(1.5f)
.enumState(SLAB_TYPE)
.booleanState(WATERLOGGED)));
public static final Block RESIN_BRICK_WALL = register(new Block("resin_brick_wall", builder().requiresCorrectToolForDrops().destroyTime(1.5f)
.enumState(EAST_WALL)
.enumState(NORTH_WALL)
.enumState(SOUTH_WALL)
.booleanState(UP)
.booleanState(WATERLOGGED)
.enumState(WEST_WALL)));
public static final Block CHISELED_RESIN_BRICKS = register(new Block("chiseled_resin_bricks", builder().requiresCorrectToolForDrops().destroyTime(1.5f)));
public static final Block NETHER_BRICKS = register(new Block("nether_bricks", builder().requiresCorrectToolForDrops().destroyTime(2.0f))); public static final Block NETHER_BRICKS = register(new Block("nether_bricks", builder().requiresCorrectToolForDrops().destroyTime(2.0f)));
public static final Block NETHER_BRICK_FENCE = register(new Block("nether_brick_fence", builder().requiresCorrectToolForDrops().destroyTime(2.0f) public static final Block NETHER_BRICK_FENCE = register(new Block("nether_brick_fence", builder().requiresCorrectToolForDrops().destroyTime(2.0f)
.booleanState(EAST) .booleanState(EAST)
@ -860,7 +887,7 @@ public final class Blocks {
public static final Block NETHER_WART = register(new Block("nether_wart", builder().pushReaction(PistonBehavior.DESTROY) public static final Block NETHER_WART = register(new Block("nether_wart", builder().pushReaction(PistonBehavior.DESTROY)
.intState(AGE_3))); .intState(AGE_3)));
public static final Block ENCHANTING_TABLE = register(new Block("enchanting_table", builder().setBlockEntity(BlockEntityType.ENCHANTING_TABLE).requiresCorrectToolForDrops().destroyTime(5.0f))); public static final Block ENCHANTING_TABLE = register(new Block("enchanting_table", builder().setBlockEntity(BlockEntityType.ENCHANTING_TABLE).requiresCorrectToolForDrops().destroyTime(5.0f)));
public static final Block BREWING_STAND = register(new Block("brewing_stand", builder().setBlockEntity(BlockEntityType.BREWING_STAND).requiresCorrectToolForDrops().destroyTime(0.5f) public static final Block BREWING_STAND = register(new Block("brewing_stand", builder().setBlockEntity(BlockEntityType.BREWING_STAND).destroyTime(0.5f)
.booleanState(HAS_BOTTLE_0) .booleanState(HAS_BOTTLE_0)
.booleanState(HAS_BOTTLE_1) .booleanState(HAS_BOTTLE_1)
.booleanState(HAS_BOTTLE_2))); .booleanState(HAS_BOTTLE_2)));
@ -888,7 +915,7 @@ public final class Blocks {
.booleanState(WATERLOGGED))); .booleanState(WATERLOGGED)));
public static final Block EMERALD_ORE = register(new Block("emerald_ore", builder().requiresCorrectToolForDrops().destroyTime(3.0f))); public static final Block EMERALD_ORE = register(new Block("emerald_ore", builder().requiresCorrectToolForDrops().destroyTime(3.0f)));
public static final Block DEEPSLATE_EMERALD_ORE = register(new Block("deepslate_emerald_ore", builder().requiresCorrectToolForDrops().destroyTime(4.5f))); public static final Block DEEPSLATE_EMERALD_ORE = register(new Block("deepslate_emerald_ore", builder().requiresCorrectToolForDrops().destroyTime(4.5f)));
public static final Block ENDER_CHEST = register(new Block("ender_chest", builder().setBlockEntity(BlockEntityType.ENDER_CHEST).requiresCorrectToolForDrops().destroyTime(22.5f) public static final Block ENDER_CHEST = register(new Block("ender_chest", builder().setBlockEntity(BlockEntityType.ENDER_CHEST).destroyTime(22.5f)
.enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
.booleanState(WATERLOGGED))); .booleanState(WATERLOGGED)));
public static final Block TRIPWIRE_HOOK = register(new Block("tripwire_hook", builder().pushReaction(PistonBehavior.DESTROY) public static final Block TRIPWIRE_HOOK = register(new Block("tripwire_hook", builder().pushReaction(PistonBehavior.DESTROY)
@ -1062,9 +1089,9 @@ public final class Blocks {
.enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
.enumState(CHEST_TYPE, ChestType.VALUES) .enumState(CHEST_TYPE, ChestType.VALUES)
.booleanState(WATERLOGGED))); .booleanState(WATERLOGGED)));
public static final Block LIGHT_WEIGHTED_PRESSURE_PLATE = register(new Block("light_weighted_pressure_plate", builder().requiresCorrectToolForDrops().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) public static final Block LIGHT_WEIGHTED_PRESSURE_PLATE = register(new Block("light_weighted_pressure_plate", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY)
.intState(POWER))); .intState(POWER)));
public static final Block HEAVY_WEIGHTED_PRESSURE_PLATE = register(new Block("heavy_weighted_pressure_plate", builder().requiresCorrectToolForDrops().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) public static final Block HEAVY_WEIGHTED_PRESSURE_PLATE = register(new Block("heavy_weighted_pressure_plate", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY)
.intState(POWER))); .intState(POWER)));
public static final Block COMPARATOR = register(new Block("comparator", builder().setBlockEntity(BlockEntityType.COMPARATOR).pushReaction(PistonBehavior.DESTROY) public static final Block COMPARATOR = register(new Block("comparator", builder().setBlockEntity(BlockEntityType.COMPARATOR).pushReaction(PistonBehavior.DESTROY)
.enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
@ -2096,14 +2123,14 @@ public final class Blocks {
public static final Block SMITHING_TABLE = register(new Block("smithing_table", builder().destroyTime(2.5f))); public static final Block SMITHING_TABLE = register(new Block("smithing_table", builder().destroyTime(2.5f)));
public static final Block STONECUTTER = register(new Block("stonecutter", builder().requiresCorrectToolForDrops().destroyTime(3.5f) public static final Block STONECUTTER = register(new Block("stonecutter", builder().requiresCorrectToolForDrops().destroyTime(3.5f)
.enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST))); .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)));
public static final Block BELL = register(new Block("bell", builder().setBlockEntity(BlockEntityType.BELL).requiresCorrectToolForDrops().destroyTime(5.0f).pushReaction(PistonBehavior.DESTROY) public static final Block BELL = register(new Block("bell", builder().setBlockEntity(BlockEntityType.BELL).destroyTime(5.0f).pushReaction(PistonBehavior.DESTROY)
.enumState(BELL_ATTACHMENT) .enumState(BELL_ATTACHMENT)
.enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
.booleanState(POWERED))); .booleanState(POWERED)));
public static final Block LANTERN = register(new Block("lantern", builder().requiresCorrectToolForDrops().destroyTime(3.5f).pushReaction(PistonBehavior.DESTROY) public static final Block LANTERN = register(new Block("lantern", builder().destroyTime(3.5f).pushReaction(PistonBehavior.DESTROY)
.booleanState(HANGING) .booleanState(HANGING)
.booleanState(WATERLOGGED))); .booleanState(WATERLOGGED)));
public static final Block SOUL_LANTERN = register(new Block("soul_lantern", builder().requiresCorrectToolForDrops().destroyTime(3.5f).pushReaction(PistonBehavior.DESTROY) public static final Block SOUL_LANTERN = register(new Block("soul_lantern", builder().destroyTime(3.5f).pushReaction(PistonBehavior.DESTROY)
.booleanState(HANGING) .booleanState(HANGING)
.booleanState(WATERLOGGED))); .booleanState(WATERLOGGED)));
public static final Block CAMPFIRE = register(new Block("campfire", builder().setBlockEntity(BlockEntityType.CAMPFIRE).destroyTime(2.0f) public static final Block CAMPFIRE = register(new Block("campfire", builder().setBlockEntity(BlockEntityType.CAMPFIRE).destroyTime(2.0f)
@ -2307,7 +2334,7 @@ public final class Blocks {
public static final Block POLISHED_BLACKSTONE_SLAB = register(new Block("polished_blackstone_slab", builder().requiresCorrectToolForDrops().destroyTime(2.0f) public static final Block POLISHED_BLACKSTONE_SLAB = register(new Block("polished_blackstone_slab", builder().requiresCorrectToolForDrops().destroyTime(2.0f)
.enumState(SLAB_TYPE) .enumState(SLAB_TYPE)
.booleanState(WATERLOGGED))); .booleanState(WATERLOGGED)));
public static final Block POLISHED_BLACKSTONE_PRESSURE_PLATE = register(new Block("polished_blackstone_pressure_plate", builder().requiresCorrectToolForDrops().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) public static final Block POLISHED_BLACKSTONE_PRESSURE_PLATE = register(new Block("polished_blackstone_pressure_plate", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY)
.booleanState(POWERED))); .booleanState(POWERED)));
public static final Block POLISHED_BLACKSTONE_BUTTON = register(new Block("polished_blackstone_button", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY) public static final Block POLISHED_BLACKSTONE_BUTTON = register(new Block("polished_blackstone_button", builder().destroyTime(0.5f).pushReaction(PistonBehavior.DESTROY)
.enumState(ATTACH_FACE) .enumState(ATTACH_FACE)
@ -2606,49 +2633,49 @@ public final class Blocks {
public static final Block WAXED_CUT_COPPER_SLAB = register(new Block("waxed_cut_copper_slab", builder().requiresCorrectToolForDrops().destroyTime(3.0f) public static final Block WAXED_CUT_COPPER_SLAB = register(new Block("waxed_cut_copper_slab", builder().requiresCorrectToolForDrops().destroyTime(3.0f)
.enumState(SLAB_TYPE) .enumState(SLAB_TYPE)
.booleanState(WATERLOGGED))); .booleanState(WATERLOGGED)));
public static final Block COPPER_DOOR = register(new DoorBlock("copper_door", builder().requiresCorrectToolForDrops().destroyTime(3.0f).pushReaction(PistonBehavior.DESTROY) public static final Block COPPER_DOOR = register(new DoorBlock("copper_door", builder().destroyTime(3.0f).pushReaction(PistonBehavior.DESTROY)
.enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
.enumState(DOUBLE_BLOCK_HALF) .enumState(DOUBLE_BLOCK_HALF)
.enumState(DOOR_HINGE) .enumState(DOOR_HINGE)
.booleanState(OPEN) .booleanState(OPEN)
.booleanState(POWERED))); .booleanState(POWERED)));
public static final Block EXPOSED_COPPER_DOOR = register(new DoorBlock("exposed_copper_door", builder().requiresCorrectToolForDrops().destroyTime(3.0f).pushReaction(PistonBehavior.DESTROY) public static final Block EXPOSED_COPPER_DOOR = register(new DoorBlock("exposed_copper_door", builder().destroyTime(3.0f).pushReaction(PistonBehavior.DESTROY)
.enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
.enumState(DOUBLE_BLOCK_HALF) .enumState(DOUBLE_BLOCK_HALF)
.enumState(DOOR_HINGE) .enumState(DOOR_HINGE)
.booleanState(OPEN) .booleanState(OPEN)
.booleanState(POWERED))); .booleanState(POWERED)));
public static final Block OXIDIZED_COPPER_DOOR = register(new DoorBlock("oxidized_copper_door", builder().requiresCorrectToolForDrops().destroyTime(3.0f).pushReaction(PistonBehavior.DESTROY) public static final Block OXIDIZED_COPPER_DOOR = register(new DoorBlock("oxidized_copper_door", builder().destroyTime(3.0f).pushReaction(PistonBehavior.DESTROY)
.enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
.enumState(DOUBLE_BLOCK_HALF) .enumState(DOUBLE_BLOCK_HALF)
.enumState(DOOR_HINGE) .enumState(DOOR_HINGE)
.booleanState(OPEN) .booleanState(OPEN)
.booleanState(POWERED))); .booleanState(POWERED)));
public static final Block WEATHERED_COPPER_DOOR = register(new DoorBlock("weathered_copper_door", builder().requiresCorrectToolForDrops().destroyTime(3.0f).pushReaction(PistonBehavior.DESTROY) public static final Block WEATHERED_COPPER_DOOR = register(new DoorBlock("weathered_copper_door", builder().destroyTime(3.0f).pushReaction(PistonBehavior.DESTROY)
.enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
.enumState(DOUBLE_BLOCK_HALF) .enumState(DOUBLE_BLOCK_HALF)
.enumState(DOOR_HINGE) .enumState(DOOR_HINGE)
.booleanState(OPEN) .booleanState(OPEN)
.booleanState(POWERED))); .booleanState(POWERED)));
public static final Block WAXED_COPPER_DOOR = register(new DoorBlock("waxed_copper_door", builder().requiresCorrectToolForDrops().destroyTime(3.0f).pushReaction(PistonBehavior.DESTROY) public static final Block WAXED_COPPER_DOOR = register(new DoorBlock("waxed_copper_door", builder().destroyTime(3.0f).pushReaction(PistonBehavior.DESTROY)
.enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
.enumState(DOUBLE_BLOCK_HALF) .enumState(DOUBLE_BLOCK_HALF)
.enumState(DOOR_HINGE) .enumState(DOOR_HINGE)
.booleanState(OPEN) .booleanState(OPEN)
.booleanState(POWERED))); .booleanState(POWERED)));
public static final Block WAXED_EXPOSED_COPPER_DOOR = register(new DoorBlock("waxed_exposed_copper_door", builder().requiresCorrectToolForDrops().destroyTime(3.0f).pushReaction(PistonBehavior.DESTROY) public static final Block WAXED_EXPOSED_COPPER_DOOR = register(new DoorBlock("waxed_exposed_copper_door", builder().destroyTime(3.0f).pushReaction(PistonBehavior.DESTROY)
.enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
.enumState(DOUBLE_BLOCK_HALF) .enumState(DOUBLE_BLOCK_HALF)
.enumState(DOOR_HINGE) .enumState(DOOR_HINGE)
.booleanState(OPEN) .booleanState(OPEN)
.booleanState(POWERED))); .booleanState(POWERED)));
public static final Block WAXED_OXIDIZED_COPPER_DOOR = register(new DoorBlock("waxed_oxidized_copper_door", builder().requiresCorrectToolForDrops().destroyTime(3.0f).pushReaction(PistonBehavior.DESTROY) public static final Block WAXED_OXIDIZED_COPPER_DOOR = register(new DoorBlock("waxed_oxidized_copper_door", builder().destroyTime(3.0f).pushReaction(PistonBehavior.DESTROY)
.enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
.enumState(DOUBLE_BLOCK_HALF) .enumState(DOUBLE_BLOCK_HALF)
.enumState(DOOR_HINGE) .enumState(DOOR_HINGE)
.booleanState(OPEN) .booleanState(OPEN)
.booleanState(POWERED))); .booleanState(POWERED)));
public static final Block WAXED_WEATHERED_COPPER_DOOR = register(new DoorBlock("waxed_weathered_copper_door", builder().requiresCorrectToolForDrops().destroyTime(3.0f).pushReaction(PistonBehavior.DESTROY) public static final Block WAXED_WEATHERED_COPPER_DOOR = register(new DoorBlock("waxed_weathered_copper_door", builder().destroyTime(3.0f).pushReaction(PistonBehavior.DESTROY)
.enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST) .enumState(HORIZONTAL_FACING, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST)
.enumState(DOUBLE_BLOCK_HALF) .enumState(DOUBLE_BLOCK_HALF)
.enumState(DOOR_HINGE) .enumState(DOOR_HINGE)
@ -2888,8 +2915,12 @@ public final class Blocks {
.enumState(NORTH_WALL) .enumState(NORTH_WALL)
.enumState(SOUTH_WALL) .enumState(SOUTH_WALL)
.enumState(WEST_WALL))); .enumState(WEST_WALL)));
public static final Block PALE_HANGING_MOSS = register(new Block("pale_hanging_moss", builder().destroyTime(0.1f).pushReaction(PistonBehavior.DESTROY) public static final Block PALE_HANGING_MOSS = register(new Block("pale_hanging_moss", builder().pushReaction(PistonBehavior.DESTROY)
.booleanState(TIP))); .booleanState(TIP)));
public static final Block OPEN_EYEBLOSSOM = register(new Block("open_eyeblossom", builder().pushReaction(PistonBehavior.DESTROY)));
public static final Block CLOSED_EYEBLOSSOM = register(new Block("closed_eyeblossom", builder().pushReaction(PistonBehavior.DESTROY)));
public static final Block POTTED_OPEN_EYEBLOSSOM = register(new FlowerPotBlock("potted_open_eyeblossom", OPEN_EYEBLOSSOM, builder().pushReaction(PistonBehavior.DESTROY)));
public static final Block POTTED_CLOSED_EYEBLOSSOM = register(new FlowerPotBlock("potted_closed_eyeblossom", CLOSED_EYEBLOSSOM, builder().pushReaction(PistonBehavior.DESTROY)));
private static <T extends Block> T register(T block) { private static <T extends Block> T register(T block) {
block.setJavaId(BlockRegistries.JAVA_BLOCKS.get().size()); block.setJavaId(BlockRegistries.JAVA_BLOCKS.get().size());

View file

@ -29,8 +29,12 @@ import org.geysermc.geyser.level.physics.Axis;
import org.geysermc.geyser.level.physics.Direction; import org.geysermc.geyser.level.physics.Direction;
public final class Properties { public final class Properties {
public static final BooleanProperty ACTIVE = BooleanProperty.create("active");
public static final BooleanProperty ATTACHED = BooleanProperty.create("attached"); public static final BooleanProperty ATTACHED = BooleanProperty.create("attached");
public static final BooleanProperty BERRIES = BooleanProperty.create("berries");
public static final BooleanProperty BLOOM = BooleanProperty.create("bloom");
public static final BooleanProperty BOTTOM = BooleanProperty.create("bottom"); public static final BooleanProperty BOTTOM = BooleanProperty.create("bottom");
public static final BooleanProperty CAN_SUMMON = BooleanProperty.create("can_summon");
public static final BooleanProperty CONDITIONAL = BooleanProperty.create("conditional"); public static final BooleanProperty CONDITIONAL = BooleanProperty.create("conditional");
public static final BooleanProperty DISARMED = BooleanProperty.create("disarmed"); public static final BooleanProperty DISARMED = BooleanProperty.create("disarmed");
public static final BooleanProperty DRAG = BooleanProperty.create("drag"); public static final BooleanProperty DRAG = BooleanProperty.create("drag");
@ -47,22 +51,20 @@ public final class Properties {
public static final BooleanProperty INVERTED = BooleanProperty.create("inverted"); public static final BooleanProperty INVERTED = BooleanProperty.create("inverted");
public static final BooleanProperty IN_WALL = BooleanProperty.create("in_wall"); public static final BooleanProperty IN_WALL = BooleanProperty.create("in_wall");
public static final BooleanProperty LIT = BooleanProperty.create("lit"); public static final BooleanProperty LIT = BooleanProperty.create("lit");
public static final BooleanProperty TIP = BooleanProperty.create("tip");
public static final BooleanProperty LOCKED = BooleanProperty.create("locked"); public static final BooleanProperty LOCKED = BooleanProperty.create("locked");
public static final BooleanProperty NATURAL = BooleanProperty.create("natural");
public static final BooleanProperty OCCUPIED = BooleanProperty.create("occupied"); public static final BooleanProperty OCCUPIED = BooleanProperty.create("occupied");
public static final BooleanProperty OPEN = BooleanProperty.create("open"); public static final BooleanProperty OPEN = BooleanProperty.create("open");
public static final BooleanProperty PERSISTENT = BooleanProperty.create("persistent"); public static final BooleanProperty PERSISTENT = BooleanProperty.create("persistent");
public static final BooleanProperty POWERED = BooleanProperty.create("powered"); public static final BooleanProperty POWERED = BooleanProperty.create("powered");
public static final BooleanProperty SHORT = BooleanProperty.create("short"); public static final BooleanProperty SHORT = BooleanProperty.create("short");
public static final BooleanProperty SHRIEKING = BooleanProperty.create("shrieking");
public static final BooleanProperty SIGNAL_FIRE = BooleanProperty.create("signal_fire"); public static final BooleanProperty SIGNAL_FIRE = BooleanProperty.create("signal_fire");
public static final BooleanProperty SNOWY = BooleanProperty.create("snowy"); public static final BooleanProperty SNOWY = BooleanProperty.create("snowy");
public static final BooleanProperty TIP = BooleanProperty.create("tip");
public static final BooleanProperty TRIGGERED = BooleanProperty.create("triggered"); public static final BooleanProperty TRIGGERED = BooleanProperty.create("triggered");
public static final BooleanProperty UNSTABLE = BooleanProperty.create("unstable"); public static final BooleanProperty UNSTABLE = BooleanProperty.create("unstable");
public static final BooleanProperty WATERLOGGED = BooleanProperty.create("waterlogged"); public static final BooleanProperty WATERLOGGED = BooleanProperty.create("waterlogged");
public static final BooleanProperty BERRIES = BooleanProperty.create("berries");
public static final BooleanProperty BLOOM = BooleanProperty.create("bloom");
public static final BooleanProperty SHRIEKING = BooleanProperty.create("shrieking");
public static final BooleanProperty CAN_SUMMON = BooleanProperty.create("can_summon");
public static final EnumProperty<Axis> HORIZONTAL_AXIS = EnumProperty.create("axis", Axis.X, Axis.Z); public static final EnumProperty<Axis> HORIZONTAL_AXIS = EnumProperty.create("axis", Axis.X, Axis.Z);
public static final EnumProperty<Axis> AXIS = EnumProperty.create("axis", Axis.VALUES); public static final EnumProperty<Axis> AXIS = EnumProperty.create("axis", Axis.VALUES);
public static final BooleanProperty UP = BooleanProperty.create("up"); public static final BooleanProperty UP = BooleanProperty.create("up");
@ -143,6 +145,5 @@ public final class Properties {
public static final BooleanProperty CRAFTING = BooleanProperty.create("crafting"); public static final BooleanProperty CRAFTING = BooleanProperty.create("crafting");
public static final BasicEnumProperty TRIAL_SPAWNER_STATE = BasicEnumProperty.create("trial_spawner_state", "inactive", "waiting_for_players", "active", "waiting_for_reward_ejection", "ejecting_reward", "cooldown"); public static final BasicEnumProperty TRIAL_SPAWNER_STATE = BasicEnumProperty.create("trial_spawner_state", "inactive", "waiting_for_players", "active", "waiting_for_reward_ejection", "ejecting_reward", "cooldown");
public static final BasicEnumProperty VAULT_STATE = BasicEnumProperty.create("vault_state", "inactive", "active", "unlocking", "ejecting"); public static final BasicEnumProperty VAULT_STATE = BasicEnumProperty.create("vault_state", "inactive", "active", "unlocking", "ejecting");
public static final BasicEnumProperty CREAKING = BasicEnumProperty.create("creaking", "disabled", "dormant", "active");
public static final BooleanProperty OMINOUS = BooleanProperty.create("ominous"); public static final BooleanProperty OMINOUS = BooleanProperty.create("ominous");
} }

View file

@ -35,17 +35,11 @@ import org.cloudburstmc.protocol.bedrock.codec.v291.serializer.MoveEntityAbsolut
import org.cloudburstmc.protocol.bedrock.codec.v291.serializer.PlayerHotbarSerializer_v291; import org.cloudburstmc.protocol.bedrock.codec.v291.serializer.PlayerHotbarSerializer_v291;
import org.cloudburstmc.protocol.bedrock.codec.v291.serializer.SetEntityLinkSerializer_v291; import org.cloudburstmc.protocol.bedrock.codec.v291.serializer.SetEntityLinkSerializer_v291;
import org.cloudburstmc.protocol.bedrock.codec.v390.serializer.PlayerSkinSerializer_v390; import org.cloudburstmc.protocol.bedrock.codec.v390.serializer.PlayerSkinSerializer_v390;
import org.cloudburstmc.protocol.bedrock.codec.v407.serializer.InventoryContentSerializer_v407;
import org.cloudburstmc.protocol.bedrock.codec.v407.serializer.InventorySlotSerializer_v407;
import org.cloudburstmc.protocol.bedrock.codec.v419.serializer.MovePlayerSerializer_v419; import org.cloudburstmc.protocol.bedrock.codec.v419.serializer.MovePlayerSerializer_v419;
import org.cloudburstmc.protocol.bedrock.codec.v486.serializer.BossEventSerializer_v486; import org.cloudburstmc.protocol.bedrock.codec.v486.serializer.BossEventSerializer_v486;
import org.cloudburstmc.protocol.bedrock.codec.v557.serializer.SetEntityDataSerializer_v557; import org.cloudburstmc.protocol.bedrock.codec.v557.serializer.SetEntityDataSerializer_v557;
import org.cloudburstmc.protocol.bedrock.codec.v662.serializer.SetEntityMotionSerializer_v662; import org.cloudburstmc.protocol.bedrock.codec.v662.serializer.SetEntityMotionSerializer_v662;
import org.cloudburstmc.protocol.bedrock.codec.v712.serializer.InventoryContentSerializer_v712;
import org.cloudburstmc.protocol.bedrock.codec.v712.serializer.InventorySlotSerializer_v712;
import org.cloudburstmc.protocol.bedrock.codec.v712.serializer.MobArmorEquipmentSerializer_v712; import org.cloudburstmc.protocol.bedrock.codec.v712.serializer.MobArmorEquipmentSerializer_v712;
import org.cloudburstmc.protocol.bedrock.codec.v729.serializer.InventoryContentSerializer_v729;
import org.cloudburstmc.protocol.bedrock.codec.v729.serializer.InventorySlotSerializer_v729;
import org.cloudburstmc.protocol.bedrock.codec.v748.serializer.InventoryContentSerializer_v748; 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.codec.v748.serializer.InventorySlotSerializer_v748;
import org.cloudburstmc.protocol.bedrock.packet.AnvilDamagePacket; import org.cloudburstmc.protocol.bedrock.packet.AnvilDamagePacket;
@ -89,12 +83,12 @@ import org.cloudburstmc.protocol.bedrock.packet.SettingsCommandPacket;
import org.cloudburstmc.protocol.bedrock.packet.SimpleEventPacket; import org.cloudburstmc.protocol.bedrock.packet.SimpleEventPacket;
import org.cloudburstmc.protocol.bedrock.packet.SubChunkRequestPacket; import org.cloudburstmc.protocol.bedrock.packet.SubChunkRequestPacket;
import org.cloudburstmc.protocol.bedrock.packet.SubClientLoginPacket; import org.cloudburstmc.protocol.bedrock.packet.SubClientLoginPacket;
import org.cloudburstmc.protocol.bedrock.packet.TickSyncPacket;
import org.cloudburstmc.protocol.common.util.VarInts; import org.cloudburstmc.protocol.common.util.VarInts;
/** /**
* Processes the Bedrock codec to remove or modify unused or unsafe packets and fields. * Processes the Bedrock codec to remove or modify unused or unsafe packets and fields.
*/ */
@SuppressWarnings("deprecation")
class CodecProcessor { class CodecProcessor {
/** /**
@ -126,27 +120,9 @@ class CodecProcessor {
public void deserialize(ByteBuf buffer, BedrockCodecHelper helper, BedrockPacket packet) { public void deserialize(ByteBuf buffer, BedrockCodecHelper helper, BedrockPacket packet) {
} }
}; };
/** /**
* Serializer that throws an exception when trying to deserialize InventoryContentPacket since server-auth inventory is used. * Serializer that throws an exception when trying to deserialize InventoryContentPacket since server-auth inventory is used.
*/ */
private static final BedrockPacketSerializer<InventoryContentPacket> INVENTORY_CONTENT_SERIALIZER_V407 = new InventoryContentSerializer_v407() {
@Override
public void deserialize(ByteBuf buffer, BedrockCodecHelper helper, InventoryContentPacket packet) {
throw new IllegalArgumentException("Client cannot send InventoryContentPacket in server-auth inventory environment!");
}
};
/**
* Serializer that throws an exception when trying to deserialize InventoryContentPacket since server-auth inventory is used.
*/
private static final BedrockPacketSerializer<InventoryContentPacket> INVENTORY_CONTENT_SERIALIZER_V712 = new InventoryContentSerializer_v712() {
@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_V748 = new InventoryContentSerializer_v748() { private static final BedrockPacketSerializer<InventoryContentPacket> INVENTORY_CONTENT_SERIALIZER_V748 = new InventoryContentSerializer_v748() {
@Override @Override
public void deserialize(ByteBuf buffer, BedrockCodecHelper helper, InventoryContentPacket packet) { public void deserialize(ByteBuf buffer, BedrockCodecHelper helper, InventoryContentPacket packet) {
@ -154,40 +130,9 @@ class CodecProcessor {
} }
}; };
private static final BedrockPacketSerializer<InventoryContentPacket> INVENTORY_CONTENT_SERIALIZER_V729 = new InventoryContentSerializer_v729() {
@Override
public void deserialize(ByteBuf buffer, BedrockCodecHelper helper, InventoryContentPacket packet) {
throw new IllegalArgumentException("Client cannot send InventoryContentPacket in server-auth inventory environment!");
}
};
/**
* Serializer that throws an exception when trying to deserialize InventorySlotPacket since server-auth inventory is used.
*/
private static final BedrockPacketSerializer<InventorySlotPacket> INVENTORY_SLOT_SERIALIZER_V407 = new InventorySlotSerializer_v407() {
@Override
public void deserialize(ByteBuf buffer, BedrockCodecHelper helper, InventorySlotPacket packet) {
throw new IllegalArgumentException("Client cannot send InventorySlotPacket in server-auth inventory environment!");
}
};
/* /*
* Serializer that throws an exception when trying to deserialize InventorySlotPacket since server-auth inventory is used. * Serializer that throws an exception when trying to deserialize InventorySlotPacket since server-auth inventory is used.
*/ */
private static final BedrockPacketSerializer<InventorySlotPacket> INVENTORY_SLOT_SERIALIZER_V712 = new InventorySlotSerializer_v712() {
@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<InventorySlotPacket> INVENTORY_SLOT_SERIALIZER_V729 = new InventorySlotSerializer_v729() {
@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<InventorySlotPacket> INVENTORY_SLOT_SERIALIZER_V748 = new InventorySlotSerializer_v748() { private static final BedrockPacketSerializer<InventorySlotPacket> INVENTORY_SLOT_SERIALIZER_V748 = new InventorySlotSerializer_v748() {
@Override @Override
public void deserialize(ByteBuf buffer, BedrockCodecHelper helper, InventorySlotPacket packet) { public void deserialize(ByteBuf buffer, BedrockCodecHelper helper, InventorySlotPacket packet) {
@ -297,32 +242,6 @@ class CodecProcessor {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
static BedrockCodec processCodec(BedrockCodec codec) { static BedrockCodec processCodec(BedrockCodec codec) {
boolean is748OrAbove = codec.getProtocolVersion() >= 748;
boolean is729OrAbove = codec.getProtocolVersion() >= 729;
boolean is712OrAbove = codec.getProtocolVersion() >= 712;
BedrockPacketSerializer<InventoryContentPacket> inventoryContentSerializer;
if (is748OrAbove) {
inventoryContentSerializer = INVENTORY_CONTENT_SERIALIZER_V748;
} else if (is729OrAbove) {
inventoryContentSerializer = INVENTORY_CONTENT_SERIALIZER_V729;
} else if (is712OrAbove) {
inventoryContentSerializer = INVENTORY_CONTENT_SERIALIZER_V712;
} else {
inventoryContentSerializer = INVENTORY_CONTENT_SERIALIZER_V407;
}
BedrockPacketSerializer<InventorySlotPacket> inventorySlotSerializer;
if (is748OrAbove) {
inventorySlotSerializer = INVENTORY_SLOT_SERIALIZER_V748;
} else if (is729OrAbove) {
inventorySlotSerializer = INVENTORY_SLOT_SERIALIZER_V729;
} else if (is712OrAbove) {
inventorySlotSerializer = INVENTORY_SLOT_SERIALIZER_V712;
} else {
inventorySlotSerializer = INVENTORY_SLOT_SERIALIZER_V407;
}
BedrockCodec.Builder codecBuilder = codec.toBuilder() BedrockCodec.Builder codecBuilder = codec.toBuilder()
// Illegal unused serverbound EDU packets // Illegal unused serverbound EDU packets
.updateSerializer(PhotoTransferPacket.class, ILLEGAL_SERIALIZER) .updateSerializer(PhotoTransferPacket.class, ILLEGAL_SERIALIZER)
@ -350,15 +269,15 @@ class CodecProcessor {
.updateSerializer(AnvilDamagePacket.class, IGNORED_SERIALIZER) .updateSerializer(AnvilDamagePacket.class, IGNORED_SERIALIZER)
.updateSerializer(RefreshEntitlementsPacket.class, IGNORED_SERIALIZER) .updateSerializer(RefreshEntitlementsPacket.class, IGNORED_SERIALIZER)
// Illegal when serverbound due to Geyser specific setup // Illegal when serverbound due to Geyser specific setup
.updateSerializer(InventoryContentPacket.class, inventoryContentSerializer) .updateSerializer(InventoryContentPacket.class, INVENTORY_CONTENT_SERIALIZER_V748)
.updateSerializer(InventorySlotPacket.class, inventorySlotSerializer) .updateSerializer(InventorySlotPacket.class, INVENTORY_SLOT_SERIALIZER_V748)
.updateSerializer(MovePlayerPacket.class, MOVE_PLAYER_SERIALIZER) .updateSerializer(MovePlayerPacket.class, MOVE_PLAYER_SERIALIZER)
.updateSerializer(MoveEntityAbsolutePacket.class, MOVE_ENTITY_SERIALIZER) .updateSerializer(MoveEntityAbsolutePacket.class, MOVE_ENTITY_SERIALIZER)
.updateSerializer(RiderJumpPacket.class, ILLEGAL_SERIALIZER) .updateSerializer(RiderJumpPacket.class, ILLEGAL_SERIALIZER)
.updateSerializer(PlayerInputPacket.class, ILLEGAL_SERIALIZER) .updateSerializer(PlayerInputPacket.class, ILLEGAL_SERIALIZER)
// Ignored only when serverbound // Ignored only when serverbound
.updateSerializer(BossEventPacket.class, BOSS_EVENT_SERIALIZER) .updateSerializer(BossEventPacket.class, BOSS_EVENT_SERIALIZER)
.updateSerializer(MobArmorEquipmentPacket.class, is712OrAbove ? MOB_ARMOR_EQUIPMENT_SERIALIZER_V712 : MOB_ARMOR_EQUIPMENT_SERIALIZER_V291) .updateSerializer(MobArmorEquipmentPacket.class, MOB_ARMOR_EQUIPMENT_SERIALIZER_V712)
.updateSerializer(PlayerHotbarPacket.class, PLAYER_HOTBAR_SERIALIZER) .updateSerializer(PlayerHotbarPacket.class, PLAYER_HOTBAR_SERIALIZER)
.updateSerializer(PlayerSkinPacket.class, PLAYER_SKIN_SERIALIZER) .updateSerializer(PlayerSkinPacket.class, PLAYER_SKIN_SERIALIZER)
.updateSerializer(SetEntityDataPacket.class, SET_ENTITY_DATA_SERIALIZER) .updateSerializer(SetEntityDataPacket.class, SET_ENTITY_DATA_SERIALIZER)
@ -375,11 +294,6 @@ class CodecProcessor {
.updateSerializer(SimpleEventPacket.class, IGNORED_SERIALIZER) .updateSerializer(SimpleEventPacket.class, IGNORED_SERIALIZER)
.updateSerializer(MultiplayerSettingsPacket.class, IGNORED_SERIALIZER); .updateSerializer(MultiplayerSettingsPacket.class, IGNORED_SERIALIZER);
if (codec.getProtocolVersion() < 685) {
// Ignored bidirectional packets
codecBuilder.updateSerializer(TickSyncPacket.class, IGNORED_SERIALIZER);
}
return codecBuilder.build(); return codecBuilder.build();
} }

View file

@ -30,6 +30,7 @@ import org.cloudburstmc.protocol.bedrock.codec.BedrockCodec;
import org.cloudburstmc.protocol.bedrock.codec.v748.Bedrock_v748; import org.cloudburstmc.protocol.bedrock.codec.v748.Bedrock_v748;
import org.cloudburstmc.protocol.bedrock.codec.v766.Bedrock_v766; import org.cloudburstmc.protocol.bedrock.codec.v766.Bedrock_v766;
import org.cloudburstmc.protocol.bedrock.netty.codec.packet.BedrockPacketCodec; import org.cloudburstmc.protocol.bedrock.netty.codec.packet.BedrockPacketCodec;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.mcprotocollib.protocol.codec.MinecraftCodec; import org.geysermc.mcprotocollib.protocol.codec.MinecraftCodec;
import org.geysermc.mcprotocollib.protocol.codec.PacketCodec; import org.geysermc.mcprotocollib.protocol.codec.PacketCodec;
@ -47,7 +48,7 @@ public final class GameProtocol {
* release of the game that Geyser supports. * release of the game that Geyser supports.
*/ */
public static final BedrockCodec DEFAULT_BEDROCK_CODEC = CodecProcessor.processCodec(Bedrock_v766.CODEC.toBuilder() public static final BedrockCodec DEFAULT_BEDROCK_CODEC = CodecProcessor.processCodec(Bedrock_v766.CODEC.toBuilder()
.minecraftVersion("1.21.50") .minecraftVersion("1.21.51")
.build()); .build());
/** /**
@ -65,7 +66,9 @@ public final class GameProtocol {
SUPPORTED_BEDROCK_CODECS.add(CodecProcessor.processCodec(Bedrock_v748.CODEC.toBuilder() SUPPORTED_BEDROCK_CODECS.add(CodecProcessor.processCodec(Bedrock_v748.CODEC.toBuilder()
.minecraftVersion("1.21.40 - 1.21.44") .minecraftVersion("1.21.40 - 1.21.44")
.build())); .build()));
SUPPORTED_BEDROCK_CODECS.add(DEFAULT_BEDROCK_CODEC); SUPPORTED_BEDROCK_CODECS.add(DEFAULT_BEDROCK_CODEC.toBuilder()
.minecraftVersion("1.21.50 - 1.21.51")
.build());
} }
/** /**
@ -84,6 +87,10 @@ public final class GameProtocol {
/* Bedrock convenience methods to gatekeep features and easily remove the check on version removal */ /* Bedrock convenience methods to gatekeep features and easily remove the check on version removal */
public static boolean isPreWinterDrop(GeyserSession session) {
return session.getUpstream().getProtocolVersion() == Bedrock_v748.CODEC.getProtocolVersion();
}
/** /**
* Gets the {@link PacketCodec} for Minecraft: Java Edition. * Gets the {@link PacketCodec} for Minecraft: Java Edition.
* *

View file

@ -30,7 +30,6 @@ import org.cloudburstmc.math.vector.Vector2f;
import org.cloudburstmc.protocol.bedrock.BedrockDisconnectReasons; import org.cloudburstmc.protocol.bedrock.BedrockDisconnectReasons;
import org.cloudburstmc.protocol.bedrock.codec.BedrockCodec; import org.cloudburstmc.protocol.bedrock.codec.BedrockCodec;
import org.cloudburstmc.protocol.bedrock.codec.compat.BedrockCompat; import org.cloudburstmc.protocol.bedrock.codec.compat.BedrockCompat;
import org.cloudburstmc.protocol.bedrock.data.ExperimentData;
import org.cloudburstmc.protocol.bedrock.data.PacketCompressionAlgorithm; import org.cloudburstmc.protocol.bedrock.data.PacketCompressionAlgorithm;
import org.cloudburstmc.protocol.bedrock.data.ResourcePackType; import org.cloudburstmc.protocol.bedrock.data.ResourcePackType;
import org.cloudburstmc.protocol.bedrock.netty.codec.compression.CompressionStrategy; import org.cloudburstmc.protocol.bedrock.netty.codec.compression.CompressionStrategy;
@ -249,14 +248,6 @@ public class UpstreamPacketHandler extends LoggingPacketHandler {
stackPacket.getResourcePacks().add(new ResourcePackStackPacket.Entry(header.uuid().toString(), header.version().toString(), "")); stackPacket.getResourcePacks().add(new ResourcePackStackPacket.Entry(header.uuid().toString(), header.version().toString(), ""));
} }
if (GeyserImpl.getInstance().getConfig().isAddNonBedrockItems()) {
// Allow custom items to work
stackPacket.getExperiments().add(new ExperimentData("data_driven_items", true));
}
// Required for experimental 1.21 features
stackPacket.getExperiments().add(new ExperimentData("updateAnnouncedLive2023", true));
session.sendUpstreamPacket(stackPacket); session.sendUpstreamPacket(stackPacket);
break; break;

View file

@ -47,6 +47,7 @@ import org.geysermc.geyser.registry.loader.RegistryLoaders;
import org.geysermc.geyser.registry.loader.SoundEventsRegistryLoader; import org.geysermc.geyser.registry.loader.SoundEventsRegistryLoader;
import org.geysermc.geyser.registry.loader.SoundRegistryLoader; import org.geysermc.geyser.registry.loader.SoundRegistryLoader;
import org.geysermc.geyser.registry.loader.SoundTranslatorRegistryLoader; import org.geysermc.geyser.registry.loader.SoundTranslatorRegistryLoader;
import org.geysermc.geyser.registry.populator.DataComponentRegistryPopulator;
import org.geysermc.geyser.registry.populator.ItemRegistryPopulator; import org.geysermc.geyser.registry.populator.ItemRegistryPopulator;
import org.geysermc.geyser.registry.populator.PacketRegistryPopulator; import org.geysermc.geyser.registry.populator.PacketRegistryPopulator;
import org.geysermc.geyser.registry.populator.TagRegistryPopulator; import org.geysermc.geyser.registry.populator.TagRegistryPopulator;
@ -60,6 +61,7 @@ import org.geysermc.geyser.translator.sound.SoundInteractionTranslator;
import org.geysermc.geyser.translator.sound.SoundTranslator; import org.geysermc.geyser.translator.sound.SoundTranslator;
import org.geysermc.mcprotocollib.network.packet.Packet; import org.geysermc.mcprotocollib.network.packet.Packet;
import org.geysermc.mcprotocollib.protocol.data.game.entity.type.EntityType; import org.geysermc.mcprotocollib.protocol.data.game.entity.type.EntityType;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents;
import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType; import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType;
import org.geysermc.mcprotocollib.protocol.data.game.level.event.LevelEvent; import org.geysermc.mcprotocollib.protocol.data.game.level.event.LevelEvent;
import org.geysermc.mcprotocollib.protocol.data.game.level.particle.ParticleType; import org.geysermc.mcprotocollib.protocol.data.game.level.particle.ParticleType;
@ -139,6 +141,8 @@ public final class Registries {
*/ */
public static final SimpleMappedRegistry<String, Item> JAVA_ITEM_IDENTIFIERS = SimpleMappedRegistry.create(RegistryLoaders.empty(Object2ObjectOpenHashMap::new)); public static final SimpleMappedRegistry<String, Item> JAVA_ITEM_IDENTIFIERS = SimpleMappedRegistry.create(RegistryLoaders.empty(Object2ObjectOpenHashMap::new));
public static final ListRegistry<DataComponents> DEFAULT_DATA_COMPONENTS = ListRegistry.create(RegistryLoaders.empty(ArrayList::new));
/** /**
* A versioned registry which holds {@link ItemMappings} for each version. These item mappings contain * A versioned registry which holds {@link ItemMappings} for each version. These item mappings contain
* primarily Bedrock version-specific data. * primarily Bedrock version-specific data.
@ -209,6 +213,7 @@ public final class Registries {
public static void populate() { public static void populate() {
PacketRegistryPopulator.populate(); PacketRegistryPopulator.populate();
DataComponentRegistryPopulator.populate();
ItemRegistryPopulator.populate(); ItemRegistryPopulator.populate();
TagRegistryPopulator.populate(); TagRegistryPopulator.populate();

View file

@ -58,7 +58,6 @@ import org.geysermc.geyser.level.block.property.Properties;
import org.geysermc.geyser.level.block.type.Block; import org.geysermc.geyser.level.block.type.Block;
import org.geysermc.geyser.level.block.type.BlockState; import org.geysermc.geyser.level.block.type.BlockState;
import org.geysermc.geyser.level.block.type.FlowerPotBlock; import org.geysermc.geyser.level.block.type.FlowerPotBlock;
import org.geysermc.geyser.level.block.type.SkullBlock;
import org.geysermc.geyser.level.physics.PistonBehavior; import org.geysermc.geyser.level.physics.PistonBehavior;
import org.geysermc.geyser.registry.BlockRegistries; import org.geysermc.geyser.registry.BlockRegistries;
import org.geysermc.geyser.registry.Registries; import org.geysermc.geyser.registry.Registries;
@ -66,7 +65,6 @@ import org.geysermc.geyser.registry.type.BlockMappings;
import org.geysermc.geyser.registry.type.GeyserBedrockBlock; import org.geysermc.geyser.registry.type.GeyserBedrockBlock;
import org.geysermc.geyser.util.BlockUtils; import org.geysermc.geyser.util.BlockUtils;
import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack; import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack;
import org.jetbrains.annotations.NotNull;
import java.io.DataInputStream; import java.io.DataInputStream;
import java.io.InputStream; import java.io.InputStream;
@ -125,8 +123,8 @@ public final class BlockRegistryPopulator {
private static void registerBedrockBlocks() { private static void registerBedrockBlocks() {
var blockMappers = ImmutableMap.<ObjectIntPair<String>, Remapper>builder() var blockMappers = ImmutableMap.<ObjectIntPair<String>, Remapper>builder()
.put(ObjectIntPair.of("1_21_40", Bedrock_v748.CODEC.getProtocolVersion()), faultyStrippedWoodRemapper()) .put(ObjectIntPair.of("1_21_40", Bedrock_v748.CODEC.getProtocolVersion()), Conversion766_748::remapBlock)
.put(ObjectIntPair.of("1_21_50", Bedrock_v766.CODEC.getProtocolVersion()), faultyStrippedWoodRemapper()) .put(ObjectIntPair.of("1_21_50", Bedrock_v766.CODEC.getProtocolVersion()), tag -> tag)
.build(); .build();
// We can keep this strong as nothing should be garbage collected // We can keep this strong as nothing should be garbage collected
@ -259,15 +257,6 @@ public final class BlockRegistryPopulator {
NbtMap originalBedrockTag = buildBedrockState(blockState, entry); NbtMap originalBedrockTag = buildBedrockState(blockState, entry);
NbtMap bedrockTag = stateMapper.remap(originalBedrockTag); NbtMap bedrockTag = stateMapper.remap(originalBedrockTag);
// FIXME TEMPORARY
if (blockState.block() instanceof SkullBlock && palette.valueInt() >= Bedrock_v748.CODEC.getProtocolVersion()) {
// The flattening must be a very interesting process.
String skullName = blockState.block().javaIdentifier().asString().replace("_wall", "");
bedrockTag = bedrockTag.toBuilder()
.putString("name", skullName)
.build();
}
GeyserBedrockBlock vanillaBedrockDefinition = blockStateOrderedMap.get(bedrockTag); GeyserBedrockBlock vanillaBedrockDefinition = blockStateOrderedMap.get(bedrockTag);
GeyserBedrockBlock bedrockDefinition; GeyserBedrockBlock bedrockDefinition;
@ -413,19 +402,6 @@ public final class BlockRegistryPopulator {
} }
} }
private static @NotNull Remapper faultyStrippedWoodRemapper() {
return tag -> {
final String name = tag.getString("name");
if (name.endsWith("_wood") && tag.getCompound("states").containsKey("stripped_bit")) {
NbtMapBuilder builder = tag.getCompound("states").toBuilder();
builder.remove("stripped_bit");
NbtMap states = builder.build();
return tag.toBuilder().putCompound("states", states).build();
}
return tag;
};
}
private static void registerJavaBlocks() { private static void registerJavaBlocks() {
List<NbtMap> blocksNbt; List<NbtMap> blocksNbt;
try (InputStream stream = GeyserImpl.getInstance().getBootstrap().getResourceOrThrow("mappings/blocks.nbt")) { try (InputStream stream = GeyserImpl.getInstance().getBootstrap().getResourceOrThrow("mappings/blocks.nbt")) {

View file

@ -1,48 +0,0 @@
/*
* 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.populator;
import org.geysermc.geyser.item.type.Item;
import org.geysermc.geyser.registry.type.GeyserMappingItem;
import java.util.Map;
public class Conversion748_729 {
private static final Map<String, Integer> NEW_PLAYER_HEADS = Map.of("minecraft:skeleton_skull", 0, "minecraft:wither_skeleton_skull", 1, "minecraft:zombie_head", 2, "minecraft:player_head", 3, "minecraft:creeper_head", 4, "minecraft:dragon_head", 5, "minecraft:piglin_head", 6);
static GeyserMappingItem remapItem(Item item, GeyserMappingItem mapping) {
String identifier = mapping.getBedrockIdentifier();
if (NEW_PLAYER_HEADS.containsKey(identifier)) {
return mapping.withBedrockIdentifier("minecraft:skull")
.withBedrockData(NEW_PLAYER_HEADS.get(identifier));
}
return mapping;
}
}

View file

@ -0,0 +1,128 @@
/*
* 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.populator;
import org.cloudburstmc.nbt.NbtMap;
import org.cloudburstmc.nbt.NbtMapBuilder;
import org.geysermc.geyser.level.block.Blocks;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
public class Conversion766_748 {
static List<String> PALE_WOODEN_BLOCKS = new ArrayList<>();
static List<String> OTHER_NEW_BLOCKS = new ArrayList<>();
static {
Set.of(
Blocks.PALE_OAK_WOOD,
Blocks.PALE_OAK_PLANKS,
Blocks.PALE_OAK_SAPLING,
Blocks.PALE_OAK_LOG,
Blocks.STRIPPED_PALE_OAK_LOG,
Blocks.STRIPPED_PALE_OAK_WOOD,
Blocks.PALE_OAK_LEAVES,
Blocks.PALE_OAK_HANGING_SIGN,
Blocks.PALE_OAK_PRESSURE_PLATE,
Blocks.PALE_OAK_TRAPDOOR,
Blocks.PALE_OAK_BUTTON,
Blocks.PALE_OAK_STAIRS,
Blocks.PALE_OAK_SLAB,
Blocks.PALE_OAK_FENCE_GATE,
Blocks.PALE_OAK_FENCE,
Blocks.PALE_OAK_DOOR
).forEach(block -> PALE_WOODEN_BLOCKS.add(block.javaIdentifier().value()));
// Some things are of course stupid
PALE_WOODEN_BLOCKS.add("pale_oak_standing_sign");
PALE_WOODEN_BLOCKS.add("pale_oak_wall_sign");
PALE_WOODEN_BLOCKS.add("pale_oak_double_slab");
Set.of(
Blocks.PALE_MOSS_BLOCK,
Blocks.PALE_MOSS_CARPET,
Blocks.PALE_HANGING_MOSS,
Blocks.OPEN_EYEBLOSSOM,
Blocks.CLOSED_EYEBLOSSOM,
Blocks.RESIN_CLUMP,
Blocks.RESIN_BLOCK,
Blocks.RESIN_BRICKS,
Blocks.RESIN_BRICK_STAIRS,
Blocks.RESIN_BRICK_SLAB,
Blocks.RESIN_BRICK_WALL,
Blocks.CHISELED_RESIN_BRICKS,
Blocks.CREAKING_HEART
).forEach(block -> OTHER_NEW_BLOCKS.add(block.javaIdentifier().value()));
OTHER_NEW_BLOCKS.add("resin_brick_double_slab");
}
static NbtMap remapBlock(NbtMap tag) {
String name = tag.getString("name").replace("minecraft:", "");
if (PALE_WOODEN_BLOCKS.contains(name)) {
return withName(tag, name.replace("pale_oak", "birch"));
}
if (OTHER_NEW_BLOCKS.contains(name)) {
return switch (name) {
case "resin_brick_double_slab" -> withName(tag,"red_sandstone_double_slab");
case "pale_moss_block" -> withName(tag, "moss_block");
case "pale_moss_carpet" -> withoutStates("moss_carpet");
case "pale_hanging_moss" -> withoutStates("hanging_roots");
case "open_eyeblossom" -> withoutStates("oxeye_daisy");
case "closed_eyeblossom" -> withoutStates("white_tulip");
case "resin_clump" -> withoutStates("unknown");
case "resin_block" -> withoutStates("red_sandstone");
case "resin_bricks" -> withoutStates("cut_red_sandstone");
case "resin_brick_stairs" -> withName(tag, "red_sandstone_stairs");
case "resin_brick_slab" -> withName(tag, "red_sandstone_slab");
case "resin_brick_wall" -> withName(tag, "red_sandstone_wall");
case "chiseled_resin_bricks" -> withName(tag, "chiseled_red_sandstone");
case "creaking_heart" -> withoutStates("chiseled_polished_blackstone");
default -> throw new IllegalStateException("missing replacement for new block! " + name);
};
}
return tag;
}
static NbtMap withName(NbtMap tag, String name) {
NbtMapBuilder builder = tag.toBuilder();
builder.replace("name", "minecraft:" + name);
return builder.build();
}
static NbtMap withoutStates(String name) {
NbtMapBuilder tagBuilder = NbtMap.builder();
tagBuilder.putString("name", "minecraft:" + name);
tagBuilder.putCompound("states", NbtMap.builder().build());
return tagBuilder.build();
}
}

View file

@ -48,8 +48,16 @@ import org.geysermc.geyser.registry.mappings.MappingsConfigReader;
import org.geysermc.geyser.registry.type.GeyserMappingItem; import org.geysermc.geyser.registry.type.GeyserMappingItem;
import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.registry.type.NonVanillaItemRegistration; import org.geysermc.geyser.registry.type.NonVanillaItemRegistration;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents;
import java.util.*; import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
public class CustomItemRegistryPopulator { public class CustomItemRegistryPopulator {
public static void populate(Map<String, GeyserMappingItem> items, Multimap<String, CustomItemData> customItems, List<NonVanillaCustomItemData> nonVanillaCustomItems) { public static void populate(Map<String, GeyserMappingItem> items, Multimap<String, CustomItemData> customItems, List<NonVanillaCustomItemData> nonVanillaCustomItems) {
@ -127,17 +135,11 @@ public class CustomItemRegistryPopulator {
public static NonVanillaItemRegistration registerCustomItem(NonVanillaCustomItemData customItemData, int customItemId, int protocolVersion) { public static NonVanillaItemRegistration registerCustomItem(NonVanillaCustomItemData customItemData, int customItemId, int protocolVersion) {
String customIdentifier = customItemData.identifier(); String customIdentifier = customItemData.identifier();
Set<String> repairMaterials = customItemData.repairMaterials(); DataComponents components = new DataComponents(new HashMap<>());
components.put(DataComponentType.MAX_STACK_SIZE, customItemData.stackSize());
components.put(DataComponentType.MAX_DAMAGE, customItemData.maxDamage());
Item.Builder itemBuilder = Item.builder() Item item = new Item(customIdentifier, Item.builder().components(components));
.stackSize(customItemData.stackSize())
.maxDamage(customItemData.maxDamage());
Item item = new Item(customIdentifier, itemBuilder) {
@Override
public boolean isValidRepairItem(Item other) {
return repairMaterials != null && repairMaterials.contains(other.javaIdentifier());
}
};
Items.register(item, customItemData.javaId()); Items.register(item, customItemData.javaId());
ItemMapping customItemMapping = ItemMapping.builder() ItemMapping customItemMapping = ItemMapping.builder()
@ -145,7 +147,6 @@ public class CustomItemRegistryPopulator {
.bedrockData(0) .bedrockData(0)
.bedrockBlockDefinition(null) .bedrockBlockDefinition(null)
.toolType(customItemData.toolType()) .toolType(customItemData.toolType())
.toolTier(customItemData.toolTier())
.translationString(customItemData.translationString()) .translationString(customItemData.translationString())
.customItemOptions(Collections.emptyList()) .customItemOptions(Collections.emptyList())
.javaItem(item) .javaItem(item)
@ -167,11 +168,11 @@ public class CustomItemRegistryPopulator {
NbtMapBuilder itemProperties = NbtMap.builder(); NbtMapBuilder itemProperties = NbtMap.builder();
NbtMapBuilder componentBuilder = NbtMap.builder(); NbtMapBuilder componentBuilder = NbtMap.builder();
setupBasicItemInfo(javaItem.maxDamage(), javaItem.maxStackSize(), mapping.getToolType() != null || customItemData.displayHandheld(), customItemData, itemProperties, componentBuilder, protocolVersion); setupBasicItemInfo(javaItem.defaultMaxDamage(), javaItem.defaultMaxStackSize(), mapping.getToolType() != null || customItemData.displayHandheld(), customItemData, itemProperties, componentBuilder, protocolVersion);
boolean canDestroyInCreative = true; boolean canDestroyInCreative = true;
if (mapping.getToolType() != null) { // This is not using the isTool boolean because it is not just a render type here. if (mapping.getToolType() != null) { // This is not using the isTool boolean because it is not just a render type here.
canDestroyInCreative = computeToolProperties(mapping.getToolType(), itemProperties, componentBuilder, javaItem.attackDamage()); canDestroyInCreative = computeToolProperties(mapping.getToolType(), itemProperties, componentBuilder, javaItem.defaultAttackDamage());
} }
itemProperties.putBoolean("can_destroy_in_creative", canDestroyInCreative); itemProperties.putBoolean("can_destroy_in_creative", canDestroyInCreative);

View file

@ -0,0 +1,89 @@
/*
* 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.populator;
import com.google.common.collect.ImmutableMap;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import org.geysermc.geyser.GeyserBootstrap;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.registry.Registries;
import org.geysermc.mcprotocollib.protocol.codec.MinecraftCodecHelper;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponent;
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.ItemCodecHelper;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Base64;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public final class DataComponentRegistryPopulator {
public static void populate() {
GeyserBootstrap bootstrap = GeyserImpl.getInstance().getBootstrap();
List<DataComponents> defaultComponents;
try (InputStream stream = bootstrap.getResourceOrThrow("java/item_data_components.json")) {
JsonElement rootElement = JsonParser.parseReader(new InputStreamReader(stream));
JsonArray jsonArray = rootElement.getAsJsonArray();
defaultComponents = new ObjectArrayList<>(jsonArray.size());
for (JsonElement element : jsonArray) {
JsonObject entryObject = element.getAsJsonObject();
JsonObject components = entryObject.getAsJsonObject("components");
Map<DataComponentType<?>, DataComponent<?, ?>> map = new HashMap<>();
for (Map.Entry<String, JsonElement> componentEntry : components.entrySet()) {
String encodedValue = componentEntry.getValue().getAsString();
byte[] bytes = Base64.getDecoder().decode(encodedValue);
ByteBuf buf = Unpooled.wrappedBuffer(bytes);
MinecraftCodecHelper helper = new MinecraftCodecHelper();
int varInt = helper.readVarInt(buf);
DataComponentType<?> dataComponentType = DataComponentType.from(varInt);
DataComponent<?, ?> dataComponent = dataComponentType.readDataComponent(ItemCodecHelper.INSTANCE, buf);
map.put(dataComponentType, dataComponent);
}
defaultComponents.add(new DataComponents(ImmutableMap.copyOf(map)));
}
} catch (Exception e) {
throw new AssertionError("Unable to load or parse components", e);
}
Registries.DEFAULT_DATA_COMPONENTS.set(defaultComponents);
}
}

View file

@ -82,6 +82,7 @@ import java.io.InputStream;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;
@ -107,8 +108,44 @@ public class ItemRegistryPopulator {
} }
public static void populate() { public static void populate() {
Map<Item, Item> itemFallbacks = new HashMap<>();
itemFallbacks.put(Items.PALE_OAK_PLANKS, Items.BIRCH_PLANKS);
itemFallbacks.put(Items.PALE_OAK_FENCE, Items.BIRCH_FENCE);
itemFallbacks.put(Items.PALE_OAK_FENCE_GATE, Items.BIRCH_FENCE_GATE);
itemFallbacks.put(Items.PALE_OAK_STAIRS, Items.BIRCH_STAIRS);
itemFallbacks.put(Items.PALE_OAK_DOOR, Items.BIRCH_DOOR);
itemFallbacks.put(Items.PALE_OAK_TRAPDOOR, Items.BIRCH_TRAPDOOR);
itemFallbacks.put(Items.PALE_OAK_SLAB, Items.BIRCH_SLAB);
itemFallbacks.put(Items.PALE_OAK_LOG, Items.BIRCH_LOG);
itemFallbacks.put(Items.STRIPPED_PALE_OAK_LOG, Items.STRIPPED_BIRCH_LOG);
itemFallbacks.put(Items.PALE_OAK_WOOD, Items.BIRCH_WOOD);
itemFallbacks.put(Items.PALE_OAK_LEAVES, Items.BIRCH_LEAVES);
itemFallbacks.put(Items.PALE_OAK_SAPLING, Items.BIRCH_SAPLING);
itemFallbacks.put(Items.STRIPPED_PALE_OAK_WOOD, Items.STRIPPED_BIRCH_WOOD);
itemFallbacks.put(Items.PALE_OAK_SIGN, Items.BIRCH_SIGN);
itemFallbacks.put(Items.PALE_OAK_HANGING_SIGN, Items.BIRCH_HANGING_SIGN);
itemFallbacks.put(Items.PALE_OAK_BOAT, Items.BIRCH_BOAT);
itemFallbacks.put(Items.PALE_OAK_CHEST_BOAT, Items.BIRCH_CHEST_BOAT);
itemFallbacks.put(Items.PALE_OAK_BUTTON, Items.BIRCH_BUTTON);
itemFallbacks.put(Items.PALE_OAK_PRESSURE_PLATE, Items.BIRCH_PRESSURE_PLATE);
itemFallbacks.put(Items.RESIN_CLUMP, Items.RAW_COPPER);
itemFallbacks.put(Items.RESIN_BRICK_WALL, Items.RED_SANDSTONE_WALL);
itemFallbacks.put(Items.RESIN_BRICK_STAIRS, Items.RED_SANDSTONE_STAIRS);
itemFallbacks.put(Items.RESIN_BRICK_SLAB, Items.RED_SANDSTONE_SLAB);
itemFallbacks.put(Items.RESIN_BLOCK, Items.RED_SANDSTONE);
itemFallbacks.put(Items.RESIN_BRICK, Items.BRICK);
itemFallbacks.put(Items.RESIN_BRICKS, Items.CUT_RED_SANDSTONE);
itemFallbacks.put(Items.CHISELED_RESIN_BRICKS, Items.CHISELED_RED_SANDSTONE);
itemFallbacks.put(Items.CLOSED_EYEBLOSSOM, Items.WHITE_TULIP);
itemFallbacks.put(Items.OPEN_EYEBLOSSOM, Items.OXEYE_DAISY);
itemFallbacks.put(Items.PALE_MOSS_BLOCK, Items.MOSS_BLOCK);
itemFallbacks.put(Items.PALE_MOSS_CARPET, Items.MOSS_CARPET);
itemFallbacks.put(Items.PALE_HANGING_MOSS, Items.HANGING_ROOTS);
itemFallbacks.put(Items.CREAKING_HEART, Items.CHISELED_POLISHED_BLACKSTONE);
itemFallbacks.put(Items.CREAKING_SPAWN_EGG, Items.HOGLIN_SPAWN_EGG);
List<PaletteVersion> paletteVersions = new ArrayList<>(2); List<PaletteVersion> paletteVersions = new ArrayList<>(2);
paletteVersions.add(new PaletteVersion("1_21_40", Bedrock_v748.CODEC.getProtocolVersion())); paletteVersions.add(new PaletteVersion("1_21_40", Bedrock_v748.CODEC.getProtocolVersion(), itemFallbacks, (item, mapping) -> mapping));
paletteVersions.add(new PaletteVersion("1_21_50", Bedrock_v766.CODEC.getProtocolVersion())); paletteVersions.add(new PaletteVersion("1_21_50", Bedrock_v766.CODEC.getProtocolVersion()));
GeyserBootstrap bootstrap = GeyserImpl.getInstance().getBootstrap(); GeyserBootstrap bootstrap = GeyserImpl.getInstance().getBootstrap();
@ -425,16 +462,10 @@ public class ItemRegistryPopulator {
.javaItem(javaItem); .javaItem(javaItem);
if (mappingItem.getToolType() != null) { if (mappingItem.getToolType() != null) {
if (mappingItem.getToolTier() != null) { mappingBuilder = mappingBuilder.toolType(mappingItem.getToolType().intern());
mappingBuilder = mappingBuilder.toolType(mappingItem.getToolType().intern())
.toolTier(mappingItem.getToolTier().intern());
} else {
mappingBuilder = mappingBuilder.toolType(mappingItem.getToolType().intern())
.toolTier("");
}
} }
if (javaOnlyItems.contains(javaItem) || javaItem.rarity() != Rarity.COMMON) { if (javaOnlyItems.contains(javaItem) || javaItem.defaultRarity() != Rarity.COMMON) {
// These items don't exist on Bedrock, so set up a variable that indicates they should have custom names // These items don't exist on Bedrock, so set up a variable that indicates they should have custom names
// Or, ensure that we are translating these at all times to account for rarity colouring // Or, ensure that we are translating these at all times to account for rarity colouring
mappingBuilder = mappingBuilder.translationString((javaItem instanceof BlockItem ? "block." : "item.") + entry.getKey().replace(":", ".")); mappingBuilder = mappingBuilder.translationString((javaItem instanceof BlockItem ? "block." : "item.") + entry.getKey().replace(":", "."));

View file

@ -48,7 +48,6 @@ public class GeyserMappingItem {
Integer firstBlockRuntimeId; Integer firstBlockRuntimeId;
Integer lastBlockRuntimeId; Integer lastBlockRuntimeId;
@JsonProperty("tool_type") String toolType; @JsonProperty("tool_type") String toolType;
@JsonProperty("tool_tier") String toolTier;
@JsonProperty("armor_type") String armorType; @JsonProperty("armor_type") String armorType;
@JsonProperty("protection_value") int protectionValue; @JsonProperty("protection_value") int protectionValue;
@JsonProperty("is_edible") boolean edible = false; @JsonProperty("is_edible") boolean edible = false;

View file

@ -52,7 +52,6 @@ public class ItemMapping {
null, // Air is never sent in full over the network for this to serialize. null, // Air is never sent in full over the network for this to serialize.
null, null,
null, null,
null,
Collections.emptyList(), Collections.emptyList(),
Items.AIR Items.AIR
); );
@ -68,7 +67,6 @@ public class ItemMapping {
BlockDefinition bedrockBlockDefinition; BlockDefinition bedrockBlockDefinition;
String toolType; String toolType;
String toolTier;
String translationString; String translationString;

View file

@ -150,7 +150,6 @@ import org.geysermc.geyser.item.type.BlockItem;
import org.geysermc.geyser.level.BedrockDimension; import org.geysermc.geyser.level.BedrockDimension;
import org.geysermc.geyser.level.JavaDimension; import org.geysermc.geyser.level.JavaDimension;
import org.geysermc.geyser.level.physics.CollisionManager; import org.geysermc.geyser.level.physics.CollisionManager;
import org.geysermc.geyser.network.GameProtocol;
import org.geysermc.geyser.network.netty.LocalSession; import org.geysermc.geyser.network.netty.LocalSession;
import org.geysermc.geyser.registry.Registries; import org.geysermc.geyser.registry.Registries;
import org.geysermc.geyser.registry.type.BlockMappings; import org.geysermc.geyser.registry.type.BlockMappings;
@ -524,6 +523,11 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
@Setter @Setter
private long blockBreakStartTime; private long blockBreakStartTime;
/**
* // TODO
*/
private long destroyProgress;
/** /**
* Stores whether the player intended to place a bucket. * Stores whether the player intended to place a bucket.
*/ */
@ -1154,7 +1158,10 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
@Override @Override
public void packetError(PacketErrorEvent event) { public void packetError(PacketErrorEvent event) {
geyser.getLogger().warning(GeyserLocale.getLocaleStringLog("geyser.network.downstream_error", event.getCause().getMessage())); geyser.getLogger().warning(GeyserLocale.getLocaleStringLog("geyser.network.downstream_error",
(event.getPacketClass() != null ? "(" + event.getPacketClass().getSimpleName() + ")" : "") +
event.getCause().getMessage())
);
if (geyser.getConfig().isDebugMode()) if (geyser.getConfig().isDebugMode())
event.getCause().printStackTrace(); event.getCause().printStackTrace();
event.setSuppress(true); event.setSuppress(true);
@ -1691,8 +1698,6 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
startGamePacket.getExperiments().add(new ExperimentData("upcoming_creator_features", true)); startGamePacket.getExperiments().add(new ExperimentData("upcoming_creator_features", true));
// Needed for certain molang queries used in blocks and items // Needed for certain molang queries used in blocks and items
startGamePacket.getExperiments().add(new ExperimentData("experimental_molang_features", true)); startGamePacket.getExperiments().add(new ExperimentData("experimental_molang_features", true));
// Required for experimental 1.21 features
startGamePacket.getExperiments().add(new ExperimentData("updateAnnouncedLive2023", true));
startGamePacket.setVanillaVersion("*"); startGamePacket.setVanillaVersion("*");
startGamePacket.setInventoriesServerAuthoritative(true); startGamePacket.setInventoriesServerAuthoritative(true);

View file

@ -28,15 +28,19 @@ package org.geysermc.geyser.session.cache;
import it.unimi.dsi.fastutil.ints.IntArrays; import it.unimi.dsi.fastutil.ints.IntArrays;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import net.kyori.adventure.key.Key; import net.kyori.adventure.key.Key;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.geysermc.geyser.GeyserLogger; import org.geysermc.geyser.GeyserLogger;
import org.geysermc.geyser.inventory.GeyserItemStack; import org.geysermc.geyser.inventory.GeyserItemStack;
import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.item.type.Item;
import org.geysermc.geyser.level.block.type.Block;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.session.cache.registry.JavaRegistries; import org.geysermc.geyser.session.cache.registry.JavaRegistries;
import org.geysermc.geyser.session.cache.registry.JavaRegistryKey; import org.geysermc.geyser.session.cache.registry.JavaRegistryKey;
import org.geysermc.geyser.session.cache.tags.GeyserHolderSet; import org.geysermc.geyser.session.cache.tags.GeyserHolderSet;
import org.geysermc.geyser.session.cache.tags.Tag; import org.geysermc.geyser.session.cache.tags.Tag;
import org.geysermc.geyser.util.MinecraftKey; import org.geysermc.geyser.util.MinecraftKey;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.HolderSet;
import org.geysermc.mcprotocollib.protocol.packet.common.clientbound.ClientboundUpdateTagsPacket; import org.geysermc.mcprotocollib.protocol.packet.common.clientbound.ClientboundUpdateTagsPacket;
import javax.annotation.ParametersAreNonnullByDefault; import javax.annotation.ParametersAreNonnullByDefault;
@ -119,10 +123,41 @@ public final class TagCache {
/** /**
* @return true if the specified network ID is in the given holder set. * @return true if the specified network ID is in the given holder set.
*/ */
public <T> boolean is(GeyserHolderSet<T> holderSet, T object) { public <T> boolean is(@Nullable GeyserHolderSet<T> holderSet, @Nullable T object) {
if (holderSet == null || object == null) {
return false;
}
return contains(holderSet.resolveRaw(this), holderSet.getRegistry().toNetworkId(session, object)); return contains(holderSet.resolveRaw(this), holderSet.getRegistry().toNetworkId(session, object));
} }
/**
* Accessible via the {@link #isItem(HolderSet, Item)} method.
* @return true if the specified network ID is in the given {@link HolderSet} set.
*/
private <T> boolean is(@Nullable HolderSet holderSet, @NonNull JavaRegistryKey<T> registry, int id) {
if (holderSet == null) {
return false;
}
int[] entries = holderSet.resolve(key -> {
if (key.value().startsWith("#")) {
key = Key.key(key.namespace(), key.value().substring(1));
}
return getRaw(new Tag<>(registry, key));
});
return contains(entries, id);
}
public boolean isItem(@Nullable HolderSet holderSet, @NonNull Item item) {
return is(holderSet, JavaRegistries.ITEM, item.javaId());
}
public boolean isBlock(@Nullable HolderSet holderSet, @NonNull Block block) {
return is(holderSet, JavaRegistries.BLOCK, block.javaId());
}
public <T> List<T> get(Tag<T> tag) { public <T> List<T> get(Tag<T> tag) {
return mapRawArray(session, getRaw(tag), tag.registry()); return mapRawArray(session, getRaw(tag), tag.registry());
} }

View file

@ -56,6 +56,7 @@ public final class BlockTag {
public static final Tag<Block> OVERWORLD_NATURAL_LOGS = create("overworld_natural_logs"); public static final Tag<Block> OVERWORLD_NATURAL_LOGS = create("overworld_natural_logs");
public static final Tag<Block> LOGS = create("logs"); public static final Tag<Block> LOGS = create("logs");
public static final Tag<Block> DARK_OAK_LOGS = create("dark_oak_logs"); public static final Tag<Block> DARK_OAK_LOGS = create("dark_oak_logs");
public static final Tag<Block> PALE_OAK_LOGS = create("pale_oak_logs");
public static final Tag<Block> OAK_LOGS = create("oak_logs"); public static final Tag<Block> OAK_LOGS = create("oak_logs");
public static final Tag<Block> BIRCH_LOGS = create("birch_logs"); public static final Tag<Block> BIRCH_LOGS = create("birch_logs");
public static final Tag<Block> ACACIA_LOGS = create("acacia_logs"); public static final Tag<Block> ACACIA_LOGS = create("acacia_logs");
@ -80,8 +81,8 @@ public final class BlockTag {
public static final Tag<Block> SMALL_FLOWERS = create("small_flowers"); public static final Tag<Block> SMALL_FLOWERS = create("small_flowers");
public static final Tag<Block> BEDS = create("beds"); public static final Tag<Block> BEDS = create("beds");
public static final Tag<Block> FENCES = create("fences"); public static final Tag<Block> FENCES = create("fences");
public static final Tag<Block> TALL_FLOWERS = create("tall_flowers");
public static final Tag<Block> FLOWERS = create("flowers"); public static final Tag<Block> FLOWERS = create("flowers");
public static final Tag<Block> BEE_ATTRACTIVE = create("bee_attractive");
public static final Tag<Block> PIGLIN_REPELLENTS = create("piglin_repellents"); public static final Tag<Block> PIGLIN_REPELLENTS = create("piglin_repellents");
public static final Tag<Block> GOLD_ORES = create("gold_ores"); public static final Tag<Block> GOLD_ORES = create("gold_ores");
public static final Tag<Block> IRON_ORES = create("iron_ores"); public static final Tag<Block> IRON_ORES = create("iron_ores");
@ -97,6 +98,7 @@ public final class BlockTag {
public static final Tag<Block> BADLANDS_TERRACOTTA = create("badlands_terracotta"); public static final Tag<Block> BADLANDS_TERRACOTTA = create("badlands_terracotta");
public static final Tag<Block> CONCRETE_POWDER = create("concrete_powder"); public static final Tag<Block> CONCRETE_POWDER = create("concrete_powder");
public static final Tag<Block> COMPLETES_FIND_TREE_TUTORIAL = create("completes_find_tree_tutorial"); public static final Tag<Block> COMPLETES_FIND_TREE_TUTORIAL = create("completes_find_tree_tutorial");
public static final Tag<Block> SHULKER_BOXES = create("shulker_boxes");
public static final Tag<Block> FLOWER_POTS = create("flower_pots"); public static final Tag<Block> FLOWER_POTS = create("flower_pots");
public static final Tag<Block> ENDERMAN_HOLDABLE = create("enderman_holdable"); public static final Tag<Block> ENDERMAN_HOLDABLE = create("enderman_holdable");
public static final Tag<Block> ICE = create("ice"); public static final Tag<Block> ICE = create("ice");
@ -130,7 +132,6 @@ public final class BlockTag {
public static final Tag<Block> WALL_POST_OVERRIDE = create("wall_post_override"); public static final Tag<Block> WALL_POST_OVERRIDE = create("wall_post_override");
public static final Tag<Block> CLIMBABLE = create("climbable"); public static final Tag<Block> CLIMBABLE = create("climbable");
public static final Tag<Block> FALL_DAMAGE_RESETTING = create("fall_damage_resetting"); public static final Tag<Block> FALL_DAMAGE_RESETTING = create("fall_damage_resetting");
public static final Tag<Block> SHULKER_BOXES = create("shulker_boxes");
public static final Tag<Block> HOGLIN_REPELLENTS = create("hoglin_repellents"); public static final Tag<Block> HOGLIN_REPELLENTS = create("hoglin_repellents");
public static final Tag<Block> SOUL_FIRE_BASE_BLOCKS = create("soul_fire_base_blocks"); public static final Tag<Block> SOUL_FIRE_BASE_BLOCKS = create("soul_fire_base_blocks");
public static final Tag<Block> STRIDER_WARM_BLOCKS = create("strider_warm_blocks"); public static final Tag<Block> STRIDER_WARM_BLOCKS = create("strider_warm_blocks");
@ -198,6 +199,7 @@ public final class BlockTag {
public static final Tag<Block> FOXES_SPAWNABLE_ON = create("foxes_spawnable_on"); public static final Tag<Block> FOXES_SPAWNABLE_ON = create("foxes_spawnable_on");
public static final Tag<Block> WOLVES_SPAWNABLE_ON = create("wolves_spawnable_on"); public static final Tag<Block> WOLVES_SPAWNABLE_ON = create("wolves_spawnable_on");
public static final Tag<Block> FROGS_SPAWNABLE_ON = create("frogs_spawnable_on"); public static final Tag<Block> FROGS_SPAWNABLE_ON = create("frogs_spawnable_on");
public static final Tag<Block> BATS_SPAWNABLE_ON = create("bats_spawnable_on");
public static final Tag<Block> AZALEA_GROWS_ON = create("azalea_grows_on"); public static final Tag<Block> AZALEA_GROWS_ON = create("azalea_grows_on");
public static final Tag<Block> CONVERTABLE_TO_MUD = create("convertable_to_mud"); public static final Tag<Block> CONVERTABLE_TO_MUD = create("convertable_to_mud");
public static final Tag<Block> MANGROVE_LOGS_CAN_GROW_THROUGH = create("mangrove_logs_can_grow_through"); public static final Tag<Block> MANGROVE_LOGS_CAN_GROW_THROUGH = create("mangrove_logs_can_grow_through");

View file

@ -25,10 +25,6 @@
package org.geysermc.geyser.session.cache.tags; package org.geysermc.geyser.session.cache.tags;
import java.util.List;
import java.util.Objects;
import java.util.function.ToIntFunction;
import it.unimi.dsi.fastutil.ints.IntArrays; import it.unimi.dsi.fastutil.ints.IntArrays;
import lombok.Data; import lombok.Data;
import net.kyori.adventure.key.Key; import net.kyori.adventure.key.Key;
@ -38,6 +34,10 @@ import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.session.cache.TagCache; import org.geysermc.geyser.session.cache.TagCache;
import org.geysermc.geyser.session.cache.registry.JavaRegistryKey; import org.geysermc.geyser.session.cache.registry.JavaRegistryKey;
import java.util.List;
import java.util.Objects;
import java.util.function.ToIntFunction;
/** /**
* Similar to vanilla Minecraft's HolderSets, stores either a tag or a list of IDs (this list can also be represented as a single ID in vanilla HolderSets). * Similar to vanilla Minecraft's HolderSets, stores either a tag or a list of IDs (this list can also be represented as a single ID in vanilla HolderSets).
* *

View file

@ -53,6 +53,7 @@ public final class ItemTag {
public static final Tag<Item> LOGS_THAT_BURN = create("logs_that_burn"); public static final Tag<Item> LOGS_THAT_BURN = create("logs_that_burn");
public static final Tag<Item> LOGS = create("logs"); public static final Tag<Item> LOGS = create("logs");
public static final Tag<Item> DARK_OAK_LOGS = create("dark_oak_logs"); public static final Tag<Item> DARK_OAK_LOGS = create("dark_oak_logs");
public static final Tag<Item> PALE_OAK_LOGS = create("pale_oak_logs");
public static final Tag<Item> OAK_LOGS = create("oak_logs"); public static final Tag<Item> OAK_LOGS = create("oak_logs");
public static final Tag<Item> BIRCH_LOGS = create("birch_logs"); public static final Tag<Item> BIRCH_LOGS = create("birch_logs");
public static final Tag<Item> ACACIA_LOGS = create("acacia_logs"); public static final Tag<Item> ACACIA_LOGS = create("acacia_logs");
@ -77,11 +78,13 @@ public final class ItemTag {
public static final Tag<Item> SMALL_FLOWERS = create("small_flowers"); public static final Tag<Item> SMALL_FLOWERS = create("small_flowers");
public static final Tag<Item> BEDS = create("beds"); public static final Tag<Item> BEDS = create("beds");
public static final Tag<Item> FENCES = create("fences"); public static final Tag<Item> FENCES = create("fences");
public static final Tag<Item> TALL_FLOWERS = create("tall_flowers");
public static final Tag<Item> FLOWERS = create("flowers");
public static final Tag<Item> PIGLIN_REPELLENTS = create("piglin_repellents"); public static final Tag<Item> PIGLIN_REPELLENTS = create("piglin_repellents");
public static final Tag<Item> PIGLIN_LOVED = create("piglin_loved"); public static final Tag<Item> PIGLIN_LOVED = create("piglin_loved");
public static final Tag<Item> IGNORED_BY_PIGLIN_BABIES = create("ignored_by_piglin_babies"); public static final Tag<Item> IGNORED_BY_PIGLIN_BABIES = create("ignored_by_piglin_babies");
public static final Tag<Item> PIGLIN_SAFE_ARMOR = create("piglin_safe_armor");
public static final Tag<Item> DUPLICATES_ALLAYS = create("duplicates_allays");
public static final Tag<Item> BREWING_FUEL = create("brewing_fuel");
public static final Tag<Item> SHULKER_BOXES = create("shulker_boxes");
public static final Tag<Item> MEAT = create("meat"); public static final Tag<Item> MEAT = create("meat");
public static final Tag<Item> SNIFFER_FOOD = create("sniffer_food"); public static final Tag<Item> SNIFFER_FOOD = create("sniffer_food");
public static final Tag<Item> PIGLIN_FOOD = create("piglin_food"); public static final Tag<Item> PIGLIN_FOOD = create("piglin_food");
@ -103,6 +106,7 @@ public final class ItemTag {
public static final Tag<Item> LLAMA_TEMPT_ITEMS = create("llama_tempt_items"); public static final Tag<Item> LLAMA_TEMPT_ITEMS = create("llama_tempt_items");
public static final Tag<Item> OCELOT_FOOD = create("ocelot_food"); public static final Tag<Item> OCELOT_FOOD = create("ocelot_food");
public static final Tag<Item> PANDA_FOOD = create("panda_food"); public static final Tag<Item> PANDA_FOOD = create("panda_food");
public static final Tag<Item> PANDA_EATS_FROM_GROUND = create("panda_eats_from_ground");
public static final Tag<Item> PIG_FOOD = create("pig_food"); public static final Tag<Item> PIG_FOOD = create("pig_food");
public static final Tag<Item> RABBIT_FOOD = create("rabbit_food"); public static final Tag<Item> RABBIT_FOOD = create("rabbit_food");
public static final Tag<Item> STRIDER_FOOD = create("strider_food"); public static final Tag<Item> STRIDER_FOOD = create("strider_food");
@ -135,7 +139,20 @@ public final class ItemTag {
public static final Tag<Item> LECTERN_BOOKS = create("lectern_books"); public static final Tag<Item> LECTERN_BOOKS = create("lectern_books");
public static final Tag<Item> BOOKSHELF_BOOKS = create("bookshelf_books"); public static final Tag<Item> BOOKSHELF_BOOKS = create("bookshelf_books");
public static final Tag<Item> BEACON_PAYMENT_ITEMS = create("beacon_payment_items"); public static final Tag<Item> BEACON_PAYMENT_ITEMS = create("beacon_payment_items");
public static final Tag<Item> WOODEN_TOOL_MATERIALS = create("wooden_tool_materials");
public static final Tag<Item> STONE_TOOL_MATERIALS = create("stone_tool_materials"); public static final Tag<Item> STONE_TOOL_MATERIALS = create("stone_tool_materials");
public static final Tag<Item> IRON_TOOL_MATERIALS = create("iron_tool_materials");
public static final Tag<Item> GOLD_TOOL_MATERIALS = create("gold_tool_materials");
public static final Tag<Item> DIAMOND_TOOL_MATERIALS = create("diamond_tool_materials");
public static final Tag<Item> NETHERITE_TOOL_MATERIALS = create("netherite_tool_materials");
public static final Tag<Item> REPAIRS_LEATHER_ARMOR = create("repairs_leather_armor");
public static final Tag<Item> REPAIRS_CHAIN_ARMOR = create("repairs_chain_armor");
public static final Tag<Item> REPAIRS_IRON_ARMOR = create("repairs_iron_armor");
public static final Tag<Item> REPAIRS_GOLD_ARMOR = create("repairs_gold_armor");
public static final Tag<Item> REPAIRS_DIAMOND_ARMOR = create("repairs_diamond_armor");
public static final Tag<Item> REPAIRS_NETHERITE_ARMOR = create("repairs_netherite_armor");
public static final Tag<Item> REPAIRS_TURTLE_HELMET = create("repairs_turtle_helmet");
public static final Tag<Item> REPAIRS_WOLF_ARMOR = create("repairs_wolf_armor");
public static final Tag<Item> STONE_CRAFTING_MATERIALS = create("stone_crafting_materials"); public static final Tag<Item> STONE_CRAFTING_MATERIALS = create("stone_crafting_materials");
public static final Tag<Item> FREEZE_IMMUNE_WEARABLES = create("freeze_immune_wearables"); public static final Tag<Item> FREEZE_IMMUNE_WEARABLES = create("freeze_immune_wearables");
public static final Tag<Item> DAMPENS_VIBRATIONS = create("dampens_vibrations"); public static final Tag<Item> DAMPENS_VIBRATIONS = create("dampens_vibrations");
@ -151,7 +168,6 @@ public final class ItemTag {
public static final Tag<Item> SKULLS = create("skulls"); public static final Tag<Item> SKULLS = create("skulls");
public static final Tag<Item> TRIMMABLE_ARMOR = create("trimmable_armor"); public static final Tag<Item> TRIMMABLE_ARMOR = create("trimmable_armor");
public static final Tag<Item> TRIM_MATERIALS = create("trim_materials"); public static final Tag<Item> TRIM_MATERIALS = create("trim_materials");
public static final Tag<Item> TRIM_TEMPLATES = create("trim_templates");
public static final Tag<Item> DECORATED_POT_SHERDS = create("decorated_pot_sherds"); public static final Tag<Item> DECORATED_POT_SHERDS = create("decorated_pot_sherds");
public static final Tag<Item> DECORATED_POT_INGREDIENTS = create("decorated_pot_ingredients"); public static final Tag<Item> DECORATED_POT_INGREDIENTS = create("decorated_pot_ingredients");
public static final Tag<Item> SWORDS = create("swords"); public static final Tag<Item> SWORDS = create("swords");
@ -161,7 +177,15 @@ public final class ItemTag {
public static final Tag<Item> SHOVELS = create("shovels"); public static final Tag<Item> SHOVELS = create("shovels");
public static final Tag<Item> BREAKS_DECORATED_POTS = create("breaks_decorated_pots"); public static final Tag<Item> BREAKS_DECORATED_POTS = create("breaks_decorated_pots");
public static final Tag<Item> VILLAGER_PLANTABLE_SEEDS = create("villager_plantable_seeds"); public static final Tag<Item> VILLAGER_PLANTABLE_SEEDS = create("villager_plantable_seeds");
public static final Tag<Item> VILLAGER_PICKS_UP = create("villager_picks_up");
public static final Tag<Item> DYEABLE = create("dyeable"); public static final Tag<Item> DYEABLE = create("dyeable");
public static final Tag<Item> FURNACE_MINECART_FUEL = create("furnace_minecart_fuel");
public static final Tag<Item> BUNDLES = create("bundles");
public static final Tag<Item> SKELETON_PREFERRED_WEAPONS = create("skeleton_preferred_weapons");
public static final Tag<Item> DROWNED_PREFERRED_WEAPONS = create("drowned_preferred_weapons");
public static final Tag<Item> PIGLIN_PREFERRED_WEAPONS = create("piglin_preferred_weapons");
public static final Tag<Item> PILLAGER_PREFERRED_WEAPONS = create("pillager_preferred_weapons");
public static final Tag<Item> WITHER_SKELETON_DISLIKED_WEAPONS = create("wither_skeleton_disliked_weapons");
public static final Tag<Item> ENCHANTABLE_FOOT_ARMOR = create("enchantable/foot_armor"); public static final Tag<Item> ENCHANTABLE_FOOT_ARMOR = create("enchantable/foot_armor");
public static final Tag<Item> ENCHANTABLE_LEG_ARMOR = create("enchantable/leg_armor"); public static final Tag<Item> ENCHANTABLE_LEG_ARMOR = create("enchantable/leg_armor");
public static final Tag<Item> ENCHANTABLE_CHEST_ARMOR = create("enchantable/chest_armor"); public static final Tag<Item> ENCHANTABLE_CHEST_ARMOR = create("enchantable/chest_armor");
@ -181,6 +205,8 @@ public final class ItemTag {
public static final Tag<Item> ENCHANTABLE_CROSSBOW = create("enchantable/crossbow"); public static final Tag<Item> ENCHANTABLE_CROSSBOW = create("enchantable/crossbow");
public static final Tag<Item> ENCHANTABLE_VANISHING = create("enchantable/vanishing"); public static final Tag<Item> ENCHANTABLE_VANISHING = create("enchantable/vanishing");
public static final Tag<Item> ENCHANTABLE_MACE = create("enchantable/mace"); public static final Tag<Item> ENCHANTABLE_MACE = create("enchantable/mace");
public static final Tag<Item> MAP_INVISIBILITY_EQUIPMENT = create("map_invisibility_equipment");
public static final Tag<Item> GAZE_DISGUISE_EQUIPMENT = create("gaze_disguise_equipment");
private ItemTag() {} private ItemTag() {}

View file

@ -25,10 +25,6 @@
package org.geysermc.geyser.skin; package org.geysermc.geyser.skin;
import org.geysermc.mcprotocollib.auth.GameProfile;
import org.geysermc.mcprotocollib.auth.GameProfile.Texture;
import org.geysermc.mcprotocollib.auth.GameProfile.TextureModel;
import org.geysermc.mcprotocollib.auth.GameProfile.TextureType;
import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader; import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache; import com.google.common.cache.LoadingCache;
@ -36,6 +32,7 @@ import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.api.skin.Cape; import org.geysermc.geyser.api.skin.Cape;
import org.geysermc.geyser.api.skin.Skin; import org.geysermc.geyser.api.skin.Skin;
@ -46,8 +43,10 @@ import org.geysermc.geyser.entity.type.player.PlayerEntity;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.skin.SkinManager.GameProfileData; import org.geysermc.geyser.skin.SkinManager.GameProfileData;
import org.geysermc.geyser.text.GeyserLocale; import org.geysermc.geyser.text.GeyserLocale;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType; import org.geysermc.mcprotocollib.auth.GameProfile;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents; import org.geysermc.mcprotocollib.auth.GameProfile.Texture;
import org.geysermc.mcprotocollib.auth.GameProfile.TextureModel;
import org.geysermc.mcprotocollib.auth.GameProfile.TextureType;
import java.awt.*; import java.awt.*;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
@ -105,9 +104,7 @@ public class FakeHeadProvider {
} }
}); });
public static void setHead(GeyserSession session, PlayerEntity entity, DataComponents components) { public static void setHead(GeyserSession session, PlayerEntity entity, @Nullable GameProfile profile) {
GameProfile profile = components.get(DataComponentType.PROFILE);
if (profile == null) { if (profile == null) {
return; return;
} }

View file

@ -73,7 +73,7 @@ public class AnvilInventoryTranslator extends AbstractBlockInventoryTranslator {
@Override @Override
public int bedrockSlotToJava(ItemStackRequestSlotData slotInfoData) { public int bedrockSlotToJava(ItemStackRequestSlotData slotInfoData) {
return switch (slotInfoData.getContainer()) { return switch (slotInfoData.getContainerName().getContainer()) {
case ANVIL_INPUT -> 0; case ANVIL_INPUT -> 0;
case ANVIL_MATERIAL -> 1; case ANVIL_MATERIAL -> 1;
case ANVIL_RESULT, CREATED_OUTPUT -> 2; case ANVIL_RESULT, CREATED_OUTPUT -> 2;

View file

@ -44,7 +44,7 @@ public abstract class BaseInventoryTranslator extends InventoryTranslator {
@Override @Override
public int bedrockSlotToJava(ItemStackRequestSlotData slotInfoData) { public int bedrockSlotToJava(ItemStackRequestSlotData slotInfoData) {
int slotnum = slotInfoData.getSlot(); int slotnum = slotInfoData.getSlot();
switch (slotInfoData.getContainer()) { switch (slotInfoData.getContainerName().getContainer()) {
case HOTBAR_AND_INVENTORY: case HOTBAR_AND_INVENTORY:
case HOTBAR: case HOTBAR:
case INVENTORY: case INVENTORY:

View file

@ -121,7 +121,7 @@ public class BeaconInventoryTranslator extends AbstractBlockInventoryTranslator
@Override @Override
public int bedrockSlotToJava(ItemStackRequestSlotData slotInfoData) { public int bedrockSlotToJava(ItemStackRequestSlotData slotInfoData) {
if (slotInfoData.getContainer() == ContainerSlotType.BEACON_PAYMENT) { if (slotInfoData.getContainerName().getContainer() == ContainerSlotType.BEACON_PAYMENT) {
return 0; return 0;
} }
return super.bedrockSlotToJava(slotInfoData); return super.bedrockSlotToJava(slotInfoData);

View file

@ -74,11 +74,11 @@ public class BrewingInventoryTranslator extends AbstractBlockInventoryTranslator
@Override @Override
public int bedrockSlotToJava(ItemStackRequestSlotData slotInfoData) { public int bedrockSlotToJava(ItemStackRequestSlotData slotInfoData) {
if (slotInfoData.getContainer() == ContainerSlotType.BREWING_INPUT) { if (slotInfoData.getContainerName().getContainer() == ContainerSlotType.BREWING_INPUT) {
// Ingredient // Ingredient
return 3; return 3;
} }
if (slotInfoData.getContainer() == ContainerSlotType.BREWING_RESULT) { if (slotInfoData.getContainerName().getContainer() == ContainerSlotType.BREWING_RESULT) {
// Potions // Potions
return slotInfoData.getSlot() - 1; return slotInfoData.getSlot() - 1;
} }

View file

@ -56,7 +56,7 @@ public class CartographyInventoryTranslator extends AbstractBlockInventoryTransl
@Override @Override
public int bedrockSlotToJava(ItemStackRequestSlotData slotInfoData) { public int bedrockSlotToJava(ItemStackRequestSlotData slotInfoData) {
return switch (slotInfoData.getContainer()) { return switch (slotInfoData.getContainerName().getContainer()) {
case CARTOGRAPHY_INPUT -> 0; case CARTOGRAPHY_INPUT -> 0;
case CARTOGRAPHY_ADDITIONAL -> 1; case CARTOGRAPHY_ADDITIONAL -> 1;
case CARTOGRAPHY_RESULT, CREATED_OUTPUT -> 2; case CARTOGRAPHY_RESULT, CREATED_OUTPUT -> 2;

View file

@ -77,7 +77,7 @@ public class CrafterInventoryTranslator extends AbstractBlockInventoryTranslator
@Override @Override
public int bedrockSlotToJava(ItemStackRequestSlotData slotInfoData) { public int bedrockSlotToJava(ItemStackRequestSlotData slotInfoData) {
int slot = slotInfoData.getSlot(); int slot = slotInfoData.getSlot();
switch (slotInfoData.getContainer()) { switch (slotInfoData.getContainerName().getContainer()) {
case HOTBAR_AND_INVENTORY, HOTBAR, INVENTORY -> { case HOTBAR_AND_INVENTORY, HOTBAR, INVENTORY -> {
//hotbar //hotbar
if (slot >= 9) { if (slot >= 9) {

View file

@ -64,12 +64,12 @@ public class CraftingInventoryTranslator extends AbstractBlockInventoryTranslato
@Override @Override
public int bedrockSlotToJava(ItemStackRequestSlotData slotInfoData) { public int bedrockSlotToJava(ItemStackRequestSlotData slotInfoData) {
if (slotInfoData.getContainer() == ContainerSlotType.CRAFTING_INPUT) { if (slotInfoData.getContainerName().getContainer() == ContainerSlotType.CRAFTING_INPUT) {
// Java goes from 1 - 9, left to right then up to down // Java goes from 1 - 9, left to right then up to down
// Bedrock is the same, but it starts from 32. // Bedrock is the same, but it starts from 32.
return slotInfoData.getSlot() - 31; return slotInfoData.getSlot() - 31;
} }
if (slotInfoData.getContainer() == ContainerSlotType.CRAFTING_OUTPUT || slotInfoData.getContainer() == ContainerSlotType.CREATED_OUTPUT) { if (slotInfoData.getContainerName().getContainer() == ContainerSlotType.CRAFTING_OUTPUT || slotInfoData.getContainerName().getContainer() == ContainerSlotType.CREATED_OUTPUT) {
return 0; return 0;
} }
return super.bedrockSlotToJava(slotInfoData); return super.bedrockSlotToJava(slotInfoData);

View file

@ -135,10 +135,10 @@ public class EnchantingInventoryTranslator extends AbstractBlockInventoryTransla
@Override @Override
public int bedrockSlotToJava(ItemStackRequestSlotData slotInfoData) { public int bedrockSlotToJava(ItemStackRequestSlotData slotInfoData) {
if (slotInfoData.getContainer() == ContainerSlotType.ENCHANTING_INPUT) { if (slotInfoData.getContainerName().getContainer() == ContainerSlotType.ENCHANTING_INPUT) {
return 0; return 0;
} }
if (slotInfoData.getContainer() == ContainerSlotType.ENCHANTING_MATERIAL) { if (slotInfoData.getContainerName().getContainer() == ContainerSlotType.ENCHANTING_MATERIAL) {
return 1; return 1;
} }
return super.bedrockSlotToJava(slotInfoData); return super.bedrockSlotToJava(slotInfoData);

View file

@ -39,7 +39,7 @@ public class GrindstoneInventoryTranslator extends AbstractBlockInventoryTransla
@Override @Override
public int bedrockSlotToJava(ItemStackRequestSlotData slotInfoData) { public int bedrockSlotToJava(ItemStackRequestSlotData slotInfoData) {
return switch (slotInfoData.getContainer()) { return switch (slotInfoData.getContainerName().getContainer()) {
case GRINDSTONE_INPUT -> 0; case GRINDSTONE_INPUT -> 0;
case GRINDSTONE_ADDITIONAL -> 1; case GRINDSTONE_ADDITIONAL -> 1;
case GRINDSTONE_RESULT, CREATED_OUTPUT -> 2; case GRINDSTONE_RESULT, CREATED_OUTPUT -> 2;

View file

@ -76,7 +76,6 @@ import org.geysermc.geyser.util.InventoryUtils;
import org.geysermc.geyser.util.ItemUtils; import org.geysermc.geyser.util.ItemUtils;
import org.geysermc.mcprotocollib.protocol.data.game.inventory.ContainerType; import org.geysermc.mcprotocollib.protocol.data.game.inventory.ContainerType;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType; import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents;
import org.geysermc.mcprotocollib.protocol.data.game.recipe.display.slot.EmptySlotDisplay; import org.geysermc.mcprotocollib.protocol.data.game.recipe.display.slot.EmptySlotDisplay;
import org.geysermc.mcprotocollib.protocol.data.game.recipe.display.slot.SlotDisplay; import org.geysermc.mcprotocollib.protocol.data.game.recipe.display.slot.SlotDisplay;
@ -252,8 +251,8 @@ public abstract class InventoryTranslator {
//only set the head if the destination is the head slot //only set the head if the destination is the head slot
GeyserItemStack javaItem = inventory.getItem(sourceSlot); GeyserItemStack javaItem = inventory.getItem(sourceSlot);
if (javaItem.asItem() == Items.PLAYER_HEAD if (javaItem.asItem() == Items.PLAYER_HEAD
&& javaItem.getComponents() != null) { && javaItem.hasNonBaseComponents()) {
FakeHeadProvider.setHead(session, session.getPlayerEntity(), javaItem.getComponents()); FakeHeadProvider.setHead(session, session.getPlayerEntity(), javaItem.getComponent(DataComponentType.PROFILE));
} }
} else if (sourceSlot == 5) { } else if (sourceSlot == 5) {
//we are probably removing the head, so restore the original skin //we are probably removing the head, so restore the original skin
@ -1020,12 +1019,9 @@ public abstract class InventoryTranslator {
// As of 1.16.210: Bedrock needs confirmation on what the current item durability is. // As of 1.16.210: Bedrock needs confirmation on what the current item durability is.
// If 0 is sent, then Bedrock thinks the item is not damaged // If 0 is sent, then Bedrock thinks the item is not damaged
int durability = 0; int durability = 0;
DataComponents components = itemStack.getComponents(); Integer damage = itemStack.getComponent(DataComponentType.DAMAGE);
if (components != null) { if (damage != null) {
Integer damage = components.get(DataComponentType.DAMAGE); durability = ItemUtils.getCorrectBedrockDurability(itemStack.asItem(), damage);
if (damage != null) {
durability = ItemUtils.getCorrectBedrockDurability(itemStack.asItem(), damage);
}
} }
itemEntry = new ItemStackResponseSlot((byte) bedrockSlot, (byte) bedrockSlot, (byte) itemStack.getAmount(), itemStack.getNetId(), "", durability, ""); itemEntry = new ItemStackResponseSlot((byte) bedrockSlot, (byte) bedrockSlot, (byte) itemStack.getAmount(), itemStack.getNetId(), "", durability, "");

View file

@ -157,13 +157,13 @@ public class LecternInventoryTranslator extends AbstractBlockInventoryTranslator
session.getLastInteractionBlockPosition() : inventory.getHolderPosition(); session.getLastInteractionBlockPosition() : inventory.getHolderPosition();
NbtMap blockEntityTag; NbtMap blockEntityTag;
if (book.getComponents() != null) { if (book.hasNonBaseComponents()) {
int pages = 0; int pages = 0;
WrittenBookContent writtenBookComponents = book.getComponents().get(DataComponentType.WRITTEN_BOOK_CONTENT); WrittenBookContent writtenBookComponents = book.getComponent(DataComponentType.WRITTEN_BOOK_CONTENT);
if (writtenBookComponents != null) { if (writtenBookComponents != null) {
pages = writtenBookComponents.getPages().size(); pages = writtenBookComponents.getPages().size();
} else { } else {
WritableBookContent writableBookComponents = book.getComponents().get(DataComponentType.WRITABLE_BOOK_CONTENT); WritableBookContent writableBookComponents = book.getComponent(DataComponentType.WRITABLE_BOOK_CONTENT);
if (writableBookComponents != null) { if (writableBookComponents != null) {
pages = writableBookComponents.getPages().size(); pages = writableBookComponents.getPages().size();
} }

View file

@ -49,11 +49,9 @@ import org.geysermc.geyser.level.block.Blocks;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.BannerPatternLayer; import org.geysermc.mcprotocollib.protocol.data.game.item.component.BannerPatternLayer;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType; import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents;
import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory.ServerboundContainerButtonClickPacket; import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory.ServerboundContainerButtonClickPacket;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap;
import java.util.List; import java.util.List;
public class LoomInventoryTranslator extends AbstractBlockInventoryTranslator { public class LoomInventoryTranslator extends AbstractBlockInventoryTranslator {
@ -156,16 +154,14 @@ public class LoomInventoryTranslator extends AbstractBlockInventoryTranslator {
GeyserItemStack inputCopy = inventory.getItem(0).copy(1); GeyserItemStack inputCopy = inventory.getItem(0).copy(1);
inputCopy.setNetId(session.getNextItemNetId()); inputCopy.setNetId(session.getNextItemNetId());
// Add the pattern manually, for better item synchronization
if (inputCopy.getComponents() == null) {
inputCopy.setComponents(new DataComponents(new HashMap<>()));
}
BannerPatternLayer bannerPatternLayer = BannerItem.getJavaBannerPattern(session, pattern); // TODO BannerPatternLayer bannerPatternLayer = BannerItem.getJavaBannerPattern(session, pattern); // TODO
if (bannerPatternLayer != null) { if (bannerPatternLayer != null) {
List<BannerPatternLayer> patternsList = inputCopy.getComponents().getOrDefault(DataComponentType.BANNER_PATTERNS, new ArrayList<>()); List<BannerPatternLayer> patternsList = inputCopy.getComponent(DataComponentType.BANNER_PATTERNS);
if (patternsList == null) {
patternsList = new ArrayList<>();
}
patternsList.add(bannerPatternLayer); patternsList.add(bannerPatternLayer);
inputCopy.getComponents().put(DataComponentType.BANNER_PATTERNS, patternsList); inputCopy.getOrCreateComponents().put(DataComponentType.BANNER_PATTERNS, patternsList);
} }
// Set the new item as the output // Set the new item as the output
@ -176,7 +172,7 @@ public class LoomInventoryTranslator extends AbstractBlockInventoryTranslator {
@Override @Override
public int bedrockSlotToJava(ItemStackRequestSlotData slotInfoData) { public int bedrockSlotToJava(ItemStackRequestSlotData slotInfoData) {
return switch (slotInfoData.getContainer()) { return switch (slotInfoData.getContainerName().getContainer()) {
case LOOM_INPUT -> 0; case LOOM_INPUT -> 0;
case LOOM_DYE -> 1; case LOOM_DYE -> 1;
case LOOM_MATERIAL -> 2; case LOOM_MATERIAL -> 2;

View file

@ -77,7 +77,7 @@ public class MerchantInventoryTranslator extends BaseInventoryTranslator {
@Override @Override
public int bedrockSlotToJava(ItemStackRequestSlotData slotInfoData) { public int bedrockSlotToJava(ItemStackRequestSlotData slotInfoData) {
return switch (slotInfoData.getContainer()) { return switch (slotInfoData.getContainerName().getContainer()) {
case TRADE2_INGREDIENT_1 -> 0; case TRADE2_INGREDIENT_1 -> 0;
case TRADE2_INGREDIENT_2 -> 1; case TRADE2_INGREDIENT_2 -> 1;
case TRADE2_RESULT, CREATED_OUTPUT -> 2; case TRADE2_RESULT, CREATED_OUTPUT -> 2;
@ -112,7 +112,7 @@ public class MerchantInventoryTranslator extends BaseInventoryTranslator {
SetEntityLinkPacket linkPacket = new SetEntityLinkPacket(); SetEntityLinkPacket linkPacket = new SetEntityLinkPacket();
EntityLinkData.Type type = EntityLinkData.Type.PASSENGER; EntityLinkData.Type type = EntityLinkData.Type.PASSENGER;
linkPacket.setEntityLink(new EntityLinkData(session.getPlayerEntity().getGeyserId(), geyserId, type, true, false)); linkPacket.setEntityLink(new EntityLinkData(session.getPlayerEntity().getGeyserId(), geyserId, type, true, false, 0f));
session.sendUpstreamPacket(linkPacket); session.sendUpstreamPacket(linkPacket);
merchantInventory.setVillager(villager); merchantInventory.setVillager(villager);

View file

@ -63,7 +63,7 @@ public class OldSmithingTableTranslator extends AbstractBlockInventoryTranslator
@Override @Override
public int bedrockSlotToJava(ItemStackRequestSlotData slotInfoData) { public int bedrockSlotToJava(ItemStackRequestSlotData slotInfoData) {
return switch (slotInfoData.getContainer()) { return switch (slotInfoData.getContainerName().getContainer()) {
case SMITHING_TABLE_INPUT -> 0; case SMITHING_TABLE_INPUT -> 0;
case SMITHING_TABLE_MATERIAL -> 1; case SMITHING_TABLE_MATERIAL -> 1;
case SMITHING_TABLE_RESULT, CREATED_OUTPUT -> 2; case SMITHING_TABLE_RESULT, CREATED_OUTPUT -> 2;
@ -130,7 +130,7 @@ public class OldSmithingTableTranslator extends AbstractBlockInventoryTranslator
} }
private boolean isInvalidAction(ItemStackRequestSlotData slotData) { private boolean isInvalidAction(ItemStackRequestSlotData slotData) {
return slotData.getContainer().equals(ContainerSlotType.SMITHING_TABLE_TEMPLATE); return slotData.getContainerName().getContainer().equals(ContainerSlotType.SMITHING_TABLE_TEMPLATE);
} }
@Override @Override

View file

@ -58,6 +58,7 @@ import org.geysermc.geyser.util.InventoryUtils;
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.GameMode; import org.geysermc.mcprotocollib.protocol.data.game.entity.player.GameMode;
import org.geysermc.mcprotocollib.protocol.data.game.inventory.ContainerType; import org.geysermc.mcprotocollib.protocol.data.game.inventory.ContainerType;
import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack; import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType;
import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory.ServerboundSetCreativeModeSlotPacket; import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory.ServerboundSetCreativeModeSlotPacket;
import java.util.Arrays; import java.util.Arrays;
@ -103,8 +104,8 @@ public class PlayerInventoryTranslator extends InventoryTranslator {
contents[i - 5] = item.getItemData(session); contents[i - 5] = item.getItemData(session);
if (i == 5 && if (i == 5 &&
item.asItem() == Items.PLAYER_HEAD && item.asItem() == Items.PLAYER_HEAD &&
item.getComponents() != null) { item.hasNonBaseComponents()) {
FakeHeadProvider.setHead(session, session.getPlayerEntity(), item.getComponents()); FakeHeadProvider.setHead(session, session.getPlayerEntity(), item.getComponent(DataComponentType.PROFILE));
} }
} }
armorContentPacket.setContents(Arrays.asList(contents)); armorContentPacket.setContents(Arrays.asList(contents));
@ -147,8 +148,8 @@ public class PlayerInventoryTranslator extends InventoryTranslator {
if (slot == 5) { if (slot == 5) {
// Check for custom skull // Check for custom skull
if (javaItem.asItem() == Items.PLAYER_HEAD if (javaItem.asItem() == Items.PLAYER_HEAD
&& javaItem.getComponents() != null) { && javaItem.hasNonBaseComponents()) {
FakeHeadProvider.setHead(session, session.getPlayerEntity(), javaItem.getComponents()); FakeHeadProvider.setHead(session, session.getPlayerEntity(), javaItem.getComponent(DataComponentType.PROFILE));
} else { } else {
FakeHeadProvider.restoreOriginalSkin(session, session.getPlayerEntity()); FakeHeadProvider.restoreOriginalSkin(session, session.getPlayerEntity());
} }
@ -183,7 +184,7 @@ public class PlayerInventoryTranslator extends InventoryTranslator {
@Override @Override
public int bedrockSlotToJava(ItemStackRequestSlotData slotInfoData) { public int bedrockSlotToJava(ItemStackRequestSlotData slotInfoData) {
int slotnum = slotInfoData.getSlot(); int slotnum = slotInfoData.getSlot();
switch (slotInfoData.getContainer()) { switch (slotInfoData.getContainerName().getContainer()) {
case HOTBAR_AND_INVENTORY: case HOTBAR_AND_INVENTORY:
case HOTBAR: case HOTBAR:
case INVENTORY: case INVENTORY:
@ -461,7 +462,7 @@ public class PlayerInventoryTranslator extends InventoryTranslator {
} }
craftState = CraftState.TRANSFER; craftState = CraftState.TRANSFER;
if (transferAction.getSource().getContainer() != ContainerSlotType.CREATED_OUTPUT) { if (transferAction.getSource().getContainerName().getContainer() != ContainerSlotType.CREATED_OUTPUT) {
return rejectRequest(request); return rejectRequest(request);
} }
@ -494,7 +495,7 @@ public class PlayerInventoryTranslator extends InventoryTranslator {
} }
DropAction dropAction = (DropAction) action; DropAction dropAction = (DropAction) action;
if (dropAction.getSource().getContainer() != ContainerSlotType.CREATED_OUTPUT || dropAction.getSource().getSlot() != 50) { if (dropAction.getSource().getContainerName().getContainer() != ContainerSlotType.CREATED_OUTPUT || dropAction.getSource().getSlot() != 50) {
return rejectRequest(request); return rejectRequest(request);
} }
@ -531,7 +532,7 @@ public class PlayerInventoryTranslator extends InventoryTranslator {
} }
private static boolean isCraftingGrid(ItemStackRequestSlotData slotInfoData) { private static boolean isCraftingGrid(ItemStackRequestSlotData slotInfoData) {
return slotInfoData.getContainer() == ContainerSlotType.CRAFTING_INPUT; return slotInfoData.getContainerName().getContainer() == ContainerSlotType.CRAFTING_INPUT;
} }
@Override @Override

View file

@ -44,7 +44,7 @@ public class SmithingInventoryTranslator extends AbstractBlockInventoryTranslato
@Override @Override
public int bedrockSlotToJava(ItemStackRequestSlotData slotInfoData) { public int bedrockSlotToJava(ItemStackRequestSlotData slotInfoData) {
return switch (slotInfoData.getContainer()) { return switch (slotInfoData.getContainerName().getContainer()) {
case SMITHING_TABLE_TEMPLATE -> TEMPLATE; case SMITHING_TABLE_TEMPLATE -> TEMPLATE;
case SMITHING_TABLE_INPUT -> INPUT; case SMITHING_TABLE_INPUT -> INPUT;
case SMITHING_TABLE_MATERIAL -> MATERIAL; case SMITHING_TABLE_MATERIAL -> MATERIAL;

View file

@ -84,7 +84,7 @@ public class StonecutterInventoryTranslator extends AbstractBlockInventoryTransl
@Override @Override
public int bedrockSlotToJava(ItemStackRequestSlotData slotInfoData) { public int bedrockSlotToJava(ItemStackRequestSlotData slotInfoData) {
return switch (slotInfoData.getContainer()) { return switch (slotInfoData.getContainerName().getContainer()) {
case STONECUTTER_INPUT -> 0; case STONECUTTER_INPUT -> 0;
case STONECUTTER_RESULT, CREATED_OUTPUT -> 1; case STONECUTTER_RESULT, CREATED_OUTPUT -> 1;
default -> super.bedrockSlotToJava(slotInfoData); default -> super.bedrockSlotToJava(slotInfoData);

View file

@ -53,10 +53,10 @@ public abstract class ChestedHorseInventoryTranslator extends AbstractHorseInven
@Override @Override
public int bedrockSlotToJava(ItemStackRequestSlotData slotInfoData) { public int bedrockSlotToJava(ItemStackRequestSlotData slotInfoData) {
if (slotInfoData.getContainer() == ContainerSlotType.HORSE_EQUIP) { if (slotInfoData.getContainerName().getContainer() == ContainerSlotType.HORSE_EQUIP) {
return this.equipSlot; return this.equipSlot;
} }
if (slotInfoData.getContainer() == ContainerSlotType.LEVEL_ENTITY) { if (slotInfoData.getContainerName().getContainer() == ContainerSlotType.LEVEL_ENTITY) {
return slotInfoData.getSlot() + 1; return slotInfoData.getSlot() + 1;
} }
return super.bedrockSlotToJava(slotInfoData); return super.bedrockSlotToJava(slotInfoData);

View file

@ -36,7 +36,7 @@ public class HorseInventoryTranslator extends AbstractHorseInventoryTranslator {
@Override @Override
public int bedrockSlotToJava(ItemStackRequestSlotData slotInfoData) { public int bedrockSlotToJava(ItemStackRequestSlotData slotInfoData) {
if (slotInfoData.getContainer() == ContainerSlotType.HORSE_EQUIP) { if (slotInfoData.getContainerName().getContainer() == ContainerSlotType.HORSE_EQUIP) {
return slotInfoData.getSlot(); return slotInfoData.getSlot();
} }
return super.bedrockSlotToJava(slotInfoData); return super.bedrockSlotToJava(slotInfoData);

View file

@ -25,6 +25,7 @@
package org.geysermc.geyser.translator.item; package org.geysermc.geyser.translator.item;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.CustomModelData;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents; import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType; import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType;
import it.unimi.dsi.fastutil.Pair; import it.unimi.dsi.fastutil.Pair;
@ -52,8 +53,16 @@ public final class CustomItemTranslator {
return null; return null;
} }
int customModelData = components.getOrDefault(DataComponentType.CUSTOM_MODEL_DATA, 0); // TODO 1.21.4
boolean checkDamage = mapping.getJavaItem().maxDamage() > 0; float customModelDataInt = 0;
CustomModelData customModelData = components.get(DataComponentType.CUSTOM_MODEL_DATA);
if (customModelData != null) {
if (!customModelData.floats().isEmpty()) {
customModelDataInt = customModelData.floats().get(0);
}
}
boolean checkDamage = mapping.getJavaItem().defaultMaxDamage() > 0;
int damage = !checkDamage ? 0 : components.getOrDefault(DataComponentType.DAMAGE, 0); int damage = !checkDamage ? 0 : components.getOrDefault(DataComponentType.DAMAGE, 0);
boolean unbreakable = checkDamage && !isDamaged(components, damage); boolean unbreakable = checkDamage && !isDamaged(components, damage);
@ -88,7 +97,7 @@ public final class CustomItemTranslator {
} }
OptionalInt customModelDataOption = options.customModelData(); OptionalInt customModelDataOption = options.customModelData();
if (customModelDataOption.isPresent() && customModelData < customModelDataOption.getAsInt()) { if (customModelDataOption.isPresent() && customModelDataInt < customModelDataOption.getAsInt()) {
continue; continue;
} }

View file

@ -25,6 +25,7 @@
package org.geysermc.geyser.translator.item; package org.geysermc.geyser.translator.item;
import net.kyori.adventure.key.Key;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.TranslatableComponent; import net.kyori.adventure.text.TranslatableComponent;
import net.kyori.adventure.text.format.NamedTextColor; import net.kyori.adventure.text.format.NamedTextColor;
@ -38,10 +39,10 @@ import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition;
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.api.block.custom.CustomBlockData; import org.geysermc.geyser.api.block.custom.CustomBlockData;
import org.geysermc.geyser.entity.attribute.GeyserAttributeType;
import org.geysermc.geyser.inventory.GeyserItemStack; import org.geysermc.geyser.inventory.GeyserItemStack;
import org.geysermc.geyser.item.Items; import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.item.components.Rarity; import org.geysermc.geyser.item.components.Rarity;
import org.geysermc.geyser.item.type.BedrockRequiresTagItem;
import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.item.type.Item;
import org.geysermc.geyser.level.block.type.Block; import org.geysermc.geyser.level.block.type.Block;
import org.geysermc.geyser.registry.BlockRegistries; import org.geysermc.geyser.registry.BlockRegistries;
@ -53,6 +54,7 @@ import org.geysermc.geyser.text.ChatColor;
import org.geysermc.geyser.text.MinecraftLocale; import org.geysermc.geyser.text.MinecraftLocale;
import org.geysermc.geyser.translator.text.MessageTranslator; import org.geysermc.geyser.translator.text.MessageTranslator;
import org.geysermc.geyser.util.InventoryUtils; import org.geysermc.geyser.util.InventoryUtils;
import org.geysermc.geyser.util.MinecraftKey;
import org.geysermc.mcprotocollib.auth.GameProfile; import org.geysermc.mcprotocollib.auth.GameProfile;
import org.geysermc.mcprotocollib.auth.GameProfile.Texture; import org.geysermc.mcprotocollib.auth.GameProfile.Texture;
import org.geysermc.mcprotocollib.auth.GameProfile.TextureType; import org.geysermc.mcprotocollib.auth.GameProfile.TextureType;
@ -90,19 +92,27 @@ public final class ItemTranslator {
ItemAttributeModifiers.EquipmentSlotGroup.FEET ItemAttributeModifiers.EquipmentSlotGroup.FEET
}; };
private static final DecimalFormat ATTRIBUTE_FORMAT = new DecimalFormat("0.#####"); private static final DecimalFormat ATTRIBUTE_FORMAT = new DecimalFormat("0.#####");
private static final Key BASE_ATTACK_DAMAGE_ID = MinecraftKey.key("base_attack_damage");
private static final Key BASE_ATTACK_SPEED_ID = MinecraftKey.key("base_attack_speed");
static { static {
// These are the only slots that are used and have translation strings // Maps slot groups to their respective translation names, ordered in their Java edition order in the item tooltip
SLOT_NAMES = new EnumMap<>(ItemAttributeModifiers.EquipmentSlotGroup.class); SLOT_NAMES = new EnumMap<>(ItemAttributeModifiers.EquipmentSlotGroup.class);
SLOT_NAMES.put(ItemAttributeModifiers.EquipmentSlotGroup.ANY, "any");
SLOT_NAMES.put(ItemAttributeModifiers.EquipmentSlotGroup.MAIN_HAND, "mainhand"); SLOT_NAMES.put(ItemAttributeModifiers.EquipmentSlotGroup.MAIN_HAND, "mainhand");
SLOT_NAMES.put(ItemAttributeModifiers.EquipmentSlotGroup.OFF_HAND, "offhand"); SLOT_NAMES.put(ItemAttributeModifiers.EquipmentSlotGroup.OFF_HAND, "offhand");
SLOT_NAMES.put(ItemAttributeModifiers.EquipmentSlotGroup.HAND, "hand");
SLOT_NAMES.put(ItemAttributeModifiers.EquipmentSlotGroup.FEET, "feet"); SLOT_NAMES.put(ItemAttributeModifiers.EquipmentSlotGroup.FEET, "feet");
SLOT_NAMES.put(ItemAttributeModifiers.EquipmentSlotGroup.LEGS, "legs"); SLOT_NAMES.put(ItemAttributeModifiers.EquipmentSlotGroup.LEGS, "legs");
SLOT_NAMES.put(ItemAttributeModifiers.EquipmentSlotGroup.CHEST, "chest"); SLOT_NAMES.put(ItemAttributeModifiers.EquipmentSlotGroup.CHEST, "chest");
SLOT_NAMES.put(ItemAttributeModifiers.EquipmentSlotGroup.HEAD, "head"); SLOT_NAMES.put(ItemAttributeModifiers.EquipmentSlotGroup.HEAD, "head");
SLOT_NAMES.put(ItemAttributeModifiers.EquipmentSlotGroup.ARMOR, "armor");
SLOT_NAMES.put(ItemAttributeModifiers.EquipmentSlotGroup.BODY, "body"); SLOT_NAMES.put(ItemAttributeModifiers.EquipmentSlotGroup.BODY, "body");
} }
private final static List<Item> GLINT_PRESENT = List.of(Items.ENCHANTED_GOLDEN_APPLE, Items.EXPERIENCE_BOTTLE, Items.WRITTEN_BOOK,
Items.NETHER_STAR, Items.ENCHANTED_BOOK, Items.END_CRYSTAL);
private ItemTranslator() { private ItemTranslator() {
} }
@ -119,7 +129,7 @@ public final class ItemTranslator {
NbtMap nbt = data.getTag(); NbtMap nbt = data.getTag();
if (nbt != null && !nbt.isEmpty()) { if (nbt != null && !nbt.isEmpty()) {
// translateToJava may have added components // translateToJava may have added components
DataComponents components = itemStack.getComponents() == null ? new DataComponents(new HashMap<>()) : itemStack.getComponents(); DataComponents components = itemStack.getOrCreateComponents();
javaItem.translateNbtToJava(session, nbt, components, bedrockItem); javaItem.translateNbtToJava(session, nbt, components, bedrockItem);
if (!components.getDataComponents().isEmpty()) { if (!components.getDataComponents().isEmpty()) {
itemStack.setComponents(components); itemStack.setComponents(components);
@ -156,42 +166,24 @@ public final class ItemTranslator {
public static ItemData.@NonNull Builder translateToBedrock(GeyserSession session, Item javaItem, ItemMapping bedrockItem, int count, @Nullable DataComponents components) { public static ItemData.@NonNull Builder translateToBedrock(GeyserSession session, Item javaItem, ItemMapping bedrockItem, int count, @Nullable DataComponents components) {
BedrockItemBuilder nbtBuilder = new BedrockItemBuilder(); BedrockItemBuilder nbtBuilder = new BedrockItemBuilder();
boolean hideTooltips = false; // Populates default components that aren't sent over the network
if (components != null) { components = javaItem.gatherComponents(components);
javaItem.translateComponentsToBedrock(session, components, nbtBuilder);
if (components.get(DataComponentType.HIDE_TOOLTIP) != null) hideTooltips = true;
}
// Fixes fireworks crafting recipe: they always contain a tag // Translate item-specific components
// TODO remove once all items have their default components javaItem.translateComponentsToBedrock(session, components, nbtBuilder);
if (javaItem instanceof BedrockRequiresTagItem requiresTagItem) {
requiresTagItem.addRequiredNbt(session, components, nbtBuilder);
}
Rarity rarity = javaItem.rarity();
boolean enchantmentGlint = javaItem.glint();
if (components != null) {
Integer rarityIndex = components.get(DataComponentType.RARITY);
if (rarityIndex != null) {
rarity = Rarity.fromId(rarityIndex);
}
Boolean enchantmentGlintOverride = components.get(DataComponentType.ENCHANTMENT_GLINT_OVERRIDE);
if (enchantmentGlintOverride != null) {
enchantmentGlint = enchantmentGlintOverride;
}
}
Rarity rarity = Rarity.fromId(components.getOrDefault(DataComponentType.RARITY, 0));
String customName = getCustomName(session, components, bedrockItem, rarity.getColor()); String customName = getCustomName(session, components, bedrockItem, rarity.getColor());
if (customName != null) { if (customName != null) {
nbtBuilder.setCustomName(customName); nbtBuilder.setCustomName(customName);
} }
if (components != null) { boolean hideTooltips = components.get(DataComponentType.HIDE_TOOLTIP) != null;
ItemAttributeModifiers attributeModifiers = components.get(DataComponentType.ATTRIBUTE_MODIFIERS);
if (attributeModifiers != null && attributeModifiers.isShowInTooltip() && !hideTooltips) { ItemAttributeModifiers attributeModifiers = components.get(DataComponentType.ATTRIBUTE_MODIFIERS);
// only add if attribute modifiers do not indicate to hide them if (attributeModifiers != null && attributeModifiers.isShowInTooltip() && !hideTooltips) {
addAttributeLore(attributeModifiers, nbtBuilder, session.locale()); // only add if attribute modifiers do not indicate to hide them
} addAttributeLore(session, attributeModifiers, nbtBuilder, session.locale());
} }
if (session.isAdvancedTooltips() && !hideTooltips) { if (session.isAdvancedTooltips() && !hideTooltips) {
@ -199,7 +191,7 @@ public final class ItemTranslator {
} }
// Add enchantment override. We can't remove it - enchantments would stop showing - but we can add it. // Add enchantment override. We can't remove it - enchantments would stop showing - but we can add it.
if (enchantmentGlint) { if (components.getOrDefault(DataComponentType.ENCHANTMENT_GLINT_OVERRIDE, false) && !GLINT_PRESENT.contains(javaItem)) {
NbtMapBuilder nbtMapBuilder = nbtBuilder.getOrCreateNbt(); NbtMapBuilder nbtMapBuilder = nbtBuilder.getOrCreateNbt();
nbtMapBuilder.putIfAbsent("ench", NbtList.EMPTY); nbtMapBuilder.putIfAbsent("ench", NbtList.EMPTY);
} }
@ -218,23 +210,21 @@ public final class ItemTranslator {
} }
if (bedrockItem.getJavaItem().equals(Items.PLAYER_HEAD)) { if (bedrockItem.getJavaItem().equals(Items.PLAYER_HEAD)) {
translatePlayerHead(session, components, builder); translatePlayerHead(session, components.get(DataComponentType.PROFILE), builder);
} }
translateCustomItem(components, builder, bedrockItem); translateCustomItem(components, builder, bedrockItem);
if (components != null) { // Translate the canDestroy and canPlaceOn Java components
// Translate the canDestroy and canPlaceOn Java components AdventureModePredicate canDestroy = components.get(DataComponentType.CAN_BREAK);
AdventureModePredicate canDestroy = components.get(DataComponentType.CAN_BREAK); AdventureModePredicate canPlaceOn = components.get(DataComponentType.CAN_PLACE_ON);
AdventureModePredicate canPlaceOn = components.get(DataComponentType.CAN_PLACE_ON); String[] canBreak = getCanModify(session, canDestroy);
String[] canBreak = getCanModify(session, canDestroy); String[] canPlace = getCanModify(session, canPlaceOn);
String[] canPlace = getCanModify(session, canPlaceOn); if (canBreak != null) {
if (canBreak != null) { builder.canBreak(canBreak);
builder.canBreak(canBreak); }
} if (canPlace != null) {
if (canPlace != null) { builder.canPlace(canPlace);
builder.canPlace(canPlace);
}
} }
return builder; return builder;
@ -247,31 +237,17 @@ public final class ItemTranslator {
* @param modifiers the attribute modifiers of the ItemStack * @param modifiers the attribute modifiers of the ItemStack
* @param language the locale of the player * @param language the locale of the player
*/ */
private static void addAttributeLore(ItemAttributeModifiers modifiers, BedrockItemBuilder builder, String language) { private static void addAttributeLore(GeyserSession session, ItemAttributeModifiers modifiers, BedrockItemBuilder builder, String language) {
// maps each slot to the modifiers applied when in such slot // maps each slot to the modifiers applied when in such slot
Map<ItemAttributeModifiers.EquipmentSlotGroup, List<String>> slotsToModifiers = new HashMap<>(); Map<ItemAttributeModifiers.EquipmentSlotGroup, List<String>> slotsToModifiers = new HashMap<>();
for (ItemAttributeModifiers.Entry entry : modifiers.getModifiers()) { for (ItemAttributeModifiers.Entry entry : modifiers.getModifiers()) {
// convert the modifier tag to a lore entry // convert the modifier tag to a lore entry
String loreEntry = attributeToLore(entry.getAttribute(), entry.getModifier(), language); String loreEntry = attributeToLore(session, entry.getAttribute(), entry.getModifier(), language);
if (loreEntry == null) { if (loreEntry == null) {
continue; // invalid or failed continue; // invalid or failed
} }
ItemAttributeModifiers.EquipmentSlotGroup slotGroup = entry.getSlot(); slotsToModifiers.computeIfAbsent(entry.getSlot(), s -> new ArrayList<>()).add(loreEntry);
if (slotGroup == ItemAttributeModifiers.EquipmentSlotGroup.ARMOR) {
// modifier applies to all armor slots
for (ItemAttributeModifiers.EquipmentSlotGroup slot : ARMOR_SLOT_NAMES) {
slotsToModifiers.computeIfAbsent(slot, s -> new ArrayList<>()).add(loreEntry);
}
} else if (slotGroup == ItemAttributeModifiers.EquipmentSlotGroup.ANY) {
// modifier applies to all slots implicitly
for (var slot : SLOT_NAMES.keySet()) {
slotsToModifiers.computeIfAbsent(slot, s -> new ArrayList<>()).add(loreEntry);
}
} else {
// modifier applies to only the specified slot
slotsToModifiers.computeIfAbsent(slotGroup, s -> new ArrayList<>()).add(loreEntry);
}
} }
// iterate through the small array, not the map, so that ordering matches Java Edition // iterate through the small array, not the map, so that ordering matches Java Edition
@ -297,7 +273,7 @@ public final class ItemTranslator {
} }
@Nullable @Nullable
private static String attributeToLore(int attribute, ItemAttributeModifiers.AttributeModifier modifier, String language) { private static String attributeToLore(GeyserSession session, int attribute, ItemAttributeModifiers.AttributeModifier modifier, String language) {
double amount = modifier.getAmount(); double amount = modifier.getAmount();
if (amount == 0) { if (amount == 0) {
return null; return null;
@ -307,24 +283,35 @@ public final class ItemTranslator {
// the namespace does not need to be present, but if it is, the java client ignores it as of pre-1.20.5 // the namespace does not need to be present, but if it is, the java client ignores it as of pre-1.20.5
ModifierOperation operation = modifier.getOperation(); ModifierOperation operation = modifier.getOperation();
boolean baseModifier = false;
String operationTotal = switch (operation) { String operationTotal = switch (operation) {
case ADD -> { case ADD -> {
if (name.equals("generic.knockback_resistance")) { if (name.equals("knockback_resistance")) {
amount *= 10; amount *= 10;
} }
if (modifier.getId().equals(BASE_ATTACK_DAMAGE_ID)) {
amount += session.getPlayerEntity().attributeOrDefault(GeyserAttributeType.ATTACK_DAMAGE);
baseModifier = true;
} else if (modifier.getId().equals(BASE_ATTACK_SPEED_ID)) {
amount += session.getPlayerEntity().attributeOrDefault(GeyserAttributeType.ATTACK_SPEED);
baseModifier = true;
}
yield ATTRIBUTE_FORMAT.format(amount); yield ATTRIBUTE_FORMAT.format(amount);
} }
case ADD_MULTIPLIED_BASE, ADD_MULTIPLIED_TOTAL -> case ADD_MULTIPLIED_BASE, ADD_MULTIPLIED_TOTAL ->
ATTRIBUTE_FORMAT.format(amount * 100) + "%"; ATTRIBUTE_FORMAT.format(amount * 100) + "%";
}; };
if (amount > 0) { if (amount > 0 && !baseModifier) {
operationTotal = "+" + operationTotal; operationTotal = "+" + operationTotal;
} }
Component attributeComponent = Component.text() Component attributeComponent = Component.text()
.resetStyle() .resetStyle()
.color(amount > 0 ? NamedTextColor.BLUE : NamedTextColor.RED) .color(baseModifier ? NamedTextColor.DARK_GREEN : amount > 0 ? NamedTextColor.BLUE : NamedTextColor.RED)
.append(Component.text(operationTotal + " "), Component.translatable("attribute.name." + name)) .append(Component.text(" " + operationTotal + " "), Component.translatable("attribute.name." + name))
.build(); .build();
return MessageTranslator.convertMessage(attributeComponent, language); return MessageTranslator.convertMessage(attributeComponent, language);
@ -390,7 +377,7 @@ public final class ItemTranslator {
} }
private static void addAdvancedTooltips(@Nullable DataComponents components, BedrockItemBuilder builder, Item item, String language) { private static void addAdvancedTooltips(@Nullable DataComponents components, BedrockItemBuilder builder, Item item, String language) {
int maxDurability = item.maxDamage(); int maxDurability = item.defaultMaxDamage();
if (maxDurability != 0 && components != null) { if (maxDurability != 0 && components != null) {
Integer durabilityComponent = components.get(DataComponentType.DAMAGE); Integer durabilityComponent = components.get(DataComponentType.DAMAGE);
@ -477,7 +464,7 @@ public final class ItemTranslator {
return ItemDefinition.AIR; return ItemDefinition.AIR;
} }
ItemMapping mapping = itemStack.asItem().toBedrockDefinition(itemStack.getComponents(), session.getItemMappings()); ItemMapping mapping = itemStack.asItem().toBedrockDefinition(itemStack.getAllComponents(), session.getItemMappings());
ItemDefinition itemDefinition = mapping.getBedrockDefinition(); ItemDefinition itemDefinition = mapping.getBedrockDefinition();
CustomBlockData customBlockData = BlockRegistries.CUSTOM_BLOCK_ITEM_OVERRIDES.getOrDefault( CustomBlockData customBlockData = BlockRegistries.CUSTOM_BLOCK_ITEM_OVERRIDES.getOrDefault(
@ -487,7 +474,7 @@ public final class ItemTranslator {
} }
if (mapping.getJavaItem().equals(Items.PLAYER_HEAD)) { if (mapping.getJavaItem().equals(Items.PLAYER_HEAD)) {
CustomSkull customSkull = getCustomSkull(itemStack.getComponents()); CustomSkull customSkull = getCustomSkull(itemStack.getComponent(DataComponentType.PROFILE));
if (customSkull != null) { if (customSkull != null) {
itemDefinition = session.getItemMappings().getCustomBlockItemDefinitions().get(customSkull.getCustomBlockData()); itemDefinition = session.getItemMappings().getCustomBlockItemDefinitions().get(customSkull.getCustomBlockData());
} }
@ -565,39 +552,35 @@ public final class ItemTranslator {
builder.blockDefinition(blockDefinition); builder.blockDefinition(blockDefinition);
} }
private static @Nullable CustomSkull getCustomSkull(DataComponents components) { private static @Nullable CustomSkull getCustomSkull(@Nullable GameProfile profile) {
if (components == null) { if (profile == null) {
return null; return null;
} }
GameProfile profile = components.get(DataComponentType.PROFILE);
if (profile != null) {
Map<TextureType, Texture> textures;
try {
textures = profile.getTextures(false);
} catch (IllegalStateException e) {
GeyserImpl.getInstance().getLogger().debug("Could not decode player head from profile %s, got: %s".formatted(profile, e.getMessage()));
return null;
}
if (textures == null || textures.isEmpty()) { Map<TextureType, Texture> textures;
return null; try {
} textures = profile.getTextures(false);
} catch (IllegalStateException e) {
Texture skinTexture = textures.get(TextureType.SKIN); GeyserImpl.getInstance().getLogger().debug("Could not decode player head from profile %s, got: %s".formatted(profile, e.getMessage()));
return null;
if (skinTexture == null) {
return null;
}
String skinHash = skinTexture.getURL().substring(skinTexture.getURL().lastIndexOf('/') + 1);
return BlockRegistries.CUSTOM_SKULLS.get(skinHash);
} }
return null;
if (textures == null || textures.isEmpty()) {
return null;
}
Texture skinTexture = textures.get(TextureType.SKIN);
if (skinTexture == null) {
return null;
}
String skinHash = skinTexture.getURL().substring(skinTexture.getURL().lastIndexOf('/') + 1);
return BlockRegistries.CUSTOM_SKULLS.get(skinHash);
} }
private static void translatePlayerHead(GeyserSession session, DataComponents components, ItemData.Builder builder) { private static void translatePlayerHead(GeyserSession session, GameProfile profile, ItemData.Builder builder) {
CustomSkull customSkull = getCustomSkull(components); CustomSkull customSkull = getCustomSkull(profile);
if (customSkull != null) { if (customSkull != null) {
CustomBlockData customBlockData = customSkull.getCustomBlockData(); CustomBlockData customBlockData = customSkull.getCustomBlockData();
ItemDefinition itemDefinition = session.getItemMappings().getCustomBlockItemDefinitions().get(customBlockData); ItemDefinition itemDefinition = session.getItemMappings().getCustomBlockItemDefinitions().get(customBlockData);

View file

@ -27,18 +27,14 @@ package org.geysermc.geyser.translator.protocol.bedrock;
import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.math.vector.Vector3i;
import org.cloudburstmc.protocol.bedrock.packet.BlockPickRequestPacket; import org.cloudburstmc.protocol.bedrock.packet.BlockPickRequestPacket;
import org.geysermc.geyser.entity.EntityDefinitions;
import org.geysermc.geyser.entity.type.ItemFrameEntity; import org.geysermc.geyser.entity.type.ItemFrameEntity;
import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.level.block.Blocks; import org.geysermc.geyser.level.block.Blocks;
import org.geysermc.geyser.level.block.type.BannerBlock;
import org.geysermc.geyser.level.block.type.BlockState; import org.geysermc.geyser.level.block.type.BlockState;
import org.geysermc.geyser.level.block.type.SkullBlock;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.PacketTranslator;
import org.geysermc.geyser.translator.protocol.Translator; import org.geysermc.geyser.translator.protocol.Translator;
import org.geysermc.geyser.util.InventoryUtils; import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory.ServerboundPickItemFromBlockPacket;
import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack; import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory.ServerboundPickItemFromEntityPacket;
@Translator(packet = BlockPickRequestPacket.class) @Translator(packet = BlockPickRequestPacket.class)
public class BedrockBlockPickRequestTranslator extends PacketTranslator<BlockPickRequestPacket> { public class BedrockBlockPickRequestTranslator extends PacketTranslator<BlockPickRequestPacket> {
@ -52,42 +48,14 @@ public class BedrockBlockPickRequestTranslator extends PacketTranslator<BlockPic
if (blockToPick.is(Blocks.AIR)) { if (blockToPick.is(Blocks.AIR)) {
// Check for an item frame since the client thinks that's a block when it's an entity in Java // Check for an item frame since the client thinks that's a block when it's an entity in Java
ItemFrameEntity entity = ItemFrameEntity.getItemFrameEntity(session, packet.getBlockPosition()); ItemFrameEntity entity = ItemFrameEntity.getItemFrameEntity(session, packet.getBlockPosition());
if (entity != null) { if (entity != null) {
// Check to see if the item frame has an item in it first session.sendDownstreamGamePacket(new ServerboundPickItemFromEntityPacket(entity.javaId(), packet.isAddUserData()));
if (!InventoryUtils.isEmpty(entity.getHeldItem())) {
// Grab the item in the frame
InventoryUtils.findOrCreateItem(session, entity.getHeldItem());
} else {
// Grab the frame as the item
InventoryUtils.findOrCreateItem(session, entity.getDefinition() == EntityDefinitions.GLOW_ITEM_FRAME ? Items.GLOW_ITEM_FRAME : Items.ITEM_FRAME);
}
} }
return; return;
} }
boolean addExtraData = packet.isAddUserData() && blockToPick.block().hasBlockEntity(); // Holding down CTRL boolean addExtraData = packet.isAddUserData() && blockToPick.block().hasBlockEntity(); // Holding down CTRL
if (session.isInstabuild() && addExtraData && blockToPick.block() instanceof SkullBlock skull) { session.sendDownstreamGamePacket(new ServerboundPickItemFromBlockPacket(vector, addExtraData));
InventoryUtils.findOrCreateItem(session, skull.pickItem(session, blockToPick, vector));
return;
}
if (blockToPick.block() instanceof BannerBlock) {
session.getGeyser().getWorldManager().getPickItemComponents(session, vector.getX(), vector.getY(), vector.getZ(), addExtraData)
.whenComplete((components, ex) -> session.ensureInEventLoop(() -> {
if (components == null) {
pickItem(session, blockToPick);
return;
}
ItemStack itemStack = new ItemStack(blockToPick.block().asItem().javaId(), 1, components);
InventoryUtils.findOrCreateItem(session, itemStack);
}));
return;
}
pickItem(session, blockToPick);
}
private void pickItem(GeyserSession session, BlockState state) {
InventoryUtils.findOrCreateItem(session, state.block().pickItem(state));
} }
} }

View file

@ -53,7 +53,7 @@ public class BedrockBookEditTranslator extends PacketTranslator<BookEditPacket>
GeyserItemStack itemStack = session.getPlayerInventory().getItemInHand(); GeyserItemStack itemStack = session.getPlayerInventory().getItemInHand();
if (itemStack != null) { if (itemStack != null) {
DataComponents components = itemStack.getComponents() != null ? itemStack.getComponents() : new DataComponents(new HashMap<>()); DataComponents components = itemStack.getOrCreateComponents();
ItemStack bookItem = new ItemStack(itemStack.getJavaId(), itemStack.getAmount(), components); ItemStack bookItem = new ItemStack(itemStack.getJavaId(), itemStack.getAmount(), components);
List<String> pages = new LinkedList<>(); List<String> pages = new LinkedList<>();

View file

@ -26,15 +26,11 @@
package org.geysermc.geyser.translator.protocol.bedrock; package org.geysermc.geyser.translator.protocol.bedrock;
import org.cloudburstmc.protocol.bedrock.packet.EntityPickRequestPacket; import org.cloudburstmc.protocol.bedrock.packet.EntityPickRequestPacket;
import org.geysermc.geyser.entity.type.BoatEntity;
import org.geysermc.geyser.entity.type.Entity; import org.geysermc.geyser.entity.type.Entity;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.PacketTranslator;
import org.geysermc.geyser.translator.protocol.Translator; import org.geysermc.geyser.translator.protocol.Translator;
import org.geysermc.geyser.util.InventoryUtils; import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory.ServerboundPickItemFromEntityPacket;
import java.util.Locale;
/** /**
* Called when the Bedrock user uses the pick block button on an entity * Called when the Bedrock user uses the pick block button on an entity
@ -49,35 +45,8 @@ public class BedrockEntityPickRequestTranslator extends PacketTranslator<EntityP
return; return;
} }
Entity entity = session.getEntityCache().getEntityByGeyserId(packet.getRuntimeEntityId()); Entity entity = session.getEntityCache().getEntityByGeyserId(packet.getRuntimeEntityId());
if (entity == null) return; if (entity != null) {
session.sendDownstreamGamePacket(new ServerboundPickItemFromEntityPacket(entity.javaId(), false));
if (entity instanceof BoatEntity boat) {
InventoryUtils.findOrCreateItem(session, boat.getPickItem());
return;
} }
// Get the corresponding item
String itemName;
switch (entity.getDefinition().entityType()) {
case LEASH_KNOT -> itemName = "lead";
case CHEST_MINECART, COMMAND_BLOCK_MINECART, FURNACE_MINECART, HOPPER_MINECART, TNT_MINECART ->
// The Bedrock identifier matches the item name which moves MINECART to the end of the name
// TODO test
itemName = entity.getDefinition().identifier();
case SPAWNER_MINECART -> itemName = "minecart"; // Turns into a normal minecart
//case ITEM_FRAME -> Not an entity in Bedrock Edition
//case GLOW_ITEM_FRAME ->
case ARMOR_STAND, END_CRYSTAL, MINECART, PAINTING ->
// No spawn egg, just an item
itemName = entity.getDefinition().entityType().toString().toLowerCase(Locale.ROOT);
default -> itemName = entity.getDefinition().entityType().toString().toLowerCase(Locale.ROOT) + "_spawn_egg";
}
String fullItemName = "minecraft:" + itemName;
ItemMapping mapping = session.getItemMappings().getMapping(fullItemName);
// Verify it is, indeed, an item
if (mapping == null) return;
InventoryUtils.findOrCreateItem(session, fullItemName);
} }
} }

View file

@ -34,6 +34,7 @@ import org.geysermc.geyser.translator.protocol.PacketTranslator;
import org.geysermc.geyser.translator.protocol.Translator; import org.geysermc.geyser.translator.protocol.Translator;
import org.geysermc.geyser.util.InventoryUtils; import org.geysermc.geyser.util.InventoryUtils;
import org.geysermc.geyser.util.LoginEncryptionUtils; import org.geysermc.geyser.util.LoginEncryptionUtils;
import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.ServerboundPlayerLoadedPacket;
@Translator(packet = SetLocalPlayerAsInitializedPacket.class) @Translator(packet = SetLocalPlayerAsInitializedPacket.class)
public class BedrockSetLocalPlayerAsInitializedTranslator extends PacketTranslator<SetLocalPlayerAsInitializedPacket> { public class BedrockSetLocalPlayerAsInitializedTranslator extends PacketTranslator<SetLocalPlayerAsInitializedPacket> {
@ -72,6 +73,7 @@ public class BedrockSetLocalPlayerAsInitializedTranslator extends PacketTranslat
session.getFormCache().resendAllForms(); session.getFormCache().resendAllForms();
GeyserImpl.getInstance().eventBus().fire(new SessionJoinEvent(session)); GeyserImpl.getInstance().eventBus().fire(new SessionJoinEvent(session));
session.sendDownstreamGamePacket(ServerboundPlayerLoadedPacket.INSTANCE);
} }
} }
} }

View file

@ -91,7 +91,7 @@ public class BedrockInteractTranslator extends PacketTranslator<InteractPacket>
// If the server doesn't agree with our dismount (sends a packet saying we dismounted), // If the server doesn't agree with our dismount (sends a packet saying we dismounted),
// then remount the player. // then remount the player.
SetEntityLinkPacket linkPacket = new SetEntityLinkPacket(); SetEntityLinkPacket linkPacket = new SetEntityLinkPacket();
linkPacket.setEntityLink(new EntityLinkData(vehicleBedrockId, session.getPlayerEntity().getGeyserId(), EntityLinkData.Type.PASSENGER, true, false)); linkPacket.setEntityLink(new EntityLinkData(vehicleBedrockId, session.getPlayerEntity().getGeyserId(), EntityLinkData.Type.PASSENGER, true, false, 0f));
session.sendUpstreamPacket(linkPacket); session.sendUpstreamPacket(linkPacket);
} }
}, 1, TimeUnit.SECONDS)); }, 1, TimeUnit.SECONDS));

View file

@ -32,6 +32,7 @@ import org.cloudburstmc.protocol.bedrock.data.PlayerActionType;
import org.cloudburstmc.protocol.bedrock.data.PlayerBlockActionData; import org.cloudburstmc.protocol.bedrock.data.PlayerBlockActionData;
import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition; import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition;
import org.cloudburstmc.protocol.bedrock.packet.LevelEventPacket; import org.cloudburstmc.protocol.bedrock.packet.LevelEventPacket;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.api.block.custom.CustomBlockState; import org.geysermc.geyser.api.block.custom.CustomBlockState;
import org.geysermc.geyser.entity.type.Entity; import org.geysermc.geyser.entity.type.Entity;
import org.geysermc.geyser.entity.type.ItemFrameEntity; import org.geysermc.geyser.entity.type.ItemFrameEntity;
@ -88,7 +89,7 @@ final class BedrockBlockActions {
LevelEventPacket startBreak = new LevelEventPacket(); LevelEventPacket startBreak = new LevelEventPacket();
startBreak.setType(LevelEvent.BLOCK_START_BREAK); startBreak.setType(LevelEvent.BLOCK_START_BREAK);
startBreak.setPosition(vector.toFloat()); startBreak.setPosition(vector.toFloat());
double breakTime = BlockUtils.getSessionBreakTime(session, BlockState.of(blockState).block()) * 20; double breakTime = BlockUtils.getSessionBreakTimeTicks(session, BlockState.of(blockState).block());
// If the block is custom or the breaking item is custom, we must keep track of break time ourselves // If the block is custom or the breaking item is custom, we must keep track of break time ourselves
GeyserItemStack item = session.getPlayerInventory().getItemInHand(); GeyserItemStack item = session.getPlayerInventory().getItemInHand();
@ -136,7 +137,7 @@ final class BedrockBlockActions {
Direction direction = Direction.VALUES[blockFace]; Direction direction = Direction.VALUES[blockFace];
spawnBlockBreakParticles(session, direction, vector, breakingBlockState); spawnBlockBreakParticles(session, direction, vector, breakingBlockState);
double breakTime = BlockUtils.getSessionBreakTime(session, breakingBlockState.block()) * 20; double breakTime = BlockUtils.getSessionBreakTimeTicks(session, breakingBlockState.block());
// If the block is custom, we must keep track of when it should break ourselves // If the block is custom, we must keep track of when it should break ourselves
long blockBreakStartTime = session.getBlockBreakStartTime(); long blockBreakStartTime = session.getBlockBreakStartTime();
if (blockBreakStartTime != 0) { if (blockBreakStartTime != 0) {
@ -180,6 +181,7 @@ final class BedrockBlockActions {
ServerboundPlayerActionPacket abortBreakingPacket = new ServerboundPlayerActionPacket(PlayerAction.CANCEL_DIGGING, vector, Direction.DOWN, 0); ServerboundPlayerActionPacket abortBreakingPacket = new ServerboundPlayerActionPacket(PlayerAction.CANCEL_DIGGING, vector, Direction.DOWN, 0);
session.sendDownstreamGamePacket(abortBreakingPacket); session.sendDownstreamGamePacket(abortBreakingPacket);
LevelEventPacket stopBreak = new LevelEventPacket(); LevelEventPacket stopBreak = new LevelEventPacket();
stopBreak.setType(LevelEvent.BLOCK_STOP_BREAK); stopBreak.setType(LevelEvent.BLOCK_STOP_BREAK);
stopBreak.setPosition(vector.toFloat()); stopBreak.setPosition(vector.toFloat());

View file

@ -312,8 +312,9 @@ public final class BedrockPlayerAuthInputTranslator extends PacketTranslator<Pla
vehicle.setPosition(vehiclePosition); vehicle.setPosition(vehiclePosition);
ServerboundMoveVehiclePacket moveVehiclePacket = new ServerboundMoveVehiclePacket( ServerboundMoveVehiclePacket moveVehiclePacket = new ServerboundMoveVehiclePacket(
vehiclePosition.getX(), vehiclePosition.getY(), vehiclePosition.getZ(), vehiclePosition.toDouble(),
vehicleRotation.getY() - 90, vehiclePosition.getX() // TODO I wonder if this is related to the horse spinning bugs... vehicleRotation.getY() - 90, vehiclePosition.getX(), // TODO I wonder if this is related to the horse spinning bugs...
vehicle.isOnGround()
); );
session.sendDownstreamGamePacket(moveVehiclePacket); session.sendDownstreamGamePacket(moveVehiclePacket);
} }

View file

@ -45,6 +45,7 @@ import org.geysermc.geyser.util.MinecraftKey;
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.PlayerSpawnInfo; import org.geysermc.mcprotocollib.protocol.data.game.entity.player.PlayerSpawnInfo;
import org.geysermc.mcprotocollib.protocol.packet.common.serverbound.ServerboundCustomPayloadPacket; import org.geysermc.mcprotocollib.protocol.packet.common.serverbound.ServerboundCustomPayloadPacket;
import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.ClientboundLoginPacket; import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.ClientboundLoginPacket;
import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.ServerboundPlayerLoadedPacket;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.Arrays; import java.util.Arrays;
@ -128,5 +129,9 @@ public class JavaLoginTranslator extends PacketTranslator<ClientboundLoginPacket
} }
ChunkUtils.loadDimension(session); ChunkUtils.loadDimension(session);
if (!needsSpawnPacket) {
session.sendDownstreamGamePacket(ServerboundPlayerLoadedPacket.INSTANCE);
}
} }
} }

View file

@ -28,6 +28,7 @@ package org.geysermc.geyser.translator.protocol.java;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import it.unimi.dsi.fastutil.Pair; import it.unimi.dsi.fastutil.Pair;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.IntComparators;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import net.kyori.adventure.key.Key; import net.kyori.adventure.key.Key;
import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.Nullable;
@ -75,12 +76,14 @@ import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.Clientbound
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
import java.util.stream.Collectors;
@Translator(packet = ClientboundRecipeBookAddPacket.class) @Translator(packet = ClientboundRecipeBookAddPacket.class)
public class JavaRecipeBookAddTranslator extends PacketTranslator<ClientboundRecipeBookAddPacket> { public class JavaRecipeBookAddTranslator extends PacketTranslator<ClientboundRecipeBookAddPacket> {
@ -386,10 +389,64 @@ public class JavaRecipeBookAddTranslator extends PacketTranslator<ClientboundRec
return Pair.of(Lists.cartesianProduct(inputs), output); return Pair.of(Lists.cartesianProduct(inputs), output);
} }
} }
// TODO:
return Pair.of( int totalSimpleRecipes = inputs.stream().mapToInt(List::size).max().orElse(1);
Collections.singletonList(inputs.stream().map(descriptors -> descriptors.get(0)).toList()),
output // Sort inputs to create "uniform" simple recipes, if possible
); inputs = inputs.stream()
.map(descriptors -> descriptors.stream()
.sorted(ItemDescriptorWithCountComparator.INSTANCE)
.collect(Collectors.toList()))
.collect(Collectors.toList());
List<List<ItemDescriptorWithCount>> finalRecipes = new ArrayList<>(totalSimpleRecipes);
for (int i = 0; i < totalSimpleRecipes; i++) {
int current = i;
finalRecipes.add(inputs.stream().map(descriptors -> {
if (descriptors.size() > current) {
return descriptors.get(current);
}
return descriptors.get(0);
}).toList());
}
return Pair.of(finalRecipes, output);
}
static class ItemDescriptorWithCountComparator implements Comparator<ItemDescriptorWithCount> {
static ItemDescriptorWithCountComparator INSTANCE = new ItemDescriptorWithCountComparator();
@Override
public int compare(ItemDescriptorWithCount o1, ItemDescriptorWithCount o2) {
String tag1 = null, tag2 = null;
// Collect item tags first
if (o1.getDescriptor() instanceof ItemTagDescriptor itemTagDescriptor) {
tag1 = itemTagDescriptor.getItemTag();
}
if (o2.getDescriptor() instanceof ItemTagDescriptor itemTagDescriptor) {
tag2 = itemTagDescriptor.getItemTag();
}
if (tag1 != null || tag2 != null) {
if (tag1 != null && tag2 != null) {
return tag1.compareTo(tag2); // Just sort based on their string id
}
if (tag1 != null) {
return -1;
}
return 1; // the second is an item tag; which should be r
}
if (o1.getDescriptor() instanceof DefaultDescriptor defaultDescriptor1 && o2.getDescriptor() instanceof DefaultDescriptor defaultDescriptor2) {
return IntComparators.NATURAL_COMPARATOR.compare(defaultDescriptor1.getItemId().getRuntimeId(), defaultDescriptor2.getItemId().getRuntimeId());
}
throw new IllegalStateException("Unable to compare unknown item descriptors: " + o1 + " and " + o2);
}
} }
} }

View file

@ -38,6 +38,7 @@ import org.geysermc.geyser.util.DimensionUtils;
import org.geysermc.geyser.util.EntityUtils; import org.geysermc.geyser.util.EntityUtils;
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.PlayerSpawnInfo; import org.geysermc.mcprotocollib.protocol.data.game.entity.player.PlayerSpawnInfo;
import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.ClientboundRespawnPacket; import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.ClientboundRespawnPacket;
import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.ServerboundPlayerLoadedPacket;
@Translator(packet = ClientboundRespawnPacket.class) @Translator(packet = ClientboundRespawnPacket.class)
public class JavaRespawnTranslator extends PacketTranslator<ClientboundRespawnPacket> { public class JavaRespawnTranslator extends PacketTranslator<ClientboundRespawnPacket> {
@ -93,5 +94,7 @@ public class JavaRespawnTranslator extends PacketTranslator<ClientboundRespawnPa
ChunkUtils.loadDimension(session); ChunkUtils.loadDimension(session);
} }
session.sendDownstreamGamePacket(ServerboundPlayerLoadedPacket.INSTANCE);
} }
} }

View file

@ -40,7 +40,7 @@ import java.util.Set;
@Translator(packet = ClientboundSelectKnownPacks.class) @Translator(packet = ClientboundSelectKnownPacks.class)
public class JavaSelectKnownPacksTranslator extends PacketTranslator<ClientboundSelectKnownPacks> { public class JavaSelectKnownPacksTranslator extends PacketTranslator<ClientboundSelectKnownPacks> {
// todo: dump from client? // todo: dump from client?
private static final Set<String> KNOWN_PACK_IDS = Set.of("core", "winter_drop", "trade_rebalance", "redstone_experiments", "minecart_improvements"); private static final Set<String> KNOWN_PACK_IDS = Set.of("core", "trade_rebalance", "redstone_experiments", "minecart_improvements");
@Override @Override
public void translate(GeyserSession session, ClientboundSelectKnownPacks packet) { public void translate(GeyserSession session, ClientboundSelectKnownPacks packet) {

View file

@ -37,12 +37,14 @@ import org.cloudburstmc.protocol.bedrock.packet.LevelSoundEvent2Packet;
import org.cloudburstmc.protocol.bedrock.packet.PlaySoundPacket; import org.cloudburstmc.protocol.bedrock.packet.PlaySoundPacket;
import org.cloudburstmc.protocol.bedrock.packet.SetEntityDataPacket; import org.cloudburstmc.protocol.bedrock.packet.SetEntityDataPacket;
import org.cloudburstmc.protocol.bedrock.packet.SetEntityMotionPacket; import org.cloudburstmc.protocol.bedrock.packet.SetEntityMotionPacket;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.entity.EntityDefinitions; import org.geysermc.geyser.entity.EntityDefinitions;
import org.geysermc.geyser.entity.type.Entity; import org.geysermc.geyser.entity.type.Entity;
import org.geysermc.geyser.entity.type.EvokerFangsEntity; import org.geysermc.geyser.entity.type.EvokerFangsEntity;
import org.geysermc.geyser.entity.type.FishingHookEntity; import org.geysermc.geyser.entity.type.FishingHookEntity;
import org.geysermc.geyser.entity.type.LivingEntity; import org.geysermc.geyser.entity.type.LivingEntity;
import org.geysermc.geyser.entity.type.living.animal.ArmadilloEntity; import org.geysermc.geyser.entity.type.living.animal.ArmadilloEntity;
import org.geysermc.geyser.entity.type.living.monster.CreakingEntity;
import org.geysermc.geyser.entity.type.living.monster.WardenEntity; import org.geysermc.geyser.entity.type.living.monster.WardenEntity;
import org.geysermc.geyser.item.Items; import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
@ -288,6 +290,16 @@ public class JavaEntityEventTranslator extends PacketTranslator<ClientboundEntit
armadilloEntity.onPeeking(); armadilloEntity.onPeeking();
} }
break; break;
case SHAKE:
if (entity instanceof CreakingEntity creakingEntity) {
creakingEntity.createParticleBeam();
}
break;
case SQUID_RESET_ROTATION:
// unused, but spams a bit
break;
default:
GeyserImpl.getInstance().getLogger().debug("unhandled entity event: " + packet);
} }
if (entityEventPacket.getType() != null) { if (entityEventPacket.getType() != null) {

View file

@ -25,13 +25,12 @@
package org.geysermc.geyser.translator.protocol.java.entity; package org.geysermc.geyser.translator.protocol.java.entity;
import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.entity.ClientboundMoveVehiclePacket;
import org.cloudburstmc.math.vector.Vector3f;
import org.geysermc.geyser.entity.type.Entity; import org.geysermc.geyser.entity.type.Entity;
import org.geysermc.geyser.entity.vehicle.ClientVehicle; import org.geysermc.geyser.entity.vehicle.ClientVehicle;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.PacketTranslator;
import org.geysermc.geyser.translator.protocol.Translator; import org.geysermc.geyser.translator.protocol.Translator;
import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.entity.ClientboundMoveVehiclePacket;
@Translator(packet = ClientboundMoveVehiclePacket.class) @Translator(packet = ClientboundMoveVehiclePacket.class)
public class JavaMoveVehicleTranslator extends PacketTranslator<ClientboundMoveVehiclePacket> { public class JavaMoveVehicleTranslator extends PacketTranslator<ClientboundMoveVehiclePacket> {
@ -42,9 +41,9 @@ public class JavaMoveVehicleTranslator extends PacketTranslator<ClientboundMoveV
if (entity == null) return; if (entity == null) return;
if (entity instanceof ClientVehicle clientVehicle) { if (entity instanceof ClientVehicle clientVehicle) {
clientVehicle.getVehicleComponent().moveAbsolute(packet.getX(), packet.getY(), packet.getZ()); clientVehicle.getVehicleComponent().moveAbsolute(packet.getPosition());
} }
entity.moveAbsolute(Vector3f.from(packet.getX(), packet.getY(), packet.getZ()), packet.getYaw(), packet.getPitch(), false, true); entity.moveAbsolute(packet.getPosition().toFloat(), packet.getYRot(), packet.getXRot(), false, true);
} }
} }

View file

@ -28,6 +28,7 @@ package org.geysermc.geyser.translator.protocol.java.entity;
import org.geysermc.geyser.entity.type.Entity; import org.geysermc.geyser.entity.type.Entity;
import org.geysermc.geyser.entity.type.LivingEntity; import org.geysermc.geyser.entity.type.LivingEntity;
import org.geysermc.geyser.entity.type.player.PlayerEntity; import org.geysermc.geyser.entity.type.player.PlayerEntity;
import org.geysermc.geyser.inventory.GeyserItemStack;
import org.geysermc.geyser.item.Items; import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.skin.FakeHeadProvider; import org.geysermc.geyser.skin.FakeHeadProvider;
@ -35,6 +36,7 @@ import org.geysermc.geyser.translator.protocol.PacketTranslator;
import org.geysermc.geyser.translator.protocol.Translator; import org.geysermc.geyser.translator.protocol.Translator;
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.Equipment; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.Equipment;
import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack; import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType;
import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.entity.ClientboundSetEquipmentPacket; import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.entity.ClientboundSetEquipmentPacket;
@Translator(packet = ClientboundSetEquipmentPacket.class) @Translator(packet = ClientboundSetEquipmentPacket.class)
@ -64,7 +66,7 @@ public class JavaSetEquipmentTranslator extends PacketTranslator<ClientboundSetE
&& javaItem != null && javaItem != null
&& javaItem.getId() == Items.PLAYER_HEAD.javaId() && javaItem.getId() == Items.PLAYER_HEAD.javaId()
&& javaItem.getDataComponents() != null) { && javaItem.getDataComponents() != null) {
FakeHeadProvider.setHead(session, (PlayerEntity) livingEntity, javaItem.getDataComponents()); FakeHeadProvider.setHead(session, (PlayerEntity) livingEntity, GeyserItemStack.from(javaItem).getComponent(DataComponentType.PROFILE));
} else { } else {
FakeHeadProvider.restoreOriginalSkin(session, livingEntity); FakeHeadProvider.restoreOriginalSkin(session, livingEntity);
} }

View file

@ -70,7 +70,7 @@ public class JavaSetPassengersTranslator extends PacketTranslator<ClientboundSet
boolean rider = packet.getPassengerIds()[0] == passengerId; boolean rider = packet.getPassengerIds()[0] == passengerId;
EntityLinkData.Type type = rider ? EntityLinkData.Type.RIDER : EntityLinkData.Type.PASSENGER; EntityLinkData.Type type = rider ? EntityLinkData.Type.RIDER : EntityLinkData.Type.PASSENGER;
SetEntityLinkPacket linkPacket = new SetEntityLinkPacket(); SetEntityLinkPacket linkPacket = new SetEntityLinkPacket();
linkPacket.setEntityLink(new EntityLinkData(entity.getGeyserId(), passenger.getGeyserId(), type, false, false)); linkPacket.setEntityLink(new EntityLinkData(entity.getGeyserId(), passenger.getGeyserId(), type, false, false, 0f));
session.sendUpstreamPacket(linkPacket); session.sendUpstreamPacket(linkPacket);
newPassengers.add(passenger); newPassengers.add(passenger);
@ -88,7 +88,7 @@ public class JavaSetPassengersTranslator extends PacketTranslator<ClientboundSet
} }
if (!newPassengers.contains(passenger)) { if (!newPassengers.contains(passenger)) {
SetEntityLinkPacket linkPacket = new SetEntityLinkPacket(); SetEntityLinkPacket linkPacket = new SetEntityLinkPacket();
linkPacket.setEntityLink(new EntityLinkData(entity.getGeyserId(), passenger.getGeyserId(), EntityLinkData.Type.REMOVE, false, false)); linkPacket.setEntityLink(new EntityLinkData(entity.getGeyserId(), passenger.getGeyserId(), EntityLinkData.Type.REMOVE, false, false, 0f));
session.sendUpstreamPacket(linkPacket); session.sendUpstreamPacket(linkPacket);
passenger.setVehicle(null); passenger.setVehicle(null);

View file

@ -173,7 +173,7 @@ public class JavaMerchantOffersTranslator extends PacketTranslator<ClientboundMe
// Bedrock expects all price adjustments to be applied to the item's count // Bedrock expects all price adjustments to be applied to the item's count
int count = stack.getAmount() + ((int) Math.max(Math.floor(stack.getAmount() * demand * priceMultiplier), 0)) + specialPrice; int count = stack.getAmount() + ((int) Math.max(Math.floor(stack.getAmount() * demand * priceMultiplier), 0)) + specialPrice;
count = MathUtils.constrain(count, 1, Registries.JAVA_ITEMS.get().get(stack.getId()).maxStackSize()); count = MathUtils.constrain(count, 1, Registries.JAVA_ITEMS.get().get(stack.getId()).defaultMaxStackSize());
return getItemTag(session, stack, mapping, count); return getItemTag(session, stack, mapping, count);
} }

View file

@ -41,7 +41,12 @@ public class JavaBlockDestructionTranslator extends PacketTranslator<Clientbound
@Override @Override
public void translate(GeyserSession session, ClientboundBlockDestructionPacket packet) { public void translate(GeyserSession session, ClientboundBlockDestructionPacket packet) {
int state = session.getGeyser().getWorldManager().getBlockAt(session, packet.getPosition().getX(), packet.getPosition().getY(), packet.getPosition().getZ()); int state = session.getGeyser().getWorldManager().getBlockAt(session, packet.getPosition().getX(), packet.getPosition().getY(), packet.getPosition().getZ());
int breakTime = (int) (65535 / Math.ceil(BlockUtils.getBreakTime(session, BlockState.of(state).block(), ItemMapping.AIR, null, false) * 20)); int breakTime = 12; //(int) (65535 / Math.ceil(BlockUtils.getBreakTime(session, BlockState.of(state).block(), ItemMapping.AIR, null, false)));
// TODO we need to send a "total" time to Bedrock.
// Current plan:
// - start with block destroy time (if applicable)
// - track the time in ticks between stages
// - attempt to "extrapolate" to a value for Bedrock
LevelEventPacket levelEventPacket = new LevelEventPacket(); LevelEventPacket levelEventPacket = new LevelEventPacket();
levelEventPacket.setPosition(packet.getPosition().toFloat()); levelEventPacket.setPosition(packet.getPosition().toFloat());
levelEventPacket.setType(LevelEvent.BLOCK_START_BREAK); levelEventPacket.setType(LevelEvent.BLOCK_START_BREAK);

View file

@ -62,6 +62,11 @@ public class JavaBlockEventTranslator extends PacketTranslator<ClientboundBlockE
Vector3i position = packet.getPosition(); Vector3i position = packet.getPosition();
BlockValue value = packet.getValue(); BlockValue value = packet.getValue();
if (value == null) {
session.getGeyser().getLogger().debug("Unable to handle packet %s - null value! ".formatted(packet.toString()));
return;
}
BlockEventPacket blockEventPacket = new BlockEventPacket(); BlockEventPacket blockEventPacket = new BlockEventPacket();
blockEventPacket.setBlockPosition(position); blockEventPacket.setBlockPosition(position);

View file

@ -25,157 +25,112 @@
package org.geysermc.geyser.util; package org.geysermc.geyser.util;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.math.vector.Vector3i;
import org.geysermc.geyser.entity.attribute.GeyserAttributeType;
import org.geysermc.geyser.inventory.GeyserItemStack; import org.geysermc.geyser.inventory.GeyserItemStack;
import org.geysermc.geyser.inventory.PlayerInventory;
import org.geysermc.geyser.inventory.item.BedrockEnchantment;
import org.geysermc.geyser.level.block.Blocks;
import org.geysermc.geyser.level.block.type.Block; import org.geysermc.geyser.level.block.type.Block;
import org.geysermc.geyser.registry.BlockRegistries; import org.geysermc.geyser.registry.BlockRegistries;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.session.cache.tags.BlockTag; import org.geysermc.geyser.session.cache.EntityEffectCache;
import org.geysermc.geyser.translator.collision.BlockCollision; import org.geysermc.geyser.translator.collision.BlockCollision;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents; import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.ToolData;
public final class BlockUtils { public final class BlockUtils {
private static boolean correctTool(GeyserSession session, Block block, String itemToolType) { /**
return switch (itemToolType) { * Returns the total mining progress added by mining the block in a single tick
case "axe" -> session.getTagCache().is(BlockTag.MINEABLE_AXE, block); * @return the mining progress added by this tick.
case "hoe" -> session.getTagCache().is(BlockTag.MINEABLE_HOE, block); */
case "pickaxe" -> session.getTagCache().is(BlockTag.MINEABLE_PICKAXE, block); public static float getBlockMiningProgressPerTick(GeyserSession session, Block block, GeyserItemStack itemInHand) {
case "shears" -> session.getTagCache().is(BlockTag.LEAVES, block) || session.getTagCache().is(BlockTag.WOOL, block); float destroySpeed = block.destroyTime();
case "shovel" -> session.getTagCache().is(BlockTag.MINEABLE_SHOVEL, block); if (destroySpeed == -1) {
case "sword" -> block == Blocks.COBWEB; return 0;
default -> { }
session.getGeyser().getLogger().warning("Unknown tool type: " + itemToolType);
yield false; int speedMultiplier = hasCorrectTool(session, block, itemInHand) ? 30 : 100;
return getPlayerDestroySpeed(session, block, itemInHand) / destroySpeed / speedMultiplier;
}
private static boolean hasCorrectTool(GeyserSession session, Block block, GeyserItemStack stack) {
return !block.requiresCorrectToolForDrops() || isCorrectItemForDrops(session, block, stack);
}
private static boolean isCorrectItemForDrops(GeyserSession session, Block block, GeyserItemStack stack) {
ToolData tool = stack.getComponent(DataComponentType.TOOL);
if (tool == null) {
return false;
}
for (ToolData.Rule rule : tool.getRules()) {
if (rule.getCorrectForDrops() != null) {
if (session.getTagCache().isBlock(rule.getBlocks(), block)) {
return rule.getCorrectForDrops();
}
} }
};
}
private static double toolBreakTimeBonus(String toolType, String toolTier, boolean isShearsEffective) {
if (toolType.equals("shears")) return isShearsEffective ? 5.0 : 15.0;
if (toolType.isEmpty()) return 1.0;
return switch (toolTier) {
// https://minecraft.wiki/w/Breaking#Speed
case "wooden" -> 2.0;
case "stone" -> 4.0;
case "iron" -> 6.0;
case "diamond" -> 8.0;
case "netherite" -> 9.0;
case "golden" -> 12.0;
default -> 1.0;
};
}
private static boolean canToolTierBreakBlock(GeyserSession session, Block block, String toolTier) {
if (toolTier.equals("netherite") || toolTier.equals("diamond")) {
// As of 1.17, these tiers can mine everything that is mineable
return true;
} }
switch (toolTier) { return false;
// Use intentional fall-throughs to check each tier with this block }
default:
if (session.getTagCache().is(BlockTag.NEEDS_STONE_TOOL, block)) { private static float getItemDestroySpeed(GeyserSession session, Block block, GeyserItemStack stack) {
return false; ToolData tool = stack.getComponent(DataComponentType.TOOL);
} if (tool == null) {
case "stone": return 1f;
if (session.getTagCache().is(BlockTag.NEEDS_IRON_TOOL, block)) { }
return false;
} for (ToolData.Rule rule : tool.getRules()) {
case "iron": if (rule.getSpeed() != null) {
if (session.getTagCache().is(BlockTag.NEEDS_DIAMOND_TOOL, block)) { if (session.getTagCache().isBlock(rule.getBlocks(), block)) {
return false; return rule.getSpeed();
} }
}
} }
return true; return tool.getDefaultMiningSpeed();
} }
// https://minecraft.wiki/w/Breaking private static float getPlayerDestroySpeed(GeyserSession session, Block block, GeyserItemStack itemInHand) {
private static double calculateBreakTime(double blockHardness, String toolTier, boolean canHarvestWithHand, boolean correctTool, boolean canTierMineBlock, float destroySpeed = getItemDestroySpeed(session, block, itemInHand);
String toolType, boolean isShearsEffective, int toolEfficiencyLevel, int hasteLevel, int miningFatigueLevel, EntityEffectCache effectCache = session.getEffectCache();
boolean insideOfWaterWithoutAquaAffinity, boolean onGround) {
double baseTime = (((correctTool && canTierMineBlock) || canHarvestWithHand) ? 1.5 : 5.0) * blockHardness;
double speed = 1.0 / baseTime;
if (correctTool) { if (destroySpeed > 1.0F) {
speed *= toolBreakTimeBonus(toolType, toolTier, isShearsEffective); destroySpeed += session.getPlayerEntity().attributeOrDefault(GeyserAttributeType.MINING_EFFICIENCY);
speed += toolEfficiencyLevel == 0 ? 0 : toolEfficiencyLevel * toolEfficiencyLevel + 1;
}
speed *= 1.0 + (0.2 * hasteLevel);
switch (miningFatigueLevel) {
case 0:
break;
case 1:
speed -= (speed * 0.7);
break;
case 2:
speed -= (speed * 0.91);
break;
case 3:
speed -= (speed * 0.9973);
break;
default:
speed -= (speed * 0.99919);
break;
} }
if (insideOfWaterWithoutAquaAffinity) speed *= 0.2; int miningSpeedMultiplier = getMiningSpeedAmplification(effectCache);
if (!onGround) speed *= 0.2; if (miningSpeedMultiplier > 0) {
return 1.0 / speed; destroySpeed *= miningSpeedMultiplier * 0.2F;
}
if (effectCache.getMiningFatigue() != 0) {
float slowdown = switch (effectCache.getMiningFatigue()) {
case 1 -> 0.3F;
case 2 -> 0.09F;
case 3 -> 0.0027F;
default -> 8.1E-4F;
};
destroySpeed *= slowdown;
}
destroySpeed *= session.getPlayerEntity().attributeOrDefault(GeyserAttributeType.BLOCK_BREAK_SPEED);
if (session.getCollisionManager().isWaterInEyes()) {
destroySpeed *= session.getPlayerEntity().attributeOrDefault(GeyserAttributeType.SUBMERGED_MINING_SPEED);
}
if (!session.getPlayerEntity().isOnGround()) {
destroySpeed /= 5F;
}
return destroySpeed;
} }
public static double getBreakTime(GeyserSession session, Block block, ItemMapping item, @Nullable DataComponents components, boolean isSessionPlayer) { private static int getMiningSpeedAmplification(EntityEffectCache cache) {
boolean isShearsEffective = session.getTagCache().is(BlockTag.LEAVES, block) || session.getTagCache().is(BlockTag.WOOL, block); //TODO called twice return Math.max(cache.getHaste(), cache.getConduitPower());
boolean canHarvestWithHand = !block.requiresCorrectToolForDrops();
String toolType = "";
String toolTier = "";
boolean correctTool = false;
boolean toolCanBreak = false;
if (item.isTool()) {
toolType = item.getToolType();
toolTier = item.getToolTier();
correctTool = correctTool(session, block, toolType);
toolCanBreak = canToolTierBreakBlock(session, block, toolTier);
}
int toolEfficiencyLevel = ItemUtils.getEnchantmentLevel(session, components, BedrockEnchantment.EFFICIENCY);
int hasteLevel = 0;
int miningFatigueLevel = 0;
if (!isSessionPlayer) {
// Another entity is currently mining; we have all the information we know
return calculateBreakTime(block.destroyTime(), toolTier, canHarvestWithHand, correctTool, toolCanBreak, toolType, isShearsEffective,
toolEfficiencyLevel, hasteLevel, miningFatigueLevel, false, true);
}
hasteLevel = Math.max(session.getEffectCache().getHaste(), session.getEffectCache().getConduitPower());
miningFatigueLevel = session.getEffectCache().getMiningFatigue();
boolean waterInEyes = session.getCollisionManager().isWaterInEyes();
boolean insideOfWaterWithoutAquaAffinity = waterInEyes &&
ItemUtils.getEnchantmentLevel(session, session.getPlayerInventory().getItem(5).getComponents(), BedrockEnchantment.AQUA_AFFINITY) < 1;
return calculateBreakTime(block.destroyTime(), toolTier, canHarvestWithHand, correctTool, toolCanBreak, toolType, isShearsEffective,
toolEfficiencyLevel, hasteLevel, miningFatigueLevel, insideOfWaterWithoutAquaAffinity, session.getPlayerEntity().isOnGround());
} }
public static double getSessionBreakTime(GeyserSession session, Block block) { public static double getSessionBreakTimeTicks(GeyserSession session, Block block) {
PlayerInventory inventory = session.getPlayerInventory(); return Math.ceil(1 / getBlockMiningProgressPerTick(session, block, session.getPlayerInventory().getItemInHand()));
GeyserItemStack item = inventory.getItemInHand();
ItemMapping mapping = ItemMapping.AIR;
DataComponents components = null;
if (item != null) {
mapping = item.getMapping(session);
components = item.getComponents();
}
return getBreakTime(session, block, mapping, components, true);
} }
/** /**

View file

@ -34,19 +34,16 @@ import org.cloudburstmc.protocol.bedrock.data.definitions.ItemDefinition;
import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerId; import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerId;
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
import org.cloudburstmc.protocol.bedrock.packet.InventorySlotPacket; import org.cloudburstmc.protocol.bedrock.packet.InventorySlotPacket;
import org.cloudburstmc.protocol.bedrock.packet.PlayerHotbarPacket;
import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.inventory.Container; import org.geysermc.geyser.inventory.Container;
import org.geysermc.geyser.inventory.GeyserItemStack; import org.geysermc.geyser.inventory.GeyserItemStack;
import org.geysermc.geyser.inventory.Inventory; import org.geysermc.geyser.inventory.Inventory;
import org.geysermc.geyser.inventory.LecternContainer; import org.geysermc.geyser.inventory.LecternContainer;
import org.geysermc.geyser.inventory.PlayerInventory;
import org.geysermc.geyser.inventory.click.Click; import org.geysermc.geyser.inventory.click.Click;
import org.geysermc.geyser.inventory.recipe.GeyserRecipe; import org.geysermc.geyser.inventory.recipe.GeyserRecipe;
import org.geysermc.geyser.inventory.recipe.GeyserShapedRecipe; import org.geysermc.geyser.inventory.recipe.GeyserShapedRecipe;
import org.geysermc.geyser.inventory.recipe.GeyserShapelessRecipe; import org.geysermc.geyser.inventory.recipe.GeyserShapelessRecipe;
import org.geysermc.geyser.item.Items; import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.item.type.Item;
import org.geysermc.geyser.level.BedrockDimension; import org.geysermc.geyser.level.BedrockDimension;
import org.geysermc.geyser.registry.Registries; import org.geysermc.geyser.registry.Registries;
import org.geysermc.geyser.registry.type.ItemMappings; import org.geysermc.geyser.registry.type.ItemMappings;
@ -58,7 +55,6 @@ import org.geysermc.geyser.text.GeyserLocale;
import org.geysermc.geyser.translator.inventory.InventoryTranslator; import org.geysermc.geyser.translator.inventory.InventoryTranslator;
import org.geysermc.geyser.translator.inventory.LecternInventoryTranslator; import org.geysermc.geyser.translator.inventory.LecternInventoryTranslator;
import org.geysermc.geyser.translator.inventory.chest.DoubleChestInventoryTranslator; import org.geysermc.geyser.translator.inventory.chest.DoubleChestInventoryTranslator;
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.GameMode;
import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack; import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents; import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents;
import org.geysermc.mcprotocollib.protocol.data.game.recipe.display.slot.CompositeSlotDisplay; import org.geysermc.mcprotocollib.protocol.data.game.recipe.display.slot.CompositeSlotDisplay;
@ -69,8 +65,6 @@ import org.geysermc.mcprotocollib.protocol.data.game.recipe.display.slot.SlotDis
import org.geysermc.mcprotocollib.protocol.data.game.recipe.display.slot.TagSlotDisplay; import org.geysermc.mcprotocollib.protocol.data.game.recipe.display.slot.TagSlotDisplay;
import org.geysermc.mcprotocollib.protocol.data.game.recipe.display.slot.WithRemainderSlotDisplay; import org.geysermc.mcprotocollib.protocol.data.game.recipe.display.slot.WithRemainderSlotDisplay;
import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory.ServerboundContainerClosePacket; import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory.ServerboundContainerClosePacket;
import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory.ServerboundPickItemPacket;
import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory.ServerboundSetCreativeModeSlotPacket;
import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.Contract;
import java.util.ArrayList; import java.util.ArrayList;
@ -271,169 +265,6 @@ public class InventoryUtils {
.count(1).build(); .count(1).build();
} }
/**
* See {@link #findOrCreateItem(GeyserSession, String)}. This is for finding a specified {@link ItemStack}.
*
* @param session the Bedrock client's session
* @param itemStack the item to try to find a match for. NBT will also be accounted for.
*/
public static void findOrCreateItem(GeyserSession session, ItemStack itemStack) {
if (isEmpty(itemStack)) {
return;
}
PlayerInventory inventory = session.getPlayerInventory();
// Check hotbar for item
for (int i = 36; i < 45; i++) {
GeyserItemStack geyserItem = inventory.getItem(i);
if (geyserItem.isEmpty()) {
continue;
}
// If this is the item we're looking for
if (geyserItem.getJavaId() == itemStack.getId() && Objects.equals(geyserItem.getComponents(), itemStack.getDataComponents())) { //TODO verify
setHotbarItem(session, i);
// Don't check inventory if item was in hotbar
return;
}
}
// Check inventory for item
for (int i = 9; i < 36; i++) {
GeyserItemStack geyserItem = inventory.getItem(i);
if (geyserItem.isEmpty()) {
continue;
}
// If this is the item we're looking for
if (geyserItem.getJavaId() == itemStack.getId() && Objects.equals(geyserItem.getComponents(), itemStack.getDataComponents())) { //TODO verify
ServerboundPickItemPacket packetToSend = new ServerboundPickItemPacket(i); // https://wiki.vg/Protocol#Pick_Item
session.sendDownstreamGamePacket(packetToSend);
return;
}
}
// If we still have not found the item, and we're in creative, ask for the item from the server.
if (session.getGameMode() == GameMode.CREATIVE) {
setPickedItem(session, inventory, GeyserItemStack.from(itemStack));
}
}
// Please remove!!!
public static void findOrCreateItem(GeyserSession session, String itemName) {
findOrCreateItem(session, Registries.JAVA_ITEM_IDENTIFIERS.getOrDefault(itemName, Items.AIR));
}
/**
* Attempt to find the specified item name in the session's inventory.
* If it is found and in the hotbar, set the user's held item to that slot.
* If it is found in another part of the inventory, move it.
* If it is not found and the user is in creative mode, create the item,
* overriding the current item slot if no other hotbar slots are empty, or otherwise selecting the empty slot.
* <p>
* This attempts to mimic Java Edition behavior as best as it can.
* @param session the Bedrock client's session
* @param item the Java item to search/select for
*/
public static void findOrCreateItem(GeyserSession session, Item item) {
// Get the inventory to choose a slot to pick
PlayerInventory inventory = session.getPlayerInventory();
if (item == Items.AIR) {
return;
}
// Check hotbar for item
for (int i = 36; i < 45; i++) {
GeyserItemStack geyserItem = inventory.getItem(i);
if (geyserItem.isEmpty()) {
continue;
}
// If this isn't the item we're looking for
if (!geyserItem.asItem().equals(item)) {
continue;
}
setHotbarItem(session, i);
// Don't check inventory if item was in hotbar
return;
}
// Check inventory for item
for (int i = 9; i < 36; i++) {
GeyserItemStack geyserItem = inventory.getItem(i);
if (geyserItem.isEmpty()) {
continue;
}
// If this isn't the item we're looking for
if (!geyserItem.asItem().equals(item)) {
continue;
}
ServerboundPickItemPacket packetToSend = new ServerboundPickItemPacket(i); // https://wiki.vg/Protocol#Pick_Item
session.sendDownstreamGamePacket(packetToSend);
return;
}
// If we still have not found the item, and we're in creative, set the item ourselves.
if (session.getGameMode() == GameMode.CREATIVE) {
GeyserItemStack itemStack = item.newItemStack(1, null);
setPickedItem(session, inventory, itemStack);
}
}
private static void setPickedItem(GeyserSession session, PlayerInventory inventory, GeyserItemStack itemStack) {
// Try to find an empty hotbar slot.
int slot = inventory.getHeldItemSlot() + 36;
if (!inventory.getItemInHand().isEmpty()) { // Otherwise we should just use the current slot
for (int i = 36; i < 45; i++) {
if (inventory.getItem(i).isEmpty()) {
slot = i;
break;
}
}
}
GeyserItemStack existingItem = inventory.getItem(slot);
if (!existingItem.isEmpty()) {
// Try to move the item to another slot.
for (int i = 9; i < 36; i++) {
if (inventory.getItem(i).isEmpty()) {
inventory.setItem(i, existingItem, session);
InventoryTranslator.PLAYER_INVENTORY_TRANSLATOR.updateSlot(session, inventory, i);
ServerboundSetCreativeModeSlotPacket actionPacket = new ServerboundSetCreativeModeSlotPacket((short) i,
existingItem.getItemStack());
session.sendDownstreamGamePacket(actionPacket);
break;
}
}
}
// As of 1.21.3 - the client does this on its own end and the server doesn't send a slot response back.
inventory.setItem(slot, itemStack, session);
InventoryTranslator.PLAYER_INVENTORY_TRANSLATOR.updateSlot(session, inventory, slot);
ServerboundSetCreativeModeSlotPacket actionPacket = new ServerboundSetCreativeModeSlotPacket((short) slot,
itemStack.getItemStack());
if ((slot - 36) != inventory.getHeldItemSlot()) {
setHotbarItem(session, slot);
}
session.sendDownstreamGamePacket(actionPacket);
}
/**
* Changes the held item slot to the specified slot
* @param session GeyserSession
* @param slot inventory slot to be selected
*/
private static void setHotbarItem(GeyserSession session, int slot) {
PlayerHotbarPacket hotbarPacket = new PlayerHotbarPacket();
hotbarPacket.setContainerId(0);
// Java inventory slot to hotbar slot ID
hotbarPacket.setSelectedHotbarSlot(slot - 36);
hotbarPacket.setSelectHotbarSlot(true);
session.sendUpstreamPacket(hotbarPacket);
// No need to send a Java packet as Bedrock sends a confirmation packet back that we translate
}
@Nullable @Nullable
public static Click getClickForHotbarSwap(int slot) { public static Click getClickForHotbarSwap(int slot) {
return switch (slot) { return switch (slot) {

View file

@ -25,7 +25,6 @@
package org.geysermc.geyser.util; package org.geysermc.geyser.util;
import net.kyori.adventure.text.Component;
import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.Nullable;
import org.geysermc.geyser.inventory.item.BedrockEnchantment; import org.geysermc.geyser.inventory.item.BedrockEnchantment;
import org.geysermc.geyser.item.Items; import org.geysermc.geyser.item.Items;
@ -102,17 +101,6 @@ public final class ItemUtils {
return original; return original;
} }
/**
* @param components the data components of the item
* @return the custom name of the item
*/
public static @Nullable Component getCustomName(DataComponents components) {
if (components == null) {
return null;
}
return components.get(DataComponentType.CUSTOM_NAME);
}
private ItemUtils() { private ItemUtils() {
} }
} }

View file

@ -6,6 +6,7 @@
"minecraft:banner" "minecraft:banner"
], ],
"minecraft:boat": [ "minecraft:boat": [
"minecraft:pale_oak_chest_boat",
"minecraft:cherry_chest_boat", "minecraft:cherry_chest_boat",
"minecraft:oak_chest_boat", "minecraft:oak_chest_boat",
"minecraft:mangrove_boat", "minecraft:mangrove_boat",
@ -23,9 +24,11 @@
"minecraft:mangrove_chest_boat", "minecraft:mangrove_chest_boat",
"minecraft:cherry_boat", "minecraft:cherry_boat",
"minecraft:bamboo_raft", "minecraft:bamboo_raft",
"minecraft:bamboo_chest_raft" "minecraft:bamboo_chest_raft",
"minecraft:pale_oak_boat"
], ],
"minecraft:boats": [ "minecraft:boats": [
"minecraft:pale_oak_chest_boat",
"minecraft:cherry_chest_boat", "minecraft:cherry_chest_boat",
"minecraft:oak_chest_boat", "minecraft:oak_chest_boat",
"minecraft:mangrove_boat", "minecraft:mangrove_boat",
@ -43,7 +46,8 @@
"minecraft:mangrove_chest_boat", "minecraft:mangrove_chest_boat",
"minecraft:cherry_boat", "minecraft:cherry_boat",
"minecraft:bamboo_raft", "minecraft:bamboo_raft",
"minecraft:bamboo_chest_raft" "minecraft:bamboo_chest_raft",
"minecraft:pale_oak_boat"
], ],
"minecraft:bookshelf_books": [ "minecraft:bookshelf_books": [
"minecraft:written_book", "minecraft:written_book",
@ -151,7 +155,8 @@
"minecraft:oxidized_copper_door", "minecraft:oxidized_copper_door",
"minecraft:waxed_copper_door", "minecraft:waxed_copper_door",
"minecraft:waxed_exposed_copper_door", "minecraft:waxed_exposed_copper_door",
"minecraft:waxed_oxidized_copper_door" "minecraft:waxed_oxidized_copper_door",
"minecraft:pale_oak_door"
], ],
"minecraft:golden_tier": [ "minecraft:golden_tier": [
"minecraft:golden_sword", "minecraft:golden_sword",
@ -170,6 +175,7 @@
"minecraft:hanging_sign": [ "minecraft:hanging_sign": [
"minecraft:mangrove_hanging_sign", "minecraft:mangrove_hanging_sign",
"minecraft:bamboo_hanging_sign", "minecraft:bamboo_hanging_sign",
"minecraft:pale_oak_hanging_sign",
"minecraft:spruce_hanging_sign", "minecraft:spruce_hanging_sign",
"minecraft:birch_hanging_sign", "minecraft:birch_hanging_sign",
"minecraft:cherry_hanging_sign", "minecraft:cherry_hanging_sign",
@ -318,6 +324,9 @@
"minecraft:golden_pickaxe", "minecraft:golden_pickaxe",
"minecraft:netherite_pickaxe" "minecraft:netherite_pickaxe"
], ],
"minecraft:is_shears": [
"minecraft:shears"
],
"minecraft:is_shovel": [ "minecraft:is_shovel": [
"minecraft:iron_shovel", "minecraft:iron_shovel",
"minecraft:wooden_shovel", "minecraft:wooden_shovel",
@ -382,6 +391,7 @@
"minecraft:writable_book" "minecraft:writable_book"
], ],
"minecraft:logs": [ "minecraft:logs": [
"minecraft:stripped_oak_log",
"minecraft:mangrove_wood", "minecraft:mangrove_wood",
"minecraft:spruce_wood", "minecraft:spruce_wood",
"minecraft:stripped_cherry_wood", "minecraft:stripped_cherry_wood",
@ -390,12 +400,14 @@
"minecraft:spruce_log", "minecraft:spruce_log",
"minecraft:acacia_wood", "minecraft:acacia_wood",
"minecraft:stripped_acacia_wood", "minecraft:stripped_acacia_wood",
"minecraft:pale_oak_wood",
"minecraft:stripped_warped_hyphae", "minecraft:stripped_warped_hyphae",
"minecraft:acacia_log", "minecraft:acacia_log",
"minecraft:stripped_warped_stem", "minecraft:stripped_warped_stem",
"minecraft:oak_log", "minecraft:oak_log",
"minecraft:birch_log", "minecraft:birch_log",
"minecraft:jungle_log", "minecraft:jungle_log",
"minecraft:stripped_pale_oak_wood",
"minecraft:dark_oak_log", "minecraft:dark_oak_log",
"minecraft:jungle_wood", "minecraft:jungle_wood",
"minecraft:stripped_jungle_wood", "minecraft:stripped_jungle_wood",
@ -405,10 +417,10 @@
"minecraft:stripped_oak_wood", "minecraft:stripped_oak_wood",
"minecraft:stripped_birch_wood", "minecraft:stripped_birch_wood",
"minecraft:stripped_dark_oak_wood", "minecraft:stripped_dark_oak_wood",
"minecraft:stripped_oak_log",
"minecraft:stripped_dark_oak_log", "minecraft:stripped_dark_oak_log",
"minecraft:mangrove_log", "minecraft:mangrove_log",
"minecraft:stripped_jungle_log", "minecraft:stripped_jungle_log",
"minecraft:stripped_pale_oak_log",
"minecraft:stripped_mangrove_wood", "minecraft:stripped_mangrove_wood",
"minecraft:crimson_hyphae", "minecraft:crimson_hyphae",
"minecraft:stripped_cherry_log", "minecraft:stripped_cherry_log",
@ -416,6 +428,7 @@
"minecraft:stripped_acacia_log", "minecraft:stripped_acacia_log",
"minecraft:crimson_stem", "minecraft:crimson_stem",
"minecraft:warped_hyphae", "minecraft:warped_hyphae",
"minecraft:pale_oak_log",
"minecraft:stripped_spruce_log", "minecraft:stripped_spruce_log",
"minecraft:warped_stem", "minecraft:warped_stem",
"minecraft:stripped_crimson_hyphae", "minecraft:stripped_crimson_hyphae",
@ -424,6 +437,7 @@
"minecraft:stripped_mangrove_log" "minecraft:stripped_mangrove_log"
], ],
"minecraft:logs_that_burn": [ "minecraft:logs_that_burn": [
"minecraft:stripped_oak_log",
"minecraft:mangrove_wood", "minecraft:mangrove_wood",
"minecraft:spruce_wood", "minecraft:spruce_wood",
"minecraft:stripped_cherry_wood", "minecraft:stripped_cherry_wood",
@ -431,10 +445,12 @@
"minecraft:spruce_log", "minecraft:spruce_log",
"minecraft:acacia_wood", "minecraft:acacia_wood",
"minecraft:stripped_acacia_wood", "minecraft:stripped_acacia_wood",
"minecraft:pale_oak_wood",
"minecraft:acacia_log", "minecraft:acacia_log",
"minecraft:oak_log", "minecraft:oak_log",
"minecraft:birch_log", "minecraft:birch_log",
"minecraft:jungle_log", "minecraft:jungle_log",
"minecraft:stripped_pale_oak_wood",
"minecraft:dark_oak_log", "minecraft:dark_oak_log",
"minecraft:jungle_wood", "minecraft:jungle_wood",
"minecraft:stripped_jungle_wood", "minecraft:stripped_jungle_wood",
@ -444,14 +460,15 @@
"minecraft:stripped_oak_wood", "minecraft:stripped_oak_wood",
"minecraft:stripped_birch_wood", "minecraft:stripped_birch_wood",
"minecraft:stripped_dark_oak_wood", "minecraft:stripped_dark_oak_wood",
"minecraft:stripped_oak_log",
"minecraft:stripped_dark_oak_log", "minecraft:stripped_dark_oak_log",
"minecraft:mangrove_log", "minecraft:mangrove_log",
"minecraft:stripped_jungle_log", "minecraft:stripped_jungle_log",
"minecraft:stripped_pale_oak_log",
"minecraft:stripped_mangrove_wood", "minecraft:stripped_mangrove_wood",
"minecraft:stripped_cherry_log", "minecraft:stripped_cherry_log",
"minecraft:stripped_birch_log", "minecraft:stripped_birch_log",
"minecraft:stripped_acacia_log", "minecraft:stripped_acacia_log",
"minecraft:pale_oak_log",
"minecraft:stripped_spruce_log", "minecraft:stripped_spruce_log",
"minecraft:cherry_wood", "minecraft:cherry_wood",
"minecraft:cherry_log", "minecraft:cherry_log",
@ -505,6 +522,7 @@
"minecraft:acacia_planks", "minecraft:acacia_planks",
"minecraft:bamboo_planks", "minecraft:bamboo_planks",
"minecraft:warped_planks", "minecraft:warped_planks",
"minecraft:pale_oak_planks",
"minecraft:crimson_planks", "minecraft:crimson_planks",
"minecraft:cherry_planks" "minecraft:cherry_planks"
], ],
@ -521,6 +539,7 @@
"minecraft:bamboo_hanging_sign", "minecraft:bamboo_hanging_sign",
"minecraft:warped_sign", "minecraft:warped_sign",
"minecraft:spruce_sign", "minecraft:spruce_sign",
"minecraft:pale_oak_hanging_sign",
"minecraft:spruce_hanging_sign", "minecraft:spruce_hanging_sign",
"minecraft:acacia_sign", "minecraft:acacia_sign",
"minecraft:birch_hanging_sign", "minecraft:birch_hanging_sign",
@ -534,7 +553,8 @@
"minecraft:acacia_hanging_sign", "minecraft:acacia_hanging_sign",
"minecraft:dark_oak_hanging_sign", "minecraft:dark_oak_hanging_sign",
"minecraft:crimson_hanging_sign", "minecraft:crimson_hanging_sign",
"minecraft:warped_hanging_sign" "minecraft:warped_hanging_sign",
"minecraft:pale_oak_sign"
], ],
"minecraft:soul_fire_base_blocks": [ "minecraft:soul_fire_base_blocks": [
"minecraft:soul_soil", "minecraft:soul_soil",
@ -596,6 +616,7 @@
"minecraft:piglin_spawn_egg", "minecraft:piglin_spawn_egg",
"minecraft:wither_skeleton_spawn_egg", "minecraft:wither_skeleton_spawn_egg",
"minecraft:donkey_spawn_egg", "minecraft:donkey_spawn_egg",
"minecraft:creaking_spawn_egg",
"minecraft:mule_spawn_egg", "minecraft:mule_spawn_egg",
"minecraft:skeleton_horse_spawn_egg", "minecraft:skeleton_horse_spawn_egg",
"minecraft:zombie_horse_spawn_egg", "minecraft:zombie_horse_spawn_egg",
@ -667,6 +688,7 @@
"minecraft:golden_boots" "minecraft:golden_boots"
], ],
"minecraft:trim_materials": [ "minecraft:trim_materials": [
"minecraft:resin_brick",
"minecraft:diamond", "minecraft:diamond",
"minecraft:iron_ingot", "minecraft:iron_ingot",
"minecraft:gold_ingot", "minecraft:gold_ingot",
@ -743,6 +765,7 @@
"minecraft:red_carpet", "minecraft:red_carpet",
"minecraft:brown_carpet", "minecraft:brown_carpet",
"minecraft:light_blue_wool", "minecraft:light_blue_wool",
"minecraft:green_carpet",
"minecraft:white_wool", "minecraft:white_wool",
"minecraft:magenta_wool", "minecraft:magenta_wool",
"minecraft:yellow_wool", "minecraft:yellow_wool",
@ -756,8 +779,7 @@
"minecraft:orange_carpet", "minecraft:orange_carpet",
"minecraft:light_blue_carpet", "minecraft:light_blue_carpet",
"minecraft:gray_carpet", "minecraft:gray_carpet",
"minecraft:light_gray_carpet", "minecraft:light_gray_carpet"
"minecraft:green_carpet"
], ],
"minecraft:warped_stems": [ "minecraft:warped_stems": [
"minecraft:stripped_warped_hyphae", "minecraft:stripped_warped_hyphae",
@ -771,6 +793,7 @@
"minecraft:spruce_slab", "minecraft:spruce_slab",
"minecraft:bamboo_slab", "minecraft:bamboo_slab",
"minecraft:warped_slab", "minecraft:warped_slab",
"minecraft:pale_oak_slab",
"minecraft:mangrove_slab", "minecraft:mangrove_slab",
"minecraft:cherry_slab", "minecraft:cherry_slab",
"minecraft:jungle_slab", "minecraft:jungle_slab",

File diff suppressed because it is too large Load diff

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