From 3721cc084e4c9472fb82cc8c6f8a9d5d2021bf2c Mon Sep 17 00:00:00 2001 From: Jason Ho Date: Sat, 28 Mar 2020 16:50:50 -0700 Subject: [PATCH 001/140] Add packet translators for Play, Stop, and Builtin sounds --- .../player/JavaPlayerPlaySoundTranslator.java | 54 +++++++++ .../player/JavaPlayerStopSoundTranslator.java | 47 ++++++++ .../world/JavaPlayBuiltinSoundTranslator.java | 55 +++++++++ .../geysermc/connector/sound/SoundMap.java | 109 ++++++++++++++++++ .../org/geysermc/connector/utils/Toolbox.java | 5 + 5 files changed, 270 insertions(+) create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerPlaySoundTranslator.java create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerStopSoundTranslator.java create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaPlayBuiltinSoundTranslator.java create mode 100644 connector/src/main/java/org/geysermc/connector/sound/SoundMap.java diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerPlaySoundTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerPlaySoundTranslator.java new file mode 100644 index 000000000..cc3d2ff19 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerPlaySoundTranslator.java @@ -0,0 +1,54 @@ +package org.geysermc.connector.network.translators.java.entity.player; + +import com.github.steveice10.mc.protocol.data.game.world.sound.BuiltinSound; +import com.github.steveice10.mc.protocol.data.game.world.sound.CustomSound; +import com.github.steveice10.mc.protocol.packet.ingame.server.world.ServerPlaySoundPacket; +import com.nukkitx.math.vector.Vector3f; +import com.nukkitx.protocol.bedrock.packet.*; +import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.PacketTranslator; +import org.geysermc.connector.sound.SoundMap; + +public class JavaPlayerPlaySoundTranslator extends PacketTranslator { + + public static double processCoordinate(double f) { + return (f / 3D) * 8D; + } + + @Override + public void translate(ServerPlaySoundPacket packet, GeyserSession session) { + String packetSound; + if(packet.getSound() instanceof BuiltinSound) { + packetSound = ((BuiltinSound) packet.getSound()).getName(); + } else if(packet.getSound() instanceof CustomSound) { + packetSound = ((CustomSound) packet.getSound()).getName(); + } else { + session.getConnector().getLogger().debug("Unknown sound packet, we were unable to map this. " + packet.toString()); + return; + } + + SoundMap.SoundMapping soundMapping = SoundMap.get().fromJava(packetSound); + session.getConnector().getLogger() + .debug("[PlaySound] Sound mapping " + packetSound + " -> " + + soundMapping + (soundMapping == null ? "[not found]" : "") + + " - " + packet.toString()); + String playsound; + if(soundMapping == null || soundMapping.getPlaysound() == null) { + // no mapping + session.getConnector().getLogger() + .debug("[PlaySound] Defaulting to sound server gave us."); + playsound = packetSound; + } else { + playsound = soundMapping.getPlaysound(); + } + + PlaySoundPacket playSoundPacket = new PlaySoundPacket(); + playSoundPacket.setSound(playsound); + playSoundPacket.setPosition(Vector3f.from(processCoordinate(packet.getX()), processCoordinate(packet.getY()), processCoordinate(packet.getZ()))); + playSoundPacket.setVolume(packet.getVolume()); + playSoundPacket.setPitch(packet.getPitch()); + + session.getUpstream().sendPacket(playSoundPacket); + session.getConnector().getLogger().debug("[PlaySound] Packet sent - " + packet.toString() + " --> " + playSoundPacket); + } +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerStopSoundTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerStopSoundTranslator.java new file mode 100644 index 000000000..dfaab7a19 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerStopSoundTranslator.java @@ -0,0 +1,47 @@ +package org.geysermc.connector.network.translators.java.entity.player; + +import com.github.steveice10.mc.protocol.data.game.world.sound.BuiltinSound; +import com.github.steveice10.mc.protocol.data.game.world.sound.CustomSound; +import com.github.steveice10.mc.protocol.packet.ingame.server.ServerStopSoundPacket; +import com.nukkitx.protocol.bedrock.packet.StopSoundPacket; +import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.PacketTranslator; +import org.geysermc.connector.sound.SoundMap; + +public class JavaPlayerStopSoundTranslator extends PacketTranslator { + + @Override + public void translate(ServerStopSoundPacket packet, GeyserSession session) { + String packetSound; + if(packet.getSound() instanceof BuiltinSound) { + packetSound = ((BuiltinSound) packet.getSound()).getName(); + } else if(packet.getSound() instanceof CustomSound) { + packetSound = ((CustomSound) packet.getSound()).getName(); + } else { + session.getConnector().getLogger().debug("Unknown sound packet, we were unable to map this. " + packet.toString()); + return; + } + SoundMap.SoundMapping soundMapping = SoundMap.get().fromJava(packetSound); + session.getConnector().getLogger() + .debug("[StopSound] Sound mapping " + packetSound + " -> " + + soundMapping + (soundMapping == null ? "[not found]" : "") + + " - " + packet.toString()); + String playsound; + if(soundMapping == null || soundMapping.getPlaysound() == null) { + // no mapping + session.getConnector().getLogger() + .debug("[StopSound] Defaulting to sound server gave us."); + playsound = packetSound; + } else { + playsound = soundMapping.getPlaysound(); + } + + StopSoundPacket stopSoundPacket = new StopSoundPacket(); + stopSoundPacket.setSoundName(playsound); + // packet not mapped in the library + stopSoundPacket.setStoppingAllSound(false); + + session.getUpstream().sendPacket(stopSoundPacket); + session.getConnector().getLogger().debug("[StopSound] Packet sent - " + packet.toString() + " --> " + stopSoundPacket); + } +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaPlayBuiltinSoundTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaPlayBuiltinSoundTranslator.java new file mode 100644 index 000000000..efde8d467 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaPlayBuiltinSoundTranslator.java @@ -0,0 +1,55 @@ +package org.geysermc.connector.network.translators.java.world; + +import com.github.steveice10.mc.protocol.packet.ingame.server.world.ServerPlayBuiltinSoundPacket; +import com.nukkitx.math.vector.Vector3f; +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.sound.SoundMap; + +public class JavaPlayBuiltinSoundTranslator extends PacketTranslator { + + @Override + public void translate(ServerPlayBuiltinSoundPacket packet, GeyserSession session) { + String packetSound = packet.getSound().getName(); + + SoundMap.SoundMapping soundMapping = SoundMap.get().fromJava(packetSound); + session.getConnector().getLogger() + .debug("[Builtin] Sound mapping " + packetSound + " -> " + + soundMapping + (soundMapping == null ? "[not found]" : "") + + " - " + packet.toString()); + if(soundMapping == null) { + return; + } + + LevelSoundEventPacket soundPacket = new LevelSoundEventPacket(); + SoundEvent sound = SoundMap.toSoundEvent(soundMapping.getBedrock()); + if(sound == null) { + sound = SoundMap.toSoundEvent(soundMapping.getBedrock()); + if(sound == null) { + sound = SoundMap.toSoundEvent(packetSound); + if(sound == null) { + session.getConnector().getLogger() + .debug("[Builtin] Sound for original " + packetSound + " to mappings " + soundPacket + + " was not a playable level sound, or has yet to be mapped to an enum in " + + "NukkitX SoundEvent "); + } else { + session.getConnector().getLogger() + .debug("[Builtin] Sound for original " + packetSound + " to mappings " + soundPacket + + " was not found in NukkitX SoundEvent, but original packet sound name was."); + } + return; + } + } + + soundPacket.setSound(sound); + soundPacket.setPosition(Vector3f.from(packet.getX(), packet.getY(), packet.getZ())); + soundPacket.setExtraData(-1); + soundPacket.setIdentifier(":"); // ??? + soundPacket.setBabySound(false); // might need to adjust this in the future + soundPacket.setRelativeVolumeDisabled(false); + session.getUpstream().sendPacket(soundPacket); + session.getConnector().getLogger().debug("Packet sent - " + packet.toString() + " --> " + soundPacket.toString()); + } +} diff --git a/connector/src/main/java/org/geysermc/connector/sound/SoundMap.java b/connector/src/main/java/org/geysermc/connector/sound/SoundMap.java new file mode 100644 index 000000000..ab11fe527 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/sound/SoundMap.java @@ -0,0 +1,109 @@ +package org.geysermc.connector.sound; + +import com.fasterxml.jackson.databind.JsonNode; +import com.nukkitx.protocol.bedrock.data.SoundEvent; +import lombok.Data; +import lombok.ToString; +import org.geysermc.connector.utils.Toolbox; + +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.Map; + +public class SoundMap { + + private static SoundMap instance; + + public static SoundMap get() { + if(instance == null) { + instance = new SoundMap(make()); + } + return instance; + } + + private static ArrayList make() { + /* Load sound mappings */ + InputStream stream = Toolbox.getResource("mappings/sounds.json"); + JsonNode soundsTree; + try { + soundsTree = Toolbox.JSON_MAPPER.readTree(stream); + } catch (IOException e) { + throw new AssertionError("Unable to load sound mappings", e); + } + + ArrayList soundMappings = new ArrayList<>(); + Iterator> soundsIterator = soundsTree.fields(); + while(soundsIterator.hasNext()) { + Map.Entry next = soundsIterator.next(); + JsonNode brMap = next.getValue(); + + soundMappings.add( + new SoundMapping( + next.getKey(), + brMap.has("bedrock_mapping") && brMap.get("bedrock_mapping").isTextual() ? brMap.get("bedrock_mapping").asText() : null, + brMap.has("playsound_mapping") && brMap.get("playsound_mapping").isTextual() ? brMap.get("playsound_mapping").asText() : null + ) + ); + } + + + return soundMappings; + } + + private ArrayList sounds; + + public SoundMap(ArrayList sounds) { + this.sounds = sounds; + } + + /** + * Get's the sound mapping for a Java edition sound identifier + * @param java Java edition sound identifier + * @return SoundMapping object with information for bedrock, nukkit, java, etc. null if not found + */ + public SoundMapping fromJava(String java) { + for (SoundMapping sound : this.sounds) { + if(sound.getJava().equals(java)) { + return sound; + } + } + return null; + } + + + + public void refresh() { + this.sounds = make(); + } + + public static SoundEvent toSoundEvent(String s) { + SoundEvent sound; + try { + sound = SoundEvent.valueOf( + s + .toUpperCase() + .replaceAll("\\.", "_") + ); + return sound; + } catch(Exception e) { + return null; + } + } + + @Data + @ToString + public static class SoundMapping { + private final String java; + private final String bedrock; + private final String playsound; + + public SoundMapping(String java, String bedrock, String playsound) { + this.java = java; + this.bedrock = bedrock == null || bedrock.equalsIgnoreCase("") ? null : bedrock; + this.playsound = playsound == null || playsound.equalsIgnoreCase("") ? null : playsound; + } + } + +} diff --git a/connector/src/main/java/org/geysermc/connector/utils/Toolbox.java b/connector/src/main/java/org/geysermc/connector/utils/Toolbox.java index 45802196b..db19ed2e1 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/Toolbox.java +++ b/connector/src/main/java/org/geysermc/connector/utils/Toolbox.java @@ -39,6 +39,8 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.network.translators.item.ItemEntry; +import org.geysermc.connector.sound.SoundMap; + import java.io.InputStream; import java.util.*; @@ -103,6 +105,9 @@ public class Toolbox { entry.getValue().get("bedrock_id").intValue(), entry.getValue().get("bedrock_data").intValue())); itemIndex++; } + + /* Load sound mappings */ + SoundMap.get(); } public static InputStream getResource(String resource) { From 9e03c9b93ac5c205c51ef40984f6d48987c9d22f Mon Sep 17 00:00:00 2001 From: Jason Ho Date: Tue, 7 Apr 2020 18:11:27 -0700 Subject: [PATCH 002/140] Annotate sound translator classes --- .../java/entity/player/JavaPlayerPlaySoundTranslator.java | 2 ++ .../java/entity/player/JavaPlayerStopSoundTranslator.java | 2 ++ .../translators/java/world/JavaPlayBuiltinSoundTranslator.java | 2 ++ 3 files changed, 6 insertions(+) diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerPlaySoundTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerPlaySoundTranslator.java index cc3d2ff19..78d826dc7 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerPlaySoundTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerPlaySoundTranslator.java @@ -7,8 +7,10 @@ import com.nukkitx.math.vector.Vector3f; import com.nukkitx.protocol.bedrock.packet.*; 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.sound.SoundMap; +@Translator(packet = ServerPlaySoundPacket.class) public class JavaPlayerPlaySoundTranslator extends PacketTranslator { public static double processCoordinate(double f) { diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerStopSoundTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerStopSoundTranslator.java index dfaab7a19..e67297326 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerStopSoundTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerStopSoundTranslator.java @@ -6,8 +6,10 @@ import com.github.steveice10.mc.protocol.packet.ingame.server.ServerStopSoundPac import com.nukkitx.protocol.bedrock.packet.StopSoundPacket; 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.sound.SoundMap; +@Translator(packet = ServerStopSoundPacket.class) public class JavaPlayerStopSoundTranslator extends PacketTranslator { @Override diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaPlayBuiltinSoundTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaPlayBuiltinSoundTranslator.java index efde8d467..c862a334c 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaPlayBuiltinSoundTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaPlayBuiltinSoundTranslator.java @@ -6,8 +6,10 @@ 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.sound.SoundMap; +@Translator(packet = ServerPlayBuiltinSoundPacket.class) public class JavaPlayBuiltinSoundTranslator extends PacketTranslator { @Override From 7993f384378c47a8665e9ea8a667751345bf5901 Mon Sep 17 00:00:00 2001 From: DoctorMacc Date: Wed, 8 Apr 2020 15:30:36 -0400 Subject: [PATCH 003/140] Prepare for PR --- .../java/world/JavaPlayBuiltinSoundTranslator.java | 9 ++++++++- .../main/java/org/geysermc/connector/sound/SoundMap.java | 7 +++++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaPlayBuiltinSoundTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaPlayBuiltinSoundTranslator.java index c862a334c..b824c89d4 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaPlayBuiltinSoundTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaPlayBuiltinSoundTranslator.java @@ -47,7 +47,14 @@ public class JavaPlayBuiltinSoundTranslator extends PacketTranslator Date: Wed, 22 Apr 2020 18:17:34 -0500 Subject: [PATCH 004/140] Nitpicks and add serverbound sound packet translator --- .../BedrockLevelSoundEventTranslator.java | 41 +++++++++ .../player/JavaPlayerPlaySoundTranslator.java | 35 +++++-- .../player/JavaPlayerStopSoundTranslator.java | 29 +++++- .../world/JavaPlayBuiltinSoundTranslator.java | 35 ++++++- .../SoundMap.java => utils/SoundUtils.java} | 91 +++++++++---------- .../org/geysermc/connector/utils/Toolbox.java | 4 +- connector/src/main/resources/mappings | 2 +- 7 files changed, 173 insertions(+), 64 deletions(-) create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockLevelSoundEventTranslator.java rename connector/src/main/java/org/geysermc/connector/{sound/SoundMap.java => utils/SoundUtils.java} (53%) diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockLevelSoundEventTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockLevelSoundEventTranslator.java new file mode 100644 index 000000000..c1c29e0bf --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockLevelSoundEventTranslator.java @@ -0,0 +1,41 @@ +/* + * 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.bedrock; + +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; + +@Translator(packet = LevelSoundEventPacket.class) +public class BedrockLevelSoundEventTranslator extends PacketTranslator { + + @Override + public void translate(LevelSoundEventPacket packet, GeyserSession session) { + // lol what even :thinking: + session.getUpstream().sendPacket(packet); + } +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerPlaySoundTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerPlaySoundTranslator.java index 78d826dc7..2bc3a794a 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerPlaySoundTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerPlaySoundTranslator.java @@ -1,3 +1,28 @@ +/* + * 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.entity.player; import com.github.steveice10.mc.protocol.data.game.world.sound.BuiltinSound; @@ -8,15 +33,11 @@ import com.nukkitx.protocol.bedrock.packet.*; 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.sound.SoundMap; +import org.geysermc.connector.utils.SoundUtils; @Translator(packet = ServerPlaySoundPacket.class) public class JavaPlayerPlaySoundTranslator extends PacketTranslator { - public static double processCoordinate(double f) { - return (f / 3D) * 8D; - } - @Override public void translate(ServerPlaySoundPacket packet, GeyserSession session) { String packetSound; @@ -29,7 +50,7 @@ public class JavaPlayerPlaySoundTranslator extends PacketTranslator " + soundMapping + (soundMapping == null ? "[not found]" : "") @@ -46,7 +67,7 @@ public class JavaPlayerPlaySoundTranslator extends PacketTranslator { @@ -23,7 +48,7 @@ public class JavaPlayerStopSoundTranslator extends PacketTranslator " + soundMapping + (soundMapping == null ? "[not found]" : "") diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaPlayBuiltinSoundTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaPlayBuiltinSoundTranslator.java index b824c89d4..a21dc3880 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaPlayBuiltinSoundTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaPlayBuiltinSoundTranslator.java @@ -1,3 +1,28 @@ +/* + * 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.packet.ingame.server.world.ServerPlayBuiltinSoundPacket; @@ -7,7 +32,7 @@ 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.sound.SoundMap; +import org.geysermc.connector.utils.SoundUtils; @Translator(packet = ServerPlayBuiltinSoundPacket.class) public class JavaPlayBuiltinSoundTranslator extends PacketTranslator { @@ -16,7 +41,7 @@ public class JavaPlayBuiltinSoundTranslator extends PacketTranslator " + soundMapping + (soundMapping == null ? "[not found]" : "") @@ -26,11 +51,11 @@ public class JavaPlayBuiltinSoundTranslator extends PacketTranslator SOUNDS; - public static SoundMap get() { - if(instance == null) { - instance = new SoundMap(make()); - } - return instance; + public static void init() { + // no-op } - private static ArrayList make() { + static { /* Load sound mappings */ InputStream stream = Toolbox.getResource("mappings/sounds.json"); JsonNode soundsTree; @@ -33,14 +55,13 @@ public class SoundMap { throw new AssertionError("Unable to load sound mappings", e); } - ArrayList soundMappings = new ArrayList<>(); + Map soundMappings = new HashMap<>(); Iterator> soundsIterator = soundsTree.fields(); while(soundsIterator.hasNext()) { Map.Entry next = soundsIterator.next(); JsonNode brMap = next.getValue(); - soundMappings.add( - new SoundMapping( + soundMappings.put(next.getKey(), new SoundMapping( next.getKey(), brMap.has("bedrock_mapping") && brMap.get("bedrock_mapping").isTextual() ? brMap.get("bedrock_mapping").asText() : null, brMap.has("playsound_mapping") && brMap.get("playsound_mapping").isTextual() ? brMap.get("playsound_mapping").asText() : null, @@ -48,15 +69,7 @@ public class SoundMap { ) ); } - - - return soundMappings; - } - - private ArrayList sounds; - - public SoundMap(ArrayList sounds) { - this.sounds = sounds; + SOUNDS = soundMappings; } /** @@ -64,35 +77,22 @@ public class SoundMap { * @param java Java edition sound identifier * @return SoundMapping object with information for bedrock, nukkit, java, etc. null if not found */ - public SoundMapping fromJava(String java) { - for (SoundMapping sound : this.sounds) { - if(sound.getJava().equals(java)) { - return sound; - } - } - return null; + public static SoundMapping fromJava(String java) { + return SOUNDS.get(java); } - - - public void refresh() { - this.sounds = make(); - } - - public static SoundEvent toSoundEvent(String s) { - SoundEvent sound; + public static SoundEvent toSoundEvent(String sound) { try { - sound = SoundEvent.valueOf( - s - .toUpperCase() - .replaceAll("\\.", "_") - ); - return sound; - } catch(Exception e) { + return SoundEvent.valueOf(sound.toUpperCase().replaceAll("\\.", "_")); + } catch (IllegalArgumentException ex) { return null; } } + public static double processCoordinate(double f) { + return (f / 3D) * 8D; + } + @Data @ToString public static class SoundMapping { @@ -108,5 +108,4 @@ public class SoundMap { this.extraData = extraData; } } - } diff --git a/connector/src/main/java/org/geysermc/connector/utils/Toolbox.java b/connector/src/main/java/org/geysermc/connector/utils/Toolbox.java index 28e185210..a4fa5cfb6 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/Toolbox.java +++ b/connector/src/main/java/org/geysermc/connector/utils/Toolbox.java @@ -39,8 +39,6 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.network.translators.item.ItemEntry; -import org.geysermc.connector.sound.SoundMap; - import java.io.*; import java.util.*; @@ -109,7 +107,7 @@ public class Toolbox { } // Load sound mappings - SoundMap.get(); + SoundUtils.init(); // Load the locale data LocaleUtils.init(); } diff --git a/connector/src/main/resources/mappings b/connector/src/main/resources/mappings index efc9db6b7..9ecd90c71 160000 --- a/connector/src/main/resources/mappings +++ b/connector/src/main/resources/mappings @@ -1 +1 @@ -Subproject commit efc9db6b7d51bdf145230933ac23b321ac1c132d +Subproject commit 9ecd90c71a26423a5f824554cce9b4236e544723 From b0a8b9219a75fc7f202e3777507f16db0fd6ccb3 Mon Sep 17 00:00:00 2001 From: DoctorMacc Date: Wed, 22 Apr 2020 23:40:49 -0500 Subject: [PATCH 005/140] Add effects support and block break particles/place sounds Co-authored-by: RednedEpic --- .../network/session/GeyserSession.java | 7 + .../bedrock/BedrockActionTranslator.java | 10 ++ ...BedrockInventoryTransactionTranslator.java | 27 ++++ .../network/translators/effect/Effect.java | 43 ++++++ .../player/JavaPlayerActionAckTranslator.java | 11 +- .../java/world/JavaBlockChangeTranslator.java | 22 ++++ .../java/world/JavaPlayEffectTranslator.java | 122 ++++++++++++++++++ .../world/JavaSpawnParticleTranslator.java | 105 +++++++++++++++ .../geysermc/connector/utils/EffectUtils.java | 106 +++++++++++++++ .../org/geysermc/connector/utils/Toolbox.java | 4 +- connector/src/main/resources/mappings | 2 +- 11 files changed, 455 insertions(+), 4 deletions(-) create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/effect/Effect.java create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaPlayEffectTranslator.java create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaSpawnParticleTranslator.java create mode 100644 connector/src/main/java/org/geysermc/connector/utils/EffectUtils.java diff --git a/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java b/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java index 12ae39bfc..7aaed75fc 100644 --- a/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java +++ b/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java @@ -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; diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockActionTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockActionTranslator.java index 7ab713893..43e0a5704 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockActionTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockActionTranslator.java @@ -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 { @@ -107,6 +112,11 @@ public class BedrockActionTranslator extends PacketTranslator { + + @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); + } + + } +} \ No newline at end of file diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaSpawnParticleTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaSpawnParticleTranslator.java new file mode 100644 index 000000000..4dd62647a --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaSpawnParticleTranslator.java @@ -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 { + + @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; + } + } + +} \ No newline at end of file diff --git a/connector/src/main/java/org/geysermc/connector/utils/EffectUtils.java b/connector/src/main/java/org/geysermc/connector/utils/EffectUtils.java new file mode 100644 index 000000000..d5a78e22e --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/utils/EffectUtils.java @@ -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 EFFECTS = new HashMap<>(); + public static final Int2ObjectMap RECORDS = new Int2ObjectOpenHashMap<>(); + + private static Map particleTypeMap = new HashMap<>(); + private static Map 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> particlesIterator = particleEntries.fields(); + while (particlesIterator.hasNext()) { + Map.Entry 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> effectsIterator = effects.fields(); + while (effectsIterator.hasNext()) { + Map.Entry 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> recordsIterator = records.fields(); + while (recordsIterator.hasNext()) { + Map.Entry 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); + } + +} \ No newline at end of file diff --git a/connector/src/main/java/org/geysermc/connector/utils/Toolbox.java b/connector/src/main/java/org/geysermc/connector/utils/Toolbox.java index 24cea5806..9dbc51abd 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/Toolbox.java +++ b/connector/src/main/java/org/geysermc/connector/utils/Toolbox.java @@ -128,7 +128,9 @@ public class Toolbox { } itemIndex++; } - + + // Load particle/effect mappings + EffectUtils.init(); // Load sound mappings SoundUtils.init(); // Load the locale data diff --git a/connector/src/main/resources/mappings b/connector/src/main/resources/mappings index 9ecd90c71..b03f56113 160000 --- a/connector/src/main/resources/mappings +++ b/connector/src/main/resources/mappings @@ -1 +1 @@ -Subproject commit 9ecd90c71a26423a5f824554cce9b4236e544723 +Subproject commit b03f56113199a1a360efc68d2a80b8f706c6f56d From 09297a467ceaa20ffc37477d44639193057d65dc Mon Sep 17 00:00:00 2001 From: RednedEpic Date: Wed, 22 Apr 2020 23:51:22 -0500 Subject: [PATCH 006/140] Update submodules --- connector/src/main/resources/mappings | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/connector/src/main/resources/mappings b/connector/src/main/resources/mappings index b03f56113..4d53e24f9 160000 --- a/connector/src/main/resources/mappings +++ b/connector/src/main/resources/mappings @@ -1 +1 @@ -Subproject commit b03f56113199a1a360efc68d2a80b8f706c6f56d +Subproject commit 4d53e24f92d20e51909ee48ac28ed17f92cb819e From 79185fabb55600da337fa408da2e69a425c9da52 Mon Sep 17 00:00:00 2001 From: RednedEpic Date: Thu, 23 Apr 2020 01:01:33 -0500 Subject: [PATCH 007/140] Only send block sounds when a block is being placed Previously, any time a block was clicked whether it be with a block in the hand or not, a sound would play. This checks if the item in the players hand is indeed a block as well as the same block in the UpdateBlockPacket, and properly plays the packet. --- connector/pom.xml | 6 ++++ .../network/session/GeyserSession.java | 3 ++ ...BedrockInventoryTransactionTranslator.java | 30 ++++++++++--------- .../translators/block/BlockTranslator.java | 8 ++++- .../network/translators/item/ItemEntry.java | 4 ++- .../translators/item/ToolItemEntry.java | 4 +-- .../java/world/JavaBlockChangeTranslator.java | 16 ++++++++++ .../org/geysermc/connector/utils/Toolbox.java | 9 ++++-- 8 files changed, 59 insertions(+), 21 deletions(-) diff --git a/connector/pom.xml b/connector/pom.xml index 9e223d4ea..a0142efb7 100644 --- a/connector/pom.xml +++ b/connector/pom.xml @@ -90,6 +90,12 @@ 8.3.1 compile + + com.google.guava + guava + 29.0-jre + compile + com.github.steveice10 opennbt diff --git a/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java b/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java index 7aaed75fc..bb0878b67 100644 --- a/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java +++ b/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java @@ -133,6 +133,9 @@ public class GeyserSession implements CommandSender { @Setter private Vector3i lastBlockPlacePosition; + @Setter + private String lastBlockPlacedId; + @Setter private boolean switchingDimension = false; private boolean manyDimPackets = false; diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockInventoryTransactionTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockInventoryTransactionTranslator.java index c6a5e7bd9..f17df09b2 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockInventoryTransactionTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockInventoryTransactionTranslator.java @@ -26,19 +26,6 @@ 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; import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position; import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode; import com.github.steveice10.mc.protocol.data.game.entity.player.Hand; @@ -48,8 +35,19 @@ import com.github.steveice10.mc.protocol.data.game.world.block.BlockFace; import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerActionPacket; import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerInteractEntityPacket; import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerUseItemPacket; +import com.nukkitx.math.vector.Vector3i; +import com.nukkitx.math.vector.Vector3f; import com.nukkitx.protocol.bedrock.packet.InventoryTransactionPacket; +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.PacketTranslator; +import org.geysermc.connector.network.translators.Translator; +import org.geysermc.connector.network.translators.Translators; +import org.geysermc.connector.network.translators.item.ItemEntry; +import org.geysermc.connector.utils.InventoryUtils; + @Translator(packet = InventoryTransactionPacket.class) public class BedrockInventoryTransactionTranslator extends PacketTranslator { @@ -99,7 +97,11 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator BEDROCK_TO_JAVA_BLOCK_MAP = new Int2ObjectOpenHashMap<>(); - private static final Map JAVA_ID_BLOCK_MAP = new HashMap<>(); + private static final BiMap JAVA_ID_BLOCK_MAP = HashBiMap.create(); private static final IntSet WATERLOGGED = new IntOpenHashSet(); // Bedrock carpet ID, used in LlamaEntity.java for decoration @@ -265,6 +267,10 @@ public class BlockTranslator { return WATERLOGGED.contains(state.getId()); } + public static BiMap getJavaIdBlockMap() { + return JAVA_ID_BLOCK_MAP; + } + public static BlockState getJavaWaterloggedState(int bedrockId) { return BEDROCK_TO_JAVA_BLOCK_MAP.get(1 << 31 | bedrockId); } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemEntry.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemEntry.java index e579c20ee..e5c803292 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemEntry.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemEntry.java @@ -32,7 +32,7 @@ import lombok.Getter; @AllArgsConstructor public class ItemEntry { - public static ItemEntry AIR = new ItemEntry("minecraft:air", 0, 0, 0); + public static ItemEntry AIR = new ItemEntry("minecraft:air", 0, 0, 0, false); private final String javaIdentifier; private final int javaId; @@ -40,6 +40,8 @@ public class ItemEntry { private final int bedrockId; private final int bedrockData; + private final boolean block; + @Override public boolean equals(Object obj) { return obj == this || (obj instanceof ItemEntry && ((ItemEntry) obj).getBedrockId() == this.getBedrockId() && ((ItemEntry) obj).getJavaIdentifier().equals(this.getJavaIdentifier())); diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/ToolItemEntry.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/ToolItemEntry.java index 5d1ddd262..cfc05a4a9 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/item/ToolItemEntry.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/ToolItemEntry.java @@ -7,8 +7,8 @@ public class ToolItemEntry extends ItemEntry { private final String toolType; private final String toolTier; - public ToolItemEntry(String javaIdentifier, int javaId, int bedrockId, int bedrockData, String toolType, String toolTier) { - super(javaIdentifier, javaId, bedrockId, bedrockData); + public ToolItemEntry(String javaIdentifier, int javaId, int bedrockId, int bedrockData, String toolType, String toolTier, boolean isBlock) { + super(javaIdentifier, javaId, bedrockId, bedrockData, isBlock); this.toolType = toolType; this.toolTier = toolTier; } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaBlockChangeTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaBlockChangeTranslator.java index 08bd3cb60..ec40e27aa 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaBlockChangeTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaBlockChangeTranslator.java @@ -51,6 +51,21 @@ public class JavaBlockChangeTranslator extends PacketTranslator Date: Thu, 23 Apr 2020 02:12:50 -0500 Subject: [PATCH 008/140] Add missing license header from EffectUtils --- .../geysermc/connector/utils/EffectUtils.java | 27 ++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/connector/src/main/java/org/geysermc/connector/utils/EffectUtils.java b/connector/src/main/java/org/geysermc/connector/utils/EffectUtils.java index d5a78e22e..7c1690e48 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/EffectUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/EffectUtils.java @@ -1,3 +1,28 @@ +/* + * 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.utils; import com.fasterxml.jackson.databind.JsonNode; @@ -103,4 +128,4 @@ public class EffectUtils { return particleStringMap.getOrDefault(type, null); } -} \ No newline at end of file +} From 87be8c378e373f105406b4d84f28ec4b371149e5 Mon Sep 17 00:00:00 2001 From: ForceUpdate1 Date: Wed, 29 Apr 2020 17:58:29 +0200 Subject: [PATCH 009/140] Fix Item Name and Lore (#443) * add basic item translator * add licence remove debugs * fix default lore --- .../translators/ItemStackTranslator.java | 2 +- .../translators/item/ItemTranslator.java | 15 ++- .../translators/nbt/BasicItemTranslator.java | 125 ++++++++++++++++++ .../connector/utils/MessageUtils.java | 13 +- 4 files changed, 142 insertions(+), 13 deletions(-) create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/BasicItemTranslator.java diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/ItemStackTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/ItemStackTranslator.java index 356dcf982..423ffd390 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/ItemStackTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/ItemStackTranslator.java @@ -126,7 +126,7 @@ public abstract class ItemStackTranslator { if (tag instanceof StringTag) { StringTag stringTag = (StringTag) tag; - return new com.nukkitx.nbt.tag.StringTag(stringTag.getName(), MessageUtils.getBedrockMessage(Message.fromString(stringTag.getValue()))); + return new com.nukkitx.nbt.tag.StringTag(stringTag.getName(), stringTag.getValue()); } if (tag instanceof ListTag) { diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemTranslator.java index 5e0361c06..f59b82ba0 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemTranslator.java @@ -45,8 +45,8 @@ public class ItemTranslator { private Int2ObjectMap itemTranslators = new Int2ObjectOpenHashMap(); private List nbtItemTranslators; private Map javaIdentifierMap = new HashMap<>(); - - // Shield ID, used in Entity.java + + // Shield ID, used in Entity.java public static final int SHIELD = 829; public void init() { @@ -91,7 +91,6 @@ public class ItemTranslator { ItemEntry javaItem = getItem(data); ItemStack itemStack; - ItemStackTranslator itemStackTranslator = itemTranslators.get(javaItem.getJavaId()); if (itemStackTranslator != null) { itemStack = itemStackTranslator.translateToJava(data, javaItem); @@ -116,19 +115,21 @@ public class ItemTranslator { ItemEntry bedrockItem = getItem(stack); - if (stack != null && stack.getNbt() != null) { + ItemStack itemStack = new ItemStack(stack.getId(), stack.getAmount(), stack.getNbt() != null ? stack.getNbt().clone() : null); + + if (itemStack.getNbt() != null) { for (NbtItemStackTranslator translator : nbtItemTranslators) { if (translator.acceptItem(bedrockItem)) { - translator.translateToBedrock(stack.getNbt(), bedrockItem); + translator.translateToBedrock(itemStack.getNbt(), bedrockItem); } } } ItemStackTranslator itemStackTranslator = itemTranslators.get(bedrockItem.getJavaId()); if (itemStackTranslator != null) { - return itemStackTranslator.translateToBedrock(stack, bedrockItem); + return itemStackTranslator.translateToBedrock(itemStack, bedrockItem); } else { - return DEFAULT_TRANSLATOR.translateToBedrock(stack, bedrockItem); + return DEFAULT_TRANSLATOR.translateToBedrock(itemStack, bedrockItem); } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/BasicItemTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/BasicItemTranslator.java new file mode 100644 index 000000000..9458ec4f1 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/BasicItemTranslator.java @@ -0,0 +1,125 @@ +/* + * 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.item.translators.nbt; + +import com.github.steveice10.opennbt.tag.builtin.CompoundTag; +import com.github.steveice10.opennbt.tag.builtin.ListTag; +import com.github.steveice10.opennbt.tag.builtin.StringTag; +import com.github.steveice10.opennbt.tag.builtin.Tag; +import net.kyori.text.Component; +import net.kyori.text.TextComponent; +import net.kyori.text.serializer.gson.GsonComponentSerializer; +import net.kyori.text.serializer.legacy.LegacyComponentSerializer; +import org.geysermc.connector.network.translators.ItemRemapper; +import org.geysermc.connector.network.translators.NbtItemStackTranslator; +import org.geysermc.connector.network.translators.item.ItemEntry; +import org.geysermc.connector.utils.MessageUtils; + +import java.util.ArrayList; +import java.util.List; + +@ItemRemapper(priority = -1) +public class BasicItemTranslator extends NbtItemStackTranslator { + + @Override + public void translateToBedrock(CompoundTag itemTag, ItemEntry itemEntry) { + if (itemTag.contains("display")) { + CompoundTag displayTag = itemTag.get("display"); + if (displayTag.contains("Name")) { + StringTag nameTag = displayTag.get("Name"); + try { + displayTag.put(new StringTag("Name", toBedrockMessage(nameTag))); + } catch (Exception ex) { + } + } + + if (displayTag.contains("Lore")) { + ListTag loreTag = displayTag.get("Lore"); + List lore = new ArrayList<>(); + for (Tag tag : loreTag.getValue()) { + if (!(tag instanceof StringTag)) return; + try { + lore.add(new StringTag("", toBedrockMessage((StringTag) tag))); + } catch (Exception ex) { + } + } + displayTag.put(new ListTag("Lore", lore)); + } + } + } + + @Override + public void translateToJava(CompoundTag itemTag, ItemEntry itemEntry) { + if (itemTag.contains("display")) { + CompoundTag displayTag = itemTag.get("display"); + if (displayTag.contains("Name")) { + StringTag nameTag = displayTag.get("Name"); + displayTag.put(new StringTag("Name", toJavaMessage(nameTag))); + } + + if (displayTag.contains("Lore")) { + ListTag loreTag = displayTag.get("Lore"); + List lore = new ArrayList<>(); + for (Tag tag : loreTag.getValue()) { + if (!(tag instanceof StringTag)) return; + lore.add(new StringTag("", "§r" + toJavaMessage((StringTag) tag))); + } + displayTag.put(new ListTag("Lore", lore)); + } + } + } + + private String toJavaMessage(StringTag tag) { + String message = tag.getValue(); + if (message == null) return null; + if (message.startsWith("§r")) { + message = message.replaceFirst("§r", ""); + } + Component component = TextComponent.of(message); + return GsonComponentSerializer.INSTANCE.serialize(component); + } + + private String toBedrockMessage(StringTag tag) { + String message = tag.getValue(); + if (message == null) return null; + TextComponent component = (TextComponent) MessageUtils.phraseJavaMessage(message); + String legacy = LegacyComponentSerializer.legacy().serialize(component); + if (hasFormatting(LegacyComponentSerializer.legacy().deserialize(legacy))) { + return "§r" + legacy; + } + return legacy; + } + + private boolean hasFormatting(Component component) { + if (component.hasStyling()) return true; + for (Component child : component.children()) { + if (hasFormatting(child)) { + return true; + } + } + return false; + } +} diff --git a/connector/src/main/java/org/geysermc/connector/utils/MessageUtils.java b/connector/src/main/java/org/geysermc/connector/utils/MessageUtils.java index ac111c71e..478e42d1b 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/MessageUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/MessageUtils.java @@ -27,6 +27,7 @@ package org.geysermc.connector.utils; import com.github.steveice10.mc.protocol.data.game.scoreboard.TeamColor; import com.github.steveice10.mc.protocol.data.message.*; +import com.github.steveice10.opennbt.tag.builtin.StringTag; import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; @@ -121,20 +122,22 @@ public class MessageUtils { } public static String getBedrockMessage(Message message) { - Component component; if (isMessage(message.getText())) { - component = GsonComponentSerializer.INSTANCE.deserialize(message.getText()); + return getBedrockMessage(message.getText()); } else { - component = GsonComponentSerializer.INSTANCE.deserialize(message.toJsonString()); + return getBedrockMessage(message.toJsonString()); } - return LegacyComponentSerializer.legacy().serialize(component); } public static String getBedrockMessage(String message) { - Component component = GsonComponentSerializer.INSTANCE.deserialize(message); + Component component = phraseJavaMessage(message); return LegacyComponentSerializer.legacy().serialize(component); } + public static Component phraseJavaMessage(String message) { + return GsonComponentSerializer.INSTANCE.deserialize(message); + } + public static String getJavaMessage(String message) { Component component = LegacyComponentSerializer.legacy().deserialize(message); return GsonComponentSerializer.INSTANCE.serialize(component); From 7a9fff1a64792a78ed8aed9106d8288be0b444a6 Mon Sep 17 00:00:00 2001 From: rtm516 Date: Wed, 29 Apr 2020 17:01:56 +0100 Subject: [PATCH 010/140] Fix shulkers being upside down on load (#446) * Added shulker box direction handeling * Update mappings * Added missing Object2ByteMap * Cleaned javadoc * Moved shulker box direction conversion to the mappings generator --- .../translators/block/BlockStateValues.java | 33 ++++++++-- .../ShulkerBoxBlockEntityTranslator.java | 64 +++++++++++++++++++ connector/src/main/resources/mappings | 2 +- 3 files changed, 94 insertions(+), 5 deletions(-) create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/block/entity/ShulkerBoxBlockEntityTranslator.java diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/block/BlockStateValues.java b/connector/src/main/java/org/geysermc/connector/network/translators/block/BlockStateValues.java index 25d6070fe..76ee52387 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/block/BlockStateValues.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/block/BlockStateValues.java @@ -43,6 +43,7 @@ public class BlockStateValues { private static final Object2ByteMap BED_COLORS = new Object2ByteOpenHashMap<>(); private static final Object2ByteMap SKULL_VARIANTS = new Object2ByteOpenHashMap<>(); private static final Object2ByteMap SKULL_ROTATIONS = new Object2ByteOpenHashMap<>(); + private static final Object2ByteMap SHULKERBOX_DIRECTIONS = new Object2ByteOpenHashMap<>(); /** * Determines if the block state contains Bedrock block information @@ -71,13 +72,19 @@ public class BlockStateValues { if (skullRotation != null) { BlockStateValues.SKULL_ROTATIONS.put(javaBlockState, (byte) skullRotation.intValue()); } + + JsonNode shulkerDirection = entry.getValue().get("shulker_direction"); + if (shulkerDirection != null) { + BlockStateValues.SHULKERBOX_DIRECTIONS.put(javaBlockState, (byte) shulkerDirection.intValue()); + } } /** * Banner colors are part of the namespaced ID in Java Edition, but part of the block entity tag in Bedrock. * This gives an integer color that Bedrock can use. + * * @param state BlockState of the block - * @return banner color integer or -1 if no color + * @return Banner color integer or -1 if no color */ public static int getBannerColor(BlockState state) { if (BANNER_COLORS.containsKey(state)) { @@ -89,8 +96,9 @@ public class BlockStateValues { /** * Bed colors are part of the namespaced ID in Java Edition, but part of the block entity tag in Bedrock. * This gives a byte color that Bedrock can use - Bedrock needs a byte in the final tag. + * * @param state BlockState of the block - * @return bed color byte or -1 if no color + * @return Bed color byte or -1 if no color */ public static byte getBedColor(BlockState state) { if (BED_COLORS.containsKey(state)) { @@ -102,8 +110,9 @@ public class BlockStateValues { /** * Skull variations are part of the namespaced ID in Java Edition, but part of the block entity tag in Bedrock. * This gives a byte variant ID that Bedrock can use. + * * @param state BlockState of the block - * @return skull variant byte or -1 if no variant + * @return Skull variant byte or -1 if no variant */ public static byte getSkullVariant(BlockState state) { if (SKULL_VARIANTS.containsKey(state)) { @@ -113,9 +122,11 @@ public class BlockStateValues { } /** + * Skull rotations are part of the namespaced ID in Java Edition, but part of the block entity tag in Bedrock. + * This gives a byte rotation that Bedrock can use. * * @param state BlockState of the block - * @return skull rotation value or -1 if no value + * @return Skull rotation value or -1 if no value */ public static byte getSkullRotation(BlockState state) { if (SKULL_ROTATIONS.containsKey(state)) { @@ -124,4 +135,18 @@ public class BlockStateValues { return -1; } + + /** + * Shulker box directions are part of the namespaced ID in Java Edition, but part of the block entity tag in Bedrock. + * This gives a byte direction that Bedrock can use. + * + * @param state BlockState of the block + * @return Shulker direction value or -1 if no value + */ + public static byte getShulkerBoxDirection(BlockState state) { + if (SHULKERBOX_DIRECTIONS.containsKey(state)) { + return SHULKERBOX_DIRECTIONS.getByte(state); + } + return -1; + } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/ShulkerBoxBlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/ShulkerBoxBlockEntityTranslator.java new file mode 100644 index 000000000..3d409a093 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/ShulkerBoxBlockEntityTranslator.java @@ -0,0 +1,64 @@ +/* + * 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.block.entity; + +import com.github.steveice10.mc.protocol.data.game.world.block.BlockState; +import com.github.steveice10.opennbt.tag.builtin.CompoundTag; +import com.nukkitx.nbt.CompoundTagBuilder; +import com.nukkitx.nbt.tag.ByteTag; +import com.nukkitx.nbt.tag.Tag; +import org.geysermc.connector.network.translators.block.BlockStateValues; + +import java.util.ArrayList; +import java.util.List; + +@BlockEntity(name = "ShulkerBox", delay = false, regex = "shulker_box") +public class ShulkerBoxBlockEntityTranslator extends BlockEntityTranslator { + + @Override + public List> translateTag(CompoundTag tag, BlockState blockState) { + List> tags = new ArrayList<>(); + + byte direction = BlockStateValues.getShulkerBoxDirection(blockState); + // Just in case... + if (direction == -1) direction = 1; + tags.add(new ByteTag("facing", direction)); + + return tags; + } + + @Override + public CompoundTag getDefaultJavaTag(String javaId, int x, int y, int z) { + return null; + } + + @Override + public com.nukkitx.nbt.tag.CompoundTag getDefaultBedrockTag(String bedrockId, int x, int y, int z) { + CompoundTagBuilder tagBuilder = getConstantBedrockTag(bedrockId, x, y, z).toBuilder(); + tagBuilder.byteTag("facing", (byte)1); + return tagBuilder.buildRootTag(); + } +} diff --git a/connector/src/main/resources/mappings b/connector/src/main/resources/mappings index 0af94e03e..4e80d3b8e 160000 --- a/connector/src/main/resources/mappings +++ b/connector/src/main/resources/mappings @@ -1 +1 @@ -Subproject commit 0af94e03efaa7e21651d7cabcef05b1927795cf5 +Subproject commit 4e80d3b8e489b12a93b1b98b7bbaf8fa91a7974a From 82433f80780047cdcd49c45a543d4a9437c91ce4 Mon Sep 17 00:00:00 2001 From: ForceUpdate1 Date: Wed, 29 Apr 2020 18:04:45 +0200 Subject: [PATCH 011/140] Fix capes (#436) * fix capes * remove gson * clean up * clean up * formatting code * Made the changes fit a bit better into the already existing code * Throw the nullptr before the download complete message, making debugging skins less confusing Co-authored-by: Tim203 --- .../connector/entity/PlayerEntity.java | 2 + .../connector/utils/SkinProvider.java | 67 +++++++++++++------ .../geysermc/connector/utils/SkinUtils.java | 2 +- 3 files changed, 51 insertions(+), 20 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/entity/PlayerEntity.java b/connector/src/main/java/org/geysermc/connector/entity/PlayerEntity.java index d0ac2aeb8..1766ae5bd 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/PlayerEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/PlayerEntity.java @@ -101,6 +101,8 @@ public class PlayerEntity extends LivingEntity { } public void sendPlayer(GeyserSession session) { + if(session.getEntityCache().getPlayerEntity(uuid) == null) + return; if (getLastSkinUpdate() == -1) { if (playerList) { PlayerListPacket playerList = new PlayerListPacket(); diff --git a/connector/src/main/java/org/geysermc/connector/utils/SkinProvider.java b/connector/src/main/java/org/geysermc/connector/utils/SkinProvider.java index ade03c54d..7c2b7fc0e 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/SkinProvider.java +++ b/connector/src/main/java/org/geysermc/connector/utils/SkinProvider.java @@ -25,16 +25,22 @@ package org.geysermc.connector.utils; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; import lombok.AllArgsConstructor; import lombok.Getter; - +import lombok.NoArgsConstructor; import org.geysermc.connector.GeyserConnector; import javax.imageio.ImageIO; import java.awt.*; import java.awt.image.BufferedImage; +import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; +import java.io.IOException; import java.net.URL; +import java.util.Arrays; +import java.util.Base64; import java.util.Map; import java.util.UUID; import java.util.concurrent.*; @@ -52,6 +58,7 @@ public class SkinProvider { private static Map cachedCapes = new ConcurrentHashMap<>(); private static Map> requestedCapes = new ConcurrentHashMap<>(); + private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); private static final int CACHE_INTERVAL = 8 * 60 * 1000; // 8 minutes public static boolean hasSkinCached(UUID uuid) { @@ -74,9 +81,10 @@ public class SkinProvider { return CompletableFuture.supplyAsync(() -> { long time = System.currentTimeMillis(); + CapeProvider provider = capeUrl != null ? CapeProvider.MINECRAFT : null; SkinAndCape skinAndCape = new SkinAndCape( getOrDefault(requestSkin(playerId, skinUrl, false), EMPTY_SKIN, 5), - getOrDefault(requestCape(capeUrl, false), EMPTY_CAPE, 5) + getOrDefault(requestCape(capeUrl, provider, false), EMPTY_CAPE, 5) ); GeyserConnector.getInstance().getLogger().debug("Took " + (System.currentTimeMillis() - time) + "ms for " + playerId); @@ -112,11 +120,11 @@ public class SkinProvider { return future; } - public static CompletableFuture requestCape(String capeUrl, boolean newThread) { + public static CompletableFuture requestCape(String capeUrl, CapeProvider provider, boolean newThread) { if (capeUrl == null || capeUrl.isEmpty()) return CompletableFuture.completedFuture(EMPTY_CAPE); if (requestedCapes.containsKey(capeUrl)) return requestedCapes.get(capeUrl); // already requested - boolean officialCape = capeUrl.startsWith("https://textures.minecraft.net"); + boolean officialCape = provider == CapeProvider.MINECRAFT; boolean validCache = (System.currentTimeMillis() - CACHE_INTERVAL) < cachedCapes.getOrDefault(capeUrl, EMPTY_CAPE).getRequestedOn(); if ((cachedCapes.containsKey(capeUrl) && officialCape) || validCache) { @@ -126,14 +134,14 @@ public class SkinProvider { CompletableFuture future; if (newThread) { - future = CompletableFuture.supplyAsync(() -> supplyCape(capeUrl), EXECUTOR_SERVICE) + future = CompletableFuture.supplyAsync(() -> supplyCape(capeUrl, provider), EXECUTOR_SERVICE) .whenCompleteAsync((cape, throwable) -> { cachedCapes.put(capeUrl, cape); requestedCapes.remove(capeUrl); }); requestedCapes.put(capeUrl, future); } else { - Cape cape = supplyCape(capeUrl); // blocking + Cape cape = supplyCape(capeUrl, provider); // blocking future = CompletableFuture.completedFuture(cape); cachedCapes.put(capeUrl, cape); } @@ -143,9 +151,9 @@ public class SkinProvider { public static CompletableFuture requestUnofficialCape(Cape officialCape, UUID playerId, String username, boolean newThread) { if (officialCape.isFailed() && ALLOW_THIRD_PARTY_CAPES) { - for (UnofficalCape cape : UnofficalCape.VALUES) { + for (CapeProvider provider : CapeProvider.VALUES) { Cape cape1 = getOrDefault( - requestCape(cape.getUrlFor(playerId, username), newThread), + requestCape(provider.getUrlFor(playerId, username), provider, newThread), EMPTY_CAPE, 4 ); if (!cape1.isFailed()) { @@ -159,15 +167,15 @@ public class SkinProvider { private static Skin supplySkin(UUID uuid, String textureUrl) { byte[] skin = EMPTY_SKIN.getSkinData(); try { - skin = requestImage(textureUrl, false); + skin = requestImage(textureUrl, null); } catch (Exception ignored) {} // just ignore I guess return new Skin(uuid, textureUrl, skin, System.currentTimeMillis(), false); } - private static Cape supplyCape(String capeUrl) { + private static Cape supplyCape(String capeUrl, CapeProvider provider) { byte[] cape = new byte[0]; try { - cape = requestImage(capeUrl, true); + cape = requestImage(capeUrl, provider); } catch (Exception ignored) {} // just ignore I guess String[] urlSection = capeUrl.split("/"); // A real url is expected at this stage @@ -181,11 +189,12 @@ public class SkinProvider { ); } - private static byte[] requestImage(String imageUrl, boolean cape) throws Exception { - BufferedImage image = ImageIO.read(new URL(imageUrl)); + private static byte[] requestImage(String imageUrl, CapeProvider provider) throws Exception { + BufferedImage image = downloadImage(imageUrl, provider); GeyserConnector.getInstance().getLogger().debug("Downloaded " + imageUrl); - if (cape) { + // if the requested image is an cape + if (provider != null) { image = image.getWidth() > 64 ? scale(image) : image; BufferedImage newImage = new BufferedImage(64, 32, BufferedImage.TYPE_INT_RGB); Graphics g = newImage.createGraphics(); @@ -209,7 +218,25 @@ public class SkinProvider { } } - private static BufferedImage scale (BufferedImage bufferedImage) { + private static BufferedImage downloadImage(String imageUrl, CapeProvider provider) throws IOException { + if (provider == CapeProvider.FIVEZIG) + return readFiveZigCape(imageUrl); + BufferedImage image = ImageIO.read(new URL(imageUrl)); + if (image == null) throw new NullPointerException(); + return image; + } + + private static BufferedImage readFiveZigCape(String url) throws IOException { + JsonNode element = OBJECT_MAPPER.readTree(WebUtils.getBody(url)); + if (element != null && element.isObject()) { + JsonNode capeElement = element.get("d"); + if (capeElement == null || capeElement.isNull()) return null; + return ImageIO.read(new ByteArrayInputStream(Base64.getDecoder().decode(capeElement.textValue()))); + } + return null; + } + + private static BufferedImage scale(BufferedImage bufferedImage) { BufferedImage resized = new BufferedImage(bufferedImage.getWidth() / 2, bufferedImage.getHeight() / 2, BufferedImage.TYPE_INT_RGB); Graphics2D g2 = resized.createGraphics(); g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); @@ -262,14 +289,16 @@ public class SkinProvider { * Sorted by 'priority' */ @AllArgsConstructor + @NoArgsConstructor @Getter - public enum UnofficalCape { + public enum CapeProvider { + MINECRAFT, OPTIFINE("http://s.optifine.net/capes/%s.png", CapeUrlType.USERNAME), - LABYMOD("http://capes.labymod.net/capes/%s.png", CapeUrlType.UUID_DASHED), - FIVEZIG("http://textures.5zig.net/2/%s", CapeUrlType.UUID), + LABYMOD("https://www.labymod.net/page/php/getCapeTexture.php?uuid=%s", CapeUrlType.UUID_DASHED), + FIVEZIG("https://textures.5zigreborn.eu/profile/%s", CapeUrlType.UUID_DASHED), MINECRAFTCAPES("https://www.minecraftcapes.co.uk/getCape/%s", CapeUrlType.UUID); - public static final UnofficalCape[] VALUES = values(); + public static final CapeProvider[] VALUES = Arrays.copyOfRange(values(), 1, 5); private String url; private CapeUrlType type; diff --git a/connector/src/main/java/org/geysermc/connector/utils/SkinUtils.java b/connector/src/main/java/org/geysermc/connector/utils/SkinUtils.java index 012bd73a4..9ce025e76 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/SkinUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/SkinUtils.java @@ -155,7 +155,7 @@ public class SkinUtils { cape = SkinProvider.getOrDefault(SkinProvider.requestUnofficialCape( cape, entity.getUuid(), entity.getUsername(), false - ), SkinProvider.EMPTY_CAPE, SkinProvider.UnofficalCape.VALUES.length * 3); + ), SkinProvider.EMPTY_CAPE, SkinProvider.CapeProvider.VALUES.length * 3); } if (entity.getLastSkinUpdate() < skin.getRequestedOn()) { From bea070395f8624daea332f9651a18b3c80eaf0b0 Mon Sep 17 00:00:00 2001 From: rtm516 Date: Wed, 29 Apr 2020 17:06:25 +0100 Subject: [PATCH 012/140] Handle player teleports properly (#389) * Handle player teleports properly Co-authored-by: ForceUpdate1 * impl teleport cache * impl teleport cache * removed debugs * Cleanup Co-authored-by: ForceUpdate1 --- .../org/geysermc/connector/entity/Entity.java | 8 ++-- .../connector/entity/PlayerEntity.java | 10 ++-- .../network/session/GeyserSession.java | 26 ++++++++-- .../network/session/cache/TeleportCache.java | 47 +++++++++++++++++++ .../bedrock/BedrockMovePlayerTranslator.java | 21 ++++++--- .../entity/JavaEntityTeleportTranslator.java | 2 +- .../JavaPlayerPositionRotationTranslator.java | 27 ++++++----- .../spawn/JavaSpawnPlayerTranslator.java | 8 ++-- 8 files changed, 114 insertions(+), 35 deletions(-) create mode 100644 connector/src/main/java/org/geysermc/connector/network/session/cache/TeleportCache.java diff --git a/connector/src/main/java/org/geysermc/connector/entity/Entity.java b/connector/src/main/java/org/geysermc/connector/entity/Entity.java index 5596ca7ae..54355d992 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/Entity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/Entity.java @@ -158,11 +158,11 @@ public class Entity { session.getUpstream().sendPacket(moveEntityPacket); } - public void moveAbsolute(GeyserSession session, Vector3f position, float yaw, float pitch, boolean isOnGround) { - moveAbsolute(session, position, Vector3f.from(yaw, pitch, yaw), isOnGround); + public void moveAbsolute(GeyserSession session, Vector3f position, float yaw, float pitch, boolean isOnGround, boolean teleported) { + moveAbsolute(session, position, Vector3f.from(yaw, pitch, yaw), isOnGround, teleported); } - public void moveAbsolute(GeyserSession session, Vector3f position, Vector3f rotation, boolean isOnGround) { + public void moveAbsolute(GeyserSession session, Vector3f position, Vector3f rotation, boolean isOnGround, boolean teleported) { setPosition(position); setRotation(rotation); @@ -171,7 +171,7 @@ public class Entity { moveEntityPacket.setPosition(position); moveEntityPacket.setRotation(getBedrockRotation()); moveEntityPacket.setOnGround(isOnGround); - moveEntityPacket.setTeleported(false); + moveEntityPacket.setTeleported(teleported); session.getUpstream().sendPacket(moveEntityPacket); } diff --git a/connector/src/main/java/org/geysermc/connector/entity/PlayerEntity.java b/connector/src/main/java/org/geysermc/connector/entity/PlayerEntity.java index 1766ae5bd..d47321683 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/PlayerEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/PlayerEntity.java @@ -83,7 +83,7 @@ public class PlayerEntity extends LivingEntity { addPlayerPacket.setUsername(username); addPlayerPacket.setRuntimeEntityId(geyserId); addPlayerPacket.setUniqueEntityId(geyserId); - addPlayerPacket.setPosition(position); + addPlayerPacket.setPosition(position.clone().sub(0, EntityType.PLAYER.getOffset(), 0)); addPlayerPacket.setRotation(getBedrockRotation()); addPlayerPacket.setMotion(motion); addPlayerPacket.setHand(hand); @@ -130,7 +130,7 @@ public class PlayerEntity extends LivingEntity { } @Override - public void moveAbsolute(GeyserSession session, Vector3f position, Vector3f rotation, boolean isOnGround) { + public void moveAbsolute(GeyserSession session, Vector3f position, Vector3f rotation, boolean isOnGround, boolean teleported) { setPosition(position); setRotation(rotation); @@ -139,7 +139,11 @@ public class PlayerEntity extends LivingEntity { movePlayerPacket.setPosition(this.position); movePlayerPacket.setRotation(getBedrockRotation()); movePlayerPacket.setOnGround(isOnGround); - movePlayerPacket.setMode(MovePlayerPacket.Mode.NORMAL); + movePlayerPacket.setMode(teleported ? MovePlayerPacket.Mode.TELEPORT : MovePlayerPacket.Mode.NORMAL); + + if (teleported) { + movePlayerPacket.setTeleportationCause(MovePlayerPacket.TeleportationCause.UNKNOWN); + } session.getUpstream().sendPacket(movePlayerPacket); } diff --git a/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java b/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java index 95c8c0301..186576e12 100644 --- a/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java +++ b/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java @@ -30,8 +30,9 @@ 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.packet.handshake.client.HandshakePacket; +import com.github.steveice10.mc.protocol.packet.ingame.client.world.ClientTeleportConfirmPacket; 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; import com.github.steveice10.packetlib.event.session.*; import com.github.steveice10.packetlib.packet.Packet; @@ -83,8 +84,10 @@ public class GeyserSession implements CommandSender { private final UpstreamSession upstream; private RemoteServer remoteServer; private Client downstream; - @Setter private AuthData authData; - @Setter private BedrockClientData clientData; + @Setter + private AuthData authData; + @Setter + private BedrockClientData clientData; private PlayerEntity playerEntity; private PlayerInventory inventory; @@ -94,6 +97,8 @@ public class GeyserSession implements CommandSender { private InventoryCache inventoryCache; private ScoreboardCache scoreboardCache; private WindowCache windowCache; + @Setter + private TeleportCache teleportCache; private DataCache javaPacketCache; @@ -439,4 +444,19 @@ public class GeyserSession implements CommandSender { // startGamePacket.setMovementServerAuthoritative(true); upstream.sendPacket(startGamePacket); } + + public boolean confirmTeleport(Vector3f position) { + if (teleportCache != null) { + if (!teleportCache.canConfirm(position)) { + GeyserConnector.getInstance().getLogger().debug("Unconfirmed Teleport " + teleportCache.getTeleportConfirmId() + + " Ignore movement " + position + " expected " + teleportCache); + return false; + } + int teleportId = teleportCache.getTeleportConfirmId(); + teleportCache = null; + ClientTeleportConfirmPacket teleportConfirmPacket = new ClientTeleportConfirmPacket(teleportId); + getDownstream().getSession().send(teleportConfirmPacket); + } + return true; + } } diff --git a/connector/src/main/java/org/geysermc/connector/network/session/cache/TeleportCache.java b/connector/src/main/java/org/geysermc/connector/network/session/cache/TeleportCache.java new file mode 100644 index 000000000..55b7e6faf --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/session/cache/TeleportCache.java @@ -0,0 +1,47 @@ +/* + * 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.session.cache; + +import com.nukkitx.math.vector.Vector3f; +import lombok.AllArgsConstructor; +import lombok.Data; + +@AllArgsConstructor +@Data +public class TeleportCache { + + private static final double ERROR = 0.2; + private static final double ERROR_Y = 0.5; + + private double x, y, z; + private int teleportConfirmId; + + public boolean canConfirm(Vector3f position) { + return (Math.abs(this.x - position.getX()) < ERROR && + Math.abs(this.y - position.getY()) < ERROR_Y && + Math.abs(this.z - position.getZ()) < ERROR); + } +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockMovePlayerTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockMovePlayerTranslator.java index 0ae3d88ae..be1587466 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockMovePlayerTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockMovePlayerTranslator.java @@ -34,7 +34,6 @@ import org.geysermc.connector.network.translators.PacketTranslator; import org.geysermc.connector.network.translators.Translator; import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerPositionRotationPacket; -import com.nukkitx.math.GenericMath; import com.nukkitx.math.vector.Vector3f; import com.nukkitx.protocol.bedrock.packet.MoveEntityAbsolutePacket; import com.nukkitx.protocol.bedrock.packet.MovePlayerPacket; @@ -59,23 +58,31 @@ public class BedrockMovePlayerTranslator extends PacketTranslator { @Override public void translate(ServerPlayerPositionRotationPacket packet, GeyserSession session) { - Entity entity = session.getPlayerEntity(); + PlayerEntity entity = session.getPlayerEntity(); if (entity == null) return; @@ -94,18 +94,21 @@ public class JavaPlayerPositionRotationTranslator extends PacketTranslator 1.5 || (yDis < 1.45 || yDis > (session.isJumping() ? 4.3 : (session.isSprinting() ? 2.5 : 1.9))) || zDis > 1.5) { - entity.moveAbsolute(session, Vector3f.from(packet.getX(), packet.getY(), packet.getZ()), packet.getYaw(), packet.getPitch(), true); + session.setTeleportCache(new TeleportCache(packet.getX(), packet.getY(), packet.getZ(), packet.getTeleportId())); + entity.moveAbsolute(session, Vector3f.from(packet.getX(), packet.getY(), packet.getZ()), packet.getYaw(), packet.getPitch(), true, true); + } else { + ClientTeleportConfirmPacket teleportConfirmPacket = new ClientTeleportConfirmPacket(packet.getTeleportId()); + session.getDownstream().getSession().send(teleportConfirmPacket); } } - - ClientTeleportConfirmPacket teleportConfirmPacket = new ClientTeleportConfirmPacket(packet.getTeleportId()); - session.getDownstream().getSession().send(teleportConfirmPacket); } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/spawn/JavaSpawnPlayerTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/spawn/JavaSpawnPlayerTranslator.java index 331eb0945..e01b95e90 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/spawn/JavaSpawnPlayerTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/spawn/JavaSpawnPlayerTranslator.java @@ -25,23 +25,21 @@ package org.geysermc.connector.network.translators.java.entity.spawn; +import com.github.steveice10.mc.protocol.packet.ingame.server.entity.spawn.ServerSpawnPlayerPacket; +import com.nukkitx.math.vector.Vector3f; import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.entity.PlayerEntity; -import org.geysermc.connector.entity.type.EntityType; 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.utils.SkinUtils; -import com.github.steveice10.mc.protocol.packet.ingame.server.entity.spawn.ServerSpawnPlayerPacket; -import com.nukkitx.math.vector.Vector3f; - @Translator(packet = ServerSpawnPlayerPacket.class) public class JavaSpawnPlayerTranslator extends PacketTranslator { @Override public void translate(ServerSpawnPlayerPacket packet, GeyserSession session) { - Vector3f position = Vector3f.from(packet.getX(), packet.getY() - EntityType.PLAYER.getOffset(), packet.getZ()); + Vector3f position = Vector3f.from(packet.getX(), packet.getY(), packet.getZ()); Vector3f rotation = Vector3f.from(packet.getYaw(), packet.getPitch(), packet.getYaw()); PlayerEntity entity = session.getEntityCache().getPlayerEntity(packet.getUuid()); From 31be608038723a2c06f4f1d308d2cf0da553c9eb Mon Sep 17 00:00:00 2001 From: RednedEpic Date: Wed, 29 Apr 2020 15:01:53 -0500 Subject: [PATCH 013/140] Add block break sounds for blocks with 0 hardness, and refactor some things The refactors in this commit go a bit beyond the scope of what the sound/effects branch was meant to accomplish, however most of these changes are necessary so chunk caching could be reintroduced for the standalone version. The chunk caching here allows for us to get the block ID before the block was broken, and in the future allow us to implement newer features. Chunk caching is optional (and disabled by default) as on non-Bukkit versions, it can eat up a lot of RAM with many players online. --- .../bukkit/GeyserBukkitConfiguration.java | 9 +- .../platform/bukkit/GeyserBukkitLogger.java | 4 +- .../platform/bukkit/GeyserBukkitPlugin.java | 14 +- .../world/GeyserBukkitWorldManager.java | 24 +-- .../bungeecord/GeyserBungeeConfiguration.java | 9 +- .../bungeecord/GeyserBungeeLogger.java | 4 +- .../bungeecord/GeyserBungeePlugin.java | 4 +- .../sponge/GeyserSpongeConfiguration.java | 9 +- .../platform/sponge/GeyserSpongeLogger.java | 4 +- .../platform/sponge/GeyserSpongePlugin.java | 5 +- bootstrap/standalone/pom.xml | 4 +- ...ap.java => GeyserStandaloneBootstrap.java} | 16 +- ...ava => GeyserStandaloneConfiguration.java} | 8 +- ...ogger.java => GeyserStandaloneLogger.java} | 40 ++--- .../platform/standalone/LoopbackUtil.java | 3 +- .../velocity/GeyserVelocityConfiguration.java | 7 +- .../velocity/GeyserVelocityLogger.java | 4 +- .../velocity/GeyserVelocityPlugin.java | 4 +- .../geysermc/common/IGeyserConfiguration.java | 87 ----------- .../common/bootstrap/IGeyserBootstrap.java | 64 -------- .../geysermc/common/logger/IGeyserLogger.java | 81 ---------- .../connector/GeyserConfiguration.java | 90 +++++++++++ .../geysermc/connector/GeyserConnector.java | 25 +-- .../org/geysermc/connector/GeyserLogger.java | 82 ++++++++++ .../connector/bootstrap/GeyserBootstrap.java | 78 ++++++++++ .../connector/command/CommandManager.java | 12 +- .../connector/entity/FallingBlockEntity.java | 2 +- .../living/animal/horse/LlamaEntity.java | 2 +- .../entity/living/monster/EndermanEntity.java | 2 +- .../network/ConnectorServerEventHandler.java | 9 +- .../network/UpstreamPacketHandler.java | 4 +- .../network/session/GeyserSession.java | 11 +- .../network/session/cache/ChunkCache.java | 43 +++--- .../network/translators/Translators.java | 6 +- .../bedrock/BedrockActionTranslator.java | 4 +- ...BedrockInventoryTransactionTranslator.java | 32 +++- .../inventory/BlockInventoryTranslator.java | 2 +- .../DoubleChestInventoryTranslator.java | 2 +- .../holder/BlockInventoryHolder.java | 2 +- .../player/JavaPlayerActionAckTranslator.java | 19 +-- .../java/world/JavaBlockChangeTranslator.java | 2 +- .../java/world/JavaChunkDataTranslator.java | 6 +- .../java/world/JavaPlayEffectTranslator.java | 2 +- .../world/JavaSpawnParticleTranslator.java | 2 +- .../java/world/JavaUnloadChunkTranslator.java | 2 +- .../world/JavaUpdateTileEntityTranslator.java | 4 +- .../translators/world/CachedChunkManager.java | 39 +++++ .../translators/world/WorldManager.java | 52 +++++++ .../{ => world}/block/BlockStateValues.java | 2 +- .../{ => world}/block/BlockTranslator.java | 6 +- .../entity/BannerBlockEntityTranslator.java | 4 +- .../entity/BedBlockEntityTranslator.java | 4 +- .../{ => world}/block/entity/BlockEntity.java | 2 +- .../block/entity/BlockEntityTranslator.java | 2 +- .../entity/CampfireBlockEntityTranslator.java | 2 +- .../entity/EmptyBlockEntityTranslator.java | 2 +- .../EndGatewayBlockEntityTranslator.java | 2 +- .../block/entity/RequiresBlockState.java | 2 +- .../entity/SignBlockEntityTranslator.java | 2 +- .../entity/SkullBlockEntityTranslator.java | 142 +++++++++--------- .../world/chunk/BlockStorage.java | 30 +++- .../world/chunk/ChunkPosition.java | 54 +++++++ .../world/chunk/ChunkSection.java | 26 +++- .../translators}/world/chunk/NibbleArray.java | 26 +++- .../world/chunk/bitarray/BitArray.java | 42 ++++++ .../world/chunk/bitarray/BitArrayVersion.java | 26 +++- .../world/chunk/bitarray/PaddedBitArray.java | 26 +++- .../world/chunk/bitarray/Pow2BitArray.java | 26 +++- .../connector/utils/BlockEntityUtils.java | 2 +- .../geysermc/connector/utils/BlockUtils.java | 2 +- .../geysermc/connector/utils/ChunkUtils.java | 11 +- .../connector/world/chunk/ChunkPosition.java | 53 ------- .../world/chunk/bitarray/BitArray.java | 26 ---- connector/src/main/resources/config.yml | 9 ++ 74 files changed, 873 insertions(+), 598 deletions(-) rename common/src/main/java/org/geysermc/common/command/ICommandManager.java => bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/world/GeyserBukkitWorldManager.java (64%) rename bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/{GeyserBootstrap.java => GeyserStandaloneBootstrap.java} (87%) rename bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/{GeyserConfiguration.java => GeyserStandaloneConfiguration.java} (94%) rename bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/{console/GeyserLogger.java => GeyserStandaloneLogger.java} (64%) delete mode 100644 common/src/main/java/org/geysermc/common/IGeyserConfiguration.java delete mode 100644 common/src/main/java/org/geysermc/common/bootstrap/IGeyserBootstrap.java delete mode 100644 common/src/main/java/org/geysermc/common/logger/IGeyserLogger.java create mode 100644 connector/src/main/java/org/geysermc/connector/GeyserConfiguration.java create mode 100644 connector/src/main/java/org/geysermc/connector/GeyserLogger.java create mode 100644 connector/src/main/java/org/geysermc/connector/bootstrap/GeyserBootstrap.java create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/world/CachedChunkManager.java create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/world/WorldManager.java rename connector/src/main/java/org/geysermc/connector/network/translators/{ => world}/block/BlockStateValues.java (98%) rename connector/src/main/java/org/geysermc/connector/network/translators/{ => world}/block/BlockTranslator.java (98%) rename connector/src/main/java/org/geysermc/connector/network/translators/{ => world}/block/entity/BannerBlockEntityTranslator.java (96%) rename connector/src/main/java/org/geysermc/connector/network/translators/{ => world}/block/entity/BedBlockEntityTranslator.java (94%) rename connector/src/main/java/org/geysermc/connector/network/translators/{ => world}/block/entity/BlockEntity.java (96%) rename connector/src/main/java/org/geysermc/connector/network/translators/{ => world}/block/entity/BlockEntityTranslator.java (98%) rename connector/src/main/java/org/geysermc/connector/network/translators/{ => world}/block/entity/CampfireBlockEntityTranslator.java (98%) rename connector/src/main/java/org/geysermc/connector/network/translators/{ => world}/block/entity/EmptyBlockEntityTranslator.java (96%) rename connector/src/main/java/org/geysermc/connector/network/translators/{ => world}/block/entity/EndGatewayBlockEntityTranslator.java (98%) rename connector/src/main/java/org/geysermc/connector/network/translators/{ => world}/block/entity/RequiresBlockState.java (95%) rename connector/src/main/java/org/geysermc/connector/network/translators/{ => world}/block/entity/SignBlockEntityTranslator.java (97%) rename connector/src/main/java/org/geysermc/connector/network/translators/{ => world}/block/entity/SkullBlockEntityTranslator.java (93%) rename connector/src/main/java/org/geysermc/connector/{ => network/translators}/world/chunk/BlockStorage.java (68%) create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/world/chunk/ChunkPosition.java rename connector/src/main/java/org/geysermc/connector/{ => network/translators}/world/chunk/ChunkSection.java (77%) rename connector/src/main/java/org/geysermc/connector/{ => network/translators}/world/chunk/NibbleArray.java (62%) create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/world/chunk/bitarray/BitArray.java rename connector/src/main/java/org/geysermc/connector/{ => network/translators}/world/chunk/bitarray/BitArrayVersion.java (60%) rename connector/src/main/java/org/geysermc/connector/{ => network/translators}/world/chunk/bitarray/PaddedBitArray.java (65%) rename connector/src/main/java/org/geysermc/connector/{ => network/translators}/world/chunk/bitarray/Pow2BitArray.java (67%) delete mode 100644 connector/src/main/java/org/geysermc/connector/world/chunk/ChunkPosition.java delete mode 100644 connector/src/main/java/org/geysermc/connector/world/chunk/bitarray/BitArray.java diff --git a/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitConfiguration.java b/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitConfiguration.java index 5b8842b4e..37ba44f92 100644 --- a/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitConfiguration.java +++ b/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitConfiguration.java @@ -26,7 +26,7 @@ package org.geysermc.platform.bukkit; import org.bukkit.configuration.file.FileConfiguration; -import org.geysermc.common.IGeyserConfiguration; +import org.geysermc.connector.GeyserConfiguration; import java.io.File; import java.nio.file.Path; @@ -34,7 +34,7 @@ import java.nio.file.Paths; import java.util.HashMap; import java.util.Map; -public class GeyserBukkitConfiguration implements IGeyserConfiguration { +public class GeyserBukkitConfiguration implements GeyserConfiguration { private FileConfiguration config; private File dataFolder; @@ -111,6 +111,11 @@ public class GeyserBukkitConfiguration implements IGeyserConfiguration { return Paths.get(dataFolder.toString(), config.getString("floodgate-key-file", "public-key.pem")); } + @Override + public boolean isCacheChunks() { + return true; // We override this as with Bukkit, we have direct access to the server implementation + } + @Override public IMetricsInfo getMetrics() { return metricsInfo; diff --git a/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitLogger.java b/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitLogger.java index 454ec9f6e..08822568c 100644 --- a/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitLogger.java +++ b/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitLogger.java @@ -27,13 +27,13 @@ package org.geysermc.platform.bukkit; import lombok.AllArgsConstructor; -import org.geysermc.common.logger.IGeyserLogger; +import org.geysermc.connector.GeyserLogger; import java.util.logging.Level; import java.util.logging.Logger; @AllArgsConstructor -public class GeyserBukkitLogger implements IGeyserLogger { +public class GeyserBukkitLogger implements GeyserLogger { private Logger logger; private boolean debugMode; diff --git a/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitPlugin.java b/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitPlugin.java index c2662695e..d5226245a 100644 --- a/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitPlugin.java +++ b/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitPlugin.java @@ -27,20 +27,22 @@ package org.geysermc.platform.bukkit; import org.bukkit.plugin.java.JavaPlugin; import org.geysermc.common.PlatformType; -import org.geysermc.common.command.ICommandManager; import org.geysermc.connector.GeyserConnector; -import org.geysermc.common.bootstrap.IGeyserBootstrap; +import org.geysermc.connector.bootstrap.GeyserBootstrap; import org.geysermc.connector.command.CommandManager; +import org.geysermc.connector.network.translators.world.WorldManager; import org.geysermc.platform.bukkit.command.GeyserBukkitCommandExecutor; import org.geysermc.platform.bukkit.command.GeyserBukkitCommandManager; +import org.geysermc.platform.bukkit.world.GeyserBukkitWorldManager; import java.util.UUID; -public class GeyserBukkitPlugin extends JavaPlugin implements IGeyserBootstrap { +public class GeyserBukkitPlugin extends JavaPlugin implements GeyserBootstrap { private GeyserBukkitCommandManager geyserCommandManager; private GeyserBukkitConfiguration geyserConfig; private GeyserBukkitLogger geyserLogger; + private GeyserBukkitWorldManager geyserWorldManager; private GeyserConnector connector; @@ -58,6 +60,7 @@ public class GeyserBukkitPlugin extends JavaPlugin implements IGeyserBootstrap { this.connector = GeyserConnector.start(PlatformType.BUKKIT, this); this.geyserCommandManager = new GeyserBukkitCommandManager(this, connector); + this.geyserWorldManager = new GeyserBukkitWorldManager(); this.getCommand("geyser").setExecutor(new GeyserBukkitCommandExecutor(connector)); } @@ -81,4 +84,9 @@ public class GeyserBukkitPlugin extends JavaPlugin implements IGeyserBootstrap { public CommandManager getGeyserCommandManager() { return this.geyserCommandManager; } + + @Override + public WorldManager getWorldManager() { + return this.geyserWorldManager; + } } diff --git a/common/src/main/java/org/geysermc/common/command/ICommandManager.java b/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/world/GeyserBukkitWorldManager.java similarity index 64% rename from common/src/main/java/org/geysermc/common/command/ICommandManager.java rename to bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/world/GeyserBukkitWorldManager.java index f46dfafcd..6172b8314 100644 --- a/common/src/main/java/org/geysermc/common/command/ICommandManager.java +++ b/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/world/GeyserBukkitWorldManager.java @@ -21,18 +21,22 @@ * * @author GeyserMC * @link https://github.com/GeyserMC/Geyser + * */ -package org.geysermc.common.command; +package org.geysermc.platform.bukkit.world; -public interface ICommandManager { +import com.github.steveice10.mc.protocol.data.game.world.block.BlockState; - /** - * Returns the description of the given command - * - * @param command Command to get the description for - * - * @return Command description - */ - String getDescription(String command); +import org.bukkit.Bukkit; +import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.world.WorldManager; +import org.geysermc.connector.network.translators.world.block.BlockTranslator; + +public class GeyserBukkitWorldManager extends WorldManager { + + @Override + public BlockState getBlockAt(GeyserSession session, int x, int y, int z) { + return BlockTranslator.getJavaIdBlockMap().get(Bukkit.getPlayer(session.getName()).getWorld().getBlockAt(x, y, z).getBlockData().getAsString()); + } } diff --git a/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/GeyserBungeeConfiguration.java b/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/GeyserBungeeConfiguration.java index e0f6a6eff..85971d0f7 100644 --- a/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/GeyserBungeeConfiguration.java +++ b/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/GeyserBungeeConfiguration.java @@ -27,7 +27,7 @@ package org.geysermc.platform.bungeecord; import net.md_5.bungee.config.Configuration; -import org.geysermc.common.IGeyserConfiguration; +import org.geysermc.connector.GeyserConfiguration; import java.io.File; import java.nio.file.Path; @@ -35,7 +35,7 @@ import java.nio.file.Paths; import java.util.HashMap; import java.util.Map; -public class GeyserBungeeConfiguration implements IGeyserConfiguration { +public class GeyserBungeeConfiguration implements GeyserConfiguration { private File dataFolder; private Configuration config; @@ -112,6 +112,11 @@ public class GeyserBungeeConfiguration implements IGeyserConfiguration { return Paths.get(dataFolder.toString(), config.getString("floodgate-key-file", "public-key.pem")); } + @Override + public boolean isCacheChunks() { + return config.getBoolean("cache-chunks", false); + } + @Override public BungeeMetricsInfo getMetrics() { return metricsInfo; diff --git a/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/GeyserBungeeLogger.java b/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/GeyserBungeeLogger.java index 7aba88bcd..cd07b333d 100644 --- a/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/GeyserBungeeLogger.java +++ b/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/GeyserBungeeLogger.java @@ -25,12 +25,12 @@ package org.geysermc.platform.bungeecord; -import org.geysermc.common.logger.IGeyserLogger; +import org.geysermc.connector.GeyserLogger; import java.util.logging.Level; import java.util.logging.Logger; -public class GeyserBungeeLogger implements IGeyserLogger { +public class GeyserBungeeLogger implements GeyserLogger { private Logger logger; private boolean debugMode; diff --git a/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/GeyserBungeePlugin.java b/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/GeyserBungeePlugin.java index 9c3934cff..3483c2938 100644 --- a/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/GeyserBungeePlugin.java +++ b/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/GeyserBungeePlugin.java @@ -32,7 +32,7 @@ import net.md_5.bungee.config.YamlConfiguration; import org.geysermc.common.PlatformType; import org.geysermc.connector.GeyserConnector; -import org.geysermc.common.bootstrap.IGeyserBootstrap; +import org.geysermc.connector.bootstrap.GeyserBootstrap; import org.geysermc.connector.command.CommandManager; import org.geysermc.platform.bungeecord.command.GeyserBungeeCommandExecutor; import org.geysermc.platform.bungeecord.command.GeyserBungeeCommandManager; @@ -44,7 +44,7 @@ import java.nio.file.Files; import java.util.UUID; import java.util.logging.Level; -public class GeyserBungeePlugin extends Plugin implements IGeyserBootstrap { +public class GeyserBungeePlugin extends Plugin implements GeyserBootstrap { private GeyserBungeeCommandManager geyserCommandManager; private GeyserBungeeConfiguration geyserConfig; diff --git a/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/GeyserSpongeConfiguration.java b/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/GeyserSpongeConfiguration.java index be4923e2b..efcf489d4 100644 --- a/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/GeyserSpongeConfiguration.java +++ b/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/GeyserSpongeConfiguration.java @@ -29,7 +29,7 @@ import lombok.AllArgsConstructor; import ninja.leaping.configurate.ConfigurationNode; -import org.geysermc.common.IGeyserConfiguration; +import org.geysermc.connector.GeyserConfiguration; import java.io.File; import java.nio.file.Path; @@ -38,7 +38,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -public class GeyserSpongeConfiguration implements IGeyserConfiguration { +public class GeyserSpongeConfiguration implements GeyserConfiguration { private File dataFolder; private ConfigurationNode node; @@ -115,6 +115,11 @@ public class GeyserSpongeConfiguration implements IGeyserConfiguration { return Paths.get(dataFolder.toString(), node.getNode("floodgate-key-file").getString("public-key.pem")); } + @Override + public boolean isCacheChunks() { + return node.getNode("cache-chunks").getBoolean(false); + } + @Override public SpongeMetricsInfo getMetrics() { return metricsInfo; diff --git a/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/GeyserSpongeLogger.java b/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/GeyserSpongeLogger.java index 758ac98d3..fb7cb54bb 100644 --- a/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/GeyserSpongeLogger.java +++ b/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/GeyserSpongeLogger.java @@ -27,11 +27,11 @@ package org.geysermc.platform.sponge; import lombok.AllArgsConstructor; -import org.geysermc.common.logger.IGeyserLogger; +import org.geysermc.connector.GeyserLogger; import org.slf4j.Logger; @AllArgsConstructor -public class GeyserSpongeLogger implements IGeyserLogger { +public class GeyserSpongeLogger implements GeyserLogger { private Logger logger; private boolean debugMode; diff --git a/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/GeyserSpongePlugin.java b/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/GeyserSpongePlugin.java index 88996fd2b..57470e283 100644 --- a/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/GeyserSpongePlugin.java +++ b/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/GeyserSpongePlugin.java @@ -31,8 +31,7 @@ import ninja.leaping.configurate.loader.ConfigurationLoader; import ninja.leaping.configurate.yaml.YAMLConfigurationLoader; import org.geysermc.common.PlatformType; -import org.geysermc.common.bootstrap.IGeyserBootstrap; -import org.geysermc.common.command.ICommandManager; +import org.geysermc.connector.bootstrap.GeyserBootstrap; import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.command.CommandManager; import org.geysermc.connector.utils.FileUtils; @@ -51,7 +50,7 @@ import java.io.IOException; import java.util.UUID; @Plugin(id = "geyser", name = GeyserConnector.NAME + "-Sponge", version = GeyserConnector.VERSION, url = "https://geysermc.org", authors = "GeyserMC") -public class GeyserSpongePlugin implements IGeyserBootstrap { +public class GeyserSpongePlugin implements GeyserBootstrap { @Inject private Logger logger; diff --git a/bootstrap/standalone/pom.xml b/bootstrap/standalone/pom.xml index 0a583fa7c..770ca1009 100644 --- a/bootstrap/standalone/pom.xml +++ b/bootstrap/standalone/pom.xml @@ -81,7 +81,7 @@ - org.geysermc.platform.standalone.GeyserBootstrap + org.geysermc.platform.standalone.GeyserStandaloneBootstrap @@ -119,7 +119,7 @@ - org.geysermc.platform.standalone.GeyserBootstrap + org.geysermc.platform.standalone.GeyserStandaloneBootstrap true diff --git a/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/GeyserBootstrap.java b/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/GeyserStandaloneBootstrap.java similarity index 87% rename from bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/GeyserBootstrap.java rename to bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/GeyserStandaloneBootstrap.java index 20b7f5ea7..9d2493635 100644 --- a/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/GeyserBootstrap.java +++ b/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/GeyserStandaloneBootstrap.java @@ -26,38 +26,38 @@ package org.geysermc.platform.standalone; import org.geysermc.common.PlatformType; -import org.geysermc.common.bootstrap.IGeyserBootstrap; +import org.geysermc.connector.GeyserConfiguration; +import org.geysermc.connector.bootstrap.GeyserBootstrap; import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.command.CommandManager; import org.geysermc.connector.utils.FileUtils; import org.geysermc.platform.standalone.command.GeyserCommandManager; -import org.geysermc.platform.standalone.console.GeyserLogger; import java.io.File; import java.io.IOException; import java.util.UUID; -public class GeyserBootstrap implements IGeyserBootstrap { +public class GeyserStandaloneBootstrap implements GeyserBootstrap { private GeyserCommandManager geyserCommandManager; private GeyserConfiguration geyserConfig; - private GeyserLogger geyserLogger; + private GeyserStandaloneLogger geyserLogger; private GeyserConnector connector; public static void main(String[] args) { - new GeyserBootstrap().onEnable(); + new GeyserStandaloneBootstrap().onEnable(); } @Override public void onEnable() { - geyserLogger = new GeyserLogger(); + geyserLogger = new GeyserStandaloneLogger(); LoopbackUtil.checkLoopback(geyserLogger); try { File configFile = FileUtils.fileOrCopiedFromResource("config.yml", (x) -> x.replaceAll("generateduuid", UUID.randomUUID().toString())); - geyserConfig = FileUtils.loadConfig(configFile, GeyserConfiguration.class); + geyserConfig = FileUtils.loadConfig(configFile, GeyserStandaloneConfiguration.class); } catch (IOException ex) { geyserLogger.severe("Failed to read/create config.yml! Make sure it's up to date and/or readable+writable!", ex); System.exit(0); @@ -80,7 +80,7 @@ public class GeyserBootstrap implements IGeyserBootstrap { } @Override - public GeyserLogger getGeyserLogger() { + public GeyserStandaloneLogger getGeyserLogger() { return geyserLogger; } diff --git a/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/GeyserConfiguration.java b/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/GeyserStandaloneConfiguration.java similarity index 94% rename from bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/GeyserConfiguration.java rename to bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/GeyserStandaloneConfiguration.java index afd6179e8..8ae83d026 100644 --- a/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/GeyserConfiguration.java +++ b/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/GeyserStandaloneConfiguration.java @@ -29,8 +29,7 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Getter; - -import org.geysermc.common.IGeyserConfiguration; +import org.geysermc.connector.GeyserConfiguration; import java.nio.file.Path; import java.nio.file.Paths; @@ -38,7 +37,7 @@ import java.util.Map; @JsonIgnoreProperties(ignoreUnknown = true) @Getter -public class GeyserConfiguration implements IGeyserConfiguration { +public class GeyserStandaloneConfiguration implements GeyserConfiguration { private BedrockConfiguration bedrock; private RemoteConfiguration remote; @@ -66,6 +65,9 @@ public class GeyserConfiguration implements IGeyserConfiguration { @JsonProperty("default-locale") private String defaultLocale; + @JsonProperty("cache-chunks") + private boolean cacheChunks; + private MetricsInfo metrics; @Override diff --git a/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/console/GeyserLogger.java b/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/GeyserStandaloneLogger.java similarity index 64% rename from bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/console/GeyserLogger.java rename to bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/GeyserStandaloneLogger.java index 631de9052..ffb252b2e 100644 --- a/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/console/GeyserLogger.java +++ b/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/GeyserStandaloneLogger.java @@ -1,29 +1,30 @@ /* * 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: + * 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 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. + * 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 * - * @author GeyserMC - * @link https://github.com/GeyserMC/Geyser */ -package org.geysermc.platform.standalone.console; +package org.geysermc.platform.standalone; import lombok.extern.log4j.Log4j2; @@ -31,12 +32,11 @@ import net.minecrell.terminalconsole.SimpleTerminalConsole; import org.apache.logging.log4j.core.config.Configurator; import org.geysermc.common.ChatColor; -import org.geysermc.common.logger.IGeyserLogger; import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.command.CommandSender; @Log4j2 -public class GeyserLogger extends SimpleTerminalConsole implements IGeyserLogger, CommandSender { +public class GeyserStandaloneLogger extends SimpleTerminalConsole implements org.geysermc.connector.GeyserLogger, CommandSender { private boolean colored = true; diff --git a/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/LoopbackUtil.java b/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/LoopbackUtil.java index 20a810726..03c49705d 100644 --- a/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/LoopbackUtil.java +++ b/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/LoopbackUtil.java @@ -6,14 +6,13 @@ import java.nio.file.OpenOption; import java.nio.file.Paths; import org.geysermc.common.ChatColor; -import org.geysermc.platform.standalone.console.GeyserLogger; public class LoopbackUtil { private static final String checkExemption = "powershell -Command \"CheckNetIsolation LoopbackExempt -s\""; // Java's Exec feature runs as CMD, NetIsolation is only accessible from PowerShell. private static final String loopbackCommand = "powershell -Command \"CheckNetIsolation LoopbackExempt -a -n='Microsoft.MinecraftUWP_8wekyb3d8bbwe'\""; private static final String startScript = "powershell -Command \"Start-Process 'cmd' -ArgumentList /c,%temp%/loopback_minecraft.bat -Verb runAs\""; - public static void checkLoopback(GeyserLogger geyserLogger) { + public static void checkLoopback(GeyserStandaloneLogger geyserLogger) { if (System.getProperty("os.name").equalsIgnoreCase("Windows 10")) { try { Process process = Runtime.getRuntime().exec(checkExemption); diff --git a/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityConfiguration.java b/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityConfiguration.java index 920c65379..62ae20e2f 100644 --- a/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityConfiguration.java +++ b/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityConfiguration.java @@ -30,7 +30,7 @@ import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Getter; -import org.geysermc.common.IGeyserConfiguration; +import org.geysermc.connector.GeyserConfiguration; import java.nio.file.Path; import java.nio.file.Paths; @@ -38,7 +38,7 @@ import java.util.Map; @JsonIgnoreProperties(ignoreUnknown = true) @Getter -public class GeyserVelocityConfiguration implements IGeyserConfiguration { +public class GeyserVelocityConfiguration implements GeyserConfiguration { private BedrockConfiguration bedrock; private RemoteConfiguration remote; @@ -66,6 +66,9 @@ public class GeyserVelocityConfiguration implements IGeyserConfiguration { @JsonProperty("default-locale") private String defaultLocale; + @JsonProperty("cache-chunks") + private boolean cacheChunks; + private MetricsInfo metrics; @Override diff --git a/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityLogger.java b/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityLogger.java index 623c6481e..a935d786c 100644 --- a/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityLogger.java +++ b/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityLogger.java @@ -27,11 +27,11 @@ package org.geysermc.platform.velocity; import lombok.AllArgsConstructor; -import org.geysermc.common.logger.IGeyserLogger; +import org.geysermc.connector.GeyserLogger; import org.slf4j.Logger; @AllArgsConstructor -public class GeyserVelocityLogger implements IGeyserLogger { +public class GeyserVelocityLogger implements GeyserLogger { private Logger logger; private boolean debugMode; diff --git a/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityPlugin.java b/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityPlugin.java index 160c2d522..6e721a5f5 100644 --- a/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityPlugin.java +++ b/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityPlugin.java @@ -34,8 +34,8 @@ import com.velocitypowered.api.event.proxy.ProxyShutdownEvent; import com.velocitypowered.api.plugin.Plugin; import org.geysermc.common.PlatformType; -import org.geysermc.common.bootstrap.IGeyserBootstrap; import org.geysermc.connector.GeyserConnector; +import org.geysermc.connector.bootstrap.GeyserBootstrap; import org.geysermc.connector.utils.FileUtils; import org.geysermc.platform.velocity.command.GeyserVelocityCommandExecutor; import org.geysermc.platform.velocity.command.GeyserVelocityCommandManager; @@ -46,7 +46,7 @@ import java.io.IOException; import java.util.UUID; @Plugin(id = "geyser", name = GeyserConnector.NAME + "-Velocity", version = GeyserConnector.VERSION, url = "https://geysermc.org", authors = "GeyserMC") -public class GeyserVelocityPlugin implements IGeyserBootstrap { +public class GeyserVelocityPlugin implements GeyserBootstrap { @Inject private Logger logger; diff --git a/common/src/main/java/org/geysermc/common/IGeyserConfiguration.java b/common/src/main/java/org/geysermc/common/IGeyserConfiguration.java deleted file mode 100644 index 774e3394d..000000000 --- a/common/src/main/java/org/geysermc/common/IGeyserConfiguration.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * 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.common; - -import java.nio.file.Path; -import java.util.Map; - -public interface IGeyserConfiguration { - - IBedrockConfiguration getBedrock(); - - IRemoteConfiguration getRemote(); - - Map getUserAuths(); - - boolean isPingPassthrough(); - - int getMaxPlayers(); - - boolean isDebugMode(); - - int getGeneralThreadPool(); - - boolean isAllowThirdPartyCapes(); - - String getDefaultLocale(); - - Path getFloodgateKeyFile(); - - IMetricsInfo getMetrics(); - - interface IBedrockConfiguration { - - String getAddress(); - - int getPort(); - - String getMotd1(); - - String getMotd2(); - } - - interface IRemoteConfiguration { - - String getAddress(); - - int getPort(); - - String getAuthType(); - } - - interface IUserAuthenticationInfo { - String getEmail(); - - String getPassword(); - } - - interface IMetricsInfo { - - boolean isEnabled(); - - String getUniqueId(); - } -} diff --git a/common/src/main/java/org/geysermc/common/bootstrap/IGeyserBootstrap.java b/common/src/main/java/org/geysermc/common/bootstrap/IGeyserBootstrap.java deleted file mode 100644 index 5df61953f..000000000 --- a/common/src/main/java/org/geysermc/common/bootstrap/IGeyserBootstrap.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * 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.common.bootstrap; - -import org.geysermc.common.IGeyserConfiguration; -import org.geysermc.common.command.ICommandManager; -import org.geysermc.common.logger.IGeyserLogger; - -public interface IGeyserBootstrap { - - /** - * Called when the GeyserBootstrap is enabled - */ - void onEnable(); - - /** - * Called when the GeyserBootstrap is disabled - */ - void onDisable(); - - /** - * Returns the current GeyserConfig - * - * @return The current GeyserConfig - */ - IGeyserConfiguration getGeyserConfig(); - - /** - * Returns the current GeyserLogger - * - * @return The current GeyserLogger - */ - IGeyserLogger getGeyserLogger(); - - /** - * Returns the current GeyserCommandManager - * - * @return The current GeyserCommandManager - */ - ICommandManager getGeyserCommandManager(); -} diff --git a/common/src/main/java/org/geysermc/common/logger/IGeyserLogger.java b/common/src/main/java/org/geysermc/common/logger/IGeyserLogger.java deleted file mode 100644 index ad571ebbb..000000000 --- a/common/src/main/java/org/geysermc/common/logger/IGeyserLogger.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * 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.common.logger; - -public interface IGeyserLogger { - - /** - * Logs a severe message to console - * - * @param message the message to log - */ - void severe(String message); - - /** - * Logs a severe message and an exception to console - */ - void severe(String message, Throwable error); - - /** - * Logs an error message to console - * - * @param message the message to log - */ - void error(String message); - - /** - * Logs an error message and an exception to console - */ - void error(String message, Throwable error); - - /** - * Logs a warning message to console - * - * @param message the message to log - */ - void warning(String message); - - /** - * Logs an info message to console - * - * @param message the message to log - */ - void info(String message); - - /** - * Logs a debug message to console - * - * @param message the message to log - */ - void debug(String message); - - /** - * Sets if the logger should print debug messages - * - * @param debug if the logger should print debug messages - */ - void setDebug(boolean debug); -} diff --git a/connector/src/main/java/org/geysermc/connector/GeyserConfiguration.java b/connector/src/main/java/org/geysermc/connector/GeyserConfiguration.java new file mode 100644 index 000000000..cbbd507a1 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/GeyserConfiguration.java @@ -0,0 +1,90 @@ +/* + * 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; + +import java.nio.file.Path; +import java.util.Map; + +public interface GeyserConfiguration { + + IBedrockConfiguration getBedrock(); + + IRemoteConfiguration getRemote(); + + Map getUserAuths(); + + boolean isPingPassthrough(); + + int getMaxPlayers(); + + boolean isDebugMode(); + + int getGeneralThreadPool(); + + boolean isAllowThirdPartyCapes(); + + String getDefaultLocale(); + + Path getFloodgateKeyFile(); + + boolean isCacheChunks(); + + IMetricsInfo getMetrics(); + + interface IBedrockConfiguration { + + String getAddress(); + + int getPort(); + + String getMotd1(); + + String getMotd2(); + } + + interface IRemoteConfiguration { + + String getAddress(); + + int getPort(); + + String getAuthType(); + } + + interface IUserAuthenticationInfo { + String getEmail(); + + String getPassword(); + } + + interface IMetricsInfo { + + boolean isEnabled(); + + String getUniqueId(); + } +} diff --git a/connector/src/main/java/org/geysermc/connector/GeyserConnector.java b/connector/src/main/java/org/geysermc/connector/GeyserConnector.java index 2679857c4..6c9e8c7db 100644 --- a/connector/src/main/java/org/geysermc/connector/GeyserConnector.java +++ b/connector/src/main/java/org/geysermc/connector/GeyserConnector.java @@ -32,16 +32,15 @@ import com.nukkitx.protocol.bedrock.v390.Bedrock_v390; import lombok.Getter; import org.geysermc.common.AuthType; -import org.geysermc.common.IGeyserConfiguration; import org.geysermc.common.PlatformType; -import org.geysermc.common.bootstrap.IGeyserBootstrap; -import org.geysermc.common.logger.IGeyserLogger; +import org.geysermc.connector.bootstrap.GeyserBootstrap; import org.geysermc.connector.command.CommandManager; import org.geysermc.connector.metrics.Metrics; import org.geysermc.connector.network.ConnectorServerEventHandler; import org.geysermc.connector.network.remote.RemoteServer; import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.Translators; +import org.geysermc.connector.network.translators.world.WorldManager; import org.geysermc.connector.thread.PingPassthroughThread; import org.geysermc.connector.utils.Toolbox; @@ -76,19 +75,19 @@ public class GeyserConnector { private BedrockServer bedrockServer; private PlatformType platformType; - private IGeyserBootstrap bootstrap; + private GeyserBootstrap bootstrap; private Metrics metrics; - private GeyserConnector(PlatformType platformType, IGeyserBootstrap bootstrap) { + private GeyserConnector(PlatformType platformType, GeyserBootstrap bootstrap) { long startupTime = System.currentTimeMillis(); instance = this; this.bootstrap = bootstrap; - IGeyserLogger logger = bootstrap.getGeyserLogger(); - IGeyserConfiguration config = bootstrap.getGeyserConfig(); + GeyserLogger logger = bootstrap.getGeyserLogger(); + GeyserConfiguration config = bootstrap.getGeyserConfig(); this.platformType = platformType; @@ -191,7 +190,7 @@ public class GeyserConnector { players.remove(player.getSocketAddress()); } - public static GeyserConnector start(PlatformType platformType, IGeyserBootstrap bootstrap) { + public static GeyserConnector start(PlatformType platformType, GeyserBootstrap bootstrap) { return new GeyserConnector(platformType, bootstrap); } @@ -200,16 +199,20 @@ public class GeyserConnector { bootstrap.onEnable(); } - public IGeyserLogger getLogger() { + public GeyserLogger getLogger() { return bootstrap.getGeyserLogger(); } - public IGeyserConfiguration getConfig() { + public GeyserConfiguration getConfig() { return bootstrap.getGeyserConfig(); } public CommandManager getCommandManager() { - return (CommandManager) bootstrap.getGeyserCommandManager(); + return bootstrap.getGeyserCommandManager(); + } + + public WorldManager getWorldManager() { + return bootstrap.getWorldManager(); } public static GeyserConnector getInstance() { diff --git a/connector/src/main/java/org/geysermc/connector/GeyserLogger.java b/connector/src/main/java/org/geysermc/connector/GeyserLogger.java new file mode 100644 index 000000000..4acab2227 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/GeyserLogger.java @@ -0,0 +1,82 @@ +/* + * 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; + +public interface GeyserLogger { + + /** + * Logs a severe message to console + * + * @param message the message to log + */ + void severe(String message); + + /** + * Logs a severe message and an exception to console + */ + void severe(String message, Throwable error); + + /** + * Logs an error message to console + * + * @param message the message to log + */ + void error(String message); + + /** + * Logs an error message and an exception to console + */ + void error(String message, Throwable error); + + /** + * Logs a warning message to console + * + * @param message the message to log + */ + void warning(String message); + + /** + * Logs an info message to console + * + * @param message the message to log + */ + void info(String message); + + /** + * Logs a debug message to console + * + * @param message the message to log + */ + void debug(String message); + + /** + * Sets if the logger should print debug messages + * + * @param debug if the logger should print debug messages + */ + void setDebug(boolean debug); +} diff --git a/connector/src/main/java/org/geysermc/connector/bootstrap/GeyserBootstrap.java b/connector/src/main/java/org/geysermc/connector/bootstrap/GeyserBootstrap.java new file mode 100644 index 000000000..24b338c87 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/bootstrap/GeyserBootstrap.java @@ -0,0 +1,78 @@ +/* + * 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.bootstrap; + +import org.geysermc.connector.GeyserConfiguration; +import org.geysermc.connector.GeyserLogger; +import org.geysermc.connector.command.CommandManager; +import org.geysermc.connector.network.translators.world.CachedChunkManager; +import org.geysermc.connector.network.translators.world.WorldManager; + +public interface GeyserBootstrap { + + CachedChunkManager DEFAULT_CHUNK_MANAGER = new CachedChunkManager(); + + /** + * Called when the GeyserBootstrap is enabled + */ + void onEnable(); + + /** + * Called when the GeyserBootstrap is disabled + */ + void onDisable(); + + /** + * Returns the current GeyserConfiguration + * + * @return The current GeyserConfiguration + */ + GeyserConfiguration getGeyserConfig(); + + /** + * Returns the current GeyserLogger + * + * @return The current GeyserLogger + */ + GeyserLogger getGeyserLogger(); + + /** + * Returns the current CommandManager + * + * @return The current CommandManager + */ + CommandManager getGeyserCommandManager(); + + /** + * Returns the current WorldManager + * + * @return the current WorldManager + */ + default WorldManager getWorldManager() { + return DEFAULT_CHUNK_MANAGER; + } +} diff --git a/connector/src/main/java/org/geysermc/connector/command/CommandManager.java b/connector/src/main/java/org/geysermc/connector/command/CommandManager.java index 7b1b4d69b..88b9e795d 100644 --- a/connector/src/main/java/org/geysermc/connector/command/CommandManager.java +++ b/connector/src/main/java/org/geysermc/connector/command/CommandManager.java @@ -26,7 +26,7 @@ package org.geysermc.connector.command; import lombok.Getter; -import org.geysermc.common.command.ICommandManager; + import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.command.defaults.*; @@ -34,7 +34,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.Map; -public abstract class CommandManager implements ICommandManager { +public abstract class CommandManager { @Getter private final Map commands = Collections.synchronizedMap(new HashMap<>()); @@ -87,4 +87,12 @@ public abstract class CommandManager implements ICommandManager { cmd.execute(sender, args); } + + /** + * Returns the description of the given command + * + * @param command Command to get the description for + * @return Command description + */ + public abstract String getDescription(String command); } diff --git a/connector/src/main/java/org/geysermc/connector/entity/FallingBlockEntity.java b/connector/src/main/java/org/geysermc/connector/entity/FallingBlockEntity.java index 5a0cac8f4..59e1d408e 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/FallingBlockEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/FallingBlockEntity.java @@ -28,7 +28,7 @@ package org.geysermc.connector.entity; import com.nukkitx.math.vector.Vector3f; import com.nukkitx.protocol.bedrock.data.EntityData; import org.geysermc.connector.entity.type.EntityType; -import org.geysermc.connector.network.translators.block.BlockTranslator; +import org.geysermc.connector.network.translators.world.block.BlockTranslator; public class FallingBlockEntity extends Entity { diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/animal/horse/LlamaEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/animal/horse/LlamaEntity.java index 26c13a5ce..c2dad7a57 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/living/animal/horse/LlamaEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/living/animal/horse/LlamaEntity.java @@ -32,7 +32,7 @@ import com.nukkitx.protocol.bedrock.data.ItemData; import com.nukkitx.protocol.bedrock.packet.MobArmorEquipmentPacket; import org.geysermc.connector.entity.type.EntityType; import org.geysermc.connector.network.session.GeyserSession; -import org.geysermc.connector.network.translators.block.BlockTranslator; +import org.geysermc.connector.network.translators.world.block.BlockTranslator; public class LlamaEntity extends ChestedHorseEntity { diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/monster/EndermanEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/monster/EndermanEntity.java index a423013cb..644181ab7 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/living/monster/EndermanEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/living/monster/EndermanEntity.java @@ -32,7 +32,7 @@ import com.nukkitx.protocol.bedrock.data.EntityData; import com.nukkitx.protocol.bedrock.data.EntityFlag; import org.geysermc.connector.entity.type.EntityType; import org.geysermc.connector.network.session.GeyserSession; -import org.geysermc.connector.network.translators.block.BlockTranslator; +import org.geysermc.connector.network.translators.world.block.BlockTranslator; public class EndermanEntity extends MonsterEntity { diff --git a/connector/src/main/java/org/geysermc/connector/network/ConnectorServerEventHandler.java b/connector/src/main/java/org/geysermc/connector/network/ConnectorServerEventHandler.java index 60ad28d47..8810cffb4 100644 --- a/connector/src/main/java/org/geysermc/connector/network/ConnectorServerEventHandler.java +++ b/connector/src/main/java/org/geysermc/connector/network/ConnectorServerEventHandler.java @@ -30,7 +30,7 @@ import com.nukkitx.protocol.bedrock.BedrockPong; import com.nukkitx.protocol.bedrock.BedrockServerEventHandler; import com.nukkitx.protocol.bedrock.BedrockServerSession; -import org.geysermc.common.IGeyserConfiguration; +import org.geysermc.connector.GeyserConfiguration; import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.utils.MessageUtils; @@ -55,7 +55,7 @@ public class ConnectorServerEventHandler implements BedrockServerEventHandler { public BedrockPong onQuery(InetSocketAddress inetSocketAddress) { connector.getLogger().debug(inetSocketAddress + " has pinged you!"); - IGeyserConfiguration config = connector.getConfig(); + GeyserConfiguration config = connector.getConfig(); ServerStatusInfo serverInfo = connector.getPassthroughThread().getInfo(); BedrockPong pong = new BedrockPong(); @@ -101,11 +101,6 @@ public class ConnectorServerEventHandler implements BedrockServerEventHandler { if (player != null) { player.disconnect(disconnectReason.name()); connector.removePlayer(player); - - player.getEntityCache().clear(); - player.getInventoryCache().getInventories().clear(); - player.getWindowCache().getWindows().clear(); - player.getScoreboardCache().removeScoreboard(); } }); bedrockServerSession.setPacketCodec(GeyserConnector.BEDROCK_PACKET_CODEC); diff --git a/connector/src/main/java/org/geysermc/connector/network/UpstreamPacketHandler.java b/connector/src/main/java/org/geysermc/connector/network/UpstreamPacketHandler.java index 7e41fca8b..2839237e3 100644 --- a/connector/src/main/java/org/geysermc/connector/network/UpstreamPacketHandler.java +++ b/connector/src/main/java/org/geysermc/connector/network/UpstreamPacketHandler.java @@ -28,7 +28,7 @@ package org.geysermc.connector.network; import com.nukkitx.protocol.bedrock.BedrockPacket; import com.nukkitx.protocol.bedrock.packet.*; import org.geysermc.common.AuthType; -import org.geysermc.common.IGeyserConfiguration; +import org.geysermc.connector.GeyserConfiguration; import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.Registry; @@ -94,7 +94,7 @@ public class UpstreamPacketHandler extends LoggingPacketHandler { private boolean couldLoginUserByName(String bedrockUsername) { if (connector.getConfig().getUserAuths() != null) { - IGeyserConfiguration.IUserAuthenticationInfo info = connector.getConfig().getUserAuths().get(bedrockUsername); + GeyserConfiguration.IUserAuthenticationInfo info = connector.getConfig().getUserAuths().get(bedrockUsername); if (info != null) { connector.getLogger().info("using stored credentials for bedrock user " + session.getAuthData().getName()); diff --git a/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java b/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java index fafa2bfaa..0b4a57dc2 100644 --- a/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java +++ b/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java @@ -62,7 +62,7 @@ import org.geysermc.connector.network.session.auth.AuthData; import org.geysermc.connector.network.session.auth.BedrockClientData; import org.geysermc.connector.network.session.cache.*; import org.geysermc.connector.network.translators.Registry; -import org.geysermc.connector.network.translators.block.BlockTranslator; +import org.geysermc.connector.network.translators.world.block.BlockTranslator; import org.geysermc.connector.utils.ChunkUtils; import org.geysermc.connector.utils.LocaleUtils; import org.geysermc.connector.utils.Toolbox; @@ -337,10 +337,11 @@ public class GeyserSession implements CommandSender { } } - this.entityCache.getEntities().clear(); - this.scoreboardCache.removeScoreboard(); - this.inventoryCache.getInventories().clear(); - this.windowCache.getWindows().clear(); + this.chunkCache = null; + this.entityCache = null; + this.scoreboardCache = null; + this.inventoryCache = null; + this.windowCache = null; closed = true; } diff --git a/connector/src/main/java/org/geysermc/connector/network/session/cache/ChunkCache.java b/connector/src/main/java/org/geysermc/connector/network/session/cache/ChunkCache.java index bc88694d8..ac7ab06cf 100644 --- a/connector/src/main/java/org/geysermc/connector/network/session/cache/ChunkCache.java +++ b/connector/src/main/java/org/geysermc/connector/network/session/cache/ChunkCache.java @@ -29,34 +29,39 @@ import com.github.steveice10.mc.protocol.data.game.chunk.Chunk; import com.github.steveice10.mc.protocol.data.game.chunk.Column; import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position; import com.github.steveice10.mc.protocol.data.game.world.block.BlockState; -import com.nukkitx.protocol.bedrock.packet.LevelChunkPacket; import lombok.Getter; import org.geysermc.connector.network.session.GeyserSession; -import org.geysermc.connector.network.translators.Translators; -import org.geysermc.connector.network.translators.block.BlockTranslator; -import org.geysermc.connector.world.chunk.ChunkPosition; +import org.geysermc.connector.network.translators.world.block.BlockTranslator; +import org.geysermc.connector.network.translators.world.chunk.ChunkPosition; import java.util.HashMap; import java.util.Map; public class ChunkCache { - private GeyserSession session; + private boolean cache; + private final GeyserSession session; @Getter - private Map chunks; + private Map chunks = new HashMap<>(); public ChunkCache(GeyserSession session) { this.session = session; - this.chunks = new HashMap<>(); + this.cache = session.getConnector().getConfig().isCacheChunks(); } public void addToCache(Column chunk) { + if (!cache) { + return; + } ChunkPosition position = new ChunkPosition(chunk.getX(), chunk.getZ()); chunks.put(position, chunk); } public void updateBlock(Position position, BlockState block) { + if (!cache) { + return; + } ChunkPosition chunkPosition = new ChunkPosition(position.getX() >> 4, position.getZ() >> 4); if (!chunks.containsKey(chunkPosition)) return; @@ -70,6 +75,9 @@ public class ChunkCache { } public BlockState getBlockAt(Position position) { + if (!cache) { + return BlockTranslator.AIR; + } ChunkPosition chunkPosition = new ChunkPosition(position.getX() >> 4, position.getZ() >> 4); if (!chunks.containsKey(chunkPosition)) return BlockTranslator.AIR; @@ -85,24 +93,9 @@ public class ChunkCache { } public void removeChunk(ChunkPosition position) { - chunks.remove(position); - sendEmptyChunk(position, true); - } - - public void sendEmptyChunk(ChunkPosition position) { - sendEmptyChunk(position, false); - } - - public void sendEmptyChunk(ChunkPosition position, boolean force) { - if (!force && chunks.containsKey(position)) + if (!cache) { return; - - LevelChunkPacket levelChunkPacket = new LevelChunkPacket(); - levelChunkPacket.setChunkX(position.getX()); - levelChunkPacket.setChunkZ(position.getZ()); - levelChunkPacket.setCachingEnabled(false); - levelChunkPacket.setSubChunksLength(0); - levelChunkPacket.setData(Translators.EMPTY_LEVEL_CHUNK_DATA); - session.getUpstream().sendPacket(levelChunkPacket); + } + chunks.remove(position); } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/Translators.java b/connector/src/main/java/org/geysermc/connector/network/translators/Translators.java index f0a3fd28c..96323c1bf 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/Translators.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/Translators.java @@ -33,8 +33,8 @@ import java.util.Map; import com.github.steveice10.mc.protocol.data.game.window.WindowType; import com.nukkitx.protocol.bedrock.data.ContainerType; import org.geysermc.connector.GeyserConnector; -import org.geysermc.connector.network.translators.block.BlockTranslator; -import org.geysermc.connector.network.translators.block.entity.*; +import org.geysermc.connector.network.translators.world.block.BlockTranslator; +import org.geysermc.connector.network.translators.world.block.entity.*; import org.geysermc.connector.network.translators.inventory.*; import org.geysermc.connector.network.translators.inventory.updater.ContainerInventoryUpdater; import org.geysermc.connector.network.translators.inventory.updater.InventoryUpdater; @@ -117,7 +117,7 @@ public class Translators { } private static void registerBlockEntityTranslators() { - Reflections ref = new Reflections("org.geysermc.connector.network.translators.block.entity"); + Reflections ref = new Reflections("org.geysermc.connector.network.translators.world.block.entity"); for (Class clazz : ref.getTypesAnnotatedWith(BlockEntity.class)) { diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockActionTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockActionTranslator.java index 43e0a5704..1c8159cfd 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockActionTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockActionTranslator.java @@ -28,9 +28,7 @@ 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; @@ -45,7 +43,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; +import org.geysermc.connector.network.translators.world.block.BlockTranslator; @Translator(packet = PlayerActionPacket.class) public class BedrockActionTranslator extends PacketTranslator { diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockInventoryTransactionTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockInventoryTransactionTranslator.java index 7eb051c50..905d7afbc 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockInventoryTransactionTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockInventoryTransactionTranslator.java @@ -25,6 +25,7 @@ package org.geysermc.connector.network.translators.bedrock; +import com.github.steveice10.mc.protocol.data.game.world.block.BlockState; import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerPlaceBlockPacket; import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position; import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode; @@ -37,8 +38,10 @@ import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlaye import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerUseItemPacket; import com.nukkitx.math.vector.Vector3i; import com.nukkitx.math.vector.Vector3f; +import com.nukkitx.protocol.bedrock.data.LevelEventType; import com.nukkitx.protocol.bedrock.packet.InventoryTransactionPacket; +import com.nukkitx.protocol.bedrock.packet.LevelEventPacket; import org.geysermc.connector.entity.Entity; import org.geysermc.connector.inventory.Inventory; import org.geysermc.connector.network.session.GeyserSession; @@ -47,6 +50,7 @@ import org.geysermc.connector.network.translators.Translator; import org.geysermc.connector.network.translators.Translators; import org.geysermc.connector.network.translators.item.ItemEntry; import org.geysermc.connector.network.translators.item.ItemTranslator; +import org.geysermc.connector.network.translators.world.block.BlockTranslator; import org.geysermc.connector.utils.InventoryUtils; @Translator(packet = InventoryTransactionPacket.class) @@ -76,31 +80,31 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator { @@ -110,7 +108,7 @@ public class JavaChunkDataTranslator extends PacketTranslator paletteList = new ArrayList<>(); - Reflections ref = new Reflections("org.geysermc.connector.network.translators.block.entity"); + Reflections ref = new Reflections("org.geysermc.connector.network.translators.world.block.entity"); ref.getTypesAnnotatedWith(BlockEntity.class); int waterRuntimeId = -1; diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/BannerBlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/BannerBlockEntityTranslator.java similarity index 96% rename from connector/src/main/java/org/geysermc/connector/network/translators/block/entity/BannerBlockEntityTranslator.java rename to connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/BannerBlockEntityTranslator.java index 22d26cb4b..0fc9abda6 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/BannerBlockEntityTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/BannerBlockEntityTranslator.java @@ -23,7 +23,7 @@ * @link https://github.com/GeyserMC/Geyser */ -package org.geysermc.connector.network.translators.block.entity; +package org.geysermc.connector.network.translators.world.block.entity; import com.github.steveice10.mc.protocol.data.game.world.block.BlockState; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; @@ -32,7 +32,7 @@ import com.nukkitx.nbt.CompoundTagBuilder; import com.nukkitx.nbt.tag.IntTag; import com.nukkitx.nbt.tag.StringTag; import com.nukkitx.nbt.tag.Tag; -import org.geysermc.connector.network.translators.block.BlockStateValues; +import org.geysermc.connector.network.translators.world.block.BlockStateValues; import java.util.ArrayList; import java.util.List; diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/BedBlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/BedBlockEntityTranslator.java similarity index 94% rename from connector/src/main/java/org/geysermc/connector/network/translators/block/entity/BedBlockEntityTranslator.java rename to connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/BedBlockEntityTranslator.java index a8dae2532..543828e8e 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/BedBlockEntityTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/BedBlockEntityTranslator.java @@ -23,14 +23,14 @@ * @link https://github.com/GeyserMC/Geyser */ -package org.geysermc.connector.network.translators.block.entity; +package org.geysermc.connector.network.translators.world.block.entity; import com.github.steveice10.mc.protocol.data.game.world.block.BlockState; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.nukkitx.nbt.CompoundTagBuilder; import com.nukkitx.nbt.tag.ByteTag; import com.nukkitx.nbt.tag.Tag; -import org.geysermc.connector.network.translators.block.BlockStateValues; +import org.geysermc.connector.network.translators.world.block.BlockStateValues; import java.util.ArrayList; import java.util.List; diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/BlockEntity.java b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/BlockEntity.java similarity index 96% rename from connector/src/main/java/org/geysermc/connector/network/translators/block/entity/BlockEntity.java rename to connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/BlockEntity.java index 47cbbaf30..d08ab561c 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/BlockEntity.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/BlockEntity.java @@ -23,7 +23,7 @@ * @link https://github.com/GeyserMC/Geyser */ -package org.geysermc.connector.network.translators.block.entity; +package org.geysermc.connector.network.translators.world.block.entity; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/BlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/BlockEntityTranslator.java similarity index 98% rename from connector/src/main/java/org/geysermc/connector/network/translators/block/entity/BlockEntityTranslator.java rename to connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/BlockEntityTranslator.java index f28257898..4545aed53 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/BlockEntityTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/BlockEntityTranslator.java @@ -23,7 +23,7 @@ * @link https://github.com/GeyserMC/Geyser */ -package org.geysermc.connector.network.translators.block.entity; +package org.geysermc.connector.network.translators.world.block.entity; import com.github.steveice10.mc.protocol.data.game.world.block.BlockState; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/CampfireBlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/CampfireBlockEntityTranslator.java similarity index 98% rename from connector/src/main/java/org/geysermc/connector/network/translators/block/entity/CampfireBlockEntityTranslator.java rename to connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/CampfireBlockEntityTranslator.java index 11b7e8649..d91e47c27 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/CampfireBlockEntityTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/CampfireBlockEntityTranslator.java @@ -23,7 +23,7 @@ * @link https://github.com/GeyserMC/Geyser */ -package org.geysermc.connector.network.translators.block.entity; +package org.geysermc.connector.network.translators.world.block.entity; import com.github.steveice10.mc.protocol.data.game.world.block.BlockState; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/EmptyBlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/EmptyBlockEntityTranslator.java similarity index 96% rename from connector/src/main/java/org/geysermc/connector/network/translators/block/entity/EmptyBlockEntityTranslator.java rename to connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/EmptyBlockEntityTranslator.java index e46014008..f95cb89ec 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/EmptyBlockEntityTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/EmptyBlockEntityTranslator.java @@ -23,7 +23,7 @@ * @link https://github.com/GeyserMC/Geyser */ -package org.geysermc.connector.network.translators.block.entity; +package org.geysermc.connector.network.translators.world.block.entity; import com.github.steveice10.mc.protocol.data.game.world.block.BlockState; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/EndGatewayBlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/EndGatewayBlockEntityTranslator.java similarity index 98% rename from connector/src/main/java/org/geysermc/connector/network/translators/block/entity/EndGatewayBlockEntityTranslator.java rename to connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/EndGatewayBlockEntityTranslator.java index de5868a4b..10de9d32d 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/EndGatewayBlockEntityTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/EndGatewayBlockEntityTranslator.java @@ -23,7 +23,7 @@ * @link https://github.com/GeyserMC/Geyser */ -package org.geysermc.connector.network.translators.block.entity; +package org.geysermc.connector.network.translators.world.block.entity; import com.github.steveice10.mc.protocol.data.game.world.block.BlockState; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/RequiresBlockState.java b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/RequiresBlockState.java similarity index 95% rename from connector/src/main/java/org/geysermc/connector/network/translators/block/entity/RequiresBlockState.java rename to connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/RequiresBlockState.java index ed8e6ede9..4df7292ad 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/RequiresBlockState.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/RequiresBlockState.java @@ -23,7 +23,7 @@ * @link https://github.com/GeyserMC/Geyser */ -package org.geysermc.connector.network.translators.block.entity; +package org.geysermc.connector.network.translators.world.block.entity; import com.github.steveice10.mc.protocol.data.game.world.block.BlockState; diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/SignBlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/SignBlockEntityTranslator.java similarity index 97% rename from connector/src/main/java/org/geysermc/connector/network/translators/block/entity/SignBlockEntityTranslator.java rename to connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/SignBlockEntityTranslator.java index 74dcdd13e..0dde33077 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/SignBlockEntityTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/SignBlockEntityTranslator.java @@ -23,7 +23,7 @@ * @link https://github.com/GeyserMC/Geyser */ -package org.geysermc.connector.network.translators.block.entity; +package org.geysermc.connector.network.translators.world.block.entity; import com.github.steveice10.mc.protocol.data.game.world.block.BlockState; import com.github.steveice10.mc.protocol.data.message.Message; diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/SkullBlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/SkullBlockEntityTranslator.java similarity index 93% rename from connector/src/main/java/org/geysermc/connector/network/translators/block/entity/SkullBlockEntityTranslator.java rename to connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/SkullBlockEntityTranslator.java index 2380663b1..7e73c8466 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/SkullBlockEntityTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/SkullBlockEntityTranslator.java @@ -1,71 +1,71 @@ -/* - * 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.block.entity; - -import com.github.steveice10.mc.protocol.data.game.world.block.BlockState; -import com.nukkitx.nbt.CompoundTagBuilder; -import com.nukkitx.nbt.tag.ByteTag; -import com.nukkitx.nbt.tag.CompoundTag; -import com.nukkitx.nbt.tag.FloatTag; -import com.nukkitx.nbt.tag.Tag; -import org.geysermc.connector.network.translators.block.BlockStateValues; - -import java.util.ArrayList; -import java.util.List; - -@BlockEntity(name = "Skull", delay = false, regex = "skull") -public class SkullBlockEntityTranslator extends BlockEntityTranslator implements RequiresBlockState { - - @Override - public boolean isBlock(BlockState blockState) { - return BlockStateValues.getSkullVariant(blockState) != -1; - } - - @Override - public List> translateTag(com.github.steveice10.opennbt.tag.builtin.CompoundTag tag, BlockState blockState) { - List> tags = new ArrayList<>(); - byte skullVariant = BlockStateValues.getSkullVariant(blockState); - float rotation = BlockStateValues.getSkullRotation(blockState) * 22.5f; - // Just in case... - if (skullVariant == -1) skullVariant = 0; - tags.add(new FloatTag("Rotation", rotation)); - tags.add(new ByteTag("SkullType", skullVariant)); - return tags; - } - - @Override - public com.github.steveice10.opennbt.tag.builtin.CompoundTag getDefaultJavaTag(String javaId, int x, int y, int z) { - return null; - } - - @Override - public CompoundTag getDefaultBedrockTag(String bedrockId, int x, int y, int z) { - CompoundTagBuilder tagBuilder = getConstantBedrockTag(bedrockId, x, y, z).toBuilder(); - tagBuilder.floatTag("Rotation", 0); - tagBuilder.byteTag("SkullType", (byte) 0); - return tagBuilder.buildRootTag(); - } -} +/* + * 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.world.block.entity; + +import com.github.steveice10.mc.protocol.data.game.world.block.BlockState; +import com.nukkitx.nbt.CompoundTagBuilder; +import com.nukkitx.nbt.tag.ByteTag; +import com.nukkitx.nbt.tag.CompoundTag; +import com.nukkitx.nbt.tag.FloatTag; +import com.nukkitx.nbt.tag.Tag; +import org.geysermc.connector.network.translators.world.block.BlockStateValues; + +import java.util.ArrayList; +import java.util.List; + +@BlockEntity(name = "Skull", delay = false, regex = "skull") +public class SkullBlockEntityTranslator extends BlockEntityTranslator implements RequiresBlockState { + + @Override + public boolean isBlock(BlockState blockState) { + return BlockStateValues.getSkullVariant(blockState) != -1; + } + + @Override + public List> translateTag(com.github.steveice10.opennbt.tag.builtin.CompoundTag tag, BlockState blockState) { + List> tags = new ArrayList<>(); + byte skullVariant = BlockStateValues.getSkullVariant(blockState); + float rotation = BlockStateValues.getSkullRotation(blockState) * 22.5f; + // Just in case... + if (skullVariant == -1) skullVariant = 0; + tags.add(new FloatTag("Rotation", rotation)); + tags.add(new ByteTag("SkullType", skullVariant)); + return tags; + } + + @Override + public com.github.steveice10.opennbt.tag.builtin.CompoundTag getDefaultJavaTag(String javaId, int x, int y, int z) { + return null; + } + + @Override + public CompoundTag getDefaultBedrockTag(String bedrockId, int x, int y, int z) { + CompoundTagBuilder tagBuilder = getConstantBedrockTag(bedrockId, x, y, z).toBuilder(); + tagBuilder.floatTag("Rotation", 0); + tagBuilder.byteTag("SkullType", (byte) 0); + return tagBuilder.buildRootTag(); + } +} diff --git a/connector/src/main/java/org/geysermc/connector/world/chunk/BlockStorage.java b/connector/src/main/java/org/geysermc/connector/network/translators/world/chunk/BlockStorage.java similarity index 68% rename from connector/src/main/java/org/geysermc/connector/world/chunk/BlockStorage.java rename to connector/src/main/java/org/geysermc/connector/network/translators/world/chunk/BlockStorage.java index 360fdea45..5995ecf9e 100644 --- a/connector/src/main/java/org/geysermc/connector/world/chunk/BlockStorage.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/world/chunk/BlockStorage.java @@ -1,21 +1,37 @@ /* * Copyright (c) 2019-2020 GeyserMC. http://geysermc.org * - * This code in this file is derived from NukkitX and permission has - * been granted to us allowing the usage of it in Geyser. + * 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 * - * Copyright (C) 2020 The NukkitX Project - * https://github.com/NukkitX/Nukkit */ -package org.geysermc.connector.world.chunk; +package org.geysermc.connector.network.translators.world.chunk; import com.nukkitx.network.VarInts; import io.netty.buffer.ByteBuf; import it.unimi.dsi.fastutil.ints.IntArrayList; import it.unimi.dsi.fastutil.ints.IntList; -import org.geysermc.connector.world.chunk.bitarray.BitArray; -import org.geysermc.connector.world.chunk.bitarray.BitArrayVersion; +import org.geysermc.connector.network.translators.world.chunk.bitarray.BitArray; +import org.geysermc.connector.network.translators.world.chunk.bitarray.BitArrayVersion; import java.util.function.IntConsumer; diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/world/chunk/ChunkPosition.java b/connector/src/main/java/org/geysermc/connector/network/translators/world/chunk/ChunkPosition.java new file mode 100644 index 000000000..a51755d0b --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/world/chunk/ChunkPosition.java @@ -0,0 +1,54 @@ +/* + * 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.world.chunk; + +import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position; +import lombok.AllArgsConstructor; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@AllArgsConstructor +@EqualsAndHashCode +public class ChunkPosition { + + private int x; + private int z; + + public Position getBlock(int x, int y, int z) { + return new Position((this.x << 4) + x, y, (this.z << 4) + z); + } + + public Position getChunkBlock(int x, int y, int z) { + int chunkX = x & 15; + int chunkY = y & 15; + int chunkZ = z & 15; + return new Position(chunkX, chunkY, chunkZ); + } +} diff --git a/connector/src/main/java/org/geysermc/connector/world/chunk/ChunkSection.java b/connector/src/main/java/org/geysermc/connector/network/translators/world/chunk/ChunkSection.java similarity index 77% rename from connector/src/main/java/org/geysermc/connector/world/chunk/ChunkSection.java rename to connector/src/main/java/org/geysermc/connector/network/translators/world/chunk/ChunkSection.java index c160d11b3..4ede0c255 100644 --- a/connector/src/main/java/org/geysermc/connector/world/chunk/ChunkSection.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/world/chunk/ChunkSection.java @@ -1,14 +1,30 @@ /* * Copyright (c) 2019-2020 GeyserMC. http://geysermc.org * - * This code in this file is derived from NukkitX and permission has - * been granted to us allowing the usage of it in Geyser. + * 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 * - * Copyright (C) 2020 The NukkitX Project - * https://github.com/NukkitX/Nukkit */ -package org.geysermc.connector.world.chunk; +package org.geysermc.connector.network.translators.world.chunk; import com.nukkitx.network.util.Preconditions; import io.netty.buffer.ByteBuf; diff --git a/connector/src/main/java/org/geysermc/connector/world/chunk/NibbleArray.java b/connector/src/main/java/org/geysermc/connector/network/translators/world/chunk/NibbleArray.java similarity index 62% rename from connector/src/main/java/org/geysermc/connector/world/chunk/NibbleArray.java rename to connector/src/main/java/org/geysermc/connector/network/translators/world/chunk/NibbleArray.java index 8da068f75..08303e189 100644 --- a/connector/src/main/java/org/geysermc/connector/world/chunk/NibbleArray.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/world/chunk/NibbleArray.java @@ -1,14 +1,30 @@ /* * Copyright (c) 2019-2020 GeyserMC. http://geysermc.org * - * This code in this file is derived from NukkitX and permission has - * been granted to us allowing the usage of it in Geyser. + * 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 * - * Copyright (C) 2020 The NukkitX Project - * https://github.com/NukkitX/Nukkit */ -package org.geysermc.connector.world.chunk; +package org.geysermc.connector.network.translators.world.chunk; import com.nukkitx.network.util.Preconditions; diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/world/chunk/bitarray/BitArray.java b/connector/src/main/java/org/geysermc/connector/network/translators/world/chunk/bitarray/BitArray.java new file mode 100644 index 000000000..728fe237e --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/world/chunk/bitarray/BitArray.java @@ -0,0 +1,42 @@ +/* + * 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.world.chunk.bitarray; + +public interface BitArray { + + void set(int index, int value); + + int get(int index); + + int size(); + + int[] getWords(); + + BitArrayVersion getVersion(); + + BitArray copy(); +} \ No newline at end of file diff --git a/connector/src/main/java/org/geysermc/connector/world/chunk/bitarray/BitArrayVersion.java b/connector/src/main/java/org/geysermc/connector/network/translators/world/chunk/bitarray/BitArrayVersion.java similarity index 60% rename from connector/src/main/java/org/geysermc/connector/world/chunk/bitarray/BitArrayVersion.java rename to connector/src/main/java/org/geysermc/connector/network/translators/world/chunk/bitarray/BitArrayVersion.java index f6e3ef5e5..be91f13d8 100644 --- a/connector/src/main/java/org/geysermc/connector/world/chunk/bitarray/BitArrayVersion.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/world/chunk/bitarray/BitArrayVersion.java @@ -1,14 +1,30 @@ /* * Copyright (c) 2019-2020 GeyserMC. http://geysermc.org * - * This code in this file is derived from NukkitX and permission has - * been granted to us allowing the usage of it in Geyser. + * 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 * - * Copyright (C) 2020 The NukkitX Project - * https://github.com/NukkitX/Nukkit */ -package org.geysermc.connector.world.chunk.bitarray; +package org.geysermc.connector.network.translators.world.chunk.bitarray; import org.geysermc.connector.utils.MathUtils; diff --git a/connector/src/main/java/org/geysermc/connector/world/chunk/bitarray/PaddedBitArray.java b/connector/src/main/java/org/geysermc/connector/network/translators/world/chunk/bitarray/PaddedBitArray.java similarity index 65% rename from connector/src/main/java/org/geysermc/connector/world/chunk/bitarray/PaddedBitArray.java rename to connector/src/main/java/org/geysermc/connector/network/translators/world/chunk/bitarray/PaddedBitArray.java index d2f9393a3..36a97a30c 100644 --- a/connector/src/main/java/org/geysermc/connector/world/chunk/bitarray/PaddedBitArray.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/world/chunk/bitarray/PaddedBitArray.java @@ -1,14 +1,30 @@ /* * Copyright (c) 2019-2020 GeyserMC. http://geysermc.org * - * This code in this file is derived from NukkitX and permission has - * been granted to us allowing the usage of it in Geyser. + * 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 * - * Copyright (C) 2020 The NukkitX Project - * https://github.com/NukkitX/Nukkit */ -package org.geysermc.connector.world.chunk.bitarray; +package org.geysermc.connector.network.translators.world.chunk.bitarray; import com.nukkitx.network.util.Preconditions; import org.geysermc.connector.utils.MathUtils; diff --git a/connector/src/main/java/org/geysermc/connector/world/chunk/bitarray/Pow2BitArray.java b/connector/src/main/java/org/geysermc/connector/network/translators/world/chunk/bitarray/Pow2BitArray.java similarity index 67% rename from connector/src/main/java/org/geysermc/connector/world/chunk/bitarray/Pow2BitArray.java rename to connector/src/main/java/org/geysermc/connector/network/translators/world/chunk/bitarray/Pow2BitArray.java index bcb878a70..c9bd27646 100644 --- a/connector/src/main/java/org/geysermc/connector/world/chunk/bitarray/Pow2BitArray.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/world/chunk/bitarray/Pow2BitArray.java @@ -1,14 +1,30 @@ /* * Copyright (c) 2019-2020 GeyserMC. http://geysermc.org * - * This code in this file is derived from NukkitX and permission has - * been granted to us allowing the usage of it in Geyser. + * 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 * - * Copyright (C) 2020 The NukkitX Project - * https://github.com/NukkitX/Nukkit */ -package org.geysermc.connector.world.chunk.bitarray; +package org.geysermc.connector.network.translators.world.chunk.bitarray; import com.nukkitx.network.util.Preconditions; import org.geysermc.connector.utils.MathUtils; diff --git a/connector/src/main/java/org/geysermc/connector/utils/BlockEntityUtils.java b/connector/src/main/java/org/geysermc/connector/utils/BlockEntityUtils.java index 0dcd13ad9..2c04c205b 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/BlockEntityUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/BlockEntityUtils.java @@ -6,7 +6,7 @@ import com.nukkitx.protocol.bedrock.packet.BlockEntityDataPacket; import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.Translators; -import org.geysermc.connector.network.translators.block.entity.BlockEntityTranslator; +import org.geysermc.connector.network.translators.world.block.entity.BlockEntityTranslator; public class BlockEntityUtils { diff --git a/connector/src/main/java/org/geysermc/connector/utils/BlockUtils.java b/connector/src/main/java/org/geysermc/connector/utils/BlockUtils.java index 34287073e..3a9ecb867 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/BlockUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/BlockUtils.java @@ -28,7 +28,7 @@ package org.geysermc.connector.utils; import com.github.steveice10.mc.protocol.data.game.entity.Effect; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import org.geysermc.connector.entity.PlayerEntity; -import org.geysermc.connector.network.translators.block.BlockTranslator; +import org.geysermc.connector.network.translators.world.block.BlockTranslator; import org.geysermc.connector.network.translators.item.ItemEntry; import org.geysermc.connector.network.translators.item.ToolItemEntry; diff --git a/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java b/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java index d496215ac..3a3d11829 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java @@ -42,16 +42,16 @@ import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; import lombok.Getter; import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.network.session.GeyserSession; -import org.geysermc.connector.network.translators.block.entity.*; +import org.geysermc.connector.network.translators.world.block.entity.*; import org.geysermc.connector.network.translators.Translators; -import org.geysermc.connector.network.translators.block.BlockTranslator; -import org.geysermc.connector.world.chunk.ChunkPosition; -import org.geysermc.connector.world.chunk.ChunkSection; +import org.geysermc.connector.network.translators.world.block.BlockTranslator; +import org.geysermc.connector.network.translators.world.chunk.ChunkPosition; +import org.geysermc.connector.network.translators.world.chunk.ChunkSection; import java.util.HashMap; import java.util.Map; -import static org.geysermc.connector.network.translators.block.BlockTranslator.BEDROCK_WATER_ID; +import static org.geysermc.connector.network.translators.world.block.BlockTranslator.BEDROCK_WATER_ID; public class ChunkUtils { @@ -181,6 +181,7 @@ public class ChunkUtils { } } } + session.getChunkCache().updateBlock(new Position(position.getX(), position.getY(), position.getZ()), blockState); } public static void sendEmptyChunks(GeyserSession session, Vector3i position, int radius, boolean forceUpdate) { diff --git a/connector/src/main/java/org/geysermc/connector/world/chunk/ChunkPosition.java b/connector/src/main/java/org/geysermc/connector/world/chunk/ChunkPosition.java deleted file mode 100644 index c45a7c942..000000000 --- a/connector/src/main/java/org/geysermc/connector/world/chunk/ChunkPosition.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * 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.world.chunk; - -import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position; -import lombok.AllArgsConstructor; -import lombok.EqualsAndHashCode; -import lombok.Getter; -import lombok.Setter; - -@Getter -@Setter -@AllArgsConstructor -@EqualsAndHashCode -public class ChunkPosition { - - private int x; - private int z; - - public Position getBlock(int x, int y, int z) { - return new Position((this.x << 4) + x, y, (this.z << 4) + z); - } - - public Position getChunkBlock(int x, int y, int z) { - int chunkX = x & 15; - int chunkY = y & 15; - int chunkZ = z & 15; - return new Position(chunkX, chunkY, chunkZ); - } -} diff --git a/connector/src/main/java/org/geysermc/connector/world/chunk/bitarray/BitArray.java b/connector/src/main/java/org/geysermc/connector/world/chunk/bitarray/BitArray.java deleted file mode 100644 index 944cabd3f..000000000 --- a/connector/src/main/java/org/geysermc/connector/world/chunk/bitarray/BitArray.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (c) 2019-2020 GeyserMC. http://geysermc.org - * - * This code in this file is derived from NukkitX and permission has - * been granted to us allowing the usage of it in Geyser. - * - * Copyright (C) 2020 The NukkitX Project - * https://github.com/NukkitX/Nukkit - */ - -package org.geysermc.connector.world.chunk.bitarray; - -public interface BitArray { - - void set(int index, int value); - - int get(int index); - - int size(); - - int[] getWords(); - - BitArrayVersion getVersion(); - - BitArray copy(); -} \ No newline at end of file diff --git a/connector/src/main/resources/config.yml b/connector/src/main/resources/config.yml index ae0cbed8d..b1e1e2f93 100644 --- a/connector/src/main/resources/config.yml +++ b/connector/src/main/resources/config.yml @@ -60,6 +60,15 @@ allow-third-party-capes: true # The default locale if we dont have the one the client requested default-locale: en_us +# Configures if chunk caching should be enabled or not. This keeps an individual +# record of each block the client loads in. While this feature does allow for a few +# things such as block break animations to show up in creative mode and among others, +# it is HIGHLY recommended you disable this on a production environment as it can eat +# up a lot of RAM. However, when using the Bukkit version of Geyser, support for features +# or implementations this allows is automatically enabled without the additional caching as +# Geyser has direct access to the server itself. +cache-chunks: false + # bStats is a stat tracker that is entirely anonymous and tracks only basic information # about Geyser, such as how many people are online, how many servers are using Geyser, # what OS is being used, etc. You can learn more about bStats here: https://bstats.org/. From 364aac7e1a2c42a53e755cff0b43a401dc42cfbc Mon Sep 17 00:00:00 2001 From: RednedEpic Date: Wed, 29 Apr 2020 15:47:29 -0500 Subject: [PATCH 014/140] Fix block break particles not displaying in survival --- .../bedrock/BedrockInventoryTransactionTranslator.java | 2 +- .../java/entity/player/JavaPlayerActionAckTranslator.java | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockInventoryTransactionTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockInventoryTransactionTranslator.java index 905d7afbc..7344a8fe0 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockInventoryTransactionTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockInventoryTransactionTranslator.java @@ -118,7 +118,7 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator Date: Wed, 29 Apr 2020 15:56:41 -0500 Subject: [PATCH 015/140] Access world manager instead of chunk cache to fix particles on Bukkit version --- .../bedrock/BedrockInventoryTransactionTranslator.java | 2 +- .../translators/inventory/DoubleChestInventoryTranslator.java | 4 ++-- .../translators/inventory/holder/BlockInventoryHolder.java | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockInventoryTransactionTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockInventoryTransactionTranslator.java index 7344a8fe0..80b37802c 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockInventoryTransactionTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockInventoryTransactionTranslator.java @@ -116,7 +116,7 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator Date: Thu, 30 Apr 2020 00:21:02 -0500 Subject: [PATCH 016/140] Add sound handlers for block interaction These sound handlers had to be added since on Minecraft: Java Edition, these sounds are handled clientside whilst Minecraft: Bedrock Edition expects something from the server. To counter this, we emulate the sounds of that on Minecraft: Java Edition within Geyser and send it to the client. The code may seem a tadredundant, but there is not much of an alternative unfortunately. --- .../network/session/GeyserSession.java | 10 ++ .../bedrock/BedrockActionTranslator.java | 2 + ...BedrockInventoryTransactionTranslator.java | 2 + .../java/world/JavaBlockChangeTranslator.java | 33 ++++++- .../java/world/JavaPlayEffectTranslator.java | 4 +- .../sound/BucketSoundInteractionHandler.java | 72 ++++++++++++++ .../sound/DoorSoundInteractionHandler.java | 46 +++++++++ .../FlintAndSteelInteractionHandler.java | 49 +++++++++ .../sound/GrassPathInteractionHandler.java | 50 ++++++++++ .../sound/LeverSoundInteractionHandler.java | 46 +++++++++ .../translators/sound/SoundHandler.java | 66 +++++++++++++ .../sound/SoundHandlerRegistry.java | 69 +++++++++++++ .../sound/SoundInteractionHandler.java | 99 +++++++++++++++++++ connector/src/main/resources/mappings | 2 +- 14 files changed, 542 insertions(+), 8 deletions(-) create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/sound/BucketSoundInteractionHandler.java create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/sound/DoorSoundInteractionHandler.java create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/sound/FlintAndSteelInteractionHandler.java create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/sound/GrassPathInteractionHandler.java create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/sound/LeverSoundInteractionHandler.java create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/sound/SoundHandler.java create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/sound/SoundHandlerRegistry.java create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/sound/SoundInteractionHandler.java diff --git a/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java b/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java index 70574032f..e9b0e4726 100644 --- a/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java +++ b/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java @@ -118,6 +118,10 @@ public class GeyserSession implements CommandSender { private GameMode gameMode = GameMode.SURVIVAL; private final AtomicInteger pendingDimSwitches = new AtomicInteger(0); + + @Setter + private boolean sneaking; + @Setter private boolean sprinting; @@ -133,6 +137,12 @@ public class GeyserSession implements CommandSender { @Setter private String lastBlockPlacedId; + @Setter + private boolean interacting; + + @Setter + private Vector3i lastInteractionPosition; + @Setter private boolean switchingDimension = false; private boolean manyDimPackets = false; diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockActionTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockActionTranslator.java index 1c8159cfd..d7248aa36 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockActionTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockActionTranslator.java @@ -78,10 +78,12 @@ public class BedrockActionTranslator extends PacketTranslator INTERACTION_HANDLERS = new HashMap<>(); + + static { + Reflections ref = new Reflections("org.geysermc.connector.network.translators.sound"); + for (Class clazz : ref.getTypesAnnotatedWith(SoundHandler.class)) { + try { + SoundInteractionHandler interactionHandler = (SoundInteractionHandler) clazz.newInstance(); + SoundHandler annotation = clazz.getAnnotation(SoundHandler.class); + INTERACTION_HANDLERS.put(annotation, interactionHandler); + } catch (InstantiationException | IllegalAccessException ex) { + ex.printStackTrace(); + } + } + } + + private SoundHandlerRegistry() { + } + + public static void init() { + // no-op + } + + /** + * Returns a map of the interaction handlers + * + * @return a map of the interaction handlers + */ + public static Map getInteractionHandlers() { + return INTERACTION_HANDLERS; + } +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/sound/SoundInteractionHandler.java b/connector/src/main/java/org/geysermc/connector/network/translators/sound/SoundInteractionHandler.java new file mode 100644 index 000000000..364b93b8f --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/sound/SoundInteractionHandler.java @@ -0,0 +1,99 @@ +/* + * 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.sound; + +import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; +import com.nukkitx.math.vector.Vector3f; + +import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.Translators; + +import java.util.Map; + +/** + * Handler for playing sounds when right-clicking + * blocks. Due to Minecraft: Bedrock Edition + * expecting interaction sounds to be played serverside + * and Minecraft: Java Edition handling them clientside, + * this had to be made to handle scenarios like that. + */ +public interface SoundInteractionHandler { + + /** + * Handles the interaction when a player + * right-clicks a block. + * + * @param session the session interacting with the block + * @param position the position of the block + * @param identifier the identifier of the block + */ + void handleInteraction(GeyserSession session, Vector3f position, String identifier); + + /** + * Handles the block interaction when a player + * right-clicks a block. + * + * @param session the session interacting with the block + * @param position the position of the block + * @param identifier the identifier of the block + */ + static void handleBlockInteraction(GeyserSession session, Vector3f position, String identifier) { + for (Map.Entry interactionEntry : SoundHandlerRegistry.INTERACTION_HANDLERS.entrySet()) { + if (interactionEntry.getKey().blocks().length != 0) { + boolean contains = false; + for (String blockIdentifier : interactionEntry.getKey().blocks()) { + if (identifier.contains(blockIdentifier)) { + contains = true; + break; + } + } + if (!contains) continue; + } + ItemStack itemInHand = session.getInventory().getItemInHand(); + if (interactionEntry.getKey().items().length != 0) { + if (itemInHand == null || itemInHand.getId() == 0) { + continue; + } + String handIdentifier = Translators.getItemTranslator().getItem(session.getInventory().getItemInHand()).getJavaIdentifier(); + boolean contains = false; + for (String itemIdentifier : interactionEntry.getKey().items()) { + if (handIdentifier.contains(itemIdentifier)) { + contains = true; + break; + } + } + if (!contains) continue; + } + if (session.isSneaking() && !interactionEntry.getKey().ignoreSneakingWhileHolding()) { + if (session.getInventory().getItemInHand() != null && session.getInventory().getItemInHand().getId() != 0) { + continue; + } + } + interactionEntry.getValue().handleInteraction(session, position, identifier); + } + } +} diff --git a/connector/src/main/resources/mappings b/connector/src/main/resources/mappings index 4d53e24f9..e28b12703 160000 --- a/connector/src/main/resources/mappings +++ b/connector/src/main/resources/mappings @@ -1 +1 @@ -Subproject commit 4d53e24f92d20e51909ee48ac28ed17f92cb819e +Subproject commit e28b127030a81330d9fabef30efda8cbfdf4e5e3 From 0ac4789f2c00280acace07a64388aa1b47847720 Mon Sep 17 00:00:00 2001 From: RednedEpic Date: Thu, 30 Apr 2020 00:45:27 -0500 Subject: [PATCH 017/140] Don't send sound updates if block of the same type already exists in placing position This prevents the block place sound (most notably buttons or blocks that don't occupy one whole block) from spamming the client if they have their place button held down. --- .../translators/java/world/JavaBlockChangeTranslator.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaBlockChangeTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaBlockChangeTranslator.java index 600c4da47..2313a1368 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaBlockChangeTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaBlockChangeTranslator.java @@ -25,6 +25,7 @@ package org.geysermc.connector.network.translators.java.world; +import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position; import com.nukkitx.math.vector.Vector3i; import com.nukkitx.protocol.bedrock.data.SoundEvent; import com.nukkitx.protocol.bedrock.packet.LevelSoundEventPacket; @@ -42,9 +43,13 @@ public class JavaBlockChangeTranslator extends PacketTranslator Date: Thu, 30 Apr 2020 00:53:28 -0500 Subject: [PATCH 018/140] Don't show block break animation at all in creative --- .../java/entity/player/JavaPlayerActionAckTranslator.java | 3 +++ .../src/main/java/org/geysermc/connector/utils/Toolbox.java | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerActionAckTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerActionAckTranslator.java index 773dec753..d62017c62 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerActionAckTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerActionAckTranslator.java @@ -61,6 +61,9 @@ public class JavaPlayerActionAckTranslator extends PacketTranslator Date: Thu, 30 Apr 2020 07:40:45 +0100 Subject: [PATCH 019/140] Adds a message if someone runs one of the plugins directly (#457) * Added Bukkit run message * Added the rest of the plugins run messages * Renamed plugin run classes to main * Added gui message if the jar isnt run from command line * Updated help message * Changed wording for bukkit --- bootstrap/bukkit/pom.xml | 20 +++-- .../platform/bukkit/GeyserBukkitMain.java | 44 +++++++++++ bootstrap/bungeecord/pom.xml | 20 +++-- .../platform/bungeecord/GeyserBungeeMain.java | 44 +++++++++++ bootstrap/sponge/pom.xml | 20 +++-- .../platform/sponge/GeyserSpongeMain.java | 44 +++++++++++ bootstrap/velocity/pom.xml | 20 +++-- .../platform/velocity/GeyserVelocityMain.java | 44 +++++++++++ .../org/geysermc/common/main/IGeyserMain.java | 74 +++++++++++++++++++ common/src/main/resources/help.txt | 18 +++++ 10 files changed, 316 insertions(+), 32 deletions(-) create mode 100644 bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitMain.java create mode 100644 bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/GeyserBungeeMain.java create mode 100644 bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/GeyserSpongeMain.java create mode 100644 bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityMain.java create mode 100644 common/src/main/java/org/geysermc/common/main/IGeyserMain.java create mode 100644 common/src/main/resources/help.txt diff --git a/bootstrap/bukkit/pom.xml b/bootstrap/bukkit/pom.xml index fd2ecbf0d..94fab83ba 100644 --- a/bootstrap/bukkit/pom.xml +++ b/bootstrap/bukkit/pom.xml @@ -33,6 +33,18 @@ + + org.apache.maven.plugins + maven-jar-plugin + 3.2.0 + + + + org.geysermc.platform.bukkit.GeyserBukkitMain + + + + org.apache.maven.plugins maven-shade-plugin @@ -58,14 +70,6 @@ - - - *:* - - META-INF/* - - - com.google.code.gson:* diff --git a/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitMain.java b/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitMain.java new file mode 100644 index 000000000..b6da66c1b --- /dev/null +++ b/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitMain.java @@ -0,0 +1,44 @@ +/* + * 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.platform.bukkit; + +import org.geysermc.common.main.IGeyserMain; + +public class GeyserBukkitMain extends IGeyserMain { + + public static void main(String[] args) { + new GeyserBukkitMain().displayMessage(); + } + + public String getPluginType() { + return "Spigot or Paper (recommended)"; + } + + public String getPluginFolder() { + return "plugins"; + } +} diff --git a/bootstrap/bungeecord/pom.xml b/bootstrap/bungeecord/pom.xml index 0f6de3faa..b9f069165 100644 --- a/bootstrap/bungeecord/pom.xml +++ b/bootstrap/bungeecord/pom.xml @@ -33,6 +33,18 @@ + + org.apache.maven.plugins + maven-jar-plugin + 3.2.0 + + + + org.geysermc.platform.bungeecord.GeyserBungeeMain + + + + org.apache.maven.plugins maven-shade-plugin @@ -58,14 +70,6 @@ - - - *:* - - META-INF/* - - - com.google.code.gson:* diff --git a/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/GeyserBungeeMain.java b/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/GeyserBungeeMain.java new file mode 100644 index 000000000..eabbcc698 --- /dev/null +++ b/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/GeyserBungeeMain.java @@ -0,0 +1,44 @@ +/* + * 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.platform.bungeecord; + +import org.geysermc.common.main.IGeyserMain; + +public class GeyserBungeeMain extends IGeyserMain { + + public static void main(String[] args) { + new GeyserBungeeMain().displayMessage(); + } + + public String getPluginType() { + return "BungeeCord"; + } + + public String getPluginFolder() { + return "plugins"; + } +} diff --git a/bootstrap/sponge/pom.xml b/bootstrap/sponge/pom.xml index 696721d20..c9abbe3ed 100644 --- a/bootstrap/sponge/pom.xml +++ b/bootstrap/sponge/pom.xml @@ -33,6 +33,18 @@ + + org.apache.maven.plugins + maven-jar-plugin + 3.2.0 + + + + org.geysermc.platform.sponge.GeyserSpongeMain + + + + org.apache.maven.plugins maven-shade-plugin @@ -62,14 +74,6 @@ - - - *:* - - META-INF/* - - - com.google.code.gson:* diff --git a/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/GeyserSpongeMain.java b/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/GeyserSpongeMain.java new file mode 100644 index 000000000..11b9583f9 --- /dev/null +++ b/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/GeyserSpongeMain.java @@ -0,0 +1,44 @@ +/* + * 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.platform.sponge; + +import org.geysermc.common.main.IGeyserMain; + +public class GeyserSpongeMain extends IGeyserMain { + + public static void main(String[] args) { + new GeyserSpongeMain().displayMessage(); + } + + public String getPluginType() { + return "Sponge"; + } + + public String getPluginFolder() { + return "mods"; + } +} diff --git a/bootstrap/velocity/pom.xml b/bootstrap/velocity/pom.xml index 075aedc32..fb06767e0 100644 --- a/bootstrap/velocity/pom.xml +++ b/bootstrap/velocity/pom.xml @@ -33,6 +33,18 @@ + + org.apache.maven.plugins + maven-jar-plugin + 3.2.0 + + + + org.geysermc.platform.velocity.GeyserVelocityMain + + + + org.apache.maven.plugins maven-shade-plugin @@ -54,14 +66,6 @@ - - - *:* - - META-INF/* - - - com.google.code.gson:* diff --git a/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityMain.java b/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityMain.java new file mode 100644 index 000000000..73eaddf09 --- /dev/null +++ b/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityMain.java @@ -0,0 +1,44 @@ +/* + * 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.platform.velocity; + +import org.geysermc.common.main.IGeyserMain; + +public class GeyserVelocityMain extends IGeyserMain { + + public static void main(String[] args) { + new GeyserVelocityMain().displayMessage(); + } + + public String getPluginType() { + return "Velocity"; + } + + public String getPluginFolder() { + return "plugins"; + } +} diff --git a/common/src/main/java/org/geysermc/common/main/IGeyserMain.java b/common/src/main/java/org/geysermc/common/main/IGeyserMain.java new file mode 100644 index 000000000..75da4e6b9 --- /dev/null +++ b/common/src/main/java/org/geysermc/common/main/IGeyserMain.java @@ -0,0 +1,74 @@ +/* + * 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.common.main; + +import javax.swing.*; +import java.io.InputStream; +import java.util.Scanner; + +public class IGeyserMain { + + public void displayMessage() { + String message = createMessage(); + + if (System.console() == null) { + JOptionPane.showMessageDialog(null, message, "GeyserMC Plugin: " + this.getPluginType(), JOptionPane.ERROR_MESSAGE); + } + + printMessage(message); + } + + private String createMessage() { + String message = ""; + + InputStream helpStream = IGeyserMain.class.getClassLoader().getResourceAsStream("help.txt"); + Scanner help = new Scanner(helpStream).useDelimiter("\\Z"); + String line = ""; + while (help.hasNext()) { + line = help.next(); + + line = line.replace("${plugin_type}", this.getPluginType()); + line = line.replace("${plugin_folder}", this.getPluginFolder()); + + message += line + "\n"; + } + + return message; + } + + private void printMessage(String message) { + System.out.print(message); + } + + public String getPluginType() { + return "unknown"; + } + + public String getPluginFolder() { + return "unknown"; + } +} diff --git a/common/src/main/resources/help.txt b/common/src/main/resources/help.txt new file mode 100644 index 000000000..3512ed839 --- /dev/null +++ b/common/src/main/resources/help.txt @@ -0,0 +1,18 @@ + +-------------------------------------------------------------------------------- + + Oops! You attempted to run a plugin version of Geyser directly! + + This jar file is a plugin for ${plugin_type}. You can run this file as a + plugin by dropping the jar file into the "${plugin_folder}" directory. + + There is also a standalone version available that doesn't need to + be installed as a plugin, you can find it on our build server: + + http://ci.geysermc.org/ + + If you need more help, you should check out our discord: + + http://discord.geysermc.org/ + +-------------------------------------------------------------------------------- \ No newline at end of file From 2e3f32d76913eeb30f2d4fcedf5adf84ae529bed Mon Sep 17 00:00:00 2001 From: rtm516 Date: Fri, 1 May 2020 06:49:29 +0100 Subject: [PATCH 020/140] Only replace the first '.' in a message (#463) --- .../translators/bedrock/BedrockTextTranslator.java | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockTextTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockTextTranslator.java index 4dfe4c76c..8a912142e 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockTextTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockTextTranslator.java @@ -38,19 +38,7 @@ public class BedrockTextTranslator extends PacketTranslator { @Override public void translate(TextPacket packet, GeyserSession session) { - if (packet.getMessage().charAt(0) == '.') { - String message = packet.getMessage().replace(".", "/").trim(); - - if (MessageUtils.isTooLong(message, session)) { - return; - } - - ClientChatPacket chatPacket = new ClientChatPacket(message); - session.getDownstream().getSession().send(chatPacket); - return; - } - - String message = packet.getMessage().trim(); + String message = packet.getMessage().replaceAll("^\\.", "/").trim(); if (MessageUtils.isTooLong(message, session)) { return; From b07161b0a911d6ebb91dd9d5db3522ab8048f527 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+DoctorMacc@users.noreply.github.com> Date: Fri, 1 May 2020 01:51:23 -0400 Subject: [PATCH 021/140] Add block values + note block note graphics (#455) * Add note block visual without note pitch * Add rest of block value code * Add rest of block value code * Fix pistons, somewhat * Remove note block attempt * Re-add whitespace * Simplify sendPacket of BlockEventPacket * Add note block visual without note pitch * Add rest of block value code * Fix pistons, somewhat * Remove note block attempt * Re-add whitespace * Add mappings for noteblock pitch * Change noteblock pitch code * Noteblock Pitch Attempt * Commit with PistonBlockEntityTranslator * Cleanup for PR * Improve pistons Co-authored-by: blazewalker462 --- .../network/translators/Translators.java | 16 +++ .../translators/block/BlockStateValues.java | 28 +++++- .../NoteblockBlockEntityTranslator.java | 58 +++++++++++ .../java/world/JavaBlockValueTranslator.java | 99 ++++++++++++++++++- .../java/world/JavaChunkDataTranslator.java | 2 - .../geysermc/connector/utils/ChunkUtils.java | 15 +-- 6 files changed, 200 insertions(+), 18 deletions(-) create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/block/entity/NoteblockBlockEntityTranslator.java diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/Translators.java b/connector/src/main/java/org/geysermc/connector/network/translators/Translators.java index f0a3fd28c..f7c7c28aa 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/Translators.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/Translators.java @@ -32,6 +32,7 @@ import java.util.Map; import com.github.steveice10.mc.protocol.data.game.window.WindowType; import com.nukkitx.protocol.bedrock.data.ContainerType; +import it.unimi.dsi.fastutil.objects.ObjectArrayList; import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.network.translators.block.BlockTranslator; import org.geysermc.connector.network.translators.block.entity.*; @@ -61,6 +62,9 @@ public class Translators { @Getter private static Map blockEntityTranslators = new HashMap<>(); + @Getter + private static ObjectArrayList requiresBlockStateMap = new ObjectArrayList<>(); + private static final CompoundTag EMPTY_TAG = CompoundTagBuilder.builder().buildRootTag(); public static final byte[] EMPTY_LEVEL_CHUNK_DATA; @@ -129,6 +133,18 @@ public class Translators { GeyserConnector.getInstance().getLogger().error("Could not instantiate annotated block entity " + clazz.getCanonicalName() + "."); } } + + for (Class clazz : ref.getSubTypesOf(RequiresBlockState.class)) { + + GeyserConnector.getInstance().getLogger().debug("Found block entity that requires block state: " + clazz.getCanonicalName()); + + try { + requiresBlockStateMap.add((RequiresBlockState) clazz.newInstance()); + } catch (InstantiationException | IllegalAccessException e) { + GeyserConnector.getInstance().getLogger().error("Could not instantiate required block state " + clazz.getCanonicalName() + "."); + } + + } } private static void registerInventoryTranslators() { diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/block/BlockStateValues.java b/connector/src/main/java/org/geysermc/connector/network/translators/block/BlockStateValues.java index 76ee52387..87966fd1d 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/block/BlockStateValues.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/block/BlockStateValues.java @@ -41,6 +41,7 @@ public class BlockStateValues { private static final Object2IntMap BANNER_COLORS = new Object2IntOpenHashMap<>(); private static final Object2ByteMap BED_COLORS = new Object2ByteOpenHashMap<>(); + private static final Object2IntMap NOTEBLOCK_PITCHES = new Object2IntOpenHashMap<>(); private static final Object2ByteMap SKULL_VARIANTS = new Object2ByteOpenHashMap<>(); private static final Object2ByteMap SKULL_ROTATIONS = new Object2ByteOpenHashMap<>(); private static final Object2ByteMap SHULKERBOX_DIRECTIONS = new Object2ByteOpenHashMap<>(); @@ -53,24 +54,30 @@ public class BlockStateValues { public static void storeBlockStateValues(Map.Entry entry, BlockState javaBlockState) { JsonNode bannerColor = entry.getValue().get("banner_color"); if (bannerColor != null) { - BlockStateValues.BANNER_COLORS.put(javaBlockState, (byte) bannerColor.intValue()); + BANNER_COLORS.put(javaBlockState, (byte) bannerColor.intValue()); return; // There will never be a banner color and a skull variant } JsonNode bedColor = entry.getValue().get("bed_color"); if (bedColor != null) { - BlockStateValues.BED_COLORS.put(javaBlockState, (byte) bedColor.intValue()); + BED_COLORS.put(javaBlockState, (byte) bedColor.intValue()); + return; + } + + JsonNode notePitch = entry.getValue().get("note_pitch"); + if (notePitch != null) { + NOTEBLOCK_PITCHES.put(javaBlockState, entry.getValue().get("note_pitch").intValue()); return; } JsonNode skullVariation = entry.getValue().get("variation"); if(skullVariation != null) { - BlockStateValues.SKULL_VARIANTS.put(javaBlockState, (byte) skullVariation.intValue()); + SKULL_VARIANTS.put(javaBlockState, (byte) skullVariation.intValue()); } JsonNode skullRotation = entry.getValue().get("skull_rotation"); if (skullRotation != null) { - BlockStateValues.SKULL_ROTATIONS.put(javaBlockState, (byte) skullRotation.intValue()); + SKULL_ROTATIONS.put(javaBlockState, (byte) skullRotation.intValue()); } JsonNode shulkerDirection = entry.getValue().get("shulker_direction"); @@ -107,6 +114,19 @@ public class BlockStateValues { return -1; } + /** + * The note that noteblocks output when hit is part of the block state in Java but sent as a BlockEventPacket in Bedrock. + * This gives an integer pitch that Bedrock can use. + * @param state BlockState of the block + * @return note block note integer or -1 if not present + */ + public static int getNoteblockPitch(BlockState state) { + if (NOTEBLOCK_PITCHES.containsKey(state)) { + return NOTEBLOCK_PITCHES.getInt(state); + } + return -1; + } + /** * Skull variations are part of the namespaced ID in Java Edition, but part of the block entity tag in Bedrock. * This gives a byte variant ID that Bedrock can use. diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/NoteblockBlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/NoteblockBlockEntityTranslator.java new file mode 100644 index 000000000..ba9ac0de8 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/block/entity/NoteblockBlockEntityTranslator.java @@ -0,0 +1,58 @@ +/* + * 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.block.entity; + +import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position; +import com.github.steveice10.mc.protocol.data.game.world.block.BlockState; +import com.nukkitx.math.vector.Vector3i; +import com.nukkitx.protocol.bedrock.packet.BlockEventPacket; +import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.block.BlockStateValues; +import org.geysermc.connector.utils.ChunkUtils; + +/** + * Does not implement BlockEntityTranslator because it's only a block entity in Bedrock + */ +public class NoteblockBlockEntityTranslator implements RequiresBlockState { + + @Override + public boolean isBlock(BlockState blockState) { + return BlockStateValues.getNoteblockPitch(blockState) != -1; + } + + public static void translate(GeyserSession session, Position position) { + BlockState blockState = ChunkUtils.CACHED_BLOCK_ENTITIES.get(position); + BlockEventPacket blockEventPacket = new BlockEventPacket(); + blockEventPacket.setBlockPosition(Vector3i.from(position.getX(), position.getY(), position.getZ())); + blockEventPacket.setEventType(0); + blockEventPacket.setEventData(BlockStateValues.getNoteblockPitch(blockState)); + session.getUpstream().sendPacket(blockEventPacket); + + ChunkUtils.CACHED_BLOCK_ENTITIES.remove(position); + } + +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaBlockValueTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaBlockValueTranslator.java index f4a4d9efa..36ccf6556 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaBlockValueTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaBlockValueTranslator.java @@ -25,15 +25,21 @@ package org.geysermc.connector.network.translators.java.world; -import com.github.steveice10.mc.protocol.data.game.world.block.value.ChestValue; -import com.github.steveice10.mc.protocol.data.game.world.block.value.EndGatewayValue; +import com.github.steveice10.mc.protocol.data.game.world.block.value.*; import com.github.steveice10.mc.protocol.packet.ingame.server.world.ServerBlockValuePacket; import com.nukkitx.math.vector.Vector3i; +import com.nukkitx.nbt.CompoundTagBuilder; +import com.nukkitx.nbt.tag.CompoundTag; +import com.nukkitx.protocol.bedrock.packet.BlockEntityDataPacket; import com.nukkitx.protocol.bedrock.packet.BlockEventPacket; 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.entity.NoteblockBlockEntityTranslator; + +import java.util.concurrent.TimeUnit; + @Translator(packet = ServerBlockValuePacket.class) public class JavaBlockValueTranslator extends PacketTranslator { @@ -53,5 +59,94 @@ public class JavaBlockValueTranslator extends PacketTranslator + extendPiston(session, position, (progress >= 1.0f) ? 1.0f : progress + 0.5f, progress), + 20, TimeUnit.MILLISECONDS); + } + } + + /** + * Emulate a piston retracting. + * @param session GeyserSession + * @param position Block position + * @param progress Current progress of piston + * @param lastProgress Last progress of piston + */ + private void retractPiston(GeyserSession session, Vector3i position, float progress, float lastProgress) { + BlockEntityDataPacket blockEntityDataPacket = new BlockEntityDataPacket(); + blockEntityDataPacket.setBlockPosition(position); + byte state = (byte) ((progress == 0.0f && lastProgress == 0.0f) ? 0 : 3); + blockEntityDataPacket.setData(buildPistonTag(position, progress, lastProgress, state)); + session.getUpstream().sendPacket(blockEntityDataPacket); + if (lastProgress != 0.0f) { + session.getConnector().getGeneralThreadPool().schedule(() -> + retractPiston(session, position, (progress <= 0.0f) ? 0.0f : progress - 0.5f, progress), + 20, TimeUnit.MILLISECONDS); + } + } + + /** + * Build a piston tag + * @param position Piston position + * @param progress Current progress of piston + * @param lastProgress Last progress of piston + * @param state + * @return Bedrock CompoundTag of piston + */ + private CompoundTag buildPistonTag(Vector3i position, float progress, float lastProgress, byte state) { + CompoundTagBuilder builder = CompoundTag.EMPTY.toBuilder(); + builder.intTag("x", position.getX()) + .intTag("y", position.getY()) + .intTag("z", position.getZ()) + .floatTag("Progress", progress) + .floatTag("LastProgress", lastProgress) + .stringTag("id", "PistonArm") + .byteTag("NewState", state) + .byteTag("State", state); + return builder.buildRootTag(); } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaChunkDataTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaChunkDataTranslator.java index e72038c51..4117add77 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaChunkDataTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaChunkDataTranslator.java @@ -46,8 +46,6 @@ import org.geysermc.connector.network.translators.Translator; import org.geysermc.connector.utils.ChunkUtils; import org.geysermc.connector.world.chunk.ChunkSection; -import java.util.Map; - @Translator(packet = ServerChunkDataPacket.class) public class JavaChunkDataTranslator extends PacketTranslator { diff --git a/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java b/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java index d496215ac..c1ddb60a7 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java @@ -32,9 +32,7 @@ import com.github.steveice10.mc.protocol.data.game.world.block.BlockState; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.nukkitx.math.vector.Vector2i; import com.nukkitx.math.vector.Vector3i; -import com.nukkitx.protocol.bedrock.packet.LevelChunkPacket; -import com.nukkitx.protocol.bedrock.packet.NetworkChunkPublisherUpdatePacket; -import com.nukkitx.protocol.bedrock.packet.UpdateBlockPacket; +import com.nukkitx.protocol.bedrock.packet.*; import it.unimi.dsi.fastutil.objects.Object2IntMap; import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; @@ -172,13 +170,10 @@ public class ChunkUtils { // Since Java stores bed colors/skull information as part of the namespaced ID and Bedrock stores it as a tag // This is the only place I could find that interacts with the Java block state and block updates // Iterates through all block entity translators and determines if the block state needs to be saved - for (Map.Entry entry : Translators.getBlockEntityTranslators().entrySet()) { - if (entry.getValue() instanceof RequiresBlockState) { - RequiresBlockState requiresBlockState = (RequiresBlockState) entry.getValue(); - if (requiresBlockState.isBlock(blockState)) { - CACHED_BLOCK_ENTITIES.put(new Position(position.getX(), position.getY(), position.getZ()), blockState); - break; //No block will be a part of two classes - } + for (RequiresBlockState requiresBlockState : Translators.getRequiresBlockStateMap()) { + if (requiresBlockState.isBlock(blockState)) { + CACHED_BLOCK_ENTITIES.put(new Position(position.getX(), position.getY(), position.getZ()), blockState); + break; //No block will be a part of two classes } } } From ff26dcad0dead8e3a00a1e3157e99e54a4ea90ad Mon Sep 17 00:00:00 2001 From: RednedEpic Date: Sat, 2 May 2020 01:06:22 -0500 Subject: [PATCH 022/140] Start work on entity sounds, other misc implementations/fixes --- ...BedrockInventoryTransactionTranslator.java | 3 + .../java/world/JavaBlockChangeTranslator.java | 4 +- .../java/world/JavaPlayEffectTranslator.java | 10 +++ .../sound/BlockSoundInteractionHandler.java | 87 ++++++++++++++++++ .../sound/EntitySoundInteractionHandler.java | 88 +++++++++++++++++++ .../translators/sound/SoundHandler.java | 20 ++++- .../sound/SoundHandlerRegistry.java | 6 +- .../sound/SoundInteractionHandler.java | 58 ++---------- .../BucketSoundInteractionHandler.java | 7 +- .../DoorSoundInteractionHandler.java | 7 +- .../FlintAndSteelInteractionHandler.java | 7 +- .../GrassPathInteractionHandler.java | 7 +- .../sound/block/HoeInteractionHandler.java | 51 +++++++++++ .../LeverSoundInteractionHandler.java | 6 +- .../MilkCowSoundInteractionHandler.java | 55 ++++++++++++ connector/src/main/resources/mappings | 2 +- 16 files changed, 342 insertions(+), 76 deletions(-) create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/sound/BlockSoundInteractionHandler.java create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/sound/EntitySoundInteractionHandler.java rename connector/src/main/java/org/geysermc/connector/network/translators/sound/{ => block}/BucketSoundInteractionHandler.java (90%) rename connector/src/main/java/org/geysermc/connector/network/translators/sound/{ => block}/DoorSoundInteractionHandler.java (86%) rename connector/src/main/java/org/geysermc/connector/network/translators/sound/{ => block}/FlintAndSteelInteractionHandler.java (87%) rename connector/src/main/java/org/geysermc/connector/network/translators/sound/{ => block}/GrassPathInteractionHandler.java (88%) create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/sound/block/HoeInteractionHandler.java rename connector/src/main/java/org/geysermc/connector/network/translators/sound/{ => block}/LeverSoundInteractionHandler.java (86%) create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/sound/entity/MilkCowSoundInteractionHandler.java diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockInventoryTransactionTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockInventoryTransactionTranslator.java index 373132c98..602e4edaf 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockInventoryTransactionTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockInventoryTransactionTranslator.java @@ -50,6 +50,7 @@ import org.geysermc.connector.network.translators.Translator; import org.geysermc.connector.network.translators.Translators; import org.geysermc.connector.network.translators.item.ItemEntry; import org.geysermc.connector.network.translators.item.ItemTranslator; +import org.geysermc.connector.network.translators.sound.EntitySoundInteractionHandler; import org.geysermc.connector.network.translators.world.block.BlockTranslator; import org.geysermc.connector.utils.InventoryUtils; @@ -160,6 +161,8 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator { + + /** + * Handles the block interaction when a player + * right-clicks a block. + * + * @param session the session interacting with the block + * @param position the position of the block + * @param identifier the identifier of the block + */ + static void handleBlockInteraction(GeyserSession session, Vector3f position, String identifier) { + for (Map.Entry> interactionEntry : SoundHandlerRegistry.INTERACTION_HANDLERS.entrySet()) { + if (!(interactionEntry.getValue() instanceof BlockSoundInteractionHandler)) { + continue; + } + if (interactionEntry.getKey().blocks().length != 0) { + boolean contains = false; + for (String blockIdentifier : interactionEntry.getKey().blocks()) { + if (identifier.contains(blockIdentifier)) { + contains = true; + break; + } + } + if (!contains) continue; + } + ItemStack itemInHand = session.getInventory().getItemInHand(); + if (interactionEntry.getKey().items().length != 0) { + if (itemInHand == null || itemInHand.getId() == 0) { + continue; + } + String handIdentifier = Translators.getItemTranslator().getItem(session.getInventory().getItemInHand()).getJavaIdentifier(); + boolean contains = false; + for (String itemIdentifier : interactionEntry.getKey().items()) { + if (handIdentifier.contains(itemIdentifier)) { + contains = true; + break; + } + } + if (!contains) continue; + } + if (session.isSneaking() && !interactionEntry.getKey().ignoreSneakingWhileHolding()) { + if (session.getInventory().getItemInHand() != null && session.getInventory().getItemInHand().getId() != 0) { + continue; + } + } + ((BlockSoundInteractionHandler) interactionEntry.getValue()).handleInteraction(session, position, identifier); + } + } +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/sound/EntitySoundInteractionHandler.java b/connector/src/main/java/org/geysermc/connector/network/translators/sound/EntitySoundInteractionHandler.java new file mode 100644 index 000000000..3e0626908 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/sound/EntitySoundInteractionHandler.java @@ -0,0 +1,88 @@ +/* + * 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.sound; + +import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; +import com.nukkitx.math.vector.Vector3f; +import org.geysermc.connector.entity.Entity; +import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.Translators; + +import java.util.Map; + +/** + * Sound interaction handler for when an entity is right-clicked. + */ +public interface EntitySoundInteractionHandler extends SoundInteractionHandler { + + /** + * Handles the block interaction when a player + * right-clicks an entity. + * + * @param session the session interacting with the block + * @param position the position of the block + * @param entity the entity interacted with + */ + static void handleEntityInteraction(GeyserSession session, Vector3f position, Entity entity) { + for (Map.Entry> interactionEntry : SoundHandlerRegistry.INTERACTION_HANDLERS.entrySet()) { + if (!(interactionEntry.getValue() instanceof EntitySoundInteractionHandler)) { + continue; + } + if (interactionEntry.getKey().entities().length != 0) { + boolean contains = false; + for (String entityIdentifier : interactionEntry.getKey().entities()) { + if (entity.getEntityType().name().toLowerCase().contains(entityIdentifier)) { + contains = true; + break; + } + } + if (!contains) continue; + } + ItemStack itemInHand = session.getInventory().getItemInHand(); + if (interactionEntry.getKey().items().length != 0) { + if (itemInHand == null || itemInHand.getId() == 0) { + continue; + } + String handIdentifier = Translators.getItemTranslator().getItem(session.getInventory().getItemInHand()).getJavaIdentifier(); + boolean contains = false; + for (String itemIdentifier : interactionEntry.getKey().items()) { + if (handIdentifier.contains(itemIdentifier)) { + contains = true; + break; + } + } + if (!contains) continue; + } + if (session.isSneaking() && !interactionEntry.getKey().ignoreSneakingWhileHolding()) { + if (session.getInventory().getItemInHand() != null && session.getInventory().getItemInHand().getId() != 0) { + continue; + } + } + ((EntitySoundInteractionHandler) interactionEntry.getValue()).handleInteraction(session, position, entity); + } + } +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/sound/SoundHandler.java b/connector/src/main/java/org/geysermc/connector/network/translators/sound/SoundHandler.java index 0f22e2ac3..52a76aa3b 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/sound/SoundHandler.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/sound/SoundHandler.java @@ -38,8 +38,10 @@ public @interface SoundHandler { /** * The identifier(s) that the placed block must contain - * one of. - * Leave empty to ignore. + * one of. Leave empty to ignore. + * + * Only applies to interaction handlers that are an + * instance of {@link BlockSoundInteractionHandler}. * * @return the value the interacted block must contain */ @@ -47,13 +49,23 @@ public @interface SoundHandler { /** * The identifier(s) that the player's hand item - * must contain one of. - * Leave empty to ignore. + * must contain one of. Leave empty to ignore. * * @return the value the item in the player's hand must contain */ String[] items() default {}; + /** + * The identifier(s) that the interacted entity must have. + * Leave empty to ignore. + * + * Only applies to interaction handlers that are an + * instance of {@link BlockSoundInteractionHandler}. + * + * @return the value the item in the player's hand must contain + */ + String[] entities() default {}; + /** * Controls if the interaction should still be * called even if the player is sneaking while diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/sound/SoundHandlerRegistry.java b/connector/src/main/java/org/geysermc/connector/network/translators/sound/SoundHandlerRegistry.java index d5187f643..260efb416 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/sound/SoundHandlerRegistry.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/sound/SoundHandlerRegistry.java @@ -36,13 +36,13 @@ import java.util.Map; */ public class SoundHandlerRegistry { - static final Map INTERACTION_HANDLERS = new HashMap<>(); + static final Map> INTERACTION_HANDLERS = new HashMap<>(); static { Reflections ref = new Reflections("org.geysermc.connector.network.translators.sound"); for (Class clazz : ref.getTypesAnnotatedWith(SoundHandler.class)) { try { - SoundInteractionHandler interactionHandler = (SoundInteractionHandler) clazz.newInstance(); + SoundInteractionHandler interactionHandler = (SoundInteractionHandler) clazz.newInstance(); SoundHandler annotation = clazz.getAnnotation(SoundHandler.class); INTERACTION_HANDLERS.put(annotation, interactionHandler); } catch (InstantiationException | IllegalAccessException ex) { @@ -63,7 +63,7 @@ public class SoundHandlerRegistry { * * @return a map of the interaction handlers */ - public static Map getInteractionHandlers() { + public static Map> getInteractionHandlers() { return INTERACTION_HANDLERS; } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/sound/SoundInteractionHandler.java b/connector/src/main/java/org/geysermc/connector/network/translators/sound/SoundInteractionHandler.java index 364b93b8f..e68061ef4 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/sound/SoundInteractionHandler.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/sound/SoundInteractionHandler.java @@ -26,22 +26,20 @@ package org.geysermc.connector.network.translators.sound; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; import com.nukkitx.math.vector.Vector3f; import org.geysermc.connector.network.session.GeyserSession; -import org.geysermc.connector.network.translators.Translators; - -import java.util.Map; /** * Handler for playing sounds when right-clicking - * blocks. Due to Minecraft: Bedrock Edition + * various objects. Due to Minecraft: Bedrock Edition * expecting interaction sounds to be played serverside * and Minecraft: Java Edition handling them clientside, * this had to be made to handle scenarios like that. + * + * @param the value */ -public interface SoundInteractionHandler { +public interface SoundInteractionHandler { /** * Handles the interaction when a player @@ -49,51 +47,7 @@ public interface SoundInteractionHandler { * * @param session the session interacting with the block * @param position the position of the block - * @param identifier the identifier of the block + * @param value the value */ - void handleInteraction(GeyserSession session, Vector3f position, String identifier); - - /** - * Handles the block interaction when a player - * right-clicks a block. - * - * @param session the session interacting with the block - * @param position the position of the block - * @param identifier the identifier of the block - */ - static void handleBlockInteraction(GeyserSession session, Vector3f position, String identifier) { - for (Map.Entry interactionEntry : SoundHandlerRegistry.INTERACTION_HANDLERS.entrySet()) { - if (interactionEntry.getKey().blocks().length != 0) { - boolean contains = false; - for (String blockIdentifier : interactionEntry.getKey().blocks()) { - if (identifier.contains(blockIdentifier)) { - contains = true; - break; - } - } - if (!contains) continue; - } - ItemStack itemInHand = session.getInventory().getItemInHand(); - if (interactionEntry.getKey().items().length != 0) { - if (itemInHand == null || itemInHand.getId() == 0) { - continue; - } - String handIdentifier = Translators.getItemTranslator().getItem(session.getInventory().getItemInHand()).getJavaIdentifier(); - boolean contains = false; - for (String itemIdentifier : interactionEntry.getKey().items()) { - if (handIdentifier.contains(itemIdentifier)) { - contains = true; - break; - } - } - if (!contains) continue; - } - if (session.isSneaking() && !interactionEntry.getKey().ignoreSneakingWhileHolding()) { - if (session.getInventory().getItemInHand() != null && session.getInventory().getItemInHand().getId() != 0) { - continue; - } - } - interactionEntry.getValue().handleInteraction(session, position, identifier); - } - } + void handleInteraction(GeyserSession session, Vector3f position, T value); } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/sound/BucketSoundInteractionHandler.java b/connector/src/main/java/org/geysermc/connector/network/translators/sound/block/BucketSoundInteractionHandler.java similarity index 90% rename from connector/src/main/java/org/geysermc/connector/network/translators/sound/BucketSoundInteractionHandler.java rename to connector/src/main/java/org/geysermc/connector/network/translators/sound/block/BucketSoundInteractionHandler.java index 4a79d1af0..00269cc7f 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/sound/BucketSoundInteractionHandler.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/sound/block/BucketSoundInteractionHandler.java @@ -24,17 +24,18 @@ * */ -package org.geysermc.connector.network.translators.sound; +package org.geysermc.connector.network.translators.sound.block; import com.nukkitx.math.vector.Vector3f; 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.Translators; +import org.geysermc.connector.network.translators.sound.BlockSoundInteractionHandler; +import org.geysermc.connector.network.translators.sound.SoundHandler; @SoundHandler(items = "bucket") -public class BucketSoundInteractionHandler implements SoundInteractionHandler { +public class BucketSoundInteractionHandler implements BlockSoundInteractionHandler { @Override public void handleInteraction(GeyserSession session, Vector3f position, String identifier) { diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/sound/DoorSoundInteractionHandler.java b/connector/src/main/java/org/geysermc/connector/network/translators/sound/block/DoorSoundInteractionHandler.java similarity index 86% rename from connector/src/main/java/org/geysermc/connector/network/translators/sound/DoorSoundInteractionHandler.java rename to connector/src/main/java/org/geysermc/connector/network/translators/sound/block/DoorSoundInteractionHandler.java index c547292f9..3cf5955f5 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/sound/DoorSoundInteractionHandler.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/sound/block/DoorSoundInteractionHandler.java @@ -24,16 +24,17 @@ * */ -package org.geysermc.connector.network.translators.sound; +package org.geysermc.connector.network.translators.sound.block; import com.nukkitx.math.vector.Vector3f; import com.nukkitx.protocol.bedrock.data.LevelEventType; import com.nukkitx.protocol.bedrock.packet.LevelEventPacket; - import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.sound.BlockSoundInteractionHandler; +import org.geysermc.connector.network.translators.sound.SoundHandler; @SoundHandler(blocks = "door") -public class DoorSoundInteractionHandler implements SoundInteractionHandler { +public class DoorSoundInteractionHandler implements BlockSoundInteractionHandler { @Override public void handleInteraction(GeyserSession session, Vector3f position, String identifier) { diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/sound/FlintAndSteelInteractionHandler.java b/connector/src/main/java/org/geysermc/connector/network/translators/sound/block/FlintAndSteelInteractionHandler.java similarity index 87% rename from connector/src/main/java/org/geysermc/connector/network/translators/sound/FlintAndSteelInteractionHandler.java rename to connector/src/main/java/org/geysermc/connector/network/translators/sound/block/FlintAndSteelInteractionHandler.java index 2a03f4af9..b28133b34 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/sound/FlintAndSteelInteractionHandler.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/sound/block/FlintAndSteelInteractionHandler.java @@ -24,16 +24,17 @@ * */ -package org.geysermc.connector.network.translators.sound; +package org.geysermc.connector.network.translators.sound.block; import com.nukkitx.math.vector.Vector3f; 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.sound.BlockSoundInteractionHandler; +import org.geysermc.connector.network.translators.sound.SoundHandler; @SoundHandler(items = "flint_and_steel", ignoreSneakingWhileHolding = true) -public class FlintAndSteelInteractionHandler implements SoundInteractionHandler { +public class FlintAndSteelInteractionHandler implements BlockSoundInteractionHandler { @Override public void handleInteraction(GeyserSession session, Vector3f position, String identifier) { diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/sound/GrassPathInteractionHandler.java b/connector/src/main/java/org/geysermc/connector/network/translators/sound/block/GrassPathInteractionHandler.java similarity index 88% rename from connector/src/main/java/org/geysermc/connector/network/translators/sound/GrassPathInteractionHandler.java rename to connector/src/main/java/org/geysermc/connector/network/translators/sound/block/GrassPathInteractionHandler.java index 10d1df91a..e29571036 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/sound/GrassPathInteractionHandler.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/sound/block/GrassPathInteractionHandler.java @@ -24,17 +24,18 @@ * */ -package org.geysermc.connector.network.translators.sound; +package org.geysermc.connector.network.translators.sound.block; import com.nukkitx.math.vector.Vector3f; 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.sound.BlockSoundInteractionHandler; +import org.geysermc.connector.network.translators.sound.SoundHandler; import org.geysermc.connector.network.translators.world.block.BlockTranslator; @SoundHandler(blocks = "grass_path", items = "shovel", ignoreSneakingWhileHolding = true) -public class GrassPathInteractionHandler implements SoundInteractionHandler { +public class GrassPathInteractionHandler implements BlockSoundInteractionHandler { @Override public void handleInteraction(GeyserSession session, Vector3f position, String identifier) { diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/sound/block/HoeInteractionHandler.java b/connector/src/main/java/org/geysermc/connector/network/translators/sound/block/HoeInteractionHandler.java new file mode 100644 index 000000000..c9d4299b4 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/sound/block/HoeInteractionHandler.java @@ -0,0 +1,51 @@ +/* + * 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.sound.block; + +import com.nukkitx.math.vector.Vector3f; +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.sound.BlockSoundInteractionHandler; +import org.geysermc.connector.network.translators.sound.SoundHandler; +import org.geysermc.connector.network.translators.world.block.BlockTranslator; + +@SoundHandler(blocks = "farmland", items = "hoe", ignoreSneakingWhileHolding = true) +public class HoeInteractionHandler implements BlockSoundInteractionHandler { + + @Override + public void handleInteraction(GeyserSession session, Vector3f position, String identifier) { + LevelSoundEventPacket levelSoundEventPacket = new LevelSoundEventPacket(); + levelSoundEventPacket.setPosition(position); + levelSoundEventPacket.setBabySound(false); + levelSoundEventPacket.setRelativeVolumeDisabled(false); + levelSoundEventPacket.setIdentifier(":"); + levelSoundEventPacket.setSound(SoundEvent.ITEM_USE_ON); + levelSoundEventPacket.setExtraData(BlockTranslator.getBedrockBlockId(BlockTranslator.getJavaBlockState(identifier))); + session.getUpstream().sendPacket(levelSoundEventPacket); + } +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/sound/LeverSoundInteractionHandler.java b/connector/src/main/java/org/geysermc/connector/network/translators/sound/block/LeverSoundInteractionHandler.java similarity index 86% rename from connector/src/main/java/org/geysermc/connector/network/translators/sound/LeverSoundInteractionHandler.java rename to connector/src/main/java/org/geysermc/connector/network/translators/sound/block/LeverSoundInteractionHandler.java index 0c3b69c5f..0175f9277 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/sound/LeverSoundInteractionHandler.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/sound/block/LeverSoundInteractionHandler.java @@ -24,15 +24,17 @@ * */ -package org.geysermc.connector.network.translators.sound; +package org.geysermc.connector.network.translators.sound.block; import com.nukkitx.math.vector.Vector3f; import com.nukkitx.protocol.bedrock.data.LevelEventType; import com.nukkitx.protocol.bedrock.packet.LevelEventPacket; import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.sound.BlockSoundInteractionHandler; +import org.geysermc.connector.network.translators.sound.SoundHandler; @SoundHandler(blocks = "lever") -public class LeverSoundInteractionHandler implements SoundInteractionHandler { +public class LeverSoundInteractionHandler implements BlockSoundInteractionHandler { @Override public void handleInteraction(GeyserSession session, Vector3f position, String identifier) { diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/sound/entity/MilkCowSoundInteractionHandler.java b/connector/src/main/java/org/geysermc/connector/network/translators/sound/entity/MilkCowSoundInteractionHandler.java new file mode 100644 index 000000000..d4046eea7 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/sound/entity/MilkCowSoundInteractionHandler.java @@ -0,0 +1,55 @@ +/* + * 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.sound.entity; + +import com.nukkitx.math.vector.Vector3f; +import com.nukkitx.protocol.bedrock.data.SoundEvent; +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.Translators; +import org.geysermc.connector.network.translators.sound.EntitySoundInteractionHandler; +import org.geysermc.connector.network.translators.sound.SoundHandler; + +@SoundHandler(entities = "cow", items = "bucket") +public class MilkCowSoundInteractionHandler implements EntitySoundInteractionHandler { + + @Override + public void handleInteraction(GeyserSession session, Vector3f position, Entity value) { + if (!Translators.getItemTranslator().getItem(session.getInventory().getItemInHand()).getJavaIdentifier().equals("minecraft:bucket")) { + return; + } + LevelSoundEventPacket levelSoundEventPacket = new LevelSoundEventPacket(); + levelSoundEventPacket.setPosition(position); + levelSoundEventPacket.setBabySound(false); + levelSoundEventPacket.setRelativeVolumeDisabled(false); + levelSoundEventPacket.setIdentifier(":"); + levelSoundEventPacket.setSound(SoundEvent.MILK); + levelSoundEventPacket.setExtraData(-1); + session.getUpstream().sendPacket(levelSoundEventPacket); + } +} diff --git a/connector/src/main/resources/mappings b/connector/src/main/resources/mappings index e28b12703..9d801ea70 160000 --- a/connector/src/main/resources/mappings +++ b/connector/src/main/resources/mappings @@ -1 +1 @@ -Subproject commit e28b127030a81330d9fabef30efda8cbfdf4e5e3 +Subproject commit 9d801ea70edf1ae36f38b91a5c17bf2245315a68 From 99e8ca83ab1176b3cdc2f5b2bfd75ed05cd5de05 Mon Sep 17 00:00:00 2001 From: RednedEpic Date: Sat, 2 May 2020 01:29:30 -0500 Subject: [PATCH 023/140] Fix eating sounds and bow sounds --- .../bedrock/BedrockEntityEventTranslator.java | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockEntityEventTranslator.java diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockEntityEventTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockEntityEventTranslator.java new file mode 100644 index 000000000..6e8b86c46 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockEntityEventTranslator.java @@ -0,0 +1,47 @@ +/* + * 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.bedrock; + +import com.nukkitx.protocol.bedrock.packet.EntityEventPacket; +import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.PacketTranslator; +import org.geysermc.connector.network.translators.Translator; + +@Translator(packet = EntityEventPacket.class) +public class BedrockEntityEventTranslator extends PacketTranslator { + + @Override + public void translate(EntityEventPacket packet, GeyserSession session) { + switch (packet.getType()) { + // Resend the packet so we get the eating sounds + case EATING_ITEM: + session.getUpstream().sendPacket(packet); + return; + } + session.getConnector().getLogger().debug("Did not translate incoming EntityEventPacket: " + packet.toString()); + } +} From d7592d8216f8701bd017e7ff572237903773080a Mon Sep 17 00:00:00 2001 From: RednedEpic Date: Sat, 2 May 2020 01:56:08 -0500 Subject: [PATCH 024/140] Add back in explosion translator, add identifier support for sounds Some sounds require an identifier be added, otherwise they don't properly play. --- .../java/world/JavaExplosionTranslator.java | 47 +++++++++++++++++++ .../world/JavaPlayBuiltinSoundTranslator.java | 2 +- .../java/world/JavaPlayEffectTranslator.java | 2 +- .../geysermc/connector/utils/SoundUtils.java | 7 ++- connector/src/main/resources/mappings | 2 +- 5 files changed, 55 insertions(+), 5 deletions(-) create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaExplosionTranslator.java diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaExplosionTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaExplosionTranslator.java new file mode 100644 index 000000000..aabf4b645 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaExplosionTranslator.java @@ -0,0 +1,47 @@ +/* + * 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.block.ExplodedBlockRecord; +import com.github.steveice10.mc.protocol.packet.ingame.server.world.ServerExplosionPacket; +import com.nukkitx.math.vector.Vector3i; +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.world.block.BlockTranslator; +import org.geysermc.connector.utils.ChunkUtils; + +@Translator(packet = ServerExplosionPacket.class) +public class JavaExplosionTranslator extends PacketTranslator { + + @Override + public void translate(ServerExplosionPacket packet, GeyserSession session) { + for (ExplodedBlockRecord record : packet.getExploded()) { + ChunkUtils.updateBlock(session, BlockTranslator.AIR, Vector3i.from(record.getX(), record.getY(), record.getZ())); + } + } +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaPlayBuiltinSoundTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaPlayBuiltinSoundTranslator.java index e6bbd7cdc..b797eb800 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaPlayBuiltinSoundTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaPlayBuiltinSoundTranslator.java @@ -77,7 +77,7 @@ public class JavaPlayBuiltinSoundTranslator extends PacketTranslator Date: Sat, 2 May 2020 16:44:05 -0400 Subject: [PATCH 025/140] Add item frames (#415) * Initial attempt * Item frames 'work' * Blocks in the item frames work * Remove commented code * Small changes * More progress * Whittling down * Fix swords, etc * NBT data implemented * Remove unused import * Add item frame item removing; add checks for removing item frames * Add requested changes; clean up logic * Add license * Always delay item frame updates by 500 milliseconds * Switch to per-session item frame cache * Revert item translator refactoring --- .../connector/entity/ItemFrameEntity.java | 226 ++++++++++++++++++ .../connector/entity/type/EntityType.java | 7 +- .../network/session/GeyserSession.java | 8 + ...BedrockInventoryTransactionTranslator.java | 25 ++ .../BedrockItemFrameDropItemTranslator.java | 57 +++++ .../translators/block/BlockTranslator.java | 34 ++- .../network/translators/item/ItemEntry.java | 1 - .../spawn/JavaSpawnObjectTranslator.java | 8 +- .../geysermc/connector/utils/ChunkUtils.java | 17 ++ .../connector/utils/DimensionUtils.java | 1 + 10 files changed, 370 insertions(+), 14 deletions(-) create mode 100644 connector/src/main/java/org/geysermc/connector/entity/ItemFrameEntity.java create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockItemFrameDropItemTranslator.java diff --git a/connector/src/main/java/org/geysermc/connector/entity/ItemFrameEntity.java b/connector/src/main/java/org/geysermc/connector/entity/ItemFrameEntity.java new file mode 100644 index 000000000..08831a459 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/entity/ItemFrameEntity.java @@ -0,0 +1,226 @@ +/* + * 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.entity; + +import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata; +import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; +import com.github.steveice10.mc.protocol.data.game.entity.type.object.HangingDirection; +import com.nukkitx.math.vector.Vector3f; +import com.nukkitx.math.vector.Vector3i; +import com.nukkitx.nbt.CompoundTagBuilder; +import com.nukkitx.nbt.tag.CompoundTag; +import com.nukkitx.protocol.bedrock.data.ItemData; +import com.nukkitx.protocol.bedrock.packet.BlockEntityDataPacket; +import com.nukkitx.protocol.bedrock.packet.StartGamePacket; +import com.nukkitx.protocol.bedrock.packet.UpdateBlockPacket; +import org.geysermc.connector.entity.type.EntityType; +import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.Translators; +import org.geysermc.connector.network.translators.block.BlockTranslator; +import org.geysermc.connector.network.translators.item.ItemEntry; +import org.geysermc.connector.utils.Toolbox; + +import java.util.concurrent.TimeUnit; + +/** + * Item frames are an entity in Java but a block entity in Bedrock. + */ +public class ItemFrameEntity extends Entity { + + /** + * Used for getting the Bedrock block position. + * Blocks deal with integers whereas entities deal with floats. + */ + private final Vector3i bedrockPosition; + /** + * Specific block 'state' we are emulating in Bedrock. + */ + private final int bedrockRuntimeId; + /** + * Rotation of item in frame. + */ + private float rotation = 0.0f; + /** + * Cached item frame's Bedrock compound tag. + */ + private CompoundTag cachedTag; + + public ItemFrameEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation, HangingDirection direction) { + super(entityId, geyserId, entityType, position, motion, rotation); + CompoundTagBuilder builder = CompoundTag.builder(); + builder.tag(CompoundTag.builder() + .stringTag("name", "minecraft:frame") + .intTag("version", BlockTranslator.getBlockStateVersion()) + .tag(CompoundTag.builder() + .intTag("facing_direction", direction.ordinal()) + .byteTag("item_frame_map_bit", (byte) 0) + .build("states")) + .build("block")); + builder.shortTag("id", (short) 199); + bedrockRuntimeId = BlockTranslator.getItemFrame(builder.buildRootTag()); + bedrockPosition = Vector3i.from(position.getFloorX(), position.getFloorY(), position.getFloorZ()); + } + + @Override + public void spawnEntity(GeyserSession session) { + session.getItemFrameCache().put(bedrockPosition, entityId); + updateBlock(session); + valid = true; + session.getConnector().getLogger().debug("Spawned item frame at location " + bedrockPosition + " with java id " + entityId); + } + + @Override + public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { + if (entityMetadata.getId() == 7 && entityMetadata.getValue() != null) { + ItemData itemData = Translators.getItemTranslator().translateToBedrock(session, (ItemStack) entityMetadata.getValue()); + ItemEntry itemEntry = Translators.getItemTranslator().getItem((ItemStack) entityMetadata.getValue()); + CompoundTagBuilder builder = CompoundTag.builder(); + + String blockName = ""; + for (StartGamePacket.ItemEntry startGamePacketItemEntry: Toolbox.ITEMS) { + if (startGamePacketItemEntry.getId() == (short) itemEntry.getBedrockId()) { + blockName = startGamePacketItemEntry.getIdentifier(); + break; + } + } + + builder.byteTag("Count", (byte) itemData.getCount()); + if (itemData.getTag() != null) { + builder.tag(itemData.getTag().toBuilder().build("tag")); + } + builder.shortTag("Damage", itemData.getDamage()); + builder.stringTag("Name", blockName); + CompoundTagBuilder tag = getDefaultTag().toBuilder(); + tag.tag(builder.build("Item")); + tag.floatTag("ItemDropChance", 1.0f); + tag.floatTag("ItemRotation", rotation); + cachedTag = tag.buildRootTag(); + updateBlock(session); + } + else if (entityMetadata.getId() == 7 && entityMetadata.getValue() == null && cachedTag != null) { + cachedTag = getDefaultTag(); + updateBlock(session); + } + else if (entityMetadata.getId() == 8) { + rotation = ((int) entityMetadata.getValue()) * 45; + if (cachedTag == null) { + updateBlock(session); + return; + } + CompoundTagBuilder builder = cachedTag.toBuilder(); + builder.floatTag("ItemRotation", rotation); + cachedTag = builder.buildRootTag(); + updateBlock(session); + } + else { + updateBlock(session); + } + } + + @Override + public boolean despawnEntity(GeyserSession session) { + UpdateBlockPacket updateBlockPacket = new UpdateBlockPacket(); + updateBlockPacket.setDataLayer(0); + updateBlockPacket.setBlockPosition(bedrockPosition); + updateBlockPacket.setRuntimeId(0); + updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.PRIORITY); + updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NONE); + updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NEIGHBORS); + session.getUpstream().sendPacket(updateBlockPacket); + session.getItemFrameCache().remove(position, entityId); + valid = false; + return true; + } + + private CompoundTag getDefaultTag() { + CompoundTagBuilder builder = CompoundTag.builder(); + builder.intTag("x", bedrockPosition.getX()); + builder.intTag("y", bedrockPosition.getY()); + builder.intTag("z", bedrockPosition.getZ()); + builder.byteTag("isMovable", (byte) 1); + builder.stringTag("id", "ItemFrame"); + return builder.buildRootTag(); + } + + /** + * Updates the item frame as a block + * @param session GeyserSession. + */ + public void updateBlock(GeyserSession session) { + // Delay is required, or else loading in frames on chunk load is sketchy at best + session.getConnector().getGeneralThreadPool().schedule(() -> { + UpdateBlockPacket updateBlockPacket = new UpdateBlockPacket(); + updateBlockPacket.setDataLayer(0); + updateBlockPacket.setBlockPosition(bedrockPosition); + updateBlockPacket.setRuntimeId(bedrockRuntimeId); + updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.PRIORITY); + updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NONE); + updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NEIGHBORS); + session.getUpstream().sendPacket(updateBlockPacket); + + BlockEntityDataPacket blockEntityDataPacket = new BlockEntityDataPacket(); + blockEntityDataPacket.setBlockPosition(bedrockPosition); + if (cachedTag != null) { + blockEntityDataPacket.setData(cachedTag); + } else { + blockEntityDataPacket.setData(getDefaultTag()); + } + + session.getUpstream().sendPacket(blockEntityDataPacket); + }, 500, TimeUnit.MILLISECONDS); + } + + /** + * Finds the Java entity ID of an item frame from its Bedrock position. + * @param position position of item frame in Bedrock. + * @param session GeyserSession. + * @return Java entity ID or -1 if not found. + */ + public static long getItemFrameEntityId(GeyserSession session, Vector3i position) { + return session.getItemFrameCache().getOrDefault(position, -1); + } + + /** + * Determines if the position contains an item frame. + * Does largely the same thing as getItemFrameEntityId, but for speed purposes is implemented separately, + * since every block destroy packet has to check for an item frame. + * @param position position of block. + * @param session GeyserSession. + * @return true if position contains item frame, false if not. + */ + public static boolean positionContainsItemFrame(GeyserSession session, Vector3i position) { + return session.getItemFrameCache().containsKey(position); + } + + /** + * Force-remove from the position-to-ID map so it doesn't cause conflicts. + * @param session GeyserSession. + * @param position position of the removed item frame. + */ + public static void removePosition(GeyserSession session, Vector3i position) { + session.getItemFrameCache().remove(position); + } +} diff --git a/connector/src/main/java/org/geysermc/connector/entity/type/EntityType.java b/connector/src/main/java/org/geysermc/connector/entity/type/EntityType.java index 7a7e13c06..263d00416 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/type/EntityType.java +++ b/connector/src/main/java/org/geysermc/connector/entity/type/EntityType.java @@ -147,7 +147,12 @@ public enum EntityType { COD(AbstractFishEntity.class, 112, 0.25f, 0.5f), PANDA(PandaEntity.class, 113, 1.25f, 1.125f, 1.825f), FOX(FoxEntity.class, 121, 0.5f, 1.25f), - BEE(BeeEntity.class, 122, 0.6f, 0.6f); + BEE(BeeEntity.class, 122, 0.6f, 0.6f), + + /** + * Item frames are handled differently since they are a block in Bedrock. + */ + ITEM_FRAME(ItemFrameEntity.class, 0, 0, 0); private Class entityClass; private final int type; diff --git a/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java b/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java index 186576e12..1ea3a1c01 100644 --- a/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java +++ b/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java @@ -49,6 +49,8 @@ import com.nukkitx.protocol.bedrock.data.GamePublishSetting; import com.nukkitx.protocol.bedrock.data.GameRuleData; import com.nukkitx.protocol.bedrock.data.PlayerPermission; import com.nukkitx.protocol.bedrock.packet.*; +import it.unimi.dsi.fastutil.objects.Object2LongMap; +import it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap; import lombok.Getter; import lombok.Setter; import org.geysermc.common.AuthType; @@ -100,6 +102,12 @@ public class GeyserSession implements CommandSender { @Setter private TeleportCache teleportCache; + /** + * A map of Vector3i positions to Java entity IDs. + * Used for translating Bedrock block actions to Java entity actions. + */ + private final Object2LongMap itemFrameCache = new Object2LongOpenHashMap<>(); + private DataCache javaPacketCache; @Setter diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockInventoryTransactionTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockInventoryTransactionTranslator.java index 3f6eba55d..7890ead7f 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockInventoryTransactionTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockInventoryTransactionTranslator.java @@ -27,11 +27,13 @@ package org.geysermc.connector.network.translators.bedrock; import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerPlaceBlockPacket; import org.geysermc.connector.entity.Entity; +import org.geysermc.connector.entity.ItemFrameEntity; import org.geysermc.connector.inventory.Inventory; 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.network.translators.item.ItemTranslator; import org.geysermc.connector.utils.InventoryUtils; @@ -67,6 +69,20 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator { + + @Override + public void translate(ItemFrameDropItemPacket packet, GeyserSession session) { + // I hope that, when we die, God (or whoever is waiting for us) tells us exactly why this code exists + // The packet sends the Y coordinate (and just the Y coordinate) divided by two, and it's negative if it needs to be subtracted by one + int y; + if (packet.getBlockPosition().getY() > 0) { + y = packet.getBlockPosition().getY() * 2; + } else { + y = (packet.getBlockPosition().getY() * -2) - 1; + } + Vector3i position = Vector3i.from(packet.getBlockPosition().getX(), y, packet.getBlockPosition().getZ()); + ClientPlayerInteractEntityPacket interactPacket = new ClientPlayerInteractEntityPacket((int) ItemFrameEntity.getItemFrameEntityId(session, position), + InteractAction.ATTACK, Hand.MAIN_HAND); + session.getDownstream().getSession().send(interactPacket); + } + +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/block/BlockTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/block/BlockTranslator.java index 5b5d5c9cc..650a494bb 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/block/BlockTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/block/BlockTranslator.java @@ -32,16 +32,7 @@ import com.nukkitx.nbt.NbtUtils; import com.nukkitx.nbt.stream.NBTInputStream; import com.nukkitx.nbt.tag.CompoundTag; import com.nukkitx.nbt.tag.ListTag; -import it.unimi.dsi.fastutil.ints.Int2BooleanMap; -import it.unimi.dsi.fastutil.ints.Int2BooleanOpenHashMap; -import it.unimi.dsi.fastutil.ints.Int2DoubleMap; -import it.unimi.dsi.fastutil.ints.Int2DoubleOpenHashMap; -import it.unimi.dsi.fastutil.ints.Int2IntMap; -import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap; -import it.unimi.dsi.fastutil.ints.Int2ObjectMap; -import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; -import it.unimi.dsi.fastutil.ints.IntOpenHashSet; -import it.unimi.dsi.fastutil.ints.IntSet; +import it.unimi.dsi.fastutil.ints.*; import it.unimi.dsi.fastutil.objects.Object2IntMap; import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; import org.geysermc.connector.GeyserConnector; @@ -61,6 +52,7 @@ public class BlockTranslator { private static final Int2ObjectMap BEDROCK_TO_JAVA_BLOCK_MAP = new Int2ObjectOpenHashMap<>(); private static final Map JAVA_ID_BLOCK_MAP = new HashMap<>(); private static final IntSet WATERLOGGED = new IntOpenHashSet(); + private static final Object2IntMap ITEM_FRAMES = new Object2IntOpenHashMap<>(); // Bedrock carpet ID, used in LlamaEntity.java for decoration public static final int CARPET = 171; @@ -202,6 +194,16 @@ public class BlockTranslator { paletteList.addAll(blockStateMap.values()); // Add any missing mappings that could crash the client + // Loop around again to find all item frame runtime IDs + int frameRuntimeId = 0; + for (CompoundTag tag : paletteList) { + CompoundTag blockTag = tag.getCompound("block"); + if (blockTag.getString("name").equals("minecraft:frame")) { + ITEM_FRAMES.put(tag, frameRuntimeId); + } + frameRuntimeId++; + } + BLOCKS = new ListTag<>("", CompoundTag.class, paletteList); } @@ -253,6 +255,18 @@ public class BlockTranslator { return BEDROCK_TO_JAVA_BLOCK_MAP.get(bedrockId); } + public static int getItemFrame(CompoundTag tag) { + return ITEM_FRAMES.getOrDefault(tag, -1); + } + + public static boolean isItemFrame(int bedrockBlockRuntimeId) { + return ITEM_FRAMES.values().contains(bedrockBlockRuntimeId); + } + + public static int getBlockStateVersion() { + return BLOCK_STATE_VERSION; + } + public static BlockState getJavaBlockState(String javaId) { return JAVA_ID_BLOCK_MAP.get(javaId); } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemEntry.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemEntry.java index e579c20ee..e9815ba67 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemEntry.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemEntry.java @@ -36,7 +36,6 @@ public class ItemEntry { private final String javaIdentifier; private final int javaId; - private final int bedrockId; private final int bedrockData; diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/spawn/JavaSpawnObjectTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/spawn/JavaSpawnObjectTranslator.java index c3998f870..d544e24ba 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/spawn/JavaSpawnObjectTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/spawn/JavaSpawnObjectTranslator.java @@ -29,8 +29,10 @@ import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import com.github.steveice10.mc.protocol.data.game.entity.type.object.FallingBlockData; +import com.github.steveice10.mc.protocol.data.game.entity.type.object.HangingDirection; import org.geysermc.connector.entity.Entity; import org.geysermc.connector.entity.FallingBlockEntity; +import org.geysermc.connector.entity.ItemFrameEntity; import org.geysermc.connector.entity.type.EntityType; import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.PacketTranslator; @@ -46,8 +48,6 @@ public class JavaSpawnObjectTranslator extends PacketTranslator entityConstructor = entityClass.getConstructor(long.class, long.class, EntityType.class, Vector3f.class, Vector3f.class, Vector3f.class); diff --git a/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java b/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java index c1ddb60a7..1347aed48 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java @@ -39,6 +39,8 @@ import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; import lombok.Getter; import org.geysermc.connector.GeyserConnector; +import org.geysermc.connector.entity.Entity; +import org.geysermc.connector.entity.ItemFrameEntity; import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.block.entity.*; import org.geysermc.connector.network.translators.Translators; @@ -49,6 +51,7 @@ import org.geysermc.connector.world.chunk.ChunkSection; import java.util.HashMap; import java.util.Map; +import static org.geysermc.connector.network.translators.block.BlockTranslator.AIR; import static org.geysermc.connector.network.translators.block.BlockTranslator.BEDROCK_WATER_ID; public class ChunkUtils { @@ -148,6 +151,20 @@ public class ChunkUtils { } public static void updateBlock(GeyserSession session, BlockState blockState, Vector3i position) { + + // Checks for item frames so they aren't tripped up and removed + if (ItemFrameEntity.positionContainsItemFrame(session, position) && blockState.equals(AIR)) { + ((ItemFrameEntity) session.getEntityCache().getEntityByJavaId(ItemFrameEntity.getItemFrameEntityId(session, position))).updateBlock(session); + return; + } else if (ItemFrameEntity.positionContainsItemFrame(session, position)) { + Entity entity = session.getEntityCache().getEntityByJavaId(ItemFrameEntity.getItemFrameEntityId(session, position)); + if (entity != null) { + session.getEntityCache().removeEntity(entity, false); + } else { + ItemFrameEntity.removePosition(session, position); + } + } + int blockId = BlockTranslator.getBedrockBlockId(blockState); UpdateBlockPacket updateBlockPacket = new UpdateBlockPacket(); diff --git a/connector/src/main/java/org/geysermc/connector/utils/DimensionUtils.java b/connector/src/main/java/org/geysermc/connector/utils/DimensionUtils.java index 9d874f13d..6dd182a79 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/DimensionUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/DimensionUtils.java @@ -38,6 +38,7 @@ public class DimensionUtils { return; session.getEntityCache().removeAllEntities(); + session.getItemFrameCache().clear(); if (session.getPendingDimSwitches().getAndIncrement() > 0) { ChunkUtils.sendEmptyChunks(session, player.getPosition().toInt(), 3, true); } From 7f7d89e517d7525e72bb30eb6f2935247cb826fa Mon Sep 17 00:00:00 2001 From: RednedEpic Date: Sun, 3 May 2020 01:48:38 -0500 Subject: [PATCH 026/140] Add tnt sounds/particles and support for level event sounds --- .../geysermc/connector/entity/TNTEntity.java | 65 +++++++++++++++++++ .../connector/entity/type/EntityType.java | 2 +- .../java/world/JavaExplosionTranslator.java | 22 ++++++- .../world/JavaPlayBuiltinSoundTranslator.java | 10 +++ .../geysermc/connector/utils/SoundUtils.java | 7 +- connector/src/main/resources/mappings | 2 +- 6 files changed, 103 insertions(+), 5 deletions(-) create mode 100644 connector/src/main/java/org/geysermc/connector/entity/TNTEntity.java diff --git a/connector/src/main/java/org/geysermc/connector/entity/TNTEntity.java b/connector/src/main/java/org/geysermc/connector/entity/TNTEntity.java new file mode 100644 index 000000000..629c9e51c --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/entity/TNTEntity.java @@ -0,0 +1,65 @@ +/* + * 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.entity; + +import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata; +import com.nukkitx.math.vector.Vector3f; +import com.nukkitx.protocol.bedrock.data.EntityData; +import com.nukkitx.protocol.bedrock.data.EntityFlag; +import org.geysermc.connector.entity.type.EntityType; +import org.geysermc.connector.network.session.GeyserSession; + +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; + +public class TNTEntity extends Entity { + + private int currentTick; + + public TNTEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { + super(entityId, geyserId, entityType, position, motion, rotation); + } + + @Override + public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { + if (entityMetadata.getId() == 7) { + currentTick = (int) entityMetadata.getValue(); + metadata.getFlags().setFlag(EntityFlag.IGNITED, true); + metadata.put(EntityData.FUSE_LENGTH, currentTick); + ScheduledFuture future = session.getConnector().getGeneralThreadPool().scheduleAtFixedRate(() -> { + if (currentTick % 5 == 0) { + metadata.put(EntityData.FUSE_LENGTH, currentTick); + } + currentTick--; + super.updateBedrockMetadata(entityMetadata, session); + }, 50, 50, TimeUnit.MILLISECONDS); // 5 ticks + session.getConnector().getGeneralThreadPool().schedule(() -> future.cancel(true), (int) entityMetadata.getValue() / 20, TimeUnit.SECONDS); + } + + super.updateBedrockMetadata(entityMetadata, session); + } +} diff --git a/connector/src/main/java/org/geysermc/connector/entity/type/EntityType.java b/connector/src/main/java/org/geysermc/connector/entity/type/EntityType.java index 263d00416..5f77fdc41 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/type/EntityType.java +++ b/connector/src/main/java/org/geysermc/connector/entity/type/EntityType.java @@ -98,7 +98,7 @@ public enum EntityType { TRIPOD_CAMERA(Entity.class, 62, 0f), PLAYER(PlayerEntity.class, 63, 1.8f, 0.6f, 0.6f, 1.62f), ITEM(ItemEntity.class, 64, 0.25f, 0.25f), - TNT(Entity.class, 65, 0.98f, 0.98f), + TNT(TNTEntity.class, 65, 0.98f, 0.98f), FALLING_BLOCK(FallingBlockEntity.class, 66, 0.98f, 0.98f), MOVING_BLOCK(Entity.class, 67, 0f), EXPERIENCE_BOTTLE(ThrowableEntity.class, 68, 0.25f, 0.25f), diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaExplosionTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaExplosionTranslator.java index aabf4b645..e6fa2ee96 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaExplosionTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaExplosionTranslator.java @@ -28,7 +28,12 @@ package org.geysermc.connector.network.translators.java.world; import com.github.steveice10.mc.protocol.data.game.world.block.ExplodedBlockRecord; import com.github.steveice10.mc.protocol.packet.ingame.server.world.ServerExplosionPacket; +import com.nukkitx.math.vector.Vector3f; import com.nukkitx.math.vector.Vector3i; +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.network.session.GeyserSession; import org.geysermc.connector.network.translators.PacketTranslator; import org.geysermc.connector.network.translators.Translator; @@ -41,7 +46,22 @@ public class JavaExplosionTranslator extends PacketTranslator Date: Sun, 3 May 2020 21:26:14 +0100 Subject: [PATCH 027/140] Remove duplicate commands by name (#474) * Remove duplicate commands by name * Removed comment --- .../translators/java/JavaServerDeclareCommandsTranslator.java | 1 + 1 file changed, 1 insertion(+) diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaServerDeclareCommandsTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaServerDeclareCommandsTranslator.java index d57b89487..0e329669b 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaServerDeclareCommandsTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaServerDeclareCommandsTranslator.java @@ -59,6 +59,7 @@ public class JavaServerDeclareCommandsTranslator extends PacketTranslator= 1) { From 9c6ac1b41c333766544c67a7c7ff09e14bdc60f6 Mon Sep 17 00:00:00 2001 From: rtm516 Date: Sun, 3 May 2020 21:30:20 +0100 Subject: [PATCH 028/140] Auto load floodgate key if floodgate installed and set authtype (#454) * Added floodgate key auto loading for Bukkit * Added floodgate key auto loading for Bungee * Added floodgate key auto loading for Velocity and fixed key location * Moved key loading to common --- .../bukkit/GeyserBukkitConfiguration.java | 12 ++++- .../platform/bukkit/GeyserBukkitPlugin.java | 3 ++ .../bungeecord/GeyserBungeeConfiguration.java | 12 ++++- .../bungeecord/GeyserBungeePlugin.java | 3 ++ .../velocity/GeyserVelocityConfiguration.java | 14 ++++- .../velocity/GeyserVelocityPlugin.java | 10 ++-- .../geysermc/common/FloodgateKeyLoader.java | 52 +++++++++++++++++++ 7 files changed, 99 insertions(+), 7 deletions(-) create mode 100644 common/src/main/java/org/geysermc/common/FloodgateKeyLoader.java diff --git a/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitConfiguration.java b/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitConfiguration.java index 5b8842b4e..55eb137bb 100644 --- a/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitConfiguration.java +++ b/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitConfiguration.java @@ -25,7 +25,10 @@ package org.geysermc.platform.bukkit; +import org.bukkit.Bukkit; import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.plugin.Plugin; +import org.geysermc.common.FloodgateKeyLoader; import org.geysermc.common.IGeyserConfiguration; import java.io.File; @@ -45,6 +48,8 @@ public class GeyserBukkitConfiguration implements IGeyserConfiguration { private Map userAuthInfo = new HashMap<>(); + private Path floodgateKey; + public GeyserBukkitConfiguration(File dataFolder, FileConfiguration config) { this.dataFolder = dataFolder; this.config = config; @@ -61,6 +66,11 @@ public class GeyserBukkitConfiguration implements IGeyserConfiguration { } } + public void loadFloodgate(GeyserBukkitPlugin plugin) { + Plugin floodgate = Bukkit.getPluginManager().getPlugin("floodgate-bukkit"); + floodgateKey = FloodgateKeyLoader.getKey(plugin.getGeyserLogger(), this, Paths.get(dataFolder.toString(), config.getString("floodgate-key-file", "public-key.pem")), floodgate, floodgate != null ? floodgate.getDataFolder().toPath() : null); + } + @Override public IBedrockConfiguration getBedrock() { return bedrockConfig; @@ -108,7 +118,7 @@ public class GeyserBukkitConfiguration implements IGeyserConfiguration { @Override public Path getFloodgateKeyFile() { - return Paths.get(dataFolder.toString(), config.getString("floodgate-key-file", "public-key.pem")); + return floodgateKey; } @Override diff --git a/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitPlugin.java b/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitPlugin.java index fa58f66c5..c4655bef9 100644 --- a/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitPlugin.java +++ b/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitPlugin.java @@ -64,6 +64,9 @@ public class GeyserBukkitPlugin extends JavaPlugin implements IGeyserBootstrap { saveConfig(); this.geyserLogger = new GeyserBukkitLogger(getLogger(), geyserConfig.isDebugMode()); + + geyserConfig.loadFloodgate(this); + this.connector = GeyserConnector.start(PlatformType.BUKKIT, this); this.geyserCommandManager = new GeyserBukkitCommandManager(this, connector); diff --git a/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/GeyserBungeeConfiguration.java b/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/GeyserBungeeConfiguration.java index e0f6a6eff..c94d27239 100644 --- a/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/GeyserBungeeConfiguration.java +++ b/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/GeyserBungeeConfiguration.java @@ -25,8 +25,9 @@ package org.geysermc.platform.bungeecord; +import net.md_5.bungee.api.plugin.Plugin; import net.md_5.bungee.config.Configuration; - +import org.geysermc.common.FloodgateKeyLoader; import org.geysermc.common.IGeyserConfiguration; import java.io.File; @@ -46,6 +47,8 @@ public class GeyserBungeeConfiguration implements IGeyserConfiguration { private Map userAuthInfo = new HashMap<>(); + private Path floodgateKey; + public GeyserBungeeConfiguration(File dataFolder, Configuration config) { this.dataFolder = dataFolder; this.config = config; @@ -62,6 +65,11 @@ public class GeyserBungeeConfiguration implements IGeyserConfiguration { } } + public void loadFloodgate(GeyserBungeePlugin plugin) { + Plugin floodgate = plugin.getProxy().getPluginManager().getPlugin("floodgate-bungee"); + floodgateKey = FloodgateKeyLoader.getKey(plugin.getGeyserLogger(), this, Paths.get(dataFolder.toString(), config.getString("floodgate-key-file", "public-key.pem")), floodgate, floodgate != null ? floodgate.getDataFolder().toPath() : null); + } + @Override public BungeeBedrockConfiguration getBedrock() { return bedrockConfig; @@ -109,7 +117,7 @@ public class GeyserBungeeConfiguration implements IGeyserConfiguration { @Override public Path getFloodgateKeyFile() { - return Paths.get(dataFolder.toString(), config.getString("floodgate-key-file", "public-key.pem")); + return floodgateKey; } @Override diff --git a/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/GeyserBungeePlugin.java b/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/GeyserBungeePlugin.java index 4c5953900..4c2e25800 100644 --- a/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/GeyserBungeePlugin.java +++ b/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/GeyserBungeePlugin.java @@ -116,6 +116,9 @@ public class GeyserBungeePlugin extends Plugin implements IGeyserBootstrap { } this.geyserLogger = new GeyserBungeeLogger(getLogger(), geyserConfig.isDebugMode()); + + geyserConfig.loadFloodgate(this); + this.connector = GeyserConnector.start(PlatformType.BUNGEECORD, this); this.geyserCommandManager = new GeyserBungeeCommandManager(connector); diff --git a/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityConfiguration.java b/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityConfiguration.java index 03f7cbeeb..33fd50fef 100644 --- a/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityConfiguration.java +++ b/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityConfiguration.java @@ -27,13 +27,18 @@ package org.geysermc.platform.velocity; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; +import com.velocitypowered.api.plugin.PluginContainer; +import com.velocitypowered.api.proxy.ProxyServer; import lombok.Getter; import lombok.Setter; +import org.geysermc.common.FloodgateKeyLoader; import org.geysermc.common.IGeyserConfiguration; +import java.io.File; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Map; +import java.util.Optional; @JsonIgnoreProperties(ignoreUnknown = true) @Getter @@ -67,9 +72,16 @@ public class GeyserVelocityConfiguration implements IGeyserConfiguration { private MetricsInfo metrics; + private Path floodgateKey; + + public void loadFloodgate(GeyserVelocityPlugin plugin, ProxyServer proxyServer, File dataFolder) { + Optional floodgate = proxyServer.getPluginManager().getPlugin("floodgate"); + floodgateKey = FloodgateKeyLoader.getKey(plugin.getGeyserLogger(), this, Paths.get(dataFolder.toString(), floodgateKeyFile.isEmpty() ? floodgateKeyFile : "public-key.pem"), floodgate.get(), Paths.get("plugins/floodgate/")); + } + @Override public Path getFloodgateKeyFile() { - return Paths.get(floodgateKeyFile); + return floodgateKey; } @Getter diff --git a/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityPlugin.java b/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityPlugin.java index 38378f01c..59647e1d3 100644 --- a/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityPlugin.java +++ b/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityPlugin.java @@ -54,7 +54,7 @@ public class GeyserVelocityPlugin implements IGeyserBootstrap { private Logger logger; @Inject - private ProxyServer server; + private ProxyServer proxyServer; @Inject private CommandManager commandManager; @@ -67,8 +67,9 @@ public class GeyserVelocityPlugin implements IGeyserBootstrap { @Override public void onEnable() { + File configDir = new File("plugins/" + GeyserConnector.NAME + "-Velocity/"); + try { - File configDir = new File("plugins/" + GeyserConnector.NAME + "-Velocity/"); if (!configDir.exists()) configDir.mkdir(); File configFile = FileUtils.fileOrCopiedFromResource(new File(configDir, "config.yml"), "config.yml", (x) -> x.replaceAll("generateduuid", UUID.randomUUID().toString())); @@ -78,7 +79,7 @@ public class GeyserVelocityPlugin implements IGeyserBootstrap { ex.printStackTrace(); } - InetSocketAddress javaAddr = server.getBoundAddress(); + InetSocketAddress javaAddr = proxyServer.getBoundAddress(); // Don't change the ip if its listening on all interfaces // By default this should be 127.0.0.1 but may need to be changed in some circumstances @@ -89,6 +90,9 @@ public class GeyserVelocityPlugin implements IGeyserBootstrap { geyserConfig.getRemote().setPort(javaAddr.getPort()); this.geyserLogger = new GeyserVelocityLogger(logger, geyserConfig.isDebugMode()); + + geyserConfig.loadFloodgate(this, proxyServer, configDir); + this.connector = GeyserConnector.start(PlatformType.VELOCITY, this); this.geyserCommandManager = new GeyserVelocityCommandManager(connector); diff --git a/common/src/main/java/org/geysermc/common/FloodgateKeyLoader.java b/common/src/main/java/org/geysermc/common/FloodgateKeyLoader.java new file mode 100644 index 000000000..9eb3275f5 --- /dev/null +++ b/common/src/main/java/org/geysermc/common/FloodgateKeyLoader.java @@ -0,0 +1,52 @@ +/* + * 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.common; + +import org.geysermc.common.logger.IGeyserLogger; + +import java.nio.file.Files; +import java.nio.file.Path; + +public class FloodgateKeyLoader { + public static Path getKey(IGeyserLogger logger, IGeyserConfiguration config, Path floodgateKey, Object floodgate, Path floodgateFolder) { + if (!Files.exists(floodgateKey) && config.getRemote().getAuthType().equals("floodgate")) { + if (floodgate != null) { + Path autoKey = floodgateFolder.resolve("public-key.pem"); + if (Files.exists(autoKey)) { + logger.info("Auto-loaded floodgate key"); + floodgateKey = autoKey; + } else { + logger.error("Auth-type set to floodgate and the public key is missing!"); + } + } else { + logger.error("Auth-type set to floodgate but floodgate is not installed!"); + } + } + + return floodgateKey; + } +} From 1aca44ec7fab8e15bc6a00131be1d597f51b36c6 Mon Sep 17 00:00:00 2001 From: RednedEpic Date: Sun, 3 May 2020 15:56:46 -0500 Subject: [PATCH 029/140] Fix playsounds --- .../JavaPlayerPlaySoundTranslator.java | 41 ++++++++++--------- .../geysermc/connector/utils/SoundUtils.java | 4 -- 2 files changed, 21 insertions(+), 24 deletions(-) rename connector/src/main/java/org/geysermc/connector/network/translators/java/{entity/player => world}/JavaPlayerPlaySoundTranslator.java (63%) diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerPlaySoundTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaPlayerPlaySoundTranslator.java similarity index 63% rename from connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerPlaySoundTranslator.java rename to connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaPlayerPlaySoundTranslator.java index 2bc3a794a..effb71c5f 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerPlaySoundTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaPlayerPlaySoundTranslator.java @@ -1,29 +1,30 @@ /* * 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: + * 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 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. + * 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 * - * @author GeyserMC - * @link https://github.com/GeyserMC/Geyser */ -package org.geysermc.connector.network.translators.java.entity.player; +package org.geysermc.connector.network.translators.java.world; import com.github.steveice10.mc.protocol.data.game.world.sound.BuiltinSound; import com.github.steveice10.mc.protocol.data.game.world.sound.CustomSound; @@ -50,7 +51,7 @@ public class JavaPlayerPlaySoundTranslator extends PacketTranslator " + soundMapping + (soundMapping == null ? "[not found]" : "") @@ -67,7 +68,7 @@ public class JavaPlayerPlaySoundTranslator extends PacketTranslator Date: Sun, 3 May 2020 23:56:07 -0500 Subject: [PATCH 030/140] Map most all missing sounds --- .../world/JavaPlayBuiltinSoundTranslator.java | 12 +++-- .../java/world/JavaPlayEffectTranslator.java | 20 ++++++-- .../block/ComparatorSoundInteractHandler.java | 48 +++++++++++++++++++ .../block/DoorSoundInteractionHandler.java | 2 +- .../block/LeverSoundInteractionHandler.java | 2 +- connector/src/main/resources/mappings | 2 +- 6 files changed, 75 insertions(+), 11 deletions(-) create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/sound/block/ComparatorSoundInteractHandler.java diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaPlayBuiltinSoundTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaPlayBuiltinSoundTranslator.java index 2e3d3d5f3..aa4ade4ad 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaPlayBuiltinSoundTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaPlayBuiltinSoundTranslator.java @@ -34,6 +34,7 @@ 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.world.block.BlockTranslator; import org.geysermc.connector.utils.SoundUtils; @Translator(packet = ServerPlayBuiltinSoundPacket.class) @@ -72,22 +73,23 @@ public class JavaPlayBuiltinSoundTranslator extends PacketTranslator Date: Mon, 4 May 2020 00:29:22 -0500 Subject: [PATCH 031/140] Update mappings --- connector/src/main/resources/mappings | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/connector/src/main/resources/mappings b/connector/src/main/resources/mappings index 311b83fb8..ddb62693f 160000 --- a/connector/src/main/resources/mappings +++ b/connector/src/main/resources/mappings @@ -1 +1 @@ -Subproject commit 311b83fb85897531d5a803afc27f666bb5626b97 +Subproject commit ddb62693f878a99f106a0d6ea16a92ec7c4c7cd0 From e798ca9d045f3eeb4f8b1c89db5a45c8c114f6d6 Mon Sep 17 00:00:00 2001 From: RednedEpic Date: Mon, 4 May 2020 00:52:18 -0500 Subject: [PATCH 032/140] Remove sounds and block particles from TODO on README --- README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.md b/README.md index f11b9bfb3..713e77b72 100644 --- a/README.md +++ b/README.md @@ -34,8 +34,6 @@ Take a look [here](https://github.com/GeyserMC/Geyser/wiki#Setup) for how to set - [ ] Cartography Table - [ ] Stonecutter - [ ] Villager Trading -- Sounds -- Block Particles - Some Entity Flags ## Compiling From d0a2f6ac2782c0f6f1fc2e3bceb73081349d867a Mon Sep 17 00:00:00 2001 From: ForceUpdate1 Date: Mon, 4 May 2020 08:06:08 +0200 Subject: [PATCH 033/140] Fix movement issues #466 (#473) --- .../geysermc/connector/network/session/GeyserSession.java | 7 ++----- .../connector/network/session/cache/TeleportCache.java | 3 ++- .../translators/bedrock/BedrockMovePlayerTranslator.java | 5 +++-- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java b/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java index 623e385da..51cc09239 100644 --- a/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java +++ b/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java @@ -40,10 +40,7 @@ import com.github.steveice10.packetlib.packet.Packet; import com.github.steveice10.packetlib.tcp.TcpSessionFactory; import com.nukkitx.math.GenericMath; import com.nukkitx.math.TrigMath; -import com.nukkitx.math.vector.Vector2f; -import com.nukkitx.math.vector.Vector2i; -import com.nukkitx.math.vector.Vector3f; -import com.nukkitx.math.vector.Vector3i; +import com.nukkitx.math.vector.*; import com.nukkitx.protocol.bedrock.BedrockServerSession; import com.nukkitx.protocol.bedrock.data.ContainerId; import com.nukkitx.protocol.bedrock.data.GamePublishSetting; @@ -474,7 +471,7 @@ public class GeyserSession implements CommandSender { upstream.sendPacket(startGamePacket); } - public boolean confirmTeleport(Vector3f position) { + public boolean confirmTeleport(Vector3d position) { if (teleportCache != null) { if (!teleportCache.canConfirm(position)) { GeyserConnector.getInstance().getLogger().debug("Unconfirmed Teleport " + teleportCache.getTeleportConfirmId() diff --git a/connector/src/main/java/org/geysermc/connector/network/session/cache/TeleportCache.java b/connector/src/main/java/org/geysermc/connector/network/session/cache/TeleportCache.java index 55b7e6faf..475630dbb 100644 --- a/connector/src/main/java/org/geysermc/connector/network/session/cache/TeleportCache.java +++ b/connector/src/main/java/org/geysermc/connector/network/session/cache/TeleportCache.java @@ -25,6 +25,7 @@ package org.geysermc.connector.network.session.cache; +import com.nukkitx.math.vector.Vector3d; import com.nukkitx.math.vector.Vector3f; import lombok.AllArgsConstructor; import lombok.Data; @@ -39,7 +40,7 @@ public class TeleportCache { private double x, y, z; private int teleportConfirmId; - public boolean canConfirm(Vector3f position) { + public boolean canConfirm(Vector3d position) { return (Math.abs(this.x - position.getX()) < ERROR && Math.abs(this.y - position.getY()) < ERROR_Y && Math.abs(this.z - position.getZ()) < ERROR); diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockMovePlayerTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockMovePlayerTranslator.java index be1587466..49b0b7fc5 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockMovePlayerTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockMovePlayerTranslator.java @@ -25,6 +25,7 @@ package org.geysermc.connector.network.translators.bedrock; +import com.nukkitx.math.vector.Vector3d; import org.geysermc.common.ChatColor; import org.geysermc.connector.entity.Entity; import org.geysermc.connector.entity.PlayerEntity; @@ -63,7 +64,7 @@ public class BedrockMovePlayerTranslator extends PacketTranslator Date: Mon, 4 May 2020 10:42:48 -0400 Subject: [PATCH 034/140] Add friendly display names for DeviceOS (#477) --- .../org/geysermc/floodgate/util/DeviceOS.java | 42 ++++++++++++------- 1 file changed, 28 insertions(+), 14 deletions(-) diff --git a/common/src/main/java/org/geysermc/floodgate/util/DeviceOS.java b/common/src/main/java/org/geysermc/floodgate/util/DeviceOS.java index 0705d1694..bd8e40027 100644 --- a/common/src/main/java/org/geysermc/floodgate/util/DeviceOS.java +++ b/common/src/main/java/org/geysermc/floodgate/util/DeviceOS.java @@ -30,24 +30,38 @@ import com.fasterxml.jackson.annotation.JsonEnumDefaultValue; public enum DeviceOS { @JsonEnumDefaultValue - UNKNOWN, - ANDROID, - IOS, - OSX, - FIREOS, - GEARVR, - HOLOLENS, - WIN10, - WIN32, - DEDICATED, - ORBIS, - NX, - SWITCH, - XBOX_ONE; + UNKNOWN("Unknown"), + ANDROID("Android"), + IOS("iOS"), + OSX("macOS"), + FIREOS("FireOS"), + GEARVR("Gear VR"), + HOLOLENS("Hololens"), + WIN10("Windows 10"), + WIN32("Windows"), + DEDICATED("Dedicated"), + ORBIS("PS4"), + NX("Switch"), + SWITCH("Switch"), + XBOX_ONE("Xbox One"); private static final DeviceOS[] VALUES = values(); + private final String displayName; + + DeviceOS(final String displayName) { + this.displayName = displayName; + } + public static DeviceOS getById(int id) { return id < VALUES.length ? VALUES[id] : VALUES[0]; } + + /** + * @return friendly display name of platform. + */ + @Override + public String toString() { + return displayName; + } } \ No newline at end of file From 3c7e89ba3f0033013368a80f3a953d62e88c5cef Mon Sep 17 00:00:00 2001 From: RednedEpic Date: Mon, 4 May 2020 13:00:32 -0500 Subject: [PATCH 035/140] Use Java Edition username when getting player in bukkit world manager --- .../platform/bukkit/world/GeyserBukkitWorldManager.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/world/GeyserBukkitWorldManager.java b/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/world/GeyserBukkitWorldManager.java index 6172b8314..07fc31361 100644 --- a/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/world/GeyserBukkitWorldManager.java +++ b/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/world/GeyserBukkitWorldManager.java @@ -37,6 +37,9 @@ public class GeyserBukkitWorldManager extends WorldManager { @Override public BlockState getBlockAt(GeyserSession session, int x, int y, int z) { - return BlockTranslator.getJavaIdBlockMap().get(Bukkit.getPlayer(session.getName()).getWorld().getBlockAt(x, y, z).getBlockData().getAsString()); + if (session.getPlayerEntity() == null) { + return BlockTranslator.AIR; + } + return BlockTranslator.getJavaIdBlockMap().get(Bukkit.getPlayer(session.getPlayerEntity().getUsername()).getWorld().getBlockAt(x, y, z).getBlockData().getAsString()); } } From 129e10c9205c95fbe3e10da9426a78013c0c9b14 Mon Sep 17 00:00:00 2001 From: rtm516 Date: Mon, 4 May 2020 20:17:25 +0100 Subject: [PATCH 036/140] Added automatic git version infomation to startup (#327) * Added automatic git version infomation to startup * Moved to compile time replacement * Cleaned up old functions * Removed redundant variable * Added project version to version string --- connector/pom.xml | 79 +++++++++++++++++++ .../geysermc/connector/GeyserConnector.java | 4 +- 2 files changed, 80 insertions(+), 3 deletions(-) diff --git a/connector/pom.xml b/connector/pom.xml index c9740ea44..229761adf 100644 --- a/connector/pom.xml +++ b/connector/pom.xml @@ -164,4 +164,83 @@ compile + + + + + pl.project13.maven + git-commit-id-plugin + 4.0.0 + + + get-the-git-infos + + revision + + + + + true + ${project.build.outputDirectory}/git.properties + properties + false + false + false + true + false + + git.user.* + + flat + + true + + + + + com.google.code.maven-replacer-plugin + replacer + 1.5.3 + + + add-version + process-sources + + replace + + + + ${project.basedir}/src/main/java/org/geysermc/connector/GeyserConnector.java + + + + VERSION = ".*" + VERSION = "${project.version} (git-${git.branch}-${git.commit.id.abbrev})" + + + + + + + remove-version + process-classes + + replace + + + + ${project.basedir}/src/main/java/org/geysermc/connector/GeyserConnector.java + + + + VERSION = ".*" + VERSION = "DEV" + + + + + + + + diff --git a/connector/src/main/java/org/geysermc/connector/GeyserConnector.java b/connector/src/main/java/org/geysermc/connector/GeyserConnector.java index 6c9e8c7db..729952939 100644 --- a/connector/src/main/java/org/geysermc/connector/GeyserConnector.java +++ b/connector/src/main/java/org/geysermc/connector/GeyserConnector.java @@ -28,9 +28,7 @@ package org.geysermc.connector; import com.nukkitx.protocol.bedrock.BedrockPacketCodec; import com.nukkitx.protocol.bedrock.BedrockServer; import com.nukkitx.protocol.bedrock.v390.Bedrock_v390; - import lombok.Getter; - import org.geysermc.common.AuthType; import org.geysermc.common.PlatformType; import org.geysermc.connector.bootstrap.GeyserBootstrap; @@ -59,7 +57,7 @@ public class GeyserConnector { public static final BedrockPacketCodec BEDROCK_PACKET_CODEC = Bedrock_v390.V390_CODEC; public static final String NAME = "Geyser"; - public static final String VERSION = "1.0-SNAPSHOT"; + public static final String VERSION = "DEV"; // A fallback for running in IDEs private final Map players = new HashMap<>(); From fcf1949b28ab023e29c8f5714657e3e8d6a2eb86 Mon Sep 17 00:00:00 2001 From: rtm516 Date: Tue, 5 May 2020 01:39:44 +0100 Subject: [PATCH 037/140] Fix trapped chests not displaying (#481) --- .../java/org/geysermc/connector/utils/BlockEntityUtils.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/connector/src/main/java/org/geysermc/connector/utils/BlockEntityUtils.java b/connector/src/main/java/org/geysermc/connector/utils/BlockEntityUtils.java index 2c04c205b..f79ffd5f7 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/BlockEntityUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/BlockEntityUtils.java @@ -17,6 +17,9 @@ public class BlockEntityUtils { if (id.contains("piston_head")) return "PistonArm"; + if (id.contains("trapped_chest")) + return "Chest"; + id = id.toLowerCase() .replace("minecraft:", "") .replace("_", " "); From b49004ddaf95f0a9409b0ab04c2b55932f439fcd Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+DoctorMacc@users.noreply.github.com> Date: Mon, 4 May 2020 22:32:02 -0400 Subject: [PATCH 038/140] Add block entity translators for Bedrock-only block entities (#478) * Initial work on flower pots * Flowers work in-game, not yet chunk load * Don't overwrite my code before merge * Finish up flower pots; add piston support on chunk load * Clean up * Remove debug line; update mappings --- .../world/block/BlockStateValues.java | 51 +++++++++++ .../world/block/BlockTranslator.java | 5 ++ .../block/entity/BedrockOnlyBlockEntity.java | 61 ++++++++++++++ .../FlowerPotBlockEntityTranslator.java | 84 +++++++++++++++++++ .../entity/PistonBlockEntityTranslator.java | 72 ++++++++++++++++ .../connector/utils/BlockEntityUtils.java | 6 +- .../geysermc/connector/utils/ChunkUtils.java | 30 ++++++- connector/src/main/resources/mappings | 2 +- 8 files changed, 306 insertions(+), 5 deletions(-) create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/BedrockOnlyBlockEntity.java create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/FlowerPotBlockEntityTranslator.java create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/PistonBlockEntityTranslator.java diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/world/block/BlockStateValues.java b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/BlockStateValues.java index 00d7171cf..408ac12c5 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/world/block/BlockStateValues.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/BlockStateValues.java @@ -27,11 +27,17 @@ package org.geysermc.connector.network.translators.world.block; import com.fasterxml.jackson.databind.JsonNode; import com.github.steveice10.mc.protocol.data.game.world.block.BlockState; +import com.nukkitx.nbt.tag.CompoundTag; +import it.unimi.dsi.fastutil.ints.Int2BooleanMap; +import it.unimi.dsi.fastutil.ints.Int2BooleanOpenHashMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2ByteMap; import it.unimi.dsi.fastutil.objects.Object2ByteOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2IntMap; import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; +import java.util.HashMap; import java.util.Map; /** @@ -41,7 +47,11 @@ public class BlockStateValues { private static final Object2IntMap BANNER_COLORS = new Object2IntOpenHashMap<>(); private static final Object2ByteMap BED_COLORS = new Object2ByteOpenHashMap<>(); + private static final Int2ObjectMap FLOWER_POT_VALUES = new Int2ObjectOpenHashMap<>(); + private static final Map FLOWER_POT_BLOCKS = new HashMap<>(); private static final Object2IntMap NOTEBLOCK_PITCHES = new Object2IntOpenHashMap<>(); + private static final Int2BooleanMap IS_STICKY_PISTON = new Int2BooleanOpenHashMap(); + private static final Int2BooleanMap PISTON_VALUES = new Int2BooleanOpenHashMap(); private static final Object2ByteMap SKULL_VARIANTS = new Object2ByteOpenHashMap<>(); private static final Object2ByteMap SKULL_ROTATIONS = new Object2ByteOpenHashMap<>(); private static final Object2ByteMap SHULKERBOX_DIRECTIONS = new Object2ByteOpenHashMap<>(); @@ -64,12 +74,25 @@ public class BlockStateValues { return; } + if (entry.getKey().contains("potted_")) { + System.out.println(entry.getKey().replace("potted_", "")); + FLOWER_POT_VALUES.put(javaBlockState.getId(), entry.getKey().replace("potted_", "")); + return; + } + JsonNode notePitch = entry.getValue().get("note_pitch"); if (notePitch != null) { NOTEBLOCK_PITCHES.put(javaBlockState, entry.getValue().get("note_pitch").intValue()); return; } + if (entry.getKey().contains("piston")) { + // True if extended, false if not + PISTON_VALUES.put(javaBlockState.getId(), entry.getKey().contains("extended=true")); + IS_STICKY_PISTON.put(javaBlockState.getId(), entry.getKey().contains("sticky")); + return; + } + JsonNode skullVariation = entry.getValue().get("variation"); if(skullVariation != null) { SKULL_VARIANTS.put(javaBlockState, (byte) skullVariation.intValue()); @@ -114,6 +137,22 @@ public class BlockStateValues { return -1; } + /** + * Get the Int2ObjectMap of flower pot block states to containing plant + * @return Int2ObjectMap of flower pot values + */ + public static Int2ObjectMap getFlowerPotValues() { + return FLOWER_POT_VALUES; + } + + /** + * Get the map of contained flower pot plants to Bedrock CompoundTag + * @return Map of flower pot blocks. + */ + public static Map getFlowerPotBlocks() { + return FLOWER_POT_BLOCKS; + } + /** * The note that noteblocks output when hit is part of the block state in Java but sent as a BlockEventPacket in Bedrock. * This gives an integer pitch that Bedrock can use. @@ -127,6 +166,18 @@ public class BlockStateValues { return -1; } + /** + * Get the Int2BooleanMap showing if a piston block state is extended or not. + * @return the Int2BooleanMap of piston extensions. + */ + public static Int2BooleanMap getPistonValues() { + return PISTON_VALUES; + } + + public static boolean isStickyPiston(BlockState blockState) { + return IS_STICKY_PISTON.get(blockState.getId()); + } + /** * Skull variations are part of the namespaced ID in Java Edition, but part of the block entity tag in Bedrock. * This gives a byte variant ID that Bedrock can use. diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/world/block/BlockTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/BlockTranslator.java index 2bb918cc8..e614900cb 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/world/block/BlockTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/BlockTranslator.java @@ -153,6 +153,11 @@ public class BlockTranslator { BlockStateValues.storeBlockStateValues(entry, javaBlockState); + // Get the tag needed for non-empty flower pots + if (entry.getValue().get("pottable") != null) { + BlockStateValues.getFlowerPotBlocks().put(entry.getKey().split("\\[")[0], buildBedrockState(entry.getValue())); + } + if ("minecraft:water[level=0]".equals(javaId)) { waterRuntimeId = bedrockRuntimeId; } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/BedrockOnlyBlockEntity.java b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/BedrockOnlyBlockEntity.java new file mode 100644 index 000000000..5b325ebad --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/BedrockOnlyBlockEntity.java @@ -0,0 +1,61 @@ +/* + * 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.world.block.entity; + +import com.github.steveice10.mc.protocol.data.game.world.block.BlockState; +import com.nukkitx.math.vector.Vector3i; +import com.nukkitx.nbt.tag.CompoundTag; +import org.geysermc.connector.network.session.GeyserSession; + +/** + * Implemented only if a block is a block entity in Bedrock and not Java Edition. + */ +public interface BedrockOnlyBlockEntity { + + /** + * Update the block on Bedrock Edition. + * @param session GeyserSession. + * @param blockState The Java block state. + * @param position The Bedrock block position. + */ + void updateBlock(GeyserSession session, BlockState blockState, Vector3i position); + + /** + * Get the tag of the Bedrock-only block entity + * @param position Bedrock position of block. + * @param blockState Java BlockState of block. + * @return Bedrock tag, or null if not a Bedrock-only Block Entity + */ + static CompoundTag getTag(Vector3i position, BlockState blockState) { + if (new FlowerPotBlockEntityTranslator().isBlock(blockState)) { + return FlowerPotBlockEntityTranslator.getTag(blockState, position); + } else if (PistonBlockEntityTranslator.isBlock(blockState)) { + return PistonBlockEntityTranslator.getTag(blockState, position); + } + return null; + } +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/FlowerPotBlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/FlowerPotBlockEntityTranslator.java new file mode 100644 index 000000000..6861a9535 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/FlowerPotBlockEntityTranslator.java @@ -0,0 +1,84 @@ +/* + * 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.world.block.entity; + +import com.github.steveice10.mc.protocol.data.game.world.block.BlockState; +import com.nukkitx.math.vector.Vector3i; +import com.nukkitx.nbt.CompoundTagBuilder; +import com.nukkitx.nbt.tag.CompoundTag; +import com.nukkitx.protocol.bedrock.packet.UpdateBlockPacket; +import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.world.block.BlockStateValues; +import org.geysermc.connector.network.translators.world.block.BlockTranslator; +import org.geysermc.connector.utils.BlockEntityUtils; + +public class FlowerPotBlockEntityTranslator implements BedrockOnlyBlockEntity, RequiresBlockState { + + @Override + public boolean isBlock(BlockState blockState) { + return (BlockStateValues.getFlowerPotValues().containsKey(blockState.getId())); + } + + @Override + public void updateBlock(GeyserSession session, BlockState blockState, Vector3i position) { + BlockEntityUtils.updateBlockEntity(session, getTag(blockState, position), position); + UpdateBlockPacket updateBlockPacket = new UpdateBlockPacket(); + updateBlockPacket.setDataLayer(0); + updateBlockPacket.setRuntimeId(BlockTranslator.getBedrockBlockId(blockState)); + updateBlockPacket.setBlockPosition(position); + updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.PRIORITY); + updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NONE); + updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NEIGHBORS); + session.getUpstream().sendPacket(updateBlockPacket); + } + + /** + * Get the Nukkit CompoundTag of the flower pot. + * @param blockState Java BlockState of flower pot. + * @param position Bedrock position of flower pot. + * @return Bedrock tag of flower pot. + */ + public static CompoundTag getTag(BlockState blockState, Vector3i position) { + CompoundTagBuilder tagBuilder = CompoundTagBuilder.builder() + .intTag("x", position.getX()) + .intTag("y", position.getY()) + .intTag("z", position.getZ()) + .byteTag("isMovable", (byte) 1) + .stringTag("id", "FlowerPot"); + // Get the Java name of the plant inside. e.g. minecraft:oak_sapling + String name = BlockStateValues.getFlowerPotValues().get(blockState.getId()); + if (name != null) { + // Get the Bedrock CompoundTag of the block. + // This is where we need to store the *Java* name because Bedrock has six minecraft:sapling blocks with different block states. + CompoundTag plant = BlockStateValues.getFlowerPotBlocks().get(name); + if (plant != null) { + tagBuilder.tag(plant.toBuilder().build("PlantBlock")); + } + } + return tagBuilder.buildRootTag(); + } +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/PistonBlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/PistonBlockEntityTranslator.java new file mode 100644 index 000000000..2dffce24c --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/PistonBlockEntityTranslator.java @@ -0,0 +1,72 @@ +/* + * 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.world.block.entity; + +import com.github.steveice10.mc.protocol.data.game.world.block.BlockState; +import com.nukkitx.math.vector.Vector3i; +import com.nukkitx.nbt.CompoundTagBuilder; +import com.nukkitx.nbt.tag.CompoundTag; +import org.geysermc.connector.network.translators.world.block.BlockStateValues; + +/** + * Pistons are a special case where they are only a block entity on Bedrock. + */ +public class PistonBlockEntityTranslator { + + /** + * Used in ChunkUtils to determine if the block is a piston. + * @param blockState Java BlockState of block. + * @return if block is a piston or not. + */ + public static boolean isBlock(BlockState blockState) { + return BlockStateValues.getPistonValues().containsKey(blockState.getId()); + } + + /** + * Calculates the Nukkit CompoundTag to send to the client on chunk + * @param blockState Java BlockState of block. + * @param position Bedrock position of piston. + * @return Bedrock tag of piston. + */ + public static CompoundTag getTag(BlockState blockState, Vector3i position) { + CompoundTagBuilder tagBuilder = CompoundTagBuilder.builder() + .intTag("x", position.getX()) + .intTag("y", position.getY()) + .intTag("z", position.getZ()) + .byteTag("isMovable", (byte) 1) + .stringTag("id", "PistonArm"); + if (BlockStateValues.getPistonValues().containsKey(blockState.getId())) { + boolean extended = BlockStateValues.getPistonValues().get(blockState.getId()); + // 1f if extended, otherwise 0f + tagBuilder.floatTag("Progress", (extended) ? 1.0f : 0.0f); + // 1 if sticky, 0 if not + tagBuilder.byteTag("Sticky", (byte)((BlockStateValues.isStickyPiston(blockState)) ? 1 : 0)); + } + return tagBuilder.buildRootTag(); + } + +} diff --git a/connector/src/main/java/org/geysermc/connector/utils/BlockEntityUtils.java b/connector/src/main/java/org/geysermc/connector/utils/BlockEntityUtils.java index f79ffd5f7..b0794e200 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/BlockEntityUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/BlockEntityUtils.java @@ -42,8 +42,12 @@ public class BlockEntityUtils { } public static void updateBlockEntity(GeyserSession session, com.nukkitx.nbt.tag.CompoundTag blockEntity, Position position) { + updateBlockEntity(session, blockEntity, Vector3i.from(position.getX(), position.getY(), position.getZ())); + } + + public static void updateBlockEntity(GeyserSession session, com.nukkitx.nbt.tag.CompoundTag blockEntity, Vector3i position) { BlockEntityDataPacket blockEntityPacket = new BlockEntityDataPacket(); - blockEntityPacket.setBlockPosition(Vector3i.from(position.getX(), position.getY(), position.getZ())); + blockEntityPacket.setBlockPosition(position); blockEntityPacket.setData(blockEntity); session.getUpstream().sendPacket(blockEntityPacket); } diff --git a/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java b/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java index 97be97324..fcc596eb1 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java @@ -35,11 +35,13 @@ import com.nukkitx.math.vector.Vector3i; import com.nukkitx.protocol.bedrock.packet.*; import it.unimi.dsi.fastutil.objects.Object2IntMap; import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; +import it.unimi.dsi.fastutil.objects.ObjectArrayList; import lombok.Getter; import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.entity.Entity; import org.geysermc.connector.entity.ItemFrameEntity; import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.world.block.BlockStateValues; import org.geysermc.connector.network.translators.world.block.entity.*; import org.geysermc.connector.network.translators.Translators; import org.geysermc.connector.network.translators.world.block.BlockTranslator; @@ -68,6 +70,9 @@ public class ChunkUtils { // Temporarily stores positions of BlockState values per chunk load Map blockEntityPositions = new HashMap<>(); + // Temporarily stores compound tags of Bedrock-only block entities + ObjectArrayList bedrockOnlyBlockEntities = new ObjectArrayList<>(); + for (int chunkY = 0; chunkY < chunks.length; chunkY++) { chunkData.sections[chunkY] = new ChunkSection(); Chunk chunk = chunks[chunkY]; @@ -99,6 +104,13 @@ public class ChunkUtils { section.getBlockStorageArray()[0].setFullBlock(ChunkSection.blockPosition(x, y, z), id); } + // Check if block is piston or flower - only block entities in Bedrock + if (BlockStateValues.getFlowerPotValues().containsKey(blockState.getId()) || + BlockStateValues.getPistonValues().containsKey(blockState.getId())) { + Position pos = new ChunkPosition(column.getX(), column.getZ()).getBlock(x, (chunkY << 4) + y, z); + bedrockOnlyBlockEntities.add(BedrockOnlyBlockEntity.getTag(Vector3i.from(pos.getX(), pos.getY(), pos.getZ()), blockState)); + } + if (BlockTranslator.isWaterlogged(blockState)) { section.getBlockStorageArray()[1].setFullBlock(ChunkSection.blockPosition(x, y, z), BEDROCK_WATER_ID); } @@ -108,8 +120,9 @@ public class ChunkUtils { } - com.nukkitx.nbt.tag.CompoundTag[] bedrockBlockEntities = new com.nukkitx.nbt.tag.CompoundTag[blockEntities.length]; - for (int i = 0; i < blockEntities.length; i++) { + com.nukkitx.nbt.tag.CompoundTag[] bedrockBlockEntities = new com.nukkitx.nbt.tag.CompoundTag[blockEntities.length + bedrockOnlyBlockEntities.size()]; + int i = 0; + while (i < blockEntities.length) { CompoundTag tag = blockEntities[i]; String tagName; if (!tag.contains("id")) { @@ -121,8 +134,14 @@ public class ChunkUtils { String id = BlockEntityUtils.getBedrockBlockEntityId(tagName); BlockEntityTranslator blockEntityTranslator = BlockEntityUtils.getBlockEntityTranslator(id); - BlockState blockState = blockEntityPositions.get(new Position((int) tag.get("x").getValue(), (int) tag.get("y").getValue(), (int) tag.get("z").getValue())); + Position pos = new Position((int) tag.get("x").getValue(), (int) tag.get("y").getValue(), (int) tag.get("z").getValue()); + BlockState blockState = blockEntityPositions.get(pos); bedrockBlockEntities[i] = blockEntityTranslator.getBlockEntityTag(tagName, tag, blockState); + i++; + } + for (com.nukkitx.nbt.tag.CompoundTag tag : bedrockOnlyBlockEntities) { + bedrockBlockEntities[i] = tag; + i++; } chunkData.blockEntities = bedrockBlockEntities; @@ -186,6 +205,11 @@ public class ChunkUtils { // Iterates through all block entity translators and determines if the block state needs to be saved for (RequiresBlockState requiresBlockState : Translators.getRequiresBlockStateMap()) { if (requiresBlockState.isBlock(blockState)) { + // Flower pots are block entities only in Bedrock and are not updated anywhere else like note blocks + if (requiresBlockState instanceof BedrockOnlyBlockEntity) { + ((BedrockOnlyBlockEntity) requiresBlockState).updateBlock(session, blockState, position); + break; + } CACHED_BLOCK_ENTITIES.put(new Position(position.getX(), position.getY(), position.getZ()), blockState); break; //No block will be a part of two classes } diff --git a/connector/src/main/resources/mappings b/connector/src/main/resources/mappings index ddb62693f..5b3a9ad1d 160000 --- a/connector/src/main/resources/mappings +++ b/connector/src/main/resources/mappings @@ -1 +1 @@ -Subproject commit ddb62693f878a99f106a0d6ea16a92ec7c4c7cd0 +Subproject commit 5b3a9ad1d2ef76105fb318e63126a096844b3195 From 5b3e7c965ff56ca18138686868e530807bf352e9 Mon Sep 17 00:00:00 2001 From: James Harrison Date: Tue, 5 May 2020 03:32:37 +0100 Subject: [PATCH 039/140] Chat/Skin fixes (#480) * Made MessageUtils mimic java chat behavior Send ClientSettingsPacket when player joins a server * Fix comments Set use client locale instead of hard coding * Moved chat reset to fix some broken formatting * Revert MessageUtil as rtm516 has implemented a better fix --- .gitignore | 1 + .../translators/java/JavaJoinGameTranslator.java | 13 +++++++++++++ 2 files changed, 14 insertions(+) diff --git a/.gitignore b/.gitignore index 6e0e8f49b..0af6ecd05 100644 --- a/.gitignore +++ b/.gitignore @@ -222,6 +222,7 @@ nbdist/ # End of https://www.gitignore.io/api/git,java,maven,eclipse,netbeans,jetbrains+all ### Geyser ### +run/ config.yml logs/ public-key.pem diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaJoinGameTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaJoinGameTranslator.java index 34fe2271d..5427dcbce 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaJoinGameTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaJoinGameTranslator.java @@ -25,6 +25,10 @@ package org.geysermc.connector.network.translators.java; +import com.github.steveice10.mc.protocol.data.game.entity.player.Hand; +import com.github.steveice10.mc.protocol.data.game.setting.ChatVisibility; +import com.github.steveice10.mc.protocol.data.game.setting.SkinPart; +import com.github.steveice10.mc.protocol.packet.ingame.client.ClientSettingsPacket; import org.geysermc.connector.entity.PlayerEntity; import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.PacketTranslator; @@ -38,6 +42,9 @@ import com.nukkitx.protocol.bedrock.packet.PlayStatusPacket; import com.nukkitx.protocol.bedrock.packet.SetEntityDataPacket; import com.nukkitx.protocol.bedrock.packet.SetPlayerGameTypePacket; +import java.util.Arrays; +import java.util.List; + @Translator(packet = ServerJoinGamePacket.class) public class JavaJoinGameTranslator extends PacketTranslator { @@ -67,6 +74,12 @@ public class JavaJoinGameTranslator extends PacketTranslator skinParts = Arrays.asList(SkinPart.values()); + ClientSettingsPacket clientSettingsPacket = new ClientSettingsPacket(locale, (byte) session.getRenderDistance(), ChatVisibility.FULL, true, skinParts, Hand.MAIN_HAND); + session.getDownstream().getSession().send(clientSettingsPacket); + if (DimensionUtils.javaToBedrock(packet.getDimension()) != entity.getDimension()) { DimensionUtils.switchDimension(session, packet.getDimension()); } From eeb4cafbc899b3eec3d8e48cf89a084310bb8e9a Mon Sep 17 00:00:00 2001 From: rtm516 Date: Tue, 5 May 2020 03:32:57 +0100 Subject: [PATCH 040/140] Fix some nested language strings (#482) --- .../connector/utils/MessageUtils.java | 28 +++++++++++++------ 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/utils/MessageUtils.java b/connector/src/main/java/org/geysermc/connector/utils/MessageUtils.java index 478e42d1b..3c924912a 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/MessageUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/MessageUtils.java @@ -27,18 +27,15 @@ package org.geysermc.connector.utils; import com.github.steveice10.mc.protocol.data.game.scoreboard.TeamColor; import com.github.steveice10.mc.protocol.data.message.*; -import com.github.steveice10.opennbt.tag.builtin.StringTag; -import com.google.gson.JsonArray; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.google.gson.JsonParser; -import com.google.gson.JsonPrimitive; +import com.google.gson.*; import net.kyori.text.Component; import net.kyori.text.serializer.gson.GsonComponentSerializer; import net.kyori.text.serializer.legacy.LegacyComponentSerializer; import org.geysermc.connector.network.session.GeyserSession; -import java.util.*; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -111,9 +108,20 @@ public class MessageUtils { builder.append(getColorOrParent(msg.getStyle())); if (!(msg.getText() == null)) { boolean isTranslationMessage = (msg instanceof TranslationMessage); - builder.append(getTranslatedBedrockMessage(msg, locale, isTranslationMessage)); + String extraText = ""; + + if (isTranslationMessage) { + List paramsTranslated = getTranslationParams(((TranslationMessage) msg).getTranslationParams(), locale); + extraText = insertParams(getTranslatedBedrockMessage(msg, locale, isTranslationMessage), paramsTranslated); + } else { + extraText = getTranslatedBedrockMessage(msg, locale, isTranslationMessage); + } + + builder.append(extraText); + builder.append("\u00a7r"); } } + return builder.toString(); } @@ -164,9 +172,11 @@ public class MessageUtils { } for (String text : params) { - newMessage = newMessage.replaceFirst("%s", text); + newMessage = newMessage.replaceFirst("%s", text.replaceAll("%s", "%r")); } + newMessage = newMessage.replaceAll("%r", "MISSING!"); + return newMessage; } From 26266bf9b63593b119b9aa71f6feeb66cd65c819 Mon Sep 17 00:00:00 2001 From: RednedEpic Date: Mon, 4 May 2020 22:01:34 -0500 Subject: [PATCH 041/140] Fix black texture of offhand item (Closes #332) --- .../src/main/java/org/geysermc/connector/entity/Entity.java | 1 + 1 file changed, 1 insertion(+) diff --git a/connector/src/main/java/org/geysermc/connector/entity/Entity.java b/connector/src/main/java/org/geysermc/connector/entity/Entity.java index 54355d992..381f8f8e5 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/Entity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/Entity.java @@ -93,6 +93,7 @@ public class Entity { setPosition(position); metadata.put(EntityData.SCALE, 1f); + metadata.put(EntityData.COLOR, 0); metadata.put(EntityData.MAX_AIR, (short) 400); metadata.put(EntityData.AIR, (short) 0); metadata.put(EntityData.LEAD_HOLDER_EID, -1L); From 6642f1ec265379e6755638a043c1a11ca3e72954 Mon Sep 17 00:00:00 2001 From: RednedEpic Date: Tue, 5 May 2020 00:09:36 -0500 Subject: [PATCH 042/140] Fix a few entities not showing up and include identifiers for entities in EntityType --- .../connector/entity/EnderCrystalEntity.java | 19 -------------- .../org/geysermc/connector/entity/Entity.java | 2 +- .../connector/entity/ExpOrbEntity.java | 14 +++++------ .../connector/entity/FishingHookEntity.java | 19 -------------- .../living/animal/TropicalFishEntity.java | 18 ------------- .../animal/horse/TraderLlamaEntity.java | 25 ------------------- .../living/merchant/VillagerEntity.java | 21 ---------------- .../connector/entity/type/EntityType.java | 22 ++++++++++------ 8 files changed, 23 insertions(+), 117 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/entity/EnderCrystalEntity.java b/connector/src/main/java/org/geysermc/connector/entity/EnderCrystalEntity.java index b3ce22783..31f7b8edf 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/EnderCrystalEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/EnderCrystalEntity.java @@ -60,23 +60,4 @@ public class EnderCrystalEntity extends Entity { } super.updateBedrockMetadata(entityMetadata, session); } - - @Override - public void spawnEntity(GeyserSession session) { - AddEntityPacket addEntityPacket = new AddEntityPacket(); - // Not end crystal but ender crystal - addEntityPacket.setIdentifier("minecraft:ender_crystal"); - addEntityPacket.setRuntimeEntityId(geyserId); - addEntityPacket.setUniqueEntityId(geyserId); - addEntityPacket.setPosition(position); - addEntityPacket.setMotion(motion); - addEntityPacket.setRotation(getBedrockRotation()); - addEntityPacket.setEntityType(entityType.getType()); - addEntityPacket.getMetadata().putAll(metadata); - - valid = true; - session.getUpstream().sendPacket(addEntityPacket); - - session.getConnector().getLogger().debug("Spawned entity " + entityType + " at location " + position + " with id " + geyserId + " (java id " + entityId + ")"); - } } diff --git a/connector/src/main/java/org/geysermc/connector/entity/Entity.java b/connector/src/main/java/org/geysermc/connector/entity/Entity.java index 381f8f8e5..7e8a190d5 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/Entity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/Entity.java @@ -109,7 +109,7 @@ public class Entity { public void spawnEntity(GeyserSession session) { AddEntityPacket addEntityPacket = new AddEntityPacket(); - addEntityPacket.setIdentifier("minecraft:" + entityType.name().toLowerCase()); + addEntityPacket.setIdentifier(entityType.getIdentifier()); addEntityPacket.setRuntimeEntityId(geyserId); addEntityPacket.setUniqueEntityId(geyserId); addEntityPacket.setPosition(position); diff --git a/connector/src/main/java/org/geysermc/connector/entity/ExpOrbEntity.java b/connector/src/main/java/org/geysermc/connector/entity/ExpOrbEntity.java index 03c9ffe3d..2fd06c234 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/ExpOrbEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/ExpOrbEntity.java @@ -26,10 +26,14 @@ package org.geysermc.connector.entity; import com.nukkitx.math.vector.Vector3f; -import com.nukkitx.protocol.bedrock.packet.SpawnExperienceOrbPacket; +import com.nukkitx.protocol.bedrock.data.EntityData; +import com.nukkitx.protocol.bedrock.packet.SetEntityMotionPacket; import org.geysermc.connector.entity.type.EntityType; import org.geysermc.connector.network.session.GeyserSession; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; + public class ExpOrbEntity extends Entity { private int amount; @@ -42,11 +46,7 @@ public class ExpOrbEntity extends Entity { @Override public void spawnEntity(GeyserSession session) { - SpawnExperienceOrbPacket spawnExpOrbPacket = new SpawnExperienceOrbPacket(); - spawnExpOrbPacket.setPosition(position); - spawnExpOrbPacket.setAmount(amount); - - valid = true; - session.getUpstream().sendPacket(spawnExpOrbPacket); + this.metadata.put(EntityData.EXPERIENCE_VALUE, amount); + super.spawnEntity(session); } } diff --git a/connector/src/main/java/org/geysermc/connector/entity/FishingHookEntity.java b/connector/src/main/java/org/geysermc/connector/entity/FishingHookEntity.java index 3a77292fe..e82a42a24 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/FishingHookEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/FishingHookEntity.java @@ -34,23 +34,4 @@ public class FishingHookEntity extends Entity { public FishingHookEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { super(entityId, geyserId, entityType, position, motion, rotation); } - - @Override - public void spawnEntity(GeyserSession session) { - AddEntityPacket addEntityPacket = new AddEntityPacket(); - // Different ID in Bedrock - addEntityPacket.setIdentifier("minecraft:fishing_hook"); - addEntityPacket.setRuntimeEntityId(geyserId); - addEntityPacket.setUniqueEntityId(geyserId); - addEntityPacket.setPosition(position); - addEntityPacket.setMotion(motion); - addEntityPacket.setRotation(getBedrockRotation()); - addEntityPacket.setEntityType(entityType.getType()); - addEntityPacket.getMetadata().putAll(metadata); - - valid = true; - session.getUpstream().sendPacket(addEntityPacket); - - session.getConnector().getLogger().debug("Spawned entity " + entityType + " at location " + position + " with id " + geyserId + " (java id " + entityId + ")"); - } } diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/animal/TropicalFishEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/animal/TropicalFishEntity.java index 3ded4cbfe..d5e9a6871 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/living/animal/TropicalFishEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/living/animal/TropicalFishEntity.java @@ -54,24 +54,6 @@ public class TropicalFishEntity extends AbstractFishEntity { super.updateBedrockMetadata(entityMetadata, session); } - @Override - public void spawnEntity(GeyserSession session) { - AddEntityPacket addEntityPacket = new AddEntityPacket(); - addEntityPacket.setIdentifier("minecraft:tropicalfish"); - addEntityPacket.setRuntimeEntityId(geyserId); - addEntityPacket.setUniqueEntityId(geyserId); - addEntityPacket.setPosition(position); - addEntityPacket.setMotion(motion); - addEntityPacket.setRotation(getBedrockRotation()); - addEntityPacket.setEntityType(entityType.getType()); - addEntityPacket.getMetadata().putAll(metadata); - - valid = true; - session.getUpstream().sendPacket(addEntityPacket); - - session.getConnector().getLogger().debug("Spawned entity " + entityType + " at location " + position + " with id " + geyserId + " (java id " + entityId + ")"); - } - @Getter @AllArgsConstructor private static class TropicalFishVariant { diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/animal/horse/TraderLlamaEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/animal/horse/TraderLlamaEntity.java index 5e591bc7c..08a718367 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/living/animal/horse/TraderLlamaEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/living/animal/horse/TraderLlamaEntity.java @@ -26,36 +26,11 @@ package org.geysermc.connector.entity.living.animal.horse; import com.nukkitx.math.vector.Vector3f; -import com.nukkitx.protocol.bedrock.data.EntityData; -import com.nukkitx.protocol.bedrock.packet.AddEntityPacket; import org.geysermc.connector.entity.type.EntityType; -import org.geysermc.connector.network.session.GeyserSession; public class TraderLlamaEntity extends LlamaEntity { public TraderLlamaEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { super(entityId, geyserId, entityType, position, motion, rotation); } - - @Override - public void spawnEntity(GeyserSession session) { - // The trader llama is a separate entity from the llama in Java but a normal llama with extra metadata in Bedrock. - AddEntityPacket addEntityPacket = new AddEntityPacket(); - addEntityPacket.setIdentifier("minecraft:llama"); - addEntityPacket.setRuntimeEntityId(geyserId); - addEntityPacket.setUniqueEntityId(geyserId); - addEntityPacket.setPosition(position); - addEntityPacket.setMotion(motion); - addEntityPacket.setRotation(getBedrockRotation()); - addEntityPacket.setEntityType(entityType.getType()); - addEntityPacket.getMetadata().putAll(metadata); - // Here's the difference - addEntityPacket.getMetadata().put(EntityData.MARK_VARIANT, 1); - - valid = true; - session.getUpstream().sendPacket(addEntityPacket); - - session.getConnector().getLogger().debug("Spawned entity " + entityType + " at location " + position + " with id " + geyserId + " (java id " + entityId + ")"); - } - } diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/merchant/VillagerEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/merchant/VillagerEntity.java index 9ed48b886..895f8cc1d 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/living/merchant/VillagerEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/living/merchant/VillagerEntity.java @@ -29,7 +29,6 @@ import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadat import com.github.steveice10.mc.protocol.data.game.entity.metadata.VillagerData; import com.nukkitx.math.vector.Vector3f; import com.nukkitx.protocol.bedrock.data.EntityData; -import com.nukkitx.protocol.bedrock.packet.AddEntityPacket; import it.unimi.dsi.fastutil.ints.Int2IntMap; import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap; import org.geysermc.connector.entity.type.EntityType; @@ -85,24 +84,4 @@ public class VillagerEntity extends AbstractMerchantEntity { } super.updateBedrockMetadata(entityMetadata, session); } - - @Override - public void spawnEntity(GeyserSession session) { - AddEntityPacket addEntityPacket = new AddEntityPacket(); - // "v2" or else it's the legacy villager - addEntityPacket.setIdentifier("minecraft:villager_v2"); - addEntityPacket.setRuntimeEntityId(geyserId); - addEntityPacket.setUniqueEntityId(geyserId); - addEntityPacket.setPosition(position); - addEntityPacket.setMotion(motion); - addEntityPacket.setRotation(getBedrockRotation()); - addEntityPacket.setEntityType(entityType.getType()); - addEntityPacket.getMetadata().putAll(metadata); - - valid = true; - session.getUpstream().sendPacket(addEntityPacket); - - session.getConnector().getLogger().debug("Spawned entity " + entityType + " at location " + position + " with id " + geyserId + " (java id " + entityId + ")"); - } - } diff --git a/connector/src/main/java/org/geysermc/connector/entity/type/EntityType.java b/connector/src/main/java/org/geysermc/connector/entity/type/EntityType.java index 5f77fdc41..98d836d20 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/type/EntityType.java +++ b/connector/src/main/java/org/geysermc/connector/entity/type/EntityType.java @@ -45,7 +45,7 @@ public enum EntityType { PIG(PigEntity.class, 12, 0.9f), SHEEP(SheepEntity.class, 13, 1.3f, 0.9f), WOLF(WolfEntity.class, 14, 0.85f, 0.6f), - VILLAGER(VillagerEntity.class, 15, 1.8f, 0.6f, 0.6f, 1.62f), + VILLAGER(VillagerEntity.class, 15, 1.8f, 0.6f, 0.6f, 1.62f, "minecraft:villager_v2"), MOOSHROOM(AnimalEntity.class, 16, 1.4f, 0.9f), SQUID(WaterEntity.class, 17, 0.8f), RABBIT(RabbitEntity.class, 18, 0.5f, 0.4f), @@ -60,7 +60,7 @@ public enum EntityType { ZOMBIE_HORSE(AbstractHorseEntity.class, 27, 1.6f, 1.3965f), POLAR_BEAR(PolarBearEntity.class, 28, 1.4f, 1.3f), LLAMA(LlamaEntity.class, 29, 1.87f, 0.9f), - TRADER_LLAMA(TraderLlamaEntity.class, 29, 1.187f, 0.9f), + TRADER_LLAMA(TraderLlamaEntity.class, 29, 1.187f, 0.9f, 0f, 0f, "minecraft:llama"), PARROT(ParrotEntity.class, 30, 0.9f, 0.5f), DOLPHIN(WaterEntity.class, 31, 0.6f, 0.9f), ZOMBIE(ZombieEntity.class, 32, 1.8f, 0.6f, 0.6f, 1.62f), @@ -101,16 +101,16 @@ public enum EntityType { TNT(TNTEntity.class, 65, 0.98f, 0.98f), FALLING_BLOCK(FallingBlockEntity.class, 66, 0.98f, 0.98f), MOVING_BLOCK(Entity.class, 67, 0f), - EXPERIENCE_BOTTLE(ThrowableEntity.class, 68, 0.25f, 0.25f), - EXPERIENCE_ORB(ExpOrbEntity.class, 69, 0f), + EXPERIENCE_BOTTLE(ThrowableEntity.class, 68, 0.25f, 0.25f, 0f, 0f, "minecraft:xp_bottle"), + EXPERIENCE_ORB(ExpOrbEntity.class, 69, 0f, 0f, 0f, 0f, "minecraft:xp_orb"), EYE_OF_ENDER(Entity.class, 70, 0f), - END_CRYSTAL(EnderCrystalEntity.class, 71, 0f), + END_CRYSTAL(EnderCrystalEntity.class, 71, 0f, 0f, 0f, 0f, "minecraft:ender_crystal"), FIREWORK_ROCKET(Entity.class, 72, 0f), TRIDENT(ArrowEntity.class, 73, 0f), TURTLE(AnimalEntity.class, 74, 0.4f, 1.2f), CAT(CatEntity.class, 75, 0.35f, 0.3f), SHULKER_BULLET(Entity.class, 76, 0f), - FISHING_BOBBER(FishingHookEntity.class, 77, 0f), + FISHING_BOBBER(FishingHookEntity.class, 77, 0f, 0f, 0f, 0f, "minecraft:fishing_hook"), CHALKBOARD(Entity.class, 78, 0f), DRAGON_FIREBALL(ItemedFireballEntity.class, 79, 0f), ARROW(ArrowEntity.class, 80, 0.25f, 0.25f), @@ -143,7 +143,7 @@ public enum EntityType { PUFFERFISH(PufferFishEntity.class, 108, 0.7f, 0.7f), SALMON(AbstractFishEntity.class, 109, 0.5f, 0.7f), DROWNED(ZombieEntity.class, 110, 1.95f, 0.6f), - TROPICAL_FISH(TropicalFishEntity.class, 111, 0.6f, 0.6f), + TROPICAL_FISH(TropicalFishEntity.class, 111, 0.6f, 0.6f, 0f, 0f, "minecraft:tropicalfish"), COD(AbstractFishEntity.class, 112, 0.25f, 0.5f), PANDA(PandaEntity.class, 113, 1.25f, 1.125f, 1.825f), FOX(FoxEntity.class, 121, 0.5f, 1.25f), @@ -160,6 +160,7 @@ public enum EntityType { private final float width; private final float length; private final float offset; + private String identifier; EntityType(Class entityClass, int type, float height) { this(entityClass, type, height, 0f); @@ -174,11 +175,18 @@ public enum EntityType { } EntityType(Class entityClass, int type, float height, float width, float length, float offset) { + this(entityClass, type, height, width, length, offset, null); + + this.identifier = "minecraft:" + name().toLowerCase(); + } + + EntityType(Class entityClass, int type, float height, float width, float length, float offset, String identifier) { this.entityClass = entityClass; this.type = type; this.height = height; this.width = width; this.length = length; this.offset = offset + 0.00001f; + this.identifier = identifier; } } From 20bbbee3eb77ae360583cc9117d215620039e4d8 Mon Sep 17 00:00:00 2001 From: RednedEpic Date: Tue, 5 May 2020 00:10:23 -0500 Subject: [PATCH 043/140] Remove flower pot debug code --- .../network/translators/world/block/BlockStateValues.java | 1 - 1 file changed, 1 deletion(-) diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/world/block/BlockStateValues.java b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/BlockStateValues.java index 408ac12c5..de08b7e8b 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/world/block/BlockStateValues.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/BlockStateValues.java @@ -75,7 +75,6 @@ public class BlockStateValues { } if (entry.getKey().contains("potted_")) { - System.out.println(entry.getKey().replace("potted_", "")); FLOWER_POT_VALUES.put(javaBlockState.getId(), entry.getKey().replace("potted_", "")); return; } From 96a7770c22cfc1db21cc2f840f511e543177710a Mon Sep 17 00:00:00 2001 From: rtm516 Date: Tue, 5 May 2020 16:48:01 +0100 Subject: [PATCH 044/140] Fixed entity bugs introduced by 6642f1e and added fishing lines (#483) * Fixed entity bugs introduced by 6642f1e * Fixed fishing line not displaying * Clean extra line and added todo --- .../connector/entity/EnderCrystalEntity.java | 1 - .../geysermc/connector/entity/ExpOrbEntity.java | 4 ---- .../connector/entity/FishingHookEntity.java | 14 ++++++++++++-- .../living/animal/TropicalFishEntity.java | 1 - .../living/animal/horse/TraderLlamaEntity.java | 8 ++++++++ .../entity/spawn/JavaSpawnObjectTranslator.java | 17 +++++++++++------ 6 files changed, 31 insertions(+), 14 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/entity/EnderCrystalEntity.java b/connector/src/main/java/org/geysermc/connector/entity/EnderCrystalEntity.java index 31f7b8edf..727df90c1 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/EnderCrystalEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/EnderCrystalEntity.java @@ -31,7 +31,6 @@ import com.nukkitx.math.vector.Vector3f; import com.nukkitx.math.vector.Vector3i; import com.nukkitx.protocol.bedrock.data.EntityData; import com.nukkitx.protocol.bedrock.data.EntityFlag; -import com.nukkitx.protocol.bedrock.packet.AddEntityPacket; import org.geysermc.connector.entity.type.EntityType; import org.geysermc.connector.network.session.GeyserSession; diff --git a/connector/src/main/java/org/geysermc/connector/entity/ExpOrbEntity.java b/connector/src/main/java/org/geysermc/connector/entity/ExpOrbEntity.java index 2fd06c234..bfd3e1cae 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/ExpOrbEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/ExpOrbEntity.java @@ -27,13 +27,9 @@ package org.geysermc.connector.entity; import com.nukkitx.math.vector.Vector3f; import com.nukkitx.protocol.bedrock.data.EntityData; -import com.nukkitx.protocol.bedrock.packet.SetEntityMotionPacket; import org.geysermc.connector.entity.type.EntityType; import org.geysermc.connector.network.session.GeyserSession; -import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.TimeUnit; - public class ExpOrbEntity extends Entity { private int amount; diff --git a/connector/src/main/java/org/geysermc/connector/entity/FishingHookEntity.java b/connector/src/main/java/org/geysermc/connector/entity/FishingHookEntity.java index e82a42a24..abd522929 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/FishingHookEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/FishingHookEntity.java @@ -25,13 +25,23 @@ package org.geysermc.connector.entity; +import com.github.steveice10.mc.protocol.data.game.entity.type.object.ProjectileData; import com.nukkitx.math.vector.Vector3f; -import com.nukkitx.protocol.bedrock.packet.AddEntityPacket; +import com.nukkitx.protocol.bedrock.data.EntityData; +import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.entity.type.EntityType; import org.geysermc.connector.network.session.GeyserSession; public class FishingHookEntity extends Entity { - public FishingHookEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { + public FishingHookEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation, ProjectileData data) { super(entityId, geyserId, entityType, position, motion, rotation); + + // TODO: Find a better way to do this + for (GeyserSession session : GeyserConnector.getInstance().getPlayers().values()) { + if (session.getPlayerEntity().getEntityId() == data.getOwnerId()) { + this.metadata.put(EntityData.OWNER_EID, session.getPlayerEntity().getGeyserId()); + return; + } + } } } diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/animal/TropicalFishEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/animal/TropicalFishEntity.java index d5e9a6871..a8866d7ec 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/living/animal/TropicalFishEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/living/animal/TropicalFishEntity.java @@ -28,7 +28,6 @@ package org.geysermc.connector.entity.living.animal; import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata; import com.nukkitx.math.vector.Vector3f; import com.nukkitx.protocol.bedrock.data.EntityData; -import com.nukkitx.protocol.bedrock.packet.AddEntityPacket; import lombok.AllArgsConstructor; import lombok.Getter; import org.geysermc.connector.entity.living.AbstractFishEntity; diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/animal/horse/TraderLlamaEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/animal/horse/TraderLlamaEntity.java index 08a718367..b9505509f 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/living/animal/horse/TraderLlamaEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/living/animal/horse/TraderLlamaEntity.java @@ -26,11 +26,19 @@ package org.geysermc.connector.entity.living.animal.horse; import com.nukkitx.math.vector.Vector3f; +import com.nukkitx.protocol.bedrock.data.EntityData; import org.geysermc.connector.entity.type.EntityType; +import org.geysermc.connector.network.session.GeyserSession; public class TraderLlamaEntity extends LlamaEntity { public TraderLlamaEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { super(entityId, geyserId, entityType, position, motion, rotation); } + + @Override + public void spawnEntity(GeyserSession session) { + this.metadata.put(EntityData.MARK_VARIANT, 1); + super.spawnEntity(session); + } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/spawn/JavaSpawnObjectTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/spawn/JavaSpawnObjectTranslator.java index d544e24ba..419f1e46a 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/spawn/JavaSpawnObjectTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/spawn/JavaSpawnObjectTranslator.java @@ -25,13 +25,15 @@ package org.geysermc.connector.network.translators.java.entity.spawn; -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; - import com.github.steveice10.mc.protocol.data.game.entity.type.object.FallingBlockData; import com.github.steveice10.mc.protocol.data.game.entity.type.object.HangingDirection; +import com.github.steveice10.mc.protocol.data.game.entity.type.object.ObjectType; +import com.github.steveice10.mc.protocol.data.game.entity.type.object.ProjectileData; +import com.github.steveice10.mc.protocol.packet.ingame.server.entity.spawn.ServerSpawnObjectPacket; +import com.nukkitx.math.vector.Vector3f; import org.geysermc.connector.entity.Entity; import org.geysermc.connector.entity.FallingBlockEntity; +import org.geysermc.connector.entity.FishingHookEntity; import org.geysermc.connector.entity.ItemFrameEntity; import org.geysermc.connector.entity.type.EntityType; import org.geysermc.connector.network.session.GeyserSession; @@ -39,9 +41,8 @@ import org.geysermc.connector.network.translators.PacketTranslator; import org.geysermc.connector.network.translators.Translator; import org.geysermc.connector.utils.EntityUtils; -import com.github.steveice10.mc.protocol.data.game.entity.type.object.ObjectType; -import com.github.steveice10.mc.protocol.packet.ingame.server.entity.spawn.ServerSpawnObjectPacket; -import com.nukkitx.math.vector.Vector3f; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; @Translator(packet = ServerSpawnObjectPacket.class) public class JavaSpawnObjectTranslator extends PacketTranslator { @@ -69,6 +70,10 @@ public class JavaSpawnObjectTranslator extends PacketTranslator entityConstructor = entityClass.getConstructor(long.class, long.class, EntityType.class, Vector3f.class, Vector3f.class, Vector3f.class); From 7195d20fae8dbfb1d165e3cdb0d4dbca4cc3d3d7 Mon Sep 17 00:00:00 2001 From: Luke <32024335+lukeeey@users.noreply.github.com> Date: Tue, 5 May 2020 16:51:43 +0100 Subject: [PATCH 045/140] Implement helper methods for sending packets (#487) * Implement helper methods for sending packets, fixes an NPE when chatting before connecting to the remote server * Change method names * Add a space between doc comment lines * Add debug messages --- .../command/defaults/OffhandCommand.java | 2 +- .../org/geysermc/connector/entity/Entity.java | 16 +++---- .../geysermc/connector/entity/ItemEntity.java | 2 +- .../connector/entity/ItemFrameEntity.java | 6 +-- .../connector/entity/LivingEntity.java | 6 +-- .../connector/entity/PaintingEntity.java | 2 +- .../connector/entity/PlayerEntity.java | 10 ++-- .../living/animal/horse/LlamaEntity.java | 2 +- .../living/monster/EnderDragonEntity.java | 4 +- .../network/UpstreamPacketHandler.java | 6 +-- .../network/session/GeyserSession.java | 46 ++++++++++++++++++- .../network/session/cache/BossBar.java | 12 ++--- .../network/session/cache/WindowCache.java | 4 +- .../bedrock/BedrockActionTranslator.java | 26 +++++------ .../bedrock/BedrockAnimateTranslator.java | 2 +- .../BedrockBlockEntityDataTranslator.java | 2 +- .../BedrockCommandRequestTranslator.java | 2 +- .../BedrockContainerCloseTranslator.java | 2 +- .../bedrock/BedrockEntityEventTranslator.java | 2 +- .../bedrock/BedrockInteractTranslator.java | 4 +- ...BedrockInventoryTransactionTranslator.java | 22 ++++----- .../BedrockItemFrameDropItemTranslator.java | 2 +- .../BedrockLevelSoundEventTranslator.java | 2 +- .../BedrockMobEquipmentTranslator.java | 2 +- .../bedrock/BedrockMovePlayerTranslator.java | 8 ++-- .../bedrock/BedrockRespawnTranslator.java | 4 +- .../bedrock/BedrockShowCreditsTranslator.java | 2 +- .../bedrock/BedrockTextTranslator.java | 2 +- .../inventory/AnvilInventoryTranslator.java | 4 +- .../inventory/BrewingInventoryTranslator.java | 4 +- .../CraftingInventoryTranslator.java | 2 +- .../DoubleChestInventoryTranslator.java | 14 +++--- .../inventory/FurnaceInventoryTranslator.java | 2 +- .../inventory/PlayerInventoryTranslator.java | 17 ++++--- .../inventory/action/ClickPlan.java | 4 +- .../action/InventoryActionDataTranslator.java | 12 ++--- .../holder/BlockInventoryHolder.java | 8 ++-- .../updater/ChestInventoryUpdater.java | 4 +- .../updater/ContainerInventoryUpdater.java | 4 +- .../updater/CursorInventoryUpdater.java | 4 +- .../inventory/updater/InventoryUpdater.java | 4 +- .../translators/java/JavaChatTranslator.java | 2 +- .../java/JavaDeclareRecipesTranslator.java | 2 +- .../java/JavaDifficultyTranslator.java | 2 +- .../java/JavaJoinGameTranslator.java | 10 ++-- .../JavaLoginPluginMessageTranslator.java | 2 +- .../java/JavaPluginMessageTranslator.java | 2 +- .../java/JavaRespawnTranslator.java | 4 +- .../JavaServerDeclareCommandsTranslator.java | 2 +- .../translators/java/JavaTitleTranslator.java | 2 +- .../entity/JavaEntityAnimationTranslator.java | 2 +- .../entity/JavaEntityEffectTranslator.java | 2 +- .../entity/JavaEntityHeadLookTranslator.java | 4 +- .../JavaEntityRemoveEffectTranslator.java | 2 +- .../entity/JavaEntityRotationTranslator.java | 4 +- .../entity/JavaEntityStatusTranslator.java | 2 +- .../entity/JavaEntityVelocityTranslator.java | 2 +- .../player/JavaPlayerAbilitiesTranslator.java | 4 +- .../player/JavaPlayerActionAckTranslator.java | 6 +-- .../JavaPlayerChangeHeldItemTranslator.java | 2 +- .../player/JavaPlayerHealthTranslator.java | 2 +- .../player/JavaPlayerListEntryTranslator.java | 2 +- .../JavaPlayerPositionRotationTranslator.java | 12 ++--- .../player/JavaPlayerStopSoundTranslator.java | 2 +- .../window/JavaCloseWindowTranslator.java | 2 +- .../JavaConfirmTransactionTranslator.java | 5 +- .../java/window/JavaOpenWindowTranslator.java | 4 +- .../java/world/JavaBlockChangeTranslator.java | 2 +- .../java/world/JavaBlockValueTranslator.java | 14 +++--- .../java/world/JavaChunkDataTranslator.java | 2 +- .../java/world/JavaCollectItemTranslator.java | 2 +- .../java/world/JavaExplosionTranslator.java | 5 +- .../world/JavaNotifyClientTranslator.java | 14 +++--- .../world/JavaPlayBuiltinSoundTranslator.java | 4 +- .../java/world/JavaPlayEffectTranslator.java | 12 ++--- .../world/JavaPlayerPlaySoundTranslator.java | 2 +- .../world/JavaSpawnParticleTranslator.java | 12 ++--- .../world/JavaSpawnPositionTranslator.java | 2 +- .../java/world/JavaUpdateTimeTranslator.java | 4 +- .../block/BucketSoundInteractionHandler.java | 2 +- .../block/ComparatorSoundInteractHandler.java | 2 +- .../block/DoorSoundInteractionHandler.java | 2 +- .../FlintAndSteelInteractionHandler.java | 2 +- .../block/GrassPathInteractionHandler.java | 2 +- .../sound/block/HoeInteractionHandler.java | 2 +- .../block/LeverSoundInteractionHandler.java | 2 +- .../MilkCowSoundInteractionHandler.java | 2 +- .../FlowerPotBlockEntityTranslator.java | 2 +- .../NoteblockBlockEntityTranslator.java | 2 +- .../connector/scoreboard/Scoreboard.java | 12 ++--- .../connector/utils/BlockEntityUtils.java | 2 +- .../geysermc/connector/utils/ChunkUtils.java | 10 ++-- .../connector/utils/DimensionUtils.java | 4 +- .../connector/utils/InventoryUtils.java | 2 +- .../connector/utils/LoginEncryptionUtils.java | 4 +- .../geysermc/connector/utils/SkinUtils.java | 4 +- 96 files changed, 270 insertions(+), 235 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/command/defaults/OffhandCommand.java b/connector/src/main/java/org/geysermc/connector/command/defaults/OffhandCommand.java index d181d07e2..5392baedd 100644 --- a/connector/src/main/java/org/geysermc/connector/command/defaults/OffhandCommand.java +++ b/connector/src/main/java/org/geysermc/connector/command/defaults/OffhandCommand.java @@ -55,7 +55,7 @@ public class OffhandCommand extends GeyserCommand { GeyserSession session = (GeyserSession) sender; ClientPlayerActionPacket releaseItemPacket = new ClientPlayerActionPacket(PlayerAction.SWAP_HANDS, new Position(0,0,0), BlockFace.DOWN); - session.getDownstream().getSession().send(releaseItemPacket); + session.sendDownstreamPacket(releaseItemPacket); } } } diff --git a/connector/src/main/java/org/geysermc/connector/entity/Entity.java b/connector/src/main/java/org/geysermc/connector/entity/Entity.java index 7e8a190d5..186c0ae8f 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/Entity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/Entity.java @@ -119,7 +119,7 @@ public class Entity { addEntityPacket.getMetadata().putAll(metadata); valid = true; - session.getUpstream().sendPacket(addEntityPacket); + session.sendUpstreamPacket(addEntityPacket); session.getConnector().getLogger().debug("Spawned entity " + entityType + " at location " + position + " with id " + geyserId + " (java id " + entityId + ")"); } @@ -135,7 +135,7 @@ public class Entity { RemoveEntityPacket removeEntityPacket = new RemoveEntityPacket(); removeEntityPacket.setUniqueEntityId(geyserId); - session.getUpstream().sendPacket(removeEntityPacket); + session.sendUpstreamPacket(removeEntityPacket); valid = false; return true; @@ -156,7 +156,7 @@ public class Entity { moveEntityPacket.setOnGround(isOnGround); moveEntityPacket.setTeleported(false); - session.getUpstream().sendPacket(moveEntityPacket); + session.sendUpstreamPacket(moveEntityPacket); } public void moveAbsolute(GeyserSession session, Vector3f position, float yaw, float pitch, boolean isOnGround, boolean teleported) { @@ -174,7 +174,7 @@ public class Entity { moveEntityPacket.setOnGround(isOnGround); moveEntityPacket.setTeleported(teleported); - session.getUpstream().sendPacket(moveEntityPacket); + session.sendUpstreamPacket(moveEntityPacket); } public void updateBedrockAttributes(GeyserSession session) { @@ -191,7 +191,7 @@ public class Entity { UpdateAttributesPacket updateAttributesPacket = new UpdateAttributesPacket(); updateAttributesPacket.setRuntimeEntityId(geyserId); updateAttributesPacket.setAttributes(attributes); - session.getUpstream().sendPacket(updateAttributesPacket); + session.sendUpstreamPacket(updateAttributesPacket); } public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { @@ -218,13 +218,13 @@ public class Entity { else { useItemPacket = new ClientPlayerUseItemPacket(Hand.OFF_HAND); } - session.getDownstream().getSession().send(useItemPacket); + session.sendDownstreamPacket(useItemPacket); } } else if (session.getPlayerEntity().getEntityId() == entityId && !metadata.getFlags().getFlag(EntityFlag.SNEAKING) && metadata.getFlags().getFlag(EntityFlag.BLOCKING)) { metadata.getFlags().setFlag(EntityFlag.BLOCKING, false); metadata.getFlags().setFlag(EntityFlag.DISABLE_BLOCKING, true); ClientPlayerActionPacket releaseItemPacket = new ClientPlayerActionPacket(PlayerAction.RELEASE_USE_ITEM, new Position(0,0,0), BlockFace.DOWN); - session.getDownstream().getSession().send(releaseItemPacket); + session.sendDownstreamPacket(releaseItemPacket); } // metadata.getFlags().setFlag(EntityFlag.INVISIBLE, (xd & 0x20) == 0x20); if ((xd & 0x20) == 0x20) @@ -265,7 +265,7 @@ public class Entity { SetEntityDataPacket entityDataPacket = new SetEntityDataPacket(); entityDataPacket.setRuntimeEntityId(geyserId); entityDataPacket.getMetadata().putAll(metadata); - session.getUpstream().sendPacket(entityDataPacket); + session.sendUpstreamPacket(entityDataPacket); } /** diff --git a/connector/src/main/java/org/geysermc/connector/entity/ItemEntity.java b/connector/src/main/java/org/geysermc/connector/entity/ItemEntity.java index a28b563b4..b321213e1 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/ItemEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/ItemEntity.java @@ -50,7 +50,7 @@ public class ItemEntity extends Entity { itemPacket.setFromFishing(false); itemPacket.getMetadata().putAll(metadata); itemPacket.setItemInHand(Translators.getItemTranslator().translateToBedrock(session, (ItemStack) entityMetadata.getValue())); - session.getUpstream().sendPacket(itemPacket); + session.sendUpstreamPacket(itemPacket); } super.updateBedrockMetadata(entityMetadata, session); diff --git a/connector/src/main/java/org/geysermc/connector/entity/ItemFrameEntity.java b/connector/src/main/java/org/geysermc/connector/entity/ItemFrameEntity.java index d49f6e17c..16942898d 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/ItemFrameEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/ItemFrameEntity.java @@ -149,7 +149,7 @@ public class ItemFrameEntity extends Entity { updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.PRIORITY); updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NONE); updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NEIGHBORS); - session.getUpstream().sendPacket(updateBlockPacket); + session.sendUpstreamPacket(updateBlockPacket); session.getItemFrameCache().remove(position, entityId); valid = false; return true; @@ -179,7 +179,7 @@ public class ItemFrameEntity extends Entity { updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.PRIORITY); updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NONE); updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NEIGHBORS); - session.getUpstream().sendPacket(updateBlockPacket); + session.sendUpstreamPacket(updateBlockPacket); BlockEntityDataPacket blockEntityDataPacket = new BlockEntityDataPacket(); blockEntityDataPacket.setBlockPosition(bedrockPosition); @@ -189,7 +189,7 @@ public class ItemFrameEntity extends Entity { blockEntityDataPacket.setData(getDefaultTag()); } - session.getUpstream().sendPacket(blockEntityDataPacket); + session.sendUpstreamPacket(blockEntityDataPacket); }, 500, TimeUnit.MILLISECONDS); } diff --git a/connector/src/main/java/org/geysermc/connector/entity/LivingEntity.java b/connector/src/main/java/org/geysermc/connector/entity/LivingEntity.java index 40b30f704..f5aa4a544 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/LivingEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/LivingEntity.java @@ -96,8 +96,8 @@ public class LivingEntity extends Entity { offHandPacket.setInventorySlot(0); offHandPacket.setContainerId(ContainerId.OFFHAND); - session.getUpstream().sendPacket(armorEquipmentPacket); - session.getUpstream().sendPacket(handPacket); - session.getUpstream().sendPacket(offHandPacket); + session.sendUpstreamPacket(armorEquipmentPacket); + session.sendUpstreamPacket(handPacket); + session.sendUpstreamPacket(offHandPacket); } } diff --git a/connector/src/main/java/org/geysermc/connector/entity/PaintingEntity.java b/connector/src/main/java/org/geysermc/connector/entity/PaintingEntity.java index 87ff9a357..56e077339 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/PaintingEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/PaintingEntity.java @@ -55,7 +55,7 @@ public class PaintingEntity extends Entity { addPaintingPacket.setName(paintingName.getBedrockName()); addPaintingPacket.setPosition(fixOffset(true)); addPaintingPacket.setDirection(direction); - session.getUpstream().sendPacket(addPaintingPacket); + session.sendUpstreamPacket(addPaintingPacket); valid = true; diff --git a/connector/src/main/java/org/geysermc/connector/entity/PlayerEntity.java b/connector/src/main/java/org/geysermc/connector/entity/PlayerEntity.java index d47321683..82e91f553 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/PlayerEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/PlayerEntity.java @@ -94,7 +94,7 @@ public class PlayerEntity extends LivingEntity { addPlayerPacket.getMetadata().putAll(metadata); valid = true; - session.getUpstream().sendPacket(addPlayerPacket); + session.sendUpstreamPacket(addPlayerPacket); updateEquipment(session); updateBedrockAttributes(session); @@ -108,7 +108,7 @@ public class PlayerEntity extends LivingEntity { PlayerListPacket playerList = new PlayerListPacket(); playerList.setAction(PlayerListPacket.Action.ADD); playerList.getEntries().add(SkinUtils.buildDefaultEntry(profile, geyserId)); - session.getUpstream().sendPacket(playerList); + session.sendUpstreamPacket(playerList); } } @@ -124,7 +124,7 @@ public class PlayerEntity extends LivingEntity { PlayerListPacket playerList = new PlayerListPacket(); playerList.setAction(PlayerListPacket.Action.REMOVE); playerList.getEntries().add(new PlayerListPacket.Entry(uuid)); - session.getUpstream().sendPacket(playerList); + session.sendUpstreamPacket(playerList); }); } } @@ -145,7 +145,7 @@ public class PlayerEntity extends LivingEntity { movePlayerPacket.setTeleportationCause(MovePlayerPacket.TeleportationCause.UNKNOWN); } - session.getUpstream().sendPacket(movePlayerPacket); + session.sendUpstreamPacket(movePlayerPacket); } @Override @@ -159,7 +159,7 @@ public class PlayerEntity extends LivingEntity { movePlayerPacket.setRotation(getBedrockRotation()); movePlayerPacket.setOnGround(isOnGround); movePlayerPacket.setMode(MovePlayerPacket.Mode.NORMAL); - session.getUpstream().sendPacket(movePlayerPacket); + session.sendUpstreamPacket(movePlayerPacket); } @Override diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/animal/horse/LlamaEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/animal/horse/LlamaEntity.java index c2dad7a57..d4d7b7262 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/living/animal/horse/LlamaEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/living/animal/horse/LlamaEntity.java @@ -65,7 +65,7 @@ public class LlamaEntity extends ChestedHorseEntity { equipmentPacket.setHelmet(ItemData.AIR); equipmentPacket.setLeggings(ItemData.AIR); - session.getUpstream().sendPacket(equipmentPacket); + session.sendUpstreamPacket(equipmentPacket); } // Color of the llama if (entityMetadata.getId() == 21) { diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/monster/EnderDragonEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/monster/EnderDragonEntity.java index b07377389..394be544b 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/living/monster/EnderDragonEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/living/monster/EnderDragonEntity.java @@ -53,7 +53,7 @@ public class EnderDragonEntity extends InsentientEntity { entityEventPacket.setType(EntityEventType.DRAGON_FLAMING); entityEventPacket.setRuntimeEntityId(geyserId); entityEventPacket.setData(0); - session.getUpstream().sendPacket(entityEventPacket); + session.sendUpstreamPacket(entityEventPacket); case 6: case 7: metadata.getFlags().setFlag(EntityFlag.SITTING, true); @@ -79,7 +79,7 @@ public class EnderDragonEntity extends InsentientEntity { addEntityPacket.getAttributes().add(new Attribute("minecraft:health", 0.0f, 200f, 200f, 200f)); valid = true; - session.getUpstream().sendPacket(addEntityPacket); + session.sendUpstreamPacket(addEntityPacket); session.getConnector().getLogger().debug("Spawned entity " + entityType + " at location " + position + " with id " + geyserId + " (java id " + entityId + ")"); } diff --git a/connector/src/main/java/org/geysermc/connector/network/UpstreamPacketHandler.java b/connector/src/main/java/org/geysermc/connector/network/UpstreamPacketHandler.java index 2839237e3..dfc3112b5 100644 --- a/connector/src/main/java/org/geysermc/connector/network/UpstreamPacketHandler.java +++ b/connector/src/main/java/org/geysermc/connector/network/UpstreamPacketHandler.java @@ -58,10 +58,10 @@ public class UpstreamPacketHandler extends LoggingPacketHandler { PlayStatusPacket playStatus = new PlayStatusPacket(); playStatus.setStatus(PlayStatusPacket.Status.LOGIN_SUCCESS); - session.getUpstream().sendPacket(playStatus); + session.sendUpstreamPacket(playStatus); ResourcePacksInfoPacket resourcePacksInfo = new ResourcePacksInfoPacket(); - session.getUpstream().sendPacket(resourcePacksInfo); + session.sendUpstreamPacket(resourcePacksInfo); return true; } @@ -77,7 +77,7 @@ public class UpstreamPacketHandler extends LoggingPacketHandler { stack.setExperimental(false); stack.setForcedToAccept(false); stack.setGameVersion("*"); - session.getUpstream().sendPacket(stack); + session.sendUpstreamPacket(stack); break; default: session.disconnect("disconnectionScreen.resourcePack"); diff --git a/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java b/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java index 51cc09239..9068456c1 100644 --- a/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java +++ b/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java @@ -29,6 +29,7 @@ import com.github.steveice10.mc.auth.data.GameProfile; import com.github.steveice10.mc.auth.exception.request.InvalidCredentialsException; import com.github.steveice10.mc.auth.exception.request.RequestException; import com.github.steveice10.mc.protocol.MinecraftProtocol; +import com.github.steveice10.mc.protocol.data.SubProtocol; import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode; import com.github.steveice10.mc.protocol.packet.ingame.client.world.ClientTeleportConfirmPacket; import com.github.steveice10.mc.protocol.data.game.world.block.BlockState; @@ -41,6 +42,7 @@ import com.github.steveice10.packetlib.tcp.TcpSessionFactory; import com.nukkitx.math.GenericMath; import com.nukkitx.math.TrigMath; import com.nukkitx.math.vector.*; +import com.nukkitx.protocol.bedrock.BedrockPacket; import com.nukkitx.protocol.bedrock.BedrockServerSession; import com.nukkitx.protocol.bedrock.data.ContainerId; import com.nukkitx.protocol.bedrock.data.GamePublishSetting; @@ -156,6 +158,8 @@ public class GeyserSession implements CommandSender { @Setter private int craftSlot = 0; + private MinecraftProtocol protocol; + public GeyserSession(GeyserConnector connector, BedrockServerSession bedrockServerSession) { this.connector = connector; this.upstream = new UpstreamSession(bedrockServerSession); @@ -227,7 +231,6 @@ public class GeyserSession implements CommandSender { // new thread so clients don't timeout new Thread(() -> { try { - MinecraftProtocol protocol; if (password != null && !password.isEmpty()) { protocol = new MinecraftProtocol(username, password); } else { @@ -481,8 +484,47 @@ public class GeyserSession implements CommandSender { int teleportId = teleportCache.getTeleportConfirmId(); teleportCache = null; ClientTeleportConfirmPacket teleportConfirmPacket = new ClientTeleportConfirmPacket(teleportId); - getDownstream().getSession().send(teleportConfirmPacket); + sendDownstreamPacket(teleportConfirmPacket); } return true; } + + /** + * Queue a packet to be sent to player. + * + * @param packet the bedrock packet from the NukkitX protocol lib + */ + public void sendUpstreamPacket(BedrockPacket packet) { + if (upstream != null && !upstream.isClosed()) { + upstream.sendPacket(packet); + } else { + connector.getLogger().debug("Tried to send upstream packet " + packet.getClass().getSimpleName() + " but the session was null"); + } + } + + /** + * Send a packet immediately to the player. + * + * @param packet the bedrock packet from the NukkitX protocol lib + */ + public void sendUpstreamPacketImmediately(BedrockPacket packet) { + if (upstream != null && !upstream.isClosed()) { + upstream.sendPacketImmediately(packet); + } else { + connector.getLogger().debug("Tried to send upstream packet " + packet.getClass().getSimpleName() + " immediately but the session was null"); + } + } + + /** + * Send a packet to the remote server. + * + * @param packet the java edition packet from MCProtocolLib + */ + public void sendDownstreamPacket(Packet packet) { + if (downstream != null && downstream.getSession() != null && protocol.getSubProtocol().equals(SubProtocol.GAME)) { + downstream.getSession().send(packet); + } else { + connector.getLogger().debug("Tried to send downstream packet " + packet.getClass().getSimpleName() + " before connected to the server"); + } + } } diff --git a/connector/src/main/java/org/geysermc/connector/network/session/cache/BossBar.java b/connector/src/main/java/org/geysermc/connector/network/session/cache/BossBar.java index abb9016a2..1fde179dc 100644 --- a/connector/src/main/java/org/geysermc/connector/network/session/cache/BossBar.java +++ b/connector/src/main/java/org/geysermc/connector/network/session/cache/BossBar.java @@ -62,7 +62,7 @@ public class BossBar { bossEventPacket.setOverlay(overlay); bossEventPacket.setDarkenSky(darkenSky); - session.getUpstream().sendPacket(bossEventPacket); + session.sendUpstreamPacket(bossEventPacket); } public void updateTitle(Message title) { @@ -72,7 +72,7 @@ public class BossBar { bossEventPacket.setAction(BossEventPacket.Action.TITLE); bossEventPacket.setTitle(MessageUtils.getTranslatedBedrockMessage(title, session.getClientData().getLanguageCode())); - session.getUpstream().sendPacket(bossEventPacket); + session.sendUpstreamPacket(bossEventPacket); } public void updateHealth(float health) { @@ -82,7 +82,7 @@ public class BossBar { bossEventPacket.setAction(BossEventPacket.Action.HEALTH_PERCENTAGE); bossEventPacket.setHealthPercentage(health); - session.getUpstream().sendPacket(bossEventPacket); + session.sendUpstreamPacket(bossEventPacket); } public void removeBossBar() { @@ -90,7 +90,7 @@ public class BossBar { bossEventPacket.setBossUniqueEntityId(entityId); bossEventPacket.setAction(BossEventPacket.Action.HIDE); - session.getUpstream().sendPacket(bossEventPacket); + session.sendUpstreamPacket(bossEventPacket); removeBossEntity(); } @@ -109,13 +109,13 @@ public class BossBar { addEntityPacket.setMotion(Vector3f.ZERO); addEntityPacket.getMetadata().put(EntityData.SCALE, 0.01F); // scale = 0 doesn't work? - session.getUpstream().sendPacket(addEntityPacket); + session.sendUpstreamPacket(addEntityPacket); } private void removeBossEntity() { RemoveEntityPacket removeEntityPacket = new RemoveEntityPacket(); removeEntityPacket.setUniqueEntityId(entityId); - session.getUpstream().sendPacket(removeEntityPacket); + session.sendUpstreamPacket(removeEntityPacket); } } diff --git a/connector/src/main/java/org/geysermc/connector/network/session/cache/WindowCache.java b/connector/src/main/java/org/geysermc/connector/network/session/cache/WindowCache.java index 1d10e4db9..15b9a7705 100644 --- a/connector/src/main/java/org/geysermc/connector/network/session/cache/WindowCache.java +++ b/connector/src/main/java/org/geysermc/connector/network/session/cache/WindowCache.java @@ -66,7 +66,7 @@ public class WindowCache { formRequestPacket.setFormId(id); formRequestPacket.setFormData(windows.get(id).getJSONData()); - session.getUpstream().sendPacket(formRequestPacket); + session.sendUpstreamPacket(formRequestPacket); } public void showWindow(FormWindow window, int id) { @@ -74,7 +74,7 @@ public class WindowCache { formRequestPacket.setFormId(id); formRequestPacket.setFormData(window.getJSONData()); - session.getUpstream().sendPacket(formRequestPacket); + session.sendUpstreamPacket(formRequestPacket); addWindow(window, id); } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockActionTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockActionTranslator.java index d7248aa36..2c44e4fdb 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockActionTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockActionTranslator.java @@ -64,44 +64,44 @@ public class BedrockActionTranslator extends PacketTranslator { case SWING_ARM: // Delay so entity damage can be processed first session.getConnector().getGeneralThreadPool().schedule(() -> - session.getDownstream().getSession().send(new ClientPlayerSwingArmPacket(Hand.MAIN_HAND)), + session.sendDownstreamPacket(new ClientPlayerSwingArmPacket(Hand.MAIN_HAND)), 25, TimeUnit.MILLISECONDS ); diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockBlockEntityDataTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockBlockEntityDataTranslator.java index dc076a910..9fe62bb44 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockBlockEntityDataTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockBlockEntityDataTranslator.java @@ -79,7 +79,7 @@ public class BedrockBlockEntityDataTranslator extends PacketTranslator } ClientPlayerInteractEntityPacket interactPacket = new ClientPlayerInteractEntityPacket((int) entity.getEntityId(), InteractAction.INTERACT, Hand.MAIN_HAND); - session.getDownstream().getSession().send(interactPacket); + session.sendDownstreamPacket(interactPacket); break; case DAMAGE: ClientPlayerInteractEntityPacket attackPacket = new ClientPlayerInteractEntityPacket((int) entity.getEntityId(), InteractAction.ATTACK, Hand.MAIN_HAND); - session.getDownstream().getSession().send(attackPacket); + session.sendDownstreamPacket(attackPacket); break; } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockInventoryTransactionTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockInventoryTransactionTranslator.java index ed9289599..71ba20e48 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockInventoryTransactionTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockInventoryTransactionTranslator.java @@ -84,8 +84,8 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator { respawnPacket.setRuntimeEntityId(0); respawnPacket.setPosition(Vector3f.ZERO); respawnPacket.setState(RespawnPacket.State.SERVER_SEARCHING); - session.getUpstream().sendPacket(respawnPacket); + session.sendUpstreamPacket(respawnPacket); ClientRequestPacket javaRespawnPacket = new ClientRequestPacket(ClientRequest.RESPAWN); - session.getDownstream().getSession().send(javaRespawnPacket); + session.sendDownstreamPacket(javaRespawnPacket); } } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockShowCreditsTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockShowCreditsTranslator.java index 161397b66..4f0af78c6 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockShowCreditsTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockShowCreditsTranslator.java @@ -40,7 +40,7 @@ public class BedrockShowCreditsTranslator extends PacketTranslator { } ClientChatPacket chatPacket = new ClientChatPacket(message); - session.getDownstream().getSession().send(chatPacket); + session.sendDownstreamPacket(chatPacket); } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/AnvilInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/AnvilInventoryTranslator.java index 8df72d362..f301d2b5d 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/AnvilInventoryTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/AnvilInventoryTranslator.java @@ -108,7 +108,7 @@ public class AnvilInventoryTranslator extends BlockInventoryTranslator { rename = ""; } ClientRenameItemPacket renameItemPacket = new ClientRenameItemPacket(rename); - session.getDownstream().getSession().send(renameItemPacket); + session.sendDownstreamPacket(renameItemPacket); } if (anvilResult != null) { //client will send another packet to grab anvil output @@ -138,7 +138,7 @@ public class AnvilInventoryTranslator extends BlockInventoryTranslator { rename = ""; } ClientRenameItemPacket renameItemPacket = new ClientRenameItemPacket(rename); - session.getDownstream().getSession().send(renameItemPacket); + session.sendDownstreamPacket(renameItemPacket); } } super.updateSlot(session, inventory, slot); diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/BrewingInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/BrewingInventoryTranslator.java index bd143698f..acda7c918 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/BrewingInventoryTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/BrewingInventoryTranslator.java @@ -44,7 +44,7 @@ public class BrewingInventoryTranslator extends BlockInventoryTranslator { dataPacket.setWindowId((byte) inventory.getId()); dataPacket.setProperty(ContainerSetDataPacket.BREWING_STAND_FUEL_TOTAL); dataPacket.setValue(20); - session.getUpstream().sendPacket(dataPacket); + session.sendUpstreamPacket(dataPacket); } @Override @@ -62,7 +62,7 @@ public class BrewingInventoryTranslator extends BlockInventoryTranslator { return; } dataPacket.setValue(value); - session.getUpstream().sendPacket(dataPacket); + session.sendUpstreamPacket(dataPacket); } @Override diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/CraftingInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/CraftingInventoryTranslator.java index 92a1d90ec..3f887001f 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/CraftingInventoryTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/CraftingInventoryTranslator.java @@ -59,7 +59,7 @@ public class CraftingInventoryTranslator extends BaseInventoryTranslator { containerOpenPacket.setType((byte) ContainerType.WORKBENCH.id()); containerOpenPacket.setBlockPosition(inventory.getHolderPosition()); containerOpenPacket.setUniqueEntityId(inventory.getHolderId()); - session.getUpstream().sendPacket(containerOpenPacket); + session.sendUpstreamPacket(containerOpenPacket); } @Override diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/DoubleChestInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/DoubleChestInventoryTranslator.java index 720280b47..8c5b2cf20 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/DoubleChestInventoryTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/DoubleChestInventoryTranslator.java @@ -60,7 +60,7 @@ public class DoubleChestInventoryTranslator extends BaseInventoryTranslator { blockPacket.setBlockPosition(position); blockPacket.setRuntimeId(blockId); blockPacket.getFlags().addAll(UpdateBlockPacket.FLAG_ALL_PRIORITY); - session.getUpstream().sendPacket(blockPacket); + session.sendUpstreamPacket(blockPacket); CompoundTag tag = CompoundTag.builder() .stringTag("id", "Chest") @@ -73,14 +73,14 @@ public class DoubleChestInventoryTranslator extends BaseInventoryTranslator { BlockEntityDataPacket dataPacket = new BlockEntityDataPacket(); dataPacket.setData(tag); dataPacket.setBlockPosition(position); - session.getUpstream().sendPacket(dataPacket); + session.sendUpstreamPacket(dataPacket); blockPacket = new UpdateBlockPacket(); blockPacket.setDataLayer(0); blockPacket.setBlockPosition(pairPosition); blockPacket.setRuntimeId(blockId); blockPacket.getFlags().addAll(UpdateBlockPacket.FLAG_ALL_PRIORITY); - session.getUpstream().sendPacket(blockPacket); + session.sendUpstreamPacket(blockPacket); tag = CompoundTag.builder() .stringTag("id", "Chest") @@ -93,7 +93,7 @@ public class DoubleChestInventoryTranslator extends BaseInventoryTranslator { dataPacket = new BlockEntityDataPacket(); dataPacket.setData(tag); dataPacket.setBlockPosition(pairPosition); - session.getUpstream().sendPacket(dataPacket); + session.sendUpstreamPacket(dataPacket); inventory.setHolderPosition(position); } @@ -105,7 +105,7 @@ public class DoubleChestInventoryTranslator extends BaseInventoryTranslator { containerOpenPacket.setType((byte) ContainerType.CONTAINER.id()); containerOpenPacket.setBlockPosition(inventory.getHolderPosition()); containerOpenPacket.setUniqueEntityId(inventory.getHolderId()); - session.getUpstream().sendPacket(containerOpenPacket); + session.sendUpstreamPacket(containerOpenPacket); } @Override @@ -117,7 +117,7 @@ public class DoubleChestInventoryTranslator extends BaseInventoryTranslator { blockPacket.setDataLayer(0); blockPacket.setBlockPosition(holderPos); blockPacket.setRuntimeId(BlockTranslator.getBedrockBlockId(realBlock)); - session.getUpstream().sendPacket(blockPacket); + session.sendUpstreamPacket(blockPacket); holderPos = holderPos.add(Vector3i.UNIT_X); pos = new Position(holderPos.getX(), holderPos.getY(), holderPos.getZ()); @@ -126,7 +126,7 @@ public class DoubleChestInventoryTranslator extends BaseInventoryTranslator { blockPacket.setDataLayer(0); blockPacket.setBlockPosition(holderPos); blockPacket.setRuntimeId(BlockTranslator.getBedrockBlockId(realBlock)); - session.getUpstream().sendPacket(blockPacket); + session.sendUpstreamPacket(blockPacket); } @Override diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/FurnaceInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/FurnaceInventoryTranslator.java index 9b45201ed..5c6de0e8a 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/FurnaceInventoryTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/FurnaceInventoryTranslator.java @@ -58,7 +58,7 @@ public class FurnaceInventoryTranslator extends BlockInventoryTranslator { return; } dataPacket.setValue(value); - session.getUpstream().sendPacket(dataPacket); + session.sendUpstreamPacket(dataPacket); } @Override diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/PlayerInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/PlayerInventoryTranslator.java index 668612c53..b711bddc4 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/PlayerInventoryTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/PlayerInventoryTranslator.java @@ -34,7 +34,6 @@ import com.nukkitx.protocol.bedrock.data.InventorySource; import com.nukkitx.protocol.bedrock.data.ItemData; import com.nukkitx.protocol.bedrock.packet.InventoryContentPacket; import com.nukkitx.protocol.bedrock.packet.InventorySlotPacket; -import it.unimi.dsi.fastutil.longs.LongArraySet; import org.geysermc.connector.inventory.Inventory; import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.Translators; @@ -66,7 +65,7 @@ public class PlayerInventoryTranslator extends InventoryTranslator { contents[i - 36] = Translators.getItemTranslator().translateToBedrock(session, inventory.getItem(i)); } inventoryContentPacket.setContents(contents); - session.getUpstream().sendPacket(inventoryContentPacket); + session.sendUpstreamPacket(inventoryContentPacket); // Armor InventoryContentPacket armorContentPacket = new InventoryContentPacket(); @@ -76,13 +75,13 @@ public class PlayerInventoryTranslator extends InventoryTranslator { contents[i - 5] = Translators.getItemTranslator().translateToBedrock(session, inventory.getItem(i)); } armorContentPacket.setContents(contents); - session.getUpstream().sendPacket(armorContentPacket); + session.sendUpstreamPacket(armorContentPacket); // Offhand InventoryContentPacket offhandPacket = new InventoryContentPacket(); offhandPacket.setContainerId(ContainerId.OFFHAND); offhandPacket.setContents(new ItemData[]{Translators.getItemTranslator().translateToBedrock(session, inventory.getItem(45))}); - session.getUpstream().sendPacket(offhandPacket); + session.sendUpstreamPacket(offhandPacket); } /** @@ -103,7 +102,7 @@ public class PlayerInventoryTranslator extends InventoryTranslator { slotPacket.setItem(Translators.getItemTranslator().translateToBedrock(session, inventory.getItem(i))); } - session.getUpstream().sendPacket(slotPacket); + session.sendUpstreamPacket(slotPacket); } } @@ -126,12 +125,12 @@ public class PlayerInventoryTranslator extends InventoryTranslator { slotPacket.setSlot(slot + 27); } slotPacket.setItem(Translators.getItemTranslator().translateToBedrock(session, inventory.getItem(slot))); - session.getUpstream().sendPacket(slotPacket); + session.sendUpstreamPacket(slotPacket); } else if (slot == 45) { InventoryContentPacket offhandPacket = new InventoryContentPacket(); offhandPacket.setContainerId(ContainerId.OFFHAND); offhandPacket.setContents(new ItemData[]{Translators.getItemTranslator().translateToBedrock(session, inventory.getItem(slot))}); - session.getUpstream().sendPacket(offhandPacket); + session.sendUpstreamPacket(offhandPacket); } } @@ -204,7 +203,7 @@ public class PlayerInventoryTranslator extends InventoryTranslator { javaItem = Translators.getItemTranslator().translateToJava(session, action.getToItem()); } ClientCreativeInventoryActionPacket creativePacket = new ClientCreativeInventoryActionPacket(javaSlot, javaItem); - session.getDownstream().getSession().send(creativePacket); + session.sendDownstreamPacket(creativePacket); inventory.setItem(javaSlot, javaItem); break; case ContainerId.CURSOR: @@ -217,7 +216,7 @@ public class PlayerInventoryTranslator extends InventoryTranslator { && action.getSource().getFlag() == InventorySource.Flag.DROP_ITEM) { javaItem = Translators.getItemTranslator().translateToJava(session, action.getToItem()); ClientCreativeInventoryActionPacket creativeDropPacket = new ClientCreativeInventoryActionPacket(-1, javaItem); - session.getDownstream().getSession().send(creativeDropPacket); + session.sendDownstreamPacket(creativeDropPacket); } break; } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/action/ClickPlan.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/action/ClickPlan.java index cdc42f961..a9c1eddca 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/action/ClickPlan.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/action/ClickPlan.java @@ -104,8 +104,8 @@ class ClickPlan { break; } } - session.getDownstream().getSession().send(clickPacket); - session.getDownstream().getSession().send(new ClientConfirmTransactionPacket(inventory.getId(), actionId, true)); + session.sendDownstreamPacket(clickPacket); + session.sendDownstreamPacket(new ClientConfirmTransactionPacket(inventory.getId(), actionId, true)); } /*if (refresh) { diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/action/InventoryActionDataTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/action/InventoryActionDataTranslator.java index 370d41777..0c2677753 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/action/InventoryActionDataTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/action/InventoryActionDataTranslator.java @@ -94,7 +94,7 @@ public class InventoryActionDataTranslator { ClientPlayerActionPacket actionPacket = new ClientPlayerActionPacket( sourceAction.getToItem().getCount() == 0 ? PlayerAction.DROP_ITEM_STACK : PlayerAction.DROP_ITEM, new Position(0, 0, 0), BlockFace.DOWN); - session.getDownstream().getSession().send(actionPacket); + session.sendDownstreamPacket(actionPacket); ItemStack item = session.getInventory().getItem(heldSlot); if (item != null) { session.getInventory().setItem(heldSlot, new ItemStack(item.getId(), item.getAmount() - 1, item.getNbt())); @@ -110,14 +110,14 @@ public class InventoryActionDataTranslator { inventory.getTransactionId().getAndIncrement(), javaSlot, null, WindowAction.DROP_ITEM, DropItemParam.DROP_SELECTED_STACK); - session.getDownstream().getSession().send(dropPacket); + session.sendDownstreamPacket(dropPacket); } else { for (int i = 0; i < dropAmount; i++) { ClientWindowActionPacket dropPacket = new ClientWindowActionPacket(inventory.getId(), inventory.getTransactionId().getAndIncrement(), javaSlot, null, WindowAction.DROP_ITEM, DropItemParam.DROP_FROM_SELECTED); - session.getDownstream().getSession().send(dropPacket); + session.sendDownstreamPacket(dropPacket); } } ItemStack item = session.getInventory().getItem(javaSlot); @@ -129,7 +129,7 @@ public class InventoryActionDataTranslator { ClientWindowActionPacket dropPacket = new ClientWindowActionPacket(inventory.getId(), inventory.getTransactionId().getAndIncrement(), -999, null, WindowAction.CLICK_ITEM, dropAmount > 1 ? ClickItemParam.LEFT_CLICK : ClickItemParam.RIGHT_CLICK); - session.getDownstream().getSession().send(dropPacket); + session.sendDownstreamPacket(dropPacket); ItemStack cursor = session.getInventory().getCursor(); if (cursor != null) { session.getInventory().setCursor(new ItemStack(cursor.getId(), dropAmount > 1 ? 0 : cursor.getAmount() - 1, cursor.getNbt())); @@ -180,7 +180,7 @@ public class InventoryActionDataTranslator { inventory.getTransactionId().getAndIncrement(), javaSlot, InventoryUtils.REFRESH_ITEM, WindowAction.SHIFT_CLICK_ITEM, ShiftClickItemParam.LEFT_CLICK); - session.getDownstream().getSession().send(shiftClickPacket); + session.sendDownstreamPacket(shiftClickPacket); translator.updateInventory(session, inventory); return; } @@ -266,7 +266,7 @@ public class InventoryActionDataTranslator { inventory.getTransactionId().getAndIncrement(), fromSlot, InventoryUtils.REFRESH_ITEM, WindowAction.SHIFT_CLICK_ITEM, ShiftClickItemParam.LEFT_CLICK); - session.getDownstream().getSession().send(shiftClickPacket); + session.sendDownstreamPacket(shiftClickPacket); translator.updateInventory(session, inventory); return; } else if (translator.getSlotType(fromSlot) == SlotType.OUTPUT) { diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/holder/BlockInventoryHolder.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/holder/BlockInventoryHolder.java index a6e5b2dd8..67ce2ce14 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/holder/BlockInventoryHolder.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/holder/BlockInventoryHolder.java @@ -54,7 +54,7 @@ public class BlockInventoryHolder extends InventoryHolder { blockPacket.setBlockPosition(position); blockPacket.setRuntimeId(blockId); blockPacket.getFlags().addAll(UpdateBlockPacket.FLAG_ALL_PRIORITY); - session.getUpstream().sendPacket(blockPacket); + session.sendUpstreamPacket(blockPacket); inventory.setHolderPosition(position); CompoundTag tag = CompoundTag.builder() @@ -65,7 +65,7 @@ public class BlockInventoryHolder extends InventoryHolder { BlockEntityDataPacket dataPacket = new BlockEntityDataPacket(); dataPacket.setData(tag); dataPacket.setBlockPosition(position); - session.getUpstream().sendPacket(dataPacket); + session.sendUpstreamPacket(dataPacket); } @Override @@ -75,7 +75,7 @@ public class BlockInventoryHolder extends InventoryHolder { containerOpenPacket.setType((byte) containerType.id()); containerOpenPacket.setBlockPosition(inventory.getHolderPosition()); containerOpenPacket.setUniqueEntityId(inventory.getHolderId()); - session.getUpstream().sendPacket(containerOpenPacket); + session.sendUpstreamPacket(containerOpenPacket); } @Override @@ -87,6 +87,6 @@ public class BlockInventoryHolder extends InventoryHolder { blockPacket.setDataLayer(0); blockPacket.setBlockPosition(holderPos); blockPacket.setRuntimeId(BlockTranslator.getBedrockBlockId(realBlock)); - session.getUpstream().sendPacket(blockPacket); + session.sendUpstreamPacket(blockPacket); } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/ChestInventoryUpdater.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/ChestInventoryUpdater.java index e8e0fc455..8318081df 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/ChestInventoryUpdater.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/ChestInventoryUpdater.java @@ -54,7 +54,7 @@ public class ChestInventoryUpdater extends InventoryUpdater { InventoryContentPacket contentPacket = new InventoryContentPacket(); contentPacket.setContainerId(inventory.getId()); contentPacket.setContents(bedrockItems); - session.getUpstream().sendPacket(contentPacket); + session.sendUpstreamPacket(contentPacket); } @Override @@ -66,7 +66,7 @@ public class ChestInventoryUpdater extends InventoryUpdater { slotPacket.setContainerId(inventory.getId()); slotPacket.setSlot(translator.javaSlotToBedrock(javaSlot)); slotPacket.setItem(Translators.getItemTranslator().translateToBedrock(session, inventory.getItem(javaSlot))); - session.getUpstream().sendPacket(slotPacket); + session.sendUpstreamPacket(slotPacket); return true; } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/ContainerInventoryUpdater.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/ContainerInventoryUpdater.java index d187ffd95..d25705e28 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/ContainerInventoryUpdater.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/ContainerInventoryUpdater.java @@ -46,7 +46,7 @@ public class ContainerInventoryUpdater extends InventoryUpdater { InventoryContentPacket contentPacket = new InventoryContentPacket(); contentPacket.setContainerId(inventory.getId()); contentPacket.setContents(bedrockItems); - session.getUpstream().sendPacket(contentPacket); + session.sendUpstreamPacket(contentPacket); } @Override @@ -58,7 +58,7 @@ public class ContainerInventoryUpdater extends InventoryUpdater { slotPacket.setContainerId(inventory.getId()); slotPacket.setSlot(translator.javaSlotToBedrock(javaSlot)); slotPacket.setItem(Translators.getItemTranslator().translateToBedrock(session, inventory.getItem(javaSlot))); - session.getUpstream().sendPacket(slotPacket); + session.sendUpstreamPacket(slotPacket); return true; } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/CursorInventoryUpdater.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/CursorInventoryUpdater.java index e3dc18648..6a93ecd3c 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/CursorInventoryUpdater.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/CursorInventoryUpdater.java @@ -45,7 +45,7 @@ public class CursorInventoryUpdater extends InventoryUpdater { slotPacket.setContainerId(ContainerId.CURSOR); slotPacket.setSlot(bedrockSlot); slotPacket.setItem(Translators.getItemTranslator().translateToBedrock(session, inventory.getItem(i))); - session.getUpstream().sendPacket(slotPacket); + session.sendUpstreamPacket(slotPacket); } } @@ -58,7 +58,7 @@ public class CursorInventoryUpdater extends InventoryUpdater { slotPacket.setContainerId(ContainerId.CURSOR); slotPacket.setSlot(translator.javaSlotToBedrock(javaSlot)); slotPacket.setItem(Translators.getItemTranslator().translateToBedrock(session, inventory.getItem(javaSlot))); - session.getUpstream().sendPacket(slotPacket); + session.sendUpstreamPacket(slotPacket); return true; } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/InventoryUpdater.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/InventoryUpdater.java index 2f139e27a..ebca038a2 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/InventoryUpdater.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/InventoryUpdater.java @@ -44,7 +44,7 @@ public abstract class InventoryUpdater { InventoryContentPacket contentPacket = new InventoryContentPacket(); contentPacket.setContainerId(ContainerId.INVENTORY); contentPacket.setContents(bedrockItems); - session.getUpstream().sendPacket(contentPacket); + session.sendUpstreamPacket(contentPacket); } public boolean updateSlot(InventoryTranslator translator, GeyserSession session, Inventory inventory, int javaSlot) { @@ -53,7 +53,7 @@ public abstract class InventoryUpdater { slotPacket.setContainerId(ContainerId.INVENTORY); slotPacket.setSlot(translator.javaSlotToBedrock(javaSlot)); slotPacket.setItem(Translators.getItemTranslator().translateToBedrock(session, inventory.getItem(javaSlot))); - session.getUpstream().sendPacket(slotPacket); + session.sendUpstreamPacket(slotPacket); return true; } return false; diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaChatTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaChatTranslator.java index a527866c9..53ce6811f 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaChatTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaChatTranslator.java @@ -76,6 +76,6 @@ public class JavaChatTranslator extends PacketTranslator { textPacket.setMessage(MessageUtils.getTranslatedBedrockMessage(packet.getMessage(), locale, false)); } - session.getUpstream().sendPacket(textPacket); + session.sendUpstreamPacket(textPacket); } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaDeclareRecipesTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaDeclareRecipesTranslator.java index c78493a36..b6a25e54d 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaDeclareRecipesTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaDeclareRecipesTranslator.java @@ -90,7 +90,7 @@ public class JavaDeclareRecipesTranslator extends PacketTranslator skinParts = Arrays.asList(SkinPart.values()); ClientSettingsPacket clientSettingsPacket = new ClientSettingsPacket(locale, (byte) session.getRenderDistance(), ChatVisibility.FULL, true, skinParts, Hand.MAIN_HAND); - session.getDownstream().getSession().send(clientSettingsPacket); + session.sendDownstreamPacket(clientSettingsPacket); if (DimensionUtils.javaToBedrock(packet.getDimension()) != entity.getDimension()) { DimensionUtils.switchDimension(session, packet.getDimension()); diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaLoginPluginMessageTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaLoginPluginMessageTranslator.java index 1ce17fe91..f2a2bf026 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaLoginPluginMessageTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaLoginPluginMessageTranslator.java @@ -12,7 +12,7 @@ public class JavaLoginPluginMessageTranslator extends PacketTranslator SetPlayerGameTypePacket playerGameTypePacket = new SetPlayerGameTypePacket(); playerGameTypePacket.setGamemode(packet.getGamemode().ordinal()); - session.getUpstream().sendPacket(playerGameTypePacket); + session.sendUpstreamPacket(playerGameTypePacket); session.setGameMode(packet.getGamemode()); LevelEventPacket stopRainPacket = new LevelEventPacket(); stopRainPacket.setType(LevelEventType.STOP_RAIN); stopRainPacket.setData(ThreadLocalRandom.current().nextInt(50000) + 10000); stopRainPacket.setPosition(Vector3f.ZERO); - session.getUpstream().sendPacket(stopRainPacket); + session.sendUpstreamPacket(stopRainPacket); if (entity.getDimension() != DimensionUtils.javaToBedrock(packet.getDimension())) { DimensionUtils.switchDimension(session, packet.getDimension()); diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaServerDeclareCommandsTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaServerDeclareCommandsTranslator.java index 0e329669b..6f16f8b42 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaServerDeclareCommandsTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaServerDeclareCommandsTranslator.java @@ -100,7 +100,7 @@ public class JavaServerDeclareCommandsTranslator extends PacketTranslator { break; } - session.getUpstream().sendPacket(titlePacket); + session.sendUpstreamPacket(titlePacket); } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/JavaEntityAnimationTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/JavaEntityAnimationTranslator.java index 9d8853e75..4f2fe0225 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/JavaEntityAnimationTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/JavaEntityAnimationTranslator.java @@ -62,6 +62,6 @@ public class JavaEntityAnimationTranslator extends PacketTranslator playerFlags = new ObjectOpenHashSet<>(); playerFlags.add(AdventureSettingsPacket.Flag.AUTO_JUMP); @@ -73,6 +73,6 @@ public class JavaPlayerAbilitiesTranslator extends PacketTranslator " + stopSoundPacket); } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/window/JavaCloseWindowTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/window/JavaCloseWindowTranslator.java index 8162b82a4..7360cbb2e 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/window/JavaCloseWindowTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/window/JavaCloseWindowTranslator.java @@ -39,7 +39,7 @@ public class JavaCloseWindowTranslator extends PacketTranslator { @@ -41,7 +38,7 @@ public class JavaConfirmTransactionTranslator extends PacketTranslator 0 ? 1 : 0); - session.getUpstream().sendPacket(blockEventPacket); + session.sendUpstreamPacket(blockEventPacket); } if (packet.getValue() instanceof EndGatewayValue) { blockEventPacket.setEventType(1); - session.getUpstream().sendPacket(blockEventPacket); + session.sendUpstreamPacket(blockEventPacket); } if (packet.getValue() instanceof NoteBlockValue) { NoteblockBlockEntityTranslator.translate(session, packet.getPosition()); @@ -77,15 +77,15 @@ public class JavaBlockValueTranslator extends PacketTranslator extendPiston(session, position, (progress >= 1.0f) ? 1.0f : progress + 0.5f, progress), @@ -121,7 +121,7 @@ public class JavaBlockValueTranslator extends PacketTranslator retractPiston(session, position, (progress <= 0.0f) ? 0.0f : progress - 0.5f, progress), diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaChunkDataTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaChunkDataTranslator.java index 9e2d2ae7a..2af7bb5bb 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaChunkDataTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaChunkDataTranslator.java @@ -98,7 +98,7 @@ public class JavaChunkDataTranslator extends PacketTranslator blockEntityEntry : chunkData.getLoadBlockEntitiesLater().object2IntEntrySet()) { diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaCollectItemTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaCollectItemTranslator.java index b4287b081..31379bd2d 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaCollectItemTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaCollectItemTranslator.java @@ -50,6 +50,6 @@ public class JavaCollectItemTranslator extends PacketTranslator playerFlags = new ObjectOpenHashSet<>(); @@ -89,14 +89,14 @@ public class JavaNotifyClientTranslator extends PacketTranslator " + soundPacket.toString()); } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaPlayEffectTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaPlayEffectTranslator.java index e22db97e1..8e76d7d8a 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaPlayEffectTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaPlayEffectTranslator.java @@ -90,12 +90,12 @@ public class JavaPlayEffectTranslator extends PacketTranslator " + playSoundPacket); } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaSpawnParticleTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaSpawnParticleTranslator.java index 1f9bcba35..d6da1c816 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaSpawnParticleTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaSpawnParticleTranslator.java @@ -52,7 +52,7 @@ public class JavaSpawnParticleTranslator extends PacketTranslator("dodaylightcycle", doCycle)); - session.getUpstream().sendPacket(gameRulesChangedPacket); + session.sendUpstreamPacket(gameRulesChangedPacket); } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/sound/block/BucketSoundInteractionHandler.java b/connector/src/main/java/org/geysermc/connector/network/translators/sound/block/BucketSoundInteractionHandler.java index 00269cc7f..031782c1b 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/sound/block/BucketSoundInteractionHandler.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/sound/block/BucketSoundInteractionHandler.java @@ -67,7 +67,7 @@ public class BucketSoundInteractionHandler implements BlockSoundInteractionHandl } if (soundEvent != null) { soundEventPacket.setSound(soundEvent); - session.getUpstream().sendPacket(soundEventPacket); + session.sendUpstreamPacket(soundEventPacket); } } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/sound/block/ComparatorSoundInteractHandler.java b/connector/src/main/java/org/geysermc/connector/network/translators/sound/block/ComparatorSoundInteractHandler.java index 260ad814f..4b74a6783 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/sound/block/ComparatorSoundInteractHandler.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/sound/block/ComparatorSoundInteractHandler.java @@ -43,6 +43,6 @@ public class ComparatorSoundInteractHandler implements BlockSoundInteractionHand levelEventPacket.setPosition(position); levelEventPacket.setType(LevelEventType.REDSTONE_TRIGGER); levelEventPacket.setData(powered ? 500 : 550); - session.getUpstream().sendPacket(levelEventPacket); + session.sendUpstreamPacket(levelEventPacket); } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/sound/block/DoorSoundInteractionHandler.java b/connector/src/main/java/org/geysermc/connector/network/translators/sound/block/DoorSoundInteractionHandler.java index b8e2854d5..39a07c3ac 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/sound/block/DoorSoundInteractionHandler.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/sound/block/DoorSoundInteractionHandler.java @@ -42,6 +42,6 @@ public class DoorSoundInteractionHandler implements BlockSoundInteractionHandler levelEventPacket.setType(LevelEventType.SOUND_DOOR); levelEventPacket.setPosition(position); levelEventPacket.setData(0); - session.getUpstream().sendPacket(levelEventPacket); + session.sendUpstreamPacket(levelEventPacket); } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/sound/block/FlintAndSteelInteractionHandler.java b/connector/src/main/java/org/geysermc/connector/network/translators/sound/block/FlintAndSteelInteractionHandler.java index b28133b34..290aa7bd6 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/sound/block/FlintAndSteelInteractionHandler.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/sound/block/FlintAndSteelInteractionHandler.java @@ -45,6 +45,6 @@ public class FlintAndSteelInteractionHandler implements BlockSoundInteractionHan levelSoundEventPacket.setIdentifier(":"); levelSoundEventPacket.setSound(SoundEvent.IGNITE); levelSoundEventPacket.setExtraData(-1); - session.getUpstream().sendPacket(levelSoundEventPacket); + session.sendUpstreamPacket(levelSoundEventPacket); } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/sound/block/GrassPathInteractionHandler.java b/connector/src/main/java/org/geysermc/connector/network/translators/sound/block/GrassPathInteractionHandler.java index e29571036..e5445e9df 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/sound/block/GrassPathInteractionHandler.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/sound/block/GrassPathInteractionHandler.java @@ -46,6 +46,6 @@ public class GrassPathInteractionHandler implements BlockSoundInteractionHandler levelSoundEventPacket.setIdentifier(":"); levelSoundEventPacket.setSound(SoundEvent.ITEM_USE_ON); levelSoundEventPacket.setExtraData(BlockTranslator.getBedrockBlockId(BlockTranslator.getJavaBlockState(identifier))); - session.getUpstream().sendPacket(levelSoundEventPacket); + session.sendUpstreamPacket(levelSoundEventPacket); } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/sound/block/HoeInteractionHandler.java b/connector/src/main/java/org/geysermc/connector/network/translators/sound/block/HoeInteractionHandler.java index c9d4299b4..17d346ae6 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/sound/block/HoeInteractionHandler.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/sound/block/HoeInteractionHandler.java @@ -46,6 +46,6 @@ public class HoeInteractionHandler implements BlockSoundInteractionHandler { levelSoundEventPacket.setIdentifier(":"); levelSoundEventPacket.setSound(SoundEvent.ITEM_USE_ON); levelSoundEventPacket.setExtraData(BlockTranslator.getBedrockBlockId(BlockTranslator.getJavaBlockState(identifier))); - session.getUpstream().sendPacket(levelSoundEventPacket); + session.sendUpstreamPacket(levelSoundEventPacket); } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/sound/block/LeverSoundInteractionHandler.java b/connector/src/main/java/org/geysermc/connector/network/translators/sound/block/LeverSoundInteractionHandler.java index cfbe7727d..fb39d4ac8 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/sound/block/LeverSoundInteractionHandler.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/sound/block/LeverSoundInteractionHandler.java @@ -43,6 +43,6 @@ public class LeverSoundInteractionHandler implements BlockSoundInteractionHandle levelEventPacket.setPosition(position); levelEventPacket.setType(LevelEventType.REDSTONE_TRIGGER); levelEventPacket.setData(powered ? 600 : 500); - session.getUpstream().sendPacket(levelEventPacket); + session.sendUpstreamPacket(levelEventPacket); } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/sound/entity/MilkCowSoundInteractionHandler.java b/connector/src/main/java/org/geysermc/connector/network/translators/sound/entity/MilkCowSoundInteractionHandler.java index d4046eea7..42e2e601f 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/sound/entity/MilkCowSoundInteractionHandler.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/sound/entity/MilkCowSoundInteractionHandler.java @@ -50,6 +50,6 @@ public class MilkCowSoundInteractionHandler implements EntitySoundInteractionHan levelSoundEventPacket.setIdentifier(":"); levelSoundEventPacket.setSound(SoundEvent.MILK); levelSoundEventPacket.setExtraData(-1); - session.getUpstream().sendPacket(levelSoundEventPacket); + session.sendUpstreamPacket(levelSoundEventPacket); } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/FlowerPotBlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/FlowerPotBlockEntityTranslator.java index 6861a9535..c4748c829 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/FlowerPotBlockEntityTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/FlowerPotBlockEntityTranslator.java @@ -53,7 +53,7 @@ public class FlowerPotBlockEntityTranslator implements BedrockOnlyBlockEntity, R updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.PRIORITY); updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NONE); updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NEIGHBORS); - session.getUpstream().sendPacket(updateBlockPacket); + session.sendUpstreamPacket(updateBlockPacket); } /** diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/NoteblockBlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/NoteblockBlockEntityTranslator.java index c538f09eb..168015f6e 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/NoteblockBlockEntityTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/NoteblockBlockEntityTranslator.java @@ -50,7 +50,7 @@ public class NoteblockBlockEntityTranslator implements RequiresBlockState { blockEventPacket.setBlockPosition(Vector3i.from(position.getX(), position.getY(), position.getZ())); blockEventPacket.setEventType(0); blockEventPacket.setEventData(BlockStateValues.getNoteblockPitch(blockState)); - session.getUpstream().sendPacket(blockEventPacket); + session.sendUpstreamPacket(blockEventPacket); ChunkUtils.CACHED_BLOCK_ENTITIES.remove(position); } diff --git a/connector/src/main/java/org/geysermc/connector/scoreboard/Scoreboard.java b/connector/src/main/java/org/geysermc/connector/scoreboard/Scoreboard.java index 03ccb2fd3..59d9b25f6 100644 --- a/connector/src/main/java/org/geysermc/connector/scoreboard/Scoreboard.java +++ b/connector/src/main/java/org/geysermc/connector/scoreboard/Scoreboard.java @@ -187,7 +187,7 @@ public class Scoreboard { if (objective.getUpdateType() == REMOVE || update) { RemoveObjectivePacket removeObjectivePacket = new RemoveObjectivePacket(); removeObjectivePacket.setObjectiveId(objective.getObjectiveName()); - session.getUpstream().sendPacket(removeObjectivePacket); + session.sendUpstreamPacket(removeObjectivePacket); if (objective.getUpdateType() == REMOVE) { objectives.remove(objective.getObjectiveName()); // now we can deregister } @@ -199,7 +199,7 @@ public class Scoreboard { displayObjectivePacket.setCriteria("dummy"); displayObjectivePacket.setDisplaySlot(objective.getDisplaySlot()); displayObjectivePacket.setSortOrder(1); // ?? - session.getUpstream().sendPacket(displayObjectivePacket); + session.sendUpstreamPacket(displayObjectivePacket); } objective.setUpdateType(NOTHING); } @@ -208,21 +208,21 @@ public class Scoreboard { SetScorePacket setScorePacket = new SetScorePacket(); setScorePacket.setAction(SetScorePacket.Action.REMOVE); setScorePacket.setInfos(removeScores); - session.getUpstream().sendPacket(setScorePacket); + session.sendUpstreamPacket(setScorePacket); } if (!addScores.isEmpty()) { SetScorePacket setScorePacket = new SetScorePacket(); setScorePacket.setAction(SetScorePacket.Action.SET); setScorePacket.setInfos(addScores); - session.getUpstream().sendPacket(setScorePacket); + session.sendUpstreamPacket(setScorePacket); } } public void despawnObjective(Objective objective) { RemoveObjectivePacket removeObjectivePacket = new RemoveObjectivePacket(); removeObjectivePacket.setObjectiveId(objective.getObjectiveName()); - session.getUpstream().sendPacket(removeObjectivePacket); + session.sendUpstreamPacket(removeObjectivePacket); objectives.remove(objective.getDisplayName()); List toRemove = new ArrayList<>(); @@ -238,7 +238,7 @@ public class Scoreboard { SetScorePacket setScorePacket = new SetScorePacket(); setScorePacket.setAction(SetScorePacket.Action.REMOVE); setScorePacket.setInfos(toRemove); - session.getUpstream().sendPacket(setScorePacket); + session.sendUpstreamPacket(setScorePacket); } } diff --git a/connector/src/main/java/org/geysermc/connector/utils/BlockEntityUtils.java b/connector/src/main/java/org/geysermc/connector/utils/BlockEntityUtils.java index b0794e200..c595eee4b 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/BlockEntityUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/BlockEntityUtils.java @@ -49,6 +49,6 @@ public class BlockEntityUtils { BlockEntityDataPacket blockEntityPacket = new BlockEntityDataPacket(); blockEntityPacket.setBlockPosition(position); blockEntityPacket.setData(blockEntity); - session.getUpstream().sendPacket(blockEntityPacket); + session.sendUpstreamPacket(blockEntityPacket); } } diff --git a/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java b/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java index fcc596eb1..7afb8e6a9 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java @@ -156,7 +156,7 @@ public class ChunkUtils { NetworkChunkPublisherUpdatePacket chunkPublisherUpdatePacket = new NetworkChunkPublisherUpdatePacket(); chunkPublisherUpdatePacket.setPosition(position); chunkPublisherUpdatePacket.setRadius(session.getRenderDistance() << 4); - session.getUpstream().sendPacket(chunkPublisherUpdatePacket); + session.sendUpstreamPacket(chunkPublisherUpdatePacket); session.setLastChunkPosition(newChunkPos); } @@ -188,7 +188,7 @@ public class ChunkUtils { updateBlockPacket.setBlockPosition(position); updateBlockPacket.setRuntimeId(blockId); updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NEIGHBORS); - session.getUpstream().sendPacket(updateBlockPacket); + session.sendUpstreamPacket(updateBlockPacket); UpdateBlockPacket waterPacket = new UpdateBlockPacket(); waterPacket.setDataLayer(1); @@ -198,7 +198,7 @@ public class ChunkUtils { } else { waterPacket.setRuntimeId(0); } - session.getUpstream().sendPacket(waterPacket); + session.sendUpstreamPacket(waterPacket); // Since Java stores bed colors/skull information as part of the namespaced ID and Bedrock stores it as a tag // This is the only place I could find that interacts with the Java block state and block updates @@ -228,7 +228,7 @@ public class ChunkUtils { data.setSubChunksLength(0); data.setData(Translators.EMPTY_LEVEL_CHUNK_DATA); data.setCachingEnabled(false); - session.getUpstream().sendPacket(data); + session.sendUpstreamPacket(data); if (forceUpdate) { Vector3i pos = Vector3i.from(chunkX + x << 4, 80, chunkZ + z << 4); @@ -236,7 +236,7 @@ public class ChunkUtils { blockPacket.setBlockPosition(pos); blockPacket.setDataLayer(0); blockPacket.setRuntimeId(1); - session.getUpstream().sendPacket(blockPacket); + session.sendUpstreamPacket(blockPacket); } } } diff --git a/connector/src/main/java/org/geysermc/connector/utils/DimensionUtils.java b/connector/src/main/java/org/geysermc/connector/utils/DimensionUtils.java index 6dd182a79..2c3933e2c 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/DimensionUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/DimensionUtils.java @@ -49,7 +49,7 @@ public class DimensionUtils { changeDimensionPacket.setDimension(bedrockDimension); changeDimensionPacket.setRespawn(true); changeDimensionPacket.setPosition(pos.toFloat()); - session.getUpstream().sendPacket(changeDimensionPacket); + session.sendUpstreamPacket(changeDimensionPacket); player.setDimension(bedrockDimension); player.setPosition(pos.toFloat()); session.setSpawned(false); @@ -59,7 +59,7 @@ public class DimensionUtils { StopSoundPacket stopSoundPacket = new StopSoundPacket(); stopSoundPacket.setStoppingAllSound(true); stopSoundPacket.setSoundName(""); - session.getUpstream().sendPacket(stopSoundPacket); + session.sendUpstreamPacket(stopSoundPacket); } /** diff --git a/connector/src/main/java/org/geysermc/connector/utils/InventoryUtils.java b/connector/src/main/java/org/geysermc/connector/utils/InventoryUtils.java index 3717b432a..609381198 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/InventoryUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/InventoryUtils.java @@ -84,7 +84,7 @@ public class InventoryUtils { cursorPacket.setContainerId(ContainerId.CURSOR); cursorPacket.setSlot(0); cursorPacket.setItem(Translators.getItemTranslator().translateToBedrock(session, session.getInventory().getCursor())); - session.getUpstream().sendPacket(cursorPacket); + session.sendUpstreamPacket(cursorPacket); } public static boolean canStack(ItemStack item1, ItemStack item2) { diff --git a/connector/src/main/java/org/geysermc/connector/utils/LoginEncryptionUtils.java b/connector/src/main/java/org/geysermc/connector/utils/LoginEncryptionUtils.java index 300294a2f..7f6c47604 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/LoginEncryptionUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/LoginEncryptionUtils.java @@ -35,8 +35,6 @@ import com.nukkitx.protocol.bedrock.packet.LoginPacket; import com.nukkitx.protocol.bedrock.packet.ServerToClientHandshakePacket; import com.nukkitx.protocol.bedrock.util.EncryptionUtils; -import net.minidev.json.JSONObject; - import org.geysermc.common.window.CustomFormBuilder; import org.geysermc.common.window.CustomFormWindow; import org.geysermc.common.window.FormWindow; @@ -152,7 +150,7 @@ public class LoginEncryptionUtils { ServerToClientHandshakePacket packet = new ServerToClientHandshakePacket(); packet.setJwt(EncryptionUtils.createHandshakeJwt(serverKeyPair, token).serialize()); - session.getUpstream().sendPacketImmediately(packet); + session.sendUpstreamPacketImmediately(packet); } private static int AUTH_FORM_ID = 1336; diff --git a/connector/src/main/java/org/geysermc/connector/utils/SkinUtils.java b/connector/src/main/java/org/geysermc/connector/utils/SkinUtils.java index 9ce025e76..db88f2fac 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/SkinUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/SkinUtils.java @@ -177,12 +177,12 @@ public class SkinUtils { PlayerListPacket playerRemovePacket = new PlayerListPacket(); playerRemovePacket.setAction(PlayerListPacket.Action.REMOVE); playerRemovePacket.getEntries().add(updatedEntry); - session.getUpstream().sendPacket(playerRemovePacket); + session.sendUpstreamPacket(playerRemovePacket); PlayerListPacket playerAddPacket = new PlayerListPacket(); playerAddPacket.setAction(PlayerListPacket.Action.ADD); playerAddPacket.getEntries().add(updatedEntry); - session.getUpstream().sendPacket(playerAddPacket); + session.sendUpstreamPacket(playerAddPacket); } } } catch (Exception e) { From 48147c2ce3b41010ce1bd6f6a24378963ee75396 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+DoctorMacc@users.noreply.github.com> Date: Tue, 5 May 2020 13:53:25 -0400 Subject: [PATCH 046/140] Fix Floodgate players causing errors on Bukkit. (#490) Co-authored-by: Tim203 --- .../geysermc/connector/network/session/GeyserSession.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java b/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java index 9068456c1..cf74f9231 100644 --- a/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java +++ b/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java @@ -35,6 +35,7 @@ import com.github.steveice10.mc.protocol.packet.ingame.client.world.ClientTelepo 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.mc.protocol.packet.login.server.LoginSuccessPacket; import com.github.steveice10.packetlib.Client; import com.github.steveice10.packetlib.event.session.*; import com.github.steveice10.packetlib.packet.Packet; @@ -332,6 +333,13 @@ public class GeyserSession implements CommandSender { lastDimPacket = null; } + // Required, or else Floodgate players break with Bukkit chunk caching + if (event.getPacket() instanceof LoginSuccessPacket) { + GameProfile profile = ((LoginSuccessPacket) event.getPacket()).getProfile(); + playerEntity.setUsername(profile.getName()); + playerEntity.setUuid(profile.getId()); + } + Registry.JAVA.translate(event.getPacket().getClass(), event.getPacket(), GeyserSession.this); } } From 425df396cb4922e1d14df1042d3ea4d7005abd63 Mon Sep 17 00:00:00 2001 From: Chase MacDonnell Date: Wed, 6 May 2020 17:02:52 -0400 Subject: [PATCH 047/140] Don't load floodgate if it isn't needed (velocity) (#499) Co-authored-by: Chase M <1860157-chasemacdonnell@users.noreply.gitlab.com> --- .../geysermc/platform/velocity/GeyserVelocityConfiguration.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityConfiguration.java b/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityConfiguration.java index ff99f8ab1..b9b3b3793 100644 --- a/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityConfiguration.java +++ b/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityConfiguration.java @@ -79,7 +79,7 @@ public class GeyserVelocityConfiguration implements GeyserConfiguration { public void loadFloodgate(GeyserVelocityPlugin plugin, ProxyServer proxyServer, File dataFolder) { Optional floodgate = proxyServer.getPluginManager().getPlugin("floodgate"); - floodgateKey = FloodgateKeyLoader.getKey(plugin.getGeyserLogger(), this, Paths.get(dataFolder.toString(), floodgateKeyFile.isEmpty() ? floodgateKeyFile : "public-key.pem"), floodgate.get(), Paths.get("plugins/floodgate/")); + floodgate.ifPresent(it -> floodgateKey = FloodgateKeyLoader.getKey(plugin.getGeyserLogger(), this, Paths.get(dataFolder.toString(), floodgateKeyFile.isEmpty() ? floodgateKeyFile : "public-key.pem"), it, Paths.get("plugins/floodgate/"))); } @Override From 4c1dae67140296440312a9c3afa38ab4d03aca4b Mon Sep 17 00:00:00 2001 From: Luke <32024335+lukeeey@users.noreply.github.com> Date: Wed, 6 May 2020 22:05:03 +0100 Subject: [PATCH 048/140] Add unusable inventory space message (#492) * Add unusable inventory space message * Remove unused imports * Fixed barrier pickup (#1) Co-authored-by: rtm516 --- .../inventory/PlayerInventoryTranslator.java | 4 +++- .../updater/ChestInventoryUpdater.java | 6 +++++- .../connector/utils/InventoryUtils.java | 19 +++++++++++++++++++ 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/PlayerInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/PlayerInventoryTranslator.java index b711bddc4..5beea2a2d 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/PlayerInventoryTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/PlayerInventoryTranslator.java @@ -44,6 +44,8 @@ import org.geysermc.connector.utils.Toolbox; import java.util.List; public class PlayerInventoryTranslator extends InventoryTranslator { + private static final ItemData UNUSUABLE_CRAFTING_SPACE_BLOCK = InventoryUtils.createUnusableSpaceBlock( + "The creative crafting grid is\nunavailable in Java Edition"); public PlayerInventoryTranslator() { super(46); @@ -97,7 +99,7 @@ public class PlayerInventoryTranslator extends InventoryTranslator { slotPacket.setSlot(i + 27); if (session.getGameMode() == GameMode.CREATIVE) { - slotPacket.setItem(Translators.getItemTranslator().translateToBedrock(session, new ItemStack(Toolbox.BARRIER_INDEX))); + slotPacket.setItem(UNUSUABLE_CRAFTING_SPACE_BLOCK); }else{ slotPacket.setItem(Translators.getItemTranslator().translateToBedrock(session, inventory.getItem(i))); } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/ChestInventoryUpdater.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/ChestInventoryUpdater.java index 8318081df..e9541bd15 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/ChestInventoryUpdater.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/ChestInventoryUpdater.java @@ -33,9 +33,13 @@ import org.geysermc.connector.inventory.Inventory; import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.Translators; import org.geysermc.connector.network.translators.inventory.InventoryTranslator; +import org.geysermc.connector.utils.InventoryUtils; @AllArgsConstructor public class ChestInventoryUpdater extends InventoryUpdater { + private static final ItemData UNUSUABLE_SPACE_BLOCK = InventoryUtils.createUnusableSpaceBlock( + "This slot does not exist in the inventory\non Java Edition, as there is less\nrows than possible in Bedrock"); + private final int paddedSize; @Override @@ -47,7 +51,7 @@ public class ChestInventoryUpdater extends InventoryUpdater { if (i <= translator.size) { bedrockItems[i] = Translators.getItemTranslator().translateToBedrock(session, inventory.getItem(i)); } else { - bedrockItems[i] = ItemData.AIR; + bedrockItems[i] = UNUSUABLE_SPACE_BLOCK; } } diff --git a/connector/src/main/java/org/geysermc/connector/utils/InventoryUtils.java b/connector/src/main/java/org/geysermc/connector/utils/InventoryUtils.java index 609381198..c0311b64f 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/InventoryUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/InventoryUtils.java @@ -27,9 +27,12 @@ package org.geysermc.connector.utils; import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; +import com.nukkitx.nbt.CompoundTagBuilder; +import com.nukkitx.nbt.tag.StringTag; import com.nukkitx.protocol.bedrock.data.ContainerId; import com.nukkitx.protocol.bedrock.data.ItemData; import com.nukkitx.protocol.bedrock.packet.InventorySlotPacket; +import org.geysermc.common.ChatColor; import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.inventory.Inventory; import org.geysermc.connector.network.session.GeyserSession; @@ -37,6 +40,7 @@ import org.geysermc.connector.network.translators.Translators; import org.geysermc.connector.network.translators.inventory.DoubleChestInventoryTranslator; import org.geysermc.connector.network.translators.inventory.InventoryTranslator; +import java.util.Collections; import java.util.Objects; import java.util.concurrent.TimeUnit; @@ -98,4 +102,19 @@ public class InventoryUtils { return false; return item1.equals(item2, false, true, true); } + + /** + * Returns a barrier block with custom name and lore to explain why + * part of the inventory is unusable. + */ + public static ItemData createUnusableSpaceBlock(String description) { + CompoundTagBuilder root = CompoundTagBuilder.builder(); + CompoundTagBuilder display = CompoundTagBuilder.builder(); + + display.stringTag("Name", ChatColor.RESET + "Unusable inventory space"); + display.listTag("Lore", StringTag.class, Collections.singletonList(new StringTag("", ChatColor.RESET + ChatColor.DARK_PURPLE + description))); + + root.tag(display.build("display")); + return ItemData.of(Toolbox.ITEM_ENTRIES.get(Toolbox.BARRIER_INDEX).getBedrockId(), (short) 0, 1, root.buildRootTag()); + } } From 5ae95433e52dc68bd28620f226965e7868ab9921 Mon Sep 17 00:00:00 2001 From: rtm516 Date: Wed, 6 May 2020 22:50:01 +0100 Subject: [PATCH 049/140] Bedrock to Bedrock legacy skin support (#276) * Added legacy skin support for bedrock to bedrock clients * Added bedrock to bedrock cape handling * Added bedrock geometry support * Bedrock skins now work in all auth modes * Tonne of debug info * Added fix to prevent customised skins from being loaded * Added skin size to bedrock client data * Cleaned debugging code * Made bedrock cape take priority over third party * Cut the customised skin image in half to hopefully get it to map * Removed hacky conversion attempt * Fixed bedrock skin caching on load and 1.14.60 support * Cleaned up debug messages * Added linked player ignore --- .../network/session/GeyserSession.java | 10 +++- .../session/auth/BedrockClientData.java | 4 ++ .../connector/utils/SkinProvider.java | 39 ++++++++++++++ .../geysermc/connector/utils/SkinUtils.java | 53 ++++++++++++++++--- 4 files changed, 98 insertions(+), 8 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java b/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java index cf74f9231..759a0f3b3 100644 --- a/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java +++ b/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java @@ -31,10 +31,10 @@ import com.github.steveice10.mc.auth.exception.request.RequestException; import com.github.steveice10.mc.protocol.MinecraftProtocol; import com.github.steveice10.mc.protocol.data.SubProtocol; import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode; -import com.github.steveice10.mc.protocol.packet.ingame.client.world.ClientTeleportConfirmPacket; 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.mc.protocol.packet.ingame.client.world.ClientTeleportConfirmPacket; +import com.github.steveice10.mc.protocol.packet.ingame.server.ServerRespawnPacket; import com.github.steveice10.mc.protocol.packet.login.server.LoginSuccessPacket; import com.github.steveice10.packetlib.Client; import com.github.steveice10.packetlib.event.session.*; @@ -68,6 +68,7 @@ import org.geysermc.connector.network.translators.Registry; import org.geysermc.connector.network.translators.world.block.BlockTranslator; import org.geysermc.connector.utils.ChunkUtils; import org.geysermc.connector.utils.LocaleUtils; +import org.geysermc.connector.utils.SkinUtils; import org.geysermc.connector.utils.Toolbox; import org.geysermc.floodgate.util.BedrockData; import org.geysermc.floodgate.util.EncryptionUtil; @@ -338,6 +339,11 @@ public class GeyserSession implements CommandSender { GameProfile profile = ((LoginSuccessPacket) event.getPacket()).getProfile(); playerEntity.setUsername(profile.getName()); playerEntity.setUuid(profile.getId()); + + // Check if they are not using a linked account + if (!playerEntity.getUuid().toString().startsWith("00000000-0000-0000")) { + SkinUtils.handleBedrockSkin(playerEntity, clientData); + } } Registry.JAVA.translate(event.getPacket().getClass(), event.getPacket(), GeyserSession.this); diff --git a/connector/src/main/java/org/geysermc/connector/network/session/auth/BedrockClientData.java b/connector/src/main/java/org/geysermc/connector/network/session/auth/BedrockClientData.java index 8fc56acd3..4ef0fe79c 100644 --- a/connector/src/main/java/org/geysermc/connector/network/session/auth/BedrockClientData.java +++ b/connector/src/main/java/org/geysermc/connector/network/session/auth/BedrockClientData.java @@ -24,6 +24,10 @@ public class BedrockClientData { private String skinId; @JsonProperty(value = "SkinData") private String skinData; + @JsonProperty(value = "SkinImageHeight") + private int skinImageHeight; + @JsonProperty(value = "SkinImageWidth") + private int skinImageWidth; @JsonProperty(value = "CapeId") private String capeId; @JsonProperty(value = "CapeData") diff --git a/connector/src/main/java/org/geysermc/connector/utils/SkinProvider.java b/connector/src/main/java/org/geysermc/connector/utils/SkinProvider.java index 7c2b7fc0e..15cccf223 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/SkinProvider.java +++ b/connector/src/main/java/org/geysermc/connector/utils/SkinProvider.java @@ -58,6 +58,9 @@ public class SkinProvider { private static Map cachedCapes = new ConcurrentHashMap<>(); private static Map> requestedCapes = new ConcurrentHashMap<>(); + public static final SkinGeometry EMPTY_GEOMETRY = SkinProvider.SkinGeometry.getLegacy("geometry.humanoid"); + private static Map cachedGeometry = new ConcurrentHashMap<>(); + private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); private static final int CACHE_INTERVAL = 8 * 60 * 1000; // 8 minutes @@ -164,6 +167,31 @@ public class SkinProvider { return CompletableFuture.completedFuture(officialCape); } + public static CompletableFuture requestBedrockCape(UUID playerID, boolean newThread) { + Cape bedrockCape = cachedCapes.getOrDefault(playerID.toString() + ".Bedrock", EMPTY_CAPE); + return CompletableFuture.completedFuture(bedrockCape); + } + + public static CompletableFuture requestBedrockGeometry(SkinGeometry currentGeometry, UUID playerID, boolean newThread) { + SkinGeometry bedrockGeometry = cachedGeometry.getOrDefault(playerID, currentGeometry); + return CompletableFuture.completedFuture(bedrockGeometry); + } + + public static void storeBedrockSkin(UUID playerID, String skinID, byte[] skinData) { + Skin skin = new Skin(playerID, skinID, skinData, System.currentTimeMillis(), true); + cachedSkins.put(playerID, skin); + } + + public static void storeBedrockCape(UUID playerID, byte[] capeData) { + Cape cape = new Cape(playerID.toString() + ".Bedrock", playerID.toString(), capeData, System.currentTimeMillis(), false); + cachedCapes.put(playerID.toString() + ".Bedrock", cape); + } + + public static void storeBedrockGeometry(UUID playerID, byte[] geometryName, byte[] geometryData) { + SkinGeometry geometry = new SkinGeometry(new String(geometryName), new String(geometryData)); + cachedGeometry.put(playerID, geometry); + } + private static Skin supplySkin(UUID uuid, String textureUrl) { byte[] skin = EMPTY_SKIN.getSkinData(); try { @@ -285,6 +313,17 @@ public class SkinProvider { private boolean failed; } + @AllArgsConstructor + @Getter + public static class SkinGeometry { + private String geometryName; + private String geometryData; + + public static SkinGeometry getLegacy(String name) { + return new SkinProvider.SkinGeometry("{\"geometry\" :{\"default\" :\"" + name + "\"}}", ""); + } + } + /* * Sorted by 'priority' */ diff --git a/connector/src/main/java/org/geysermc/connector/utils/SkinUtils.java b/connector/src/main/java/org/geysermc/connector/utils/SkinUtils.java index db88f2fac..1d0ee2168 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/SkinUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/SkinUtils.java @@ -39,6 +39,7 @@ import org.geysermc.common.AuthType; import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.entity.PlayerEntity; import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.session.auth.BedrockClientData; import java.nio.charset.StandardCharsets; import java.util.Base64; @@ -52,6 +53,8 @@ public class SkinUtils { GameProfileData data = GameProfileData.from(profile); SkinProvider.Cape cape = SkinProvider.getCachedCape(data.getCapeUrl()); + SkinProvider.SkinGeometry geometry = SkinProvider.SkinGeometry.getLegacy("geometry.humanoid.custom" + (data.isAlex() ? "Slim" : "")); + return buildEntryManually( profile.getId(), profile.getName(), @@ -60,8 +63,8 @@ public class SkinUtils { SkinProvider.getCachedSkin(profile.getId()).getSkinData(), cape.getCapeId(), cape.getCapeData(), - getLegacySkinGeometry("geometry.humanoid.custom" + (data.isAlex() ? "Slim" : "")), - "" + geometry.getGeometryName(), + geometry.getGeometryData() ); } @@ -74,8 +77,8 @@ public class SkinUtils { SkinProvider.STEVE_SKIN, SkinProvider.EMPTY_CAPE.getCapeId(), SkinProvider.EMPTY_CAPE.getCapeData(), - getLegacySkinGeometry("geometry.humanoid"), - "" + SkinProvider.EMPTY_GEOMETRY.getGeometryName(), + SkinProvider.EMPTY_GEOMETRY.getGeometryData() ); } @@ -151,6 +154,12 @@ public class SkinUtils { SkinProvider.Skin skin = skinAndCape.getSkin(); SkinProvider.Cape cape = skinAndCape.getCape(); + if (cape.isFailed()) { + cape = SkinProvider.getOrDefault(SkinProvider.requestBedrockCape( + entity.getUuid(), false + ), SkinProvider.EMPTY_CAPE, 3); + } + if (cape.isFailed() && SkinProvider.ALLOW_THIRD_PARTY_CAPES) { cape = SkinProvider.getOrDefault(SkinProvider.requestUnofficialCape( cape, entity.getUuid(), @@ -158,6 +167,11 @@ public class SkinUtils { ), SkinProvider.EMPTY_CAPE, SkinProvider.CapeProvider.VALUES.length * 3); } + SkinProvider.SkinGeometry geometry = SkinProvider.SkinGeometry.getLegacy("geometry.humanoid.custom" + (data.isAlex() ? "Slim" : "")); + geometry = SkinProvider.getOrDefault(SkinProvider.requestBedrockGeometry( + geometry, entity.getUuid(), false + ), geometry, 3); + if (entity.getLastSkinUpdate() < skin.getRequestedOn()) { entity.setLastSkinUpdate(skin.getRequestedOn()); @@ -170,8 +184,8 @@ public class SkinUtils { skin.getSkinData(), cape.getCapeId(), cape.getCapeData(), - getLegacySkinGeometry("geometry.humanoid.custom" + (data.isAlex() ? "Slim" : "")), - "" + geometry.getGeometryName(), + geometry.getGeometryData() ); PlayerListPacket playerRemovePacket = new PlayerListPacket(); @@ -194,6 +208,33 @@ public class SkinUtils { }); } + public static void handleBedrockSkin(PlayerEntity playerEntity, BedrockClientData clientData) { + GameProfileData data = GameProfileData.from(playerEntity.getProfile()); + + GeyserConnector.getInstance().getLogger().info("Registering bedrock skin for " + playerEntity.getUsername() + " (" + playerEntity.getUuid() + ")"); + + try { + byte[] skinBytes = com.github.steveice10.mc.auth.util.Base64.decode(clientData.getSkinData().getBytes("UTF-8")); + byte[] capeBytes = clientData.getCapeData(); + + byte[] geometryNameBytes = com.github.steveice10.mc.auth.util.Base64.decode(clientData.getGeometryName().getBytes("UTF-8")); + byte[] geometryBytes = com.github.steveice10.mc.auth.util.Base64.decode(clientData.getGeometryData().getBytes("UTF-8")); + + if (skinBytes.length <= (128 * 128 * 4)) { + SkinProvider.storeBedrockSkin(playerEntity.getUuid(), data.getSkinUrl(), skinBytes); + } else { + GeyserConnector.getInstance().getLogger().info("Unable to load bedrock skin for '" + playerEntity.getUsername() + "' as they are using a customised skin"); + GeyserConnector.getInstance().getLogger().debug("The size of '" + playerEntity.getUsername() + "' skin is: " + clientData.getSkinImageWidth() + "x" + clientData.getSkinImageHeight()); + } + SkinProvider.storeBedrockGeometry(playerEntity.getUuid(), geometryNameBytes, geometryBytes); + if (!clientData.getCapeId().equals("")) { + SkinProvider.storeBedrockCape(playerEntity.getUuid(), capeBytes); + } + } catch (Exception e) { + throw new AssertionError("Failed to cache skin for bedrock user (" + playerEntity.getUsername() + "): ", e); + } + } + /** * Create a basic geometry json for the given name * From f11bae0bf078a4ee0f8308d6fcc0b421e95cb37c Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+DoctorMacc@users.noreply.github.com> Date: Wed, 6 May 2020 17:52:57 -0400 Subject: [PATCH 050/140] Fix signs (#439) * Fix signs on everything except Paper * Fix sign line placement * Update shulker box block entity Co-authored-by: James Harrison --- .../world/JavaUpdateTileEntityTranslator.java | 11 -- .../entity/BannerBlockEntityTranslator.java | 2 +- .../entity/BedBlockEntityTranslator.java | 2 +- .../world/block/entity/BlockEntity.java | 6 - .../entity/CampfireBlockEntityTranslator.java | 2 +- .../entity/EmptyBlockEntityTranslator.java | 2 +- .../EndGatewayBlockEntityTranslator.java | 2 +- .../ShulkerBoxBlockEntityTranslator.java | 2 +- .../entity/SignBlockEntityTranslator.java | 26 ++-- .../entity/SkullBlockEntityTranslator.java | 142 +++++++++--------- .../geysermc/connector/utils/ChunkUtils.java | 13 +- 11 files changed, 95 insertions(+), 115 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaUpdateTileEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaUpdateTileEntityTranslator.java index 5c55efed6..362d67d06 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaUpdateTileEntityTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaUpdateTileEntityTranslator.java @@ -30,19 +30,13 @@ import com.github.steveice10.mc.protocol.packet.ingame.server.world.ServerUpdate 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.world.block.entity.BlockEntity; import org.geysermc.connector.network.translators.world.block.entity.BlockEntityTranslator; import org.geysermc.connector.utils.BlockEntityUtils; import org.geysermc.connector.utils.ChunkUtils; -import java.util.concurrent.TimeUnit; - @Translator(packet = ServerUpdateTileEntityPacket.class) public class JavaUpdateTileEntityTranslator extends PacketTranslator { - // This should be modified if sign text is not showing up - private static final int DELAY = 500; - @Override public void translate(ServerUpdateTileEntityPacket packet, GeyserSession session) { String id = BlockEntityUtils.getBedrockBlockEntityId(packet.getType().name()); @@ -52,11 +46,6 @@ public class JavaUpdateTileEntityTranslator extends PacketTranslator - BlockEntityUtils.updateBlockEntity(session, translator.getBlockEntityTag(id, packet.getNbt(), null), packet.getPosition()), - DELAY, TimeUnit.MILLISECONDS); } else { BlockEntityUtils.updateBlockEntity(session, translator.getBlockEntityTag(id, packet.getNbt(), null), packet.getPosition()); } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/BannerBlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/BannerBlockEntityTranslator.java index 2034b3d52..eefd84022 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/BannerBlockEntityTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/BannerBlockEntityTranslator.java @@ -37,7 +37,7 @@ import org.geysermc.connector.network.translators.world.block.BlockStateValues; import java.util.ArrayList; import java.util.List; -@BlockEntity(name = "Banner", delay = false, regex = "banner") +@BlockEntity(name = "Banner", regex = "banner") public class BannerBlockEntityTranslator extends BlockEntityTranslator implements RequiresBlockState { @Override diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/BedBlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/BedBlockEntityTranslator.java index 543828e8e..5f0b1cc0d 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/BedBlockEntityTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/BedBlockEntityTranslator.java @@ -35,7 +35,7 @@ import org.geysermc.connector.network.translators.world.block.BlockStateValues; import java.util.ArrayList; import java.util.List; -@BlockEntity(name = "Bed", delay = false, regex = "bed") +@BlockEntity(name = "Bed", regex = "bed") public class BedBlockEntityTranslator extends BlockEntityTranslator implements RequiresBlockState { @Override diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/BlockEntity.java b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/BlockEntity.java index d08ab561c..11bfe0ea4 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/BlockEntity.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/BlockEntity.java @@ -31,12 +31,6 @@ import java.lang.annotation.RetentionPolicy; @Retention(value = RetentionPolicy.RUNTIME) public @interface BlockEntity { - /** - * Whether to delay the sending of the block entity - * @return the delay for when sending the block entity - */ - boolean delay(); - /** * The block entity name * @return the name of the block entity diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/CampfireBlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/CampfireBlockEntityTranslator.java index d91e47c27..eac87b041 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/CampfireBlockEntityTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/CampfireBlockEntityTranslator.java @@ -38,7 +38,7 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; -@BlockEntity(name = "Campfire", delay = false, regex = "campfire") +@BlockEntity(name = "Campfire", regex = "campfire") public class CampfireBlockEntityTranslator extends BlockEntityTranslator { @Override diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/EmptyBlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/EmptyBlockEntityTranslator.java index f95cb89ec..d10682775 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/EmptyBlockEntityTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/EmptyBlockEntityTranslator.java @@ -32,7 +32,7 @@ import com.nukkitx.nbt.tag.Tag; import java.util.ArrayList; import java.util.List; -@BlockEntity(name = "Empty", delay = false, regex = "") +@BlockEntity(name = "Empty", regex = "") public class EmptyBlockEntityTranslator extends BlockEntityTranslator { @Override diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/EndGatewayBlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/EndGatewayBlockEntityTranslator.java index 10de9d32d..4cd2eaa9e 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/EndGatewayBlockEntityTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/EndGatewayBlockEntityTranslator.java @@ -36,7 +36,7 @@ import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; -@BlockEntity(name = "EndGateway", delay = true, regex = "end_gateway") +@BlockEntity(name = "EndGateway", regex = "end_gateway") public class EndGatewayBlockEntityTranslator extends BlockEntityTranslator { @Override diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/ShulkerBoxBlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/ShulkerBoxBlockEntityTranslator.java index b0b8fa3d4..373b963e2 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/ShulkerBoxBlockEntityTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/ShulkerBoxBlockEntityTranslator.java @@ -36,7 +36,7 @@ import org.geysermc.connector.network.translators.world.block.BlockStateValues; import java.util.ArrayList; import java.util.List; -@BlockEntity(name = "ShulkerBox", delay = false, regex = "shulker_box") +@BlockEntity(name = "ShulkerBox", regex = "shulker_box") public class ShulkerBoxBlockEntityTranslator extends BlockEntityTranslator { @Override diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/SignBlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/SignBlockEntityTranslator.java index 0dde33077..6c1704622 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/SignBlockEntityTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/SignBlockEntityTranslator.java @@ -31,29 +31,35 @@ import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.nukkitx.nbt.CompoundTagBuilder; import com.nukkitx.nbt.tag.StringTag; import com.nukkitx.nbt.tag.Tag; +import io.netty.util.internal.StringUtil; import org.geysermc.connector.utils.MessageUtils; import java.util.ArrayList; import java.util.List; -@BlockEntity(name = "Sign", delay = true, regex = "sign") +@BlockEntity(name = "Sign", regex = "sign") public class SignBlockEntityTranslator extends BlockEntityTranslator { @Override public List> translateTag(CompoundTag tag, BlockState blockState) { List> tags = new ArrayList<>(); - String line1 = getOrDefault(tag.getValue().get("Text1"), ""); - String line2 = getOrDefault(tag.getValue().get("Text2"), ""); - String line3 = getOrDefault(tag.getValue().get("Text3"), ""); - String line4 = getOrDefault(tag.getValue().get("Text4"), ""); + StringBuilder signText = new StringBuilder(); + for(int i = 0; i < 4; i++) { + int currentLine = i+1; + String signLine = getOrDefault(tag.getValue().get("Text" + currentLine), ""); + signLine = MessageUtils.getBedrockMessage(Message.fromString(signLine)); - tags.add(new StringTag("Text", MessageUtils.getBedrockMessage(Message.fromString(line1)) - + "\n" + MessageUtils.getBedrockMessage(Message.fromString(line2)) - + "\n" + MessageUtils.getBedrockMessage(Message.fromString(line3)) - + "\n" + MessageUtils.getBedrockMessage(Message.fromString(line4)) - )); + //Java allows up to 16+ characters on certain symbols. + if(signLine.length() >= 15 && (signLine.contains("-") || signLine.contains("="))) { + signLine = signLine.substring(0, 14); + } + signText.append(signLine); + signText.append("\n"); + } + + tags.add(new StringTag("Text", MessageUtils.getBedrockMessage(Message.fromString(signText.toString())))); return tags; } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/SkullBlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/SkullBlockEntityTranslator.java index 7e73c8466..9393f7bb0 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/SkullBlockEntityTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/SkullBlockEntityTranslator.java @@ -1,71 +1,71 @@ -/* - * 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.world.block.entity; - -import com.github.steveice10.mc.protocol.data.game.world.block.BlockState; -import com.nukkitx.nbt.CompoundTagBuilder; -import com.nukkitx.nbt.tag.ByteTag; -import com.nukkitx.nbt.tag.CompoundTag; -import com.nukkitx.nbt.tag.FloatTag; -import com.nukkitx.nbt.tag.Tag; -import org.geysermc.connector.network.translators.world.block.BlockStateValues; - -import java.util.ArrayList; -import java.util.List; - -@BlockEntity(name = "Skull", delay = false, regex = "skull") -public class SkullBlockEntityTranslator extends BlockEntityTranslator implements RequiresBlockState { - - @Override - public boolean isBlock(BlockState blockState) { - return BlockStateValues.getSkullVariant(blockState) != -1; - } - - @Override - public List> translateTag(com.github.steveice10.opennbt.tag.builtin.CompoundTag tag, BlockState blockState) { - List> tags = new ArrayList<>(); - byte skullVariant = BlockStateValues.getSkullVariant(blockState); - float rotation = BlockStateValues.getSkullRotation(blockState) * 22.5f; - // Just in case... - if (skullVariant == -1) skullVariant = 0; - tags.add(new FloatTag("Rotation", rotation)); - tags.add(new ByteTag("SkullType", skullVariant)); - return tags; - } - - @Override - public com.github.steveice10.opennbt.tag.builtin.CompoundTag getDefaultJavaTag(String javaId, int x, int y, int z) { - return null; - } - - @Override - public CompoundTag getDefaultBedrockTag(String bedrockId, int x, int y, int z) { - CompoundTagBuilder tagBuilder = getConstantBedrockTag(bedrockId, x, y, z).toBuilder(); - tagBuilder.floatTag("Rotation", 0); - tagBuilder.byteTag("SkullType", (byte) 0); - return tagBuilder.buildRootTag(); - } -} +/* + * 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.world.block.entity; + +import com.github.steveice10.mc.protocol.data.game.world.block.BlockState; +import com.nukkitx.nbt.CompoundTagBuilder; +import com.nukkitx.nbt.tag.ByteTag; +import com.nukkitx.nbt.tag.CompoundTag; +import com.nukkitx.nbt.tag.FloatTag; +import com.nukkitx.nbt.tag.Tag; +import org.geysermc.connector.network.translators.world.block.BlockStateValues; + +import java.util.ArrayList; +import java.util.List; + +@BlockEntity(name = "Skull", regex = "skull") +public class SkullBlockEntityTranslator extends BlockEntityTranslator implements RequiresBlockState { + + @Override + public boolean isBlock(BlockState blockState) { + return BlockStateValues.getSkullVariant(blockState) != -1; + } + + @Override + public List> translateTag(com.github.steveice10.opennbt.tag.builtin.CompoundTag tag, BlockState blockState) { + List> tags = new ArrayList<>(); + byte skullVariant = BlockStateValues.getSkullVariant(blockState); + float rotation = BlockStateValues.getSkullRotation(blockState) * 22.5f; + // Just in case... + if (skullVariant == -1) skullVariant = 0; + tags.add(new FloatTag("Rotation", rotation)); + tags.add(new ByteTag("SkullType", skullVariant)); + return tags; + } + + @Override + public com.github.steveice10.opennbt.tag.builtin.CompoundTag getDefaultJavaTag(String javaId, int x, int y, int z) { + return null; + } + + @Override + public CompoundTag getDefaultBedrockTag(String bedrockId, int x, int y, int z) { + CompoundTagBuilder tagBuilder = getConstantBedrockTag(bedrockId, x, y, z).toBuilder(); + tagBuilder.floatTag("Rotation", 0); + tagBuilder.byteTag("SkullType", (byte) 0); + return tagBuilder.buildRootTag(); + } +} diff --git a/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java b/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java index 7afb8e6a9..41d0dc2d6 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java @@ -89,21 +89,12 @@ public class ChunkUtils { // Check to see if the name is in BlockTranslator.getBlockEntityString, and therefore must be handled differently if (BlockTranslator.getBlockEntityString(blockState) != null) { - // Get the block entity translator - BlockEntityTranslator blockEntityTranslator = BlockEntityUtils.getBlockEntityTranslator(BlockTranslator.getBlockEntityString(blockState)); Position pos = new ChunkPosition(column.getX(), column.getZ()).getBlock(x, (chunkY << 4) + y, z); blockEntityPositions.put(pos, blockState); - // If there is a delay required for the block, allow it. - if (blockEntityTranslator.getClass().getAnnotation(BlockEntity.class).delay()) { - chunkData.loadBlockEntitiesLater.put(blockEntityTranslator.getDefaultBedrockTag(BlockEntityUtils.getBedrockBlockEntityId(BlockTranslator.getBlockEntityString(blockState)), - pos.getX(), pos.getY(), pos.getZ()), blockState.getId()); - } else { - section.getBlockStorageArray()[0].setFullBlock(ChunkSection.blockPosition(x, y, z), id); - } - } else { - section.getBlockStorageArray()[0].setFullBlock(ChunkSection.blockPosition(x, y, z), id); } + section.getBlockStorageArray()[0].setFullBlock(ChunkSection.blockPosition(x, y, z), id); + // Check if block is piston or flower - only block entities in Bedrock if (BlockStateValues.getFlowerPotValues().containsKey(blockState.getId()) || BlockStateValues.getPistonValues().containsKey(blockState.getId())) { From 2355c503c929f792634c78cb26f7b9c2528a656f Mon Sep 17 00:00:00 2001 From: James Harrison Date: Fri, 8 May 2020 03:49:44 +0100 Subject: [PATCH 051/140] Enderchest and Invisible Players fix. (#506) * Fix EnderChests not showing on legacy servers (Hypixel) Fix NPCs/Players sometimes being invisible * Remove unused import * Fix standard --- .../java/entity/player/JavaPlayerListEntryTranslator.java | 3 ++- .../java/org/geysermc/connector/utils/BlockEntityUtils.java | 6 ++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerListEntryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerListEntryTranslator.java index 5fff40b12..2f71d6839 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerListEntryTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerListEntryTranslator.java @@ -63,8 +63,9 @@ public class JavaPlayerListEntryTranslator extends PacketTranslator Date: Thu, 7 May 2020 22:57:08 -0500 Subject: [PATCH 052/140] Add slime and magma cube size support --- .../connector/entity/living/SlimeEntity.java | 48 +++++++++++++++++++ .../connector/entity/type/EntityType.java | 4 +- 2 files changed, 50 insertions(+), 2 deletions(-) create mode 100644 connector/src/main/java/org/geysermc/connector/entity/living/SlimeEntity.java diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/SlimeEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/SlimeEntity.java new file mode 100644 index 000000000..26106f0a5 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/entity/living/SlimeEntity.java @@ -0,0 +1,48 @@ +/* + * 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.entity.living; + +import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata; +import com.nukkitx.math.vector.Vector3f; +import com.nukkitx.protocol.bedrock.data.EntityData; +import org.geysermc.connector.entity.type.EntityType; +import org.geysermc.connector.network.session.GeyserSession; + +public class SlimeEntity extends InsentientEntity { + + public SlimeEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { + super(entityId, geyserId, entityType, position, motion, rotation); + } + + @Override + public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { + if (entityMetadata.getId() == 15) { + this.metadata.put(EntityData.SCALE, 0.10f + (int) entityMetadata.getValue()); + } + super.updateBedrockMetadata(entityMetadata, session); + } +} diff --git a/connector/src/main/java/org/geysermc/connector/entity/type/EntityType.java b/connector/src/main/java/org/geysermc/connector/entity/type/EntityType.java index 98d836d20..1173796ff 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/type/EntityType.java +++ b/connector/src/main/java/org/geysermc/connector/entity/type/EntityType.java @@ -68,12 +68,12 @@ public enum EntityType { SKELETON(AbstractSkeletonEntity.class, 34, 1.8f, 0.6f, 0.6f, 1.62f), SPIDER(SpiderEntity.class, 35, 0.9f, 1.4f, 1.4f, 1f), ZOMBIE_PIGMAN(MonsterEntity.class, 36, 1.8f, 0.6f, 0.6f, 1.62f), - SLIME(InsentientEntity.class, 37, 0.51f), + SLIME(SlimeEntity.class, 37, 0.51f), ENDERMAN(EndermanEntity.class, 38, 2.9f, 0.6f), SILVERFISH(MonsterEntity.class, 39, 0.3f, 0.4f), CAVE_SPIDER(MonsterEntity.class, 40, 0.5f, 0.7f), GHAST(FlyingEntity.class, 41, 4.0f), - MAGMA_CUBE(InsentientEntity.class, 42, 0.51f), + MAGMA_CUBE(SlimeEntity.class, 42, 0.51f), BLAZE(BlazeEntity.class, 43, 1.8f, 0.6f), ZOMBIE_VILLAGER(ZombieEntity.class, 44, 1.8f, 0.6f, 0.6f, 1.62f), WITCH(RaidParticipantEntity.class, 45, 1.8f, 0.6f, 0.6f, 1.62f), From e58ffdd3c039a6c0d7e155535f2ed9e0d4effbd6 Mon Sep 17 00:00:00 2001 From: RednedEpic Date: Fri, 8 May 2020 00:18:05 -0500 Subject: [PATCH 053/140] Add support for block break animations from java players to bedrock --- .../world/JavaBlockBreakAnimTranslator.java | 95 +++++++++++++++++++ .../geysermc/connector/utils/BlockUtils.java | 8 +- 2 files changed, 101 insertions(+), 2 deletions(-) create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaBlockBreakAnimTranslator.java diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaBlockBreakAnimTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaBlockBreakAnimTranslator.java new file mode 100644 index 000000000..27bc34c98 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaBlockBreakAnimTranslator.java @@ -0,0 +1,95 @@ +/* + * 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.block.BlockState; +import com.github.steveice10.mc.protocol.packet.ingame.server.world.ServerBlockBreakAnimPacket; +import com.github.steveice10.opennbt.tag.builtin.CompoundTag; +import com.nukkitx.math.vector.Vector3f; +import com.nukkitx.protocol.bedrock.data.LevelEventType; +import com.nukkitx.protocol.bedrock.packet.LevelEventPacket; +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.item.ItemEntry; +import org.geysermc.connector.network.translators.world.block.BlockTranslator; +import org.geysermc.connector.utils.BlockUtils; + +@Translator(packet = ServerBlockBreakAnimPacket.class) +public class JavaBlockBreakAnimTranslator extends PacketTranslator { + + @Override + public void translate(ServerBlockBreakAnimPacket packet, GeyserSession session) { + BlockState state = session.getConnector().getWorldManager().getBlockAt(session, packet.getPosition().getX(), packet.getPosition().getY(), packet.getPosition().getZ()); + int breakTime = (int) (65535 / Math.ceil(BlockUtils.getBreakTime(BlockTranslator.JAVA_RUNTIME_ID_TO_HARDNESS.get(state.getId()), state.getId(), ItemEntry.AIR, new CompoundTag(""), null) * 20)); + LevelEventPacket levelEventPacket = new LevelEventPacket(); + levelEventPacket.setPosition(Vector3f.from( + packet.getPosition().getX(), + packet.getPosition().getY(), + packet.getPosition().getZ() + )); + levelEventPacket.setType(LevelEventType.BLOCK_START_BREAK); + + switch (packet.getStage()) { + case STAGE_1: + levelEventPacket.setData(breakTime); + break; + case STAGE_2: + levelEventPacket.setData(breakTime * 2); + break; + case STAGE_3: + levelEventPacket.setData(breakTime * 3); + break; + case STAGE_4: + levelEventPacket.setData(breakTime * 4); + break; + case STAGE_5: + levelEventPacket.setData(breakTime * 5); + break; + case STAGE_6: + levelEventPacket.setData(breakTime * 6); + break; + case STAGE_7: + levelEventPacket.setData(breakTime * 7); + break; + case STAGE_8: + levelEventPacket.setData(breakTime * 8); + break; + case STAGE_9: + levelEventPacket.setData(breakTime * 9); + break; + case STAGE_10: + levelEventPacket.setData(breakTime * 10); + break; + case RESET: + levelEventPacket.setType(LevelEventType.BLOCK_STOP_BREAK); + levelEventPacket.setData(0); + break; + } + session.sendUpstreamPacket(levelEventPacket); + } +} diff --git a/connector/src/main/java/org/geysermc/connector/utils/BlockUtils.java b/connector/src/main/java/org/geysermc/connector/utils/BlockUtils.java index 3a9ecb867..deddce586 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/BlockUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/BlockUtils.java @@ -114,9 +114,13 @@ public class BlockUtils { correctTool = correctTool(blockToolType, toolType); } int toolEfficiencyLevel = ItemUtils.getEnchantmentLevel(nbtData, "minecraft:efficiency"); - int hasteLevel = player.getEffectCache().getEffectLevel(Effect.FASTER_DIG); - int miningFatigueLevel = player.getEffectCache().getEffectLevel(Effect.SLOWER_DIG); + int hasteLevel = 0; + int miningFatigueLevel = 0; + if (player != null) { + hasteLevel = player.getEffectCache().getEffectLevel(Effect.FASTER_DIG); + miningFatigueLevel = player.getEffectCache().getEffectLevel(Effect.SLOWER_DIG); + } // TODO implement these checks and material check if possible //boolean insideOfWaterWithoutAquaAffinity = player.isInsideOfWater() && // Optional.ofNullable(player.getInventory().getHelmet().getEnchantment(Enchantment.ID_WATER_WORKER)) From 7b3893ff78d4e484386436e361f0d545a967997d Mon Sep 17 00:00:00 2001 From: rtm516 Date: Sat, 9 May 2020 04:58:29 +0100 Subject: [PATCH 054/140] Fixed empty listen IPs breaking automatic config (#519) --- .../java/org/geysermc/platform/bukkit/GeyserBukkitPlugin.java | 2 +- .../org/geysermc/platform/bungeecord/GeyserBungeePlugin.java | 2 +- .../java/org/geysermc/platform/sponge/GeyserSpongePlugin.java | 2 +- .../org/geysermc/platform/velocity/GeyserVelocityPlugin.java | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitPlugin.java b/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitPlugin.java index d6bd31acd..579e8b16d 100644 --- a/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitPlugin.java +++ b/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitPlugin.java @@ -59,7 +59,7 @@ public class GeyserBukkitPlugin extends JavaPlugin implements GeyserBootstrap { // Don't change the ip if its listening on all interfaces // By default this should be 127.0.0.1 but may need to be changed in some circumstances - if (!Bukkit.getIp().equals("0.0.0.0")) { + if (!Bukkit.getIp().equals("0.0.0.0") && !Bukkit.getIp().equals("")) { getConfig().set("remote.address", Bukkit.getIp()); } diff --git a/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/GeyserBungeePlugin.java b/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/GeyserBungeePlugin.java index bfd0cf49c..488854c9e 100644 --- a/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/GeyserBungeePlugin.java +++ b/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/GeyserBungeePlugin.java @@ -91,7 +91,7 @@ public class GeyserBungeePlugin extends Plugin implements GeyserBootstrap { // Don't change the ip if its listening on all interfaces // By default this should be 127.0.0.1 but may need to be changed in some circumstances - if (!javaAddr.getHostString().equals("0.0.0.0")) { + if (!javaAddr.getHostString().equals("0.0.0.0") && !javaAddr.getHostString().equals("")) { configuration.set("remote.address", javaAddr.getHostString()); } diff --git a/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/GeyserSpongePlugin.java b/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/GeyserSpongePlugin.java index 01d71f1c0..0c323a5ec 100644 --- a/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/GeyserSpongePlugin.java +++ b/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/GeyserSpongePlugin.java @@ -97,7 +97,7 @@ public class GeyserSpongePlugin implements GeyserBootstrap { // Don't change the ip if its listening on all interfaces // By default this should be 127.0.0.1 but may need to be changed in some circumstances - if (!javaAddr.getHostString().equals("0.0.0.0")) { + if (!javaAddr.getHostString().equals("0.0.0.0") && !javaAddr.getHostString().equals("")) { serverIP.setValue("127.0.0.1"); } diff --git a/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityPlugin.java b/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityPlugin.java index bd8924133..0269d9335 100644 --- a/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityPlugin.java +++ b/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityPlugin.java @@ -83,7 +83,7 @@ public class GeyserVelocityPlugin implements GeyserBootstrap { // Don't change the ip if its listening on all interfaces // By default this should be 127.0.0.1 but may need to be changed in some circumstances - if (!javaAddr.getHostString().equals("0.0.0.0")) { + if (!javaAddr.getHostString().equals("0.0.0.0") && !javaAddr.getHostString().equals("")) { geyserConfig.getRemote().setAddress(javaAddr.getHostString()); } From d4291888b3f22b19bc309a6ca1e3bd98473c99d1 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+DoctorMacc@users.noreply.github.com> Date: Sat, 9 May 2020 22:37:18 -0400 Subject: [PATCH 055/140] Fallback to ViaVersion to convert block state (#515) * Fallback to ViaVersion to convert block state * Use ViaVersion 3.0.0-SNAPSHOT * Detect versions better; change logic for getting blocks --- bootstrap/bukkit/pom.xml | 6 +++ .../platform/bukkit/GeyserBukkitPlugin.java | 54 ++++++++++++++++++- .../world/GeyserBukkitWorldManager.java | 25 +++++++++ .../bukkit/src/main/resources/plugin.yml | 1 + pom.xml | 4 ++ 5 files changed, 89 insertions(+), 1 deletion(-) diff --git a/bootstrap/bukkit/pom.xml b/bootstrap/bukkit/pom.xml index 94fab83ba..1f831d673 100644 --- a/bootstrap/bukkit/pom.xml +++ b/bootstrap/bukkit/pom.xml @@ -23,6 +23,12 @@ 1.14-R0.1-SNAPSHOT provided + + us.myles + viaversion + 3.0.0-SNAPSHOT + provided + ${outputName}-Bukkit diff --git a/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitPlugin.java b/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitPlugin.java index 579e8b16d..3f2b9cad5 100644 --- a/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitPlugin.java +++ b/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitPlugin.java @@ -35,6 +35,7 @@ import org.geysermc.connector.network.translators.world.WorldManager; import org.geysermc.platform.bukkit.command.GeyserBukkitCommandExecutor; import org.geysermc.platform.bukkit.command.GeyserBukkitCommandManager; import org.geysermc.platform.bukkit.world.GeyserBukkitWorldManager; +import us.myles.ViaVersion.api.Via; import java.util.UUID; @@ -73,7 +74,24 @@ public class GeyserBukkitPlugin extends JavaPlugin implements GeyserBootstrap { this.connector = GeyserConnector.start(PlatformType.BUKKIT, this); this.geyserCommandManager = new GeyserBukkitCommandManager(this, connector); - this.geyserWorldManager = new GeyserBukkitWorldManager(); + + boolean isViaVersion = false; + // Used to determine if Block.getBlockData() is present. + boolean isLegacy = !isCompatible(Bukkit.getServer().getVersion(), "1.13.0"); + if (isLegacy) + geyserLogger.debug("Legacy version of Minecraft (1.12.2 or older) detected."); + + if (Bukkit.getPluginManager().getPlugin("ViaVersion") != null) { + // TODO: Update when ViaVersion updates + // API changes between 2.2.3 and 3.0.0-SNAPSHOT require this check + if (!Via.getAPI().getVersion().equals("3.0.0-SNAPSHOT") && isLegacy) { + geyserLogger.info("ViaVersion detected but not ViaVersion-ABSTRACTION. Please update your ViaVersion plugin for compatibility with Geyser."); + } else { + isViaVersion = true; + } + } + + this.geyserWorldManager = new GeyserBukkitWorldManager(isLegacy, isViaVersion); this.getCommand("geyser").setExecutor(new GeyserBukkitCommandExecutor(connector)); } @@ -102,4 +120,38 @@ public class GeyserBukkitPlugin extends JavaPlugin implements GeyserBootstrap { public WorldManager getWorldManager() { return this.geyserWorldManager; } + + public boolean isCompatible(String version, String whichVersion) { + int[] currentVersion = parseVersion(version); + int[] otherVersion = parseVersion(whichVersion); + int length = Math.max(currentVersion.length, otherVersion.length); + for (int index = 0; index < length; index = index + 1) { + int self = (index < currentVersion.length) ? currentVersion[index] : 0; + int other = (index < otherVersion.length) ? otherVersion[index] : 0; + + if (self != other) { + return (self - other) > 0; + } + } + return true; + } + + private int[] parseVersion(String versionParam) { + versionParam = (versionParam == null) ? "" : versionParam; + if (versionParam.contains("(MC: ")) { + versionParam = versionParam.split("\\(MC: ")[1]; + versionParam = versionParam.split("\\)")[0]; + } + String[] stringArray = versionParam.split("[_.-]"); + int[] temp = new int[stringArray.length]; + for (int index = 0; index <= (stringArray.length - 1); index = index + 1) { + String t = stringArray[index].replaceAll("\\D", ""); + try { + temp[index] = Integer.parseInt(t); + } catch(NumberFormatException ex) { + temp[index] = 0; + } + } + return temp; + } } diff --git a/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/world/GeyserBukkitWorldManager.java b/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/world/GeyserBukkitWorldManager.java index 07fc31361..44a520e8d 100644 --- a/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/world/GeyserBukkitWorldManager.java +++ b/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/world/GeyserBukkitWorldManager.java @@ -28,18 +28,43 @@ package org.geysermc.platform.bukkit.world; import com.github.steveice10.mc.protocol.data.game.world.block.BlockState; +import lombok.AllArgsConstructor; import org.bukkit.Bukkit; +import org.bukkit.block.Block; import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.world.WorldManager; import org.geysermc.connector.network.translators.world.block.BlockTranslator; +import us.myles.ViaVersion.protocols.protocol1_13_1to1_13.Protocol1_13_1To1_13; +import us.myles.ViaVersion.protocols.protocol1_15to1_14_4.data.MappingData; +@AllArgsConstructor public class GeyserBukkitWorldManager extends WorldManager { + private final boolean isLegacy; + // You need ViaVersion to connect to an older server with Geyser. + // However, we still check for ViaVersion in case there's some other way that gets Geyser on a pre-1.13 Bukkit server + private final boolean isViaVersion; + @Override + @SuppressWarnings("deprecation") public BlockState getBlockAt(GeyserSession session, int x, int y, int z) { if (session.getPlayerEntity() == null) { return BlockTranslator.AIR; } + if (isLegacy) { + if (isViaVersion) { + Block block = Bukkit.getPlayer(session.getPlayerEntity().getUsername()).getWorld().getBlockAt(x, y, z); + // Black magic that gets the old block state ID + int oldBlockId = (block.getType().getId() << 4) | (block.getData() & 0xF); + // Convert block state from old version -> 1.13 -> 1.13.1 -> 1.14 -> 1.15 + int thirteenBlockId = us.myles.ViaVersion.protocols.protocol1_13to1_12_2.data.MappingData.blockMappings.getNewId(oldBlockId); + int thirteenPointOneBlockId = Protocol1_13_1To1_13.getNewBlockStateId(thirteenBlockId); + int fourteenBlockId = us.myles.ViaVersion.protocols.protocol1_14to1_13_2.data.MappingData.blockStateMappings.getNewId(thirteenPointOneBlockId); + return new BlockState(MappingData.blockStateMappings.getNewId(fourteenBlockId)); + } else { + return BlockTranslator.AIR; + } + } return BlockTranslator.getJavaIdBlockMap().get(Bukkit.getPlayer(session.getPlayerEntity().getUsername()).getWorld().getBlockAt(x, y, z).getBlockData().getAsString()); } } diff --git a/bootstrap/bukkit/src/main/resources/plugin.yml b/bootstrap/bukkit/src/main/resources/plugin.yml index 8e002eb22..7e32f0e1f 100644 --- a/bootstrap/bukkit/src/main/resources/plugin.yml +++ b/bootstrap/bukkit/src/main/resources/plugin.yml @@ -3,6 +3,7 @@ name: ${outputName}-Bukkit author: ${project.organization.name} website: ${project.organization.url} version: ${project.version} +softdepend: ["ViaVersion"] commands: geyser: description: The main command for Geyser. diff --git a/pom.xml b/pom.xml index fc1ead33b..a82d6217e 100644 --- a/pom.xml +++ b/pom.xml @@ -67,6 +67,10 @@ true + + viaversion-repo + https://repo.viaversion.com + From 34d48177959fea4d53677431fe8e737420166abd Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+DoctorMacc@users.noreply.github.com> Date: Sun, 10 May 2020 15:26:00 -0400 Subject: [PATCH 056/140] Add visual support for double chests (#523) * Add visual support for double chests * Update mappings submodule --- .../world/block/BlockStateValues.java | 19 +++ .../world/block/DoubleChestValue.java | 52 +++++++++ .../DoubleChestBlockEntityTranslator.java | 108 ++++++++++++++++++ connector/src/main/resources/mappings | 2 +- 4 files changed, 180 insertions(+), 1 deletion(-) create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/world/block/DoubleChestValue.java create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/DoubleChestBlockEntityTranslator.java diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/world/block/BlockStateValues.java b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/BlockStateValues.java index de08b7e8b..070a0592c 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/world/block/BlockStateValues.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/BlockStateValues.java @@ -47,6 +47,7 @@ public class BlockStateValues { private static final Object2IntMap BANNER_COLORS = new Object2IntOpenHashMap<>(); private static final Object2ByteMap BED_COLORS = new Object2ByteOpenHashMap<>(); + private static final Int2ObjectMap DOUBLE_CHEST_VALUES = new Int2ObjectOpenHashMap<>(); private static final Int2ObjectMap FLOWER_POT_VALUES = new Int2ObjectOpenHashMap<>(); private static final Map FLOWER_POT_BLOCKS = new HashMap<>(); private static final Object2IntMap NOTEBLOCK_PITCHES = new Object2IntOpenHashMap<>(); @@ -74,6 +75,15 @@ public class BlockStateValues { return; } + if (entry.getValue().get("double_chest_position") != null) { + boolean isX = (entry.getValue().get("x") != null); + boolean isDirectionPositive = ((entry.getValue().get("x") != null && entry.getValue().get("x").asBoolean()) || + (entry.getValue().get("z") != null && entry.getValue().get("z").asBoolean())); + boolean isLeft = (entry.getValue().get("double_chest_position").asText().contains("left")); + DOUBLE_CHEST_VALUES.put(javaBlockState.getId(), new DoubleChestValue(isX, isDirectionPositive, isLeft)); + return; + } + if (entry.getKey().contains("potted_")) { FLOWER_POT_VALUES.put(javaBlockState.getId(), entry.getKey().replace("potted_", "")); return; @@ -136,6 +146,15 @@ public class BlockStateValues { return -1; } + /** + * All double chest values are part of the block state in Java and part of the block entity tag in Bedrock. + * This gives the DoubleChestValue that can be calculated into the final tag. + * @return The map of all DoubleChestValues. + */ + public static Int2ObjectMap getDoubleChestValues() { + return DOUBLE_CHEST_VALUES; + } + /** * Get the Int2ObjectMap of flower pot block states to containing plant * @return Int2ObjectMap of flower pot values diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/world/block/DoubleChestValue.java b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/DoubleChestValue.java new file mode 100644 index 000000000..5bd217241 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/DoubleChestValue.java @@ -0,0 +1,52 @@ +/* + * 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.world.block; + +import lombok.AllArgsConstructor; + +/** + * This stores all values of double chests that are part of the Java block state. + */ +@AllArgsConstructor +public class DoubleChestValue { + + /** + * If true, then chest is facing east/west; if false, south/north + */ + public boolean isFacingEast; + + /** + * If true, direction is positive (east/south); if false, direction is negative (west/north) + */ + public boolean isDirectionPositive; + + /** + * If true, chest is the left of a pair; if false, chest is the right of a pair. + */ + public boolean isLeft; + +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/DoubleChestBlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/DoubleChestBlockEntityTranslator.java new file mode 100644 index 000000000..f5599832d --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/DoubleChestBlockEntityTranslator.java @@ -0,0 +1,108 @@ +/* + * 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.world.block.entity; + +import com.github.steveice10.mc.protocol.data.game.world.block.BlockState; +import com.github.steveice10.opennbt.tag.builtin.CompoundTag; +import com.nukkitx.math.vector.Vector3i; +import com.nukkitx.nbt.CompoundTagBuilder; +import com.nukkitx.nbt.tag.ByteTag; +import com.nukkitx.nbt.tag.IntTag; +import com.nukkitx.nbt.tag.Tag; +import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.world.block.BlockStateValues; +import org.geysermc.connector.network.translators.world.block.DoubleChestValue; +import org.geysermc.connector.utils.BlockEntityUtils; + +import java.util.ArrayList; +import java.util.List; + +/** + * Chests have more block entity properties in Bedrock, which is solved by implementing the BedrockOnlyBlockEntity + */ +@BlockEntity(name = "Chest", regex = "chest") +public class DoubleChestBlockEntityTranslator extends BlockEntityTranslator implements BedrockOnlyBlockEntity, RequiresBlockState { + + @Override + public boolean isBlock(BlockState blockState) { + return BlockStateValues.getDoubleChestValues().containsKey(blockState.getId()); + } + + @Override + public void updateBlock(GeyserSession session, BlockState blockState, Vector3i position) { + CompoundTag javaTag = getConstantJavaTag("chest", position.getX(), position.getY(), position.getZ()); + CompoundTagBuilder tagBuilder = getConstantBedrockTag(BlockEntityUtils.getBedrockBlockEntityId("chest"), position.getX(), position.getY(), position.getZ()).toBuilder(); + translateTag(javaTag, blockState).forEach(tagBuilder::tag); + BlockEntityUtils.updateBlockEntity(session, tagBuilder.buildRootTag(), position); + } + + @Override + public List> translateTag(CompoundTag tag, BlockState blockState) { + List> tags = new ArrayList<>(); + if (blockState != null && BlockStateValues.getDoubleChestValues().containsKey(blockState.getId())) { + DoubleChestValue chestValues = BlockStateValues.getDoubleChestValues().get(blockState.getId()); + if (chestValues != null) { + int x = (int) tag.getValue().get("x").getValue(); + int z = (int) tag.getValue().get("z").getValue(); + // Calculate the position of the other chest based on the Java block state + if (chestValues.isFacingEast) { + if (chestValues.isDirectionPositive) { + // East + z = z + (chestValues.isLeft ? 1 : -1); + } else { + // West + z = z + (chestValues.isLeft ? -1 : 1); + } + } else { + if (chestValues.isDirectionPositive) { + // South + x = x + (chestValues.isLeft ? -1 : 1); + } else { + // North + x = x + (chestValues.isLeft ? 1 : -1); + } + } + tags.add(new IntTag("pairx", x)); + tags.add(new IntTag("pairz", z)); + if (!chestValues.isLeft) { + tags.add(new ByteTag("pairlead", (byte) 1)); + } + } + } + return tags; + } + + @Override + public CompoundTag getDefaultJavaTag(String javaId, int x, int y, int z) { + return null; + } + + @Override + public com.nukkitx.nbt.tag.CompoundTag getDefaultBedrockTag(String bedrockId, int x, int y, int z) { + return null; + } +} diff --git a/connector/src/main/resources/mappings b/connector/src/main/resources/mappings index 5b3a9ad1d..a7963d0a0 160000 --- a/connector/src/main/resources/mappings +++ b/connector/src/main/resources/mappings @@ -1 +1 @@ -Subproject commit 5b3a9ad1d2ef76105fb318e63126a096844b3195 +Subproject commit a7963d0a0236b1c47eea21718ac50706139d90cc From 6192237cc986a9fcbae3350efe92936836b14ef5 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+DoctorMacc@users.noreply.github.com> Date: Sun, 10 May 2020 15:38:39 -0400 Subject: [PATCH 057/140] Add parrots on player shoulders (#530) * Add parrots on player shoulders Parrots on player shoulders are a separate entity in Bedrock, but part of the player metadata in Java. This commit creates a parrot entity from the NBT data given by the player's entity data. * Remove unused import * Nullify parrot after despawning * Remove debug code --- .../connector/entity/PlayerEntity.java | 62 ++++++++++++++++++- 1 file changed, 59 insertions(+), 3 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/entity/PlayerEntity.java b/connector/src/main/java/org/geysermc/connector/entity/PlayerEntity.java index 82e91f553..a5d2d9a89 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/PlayerEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/PlayerEntity.java @@ -28,13 +28,13 @@ package org.geysermc.connector.entity; import com.github.steveice10.mc.auth.data.GameProfile; import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata; import com.github.steveice10.mc.protocol.data.message.TextMessage; +import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.nukkitx.math.vector.Vector3f; import com.nukkitx.protocol.bedrock.data.CommandPermission; import com.nukkitx.protocol.bedrock.data.EntityData; +import com.nukkitx.protocol.bedrock.data.EntityLink; import com.nukkitx.protocol.bedrock.data.PlayerPermission; -import com.nukkitx.protocol.bedrock.packet.AddPlayerPacket; -import com.nukkitx.protocol.bedrock.packet.MovePlayerPacket; -import com.nukkitx.protocol.bedrock.packet.PlayerListPacket; +import com.nukkitx.protocol.bedrock.packet.*; import lombok.Getter; import lombok.Setter; @@ -48,6 +48,7 @@ import org.geysermc.connector.network.session.cache.EntityEffectCache; import org.geysermc.connector.utils.SkinUtils; import java.util.UUID; +import java.util.concurrent.TimeUnit; @Getter @Setter public class PlayerEntity extends LivingEntity { @@ -58,6 +59,9 @@ public class PlayerEntity extends LivingEntity { private boolean playerList = true; private final EntityEffectCache effectCache; + private Entity leftParrot; + private Entity rightParrot; + public PlayerEntity(GameProfile gameProfile, long entityId, long geyserId, Vector3f position, Vector3f motion, Vector3f rotation) { super(entityId, geyserId, EntityType.PLAYER, position, motion, rotation); @@ -146,6 +150,12 @@ public class PlayerEntity extends LivingEntity { } session.sendUpstreamPacket(movePlayerPacket); + if (leftParrot != null) { + leftParrot.moveAbsolute(session, position, rotation, true, teleported); + } + if (rightParrot != null) { + rightParrot.moveAbsolute(session, position, rotation, true, teleported); + } } @Override @@ -160,6 +170,12 @@ public class PlayerEntity extends LivingEntity { movePlayerPacket.setOnGround(isOnGround); movePlayerPacket.setMode(MovePlayerPacket.Mode.NORMAL); session.sendUpstreamPacket(movePlayerPacket); + if (leftParrot != null) { + leftParrot.moveRelative(session, relX, relY, relZ, rotation, true); + } + if (rightParrot != null) { + rightParrot.moveRelative(session, relX, relY, relZ, rotation, true); + } } @Override @@ -188,5 +204,45 @@ public class PlayerEntity extends LivingEntity { metadata.put(EntityData.NAMETAG, team.getPrefix() + MessageUtils.toChatColor(team.getColor()) + username + team.getSuffix()); } } + + // Parrot occupying shoulder + if (entityMetadata.getId() == 18 || entityMetadata.getId() == 19) { + CompoundTag tag = (CompoundTag) entityMetadata.getValue(); + if (tag != null && !tag.isEmpty()) { + // The parrot is a separate entity in Bedrock, but part of the player entity in Java + Entity parrot = new Entity(0, session.getEntityCache().getNextEntityId().incrementAndGet(), + EntityType.PARROT, position, motion, rotation); + parrot.spawnEntity(session); + parrot.getMetadata().put(EntityData.VARIANT, tag.get("Variant").getValue()); + // Different position whether the parrot is left or right + float offset = (entityMetadata.getId() == 18) ? 0.4f : -0.4f; + parrot.getMetadata().put(EntityData.RIDER_SEAT_POSITION, Vector3f.from(offset, -0.22, -0.1)); + parrot.getMetadata().put(EntityData.RIDER_ROTATION_LOCKED, 1); + parrot.updateBedrockMetadata(session); + SetEntityLinkPacket linkPacket = new SetEntityLinkPacket(); + EntityLink.Type type = (entityMetadata.getId() == 18) ? EntityLink.Type.RIDER : EntityLink.Type.PASSENGER; + linkPacket.setEntityLink(new EntityLink(geyserId, parrot.getGeyserId(), type, false)); + // Delay, or else spawned-in players won't get the link + // TODO: Find a better solution. This problem also exists with item frames + session.getConnector().getGeneralThreadPool().schedule(() -> session.sendUpstreamPacket(linkPacket), 500, TimeUnit.MILLISECONDS); + if (entityMetadata.getId() == 18) { + leftParrot = parrot; + } else { + rightParrot = parrot; + } + } else { + Entity parrot = (entityMetadata.getId() == 18 ? leftParrot : rightParrot); + if (parrot != null) { + SetEntityLinkPacket linkPacket = new SetEntityLinkPacket(); + linkPacket.setEntityLink(new EntityLink(parrot.getGeyserId(), geyserId, EntityLink.Type.REMOVE, false)); + parrot.despawnEntity(session); + if (entityMetadata.getId() == 18) { + leftParrot = null; + } else { + rightParrot = null; + } + } + } + } } } From d2a18f8fd59ee0e6dd715acfcb39b13e16bb40f8 Mon Sep 17 00:00:00 2001 From: RednedEpic Date: Sun, 10 May 2020 14:47:40 -0500 Subject: [PATCH 058/140] Remove dangling entity link packet in PlayerEntity for parrots --- .../main/java/org/geysermc/connector/entity/PlayerEntity.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/entity/PlayerEntity.java b/connector/src/main/java/org/geysermc/connector/entity/PlayerEntity.java index a5d2d9a89..43891a7ed 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/PlayerEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/PlayerEntity.java @@ -233,8 +233,6 @@ public class PlayerEntity extends LivingEntity { } else { Entity parrot = (entityMetadata.getId() == 18 ? leftParrot : rightParrot); if (parrot != null) { - SetEntityLinkPacket linkPacket = new SetEntityLinkPacket(); - linkPacket.setEntityLink(new EntityLink(parrot.getGeyserId(), geyserId, EntityLink.Type.REMOVE, false)); parrot.despawnEntity(session); if (entityMetadata.getId() == 18) { leftParrot = null; From cf6309886498c6a11a650c1e81b8c38878f6277f Mon Sep 17 00:00:00 2001 From: RednedEpic Date: Sun, 10 May 2020 15:03:12 -0500 Subject: [PATCH 059/140] Add Windows Phone in DeviceOS (Fixes #520) --- common/src/main/java/org/geysermc/floodgate/util/DeviceOS.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/common/src/main/java/org/geysermc/floodgate/util/DeviceOS.java b/common/src/main/java/org/geysermc/floodgate/util/DeviceOS.java index bd8e40027..93d3c121e 100644 --- a/common/src/main/java/org/geysermc/floodgate/util/DeviceOS.java +++ b/common/src/main/java/org/geysermc/floodgate/util/DeviceOS.java @@ -43,7 +43,8 @@ public enum DeviceOS { ORBIS("PS4"), NX("Switch"), SWITCH("Switch"), - XBOX_ONE("Xbox One"); + XBOX_ONE("Xbox One"), + WIN_PHONE("Windows Phone"); private static final DeviceOS[] VALUES = values(); From 720ae3c92dbcf7355f9ed7e7dd66b8e049571462 Mon Sep 17 00:00:00 2001 From: Heath123 Date: Sun, 10 May 2020 21:05:51 +0100 Subject: [PATCH 060/140] Add survival-style block pick support (#526) * Add survival-style block pick support * Add BedrockBlockPickRequestPacketTranslator.java * Remove unnecessary println * Edit styling and add null check * Fix compile error * Remove nesting and unnecessary check * Further reduce nesting * Change 1-line statements and add missing comment * Fix creating translator * Fix imports --- ...drockBlockPickRequestPacketTranslator.java | 104 ++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockBlockPickRequestPacketTranslator.java diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockBlockPickRequestPacketTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockBlockPickRequestPacketTranslator.java new file mode 100644 index 000000000..288b99d31 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockBlockPickRequestPacketTranslator.java @@ -0,0 +1,104 @@ +/* + * 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.bedrock; + +import com.github.steveice10.mc.protocol.data.game.world.block.BlockState; +import com.github.steveice10.mc.protocol.packet.ingame.client.window.ClientMoveItemToHotbarPacket; +import com.nukkitx.math.vector.Vector3i; +import com.nukkitx.protocol.bedrock.packet.BlockPickRequestPacket; +import com.nukkitx.protocol.bedrock.packet.PlayerHotbarPacket; +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.PacketTranslator; +import org.geysermc.connector.network.translators.Translator; +import org.geysermc.connector.network.translators.item.ItemEntry; +import org.geysermc.connector.network.translators.world.block.BlockTranslator; +import org.geysermc.connector.network.translators.item.ItemTranslator; +import org.geysermc.connector.network.translators.Translators; + +@Translator(packet = BlockPickRequestPacket.class) +public class BedrockBlockPickRequestPacketTranslator extends PacketTranslator { + + @Override + public void translate(BlockPickRequestPacket packet, GeyserSession session) { + Vector3i vector = packet.getBlockPosition(); + BlockState blockToPick = session.getConnector().getWorldManager().getBlockAt(session, vector.getX(), vector.getY(), vector.getZ()); + + // Block is air - chunk caching is probably off + if (blockToPick.getId() == 0) { + return; + } + + // Get the inventory to choose a slot to pick + Inventory inventory = session.getInventoryCache().getOpenInventory(); + if (inventory == null) { + inventory = session.getInventory(); + } + + String targetIdentifier = BlockTranslator.getJavaIdBlockMap().inverse().get(blockToPick).split("\\[")[0]; + ItemTranslator itemTranslator = Translators.getItemTranslator(); + + // Check hotbar for item + for (int i = 36; i < 45; i++) { + if (inventory.getItem(i) == null) { + continue; + } + ItemEntry item = itemTranslator.getItem(inventory.getItem(i)); + // If this isn't the item we're looking for + if (!item.getJavaIdentifier().equals(targetIdentifier)) { + continue; + } + + PlayerHotbarPacket hotbarPacket = new PlayerHotbarPacket(); + hotbarPacket.setContainerId(0); + // Java inventory slot to hotbar slot ID + hotbarPacket.setSelectedHotbarSlot(i - 36); + hotbarPacket.setSelectHotbarSlot(true); + session.sendUpstreamPacket(hotbarPacket); + session.getInventory().setHeldItemSlot(i - 36); + // Don't check inventory if item was in hotbar + return; + } + + // Check inventory for item + for (int i = 9; i < 36; i++) { + if (inventory.getItem(i) == null) { + continue; + } + ItemEntry item = itemTranslator.getItem(inventory.getItem(i)); + // If this isn't the item we're looking for + if (!item.getJavaIdentifier().equals(targetIdentifier)) { + continue; + } + + ClientMoveItemToHotbarPacket packetToSend = new ClientMoveItemToHotbarPacket(i); // https://wiki.vg/Protocol#Pick_Item + session.sendDownstreamPacket(packetToSend); + return; + } + } +} From 64bfad2af94ef40bf73c6d27652a76f654c2b81e Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+DoctorMacc@users.noreply.github.com> Date: Sun, 10 May 2020 16:25:28 -0400 Subject: [PATCH 061/140] Use Bukkit methods to send block sound (#522) --- .../platform/bukkit/GeyserBukkitPlugin.java | 4 ++ .../world/GeyserBukkitBlockPlaceListener.java | 63 +++++++++++++++++++ .../java/world/JavaBlockChangeTranslator.java | 3 +- 3 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/world/GeyserBukkitBlockPlaceListener.java diff --git a/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitPlugin.java b/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitPlugin.java index 3f2b9cad5..9ab025835 100644 --- a/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitPlugin.java +++ b/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitPlugin.java @@ -34,6 +34,7 @@ import org.geysermc.connector.command.CommandManager; import org.geysermc.connector.network.translators.world.WorldManager; import org.geysermc.platform.bukkit.command.GeyserBukkitCommandExecutor; import org.geysermc.platform.bukkit.command.GeyserBukkitCommandManager; +import org.geysermc.platform.bukkit.world.GeyserBukkitBlockPlaceListener; import org.geysermc.platform.bukkit.world.GeyserBukkitWorldManager; import us.myles.ViaVersion.api.Via; @@ -44,6 +45,7 @@ public class GeyserBukkitPlugin extends JavaPlugin implements GeyserBootstrap { private GeyserBukkitCommandManager geyserCommandManager; private GeyserBukkitConfiguration geyserConfig; private GeyserBukkitLogger geyserLogger; + private GeyserBukkitBlockPlaceListener blockPlaceListener; private GeyserBukkitWorldManager geyserWorldManager; private GeyserConnector connector; @@ -92,6 +94,8 @@ public class GeyserBukkitPlugin extends JavaPlugin implements GeyserBootstrap { } this.geyserWorldManager = new GeyserBukkitWorldManager(isLegacy, isViaVersion); + this.blockPlaceListener = new GeyserBukkitBlockPlaceListener(connector); + Bukkit.getServer().getPluginManager().registerEvents(blockPlaceListener, this); this.getCommand("geyser").setExecutor(new GeyserBukkitCommandExecutor(connector)); } diff --git a/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/world/GeyserBukkitBlockPlaceListener.java b/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/world/GeyserBukkitBlockPlaceListener.java new file mode 100644 index 000000000..d4b57145a --- /dev/null +++ b/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/world/GeyserBukkitBlockPlaceListener.java @@ -0,0 +1,63 @@ +/* + * 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.platform.bukkit.world; + +import com.nukkitx.math.vector.Vector3f; +import com.nukkitx.protocol.bedrock.data.SoundEvent; +import com.nukkitx.protocol.bedrock.packet.LevelSoundEventPacket; +import lombok.AllArgsConstructor; +import org.bukkit.Bukkit; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.block.BlockPlaceEvent; +import org.geysermc.connector.GeyserConnector; +import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.world.block.BlockTranslator; + +@AllArgsConstructor +public class GeyserBukkitBlockPlaceListener implements Listener { + + private final GeyserConnector connector; + + @EventHandler + public void place(final BlockPlaceEvent event) { + for (GeyserSession session : connector.getPlayers().values()) { + if (event.getPlayer() == Bukkit.getPlayer(session.getPlayerEntity().getUsername())) { + LevelSoundEventPacket placeBlockSoundPacket = new LevelSoundEventPacket(); + placeBlockSoundPacket.setSound(SoundEvent.PLACE); + placeBlockSoundPacket.setPosition(Vector3f.from(event.getBlockPlaced().getX(), event.getBlockPlaced().getY(), event.getBlockPlaced().getZ())); + placeBlockSoundPacket.setBabySound(false); + placeBlockSoundPacket.setExtraData(BlockTranslator.getBedrockBlockId(BlockTranslator.getJavaIdBlockMap().get(event.getBlockPlaced().getBlockData().getAsString()))); + placeBlockSoundPacket.setIdentifier(":"); + session.sendUpstreamPacket(placeBlockSoundPacket); + session.setLastBlockPlacePosition(null); + session.setLastBlockPlacedId(null); + } + } + } + +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaBlockChangeTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaBlockChangeTranslator.java index 0fa58ef8a..2eb04a8ae 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaBlockChangeTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaBlockChangeTranslator.java @@ -29,6 +29,7 @@ import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position; import com.nukkitx.math.vector.Vector3i; import com.nukkitx.protocol.bedrock.data.SoundEvent; import com.nukkitx.protocol.bedrock.packet.LevelSoundEventPacket; +import org.geysermc.common.PlatformType; import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.PacketTranslator; import org.geysermc.connector.network.translators.Translator; @@ -46,7 +47,7 @@ public class JavaBlockChangeTranslator extends PacketTranslator Date: Mon, 11 May 2020 06:09:16 +0100 Subject: [PATCH 062/140] Various entity fixes (#529) * Fixed invisible entities nametags being displayed * Fixed most entity collision boxes * Fixed area effect cloud not displaying * Fixed armour stand size and marker * Fix baby collision boxes * Fixed squid animation (rotation still broken) * Fix Guardian beam for local player * Fixed armour stand invisibility * Fixed Wither boss data * Fixed fishing line attach to entities --- .../entity/AreaEffectCloudEntity.java | 61 +++++++++++++ .../org/geysermc/connector/entity/Entity.java | 40 +++++---- .../connector/entity/FishingHookEntity.java | 17 ++++ .../entity/living/AbstractFishEntity.java | 10 --- .../entity/living/AgeableEntity.java | 3 + .../entity/living/ArmorStandEntity.java | 25 +++++- .../connector/entity/living/SquidEntity.java | 36 ++++++++ .../connector/entity/living/WaterEntity.java | 3 + .../entity/living/monster/GuardianEntity.java | 4 + .../entity/living/monster/WitherEntity.java | 89 +++++++++++++++++++ .../connector/entity/type/EntityType.java | 52 +++++------ 11 files changed, 287 insertions(+), 53 deletions(-) create mode 100644 connector/src/main/java/org/geysermc/connector/entity/AreaEffectCloudEntity.java create mode 100644 connector/src/main/java/org/geysermc/connector/entity/living/SquidEntity.java create mode 100644 connector/src/main/java/org/geysermc/connector/entity/living/monster/WitherEntity.java diff --git a/connector/src/main/java/org/geysermc/connector/entity/AreaEffectCloudEntity.java b/connector/src/main/java/org/geysermc/connector/entity/AreaEffectCloudEntity.java new file mode 100644 index 000000000..2808b093c --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/entity/AreaEffectCloudEntity.java @@ -0,0 +1,61 @@ +/* + * 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.entity; + +import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata; +import com.github.steveice10.mc.protocol.data.game.world.particle.Particle; +import com.nukkitx.math.vector.Vector3f; +import com.nukkitx.protocol.bedrock.data.EntityData; +import org.geysermc.connector.entity.type.EntityType; +import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.utils.EffectUtils; + +public class AreaEffectCloudEntity extends Entity { + + public AreaEffectCloudEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { + super(entityId, geyserId, entityType, position, motion, rotation); + + // Without this the cloud doesn't appear, + metadata.put(EntityData.AREA_EFFECT_CLOUD_DURATION, 600); + + // This disabled client side shrink of the cloud + metadata.put(EntityData.AREA_EFFECT_CLOUD_RADIUS_PER_TICK, 0.0f); + } + + @Override + public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { + if (entityMetadata.getId() == 7) { + metadata.put(EntityData.AREA_EFFECT_CLOUD_RADIUS, (float) entityMetadata.getValue()); + metadata.put(EntityData.BOUNDING_BOX_WIDTH, 2.0f * (float) entityMetadata.getValue()); + } else if (entityMetadata.getId() == 10) { + Particle particle = (Particle) entityMetadata.getValue(); + metadata.put(EntityData.AREA_EFFECT_CLOUD_PARTICLE_ID, EffectUtils.getParticleString(particle.getType())); + } else if (entityMetadata.getId() == 8) { + metadata.put(EntityData.POTION_COLOR, entityMetadata.getValue()); + } + super.updateBedrockMetadata(entityMetadata, session); + } +} diff --git a/connector/src/main/java/org/geysermc/connector/entity/Entity.java b/connector/src/main/java/org/geysermc/connector/entity/Entity.java index 186c0ae8f..d911ff7ac 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/Entity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/Entity.java @@ -35,24 +35,28 @@ import com.github.steveice10.mc.protocol.data.message.TextMessage; import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerActionPacket; import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerUseItemPacket; import com.nukkitx.math.vector.Vector3f; -import com.nukkitx.protocol.bedrock.data.*; +import com.nukkitx.protocol.bedrock.data.EntityData; +import com.nukkitx.protocol.bedrock.data.EntityDataMap; +import com.nukkitx.protocol.bedrock.data.EntityFlag; +import com.nukkitx.protocol.bedrock.data.EntityFlags; import com.nukkitx.protocol.bedrock.packet.*; - import it.unimi.dsi.fastutil.longs.LongOpenHashSet; import it.unimi.dsi.fastutil.longs.LongSet; - import lombok.Getter; import lombok.Setter; - import org.geysermc.connector.entity.attribute.Attribute; import org.geysermc.connector.entity.attribute.AttributeType; +import org.geysermc.connector.entity.living.ArmorStandEntity; import org.geysermc.connector.entity.type.EntityType; import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.item.ItemTranslator; import org.geysermc.connector.utils.AttributeUtils; import org.geysermc.connector.utils.MessageUtils; -import java.util.*; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; @Getter @Setter @@ -205,6 +209,16 @@ public class Entity { metadata.getFlags().setFlag(EntityFlag.SWIMMING, (xd & 0x10) == 0x10); metadata.getFlags().setFlag(EntityFlag.GLIDING, (xd & 0x80) == 0x80); + metadata.put(EntityData.SCALE, scale); + + if ((xd & 0x20) == 0x20) { + if (this.is(ArmorStandEntity.class)) { + metadata.put(EntityData.SCALE, 0.0f); + } else { + metadata.getFlags().setFlag(EntityFlag.INVISIBLE, true); + } + } + // Shield code if (session.getPlayerEntity().getEntityId() == entityId && metadata.getFlags().getFlag(EntityFlag.SNEAKING)) { if ((session.getInventory().getItemInHand() != null && session.getInventory().getItemInHand().getId() == ItemTranslator.SHIELD) || @@ -221,16 +235,11 @@ public class Entity { session.sendDownstreamPacket(useItemPacket); } } else if (session.getPlayerEntity().getEntityId() == entityId && !metadata.getFlags().getFlag(EntityFlag.SNEAKING) && metadata.getFlags().getFlag(EntityFlag.BLOCKING)) { - metadata.getFlags().setFlag(EntityFlag.BLOCKING, false); - metadata.getFlags().setFlag(EntityFlag.DISABLE_BLOCKING, true); - ClientPlayerActionPacket releaseItemPacket = new ClientPlayerActionPacket(PlayerAction.RELEASE_USE_ITEM, new Position(0,0,0), BlockFace.DOWN); - session.sendDownstreamPacket(releaseItemPacket); - } - // metadata.getFlags().setFlag(EntityFlag.INVISIBLE, (xd & 0x20) == 0x20); - if ((xd & 0x20) == 0x20) - metadata.put(EntityData.SCALE, 0.0f); - else - metadata.put(EntityData.SCALE, scale); + metadata.getFlags().setFlag(EntityFlag.BLOCKING, false); + metadata.getFlags().setFlag(EntityFlag.DISABLE_BLOCKING, true); + ClientPlayerActionPacket releaseItemPacket = new ClientPlayerActionPacket(PlayerAction.RELEASE_USE_ITEM, new Position(0, 0, 0), BlockFace.DOWN); + session.sendDownstreamPacket(releaseItemPacket); + } } break; case 2: // custom name @@ -270,6 +279,7 @@ public class Entity { /** * x = Pitch, y = HeadYaw, z = Yaw + * * @return the bedrock rotation */ public Vector3f getBedrockRotation() { diff --git a/connector/src/main/java/org/geysermc/connector/entity/FishingHookEntity.java b/connector/src/main/java/org/geysermc/connector/entity/FishingHookEntity.java index abd522929..8d8d5ef24 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/FishingHookEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/FishingHookEntity.java @@ -25,6 +25,7 @@ package org.geysermc.connector.entity; +import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata; import com.github.steveice10.mc.protocol.data.game.entity.type.object.ProjectileData; import com.nukkitx.math.vector.Vector3f; import com.nukkitx.protocol.bedrock.data.EntityData; @@ -44,4 +45,20 @@ public class FishingHookEntity extends Entity { } } } + + @Override + public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { + if (entityMetadata.getId() == 7) { + Entity entity = session.getEntityCache().getEntityByJavaId((Integer) entityMetadata.getValue() - 1); + if (entity == null && session.getPlayerEntity().getEntityId() == (Integer) entityMetadata.getValue() - 1) { + entity = session.getPlayerEntity(); + } + + if (entity != null) { + metadata.put(EntityData.TARGET_EID, entity.getGeyserId()); + } + } + + super.updateBedrockMetadata(entityMetadata, session); + } } diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/AbstractFishEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/AbstractFishEntity.java index 54443825a..de5fa1b5b 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/living/AbstractFishEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/living/AbstractFishEntity.java @@ -25,28 +25,18 @@ package org.geysermc.connector.entity.living; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata; import com.nukkitx.math.vector.Vector3f; -import com.nukkitx.protocol.bedrock.data.EntityData; import com.nukkitx.protocol.bedrock.data.EntityFlag; import org.geysermc.connector.entity.type.EntityType; -import org.geysermc.connector.network.session.GeyserSession; public class AbstractFishEntity extends WaterEntity { public AbstractFishEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { super(entityId, geyserId, entityType, position, motion, rotation); - } - @Override - public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { metadata.getFlags().setFlag(EntityFlag.CAN_SWIM, true); metadata.getFlags().setFlag(EntityFlag.BREATHING, true); metadata.getFlags().setFlag(EntityFlag.CAN_CLIMB, false); metadata.getFlags().setFlag(EntityFlag.HAS_GRAVITY, false); - - metadata.put(EntityData.AIR, (short) 400); - - super.updateBedrockMetadata(entityMetadata, session); } } diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/AgeableEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/AgeableEntity.java index 634f06743..b90983f78 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/living/AgeableEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/living/AgeableEntity.java @@ -44,6 +44,9 @@ public class AgeableEntity extends CreatureEntity { boolean isBaby = (boolean) entityMetadata.getValue(); metadata.put(EntityData.SCALE, isBaby ? .55f : 1f); metadata.getFlags().setFlag(EntityFlag.BABY, isBaby); + + metadata.put(EntityData.BOUNDING_BOX_HEIGHT, entityType.getHeight() * (isBaby ? 0.55f : 1f)); + metadata.put(EntityData.BOUNDING_BOX_WIDTH, entityType.getWidth() * (isBaby ? 0.55f : 1f)); } super.updateBedrockMetadata(entityMetadata, session); diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/ArmorStandEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/ArmorStandEntity.java index 1beb8ab8f..3c05933f2 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/living/ArmorStandEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/living/ArmorStandEntity.java @@ -29,6 +29,7 @@ import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadat import com.github.steveice10.mc.protocol.data.game.entity.metadata.MetadataType; import com.nukkitx.math.vector.Vector3f; import com.nukkitx.protocol.bedrock.data.EntityData; +import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.entity.LivingEntity; import org.geysermc.connector.entity.type.EntityType; import org.geysermc.connector.network.session.GeyserSession; @@ -43,8 +44,28 @@ public class ArmorStandEntity extends LivingEntity { public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { if (entityMetadata.getType() == MetadataType.BYTE) { byte xd = (byte) entityMetadata.getValue(); - if ((xd & 0x01) == 0x01 && (metadata.get(EntityData.SCALE) != null && !metadata.get(EntityData.SCALE).equals(0.0f))) { - metadata.put(EntityData.SCALE, .55f); + + // isSmall + if ((xd & 0x01) == 0x01) { + GeyserConnector.getInstance().getLogger().debug("S: " + metadata.get(EntityData.SCALE)); + + if (metadata.get(EntityData.SCALE) == null || (metadata.get(EntityData.SCALE) != null && !metadata.get(EntityData.SCALE).equals(0.55f))) { + metadata.put(EntityData.SCALE, 0.55f); + } + + if (metadata.get(EntityData.BOUNDING_BOX_WIDTH) != null && metadata.get(EntityData.BOUNDING_BOX_WIDTH).equals(0.5f)) { + metadata.put(EntityData.BOUNDING_BOX_WIDTH, 0.25f); + metadata.put(EntityData.BOUNDING_BOX_HEIGHT, 0.9875f); + } + } else if (metadata.get(EntityData.BOUNDING_BOX_WIDTH) != null && metadata.get(EntityData.BOUNDING_BOX_WIDTH).equals(0.25f)) { + metadata.put(EntityData.BOUNDING_BOX_WIDTH, entityType.getWidth()); + metadata.put(EntityData.BOUNDING_BOX_HEIGHT, entityType.getHeight()); + } + + // setMarker + if ((xd & 0x10) == 0x10 && (metadata.get(EntityData.BOUNDING_BOX_WIDTH) != null && !metadata.get(EntityData.BOUNDING_BOX_WIDTH).equals(0.0f))) { + metadata.put(EntityData.BOUNDING_BOX_WIDTH, 0.0f); + metadata.put(EntityData.BOUNDING_BOX_HEIGHT, 0.0f); } } super.updateBedrockMetadata(entityMetadata, session); diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/SquidEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/SquidEntity.java new file mode 100644 index 000000000..81c0eeef1 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/entity/living/SquidEntity.java @@ -0,0 +1,36 @@ +/* + * 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.entity.living; + +import com.nukkitx.math.vector.Vector3f; +import org.geysermc.connector.entity.type.EntityType; + +public class SquidEntity extends WaterEntity { + + public SquidEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { + super(entityId, geyserId, entityType, position, motion, rotation); + } +} diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/WaterEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/WaterEntity.java index dc83847a1..69afd9754 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/living/WaterEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/living/WaterEntity.java @@ -26,11 +26,14 @@ package org.geysermc.connector.entity.living; import com.nukkitx.math.vector.Vector3f; +import com.nukkitx.protocol.bedrock.data.EntityData; import org.geysermc.connector.entity.type.EntityType; public class WaterEntity extends CreatureEntity { public WaterEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { super(entityId, geyserId, entityType, position, motion, rotation); + + metadata.put(EntityData.AIR, (short) 400); } } diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/monster/GuardianEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/monster/GuardianEntity.java index 682b02b24..3abbebbac 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/living/monster/GuardianEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/living/monster/GuardianEntity.java @@ -42,6 +42,10 @@ public class GuardianEntity extends MonsterEntity { public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { if (entityMetadata.getId() == 16) { Entity entity = session.getEntityCache().getEntityByJavaId((int) entityMetadata.getValue()); + if (entity == null && session.getPlayerEntity().getEntityId() == (Integer) entityMetadata.getValue()) { + entity = session.getPlayerEntity(); + } + if (entity != null) { metadata.put(EntityData.TARGET_EID, entity.getGeyserId()); } diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/monster/WitherEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/monster/WitherEntity.java new file mode 100644 index 000000000..062f4388d --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/entity/living/monster/WitherEntity.java @@ -0,0 +1,89 @@ +/* + * 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.entity.living.monster; + +import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata; +import com.nukkitx.math.vector.Vector3f; +import com.nukkitx.protocol.bedrock.data.EntityData; +import org.geysermc.connector.entity.Entity; +import org.geysermc.connector.entity.attribute.Attribute; +import org.geysermc.connector.entity.attribute.AttributeType; +import org.geysermc.connector.entity.type.EntityType; +import org.geysermc.connector.network.session.GeyserSession; + +public class WitherEntity extends MonsterEntity { + + public WitherEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { + super(entityId, geyserId, entityType, position, motion, rotation); + + // After WITHER_AERIAL_ATTACK gets fixed in NukkitX/Protocol this can be uncommented + // It hides the withers shield + //metadata.put(EntityData.WITHER_AERIAL_ATTACK, (short) 1); + } + + @Override + public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { + long targetID = -1; + + if (entityMetadata.getId() >= 15 && entityMetadata.getId() <= 17) { + Entity entity = session.getEntityCache().getEntityByJavaId((int) entityMetadata.getValue()); + if (entity == null && session.getPlayerEntity().getEntityId() == (Integer) entityMetadata.getValue()) { + entity = session.getPlayerEntity(); + } + + if (entity != null) { + targetID = entity.getGeyserId(); + } + } + + if (entityMetadata.getId() == 15) { + metadata.put(EntityData.WITHER_TARGET_1, targetID); + } else if (entityMetadata.getId() == 16) { + metadata.put(EntityData.WITHER_TARGET_2, targetID); + } else if (entityMetadata.getId() == 17) { + metadata.put(EntityData.WITHER_TARGET_3, targetID); + } else if (entityMetadata.getId() == 18) { + metadata.put(EntityData.WITHER_INVULNERABLE_TICKS, (int) entityMetadata.getValue()); + + // Show the shield for the first few seconds of spawning (like Java) + if ((int) entityMetadata.getValue() >= 175) { + //metadata.put(EntityData.WITHER_AERIAL_ATTACK, (short) 0); + } else { + //metadata.put(EntityData.WITHER_AERIAL_ATTACK, (short) 1); + } + } + + // If less than 50% health show shield + Attribute health = attributes.get(AttributeType.HEALTH); + if ((health.getValue() <= health.getMaximum() / 2) || health.getMaximum() == 300f) { + //metadata.put(EntityData.WITHER_AERIAL_ATTACK, (short) 0); + } else { + //metadata.put(EntityData.WITHER_AERIAL_ATTACK, (short) 1); + } + + super.updateBedrockMetadata(entityMetadata, session); + } +} diff --git a/connector/src/main/java/org/geysermc/connector/entity/type/EntityType.java b/connector/src/main/java/org/geysermc/connector/entity/type/EntityType.java index 1173796ff..5ab4eb1ae 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/type/EntityType.java +++ b/connector/src/main/java/org/geysermc/connector/entity/type/EntityType.java @@ -47,7 +47,7 @@ public enum EntityType { WOLF(WolfEntity.class, 14, 0.85f, 0.6f), VILLAGER(VillagerEntity.class, 15, 1.8f, 0.6f, 0.6f, 1.62f, "minecraft:villager_v2"), MOOSHROOM(AnimalEntity.class, 16, 1.4f, 0.9f), - SQUID(WaterEntity.class, 17, 0.8f), + SQUID(SquidEntity.class, 17, 0.8f), RABBIT(RabbitEntity.class, 18, 0.5f, 0.4f), BAT(AmbientEntity.class, 19, 0.9f, 0.5f), IRON_GOLEM(GolemEntity.class, 20, 2.7f, 1.4f), @@ -83,7 +83,7 @@ public enum EntityType { GUARDIAN(GuardianEntity.class, 49, 0.85f), ELDER_GUARDIAN(GuardianEntity.class, 50, 1.9975f), NPC(PlayerEntity.class, 51, 1.8f, 0.6f, 0.6f, 1.62f), - WITHER(MonsterEntity.class, 52, 3.5f, 0.9f), + WITHER(WitherEntity.class, 52, 3.5f, 0.9f), ENDER_DRAGON(EnderDragonEntity.class, 53, 4f, 13f), SHULKER(ShulkerEntity.class, 54, 1f, 1f), ENDERMITE(MonsterEntity.class, 55, 0.3f, 0.4f), @@ -94,7 +94,7 @@ public enum EntityType { PHANTOM(FlyingEntity.class, 58, 0.5f, 0.9f, 0.9f, 0.6f), RAVAGER(RaidParticipantEntity.class, 59, 1.9f, 1.2f), - ARMOR_STAND(ArmorStandEntity.class, 61, 0f), + ARMOR_STAND(ArmorStandEntity.class, 61, 1.975f, 0.5f), TRIPOD_CAMERA(Entity.class, 62, 0f), PLAYER(PlayerEntity.class, 63, 1.8f, 0.6f, 0.6f, 1.62f), ITEM(ItemEntity.class, 64, 0.25f, 0.25f), @@ -103,41 +103,41 @@ public enum EntityType { MOVING_BLOCK(Entity.class, 67, 0f), EXPERIENCE_BOTTLE(ThrowableEntity.class, 68, 0.25f, 0.25f, 0f, 0f, "minecraft:xp_bottle"), EXPERIENCE_ORB(ExpOrbEntity.class, 69, 0f, 0f, 0f, 0f, "minecraft:xp_orb"), - EYE_OF_ENDER(Entity.class, 70, 0f), + EYE_OF_ENDER(Entity.class, 70, 0.25f), END_CRYSTAL(EnderCrystalEntity.class, 71, 0f, 0f, 0f, 0f, "minecraft:ender_crystal"), - FIREWORK_ROCKET(Entity.class, 72, 0f), + FIREWORK_ROCKET(Entity.class, 72, 0.25f), TRIDENT(ArrowEntity.class, 73, 0f), TURTLE(AnimalEntity.class, 74, 0.4f, 1.2f), CAT(CatEntity.class, 75, 0.35f, 0.3f), - SHULKER_BULLET(Entity.class, 76, 0f), + SHULKER_BULLET(Entity.class, 76, 0.3125f), FISHING_BOBBER(FishingHookEntity.class, 77, 0f, 0f, 0f, 0f, "minecraft:fishing_hook"), CHALKBOARD(Entity.class, 78, 0f), - DRAGON_FIREBALL(ItemedFireballEntity.class, 79, 0f), + DRAGON_FIREBALL(ItemedFireballEntity.class, 79, 1.0f), ARROW(ArrowEntity.class, 80, 0.25f, 0.25f), - SNOWBALL(ThrowableEntity.class, 81, 0f), - EGG(ThrowableEntity.class, 82, 0f), + SNOWBALL(ThrowableEntity.class, 81, 0.25f), + EGG(ThrowableEntity.class, 82, 0.25f), PAINTING(PaintingEntity.class, 83, 0f), - MINECART(MinecartEntity.class, 84, 0f), - FIREBALL(ItemedFireballEntity.class, 85, 0f), - POTION(ThrowableEntity.class, 86, 0f), - ENDER_PEARL(ThrowableEntity.class, 87, 0f), - LEASH_KNOT(Entity.class, 88, 0f), - WITHER_SKULL(Entity.class, 89, 0f), + MINECART(MinecartEntity.class, 84, 0.7f, 0.98f), + FIREBALL(ItemedFireballEntity.class, 85, 1.0f), + POTION(ThrowableEntity.class, 86, 0.25f), + ENDER_PEARL(ThrowableEntity.class, 87, 0.25f), + LEASH_KNOT(Entity.class, 88, 0.5f, 0.375f), + WITHER_SKULL(Entity.class, 89, 0.3125f), BOAT(Entity.class, 90, 0.7f, 1.6f, 1.6f, 0.35f), WITHER_SKULL_DANGEROUS(Entity.class, 91, 0f), LIGHTNING_BOLT(Entity.class, 93, 0f), - SMALL_FIREBALL(ItemedFireballEntity.class, 94, 0f), - AREA_EFFECT_CLOUD(Entity.class, 95, 0f), - HOPPER_MINECART(MinecartEntity.class, 96, 0f), - TNT_MINECART(MinecartEntity.class, 97, 0f), - CHEST_MINECART(MinecartEntity.class, 98, 0f), + SMALL_FIREBALL(ItemedFireballEntity.class, 94, 0.3125f), + AREA_EFFECT_CLOUD(AreaEffectCloudEntity.class, 95, 0.5f, 1.0f), + HOPPER_MINECART(MinecartEntity.class, 96, 0.7f, 0.98f), + TNT_MINECART(MinecartEntity.class, 97, 0.7f, 0.98f), + CHEST_MINECART(MinecartEntity.class, 98, 0.7f, 0.98f), - COMMAND_BLOCK_MINECART(MinecartEntity.class, 100, 0f), + COMMAND_BLOCK_MINECART(MinecartEntity.class, 100, 0.7f, 0.98f), LINGERING_POTION(ThrowableEntity.class, 101, 0f), - LLAMA_SPIT(Entity.class, 102, 0f), - EVOKER_FANGS(Entity.class, 103, 0f), - EVOKER(SpellcasterIllagerEntity.class, 104, 0f), - VEX(MonsterEntity.class, 105, 0f), + LLAMA_SPIT(Entity.class, 102, 0.25f), + EVOKER_FANGS(Entity.class, 103, 0.8f, 0.5f), + EVOKER(SpellcasterIllagerEntity.class, 104, 1.95f, 0.5f), + VEX(MonsterEntity.class, 105, 0.8f, 0.4f), ICE_BOMB(Entity.class, 106, 0f), BALLOON(Entity.class, 107, 0f), //TODO PUFFERFISH(PufferFishEntity.class, 108, 0.7f, 0.7f), @@ -163,7 +163,7 @@ public enum EntityType { private String identifier; EntityType(Class entityClass, int type, float height) { - this(entityClass, type, height, 0f); + this(entityClass, type, height, height); } EntityType(Class entityClass, int type, float height, float width) { From 324bc67c97935832927a03949208885fc8a37503 Mon Sep 17 00:00:00 2001 From: rtm516 Date: Mon, 11 May 2020 20:56:50 +0100 Subject: [PATCH 063/140] Fixed small armour stands not respecting invisibility (#533) --- .../src/main/java/org/geysermc/connector/entity/Entity.java | 2 -- .../geysermc/connector/entity/living/ArmorStandEntity.java | 5 +---- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/entity/Entity.java b/connector/src/main/java/org/geysermc/connector/entity/Entity.java index d911ff7ac..ae3679feb 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/Entity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/Entity.java @@ -209,8 +209,6 @@ public class Entity { metadata.getFlags().setFlag(EntityFlag.SWIMMING, (xd & 0x10) == 0x10); metadata.getFlags().setFlag(EntityFlag.GLIDING, (xd & 0x80) == 0x80); - metadata.put(EntityData.SCALE, scale); - if ((xd & 0x20) == 0x20) { if (this.is(ArmorStandEntity.class)) { metadata.put(EntityData.SCALE, 0.0f); diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/ArmorStandEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/ArmorStandEntity.java index 3c05933f2..8d3c8f8fd 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/living/ArmorStandEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/living/ArmorStandEntity.java @@ -29,7 +29,6 @@ import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadat import com.github.steveice10.mc.protocol.data.game.entity.metadata.MetadataType; import com.nukkitx.math.vector.Vector3f; import com.nukkitx.protocol.bedrock.data.EntityData; -import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.entity.LivingEntity; import org.geysermc.connector.entity.type.EntityType; import org.geysermc.connector.network.session.GeyserSession; @@ -47,9 +46,7 @@ public class ArmorStandEntity extends LivingEntity { // isSmall if ((xd & 0x01) == 0x01) { - GeyserConnector.getInstance().getLogger().debug("S: " + metadata.get(EntityData.SCALE)); - - if (metadata.get(EntityData.SCALE) == null || (metadata.get(EntityData.SCALE) != null && !metadata.get(EntityData.SCALE).equals(0.55f))) { + if (metadata.getFloat(EntityData.SCALE) != 0.55f && metadata.getFloat(EntityData.SCALE) != 0.0f) { metadata.put(EntityData.SCALE, 0.55f); } From c84c0f23cb583b65970593ee1b870134bda3a049 Mon Sep 17 00:00:00 2001 From: rtm516 Date: Tue, 12 May 2020 05:44:30 +0100 Subject: [PATCH 064/140] Fixed invisible flag not getting set back (#535) * Fixed invisible flag not getting set back * Fixed indentation --- .../src/main/java/org/geysermc/connector/entity/Entity.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/connector/src/main/java/org/geysermc/connector/entity/Entity.java b/connector/src/main/java/org/geysermc/connector/entity/Entity.java index ae3679feb..2fe830afd 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/Entity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/Entity.java @@ -215,6 +215,8 @@ public class Entity { } else { metadata.getFlags().setFlag(EntityFlag.INVISIBLE, true); } + } else { + metadata.getFlags().setFlag(EntityFlag.INVISIBLE, false); } // Shield code From 0c60af66b2a6503fc762af2ab215fb8219826e3b Mon Sep 17 00:00:00 2001 From: rtm516 Date: Tue, 12 May 2020 05:45:16 +0100 Subject: [PATCH 065/140] Fixed customised skins causing strange display (#534) * Fixed customised skins causing strange display * Cleaned up floodgate player checking * Fixed cape scale Co-authored-by: James Harrison --- .../connector/network/session/GeyserSession.java | 2 +- .../network/session/auth/BedrockClientData.java | 15 +++++++++++++++ .../geysermc/connector/utils/SkinProvider.java | 4 +++- .../org/geysermc/connector/utils/SkinUtils.java | 7 ++++--- 4 files changed, 23 insertions(+), 5 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java b/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java index 759a0f3b3..fa9960f2e 100644 --- a/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java +++ b/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java @@ -341,7 +341,7 @@ public class GeyserSession implements CommandSender { playerEntity.setUuid(profile.getId()); // Check if they are not using a linked account - if (!playerEntity.getUuid().toString().startsWith("00000000-0000-0000")) { + if (connector.getAuthType() == AuthType.OFFLINE || playerEntity.getUuid().getMostSignificantBits() == 0) { SkinUtils.handleBedrockSkin(playerEntity, clientData); } } diff --git a/connector/src/main/java/org/geysermc/connector/network/session/auth/BedrockClientData.java b/connector/src/main/java/org/geysermc/connector/network/session/auth/BedrockClientData.java index 4ef0fe79c..6aeebbaa3 100644 --- a/connector/src/main/java/org/geysermc/connector/network/session/auth/BedrockClientData.java +++ b/connector/src/main/java/org/geysermc/connector/network/session/auth/BedrockClientData.java @@ -32,12 +32,18 @@ public class BedrockClientData { private String capeId; @JsonProperty(value = "CapeData") private byte[] capeData; + @JsonProperty(value = "CapeImageHeight") + private int capeImageHeight; + @JsonProperty(value = "CapeImageWidth") + private int capeImageWidth; @JsonProperty(value = "CapeOnClassicSkin") private boolean capeOnClassicSkin; @JsonProperty(value = "SkinResourcePatch") private String geometryName; @JsonProperty(value = "SkinGeometryData") private String geometryData; + @JsonProperty(value = "PersonaSkin") + private boolean personaSkin; @JsonProperty(value = "PremiumSkin") private boolean premiumSkin; @@ -64,6 +70,15 @@ public class BedrockClientData { @JsonProperty(value = "ClientRandomId") private long clientRandomId; + @JsonProperty(value = "ArmSize") + private String armSize; + @JsonProperty(value = "SkinAnimationData") + private String skinAnimationData; + @JsonProperty(value = "SkinColor") + private String skinColor; + @JsonProperty(value = "ThirdPartyNameOnly") + private boolean thirdPartyNameOnly; + public enum UIProfile { @JsonEnumDefaultValue CLASSIC, diff --git a/connector/src/main/java/org/geysermc/connector/utils/SkinProvider.java b/connector/src/main/java/org/geysermc/connector/utils/SkinProvider.java index 15cccf223..469ae7588 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/SkinProvider.java +++ b/connector/src/main/java/org/geysermc/connector/utils/SkinProvider.java @@ -223,7 +223,9 @@ public class SkinProvider { // if the requested image is an cape if (provider != null) { - image = image.getWidth() > 64 ? scale(image) : image; + while(image.getWidth() > 64) { + image = scale(image); + } BufferedImage newImage = new BufferedImage(64, 32, BufferedImage.TYPE_INT_RGB); Graphics g = newImage.createGraphics(); g.drawImage(image, 0, 0, image.getWidth(), image.getHeight(), null); diff --git a/connector/src/main/java/org/geysermc/connector/utils/SkinUtils.java b/connector/src/main/java/org/geysermc/connector/utils/SkinUtils.java index 1d0ee2168..8e68d3e12 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/SkinUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/SkinUtils.java @@ -220,13 +220,14 @@ public class SkinUtils { byte[] geometryNameBytes = com.github.steveice10.mc.auth.util.Base64.decode(clientData.getGeometryName().getBytes("UTF-8")); byte[] geometryBytes = com.github.steveice10.mc.auth.util.Base64.decode(clientData.getGeometryData().getBytes("UTF-8")); - if (skinBytes.length <= (128 * 128 * 4)) { + if (skinBytes.length <= (128 * 128 * 4) && !clientData.isPersonaSkin()) { SkinProvider.storeBedrockSkin(playerEntity.getUuid(), data.getSkinUrl(), skinBytes); + SkinProvider.storeBedrockGeometry(playerEntity.getUuid(), geometryNameBytes, geometryBytes); } else { - GeyserConnector.getInstance().getLogger().info("Unable to load bedrock skin for '" + playerEntity.getUsername() + "' as they are using a customised skin"); + GeyserConnector.getInstance().getLogger().info("Unable to load bedrock skin for '" + playerEntity.getUsername() + "' as they are likely using a customised skin"); GeyserConnector.getInstance().getLogger().debug("The size of '" + playerEntity.getUsername() + "' skin is: " + clientData.getSkinImageWidth() + "x" + clientData.getSkinImageHeight()); } - SkinProvider.storeBedrockGeometry(playerEntity.getUuid(), geometryNameBytes, geometryBytes); + if (!clientData.getCapeId().equals("")) { SkinProvider.storeBedrockCape(playerEntity.getUuid(), capeBytes); } From d63d0def5ad30d8547d98cc90f162f0784fa673b Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+DoctorMacc@users.noreply.github.com> Date: Tue, 12 May 2020 15:59:28 -0400 Subject: [PATCH 066/140] Break for loop in GeyserBukkitBlockPlaceListener when a player is found (#538) No need to keep searching when a player is found. --- .../platform/bukkit/world/GeyserBukkitBlockPlaceListener.java | 1 + 1 file changed, 1 insertion(+) diff --git a/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/world/GeyserBukkitBlockPlaceListener.java b/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/world/GeyserBukkitBlockPlaceListener.java index d4b57145a..877e66463 100644 --- a/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/world/GeyserBukkitBlockPlaceListener.java +++ b/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/world/GeyserBukkitBlockPlaceListener.java @@ -56,6 +56,7 @@ public class GeyserBukkitBlockPlaceListener implements Listener { session.sendUpstreamPacket(placeBlockSoundPacket); session.setLastBlockPlacePosition(null); session.setLastBlockPlacedId(null); + break; } } } From 46b005443555517248bab1ea21c7d8ae78d23ed0 Mon Sep 17 00:00:00 2001 From: rtm516 Date: Wed, 13 May 2020 03:31:42 +0100 Subject: [PATCH 067/140] Fixed guardian beam getting stuck on players (#540) * Fixed guardian beam getting stuck on players * Fixed formatting --- .../connector/entity/living/monster/GuardianEntity.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/monster/GuardianEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/monster/GuardianEntity.java index 3abbebbac..821faa850 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/living/monster/GuardianEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/living/monster/GuardianEntity.java @@ -48,6 +48,8 @@ public class GuardianEntity extends MonsterEntity { if (entity != null) { metadata.put(EntityData.TARGET_EID, entity.getGeyserId()); + } else { + metadata.put(EntityData.TARGET_EID, (long) 0); } } From 9673e1e4aa3432ade3d288765f22e6482fbb05db Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+DoctorMacc@users.noreply.github.com> Date: Wed, 13 May 2020 17:07:41 -0400 Subject: [PATCH 068/140] Use ViaVersion for block placing sounds (#551) GeyserBukkitBlockPlaceListener previous assumed that getBlockData() was available. This separates the ViaVersion code from getBlockAt to make it accessible elsewhere. --- .../platform/bukkit/GeyserBukkitPlugin.java | 2 +- .../world/GeyserBukkitBlockPlaceListener.java | 11 ++++++- .../world/GeyserBukkitWorldManager.java | 32 +++++++++++-------- 3 files changed, 30 insertions(+), 15 deletions(-) diff --git a/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitPlugin.java b/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitPlugin.java index 9ab025835..dda804b78 100644 --- a/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitPlugin.java +++ b/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitPlugin.java @@ -94,7 +94,7 @@ public class GeyserBukkitPlugin extends JavaPlugin implements GeyserBootstrap { } this.geyserWorldManager = new GeyserBukkitWorldManager(isLegacy, isViaVersion); - this.blockPlaceListener = new GeyserBukkitBlockPlaceListener(connector); + this.blockPlaceListener = new GeyserBukkitBlockPlaceListener(connector, isLegacy, isViaVersion); Bukkit.getServer().getPluginManager().registerEvents(blockPlaceListener, this); this.getCommand("geyser").setExecutor(new GeyserBukkitCommandExecutor(connector)); diff --git a/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/world/GeyserBukkitBlockPlaceListener.java b/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/world/GeyserBukkitBlockPlaceListener.java index 877e66463..76d1564ea 100644 --- a/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/world/GeyserBukkitBlockPlaceListener.java +++ b/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/world/GeyserBukkitBlockPlaceListener.java @@ -42,6 +42,8 @@ import org.geysermc.connector.network.translators.world.block.BlockTranslator; public class GeyserBukkitBlockPlaceListener implements Listener { private final GeyserConnector connector; + private final boolean isLegacy; + private final boolean isViaVersion; @EventHandler public void place(final BlockPlaceEvent event) { @@ -51,7 +53,14 @@ public class GeyserBukkitBlockPlaceListener implements Listener { placeBlockSoundPacket.setSound(SoundEvent.PLACE); placeBlockSoundPacket.setPosition(Vector3f.from(event.getBlockPlaced().getX(), event.getBlockPlaced().getY(), event.getBlockPlaced().getZ())); placeBlockSoundPacket.setBabySound(false); - placeBlockSoundPacket.setExtraData(BlockTranslator.getBedrockBlockId(BlockTranslator.getJavaIdBlockMap().get(event.getBlockPlaced().getBlockData().getAsString()))); + String javaBlockId; + if (isLegacy) { + javaBlockId = BlockTranslator.getJavaIdBlockMap().inverse().get(GeyserBukkitWorldManager.getLegacyBlock(session, + event.getBlockPlaced().getX(), event.getBlockPlaced().getY(), event.getBlockPlaced().getZ(), isViaVersion)); + } else { + javaBlockId = event.getBlockPlaced().getBlockData().getAsString(); + } + placeBlockSoundPacket.setExtraData(BlockTranslator.getBedrockBlockId(BlockTranslator.getJavaIdBlockMap().get(javaBlockId))); placeBlockSoundPacket.setIdentifier(":"); session.sendUpstreamPacket(placeBlockSoundPacket); session.setLastBlockPlacePosition(null); diff --git a/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/world/GeyserBukkitWorldManager.java b/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/world/GeyserBukkitWorldManager.java index 44a520e8d..fbdf2a47b 100644 --- a/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/world/GeyserBukkitWorldManager.java +++ b/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/world/GeyserBukkitWorldManager.java @@ -29,11 +29,13 @@ package org.geysermc.platform.bukkit.world; import com.github.steveice10.mc.protocol.data.game.world.block.BlockState; import lombok.AllArgsConstructor; +import lombok.Getter; import org.bukkit.Bukkit; import org.bukkit.block.Block; import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.world.WorldManager; import org.geysermc.connector.network.translators.world.block.BlockTranslator; +import org.geysermc.platform.bukkit.GeyserBukkitPlugin; import us.myles.ViaVersion.protocols.protocol1_13_1to1_13.Protocol1_13_1To1_13; import us.myles.ViaVersion.protocols.protocol1_15to1_14_4.data.MappingData; @@ -46,25 +48,29 @@ public class GeyserBukkitWorldManager extends WorldManager { private final boolean isViaVersion; @Override - @SuppressWarnings("deprecation") public BlockState getBlockAt(GeyserSession session, int x, int y, int z) { if (session.getPlayerEntity() == null) { return BlockTranslator.AIR; } if (isLegacy) { - if (isViaVersion) { - Block block = Bukkit.getPlayer(session.getPlayerEntity().getUsername()).getWorld().getBlockAt(x, y, z); - // Black magic that gets the old block state ID - int oldBlockId = (block.getType().getId() << 4) | (block.getData() & 0xF); - // Convert block state from old version -> 1.13 -> 1.13.1 -> 1.14 -> 1.15 - int thirteenBlockId = us.myles.ViaVersion.protocols.protocol1_13to1_12_2.data.MappingData.blockMappings.getNewId(oldBlockId); - int thirteenPointOneBlockId = Protocol1_13_1To1_13.getNewBlockStateId(thirteenBlockId); - int fourteenBlockId = us.myles.ViaVersion.protocols.protocol1_14to1_13_2.data.MappingData.blockStateMappings.getNewId(thirteenPointOneBlockId); - return new BlockState(MappingData.blockStateMappings.getNewId(fourteenBlockId)); - } else { - return BlockTranslator.AIR; - } + return getLegacyBlock(session, x, y, z, isViaVersion); } return BlockTranslator.getJavaIdBlockMap().get(Bukkit.getPlayer(session.getPlayerEntity().getUsername()).getWorld().getBlockAt(x, y, z).getBlockData().getAsString()); } + + @SuppressWarnings("deprecation") + public static BlockState getLegacyBlock(GeyserSession session, int x, int y, int z, boolean isViaVersion) { + if (isViaVersion) { + Block block = Bukkit.getPlayer(session.getPlayerEntity().getUsername()).getWorld().getBlockAt(x, y, z); + // Black magic that gets the old block state ID + int oldBlockId = (block.getType().getId() << 4) | (block.getData() & 0xF); + // Convert block state from old version -> 1.13 -> 1.13.1 -> 1.14 -> 1.15 + int thirteenBlockId = us.myles.ViaVersion.protocols.protocol1_13to1_12_2.data.MappingData.blockMappings.getNewId(oldBlockId); + int thirteenPointOneBlockId = Protocol1_13_1To1_13.getNewBlockStateId(thirteenBlockId); + int fourteenBlockId = us.myles.ViaVersion.protocols.protocol1_14to1_13_2.data.MappingData.blockStateMappings.getNewId(thirteenPointOneBlockId); + return new BlockState(MappingData.blockStateMappings.getNewId(fourteenBlockId)); + } else { + return BlockTranslator.AIR; + } + } } From 6aadfb3a63532085e299d5614bff871bc5c64d57 Mon Sep 17 00:00:00 2001 From: rtm516 Date: Wed, 13 May 2020 22:08:14 +0100 Subject: [PATCH 069/140] Fixed wither shield (#544) --- .../entity/living/monster/WitherEntity.java | 22 +++++-------------- 1 file changed, 5 insertions(+), 17 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/monster/WitherEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/monster/WitherEntity.java index 062f4388d..005d0db3a 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/living/monster/WitherEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/living/monster/WitherEntity.java @@ -29,8 +29,6 @@ import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadat import com.nukkitx.math.vector.Vector3f; import com.nukkitx.protocol.bedrock.data.EntityData; import org.geysermc.connector.entity.Entity; -import org.geysermc.connector.entity.attribute.Attribute; -import org.geysermc.connector.entity.attribute.AttributeType; import org.geysermc.connector.entity.type.EntityType; import org.geysermc.connector.network.session.GeyserSession; @@ -39,14 +37,12 @@ public class WitherEntity extends MonsterEntity { public WitherEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { super(entityId, geyserId, entityType, position, motion, rotation); - // After WITHER_AERIAL_ATTACK gets fixed in NukkitX/Protocol this can be uncommented - // It hides the withers shield - //metadata.put(EntityData.WITHER_AERIAL_ATTACK, (short) 1); + metadata.put(EntityData.WITHER_AERIAL_ATTACK, (short) 1); } @Override public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { - long targetID = -1; + long targetID = 0; if (entityMetadata.getId() >= 15 && entityMetadata.getId() <= 17) { Entity entity = session.getEntityCache().getEntityByJavaId((int) entityMetadata.getValue()); @@ -69,21 +65,13 @@ public class WitherEntity extends MonsterEntity { metadata.put(EntityData.WITHER_INVULNERABLE_TICKS, (int) entityMetadata.getValue()); // Show the shield for the first few seconds of spawning (like Java) - if ((int) entityMetadata.getValue() >= 175) { - //metadata.put(EntityData.WITHER_AERIAL_ATTACK, (short) 0); + if ((int) entityMetadata.getValue() >= 165) { + metadata.put(EntityData.WITHER_AERIAL_ATTACK, (short) 0); } else { - //metadata.put(EntityData.WITHER_AERIAL_ATTACK, (short) 1); + metadata.put(EntityData.WITHER_AERIAL_ATTACK, (short) 1); } } - // If less than 50% health show shield - Attribute health = attributes.get(AttributeType.HEALTH); - if ((health.getValue() <= health.getMaximum() / 2) || health.getMaximum() == 300f) { - //metadata.put(EntityData.WITHER_AERIAL_ATTACK, (short) 0); - } else { - //metadata.put(EntityData.WITHER_AERIAL_ATTACK, (short) 1); - } - super.updateBedrockMetadata(entityMetadata, session); } } From 278f59103e8977b97078623103b39c853a6a1eef Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+DoctorMacc@users.noreply.github.com> Date: Wed, 13 May 2020 17:08:32 -0400 Subject: [PATCH 070/140] Replace illusioners with pillagers (#550) Illusioners do not exist in Bedrock edition; this commit replaces them with pillagers so they can be somewhat replicated. --- .../org/geysermc/connector/entity/type/EntityType.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/connector/src/main/java/org/geysermc/connector/entity/type/EntityType.java b/connector/src/main/java/org/geysermc/connector/entity/type/EntityType.java index 5ab4eb1ae..c77baf0e7 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/type/EntityType.java +++ b/connector/src/main/java/org/geysermc/connector/entity/type/EntityType.java @@ -152,7 +152,12 @@ public enum EntityType { /** * Item frames are handled differently since they are a block in Bedrock. */ - ITEM_FRAME(ItemFrameEntity.class, 0, 0, 0); + ITEM_FRAME(ItemFrameEntity.class, 0, 0, 0), + + /** + * Not an entity in Bedrock, so we replace it with a Pillager + */ + ILLUSIONER(AbstractIllagerEntity.class, 114, 1.8f, 0.6f, 0.6f, 1.62f, "minecraft:pillager"); private Class entityClass; private final int type; From d5c14921e93972a380a6cadf55f40326577c5264 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+DoctorMacc@users.noreply.github.com> Date: Wed, 13 May 2020 17:08:52 -0400 Subject: [PATCH 071/140] Add message when playing record (#549) It appears that the record message is client-sided in Java Edition, so this sends a message whenever a record is played in-world. --- .../java/world/JavaPlayEffectTranslator.java | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaPlayEffectTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaPlayEffectTranslator.java index 8e76d7d8a..3afb79bd1 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaPlayEffectTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaPlayEffectTranslator.java @@ -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.TextPacket; import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.PacketTranslator; @@ -40,6 +41,10 @@ import org.geysermc.connector.network.translators.Translator; import org.geysermc.connector.network.translators.world.block.BlockTranslator; import org.geysermc.connector.network.translators.effect.Effect; import org.geysermc.connector.utils.EffectUtils; +import org.geysermc.connector.utils.LocaleUtils; + +import java.util.ArrayList; +import java.util.List; @Translator(packet = ServerPlayEffectPacket.class) public class JavaPlayEffectTranslator extends PacketTranslator { @@ -125,6 +130,22 @@ public class JavaPlayEffectTranslator extends PacketTranslator params = new ArrayList<>(); + // Couldn't figure out how to set this to Bedrock translation so it just uses the Java translation + String recordString = "item.minecraft." + EffectUtils.RECORDS.get(recordEffectData.getRecordId()).name().toLowerCase().replace("record_", "music_disc_") + ".desc"; + params.add(LocaleUtils.getLocaleString(recordString, session.getClientData().getLanguageCode())); + textPacket.setParameters(params); + session.sendUpstreamPacket(textPacket); + } } else { soundEvent.setSound(SoundEvent.valueOf(geyserEffect.getBedrockName())); } From c6527fa723038bdf433c5399cf92f4a27fecf825 Mon Sep 17 00:00:00 2001 From: Redned Date: Wed, 13 May 2020 17:53:13 -0500 Subject: [PATCH 072/140] Update README.md --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 713e77b72..874c79f33 100644 --- a/README.md +++ b/README.md @@ -9,10 +9,14 @@ Geyser is a bridge between Minecraft: Bedrock Edition and Minecraft: Java Edition, closing the gap from those wanting to play true cross-platform. +Geyser is an open collaboration project by [CubeCraft Games](https://cubecraft.net). + ## What is Geyser? Geyser is a proxy, bridging the gap between Minecraft: Bedrock Edition and Minecraft: Java Edition servers. The ultimate goal of this project is to allow Minecraft: Bedrock Edition users to join Minecraft: Java Edition servers as seamlessly as possible. **Please note, this project is still a work in progress and should not be used on production. Expect bugs!** +Special thanks to the DragonProxy project for being a trailblazer in protocol translation and for all the team members who have now joined us here! + ### Currently supporting Minecraft Bedrock v1.14.6(0) and Minecraft Java v1.15.2. ## Setting Up From d4995acec694009fb512a7a9d6d5a106208f7f17 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+DoctorMacc@users.noreply.github.com> Date: Thu, 14 May 2020 12:30:33 -0400 Subject: [PATCH 073/140] Add support for absorption (golden hearts) (#553) Absorption is an attribute in Bedrock and an entity metadata value in Java. This commit sends an attribute update packet when the metadata value is updated. --- .../connector/entity/PlayerEntity.java | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/entity/PlayerEntity.java b/connector/src/main/java/org/geysermc/connector/entity/PlayerEntity.java index 43891a7ed..98b6b7da8 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/PlayerEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/PlayerEntity.java @@ -26,14 +26,12 @@ package org.geysermc.connector.entity; import com.github.steveice10.mc.auth.data.GameProfile; +import com.github.steveice10.mc.protocol.data.game.entity.Effect; import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata; import com.github.steveice10.mc.protocol.data.message.TextMessage; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.nukkitx.math.vector.Vector3f; -import com.nukkitx.protocol.bedrock.data.CommandPermission; -import com.nukkitx.protocol.bedrock.data.EntityData; -import com.nukkitx.protocol.bedrock.data.EntityLink; -import com.nukkitx.protocol.bedrock.data.PlayerPermission; +import com.nukkitx.protocol.bedrock.data.*; import com.nukkitx.protocol.bedrock.packet.*; import lombok.Getter; @@ -47,6 +45,8 @@ import org.geysermc.connector.utils.MessageUtils; import org.geysermc.connector.network.session.cache.EntityEffectCache; import org.geysermc.connector.utils.SkinUtils; +import java.util.ArrayList; +import java.util.List; import java.util.UUID; import java.util.concurrent.TimeUnit; @@ -205,6 +205,17 @@ public class PlayerEntity extends LivingEntity { } } + // Extra hearts - is not metadata but an attribute on Bedrock + if (entityMetadata.getId() == 14) { + UpdateAttributesPacket attributesPacket = new UpdateAttributesPacket(); + attributesPacket.setRuntimeEntityId(geyserId); + List attributes = new ArrayList<>(); + // Setting to a higher maximum since plugins/datapacks can probably extend the Bedrock soft limit + attributes.add(new Attribute("minecraft:absorption", 0.0f, 1024f, (float) entityMetadata.getValue(), 0.0f)); + attributesPacket.setAttributes(attributes); + session.sendUpstreamPacket(attributesPacket); + } + // Parrot occupying shoulder if (entityMetadata.getId() == 18 || entityMetadata.getId() == 19) { CompoundTag tag = (CompoundTag) entityMetadata.getValue(); From 919af5203d27289af3f0e7549d2e5982958cdabf Mon Sep 17 00:00:00 2001 From: rtm516 Date: Fri, 15 May 2020 01:41:42 +0100 Subject: [PATCH 074/140] Fix banner items loosing patterns in inventory (#560) --- .../item/translators/BannerTranslator.java | 93 +++++++++++++++++++ .../entity/BannerBlockEntityTranslator.java | 39 ++------ .../geysermc/connector/utils/ItemUtils.java | 79 ++++++++++++++++ 3 files changed, 179 insertions(+), 32 deletions(-) create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/item/translators/BannerTranslator.java diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/BannerTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/BannerTranslator.java new file mode 100644 index 000000000..00ee7c0de --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/BannerTranslator.java @@ -0,0 +1,93 @@ +/* + * 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.item.translators; + +import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; +import com.github.steveice10.opennbt.tag.builtin.CompoundTag; +import com.github.steveice10.opennbt.tag.builtin.ListTag; +import com.nukkitx.nbt.CompoundTagBuilder; +import com.nukkitx.protocol.bedrock.data.ItemData; +import org.geysermc.connector.network.translators.ItemRemapper; +import org.geysermc.connector.network.translators.ItemStackTranslator; +import org.geysermc.connector.network.translators.item.ItemEntry; +import org.geysermc.connector.utils.ItemUtils; +import org.geysermc.connector.utils.Toolbox; + +import java.util.List; +import java.util.stream.Collectors; + +@ItemRemapper +public class BannerTranslator extends ItemStackTranslator { + + private List appliedItems; + + public BannerTranslator() { + appliedItems = Toolbox.ITEM_ENTRIES.values().stream().filter(entry -> entry.getJavaIdentifier().endsWith("banner")).collect(Collectors.toList()); + } + + @Override + public ItemData translateToBedrock(ItemStack itemStack, ItemEntry itemEntry) { + if (itemStack.getNbt() == null) return super.translateToBedrock(itemStack, itemEntry); + + ItemData itemData = super.translateToBedrock(itemStack, itemEntry); + + CompoundTag blockEntityTag = itemStack.getNbt().get("BlockEntityTag"); + if (blockEntityTag.contains("Patterns")) { + ListTag patterns = blockEntityTag.get("Patterns"); + + CompoundTagBuilder builder = itemData.getTag().toBuilder(); + builder.tag(ItemUtils.convertBannerPattern(patterns)); + + itemData = ItemData.of(itemData.getId(), itemData.getDamage(), itemData.getCount(), builder.buildRootTag()); + } + + return itemData; + } + + @Override + public ItemStack translateToJava(ItemData itemData, ItemEntry itemEntry) { + if (itemData.getTag() == null) return super.translateToJava(itemData, itemEntry); + + ItemStack itemStack = super.translateToJava(itemData, itemEntry); + + com.nukkitx.nbt.tag.CompoundTag nbtTag = itemData.getTag(); + if (nbtTag.contains("Patterns")) { + com.nukkitx.nbt.tag.ListTag patterns = (com.nukkitx.nbt.tag.ListTag) nbtTag.get("Patterns"); + + CompoundTag blockEntityTag = new CompoundTag("BlockEntityTag"); + blockEntityTag.put(ItemUtils.convertBannerPattern(patterns)); + + itemStack.getNbt().put(blockEntityTag); + } + + return itemStack; + } + + @Override + public List getAppliedItems() { + return appliedItems; + } +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/BannerBlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/BannerBlockEntityTranslator.java index eefd84022..41f83bad4 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/BannerBlockEntityTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/BannerBlockEntityTranslator.java @@ -33,6 +33,7 @@ import com.nukkitx.nbt.tag.IntTag; import com.nukkitx.nbt.tag.StringTag; import com.nukkitx.nbt.tag.Tag; import org.geysermc.connector.network.translators.world.block.BlockStateValues; +import org.geysermc.connector.utils.ItemUtils; import java.util.ArrayList; import java.util.List; @@ -48,26 +49,21 @@ public class BannerBlockEntityTranslator extends BlockEntityTranslator implement @Override public List> translateTag(CompoundTag tag, BlockState blockState) { List> tags = new ArrayList<>(); + int bannerColor = BlockStateValues.getBannerColor(blockState); if (bannerColor != -1) { tags.add(new IntTag("Base", 15 - bannerColor)); } - ListTag patterns = tag.get("Patterns"); - List tagsList = new ArrayList<>(); + if (tag.contains("Patterns")) { - for (com.github.steveice10.opennbt.tag.builtin.Tag patternTag : patterns.getValue()) { - com.nukkitx.nbt.tag.CompoundTag newPatternTag = getPattern((CompoundTag) patternTag); - if (newPatternTag != null) { - tagsList.add(newPatternTag); - } - } - com.nukkitx.nbt.tag.ListTag bedrockPatterns = - new com.nukkitx.nbt.tag.ListTag<>("Patterns", com.nukkitx.nbt.tag.CompoundTag.class, tagsList); - tags.add(bedrockPatterns); + ListTag patterns = tag.get("Patterns"); + tags.add(ItemUtils.convertBannerPattern(patterns)); } + if (tag.contains("CustomName")) { tags.add(new StringTag("CustomName", (String) tag.get("CustomName").getValue())); } + return tags; } @@ -84,25 +80,4 @@ public class BannerBlockEntityTranslator extends BlockEntityTranslator implement tagBuilder.listTag("Patterns", com.nukkitx.nbt.tag.CompoundTag.class, new ArrayList<>()); return tagBuilder.buildRootTag(); } - - /** - * Convert the Java edition pattern nbt to Bedrock edition, null if the pattern doesn't exist - * - * @param pattern Java edition pattern nbt - * @return The Bedrock edition format pattern nbt - */ - protected com.nukkitx.nbt.tag.CompoundTag getPattern(CompoundTag pattern) { - String patternName = (String) pattern.get("Pattern").getValue(); - - // Return null if its the globe pattern as it doesn't exist on bedrock - if (patternName.equals("glb")) { - return null; - } - - return CompoundTagBuilder.builder() - .intTag("Color", 15 - (int) pattern.get("Color").getValue()) - .stringTag("Pattern", (String) pattern.get("Pattern").getValue()) - .stringTag("Pattern", patternName) - .buildRootTag(); - } } diff --git a/connector/src/main/java/org/geysermc/connector/utils/ItemUtils.java b/connector/src/main/java/org/geysermc/connector/utils/ItemUtils.java index bb3cf0ed0..d3fe48d99 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/ItemUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/ItemUtils.java @@ -26,6 +26,12 @@ package org.geysermc.connector.utils; import com.github.steveice10.opennbt.tag.builtin.*; +import com.nukkitx.nbt.CompoundTagBuilder; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; public class ItemUtils { @@ -44,4 +50,77 @@ public class ItemUtils { } return 0; } + + /** + * Convert a list of patterns from Java nbt to Bedrock nbt + * + * @param patterns The patterns to convert + * @return The new converted patterns + */ + public static com.nukkitx.nbt.tag.ListTag convertBannerPattern(ListTag patterns) { + List tagsList = new ArrayList<>(); + for (com.github.steveice10.opennbt.tag.builtin.Tag patternTag : patterns.getValue()) { + com.nukkitx.nbt.tag.CompoundTag newPatternTag = getBedrockBannerPattern((CompoundTag) patternTag); + if (newPatternTag != null) { + tagsList.add(newPatternTag); + } + } + + return new com.nukkitx.nbt.tag.ListTag<>("Patterns", com.nukkitx.nbt.tag.CompoundTag.class, tagsList); + } + + /** + * Convert the Java edition banner pattern nbt to Bedrock edition, null if the pattern doesn't exist + * + * @param pattern Java edition pattern nbt + * @return The Bedrock edition format pattern nbt + */ + public static com.nukkitx.nbt.tag.CompoundTag getBedrockBannerPattern(CompoundTag pattern) { + String patternName = (String) pattern.get("Pattern").getValue(); + + // Return null if its the globe pattern as it doesn't exist on bedrock + if (patternName.equals("glb")) { + return null; + } + + return CompoundTagBuilder.builder() + .intTag("Color", 15 - (int) pattern.get("Color").getValue()) + .stringTag("Pattern", (String) pattern.get("Pattern").getValue()) + .stringTag("Pattern", patternName) + .buildRootTag(); + } + + /** + * Convert a list of patterns from Bedrock nbt to Java nbt + * + * @param patterns The patterns to convert + * @return The new converted patterns + */ + public static ListTag convertBannerPattern(com.nukkitx.nbt.tag.ListTag patterns) { + List tagsList = new ArrayList<>(); + for (Object patternTag : patterns.getValue()) { + CompoundTag newPatternTag = getJavaBannerPattern((com.nukkitx.nbt.tag.CompoundTag) patternTag); + if (newPatternTag != null) { + tagsList.add(newPatternTag); + } + } + + return new ListTag("Patterns", tagsList); + } + + /** + * Convert the Bedrock edition banner pattern nbt to Java edition + * + * @param pattern Bedorck edition pattern nbt + * @return The Java edition format pattern nbt + */ + public static CompoundTag getJavaBannerPattern(com.nukkitx.nbt.tag.CompoundTag pattern) { + String patternName = (String) pattern.get("Pattern").getValue(); + + Map tags = new HashMap<>(); + tags.put("Color", new IntTag("Color", 15 - pattern.getInt("Color"))); + tags.put("Pattern", new StringTag("Pattern", pattern.getString("Pattern"))); + + return new CompoundTag("", tags); + } } From 2830756a55e5dbe14c906d05600d2933624a9407 Mon Sep 17 00:00:00 2001 From: rtm516 Date: Fri, 15 May 2020 17:08:44 +0100 Subject: [PATCH 075/140] Fixed unusable space being off by 1 (#561) --- .../translators/inventory/updater/ChestInventoryUpdater.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/ChestInventoryUpdater.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/ChestInventoryUpdater.java index e9541bd15..6656cc830 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/ChestInventoryUpdater.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/ChestInventoryUpdater.java @@ -48,7 +48,7 @@ public class ChestInventoryUpdater extends InventoryUpdater { ItemData[] bedrockItems = new ItemData[paddedSize]; for (int i = 0; i < bedrockItems.length; i++) { - if (i <= translator.size) { + if (i < translator.size) { bedrockItems[i] = Translators.getItemTranslator().translateToBedrock(session, inventory.getItem(i)); } else { bedrockItems[i] = UNUSUABLE_SPACE_BLOCK; From 1b260c16d7cbe6731d5f378fc0f15fee79c4b71a Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+DoctorMacc@users.noreply.github.com> Date: Fri, 15 May 2020 13:50:34 -0400 Subject: [PATCH 076/140] Leash fixes (#567) * Leash fixes - Adds visuals for leash string by translating ServerEntityAttachPacket - Updates position offset for lead knots, making them properly appear on fences * Add basic description of JavaEntityAttachTranslator --- .../connector/entity/LeashKnotEntity.java | 39 +++++++++ .../connector/entity/type/EntityType.java | 2 +- .../entity/JavaEntityAttachTranslator.java | 81 +++++++++++++++++++ 3 files changed, 121 insertions(+), 1 deletion(-) create mode 100644 connector/src/main/java/org/geysermc/connector/entity/LeashKnotEntity.java create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/java/entity/JavaEntityAttachTranslator.java diff --git a/connector/src/main/java/org/geysermc/connector/entity/LeashKnotEntity.java b/connector/src/main/java/org/geysermc/connector/entity/LeashKnotEntity.java new file mode 100644 index 000000000..0bec07b0e --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/entity/LeashKnotEntity.java @@ -0,0 +1,39 @@ +/* + * 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.entity; + +import com.nukkitx.math.vector.Vector3f; +import org.geysermc.connector.entity.type.EntityType; + +public class LeashKnotEntity extends Entity { + + public LeashKnotEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { + // Position is incorrect by default + super(entityId, geyserId, entityType, position.add(0.5f, 0.25f, 0.5f), motion, rotation); + } + +} diff --git a/connector/src/main/java/org/geysermc/connector/entity/type/EntityType.java b/connector/src/main/java/org/geysermc/connector/entity/type/EntityType.java index c77baf0e7..ed231d8c7 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/type/EntityType.java +++ b/connector/src/main/java/org/geysermc/connector/entity/type/EntityType.java @@ -121,7 +121,7 @@ public enum EntityType { FIREBALL(ItemedFireballEntity.class, 85, 1.0f), POTION(ThrowableEntity.class, 86, 0.25f), ENDER_PEARL(ThrowableEntity.class, 87, 0.25f), - LEASH_KNOT(Entity.class, 88, 0.5f, 0.375f), + LEASH_KNOT(LeashKnotEntity.class, 88, 0.5f, 0.375f), WITHER_SKULL(Entity.class, 89, 0.3125f), BOAT(Entity.class, 90, 0.7f, 1.6f, 1.6f, 0.35f), WITHER_SKULL_DANGEROUS(Entity.class, 91, 0f), diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/JavaEntityAttachTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/JavaEntityAttachTranslator.java new file mode 100644 index 000000000..6e53df27c --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/JavaEntityAttachTranslator.java @@ -0,0 +1,81 @@ +/* + * 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.entity; + +import com.github.steveice10.mc.protocol.packet.ingame.server.entity.ServerEntityAttachPacket; +import com.nukkitx.protocol.bedrock.data.EntityData; +import com.nukkitx.protocol.bedrock.data.EntityEventType; +import com.nukkitx.protocol.bedrock.data.EntityFlag; +import com.nukkitx.protocol.bedrock.packet.EntityEventPacket; +import org.geysermc.connector.entity.Entity; +import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.PacketTranslator; +import org.geysermc.connector.network.translators.Translator; + +/** + * Called when a leash is attached, removed or updated from an entity + */ +@Translator(packet = ServerEntityAttachPacket.class) +public class JavaEntityAttachTranslator extends PacketTranslator { + + @Override + public void translate(ServerEntityAttachPacket packet, GeyserSession session) { + + Entity holderId; + if (packet.getEntityId() == session.getPlayerEntity().getEntityId()) { + holderId = session.getPlayerEntity(); + } else { + holderId = session.getEntityCache().getEntityByJavaId(packet.getEntityId()); + if (holderId == null) { + return; + } + } + + Entity attachedToId; + if (packet.getAttachedToId() == session.getPlayerEntity().getEntityId()) { + attachedToId = session.getPlayerEntity(); + } else { + attachedToId = session.getEntityCache().getEntityByJavaId(packet.getAttachedToId()); + if ((attachedToId == null || packet.getAttachedToId() == 0)) { + // Is not being leashed + holderId.getMetadata().getFlags().setFlag(EntityFlag.LEASHED, false); + holderId.getMetadata().put(EntityData.LEAD_HOLDER_EID, 0); + holderId.updateBedrockMetadata(session); + EntityEventPacket eventPacket = new EntityEventPacket(); + eventPacket.setRuntimeEntityId(holderId.getGeyserId()); + eventPacket.setType(EntityEventType.REMOVE_LEASH); + eventPacket.setData(0); + session.sendUpstreamPacket(eventPacket); + return; + } + } + + holderId.getMetadata().getFlags().setFlag(EntityFlag.LEASHED, true); + holderId.getMetadata().put(EntityData.LEAD_HOLDER_EID, attachedToId.getGeyserId()); + holderId.updateBedrockMetadata(session); + } +} From b4ecb88d4942fa75d9d2fc1221e34695ef15c9b2 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+DoctorMacc@users.noreply.github.com> Date: Fri, 15 May 2020 16:29:54 -0400 Subject: [PATCH 077/140] Add air bubble UI support (#569) This commit translates entity metadata ID 1 into the AIR entity metadata. --- .../main/java/org/geysermc/connector/entity/Entity.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/connector/src/main/java/org/geysermc/connector/entity/Entity.java b/connector/src/main/java/org/geysermc/connector/entity/Entity.java index 2fe830afd..d0c1920f2 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/Entity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/Entity.java @@ -98,7 +98,7 @@ public class Entity { metadata.put(EntityData.SCALE, 1f); metadata.put(EntityData.COLOR, 0); - metadata.put(EntityData.MAX_AIR, (short) 400); + metadata.put(EntityData.MAX_AIR, (short) 300); metadata.put(EntityData.AIR, (short) 0); metadata.put(EntityData.LEAD_HOLDER_EID, -1L); metadata.put(EntityData.BOUNDING_BOX_HEIGHT, entityType.getHeight()); @@ -242,6 +242,13 @@ public class Entity { } } break; + case 1: // Air/bubbles + if ((int) entityMetadata.getValue() == 300) { + metadata.put(EntityData.AIR, (short) 0); // Otherwise the bubble counter remains in the UI + } else { + metadata.put(EntityData.AIR, (short) (int) entityMetadata.getValue()); + } + break; case 2: // custom name TextMessage name = (TextMessage) entityMetadata.getValue(); if (name != null) From 3220532083982f2357c9c8c35cd2e6046c712208 Mon Sep 17 00:00:00 2001 From: rtm516 Date: Sun, 17 May 2020 05:57:18 +0100 Subject: [PATCH 078/140] Fixed fishing rod lines not connecting to other players (#580) --- .../geysermc/connector/entity/FishingHookEntity.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/entity/FishingHookEntity.java b/connector/src/main/java/org/geysermc/connector/entity/FishingHookEntity.java index 8d8d5ef24..808e16670 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/FishingHookEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/FishingHookEntity.java @@ -37,10 +37,14 @@ public class FishingHookEntity extends Entity { public FishingHookEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation, ProjectileData data) { super(entityId, geyserId, entityType, position, motion, rotation); - // TODO: Find a better way to do this for (GeyserSession session : GeyserConnector.getInstance().getPlayers().values()) { - if (session.getPlayerEntity().getEntityId() == data.getOwnerId()) { - this.metadata.put(EntityData.OWNER_EID, session.getPlayerEntity().getGeyserId()); + Entity entity = session.getEntityCache().getEntityByJavaId(data.getOwnerId()); + if (entity == null && session.getPlayerEntity().getEntityId() == data.getOwnerId()) { + entity = session.getPlayerEntity(); + } + + if (entity != null) { + this.metadata.put(EntityData.OWNER_EID, entity.getGeyserId()); return; } } From 563cde2adece3cc99702160bb5249ee45aa18268 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+DoctorMacc@users.noreply.github.com> Date: Sun, 17 May 2020 00:57:34 -0400 Subject: [PATCH 079/140] Switch to client's translation for jukebox song name. (#573) Just for consistency with the other part of the code. --- .../translators/java/world/JavaPlayEffectTranslator.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaPlayEffectTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaPlayEffectTranslator.java index 3afb79bd1..79a2c920e 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaPlayEffectTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaPlayEffectTranslator.java @@ -140,8 +140,7 @@ public class JavaPlayEffectTranslator extends PacketTranslator params = new ArrayList<>(); - // Couldn't figure out how to set this to Bedrock translation so it just uses the Java translation - String recordString = "item.minecraft." + EffectUtils.RECORDS.get(recordEffectData.getRecordId()).name().toLowerCase().replace("record_", "music_disc_") + ".desc"; + String recordString = "%item." + EffectUtils.RECORDS.get(recordEffectData.getRecordId()).name().toLowerCase() + ".desc"; params.add(LocaleUtils.getLocaleString(recordString, session.getClientData().getLanguageCode())); textPacket.setParameters(params); session.sendUpstreamPacket(textPacket); From 95b7055c10dfdce25c226b7ad5209407e75f3414 Mon Sep 17 00:00:00 2001 From: rtm516 Date: Sun, 17 May 2020 05:58:00 +0100 Subject: [PATCH 080/140] Added map icons (#572) * Added map icons * Cleaned up and moved to enum --- .../translators/nbt/MapItemTranslator.java | 2 + .../java/world/JavaMapDataTranslator.java | 14 +++ .../connector/utils/BedrockMapIcon.java | 118 ++++++++++++++++++ .../geysermc/connector/utils/MapColor.java | 26 ++++ 4 files changed, 160 insertions(+) create mode 100644 connector/src/main/java/org/geysermc/connector/utils/BedrockMapIcon.java diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/MapItemTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/MapItemTranslator.java index cdf272ece..7e6bc7298 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/MapItemTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/MapItemTranslator.java @@ -25,6 +25,7 @@ package org.geysermc.connector.network.translators.item.translators.nbt; +import com.github.steveice10.opennbt.tag.builtin.ByteTag; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.IntTag; import com.github.steveice10.opennbt.tag.builtin.StringTag; @@ -42,6 +43,7 @@ public class MapItemTranslator extends NbtItemStackTranslator { if (mapId != null) { itemTag.put(new StringTag("map_uuid", mapId.getValue().toString())); itemTag.put(new IntTag("map_name_index", mapId.getValue())); + itemTag.put(new ByteTag("map_display_players", (byte) 1)); itemTag.remove("map"); } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaMapDataTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaMapDataTranslator.java index 78681f8fb..c8be3a56e 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaMapDataTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaMapDataTranslator.java @@ -26,11 +26,15 @@ package org.geysermc.connector.network.translators.java.world; import com.github.steveice10.mc.protocol.data.game.world.map.MapData; +import com.github.steveice10.mc.protocol.data.game.world.map.MapIcon; import com.github.steveice10.mc.protocol.packet.ingame.server.world.ServerMapDataPacket; +import com.nukkitx.protocol.bedrock.data.MapDecoration; +import com.nukkitx.protocol.bedrock.data.MapTrackedObject; import com.nukkitx.protocol.bedrock.packet.ClientboundMapItemDataPacket; 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.utils.BedrockMapIcon; import org.geysermc.connector.utils.MapColor; @Translator(packet = ServerMapDataPacket.class) @@ -62,6 +66,16 @@ public class JavaMapDataTranslator extends PacketTranslator mapItemDataPacket.setColors(colors); } + // Bedrock needs an entity id to display an icon + int id = 0; + for (MapIcon icon : packet.getIcons()) { + BedrockMapIcon bedrockMapIcon = BedrockMapIcon.fromType(icon.getIconType()); + + mapItemDataPacket.getTrackedObjects().add(new MapTrackedObject(id)); + mapItemDataPacket.getDecorations().add(new MapDecoration(bedrockMapIcon.getIconID(), icon.getIconRotation(), icon.getCenterX(), icon.getCenterZ(), "", bedrockMapIcon.toARGB())); + id++; + } + session.getUpstream().getSession().sendPacket(mapItemDataPacket); } } diff --git a/connector/src/main/java/org/geysermc/connector/utils/BedrockMapIcon.java b/connector/src/main/java/org/geysermc/connector/utils/BedrockMapIcon.java new file mode 100644 index 000000000..f3ee956b3 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/utils/BedrockMapIcon.java @@ -0,0 +1,118 @@ +/* + * 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.utils; + +import com.github.steveice10.mc.protocol.data.game.world.map.MapIconType; +import lombok.Getter; + +public enum BedrockMapIcon { + ICON_WHITE_ARROW(MapIconType.WHITE_ARROW, 0), + ICON_ITEM_FRAME(MapIconType.GREEN_ARROW, 7), + ICON_RED_ARROW(MapIconType.RED_ARROW, 2), + ICON_BLUE_ARROW(MapIconType.BLUE_ARROW, 3), + ICON_TREASURE_MARKER(MapIconType.TREASURE_MARKER, 4), + ICON_RED_POINTER(MapIconType.RED_POINTER, 5), + ICON_WHITE_CIRCLE(MapIconType.WHITE_CIRCLE, 6), + ICON_SMALL_WHITE_CIRCLE(MapIconType.SMALL_WHITE_CIRCLE, 13), + ICON_MANSION(MapIconType.MANSION, 14), + ICON_TEMPLE(MapIconType.TEMPLE, 15), + ICON_WHITE_BANNER(MapIconType.WHITE_BANNER, 13, 255, 255, 255), + ICON_ORANGE_BANNER(MapIconType.ORANGE_BANNER, 13, 249, 128, 29), + ICON_MAGENTA_BANNER(MapIconType.MAGENTA_BANNER, 13, 199, 78, 189), + ICON_LIGHT_BLUE_BANNER(MapIconType.LIGHT_BLUE_BANNER, 13, 58, 179, 218), + ICON_YELLOW_BANNER(MapIconType.YELLOW_BANNER, 13, 254, 216, 61), + ICON_LIME_BANNER(MapIconType.LIME_BANNER, 13, 128, 199, 31), + ICON_PINK_BANNER(MapIconType.PINK_BANNER, 13, 243, 139, 170), + ICON_GRAY_BANNER(MapIconType.GRAY_BANNER, 13, 71, 79, 82), + ICON_LIGHT_GRAY_BANNER(MapIconType.LIGHT_GRAY_BANNER, 13, 157, 157, 151), + ICON_CYAN_BANNER(MapIconType.CYAN_BANNER, 13, 22, 156, 156), + ICON_PURPLE_BANNER(MapIconType.PURPLE_BANNER, 13, 137, 50, 184), + ICON_BLUE_BANNER(MapIconType.BLUE_BANNER, 13, 60, 68, 170), + ICON_BROWN_BANNER(MapIconType.BROWN_BANNER, 13, 131, 84, 50), + ICON_GREEN_BANNER(MapIconType.GREEN_BANNER, 13, 94, 124, 22), + ICON_RED_BANNER(MapIconType.RED_BANNER, 13, 176, 46, 38), + ICON_BLACK_BANNER(MapIconType.BLACK_BANNER, 13, 29, 29, 33); + + private static final BedrockMapIcon[] VALUES = values(); + + private MapIconType iconType; + + @Getter + private int iconID; + + private int red; + private int green; + private int blue; + + BedrockMapIcon(MapIconType iconType, int iconID) { + this.iconType = iconType; + this.iconID = iconID; + + this.red = 255; + this.green = 255; + this.blue = 255; + } + + BedrockMapIcon(MapIconType iconType, int iconID, int red, int green, int blue) { + this.iconType = iconType; + this.iconID = iconID; + + this.red = red; + this.green = green; + this.blue = blue; + } + + /** + * Get the BedrockMapIcon for the Java MapIconType + * + * @param iconType A MapIconType + * @return The mapping for a BedrockMapIcon + */ + public static BedrockMapIcon fromType(MapIconType iconType) { + for (BedrockMapIcon icon : VALUES) { + if (icon.iconType.equals(iconType)) { + return icon; + } + } + + return null; + } + + /** + * Get the ARGB value of a BedrockMapIcon + * + * @return ARGB as an int + */ + public int toARGB() { + int alpha = 255; + + return ((alpha & 0xFF) << 24) | + ((red & 0xFF) << 16) | + ((green & 0xFF) << 8) | + ((blue & 0xFF) << 0); + } +} diff --git a/connector/src/main/java/org/geysermc/connector/utils/MapColor.java b/connector/src/main/java/org/geysermc/connector/utils/MapColor.java index b011edc71..4328d758e 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/MapColor.java +++ b/connector/src/main/java/org/geysermc/connector/utils/MapColor.java @@ -1,3 +1,29 @@ +/* + * 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.utils; public enum MapColor { From 57717795a378120a9cd26495badad1e05c3b4cab Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+DoctorMacc@users.noreply.github.com> Date: Sun, 17 May 2020 00:59:03 -0400 Subject: [PATCH 081/140] Add enchantment table book on chunk load (#568) Java's block entity ID is enchantment_table whereas Bedrock's is EnchantTable; this commit adds an exception to the block entity regex as such. --- .../java/org/geysermc/connector/utils/BlockEntityUtils.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/connector/src/main/java/org/geysermc/connector/utils/BlockEntityUtils.java b/connector/src/main/java/org/geysermc/connector/utils/BlockEntityUtils.java index 9423a4f87..da32b12b0 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/BlockEntityUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/BlockEntityUtils.java @@ -22,6 +22,10 @@ public class BlockEntityUtils { if (id.contains("EnderChest")) return "EnderChest"; + if (id.contains("enchanting_table")) { + return "EnchantTable"; + } + id = id.toLowerCase() .replace("minecraft:", "") .replace("_", " "); From b0d0c168d2b9837f484863fb8aa24498c5741af7 Mon Sep 17 00:00:00 2001 From: RednedEpic Date: Sun, 17 May 2020 01:06:07 -0500 Subject: [PATCH 082/140] Fix bossbar causing players to be unable to break blocks or interact in small areas (Closes #537) --- .../geysermc/connector/network/session/cache/BossBar.java | 7 +++++-- .../network/translators/java/JavaBossBarTranslator.java | 2 -- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/network/session/cache/BossBar.java b/connector/src/main/java/org/geysermc/connector/network/session/cache/BossBar.java index 1fde179dc..267f3cb1f 100644 --- a/connector/src/main/java/org/geysermc/connector/network/session/cache/BossBar.java +++ b/connector/src/main/java/org/geysermc/connector/network/session/cache/BossBar.java @@ -104,10 +104,13 @@ public class BossBar { addEntityPacket.setRuntimeEntityId(entityId); addEntityPacket.setIdentifier("minecraft:creeper"); addEntityPacket.setEntityType(33); - addEntityPacket.setPosition(session.getPlayerEntity().getPosition()); + addEntityPacket.setPosition(session.getPlayerEntity().getPosition().sub(0D, -10D, 0D)); addEntityPacket.setRotation(Vector3f.ZERO); addEntityPacket.setMotion(Vector3f.ZERO); - addEntityPacket.getMetadata().put(EntityData.SCALE, 0.01F); // scale = 0 doesn't work? + addEntityPacket.getMetadata() + .putFloat(EntityData.SCALE, 0F) + .putFloat(EntityData.BOUNDING_BOX_WIDTH, 0F) + .putFloat(EntityData.BOUNDING_BOX_HEIGHT, 0F); session.sendUpstreamPacket(addEntityPacket); } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaBossBarTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaBossBarTranslator.java index 2c32ef6fe..3da76a228 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaBossBarTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaBossBarTranslator.java @@ -32,8 +32,6 @@ import org.geysermc.connector.network.translators.Translator; import com.github.steveice10.mc.protocol.packet.ingame.server.ServerBossBarPacket; -import java.awt.*; - @Translator(packet = ServerBossBarPacket.class) public class JavaBossBarTranslator extends PacketTranslator { @Override From 43ee7d602765c2ef0f75f3ad467efd23b1162531 Mon Sep 17 00:00:00 2001 From: rtm516 Date: Sun, 17 May 2020 07:26:13 +0100 Subject: [PATCH 083/140] Fixed creepers, giants and eye of ender (#578) --- .../entity/living/monster/CreeperEntity.java | 4 +- .../entity/living/monster/GiantEntity.java | 39 +++++++++++++++++++ .../connector/entity/type/EntityType.java | 3 +- 3 files changed, 43 insertions(+), 3 deletions(-) create mode 100644 connector/src/main/java/org/geysermc/connector/entity/living/monster/GiantEntity.java diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/monster/CreeperEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/monster/CreeperEntity.java index e99e1a63f..9b5c38220 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/living/monster/CreeperEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/living/monster/CreeperEntity.java @@ -39,8 +39,8 @@ public class CreeperEntity extends MonsterEntity { @Override public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { - if (entityMetadata.getId() == 15 && (int) entityMetadata.getValue() > 0) { - metadata.getFlags().setFlag(EntityFlag.IGNITED, true); + if (entityMetadata.getId() == 15) { + metadata.getFlags().setFlag(EntityFlag.IGNITED, (int) entityMetadata.getValue() == 1); } if (entityMetadata.getId() == 16) { metadata.getFlags().setFlag(EntityFlag.POWERED, (boolean) entityMetadata.getValue()); diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/monster/GiantEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/monster/GiantEntity.java new file mode 100644 index 000000000..b9dc9e66b --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/entity/living/monster/GiantEntity.java @@ -0,0 +1,39 @@ +/* + * 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.entity.living.monster; + +import com.nukkitx.math.vector.Vector3f; +import com.nukkitx.protocol.bedrock.data.EntityData; +import org.geysermc.connector.entity.type.EntityType; + +public class GiantEntity extends MonsterEntity { + + public GiantEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { + super(entityId, geyserId, entityType, position, motion, rotation); + + metadata.put(EntityData.SCALE, 6f); + } +} diff --git a/connector/src/main/java/org/geysermc/connector/entity/type/EntityType.java b/connector/src/main/java/org/geysermc/connector/entity/type/EntityType.java index ed231d8c7..d08c5e331 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/type/EntityType.java +++ b/connector/src/main/java/org/geysermc/connector/entity/type/EntityType.java @@ -64,6 +64,7 @@ public enum EntityType { PARROT(ParrotEntity.class, 30, 0.9f, 0.5f), DOLPHIN(WaterEntity.class, 31, 0.6f, 0.9f), ZOMBIE(ZombieEntity.class, 32, 1.8f, 0.6f, 0.6f, 1.62f), + GIANT(GiantEntity.class, 32, 1.8f, 0.6f, 0.6f, 1.62f, "minecraft:zombie"), CREEPER(CreeperEntity.class, 33, 1.7f, 0.6f, 0.6f, 1.62f), SKELETON(AbstractSkeletonEntity.class, 34, 1.8f, 0.6f, 0.6f, 1.62f), SPIDER(SpiderEntity.class, 35, 0.9f, 1.4f, 1.4f, 1f), @@ -103,7 +104,7 @@ public enum EntityType { MOVING_BLOCK(Entity.class, 67, 0f), EXPERIENCE_BOTTLE(ThrowableEntity.class, 68, 0.25f, 0.25f, 0f, 0f, "minecraft:xp_bottle"), EXPERIENCE_ORB(ExpOrbEntity.class, 69, 0f, 0f, 0f, 0f, "minecraft:xp_orb"), - EYE_OF_ENDER(Entity.class, 70, 0.25f), + EYE_OF_ENDER(Entity.class, 70, 0.25f, 0.25f, 0f, 0f, "minecraft:eye_of_ender_signal"), END_CRYSTAL(EnderCrystalEntity.class, 71, 0f, 0f, 0f, 0f, "minecraft:ender_crystal"), FIREWORK_ROCKET(Entity.class, 72, 0.25f), TRIDENT(ArrowEntity.class, 73, 0f), From 405ffb2666203bb2c6f17eed3f151881bd27cbf1 Mon Sep 17 00:00:00 2001 From: rtm516 Date: Mon, 18 May 2020 05:35:01 +0100 Subject: [PATCH 084/140] Added mob spawner block entity data (#587) --- .../connector/entity/type/EntityType.java | 12 ++ .../entity/SpawnerBlockEntityTranslator.java | 105 ++++++++++++++++++ 2 files changed, 117 insertions(+) create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/SpawnerBlockEntityTranslator.java diff --git a/connector/src/main/java/org/geysermc/connector/entity/type/EntityType.java b/connector/src/main/java/org/geysermc/connector/entity/type/EntityType.java index d08c5e331..ad3ac1056 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/type/EntityType.java +++ b/connector/src/main/java/org/geysermc/connector/entity/type/EntityType.java @@ -160,6 +160,8 @@ public enum EntityType { */ ILLUSIONER(AbstractIllagerEntity.class, 114, 1.8f, 0.6f, 0.6f, 1.62f, "minecraft:pillager"); + private static final EntityType[] VALUES = values(); + private Class entityClass; private final int type; private final float height; @@ -195,4 +197,14 @@ public enum EntityType { this.offset = offset + 0.00001f; this.identifier = identifier; } + + public static EntityType getFromIdentifier(String identifier) { + for (EntityType type : VALUES) { + if (type.identifier.equals(identifier)) { + return type; + } + } + + return null; + } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/SpawnerBlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/SpawnerBlockEntityTranslator.java new file mode 100644 index 000000000..100dbddd6 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/SpawnerBlockEntityTranslator.java @@ -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.world.block.entity; + +import com.github.steveice10.mc.protocol.data.game.world.block.BlockState; +import com.github.steveice10.opennbt.tag.builtin.CompoundTag; +import com.nukkitx.nbt.CompoundTagBuilder; +import com.nukkitx.nbt.tag.*; +import org.geysermc.connector.entity.type.EntityType; + +import java.util.ArrayList; +import java.util.List; + +@BlockEntity(name = "MobSpawner", regex = "mob_spawner") +public class SpawnerBlockEntityTranslator extends BlockEntityTranslator { + + @Override + public List> translateTag(CompoundTag tag, BlockState blockState) { + List> tags = new ArrayList<>(); + + if (tag.get("MaxNearbyEntities") != null) { + tags.add(new ShortTag("MaxNearbyEntities", (short) tag.get("MaxNearbyEntities").getValue())); + } + + if (tag.get("RequiredPlayerRange") != null) { + tags.add(new ShortTag("RequiredPlayerRange", (short) tag.get("RequiredPlayerRange").getValue())); + } + + if (tag.get("SpawnCount") != null) { + tags.add(new ShortTag("SpawnCount", (short) tag.get("SpawnCount").getValue())); + } + + if (tag.get("MaxSpawnDelay") != null) { + tags.add(new ShortTag("MaxSpawnDelay", (short) tag.get("MaxSpawnDelay").getValue())); + } + + if (tag.get("Delay") != null) { + tags.add(new ShortTag("Delay", (short) tag.get("Delay").getValue())); + } + + if (tag.get("SpawnRange") != null) { + tags.add(new ShortTag("SpawnRange", (short) tag.get("SpawnRange").getValue())); + } + + if (tag.get("MinSpawnDelay") != null) { + tags.add(new ShortTag("MinSpawnDelay", (short) tag.get("MinSpawnDelay").getValue())); + } + + if (tag.get("SpawnData") != null) { + CompoundTag spawnData = tag.get("SpawnData"); + String entityID = (String) spawnData.get("id").getValue(); + tags.add(new StringTag("EntityIdentifier", entityID)); + + EntityType type = EntityType.getFromIdentifier(entityID); + if (type != null) { + tags.add(new FloatTag("DisplayEntityWidth", type.getWidth())); + tags.add(new FloatTag("DisplayEntityHeight", type.getHeight())); + tags.add(new FloatTag("DisplayEntityScale", 1.0f)); + } + } + + tags.add(new StringTag("id", "MobSpawner")); + tags.add(new ByteTag("isMovable", (byte) 1)); + + return tags; + } + + @Override + public CompoundTag getDefaultJavaTag(String javaId, int x, int y, int z) { + return null; + } + + @Override + public com.nukkitx.nbt.tag.CompoundTag getDefaultBedrockTag(String bedrockId, int x, int y, int z) { + CompoundTagBuilder tagBuilder = getConstantBedrockTag(bedrockId, x, y, z).toBuilder(); + tagBuilder.byteTag("isMovable", (byte) 1) + .stringTag("id", "MobSpawner"); + + return tagBuilder.buildRootTag(); + } +} From 31d3d2e289c9a9bca6826b333acc86788ea4de0b Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+DoctorMacc@users.noreply.github.com> Date: Mon, 18 May 2020 00:35:26 -0400 Subject: [PATCH 085/140] Add some elder guardian properties (#586) - Adds the ELDER flag to all elder guardians, so they look like elder guardians and not giant regular guardians. - Translates AFFECTED_BY_ELDER_GUARDIAN in JavaNotifyClientTranslator to add the elder guardian curse event. --- .../living/monster/ElderGuardianEntity.java | 41 +++++++++++++++++++ .../connector/entity/type/EntityType.java | 2 +- .../world/JavaNotifyClientTranslator.java | 11 +++-- 3 files changed, 49 insertions(+), 5 deletions(-) create mode 100644 connector/src/main/java/org/geysermc/connector/entity/living/monster/ElderGuardianEntity.java diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/monster/ElderGuardianEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/monster/ElderGuardianEntity.java new file mode 100644 index 000000000..fedd7980e --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/entity/living/monster/ElderGuardianEntity.java @@ -0,0 +1,41 @@ +/* + * 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.entity.living.monster; + +import com.nukkitx.math.vector.Vector3f; +import com.nukkitx.protocol.bedrock.data.EntityFlag; +import org.geysermc.connector.entity.type.EntityType; + +public class ElderGuardianEntity extends GuardianEntity { + + public ElderGuardianEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { + super(entityId, geyserId, entityType, position, motion, rotation); + // Otherwise it just looks like a normal guardian but bigger + metadata.getFlags().setFlag(EntityFlag.ELDER, true); + } + +} diff --git a/connector/src/main/java/org/geysermc/connector/entity/type/EntityType.java b/connector/src/main/java/org/geysermc/connector/entity/type/EntityType.java index ad3ac1056..f2b662805 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/type/EntityType.java +++ b/connector/src/main/java/org/geysermc/connector/entity/type/EntityType.java @@ -82,7 +82,7 @@ public enum EntityType { HUSK(ZombieEntity.class, 47, 1.8f, 0.6f, 0.6f, 1.62f), WITHER_SKELETON(AbstractSkeletonEntity.class, 48, 2.4f, 0.7f), GUARDIAN(GuardianEntity.class, 49, 0.85f), - ELDER_GUARDIAN(GuardianEntity.class, 50, 1.9975f), + ELDER_GUARDIAN(ElderGuardianEntity.class, 50, 1.9975f), NPC(PlayerEntity.class, 51, 1.8f, 0.6f, 0.6f, 1.62f), WITHER(WitherEntity.class, 52, 3.5f, 0.9f), ENDER_DRAGON(EnderDragonEntity.class, 53, 4f, 13f), diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaNotifyClientTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaNotifyClientTranslator.java index 0db343b27..de1066c00 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaNotifyClientTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaNotifyClientTranslator.java @@ -31,10 +31,7 @@ import com.github.steveice10.mc.protocol.data.game.world.notify.EnterCreditsValu import com.github.steveice10.mc.protocol.packet.ingame.client.ClientRequestPacket; import com.github.steveice10.mc.protocol.packet.ingame.server.world.ServerNotifyClientPacket; import com.nukkitx.math.vector.Vector3f; -import com.nukkitx.protocol.bedrock.data.EntityDataMap; -import com.nukkitx.protocol.bedrock.data.EntityFlag; -import com.nukkitx.protocol.bedrock.data.LevelEventType; -import com.nukkitx.protocol.bedrock.data.PlayerPermission; +import com.nukkitx.protocol.bedrock.data.*; import com.nukkitx.protocol.bedrock.packet.*; import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; import org.geysermc.connector.entity.Entity; @@ -124,6 +121,12 @@ public class JavaNotifyClientTranslator extends PacketTranslator Date: Mon, 18 May 2020 10:46:35 -0400 Subject: [PATCH 086/140] Add firework boost for elytras (#552) * Add firework boost for elytras! * Change how to detect player glide * Add comments explaining code * Remove unused ID --- .../connector/entity/FireworkEntity.java | 64 +++++++++++++++++++ .../connector/entity/type/EntityType.java | 2 +- 2 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 connector/src/main/java/org/geysermc/connector/entity/FireworkEntity.java diff --git a/connector/src/main/java/org/geysermc/connector/entity/FireworkEntity.java b/connector/src/main/java/org/geysermc/connector/entity/FireworkEntity.java new file mode 100644 index 000000000..25128d486 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/entity/FireworkEntity.java @@ -0,0 +1,64 @@ +/* + * 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.entity; + +import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata; +import com.nukkitx.math.vector.Vector3f; +import com.nukkitx.protocol.bedrock.packet.SetEntityMotionPacket; +import org.geysermc.connector.entity.type.EntityType; +import org.geysermc.connector.network.session.GeyserSession; + +import java.util.OptionalInt; + +public class FireworkEntity extends Entity { + + public FireworkEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { + super(entityId, geyserId, entityType, position, motion, rotation); + } + + @Override + public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { + if (entityMetadata.getId() == 8 && !entityMetadata.getValue().equals(OptionalInt.empty()) && ((OptionalInt) entityMetadata.getValue()).getAsInt() == session.getPlayerEntity().getEntityId()) { + //Checks if the firework has an entity ID (used when a player is gliding) and checks to make sure the player that is gliding is the one getting sent the packet or else every player near the gliding player will boost too. + PlayerEntity entity = session.getPlayerEntity(); + float yaw = entity.getRotation().getX(); + float pitch = entity.getRotation().getY(); + //Uses math from NukkitX + entity.setMotion(Vector3f.from( + -Math.sin(Math.toRadians(yaw)) * Math.cos(Math.toRadians(pitch)) * 2, + -Math.sin(Math.toRadians(pitch)) * 2, + Math.cos(Math.toRadians(yaw)) * Math.cos(Math.toRadians(pitch)) * 2)); + //Need to update the EntityMotionPacket or else the player won't boost + SetEntityMotionPacket entityMotionPacket = new SetEntityMotionPacket(); + entityMotionPacket.setRuntimeEntityId(entity.getGeyserId()); + entityMotionPacket.setMotion(entity.getMotion()); + + session.sendUpstreamPacket(entityMotionPacket); + } + super.updateBedrockMetadata(entityMetadata, session); + } +} \ No newline at end of file diff --git a/connector/src/main/java/org/geysermc/connector/entity/type/EntityType.java b/connector/src/main/java/org/geysermc/connector/entity/type/EntityType.java index f2b662805..6cfda74aa 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/type/EntityType.java +++ b/connector/src/main/java/org/geysermc/connector/entity/type/EntityType.java @@ -106,7 +106,7 @@ public enum EntityType { EXPERIENCE_ORB(ExpOrbEntity.class, 69, 0f, 0f, 0f, 0f, "minecraft:xp_orb"), EYE_OF_ENDER(Entity.class, 70, 0.25f, 0.25f, 0f, 0f, "minecraft:eye_of_ender_signal"), END_CRYSTAL(EnderCrystalEntity.class, 71, 0f, 0f, 0f, 0f, "minecraft:ender_crystal"), - FIREWORK_ROCKET(Entity.class, 72, 0.25f), + FIREWORK_ROCKET(FireworkEntity.class, 72, 0.25f), TRIDENT(ArrowEntity.class, 73, 0f), TURTLE(AnimalEntity.class, 74, 0.4f, 1.2f), CAT(CatEntity.class, 75, 0.35f, 0.3f), From fd36930502d45302b64a1658ef1b435ddb77dae1 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+DoctorMacc@users.noreply.github.com> Date: Mon, 18 May 2020 23:26:27 -0400 Subject: [PATCH 087/140] Add entity event for drowning. (#588) This commit translates Java's LIVING_DROWN entity status to Bedrock's HURT_ANIMATION. --- .../translators/java/entity/JavaEntityStatusTranslator.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/JavaEntityStatusTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/JavaEntityStatusTranslator.java index 06d066959..3032785af 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/JavaEntityStatusTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/JavaEntityStatusTranslator.java @@ -49,6 +49,8 @@ public class JavaEntityStatusTranslator extends PacketTranslator Date: Tue, 19 May 2020 04:27:35 +0100 Subject: [PATCH 088/140] Added a docker container IP warning (#584) * Added a docker container IP warning * Corrected messages * Moved to normal java file read instead of starting cat * Fixed capitalisation on method name --- .../geysermc/connector/GeyserConnector.java | 5 ++ .../geysermc/connector/utils/DockerCheck.java | 58 +++++++++++++++++++ 2 files changed, 63 insertions(+) create mode 100644 connector/src/main/java/org/geysermc/connector/utils/DockerCheck.java diff --git a/connector/src/main/java/org/geysermc/connector/GeyserConnector.java b/connector/src/main/java/org/geysermc/connector/GeyserConnector.java index 729952939..58307682b 100644 --- a/connector/src/main/java/org/geysermc/connector/GeyserConnector.java +++ b/connector/src/main/java/org/geysermc/connector/GeyserConnector.java @@ -40,6 +40,7 @@ import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.Translators; import org.geysermc.connector.network.translators.world.WorldManager; import org.geysermc.connector.thread.PingPassthroughThread; +import org.geysermc.connector.utils.DockerCheck; import org.geysermc.connector.utils.Toolbox; import java.net.InetSocketAddress; @@ -102,6 +103,10 @@ public class GeyserConnector { Toolbox.init(); Translators.start(); + if (platformType != PlatformType.STANDALONE) { + DockerCheck.check(bootstrap); + } + remoteServer = new RemoteServer(config.getRemote().getAddress(), config.getRemote().getPort()); authType = AuthType.getByName(config.getRemote().getAuthType()); diff --git a/connector/src/main/java/org/geysermc/connector/utils/DockerCheck.java b/connector/src/main/java/org/geysermc/connector/utils/DockerCheck.java new file mode 100644 index 000000000..0a5a2278c --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/utils/DockerCheck.java @@ -0,0 +1,58 @@ +/* + * 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.utils; + +import org.geysermc.connector.bootstrap.GeyserBootstrap; + +import java.net.InetAddress; +import java.nio.file.Files; +import java.nio.file.Paths; + +public class DockerCheck { + public static void check(GeyserBootstrap bootstrap) { + try { + String OS = System.getProperty("os.name").toLowerCase(); + String ipAddress = InetAddress.getLocalHost().getHostAddress(); + + // Check if the user is already using the recommended IP + if (ipAddress.equals(bootstrap.getGeyserConfig().getRemote().getAddress())) { + return; + } + + if (OS.indexOf("nix") >= 0 || OS.indexOf("nux") >= 0 || OS.indexOf("aix") > 0) { + bootstrap.getGeyserLogger().debug("We are on a Unix system, checking for Docker..."); + + String output = new String(Files.readAllBytes(Paths.get("/proc/1/cgroup"))); + + if (output.contains("docker")) { + bootstrap.getGeyserLogger().warning("You are most likely in a Docker container, this may cause connection issues from Geyser to the Java server"); + bootstrap.getGeyserLogger().warning("We recommended using the following IP as the remote address: " + ipAddress); + } + } + } catch (Exception e) { } // Ignore any errors, inc ip failed to fetch, process could not run or access denied + } +} From 3ab5c697c1376acfef80b4e17100f9e28227868f Mon Sep 17 00:00:00 2001 From: rtm516 Date: Tue, 19 May 2020 21:39:10 +0100 Subject: [PATCH 089/140] Updated mappings submodule (#596) --- connector/src/main/resources/mappings | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/connector/src/main/resources/mappings b/connector/src/main/resources/mappings index a7963d0a0..a67cc940c 160000 --- a/connector/src/main/resources/mappings +++ b/connector/src/main/resources/mappings @@ -1 +1 @@ -Subproject commit a7963d0a0236b1c47eea21718ac50706139d90cc +Subproject commit a67cc940c0d47874c833ffeb58f38e33eabfcc33 From 5fe38fa83f0494fc979ea9751d6387f3a78fab72 Mon Sep 17 00:00:00 2001 From: Creeperface01 Date: Wed, 20 May 2020 17:12:03 +0200 Subject: [PATCH 090/140] Show form window immediately after spawn (#606) --- .../connector/network/UpstreamPacketHandler.java | 7 ++++++- .../connector/utils/LoginEncryptionUtils.java | 11 +++++++---- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/network/UpstreamPacketHandler.java b/connector/src/main/java/org/geysermc/connector/network/UpstreamPacketHandler.java index dfc3112b5..2fbd487d4 100644 --- a/connector/src/main/java/org/geysermc/connector/network/UpstreamPacketHandler.java +++ b/connector/src/main/java/org/geysermc/connector/network/UpstreamPacketHandler.java @@ -110,7 +110,7 @@ public class UpstreamPacketHandler extends LoggingPacketHandler { } @Override - public boolean handle(MovePlayerPacket packet) { + public boolean handle(SetLocalPlayerAsInitializedPacket packet) { if (!session.isLoggedIn() && !session.isLoggingIn() && session.getConnector().getAuthType() == AuthType.ONLINE) { // TODO it is safer to key authentication on something that won't change (UUID, not username) if (!couldLoginUserByName(session.getAuthData().getName())) { @@ -119,6 +119,11 @@ public class UpstreamPacketHandler extends LoggingPacketHandler { // else we were able to log the user in return true; } + return translateAndDefault(packet); + } + + @Override + public boolean handle(MovePlayerPacket packet) { if (session.isLoggingIn()) { session.sendMessage("Please wait until you are logged in..."); } diff --git a/connector/src/main/java/org/geysermc/connector/utils/LoginEncryptionUtils.java b/connector/src/main/java/org/geysermc/connector/utils/LoginEncryptionUtils.java index 7f6c47604..f9a7fec26 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/LoginEncryptionUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/LoginEncryptionUtils.java @@ -34,7 +34,6 @@ import com.nukkitx.network.util.Preconditions; import com.nukkitx.protocol.bedrock.packet.LoginPacket; import com.nukkitx.protocol.bedrock.packet.ServerToClientHandshakePacket; import com.nukkitx.protocol.bedrock.util.EncryptionUtils; - import org.geysermc.common.window.CustomFormBuilder; import org.geysermc.common.window.CustomFormWindow; import org.geysermc.common.window.FormWindow; @@ -193,18 +192,22 @@ public class LoginEncryptionUtils { String password = response.getInputResponses().get(2); session.authenticate(email, password); + } else { + showLoginDetailsWindow(session); } // Clear windows so authentication data isn't accidentally cached windowCache.getWindows().clear(); } else if (formId == AUTH_FORM_ID && window instanceof SimpleFormWindow) { SimpleFormResponse response = (SimpleFormResponse) window.getResponse(); - if(response != null) { - if(response.getClickedButtonId() == 0) { + if (response != null) { + if (response.getClickedButtonId() == 0) { showLoginDetailsWindow(session); - } else if(response.getClickedButtonId() == 1) { + } else if (response.getClickedButtonId() == 1) { session.disconnect("Login is required"); } + } else { + showLoginWindow(session); } } } From 1395b719cb929a956622c8dabbb24a26e1dcf497 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+DoctorMacc@users.noreply.github.com> Date: Wed, 20 May 2020 11:12:31 -0400 Subject: [PATCH 091/140] Add missing break to JavaEntityStatusTranslator (#600) --- .../translators/java/entity/JavaEntityStatusTranslator.java | 1 + 1 file changed, 1 insertion(+) diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/JavaEntityStatusTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/JavaEntityStatusTranslator.java index 3032785af..b8675dbfe 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/JavaEntityStatusTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/JavaEntityStatusTranslator.java @@ -72,6 +72,7 @@ public class JavaEntityStatusTranslator extends PacketTranslator Date: Wed, 20 May 2020 18:39:58 +0100 Subject: [PATCH 092/140] Fixed trident display and some arrow related cleanup (#609) * Fixed trident display and some arrow related cleanup * Renamed trident entity --- .../connector/entity/AbstractArrowEntity.java | 50 +++++++++++++++++++ ...rrowEntity.java => TippedArrowEntity.java} | 4 +- .../connector/entity/TridentEntity.java | 48 ++++++++++++++++++ .../connector/entity/type/EntityType.java | 5 +- 4 files changed, 103 insertions(+), 4 deletions(-) create mode 100644 connector/src/main/java/org/geysermc/connector/entity/AbstractArrowEntity.java rename connector/src/main/java/org/geysermc/connector/entity/{ArrowEntity.java => TippedArrowEntity.java} (87%) create mode 100644 connector/src/main/java/org/geysermc/connector/entity/TridentEntity.java diff --git a/connector/src/main/java/org/geysermc/connector/entity/AbstractArrowEntity.java b/connector/src/main/java/org/geysermc/connector/entity/AbstractArrowEntity.java new file mode 100644 index 000000000..fa089707c --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/entity/AbstractArrowEntity.java @@ -0,0 +1,50 @@ +/* + * 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.entity; + +import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata; +import com.nukkitx.math.vector.Vector3f; +import com.nukkitx.protocol.bedrock.data.EntityFlag; +import org.geysermc.connector.entity.type.EntityType; +import org.geysermc.connector.network.session.GeyserSession; + +public class AbstractArrowEntity extends Entity { + + public AbstractArrowEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { + super(entityId, geyserId, entityType, position, motion, rotation); + } + + @Override + public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { + if (entityMetadata.getId() == 7) { + byte data = (byte) entityMetadata.getValue(); + + metadata.getFlags().setFlag(EntityFlag.CRITICAL, (data & 0x01) == 0x01); + } + + super.updateBedrockMetadata(entityMetadata, session); + } +} diff --git a/connector/src/main/java/org/geysermc/connector/entity/ArrowEntity.java b/connector/src/main/java/org/geysermc/connector/entity/TippedArrowEntity.java similarity index 87% rename from connector/src/main/java/org/geysermc/connector/entity/ArrowEntity.java rename to connector/src/main/java/org/geysermc/connector/entity/TippedArrowEntity.java index 961908a27..def5715c7 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/ArrowEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/TippedArrowEntity.java @@ -28,9 +28,9 @@ package org.geysermc.connector.entity; import com.nukkitx.math.vector.Vector3f; import org.geysermc.connector.entity.type.EntityType; -public class ArrowEntity extends Entity { +public class TippedArrowEntity extends AbstractArrowEntity { - public ArrowEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { + public TippedArrowEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { super(entityId, geyserId, entityType, position, motion, rotation); } } diff --git a/connector/src/main/java/org/geysermc/connector/entity/TridentEntity.java b/connector/src/main/java/org/geysermc/connector/entity/TridentEntity.java new file mode 100644 index 000000000..7c2442b0a --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/entity/TridentEntity.java @@ -0,0 +1,48 @@ +/* + * 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.entity; + +import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata; +import com.nukkitx.math.vector.Vector3f; +import com.nukkitx.protocol.bedrock.data.EntityFlag; +import org.geysermc.connector.entity.type.EntityType; +import org.geysermc.connector.network.session.GeyserSession; + +public class TridentEntity extends AbstractArrowEntity { + + public TridentEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { + super(entityId, geyserId, entityType, position, motion, rotation); + } + + @Override + public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { + if (entityMetadata.getId() == 11) { + metadata.getFlags().setFlag(EntityFlag.ENCHANTED, (boolean) entityMetadata.getValue()); + } + + super.updateBedrockMetadata(entityMetadata, session); + } +} diff --git a/connector/src/main/java/org/geysermc/connector/entity/type/EntityType.java b/connector/src/main/java/org/geysermc/connector/entity/type/EntityType.java index 6cfda74aa..99d659d11 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/type/EntityType.java +++ b/connector/src/main/java/org/geysermc/connector/entity/type/EntityType.java @@ -107,14 +107,15 @@ public enum EntityType { EYE_OF_ENDER(Entity.class, 70, 0.25f, 0.25f, 0f, 0f, "minecraft:eye_of_ender_signal"), END_CRYSTAL(EnderCrystalEntity.class, 71, 0f, 0f, 0f, 0f, "minecraft:ender_crystal"), FIREWORK_ROCKET(FireworkEntity.class, 72, 0.25f), - TRIDENT(ArrowEntity.class, 73, 0f), + TRIDENT(TridentEntity.class, 73, 0f, 0f, 0f, 0f, "minecraft:thrown_trident"), TURTLE(AnimalEntity.class, 74, 0.4f, 1.2f), CAT(CatEntity.class, 75, 0.35f, 0.3f), SHULKER_BULLET(Entity.class, 76, 0.3125f), FISHING_BOBBER(FishingHookEntity.class, 77, 0f, 0f, 0f, 0f, "minecraft:fishing_hook"), CHALKBOARD(Entity.class, 78, 0f), DRAGON_FIREBALL(ItemedFireballEntity.class, 79, 1.0f), - ARROW(ArrowEntity.class, 80, 0.25f, 0.25f), + ARROW(TippedArrowEntity.class, 80, 0.25f, 0.25f), + SPECTRAL_ARROW(AbstractArrowEntity.class, 80, 0.25f, 0.25f, 0.25f, 0f, "minecraft:arrow"), SNOWBALL(ThrowableEntity.class, 81, 0.25f), EGG(ThrowableEntity.class, 82, 0.25f), PAINTING(PaintingEntity.class, 83, 0f), From fbfc987d2b2e3e60f3cfc169d53ac20c7f0d05ae Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+DoctorMacc@users.noreply.github.com> Date: Wed, 20 May 2020 13:40:07 -0400 Subject: [PATCH 093/140] Fix mapping for Burning Skull painting type (#608) Otherwise, painting shows up as a 1x1 painting of another kind. --- .../main/java/org/geysermc/connector/utils/PaintingType.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/connector/src/main/java/org/geysermc/connector/utils/PaintingType.java b/connector/src/main/java/org/geysermc/connector/utils/PaintingType.java index 00993522b..63f1119c6 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/PaintingType.java +++ b/connector/src/main/java/org/geysermc/connector/utils/PaintingType.java @@ -57,7 +57,7 @@ public enum PaintingType { DONKEY_KONG("DonkeyKong", 4, 3), POINTER("Pointer", 4, 4), PIG_SCENE("Pigscene", 4, 4), - BURNING_SKULL("Flaming Skull", 4, 4); // burning skull on java edition, flaming skull on bedrock + BURNING_SKULL("BurningSkull", 4, 4); private static final PaintingType[] VALUES = values(); private String bedrockName; From 83c7858a8ca73b0703d34caa2e8faf73e4033227 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+DoctorMacc@users.noreply.github.com> Date: Wed, 20 May 2020 13:43:17 -0400 Subject: [PATCH 094/140] Fix bug where online mode players couldn't move after logging in (#610) --- .../org/geysermc/connector/network/UpstreamPacketHandler.java | 1 - 1 file changed, 1 deletion(-) diff --git a/connector/src/main/java/org/geysermc/connector/network/UpstreamPacketHandler.java b/connector/src/main/java/org/geysermc/connector/network/UpstreamPacketHandler.java index 2fbd487d4..3d2ded446 100644 --- a/connector/src/main/java/org/geysermc/connector/network/UpstreamPacketHandler.java +++ b/connector/src/main/java/org/geysermc/connector/network/UpstreamPacketHandler.java @@ -117,7 +117,6 @@ public class UpstreamPacketHandler extends LoggingPacketHandler { LoginEncryptionUtils.showLoginWindow(session); } // else we were able to log the user in - return true; } return translateAndDefault(packet); } From a7f363ec09a4f0410888cf669c4cc9130e7dbac6 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+DoctorMacc@users.noreply.github.com> Date: Wed, 20 May 2020 23:43:22 -0400 Subject: [PATCH 095/140] Add option for disabling command suggestions; add config version (#598) * Add option for disabling command suggestions; add config version This commit adds an option for disabling command suggestions. If enabled, command suggestions will not be sent to the server so as to remove command freezing. This commit also adds a config version variable so users are notified when to regenerate their configs. * Rename GeyserConfiguration.checkGeyserConfiguration() --- .../bukkit/GeyserBukkitConfiguration.java | 10 ++++++++++ .../platform/bukkit/GeyserBukkitPlugin.java | 2 ++ .../bungeecord/GeyserBungeeConfiguration.java | 10 ++++++++++ .../platform/bungeecord/GeyserBungeePlugin.java | 2 ++ .../sponge/GeyserSpongeConfiguration.java | 10 ++++++++++ .../platform/sponge/GeyserSpongePlugin.java | 2 ++ .../standalone/GeyserStandaloneBootstrap.java | 1 + .../standalone/GeyserStandaloneConfiguration.java | 6 ++++++ .../velocity/GeyserVelocityConfiguration.java | 6 ++++++ .../platform/velocity/GeyserVelocityPlugin.java | 2 ++ .../geysermc/connector/GeyserConfiguration.java | 15 +++++++++++++++ ...or.java => JavaDeclareCommandsTranslator.java} | 7 ++++++- connector/src/main/resources/config.yml | 7 +++++++ 13 files changed, 79 insertions(+), 1 deletion(-) rename connector/src/main/java/org/geysermc/connector/network/translators/java/{JavaServerDeclareCommandsTranslator.java => JavaDeclareCommandsTranslator.java} (97%) diff --git a/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitConfiguration.java b/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitConfiguration.java index 2213f90bb..10b06a39c 100644 --- a/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitConfiguration.java +++ b/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitConfiguration.java @@ -86,6 +86,11 @@ public class GeyserBukkitConfiguration implements GeyserConfiguration { return userAuthInfo; } + @Override + public boolean isCommandSuggestions() { + return config.getBoolean("command-suggestions", true); + } + @Override public boolean isPingPassthrough() { return config.getBoolean("ping-passthrough", false); @@ -203,4 +208,9 @@ public class GeyserBukkitConfiguration implements GeyserConfiguration { return config.getString("metrics.uuid", "generateduuid"); } } + + @Override + public int getConfigVersion() { + return config.getInt("config-version", 0); + } } diff --git a/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitPlugin.java b/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitPlugin.java index dda804b78..254b52856 100644 --- a/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitPlugin.java +++ b/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitPlugin.java @@ -28,6 +28,7 @@ package org.geysermc.platform.bukkit; import org.bukkit.Bukkit; import org.bukkit.plugin.java.JavaPlugin; import org.geysermc.common.PlatformType; +import org.geysermc.connector.GeyserConfiguration; import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.bootstrap.GeyserBootstrap; import org.geysermc.connector.command.CommandManager; @@ -55,6 +56,7 @@ public class GeyserBukkitPlugin extends JavaPlugin implements GeyserBootstrap { saveDefaultConfig(); this.geyserConfig = new GeyserBukkitConfiguration(getDataFolder(), getConfig()); + GeyserConfiguration.checkGeyserConfiguration(geyserConfig, geyserLogger); if (geyserConfig.getMetrics().getUniqueId().equals("generateduuid")) { getConfig().set("metrics.uuid", UUID.randomUUID().toString()); saveConfig(); diff --git a/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/GeyserBungeeConfiguration.java b/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/GeyserBungeeConfiguration.java index f8e401418..dc5c0fc48 100644 --- a/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/GeyserBungeeConfiguration.java +++ b/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/GeyserBungeeConfiguration.java @@ -85,6 +85,11 @@ public class GeyserBungeeConfiguration implements GeyserConfiguration { return userAuthInfo; } + @Override + public boolean isCommandSuggestions() { + return config.getBoolean("command-suggestions", true); + } + @Override public boolean isPingPassthrough() { return config.getBoolean("ping-passthrough", false); @@ -202,4 +207,9 @@ public class GeyserBungeeConfiguration implements GeyserConfiguration { return config.getString("metrics.uuid", "generateduuid"); } } + + @Override + public int getConfigVersion() { + return config.getInt("config-version", 0); + } } diff --git a/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/GeyserBungeePlugin.java b/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/GeyserBungeePlugin.java index 488854c9e..270fbd1ce 100644 --- a/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/GeyserBungeePlugin.java +++ b/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/GeyserBungeePlugin.java @@ -31,6 +31,7 @@ import net.md_5.bungee.config.Configuration; import net.md_5.bungee.config.ConfigurationProvider; import net.md_5.bungee.config.YamlConfiguration; import org.geysermc.common.PlatformType; +import org.geysermc.connector.GeyserConfiguration; import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.bootstrap.GeyserBootstrap; import org.geysermc.connector.command.CommandManager; @@ -116,6 +117,7 @@ public class GeyserBungeePlugin extends Plugin implements GeyserBootstrap { } this.geyserLogger = new GeyserBungeeLogger(getLogger(), geyserConfig.isDebugMode()); + GeyserConfiguration.checkGeyserConfiguration(geyserConfig, geyserLogger); geyserConfig.loadFloodgate(this); diff --git a/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/GeyserSpongeConfiguration.java b/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/GeyserSpongeConfiguration.java index e8459550e..96a12399b 100644 --- a/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/GeyserSpongeConfiguration.java +++ b/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/GeyserSpongeConfiguration.java @@ -79,6 +79,11 @@ public class GeyserSpongeConfiguration implements GeyserConfiguration { return userAuthInfo; } + @Override + public boolean isCommandSuggestions() { + return node.getNode("command-suggestions").getBoolean(true); + } + @Override public boolean isPingPassthrough() { return node.getNode("ping-passthrough").getBoolean(false); @@ -202,4 +207,9 @@ public class GeyserSpongeConfiguration implements GeyserConfiguration { return node.getNode("metrics").getNode("uuid").getString("generateduuid"); } } + + @Override + public int getConfigVersion() { + return node.getNode("config-version").getInt(0); + } } diff --git a/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/GeyserSpongePlugin.java b/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/GeyserSpongePlugin.java index 0c323a5ec..04a80adfc 100644 --- a/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/GeyserSpongePlugin.java +++ b/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/GeyserSpongePlugin.java @@ -30,6 +30,7 @@ import ninja.leaping.configurate.ConfigurationNode; import ninja.leaping.configurate.loader.ConfigurationLoader; import ninja.leaping.configurate.yaml.YAMLConfigurationLoader; import org.geysermc.common.PlatformType; +import org.geysermc.connector.GeyserConfiguration; import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.bootstrap.GeyserBootstrap; import org.geysermc.connector.command.CommandManager; @@ -105,6 +106,7 @@ public class GeyserSpongePlugin implements GeyserBootstrap { } this.geyserLogger = new GeyserSpongeLogger(logger, geyserConfig.isDebugMode()); + GeyserConfiguration.checkGeyserConfiguration(geyserConfig, geyserLogger); this.connector = GeyserConnector.start(PlatformType.SPONGE, this); this.geyserCommandManager = new GeyserSpongeCommandManager(Sponge.getCommandManager(), connector); diff --git a/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/GeyserStandaloneBootstrap.java b/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/GeyserStandaloneBootstrap.java index 9d2493635..0916f2129 100644 --- a/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/GeyserStandaloneBootstrap.java +++ b/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/GeyserStandaloneBootstrap.java @@ -62,6 +62,7 @@ public class GeyserStandaloneBootstrap implements GeyserBootstrap { geyserLogger.severe("Failed to read/create config.yml! Make sure it's up to date and/or readable+writable!", ex); System.exit(0); } + GeyserConfiguration.checkGeyserConfiguration(geyserConfig, geyserLogger); connector = GeyserConnector.start(PlatformType.STANDALONE, this); geyserCommandManager = new GeyserCommandManager(connector); diff --git a/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/GeyserStandaloneConfiguration.java b/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/GeyserStandaloneConfiguration.java index 8ae83d026..10e1fe0bb 100644 --- a/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/GeyserStandaloneConfiguration.java +++ b/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/GeyserStandaloneConfiguration.java @@ -47,6 +47,9 @@ public class GeyserStandaloneConfiguration implements GeyserConfiguration { private Map userAuths; + @JsonProperty("command-suggestions") + private boolean isCommandSuggestions; + @JsonProperty("ping-passthrough") private boolean pingPassthrough; @@ -112,4 +115,7 @@ public class GeyserStandaloneConfiguration implements GeyserConfiguration { @JsonProperty("uuid") private String uniqueId; } + + @JsonProperty("config-version") + private int configVersion; } diff --git a/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityConfiguration.java b/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityConfiguration.java index b9b3b3793..bc29f20d8 100644 --- a/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityConfiguration.java +++ b/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityConfiguration.java @@ -52,6 +52,9 @@ public class GeyserVelocityConfiguration implements GeyserConfiguration { private Map userAuths; + @JsonProperty("command-suggestions") + private boolean commandSuggestions; + @JsonProperty("ping-passthrough") private boolean pingPassthrough; @@ -127,4 +130,7 @@ public class GeyserVelocityConfiguration implements GeyserConfiguration { @JsonProperty("uuid") private String uniqueId; } + + @JsonProperty("config-version") + private int configVersion; } diff --git a/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityPlugin.java b/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityPlugin.java index 0269d9335..9ad8ea9ab 100644 --- a/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityPlugin.java +++ b/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityPlugin.java @@ -35,6 +35,7 @@ import com.velocitypowered.api.plugin.Plugin; import com.velocitypowered.api.proxy.ProxyServer; import org.geysermc.common.PlatformType; +import org.geysermc.connector.GeyserConfiguration; import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.bootstrap.GeyserBootstrap; import org.geysermc.connector.utils.FileUtils; @@ -90,6 +91,7 @@ public class GeyserVelocityPlugin implements GeyserBootstrap { geyserConfig.getRemote().setPort(javaAddr.getPort()); this.geyserLogger = new GeyserVelocityLogger(logger, geyserConfig.isDebugMode()); + GeyserConfiguration.checkGeyserConfiguration(geyserConfig, geyserLogger); geyserConfig.loadFloodgate(this, proxyServer, configDir); diff --git a/connector/src/main/java/org/geysermc/connector/GeyserConfiguration.java b/connector/src/main/java/org/geysermc/connector/GeyserConfiguration.java index cbbd507a1..423a3600b 100644 --- a/connector/src/main/java/org/geysermc/connector/GeyserConfiguration.java +++ b/connector/src/main/java/org/geysermc/connector/GeyserConfiguration.java @@ -31,12 +31,17 @@ import java.util.Map; public interface GeyserConfiguration { + // Modify this when you update the config + int CURRENT_CONFIG_VERSION = 1; + IBedrockConfiguration getBedrock(); IRemoteConfiguration getRemote(); Map getUserAuths(); + boolean isCommandSuggestions(); + boolean isPingPassthrough(); int getMaxPlayers(); @@ -87,4 +92,14 @@ public interface GeyserConfiguration { String getUniqueId(); } + + int getConfigVersion(); + + static void checkGeyserConfiguration(GeyserConfiguration geyserConfig, GeyserLogger geyserLogger) { + if (geyserConfig.getConfigVersion() < CURRENT_CONFIG_VERSION) { + geyserLogger.warning("Your Geyser config is out of date! Please regenerate your config when possible."); + } else if (geyserConfig.getConfigVersion() > CURRENT_CONFIG_VERSION) { + geyserLogger.warning("Your Geyser config is too new! Errors may occur."); + } + } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaServerDeclareCommandsTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaDeclareCommandsTranslator.java similarity index 97% rename from connector/src/main/java/org/geysermc/connector/network/translators/java/JavaServerDeclareCommandsTranslator.java rename to connector/src/main/java/org/geysermc/connector/network/translators/java/JavaDeclareCommandsTranslator.java index 6f16f8b42..053630d53 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaServerDeclareCommandsTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaDeclareCommandsTranslator.java @@ -43,9 +43,14 @@ import org.geysermc.connector.network.translators.Translator; import java.util.*; @Translator(packet = ServerDeclareCommandsPacket.class) -public class JavaServerDeclareCommandsTranslator extends PacketTranslator { +public class JavaDeclareCommandsTranslator extends PacketTranslator { @Override public void translate(ServerDeclareCommandsPacket packet, GeyserSession session) { + // Don't send command suggestions if they are disabled + if (!session.getConnector().getConfig().isCommandSuggestions()) { + session.getConnector().getLogger().debug("Not sending command suggestions as they are disabled."); + return; + } List commandData = new ArrayList<>(); Int2ObjectMap commands = new Int2ObjectOpenHashMap<>(); Int2ObjectMap> commandArgs = new Int2ObjectOpenHashMap<>(); diff --git a/connector/src/main/resources/config.yml b/connector/src/main/resources/config.yml index b1e1e2f93..221707f26 100644 --- a/connector/src/main/resources/config.yml +++ b/connector/src/main/resources/config.yml @@ -41,6 +41,10 @@ floodgate-key-file: public-key.pem # email: herpderp@derpherp.com # password: dooooo +# Bedrock clients can freeze when opening up the command prompt for the first time if given a lot of commands. +# Disabling this will prevent command suggestions from being sent and solve freezing for Bedrock clients. +command-suggestions: true + # Relay the MOTD, player count and max players from the remote server ping-passthrough: false @@ -78,3 +82,6 @@ metrics: enabled: true # UUID of server, don't change! uuid: generateduuid + +# DO NOT TOUCH! +config-version: 1 From 93d15c16f523ab0bca55c4228bf43c23d91f82ad Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+DoctorMacc@users.noreply.github.com> Date: Thu, 21 May 2020 10:29:32 -0400 Subject: [PATCH 096/140] Fix NPE if Bukkit configuration is out of date. (#614) --- .../java/org/geysermc/platform/bukkit/GeyserBukkitPlugin.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitPlugin.java b/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitPlugin.java index 254b52856..ad1f6194f 100644 --- a/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitPlugin.java +++ b/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitPlugin.java @@ -56,7 +56,6 @@ public class GeyserBukkitPlugin extends JavaPlugin implements GeyserBootstrap { saveDefaultConfig(); this.geyserConfig = new GeyserBukkitConfiguration(getDataFolder(), getConfig()); - GeyserConfiguration.checkGeyserConfiguration(geyserConfig, geyserLogger); if (geyserConfig.getMetrics().getUniqueId().equals("generateduuid")) { getConfig().set("metrics.uuid", UUID.randomUUID().toString()); saveConfig(); @@ -72,6 +71,7 @@ public class GeyserBukkitPlugin extends JavaPlugin implements GeyserBootstrap { saveConfig(); this.geyserLogger = new GeyserBukkitLogger(getLogger(), geyserConfig.isDebugMode()); + GeyserConfiguration.checkGeyserConfiguration(geyserConfig, geyserLogger); geyserConfig.loadFloodgate(this); From 61e0e796daf7dceacccf509e3ce19c96eafcb895 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+DoctorMacc@users.noreply.github.com> Date: Thu, 21 May 2020 18:48:24 -0400 Subject: [PATCH 097/140] Fix /geyser offhand command on Bukkit (#611) If CommandSender is not an instance of GeyserSession, we iterate through all GeyserSessions in order to find the sender. --- .../connector/command/defaults/OffhandCommand.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/connector/src/main/java/org/geysermc/connector/command/defaults/OffhandCommand.java b/connector/src/main/java/org/geysermc/connector/command/defaults/OffhandCommand.java index 5392baedd..a49506b0f 100644 --- a/connector/src/main/java/org/geysermc/connector/command/defaults/OffhandCommand.java +++ b/connector/src/main/java/org/geysermc/connector/command/defaults/OffhandCommand.java @@ -56,6 +56,16 @@ public class OffhandCommand extends GeyserCommand { ClientPlayerActionPacket releaseItemPacket = new ClientPlayerActionPacket(PlayerAction.SWAP_HANDS, new Position(0,0,0), BlockFace.DOWN); session.sendDownstreamPacket(releaseItemPacket); + return; + } + // Needed for Bukkit - sender is not an instance of GeyserSession + for (GeyserSession session : connector.getPlayers().values()) { + if (sender.getName().equals(session.getPlayerEntity().getUsername())) { + ClientPlayerActionPacket releaseItemPacket = new ClientPlayerActionPacket(PlayerAction.SWAP_HANDS, new Position(0,0,0), + BlockFace.DOWN); + session.sendDownstreamPacket(releaseItemPacket); + break; + } } } } From 81d3b0ef105fc9b07645169a281d8b2764e1e2dd Mon Sep 17 00:00:00 2001 From: OnlyBMan <27742182+OnlyBMan@users.noreply.github.com> Date: Thu, 21 May 2020 19:45:35 -0400 Subject: [PATCH 098/140] Fix painting rotation (#597) * Fix painting rotation * add comment and spacing * Dont sleep everything :P * Fix whitespace * Remove whitespace * Fix underlying issue Instead of adding a delay, exclude Painting in HeadLookTranslator.java. Thanks AJ! * Remove unneeded import Co-authored-by: Camotoy <20743703+DoctorMacc@users.noreply.github.com> --- .../translators/java/entity/JavaEntityHeadLookTranslator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/JavaEntityHeadLookTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/JavaEntityHeadLookTranslator.java index 09dd75f63..e26a5880f 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/JavaEntityHeadLookTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/JavaEntityHeadLookTranslator.java @@ -50,7 +50,7 @@ public class JavaEntityHeadLookTranslator extends PacketTranslator Date: Sat, 23 May 2020 21:56:49 +0100 Subject: [PATCH 099/140] Updated to support latest MCProtocolLib (#623) * Updated to support latest MCProtocolLib * Cleaned up names and imports * Fixed minecarts * Fixed throwables * Fixed tnt --- .../connector/entity/FishingHookEntity.java | 2 +- .../connector/entity/ItemFrameEntity.java | 2 +- .../connector/entity/type/EntityType.java | 18 ++++++------- ...or.java => JavaSpawnEntityTranslator.java} | 27 +++++++++---------- ...a => JavaSpawnLivingEntityTranslator.java} | 15 +++++------ ... => JavaSpawnWeatherEntityTranslator.java} | 10 +++---- .../geysermc/connector/utils/EntityUtils.java | 18 +------------ 7 files changed, 37 insertions(+), 55 deletions(-) rename connector/src/main/java/org/geysermc/connector/network/translators/java/entity/spawn/{JavaSpawnObjectTranslator.java => JavaSpawnEntityTranslator.java} (80%) rename connector/src/main/java/org/geysermc/connector/network/translators/java/entity/spawn/{JavaSpawnMobTranslator.java => JavaSpawnLivingEntityTranslator.java} (91%) rename connector/src/main/java/org/geysermc/connector/network/translators/java/entity/spawn/{JavaSpawnGlobalEntityTranslator.java => JavaSpawnWeatherEntityTranslator.java} (85%) diff --git a/connector/src/main/java/org/geysermc/connector/entity/FishingHookEntity.java b/connector/src/main/java/org/geysermc/connector/entity/FishingHookEntity.java index 808e16670..1b648f7cf 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/FishingHookEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/FishingHookEntity.java @@ -26,7 +26,7 @@ package org.geysermc.connector.entity; import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata; -import com.github.steveice10.mc.protocol.data.game.entity.type.object.ProjectileData; +import com.github.steveice10.mc.protocol.data.game.entity.object.ProjectileData; import com.nukkitx.math.vector.Vector3f; import com.nukkitx.protocol.bedrock.data.EntityData; import org.geysermc.connector.GeyserConnector; diff --git a/connector/src/main/java/org/geysermc/connector/entity/ItemFrameEntity.java b/connector/src/main/java/org/geysermc/connector/entity/ItemFrameEntity.java index 16942898d..f100704f1 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/ItemFrameEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/ItemFrameEntity.java @@ -27,7 +27,7 @@ package org.geysermc.connector.entity; import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata; import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; -import com.github.steveice10.mc.protocol.data.game.entity.type.object.HangingDirection; +import com.github.steveice10.mc.protocol.data.game.entity.object.HangingDirection; import com.nukkitx.math.vector.Vector3f; import com.nukkitx.math.vector.Vector3i; import com.nukkitx.nbt.CompoundTagBuilder; diff --git a/connector/src/main/java/org/geysermc/connector/entity/type/EntityType.java b/connector/src/main/java/org/geysermc/connector/entity/type/EntityType.java index 99d659d11..43beca9ba 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/type/EntityType.java +++ b/connector/src/main/java/org/geysermc/connector/entity/type/EntityType.java @@ -99,10 +99,10 @@ public enum EntityType { TRIPOD_CAMERA(Entity.class, 62, 0f), PLAYER(PlayerEntity.class, 63, 1.8f, 0.6f, 0.6f, 1.62f), ITEM(ItemEntity.class, 64, 0.25f, 0.25f), - TNT(TNTEntity.class, 65, 0.98f, 0.98f), + PRIMED_TNT(TNTEntity.class, 65, 0.98f, 0.98f, 0.98f, 0f, "minecraft:tnt"), FALLING_BLOCK(FallingBlockEntity.class, 66, 0.98f, 0.98f), MOVING_BLOCK(Entity.class, 67, 0f), - EXPERIENCE_BOTTLE(ThrowableEntity.class, 68, 0.25f, 0.25f, 0f, 0f, "minecraft:xp_bottle"), + THROWN_EXP_BOTTLE(ThrowableEntity.class, 68, 0.25f, 0.25f, 0f, 0f, "minecraft:xp_bottle"), EXPERIENCE_ORB(ExpOrbEntity.class, 69, 0f, 0f, 0f, 0f, "minecraft:xp_orb"), EYE_OF_ENDER(Entity.class, 70, 0.25f, 0.25f, 0f, 0f, "minecraft:eye_of_ender_signal"), END_CRYSTAL(EnderCrystalEntity.class, 71, 0f, 0f, 0f, 0f, "minecraft:ender_crystal"), @@ -117,12 +117,12 @@ public enum EntityType { ARROW(TippedArrowEntity.class, 80, 0.25f, 0.25f), SPECTRAL_ARROW(AbstractArrowEntity.class, 80, 0.25f, 0.25f, 0.25f, 0f, "minecraft:arrow"), SNOWBALL(ThrowableEntity.class, 81, 0.25f), - EGG(ThrowableEntity.class, 82, 0.25f), + THROWN_EGG(ThrowableEntity.class, 82, 0.25f, 0.25f, 0.25f, 0f, "minecraft:egg"), PAINTING(PaintingEntity.class, 83, 0f), MINECART(MinecartEntity.class, 84, 0.7f, 0.98f), FIREBALL(ItemedFireballEntity.class, 85, 1.0f), - POTION(ThrowableEntity.class, 86, 0.25f), - ENDER_PEARL(ThrowableEntity.class, 87, 0.25f), + THROWN_POTION(ThrowableEntity.class, 86, 0.25f, 0.25f, 0.25f, 0f, "minecraft:splash_potion"), + THROWN_ENDERPEARL(ThrowableEntity.class, 87, 0.25f, 0.25f, 0.25f, 0f, "minecraft:ender_pearl"), LEASH_KNOT(LeashKnotEntity.class, 88, 0.5f, 0.375f), WITHER_SKULL(Entity.class, 89, 0.3125f), BOAT(Entity.class, 90, 0.7f, 1.6f, 1.6f, 0.35f), @@ -130,11 +130,11 @@ public enum EntityType { LIGHTNING_BOLT(Entity.class, 93, 0f), SMALL_FIREBALL(ItemedFireballEntity.class, 94, 0.3125f), AREA_EFFECT_CLOUD(AreaEffectCloudEntity.class, 95, 0.5f, 1.0f), - HOPPER_MINECART(MinecartEntity.class, 96, 0.7f, 0.98f), - TNT_MINECART(MinecartEntity.class, 97, 0.7f, 0.98f), - CHEST_MINECART(MinecartEntity.class, 98, 0.7f, 0.98f), + MINECART_HOPPER(MinecartEntity.class, 96, 0.7f, 0.98f, 0.98f, 0f, "minecraft:hopper_minecart"), + MINECART_TNT(MinecartEntity.class, 97, 0.7f, 0.98f, 0.98f, 0f, "minecraft:tnt_minecart"), + MINECART_CHEST(MinecartEntity.class, 98, 0.7f, 0.98f, 0.98f, 0f, "minecraft:chest_minecart"), - COMMAND_BLOCK_MINECART(MinecartEntity.class, 100, 0.7f, 0.98f), + MINECART_COMMAND_BLOCK(MinecartEntity.class, 100, 0.7f, 0.98f, 0.98f, 0f, "minecraft:command_block_minecart"), LINGERING_POTION(ThrowableEntity.class, 101, 0f), LLAMA_SPIT(Entity.class, 102, 0.25f), EVOKER_FANGS(Entity.class, 103, 0.8f, 0.5f), diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/spawn/JavaSpawnObjectTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/spawn/JavaSpawnEntityTranslator.java similarity index 80% rename from connector/src/main/java/org/geysermc/connector/network/translators/java/entity/spawn/JavaSpawnObjectTranslator.java rename to connector/src/main/java/org/geysermc/connector/network/translators/java/entity/spawn/JavaSpawnEntityTranslator.java index 419f1e46a..920969a75 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/spawn/JavaSpawnObjectTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/spawn/JavaSpawnEntityTranslator.java @@ -25,17 +25,16 @@ package org.geysermc.connector.network.translators.java.entity.spawn; -import com.github.steveice10.mc.protocol.data.game.entity.type.object.FallingBlockData; -import com.github.steveice10.mc.protocol.data.game.entity.type.object.HangingDirection; -import com.github.steveice10.mc.protocol.data.game.entity.type.object.ObjectType; -import com.github.steveice10.mc.protocol.data.game.entity.type.object.ProjectileData; -import com.github.steveice10.mc.protocol.packet.ingame.server.entity.spawn.ServerSpawnObjectPacket; +import com.github.steveice10.mc.protocol.data.game.entity.object.FallingBlockData; +import com.github.steveice10.mc.protocol.data.game.entity.object.HangingDirection; +import com.github.steveice10.mc.protocol.data.game.entity.object.ProjectileData; +import com.github.steveice10.mc.protocol.data.game.entity.type.EntityType; +import com.github.steveice10.mc.protocol.packet.ingame.server.entity.spawn.ServerSpawnEntityPacket; import com.nukkitx.math.vector.Vector3f; import org.geysermc.connector.entity.Entity; import org.geysermc.connector.entity.FallingBlockEntity; import org.geysermc.connector.entity.FishingHookEntity; import org.geysermc.connector.entity.ItemFrameEntity; -import org.geysermc.connector.entity.type.EntityType; import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.PacketTranslator; import org.geysermc.connector.network.translators.Translator; @@ -44,17 +43,17 @@ import org.geysermc.connector.utils.EntityUtils; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; -@Translator(packet = ServerSpawnObjectPacket.class) -public class JavaSpawnObjectTranslator extends PacketTranslator { +@Translator(packet = ServerSpawnEntityPacket.class) +public class JavaSpawnEntityTranslator extends PacketTranslator { @Override - public void translate(ServerSpawnObjectPacket packet, GeyserSession session) { + public void translate(ServerSpawnEntityPacket packet, GeyserSession session) { Vector3f position = Vector3f.from(packet.getX(), packet.getY(), packet.getZ()); Vector3f motion = Vector3f.from(packet.getMotionX(), packet.getMotionY(), packet.getMotionZ()); Vector3f rotation = Vector3f.from(packet.getYaw(), packet.getPitch(), 0); - EntityType type = EntityUtils.toBedrockEntity(packet.getType()); + org.geysermc.connector.entity.type.EntityType type = EntityUtils.toBedrockEntity(packet.getType()); if (type == null) { session.getConnector().getLogger().warning("Entity type " + packet.getType() + " was null."); return; @@ -63,19 +62,19 @@ public class JavaSpawnObjectTranslator extends PacketTranslator entityClass = type.getEntityClass(); try { Entity entity; - if (packet.getType() == ObjectType.FALLING_BLOCK) { + if (packet.getType() == EntityType.FALLING_BLOCK) { entity = new FallingBlockEntity(packet.getEntityId(), session.getEntityCache().getNextEntityId().incrementAndGet(), type, position, motion, rotation, ((FallingBlockData) packet.getData()).getId()); - } else if (packet.getType() == ObjectType.ITEM_FRAME) { + } else if (packet.getType() == EntityType.ITEM_FRAME) { // Item frames need the hanging direction entity = new ItemFrameEntity(packet.getEntityId(), session.getEntityCache().getNextEntityId().incrementAndGet(), type, position, motion, rotation, (HangingDirection) packet.getData()); - } else if (packet.getType() == ObjectType.FISHING_BOBBER) { + } else if (packet.getType() == EntityType.FISHING_BOBBER) { // Fishing bobbers need the owner for the line entity = new FishingHookEntity(packet.getEntityId(), session.getEntityCache().getNextEntityId().incrementAndGet(), type, position, motion, rotation, (ProjectileData) packet.getData()); } else { - Constructor entityConstructor = entityClass.getConstructor(long.class, long.class, EntityType.class, + Constructor entityConstructor = entityClass.getConstructor(long.class, long.class, org.geysermc.connector.entity.type.EntityType.class, Vector3f.class, Vector3f.class, Vector3f.class); entity = entityConstructor.newInstance(packet.getEntityId(), session.getEntityCache().getNextEntityId().incrementAndGet(), diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/spawn/JavaSpawnMobTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/spawn/JavaSpawnLivingEntityTranslator.java similarity index 91% rename from connector/src/main/java/org/geysermc/connector/network/translators/java/entity/spawn/JavaSpawnMobTranslator.java rename to connector/src/main/java/org/geysermc/connector/network/translators/java/entity/spawn/JavaSpawnLivingEntityTranslator.java index d955ecfdb..8c246e514 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/spawn/JavaSpawnMobTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/spawn/JavaSpawnLivingEntityTranslator.java @@ -25,9 +25,8 @@ package org.geysermc.connector.network.translators.java.entity.spawn; -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; - +import com.github.steveice10.mc.protocol.packet.ingame.server.entity.spawn.ServerSpawnLivingEntityPacket; +import com.nukkitx.math.vector.Vector3f; import org.geysermc.connector.entity.Entity; import org.geysermc.connector.entity.type.EntityType; import org.geysermc.connector.network.session.GeyserSession; @@ -35,14 +34,14 @@ import org.geysermc.connector.network.translators.PacketTranslator; import org.geysermc.connector.network.translators.Translator; import org.geysermc.connector.utils.EntityUtils; -import com.github.steveice10.mc.protocol.packet.ingame.server.entity.spawn.ServerSpawnMobPacket; -import com.nukkitx.math.vector.Vector3f; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; -@Translator(packet = ServerSpawnMobPacket.class) -public class JavaSpawnMobTranslator extends PacketTranslator { +@Translator(packet = ServerSpawnLivingEntityPacket.class) +public class JavaSpawnLivingEntityTranslator extends PacketTranslator { @Override - public void translate(ServerSpawnMobPacket packet, GeyserSession session) { + public void translate(ServerSpawnLivingEntityPacket packet, GeyserSession session) { Vector3f position = Vector3f.from(packet.getX(), packet.getY(), packet.getZ()); Vector3f motion = Vector3f.from(packet.getMotionX(), packet.getMotionY(), packet.getMotionZ()); Vector3f rotation = Vector3f.from(packet.getYaw(), packet.getPitch(), packet.getHeadYaw()); diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/spawn/JavaSpawnGlobalEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/spawn/JavaSpawnWeatherEntityTranslator.java similarity index 85% rename from connector/src/main/java/org/geysermc/connector/network/translators/java/entity/spawn/JavaSpawnGlobalEntityTranslator.java rename to connector/src/main/java/org/geysermc/connector/network/translators/java/entity/spawn/JavaSpawnWeatherEntityTranslator.java index da2e59afe..c50686a04 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/spawn/JavaSpawnGlobalEntityTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/spawn/JavaSpawnWeatherEntityTranslator.java @@ -31,17 +31,17 @@ import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.PacketTranslator; import org.geysermc.connector.network.translators.Translator; -import com.github.steveice10.mc.protocol.packet.ingame.server.entity.spawn.ServerSpawnGlobalEntityPacket; +import com.github.steveice10.mc.protocol.packet.ingame.server.entity.spawn.ServerSpawnWeatherEntityPacket; import com.nukkitx.math.vector.Vector3f; -@Translator(packet = ServerSpawnGlobalEntityPacket.class) -public class JavaSpawnGlobalEntityTranslator extends PacketTranslator { +@Translator(packet = ServerSpawnWeatherEntityPacket.class) +public class JavaSpawnWeatherEntityTranslator extends PacketTranslator { @Override - public void translate(ServerSpawnGlobalEntityPacket packet, GeyserSession session) { + public void translate(ServerSpawnWeatherEntityPacket packet, GeyserSession session) { Vector3f position = Vector3f.from(packet.getX(), packet.getY(), packet.getZ()); - // Currently GlobalEntityType only has a lightning bolt + // Currently WeatherEntityType only has a lightning bolt Entity entity = new Entity( packet.getEntityId(), session.getEntityCache().getNextEntityId().incrementAndGet(), EntityType.LIGHTNING_BOLT, position, Vector3f.ZERO, Vector3f.ZERO diff --git a/connector/src/main/java/org/geysermc/connector/utils/EntityUtils.java b/connector/src/main/java/org/geysermc/connector/utils/EntityUtils.java index 79ce9e8b9..b5033c947 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/EntityUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/EntityUtils.java @@ -26,8 +26,6 @@ package org.geysermc.connector.utils; import com.github.steveice10.mc.protocol.data.game.entity.Effect; -import com.github.steveice10.mc.protocol.data.game.entity.type.MobType; -import com.github.steveice10.mc.protocol.data.game.entity.type.object.ObjectType; import org.geysermc.connector.entity.type.EntityType; public class EntityUtils { @@ -64,21 +62,7 @@ public class EntityUtils { * @param type The MobType to convert * @return Converted EntityType */ - public static EntityType toBedrockEntity(MobType type) { - try { - return EntityType.valueOf(type.name()); - } catch (IllegalArgumentException ex) { - return null; - } - } - - /** - * Converts a ObjectType to a Bedrock edition EntityType, returns null if the EntityType is not found - * - * @param type The ObjectType to convert - * @return Converted EntityType - */ - public static EntityType toBedrockEntity(ObjectType type) { + public static EntityType toBedrockEntity(com.github.steveice10.mc.protocol.data.game.entity.type.EntityType type) { try { return EntityType.valueOf(type.name()); } catch (IllegalArgumentException ex) { From 1664221fa9c000b711fab012ab177afb78918a08 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+DoctorMacc@users.noreply.github.com> Date: Sat, 23 May 2020 17:02:51 -0400 Subject: [PATCH 100/140] Add optional workaround for >Y128 Nether building (#615) * Add optional workaround for >Y128 Nether building This commit adds a config option for building above the Nether by changing the Nether's dimension ID to match the End's. * Only check for workaround application once * Fix mappings? * Include a bit more for the above bedrock nether building config option Co-authored-by: Redned --- .../platform/bukkit/GeyserBukkitConfiguration.java | 5 +++++ .../bungeecord/GeyserBungeeConfiguration.java | 5 +++++ .../platform/sponge/GeyserSpongeConfiguration.java | 5 +++++ .../standalone/GeyserStandaloneConfiguration.java | 3 +++ .../velocity/GeyserVelocityConfiguration.java | 3 +++ .../org/geysermc/connector/GeyserConfiguration.java | 4 +++- .../java/org/geysermc/connector/GeyserConnector.java | 4 ++++ .../org/geysermc/connector/utils/DimensionUtils.java | 11 ++++++++++- connector/src/main/resources/config.yml | 6 ++++++ 9 files changed, 44 insertions(+), 2 deletions(-) diff --git a/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitConfiguration.java b/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitConfiguration.java index 10b06a39c..aeaa912eb 100644 --- a/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitConfiguration.java +++ b/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitConfiguration.java @@ -131,6 +131,11 @@ public class GeyserBukkitConfiguration implements GeyserConfiguration { return true; // We override this as with Bukkit, we have direct access to the server implementation } + @Override + public boolean isAboveBedrockNetherBuilding() { + return config.getBoolean("above-bedrock-nether-building", false); + } + @Override public IMetricsInfo getMetrics() { return metricsInfo; diff --git a/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/GeyserBungeeConfiguration.java b/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/GeyserBungeeConfiguration.java index dc5c0fc48..b097501f7 100644 --- a/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/GeyserBungeeConfiguration.java +++ b/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/GeyserBungeeConfiguration.java @@ -130,6 +130,11 @@ public class GeyserBungeeConfiguration implements GeyserConfiguration { return config.getBoolean("cache-chunks", false); } + @Override + public boolean isAboveBedrockNetherBuilding() { + return config.getBoolean("above-bedrock-nether-building", false); + } + @Override public BungeeMetricsInfo getMetrics() { return metricsInfo; diff --git a/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/GeyserSpongeConfiguration.java b/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/GeyserSpongeConfiguration.java index 96a12399b..eb660b86d 100644 --- a/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/GeyserSpongeConfiguration.java +++ b/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/GeyserSpongeConfiguration.java @@ -124,6 +124,11 @@ public class GeyserSpongeConfiguration implements GeyserConfiguration { return node.getNode("cache-chunks").getBoolean(false); } + @Override + public boolean isAboveBedrockNetherBuilding() { + return node.getNode("above-bedrock-nether-building").getBoolean(false); + } + @Override public SpongeMetricsInfo getMetrics() { return metricsInfo; diff --git a/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/GeyserStandaloneConfiguration.java b/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/GeyserStandaloneConfiguration.java index 10e1fe0bb..a856f8a58 100644 --- a/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/GeyserStandaloneConfiguration.java +++ b/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/GeyserStandaloneConfiguration.java @@ -71,6 +71,9 @@ public class GeyserStandaloneConfiguration implements GeyserConfiguration { @JsonProperty("cache-chunks") private boolean cacheChunks; + @JsonProperty("above-bedrock-nether-building") + private boolean isAboveBedrockNetherBuilding; + private MetricsInfo metrics; @Override diff --git a/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityConfiguration.java b/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityConfiguration.java index bc29f20d8..aec4ccf9b 100644 --- a/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityConfiguration.java +++ b/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityConfiguration.java @@ -76,6 +76,9 @@ public class GeyserVelocityConfiguration implements GeyserConfiguration { @JsonProperty("cache-chunks") private boolean cacheChunks; + @JsonProperty("above-bedrock-nether-building") + private boolean aboveBedrockNetherBuilding; + private MetricsInfo metrics; private Path floodgateKey; diff --git a/connector/src/main/java/org/geysermc/connector/GeyserConfiguration.java b/connector/src/main/java/org/geysermc/connector/GeyserConfiguration.java index 423a3600b..938d25efe 100644 --- a/connector/src/main/java/org/geysermc/connector/GeyserConfiguration.java +++ b/connector/src/main/java/org/geysermc/connector/GeyserConfiguration.java @@ -32,7 +32,7 @@ import java.util.Map; public interface GeyserConfiguration { // Modify this when you update the config - int CURRENT_CONFIG_VERSION = 1; + int CURRENT_CONFIG_VERSION = 2; IBedrockConfiguration getBedrock(); @@ -56,6 +56,8 @@ public interface GeyserConfiguration { Path getFloodgateKeyFile(); + boolean isAboveBedrockNetherBuilding(); + boolean isCacheChunks(); IMetricsInfo getMetrics(); diff --git a/connector/src/main/java/org/geysermc/connector/GeyserConnector.java b/connector/src/main/java/org/geysermc/connector/GeyserConnector.java index 58307682b..75c17b29b 100644 --- a/connector/src/main/java/org/geysermc/connector/GeyserConnector.java +++ b/connector/src/main/java/org/geysermc/connector/GeyserConnector.java @@ -40,6 +40,7 @@ import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.Translators; import org.geysermc.connector.network.translators.world.WorldManager; import org.geysermc.connector.thread.PingPassthroughThread; +import org.geysermc.connector.utils.DimensionUtils; import org.geysermc.connector.utils.DockerCheck; import org.geysermc.connector.utils.Toolbox; @@ -114,6 +115,9 @@ public class GeyserConnector { if (config.isPingPassthrough()) generalThreadPool.scheduleAtFixedRate(passthroughThread, 1, 1, TimeUnit.SECONDS); + if (config.isAboveBedrockNetherBuilding()) + DimensionUtils.changeBedrockNetherId(); // Apply End dimension ID workaround to Nether + bedrockServer = new BedrockServer(new InetSocketAddress(config.getBedrock().getAddress(), config.getBedrock().getPort())); bedrockServer.setHandler(new ConnectorServerEventHandler(this)); bedrockServer.bind().whenComplete((avoid, throwable) -> { diff --git a/connector/src/main/java/org/geysermc/connector/utils/DimensionUtils.java b/connector/src/main/java/org/geysermc/connector/utils/DimensionUtils.java index 2c3933e2c..bc7745ca9 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/DimensionUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/DimensionUtils.java @@ -31,6 +31,10 @@ import org.geysermc.connector.entity.Entity; import org.geysermc.connector.network.session.GeyserSession; public class DimensionUtils { + + // Changes if the above-bedrock Nether building workaround is applied + private static int BEDROCK_NETHER_ID = 1; + public static void switchDimension(GeyserSession session, int javaDimension) { int bedrockDimension = javaToBedrock(javaDimension); Entity player = session.getPlayerEntity(); @@ -71,11 +75,16 @@ public class DimensionUtils { public static int javaToBedrock(int javaDimension) { switch (javaDimension) { case -1: - return 1; + return BEDROCK_NETHER_ID; case 1: return 2; default: return javaDimension; } } + + public static void changeBedrockNetherId() { + // Change dimension ID to the End to allow for building above Bedrock + BEDROCK_NETHER_ID = 2; + } } diff --git a/connector/src/main/resources/config.yml b/connector/src/main/resources/config.yml index 221707f26..70fcad4a2 100644 --- a/connector/src/main/resources/config.yml +++ b/connector/src/main/resources/config.yml @@ -73,6 +73,12 @@ default-locale: en_us # Geyser has direct access to the server itself. cache-chunks: false +# Bedrock prevents building and displaying blocks above Y127 in the Nether - +# enabling this config option works around that by changing the Nether dimension ID +# to the End ID. The main downside to this is that the sky will resemble that of +# the end sky in the nether, but ultimately it's the only way for this feature to work. +above-bedrock-nether-building: false + # bStats is a stat tracker that is entirely anonymous and tracks only basic information # about Geyser, such as how many people are online, how many servers are using Geyser, # what OS is being used, etc. You can learn more about bStats here: https://bstats.org/. From fc6532732da3d7ac6a1b067b4faf632f238c546e Mon Sep 17 00:00:00 2001 From: rtm516 Date: Sat, 23 May 2020 22:06:34 +0100 Subject: [PATCH 101/140] Adds skin ears from MinecraftCapes.co.uk + Clientside linked account skins + Elytra textures (#539) * Added ears geometry support * Added ear fetching from mc capes * Added support for deadmau5 * Commented, documented and cleaned code * Allow bedrock players to see their java skin/cape/ears when joining * Optimised Imports * Fix missing else statement * Moved ears and fixed elytra skins * Added ears config option * Fixed cape/elytra transparency * Fixed slim skin geometry * Fixed async ears request and added alex skin * Fixed default elytra not showing with no cape * Moved to normal Base64 functions Co-authored-by: James Harrison --- .../bukkit/GeyserBukkitConfiguration.java | 5 + .../bungeecord/GeyserBungeeConfiguration.java | 5 + .../sponge/GeyserSpongeConfiguration.java | 5 + .../GeyserStandaloneConfiguration.java | 3 + .../velocity/GeyserVelocityConfiguration.java | 3 + .../connector/GeyserConfiguration.java | 2 + .../network/session/GeyserSession.java | 11 + .../player/JavaPlayerListEntryTranslator.java | 9 +- .../connector/utils/SkinProvider.java | 278 ++++++++++++++++-- .../geysermc/connector/utils/SkinUtils.java | 58 ++-- .../bedrock/skin/geometry.humanoid.ears.json | 249 ++++++++++++++++ .../skin/geometry.humanoid.earsSlim.json | 249 ++++++++++++++++ .../main/resources/bedrock/skin/skin_alex.png | Bin 0 -> 2105 bytes connector/src/main/resources/config.yml | 4 + 14 files changed, 838 insertions(+), 43 deletions(-) create mode 100644 connector/src/main/resources/bedrock/skin/geometry.humanoid.ears.json create mode 100644 connector/src/main/resources/bedrock/skin/geometry.humanoid.earsSlim.json create mode 100644 connector/src/main/resources/bedrock/skin/skin_alex.png diff --git a/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitConfiguration.java b/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitConfiguration.java index aeaa912eb..9ea2da2ba 100644 --- a/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitConfiguration.java +++ b/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitConfiguration.java @@ -116,6 +116,11 @@ public class GeyserBukkitConfiguration implements GeyserConfiguration { return config.getBoolean("allow-third-party-capes", true); } + @Override + public boolean isAllowThirdPartyEars() { + return config.getBoolean("allow-third-party-ears", false); + } + @Override public String getDefaultLocale() { return config.getString("default-locale", "en_us"); diff --git a/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/GeyserBungeeConfiguration.java b/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/GeyserBungeeConfiguration.java index b097501f7..cb9d1fbff 100644 --- a/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/GeyserBungeeConfiguration.java +++ b/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/GeyserBungeeConfiguration.java @@ -115,6 +115,11 @@ public class GeyserBungeeConfiguration implements GeyserConfiguration { return config.getBoolean("allow-third-party-capes", true); } + @Override + public boolean isAllowThirdPartyEars() { + return config.getBoolean("allow-third-party-ears", false); + } + @Override public String getDefaultLocale() { return config.getString("default-locale", "en_us"); diff --git a/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/GeyserSpongeConfiguration.java b/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/GeyserSpongeConfiguration.java index eb660b86d..c84f2dfcb 100644 --- a/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/GeyserSpongeConfiguration.java +++ b/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/GeyserSpongeConfiguration.java @@ -109,6 +109,11 @@ public class GeyserSpongeConfiguration implements GeyserConfiguration { return node.getNode("allow-third-party-capes").getBoolean(true); } + @Override + public boolean isAllowThirdPartyEars() { + return node.getNode("allow-third-party-ears").getBoolean(false); + } + @Override public String getDefaultLocale() { return node.getNode("default-locale").getString("en_us"); diff --git a/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/GeyserStandaloneConfiguration.java b/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/GeyserStandaloneConfiguration.java index a856f8a58..8c8ce3764 100644 --- a/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/GeyserStandaloneConfiguration.java +++ b/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/GeyserStandaloneConfiguration.java @@ -65,6 +65,9 @@ public class GeyserStandaloneConfiguration implements GeyserConfiguration { @JsonProperty("allow-third-party-capes") private boolean allowThirdPartyCapes; + @JsonProperty("allow-third-party-ears") + private boolean allowThirdPartyEars; + @JsonProperty("default-locale") private String defaultLocale; diff --git a/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityConfiguration.java b/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityConfiguration.java index aec4ccf9b..685c21a39 100644 --- a/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityConfiguration.java +++ b/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityConfiguration.java @@ -70,6 +70,9 @@ public class GeyserVelocityConfiguration implements GeyserConfiguration { @JsonProperty("allow-third-party-capes") private boolean allowThirdPartyCapes; + @JsonProperty("allow-third-party-ears") + private boolean allowThirdPartyEars; + @JsonProperty("default-locale") private String defaultLocale; diff --git a/connector/src/main/java/org/geysermc/connector/GeyserConfiguration.java b/connector/src/main/java/org/geysermc/connector/GeyserConfiguration.java index 938d25efe..34edd8e08 100644 --- a/connector/src/main/java/org/geysermc/connector/GeyserConfiguration.java +++ b/connector/src/main/java/org/geysermc/connector/GeyserConfiguration.java @@ -52,6 +52,8 @@ public interface GeyserConfiguration { boolean isAllowThirdPartyCapes(); + boolean isAllowThirdPartyEars(); + String getDefaultLocale(); Path getFloodgateKeyFile(); diff --git a/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java b/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java index fa9960f2e..cec38f20b 100644 --- a/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java +++ b/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java @@ -207,6 +207,17 @@ public class GeyserSession implements CommandSender { upstream.sendPacket(playStatusPacket); } + public void fetchOurSkin(PlayerListPacket.Entry entry) { + PlayerSkinPacket playerSkinPacket = new PlayerSkinPacket(); + playerSkinPacket.setUuid(authData.getUUID()); + playerSkinPacket.setSkin(entry.getSkin()); + playerSkinPacket.setOldSkinName("OldName"); + playerSkinPacket.setNewSkinName("NewName"); + playerSkinPacket.setTrustedSkin(true); + upstream.sendPacket(playerSkinPacket); + getConnector().getLogger().debug("Sending skin for " + playerEntity.getUsername() + " " + authData.getUUID()); + } + public void login() { if (connector.getAuthType() != AuthType.ONLINE) { connector.getLogger().info( diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerListEntryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerListEntryTranslator.java index 2f71d6839..96dc60503 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerListEntryTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerListEntryTranslator.java @@ -25,6 +25,7 @@ package org.geysermc.connector.network.translators.java.entity.player; +import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.entity.PlayerEntity; import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.PacketTranslator; @@ -51,8 +52,12 @@ public class JavaPlayerListEntryTranslator extends PacketTranslator { + GeyserConnector.getInstance().getLogger().debug("Loading Local Bedrock Java Skin Data"); + }); + } else { playerEntity = new PlayerEntity( entry.getProfile(), -1, diff --git a/connector/src/main/java/org/geysermc/connector/utils/SkinProvider.java b/connector/src/main/java/org/geysermc/connector/utils/SkinProvider.java index 469ae7588..b14a99016 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/SkinProvider.java +++ b/connector/src/main/java/org/geysermc/connector/utils/SkinProvider.java @@ -35,10 +35,10 @@ import org.geysermc.connector.GeyserConnector; import javax.imageio.ImageIO; import java.awt.*; import java.awt.image.BufferedImage; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; +import java.io.*; import java.net.URL; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import java.util.Arrays; import java.util.Base64; import java.util.Map; @@ -51,6 +51,8 @@ public class SkinProvider { public static final byte[] STEVE_SKIN = new ProvidedSkin("bedrock/skin/skin_steve.png").getSkin(); public static final Skin EMPTY_SKIN = new Skin(-1, "steve", STEVE_SKIN); + public static final byte[] ALEX_SKIN = new ProvidedSkin("bedrock/skin/skin_alex.png").getSkin(); + public static final Skin EMPTY_SKIN_ALEX = new Skin(-1, "alex", ALEX_SKIN); private static Map cachedSkins = new ConcurrentHashMap<>(); private static Map> requestedSkins = new ConcurrentHashMap<>(); @@ -58,12 +60,49 @@ public class SkinProvider { private static Map cachedCapes = new ConcurrentHashMap<>(); private static Map> requestedCapes = new ConcurrentHashMap<>(); - public static final SkinGeometry EMPTY_GEOMETRY = SkinProvider.SkinGeometry.getLegacy("geometry.humanoid"); + public static final SkinGeometry EMPTY_GEOMETRY = SkinProvider.SkinGeometry.getLegacy(false); private static Map cachedGeometry = new ConcurrentHashMap<>(); + public static final boolean ALLOW_THIRD_PARTY_EARS = GeyserConnector.getInstance().getConfig().isAllowThirdPartyEars(); + public static String EARS_GEOMETRY; + public static String EARS_GEOMETRY_SLIM; + private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); private static final int CACHE_INTERVAL = 8 * 60 * 1000; // 8 minutes + static { + /* Load in the normal ears geometry */ + InputStream earsStream = Toolbox.getResource("bedrock/skin/geometry.humanoid.ears.json"); + + StringBuilder earsDataBuilder = new StringBuilder(); + try (Reader reader = new BufferedReader(new InputStreamReader(earsStream, Charset.forName(StandardCharsets.UTF_8.name())))) { + int c = 0; + while ((c = reader.read()) != -1) { + earsDataBuilder.append((char) c); + } + } catch (IOException e) { + throw new AssertionError("Unable to load ears geometry", e); + } + + EARS_GEOMETRY = earsDataBuilder.toString(); + + + /* Load in the slim ears geometry */ + earsStream = Toolbox.getResource("bedrock/skin/geometry.humanoid.earsSlim.json"); + + earsDataBuilder = new StringBuilder(); + try (Reader reader = new BufferedReader(new InputStreamReader(earsStream, Charset.forName(StandardCharsets.UTF_8.name())))) { + int c = 0; + while ((c = reader.read()) != -1) { + earsDataBuilder.append((char) c); + } + } catch (IOException e) { + throw new AssertionError("Unable to load ears geometry", e); + } + + EARS_GEOMETRY_SLIM = earsDataBuilder.toString(); + } + public static boolean hasSkinCached(UUID uuid) { return cachedSkins.containsKey(uuid); } @@ -167,6 +206,43 @@ public class SkinProvider { return CompletableFuture.completedFuture(officialCape); } + public static CompletableFuture requestEars(String earsUrl, EarsProvider provider, boolean newThread, Skin skin) { + if (earsUrl == null || earsUrl.isEmpty()) return CompletableFuture.completedFuture(skin); + + CompletableFuture future; + if (newThread) { + future = CompletableFuture.supplyAsync(() -> supplyEars(skin, earsUrl, provider), EXECUTOR_SERVICE) + .whenCompleteAsync((outSkin, throwable) -> { }); + } else { + Skin ears = supplyEars(skin, earsUrl, provider); // blocking + future = CompletableFuture.completedFuture(ears); + } + return future; + } + + /** + * Try and find an ear texture for a Java player + * + * @param officialSkin The current players skin + * @param playerId The players UUID + * @param username The players username + * @param newThread Should we start in a new thread + * @return The updated skin with ears + */ + public static CompletableFuture requestUnofficialEars(Skin officialSkin, UUID playerId, String username, boolean newThread) { + for (EarsProvider provider : EarsProvider.VALUES) { + Skin skin1 = getOrDefault( + requestEars(provider.getUrlFor(playerId, username), provider, newThread, officialSkin), + officialSkin, 4 + ); + if (skin1.isEars()) { + return CompletableFuture.completedFuture(skin1); + } + } + + return CompletableFuture.completedFuture(officialSkin); + } + public static CompletableFuture requestBedrockCape(UUID playerID, boolean newThread) { Cape bedrockCape = cachedCapes.getOrDefault(playerID.toString() + ".Bedrock", EMPTY_CAPE); return CompletableFuture.completedFuture(bedrockCape); @@ -178,7 +254,7 @@ public class SkinProvider { } public static void storeBedrockSkin(UUID playerID, String skinID, byte[] skinData) { - Skin skin = new Skin(playerID, skinID, skinData, System.currentTimeMillis(), true); + Skin skin = new Skin(playerID, skinID, skinData, System.currentTimeMillis(), true, false); cachedSkins.put(playerID, skin); } @@ -188,16 +264,36 @@ public class SkinProvider { } public static void storeBedrockGeometry(UUID playerID, byte[] geometryName, byte[] geometryData) { - SkinGeometry geometry = new SkinGeometry(new String(geometryName), new String(geometryData)); + SkinGeometry geometry = new SkinGeometry(new String(geometryName), new String(geometryData), false); cachedGeometry.put(playerID, geometry); } + /** + * Stores the ajusted skin with the ear texture to the cache + * + * @param playerID The UUID to cache it against + * @param skin The skin to cache + */ + public static void storeEarSkin(UUID playerID, Skin skin) { + cachedSkins.put(playerID, skin); + } + + /** + * Stores the geometry for a Java player with ears + * + * @param playerID The UUID to cache it against + * @param isSlim If the player is using an slim base + */ + public static void storeEarGeometry(UUID playerID, boolean isSlim) { + cachedGeometry.put(playerID, SkinGeometry.getEars(isSlim)); + } + private static Skin supplySkin(UUID uuid, String textureUrl) { byte[] skin = EMPTY_SKIN.getSkinData(); try { skin = requestImage(textureUrl, null); } catch (Exception ignored) {} // just ignore I guess - return new Skin(uuid, textureUrl, skin, System.currentTimeMillis(), false); + return new Skin(uuid, textureUrl, skin, System.currentTimeMillis(), false, false); } private static Cape supplyCape(String capeUrl, CapeProvider provider) { @@ -217,6 +313,48 @@ public class SkinProvider { ); } + /** + * Get the ears texture and place it on the skin from the given URL + * + * @param existingSkin The players current skin + * @param earsUrl The URL to get the ears texture from + * @param provider The ears texture provider + * @return The updated skin with ears + */ + private static Skin supplyEars(Skin existingSkin, String earsUrl, EarsProvider provider) { + try { + // Get the ears texture + BufferedImage ears = ImageIO.read(new URL(earsUrl)); + if (ears == null) throw new NullPointerException(); + + // Convert the skin data to a BufferedImage + int height = (existingSkin.getSkinData().length / 4 / 64); + BufferedImage skinImage = imageDataToBufferedImage(existingSkin.getSkinData(), 64, height); + + // Create a new image with the ears texture over it + BufferedImage newSkin = new BufferedImage(skinImage.getWidth(), skinImage.getHeight(), BufferedImage.TYPE_INT_ARGB); + Graphics2D g = (Graphics2D) newSkin.getGraphics(); + g.drawImage(skinImage, 0, 0, null); + g.drawImage(ears, 24, 0, null); + + // Turn the buffered image back into an array of bytes + byte[] data = bufferedImageToImageData(newSkin); + skinImage.flush(); + + // Create a new skin object with the new infomation + return new Skin( + existingSkin.getSkinOwner(), + existingSkin.getTextureUrl(), + data, + System.currentTimeMillis(), + true, + true + ); + } catch (Exception ignored) {} // just ignore I guess + + return existingSkin; + } + private static byte[] requestImage(String imageUrl, CapeProvider provider) throws Exception { BufferedImage image = downloadImage(imageUrl, provider); GeyserConnector.getInstance().getLogger().debug("Downloaded " + imageUrl); @@ -226,26 +364,16 @@ public class SkinProvider { while(image.getWidth() > 64) { image = scale(image); } - BufferedImage newImage = new BufferedImage(64, 32, BufferedImage.TYPE_INT_RGB); + BufferedImage newImage = new BufferedImage(64, 32, BufferedImage.TYPE_INT_ARGB); Graphics g = newImage.createGraphics(); g.drawImage(image, 0, 0, image.getWidth(), image.getHeight(), null); g.dispose(); image = newImage; } - try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream(image.getWidth() * 4 + image.getHeight() * 4)) { - for (int y = 0; y < image.getHeight(); y++) { - for (int x = 0; x < image.getWidth(); x++) { - int rgba = image.getRGB(x, y); - outputStream.write((rgba >> 16) & 0xFF); - outputStream.write((rgba >> 8) & 0xFF); - outputStream.write(rgba & 0xFF); - outputStream.write((rgba >> 24) & 0xFF); - } - } - image.flush(); - return outputStream.toByteArray(); - } + byte[] data = bufferedImageToImageData(image); + image.flush(); + return data; } private static BufferedImage downloadImage(String imageUrl, CapeProvider provider) throws IOException { @@ -267,7 +395,7 @@ public class SkinProvider { } private static BufferedImage scale(BufferedImage bufferedImage) { - BufferedImage resized = new BufferedImage(bufferedImage.getWidth() / 2, bufferedImage.getHeight() / 2, BufferedImage.TYPE_INT_RGB); + BufferedImage resized = new BufferedImage(bufferedImage.getWidth() / 2, bufferedImage.getHeight() / 2, BufferedImage.TYPE_INT_ARGB); Graphics2D g2 = resized.createGraphics(); g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); g2.drawImage(bufferedImage, 0, 0, bufferedImage.getWidth() / 2, bufferedImage.getHeight() / 2, null); @@ -275,6 +403,60 @@ public class SkinProvider { return resized; } + /** + * Get the RGBA int for a given index in some image data + * + * @param index Index to get + * @param data Image data to find in + * @return An int representing RGBA + */ + private static int getRGBA(int index, byte[] data) { + return (data[index] & 0xFF) << 16 | (data[index + 1] & 0xFF) << 8 | + data[index + 2] & 0xFF | (data[index + 3] & 0xFF) << 24; + } + + /** + * Convert a byte[] to a BufferedImage + * + * @param imageData The byte[] to convert + * @param imageWidth The width of the target image + * @param imageHeight The height of the target image + * @return The converted BufferedImage + */ + public static BufferedImage imageDataToBufferedImage(byte[] imageData, int imageWidth, int imageHeight) { + BufferedImage image = new BufferedImage(imageWidth, imageHeight, BufferedImage.TYPE_INT_ARGB); + int index = 0; + for (int y = 0; y < imageHeight; y++) { + for (int x = 0; x < imageWidth; x++) { + image.setRGB(x, y, getRGBA(index, imageData)); + index += 4; + } + } + + return image; + } + + /** + * Convert a BufferedImage to a byte[] + * + * @param image The BufferedImage to convert + * @return The converted byte[] + */ + public static byte[] bufferedImageToImageData(BufferedImage image) { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(image.getWidth() * 4 + image.getHeight() * 4); + for (int y = 0; y < image.getHeight(); y++) { + for (int x = 0; x < image.getWidth(); x++) { + int rgba = image.getRGB(x, y); + outputStream.write((rgba >> 16) & 0xFF); + outputStream.write((rgba >> 8) & 0xFF); + outputStream.write(rgba & 0xFF); + outputStream.write((rgba >> 24) & 0xFF); + } + } + + return outputStream.toByteArray(); + } + public static T getOrDefault(CompletableFuture future, T defaultValue, int timeoutInSeconds) { try { return future.get(timeoutInSeconds, TimeUnit.SECONDS); @@ -297,6 +479,7 @@ public class SkinProvider { private byte[] skinData; private long requestedOn; private boolean updated; + private boolean ears; private Skin(long requestedOn, String textureUrl, byte[] skinData) { this.requestedOn = requestedOn; @@ -320,9 +503,26 @@ public class SkinProvider { public static class SkinGeometry { private String geometryName; private String geometryData; + private boolean failed; - public static SkinGeometry getLegacy(String name) { - return new SkinProvider.SkinGeometry("{\"geometry\" :{\"default\" :\"" + name + "\"}}", ""); + /** + * Generate generic geometry + * + * @param isSlim Should it be the alex model + * @return The generic geometry object + */ + public static SkinGeometry getLegacy(boolean isSlim) { + return new SkinProvider.SkinGeometry("{\"geometry\" :{\"default\" :\"geometry.humanoid.custom" + (isSlim ? "Slim" : "") + "\"}}", "", true); + } + + /** + * Generate basic geometry with ears + * + * @param isSlim Should it be the alex model + * @return The generated geometry for the ears model + */ + public static SkinGeometry getEars(boolean isSlim) { + return new SkinProvider.SkinGeometry("{\"geometry\" :{\"default\" :\"geometry.humanoid.ears" + (isSlim ? "Slim" : "") + "\"}}", (isSlim ? EARS_GEOMETRY_SLIM : EARS_GEOMETRY), false); } } @@ -365,4 +565,34 @@ public class SkinProvider { UUID, UUID_DASHED } + + /* + * Sorted by 'priority' + */ + @AllArgsConstructor + @NoArgsConstructor + @Getter + public enum EarsProvider { + MINECRAFTCAPES("https://www.minecraftcapes.co.uk/getEars/%s", CapeUrlType.UUID); + + public static final EarsProvider[] VALUES = values(); + private String url; + private CapeUrlType type; + + public String getUrlFor(String type) { + return String.format(url, type); + } + + public String getUrlFor(UUID uuid, String username) { + return getUrlFor(toRequestedType(type, uuid, username)); + } + + public static String toRequestedType(CapeUrlType type, UUID uuid, String username) { + switch (type) { + case UUID: return uuid.toString().replace("-", ""); + case UUID_DASHED: return uuid.toString(); + default: return username; + } + } + } } diff --git a/connector/src/main/java/org/geysermc/connector/utils/SkinUtils.java b/connector/src/main/java/org/geysermc/connector/utils/SkinUtils.java index 8e68d3e12..95a3ff19b 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/SkinUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/SkinUtils.java @@ -53,7 +53,7 @@ public class SkinUtils { GameProfileData data = GameProfileData.from(profile); SkinProvider.Cape cape = SkinProvider.getCachedCape(data.getCapeUrl()); - SkinProvider.SkinGeometry geometry = SkinProvider.SkinGeometry.getLegacy("geometry.humanoid.custom" + (data.isAlex() ? "Slim" : "")); + SkinProvider.SkinGeometry geometry = SkinProvider.SkinGeometry.getLegacy(data.isAlex()); return buildEntryManually( profile.getId(), @@ -88,7 +88,7 @@ public class SkinUtils { String geometryName, String geometryData) { SerializedSkin serializedSkin = SerializedSkin.of( skinId, geometryName, ImageData.of(skinData), Collections.emptyList(), - ImageData.of(capeData), geometryData, "", true, false, false, capeId, uuid.toString() + ImageData.of(capeData), geometryData, "", true, false, !capeId.equals(SkinProvider.EMPTY_CAPE.getCapeId()), capeId, uuid.toString() ); PlayerListPacket.Entry entry = new PlayerListPacket.Entry(uuid); @@ -115,6 +115,9 @@ public class SkinUtils { * @return The built GameProfileData */ public static GameProfileData from(GameProfile profile) { + // Fallback to the offline mode of working it out + boolean isAlex = ((profile.getId().hashCode() % 2) == 1); + try { GameProfile.Property skinProperty = profile.getProperty("textures"); @@ -124,7 +127,7 @@ public class SkinUtils { JsonNode skinTexture = textures.get("SKIN"); String skinUrl = skinTexture.get("url").asText(); - boolean isAlex = skinTexture.has("metadata"); + isAlex = skinTexture.has("metadata"); String capeUrl = null; if (textures.has("CAPE")) { @@ -138,7 +141,7 @@ public class SkinUtils { GeyserConnector.getInstance().getLogger().debug("Got invalid texture data for " + profile.getName() + " " + exception.getMessage()); } // return default skin with default cape when texture data is invalid - return new GameProfileData(SkinProvider.EMPTY_SKIN.getTextureUrl(), SkinProvider.EMPTY_CAPE.getTextureUrl(), false); + return new GameProfileData((isAlex ? SkinProvider.EMPTY_SKIN_ALEX.getTextureUrl() : SkinProvider.EMPTY_SKIN.getTextureUrl()), SkinProvider.EMPTY_CAPE.getTextureUrl(), isAlex); } } } @@ -167,11 +170,38 @@ public class SkinUtils { ), SkinProvider.EMPTY_CAPE, SkinProvider.CapeProvider.VALUES.length * 3); } - SkinProvider.SkinGeometry geometry = SkinProvider.SkinGeometry.getLegacy("geometry.humanoid.custom" + (data.isAlex() ? "Slim" : "")); + SkinProvider.SkinGeometry geometry = SkinProvider.SkinGeometry.getLegacy(data.isAlex()); geometry = SkinProvider.getOrDefault(SkinProvider.requestBedrockGeometry( geometry, entity.getUuid(), false ), geometry, 3); + // Not a bedrock player check for ears + if (geometry.isFailed() && SkinProvider.ALLOW_THIRD_PARTY_EARS) { + boolean isEars = false; + + // Its deadmau5, gotta support his skin :) + if (entity.getUuid().toString().equals("1e18d5ff-643d-45c8-b509-43b8461d8614")) { + isEars = true; + } else { + // Get the ears texture for the player + skin = SkinProvider.getOrDefault(SkinProvider.requestUnofficialEars( + skin, entity.getUuid(), entity.getUsername(), false + ), skin, 3); + + isEars = skin.isEars(); + } + + // Does the skin have an ears texture + if (isEars) { + // Get the new geometry + geometry = SkinProvider.SkinGeometry.getEars(data.isAlex()); + + // Store the skin and geometry for the ears + SkinProvider.storeEarSkin(entity.getUuid(), skin); + SkinProvider.storeEarGeometry(entity.getUuid(), data.isAlex()); + } + } + if (entity.getLastSkinUpdate() < skin.getRequestedOn()) { entity.setLastSkinUpdate(skin.getRequestedOn()); @@ -197,6 +227,10 @@ public class SkinUtils { playerAddPacket.setAction(PlayerListPacket.Action.ADD); playerAddPacket.getEntries().add(updatedEntry); session.sendUpstreamPacket(playerAddPacket); + + if(entity.getUuid().equals(session.getPlayerEntity().getUuid())) { + session.fetchOurSkin(updatedEntry); + } } } } catch (Exception e) { @@ -217,8 +251,8 @@ public class SkinUtils { byte[] skinBytes = com.github.steveice10.mc.auth.util.Base64.decode(clientData.getSkinData().getBytes("UTF-8")); byte[] capeBytes = clientData.getCapeData(); - byte[] geometryNameBytes = com.github.steveice10.mc.auth.util.Base64.decode(clientData.getGeometryName().getBytes("UTF-8")); - byte[] geometryBytes = com.github.steveice10.mc.auth.util.Base64.decode(clientData.getGeometryData().getBytes("UTF-8")); + byte[] geometryNameBytes = Base64.getDecoder().decode(clientData.getGeometryName().getBytes("UTF-8")); + byte[] geometryBytes = Base64.getDecoder().decode(clientData.getGeometryData().getBytes("UTF-8")); if (skinBytes.length <= (128 * 128 * 4) && !clientData.isPersonaSkin()) { SkinProvider.storeBedrockSkin(playerEntity.getUuid(), data.getSkinUrl(), skinBytes); @@ -235,14 +269,4 @@ public class SkinUtils { throw new AssertionError("Failed to cache skin for bedrock user (" + playerEntity.getUsername() + "): ", e); } } - - /** - * Create a basic geometry json for the given name - * - * @param geometryName Geometry name to use - * @return Geometry data as a json string - */ - private static String getLegacySkinGeometry(String geometryName) { - return "{\"geometry\" :{\"default\" :\"" + geometryName + "\"}}"; - } } diff --git a/connector/src/main/resources/bedrock/skin/geometry.humanoid.ears.json b/connector/src/main/resources/bedrock/skin/geometry.humanoid.ears.json new file mode 100644 index 000000000..5571655b8 --- /dev/null +++ b/connector/src/main/resources/bedrock/skin/geometry.humanoid.ears.json @@ -0,0 +1,249 @@ +{ + "format_version": "1.14.0", + "minecraft:geometry": [ + { + "bones": [ + { + "name" : "root", + "pivot" : [ 0.0, 0.0, 0.0 ] + }, + + { + "name" : "waist", + "parent" : "root", + "pivot" : [ 0.0, 12.0, 0.0 ], + "rotation" : [ 0.0, 0.0, 0.0 ], + "cubes" : [] + }, + + + { + "name": "body", + "parent" : "waist", + "pivot": [ 0.0, 24.0, 0.0 ], + "rotation" : [ 0.0, 0.0, 0.0 ], + "cubes": [ + { + "origin": [ -4.0, 12.0, -2.0 ], + "size": [ 8, 12, 4 ], + "uv": [ 16, 16 ] + } + ] + }, + + { + "name": "jacket", + "parent" : "body", + "pivot": [ 0.0, 24.0, 0.0 ], + "rotation" : [ 0.0, 0.0, 0.0 ], + "cubes": [ + { + "origin": [ -4.0, 12.0, -2.0 ], + "size": [ 8, 12, 4 ], + "uv": [ 16, 32 ], + "inflate": 0.25 + } + ] + }, + + + { + "name": "head", + "parent" : "body", + "pivot": [ 0.0, 24.0, 0.0 ], + "rotation" : [ 0.0, 0.0, 0.0 ], + "cubes": [ + { + "origin": [ -4.0, 24.0, -4.0 ], + "size": [ 8, 8, 8 ], + "uv": [ 0, 0 ] + } + ] + }, + + { + "name": "hat", + "parent" : "head", + "pivot": [ 0.0, 24.0, 0.0 ], + "rotation" : [ 0.0, 0.0, 0.0 ], + "cubes": [ + { + "origin": [ -4.0, 24.0, -4.0 ], + "size": [ 8, 8, 8 ], + "uv": [ 32, 0 ], + "inflate": 0.5 + } + ] + }, + + + { + "name": "leftArm", + "parent" : "body", + "pivot": [ 5.0, 22.0, 0.0 ], + "rotation" : [ 0.0, 0.0, 0.0 ], + "cubes": [ + { + "origin": [ 4.0, 12.0, -2.0 ], + "size": [ 4, 12, 4 ], + "uv": [ 32, 48 ] + } + ] + }, + { + "name": "rightArm", + "parent" : "body", + "pivot": [ -5.0, 22.0, 0.0 ], + "rotation" : [ 0.0, 0.0, 0.0 ], + "cubes": [ + { + "origin": [ -8.0, 12.0, -2.0 ], + "size": [ 4, 12, 4 ], + "uv": [ 40, 16 ] + } + ] + }, + + { + "name": "leftSleeve", + "parent" : "leftArm", + "pivot": [ 5.0, 22.0, 0.0 ], + "rotation" : [ 0.0, 0.0, 0.0 ], + "cubes": [ + { + "origin": [ 4.0, 12.0, -2.0 ], + "size": [ 4, 12, 4 ], + "uv": [ 48, 48 ], + "inflate": 0.25 + } + ] + }, + + { + "name": "rightSleeve", + "parent" : "rightArm", + "pivot": [ -5.0, 22.0, 0.0 ], + "rotation" : [ 0.0, 0.0, 0.0 ], + "cubes": [ + { + "origin": [ -8.0, 12.0, -2.0 ], + "size": [ 4, 12, 4 ], + "uv": [ 40, 32 ], + "inflate": 0.25 + } + ] + }, + + + { + "name": "leftLeg", + "parent" : "root", + "pivot": [ 1.9, 12.0, 0.0 ], + "rotation" : [ 0.0, 0.0, 0.0 ], + "cubes": [ + { + "origin": [ -0.1, 0.0, -2.0 ], + "size": [ 4, 12, 4 ], + "uv": [ 0, 16 ] + } + ] + }, + + { + "name": "rightLeg", + "parent" : "root", + "pivot": [ -1.9, 12.0, 0.0 ], + "rotation" : [ 0.0, 0.0, 0.0 ], + "cubes": [ + { + "origin": [ -3.9, 0.0, -2.0 ], + "size": [ 4, 12, 4 ], + "uv": [ 0, 16 ] + } + ] + }, + + { + "name": "leftPants", + "parent" : "leftLeg", + "pivot": [1.9, 12.0, 0.0], + "rotation" : [ 0.0, 0.0, 0.0 ], + "cubes": [ + { + "origin": [ -0.1, 0.0, -2.0 ], + "size": [ 4, 12, 4 ], + "uv": [ 0, 48 ], + "inflate": 0.25 + } + ] + }, + + { + "name": "rightPants", + "parent" : "rightLeg", + "pivot": [ -1.9, 12.0, 0.0 ], + "rotation" : [ 0.0, 0.0, 0.0 ], + "cubes": [ + { + "origin": [ -3.9, 0.0, -2.0] , + "size": [ 4, 12, 4 ], + "uv": [ 0, 32], + "inflate": 0.25 + } + ] + }, + + + { + "name" : "rightItem", + "parent" : "rightArm", + "pivot" : [ -6.0, 15.0, 1.0 ], + "rotation" : [ 0.0, 0.0, 0.0 ], + "cubes" : [] + }, + + { + "name" : "leftItem", + "parent" : "leftArm", + "pivot" : [ 6.0, 15.0, 1.0 ], + "rotation" : [ 0.0, 0.0, 0.0 ], + "cubes" : [] + }, + + + { + "name": "leftEar", + "parent" : "head", + "pivot": [ -1.9, 12.0, 0.0 ], + "cubes": [ + { + "origin": [ 3.0, 31.0, -0.5 ], + "size": [ 6, 6, 1 ], + "uv": [ 24, 0 ], + "inflate": 0.5 + } + ] + }, + + { + "name": "rightEar", + "parent" : "head", + "pivot": [ -1.9, 12.0, 0.0 ], + "cubes": [ + { + "origin": [ -9.0, 31.0, -0.5 ], + "size": [ 6, 6, 1 ], + "uv": [ 24, 0 ], + "inflate": 0.5 + } + ] + } + ], + "description": { + "identifier": "geometry.humanoid.ears", + "texture_height": 64, + "texture_width": 64 + } + } + ] +} \ No newline at end of file diff --git a/connector/src/main/resources/bedrock/skin/geometry.humanoid.earsSlim.json b/connector/src/main/resources/bedrock/skin/geometry.humanoid.earsSlim.json new file mode 100644 index 000000000..70c44f854 --- /dev/null +++ b/connector/src/main/resources/bedrock/skin/geometry.humanoid.earsSlim.json @@ -0,0 +1,249 @@ +{ + "format_version": "1.14.0", + "minecraft:geometry": [ + { + "bones": [ + { + "name" : "root", + "pivot" : [ 0.0, 0.0, 0.0 ] + }, + + { + "name" : "waist", + "parent" : "root", + "pivot" : [ 0.0, 12.0, 0.0 ], + "rotation" : [ 0.0, 0.0, 0.0 ], + "cubes" : [] + }, + + + { + "name": "body", + "parent" : "waist", + "pivot": [ 0.0, 24.0, 0.0 ], + "rotation" : [ 0.0, 0.0, 0.0 ], + "cubes": [ + { + "origin": [ -4.0, 12.0, -2.0 ], + "size": [ 8, 12, 4 ], + "uv": [ 16, 16 ] + } + ] + }, + + { + "name": "jacket", + "parent" : "body", + "pivot": [ 0.0, 24.0, 0.0 ], + "rotation" : [ 0.0, 0.0, 0.0 ], + "cubes": [ + { + "origin": [ -4.0, 12.0, -2.0 ], + "size": [ 8, 12, 4 ], + "uv": [ 16, 32 ], + "inflate": 0.25 + } + ] + }, + + + { + "name": "head", + "parent" : "body", + "pivot": [ 0.0, 24.0, 0.0 ], + "rotation" : [ 0.0, 0.0, 0.0 ], + "cubes": [ + { + "origin": [ -4.0, 24.0, -4.0 ], + "size": [ 8, 8, 8 ], + "uv": [ 0, 0 ] + } + ] + }, + + { + "name": "hat", + "parent" : "head", + "pivot": [ 0.0, 24.0, 0.0 ], + "rotation" : [ 0.0, 0.0, 0.0 ], + "cubes": [ + { + "origin": [ -4.0, 24.0, -4.0 ], + "size": [ 8, 8, 8 ], + "uv": [ 32, 0 ], + "inflate": 0.5 + } + ] + }, + + + { + "name": "leftArm", + "parent" : "body", + "pivot": [ 5.0, 21.5, 0.0 ], + "rotation" : [ 0.0, 0.0, 0.0 ], + "cubes": [ + { + "origin": [ 4.0, 12, -2.0 ], + "size": [ 3, 12, 4 ], + "uv": [ 32, 48 ] + } + ] + }, + { + "name": "rightArm", + "parent" : "body", + "pivot": [ -5.0, 21.5, 0.0 ], + "rotation" : [ 0.0, 0.0, 0.0 ], + "cubes": [ + { + "origin": [ -7.0, 12, -2.0 ], + "size": [ 3, 12, 4 ], + "uv": [ 40, 16 ] + } + ] + }, + + { + "name": "leftSleeve", + "parent" : "leftArm", + "pivot": [ 5.0, 21.5, 0.0 ], + "rotation" : [ 0.0, 0.0, 0.0 ], + "cubes": [ + { + "origin": [ 4.0, 11.5, -2.0 ], + "size": [ 3, 12, 4 ], + "uv": [ 48, 48 ], + "inflate": 0.25 + } + ] + }, + + { + "name": "rightSleeve", + "parent" : "rightArm", + "pivot": [ -5.0, 21.5, 0.0 ], + "rotation" : [ 0.0, 0.0, 0.0 ], + "cubes": [ + { + "origin": [ -7.0, 11.5, -2.0 ], + "size": [ 3, 12, 4 ], + "uv": [ 40, 32 ], + "inflate": 0.25 + } + ] + }, + + + { + "name": "leftLeg", + "parent" : "root", + "pivot": [ 1.9, 12.0, 0.0 ], + "rotation" : [ 0.0, 0.0, 0.0 ], + "cubes": [ + { + "origin": [ -0.1, 0.0, -2.0 ], + "size": [ 4, 12, 4 ], + "uv": [ 0, 16 ] + } + ] + }, + + { + "name": "rightLeg", + "parent" : "root", + "pivot": [ -1.9, 12.0, 0.0 ], + "rotation" : [ 0.0, 0.0, 0.0 ], + "cubes": [ + { + "origin": [ -3.9, 0.0, -2.0 ], + "size": [ 4, 12, 4 ], + "uv": [ 0, 16 ] + } + ] + }, + + { + "name": "leftPants", + "parent" : "leftLeg", + "pivot": [1.9, 12.0, 0.0], + "rotation" : [ 0.0, 0.0, 0.0 ], + "cubes": [ + { + "origin": [ -0.1, 0.0, -2.0 ], + "size": [ 4, 12, 4 ], + "uv": [ 0, 48 ], + "inflate": 0.25 + } + ] + }, + + { + "name": "rightPants", + "parent" : "rightLeg", + "pivot": [ -1.9, 12.0, 0.0 ], + "rotation" : [ 0.0, 0.0, 0.0 ], + "cubes": [ + { + "origin": [ -3.9, 0.0, -2.0] , + "size": [ 4, 12, 4 ], + "uv": [ 0, 32], + "inflate": 0.25 + } + ] + }, + + + { + "name" : "rightItem", + "parent" : "rightArm", + "pivot" : [ -6.0, 15.0, 1.0 ], + "rotation" : [ 0.0, 0.0, 0.0 ], + "cubes" : [] + }, + + { + "name" : "leftItem", + "parent" : "leftArm", + "pivot" : [ 6.0, 15.0, 1.0 ], + "rotation" : [ 0.0, 0.0, 0.0 ], + "cubes" : [] + }, + + + { + "name": "leftEar", + "parent" : "head", + "pivot": [ -1.9, 12.0, 0.0 ], + "cubes": [ + { + "origin": [ 3.0, 31.0, -0.5 ], + "size": [ 6, 6, 1 ], + "uv": [ 24, 0 ], + "inflate": 0.5 + } + ] + }, + + { + "name": "rightEar", + "parent" : "head", + "pivot": [ -1.9, 12.0, 0.0 ], + "cubes": [ + { + "origin": [ -9.0, 31.0, -0.5 ], + "size": [ 6, 6, 1 ], + "uv": [ 24, 0 ], + "inflate": 0.5 + } + ] + } + ], + "description": { + "identifier": "geometry.humanoid.earsSlim", + "texture_height": 64, + "texture_width": 64 + } + } + ] +} \ No newline at end of file diff --git a/connector/src/main/resources/bedrock/skin/skin_alex.png b/connector/src/main/resources/bedrock/skin/skin_alex.png new file mode 100644 index 0000000000000000000000000000000000000000..ffd8e0719a1a4fac1f58895ed3a30130d3aa4b46 GIT binary patch literal 2105 zcmV-92*&q`P)E~eMGYDf65)*| zViT=e&nSo{8jS>AST+16Bm|5oP~|Nz*84u)@ATQ{X0O-Vy|!F8`DSKkcJKE4nP+Bq zb~Xqm*sdL17K--Ohei29dba=Zk_u98mk;K~G_bTdUr0y#7M4`%O`9cvi|;Oy^shrX zXLN9PTTGb&P-Y3>^!_E1UOCk4jDEDcJ*MmcM22COAOt`Jgy!Gh-V_rdWDx-{46_6w z03skXf3T-HCPK(00%8DEH$ZvS0Yru!0M!jpJ|zGk0ie1A_5tAX&mUAB03-lZcfdXX zT>9z5Dg!Wsp6>rp)d846PxpVQ>Hu7S*LMLG1q9$z764p-*LMLG1q9$zCIIx{$5yvp zpp?@7zaIS9>b47%QrRI+qcmyzyh}Z|Mc;86oG<0?YjZlZZJ&3k=eFoOPJ{EM{QV%& zNWz7446tUBpt*8S6rn89NWz7446tUBpt*8S6rn6Ab>Y@1%>VQIuqf8j1ZG;^g3(dN z-z;_E)+o$h|1B?ywKRd5mbYMZlsN#lRoS;$#yrj6K7Ta4dh%nD9u(bg=vFq6eBHvf zs=Wi~4aWaH_if2zVy$c-`MO0A3u)8J$iwKJJ9okd*FPlYZ(sUB@+d={ekv?ACTPGq z9}DTo3|kr7%Z(2Nh5riXZ(ra{B9AiE>BnW?ZPShyIh@Fv~t0um@Vkm>94}k zbH|){NiQ4^Z=Lx@@&x5I>gg7-{epO#(KmeUf=a$rjzdzI+QfH68Ck=q~nRyQfQ0gr!09pXR@XrK5{w@K)$6@5F z0f6R_ZdyDyfMyH;H<%Wr$A&DsKqdej(TFN8;-oNL@6k6y-QxUxl*@mcYezZjgQ1~7R8EWY$6<2o(+dOu zq|GzGIX7S6KsZ)k055RQ-i5{ZmT}1#G;yc?KM9ABEJ80P!(f}B$V*bk> zZ%F$9IDiFRJ#i!^Mio@5Zm@S_08O~n)zyU*4Ziy9A`x3&AJfp#5K}Ay3Mox%Q`%e% zz)-wTYXD5GIsF)}L9mW#*#K6oSP@b%*wWGxwzjs4kVlz5X4R@y;o7xpMaWwKw)L$c z+huf%GtYAgK$|6i>%R`k{*6DrF3d^?CDo7W6#; z>FWMm41gXJP={lD$IG#wy%IYIbug$U0HVnl_FC z$Kx6s8^fliCK2*F{E@;KrOk3*4}g%Z*Ki=3gHdT^n!Nl=F@QoD>i#a|4{UxefF=cC z-MV!}5rDGE0I+?Yx3kz7;5puo8!V@BniZ3gQP#1Zg(%63TDyrTefTwA&)YB z%<|>S!(1*WLf-c{io3_QriC$~Ozr~tWB^vE6XQ`|cK}ou&{0qkfa%&gIyx#labO?_ z1_vd@=^58uzpY#u1f88@>gyYu;T<^=1cwig?L)c_A_%A^B0vLxc^aLS0MPO< zIa?xN>r;;g2cBOd+O?)G;4?mieTelef2(tiQ%wTE6P~21yk-G()IH(_AewCev`Gs< zcaNF`U|U%Ou;W8bjsX^c9s_K2^tR@lY8pV&U7#ibP%wqiM*7mSc|q^$1x_rVRsd-i zS7r6cv;1B5WQUWbXu3S*?+elb&`W3)0f6}k#I(FG$N~V?67BML*#-!pkWS0{g46(D z-tz%O*#M^ceS!Uc0N)gF@l-FX>*aO5@S$Ijvh_)E0O08>a|kgLmOEw7vPf8Q4%-t~V(fChl~ z1=#d-x!M5q(mB5{@rAz+K3joHk=@%wb1)!4e3(~It<3WiV=L3uYJ}F|W+H5iH z_XTO!|C0ddxk6O|r2W1iY5kvO_42rH{U5W%83Uk_?+dg+tO4rvf0kqYKMBB Date: Sat, 23 May 2020 17:09:11 -0400 Subject: [PATCH 102/140] Add players able to sleep in beds (#575) * Add players able to sleep in beds This commit sets the correct metadata and flags when the Java pose changes to sleeping. * Player view while sleeping now works * Fixed bed offset for other players --- .../org/geysermc/connector/entity/Entity.java | 31 +++++++++++++++++++ ...BedrockInventoryTransactionTranslator.java | 2 ++ .../java/world/JavaBlockChangeTranslator.java | 1 - 3 files changed, 33 insertions(+), 1 deletion(-) diff --git a/connector/src/main/java/org/geysermc/connector/entity/Entity.java b/connector/src/main/java/org/geysermc/connector/entity/Entity.java index d0c1920f2..91686e428 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/Entity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/Entity.java @@ -27,14 +27,17 @@ package org.geysermc.connector.entity; import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata; import com.github.steveice10.mc.protocol.data.game.entity.metadata.MetadataType; +import com.github.steveice10.mc.protocol.data.game.entity.metadata.Pose; import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position; import com.github.steveice10.mc.protocol.data.game.entity.player.Hand; import com.github.steveice10.mc.protocol.data.game.entity.player.PlayerAction; import com.github.steveice10.mc.protocol.data.game.world.block.BlockFace; +import com.github.steveice10.mc.protocol.data.game.world.block.BlockState; import com.github.steveice10.mc.protocol.data.message.TextMessage; import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerActionPacket; import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerUseItemPacket; import com.nukkitx.math.vector.Vector3f; +import com.nukkitx.math.vector.Vector3i; import com.nukkitx.protocol.bedrock.data.EntityData; import com.nukkitx.protocol.bedrock.data.EntityDataMap; import com.nukkitx.protocol.bedrock.data.EntityFlag; @@ -50,7 +53,9 @@ import org.geysermc.connector.entity.living.ArmorStandEntity; import org.geysermc.connector.entity.type.EntityType; import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.item.ItemTranslator; +import org.geysermc.connector.network.translators.world.block.BlockTranslator; import org.geysermc.connector.utils.AttributeUtils; +import org.geysermc.connector.utils.ChunkUtils; import org.geysermc.connector.utils.MessageUtils; import java.util.ArrayList; @@ -264,6 +269,32 @@ public class Entity { case 5: // no gravity metadata.getFlags().setFlag(EntityFlag.HAS_GRAVITY, !(boolean) entityMetadata.getValue()); break; + case 6: // Pose change + if (entityMetadata.getValue().equals(Pose.SLEEPING)) { + metadata.getFlags().setFlag(EntityFlag.SLEEPING, true); + // Has to be a byte or it does not work + metadata.put(EntityData.CAN_START_SLEEP, (byte) 2); + if (entityId == session.getPlayerEntity().getEntityId()) { + Vector3i lastInteractionPos = session.getLastInteractionPosition(); + metadata.put(EntityData.BED_RESPAWN_POS, lastInteractionPos); + if (session.getConnector().getConfig().isCacheChunks()) { + BlockState bed = session.getConnector().getWorldManager().getBlockAt(session, lastInteractionPos.getX(), + lastInteractionPos.getY(), lastInteractionPos.getZ()); + // Bed has to be updated, or else player is floating in the air + ChunkUtils.updateBlock(session, bed, lastInteractionPos); + } + } else { + metadata.put(EntityData.BED_RESPAWN_POS, Vector3i.from(position.getFloorX(), position.getFloorY() - 2, position.getFloorZ())); + } + metadata.put(EntityData.BOUNDING_BOX_WIDTH, 0.2f); + metadata.put(EntityData.BOUNDING_BOX_HEIGHT, 0.2f); + } else if (metadata.getFlags().getFlag(EntityFlag.SLEEPING)) { + metadata.getFlags().setFlag(EntityFlag.SLEEPING, false); + metadata.put(EntityData.BOUNDING_BOX_WIDTH, getEntityType().getWidth()); + metadata.put(EntityData.BOUNDING_BOX_HEIGHT, getEntityType().getHeight()); + metadata.put(EntityData.CAN_START_SLEEP, (byte) 0); + } + break; case 7: // blocking if (entityMetadata.getType() == MetadataType.BYTE) { byte xd = (byte) entityMetadata.getValue(); diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockInventoryTransactionTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockInventoryTransactionTranslator.java index 71ba20e48..7a60143d2 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockInventoryTransactionTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockInventoryTransactionTranslator.java @@ -132,6 +132,8 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator Date: Sat, 23 May 2020 17:11:54 -0400 Subject: [PATCH 103/140] Debugging improvements (#585) * Debugging improvements - Added an ObjectArrayList of packets we don't anticipate ever translating. Currently only holds ServerUpdateLightPacket which we don't use and probably don't need. - Only print debugging logs from sounds if they failed to play. * Add space --- .../connector/network/translators/Registry.java | 11 ++++++++++- .../java/world/JavaPlayBuiltinSoundTranslator.java | 5 +---- .../java/world/JavaPlayerPlaySoundTranslator.java | 7 +------ 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/Registry.java b/connector/src/main/java/org/geysermc/connector/network/translators/Registry.java index 70201ba88..399ec1a6d 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/Registry.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/Registry.java @@ -28,6 +28,8 @@ package org.geysermc.connector.network.translators; import java.util.HashMap; import java.util.Map; +import com.github.steveice10.mc.protocol.packet.ingame.server.world.ServerUpdateLightPacket; +import it.unimi.dsi.fastutil.objects.ObjectArrayList; import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.network.session.GeyserSession; @@ -40,6 +42,12 @@ public class Registry { public static final Registry JAVA = new Registry<>(); public static final Registry BEDROCK = new Registry<>(); + private static final ObjectArrayList> IGNORED_PACKETS = new ObjectArrayList<>(); + + static { + IGNORED_PACKETS.add(ServerUpdateLightPacket.class); + } + public static void registerJava(Class targetPacket, PacketTranslator translator) { JAVA.MAP.put(targetPacket, translator); } @@ -56,7 +64,8 @@ public class Registry { ((PacketTranslator

) MAP.get(clazz)).translate(packet, session); return true; } else { - GeyserConnector.getInstance().getLogger().debug("Could not find packet for " + (packet.toString().length() > 25 ? packet.getClass().getSimpleName() : packet)); + if (!IGNORED_PACKETS.contains(clazz)) + GeyserConnector.getInstance().getLogger().debug("Could not find packet for " + (packet.toString().length() > 25 ? packet.getClass().getSimpleName() : packet)); } } catch (Throwable ex) { GeyserConnector.getInstance().getLogger().error("Could not translate packet " + packet.getClass().getSimpleName(), ex); diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaPlayBuiltinSoundTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaPlayBuiltinSoundTranslator.java index e060e0956..0a5274db8 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaPlayBuiltinSoundTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaPlayBuiltinSoundTranslator.java @@ -45,10 +45,8 @@ public class JavaPlayBuiltinSoundTranslator extends PacketTranslator " - + soundMapping + (soundMapping == null ? "[not found]" : "") - + " - " + packet.toString()); if (soundMapping == null) { + session.getConnector().getLogger().debug("[Builtin] Sound mapping " + packetSound + " not found - " + packet.toString()); return; } @@ -93,6 +91,5 @@ public class JavaPlayBuiltinSoundTranslator extends PacketTranslator " + soundPacket.toString()); } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaPlayerPlaySoundTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaPlayerPlaySoundTranslator.java index 97274a723..c349c628b 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaPlayerPlaySoundTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaPlayerPlaySoundTranslator.java @@ -52,15 +52,11 @@ public class JavaPlayerPlaySoundTranslator extends PacketTranslator " - + soundMapping + (soundMapping == null ? "[not found]" : "") - + " - " + packet.toString()); String playsound; if(soundMapping == null || soundMapping.getPlaysound() == null) { // no mapping session.getConnector().getLogger() - .debug("[PlaySound] Defaulting to sound server gave us."); + .debug("[PlaySound] Defaulting to sound server gave us for " + packet.toString()); playsound = packetSound; } else { playsound = soundMapping.getPlaysound(); @@ -73,6 +69,5 @@ public class JavaPlayerPlaySoundTranslator extends PacketTranslator " + playSoundPacket); } } From d8d9fb7190167e24b60ed04285782b63f64f3a54 Mon Sep 17 00:00:00 2001 From: rtm516 Date: Sat, 23 May 2020 22:33:39 +0100 Subject: [PATCH 104/140] Fireworks! (#579) * Fixed firework entity * Added firework item translator * Fixed mappings submodule --- .../connector/entity/FireworkEntity.java | 200 ++++++++++++------ .../connector/entity/type/EntityType.java | 2 +- .../translators/nbt/FireworkTranslator.java | 143 +++++++++++++ .../connector/utils/FireworkColor.java | 80 +++++++ 4 files changed, 360 insertions(+), 65 deletions(-) create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/FireworkTranslator.java create mode 100644 connector/src/main/java/org/geysermc/connector/utils/FireworkColor.java diff --git a/connector/src/main/java/org/geysermc/connector/entity/FireworkEntity.java b/connector/src/main/java/org/geysermc/connector/entity/FireworkEntity.java index 25128d486..a074a53ca 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/FireworkEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/FireworkEntity.java @@ -1,64 +1,136 @@ -/* - * 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.entity; - -import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata; -import com.nukkitx.math.vector.Vector3f; -import com.nukkitx.protocol.bedrock.packet.SetEntityMotionPacket; -import org.geysermc.connector.entity.type.EntityType; -import org.geysermc.connector.network.session.GeyserSession; - -import java.util.OptionalInt; - -public class FireworkEntity extends Entity { - - public FireworkEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { - super(entityId, geyserId, entityType, position, motion, rotation); - } - - @Override - public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { - if (entityMetadata.getId() == 8 && !entityMetadata.getValue().equals(OptionalInt.empty()) && ((OptionalInt) entityMetadata.getValue()).getAsInt() == session.getPlayerEntity().getEntityId()) { - //Checks if the firework has an entity ID (used when a player is gliding) and checks to make sure the player that is gliding is the one getting sent the packet or else every player near the gliding player will boost too. - PlayerEntity entity = session.getPlayerEntity(); - float yaw = entity.getRotation().getX(); - float pitch = entity.getRotation().getY(); - //Uses math from NukkitX - entity.setMotion(Vector3f.from( - -Math.sin(Math.toRadians(yaw)) * Math.cos(Math.toRadians(pitch)) * 2, - -Math.sin(Math.toRadians(pitch)) * 2, - Math.cos(Math.toRadians(yaw)) * Math.cos(Math.toRadians(pitch)) * 2)); - //Need to update the EntityMotionPacket or else the player won't boost - SetEntityMotionPacket entityMotionPacket = new SetEntityMotionPacket(); - entityMotionPacket.setRuntimeEntityId(entity.getGeyserId()); - entityMotionPacket.setMotion(entity.getMotion()); - - session.sendUpstreamPacket(entityMotionPacket); - } - super.updateBedrockMetadata(entityMetadata, session); - } -} \ No newline at end of file +/* + * 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.entity; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata; +import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; +import com.github.steveice10.opennbt.tag.builtin.CompoundTag; +import com.github.steveice10.opennbt.tag.builtin.ListTag; +import com.github.steveice10.opennbt.tag.builtin.Tag; +import com.nukkitx.math.vector.Vector3f; +import com.nukkitx.nbt.CompoundTagBuilder; +import com.nukkitx.protocol.bedrock.data.EntityData; +import com.nukkitx.protocol.bedrock.packet.SetEntityMotionPacket; +import org.geysermc.connector.GeyserConnector; +import org.geysermc.connector.entity.type.EntityType; +import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.utils.FireworkColor; + +import java.util.ArrayList; +import java.util.List; +import java.util.OptionalInt; + +public class FireworkEntity extends Entity { + + public FireworkEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { + super(entityId, geyserId, entityType, position, motion, rotation); + } + + + @Override + public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { + if (entityMetadata.getId() == 7) { + ItemStack item = (ItemStack) entityMetadata.getValue(); + CompoundTag tag = item.getNbt(); + CompoundTag fireworks = tag.get("Fireworks"); + + CompoundTagBuilder fireworksBuilder = CompoundTagBuilder.builder(); + fireworksBuilder.byteTag("Flight", (Byte) fireworks.get("Flight").getValue()); + + List explosions = new ArrayList<>(); + for (Tag effect : ((ListTag) fireworks.get("Explosions")).getValue()) { + CompoundTag effectData = (CompoundTag) effect; + + try { + GeyserConnector.getInstance().getLogger().debug("Effect: " + new ObjectMapper().writeValueAsString(effect)); + } catch (JsonProcessingException e) { } + + CompoundTagBuilder effectBuilder = CompoundTagBuilder.builder(); + if (effectData.get("Type") != null) { + effectBuilder.byteTag("FireworkType", (Byte) effectData.get("Type").getValue()); + } + + if (effectData.get("Colors") != null) { + int[] oldColors = (int[]) effectData.get("Colors").getValue(); + byte[] colors = new byte[oldColors.length]; + + int i = 0; + for (int color : oldColors) { + colors[i++] = FireworkColor.fromJavaID(color).getBedrockID(); + } + + effectBuilder.byteArrayTag("FireworkColor", colors); + } + + if (effectData.get("FadeColors") != null) { + int[] oldColors = (int[]) effectData.get("FadeColors").getValue(); + byte[] colors = new byte[oldColors.length]; + + int i = 0; + for (int color : oldColors) { + colors[i++] = FireworkColor.fromJavaID(color).getBedrockID(); + } + + effectBuilder.byteArrayTag("FireworkFade", colors); + } + + if (effectData.get("Trail") != null) { + effectBuilder.byteTag("FireworkTrail", (Byte) effectData.get("Trail").getValue()); + } + + if (effectData.get("Flicker") != null) { + effectBuilder.byteTag("FireworkFlicker", (Byte) effectData.get("Flicker").getValue()); + } + + explosions.add(effectBuilder.buildRootTag()); + } + + fireworksBuilder.tag(new com.nukkitx.nbt.tag.ListTag<>("Explosions", com.nukkitx.nbt.tag.CompoundTag.class, explosions)); + + metadata.put(EntityData.DISPLAY_ITEM, CompoundTagBuilder.builder().tag(fireworksBuilder.build("Fireworks")).buildRootTag()); + } else if (entityMetadata.getId() == 8 && !entityMetadata.getValue().equals(OptionalInt.empty()) && ((OptionalInt) entityMetadata.getValue()).getAsInt() == session.getPlayerEntity().getEntityId()) { + //Checks if the firework has an entity ID (used when a player is gliding) and checks to make sure the player that is gliding is the one getting sent the packet or else every player near the gliding player will boost too. + PlayerEntity entity = session.getPlayerEntity(); + float yaw = entity.getRotation().getX(); + float pitch = entity.getRotation().getY(); + //Uses math from NukkitX + entity.setMotion(Vector3f.from( + -Math.sin(Math.toRadians(yaw)) * Math.cos(Math.toRadians(pitch)) * 2, + -Math.sin(Math.toRadians(pitch)) * 2, + Math.cos(Math.toRadians(yaw)) * Math.cos(Math.toRadians(pitch)) * 2)); + //Need to update the EntityMotionPacket or else the player won't boost + SetEntityMotionPacket entityMotionPacket = new SetEntityMotionPacket(); + entityMotionPacket.setRuntimeEntityId(entity.getGeyserId()); + entityMotionPacket.setMotion(entity.getMotion()); + + session.sendUpstreamPacket(entityMotionPacket); + } + + super.updateBedrockMetadata(entityMetadata, session); + } +} diff --git a/connector/src/main/java/org/geysermc/connector/entity/type/EntityType.java b/connector/src/main/java/org/geysermc/connector/entity/type/EntityType.java index 43beca9ba..2e910a63d 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/type/EntityType.java +++ b/connector/src/main/java/org/geysermc/connector/entity/type/EntityType.java @@ -106,7 +106,7 @@ public enum EntityType { EXPERIENCE_ORB(ExpOrbEntity.class, 69, 0f, 0f, 0f, 0f, "minecraft:xp_orb"), EYE_OF_ENDER(Entity.class, 70, 0.25f, 0.25f, 0f, 0f, "minecraft:eye_of_ender_signal"), END_CRYSTAL(EnderCrystalEntity.class, 71, 0f, 0f, 0f, 0f, "minecraft:ender_crystal"), - FIREWORK_ROCKET(FireworkEntity.class, 72, 0.25f), + FIREWORK_ROCKET(FireworkEntity.class, 72, 0.25f, 0.25f, 0.25f, 0f, "minecraft:fireworks_rocket"), TRIDENT(TridentEntity.class, 73, 0f, 0f, 0f, 0f, "minecraft:thrown_trident"), TURTLE(AnimalEntity.class, 74, 0.4f, 1.2f), CAT(CatEntity.class, 75, 0.35f, 0.3f), diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/FireworkTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/FireworkTranslator.java new file mode 100644 index 000000000..77e14e5ae --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/FireworkTranslator.java @@ -0,0 +1,143 @@ +/* + * 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.item.translators.nbt; + +import com.github.steveice10.opennbt.tag.builtin.*; +import org.geysermc.connector.network.translators.ItemRemapper; +import org.geysermc.connector.network.translators.NbtItemStackTranslator; +import org.geysermc.connector.network.translators.item.ItemEntry; +import org.geysermc.connector.utils.FireworkColor; + +@ItemRemapper +public class FireworkTranslator extends NbtItemStackTranslator { + + @Override + public void translateToBedrock(CompoundTag itemTag, ItemEntry itemEntry) { + CompoundTag fireworks = itemTag.get("Fireworks"); + + ListTag explosions = fireworks.get("Explosions"); + for (Tag effect : explosions.getValue()) { + CompoundTag effectData = (CompoundTag) effect; + + CompoundTag newEffectData = new CompoundTag(""); + + if (effectData.get("Type") != null) { + newEffectData.put(new ByteTag("FireworkType", (Byte) effectData.get("Type").getValue())); + } + + if (effectData.get("Colors") != null) { + int[] oldColors = (int[]) effectData.get("Colors").getValue(); + byte[] colors = new byte[oldColors.length]; + + int i = 0; + for (int color : oldColors) { + colors[i++] = FireworkColor.fromJavaID(color).getBedrockID(); + } + + newEffectData.put(new ByteArrayTag("FireworkColor", colors)); + } + + if (effectData.get("FadeColors") != null) { + int[] oldColors = (int[]) effectData.get("FadeColors").getValue(); + byte[] colors = new byte[oldColors.length]; + + int i = 0; + for (int color : oldColors) { + colors[i++] = FireworkColor.fromJavaID(color).getBedrockID(); + } + + newEffectData.put(new ByteArrayTag("FireworkFade", colors)); + } + + if (effectData.get("Trail") != null) { + newEffectData.put(new ByteTag("FireworkTrail", (Byte) effectData.get("Trail").getValue())); + } + + if (effectData.get("Flicker") != null) { + newEffectData.put(new ByteTag("FireworkFlicker", (Byte) effectData.get("Flicker").getValue())); + } + + explosions.remove(effect); + explosions.add(newEffectData); + } + } + + @Override + public void translateToJava(CompoundTag itemTag, ItemEntry itemEntry) { + CompoundTag fireworks = itemTag.get("Fireworks"); + + ListTag explosions = fireworks.get("Explosions"); + for (Tag effect : explosions.getValue()) { + CompoundTag effectData = (CompoundTag) effect; + + CompoundTag newEffectData = new CompoundTag(""); + + if (effectData.get("FireworkType") != null) { + newEffectData.put(new ByteTag("Type", (Byte) effectData.get("FireworkType").getValue())); + } + + if (effectData.get("FireworkColor") != null) { + byte[] oldColors = (byte[]) effectData.get("FireworkColor").getValue(); + int[] colors = new int[oldColors.length]; + + int i = 0; + for (byte color : oldColors) { + colors[i++] = FireworkColor.fromBedrockID(color).getJavaID(); + } + + newEffectData.put(new IntArrayTag("Colors", colors)); + } + + if (effectData.get("FireworkFade") != null) { + byte[] oldColors = (byte[]) effectData.get("FireworkFade").getValue(); + int[] colors = new int[oldColors.length]; + + int i = 0; + for (byte color : oldColors) { + colors[i++] = FireworkColor.fromBedrockID(color).getJavaID(); + } + + newEffectData.put(new IntArrayTag("FadeColors", colors)); + } + + if (effectData.get("FireworkTrail") != null) { + newEffectData.put(new ByteTag("Trail", (Byte) effectData.get("FireworkTrail").getValue())); + } + + if (effectData.get("FireworkFlicker") != null) { + newEffectData.put(new ByteTag("Flicker", (Byte) effectData.get("FireworkFlicker").getValue())); + } + + explosions.remove(effect); + explosions.add(newEffectData); + } + } + + @Override + public boolean acceptItem(ItemEntry itemEntry) { + return "minecraft:firework_rocket".equals(itemEntry.getJavaIdentifier()); + } +} diff --git a/connector/src/main/java/org/geysermc/connector/utils/FireworkColor.java b/connector/src/main/java/org/geysermc/connector/utils/FireworkColor.java new file mode 100644 index 000000000..2f3939340 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/utils/FireworkColor.java @@ -0,0 +1,80 @@ +/* + * 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.utils; + +import lombok.Getter; + +public enum FireworkColor { + BLACK((byte) 0, 1973019), + RED((byte) 1, 11743532), + GREEN((byte) 2, 3887386), + BROWN((byte) 3, 5320730), + BLUE((byte) 4, 2437522), + PURPLE((byte) 5, 8073150), + CYAN((byte) 6, 2651799), + LIGHT_GRAY((byte) 7, 11250603), + GRAY((byte) 8, 4408131), + PINK((byte) 9, 14188952), + LIME((byte) 10, 4312372), + YELLOW((byte) 11, 14602026), + LIGHT_BLUE((byte) 12, 6719955), + MAGENTA((byte) 13, 12801229), + ORANGE((byte) 14, 15435844), + WHITE((byte) 15, 15790320); + + private static final FireworkColor[] VALUES = values(); + + @Getter + private byte bedrockID; + @Getter + private int javaID; + + FireworkColor(byte bedrockID, int javaID) { + this.bedrockID = bedrockID; + this.javaID = javaID; + } + + public static FireworkColor fromJavaID(int id) { + for (FireworkColor color : VALUES) { + if (color.javaID == id) { + return color; + } + } + + return null; + } + + public static FireworkColor fromBedrockID(int id) { + for (FireworkColor color : VALUES) { + if (color.bedrockID == id) { + return color; + } + } + + return null; + } +} From 59da87a10f5ec854396c45378b0d1ca17b0f39e9 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+DoctorMacc@users.noreply.github.com> Date: Sat, 23 May 2020 17:39:17 -0400 Subject: [PATCH 105/140] Merge entity mounts branch to master (#589) * Initial support for entity mounts* * This only works for viewing other players on mounts/vehicles. Currently, mounting on vehicles through Geyser with bedrock does not work at all, though, you can see other Java players on mounts just fine. * Fix Bedrock player mounting; add minecart offset * Remove debug code * Fix boat animation * Remove debug code * Add notice of possible steering flip * Add translator for PlayerInputPacket * Upload WIP code for BoatEntity.java * Add animation for rowing on Bedrock side * Clean up debug code, start on boat movement * Add notice about flying horses * Rename BedrockPlayerInputPacket.java to BedrockPlayerInputTranslator.java * Delete BedrockPlayerInputPacket.java * Use Translator Annotation again; Thanks to LegacyGamerHD * Upload ineffective mount-on-login code * Upload current changes with no debug code * Change case where applicable * Change Integer[] to int[]; Change schedule() to execute() * Don't use Thread.Sleep() and instead call itself again * Fix players not being linked on login/chunk load * Little changes * Minor improvements/fixes to boats * Remove empty file * Fix horse flying. * Various entity mounting fixes * Add mounting offsets for skeleton and zombie horses * Another round of entity mount-related fixes - Add offsets for skeleton and zombie horses (Thanks to tester DirtNasty) - Boats can now be placed in survival (Thanks again to tester DirtNasty) - Boats and minecarts can now shake * Add translating for ServerVehicleMovePacket * Cleaning up * More cleaning up * Add interactive tag support for mountable entities * Boats move far more nicely * Add horse heart visuals * Update interactive tags Co-authored-by: RednedEpic --- .../geysermc/connector/entity/BoatEntity.java | 138 ++++++++++++++++ .../org/geysermc/connector/entity/Entity.java | 3 +- .../connector/entity/MinecartEntity.java | 30 +++- .../connector/entity/PlayerEntity.java | 5 + .../entity/attribute/AttributeType.java | 1 + .../animal/horse/AbstractHorseEntity.java | 44 +++++ .../living/animal/horse/HorseEntity.java | 4 +- .../connector/entity/type/EntityType.java | 12 +- .../network/session/GeyserSession.java | 4 + .../network/session/cache/EntityCache.java | 11 +- .../bedrock/BedrockAnimateTranslator.java | 16 ++ .../bedrock/BedrockInteractTranslator.java | 56 +++++++ ...BedrockInventoryTransactionTranslator.java | 7 + .../BedrockMoveEntityAbsoluteTranslator.java | 48 ++++++ .../bedrock/BedrockPlayerInputTranslator.java | 21 +++ .../translators/item/ItemTranslator.java | 2 + .../JavaEntityPositionRotationTranslator.java | 8 +- .../JavaEntityPropertiesTranslator.java | 3 + .../JavaEntitySetPassengersTranslator.java | 153 ++++++++++++++++++ .../java/world/JavaVehicleMoveTranslator.java | 47 ++++++ 20 files changed, 599 insertions(+), 14 deletions(-) create mode 100644 connector/src/main/java/org/geysermc/connector/entity/BoatEntity.java create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockMoveEntityAbsoluteTranslator.java create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockPlayerInputTranslator.java create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/java/entity/JavaEntitySetPassengersTranslator.java create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaVehicleMoveTranslator.java diff --git a/connector/src/main/java/org/geysermc/connector/entity/BoatEntity.java b/connector/src/main/java/org/geysermc/connector/entity/BoatEntity.java new file mode 100644 index 000000000..8f79526de --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/entity/BoatEntity.java @@ -0,0 +1,138 @@ +/* + * 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.entity; + +import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata; +import com.nukkitx.math.vector.Vector3f; +import com.nukkitx.protocol.bedrock.data.EntityData; +import org.geysermc.connector.entity.type.EntityType; +import org.geysermc.connector.network.session.GeyserSession; + +import java.util.concurrent.TimeUnit; + +public class BoatEntity extends Entity { + + private boolean isPaddlingLeft; + private float paddleTimeLeft; + private boolean isPaddlingRight; + private float paddleTimeRight; + + // Looks too fast and too choppy with 0.1f, which is how I believe the Microsoftian client handles it + private final float ROWING_SPEED = 0.05f; + + public BoatEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { + super(entityId, geyserId, entityType, position.add(0d, entityType.getOffset(), 0d), motion, rotation.add(0, 0, 90)); + } + + @Override + public void moveAbsolute(GeyserSession session, Vector3f position, Vector3f rotation, boolean isOnGround, boolean teleported) { + // Rotation is basically only called when entering/exiting a boat. + // We don't include the rotation (y) as it causes the boat to appear sideways + super.moveAbsolute(session, position.add(0d, this.entityType.getOffset(), 0d), Vector3f.from(0, 0, rotation.getZ() + 90), isOnGround, teleported); + } + + @Override + public void moveRelative(GeyserSession session, double relX, double relY, double relZ, Vector3f rotation, boolean isOnGround) { + super.moveRelative(session, relX, relY, relZ, Vector3f.from(0, 0, rotation.getZ()), isOnGround); + } + + @Override + public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { + + // Time since last hit + if (entityMetadata.getId() == 7) { + metadata.put(EntityData.HURT_TIME, entityMetadata.getValue()); + } + + // Rocking direction + if (entityMetadata.getId() == 8) { + metadata.put(EntityData.HURT_DIRECTION, entityMetadata.getValue()); + } + + // 'Health' in Bedrock, damage taken in Java + if (entityMetadata.getId() == 9) { + // Not exactly health but it makes motion in Bedrock + metadata.put(EntityData.HEALTH, 40 - ((int) (float) entityMetadata.getValue())); + } + + if (entityMetadata.getId() == 10) { + metadata.put(EntityData.VARIANT, entityMetadata.getValue()); + } else if (entityMetadata.getId() == 11) { + isPaddlingLeft = (boolean) entityMetadata.getValue(); + if (!isPaddlingLeft) { + metadata.put(EntityData.PADDLE_TIME_LEFT, 0f); + } + else { + // Java sends simply "true" and "false" (is_paddling_left), Bedrock keeps sending packets as you're rowing + // This is an asynchronous method that emulates Bedrock rowing until "false" is sent. + paddleTimeLeft = 0f; + session.getConnector().getGeneralThreadPool().execute(() -> + updateLeftPaddle(session, entityMetadata) + ); + } + } + else if (entityMetadata.getId() == 12) { + isPaddlingRight = (boolean) entityMetadata.getValue(); + if (!isPaddlingRight) { + metadata.put(EntityData.PADDLE_TIME_RIGHT, 0f); + } else { + paddleTimeRight = 0f; + session.getConnector().getGeneralThreadPool().execute(() -> + updateRightPaddle(session, entityMetadata) + ); + } + } else if (entityMetadata.getId() == 13) { + // Possibly - I don't think this does anything? + metadata.put(EntityData.BOAT_BUBBLE_TIME, entityMetadata.getValue()); + } + + super.updateBedrockMetadata(entityMetadata, session); + } + + public void updateLeftPaddle(GeyserSession session, EntityMetadata entityMetadata) { + if (isPaddlingLeft) { + paddleTimeLeft += ROWING_SPEED; + metadata.put(EntityData.PADDLE_TIME_LEFT, paddleTimeLeft); + super.updateBedrockMetadata(entityMetadata, session); + session.getConnector().getGeneralThreadPool().schedule(() -> + updateLeftPaddle(session, entityMetadata), + 100, + TimeUnit.MILLISECONDS + ); + }} + + public void updateRightPaddle(GeyserSession session, EntityMetadata entityMetadata) { + if (isPaddlingRight) { + paddleTimeRight += ROWING_SPEED; + metadata.put(EntityData.PADDLE_TIME_RIGHT, paddleTimeRight); + super.updateBedrockMetadata(entityMetadata, session); + session.getConnector().getGeneralThreadPool().schedule(() -> + updateRightPaddle(session, entityMetadata), + 100, + TimeUnit.MILLISECONDS + ); + }} +} diff --git a/connector/src/main/java/org/geysermc/connector/entity/Entity.java b/connector/src/main/java/org/geysermc/connector/entity/Entity.java index 91686e428..30df1085c 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/Entity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/Entity.java @@ -44,7 +44,6 @@ import com.nukkitx.protocol.bedrock.data.EntityFlag; import com.nukkitx.protocol.bedrock.data.EntityFlags; import com.nukkitx.protocol.bedrock.packet.*; import it.unimi.dsi.fastutil.longs.LongOpenHashSet; -import it.unimi.dsi.fastutil.longs.LongSet; import lombok.Getter; import lombok.Setter; import org.geysermc.connector.entity.attribute.Attribute; @@ -85,7 +84,7 @@ public class Entity { protected boolean valid; - protected LongSet passengers = new LongOpenHashSet(); + protected LongOpenHashSet passengers = new LongOpenHashSet(); protected Map attributes = new HashMap<>(); protected EntityDataMap metadata = new EntityDataMap(); diff --git a/connector/src/main/java/org/geysermc/connector/entity/MinecartEntity.java b/connector/src/main/java/org/geysermc/connector/entity/MinecartEntity.java index 58c887ee6..ee004a257 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/MinecartEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/MinecartEntity.java @@ -25,12 +25,40 @@ package org.geysermc.connector.entity; +import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata; import com.nukkitx.math.vector.Vector3f; +import com.nukkitx.protocol.bedrock.data.EntityData; import org.geysermc.connector.entity.type.EntityType; +import org.geysermc.connector.network.session.GeyserSession; public class MinecartEntity extends Entity { public MinecartEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { - super(entityId, geyserId, entityType, position, motion, rotation); + super(entityId, geyserId, entityType, position.add(0d, entityType.getOffset(), 0d), motion, rotation); + } + + @Override + public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { + + if (entityMetadata.getId() == 7) { + metadata.put(EntityData.HEALTH, entityMetadata.getValue()); + } + + // Direction in which the minecart is shaking + if (entityMetadata.getId() == 8) { + metadata.put(EntityData.HURT_DIRECTION, entityMetadata.getValue()); + } + + // Power in Java, time in Bedrock + if (entityMetadata.getId() == 9) { + metadata.put(EntityData.HURT_TIME, Math.min((int) (float) entityMetadata.getValue(), 15)); + } + + super.updateBedrockMetadata(entityMetadata, session); + } + + @Override + public void moveAbsolute(GeyserSession session, Vector3f position, Vector3f rotation, boolean isOnGround, boolean teleported) { + super.moveAbsolute(session, position.add(0d, this.entityType.getOffset(), 0d), rotation, isOnGround, teleported); } } diff --git a/connector/src/main/java/org/geysermc/connector/entity/PlayerEntity.java b/connector/src/main/java/org/geysermc/connector/entity/PlayerEntity.java index 98b6b7da8..5db3fdecc 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/PlayerEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/PlayerEntity.java @@ -97,6 +97,11 @@ public class PlayerEntity extends LivingEntity { addPlayerPacket.setPlatformChatId(""); addPlayerPacket.getMetadata().putAll(metadata); + long linkedEntityId = session.getEntityCache().getCachedPlayerEntityLink(entityId); + if (linkedEntityId != -1) { + addPlayerPacket.getEntityLinks().add(new EntityLink(session.getEntityCache().getEntityByJavaId(linkedEntityId).getGeyserId(), geyserId, EntityLink.Type.RIDER, false)); + } + valid = true; session.sendUpstreamPacket(addPlayerPacket); diff --git a/connector/src/main/java/org/geysermc/connector/entity/attribute/AttributeType.java b/connector/src/main/java/org/geysermc/connector/entity/attribute/AttributeType.java index 9166fc8a2..2061b8953 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/attribute/AttributeType.java +++ b/connector/src/main/java/org/geysermc/connector/entity/attribute/AttributeType.java @@ -38,6 +38,7 @@ public enum AttributeType { MOVEMENT_SPEED("generic.movementSpeed", "minecraft:movement", 0f, 1024f, 0.1f), FLYING_SPEED("generic.flyingSpeed", "minecraft:movement", 0.0f, 1024.0f, 0.4000000059604645f), ATTACK_DAMAGE("generic.attackDamage", "minecraft:attack_damage", 0f, 2048f, 1f), + HORSE_JUMP_STRENGTH("horse.jumpStrength", "minecraft:horse.jump_strength", 0.0f, 2.0f, 0.7f), // Java Attributes ARMOR("generic.armor", null, 0f, 30f, 0f), diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/animal/horse/AbstractHorseEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/animal/horse/AbstractHorseEntity.java index 396ad6849..3773011a3 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/living/animal/horse/AbstractHorseEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/living/animal/horse/AbstractHorseEntity.java @@ -27,25 +27,69 @@ package org.geysermc.connector.entity.living.animal.horse; import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata; import com.nukkitx.math.vector.Vector3f; +import com.nukkitx.protocol.bedrock.data.Attribute; import com.nukkitx.protocol.bedrock.data.EntityFlag; +import com.nukkitx.protocol.bedrock.packet.UpdateAttributesPacket; +import org.geysermc.connector.entity.attribute.AttributeType; import org.geysermc.connector.entity.living.animal.AnimalEntity; import org.geysermc.connector.entity.type.EntityType; import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.utils.AttributeUtils; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; public class AbstractHorseEntity extends AnimalEntity { + // For updating the horse visual easier + private float health = 20f; + public AbstractHorseEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { super(entityId, geyserId, entityType, position, motion, rotation); } @Override public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { + + if (entityMetadata.getId() == 8) { + health = (float) entityMetadata.getValue(); + updateBedrockAttributes(session); + } + if (entityMetadata.getId() == 16) { byte xd = (byte) entityMetadata.getValue(); metadata.getFlags().setFlag(EntityFlag.TAMED, (xd & 0x02) == 0x02); metadata.getFlags().setFlag(EntityFlag.SADDLED, (xd & 0x04) == 0x04); metadata.getFlags().setFlag(EntityFlag.EATING, (xd & 0x10) == 0x10); + metadata.getFlags().setFlag(EntityFlag.STANDING, (xd & 0x20) == 0x20); } + + // Needed to control horses + metadata.getFlags().setFlag(EntityFlag.CAN_POWER_JUMP, true); + metadata.getFlags().setFlag(EntityFlag.WASD_CONTROLLED, true); + super.updateBedrockMetadata(entityMetadata, session); } + + @Override + public void updateBedrockAttributes(GeyserSession session) { + if (!valid) return; + + float maxHealth = attributes.containsKey(AttributeType.MAX_HEALTH) ? attributes.get(AttributeType.MAX_HEALTH).getValue() : 20f; + + List attributesLocal = new ArrayList<>(); + for (Map.Entry entry : this.attributes.entrySet()) { + if (!entry.getValue().getType().isBedrockAttribute()) + continue; + + attributesLocal.add(AttributeUtils.getBedrockAttribute(entry.getValue())); + } + attributesLocal.add(new Attribute("minecraft:health", 0.0f, maxHealth, health, maxHealth)); + + UpdateAttributesPacket updateAttributesPacket = new UpdateAttributesPacket(); + updateAttributesPacket.setRuntimeEntityId(geyserId); + updateAttributesPacket.setAttributes(attributesLocal); + session.sendUpstreamPacket(updateAttributesPacket); + } } diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/animal/horse/HorseEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/animal/horse/HorseEntity.java index b6a50520a..27f4b83c7 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/living/animal/horse/HorseEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/living/animal/horse/HorseEntity.java @@ -28,6 +28,7 @@ package org.geysermc.connector.entity.living.animal.horse; import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata; import com.nukkitx.math.vector.Vector3f; import com.nukkitx.protocol.bedrock.data.EntityData; +import com.nukkitx.protocol.bedrock.data.EntityFlag; import org.geysermc.connector.entity.type.EntityType; import org.geysermc.connector.network.session.GeyserSession; @@ -41,8 +42,9 @@ public class HorseEntity extends AbstractHorseEntity { public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { if (entityMetadata.getId() == 18) { metadata.put(EntityData.VARIANT, (int) entityMetadata.getValue()); + metadata.put(EntityData.MARK_VARIANT, (((int) entityMetadata.getValue()) >> 8) % 5); } - super.updateBedrockMetadata(entityMetadata, session); } + } \ No newline at end of file diff --git a/connector/src/main/java/org/geysermc/connector/entity/type/EntityType.java b/connector/src/main/java/org/geysermc/connector/entity/type/EntityType.java index 2e910a63d..889341965 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/type/EntityType.java +++ b/connector/src/main/java/org/geysermc/connector/entity/type/EntityType.java @@ -119,22 +119,22 @@ public enum EntityType { SNOWBALL(ThrowableEntity.class, 81, 0.25f), THROWN_EGG(ThrowableEntity.class, 82, 0.25f, 0.25f, 0.25f, 0f, "minecraft:egg"), PAINTING(PaintingEntity.class, 83, 0f), - MINECART(MinecartEntity.class, 84, 0.7f, 0.98f), + MINECART(MinecartEntity.class, 84, 0.7f, 0.98f, 0.98f, 0.35f), FIREBALL(ItemedFireballEntity.class, 85, 1.0f), THROWN_POTION(ThrowableEntity.class, 86, 0.25f, 0.25f, 0.25f, 0f, "minecraft:splash_potion"), THROWN_ENDERPEARL(ThrowableEntity.class, 87, 0.25f, 0.25f, 0.25f, 0f, "minecraft:ender_pearl"), LEASH_KNOT(LeashKnotEntity.class, 88, 0.5f, 0.375f), WITHER_SKULL(Entity.class, 89, 0.3125f), - BOAT(Entity.class, 90, 0.7f, 1.6f, 1.6f, 0.35f), + BOAT(BoatEntity.class, 90, 0.7f, 1.6f, 1.6f, 0.35f), WITHER_SKULL_DANGEROUS(Entity.class, 91, 0f), LIGHTNING_BOLT(Entity.class, 93, 0f), SMALL_FIREBALL(ItemedFireballEntity.class, 94, 0.3125f), AREA_EFFECT_CLOUD(AreaEffectCloudEntity.class, 95, 0.5f, 1.0f), - MINECART_HOPPER(MinecartEntity.class, 96, 0.7f, 0.98f, 0.98f, 0f, "minecraft:hopper_minecart"), - MINECART_TNT(MinecartEntity.class, 97, 0.7f, 0.98f, 0.98f, 0f, "minecraft:tnt_minecart"), - MINECART_CHEST(MinecartEntity.class, 98, 0.7f, 0.98f, 0.98f, 0f, "minecraft:chest_minecart"), + MINECART_HOPPER(MinecartEntity.class, 96, 0.7f, 0.98f, 0.98f, 0.35f, "minecraft:hopper_minecart"), + MINECART_TNT(MinecartEntity.class, 97, 0.7f, 0.98f, 0.98f, 0.35f, "minecraft:tnt_minecart"), + MINECART_CHEST(MinecartEntity.class, 98, 0.7f, 0.98f, 0.98f, 0.35f, "minecraft:chest_minecart"), - MINECART_COMMAND_BLOCK(MinecartEntity.class, 100, 0.7f, 0.98f, 0.98f, 0f, "minecraft:command_block_minecart"), + MINECART_COMMAND_BLOCK(MinecartEntity.class, 100, 0.7f, 0.98f, 0.98f, 0.35f, "minecraft:command_block_minecart"), LINGERING_POTION(ThrowableEntity.class, 101, 0f), LLAMA_SPIT(Entity.class, 102, 0.25f), EVOKER_FANGS(Entity.class, 103, 0.8f, 0.5f), diff --git a/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java b/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java index cec38f20b..90ca13447 100644 --- a/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java +++ b/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java @@ -58,6 +58,7 @@ import org.geysermc.common.AuthType; import org.geysermc.common.window.FormWindow; import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.command.CommandSender; +import org.geysermc.connector.entity.Entity; import org.geysermc.connector.entity.PlayerEntity; import org.geysermc.connector.inventory.PlayerInventory; import org.geysermc.connector.network.remote.RemoteServer; @@ -157,6 +158,9 @@ public class GeyserSession implements CommandSender { private boolean manyDimPackets = false; private ServerRespawnPacket lastDimPacket = null; + @Setter + private Entity ridingVehicleEntity; + @Setter private int craftSlot = 0; diff --git a/connector/src/main/java/org/geysermc/connector/network/session/cache/EntityCache.java b/connector/src/main/java/org/geysermc/connector/network/session/cache/EntityCache.java index 80d10b1a0..0bc51ac7a 100644 --- a/connector/src/main/java/org/geysermc/connector/network/session/cache/EntityCache.java +++ b/connector/src/main/java/org/geysermc/connector/network/session/cache/EntityCache.java @@ -26,8 +26,6 @@ package org.geysermc.connector.network.session.cache; import it.unimi.dsi.fastutil.longs.*; -import it.unimi.dsi.fastutil.objects.Object2LongMap; -import it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; import lombok.Getter; import org.geysermc.connector.entity.Entity; @@ -49,6 +47,7 @@ public class EntityCache { private Long2LongMap entityIdTranslations = Long2LongMaps.synchronize(new Long2LongOpenHashMap()); private Map playerEntities = Collections.synchronizedMap(new HashMap<>()); private Map bossBars = Collections.synchronizedMap(new HashMap<>()); + private Long2LongMap cachedPlayerEntityLinks = Long2LongMaps.synchronize(new Long2LongOpenHashMap()); @Getter private AtomicLong nextEntityId = new AtomicLong(2L); @@ -148,4 +147,12 @@ public class EntityCache { playerEntities = null; bossBars = null; } + + public long getCachedPlayerEntityLink(long playerId) { + return cachedPlayerEntityLinks.getOrDefault(playerId, -1); + } + + public void addCachedPlayerEntityLink(long playerId, long linkedEntityId) { + cachedPlayerEntityLinks.put(playerId, linkedEntityId); + } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockAnimateTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockAnimateTranslator.java index 35f710bd3..012582da5 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockAnimateTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockAnimateTranslator.java @@ -31,6 +31,7 @@ import org.geysermc.connector.network.translators.Translator; import com.github.steveice10.mc.protocol.data.game.entity.player.Hand; import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerSwingArmPacket; +import com.github.steveice10.mc.protocol.packet.ingame.client.world.ClientSteerBoatPacket; import com.nukkitx.protocol.bedrock.packet.AnimatePacket; import java.util.concurrent.TimeUnit; @@ -38,6 +39,9 @@ import java.util.concurrent.TimeUnit; @Translator(packet = AnimatePacket.class) public class BedrockAnimateTranslator extends PacketTranslator { + private boolean isSteeringLeft; + private boolean isSteeringRight; + @Override public void translate(AnimatePacket packet, GeyserSession session) { // Stop the player sending animations before they have fully spawned into the server @@ -54,6 +58,18 @@ public class BedrockAnimateTranslator extends PacketTranslator { TimeUnit.MILLISECONDS ); break; + // These two might need to be flipped, but my recommendation is getting moving working first + case ROW_LEFT: + // Packet value is a float of how long one has been rowing, so we convert that into a boolean + isSteeringLeft = packet.getRowingTime() > 0.0; + ClientSteerBoatPacket steerLeftPacket = new ClientSteerBoatPacket(isSteeringRight, isSteeringLeft); + session.sendDownstreamPacket(steerLeftPacket); + break; + case ROW_RIGHT: + isSteeringRight = packet.getRowingTime() > 0.0; + ClientSteerBoatPacket steerRightPacket = new ClientSteerBoatPacket(isSteeringRight, isSteeringLeft); + session.sendDownstreamPacket(steerRightPacket); + break; } } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockInteractTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockInteractTranslator.java index a40558a23..b2fd957df 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockInteractTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockInteractTranslator.java @@ -25,6 +25,8 @@ package org.geysermc.connector.network.translators.bedrock; +import com.nukkitx.protocol.bedrock.data.EntityData; +import com.nukkitx.protocol.bedrock.data.EntityFlag; import org.geysermc.connector.entity.Entity; import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.PacketTranslator; @@ -32,7 +34,9 @@ import org.geysermc.connector.network.translators.Translator; import com.github.steveice10.mc.protocol.data.game.entity.player.Hand; import com.github.steveice10.mc.protocol.data.game.entity.player.InteractAction; +import com.github.steveice10.mc.protocol.data.game.entity.player.PlayerState; import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerInteractEntityPacket; +import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerStatePacket; import com.nukkitx.protocol.bedrock.packet.InteractPacket; import org.geysermc.connector.network.translators.item.ItemTranslator; @@ -59,6 +63,58 @@ public class BedrockInteractTranslator extends PacketTranslator InteractAction.ATTACK, Hand.MAIN_HAND); session.sendDownstreamPacket(attackPacket); break; + case LEAVE_VEHICLE: + ClientPlayerStatePacket sneakPacket = new ClientPlayerStatePacket((int) entity.getEntityId(), PlayerState.START_SNEAKING); + session.sendDownstreamPacket(sneakPacket); + session.setRidingVehicleEntity(null); + break; + case MOUSEOVER: + // Handle the buttons for mobile - "Mount", etc; and the suggestions for console - "ZL: Mount", etc + if (packet.getRuntimeEntityId() != 0) { + Entity interactEntity = session.getEntityCache().getEntityByGeyserId(packet.getRuntimeEntityId()); + if (interactEntity == null) + return; + + String interactiveTag; + switch (interactEntity.getEntityType()) { + case PIG: + if (interactEntity.getMetadata().getFlags().getFlag(EntityFlag.SADDLED)) { + interactiveTag = "action.interact.mount"; + } else interactiveTag = ""; + break; + case HORSE: + case SKELETON_HORSE: + case ZOMBIE_HORSE: + case DONKEY: + case MULE: + case LLAMA: + case TRADER_LLAMA: + if (interactEntity.getMetadata().getFlags().getFlag(EntityFlag.TAMED)) { + interactiveTag = "action.interact.ride.horse"; + } else { + interactiveTag = "action.interact.mount"; + } + break; + case BOAT: + interactiveTag = "action.interact.ride.boat"; + break; + case MINECART: + interactiveTag = "action.interact.ride.minecart"; + break; + default: + return; // No need to process any further since there is no interactive tag + } + session.getPlayerEntity().getMetadata().put(EntityData.INTERACTIVE_TAG, interactiveTag); + session.getPlayerEntity().updateBedrockMetadata(session); + } else { + if (!(session.getPlayerEntity().getMetadata().get(EntityData.INTERACTIVE_TAG) == null) || + !(session.getPlayerEntity().getMetadata().get(EntityData.INTERACTIVE_TAG) == "")) { + // No interactive tag should be sent + session.getPlayerEntity().getMetadata().remove(EntityData.INTERACTIVE_TAG); + session.getPlayerEntity().updateBedrockMetadata(session); + } + } + break; } } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockInventoryTransactionTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockInventoryTransactionTranslator.java index 7a60143d2..e4e654f0a 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockInventoryTransactionTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockInventoryTransactionTranslator.java @@ -96,6 +96,13 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator { + + @Override + public void translate(MoveEntityAbsolutePacket packet, GeyserSession session) { + + ClientVehicleMovePacket clientVehicleMovePacket = new ClientVehicleMovePacket( + packet.getPosition().getX(), packet.getPosition().getY(), packet.getPosition().getZ(), + packet.getRotation().getY() - 90, packet.getRotation().getX() + ); + session.sendDownstreamPacket(clientVehicleMovePacket); + } +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockPlayerInputTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockPlayerInputTranslator.java new file mode 100644 index 000000000..960fbf486 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockPlayerInputTranslator.java @@ -0,0 +1,21 @@ +package org.geysermc.connector.network.translators.bedrock; + +import com.github.steveice10.mc.protocol.packet.ingame.client.world.ClientSteerVehiclePacket; +import com.nukkitx.protocol.bedrock.packet.PlayerInputPacket; +import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.PacketTranslator; +import org.geysermc.connector.network.translators.Translator; + +// Makes minecarts respond to player input +@Translator(packet = PlayerInputPacket.class) +public class BedrockPlayerInputTranslator extends PacketTranslator { + + @Override + public void translate(PlayerInputPacket packet, GeyserSession session) { + ClientSteerVehiclePacket clientSteerVehiclePacket = new ClientSteerVehiclePacket( + packet.getInputMotion().getX(), packet.getInputMotion().getY(), packet.isJumping(), packet.isSneaking() + ); + + session.sendDownstreamPacket(clientSteerVehiclePacket); + } +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemTranslator.java index f59b82ba0..287669713 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemTranslator.java @@ -48,6 +48,8 @@ public class ItemTranslator { // Shield ID, used in Entity.java public static final int SHIELD = 829; + // Boat ID, used in BedrockInventoryTransactionTranslator.java + public static final int BOAT = 333; public void init() { Reflections ref = new Reflections("org.geysermc.connector.network.translators.item"); diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/JavaEntityPositionRotationTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/JavaEntityPositionRotationTranslator.java index 581f16e36..477c8f261 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/JavaEntityPositionRotationTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/JavaEntityPositionRotationTranslator.java @@ -26,6 +26,7 @@ package org.geysermc.connector.network.translators.java.entity; import org.geysermc.connector.entity.Entity; +import org.geysermc.connector.entity.type.EntityType; import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.PacketTranslator; import org.geysermc.connector.network.translators.Translator; @@ -42,7 +43,10 @@ public class JavaEntityPositionRotationTranslator extends PacketTranslator { + + @Override + public void translate(ServerEntitySetPassengersPacket packet, GeyserSession session) { + Entity entity = session.getEntityCache().getEntityByJavaId(packet.getEntityId()); + if (entity == null) return; + + LongOpenHashSet passengers = entity.getPassengers().clone(); + boolean rider = true; + for (long passengerId : packet.getPassengerIds()) { + Entity passenger = session.getEntityCache().getEntityByJavaId(passengerId); + if (passengerId == session.getPlayerEntity().getEntityId()) { + passenger = session.getPlayerEntity(); + session.setRidingVehicleEntity(entity); + } + // Passenger hasn't loaded in and entity link needs to be set later + if (passenger == null && passengerId != 0) { + session.getEntityCache().addCachedPlayerEntityLink(passengerId, packet.getEntityId()); + } + if (passenger == null) { + continue; + } + + EntityLink.Type type = rider ? EntityLink.Type.RIDER : EntityLink.Type.PASSENGER; + SetEntityLinkPacket linkPacket = new SetEntityLinkPacket(); + linkPacket.setEntityLink(new EntityLink(entity.getGeyserId(), passenger.getGeyserId(), type, false)); + session.sendUpstreamPacket(linkPacket); + passengers.add(passengerId); + + // Head rotation on boats + if (entity.getEntityType() == EntityType.BOAT) { + passenger.getMetadata().put(EntityData.RIDER_ROTATION_LOCKED, (byte) 1); + passenger.getMetadata().put(EntityData.RIDER_MAX_ROTATION, 90f); + passenger.getMetadata().put(EntityData.RIDER_MIN_ROTATION, !passengers.isEmpty() ? -90f : 0f); + } else { + passenger.getMetadata().remove(EntityData.RIDER_ROTATION_LOCKED); + passenger.getMetadata().remove(EntityData.RIDER_MAX_ROTATION); + passenger.getMetadata().remove(EntityData.RIDER_MIN_ROTATION); + } + + passenger.updateBedrockMetadata(session); + this.updateOffset(passenger, entity.getEntityType(), session, rider, true); + rider = false; + } + + entity.setPassengers(passengers); + + for (long passengerId : entity.getPassengers()) { + Entity passenger = session.getEntityCache().getEntityByJavaId(passengerId); + if (passenger == null) { + continue; + } + if (Arrays.stream(packet.getPassengerIds()).noneMatch(id -> id == passengerId)) { + SetEntityLinkPacket linkPacket = new SetEntityLinkPacket(); + linkPacket.setEntityLink(new EntityLink(entity.getGeyserId(), passenger.getGeyserId(), EntityLink.Type.REMOVE, false)); + session.sendUpstreamPacket(linkPacket); + passengers.remove(passenger.getEntityId()); + + this.updateOffset(passenger, entity.getEntityType(), session, false, false); + } + } + + if (entity.getEntityType() == EntityType.HORSE) { + entity.getMetadata().put(EntityData.RIDER_SEAT_POSITION, Vector3f.from(0.0f, 2.3200102f, -0.2f)); + entity.getMetadata().put(EntityData.RIDER_MAX_ROTATION, 181.0f); + + entity.updateBedrockMetadata(session); + } + } + + private void updateOffset(Entity passenger, EntityType mountType, GeyserSession session, boolean rider, boolean riding) { + // Without these, Bedrock players will find themselves in the floor when mounting + float yOffset = 0; + switch (mountType) { + case BOAT: + yOffset = passenger.getEntityType() == EntityType.PLAYER ? 1.02001f : -0.2f; + break; + case MINECART: + yOffset = passenger.getEntityType() == EntityType.PLAYER ? 1.02001f : 0f; + break; + case DONKEY: + yOffset = 2.1f; + break; + case HORSE: + case SKELETON_HORSE: + case ZOMBIE_HORSE: + case MULE: + yOffset = 2.3f; + break; + case LLAMA: + case TRADER_LLAMA: + yOffset = 2.5f; + break; + case PIG: + yOffset = 1.85001f; + break; + } + Vector3f offset = Vector3f.from(0f, yOffset, 0f); + if (rider) { + offset.add(Vector3f.from(0.2, 0, 0)); + } else { + offset.add(Vector3f.from(-0.6, 0, 0)); + } + passenger.getMetadata().getFlags().setFlag(EntityFlag.RIDING, riding); + if (riding) { + passenger.getMetadata().put(EntityData.RIDER_SEAT_POSITION, offset); + } + passenger.updateBedrockMetadata(session); + } +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaVehicleMoveTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaVehicleMoveTranslator.java new file mode 100644 index 000000000..1bcd99197 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaVehicleMoveTranslator.java @@ -0,0 +1,47 @@ +/* + * 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.packet.ingame.server.entity.ServerVehicleMovePacket; +import com.nukkitx.math.vector.Vector3f; +import org.geysermc.connector.entity.Entity; +import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.PacketTranslator; +import org.geysermc.connector.network.translators.Translator; + +@Translator(packet = ServerVehicleMovePacket.class) +public class JavaVehicleMoveTranslator extends PacketTranslator { + + @Override + public void translate(ServerVehicleMovePacket packet, GeyserSession session) { + Entity entity = session.getRidingVehicleEntity(); + if (entity == null) return; + + entity.moveAbsolute(session, Vector3f.from(packet.getX(), packet.getY(), packet.getZ()), packet.getYaw(), packet.getPitch(), false, false); + + } +} From 99f69b3a7d0a3cad0e345e489e5151c4aaffaaa0 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+DoctorMacc@users.noreply.github.com> Date: Sat, 23 May 2020 17:50:04 -0400 Subject: [PATCH 106/140] Rewrite Ping Passthrough (#468) * Fix ping passthrough on BungeeCord * Initial implementation of direct ping passthrough * Finished implementation of direct ping passthrough * Remove test for something else entirely * Fix standalone * Add config option for ping passthrough interval * Use GeyserPingInfo to reduce methods * Add querying; modify ping passthrough * Add separate config options for passthrough MOTD and player counts * Convert all plugin bootstraps to use internal ping events to that other plugins can handle ping modifications * Small changes * Fix invalid packet spawm * Add legacy ping passthrough option * Fix BungeeCord * Proper UUID for BungeeCord, thanks @theminecoder * Update config version and messages * Merge master... again * Add missing javadocs and minor changes Co-authored-by: James Harrison Co-authored-by: theminecoder Co-authored-by: Redned --- .../bukkit/GeyserBukkitConfiguration.java | 19 +- .../bukkit/GeyserBukkitPingPassthrough.java | 79 ++++++ .../platform/bukkit/GeyserBukkitPlugin.java | 14 + bootstrap/bungeecord/pom.xml | 4 +- .../bungeecord/GeyserBungeeConfiguration.java | 19 +- .../GeyserBungeePingPassthrough.java | 180 ++++++++++++ .../bungeecord/GeyserBungeePlugin.java | 14 + .../sponge/GeyserSpongeConfiguration.java | 19 +- .../sponge/GeyserSpongePingPassthrough.java | 99 +++++++ .../platform/sponge/GeyserSpongePlugin.java | 16 +- .../standalone/GeyserStandaloneBootstrap.java | 13 +- .../GeyserStandaloneConfiguration.java | 13 +- .../velocity/GeyserVelocityConfiguration.java | 13 +- .../GeyserVelocityPingPassthrough.java | 98 +++++++ .../velocity/GeyserVelocityPlugin.java | 13 + .../geysermc/common/ping/GeyserPingInfo.java | 48 ++++ .../connector/GeyserConfiguration.java | 10 +- .../geysermc/connector/GeyserConnector.java | 6 - .../connector/bootstrap/GeyserBootstrap.java | 8 + .../network/ConnectorServerEventHandler.java | 44 ++- .../connector/network/QueryPacketHandler.java | 268 ++++++++++++++++++ .../ping/GeyserLegacyPingPassthrough.java | 91 ++++++ .../ping/IGeyserPingPassthrough.java | 42 +++ .../thread/PingPassthroughThread.java | 65 ----- connector/src/main/resources/config.yml | 17 +- connector/src/main/resources/mappings | 2 +- 26 files changed, 1108 insertions(+), 106 deletions(-) create mode 100644 bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitPingPassthrough.java create mode 100644 bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/GeyserBungeePingPassthrough.java create mode 100644 bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/GeyserSpongePingPassthrough.java create mode 100644 bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityPingPassthrough.java create mode 100644 common/src/main/java/org/geysermc/common/ping/GeyserPingInfo.java create mode 100644 connector/src/main/java/org/geysermc/connector/network/QueryPacketHandler.java create mode 100644 connector/src/main/java/org/geysermc/connector/ping/GeyserLegacyPingPassthrough.java create mode 100644 connector/src/main/java/org/geysermc/connector/ping/IGeyserPingPassthrough.java delete mode 100644 connector/src/main/java/org/geysermc/connector/thread/PingPassthroughThread.java diff --git a/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitConfiguration.java b/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitConfiguration.java index 9ea2da2ba..df98b408d 100644 --- a/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitConfiguration.java +++ b/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitConfiguration.java @@ -92,8 +92,23 @@ public class GeyserBukkitConfiguration implements GeyserConfiguration { } @Override - public boolean isPingPassthrough() { - return config.getBoolean("ping-passthrough", false); + public boolean isPassthroughMotd() { + return config.getBoolean("passthrough-motd", false); + } + + @Override + public boolean isPassthroughPlayerCounts() { + return config.getBoolean("passthrough-player-counts", false); + } + + @Override + public boolean isLegacyPingPassthrough() { + return config.getBoolean("legacy-ping-passthrough", false); + } + + @Override + public int getPingPassthroughInterval() { + return config.getInt("ping-passthrough-interval", 3); } @Override diff --git a/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitPingPassthrough.java b/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitPingPassthrough.java new file mode 100644 index 000000000..812467be7 --- /dev/null +++ b/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitPingPassthrough.java @@ -0,0 +1,79 @@ +/* + * 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.platform.bukkit; + +import lombok.AllArgsConstructor; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.event.server.ServerListPingEvent; +import org.bukkit.util.CachedServerIcon; +import org.geysermc.common.ping.GeyserPingInfo; +import org.geysermc.connector.ping.IGeyserPingPassthrough; + +import java.net.InetAddress; +import java.util.Collections; +import java.util.Iterator; + +@AllArgsConstructor +public class GeyserBukkitPingPassthrough implements IGeyserPingPassthrough { + + private final GeyserBukkitLogger logger; + + @Override + public GeyserPingInfo getPingInformation() { + try { + ServerListPingEvent event = new GeyserPingEvent(InetAddress.getLocalHost(), Bukkit.getMotd(), Bukkit.getOnlinePlayers().size(), Bukkit.getMaxPlayers()); + Bukkit.getPluginManager().callEvent(event); + GeyserPingInfo geyserPingInfo = new GeyserPingInfo(event.getMotd(), event.getNumPlayers(), event.getMaxPlayers()); + Bukkit.getOnlinePlayers().forEach(player -> { + geyserPingInfo.addPlayer(player.getName()); + }); + return geyserPingInfo; + } catch (Exception e) { + logger.debug("Error while getting Bukkit ping passthrough: " + e.toString()); + return new GeyserPingInfo(null, 0, 0); + } + } + + // These methods are unimplemented on spigot api by default so we add stubs so plugins don't complain + private static class GeyserPingEvent extends ServerListPingEvent { + + public GeyserPingEvent(InetAddress address, String motd, int numPlayers, int maxPlayers) { + super(address, motd, numPlayers, maxPlayers); + } + + @Override + public void setServerIcon(CachedServerIcon icon) throws IllegalArgumentException, UnsupportedOperationException { + } + + @Override + public Iterator iterator() throws UnsupportedOperationException { + return Collections.EMPTY_LIST.iterator(); + } + } + +} diff --git a/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitPlugin.java b/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitPlugin.java index ad1f6194f..5f0e967a2 100644 --- a/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitPlugin.java +++ b/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitPlugin.java @@ -33,6 +33,8 @@ import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.bootstrap.GeyserBootstrap; import org.geysermc.connector.command.CommandManager; import org.geysermc.connector.network.translators.world.WorldManager; +import org.geysermc.connector.ping.GeyserLegacyPingPassthrough; +import org.geysermc.connector.ping.IGeyserPingPassthrough; import org.geysermc.platform.bukkit.command.GeyserBukkitCommandExecutor; import org.geysermc.platform.bukkit.command.GeyserBukkitCommandManager; import org.geysermc.platform.bukkit.world.GeyserBukkitBlockPlaceListener; @@ -46,6 +48,7 @@ public class GeyserBukkitPlugin extends JavaPlugin implements GeyserBootstrap { private GeyserBukkitCommandManager geyserCommandManager; private GeyserBukkitConfiguration geyserConfig; private GeyserBukkitLogger geyserLogger; + private IGeyserPingPassthrough geyserBukkitPingPassthrough; private GeyserBukkitBlockPlaceListener blockPlaceListener; private GeyserBukkitWorldManager geyserWorldManager; @@ -77,6 +80,12 @@ public class GeyserBukkitPlugin extends JavaPlugin implements GeyserBootstrap { this.connector = GeyserConnector.start(PlatformType.BUKKIT, this); + if (geyserConfig.isLegacyPingPassthrough()) { + this.geyserBukkitPingPassthrough = GeyserLegacyPingPassthrough.init(connector); + } else { + this.geyserBukkitPingPassthrough = new GeyserBukkitPingPassthrough(geyserLogger); + } + this.geyserCommandManager = new GeyserBukkitCommandManager(this, connector); boolean isViaVersion = false; @@ -122,6 +131,11 @@ public class GeyserBukkitPlugin extends JavaPlugin implements GeyserBootstrap { return this.geyserCommandManager; } + @Override + public IGeyserPingPassthrough getGeyserPingPassthrough() { + return geyserBukkitPingPassthrough; + } + @Override public WorldManager getWorldManager() { return this.geyserWorldManager; diff --git a/bootstrap/bungeecord/pom.xml b/bootstrap/bungeecord/pom.xml index b9f069165..dd66db322 100644 --- a/bootstrap/bungeecord/pom.xml +++ b/bootstrap/bungeecord/pom.xml @@ -20,7 +20,7 @@ net.md-5 bungeecord-api - 1.14-SNAPSHOT + 1.15-SNAPSHOT provided @@ -80,4 +80,4 @@ - \ No newline at end of file + diff --git a/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/GeyserBungeeConfiguration.java b/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/GeyserBungeeConfiguration.java index cb9d1fbff..d983aec1c 100644 --- a/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/GeyserBungeeConfiguration.java +++ b/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/GeyserBungeeConfiguration.java @@ -91,8 +91,23 @@ public class GeyserBungeeConfiguration implements GeyserConfiguration { } @Override - public boolean isPingPassthrough() { - return config.getBoolean("ping-passthrough", false); + public boolean isPassthroughMotd() { + return config.getBoolean("passthrough-motd", false); + } + + @Override + public boolean isPassthroughPlayerCounts() { + return config.getBoolean("passthrough-player-counts", false); + } + + @Override + public boolean isLegacyPingPassthrough() { + return config.getBoolean("legacy-ping-passthrough", false); + } + + @Override + public int getPingPassthroughInterval() { + return config.getInt("ping-passthrough-interval", 3); } @Override diff --git a/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/GeyserBungeePingPassthrough.java b/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/GeyserBungeePingPassthrough.java new file mode 100644 index 000000000..c7f8f2762 --- /dev/null +++ b/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/GeyserBungeePingPassthrough.java @@ -0,0 +1,180 @@ +/* + * 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.platform.bungeecord; + +import lombok.AllArgsConstructor; +import net.md_5.bungee.api.ProxyServer; +import net.md_5.bungee.api.ServerPing; +import net.md_5.bungee.api.chat.BaseComponent; +import net.md_5.bungee.api.config.ListenerInfo; +import net.md_5.bungee.api.connection.PendingConnection; +import net.md_5.bungee.api.event.ProxyPingEvent; +import net.md_5.bungee.api.plugin.Listener; +import net.md_5.bungee.protocol.ProtocolConstants; +import org.geysermc.common.ping.GeyserPingInfo; +import org.geysermc.connector.ping.IGeyserPingPassthrough; + +import java.net.Inet4Address; +import java.net.InetSocketAddress; +import java.net.SocketAddress; +import java.util.Arrays; +import java.util.UUID; +import java.util.concurrent.CompletableFuture; + +@AllArgsConstructor +public class GeyserBungeePingPassthrough implements IGeyserPingPassthrough, Listener { + + private static final GeyserPendingConnection PENDING_CONNECTION = new GeyserPendingConnection(); + + private final ProxyServer proxyServer; + + @Override + public GeyserPingInfo getPingInformation() { + CompletableFuture future = new CompletableFuture<>(); + proxyServer.getPluginManager().callEvent(new ProxyPingEvent(PENDING_CONNECTION, getPingInfo(), (event, throwable) -> { + if (throwable != null) future.completeExceptionally(throwable); + else future.complete(event); + })); + ProxyPingEvent event = future.join(); + GeyserPingInfo geyserPingInfo = new GeyserPingInfo( + event.getResponse().getDescription(), + event.getResponse().getPlayers().getOnline(), + event.getResponse().getPlayers().getMax() + ); + if (event.getResponse().getPlayers().getSample() != null) { + Arrays.stream(event.getResponse().getPlayers().getSample()).forEach(proxiedPlayer -> { + geyserPingInfo.addPlayer(proxiedPlayer.getName()); + }); + } + return geyserPingInfo; + } + + // This is static so pending connection can use it + private static ListenerInfo getDefaultListener() { + return ProxyServer.getInstance().getConfig().getListeners().iterator().next(); + } + + private ServerPing getPingInfo() { + return new ServerPing( + new ServerPing.Protocol(proxyServer.getName() + " " + proxyServer.getGameVersion(), ProtocolConstants.SUPPORTED_VERSION_IDS.get(ProtocolConstants.SUPPORTED_VERSION_IDS.size() - 1)), + new ServerPing.Players(getDefaultListener().getMaxPlayers(), proxyServer.getOnlineCount(), null), + getDefaultListener().getMotd(), proxyServer.getConfig().getFaviconObject() + ); + } + + private static class GeyserPendingConnection implements PendingConnection { + + private static final UUID FAKE_UUID = UUID.nameUUIDFromBytes("geyser!internal".getBytes()); + private static final InetSocketAddress FAKE_REMOTE = new InetSocketAddress(Inet4Address.getLoopbackAddress(), 69); + + @Override + public String getName() { + throw new UnsupportedOperationException(); + } + + @Override + public int getVersion() { + return ProtocolConstants.SUPPORTED_VERSION_IDS.get(ProtocolConstants.SUPPORTED_VERSION_IDS.size() - 1); + } + + @Override + public InetSocketAddress getVirtualHost() { + return null; + } + + @Override + public ListenerInfo getListener() { + return getDefaultListener(); + } + + @Override + public String getUUID() { + return FAKE_UUID.toString(); + } + + @Override + public UUID getUniqueId() { + return FAKE_UUID; + } + + @Override + public void setUniqueId(UUID uuid) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean isOnlineMode() { + return true; + } + + @Override + public void setOnlineMode(boolean b) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean isLegacy() { + return false; + } + + @Override + public InetSocketAddress getAddress() { + return FAKE_REMOTE; + } + + @Override + public SocketAddress getSocketAddress() { + return getAddress(); + } + + @Override + public void disconnect(String s) { + throw new UnsupportedOperationException(); + } + + @Override + public void disconnect(BaseComponent... baseComponents) { + throw new UnsupportedOperationException(); + } + + @Override + public void disconnect(BaseComponent baseComponent) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean isConnected() { + return false; + } + + @Override + public Unsafe unsafe() { + throw new UnsupportedOperationException(); + } + } + +} diff --git a/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/GeyserBungeePlugin.java b/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/GeyserBungeePlugin.java index 270fbd1ce..525b9b6db 100644 --- a/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/GeyserBungeePlugin.java +++ b/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/GeyserBungeePlugin.java @@ -35,6 +35,8 @@ import org.geysermc.connector.GeyserConfiguration; import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.bootstrap.GeyserBootstrap; import org.geysermc.connector.command.CommandManager; +import org.geysermc.connector.ping.GeyserLegacyPingPassthrough; +import org.geysermc.connector.ping.IGeyserPingPassthrough; import org.geysermc.platform.bungeecord.command.GeyserBungeeCommandExecutor; import org.geysermc.platform.bungeecord.command.GeyserBungeeCommandManager; @@ -51,6 +53,7 @@ public class GeyserBungeePlugin extends Plugin implements GeyserBootstrap { private GeyserBungeeCommandManager geyserCommandManager; private GeyserBungeeConfiguration geyserConfig; private GeyserBungeeLogger geyserLogger; + private IGeyserPingPassthrough geyserBungeePingPassthrough; private GeyserConnector connector; @@ -125,6 +128,12 @@ public class GeyserBungeePlugin extends Plugin implements GeyserBootstrap { this.geyserCommandManager = new GeyserBungeeCommandManager(connector); + if (geyserConfig.isLegacyPingPassthrough()) { + this.geyserBungeePingPassthrough = GeyserLegacyPingPassthrough.init(connector); + } else { + this.geyserBungeePingPassthrough = new GeyserBungeePingPassthrough(getProxy()); + } + this.getProxy().getPluginManager().registerCommand(this, new GeyserBungeeCommandExecutor(connector)); } @@ -147,4 +156,9 @@ public class GeyserBungeePlugin extends Plugin implements GeyserBootstrap { public CommandManager getGeyserCommandManager() { return this.geyserCommandManager; } + + @Override + public IGeyserPingPassthrough getGeyserPingPassthrough() { + return geyserBungeePingPassthrough; + } } diff --git a/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/GeyserSpongeConfiguration.java b/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/GeyserSpongeConfiguration.java index c84f2dfcb..fc1484708 100644 --- a/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/GeyserSpongeConfiguration.java +++ b/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/GeyserSpongeConfiguration.java @@ -85,8 +85,23 @@ public class GeyserSpongeConfiguration implements GeyserConfiguration { } @Override - public boolean isPingPassthrough() { - return node.getNode("ping-passthrough").getBoolean(false); + public boolean isPassthroughMotd() { + return node.getNode("passthrough-motd").getBoolean(false); + } + + @Override + public boolean isPassthroughPlayerCounts() { + return node.getNode("passthrough-player-counts").getBoolean(false); + } + + @Override + public boolean isLegacyPingPassthrough() { + return node.getNode("legacy-ping-passthrough").getBoolean(false); + } + + @Override + public int getPingPassthroughInterval() { + return node.getNode("ping-passthrough-interval").getInt(3); } @Override diff --git a/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/GeyserSpongePingPassthrough.java b/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/GeyserSpongePingPassthrough.java new file mode 100644 index 000000000..31b6dc7fb --- /dev/null +++ b/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/GeyserSpongePingPassthrough.java @@ -0,0 +1,99 @@ +/* + * 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.platform.sponge; + +import org.geysermc.common.ping.GeyserPingInfo; +import org.geysermc.connector.ping.IGeyserPingPassthrough; +import org.spongepowered.api.MinecraftVersion; +import org.spongepowered.api.Sponge; +import org.spongepowered.api.event.SpongeEventFactory; +import org.spongepowered.api.event.cause.Cause; +import org.spongepowered.api.event.cause.EventContext; +import org.spongepowered.api.event.server.ClientPingServerEvent; +import org.spongepowered.api.network.status.StatusClient; + +import java.lang.reflect.Method; +import java.net.Inet4Address; +import java.net.InetSocketAddress; +import java.util.Optional; + +public class GeyserSpongePingPassthrough implements IGeyserPingPassthrough { + + private static final GeyserStatusClient STATUS_CLIENT = new GeyserStatusClient(); + private static final Cause CAUSE = Cause.of(EventContext.empty(), Sponge.getServer()); + + private static Method SpongeStatusResponse_create; + + @SuppressWarnings({"unchecked", "rawtypes"}) + @Override + public GeyserPingInfo getPingInformation() { + // come on Sponge, this is in commons, why not expose it :( + ClientPingServerEvent event; + try { + if(SpongeStatusResponse_create == null) { + Class SpongeStatusResponse = Class.forName("org.spongepowered.common.network.status.SpongeStatusResponse"); + Class MinecraftServer = Class.forName("net.minecraft.server.MinecraftServer"); + SpongeStatusResponse_create = SpongeStatusResponse.getDeclaredMethod("create", MinecraftServer); + } + + Object response = SpongeStatusResponse_create.invoke(null, Sponge.getServer()); + event = SpongeEventFactory.createClientPingServerEvent(CAUSE, STATUS_CLIENT, (ClientPingServerEvent.Response) response); + } catch (ReflectiveOperationException e) { + throw new RuntimeException(e); + } + Sponge.getEventManager().post(event); + GeyserPingInfo geyserPingInfo = new GeyserPingInfo( + event.getResponse().getDescription().toPlain(), + event.getResponse().getPlayers().orElseThrow(IllegalStateException::new).getOnline(), + event.getResponse().getPlayers().orElseThrow(IllegalStateException::new).getMax()); + event.getResponse().getPlayers().get().getProfiles().forEach(player -> { + geyserPingInfo.addPlayer(player.getName().orElseThrow(IllegalStateException::new)); + }); + return geyserPingInfo; + } + + @SuppressWarnings("NullableProblems") + private static class GeyserStatusClient implements StatusClient { + + private static final InetSocketAddress FAKE_REMOTE = new InetSocketAddress(Inet4Address.getLoopbackAddress(), 69); + + @Override + public InetSocketAddress getAddress() { + return FAKE_REMOTE; + } + + @Override + public MinecraftVersion getVersion() { + return Sponge.getPlatform().getMinecraftVersion(); + } + + @Override + public Optional getVirtualHost() { + return Optional.empty(); + } + } +} diff --git a/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/GeyserSpongePlugin.java b/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/GeyserSpongePlugin.java index 04a80adfc..d226add77 100644 --- a/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/GeyserSpongePlugin.java +++ b/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/GeyserSpongePlugin.java @@ -34,6 +34,8 @@ import org.geysermc.connector.GeyserConfiguration; import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.bootstrap.GeyserBootstrap; import org.geysermc.connector.command.CommandManager; +import org.geysermc.connector.ping.GeyserLegacyPingPassthrough; +import org.geysermc.connector.ping.IGeyserPingPassthrough; import org.geysermc.connector.utils.FileUtils; import org.geysermc.platform.sponge.command.GeyserSpongeCommandExecutor; import org.geysermc.platform.sponge.command.GeyserSpongeCommandManager; @@ -63,6 +65,7 @@ public class GeyserSpongePlugin implements GeyserBootstrap { private GeyserSpongeCommandManager geyserCommandManager; private GeyserSpongeConfiguration geyserConfig; private GeyserSpongeLogger geyserLogger; + private IGeyserPingPassthrough geyserSpongePingPassthrough; private GeyserConnector connector; @@ -108,8 +111,14 @@ public class GeyserSpongePlugin implements GeyserBootstrap { this.geyserLogger = new GeyserSpongeLogger(logger, geyserConfig.isDebugMode()); GeyserConfiguration.checkGeyserConfiguration(geyserConfig, geyserLogger); this.connector = GeyserConnector.start(PlatformType.SPONGE, this); - this.geyserCommandManager = new GeyserSpongeCommandManager(Sponge.getCommandManager(), connector); + if (geyserConfig.isLegacyPingPassthrough()) { + this.geyserSpongePingPassthrough = GeyserLegacyPingPassthrough.init(connector); + } else { + this.geyserSpongePingPassthrough = new GeyserSpongePingPassthrough(); + } + + this.geyserCommandManager = new GeyserSpongeCommandManager(Sponge.getCommandManager(), connector); Sponge.getCommandManager().register(this, new GeyserSpongeCommandExecutor(connector), "geyser"); } @@ -133,6 +142,11 @@ public class GeyserSpongePlugin implements GeyserBootstrap { return this.geyserCommandManager; } + @Override + public IGeyserPingPassthrough getGeyserPingPassthrough() { + return geyserSpongePingPassthrough; + } + @Listener public void onServerStart(GameStartedServerEvent event) { onEnable(); diff --git a/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/GeyserStandaloneBootstrap.java b/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/GeyserStandaloneBootstrap.java index 0916f2129..aa0d2392e 100644 --- a/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/GeyserStandaloneBootstrap.java +++ b/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/GeyserStandaloneBootstrap.java @@ -26,10 +26,12 @@ package org.geysermc.platform.standalone; import org.geysermc.common.PlatformType; +import org.geysermc.connector.ping.GeyserLegacyPingPassthrough; import org.geysermc.connector.GeyserConfiguration; import org.geysermc.connector.bootstrap.GeyserBootstrap; import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.command.CommandManager; +import org.geysermc.connector.ping.IGeyserPingPassthrough; import org.geysermc.connector.utils.FileUtils; import org.geysermc.platform.standalone.command.GeyserCommandManager; @@ -40,8 +42,9 @@ import java.util.UUID; public class GeyserStandaloneBootstrap implements GeyserBootstrap { private GeyserCommandManager geyserCommandManager; - private GeyserConfiguration geyserConfig; + private GeyserStandaloneConfiguration geyserConfig; private GeyserStandaloneLogger geyserLogger; + private IGeyserPingPassthrough geyserPingPassthrough; private GeyserConnector connector; @@ -66,6 +69,9 @@ public class GeyserStandaloneBootstrap implements GeyserBootstrap { connector = GeyserConnector.start(PlatformType.STANDALONE, this); geyserCommandManager = new GeyserCommandManager(connector); + + geyserPingPassthrough = GeyserLegacyPingPassthrough.init(connector); + geyserLogger.start(); } @@ -89,4 +95,9 @@ public class GeyserStandaloneBootstrap implements GeyserBootstrap { public CommandManager getGeyserCommandManager() { return geyserCommandManager; } + + @Override + public IGeyserPingPassthrough getGeyserPingPassthrough() { + return geyserPingPassthrough; + } } diff --git a/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/GeyserStandaloneConfiguration.java b/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/GeyserStandaloneConfiguration.java index 8c8ce3764..bd0292040 100644 --- a/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/GeyserStandaloneConfiguration.java +++ b/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/GeyserStandaloneConfiguration.java @@ -50,8 +50,17 @@ public class GeyserStandaloneConfiguration implements GeyserConfiguration { @JsonProperty("command-suggestions") private boolean isCommandSuggestions; - @JsonProperty("ping-passthrough") - private boolean pingPassthrough; + @JsonProperty("passthrough-motd") + private boolean isPassthroughMotd; + + @JsonProperty("passthrough-player-counts") + private boolean isPassthroughPlayerCounts; + + @JsonProperty("legacy-ping-passthrough") + private boolean isLegacyPingPassthrough; + + @JsonProperty("ping-passthrough-interval") + private int pingPassthroughInterval; @JsonProperty("max-players") private int maxPlayers; diff --git a/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityConfiguration.java b/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityConfiguration.java index 685c21a39..aef0edaa5 100644 --- a/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityConfiguration.java +++ b/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityConfiguration.java @@ -55,8 +55,17 @@ public class GeyserVelocityConfiguration implements GeyserConfiguration { @JsonProperty("command-suggestions") private boolean commandSuggestions; - @JsonProperty("ping-passthrough") - private boolean pingPassthrough; + @JsonProperty("passthrough-motd") + private boolean isPassthroughMotd; + + @JsonProperty("passthrough-player-counts") + private boolean isPassthroughPlayerCounts; + + @JsonProperty("legacy-ping-passthrough") + private boolean isLegacyPingPassthrough; + + @JsonProperty("ping-passthrough-interval") + private int pingPassthroughInterval; @JsonProperty("max-players") private int maxPlayers; diff --git a/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityPingPassthrough.java b/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityPingPassthrough.java new file mode 100644 index 000000000..01be949b8 --- /dev/null +++ b/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityPingPassthrough.java @@ -0,0 +1,98 @@ +/* + * 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.platform.velocity; + +import com.velocitypowered.api.event.proxy.ProxyPingEvent; +import com.velocitypowered.api.network.ProtocolVersion; +import com.velocitypowered.api.proxy.InboundConnection; +import com.velocitypowered.api.proxy.ProxyServer; +import com.velocitypowered.api.proxy.server.ServerPing; +import lombok.AllArgsConstructor; +import net.kyori.text.TextComponent; +import net.kyori.text.serializer.legacy.LegacyComponentSerializer; +import org.geysermc.common.ping.GeyserPingInfo; +import org.geysermc.connector.ping.IGeyserPingPassthrough; + +import java.net.Inet4Address; +import java.net.InetSocketAddress; +import java.util.Optional; +import java.util.concurrent.ExecutionException; + +@AllArgsConstructor +public class GeyserVelocityPingPassthrough implements IGeyserPingPassthrough { + + private static final GeyserInboundConnection FAKE_INBOUND_CONNECTION = new GeyserInboundConnection(); + + private final ProxyServer server; + + @Override + public GeyserPingInfo getPingInformation() { + ProxyPingEvent event; + try { + event = server.getEventManager().fire(new ProxyPingEvent(FAKE_INBOUND_CONNECTION, ServerPing.builder() + .description(server.getConfiguration().getMotdComponent()).onlinePlayers(server.getPlayerCount()) + .maximumPlayers(server.getConfiguration().getShowMaxPlayers()).build())).get(); + } catch (ExecutionException | InterruptedException e) { + throw new RuntimeException(e); + } + GeyserPingInfo geyserPingInfo = new GeyserPingInfo( + LegacyComponentSerializer.INSTANCE.serialize(event.getPing().getDescription(), '§'), + event.getPing().getPlayers().orElseThrow(IllegalStateException::new).getOnline(), + event.getPing().getPlayers().orElseThrow(IllegalStateException::new).getMax() + ); + event.getPing().getPlayers().get().getSample().forEach(player -> { + geyserPingInfo.addPlayer(player.getName()); + }); + return geyserPingInfo; + } + + private static class GeyserInboundConnection implements InboundConnection { + + private static final InetSocketAddress FAKE_REMOTE = new InetSocketAddress(Inet4Address.getLoopbackAddress(), 69); + + @Override + public InetSocketAddress getRemoteAddress() { + return FAKE_REMOTE; + } + + @Override + public Optional getVirtualHost() { + return Optional.empty(); + } + + @Override + public boolean isActive() { + return false; + } + + @Override + public ProtocolVersion getProtocolVersion() { + return ProtocolVersion.MAXIMUM_VERSION; + } + } + +} diff --git a/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityPlugin.java b/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityPlugin.java index 9ad8ea9ab..e7b44da53 100644 --- a/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityPlugin.java +++ b/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityPlugin.java @@ -38,6 +38,8 @@ import org.geysermc.common.PlatformType; import org.geysermc.connector.GeyserConfiguration; import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.bootstrap.GeyserBootstrap; +import org.geysermc.connector.ping.GeyserLegacyPingPassthrough; +import org.geysermc.connector.ping.IGeyserPingPassthrough; import org.geysermc.connector.utils.FileUtils; import org.geysermc.platform.velocity.command.GeyserVelocityCommandExecutor; import org.geysermc.platform.velocity.command.GeyserVelocityCommandManager; @@ -63,6 +65,7 @@ public class GeyserVelocityPlugin implements GeyserBootstrap { private GeyserVelocityCommandManager geyserCommandManager; private GeyserVelocityConfiguration geyserConfig; private GeyserVelocityLogger geyserLogger; + private IGeyserPingPassthrough geyserPingPassthrough; private GeyserConnector connector; @@ -99,6 +102,11 @@ public class GeyserVelocityPlugin implements GeyserBootstrap { this.geyserCommandManager = new GeyserVelocityCommandManager(connector); this.commandManager.register(new GeyserVelocityCommandExecutor(connector), "geyser"); + if (geyserConfig.isLegacyPingPassthrough()) { + this.geyserPingPassthrough = GeyserLegacyPingPassthrough.init(connector); + } else { + this.geyserPingPassthrough = new GeyserVelocityPingPassthrough(proxyServer); + } } @Override @@ -121,6 +129,11 @@ public class GeyserVelocityPlugin implements GeyserBootstrap { return this.geyserCommandManager; } + @Override + public IGeyserPingPassthrough getGeyserPingPassthrough() { + return geyserPingPassthrough; + } + @Subscribe public void onInit(ProxyInitializeEvent event) { onEnable(); diff --git a/common/src/main/java/org/geysermc/common/ping/GeyserPingInfo.java b/common/src/main/java/org/geysermc/common/ping/GeyserPingInfo.java new file mode 100644 index 000000000..40ef6da62 --- /dev/null +++ b/common/src/main/java/org/geysermc/common/ping/GeyserPingInfo.java @@ -0,0 +1,48 @@ +/* + * 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.common.ping; + +import lombok.Data; +import lombok.Getter; + +import java.util.ArrayList; +import java.util.Collection; + +@Data +public class GeyserPingInfo { + + public final String motd; + public final int currentPlayerCount; + public final int maxPlayerCount; + + @Getter + private Collection players = new ArrayList<>(); + + public void addPlayer(String username) { + players.add(username); + } +} diff --git a/connector/src/main/java/org/geysermc/connector/GeyserConfiguration.java b/connector/src/main/java/org/geysermc/connector/GeyserConfiguration.java index 34edd8e08..8a39323b6 100644 --- a/connector/src/main/java/org/geysermc/connector/GeyserConfiguration.java +++ b/connector/src/main/java/org/geysermc/connector/GeyserConfiguration.java @@ -32,7 +32,7 @@ import java.util.Map; public interface GeyserConfiguration { // Modify this when you update the config - int CURRENT_CONFIG_VERSION = 2; + int CURRENT_CONFIG_VERSION = 3; IBedrockConfiguration getBedrock(); @@ -42,7 +42,13 @@ public interface GeyserConfiguration { boolean isCommandSuggestions(); - boolean isPingPassthrough(); + boolean isPassthroughMotd(); + + boolean isPassthroughPlayerCounts(); + + boolean isLegacyPingPassthrough(); + + int getPingPassthroughInterval(); int getMaxPlayers(); diff --git a/connector/src/main/java/org/geysermc/connector/GeyserConnector.java b/connector/src/main/java/org/geysermc/connector/GeyserConnector.java index 75c17b29b..43b100533 100644 --- a/connector/src/main/java/org/geysermc/connector/GeyserConnector.java +++ b/connector/src/main/java/org/geysermc/connector/GeyserConnector.java @@ -39,7 +39,6 @@ import org.geysermc.connector.network.remote.RemoteServer; import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.Translators; import org.geysermc.connector.network.translators.world.WorldManager; -import org.geysermc.connector.thread.PingPassthroughThread; import org.geysermc.connector.utils.DimensionUtils; import org.geysermc.connector.utils.DockerCheck; import org.geysermc.connector.utils.Toolbox; @@ -71,7 +70,6 @@ public class GeyserConnector { private boolean shuttingDown = false; private final ScheduledExecutorService generalThreadPool; - private PingPassthroughThread passthroughThread; private BedrockServer bedrockServer; private PlatformType platformType; @@ -111,10 +109,6 @@ public class GeyserConnector { remoteServer = new RemoteServer(config.getRemote().getAddress(), config.getRemote().getPort()); authType = AuthType.getByName(config.getRemote().getAuthType()); - passthroughThread = new PingPassthroughThread(this); - if (config.isPingPassthrough()) - generalThreadPool.scheduleAtFixedRate(passthroughThread, 1, 1, TimeUnit.SECONDS); - if (config.isAboveBedrockNetherBuilding()) DimensionUtils.changeBedrockNetherId(); // Apply End dimension ID workaround to Nether diff --git a/connector/src/main/java/org/geysermc/connector/bootstrap/GeyserBootstrap.java b/connector/src/main/java/org/geysermc/connector/bootstrap/GeyserBootstrap.java index 24b338c87..24ce81cfd 100644 --- a/connector/src/main/java/org/geysermc/connector/bootstrap/GeyserBootstrap.java +++ b/connector/src/main/java/org/geysermc/connector/bootstrap/GeyserBootstrap.java @@ -26,6 +26,7 @@ package org.geysermc.connector.bootstrap; +import org.geysermc.connector.ping.IGeyserPingPassthrough; import org.geysermc.connector.GeyserConfiguration; import org.geysermc.connector.GeyserLogger; import org.geysermc.connector.command.CommandManager; @@ -67,6 +68,13 @@ public interface GeyserBootstrap { */ CommandManager getGeyserCommandManager(); + /** + * Returns the current PingPassthrough manager + * + * @return The current PingPassthrough manager + */ + IGeyserPingPassthrough getGeyserPingPassthrough(); + /** * Returns the current WorldManager * diff --git a/connector/src/main/java/org/geysermc/connector/network/ConnectorServerEventHandler.java b/connector/src/main/java/org/geysermc/connector/network/ConnectorServerEventHandler.java index 8810cffb4..29ba15678 100644 --- a/connector/src/main/java/org/geysermc/connector/network/ConnectorServerEventHandler.java +++ b/connector/src/main/java/org/geysermc/connector/network/ConnectorServerEventHandler.java @@ -25,11 +25,12 @@ package org.geysermc.connector.network; -import com.github.steveice10.mc.protocol.data.status.ServerStatusInfo; -import com.nukkitx.protocol.bedrock.BedrockPong; -import com.nukkitx.protocol.bedrock.BedrockServerEventHandler; -import com.nukkitx.protocol.bedrock.BedrockServerSession; - +import com.github.steveice10.mc.protocol.data.message.Message; +import com.nukkitx.protocol.bedrock.*; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.socket.DatagramPacket; +import org.geysermc.common.ping.GeyserPingInfo; +import org.geysermc.connector.ping.IGeyserPingPassthrough; import org.geysermc.connector.GeyserConfiguration; import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.network.session.GeyserSession; @@ -39,7 +40,7 @@ import java.net.InetSocketAddress; public class ConnectorServerEventHandler implements BedrockServerEventHandler { - private GeyserConnector connector; + private final GeyserConnector connector; public ConnectorServerEventHandler(GeyserConnector connector) { this.connector = connector; @@ -56,29 +57,39 @@ public class ConnectorServerEventHandler implements BedrockServerEventHandler { connector.getLogger().debug(inetSocketAddress + " has pinged you!"); GeyserConfiguration config = connector.getConfig(); - ServerStatusInfo serverInfo = connector.getPassthroughThread().getInfo(); + + GeyserPingInfo pingInfo = null; + if (config.isPassthroughMotd() || config.isPassthroughPlayerCounts()) { + IGeyserPingPassthrough pingPassthrough = connector.getBootstrap().getGeyserPingPassthrough(); + pingInfo = pingPassthrough.getPingInformation(); + } BedrockPong pong = new BedrockPong(); pong.setEdition("MCPE"); pong.setGameType("Default"); pong.setNintendoLimited(false); pong.setProtocolVersion(GeyserConnector.BEDROCK_PACKET_CODEC.getProtocolVersion()); - pong.setVersion(GeyserConnector.BEDROCK_PACKET_CODEC.getMinecraftVersion()); + pong.setVersion(null); // Server tries to connect either way and it looks better pong.setIpv4Port(config.getBedrock().getPort()); - if (connector.getConfig().isPingPassthrough() && serverInfo != null) { - String[] motd = MessageUtils.getBedrockMessage(serverInfo.getDescription()).split("\n"); + + if (config.isPassthroughMotd() && pingInfo != null && pingInfo.motd != null) { + String[] motd = MessageUtils.getBedrockMessage(Message.fromString(pingInfo.motd)).split("\n"); String mainMotd = motd[0]; // First line of the motd. String subMotd = (motd.length != 1) ? motd[1] : ""; // Second line of the motd if present, otherwise blank. pong.setMotd(mainMotd.trim()); pong.setSubMotd(subMotd.trim()); // Trimmed to shift it to the left, prevents the universe from collapsing on us just because we went 2 characters over the text box's limit. - pong.setPlayerCount(serverInfo.getPlayerInfo().getOnlinePlayers()); - pong.setMaximumPlayerCount(serverInfo.getPlayerInfo().getMaxPlayers()); + } else { + pong.setMotd(config.getBedrock().getMotd1()); + pong.setSubMotd(config.getBedrock().getMotd2()); + } + + if (config.isPassthroughPlayerCounts() && pingInfo != null) { + pong.setPlayerCount(pingInfo.currentPlayerCount); + pong.setMaximumPlayerCount(pingInfo.maxPlayerCount); } else { pong.setPlayerCount(connector.getPlayers().size()); pong.setMaximumPlayerCount(config.getMaxPlayers()); - pong.setMotd(config.getBedrock().getMotd1()); - pong.setMotd(config.getBedrock().getMotd2()); } //Bedrock will not even attempt a connection if the client thinks the server is full @@ -105,4 +116,9 @@ public class ConnectorServerEventHandler implements BedrockServerEventHandler { }); bedrockServerSession.setPacketCodec(GeyserConnector.BEDROCK_PACKET_CODEC); } + + @Override + public void onUnhandledDatagram(ChannelHandlerContext ctx, DatagramPacket packet) { + new QueryPacketHandler(connector, packet.sender(), packet.content()); + } } \ No newline at end of file diff --git a/connector/src/main/java/org/geysermc/connector/network/QueryPacketHandler.java b/connector/src/main/java/org/geysermc/connector/network/QueryPacketHandler.java new file mode 100644 index 000000000..061e0f86b --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/QueryPacketHandler.java @@ -0,0 +1,268 @@ +/* + * 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; + +import com.github.steveice10.mc.protocol.data.message.Message; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufAllocator; +import org.geysermc.common.ping.GeyserPingInfo; +import org.geysermc.connector.GeyserConnector; +import org.geysermc.connector.utils.MessageUtils; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.nio.ByteBuffer; +import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import java.util.Random; +import java.util.concurrent.ThreadLocalRandom; + +public class QueryPacketHandler { + + public static final byte HANDSHAKE = 0x09; + public static final byte STATISTICS = 0x00; + + private GeyserConnector connector; + private InetSocketAddress sender; + private byte type; + private int sessionId; + private byte[] token; + + /** + * The Query packet handler instance + * @param connector Geyser Connector + * @param sender The Sender IP/Port for the Query + * @param buffer The Query data + */ + public QueryPacketHandler(GeyserConnector connector, InetSocketAddress sender, ByteBuf buffer) { + if(!isQueryPacket(buffer)) + return; + + this.connector = connector; + this.sender = sender; + this.type = buffer.readByte(); + this.sessionId = buffer.readInt(); + + regenerateToken(); + handle(); + } + + /** + * Checks the packet is in fact a query packet + * @param buffer Query data + * @return if the packet is a query packet + */ + private boolean isQueryPacket(ByteBuf buffer) { + return (buffer.readableBytes() >= 2) ? buffer.readUnsignedShort() == 65277 : false; + } + + /** + * Handles the query + */ + private void handle() { + switch (type) { + case HANDSHAKE: + sendToken(); + case STATISTICS: + sendQueryData(); + } + } + + /** + * Sends the token to the sender + */ + private void sendToken() { + ByteBuf reply = ByteBufAllocator.DEFAULT.ioBuffer(10); + reply.writeByte(HANDSHAKE); + reply.writeInt(sessionId); + reply.writeBytes(getTokenString(this.token, this.sender.getAddress())); + reply.writeByte(0); + + sendPacket(reply); + } + + /** + * Sends the query data to the sender + */ + private void sendQueryData() { + ByteBuf reply = ByteBufAllocator.DEFAULT.ioBuffer(64); + reply.writeByte(STATISTICS); + reply.writeInt(sessionId); + + // Game Info + reply.writeBytes(getGameData()); + + // Players + reply.writeBytes(getPlayers()); + + sendPacket(reply); + } + + /** + * Gets the game data for the query + * @return the game data for the query + */ + private byte[] getGameData() { + ByteArrayOutputStream query = new ByteArrayOutputStream(); + + GeyserPingInfo pingInfo = null; + String motd; + String currentPlayerCount; + String maxPlayerCount; + + if (connector.getConfig().isPassthroughMotd() || connector.getConfig().isPassthroughPlayerCounts()) { + pingInfo = connector.getBootstrap().getGeyserPingPassthrough().getPingInformation(); + } + + if (connector.getConfig().isPassthroughMotd() && pingInfo != null) { + String[] javaMotd = MessageUtils.getBedrockMessage(Message.fromString(pingInfo.motd)).split("\n"); + motd = javaMotd[0].trim(); // First line of the motd. + } else { + motd = connector.getConfig().getBedrock().getMotd1(); + } + + // If passthrough player counts is enabled lets get players from the server + if (connector.getConfig().isPassthroughPlayerCounts() && pingInfo != null) { + currentPlayerCount = String.valueOf(pingInfo.currentPlayerCount); + maxPlayerCount = String.valueOf(pingInfo.maxPlayerCount); + } else { + currentPlayerCount = String.valueOf(connector.getPlayers().size()); + maxPlayerCount = String.valueOf(connector.getConfig().getMaxPlayers()); + } + + // Create a hashmap of all game data needed in the query + Map gameData = new HashMap(); + gameData.put("hostname", motd); + gameData.put("gametype", "SMP"); + gameData.put("game_id", "MINECRAFT"); + gameData.put("version", GeyserConnector.BEDROCK_PACKET_CODEC.getMinecraftVersion()); + gameData.put("plugins", ""); + gameData.put("map", GeyserConnector.NAME); + gameData.put("numplayers", currentPlayerCount); + gameData.put("maxplayers", maxPlayerCount); + gameData.put("hostport", String.valueOf(connector.getConfig().getBedrock().getPort())); + gameData.put("hostip", connector.getConfig().getBedrock().getAddress()); + + try { + // Blank Buffer Bytes + query.write("GeyserMC".getBytes()); + query.write((byte) 0x00); + query.write((byte) 128); + query.write((byte) 0x00); + + // Fills the game data + for(Map.Entry entry : gameData.entrySet()) { + query.write(entry.getKey().getBytes()); + query.write((byte) 0x00); + query.write(entry.getValue().getBytes()); + query.write((byte) 0x00); + } + + // Final byte to show the end of the game data + query.write(new byte[]{0x00, 0x01}); + return query.toByteArray(); + } catch (IOException e) { + e.printStackTrace(); + return new byte[0]; + } + } + + private byte[] getPlayers() { + ByteArrayOutputStream query = new ByteArrayOutputStream(); + + GeyserPingInfo pingInfo = null; + if (connector.getConfig().isPassthroughMotd() || connector.getConfig().isPassthroughPlayerCounts()) { + pingInfo = connector.getBootstrap().getGeyserPingPassthrough().getPingInformation(); + } + + try { + // Start the player section + query.write("player_".getBytes()); + query.write(new byte[]{0x00, 0x00}); + + // Fill player names + if(pingInfo != null) { + for (String username : pingInfo.getPlayers()) { + query.write(username.getBytes()); + query.write((byte) 0x00); + } + } + + // Final byte to show the end of the player data + query.write((byte) 0x00); + return query.toByteArray(); + } catch (IOException e) { + e.printStackTrace(); + return new byte[0]; + } + } + + /** + * Sends a packet to the sender + * @param data packet data + */ + private void sendPacket(ByteBuf data) { + connector.getBedrockServer().getRakNet().send(sender, data); + } + + /** + * Regenerates a token + */ + public void regenerateToken() { + byte[] token = new byte[16]; + for (int i = 0; i < 16; i++) { + token[i] = (byte) new Random().nextInt(255); + } + + this.token = token; + } + + /** + * Gets an MD5 token for the current IP/Port. + * This should reset every 30 seconds but a new one is generated per instance + * Seems wasteful to code something in to clear it when it has no use. + * @param token the token + * @param address the address + * @return an MD5 token for the current IP/Port + */ + public static byte[] getTokenString(byte[] token, InetAddress address) { + try { + MessageDigest digest = MessageDigest.getInstance("MD5"); + digest.update(address.toString().getBytes(StandardCharsets.UTF_8)); + digest.update(token); + return Arrays.copyOf(digest.digest(), 4); + } catch (NoSuchAlgorithmException e) { + return ByteBuffer.allocate(4).putInt(ThreadLocalRandom.current().nextInt()).array(); + } + } +} diff --git a/connector/src/main/java/org/geysermc/connector/ping/GeyserLegacyPingPassthrough.java b/connector/src/main/java/org/geysermc/connector/ping/GeyserLegacyPingPassthrough.java new file mode 100644 index 000000000..ea0d67c21 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/ping/GeyserLegacyPingPassthrough.java @@ -0,0 +1,91 @@ +/* + * 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.ping; + +import com.github.steveice10.mc.protocol.MinecraftConstants; +import com.github.steveice10.mc.protocol.MinecraftProtocol; +import com.github.steveice10.mc.protocol.data.SubProtocol; +import com.github.steveice10.mc.protocol.data.status.handler.ServerInfoHandler; +import com.github.steveice10.packetlib.Client; +import com.github.steveice10.packetlib.tcp.TcpSessionFactory; +import org.geysermc.common.ping.GeyserPingInfo; +import org.geysermc.connector.GeyserConfiguration; +import org.geysermc.connector.GeyserConnector; +import org.geysermc.connector.GeyserLogger; + +import java.util.concurrent.TimeUnit; + +public class GeyserLegacyPingPassthrough implements IGeyserPingPassthrough, Runnable { + + private GeyserConnector connector; + + public GeyserLegacyPingPassthrough(GeyserConnector connector) { + this.connector = connector; + this.pingInfo = new GeyserPingInfo(null, 0, 0); + } + + private GeyserPingInfo pingInfo; + + private Client client; + + /** + * Start legacy ping passthrough thread + * @param connector GeyserConnector + * @return GeyserPingPassthrough, or null if not initialized + */ + public static IGeyserPingPassthrough init(GeyserConnector connector) { + if (connector.getConfig().isPassthroughMotd() || connector.getConfig().isPassthroughPlayerCounts()) { + GeyserLegacyPingPassthrough pingPassthrough = new GeyserLegacyPingPassthrough(connector); + // Ensure delay is not zero + int interval = (connector.getConfig().getPingPassthroughInterval() == 0) ? 1 : connector.getConfig().getPingPassthroughInterval(); + connector.getLogger().debug("Scheduling ping passthrough at an interval of " + interval + " second(s)."); + connector.getGeneralThreadPool().scheduleAtFixedRate(pingPassthrough, 1, interval, TimeUnit.SECONDS); + return pingPassthrough; + } + return null; + } + + @Override + public GeyserPingInfo getPingInformation() { + return pingInfo; + } + + @Override + public void run() { + try { + this.client = new Client(connector.getConfig().getRemote().getAddress(), connector.getConfig().getRemote().getPort(), new MinecraftProtocol(SubProtocol.STATUS), new TcpSessionFactory()); + this.client.getSession().setFlag(MinecraftConstants.SERVER_INFO_HANDLER_KEY, (ServerInfoHandler) (session, info) -> { + this.pingInfo = new GeyserPingInfo(info.getDescription().getFullText(), info.getPlayerInfo().getOnlinePlayers(), info.getPlayerInfo().getMaxPlayers()); + this.client.getSession().disconnect(null); + }); + + client.getSession().connect(); + } catch (Exception ex) { + ex.printStackTrace(); + } + } +} diff --git a/connector/src/main/java/org/geysermc/connector/ping/IGeyserPingPassthrough.java b/connector/src/main/java/org/geysermc/connector/ping/IGeyserPingPassthrough.java new file mode 100644 index 000000000..7bc842dfb --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/ping/IGeyserPingPassthrough.java @@ -0,0 +1,42 @@ +/* + * 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.ping; + +import org.geysermc.common.ping.GeyserPingInfo; + +/** + * Interface that retrieves ping passthrough information from the Java server + */ +public interface IGeyserPingPassthrough { + + /** + * Get the MOTD of the server displayed on the multiplayer screen + * @return string of the MOTD + */ + GeyserPingInfo getPingInformation(); + +} diff --git a/connector/src/main/java/org/geysermc/connector/thread/PingPassthroughThread.java b/connector/src/main/java/org/geysermc/connector/thread/PingPassthroughThread.java deleted file mode 100644 index fa87809b1..000000000 --- a/connector/src/main/java/org/geysermc/connector/thread/PingPassthroughThread.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * 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.thread; - -import com.github.steveice10.mc.protocol.MinecraftConstants; -import com.github.steveice10.mc.protocol.MinecraftProtocol; -import com.github.steveice10.mc.protocol.data.SubProtocol; -import com.github.steveice10.mc.protocol.data.status.ServerStatusInfo; -import com.github.steveice10.mc.protocol.data.status.handler.ServerInfoHandler; -import com.github.steveice10.packetlib.Client; -import com.github.steveice10.packetlib.tcp.TcpSessionFactory; -import lombok.Getter; -import org.geysermc.connector.GeyserConnector; - -public class PingPassthroughThread implements Runnable { - - private GeyserConnector connector; - - public PingPassthroughThread(GeyserConnector connector) { - this.connector = connector; - } - - @Getter - private ServerStatusInfo info; - - private Client client; - - @Override - public void run() { - try { - this.client = new Client(connector.getConfig().getRemote().getAddress(), connector.getConfig().getRemote().getPort(), new MinecraftProtocol(SubProtocol.STATUS), new TcpSessionFactory()); - this.client.getSession().setFlag(MinecraftConstants.SERVER_INFO_HANDLER_KEY, (ServerInfoHandler) (session, info) -> { - this.info = info; - this.client.getSession().disconnect(null); - }); - - client.getSession().connect(); - } catch (Exception ex) { - ex.printStackTrace(); - } - } -} diff --git a/connector/src/main/resources/config.yml b/connector/src/main/resources/config.yml index d12b76480..931e0a8d4 100644 --- a/connector/src/main/resources/config.yml +++ b/connector/src/main/resources/config.yml @@ -12,7 +12,7 @@ bedrock: address: 0.0.0.0 # The port that will listen for connections port: 19132 - # The MOTD that will be broadcasted to Minecraft: Bedrock Edition clients + # The MOTD that will be broadcasted to Minecraft: Bedrock Edition clients. Irrelevant if "passthrough-motd" is set to true motd1: "GeyserMC" motd2: "Another GeyserMC forced host." remote: @@ -45,8 +45,17 @@ floodgate-key-file: public-key.pem # Disabling this will prevent command suggestions from being sent and solve freezing for Bedrock clients. command-suggestions: true -# Relay the MOTD, player count and max players from the remote server -ping-passthrough: false +# The following two options enable "ping passthrough" - the MOTD and/or player count gets retrieved from the Java server. +# Relay the MOTD from the remote server to Bedrock players. +passthrough-motd: false +# Relay the player count and max players from the remote server to Bedrock players. +passthrough-player-counts: false +# Enable LEGACY ping passthrough. There is no need to enable this unless your MOTD or player count does not appear properly. +# This option does nothing on standalone. +legacy-ping-passthrough: false +# How often to ping the remote server, in seconds. Only relevant for standalone or legacy ping passthrough. +# Increase if you are getting BrokenPipe errors. +ping-passthrough-interval: 3 # Maximum amount of players that can connect max-players: 100 @@ -94,4 +103,4 @@ metrics: uuid: generateduuid # DO NOT TOUCH! -config-version: 1 +config-version: 3 diff --git a/connector/src/main/resources/mappings b/connector/src/main/resources/mappings index a67cc940c..a7963d0a0 160000 --- a/connector/src/main/resources/mappings +++ b/connector/src/main/resources/mappings @@ -1 +1 @@ -Subproject commit a67cc940c0d47874c833ffeb58f38e33eabfcc33 +Subproject commit a7963d0a0236b1c47eea21718ac50706139d90cc From 0574feb87e23784b4cd771ae0ff4d52972d5af3c Mon Sep 17 00:00:00 2001 From: RednedEpic Date: Sat, 23 May 2020 18:26:20 -0500 Subject: [PATCH 107/140] Fix block breaking animations when in water (Closes #494) --- .../connector/entity/PlayerEntity.java | 5 +++ .../bedrock/BedrockMovePlayerTranslator.java | 1 + .../player/JavaPlayerActionAckTranslator.java | 2 +- .../translators/world/WorldManager.java | 24 +++++++++++ .../geysermc/connector/utils/BlockUtils.java | 41 +++++++++++-------- 5 files changed, 56 insertions(+), 17 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/entity/PlayerEntity.java b/connector/src/main/java/org/geysermc/connector/entity/PlayerEntity.java index 5db3fdecc..aa7848da2 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/PlayerEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/PlayerEntity.java @@ -57,6 +57,7 @@ public class PlayerEntity extends LivingEntity { private String username; private long lastSkinUpdate = -1; private boolean playerList = true; + private boolean onGround; private final EntityEffectCache effectCache; private Entity leftParrot; @@ -143,6 +144,8 @@ public class PlayerEntity extends LivingEntity { setPosition(position); setRotation(rotation); + this.onGround = isOnGround; + MovePlayerPacket movePlayerPacket = new MovePlayerPacket(); movePlayerPacket.setRuntimeEntityId(geyserId); movePlayerPacket.setPosition(this.position); @@ -168,6 +171,8 @@ public class PlayerEntity extends LivingEntity { setRotation(rotation); this.position = Vector3f.from(position.getX() + relX, position.getY() + relY, position.getZ() + relZ); + this.onGround = isOnGround; + MovePlayerPacket movePlayerPacket = new MovePlayerPacket(); movePlayerPacket.setRuntimeEntityId(geyserId); movePlayerPacket.setPosition(position); diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockMovePlayerTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockMovePlayerTranslator.java index d61461cc4..14d597fd5 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockMovePlayerTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockMovePlayerTranslator.java @@ -85,6 +85,7 @@ public class BedrockMovePlayerTranslator extends PacketTranslator l >= 1).orElse(false); - //boolean outOfWaterButNotOnGround = (!player.isInsideOfWater()) && (!player.isOnGround()); - return calculateBreakTime(blockHardness, toolTier, canHarvestWithHand, correctTool, toolType, isWoolBlock, isCobweb, toolEfficiencyLevel, hasteLevel, miningFatigueLevel); + + hasteLevel = session.getPlayerEntity().getEffectCache().getEffectLevel(Effect.FASTER_DIG); + miningFatigueLevel = session.getPlayerEntity().getEffectCache().getEffectLevel(Effect.SLOWER_DIG); + + boolean isInWater = session.getConnector().getConfig().isCacheChunks() + && BlockTranslator.getBedrockBlockId(session.getConnector().getWorldManager().getBlockAt(session, session.getPlayerEntity().getPosition().toInt())) == BlockTranslator.BEDROCK_WATER_ID; + + boolean insideOfWaterWithoutAquaAffinity = isInWater && + ItemUtils.getEnchantmentLevel(Optional.ofNullable(session.getInventory().getItem(5)).map(ItemStack::getNbt).orElse(null), "minecraft:aqua_affinity") < 1; + + boolean outOfWaterButNotOnGround = (!isInWater) && (!session.getPlayerEntity().isOnGround()); + boolean insideWaterNotOnGround = isInWater && !session.getPlayerEntity().isOnGround(); + return calculateBreakTime(blockHardness, toolTier, canHarvestWithHand, correctTool, toolType, isWoolBlock, isCobweb, toolEfficiencyLevel, hasteLevel, miningFatigueLevel, insideOfWaterWithoutAquaAffinity, outOfWaterButNotOnGround, insideWaterNotOnGround); } } From a49f6fe0e372d754ebc6f80cb1fbb923ff0cb968 Mon Sep 17 00:00:00 2001 From: RednedEpic Date: Sat, 23 May 2020 18:58:36 -0500 Subject: [PATCH 108/140] Specify API version for Bukkit to stop legacy material loading (Closes #595) --- bootstrap/bukkit/src/main/resources/plugin.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/bootstrap/bukkit/src/main/resources/plugin.yml b/bootstrap/bukkit/src/main/resources/plugin.yml index 7e32f0e1f..89c90789e 100644 --- a/bootstrap/bukkit/src/main/resources/plugin.yml +++ b/bootstrap/bukkit/src/main/resources/plugin.yml @@ -4,6 +4,7 @@ author: ${project.organization.name} website: ${project.organization.url} version: ${project.version} softdepend: ["ViaVersion"] +api-version: 1.13 commands: geyser: description: The main command for Geyser. From fe6257bb38c417c78dea9d2e1b229c32443c7b70 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+DoctorMacc@users.noreply.github.com> Date: Sat, 23 May 2020 21:16:11 -0400 Subject: [PATCH 109/140] Check if firework item explosions tag is null (#626) --- .../translators/nbt/FireworkTranslator.java | 66 ++++++++++--------- 1 file changed, 34 insertions(+), 32 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/FireworkTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/FireworkTranslator.java index 77e14e5ae..849df3a4a 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/FireworkTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/FireworkTranslator.java @@ -39,49 +39,51 @@ public class FireworkTranslator extends NbtItemStackTranslator { CompoundTag fireworks = itemTag.get("Fireworks"); ListTag explosions = fireworks.get("Explosions"); - for (Tag effect : explosions.getValue()) { - CompoundTag effectData = (CompoundTag) effect; + if (explosions != null) { + for (Tag effect : explosions.getValue()) { + CompoundTag effectData = (CompoundTag) effect; - CompoundTag newEffectData = new CompoundTag(""); + CompoundTag newEffectData = new CompoundTag(""); - if (effectData.get("Type") != null) { - newEffectData.put(new ByteTag("FireworkType", (Byte) effectData.get("Type").getValue())); - } - - if (effectData.get("Colors") != null) { - int[] oldColors = (int[]) effectData.get("Colors").getValue(); - byte[] colors = new byte[oldColors.length]; - - int i = 0; - for (int color : oldColors) { - colors[i++] = FireworkColor.fromJavaID(color).getBedrockID(); + if (effectData.get("Type") != null) { + newEffectData.put(new ByteTag("FireworkType", (Byte) effectData.get("Type").getValue())); } - newEffectData.put(new ByteArrayTag("FireworkColor", colors)); - } + if (effectData.get("Colors") != null) { + int[] oldColors = (int[]) effectData.get("Colors").getValue(); + byte[] colors = new byte[oldColors.length]; - if (effectData.get("FadeColors") != null) { - int[] oldColors = (int[]) effectData.get("FadeColors").getValue(); - byte[] colors = new byte[oldColors.length]; + int i = 0; + for (int color : oldColors) { + colors[i++] = FireworkColor.fromJavaID(color).getBedrockID(); + } - int i = 0; - for (int color : oldColors) { - colors[i++] = FireworkColor.fromJavaID(color).getBedrockID(); + newEffectData.put(new ByteArrayTag("FireworkColor", colors)); } - newEffectData.put(new ByteArrayTag("FireworkFade", colors)); - } + if (effectData.get("FadeColors") != null) { + int[] oldColors = (int[]) effectData.get("FadeColors").getValue(); + byte[] colors = new byte[oldColors.length]; - if (effectData.get("Trail") != null) { - newEffectData.put(new ByteTag("FireworkTrail", (Byte) effectData.get("Trail").getValue())); - } + int i = 0; + for (int color : oldColors) { + colors[i++] = FireworkColor.fromJavaID(color).getBedrockID(); + } - if (effectData.get("Flicker") != null) { - newEffectData.put(new ByteTag("FireworkFlicker", (Byte) effectData.get("Flicker").getValue())); - } + newEffectData.put(new ByteArrayTag("FireworkFade", colors)); + } - explosions.remove(effect); - explosions.add(newEffectData); + if (effectData.get("Trail") != null) { + newEffectData.put(new ByteTag("FireworkTrail", (Byte) effectData.get("Trail").getValue())); + } + + if (effectData.get("Flicker") != null) { + newEffectData.put(new ByteTag("FireworkFlicker", (Byte) effectData.get("Flicker").getValue())); + } + + explosions.remove(effect); + explosions.add(newEffectData); + } } } From 681cbeeae5d47bd37e72c067deb546cb858bf539 Mon Sep 17 00:00:00 2001 From: RednedEpic Date: Sat, 23 May 2020 22:45:34 -0500 Subject: [PATCH 110/140] Add armor stand entity offset (Fixes #627) --- .../java/entity/JavaEntitySetPassengersTranslator.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/JavaEntitySetPassengersTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/JavaEntitySetPassengersTranslator.java index 0ec79bc07..ad0d0f9e0 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/JavaEntitySetPassengersTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/JavaEntitySetPassengersTranslator.java @@ -137,6 +137,9 @@ public class JavaEntitySetPassengersTranslator extends PacketTranslator Date: Sat, 23 May 2020 23:14:29 -0500 Subject: [PATCH 111/140] Don't delay item frame interactions Causes interacting (moving) an item in an item frame to delay by about half a second. This delay is still present on chunk load where this delay is absolutely needed in order to the item frame to show up. --- .../connector/entity/ItemFrameEntity.java | 42 +++++++++---------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/entity/ItemFrameEntity.java b/connector/src/main/java/org/geysermc/connector/entity/ItemFrameEntity.java index f100704f1..5954e77eb 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/ItemFrameEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/ItemFrameEntity.java @@ -87,9 +87,12 @@ public class ItemFrameEntity extends Entity { @Override public void spawnEntity(GeyserSession session) { session.getItemFrameCache().put(bedrockPosition, entityId); - updateBlock(session); + // Delay is required, or else loading in frames on chunk load is sketchy at best + session.getConnector().getGeneralThreadPool().schedule(() -> { + updateBlock(session); + session.getConnector().getLogger().debug("Spawned item frame at location " + bedrockPosition + " with java id " + entityId); + }, 500, TimeUnit.MILLISECONDS); valid = true; - session.getConnector().getLogger().debug("Spawned item frame at location " + bedrockPosition + " with java id " + entityId); } @Override @@ -170,27 +173,24 @@ public class ItemFrameEntity extends Entity { * @param session GeyserSession. */ public void updateBlock(GeyserSession session) { - // Delay is required, or else loading in frames on chunk load is sketchy at best - session.getConnector().getGeneralThreadPool().schedule(() -> { - UpdateBlockPacket updateBlockPacket = new UpdateBlockPacket(); - updateBlockPacket.setDataLayer(0); - updateBlockPacket.setBlockPosition(bedrockPosition); - updateBlockPacket.setRuntimeId(bedrockRuntimeId); - updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.PRIORITY); - updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NONE); - updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NEIGHBORS); - session.sendUpstreamPacket(updateBlockPacket); + UpdateBlockPacket updateBlockPacket = new UpdateBlockPacket(); + updateBlockPacket.setDataLayer(0); + updateBlockPacket.setBlockPosition(bedrockPosition); + updateBlockPacket.setRuntimeId(bedrockRuntimeId); + updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.PRIORITY); + updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NONE); + updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NEIGHBORS); + session.sendUpstreamPacket(updateBlockPacket); - BlockEntityDataPacket blockEntityDataPacket = new BlockEntityDataPacket(); - blockEntityDataPacket.setBlockPosition(bedrockPosition); - if (cachedTag != null) { - blockEntityDataPacket.setData(cachedTag); - } else { - blockEntityDataPacket.setData(getDefaultTag()); - } + BlockEntityDataPacket blockEntityDataPacket = new BlockEntityDataPacket(); + blockEntityDataPacket.setBlockPosition(bedrockPosition); + if (cachedTag != null) { + blockEntityDataPacket.setData(cachedTag); + } else { + blockEntityDataPacket.setData(getDefaultTag()); + } - session.sendUpstreamPacket(blockEntityDataPacket); - }, 500, TimeUnit.MILLISECONDS); + session.sendUpstreamPacket(blockEntityDataPacket); } /** From 7f5414cdef44e5a9587a636d76ab9bb7c1265dfd Mon Sep 17 00:00:00 2001 From: RednedEpic Date: Sat, 23 May 2020 23:27:16 -0500 Subject: [PATCH 112/140] Fix painting offset if height is equal to 3 (Fixes #629) --- .../main/java/org/geysermc/connector/entity/PaintingEntity.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/connector/src/main/java/org/geysermc/connector/entity/PaintingEntity.java b/connector/src/main/java/org/geysermc/connector/entity/PaintingEntity.java index 56e077339..1711fd38c 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/PaintingEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/PaintingEntity.java @@ -67,7 +67,7 @@ public class PaintingEntity extends Entity { Vector3f position = super.position; position = position.add(0.5, 0.5, 0.5); double widthOffset = paintingName.getWidth() > 1 ? 0.5 : 0; - double heightOffset = paintingName.getHeight() > 1 ? 0.5 : 0; + double heightOffset = paintingName.getHeight() > 1 && paintingName.getHeight() != 3 ? 0.5 : 0; switch (direction) { case 0: return position.add(widthOffset, heightOffset, OFFSET); From 3d0dbff87b002a2a7409cb771ddc07c8e880f070 Mon Sep 17 00:00:00 2001 From: RednedEpic Date: Sat, 23 May 2020 23:45:39 -0500 Subject: [PATCH 113/140] Remove effects on world/server change (Fixes #467) The server re-sends these effects upon joining the new world or server. --- .../org/geysermc/connector/utils/DimensionUtils.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/connector/src/main/java/org/geysermc/connector/utils/DimensionUtils.java b/connector/src/main/java/org/geysermc/connector/utils/DimensionUtils.java index bc7745ca9..6c8d9f944 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/DimensionUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/DimensionUtils.java @@ -25,6 +25,7 @@ package org.geysermc.connector.utils; +import com.github.steveice10.mc.protocol.data.game.entity.Effect; import com.nukkitx.math.vector.Vector3i; import com.nukkitx.protocol.bedrock.packet.*; import org.geysermc.connector.entity.Entity; @@ -59,6 +60,16 @@ public class DimensionUtils { session.setSpawned(false); session.setLastChunkPosition(null); + for (Effect effect : session.getPlayerEntity().getEffectCache().getEntityEffects().keySet()) { + MobEffectPacket mobEffectPacket = new MobEffectPacket(); + mobEffectPacket.setEvent(MobEffectPacket.Event.REMOVE); + mobEffectPacket.setRuntimeEntityId(session.getPlayerEntity().getGeyserId()); + mobEffectPacket.setEffectId(EntityUtils.toBedrockEffectId(effect)); + session.sendUpstreamPacket(mobEffectPacket); + } + // Effects are re-sent from server + session.getPlayerEntity().getEffectCache().getEntityEffects().clear(); + //let java server handle portal travel sound StopSoundPacket stopSoundPacket = new StopSoundPacket(); stopSoundPacket.setStoppingAllSound(true); From 259be966529a3a5f4eb09a61b624257039b0a251 Mon Sep 17 00:00:00 2001 From: RednedEpic Date: Sun, 24 May 2020 12:51:56 -0500 Subject: [PATCH 114/140] Update mappings submodule (Fixes #630) --- connector/src/main/resources/mappings | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/connector/src/main/resources/mappings b/connector/src/main/resources/mappings index a7963d0a0..a67cc940c 160000 --- a/connector/src/main/resources/mappings +++ b/connector/src/main/resources/mappings @@ -1 +1 @@ -Subproject commit a7963d0a0236b1c47eea21718ac50706139d90cc +Subproject commit a67cc940c0d47874c833ffeb58f38e33eabfcc33 From 286970676bc0b13d8363b61d42f4774dd723b072 Mon Sep 17 00:00:00 2001 From: RednedEpic Date: Sun, 24 May 2020 13:06:25 -0500 Subject: [PATCH 115/140] Add null check for shield code (Fixes #644) --- .../bedrock/BedrockInventoryTransactionTranslator.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockInventoryTransactionTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockInventoryTransactionTranslator.java index e4e654f0a..03f7a112a 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockInventoryTransactionTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockInventoryTransactionTranslator.java @@ -25,6 +25,7 @@ package org.geysermc.connector.network.translators.bedrock; +import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position; import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode; import com.github.steveice10.mc.protocol.data.game.entity.player.Hand; @@ -134,7 +135,8 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator Date: Sun, 24 May 2020 14:15:02 -0400 Subject: [PATCH 116/140] Check if firework item explosions tag is null (corresponding entity fix) (#633) * Check if firework item explosions tag is null (corresponding entity fix) * Add null check on flight * Add null check around Flight * Fix newline on if statement * Fix newline on if statement, add null check on flight, remove debug code. * fix missing space.. --- .../connector/entity/FireworkEntity.java | 72 +++++++++---------- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/entity/FireworkEntity.java b/connector/src/main/java/org/geysermc/connector/entity/FireworkEntity.java index a074a53ca..55d9c790c 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/FireworkEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/FireworkEntity.java @@ -60,54 +60,54 @@ public class FireworkEntity extends Entity { CompoundTag fireworks = tag.get("Fireworks"); CompoundTagBuilder fireworksBuilder = CompoundTagBuilder.builder(); - fireworksBuilder.byteTag("Flight", (Byte) fireworks.get("Flight").getValue()); + if (fireworks.get("Flight") != null) { + fireworksBuilder.byteTag("Flight", (Byte) fireworks.get("Flight").getValue()); + } List explosions = new ArrayList<>(); - for (Tag effect : ((ListTag) fireworks.get("Explosions")).getValue()) { - CompoundTag effectData = (CompoundTag) effect; + if (fireworks.get("Explosions") != null) { + for (Tag effect : ((ListTag) fireworks.get("Explosions")).getValue()) { + CompoundTag effectData = (CompoundTag) effect; + CompoundTagBuilder effectBuilder = CompoundTagBuilder.builder(); - try { - GeyserConnector.getInstance().getLogger().debug("Effect: " + new ObjectMapper().writeValueAsString(effect)); - } catch (JsonProcessingException e) { } - - CompoundTagBuilder effectBuilder = CompoundTagBuilder.builder(); - if (effectData.get("Type") != null) { - effectBuilder.byteTag("FireworkType", (Byte) effectData.get("Type").getValue()); - } - - if (effectData.get("Colors") != null) { - int[] oldColors = (int[]) effectData.get("Colors").getValue(); - byte[] colors = new byte[oldColors.length]; - - int i = 0; - for (int color : oldColors) { - colors[i++] = FireworkColor.fromJavaID(color).getBedrockID(); + if (effectData.get("Type") != null) { + effectBuilder.byteTag("FireworkType", (Byte) effectData.get("Type").getValue()); } - effectBuilder.byteArrayTag("FireworkColor", colors); - } + if (effectData.get("Colors") != null) { + int[] oldColors = (int[]) effectData.get("Colors").getValue(); + byte[] colors = new byte[oldColors.length]; - if (effectData.get("FadeColors") != null) { - int[] oldColors = (int[]) effectData.get("FadeColors").getValue(); - byte[] colors = new byte[oldColors.length]; + int i = 0; + for (int color : oldColors) { + colors[i++] = FireworkColor.fromJavaID(color).getBedrockID(); + } - int i = 0; - for (int color : oldColors) { - colors[i++] = FireworkColor.fromJavaID(color).getBedrockID(); + effectBuilder.byteArrayTag("FireworkColor", colors); } - effectBuilder.byteArrayTag("FireworkFade", colors); - } + if (effectData.get("FadeColors") != null) { + int[] oldColors = (int[]) effectData.get("FadeColors").getValue(); + byte[] colors = new byte[oldColors.length]; - if (effectData.get("Trail") != null) { - effectBuilder.byteTag("FireworkTrail", (Byte) effectData.get("Trail").getValue()); - } + int i = 0; + for (int color : oldColors) { + colors[i++] = FireworkColor.fromJavaID(color).getBedrockID(); + } - if (effectData.get("Flicker") != null) { - effectBuilder.byteTag("FireworkFlicker", (Byte) effectData.get("Flicker").getValue()); - } + effectBuilder.byteArrayTag("FireworkFade", colors); + } - explosions.add(effectBuilder.buildRootTag()); + if (effectData.get("Trail") != null) { + effectBuilder.byteTag("FireworkTrail", (Byte) effectData.get("Trail").getValue()); + } + + if (effectData.get("Flicker") != null) { + effectBuilder.byteTag("FireworkFlicker", (Byte) effectData.get("Flicker").getValue()); + } + + explosions.add(effectBuilder.buildRootTag()); + } } fireworksBuilder.tag(new com.nukkitx.nbt.tag.ListTag<>("Explosions", com.nukkitx.nbt.tag.CompoundTag.class, explosions)); From 6dabc22d22b6deb4db633026b1f9e06b44351a92 Mon Sep 17 00:00:00 2001 From: RednedEpic Date: Sun, 24 May 2020 13:20:19 -0500 Subject: [PATCH 117/140] Add null check for fireworks tag (Closes #636) --- .../translators/nbt/FireworkTranslator.java | 90 ++++++++++--------- 1 file changed, 47 insertions(+), 43 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/FireworkTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/FireworkTranslator.java index 849df3a4a..573e520e4 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/FireworkTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/FireworkTranslator.java @@ -36,54 +36,58 @@ public class FireworkTranslator extends NbtItemStackTranslator { @Override public void translateToBedrock(CompoundTag itemTag, ItemEntry itemEntry) { + if (!itemTag.contains("Fireworks")) { + return; + } + CompoundTag fireworks = itemTag.get("Fireworks"); - ListTag explosions = fireworks.get("Explosions"); - if (explosions != null) { - for (Tag effect : explosions.getValue()) { - CompoundTag effectData = (CompoundTag) effect; + if (explosions == null) { + return; + } + for (Tag effect : explosions.getValue()) { + CompoundTag effectData = (CompoundTag) effect; - CompoundTag newEffectData = new CompoundTag(""); + CompoundTag newEffectData = new CompoundTag(""); - if (effectData.get("Type") != null) { - newEffectData.put(new ByteTag("FireworkType", (Byte) effectData.get("Type").getValue())); - } - - if (effectData.get("Colors") != null) { - int[] oldColors = (int[]) effectData.get("Colors").getValue(); - byte[] colors = new byte[oldColors.length]; - - int i = 0; - for (int color : oldColors) { - colors[i++] = FireworkColor.fromJavaID(color).getBedrockID(); - } - - newEffectData.put(new ByteArrayTag("FireworkColor", colors)); - } - - if (effectData.get("FadeColors") != null) { - int[] oldColors = (int[]) effectData.get("FadeColors").getValue(); - byte[] colors = new byte[oldColors.length]; - - int i = 0; - for (int color : oldColors) { - colors[i++] = FireworkColor.fromJavaID(color).getBedrockID(); - } - - newEffectData.put(new ByteArrayTag("FireworkFade", colors)); - } - - if (effectData.get("Trail") != null) { - newEffectData.put(new ByteTag("FireworkTrail", (Byte) effectData.get("Trail").getValue())); - } - - if (effectData.get("Flicker") != null) { - newEffectData.put(new ByteTag("FireworkFlicker", (Byte) effectData.get("Flicker").getValue())); - } - - explosions.remove(effect); - explosions.add(newEffectData); + if (effectData.get("Type") != null) { + newEffectData.put(new ByteTag("FireworkType", (Byte) effectData.get("Type").getValue())); } + + if (effectData.get("Colors") != null) { + int[] oldColors = (int[]) effectData.get("Colors").getValue(); + byte[] colors = new byte[oldColors.length]; + + int i = 0; + for (int color : oldColors) { + colors[i++] = FireworkColor.fromJavaID(color).getBedrockID(); + } + + newEffectData.put(new ByteArrayTag("FireworkColor", colors)); + } + + if (effectData.get("FadeColors") != null) { + int[] oldColors = (int[]) effectData.get("FadeColors").getValue(); + byte[] colors = new byte[oldColors.length]; + + int i = 0; + for (int color : oldColors) { + colors[i++] = FireworkColor.fromJavaID(color).getBedrockID(); + } + + newEffectData.put(new ByteArrayTag("FireworkFade", colors)); + } + + if (effectData.get("Trail") != null) { + newEffectData.put(new ByteTag("FireworkTrail", (Byte) effectData.get("Trail").getValue())); + } + + if (effectData.get("Flicker") != null) { + newEffectData.put(new ByteTag("FireworkFlicker", (Byte) effectData.get("Flicker").getValue())); + } + + explosions.remove(effect); + explosions.add(newEffectData); } } From 56d84c24d3df95b7c1db26c71f31fca505a1cab6 Mon Sep 17 00:00:00 2001 From: RednedEpic Date: Sun, 24 May 2020 14:21:06 -0500 Subject: [PATCH 118/140] Reduce nesting in item nbt translators --- .../translators/nbt/BasicItemTranslator.java | 66 ++++++++------- .../translators/nbt/BookPagesTranslator.java | 66 ++++++++------- .../nbt/EnchantedBookTranslator.java | 30 +++---- .../nbt/EnchantmentTranslator.java | 84 ++++++++++--------- .../nbt/LeatherArmorTranslator.java | 34 ++++---- 5 files changed, 145 insertions(+), 135 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/BasicItemTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/BasicItemTranslator.java index 9458ec4f1..418f97da4 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/BasicItemTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/BasicItemTranslator.java @@ -46,49 +46,51 @@ public class BasicItemTranslator extends NbtItemStackTranslator { @Override public void translateToBedrock(CompoundTag itemTag, ItemEntry itemEntry) { - if (itemTag.contains("display")) { - CompoundTag displayTag = itemTag.get("display"); - if (displayTag.contains("Name")) { - StringTag nameTag = displayTag.get("Name"); + if (!itemTag.contains("display")) { + return; + } + CompoundTag displayTag = itemTag.get("display"); + if (displayTag.contains("Name")) { + StringTag nameTag = displayTag.get("Name"); + try { + displayTag.put(new StringTag("Name", toBedrockMessage(nameTag))); + } catch (Exception ex) { + } + } + + if (displayTag.contains("Lore")) { + ListTag loreTag = displayTag.get("Lore"); + List lore = new ArrayList<>(); + for (Tag tag : loreTag.getValue()) { + if (!(tag instanceof StringTag)) return; try { - displayTag.put(new StringTag("Name", toBedrockMessage(nameTag))); + lore.add(new StringTag("", toBedrockMessage((StringTag) tag))); } catch (Exception ex) { } } - - if (displayTag.contains("Lore")) { - ListTag loreTag = displayTag.get("Lore"); - List lore = new ArrayList<>(); - for (Tag tag : loreTag.getValue()) { - if (!(tag instanceof StringTag)) return; - try { - lore.add(new StringTag("", toBedrockMessage((StringTag) tag))); - } catch (Exception ex) { - } - } - displayTag.put(new ListTag("Lore", lore)); - } + displayTag.put(new ListTag("Lore", lore)); } } @Override public void translateToJava(CompoundTag itemTag, ItemEntry itemEntry) { - if (itemTag.contains("display")) { - CompoundTag displayTag = itemTag.get("display"); - if (displayTag.contains("Name")) { - StringTag nameTag = displayTag.get("Name"); - displayTag.put(new StringTag("Name", toJavaMessage(nameTag))); - } + if (!itemTag.contains("display")) { + return; + } + CompoundTag displayTag = itemTag.get("display"); + if (displayTag.contains("Name")) { + StringTag nameTag = displayTag.get("Name"); + displayTag.put(new StringTag("Name", toJavaMessage(nameTag))); + } - if (displayTag.contains("Lore")) { - ListTag loreTag = displayTag.get("Lore"); - List lore = new ArrayList<>(); - for (Tag tag : loreTag.getValue()) { - if (!(tag instanceof StringTag)) return; - lore.add(new StringTag("", "§r" + toJavaMessage((StringTag) tag))); - } - displayTag.put(new ListTag("Lore", lore)); + if (displayTag.contains("Lore")) { + ListTag loreTag = displayTag.get("Lore"); + List lore = new ArrayList<>(); + for (Tag tag : loreTag.getValue()) { + if (!(tag instanceof StringTag)) return; + lore.add(new StringTag("", "§r" + toJavaMessage((StringTag) tag))); } + displayTag.put(new ListTag("Lore", lore)); } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/BookPagesTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/BookPagesTranslator.java index f29f16fea..d9c48a194 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/BookPagesTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/BookPagesTranslator.java @@ -42,43 +42,45 @@ public class BookPagesTranslator extends NbtItemStackTranslator { @Override public void translateToBedrock(CompoundTag itemTag, ItemEntry itemEntry) { - if (itemTag.contains("pages")) { - List pages = new ArrayList<>(); - ListTag pagesTag = itemTag.get("pages"); - for (Tag tag : pagesTag.getValue()) { - if (!(tag instanceof StringTag)) - continue; - - StringTag textTag = (StringTag) tag; - - CompoundTag pageTag = new CompoundTag(""); - pageTag.put(new StringTag("photoname", "")); - pageTag.put(new StringTag("text", MessageUtils.getBedrockMessage(textTag.getValue()))); - pages.add(pageTag); - } - - itemTag.remove("pages"); - itemTag.put(new ListTag("pages", pages)); + if (!itemTag.contains("pages")) { + return; } + List pages = new ArrayList<>(); + ListTag pagesTag = itemTag.get("pages"); + for (Tag tag : pagesTag.getValue()) { + if (!(tag instanceof StringTag)) + continue; + + StringTag textTag = (StringTag) tag; + + CompoundTag pageTag = new CompoundTag(""); + pageTag.put(new StringTag("photoname", "")); + pageTag.put(new StringTag("text", MessageUtils.getBedrockMessage(textTag.getValue()))); + pages.add(pageTag); + } + + itemTag.remove("pages"); + itemTag.put(new ListTag("pages", pages)); } @Override public void translateToJava(CompoundTag itemTag, ItemEntry itemEntry) { - if (itemTag.contains("pages")) { - List pages = new ArrayList<>(); - ListTag pagesTag = itemTag.get("pages"); - for (Tag tag : pagesTag.getValue()) { - if (!(tag instanceof CompoundTag)) - continue; - - CompoundTag pageTag = (CompoundTag) tag; - - StringTag textTag = pageTag.get("text"); - pages.add(new StringTag(MessageUtils.getJavaMessage(textTag.getValue()))); - } - - itemTag.remove("pages"); - itemTag.put(new ListTag("pages", pages)); + if (!itemTag.contains("pages")) { + return; } + List pages = new ArrayList<>(); + ListTag pagesTag = itemTag.get("pages"); + for (Tag tag : pagesTag.getValue()) { + if (!(tag instanceof CompoundTag)) + continue; + + CompoundTag pageTag = (CompoundTag) tag; + + StringTag textTag = pageTag.get("text"); + pages.add(new StringTag(MessageUtils.getJavaMessage(textTag.getValue()))); + } + + itemTag.remove("pages"); + itemTag.put(new ListTag("pages", pages)); } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/EnchantedBookTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/EnchantedBookTranslator.java index 2ca6e35cc..38df1ee39 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/EnchantedBookTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/EnchantedBookTranslator.java @@ -37,25 +37,27 @@ public class EnchantedBookTranslator extends NbtItemStackTranslator { @Override public void translateToBedrock(CompoundTag itemTag, ItemEntry itemEntry) { - if (itemTag.contains("StoredEnchantments")) { - Tag enchTag = itemTag.get("StoredEnchantments"); - if (enchTag instanceof ListTag) { - enchTag = new ListTag("Enchantments", ((ListTag) enchTag).getValue()); - itemTag.remove("StoredEnchantments"); - itemTag.put(enchTag); - } + if (!itemTag.contains("StoredEnchantments")) { + return; + } + Tag enchTag = itemTag.get("StoredEnchantments"); + if (enchTag instanceof ListTag) { + enchTag = new ListTag("Enchantments", ((ListTag) enchTag).getValue()); + itemTag.remove("StoredEnchantments"); + itemTag.put(enchTag); } } @Override public void translateToJava(CompoundTag itemTag, ItemEntry itemEntry) { - if (itemTag.contains("Enchantments")) { - Tag enchTag = itemTag.get("Enchantments"); - if (enchTag instanceof ListTag) { - enchTag = new ListTag("StoredEnchantments", ((ListTag) enchTag).getValue()); - itemTag.remove("Enchantments"); - itemTag.put(enchTag); - } + if (!itemTag.contains("Enchantments")) { + return; + } + Tag enchTag = itemTag.get("Enchantments"); + if (enchTag instanceof ListTag) { + enchTag = new ListTag("StoredEnchantments", ((ListTag) enchTag).getValue()); + itemTag.remove("Enchantments"); + itemTag.put(enchTag); } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/EnchantmentTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/EnchantmentTranslator.java index 41e1ae36a..5dbb926cd 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/EnchantmentTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/EnchantmentTranslator.java @@ -73,48 +73,50 @@ public class EnchantmentTranslator extends NbtItemStackTranslator { @Override public void translateToJava(CompoundTag itemTag, ItemEntry itemEntry) { - if (itemTag.contains("ench")) { - ListTag enchantmentTag = itemTag.get("ench"); - List enchantments = new ArrayList<>(); - List storedEnchantments = new ArrayList<>(); - for (Tag value : enchantmentTag.getValue()) { - if (!(value instanceof CompoundTag)) - continue; - - CompoundTag tagValue = (CompoundTag) value; - ShortTag bedrockId = tagValue.get("id"); - if (bedrockId == null) continue; - - ShortTag geyserStoredEnchantmentTag = tagValue.get("GeyserStoredEnchantment"); - - Enchantment enchantment = Enchantment.getByBedrockId(bedrockId.getValue()); - if (enchantment != null) { - CompoundTag javaTag = new CompoundTag(""); - Map javaValue = javaTag.getValue(); - javaValue.put("id", new StringTag("id", enchantment.getJavaIdentifier())); - ShortTag levelTag = tagValue.get("lvl"); - javaValue.put("lvl", new IntTag("lvl", levelTag != null ? levelTag.getValue() : 1)); - javaTag.setValue(javaValue); - - - if (geyserStoredEnchantmentTag != null) { - tagValue.remove("GeyserStoredEnchantment"); - storedEnchantments.add(javaTag); - } else { - enchantments.add(javaTag); - } - } else { - GeyserConnector.getInstance().getLogger().debug("Unknown bedrock enchantment: " + bedrockId); - } - } - if (!enchantments.isEmpty()) { - itemTag.put(new ListTag("Enchantments", enchantments)); - } - if (!storedEnchantments.isEmpty()) { - itemTag.put(new ListTag("StoredEnchantments", enchantments)); - } - itemTag.remove("ench"); + if (!itemTag.contains("ench")) { + return; } + + ListTag enchantmentTag = itemTag.get("ench"); + List enchantments = new ArrayList<>(); + List storedEnchantments = new ArrayList<>(); + for (Tag value : enchantmentTag.getValue()) { + if (!(value instanceof CompoundTag)) + continue; + + CompoundTag tagValue = (CompoundTag) value; + ShortTag bedrockId = tagValue.get("id"); + if (bedrockId == null) continue; + + ShortTag geyserStoredEnchantmentTag = tagValue.get("GeyserStoredEnchantment"); + + Enchantment enchantment = Enchantment.getByBedrockId(bedrockId.getValue()); + if (enchantment != null) { + CompoundTag javaTag = new CompoundTag(""); + Map javaValue = javaTag.getValue(); + javaValue.put("id", new StringTag("id", enchantment.getJavaIdentifier())); + ShortTag levelTag = tagValue.get("lvl"); + javaValue.put("lvl", new IntTag("lvl", levelTag != null ? levelTag.getValue() : 1)); + javaTag.setValue(javaValue); + + + if (geyserStoredEnchantmentTag != null) { + tagValue.remove("GeyserStoredEnchantment"); + storedEnchantments.add(javaTag); + } else { + enchantments.add(javaTag); + } + } else { + GeyserConnector.getInstance().getLogger().debug("Unknown bedrock enchantment: " + bedrockId); + } + } + if (!enchantments.isEmpty()) { + itemTag.put(new ListTag("Enchantments", enchantments)); + } + if (!storedEnchantments.isEmpty()) { + itemTag.put(new ListTag("StoredEnchantments", enchantments)); + } + itemTag.remove("ench"); } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/LeatherArmorTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/LeatherArmorTranslator.java index 4b01d912d..5b283ef57 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/LeatherArmorTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/LeatherArmorTranslator.java @@ -38,29 +38,31 @@ public class LeatherArmorTranslator extends NbtItemStackTranslator { @Override public void translateToBedrock(CompoundTag itemTag, ItemEntry itemEntry) { - if (itemTag.contains("display")) { - CompoundTag displayTag = itemTag.get("display"); - if (displayTag.contains("color")) { - IntTag color = displayTag.get("color"); - if (color != null) { - itemTag.put(new IntTag("customColor", color.getValue())); - displayTag.remove("color"); - } + if (!itemTag.contains("display")) { + return; + } + CompoundTag displayTag = itemTag.get("display"); + if (displayTag.contains("color")) { + IntTag color = displayTag.get("color"); + if (color != null) { + itemTag.put(new IntTag("customColor", color.getValue())); + displayTag.remove("color"); } } } @Override public void translateToJava(CompoundTag itemTag, ItemEntry itemEntry) { - if (itemTag.contains("customColor")) { - IntTag color = itemTag.get("customColor"); - CompoundTag displayTag = itemTag.get("display"); - if (displayTag == null) { - displayTag = new CompoundTag("display"); - } - displayTag.put(color); - itemTag.remove("customColor"); + if (!itemTag.contains("customColor")) { + return; } + IntTag color = itemTag.get("customColor"); + CompoundTag displayTag = itemTag.get("display"); + if (displayTag == null) { + displayTag = new CompoundTag("display"); + } + displayTag.put(color); + itemTag.remove("customColor"); } @Override From 0215220ac1dbfaf39fc504280896aaecec7c09e9 Mon Sep 17 00:00:00 2001 From: RednedEpic Date: Sun, 24 May 2020 14:46:36 -0500 Subject: [PATCH 119/140] Fix spectator mode --- .../world/JavaNotifyClientTranslator.java | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaNotifyClientTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaNotifyClientTranslator.java index de1066c00..781018b2f 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaNotifyClientTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaNotifyClientTranslator.java @@ -42,6 +42,7 @@ import org.geysermc.connector.network.translators.inventory.PlayerInventoryTrans import java.util.Set; import java.util.concurrent.ThreadLocalRandom; +import java.util.concurrent.TimeUnit; @Translator(packet = ServerNotifyClientPacket.class) public class JavaNotifyClientTranslator extends PacketTranslator { @@ -80,6 +81,7 @@ public class JavaNotifyClientTranslator extends PacketTranslator { + AdventureSettingsPacket adventureSettingsPacket = new AdventureSettingsPacket(); + adventureSettingsPacket.setPlayerPermission(PlayerPermission.MEMBER); + adventureSettingsPacket.setCommandPermission(CommandPermission.NORMAL); + adventureSettingsPacket.setUniqueEntityId(entity.getGeyserId()); + adventureSettingsPacket.getFlags().addAll(playerFlags); + session.sendUpstreamPacket(adventureSettingsPacket); + }, 50, TimeUnit.MILLISECONDS); EntityDataMap metadata = entity.getMetadata(); - metadata.getFlags().setFlag(EntityFlag.CAN_FLY, gameMode == GameMode.CREATIVE || gameMode == GameMode.SPECTATOR); + metadata.getFlags().setFlag(EntityFlag.CAN_FLY, gameMode == GameMode.CREATIVE); SetEntityDataPacket entityDataPacket = new SetEntityDataPacket(); entityDataPacket.setRuntimeEntityId(entity.getGeyserId()); @@ -105,7 +111,6 @@ public class JavaNotifyClientTranslator extends PacketTranslator Date: Sun, 24 May 2020 20:51:30 +0100 Subject: [PATCH 120/140] Added Crossbow nbt translator (#590) They still infinitely reload but they correctly track if they have data in now. --- .../translators/nbt/CrossbowTranslator.java | 78 +++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/CrossbowTranslator.java diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/CrossbowTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/CrossbowTranslator.java new file mode 100644 index 000000000..757011036 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/CrossbowTranslator.java @@ -0,0 +1,78 @@ +/* + * 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.item.translators.nbt; + +import com.github.steveice10.opennbt.tag.builtin.ByteTag; +import com.github.steveice10.opennbt.tag.builtin.CompoundTag; +import com.github.steveice10.opennbt.tag.builtin.ListTag; +import com.github.steveice10.opennbt.tag.builtin.StringTag; +import org.geysermc.connector.network.translators.ItemRemapper; +import org.geysermc.connector.network.translators.NbtItemStackTranslator; +import org.geysermc.connector.network.translators.item.ItemEntry; + +@ItemRemapper +public class CrossbowTranslator extends NbtItemStackTranslator { + + @Override + public void translateToBedrock(CompoundTag itemTag, ItemEntry itemEntry) { + if (itemTag.get("ChargedProjectiles") != null) { + ListTag chargedProjectiles = itemTag.get("ChargedProjectiles"); + if (!chargedProjectiles.getValue().isEmpty()) { + CompoundTag projectile = (CompoundTag) chargedProjectiles.getValue().get(0); + + CompoundTag newProjectile = new CompoundTag("chargedItem"); + newProjectile.put(new ByteTag("Count", (byte) projectile.get("Count").getValue())); + newProjectile.put(new StringTag("Name", (String) projectile.get("id").getValue())); + + // Not sure what this is for + newProjectile.put(new ByteTag("Damage", (byte) 0)); + + itemTag.put(newProjectile); + } + } + } + + @Override + public void translateToJava(CompoundTag itemTag, ItemEntry itemEntry) { + if (itemTag.get("chargedItem") != null) { + CompoundTag chargedItem = itemTag.get("chargedItem"); + + CompoundTag newProjectile = new CompoundTag(""); + newProjectile.put(new ByteTag("Count", (byte) chargedItem.get("Count").getValue())); + newProjectile.put(new StringTag("id", (String) chargedItem.get("Name").getValue())); + + ListTag chargedProjectiles = new ListTag("ChargedProjectiles"); + chargedProjectiles.add(newProjectile); + + itemTag.put(chargedProjectiles); + } + } + + @Override + public boolean acceptItem(ItemEntry itemEntry) { + return "minecraft:crossbow".equals(itemEntry.getJavaIdentifier()); + } +} From 7154e1c816470cade4a8d4250c04f86515cc4f93 Mon Sep 17 00:00:00 2001 From: RednedEpic Date: Sun, 24 May 2020 14:55:48 -0500 Subject: [PATCH 121/140] Strip Minecraft identifier when playing non-mapped sounds to allow for bedrock-exclusive sounds to be played --- .../translators/java/world/JavaPlayerPlaySoundTranslator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaPlayerPlaySoundTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaPlayerPlaySoundTranslator.java index c349c628b..58386841e 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaPlayerPlaySoundTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaPlayerPlaySoundTranslator.java @@ -57,7 +57,7 @@ public class JavaPlayerPlaySoundTranslator extends PacketTranslator Date: Sun, 24 May 2020 20:07:05 -0500 Subject: [PATCH 122/140] Large refactoring to item translator and registry/util classes - Merged ItemTranslator and ItemStackTranslator together. - Split ItemTranslator into two classes: ItemTranslator and ItemRegistry. The registry is where items are registered, and the translator class is where item translation takes place. - Made most of ItemTranslator's methods static and removed the initialization in Toolbox. - Moved a handful of registry classes previously ending with 'Utils' to a 'Registry' class to be more fitting for the term. - Moved inventory and block entity registration out of Translators. - Renamed Translators to PacketTranslatorRegistry. - Yeeted Toolbox. - Minor cleanups and small refactors. --- .../geysermc/connector/GeyserConnector.java | 32 +- .../entity/AreaEffectCloudEntity.java | 4 +- .../org/geysermc/connector/entity/Entity.java | 9 +- .../geysermc/connector/entity/ItemEntity.java | 4 +- .../connector/entity/ItemFrameEntity.java | 10 +- .../network/UpstreamPacketHandler.java | 4 +- .../network/session/GeyserSession.java | 18 +- .../network/translators/BiomeTranslator.java | 70 +++- .../translators/EntityIdentifierRegistry.java | 60 ++++ .../translators/ItemStackTranslator.java | 250 ------------- .../translators/NbtItemStackTranslator.java | 45 --- ...try.java => PacketTranslatorRegistry.java} | 46 ++- .../network/translators/Translators.java | 175 ---------- ...drockBlockPickRequestPacketTranslator.java | 9 +- .../bedrock/BedrockInteractTranslator.java | 4 +- ...BedrockInventoryTransactionTranslator.java | 14 +- .../translators/effect/EffectRegistry.java} | 68 ++-- .../inventory/InventoryTranslator.java | 35 ++ .../inventory/PlayerInventoryTranslator.java | 23 +- .../action/InventoryActionDataTranslator.java | 6 +- .../updater/ChestInventoryUpdater.java | 6 +- .../updater/ContainerInventoryUpdater.java | 6 +- .../updater/CursorInventoryUpdater.java | 6 +- .../inventory/updater/InventoryUpdater.java | 6 +- .../translators/item/ItemRegistry.java} | 178 +++++----- .../translators/item/ItemTranslator.java | 330 ++++++++++++++---- .../item/NbtItemStackTranslator.java | 45 +++ .../item/translators/BannerTranslator.java | 90 ++++- .../item/translators/PotionTranslator.java | 8 +- .../translators/nbt/BasicItemTranslator.java | 2 +- .../translators/nbt/BookPagesTranslator.java | 2 +- .../translators/nbt/CrossbowTranslator.java | 2 +- .../nbt/EnchantedBookTranslator.java | 2 +- .../nbt/EnchantmentTranslator.java | 2 +- .../translators/nbt/FireworkTranslator.java | 2 +- .../nbt/LeatherArmorTranslator.java | 2 +- .../translators/nbt/MapItemTranslator.java | 2 +- .../java/JavaDeclareRecipesTranslator.java | 14 +- .../entity/JavaEntityEquipmentTranslator.java | 4 +- .../player/JavaPlayerActionAckTranslator.java | 4 +- .../player/JavaPlayerStopSoundTranslator.java | 4 +- .../java/window/JavaOpenWindowTranslator.java | 7 +- .../java/window/JavaSetSlotTranslator.java | 3 +- .../window/JavaWindowItemsTranslator.java | 3 +- .../window/JavaWindowPropertyTranslator.java | 3 +- .../world/JavaPlayBuiltinSoundTranslator.java | 10 +- .../java/world/JavaPlayEffectTranslator.java | 12 +- .../world/JavaPlayerPlaySoundTranslator.java | 4 +- .../world/JavaSpawnParticleTranslator.java | 10 +- .../sound/BlockSoundInteractionHandler.java | 4 +- .../sound/EntitySoundInteractionHandler.java | 4 +- .../translators/sound/SoundRegistry.java} | 57 +-- .../block/BucketSoundInteractionHandler.java | 4 +- .../MilkCowSoundInteractionHandler.java | 4 +- .../world/block/BlockTranslator.java | 8 +- .../entity/BannerBlockEntityTranslator.java | 4 +- .../block/entity/BlockEntityTranslator.java | 37 ++ .../entity/CampfireBlockEntityTranslator.java | 5 +- .../connector/utils/BlockEntityUtils.java | 5 +- .../geysermc/connector/utils/ChunkUtils.java | 27 +- .../geysermc/connector/utils/FileUtils.java | 14 + .../connector/utils/InventoryUtils.java | 13 +- .../geysermc/connector/utils/ItemUtils.java | 73 ---- .../geysermc/connector/utils/LocaleUtils.java | 10 +- .../connector/utils/SkinProvider.java | 4 +- 65 files changed, 980 insertions(+), 948 deletions(-) create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/EntityIdentifierRegistry.java delete mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/ItemStackTranslator.java delete mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/NbtItemStackTranslator.java rename connector/src/main/java/org/geysermc/connector/network/translators/{Registry.java => PacketTranslatorRegistry.java} (55%) delete mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/Translators.java rename connector/src/main/java/org/geysermc/connector/{utils/EffectUtils.java => network/translators/effect/EffectRegistry.java} (64%) rename connector/src/main/java/org/geysermc/connector/{utils/Toolbox.java => network/translators/item/ItemRegistry.java} (52%) create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/item/NbtItemStackTranslator.java rename connector/src/main/java/org/geysermc/connector/{utils/SoundUtils.java => network/translators/sound/SoundRegistry.java} (65%) diff --git a/connector/src/main/java/org/geysermc/connector/GeyserConnector.java b/connector/src/main/java/org/geysermc/connector/GeyserConnector.java index 43b100533..02e0c5003 100644 --- a/connector/src/main/java/org/geysermc/connector/GeyserConnector.java +++ b/connector/src/main/java/org/geysermc/connector/GeyserConnector.java @@ -25,6 +25,8 @@ package org.geysermc.connector; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; import com.nukkitx.protocol.bedrock.BedrockPacketCodec; import com.nukkitx.protocol.bedrock.BedrockServer; import com.nukkitx.protocol.bedrock.v390.Bedrock_v390; @@ -37,11 +39,20 @@ import org.geysermc.connector.metrics.Metrics; import org.geysermc.connector.network.ConnectorServerEventHandler; import org.geysermc.connector.network.remote.RemoteServer; import org.geysermc.connector.network.session.GeyserSession; -import org.geysermc.connector.network.translators.Translators; +import org.geysermc.connector.network.translators.BiomeTranslator; +import org.geysermc.connector.network.translators.EntityIdentifierRegistry; +import org.geysermc.connector.network.translators.PacketTranslatorRegistry; +import org.geysermc.connector.network.translators.item.ItemRegistry; +import org.geysermc.connector.network.translators.item.ItemTranslator; +import org.geysermc.connector.network.translators.sound.SoundHandlerRegistry; import org.geysermc.connector.network.translators.world.WorldManager; +import org.geysermc.connector.network.translators.world.block.BlockTranslator; +import org.geysermc.connector.network.translators.effect.EffectRegistry; +import org.geysermc.connector.network.translators.world.block.entity.BlockEntityTranslator; import org.geysermc.connector.utils.DimensionUtils; import org.geysermc.connector.utils.DockerCheck; -import org.geysermc.connector.utils.Toolbox; +import org.geysermc.connector.utils.LocaleUtils; +import org.geysermc.connector.network.translators.sound.SoundRegistry; import java.net.InetSocketAddress; import java.text.DecimalFormat; @@ -55,6 +66,8 @@ import java.util.concurrent.TimeUnit; @Getter public class GeyserConnector { + public static final ObjectMapper JSON_MAPPER = new ObjectMapper().disable(DeserializationFeature.FAIL_ON_IGNORED_PROPERTIES); + public static final BedrockPacketCodec BEDROCK_PACKET_CODEC = Bedrock_v390.V390_CODEC; public static final String NAME = "Geyser"; @@ -99,8 +112,19 @@ public class GeyserConnector { logger.setDebug(config.isDebugMode()); - Toolbox.init(); - Translators.start(); + PacketTranslatorRegistry.init(); + + /* Initialize translators and registries */ + BiomeTranslator.init(); + BlockTranslator.init(); + BlockEntityTranslator.init(); + EffectRegistry.init(); + EntityIdentifierRegistry.init(); + ItemRegistry.init(); + ItemTranslator.init(); + LocaleUtils.init(); + SoundRegistry.init(); + SoundHandlerRegistry.init(); if (platformType != PlatformType.STANDALONE) { DockerCheck.check(bootstrap); diff --git a/connector/src/main/java/org/geysermc/connector/entity/AreaEffectCloudEntity.java b/connector/src/main/java/org/geysermc/connector/entity/AreaEffectCloudEntity.java index 2808b093c..79e67f345 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/AreaEffectCloudEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/AreaEffectCloudEntity.java @@ -31,7 +31,7 @@ import com.nukkitx.math.vector.Vector3f; import com.nukkitx.protocol.bedrock.data.EntityData; import org.geysermc.connector.entity.type.EntityType; import org.geysermc.connector.network.session.GeyserSession; -import org.geysermc.connector.utils.EffectUtils; +import org.geysermc.connector.network.translators.effect.EffectRegistry; public class AreaEffectCloudEntity extends Entity { @@ -52,7 +52,7 @@ public class AreaEffectCloudEntity extends Entity { metadata.put(EntityData.BOUNDING_BOX_WIDTH, 2.0f * (float) entityMetadata.getValue()); } else if (entityMetadata.getId() == 10) { Particle particle = (Particle) entityMetadata.getValue(); - metadata.put(EntityData.AREA_EFFECT_CLOUD_PARTICLE_ID, EffectUtils.getParticleString(particle.getType())); + metadata.put(EntityData.AREA_EFFECT_CLOUD_PARTICLE_ID, EffectRegistry.getParticleString(particle.getType())); } else if (entityMetadata.getId() == 8) { metadata.put(EntityData.POTION_COLOR, entityMetadata.getValue()); } diff --git a/connector/src/main/java/org/geysermc/connector/entity/Entity.java b/connector/src/main/java/org/geysermc/connector/entity/Entity.java index 30df1085c..434c983bb 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/Entity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/Entity.java @@ -51,8 +51,7 @@ import org.geysermc.connector.entity.attribute.AttributeType; import org.geysermc.connector.entity.living.ArmorStandEntity; import org.geysermc.connector.entity.type.EntityType; import org.geysermc.connector.network.session.GeyserSession; -import org.geysermc.connector.network.translators.item.ItemTranslator; -import org.geysermc.connector.network.translators.world.block.BlockTranslator; +import org.geysermc.connector.network.translators.item.ItemRegistry; import org.geysermc.connector.utils.AttributeUtils; import org.geysermc.connector.utils.ChunkUtils; import org.geysermc.connector.utils.MessageUtils; @@ -225,11 +224,11 @@ public class Entity { // Shield code if (session.getPlayerEntity().getEntityId() == entityId && metadata.getFlags().getFlag(EntityFlag.SNEAKING)) { - if ((session.getInventory().getItemInHand() != null && session.getInventory().getItemInHand().getId() == ItemTranslator.SHIELD) || - (session.getInventoryCache().getPlayerInventory().getItem(45) != null && session.getInventoryCache().getPlayerInventory().getItem(45).getId() == ItemTranslator.SHIELD)) { + if ((session.getInventory().getItemInHand() != null && session.getInventory().getItemInHand().getId() == ItemRegistry.SHIELD) || + (session.getInventoryCache().getPlayerInventory().getItem(45) != null && session.getInventoryCache().getPlayerInventory().getItem(45).getId() == ItemRegistry.SHIELD)) { ClientPlayerUseItemPacket useItemPacket; metadata.getFlags().setFlag(EntityFlag.BLOCKING, true); - if (session.getInventory().getItemInHand() != null && session.getInventory().getItemInHand().getId() == ItemTranslator.SHIELD) { + if (session.getInventory().getItemInHand() != null && session.getInventory().getItemInHand().getId() == ItemRegistry.SHIELD) { useItemPacket = new ClientPlayerUseItemPacket(Hand.MAIN_HAND); } // Else we just assume it's the offhand, to simplify logic and to assure the packet gets sent diff --git a/connector/src/main/java/org/geysermc/connector/entity/ItemEntity.java b/connector/src/main/java/org/geysermc/connector/entity/ItemEntity.java index b321213e1..bd18dc46e 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/ItemEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/ItemEntity.java @@ -31,7 +31,7 @@ import com.nukkitx.math.vector.Vector3f; import com.nukkitx.protocol.bedrock.packet.AddItemEntityPacket; import org.geysermc.connector.entity.type.EntityType; import org.geysermc.connector.network.session.GeyserSession; -import org.geysermc.connector.network.translators.Translators; +import org.geysermc.connector.network.translators.item.ItemTranslator; public class ItemEntity extends Entity { @@ -49,7 +49,7 @@ public class ItemEntity extends Entity { itemPacket.setUniqueEntityId(geyserId); itemPacket.setFromFishing(false); itemPacket.getMetadata().putAll(metadata); - itemPacket.setItemInHand(Translators.getItemTranslator().translateToBedrock(session, (ItemStack) entityMetadata.getValue())); + itemPacket.setItemInHand(ItemTranslator.translateToBedrock((ItemStack) entityMetadata.getValue())); session.sendUpstreamPacket(itemPacket); } diff --git a/connector/src/main/java/org/geysermc/connector/entity/ItemFrameEntity.java b/connector/src/main/java/org/geysermc/connector/entity/ItemFrameEntity.java index 5954e77eb..a6d8af154 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/ItemFrameEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/ItemFrameEntity.java @@ -38,10 +38,10 @@ import com.nukkitx.protocol.bedrock.packet.StartGamePacket; import com.nukkitx.protocol.bedrock.packet.UpdateBlockPacket; import org.geysermc.connector.entity.type.EntityType; import org.geysermc.connector.network.session.GeyserSession; -import org.geysermc.connector.network.translators.Translators; import org.geysermc.connector.network.translators.item.ItemEntry; +import org.geysermc.connector.network.translators.item.ItemRegistry; +import org.geysermc.connector.network.translators.item.ItemTranslator; import org.geysermc.connector.network.translators.world.block.BlockTranslator; -import org.geysermc.connector.utils.Toolbox; import java.util.concurrent.TimeUnit; @@ -98,12 +98,12 @@ public class ItemFrameEntity extends Entity { @Override public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { if (entityMetadata.getId() == 7 && entityMetadata.getValue() != null) { - ItemData itemData = Translators.getItemTranslator().translateToBedrock(session, (ItemStack) entityMetadata.getValue()); - ItemEntry itemEntry = Translators.getItemTranslator().getItem((ItemStack) entityMetadata.getValue()); + ItemData itemData = ItemTranslator.translateToBedrock((ItemStack) entityMetadata.getValue()); + ItemEntry itemEntry = ItemRegistry.getItem((ItemStack) entityMetadata.getValue()); CompoundTagBuilder builder = CompoundTag.builder(); String blockName = ""; - for (StartGamePacket.ItemEntry startGamePacketItemEntry: Toolbox.ITEMS) { + for (StartGamePacket.ItemEntry startGamePacketItemEntry : ItemRegistry.ITEMS) { if (startGamePacketItemEntry.getId() == (short) itemEntry.getBedrockId()) { blockName = startGamePacketItemEntry.getIdentifier(); break; diff --git a/connector/src/main/java/org/geysermc/connector/network/UpstreamPacketHandler.java b/connector/src/main/java/org/geysermc/connector/network/UpstreamPacketHandler.java index 3d2ded446..67862d0e7 100644 --- a/connector/src/main/java/org/geysermc/connector/network/UpstreamPacketHandler.java +++ b/connector/src/main/java/org/geysermc/connector/network/UpstreamPacketHandler.java @@ -31,7 +31,7 @@ import org.geysermc.common.AuthType; import org.geysermc.connector.GeyserConfiguration; import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.network.session.GeyserSession; -import org.geysermc.connector.network.translators.Registry; +import org.geysermc.connector.network.translators.PacketTranslatorRegistry; import org.geysermc.connector.utils.LoginEncryptionUtils; public class UpstreamPacketHandler extends LoggingPacketHandler { @@ -41,7 +41,7 @@ public class UpstreamPacketHandler extends LoggingPacketHandler { } private boolean translateAndDefault(BedrockPacket packet) { - return Registry.BEDROCK.translate(packet.getClass(), packet, session); + return PacketTranslatorRegistry.BEDROCK_TRANSLATOR.translate(packet.getClass(), packet, session); } @Override diff --git a/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java b/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java index 90ca13447..cc052509a 100644 --- a/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java +++ b/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java @@ -65,12 +65,14 @@ import org.geysermc.connector.network.remote.RemoteServer; import org.geysermc.connector.network.session.auth.AuthData; import org.geysermc.connector.network.session.auth.BedrockClientData; import org.geysermc.connector.network.session.cache.*; -import org.geysermc.connector.network.translators.Registry; +import org.geysermc.connector.network.translators.BiomeTranslator; +import org.geysermc.connector.network.translators.EntityIdentifierRegistry; +import org.geysermc.connector.network.translators.PacketTranslatorRegistry; +import org.geysermc.connector.network.translators.item.ItemRegistry; import org.geysermc.connector.network.translators.world.block.BlockTranslator; import org.geysermc.connector.utils.ChunkUtils; import org.geysermc.connector.utils.LocaleUtils; import org.geysermc.connector.utils.SkinUtils; -import org.geysermc.connector.utils.Toolbox; import org.geysermc.floodgate.util.BedrockData; import org.geysermc.floodgate.util.EncryptionUtil; @@ -194,16 +196,16 @@ public class GeyserSession implements CommandSender { ChunkUtils.sendEmptyChunks(this, playerEntity.getPosition().toInt(), 0, false); BiomeDefinitionListPacket biomeDefinitionListPacket = new BiomeDefinitionListPacket(); - biomeDefinitionListPacket.setTag(Toolbox.BIOMES); + biomeDefinitionListPacket.setTag(BiomeTranslator.BIOMES); upstream.sendPacket(biomeDefinitionListPacket); AvailableEntityIdentifiersPacket entityPacket = new AvailableEntityIdentifiersPacket(); - entityPacket.setTag(Toolbox.ENTITY_IDENTIFIERS); + entityPacket.setTag(EntityIdentifierRegistry.ENTITY_IDENTIFIERS); upstream.sendPacket(entityPacket); InventoryContentPacket creativePacket = new InventoryContentPacket(); creativePacket.setContainerId(ContainerId.CREATIVE); - creativePacket.setContents(Toolbox.CREATIVE_ITEMS); + creativePacket.setContents(ItemRegistry.CREATIVE_ITEMS); upstream.sendPacket(creativePacket); PlayStatusPacket playStatusPacket = new PlayStatusPacket(); @@ -345,7 +347,7 @@ public class GeyserSession implements CommandSender { lastDimPacket = event.getPacket(); return; } else if (lastDimPacket != null) { - Registry.JAVA.translate(lastDimPacket.getClass(), lastDimPacket, GeyserSession.this); + PacketTranslatorRegistry.JAVA_TRANSLATOR.translate(lastDimPacket.getClass(), lastDimPacket, GeyserSession.this); lastDimPacket = null; } @@ -361,7 +363,7 @@ public class GeyserSession implements CommandSender { } } - Registry.JAVA.translate(event.getPacket().getClass(), event.getPacket(), GeyserSession.this); + PacketTranslatorRegistry.JAVA_TRANSLATOR.translate(event.getPacket().getClass(), event.getPacket(), GeyserSession.this); } } }); @@ -497,7 +499,7 @@ public class GeyserSession implements CommandSender { startGamePacket.setEnchantmentSeed(0); startGamePacket.setMultiplayerCorrelationId(""); startGamePacket.setBlockPalette(BlockTranslator.BLOCKS); - startGamePacket.setItemEntries(Toolbox.ITEMS); + startGamePacket.setItemEntries(ItemRegistry.ITEMS); startGamePacket.setVanillaVersion("*"); // startGamePacket.setMovementServerAuthoritative(true); upstream.sendPacket(startGamePacket); diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/BiomeTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/BiomeTranslator.java index 122788412..c12cc5136 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/BiomeTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/BiomeTranslator.java @@ -1,14 +1,72 @@ +/* + * 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; + +import com.nukkitx.nbt.NbtUtils; +import com.nukkitx.nbt.stream.NBTInputStream; +import com.nukkitx.nbt.tag.CompoundTag; +import org.geysermc.connector.GeyserConnector; +import org.geysermc.connector.utils.FileUtils; + +import java.io.InputStream; import java.util.Arrays; -//Based off of ProtocolSupport's LegacyBiomeData.java https://github.com/ProtocolSupport/ProtocolSupport/blob/b2cad35977f3fcb65bee57b9e14fc9c975f71d32/src/protocolsupport/protocol/typeremapper/legacy/LegacyBiomeData.java -//Array index formula by https://wiki.vg/Chunk_Format - +// Based off of ProtocolSupport's LegacyBiomeData.java: +// https://github.com/ProtocolSupport/ProtocolSupport/blob/b2cad35977f3fcb65bee57b9e14fc9c975f71d32/src/protocolsupport/protocol/typeremapper/legacy/LegacyBiomeData.java +// Array index formula by https://wiki.vg/Chunk_Format public class BiomeTranslator { + public static final CompoundTag BIOMES; + + private BiomeTranslator() { + } + + public static void init() { + // no-op + } + + static { + /* Load biomes */ + InputStream stream = FileUtils.getResource("bedrock/biome_definitions.dat"); + + CompoundTag biomesTag; + + try (NBTInputStream biomenbtInputStream = NbtUtils.createNetworkReader(stream)){ + biomesTag = (CompoundTag) biomenbtInputStream.readTag(); + BIOMES = biomesTag; + } catch (Exception ex) { + GeyserConnector.getInstance().getLogger().warning("Failed to get biomes from biome definitions, is there something wrong with the file?"); + throw new AssertionError(ex); + } + } + public static byte[] toBedrockBiome(int[] biomeData) { byte[] bedrockData = new byte[256]; - if(biomeData == null) { + if (biomeData == null) { return bedrockData; } @@ -24,12 +82,12 @@ public class BiomeTranslator { return bedrockData; } - protected static void fillArray(int z, int x, byte[] legacyBiomeData, int biomeId) { + private static void fillArray(int z, int x, byte[] legacyBiomeData, int biomeId) { int offset = (z << 4) | x; Arrays.fill(legacyBiomeData, offset, offset + 4, (byte) biomeId); } - protected static byte biomeID(int[] biomeData, int x, int z) { + private static byte biomeID(int[] biomeData, int x, int z) { return (byte) biomeData[((z >> 2) & 3) << 2 | ((x >> 2) & 3)]; } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/EntityIdentifierRegistry.java b/connector/src/main/java/org/geysermc/connector/network/translators/EntityIdentifierRegistry.java new file mode 100644 index 000000000..cc9b2cd89 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/EntityIdentifierRegistry.java @@ -0,0 +1,60 @@ +/* + * 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; + +import com.nukkitx.nbt.NbtUtils; +import com.nukkitx.nbt.stream.NBTInputStream; +import com.nukkitx.nbt.tag.CompoundTag; +import org.geysermc.connector.utils.FileUtils; + +import java.io.InputStream; + +/** + * Registry for entity identifiers. + */ +public class EntityIdentifierRegistry { + + public static CompoundTag ENTITY_IDENTIFIERS; + + private EntityIdentifierRegistry() { + } + + public static void init() { + // no-op + } + + static { + /* Load entity identifiers */ + InputStream stream = FileUtils.getResource("bedrock/entity_identifiers.dat"); + + try (NBTInputStream nbtInputStream = NbtUtils.createNetworkReader(stream)) { + ENTITY_IDENTIFIERS = (CompoundTag) nbtInputStream.readTag(); + } catch (Exception e) { + throw new AssertionError("Unable to get entities from entity identifiers", e); + } + } +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/ItemStackTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/ItemStackTranslator.java deleted file mode 100644 index 423ffd390..000000000 --- a/connector/src/main/java/org/geysermc/connector/network/translators/ItemStackTranslator.java +++ /dev/null @@ -1,250 +0,0 @@ -/* - * 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; - -import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; -import com.github.steveice10.mc.protocol.data.message.Message; -import com.github.steveice10.opennbt.tag.builtin.*; -import com.nukkitx.nbt.tag.CompoundTag; -import com.nukkitx.nbt.tag.Tag; -import com.nukkitx.protocol.bedrock.data.ItemData; -import org.geysermc.connector.network.translators.item.ItemEntry; -import org.geysermc.connector.utils.MessageUtils; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -public abstract class ItemStackTranslator { - - public ItemData translateToBedrock(ItemStack itemStack, ItemEntry itemEntry) { - if (itemStack == null) { - return ItemData.AIR; - } - if (itemStack.getNbt() == null) { - return ItemData.of(itemEntry.getBedrockId(), (short) itemEntry.getBedrockData(), itemStack.getAmount()); - } - return ItemData.of(itemEntry.getBedrockId(), (short) itemEntry.getBedrockData(), itemStack.getAmount(), this.translateNbtToBedrock(itemStack.getNbt())); - } - - public ItemStack translateToJava(ItemData itemData, ItemEntry itemEntry) { - if (itemData == null) return null; - if (itemData.getTag() == null) { - return new ItemStack(itemEntry.getJavaId(), itemData.getCount(), new com.github.steveice10.opennbt.tag.builtin.CompoundTag("")); - } - return new ItemStack(itemEntry.getJavaId(), itemData.getCount(), this.translateToJavaNBT(itemData.getTag())); - } - - public abstract List getAppliedItems(); - - public CompoundTag translateNbtToBedrock(com.github.steveice10.opennbt.tag.builtin.CompoundTag tag) { - Map> javaValue = new HashMap>(); - if (tag.getValue() != null && !tag.getValue().isEmpty()) { - for (String str : tag.getValue().keySet()) { - com.github.steveice10.opennbt.tag.builtin.Tag javaTag = tag.get(str); - com.nukkitx.nbt.tag.Tag translatedTag = translateToBedrockNBT(javaTag); - if (translatedTag == null) - continue; - - javaValue.put(translatedTag.getName(), translatedTag); - } - } - - com.nukkitx.nbt.tag.CompoundTag bedrockTag = new com.nukkitx.nbt.tag.CompoundTag(tag.getName(), javaValue); - return bedrockTag; - } - - private com.nukkitx.nbt.tag.Tag translateToBedrockNBT(com.github.steveice10.opennbt.tag.builtin.Tag tag) { - if (tag instanceof ByteArrayTag) { - ByteArrayTag byteArrayTag = (ByteArrayTag) tag; - return new com.nukkitx.nbt.tag.ByteArrayTag(byteArrayTag.getName(), byteArrayTag.getValue()); - } - - if (tag instanceof ByteTag) { - ByteTag byteTag = (ByteTag) tag; - return new com.nukkitx.nbt.tag.ByteTag(byteTag.getName(), byteTag.getValue()); - } - - if (tag instanceof DoubleTag) { - DoubleTag doubleTag = (DoubleTag) tag; - return new com.nukkitx.nbt.tag.DoubleTag(doubleTag.getName(), doubleTag.getValue()); - } - - if (tag instanceof FloatTag) { - FloatTag floatTag = (FloatTag) tag; - return new com.nukkitx.nbt.tag.FloatTag(floatTag.getName(), floatTag.getValue()); - } - - if (tag instanceof IntArrayTag) { - IntArrayTag intArrayTag = (IntArrayTag) tag; - return new com.nukkitx.nbt.tag.IntArrayTag(intArrayTag.getName(), intArrayTag.getValue()); - } - - if (tag instanceof IntTag) { - IntTag intTag = (IntTag) tag; - return new com.nukkitx.nbt.tag.IntTag(intTag.getName(), intTag.getValue()); - } - - if (tag instanceof LongArrayTag) { - LongArrayTag longArrayTag = (LongArrayTag) tag; - return new com.nukkitx.nbt.tag.LongArrayTag(longArrayTag.getName(), longArrayTag.getValue()); - } - - if (tag instanceof LongTag) { - LongTag longTag = (LongTag) tag; - return new com.nukkitx.nbt.tag.LongTag(longTag.getName(), longTag.getValue()); - } - - if (tag instanceof ShortTag) { - ShortTag shortTag = (ShortTag) tag; - return new com.nukkitx.nbt.tag.ShortTag(shortTag.getName(), shortTag.getValue()); - } - - if (tag instanceof StringTag) { - StringTag stringTag = (StringTag) tag; - return new com.nukkitx.nbt.tag.StringTag(stringTag.getName(), stringTag.getValue()); - } - - if (tag instanceof ListTag) { - ListTag listTag = (ListTag) tag; - - List tagList = new ArrayList<>(); - for (com.github.steveice10.opennbt.tag.builtin.Tag value : listTag) { - tagList.add(translateToBedrockNBT(value)); - } - Class clazz = CompoundTag.class; - if (!tagList.isEmpty()) { - clazz = tagList.get(0).getClass(); - } - return new com.nukkitx.nbt.tag.ListTag(listTag.getName(), clazz, tagList); - } - - if (tag instanceof com.github.steveice10.opennbt.tag.builtin.CompoundTag) { - com.github.steveice10.opennbt.tag.builtin.CompoundTag compoundTag = (com.github.steveice10.opennbt.tag.builtin.CompoundTag) tag; - - return translateNbtToBedrock(compoundTag); - } - - return null; - } - - public com.github.steveice10.opennbt.tag.builtin.CompoundTag translateToJavaNBT(com.nukkitx.nbt.tag.CompoundTag tag) { - com.github.steveice10.opennbt.tag.builtin.CompoundTag javaTag = new com.github.steveice10.opennbt.tag.builtin.CompoundTag(tag.getName()); - Map javaValue = javaTag.getValue(); - if (tag.getValue() != null && !tag.getValue().isEmpty()) { - for (String str : tag.getValue().keySet()) { - com.nukkitx.nbt.tag.Tag bedrockTag = tag.get(str); - com.github.steveice10.opennbt.tag.builtin.Tag translatedTag = translateToJavaNBT(bedrockTag); - if (translatedTag == null) - continue; - - javaValue.put(translatedTag.getName(), translatedTag); - } - } - - javaTag.setValue(javaValue); - return javaTag; - } - - private com.github.steveice10.opennbt.tag.builtin.Tag translateToJavaNBT(com.nukkitx.nbt.tag.Tag tag) { - if (tag instanceof com.nukkitx.nbt.tag.ByteArrayTag) { - com.nukkitx.nbt.tag.ByteArrayTag byteArrayTag = (com.nukkitx.nbt.tag.ByteArrayTag) tag; - return new ByteArrayTag(byteArrayTag.getName(), byteArrayTag.getValue()); - } - - if (tag instanceof com.nukkitx.nbt.tag.ByteTag) { - com.nukkitx.nbt.tag.ByteTag byteTag = (com.nukkitx.nbt.tag.ByteTag) tag; - return new ByteTag(byteTag.getName(), byteTag.getValue()); - } - - if (tag instanceof com.nukkitx.nbt.tag.DoubleTag) { - com.nukkitx.nbt.tag.DoubleTag doubleTag = (com.nukkitx.nbt.tag.DoubleTag) tag; - return new DoubleTag(doubleTag.getName(), doubleTag.getValue()); - } - - if (tag instanceof com.nukkitx.nbt.tag.FloatTag) { - com.nukkitx.nbt.tag.FloatTag floatTag = (com.nukkitx.nbt.tag.FloatTag) tag; - return new FloatTag(floatTag.getName(), floatTag.getValue()); - } - - if (tag instanceof com.nukkitx.nbt.tag.IntArrayTag) { - com.nukkitx.nbt.tag.IntArrayTag intArrayTag = (com.nukkitx.nbt.tag.IntArrayTag) tag; - return new IntArrayTag(intArrayTag.getName(), intArrayTag.getValue()); - } - - if (tag instanceof com.nukkitx.nbt.tag.IntTag) { - com.nukkitx.nbt.tag.IntTag intTag = (com.nukkitx.nbt.tag.IntTag) tag; - return new IntTag(intTag.getName(), intTag.getValue()); - } - - if (tag instanceof com.nukkitx.nbt.tag.LongArrayTag) { - com.nukkitx.nbt.tag.LongArrayTag longArrayTag = (com.nukkitx.nbt.tag.LongArrayTag) tag; - return new LongArrayTag(longArrayTag.getName(), longArrayTag.getValue()); - } - - if (tag instanceof com.nukkitx.nbt.tag.LongTag) { - com.nukkitx.nbt.tag.LongTag longTag = (com.nukkitx.nbt.tag.LongTag) tag; - return new LongTag(longTag.getName(), longTag.getValue()); - } - - if (tag instanceof com.nukkitx.nbt.tag.ShortTag) { - com.nukkitx.nbt.tag.ShortTag shortTag = (com.nukkitx.nbt.tag.ShortTag) tag; - return new ShortTag(shortTag.getName(), shortTag.getValue()); - } - - if (tag instanceof com.nukkitx.nbt.tag.StringTag) { - com.nukkitx.nbt.tag.StringTag stringTag = (com.nukkitx.nbt.tag.StringTag) tag; - return new StringTag(stringTag.getName(), stringTag.getValue()); - } - - if (tag instanceof com.nukkitx.nbt.tag.ListTag) { - com.nukkitx.nbt.tag.ListTag listTag = (com.nukkitx.nbt.tag.ListTag) tag; - - List tags = new ArrayList<>(); - - for (Object value : listTag.getValue()) { - if (!(value instanceof com.nukkitx.nbt.tag.Tag)) - continue; - - com.nukkitx.nbt.tag.Tag tagValue = (com.nukkitx.nbt.tag.Tag) value; - com.github.steveice10.opennbt.tag.builtin.Tag javaTag = translateToJavaNBT(tagValue); - if (javaTag != null) - tags.add(javaTag); - } - return new ListTag(listTag.getName(), tags); - } - - if (tag instanceof com.nukkitx.nbt.tag.CompoundTag) { - com.nukkitx.nbt.tag.CompoundTag compoundTag = (com.nukkitx.nbt.tag.CompoundTag) tag; - return translateToJavaNBT(compoundTag); - } - - return null; - } - - -} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/NbtItemStackTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/NbtItemStackTranslator.java deleted file mode 100644 index 56c780f44..000000000 --- a/connector/src/main/java/org/geysermc/connector/network/translators/NbtItemStackTranslator.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * 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; - -import com.github.steveice10.opennbt.tag.builtin.CompoundTag; -import org.geysermc.connector.network.translators.item.ItemEntry; - -public class NbtItemStackTranslator { - - public void translateToBedrock(CompoundTag itemTag, ItemEntry itemEntry) { - - } - - public void translateToJava(CompoundTag itemTag, ItemEntry itemEntry) { - - } - - public boolean acceptItem(ItemEntry itemEntry) { - return true; - } - -} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/Registry.java b/connector/src/main/java/org/geysermc/connector/network/translators/PacketTranslatorRegistry.java similarity index 55% rename from connector/src/main/java/org/geysermc/connector/network/translators/Registry.java rename to connector/src/main/java/org/geysermc/connector/network/translators/PacketTranslatorRegistry.java index 399ec1a6d..131363317 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/Registry.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/PacketTranslatorRegistry.java @@ -35,33 +35,59 @@ import org.geysermc.connector.network.session.GeyserSession; import com.github.steveice10.packetlib.packet.Packet; import com.nukkitx.protocol.bedrock.BedrockPacket; +import org.reflections.Reflections; -public class Registry { - private final Map, PacketTranslator> MAP = new HashMap<>(); +public class PacketTranslatorRegistry { + private final Map, PacketTranslator> translators = new HashMap<>(); - public static final Registry JAVA = new Registry<>(); - public static final Registry BEDROCK = new Registry<>(); + public static final PacketTranslatorRegistry JAVA_TRANSLATOR = new PacketTranslatorRegistry<>(); + public static final PacketTranslatorRegistry BEDROCK_TRANSLATOR = new PacketTranslatorRegistry<>(); private static final ObjectArrayList> IGNORED_PACKETS = new ObjectArrayList<>(); static { + Reflections ref = new Reflections("org.geysermc.connector.network.translators"); + + for (Class clazz : ref.getTypesAnnotatedWith(Translator.class)) { + Class packet = clazz.getAnnotation(Translator.class).packet(); + + GeyserConnector.getInstance().getLogger().debug("Found annotated translator: " + clazz.getCanonicalName() + " : " + packet.getSimpleName()); + + try { + if (Packet.class.isAssignableFrom(packet)) { + Class targetPacket = (Class) packet; + PacketTranslator translator = (PacketTranslator) clazz.newInstance(); + + JAVA_TRANSLATOR.translators.put(targetPacket, translator); + } else if (BedrockPacket.class.isAssignableFrom(packet)) { + Class targetPacket = (Class) packet; + PacketTranslator translator = (PacketTranslator) clazz.newInstance(); + + BEDROCK_TRANSLATOR.translators.put(targetPacket, translator); + } else { + GeyserConnector.getInstance().getLogger().error("Class " + clazz.getCanonicalName() + " is annotated as a translator but has an invalid target packet."); + } + } catch (InstantiationException | IllegalAccessException e) { + GeyserConnector.getInstance().getLogger().error("Could not instantiate annotated translator " + clazz.getCanonicalName() + "."); + } + } + IGNORED_PACKETS.add(ServerUpdateLightPacket.class); } - public static void registerJava(Class targetPacket, PacketTranslator translator) { - JAVA.MAP.put(targetPacket, translator); + private PacketTranslatorRegistry() { } - public static void registerBedrock(Class targetPacket, PacketTranslator translator) { - BEDROCK.MAP.put(targetPacket, translator); + public static void init() { + // no-op } @SuppressWarnings("unchecked") public

boolean translate(Class clazz, P packet, GeyserSession session) { if (!session.getUpstream().isClosed() && !session.isClosed()) { try { - if (MAP.containsKey(clazz)) { - ((PacketTranslator

) MAP.get(clazz)).translate(packet, session); + if (translators.containsKey(clazz)) { + ((PacketTranslator

) translators.get(clazz)).translate(packet, session); return true; } else { if (!IGNORED_PACKETS.contains(clazz)) diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/Translators.java b/connector/src/main/java/org/geysermc/connector/network/translators/Translators.java deleted file mode 100644 index 03042e3a4..000000000 --- a/connector/src/main/java/org/geysermc/connector/network/translators/Translators.java +++ /dev/null @@ -1,175 +0,0 @@ -/* - * 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; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; - -import com.github.steveice10.mc.protocol.data.game.window.WindowType; -import com.nukkitx.protocol.bedrock.data.ContainerType; -import it.unimi.dsi.fastutil.objects.ObjectArrayList; -import org.geysermc.connector.GeyserConnector; -import org.geysermc.connector.network.translators.world.block.BlockTranslator; -import org.geysermc.connector.network.translators.world.block.entity.*; -import org.geysermc.connector.network.translators.inventory.*; -import org.geysermc.connector.network.translators.inventory.updater.ContainerInventoryUpdater; -import org.geysermc.connector.network.translators.inventory.updater.InventoryUpdater; -import org.geysermc.connector.network.translators.item.ItemTranslator; -import org.reflections.Reflections; - -import com.github.steveice10.packetlib.packet.Packet; -import com.nukkitx.nbt.CompoundTagBuilder; -import com.nukkitx.nbt.NbtUtils; -import com.nukkitx.nbt.stream.NBTOutputStream; -import com.nukkitx.nbt.tag.CompoundTag; -import com.nukkitx.protocol.bedrock.BedrockPacket; - -import lombok.Getter; - -public class Translators { - - @Getter - private static ItemTranslator itemTranslator; - - @Getter - private static Map inventoryTranslators = new HashMap<>(); - - @Getter - private static Map blockEntityTranslators = new HashMap<>(); - - @Getter - private static ObjectArrayList requiresBlockStateMap = new ObjectArrayList<>(); - - private static final CompoundTag EMPTY_TAG = CompoundTagBuilder.builder().buildRootTag(); - public static final byte[] EMPTY_LEVEL_CHUNK_DATA; - - static { - try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) { - outputStream.write(new byte[258]); // Biomes + Border Size + Extra Data Size - - try (NBTOutputStream stream = NbtUtils.createNetworkWriter(outputStream)) { - stream.write(EMPTY_TAG); - } - - EMPTY_LEVEL_CHUNK_DATA = outputStream.toByteArray(); - }catch (IOException e) { - throw new AssertionError("Unable to generate empty level chunk data"); - } - } - - @SuppressWarnings("unchecked") - public static void start() { - Reflections ref = new Reflections("org.geysermc.connector.network.translators"); - - for (Class clazz : ref.getTypesAnnotatedWith(Translator.class)) { - Class packet = clazz.getAnnotation(Translator.class).packet(); - - GeyserConnector.getInstance().getLogger().debug("Found annotated translator: " + clazz.getCanonicalName() + " : " + packet.getSimpleName()); - - try { - if (Packet.class.isAssignableFrom(packet)) { - Class targetPacket = (Class) packet; - PacketTranslator translator = (PacketTranslator) clazz.newInstance(); - - Registry.registerJava(targetPacket, translator); - - } else if (BedrockPacket.class.isAssignableFrom(packet)) { - Class targetPacket = (Class) packet; - PacketTranslator translator = (PacketTranslator) clazz.newInstance(); - - Registry.registerBedrock(targetPacket, translator); - - } else { - GeyserConnector.getInstance().getLogger().error("Class " + clazz.getCanonicalName() + " is annotated as a translator but has an invalid target packet."); - } - } catch (InstantiationException | IllegalAccessException e) { - GeyserConnector.getInstance().getLogger().error("Could not instantiate annotated translator " + clazz.getCanonicalName() + "."); - } - } - - itemTranslator = new ItemTranslator(); - itemTranslator.init(); - BlockTranslator.init(); - - registerBlockEntityTranslators(); - registerInventoryTranslators(); - } - - private static void registerBlockEntityTranslators() { - Reflections ref = new Reflections("org.geysermc.connector.network.translators.world.block.entity"); - - for (Class clazz : ref.getTypesAnnotatedWith(BlockEntity.class)) { - - GeyserConnector.getInstance().getLogger().debug("Found annotated block entity: " + clazz.getCanonicalName()); - - try { - blockEntityTranslators.put(clazz.getAnnotation(BlockEntity.class).name(), (BlockEntityTranslator) clazz.newInstance()); - } catch (InstantiationException | IllegalAccessException e) { - GeyserConnector.getInstance().getLogger().error("Could not instantiate annotated block entity " + clazz.getCanonicalName() + "."); - } - } - - for (Class clazz : ref.getSubTypesOf(RequiresBlockState.class)) { - - GeyserConnector.getInstance().getLogger().debug("Found block entity that requires block state: " + clazz.getCanonicalName()); - - try { - requiresBlockStateMap.add((RequiresBlockState) clazz.newInstance()); - } catch (InstantiationException | IllegalAccessException e) { - GeyserConnector.getInstance().getLogger().error("Could not instantiate required block state " + clazz.getCanonicalName() + "."); - } - - } - } - - private static void registerInventoryTranslators() { - inventoryTranslators.put(null, new PlayerInventoryTranslator()); //player inventory - inventoryTranslators.put(WindowType.GENERIC_9X1, new SingleChestInventoryTranslator(9)); - inventoryTranslators.put(WindowType.GENERIC_9X2, new SingleChestInventoryTranslator(18)); - inventoryTranslators.put(WindowType.GENERIC_9X3, new SingleChestInventoryTranslator(27)); - inventoryTranslators.put(WindowType.GENERIC_9X4, new DoubleChestInventoryTranslator(36)); - inventoryTranslators.put(WindowType.GENERIC_9X5, new DoubleChestInventoryTranslator(45)); - inventoryTranslators.put(WindowType.GENERIC_9X6, new DoubleChestInventoryTranslator(54)); - inventoryTranslators.put(WindowType.BREWING_STAND, new BrewingInventoryTranslator()); - inventoryTranslators.put(WindowType.ANVIL, new AnvilInventoryTranslator()); - inventoryTranslators.put(WindowType.CRAFTING, new CraftingInventoryTranslator()); - inventoryTranslators.put(WindowType.GRINDSTONE, new GrindstoneInventoryTranslator()); - //inventoryTranslators.put(WindowType.ENCHANTMENT, new EnchantmentInventoryTranslator()); //TODO - - InventoryTranslator furnace = new FurnaceInventoryTranslator(); - inventoryTranslators.put(WindowType.FURNACE, furnace); - inventoryTranslators.put(WindowType.BLAST_FURNACE, furnace); - inventoryTranslators.put(WindowType.SMOKER, furnace); - - InventoryUpdater containerUpdater = new ContainerInventoryUpdater(); - inventoryTranslators.put(WindowType.GENERIC_3X3, new BlockInventoryTranslator(9, "minecraft:dispenser[facing=north,triggered=false]", ContainerType.DISPENSER, containerUpdater)); - inventoryTranslators.put(WindowType.HOPPER, new BlockInventoryTranslator(5, "minecraft:hopper[enabled=false,facing=down]", ContainerType.HOPPER, containerUpdater)); - inventoryTranslators.put(WindowType.SHULKER_BOX, new BlockInventoryTranslator(27, "minecraft:shulker_box[facing=north]", ContainerType.CONTAINER, containerUpdater)); - //inventoryTranslators.put(WindowType.BEACON, new BlockInventoryTranslator(1, "minecraft:beacon", ContainerType.BEACON)); //TODO - } -} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockBlockPickRequestPacketTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockBlockPickRequestPacketTranslator.java index 288b99d31..04fe8dbf3 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockBlockPickRequestPacketTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockBlockPickRequestPacketTranslator.java @@ -31,15 +31,13 @@ import com.github.steveice10.mc.protocol.packet.ingame.client.window.ClientMoveI import com.nukkitx.math.vector.Vector3i; import com.nukkitx.protocol.bedrock.packet.BlockPickRequestPacket; import com.nukkitx.protocol.bedrock.packet.PlayerHotbarPacket; -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.PacketTranslator; import org.geysermc.connector.network.translators.Translator; import org.geysermc.connector.network.translators.item.ItemEntry; +import org.geysermc.connector.network.translators.item.ItemRegistry; import org.geysermc.connector.network.translators.world.block.BlockTranslator; -import org.geysermc.connector.network.translators.item.ItemTranslator; -import org.geysermc.connector.network.translators.Translators; @Translator(packet = BlockPickRequestPacket.class) public class BedrockBlockPickRequestPacketTranslator extends PacketTranslator { @@ -61,14 +59,13 @@ public class BedrockBlockPickRequestPacketTranslator extends PacketTranslator { @@ -51,7 +51,7 @@ public class BedrockInteractTranslator extends PacketTranslator switch (packet.getAction()) { case INTERACT: - if (session.getInventory().getItem(session.getInventory().getHeldItemSlot() + 36).getId() == ItemTranslator.SHIELD) { + if (session.getInventory().getItem(session.getInventory().getHeldItemSlot() + 36).getId() == ItemRegistry.SHIELD) { break; } ClientPlayerInteractEntityPacket interactPacket = new ClientPlayerInteractEntityPacket((int) entity.getEntityId(), diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockInventoryTransactionTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockInventoryTransactionTranslator.java index 03f7a112a..8f96b8004 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockInventoryTransactionTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockInventoryTransactionTranslator.java @@ -49,9 +49,9 @@ import org.geysermc.connector.inventory.Inventory; 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.inventory.InventoryTranslator; import org.geysermc.connector.network.translators.item.ItemEntry; -import org.geysermc.connector.network.translators.item.ItemTranslator; +import org.geysermc.connector.network.translators.item.ItemRegistry; import org.geysermc.connector.network.translators.sound.EntitySoundInteractionHandler; import org.geysermc.connector.network.translators.world.block.BlockTranslator; import org.geysermc.connector.utils.InventoryUtils; @@ -65,12 +65,12 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator EFFECTS = new HashMap<>(); public static final Int2ObjectMap RECORDS = new Int2ObjectOpenHashMap<>(); @@ -57,10 +58,10 @@ public class EffectUtils { static { /* Load particles */ - InputStream particleStream = Toolbox.getResource("mappings/particles.json"); + InputStream particleStream = FileUtils.getResource("mappings/particles.json"); JsonNode particleEntries; try { - particleEntries = Toolbox.JSON_MAPPER.readTree(particleStream); + particleEntries = GeyserConnector.JSON_MAPPER.readTree(particleStream); } catch (Exception e) { throw new AssertionError("Unable to load particle map", e); } @@ -69,10 +70,10 @@ public class EffectUtils { while (particlesIterator.hasNext()) { Map.Entry entry = particlesIterator.next(); try { - setIdentifier(ParticleType.valueOf(entry.getKey().toUpperCase()), LevelEventType.valueOf(entry.getValue().asText().toUpperCase())); + particleTypeMap.put(ParticleType.valueOf(entry.getKey().toUpperCase()), LevelEventType.valueOf(entry.getValue().asText().toUpperCase())); } catch (IllegalArgumentException e1) { try { - setIdentifier(ParticleType.valueOf(entry.getKey().toUpperCase()), entry.getValue().asText()); + particleStringMap.put(ParticleType.valueOf(entry.getKey().toUpperCase()), entry.getValue().asText()); GeyserConnector.getInstance().getLogger().debug("Force to map particle " + entry.getKey() + "=>" @@ -85,10 +86,10 @@ public class EffectUtils { } /* Load effects */ - InputStream effectsStream = Toolbox.getResource("mappings/effects.json"); + InputStream effectsStream = FileUtils.getResource("mappings/effects.json"); JsonNode effects; try { - effects = Toolbox.JSON_MAPPER.readTree(effectsStream); + effects = GeyserConnector.JSON_MAPPER.readTree(effectsStream); } catch (Exception e) { throw new AssertionError("Unable to load effects mappings", e); } @@ -112,14 +113,6 @@ public class EffectUtils { } } - 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); } @@ -127,5 +120,4 @@ public class EffectUtils { public static String getParticleString(@NonNull ParticleType type){ return particleStringMap.getOrDefault(type, null); } - } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/InventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/InventoryTranslator.java index 2a5afb8c0..7b4b26e62 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/InventoryTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/InventoryTranslator.java @@ -25,15 +25,50 @@ package org.geysermc.connector.network.translators.inventory; +import com.github.steveice10.mc.protocol.data.game.window.WindowType; +import com.nukkitx.protocol.bedrock.data.ContainerType; import com.nukkitx.protocol.bedrock.data.InventoryActionData; import lombok.AllArgsConstructor; import org.geysermc.connector.inventory.Inventory; import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.inventory.updater.ContainerInventoryUpdater; +import org.geysermc.connector.network.translators.inventory.updater.InventoryUpdater; +import java.util.HashMap; import java.util.List; +import java.util.Map; @AllArgsConstructor public abstract class InventoryTranslator { + + public static final Map INVENTORY_TRANSLATORS = new HashMap() { + { + put(null, new PlayerInventoryTranslator()); //player inventory + put(WindowType.GENERIC_9X1, new SingleChestInventoryTranslator(9)); + put(WindowType.GENERIC_9X2, new SingleChestInventoryTranslator(18)); + put(WindowType.GENERIC_9X3, new SingleChestInventoryTranslator(27)); + put(WindowType.GENERIC_9X4, new DoubleChestInventoryTranslator(36)); + put(WindowType.GENERIC_9X5, new DoubleChestInventoryTranslator(45)); + put(WindowType.GENERIC_9X6, new DoubleChestInventoryTranslator(54)); + put(WindowType.BREWING_STAND, new BrewingInventoryTranslator()); + put(WindowType.ANVIL, new AnvilInventoryTranslator()); + put(WindowType.CRAFTING, new CraftingInventoryTranslator()); + put(WindowType.GRINDSTONE, new GrindstoneInventoryTranslator()); + //put(WindowType.ENCHANTMENT, new EnchantmentInventoryTranslator()); //TODO + + InventoryTranslator furnace = new FurnaceInventoryTranslator(); + put(WindowType.FURNACE, furnace); + put(WindowType.BLAST_FURNACE, furnace); + put(WindowType.SMOKER, furnace); + + InventoryUpdater containerUpdater = new ContainerInventoryUpdater(); + put(WindowType.GENERIC_3X3, new BlockInventoryTranslator(9, "minecraft:dispenser[facing=north,triggered=false]", ContainerType.DISPENSER, containerUpdater)); + put(WindowType.HOPPER, new BlockInventoryTranslator(5, "minecraft:hopper[enabled=false,facing=down]", ContainerType.HOPPER, containerUpdater)); + put(WindowType.SHULKER_BOX, new BlockInventoryTranslator(27, "minecraft:shulker_box[facing=north]", ContainerType.CONTAINER, containerUpdater)); + //put(WindowType.BEACON, new BlockInventoryTranslator(1, "minecraft:beacon", ContainerType.BEACON)); //TODO + } + }; + public final int size; public abstract void prepareInventory(GeyserSession session, Inventory inventory); diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/PlayerInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/PlayerInventoryTranslator.java index 5beea2a2d..055b69efd 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/PlayerInventoryTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/PlayerInventoryTranslator.java @@ -36,10 +36,9 @@ import com.nukkitx.protocol.bedrock.packet.InventoryContentPacket; import com.nukkitx.protocol.bedrock.packet.InventorySlotPacket; import org.geysermc.connector.inventory.Inventory; import org.geysermc.connector.network.session.GeyserSession; -import org.geysermc.connector.network.translators.Translators; import org.geysermc.connector.network.translators.inventory.action.InventoryActionDataTranslator; +import org.geysermc.connector.network.translators.item.ItemTranslator; import org.geysermc.connector.utils.InventoryUtils; -import org.geysermc.connector.utils.Toolbox; import java.util.List; @@ -60,11 +59,11 @@ public class PlayerInventoryTranslator extends InventoryTranslator { ItemData[] contents = new ItemData[36]; // Inventory for (int i = 9; i < 36; i++) { - contents[i] = Translators.getItemTranslator().translateToBedrock(session, inventory.getItem(i)); + contents[i] = ItemTranslator.translateToBedrock(inventory.getItem(i)); } // Hotbar for (int i = 36; i < 45; i++) { - contents[i - 36] = Translators.getItemTranslator().translateToBedrock(session, inventory.getItem(i)); + contents[i - 36] = ItemTranslator.translateToBedrock(inventory.getItem(i)); } inventoryContentPacket.setContents(contents); session.sendUpstreamPacket(inventoryContentPacket); @@ -74,7 +73,7 @@ public class PlayerInventoryTranslator extends InventoryTranslator { armorContentPacket.setContainerId(ContainerId.ARMOR); contents = new ItemData[4]; for (int i = 5; i < 9; i++) { - contents[i - 5] = Translators.getItemTranslator().translateToBedrock(session, inventory.getItem(i)); + contents[i - 5] = ItemTranslator.translateToBedrock(inventory.getItem(i)); } armorContentPacket.setContents(contents); session.sendUpstreamPacket(armorContentPacket); @@ -82,7 +81,7 @@ public class PlayerInventoryTranslator extends InventoryTranslator { // Offhand InventoryContentPacket offhandPacket = new InventoryContentPacket(); offhandPacket.setContainerId(ContainerId.OFFHAND); - offhandPacket.setContents(new ItemData[]{Translators.getItemTranslator().translateToBedrock(session, inventory.getItem(45))}); + offhandPacket.setContents(new ItemData[]{ItemTranslator.translateToBedrock(inventory.getItem(45))}); session.sendUpstreamPacket(offhandPacket); } @@ -101,7 +100,7 @@ public class PlayerInventoryTranslator extends InventoryTranslator { if (session.getGameMode() == GameMode.CREATIVE) { slotPacket.setItem(UNUSUABLE_CRAFTING_SPACE_BLOCK); }else{ - slotPacket.setItem(Translators.getItemTranslator().translateToBedrock(session, inventory.getItem(i))); + slotPacket.setItem(ItemTranslator.translateToBedrock(inventory.getItem(i))); } session.sendUpstreamPacket(slotPacket); @@ -126,12 +125,12 @@ public class PlayerInventoryTranslator extends InventoryTranslator { slotPacket.setContainerId(ContainerId.CURSOR); slotPacket.setSlot(slot + 27); } - slotPacket.setItem(Translators.getItemTranslator().translateToBedrock(session, inventory.getItem(slot))); + slotPacket.setItem(ItemTranslator.translateToBedrock(inventory.getItem(slot))); session.sendUpstreamPacket(slotPacket); } else if (slot == 45) { InventoryContentPacket offhandPacket = new InventoryContentPacket(); offhandPacket.setContainerId(ContainerId.OFFHAND); - offhandPacket.setContents(new ItemData[]{Translators.getItemTranslator().translateToBedrock(session, inventory.getItem(slot))}); + offhandPacket.setContents(new ItemData[]{ItemTranslator.translateToBedrock(inventory.getItem(slot))}); session.sendUpstreamPacket(offhandPacket); } } @@ -202,7 +201,7 @@ public class PlayerInventoryTranslator extends InventoryTranslator { if (action.getToItem().getId() == 0) { javaItem = new ItemStack(-1, 0, null); } else { - javaItem = Translators.getItemTranslator().translateToJava(session, action.getToItem()); + javaItem = ItemTranslator.translateToJava(action.getToItem()); } ClientCreativeInventoryActionPacket creativePacket = new ClientCreativeInventoryActionPacket(javaSlot, javaItem); session.sendDownstreamPacket(creativePacket); @@ -210,13 +209,13 @@ public class PlayerInventoryTranslator extends InventoryTranslator { break; case ContainerId.CURSOR: if (action.getSlot() == 0) { - session.getInventory().setCursor(Translators.getItemTranslator().translateToJava(session, action.getToItem())); + session.getInventory().setCursor(ItemTranslator.translateToJava(action.getToItem())); } break; case ContainerId.NONE: if (action.getSource().getType() == InventorySource.Type.WORLD_INTERACTION && action.getSource().getFlag() == InventorySource.Flag.DROP_ITEM) { - javaItem = Translators.getItemTranslator().translateToJava(session, action.getToItem()); + javaItem = ItemTranslator.translateToJava(action.getToItem()); ClientCreativeInventoryActionPacket creativeDropPacket = new ClientCreativeInventoryActionPacket(-1, javaItem); session.sendDownstreamPacket(creativeDropPacket); } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/action/InventoryActionDataTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/action/InventoryActionDataTranslator.java index 0c2677753..9139da1fd 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/action/InventoryActionDataTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/action/InventoryActionDataTranslator.java @@ -38,9 +38,9 @@ import com.nukkitx.protocol.bedrock.data.InventorySource; import com.nukkitx.protocol.bedrock.data.ItemData; import org.geysermc.connector.inventory.Inventory; import org.geysermc.connector.network.session.GeyserSession; -import org.geysermc.connector.network.translators.Translators; import org.geysermc.connector.network.translators.inventory.InventoryTranslator; import org.geysermc.connector.network.translators.inventory.SlotType; +import org.geysermc.connector.network.translators.item.ItemTranslator; import org.geysermc.connector.utils.InventoryUtils; import java.util.*; @@ -61,13 +61,13 @@ public class InventoryActionDataTranslator { worldAction = action; } else if (action.getSource().getContainerId() == ContainerId.CURSOR && action.getSlot() == 0) { cursorAction = action; - ItemData translatedCursor = Translators.getItemTranslator().translateToBedrock(session, session.getInventory().getCursor()); + ItemData translatedCursor = ItemTranslator.translateToBedrock(session.getInventory().getCursor()); if (!translatedCursor.equals(action.getFromItem())) { refresh = true; } } else { containerAction = action; - ItemData translatedItem = Translators.getItemTranslator().translateToBedrock(session, inventory.getItem(translator.bedrockSlotToJava(action))); + ItemData translatedItem = ItemTranslator.translateToBedrock(inventory.getItem(translator.bedrockSlotToJava(action))); if (!translatedItem.equals(action.getFromItem())) { refresh = true; } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/ChestInventoryUpdater.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/ChestInventoryUpdater.java index 6656cc830..61bbda501 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/ChestInventoryUpdater.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/ChestInventoryUpdater.java @@ -31,8 +31,8 @@ import com.nukkitx.protocol.bedrock.packet.InventorySlotPacket; import lombok.AllArgsConstructor; import org.geysermc.connector.inventory.Inventory; import org.geysermc.connector.network.session.GeyserSession; -import org.geysermc.connector.network.translators.Translators; import org.geysermc.connector.network.translators.inventory.InventoryTranslator; +import org.geysermc.connector.network.translators.item.ItemTranslator; import org.geysermc.connector.utils.InventoryUtils; @AllArgsConstructor @@ -49,7 +49,7 @@ public class ChestInventoryUpdater extends InventoryUpdater { ItemData[] bedrockItems = new ItemData[paddedSize]; for (int i = 0; i < bedrockItems.length; i++) { if (i < translator.size) { - bedrockItems[i] = Translators.getItemTranslator().translateToBedrock(session, inventory.getItem(i)); + bedrockItems[i] = ItemTranslator.translateToBedrock(inventory.getItem(i)); } else { bedrockItems[i] = UNUSUABLE_SPACE_BLOCK; } @@ -69,7 +69,7 @@ public class ChestInventoryUpdater extends InventoryUpdater { InventorySlotPacket slotPacket = new InventorySlotPacket(); slotPacket.setContainerId(inventory.getId()); slotPacket.setSlot(translator.javaSlotToBedrock(javaSlot)); - slotPacket.setItem(Translators.getItemTranslator().translateToBedrock(session, inventory.getItem(javaSlot))); + slotPacket.setItem(ItemTranslator.translateToBedrock(inventory.getItem(javaSlot))); session.sendUpstreamPacket(slotPacket); return true; } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/ContainerInventoryUpdater.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/ContainerInventoryUpdater.java index d25705e28..e84c29310 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/ContainerInventoryUpdater.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/ContainerInventoryUpdater.java @@ -30,8 +30,8 @@ import com.nukkitx.protocol.bedrock.packet.InventoryContentPacket; import com.nukkitx.protocol.bedrock.packet.InventorySlotPacket; import org.geysermc.connector.inventory.Inventory; import org.geysermc.connector.network.session.GeyserSession; -import org.geysermc.connector.network.translators.Translators; import org.geysermc.connector.network.translators.inventory.InventoryTranslator; +import org.geysermc.connector.network.translators.item.ItemTranslator; public class ContainerInventoryUpdater extends InventoryUpdater { @Override @@ -40,7 +40,7 @@ public class ContainerInventoryUpdater extends InventoryUpdater { ItemData[] bedrockItems = new ItemData[translator.size]; for (int i = 0; i < bedrockItems.length; i++) { - bedrockItems[translator.javaSlotToBedrock(i)] = Translators.getItemTranslator().translateToBedrock(session, inventory.getItem(i)); + bedrockItems[translator.javaSlotToBedrock(i)] = ItemTranslator.translateToBedrock(inventory.getItem(i)); } InventoryContentPacket contentPacket = new InventoryContentPacket(); @@ -57,7 +57,7 @@ public class ContainerInventoryUpdater extends InventoryUpdater { InventorySlotPacket slotPacket = new InventorySlotPacket(); slotPacket.setContainerId(inventory.getId()); slotPacket.setSlot(translator.javaSlotToBedrock(javaSlot)); - slotPacket.setItem(Translators.getItemTranslator().translateToBedrock(session, inventory.getItem(javaSlot))); + slotPacket.setItem(ItemTranslator.translateToBedrock(inventory.getItem(javaSlot))); session.sendUpstreamPacket(slotPacket); return true; } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/CursorInventoryUpdater.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/CursorInventoryUpdater.java index 6a93ecd3c..aa7a01746 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/CursorInventoryUpdater.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/CursorInventoryUpdater.java @@ -29,8 +29,8 @@ import com.nukkitx.protocol.bedrock.data.ContainerId; import com.nukkitx.protocol.bedrock.packet.InventorySlotPacket; import org.geysermc.connector.inventory.Inventory; import org.geysermc.connector.network.session.GeyserSession; -import org.geysermc.connector.network.translators.Translators; import org.geysermc.connector.network.translators.inventory.InventoryTranslator; +import org.geysermc.connector.network.translators.item.ItemTranslator; public class CursorInventoryUpdater extends InventoryUpdater { @Override @@ -44,7 +44,7 @@ public class CursorInventoryUpdater extends InventoryUpdater { InventorySlotPacket slotPacket = new InventorySlotPacket(); slotPacket.setContainerId(ContainerId.CURSOR); slotPacket.setSlot(bedrockSlot); - slotPacket.setItem(Translators.getItemTranslator().translateToBedrock(session, inventory.getItem(i))); + slotPacket.setItem(ItemTranslator.translateToBedrock(inventory.getItem(i))); session.sendUpstreamPacket(slotPacket); } } @@ -57,7 +57,7 @@ public class CursorInventoryUpdater extends InventoryUpdater { InventorySlotPacket slotPacket = new InventorySlotPacket(); slotPacket.setContainerId(ContainerId.CURSOR); slotPacket.setSlot(translator.javaSlotToBedrock(javaSlot)); - slotPacket.setItem(Translators.getItemTranslator().translateToBedrock(session, inventory.getItem(javaSlot))); + slotPacket.setItem(ItemTranslator.translateToBedrock(inventory.getItem(javaSlot))); session.sendUpstreamPacket(slotPacket); return true; } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/InventoryUpdater.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/InventoryUpdater.java index ebca038a2..9710d8057 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/InventoryUpdater.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/InventoryUpdater.java @@ -31,15 +31,15 @@ import com.nukkitx.protocol.bedrock.packet.InventoryContentPacket; import com.nukkitx.protocol.bedrock.packet.InventorySlotPacket; import org.geysermc.connector.inventory.Inventory; import org.geysermc.connector.network.session.GeyserSession; -import org.geysermc.connector.network.translators.Translators; import org.geysermc.connector.network.translators.inventory.InventoryTranslator; +import org.geysermc.connector.network.translators.item.ItemTranslator; public abstract class InventoryUpdater { public void updateInventory(InventoryTranslator translator, GeyserSession session, Inventory inventory) { ItemData[] bedrockItems = new ItemData[36]; for (int i = 0; i < 36; i++) { final int offset = i < 9 ? 27 : -9; - bedrockItems[i] = Translators.getItemTranslator().translateToBedrock(session, inventory.getItem(translator.size + i + offset)); + bedrockItems[i] = ItemTranslator.translateToBedrock(inventory.getItem(translator.size + i + offset)); } InventoryContentPacket contentPacket = new InventoryContentPacket(); contentPacket.setContainerId(ContainerId.INVENTORY); @@ -52,7 +52,7 @@ public abstract class InventoryUpdater { InventorySlotPacket slotPacket = new InventorySlotPacket(); slotPacket.setContainerId(ContainerId.INVENTORY); slotPacket.setSlot(translator.javaSlotToBedrock(javaSlot)); - slotPacket.setItem(Translators.getItemTranslator().translateToBedrock(session, inventory.getItem(javaSlot))); + slotPacket.setItem(ItemTranslator.translateToBedrock(inventory.getItem(javaSlot))); session.sendUpstreamPacket(slotPacket); return true; } diff --git a/connector/src/main/java/org/geysermc/connector/utils/Toolbox.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemRegistry.java similarity index 52% rename from connector/src/main/java/org/geysermc/connector/utils/Toolbox.java rename to connector/src/main/java/org/geysermc/connector/network/translators/item/ItemRegistry.java index 953b70a8a..ed99ece31 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/Toolbox.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemRegistry.java @@ -1,91 +1,85 @@ /* * 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: + * 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 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. + * 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 * - * @author GeyserMC - * @link https://github.com/GeyserMC/Geyser */ -package org.geysermc.connector.utils; +package org.geysermc.connector.network.translators.item; import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; +import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; import com.nukkitx.nbt.NbtUtils; -import com.nukkitx.nbt.stream.NBTInputStream; -import com.nukkitx.nbt.tag.CompoundTag; import com.nukkitx.protocol.bedrock.data.ItemData; import com.nukkitx.protocol.bedrock.packet.StartGamePacket; - import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; - import org.geysermc.connector.GeyserConnector; -import org.geysermc.connector.network.translators.item.ItemEntry; -import org.geysermc.connector.network.translators.item.ToolItemEntry; -import org.geysermc.connector.network.translators.sound.SoundHandlerRegistry; +import org.geysermc.connector.utils.FileUtils; -import java.io.*; -import java.util.*; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Base64; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; -public class Toolbox { +/** + * Registry for anything item related. + */ +public class ItemRegistry { + + private static final Map JAVA_IDENTIFIER_MAP = new HashMap<>(); - public static final ObjectMapper JSON_MAPPER = new ObjectMapper().disable(DeserializationFeature.FAIL_ON_IGNORED_PROPERTIES); - public static final CompoundTag BIOMES; public static final ItemData[] CREATIVE_ITEMS; public static final List ITEMS = new ArrayList<>(); - public static final Int2ObjectMap ITEM_ENTRIES = new Int2ObjectOpenHashMap<>(); - public static CompoundTag ENTITY_IDENTIFIERS; + // Shield ID, used in Entity.java + public static final int SHIELD = 829; + // Boat ID, used in BedrockInventoryTransactionTranslator.java + public static final int BOAT = 333; public static int BARRIER_INDEX = 0; + public static void init() { + // no-op + } + static { - /* Load biomes */ - InputStream biomestream = GeyserConnector.class.getClassLoader().getResourceAsStream("bedrock/biome_definitions.dat"); - if (biomestream == null) { - throw new AssertionError("Unable to find bedrock/biome_definitions.dat"); - } - - CompoundTag biomesTag; - - try (NBTInputStream biomenbtInputStream = NbtUtils.createNetworkReader(biomestream)){ - biomesTag = (CompoundTag) biomenbtInputStream.readTag(); - BIOMES = biomesTag; - } catch (Exception ex) { - GeyserConnector.getInstance().getLogger().warning("Failed to get biomes from biome definitions, is there something wrong with the file?"); - throw new AssertionError(ex); - } - /* Load item palette */ - InputStream stream = getResource("bedrock/items.json"); + InputStream stream = FileUtils.getResource("bedrock/items.json"); TypeReference> itemEntriesType = new TypeReference>() { }; List itemEntries; try { - itemEntries = JSON_MAPPER.readValue(stream, itemEntriesType); + itemEntries = GeyserConnector.JSON_MAPPER.readValue(stream, itemEntriesType); } catch (Exception e) { throw new AssertionError("Unable to load Bedrock runtime item IDs", e); } @@ -94,11 +88,11 @@ public class Toolbox { ITEMS.add(new StartGamePacket.ItemEntry(entry.get("name").textValue(), (short) entry.get("id").intValue())); } - stream = getResource("mappings/items.json"); + stream = FileUtils.getResource("mappings/items.json"); JsonNode items; try { - items = JSON_MAPPER.readTree(stream); + items = GeyserConnector.JSON_MAPPER.readTree(stream); } catch (Exception e) { throw new AssertionError("Unable to load Java runtime item IDs", e); } @@ -139,22 +133,12 @@ public class Toolbox { itemIndex++; } - // Load particle/effect mappings - EffectUtils.init(); - // Load sound mappings - SoundUtils.init(); - // Load the locale data - LocaleUtils.init(); - - // Load sound handlers - SoundHandlerRegistry.init(); - /* Load creative items */ - stream = getResource("bedrock/creative_items.json"); + stream = FileUtils.getResource("bedrock/creative_items.json"); JsonNode creativeItemEntries; try { - creativeItemEntries = JSON_MAPPER.readTree(stream).get("items"); + creativeItemEntries = GeyserConnector.JSON_MAPPER.readTree(stream).get("items"); } catch (Exception e) { throw new AssertionError("Unable to load creative items", e); } @@ -179,33 +163,51 @@ public class Toolbox { } } CREATIVE_ITEMS = creativeItems.toArray(new ItemData[0]); - - - /* Load entity identifiers */ - stream = Toolbox.getResource("bedrock/entity_identifiers.dat"); - - try (NBTInputStream nbtInputStream = NbtUtils.createNetworkReader(stream)) { - ENTITY_IDENTIFIERS = (CompoundTag) nbtInputStream.readTag(); - } catch (Exception e) { - throw new AssertionError("Unable to get entities from entity identifiers", e); - } } /** - * Get an InputStream for the given resource path, throws AssertionError if resource is not found + * Gets an {@link ItemEntry} from the given {@link ItemStack}. * - * @param resource Resource to get - * @return InputStream of the given resource + * @param stack the item stack + * @return an item entry from the given item stack */ - public static InputStream getResource(String resource) { - InputStream stream = Toolbox.class.getClassLoader().getResourceAsStream(resource); - if (stream == null) { - throw new AssertionError("Unable to find resource: " + resource); - } - return stream; + public static ItemEntry getItem(ItemStack stack) { + return ITEM_ENTRIES.get(stack.getId()); } - public static void init() { - // no-op + /** + * Gets an {@link ItemEntry} from the given {@link ItemData}. + * + * @param data the item data + * @return an item entry from the given item data + */ + public static ItemEntry getItem(ItemData data) { + for (ItemEntry itemEntry : ITEM_ENTRIES.values()) { + if (itemEntry.getBedrockId() == data.getId() && (itemEntry.getBedrockData() == data.getDamage() || itemEntry.getJavaIdentifier().endsWith("potion"))) { + return itemEntry; + } + } + // If item find was unsuccessful first time, we try again while ignoring damage + // Fixes piston, sticky pistons, dispensers and droppers turning into air from creative inventory + for (ItemEntry itemEntry : ITEM_ENTRIES.values()) { + if (itemEntry.getBedrockId() == data.getId()) { + return itemEntry; + } + } + + GeyserConnector.getInstance().getLogger().debug("Missing mapping for bedrock item " + data.getId() + ":" + data.getDamage()); + return ItemEntry.AIR; } -} \ No newline at end of file + + /** + * Gets an {@link ItemEntry} from the given Minecraft: Java Edition + * block state identifier. + * + * @param javaIdentifier the block state identifier + * @return an item entry from the given java edition identifier + */ + public static ItemEntry getItemEntry(String javaIdentifier) { + return JAVA_IDENTIFIER_MAP.computeIfAbsent(javaIdentifier, key -> ITEM_ENTRIES.values() + .stream().filter(itemEntry -> itemEntry.getJavaIdentifier().equals(key)).findFirst().orElse(null)); + } +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemTranslator.java index 287669713..490681d8e 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemTranslator.java @@ -1,57 +1,63 @@ /* * 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: + * 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 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. + * 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 * - * @author GeyserMC - * @link https://github.com/GeyserMC/Geyser */ package org.geysermc.connector.network.translators.item; import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; +import com.github.steveice10.opennbt.tag.builtin.*; +import com.nukkitx.nbt.tag.CompoundTag; +import com.nukkitx.nbt.tag.Tag; import com.nukkitx.protocol.bedrock.data.ItemData; - import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import org.geysermc.connector.GeyserConnector; - -import org.geysermc.connector.network.session.GeyserSession; -import org.geysermc.connector.network.translators.*; -import org.geysermc.connector.utils.Toolbox; +import org.geysermc.connector.network.translators.ItemRemapper; import org.reflections.Reflections; -import java.util.*; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; import java.util.stream.Collectors; -public class ItemTranslator { +public abstract class ItemTranslator { - private Int2ObjectMap itemTranslators = new Int2ObjectOpenHashMap(); - private List nbtItemTranslators; - private Map javaIdentifierMap = new HashMap<>(); + private static final Int2ObjectMap ITEM_STACK_TRANSLATORS = new Int2ObjectOpenHashMap<>(); + private static final List NBT_TRANSLATORS; - // Shield ID, used in Entity.java - public static final int SHIELD = 829; - // Boat ID, used in BedrockInventoryTransactionTranslator.java - public static final int BOAT = 333; + protected ItemTranslator() { + } - public void init() { + public static void init() { + // no-op + } + + static { + /* Load item translators */ Reflections ref = new Reflections("org.geysermc.connector.network.translators.item"); Map loadedNbtItemTranslators = new HashMap<>(); @@ -66,34 +72,33 @@ public class ItemTranslator { loadedNbtItemTranslators.put(nbtItemTranslator, priority); continue; } - ItemStackTranslator itemStackTranslator = (ItemStackTranslator) clazz.newInstance(); + ItemTranslator itemStackTranslator = (ItemTranslator) clazz.newInstance(); List appliedItems = itemStackTranslator.getAppliedItems(); for (ItemEntry item : appliedItems) { - ItemStackTranslator registered = itemTranslators.get(item.getJavaId()); + ItemTranslator registered = ITEM_STACK_TRANSLATORS.get(item.getJavaId()); if (registered != null) { GeyserConnector.getInstance().getLogger().error("Could not instantiate annotated item translator " + clazz.getCanonicalName() + "." + " Item translator " + registered.getClass().getCanonicalName() + " is already registered for the item " + item.getJavaIdentifier()); continue; } - itemTranslators.put(item.getJavaId(), itemStackTranslator); + ITEM_STACK_TRANSLATORS.put(item.getJavaId(), itemStackTranslator); } } catch (InstantiationException | IllegalAccessException e) { GeyserConnector.getInstance().getLogger().error("Could not instantiate annotated item translator " + clazz.getCanonicalName() + "."); } } - nbtItemTranslators = loadedNbtItemTranslators.keySet().stream() - .sorted(Comparator.comparingInt(value -> loadedNbtItemTranslators.get(value))).collect(Collectors.toList()); + NBT_TRANSLATORS = loadedNbtItemTranslators.keySet().stream().sorted(Comparator.comparingInt(loadedNbtItemTranslators::get)).collect(Collectors.toList()); } - public ItemStack translateToJava(GeyserSession session, ItemData data) { + public static ItemStack translateToJava(ItemData data) { if (data == null) { return new ItemStack(0); } - ItemEntry javaItem = getItem(data); + ItemEntry javaItem = ItemRegistry.getItem(data); ItemStack itemStack; - ItemStackTranslator itemStackTranslator = itemTranslators.get(javaItem.getJavaId()); + ItemTranslator itemStackTranslator = ITEM_STACK_TRANSLATORS.get(javaItem.getJavaId()); if (itemStackTranslator != null) { itemStack = itemStackTranslator.translateToJava(data, javaItem); } else { @@ -101,7 +106,7 @@ public class ItemTranslator { } if (itemStack != null && itemStack.getNbt() != null) { - for (NbtItemStackTranslator translator : nbtItemTranslators) { + for (NbtItemStackTranslator translator : NBT_TRANSLATORS) { if (translator.acceptItem(javaItem)) { translator.translateToJava(itemStack.getNbt(), javaItem); } @@ -110,24 +115,24 @@ public class ItemTranslator { return itemStack; } - public ItemData translateToBedrock(GeyserSession session, ItemStack stack) { + public static ItemData translateToBedrock(ItemStack stack) { if (stack == null) { return ItemData.AIR; } - ItemEntry bedrockItem = getItem(stack); + ItemEntry bedrockItem = ItemRegistry.getItem(stack); ItemStack itemStack = new ItemStack(stack.getId(), stack.getAmount(), stack.getNbt() != null ? stack.getNbt().clone() : null); if (itemStack.getNbt() != null) { - for (NbtItemStackTranslator translator : nbtItemTranslators) { + for (NbtItemStackTranslator translator : NBT_TRANSLATORS) { if (translator.acceptItem(bedrockItem)) { translator.translateToBedrock(itemStack.getNbt(), bedrockItem); } } } - ItemStackTranslator itemStackTranslator = itemTranslators.get(bedrockItem.getJavaId()); + ItemTranslator itemStackTranslator = ITEM_STACK_TRANSLATORS.get(bedrockItem.getJavaId()); if (itemStackTranslator != null) { return itemStackTranslator.translateToBedrock(itemStack, bedrockItem); } else { @@ -135,37 +140,216 @@ public class ItemTranslator { } } - public ItemEntry getItem(ItemStack stack) { - return Toolbox.ITEM_ENTRIES.get(stack.getId()); - } - - public ItemEntry getItem(ItemData data) { - for (ItemEntry itemEntry : Toolbox.ITEM_ENTRIES.values()) { - if (itemEntry.getBedrockId() == data.getId() && (itemEntry.getBedrockData() == data.getDamage() || itemEntry.getJavaIdentifier().endsWith("potion"))) { - return itemEntry; - } - } - // If item find was unsuccessful first time, we try again while ignoring damage - // Fixes piston, sticky pistons, dispensers and droppers turning into air from creative inventory - for (ItemEntry itemEntry : Toolbox.ITEM_ENTRIES.values()) { - if (itemEntry.getBedrockId() == data.getId()) { - return itemEntry; - } - } - - GeyserConnector.getInstance().getLogger().debug("Missing mapping for bedrock item " + data.getId() + ":" + data.getDamage()); - return ItemEntry.AIR; - } - - public ItemEntry getItemEntry(String javaIdentifier) { - return javaIdentifierMap.computeIfAbsent(javaIdentifier, key -> Toolbox.ITEM_ENTRIES.values() - .stream().filter(itemEntry -> itemEntry.getJavaIdentifier().equals(key)).findFirst().orElse(null)); - } - - private static final ItemStackTranslator DEFAULT_TRANSLATOR = new ItemStackTranslator() { + private static final ItemTranslator DEFAULT_TRANSLATOR = new ItemTranslator() { @Override public List getAppliedItems() { return null; } }; + + public ItemData translateToBedrock(ItemStack itemStack, ItemEntry itemEntry) { + if (itemStack == null) { + return ItemData.AIR; + } + if (itemStack.getNbt() == null) { + return ItemData.of(itemEntry.getBedrockId(), (short) itemEntry.getBedrockData(), itemStack.getAmount()); + } + return ItemData.of(itemEntry.getBedrockId(), (short) itemEntry.getBedrockData(), itemStack.getAmount(), this.translateNbtToBedrock(itemStack.getNbt())); + } + + public ItemStack translateToJava(ItemData itemData, ItemEntry itemEntry) { + if (itemData == null) return null; + if (itemData.getTag() == null) { + return new ItemStack(itemEntry.getJavaId(), itemData.getCount(), new com.github.steveice10.opennbt.tag.builtin.CompoundTag("")); + } + return new ItemStack(itemEntry.getJavaId(), itemData.getCount(), this.translateToJavaNBT(itemData.getTag())); + } + + public abstract List getAppliedItems(); + + public CompoundTag translateNbtToBedrock(com.github.steveice10.opennbt.tag.builtin.CompoundTag tag) { + Map> javaValue = new HashMap<>(); + if (tag.getValue() != null && !tag.getValue().isEmpty()) { + for (String str : tag.getValue().keySet()) { + com.github.steveice10.opennbt.tag.builtin.Tag javaTag = tag.get(str); + com.nukkitx.nbt.tag.Tag translatedTag = translateToBedrockNBT(javaTag); + if (translatedTag == null) + continue; + + javaValue.put(translatedTag.getName(), translatedTag); + } + } + + return new CompoundTag(tag.getName(), javaValue); + } + + private Tag translateToBedrockNBT(com.github.steveice10.opennbt.tag.builtin.Tag tag) { + if (tag instanceof ByteArrayTag) { + ByteArrayTag byteArrayTag = (ByteArrayTag) tag; + return new com.nukkitx.nbt.tag.ByteArrayTag(byteArrayTag.getName(), byteArrayTag.getValue()); + } + + if (tag instanceof ByteTag) { + ByteTag byteTag = (ByteTag) tag; + return new com.nukkitx.nbt.tag.ByteTag(byteTag.getName(), byteTag.getValue()); + } + + if (tag instanceof DoubleTag) { + DoubleTag doubleTag = (DoubleTag) tag; + return new com.nukkitx.nbt.tag.DoubleTag(doubleTag.getName(), doubleTag.getValue()); + } + + if (tag instanceof FloatTag) { + FloatTag floatTag = (FloatTag) tag; + return new com.nukkitx.nbt.tag.FloatTag(floatTag.getName(), floatTag.getValue()); + } + + if (tag instanceof IntArrayTag) { + IntArrayTag intArrayTag = (IntArrayTag) tag; + return new com.nukkitx.nbt.tag.IntArrayTag(intArrayTag.getName(), intArrayTag.getValue()); + } + + if (tag instanceof IntTag) { + IntTag intTag = (IntTag) tag; + return new com.nukkitx.nbt.tag.IntTag(intTag.getName(), intTag.getValue()); + } + + if (tag instanceof LongArrayTag) { + LongArrayTag longArrayTag = (LongArrayTag) tag; + return new com.nukkitx.nbt.tag.LongArrayTag(longArrayTag.getName(), longArrayTag.getValue()); + } + + if (tag instanceof LongTag) { + LongTag longTag = (LongTag) tag; + return new com.nukkitx.nbt.tag.LongTag(longTag.getName(), longTag.getValue()); + } + + if (tag instanceof ShortTag) { + ShortTag shortTag = (ShortTag) tag; + return new com.nukkitx.nbt.tag.ShortTag(shortTag.getName(), shortTag.getValue()); + } + + if (tag instanceof StringTag) { + StringTag stringTag = (StringTag) tag; + return new com.nukkitx.nbt.tag.StringTag(stringTag.getName(), stringTag.getValue()); + } + + if (tag instanceof ListTag) { + ListTag listTag = (ListTag) tag; + + List> tagList = new ArrayList<>(); + for (com.github.steveice10.opennbt.tag.builtin.Tag value : listTag) { + tagList.add(translateToBedrockNBT(value)); + } + Class clazz = CompoundTag.class; + if (!tagList.isEmpty()) { + clazz = tagList.get(0).getClass(); + } + return new com.nukkitx.nbt.tag.ListTag(listTag.getName(), clazz, tagList); + } + + if (tag instanceof com.github.steveice10.opennbt.tag.builtin.CompoundTag) { + com.github.steveice10.opennbt.tag.builtin.CompoundTag compoundTag = (com.github.steveice10.opennbt.tag.builtin.CompoundTag) tag; + + return translateNbtToBedrock(compoundTag); + } + + return null; + } + + public com.github.steveice10.opennbt.tag.builtin.CompoundTag translateToJavaNBT(com.nukkitx.nbt.tag.CompoundTag tag) { + com.github.steveice10.opennbt.tag.builtin.CompoundTag javaTag = new com.github.steveice10.opennbt.tag.builtin.CompoundTag(tag.getName()); + Map javaValue = javaTag.getValue(); + if (tag.getValue() != null && !tag.getValue().isEmpty()) { + for (String str : tag.getValue().keySet()) { + Tag bedrockTag = tag.get(str); + com.github.steveice10.opennbt.tag.builtin.Tag translatedTag = translateToJavaNBT(bedrockTag); + if (translatedTag == null) + continue; + + javaValue.put(translatedTag.getName(), translatedTag); + } + } + + javaTag.setValue(javaValue); + return javaTag; + } + + private com.github.steveice10.opennbt.tag.builtin.Tag translateToJavaNBT(com.nukkitx.nbt.tag.Tag tag) { + if (tag instanceof com.nukkitx.nbt.tag.ByteArrayTag) { + com.nukkitx.nbt.tag.ByteArrayTag byteArrayTag = (com.nukkitx.nbt.tag.ByteArrayTag) tag; + return new ByteArrayTag(byteArrayTag.getName(), byteArrayTag.getValue()); + } + + if (tag instanceof com.nukkitx.nbt.tag.ByteTag) { + com.nukkitx.nbt.tag.ByteTag byteTag = (com.nukkitx.nbt.tag.ByteTag) tag; + return new ByteTag(byteTag.getName(), byteTag.getValue()); + } + + if (tag instanceof com.nukkitx.nbt.tag.DoubleTag) { + com.nukkitx.nbt.tag.DoubleTag doubleTag = (com.nukkitx.nbt.tag.DoubleTag) tag; + return new DoubleTag(doubleTag.getName(), doubleTag.getValue()); + } + + if (tag instanceof com.nukkitx.nbt.tag.FloatTag) { + com.nukkitx.nbt.tag.FloatTag floatTag = (com.nukkitx.nbt.tag.FloatTag) tag; + return new FloatTag(floatTag.getName(), floatTag.getValue()); + } + + if (tag instanceof com.nukkitx.nbt.tag.IntArrayTag) { + com.nukkitx.nbt.tag.IntArrayTag intArrayTag = (com.nukkitx.nbt.tag.IntArrayTag) tag; + return new IntArrayTag(intArrayTag.getName(), intArrayTag.getValue()); + } + + if (tag instanceof com.nukkitx.nbt.tag.IntTag) { + com.nukkitx.nbt.tag.IntTag intTag = (com.nukkitx.nbt.tag.IntTag) tag; + return new IntTag(intTag.getName(), intTag.getValue()); + } + + if (tag instanceof com.nukkitx.nbt.tag.LongArrayTag) { + com.nukkitx.nbt.tag.LongArrayTag longArrayTag = (com.nukkitx.nbt.tag.LongArrayTag) tag; + return new LongArrayTag(longArrayTag.getName(), longArrayTag.getValue()); + } + + if (tag instanceof com.nukkitx.nbt.tag.LongTag) { + com.nukkitx.nbt.tag.LongTag longTag = (com.nukkitx.nbt.tag.LongTag) tag; + return new LongTag(longTag.getName(), longTag.getValue()); + } + + if (tag instanceof com.nukkitx.nbt.tag.ShortTag) { + com.nukkitx.nbt.tag.ShortTag shortTag = (com.nukkitx.nbt.tag.ShortTag) tag; + return new ShortTag(shortTag.getName(), shortTag.getValue()); + } + + if (tag instanceof com.nukkitx.nbt.tag.StringTag) { + com.nukkitx.nbt.tag.StringTag stringTag = (com.nukkitx.nbt.tag.StringTag) tag; + return new StringTag(stringTag.getName(), stringTag.getValue()); + } + + if (tag instanceof com.nukkitx.nbt.tag.ListTag) { + com.nukkitx.nbt.tag.ListTag listTag = (com.nukkitx.nbt.tag.ListTag) tag; + + List tags = new ArrayList<>(); + + for (Object value : listTag.getValue()) { + if (!(value instanceof com.nukkitx.nbt.tag.Tag)) + continue; + + com.nukkitx.nbt.tag.Tag tagValue = (com.nukkitx.nbt.tag.Tag) value; + com.github.steveice10.opennbt.tag.builtin.Tag javaTag = translateToJavaNBT(tagValue); + if (javaTag != null) + tags.add(javaTag); + } + return new ListTag(listTag.getName(), tags); + } + + if (tag instanceof com.nukkitx.nbt.tag.CompoundTag) { + com.nukkitx.nbt.tag.CompoundTag compoundTag = (com.nukkitx.nbt.tag.CompoundTag) tag; + return translateToJavaNBT(compoundTag); + } + + return null; + } + + } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/NbtItemStackTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/NbtItemStackTranslator.java new file mode 100644 index 000000000..d8fcbc4a7 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/NbtItemStackTranslator.java @@ -0,0 +1,45 @@ +/* + * 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.item; + +import com.github.steveice10.opennbt.tag.builtin.CompoundTag; + +public class NbtItemStackTranslator { + + public void translateToBedrock(CompoundTag itemTag, ItemEntry itemEntry) { + + } + + public void translateToJava(CompoundTag itemTag, ItemEntry itemEntry) { + + } + + public boolean acceptItem(ItemEntry itemEntry) { + return true; + } + +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/BannerTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/BannerTranslator.java index 00ee7c0de..f4f545ffe 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/BannerTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/BannerTranslator.java @@ -27,25 +27,30 @@ package org.geysermc.connector.network.translators.item.translators; import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; +import com.github.steveice10.opennbt.tag.builtin.IntTag; import com.github.steveice10.opennbt.tag.builtin.ListTag; +import com.github.steveice10.opennbt.tag.builtin.StringTag; +import com.github.steveice10.opennbt.tag.builtin.Tag; import com.nukkitx.nbt.CompoundTagBuilder; import com.nukkitx.protocol.bedrock.data.ItemData; import org.geysermc.connector.network.translators.ItemRemapper; -import org.geysermc.connector.network.translators.ItemStackTranslator; +import org.geysermc.connector.network.translators.item.ItemRegistry; +import org.geysermc.connector.network.translators.item.ItemTranslator; import org.geysermc.connector.network.translators.item.ItemEntry; -import org.geysermc.connector.utils.ItemUtils; -import org.geysermc.connector.utils.Toolbox; +import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.stream.Collectors; @ItemRemapper -public class BannerTranslator extends ItemStackTranslator { +public class BannerTranslator extends ItemTranslator { private List appliedItems; public BannerTranslator() { - appliedItems = Toolbox.ITEM_ENTRIES.values().stream().filter(entry -> entry.getJavaIdentifier().endsWith("banner")).collect(Collectors.toList()); + appliedItems = ItemRegistry.ITEM_ENTRIES.values().stream().filter(entry -> entry.getJavaIdentifier().endsWith("banner")).collect(Collectors.toList()); } @Override @@ -59,7 +64,7 @@ public class BannerTranslator extends ItemStackTranslator { ListTag patterns = blockEntityTag.get("Patterns"); CompoundTagBuilder builder = itemData.getTag().toBuilder(); - builder.tag(ItemUtils.convertBannerPattern(patterns)); + builder.tag(convertBannerPattern(patterns)); itemData = ItemData.of(itemData.getId(), itemData.getDamage(), itemData.getCount(), builder.buildRootTag()); } @@ -75,10 +80,10 @@ public class BannerTranslator extends ItemStackTranslator { com.nukkitx.nbt.tag.CompoundTag nbtTag = itemData.getTag(); if (nbtTag.contains("Patterns")) { - com.nukkitx.nbt.tag.ListTag patterns = (com.nukkitx.nbt.tag.ListTag) nbtTag.get("Patterns"); + com.nukkitx.nbt.tag.ListTag patterns = nbtTag.get("Patterns"); CompoundTag blockEntityTag = new CompoundTag("BlockEntityTag"); - blockEntityTag.put(ItemUtils.convertBannerPattern(patterns)); + blockEntityTag.put(convertBannerPattern(patterns)); itemStack.getNbt().put(blockEntityTag); } @@ -90,4 +95,73 @@ public class BannerTranslator extends ItemStackTranslator { public List getAppliedItems() { return appliedItems; } + + /** + * Convert a list of patterns from Java nbt to Bedrock nbt + * + * @param patterns The patterns to convert + * @return The new converted patterns + */ + public static com.nukkitx.nbt.tag.ListTag convertBannerPattern(ListTag patterns) { + List tagsList = new ArrayList<>(); + for (com.github.steveice10.opennbt.tag.builtin.Tag patternTag : patterns.getValue()) { + com.nukkitx.nbt.tag.CompoundTag newPatternTag = getBedrockBannerPattern((CompoundTag) patternTag); + if (newPatternTag != null) { + tagsList.add(newPatternTag); + } + } + + return new com.nukkitx.nbt.tag.ListTag<>("Patterns", com.nukkitx.nbt.tag.CompoundTag.class, tagsList); + } + + /** + * Convert the Java edition banner pattern nbt to Bedrock edition, null if the pattern doesn't exist + * + * @param pattern Java edition pattern nbt + * @return The Bedrock edition format pattern nbt + */ + public static com.nukkitx.nbt.tag.CompoundTag getBedrockBannerPattern(CompoundTag pattern) { + String patternName = (String) pattern.get("Pattern").getValue(); + + // Return null if its the globe pattern as it doesn't exist on bedrock + if (patternName.equals("glb")) { + return null; + } + + return CompoundTagBuilder.builder() + .intTag("Color", 15 - (int) pattern.get("Color").getValue()) + .stringTag("Pattern", (String) pattern.get("Pattern").getValue()) + .stringTag("Pattern", patternName) + .buildRootTag(); + } + + /** + * Convert a list of patterns from Bedrock nbt to Java nbt + * + * @param patterns The patterns to convert + * @return The new converted patterns + */ + public static ListTag convertBannerPattern(com.nukkitx.nbt.tag.ListTag patterns) { + List tagsList = new ArrayList<>(); + for (Object patternTag : patterns.getValue()) { + CompoundTag newPatternTag = getJavaBannerPattern((com.nukkitx.nbt.tag.CompoundTag) patternTag); + tagsList.add(newPatternTag); + } + + return new ListTag("Patterns", tagsList); + } + + /** + * Convert the Bedrock edition banner pattern nbt to Java edition + * + * @param pattern Bedorck edition pattern nbt + * @return The Java edition format pattern nbt + */ + public static CompoundTag getJavaBannerPattern(com.nukkitx.nbt.tag.CompoundTag pattern) { + Map tags = new HashMap<>(); + tags.put("Color", new IntTag("Color", 15 - pattern.getInt("Color"))); + tags.put("Pattern", new StringTag("Pattern", pattern.getString("Pattern"))); + + return new CompoundTag("", tags); + } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/PotionTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/PotionTranslator.java index e528b448e..2fdde31dd 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/PotionTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/PotionTranslator.java @@ -30,22 +30,22 @@ import com.github.steveice10.opennbt.tag.builtin.StringTag; import com.github.steveice10.opennbt.tag.builtin.Tag; import com.nukkitx.protocol.bedrock.data.ItemData; import org.geysermc.connector.GeyserConnector; -import org.geysermc.connector.network.translators.ItemStackTranslator; +import org.geysermc.connector.network.translators.item.ItemRegistry; +import org.geysermc.connector.network.translators.item.ItemTranslator; import org.geysermc.connector.network.translators.ItemRemapper; import org.geysermc.connector.network.translators.item.ItemEntry; import org.geysermc.connector.network.translators.item.Potion; -import org.geysermc.connector.utils.Toolbox; import java.util.List; import java.util.stream.Collectors; @ItemRemapper -public class PotionTranslator extends ItemStackTranslator { +public class PotionTranslator extends ItemTranslator { private List appliedItems; public PotionTranslator() { - appliedItems = Toolbox.ITEM_ENTRIES.values().stream().filter(entry -> entry.getJavaIdentifier().endsWith("potion")).collect(Collectors.toList()); + appliedItems = ItemRegistry.ITEM_ENTRIES.values().stream().filter(entry -> entry.getJavaIdentifier().endsWith("potion")).collect(Collectors.toList()); } @Override diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/BasicItemTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/BasicItemTranslator.java index 418f97da4..776cec729 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/BasicItemTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/BasicItemTranslator.java @@ -34,7 +34,7 @@ import net.kyori.text.TextComponent; import net.kyori.text.serializer.gson.GsonComponentSerializer; import net.kyori.text.serializer.legacy.LegacyComponentSerializer; import org.geysermc.connector.network.translators.ItemRemapper; -import org.geysermc.connector.network.translators.NbtItemStackTranslator; +import org.geysermc.connector.network.translators.item.NbtItemStackTranslator; import org.geysermc.connector.network.translators.item.ItemEntry; import org.geysermc.connector.utils.MessageUtils; diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/BookPagesTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/BookPagesTranslator.java index d9c48a194..15279c7a0 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/BookPagesTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/BookPagesTranslator.java @@ -30,7 +30,7 @@ import com.github.steveice10.opennbt.tag.builtin.ListTag; import com.github.steveice10.opennbt.tag.builtin.StringTag; import com.github.steveice10.opennbt.tag.builtin.Tag; import org.geysermc.connector.network.translators.ItemRemapper; -import org.geysermc.connector.network.translators.NbtItemStackTranslator; +import org.geysermc.connector.network.translators.item.NbtItemStackTranslator; import org.geysermc.connector.network.translators.item.ItemEntry; import org.geysermc.connector.utils.MessageUtils; diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/CrossbowTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/CrossbowTranslator.java index 757011036..3c5271ebf 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/CrossbowTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/CrossbowTranslator.java @@ -30,7 +30,7 @@ import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.ListTag; import com.github.steveice10.opennbt.tag.builtin.StringTag; import org.geysermc.connector.network.translators.ItemRemapper; -import org.geysermc.connector.network.translators.NbtItemStackTranslator; +import org.geysermc.connector.network.translators.item.NbtItemStackTranslator; import org.geysermc.connector.network.translators.item.ItemEntry; @ItemRemapper diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/EnchantedBookTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/EnchantedBookTranslator.java index 38df1ee39..63ac6c510 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/EnchantedBookTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/EnchantedBookTranslator.java @@ -29,7 +29,7 @@ import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.ListTag; import com.github.steveice10.opennbt.tag.builtin.Tag; import org.geysermc.connector.network.translators.ItemRemapper; -import org.geysermc.connector.network.translators.NbtItemStackTranslator; +import org.geysermc.connector.network.translators.item.NbtItemStackTranslator; import org.geysermc.connector.network.translators.item.ItemEntry; @ItemRemapper(priority = 1) diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/EnchantmentTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/EnchantmentTranslator.java index 5dbb926cd..404d7824c 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/EnchantmentTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/EnchantmentTranslator.java @@ -28,7 +28,7 @@ package org.geysermc.connector.network.translators.item.translators.nbt; import com.github.steveice10.opennbt.tag.builtin.*; import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.network.translators.ItemRemapper; -import org.geysermc.connector.network.translators.NbtItemStackTranslator; +import org.geysermc.connector.network.translators.item.NbtItemStackTranslator; import org.geysermc.connector.network.translators.item.Enchantment; import org.geysermc.connector.network.translators.item.ItemEntry; diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/FireworkTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/FireworkTranslator.java index 573e520e4..268fe3932 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/FireworkTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/FireworkTranslator.java @@ -27,7 +27,7 @@ package org.geysermc.connector.network.translators.item.translators.nbt; import com.github.steveice10.opennbt.tag.builtin.*; import org.geysermc.connector.network.translators.ItemRemapper; -import org.geysermc.connector.network.translators.NbtItemStackTranslator; +import org.geysermc.connector.network.translators.item.NbtItemStackTranslator; import org.geysermc.connector.network.translators.item.ItemEntry; import org.geysermc.connector.utils.FireworkColor; diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/LeatherArmorTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/LeatherArmorTranslator.java index 5b283ef57..9f864ccf4 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/LeatherArmorTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/LeatherArmorTranslator.java @@ -28,7 +28,7 @@ package org.geysermc.connector.network.translators.item.translators.nbt; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.IntTag; import org.geysermc.connector.network.translators.ItemRemapper; -import org.geysermc.connector.network.translators.NbtItemStackTranslator; +import org.geysermc.connector.network.translators.item.NbtItemStackTranslator; import org.geysermc.connector.network.translators.item.ItemEntry; @ItemRemapper diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/MapItemTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/MapItemTranslator.java index 7e6bc7298..8c418c0f2 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/MapItemTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/MapItemTranslator.java @@ -30,7 +30,7 @@ import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.IntTag; import com.github.steveice10.opennbt.tag.builtin.StringTag; import org.geysermc.connector.network.translators.ItemRemapper; -import org.geysermc.connector.network.translators.NbtItemStackTranslator; +import org.geysermc.connector.network.translators.item.NbtItemStackTranslator; import org.geysermc.connector.network.translators.item.ItemEntry; @ItemRemapper diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaDeclareRecipesTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaDeclareRecipesTranslator.java index b6a25e54d..7763a2c1d 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaDeclareRecipesTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaDeclareRecipesTranslator.java @@ -42,9 +42,9 @@ import lombok.EqualsAndHashCode; 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.item.ItemEntry; -import org.geysermc.connector.utils.Toolbox; +import org.geysermc.connector.network.translators.item.ItemRegistry; +import org.geysermc.connector.network.translators.item.ItemTranslator; import java.util.*; import java.util.stream.Collectors; @@ -64,7 +64,7 @@ public class JavaDeclareRecipesTranslator extends PacketTranslator> groupedByIds = Arrays.stream(ingredient.getOptions()) - .map(item -> Translators.getItemTranslator().translateToBedrock(session, item)) + .map(ItemTranslator::translateToBedrock) .collect(Collectors.groupingBy(item -> new GroupedItem(item.getId(), item.getCount(), item.getTag()))); Set optionSet = new HashSet<>(groupedByIds.size()); for (Map.Entry> entry : groupedByIds.entrySet()) { @@ -111,7 +111,7 @@ public class JavaDeclareRecipesTranslator extends PacketTranslator 0) { - translatedItems[i] = Translators.getItemTranslator().translateToBedrock(session, ingredients[i].getOptions()[0]); + translatedItems[i] = ItemTranslator.translateToBedrock(ingredients[i].getOptions()[0]); } else { translatedItems[i] = ItemData.AIR; } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/JavaEntityEquipmentTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/JavaEntityEquipmentTranslator.java index a010752d4..e977e9b0c 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/JavaEntityEquipmentTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/JavaEntityEquipmentTranslator.java @@ -30,10 +30,10 @@ import org.geysermc.connector.entity.LivingEntity; 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 com.github.steveice10.mc.protocol.packet.ingame.server.entity.ServerEntityEquipmentPacket; import com.nukkitx.protocol.bedrock.data.ItemData; +import org.geysermc.connector.network.translators.item.ItemTranslator; @Translator(packet = ServerEntityEquipmentPacket.class) public class JavaEntityEquipmentTranslator extends PacketTranslator { @@ -55,7 +55,7 @@ public class JavaEntityEquipmentTranslator extends PacketTranslator { @@ -48,7 +48,7 @@ public class JavaPlayerStopSoundTranslator extends PacketTranslator " + soundMapping + (soundMapping == null ? "[not found]" : "") diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/window/JavaOpenWindowTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/window/JavaOpenWindowTranslator.java index 6c0e3406d..e2c645109 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/window/JavaOpenWindowTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/window/JavaOpenWindowTranslator.java @@ -35,7 +35,6 @@ import org.geysermc.connector.inventory.Inventory; 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.inventory.InventoryTranslator; import org.geysermc.connector.utils.InventoryUtils; @@ -49,14 +48,14 @@ public class JavaOpenWindowTranslator extends PacketTranslator InventoryUtils.openInventory(session, newInventory), 500, TimeUnit.MILLISECONDS); diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/window/JavaSetSlotTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/window/JavaSetSlotTranslator.java index 6fafa2a47..5d44069fe 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/window/JavaSetSlotTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/window/JavaSetSlotTranslator.java @@ -29,7 +29,6 @@ import com.github.steveice10.mc.protocol.packet.ingame.server.window.ServerSetSl import org.geysermc.connector.inventory.Inventory; import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.PacketTranslator; -import org.geysermc.connector.network.translators.Translators; import org.geysermc.connector.network.translators.inventory.InventoryTranslator; import org.geysermc.connector.network.translators.Translator; import org.geysermc.connector.utils.InventoryUtils; @@ -56,7 +55,7 @@ public class JavaSetSlotTranslator extends PacketTranslator if (inventory == null || (packet.getWindowId() != 0 && inventory.getWindowType() == null)) return; - InventoryTranslator translator = Translators.getInventoryTranslators().get(inventory.getWindowType()); + InventoryTranslator translator = InventoryTranslator.INVENTORY_TRANSLATORS.get(inventory.getWindowType()); if (translator != null) { inventory.setItem(packet.getSlot(), packet.getItem()); translator.updateSlot(session, inventory, packet.getSlot()); diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/window/JavaWindowItemsTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/window/JavaWindowItemsTranslator.java index eab57a644..2cc392f53 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/window/JavaWindowItemsTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/window/JavaWindowItemsTranslator.java @@ -30,7 +30,6 @@ import org.geysermc.connector.inventory.Inventory; 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.inventory.InventoryTranslator; import java.util.Arrays; @@ -50,7 +49,7 @@ public class JavaWindowItemsTranslator extends PacketTranslator { @@ -44,7 +44,7 @@ public class JavaPlayBuiltinSoundTranslator extends PacketTranslator params = new ArrayList<>(); - String recordString = "%item." + EffectUtils.RECORDS.get(recordEffectData.getRecordId()).name().toLowerCase() + ".desc"; + String recordString = "%item." + EffectRegistry.RECORDS.get(recordEffectData.getRecordId()).name().toLowerCase() + ".desc"; params.add(LocaleUtils.getLocaleString(recordString, session.getClientData().getLanguageCode())); textPacket.setParameters(params); session.sendUpstreamPacket(textPacket); diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaPlayerPlaySoundTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaPlayerPlaySoundTranslator.java index 58386841e..c99de3e37 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaPlayerPlaySoundTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaPlayerPlaySoundTranslator.java @@ -34,7 +34,7 @@ import com.nukkitx.protocol.bedrock.packet.*; 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.utils.SoundUtils; +import org.geysermc.connector.network.translators.sound.SoundRegistry; @Translator(packet = ServerPlaySoundPacket.class) public class JavaPlayerPlaySoundTranslator extends PacketTranslator { @@ -51,7 +51,7 @@ public class JavaPlayerPlaySoundTranslator extends PacketTranslator { @@ -64,7 +64,7 @@ public class JavaSpawnParticleTranslator extends PacketTranslator SOUNDS; + private SoundRegistry() { + } + public static void init() { // no-op } static { /* Load sound mappings */ - InputStream stream = Toolbox.getResource("mappings/sounds.json"); + InputStream stream = FileUtils.getResource("mappings/sounds.json"); JsonNode soundsTree; try { - soundsTree = Toolbox.JSON_MAPPER.readTree(stream); + soundsTree = GeyserConnector.JSON_MAPPER.readTree(stream); } catch (IOException e) { throw new AssertionError("Unable to load sound mappings", e); } @@ -83,6 +87,13 @@ public class SoundUtils { return SOUNDS.get(java); } + /** + * Maps a sound name to a sound event, null if one + * does not exist. + * + * @param sound the sound name + * @return a sound event from the given sound + */ public static SoundEvent toSoundEvent(String sound) { try { return SoundEvent.valueOf(sound.toUpperCase().replaceAll("\\.", "_")); diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/sound/block/BucketSoundInteractionHandler.java b/connector/src/main/java/org/geysermc/connector/network/translators/sound/block/BucketSoundInteractionHandler.java index 031782c1b..367f9beb8 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/sound/block/BucketSoundInteractionHandler.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/sound/block/BucketSoundInteractionHandler.java @@ -30,7 +30,7 @@ import com.nukkitx.math.vector.Vector3f; 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.Translators; +import org.geysermc.connector.network.translators.item.ItemRegistry; import org.geysermc.connector.network.translators.sound.BlockSoundInteractionHandler; import org.geysermc.connector.network.translators.sound.SoundHandler; @@ -39,7 +39,7 @@ public class BucketSoundInteractionHandler implements BlockSoundInteractionHandl @Override public void handleInteraction(GeyserSession session, Vector3f position, String identifier) { - String handItemIdentifier = Translators.getItemTranslator().getItem(session.getInventory().getItemInHand()).getJavaIdentifier(); + String handItemIdentifier = ItemRegistry.getItem(session.getInventory().getItemInHand()).getJavaIdentifier(); LevelSoundEventPacket soundEventPacket = new LevelSoundEventPacket(); soundEventPacket.setPosition(position); soundEventPacket.setIdentifier(":"); diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/sound/entity/MilkCowSoundInteractionHandler.java b/connector/src/main/java/org/geysermc/connector/network/translators/sound/entity/MilkCowSoundInteractionHandler.java index 42e2e601f..d33d68af2 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/sound/entity/MilkCowSoundInteractionHandler.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/sound/entity/MilkCowSoundInteractionHandler.java @@ -31,7 +31,7 @@ import com.nukkitx.protocol.bedrock.data.SoundEvent; 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.Translators; +import org.geysermc.connector.network.translators.item.ItemRegistry; import org.geysermc.connector.network.translators.sound.EntitySoundInteractionHandler; import org.geysermc.connector.network.translators.sound.SoundHandler; @@ -40,7 +40,7 @@ public class MilkCowSoundInteractionHandler implements EntitySoundInteractionHan @Override public void handleInteraction(GeyserSession session, Vector3f position, Entity value) { - if (!Translators.getItemTranslator().getItem(session.getInventory().getItemInHand()).getJavaIdentifier().equals("minecraft:bucket")) { + if (!ItemRegistry.getItem(session.getInventory().getItemInHand()).getJavaIdentifier().equals("minecraft:bucket")) { return; } LevelSoundEventPacket levelSoundEventPacket = new LevelSoundEventPacket(); diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/world/block/BlockTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/BlockTranslator.java index e614900cb..a40dd15f3 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/world/block/BlockTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/BlockTranslator.java @@ -39,7 +39,7 @@ import it.unimi.dsi.fastutil.objects.Object2IntMap; import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.network.translators.world.block.entity.BlockEntity; -import org.geysermc.connector.utils.Toolbox; +import org.geysermc.connector.utils.FileUtils; import org.reflections.Reflections; import java.io.InputStream; @@ -73,7 +73,7 @@ public class BlockTranslator { static { /* Load block palette */ - InputStream stream = Toolbox.getResource("bedrock/runtime_block_states.dat"); + InputStream stream = FileUtils.getResource("bedrock/runtime_block_states.dat"); ListTag blocksTag; try (NBTInputStream nbtInputStream = NbtUtils.createNetworkReader(stream)) { @@ -90,10 +90,10 @@ public class BlockTranslator { } } - stream = Toolbox.getResource("mappings/blocks.json"); + stream = FileUtils.getResource("mappings/blocks.json"); JsonNode blocks; try { - blocks = Toolbox.JSON_MAPPER.readTree(stream); + blocks = GeyserConnector.JSON_MAPPER.readTree(stream); } catch (Exception e) { throw new AssertionError("Unable to load Java block mappings", e); } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/BannerBlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/BannerBlockEntityTranslator.java index 41f83bad4..3e2c0a959 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/BannerBlockEntityTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/BannerBlockEntityTranslator.java @@ -32,8 +32,8 @@ import com.nukkitx.nbt.CompoundTagBuilder; import com.nukkitx.nbt.tag.IntTag; import com.nukkitx.nbt.tag.StringTag; import com.nukkitx.nbt.tag.Tag; +import org.geysermc.connector.network.translators.item.translators.BannerTranslator; import org.geysermc.connector.network.translators.world.block.BlockStateValues; -import org.geysermc.connector.utils.ItemUtils; import java.util.ArrayList; import java.util.List; @@ -57,7 +57,7 @@ public class BannerBlockEntityTranslator extends BlockEntityTranslator implement if (tag.contains("Patterns")) { ListTag patterns = tag.get("Patterns"); - tags.add(ItemUtils.convertBannerPattern(patterns)); + tags.add(BannerTranslator.convertBannerPattern(patterns)); } if (tag.contains("CustomName")) { diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/BlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/BlockEntityTranslator.java index 4545aed53..3d663926d 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/BlockEntityTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/BlockEntityTranslator.java @@ -32,12 +32,49 @@ import com.github.steveice10.opennbt.tag.builtin.StringTag; import com.nukkitx.nbt.CompoundTagBuilder; import com.nukkitx.nbt.tag.Tag; +import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.utils.BlockEntityUtils; +import org.reflections.Reflections; +import java.util.HashMap; import java.util.List; +import java.util.Map; public abstract class BlockEntityTranslator { + public static final Map BLOCK_ENTITY_TRANSLATORS = new HashMap<>(); + public static ObjectArrayList REQUIRES_BLOCK_STATE_LIST = new ObjectArrayList<>(); + + protected BlockEntityTranslator() { + } + + public static void init() { + // no-op + } + + static { + Reflections ref = new Reflections("org.geysermc.connector.network.translators.world.block.entity"); + for (Class clazz : ref.getTypesAnnotatedWith(BlockEntity.class)) { + GeyserConnector.getInstance().getLogger().debug("Found annotated block entity: " + clazz.getCanonicalName()); + + try { + BLOCK_ENTITY_TRANSLATORS.put(clazz.getAnnotation(BlockEntity.class).name(), (BlockEntityTranslator) clazz.newInstance()); + } catch (InstantiationException | IllegalAccessException e) { + GeyserConnector.getInstance().getLogger().error("Could not instantiate annotated block entity " + clazz.getCanonicalName() + "."); + } + } + for (Class clazz : ref.getSubTypesOf(RequiresBlockState.class)) { + GeyserConnector.getInstance().getLogger().debug("Found block entity that requires block state: " + clazz.getCanonicalName()); + + try { + REQUIRES_BLOCK_STATE_LIST.add((RequiresBlockState) clazz.newInstance()); + } catch (InstantiationException | IllegalAccessException e) { + GeyserConnector.getInstance().getLogger().error("Could not instantiate required block state " + clazz.getCanonicalName() + "."); + } + } + } + public abstract List> translateTag(CompoundTag tag, BlockState blockState); public abstract CompoundTag getDefaultJavaTag(String javaId, int x, int y, int z); diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/CampfireBlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/CampfireBlockEntityTranslator.java index eac87b041..cd31636c8 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/CampfireBlockEntityTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/CampfireBlockEntityTranslator.java @@ -30,9 +30,8 @@ import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.ListTag; import com.nukkitx.nbt.CompoundTagBuilder; import com.nukkitx.nbt.tag.Tag; - -import org.geysermc.connector.network.translators.Translators; import org.geysermc.connector.network.translators.item.ItemEntry; +import org.geysermc.connector.network.translators.item.ItemRegistry; import java.util.ArrayList; import java.util.HashMap; @@ -71,7 +70,7 @@ public class CampfireBlockEntityTranslator extends BlockEntityTranslator { } protected com.nukkitx.nbt.tag.CompoundTag getItem(CompoundTag tag) { - ItemEntry entry = Translators.getItemTranslator().getItemEntry((String) tag.get("id").getValue()); + ItemEntry entry = ItemRegistry.getItemEntry((String) tag.get("id").getValue()); CompoundTagBuilder tagBuilder = CompoundTagBuilder.builder() .shortTag("id", (short) entry.getBedrockId()) .byteTag("Count", (byte) tag.get("Count").getValue()) diff --git a/connector/src/main/java/org/geysermc/connector/utils/BlockEntityUtils.java b/connector/src/main/java/org/geysermc/connector/utils/BlockEntityUtils.java index da32b12b0..038084c3a 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/BlockEntityUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/BlockEntityUtils.java @@ -4,12 +4,11 @@ import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position; import com.nukkitx.math.vector.Vector3i; import com.nukkitx.protocol.bedrock.packet.BlockEntityDataPacket; import org.geysermc.connector.network.session.GeyserSession; -import org.geysermc.connector.network.translators.Translators; import org.geysermc.connector.network.translators.world.block.entity.BlockEntityTranslator; public class BlockEntityUtils { - private static final BlockEntityTranslator EMPTY_TRANSLATOR = Translators.getBlockEntityTranslators().get("Empty"); + private static final BlockEntityTranslator EMPTY_TRANSLATOR = BlockEntityTranslator.BLOCK_ENTITY_TRANSLATORS.get("Empty"); public static String getBedrockBlockEntityId(String id) { // These are the only exceptions when it comes to block entity ids @@ -39,7 +38,7 @@ public class BlockEntityUtils { } public static BlockEntityTranslator getBlockEntityTranslator(String name) { - BlockEntityTranslator blockEntityTranslator = Translators.getBlockEntityTranslators().get(name); + BlockEntityTranslator blockEntityTranslator = BlockEntityTranslator.BLOCK_ENTITY_TRANSLATORS.get(name); if (blockEntityTranslator == null) { return EMPTY_TRANSLATOR; } diff --git a/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java b/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java index 41d0dc2d6..010a87afa 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java @@ -32,6 +32,9 @@ import com.github.steveice10.mc.protocol.data.game.world.block.BlockState; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.nukkitx.math.vector.Vector2i; import com.nukkitx.math.vector.Vector3i; +import com.nukkitx.nbt.CompoundTagBuilder; +import com.nukkitx.nbt.NbtUtils; +import com.nukkitx.nbt.stream.NBTOutputStream; import com.nukkitx.protocol.bedrock.packet.*; import it.unimi.dsi.fastutil.objects.Object2IntMap; import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; @@ -43,11 +46,12 @@ import org.geysermc.connector.entity.ItemFrameEntity; import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.world.block.BlockStateValues; import org.geysermc.connector.network.translators.world.block.entity.*; -import org.geysermc.connector.network.translators.Translators; import org.geysermc.connector.network.translators.world.block.BlockTranslator; import org.geysermc.connector.network.translators.world.chunk.ChunkPosition; import org.geysermc.connector.network.translators.world.chunk.ChunkSection; +import java.io.ByteArrayOutputStream; +import java.io.IOException; import java.util.HashMap; import java.util.Map; @@ -61,6 +65,23 @@ public class ChunkUtils { */ public static final Map CACHED_BLOCK_ENTITIES = new HashMap<>(); + private static final com.nukkitx.nbt.tag.CompoundTag EMPTY_TAG = CompoundTagBuilder.builder().buildRootTag(); + public static final byte[] EMPTY_LEVEL_CHUNK_DATA; + + static { + try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) { + outputStream.write(new byte[258]); // Biomes + Border Size + Extra Data Size + + try (NBTOutputStream stream = NbtUtils.createNetworkWriter(outputStream)) { + stream.write(EMPTY_TAG); + } + + EMPTY_LEVEL_CHUNK_DATA = outputStream.toByteArray(); + }catch (IOException e) { + throw new AssertionError("Unable to generate empty level chunk data"); + } + } + public static ChunkData translateToBedrock(Column column) { ChunkData chunkData = new ChunkData(); Chunk[] chunks = column.getChunks(); @@ -194,7 +215,7 @@ public class ChunkUtils { // Since Java stores bed colors/skull information as part of the namespaced ID and Bedrock stores it as a tag // This is the only place I could find that interacts with the Java block state and block updates // Iterates through all block entity translators and determines if the block state needs to be saved - for (RequiresBlockState requiresBlockState : Translators.getRequiresBlockStateMap()) { + for (RequiresBlockState requiresBlockState : BlockEntityTranslator.REQUIRES_BLOCK_STATE_LIST) { if (requiresBlockState.isBlock(blockState)) { // Flower pots are block entities only in Bedrock and are not updated anywhere else like note blocks if (requiresBlockState instanceof BedrockOnlyBlockEntity) { @@ -217,7 +238,7 @@ public class ChunkUtils { data.setChunkX(chunkX + x); data.setChunkZ(chunkZ + z); data.setSubChunksLength(0); - data.setData(Translators.EMPTY_LEVEL_CHUNK_DATA); + data.setData(EMPTY_LEVEL_CHUNK_DATA); data.setCachingEnabled(false); session.sendUpstreamPacket(data); diff --git a/connector/src/main/java/org/geysermc/connector/utils/FileUtils.java b/connector/src/main/java/org/geysermc/connector/utils/FileUtils.java index dea427280..04b6ecc4d 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/FileUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/FileUtils.java @@ -125,4 +125,18 @@ public class FileUtils { public static void writeFile(String name, char[] data) throws IOException { writeFile(new File(name), data); } + + /** + * Get an InputStream for the given resource path, throws AssertionError if resource is not found + * + * @param resource Resource to get + * @return InputStream of the given resource + */ + public static InputStream getResource(String resource) { + InputStream stream = FileUtils.class.getClassLoader().getResourceAsStream(resource); + if (stream == null) { + throw new AssertionError("Unable to find resource: " + resource); + } + return stream; + } } diff --git a/connector/src/main/java/org/geysermc/connector/utils/InventoryUtils.java b/connector/src/main/java/org/geysermc/connector/utils/InventoryUtils.java index c0311b64f..fd4c5e4e5 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/InventoryUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/InventoryUtils.java @@ -36,9 +36,10 @@ import org.geysermc.common.ChatColor; import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.inventory.Inventory; import org.geysermc.connector.network.session.GeyserSession; -import org.geysermc.connector.network.translators.Translators; import org.geysermc.connector.network.translators.inventory.DoubleChestInventoryTranslator; import org.geysermc.connector.network.translators.inventory.InventoryTranslator; +import org.geysermc.connector.network.translators.item.ItemRegistry; +import org.geysermc.connector.network.translators.item.ItemTranslator; import java.util.Collections; import java.util.Objects; @@ -48,7 +49,7 @@ public class InventoryUtils { public static final ItemStack REFRESH_ITEM = new ItemStack(1, 127, new CompoundTag("")); //TODO: stop using this public static void openInventory(GeyserSession session, Inventory inventory) { - InventoryTranslator translator = Translators.getInventoryTranslators().get(inventory.getWindowType()); + InventoryTranslator translator = InventoryTranslator.INVENTORY_TRANSLATORS.get(inventory.getWindowType()); if (translator != null) { session.getInventoryCache().setOpenInventory(inventory); translator.prepareInventory(session, inventory); @@ -69,14 +70,14 @@ public class InventoryUtils { if (windowId != 0) { Inventory inventory = session.getInventoryCache().getInventories().get(windowId); if (inventory != null) { - InventoryTranslator translator = Translators.getInventoryTranslators().get(inventory.getWindowType()); + InventoryTranslator translator = InventoryTranslator.INVENTORY_TRANSLATORS.get(inventory.getWindowType()); translator.closeInventory(session, inventory); session.getInventoryCache().uncacheInventory(windowId); session.getInventoryCache().setOpenInventory(null); } } else { Inventory inventory = session.getInventory(); - InventoryTranslator translator = Translators.getInventoryTranslators().get(inventory.getWindowType()); + InventoryTranslator translator = InventoryTranslator.INVENTORY_TRANSLATORS.get(inventory.getWindowType()); translator.updateInventory(session, inventory); } session.setCraftSlot(0); @@ -87,7 +88,7 @@ public class InventoryUtils { InventorySlotPacket cursorPacket = new InventorySlotPacket(); cursorPacket.setContainerId(ContainerId.CURSOR); cursorPacket.setSlot(0); - cursorPacket.setItem(Translators.getItemTranslator().translateToBedrock(session, session.getInventory().getCursor())); + cursorPacket.setItem(ItemTranslator.translateToBedrock(session.getInventory().getCursor())); session.sendUpstreamPacket(cursorPacket); } @@ -115,6 +116,6 @@ public class InventoryUtils { display.listTag("Lore", StringTag.class, Collections.singletonList(new StringTag("", ChatColor.RESET + ChatColor.DARK_PURPLE + description))); root.tag(display.build("display")); - return ItemData.of(Toolbox.ITEM_ENTRIES.get(Toolbox.BARRIER_INDEX).getBedrockId(), (short) 0, 1, root.buildRootTag()); + return ItemData.of(ItemRegistry.ITEM_ENTRIES.get(ItemRegistry.BARRIER_INDEX).getBedrockId(), (short) 0, 1, root.buildRootTag()); } } diff --git a/connector/src/main/java/org/geysermc/connector/utils/ItemUtils.java b/connector/src/main/java/org/geysermc/connector/utils/ItemUtils.java index d3fe48d99..b96002224 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/ItemUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/ItemUtils.java @@ -50,77 +50,4 @@ public class ItemUtils { } return 0; } - - /** - * Convert a list of patterns from Java nbt to Bedrock nbt - * - * @param patterns The patterns to convert - * @return The new converted patterns - */ - public static com.nukkitx.nbt.tag.ListTag convertBannerPattern(ListTag patterns) { - List tagsList = new ArrayList<>(); - for (com.github.steveice10.opennbt.tag.builtin.Tag patternTag : patterns.getValue()) { - com.nukkitx.nbt.tag.CompoundTag newPatternTag = getBedrockBannerPattern((CompoundTag) patternTag); - if (newPatternTag != null) { - tagsList.add(newPatternTag); - } - } - - return new com.nukkitx.nbt.tag.ListTag<>("Patterns", com.nukkitx.nbt.tag.CompoundTag.class, tagsList); - } - - /** - * Convert the Java edition banner pattern nbt to Bedrock edition, null if the pattern doesn't exist - * - * @param pattern Java edition pattern nbt - * @return The Bedrock edition format pattern nbt - */ - public static com.nukkitx.nbt.tag.CompoundTag getBedrockBannerPattern(CompoundTag pattern) { - String patternName = (String) pattern.get("Pattern").getValue(); - - // Return null if its the globe pattern as it doesn't exist on bedrock - if (patternName.equals("glb")) { - return null; - } - - return CompoundTagBuilder.builder() - .intTag("Color", 15 - (int) pattern.get("Color").getValue()) - .stringTag("Pattern", (String) pattern.get("Pattern").getValue()) - .stringTag("Pattern", patternName) - .buildRootTag(); - } - - /** - * Convert a list of patterns from Bedrock nbt to Java nbt - * - * @param patterns The patterns to convert - * @return The new converted patterns - */ - public static ListTag convertBannerPattern(com.nukkitx.nbt.tag.ListTag patterns) { - List tagsList = new ArrayList<>(); - for (Object patternTag : patterns.getValue()) { - CompoundTag newPatternTag = getJavaBannerPattern((com.nukkitx.nbt.tag.CompoundTag) patternTag); - if (newPatternTag != null) { - tagsList.add(newPatternTag); - } - } - - return new ListTag("Patterns", tagsList); - } - - /** - * Convert the Bedrock edition banner pattern nbt to Java edition - * - * @param pattern Bedorck edition pattern nbt - * @return The Java edition format pattern nbt - */ - public static CompoundTag getJavaBannerPattern(com.nukkitx.nbt.tag.CompoundTag pattern) { - String patternName = (String) pattern.get("Pattern").getValue(); - - Map tags = new HashMap<>(); - tags.put("Color", new IntTag("Color", 15 - pattern.getInt("Color"))); - tags.put("Pattern", new StringTag("Pattern", pattern.getString("Pattern"))); - - return new CompoundTag("", tags); - } } diff --git a/connector/src/main/java/org/geysermc/connector/utils/LocaleUtils.java b/connector/src/main/java/org/geysermc/connector/utils/LocaleUtils.java index 726ad1c19..f55cb261e 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/LocaleUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/LocaleUtils.java @@ -63,7 +63,7 @@ public class LocaleUtils { private static void generateAssetCache() { try { // Get the version manifest from Mojang - VersionManifest versionManifest = Toolbox.JSON_MAPPER.readValue(WebUtils.getBody("https://launchermeta.mojang.com/mc/game/version_manifest.json"), VersionManifest.class); + VersionManifest versionManifest = GeyserConnector.JSON_MAPPER.readValue(WebUtils.getBody("https://launchermeta.mojang.com/mc/game/version_manifest.json"), VersionManifest.class); // Get the url for the latest version of the games manifest String latestInfoURL = ""; @@ -80,7 +80,7 @@ public class LocaleUtils { } // Get the individual version manifest - VersionInfo versionInfo = Toolbox.JSON_MAPPER.readValue(WebUtils.getBody(latestInfoURL), VersionInfo.class); + VersionInfo versionInfo = GeyserConnector.JSON_MAPPER.readValue(WebUtils.getBody(latestInfoURL), VersionInfo.class); // Get the smallest jar for use when downloading the en_us locale, will be either the server or client int currentSize = Integer.MAX_VALUE; @@ -92,13 +92,13 @@ public class LocaleUtils { } // Get the assets list - JsonNode assets = Toolbox.JSON_MAPPER.readTree(WebUtils.getBody(versionInfo.getAssetIndex().getUrl())).get("objects"); + JsonNode assets = GeyserConnector.JSON_MAPPER.readTree(WebUtils.getBody(versionInfo.getAssetIndex().getUrl())).get("objects"); // Put each asset into an array for use later Iterator> assetIterator = assets.fields(); while (assetIterator.hasNext()) { Map.Entry entry = assetIterator.next(); - Asset asset = Toolbox.JSON_MAPPER.treeToValue(entry.getValue(), Asset.class); + Asset asset = GeyserConnector.JSON_MAPPER.treeToValue(entry.getValue(), Asset.class); ASSET_MAP.put(entry.getKey(), asset); } } catch (Exception e) { @@ -173,7 +173,7 @@ public class LocaleUtils { // Parse the file as json JsonNode localeObj; try { - localeObj = Toolbox.JSON_MAPPER.readTree(localeStream); + localeObj = GeyserConnector.JSON_MAPPER.readTree(localeStream); } catch (Exception e) { throw new AssertionError("Unable to load Java edition lang map for " + locale, e); } diff --git a/connector/src/main/java/org/geysermc/connector/utils/SkinProvider.java b/connector/src/main/java/org/geysermc/connector/utils/SkinProvider.java index b14a99016..aea9ba189 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/SkinProvider.java +++ b/connector/src/main/java/org/geysermc/connector/utils/SkinProvider.java @@ -72,7 +72,7 @@ public class SkinProvider { static { /* Load in the normal ears geometry */ - InputStream earsStream = Toolbox.getResource("bedrock/skin/geometry.humanoid.ears.json"); + InputStream earsStream = FileUtils.getResource("bedrock/skin/geometry.humanoid.ears.json"); StringBuilder earsDataBuilder = new StringBuilder(); try (Reader reader = new BufferedReader(new InputStreamReader(earsStream, Charset.forName(StandardCharsets.UTF_8.name())))) { @@ -88,7 +88,7 @@ public class SkinProvider { /* Load in the slim ears geometry */ - earsStream = Toolbox.getResource("bedrock/skin/geometry.humanoid.earsSlim.json"); + earsStream = FileUtils.getResource("bedrock/skin/geometry.humanoid.earsSlim.json"); earsDataBuilder = new StringBuilder(); try (Reader reader = new BufferedReader(new InputStreamReader(earsStream, Charset.forName(StandardCharsets.UTF_8.name())))) { From d0545c57c454f72d639e27caa7339b1679a8d701 Mon Sep 17 00:00:00 2001 From: rtm516 Date: Mon, 25 May 2020 22:57:10 +0100 Subject: [PATCH 123/140] Fix some fireworks colors and NPE of there is no NBT (#650) Adds Bukkit colors and an additional NPE check --- .../connector/entity/FireworkEntity.java | 8 +++--- .../connector/utils/FireworkColor.java | 27 ++++++++++++++++--- 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/entity/FireworkEntity.java b/connector/src/main/java/org/geysermc/connector/entity/FireworkEntity.java index 55d9c790c..cb050e860 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/FireworkEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/FireworkEntity.java @@ -25,8 +25,6 @@ package org.geysermc.connector.entity; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata; import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; @@ -36,7 +34,6 @@ import com.nukkitx.math.vector.Vector3f; import com.nukkitx.nbt.CompoundTagBuilder; import com.nukkitx.protocol.bedrock.data.EntityData; import com.nukkitx.protocol.bedrock.packet.SetEntityMotionPacket; -import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.entity.type.EntityType; import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.utils.FireworkColor; @@ -57,6 +54,11 @@ public class FireworkEntity extends Entity { if (entityMetadata.getId() == 7) { ItemStack item = (ItemStack) entityMetadata.getValue(); CompoundTag tag = item.getNbt(); + + if (tag == null) { + return; + } + CompoundTag fireworks = tag.get("Fireworks"); CompoundTagBuilder fireworksBuilder = CompoundTagBuilder.builder(); diff --git a/connector/src/main/java/org/geysermc/connector/utils/FireworkColor.java b/connector/src/main/java/org/geysermc/connector/utils/FireworkColor.java index 2f3939340..d729e3a19 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/FireworkColor.java +++ b/connector/src/main/java/org/geysermc/connector/utils/FireworkColor.java @@ -29,6 +29,7 @@ package org.geysermc.connector.utils; import lombok.Getter; public enum FireworkColor { + // Vanilla colors BLACK((byte) 0, 1973019), RED((byte) 1, 11743532), GREEN((byte) 2, 3887386), @@ -44,7 +45,27 @@ public enum FireworkColor { LIGHT_BLUE((byte) 12, 6719955), MAGENTA((byte) 13, 12801229), ORANGE((byte) 14, 15435844), - WHITE((byte) 15, 15790320); + WHITE((byte) 15, 15790320), + + // Bukkit colors + // https://hub.spigotmc.org/javadocs/spigot/org/bukkit/Color.html + BUKKIT_WHITE((byte) 15, 0xFFFFFF), + BUKKIT_SILVER((byte) 7, 0xC0C0C0), + BUKKIT_GRAY((byte) 8, 0x808080), + BUKKIT_BLACK((byte) 0, 0x000000), + BUKKIT_RED((byte) 1, 0xFF0000), + BUKKIT_MAROON((byte) 1, 0x800000), // No perfect map but this is as close as it can be + BUKKIT_YELLOW((byte) 11, 0xFFFF00), + BUKKIT_OLIVE((byte) 2, 0x808000), // No perfect map but this is as close as it can be + BUKKIT_LIME((byte) 10, 0x00FF00), + BUKKIT_GREEN((byte) 2, 0x008000), + BUKKIT_AQUA((byte) 12, 0x00FFFF), + BUKKIT_TEAL((byte) 6, 0x008080), + BUKKIT_BLUE((byte) 4, 0x0000FF), + BUKKIT_NAVY((byte) 4, 0x000080), // No perfect map but this is as close as it can be + BUKKIT_FUCHSIA((byte) 9, 0xFF00FF), // No perfect map but this is as close as it can be + BUKKIT_PURPLE((byte) 5, 0x800080), + BUKKIT_ORANGE((byte) 14, 0xFFA500); private static final FireworkColor[] VALUES = values(); @@ -65,7 +86,7 @@ public enum FireworkColor { } } - return null; + return WHITE; } public static FireworkColor fromBedrockID(int id) { @@ -75,6 +96,6 @@ public enum FireworkColor { } } - return null; + return WHITE; } } From 0178492b593bab466d948409077c71e298cee051 Mon Sep 17 00:00:00 2001 From: Arktisfox <65837019+Arktisfox@users.noreply.github.com> Date: Mon, 25 May 2020 21:19:37 -0400 Subject: [PATCH 124/140] Fix some book translation failures (#661) Book pages can be sent as plain text rather than JSON. The text library doesn't use lenient parsing, so this fails, and the book isn't visible in the inventory. This will convert the text into JSON if it's not already, before feeding it to the text library. --- .../translators/nbt/BookPagesTranslator.java | 2 +- .../geysermc/connector/utils/MessageUtils.java | 17 +++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/BookPagesTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/BookPagesTranslator.java index 15279c7a0..e802f0174 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/BookPagesTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/BookPagesTranslator.java @@ -55,7 +55,7 @@ public class BookPagesTranslator extends NbtItemStackTranslator { CompoundTag pageTag = new CompoundTag(""); pageTag.put(new StringTag("photoname", "")); - pageTag.put(new StringTag("text", MessageUtils.getBedrockMessage(textTag.getValue()))); + pageTag.put(new StringTag("text", MessageUtils.getBedrockMessageLenient(textTag.getValue()))); pages.add(pageTag); } diff --git a/connector/src/main/java/org/geysermc/connector/utils/MessageUtils.java b/connector/src/main/java/org/geysermc/connector/utils/MessageUtils.java index 3c924912a..d79cdab82 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/MessageUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/MessageUtils.java @@ -137,6 +137,23 @@ public class MessageUtils { } } + /** + * Verifies the message is valid JSON in case it's plaintext. Works around GsonComponentSeraializer not using lenient mode. + * See https://wiki.vg/Chat for messages sent in lenient mode, and for a description on leniency. + * + * @param message Potentially lenient JSON message + * @return Bedrock formatted message + */ + public static String getBedrockMessageLenient(String message) { + if (isMessage(message)) { + return getBedrockMessage(message); + } else { + final JsonObject obj = new JsonObject(); + obj.addProperty("text", message); + return getBedrockMessage(obj.toString()); + } + } + public static String getBedrockMessage(String message) { Component component = phraseJavaMessage(message); return LegacyComponentSerializer.legacy().serialize(component); From cc6c7fe78dbb738985085312c721bbabc957ddcf Mon Sep 17 00:00:00 2001 From: bundabrg Date: Tue, 26 May 2020 11:35:26 +0800 Subject: [PATCH 125/140] When spawning don't add the player offset (#655) Fixes falling when logging in --- .../entity/player/JavaPlayerPositionRotationTranslator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerPositionRotationTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerPositionRotationTranslator.java index ff6d41a1d..37fb96fb8 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerPositionRotationTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerPositionRotationTranslator.java @@ -54,7 +54,7 @@ public class JavaPlayerPositionRotationTranslator extends PacketTranslator Date: Tue, 26 May 2020 11:39:57 +0800 Subject: [PATCH 126/140] Use authData UUID when sending playerlist packets to the client (#654) Bedrock knows its own UUID and when it receives the Java uuid it will either crash (MCEE) or add a ghost player onto the playerlist (Bedrock). This change will check if an entity is the client and if so replace the entities UUID with the AuthData UUID. A refactor of JavaPlayerListEntryTranslator was also done as I got confused each time what it was doing so it is now hopefully a bit clearer and also fixes the case where an entity is removed but still exists on the server (Vanished). --- .../player/JavaPlayerListEntryTranslator.java | 94 ++++++++++++------- .../geysermc/connector/utils/SkinUtils.java | 13 +++ 2 files changed, 75 insertions(+), 32 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerListEntryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerListEntryTranslator.java index 96dc60503..f387daecf 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerListEntryTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerListEntryTranslator.java @@ -42,47 +42,77 @@ import com.nukkitx.protocol.bedrock.packet.PlayerListPacket; public class JavaPlayerListEntryTranslator extends PacketTranslator { @Override public void translate(ServerPlayerListEntryPacket packet, GeyserSession session) { - if (packet.getAction() != PlayerListEntryAction.ADD_PLAYER && packet.getAction() != PlayerListEntryAction.REMOVE_PLAYER) return; + if (packet.getAction() != PlayerListEntryAction.ADD_PLAYER && packet.getAction() != PlayerListEntryAction.REMOVE_PLAYER) + return; PlayerListPacket translate = new PlayerListPacket(); translate.setAction(packet.getAction() == PlayerListEntryAction.ADD_PLAYER ? PlayerListPacket.Action.ADD : PlayerListPacket.Action.REMOVE); for (PlayerListEntry entry : packet.getEntries()) { - if (packet.getAction() == PlayerListEntryAction.ADD_PLAYER) { - boolean self = entry.getProfile().getId().equals(session.getPlayerEntity().getUuid()); + switch (packet.getAction()) { + case ADD_PLAYER: + PlayerEntity playerEntity; + boolean self = entry.getProfile().getId().equals(session.getPlayerEntity().getUuid()); + + if (self) { + // Entity is ourself + playerEntity = session.getPlayerEntity(); + SkinUtils.requestAndHandleSkinAndCape(playerEntity, session, skinAndCape -> { + GeyserConnector.getInstance().getLogger().debug("Loading Local Bedrock Java Skin Data"); + }); + } else { + playerEntity = session.getEntityCache().getPlayerEntity(entry.getProfile().getId()); + } + + if (playerEntity == null) { + // It's a new player + playerEntity = new PlayerEntity( + entry.getProfile(), + -1, + session.getEntityCache().getNextEntityId().incrementAndGet(), + Vector3f.ZERO, + Vector3f.ZERO, + Vector3f.ZERO + ); + } + + session.getEntityCache().addPlayerEntity(playerEntity); - PlayerEntity playerEntity = session.getPlayerEntity(); - if (self) { playerEntity.setProfile(entry.getProfile()); - SkinUtils.requestAndHandleSkinAndCape(playerEntity, session, skinAndCape -> { - GeyserConnector.getInstance().getLogger().debug("Loading Local Bedrock Java Skin Data"); - }); - } else { - playerEntity = new PlayerEntity( - entry.getProfile(), - -1, - session.getEntityCache().getNextEntityId().incrementAndGet(), - Vector3f.ZERO, - Vector3f.ZERO, - Vector3f.ZERO - ); - } + playerEntity.setPlayerList(true); + playerEntity.setValid(true); - playerEntity.setPlayerList(true); - playerEntity.setValid(true); - session.getEntityCache().addPlayerEntity(playerEntity); + PlayerListPacket.Entry playerListEntry = SkinUtils.buildCachedEntry(entry.getProfile(), playerEntity.getGeyserId()); + if (self) { + // Copy the entry with our identity instead. + PlayerListPacket.Entry copy = new PlayerListPacket.Entry(session.getAuthData().getUUID()); + copy.setName(playerListEntry.getName()); + copy.setEntityId(playerListEntry.getEntityId()); + copy.setSkin(playerListEntry.getSkin()); + copy.setXuid(playerListEntry.getXuid()); + copy.setPlatformChatId(playerListEntry.getPlatformChatId()); + copy.setTeacher(playerListEntry.isTeacher()); + playerListEntry = copy; + } - translate.getEntries().add(SkinUtils.buildCachedEntry(entry.getProfile(), playerEntity.getGeyserId())); - } else { - PlayerEntity entity = session.getEntityCache().getPlayerEntity(entry.getProfile().getId()); - if (entity != null && entity.isValid()) { - // remove from tablist but player entity is still there - entity.setPlayerList(false); - } else { - // just remove it from caching - session.getEntityCache().removePlayerEntity(entry.getProfile().getId()); - } - translate.getEntries().add(new PlayerListPacket.Entry(entry.getProfile().getId())); + translate.getEntries().add(playerListEntry); + break; + case REMOVE_PLAYER: + PlayerEntity entity = session.getEntityCache().getPlayerEntity(entry.getProfile().getId()); + if (entity != null && entity.isValid()) { + // remove from tablist but player entity is still there + entity.setPlayerList(false); + } else { + // just remove it from caching + if (entity == null) { + session.getEntityCache().removePlayerEntity(entry.getProfile().getId()); + } else { + entity.setPlayerList(false); + session.getEntityCache().removeEntity(entity, false); + } + } + translate.getEntries().add(new PlayerListPacket.Entry(entry.getProfile().getId())); + break; } } diff --git a/connector/src/main/java/org/geysermc/connector/utils/SkinUtils.java b/connector/src/main/java/org/geysermc/connector/utils/SkinUtils.java index 95a3ff19b..48e4c4c80 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/SkinUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/SkinUtils.java @@ -218,6 +218,19 @@ public class SkinUtils { geometry.getGeometryData() ); + // If it is our skin we replace the UUID with the authdata UUID + if (session.getPlayerEntity() == entity) { + // Copy the entry with our identity instead. + PlayerListPacket.Entry copy = new PlayerListPacket.Entry(session.getAuthData().getUUID()); + copy.setName(updatedEntry.getName()); + copy.setEntityId(updatedEntry.getEntityId()); + copy.setSkin(updatedEntry.getSkin()); + copy.setXuid(updatedEntry.getXuid()); + copy.setPlatformChatId(updatedEntry.getPlatformChatId()); + copy.setTeacher(updatedEntry.isTeacher()); + updatedEntry = copy; + } + PlayerListPacket playerRemovePacket = new PlayerListPacket(); playerRemovePacket.setAction(PlayerListPacket.Action.REMOVE); playerRemovePacket.getEntries().add(updatedEntry); From 14fcd77925f2246ad5e526038d21a521c141dd8d Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+DoctorMacc@users.noreply.github.com> Date: Mon, 25 May 2020 23:43:29 -0400 Subject: [PATCH 127/140] Fix entities stacking on top of each other when mounted (#660) The offset was being called but not properly saved to a variable. The check will also not apply if there is only one mounted entity. --- .../JavaEntitySetPassengersTranslator.java | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/JavaEntitySetPassengersTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/JavaEntitySetPassengersTranslator.java index ad0d0f9e0..912ee8325 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/JavaEntitySetPassengersTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/JavaEntitySetPassengersTranslator.java @@ -82,7 +82,7 @@ public class JavaEntitySetPassengersTranslator extends PacketTranslator 1)); rider = false; } @@ -99,7 +99,7 @@ public class JavaEntitySetPassengersTranslator extends PacketTranslator 1)); } } @@ -111,8 +111,8 @@ public class JavaEntitySetPassengersTranslator extends PacketTranslator Date: Thu, 28 May 2020 16:38:23 +0100 Subject: [PATCH 128/140] Add byte conversion to allow int NBT values for Fireworks (#681) Firework NBT data might be either an int or byte and bedrock only takes it as a byte. Co-authored-by: Arktisfox <65837019+Arktisfox@users.noreply.github.com> --- .../connector/entity/FireworkEntity.java | 9 ++++---- .../translators/nbt/FireworkTranslator.java | 22 +++++++++++++------ .../geysermc/connector/utils/MathUtils.java | 15 +++++++++++++ 3 files changed, 35 insertions(+), 11 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/entity/FireworkEntity.java b/connector/src/main/java/org/geysermc/connector/entity/FireworkEntity.java index cb050e860..1db4f757a 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/FireworkEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/FireworkEntity.java @@ -37,6 +37,7 @@ import com.nukkitx.protocol.bedrock.packet.SetEntityMotionPacket; import org.geysermc.connector.entity.type.EntityType; import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.utils.FireworkColor; +import org.geysermc.connector.utils.MathUtils; import java.util.ArrayList; import java.util.List; @@ -63,7 +64,7 @@ public class FireworkEntity extends Entity { CompoundTagBuilder fireworksBuilder = CompoundTagBuilder.builder(); if (fireworks.get("Flight") != null) { - fireworksBuilder.byteTag("Flight", (Byte) fireworks.get("Flight").getValue()); + fireworksBuilder.byteTag("Flight", MathUtils.convertByte(fireworks.get("Flight").getValue())); } List explosions = new ArrayList<>(); @@ -73,7 +74,7 @@ public class FireworkEntity extends Entity { CompoundTagBuilder effectBuilder = CompoundTagBuilder.builder(); if (effectData.get("Type") != null) { - effectBuilder.byteTag("FireworkType", (Byte) effectData.get("Type").getValue()); + effectBuilder.byteTag("FireworkType", MathUtils.convertByte(effectData.get("Type").getValue())); } if (effectData.get("Colors") != null) { @@ -101,11 +102,11 @@ public class FireworkEntity extends Entity { } if (effectData.get("Trail") != null) { - effectBuilder.byteTag("FireworkTrail", (Byte) effectData.get("Trail").getValue()); + effectBuilder.byteTag("FireworkTrail", MathUtils.convertByte(effectData.get("Trail").getValue())); } if (effectData.get("Flicker") != null) { - effectBuilder.byteTag("FireworkFlicker", (Byte) effectData.get("Flicker").getValue()); + effectBuilder.byteTag("FireworkFlicker", MathUtils.convertByte(effectData.get("Flicker").getValue())); } explosions.add(effectBuilder.buildRootTag()); diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/FireworkTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/FireworkTranslator.java index 268fe3932..5b5182a5b 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/FireworkTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/FireworkTranslator.java @@ -27,9 +27,10 @@ package org.geysermc.connector.network.translators.item.translators.nbt; import com.github.steveice10.opennbt.tag.builtin.*; import org.geysermc.connector.network.translators.ItemRemapper; -import org.geysermc.connector.network.translators.item.NbtItemStackTranslator; import org.geysermc.connector.network.translators.item.ItemEntry; +import org.geysermc.connector.network.translators.item.NbtItemStackTranslator; import org.geysermc.connector.utils.FireworkColor; +import org.geysermc.connector.utils.MathUtils; @ItemRemapper public class FireworkTranslator extends NbtItemStackTranslator { @@ -41,6 +42,10 @@ public class FireworkTranslator extends NbtItemStackTranslator { } CompoundTag fireworks = itemTag.get("Fireworks"); + if (fireworks.get("Flight") != null) { + fireworks.put(new ByteTag("Flight", MathUtils.convertByte(fireworks.get("Flight").getValue()))); + } + ListTag explosions = fireworks.get("Explosions"); if (explosions == null) { return; @@ -51,7 +56,7 @@ public class FireworkTranslator extends NbtItemStackTranslator { CompoundTag newEffectData = new CompoundTag(""); if (effectData.get("Type") != null) { - newEffectData.put(new ByteTag("FireworkType", (Byte) effectData.get("Type").getValue())); + newEffectData.put(new ByteTag("FireworkType", MathUtils.convertByte(effectData.get("Type").getValue()))); } if (effectData.get("Colors") != null) { @@ -79,11 +84,11 @@ public class FireworkTranslator extends NbtItemStackTranslator { } if (effectData.get("Trail") != null) { - newEffectData.put(new ByteTag("FireworkTrail", (Byte) effectData.get("Trail").getValue())); + newEffectData.put(new ByteTag("FireworkTrail", MathUtils.convertByte(effectData.get("Trail").getValue()))); } if (effectData.get("Flicker") != null) { - newEffectData.put(new ByteTag("FireworkFlicker", (Byte) effectData.get("Flicker").getValue())); + newEffectData.put(new ByteTag("FireworkFlicker", MathUtils.convertByte(effectData.get("Flicker").getValue()))); } explosions.remove(effect); @@ -94,6 +99,9 @@ public class FireworkTranslator extends NbtItemStackTranslator { @Override public void translateToJava(CompoundTag itemTag, ItemEntry itemEntry) { CompoundTag fireworks = itemTag.get("Fireworks"); + if (fireworks.get("Flight") != null) { + fireworks.put(new ByteTag("Flight", MathUtils.convertByte(fireworks.get("Flight").getValue()))); + } ListTag explosions = fireworks.get("Explosions"); for (Tag effect : explosions.getValue()) { @@ -102,7 +110,7 @@ public class FireworkTranslator extends NbtItemStackTranslator { CompoundTag newEffectData = new CompoundTag(""); if (effectData.get("FireworkType") != null) { - newEffectData.put(new ByteTag("Type", (Byte) effectData.get("FireworkType").getValue())); + newEffectData.put(new ByteTag("Type", MathUtils.convertByte(effectData.get("FireworkType").getValue()))); } if (effectData.get("FireworkColor") != null) { @@ -130,11 +138,11 @@ public class FireworkTranslator extends NbtItemStackTranslator { } if (effectData.get("FireworkTrail") != null) { - newEffectData.put(new ByteTag("Trail", (Byte) effectData.get("FireworkTrail").getValue())); + newEffectData.put(new ByteTag("Trail", MathUtils.convertByte(effectData.get("FireworkTrail").getValue()))); } if (effectData.get("FireworkFlicker") != null) { - newEffectData.put(new ByteTag("Flicker", (Byte) effectData.get("FireworkFlicker").getValue())); + newEffectData.put(new ByteTag("Flicker", MathUtils.convertByte(effectData.get("FireworkFlicker").getValue()))); } explosions.remove(effect); diff --git a/connector/src/main/java/org/geysermc/connector/utils/MathUtils.java b/connector/src/main/java/org/geysermc/connector/utils/MathUtils.java index 4e8497c6d..f66e869db 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/MathUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/MathUtils.java @@ -37,4 +37,19 @@ public class MathUtils { int truncated = (int) floatNumber; return floatNumber > truncated ? truncated + 1 : truncated; } + + /** + * Converts the given object from an int or byte to byte. + * This is used for NBT data that might be either an int + * or byte and bedrock only takes it as an byte + * + * @param value The value to convert + * @return The converted byte + */ + public static Byte convertByte(Object value) { + if (value instanceof Integer) { + return ((Integer) value).byteValue(); + } + return (Byte) value; + } } From 3f76ae1d48e27f111ea91bc955af557d386eed0d Mon Sep 17 00:00:00 2001 From: rtm516 Date: Thu, 28 May 2020 16:43:31 +0100 Subject: [PATCH 129/140] Add ignore for ServerKeepAlivePacket (#664) This packet is already handled by MCProtocolLib for us. Co-authored-by: Camotoy <20743703+DoctorMacc@users.noreply.github.com> --- .../translators/PacketTranslatorRegistry.java | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/PacketTranslatorRegistry.java b/connector/src/main/java/org/geysermc/connector/network/translators/PacketTranslatorRegistry.java index 131363317..c3ec8ff2d 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/PacketTranslatorRegistry.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/PacketTranslatorRegistry.java @@ -25,18 +25,18 @@ package org.geysermc.connector.network.translators; -import java.util.HashMap; -import java.util.Map; - +import com.github.steveice10.mc.protocol.packet.ingame.server.ServerKeepAlivePacket; import com.github.steveice10.mc.protocol.packet.ingame.server.world.ServerUpdateLightPacket; +import com.github.steveice10.packetlib.packet.Packet; +import com.nukkitx.protocol.bedrock.BedrockPacket; import it.unimi.dsi.fastutil.objects.ObjectArrayList; import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.network.session.GeyserSession; - -import com.github.steveice10.packetlib.packet.Packet; -import com.nukkitx.protocol.bedrock.BedrockPacket; import org.reflections.Reflections; +import java.util.HashMap; +import java.util.Map; + public class PacketTranslatorRegistry { private final Map, PacketTranslator> translators = new HashMap<>(); @@ -72,7 +72,8 @@ public class PacketTranslatorRegistry { } } - IGNORED_PACKETS.add(ServerUpdateLightPacket.class); + IGNORED_PACKETS.add(ServerKeepAlivePacket.class); // Handled by MCProtocolLib + IGNORED_PACKETS.add(ServerUpdateLightPacket.class); // Light is handled on Bedrock for us } private PacketTranslatorRegistry() { From 5c8f6eb184d77eed8f82c83c46e9e15c793f4c88 Mon Sep 17 00:00:00 2001 From: Heath123 Date: Fri, 29 May 2020 20:11:38 +0100 Subject: [PATCH 130/140] Fix relative teleports (#688) --- .../JavaPlayerPositionRotationTranslator.java | 32 ++++++++++++++----- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerPositionRotationTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerPositionRotationTranslator.java index 37fb96fb8..a44b200e3 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerPositionRotationTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerPositionRotationTranslator.java @@ -25,6 +25,7 @@ package org.geysermc.connector.network.translators.java.entity.player; +import com.github.steveice10.mc.protocol.data.game.entity.player.PositionElement; import com.github.steveice10.mc.protocol.packet.ingame.client.world.ClientTeleportConfirmPacket; import com.github.steveice10.mc.protocol.packet.ingame.server.entity.player.ServerPlayerPositionRotationPacket; import com.nukkitx.math.vector.Vector3f; @@ -95,20 +96,35 @@ public class JavaPlayerPositionRotationTranslator extends PacketTranslator 1.5 || (yDis < 1.45 || yDis > (session.isJumping() ? 4.3 : (session.isSprinting() ? 2.5 : 1.9))) || zDis > 1.5) { - session.setTeleportCache(new TeleportCache(packet.getX(), packet.getY(), packet.getZ(), packet.getTeleportId())); - entity.moveAbsolute(session, Vector3f.from(packet.getX(), packet.getY(), packet.getZ()), packet.getYaw(), packet.getPitch(), true, true); - } else { + if (!(xDis > 1.5 || (yDis < 1.45 || yDis > (session.isJumping() ? 4.3 : (session.isSprinting() ? 2.5 : 1.9))) || zDis > 1.5)) { + // Fake confirm the teleport but don't send it to the client ClientTeleportConfirmPacket teleportConfirmPacket = new ClientTeleportConfirmPacket(packet.getTeleportId()); session.sendDownstreamPacket(teleportConfirmPacket); + return; } } + + // If coordinates are relative, then add to the existing coordinate + double newX = packet.getX() + + (packet.getRelative().contains(PositionElement.X) ? entity.getPosition().getX() : 0); + double newY = packet.getY() + + (packet.getRelative().contains(PositionElement.Y) ? entity.getPosition().getY() - EntityType.PLAYER.getOffset() : 0); + double newZ = packet.getZ() + + (packet.getRelative().contains(PositionElement.Z) ? entity.getPosition().getZ() : 0); + + double newPitch = packet.getPitch() + + (packet.getRelative().contains(PositionElement.PITCH) ? entity.getBedrockRotation().getX() : 0); + double newYaw = packet.getYaw() + + (packet.getRelative().contains(PositionElement.YAW) ? entity.getBedrockRotation().getY() : 0); + + + session.setTeleportCache(new TeleportCache(newX, newY, newZ, packet.getTeleportId())); + entity.moveAbsolute(session, Vector3f.from(newX, newY, newZ), (float) newYaw, (float) newPitch, true, true); } } From 64e32046113e87bf37884c47e558a9f50317cb80 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+DoctorMacc@users.noreply.github.com> Date: Fri, 29 May 2020 19:56:21 -0400 Subject: [PATCH 131/140] Implement translator for AdventureSettingsPacket (#691) * Implement translator for AdventureSettingsPacket The AdventureSettingsPacket is translated into ClientSettingsPacket so the MAY_FLY and FLYING flags are sent to the server. This fixes double-jumping on some servers that rely on the client sending their flying information through this packet. * Remove top-secret code analysis --- .../BedrockAdventureSettingsTranslator.java | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockAdventureSettingsTranslator.java diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockAdventureSettingsTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockAdventureSettingsTranslator.java new file mode 100644 index 000000000..75a1547f5 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockAdventureSettingsTranslator.java @@ -0,0 +1,51 @@ +/* + * 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.bedrock; + +import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode; +import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerAbilitiesPacket; +import com.nukkitx.protocol.bedrock.packet.AdventureSettingsPacket; +import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.PacketTranslator; +import org.geysermc.connector.network.translators.Translator; + +@Translator(packet = AdventureSettingsPacket.class) +public class BedrockAdventureSettingsTranslator extends PacketTranslator { + + @Override + public void translate(AdventureSettingsPacket packet, GeyserSession session) { + // Only canFly and flying are used by the server + // https://wiki.vg/Protocol#Player_Abilities_.28serverbound.29 + boolean canFly = packet.getFlags().contains(AdventureSettingsPacket.Flag.MAY_FLY); + boolean flying = packet.getFlags().contains(AdventureSettingsPacket.Flag.FLYING); + boolean creative = session.getGameMode() == GameMode.CREATIVE; + ClientPlayerAbilitiesPacket abilitiesPacket = new ClientPlayerAbilitiesPacket( + false, canFly, flying, creative, 0.05f, 0.1f + ); + session.sendDownstreamPacket(abilitiesPacket); + } +} From b8a3009c9d763b5efb6098bd1f8f7d54521d15f8 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+DoctorMacc@users.noreply.github.com> Date: Sat, 30 May 2020 18:31:20 -0400 Subject: [PATCH 132/140] Ignore all downstream packet errors (#693) * Ignore all downstream packet errors Instead of kicking the client off because of an error, we simply display a logger warning and suppress the error. * If debug mode, print stacktrace --- connector/pom.xml | 2 +- .../geysermc/connector/network/session/GeyserSession.java | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/connector/pom.xml b/connector/pom.xml index 229761adf..5743c0c63 100644 --- a/connector/pom.xml +++ b/connector/pom.xml @@ -105,7 +105,7 @@ com.github.steveice10 packetlib - 1.5-SNAPSHOT + 1.6-SNAPSHOT compile diff --git a/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java b/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java index cc052509a..ad5caf145 100644 --- a/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java +++ b/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java @@ -366,6 +366,14 @@ public class GeyserSession implements CommandSender { PacketTranslatorRegistry.JAVA_TRANSLATOR.translate(event.getPacket().getClass(), event.getPacket(), GeyserSession.this); } } + + @Override + public void packetError(PacketErrorEvent event) { + connector.getLogger().warning("Downstream packet error! " + event.getCause().getMessage()); + if (connector.getConfig().isDebugMode()) + event.getCause().printStackTrace(); + event.setSuppress(true); + } }); downstream.getSession().connect(); From b8615874f9b4b601b5fe39b36c2a242618d19406 Mon Sep 17 00:00:00 2001 From: rtm516 Date: Mon, 1 Jun 2020 02:46:36 +0100 Subject: [PATCH 133/140] Add furnace minecart (#712) Adds the display of the furnace minecart, functions as expected. --- .../entity/FurnaceMinecartEntity.java | 54 +++++++++++++++++++ .../connector/entity/type/EntityType.java | 2 +- .../world/block/BlockTranslator.java | 23 ++++++++ 3 files changed, 78 insertions(+), 1 deletion(-) create mode 100644 connector/src/main/java/org/geysermc/connector/entity/FurnaceMinecartEntity.java diff --git a/connector/src/main/java/org/geysermc/connector/entity/FurnaceMinecartEntity.java b/connector/src/main/java/org/geysermc/connector/entity/FurnaceMinecartEntity.java new file mode 100644 index 000000000..ad2db877f --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/entity/FurnaceMinecartEntity.java @@ -0,0 +1,54 @@ +/* + * 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.entity; + +import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata; +import com.nukkitx.math.vector.Vector3f; +import com.nukkitx.protocol.bedrock.data.EntityData; +import org.geysermc.connector.entity.type.EntityType; +import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.world.block.BlockTranslator; + +public class FurnaceMinecartEntity extends MinecartEntity { + + public FurnaceMinecartEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { + super(entityId, geyserId, entityType, position, motion, rotation); + + metadata.put(EntityData.DISPLAY_ITEM, BlockTranslator.getBedrockBlockId(BlockTranslator.JAVA_RUNTIME_FURNACE_ID)); + metadata.put(EntityData.HAS_DISPLAY, (byte) 1); + } + + @Override + public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { + if (entityMetadata.getId() == 13) { + boolean hasFuel = (boolean) entityMetadata.getValue(); + + metadata.put(EntityData.DISPLAY_ITEM, BlockTranslator.getBedrockBlockId(hasFuel ? BlockTranslator.JAVA_RUNTIME_FURNACE_LIT_ID : BlockTranslator.JAVA_RUNTIME_FURNACE_ID)); + } + + super.updateBedrockMetadata(entityMetadata, session); + } +} diff --git a/connector/src/main/java/org/geysermc/connector/entity/type/EntityType.java b/connector/src/main/java/org/geysermc/connector/entity/type/EntityType.java index 889341965..cbe8e4cc9 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/type/EntityType.java +++ b/connector/src/main/java/org/geysermc/connector/entity/type/EntityType.java @@ -133,7 +133,7 @@ public enum EntityType { MINECART_HOPPER(MinecartEntity.class, 96, 0.7f, 0.98f, 0.98f, 0.35f, "minecraft:hopper_minecart"), MINECART_TNT(MinecartEntity.class, 97, 0.7f, 0.98f, 0.98f, 0.35f, "minecraft:tnt_minecart"), MINECART_CHEST(MinecartEntity.class, 98, 0.7f, 0.98f, 0.98f, 0.35f, "minecraft:chest_minecart"), - + MINECART_FURNACE(FurnaceMinecartEntity.class, 98, 0.7f, 0.98f, 0.98f, 0.35f, "minecraft:minecart"), MINECART_COMMAND_BLOCK(MinecartEntity.class, 100, 0.7f, 0.98f, 0.98f, 0.35f, "minecraft:command_block_minecart"), LINGERING_POTION(ThrowableEntity.class, 101, 0f), LLAMA_SPIT(Entity.class, 102, 0.25f), diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/world/block/BlockTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/BlockTranslator.java index a40dd15f3..781dc3260 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/world/block/BlockTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/BlockTranslator.java @@ -69,6 +69,9 @@ public class BlockTranslator { public static final IntSet JAVA_RUNTIME_WOOL_IDS = new IntOpenHashSet(); public static final int JAVA_RUNTIME_COBWEB_ID; + public static final int JAVA_RUNTIME_FURNACE_ID; + public static final int JAVA_RUNTIME_FURNACE_LIT_ID; + private static final int BLOCK_STATE_VERSION = 17760256; static { @@ -108,6 +111,8 @@ public class BlockTranslator { int javaRuntimeId = -1; int bedrockRuntimeId = 0; int cobwebRuntimeId = -1; + int furnaceRuntimeId = -1; + int furnaceLitRuntimeId = -1; Iterator> blocksIterator = blocks.fields(); while (blocksIterator.hasNext()) { javaRuntimeId++; @@ -186,6 +191,14 @@ public class BlockTranslator { } JAVA_TO_BEDROCK_BLOCK_MAP.put(javaRuntimeId, bedrockRuntimeId); + if (javaId.startsWith("minecraft:furnace[facing=north")) { + if (javaId.contains("lit=true")) { + furnaceLitRuntimeId = javaRuntimeId; + } else { + furnaceRuntimeId = javaRuntimeId; + } + } + bedrockRuntimeId++; } @@ -194,6 +207,16 @@ public class BlockTranslator { } JAVA_RUNTIME_COBWEB_ID = cobwebRuntimeId; + if (furnaceRuntimeId == -1) { + throw new AssertionError("Unable to find furnace in palette"); + } + JAVA_RUNTIME_FURNACE_ID = furnaceRuntimeId; + + if (furnaceLitRuntimeId == -1) { + throw new AssertionError("Unable to find lit furnace in palette"); + } + JAVA_RUNTIME_FURNACE_LIT_ID = furnaceLitRuntimeId; + if (waterRuntimeId == -1) { throw new AssertionError("Unable to find water in palette"); } From 215e5a7e214f3cc429f077c37b83674c34210c39 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+DoctorMacc@users.noreply.github.com> Date: Sun, 31 May 2020 21:47:54 -0400 Subject: [PATCH 134/140] Add custom minecart metadata (#713) Adds display item, offset, and enable values. --- .../connector/entity/MinecartEntity.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/connector/src/main/java/org/geysermc/connector/entity/MinecartEntity.java b/connector/src/main/java/org/geysermc/connector/entity/MinecartEntity.java index ee004a257..c2d7d47d5 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/MinecartEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/MinecartEntity.java @@ -30,6 +30,7 @@ import com.nukkitx.math.vector.Vector3f; import com.nukkitx.protocol.bedrock.data.EntityData; import org.geysermc.connector.entity.type.EntityType; import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.world.block.BlockTranslator; public class MinecartEntity extends Entity { @@ -54,6 +55,22 @@ public class MinecartEntity extends Entity { metadata.put(EntityData.HURT_TIME, Math.min((int) (float) entityMetadata.getValue(), 15)); } + // Custom block + if (entityMetadata.getId() == 10) { + metadata.put(EntityData.DISPLAY_ITEM, BlockTranslator.getBedrockBlockId((int) entityMetadata.getValue())); + } + + // Custom block offset + if (entityMetadata.getId() == 11) { + metadata.put(EntityData.DISPLAY_OFFSET, entityMetadata.getValue()); + } + + // If the custom block should be enabled + if (entityMetadata.getId() == 12) { + // Needs a byte based off of Java's boolean + metadata.put(EntityData.HAS_DISPLAY, (byte) ((boolean) entityMetadata.getValue() ? 1 : 0)); + } + super.updateBedrockMetadata(entityMetadata, session); } From ac5ab229f977176b078edbe21d682a8c32e8a92d Mon Sep 17 00:00:00 2001 From: rtm516 Date: Mon, 1 Jun 2020 20:57:27 +0100 Subject: [PATCH 135/140] Fix Ender Crystal collision and explosion effects (#716) Fixed the collision box being non-existent for ender crystals and fixed explosion effects not being displayed properly --- .../connector/entity/type/EntityType.java | 2 +- .../java/world/JavaExplosionTranslator.java | 15 +++++++++------ 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/entity/type/EntityType.java b/connector/src/main/java/org/geysermc/connector/entity/type/EntityType.java index cbe8e4cc9..2cfe54c6b 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/type/EntityType.java +++ b/connector/src/main/java/org/geysermc/connector/entity/type/EntityType.java @@ -105,7 +105,7 @@ public enum EntityType { THROWN_EXP_BOTTLE(ThrowableEntity.class, 68, 0.25f, 0.25f, 0f, 0f, "minecraft:xp_bottle"), EXPERIENCE_ORB(ExpOrbEntity.class, 69, 0f, 0f, 0f, 0f, "minecraft:xp_orb"), EYE_OF_ENDER(Entity.class, 70, 0.25f, 0.25f, 0f, 0f, "minecraft:eye_of_ender_signal"), - END_CRYSTAL(EnderCrystalEntity.class, 71, 0f, 0f, 0f, 0f, "minecraft:ender_crystal"), + END_CRYSTAL(EnderCrystalEntity.class, 71, 2.0f, 2.0f, 2.0f, 0f, "minecraft:ender_crystal"), FIREWORK_ROCKET(FireworkEntity.class, 72, 0.25f, 0.25f, 0.25f, 0f, "minecraft:fireworks_rocket"), TRIDENT(TridentEntity.class, 73, 0f, 0f, 0f, 0f, "minecraft:thrown_trident"), TURTLE(AnimalEntity.class, 74, 0.4f, 1.2f), diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaExplosionTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaExplosionTranslator.java index 49a17f987..79b27f6a5 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaExplosionTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaExplosionTranslator.java @@ -46,14 +46,17 @@ public class JavaExplosionTranslator extends PacketTranslator= 2.0f ? LevelEventType.PARTICLE_HUGE_EXPLODE : LevelEventType.PARTICLE_LARGE_EXPLOSION); + levelEventPacket.setData(0); + levelEventPacket.setPosition(pos.toFloat()); + session.sendUpstreamPacket(levelEventPacket); + LevelSoundEventPacket levelSoundEventPacket = new LevelSoundEventPacket(); levelSoundEventPacket.setRelativeVolumeDisabled(false); levelSoundEventPacket.setBabySound(false); From 5bb345daa683ec0e755afc9ee0ab59f4087db337 Mon Sep 17 00:00:00 2001 From: rtm516 Date: Mon, 1 Jun 2020 20:59:46 +0100 Subject: [PATCH 136/140] Fix new minecart with block breaking furnace minecart display (#717) This handles DISPLAY_ITEM and related properties separately on furnace minecarts in order to prevent overwriting furnace minecart graphics. Co-authored-by: DoctorMacc --- .../entity/FurnaceMinecartEntity.java | 38 +++++++++++++++++-- .../connector/entity/MinecartEntity.java | 26 +++++++------ 2 files changed, 49 insertions(+), 15 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/entity/FurnaceMinecartEntity.java b/connector/src/main/java/org/geysermc/connector/entity/FurnaceMinecartEntity.java index ad2db877f..ad9be77f8 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/FurnaceMinecartEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/FurnaceMinecartEntity.java @@ -34,6 +34,11 @@ import org.geysermc.connector.network.translators.world.block.BlockTranslator; public class FurnaceMinecartEntity extends MinecartEntity { + private int customBlock = 0; + private int customBlockOffset = 0; + private boolean showCustomBlock = false; + private boolean hasFuel = false; + public FurnaceMinecartEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { super(entityId, geyserId, entityType, position, motion, rotation); @@ -43,12 +48,39 @@ public class FurnaceMinecartEntity extends MinecartEntity { @Override public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { - if (entityMetadata.getId() == 13) { - boolean hasFuel = (boolean) entityMetadata.getValue(); - metadata.put(EntityData.DISPLAY_ITEM, BlockTranslator.getBedrockBlockId(hasFuel ? BlockTranslator.JAVA_RUNTIME_FURNACE_LIT_ID : BlockTranslator.JAVA_RUNTIME_FURNACE_ID)); + // Custom block + if (entityMetadata.getId() == 10) { + customBlock = (int) entityMetadata.getValue(); + } + + // Custom block offset + if (entityMetadata.getId() == 11) { + customBlockOffset = (int) entityMetadata.getValue(); + } + + // If the custom block should be enabled + if (entityMetadata.getId() == 12) { + if ((boolean) entityMetadata.getValue()) { + showCustomBlock = true; + metadata.put(EntityData.DISPLAY_ITEM, BlockTranslator.getBedrockBlockId(customBlock)); + metadata.put(EntityData.DISPLAY_OFFSET, customBlockOffset); + } else { + showCustomBlock = false; + updateFurnaceMetadata(); + } + } + + if (entityMetadata.getId() == 13 && !showCustomBlock) { + hasFuel = (boolean) entityMetadata.getValue(); + updateFurnaceMetadata(); } super.updateBedrockMetadata(entityMetadata, session); } + + private void updateFurnaceMetadata() { + metadata.put(EntityData.DISPLAY_ITEM, BlockTranslator.getBedrockBlockId(hasFuel ? BlockTranslator.JAVA_RUNTIME_FURNACE_LIT_ID : BlockTranslator.JAVA_RUNTIME_FURNACE_ID)); + metadata.put(EntityData.DISPLAY_OFFSET, 6); + } } diff --git a/connector/src/main/java/org/geysermc/connector/entity/MinecartEntity.java b/connector/src/main/java/org/geysermc/connector/entity/MinecartEntity.java index c2d7d47d5..cdc3d8f24 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/MinecartEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/MinecartEntity.java @@ -55,20 +55,22 @@ public class MinecartEntity extends Entity { metadata.put(EntityData.HURT_TIME, Math.min((int) (float) entityMetadata.getValue(), 15)); } - // Custom block - if (entityMetadata.getId() == 10) { - metadata.put(EntityData.DISPLAY_ITEM, BlockTranslator.getBedrockBlockId((int) entityMetadata.getValue())); - } + if (!(this instanceof FurnaceMinecartEntity)) { // Handled in FurnaceMinecartEntity.java + // Custom block + if (entityMetadata.getId() == 10) { + metadata.put(EntityData.DISPLAY_ITEM, BlockTranslator.getBedrockBlockId((int) entityMetadata.getValue())); + } - // Custom block offset - if (entityMetadata.getId() == 11) { - metadata.put(EntityData.DISPLAY_OFFSET, entityMetadata.getValue()); - } + // Custom block offset + if (entityMetadata.getId() == 11) { + metadata.put(EntityData.DISPLAY_OFFSET, entityMetadata.getValue()); + } - // If the custom block should be enabled - if (entityMetadata.getId() == 12) { - // Needs a byte based off of Java's boolean - metadata.put(EntityData.HAS_DISPLAY, (byte) ((boolean) entityMetadata.getValue() ? 1 : 0)); + // If the custom block should be enabled + if (entityMetadata.getId() == 12) { + // Needs a byte based off of Java's boolean + metadata.put(EntityData.HAS_DISPLAY, (byte) ((boolean) entityMetadata.getValue() ? 1 : 0)); + } } super.updateBedrockMetadata(entityMetadata, session); From 05024dde8c9181209bccf8db5e3ccd986926f1e2 Mon Sep 17 00:00:00 2001 From: AJ Ferguson Date: Mon, 1 Jun 2020 18:19:16 -0800 Subject: [PATCH 137/140] Don't manually grab MCProtocolLib's dependencies (#720) * Don't manually grab MCProtocolLib's dependencies * Add netty-resolver-dns and exclude netty-all --- connector/pom.xml | 36 +++++------------------------------- 1 file changed, 5 insertions(+), 31 deletions(-) diff --git a/connector/pom.xml b/connector/pom.xml index 5743c0c63..9c503dcc4 100644 --- a/connector/pom.xml +++ b/connector/pom.xml @@ -98,14 +98,8 @@ com.github.steveice10 - opennbt - 1.4-SNAPSHOT - compile - - - com.github.steveice10 - packetlib - 1.6-SNAPSHOT + mcprotocollib + 1.15.2-1-SNAPSHOT compile @@ -115,31 +109,11 @@ - com.github.steveice10 - mcauthlib - 1.3-SNAPSHOT + io.netty + netty-resolver-dns + 4.1.43.Final compile - - com.github.steveice10 - mcprotocollib - 1.15.2-1-SNAPSHOT - compile - - - com.github.steveice10 - opennbt - - - com.github.steveice10 - packetlib - - - com.github.steveice10 - mcauthlib - - - org.reflections reflections From 18891a22f1f2e1fba0b5c9fe38570a186c1480b3 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+DoctorMacc@users.noreply.github.com> Date: Tue, 2 Jun 2020 10:45:33 -0400 Subject: [PATCH 138/140] Check for instance of TranslationMessage (#722) Checks for class of custom name ID in case it's translation message. --- .../java/org/geysermc/connector/entity/Entity.java | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/entity/Entity.java b/connector/src/main/java/org/geysermc/connector/entity/Entity.java index 434c983bb..06679934a 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/Entity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/Entity.java @@ -34,6 +34,7 @@ import com.github.steveice10.mc.protocol.data.game.entity.player.PlayerAction; import com.github.steveice10.mc.protocol.data.game.world.block.BlockFace; import com.github.steveice10.mc.protocol.data.game.world.block.BlockState; import com.github.steveice10.mc.protocol.data.message.TextMessage; +import com.github.steveice10.mc.protocol.data.message.TranslationMessage; import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerActionPacket; import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerUseItemPacket; import com.nukkitx.math.vector.Vector3f; @@ -253,9 +254,15 @@ public class Entity { } break; case 2: // custom name - TextMessage name = (TextMessage) entityMetadata.getValue(); - if (name != null) - metadata.put(EntityData.NAMETAG, MessageUtils.getBedrockMessage(name)); + if (entityMetadata.getValue() instanceof TextMessage) { + TextMessage name = (TextMessage) entityMetadata.getValue(); + if (name != null) + metadata.put(EntityData.NAMETAG, MessageUtils.getBedrockMessage(name)); + } else if (entityMetadata.getValue() instanceof TranslationMessage) { + TranslationMessage message = (TranslationMessage) entityMetadata.getValue(); + if (message != null) + metadata.put(EntityData.NAMETAG, MessageUtils.getTranslatedBedrockMessage(message, session.getClientData().getLanguageCode(), true)); + } break; case 3: // is custom name visible if (!this.is(PlayerEntity.class)) From 3d357af739747fcb1afa9bcbd21f52861a6402d5 Mon Sep 17 00:00:00 2001 From: AJ Ferguson Date: Tue, 2 Jun 2020 08:48:26 -0800 Subject: [PATCH 139/140] Inventory Fixes (#602) * Fix edge case when shift clicking an output slot * Don't send window close packet if window is already closed * Limit amount of window close packets sent to the client Fixes hidden inventory bar bug * Restrict user from unusable chest inventory slots * Fix crafting table slot mappings * Always send cursor update --- .../network/session/GeyserSession.java | 3 + .../BedrockContainerCloseTranslator.java | 14 ++-- .../inventory/ChestInventoryTranslator.java | 69 +++++++++++++++++++ .../CraftingInventoryTranslator.java | 5 +- .../DoubleChestInventoryTranslator.java | 16 +---- .../SingleChestInventoryTranslator.java | 30 +++++++- .../action/InventoryActionDataTranslator.java | 14 +++- .../window/JavaCloseWindowTranslator.java | 5 +- .../java/window/JavaOpenWindowTranslator.java | 7 +- .../java/window/JavaSetSlotTranslator.java | 2 - .../connector/utils/InventoryUtils.java | 20 +++++- 11 files changed, 149 insertions(+), 36 deletions(-) create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/inventory/ChestInventoryTranslator.java diff --git a/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java b/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java index ad5caf145..a40443a5b 100644 --- a/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java +++ b/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java @@ -166,6 +166,9 @@ public class GeyserSession implements CommandSender { @Setter private int craftSlot = 0; + @Setter + private long lastWindowCloseTime = 0; + private MinecraftProtocol protocol; public GeyserSession(GeyserConnector connector, BedrockServerSession bedrockServerSession) { diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockContainerCloseTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockContainerCloseTranslator.java index 6f4a243f0..05eac2032 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockContainerCloseTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockContainerCloseTranslator.java @@ -38,17 +38,23 @@ public class BedrockContainerCloseTranslator extends PacketTranslator actions) { + for (InventoryActionData action : actions) { + if (action.getSource().getContainerId() == inventory.getId()) { + if (action.getSlot() >= size) { + updateInventory(session, inventory); + InventoryUtils.updateCursor(session); + return; + } + } + } + + super.translateActions(session, inventory, actions); + } +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/CraftingInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/CraftingInventoryTranslator.java index 3f887001f..e31eb1e36 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/CraftingInventoryTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/CraftingInventoryTranslator.java @@ -92,7 +92,10 @@ public class CraftingInventoryTranslator extends BaseInventoryTranslator { @Override public int javaSlotToBedrock(int slot) { - return slot == 0 ? 50 : slot + 31; + if (slot < size) { + return slot == 0 ? 50 : slot + 31; + } + return super.javaSlotToBedrock(slot); } @Override diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/DoubleChestInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/DoubleChestInventoryTranslator.java index 8c5b2cf20..6d6cadd7d 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/DoubleChestInventoryTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/DoubleChestInventoryTranslator.java @@ -39,15 +39,13 @@ import org.geysermc.connector.network.translators.world.block.BlockTranslator; import org.geysermc.connector.network.translators.inventory.updater.ChestInventoryUpdater; import org.geysermc.connector.network.translators.inventory.updater.InventoryUpdater; -public class DoubleChestInventoryTranslator extends BaseInventoryTranslator { +public class DoubleChestInventoryTranslator extends ChestInventoryTranslator { private final int blockId; - private final InventoryUpdater updater; public DoubleChestInventoryTranslator(int size) { - super(size); + super(size, 54); BlockState javaBlockState = BlockTranslator.getJavaBlockState("minecraft:chest[facing=north,type=single,waterlogged=false]"); this.blockId = BlockTranslator.getBedrockBlockId(javaBlockState); - this.updater = new ChestInventoryUpdater(54); } @Override @@ -128,14 +126,4 @@ public class DoubleChestInventoryTranslator extends BaseInventoryTranslator { blockPacket.setRuntimeId(BlockTranslator.getBedrockBlockId(realBlock)); session.sendUpstreamPacket(blockPacket); } - - @Override - public void updateInventory(GeyserSession session, Inventory inventory) { - updater.updateInventory(this, session, inventory); - } - - @Override - public void updateSlot(GeyserSession session, Inventory inventory, int slot) { - updater.updateSlot(this, session, inventory, slot); - } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/SingleChestInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/SingleChestInventoryTranslator.java index 5c99b0126..3f1a58f4d 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/SingleChestInventoryTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/SingleChestInventoryTranslator.java @@ -25,11 +25,35 @@ package org.geysermc.connector.network.translators.inventory; +import com.github.steveice10.mc.protocol.data.game.world.block.BlockState; import com.nukkitx.protocol.bedrock.data.ContainerType; -import org.geysermc.connector.network.translators.inventory.updater.ChestInventoryUpdater; +import org.geysermc.connector.inventory.Inventory; +import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.inventory.holder.BlockInventoryHolder; +import org.geysermc.connector.network.translators.inventory.holder.InventoryHolder; +import org.geysermc.connector.network.translators.world.block.BlockTranslator; + +public class SingleChestInventoryTranslator extends ChestInventoryTranslator { + private final InventoryHolder holder; -public class SingleChestInventoryTranslator extends BlockInventoryTranslator { public SingleChestInventoryTranslator(int size) { - super(size, "minecraft:chest[facing=north,type=single,waterlogged=false]", ContainerType.CONTAINER, new ChestInventoryUpdater(27)); + super(size, 27); + BlockState javaBlockState = BlockTranslator.getJavaBlockState("minecraft:chest[facing=north,type=single,waterlogged=false]"); + this.holder = new BlockInventoryHolder(BlockTranslator.getBedrockBlockId(javaBlockState), ContainerType.CONTAINER); + } + + @Override + public void prepareInventory(GeyserSession session, Inventory inventory) { + holder.prepareInventory(this, session, inventory); + } + + @Override + public void openInventory(GeyserSession session, Inventory inventory) { + holder.openInventory(this, session, inventory); + } + + @Override + public void closeInventory(GeyserSession session, Inventory inventory) { + holder.closeInventory(this, session, inventory); } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/action/InventoryActionDataTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/action/InventoryActionDataTranslator.java index 9139da1fd..41b218b0e 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/action/InventoryActionDataTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/action/InventoryActionDataTranslator.java @@ -187,11 +187,12 @@ public class InventoryActionDataTranslator { } else if (translator.getSlotType(javaSlot) == SlotType.OUTPUT) { plan.add(Click.LEFT, javaSlot); } else { - int cursorSlot = findTempSlot(inventory, session.getInventory().getCursor(), Collections.singletonList(javaSlot)); + int cursorSlot = findTempSlot(inventory, session.getInventory().getCursor(), Collections.singletonList(javaSlot), false); if (cursorSlot != -1) { plan.add(Click.LEFT, cursorSlot); } else { translator.updateInventory(session, inventory); + InventoryUtils.updateCursor(session); return; } plan.add(Click.LEFT, javaSlot); @@ -245,11 +246,15 @@ public class InventoryActionDataTranslator { int cursorSlot = -1; if (session.getInventory().getCursor() != null) { //move cursor contents to a temporary slot - cursorSlot = findTempSlot(inventory, session.getInventory().getCursor(), Arrays.asList(fromSlot, toSlot)); + cursorSlot = findTempSlot(inventory, + session.getInventory().getCursor(), + Arrays.asList(fromSlot, toSlot), + translator.getSlotType(fromSlot) == SlotType.OUTPUT); if (cursorSlot != -1) { plan.add(Click.LEFT, cursorSlot); } else { translator.updateInventory(session, inventory); + InventoryUtils.updateCursor(session); return; } } @@ -298,7 +303,7 @@ public class InventoryActionDataTranslator { InventoryUtils.updateCursor(session); } - private static int findTempSlot(Inventory inventory, ItemStack item, List slotBlacklist) { + private static int findTempSlot(Inventory inventory, ItemStack item, List slotBlacklist, boolean emptyOnly) { /*try and find a slot that can temporarily store the given item only look in the main inventory and hotbar only slots that are empty or contain a different type of item are valid*/ @@ -314,6 +319,9 @@ public class InventoryActionDataTranslator { ItemStack testItem = inventory.getItem(i); boolean acceptable = true; if (testItem != null) { + if (emptyOnly) { + continue; + } for (ItemStack blacklistItem : itemBlacklist) { if (InventoryUtils.canStack(testItem, blacklistItem)) { acceptable = false; diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/window/JavaCloseWindowTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/window/JavaCloseWindowTranslator.java index 7360cbb2e..93cfa08e4 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/window/JavaCloseWindowTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/window/JavaCloseWindowTranslator.java @@ -26,7 +26,6 @@ package org.geysermc.connector.network.translators.java.window; import com.github.steveice10.mc.protocol.packet.ingame.server.window.ServerCloseWindowPacket; -import com.nukkitx.protocol.bedrock.packet.ContainerClosePacket; import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.PacketTranslator; import org.geysermc.connector.network.translators.Translator; @@ -37,9 +36,7 @@ public class JavaCloseWindowTranslator extends PacketTranslator { @@ -80,8 +78,11 @@ public class JavaOpenWindowTranslator extends PacketTranslator InventoryUtils.openInventory(session, newInventory), 500, TimeUnit.MILLISECONDS); + session.getInventoryCache().setOpenInventory(newInventory); + //The new window will be opened when the bedrock client sends the + //window close confirmation in BedrockContainerCloseTranslator return; } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/window/JavaSetSlotTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/window/JavaSetSlotTranslator.java index 5d44069fe..19d7db217 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/window/JavaSetSlotTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/window/JavaSetSlotTranslator.java @@ -41,8 +41,6 @@ public class JavaSetSlotTranslator extends PacketTranslator @Override public void translate(ServerSetSlotPacket packet, GeyserSession session) { if (packet.getWindowId() == 255 && packet.getSlot() == -1) { //cursor - if (Objects.equals(session.getInventory().getCursor(), packet.getItem())) - return; if (session.getCraftSlot() != 0) return; diff --git a/connector/src/main/java/org/geysermc/connector/utils/InventoryUtils.java b/connector/src/main/java/org/geysermc/connector/utils/InventoryUtils.java index fd4c5e4e5..187d09513 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/InventoryUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/InventoryUtils.java @@ -31,6 +31,7 @@ import com.nukkitx.nbt.CompoundTagBuilder; import com.nukkitx.nbt.tag.StringTag; import com.nukkitx.protocol.bedrock.data.ContainerId; import com.nukkitx.protocol.bedrock.data.ItemData; +import com.nukkitx.protocol.bedrock.packet.ContainerClosePacket; import com.nukkitx.protocol.bedrock.packet.InventorySlotPacket; import org.geysermc.common.ChatColor; import org.geysermc.connector.GeyserConnector; @@ -69,19 +70,34 @@ public class InventoryUtils { public static void closeInventory(GeyserSession session, int windowId) { if (windowId != 0) { Inventory inventory = session.getInventoryCache().getInventories().get(windowId); - if (inventory != null) { + Inventory openInventory = session.getInventoryCache().getOpenInventory(); + session.getInventoryCache().uncacheInventory(windowId); + if (inventory != null && openInventory != null && inventory.getId() == openInventory.getId()) { InventoryTranslator translator = InventoryTranslator.INVENTORY_TRANSLATORS.get(inventory.getWindowType()); translator.closeInventory(session, inventory); - session.getInventoryCache().uncacheInventory(windowId); session.getInventoryCache().setOpenInventory(null); + } else { + return; } } else { Inventory inventory = session.getInventory(); InventoryTranslator translator = InventoryTranslator.INVENTORY_TRANSLATORS.get(inventory.getWindowType()); translator.updateInventory(session, inventory); } + session.setCraftSlot(0); session.getInventory().setCursor(null); + updateCursor(session); + } + + public static void closeWindow(GeyserSession session, int windowId) { + //Spamming close window packets can bug the client + if (System.currentTimeMillis() - session.getLastWindowCloseTime() > 500) { + ContainerClosePacket closePacket = new ContainerClosePacket(); + closePacket.setWindowId((byte) windowId); + session.sendUpstreamPacket(closePacket); + session.setLastWindowCloseTime(System.currentTimeMillis()); + } } public static void updateCursor(GeyserSession session) { From a91eaa7821f0db4d00a6b6216dca93f543510d66 Mon Sep 17 00:00:00 2001 From: rtm516 Date: Tue, 2 Jun 2020 21:33:37 +0100 Subject: [PATCH 140/140] Add item name translation (#559) * Added item name translation * Change to more appropriate NPE catch * Remove whitespace * Switch from try/catch to null checking * Update mappings Co-authored-by: DoctorMacc --- .../geysermc/connector/entity/ItemEntity.java | 2 +- .../connector/entity/ItemFrameEntity.java | 2 +- .../inventory/PlayerInventoryTranslator.java | 14 +++---- .../action/InventoryActionDataTranslator.java | 4 +- .../updater/ChestInventoryUpdater.java | 4 +- .../updater/ContainerInventoryUpdater.java | 4 +- .../updater/CursorInventoryUpdater.java | 4 +- .../inventory/updater/InventoryUpdater.java | 4 +- .../translators/item/ItemTranslator.java | 40 +++++++++++++++++-- .../java/JavaDeclareRecipesTranslator.java | 8 ++-- .../entity/JavaEntityEquipmentTranslator.java | 2 +- .../world/JavaSpawnParticleTranslator.java | 2 +- .../connector/utils/InventoryUtils.java | 2 +- 13 files changed, 63 insertions(+), 29 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/entity/ItemEntity.java b/connector/src/main/java/org/geysermc/connector/entity/ItemEntity.java index bd18dc46e..41308a0de 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/ItemEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/ItemEntity.java @@ -49,7 +49,7 @@ public class ItemEntity extends Entity { itemPacket.setUniqueEntityId(geyserId); itemPacket.setFromFishing(false); itemPacket.getMetadata().putAll(metadata); - itemPacket.setItemInHand(ItemTranslator.translateToBedrock((ItemStack) entityMetadata.getValue())); + itemPacket.setItemInHand(ItemTranslator.translateToBedrock(session, (ItemStack) entityMetadata.getValue())); session.sendUpstreamPacket(itemPacket); } diff --git a/connector/src/main/java/org/geysermc/connector/entity/ItemFrameEntity.java b/connector/src/main/java/org/geysermc/connector/entity/ItemFrameEntity.java index a6d8af154..3680945cb 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/ItemFrameEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/ItemFrameEntity.java @@ -98,7 +98,7 @@ public class ItemFrameEntity extends Entity { @Override public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { if (entityMetadata.getId() == 7 && entityMetadata.getValue() != null) { - ItemData itemData = ItemTranslator.translateToBedrock((ItemStack) entityMetadata.getValue()); + ItemData itemData = ItemTranslator.translateToBedrock(session, (ItemStack) entityMetadata.getValue()); ItemEntry itemEntry = ItemRegistry.getItem((ItemStack) entityMetadata.getValue()); CompoundTagBuilder builder = CompoundTag.builder(); diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/PlayerInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/PlayerInventoryTranslator.java index 055b69efd..28986e58c 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/PlayerInventoryTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/PlayerInventoryTranslator.java @@ -59,11 +59,11 @@ public class PlayerInventoryTranslator extends InventoryTranslator { ItemData[] contents = new ItemData[36]; // Inventory for (int i = 9; i < 36; i++) { - contents[i] = ItemTranslator.translateToBedrock(inventory.getItem(i)); + contents[i] = ItemTranslator.translateToBedrock(session, inventory.getItem(i)); } // Hotbar for (int i = 36; i < 45; i++) { - contents[i - 36] = ItemTranslator.translateToBedrock(inventory.getItem(i)); + contents[i - 36] = ItemTranslator.translateToBedrock(session, inventory.getItem(i)); } inventoryContentPacket.setContents(contents); session.sendUpstreamPacket(inventoryContentPacket); @@ -73,7 +73,7 @@ public class PlayerInventoryTranslator extends InventoryTranslator { armorContentPacket.setContainerId(ContainerId.ARMOR); contents = new ItemData[4]; for (int i = 5; i < 9; i++) { - contents[i - 5] = ItemTranslator.translateToBedrock(inventory.getItem(i)); + contents[i - 5] = ItemTranslator.translateToBedrock(session, inventory.getItem(i)); } armorContentPacket.setContents(contents); session.sendUpstreamPacket(armorContentPacket); @@ -81,7 +81,7 @@ public class PlayerInventoryTranslator extends InventoryTranslator { // Offhand InventoryContentPacket offhandPacket = new InventoryContentPacket(); offhandPacket.setContainerId(ContainerId.OFFHAND); - offhandPacket.setContents(new ItemData[]{ItemTranslator.translateToBedrock(inventory.getItem(45))}); + offhandPacket.setContents(new ItemData[]{ItemTranslator.translateToBedrock(session, inventory.getItem(45))}); session.sendUpstreamPacket(offhandPacket); } @@ -100,7 +100,7 @@ public class PlayerInventoryTranslator extends InventoryTranslator { if (session.getGameMode() == GameMode.CREATIVE) { slotPacket.setItem(UNUSUABLE_CRAFTING_SPACE_BLOCK); }else{ - slotPacket.setItem(ItemTranslator.translateToBedrock(inventory.getItem(i))); + slotPacket.setItem(ItemTranslator.translateToBedrock(session, inventory.getItem(i))); } session.sendUpstreamPacket(slotPacket); @@ -125,12 +125,12 @@ public class PlayerInventoryTranslator extends InventoryTranslator { slotPacket.setContainerId(ContainerId.CURSOR); slotPacket.setSlot(slot + 27); } - slotPacket.setItem(ItemTranslator.translateToBedrock(inventory.getItem(slot))); + slotPacket.setItem(ItemTranslator.translateToBedrock(session, inventory.getItem(slot))); session.sendUpstreamPacket(slotPacket); } else if (slot == 45) { InventoryContentPacket offhandPacket = new InventoryContentPacket(); offhandPacket.setContainerId(ContainerId.OFFHAND); - offhandPacket.setContents(new ItemData[]{ItemTranslator.translateToBedrock(inventory.getItem(slot))}); + offhandPacket.setContents(new ItemData[]{ItemTranslator.translateToBedrock(session, inventory.getItem(slot))}); session.sendUpstreamPacket(offhandPacket); } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/action/InventoryActionDataTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/action/InventoryActionDataTranslator.java index 41b218b0e..209df0748 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/action/InventoryActionDataTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/action/InventoryActionDataTranslator.java @@ -61,13 +61,13 @@ public class InventoryActionDataTranslator { worldAction = action; } else if (action.getSource().getContainerId() == ContainerId.CURSOR && action.getSlot() == 0) { cursorAction = action; - ItemData translatedCursor = ItemTranslator.translateToBedrock(session.getInventory().getCursor()); + ItemData translatedCursor = ItemTranslator.translateToBedrock(session, session.getInventory().getCursor()); if (!translatedCursor.equals(action.getFromItem())) { refresh = true; } } else { containerAction = action; - ItemData translatedItem = ItemTranslator.translateToBedrock(inventory.getItem(translator.bedrockSlotToJava(action))); + ItemData translatedItem = ItemTranslator.translateToBedrock(session, inventory.getItem(translator.bedrockSlotToJava(action))); if (!translatedItem.equals(action.getFromItem())) { refresh = true; } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/ChestInventoryUpdater.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/ChestInventoryUpdater.java index 61bbda501..6ec8d4810 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/ChestInventoryUpdater.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/ChestInventoryUpdater.java @@ -49,7 +49,7 @@ public class ChestInventoryUpdater extends InventoryUpdater { ItemData[] bedrockItems = new ItemData[paddedSize]; for (int i = 0; i < bedrockItems.length; i++) { if (i < translator.size) { - bedrockItems[i] = ItemTranslator.translateToBedrock(inventory.getItem(i)); + bedrockItems[i] = ItemTranslator.translateToBedrock(session, inventory.getItem(i)); } else { bedrockItems[i] = UNUSUABLE_SPACE_BLOCK; } @@ -69,7 +69,7 @@ public class ChestInventoryUpdater extends InventoryUpdater { InventorySlotPacket slotPacket = new InventorySlotPacket(); slotPacket.setContainerId(inventory.getId()); slotPacket.setSlot(translator.javaSlotToBedrock(javaSlot)); - slotPacket.setItem(ItemTranslator.translateToBedrock(inventory.getItem(javaSlot))); + slotPacket.setItem(ItemTranslator.translateToBedrock(session, inventory.getItem(javaSlot))); session.sendUpstreamPacket(slotPacket); return true; } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/ContainerInventoryUpdater.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/ContainerInventoryUpdater.java index e84c29310..ec6175c36 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/ContainerInventoryUpdater.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/ContainerInventoryUpdater.java @@ -40,7 +40,7 @@ public class ContainerInventoryUpdater extends InventoryUpdater { ItemData[] bedrockItems = new ItemData[translator.size]; for (int i = 0; i < bedrockItems.length; i++) { - bedrockItems[translator.javaSlotToBedrock(i)] = ItemTranslator.translateToBedrock(inventory.getItem(i)); + bedrockItems[translator.javaSlotToBedrock(i)] = ItemTranslator.translateToBedrock(session, inventory.getItem(i)); } InventoryContentPacket contentPacket = new InventoryContentPacket(); @@ -57,7 +57,7 @@ public class ContainerInventoryUpdater extends InventoryUpdater { InventorySlotPacket slotPacket = new InventorySlotPacket(); slotPacket.setContainerId(inventory.getId()); slotPacket.setSlot(translator.javaSlotToBedrock(javaSlot)); - slotPacket.setItem(ItemTranslator.translateToBedrock(inventory.getItem(javaSlot))); + slotPacket.setItem(ItemTranslator.translateToBedrock(session, inventory.getItem(javaSlot))); session.sendUpstreamPacket(slotPacket); return true; } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/CursorInventoryUpdater.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/CursorInventoryUpdater.java index aa7a01746..adbbdbacd 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/CursorInventoryUpdater.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/CursorInventoryUpdater.java @@ -44,7 +44,7 @@ public class CursorInventoryUpdater extends InventoryUpdater { InventorySlotPacket slotPacket = new InventorySlotPacket(); slotPacket.setContainerId(ContainerId.CURSOR); slotPacket.setSlot(bedrockSlot); - slotPacket.setItem(ItemTranslator.translateToBedrock(inventory.getItem(i))); + slotPacket.setItem(ItemTranslator.translateToBedrock(session, inventory.getItem(i))); session.sendUpstreamPacket(slotPacket); } } @@ -57,7 +57,7 @@ public class CursorInventoryUpdater extends InventoryUpdater { InventorySlotPacket slotPacket = new InventorySlotPacket(); slotPacket.setContainerId(ContainerId.CURSOR); slotPacket.setSlot(translator.javaSlotToBedrock(javaSlot)); - slotPacket.setItem(ItemTranslator.translateToBedrock(inventory.getItem(javaSlot))); + slotPacket.setItem(ItemTranslator.translateToBedrock(session, inventory.getItem(javaSlot))); session.sendUpstreamPacket(slotPacket); return true; } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/InventoryUpdater.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/InventoryUpdater.java index 9710d8057..88157df09 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/InventoryUpdater.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/InventoryUpdater.java @@ -39,7 +39,7 @@ public abstract class InventoryUpdater { ItemData[] bedrockItems = new ItemData[36]; for (int i = 0; i < 36; i++) { final int offset = i < 9 ? 27 : -9; - bedrockItems[i] = ItemTranslator.translateToBedrock(inventory.getItem(translator.size + i + offset)); + bedrockItems[i] = ItemTranslator.translateToBedrock(session, inventory.getItem(translator.size + i + offset)); } InventoryContentPacket contentPacket = new InventoryContentPacket(); contentPacket.setContainerId(ContainerId.INVENTORY); @@ -52,7 +52,7 @@ public abstract class InventoryUpdater { InventorySlotPacket slotPacket = new InventorySlotPacket(); slotPacket.setContainerId(ContainerId.INVENTORY); slotPacket.setSlot(translator.javaSlotToBedrock(javaSlot)); - slotPacket.setItem(ItemTranslator.translateToBedrock(inventory.getItem(javaSlot))); + slotPacket.setItem(ItemTranslator.translateToBedrock(session, inventory.getItem(javaSlot))); session.sendUpstreamPacket(slotPacket); return true; } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemTranslator.java index 490681d8e..273226fe6 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemTranslator.java @@ -27,6 +27,8 @@ package org.geysermc.connector.network.translators.item; import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; +import com.github.steveice10.mc.protocol.data.message.Message; +import com.nukkitx.nbt.CompoundTagBuilder; import com.github.steveice10.opennbt.tag.builtin.*; import com.nukkitx.nbt.tag.CompoundTag; import com.nukkitx.nbt.tag.Tag; @@ -34,7 +36,9 @@ import com.nukkitx.protocol.bedrock.data.ItemData; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import org.geysermc.connector.GeyserConnector; +import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.ItemRemapper; +import org.geysermc.connector.utils.MessageUtils; import org.reflections.Reflections; import java.util.ArrayList; @@ -115,7 +119,7 @@ public abstract class ItemTranslator { return itemStack; } - public static ItemData translateToBedrock(ItemStack stack) { + public static ItemData translateToBedrock(GeyserSession session, ItemStack stack) { if (stack == null) { return ItemData.AIR; } @@ -132,12 +136,42 @@ public abstract class ItemTranslator { } } + ItemData itemData; ItemTranslator itemStackTranslator = ITEM_STACK_TRANSLATORS.get(bedrockItem.getJavaId()); if (itemStackTranslator != null) { - return itemStackTranslator.translateToBedrock(itemStack, bedrockItem); + itemData = itemStackTranslator.translateToBedrock(itemStack, bedrockItem); } else { - return DEFAULT_TRANSLATOR.translateToBedrock(itemStack, bedrockItem); + itemData = DEFAULT_TRANSLATOR.translateToBedrock(itemStack, bedrockItem); } + + + // Get the display name of the item + CompoundTag tag = itemData.getTag(); + if (tag != null) { + CompoundTag display = tag.getCompound("display"); + if (display != null) { + String name = display.getString("Name"); + + // Check if its a message to translate + if (MessageUtils.isMessage(name)) { + // Get the translated name + name = MessageUtils.getTranslatedBedrockMessage(Message.fromString(name), session.getClientData().getLanguageCode()); + + // Build the new display tag + CompoundTagBuilder displayBuilder = display.toBuilder(); + displayBuilder.stringTag("Name", name); + + // Build the new root tag + CompoundTagBuilder builder = tag.toBuilder(); + builder.tag(displayBuilder.build("display")); + + // Create a new item with the original data + updated name + itemData = ItemData.of(itemData.getId(), itemData.getDamage(), itemData.getCount(), builder.buildRootTag()); + } + } + } + + return itemData; } private static final ItemTranslator DEFAULT_TRANSLATOR = new ItemTranslator() { diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaDeclareRecipesTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaDeclareRecipesTranslator.java index 7763a2c1d..b0637722b 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaDeclareRecipesTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaDeclareRecipesTranslator.java @@ -64,7 +64,7 @@ public class JavaDeclareRecipesTranslator extends PacketTranslator> groupedByIds = Arrays.stream(ingredient.getOptions()) - .map(ItemTranslator::translateToBedrock) + .map(item -> ItemTranslator.translateToBedrock(session, item)) .collect(Collectors.groupingBy(item -> new GroupedItem(item.getId(), item.getCount(), item.getTag()))); Set optionSet = new HashSet<>(groupedByIds.size()); for (Map.Entry> entry : groupedByIds.entrySet()) { @@ -136,7 +136,7 @@ public class JavaDeclareRecipesTranslator extends PacketTranslator 0) { - translatedItems[i] = ItemTranslator.translateToBedrock(ingredients[i].getOptions()[0]); + translatedItems[i] = ItemTranslator.translateToBedrock(session, ingredients[i].getOptions()[0]); } else { translatedItems[i] = ItemData.AIR; } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/JavaEntityEquipmentTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/JavaEntityEquipmentTranslator.java index e977e9b0c..8918217a1 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/JavaEntityEquipmentTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/JavaEntityEquipmentTranslator.java @@ -55,7 +55,7 @@ public class JavaEntityEquipmentTranslator extends PacketTranslator