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
This commit is contained in:
Camotoy 2020-05-09 22:37:18 -04:00 committed by GitHub
parent 7b3893ff78
commit d4291888b3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 89 additions and 1 deletions

View file

@ -23,6 +23,12 @@
<version>1.14-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>us.myles</groupId>
<artifactId>viaversion</artifactId>
<version>3.0.0-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<finalName>${outputName}-Bukkit</finalName>

View file

@ -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;
}
}

View file

@ -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());
}
}

View file

@ -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.

View file

@ -67,6 +67,10 @@
<enabled>true</enabled>
</snapshots>
</repository>
<repository>
<id>viaversion-repo</id>
<url>https://repo.viaversion.com</url>
</repository>
</repositories>
<distributionManagement>