mirror of
https://github.com/GeyserMC/Geyser.git
synced 2024-08-14 23:57:35 +00:00
Set entities silent client-side, and more
Add warden entity events. Fix up other things.
This commit is contained in:
parent
bf4e1d5be7
commit
196742a597
13 changed files with 86 additions and 51 deletions
|
@ -184,7 +184,7 @@ public final class EntityDefinitions {
|
|||
.addTranslator(MetadataType.INT, Entity::setAir) // Air/bubbles
|
||||
.addTranslator(MetadataType.OPTIONAL_CHAT, Entity::setDisplayName)
|
||||
.addTranslator(MetadataType.BOOLEAN, Entity::setDisplayNameVisible)
|
||||
.addTranslator(MetadataType.BOOLEAN, (entity, entityMetadata) -> entity.setFlag(EntityFlag.SILENT, ((BooleanEntityMetadata) entityMetadata).getPrimitiveValue()))
|
||||
.addTranslator(MetadataType.BOOLEAN, Entity::setSilent)
|
||||
.addTranslator(MetadataType.BOOLEAN, Entity::setGravity)
|
||||
.addTranslator(MetadataType.POSE, (entity, entityMetadata) -> entity.setPose(entityMetadata.getValue()))
|
||||
.addTranslator(MetadataType.INT, Entity::setFreezing)
|
||||
|
|
|
@ -23,11 +23,11 @@
|
|||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.entity;
|
||||
package org.geysermc.geyser.entity.type;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import org.geysermc.geyser.entity.type.BoatEntity;
|
||||
import org.geysermc.geyser.entity.EntityDefinition;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.util.InteractionResult;
|
||||
import org.geysermc.geyser.util.InteractiveTag;
|
|
@ -94,6 +94,8 @@ public class Entity {
|
|||
private float boundingBoxWidth;
|
||||
@Setter(AccessLevel.NONE)
|
||||
protected String nametag = "";
|
||||
@Setter(AccessLevel.NONE)
|
||||
protected boolean silent = false;
|
||||
/* Metadata end */
|
||||
|
||||
protected List<Entity> passengers = Collections.emptyList();
|
||||
|
@ -148,6 +150,12 @@ public class Entity {
|
|||
setFlag(EntityFlag.HAS_COLLISION, true);
|
||||
setFlag(EntityFlag.CAN_SHOW_NAME, true);
|
||||
setFlag(EntityFlag.CAN_CLIMB, true);
|
||||
// Let the Java server (or us) supply all sounds for an entity
|
||||
setClientSideSilent();
|
||||
}
|
||||
|
||||
protected void setClientSideSilent() {
|
||||
setFlag(EntityFlag.SILENT, true);
|
||||
}
|
||||
|
||||
public void spawnEntity() {
|
||||
|
@ -370,6 +378,10 @@ public class Entity {
|
|||
dirtyMetadata.put(EntityData.NAMETAG_ALWAYS_SHOW, (byte) (entityMetadata.getPrimitiveValue() ? 1 : 0));
|
||||
}
|
||||
|
||||
public final void setSilent(BooleanEntityMetadata entityMetadata) {
|
||||
silent = entityMetadata.getPrimitiveValue();
|
||||
}
|
||||
|
||||
public void setGravity(BooleanEntityMetadata entityMetadata) {
|
||||
setFlag(EntityFlag.HAS_GRAVITY, !entityMetadata.getPrimitiveValue());
|
||||
}
|
||||
|
|
|
@ -27,7 +27,6 @@ package org.geysermc.geyser.entity.type;
|
|||
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
|
||||
import com.nukkitx.protocol.bedrock.packet.PlaySoundPacket;
|
||||
import org.geysermc.geyser.entity.EntityDefinition;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
|
@ -58,7 +57,7 @@ public class EvokerFangsEntity extends Entity implements Tickable {
|
|||
|
||||
public void setAttackStarted() {
|
||||
this.attackStarted = true;
|
||||
if (!getFlag(EntityFlag.SILENT)) {
|
||||
if (!silent) {
|
||||
// Play the chomp sound
|
||||
PlaySoundPacket packet = new PlaySoundPacket();
|
||||
packet.setPosition(this.position);
|
||||
|
|
|
@ -28,17 +28,16 @@ package org.geysermc.geyser.entity.type;
|
|||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
|
||||
import com.nukkitx.protocol.bedrock.packet.PlaySoundPacket;
|
||||
import lombok.Getter;
|
||||
import org.geysermc.geyser.entity.EntityDefinitions;
|
||||
import org.geysermc.geyser.entity.type.player.PlayerEntity;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.level.physics.BoundingBox;
|
||||
import org.geysermc.geyser.translator.collision.BlockCollision;
|
||||
import org.geysermc.geyser.level.block.BlockStateValues;
|
||||
import org.geysermc.geyser.registry.BlockRegistries;
|
||||
import org.geysermc.geyser.level.block.BlockPositionIterator;
|
||||
import org.geysermc.geyser.level.block.BlockStateValues;
|
||||
import org.geysermc.geyser.level.physics.BoundingBox;
|
||||
import org.geysermc.geyser.registry.BlockRegistries;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.translator.collision.BlockCollision;
|
||||
import org.geysermc.geyser.util.BlockUtils;
|
||||
|
||||
import java.util.UUID;
|
||||
|
@ -129,7 +128,7 @@ public class FishingHookEntity extends ThrowableEntity {
|
|||
}
|
||||
|
||||
private void sendSplashSound(GeyserSession session) {
|
||||
if (!getFlag(EntityFlag.SILENT)) {
|
||||
if (!silent) {
|
||||
float volume = (float) (0.2f * Math.sqrt(0.2 * (motion.getX() * motion.getX() + motion.getZ() * motion.getZ()) + motion.getY() * motion.getY()));
|
||||
if (volume > 1) {
|
||||
volume = 1;
|
||||
|
|
|
@ -213,7 +213,7 @@ public class EnderDragonEntity extends MobEntity implements Tickable {
|
|||
*/
|
||||
private void effectTick() {
|
||||
Random random = ThreadLocalRandom.current();
|
||||
if (!getFlag(EntityFlag.SILENT)) {
|
||||
if (!silent) {
|
||||
if (Math.cos(wingPosition * 2f * Math.PI) <= -0.3f && Math.cos(lastWingPosition * 2f * Math.PI) >= -0.3f) {
|
||||
PlaySoundPacket playSoundPacket = new PlaySoundPacket();
|
||||
playSoundPacket.setSound("mob.enderdragon.flap");
|
||||
|
|
|
@ -31,13 +31,19 @@ import com.nukkitx.math.GenericMath;
|
|||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
|
||||
import com.nukkitx.protocol.bedrock.packet.PlaySoundPacket;
|
||||
import org.geysermc.geyser.entity.EntityDefinition;
|
||||
import org.geysermc.geyser.entity.type.Tickable;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.util.MathUtils;
|
||||
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
public class WardenEntity extends MonsterEntity implements Tickable {
|
||||
private int heartBeatDelay;
|
||||
private int tickCount;
|
||||
|
||||
public class WardenEntity extends MonsterEntity {
|
||||
public WardenEntity(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);
|
||||
}
|
||||
|
@ -53,6 +59,23 @@ public class WardenEntity extends MonsterEntity {
|
|||
|
||||
public void setAngerLevel(IntEntityMetadata entityMetadata) {
|
||||
float anger = (float) entityMetadata.getPrimitiveValue() / 80f;
|
||||
dirtyMetadata.put(EntityData.HEARTBEAT_INTERVAL_TICKS, 40 - GenericMath.floor(MathUtils.clamp(anger, 0.0F, 1.0F) * 30F));
|
||||
heartBeatDelay = 40 - GenericMath.floor(MathUtils.clamp(anger, 0.0F, 1.0F) * 30F);
|
||||
dirtyMetadata.put(EntityData.HEARTBEAT_INTERVAL_TICKS, heartBeatDelay);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
if (++tickCount % heartBeatDelay == 0 && !silent) {
|
||||
// We have to do these calculations because they're clientside on Java Edition but we mute entities
|
||||
// to prevent hearing their step sounds
|
||||
ThreadLocalRandom random = ThreadLocalRandom.current();
|
||||
|
||||
PlaySoundPacket packet = new PlaySoundPacket();
|
||||
packet.setSound("mob.warden.heartbeat");
|
||||
packet.setPosition(position);
|
||||
packet.setPitch(1.0f);
|
||||
packet.setVolume((random.nextFloat() - random.nextFloat()) * 0.2f + 1.0f);
|
||||
session.sendUpstreamPacket(packet);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -75,6 +75,11 @@ public class SessionPlayerEntity extends PlayerEntity {
|
|||
valid = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setClientSideSilent() {
|
||||
// Do nothing, since we want the session player to hear their own footstep sounds for example.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void spawnEntity() {
|
||||
// Already logged in
|
||||
|
|
|
@ -38,10 +38,10 @@ public class SoundMapping {
|
|||
|
||||
public SoundMapping(String java, String bedrock, String playsound, int extraData, String identifier, boolean levelEvent) {
|
||||
this.java = java;
|
||||
this.bedrock = bedrock == null || bedrock.equalsIgnoreCase("") ? null : bedrock;
|
||||
this.playsound = playsound == null || playsound.equalsIgnoreCase("") ? null : playsound;
|
||||
this.bedrock = bedrock == null || bedrock.isEmpty() ? null : bedrock;
|
||||
this.playsound = playsound == null || playsound.isEmpty() ? null : playsound;
|
||||
this.extraData = extraData;
|
||||
this.identifier = identifier == null || identifier.equalsIgnoreCase("") ? ":" : identifier;
|
||||
this.identifier = identifier == null || identifier.isEmpty() ? ":" : identifier;
|
||||
this.levelEvent = levelEvent;
|
||||
}
|
||||
}
|
|
@ -26,7 +26,6 @@
|
|||
package org.geysermc.geyser.translator.protocol.java.entity;
|
||||
|
||||
import com.github.steveice10.mc.protocol.packet.ingame.clientbound.entity.ClientboundEntityEventPacket;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.protocol.bedrock.data.LevelEventType;
|
||||
import com.nukkitx.protocol.bedrock.data.SoundEvent;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
|
||||
|
@ -42,7 +41,6 @@ import org.geysermc.geyser.session.GeyserSession;
|
|||
import org.geysermc.geyser.translator.protocol.PacketTranslator;
|
||||
import org.geysermc.geyser.translator.protocol.Translator;
|
||||
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
@Translator(packet = ClientboundEntityEventPacket.class)
|
||||
|
@ -50,6 +48,7 @@ public class JavaEntityEventTranslator extends PacketTranslator<ClientboundEntit
|
|||
|
||||
@Override
|
||||
public void translate(GeyserSession session, ClientboundEntityEventPacket packet) {
|
||||
System.out.println(packet);
|
||||
Entity entity = session.getEntityCache().getEntityByJavaId(packet.getEntityId());
|
||||
if (entity == null)
|
||||
return;
|
||||
|
@ -180,8 +179,9 @@ public class JavaEntityEventTranslator extends PacketTranslator<ClientboundEntit
|
|||
case IRON_GOLEM_EMPTY_HAND:
|
||||
entityEventPacket.setType(EntityEventType.GOLEM_FLOWER_WITHDRAW);
|
||||
break;
|
||||
case IRON_GOLEM_ATTACK:
|
||||
if (entity.getDefinition() == EntityDefinitions.IRON_GOLEM || entity.getDefinition() == EntityDefinitions.EVOKER_FANGS) {
|
||||
case ATTACK:
|
||||
if (entity.getDefinition() == EntityDefinitions.IRON_GOLEM || entity.getDefinition() == EntityDefinitions.EVOKER_FANGS
|
||||
|| entity.getDefinition() == EntityDefinitions.WARDEN) {
|
||||
entityEventPacket.setType(EntityEventType.ATTACK_START);
|
||||
if (entity.getDefinition() == EntityDefinitions.EVOKER_FANGS) {
|
||||
((EvokerFangsEntity) entity).setAttackStarted();
|
||||
|
@ -236,28 +236,14 @@ public class JavaEntityEventTranslator extends PacketTranslator<ClientboundEntit
|
|||
break;
|
||||
case MAKE_POOF_PARTICLES:
|
||||
if (entity instanceof LivingEntity) {
|
||||
// Not ideal, but...
|
||||
// LevelEventType.PARTICLE_DEATH_SMOKE doesn't work (as of 1.18.2 Bedrock)
|
||||
// EntityEventType.DEATH_SMOKE_CLOUD also plays the entity death noise
|
||||
// Bedrock sends the particles through EntityEventType.DEATH, but Java despawns the entity
|
||||
// prematurely so they don't show up.
|
||||
Vector3f position = entity.getPosition();
|
||||
float baseX = position.getX();
|
||||
float baseY = position.getY();
|
||||
float baseZ = position.getZ();
|
||||
float height = entity.getBoundingBoxHeight();
|
||||
float width = entity.getBoundingBoxWidth();
|
||||
Random random = ThreadLocalRandom.current();
|
||||
for (int i = 0; i < 20; i++) {
|
||||
// Reconstruct the Java Edition (1.18.1) logic, but in floats
|
||||
float x = baseX + width * (2.0f * random.nextFloat() - 1f);
|
||||
float y = baseY + height * random.nextFloat();
|
||||
float z = baseZ + width * (2.0f * random.nextFloat() - 1f);
|
||||
LevelEventPacket levelEventPacket = new LevelEventPacket();
|
||||
levelEventPacket.setPosition(Vector3f.from(x, y, z));
|
||||
levelEventPacket.setType(LevelEventType.PARTICLE_EXPLODE);
|
||||
session.sendUpstreamPacket(levelEventPacket);
|
||||
}
|
||||
// Note that this event usually makes noise, but because we set all entities as silent on the
|
||||
// client end this isn't an issue.
|
||||
entityEventPacket.setType(EntityEventType.DEATH_SMOKE_CLOUD);
|
||||
}
|
||||
break;
|
||||
case WARDEN_RECEIVE_SIGNAL:
|
||||
if (entity.getDefinition() == EntityDefinitions.WARDEN) {
|
||||
entityEventPacket.setType(EntityEventType.VIBRATION_DETECTED);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -40,6 +40,6 @@ public class JavaSoundEntityTranslator extends PacketTranslator<ClientboundSound
|
|||
if (entity == null) {
|
||||
return;
|
||||
}
|
||||
SoundUtils.playBuiltinSound(session, packet.getSound(), entity.getPosition(), packet.getPitch());
|
||||
SoundUtils.playBuiltinSound(session, packet.getSound(), entity.getPosition(), packet.getVolume(), packet.getPitch());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,6 +38,6 @@ public class JavaSoundTranslator extends PacketTranslator<ClientboundSoundPacket
|
|||
@Override
|
||||
public void translate(GeyserSession session, ClientboundSoundPacket packet) {
|
||||
Vector3f position = Vector3f.from(packet.getX(), packet.getY(), packet.getZ());
|
||||
SoundUtils.playBuiltinSound(session, packet.getSound(), position, packet.getPitch());
|
||||
SoundUtils.playBuiltinSound(session, packet.getSound(), position, packet.getVolume(), packet.getPitch());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@ 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.PlaySoundPacket;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.level.block.BlockStateValues;
|
||||
import org.geysermc.geyser.registry.BlockRegistries;
|
||||
|
@ -74,10 +75,9 @@ public class SoundUtils {
|
|||
return "";
|
||||
}
|
||||
|
||||
// Drop the namespace
|
||||
int colonPos = packetSound.indexOf(":");
|
||||
if (colonPos != -1) {
|
||||
packetSound = packetSound.substring(colonPos + 1);
|
||||
// Drop the Minecraft namespace if applicable
|
||||
if (packetSound.startsWith("minecraft:")) {
|
||||
packetSound = packetSound.substring("minecraft:".length());
|
||||
}
|
||||
|
||||
SoundMapping soundMapping = Registries.SOUNDS.get(packetSound);
|
||||
|
@ -97,7 +97,7 @@ public class SoundUtils {
|
|||
* @param position the position
|
||||
* @param pitch the pitch
|
||||
*/
|
||||
public static void playBuiltinSound(GeyserSession session, BuiltinSound javaSound, Vector3f position, float pitch) {
|
||||
public static void playBuiltinSound(GeyserSession session, BuiltinSound javaSound, Vector3f position, float volume, float pitch) {
|
||||
String packetSound = javaSound.getName();
|
||||
|
||||
SoundMapping soundMapping = Registries.SOUNDS.get(packetSound);
|
||||
|
@ -106,6 +106,17 @@ public class SoundUtils {
|
|||
return;
|
||||
}
|
||||
|
||||
if (soundMapping.getPlaysound() != null) {
|
||||
// We always prefer the PlaySound mapping because we can control volume and pitch
|
||||
PlaySoundPacket playSoundPacket = new PlaySoundPacket();
|
||||
playSoundPacket.setSound(soundMapping.getPlaysound());
|
||||
playSoundPacket.setPosition(position);
|
||||
playSoundPacket.setVolume(volume);
|
||||
playSoundPacket.setPitch(pitch);
|
||||
session.sendUpstreamPacket(playSoundPacket);
|
||||
return;
|
||||
}
|
||||
|
||||
if (soundMapping.isLevelEvent()) {
|
||||
LevelEventPacket levelEventPacket = new LevelEventPacket();
|
||||
levelEventPacket.setPosition(position);
|
||||
|
|
Loading…
Reference in a new issue