forked from GeyserMC/Geyser
Add effects support and block break particles/place sounds
Co-authored-by: RednedEpic <redned235@gmail.com>
This commit is contained in:
parent
3e15d21931
commit
b0a8b9219a
11 changed files with 455 additions and 4 deletions
|
@ -30,6 +30,7 @@ import com.github.steveice10.mc.auth.exception.request.InvalidCredentialsExcepti
|
|||
import com.github.steveice10.mc.auth.exception.request.RequestException;
|
||||
import com.github.steveice10.mc.protocol.MinecraftProtocol;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode;
|
||||
import com.github.steveice10.mc.protocol.data.game.world.block.BlockState;
|
||||
import com.github.steveice10.mc.protocol.packet.ingame.server.ServerRespawnPacket;
|
||||
import com.github.steveice10.mc.protocol.packet.handshake.client.HandshakePacket;
|
||||
import com.github.steveice10.packetlib.Client;
|
||||
|
@ -126,6 +127,12 @@ public class GeyserSession implements CommandSender {
|
|||
@Setter
|
||||
private boolean jumping;
|
||||
|
||||
@Setter
|
||||
private BlockState breakingBlock;
|
||||
|
||||
@Setter
|
||||
private Vector3i lastBlockPlacePosition;
|
||||
|
||||
@Setter
|
||||
private boolean switchingDimension = false;
|
||||
private boolean manyDimPackets = false;
|
||||
|
|
|
@ -27,6 +27,10 @@ package org.geysermc.connector.network.translators.bedrock;
|
|||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
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 org.geysermc.connector.entity.Entity;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
import org.geysermc.connector.network.translators.PacketTranslator;
|
||||
|
@ -41,6 +45,7 @@ import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlaye
|
|||
import com.nukkitx.math.vector.Vector3i;
|
||||
import com.nukkitx.protocol.bedrock.packet.PlayStatusPacket;
|
||||
import com.nukkitx.protocol.bedrock.packet.PlayerActionPacket;
|
||||
import org.geysermc.connector.network.translators.block.BlockTranslator;
|
||||
|
||||
@Translator(packet = PlayerActionPacket.class)
|
||||
public class BedrockActionTranslator extends PacketTranslator<PlayerActionPacket> {
|
||||
|
@ -107,6 +112,11 @@ public class BedrockActionTranslator extends PacketTranslator<PlayerActionPacket
|
|||
session.getDownstream().getSession().send(startBreakingPacket);
|
||||
break;
|
||||
case CONTINUE_BREAK:
|
||||
LevelEventPacket continueBreakPacket = new LevelEventPacket();
|
||||
continueBreakPacket.setType(LevelEventType.PUNCH_BLOCK);
|
||||
continueBreakPacket.setData(BlockTranslator.getBedrockBlockId(session.getBreakingBlock() == null ? BlockTranslator.AIR : session.getBreakingBlock()));
|
||||
continueBreakPacket.setPosition(packet.getBlockPosition().toFloat());
|
||||
session.getUpstream().sendPacket(continueBreakPacket);
|
||||
break;
|
||||
case ABORT_BREAK:
|
||||
ClientPlayerActionPacket abortBreakingPacket = new ClientPlayerActionPacket(PlayerAction.CANCEL_DIGGING, new Position(packet.getBlockPosition().getX(),
|
||||
|
|
|
@ -26,12 +26,16 @@
|
|||
package org.geysermc.connector.network.translators.bedrock;
|
||||
|
||||
import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerPlaceBlockPacket;
|
||||
import com.nukkitx.math.vector.Vector3i;
|
||||
import org.geysermc.connector.entity.Entity;
|
||||
import org.geysermc.connector.inventory.Inventory;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
import org.geysermc.connector.network.translators.ItemStackTranslator;
|
||||
import org.geysermc.connector.network.translators.PacketTranslator;
|
||||
import org.geysermc.connector.network.translators.Translator;
|
||||
import org.geysermc.connector.network.translators.Translators;
|
||||
import org.geysermc.connector.network.translators.block.BlockTranslator;
|
||||
import org.geysermc.connector.network.translators.item.ItemTranslator;
|
||||
import org.geysermc.connector.utils.InventoryUtils;
|
||||
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
|
@ -73,6 +77,29 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator<Inve
|
|||
packet.getClickPosition().getX(), packet.getClickPosition().getY(), packet.getClickPosition().getZ(),
|
||||
false);
|
||||
session.getDownstream().getSession().send(blockPacket);
|
||||
Vector3i clickPos = packet.getBlockPosition();
|
||||
// TODO: Find a better way to do this?
|
||||
switch (packet.getFace()) {
|
||||
case 0:
|
||||
clickPos = clickPos.sub(0, 1, 0);
|
||||
break;
|
||||
case 1:
|
||||
clickPos = clickPos.add(0, 1, 0);
|
||||
break;
|
||||
case 2:
|
||||
clickPos = clickPos.sub(0, 0, 1);
|
||||
break;
|
||||
case 3:
|
||||
clickPos = clickPos.add(0, 0, 1);
|
||||
break;
|
||||
case 4:
|
||||
clickPos = clickPos.sub(1, 0, 0);
|
||||
break;
|
||||
case 5:
|
||||
clickPos = clickPos.add(1, 0, 0);
|
||||
break;
|
||||
}
|
||||
session.setLastBlockPlacePosition(clickPos);
|
||||
break;
|
||||
case 1:
|
||||
ClientPlayerUseItemPacket useItemPacket = new ClientPlayerUseItemPacket(Hand.MAIN_HAND);
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2020 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.connector.network.translators.effect;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@AllArgsConstructor
|
||||
public class Effect {
|
||||
|
||||
private String javaName;
|
||||
private String bedrockName;
|
||||
private String type;
|
||||
private int data;
|
||||
private String identifier;
|
||||
|
||||
}
|
|
@ -26,6 +26,8 @@
|
|||
package org.geysermc.connector.network.translators.java.entity.player;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack;
|
||||
import com.github.steveice10.mc.protocol.data.game.world.block.BlockState;
|
||||
import com.github.steveice10.mc.protocol.data.game.world.particle.BlockParticleData;
|
||||
import com.github.steveice10.mc.protocol.packet.ingame.server.entity.player.ServerPlayerActionAckPacket;
|
||||
import com.github.steveice10.opennbt.tag.builtin.*;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
|
@ -49,9 +51,13 @@ public class JavaPlayerActionAckTranslator extends PacketTranslator<ServerPlayer
|
|||
LevelEventPacket levelEvent = new LevelEventPacket();
|
||||
switch (packet.getAction()) {
|
||||
case FINISH_DIGGING:
|
||||
levelEvent.setType(LevelEventType.DESTROY);
|
||||
levelEvent.setPosition(Vector3f.from(packet.getPosition().getX(), packet.getPosition().getY(), packet.getPosition().getZ()));
|
||||
levelEvent.setData(BlockTranslator.getBedrockBlockId(session.getBreakingBlock()));
|
||||
session.getUpstream().sendPacket(levelEvent);
|
||||
session.setBreakingBlock(null);
|
||||
ChunkUtils.updateBlock(session, packet.getNewState(), packet.getPosition());
|
||||
break;
|
||||
|
||||
case START_DIGGING:
|
||||
levelEvent.setType(LevelEventType.BLOCK_START_BREAK);
|
||||
levelEvent.setPosition(Vector3f.from(
|
||||
|
@ -70,9 +76,9 @@ public class JavaPlayerActionAckTranslator extends PacketTranslator<ServerPlayer
|
|||
}
|
||||
double breakTime = Math.ceil(BlockUtils.getBreakTime(blockHardness, packet.getNewState().getId(), itemEntry, nbtData, session.getPlayerEntity()) * 20);
|
||||
levelEvent.setData((int) (65535 / breakTime));
|
||||
session.setBreakingBlock(packet.getNewState());
|
||||
session.getUpstream().sendPacket(levelEvent);
|
||||
break;
|
||||
|
||||
case CANCEL_DIGGING:
|
||||
levelEvent.setType(LevelEventType.BLOCK_STOP_BREAK);
|
||||
levelEvent.setPosition(Vector3f.from(
|
||||
|
@ -81,6 +87,7 @@ public class JavaPlayerActionAckTranslator extends PacketTranslator<ServerPlayer
|
|||
packet.getPosition().getZ()
|
||||
));
|
||||
levelEvent.setData(0);
|
||||
session.setBreakingBlock(null);
|
||||
session.getUpstream().sendPacket(levelEvent);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -25,9 +25,13 @@
|
|||
|
||||
package org.geysermc.connector.network.translators.java.world;
|
||||
|
||||
import com.nukkitx.math.vector.Vector3i;
|
||||
import com.nukkitx.protocol.bedrock.data.SoundEvent;
|
||||
import com.nukkitx.protocol.bedrock.packet.LevelSoundEventPacket;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
import org.geysermc.connector.network.translators.PacketTranslator;
|
||||
import org.geysermc.connector.network.translators.Translator;
|
||||
import org.geysermc.connector.network.translators.block.BlockTranslator;
|
||||
import org.geysermc.connector.utils.ChunkUtils;
|
||||
|
||||
import com.github.steveice10.mc.protocol.packet.ingame.server.world.ServerBlockChangePacket;
|
||||
|
@ -38,5 +42,23 @@ public class JavaBlockChangeTranslator extends PacketTranslator<ServerBlockChang
|
|||
@Override
|
||||
public void translate(ServerBlockChangePacket packet, GeyserSession session) {
|
||||
ChunkUtils.updateBlock(session, packet.getRecord().getBlock(), packet.getRecord().getPosition());
|
||||
Vector3i lastPlacePos = session.getLastBlockPlacePosition();
|
||||
if (lastPlacePos == null) {
|
||||
return;
|
||||
}
|
||||
if (lastPlacePos.getX() != packet.getRecord().getPosition().getX()
|
||||
|| lastPlacePos.getY() != packet.getRecord().getPosition().getY()
|
||||
|| lastPlacePos.getZ() != packet.getRecord().getPosition().getZ()) {
|
||||
return;
|
||||
}
|
||||
// This is not sent from the server, so we need to send it this way
|
||||
LevelSoundEventPacket placeBlockSoundPacket = new LevelSoundEventPacket();
|
||||
placeBlockSoundPacket.setSound(SoundEvent.PLACE);
|
||||
placeBlockSoundPacket.setPosition(lastPlacePos.toFloat());
|
||||
placeBlockSoundPacket.setBabySound(false);
|
||||
placeBlockSoundPacket.setExtraData(BlockTranslator.getBedrockBlockId(packet.getRecord().getBlock()));
|
||||
placeBlockSoundPacket.setIdentifier(":");
|
||||
session.getUpstream().sendPacket(placeBlockSoundPacket);
|
||||
session.setLastBlockPlacePosition(null);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,122 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2020 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.connector.network.translators.java.world;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.world.effect.ParticleEffect;
|
||||
import com.github.steveice10.mc.protocol.data.game.world.effect.*;
|
||||
import com.github.steveice10.mc.protocol.packet.ingame.server.world.ServerPlayEffectPacket;
|
||||
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.packet.LevelEventPacket;
|
||||
import com.nukkitx.protocol.bedrock.packet.LevelSoundEvent2Packet;
|
||||
import org.geysermc.connector.GeyserConnector;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
import org.geysermc.connector.network.translators.PacketTranslator;
|
||||
import org.geysermc.connector.network.translators.Translator;
|
||||
import org.geysermc.connector.network.translators.block.BlockTranslator;
|
||||
import org.geysermc.connector.network.translators.effect.Effect;
|
||||
import org.geysermc.connector.utils.EffectUtils;
|
||||
|
||||
@Translator(packet = ServerPlayEffectPacket.class)
|
||||
public class JavaPlayEffectTranslator extends PacketTranslator<ServerPlayEffectPacket> {
|
||||
|
||||
@Override
|
||||
public void translate(ServerPlayEffectPacket packet, GeyserSession session) {
|
||||
LevelEventPacket effect = new LevelEventPacket();
|
||||
// Some things here are particles, others are not
|
||||
if (packet.getEffect() instanceof ParticleEffect) {
|
||||
ParticleEffect particleEffect = (ParticleEffect) packet.getEffect();
|
||||
Effect geyserEffect = EffectUtils.EFFECTS.get(particleEffect.name());
|
||||
if (geyserEffect != null) {
|
||||
String name = geyserEffect.getBedrockName();
|
||||
effect.setType(LevelEventType.valueOf(name));
|
||||
} else {
|
||||
switch (particleEffect) {
|
||||
// TODO: BREAK_SPLASH_POTION has additional data
|
||||
// TODO: Block break doesn't work when you're the player.
|
||||
case BONEMEAL_GROW:
|
||||
effect.setType(LevelEventType.BONEMEAL);
|
||||
BonemealGrowEffectData growEffectData = (BonemealGrowEffectData) packet.getData();
|
||||
effect.setData(growEffectData.getParticleCount());
|
||||
break;
|
||||
//TODO: Block break particles when under fire
|
||||
case BREAK_BLOCK:
|
||||
effect.setType(LevelEventType.DESTROY);
|
||||
BreakBlockEffectData breakBlockEffectData = (BreakBlockEffectData) packet.getData();
|
||||
effect.setData(BlockTranslator.getBedrockBlockId(breakBlockEffectData.getBlockState()));
|
||||
break;
|
||||
// TODO: Check these three
|
||||
case EXPLOSION:
|
||||
effect.setType(LevelEventType.PARTICLE_EXPLODE);
|
||||
break;
|
||||
case MOB_SPAWN:
|
||||
effect.setType(LevelEventType.ENTITY_SPAWN);
|
||||
break;
|
||||
// Done with a dispenser
|
||||
case SMOKE:
|
||||
// Might need to be SHOOT
|
||||
effect.setType(LevelEventType.PARTICLE_SMOKE);
|
||||
break;
|
||||
default:
|
||||
GeyserConnector.getInstance().getLogger().debug("No effect handling for particle effect: " + packet.getEffect());
|
||||
}
|
||||
}
|
||||
effect.setPosition(Vector3f.from(packet.getPosition().getX(), packet.getPosition().getY(), packet.getPosition().getZ()));
|
||||
session.getUpstream().sendPacket(effect);
|
||||
} else if (packet.getEffect() instanceof SoundEffect) {
|
||||
SoundEffect soundEffect = (SoundEffect) packet.getEffect();
|
||||
Effect geyserEffect = EffectUtils.EFFECTS.get(soundEffect.name());
|
||||
if (geyserEffect != null) {
|
||||
// Some events are LevelEventTypes, some are SoundEvents.
|
||||
if (geyserEffect.getType().equals("soundLevel")) {
|
||||
// TODO: Opening doors also does not work as the player
|
||||
effect.setType(LevelEventType.valueOf(geyserEffect.getBedrockName()));
|
||||
} else if (geyserEffect.getType().equals("soundEvent")) {
|
||||
LevelSoundEvent2Packet soundEvent = new LevelSoundEvent2Packet();
|
||||
// Separate case since each RecordEffectData in Java is an individual track in Bedrock
|
||||
if (geyserEffect.getJavaName().equals("RECORD")) {
|
||||
RecordEffectData recordEffectData = (RecordEffectData) packet.getData();
|
||||
soundEvent.setSound(EffectUtils.RECORDS.get(recordEffectData.getRecordId()));
|
||||
} else {
|
||||
soundEvent.setSound(SoundEvent.valueOf(geyserEffect.getBedrockName()));
|
||||
}
|
||||
soundEvent.setExtraData(geyserEffect.getData());
|
||||
soundEvent.setIdentifier(geyserEffect.getIdentifier());
|
||||
soundEvent.setPosition(Vector3f.from(packet.getPosition().getX(), packet.getPosition().getY(), packet.getPosition().getZ()));
|
||||
session.getUpstream().sendPacket(soundEvent);
|
||||
}
|
||||
} else {
|
||||
GeyserConnector.getInstance().getLogger().debug("No effect handling for sound effect: " + packet.getEffect());
|
||||
}
|
||||
}
|
||||
if (effect.getType() != null) {
|
||||
effect.setPosition(Vector3f.from(packet.getPosition().getX(), packet.getPosition().getY(), packet.getPosition().getZ()));
|
||||
session.getUpstream().sendPacket(effect);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,105 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2020 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.connector.network.translators.java.world;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack;
|
||||
import com.github.steveice10.mc.protocol.data.game.world.particle.*;
|
||||
import com.nukkitx.protocol.bedrock.data.ItemData;
|
||||
import com.nukkitx.protocol.bedrock.data.LevelEventType;
|
||||
import com.nukkitx.protocol.bedrock.packet.LevelEventPacket;
|
||||
import com.nukkitx.protocol.bedrock.packet.SpawnParticleEffectPacket;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
import org.geysermc.connector.network.translators.PacketTranslator;
|
||||
import org.geysermc.connector.network.translators.Translator;
|
||||
import org.geysermc.connector.network.translators.Translators;
|
||||
import org.geysermc.connector.network.translators.block.BlockTranslator;
|
||||
import org.geysermc.connector.utils.EffectUtils;
|
||||
|
||||
import com.github.steveice10.mc.protocol.packet.ingame.server.world.ServerSpawnParticlePacket;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
|
||||
@Translator(packet = ServerSpawnParticlePacket.class)
|
||||
public class JavaSpawnParticleTranslator extends PacketTranslator<ServerSpawnParticlePacket> {
|
||||
|
||||
@Override
|
||||
public void translate(ServerSpawnParticlePacket packet, GeyserSession session) {
|
||||
LevelEventPacket particle = new LevelEventPacket();
|
||||
switch (packet.getParticle().getType()) {
|
||||
case BLOCK:
|
||||
particle.setType(LevelEventType.DESTROY);
|
||||
particle.setPosition(Vector3f.from(packet.getX(), packet.getY(), packet.getZ()));
|
||||
particle.setData(BlockTranslator.getBedrockBlockId(((BlockParticleData) packet.getParticle().getData()).getBlockState()));
|
||||
session.getUpstream().sendPacket(particle);
|
||||
break;
|
||||
case FALLING_DUST:
|
||||
//In fact, FallingDustParticle should have data like DustParticle,
|
||||
//but in MCProtocol, its data is BlockState(1).
|
||||
particle.setType(LevelEventType.PARTICLE_FALLING_DUST);
|
||||
particle.setData(BlockTranslator.getBedrockBlockId(((FallingDustParticleData)packet.getParticle().getData()).getBlockState()));
|
||||
particle.setPosition(Vector3f.from(packet.getX(), packet.getY(), packet.getZ()));
|
||||
session.getUpstream().sendPacket(particle);
|
||||
break;
|
||||
case ITEM:
|
||||
ItemStack javaItem = ((ItemParticleData)packet.getParticle().getData()).getItemStack();
|
||||
ItemData bedrockItem = Translators.getItemTranslator().translateToBedrock(session, javaItem);
|
||||
int id = bedrockItem.getId();
|
||||
short damage = bedrockItem.getDamage();
|
||||
particle.setType(LevelEventType.PARTICLE_ITEM_BREAK);
|
||||
particle.setData(id << 16 | damage);
|
||||
particle.setPosition(Vector3f.from(packet.getX(), packet.getY(), packet.getZ()));
|
||||
session.getUpstream().sendPacket(particle);
|
||||
break;
|
||||
case DUST:
|
||||
DustParticleData data = (DustParticleData)packet.getParticle().getData();
|
||||
int r = (int) (data.getRed()*255);
|
||||
int g = (int) (data.getGreen()*255);
|
||||
int b = (int) (data.getBlue()*255);
|
||||
particle.setType(LevelEventType.PARTICLE_FALLING_DUST);
|
||||
particle.setData(((0xff) << 24) | ((r & 0xff) << 16) | ((g & 0xff) << 8) | (b & 0xff));
|
||||
particle.setPosition(Vector3f.from(packet.getX(), packet.getY(), packet.getZ()));
|
||||
session.getUpstream().sendPacket(particle);
|
||||
break;
|
||||
default:
|
||||
LevelEventType typeParticle = EffectUtils.getParticleLevelEventType(packet.getParticle().getType());
|
||||
if (typeParticle != null) {
|
||||
particle.setType(typeParticle);
|
||||
particle.setPosition(Vector3f.from(packet.getX(), packet.getY(), packet.getZ()));
|
||||
session.getUpstream().sendPacket(particle);
|
||||
} else {
|
||||
String stringParticle = EffectUtils.getParticleString(packet.getParticle().getType());
|
||||
if (stringParticle != null) {
|
||||
SpawnParticleEffectPacket stringPacket = new SpawnParticleEffectPacket();
|
||||
stringPacket.setIdentifier(stringParticle);
|
||||
stringPacket.setDimensionId(session.getPlayerEntity().getDimension());
|
||||
stringPacket.setPosition(Vector3f.from(packet.getX(), packet.getY(), packet.getZ()));
|
||||
session.getUpstream().sendPacket(stringPacket);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,106 @@
|
|||
package org.geysermc.connector.utils;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.github.steveice10.mc.protocol.data.game.world.particle.ParticleType;
|
||||
import com.nukkitx.protocol.bedrock.data.LevelEventType;
|
||||
import com.nukkitx.protocol.bedrock.data.SoundEvent;
|
||||
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
|
||||
import lombok.NonNull;
|
||||
|
||||
import org.geysermc.connector.GeyserConnector;
|
||||
import org.geysermc.connector.network.translators.effect.Effect;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
public class EffectUtils {
|
||||
|
||||
public static final Map<String, Effect> EFFECTS = new HashMap<>();
|
||||
public static final Int2ObjectMap<SoundEvent> RECORDS = new Int2ObjectOpenHashMap<>();
|
||||
|
||||
private static Map<ParticleType, LevelEventType> particleTypeMap = new HashMap<>();
|
||||
private static Map<ParticleType, String> particleStringMap = new HashMap<>();
|
||||
|
||||
public static void init() {
|
||||
// no-op
|
||||
}
|
||||
|
||||
static {
|
||||
/* Load particles */
|
||||
InputStream particleStream = Toolbox.getResource("mappings/particles.json");
|
||||
JsonNode particleEntries;
|
||||
try {
|
||||
particleEntries = Toolbox.JSON_MAPPER.readTree(particleStream);
|
||||
} catch (Exception e) {
|
||||
throw new AssertionError("Unable to load particle map", e);
|
||||
}
|
||||
|
||||
Iterator<Map.Entry<String, JsonNode>> particlesIterator = particleEntries.fields();
|
||||
while (particlesIterator.hasNext()) {
|
||||
Map.Entry<String, JsonNode> entry = particlesIterator.next();
|
||||
try {
|
||||
setIdentifier(ParticleType.valueOf(entry.getKey().toUpperCase()), LevelEventType.valueOf(entry.getValue().asText().toUpperCase()));
|
||||
} catch (IllegalArgumentException e1) {
|
||||
try {
|
||||
setIdentifier(ParticleType.valueOf(entry.getKey().toUpperCase()), entry.getValue().asText());
|
||||
GeyserConnector.getInstance().getLogger().debug("Force to map particle "
|
||||
+ entry.getKey()
|
||||
+ "=>"
|
||||
+ entry.getValue().asText()
|
||||
+ ", it will take effect.");
|
||||
} catch (IllegalArgumentException e2){
|
||||
GeyserConnector.getInstance().getLogger().warning("Fail to map particle " + entry.getKey() + "=>" + entry.getValue().asText());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Load effects */
|
||||
InputStream effectsStream = Toolbox.getResource("mappings/effects.json");
|
||||
JsonNode effects;
|
||||
try {
|
||||
effects = Toolbox.JSON_MAPPER.readTree(effectsStream);
|
||||
} catch (Exception e) {
|
||||
throw new AssertionError("Unable to load effects mappings", e);
|
||||
}
|
||||
|
||||
Iterator<Map.Entry<String, JsonNode>> effectsIterator = effects.fields();
|
||||
while (effectsIterator.hasNext()) {
|
||||
Map.Entry<String, JsonNode> entry = effectsIterator.next();
|
||||
// Separate records database since they're handled differently between the two versions
|
||||
if (entry.getValue().has("records")) {
|
||||
JsonNode records = entry.getValue().get("records");
|
||||
Iterator<Map.Entry<String, JsonNode>> recordsIterator = records.fields();
|
||||
while (recordsIterator.hasNext()) {
|
||||
Map.Entry<String, JsonNode> recordEntry = recordsIterator.next();
|
||||
RECORDS.put(Integer.parseInt(recordEntry.getKey()), SoundEvent.valueOf(recordEntry.getValue().asText()));
|
||||
}
|
||||
}
|
||||
String identifier = (entry.getValue().has("identifier")) ? entry.getValue().get("identifier").asText() : "";
|
||||
int data = (entry.getValue().has("data")) ? entry.getValue().get("data").asInt() : -1;
|
||||
Effect effect = new Effect(entry.getKey(), entry.getValue().get("name").asText(), entry.getValue().get("type").asText(), data, identifier);
|
||||
EFFECTS.put(entry.getKey(), effect);
|
||||
}
|
||||
}
|
||||
|
||||
public static void setIdentifier(ParticleType type, LevelEventType identifier) {
|
||||
particleTypeMap.put(type, identifier);
|
||||
}
|
||||
|
||||
public static void setIdentifier(ParticleType type, String identifier) {
|
||||
particleStringMap.put(type, identifier);
|
||||
}
|
||||
|
||||
public static LevelEventType getParticleLevelEventType(@NonNull ParticleType type) {
|
||||
return particleTypeMap.getOrDefault(type, null);
|
||||
}
|
||||
|
||||
public static String getParticleString(@NonNull ParticleType type){
|
||||
return particleStringMap.getOrDefault(type, null);
|
||||
}
|
||||
|
||||
}
|
|
@ -129,6 +129,8 @@ public class Toolbox {
|
|||
itemIndex++;
|
||||
}
|
||||
|
||||
// Load particle/effect mappings
|
||||
EffectUtils.init();
|
||||
// Load sound mappings
|
||||
SoundUtils.init();
|
||||
// Load the locale data
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 9ecd90c71a26423a5f824554cce9b4236e544723
|
||||
Subproject commit b03f56113199a1a360efc68d2a80b8f706c6f56d
|
Loading…
Reference in a new issue