mirror of
https://github.com/GeyserMC/Geyser.git
synced 2024-08-14 23:57:35 +00: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;
|
||||
|
||||
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.mcprotocollib.protocol.data.game.entity.metadata.MetadataType;
|
||||
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<BoatEntity> BOAT;
|
||||
public static final EntityDefinition<BoggedEntity> BOGGED;
|
||||
public static final EntityDefinition<AbstractWindChargeEntity> BREEZE_WIND_CHARGE;
|
||||
public static final EntityDefinition<CamelEntity> CAMEL;
|
||||
public static final EntityDefinition<CatEntity> CAT;
|
||||
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<AbstractMerchantEntity> WANDERING_TRADER;
|
||||
public static final EntityDefinition<WardenEntity> WARDEN;
|
||||
public static final EntityDefinition<AbstractWindChargeEntity> WIND_CHARGE;
|
||||
public static final EntityDefinition<RaidParticipantEntity> WITCH;
|
||||
public static final EntityDefinition<WitherEntity> WITHER;
|
||||
public static final EntityDefinition<AbstractSkeletonEntity> WITHER_SKELETON;
|
||||
|
@ -376,6 +380,18 @@ public final class EntityDefinitions {
|
|||
.heightAndWidth(0.25f)
|
||||
.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)
|
||||
.addTranslator(MetadataType.BYTE, AbstractArrowEntity::setArrowFlags)
|
||||
.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
|
||||
public void packetReceived(Session session, Packet packet) {
|
||||
System.out.println(packet);
|
||||
Registries.JAVA_PACKET_TRANSLATORS.translate(packet.getClass(), packet, GeyserSession.this);
|
||||
}
|
||||
|
||||
|
|
|
@ -25,22 +25,24 @@
|
|||
|
||||
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.Vector3i;
|
||||
import org.cloudburstmc.nbt.NbtMap;
|
||||
import org.cloudburstmc.nbt.NbtMapBuilder;
|
||||
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.LevelSoundEventPacket;
|
||||
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.translator.protocol.PacketTranslator;
|
||||
import org.geysermc.geyser.translator.protocol.Translator;
|
||||
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)
|
||||
public class JavaExplodeTranslator extends PacketTranslator<ClientboundExplodePacket> {
|
||||
|
@ -56,27 +58,39 @@ public class JavaExplodeTranslator extends PacketTranslator<ClientboundExplodePa
|
|||
builder.putFloat("originZ", (float) packet.getZ());
|
||||
builder.putFloat("radius", packet.getRadius());
|
||||
builder.putInt("size", packet.getExploded().size());
|
||||
int i = 0;
|
||||
for (Vector3i position : packet.getExploded()) {
|
||||
Vector3i pos = Vector3i.from(packet.getX() + position.getX(), packet.getY() + position.getY(), packet.getZ() + position.getZ());
|
||||
ChunkUtils.updateBlock(session, Block.JAVA_AIR_ID, pos);
|
||||
builder.putFloat("pos" + i + "x", pos.getX());
|
||||
builder.putFloat("pos" + i + "y", pos.getY());
|
||||
builder.putFloat("pos" + i + "z", pos.getZ());
|
||||
i++;
|
||||
// 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;
|
||||
for (Vector3i position : packet.getExploded()) {
|
||||
Vector3i pos = Vector3i.from(packet.getX() + position.getX(), packet.getY() + position.getY(), packet.getZ() + position.getZ());
|
||||
ChunkUtils.updateBlock(session, Block.JAVA_AIR_ID, pos);
|
||||
builder.putFloat("pos" + i + "x", pos.getX());
|
||||
builder.putFloat("pos" + i + "y", pos.getY());
|
||||
builder.putFloat("pos" + i + "z", pos.getZ());
|
||||
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());
|
||||
session.sendUpstreamPacket(levelEventPacket);
|
||||
|
||||
Vector3f pos = Vector3f.from(packet.getX(), packet.getY(), packet.getZ());
|
||||
LevelSoundEventPacket levelSoundEventPacket = new LevelSoundEventPacket();
|
||||
levelSoundEventPacket.setRelativeVolumeDisabled(false);
|
||||
levelSoundEventPacket.setBabySound(false);
|
||||
levelSoundEventPacket.setExtraData(-1);
|
||||
levelSoundEventPacket.setSound(SoundEvent.EXPLODE);
|
||||
levelSoundEventPacket.setIdentifier(":");
|
||||
levelSoundEventPacket.setPosition(pos);
|
||||
session.sendUpstreamPacket(levelSoundEventPacket);
|
||||
ThreadLocalRandom random = ThreadLocalRandom.current();
|
||||
float pitch = (1.0f + (random.nextFloat() - random.nextFloat()) * 0.2f) * 0.7f; // As of 1.21, Explosion#finalizeExplosion
|
||||
SoundUtils.playSound(session, packet.getExplosionSound(), pos, 4.0f, pitch);
|
||||
|
||||
if (packet.getPushX() != 0f || packet.getPushY() != 0f || packet.getPushZ() != 0f) {
|
||||
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
|
||||
* 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()) {
|
||||
case BLOCK -> {
|
||||
int blockState = session.getBlockMappings().getBedrockBlockId(((BlockParticleData) particle.getData()).getBlockState());
|
||||
|
@ -177,6 +177,7 @@ public class JavaLevelParticlesTranslator extends PacketTranslator<ClientboundLe
|
|||
}
|
||||
default -> {
|
||||
ParticleMapping particleMapping = Registries.PARTICLES.get(particle.getType());
|
||||
System.out.println(particle.getType() + " " + particleMapping);
|
||||
if (particleMapping == null) { //TODO ensure no particle can be 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()
|
||||
.putString("type", "vec3")
|
||||
.putFloat("x", position.getX())
|
||||
|
|
Loading…
Reference in a new issue