From dbf366b138c581c4bbb139b3bdb353274fbfa62d Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Mon, 10 May 2021 21:14:30 -0400 Subject: [PATCH 1/6] ACTUALLY fix swapping armor in hotbar when armor is already present (#2206) Tested with iOS, desktop and console --- .../bedrock/BedrockInventoryTransactionTranslator.java | 10 ++++------ 1 file changed, 4 insertions(+), 6 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 2358fa278..6378c0ba9 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 @@ -39,10 +39,7 @@ 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.entity.EntityFlags; -import com.nukkitx.protocol.bedrock.data.inventory.ContainerId; -import com.nukkitx.protocol.bedrock.data.inventory.ContainerType; -import com.nukkitx.protocol.bedrock.data.inventory.InventoryActionData; -import com.nukkitx.protocol.bedrock.data.inventory.InventorySource; +import com.nukkitx.protocol.bedrock.data.inventory.*; import com.nukkitx.protocol.bedrock.packet.*; import org.geysermc.connector.entity.CommandBlockMinecartEntity; import org.geysermc.connector.entity.Entity; @@ -241,9 +238,10 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator 0) { InventoryActionData actionData = packet.getActions().get(0); - if (actionData.getSlot() == 6 && actionData.getToItem().getId() != 0) { + LegacySetItemSlotData slotData = packet.getLegacySlots().get(0); + if (slotData.getContainerId() == 6 && actionData.getToItem().getId() != 0) { // The player is trying to swap out an armor piece that already has an item in it // Java Edition does not allow this; let's revert it session.getInventoryTranslator().updateInventory(session, session.getPlayerInventory()); From 3e3b8faf16ad09fa8aeb436cf1de53b1c90f82cd Mon Sep 17 00:00:00 2001 From: Konicai <71294714+Konicai@users.noreply.github.com> Date: Fri, 14 May 2021 22:48:34 -0400 Subject: [PATCH 2/6] Add client setting for cooldown type, refactor show-coordinates (#2193) --- .../geysermc/connector/GeyserConnector.java | 2 +- .../network/session/GeyserSession.java | 4 +- .../session/cache/PreferencesCache.java | 71 +++++++++++++++++++ .../network/session/cache/WorldCache.java | 21 ------ .../connector/utils/CooldownUtils.java | 31 +++++--- .../connector/utils/SettingsUtils.java | 37 +++++++--- connector/src/main/resources/languages | 2 +- 7 files changed, 125 insertions(+), 43 deletions(-) create mode 100644 connector/src/main/java/org/geysermc/connector/network/session/cache/PreferencesCache.java diff --git a/connector/src/main/java/org/geysermc/connector/GeyserConnector.java b/connector/src/main/java/org/geysermc/connector/GeyserConnector.java index 03bf7538c..d2caac216 100644 --- a/connector/src/main/java/org/geysermc/connector/GeyserConnector.java +++ b/connector/src/main/java/org/geysermc/connector/GeyserConnector.java @@ -188,7 +188,7 @@ public class GeyserConnector { defaultAuthType = AuthType.getByName(config.getRemote().getAuthType()); - CooldownUtils.setShowCooldown(config.getShowCooldown()); + CooldownUtils.setDefaultShowCooldown(config.getShowCooldown()); DimensionUtils.changeBedrockNetherId(config.isAboveBedrockNetherBuilding()); // Apply End dimension ID workaround to Nether SkullBlockEntityTranslator.ALLOW_CUSTOM_SKULLS = config.isAllowCustomSkulls(); 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 28aff40b9..3748a3ba2 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 @@ -144,6 +144,7 @@ public class GeyserSession implements CommandSender { private ChunkCache chunkCache; private EntityCache entityCache; private EntityEffectCache effectCache; + private final PreferencesCache preferencesCache; private final TagCache tagCache; private WorldCache worldCache; private WindowCache windowCache; @@ -451,6 +452,7 @@ public class GeyserSession implements CommandSender { this.chunkCache = new ChunkCache(this); this.entityCache = new EntityCache(this); this.effectCache = new EntityEffectCache(); + this.preferencesCache = new PreferencesCache(this); this.tagCache = new TagCache(); this.worldCache = new WorldCache(this); this.windowCache = new WindowCache(this); @@ -1224,7 +1226,7 @@ public class GeyserSession implements CommandSender { public void setReducedDebugInfo(boolean value) { reducedDebugInfo = value; // Set the showCoordinates data. This is done because updateShowCoordinates() uses this gamerule as a variable. - getWorldCache().updateShowCoordinates(); + preferencesCache.updateShowCoordinates(); } /** diff --git a/connector/src/main/java/org/geysermc/connector/network/session/cache/PreferencesCache.java b/connector/src/main/java/org/geysermc/connector/network/session/cache/PreferencesCache.java new file mode 100644 index 000000000..d477066c2 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/session/cache/PreferencesCache.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2019-2021 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 lombok.Getter; +import lombok.Setter; +import org.geysermc.connector.configuration.GeyserConfiguration; +import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.utils.CooldownUtils; + +@Getter +public class PreferencesCache { + private final GeyserSession session; + + /** + * True if the client prefers being shown their coordinates, regardless if they're being shown or not. + * This will be true everytime the client joins the server because neither the client nor server store the preference permanently. + */ + @Setter + private boolean prefersShowCoordinates = true; + /** + * If the client's preference will be ignored, this will return false. + */ + private boolean allowShowCoordinates; + + /** + * Which CooldownType the client prefers. Initially set to {@link CooldownUtils#getDefaultShowCooldown()}. + */ + @Setter + private CooldownUtils.CooldownType cooldownPreference = CooldownUtils.getDefaultShowCooldown(); + + public PreferencesCache(GeyserSession session) { + this.session = session; + } + + /** + * Tell the client to hide or show the coordinates. + * + * If {@link #prefersShowCoordinates} is true, coordinates will be shown, unless either of the following conditions apply:
+ *
+ * {@link GeyserSession#reducedDebugInfo} is enabled + * {@link GeyserConfiguration#isShowCoordinates()} is disabled + */ + public void updateShowCoordinates() { + allowShowCoordinates = !session.isReducedDebugInfo() && session.getConnector().getConfig().isShowCoordinates(); + session.sendGameRule("showcoordinates", allowShowCoordinates && prefersShowCoordinates); + } +} diff --git a/connector/src/main/java/org/geysermc/connector/network/session/cache/WorldCache.java b/connector/src/main/java/org/geysermc/connector/network/session/cache/WorldCache.java index 84678c211..4a2939621 100644 --- a/connector/src/main/java/org/geysermc/connector/network/session/cache/WorldCache.java +++ b/connector/src/main/java/org/geysermc/connector/network/session/cache/WorldCache.java @@ -28,7 +28,6 @@ package org.geysermc.connector.network.session.cache; import com.github.steveice10.mc.protocol.data.game.setting.Difficulty; import lombok.Getter; import lombok.Setter; -import org.geysermc.connector.configuration.GeyserConfiguration; import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.scoreboard.Objective; import org.geysermc.connector.scoreboard.Scoreboard; @@ -40,13 +39,6 @@ public class WorldCache { @Setter private Difficulty difficulty = Difficulty.EASY; - /** - * True if the client prefers being shown their coordinates, regardless if they're being shown or not. - * This will be true everytime the client joins the server because neither the client nor server store the preference permanently. - */ - @Setter - private boolean prefersShowCoordinates = true; - private Scoreboard scoreboard; private final ScoreboardUpdater scoreboardUpdater; @@ -71,17 +63,4 @@ public class WorldCache { int pps = scoreboardUpdater.getPacketsPerSecond(); return Math.max(pps, pendingPps); } - - /** - * Tell the client to hide or show the coordinates. - * - * If {@link #prefersShowCoordinates} is true, coordinates will be shown, unless either of the following conditions apply:
- *
- * {@link GeyserSession#reducedDebugInfo} is enabled - * {@link GeyserConfiguration#isShowCoordinates()} is disabled - */ - public void updateShowCoordinates() { - boolean allowShowCoordinates = !session.isReducedDebugInfo() && session.getConnector().getConfig().isShowCoordinates(); - session.sendGameRule("showcoordinates", allowShowCoordinates && prefersShowCoordinates); - } } \ No newline at end of file diff --git a/connector/src/main/java/org/geysermc/connector/utils/CooldownUtils.java b/connector/src/main/java/org/geysermc/connector/utils/CooldownUtils.java index 0b5c2bdd3..615143589 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/CooldownUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/CooldownUtils.java @@ -28,6 +28,7 @@ package org.geysermc.connector.utils; import com.nukkitx.protocol.bedrock.packet.SetTitlePacket; import lombok.Getter; import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.session.cache.PreferencesCache; import java.util.concurrent.TimeUnit; @@ -36,18 +37,25 @@ import java.util.concurrent.TimeUnit; * Much of the work here is from the wonderful folks from ViaRewind: https://github.com/ViaVersion/ViaRewind */ public class CooldownUtils { - private static CooldownType SHOW_COOLDOWN; + private static CooldownType DEFAULT_SHOW_COOLDOWN; - public static void setShowCooldown(String showCooldown) { - SHOW_COOLDOWN = CooldownType.getByName(showCooldown); + public static void setDefaultShowCooldown(String showCooldown) { + DEFAULT_SHOW_COOLDOWN = CooldownType.getByName(showCooldown); + } + + public static CooldownType getDefaultShowCooldown() { + return DEFAULT_SHOW_COOLDOWN; } /** - * Starts sending the fake cooldown to the Bedrock client. + * Starts sending the fake cooldown to the Bedrock client. If the cooldown is not disabled, the sent type is {@link PreferencesCache#getCooldownPreference()} * @param session GeyserSession */ public static void sendCooldown(GeyserSession session) { - if (SHOW_COOLDOWN == CooldownType.DISABLED) return; + if (DEFAULT_SHOW_COOLDOWN == CooldownType.DISABLED) return; + CooldownType sessionPreference = session.getPreferencesCache().getCooldownPreference(); + if (sessionPreference == CooldownType.DISABLED) return; + if (session.getAttackSpeed() == 0.0 || session.getAttackSpeed() > 20) return; // 0.0 usually happens on login and causes issues with visuals; anything above 20 means a plugin like OldCombatMechanics is being used // Needs to be sent or no subtitle packet is recognized by the client SetTitlePacket titlePacket = new SetTitlePacket(); @@ -56,19 +64,20 @@ public class CooldownUtils { session.sendUpstreamPacket(titlePacket); session.setLastHitTime(System.currentTimeMillis()); long lastHitTime = session.getLastHitTime(); // Used later to prevent multiple scheduled cooldown threads - computeCooldown(session, lastHitTime); + computeCooldown(session, sessionPreference, lastHitTime); } /** * Keeps updating the cooldown until the bar is complete. * @param session GeyserSession + * @param sessionPreference The type of cooldown the client prefers * @param lastHitTime The time of the last hit. Used to gauge how long the cooldown is taking. */ - private static void computeCooldown(GeyserSession session, long lastHitTime) { + private static void computeCooldown(GeyserSession session, CooldownType sessionPreference, long lastHitTime) { if (session.isClosed()) return; // Don't run scheduled tasks if the client left if (lastHitTime != session.getLastHitTime()) return; // Means another cooldown has started so there's no need to continue this one SetTitlePacket titlePacket = new SetTitlePacket(); - if (SHOW_COOLDOWN == CooldownType.ACTIONBAR) { + if (sessionPreference == CooldownType.ACTIONBAR) { titlePacket.setType(SetTitlePacket.Type.ACTIONBAR); } else { titlePacket.setType(SetTitlePacket.Type.SUBTITLE); @@ -79,10 +88,10 @@ public class CooldownUtils { titlePacket.setStayTime(2); session.sendUpstreamPacket(titlePacket); if (hasCooldown(session)) { - session.getConnector().getGeneralThreadPool().schedule(() -> computeCooldown(session, lastHitTime), 50, TimeUnit.MILLISECONDS); // Updated per tick. 1000 divided by 20 ticks equals 50 + session.getConnector().getGeneralThreadPool().schedule(() -> computeCooldown(session, sessionPreference, lastHitTime), 50, TimeUnit.MILLISECONDS); // Updated per tick. 1000 divided by 20 ticks equals 50 } else { SetTitlePacket removeTitlePacket = new SetTitlePacket(); - if (SHOW_COOLDOWN == CooldownType.ACTIONBAR) { + if (sessionPreference == CooldownType.ACTIONBAR) { removeTitlePacket.setType(SetTitlePacket.Type.ACTIONBAR); } else { removeTitlePacket.setType(SetTitlePacket.Type.SUBTITLE); @@ -133,7 +142,7 @@ public class CooldownUtils { public static final CooldownType[] VALUES = values(); /** - * Convert the CooldownType string (from config) to the enum, TITLE on fail + * Convert the CooldownType string (from config) to the enum, DISABLED on fail * * @param name CooldownType string * diff --git a/connector/src/main/java/org/geysermc/connector/utils/SettingsUtils.java b/connector/src/main/java/org/geysermc/connector/utils/SettingsUtils.java index 1d06c8a0f..d0cfce862 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/SettingsUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/SettingsUtils.java @@ -57,11 +57,24 @@ public class SettingsUtils { CustomFormBuilder builder = new CustomFormBuilder(LanguageUtils.getPlayerLocaleString("geyser.settings.title.main", language)); builder.setIcon(new FormImage(FormImage.FormImageType.PATH, "textures/ui/settings_glyph_color_2x.png")); - // Client can only see its coordinates if reducedDebugInfo is disabled and coordinates are enabled in geyser config. - if (!session.isReducedDebugInfo() && session.getConnector().getConfig().isShowCoordinates()) { + // Only show the client title if any of the client settings are available + if (session.getPreferencesCache().isAllowShowCoordinates() || CooldownUtils.getDefaultShowCooldown() != CooldownUtils.CooldownType.DISABLED) { builder.addComponent(new LabelComponent(LanguageUtils.getPlayerLocaleString("geyser.settings.title.client", language))); - builder.addComponent(new ToggleComponent(LanguageUtils.getPlayerLocaleString("geyser.settings.option.coordinates", language), session.getWorldCache().isPrefersShowCoordinates())); + // Client can only see its coordinates if reducedDebugInfo is disabled and coordinates are enabled in geyser config. + if (session.getPreferencesCache().isAllowShowCoordinates()) { + builder.addComponent(new ToggleComponent(LanguageUtils.getPlayerLocaleString("geyser.settings.option.coordinates", language), session.getPreferencesCache().isPrefersShowCoordinates())); + } + + if (CooldownUtils.getDefaultShowCooldown() != CooldownUtils.CooldownType.DISABLED) { + DropdownComponent cooldownDropdown = new DropdownComponent(); + cooldownDropdown.setText(LocaleUtils.getLocaleString("options.attackIndicator", language)); + cooldownDropdown.setOptions(new ArrayList<>()); + cooldownDropdown.addOption(LocaleUtils.getLocaleString("options.attack.crosshair", language), session.getPreferencesCache().getCooldownPreference() == CooldownUtils.CooldownType.TITLE); + cooldownDropdown.addOption(LocaleUtils.getLocaleString("options.attack.hotbar", language), session.getPreferencesCache().getCooldownPreference() == CooldownUtils.CooldownType.ACTIONBAR); + cooldownDropdown.addOption(LocaleUtils.getLocaleString("options.off", language), session.getPreferencesCache().getCooldownPreference() == CooldownUtils.CooldownType.DISABLED); + builder.addComponent(cooldownDropdown); + } } @@ -121,13 +134,21 @@ public class SettingsUtils { } int offset = 0; - // Client can only see its coordinates if reducedDebugInfo is disabled and coordinates are enabled in geyser config. - if (!session.isReducedDebugInfo() && session.getConnector().getConfig().isShowCoordinates()) { + if (session.getPreferencesCache().isAllowShowCoordinates() || CooldownUtils.getDefaultShowCooldown() != CooldownUtils.CooldownType.DISABLED) { offset++; // Client settings title - session.getWorldCache().setPrefersShowCoordinates(settingsResponse.getToggleResponses().get(offset)); - session.getWorldCache().updateShowCoordinates(); - offset++; + // Client can only see its coordinates if reducedDebugInfo is disabled and coordinates are enabled in geyser config. + if (session.getPreferencesCache().isAllowShowCoordinates()) { + session.getPreferencesCache().setPrefersShowCoordinates(settingsResponse.getToggleResponses().get(offset)); + session.getPreferencesCache().updateShowCoordinates(); + offset++; + } + + if (CooldownUtils.getDefaultShowCooldown() != CooldownUtils.CooldownType.DISABLED) { + CooldownUtils.CooldownType cooldownType = CooldownUtils.CooldownType.VALUES[settingsResponse.getDropdownResponses().get(offset).getElementID()]; + session.getPreferencesCache().setCooldownPreference(cooldownType); + offset++; + } } if (session.getOpPermissionLevel() >= 2 || session.hasPermission("geyser.settings.server")) { diff --git a/connector/src/main/resources/languages b/connector/src/main/resources/languages index 96e7ed66c..9b08df518 160000 --- a/connector/src/main/resources/languages +++ b/connector/src/main/resources/languages @@ -1 +1 @@ -Subproject commit 96e7ed66ccdafea0cc991b8004566d448e8f6e6a +Subproject commit 9b08df51898fd71ee24e7accdfbe56f164b5c539 From dfc24f1ecb1f626002b1eacc79916471b7047ada Mon Sep 17 00:00:00 2001 From: Konicai <71294714+Konicai@users.noreply.github.com> Date: Fri, 14 May 2021 23:12:37 -0400 Subject: [PATCH 3/6] Fix Javadoc in CooldownUtils (#2213) --- .../main/java/org/geysermc/connector/utils/CooldownUtils.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/connector/src/main/java/org/geysermc/connector/utils/CooldownUtils.java b/connector/src/main/java/org/geysermc/connector/utils/CooldownUtils.java index 615143589..43675ebfd 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/CooldownUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/CooldownUtils.java @@ -48,7 +48,7 @@ public class CooldownUtils { } /** - * Starts sending the fake cooldown to the Bedrock client. If the cooldown is not disabled, the sent type is {@link PreferencesCache#getCooldownPreference()} + * Starts sending the fake cooldown to the Bedrock client. If the cooldown is not disabled, the sent type is the cooldownPreference in {@link PreferencesCache} * @param session GeyserSession */ public static void sendCooldown(GeyserSession session) { From 74a688b44b189a81ccd07ffefcce9a8becd04aaf Mon Sep 17 00:00:00 2001 From: Redned Date: Fri, 21 May 2021 18:46:26 -0500 Subject: [PATCH 4/6] Replace the "What can't be fixed" list with a link to a new page on the wiki --- README.md | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/README.md b/README.md index a51c61f9f..21cdf945e 100644 --- a/README.md +++ b/README.md @@ -40,13 +40,7 @@ Take a look [here](https://github.com/GeyserMC/Geyser/wiki#Setup) for how to set - Structure block UI ## What can't be fixed -The following things cannot be fixed without changes to Bedrock. As of now, they are not fixable in Geyser. - -- Custom heads in inventories -- Clickable links in chat -- Glowing effect - -Do note that some things require the [GeyserOptionalPack](https://github.com/GeyserMC/Geyser/wiki/GeyserOptionalPack) in order to function, such as custom armor stand poses. +There are a few things Geyser is unable to support due to various differences between Minecraft Bedrock and Java. For a list of these limitations, see the [Current Limitations](https://github.com/GeyserMC/Geyser/wiki/Current-Limitations) page. ## Compiling 1. Clone the repo to your computer From f8315579191c2e4aba9e57e6c0746b44fc046164 Mon Sep 17 00:00:00 2001 From: Hellohi3654 <57390764+Hellohi3654@users.noreply.github.com> Date: Sat, 22 May 2021 23:26:47 +1000 Subject: [PATCH 5/6] Update pom.xml (#2220) --- bootstrap/bungeecord/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bootstrap/bungeecord/pom.xml b/bootstrap/bungeecord/pom.xml index a62faa33a..738c1ee1c 100644 --- a/bootstrap/bungeecord/pom.xml +++ b/bootstrap/bungeecord/pom.xml @@ -20,7 +20,7 @@ net.md-5 bungeecord-api - 1.16-R0.4-SNAPSHOT + 1.16-R0.5-SNAPSHOT provided From 4734ce20595bdc38608af54648142ed209c298ac Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+Camotoy@users.noreply.github.com> Date: Sun, 23 May 2021 15:55:01 -0400 Subject: [PATCH 6/6] Update MCProtocolLib + PacketLib (#2211) By updating these dependencies, we bring in a couple fixes that should improve network performance: Use TCP_NODELAY for the Java connection Use Epoll/KQueue if possible for the Java connection Only use one event loop for the Java connection Fix Netty dependencies so Spigot and BungeeCord can use native network types Currently, Geyser-Spigot pre-1.12 breaks with these changes. It is unlikely that this will be fixed. --- bootstrap/bungeecord/pom.xml | 15 +++++++-- bootstrap/spigot/pom.xml | 18 ++++++++--- .../platform/spigot/GeyserSpigotPlugin.java | 17 ++++++++++ bootstrap/velocity/pom.xml | 1 + connector/pom.xml | 4 +-- .../geysermc/connector/GeyserConnector.java | 15 +++++++++ .../network/session/GeyserSession.java | 31 +++++++++---------- .../network/session/cache/BookEditCache.java | 2 +- connector/src/main/resources/languages | 2 +- 9 files changed, 79 insertions(+), 26 deletions(-) diff --git a/bootstrap/bungeecord/pom.xml b/bootstrap/bungeecord/pom.xml index 738c1ee1c..9cf8b4763 100644 --- a/bootstrap/bungeecord/pom.xml +++ b/bootstrap/bungeecord/pom.xml @@ -66,8 +66,10 @@ org.geysermc.platform.bungeecord.shaded.jackson - io.netty - org.geysermc.platform.bungeecord.shaded.netty + + io.netty.channel.kqueue + org.geysermc.platform.bungeecord.shaded.io.netty.channel.kqueue org.reflections @@ -98,6 +100,15 @@ com.google.code.gson:* org.yaml:* + io.netty:netty-transport-native-epoll:* + io.netty:netty-transport-native-unix-common:* + io.netty:netty-handler:* + io.netty:netty-common:* + io.netty:netty-buffer:* + io.netty:netty-resolver:* + io.netty:netty-transport:* + io.netty:netty-codec:* + io.netty:netty-resolver-dns:* diff --git a/bootstrap/spigot/pom.xml b/bootstrap/spigot/pom.xml index 12c8292e9..3dd25312c 100644 --- a/bootstrap/spigot/pom.xml +++ b/bootstrap/spigot/pom.xml @@ -68,10 +68,6 @@ - - io.netty - org.geysermc.platform.spigot.shaded.netty - it.unimi.dsi.fastutil org.geysermc.platform.spigot.shaded.fastutil @@ -109,6 +105,20 @@ com.google.code.gson:* org.yaml:* + + + io.netty:netty-transport-native-epoll:* + io.netty:netty-transport-native-unix-common:* + io.netty:netty-transport-native-kqueue:* + io.netty:netty-handler:* + io.netty:netty-common:* + io.netty:netty-buffer:* + io.netty:netty-resolver:* + io.netty:netty-transport:* + io.netty:netty-codec:* + io.netty:netty-codec-dns:* + io.netty:netty-resolver-dns:* + io.netty:netty-resolver-dns-native-macos:* diff --git a/bootstrap/spigot/src/main/java/org/geysermc/platform/spigot/GeyserSpigotPlugin.java b/bootstrap/spigot/src/main/java/org/geysermc/platform/spigot/GeyserSpigotPlugin.java index 671ad18cf..b45cb7000 100644 --- a/bootstrap/spigot/src/main/java/org/geysermc/platform/spigot/GeyserSpigotPlugin.java +++ b/bootstrap/spigot/src/main/java/org/geysermc/platform/spigot/GeyserSpigotPlugin.java @@ -95,6 +95,23 @@ public class GeyserSpigotPlugin extends JavaPlugin implements GeyserBootstrap { ex.printStackTrace(); } + try { + // Required for the Cloudburst Network dependency to initialize. + Class.forName("io.netty.channel.kqueue.KQueue"); + } catch (ClassNotFoundException e) { + // While we could support these older versions, the downside is not having KQueue working at all + // And since there are alternative ways to get Geyser working for these aging platforms, it's not worth it. + getLogger().severe("*********************************************"); + getLogger().severe(""); + getLogger().severe(LanguageUtils.getLocaleStringLog("geyser.bootstrap.unsupported_server.header")); + getLogger().severe(LanguageUtils.getLocaleStringLog("geyser.bootstrap.unsupported_server.message", "1.12.2")); + getLogger().severe(""); + getLogger().severe("*********************************************"); + + Bukkit.getPluginManager().disablePlugin(this); + return; + } + // By default this should be localhost but may need to be changed in some circumstances if (this.geyserConfig.getRemote().getAddress().equalsIgnoreCase("auto")) { geyserConfig.setAutoconfiguredRemote(true); diff --git a/bootstrap/velocity/pom.xml b/bootstrap/velocity/pom.xml index bcc62ed4c..b9f2e64f2 100644 --- a/bootstrap/velocity/pom.xml +++ b/bootstrap/velocity/pom.xml @@ -103,6 +103,7 @@ io.netty:netty-resolver:* io.netty:netty-transport:* io.netty:netty-codec:* + io.netty:netty-codec-haproxy:* org.slf4j:* org.ow2.asm:* diff --git a/connector/pom.xml b/connector/pom.xml index 7d4bae7a0..9feb717b9 100644 --- a/connector/pom.xml +++ b/connector/pom.xml @@ -122,7 +122,7 @@ com.github.steveice10 mcprotocollib - 26201a4 + 8c204eb compile @@ -142,7 +142,7 @@ com.github.GeyserMC PacketLib - b77a427 + 6e5dea9 compile diff --git a/connector/src/main/java/org/geysermc/connector/GeyserConnector.java b/connector/src/main/java/org/geysermc/connector/GeyserConnector.java index d2caac216..3f82889f5 100644 --- a/connector/src/main/java/org/geysermc/connector/GeyserConnector.java +++ b/connector/src/main/java/org/geysermc/connector/GeyserConnector.java @@ -31,6 +31,8 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.nukkitx.network.raknet.RakNetConstants; import com.nukkitx.network.util.EventLoops; import com.nukkitx.protocol.bedrock.BedrockServer; +import io.netty.channel.epoll.Epoll; +import io.netty.channel.kqueue.KQueue; import lombok.Getter; import lombok.Setter; import org.geysermc.common.PlatformType; @@ -203,6 +205,19 @@ public class GeyserConnector { EventLoops.commonGroup(), enableProxyProtocol ); + + if (config.isDebugMode()) { + logger.debug("EventLoop type: " + EventLoops.getChannelType()); + if (EventLoops.getChannelType() == EventLoops.ChannelType.NIO) { + if (System.getProperties().contains("disableNativeEventLoop")) { + logger.debug("EventLoop type is NIO because native event loops are disabled."); + } else { + logger.debug("Reason for no Epoll: " + Epoll.unavailabilityCause().toString()); + logger.debug("Reason for no KQueue: " + KQueue.unavailabilityCause().toString()); + } + } + } + bedrockServer.setHandler(new ConnectorServerEventHandler(this)); bedrockServer.bind().whenComplete((avoid, throwable) -> { if (throwable == null) { 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 3748a3ba2..1130356c1 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 @@ -46,10 +46,9 @@ import com.github.steveice10.mc.protocol.packet.ingame.client.world.ClientTelepo import com.github.steveice10.mc.protocol.packet.login.client.LoginPluginResponsePacket; import com.github.steveice10.mc.protocol.packet.login.server.LoginSuccessPacket; import com.github.steveice10.packetlib.BuiltinFlags; -import com.github.steveice10.packetlib.Client; import com.github.steveice10.packetlib.event.session.*; import com.github.steveice10.packetlib.packet.Packet; -import com.github.steveice10.packetlib.tcp.TcpSessionFactory; +import com.github.steveice10.packetlib.tcp.TcpClientSession; import com.nukkitx.math.GenericMath; import com.nukkitx.math.vector.*; import com.nukkitx.protocol.bedrock.BedrockPacket; @@ -118,7 +117,7 @@ public class GeyserSession implements CommandSender { private final GeyserConnector connector; private final UpstreamSession upstream; - private Client downstream; + private TcpClientSession downstream; @Setter private AuthData authData; @Setter @@ -587,7 +586,7 @@ public class GeyserSession implements CommandSender { authenticationService.setPassword(password); authenticationService.login(); - protocol = new MinecraftProtocol(authenticationService); + protocol = new MinecraftProtocol(authenticationService.getSelectedProfile(), authenticationService.getAccessToken()); } else { protocol = new MinecraftProtocol(username); } @@ -645,7 +644,7 @@ public class GeyserSession implements CommandSender { } try { msaAuthenticationService.login(); - protocol = new MinecraftProtocol(msaAuthenticationService); + protocol = new MinecraftProtocol(msaAuthenticationService.getSelectedProfile(), msaAuthenticationService.getAccessToken()); connectDownstream(); } catch (RequestException e) { @@ -685,17 +684,17 @@ public class GeyserSession implements CommandSender { // Start ticking tickThread = connector.getGeneralThreadPool().scheduleAtFixedRate(this::tick, 50, 50, TimeUnit.MILLISECONDS); - downstream = new Client(this.remoteAddress, this.remotePort, protocol, new TcpSessionFactory()); + downstream = new TcpClientSession(this.remoteAddress, this.remotePort, protocol); disableSrvResolving(); if (connector.getConfig().getRemote().isUseProxyProtocol()) { - downstream.getSession().setFlag(BuiltinFlags.ENABLE_CLIENT_PROXY_PROTOCOL, true); - downstream.getSession().setFlag(BuiltinFlags.CLIENT_PROXIED_ADDRESS, upstream.getAddress()); + downstream.setFlag(BuiltinFlags.ENABLE_CLIENT_PROXY_PROTOCOL, true); + downstream.setFlag(BuiltinFlags.CLIENT_PROXIED_ADDRESS, upstream.getAddress()); } if (connector.getConfig().isForwardPlayerPing()) { // Let Geyser handle sending the keep alive - downstream.getSession().setFlag(MinecraftConstants.AUTOMATIC_KEEP_ALIVE_MANAGEMENT, false); + downstream.setFlag(MinecraftConstants.AUTOMATIC_KEEP_ALIVE_MANAGEMENT, false); } - downstream.getSession().addListener(new SessionAdapter() { + downstream.addListener(new SessionAdapter() { @Override public void packetSending(PacketSendingEvent event) { //todo move this somewhere else @@ -818,15 +817,15 @@ public class GeyserSession implements CommandSender { if (!daylightCycle) { setDaylightCycle(true); } - downstream.getSession().connect(); + downstream.connect(); connector.addPlayer(this); } public void disconnect(String reason) { if (!closed) { loggedIn = false; - if (downstream != null && downstream.getSession() != null) { - downstream.getSession().disconnect(reason); + if (downstream != null) { + downstream.disconnect(reason); } if (upstream != null && !upstream.isClosed()) { connector.getPlayers().remove(this); @@ -954,7 +953,7 @@ public class GeyserSession implements CommandSender { * Will be overwritten for GeyserConnect. */ protected void disableSrvResolving() { - this.downstream.getSession().setFlag(BuiltinFlags.ATTEMPT_SRV_RESOLVE, false); + this.downstream.setFlag(BuiltinFlags.ATTEMPT_SRV_RESOLVE, false); } @Override @@ -1210,8 +1209,8 @@ public class GeyserSession implements CommandSender { * @param packet the java edition packet from MCProtocolLib */ public void sendDownstreamPacket(Packet packet) { - if (downstream != null && downstream.getSession() != null && (protocol.getSubProtocol().equals(SubProtocol.GAME) || packet.getClass() == LoginPluginResponsePacket.class)) { - downstream.getSession().send(packet); + if (downstream != null && (protocol.getSubProtocol().equals(SubProtocol.GAME) || packet.getClass() == LoginPluginResponsePacket.class)) { + downstream.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/BookEditCache.java b/connector/src/main/java/org/geysermc/connector/network/session/cache/BookEditCache.java index c82645dbf..cb3737895 100644 --- a/connector/src/main/java/org/geysermc/connector/network/session/cache/BookEditCache.java +++ b/connector/src/main/java/org/geysermc/connector/network/session/cache/BookEditCache.java @@ -68,7 +68,7 @@ public class BookEditCache { packet = null; return; } - session.getDownstream().getSession().send(packet); + session.sendDownstreamPacket(packet); packet = null; lastBookUpdate = System.currentTimeMillis(); } diff --git a/connector/src/main/resources/languages b/connector/src/main/resources/languages index 9b08df518..e1e8fd6c2 160000 --- a/connector/src/main/resources/languages +++ b/connector/src/main/resources/languages @@ -1 +1 @@ -Subproject commit 9b08df51898fd71ee24e7accdfbe56f164b5c539 +Subproject commit e1e8fd6c2b8abf366e60085c23a55a2c943806ae