mirror of
https://github.com/GeyserMC/Geyser.git
synced 2025-03-23 15:29:29 +01:00
Implement wind charges
This commit is contained in:
parent
e9e364636a
commit
ae6059bdc3
5 changed files with 108 additions and 23 deletions
|
@ -25,6 +25,8 @@
|
||||||
|
|
||||||
package org.geysermc.geyser.entity;
|
package org.geysermc.geyser.entity;
|
||||||
|
|
||||||
|
import org.geysermc.geyser.entity.type.AbstractWindChargeEntity;
|
||||||
|
import org.geysermc.geyser.entity.factory.EntityFactory;
|
||||||
import org.geysermc.geyser.entity.type.living.monster.raid.RavagerEntity;
|
import org.geysermc.geyser.entity.type.living.monster.raid.RavagerEntity;
|
||||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.MetadataType;
|
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.MetadataType;
|
||||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.BooleanEntityMetadata;
|
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.BooleanEntityMetadata;
|
||||||
|
@ -64,6 +66,7 @@ public final class EntityDefinitions {
|
||||||
public static final EntityDefinition<BlazeEntity> BLAZE;
|
public static final EntityDefinition<BlazeEntity> BLAZE;
|
||||||
public static final EntityDefinition<BoatEntity> BOAT;
|
public static final EntityDefinition<BoatEntity> BOAT;
|
||||||
public static final EntityDefinition<BoggedEntity> BOGGED;
|
public static final EntityDefinition<BoggedEntity> BOGGED;
|
||||||
|
public static final EntityDefinition<AbstractWindChargeEntity> BREEZE_WIND_CHARGE;
|
||||||
public static final EntityDefinition<CamelEntity> CAMEL;
|
public static final EntityDefinition<CamelEntity> CAMEL;
|
||||||
public static final EntityDefinition<CatEntity> CAT;
|
public static final EntityDefinition<CatEntity> CAT;
|
||||||
public static final EntityDefinition<SpiderEntity> CAVE_SPIDER;
|
public static final EntityDefinition<SpiderEntity> CAVE_SPIDER;
|
||||||
|
@ -166,6 +169,7 @@ public final class EntityDefinitions {
|
||||||
public static final EntityDefinition<VindicatorEntity> VINDICATOR;
|
public static final EntityDefinition<VindicatorEntity> VINDICATOR;
|
||||||
public static final EntityDefinition<AbstractMerchantEntity> WANDERING_TRADER;
|
public static final EntityDefinition<AbstractMerchantEntity> WANDERING_TRADER;
|
||||||
public static final EntityDefinition<WardenEntity> WARDEN;
|
public static final EntityDefinition<WardenEntity> WARDEN;
|
||||||
|
public static final EntityDefinition<AbstractWindChargeEntity> WIND_CHARGE;
|
||||||
public static final EntityDefinition<RaidParticipantEntity> WITCH;
|
public static final EntityDefinition<RaidParticipantEntity> WITCH;
|
||||||
public static final EntityDefinition<WitherEntity> WITHER;
|
public static final EntityDefinition<WitherEntity> WITHER;
|
||||||
public static final EntityDefinition<AbstractSkeletonEntity> WITHER_SKELETON;
|
public static final EntityDefinition<AbstractSkeletonEntity> WITHER_SKELETON;
|
||||||
|
@ -376,6 +380,18 @@ public final class EntityDefinitions {
|
||||||
.heightAndWidth(0.25f)
|
.heightAndWidth(0.25f)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
EntityFactory<AbstractWindChargeEntity> windChargeSupplier = AbstractWindChargeEntity::new;
|
||||||
|
BREEZE_WIND_CHARGE = EntityDefinition.inherited(windChargeSupplier, entityBase)
|
||||||
|
.type(EntityType.BREEZE_WIND_CHARGE)
|
||||||
|
.identifier("minecraft:breeze_wind_charge_projectile")
|
||||||
|
.heightAndWidth(0.3125f)
|
||||||
|
.build();
|
||||||
|
WIND_CHARGE = EntityDefinition.inherited(windChargeSupplier, entityBase)
|
||||||
|
.type(EntityType.WIND_CHARGE)
|
||||||
|
.identifier("minecraft:wind_charge_projectile")
|
||||||
|
.heightAndWidth(0.3125f)
|
||||||
|
.build();
|
||||||
|
|
||||||
EntityDefinition<AbstractArrowEntity> abstractArrowBase = EntityDefinition.inherited(AbstractArrowEntity::new, entityBase)
|
EntityDefinition<AbstractArrowEntity> abstractArrowBase = EntityDefinition.inherited(AbstractArrowEntity::new, entityBase)
|
||||||
.addTranslator(MetadataType.BYTE, AbstractArrowEntity::setArrowFlags)
|
.addTranslator(MetadataType.BYTE, AbstractArrowEntity::setArrowFlags)
|
||||||
.addTranslator(null) // "Piercing level"
|
.addTranslator(null) // "Piercing level"
|
||||||
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
/*
|
||||||
|
* 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.entity.type;
|
||||||
|
|
||||||
|
import org.cloudburstmc.math.vector.Vector3f;
|
||||||
|
import org.geysermc.geyser.entity.EntityDefinition;
|
||||||
|
import org.geysermc.geyser.session.GeyserSession;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Note that, as of 1.21, a wind charge entity does not actually implement the thrown item. We're just reusing
|
||||||
|
* the "hide until far away" aspect.
|
||||||
|
*/
|
||||||
|
public class AbstractWindChargeEntity extends ThrowableItemEntity {
|
||||||
|
public AbstractWindChargeEntity(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);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void tick() {
|
||||||
|
super.tick();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected float getDrag() {
|
||||||
|
// Always, even in water. As of 1.21.
|
||||||
|
return 1f;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1047,6 +1047,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void packetReceived(Session session, Packet packet) {
|
public void packetReceived(Session session, Packet packet) {
|
||||||
|
System.out.println(packet);
|
||||||
Registries.JAVA_PACKET_TRANSLATORS.translate(packet.getClass(), packet, GeyserSession.this);
|
Registries.JAVA_PACKET_TRANSLATORS.translate(packet.getClass(), packet, GeyserSession.this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,22 +25,24 @@
|
||||||
|
|
||||||
package org.geysermc.geyser.translator.protocol.java.level;
|
package org.geysermc.geyser.translator.protocol.java.level;
|
||||||
|
|
||||||
import org.geysermc.geyser.level.block.type.Block;
|
|
||||||
import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.level.ClientboundExplodePacket;
|
|
||||||
import org.cloudburstmc.math.vector.Vector3f;
|
import org.cloudburstmc.math.vector.Vector3f;
|
||||||
import org.cloudburstmc.math.vector.Vector3i;
|
import org.cloudburstmc.math.vector.Vector3i;
|
||||||
import org.cloudburstmc.nbt.NbtMap;
|
import org.cloudburstmc.nbt.NbtMap;
|
||||||
import org.cloudburstmc.nbt.NbtMapBuilder;
|
import org.cloudburstmc.nbt.NbtMapBuilder;
|
||||||
import org.cloudburstmc.protocol.bedrock.data.LevelEvent;
|
import org.cloudburstmc.protocol.bedrock.data.LevelEvent;
|
||||||
import org.cloudburstmc.protocol.bedrock.data.SoundEvent;
|
|
||||||
import org.cloudburstmc.protocol.bedrock.packet.LevelEventGenericPacket;
|
import org.cloudburstmc.protocol.bedrock.packet.LevelEventGenericPacket;
|
||||||
import org.cloudburstmc.protocol.bedrock.packet.LevelSoundEventPacket;
|
|
||||||
import org.cloudburstmc.protocol.bedrock.packet.SetEntityMotionPacket;
|
import org.cloudburstmc.protocol.bedrock.packet.SetEntityMotionPacket;
|
||||||
import org.geysermc.geyser.level.block.BlockStateValues;
|
import org.geysermc.geyser.level.block.type.Block;
|
||||||
import org.geysermc.geyser.session.GeyserSession;
|
import org.geysermc.geyser.session.GeyserSession;
|
||||||
import org.geysermc.geyser.translator.protocol.PacketTranslator;
|
import org.geysermc.geyser.translator.protocol.PacketTranslator;
|
||||||
import org.geysermc.geyser.translator.protocol.Translator;
|
import org.geysermc.geyser.translator.protocol.Translator;
|
||||||
import org.geysermc.geyser.util.ChunkUtils;
|
import org.geysermc.geyser.util.ChunkUtils;
|
||||||
|
import org.geysermc.geyser.util.SoundUtils;
|
||||||
|
import org.geysermc.mcprotocollib.protocol.data.game.level.block.ExplosionInteraction;
|
||||||
|
import org.geysermc.mcprotocollib.protocol.data.game.level.particle.Particle;
|
||||||
|
import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.level.ClientboundExplodePacket;
|
||||||
|
|
||||||
|
import java.util.concurrent.ThreadLocalRandom;
|
||||||
|
|
||||||
@Translator(packet = ClientboundExplodePacket.class)
|
@Translator(packet = ClientboundExplodePacket.class)
|
||||||
public class JavaExplodeTranslator extends PacketTranslator<ClientboundExplodePacket> {
|
public class JavaExplodeTranslator extends PacketTranslator<ClientboundExplodePacket> {
|
||||||
|
@ -56,6 +58,8 @@ public class JavaExplodeTranslator extends PacketTranslator<ClientboundExplodePa
|
||||||
builder.putFloat("originZ", (float) packet.getZ());
|
builder.putFloat("originZ", (float) packet.getZ());
|
||||||
builder.putFloat("radius", packet.getRadius());
|
builder.putFloat("radius", packet.getRadius());
|
||||||
builder.putInt("size", packet.getExploded().size());
|
builder.putInt("size", packet.getExploded().size());
|
||||||
|
// As of 1.21, KEEP means no block actions are run. TRIGGER_BLOCK will run some actions, like buttons can be pressed
|
||||||
|
if (packet.getBlockInteraction() != ExplosionInteraction.KEEP && packet.getBlockInteraction() != ExplosionInteraction.TRIGGER_BLOCK) {
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (Vector3i position : packet.getExploded()) {
|
for (Vector3i position : packet.getExploded()) {
|
||||||
Vector3i pos = Vector3i.from(packet.getX() + position.getX(), packet.getY() + position.getY(), packet.getZ() + position.getZ());
|
Vector3i pos = Vector3i.from(packet.getX() + position.getX(), packet.getY() + position.getY(), packet.getZ() + position.getZ());
|
||||||
|
@ -65,18 +69,28 @@ public class JavaExplodeTranslator extends PacketTranslator<ClientboundExplodePa
|
||||||
builder.putFloat("pos" + i + "z", pos.getZ());
|
builder.putFloat("pos" + i + "z", pos.getZ());
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
// As of Bedrock 1.21 - particles will only be created by the above packet if there are blocks to blow up?
|
||||||
|
// Not sure if the packet does anything - sending it just in case, because BDS still sends it.
|
||||||
|
// TODO move out of packet translator class
|
||||||
|
Particle particle;
|
||||||
|
if (!(packet.getRadius() < 2f) && packet.getBlockInteraction() == ExplosionInteraction.KEEP) {
|
||||||
|
particle = packet.getLargeExplosionParticles();
|
||||||
|
} else {
|
||||||
|
particle = packet.getSmallExplosionParticles();
|
||||||
|
}
|
||||||
|
var particleCreator = JavaLevelParticlesTranslator.createParticle(session, particle);
|
||||||
|
if (particleCreator != null) {
|
||||||
|
session.sendUpstreamPacket(particleCreator.apply(Vector3f.from(packet.getX(), packet.getY(), packet.getZ())));
|
||||||
|
}
|
||||||
|
}
|
||||||
levelEventPacket.setTag(builder.build());
|
levelEventPacket.setTag(builder.build());
|
||||||
session.sendUpstreamPacket(levelEventPacket);
|
session.sendUpstreamPacket(levelEventPacket);
|
||||||
|
|
||||||
Vector3f pos = Vector3f.from(packet.getX(), packet.getY(), packet.getZ());
|
Vector3f pos = Vector3f.from(packet.getX(), packet.getY(), packet.getZ());
|
||||||
LevelSoundEventPacket levelSoundEventPacket = new LevelSoundEventPacket();
|
ThreadLocalRandom random = ThreadLocalRandom.current();
|
||||||
levelSoundEventPacket.setRelativeVolumeDisabled(false);
|
float pitch = (1.0f + (random.nextFloat() - random.nextFloat()) * 0.2f) * 0.7f; // As of 1.21, Explosion#finalizeExplosion
|
||||||
levelSoundEventPacket.setBabySound(false);
|
SoundUtils.playSound(session, packet.getExplosionSound(), pos, 4.0f, pitch);
|
||||||
levelSoundEventPacket.setExtraData(-1);
|
|
||||||
levelSoundEventPacket.setSound(SoundEvent.EXPLODE);
|
|
||||||
levelSoundEventPacket.setIdentifier(":");
|
|
||||||
levelSoundEventPacket.setPosition(pos);
|
|
||||||
session.sendUpstreamPacket(levelSoundEventPacket);
|
|
||||||
|
|
||||||
if (packet.getPushX() != 0f || packet.getPushY() != 0f || packet.getPushZ() != 0f) {
|
if (packet.getPushX() != 0f || packet.getPushY() != 0f || packet.getPushZ() != 0f) {
|
||||||
SetEntityMotionPacket motionPacket = new SetEntityMotionPacket();
|
SetEntityMotionPacket motionPacket = new SetEntityMotionPacket();
|
||||||
|
|
|
@ -92,7 +92,7 @@ public class JavaLevelParticlesTranslator extends PacketTranslator<ClientboundLe
|
||||||
* @return a function to create a packet with a specified particle, in the event we need to spawn multiple particles
|
* @return a function to create a packet with a specified particle, in the event we need to spawn multiple particles
|
||||||
* with different offsets.
|
* with different offsets.
|
||||||
*/
|
*/
|
||||||
private @Nullable Function<Vector3f, BedrockPacket> createParticle(GeyserSession session, Particle particle) {
|
public static @Nullable Function<Vector3f, BedrockPacket> createParticle(GeyserSession session, Particle particle) {
|
||||||
switch (particle.getType()) {
|
switch (particle.getType()) {
|
||||||
case BLOCK -> {
|
case BLOCK -> {
|
||||||
int blockState = session.getBlockMappings().getBedrockBlockId(((BlockParticleData) particle.getData()).getBlockState());
|
int blockState = session.getBlockMappings().getBedrockBlockId(((BlockParticleData) particle.getData()).getBlockState());
|
||||||
|
@ -177,6 +177,7 @@ public class JavaLevelParticlesTranslator extends PacketTranslator<ClientboundLe
|
||||||
}
|
}
|
||||||
default -> {
|
default -> {
|
||||||
ParticleMapping particleMapping = Registries.PARTICLES.get(particle.getType());
|
ParticleMapping particleMapping = Registries.PARTICLES.get(particle.getType());
|
||||||
|
System.out.println(particle.getType() + " " + particleMapping);
|
||||||
if (particleMapping == null) { //TODO ensure no particle can be null
|
if (particleMapping == null) { //TODO ensure no particle can be null
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -205,7 +206,7 @@ public class JavaLevelParticlesTranslator extends PacketTranslator<ClientboundLe
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private NbtMap buildVec3PositionTag(Vector3f position) {
|
private static NbtMap buildVec3PositionTag(Vector3f position) {
|
||||||
return NbtMap.builder()
|
return NbtMap.builder()
|
||||||
.putString("type", "vec3")
|
.putString("type", "vec3")
|
||||||
.putFloat("x", position.getX())
|
.putFloat("x", position.getX())
|
||||||
|
|
Loading…
Add table
Reference in a new issue