Mirror von
https://github.com/GeyserMC/Geyser.git
synchronisiert 2024-11-20 06:50:09 +01:00
Merge remote-tracking branch 'upstream/dev' into client-vehicle
Dieser Commit ist enthalten in:
Commit
91574efdb6
@ -4,6 +4,12 @@ dependencies {
|
||||
isTransitive = false
|
||||
}
|
||||
|
||||
implementation(libs.erosion.bukkit.nms) {
|
||||
attributes {
|
||||
attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 21)
|
||||
}
|
||||
}
|
||||
|
||||
implementation(variantOf(libs.adapters.spigot) {
|
||||
classifier("all") // otherwise the unshaded jar is used without the shaded NMS implementations
|
||||
})
|
||||
|
@ -34,6 +34,7 @@ import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.block.BlockPlaceEvent;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.level.block.BlockStateValues;
|
||||
import org.geysermc.geyser.level.block.type.Block;
|
||||
import org.geysermc.geyser.platform.spigot.world.manager.GeyserSpigotWorldManager;
|
||||
import org.geysermc.geyser.registry.BlockRegistries;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
@ -59,7 +60,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_IDENTIFIER_TO_ID.get().getOrDefault(javaBlockId, BlockStateValues.JAVA_AIR_ID)));
|
||||
placeBlockSoundPacket.setExtraData(session.getBlockMappings().getBedrockBlockId(BlockRegistries.JAVA_IDENTIFIER_TO_ID.get().getOrDefault(javaBlockId, Block.JAVA_AIR_ID)));
|
||||
}
|
||||
placeBlockSoundPacket.setIdentifier(":");
|
||||
session.sendUpstreamPacket(placeBlockSoundPacket);
|
||||
|
@ -34,6 +34,7 @@ import org.geysermc.geyser.adapters.WorldAdapter;
|
||||
import org.geysermc.geyser.adapters.paper.PaperAdapters;
|
||||
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.session.GeyserSession;
|
||||
|
||||
public class GeyserSpigotNativeWorldManager extends GeyserSpigotWorldManager {
|
||||
@ -52,7 +53,7 @@ public class GeyserSpigotNativeWorldManager extends GeyserSpigotWorldManager {
|
||||
public int getBlockAt(GeyserSession session, int x, int y, int z) {
|
||||
Player player = Bukkit.getPlayer(session.getPlayerEntity().getUsername());
|
||||
if (player == null) {
|
||||
return BlockStateValues.JAVA_AIR_ID;
|
||||
return Block.JAVA_AIR_ID;
|
||||
}
|
||||
return adapter.getBlockAt(player.getWorld(), x, y, z);
|
||||
}
|
||||
|
@ -25,9 +25,7 @@
|
||||
|
||||
package org.geysermc.geyser.platform.spigot.world.manager;
|
||||
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.GameMode;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityInfo;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.World;
|
||||
@ -39,6 +37,7 @@ import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.cloudburstmc.nbt.NbtMap;
|
||||
import org.geysermc.erosion.bukkit.BukkitLecterns;
|
||||
import org.geysermc.erosion.bukkit.BukkitUtils;
|
||||
import org.geysermc.erosion.bukkit.PickBlockUtils;
|
||||
import org.geysermc.erosion.bukkit.SchedulerUtils;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.level.GameRule;
|
||||
@ -47,6 +46,9 @@ import org.geysermc.geyser.level.block.BlockStateValues;
|
||||
import org.geysermc.geyser.registry.BlockRegistries;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.util.BlockEntityUtils;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.GameMode;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityInfo;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
@ -68,12 +70,12 @@ public class GeyserSpigotWorldManager extends WorldManager {
|
||||
public int getBlockAt(GeyserSession session, int x, int y, int z) {
|
||||
Player bukkitPlayer;
|
||||
if ((bukkitPlayer = Bukkit.getPlayer(session.getPlayerEntity().getUsername())) == null) {
|
||||
return BlockStateValues.JAVA_AIR_ID;
|
||||
return org.geysermc.geyser.level.block.type.Block.JAVA_AIR_ID;
|
||||
}
|
||||
World world = bukkitPlayer.getWorld();
|
||||
if (!world.isChunkLoaded(x >> 4, z >> 4)) {
|
||||
// If the chunk isn't loaded, how could we even be here?
|
||||
return BlockStateValues.JAVA_AIR_ID;
|
||||
return org.geysermc.geyser.level.block.type.Block.JAVA_AIR_ID;
|
||||
}
|
||||
|
||||
return getBlockNetworkId(world.getBlockAt(x, y, z));
|
||||
@ -84,9 +86,9 @@ public class GeyserSpigotWorldManager extends WorldManager {
|
||||
// Terrible behavior, but this is basically what's always been happening behind the scenes anyway.
|
||||
CompletableFuture<String> blockData = new CompletableFuture<>();
|
||||
Bukkit.getRegionScheduler().execute(this.plugin, block.getLocation(), () -> blockData.complete(block.getBlockData().getAsString()));
|
||||
return BlockRegistries.JAVA_IDENTIFIER_TO_ID.getOrDefault(blockData.join(), BlockStateValues.JAVA_AIR_ID);
|
||||
return BlockRegistries.JAVA_IDENTIFIER_TO_ID.getOrDefault(blockData.join(), org.geysermc.geyser.level.block.type.Block.JAVA_AIR_ID);
|
||||
}
|
||||
return BlockRegistries.JAVA_IDENTIFIER_TO_ID.getOrDefault(block.getBlockData().getAsString(), BlockStateValues.JAVA_AIR_ID);
|
||||
return BlockRegistries.JAVA_IDENTIFIER_TO_ID.getOrDefault(block.getBlockData().getAsString(), org.geysermc.geyser.level.block.type.Block.JAVA_AIR_ID);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -205,17 +207,16 @@ public class GeyserSpigotWorldManager extends WorldManager {
|
||||
|
||||
@Override
|
||||
public @NonNull CompletableFuture<@Nullable DataComponents> getPickItemComponents(GeyserSession session, int x, int y, int z, boolean addNbtData) {
|
||||
CompletableFuture<@Nullable DataComponents> future = new CompletableFuture<>();
|
||||
Player bukkitPlayer;
|
||||
if ((bukkitPlayer = Bukkit.getPlayer(session.getPlayerEntity().getUuid())) == null) {
|
||||
future.complete(null);
|
||||
return future;
|
||||
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)*/ null), block); // TODO fix erosion once clear how to handle this
|
||||
return future;
|
||||
SchedulerUtils.runTask(this.plugin, () -> future.complete(PickBlockUtils.pickBlock(block)), block);
|
||||
return future.thenApply(RAW_TRANSFORMER);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -45,6 +45,7 @@ import org.cloudburstmc.protocol.bedrock.codec.BedrockCodec;
|
||||
import org.geysermc.api.Geyser;
|
||||
import org.geysermc.cumulus.form.Form;
|
||||
import org.geysermc.cumulus.form.util.FormBuilder;
|
||||
import org.geysermc.erosion.packet.Packets;
|
||||
import org.geysermc.floodgate.crypto.AesCipher;
|
||||
import org.geysermc.floodgate.crypto.AesKeyProducer;
|
||||
import org.geysermc.floodgate.crypto.Base64Topping;
|
||||
@ -77,6 +78,7 @@ import org.geysermc.geyser.scoreboard.ScoreboardUpdater;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.session.PendingMicrosoftAuthentication;
|
||||
import org.geysermc.geyser.session.SessionManager;
|
||||
import org.geysermc.geyser.session.cache.RegistryCache;
|
||||
import org.geysermc.geyser.skin.FloodgateSkinUploader;
|
||||
import org.geysermc.geyser.skin.ProvidedSkins;
|
||||
import org.geysermc.geyser.skin.SkinProvider;
|
||||
@ -211,6 +213,8 @@ public class GeyserImpl implements GeyserApi {
|
||||
Registries.init();
|
||||
BlockRegistries.init();
|
||||
|
||||
RegistryCache.init();
|
||||
|
||||
/* Initialize translators */
|
||||
EntityDefinitions.init();
|
||||
MessageTranslator.init();
|
||||
@ -252,6 +256,17 @@ public class GeyserImpl implements GeyserApi {
|
||||
}
|
||||
|
||||
VersionCheckUtils.checkForOutdatedJava(logger);
|
||||
|
||||
for (int i = 0; i < BlockRegistries.JAVA_BLOCKS.get().length; i++) {
|
||||
String cleanIdentifier = BlockRegistries.JAVA_BLOCKS.get(i).getCleanJavaIdentifier();
|
||||
String newIdentifier = BlockRegistries.BLOCK_STATES.get(i).block().javaIdentifier();
|
||||
if (!cleanIdentifier.equals(newIdentifier)) {
|
||||
System.out.println("Check block " + BlockRegistries.BLOCK_STATES.get(i).block().javaIdentifier());
|
||||
break;
|
||||
}
|
||||
}
|
||||
System.out.println(BlockRegistries.JAVA_BLOCKS.get().length);
|
||||
System.out.println(BlockRegistries.BLOCK_STATES.get().size());
|
||||
}
|
||||
|
||||
private void startInstance() {
|
||||
@ -383,7 +398,7 @@ public class GeyserImpl implements GeyserApi {
|
||||
|
||||
this.newsHandler = new NewsHandler(BRANCH, this.buildNumber());
|
||||
|
||||
//Packets.initGeyser();
|
||||
Packets.initGeyser();
|
||||
|
||||
if (Epoll.isAvailable()) {
|
||||
this.erosionUnixListener = new UnixSocketClientListener();
|
||||
|
@ -135,7 +135,7 @@ public class Entity implements GeyserEntity {
|
||||
|
||||
this.valid = false;
|
||||
|
||||
this.propertyManager = new GeyserEntityPropertyManager(definition.registeredProperties());
|
||||
this.propertyManager = definition.registeredProperties() == null ? null : new GeyserEntityPropertyManager(definition.registeredProperties());
|
||||
|
||||
setPosition(position);
|
||||
setAirSupply(getMaxAir());
|
||||
@ -369,7 +369,7 @@ public class Entity implements GeyserEntity {
|
||||
return;
|
||||
}
|
||||
|
||||
if (propertyManager.hasProperties()) {
|
||||
if (propertyManager != null && propertyManager.hasProperties()) {
|
||||
SetEntityDataPacket entityDataPacket = new SetEntityDataPacket();
|
||||
entityDataPacket.setRuntimeEntityId(geyserId);
|
||||
propertyManager.applyIntProperties(entityDataPacket.getProperties().getIntProperties());
|
||||
|
@ -33,6 +33,7 @@ import org.geysermc.erosion.util.BlockPositionIterator;
|
||||
import org.geysermc.geyser.entity.EntityDefinitions;
|
||||
import org.geysermc.geyser.entity.type.player.PlayerEntity;
|
||||
import org.geysermc.geyser.level.block.BlockStateValues;
|
||||
import org.geysermc.geyser.level.block.type.Block;
|
||||
import org.geysermc.geyser.level.physics.BoundingBox;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.translator.collision.BlockCollision;
|
||||
@ -162,7 +163,7 @@ public class FishingHookEntity extends ThrowableEntity {
|
||||
*/
|
||||
protected boolean isInAir() {
|
||||
int block = session.getGeyser().getWorldManager().getBlockAt(session, position.toInt());
|
||||
return block == BlockStateValues.JAVA_AIR_ID;
|
||||
return block == Block.JAVA_AIR_ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -25,8 +25,6 @@
|
||||
|
||||
package org.geysermc.geyser.erosion;
|
||||
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.level.block.value.PistonValueType;
|
||||
import io.netty.channel.Channel;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMaps;
|
||||
@ -43,21 +41,16 @@ import org.geysermc.erosion.packet.ErosionPacketHandler;
|
||||
import org.geysermc.erosion.packet.ErosionPacketSender;
|
||||
import org.geysermc.erosion.packet.backendbound.BackendboundInitializePacket;
|
||||
import org.geysermc.erosion.packet.backendbound.BackendboundPacket;
|
||||
import org.geysermc.erosion.packet.geyserbound.GeyserboundBatchBlockIdPacket;
|
||||
import org.geysermc.erosion.packet.geyserbound.GeyserboundBlockEntityPacket;
|
||||
import org.geysermc.erosion.packet.geyserbound.GeyserboundBlockIdPacket;
|
||||
import org.geysermc.erosion.packet.geyserbound.GeyserboundBlockLookupFailPacket;
|
||||
import org.geysermc.erosion.packet.geyserbound.GeyserboundBlockPlacePacket;
|
||||
import org.geysermc.erosion.packet.geyserbound.GeyserboundHandshakePacket;
|
||||
import org.geysermc.erosion.packet.geyserbound.GeyserboundPickBlockPacket;
|
||||
import org.geysermc.erosion.packet.geyserbound.GeyserboundPistonEventPacket;
|
||||
import org.geysermc.erosion.packet.geyserbound.*;
|
||||
import org.geysermc.geyser.level.block.BlockStateValues;
|
||||
import org.geysermc.geyser.level.block.type.Block;
|
||||
import org.geysermc.geyser.level.physics.Direction;
|
||||
import org.geysermc.geyser.network.GameProtocol;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.session.cache.PistonCache;
|
||||
import org.geysermc.geyser.translator.level.block.entity.PistonBlockEntity;
|
||||
import org.geysermc.geyser.util.BlockEntityUtils;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.level.block.value.PistonValueType;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
@ -71,7 +64,7 @@ public final class GeyserboundPacketHandlerImpl extends AbstractGeyserboundPacke
|
||||
@Setter
|
||||
private CompletableFuture<int[]> pendingBatchLookup = null;
|
||||
@Setter
|
||||
private CompletableFuture<DataComponents> pickBlockLookup = null;
|
||||
private CompletableFuture<Int2ObjectMap<byte[]>> pickBlockLookup = null;
|
||||
|
||||
private final AtomicInteger nextTransactionId = new AtomicInteger(1);
|
||||
|
||||
@ -127,7 +120,7 @@ public final class GeyserboundPacketHandlerImpl extends AbstractGeyserboundPacke
|
||||
}
|
||||
CompletableFuture<Integer> future = this.asyncPendingLookups.remove(transactionId);
|
||||
if (future != null) {
|
||||
future.complete(BlockStateValues.JAVA_AIR_ID);
|
||||
future.complete(Block.JAVA_AIR_ID);
|
||||
}
|
||||
}
|
||||
|
||||
@ -147,7 +140,7 @@ public final class GeyserboundPacketHandlerImpl extends AbstractGeyserboundPacke
|
||||
@Override
|
||||
public void handlePickBlock(GeyserboundPickBlockPacket packet) {
|
||||
if (this.pickBlockLookup != null) {
|
||||
//this.pickBlockLookup.complete(packet.getTag()); // TODO 1.20.5
|
||||
this.pickBlockLookup.complete(packet.getComponents());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -25,6 +25,7 @@
|
||||
|
||||
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.Object2ObjectOpenHashMap;
|
||||
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
|
||||
@ -179,9 +180,9 @@ public class GeyserWorldManager extends WorldManager {
|
||||
if (erosionHandler == null) {
|
||||
return super.getPickItemComponents(session, x, y, z, addNbtData);
|
||||
}
|
||||
CompletableFuture<DataComponents> future = new CompletableFuture<>();
|
||||
CompletableFuture<Int2ObjectMap<byte[]>> future = new CompletableFuture<>();
|
||||
erosionHandler.setPickBlockLookup(future);
|
||||
erosionHandler.sendPacket(new BackendboundPickBlockPacket(Vector3i.from(x, y, z)));
|
||||
return future;
|
||||
return future.thenApply(RAW_TRANSFORMER);
|
||||
}
|
||||
}
|
||||
|
@ -25,19 +25,29 @@
|
||||
|
||||
package org.geysermc.geyser.level;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMaps;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.cloudburstmc.math.vector.Vector3i;
|
||||
import org.geysermc.erosion.util.BlockPositionIterator;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.GameMode;
|
||||
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 org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityInfo;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.setting.Difficulty;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* Class that manages or retrieves various information
|
||||
@ -223,4 +233,20 @@ public abstract class WorldManager {
|
||||
public CompletableFuture<@Nullable DataComponents> getPickItemComponents(GeyserSession session, int x, int y, int z, boolean addExtraData) {
|
||||
return CompletableFuture.completedFuture(null);
|
||||
}
|
||||
|
||||
protected static final Function<Int2ObjectMap<byte[]>, DataComponents> RAW_TRANSFORMER = map -> {
|
||||
try {
|
||||
Map<DataComponentType<?>, DataComponent<?, ?>> components = new HashMap<>();
|
||||
Int2ObjectMaps.fastForEach(map, entry -> {
|
||||
DataComponentType type = DataComponentType.from(entry.getIntKey());
|
||||
ByteBuf buf = Unpooled.wrappedBuffer(entry.getValue());
|
||||
DataComponent value = type.readDataComponent(ItemCodecHelper.INSTANCE, buf);
|
||||
components.put(type, value);
|
||||
});
|
||||
return new DataComponents(components);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -30,6 +30,7 @@ import it.unimi.dsi.fastutil.ints.*;
|
||||
import it.unimi.dsi.fastutil.objects.Object2IntMap;
|
||||
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.geysermc.geyser.level.block.type.Block;
|
||||
import org.geysermc.geyser.level.physics.Direction;
|
||||
import org.geysermc.geyser.level.physics.PistonBehavior;
|
||||
import org.geysermc.geyser.registry.BlockRegistries;
|
||||
@ -49,7 +50,6 @@ public final class BlockStateValues {
|
||||
private static final Int2IntMap BANNER_COLORS = new FixedInt2IntMap();
|
||||
private static final Int2ByteMap BED_COLORS = new FixedInt2ByteMap();
|
||||
private static final Int2IntMap BRUSH_PROGRESS = new Int2IntOpenHashMap();
|
||||
private static final Int2ByteMap COMMAND_BLOCK_VALUES = new Int2ByteOpenHashMap();
|
||||
private static final Int2ObjectMap<DoubleChestValue> DOUBLE_CHEST_VALUES = new Int2ObjectOpenHashMap<>();
|
||||
private static final Int2ObjectMap<String> FLOWER_POT_VALUES = new Int2ObjectOpenHashMap<>();
|
||||
private static final IntSet HORIZONTAL_FACING_JIGSAWS = new IntOpenHashSet();
|
||||
@ -83,10 +83,6 @@ public final class BlockStateValues {
|
||||
public static int JAVA_SLIME_BLOCK_ID;
|
||||
public static int JAVA_SPAWNER_ID;
|
||||
public static int JAVA_WATER_ID;
|
||||
public static int JAVA_BUBBLE_COLUMN_DRAG_ID;
|
||||
public static int JAVA_BUBBLE_COLUMN_UPWARD_ID;
|
||||
public static int JAVA_SOUL_SAND_ID;
|
||||
public static int JAVA_ICE_ID;
|
||||
|
||||
public static final int NUM_FLUID_LEVELS = 9;
|
||||
|
||||
@ -119,11 +115,6 @@ public final class BlockStateValues {
|
||||
}
|
||||
}
|
||||
|
||||
if (javaId.contains("command_block")) {
|
||||
COMMAND_BLOCK_VALUES.put(javaBlockState, javaId.contains("conditional=true") ? (byte) 1 : (byte) 0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (blockData.get("double_chest_position") != null) {
|
||||
boolean isX = (blockData.get("x") != null);
|
||||
boolean isDirectionPositive = ((blockData.get("x") != null && blockData.get("x").asBoolean()) ||
|
||||
@ -234,7 +225,7 @@ public final class BlockStateValues {
|
||||
ALL_CAULDRONS.add(javaBlockState);
|
||||
}
|
||||
if (javaId.contains("_cauldron") && !javaId.contains("water_")) {
|
||||
NON_WATER_CAULDRONS.add(javaBlockState);
|
||||
NON_WATER_CAULDRONS.add(javaBlockState);
|
||||
}
|
||||
|
||||
if (javaId.contains("vine") || javaId.startsWith("minecraft:ladder") || javaId.startsWith("minecraft:scaffolding")) {
|
||||
@ -305,16 +296,6 @@ public final class BlockStateValues {
|
||||
return ALL_CAULDRONS.contains(state);
|
||||
}
|
||||
|
||||
/**
|
||||
* The block state in Java and Bedrock both contain the conditional bit, however command block block entity tags
|
||||
* in Bedrock need the conditional information.
|
||||
*
|
||||
* @return the list of all command blocks and if they are conditional (1 or 0)
|
||||
*/
|
||||
public static Int2ByteMap getCommandBlockValues() {
|
||||
return COMMAND_BLOCK_VALUES;
|
||||
}
|
||||
|
||||
/**
|
||||
* All double chest values are part of the block state in Java and part of the block entity tag in Bedrock.
|
||||
* This gives the DoubleChestValue that can be calculated into the final tag.
|
||||
@ -384,7 +365,7 @@ public final class BlockStateValues {
|
||||
* @return Block state for the piston head
|
||||
*/
|
||||
public static int getPistonHead(Direction direction) {
|
||||
return PISTON_HEADS.getOrDefault(direction, BlockStateValues.JAVA_AIR_ID);
|
||||
return PISTON_HEADS.getOrDefault(direction, Block.JAVA_AIR_ID);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -448,7 +429,7 @@ public final class BlockStateValues {
|
||||
}
|
||||
|
||||
public static boolean canPistonMoveBlock(int javaId, boolean isPushing) {
|
||||
if (javaId == JAVA_AIR_ID) {
|
||||
if (javaId == Block.JAVA_AIR_ID) {
|
||||
return true;
|
||||
}
|
||||
// Pistons can only be moved if they aren't extended
|
||||
|
2820
core/src/main/java/org/geysermc/geyser/level/block/Blocks.java
Normale Datei
2820
core/src/main/java/org/geysermc/geyser/level/block/Blocks.java
Normale Datei
Datei-Diff unterdrückt, da er zu groß ist
Diff laden
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* 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.level.block.property;
|
||||
|
||||
public enum ChestType {
|
||||
SINGLE,
|
||||
LEFT,
|
||||
RIGHT;
|
||||
|
||||
public static final ChestType[] VALUES = values();
|
||||
}
|
@ -0,0 +1,146 @@
|
||||
/*
|
||||
* 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.level.block.property;
|
||||
|
||||
import org.geysermc.geyser.level.physics.Axis;
|
||||
import org.geysermc.geyser.level.physics.Direction;
|
||||
|
||||
public final class Properties {
|
||||
public static final Property<Boolean> ATTACHED = Property.create("attached");
|
||||
public static final Property<Boolean> BOTTOM = Property.create("bottom");
|
||||
public static final Property<Boolean> CONDITIONAL = Property.create("conditional");
|
||||
public static final Property<Boolean> DISARMED = Property.create("disarmed");
|
||||
public static final Property<Boolean> DRAG = Property.create("drag");
|
||||
public static final Property<Boolean> ENABLED = Property.create("enabled");
|
||||
public static final Property<Boolean> EXTENDED = Property.create("extended");
|
||||
public static final Property<Boolean> EYE = Property.create("eye");
|
||||
public static final Property<Boolean> FALLING = Property.create("falling");
|
||||
public static final Property<Boolean> HANGING = Property.create("hanging");
|
||||
public static final Property<Boolean> HAS_BOTTLE_0 = Property.create("has_bottle_0");
|
||||
public static final Property<Boolean> HAS_BOTTLE_1 = Property.create("has_bottle_1");
|
||||
public static final Property<Boolean> HAS_BOTTLE_2 = Property.create("has_bottle_2");
|
||||
public static final Property<Boolean> HAS_RECORD = Property.create("has_record");
|
||||
public static final Property<Boolean> HAS_BOOK = Property.create("has_book");
|
||||
public static final Property<Boolean> INVERTED = Property.create("inverted");
|
||||
public static final Property<Boolean> IN_WALL = Property.create("in_wall");
|
||||
public static final Property<Boolean> LIT = Property.create("lit");
|
||||
public static final Property<Boolean> LOCKED = Property.create("locked");
|
||||
public static final Property<Boolean> OCCUPIED = Property.create("occupied");
|
||||
public static final Property<Boolean> OPEN = Property.create("open");
|
||||
public static final Property<Boolean> PERSISTENT = Property.create("persistent");
|
||||
public static final Property<Boolean> POWERED = Property.create("powered");
|
||||
public static final Property<Boolean> SHORT = Property.create("short");
|
||||
public static final Property<Boolean> SIGNAL_FIRE = Property.create("signal_fire");
|
||||
public static final Property<Boolean> SNOWY = Property.create("snowy");
|
||||
public static final Property<Boolean> TRIGGERED = Property.create("triggered");
|
||||
public static final Property<Boolean> UNSTABLE = Property.create("unstable");
|
||||
public static final Property<Boolean> WATERLOGGED = Property.create("waterlogged");
|
||||
public static final Property<Boolean> BERRIES = Property.create("berries");
|
||||
public static final Property<Boolean> BLOOM = Property.create("bloom");
|
||||
public static final Property<Boolean> SHRIEKING = Property.create("shrieking");
|
||||
public static final Property<Boolean> CAN_SUMMON = Property.create("can_summon");
|
||||
public static final Property<Axis> HORIZONTAL_AXIS = Property.create("axis");
|
||||
public static final Property<Axis> AXIS = Property.create("axis");
|
||||
public static final Property<Boolean> UP = Property.create("up");
|
||||
public static final Property<Boolean> DOWN = Property.create("down");
|
||||
public static final Property<Boolean> NORTH = Property.create("north");
|
||||
public static final Property<Boolean> EAST = Property.create("east");
|
||||
public static final Property<Boolean> SOUTH = Property.create("south");
|
||||
public static final Property<Boolean> WEST = Property.create("west");
|
||||
public static final Property<Direction> FACING = Property.create("facing");
|
||||
public static final Property<Direction> FACING_HOPPER = Property.create("facing");
|
||||
public static final Property<Direction> HORIZONTAL_FACING = Property.create("facing");
|
||||
public static final Property<Integer> FLOWER_AMOUNT = Property.create("flower_amount");
|
||||
public static final Property<String> ORIENTATION = Property.create("orientation");
|
||||
public static final Property<String> ATTACH_FACE = Property.create("face");
|
||||
public static final Property<String> BELL_ATTACHMENT = Property.create("attachment");
|
||||
public static final Property<String> EAST_WALL = Property.create("east");
|
||||
public static final Property<String> NORTH_WALL = Property.create("north");
|
||||
public static final Property<String> SOUTH_WALL = Property.create("south");
|
||||
public static final Property<String> WEST_WALL = Property.create("west");
|
||||
public static final Property<String> EAST_REDSTONE = Property.create("east");
|
||||
public static final Property<String> NORTH_REDSTONE = Property.create("north");
|
||||
public static final Property<String> SOUTH_REDSTONE = Property.create("south");
|
||||
public static final Property<String> WEST_REDSTONE = Property.create("west");
|
||||
public static final Property<String> DOUBLE_BLOCK_HALF = Property.create("half");
|
||||
public static final Property<String> HALF = Property.create("half");
|
||||
public static final Property<String> RAIL_SHAPE = Property.create("shape");
|
||||
public static final Property<String> RAIL_SHAPE_STRAIGHT = Property.create("shape");
|
||||
public static final Property<Integer> AGE_1 = Property.create("age");
|
||||
public static final Property<Integer> AGE_2 = Property.create("age");
|
||||
public static final Property<Integer> AGE_3 = Property.create("age");
|
||||
public static final Property<Integer> AGE_4 = Property.create("age");
|
||||
public static final Property<Integer> AGE_5 = Property.create("age");
|
||||
public static final Property<Integer> AGE_7 = Property.create("age");
|
||||
public static final Property<Integer> AGE_15 = Property.create("age");
|
||||
public static final Property<Integer> AGE_25 = Property.create("age");
|
||||
public static final Property<Integer> BITES = Property.create("bites");
|
||||
public static final Property<Integer> CANDLES = Property.create("candles");
|
||||
public static final Property<Integer> DELAY = Property.create("delay");
|
||||
public static final Property<Integer> DISTANCE = Property.create("distance");
|
||||
public static final Property<Integer> EGGS = Property.create("eggs");
|
||||
public static final Property<Integer> HATCH = Property.create("hatch");
|
||||
public static final Property<Integer> LAYERS = Property.create("layers");
|
||||
public static final Property<Integer> LEVEL_CAULDRON = Property.create("level");
|
||||
public static final Property<Integer> LEVEL_COMPOSTER = Property.create("level");
|
||||
public static final Property<Integer> LEVEL_FLOWING = Property.create("level");
|
||||
public static final Property<Integer> LEVEL_HONEY = Property.create("honey_level");
|
||||
public static final Property<Integer> LEVEL = Property.create("level");
|
||||
public static final Property<Integer> MOISTURE = Property.create("moisture");
|
||||
public static final Property<Integer> NOTE = Property.create("note");
|
||||
public static final Property<Integer> PICKLES = Property.create("pickles");
|
||||
public static final Property<Integer> POWER = Property.create("power");
|
||||
public static final Property<Integer> STAGE = Property.create("stage");
|
||||
public static final Property<Integer> STABILITY_DISTANCE = Property.create("distance");
|
||||
public static final Property<Integer> RESPAWN_ANCHOR_CHARGES = Property.create("charges");
|
||||
public static final Property<Integer> ROTATION_16 = Property.create("rotation");
|
||||
public static final Property<String> BED_PART = Property.create("part");
|
||||
public static final Property<String> CHEST_TYPE = Property.create("type");
|
||||
public static final Property<String> MODE_COMPARATOR = Property.create("mode");
|
||||
public static final Property<String> DOOR_HINGE = Property.create("hinge");
|
||||
public static final Property<String> NOTEBLOCK_INSTRUMENT = Property.create("instrument");
|
||||
public static final Property<String> PISTON_TYPE = Property.create("type");
|
||||
public static final Property<String> SLAB_TYPE = Property.create("type");
|
||||
public static final Property<String> STAIRS_SHAPE = Property.create("shape");
|
||||
public static final Property<String> STRUCTUREBLOCK_MODE = Property.create("mode");
|
||||
public static final Property<String> BAMBOO_LEAVES = Property.create("leaves");
|
||||
public static final Property<String> TILT = Property.create("tilt");
|
||||
public static final Property<Direction> VERTICAL_DIRECTION = Property.create("vertical_direction");
|
||||
public static final Property<String> DRIPSTONE_THICKNESS = Property.create("thickness");
|
||||
public static final Property<String> SCULK_SENSOR_PHASE = Property.create("sculk_sensor_phase");
|
||||
public static final Property<Boolean> CHISELED_BOOKSHELF_SLOT_0_OCCUPIED = Property.create("slot_0_occupied");
|
||||
public static final Property<Boolean> CHISELED_BOOKSHELF_SLOT_1_OCCUPIED = Property.create("slot_1_occupied");
|
||||
public static final Property<Boolean> CHISELED_BOOKSHELF_SLOT_2_OCCUPIED = Property.create("slot_2_occupied");
|
||||
public static final Property<Boolean> CHISELED_BOOKSHELF_SLOT_3_OCCUPIED = Property.create("slot_3_occupied");
|
||||
public static final Property<Boolean> CHISELED_BOOKSHELF_SLOT_4_OCCUPIED = Property.create("slot_4_occupied");
|
||||
public static final Property<Boolean> CHISELED_BOOKSHELF_SLOT_5_OCCUPIED = Property.create("slot_5_occupied");
|
||||
public static final Property<Integer> DUSTED = Property.create("dusted");
|
||||
public static final Property<Boolean> CRACKED = Property.create("cracked");
|
||||
public static final Property<Boolean> CRAFTING = Property.create("crafting");
|
||||
public static final Property<String> TRIAL_SPAWNER_STATE = Property.create("trial_spawner_state");
|
||||
public static final Property<String> VAULT_STATE = Property.create("vault_state");
|
||||
public static final Property<Boolean> OMINOUS = Property.create("ominous");
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (c) 2024 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.level.block.property;
|
||||
|
||||
public class Property<T extends Comparable<T>> {
|
||||
private final String name;
|
||||
|
||||
public Property(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getClass().getSimpleName() + "[" + name + "]";
|
||||
}
|
||||
|
||||
public static <T extends Comparable<T>> Property<T> create(String name) {
|
||||
return new Property<>(name);
|
||||
}
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* 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.level.block.type;
|
||||
|
||||
public class BannerBlock extends Block {
|
||||
private final int dyeColor;
|
||||
|
||||
public BannerBlock(String javaIdentifier, int dyeColor, Builder builder) {
|
||||
super(javaIdentifier, builder);
|
||||
this.dyeColor = dyeColor;
|
||||
}
|
||||
|
||||
public int dyeColor() {
|
||||
return dyeColor;
|
||||
}
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* 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.level.block.type;
|
||||
|
||||
public class BedBlock extends Block {
|
||||
private final int dyeColor;
|
||||
|
||||
public BedBlock(String javaIdentifier, int dyeColor, Builder builder) {
|
||||
super(javaIdentifier, builder);
|
||||
this.dyeColor = dyeColor;
|
||||
}
|
||||
|
||||
public int dyeColor() {
|
||||
return dyeColor;
|
||||
}
|
||||
}
|
188
core/src/main/java/org/geysermc/geyser/level/block/type/Block.java
Normale Datei
188
core/src/main/java/org/geysermc/geyser/level/block/type/Block.java
Normale Datei
@ -0,0 +1,188 @@
|
||||
/*
|
||||
* 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.level.block.type;
|
||||
|
||||
import it.unimi.dsi.fastutil.Pair;
|
||||
import it.unimi.dsi.fastutil.ints.IntArrayList;
|
||||
import it.unimi.dsi.fastutil.ints.IntList;
|
||||
import it.unimi.dsi.fastutil.objects.Reference2ObjectArrayMap;
|
||||
import it.unimi.dsi.fastutil.objects.Reference2ObjectMap;
|
||||
import org.geysermc.geyser.level.block.property.Property;
|
||||
import org.geysermc.geyser.registry.BlockRegistries;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.Identifier;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class Block {
|
||||
public static final int JAVA_AIR_ID = 0;
|
||||
|
||||
private final String javaIdentifier;
|
||||
private final boolean requiresCorrectToolForDrops;
|
||||
private final boolean hasBlockEntity;
|
||||
private final float destroyTime;
|
||||
private int javaId = -1;
|
||||
|
||||
public Block(String javaIdentifier, Builder builder) {
|
||||
this.javaIdentifier = Identifier.formalize(javaIdentifier).intern();
|
||||
this.requiresCorrectToolForDrops = builder.requiresCorrectToolForDrops;
|
||||
this.hasBlockEntity = builder.hasBlockEntity;
|
||||
this.destroyTime = builder.destroyTime;
|
||||
builder.build(this);
|
||||
}
|
||||
|
||||
public String javaIdentifier() {
|
||||
return javaIdentifier;
|
||||
}
|
||||
|
||||
public boolean requiresCorrectToolForDrops() {
|
||||
return requiresCorrectToolForDrops;
|
||||
}
|
||||
|
||||
public boolean hasBlockEntity() {
|
||||
return hasBlockEntity;
|
||||
}
|
||||
|
||||
public float destroyTime() {
|
||||
return destroyTime;
|
||||
}
|
||||
|
||||
public int javaId() {
|
||||
return javaId;
|
||||
}
|
||||
|
||||
public void setJavaId(int javaId) {
|
||||
if (this.javaId != -1) {
|
||||
throw new RuntimeException("Block ID has already been set!");
|
||||
}
|
||||
this.javaId = javaId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Item{" +
|
||||
"javaIdentifier='" + javaIdentifier + '\'' +
|
||||
", javaId=" + javaId +
|
||||
'}';
|
||||
}
|
||||
|
||||
public static Builder builder() {
|
||||
return new Builder();
|
||||
}
|
||||
|
||||
public static final class Builder {
|
||||
private final Map<Property<?>, List<Comparable<?>>> states = new LinkedHashMap<>();
|
||||
private boolean requiresCorrectToolForDrops = false;
|
||||
private boolean hasBlockEntity = false;
|
||||
private float destroyTime;
|
||||
|
||||
/**
|
||||
* For states that we're just tracking for mirroring Java states.
|
||||
*/
|
||||
public Builder enumState(Property<String> property, String... values) {
|
||||
states.put(property, List.of(values));
|
||||
return this;
|
||||
}
|
||||
|
||||
@SafeVarargs
|
||||
public final <T extends Enum<T>> Builder enumState(Property<T> property, T... enums) {
|
||||
states.put(property, List.of(enums));
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder booleanState(Property<Boolean> property) {
|
||||
states.put(property, List.of(Boolean.TRUE, Boolean.FALSE)); // Make this list a static constant if it'll survive past initialization
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder intState(Property<Integer> property, int low, int high) {
|
||||
IntList list = new IntArrayList();
|
||||
// There is a state for every number between the low and high.
|
||||
for (int i = low; i <= high; i++) {
|
||||
list.add(i);
|
||||
}
|
||||
states.put(property, List.copyOf(list)); // Boxing reasons for that copy I guess.
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder requiresCorrectToolForDrops() {
|
||||
this.requiresCorrectToolForDrops = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setBlockEntity() {
|
||||
this.hasBlockEntity = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder destroyTime(float destroyTime) {
|
||||
this.destroyTime = destroyTime;
|
||||
return this;
|
||||
}
|
||||
|
||||
private void build(Block block) {
|
||||
if (states.isEmpty()) {
|
||||
BlockRegistries.BLOCK_STATES.get().add(new BlockState(block, BlockRegistries.BLOCK_STATES.get().size()));
|
||||
} else {
|
||||
// Think of this stream as another list containing, at the start, one empty list.
|
||||
// It's two collections. Not a stream from the empty list.
|
||||
Stream<List<Pair<Property<?>, Comparable<?>>>> stream = Stream.of(Collections.emptyList());
|
||||
for (var state : this.states.entrySet()) {
|
||||
// OK, so here's how I understand this works. Because this was staring at vanilla Java code trying
|
||||
// to figure out exactly how it works so we don't have any discrepencies.
|
||||
// For each existing pair in the list, a new list is created, adding one of the new values.
|
||||
// Property up [true/false] would exist as true and false
|
||||
// Both entries will get duplicated, adding down, true and false.
|
||||
stream = stream.flatMap(aPreviousPropertiesList ->
|
||||
// So the above is a list. It may be empty if this is the first property,
|
||||
// or it may be populated if this is not the first property.
|
||||
// We're about to create a new stream, each with a new list,
|
||||
// for every previous property
|
||||
state.getValue().stream().map(value -> {
|
||||
var newProperties = new ArrayList<>(aPreviousPropertiesList);
|
||||
newProperties.add(Pair.of(state.getKey(), value));
|
||||
return newProperties;
|
||||
}));
|
||||
}
|
||||
|
||||
// Now we have a list of Pair<Property, Value>s. Each list is a block state!
|
||||
// If we have two boolean properties: up [true/false] and down [true/false],
|
||||
// We'll see [up=true,down=true], [up=false,down=true], [up=true,down=false], [up=false,down=false]
|
||||
stream.forEach(properties -> {
|
||||
Reference2ObjectMap<Property<?>, Comparable<?>> propertyMap = new Reference2ObjectArrayMap<>(properties.size());
|
||||
for (int i = 0; i < properties.size(); i++) {
|
||||
Pair<Property<?>, Comparable<?>> property = properties.get(i);
|
||||
propertyMap.put(property.key(), property.value());
|
||||
}
|
||||
BlockRegistries.BLOCK_STATES.get().add(new BlockState(block, BlockRegistries.BLOCK_STATES.get().size(), propertyMap));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private Builder() {
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* 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.level.block.type;
|
||||
|
||||
import it.unimi.dsi.fastutil.objects.Reference2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.objects.Reference2ObjectMaps;
|
||||
import org.geysermc.geyser.level.block.property.Property;
|
||||
import org.geysermc.geyser.registry.BlockRegistries;
|
||||
|
||||
public final class BlockState {
|
||||
private final Block block;
|
||||
private final int javaId;
|
||||
private final Reference2ObjectMap<Property<?>, Comparable<?>> states;
|
||||
|
||||
BlockState(Block block, int javaId) {
|
||||
this(block, javaId, Reference2ObjectMaps.emptyMap());
|
||||
}
|
||||
|
||||
BlockState(Block block, int javaId, Reference2ObjectMap<Property<?>, Comparable<?>> states) {
|
||||
this.block = block;
|
||||
this.javaId = javaId;
|
||||
this.states = states;
|
||||
}
|
||||
|
||||
public <T extends Comparable<T>> T getValue(Property<T> property) {
|
||||
//noinspection unchecked
|
||||
return (T) states.get(property);
|
||||
}
|
||||
|
||||
public Block block() {
|
||||
return block;
|
||||
}
|
||||
|
||||
public int javaId() {
|
||||
return javaId;
|
||||
}
|
||||
|
||||
public static BlockState of(int javaId) {
|
||||
return BlockRegistries.BLOCK_STATES.get(javaId);
|
||||
}
|
||||
}
|
@ -34,6 +34,9 @@ import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
|
||||
import org.geysermc.geyser.api.block.custom.CustomBlockData;
|
||||
import org.geysermc.geyser.api.block.custom.CustomBlockState;
|
||||
import org.geysermc.geyser.api.block.custom.nonvanilla.JavaBlockState;
|
||||
import org.geysermc.geyser.level.block.Blocks;
|
||||
import org.geysermc.geyser.level.block.type.Block;
|
||||
import org.geysermc.geyser.level.block.type.BlockState;
|
||||
import org.geysermc.geyser.registry.loader.CollisionRegistryLoader;
|
||||
import org.geysermc.geyser.registry.loader.RegistryLoaders;
|
||||
import org.geysermc.geyser.registry.populator.BlockRegistryPopulator;
|
||||
@ -44,8 +47,8 @@ import org.geysermc.geyser.registry.type.BlockMappings;
|
||||
import org.geysermc.geyser.registry.type.CustomSkull;
|
||||
import org.geysermc.geyser.translator.collision.BlockCollision;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.BitSet;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
@ -58,6 +61,14 @@ public class BlockRegistries {
|
||||
*/
|
||||
public static final VersionedRegistry<BlockMappings> BLOCKS = VersionedRegistry.create(RegistryLoaders.empty(Int2ObjectOpenHashMap::new));
|
||||
|
||||
/**
|
||||
* A registry which stores Java IDs to Java {@link BlockState}s, each with their specific state differences and a link
|
||||
* to the overarching block.
|
||||
*/
|
||||
public static final ListRegistry<BlockState> BLOCK_STATES = ListRegistry.create(RegistryLoaders.empty(ArrayList::new));
|
||||
|
||||
public static final ListRegistry<Block> JAVA_BLOCKS_TO_RENAME = ListRegistry.create(RegistryLoaders.empty(ArrayList::new));
|
||||
|
||||
/**
|
||||
* A mapped registry which stores Java to Bedrock block identifiers.
|
||||
*/
|
||||
@ -72,19 +83,13 @@ public class BlockRegistries {
|
||||
/**
|
||||
* A mapped registry containing which holds block IDs to its {@link BlockCollision}.
|
||||
*/
|
||||
public static final IntMappedRegistry<BlockCollision> COLLISIONS;
|
||||
public static final ListRegistry<BlockCollision> COLLISIONS;
|
||||
|
||||
/**
|
||||
* A mapped registry containing the Java identifiers to IDs.
|
||||
*/
|
||||
public static final MappedRegistry<String, Integer, Object2IntMap<String>> 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<String> CLEAN_JAVA_IDENTIFIERS = ArrayRegistry.create(RegistryLoaders.uninitialized());
|
||||
|
||||
/**
|
||||
* A registry containing all the waterlogged blockstates.
|
||||
*/
|
||||
@ -131,12 +136,13 @@ public class BlockRegistries {
|
||||
public static final SimpleMappedRegistry<String, CustomSkull> CUSTOM_SKULLS = SimpleMappedRegistry.create(RegistryLoaders.empty(Object2ObjectOpenHashMap::new));
|
||||
|
||||
static {
|
||||
Blocks.VAULT.javaId(); // FIXME
|
||||
CustomSkullRegistryPopulator.populate();
|
||||
BlockRegistryPopulator.populate(BlockRegistryPopulator.Stage.PRE_INIT);
|
||||
CustomBlockRegistryPopulator.populate(CustomBlockRegistryPopulator.Stage.DEFINITION);
|
||||
CustomBlockRegistryPopulator.populate(CustomBlockRegistryPopulator.Stage.NON_VANILLA_REGISTRATION);
|
||||
BlockRegistryPopulator.populate(BlockRegistryPopulator.Stage.INIT_JAVA);
|
||||
COLLISIONS = IntMappedRegistry.create(Pair.of("org.geysermc.geyser.translator.collision.CollisionRemapper", "mappings/collision.json"), CollisionRegistryLoader::new);
|
||||
COLLISIONS = ListRegistry.create(Pair.of("org.geysermc.geyser.translator.collision.CollisionRemapper", "mappings/collisions.nbt"), CollisionRegistryLoader::new);
|
||||
CustomBlockRegistryPopulator.populate(CustomBlockRegistryPopulator.Stage.VANILLA_REGISTRATION);
|
||||
CustomBlockRegistryPopulator.populate(CustomBlockRegistryPopulator.Stage.CUSTOM_REGISTRATION);
|
||||
BlockRegistryPopulator.populate(BlockRegistryPopulator.Stage.INIT_BEDROCK);
|
||||
|
116
core/src/main/java/org/geysermc/geyser/registry/ListRegistry.java
Normale Datei
116
core/src/main/java/org/geysermc/geyser/registry/ListRegistry.java
Normale Datei
@ -0,0 +1,116 @@
|
||||
/*
|
||||
* Copyright (c) 2024 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.registry;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.geysermc.geyser.registry.loader.RegistryLoader;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class ListRegistry<M> extends Registry<List<M>> {
|
||||
/**
|
||||
* Creates a new instance of this class with the given input and
|
||||
* {@link RegistryLoader}. The input specified is what the registry
|
||||
* loader needs to take in.
|
||||
*
|
||||
* @param input the input
|
||||
* @param registryLoader the registry loader
|
||||
*/
|
||||
protected <I> ListRegistry(I input, RegistryLoader<I, List<M>> registryLoader) {
|
||||
super(input, registryLoader);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value registered by the given index.
|
||||
*
|
||||
* @param index the index
|
||||
* @return the value registered by the given index.
|
||||
*/
|
||||
@Nullable
|
||||
public M get(int index) {
|
||||
if (index >= this.mappings.size()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return this.mappings.get(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value registered by the given index or the default value
|
||||
* specified if null.
|
||||
*
|
||||
* @param index the index
|
||||
* @param defaultValue the default value
|
||||
* @return the value registered by the given key or the default value
|
||||
* specified if null.
|
||||
*/
|
||||
public M getOrDefault(int index, M defaultValue) {
|
||||
M value = this.get(index);
|
||||
if (value == null) {
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a new value into this registry with the given index.
|
||||
*
|
||||
* @param index the index
|
||||
* @param value the value
|
||||
* @return a new value into this registry with the given index.
|
||||
*/
|
||||
public M register(int index, M value) {
|
||||
return this.mappings.set(index, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new array registry with the given {@link RegistryLoader}. The
|
||||
* input type is not specified here, meaning the loader return type is either
|
||||
* predefined, or the registry is populated at a later point.
|
||||
*
|
||||
* @param registryLoader the registry loader
|
||||
* @param <I> the input type
|
||||
* @param <M> the returned mappings type
|
||||
* @return a new registry with the given RegistryLoader supplier
|
||||
*/
|
||||
public static <I, M> ListRegistry<M> create(RegistryLoader<I, List<M>> registryLoader) {
|
||||
return new ListRegistry<>(null, registryLoader);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new integer mapped registry with the given {@link RegistryLoader} and input.
|
||||
*
|
||||
* @param registryLoader the registry loader
|
||||
* @param <I> the input
|
||||
* @param <M> the type value
|
||||
* @return a new registry with the given RegistryLoader supplier
|
||||
*/
|
||||
public static <I, M> ListRegistry<M> create(I input, Supplier<RegistryLoader<I, List<M>>> registryLoader) {
|
||||
return new ListRegistry<>(input, registryLoader.get());
|
||||
}
|
||||
}
|
@ -25,18 +25,19 @@
|
||||
|
||||
package org.geysermc.geyser.registry.loader;
|
||||
|
||||
import com.fasterxml.jackson.databind.node.ArrayNode;
|
||||
import it.unimi.dsi.fastutil.Pair;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
|
||||
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.cloudburstmc.nbt.NbtList;
|
||||
import org.cloudburstmc.nbt.NbtMap;
|
||||
import org.cloudburstmc.nbt.NbtType;
|
||||
import org.cloudburstmc.nbt.NbtUtils;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.level.block.type.BlockState;
|
||||
import org.geysermc.geyser.level.physics.BoundingBox;
|
||||
import org.geysermc.geyser.registry.BlockRegistries;
|
||||
import org.geysermc.geyser.registry.type.BlockMapping;
|
||||
import org.geysermc.geyser.translator.collision.BlockCollision;
|
||||
import org.geysermc.geyser.translator.collision.CollisionRemapper;
|
||||
import org.geysermc.geyser.translator.collision.OtherCollision;
|
||||
@ -51,41 +52,43 @@ import java.util.regex.Pattern;
|
||||
/**
|
||||
* Loads collision data from the given resource path.
|
||||
*/
|
||||
public class CollisionRegistryLoader extends MultiResourceRegistryLoader<String, Int2ObjectMap<BlockCollision>> {
|
||||
public class CollisionRegistryLoader extends MultiResourceRegistryLoader<String, List<BlockCollision>> {
|
||||
|
||||
@Override
|
||||
public Int2ObjectMap<BlockCollision> load(Pair<String, String> input) {
|
||||
Int2ObjectMap<BlockCollision> collisions = new Int2ObjectOpenHashMap<>();
|
||||
|
||||
public List<BlockCollision> load(Pair<String, String> input) {
|
||||
Map<Class<?>, CollisionInfo> annotationMap = new IdentityHashMap<>();
|
||||
for (Class<?> clazz : FileUtils.getGeneratedClassesForAnnotation(CollisionRemapper.class.getName())) {
|
||||
GeyserImpl.getInstance().getLogger().debug("Found annotated collision translator: " + clazz.getCanonicalName());
|
||||
|
||||
CollisionRemapper collisionRemapper = clazz.getAnnotation(CollisionRemapper.class);
|
||||
annotationMap.put(clazz, new CollisionInfo(collisionRemapper, Pattern.compile(collisionRemapper.regex()), Pattern.compile(collisionRemapper.paramRegex())));
|
||||
annotationMap.put(clazz, new CollisionInfo(collisionRemapper, Pattern.compile(collisionRemapper.regex())));
|
||||
}
|
||||
|
||||
// Load collision mappings file
|
||||
int[] indices;
|
||||
List<BoundingBox[]> collisionList;
|
||||
try (InputStream stream = GeyserImpl.getInstance().getBootstrap().getResourceOrThrow(input.value())) {
|
||||
ArrayNode collisionNode = (ArrayNode) GeyserImpl.JSON_MAPPER.readTree(stream);
|
||||
collisionList = loadBoundingBoxes(collisionNode);
|
||||
NbtMap collisionData = (NbtMap) NbtUtils.createGZIPReader(stream).readTag();
|
||||
indices = collisionData.getIntArray("indices");
|
||||
//SuppressWarnings unchecked
|
||||
collisionList = loadBoundingBoxes(collisionData.getList("collisions", NbtType.LIST));
|
||||
} catch (Exception e) {
|
||||
throw new AssertionError("Unable to load collision data", e);
|
||||
}
|
||||
|
||||
BlockMapping[] blockMappings = BlockRegistries.JAVA_BLOCKS.get();
|
||||
List<BlockState> blockStates = BlockRegistries.BLOCK_STATES.get();
|
||||
List<BlockCollision> collisions = new ObjectArrayList<>(blockStates.size());
|
||||
|
||||
// Map of unique collisions to its instance
|
||||
Map<BlockCollision, BlockCollision> collisionInstances = new Object2ObjectOpenHashMap<>();
|
||||
for (int i = 0; i < blockMappings.length; i++) {
|
||||
BlockMapping blockMapping = blockMappings[i];
|
||||
if (blockMapping == null) {
|
||||
GeyserImpl.getInstance().getLogger().warning("Missing block mapping for Java block " + i);
|
||||
for (int i = 0; i < blockStates.size(); i++) {
|
||||
BlockState state = blockStates.get(i);
|
||||
if (state == null) {
|
||||
GeyserImpl.getInstance().getLogger().warning("Missing block state for Java block " + i);
|
||||
continue;
|
||||
}
|
||||
|
||||
BlockCollision newCollision = instantiateCollision(blockMapping, annotationMap, collisionList);
|
||||
BlockCollision newCollision = instantiateCollision(state, annotationMap, indices[i], collisionList);
|
||||
|
||||
if (newCollision != null) {
|
||||
// If there's an existing instance equal to this one, use that instead
|
||||
@ -97,33 +100,27 @@ public class CollisionRegistryLoader extends MultiResourceRegistryLoader<String,
|
||||
}
|
||||
}
|
||||
|
||||
collisions.put(i, newCollision);
|
||||
collisions.add(newCollision);
|
||||
}
|
||||
return collisions;
|
||||
}
|
||||
|
||||
private @Nullable BlockCollision instantiateCollision(BlockMapping mapping, Map<Class<?>, CollisionInfo> annotationMap, List<BoundingBox[]> collisionList) {
|
||||
String[] blockIdParts = mapping.getJavaIdentifier().split("\\[");
|
||||
String blockName = blockIdParts[0].replace("minecraft:", "");
|
||||
String params = "";
|
||||
if (blockIdParts.length == 2) {
|
||||
params = "[" + blockIdParts[1];
|
||||
}
|
||||
int collisionIndex = mapping.getCollisionIndex();
|
||||
private @Nullable BlockCollision instantiateCollision(BlockState state, Map<Class<?>, CollisionInfo> annotationMap, int collisionIndex, List<BoundingBox[]> collisionList) {
|
||||
String blockName = state.block().javaIdentifier().substring("minecraft:".length());
|
||||
|
||||
for (Map.Entry<Class<?>, CollisionInfo> collisionRemappers : annotationMap.entrySet()) {
|
||||
Class<?> type = collisionRemappers.getKey();
|
||||
CollisionInfo collisionInfo = collisionRemappers.getValue();
|
||||
CollisionRemapper annotation = collisionInfo.collisionRemapper;
|
||||
|
||||
if (collisionInfo.pattern.matcher(blockName).find() && collisionInfo.paramsPattern.matcher(params).find()) {
|
||||
if (collisionInfo.pattern.matcher(blockName).find()) {
|
||||
try {
|
||||
if (annotation.passDefaultBoxes()) {
|
||||
// Create an OtherCollision instance and get the bounding boxes
|
||||
BoundingBox[] defaultBoxes = collisionList.get(collisionIndex);
|
||||
return (BlockCollision) type.getDeclaredConstructor(String.class, BoundingBox[].class).newInstance(params, defaultBoxes);
|
||||
return (BlockCollision) type.getDeclaredConstructor(BlockState.class, BoundingBox[].class).newInstance(state, defaultBoxes);
|
||||
} else {
|
||||
return (BlockCollision) type.getDeclaredConstructor(String.class).newInstance(params);
|
||||
return (BlockCollision) type.getDeclaredConstructor(BlockState.class).newInstance(state);
|
||||
}
|
||||
} catch (IllegalAccessException | InstantiationException | NoSuchMethodException | InvocationTargetException e) {
|
||||
throw new RuntimeException(e);
|
||||
@ -138,25 +135,25 @@ public class CollisionRegistryLoader extends MultiResourceRegistryLoader<String,
|
||||
|
||||
// Unless some of the low IDs are changed, which is unlikely, the second item should always be full collision
|
||||
if (collisionIndex == 1) {
|
||||
return new SolidCollision(params);
|
||||
return new SolidCollision(state);
|
||||
}
|
||||
return new OtherCollision(collisionList.get(collisionIndex));
|
||||
}
|
||||
|
||||
private List<BoundingBox[]> loadBoundingBoxes(ArrayNode collisionNode) {
|
||||
private List<BoundingBox[]> loadBoundingBoxes(List<NbtList> collisionNode) {
|
||||
List<BoundingBox[]> collisions = new ObjectArrayList<>();
|
||||
for (int collisionIndex = 0; collisionIndex < collisionNode.size(); collisionIndex++) {
|
||||
ArrayNode boundingBoxArray = (ArrayNode) collisionNode.get(collisionIndex);
|
||||
@SuppressWarnings("unchecked") NbtList<NbtList<Double>> boundingBoxArray = (NbtList<NbtList<Double>>) collisionNode.get(collisionIndex);
|
||||
|
||||
BoundingBox[] boundingBoxes = new BoundingBox[boundingBoxArray.size()];
|
||||
for (int i = 0; i < boundingBoxArray.size(); i++) {
|
||||
ArrayNode boxProperties = (ArrayNode) boundingBoxArray.get(i);
|
||||
boundingBoxes[i] = new BoundingBox(boxProperties.get(0).asDouble(),
|
||||
boxProperties.get(1).asDouble(),
|
||||
boxProperties.get(2).asDouble(),
|
||||
boxProperties.get(3).asDouble(),
|
||||
boxProperties.get(4).asDouble(),
|
||||
boxProperties.get(5).asDouble());
|
||||
NbtList<Double> boxProperties = boundingBoxArray.get(i);
|
||||
boundingBoxes[i] = new BoundingBox(boxProperties.get(0),
|
||||
boxProperties.get(1),
|
||||
boxProperties.get(2),
|
||||
boxProperties.get(3),
|
||||
boxProperties.get(4),
|
||||
boxProperties.get(5));
|
||||
}
|
||||
|
||||
// Sorting by lowest Y first fixes some bugs
|
||||
@ -173,6 +170,5 @@ public class CollisionRegistryLoader extends MultiResourceRegistryLoader<String,
|
||||
public static class CollisionInfo {
|
||||
private final CollisionRemapper collisionRemapper;
|
||||
private final Pattern pattern;
|
||||
private final Pattern paramsPattern;
|
||||
}
|
||||
}
|
@ -51,6 +51,7 @@ import org.geysermc.geyser.api.block.custom.CustomBlockData;
|
||||
import org.geysermc.geyser.api.block.custom.CustomBlockState;
|
||||
import org.geysermc.geyser.api.block.custom.nonvanilla.JavaBlockState;
|
||||
import org.geysermc.geyser.level.block.BlockStateValues;
|
||||
import org.geysermc.geyser.level.block.type.Block;
|
||||
import org.geysermc.geyser.level.physics.PistonBehavior;
|
||||
import org.geysermc.geyser.registry.BlockRegistries;
|
||||
import org.geysermc.geyser.registry.type.BlockMapping;
|
||||
@ -137,7 +138,7 @@ public final class BlockRegistryPopulator {
|
||||
List<NbtMap> vanillaBlockStates;
|
||||
List<NbtMap> blockStates;
|
||||
try (InputStream stream = GeyserImpl.getInstance().getBootstrap().getResourceOrThrow(String.format("bedrock/block_palette.%s.nbt", palette.key()));
|
||||
NBTInputStream nbtInputStream = new NBTInputStream(new DataInputStream(new GZIPInputStream(stream)), true, true)) {
|
||||
NBTInputStream nbtInputStream = new NBTInputStream(new DataInputStream(new GZIPInputStream(stream)), true, true)) {
|
||||
NbtMap blockPalette = (NbtMap) nbtInputStream.readTag();
|
||||
|
||||
vanillaBlockStates = new ArrayList<>(blockPalette.getList("blocks", NbtType.COMPOUND));
|
||||
@ -259,7 +260,7 @@ public final class BlockRegistryPopulator {
|
||||
bedrockDefinition = customBlockStateDefinitions.get(blockStateOverride);
|
||||
if (bedrockDefinition == null) {
|
||||
throw new RuntimeException("Unable to find " + javaId + " Bedrock runtime ID! Custom block override: \n" +
|
||||
blockStateOverride);
|
||||
blockStateOverride);
|
||||
}
|
||||
}
|
||||
|
||||
@ -555,26 +556,6 @@ public final class BlockRegistryPopulator {
|
||||
}
|
||||
BlockStateValues.JAVA_WATER_ID = waterRuntimeId;
|
||||
|
||||
if (bubbleColumnDragRuntimeId == -1) {
|
||||
throw new AssertionError("Unable to find drag bubble column in palette");
|
||||
}
|
||||
BlockStateValues.JAVA_BUBBLE_COLUMN_DRAG_ID = bubbleColumnDragRuntimeId;
|
||||
|
||||
if (bubbleColumnUpwardRuntimeId == -1) {
|
||||
throw new AssertionError("Unable to find upward bubble column in palette");
|
||||
}
|
||||
BlockStateValues.JAVA_BUBBLE_COLUMN_UPWARD_ID = bubbleColumnUpwardRuntimeId;
|
||||
|
||||
if (soulSandRuntimeId == -1) {
|
||||
throw new AssertionError("Unable to find soul sand in palette");
|
||||
}
|
||||
BlockStateValues.JAVA_SOUL_SAND_ID = soulSandRuntimeId;
|
||||
|
||||
if (iceRuntimeId == -1) {
|
||||
throw new AssertionError("Unable to find ice in palette");
|
||||
}
|
||||
BlockStateValues.JAVA_ICE_ID = iceRuntimeId;
|
||||
|
||||
if (!BlockRegistries.NON_VANILLA_BLOCK_STATE_OVERRIDES.get().isEmpty()) {
|
||||
Set<Integer> usedNonVanillaRuntimeIDs = new HashSet<>();
|
||||
|
||||
@ -589,15 +570,24 @@ public final class BlockRegistryPopulator {
|
||||
int stateRuntimeId = javaBlockState.javaId();
|
||||
String pistonBehavior = javaBlockState.pistonBehavior();
|
||||
BlockMapping blockMapping = BlockMapping.builder()
|
||||
.canBreakWithHand(javaBlockState.canBreakWithHand())
|
||||
.pickItem(javaBlockState.pickItem())
|
||||
.isNonVanilla(true)
|
||||
.javaIdentifier(javaId)
|
||||
.javaBlockId(javaBlockState.stateGroupId())
|
||||
.hardness(javaBlockState.blockHardness())
|
||||
.pistonBehavior(pistonBehavior == null ? PistonBehavior.NORMAL : PistonBehavior.getByName(pistonBehavior))
|
||||
.isBlockEntity(javaBlockState.hasBlockEntity())
|
||||
.build();
|
||||
.canBreakWithHand(javaBlockState.canBreakWithHand())
|
||||
.pickItem(javaBlockState.pickItem())
|
||||
.isNonVanilla(true)
|
||||
.javaIdentifier(javaId)
|
||||
.javaBlockId(javaBlockState.stateGroupId())
|
||||
.hardness(javaBlockState.blockHardness())
|
||||
.pistonBehavior(pistonBehavior == null ? PistonBehavior.NORMAL : PistonBehavior.getByName(pistonBehavior))
|
||||
.isBlockEntity(javaBlockState.hasBlockEntity())
|
||||
.build();
|
||||
|
||||
Block.Builder builder = Block.builder()
|
||||
.destroyTime(javaBlockState.blockHardness());
|
||||
if (!javaBlockState.canBreakWithHand()) {
|
||||
builder.requiresCorrectToolForDrops();
|
||||
}
|
||||
if (javaBlockState.hasBlockEntity()) {
|
||||
builder.setBlockEntity();
|
||||
}
|
||||
|
||||
String cleanJavaIdentifier = BlockUtils.getCleanIdentifier(javaBlockState.identifier());
|
||||
String bedrockIdentifier = customBlockState.block().identifier();
|
||||
@ -616,8 +606,6 @@ public final class BlockRegistryPopulator {
|
||||
}
|
||||
}
|
||||
|
||||
BlockRegistries.CLEAN_JAVA_IDENTIFIERS.set(cleanIdentifiers.toArray(new String[0]));
|
||||
|
||||
BLOCKS_JSON = blocksJson;
|
||||
|
||||
JsonNode blockInteractionsJson;
|
||||
|
@ -28,35 +28,6 @@ package org.geysermc.geyser.session;
|
||||
import com.github.steveice10.mc.auth.data.GameProfile;
|
||||
import com.github.steveice10.mc.auth.exception.request.RequestException;
|
||||
import com.github.steveice10.mc.auth.service.MsaAuthenticationService;
|
||||
import org.geysermc.mcprotocollib.protocol.MinecraftConstants;
|
||||
import org.geysermc.mcprotocollib.protocol.MinecraftProtocol;
|
||||
import org.geysermc.mcprotocollib.protocol.data.ProtocolState;
|
||||
import org.geysermc.mcprotocollib.protocol.data.UnexpectedEncryptionException;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.Pose;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.object.Direction;
|
||||
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.HandPreference;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.PlayerAction;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.setting.ChatVisibility;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.setting.SkinPart;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.statistic.CustomStatistic;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.statistic.Statistic;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.common.serverbound.ServerboundClientInformationPacket;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.handshake.serverbound.ClientIntentionPacket;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.ServerboundChatCommandSignedPacket;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.ServerboundChatPacket;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.player.ServerboundMovePlayerPosPacket;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.player.ServerboundPlayerAbilitiesPacket;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.player.ServerboundPlayerActionPacket;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.player.ServerboundUseItemPacket;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.login.serverbound.ServerboundCustomQueryAnswerPacket;
|
||||
import org.geysermc.mcprotocollib.network.BuiltinFlags;
|
||||
import org.geysermc.mcprotocollib.network.Session;
|
||||
import org.geysermc.mcprotocollib.network.event.session.*;
|
||||
import org.geysermc.mcprotocollib.network.packet.Packet;
|
||||
import org.geysermc.mcprotocollib.network.tcp.TcpClientSession;
|
||||
import org.geysermc.mcprotocollib.network.tcp.TcpSession;
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.EventLoop;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
@ -146,6 +117,38 @@ import org.geysermc.geyser.util.ChunkUtils;
|
||||
import org.geysermc.geyser.util.DimensionUtils;
|
||||
import org.geysermc.geyser.util.EntityUtils;
|
||||
import org.geysermc.geyser.util.LoginEncryptionUtils;
|
||||
import org.geysermc.mcprotocollib.network.BuiltinFlags;
|
||||
import org.geysermc.mcprotocollib.network.Session;
|
||||
import org.geysermc.mcprotocollib.network.event.session.*;
|
||||
import org.geysermc.mcprotocollib.network.packet.Packet;
|
||||
import org.geysermc.mcprotocollib.network.tcp.TcpClientSession;
|
||||
import org.geysermc.mcprotocollib.network.tcp.TcpSession;
|
||||
import org.geysermc.mcprotocollib.protocol.ClientListener;
|
||||
import org.geysermc.mcprotocollib.protocol.MinecraftConstants;
|
||||
import org.geysermc.mcprotocollib.protocol.MinecraftProtocol;
|
||||
import org.geysermc.mcprotocollib.protocol.data.ProtocolState;
|
||||
import org.geysermc.mcprotocollib.protocol.data.UnexpectedEncryptionException;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.Pose;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.object.Direction;
|
||||
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.HandPreference;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.PlayerAction;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.setting.ChatVisibility;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.setting.SkinPart;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.statistic.CustomStatistic;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.statistic.Statistic;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.common.serverbound.ServerboundClientInformationPacket;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.configuration.clientbound.ClientboundFinishConfigurationPacket;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.configuration.serverbound.ServerboundFinishConfigurationPacket;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.handshake.serverbound.ClientIntentionPacket;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.ServerboundChatCommandSignedPacket;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.ServerboundChatPacket;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.player.ServerboundMovePlayerPosPacket;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.player.ServerboundPlayerAbilitiesPacket;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.player.ServerboundPlayerActionPacket;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.player.ServerboundUseItemPacket;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.login.serverbound.ServerboundCustomQueryAnswerPacket;
|
||||
|
||||
import java.net.ConnectException;
|
||||
import java.net.InetSocketAddress;
|
||||
@ -660,9 +663,6 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
|
||||
sentSpawnPacket = true;
|
||||
syncEntityProperties();
|
||||
|
||||
// Set the hardcoded shield ID to the ID we just defined in StartGamePacket
|
||||
// upstream.getSession().getHardcodedBlockingId().set(this.itemMappings.getStoredItems().shield().getBedrockId());
|
||||
|
||||
if (GeyserImpl.getInstance().getConfig().isAddNonBedrockItems()) {
|
||||
ItemComponentPacket componentPacket = new ItemComponentPacket();
|
||||
componentPacket.getItems().addAll(itemMappings.getComponentItemData());
|
||||
@ -889,6 +889,8 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
|
||||
// Start ticking
|
||||
tickThread = eventLoop.scheduleAtFixedRate(this::tick, 50, 50, TimeUnit.MILLISECONDS);
|
||||
|
||||
this.protocol.setUseDefaultListeners(false);
|
||||
|
||||
TcpSession downstream;
|
||||
if (geyser.getBootstrap().getSocketAddress() != null) {
|
||||
// We're going to connect through the JVM and not through TCP
|
||||
@ -918,6 +920,25 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
|
||||
// Let Geyser handle sending the keep alive
|
||||
downstream.setFlag(MinecraftConstants.AUTOMATIC_KEEP_ALIVE_MANAGEMENT, false);
|
||||
}
|
||||
// We'll handle this since we have the registry data on hand
|
||||
downstream.setFlag(MinecraftConstants.SEND_BLANK_KNOWN_PACKS_RESPONSE, false);
|
||||
|
||||
// This isn't a great solution, but... we want to make sure the finish configuration packet cannot be sent
|
||||
// before the KnownPacks packet.
|
||||
this.downstream.getSession().addListener(new ClientListener(ProtocolState.LOGIN, loginEvent.transferring()) {
|
||||
@Override
|
||||
public void packetReceived(Session session, Packet packet) {
|
||||
if (protocol.getState() == ProtocolState.CONFIGURATION) {
|
||||
if (packet instanceof ClientboundFinishConfigurationPacket) {
|
||||
// Prevent
|
||||
GeyserSession.this.ensureInEventLoop(() -> GeyserSession.this.sendDownstreamPacket(new ServerboundFinishConfigurationPacket()));
|
||||
return;
|
||||
}
|
||||
}
|
||||
super.packetReceived(session, packet);
|
||||
}
|
||||
});
|
||||
|
||||
downstream.addListener(new SessionAdapter() {
|
||||
@Override
|
||||
public void packetSending(PacketSendingEvent event) {
|
||||
@ -1564,8 +1585,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
|
||||
startGamePacket.setEnchantmentSeed(0);
|
||||
startGamePacket.setMultiplayerCorrelationId("");
|
||||
|
||||
startGamePacket.setItemDefinitions(this.itemMappings.getItemDefinitions().values().stream().toList()); // TODO
|
||||
// startGamePacket.setBlockPalette(this.blockMappings.getBedrockBlockPalette());
|
||||
startGamePacket.getItemDefinitions().addAll(this.itemMappings.getItemDefinitions().values());
|
||||
|
||||
// Needed for custom block mappings and custom skulls system
|
||||
startGamePacket.getBlockProperties().addAll(this.blockMappings.getBlockProperties());
|
||||
@ -1593,9 +1613,6 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
|
||||
startGamePacket.setRewindHistorySize(0);
|
||||
startGamePacket.setServerAuthoritativeBlockBreaking(false);
|
||||
|
||||
// Entity properties for older versions
|
||||
startGamePacket.getExperiments().add(new ExperimentData("upcoming_creator_features", true));
|
||||
|
||||
upstream.sendPacket(startGamePacket);
|
||||
}
|
||||
|
||||
|
@ -25,6 +25,7 @@
|
||||
|
||||
package org.geysermc.geyser.session.cache;
|
||||
|
||||
import org.geysermc.geyser.level.block.type.Block;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.chunk.DataPalette;
|
||||
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
|
||||
@ -92,11 +93,11 @@ public class ChunkCache {
|
||||
|
||||
DataPalette palette = chunk.sections()[(y - minY) >> 4];
|
||||
if (palette == null) {
|
||||
if (block != BlockStateValues.JAVA_AIR_ID) {
|
||||
if (block != Block.JAVA_AIR_ID) {
|
||||
// A previously empty chunk, which is no longer empty as a block has been added to it
|
||||
palette = DataPalette.createForChunk();
|
||||
// Fixes the chunk assuming that all blocks is the `block` variable we are updating. /shrug
|
||||
palette.getPalette().stateToId(BlockStateValues.JAVA_AIR_ID);
|
||||
palette.getPalette().stateToId(Block.JAVA_AIR_ID);
|
||||
chunk.sections()[(y - minY) >> 4] = palette;
|
||||
} else {
|
||||
// Nothing to update
|
||||
@ -109,17 +110,17 @@ public class ChunkCache {
|
||||
|
||||
public int getBlockAt(int x, int y, int z) {
|
||||
if (!cache) {
|
||||
return BlockStateValues.JAVA_AIR_ID;
|
||||
return Block.JAVA_AIR_ID;
|
||||
}
|
||||
|
||||
GeyserChunk column = this.getChunk(x >> 4, z >> 4);
|
||||
if (column == null) {
|
||||
return BlockStateValues.JAVA_AIR_ID;
|
||||
return Block.JAVA_AIR_ID;
|
||||
}
|
||||
|
||||
if (y < minY || ((y - minY) >> 4) > column.sections().length - 1) {
|
||||
// Y likely goes above or below the height limit of this world
|
||||
return BlockStateValues.JAVA_AIR_ID;
|
||||
return Block.JAVA_AIR_ID;
|
||||
}
|
||||
|
||||
DataPalette chunk = column.sections()[(y - minY) >> 4];
|
||||
@ -127,7 +128,7 @@ public class ChunkCache {
|
||||
return chunk.get(x & 0xF, y & 0xF, z & 0xF);
|
||||
}
|
||||
|
||||
return BlockStateValues.JAVA_AIR_ID;
|
||||
return Block.JAVA_AIR_ID;
|
||||
}
|
||||
|
||||
public void removeChunk(int chunkX, int chunkZ) {
|
||||
|
@ -30,6 +30,8 @@ import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.cloudburstmc.nbt.NbtMap;
|
||||
import org.cloudburstmc.nbt.NbtType;
|
||||
import org.cloudburstmc.protocol.bedrock.data.TrimMaterial;
|
||||
import org.cloudburstmc.protocol.bedrock.data.TrimPattern;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
@ -42,6 +44,7 @@ import org.geysermc.geyser.session.cache.registry.JavaRegistry;
|
||||
import org.geysermc.geyser.session.cache.registry.SimpleJavaRegistry;
|
||||
import org.geysermc.geyser.text.TextDecoration;
|
||||
import org.geysermc.geyser.translator.level.BiomeTranslator;
|
||||
import org.geysermc.mcprotocollib.protocol.MinecraftProtocol;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.RegistryEntry;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.configuration.clientbound.ClientboundRegistryDataPacket;
|
||||
|
||||
@ -63,6 +66,7 @@ import java.util.function.ToIntFunction;
|
||||
@Accessors(fluent = true)
|
||||
@Getter
|
||||
public final class RegistryCache {
|
||||
private static final Map<String, Map<String, NbtMap>> DEFAULTS;
|
||||
private static final Map<String, BiConsumer<RegistryCache, List<RegistryEntry>>> REGISTRIES = new HashMap<>();
|
||||
|
||||
static {
|
||||
@ -73,6 +77,24 @@ public final class RegistryCache {
|
||||
register("worldgen/biome", (cache, array) -> cache.biomeTranslations = array, BiomeTranslator::loadServerBiome);
|
||||
register("banner_pattern", cache -> cache.bannerPatterns, ($, entry) -> BannerPattern.getByJavaIdentifier(entry.getId()));
|
||||
register("wolf_variant", cache -> cache.wolfVariants, ($, entry) -> WolfEntity.WolfVariant.getByJavaIdentifier(entry.getId()));
|
||||
|
||||
// Load from MCProtocolLib's classloader
|
||||
NbtMap tag = MinecraftProtocol.loadNetworkCodec();
|
||||
Map<String, Map<String, NbtMap>> defaults = new HashMap<>();
|
||||
// Don't create a keySet - no need to create the cached object in HashMap if we don't use it again
|
||||
REGISTRIES.forEach((key, $) -> {
|
||||
List<NbtMap> rawValues = tag.getCompound(key)
|
||||
.getList("value", NbtType.COMPOUND);
|
||||
Map<String, NbtMap> values = new HashMap<>();
|
||||
for (NbtMap value : rawValues) {
|
||||
String name = value.getString("name");
|
||||
values.put(name, value.getCompound("element"));
|
||||
}
|
||||
// Can make these maps immutable and as efficient as possible after initialization
|
||||
defaults.put(key, Map.copyOf(values));
|
||||
});
|
||||
|
||||
DEFAULTS = Map.copyOf(defaults);
|
||||
}
|
||||
|
||||
@Getter(AccessLevel.NONE)
|
||||
@ -116,13 +138,22 @@ public final class RegistryCache {
|
||||
* @param <T> the class that represents these entries.
|
||||
*/
|
||||
private static <T> void register(String registry, Function<RegistryCache, JavaRegistry<T>> localCacheFunction, BiFunction<GeyserSession, RegistryEntry, T> reader) {
|
||||
REGISTRIES.put("minecraft:" + registry, (registryCache, entries) -> {
|
||||
String key = "minecraft:" + registry;
|
||||
REGISTRIES.put(key, (registryCache, entries) -> {
|
||||
Map<String, NbtMap> localRegistry = null;
|
||||
JavaRegistry<T> localCache = localCacheFunction.apply(registryCache);
|
||||
// Clear each local cache every time a new registry entry is given to us
|
||||
// (e.g. proxy server switches)
|
||||
List<T> builder = new ArrayList<>(entries.size());
|
||||
for (int i = 0; i < entries.size(); i++) {
|
||||
RegistryEntry entry = entries.get(i);
|
||||
// If the data is null, that's the server telling us we need to use our default values.
|
||||
if (entry.getData() == null) {
|
||||
if (localRegistry == null) { // Lazy initialize
|
||||
localRegistry = DEFAULTS.get(key);
|
||||
}
|
||||
entry = new RegistryEntry(entry.getId(), localRegistry.get(entry.getId()));
|
||||
}
|
||||
// This is what Geyser wants to keep as a value for this registry.
|
||||
T cacheEntry = reader.apply(registryCache.session, entry);
|
||||
builder.add(i, cacheEntry);
|
||||
@ -156,4 +187,8 @@ public final class RegistryCache {
|
||||
localCacheFunction.accept(registryCache, array);
|
||||
});
|
||||
}
|
||||
|
||||
public static void init() {
|
||||
// no-op
|
||||
}
|
||||
}
|
||||
|
@ -25,15 +25,16 @@
|
||||
|
||||
package org.geysermc.geyser.session.cache;
|
||||
|
||||
import org.geysermc.mcprotocollib.protocol.packet.common.clientbound.ClientboundUpdateTagsPacket;
|
||||
import it.unimi.dsi.fastutil.ints.IntList;
|
||||
import org.geysermc.geyser.GeyserLogger;
|
||||
import org.geysermc.geyser.inventory.GeyserItemStack;
|
||||
import org.geysermc.geyser.item.type.Item;
|
||||
import org.geysermc.geyser.level.block.type.Block;
|
||||
import org.geysermc.geyser.registry.type.BlockMapping;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.session.cache.tags.BlockTag;
|
||||
import org.geysermc.geyser.session.cache.tags.ItemTag;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.common.clientbound.ClientboundUpdateTagsPacket;
|
||||
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
import java.util.EnumMap;
|
||||
@ -95,6 +96,17 @@ public final class TagCache {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if the block tag is present and contains this block mapping's Java ID.
|
||||
*/
|
||||
public boolean is(BlockTag tag, Block block) {
|
||||
IntList values = this.blocks.get(tag);
|
||||
if (values != null) {
|
||||
return values.contains(block.javaId());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if the block tag is present and contains this block mapping's Java ID.
|
||||
*/
|
||||
|
@ -37,12 +37,6 @@ public @interface CollisionRemapper {
|
||||
*/
|
||||
String regex();
|
||||
|
||||
/**
|
||||
* Regex of block state parameters to apply this collision to
|
||||
* Defaults to matching any value
|
||||
*/
|
||||
String paramRegex() default ".*";
|
||||
|
||||
/**
|
||||
* Signals if a new instance needs to created for every block state
|
||||
*/
|
||||
|
@ -26,13 +26,14 @@
|
||||
package org.geysermc.geyser.translator.collision;
|
||||
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.geysermc.geyser.level.block.type.BlockState;
|
||||
import org.geysermc.geyser.level.physics.BoundingBox;
|
||||
import org.geysermc.geyser.level.physics.CollisionManager;
|
||||
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@CollisionRemapper(regex = "^dirt_path$", passDefaultBoxes = true)
|
||||
public class DirtPathCollision extends BlockCollision {
|
||||
public DirtPathCollision(String params, BoundingBox[] defaultBoxes) {
|
||||
public DirtPathCollision(BlockState state, BoundingBox[] defaultBoxes) {
|
||||
super(defaultBoxes);
|
||||
}
|
||||
|
||||
|
@ -26,6 +26,8 @@
|
||||
package org.geysermc.geyser.translator.collision;
|
||||
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.geysermc.geyser.level.block.property.Properties;
|
||||
import org.geysermc.geyser.level.block.type.BlockState;
|
||||
import org.geysermc.geyser.level.physics.BoundingBox;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
|
||||
@ -40,20 +42,18 @@ public class DoorCollision extends BlockCollision {
|
||||
*/
|
||||
private int facing;
|
||||
|
||||
public DoorCollision(String params, BoundingBox[] defaultBoxes) {
|
||||
public DoorCollision(BlockState state, BoundingBox[] defaultBoxes) {
|
||||
super(defaultBoxes);
|
||||
if (params.contains("facing=north")) {
|
||||
facing = 1;
|
||||
} else if (params.contains("facing=east")) {
|
||||
facing = 2;
|
||||
} else if (params.contains("facing=south")) {
|
||||
facing = 3;
|
||||
} else if (params.contains("facing=west")) {
|
||||
facing = 4;
|
||||
}
|
||||
facing = switch (state.getValue(Properties.HORIZONTAL_FACING)) {
|
||||
case NORTH -> 1;
|
||||
case EAST -> 2;
|
||||
case SOUTH -> 3;
|
||||
case WEST -> 4;
|
||||
default -> throw new IllegalStateException();
|
||||
};
|
||||
|
||||
// If the door is open it changes direction
|
||||
if (params.contains("open=true")) {
|
||||
if (state.getValue(Properties.OPEN)) {
|
||||
facing = facing % 2 + 1;
|
||||
}
|
||||
}
|
||||
|
@ -26,6 +26,8 @@
|
||||
package org.geysermc.geyser.translator.collision;
|
||||
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.geysermc.geyser.level.block.property.Properties;
|
||||
import org.geysermc.geyser.level.block.type.BlockState;
|
||||
import org.geysermc.geyser.level.physics.BoundingBox;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
|
||||
@ -44,24 +46,23 @@ public class GlassPaneAndIronBarsCollision extends BlockCollision {
|
||||
*/
|
||||
private int facing;
|
||||
|
||||
public GlassPaneAndIronBarsCollision(String params, BoundingBox[] defaultBoxes) {
|
||||
public GlassPaneAndIronBarsCollision(BlockState state, BoundingBox[] defaultBoxes) {
|
||||
super(defaultBoxes);
|
||||
//east=true,north=true,south=true,west=true
|
||||
if (params.contains("north=true") && params.contains("east=true")) {
|
||||
if (state.getValue(Properties.NORTH) && state.getValue(Properties.EAST)) {
|
||||
facing = 5;
|
||||
} else if (params.contains("east=true") && params.contains("south=true")) {
|
||||
} else if (state.getValue(Properties.EAST) && state.getValue(Properties.SOUTH)) {
|
||||
facing = 6;
|
||||
} else if (params.contains("south=true") && params.contains("west=true")) {
|
||||
} else if (state.getValue(Properties.SOUTH) && state.getValue(Properties.WEST)) {
|
||||
facing = 7;
|
||||
} else if (params.contains("west=true") && params.contains("north=true")) {
|
||||
} else if (state.getValue(Properties.WEST) && state.getValue(Properties.NORTH)) {
|
||||
facing = 8;
|
||||
} else if (params.contains("north=true")) {
|
||||
} else if (state.getValue(Properties.NORTH)) {
|
||||
facing = 1;
|
||||
} else if (params.contains("east=true")) {
|
||||
} else if (state.getValue(Properties.EAST)) {
|
||||
facing = 2;
|
||||
} else if (params.contains("south=true")) {
|
||||
} else if (state.getValue(Properties.SOUTH)) {
|
||||
facing = 3;
|
||||
} else if (params.contains("west=true")) {
|
||||
} else if (state.getValue(Properties.WEST)) {
|
||||
facing = 4;
|
||||
}
|
||||
}
|
||||
|
@ -26,6 +26,7 @@
|
||||
package org.geysermc.geyser.translator.collision;
|
||||
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.geysermc.geyser.level.block.type.BlockState;
|
||||
import org.geysermc.geyser.level.physics.BoundingBox;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
|
||||
@ -35,7 +36,7 @@ import org.geysermc.geyser.session.GeyserSession;
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@CollisionRemapper(regex = "^scaffolding$", usesParams = true, passDefaultBoxes = true)
|
||||
public class ScaffoldingCollision extends BlockCollision {
|
||||
public ScaffoldingCollision(String params, BoundingBox[] defaultBoxes) {
|
||||
public ScaffoldingCollision(BlockState state, BoundingBox[] defaultBoxes) {
|
||||
super(defaultBoxes);
|
||||
}
|
||||
|
||||
|
@ -30,7 +30,7 @@ import org.geysermc.geyser.level.physics.BoundingBox;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@CollisionRemapper(regex = "^snow$", passDefaultBoxes = true, usesParams = true)
|
||||
//@CollisionRemapper(regex = "^snow$", passDefaultBoxes = true, usesParams = true) TODO remove if no bugs are found. Seems fine with Bedrock 1.20.80 and 1.20.5
|
||||
public class SnowCollision extends BlockCollision {
|
||||
private final int layers;
|
||||
|
||||
|
@ -26,12 +26,13 @@
|
||||
package org.geysermc.geyser.translator.collision;
|
||||
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.geysermc.geyser.level.block.type.BlockState;
|
||||
import org.geysermc.geyser.level.physics.BoundingBox;
|
||||
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@CollisionRemapper(regex = "shulker_box$") // These have no collision in the mappings as it depends on the NBT data
|
||||
public class SolidCollision extends BlockCollision {
|
||||
public SolidCollision(String params) {
|
||||
public SolidCollision(BlockState state) {
|
||||
super(new BoundingBox[] {
|
||||
new BoundingBox(0.5, 0.5, 0.5, 1, 1, 1)
|
||||
});
|
||||
|
@ -26,42 +26,27 @@
|
||||
package org.geysermc.geyser.translator.collision;
|
||||
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.geysermc.geyser.level.block.property.Properties;
|
||||
import org.geysermc.geyser.level.block.type.BlockState;
|
||||
import org.geysermc.geyser.level.physics.BoundingBox;
|
||||
import org.geysermc.geyser.level.physics.CollisionManager;
|
||||
import org.geysermc.geyser.level.physics.Direction;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@CollisionRemapper(regex = "_trapdoor$", usesParams = true, passDefaultBoxes = true)
|
||||
public class TrapdoorCollision extends BlockCollision {
|
||||
/**
|
||||
* 1 = north
|
||||
* 2 = east
|
||||
* 3 = south
|
||||
* 4 = west
|
||||
* 5 = up
|
||||
* 6 = down
|
||||
*/
|
||||
private int facing;
|
||||
private final Direction facing;
|
||||
|
||||
public TrapdoorCollision(String params, BoundingBox[] defaultBoxes) {
|
||||
public TrapdoorCollision(BlockState state, BoundingBox[] defaultBoxes) {
|
||||
super(defaultBoxes);
|
||||
if (params.contains("open=true")) {
|
||||
if (params.contains("facing=north")) {
|
||||
facing = 1;
|
||||
} else if (params.contains("facing=east")) {
|
||||
facing = 2;
|
||||
} else if (params.contains("facing=south")) {
|
||||
facing = 3;
|
||||
} else if (params.contains("facing=west")) {
|
||||
facing = 4;
|
||||
}
|
||||
if (state.getValue(Properties.OPEN)) {
|
||||
facing = state.getValue(Properties.HORIZONTAL_FACING);
|
||||
} else {
|
||||
if (params.contains("half=bottom")) {
|
||||
// Up
|
||||
facing = 5;
|
||||
if (state.getValue(Properties.HALF).equals("bottom")) {
|
||||
facing = Direction.UP;
|
||||
} else {
|
||||
// Down
|
||||
facing = 6;
|
||||
facing = Direction.DOWN;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -72,22 +57,22 @@ public class TrapdoorCollision extends BlockCollision {
|
||||
// Check for door bug (doors are 0.1875 blocks thick on Java but 0.1825 blocks thick on Bedrock)
|
||||
if (this.checkIntersection(x, y, z, playerCollision)) {
|
||||
switch (facing) {
|
||||
case 1: // North
|
||||
case NORTH:
|
||||
playerCollision.setMiddleZ(z + 0.5125);
|
||||
break;
|
||||
case 2: // East
|
||||
case EAST:
|
||||
playerCollision.setMiddleX(x + 0.5125);
|
||||
break;
|
||||
case 3: // South
|
||||
case SOUTH:
|
||||
playerCollision.setMiddleZ(z + 0.4875);
|
||||
break;
|
||||
case 4: // West
|
||||
case WEST:
|
||||
playerCollision.setMiddleX(x + 0.4875);
|
||||
break;
|
||||
case 5:
|
||||
case UP:
|
||||
// Up-facing trapdoors are handled by the step-up check
|
||||
break;
|
||||
case 6: // Down
|
||||
case DOWN:
|
||||
// (top y of trap door) - (trap door thickness) = top y of player
|
||||
playerCollision.setMiddleY(y + 1 - (3.0 / 16.0) - playerCollision.getSizeY() / 2.0 - CollisionManager.COLLISION_TOLERANCE);
|
||||
break;
|
||||
|
@ -35,6 +35,7 @@ import org.geysermc.geyser.inventory.BedrockContainerSlot;
|
||||
import org.geysermc.geyser.inventory.Inventory;
|
||||
import org.geysermc.geyser.inventory.holder.BlockInventoryHolder;
|
||||
import org.geysermc.geyser.inventory.updater.ContainerInventoryUpdater;
|
||||
import org.geysermc.geyser.level.block.type.BlockState;
|
||||
import org.geysermc.geyser.registry.Registries;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.translator.level.block.entity.BlockEntityTranslator;
|
||||
@ -58,7 +59,7 @@ public class ShulkerInventoryTranslator extends AbstractBlockInventoryTranslator
|
||||
.putInt("z", position.getZ())
|
||||
.putString("CustomName", inventory.getTitle());
|
||||
// Don't reset facing property
|
||||
shulkerBoxTranslator.translateTag(session, tag, null, javaBlockState);
|
||||
shulkerBoxTranslator.translateTag(session, tag, null, BlockState.of(javaBlockState));
|
||||
|
||||
BlockEntityDataPacket dataPacket = new BlockEntityDataPacket();
|
||||
dataPacket.setData(tag.build());
|
||||
|
@ -36,8 +36,7 @@ import org.cloudburstmc.protocol.bedrock.packet.ContainerOpenPacket;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.UpdateBlockPacket;
|
||||
import org.geysermc.geyser.inventory.Container;
|
||||
import org.geysermc.geyser.inventory.Inventory;
|
||||
import org.geysermc.geyser.level.block.BlockStateValues;
|
||||
import org.geysermc.geyser.level.block.DoubleChestValue;
|
||||
import org.geysermc.geyser.level.block.type.BlockState;
|
||||
import org.geysermc.geyser.registry.BlockRegistries;
|
||||
import org.geysermc.geyser.registry.type.BlockMapping;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
@ -72,8 +71,8 @@ public class DoubleChestInventoryTranslator extends ChestInventoryTranslator {
|
||||
.putString("CustomName", inventory.getTitle())
|
||||
.putString("id", "Chest");
|
||||
|
||||
DoubleChestValue chestValue = BlockStateValues.getDoubleChestValues().get(javaBlockId);
|
||||
DoubleChestBlockEntityTranslator.translateChestValue(tag, chestValue,
|
||||
BlockState blockState = BlockState.of(javaBlockId);
|
||||
DoubleChestBlockEntityTranslator.translateChestValue(tag, blockState,
|
||||
session.getLastInteractionBlockPosition().getX(), session.getLastInteractionBlockPosition().getZ());
|
||||
|
||||
BlockEntityDataPacket dataPacket = new BlockEntityDataPacket();
|
||||
|
@ -30,7 +30,8 @@ import org.cloudburstmc.nbt.NbtMap;
|
||||
import org.cloudburstmc.nbt.NbtMapBuilder;
|
||||
import org.cloudburstmc.nbt.NbtType;
|
||||
import org.geysermc.geyser.item.type.BannerItem;
|
||||
import org.geysermc.geyser.level.block.BlockStateValues;
|
||||
import org.geysermc.geyser.level.block.type.BannerBlock;
|
||||
import org.geysermc.geyser.level.block.type.BlockState;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType;
|
||||
|
||||
@ -39,10 +40,9 @@ import java.util.List;
|
||||
@BlockEntity(type = BlockEntityType.BANNER)
|
||||
public class BannerBlockEntityTranslator extends BlockEntityTranslator implements RequiresBlockState {
|
||||
@Override
|
||||
public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, @Nullable NbtMap javaNbt, int blockState) {
|
||||
int bannerColor = BlockStateValues.getBannerColor(blockState);
|
||||
if (bannerColor != -1) {
|
||||
bedrockNbt.putInt("Base", 15 - bannerColor);
|
||||
public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, @Nullable NbtMap javaNbt, BlockState blockState) {
|
||||
if (blockState.block() instanceof BannerBlock banner) {
|
||||
bedrockNbt.putInt("Base", 15 - banner.dyeColor());
|
||||
}
|
||||
|
||||
if (javaNbt == null) {
|
||||
|
@ -27,13 +27,14 @@ package org.geysermc.geyser.translator.level.block.entity;
|
||||
|
||||
import org.cloudburstmc.nbt.NbtMap;
|
||||
import org.cloudburstmc.nbt.NbtMapBuilder;
|
||||
import org.geysermc.geyser.level.block.type.BlockState;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType;
|
||||
|
||||
@BlockEntity(type = BlockEntityType.BEACON)
|
||||
public class BeaconBlockEntityTranslator extends BlockEntityTranslator {
|
||||
@Override
|
||||
public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, int blockState) {
|
||||
public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, BlockState blockState) {
|
||||
int primary = javaNbt.getInt("primary");
|
||||
// The effects here generally map one-to-one Java <-> Bedrock. Only the newer ones get more complicated
|
||||
bedrockNbt.putInt("primary", primary == -1 ? 0 : primary);
|
||||
|
@ -27,19 +27,15 @@ package org.geysermc.geyser.translator.level.block.entity;
|
||||
|
||||
import org.cloudburstmc.nbt.NbtMap;
|
||||
import org.cloudburstmc.nbt.NbtMapBuilder;
|
||||
import org.geysermc.geyser.level.block.BlockStateValues;
|
||||
import org.geysermc.geyser.level.block.type.BedBlock;
|
||||
import org.geysermc.geyser.level.block.type.BlockState;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType;
|
||||
|
||||
@BlockEntity(type = BlockEntityType.BED)
|
||||
public class BedBlockEntityTranslator extends BlockEntityTranslator implements RequiresBlockState {
|
||||
@Override
|
||||
public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, int blockState) {
|
||||
byte bedcolor = BlockStateValues.getBedColor(blockState);
|
||||
// Just in case...
|
||||
if (bedcolor == -1) {
|
||||
bedcolor = 0;
|
||||
}
|
||||
bedrockNbt.putByte("color", bedcolor);
|
||||
public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, BlockState blockState) {
|
||||
bedrockNbt.putByte("color", (byte) (blockState.block() instanceof BedBlock bed ? bed.dyeColor() : 0));
|
||||
}
|
||||
}
|
||||
|
@ -31,6 +31,7 @@ import org.cloudburstmc.nbt.NbtList;
|
||||
import org.cloudburstmc.nbt.NbtMap;
|
||||
import org.cloudburstmc.nbt.NbtType;
|
||||
import org.geysermc.geyser.level.block.BlockStateValues;
|
||||
import org.geysermc.geyser.level.block.type.BlockState;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
|
||||
/**
|
||||
@ -50,7 +51,7 @@ public interface BedrockOnlyBlockEntity extends RequiresBlockState {
|
||||
* @param blockState The Java block state.
|
||||
* @param position The Bedrock block position.
|
||||
*/
|
||||
void updateBlock(GeyserSession session, int blockState, Vector3i position);
|
||||
void updateBlock(GeyserSession session, BlockState blockState, Vector3i position);
|
||||
|
||||
/**
|
||||
* Get the tag of the Bedrock-only block entity
|
||||
|
@ -28,6 +28,7 @@ package org.geysermc.geyser.translator.level.block.entity;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.cloudburstmc.nbt.NbtMap;
|
||||
import org.cloudburstmc.nbt.NbtMapBuilder;
|
||||
import org.geysermc.geyser.level.block.type.BlockState;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.util.BlockEntityUtils;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType;
|
||||
@ -39,9 +40,9 @@ public abstract class BlockEntityTranslator {
|
||||
protected BlockEntityTranslator() {
|
||||
}
|
||||
|
||||
public abstract void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, int blockState);
|
||||
public abstract void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, BlockState blockState);
|
||||
|
||||
public NbtMap getBlockEntityTag(GeyserSession session, BlockEntityType type, int x, int y, int z, @Nullable NbtMap javaNbt, int blockState) {
|
||||
public NbtMap getBlockEntityTag(GeyserSession session, BlockEntityType type, int x, int y, int z, @Nullable NbtMap javaNbt, BlockState blockState) {
|
||||
NbtMapBuilder tagBuilder = getConstantBedrockTag(type, x, y, z);
|
||||
if (javaNbt != null || this instanceof RequiresBlockState) {
|
||||
// Always process tags if the block state is part of the tag.
|
||||
|
@ -29,7 +29,8 @@ import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.cloudburstmc.nbt.NbtMap;
|
||||
import org.cloudburstmc.nbt.NbtMapBuilder;
|
||||
import org.geysermc.geyser.item.Items;
|
||||
import org.geysermc.geyser.level.block.BlockStateValues;
|
||||
import org.geysermc.geyser.level.block.property.Properties;
|
||||
import org.geysermc.geyser.level.block.type.BlockState;
|
||||
import org.geysermc.geyser.registry.type.ItemMapping;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType;
|
||||
@ -38,7 +39,7 @@ import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType
|
||||
public class BrushableBlockEntityTranslator extends BlockEntityTranslator implements RequiresBlockState {
|
||||
|
||||
@Override
|
||||
public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, @Nullable NbtMap javaNbt, int blockState) {
|
||||
public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, @Nullable NbtMap javaNbt, BlockState blockState) {
|
||||
if (javaNbt == null) {
|
||||
return;
|
||||
}
|
||||
@ -70,6 +71,6 @@ public class BrushableBlockEntityTranslator extends BlockEntityTranslator implem
|
||||
// controls which side the item protrudes from
|
||||
bedrockNbt.putByte("brush_direction", hitDirection);
|
||||
// controls how much the item protrudes
|
||||
bedrockNbt.putInt("brush_count", BlockStateValues.getBrushProgress(blockState));
|
||||
bedrockNbt.putInt("brush_count", blockState.getValue(Properties.DUSTED));
|
||||
}
|
||||
}
|
||||
|
@ -28,6 +28,7 @@ package org.geysermc.geyser.translator.level.block.entity;
|
||||
import org.cloudburstmc.nbt.NbtMap;
|
||||
import org.cloudburstmc.nbt.NbtMapBuilder;
|
||||
import org.cloudburstmc.nbt.NbtType;
|
||||
import org.geysermc.geyser.level.block.type.BlockState;
|
||||
import org.geysermc.geyser.registry.type.ItemMapping;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.translator.item.BedrockItemBuilder;
|
||||
@ -38,7 +39,7 @@ import java.util.List;
|
||||
@BlockEntity(type = BlockEntityType.CAMPFIRE)
|
||||
public class CampfireBlockEntityTranslator extends BlockEntityTranslator {
|
||||
@Override
|
||||
public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, int blockState) {
|
||||
public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, BlockState blockState) {
|
||||
List<NbtMap> items = javaNbt.getList("Items", NbtType.COMPOUND);
|
||||
if (items != null) {
|
||||
int i = 1;
|
||||
|
@ -27,7 +27,8 @@ package org.geysermc.geyser.translator.level.block.entity;
|
||||
|
||||
import org.cloudburstmc.nbt.NbtMap;
|
||||
import org.cloudburstmc.nbt.NbtMapBuilder;
|
||||
import org.geysermc.geyser.level.block.BlockStateValues;
|
||||
import org.geysermc.geyser.level.block.property.Properties;
|
||||
import org.geysermc.geyser.level.block.type.BlockState;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.translator.text.MessageTranslator;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType;
|
||||
@ -35,12 +36,12 @@ import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType
|
||||
@BlockEntity(type = BlockEntityType.COMMAND_BLOCK)
|
||||
public class CommandBlockBlockEntityTranslator extends BlockEntityTranslator implements RequiresBlockState {
|
||||
@Override
|
||||
public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, int blockState) {
|
||||
public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, BlockState blockState) {
|
||||
if (javaNbt == null || javaNbt.size() < 5) {
|
||||
return; // These values aren't here
|
||||
}
|
||||
// Java infers from the block state, but Bedrock needs it in the tag
|
||||
bedrockNbt.putByte("conditionalMode", BlockStateValues.getCommandBlockValues().getOrDefault(blockState, (byte) 0));
|
||||
bedrockNbt.putBoolean("conditionalMode", blockState.getValue(Properties.CONDITIONAL));
|
||||
// Java and Bedrock values
|
||||
bedrockNbt.putByte("conditionMet", javaNbt.getByte("conditionMet"));
|
||||
bedrockNbt.putByte("auto", javaNbt.getByte("auto"));
|
||||
|
@ -28,6 +28,7 @@ package org.geysermc.geyser.translator.level.block.entity;
|
||||
import org.cloudburstmc.nbt.NbtMap;
|
||||
import org.cloudburstmc.nbt.NbtMapBuilder;
|
||||
import org.cloudburstmc.nbt.NbtType;
|
||||
import org.geysermc.geyser.level.block.type.BlockState;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType;
|
||||
|
||||
@ -35,7 +36,7 @@ import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType
|
||||
public class DecoratedPotBlockEntityTranslator extends BlockEntityTranslator {
|
||||
|
||||
@Override
|
||||
public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, int blockState) {
|
||||
public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, BlockState blockState) {
|
||||
if (javaNbt == null) {
|
||||
return;
|
||||
}
|
||||
|
@ -29,7 +29,9 @@ import org.cloudburstmc.math.vector.Vector3i;
|
||||
import org.cloudburstmc.nbt.NbtMap;
|
||||
import org.cloudburstmc.nbt.NbtMapBuilder;
|
||||
import org.geysermc.geyser.level.block.BlockStateValues;
|
||||
import org.geysermc.geyser.level.block.DoubleChestValue;
|
||||
import org.geysermc.geyser.level.block.property.Properties;
|
||||
import org.geysermc.geyser.level.block.type.BlockState;
|
||||
import org.geysermc.geyser.level.physics.Direction;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.util.BlockEntityUtils;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType;
|
||||
@ -45,52 +47,40 @@ public class DoubleChestBlockEntityTranslator extends BlockEntityTranslator impl
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateBlock(GeyserSession session, int blockState, Vector3i position) {
|
||||
public void updateBlock(GeyserSession session, BlockState blockState, Vector3i position) {
|
||||
NbtMapBuilder tagBuilder = getConstantBedrockTag(BlockEntityUtils.getBedrockBlockEntityId(BlockEntityType.CHEST), position.getX(), position.getY(), position.getZ());
|
||||
translateTag(session, tagBuilder, null, blockState);
|
||||
BlockEntityUtils.updateBlockEntity(session, tagBuilder.build(), position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, int blockState) {
|
||||
DoubleChestValue chestValues = BlockStateValues.getDoubleChestValues().get(blockState);
|
||||
if (chestValues != null) {
|
||||
int x = (int) bedrockNbt.get("x");
|
||||
int z = (int) bedrockNbt.get("z");
|
||||
translateChestValue(bedrockNbt, chestValues, x, z);
|
||||
}
|
||||
public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, BlockState blockState) {
|
||||
int x = (int) bedrockNbt.get("x");
|
||||
int z = (int) bedrockNbt.get("z");
|
||||
translateChestValue(bedrockNbt, blockState, x, z);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add Bedrock block entity tags to a NbtMap based on Java properties
|
||||
*
|
||||
* @param builder the NbtMapBuilder to apply properties to
|
||||
* @param chestValues the position properties of this double chest
|
||||
* @param state the BlockState of this double chest
|
||||
* @param x the x position of this chest pair
|
||||
* @param z the z position of this chest pair
|
||||
*/
|
||||
public static void translateChestValue(NbtMapBuilder builder, DoubleChestValue chestValues, int x, int z) {
|
||||
public static void translateChestValue(NbtMapBuilder builder, BlockState state, int x, int z) {
|
||||
// Calculate the position of the other chest based on the Java block state
|
||||
if (chestValues.isFacingEast()) {
|
||||
if (chestValues.isDirectionPositive()) {
|
||||
// East
|
||||
z = z + (chestValues.isLeft() ? 1 : -1);
|
||||
} else {
|
||||
// West
|
||||
z = z + (chestValues.isLeft() ? -1 : 1);
|
||||
}
|
||||
} else {
|
||||
if (chestValues.isDirectionPositive()) {
|
||||
// South
|
||||
x = x + (chestValues.isLeft() ? -1 : 1);
|
||||
} else {
|
||||
// North
|
||||
x = x + (chestValues.isLeft() ? 1 : -1);
|
||||
}
|
||||
Direction facing = state.getValue(Properties.HORIZONTAL_FACING);
|
||||
boolean isLeft = state.getValue(Properties.CHEST_TYPE).equals("left"); //TODO enum
|
||||
switch (facing) {
|
||||
case EAST -> z = z + (isLeft ? 1 : -1);
|
||||
case WEST -> z = z + (isLeft ? -1 : 1);
|
||||
case SOUTH -> x = x + (isLeft ? -1 : 1);
|
||||
case NORTH -> x = x + (isLeft ? 1 : -1);
|
||||
}
|
||||
builder.putInt("pairx", x);
|
||||
builder.putInt("pairz", z);
|
||||
if (!chestValues.isLeft()) {
|
||||
if (!isLeft) {
|
||||
builder.putInt("pairlead", (byte) 1);
|
||||
}
|
||||
}
|
||||
|
@ -27,10 +27,11 @@ package org.geysermc.geyser.translator.level.block.entity;
|
||||
|
||||
import org.cloudburstmc.nbt.NbtMap;
|
||||
import org.cloudburstmc.nbt.NbtMapBuilder;
|
||||
import org.geysermc.geyser.level.block.type.BlockState;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
|
||||
public class EmptyBlockEntityTranslator extends BlockEntityTranslator {
|
||||
@Override
|
||||
public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, int blockState) {
|
||||
public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, BlockState blockState) {
|
||||
}
|
||||
}
|
||||
|
@ -31,13 +31,14 @@ import org.cloudburstmc.nbt.NbtList;
|
||||
import org.cloudburstmc.nbt.NbtMap;
|
||||
import org.cloudburstmc.nbt.NbtMapBuilder;
|
||||
import org.cloudburstmc.nbt.NbtType;
|
||||
import org.geysermc.geyser.level.block.type.BlockState;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType;
|
||||
|
||||
@BlockEntity(type = BlockEntityType.END_GATEWAY)
|
||||
public class EndGatewayBlockEntityTranslator extends BlockEntityTranslator {
|
||||
@Override
|
||||
public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, int blockState) {
|
||||
public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, BlockState blockState) {
|
||||
bedrockNbt.putInt("Age", (int) javaNbt.getLong("Age"));
|
||||
// Java sometimes does not provide this tag, but Bedrock crashes if it doesn't exist
|
||||
// Linked coordinates
|
||||
|
@ -30,6 +30,7 @@ import org.cloudburstmc.nbt.NbtMap;
|
||||
import org.cloudburstmc.nbt.NbtMapBuilder;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.UpdateBlockPacket;
|
||||
import org.geysermc.geyser.level.block.BlockStateValues;
|
||||
import org.geysermc.geyser.level.block.type.BlockState;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.util.BlockEntityUtils;
|
||||
|
||||
@ -75,12 +76,12 @@ public class FlowerPotBlockEntityTranslator implements BedrockOnlyBlockEntity {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateBlock(GeyserSession session, int blockState, Vector3i position) {
|
||||
NbtMap tag = getTag(session, blockState, position);
|
||||
public void updateBlock(GeyserSession session, BlockState blockState, Vector3i position) {
|
||||
NbtMap tag = getTag(session, blockState.javaId(), position);
|
||||
BlockEntityUtils.updateBlockEntity(session, tag, position);
|
||||
UpdateBlockPacket updateBlockPacket = new UpdateBlockPacket();
|
||||
updateBlockPacket.setDataLayer(0);
|
||||
updateBlockPacket.setDefinition(session.getBlockMappings().getBedrockBlock(blockState));
|
||||
updateBlockPacket.setDefinition(session.getBlockMappings().getBedrockBlock(blockState.javaId()));
|
||||
updateBlockPacket.setBlockPosition(position);
|
||||
updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NEIGHBORS);
|
||||
updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NETWORK);
|
||||
|
@ -29,13 +29,14 @@ import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.cloudburstmc.nbt.NbtMap;
|
||||
import org.cloudburstmc.nbt.NbtMapBuilder;
|
||||
import org.geysermc.geyser.level.block.BlockStateValues;
|
||||
import org.geysermc.geyser.level.block.type.BlockState;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType;
|
||||
|
||||
@BlockEntity(type = BlockEntityType.JIGSAW)
|
||||
public class JigsawBlockBlockEntityTranslator extends BlockEntityTranslator implements RequiresBlockState {
|
||||
@Override
|
||||
public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, @Nullable NbtMap javaNbt, int blockState) {
|
||||
public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, @Nullable NbtMap javaNbt, BlockState blockState) {
|
||||
if (javaNbt == null) {
|
||||
return;
|
||||
}
|
||||
@ -46,7 +47,7 @@ public class JigsawBlockBlockEntityTranslator extends BlockEntityTranslator impl
|
||||
} else {
|
||||
// Tag is not present in at least 1.14.4 Paper
|
||||
// Minecraft 1.18.1 deliberately has a fallback here, but not for any other value
|
||||
bedrockNbt.putString("joint", BlockStateValues.getHorizontalFacingJigsaws().contains(blockState) ? "aligned" : "rollable");
|
||||
bedrockNbt.putString("joint", BlockStateValues.getHorizontalFacingJigsaws().contains(blockState.javaId()) ? "aligned" : "rollable"); // TODO
|
||||
}
|
||||
bedrockNbt.putString("name", javaNbt.getString("name"));
|
||||
bedrockNbt.putString("target_pool", javaNbt.getString("target_pool"));
|
||||
|
@ -25,6 +25,7 @@
|
||||
|
||||
package org.geysermc.geyser.translator.level.block.entity;
|
||||
|
||||
import org.geysermc.geyser.level.block.type.Block;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.level.block.value.PistonValueType;
|
||||
import org.cloudburstmc.math.vector.Vector3d;
|
||||
import org.cloudburstmc.math.vector.Vector3f;
|
||||
@ -222,10 +223,10 @@ public class PistonBlockEntity {
|
||||
Vector3i blockInFront = position.add(orientation.getUnitVector());
|
||||
int blockId = session.getGeyser().getWorldManager().getBlockAt(session, blockInFront);
|
||||
if (BlockStateValues.isPistonHead(blockId)) {
|
||||
ChunkUtils.updateBlock(session, BlockStateValues.JAVA_AIR_ID, blockInFront);
|
||||
} else if ((session.getGeyser().getPlatformType() == PlatformType.SPIGOT || session.getErosionHandler().isActive()) && blockId == BlockStateValues.JAVA_AIR_ID) {
|
||||
ChunkUtils.updateBlock(session, Block.JAVA_AIR_ID, blockInFront);
|
||||
} else if ((session.getGeyser().getPlatformType() == PlatformType.SPIGOT || session.getErosionHandler().isActive()) && blockId == Block.JAVA_AIR_ID) {
|
||||
// Spigot removes the piston head from the cache, but we need to send the block update ourselves
|
||||
ChunkUtils.updateBlock(session, BlockStateValues.JAVA_AIR_ID, blockInFront);
|
||||
ChunkUtils.updateBlock(session, Block.JAVA_AIR_ID, blockInFront);
|
||||
}
|
||||
}
|
||||
|
||||
@ -255,7 +256,7 @@ public class PistonBlockEntity {
|
||||
continue;
|
||||
}
|
||||
int blockId = session.getGeyser().getWorldManager().getBlockAt(session, blockPos);
|
||||
if (blockId == BlockStateValues.JAVA_AIR_ID) {
|
||||
if (blockId == Block.JAVA_AIR_ID) {
|
||||
continue;
|
||||
}
|
||||
if (BlockStateValues.canPistonMoveBlock(blockId, action == PistonValueType.PUSHING)) {
|
||||
@ -278,7 +279,7 @@ public class PistonBlockEntity {
|
||||
continue;
|
||||
}
|
||||
int adjacentBlockId = session.getGeyser().getWorldManager().getBlockAt(session, adjacentPos);
|
||||
if (adjacentBlockId != BlockStateValues.JAVA_AIR_ID && BlockStateValues.isBlockAttached(blockId, adjacentBlockId) && BlockStateValues.canPistonMoveBlock(adjacentBlockId, false)) {
|
||||
if (adjacentBlockId != Block.JAVA_AIR_ID && BlockStateValues.isBlockAttached(blockId, adjacentBlockId) && BlockStateValues.canPistonMoveBlock(adjacentBlockId, false)) {
|
||||
// If it is another slime/honey block we need to check its adjacent blocks
|
||||
if (BlockStateValues.isBlockSticky(adjacentBlockId)) {
|
||||
blocksToCheck.add(adjacentPos);
|
||||
@ -322,7 +323,7 @@ public class PistonBlockEntity {
|
||||
*/
|
||||
private void removeBlocks() {
|
||||
for (Vector3i blockPos : attachedBlocks.keySet()) {
|
||||
ChunkUtils.updateBlock(session, BlockStateValues.JAVA_AIR_ID, blockPos);
|
||||
ChunkUtils.updateBlock(session, Block.JAVA_AIR_ID, blockPos);
|
||||
}
|
||||
if (action != PistonValueType.PUSHING) {
|
||||
removePistonHead();
|
||||
@ -560,7 +561,7 @@ public class PistonBlockEntity {
|
||||
if (blockPos.equals(getPistonHeadPos())) {
|
||||
return BlockStateValues.getPistonHead(orientation);
|
||||
} else {
|
||||
return attachedBlocks.getOrDefault(blockPos, BlockStateValues.JAVA_AIR_ID);
|
||||
return attachedBlocks.getOrDefault(blockPos, Block.JAVA_AIR_ID);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -28,7 +28,8 @@ package org.geysermc.geyser.translator.level.block.entity;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.cloudburstmc.nbt.NbtMap;
|
||||
import org.cloudburstmc.nbt.NbtMapBuilder;
|
||||
import org.geysermc.geyser.level.block.BlockStateValues;
|
||||
import org.geysermc.geyser.level.block.property.Properties;
|
||||
import org.geysermc.geyser.level.block.type.BlockState;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.translator.inventory.ShulkerInventoryTranslator;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType;
|
||||
@ -40,12 +41,7 @@ public class ShulkerBoxBlockEntityTranslator extends BlockEntityTranslator imple
|
||||
* where {@code tag} is passed as null.
|
||||
*/
|
||||
@Override
|
||||
public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, @Nullable NbtMap javaNbt, int blockState) {
|
||||
byte direction = BlockStateValues.getShulkerBoxDirection(blockState);
|
||||
// Just in case...
|
||||
if (direction == -1) {
|
||||
direction = 1;
|
||||
}
|
||||
bedrockNbt.putByte("facing", direction);
|
||||
public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, @Nullable NbtMap javaNbt, BlockState blockState) {
|
||||
bedrockNbt.putByte("facing", (byte) blockState.getValue(Properties.FACING).ordinal());
|
||||
}
|
||||
}
|
||||
|
@ -28,6 +28,7 @@ package org.geysermc.geyser.translator.level.block.entity;
|
||||
import org.cloudburstmc.nbt.NbtMap;
|
||||
import org.cloudburstmc.nbt.NbtMapBuilder;
|
||||
import org.cloudburstmc.nbt.NbtType;
|
||||
import org.geysermc.geyser.level.block.type.BlockState;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.text.ChatColor;
|
||||
import org.geysermc.geyser.translator.text.MessageTranslator;
|
||||
@ -73,7 +74,7 @@ public class SignBlockEntityTranslator extends BlockEntityTranslator {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, int blockState) {
|
||||
public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, BlockState blockState) {
|
||||
bedrockNbt.putCompound("FrontText", translateSide(javaNbt.getCompound("front_text")));
|
||||
bedrockNbt.putCompound("BackText", translateSide(javaNbt.getCompound("back_text")));
|
||||
bedrockNbt.putBoolean("IsWaxed", javaNbt.getBoolean("is_waxed"));
|
||||
|
@ -34,6 +34,8 @@ import org.cloudburstmc.protocol.bedrock.data.definitions.BlockDefinition;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.UpdateBlockPacket;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.level.block.BlockStateValues;
|
||||
import org.geysermc.geyser.level.block.property.Properties;
|
||||
import org.geysermc.geyser.level.block.type.BlockState;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.session.cache.SkullCache;
|
||||
import org.geysermc.geyser.skin.SkinProvider;
|
||||
@ -50,16 +52,19 @@ import java.util.concurrent.ExecutionException;
|
||||
public class SkullBlockEntityTranslator extends BlockEntityTranslator implements RequiresBlockState {
|
||||
|
||||
@Override
|
||||
public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, int blockState) {
|
||||
byte skullVariant = BlockStateValues.getSkullVariant(blockState);
|
||||
float rotation = BlockStateValues.getSkullRotation(blockState) * 22.5f;
|
||||
public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, BlockState blockState) {
|
||||
byte skullVariant = BlockStateValues.getSkullVariant(blockState.javaId()); // TODO
|
||||
// Just in case...
|
||||
if (skullVariant == -1) {
|
||||
skullVariant = 0;
|
||||
}
|
||||
bedrockNbt.putFloat("Rotation", rotation);
|
||||
Integer rotation = blockState.getValue(Properties.ROTATION_16);
|
||||
if (rotation != null) {
|
||||
// Could be a wall skull block
|
||||
bedrockNbt.putFloat("Rotation", rotation * 22.5f);
|
||||
}
|
||||
bedrockNbt.putByte("SkullType", skullVariant);
|
||||
if (BlockStateValues.isSkullPowered(blockState)) {
|
||||
if (blockState.getValue(Properties.POWERED)) {
|
||||
bedrockNbt.putBoolean("MouthMoving", true);
|
||||
}
|
||||
}
|
||||
|
@ -32,6 +32,7 @@ import org.cloudburstmc.nbt.NbtMap;
|
||||
import org.cloudburstmc.nbt.NbtMapBuilder;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.UpdateBlockPacket;
|
||||
import org.geysermc.geyser.entity.EntityDefinition;
|
||||
import org.geysermc.geyser.level.block.type.BlockState;
|
||||
import org.geysermc.geyser.registry.Registries;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType;
|
||||
@ -40,7 +41,7 @@ import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType
|
||||
public class SpawnerBlockEntityTranslator extends BlockEntityTranslator {
|
||||
|
||||
@Override
|
||||
public NbtMap getBlockEntityTag(GeyserSession session, BlockEntityType type, int x, int y, int z, @Nullable NbtMap javaNbt, int blockState) {
|
||||
public NbtMap getBlockEntityTag(GeyserSession session, BlockEntityType type, int x, int y, int z, @Nullable NbtMap javaNbt, BlockState blockState) {
|
||||
if (javaNbt == null) {
|
||||
return super.getBlockEntityTag(session, type, x, y, z, javaNbt, blockState);
|
||||
}
|
||||
@ -70,7 +71,7 @@ public class SpawnerBlockEntityTranslator extends BlockEntityTranslator {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, int blockState) {
|
||||
public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, BlockState blockState) {
|
||||
Object current;
|
||||
|
||||
// TODO use primitive get and put methods
|
||||
|
@ -32,6 +32,7 @@ import org.cloudburstmc.nbt.NbtMapBuilder;
|
||||
import org.cloudburstmc.protocol.bedrock.data.structure.StructureMirror;
|
||||
import org.cloudburstmc.protocol.bedrock.data.structure.StructureRotation;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.UpdateBlockPacket;
|
||||
import org.geysermc.geyser.level.block.type.BlockState;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.util.StructureBlockUtils;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType;
|
||||
@ -40,7 +41,7 @@ import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType
|
||||
public class StructureBlockBlockEntityTranslator extends BlockEntityTranslator {
|
||||
|
||||
@Override
|
||||
public NbtMap getBlockEntityTag(GeyserSession session, BlockEntityType type, int x, int y, int z, @Nullable NbtMap javaNbt, int blockState) {
|
||||
public NbtMap getBlockEntityTag(GeyserSession session, BlockEntityType type, int x, int y, int z, @Nullable NbtMap javaNbt, BlockState blockState) {
|
||||
if (javaNbt == null) {
|
||||
return super.getBlockEntityTag(session, type, x, y, z, javaNbt, blockState);
|
||||
}
|
||||
@ -73,7 +74,7 @@ public class StructureBlockBlockEntityTranslator extends BlockEntityTranslator {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, int blockState) {
|
||||
public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, BlockState blockState) {
|
||||
if (javaNbt.size() < 5) {
|
||||
return; // These values aren't here
|
||||
}
|
||||
|
@ -27,6 +27,7 @@ package org.geysermc.geyser.translator.level.block.entity;
|
||||
|
||||
import org.cloudburstmc.nbt.NbtMap;
|
||||
import org.cloudburstmc.nbt.NbtMapBuilder;
|
||||
import org.geysermc.geyser.level.block.type.BlockState;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType;
|
||||
|
||||
@ -34,7 +35,7 @@ import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType
|
||||
public class TrialSpawnerBlockEntityTranslator extends BlockEntityTranslator {
|
||||
|
||||
@Override
|
||||
public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, int blockState) {
|
||||
public void translateTag(GeyserSession session, NbtMapBuilder bedrockNbt, NbtMap javaNbt, BlockState blockState) {
|
||||
if (javaNbt == null) {
|
||||
return;
|
||||
}
|
||||
|
@ -25,6 +25,7 @@
|
||||
|
||||
package org.geysermc.geyser.translator.protocol.bedrock;
|
||||
|
||||
import org.geysermc.geyser.level.block.type.Block;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack;
|
||||
import org.cloudburstmc.math.vector.Vector3i;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.BlockPickRequestPacket;
|
||||
@ -48,7 +49,7 @@ public class BedrockBlockPickRequestTranslator extends PacketTranslator<BlockPic
|
||||
int blockToPick = session.getGeyser().getWorldManager().getBlockAt(session, vector.getX(), vector.getY(), vector.getZ());
|
||||
|
||||
// Block is air - chunk caching is probably off
|
||||
if (blockToPick == BlockStateValues.JAVA_AIR_ID) {
|
||||
if (blockToPick == Block.JAVA_AIR_ID) {
|
||||
// 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());
|
||||
if (entity != null) {
|
||||
|
@ -57,6 +57,7 @@ import org.geysermc.geyser.item.type.BoatItem;
|
||||
import org.geysermc.geyser.item.type.Item;
|
||||
import org.geysermc.geyser.item.type.SpawnEggItem;
|
||||
import org.geysermc.geyser.level.block.BlockStateValues;
|
||||
import org.geysermc.geyser.level.block.type.Block;
|
||||
import org.geysermc.geyser.registry.BlockRegistries;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.session.cache.SkullCache;
|
||||
@ -444,7 +445,7 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator<Inve
|
||||
session.getWorldCache().markPositionInSequence(packet.getBlockPosition());
|
||||
// -1 means we don't know what block they're breaking
|
||||
if (blockState == -1) {
|
||||
blockState = BlockStateValues.JAVA_AIR_ID;
|
||||
blockState = Block.JAVA_AIR_ID;
|
||||
}
|
||||
|
||||
LevelEventPacket blockBreakPacket = new LevelEventPacket();
|
||||
|
@ -39,6 +39,8 @@ import org.geysermc.geyser.entity.type.ItemFrameEntity;
|
||||
import org.geysermc.geyser.entity.type.player.SessionPlayerEntity;
|
||||
import org.geysermc.geyser.inventory.GeyserItemStack;
|
||||
import org.geysermc.geyser.level.block.BlockStateValues;
|
||||
import org.geysermc.geyser.level.block.type.Block;
|
||||
import org.geysermc.geyser.level.block.type.BlockState;
|
||||
import org.geysermc.geyser.network.GameProtocol;
|
||||
import org.geysermc.geyser.registry.BlockRegistries;
|
||||
import org.geysermc.geyser.registry.type.BlockMapping;
|
||||
@ -159,7 +161,7 @@ public class BedrockActionTranslator extends PacketTranslator<PlayerActionPacket
|
||||
LevelEventPacket startBreak = new LevelEventPacket();
|
||||
startBreak.setType(LevelEvent.BLOCK_START_BREAK);
|
||||
startBreak.setPosition(vector.toFloat());
|
||||
double breakTime = BlockUtils.getSessionBreakTime(session, BlockRegistries.JAVA_BLOCKS.getOrDefault(blockState, BlockMapping.DEFAULT)) * 20;
|
||||
double breakTime = BlockUtils.getSessionBreakTime(session, BlockRegistries.BLOCK_STATES.getOrDefault(blockState, BlockState.of(Block.JAVA_AIR_ID)).block()) * 20;
|
||||
|
||||
// If the block is custom or the breaking item is custom, we must keep track of break time ourselves
|
||||
GeyserItemStack item = session.getPlayerInventory().getItemInHand();
|
||||
@ -197,7 +199,7 @@ public class BedrockActionTranslator extends PacketTranslator<PlayerActionPacket
|
||||
}
|
||||
int breakingBlock = session.getBreakingBlock();
|
||||
if (breakingBlock == -1) {
|
||||
breakingBlock = BlockStateValues.JAVA_AIR_ID;
|
||||
breakingBlock = Block.JAVA_AIR_ID;
|
||||
}
|
||||
|
||||
Vector3f vectorFloat = vector.toFloat();
|
||||
@ -211,7 +213,7 @@ public class BedrockActionTranslator extends PacketTranslator<PlayerActionPacket
|
||||
LevelEventPacket updateBreak = new LevelEventPacket();
|
||||
updateBreak.setType(LevelEvent.BLOCK_UPDATE_BREAK);
|
||||
updateBreak.setPosition(vectorFloat);
|
||||
double breakTime = BlockUtils.getSessionBreakTime(session, BlockRegistries.JAVA_BLOCKS.getOrDefault(breakingBlock, BlockMapping.DEFAULT)) * 20;
|
||||
double breakTime = BlockUtils.getSessionBreakTime(session, BlockRegistries.BLOCK_STATES.getOrDefault(breakingBlock, BlockState.of(Block.JAVA_AIR_ID)).block()) * 20;
|
||||
|
||||
|
||||
// If the block is custom, we must keep track of when it should break ourselves
|
||||
|
@ -25,6 +25,7 @@
|
||||
|
||||
package org.geysermc.geyser.translator.protocol.java;
|
||||
|
||||
import org.geysermc.erosion.Constants;
|
||||
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.ingame.clientbound.ClientboundLoginPacket;
|
||||
@ -45,6 +46,8 @@ import org.geysermc.geyser.util.ChunkUtils;
|
||||
import org.geysermc.geyser.util.DimensionUtils;
|
||||
import org.geysermc.geyser.util.EntityUtils;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
@Translator(packet = ClientboundLoginPacket.class)
|
||||
public class JavaLoginTranslator extends PacketTranslator<ClientboundLoginPacket> {
|
||||
|
||||
@ -134,6 +137,7 @@ public class JavaLoginTranslator extends PacketTranslator<ClientboundLoginPacket
|
||||
if (session.remoteServer().authType() == AuthType.FLOODGATE) {
|
||||
session.sendDownstreamPacket(new ServerboundCustomPayloadPacket("minecraft:register", PluginMessageChannels.getFloodgateRegisterData()));
|
||||
}
|
||||
session.sendDownstreamPacket(new ServerboundCustomPayloadPacket("minecraft:register", Constants.PLUGIN_MESSAGE.getBytes(StandardCharsets.UTF_8)));
|
||||
|
||||
if (newDimension != session.getDimension()) {
|
||||
DimensionUtils.switchDimension(session, newDimension);
|
||||
|
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* 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.translator.protocol.java;
|
||||
|
||||
import org.geysermc.geyser.network.GameProtocol;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.translator.protocol.PacketTranslator;
|
||||
import org.geysermc.geyser.translator.protocol.Translator;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.KnownPack;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.configuration.clientbound.ClientboundSelectKnownPacks;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.configuration.serverbound.ServerboundSelectKnownPacks;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
@Translator(packet = ClientboundSelectKnownPacks.class)
|
||||
public class JavaSelectKnownPacksTranslator extends PacketTranslator<ClientboundSelectKnownPacks> {
|
||||
// todo: dump from client?
|
||||
private static final Set<String> KNOWN_PACK_IDS = Set.of("core", "update_1_21", "bundle", "trade_rebalance");
|
||||
|
||||
@Override
|
||||
public void translate(GeyserSession session, ClientboundSelectKnownPacks packet) {
|
||||
List<KnownPack> knownPacks = new ArrayList<>(1);
|
||||
for (KnownPack pack : packet.getKnownPacks()) {
|
||||
if ("minecraft".equals(pack.getNamespace()) && GameProtocol.getJavaMinecraftVersion().equals(pack.getVersion())) {
|
||||
// Implementation note: these won't always necessarily be equal.
|
||||
// 1.20.5 versus 1.20.6 for example - same protocol version. A vanilla server for either version will gracefully accept either.
|
||||
// If the versions mismatch, the registry will be sent over the network, though.
|
||||
// For vanilla compliancy, to minimize network traffic, and for potential future behavior,
|
||||
// We'll implement how the Java client does it.
|
||||
if (KNOWN_PACK_IDS.contains(pack.getId())) {
|
||||
knownPacks.add(pack);
|
||||
}
|
||||
}
|
||||
}
|
||||
session.sendDownstreamPacket(new ServerboundSelectKnownPacks(knownPacks));
|
||||
}
|
||||
}
|
@ -25,16 +25,17 @@
|
||||
|
||||
package org.geysermc.geyser.translator.protocol.java.level;
|
||||
|
||||
import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.level.ClientboundBlockDestructionPacket;
|
||||
import org.cloudburstmc.protocol.bedrock.data.LevelEvent;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.LevelEventPacket;
|
||||
import org.geysermc.geyser.level.block.type.Block;
|
||||
import org.geysermc.geyser.level.block.type.BlockState;
|
||||
import org.geysermc.geyser.registry.BlockRegistries;
|
||||
import org.geysermc.geyser.registry.type.BlockMapping;
|
||||
import org.geysermc.geyser.registry.type.ItemMapping;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.translator.protocol.PacketTranslator;
|
||||
import org.geysermc.geyser.translator.protocol.Translator;
|
||||
import org.geysermc.geyser.util.BlockUtils;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.level.ClientboundBlockDestructionPacket;
|
||||
|
||||
@Translator(packet = ClientboundBlockDestructionPacket.class)
|
||||
public class JavaBlockDestructionTranslator extends PacketTranslator<ClientboundBlockDestructionPacket> {
|
||||
@ -42,7 +43,7 @@ public class JavaBlockDestructionTranslator extends PacketTranslator<Clientbound
|
||||
@Override
|
||||
public void translate(GeyserSession session, ClientboundBlockDestructionPacket packet) {
|
||||
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, BlockRegistries.JAVA_BLOCKS.getOrDefault(state, BlockMapping.DEFAULT), ItemMapping.AIR, null, false) * 20));
|
||||
int breakTime = (int) (65535 / Math.ceil(BlockUtils.getBreakTime(session, BlockRegistries.BLOCK_STATES.getOrDefault(state, BlockState.of(Block.JAVA_AIR_ID)).block(), ItemMapping.AIR, null, false) * 20));
|
||||
LevelEventPacket levelEventPacket = new LevelEventPacket();
|
||||
levelEventPacket.setPosition(packet.getPosition().toFloat());
|
||||
levelEventPacket.setType(LevelEvent.BLOCK_START_BREAK);
|
||||
|
@ -33,7 +33,8 @@ import org.cloudburstmc.protocol.bedrock.data.structure.StructureMirror;
|
||||
import org.cloudburstmc.protocol.bedrock.data.structure.StructureRotation;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.ContainerOpenPacket;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.UpdateBlockPacket;
|
||||
import org.geysermc.geyser.level.block.BlockStateValues;
|
||||
import org.geysermc.geyser.level.block.type.BlockState;
|
||||
import org.geysermc.geyser.registry.BlockRegistries;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.translator.level.block.entity.BlockEntityTranslator;
|
||||
import org.geysermc.geyser.translator.level.block.entity.RequiresBlockState;
|
||||
@ -58,11 +59,11 @@ public class JavaBlockEntityDataTranslator extends PacketTranslator<ClientboundB
|
||||
BlockEntityTranslator translator = BlockEntityUtils.getBlockEntityTranslator(type);
|
||||
// The Java block state is used in BlockEntityTranslator.translateTag() to make up for some inconsistencies
|
||||
// between Java block states and Bedrock block entity data
|
||||
int blockState;
|
||||
BlockState blockState;
|
||||
if (translator instanceof RequiresBlockState) {
|
||||
blockState = session.getGeyser().getWorldManager().getBlockAt(session, packet.getPosition());
|
||||
blockState = BlockRegistries.BLOCK_STATES.get(session.getGeyser().getWorldManager().getBlockAt(session, packet.getPosition()));
|
||||
} else {
|
||||
blockState = BlockStateValues.JAVA_AIR_ID;
|
||||
blockState = BlockRegistries.BLOCK_STATES.get(0); //TODO
|
||||
}
|
||||
|
||||
Vector3i position = packet.getPosition();
|
||||
@ -71,7 +72,7 @@ public class JavaBlockEntityDataTranslator extends PacketTranslator<ClientboundB
|
||||
// Check for custom skulls.
|
||||
boolean hasCustomHeadBlock = false;
|
||||
if (session.getPreferencesCache().showCustomSkulls() && packet.getNbt() != null && packet.getNbt().containsKey("profile")) {
|
||||
BlockDefinition blockDefinition = SkullBlockEntityTranslator.translateSkull(session, packet.getNbt(), position, blockState);
|
||||
BlockDefinition blockDefinition = SkullBlockEntityTranslator.translateSkull(session, packet.getNbt(), position, blockState.javaId());
|
||||
if (blockDefinition != null) {
|
||||
hasCustomHeadBlock = true;
|
||||
UpdateBlockPacket updateBlockPacket = new UpdateBlockPacket();
|
||||
|
@ -25,6 +25,7 @@
|
||||
|
||||
package org.geysermc.geyser.translator.protocol.java.level;
|
||||
|
||||
import org.geysermc.geyser.level.block.type.Block;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.level.block.value.*;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.level.ClientboundBlockEventPacket;
|
||||
import org.cloudburstmc.math.vector.Vector3i;
|
||||
@ -82,7 +83,7 @@ public class JavaBlockEventTranslator extends PacketTranslator<ClientboundBlockE
|
||||
if (action != PistonValueType.CANCELLED_MID_PUSH) {
|
||||
Vector3i blockInFrontPos = position.add(direction.getUnitVector());
|
||||
int blockInFront = session.getGeyser().getWorldManager().getBlockAt(session, blockInFrontPos);
|
||||
if (blockInFront != BlockStateValues.JAVA_AIR_ID) {
|
||||
if (blockInFront != Block.JAVA_AIR_ID) {
|
||||
// Piston pulled something
|
||||
return;
|
||||
}
|
||||
|
@ -25,6 +25,7 @@
|
||||
|
||||
package org.geysermc.geyser.translator.protocol.java.level;
|
||||
|
||||
import org.geysermc.geyser.level.block.type.Block;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.level.ClientboundExplodePacket;
|
||||
import org.cloudburstmc.math.vector.Vector3f;
|
||||
import org.cloudburstmc.math.vector.Vector3i;
|
||||
@ -58,7 +59,7 @@ public class JavaExplodeTranslator extends PacketTranslator<ClientboundExplodePa
|
||||
int i = 0;
|
||||
for (Vector3i position : packet.getExploded()) {
|
||||
Vector3i pos = Vector3i.from(packet.getX() + position.getX(), packet.getY() + position.getY(), packet.getZ() + position.getZ());
|
||||
ChunkUtils.updateBlock(session, BlockStateValues.JAVA_AIR_ID, pos);
|
||||
ChunkUtils.updateBlock(session, Block.JAVA_AIR_ID, pos);
|
||||
builder.putFloat("pos" + i + "x", pos.getX());
|
||||
builder.putFloat("pos" + i + "y", pos.getY());
|
||||
builder.putFloat("pos" + i + "z", pos.getZ());
|
||||
|
@ -42,6 +42,9 @@ import org.geysermc.erosion.util.LecternUtils;
|
||||
import org.geysermc.geyser.entity.type.ItemFrameEntity;
|
||||
import org.geysermc.geyser.level.BedrockDimension;
|
||||
import org.geysermc.geyser.level.block.BlockStateValues;
|
||||
import org.geysermc.geyser.level.block.property.Properties;
|
||||
import org.geysermc.geyser.level.block.type.Block;
|
||||
import org.geysermc.geyser.level.block.type.BlockState;
|
||||
import org.geysermc.geyser.level.chunk.BlockStorage;
|
||||
import org.geysermc.geyser.level.chunk.GeyserChunkSection;
|
||||
import org.geysermc.geyser.level.chunk.bitarray.BitArray;
|
||||
@ -175,7 +178,7 @@ public class JavaLevelChunkWithLightTranslator extends PacketTranslator<Clientbo
|
||||
// Extended collision blocks
|
||||
if (useExtendedCollisions) {
|
||||
if (EXTENDED_COLLISIONS_STORAGE.get().get(yzx, sectionY) != 0) {
|
||||
if (javaId == BlockStateValues.JAVA_AIR_ID) {
|
||||
if (javaId == Block.JAVA_AIR_ID) {
|
||||
section.getBlockStorageArray()[0].setFullBlock(xzy, EXTENDED_COLLISIONS_STORAGE.get().get(yzx, sectionY));
|
||||
}
|
||||
EXTENDED_COLLISIONS_STORAGE.get().set(yzx, 0, sectionY);
|
||||
@ -238,7 +241,7 @@ public class JavaLevelChunkWithLightTranslator extends PacketTranslator<Clientbo
|
||||
waterloggedPaletteIds.set(i);
|
||||
}
|
||||
|
||||
if (javaId == BlockStateValues.JAVA_AIR_ID) {
|
||||
if (javaId == Block.JAVA_AIR_ID) {
|
||||
airPaletteId = i;
|
||||
}
|
||||
|
||||
@ -396,9 +399,9 @@ public class JavaLevelChunkWithLightTranslator extends PacketTranslator<Clientbo
|
||||
|
||||
// Get the Java block state ID from block entity position
|
||||
DataPalette section = javaChunks[(y >> 4) - yOffset];
|
||||
int blockState = section.get(x, y & 0xF, z);
|
||||
BlockState blockState = BlockRegistries.BLOCK_STATES.get(section.get(x, y & 0xF, z));
|
||||
|
||||
if (type == BlockEntityType.LECTERN && BlockStateValues.getLecternBookStates().get(blockState)) {
|
||||
if (type == BlockEntityType.LECTERN && blockState.getValue(Properties.HAS_BOOK)) {
|
||||
// If getLecternBookStates is false, let's just treat it like a normal block entity
|
||||
// Fill in tag with a default value
|
||||
NbtMapBuilder lecternTag = LecternUtils.getBaseLecternTag(x + chunkBlockX, y, z + chunkBlockZ, 1);
|
||||
@ -419,7 +422,7 @@ public class JavaLevelChunkWithLightTranslator extends PacketTranslator<Clientbo
|
||||
|
||||
// Check for custom skulls
|
||||
if (session.getPreferencesCache().showCustomSkulls() && type == BlockEntityType.SKULL && tag != null && tag.containsKey("profile")) {
|
||||
BlockDefinition blockDefinition = SkullBlockEntityTranslator.translateSkull(session, tag, Vector3i.from(x + chunkBlockX, y, z + chunkBlockZ), blockState);
|
||||
BlockDefinition blockDefinition = SkullBlockEntityTranslator.translateSkull(session, tag, Vector3i.from(x + chunkBlockX, y, z + chunkBlockZ), blockState.javaId());
|
||||
if (blockDefinition != null) {
|
||||
int bedrockSectionY = (y >> 4) - (bedrockDimension.minY() >> 4);
|
||||
int subChunkIndex = (y >> 4) + (bedrockDimension.minY() >> 4);
|
||||
|
@ -30,9 +30,9 @@ import org.cloudburstmc.math.vector.Vector3i;
|
||||
import org.geysermc.geyser.inventory.GeyserItemStack;
|
||||
import org.geysermc.geyser.inventory.PlayerInventory;
|
||||
import org.geysermc.geyser.inventory.item.Enchantment;
|
||||
import org.geysermc.geyser.level.block.BlockStateValues;
|
||||
import org.geysermc.geyser.level.block.Blocks;
|
||||
import org.geysermc.geyser.level.block.type.Block;
|
||||
import org.geysermc.geyser.registry.BlockRegistries;
|
||||
import org.geysermc.geyser.registry.type.BlockMapping;
|
||||
import org.geysermc.geyser.registry.type.ItemMapping;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.session.cache.tags.BlockTag;
|
||||
@ -41,14 +41,14 @@ import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponen
|
||||
|
||||
public final class BlockUtils {
|
||||
|
||||
private static boolean correctTool(GeyserSession session, BlockMapping blockMapping, String itemToolType) {
|
||||
private static boolean correctTool(GeyserSession session, Block block, String itemToolType) {
|
||||
return switch (itemToolType) {
|
||||
case "axe" -> session.getTagCache().is(BlockTag.AXE_EFFECTIVE, blockMapping);
|
||||
case "hoe" -> session.getTagCache().is(BlockTag.HOE_EFFECTIVE, blockMapping);
|
||||
case "pickaxe" -> session.getTagCache().is(BlockTag.PICKAXE_EFFECTIVE, blockMapping);
|
||||
case "shears" -> session.getTagCache().is(BlockTag.LEAVES, blockMapping) || session.getTagCache().is(BlockTag.WOOL, blockMapping);
|
||||
case "shovel" -> session.getTagCache().is(BlockTag.SHOVEL_EFFECTIVE, blockMapping);
|
||||
case "sword" -> blockMapping.getJavaBlockId() == BlockStateValues.JAVA_COBWEB_ID;
|
||||
case "axe" -> session.getTagCache().is(BlockTag.AXE_EFFECTIVE, block);
|
||||
case "hoe" -> session.getTagCache().is(BlockTag.HOE_EFFECTIVE, block);
|
||||
case "pickaxe" -> session.getTagCache().is(BlockTag.PICKAXE_EFFECTIVE, block);
|
||||
case "shears" -> session.getTagCache().is(BlockTag.LEAVES, block) || session.getTagCache().is(BlockTag.WOOL, block);
|
||||
case "shovel" -> session.getTagCache().is(BlockTag.SHOVEL_EFFECTIVE, block);
|
||||
case "sword" -> block == Blocks.COBWEB;
|
||||
default -> {
|
||||
session.getGeyser().getLogger().warning("Unknown tool type: " + itemToolType);
|
||||
yield false;
|
||||
@ -71,7 +71,7 @@ public final class BlockUtils {
|
||||
};
|
||||
}
|
||||
|
||||
private static boolean canToolTierBreakBlock(GeyserSession session, BlockMapping blockMapping, String toolTier) {
|
||||
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;
|
||||
@ -80,15 +80,15 @@ public final class BlockUtils {
|
||||
switch (toolTier) {
|
||||
// Use intentional fall-throughs to check each tier with this block
|
||||
default:
|
||||
if (session.getTagCache().is(BlockTag.NEEDS_STONE_TOOL, blockMapping)) {
|
||||
if (session.getTagCache().is(BlockTag.NEEDS_STONE_TOOL, block)) {
|
||||
return false;
|
||||
}
|
||||
case "stone":
|
||||
if (session.getTagCache().is(BlockTag.NEEDS_IRON_TOOL, blockMapping)) {
|
||||
if (session.getTagCache().is(BlockTag.NEEDS_IRON_TOOL, block)) {
|
||||
return false;
|
||||
}
|
||||
case "iron":
|
||||
if (session.getTagCache().is(BlockTag.NEEDS_DIAMOND_TOOL, blockMapping)) {
|
||||
if (session.getTagCache().is(BlockTag.NEEDS_DIAMOND_TOOL, block)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -131,9 +131,9 @@ public final class BlockUtils {
|
||||
return 1.0 / speed;
|
||||
}
|
||||
|
||||
public static double getBreakTime(GeyserSession session, BlockMapping blockMapping, ItemMapping item, @Nullable DataComponents components, boolean isSessionPlayer) {
|
||||
boolean isShearsEffective = session.getTagCache().is(BlockTag.LEAVES, blockMapping) || session.getTagCache().is(BlockTag.WOOL, blockMapping); //TODO called twice
|
||||
boolean canHarvestWithHand = blockMapping.isCanBreakWithHand();
|
||||
public static double getBreakTime(GeyserSession session, Block block, ItemMapping item, @Nullable DataComponents components, boolean isSessionPlayer) {
|
||||
boolean isShearsEffective = session.getTagCache().is(BlockTag.LEAVES, block) || session.getTagCache().is(BlockTag.WOOL, block); //TODO called twice
|
||||
boolean canHarvestWithHand = !block.requiresCorrectToolForDrops();
|
||||
String toolType = "";
|
||||
String toolTier = "";
|
||||
boolean correctTool = false;
|
||||
@ -141,8 +141,8 @@ public final class BlockUtils {
|
||||
if (item.isTool()) {
|
||||
toolType = item.getToolType();
|
||||
toolTier = item.getToolTier();
|
||||
correctTool = correctTool(session, blockMapping, toolType);
|
||||
toolCanBreak = canToolTierBreakBlock(session, blockMapping, toolTier);
|
||||
correctTool = correctTool(session, block, toolType);
|
||||
toolCanBreak = canToolTierBreakBlock(session, block, toolTier);
|
||||
}
|
||||
|
||||
int toolEfficiencyLevel = ItemUtils.getEnchantmentLevel(components, Enchantment.JavaEnchantment.EFFICIENCY);
|
||||
@ -151,7 +151,7 @@ public final class BlockUtils {
|
||||
|
||||
if (!isSessionPlayer) {
|
||||
// Another entity is currently mining; we have all the information we know
|
||||
return calculateBreakTime(blockMapping.getHardness(), toolTier, canHarvestWithHand, correctTool, toolCanBreak, toolType, isShearsEffective,
|
||||
return calculateBreakTime(block.destroyTime(), toolTier, canHarvestWithHand, correctTool, toolCanBreak, toolType, isShearsEffective,
|
||||
toolEfficiencyLevel, hasteLevel, miningFatigueLevel, false, true);
|
||||
}
|
||||
|
||||
@ -162,11 +162,11 @@ public final class BlockUtils {
|
||||
boolean insideOfWaterWithoutAquaAffinity = waterInEyes &&
|
||||
ItemUtils.getEnchantmentLevel(session.getPlayerInventory().getItem(5).getComponents(), Enchantment.JavaEnchantment.AQUA_AFFINITY) < 1;
|
||||
|
||||
return calculateBreakTime(blockMapping.getHardness(), toolTier, canHarvestWithHand, correctTool, toolCanBreak, toolType, isShearsEffective,
|
||||
return calculateBreakTime(block.destroyTime(), toolTier, canHarvestWithHand, correctTool, toolCanBreak, toolType, isShearsEffective,
|
||||
toolEfficiencyLevel, hasteLevel, miningFatigueLevel, insideOfWaterWithoutAquaAffinity, session.getPlayerEntity().isOnGround());
|
||||
}
|
||||
|
||||
public static double getSessionBreakTime(GeyserSession session, BlockMapping blockMapping) {
|
||||
public static double getSessionBreakTime(GeyserSession session, Block block) {
|
||||
PlayerInventory inventory = session.getPlayerInventory();
|
||||
GeyserItemStack item = inventory.getItemInHand();
|
||||
ItemMapping mapping = ItemMapping.AIR;
|
||||
@ -175,7 +175,7 @@ public final class BlockUtils {
|
||||
mapping = item.getMapping(session);
|
||||
components = item.getComponents();
|
||||
}
|
||||
return getBreakTime(session, blockMapping, mapping, components, true);
|
||||
return getBreakTime(session, block, mapping, components, true);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -41,6 +41,8 @@ import org.geysermc.geyser.entity.type.ItemFrameEntity;
|
||||
import org.geysermc.geyser.level.BedrockDimension;
|
||||
import org.geysermc.geyser.level.JavaDimension;
|
||||
import org.geysermc.geyser.level.block.BlockStateValues;
|
||||
import org.geysermc.geyser.level.block.type.Block;
|
||||
import org.geysermc.geyser.level.block.type.BlockState;
|
||||
import org.geysermc.geyser.level.chunk.BlockStorage;
|
||||
import org.geysermc.geyser.level.chunk.GeyserChunkSection;
|
||||
import org.geysermc.geyser.level.chunk.bitarray.SingletonBitArray;
|
||||
@ -50,8 +52,6 @@ import org.geysermc.geyser.session.cache.SkullCache;
|
||||
import org.geysermc.geyser.text.GeyserLocale;
|
||||
import org.geysermc.geyser.translator.level.block.entity.BedrockOnlyBlockEntity;
|
||||
|
||||
import static org.geysermc.geyser.level.block.BlockStateValues.JAVA_AIR_ID;
|
||||
|
||||
@UtilityClass
|
||||
public class ChunkUtils {
|
||||
|
||||
@ -130,7 +130,7 @@ public class ChunkUtils {
|
||||
// Checks for item frames so they aren't tripped up and removed
|
||||
ItemFrameEntity itemFrameEntity = ItemFrameEntity.getItemFrameEntity(session, position);
|
||||
if (itemFrameEntity != null) {
|
||||
if (blockState == JAVA_AIR_ID) { // Item frame is still present and no block overrides that; refresh it
|
||||
if (blockState == Block.JAVA_AIR_ID) { // Item frame is still present and no block overrides that; refresh it
|
||||
itemFrameEntity.updateBlock(true);
|
||||
// Still update the chunk cache with the new block if updateBlock is called
|
||||
return;
|
||||
@ -180,21 +180,21 @@ public class ChunkUtils {
|
||||
BlockDefinition aboveBedrockExtendedCollisionDefinition = session.getBlockMappings().getExtendedCollisionBoxes().get(blockState);
|
||||
int belowBlock = session.getGeyser().getWorldManager().getBlockAt(session, position.getX(), position.getY() - 1, position.getZ());
|
||||
BlockDefinition belowBedrockExtendedCollisionDefinition = session.getBlockMappings().getExtendedCollisionBoxes().get(belowBlock);
|
||||
if (belowBedrockExtendedCollisionDefinition != null && blockState == BlockStateValues.JAVA_AIR_ID) {
|
||||
if (belowBedrockExtendedCollisionDefinition != null && blockState == Block.JAVA_AIR_ID) {
|
||||
UpdateBlockPacket updateBlockPacket = new UpdateBlockPacket();
|
||||
updateBlockPacket.setDataLayer(0);
|
||||
updateBlockPacket.setBlockPosition(position);
|
||||
updateBlockPacket.setDefinition(belowBedrockExtendedCollisionDefinition);
|
||||
updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NETWORK);
|
||||
session.sendUpstreamPacket(updateBlockPacket);
|
||||
} else if (aboveBedrockExtendedCollisionDefinition != null && aboveBlock == BlockStateValues.JAVA_AIR_ID) {
|
||||
} else if (aboveBedrockExtendedCollisionDefinition != null && aboveBlock == Block.JAVA_AIR_ID) {
|
||||
UpdateBlockPacket updateBlockPacket = new UpdateBlockPacket();
|
||||
updateBlockPacket.setDataLayer(0);
|
||||
updateBlockPacket.setBlockPosition(position.add(0, 1, 0));
|
||||
updateBlockPacket.setDefinition(aboveBedrockExtendedCollisionDefinition);
|
||||
updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NETWORK);
|
||||
session.sendUpstreamPacket(updateBlockPacket);
|
||||
} else if (aboveBlock == BlockStateValues.JAVA_AIR_ID) {
|
||||
} else if (aboveBlock == Block.JAVA_AIR_ID) {
|
||||
UpdateBlockPacket updateBlockPacket = new UpdateBlockPacket();
|
||||
updateBlockPacket.setDataLayer(0);
|
||||
updateBlockPacket.setBlockPosition(position.add(0, 1, 0));
|
||||
@ -211,7 +211,7 @@ public class ChunkUtils {
|
||||
for (BedrockOnlyBlockEntity bedrockOnlyBlockEntity : BlockEntityUtils.BEDROCK_ONLY_BLOCK_ENTITIES) {
|
||||
if (bedrockOnlyBlockEntity.isBlock(blockState)) {
|
||||
// Flower pots are block entities only in Bedrock and are not updated anywhere else like note blocks
|
||||
bedrockOnlyBlockEntity.updateBlock(session, blockState, position);
|
||||
bedrockOnlyBlockEntity.updateBlock(session, BlockState.of(blockState), position); //TODO blockState
|
||||
break; //No block will be a part of two classes
|
||||
}
|
||||
}
|
||||
|
@ -34,6 +34,7 @@ import org.cloudburstmc.protocol.bedrock.packet.LevelSoundEventPacket;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.PlaySoundPacket;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.level.block.BlockStateValues;
|
||||
import org.geysermc.geyser.level.block.type.Block;
|
||||
import org.geysermc.geyser.registry.BlockRegistries;
|
||||
import org.geysermc.geyser.registry.Registries;
|
||||
import org.geysermc.geyser.registry.type.SoundMapping;
|
||||
@ -147,7 +148,7 @@ public final class SoundUtils {
|
||||
soundPacket.setExtraData(soundMapping.getExtraData() + (int)(Math.round((Math.log10(pitch) / Math.log10(2)) * 12)) + 12);
|
||||
} else if (sound == SoundEvent.PLACE && soundMapping.getExtraData() == -1) {
|
||||
if (!soundMapping.getIdentifier().equals(":")) {
|
||||
int javaId = BlockRegistries.JAVA_IDENTIFIER_TO_ID.get().getOrDefault(soundMapping.getIdentifier(), BlockStateValues.JAVA_AIR_ID);
|
||||
int javaId = BlockRegistries.JAVA_IDENTIFIER_TO_ID.get().getOrDefault(soundMapping.getIdentifier(), Block.JAVA_AIR_ID);
|
||||
soundPacket.setExtraData(session.getBlockMappings().getBedrockBlockId(javaId));
|
||||
} else {
|
||||
session.getGeyser().getLogger().debug("PLACE sound mapping identifier was invalid! Please report: " + soundMapping);
|
||||
|
@ -29,6 +29,7 @@ import it.unimi.dsi.fastutil.objects.Object2IntMap;
|
||||
import org.geysermc.cumulus.form.SimpleForm;
|
||||
import org.geysermc.cumulus.util.FormImage;
|
||||
import org.geysermc.geyser.item.type.Item;
|
||||
import org.geysermc.geyser.level.block.type.Block;
|
||||
import org.geysermc.geyser.registry.BlockRegistries;
|
||||
import org.geysermc.geyser.registry.Registries;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
@ -93,10 +94,10 @@ public class StatisticsUtils {
|
||||
|
||||
for (Object2IntMap.Entry<Statistic> entry : session.getStatistics().object2IntEntrySet()) {
|
||||
if (entry.getKey() instanceof BreakBlockStatistic statistic) {
|
||||
String identifier = BlockRegistries.CLEAN_JAVA_IDENTIFIERS.get(statistic.getId());
|
||||
if (identifier != null) {
|
||||
String block = identifier.replace("minecraft:", "block.minecraft.");
|
||||
content.add(block + ": " + entry.getIntValue());
|
||||
Block block = BlockRegistries.JAVA_BLOCKS_TO_RENAME.get(statistic.getId());
|
||||
if (block != null) {
|
||||
String identifier = block.javaIdentifier().replace("minecraft:", "block.minecraft.");
|
||||
content.add(identifier + ": " + entry.getIntValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 7c01501ed6a0ee8848a66d729000539f2661f785
|
||||
Subproject commit 6b661f0d517d895aebc1f55a25d2c86f033beb1d
|
@ -1,7 +1,7 @@
|
||||
[versions]
|
||||
base-api = "1.0.0-SNAPSHOT"
|
||||
cumulus = "1.1.2"
|
||||
erosion = "1.0-20230406.174837-8"
|
||||
erosion = "1.1-20240515.191456-1"
|
||||
events = "1.1-SNAPSHOT"
|
||||
jackson = "2.17.0"
|
||||
fastutil = "8.5.2"
|
||||
@ -15,7 +15,7 @@ protocol-connection = "3.0.0.Beta1-20240411.165033-128"
|
||||
raknet = "1.0.0.CR3-20240416.144209-1"
|
||||
blockstateupdater="1.20.80-20240411.142413-1"
|
||||
mcauthlib = "e5b0bcc"
|
||||
mcprotocollib = "42ea4a4" # Revert from jitpack after release
|
||||
mcprotocollib = "1.20.6-2-20240515.051848-2" # Revert from jitpack after release
|
||||
adventure = "4.14.0"
|
||||
adventure-platform = "4.3.0"
|
||||
junit = "5.9.2"
|
||||
@ -52,6 +52,7 @@ cumulus = { group = "org.geysermc.cumulus", name = "cumulus", version.ref = "cum
|
||||
events = { group = "org.geysermc.event", name = "events", version.ref = "events" }
|
||||
|
||||
erosion-bukkit-common = { group = "org.geysermc.erosion", name = "bukkit-common", version.ref = "erosion" }
|
||||
erosion-bukkit-nms = { group = "org.geysermc.erosion", name = "bukkit-nms", version.ref = "erosion" }
|
||||
erosion-common = { group = "org.geysermc.erosion", name = "common", version.ref = "erosion" }
|
||||
|
||||
jackson-annotations = { group = "com.fasterxml.jackson.core", name = "jackson-annotations", version.ref = "jackson" }
|
||||
@ -64,6 +65,7 @@ fastutil-int-byte-maps = { group = "com.nukkitx.fastutil", name = "fastutil-int-
|
||||
fastutil-int-boolean-maps = { group = "com.nukkitx.fastutil", name = "fastutil-int-boolean-maps", version.ref = "fastutil" }
|
||||
fastutil-object-int-maps = { group = "com.nukkitx.fastutil", name = "fastutil-object-int-maps", version.ref = "fastutil" }
|
||||
fastutil-object-object-maps = { group = "com.nukkitx.fastutil", name = "fastutil-object-object-maps", version.ref = "fastutil" }
|
||||
fastutil-reference-object-maps = { group = "com.nukkitx.fastutil", name = "fastutil-reference-object-maps", version.ref = "fastutil" }
|
||||
|
||||
adventure-text-serializer-gson = { group = "net.kyori", name = "adventure-text-serializer-gson", version.ref = "adventure" } # Remove when we remove our Adventure bump
|
||||
adventure-text-serializer-legacy = { group = "net.kyori", name = "adventure-text-serializer-legacy", version.ref = "adventure" }
|
||||
@ -108,7 +110,7 @@ guava = { group = "com.google.guava", name = "guava", version.ref = "guava" }
|
||||
gson = { group = "com.google.code.gson", name = "gson", version.ref = "gson" }
|
||||
junit = { group = "org.junit.jupiter", name = "junit-jupiter", version.ref = "junit" }
|
||||
mcauthlib = { group = "com.github.GeyserMC", name = "MCAuthLib", version.ref = "mcauthlib" }
|
||||
mcprotocollib = { group = "com.github.geysermc", name = "mcprotocollib", version.ref = "mcprotocollib" }
|
||||
mcprotocollib = { group = "org.geysermc.mcprotocollib", name = "protocol", version.ref = "mcprotocollib" }
|
||||
raknet = { group = "org.cloudburstmc.netty", name = "netty-transport-raknet", version.ref = "raknet" }
|
||||
terminalconsoleappender = { group = "net.minecrell", name = "terminalconsoleappender", version.ref = "terminalconsoleappender" }
|
||||
velocity-api = { group = "com.velocitypowered", name = "velocity-api", version.ref = "velocity" }
|
||||
@ -141,7 +143,7 @@ blossom = { id = "net.kyori.blossom", version.ref = "blossom" }
|
||||
|
||||
[bundles]
|
||||
jackson = [ "jackson-annotations", "jackson-core", "jackson-dataformat-yaml" ]
|
||||
fastutil = [ "fastutil-int-int-maps", "fastutil-int-long-maps", "fastutil-int-byte-maps", "fastutil-int-boolean-maps", "fastutil-object-int-maps", "fastutil-object-object-maps" ]
|
||||
fastutil = [ "fastutil-int-int-maps", "fastutil-int-long-maps", "fastutil-int-byte-maps", "fastutil-int-boolean-maps", "fastutil-object-int-maps", "fastutil-object-object-maps", "fastutil-reference-object-maps" ]
|
||||
adventure = [ "adventure-text-serializer-gson", "adventure-text-serializer-legacy", "adventure-text-serializer-plain" ]
|
||||
log4j = [ "log4j-api", "log4j-core", "log4j-slf4j2-impl" ]
|
||||
jline = [ "jline-terminal", "jline-terminal-jna", "jline-reader" ]
|
||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren