Mirror von
https://github.com/GeyserMC/Geyser.git
synchronisiert 2024-11-08 17:20:20 +01:00
Add effects support and block break particles/place sounds
Co-authored-by: RednedEpic <redned235@gmail.com>
Dieser Commit ist enthalten in:
Ursprung
3e15d21931
Commit
b0a8b9219a
@ -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.auth.exception.request.RequestException;
|
||||||
import com.github.steveice10.mc.protocol.MinecraftProtocol;
|
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.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.ingame.server.ServerRespawnPacket;
|
||||||
import com.github.steveice10.mc.protocol.packet.handshake.client.HandshakePacket;
|
import com.github.steveice10.mc.protocol.packet.handshake.client.HandshakePacket;
|
||||||
import com.github.steveice10.packetlib.Client;
|
import com.github.steveice10.packetlib.Client;
|
||||||
@ -126,6 +127,12 @@ public class GeyserSession implements CommandSender {
|
|||||||
@Setter
|
@Setter
|
||||||
private boolean jumping;
|
private boolean jumping;
|
||||||
|
|
||||||
|
@Setter
|
||||||
|
private BlockState breakingBlock;
|
||||||
|
|
||||||
|
@Setter
|
||||||
|
private Vector3i lastBlockPlacePosition;
|
||||||
|
|
||||||
@Setter
|
@Setter
|
||||||
private boolean switchingDimension = false;
|
private boolean switchingDimension = false;
|
||||||
private boolean manyDimPackets = false;
|
private boolean manyDimPackets = false;
|
||||||
|
@ -27,6 +27,10 @@ package org.geysermc.connector.network.translators.bedrock;
|
|||||||
|
|
||||||
import java.util.concurrent.TimeUnit;
|
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.entity.Entity;
|
||||||
import org.geysermc.connector.network.session.GeyserSession;
|
import org.geysermc.connector.network.session.GeyserSession;
|
||||||
import org.geysermc.connector.network.translators.PacketTranslator;
|
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.math.vector.Vector3i;
|
||||||
import com.nukkitx.protocol.bedrock.packet.PlayStatusPacket;
|
import com.nukkitx.protocol.bedrock.packet.PlayStatusPacket;
|
||||||
import com.nukkitx.protocol.bedrock.packet.PlayerActionPacket;
|
import com.nukkitx.protocol.bedrock.packet.PlayerActionPacket;
|
||||||
|
import org.geysermc.connector.network.translators.block.BlockTranslator;
|
||||||
|
|
||||||
@Translator(packet = PlayerActionPacket.class)
|
@Translator(packet = PlayerActionPacket.class)
|
||||||
public class BedrockActionTranslator extends PacketTranslator<PlayerActionPacket> {
|
public class BedrockActionTranslator extends PacketTranslator<PlayerActionPacket> {
|
||||||
@ -107,6 +112,11 @@ public class BedrockActionTranslator extends PacketTranslator<PlayerActionPacket
|
|||||||
session.getDownstream().getSession().send(startBreakingPacket);
|
session.getDownstream().getSession().send(startBreakingPacket);
|
||||||
break;
|
break;
|
||||||
case CONTINUE_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;
|
break;
|
||||||
case ABORT_BREAK:
|
case ABORT_BREAK:
|
||||||
ClientPlayerActionPacket abortBreakingPacket = new ClientPlayerActionPacket(PlayerAction.CANCEL_DIGGING, new Position(packet.getBlockPosition().getX(),
|
ClientPlayerActionPacket abortBreakingPacket = new ClientPlayerActionPacket(PlayerAction.CANCEL_DIGGING, new Position(packet.getBlockPosition().getX(),
|
||||||
|
@ -26,12 +26,16 @@
|
|||||||
package org.geysermc.connector.network.translators.bedrock;
|
package org.geysermc.connector.network.translators.bedrock;
|
||||||
|
|
||||||
import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerPlaceBlockPacket;
|
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.entity.Entity;
|
||||||
import org.geysermc.connector.inventory.Inventory;
|
import org.geysermc.connector.inventory.Inventory;
|
||||||
import org.geysermc.connector.network.session.GeyserSession;
|
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.PacketTranslator;
|
||||||
import org.geysermc.connector.network.translators.Translator;
|
import org.geysermc.connector.network.translators.Translator;
|
||||||
import org.geysermc.connector.network.translators.Translators;
|
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 org.geysermc.connector.utils.InventoryUtils;
|
||||||
|
|
||||||
import com.nukkitx.math.vector.Vector3f;
|
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(),
|
packet.getClickPosition().getX(), packet.getClickPosition().getY(), packet.getClickPosition().getZ(),
|
||||||
false);
|
false);
|
||||||
session.getDownstream().getSession().send(blockPacket);
|
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;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
ClientPlayerUseItemPacket useItemPacket = new ClientPlayerUseItemPacket(Hand.MAIN_HAND);
|
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;
|
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.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.mc.protocol.packet.ingame.server.entity.player.ServerPlayerActionAckPacket;
|
||||||
import com.github.steveice10.opennbt.tag.builtin.*;
|
import com.github.steveice10.opennbt.tag.builtin.*;
|
||||||
import com.nukkitx.math.vector.Vector3f;
|
import com.nukkitx.math.vector.Vector3f;
|
||||||
@ -49,9 +51,13 @@ public class JavaPlayerActionAckTranslator extends PacketTranslator<ServerPlayer
|
|||||||
LevelEventPacket levelEvent = new LevelEventPacket();
|
LevelEventPacket levelEvent = new LevelEventPacket();
|
||||||
switch (packet.getAction()) {
|
switch (packet.getAction()) {
|
||||||
case FINISH_DIGGING:
|
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());
|
ChunkUtils.updateBlock(session, packet.getNewState(), packet.getPosition());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case START_DIGGING:
|
case START_DIGGING:
|
||||||
levelEvent.setType(LevelEventType.BLOCK_START_BREAK);
|
levelEvent.setType(LevelEventType.BLOCK_START_BREAK);
|
||||||
levelEvent.setPosition(Vector3f.from(
|
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);
|
double breakTime = Math.ceil(BlockUtils.getBreakTime(blockHardness, packet.getNewState().getId(), itemEntry, nbtData, session.getPlayerEntity()) * 20);
|
||||||
levelEvent.setData((int) (65535 / breakTime));
|
levelEvent.setData((int) (65535 / breakTime));
|
||||||
|
session.setBreakingBlock(packet.getNewState());
|
||||||
session.getUpstream().sendPacket(levelEvent);
|
session.getUpstream().sendPacket(levelEvent);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CANCEL_DIGGING:
|
case CANCEL_DIGGING:
|
||||||
levelEvent.setType(LevelEventType.BLOCK_STOP_BREAK);
|
levelEvent.setType(LevelEventType.BLOCK_STOP_BREAK);
|
||||||
levelEvent.setPosition(Vector3f.from(
|
levelEvent.setPosition(Vector3f.from(
|
||||||
@ -81,6 +87,7 @@ public class JavaPlayerActionAckTranslator extends PacketTranslator<ServerPlayer
|
|||||||
packet.getPosition().getZ()
|
packet.getPosition().getZ()
|
||||||
));
|
));
|
||||||
levelEvent.setData(0);
|
levelEvent.setData(0);
|
||||||
|
session.setBreakingBlock(null);
|
||||||
session.getUpstream().sendPacket(levelEvent);
|
session.getUpstream().sendPacket(levelEvent);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -25,9 +25,13 @@
|
|||||||
|
|
||||||
package org.geysermc.connector.network.translators.java.world;
|
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.session.GeyserSession;
|
||||||
import org.geysermc.connector.network.translators.PacketTranslator;
|
import org.geysermc.connector.network.translators.PacketTranslator;
|
||||||
import org.geysermc.connector.network.translators.Translator;
|
import org.geysermc.connector.network.translators.Translator;
|
||||||
|
import org.geysermc.connector.network.translators.block.BlockTranslator;
|
||||||
import org.geysermc.connector.utils.ChunkUtils;
|
import org.geysermc.connector.utils.ChunkUtils;
|
||||||
|
|
||||||
import com.github.steveice10.mc.protocol.packet.ingame.server.world.ServerBlockChangePacket;
|
import com.github.steveice10.mc.protocol.packet.ingame.server.world.ServerBlockChangePacket;
|
||||||
@ -38,5 +42,23 @@ public class JavaBlockChangeTranslator extends PacketTranslator<ServerBlockChang
|
|||||||
@Override
|
@Override
|
||||||
public void translate(ServerBlockChangePacket packet, GeyserSession session) {
|
public void translate(ServerBlockChangePacket packet, GeyserSession session) {
|
||||||
ChunkUtils.updateBlock(session, packet.getRecord().getBlock(), packet.getRecord().getPosition());
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
106
connector/src/main/java/org/geysermc/connector/utils/EffectUtils.java
Normale Datei
106
connector/src/main/java/org/geysermc/connector/utils/EffectUtils.java
Normale Datei
@ -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++;
|
itemIndex++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Load particle/effect mappings
|
||||||
|
EffectUtils.init();
|
||||||
// Load sound mappings
|
// Load sound mappings
|
||||||
SoundUtils.init();
|
SoundUtils.init();
|
||||||
// Load the locale data
|
// Load the locale data
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit 9ecd90c71a26423a5f824554cce9b4236e544723
|
Subproject commit b03f56113199a1a360efc68d2a80b8f706c6f56d
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren