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
32d587a65a
@ -41,6 +41,7 @@ import org.bukkit.event.block.BlockPistonRetractEvent;
|
||||
import org.cloudburstmc.math.vector.Vector3i;
|
||||
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.level.physics.Direction;
|
||||
import org.geysermc.geyser.platform.spigot.world.manager.GeyserSpigotWorldManager;
|
||||
@ -120,7 +121,7 @@ public class GeyserPistonListener implements Listener {
|
||||
|
||||
int pistonBlockId = worldManager.getBlockNetworkId(event.getBlock());
|
||||
// event.getDirection() is unreliable
|
||||
Direction orientation = BlockStateValues.getPistonOrientation(pistonBlockId);
|
||||
Direction orientation = BlockState.of(pistonBlockId).getValue(Properties.FACING);
|
||||
|
||||
session.executeInEventLoop(() -> {
|
||||
PistonCache pistonCache = session.getPistonCache();
|
||||
|
@ -42,7 +42,6 @@ import org.geysermc.erosion.bukkit.SchedulerUtils;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.level.GameRule;
|
||||
import org.geysermc.geyser.level.WorldManager;
|
||||
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;
|
||||
@ -88,7 +87,7 @@ public class GeyserSpigotWorldManager extends WorldManager {
|
||||
Bukkit.getRegionScheduler().execute(this.plugin, block.getLocation(), () -> blockData.complete(block.getBlockData().getAsString()));
|
||||
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(), org.geysermc.geyser.level.block.type.Block.JAVA_AIR_ID);
|
||||
return BlockRegistries.JAVA_IDENTIFIER_TO_ID.getOrDefault(block.getBlockData().getAsString(), org.geysermc.geyser.level.block.type.Block.JAVA_AIR_ID); // TODO could just make this a BlockState lookup?
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -235,7 +235,7 @@ public final class EntityDefinitions {
|
||||
.addTranslator(MetadataType.BOOLEAN,
|
||||
(enderCrystalEntity, entityMetadata) -> enderCrystalEntity.setFlag(EntityFlag.SHOW_BOTTOM, ((BooleanEntityMetadata) entityMetadata).getPrimitiveValue())) // There is a base located on the ender crystal
|
||||
.build();
|
||||
EXPERIENCE_ORB = EntityDefinition.<ExpOrbEntity>inherited(null, entityBase)
|
||||
EXPERIENCE_ORB = EntityDefinition.inherited(ExpOrbEntity::new, entityBase)
|
||||
.type(EntityType.EXPERIENCE_ORB)
|
||||
.identifier("minecraft:xp_orb")
|
||||
.build();
|
||||
@ -297,6 +297,7 @@ public final class EntityDefinitions {
|
||||
TNT = EntityDefinition.inherited(TNTEntity::new, entityBase)
|
||||
.type(EntityType.TNT)
|
||||
.heightAndWidth(0.98f)
|
||||
.offset(0.49f)
|
||||
.addTranslator(MetadataType.INT, TNTEntity::setFuseLength)
|
||||
.build();
|
||||
|
||||
|
@ -60,6 +60,9 @@ import java.util.*;
|
||||
@Getter
|
||||
@Setter
|
||||
public class Entity implements GeyserEntity {
|
||||
|
||||
private static final boolean PRINT_ENTITY_SPAWN_DEBUG = Boolean.parseBoolean(System.getProperty("Geyser.PrintEntitySpawnDebug", "false"));
|
||||
|
||||
protected final GeyserSession session;
|
||||
|
||||
protected int entityId;
|
||||
@ -182,7 +185,7 @@ public class Entity implements GeyserEntity {
|
||||
|
||||
flagsDirty = false;
|
||||
|
||||
if (session.getGeyser().getConfig().isDebugMode()) {
|
||||
if (session.getGeyser().getConfig().isDebugMode() && PRINT_ENTITY_SPAWN_DEBUG) {
|
||||
EntityType type = definition.entityType();
|
||||
String name = type != null ? type.name() : getClass().getSimpleName();
|
||||
session.getGeyser().getLogger().debug("Spawned entity " + name + " at location " + position + " with id " + geyserId + " (java id " + entityId + ")");
|
||||
|
@ -27,11 +27,18 @@ package org.geysermc.geyser.entity.type;
|
||||
|
||||
import org.cloudburstmc.math.vector.Vector3f;
|
||||
import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
|
||||
import org.geysermc.geyser.entity.EntityDefinition;
|
||||
import org.geysermc.geyser.entity.EntityDefinitions;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class ExpOrbEntity extends Entity {
|
||||
|
||||
public ExpOrbEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, EntityDefinition<?> entityDefinition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
this(session, 1, entityId, geyserId, position);
|
||||
}
|
||||
|
||||
public ExpOrbEntity(GeyserSession session, int amount, int entityId, long geyserId, Vector3f position) {
|
||||
super(session, entityId, geyserId, null, EntityDefinitions.EXPERIENCE_ORB, position, Vector3f.ZERO, 0, 0, 0);
|
||||
|
||||
|
@ -28,7 +28,9 @@ package org.geysermc.geyser.entity.type;
|
||||
import org.cloudburstmc.math.vector.Vector3f;
|
||||
import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
|
||||
import org.geysermc.geyser.entity.EntityDefinition;
|
||||
import org.geysermc.geyser.level.block.type.FurnaceBlock;
|
||||
import org.geysermc.geyser.level.block.Blocks;
|
||||
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.util.InteractionResult;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.BooleanEntityMetadata;
|
||||
@ -51,7 +53,8 @@ public class FurnaceMinecartEntity extends DefaultBlockMinecartEntity {
|
||||
|
||||
@Override
|
||||
public void updateDefaultBlockMetadata() {
|
||||
dirtyMetadata.put(EntityDataTypes.DISPLAY_BLOCK_STATE, session.getBlockMappings().getBedrockBlock(FurnaceBlock.state(hasFuel)));
|
||||
BlockState furnace = Blocks.FURNACE.defaultBlockState().withValue(Properties.LIT, hasFuel);
|
||||
dirtyMetadata.put(EntityDataTypes.DISPLAY_BLOCK_STATE, session.getBlockMappings().getBedrockBlock(furnace));
|
||||
dirtyMetadata.put(EntityDataTypes.DISPLAY_OFFSET, 6);
|
||||
}
|
||||
|
||||
|
@ -28,7 +28,7 @@ package org.geysermc.geyser.entity.type;
|
||||
import org.cloudburstmc.math.vector.Vector3f;
|
||||
import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
|
||||
import org.geysermc.geyser.entity.EntityDefinition;
|
||||
import org.geysermc.geyser.level.block.type.SpawnerBlock;
|
||||
import org.geysermc.geyser.level.block.Blocks;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
|
||||
import java.util.UUID;
|
||||
@ -41,7 +41,7 @@ public class SpawnerMinecartEntity extends DefaultBlockMinecartEntity {
|
||||
|
||||
@Override
|
||||
public void updateDefaultBlockMetadata() {
|
||||
dirtyMetadata.put(EntityDataTypes.DISPLAY_BLOCK_STATE, session.getBlockMappings().getBedrockBlock(SpawnerBlock.state()));
|
||||
dirtyMetadata.put(EntityDataTypes.DISPLAY_BLOCK_STATE, session.getBlockMappings().getBedrockBlock(Blocks.SPAWNER.defaultBlockState()));
|
||||
dirtyMetadata.put(EntityDataTypes.DISPLAY_OFFSET, 6);
|
||||
}
|
||||
}
|
||||
|
@ -39,7 +39,17 @@ public class TNTEntity extends Entity implements Tickable {
|
||||
private int currentTick;
|
||||
|
||||
public TNTEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
|
||||
super(session, entityId, geyserId, uuid, definition, position.add(0, definition.offset(), 0), motion, yaw, pitch, headYaw);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void moveRelative(double relX, double relY, double relZ, float yaw, float pitch, boolean isOnGround) {
|
||||
super.moveRelative(relX, relY + definition.offset(), relZ, yaw, pitch, isOnGround);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void moveAbsolute(Vector3f position, float yaw, float pitch, float headYaw, boolean isOnGround, boolean teleported) {
|
||||
super.moveAbsolute(position.add(Vector3f.from(0, definition.offset(), 0)), yaw, pitch, headYaw, isOnGround, teleported);
|
||||
}
|
||||
|
||||
public void setFuseLength(IntEntityMetadata entityMetadata) {
|
||||
|
@ -41,6 +41,7 @@ import org.cloudburstmc.protocol.bedrock.data.command.CommandPermission;
|
||||
import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
|
||||
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
|
||||
import org.cloudburstmc.protocol.bedrock.data.entity.EntityLinkData;
|
||||
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.*;
|
||||
import org.geysermc.geyser.api.entity.type.player.GeyserPlayerEntity;
|
||||
import org.geysermc.geyser.entity.EntityDefinitions;
|
||||
@ -166,6 +167,31 @@ public class PlayerEntity extends LivingEntity implements GeyserPlayerEntity {
|
||||
session.sendUpstreamPacket(addPlayerPacket);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void despawnEntity() {
|
||||
super.despawnEntity();
|
||||
|
||||
// Since we re-use player entities: Clear flags, held item, etc
|
||||
this.resetMetadata();
|
||||
this.hand = ItemData.AIR;
|
||||
this.offhand = ItemData.AIR;
|
||||
this.boots = ItemData.AIR;
|
||||
this.leggings = ItemData.AIR;
|
||||
this.chestplate = ItemData.AIR;
|
||||
this.helmet = ItemData.AIR;
|
||||
}
|
||||
|
||||
public void resetMetadata() {
|
||||
// Reset all metadata to their default values
|
||||
// This is used when a player respawns
|
||||
this.flags.clear();
|
||||
this.initializeMetadata();
|
||||
|
||||
// Explicitly reset all metadata not handled by initializeMetadata
|
||||
setParrot(null, true);
|
||||
setParrot(null, false);
|
||||
}
|
||||
|
||||
public void sendPlayer() {
|
||||
if (session.getEntityCache().getPlayerEntity(uuid) == null)
|
||||
return;
|
||||
|
@ -33,7 +33,6 @@ import org.cloudburstmc.math.vector.Vector2f;
|
||||
import org.cloudburstmc.math.vector.Vector3f;
|
||||
import org.cloudburstmc.protocol.bedrock.data.AttributeData;
|
||||
import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
|
||||
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.UpdateAttributesPacket;
|
||||
import org.geysermc.geyser.entity.attribute.GeyserAttributeType;
|
||||
import org.geysermc.geyser.item.Items;
|
||||
@ -62,10 +61,6 @@ public class SessionPlayerEntity extends PlayerEntity {
|
||||
*/
|
||||
@Getter
|
||||
protected final Map<GeyserAttributeType, AttributeData> attributes = new Object2ObjectOpenHashMap<>();
|
||||
/**
|
||||
* Whether to check for updated speed after all entity metadata has been processed
|
||||
*/
|
||||
private boolean refreshSpeed = false;
|
||||
/**
|
||||
* Used in PlayerInputTranslator for movement checks.
|
||||
*/
|
||||
@ -134,9 +129,7 @@ public class SessionPlayerEntity extends PlayerEntity {
|
||||
// TODO: proper fix, BDS somehow does it? https://paste.gg/p/anonymous/3adfb7612f1540be80fa03a2281f93dc (BDS 1.20.13)
|
||||
if (!this.session.getGameMode().equals(GameMode.SPECTATOR)) {
|
||||
super.setFlags(entityMetadata);
|
||||
session.setSwimmingInWater((entityMetadata.getPrimitiveValue() & 0x10) == 0x10 && getFlag(EntityFlag.SPRINTING));
|
||||
}
|
||||
refreshSpeed = true;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -164,7 +157,6 @@ public class SessionPlayerEntity extends PlayerEntity {
|
||||
public void setPose(Pose pose) {
|
||||
super.setPose(pose);
|
||||
session.setPose(pose);
|
||||
refreshSpeed = true;
|
||||
}
|
||||
|
||||
public float getMaxHealth() {
|
||||
@ -213,21 +205,6 @@ public class SessionPlayerEntity extends PlayerEntity {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateBedrockMetadata() {
|
||||
super.updateBedrockMetadata();
|
||||
if (refreshSpeed) {
|
||||
AttributeData speedAttribute = session.adjustSpeed();
|
||||
if (speedAttribute != null) {
|
||||
UpdateAttributesPacket attributesPacket = new UpdateAttributesPacket();
|
||||
attributesPacket.setRuntimeEntityId(geyserId);
|
||||
attributesPacket.setAttributes(Collections.singletonList(speedAttribute));
|
||||
session.sendUpstreamPacket(attributesPacket);
|
||||
}
|
||||
refreshSpeed = false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateAttribute(Attribute javaAttribute, List<AttributeData> newAttributes) {
|
||||
if (javaAttribute.getType() == AttributeType.Builtin.GENERIC_ATTACK_SPEED) {
|
||||
@ -240,17 +217,6 @@ public class SessionPlayerEntity extends PlayerEntity {
|
||||
@Override
|
||||
protected AttributeData calculateAttribute(Attribute javaAttribute, GeyserAttributeType type) {
|
||||
AttributeData attributeData = super.calculateAttribute(javaAttribute, type);
|
||||
|
||||
if (javaAttribute.getType() == AttributeType.Builtin.GENERIC_MOVEMENT_SPEED) {
|
||||
session.setOriginalSpeedAttribute(attributeData.getValue());
|
||||
AttributeData speedAttribute = session.adjustSpeed();
|
||||
if (speedAttribute != null) {
|
||||
// Overwrite the attribute with our own
|
||||
this.attributes.put(type, speedAttribute);
|
||||
return speedAttribute;
|
||||
}
|
||||
}
|
||||
|
||||
this.attributes.put(type, attributeData);
|
||||
return attributeData;
|
||||
}
|
||||
@ -278,19 +244,13 @@ public class SessionPlayerEntity extends PlayerEntity {
|
||||
super.setAbsorptionHearts(entityMetadata);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetMetadata() {
|
||||
// Reset all metadata to their default values
|
||||
// This is used when a player respawns
|
||||
this.flags.clear();
|
||||
this.initializeMetadata();
|
||||
super.resetMetadata();
|
||||
|
||||
// Reset air
|
||||
this.resetAir();
|
||||
|
||||
// Explicitly reset all metadata not handled by initializeMetadata
|
||||
setParrot(null, true);
|
||||
setParrot(null, false);
|
||||
|
||||
// Absorption is metadata in java edition
|
||||
attributes.remove(GeyserAttributeType.ABSORPTION);
|
||||
UpdateAttributesPacket attributesPacket = new UpdateAttributesPacket();
|
||||
|
@ -44,6 +44,7 @@ import org.geysermc.erosion.packet.backendbound.BackendboundInitializePacket;
|
||||
import org.geysermc.erosion.packet.backendbound.BackendboundPacket;
|
||||
import org.geysermc.erosion.packet.geyserbound.*;
|
||||
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.physics.Direction;
|
||||
@ -148,7 +149,7 @@ public final class GeyserboundPacketHandlerImpl extends AbstractGeyserboundPacke
|
||||
|
||||
@Override
|
||||
public void handlePistonEvent(GeyserboundPistonEventPacket packet) {
|
||||
Direction orientation = BlockStateValues.getPistonOrientation(packet.getBlockId());
|
||||
Direction orientation = BlockState.of(packet.getBlockId()).getValue(Properties.FACING);
|
||||
Vector3i position = packet.getPos();
|
||||
boolean isExtend = packet.isExtend();
|
||||
|
||||
|
@ -41,7 +41,6 @@ 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.inventory.InventoryTranslator;
|
||||
import org.geysermc.geyser.util.BlockUtils;
|
||||
import org.geysermc.geyser.util.InventoryUtils;
|
||||
|
||||
import java.util.Collections;
|
||||
@ -56,22 +55,24 @@ public class BlockInventoryHolder extends InventoryHolder {
|
||||
/**
|
||||
* The default Java block ID to translate as a fake block
|
||||
*/
|
||||
private final int defaultJavaBlockState;
|
||||
private final BlockState defaultJavaBlockState;
|
||||
private final ContainerType containerType;
|
||||
private final Set<String> validBlocks;
|
||||
private final Set<Block> validBlocks;
|
||||
|
||||
public BlockInventoryHolder(String javaBlockIdentifier, ContainerType containerType, Block... validBlocks) {
|
||||
this.defaultJavaBlockState = BlockRegistries.JAVA_IDENTIFIER_TO_ID.get().getInt(javaBlockIdentifier);
|
||||
public BlockInventoryHolder(Block defaultJavaBlock, ContainerType containerType, Block... validBlocks) {
|
||||
this(defaultJavaBlock.defaultBlockState(), containerType, validBlocks);
|
||||
}
|
||||
|
||||
public BlockInventoryHolder(BlockState defaultJavaBlockState, ContainerType containerType, Block... validBlocks) {
|
||||
this.defaultJavaBlockState = defaultJavaBlockState;
|
||||
this.containerType = containerType;
|
||||
if (validBlocks != null) {
|
||||
Set<String> validBlocksTemp = new HashSet<>(validBlocks.length + 1);
|
||||
for (Block block : validBlocks) {
|
||||
validBlocksTemp.add(block.javaIdentifier().toString());
|
||||
}
|
||||
validBlocksTemp.add(BlockUtils.getCleanIdentifier(javaBlockIdentifier));
|
||||
Set<Block> validBlocksTemp = new HashSet<>(validBlocks.length + 1);
|
||||
Collections.addAll(validBlocksTemp, validBlocks);
|
||||
validBlocksTemp.add(defaultJavaBlockState.block());
|
||||
this.validBlocks = Set.copyOf(validBlocksTemp);
|
||||
} else {
|
||||
this.validBlocks = Collections.singleton(BlockUtils.getCleanIdentifier(javaBlockIdentifier));
|
||||
this.validBlocks = Collections.singleton(defaultJavaBlockState.block());
|
||||
}
|
||||
}
|
||||
|
||||
@ -85,9 +86,7 @@ public class BlockInventoryHolder extends InventoryHolder {
|
||||
// and the bedrock block is vanilla
|
||||
BlockState state = session.getGeyser().getWorldManager().blockAt(session, session.getLastInteractionBlockPosition());
|
||||
if (!BlockRegistries.CUSTOM_BLOCK_STATE_OVERRIDES.get().containsKey(state.javaId())) {
|
||||
// TODO TODO TODO
|
||||
String[] javaBlockString = state.toString().split("\\[");
|
||||
if (isValidBlock(javaBlockString)) {
|
||||
if (isValidBlock(state)) {
|
||||
// We can safely use this block
|
||||
inventory.setHolderPosition(session.getLastInteractionBlockPosition());
|
||||
((Container) inventory).setUsingRealBlock(true, state.block());
|
||||
@ -111,7 +110,7 @@ public class BlockInventoryHolder extends InventoryHolder {
|
||||
session.sendUpstreamPacket(blockPacket);
|
||||
inventory.setHolderPosition(position);
|
||||
|
||||
setCustomName(session, position, inventory, BlockState.of(defaultJavaBlockState));
|
||||
setCustomName(session, position, inventory, defaultJavaBlockState);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -129,8 +128,8 @@ public class BlockInventoryHolder extends InventoryHolder {
|
||||
/**
|
||||
* @return true if this Java block ID can be used for player inventory.
|
||||
*/
|
||||
protected boolean isValidBlock(String[] javaBlockString) {
|
||||
return this.validBlocks.contains(javaBlockString[0]);
|
||||
protected boolean isValidBlock(BlockState blockState) {
|
||||
return this.validBlocks.contains(blockState.block());
|
||||
}
|
||||
|
||||
protected void setCustomName(GeyserSession session, Vector3i position, Inventory inventory, BlockState javaBlockState) {
|
||||
|
@ -25,116 +25,19 @@
|
||||
|
||||
package org.geysermc.geyser.level.block;
|
||||
|
||||
import it.unimi.dsi.fastutil.ints.*;
|
||||
import it.unimi.dsi.fastutil.objects.Object2IntMap;
|
||||
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
|
||||
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.block.type.PistonBlock;
|
||||
import org.geysermc.geyser.level.physics.Direction;
|
||||
import org.geysermc.geyser.level.physics.PistonBehavior;
|
||||
import org.geysermc.geyser.registry.BlockRegistries;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* Used for block entities if the Java block state contains Bedrock block information.
|
||||
*/
|
||||
public final class BlockStateValues {
|
||||
private static final IntSet HORIZONTAL_FACING_JIGSAWS = new IntOpenHashSet();
|
||||
private static final IntSet STICKY_PISTONS = new IntOpenHashSet();
|
||||
private static final Object2IntMap<Direction> PISTON_HEADS = new Object2IntOpenHashMap<>();
|
||||
private static final Int2ObjectMap<Direction> PISTON_ORIENTATION = new Int2ObjectOpenHashMap<>();
|
||||
private static final IntSet ALL_PISTON_HEADS = new IntOpenHashSet();
|
||||
private static final Int2IntMap WATER_LEVEL = new Int2IntOpenHashMap();
|
||||
private static final Int2IntMap LAVA_LEVEL = new Int2IntOpenHashMap();
|
||||
|
||||
public static int JAVA_WATER_ID;
|
||||
|
||||
public static final int NUM_FLUID_LEVELS = 9;
|
||||
|
||||
/**
|
||||
* Determines if the block state contains Bedrock block information
|
||||
*
|
||||
* @param javaId The Java Identifier of the block
|
||||
* @param javaBlockState the Java Block State of the block
|
||||
*/
|
||||
public static void storeBlockStateValues(String javaId, int javaBlockState) {
|
||||
if (javaId.contains("piston[")) { // minecraft:moving_piston, minecraft:sticky_piston, minecraft:piston
|
||||
if (javaId.contains("sticky")) {
|
||||
STICKY_PISTONS.add(javaBlockState);
|
||||
}
|
||||
PISTON_ORIENTATION.put(javaBlockState, getBlockDirection(javaId));
|
||||
return;
|
||||
} else if (javaId.startsWith("minecraft:piston_head")) {
|
||||
ALL_PISTON_HEADS.add(javaBlockState);
|
||||
if (javaId.contains("short=false")) {
|
||||
PISTON_HEADS.put(getBlockDirection(javaId), javaBlockState);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (javaId.startsWith("minecraft:water") && !javaId.contains("cauldron")) {
|
||||
String strLevel = javaId.substring(javaId.lastIndexOf("level=") + 6, javaId.length() - 1);
|
||||
int level = Integer.parseInt(strLevel);
|
||||
WATER_LEVEL.put(javaBlockState, level);
|
||||
return;
|
||||
}
|
||||
|
||||
if (javaId.startsWith("minecraft:lava") && !javaId.contains("cauldron")) {
|
||||
String strLevel = javaId.substring(javaId.lastIndexOf("level=") + 6, javaId.length() - 1);
|
||||
int level = Integer.parseInt(strLevel);
|
||||
LAVA_LEVEL.put(javaBlockState, level);
|
||||
return;
|
||||
}
|
||||
|
||||
if (javaId.startsWith("minecraft:jigsaw[orientation=")) {
|
||||
String blockStateData = javaId.substring(javaId.indexOf("orientation=") + "orientation=".length(), javaId.lastIndexOf('_'));
|
||||
Direction direction = Direction.valueOf(blockStateData.toUpperCase(Locale.ROOT));
|
||||
if (direction.isHorizontal()) {
|
||||
HORIZONTAL_FACING_JIGSAWS.add(javaBlockState);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a set of all forward-facing jigsaws, to use as a fallback if NBT is missing.
|
||||
*/
|
||||
public static IntSet getHorizontalFacingJigsaws() {
|
||||
return HORIZONTAL_FACING_JIGSAWS;
|
||||
}
|
||||
|
||||
public static boolean isStickyPiston(int blockState) {
|
||||
return STICKY_PISTONS.contains(blockState);
|
||||
}
|
||||
|
||||
public static boolean isPistonHead(int state) {
|
||||
return ALL_PISTON_HEADS.contains(state);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Java Block State for a piston head for a specific direction
|
||||
* This is used in PistonBlockEntity to get the BlockCollision for the piston head.
|
||||
*
|
||||
* @param direction Direction the piston head points in
|
||||
* @return Block state for the piston head
|
||||
*/
|
||||
public static int getPistonHead(Direction direction) {
|
||||
return PISTON_HEADS.getOrDefault(direction, Block.JAVA_AIR_ID);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is used in GeyserPistonEvents.java and accepts minecraft:piston,
|
||||
* minecraft:sticky_piston, and minecraft:moving_piston.
|
||||
*
|
||||
* @param state The block state of the piston base
|
||||
* @return The direction in which the piston faces
|
||||
*/
|
||||
public static Direction getPistonOrientation(int state) {
|
||||
return PISTON_ORIENTATION.get(state);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a block sticks to other blocks
|
||||
* (Slime and honey blocks)
|
||||
@ -203,11 +106,12 @@ public final class BlockStateValues {
|
||||
* @return The type of fluid
|
||||
*/
|
||||
public static Fluid getFluid(int state) {
|
||||
if (WATER_LEVEL.containsKey(state) || BlockRegistries.WATERLOGGED.get().get(state)) {
|
||||
BlockState blockState = BlockState.of(state);
|
||||
if (blockState.is(Blocks.WATER) || BlockRegistries.WATERLOGGED.get().get(state)) {
|
||||
return Fluid.WATER;
|
||||
}
|
||||
|
||||
if (LAVA_LEVEL.containsKey(state)) {
|
||||
if (blockState.is(Blocks.LAVA)) {
|
||||
return Fluid.LAVA;
|
||||
}
|
||||
|
||||
@ -221,7 +125,11 @@ public final class BlockStateValues {
|
||||
* @return The water level or -1 if the block isn't water
|
||||
*/
|
||||
public static int getWaterLevel(int state) {
|
||||
return WATER_LEVEL.getOrDefault(state, -1);
|
||||
BlockState blockState = BlockState.of(state);
|
||||
if (!blockState.is(Blocks.WATER)) {
|
||||
return -1;
|
||||
}
|
||||
return blockState.getValue(Properties.LEVEL);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -255,7 +163,11 @@ public final class BlockStateValues {
|
||||
* @return The lava level or -1 if the block isn't lava
|
||||
*/
|
||||
public static int getLavaLevel(int state) {
|
||||
return LAVA_LEVEL.getOrDefault(state, -1);
|
||||
BlockState blockState = BlockState.of(state);
|
||||
if (!blockState.is(Blocks.LAVA)) {
|
||||
return -1;
|
||||
}
|
||||
return blockState.getValue(Properties.LEVEL);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -298,23 +210,6 @@ public final class BlockStateValues {
|
||||
return 0.6f;
|
||||
}
|
||||
|
||||
private static Direction getBlockDirection(String javaId) {
|
||||
if (javaId.contains("down")) {
|
||||
return Direction.DOWN;
|
||||
} else if (javaId.contains("up")) {
|
||||
return Direction.UP;
|
||||
} else if (javaId.contains("south")) {
|
||||
return Direction.SOUTH;
|
||||
} else if (javaId.contains("west")) {
|
||||
return Direction.WEST;
|
||||
} else if (javaId.contains("north")) {
|
||||
return Direction.NORTH;
|
||||
} else if (javaId.contains("east")) {
|
||||
return Direction.EAST;
|
||||
}
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
private BlockStateValues() {
|
||||
}
|
||||
}
|
||||
|
Datei-Diff unterdrückt, da er zu groß ist
Diff laden
@ -0,0 +1,63 @@
|
||||
/*
|
||||
* 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 java.util.List;
|
||||
|
||||
/**
|
||||
* Represents enums we don't need classes for in Geyser.
|
||||
*/
|
||||
public final class BasicEnumProperty extends Property<String> {
|
||||
private final List<String> values;
|
||||
|
||||
private BasicEnumProperty(String name, List<String> values) {
|
||||
super(name);
|
||||
this.values = values;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int valuesCount() {
|
||||
return this.values.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int indexOf(String value) {
|
||||
int index = this.values.indexOf(value);
|
||||
if (index == -1) {
|
||||
throw new IllegalStateException("Property " + this + " does not have value " + value);
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T values() {
|
||||
return (T) this.values;
|
||||
}
|
||||
|
||||
public static BasicEnumProperty create(String name, String... values) {
|
||||
return new BasicEnumProperty(name, List.of(values));
|
||||
}
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* 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 final class BooleanProperty extends Property<Boolean> {
|
||||
private BooleanProperty(String name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int valuesCount() {
|
||||
return 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int indexOf(Boolean value) {
|
||||
return value ? 0 : 1;
|
||||
}
|
||||
|
||||
public static BooleanProperty create(String name) {
|
||||
return new BooleanProperty(name);
|
||||
}
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* 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 it.unimi.dsi.fastutil.ints.IntArrayList;
|
||||
import it.unimi.dsi.fastutil.ints.IntList;
|
||||
|
||||
public final class EnumProperty<T extends Enum<T>> extends Property<T> {
|
||||
private final IntList ordinalValues;
|
||||
|
||||
/**
|
||||
* @param values all possible values of this enum.
|
||||
*/
|
||||
private EnumProperty(String name, T[] values) {
|
||||
super(name);
|
||||
this.ordinalValues = new IntArrayList(values.length);
|
||||
for (T anEnum : values) {
|
||||
this.ordinalValues.add(anEnum.ordinal());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int valuesCount() {
|
||||
return this.ordinalValues.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int indexOf(T value) {
|
||||
return this.ordinalValues.indexOf(value.ordinal());
|
||||
}
|
||||
|
||||
@SafeVarargs
|
||||
public static <T extends Enum<T>> EnumProperty<T> create(String name, T... values) {
|
||||
return new EnumProperty<>(name, values);
|
||||
}
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
/*
|
||||
* 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.Direction;
|
||||
|
||||
public enum FrontAndTop {
|
||||
DOWN_EAST(Direction.DOWN),
|
||||
DOWN_NORTH(Direction.DOWN),
|
||||
DOWN_SOUTH(Direction.DOWN),
|
||||
DOWN_WEST(Direction.DOWN),
|
||||
UP_EAST(Direction.UP),
|
||||
UP_NORTH(Direction.UP),
|
||||
UP_SOUTH(Direction.UP),
|
||||
UP_WEST(Direction.UP),
|
||||
WEST_UP(Direction.WEST),
|
||||
EAST_UP(Direction.EAST),
|
||||
NORTH_UP(Direction.NORTH),
|
||||
SOUTH_UP(Direction.SOUTH);
|
||||
|
||||
private final boolean horizontal;
|
||||
|
||||
FrontAndTop(Direction front) {
|
||||
this.horizontal = front.isHorizontal();
|
||||
}
|
||||
|
||||
public boolean isHorizontal() {
|
||||
return horizontal;
|
||||
}
|
||||
|
||||
public static final FrontAndTop[] VALUES = values();
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* 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 final class IntegerProperty extends Property<Integer> {
|
||||
private final int offset;
|
||||
private final int valuesCount;
|
||||
|
||||
private IntegerProperty(String name, int low, int high) {
|
||||
super(name);
|
||||
this.offset = low;
|
||||
this.valuesCount = high - low;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int valuesCount() {
|
||||
return this.valuesCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int indexOf(Integer value) {
|
||||
return value - this.offset;
|
||||
}
|
||||
|
||||
public int low() {
|
||||
return this.offset;
|
||||
}
|
||||
|
||||
public int high() {
|
||||
return this.offset + this.valuesCount;
|
||||
}
|
||||
|
||||
public static IntegerProperty create(String name, int low, int high) {
|
||||
return new IntegerProperty(name, low, high);
|
||||
}
|
||||
}
|
@ -29,118 +29,118 @@ 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<ChestType> 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");
|
||||
public static final BooleanProperty ATTACHED = BooleanProperty.create("attached");
|
||||
public static final BooleanProperty BOTTOM = BooleanProperty.create("bottom");
|
||||
public static final BooleanProperty CONDITIONAL = BooleanProperty.create("conditional");
|
||||
public static final BooleanProperty DISARMED = BooleanProperty.create("disarmed");
|
||||
public static final BooleanProperty DRAG = BooleanProperty.create("drag");
|
||||
public static final BooleanProperty ENABLED = BooleanProperty.create("enabled");
|
||||
public static final BooleanProperty EXTENDED = BooleanProperty.create("extended");
|
||||
public static final BooleanProperty EYE = BooleanProperty.create("eye");
|
||||
public static final BooleanProperty FALLING = BooleanProperty.create("falling");
|
||||
public static final BooleanProperty HANGING = BooleanProperty.create("hanging");
|
||||
public static final BooleanProperty HAS_BOTTLE_0 = BooleanProperty.create("has_bottle_0");
|
||||
public static final BooleanProperty HAS_BOTTLE_1 = BooleanProperty.create("has_bottle_1");
|
||||
public static final BooleanProperty HAS_BOTTLE_2 = BooleanProperty.create("has_bottle_2");
|
||||
public static final BooleanProperty HAS_RECORD = BooleanProperty.create("has_record");
|
||||
public static final BooleanProperty HAS_BOOK = BooleanProperty.create("has_book");
|
||||
public static final BooleanProperty INVERTED = BooleanProperty.create("inverted");
|
||||
public static final BooleanProperty IN_WALL = BooleanProperty.create("in_wall");
|
||||
public static final BooleanProperty LIT = BooleanProperty.create("lit");
|
||||
public static final BooleanProperty LOCKED = BooleanProperty.create("locked");
|
||||
public static final BooleanProperty OCCUPIED = BooleanProperty.create("occupied");
|
||||
public static final BooleanProperty OPEN = BooleanProperty.create("open");
|
||||
public static final BooleanProperty PERSISTENT = BooleanProperty.create("persistent");
|
||||
public static final BooleanProperty POWERED = BooleanProperty.create("powered");
|
||||
public static final BooleanProperty SHORT = BooleanProperty.create("short");
|
||||
public static final BooleanProperty SIGNAL_FIRE = BooleanProperty.create("signal_fire");
|
||||
public static final BooleanProperty SNOWY = BooleanProperty.create("snowy");
|
||||
public static final BooleanProperty TRIGGERED = BooleanProperty.create("triggered");
|
||||
public static final BooleanProperty UNSTABLE = BooleanProperty.create("unstable");
|
||||
public static final BooleanProperty WATERLOGGED = BooleanProperty.create("waterlogged");
|
||||
public static final BooleanProperty BERRIES = BooleanProperty.create("berries");
|
||||
public static final BooleanProperty BLOOM = BooleanProperty.create("bloom");
|
||||
public static final BooleanProperty SHRIEKING = BooleanProperty.create("shrieking");
|
||||
public static final BooleanProperty CAN_SUMMON = BooleanProperty.create("can_summon");
|
||||
public static final EnumProperty<Axis> HORIZONTAL_AXIS = EnumProperty.create("axis", Axis.X, Axis.Z);
|
||||
public static final EnumProperty<Axis> AXIS = EnumProperty.create("axis", Axis.VALUES);
|
||||
public static final BooleanProperty UP = BooleanProperty.create("up");
|
||||
public static final BooleanProperty DOWN = BooleanProperty.create("down");
|
||||
public static final BooleanProperty NORTH = BooleanProperty.create("north");
|
||||
public static final BooleanProperty EAST = BooleanProperty.create("east");
|
||||
public static final BooleanProperty SOUTH = BooleanProperty.create("south");
|
||||
public static final BooleanProperty WEST = BooleanProperty.create("west");
|
||||
public static final EnumProperty<Direction> FACING = EnumProperty.create("facing", Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN);
|
||||
public static final EnumProperty<Direction> FACING_HOPPER = EnumProperty.create("facing", Direction.DOWN, Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST);
|
||||
public static final EnumProperty<Direction> HORIZONTAL_FACING = EnumProperty.create("facing", Direction.NORTH, Direction.SOUTH, Direction.WEST, Direction.EAST);
|
||||
public static final IntegerProperty FLOWER_AMOUNT = IntegerProperty.create("flower_amount", 1, 4);
|
||||
public static final EnumProperty<FrontAndTop> ORIENTATION = EnumProperty.create("orientation", FrontAndTop.VALUES);
|
||||
public static final BasicEnumProperty ATTACH_FACE = BasicEnumProperty.create("face", "floor", "wall", "ceiling");
|
||||
public static final BasicEnumProperty BELL_ATTACHMENT = BasicEnumProperty.create("attachment", "floor", "ceiling", "single_wall", "double_wall");
|
||||
public static final BasicEnumProperty EAST_WALL = BasicEnumProperty.create("east", "none", "low", "tall");
|
||||
public static final BasicEnumProperty NORTH_WALL = BasicEnumProperty.create("north", "none", "low", "tall");
|
||||
public static final BasicEnumProperty SOUTH_WALL = BasicEnumProperty.create("south", "none", "low", "tall");
|
||||
public static final BasicEnumProperty WEST_WALL = BasicEnumProperty.create("west", "none", "low", "tall");
|
||||
public static final BasicEnumProperty EAST_REDSTONE = BasicEnumProperty.create("east", "up", "side", "none");
|
||||
public static final BasicEnumProperty NORTH_REDSTONE = BasicEnumProperty.create("north", "up", "side", "none");
|
||||
public static final BasicEnumProperty SOUTH_REDSTONE = BasicEnumProperty.create("south", "up", "side", "none");
|
||||
public static final BasicEnumProperty WEST_REDSTONE = BasicEnumProperty.create("west", "up", "side", "none");
|
||||
public static final BasicEnumProperty DOUBLE_BLOCK_HALF = BasicEnumProperty.create("half", "upper", "lower");
|
||||
public static final BasicEnumProperty HALF = BasicEnumProperty.create("half", "top", "bottom");
|
||||
public static final BasicEnumProperty RAIL_SHAPE = BasicEnumProperty.create("shape", "north_south", "east_west", "ascending_east", "ascending_west", "ascending_north", "ascending_south", "south_east", "south_west", "north_west", "north_east");
|
||||
public static final BasicEnumProperty RAIL_SHAPE_STRAIGHT = BasicEnumProperty.create("shape", "north_south", "east_west", "ascending_east", "ascending_west", "ascending_north", "ascending_south");
|
||||
public static final IntegerProperty AGE_1 = IntegerProperty.create("age", 0, 1);
|
||||
public static final IntegerProperty AGE_2 = IntegerProperty.create("age", 0, 2);
|
||||
public static final IntegerProperty AGE_3 = IntegerProperty.create("age", 0, 3);
|
||||
public static final IntegerProperty AGE_4 = IntegerProperty.create("age", 0, 4);
|
||||
public static final IntegerProperty AGE_5 = IntegerProperty.create("age", 0, 5);
|
||||
public static final IntegerProperty AGE_7 = IntegerProperty.create("age", 0, 7);
|
||||
public static final IntegerProperty AGE_15 = IntegerProperty.create("age", 0, 15);
|
||||
public static final IntegerProperty AGE_25 = IntegerProperty.create("age", 0, 25);
|
||||
public static final IntegerProperty BITES = IntegerProperty.create("bites", 0, 6);
|
||||
public static final IntegerProperty CANDLES = IntegerProperty.create("candles", 1, 4);
|
||||
public static final IntegerProperty DELAY = IntegerProperty.create("delay", 1, 4);
|
||||
public static final IntegerProperty DISTANCE = IntegerProperty.create("distance", 1, 7);
|
||||
public static final IntegerProperty EGGS = IntegerProperty.create("eggs", 1, 4);
|
||||
public static final IntegerProperty HATCH = IntegerProperty.create("hatch", 0, 2);
|
||||
public static final IntegerProperty LAYERS = IntegerProperty.create("layers", 1, 8);
|
||||
public static final IntegerProperty LEVEL_CAULDRON = IntegerProperty.create("level", 1, 3);
|
||||
public static final IntegerProperty LEVEL_COMPOSTER = IntegerProperty.create("level", 0, 8);
|
||||
public static final IntegerProperty LEVEL_FLOWING = IntegerProperty.create("level", 1, 8);
|
||||
public static final IntegerProperty LEVEL_HONEY = IntegerProperty.create("honey_level", 0, 5);
|
||||
public static final IntegerProperty LEVEL = IntegerProperty.create("level", 0, 15);
|
||||
public static final IntegerProperty MOISTURE = IntegerProperty.create("moisture", 0, 7);
|
||||
public static final IntegerProperty NOTE = IntegerProperty.create("note", 0, 24);
|
||||
public static final IntegerProperty PICKLES = IntegerProperty.create("pickles", 1, 4);
|
||||
public static final IntegerProperty POWER = IntegerProperty.create("power", 0, 15);
|
||||
public static final IntegerProperty STAGE = IntegerProperty.create("stage", 0, 1);
|
||||
public static final IntegerProperty STABILITY_DISTANCE = IntegerProperty.create("distance", 0, 7);
|
||||
public static final IntegerProperty RESPAWN_ANCHOR_CHARGES = IntegerProperty.create("charges", 0, 4);
|
||||
public static final IntegerProperty ROTATION_16 = IntegerProperty.create("rotation", 0, 15);
|
||||
public static final BasicEnumProperty BED_PART = BasicEnumProperty.create("part", "head", "foot");
|
||||
public static final EnumProperty<ChestType> CHEST_TYPE = EnumProperty.create("type", ChestType.VALUES);
|
||||
public static final BasicEnumProperty MODE_COMPARATOR = BasicEnumProperty.create("mode", "compare", "subtract");
|
||||
public static final BasicEnumProperty DOOR_HINGE = BasicEnumProperty.create("hinge", "left", "right");
|
||||
public static final BasicEnumProperty NOTEBLOCK_INSTRUMENT = BasicEnumProperty.create("instrument", "harp", "basedrum", "snare", "hat", "bass", "flute", "bell", "guitar", "chime", "xylophone", "iron_xylophone", "cow_bell", "didgeridoo", "bit", "banjo", "pling", "zombie", "skeleton", "creeper", "dragon", "wither_skeleton", "piglin", "custom_head");
|
||||
public static final BasicEnumProperty PISTON_TYPE = BasicEnumProperty.create("type", "normal", "sticky");
|
||||
public static final BasicEnumProperty SLAB_TYPE = BasicEnumProperty.create("type", "top", "bottom", "double");
|
||||
public static final BasicEnumProperty STAIRS_SHAPE = BasicEnumProperty.create("shape", "straight", "inner_left", "inner_right", "outer_left", "outer_right");
|
||||
public static final BasicEnumProperty STRUCTUREBLOCK_MODE = BasicEnumProperty.create("mode", "save", "load", "corner", "data");
|
||||
public static final BasicEnumProperty BAMBOO_LEAVES = BasicEnumProperty.create("leaves", "none", "small", "large");
|
||||
public static final BasicEnumProperty TILT = BasicEnumProperty.create("tilt", "none", "unstable", "partial", "full");
|
||||
public static final EnumProperty<Direction> VERTICAL_DIRECTION = EnumProperty.create("vertical_direction", Direction.UP, Direction.DOWN);
|
||||
public static final BasicEnumProperty DRIPSTONE_THICKNESS = BasicEnumProperty.create("thickness", "tip_merge", "tip", "frustum", "middle", "base");
|
||||
public static final BasicEnumProperty SCULK_SENSOR_PHASE = BasicEnumProperty.create("sculk_sensor_phase", "inactive", "active", "cooldown");
|
||||
public static final BooleanProperty CHISELED_BOOKSHELF_SLOT_0_OCCUPIED = BooleanProperty.create("slot_0_occupied");
|
||||
public static final BooleanProperty CHISELED_BOOKSHELF_SLOT_1_OCCUPIED = BooleanProperty.create("slot_1_occupied");
|
||||
public static final BooleanProperty CHISELED_BOOKSHELF_SLOT_2_OCCUPIED = BooleanProperty.create("slot_2_occupied");
|
||||
public static final BooleanProperty CHISELED_BOOKSHELF_SLOT_3_OCCUPIED = BooleanProperty.create("slot_3_occupied");
|
||||
public static final BooleanProperty CHISELED_BOOKSHELF_SLOT_4_OCCUPIED = BooleanProperty.create("slot_4_occupied");
|
||||
public static final BooleanProperty CHISELED_BOOKSHELF_SLOT_5_OCCUPIED = BooleanProperty.create("slot_5_occupied");
|
||||
public static final IntegerProperty DUSTED = IntegerProperty.create("dusted", 0, 3);
|
||||
public static final BooleanProperty CRACKED = BooleanProperty.create("cracked");
|
||||
public static final BooleanProperty CRAFTING = BooleanProperty.create("crafting");
|
||||
public static final BasicEnumProperty TRIAL_SPAWNER_STATE = BasicEnumProperty.create("trial_spawner_state", "inactive", "waiting_for_players", "active", "waiting_for_reward_ejection", "ejecting_reward", "cooldown");
|
||||
public static final BasicEnumProperty VAULT_STATE = BasicEnumProperty.create("vault_state", "inactive", "active", "unlocking", "ejecting");
|
||||
public static final BooleanProperty OMINOUS = BooleanProperty.create("ominous");
|
||||
}
|
||||
|
@ -25,10 +25,10 @@
|
||||
|
||||
package org.geysermc.geyser.level.block.property;
|
||||
|
||||
public class Property<T extends Comparable<T>> {
|
||||
public abstract class Property<T extends Comparable<T>> {
|
||||
private final String name;
|
||||
|
||||
public Property(String name) {
|
||||
protected Property(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@ -36,12 +36,12 @@ public class Property<T extends Comparable<T>> {
|
||||
return name;
|
||||
}
|
||||
|
||||
public abstract int valuesCount();
|
||||
|
||||
public abstract int indexOf(T value);
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getClass().getSimpleName() + "[" + name + "]";
|
||||
}
|
||||
|
||||
public static <T extends Comparable<T>> Property<T> create(String name) {
|
||||
return new Property<>(name);
|
||||
}
|
||||
}
|
||||
|
@ -27,9 +27,6 @@ package org.geysermc.geyser.level.block.type;
|
||||
|
||||
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 it.unimi.dsi.fastutil.objects.Reference2ObjectMaps;
|
||||
import net.kyori.adventure.key.Key;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.cloudburstmc.math.vector.Vector3i;
|
||||
@ -37,6 +34,8 @@ import org.cloudburstmc.protocol.bedrock.data.definitions.BlockDefinition;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.UpdateBlockPacket;
|
||||
import org.geysermc.geyser.item.type.Item;
|
||||
import org.geysermc.geyser.level.block.Blocks;
|
||||
import org.geysermc.geyser.level.block.property.BasicEnumProperty;
|
||||
import org.geysermc.geyser.level.block.property.IntegerProperty;
|
||||
import org.geysermc.geyser.level.block.property.Property;
|
||||
import org.geysermc.geyser.level.physics.PistonBehavior;
|
||||
import org.geysermc.geyser.registry.BlockRegistries;
|
||||
@ -67,6 +66,12 @@ public class Block {
|
||||
protected Item item = null;
|
||||
private int javaId = -1;
|
||||
|
||||
/**
|
||||
* Used for switching a given block state to different states.
|
||||
*/
|
||||
private final Property<?>[] propertyKeys;
|
||||
private final BlockState defaultState;
|
||||
|
||||
public Block(@Subst("empty") String javaIdentifier, Builder builder) {
|
||||
this.javaIdentifier = Key.key(javaIdentifier);
|
||||
this.requiresCorrectToolForDrops = builder.requiresCorrectToolForDrops;
|
||||
@ -74,7 +79,10 @@ public class Block {
|
||||
this.destroyTime = builder.destroyTime;
|
||||
this.pushReaction = builder.pushReaction;
|
||||
this.pickItem = builder.pickItem;
|
||||
processStates(builder.build(this));
|
||||
|
||||
BlockState firstState = builder.build(this).get(0);
|
||||
this.propertyKeys = builder.propertyKeys; // Ensure this is not null before iterating over states
|
||||
this.defaultState = setDefaultState(firstState);
|
||||
}
|
||||
|
||||
public void updateBlock(GeyserSession session, BlockState state, Vector3i position) {
|
||||
@ -167,9 +175,11 @@ public class Block {
|
||||
}
|
||||
|
||||
/**
|
||||
* A list of BlockStates is created pertaining to this block. Do we need any of them? If so, override this method.
|
||||
* Should only be ran on block creation. Can be overridden.
|
||||
* @param firstState the first state created from this block
|
||||
*/
|
||||
protected void processStates(List<BlockState> states) {
|
||||
protected BlockState setDefaultState(BlockState firstState) {
|
||||
return firstState;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@ -194,6 +204,10 @@ public class Block {
|
||||
return this.pushReaction;
|
||||
}
|
||||
|
||||
public BlockState defaultBlockState() {
|
||||
return this.defaultState;
|
||||
}
|
||||
|
||||
public int javaId() {
|
||||
return javaId;
|
||||
}
|
||||
@ -213,6 +227,10 @@ public class Block {
|
||||
'}';
|
||||
}
|
||||
|
||||
Property<?>[] propertyKeys() {
|
||||
return propertyKeys;
|
||||
}
|
||||
|
||||
public static Builder builder() {
|
||||
return new Builder();
|
||||
}
|
||||
@ -225,11 +243,14 @@ public class Block {
|
||||
private float destroyTime;
|
||||
private Supplier<Item> pickItem;
|
||||
|
||||
// We'll use this field after building
|
||||
private Property<?>[] propertyKeys;
|
||||
|
||||
/**
|
||||
* 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));
|
||||
public Builder enumState(BasicEnumProperty property) {
|
||||
states.put(property, property.values());
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -244,7 +265,9 @@ public class Block {
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder intState(Property<Integer> property, int low, int high) {
|
||||
public Builder intState(IntegerProperty property) {
|
||||
int low = property.low();
|
||||
int high = property.high();
|
||||
IntList list = new IntArrayList();
|
||||
// There is a state for every number between the low and high.
|
||||
for (int i = low; i <= high; i++) {
|
||||
@ -283,17 +306,18 @@ public class Block {
|
||||
if (states.isEmpty()) {
|
||||
BlockState state = new BlockState(block, BlockRegistries.BLOCK_STATES.get().size());
|
||||
BlockRegistries.BLOCK_STATES.get().add(state);
|
||||
propertyKeys = null;
|
||||
return List.of(state);
|
||||
} else if (states.size() == 1) {
|
||||
// We can optimize because we don't need to worry about combinations
|
||||
Map.Entry<Property<?>, List<Comparable<?>>> property = this.states.entrySet().stream().findFirst().orElseThrow();
|
||||
List<BlockState> states = new ArrayList<>(property.getValue().size());
|
||||
property.getValue().forEach(value -> {
|
||||
Reference2ObjectMap<Property<?>, Comparable<?>> propertyMap = Reference2ObjectMaps.singleton(property.getKey(), value);
|
||||
BlockState state = new BlockState(block, BlockRegistries.BLOCK_STATES.get().size(), propertyMap);
|
||||
BlockState state = new BlockState(block, BlockRegistries.BLOCK_STATES.get().size(), new Comparable[] {value});
|
||||
BlockRegistries.BLOCK_STATES.get().add(state);
|
||||
states.add(state);
|
||||
});
|
||||
this.propertyKeys = new Property[]{property.getKey()};
|
||||
return states;
|
||||
} else {
|
||||
// Think of this stream as another list containing, at the start, one empty list.
|
||||
@ -327,11 +351,11 @@ public class Block {
|
||||
Property<?>[] keys = this.states.keySet().toArray(new Property<?>[0]);
|
||||
result.forEach(properties -> {
|
||||
Comparable<?>[] values = properties.toArray(new Comparable<?>[0]);
|
||||
Reference2ObjectMap<Property<?>, Comparable<?>> propertyMap = new Reference2ObjectArrayMap<>(keys, values);
|
||||
BlockState state = new BlockState(block, BlockRegistries.BLOCK_STATES.get().size(), propertyMap);
|
||||
BlockState state = new BlockState(block, BlockRegistries.BLOCK_STATES.get().size(), values);
|
||||
BlockRegistries.BLOCK_STATES.get().add(state);
|
||||
states.add(state);
|
||||
});
|
||||
this.propertyKeys = keys;
|
||||
return states;
|
||||
}
|
||||
}
|
||||
|
@ -25,8 +25,7 @@
|
||||
|
||||
package org.geysermc.geyser.level.block.type;
|
||||
|
||||
import it.unimi.dsi.fastutil.objects.Reference2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.objects.Reference2ObjectMaps;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.geysermc.geyser.level.block.property.Property;
|
||||
import org.geysermc.geyser.registry.BlockRegistries;
|
||||
|
||||
@ -35,13 +34,18 @@ import java.util.Locale;
|
||||
public final class BlockState {
|
||||
private final Block block;
|
||||
private final int javaId;
|
||||
private final Reference2ObjectMap<Property<?>, Comparable<?>> states;
|
||||
/**
|
||||
* The values of each property of this block state. These should be treated as keys to {@link Block#propertyKeys()}
|
||||
* Of note - the comparable part probably doesn't do anything because we occasionally use strings in place of enums.
|
||||
* Will be null if there's only one block state for a block.
|
||||
*/
|
||||
private final Comparable<?>[] states;
|
||||
|
||||
public BlockState(Block block, int javaId) {
|
||||
this(block, javaId, Reference2ObjectMaps.emptyMap());
|
||||
this(block, javaId, null);
|
||||
}
|
||||
|
||||
BlockState(Block block, int javaId, Reference2ObjectMap<Property<?>, Comparable<?>> states) {
|
||||
BlockState(Block block, int javaId, Comparable<?>[] states) {
|
||||
this.block = block;
|
||||
this.javaId = javaId;
|
||||
this.states = states;
|
||||
@ -49,23 +53,97 @@ public final class BlockState {
|
||||
|
||||
public <T extends Comparable<T>> T getValue(Property<T> property) {
|
||||
//noinspection unchecked
|
||||
return (T) states.get(property);
|
||||
return (T) get(property);
|
||||
}
|
||||
|
||||
public boolean getValue(Property<Boolean> property, boolean def) {
|
||||
var value = states.get(property);
|
||||
var value = get(property);
|
||||
if (value == null) {
|
||||
return def;
|
||||
}
|
||||
return (Boolean) value;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Comparable<?> get(Property<?> property) {
|
||||
Property<?>[] keys = this.block.propertyKeys();
|
||||
if (keys == null) {
|
||||
return null;
|
||||
}
|
||||
// We're copying the behavior Reference2ObjectArrayMap uses
|
||||
for (int i = keys.length; i-- != 0;) {
|
||||
if (keys[i] == property) {
|
||||
return this.states[i];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the {@link BlockState} instance with the given value.
|
||||
*/
|
||||
public <T extends Comparable<T>> BlockState withValue(Property<T> property, T value) {
|
||||
Property<?>[] keys = this.block.propertyKeys();
|
||||
if (keys == null) {
|
||||
throw new IllegalStateException(this + " does not have any different states!");
|
||||
}
|
||||
|
||||
T currentValue = getValue(property);
|
||||
if (currentValue == null) {
|
||||
throw new IllegalArgumentException("This BlockState does not have the property " + property);
|
||||
}
|
||||
if (currentValue.equals(value)) {
|
||||
// No action required. This block state is the state we're looking for.
|
||||
return this;
|
||||
}
|
||||
|
||||
// Diff is how much we will have to traverse as a sort of offset
|
||||
|
||||
// Block states are calculated in a predictable structure:
|
||||
// minecraft:cobblestone_wall[east=none,north=none,south=none,up=true,waterlogged=true,west=none]
|
||||
// minecraft:cobblestone_wall[east=none,north=none,south=none,up=true,waterlogged=true,west=low]
|
||||
// minecraft:cobblestone_wall[east=none,north=none,south=none,up=true,waterlogged=true,west=tall]
|
||||
// minecraft:cobblestone_wall[east=none,north=none,south=none,up=true,waterlogged=false,west=none]
|
||||
// minecraft:cobblestone_wall[east=none,north=none,south=none,up=true,waterlogged=false,west=low]
|
||||
// minecraft:cobblestone_wall[east=none,north=none,south=none,up=true,waterlogged=false,west=tall]
|
||||
// minecraft:cobblestone_wall[east=none,north=none,south=none,up=false,waterlogged=true,west=none]
|
||||
|
||||
// The last value goes through all its iterations, then the next state goes through all its iterations.
|
||||
// West goes none -> low -> tall, then waterlogged is toggled as west cycles again.
|
||||
// Then when waterlogged goes through all its properties, up is toggled, and west goes through again
|
||||
// If we want to find the "up" property in order, then we need to find how many iterations each property
|
||||
// after it goes in. West goes for 3, waterlogged goes for 2. Adding those together, we find that we need to
|
||||
// add five to get to the next toggle of the up property
|
||||
int diff = 0;
|
||||
for (int i = keys.length - 1; i >= 0; i--) {
|
||||
if (keys[i] != property) {
|
||||
diff += keys[i].valuesCount();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// How many times do we have to jump by diff? This depends on how far away each value is from each other.
|
||||
// piston_head[facing=north] might be right next to piston_head[facing=south], which just one diff'd hop.
|
||||
// But piston_head[facing=west] is further away, requiring more hops.
|
||||
int thatOffset = property.indexOf(value);
|
||||
int thisOffset = property.indexOf(currentValue);
|
||||
if (diff == 0) {
|
||||
// This can happen if the property is at the tail end of the block and there are no other properties to look through
|
||||
// If we have minecraft:cobblestone_wall[east=none,north=none,south=none,up=true,waterlogged=true,west=none]
|
||||
// And want minecraft:cobblestone_wall[east=none,north=none,south=none,up=true,waterlogged=true,west=low]
|
||||
// The above for loop will always stop at the first break because the last property has already been found
|
||||
diff = 1;
|
||||
}
|
||||
return BlockState.of(this.javaId + ((thatOffset - thisOffset) * diff));
|
||||
}
|
||||
|
||||
public Block block() {
|
||||
return block;
|
||||
return this.block;
|
||||
}
|
||||
|
||||
public int javaId() {
|
||||
return javaId;
|
||||
return this.javaId;
|
||||
}
|
||||
|
||||
public boolean is(Block block) {
|
||||
@ -74,7 +152,7 @@ public final class BlockState {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (this.states.isEmpty()) {
|
||||
if (this.states == null) {
|
||||
return this.block.javaIdentifier().toString();
|
||||
}
|
||||
return this.block.javaIdentifier().toString() + "[" + paramsToString() + "]";
|
||||
@ -82,14 +160,15 @@ public final class BlockState {
|
||||
|
||||
private String paramsToString() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
var it = this.states.entrySet().iterator();
|
||||
while (it.hasNext()) {
|
||||
var entry = it.next();
|
||||
builder.append(entry.getKey().name())
|
||||
.append("=")
|
||||
.append(entry.getValue().toString().toLowerCase(Locale.ROOT)); // lowercase covers enums
|
||||
if (it.hasNext()) {
|
||||
builder.append(",");
|
||||
Property<?>[] propertyKeys = this.block.propertyKeys();
|
||||
if (propertyKeys != null) {
|
||||
for (int i = 0; i < propertyKeys.length; i++) {
|
||||
builder.append(propertyKeys[i].name())
|
||||
.append("=")
|
||||
.append(this.states[i].toString().toLowerCase(Locale.ROOT)); // lowercase covers enums
|
||||
if (i < propertyKeys.length - 1) {
|
||||
builder.append(",");
|
||||
}
|
||||
}
|
||||
}
|
||||
return builder.toString();
|
||||
|
@ -28,29 +28,14 @@ package org.geysermc.geyser.level.block.type;
|
||||
import org.geysermc.geyser.level.block.property.Properties;
|
||||
import org.geysermc.geyser.level.physics.Direction;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class FurnaceBlock extends Block {
|
||||
private static BlockState LIT;
|
||||
private static BlockState UNLIT;
|
||||
|
||||
public FurnaceBlock(String javaIdentifier, Builder builder) {
|
||||
super(javaIdentifier, builder);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processStates(List<BlockState> states) {
|
||||
LIT = states.stream()
|
||||
.filter(state -> state.getValue(Properties.HORIZONTAL_FACING) == Direction.NORTH
|
||||
&& state.getValue(Properties.LIT))
|
||||
.findFirst().orElseThrow();
|
||||
UNLIT = states.stream()
|
||||
.filter(state -> state.getValue(Properties.HORIZONTAL_FACING) == Direction.NORTH
|
||||
&& !state.getValue(Properties.LIT))
|
||||
.findFirst().orElseThrow();
|
||||
}
|
||||
|
||||
public static BlockState state(boolean lit) {
|
||||
return lit ? LIT : UNLIT;
|
||||
protected BlockState setDefaultState(BlockState firstState) {
|
||||
// Both furnace minecart states look north.
|
||||
return firstState.withValue(Properties.HORIZONTAL_FACING, Direction.NORTH);
|
||||
}
|
||||
}
|
||||
|
@ -25,21 +25,8 @@
|
||||
|
||||
package org.geysermc.geyser.level.block.type;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class HoneyBlock extends Block {
|
||||
private static BlockState STATE;
|
||||
|
||||
public HoneyBlock(String javaIdentifier, Builder builder) {
|
||||
super(javaIdentifier, builder);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processStates(List<BlockState> states) {
|
||||
STATE = states.get(0);
|
||||
}
|
||||
|
||||
public static BlockState state() {
|
||||
return STATE;
|
||||
}
|
||||
}
|
||||
|
@ -25,21 +25,8 @@
|
||||
|
||||
package org.geysermc.geyser.level.block.type;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class SpawnerBlock extends Block {
|
||||
private static BlockState STATE;
|
||||
|
||||
public SpawnerBlock(String javaIdentifier, Builder builder) {
|
||||
super(javaIdentifier, builder);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processStates(List<BlockState> states) {
|
||||
STATE = states.get(0);
|
||||
}
|
||||
|
||||
public static BlockState state() {
|
||||
return STATE;
|
||||
}
|
||||
}
|
||||
|
@ -25,17 +25,8 @@
|
||||
|
||||
package org.geysermc.geyser.level.block.type;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class WaterBlock extends Block {
|
||||
private static BlockState LEVEL_0;
|
||||
|
||||
public WaterBlock(String javaIdentifier, Builder builder) {
|
||||
super(javaIdentifier, builder);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processStates(List<BlockState> states) {
|
||||
super.processStates(states);
|
||||
}
|
||||
}
|
||||
|
@ -39,6 +39,9 @@ import org.geysermc.geyser.entity.EntityDefinitions;
|
||||
import org.geysermc.geyser.entity.type.Entity;
|
||||
import org.geysermc.geyser.entity.type.player.PlayerEntity;
|
||||
import org.geysermc.geyser.level.block.BlockStateValues;
|
||||
import org.geysermc.geyser.level.block.Blocks;
|
||||
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.PistonCache;
|
||||
import org.geysermc.geyser.translator.collision.BlockCollision;
|
||||
@ -436,7 +439,8 @@ public class CollisionManager {
|
||||
* @return if the player is currently in a water block
|
||||
*/
|
||||
public boolean isPlayerInWater() {
|
||||
return session.getGeyser().getWorldManager().getBlockAt(session, session.getPlayerEntity().getPosition().toInt()) == BlockStateValues.JAVA_WATER_ID;
|
||||
BlockState state = session.getGeyser().getWorldManager().blockAt(session, session.getPlayerEntity().getPosition().toInt());
|
||||
return state.is(Blocks.WATER) && state.getValue(Properties.LEVEL) == 0;
|
||||
}
|
||||
|
||||
public boolean isWaterInEyes() {
|
||||
|
@ -28,10 +28,13 @@ package org.geysermc.geyser.registry;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.geysermc.geyser.registry.loader.RegistryLoader;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class ListRegistry<M> extends Registry<List<M>> {
|
||||
private boolean frozen = false;
|
||||
|
||||
/**
|
||||
* Creates a new instance of this class with the given input and
|
||||
* {@link RegistryLoader}. The input specified is what the registry
|
||||
@ -85,9 +88,24 @@ public class ListRegistry<M> extends Registry<List<M>> {
|
||||
* @return a new value into this registry with the given index.
|
||||
*/
|
||||
public M register(int index, M value) {
|
||||
if (this.frozen) {
|
||||
throw new IllegalStateException("Registry should not be modified after frozen!");
|
||||
}
|
||||
return this.mappings.set(index, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark this registry as unsuitable for new additions. The backing list will then be optimized for storage.
|
||||
*/
|
||||
public void freeze() {
|
||||
if (!this.frozen) {
|
||||
this.frozen = true;
|
||||
if (this.mappings instanceof ArrayList<M> arrayList) {
|
||||
arrayList.trimToSize();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new array registry with the given {@link RegistryLoader}. The
|
||||
* input type is not specified here, meaning the loader return type is either
|
||||
|
@ -77,7 +77,7 @@ public class CollisionRegistryLoader extends MultiResourceRegistryLoader<String,
|
||||
}
|
||||
|
||||
List<BlockState> blockStates = BlockRegistries.BLOCK_STATES.get();
|
||||
List<BlockCollision> collisions = new ObjectArrayList<>(blockStates.size());
|
||||
var collisions = new ObjectArrayList<BlockCollision>(blockStates.size());
|
||||
|
||||
// Map of unique collisions to its instance
|
||||
Map<BlockCollision, BlockCollision> collisionInstances = new Object2ObjectOpenHashMap<>();
|
||||
@ -102,6 +102,7 @@ public class CollisionRegistryLoader extends MultiResourceRegistryLoader<String,
|
||||
|
||||
collisions.add(newCollision);
|
||||
}
|
||||
collisions.trim();
|
||||
return collisions;
|
||||
}
|
||||
|
||||
|
@ -50,7 +50,6 @@ 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.item.Items;
|
||||
import org.geysermc.geyser.level.block.BlockStateValues;
|
||||
import org.geysermc.geyser.level.block.Blocks;
|
||||
import org.geysermc.geyser.level.block.property.Properties;
|
||||
import org.geysermc.geyser.level.block.type.Block;
|
||||
@ -433,32 +432,13 @@ public final class BlockRegistryPopulator {
|
||||
}
|
||||
|
||||
int javaRuntimeId = -1;
|
||||
int waterRuntimeId = -1;
|
||||
for (BlockState javaBlockState : BlockRegistries.BLOCK_STATES.get()) {
|
||||
javaRuntimeId++;
|
||||
String javaId = javaBlockState.toString().intern();
|
||||
|
||||
BlockStateValues.storeBlockStateValues(javaId, javaRuntimeId);
|
||||
|
||||
//String cleanJavaIdentifier = javaBlockState.block().javaIdentifier().toString();
|
||||
//String bedrockIdentifier = entry.getValue().get("bedrock_identifier").asText();
|
||||
|
||||
BlockRegistries.JAVA_IDENTIFIER_TO_ID.register(javaId, javaRuntimeId);
|
||||
|
||||
// Keeping this here since this is currently unchanged between versions
|
||||
// It's possible to only have this store differences in names, but the key set of all Java names is used in sending command suggestions
|
||||
//BlockRegistries.JAVA_TO_BEDROCK_IDENTIFIERS.register(cleanJavaIdentifier.intern(), bedrockIdentifier.intern());
|
||||
|
||||
if ("minecraft:water[level=0]".equals(javaId)) {
|
||||
waterRuntimeId = javaRuntimeId;
|
||||
}
|
||||
}
|
||||
|
||||
if (waterRuntimeId == -1) {
|
||||
throw new AssertionError("Unable to find Java water in palette");
|
||||
}
|
||||
BlockStateValues.JAVA_WATER_ID = waterRuntimeId;
|
||||
|
||||
if (!BlockRegistries.NON_VANILLA_BLOCK_STATE_OVERRIDES.get().isEmpty()) {
|
||||
IntSet usedNonVanillaRuntimeIDs = new IntOpenHashSet();
|
||||
|
||||
@ -467,8 +447,6 @@ public final class BlockRegistryPopulator {
|
||||
throw new RuntimeException("Duplicate runtime ID " + javaBlockState.javaId() + " for non vanilla Java block state " + javaBlockState.identifier());
|
||||
}
|
||||
|
||||
CustomBlockState customBlockState = BlockRegistries.NON_VANILLA_BLOCK_STATE_OVERRIDES.get().get(javaBlockState);
|
||||
|
||||
String javaId = javaBlockState.identifier();
|
||||
int stateRuntimeId = javaBlockState.javaId();
|
||||
String pistonBehavior = javaBlockState.pistonBehavior();
|
||||
@ -517,6 +495,8 @@ public final class BlockRegistryPopulator {
|
||||
|
||||
BlockRegistries.INTERACTIVE.set(toBlockStateSet((ArrayNode) blockInteractionsJson.get("always_consumes")));
|
||||
BlockRegistries.INTERACTIVE_MAY_BUILD.set(toBlockStateSet((ArrayNode) blockInteractionsJson.get("requires_may_build")));
|
||||
|
||||
BlockRegistries.BLOCK_STATES.freeze();
|
||||
}
|
||||
|
||||
private static BitSet toBlockStateSet(ArrayNode node) {
|
||||
|
@ -90,6 +90,10 @@ public class BlockMappings implements DefinitionRegistry<GeyserBedrockBlock> {
|
||||
return this.getBedrockBlock(javaState.javaId());
|
||||
}
|
||||
|
||||
public GeyserBedrockBlock getVanillaBedrockBlock(BlockState javaState) {
|
||||
return getVanillaBedrockBlock(javaState.javaId());
|
||||
}
|
||||
|
||||
public GeyserBedrockBlock getVanillaBedrockBlock(int javaState) {
|
||||
if (javaState < 0 || javaState >= this.javaToVanillaBedrockBlocks.length) {
|
||||
return bedrockAir;
|
||||
|
@ -318,22 +318,6 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
|
||||
@Setter
|
||||
private boolean sprinting;
|
||||
|
||||
/**
|
||||
* Whether the player is swimming in water.
|
||||
* Used to update speed when crawling.
|
||||
*/
|
||||
@Setter
|
||||
private boolean swimmingInWater;
|
||||
|
||||
/**
|
||||
* Tracks the original speed attribute.
|
||||
* <p>
|
||||
* We need to do this in order to emulate speeds when sneaking under 1.5-blocks-tall areas if the player isn't sneaking,
|
||||
* and when crawling.
|
||||
*/
|
||||
@Setter
|
||||
private float originalSpeedAttribute;
|
||||
|
||||
/**
|
||||
* The dimension of the player.
|
||||
* As all entities are in the same world, this can be safely applied to all other entities.
|
||||
@ -913,6 +897,9 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
|
||||
this.downstream.getSession().setFlag(BuiltinFlags.ATTEMPT_SRV_RESOLVE, resolveSrv);
|
||||
}
|
||||
|
||||
// Disable automatic creation of a new TcpClientSession when transferring - we don't use that functionality.
|
||||
this.downstream.getSession().setFlag(MinecraftConstants.FOLLOW_TRANSFERS, false);
|
||||
|
||||
if (geyser.getConfig().getRemote().isUseProxyProtocol()) {
|
||||
downstream.setFlag(BuiltinFlags.ENABLE_CLIENT_PROXY_PROTOCOL, true);
|
||||
downstream.setFlag(BuiltinFlags.CLIENT_PROXIED_ADDRESS, upstream.getAddress());
|
||||
@ -1304,21 +1291,11 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
|
||||
this.sneaking = sneaking;
|
||||
|
||||
// Update pose and bounding box on our end
|
||||
AttributeData speedAttribute;
|
||||
if (!sneaking && (speedAttribute = adjustSpeed()) != null) {
|
||||
// Update attributes since we're still "sneaking" under a 1.5-block-tall area
|
||||
UpdateAttributesPacket attributesPacket = new UpdateAttributesPacket();
|
||||
attributesPacket.setRuntimeEntityId(playerEntity.getGeyserId());
|
||||
attributesPacket.setAttributes(Collections.singletonList(speedAttribute));
|
||||
sendUpstreamPacket(attributesPacket);
|
||||
// the server *should* update our pose once it has returned to normal
|
||||
} else {
|
||||
if (!flying) {
|
||||
// The pose and bounding box should not be updated if the player is flying
|
||||
setSneakingPose(sneaking);
|
||||
}
|
||||
collisionManager.updateScaffoldingFlags(false);
|
||||
if (!flying) {
|
||||
// The pose and bounding box should not be updated if the player is flying
|
||||
setSneakingPose(sneaking);
|
||||
}
|
||||
collisionManager.updateScaffoldingFlags(false);
|
||||
|
||||
playerEntity.updateBedrockMetadata();
|
||||
|
||||
@ -1361,30 +1338,6 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adjusts speed if the player is crawling.
|
||||
*
|
||||
* @return not null if attributes should be updated.
|
||||
*/
|
||||
public @Nullable AttributeData adjustSpeed() {
|
||||
AttributeData currentPlayerSpeed = playerEntity.getAttributes().get(GeyserAttributeType.MOVEMENT_SPEED);
|
||||
if (currentPlayerSpeed != null) {
|
||||
if ((pose.equals(Pose.SNEAKING) && !sneaking && collisionManager.mustPlayerSneakHere()) ||
|
||||
(!swimmingInWater && playerEntity.getFlag(EntityFlag.SWIMMING) && !collisionManager.isPlayerInWater())) {
|
||||
// Either of those conditions means that Bedrock goes zoom when they shouldn't be
|
||||
AttributeData speedAttribute = GeyserAttributeType.MOVEMENT_SPEED.getAttribute(originalSpeedAttribute / 3.32f);
|
||||
playerEntity.getAttributes().put(GeyserAttributeType.MOVEMENT_SPEED, speedAttribute);
|
||||
return speedAttribute;
|
||||
} else if (originalSpeedAttribute != currentPlayerSpeed.getValue()) {
|
||||
// Speed has reset to normal
|
||||
AttributeData speedAttribute = GeyserAttributeType.MOVEMENT_SPEED.getAttribute(originalSpeedAttribute);
|
||||
playerEntity.getAttributes().put(GeyserAttributeType.MOVEMENT_SPEED, speedAttribute);
|
||||
return speedAttribute;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see if a shield is in either hand to activate blocking. If so, it sets the Bedrock client to display
|
||||
* blocking and sends a packet to the Java server.
|
||||
|
@ -91,15 +91,11 @@ public class AdvancementsCache {
|
||||
builder.validResultHandler((response) -> {
|
||||
String id = rootAdvancementIds.get(response.clickedButtonId());
|
||||
if (!id.equals("")) {
|
||||
if (id.equals(currentAdvancementCategoryId)) {
|
||||
// The server thinks we are already on this tab
|
||||
buildAndShowListForm();
|
||||
} else {
|
||||
// Send a packet indicating that we intend to open this particular advancement window
|
||||
ServerboundSeenAdvancementsPacket packet = new ServerboundSeenAdvancementsPacket(id);
|
||||
session.sendDownstreamGamePacket(packet);
|
||||
// Wait for a response there
|
||||
}
|
||||
// Send a packet indicating that we are opening this particular advancement window
|
||||
ServerboundSeenAdvancementsPacket packet = new ServerboundSeenAdvancementsPacket(id);
|
||||
session.sendDownstreamGamePacket(packet);
|
||||
currentAdvancementCategoryId = id;
|
||||
buildAndShowListForm();
|
||||
}
|
||||
});
|
||||
|
||||
@ -190,6 +186,10 @@ public class AdvancementsCache {
|
||||
.content(content)
|
||||
.button(GeyserLocale.getPlayerLocaleString("gui.back", language))
|
||||
.validResultHandler((response) -> buildAndShowListForm())
|
||||
.closedResultHandler(() -> {
|
||||
// Indicate that we have closed the current advancement tab
|
||||
session.sendDownstreamGamePacket(new ServerboundSeenAdvancementsPacket());
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -28,7 +28,6 @@ package org.geysermc.geyser.session.cache;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.inventory.GeyserItemStack;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.GlobalPos;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.item.component.LodestoneTracker;
|
||||
@ -53,11 +52,13 @@ public final class LodestoneCache {
|
||||
private int id = 1;
|
||||
|
||||
public void cacheInventoryItem(GeyserItemStack itemStack, LodestoneTracker tracker) {
|
||||
GlobalPos position = tracker.getPos();
|
||||
if (!tracker.isTracked()) {
|
||||
return;
|
||||
}
|
||||
|
||||
GlobalPos position = tracker.getPos();
|
||||
if (position == null) {
|
||||
GeyserImpl.getInstance().getLogger().error("Position is null. Find out why.");
|
||||
Thread.dumpStack();
|
||||
// As of 1.20.6, position can still be null even if tracking is enabled.
|
||||
return;
|
||||
}
|
||||
int x = position.getX();
|
||||
@ -84,13 +85,16 @@ public final class LodestoneCache {
|
||||
}
|
||||
|
||||
public int store(LodestoneTracker tracker) {
|
||||
GlobalPos position = tracker.getPos();
|
||||
|
||||
if (position == null) {
|
||||
GeyserImpl.getInstance().getLogger().error("Position is null. Find out why.");
|
||||
Thread.dumpStack();
|
||||
return -1;
|
||||
if (!tracker.isTracked()) {
|
||||
// No coordinates; nothing to convert
|
||||
return 0;
|
||||
}
|
||||
|
||||
GlobalPos position = tracker.getPos();
|
||||
if (position == null) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int x = position.getX();
|
||||
int y = position.getY();
|
||||
int z = position.getZ();
|
||||
|
@ -63,6 +63,13 @@ public class MinecraftTranslationRegistry extends TranslatableComponentRenderer<
|
||||
}
|
||||
}
|
||||
|
||||
// replace single quote instances which get lost in MessageFormat otherwise
|
||||
localeString = localeString.replace("'", "''");
|
||||
|
||||
// Wrap all curly brackets with single quote inserts - fixes https://github.com/GeyserMC/Geyser/issues/4662
|
||||
localeString = localeString.replace("{", "'{")
|
||||
.replace("}", "'}");
|
||||
|
||||
// Replace the `%s` with numbered inserts `{0}`
|
||||
Pattern p = stringReplacement;
|
||||
Matcher m = p.matcher(localeString);
|
||||
@ -83,8 +90,7 @@ public class MinecraftTranslationRegistry extends TranslatableComponentRenderer<
|
||||
}
|
||||
m.appendTail(sb);
|
||||
|
||||
// replace single quote instances which get lost in MessageFormat otherwise
|
||||
// Locale shouldn't need to be specific - dates for example will not be handled
|
||||
return new MessageFormat(sb.toString().replace("'", "''"), Locale.ROOT);
|
||||
return new MessageFormat(sb.toString(), Locale.ROOT);
|
||||
}
|
||||
}
|
||||
|
@ -31,6 +31,7 @@ import org.geysermc.geyser.inventory.holder.BlockInventoryHolder;
|
||||
import org.geysermc.geyser.inventory.holder.InventoryHolder;
|
||||
import org.geysermc.geyser.inventory.updater.InventoryUpdater;
|
||||
import org.geysermc.geyser.level.block.type.Block;
|
||||
import org.geysermc.geyser.level.block.type.BlockState;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
|
||||
/**
|
||||
@ -40,17 +41,25 @@ public abstract class AbstractBlockInventoryTranslator extends BaseInventoryTran
|
||||
private final InventoryHolder holder;
|
||||
private final InventoryUpdater updater;
|
||||
|
||||
/**
|
||||
* @param javaBlock a Java block that is used as a temporary block
|
||||
*/
|
||||
public AbstractBlockInventoryTranslator(int size, Block javaBlock, ContainerType containerType, InventoryUpdater updater,
|
||||
Block... additionalValidBlocks) {
|
||||
this(size, javaBlock.defaultBlockState(), containerType, updater, additionalValidBlocks);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param size the amount of slots that the inventory adds alongside the base inventory slots
|
||||
* @param javaBlockIdentifier a Java block identifier that is used as a temporary block
|
||||
* @param javaBlockState a Java block state that is used as a temporary block
|
||||
* @param containerType the container type of this inventory
|
||||
* @param updater updater
|
||||
* @param additionalValidBlocks any other blocks that can safely use this inventory without a fake block
|
||||
*/
|
||||
public AbstractBlockInventoryTranslator(int size, String javaBlockIdentifier, ContainerType containerType, InventoryUpdater updater,
|
||||
public AbstractBlockInventoryTranslator(int size, BlockState javaBlockState, ContainerType containerType, InventoryUpdater updater,
|
||||
Block... additionalValidBlocks) {
|
||||
super(size);
|
||||
this.holder = new BlockInventoryHolder(javaBlockIdentifier, containerType, additionalValidBlocks);
|
||||
this.holder = new BlockInventoryHolder(javaBlockState, containerType, additionalValidBlocks);
|
||||
this.updater = updater;
|
||||
}
|
||||
|
||||
|
@ -45,7 +45,7 @@ import java.util.Objects;
|
||||
|
||||
public class AnvilInventoryTranslator extends AbstractBlockInventoryTranslator {
|
||||
public AnvilInventoryTranslator() {
|
||||
super(3, "minecraft:anvil[facing=north]", org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType.ANVIL, AnvilInventoryUpdater.INSTANCE,
|
||||
super(3, Blocks.ANVIL, org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType.ANVIL, AnvilInventoryUpdater.INSTANCE,
|
||||
Blocks.CHIPPED_ANVIL, Blocks.DAMAGED_ANVIL);
|
||||
}
|
||||
|
||||
|
@ -27,7 +27,6 @@ package org.geysermc.geyser.translator.inventory;
|
||||
|
||||
import it.unimi.dsi.fastutil.ints.IntSets;
|
||||
import org.cloudburstmc.math.vector.Vector3i;
|
||||
import org.cloudburstmc.nbt.NbtMap;
|
||||
import org.cloudburstmc.nbt.NbtMapBuilder;
|
||||
import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerSlotType;
|
||||
import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.ItemStackRequest;
|
||||
@ -43,7 +42,9 @@ import org.geysermc.geyser.inventory.Inventory;
|
||||
import org.geysermc.geyser.inventory.PlayerInventory;
|
||||
import org.geysermc.geyser.inventory.holder.BlockInventoryHolder;
|
||||
import org.geysermc.geyser.inventory.updater.UIInventoryUpdater;
|
||||
import org.geysermc.geyser.level.block.Blocks;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.translator.level.block.entity.BlockEntityTranslator;
|
||||
import org.geysermc.geyser.util.InventoryUtils;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.inventory.ContainerType;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory.ServerboundSetBeaconPacket;
|
||||
@ -52,7 +53,7 @@ import java.util.OptionalInt;
|
||||
|
||||
public class BeaconInventoryTranslator extends AbstractBlockInventoryTranslator {
|
||||
public BeaconInventoryTranslator() {
|
||||
super(1, new BlockInventoryHolder("minecraft:beacon", org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType.BEACON) {
|
||||
super(1, new BlockInventoryHolder(Blocks.BEACON, org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType.BEACON) {
|
||||
@Override
|
||||
protected boolean checkInteractionPosition(GeyserSession session) {
|
||||
// Since we can't fall back to a virtual inventory, let's make opening one easier
|
||||
@ -89,12 +90,8 @@ public class BeaconInventoryTranslator extends AbstractBlockInventoryTranslator
|
||||
|
||||
// Send a block entity data packet update to the fake beacon inventory
|
||||
Vector3i position = inventory.getHolderPosition();
|
||||
NbtMapBuilder builder = NbtMap.builder()
|
||||
.putInt("x", position.getX())
|
||||
.putInt("y", position.getY())
|
||||
.putInt("z", position.getZ())
|
||||
NbtMapBuilder builder = BlockEntityTranslator.getConstantBedrockTag("Beacon", position)
|
||||
.putString("CustomName", inventory.getTitle())
|
||||
.putString("id", "Beacon")
|
||||
.putInt("primary", beaconContainer.getPrimaryId())
|
||||
.putInt("secondary", beaconContainer.getSecondaryId());
|
||||
|
||||
|
@ -32,11 +32,16 @@ import org.cloudburstmc.protocol.bedrock.packet.ContainerSetDataPacket;
|
||||
import org.geysermc.geyser.inventory.BedrockContainerSlot;
|
||||
import org.geysermc.geyser.inventory.Inventory;
|
||||
import org.geysermc.geyser.inventory.updater.ContainerInventoryUpdater;
|
||||
import org.geysermc.geyser.level.block.Blocks;
|
||||
import org.geysermc.geyser.level.block.property.Properties;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
|
||||
public class BrewingInventoryTranslator extends AbstractBlockInventoryTranslator {
|
||||
public BrewingInventoryTranslator() {
|
||||
super(5, "minecraft:brewing_stand[has_bottle_0=false,has_bottle_1=false,has_bottle_2=false]", ContainerType.BREWING_STAND, ContainerInventoryUpdater.INSTANCE);
|
||||
super(5, Blocks.BREWING_STAND.defaultBlockState()
|
||||
.withValue(Properties.HAS_BOTTLE_0, false)
|
||||
.withValue(Properties.HAS_BOTTLE_1, false)
|
||||
.withValue(Properties.HAS_BOTTLE_2, false), ContainerType.BREWING_STAND, ContainerInventoryUpdater.INSTANCE);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -30,12 +30,13 @@ import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.ItemSt
|
||||
import org.geysermc.geyser.inventory.*;
|
||||
import org.geysermc.geyser.inventory.updater.UIInventoryUpdater;
|
||||
import org.geysermc.geyser.item.Items;
|
||||
import org.geysermc.geyser.level.block.Blocks;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.inventory.ContainerType;
|
||||
|
||||
public class CartographyInventoryTranslator extends AbstractBlockInventoryTranslator {
|
||||
public CartographyInventoryTranslator() {
|
||||
super(3, "minecraft:cartography_table", org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType.CARTOGRAPHY, UIInventoryUpdater.INSTANCE);
|
||||
super(3, Blocks.CARTOGRAPHY_TABLE, org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType.CARTOGRAPHY, UIInventoryUpdater.INSTANCE);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -31,6 +31,7 @@ import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerSlotType;
|
||||
import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.ItemStackRequestSlotData;
|
||||
import org.geysermc.geyser.inventory.*;
|
||||
import org.geysermc.geyser.inventory.updater.CrafterInventoryUpdater;
|
||||
import org.geysermc.geyser.level.block.Blocks;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.util.BlockEntityUtils;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.inventory.ContainerType;
|
||||
@ -53,7 +54,7 @@ public class CrafterInventoryTranslator extends AbstractBlockInventoryTranslator
|
||||
private static final int TRIGGERED = 1; // triggered value
|
||||
|
||||
public CrafterInventoryTranslator() {
|
||||
super(10, "minecraft:crafter", org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType.CRAFTER, CrafterInventoryUpdater.INSTANCE);
|
||||
super(10, Blocks.CRAFTER, org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType.CRAFTER, CrafterInventoryUpdater.INSTANCE);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -31,10 +31,11 @@ import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.ItemSt
|
||||
import org.geysermc.geyser.inventory.BedrockContainerSlot;
|
||||
import org.geysermc.geyser.inventory.SlotType;
|
||||
import org.geysermc.geyser.inventory.updater.UIInventoryUpdater;
|
||||
import org.geysermc.geyser.level.block.Blocks;
|
||||
|
||||
public class CraftingInventoryTranslator extends AbstractBlockInventoryTranslator {
|
||||
public CraftingInventoryTranslator() {
|
||||
super(10, "minecraft:crafting_table", ContainerType.WORKBENCH, UIInventoryUpdater.INSTANCE);
|
||||
super(10, Blocks.CRAFTING_TABLE, ContainerType.WORKBENCH, UIInventoryUpdater.INSTANCE);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -38,6 +38,7 @@ import org.cloudburstmc.protocol.bedrock.packet.PlayerEnchantOptionsPacket;
|
||||
import org.geysermc.geyser.inventory.*;
|
||||
import org.geysermc.geyser.inventory.item.Enchantment;
|
||||
import org.geysermc.geyser.inventory.updater.UIInventoryUpdater;
|
||||
import org.geysermc.geyser.level.block.Blocks;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.inventory.ContainerType;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory.ServerboundContainerButtonClickPacket;
|
||||
@ -47,7 +48,7 @@ import java.util.Locale;
|
||||
|
||||
public class EnchantingInventoryTranslator extends AbstractBlockInventoryTranslator {
|
||||
public EnchantingInventoryTranslator() {
|
||||
super(2, "minecraft:enchanting_table", org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType.ENCHANTMENT, UIInventoryUpdater.INSTANCE);
|
||||
super(2, Blocks.ENCHANTING_TABLE, org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType.ENCHANTMENT, UIInventoryUpdater.INSTANCE);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -41,7 +41,7 @@ import org.geysermc.mcprotocollib.protocol.data.game.inventory.ContainerType;
|
||||
*/
|
||||
public class Generic3X3InventoryTranslator extends AbstractBlockInventoryTranslator {
|
||||
public Generic3X3InventoryTranslator() {
|
||||
super(9, "minecraft:dispenser[facing=north,triggered=false]", org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType.DISPENSER, ContainerInventoryUpdater.INSTANCE,
|
||||
super(9, Blocks.DISPENSER, org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType.DISPENSER, ContainerInventoryUpdater.INSTANCE,
|
||||
Blocks.DROPPER);
|
||||
}
|
||||
|
||||
|
@ -30,10 +30,11 @@ import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType;
|
||||
import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.ItemStackRequestSlotData;
|
||||
import org.geysermc.geyser.inventory.BedrockContainerSlot;
|
||||
import org.geysermc.geyser.inventory.updater.UIInventoryUpdater;
|
||||
import org.geysermc.geyser.level.block.Blocks;
|
||||
|
||||
public class GrindstoneInventoryTranslator extends AbstractBlockInventoryTranslator {
|
||||
public GrindstoneInventoryTranslator() {
|
||||
super(3, "minecraft:grindstone[face=floor,facing=north]", ContainerType.GRINDSTONE, UIInventoryUpdater.INSTANCE);
|
||||
super(3, Blocks.GRINDSTONE, ContainerType.GRINDSTONE, UIInventoryUpdater.INSTANCE);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -29,13 +29,14 @@ import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerSlotType;
|
||||
import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType;
|
||||
import org.geysermc.geyser.inventory.BedrockContainerSlot;
|
||||
import org.geysermc.geyser.inventory.updater.ContainerInventoryUpdater;
|
||||
import org.geysermc.geyser.level.block.Blocks;
|
||||
|
||||
/**
|
||||
* Implemented on top of any block that does not have special properties implemented
|
||||
*/
|
||||
public class HopperInventoryTranslator extends AbstractBlockInventoryTranslator {
|
||||
public HopperInventoryTranslator() {
|
||||
super(5, "minecraft:hopper[enabled=false,facing=down]", ContainerType.HOPPER, ContainerInventoryUpdater.INSTANCE);
|
||||
super(5, Blocks.HOPPER, ContainerType.HOPPER, ContainerInventoryUpdater.INSTANCE);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -34,6 +34,7 @@ import org.geysermc.erosion.util.LecternUtils;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.inventory.*;
|
||||
import org.geysermc.geyser.inventory.updater.ContainerInventoryUpdater;
|
||||
import org.geysermc.geyser.level.block.Blocks;
|
||||
import org.geysermc.geyser.network.GameProtocol;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.util.BlockEntityUtils;
|
||||
@ -56,7 +57,7 @@ public class LecternInventoryTranslator extends AbstractBlockInventoryTranslator
|
||||
private boolean initialized = false;
|
||||
|
||||
public LecternInventoryTranslator() {
|
||||
super(1, "minecraft:lectern[facing=north,has_book=true,powered=true]", org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType.LECTERN , ContainerInventoryUpdater.INSTANCE);
|
||||
super(1, Blocks.LECTERN, org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType.LECTERN , ContainerInventoryUpdater.INSTANCE);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -45,6 +45,7 @@ import org.geysermc.geyser.inventory.SlotType;
|
||||
import org.geysermc.geyser.inventory.updater.UIInventoryUpdater;
|
||||
import org.geysermc.geyser.item.type.BannerItem;
|
||||
import org.geysermc.geyser.item.type.DyeItem;
|
||||
import org.geysermc.geyser.level.block.Blocks;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.item.component.BannerPatternLayer;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType;
|
||||
@ -101,7 +102,7 @@ public class LoomInventoryTranslator extends AbstractBlockInventoryTranslator {
|
||||
}
|
||||
|
||||
public LoomInventoryTranslator() {
|
||||
super(4, "minecraft:loom[facing=north]", ContainerType.LOOM, UIInventoryUpdater.INSTANCE);
|
||||
super(4, Blocks.LOOM, ContainerType.LOOM, UIInventoryUpdater.INSTANCE);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -37,6 +37,7 @@ import org.cloudburstmc.protocol.bedrock.packet.InventorySlotPacket;
|
||||
import org.geysermc.geyser.inventory.BedrockContainerSlot;
|
||||
import org.geysermc.geyser.inventory.Inventory;
|
||||
import org.geysermc.geyser.inventory.updater.UIInventoryUpdater;
|
||||
import org.geysermc.geyser.level.block.Blocks;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.util.InventoryUtils;
|
||||
|
||||
@ -53,7 +54,7 @@ public class OldSmithingTableTranslator extends AbstractBlockInventoryTranslator
|
||||
private static final IntFunction<ItemData> UPGRADE_TEMPLATE = InventoryUtils.getUpgradeTemplate();
|
||||
|
||||
private OldSmithingTableTranslator() {
|
||||
super(3, "minecraft:smithing_table", ContainerType.SMITHING_TABLE, UIInventoryUpdater.INSTANCE);
|
||||
super(3, Blocks.SMITHING_TABLE, ContainerType.SMITHING_TABLE, UIInventoryUpdater.INSTANCE);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -35,7 +35,10 @@ 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.Blocks;
|
||||
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.registry.Registries;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.translator.level.block.entity.BlockEntityTranslator;
|
||||
@ -43,12 +46,13 @@ import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType
|
||||
|
||||
public class ShulkerInventoryTranslator extends AbstractBlockInventoryTranslator {
|
||||
public ShulkerInventoryTranslator() {
|
||||
super(27, new BlockInventoryHolder("minecraft:shulker_box[facing=north]", ContainerType.CONTAINER) {
|
||||
// Ensure that the shulker box default state won't be trying to open in a state facing the player
|
||||
super(27, new BlockInventoryHolder(Blocks.SHULKER_BOX.defaultBlockState().withValue(Properties.FACING, Direction.NORTH), ContainerType.CONTAINER) {
|
||||
private final BlockEntityTranslator shulkerBoxTranslator = Registries.BLOCK_ENTITIES.get(BlockEntityType.SHULKER_BOX);
|
||||
|
||||
@Override
|
||||
protected boolean isValidBlock(String[] javaBlockString) {
|
||||
return javaBlockString[0].contains("shulker_box");
|
||||
protected boolean isValidBlock(BlockState blockState) {
|
||||
return blockState.block().javaIdentifier().value().contains("shulker_box"); // TODO ew
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -30,10 +30,11 @@ import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType;
|
||||
import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.ItemStackRequestSlotData;
|
||||
import org.geysermc.geyser.inventory.BedrockContainerSlot;
|
||||
import org.geysermc.geyser.inventory.updater.UIInventoryUpdater;
|
||||
import org.geysermc.geyser.level.block.Blocks;
|
||||
|
||||
public class SmithingInventoryTranslator extends AbstractBlockInventoryTranslator {
|
||||
public SmithingInventoryTranslator() {
|
||||
super(4, "minecraft:smithing_table", ContainerType.SMITHING_TABLE, UIInventoryUpdater.INSTANCE);
|
||||
super(4, Blocks.SMITHING_TABLE, ContainerType.SMITHING_TABLE, UIInventoryUpdater.INSTANCE);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -35,6 +35,7 @@ import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.response.ItemS
|
||||
import org.geysermc.geyser.inventory.*;
|
||||
import org.geysermc.geyser.inventory.recipe.GeyserStonecutterData;
|
||||
import org.geysermc.geyser.inventory.updater.UIInventoryUpdater;
|
||||
import org.geysermc.geyser.level.block.Blocks;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.inventory.ContainerType;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack;
|
||||
@ -42,7 +43,7 @@ import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory.S
|
||||
|
||||
public class StonecutterInventoryTranslator extends AbstractBlockInventoryTranslator {
|
||||
public StonecutterInventoryTranslator() {
|
||||
super(2, "minecraft:stonecutter[facing=north]", org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType.STONECUTTER, UIInventoryUpdater.INSTANCE);
|
||||
super(2, Blocks.STONECUTTER, org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType.STONECUTTER, UIInventoryUpdater.INSTANCE);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -40,6 +40,7 @@ import org.geysermc.geyser.level.block.Blocks;
|
||||
import org.geysermc.geyser.level.block.property.ChestType;
|
||||
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.registry.BlockRegistries;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.translator.level.block.entity.BlockEntityTranslator;
|
||||
@ -51,7 +52,10 @@ public class DoubleChestInventoryTranslator extends ChestInventoryTranslator {
|
||||
|
||||
public DoubleChestInventoryTranslator(int size) {
|
||||
super(size, 54);
|
||||
this.defaultJavaBlockState = BlockRegistries.JAVA_IDENTIFIER_TO_ID.get().getInt("minecraft:chest[facing=north,type=single,waterlogged=false]");
|
||||
this.defaultJavaBlockState = Blocks.CHEST.defaultBlockState()
|
||||
.withValue(Properties.HORIZONTAL_FACING, Direction.NORTH)
|
||||
.withValue(Properties.CHEST_TYPE, ChestType.SINGLE)
|
||||
.javaId();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -96,11 +100,7 @@ public class DoubleChestInventoryTranslator extends ChestInventoryTranslator {
|
||||
blockPacket.getFlags().addAll(UpdateBlockPacket.FLAG_ALL_PRIORITY);
|
||||
session.sendUpstreamPacket(blockPacket);
|
||||
|
||||
NbtMap tag = NbtMap.builder()
|
||||
.putString("id", "Chest")
|
||||
.putInt("x", position.getX())
|
||||
.putInt("y", position.getY())
|
||||
.putInt("z", position.getZ())
|
||||
NbtMap tag = BlockEntityTranslator.getConstantBedrockTag("Chest", position)
|
||||
.putInt("pairx", pairPosition.getX())
|
||||
.putInt("pairz", pairPosition.getZ())
|
||||
.putString("CustomName", inventory.getTitle()).build();
|
||||
|
@ -30,6 +30,9 @@ import org.geysermc.geyser.inventory.Inventory;
|
||||
import org.geysermc.geyser.inventory.holder.BlockInventoryHolder;
|
||||
import org.geysermc.geyser.inventory.holder.InventoryHolder;
|
||||
import org.geysermc.geyser.level.block.Blocks;
|
||||
import org.geysermc.geyser.level.block.property.ChestType;
|
||||
import org.geysermc.geyser.level.block.property.Properties;
|
||||
import org.geysermc.geyser.level.block.type.BlockState;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
|
||||
public class SingleChestInventoryTranslator extends ChestInventoryTranslator {
|
||||
@ -38,17 +41,17 @@ public class SingleChestInventoryTranslator extends ChestInventoryTranslator {
|
||||
// TODO add barrel???
|
||||
public SingleChestInventoryTranslator(int size) {
|
||||
super(size, 27);
|
||||
this.holder = new BlockInventoryHolder("minecraft:chest[facing=north,type=single,waterlogged=false]", ContainerType.CONTAINER,
|
||||
this.holder = new BlockInventoryHolder(Blocks.CHEST.defaultBlockState().withValue(Properties.CHEST_TYPE, ChestType.SINGLE), ContainerType.CONTAINER,
|
||||
Blocks.ENDER_CHEST, Blocks.TRAPPED_CHEST) {
|
||||
@Override
|
||||
protected boolean isValidBlock(String[] javaBlockString) {
|
||||
if (javaBlockString[0].equals("minecraft:ender_chest")) {
|
||||
protected boolean isValidBlock(BlockState blockState) {
|
||||
if (blockState.is(Blocks.ENDER_CHEST)) {
|
||||
// Can't have double ender chests
|
||||
return true;
|
||||
}
|
||||
|
||||
// Add provision to ensure this isn't a double chest
|
||||
return super.isValidBlock(javaBlockString) && (javaBlockString.length > 1 && javaBlockString[1].contains("type=single"));
|
||||
return super.isValidBlock(blockState) && blockState.getValue(Properties.CHEST_TYPE) == ChestType.SINGLE;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -32,12 +32,14 @@ import org.geysermc.geyser.inventory.BedrockContainerSlot;
|
||||
import org.geysermc.geyser.inventory.Inventory;
|
||||
import org.geysermc.geyser.inventory.SlotType;
|
||||
import org.geysermc.geyser.inventory.updater.ContainerInventoryUpdater;
|
||||
import org.geysermc.geyser.level.block.property.Properties;
|
||||
import org.geysermc.geyser.level.block.type.Block;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.translator.inventory.AbstractBlockInventoryTranslator;
|
||||
|
||||
public abstract class AbstractFurnaceInventoryTranslator extends AbstractBlockInventoryTranslator {
|
||||
AbstractFurnaceInventoryTranslator(String javaBlockIdentifier, ContainerType containerType) {
|
||||
super(3, javaBlockIdentifier, containerType, ContainerInventoryUpdater.INSTANCE);
|
||||
AbstractFurnaceInventoryTranslator(Block javaBlock, ContainerType containerType) {
|
||||
super(3, javaBlock.defaultBlockState().withValue(Properties.LIT, false), containerType, ContainerInventoryUpdater.INSTANCE);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -28,10 +28,11 @@ package org.geysermc.geyser.translator.inventory.furnace;
|
||||
import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerSlotType;
|
||||
import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType;
|
||||
import org.geysermc.geyser.inventory.BedrockContainerSlot;
|
||||
import org.geysermc.geyser.level.block.Blocks;
|
||||
|
||||
public class BlastFurnaceInventoryTranslator extends AbstractFurnaceInventoryTranslator {
|
||||
public BlastFurnaceInventoryTranslator() {
|
||||
super("minecraft:blast_furnace[facing=north,lit=false]", ContainerType.BLAST_FURNACE);
|
||||
super(Blocks.BLAST_FURNACE, ContainerType.BLAST_FURNACE);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -28,10 +28,11 @@ package org.geysermc.geyser.translator.inventory.furnace;
|
||||
import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerSlotType;
|
||||
import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType;
|
||||
import org.geysermc.geyser.inventory.BedrockContainerSlot;
|
||||
import org.geysermc.geyser.level.block.Blocks;
|
||||
|
||||
public class FurnaceInventoryTranslator extends AbstractFurnaceInventoryTranslator {
|
||||
public FurnaceInventoryTranslator() {
|
||||
super("minecraft:furnace[facing=north,lit=false]", ContainerType.FURNACE);
|
||||
super(Blocks.FURNACE, ContainerType.FURNACE);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -28,10 +28,11 @@ package org.geysermc.geyser.translator.inventory.furnace;
|
||||
import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerSlotType;
|
||||
import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType;
|
||||
import org.geysermc.geyser.inventory.BedrockContainerSlot;
|
||||
import org.geysermc.geyser.level.block.Blocks;
|
||||
|
||||
public class SmokerInventoryTranslator extends AbstractFurnaceInventoryTranslator {
|
||||
public SmokerInventoryTranslator() {
|
||||
super("minecraft:smoker[facing=north,lit=false]", ContainerType.SMOKER);
|
||||
super(Blocks.SMOKER, ContainerType.SMOKER);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -28,7 +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.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.mcprotocollib.protocol.data.game.level.block.BlockEntityType;
|
||||
@ -47,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.javaId()) ? "aligned" : "rollable"); // TODO
|
||||
bedrockNbt.putString("joint", blockState.getValue(Properties.ORIENTATION).isHorizontal() ? "aligned" : "rollable");
|
||||
}
|
||||
bedrockNbt.putString("name", javaNbt.getString("name"));
|
||||
bedrockNbt.putString("target_pool", javaNbt.getString("target_pool"));
|
||||
|
@ -26,22 +26,24 @@
|
||||
package org.geysermc.geyser.translator.level.block.entity;
|
||||
|
||||
import it.unimi.dsi.fastutil.ints.IntArrays;
|
||||
import it.unimi.dsi.fastutil.objects.*;
|
||||
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.level.block.type.HoneyBlock;
|
||||
import org.geysermc.geyser.level.block.type.PistonBlock;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.level.block.value.PistonValueType;
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectMaps;
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
|
||||
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet;
|
||||
import lombok.Getter;
|
||||
import org.cloudburstmc.math.vector.Vector3d;
|
||||
import org.cloudburstmc.math.vector.Vector3f;
|
||||
import org.cloudburstmc.math.vector.Vector3i;
|
||||
import org.cloudburstmc.nbt.NbtMap;
|
||||
import org.cloudburstmc.nbt.NbtMapBuilder;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.UpdateBlockPacket;
|
||||
import lombok.Getter;
|
||||
import org.geysermc.geyser.api.util.PlatformType;
|
||||
import org.geysermc.geyser.level.block.BlockStateValues;
|
||||
import org.geysermc.geyser.level.block.Blocks;
|
||||
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.block.type.PistonBlock;
|
||||
import org.geysermc.geyser.level.physics.Axis;
|
||||
import org.geysermc.geyser.level.physics.BoundingBox;
|
||||
import org.geysermc.geyser.level.physics.CollisionManager;
|
||||
@ -53,6 +55,7 @@ import org.geysermc.geyser.translator.collision.BlockCollision;
|
||||
import org.geysermc.geyser.util.BlockEntityUtils;
|
||||
import org.geysermc.geyser.util.BlockUtils;
|
||||
import org.geysermc.geyser.util.ChunkUtils;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.level.block.value.PistonValueType;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.Map;
|
||||
@ -99,7 +102,7 @@ public class PistonBlockEntity {
|
||||
|
||||
static {
|
||||
// Create a ~1 x ~0.5 x ~1 bounding box above the honey block
|
||||
BlockCollision blockCollision = BlockRegistries.COLLISIONS.get(HoneyBlock.state().javaId());
|
||||
BlockCollision blockCollision = BlockRegistries.COLLISIONS.get(Blocks.HONEY_BLOCK.defaultBlockState().javaId());
|
||||
if (blockCollision == null) {
|
||||
throw new RuntimeException("Failed to find honey block collision");
|
||||
}
|
||||
@ -224,10 +227,10 @@ public class PistonBlockEntity {
|
||||
|
||||
private void removePistonHead() {
|
||||
Vector3i blockInFront = position.add(orientation.getUnitVector());
|
||||
int blockId = session.getGeyser().getWorldManager().getBlockAt(session, blockInFront);
|
||||
if (BlockStateValues.isPistonHead(blockId)) {
|
||||
BlockState state = session.getGeyser().getWorldManager().blockAt(session, blockInFront);
|
||||
if (state.is(Blocks.PISTON_HEAD)) {
|
||||
ChunkUtils.updateBlock(session, Block.JAVA_AIR_ID, blockInFront);
|
||||
} else if ((session.getGeyser().getPlatformType() == PlatformType.SPIGOT || session.getErosionHandler().isActive()) && blockId == Block.JAVA_AIR_ID) {
|
||||
} else if ((session.getGeyser().getPlatformType() == PlatformType.SPIGOT || session.getErosionHandler().isActive()) && state.is(Blocks.AIR)) {
|
||||
// Spigot removes the piston head from the cache, but we need to send the block update ourselves
|
||||
ChunkUtils.updateBlock(session, Block.JAVA_AIR_ID, blockInFront);
|
||||
}
|
||||
@ -353,7 +356,9 @@ public class PistonBlockEntity {
|
||||
playerBoundingBox.setSizeZ(playerBoundingBox.getSizeZ() - shrink.getZ());
|
||||
|
||||
// Resolve collision with the piston head
|
||||
BlockState pistonHeadId = BlockState.of(BlockStateValues.getPistonHead(orientation));
|
||||
BlockState pistonHeadId = Blocks.PISTON_HEAD.defaultBlockState()
|
||||
.withValue(Properties.SHORT, false)
|
||||
.withValue(Properties.FACING, orientation);
|
||||
pushPlayerBlock(pistonHeadId, getPistonHeadPos().toDouble(), blockMovement, playerBoundingBox);
|
||||
|
||||
// Resolve collision with any attached moving blocks, but skip slime blocks
|
||||
@ -562,9 +567,11 @@ public class PistonBlockEntity {
|
||||
|
||||
private BlockState getAttachedBlockId(Vector3i blockPos) {
|
||||
if (blockPos.equals(getPistonHeadPos())) {
|
||||
return BlockState.of(BlockStateValues.getPistonHead(orientation));
|
||||
return Blocks.PISTON_HEAD.defaultBlockState()
|
||||
.withValue(Properties.SHORT, false)
|
||||
.withValue(Properties.FACING, orientation);
|
||||
} else {
|
||||
return attachedBlocks.getOrDefault(blockPos, BlockState.of(Block.JAVA_AIR_ID)); //FIXME
|
||||
return attachedBlocks.getOrDefault(blockPos, Blocks.AIR.defaultBlockState());
|
||||
}
|
||||
}
|
||||
|
||||
@ -633,7 +640,9 @@ public class PistonBlockEntity {
|
||||
if (action == PistonValueType.PUSHING) {
|
||||
Vector3i pistonHeadPos = getPistonHeadPos().add(movement);
|
||||
if (!SOLID_BOUNDING_BOX.checkIntersection(pistonHeadPos.toDouble(), session.getCollisionManager().getPlayerBoundingBox())) {
|
||||
ChunkUtils.updateBlock(session, BlockStateValues.getPistonHead(orientation), pistonHeadPos);
|
||||
ChunkUtils.updateBlock(session, Blocks.PISTON_HEAD.defaultBlockState()
|
||||
.withValue(Properties.SHORT, false)
|
||||
.withValue(Properties.FACING, orientation), pistonHeadPos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -56,8 +56,8 @@ import org.geysermc.geyser.item.type.BlockItem;
|
||||
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.Blocks;
|
||||
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.block.type.CauldronBlock;
|
||||
@ -295,10 +295,10 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator<Inve
|
||||
*/
|
||||
|
||||
if (packet.getItemInHand() != null && session.getItemMappings().getMapping(packet.getItemInHand()).getJavaItem() instanceof SpawnEggItem) {
|
||||
int blockState = session.getGeyser().getWorldManager().getBlockAt(session, packet.getBlockPosition());
|
||||
if (blockState == BlockStateValues.JAVA_WATER_ID) {
|
||||
BlockState blockState = session.getGeyser().getWorldManager().blockAt(session, packet.getBlockPosition());
|
||||
if (blockState.is(Blocks.WATER) && blockState.getValue(Properties.LEVEL) == 0) {
|
||||
// Otherwise causes multiple mobs to spawn - just send a use item packet
|
||||
useItem(session, packet, blockState);
|
||||
useItem(session, packet, blockState.javaId());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -25,6 +25,7 @@
|
||||
|
||||
package org.geysermc.geyser.translator.protocol.java;
|
||||
|
||||
import com.google.common.base.Suppliers;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.command.CommandNode;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.command.CommandParser;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.command.properties.ResourceProperties;
|
||||
@ -54,12 +55,16 @@ import org.geysermc.geyser.translator.protocol.Translator;
|
||||
import org.geysermc.geyser.util.EntityUtils;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
@SuppressWarnings("removal") // We know. This is our doing.
|
||||
@Translator(packet = ClientboundCommandsPacket.class)
|
||||
public class JavaCommandsTranslator extends PacketTranslator<ClientboundCommandsPacket> {
|
||||
|
||||
private static final String[] ALL_BLOCK_NAMES = BlockRegistries.JAVA_BLOCKS.get().stream().map(block -> block.javaIdentifier().toString()).toArray(String[]::new);
|
||||
/**
|
||||
* Wait until the registries load before getting all the block names.
|
||||
*/
|
||||
private static final Supplier<String[]> ALL_BLOCK_NAMES = Suppliers.memoize(() -> BlockRegistries.JAVA_BLOCKS.get().stream().map(block -> block.javaIdentifier().toString()).toArray(String[]::new));
|
||||
private static final String[] ALL_EFFECT_IDENTIFIERS = EntityUtils.getAllEffectIdentifiers();
|
||||
private static final String[] ATTRIBUTES = AttributeType.Builtin.BUILTIN.values().stream().map(AttributeType::getIdentifier).toList().toArray(new String[0]);
|
||||
private static final String[] ENUM_BOOLEAN = {"true", "false"};
|
||||
@ -247,7 +252,7 @@ public class JavaCommandsTranslator extends PacketTranslator<ClientboundCommands
|
||||
case RESOURCE_LOCATION, FUNCTION -> CommandParam.FILE_PATH;
|
||||
case BOOL -> ENUM_BOOLEAN;
|
||||
case OPERATION -> CommandParam.OPERATOR; // ">=", "==", etc
|
||||
case BLOCK_STATE -> ALL_BLOCK_NAMES;
|
||||
case BLOCK_STATE -> ALL_BLOCK_NAMES.get();
|
||||
case ITEM_STACK -> context.getItemNames();
|
||||
case COLOR -> VALID_COLORS;
|
||||
case SCOREBOARD_SLOT -> VALID_SCOREBOARD_SLOTS;
|
||||
|
@ -31,7 +31,7 @@ import org.cloudburstmc.nbt.NbtMapBuilder;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.BlockEntityDataPacket;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.BlockEventPacket;
|
||||
import org.geysermc.geyser.api.util.PlatformType;
|
||||
import org.geysermc.geyser.level.block.BlockStateValues;
|
||||
import org.geysermc.geyser.level.block.Blocks;
|
||||
import org.geysermc.geyser.level.block.property.Properties;
|
||||
import org.geysermc.geyser.level.block.type.Block;
|
||||
import org.geysermc.geyser.level.block.type.BlockState;
|
||||
@ -78,8 +78,8 @@ public class JavaBlockEventTranslator extends PacketTranslator<ClientboundBlockE
|
||||
// Retracting sticky pistons is an exception, since the event is not called on Spigot from 1.13.2 - 1.17.1
|
||||
// See https://github.com/PaperMC/Paper/blob/6fa1983e9ce177a4a412d5b950fd978620174777/patches/server/0304-Fire-BlockPistonRetractEvent-for-all-empty-pistons.patch
|
||||
if (action == PistonValueType.PULLING || action == PistonValueType.CANCELLED_MID_PUSH) {
|
||||
int pistonBlock = session.getGeyser().getWorldManager().getBlockAt(session, position);
|
||||
if (!BlockStateValues.isStickyPiston(pistonBlock)) {
|
||||
BlockState pistonBlock = session.getGeyser().getWorldManager().blockAt(session, position);
|
||||
if (!pistonBlock.is(Blocks.STICKY_PISTON)) {
|
||||
return;
|
||||
}
|
||||
if (action != PistonValueType.CANCELLED_MID_PUSH) {
|
||||
@ -97,8 +97,8 @@ public class JavaBlockEventTranslator extends PacketTranslator<ClientboundBlockE
|
||||
}
|
||||
} else {
|
||||
PistonBlockEntity blockEntity = pistonCache.getPistons().computeIfAbsent(position, pos -> {
|
||||
int blockId = session.getGeyser().getWorldManager().getBlockAt(session, position);
|
||||
boolean sticky = BlockStateValues.isStickyPiston(blockId);
|
||||
BlockState state = session.getGeyser().getWorldManager().blockAt(session, position);
|
||||
boolean sticky = state.is(Blocks.STICKY_PISTON);
|
||||
boolean extended = action != PistonValueType.PUSHING;
|
||||
return new PistonBlockEntity(session, pos, direction, sticky, extended);
|
||||
});
|
||||
|
@ -65,7 +65,6 @@ 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" }
|
||||
@ -143,7 +142,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-reference-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" ]
|
||||
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