diff --git a/core/pom.xml b/core/pom.xml index 2d06c6bff..038f9ec8d 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -72,7 +72,7 @@ com.nukkitx nbt - 2.1.0 + 2.2.1 compile diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaLevelEventTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaLevelEventTranslator.java index 195835a15..8fcfa381f 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaLevelEventTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaLevelEventTranslator.java @@ -25,15 +25,15 @@ package org.geysermc.geyser.translator.protocol.java.level; +import com.github.steveice10.mc.protocol.data.game.entity.object.Direction; import com.github.steveice10.mc.protocol.data.game.level.event.*; import com.github.steveice10.mc.protocol.packet.ingame.clientbound.level.ClientboundLevelEventPacket; import com.nukkitx.math.vector.Vector3f; import com.nukkitx.math.vector.Vector3i; +import com.nukkitx.nbt.NbtMap; import com.nukkitx.protocol.bedrock.data.LevelEventType; import com.nukkitx.protocol.bedrock.data.SoundEvent; -import com.nukkitx.protocol.bedrock.packet.LevelEventPacket; -import com.nukkitx.protocol.bedrock.packet.LevelSoundEventPacket; -import com.nukkitx.protocol.bedrock.packet.TextPacket; +import com.nukkitx.protocol.bedrock.packet.*; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.registry.Registries; import org.geysermc.geyser.session.GeyserSession; @@ -44,6 +44,7 @@ import org.geysermc.geyser.translator.protocol.Translator; import java.util.Collections; import java.util.Locale; +import java.util.Set; @Translator(packet = ClientboundLevelEventPacket.class) public class JavaLevelEventTranslator extends PacketTranslator { @@ -257,6 +258,56 @@ public class JavaLevelEventTranslator extends PacketTranslator effectPacket.setType(LevelEventType.PARTICLE_WAX_ON); case WAX_OFF -> effectPacket.setType(LevelEventType.PARTICLE_WAX_OFF); case SCRAPE -> effectPacket.setType(LevelEventType.PARTICLE_SCRAPE); + case SCULK_BLOCK_CHARGE -> { + SculkBlockChargeEventData eventData = (SculkBlockChargeEventData) packet.getData(); + LevelEventGenericPacket levelEventPacket = new LevelEventGenericPacket(); + // TODO add SCULK_BLOCK_CHARGE sound + if (eventData.getCharge() > 0) { + levelEventPacket.setEventId(2037); + levelEventPacket.setTag( + NbtMap.builder() + .putInt("x", packet.getPosition().getX()) + .putInt("y", packet.getPosition().getY()) + .putInt("z", packet.getPosition().getZ()) + .putShort("charge", (short) eventData.getCharge()) + .putShort("facing", encodeFacing(eventData.getBlockFaces())) // TODO check if this is actually correct + .build() + ); + } else { + levelEventPacket.setEventId(2038); + levelEventPacket.setTag( + NbtMap.builder() + .putInt("x", packet.getPosition().getX()) + .putInt("y", packet.getPosition().getY()) + .putInt("z", packet.getPosition().getZ()) + .build() + ); + } + session.sendUpstreamPacket(levelEventPacket); + return; + } + case SCULK_SHRIEKER_SHRIEK -> { + LevelEventGenericPacket levelEventPacket = new LevelEventGenericPacket(); + levelEventPacket.setEventId(2035); + levelEventPacket.setTag( + NbtMap.builder() + .putInt("originX", packet.getPosition().getX()) + .putInt("originY", packet.getPosition().getY()) + .putInt("originZ", packet.getPosition().getZ()) + .build() + ); + session.sendUpstreamPacket(levelEventPacket); + + LevelSoundEventPacket soundEventPacket = new LevelSoundEventPacket(); + soundEventPacket.setSound(SoundEvent.SCULK_SHRIEKER_SHRIEK); + soundEventPacket.setPosition(packet.getPosition().toFloat()); + soundEventPacket.setExtraData(-1); + soundEventPacket.setIdentifier(""); + soundEventPacket.setBabySound(false); + soundEventPacket.setRelativeVolumeDisabled(false); + session.sendUpstreamPacket(soundEventPacket); + return; + } default -> { GeyserImpl.getInstance().getLogger().debug("Unhandled level event: " + packet.getEvent()); return; @@ -264,4 +315,27 @@ public class JavaLevelEventTranslator extends PacketTranslator blockFaces) { + short facing = 0; + if (blockFaces.contains(Direction.DOWN)) { + facing |= 1; + } + if (blockFaces.contains(Direction.UP)) { + facing |= 1 << 1; + } + if (blockFaces.contains(Direction.SOUTH)) { + facing |= 1 << 2; + } + if (blockFaces.contains(Direction.WEST)) { + facing |= 1 << 3; + } + if (blockFaces.contains(Direction.NORTH)) { + facing |= 1 << 4; + } + if (blockFaces.contains(Direction.EAST)) { + facing |= 1 << 5; + } + return facing; + } } \ No newline at end of file diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaLevelParticlesTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaLevelParticlesTranslator.java index de586b600..a413421a3 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaLevelParticlesTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaLevelParticlesTranslator.java @@ -27,13 +27,18 @@ package org.geysermc.geyser.translator.protocol.java.level; import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; import com.github.steveice10.mc.protocol.data.game.level.particle.*; +import com.github.steveice10.mc.protocol.data.game.level.particle.positionsource.BlockPositionSource; +import com.github.steveice10.mc.protocol.data.game.level.particle.positionsource.EntityPositionSource; import com.github.steveice10.mc.protocol.packet.ingame.clientbound.level.ClientboundLevelParticlesPacket; import com.nukkitx.math.vector.Vector3f; +import com.nukkitx.nbt.NbtMap; import com.nukkitx.protocol.bedrock.BedrockPacket; import com.nukkitx.protocol.bedrock.data.LevelEventType; import com.nukkitx.protocol.bedrock.data.inventory.ItemData; +import com.nukkitx.protocol.bedrock.packet.LevelEventGenericPacket; import com.nukkitx.protocol.bedrock.packet.LevelEventPacket; import com.nukkitx.protocol.bedrock.packet.SpawnParticleEffectPacket; +import org.geysermc.geyser.entity.type.Entity; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; @@ -131,6 +136,39 @@ public class JavaLevelParticlesTranslator extends PacketTranslator { + VibrationParticleData data = (VibrationParticleData) particle.getData(); + + Vector3f target; + if (data.getPositionSource() instanceof BlockPositionSource blockPositionSource) { + target = blockPositionSource.getPosition().toFloat().add(0.5f, 0.5f, 0.5f); + } else if (data.getPositionSource() instanceof EntityPositionSource entityPositionSource) { + Entity entity = session.getEntityCache().getEntityByJavaId(entityPositionSource.getEntityId()); + if (entity != null) { + target = entity.getPosition().up(entityPositionSource.getYOffset()); + } else { + session.getGeyser().getLogger().debug("Unable to find entity with Java Id: " + entityPositionSource.getEntityId() + " for vibration particle."); + return null; + } + } else { + session.getGeyser().getLogger().debug("Unknown position source " + data.getPositionSource() + " for vibration particle."); + return null; + } + + return (position) -> { + LevelEventGenericPacket packet = new LevelEventGenericPacket(); + packet.setEventId(2027); + packet.setTag( + NbtMap.builder() + .putCompound("origin", buildVec3PositionTag(position)) + .putCompound("target", buildVec3PositionTag(target)) // There is a way to target an entity but that takes an attachPos instead of a y offset + .putFloat("speed", 20f) + .putFloat("timeToLive", data.getArrivalTicks() / 20f) + .build() + ); + return packet; + }; + } default -> { ParticleMapping particleMapping = Registries.PARTICLES.get(particle.getType()); if (particleMapping == null) { //TODO ensure no particle can be null @@ -160,4 +198,13 @@ public class JavaLevelParticlesTranslator extends PacketTranslator