From b6113dfd318e3ac9795d8e1361e7cc75d1b0afb9 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Thu, 6 Apr 2023 21:47:37 -0400 Subject: [PATCH] Optimizations and regression fix --- .../world/GeyserSpigotBlockPlaceListener.java | 2 +- .../manager/GeyserSpigotWorldManager.java | 4 +- .../java/org/geysermc/geyser/GeyserImpl.java | 32 +-- .../geyser/entity/type/LivingEntity.java | 10 - .../type/living/merchant/VillagerEntity.java | 5 +- .../entity/type/player/PlayerEntity.java | 34 +-- .../holder/BlockInventoryHolder.java | 5 +- .../geyser/level/block/BlockStateValues.java | 2 +- .../geyser/network/netty/GeyserServer.java | 22 +- .../geyser/registry/BlockRegistries.java | 21 +- .../registry/loader/RegistryLoaders.java | 17 +- .../populator/BlockRegistryPopulator.java | 17 +- .../chest/DoubleChestInventoryTranslator.java | 5 +- ...BedrockInventoryTransactionTranslator.java | 15 +- .../player/BedrockActionTranslator.java | 3 +- .../java/level/JavaBlockUpdateTranslator.java | 3 +- .../JavaLevelChunkWithLightTranslator.java | 6 +- .../block/GrassPathInteractionTranslator.java | 2 +- .../sound/block/HoeInteractionTranslator.java | 2 +- .../org/geysermc/geyser/util/ChunkUtils.java | 2 +- .../org/geysermc/geyser/util/SoundUtils.java | 2 +- .../util/collection/Object2IntBiMap.java | 200 ------------------ 22 files changed, 114 insertions(+), 297 deletions(-) delete mode 100644 core/src/main/java/org/geysermc/geyser/util/collection/Object2IntBiMap.java diff --git a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/GeyserSpigotBlockPlaceListener.java b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/GeyserSpigotBlockPlaceListener.java index 0ad269b6d..71aba11f9 100644 --- a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/GeyserSpigotBlockPlaceListener.java +++ b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/GeyserSpigotBlockPlaceListener.java @@ -59,7 +59,7 @@ public class GeyserSpigotBlockPlaceListener implements Listener { event.getBlockPlaced().getX(), event.getBlockPlaced().getY(), event.getBlockPlaced().getZ()))); } else { String javaBlockId = event.getBlockPlaced().getBlockData().getAsString(); - placeBlockSoundPacket.setExtraData(session.getBlockMappings().getBedrockBlockId(BlockRegistries.JAVA_IDENTIFIERS.get().getOrDefault(javaBlockId, BlockStateValues.JAVA_AIR_ID))); + placeBlockSoundPacket.setExtraData(session.getBlockMappings().getBedrockBlockId(BlockRegistries.JAVA_IDENTIFIER_TO_ID.get().getOrDefault(javaBlockId, BlockStateValues.JAVA_AIR_ID))); } placeBlockSoundPacket.setIdentifier(":"); session.sendUpstreamPacket(placeBlockSoundPacket); diff --git a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/manager/GeyserSpigotWorldManager.java b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/manager/GeyserSpigotWorldManager.java index d54926a5b..056747d6a 100644 --- a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/manager/GeyserSpigotWorldManager.java +++ b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/world/manager/GeyserSpigotWorldManager.java @@ -82,9 +82,9 @@ public class GeyserSpigotWorldManager extends WorldManager { // Terrible behavior, but this is basically what's always been happening behind the scenes anyway. CompletableFuture blockData = new CompletableFuture<>(); Bukkit.getRegionScheduler().execute(this.plugin, block.getLocation(), () -> blockData.complete(block.getBlockData().getAsString())); - return BlockRegistries.JAVA_IDENTIFIERS.getOrDefault(blockData.join(), BlockStateValues.JAVA_AIR_ID); + return BlockRegistries.JAVA_IDENTIFIER_TO_ID.getOrDefault(blockData.join(), BlockStateValues.JAVA_AIR_ID); } - return BlockRegistries.JAVA_IDENTIFIERS.getOrDefault(block.getBlockData().getAsString(), BlockStateValues.JAVA_AIR_ID); + return BlockRegistries.JAVA_IDENTIFIER_TO_ID.getOrDefault(block.getBlockData().getAsString(), BlockStateValues.JAVA_AIR_ID); } @Override diff --git a/core/src/main/java/org/geysermc/geyser/GeyserImpl.java b/core/src/main/java/org/geysermc/geyser/GeyserImpl.java index e9c567473..d6988b052 100644 --- a/core/src/main/java/org/geysermc/geyser/GeyserImpl.java +++ b/core/src/main/java/org/geysermc/geyser/GeyserImpl.java @@ -31,7 +31,6 @@ import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.github.steveice10.packetlib.tcp.TcpSession; import io.netty.channel.epoll.Epoll; -import io.netty.channel.kqueue.KQueue; import io.netty.util.NettyRuntime; import io.netty.util.concurrent.DefaultThreadFactory; import io.netty.util.internal.SystemPropertyUtil; @@ -312,21 +311,22 @@ public class GeyserImpl implements GeyserApi { } if (shouldStartListener) { - try { - this.geyserServer = new GeyserServer(this, bedrockThreadCount); - this.geyserServer.bind(new InetSocketAddress(config.getBedrock().address(), config.getBedrock().port())); - - logger.info(GeyserLocale.getLocaleStringLog("geyser.core.start", config.getBedrock().address(), - String.valueOf(config.getBedrock().port()))); - } catch (Throwable t) { - String address = config.getBedrock().address(); - int port = config.getBedrock().port(); - logger.severe(GeyserLocale.getLocaleStringLog("geyser.core.fail", address, String.valueOf(port))); - if (!"0.0.0.0".equals(address)) { - logger.info(Component.text("Suggestion: try setting `address` under `bedrock` in the Geyser config back to 0.0.0.0", NamedTextColor.GREEN)); - logger.info(Component.text("Then, restart this server.", NamedTextColor.GREEN)); - } - } + this.geyserServer = new GeyserServer(this, bedrockThreadCount); + this.geyserServer.bind(new InetSocketAddress(config.getBedrock().address(), config.getBedrock().port())) + .whenComplete((avoid, throwable) -> { + if (throwable == null) { + logger.info(GeyserLocale.getLocaleStringLog("geyser.core.start", config.getBedrock().address(), + String.valueOf(config.getBedrock().port()))); + } else { + String address = config.getBedrock().address(); + int port = config.getBedrock().port(); + logger.severe(GeyserLocale.getLocaleStringLog("geyser.core.fail", address, String.valueOf(port))); + if (!"0.0.0.0".equals(address)) { + logger.info(Component.text("Suggestion: try setting `address` under `bedrock` in the Geyser config back to 0.0.0.0", NamedTextColor.GREEN)); + logger.info(Component.text("Then, restart this server.", NamedTextColor.GREEN)); + } + } + }).join(); } if (config.getRemote().authType() == AuthType.FLOODGATE) { diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/LivingEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/LivingEntity.java index b03e7126a..43fe555b0 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/LivingEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/LivingEntity.java @@ -56,7 +56,6 @@ import org.geysermc.geyser.item.Items; import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.util.AttributeUtils; -import org.geysermc.geyser.util.ChunkUtils; import org.geysermc.geyser.util.InteractionResult; import java.util.*; @@ -127,17 +126,8 @@ public class LivingEntity extends Entity { if (optionalPos.isPresent()) { Vector3i bedPosition = optionalPos.get(); dirtyMetadata.put(EntityDataTypes.BED_POSITION, bedPosition); - int bed = session.getGeyser().getWorldManager().getBlockAt(session, bedPosition); - // Bed has to be updated, or else player is floating in the air - ChunkUtils.updateBlock(session, bed, bedPosition); - // Indicate that the player should enter the sleep cycle - // Has to be a byte or it does not work - // (Bed position is what actually triggers sleep - "pose" is only optional) - dirtyMetadata.put(EntityDataTypes.PLAYER_FLAGS, (byte) 2); return bedPosition; } else { - // Player is no longer sleeping - dirtyMetadata.put(EntityDataTypes.PLAYER_FLAGS, (byte) 0); return null; } } diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/living/merchant/VillagerEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/living/merchant/VillagerEntity.java index c5d752677..84b8b5143 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/living/merchant/VillagerEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/living/merchant/VillagerEntity.java @@ -27,14 +27,15 @@ package org.geysermc.geyser.entity.type.living.merchant; import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata; import com.github.steveice10.mc.protocol.data.game.entity.metadata.VillagerData; +import lombok.Getter; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.cloudburstmc.protocol.bedrock.packet.MoveEntityAbsolutePacket; -import lombok.Getter; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.registry.BlockRegistries; +import org.geysermc.geyser.registry.type.BlockMapping; import org.geysermc.geyser.session.GeyserSession; import java.util.Optional; @@ -117,7 +118,7 @@ public class VillagerEntity extends AbstractMerchantEntity { // The bed block int blockId = session.getGeyser().getWorldManager().getBlockAt(session, bedPosition); - String fullIdentifier = BlockRegistries.JAVA_IDENTIFIERS.get().get(blockId); + String fullIdentifier = BlockRegistries.JAVA_BLOCKS.getOrDefault(blockId, BlockMapping.AIR).getJavaIdentifier(); // Set the correct position offset and rotation when sleeping int bedRotation = 0; diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/player/PlayerEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/player/PlayerEntity.java index b060758ae..81f556e2b 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/player/PlayerEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/player/PlayerEntity.java @@ -38,20 +38,12 @@ import lombok.Setter; import net.kyori.adventure.text.Component; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.math.vector.Vector3i; -import org.cloudburstmc.protocol.bedrock.data.Ability; -import org.cloudburstmc.protocol.bedrock.data.AbilityLayer; -import org.cloudburstmc.protocol.bedrock.data.AttributeData; -import org.cloudburstmc.protocol.bedrock.data.GameType; -import org.cloudburstmc.protocol.bedrock.data.PlayerPermission; +import org.cloudburstmc.protocol.bedrock.data.*; import org.cloudburstmc.protocol.bedrock.data.command.CommandPermission; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.cloudburstmc.protocol.bedrock.data.entity.EntityLinkData; -import org.cloudburstmc.protocol.bedrock.packet.AddPlayerPacket; -import org.cloudburstmc.protocol.bedrock.packet.MovePlayerPacket; -import org.cloudburstmc.protocol.bedrock.packet.SetEntityDataPacket; -import org.cloudburstmc.protocol.bedrock.packet.SetEntityLinkPacket; -import org.cloudburstmc.protocol.bedrock.packet.UpdateAttributesPacket; +import org.cloudburstmc.protocol.bedrock.packet.*; import org.geysermc.geyser.entity.EntityDefinitions; import org.geysermc.geyser.entity.type.Entity; import org.geysermc.geyser.entity.type.LivingEntity; @@ -62,6 +54,7 @@ import org.geysermc.geyser.scoreboard.Team; import org.geysermc.geyser.scoreboard.UpdateType; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.text.MessageTranslator; +import org.geysermc.geyser.util.ChunkUtils; import javax.annotation.Nullable; import java.util.Collections; @@ -248,8 +241,25 @@ public class PlayerEntity extends LivingEntity { @Override public Vector3i setBedPosition(EntityMetadata, ?> entityMetadata) { bedPosition = super.setBedPosition(entityMetadata); - // Fixes https://github.com/GeyserMC/Geyser/issues/3595 on vanilla 1.19.3 servers - did not happen on Paper - entityMetadata.getValue().ifPresent(pos -> this.setPosition(pos.toFloat())); + if (bedPosition != null) { + // Required to sync position of entity to bed + // Fixes https://github.com/GeyserMC/Geyser/issues/3595 on vanilla 1.19.3 servers - did not happen on Paper + this.setPosition(bedPosition.toFloat()); + + // TODO evaluate if needed + int bed = session.getGeyser().getWorldManager().getBlockAt(session, bedPosition); + // Bed has to be updated, or else player is floating in the air + ChunkUtils.updateBlock(session, bed, bedPosition); + + // Indicate that the player should enter the sleep cycle + // Has to be a byte or it does not work + // (Bed position is what actually triggers sleep - "pose" is only optional) + dirtyMetadata.put(EntityDataTypes.PLAYER_FLAGS, (byte) 2); + } else { + // Player is no longer sleeping + dirtyMetadata.put(EntityDataTypes.PLAYER_FLAGS, (byte) 0); + return null; + } return bedPosition; } diff --git a/core/src/main/java/org/geysermc/geyser/inventory/holder/BlockInventoryHolder.java b/core/src/main/java/org/geysermc/geyser/inventory/holder/BlockInventoryHolder.java index b1a3174fa..01365be34 100644 --- a/core/src/main/java/org/geysermc/geyser/inventory/holder/BlockInventoryHolder.java +++ b/core/src/main/java/org/geysermc/geyser/inventory/holder/BlockInventoryHolder.java @@ -35,6 +35,7 @@ import org.cloudburstmc.protocol.bedrock.packet.UpdateBlockPacket; import org.geysermc.geyser.inventory.Container; import org.geysermc.geyser.inventory.Inventory; import org.geysermc.geyser.registry.BlockRegistries; +import org.geysermc.geyser.registry.type.BlockMapping; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.inventory.InventoryTranslator; import org.geysermc.geyser.util.BlockUtils; @@ -57,7 +58,7 @@ public class BlockInventoryHolder extends InventoryHolder { private final Set validBlocks; public BlockInventoryHolder(String javaBlockIdentifier, ContainerType containerType, String... validBlocks) { - this.defaultJavaBlockState = BlockRegistries.JAVA_IDENTIFIERS.get(javaBlockIdentifier); + this.defaultJavaBlockState = BlockRegistries.JAVA_IDENTIFIER_TO_ID.get().getInt(javaBlockIdentifier); this.containerType = containerType; if (validBlocks != null) { Set validBlocksTemp = new HashSet<>(validBlocks.length + 1); @@ -77,7 +78,7 @@ public class BlockInventoryHolder extends InventoryHolder { if (checkInteractionPosition(session)) { // Then, check to see if the interacted block is valid for this inventory by ensuring the block state identifier is valid int javaBlockId = session.getGeyser().getWorldManager().getBlockAt(session, session.getLastInteractionBlockPosition()); - String[] javaBlockString = BlockRegistries.JAVA_IDENTIFIERS.get().getOrDefault(javaBlockId, "minecraft:air").split("\\["); + String[] javaBlockString = BlockRegistries.JAVA_BLOCKS.getOrDefault(javaBlockId, BlockMapping.AIR).getJavaIdentifier().split("\\["); if (isValidBlock(javaBlockString)) { // We can safely use this block inventory.setHolderPosition(session.getLastInteractionBlockPosition()); diff --git a/core/src/main/java/org/geysermc/geyser/level/block/BlockStateValues.java b/core/src/main/java/org/geysermc/geyser/level/block/BlockStateValues.java index c6fc60303..1d56946a8 100644 --- a/core/src/main/java/org/geysermc/geyser/level/block/BlockStateValues.java +++ b/core/src/main/java/org/geysermc/geyser/level/block/BlockStateValues.java @@ -468,7 +468,7 @@ public final class BlockStateValues { */ public static double getWaterHeight(int state) { int waterLevel = BlockStateValues.getWaterLevel(state); - if (BlockRegistries.WATERLOGGED.get().contains(state)) { + if (BlockRegistries.WATERLOGGED.get().get(state)) { waterLevel = 0; } if (waterLevel >= 0) { diff --git a/core/src/main/java/org/geysermc/geyser/network/netty/GeyserServer.java b/core/src/main/java/org/geysermc/geyser/network/netty/GeyserServer.java index 0c7ba6f2f..5e1c1331f 100644 --- a/core/src/main/java/org/geysermc/geyser/network/netty/GeyserServer.java +++ b/core/src/main/java/org/geysermc/geyser/network/netty/GeyserServer.java @@ -27,7 +27,6 @@ package org.geysermc.geyser.network.netty; import com.github.steveice10.packetlib.helper.TransportHelper; import io.netty.bootstrap.ServerBootstrap; -import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.EventLoopGroup; import io.netty.channel.epoll.Epoll; @@ -54,7 +53,8 @@ import org.geysermc.geyser.translator.text.MessageTranslator; import java.net.InetSocketAddress; import java.nio.charset.StandardCharsets; -import java.util.function.Function; +import java.util.concurrent.CompletableFuture; +import java.util.function.IntFunction; public final class GeyserServer { private static final boolean PRINT_DEBUG_PINGS = Boolean.parseBoolean(System.getProperty("Geyser.PrintPingsInDebugMode", "true")); @@ -76,7 +76,6 @@ public final class GeyserServer { private final ServerBootstrap bootstrap; private ChannelFuture future; - private Channel channel; public GeyserServer(GeyserImpl geyser, int threadCount) { this.geyser = geyser; @@ -85,12 +84,19 @@ public final class GeyserServer { this.bootstrap = this.createBootstrap(this.group); } - public void bind(InetSocketAddress address) { - this.future = this.bootstrap.bind(address).syncUninterruptibly(); - this.channel = this.future.channel(); + public CompletableFuture bind(InetSocketAddress address) { + CompletableFuture future = new CompletableFuture<>(); + this.future = this.bootstrap.bind(address).addListener(bindResult -> { + if (bindResult.cause() != null) { + future.completeExceptionally(bindResult.cause()); + return; + } + future.complete(null); + }); // Add our ping handler - this.channel.pipeline().addAfter(RakServerOfflineHandler.NAME, RakPingHandler.NAME, new RakPingHandler(this)); + this.future.channel().pipeline().addAfter(RakServerOfflineHandler.NAME, RakPingHandler.NAME, new RakPingHandler(this)); + return future; } public void shutdown() { @@ -219,6 +225,6 @@ public final class GeyserServer { return new Transport(NioDatagramChannel.class, NioEventLoopGroup::new); } - private record Transport(Class datagramChannel, Function eventLoopGroupFactory) { + private record Transport(Class datagramChannel, IntFunction eventLoopGroupFactory) { } } diff --git a/core/src/main/java/org/geysermc/geyser/registry/BlockRegistries.java b/core/src/main/java/org/geysermc/geyser/registry/BlockRegistries.java index 586e7d08b..8b576a673 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/BlockRegistries.java +++ b/core/src/main/java/org/geysermc/geyser/registry/BlockRegistries.java @@ -26,14 +26,15 @@ package org.geysermc.geyser.registry; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; -import it.unimi.dsi.fastutil.ints.IntOpenHashSet; -import it.unimi.dsi.fastutil.ints.IntSet; +import it.unimi.dsi.fastutil.objects.Object2IntMap; +import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import org.geysermc.geyser.registry.loader.RegistryLoaders; import org.geysermc.geyser.registry.populator.BlockRegistryPopulator; import org.geysermc.geyser.registry.type.BlockMapping; import org.geysermc.geyser.registry.type.BlockMappings; -import org.geysermc.geyser.util.collection.Object2IntBiMap; + +import java.util.BitSet; /** * Holds all the block registries in Geyser. @@ -54,33 +55,33 @@ public class BlockRegistries { * A registry which stores Java IDs to {@link BlockMapping}, containing miscellaneous information about * blocks and their behavior in many cases. */ - public static final ArrayRegistry JAVA_BLOCKS = ArrayRegistry.create(RegistryLoaders.empty(() -> new BlockMapping[] {})); + public static final ArrayRegistry JAVA_BLOCKS = ArrayRegistry.create(RegistryLoaders.uninitialized()); /** - * A (bi)mapped registry containing the Java IDs to identifiers. + * A mapped registry containing the Java identifiers to IDs. */ - public static final MappedRegistry> JAVA_IDENTIFIERS = MappedRegistry.create(RegistryLoaders.empty(Object2IntBiMap::new)); + public static final MappedRegistry> JAVA_IDENTIFIER_TO_ID = MappedRegistry.create(RegistryLoaders.empty(Object2IntOpenHashMap::new)); /** * A registry which stores unique Java IDs to its clean identifier * This is used in the statistics form. */ - public static final ArrayRegistry CLEAN_JAVA_IDENTIFIERS = ArrayRegistry.create(RegistryLoaders.empty(() -> new String[] {})); + public static final ArrayRegistry CLEAN_JAVA_IDENTIFIERS = ArrayRegistry.create(RegistryLoaders.uninitialized()); /** * A registry containing all the waterlogged blockstates. */ - public static final SimpleRegistry WATERLOGGED = SimpleRegistry.create(RegistryLoaders.empty(IntOpenHashSet::new)); + public static final SimpleRegistry WATERLOGGED = SimpleRegistry.create(RegistryLoaders.empty(BitSet::new)); /** * A registry containing all blockstates which are always interactive. */ - public static final SimpleRegistry INTERACTIVE = SimpleRegistry.create(RegistryLoaders.empty(IntOpenHashSet::new)); + public static final SimpleRegistry INTERACTIVE = SimpleRegistry.create(RegistryLoaders.uninitialized()); /** * A registry containing all blockstates which are interactive if the player has the may build permission. */ - public static final SimpleRegistry INTERACTIVE_MAY_BUILD = SimpleRegistry.create(RegistryLoaders.empty(IntOpenHashSet::new)); + public static final SimpleRegistry INTERACTIVE_MAY_BUILD = SimpleRegistry.create(RegistryLoaders.uninitialized()); static { BlockRegistryPopulator.populate(); diff --git a/core/src/main/java/org/geysermc/geyser/registry/loader/RegistryLoaders.java b/core/src/main/java/org/geysermc/geyser/registry/loader/RegistryLoaders.java index 132b7cff5..62b6e4737 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/loader/RegistryLoaders.java +++ b/core/src/main/java/org/geysermc/geyser/registry/loader/RegistryLoaders.java @@ -25,12 +25,14 @@ package org.geysermc.geyser.registry.loader; +import org.checkerframework.checker.nullness.qual.NonNull; + import java.util.function.Supplier; /** * Holds common {@link RegistryLoader}s or utility methods surrounding them. */ -public class RegistryLoaders { +public final class RegistryLoaders { /** * The {@link RegistryLoader} responsible for loading NBT. */ @@ -44,7 +46,18 @@ public class RegistryLoaders { * @param the value * @return a RegistryLoader wrapping the given Supplier */ - public static RegistryLoader empty(Supplier supplier) { + public static RegistryLoader empty(@NonNull Supplier supplier) { return input -> supplier.get(); } + + /** + * @param the value + * @return a RegistryLoader that is yet to contain a value. + */ + public static RegistryLoader uninitialized() { + return input -> null; + } + + private RegistryLoaders() { + } } \ No newline at end of file diff --git a/core/src/main/java/org/geysermc/geyser/registry/populator/BlockRegistryPopulator.java b/core/src/main/java/org/geysermc/geyser/registry/populator/BlockRegistryPopulator.java index b20192e9a..99815709a 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/populator/BlockRegistryPopulator.java +++ b/core/src/main/java/org/geysermc/geyser/registry/populator/BlockRegistryPopulator.java @@ -28,8 +28,6 @@ package org.geysermc.geyser.registry.populator; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ArrayNode; import com.google.common.collect.ImmutableMap; -import it.unimi.dsi.fastutil.ints.IntOpenHashSet; -import it.unimi.dsi.fastutil.ints.IntSet; import it.unimi.dsi.fastutil.objects.*; import org.cloudburstmc.nbt.*; import org.cloudburstmc.protocol.bedrock.codec.v544.Bedrock_v544; @@ -160,7 +158,7 @@ public final class BlockRegistryPopulator { if (waterlogged) { int finalJavaRuntimeId = javaRuntimeId; - BlockRegistries.WATERLOGGED.register(set -> set.add(finalJavaRuntimeId)); + BlockRegistries.WATERLOGGED.register(set -> set.set(finalJavaRuntimeId)); } String cleanJavaIdentifier = BlockUtils.getCleanIdentifier(entry.getKey()); @@ -296,7 +294,7 @@ public final class BlockRegistryPopulator { builder.javaIdentifier(javaId); builder.javaBlockId(uniqueJavaId); - BlockRegistries.JAVA_IDENTIFIERS.register(javaId, javaRuntimeId); + BlockRegistries.JAVA_IDENTIFIER_TO_ID.register(javaId, javaRuntimeId); BlockRegistries.JAVA_BLOCKS.register(javaRuntimeId, builder.build()); // Keeping this here since this is currently unchanged between versions @@ -375,10 +373,10 @@ public final class BlockRegistryPopulator { BlockRegistries.INTERACTIVE_MAY_BUILD.set(toBlockStateSet((ArrayNode) blockInteractionsJson.get("requires_may_build"))); } - private static IntSet toBlockStateSet(ArrayNode node) { - IntSet blockStateSet = new IntOpenHashSet(node.size()); + private static BitSet toBlockStateSet(ArrayNode node) { + BitSet blockStateSet = new BitSet(node.size()); for (JsonNode javaIdentifier : node) { - blockStateSet.add(BlockRegistries.JAVA_IDENTIFIERS.get().getInt(javaIdentifier.textValue())); + blockStateSet.set(BlockRegistries.JAVA_IDENTIFIER_TO_ID.get().getInt(javaIdentifier.textValue())); } return blockStateSet; } @@ -392,8 +390,9 @@ public final class BlockRegistryPopulator { NbtMapBuilder statesBuilder = NbtMap.builder(); // check for states - if (node.has("bedrock_states")) { - Iterator> statesIterator = node.get("bedrock_states").fields(); + JsonNode states = node.get("bedrock_states"); + if (states != null) { + Iterator> statesIterator = states.fields(); while (statesIterator.hasNext()) { Map.Entry stateEntry = statesIterator.next(); diff --git a/core/src/main/java/org/geysermc/geyser/translator/inventory/chest/DoubleChestInventoryTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/inventory/chest/DoubleChestInventoryTranslator.java index 5d0bd12ba..2f19f56f3 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/inventory/chest/DoubleChestInventoryTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/inventory/chest/DoubleChestInventoryTranslator.java @@ -39,6 +39,7 @@ import org.geysermc.geyser.inventory.Inventory; import org.geysermc.geyser.level.block.BlockStateValues; import org.geysermc.geyser.level.block.DoubleChestValue; import org.geysermc.geyser.registry.BlockRegistries; +import org.geysermc.geyser.registry.type.BlockMapping; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.level.block.entity.DoubleChestBlockEntityTranslator; import org.geysermc.geyser.util.InventoryUtils; @@ -48,7 +49,7 @@ public class DoubleChestInventoryTranslator extends ChestInventoryTranslator { public DoubleChestInventoryTranslator(int size) { super(size, 54); - this.defaultJavaBlockState = BlockRegistries.JAVA_IDENTIFIERS.get("minecraft:chest[facing=north,type=single,waterlogged=false]"); + this.defaultJavaBlockState = BlockRegistries.JAVA_IDENTIFIER_TO_ID.get().getInt("minecraft:chest[facing=north,type=single,waterlogged=false]"); } @Override @@ -56,7 +57,7 @@ public class DoubleChestInventoryTranslator extends ChestInventoryTranslator { // See BlockInventoryHolder - same concept there except we're also dealing with a specific block state if (session.getLastInteractionPlayerPosition().equals(session.getPlayerEntity().getPosition())) { int javaBlockId = session.getGeyser().getWorldManager().getBlockAt(session, session.getLastInteractionBlockPosition()); - String[] javaBlockString = BlockRegistries.JAVA_IDENTIFIERS.get().getOrDefault(javaBlockId, "minecraft:air").split("\\["); + String[] javaBlockString = BlockRegistries.JAVA_BLOCKS.getOrDefault(javaBlockId, BlockMapping.AIR).getJavaIdentifier().split("\\["); if (javaBlockString.length > 1 && (javaBlockString[0].equals("minecraft:chest") || javaBlockString[0].equals("minecraft:trapped_chest")) && !javaBlockString[1].contains("type=single")) { inventory.setHolderPosition(session.getLastInteractionBlockPosition()); diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockInventoryTransactionTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockInventoryTransactionTranslator.java index ba96e69c5..3977b6476 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockInventoryTransactionTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockInventoryTransactionTranslator.java @@ -32,15 +32,9 @@ import com.github.steveice10.mc.protocol.data.game.entity.player.Hand; import com.github.steveice10.mc.protocol.data.game.entity.player.InteractAction; import com.github.steveice10.mc.protocol.data.game.entity.player.PlayerAction; import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.ServerboundContainerClickPacket; -import com.github.steveice10.mc.protocol.packet.ingame.serverbound.player.ServerboundInteractPacket; -import com.github.steveice10.mc.protocol.packet.ingame.serverbound.player.ServerboundMovePlayerPosRotPacket; -import com.github.steveice10.mc.protocol.packet.ingame.serverbound.player.ServerboundPlayerActionPacket; -import com.github.steveice10.mc.protocol.packet.ingame.serverbound.player.ServerboundSwingPacket; -import com.github.steveice10.mc.protocol.packet.ingame.serverbound.player.ServerboundUseItemOnPacket; -import com.github.steveice10.mc.protocol.packet.ingame.serverbound.player.ServerboundUseItemPacket; +import com.github.steveice10.mc.protocol.packet.ingame.serverbound.player.*; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectMaps; -import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import org.cloudburstmc.math.vector.Vector3d; import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.math.vector.Vector3i; @@ -50,7 +44,6 @@ import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.cloudburstmc.protocol.bedrock.data.inventory.transaction.InventoryActionData; import org.cloudburstmc.protocol.bedrock.data.inventory.transaction.InventorySource; -import org.cloudburstmc.protocol.bedrock.data.inventory.transaction.LegacySetItemSlotData; import org.cloudburstmc.protocol.bedrock.packet.ContainerOpenPacket; import org.cloudburstmc.protocol.bedrock.packet.InventoryTransactionPacket; import org.cloudburstmc.protocol.bedrock.packet.LevelEventPacket; @@ -506,7 +499,7 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator the value - */ -public class Object2IntBiMap implements Object2IntMap { - private final Object2IntMap forwards; - private final Int2ObjectMap backwards; - - public Object2IntBiMap() { - this(16); - } - - public Object2IntBiMap(int expected) { - this(expected, 0.75F); - } - - public Object2IntBiMap(T defaultForwardsValue) { - this(16, 0.75F, defaultForwardsValue, -1); - } - - public Object2IntBiMap(int expected, float loadFactor) { - this(expected, loadFactor, -1); - } - - public Object2IntBiMap(int expected, float loadFactor, int defaultBackwardsValue) { - this(expected, loadFactor, null, defaultBackwardsValue); - } - - public Object2IntBiMap(int expected, float loadFactor, T defaultForwardsValue, int defaultBackwardsValue) { - this.forwards = new Object2IntOpenHashMap<>(expected, loadFactor); - this.backwards = new Int2ObjectOpenHashMap<>(expected, loadFactor); - this.forwards.defaultReturnValue(defaultBackwardsValue); - this.backwards.defaultReturnValue(defaultForwardsValue); - } - - @Override - public int size() { - return this.forwards.size(); - } - - @Override - public boolean isEmpty() { - return this.forwards.isEmpty(); - } - - @Override - public int getInt(Object o) { - return this.forwards.getInt(o); - } - - public T get(int key) { - return this.backwards.get(key); - } - - @Override - public int getOrDefault(Object key, int defaultValue) { - return this.forwards.getOrDefault(key, defaultValue); - } - - public T getOrDefault(int key, T defaultValue) { - return this.backwards.getOrDefault(key, defaultValue); - } - - @Override - public void defaultReturnValue(int i) { - this.forwards.defaultReturnValue(i); - } - - public void defaultReturnValue(T v) { - this.backwards.defaultReturnValue(v); - } - - @Override - public int defaultReturnValue() { - return this.forwards.defaultReturnValue(); - } - - public T backwardsDefaultReturnValue() { - return this.backwards.defaultReturnValue(); - } - - @Override - public ObjectSet> object2IntEntrySet() { - return ObjectSets.unmodifiable(this.forwards.object2IntEntrySet()); - } - - public ObjectSet> int2ObjectEntrySet() { - return ObjectSets.unmodifiable(this.backwards.int2ObjectEntrySet()); - } - - @Override - public ObjectSet keySet() { - return this.forwards.keySet(); - } - - @Override - public IntCollection values() { - return this.forwards.values(); - } - - @Override - public boolean containsKey(Object o) { - return this.forwards.containsKey(o); - } - - @Override - public boolean containsValue(int i) { - return this.backwards.containsKey(i); - } - - @Override - public int put(T key, int value) { - this.backwards.put(value, key); - return this.forwards.put(key, value); - } - - @Override - public void putAll(@NotNull Map m) { - this.forwards.putAll(m); - for (Map.Entry entry : m.entrySet()) { - this.backwards.put((int) entry.getValue(), entry.getKey()); - } - } - - @Override - public int removeInt(Object key) { - if (!this.forwards.containsKey(key)) { - return this.defaultReturnValue(); - } - - int value = this.forwards.getInt(key); - if (!this.backwards.containsKey(value)) { - return this.defaultReturnValue(); - }; - this.backwards.remove(value); - return this.forwards.removeInt(key); - } - - @Override - public int hashCode() { - return this.forwards.hashCode(); - } - - @Override - public String toString() { - return this.forwards.toString(); - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - Object2IntBiMap that = (Object2IntBiMap) o; - return Objects.equals(this.forwards, that.forwards) && Objects.equals(this.backwards, that.backwards); - } -}