diff --git a/core/src/main/java/org/geysermc/geyser/registry/Registries.java b/core/src/main/java/org/geysermc/geyser/registry/Registries.java index 0b59492d3..8f2a9775a 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/Registries.java +++ b/core/src/main/java/org/geysermc/geyser/registry/Registries.java @@ -27,7 +27,7 @@ package org.geysermc.geyser.registry; import com.github.steveice10.mc.protocol.data.game.entity.type.EntityType; import com.github.steveice10.mc.protocol.data.game.level.block.BlockEntityType; -import com.github.steveice10.mc.protocol.data.game.level.event.SoundEvent; +import com.github.steveice10.mc.protocol.data.game.level.event.LevelEvent; import com.github.steveice10.mc.protocol.data.game.level.particle.ParticleType; import com.github.steveice10.mc.protocol.data.game.recipe.RecipeType; import com.github.steveice10.packetlib.packet.Packet; @@ -155,9 +155,9 @@ public final class Registries { public static final SimpleMappedRegistry SOUNDS = SimpleMappedRegistry.create("mappings/sounds.json", SoundRegistryLoader::new); /** - * A mapped registry holding {@link SoundEvent}s to their corresponding {@link LevelEventTranslator}. + * A mapped registry holding {@link LevelEvent}s to their corresponding {@link LevelEventTranslator}. */ - public static final SimpleMappedRegistry SOUND_EVENTS = SimpleMappedRegistry.create("mappings/effects.json", SoundEventsRegistryLoader::new); + public static final SimpleMappedRegistry SOUND_LEVEL_EVENTS = SimpleMappedRegistry.create("mappings/effects.json", SoundEventsRegistryLoader::new); /** * A mapped registry holding {@link SoundTranslator}s to their corresponding {@link SoundInteractionTranslator}. diff --git a/core/src/main/java/org/geysermc/geyser/registry/loader/SoundEventsRegistryLoader.java b/core/src/main/java/org/geysermc/geyser/registry/loader/SoundEventsRegistryLoader.java index fa7898f97..64d974bc3 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/loader/SoundEventsRegistryLoader.java +++ b/core/src/main/java/org/geysermc/geyser/registry/loader/SoundEventsRegistryLoader.java @@ -26,7 +26,7 @@ package org.geysermc.geyser.registry.loader; import com.fasterxml.jackson.databind.JsonNode; -import com.github.steveice10.mc.protocol.data.game.level.event.SoundEvent; +import com.github.steveice10.mc.protocol.data.game.level.event.LevelEvent; import com.nukkitx.protocol.bedrock.data.LevelEventType; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import org.geysermc.geyser.GeyserImpl; @@ -41,37 +41,37 @@ import java.util.Map; /** * Loads sound effects from the given resource path. */ -public class SoundEventsRegistryLoader extends EffectRegistryLoader> { +public class SoundEventsRegistryLoader extends EffectRegistryLoader> { @Override - public Map load(String input) { + public Map load(String input) { this.loadFile(input); Iterator> effectsIterator = this.get(input).fields(); - Map soundEffects = new Object2ObjectOpenHashMap<>(); + Map soundEffects = new Object2ObjectOpenHashMap<>(); while (effectsIterator.hasNext()) { Map.Entry entry = effectsIterator.next(); JsonNode node = entry.getValue(); try { String type = node.get("type").asText(); - SoundEvent javaEffect = null; + LevelEvent javaEffect = null; LevelEventTranslator transformer = null; switch (type) { case "soundLevel" -> { - javaEffect = SoundEvent.valueOf(entry.getKey()); + javaEffect = LevelEvent.valueOf(entry.getKey()); LevelEventType levelEventType = LevelEventType.valueOf(node.get("name").asText()); int data = node.has("data") ? node.get("data").intValue() : 0; transformer = new SoundLevelEventTranslator(levelEventType, data); } case "soundEvent" -> { - javaEffect = SoundEvent.valueOf(entry.getKey()); + javaEffect = LevelEvent.valueOf(entry.getKey()); com.nukkitx.protocol.bedrock.data.SoundEvent soundEvent = com.nukkitx.protocol.bedrock.data.SoundEvent.valueOf(node.get("name").asText()); String identifier = node.has("identifier") ? node.get("identifier").asText() : ""; int extraData = node.has("extraData") ? node.get("extraData").intValue() : -1; transformer = new SoundEventEventTranslator(soundEvent, identifier, extraData); } case "playSound" -> { - javaEffect = SoundEvent.valueOf(entry.getKey()); + javaEffect = LevelEvent.valueOf(entry.getKey()); String name = node.get("name").asText(); float volume = node.has("volume") ? node.get("volume").floatValue() : 1.0f; boolean pitchSub = node.has("pitch_sub") && node.get("pitch_sub").booleanValue(); @@ -85,7 +85,7 @@ public class SoundEventsRegistryLoader extends EffectRegistryLoader { + effectPacket.setType(LevelEventType.PARTICLE_CROP_GROWTH); + + ComposterEventData composterEventData = (ComposterEventData) packet.getData(); + LevelSoundEventPacket soundEventPacket = new LevelSoundEventPacket(); + switch (composterEventData) { + case FILL -> soundEventPacket.setSound(SoundEvent.COMPOSTER_FILL); + case FILL_SUCCESS -> soundEventPacket.setSound(SoundEvent.COMPOSTER_FILL_LAYER); + } + soundEventPacket.setPosition(pos); + soundEventPacket.setIdentifier(""); + soundEventPacket.setExtraData(-1); + soundEventPacket.setBabySound(false); + soundEventPacket.setRelativeVolumeDisabled(false); + session.sendUpstreamPacket(soundEventPacket); } - GeyserImpl.getInstance().getLogger().debug("Unhandled sound event: " + soundEvent.name()); - } else if (packet.getEvent() instanceof ParticleEvent particleEvent) { - Vector3i origin = packet.getPosition(); - Vector3f pos = Vector3f.from(origin.getX() + 0.5f, origin.getY() + 0.5f, origin.getZ() + 0.5f); + case BLOCK_LAVA_EXTINGUISH -> { + effectPacket.setType(LevelEventType.PARTICLE_EVAPORATE); + effectPacket.setPosition(pos.add(-0.5f, 0.7f, -0.5f)); - LevelEventPacket effectPacket = new LevelEventPacket(); - effectPacket.setPosition(pos); - effectPacket.setData(0); - switch (particleEvent) { - case COMPOSTER -> { - effectPacket.setType(LevelEventType.PARTICLE_CROP_GROWTH); + LevelSoundEventPacket soundEventPacket = new LevelSoundEventPacket(); + soundEventPacket.setSound(SoundEvent.EXTINGUISH_FIRE); + soundEventPacket.setPosition(pos); + soundEventPacket.setIdentifier(""); + soundEventPacket.setExtraData(-1); + soundEventPacket.setBabySound(false); + soundEventPacket.setRelativeVolumeDisabled(false); + session.sendUpstreamPacket(soundEventPacket); + } + case BLOCK_REDSTONE_TORCH_BURNOUT -> { + effectPacket.setType(LevelEventType.PARTICLE_EVAPORATE); + effectPacket.setPosition(pos.add(-0.5f, 0, -0.5f)); - ComposterEventData composterEventData = (ComposterEventData) packet.getData(); - LevelSoundEventPacket soundEventPacket = new LevelSoundEventPacket(); - switch (composterEventData) { - case FILL -> soundEventPacket.setSound(SoundEvent.COMPOSTER_FILL); - case FILL_SUCCESS -> soundEventPacket.setSound(SoundEvent.COMPOSTER_FILL_LAYER); + LevelSoundEventPacket soundEventPacket = new LevelSoundEventPacket(); + soundEventPacket.setSound(SoundEvent.EXTINGUISH_FIRE); + soundEventPacket.setPosition(pos); + soundEventPacket.setIdentifier(""); + soundEventPacket.setExtraData(-1); + soundEventPacket.setBabySound(false); + soundEventPacket.setRelativeVolumeDisabled(false); + session.sendUpstreamPacket(soundEventPacket); + } + case BLOCK_END_PORTAL_FRAME_FILL -> { + effectPacket.setType(LevelEventType.PARTICLE_EVAPORATE); + effectPacket.setPosition(pos.add(-0.5f, 0.3125f, -0.5f)); + + LevelSoundEventPacket soundEventPacket = new LevelSoundEventPacket(); + soundEventPacket.setSound(SoundEvent.BLOCK_END_PORTAL_FRAME_FILL); + soundEventPacket.setPosition(pos); + soundEventPacket.setIdentifier(""); + soundEventPacket.setExtraData(-1); + soundEventPacket.setBabySound(false); + soundEventPacket.setRelativeVolumeDisabled(false); + session.sendUpstreamPacket(soundEventPacket); + } + case SMOKE -> { + effectPacket.setType(LevelEventType.PARTICLE_SHOOT); + + SmokeEventData smokeEventData = (SmokeEventData) packet.getData(); + int data = 0; + switch (smokeEventData) { + case DOWN -> { + data = 4; + pos = pos.add(0, -0.9f, 0); } - soundEventPacket.setPosition(pos); - soundEventPacket.setIdentifier(""); - soundEventPacket.setExtraData(-1); - soundEventPacket.setBabySound(false); - soundEventPacket.setRelativeVolumeDisabled(false); - session.sendUpstreamPacket(soundEventPacket); - } - case BLOCK_LAVA_EXTINGUISH -> { - effectPacket.setType(LevelEventType.PARTICLE_EVAPORATE); - effectPacket.setPosition(pos.add(-0.5f, 0.7f, -0.5f)); - - LevelSoundEventPacket soundEventPacket = new LevelSoundEventPacket(); - soundEventPacket.setSound(SoundEvent.EXTINGUISH_FIRE); - soundEventPacket.setPosition(pos); - soundEventPacket.setIdentifier(""); - soundEventPacket.setExtraData(-1); - soundEventPacket.setBabySound(false); - soundEventPacket.setRelativeVolumeDisabled(false); - session.sendUpstreamPacket(soundEventPacket); - } - case BLOCK_REDSTONE_TORCH_BURNOUT -> { - effectPacket.setType(LevelEventType.PARTICLE_EVAPORATE); - effectPacket.setPosition(pos.add(-0.5f, 0, -0.5f)); - - LevelSoundEventPacket soundEventPacket = new LevelSoundEventPacket(); - soundEventPacket.setSound(SoundEvent.EXTINGUISH_FIRE); - soundEventPacket.setPosition(pos); - soundEventPacket.setIdentifier(""); - soundEventPacket.setExtraData(-1); - soundEventPacket.setBabySound(false); - soundEventPacket.setRelativeVolumeDisabled(false); - session.sendUpstreamPacket(soundEventPacket); - } - case BLOCK_END_PORTAL_FRAME_FILL -> { - effectPacket.setType(LevelEventType.PARTICLE_EVAPORATE); - effectPacket.setPosition(pos.add(-0.5f, 0.3125f, -0.5f)); - - LevelSoundEventPacket soundEventPacket = new LevelSoundEventPacket(); - soundEventPacket.setSound(SoundEvent.BLOCK_END_PORTAL_FRAME_FILL); - soundEventPacket.setPosition(pos); - soundEventPacket.setIdentifier(""); - soundEventPacket.setExtraData(-1); - soundEventPacket.setBabySound(false); - soundEventPacket.setRelativeVolumeDisabled(false); - session.sendUpstreamPacket(soundEventPacket); - } - case SMOKE -> { - effectPacket.setType(LevelEventType.PARTICLE_SHOOT); - - SmokeEventData smokeEventData = (SmokeEventData) packet.getData(); - int data = 0; - switch (smokeEventData) { - case DOWN -> { - data = 4; - pos = pos.add(0, -0.9f, 0); - } - case UP -> { - data = 4; - pos = pos.add(0, 0.5f, 0); - } - case NORTH -> { - data = 1; - pos = pos.add(0, -0.2f, -0.7f); - } - case SOUTH -> { - data = 7; - pos = pos.add(0, -0.2f, 0.7f); - } - case WEST -> { - data = 3; - pos = pos.add(-0.7f, -0.2f, 0); - } - case EAST -> { - data = 5; - pos = pos.add(0.7f, -0.2f, 0); - } + case UP -> { + data = 4; + pos = pos.add(0, 0.5f, 0); } - effectPacket.setPosition(pos); - effectPacket.setData(data); - } - - //TODO: Block break particles when under fire - case BREAK_BLOCK -> { - effectPacket.setType(LevelEventType.PARTICLE_DESTROY_BLOCK); - - BreakBlockEventData breakBlockEventData = (BreakBlockEventData) packet.getData(); - effectPacket.setData(session.getBlockMappings().getBedrockBlockId(breakBlockEventData.getBlockState())); - } - case BREAK_SPLASH_POTION -> { - effectPacket.setType(LevelEventType.PARTICLE_POTION_SPLASH); - effectPacket.setPosition(pos.add(0, -0.5f, 0)); - - BreakPotionEventData splashPotionData = (BreakPotionEventData) packet.getData(); - effectPacket.setData(splashPotionData.getPotionId()); - - LevelSoundEventPacket soundEventPacket = new LevelSoundEventPacket(); - soundEventPacket.setSound(SoundEvent.GLASS); - soundEventPacket.setPosition(pos); - soundEventPacket.setIdentifier(""); - soundEventPacket.setExtraData(-1); - soundEventPacket.setBabySound(false); - soundEventPacket.setRelativeVolumeDisabled(false); - session.sendUpstreamPacket(soundEventPacket); - } - case BREAK_EYE_OF_ENDER -> effectPacket.setType(LevelEventType.PARTICLE_EYE_OF_ENDER_DEATH); - case MOB_SPAWN -> effectPacket.setType(LevelEventType.PARTICLE_MOB_BLOCK_SPAWN); // TODO: Check, but I don't think I really verified this ever went into effect on Java - case BONEMEAL_GROW_WITH_SOUND, BONEMEAL_GROW -> { - effectPacket.setType(particleEvent == ParticleEvent.BONEMEAL_GROW ? LevelEventType.PARTICLE_TURTLE_EGG : LevelEventType.PARTICLE_CROP_GROWTH); - - BonemealGrowEventData growEventData = (BonemealGrowEventData) packet.getData(); - effectPacket.setData(growEventData.getParticleCount()); - } - case ENDERDRAGON_FIREBALL_EXPLODE -> { - effectPacket.setType(LevelEventType.PARTICLE_EYE_OF_ENDER_DEATH); // TODO - - DragonFireballEventData fireballEventData = (DragonFireballEventData) packet.getData(); - if (fireballEventData == DragonFireballEventData.HAS_SOUND) { - LevelSoundEventPacket soundEventPacket = new LevelSoundEventPacket(); - soundEventPacket.setSound(SoundEvent.EXPLODE); - soundEventPacket.setPosition(pos); - soundEventPacket.setIdentifier(""); - soundEventPacket.setExtraData(-1); - soundEventPacket.setBabySound(false); - soundEventPacket.setRelativeVolumeDisabled(false); - session.sendUpstreamPacket(soundEventPacket); + case NORTH -> { + data = 1; + pos = pos.add(0, -0.2f, -0.7f); + } + case SOUTH -> { + data = 7; + pos = pos.add(0, -0.2f, 0.7f); + } + case WEST -> { + data = 3; + pos = pos.add(-0.7f, -0.2f, 0); + } + case EAST -> { + data = 5; + pos = pos.add(0.7f, -0.2f, 0); } } - case EXPLOSION -> { - effectPacket.setType(LevelEventType.PARTICLE_GENERIC_SPAWN); - effectPacket.setData(61); - } - case EVAPORATE -> { - effectPacket.setType(LevelEventType.PARTICLE_EVAPORATE_WATER); - effectPacket.setPosition(pos.add(-0.5f, 0.5f, -0.5f)); - } - case END_GATEWAY_SPAWN -> { - effectPacket.setType(LevelEventType.PARTICLE_EXPLOSION); + effectPacket.setPosition(pos); + effectPacket.setData(data); + } + //TODO: Block break particles when under fire + case BREAK_BLOCK -> { + effectPacket.setType(LevelEventType.PARTICLE_DESTROY_BLOCK); + + BreakBlockEventData breakBlockEventData = (BreakBlockEventData) packet.getData(); + effectPacket.setData(session.getBlockMappings().getBedrockBlockId(breakBlockEventData.getBlockState())); + } + case BREAK_SPLASH_POTION, BREAK_SPLASH_POTION2 -> { + effectPacket.setType(LevelEventType.PARTICLE_POTION_SPLASH); + effectPacket.setPosition(pos.add(0, -0.5f, 0)); + + BreakPotionEventData splashPotionData = (BreakPotionEventData) packet.getData(); + effectPacket.setData(splashPotionData.getPotionId()); + + LevelSoundEventPacket soundEventPacket = new LevelSoundEventPacket(); + soundEventPacket.setSound(SoundEvent.GLASS); + soundEventPacket.setPosition(pos); + soundEventPacket.setIdentifier(""); + soundEventPacket.setExtraData(-1); + soundEventPacket.setBabySound(false); + soundEventPacket.setRelativeVolumeDisabled(false); + session.sendUpstreamPacket(soundEventPacket); + } + case BREAK_EYE_OF_ENDER -> effectPacket.setType(LevelEventType.PARTICLE_EYE_OF_ENDER_DEATH); + case MOB_SPAWN -> effectPacket.setType(LevelEventType.PARTICLE_MOB_BLOCK_SPAWN); // TODO: Check, but I don't think I really verified this ever went into effect on Java + case BONEMEAL_GROW_WITH_SOUND, BONEMEAL_GROW -> { + effectPacket.setType(packet.getEvent() == LevelEvent.BONEMEAL_GROW ? LevelEventType.PARTICLE_TURTLE_EGG : LevelEventType.PARTICLE_CROP_GROWTH); + + BonemealGrowEventData growEventData = (BonemealGrowEventData) packet.getData(); + effectPacket.setData(growEventData.getParticleCount()); + } + case ENDERDRAGON_FIREBALL_EXPLODE -> { + effectPacket.setType(LevelEventType.PARTICLE_EYE_OF_ENDER_DEATH); // TODO + + DragonFireballEventData fireballEventData = (DragonFireballEventData) packet.getData(); + if (fireballEventData == DragonFireballEventData.HAS_SOUND) { LevelSoundEventPacket soundEventPacket = new LevelSoundEventPacket(); soundEventPacket.setSound(SoundEvent.EXPLODE); soundEventPacket.setPosition(pos); @@ -253,17 +231,37 @@ public class JavaLevelEventTranslator extends PacketTranslator effectPacket.setType(LevelEventType.PARTICLE_DRIPSTONE_DRIP); - case ELECTRIC_SPARK -> effectPacket.setType(LevelEventType.PARTICLE_ELECTRIC_SPARK); // Matches with a Bedrock server but doesn't seem to match up with Java - case WAX_ON -> effectPacket.setType(LevelEventType.PARTICLE_WAX_ON); - case WAX_OFF -> effectPacket.setType(LevelEventType.PARTICLE_WAX_OFF); - case SCRAPE -> effectPacket.setType(LevelEventType.PARTICLE_SCRAPE); - default -> { - GeyserImpl.getInstance().getLogger().debug("Unhandled particle event: " + particleEvent.name()); - return; - } } - session.sendUpstreamPacket(effectPacket); + case EXPLOSION -> { + effectPacket.setType(LevelEventType.PARTICLE_GENERIC_SPAWN); + effectPacket.setData(61); + } + case EVAPORATE -> { + effectPacket.setType(LevelEventType.PARTICLE_EVAPORATE_WATER); + effectPacket.setPosition(pos.add(-0.5f, 0.5f, -0.5f)); + } + case END_GATEWAY_SPAWN -> { + effectPacket.setType(LevelEventType.PARTICLE_EXPLOSION); + + LevelSoundEventPacket soundEventPacket = new LevelSoundEventPacket(); + soundEventPacket.setSound(SoundEvent.EXPLODE); + soundEventPacket.setPosition(pos); + soundEventPacket.setIdentifier(""); + soundEventPacket.setExtraData(-1); + soundEventPacket.setBabySound(false); + soundEventPacket.setRelativeVolumeDisabled(false); + session.sendUpstreamPacket(soundEventPacket); + } + case DRIPSTONE_DRIP -> effectPacket.setType(LevelEventType.PARTICLE_DRIPSTONE_DRIP); + case ELECTRIC_SPARK -> effectPacket.setType(LevelEventType.PARTICLE_ELECTRIC_SPARK); // Matches with a Bedrock server but doesn't seem to match up with Java + case WAX_ON -> effectPacket.setType(LevelEventType.PARTICLE_WAX_ON); + case WAX_OFF -> effectPacket.setType(LevelEventType.PARTICLE_WAX_OFF); + case SCRAPE -> effectPacket.setType(LevelEventType.PARTICLE_SCRAPE); + default -> { + GeyserImpl.getInstance().getLogger().debug("Unhandled level event: " + packet.getEvent()); + return; + } } + session.sendUpstreamPacket(effectPacket); } } \ No newline at end of file