forked from GeyserMC/Geyser
Tweaks to support Android (#1206)
* Downgrade reflections to 0.9.11 * Add comment explaining downgrade * Move to pre-build reflections * Update skins to use https and relative cache dir * Move to https OptiFine cape url * Add javadoc to isProduction * Add ANDROID as a platform type * Re-ordered PlatformType * Change stop command to call onDisable
This commit is contained in:
parent
1c84993853
commit
79bf56a75c
13 changed files with 104 additions and 18 deletions
|
@ -129,7 +129,12 @@
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.reflections</groupId>
|
<groupId>org.reflections</groupId>
|
||||||
<artifactId>reflections</artifactId>
|
<artifactId>reflections</artifactId>
|
||||||
<version>0.9.12</version>
|
<version>0.9.11</version> <!-- This isn't the latest version to get round https://github.com/ronmamo/reflections/issues/273 -->
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.dom4j</groupId>
|
||||||
|
<artifactId>dom4j</artifactId>
|
||||||
|
<version>2.1.3</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>net.kyori</groupId>
|
<groupId>net.kyori</groupId>
|
||||||
|
@ -232,6 +237,52 @@
|
||||||
</execution>
|
</execution>
|
||||||
</executions>
|
</executions>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.codehaus.gmavenplus</groupId>
|
||||||
|
<artifactId>gmavenplus-plugin</artifactId>
|
||||||
|
<version>1.9.1</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<phase>process-classes</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>execute</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<scripts>
|
||||||
|
<script><![CDATA[
|
||||||
|
new org.reflections.Reflections("org.geysermc.connector.network.translators")
|
||||||
|
.save("${project.artifactId}/target/classes/META-INF/reflections/org.geysermc.connector.network.translators-reflections.xml")
|
||||||
|
new org.reflections.Reflections("org.geysermc.connector.network.translators.item")
|
||||||
|
.save("${project.artifactId}/target/classes/META-INF/reflections/org.geysermc.connector.network.translators.item-reflections.xml")
|
||||||
|
new org.reflections.Reflections("org.geysermc.connector.network.translators.sound")
|
||||||
|
.save("${project.artifactId}/target/classes/META-INF/reflections/org.geysermc.connector.network.translators.sound-reflections.xml")
|
||||||
|
new org.reflections.Reflections("org.geysermc.connector.network.translators.world.block.entity")
|
||||||
|
.save("${project.artifactId}/target/classes/META-INF/reflections/org.geysermc.connector.network.translators.world.block.entity-reflections.xml")
|
||||||
|
]]></script>
|
||||||
|
</scripts>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.reflections</groupId>
|
||||||
|
<artifactId>reflections</artifactId>
|
||||||
|
<version>0.9.11</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.dom4j</groupId>
|
||||||
|
<artifactId>dom4j</artifactId>
|
||||||
|
<version>2.1.3</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.codehaus.groovy</groupId>
|
||||||
|
<artifactId>groovy-all</artifactId>
|
||||||
|
<version>3.0.5</version>
|
||||||
|
<scope>runtime</scope>
|
||||||
|
<type>pom</type>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
</project>
|
</project>
|
||||||
|
|
|
@ -163,7 +163,7 @@ public class GeyserConnector {
|
||||||
config.getRemote().setPort(remotePort = Integer.parseInt(record[2]));
|
config.getRemote().setPort(remotePort = Integer.parseInt(record[2]));
|
||||||
logger.debug("Found SRV record \"" + remoteAddress + ":" + remotePort + "\"");
|
logger.debug("Found SRV record \"" + remoteAddress + ":" + remotePort + "\"");
|
||||||
}
|
}
|
||||||
} catch (Exception ex) {
|
} catch (Exception | NoClassDefFoundError ex) { // Check for a NoClassDefFoundError to prevent Android crashes
|
||||||
logger.debug("Exception while trying to find an SRV record for the remote host.");
|
logger.debug("Exception while trying to find an SRV record for the remote host.");
|
||||||
if (config.isDebugMode())
|
if (config.isDebugMode())
|
||||||
ex.printStackTrace(); // Otherwise we can get a stack trace for any domain that doesn't have an SRV record
|
ex.printStackTrace(); // Otherwise we can get a stack trace for any domain that doesn't have an SRV record
|
||||||
|
@ -307,6 +307,18 @@ public class GeyserConnector {
|
||||||
return bootstrap.getWorldManager();
|
return bootstrap.getWorldManager();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the production status of the current runtime.
|
||||||
|
* Will return true if the version number is not 'DEV'.
|
||||||
|
* Should only happen in compiled jars.
|
||||||
|
*
|
||||||
|
* @return If we are in a production build/environment
|
||||||
|
*/
|
||||||
|
public boolean isProduction() {
|
||||||
|
//noinspection ConstantConditions
|
||||||
|
return !"DEV".equals(GeyserConnector.VERSION);
|
||||||
|
}
|
||||||
|
|
||||||
public static GeyserConnector getInstance() {
|
public static GeyserConnector getInstance() {
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,10 +49,6 @@ public class StopCommand extends GeyserCommand {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
connector.shutdown();
|
connector.getBootstrap().onDisable();
|
||||||
|
|
||||||
if (connector.getPlatformType() == PlatformType.STANDALONE) {
|
|
||||||
System.exit(0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,6 +32,7 @@ import lombok.Getter;
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
public enum PlatformType {
|
public enum PlatformType {
|
||||||
|
|
||||||
|
ANDROID("Android"),
|
||||||
BUNGEECORD("BungeeCord"),
|
BUNGEECORD("BungeeCord"),
|
||||||
SPIGOT("Spigot"),
|
SPIGOT("Spigot"),
|
||||||
SPONGE("Sponge"),
|
SPONGE("Sponge"),
|
||||||
|
|
|
@ -33,6 +33,7 @@ import com.nukkitx.protocol.bedrock.BedrockPacket;
|
||||||
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
|
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
|
||||||
import org.geysermc.connector.GeyserConnector;
|
import org.geysermc.connector.GeyserConnector;
|
||||||
import org.geysermc.connector.network.session.GeyserSession;
|
import org.geysermc.connector.network.session.GeyserSession;
|
||||||
|
import org.geysermc.connector.utils.FileUtils;
|
||||||
import org.geysermc.connector.utils.LanguageUtils;
|
import org.geysermc.connector.utils.LanguageUtils;
|
||||||
import org.reflections.Reflections;
|
import org.reflections.Reflections;
|
||||||
|
|
||||||
|
@ -48,7 +49,7 @@ public class PacketTranslatorRegistry<T> {
|
||||||
private static final ObjectArrayList<Class<?>> IGNORED_PACKETS = new ObjectArrayList<>();
|
private static final ObjectArrayList<Class<?>> IGNORED_PACKETS = new ObjectArrayList<>();
|
||||||
|
|
||||||
static {
|
static {
|
||||||
Reflections ref = new Reflections("org.geysermc.connector.network.translators");
|
Reflections ref = GeyserConnector.getInstance().isProduction() ? FileUtils.getReflections("org.geysermc.connector.network.translators") : new Reflections("org.geysermc.connector.network.translators");
|
||||||
|
|
||||||
for (Class<?> clazz : ref.getTypesAnnotatedWith(Translator.class)) {
|
for (Class<?> clazz : ref.getTypesAnnotatedWith(Translator.class)) {
|
||||||
Class<?> packet = clazz.getAnnotation(Translator.class).packet();
|
Class<?> packet = clazz.getAnnotation(Translator.class).packet();
|
||||||
|
|
|
@ -41,6 +41,7 @@ import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
|
||||||
import org.geysermc.connector.GeyserConnector;
|
import org.geysermc.connector.GeyserConnector;
|
||||||
import org.geysermc.connector.network.session.GeyserSession;
|
import org.geysermc.connector.network.session.GeyserSession;
|
||||||
import org.geysermc.connector.network.translators.ItemRemapper;
|
import org.geysermc.connector.network.translators.ItemRemapper;
|
||||||
|
import org.geysermc.connector.utils.FileUtils;
|
||||||
import org.geysermc.connector.utils.LanguageUtils;
|
import org.geysermc.connector.utils.LanguageUtils;
|
||||||
import org.geysermc.connector.utils.MessageUtils;
|
import org.geysermc.connector.utils.MessageUtils;
|
||||||
import org.reflections.Reflections;
|
import org.reflections.Reflections;
|
||||||
|
@ -62,7 +63,7 @@ public abstract class ItemTranslator {
|
||||||
|
|
||||||
static {
|
static {
|
||||||
/* Load item translators */
|
/* Load item translators */
|
||||||
Reflections ref = new Reflections("org.geysermc.connector.network.translators.item");
|
Reflections ref = GeyserConnector.getInstance().isProduction() ? FileUtils.getReflections("org.geysermc.connector.network.translators.item") : new Reflections("org.geysermc.connector.network.translators.item");
|
||||||
|
|
||||||
Map<NbtItemStackTranslator, Integer> loadedNbtItemTranslators = new HashMap<>();
|
Map<NbtItemStackTranslator, Integer> loadedNbtItemTranslators = new HashMap<>();
|
||||||
for (Class<?> clazz : ref.getTypesAnnotatedWith(ItemRemapper.class)) {
|
for (Class<?> clazz : ref.getTypesAnnotatedWith(ItemRemapper.class)) {
|
||||||
|
|
|
@ -25,6 +25,8 @@
|
||||||
|
|
||||||
package org.geysermc.connector.network.translators.sound;
|
package org.geysermc.connector.network.translators.sound;
|
||||||
|
|
||||||
|
import org.geysermc.connector.GeyserConnector;
|
||||||
|
import org.geysermc.connector.utils.FileUtils;
|
||||||
import org.reflections.Reflections;
|
import org.reflections.Reflections;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
@ -38,7 +40,7 @@ public class SoundHandlerRegistry {
|
||||||
static final Map<SoundHandler, SoundInteractionHandler<?>> INTERACTION_HANDLERS = new HashMap<>();
|
static final Map<SoundHandler, SoundInteractionHandler<?>> INTERACTION_HANDLERS = new HashMap<>();
|
||||||
|
|
||||||
static {
|
static {
|
||||||
Reflections ref = new Reflections("org.geysermc.connector.network.translators.sound");
|
Reflections ref = GeyserConnector.getInstance().isProduction() ? FileUtils.getReflections("org.geysermc.connector.network.translators.sound") : new Reflections("org.geysermc.connector.network.translators.sound");
|
||||||
for (Class<?> clazz : ref.getTypesAnnotatedWith(SoundHandler.class)) {
|
for (Class<?> clazz : ref.getTypesAnnotatedWith(SoundHandler.class)) {
|
||||||
try {
|
try {
|
||||||
SoundInteractionHandler<?> interactionHandler = (SoundInteractionHandler<?>) clazz.newInstance();
|
SoundInteractionHandler<?> interactionHandler = (SoundInteractionHandler<?>) clazz.newInstance();
|
||||||
|
|
|
@ -106,7 +106,7 @@ public class BlockTranslator {
|
||||||
addedStatesMap.defaultReturnValue(-1);
|
addedStatesMap.defaultReturnValue(-1);
|
||||||
List<NbtMap> paletteList = new ArrayList<>();
|
List<NbtMap> paletteList = new ArrayList<>();
|
||||||
|
|
||||||
Reflections ref = new Reflections("org.geysermc.connector.network.translators.world.block.entity");
|
Reflections ref = GeyserConnector.getInstance().isProduction() ? FileUtils.getReflections("org.geysermc.connector.network.translators.world.block.entity") : new Reflections("org.geysermc.connector.network.translators.world.block.entity");
|
||||||
ref.getTypesAnnotatedWith(BlockEntity.class);
|
ref.getTypesAnnotatedWith(BlockEntity.class);
|
||||||
|
|
||||||
int waterRuntimeId = -1;
|
int waterRuntimeId = -1;
|
||||||
|
|
|
@ -34,6 +34,7 @@ import com.nukkitx.nbt.NbtMapBuilder;
|
||||||
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
|
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
|
||||||
import org.geysermc.connector.GeyserConnector;
|
import org.geysermc.connector.GeyserConnector;
|
||||||
import org.geysermc.connector.utils.BlockEntityUtils;
|
import org.geysermc.connector.utils.BlockEntityUtils;
|
||||||
|
import org.geysermc.connector.utils.FileUtils;
|
||||||
import org.geysermc.connector.utils.LanguageUtils;
|
import org.geysermc.connector.utils.LanguageUtils;
|
||||||
import org.reflections.Reflections;
|
import org.reflections.Reflections;
|
||||||
|
|
||||||
|
@ -66,7 +67,7 @@ public abstract class BlockEntityTranslator {
|
||||||
}
|
}
|
||||||
|
|
||||||
static {
|
static {
|
||||||
Reflections ref = new Reflections("org.geysermc.connector.network.translators.world.block.entity");
|
Reflections ref = GeyserConnector.getInstance().isProduction() ? FileUtils.getReflections("org.geysermc.connector.network.translators.world.block.entity") : new Reflections("org.geysermc.connector.network.translators.world.block.entity");
|
||||||
for (Class<?> clazz : ref.getTypesAnnotatedWith(BlockEntity.class)) {
|
for (Class<?> clazz : ref.getTypesAnnotatedWith(BlockEntity.class)) {
|
||||||
GeyserConnector.getInstance().getLogger().debug("Found annotated block entity: " + clazz.getCanonicalName());
|
GeyserConnector.getInstance().getLogger().debug("Found annotated block entity: " + clazz.getCanonicalName());
|
||||||
|
|
||||||
|
|
|
@ -28,11 +28,15 @@ package org.geysermc.connector.utils;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
|
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
|
||||||
import org.geysermc.connector.GeyserConnector;
|
import org.geysermc.connector.GeyserConnector;
|
||||||
|
import org.reflections.Reflections;
|
||||||
|
import org.reflections.serializers.XmlSerializer;
|
||||||
|
import org.reflections.util.ConfigurationBuilder;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.net.URL;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
public class FileUtils {
|
public class FileUtils {
|
||||||
|
@ -140,4 +144,21 @@ public class FileUtils {
|
||||||
}
|
}
|
||||||
return stream;
|
return stream;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the stored reflection data for a given path
|
||||||
|
*
|
||||||
|
* @param path The path to get the reflection data for
|
||||||
|
* @return The created Reflections object
|
||||||
|
*/
|
||||||
|
public static Reflections getReflections(String path) {
|
||||||
|
Reflections reflections = new Reflections(new ConfigurationBuilder());
|
||||||
|
XmlSerializer serializer = new XmlSerializer();
|
||||||
|
URL resource = FileUtils.class.getClassLoader().getResource("META-INF/reflections/" + path + "-reflections.xml");
|
||||||
|
try (InputStream inputStream = resource.openConnection().getInputStream()) {
|
||||||
|
reflections.merge(serializer.read(inputStream));
|
||||||
|
} catch (IOException e) { }
|
||||||
|
|
||||||
|
return reflections;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -150,7 +150,7 @@ public class LocaleUtils {
|
||||||
|
|
||||||
// Get the hash and download the locale
|
// Get the hash and download the locale
|
||||||
String hash = ASSET_MAP.get("minecraft/lang/" + locale + ".json").getHash();
|
String hash = ASSET_MAP.get("minecraft/lang/" + locale + ".json").getHash();
|
||||||
WebUtils.downloadFile("http://resources.download.minecraft.net/" + hash.substring(0, 2) + "/" + hash, localeFile.toString());
|
WebUtils.downloadFile("https://resources.download.minecraft.net/" + hash.substring(0, 2) + "/" + hash, localeFile.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -119,7 +119,7 @@ public class SkinProvider {
|
||||||
// Schedule Daily Image Expiry if we are caching them
|
// Schedule Daily Image Expiry if we are caching them
|
||||||
if (GeyserConnector.getInstance().getConfig().getCacheImages() > 0) {
|
if (GeyserConnector.getInstance().getConfig().getCacheImages() > 0) {
|
||||||
GeyserConnector.getInstance().getGeneralThreadPool().scheduleAtFixedRate(() -> {
|
GeyserConnector.getInstance().getGeneralThreadPool().scheduleAtFixedRate(() -> {
|
||||||
File cacheFolder = Paths.get("cache", "images").toFile();
|
File cacheFolder = GeyserConnector.getInstance().getBootstrap().getConfigFolder().resolve("cache").resolve("images").toFile();
|
||||||
if (!cacheFolder.exists()) {
|
if (!cacheFolder.exists()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -395,7 +395,7 @@ public class SkinProvider {
|
||||||
BufferedImage image = null;
|
BufferedImage image = null;
|
||||||
|
|
||||||
// First see if we have a cached file. We also update the modification stamp so we know when the file was last used
|
// First see if we have a cached file. We also update the modification stamp so we know when the file was last used
|
||||||
File imageFile = Paths.get("cache", "images", UUID.nameUUIDFromBytes(imageUrl.getBytes()).toString() + ".png").toFile();
|
File imageFile = GeyserConnector.getInstance().getBootstrap().getConfigFolder().resolve("cache").resolve("images").resolve(UUID.nameUUIDFromBytes(imageUrl.getBytes()).toString() + ".png").toFile();
|
||||||
if (imageFile.exists()) {
|
if (imageFile.exists()) {
|
||||||
try {
|
try {
|
||||||
GeyserConnector.getInstance().getLogger().debug("Reading cached image from file " + imageFile.getPath() + " for " + imageUrl);
|
GeyserConnector.getInstance().getLogger().debug("Reading cached image from file " + imageFile.getPath() + " for " + imageUrl);
|
||||||
|
@ -600,7 +600,7 @@ public class SkinProvider {
|
||||||
@Getter
|
@Getter
|
||||||
public enum CapeProvider {
|
public enum CapeProvider {
|
||||||
MINECRAFT,
|
MINECRAFT,
|
||||||
OPTIFINE("http://s.optifine.net/capes/%s.png", CapeUrlType.USERNAME),
|
OPTIFINE("https://optifine.net/capes/%s.png", CapeUrlType.USERNAME),
|
||||||
LABYMOD("https://www.labymod.net/page/php/getCapeTexture.php?uuid=%s", CapeUrlType.UUID_DASHED),
|
LABYMOD("https://www.labymod.net/page/php/getCapeTexture.php?uuid=%s", CapeUrlType.UUID_DASHED),
|
||||||
FIVEZIG("https://textures.5zigreborn.eu/profile/%s", CapeUrlType.UUID_DASHED),
|
FIVEZIG("https://textures.5zigreborn.eu/profile/%s", CapeUrlType.UUID_DASHED),
|
||||||
MINECRAFTCAPES("https://minecraftcapes.net/profile/%s/cape", CapeUrlType.UUID);
|
MINECRAFTCAPES("https://minecraftcapes.net/profile/%s/cape", CapeUrlType.UUID);
|
||||||
|
|
|
@ -150,14 +150,14 @@ public class SkinUtils {
|
||||||
JsonNode textures = skinObject.get("textures");
|
JsonNode textures = skinObject.get("textures");
|
||||||
|
|
||||||
JsonNode skinTexture = textures.get("SKIN");
|
JsonNode skinTexture = textures.get("SKIN");
|
||||||
String skinUrl = skinTexture.get("url").asText();
|
String skinUrl = skinTexture.get("url").asText().replace("http://", "https://");
|
||||||
|
|
||||||
isAlex = skinTexture.has("metadata");
|
isAlex = skinTexture.has("metadata");
|
||||||
|
|
||||||
String capeUrl = null;
|
String capeUrl = null;
|
||||||
if (textures.has("CAPE")) {
|
if (textures.has("CAPE")) {
|
||||||
JsonNode capeTexture = textures.get("CAPE");
|
JsonNode capeTexture = textures.get("CAPE");
|
||||||
capeUrl = capeTexture.get("url").asText();
|
capeUrl = capeTexture.get("url").asText().replace("http://", "https://");
|
||||||
}
|
}
|
||||||
|
|
||||||
return new GameProfileData(skinUrl, capeUrl, isAlex);
|
return new GameProfileData(skinUrl, capeUrl, isAlex);
|
||||||
|
|
Loading…
Reference in a new issue