diff --git a/bootstrap/bukkit/pom.xml b/bootstrap/bukkit/pom.xml
index 94fab83b..1f831d67 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 579e8b16..3f2b9cad 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 07fc3136..44a520e8 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 8e002eb2..7e32f0e1 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 fc1ead33..a82d6217 100644
--- a/pom.xml
+++ b/pom.xml
@@ -67,6 +67,10 @@
true
+
+ viaversion-repo
+ https://repo.viaversion.com
+