Mirror von
https://github.com/GeyserMC/Geyser.git
synchronisiert 2024-10-08 10:50:11 +02:00
New config used in core
Dieser Commit ist enthalten in:
Ursprung
db9b951352
Commit
29f8e294ad
@ -108,7 +108,7 @@ public class GeyserBungeeInjector extends GeyserInjector implements Listener {
|
|||||||
listenerInfo.isPingPassthrough(),
|
listenerInfo.isPingPassthrough(),
|
||||||
listenerInfo.getQueryPort(),
|
listenerInfo.getQueryPort(),
|
||||||
listenerInfo.isQueryEnabled(),
|
listenerInfo.isQueryEnabled(),
|
||||||
bootstrap.getGeyserConfig().getRemote().isUseProxyProtocol() // If Geyser is expecting HAProxy, so should the Bungee end
|
bootstrap.config().java().useProxyProtocol() // If Geyser is expecting HAProxy, so should the Bungee end
|
||||||
);
|
);
|
||||||
|
|
||||||
// The field that stores all listeners in BungeeCord
|
// The field that stores all listeners in BungeeCord
|
||||||
@ -142,7 +142,7 @@ public class GeyserBungeeInjector extends GeyserInjector implements Listener {
|
|||||||
}
|
}
|
||||||
initChannel.invoke(channelInitializer, ch);
|
initChannel.invoke(channelInitializer, ch);
|
||||||
|
|
||||||
if (bootstrap.getGeyserConfig().isDisableCompression()) {
|
if (bootstrap.config().asPluginConfig().orElseThrow().useDirectConnection()) {
|
||||||
ch.pipeline().addAfter(PipelineUtils.PACKET_ENCODER, "geyser-compression-disabler",
|
ch.pipeline().addAfter(PipelineUtils.PACKET_ENCODER, "geyser-compression-disabler",
|
||||||
new GeyserBungeeCompressionDisabler());
|
new GeyserBungeeCompressionDisabler());
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,7 @@ public final class GeyserBungeeUpdateListener implements Listener {
|
|||||||
|
|
||||||
@EventHandler
|
@EventHandler
|
||||||
public void onPlayerJoin(final PostLoginEvent event) {
|
public void onPlayerJoin(final PostLoginEvent event) {
|
||||||
if (GeyserImpl.getInstance().getConfig().isNotifyOnNewBedrockUpdate()) {
|
if (GeyserImpl.getInstance().config().notifyOnNewBedrockUpdate()) {
|
||||||
final ProxiedPlayer player = event.getPlayer();
|
final ProxiedPlayer player = event.getPlayer();
|
||||||
if (player.hasPermission(Constants.UPDATE_PERMISSION)) {
|
if (player.hasPermission(Constants.UPDATE_PERMISSION)) {
|
||||||
VersionCheckUtils.checkForGeyserUpdate(() -> new BungeeCommandSource(player));
|
VersionCheckUtils.checkForGeyserUpdate(() -> new BungeeCommandSource(player));
|
||||||
|
@ -96,7 +96,7 @@ public class GeyserModInjector extends GeyserInjector {
|
|||||||
int index = ch.pipeline().names().indexOf("encoder");
|
int index = ch.pipeline().names().indexOf("encoder");
|
||||||
String baseName = index != -1 ? "encoder" : "outbound_config";
|
String baseName = index != -1 ? "encoder" : "outbound_config";
|
||||||
|
|
||||||
if (bootstrap.getGeyserConfig().isDisableCompression()) {
|
if (bootstrap.config().asPluginConfig().orElseThrow().disableCompression()) {
|
||||||
ch.pipeline().addAfter(baseName, "geyser-compression-disabler", new GeyserModCompressionDisabler());
|
ch.pipeline().addAfter(baseName, "geyser-compression-disabler", new GeyserModCompressionDisabler());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -125,7 +125,7 @@ public class GeyserModInjector extends GeyserInjector {
|
|||||||
childHandler = (ChannelInitializer<Channel>) childHandlerField.get(handler);
|
childHandler = (ChannelInitializer<Channel>) childHandlerField.get(handler);
|
||||||
break;
|
break;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
if (bootstrap.getGeyserConfig().isDebugMode()) {
|
if (bootstrap.config().debugMode()) {
|
||||||
bootstrap.getGeyserLogger().debug("The handler " + name + " isn't a ChannelInitializer. THIS ERROR IS SAFE TO IGNORE!");
|
bootstrap.getGeyserLogger().debug("The handler " + name + " isn't a ChannelInitializer. THIS ERROR IS SAFE TO IGNORE!");
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
@ -56,7 +56,6 @@ public class IntegratedServerMixin implements GeyserServerPortGetter {
|
|||||||
// If the LAN is opened, starts Geyser.
|
// If the LAN is opened, starts Geyser.
|
||||||
GeyserModBootstrap instance = GeyserModBootstrap.getInstance();
|
GeyserModBootstrap instance = GeyserModBootstrap.getInstance();
|
||||||
instance.setServer((MinecraftServer) (Object) this);
|
instance.setServer((MinecraftServer) (Object) this);
|
||||||
instance.getGeyserConfig().getRemote().setPort(port);
|
|
||||||
instance.onGeyserEnable();
|
instance.onGeyserEnable();
|
||||||
// Ensure player locale has been loaded, in case it's different from Java system language
|
// Ensure player locale has been loaded, in case it's different from Java system language
|
||||||
GeyserLocale.loadGeyserLocale(this.minecraft.options.languageCode);
|
GeyserLocale.loadGeyserLocale(this.minecraft.options.languageCode);
|
||||||
|
@ -122,7 +122,7 @@ public class GeyserSpigotInjector extends GeyserInjector {
|
|||||||
int index = ch.pipeline().names().indexOf("encoder");
|
int index = ch.pipeline().names().indexOf("encoder");
|
||||||
String baseName = index != -1 ? "encoder" : "outbound_config";
|
String baseName = index != -1 ? "encoder" : "outbound_config";
|
||||||
|
|
||||||
if (bootstrap.getGeyserConfig().isDisableCompression() && GeyserSpigotCompressionDisabler.ENABLED) {
|
if (bootstrap.config().asPluginConfig().orElseThrow().disableCompression() && GeyserSpigotCompressionDisabler.ENABLED) {
|
||||||
ch.pipeline().addAfter(baseName, "geyser-compression-disabler", new GeyserSpigotCompressionDisabler());
|
ch.pipeline().addAfter(baseName, "geyser-compression-disabler", new GeyserSpigotCompressionDisabler());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -157,7 +157,7 @@ public class GeyserSpigotInjector extends GeyserInjector {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
if (bootstrap.getGeyserConfig().isDebugMode()) {
|
if (bootstrap.config().debugMode()) {
|
||||||
bootstrap.getGeyserLogger().debug("The handler " + name + " isn't a ChannelInitializer. THIS ERROR IS SAFE TO IGNORE!");
|
bootstrap.getGeyserLogger().debug("The handler " + name + " isn't a ChannelInitializer. THIS ERROR IS SAFE TO IGNORE!");
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
@ -176,8 +176,8 @@ public class GeyserSpigotInjector extends GeyserInjector {
|
|||||||
*/
|
*/
|
||||||
private void workAroundWeirdBug(GeyserBootstrap bootstrap) {
|
private void workAroundWeirdBug(GeyserBootstrap bootstrap) {
|
||||||
MinecraftProtocol protocol = new MinecraftProtocol();
|
MinecraftProtocol protocol = new MinecraftProtocol();
|
||||||
LocalSession session = new LocalSession(bootstrap.getGeyserConfig().getRemote().address(),
|
LocalSession session = new LocalSession(bootstrap.config().java().address(),
|
||||||
bootstrap.getGeyserConfig().getRemote().port(), this.serverSocketAddress,
|
bootstrap.config().java().port(), this.serverSocketAddress,
|
||||||
InetAddress.getLoopbackAddress().getHostAddress(), protocol, protocol.createHelper());
|
InetAddress.getLoopbackAddress().getHostAddress(), protocol, protocol.createHelper());
|
||||||
session.connect();
|
session.connect();
|
||||||
session.disconnect("");
|
session.disconnect("");
|
||||||
|
@ -487,7 +487,7 @@ public class GeyserSpigotPlugin extends JavaPlugin implements GeyserBootstrap {
|
|||||||
File configFile = FileUtils.fileOrCopiedFromResource(new File(getDataFolder(), "config.yml"), "config.yml",
|
File configFile = FileUtils.fileOrCopiedFromResource(new File(getDataFolder(), "config.yml"), "config.yml",
|
||||||
(x) -> x.replaceAll("generateduuid", UUID.randomUUID().toString()), this);
|
(x) -> x.replaceAll("generateduuid", UUID.randomUUID().toString()), this);
|
||||||
this.geyserConfig = FileUtils.loadConfig(configFile, GeyserSpigotConfiguration.class);
|
this.geyserConfig = FileUtils.loadConfig(configFile, GeyserSpigotConfiguration.class);
|
||||||
ConfigLoaderTemp.load(GeyserPluginConfig.class);
|
ConfigLoaderTemp.load(new File(getDataFolder(), "config.yml"), GeyserPluginConfig.class);
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
geyserLogger.error(GeyserLocale.getLocaleStringLog("geyser.config.failed"), ex);
|
geyserLogger.error(GeyserLocale.getLocaleStringLog("geyser.config.failed"), ex);
|
||||||
ex.printStackTrace();
|
ex.printStackTrace();
|
||||||
|
@ -38,7 +38,7 @@ public final class GeyserSpigotUpdateListener implements Listener {
|
|||||||
|
|
||||||
@EventHandler
|
@EventHandler
|
||||||
public void onPlayerJoin(final PlayerJoinEvent event) {
|
public void onPlayerJoin(final PlayerJoinEvent event) {
|
||||||
if (GeyserImpl.getInstance().getConfig().isNotifyOnNewBedrockUpdate()) {
|
if (GeyserImpl.getInstance().config().notifyOnNewBedrockUpdate()) {
|
||||||
final Player player = event.getPlayer();
|
final Player player = event.getPlayer();
|
||||||
if (player.hasPermission(Constants.UPDATE_PERMISSION)) {
|
if (player.hasPermission(Constants.UPDATE_PERMISSION)) {
|
||||||
VersionCheckUtils.checkForGeyserUpdate(() -> new SpigotCommandSource(player));
|
VersionCheckUtils.checkForGeyserUpdate(() -> new SpigotCommandSource(player));
|
||||||
|
@ -76,7 +76,7 @@ public final class GeyserPaperCommandListener implements Listener {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GeyserImpl.getInstance().getConfig().isUseDirectConnection()) {
|
if (GeyserImpl.getInstance().config().asPluginConfig().orElseThrow().useDirectConnection()) {
|
||||||
InetSocketAddress address = player.getAddress();
|
InetSocketAddress address = player.getAddress();
|
||||||
if (address != null) {
|
if (address != null) {
|
||||||
return address.getPort() != 0;
|
return address.getPort() != 0;
|
||||||
|
@ -25,11 +25,6 @@
|
|||||||
|
|
||||||
package org.geysermc.geyser.platform.standalone;
|
package org.geysermc.geyser.platform.standalone;
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.BeanDescription;
|
|
||||||
import com.fasterxml.jackson.databind.JavaType;
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
||||||
import com.fasterxml.jackson.databind.introspect.AnnotatedField;
|
|
||||||
import com.fasterxml.jackson.databind.introspect.BeanPropertyDefinition;
|
|
||||||
import io.netty.util.ResourceLeakDetector;
|
import io.netty.util.ResourceLeakDetector;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import net.minecrell.terminalconsole.TerminalConsoleAppender;
|
import net.minecrell.terminalconsole.TerminalConsoleAppender;
|
||||||
@ -44,16 +39,17 @@ import org.geysermc.geyser.GeyserImpl;
|
|||||||
import org.geysermc.geyser.api.util.PlatformType;
|
import org.geysermc.geyser.api.util.PlatformType;
|
||||||
import org.geysermc.geyser.command.GeyserCommandManager;
|
import org.geysermc.geyser.command.GeyserCommandManager;
|
||||||
import org.geysermc.geyser.configuration.ConfigLoaderTemp;
|
import org.geysermc.geyser.configuration.ConfigLoaderTemp;
|
||||||
import org.geysermc.geyser.configuration.GeyserConfiguration;
|
import org.geysermc.geyser.configuration.GeyserConfig;
|
||||||
import org.geysermc.geyser.configuration.GeyserJacksonConfiguration;
|
|
||||||
import org.geysermc.geyser.configuration.GeyserRemoteConfig;
|
import org.geysermc.geyser.configuration.GeyserRemoteConfig;
|
||||||
import org.geysermc.geyser.dump.BootstrapDumpInfo;
|
import org.geysermc.geyser.dump.BootstrapDumpInfo;
|
||||||
import org.geysermc.geyser.ping.GeyserLegacyPingPassthrough;
|
import org.geysermc.geyser.ping.GeyserLegacyPingPassthrough;
|
||||||
import org.geysermc.geyser.ping.IGeyserPingPassthrough;
|
import org.geysermc.geyser.ping.IGeyserPingPassthrough;
|
||||||
import org.geysermc.geyser.platform.standalone.gui.GeyserStandaloneGUI;
|
import org.geysermc.geyser.platform.standalone.gui.GeyserStandaloneGUI;
|
||||||
import org.geysermc.geyser.text.GeyserLocale;
|
import org.geysermc.geyser.text.GeyserLocale;
|
||||||
import org.geysermc.geyser.util.FileUtils;
|
|
||||||
import org.geysermc.geyser.util.LoopbackUtil;
|
import org.geysermc.geyser.util.LoopbackUtil;
|
||||||
|
import org.spongepowered.configurate.CommentedConfigurationNode;
|
||||||
|
import org.spongepowered.configurate.NodePath;
|
||||||
|
import org.spongepowered.configurate.serialize.SerializationException;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -61,13 +57,13 @@ import java.lang.reflect.Method;
|
|||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
import java.text.MessageFormat;
|
import java.text.MessageFormat;
|
||||||
import java.util.*;
|
import java.util.HashMap;
|
||||||
import java.util.stream.Collectors;
|
import java.util.Map;
|
||||||
|
|
||||||
public class GeyserStandaloneBootstrap implements GeyserBootstrap {
|
public class GeyserStandaloneBootstrap implements GeyserBootstrap {
|
||||||
|
|
||||||
private GeyserCommandManager geyserCommandManager;
|
private GeyserCommandManager geyserCommandManager;
|
||||||
private GeyserStandaloneConfiguration geyserConfig;
|
private GeyserConfig geyserConfig;
|
||||||
private final GeyserStandaloneLogger geyserLogger = new GeyserStandaloneLogger();
|
private final GeyserStandaloneLogger geyserLogger = new GeyserStandaloneLogger();
|
||||||
private IGeyserPingPassthrough geyserPingPassthrough;
|
private IGeyserPingPassthrough geyserPingPassthrough;
|
||||||
private GeyserStandaloneGUI gui;
|
private GeyserStandaloneGUI gui;
|
||||||
@ -78,15 +74,15 @@ public class GeyserStandaloneBootstrap implements GeyserBootstrap {
|
|||||||
|
|
||||||
private GeyserImpl geyser;
|
private GeyserImpl geyser;
|
||||||
|
|
||||||
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
|
private static final Map<NodePath, String> argsConfigKeys = new HashMap<>();
|
||||||
|
|
||||||
private static final Map<String, String> argsConfigKeys = new HashMap<>();
|
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
if (System.getProperty("io.netty.leakDetection.level") == null) {
|
if (System.getProperty("io.netty.leakDetection.level") == null) {
|
||||||
ResourceLeakDetector.setLevel(ResourceLeakDetector.Level.DISABLED); // Can eat performance
|
ResourceLeakDetector.setLevel(ResourceLeakDetector.Level.DISABLED); // Can eat performance
|
||||||
}
|
}
|
||||||
|
|
||||||
|
System.setProperty("bstats.relocatecheck", "false");
|
||||||
|
|
||||||
GeyserStandaloneBootstrap bootstrap = new GeyserStandaloneBootstrap();
|
GeyserStandaloneBootstrap bootstrap = new GeyserStandaloneBootstrap();
|
||||||
// Set defaults
|
// Set defaults
|
||||||
boolean useGuiOpts = bootstrap.useGui;
|
boolean useGuiOpts = bootstrap.useGui;
|
||||||
@ -94,8 +90,6 @@ public class GeyserStandaloneBootstrap implements GeyserBootstrap {
|
|||||||
|
|
||||||
GeyserLocale.init(bootstrap);
|
GeyserLocale.init(bootstrap);
|
||||||
|
|
||||||
List<BeanPropertyDefinition> availableProperties = getPOJOForClass(GeyserJacksonConfiguration.class);
|
|
||||||
|
|
||||||
for (int i = 0; i < args.length; i++) {
|
for (int i = 0; i < args.length; i++) {
|
||||||
// By default, standalone Geyser will check if it should open the GUI based on if the GUI is null
|
// By default, standalone Geyser will check if it should open the GUI based on if the GUI is null
|
||||||
// Optionally, you can force the use of a GUI or no GUI by specifying args
|
// Optionally, you can force the use of a GUI or no GUI by specifying args
|
||||||
@ -127,36 +121,10 @@ public class GeyserStandaloneBootstrap implements GeyserBootstrap {
|
|||||||
// Split the argument by an =
|
// Split the argument by an =
|
||||||
String[] argParts = arg.substring(2).split("=");
|
String[] argParts = arg.substring(2).split("=");
|
||||||
if (argParts.length == 2) {
|
if (argParts.length == 2) {
|
||||||
// Split the config key by . to allow for nested options
|
argsConfigKeys.put(NodePath.of(argParts[0].split("\\.")), argParts[1]);
|
||||||
String[] configKeyParts = argParts[0].split("\\.");
|
|
||||||
|
|
||||||
// Loop the possible config options to check the passed key is valid
|
|
||||||
boolean found = false;
|
|
||||||
for (BeanPropertyDefinition property : availableProperties) {
|
|
||||||
if (configKeyParts[0].equals(property.getName())) {
|
|
||||||
if (configKeyParts.length > 1) {
|
|
||||||
// Loop sub-section options to check the passed key is valid
|
|
||||||
for (BeanPropertyDefinition subProperty : getPOJOForClass(property.getRawPrimaryType())) {
|
|
||||||
if (configKeyParts[1].equals(subProperty.getName())) {
|
|
||||||
found = true;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
found = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add the found key to the stored list for later usage
|
|
||||||
if (found) {
|
|
||||||
argsConfigKeys.put(argParts[0], argParts[1]);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
System.err.println(GeyserLocale.getLocaleStringLog("geyser.bootstrap.args.unrecognised", arg));
|
System.err.println(GeyserLocale.getLocaleStringLog("geyser.bootstrap.args.unrecognised", arg));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -192,18 +160,7 @@ public class GeyserStandaloneBootstrap implements GeyserBootstrap {
|
|||||||
@Override
|
@Override
|
||||||
public void onGeyserEnable() {
|
public void onGeyserEnable() {
|
||||||
try {
|
try {
|
||||||
File configFile = FileUtils.fileOrCopiedFromResource(new File(configFilename), "config.yml",
|
geyserConfig = ConfigLoaderTemp.load(new File(configFilename), GeyserRemoteConfig.class, this::handleArgsConfigOptions);
|
||||||
(x) -> x.replaceAll("generateduuid", UUID.randomUUID().toString()), this);
|
|
||||||
geyserConfig = FileUtils.loadConfig(configFile, GeyserStandaloneConfiguration.class);
|
|
||||||
|
|
||||||
ConfigLoaderTemp.load(GeyserRemoteConfig.class);
|
|
||||||
|
|
||||||
handleArgsConfigOptions();
|
|
||||||
|
|
||||||
if (this.geyserConfig.getRemote().address().equalsIgnoreCase("auto")) {
|
|
||||||
geyserConfig.setAutoconfiguredRemote(true); // Doesn't really need to be set but /shrug
|
|
||||||
geyserConfig.getRemote().setAddress("127.0.0.1");
|
|
||||||
}
|
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
geyserLogger.severe(GeyserLocale.getLocaleStringLog("geyser.config.failed"), ex);
|
geyserLogger.severe(GeyserLocale.getLocaleStringLog("geyser.config.failed"), ex);
|
||||||
if (gui == null) {
|
if (gui == null) {
|
||||||
@ -213,11 +170,10 @@ public class GeyserStandaloneBootstrap implements GeyserBootstrap {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
geyserLogger.setDebug(geyserConfig.isDebugMode());
|
geyserLogger.setDebug(geyserConfig.debugMode());
|
||||||
GeyserConfiguration.checkGeyserConfiguration(geyserConfig, geyserLogger);
|
|
||||||
|
|
||||||
// Allow libraries like Protocol to have their debug information passthrough
|
// Allow libraries like Protocol to have their debug information passthrough
|
||||||
log4jLogger.get().setLevel(geyserConfig.isDebugMode() ? Level.DEBUG : Level.INFO);
|
log4jLogger.get().setLevel(geyserConfig.debugMode() ? Level.DEBUG : Level.INFO);
|
||||||
|
|
||||||
geyser = GeyserImpl.load(PlatformType.STANDALONE, this);
|
geyser = GeyserImpl.load(PlatformType.STANDALONE, this);
|
||||||
|
|
||||||
@ -266,8 +222,8 @@ public class GeyserStandaloneBootstrap implements GeyserBootstrap {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public GeyserConfiguration getGeyserConfig() {
|
public GeyserConfig config() {
|
||||||
return geyserConfig;
|
return this.geyserConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -318,100 +274,47 @@ public class GeyserStandaloneBootstrap implements GeyserBootstrap {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Get the {@link BeanPropertyDefinition}s for the given class
|
public Path getFloodgateKeyPath() {
|
||||||
*
|
return Path.of(geyserConfig.floodgateKeyFile());
|
||||||
* @param clazz The class to get the definitions for
|
|
||||||
* @return A list of {@link BeanPropertyDefinition} for the given class
|
|
||||||
*/
|
|
||||||
public static List<BeanPropertyDefinition> getPOJOForClass(Class<?> clazz) {
|
|
||||||
JavaType javaType = OBJECT_MAPPER.getTypeFactory().constructType(clazz);
|
|
||||||
|
|
||||||
// Introspect the given type
|
|
||||||
BeanDescription beanDescription = OBJECT_MAPPER.getSerializationConfig().introspect(javaType);
|
|
||||||
|
|
||||||
// Find properties
|
|
||||||
List<BeanPropertyDefinition> properties = beanDescription.findProperties();
|
|
||||||
|
|
||||||
// Get the ignored properties
|
|
||||||
Set<String> ignoredProperties = OBJECT_MAPPER.getSerializationConfig().getAnnotationIntrospector()
|
|
||||||
.findPropertyIgnoralByName(OBJECT_MAPPER.getSerializationConfig() ,beanDescription.getClassInfo()).getIgnored();
|
|
||||||
|
|
||||||
// Filter properties removing the ignored ones
|
|
||||||
return properties.stream()
|
|
||||||
.filter(property -> !ignoredProperties.contains(property.getName()))
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set a POJO property value on an object
|
* Set a POJO property value on an object
|
||||||
*
|
*
|
||||||
* @param property The {@link BeanPropertyDefinition} to set
|
|
||||||
* @param parentObject The object to alter
|
|
||||||
* @param value The new value of the property
|
* @param value The new value of the property
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings({"unchecked", "rawtypes"}) // Required for enum usage
|
private static void setConfigOption(CommentedConfigurationNode node, Object value) throws SerializationException {
|
||||||
private static void setConfigOption(BeanPropertyDefinition property, Object parentObject, Object value) {
|
|
||||||
Object parsedValue = value;
|
Object parsedValue = value;
|
||||||
|
|
||||||
// Change the values type if needed
|
// Change the values type if needed
|
||||||
if (int.class.equals(property.getRawPrimaryType())) {
|
Class<?> clazz = node.raw().getClass();
|
||||||
|
if (Integer.class == clazz) {
|
||||||
parsedValue = Integer.valueOf((String) parsedValue);
|
parsedValue = Integer.valueOf((String) parsedValue);
|
||||||
} else if (boolean.class.equals(property.getRawPrimaryType())) {
|
} else if (Boolean.class == clazz) {
|
||||||
parsedValue = Boolean.valueOf((String) parsedValue);
|
parsedValue = Boolean.valueOf((String) parsedValue);
|
||||||
} else if (Enum.class.isAssignableFrom(property.getRawPrimaryType())) {
|
|
||||||
parsedValue = Enum.valueOf((Class<? extends Enum>) property.getRawPrimaryType(), ((String) parsedValue).toUpperCase(Locale.ROOT));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Force the value to be set
|
node.set(parsedValue);
|
||||||
AnnotatedField field = property.getField();
|
|
||||||
field.fixAccess(true);
|
|
||||||
field.setValue(parentObject, parsedValue);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update the loaded {@link GeyserStandaloneConfiguration} with any values passed in the command line arguments
|
* Update the loaded config with any values passed in the command line arguments
|
||||||
*/
|
*/
|
||||||
private void handleArgsConfigOptions() {
|
private void handleArgsConfigOptions(CommentedConfigurationNode node) {
|
||||||
// Get the available properties from the class
|
for (Map.Entry<NodePath, String> configKey : argsConfigKeys.entrySet()) {
|
||||||
List<BeanPropertyDefinition> availableProperties = getPOJOForClass(GeyserJacksonConfiguration.class);
|
NodePath path = configKey.getKey();
|
||||||
|
CommentedConfigurationNode subNode = node.node(path);
|
||||||
|
if (subNode.virtual()) {
|
||||||
|
geyserLogger.error(GeyserLocale.getLocaleStringLog("geyser.bootstrap.args.unrecognised", path));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
for (Map.Entry<String, String> configKey : argsConfigKeys.entrySet()) {
|
|
||||||
String[] configKeyParts = configKey.getKey().split("\\.");
|
|
||||||
|
|
||||||
// Loop over the properties looking for any matches against the stored one from the argument
|
|
||||||
for (BeanPropertyDefinition property : availableProperties) {
|
|
||||||
if (configKeyParts[0].equals(property.getName())) {
|
|
||||||
if (configKeyParts.length > 1) {
|
|
||||||
// Loop through the sub property if the first part matches
|
|
||||||
for (BeanPropertyDefinition subProperty : getPOJOForClass(property.getRawPrimaryType())) {
|
|
||||||
if (configKeyParts[1].equals(subProperty.getName())) {
|
|
||||||
geyserLogger.info(GeyserLocale.getLocaleStringLog("geyser.bootstrap.args.set_config_option", configKey.getKey(), configKey.getValue()));
|
|
||||||
|
|
||||||
// Set the sub property value on the config
|
|
||||||
try {
|
try {
|
||||||
Object subConfig = property.getGetter().callOn(geyserConfig);
|
setConfigOption(subNode, configKey.getValue());
|
||||||
setConfigOption(subProperty, subConfig, configKey.getValue());
|
|
||||||
} catch (Exception e) {
|
|
||||||
geyserLogger.error("Failed to set config option: " + property.getFullName());
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
geyserLogger.info(GeyserLocale.getLocaleStringLog("geyser.bootstrap.args.set_config_option", configKey.getKey(), configKey.getValue()));
|
geyserLogger.info(GeyserLocale.getLocaleStringLog("geyser.bootstrap.args.set_config_option", configKey.getKey(), configKey.getValue()));
|
||||||
|
} catch (SerializationException e) {
|
||||||
// Set the property value on the config
|
geyserLogger.error("Failed to set config option: " + path);
|
||||||
try {
|
|
||||||
setConfigOption(property, geyserConfig, configKey.getValue());
|
|
||||||
} catch (Exception e) {
|
|
||||||
geyserLogger.error("Failed to set config option: " + property.getFullName());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,10 +27,15 @@ package org.geysermc.geyser.platform.velocity;
|
|||||||
|
|
||||||
import com.velocitypowered.api.proxy.ProxyServer;
|
import com.velocitypowered.api.proxy.ProxyServer;
|
||||||
import io.netty.bootstrap.ServerBootstrap;
|
import io.netty.bootstrap.ServerBootstrap;
|
||||||
import io.netty.channel.*;
|
import io.netty.channel.Channel;
|
||||||
|
import io.netty.channel.ChannelFuture;
|
||||||
|
import io.netty.channel.ChannelInitializer;
|
||||||
|
import io.netty.channel.ChannelOption;
|
||||||
|
import io.netty.channel.EventLoopGroup;
|
||||||
|
import io.netty.channel.WriteBufferWaterMark;
|
||||||
import io.netty.channel.local.LocalAddress;
|
import io.netty.channel.local.LocalAddress;
|
||||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
import org.geysermc.geyser.GeyserBootstrap;
|
import org.geysermc.geyser.GeyserPluginBootstrap;
|
||||||
import org.geysermc.geyser.network.netty.GeyserInjector;
|
import org.geysermc.geyser.network.netty.GeyserInjector;
|
||||||
import org.geysermc.geyser.network.netty.LocalServerChannelWrapper;
|
import org.geysermc.geyser.network.netty.LocalServerChannelWrapper;
|
||||||
|
|
||||||
@ -47,7 +52,7 @@ public class GeyserVelocityInjector extends GeyserInjector {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
protected void initializeLocalChannel0(GeyserBootstrap bootstrap) throws Exception {
|
protected void initializeLocalChannel0(GeyserPluginBootstrap bootstrap) throws Exception {
|
||||||
Field cm = proxy.getClass().getDeclaredField("cm");
|
Field cm = proxy.getClass().getDeclaredField("cm");
|
||||||
cm.setAccessible(true);
|
cm.setAccessible(true);
|
||||||
Object connectionManager = cm.get(proxy);
|
Object connectionManager = cm.get(proxy);
|
||||||
@ -80,7 +85,7 @@ public class GeyserVelocityInjector extends GeyserInjector {
|
|||||||
protected void initChannel(@NonNull Channel ch) throws Exception {
|
protected void initChannel(@NonNull Channel ch) throws Exception {
|
||||||
initChannel.invoke(channelInitializer, ch);
|
initChannel.invoke(channelInitializer, ch);
|
||||||
|
|
||||||
if (bootstrap.getGeyserConfig().isDisableCompression() && GeyserVelocityCompressionDisabler.ENABLED) {
|
if (bootstrap.config().disableCompression() && GeyserVelocityCompressionDisabler.ENABLED) {
|
||||||
ch.pipeline().addAfter("minecraft-encoder", "geyser-compression-disabler",
|
ch.pipeline().addAfter("minecraft-encoder", "geyser-compression-disabler",
|
||||||
new GeyserVelocityCompressionDisabler());
|
new GeyserVelocityCompressionDisabler());
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,7 @@ public final class GeyserVelocityUpdateListener {
|
|||||||
|
|
||||||
@Subscribe
|
@Subscribe
|
||||||
public void onPlayerJoin(PostLoginEvent event) {
|
public void onPlayerJoin(PostLoginEvent event) {
|
||||||
if (GeyserImpl.getInstance().getConfig().isNotifyOnNewBedrockUpdate()) {
|
if (GeyserImpl.getInstance().config().notifyOnNewBedrockUpdate()) {
|
||||||
final Player player = event.getPlayer();
|
final Player player = event.getPlayer();
|
||||||
if (player.hasPermission(Constants.UPDATE_PERMISSION)) {
|
if (player.hasPermission(Constants.UPDATE_PERMISSION)) {
|
||||||
VersionCheckUtils.checkForGeyserUpdate(() -> new VelocityCommandSource(player));
|
VersionCheckUtils.checkForGeyserUpdate(() -> new VelocityCommandSource(player));
|
||||||
|
@ -73,6 +73,8 @@ dependencies {
|
|||||||
annotationProcessor(projects.ap)
|
annotationProcessor(projects.ap)
|
||||||
|
|
||||||
api(libs.events)
|
api(libs.events)
|
||||||
|
|
||||||
|
api(libs.bstats)
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.processResources {
|
tasks.processResources {
|
||||||
|
@ -47,6 +47,8 @@ public final class Constants {
|
|||||||
|
|
||||||
public static final int CONFIG_VERSION = 5;
|
public static final int CONFIG_VERSION = 5;
|
||||||
|
|
||||||
|
public static final int BSTATS_ID = 5273;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
URI wsUri = null;
|
URI wsUri = null;
|
||||||
try {
|
try {
|
||||||
|
@ -28,6 +28,7 @@ package org.geysermc.geyser;
|
|||||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
import org.geysermc.geyser.command.GeyserCommandManager;
|
import org.geysermc.geyser.command.GeyserCommandManager;
|
||||||
|
import org.geysermc.geyser.configuration.GeyserConfig;
|
||||||
import org.geysermc.geyser.configuration.GeyserConfiguration;
|
import org.geysermc.geyser.configuration.GeyserConfiguration;
|
||||||
import org.geysermc.geyser.dump.BootstrapDumpInfo;
|
import org.geysermc.geyser.dump.BootstrapDumpInfo;
|
||||||
import org.geysermc.geyser.level.GeyserWorldManager;
|
import org.geysermc.geyser.level.GeyserWorldManager;
|
||||||
@ -72,7 +73,16 @@ public interface GeyserBootstrap {
|
|||||||
*
|
*
|
||||||
* @return The current GeyserConfiguration
|
* @return The current GeyserConfiguration
|
||||||
*/
|
*/
|
||||||
GeyserConfiguration getGeyserConfig();
|
default GeyserConfiguration getGeyserConfig() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the current GeyserConfig
|
||||||
|
*
|
||||||
|
* @return The current GeyserConfig
|
||||||
|
*/
|
||||||
|
GeyserConfig config();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the current GeyserLogger
|
* Returns the current GeyserLogger
|
||||||
@ -189,4 +199,9 @@ public interface GeyserBootstrap {
|
|||||||
* Tests if Floodgate is installed, loads the Floodgate key if so, and returns the result of Floodgate installed.
|
* Tests if Floodgate is installed, loads the Floodgate key if so, and returns the result of Floodgate installed.
|
||||||
*/
|
*/
|
||||||
boolean testFloodgatePluginPresent();
|
boolean testFloodgatePluginPresent();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TEMPORARY - will be removed after The Merge:tm:.
|
||||||
|
*/
|
||||||
|
Path getFloodgateKeyPath();
|
||||||
}
|
}
|
||||||
|
@ -25,9 +25,6 @@
|
|||||||
|
|
||||||
package org.geysermc.geyser;
|
package org.geysermc.geyser;
|
||||||
|
|
||||||
import com.fasterxml.jackson.core.JsonParser;
|
|
||||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import com.google.gson.reflect.TypeToken;
|
import com.google.gson.reflect.TypeToken;
|
||||||
import io.netty.channel.epoll.Epoll;
|
import io.netty.channel.epoll.Epoll;
|
||||||
@ -39,6 +36,11 @@ import lombok.Getter;
|
|||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import net.kyori.adventure.text.format.NamedTextColor;
|
import net.kyori.adventure.text.format.NamedTextColor;
|
||||||
|
import org.bstats.MetricsBase;
|
||||||
|
import org.bstats.charts.AdvancedPie;
|
||||||
|
import org.bstats.charts.DrilldownPie;
|
||||||
|
import org.bstats.charts.SimplePie;
|
||||||
|
import org.bstats.charts.SingleLineChart;
|
||||||
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
@ -67,7 +69,7 @@ import org.geysermc.geyser.api.network.RemoteServer;
|
|||||||
import org.geysermc.geyser.api.util.MinecraftVersion;
|
import org.geysermc.geyser.api.util.MinecraftVersion;
|
||||||
import org.geysermc.geyser.api.util.PlatformType;
|
import org.geysermc.geyser.api.util.PlatformType;
|
||||||
import org.geysermc.geyser.command.GeyserCommandManager;
|
import org.geysermc.geyser.command.GeyserCommandManager;
|
||||||
import org.geysermc.geyser.configuration.GeyserConfiguration;
|
import org.geysermc.geyser.configuration.GeyserConfig;
|
||||||
import org.geysermc.geyser.entity.EntityDefinitions;
|
import org.geysermc.geyser.entity.EntityDefinitions;
|
||||||
import org.geysermc.geyser.erosion.UnixSocketClientListener;
|
import org.geysermc.geyser.erosion.UnixSocketClientListener;
|
||||||
import org.geysermc.geyser.event.GeyserEventBus;
|
import org.geysermc.geyser.event.GeyserEventBus;
|
||||||
@ -91,10 +93,8 @@ import org.geysermc.geyser.text.GeyserLocale;
|
|||||||
import org.geysermc.geyser.text.MinecraftLocale;
|
import org.geysermc.geyser.text.MinecraftLocale;
|
||||||
import org.geysermc.geyser.translator.text.MessageTranslator;
|
import org.geysermc.geyser.translator.text.MessageTranslator;
|
||||||
import org.geysermc.geyser.util.AssetUtils;
|
import org.geysermc.geyser.util.AssetUtils;
|
||||||
import org.geysermc.geyser.util.CooldownUtils;
|
|
||||||
import org.geysermc.geyser.util.DimensionUtils;
|
import org.geysermc.geyser.util.DimensionUtils;
|
||||||
import org.geysermc.geyser.util.JsonUtils;
|
import org.geysermc.geyser.util.JsonUtils;
|
||||||
import org.geysermc.geyser.util.Metrics;
|
|
||||||
import org.geysermc.geyser.util.NewsHandler;
|
import org.geysermc.geyser.util.NewsHandler;
|
||||||
import org.geysermc.geyser.util.VersionCheckUtils;
|
import org.geysermc.geyser.util.VersionCheckUtils;
|
||||||
import org.geysermc.geyser.util.WebUtils;
|
import org.geysermc.geyser.util.WebUtils;
|
||||||
@ -128,13 +128,6 @@ import java.util.regex.Pattern;
|
|||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
public class GeyserImpl implements GeyserApi {
|
public class GeyserImpl implements GeyserApi {
|
||||||
public static final ObjectMapper JSON_MAPPER = new ObjectMapper()
|
|
||||||
.enable(JsonParser.Feature.IGNORE_UNDEFINED)
|
|
||||||
.enable(JsonParser.Feature.ALLOW_COMMENTS)
|
|
||||||
.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
|
|
||||||
.enable(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES)
|
|
||||||
.enable(JsonParser.Feature.ALLOW_SINGLE_QUOTES);
|
|
||||||
|
|
||||||
public static final Gson GSON = JsonUtils.createGson();
|
public static final Gson GSON = JsonUtils.createGson();
|
||||||
|
|
||||||
public static final String NAME = "Geyser";
|
public static final String NAME = "Geyser";
|
||||||
@ -180,7 +173,7 @@ public class GeyserImpl implements GeyserApi {
|
|||||||
private final EventBus<EventRegistrar> eventBus;
|
private final EventBus<EventRegistrar> eventBus;
|
||||||
private final GeyserExtensionManager extensionManager;
|
private final GeyserExtensionManager extensionManager;
|
||||||
|
|
||||||
private Metrics metrics;
|
private MetricsBase metrics;
|
||||||
|
|
||||||
private PendingMicrosoftAuthentication pendingMicrosoftAuthentication;
|
private PendingMicrosoftAuthentication pendingMicrosoftAuthentication;
|
||||||
@Getter(AccessLevel.NONE)
|
@Getter(AccessLevel.NONE)
|
||||||
@ -269,7 +262,7 @@ public class GeyserImpl implements GeyserApi {
|
|||||||
|
|
||||||
startInstance();
|
startInstance();
|
||||||
|
|
||||||
GeyserConfiguration config = bootstrap.getGeyserConfig();
|
GeyserConfig config = bootstrap.config();
|
||||||
|
|
||||||
double completeTime = (System.currentTimeMillis() - startupTime) / 1000D;
|
double completeTime = (System.currentTimeMillis() - startupTime) / 1000D;
|
||||||
String message = GeyserLocale.getLocaleStringLog("geyser.core.finish.done", new DecimalFormat("#.###").format(completeTime));
|
String message = GeyserLocale.getLocaleStringLog("geyser.core.finish.done", new DecimalFormat("#.###").format(completeTime));
|
||||||
@ -277,11 +270,11 @@ public class GeyserImpl implements GeyserApi {
|
|||||||
logger.info(message);
|
logger.info(message);
|
||||||
|
|
||||||
if (platformType == PlatformType.STANDALONE) {
|
if (platformType == PlatformType.STANDALONE) {
|
||||||
if (config.getRemote().authType() != AuthType.FLOODGATE) {
|
if (config.java().authType() != AuthType.FLOODGATE) {
|
||||||
// If the auth-type is Floodgate, then this Geyser instance is probably owned by the Java server
|
// If the auth-type is Floodgate, then this Geyser instance is probably owned by the Java server
|
||||||
logger.warning(GeyserLocale.getLocaleStringLog("geyser.core.movement_warn"));
|
logger.warning(GeyserLocale.getLocaleStringLog("geyser.core.movement_warn"));
|
||||||
}
|
}
|
||||||
} else if (config.getRemote().authType() == AuthType.FLOODGATE) {
|
} else if (config.java().authType() == AuthType.FLOODGATE) {
|
||||||
VersionCheckUtils.checkForOutdatedFloodgate(logger);
|
VersionCheckUtils.checkForOutdatedFloodgate(logger);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -296,7 +289,7 @@ public class GeyserImpl implements GeyserApi {
|
|||||||
GeyserLocale.finalizeDefaultLocale(this);
|
GeyserLocale.finalizeDefaultLocale(this);
|
||||||
}
|
}
|
||||||
GeyserLogger logger = bootstrap.getGeyserLogger();
|
GeyserLogger logger = bootstrap.getGeyserLogger();
|
||||||
GeyserConfiguration config = bootstrap.getGeyserConfig();
|
GeyserConfig config = bootstrap.config();
|
||||||
|
|
||||||
ScoreboardUpdater.init();
|
ScoreboardUpdater.init();
|
||||||
|
|
||||||
@ -314,31 +307,28 @@ public class GeyserImpl implements GeyserApi {
|
|||||||
|
|
||||||
if (platformType != PlatformType.STANDALONE) {
|
if (platformType != PlatformType.STANDALONE) {
|
||||||
int javaPort = bootstrap.getServerPort();
|
int javaPort = bootstrap.getServerPort();
|
||||||
if (config.getRemote().address().equals("auto")) {
|
|
||||||
config.setAutoconfiguredRemote(true);
|
|
||||||
String serverAddress = bootstrap.getServerBindAddress();
|
String serverAddress = bootstrap.getServerBindAddress();
|
||||||
if (!serverAddress.isEmpty() && !"0.0.0.0".equals(serverAddress)) {
|
if (!serverAddress.isEmpty() && !"0.0.0.0".equals(serverAddress)) {
|
||||||
config.getRemote().setAddress(serverAddress);
|
config.java().address(serverAddress);
|
||||||
} else {
|
} else {
|
||||||
// Set the remote address to localhost since that is where we are always connecting
|
// Set the remote address to localhost since that is where we are always connecting
|
||||||
try {
|
try {
|
||||||
config.getRemote().setAddress(InetAddress.getLocalHost().getHostAddress());
|
config.java().address(InetAddress.getLocalHost().getHostAddress());
|
||||||
} catch (UnknownHostException ex) {
|
} catch (UnknownHostException ex) {
|
||||||
logger.debug("Unknown host when trying to find localhost.");
|
logger.debug("Unknown host when trying to find localhost.");
|
||||||
if (config.isDebugMode()) {
|
if (config.debugMode()) {
|
||||||
ex.printStackTrace();
|
ex.printStackTrace();
|
||||||
}
|
}
|
||||||
config.getRemote().setAddress(InetAddress.getLoopbackAddress().getHostAddress());
|
config.java().address(InetAddress.getLoopbackAddress().getHostAddress());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (javaPort != -1) {
|
if (javaPort != -1 && config.asPluginConfig().isEmpty()) {
|
||||||
config.getRemote().setPort(javaPort);
|
config.java().port(javaPort);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean forceMatchServerPort = "server".equals(pluginUdpPort);
|
boolean forceMatchServerPort = "server".equals(pluginUdpPort);
|
||||||
if ((config.getBedrock().isCloneRemotePort() || forceMatchServerPort) && javaPort != -1) {
|
if ((config.asPluginConfig().map(pluginConfig -> pluginConfig.bedrock().cloneRemotePort()).orElse(false) || forceMatchServerPort) && javaPort != -1) {
|
||||||
config.getBedrock().setPort(javaPort);
|
config.bedrock().port(javaPort);
|
||||||
if (forceMatchServerPort) {
|
if (forceMatchServerPort) {
|
||||||
if (geyserUdpPort.isEmpty()) {
|
if (geyserUdpPort.isEmpty()) {
|
||||||
logger.info("Port set from system generic property to match Java server.");
|
logger.info("Port set from system generic property to match Java server.");
|
||||||
@ -352,15 +342,15 @@ public class GeyserImpl implements GeyserApi {
|
|||||||
if ("server".equals(pluginUdpAddress)) {
|
if ("server".equals(pluginUdpAddress)) {
|
||||||
String address = bootstrap.getServerBindAddress();
|
String address = bootstrap.getServerBindAddress();
|
||||||
if (!address.isEmpty()) {
|
if (!address.isEmpty()) {
|
||||||
config.getBedrock().setAddress(address);
|
config.bedrock().address(address);
|
||||||
}
|
}
|
||||||
} else if (!pluginUdpAddress.isEmpty()) {
|
} else if (!pluginUdpAddress.isEmpty()) {
|
||||||
config.getBedrock().setAddress(pluginUdpAddress);
|
config.bedrock().address(pluginUdpAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!portPropertyApplied && !pluginUdpPort.isEmpty()) {
|
if (!portPropertyApplied && !pluginUdpPort.isEmpty()) {
|
||||||
int port = Integer.parseInt(pluginUdpPort);
|
int port = Integer.parseInt(pluginUdpPort);
|
||||||
config.getBedrock().setPort(port);
|
config.bedrock().port(port);
|
||||||
if (geyserUdpPort.isEmpty()) {
|
if (geyserUdpPort.isEmpty()) {
|
||||||
logger.info("Port set from generic system property: " + port);
|
logger.info("Port set from generic system property: " + port);
|
||||||
} else {
|
} else {
|
||||||
@ -378,42 +368,44 @@ public class GeyserImpl implements GeyserApi {
|
|||||||
}
|
}
|
||||||
} catch (NumberFormatException e) {
|
} catch (NumberFormatException e) {
|
||||||
logger.error(String.format("Invalid broadcast port: %s! Defaulting to configured port.", broadcastPort + " (" + e.getMessage() + ")"));
|
logger.error(String.format("Invalid broadcast port: %s! Defaulting to configured port.", broadcastPort + " (" + e.getMessage() + ")"));
|
||||||
parsedPort = config.getBedrock().port();
|
parsedPort = config.bedrock().port();
|
||||||
}
|
}
|
||||||
config.getBedrock().setBroadcastPort(parsedPort);
|
config.bedrock().broadcastPort(parsedPort);
|
||||||
logger.info("Broadcast port set from system property: " + parsedPort);
|
logger.info("Broadcast port set from system property: " + parsedPort);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (platformType != PlatformType.VIAPROXY) {
|
if (platformType != PlatformType.VIAPROXY) {
|
||||||
boolean floodgatePresent = bootstrap.testFloodgatePluginPresent();
|
boolean floodgatePresent = bootstrap.testFloodgatePluginPresent();
|
||||||
if (config.getRemote().authType() == AuthType.FLOODGATE && !floodgatePresent) {
|
if (config.java().authType() == AuthType.FLOODGATE && !floodgatePresent) {
|
||||||
logger.severe(GeyserLocale.getLocaleStringLog("geyser.bootstrap.floodgate.not_installed") + " "
|
logger.severe(GeyserLocale.getLocaleStringLog("geyser.bootstrap.floodgate.not_installed") + " "
|
||||||
+ GeyserLocale.getLocaleStringLog("geyser.bootstrap.floodgate.disabling"));
|
+ GeyserLocale.getLocaleStringLog("geyser.bootstrap.floodgate.disabling"));
|
||||||
return;
|
return;
|
||||||
} else if (config.isAutoconfiguredRemote() && floodgatePresent) {
|
} else if (floodgatePresent) {
|
||||||
// Floodgate installed means that the user wants Floodgate authentication
|
// Floodgate installed means that the user wants Floodgate authentication
|
||||||
logger.debug("Auto-setting to Floodgate authentication.");
|
logger.debug("Auto-setting to Floodgate authentication.");
|
||||||
config.getRemote().setAuthType(AuthType.FLOODGATE);
|
config.java().authType(AuthType.FLOODGATE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String remoteAddress = config.getRemote().address();
|
if (config.asPluginConfig().isEmpty()) {
|
||||||
|
String remoteAddress = config.java().address();
|
||||||
// Filters whether it is not an IP address or localhost, because otherwise it is not possible to find out an SRV entry.
|
// Filters whether it is not an IP address or localhost, because otherwise it is not possible to find out an SRV entry.
|
||||||
if (!remoteAddress.matches(IP_REGEX) && !remoteAddress.equalsIgnoreCase("localhost")) {
|
if (!remoteAddress.matches(IP_REGEX) && !remoteAddress.equalsIgnoreCase("localhost")) {
|
||||||
String[] record = WebUtils.findSrvRecord(this, remoteAddress);
|
String[] record = WebUtils.findSrvRecord(this, remoteAddress);
|
||||||
if (record != null) {
|
if (record != null) {
|
||||||
int remotePort = Integer.parseInt(record[2]);
|
int remotePort = Integer.parseInt(record[2]);
|
||||||
config.getRemote().setAddress(remoteAddress = record[3]);
|
config.java().address(remoteAddress = record[3]);
|
||||||
config.getRemote().setPort(remotePort);
|
config.java().port(remotePort);
|
||||||
logger.debug("Found SRV record \"" + remoteAddress + ":" + remotePort + "\"");
|
logger.debug("Found SRV record \"" + remoteAddress + ":" + remotePort + "\"");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Ensure that PacketLib does not create an event loop for handling packets; we'll do that ourselves
|
// Ensure that PacketLib does not create an event loop for handling packets; we'll do that ourselves
|
||||||
TcpSession.USE_EVENT_LOOP_FOR_PACKETS = false;
|
TcpSession.USE_EVENT_LOOP_FOR_PACKETS = false;
|
||||||
|
|
||||||
pendingMicrosoftAuthentication = new PendingMicrosoftAuthentication(config.getPendingAuthenticationTimeout());
|
pendingMicrosoftAuthentication = new PendingMicrosoftAuthentication(config.pendingAuthenticationTimeout());
|
||||||
|
|
||||||
this.newsHandler = new NewsHandler(BRANCH, this.buildNumber());
|
this.newsHandler = new NewsHandler(BRANCH, this.buildNumber());
|
||||||
|
|
||||||
@ -425,8 +417,7 @@ public class GeyserImpl implements GeyserApi {
|
|||||||
logger.debug("Epoll is not available; Erosion's Unix socket handling will not work.");
|
logger.debug("Epoll is not available; Erosion's Unix socket handling will not work.");
|
||||||
}
|
}
|
||||||
|
|
||||||
CooldownUtils.setDefaultShowCooldown(config.getShowCooldown());
|
DimensionUtils.changeBedrockNetherId(config.aboveBedrockNetherBuilding()); // Apply End dimension ID workaround to Nether
|
||||||
DimensionUtils.changeBedrockNetherId(config.isAboveBedrockNetherBuilding()); // Apply End dimension ID workaround to Nether
|
|
||||||
|
|
||||||
Integer bedrockThreadCount = Integer.getInteger("Geyser.BedrockNetworkThreads");
|
Integer bedrockThreadCount = Integer.getInteger("Geyser.BedrockNetworkThreads");
|
||||||
if (bedrockThreadCount == null) {
|
if (bedrockThreadCount == null) {
|
||||||
@ -436,14 +427,14 @@ public class GeyserImpl implements GeyserApi {
|
|||||||
|
|
||||||
if (shouldStartListener) {
|
if (shouldStartListener) {
|
||||||
this.geyserServer = new GeyserServer(this, bedrockThreadCount);
|
this.geyserServer = new GeyserServer(this, bedrockThreadCount);
|
||||||
this.geyserServer.bind(new InetSocketAddress(config.getBedrock().address(), config.getBedrock().port()))
|
this.geyserServer.bind(new InetSocketAddress(config.bedrock().address(), config.bedrock().port()))
|
||||||
.whenComplete((avoid, throwable) -> {
|
.whenComplete((avoid, throwable) -> {
|
||||||
if (throwable == null) {
|
if (throwable == null) {
|
||||||
logger.info(GeyserLocale.getLocaleStringLog("geyser.core.start", config.getBedrock().address(),
|
logger.info(GeyserLocale.getLocaleStringLog("geyser.core.start", config.bedrock().address(),
|
||||||
String.valueOf(config.getBedrock().port())));
|
String.valueOf(config.bedrock().port())));
|
||||||
} else {
|
} else {
|
||||||
String address = config.getBedrock().address();
|
String address = config.bedrock().address();
|
||||||
int port = config.getBedrock().port();
|
int port = config.bedrock().port();
|
||||||
logger.severe(GeyserLocale.getLocaleStringLog("geyser.core.fail", address, String.valueOf(port)));
|
logger.severe(GeyserLocale.getLocaleStringLog("geyser.core.fail", address, String.valueOf(port)));
|
||||||
if (!"0.0.0.0".equals(address)) {
|
if (!"0.0.0.0".equals(address)) {
|
||||||
logger.info(Component.text("Suggestion: try setting `address` under `bedrock` in the Geyser config back to 0.0.0.0", NamedTextColor.GREEN));
|
logger.info(Component.text("Suggestion: try setting `address` under `bedrock` in the Geyser config back to 0.0.0.0", NamedTextColor.GREEN));
|
||||||
@ -453,9 +444,9 @@ public class GeyserImpl implements GeyserApi {
|
|||||||
}).join();
|
}).join();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config.getRemote().authType() == AuthType.FLOODGATE) {
|
if (config.java().authType() == AuthType.FLOODGATE) {
|
||||||
try {
|
try {
|
||||||
Key key = new AesKeyProducer().produceFrom(config.getFloodgateKeyPath());
|
Key key = new AesKeyProducer().produceFrom(bootstrap.getFloodgateKeyPath());
|
||||||
cipher = new AesCipher(new Base64Topping());
|
cipher = new AesCipher(new Base64Topping());
|
||||||
cipher.init(key);
|
cipher.init(key);
|
||||||
logger.debug("Loaded Floodgate key!");
|
logger.debug("Loaded Floodgate key!");
|
||||||
@ -467,15 +458,39 @@ public class GeyserImpl implements GeyserApi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config.getMetrics().isEnabled()) {
|
if (config.metrics().enabled()) {
|
||||||
metrics = new Metrics(this, "GeyserMC", config.getMetrics().getUniqueId(), false, java.util.logging.Logger.getLogger(""));
|
metrics = new MetricsBase(
|
||||||
metrics.addCustomChart(new Metrics.SingleLineChart("players", sessionManager::size));
|
"server-implementation",
|
||||||
|
config.metrics().uuid().toString(),
|
||||||
|
Constants.BSTATS_ID,
|
||||||
|
true, // Already checked above.
|
||||||
|
builder -> {
|
||||||
|
// OS specific data
|
||||||
|
String osName = System.getProperty("os.name");
|
||||||
|
String osArch = System.getProperty("os.arch");
|
||||||
|
String osVersion = System.getProperty("os.version");
|
||||||
|
int coreCount = Runtime.getRuntime().availableProcessors();
|
||||||
|
|
||||||
|
builder.appendField("osName", osName);
|
||||||
|
builder.appendField("osArch", osArch);
|
||||||
|
builder.appendField("osVersion", osVersion);
|
||||||
|
builder.appendField("coreCount", coreCount);
|
||||||
|
},
|
||||||
|
builder -> {},
|
||||||
|
null,
|
||||||
|
() -> true,
|
||||||
|
logger::error,
|
||||||
|
logger::info,
|
||||||
|
config.debugMode(),
|
||||||
|
config.debugMode(),
|
||||||
|
config.debugMode());
|
||||||
|
metrics.addCustomChart(new SingleLineChart("players", sessionManager::size));
|
||||||
// Prevent unwanted words best we can
|
// Prevent unwanted words best we can
|
||||||
metrics.addCustomChart(new Metrics.SimplePie("authMode", () -> config.getRemote().authType().toString().toLowerCase(Locale.ROOT)));
|
metrics.addCustomChart(new SimplePie("authMode", () -> config.java().authType().toString().toLowerCase(Locale.ROOT)));
|
||||||
metrics.addCustomChart(new Metrics.SimplePie("platform", platformType::platformName));
|
metrics.addCustomChart(new SimplePie("platform", platformType::platformName));
|
||||||
metrics.addCustomChart(new Metrics.SimplePie("defaultLocale", GeyserLocale::getDefaultLocale));
|
metrics.addCustomChart(new SimplePie("defaultLocale", GeyserLocale::getDefaultLocale));
|
||||||
metrics.addCustomChart(new Metrics.SimplePie("version", () -> GeyserImpl.VERSION));
|
metrics.addCustomChart(new SimplePie("version", () -> GeyserImpl.VERSION));
|
||||||
metrics.addCustomChart(new Metrics.AdvancedPie("playerPlatform", () -> {
|
metrics.addCustomChart(new AdvancedPie("playerPlatform", () -> {
|
||||||
Map<String, Integer> valueMap = new HashMap<>();
|
Map<String, Integer> valueMap = new HashMap<>();
|
||||||
for (GeyserSession session : sessionManager.getAllSessions()) {
|
for (GeyserSession session : sessionManager.getAllSessions()) {
|
||||||
if (session == null) continue;
|
if (session == null) continue;
|
||||||
@ -489,7 +504,7 @@ public class GeyserImpl implements GeyserApi {
|
|||||||
}
|
}
|
||||||
return valueMap;
|
return valueMap;
|
||||||
}));
|
}));
|
||||||
metrics.addCustomChart(new Metrics.AdvancedPie("playerVersion", () -> {
|
metrics.addCustomChart(new AdvancedPie("playerVersion", () -> {
|
||||||
Map<String, Integer> valueMap = new HashMap<>();
|
Map<String, Integer> valueMap = new HashMap<>();
|
||||||
for (GeyserSession session : sessionManager.getAllSessions()) {
|
for (GeyserSession session : sessionManager.getAllSessions()) {
|
||||||
if (session == null) continue;
|
if (session == null) continue;
|
||||||
@ -511,7 +526,7 @@ public class GeyserImpl implements GeyserApi {
|
|||||||
platformMap.put(platformType.platformName(), 1);
|
platformMap.put(platformType.platformName(), 1);
|
||||||
versionMap.put(minecraftVersion, platformMap);
|
versionMap.put(minecraftVersion, platformMap);
|
||||||
|
|
||||||
metrics.addCustomChart(new Metrics.DrilldownPie("minecraftServerVersion", () -> {
|
metrics.addCustomChart(new DrilldownPie("minecraftServerVersion", () -> {
|
||||||
// By the end, we should return, for example:
|
// By the end, we should return, for example:
|
||||||
// 1.16.5 => (Spigot, 1)
|
// 1.16.5 => (Spigot, 1)
|
||||||
return versionMap;
|
return versionMap;
|
||||||
@ -520,7 +535,7 @@ public class GeyserImpl implements GeyserApi {
|
|||||||
|
|
||||||
// The following code can be attributed to the PaperMC project
|
// The following code can be attributed to the PaperMC project
|
||||||
// https://github.com/PaperMC/Paper/blob/master/Spigot-Server-Patches/0005-Paper-Metrics.patch#L614
|
// https://github.com/PaperMC/Paper/blob/master/Spigot-Server-Patches/0005-Paper-Metrics.patch#L614
|
||||||
metrics.addCustomChart(new Metrics.DrilldownPie("javaVersion", () -> {
|
metrics.addCustomChart(new DrilldownPie("javaVersion", () -> {
|
||||||
Map<String, Map<String, Integer>> map = new HashMap<>();
|
Map<String, Map<String, Integer>> map = new HashMap<>();
|
||||||
String javaVersion = System.getProperty("java.version");
|
String javaVersion = System.getProperty("java.version");
|
||||||
Map<String, Integer> entry = new HashMap<>();
|
Map<String, Integer> entry = new HashMap<>();
|
||||||
@ -555,7 +570,7 @@ public class GeyserImpl implements GeyserApi {
|
|||||||
metrics = null;
|
metrics = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config.getRemote().authType() == AuthType.ONLINE) {
|
if (config.java().authType() == AuthType.ONLINE) {
|
||||||
// May be written/read to on multiple threads from each GeyserSession as well as writing the config
|
// May be written/read to on multiple threads from each GeyserSession as well as writing the config
|
||||||
savedRefreshTokens = new ConcurrentHashMap<>();
|
savedRefreshTokens = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
@ -570,7 +585,7 @@ public class GeyserImpl implements GeyserApi {
|
|||||||
logger.error("Cannot load saved user tokens!", e);
|
logger.error("Cannot load saved user tokens!", e);
|
||||||
}
|
}
|
||||||
if (refreshTokenFile != null) {
|
if (refreshTokenFile != null) {
|
||||||
List<String> validUsers = config.getSavedUserLogins();
|
List<String> validUsers = config.savedUserLogins();
|
||||||
boolean doWrite = false;
|
boolean doWrite = false;
|
||||||
for (Map.Entry<String, String> entry : refreshTokenFile.entrySet()) {
|
for (Map.Entry<String, String> entry : refreshTokenFile.entrySet()) {
|
||||||
String user = entry.getKey();
|
String user = entry.getKey();
|
||||||
@ -598,7 +613,7 @@ public class GeyserImpl implements GeyserApi {
|
|||||||
this.eventBus.fire(new GeyserPostInitializeEvent(this.extensionManager, this.eventBus));
|
this.eventBus.fire(new GeyserPostInitializeEvent(this.extensionManager, this.eventBus));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config.isNotifyOnNewBedrockUpdate()) {
|
if (config.notifyOnNewBedrockUpdate()) {
|
||||||
VersionCheckUtils.checkForGeyserUpdate(this::getLogger);
|
VersionCheckUtils.checkForGeyserUpdate(this::getLogger);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -750,13 +765,13 @@ public class GeyserImpl implements GeyserApi {
|
|||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
public RemoteServer defaultRemoteServer() {
|
public RemoteServer defaultRemoteServer() {
|
||||||
return getConfig().getRemote();
|
return config().java();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@NonNull
|
@NonNull
|
||||||
public BedrockListener bedrockListener() {
|
public BedrockListener bedrockListener() {
|
||||||
return getConfig().getBedrock();
|
return config().bedrock();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -830,8 +845,8 @@ public class GeyserImpl implements GeyserApi {
|
|||||||
return bootstrap.getGeyserLogger();
|
return bootstrap.getGeyserLogger();
|
||||||
}
|
}
|
||||||
|
|
||||||
public GeyserConfiguration getConfig() {
|
public GeyserConfig config() {
|
||||||
return bootstrap.getGeyserConfig();
|
return bootstrap.config();
|
||||||
}
|
}
|
||||||
|
|
||||||
public WorldManager getWorldManager() {
|
public WorldManager getWorldManager() {
|
||||||
@ -844,7 +859,7 @@ public class GeyserImpl implements GeyserApi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void saveRefreshToken(@NonNull String bedrockName, @NonNull String refreshToken) {
|
public void saveRefreshToken(@NonNull String bedrockName, @NonNull String refreshToken) {
|
||||||
if (!getConfig().getSavedUserLogins().contains(bedrockName)) {
|
if (!config().savedUserLogins().contains(bedrockName)) {
|
||||||
// Do not save this login
|
// Do not save this login
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
36
core/src/main/java/org/geysermc/geyser/GeyserPluginBootstrap.java
Normale Datei
36
core/src/main/java/org/geysermc/geyser/GeyserPluginBootstrap.java
Normale Datei
@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2024 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.geyser;
|
||||||
|
|
||||||
|
import org.geysermc.geyser.configuration.GeyserPluginConfig;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used in any instance where Geyser is directly attached to a server instance of some sort.
|
||||||
|
*/
|
||||||
|
public interface GeyserPluginBootstrap extends GeyserBootstrap {
|
||||||
|
@Override
|
||||||
|
GeyserPluginConfig config();
|
||||||
|
}
|
@ -32,7 +32,7 @@ import org.geysermc.geyser.GeyserImpl;
|
|||||||
import org.geysermc.geyser.api.util.PlatformType;
|
import org.geysermc.geyser.api.util.PlatformType;
|
||||||
import org.geysermc.geyser.command.GeyserCommand;
|
import org.geysermc.geyser.command.GeyserCommand;
|
||||||
import org.geysermc.geyser.command.GeyserCommandSource;
|
import org.geysermc.geyser.command.GeyserCommandSource;
|
||||||
import org.geysermc.geyser.configuration.GeyserConfiguration;
|
import org.geysermc.geyser.configuration.GeyserConfig;
|
||||||
import org.geysermc.geyser.session.GeyserSession;
|
import org.geysermc.geyser.session.GeyserSession;
|
||||||
import org.geysermc.geyser.text.GeyserLocale;
|
import org.geysermc.geyser.text.GeyserLocale;
|
||||||
import org.geysermc.geyser.util.LoopbackUtil;
|
import org.geysermc.geyser.util.LoopbackUtil;
|
||||||
@ -86,7 +86,7 @@ public class ConnectionTestCommand extends GeyserCommand {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
port = geyser.getConfig().getBedrock().broadcastPort();
|
port = geyser.config().bedrock().broadcastPort();
|
||||||
}
|
}
|
||||||
String ip = fullAddress[0];
|
String ip = fullAddress[0];
|
||||||
|
|
||||||
@ -114,41 +114,41 @@ public class ConnectionTestCommand extends GeyserCommand {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
GeyserConfiguration config = geyser.getConfig();
|
GeyserConfig config = geyser.config();
|
||||||
|
|
||||||
// Issue: do the ports not line up? We only check this if players don't override the broadcast port - if they do, they (hopefully) know what they're doing
|
// Issue: do the ports not line up? We only check this if players don't override the broadcast port - if they do, they (hopefully) know what they're doing
|
||||||
if (config.getBedrock().broadcastPort() == config.getBedrock().port()) {
|
if (config.bedrock().broadcastPort() == config.bedrock().port()) {
|
||||||
if (port != config.getBedrock().port()) {
|
if (port != config.bedrock().port()) {
|
||||||
if (fullAddress.length == 2) {
|
if (fullAddress.length == 2) {
|
||||||
sender.sendMessage("The port you are testing with (" + port + ") is not the same as you set in your Geyser configuration ("
|
sender.sendMessage("The port you are testing with (" + port + ") is not the same as you set in your Geyser configuration ("
|
||||||
+ config.getBedrock().port() + ")");
|
+ config.bedrock().port() + ")");
|
||||||
sender.sendMessage("Re-run the command with the port in the config, or change the `bedrock` `port` in the config.");
|
sender.sendMessage("Re-run the command with the port in the config, or change the `bedrock` `port` in the config.");
|
||||||
if (config.getBedrock().isCloneRemotePort()) {
|
if (config.asPluginConfig().map(pluginConfig -> pluginConfig.bedrock().cloneRemotePort()).orElse(false)) {
|
||||||
sender.sendMessage("You have `clone-remote-port` enabled. This option ignores the `bedrock` `port` in the config, and uses the Java server port instead.");
|
sender.sendMessage("You have `clone-remote-port` enabled. This option ignores the `bedrock` `port` in the config, and uses the Java server port instead.");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
sender.sendMessage("You did not specify the port to check (add it with \":<port>\"), " +
|
sender.sendMessage("You did not specify the port to check (add it with \":<port>\"), " +
|
||||||
"and the default port 19132 does not match the port in your Geyser configuration ("
|
"and the default port 19132 does not match the port in your Geyser configuration ("
|
||||||
+ config.getBedrock().port() + ")!");
|
+ config.bedrock().port() + ")!");
|
||||||
sender.sendMessage("Re-run the command with that port, or change the port in the config under `bedrock` `port`.");
|
sender.sendMessage("Re-run the command with that port, or change the port in the config under `bedrock` `port`.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (config.getBedrock().broadcastPort() != port) {
|
if (config.bedrock().broadcastPort() != port) {
|
||||||
sender.sendMessage("The port you are testing with (" + port + ") is not the same as the broadcast port set in your Geyser configuration ("
|
sender.sendMessage("The port you are testing with (" + port + ") is not the same as the broadcast port set in your Geyser configuration ("
|
||||||
+ config.getBedrock().broadcastPort() + "). ");
|
+ config.bedrock().broadcastPort() + "). ");
|
||||||
sender.sendMessage("You ONLY need to change the broadcast port if clients connects with a port different from the port Geyser is running on.");
|
sender.sendMessage("You ONLY need to change the broadcast port if clients connects with a port different from the port Geyser is running on.");
|
||||||
sender.sendMessage("Re-run the command with the port in the config, or change the `bedrock` `broadcast-port` in the config.");
|
sender.sendMessage("Re-run the command with the port in the config, or change the `bedrock` `broadcast-port` in the config.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Issue: is the `bedrock` `address` in the config different?
|
// Issue: is the `bedrock` `address` in the config different?
|
||||||
if (!config.getBedrock().address().equals("0.0.0.0")) {
|
if (!config.bedrock().address().equals("0.0.0.0")) {
|
||||||
sender.sendMessage("The address specified in `bedrock` `address` is not \"0.0.0.0\" - this may cause issues unless this is deliberate and intentional.");
|
sender.sendMessage("The address specified in `bedrock` `address` is not \"0.0.0.0\" - this may cause issues unless this is deliberate and intentional.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Issue: did someone turn on enable-proxy-protocol, and they didn't mean it?
|
// Issue: did someone turn on enable-proxy-protocol, and they didn't mean it?
|
||||||
if (config.getBedrock().isEnableProxyProtocol()) {
|
if (config.bedrock().enableProxyProtocol()) {
|
||||||
sender.sendMessage("You have the `enable-proxy-protocol` setting enabled. " +
|
sender.sendMessage("You have the `enable-proxy-protocol` setting enabled. " +
|
||||||
"Unless you're deliberately using additional software that REQUIRES this setting, you may not need it enabled.");
|
"Unless you're deliberately using additional software that REQUIRES this setting, you may not need it enabled.");
|
||||||
}
|
}
|
||||||
|
@ -25,13 +25,14 @@
|
|||||||
|
|
||||||
package org.geysermc.geyser.command.defaults;
|
package org.geysermc.geyser.command.defaults;
|
||||||
|
|
||||||
import com.fasterxml.jackson.core.util.DefaultIndenter;
|
import com.google.gson.Gson;
|
||||||
import com.fasterxml.jackson.core.util.DefaultPrettyPrinter;
|
import com.google.gson.GsonBuilder;
|
||||||
import com.fasterxml.jackson.databind.JsonNode;
|
import com.google.gson.JsonObject;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.google.gson.JsonParser;
|
||||||
|
import com.google.gson.JsonSyntaxException;
|
||||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
import org.geysermc.geyser.api.util.PlatformType;
|
|
||||||
import org.geysermc.geyser.GeyserImpl;
|
import org.geysermc.geyser.GeyserImpl;
|
||||||
|
import org.geysermc.geyser.api.util.PlatformType;
|
||||||
import org.geysermc.geyser.command.GeyserCommand;
|
import org.geysermc.geyser.command.GeyserCommand;
|
||||||
import org.geysermc.geyser.command.GeyserCommandSource;
|
import org.geysermc.geyser.command.GeyserCommandSource;
|
||||||
import org.geysermc.geyser.dump.DumpInfo;
|
import org.geysermc.geyser.dump.DumpInfo;
|
||||||
@ -49,7 +50,6 @@ import java.util.List;
|
|||||||
public class DumpCommand extends GeyserCommand {
|
public class DumpCommand extends GeyserCommand {
|
||||||
|
|
||||||
private final GeyserImpl geyser;
|
private final GeyserImpl geyser;
|
||||||
private static final ObjectMapper MAPPER = new ObjectMapper();
|
|
||||||
private static final String DUMP_URL = "https://dump.geysermc.org/";
|
private static final String DUMP_URL = "https://dump.geysermc.org/";
|
||||||
|
|
||||||
public DumpCommand(GeyserImpl geyser, String name, String description, String permission) {
|
public DumpCommand(GeyserImpl geyser, String name, String description, String permission) {
|
||||||
@ -81,18 +81,13 @@ public class DumpCommand extends GeyserCommand {
|
|||||||
|
|
||||||
AsteriskSerializer.showSensitive = showSensitive;
|
AsteriskSerializer.showSensitive = showSensitive;
|
||||||
|
|
||||||
|
Gson gson = new GsonBuilder().setPrettyPrinting().create();
|
||||||
|
|
||||||
sender.sendMessage(GeyserLocale.getPlayerLocaleString("geyser.commands.dump.collecting", sender.locale()));
|
sender.sendMessage(GeyserLocale.getPlayerLocaleString("geyser.commands.dump.collecting", sender.locale()));
|
||||||
String dumpData;
|
String dumpData;
|
||||||
try {
|
try {
|
||||||
if (offlineDump) {
|
dumpData = gson.toJson(new DumpInfo(addLog));
|
||||||
DefaultPrettyPrinter prettyPrinter = new DefaultPrettyPrinter();
|
} catch (JsonSyntaxException e) {
|
||||||
// Make arrays easier to read
|
|
||||||
prettyPrinter.indentArraysWith(new DefaultIndenter(" ", "\n"));
|
|
||||||
dumpData = MAPPER.writer(prettyPrinter).writeValueAsString(new DumpInfo(addLog));
|
|
||||||
} else {
|
|
||||||
dumpData = MAPPER.writeValueAsString(new DumpInfo(addLog));
|
|
||||||
}
|
|
||||||
} catch (IOException e) {
|
|
||||||
sender.sendMessage(ChatColor.RED + GeyserLocale.getPlayerLocaleString("geyser.commands.dump.collect_error", sender.locale()));
|
sender.sendMessage(ChatColor.RED + GeyserLocale.getPlayerLocaleString("geyser.commands.dump.collect_error", sender.locale()));
|
||||||
geyser.getLogger().error(GeyserLocale.getLocaleStringLog("geyser.commands.dump.collect_error_short"), e);
|
geyser.getLogger().error(GeyserLocale.getLocaleStringLog("geyser.commands.dump.collect_error_short"), e);
|
||||||
return;
|
return;
|
||||||
@ -118,10 +113,10 @@ public class DumpCommand extends GeyserCommand {
|
|||||||
sender.sendMessage(GeyserLocale.getPlayerLocaleString("geyser.commands.dump.uploading", sender.locale()));
|
sender.sendMessage(GeyserLocale.getPlayerLocaleString("geyser.commands.dump.uploading", sender.locale()));
|
||||||
|
|
||||||
String response;
|
String response;
|
||||||
JsonNode responseNode;
|
JsonObject responseNode;
|
||||||
try {
|
try {
|
||||||
response = WebUtils.post(DUMP_URL + "documents", dumpData);
|
response = WebUtils.post(DUMP_URL + "documents", dumpData);
|
||||||
responseNode = MAPPER.readTree(response);
|
responseNode = (JsonObject) new JsonParser().parse(response);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
sender.sendMessage(ChatColor.RED + GeyserLocale.getPlayerLocaleString("geyser.commands.dump.upload_error", sender.locale()));
|
sender.sendMessage(ChatColor.RED + GeyserLocale.getPlayerLocaleString("geyser.commands.dump.upload_error", sender.locale()));
|
||||||
geyser.getLogger().error(GeyserLocale.getLocaleStringLog("geyser.commands.dump.upload_error_short"), e);
|
geyser.getLogger().error(GeyserLocale.getLocaleStringLog("geyser.commands.dump.upload_error_short"), e);
|
||||||
@ -129,11 +124,11 @@ public class DumpCommand extends GeyserCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!responseNode.has("key")) {
|
if (!responseNode.has("key")) {
|
||||||
sender.sendMessage(ChatColor.RED + GeyserLocale.getPlayerLocaleString("geyser.commands.dump.upload_error_short", sender.locale()) + ": " + (responseNode.has("message") ? responseNode.get("message").asText() : response));
|
sender.sendMessage(ChatColor.RED + GeyserLocale.getPlayerLocaleString("geyser.commands.dump.upload_error_short", sender.locale()) + ": " + (responseNode.has("message") ? responseNode.get("message").getAsString() : response));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
uploadedDumpUrl = DUMP_URL + responseNode.get("key").asText();
|
uploadedDumpUrl = DUMP_URL + responseNode.get("key").getAsString();
|
||||||
}
|
}
|
||||||
|
|
||||||
sender.sendMessage(GeyserLocale.getPlayerLocaleString("geyser.commands.dump.message", sender.locale()) + " " + ChatColor.DARK_AQUA + uploadedDumpUrl);
|
sender.sendMessage(GeyserLocale.getPlayerLocaleString("geyser.commands.dump.message", sender.locale()) + " " + ChatColor.DARK_AQUA + uploadedDumpUrl);
|
||||||
|
@ -25,18 +25,21 @@
|
|||||||
|
|
||||||
package org.geysermc.geyser.configuration;
|
package org.geysermc.geyser.configuration;
|
||||||
|
|
||||||
import org.spongepowered.configurate.ConfigurationNode;
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
import org.spongepowered.configurate.NodePath;
|
import org.spongepowered.configurate.CommentedConfigurationNode;
|
||||||
import org.spongepowered.configurate.interfaces.InterfaceDefaultOptions;
|
import org.spongepowered.configurate.interfaces.InterfaceDefaultOptions;
|
||||||
import org.spongepowered.configurate.transformation.ConfigurationTransformation;
|
import org.spongepowered.configurate.transformation.ConfigurationTransformation;
|
||||||
import org.spongepowered.configurate.yaml.YamlConfigurationLoader;
|
import org.spongepowered.configurate.yaml.YamlConfigurationLoader;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.Files;
|
import java.util.function.Consumer;
|
||||||
import java.nio.file.Path;
|
|
||||||
|
|
||||||
public class ConfigLoaderTemp {
|
import static org.spongepowered.configurate.NodePath.path;
|
||||||
|
import static org.spongepowered.configurate.transformation.TransformAction.remove;
|
||||||
|
import static org.spongepowered.configurate.transformation.TransformAction.rename;
|
||||||
|
|
||||||
|
public final class ConfigLoaderTemp {
|
||||||
private static final String HEADER = """
|
private static final String HEADER = """
|
||||||
--------------------------------
|
--------------------------------
|
||||||
Geyser Configuration File
|
Geyser Configuration File
|
||||||
@ -51,35 +54,81 @@ public class ConfigLoaderTemp {
|
|||||||
In most cases, especially with server hosting providers, further hosting-specific configuration is required.
|
In most cases, especially with server hosting providers, further hosting-specific configuration is required.
|
||||||
--------------------------------""";
|
--------------------------------""";
|
||||||
|
|
||||||
public static <T extends GeyserConfig> T load(Class<T> configClass) throws IOException {
|
public static <T extends GeyserConfig> T load(File file, Class<T> configClass) throws IOException {
|
||||||
var loader = YamlConfigurationLoader.builder()
|
return load(file, configClass, null);
|
||||||
.file(new File("newconfig.yml"))
|
}
|
||||||
.defaultOptions(options -> InterfaceDefaultOptions.addTo(options.header(HEADER)))
|
|
||||||
.build();
|
|
||||||
ConfigurationNode node = loader.load();
|
|
||||||
// temp fix for node.virtual() being broken
|
|
||||||
var virtual = !Files.exists(Path.of("newconfig.yml"));
|
|
||||||
|
|
||||||
// TODO needed or else Configurate breaks
|
public static <T extends GeyserConfig> T load(File file, Class<T> configClass, @Nullable Consumer<CommentedConfigurationNode> transformer) throws IOException {
|
||||||
|
var loader = YamlConfigurationLoader.builder()
|
||||||
|
.file(file)
|
||||||
|
.defaultOptions(options -> InterfaceDefaultOptions.addTo(options
|
||||||
|
.header(HEADER)
|
||||||
|
.serializers(builder -> builder.register(new LowercaseEnumSerializer()))))
|
||||||
|
.build();
|
||||||
|
var node = loader.load();
|
||||||
|
// temp fix for node.virtual() being broken
|
||||||
|
boolean virtual = file.exists();
|
||||||
|
|
||||||
|
// Note for Tim? Needed or else Configurate breaks.
|
||||||
var migrations = ConfigurationTransformation.versionedBuilder()
|
var migrations = ConfigurationTransformation.versionedBuilder()
|
||||||
|
.versionKey("config-version")
|
||||||
// Pre-Configurate
|
// Pre-Configurate
|
||||||
.addVersion(5, ConfigurationTransformation.builder()
|
.addVersion(5, ConfigurationTransformation.builder()
|
||||||
.addAction(NodePath.path("legacyPingPassthrough"), (path, value) -> {
|
.addAction(path("legacy-ping-passthrough"), configClass == GeyserRemoteConfig.class ? remove() : (path, value) -> {
|
||||||
// Invert value
|
// Invert value
|
||||||
value.set(Boolean.FALSE.equals(value.get(boolean.class)));
|
value.set(!value.getBoolean());
|
||||||
return new Object[]{"integratedPingPassthrough"};
|
return new Object[]{"integrated-ping-passthrough"};
|
||||||
})
|
})
|
||||||
.addAction(NodePath.path("remote"), (path, value) ->
|
.addAction(path("remote"), rename("java"))
|
||||||
new Object[]{"java"})
|
.addAction(path("floodgate-key-file"), (path, value) -> {
|
||||||
|
// Elimate any legacy config values
|
||||||
|
if ("public-key.pem".equals(value.getString())) {
|
||||||
|
value.set("key.pem");
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
})
|
||||||
|
.addAction(path("default-locale"), (path, value) -> {
|
||||||
|
if (value.getString() == null) {
|
||||||
|
value.set("system");
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
})
|
||||||
|
.addAction(path("show-cooldown"), (path, value) -> {
|
||||||
|
String s = value.getString();
|
||||||
|
if (s != null) {
|
||||||
|
switch (s) {
|
||||||
|
case "true" -> value.set("title");
|
||||||
|
case "false" -> value.set("disabled");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
})
|
||||||
|
.addAction(path("bedrock", "motd1"), rename("primary-motd"))
|
||||||
|
.addAction(path("bedrock", "motd2"), rename("secondary-motd"))
|
||||||
|
// Legacy config values
|
||||||
|
.addAction(path("emote-offhand-workaround"), remove())
|
||||||
|
.addAction(path("allow-third-party-capes"), remove())
|
||||||
|
.addAction(path("allow-third-party-ears"), remove())
|
||||||
|
.addAction(path("general-thread-pool"), remove())
|
||||||
|
.addAction(path("cache-chunks"), remove())
|
||||||
.build())
|
.build())
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
int currentVersion = migrations.version(node);
|
||||||
migrations.apply(node);
|
migrations.apply(node);
|
||||||
|
int newVersion = migrations.version(node);
|
||||||
|
|
||||||
T config = node.get(configClass);
|
T config = node.get(configClass);
|
||||||
System.out.println(config);
|
|
||||||
|
|
||||||
|
if (virtual || currentVersion != newVersion) {
|
||||||
loader.save(node);
|
loader.save(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (transformer != null) {
|
||||||
|
// Do not let the transformer change the node.
|
||||||
|
transformer.accept(node);
|
||||||
|
config = node.get(configClass);
|
||||||
|
}
|
||||||
|
|
||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
|
@ -31,6 +31,7 @@ import org.geysermc.geyser.api.network.AuthType;
|
|||||||
import org.geysermc.geyser.api.network.BedrockListener;
|
import org.geysermc.geyser.api.network.BedrockListener;
|
||||||
import org.geysermc.geyser.api.network.RemoteServer;
|
import org.geysermc.geyser.api.network.RemoteServer;
|
||||||
import org.geysermc.geyser.network.GameProtocol;
|
import org.geysermc.geyser.network.GameProtocol;
|
||||||
|
import org.geysermc.geyser.util.CooldownUtils;
|
||||||
import org.spongepowered.configurate.interfaces.meta.Exclude;
|
import org.spongepowered.configurate.interfaces.meta.Exclude;
|
||||||
import org.spongepowered.configurate.interfaces.meta.defaults.DefaultBoolean;
|
import org.spongepowered.configurate.interfaces.meta.defaults.DefaultBoolean;
|
||||||
import org.spongepowered.configurate.interfaces.meta.defaults.DefaultNumeric;
|
import org.spongepowered.configurate.interfaces.meta.defaults.DefaultNumeric;
|
||||||
@ -39,8 +40,9 @@ import org.spongepowered.configurate.interfaces.meta.range.NumericRange;
|
|||||||
import org.spongepowered.configurate.objectmapping.ConfigSerializable;
|
import org.spongepowered.configurate.objectmapping.ConfigSerializable;
|
||||||
import org.spongepowered.configurate.objectmapping.meta.Comment;
|
import org.spongepowered.configurate.objectmapping.meta.Comment;
|
||||||
|
|
||||||
import java.nio.file.Path;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
@ConfigSerializable
|
@ConfigSerializable
|
||||||
@ -49,7 +51,9 @@ public interface GeyserConfig {
|
|||||||
|
|
||||||
JavaConfig java();
|
JavaConfig java();
|
||||||
|
|
||||||
Path floodgateKeyPath();
|
// Cannot be type File yet because we want to hide it in plugin instances.
|
||||||
|
@DefaultString("key.pem")
|
||||||
|
String floodgateKeyFile();
|
||||||
|
|
||||||
@Comment("""
|
@Comment("""
|
||||||
For online mode authentication type only.
|
For online mode authentication type only.
|
||||||
@ -108,8 +112,9 @@ public interface GeyserConfig {
|
|||||||
https://cdn.discordapp.com/attachments/613170125696270357/957075682230419466/Screenshot_from_2022-03-25_20-35-08.png
|
https://cdn.discordapp.com/attachments/613170125696270357/957075682230419466/Screenshot_from_2022-03-25_20-35-08.png
|
||||||
This can be disabled by going into Bedrock settings under the accessibility tab and setting "Text Background Opacity" to 0
|
This can be disabled by going into Bedrock settings under the accessibility tab and setting "Text Background Opacity" to 0
|
||||||
This setting can be set to "title", "actionbar" or "false\"""")
|
This setting can be set to "title", "actionbar" or "false\"""")
|
||||||
@DefaultString("title")
|
default CooldownUtils.CooldownType showCooldown() {
|
||||||
String showCooldown();
|
return CooldownUtils.CooldownType.TITLE;
|
||||||
|
}
|
||||||
|
|
||||||
@Comment("Controls if coordinates are shown to players.")
|
@Comment("Controls if coordinates are shown to players.")
|
||||||
@DefaultBoolean(true)
|
@DefaultBoolean(true)
|
||||||
@ -118,9 +123,9 @@ public interface GeyserConfig {
|
|||||||
@Comment("Whether Bedrock players are blocked from performing their scaffolding-style bridging.")
|
@Comment("Whether Bedrock players are blocked from performing their scaffolding-style bridging.")
|
||||||
boolean disableBedrockScaffolding();
|
boolean disableBedrockScaffolding();
|
||||||
|
|
||||||
//@DefaultString("disabled")
|
@Comment("The default locale if we don't have the one the client requested. If set to \"system\", the system's language will be used.")
|
||||||
EmoteOffhandWorkaroundOption emoteOffhandWorkaround();
|
@NonNull
|
||||||
|
@DefaultString("system")
|
||||||
String defaultLocale();
|
String defaultLocale();
|
||||||
|
|
||||||
@Comment("""
|
@Comment("""
|
||||||
@ -207,13 +212,15 @@ public interface GeyserConfig {
|
|||||||
@Override
|
@Override
|
||||||
@Comment("The port that will listen for connections")
|
@Comment("The port that will listen for connections")
|
||||||
@DefaultNumeric(19132)
|
@DefaultNumeric(19132)
|
||||||
|
@NumericRange(from = 0, to = 65535)
|
||||||
int port();
|
int port();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Comment("""
|
@Comment("""
|
||||||
The port to broadcast to Bedrock clients with the MOTD that they should use to connect to the server.
|
The port to broadcast to Bedrock clients with the MOTD that they should use to connect to the server.
|
||||||
DO NOT uncomment and change this unless Geyser runs on a different internal port than the one that is used to connect.""")
|
DO NOT change this unless Geyser runs on a different internal port than the one that is used to connect.""")
|
||||||
@DefaultNumeric(19132)
|
@DefaultNumeric(19132)
|
||||||
|
@NumericRange(from = 0, to = 65535)
|
||||||
int broadcastPort();
|
int broadcastPort();
|
||||||
|
|
||||||
void address(String address);
|
void address(String address);
|
||||||
@ -223,13 +230,21 @@ public interface GeyserConfig {
|
|||||||
void broadcastPort(int broadcastPort);
|
void broadcastPort(int broadcastPort);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@Comment("""
|
||||||
|
The MOTD that will be broadcasted to Minecraft: Bedrock Edition clients. This is irrelevant if "passthrough-motd" is set to true.
|
||||||
|
If either of these are empty, the respective string will default to "Geyser\"""")
|
||||||
@DefaultString("Geyser")
|
@DefaultString("Geyser")
|
||||||
String primaryMotd();
|
String primaryMotd();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@DefaultString("Another Geyser server.") // TODO migrate or change name
|
@DefaultString("Another Geyser server.")
|
||||||
String secondaryMotd();
|
String secondaryMotd();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Comment("The Server Name that will be sent to Minecraft: Bedrock Edition clients. This is visible in both the pause menu and the settings menu.")
|
||||||
|
@DefaultString("Geyser")
|
||||||
|
String serverName();
|
||||||
|
|
||||||
@Comment("""
|
@Comment("""
|
||||||
How much to compress network traffic to the Bedrock client. The higher the number, the more CPU usage used, but
|
How much to compress network traffic to the Bedrock client. The higher the number, the more CPU usage used, but
|
||||||
the smaller the bandwidth used. Does not have any effect below -1 or above 9. Set to -1 to disable.""")
|
the smaller the bandwidth used. Does not have any effect below -1 or above 9. Set to -1 to disable.""")
|
||||||
@ -237,6 +252,9 @@ public interface GeyserConfig {
|
|||||||
@NumericRange(from = -1, to = 9)
|
@NumericRange(from = -1, to = 9)
|
||||||
int compressionLevel();
|
int compressionLevel();
|
||||||
|
|
||||||
|
@Comment("""
|
||||||
|
Whether to enable PROXY protocol or not for clients. You DO NOT WANT this feature unless you run UDP reverse proxy
|
||||||
|
in front of your Geyser instance.""")
|
||||||
@DefaultBoolean
|
@DefaultBoolean
|
||||||
boolean enableProxyProtocol();
|
boolean enableProxyProtocol();
|
||||||
|
|
||||||
@ -245,13 +263,9 @@ public interface GeyserConfig {
|
|||||||
should really only be used when you are not able to use a proper firewall (usually true with shared hosting providers etc.).
|
should really only be used when you are not able to use a proper firewall (usually true with shared hosting providers etc.).
|
||||||
Keeping this list empty means there is no IP address whitelist.
|
Keeping this list empty means there is no IP address whitelist.
|
||||||
IP addresses, subnets, and links to plain text files are supported.""")
|
IP addresses, subnets, and links to plain text files are supported.""")
|
||||||
List<String> proxyProtocolWhitelistedIPs();
|
default List<String> proxyProtocolWhitelistedIps() {
|
||||||
|
return Collections.emptyList();
|
||||||
// /**
|
}
|
||||||
// * @return Unmodifiable list of {@link CIDRMatcher}s from {@link #proxyProtocolWhitelistedIPs()}
|
|
||||||
// */
|
|
||||||
// @Exclude
|
|
||||||
// List<CIDRMatcher> whitelistedIPsMatchers();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ConfigSerializable
|
@ConfigSerializable
|
||||||
@ -270,6 +284,8 @@ public interface GeyserConfig {
|
|||||||
return AuthType.ONLINE;
|
return AuthType.ONLINE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void authType(AuthType authType);
|
||||||
|
|
||||||
@Comment("""
|
@Comment("""
|
||||||
Whether to enable PROXY protocol or not while connecting to the server.
|
Whether to enable PROXY protocol or not while connecting to the server.
|
||||||
This is useful only when:
|
This is useful only when:
|
||||||
@ -297,17 +313,16 @@ public interface GeyserConfig {
|
|||||||
default boolean resolveSrv() {
|
default boolean resolveSrv() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void authType(AuthType authType);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ConfigSerializable
|
@ConfigSerializable
|
||||||
interface MetricsInfo {
|
interface MetricsInfo {
|
||||||
|
@Comment("If metrics should be enabled")
|
||||||
@DefaultBoolean(true)
|
@DefaultBoolean(true)
|
||||||
boolean enabled();
|
boolean enabled();
|
||||||
|
|
||||||
default UUID uniqueId() { //TODO rename?
|
@Comment("UUID of server. Don't change!")
|
||||||
|
default UUID uuid() { //TODO rename?
|
||||||
return UUID.randomUUID();
|
return UUID.randomUUID();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -333,7 +348,15 @@ public interface GeyserConfig {
|
|||||||
int mtu();
|
int mtu();
|
||||||
|
|
||||||
@Comment("Do not change!")
|
@Comment("Do not change!")
|
||||||
default int version() {
|
default int configVersion() {
|
||||||
return Constants.CONFIG_VERSION;
|
return Constants.CONFIG_VERSION;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Exclude
|
||||||
|
default Optional<GeyserPluginConfig> asPluginConfig() {
|
||||||
|
if (this instanceof GeyserPluginConfig config) {
|
||||||
|
return Optional.of(config);
|
||||||
|
}
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -32,6 +32,8 @@ import org.spongepowered.configurate.interfaces.meta.defaults.DefaultBoolean;
|
|||||||
import org.spongepowered.configurate.objectmapping.ConfigSerializable;
|
import org.spongepowered.configurate.objectmapping.ConfigSerializable;
|
||||||
import org.spongepowered.configurate.objectmapping.meta.Comment;
|
import org.spongepowered.configurate.objectmapping.meta.Comment;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
@ConfigSerializable
|
@ConfigSerializable
|
||||||
public interface GeyserPluginConfig extends GeyserConfig {
|
public interface GeyserPluginConfig extends GeyserConfig {
|
||||||
@Override
|
@Override
|
||||||
@ -89,6 +91,10 @@ public interface GeyserPluginConfig extends GeyserConfig {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Hidden
|
||||||
|
String floodgateKeyFile();
|
||||||
|
|
||||||
@Comment("""
|
@Comment("""
|
||||||
Use server API methods to determine the Java server's MOTD and ping passthrough.
|
Use server API methods to determine the Java server's MOTD and ping passthrough.
|
||||||
There is no need to disable this unless your MOTD or player count does not appear properly.""")
|
There is no need to disable this unless your MOTD or player count does not appear properly.""")
|
||||||
|
@ -25,10 +25,9 @@
|
|||||||
|
|
||||||
package org.geysermc.geyser.configuration;
|
package org.geysermc.geyser.configuration;
|
||||||
|
|
||||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
|
||||||
import org.geysermc.geyser.api.network.AuthType;
|
|
||||||
import org.spongepowered.configurate.interfaces.meta.defaults.DefaultNumeric;
|
import org.spongepowered.configurate.interfaces.meta.defaults.DefaultNumeric;
|
||||||
import org.spongepowered.configurate.interfaces.meta.defaults.DefaultString;
|
import org.spongepowered.configurate.interfaces.meta.defaults.DefaultString;
|
||||||
|
import org.spongepowered.configurate.interfaces.meta.range.NumericRange;
|
||||||
import org.spongepowered.configurate.objectmapping.ConfigSerializable;
|
import org.spongepowered.configurate.objectmapping.ConfigSerializable;
|
||||||
import org.spongepowered.configurate.objectmapping.meta.Comment;
|
import org.spongepowered.configurate.objectmapping.meta.Comment;
|
||||||
|
|
||||||
@ -37,12 +36,17 @@ import org.spongepowered.configurate.objectmapping.meta.Comment;
|
|||||||
*/
|
*/
|
||||||
@ConfigSerializable
|
@ConfigSerializable
|
||||||
public interface GeyserRemoteConfig extends GeyserConfig {
|
public interface GeyserRemoteConfig extends GeyserConfig {
|
||||||
// @Override // For config placement
|
|
||||||
// BedrockConfig bedrock();
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
RemoteConfig java();
|
RemoteConfig java();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Comment("""
|
||||||
|
Floodgate uses encryption to ensure use from authorized sources.
|
||||||
|
This should point to the public key generated by Floodgate (BungeeCord, Spigot or Velocity)
|
||||||
|
You can ignore this when not using Floodgate.
|
||||||
|
If you're using a plugin version of Floodgate on the same server, the key will automatically be picked up from Floodgate.""")
|
||||||
|
String floodgateKeyFile();
|
||||||
|
|
||||||
@ConfigSerializable
|
@ConfigSerializable
|
||||||
interface RemoteConfig extends JavaConfig {
|
interface RemoteConfig extends JavaConfig {
|
||||||
@Override
|
@Override
|
||||||
@ -53,13 +57,9 @@ public interface GeyserRemoteConfig extends GeyserConfig {
|
|||||||
@Override
|
@Override
|
||||||
@Comment("The port of the Java Edition server.")
|
@Comment("The port of the Java Edition server.")
|
||||||
@DefaultNumeric(25565)
|
@DefaultNumeric(25565)
|
||||||
|
@NumericRange(from = 0, to = 65535)
|
||||||
int port();
|
int port();
|
||||||
|
|
||||||
@Override // For config placement
|
|
||||||
default @NonNull AuthType authType() {
|
|
||||||
return JavaConfig.super.authType();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Comment("""
|
@Comment("""
|
||||||
Forward the hostname that the Bedrock client used to connect over to the Java server
|
Forward the hostname that the Bedrock client used to connect over to the Java server
|
||||||
|
@ -0,0 +1,55 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2024 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.geyser.configuration;
|
||||||
|
|
||||||
|
import io.leangen.geantyref.TypeToken;
|
||||||
|
import org.spongepowered.configurate.serialize.ScalarSerializer;
|
||||||
|
import org.spongepowered.configurate.serialize.Scalars;
|
||||||
|
import org.spongepowered.configurate.serialize.SerializationException;
|
||||||
|
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ensures enum values are written to lowercase. {@link Scalars#ENUM} will read enum values
|
||||||
|
* in any case.
|
||||||
|
*/
|
||||||
|
final class LowercaseEnumSerializer extends ScalarSerializer<Enum<?>> {
|
||||||
|
LowercaseEnumSerializer() {
|
||||||
|
super(new TypeToken<Enum<?>>() {});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Enum<?> deserialize(Type type, Object obj) throws SerializationException {
|
||||||
|
return Scalars.ENUM.deserialize(type, obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Object serialize(Enum<?> item, Predicate<Class<?>> typeSupported) {
|
||||||
|
return item.name().toLowerCase(Locale.ROOT);
|
||||||
|
}
|
||||||
|
}
|
@ -25,13 +25,12 @@
|
|||||||
|
|
||||||
package org.geysermc.geyser.dump;
|
package org.geysermc.geyser.dump;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
|
||||||
import com.google.common.hash.Hashing;
|
import com.google.common.hash.Hashing;
|
||||||
import com.google.common.io.ByteSource;
|
import com.google.common.io.ByteSource;
|
||||||
import com.google.common.io.Files;
|
import com.google.common.io.Files;
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
import com.google.gson.JsonParser;
|
import com.google.gson.JsonParser;
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
import it.unimi.dsi.fastutil.objects.Object2IntMap;
|
import it.unimi.dsi.fastutil.objects.Object2IntMap;
|
||||||
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
|
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
@ -41,7 +40,7 @@ import org.geysermc.floodgate.util.FloodgateInfoHolder;
|
|||||||
import org.geysermc.geyser.GeyserImpl;
|
import org.geysermc.geyser.GeyserImpl;
|
||||||
import org.geysermc.geyser.api.GeyserApi;
|
import org.geysermc.geyser.api.GeyserApi;
|
||||||
import org.geysermc.geyser.api.extension.Extension;
|
import org.geysermc.geyser.api.extension.Extension;
|
||||||
import org.geysermc.geyser.configuration.GeyserConfiguration;
|
import org.geysermc.geyser.configuration.GeyserConfig;
|
||||||
import org.geysermc.geyser.network.GameProtocol;
|
import org.geysermc.geyser.network.GameProtocol;
|
||||||
import org.geysermc.geyser.session.GeyserSession;
|
import org.geysermc.geyser.session.GeyserSession;
|
||||||
import org.geysermc.geyser.text.AsteriskSerializer;
|
import org.geysermc.geyser.text.AsteriskSerializer;
|
||||||
@ -57,12 +56,16 @@ import java.net.InetSocketAddress;
|
|||||||
import java.net.Socket;
|
import java.net.Socket;
|
||||||
import java.net.UnknownHostException;
|
import java.net.UnknownHostException;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
import java.util.*;
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Properties;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
public class DumpInfo {
|
public class DumpInfo {
|
||||||
@JsonIgnore
|
|
||||||
private static final long MEGABYTE = 1024L * 1024L;
|
private static final long MEGABYTE = 1024L * 1024L;
|
||||||
|
|
||||||
private final DumpInfo.VersionInfo versionInfo;
|
private final DumpInfo.VersionInfo versionInfo;
|
||||||
@ -71,7 +74,7 @@ public class DumpInfo {
|
|||||||
private final Locale systemLocale;
|
private final Locale systemLocale;
|
||||||
private final String systemEncoding;
|
private final String systemEncoding;
|
||||||
private final GitInfo gitInfo;
|
private final GitInfo gitInfo;
|
||||||
private final GeyserConfiguration config;
|
private final GeyserConfig config;
|
||||||
private final Floodgate floodgate;
|
private final Floodgate floodgate;
|
||||||
private final Object2IntMap<DeviceOs> userPlatforms;
|
private final Object2IntMap<DeviceOs> userPlatforms;
|
||||||
private final int connectionAttempts;
|
private final int connectionAttempts;
|
||||||
@ -92,7 +95,7 @@ public class DumpInfo {
|
|||||||
|
|
||||||
this.gitInfo = new GitInfo(GeyserImpl.BUILD_NUMBER, GeyserImpl.COMMIT.substring(0, 7), GeyserImpl.COMMIT, GeyserImpl.BRANCH, GeyserImpl.REPOSITORY);
|
this.gitInfo = new GitInfo(GeyserImpl.BUILD_NUMBER, GeyserImpl.COMMIT.substring(0, 7), GeyserImpl.COMMIT, GeyserImpl.BRANCH, GeyserImpl.REPOSITORY);
|
||||||
|
|
||||||
this.config = GeyserImpl.getInstance().getConfig();
|
this.config = GeyserImpl.getInstance().config();
|
||||||
this.floodgate = new Floodgate();
|
this.floodgate = new Floodgate();
|
||||||
|
|
||||||
String md5Hash = "unknown";
|
String md5Hash = "unknown";
|
||||||
@ -108,7 +111,7 @@ public class DumpInfo {
|
|||||||
//noinspection UnstableApiUsage
|
//noinspection UnstableApiUsage
|
||||||
sha256Hash = byteSource.hash(Hashing.sha256()).toString();
|
sha256Hash = byteSource.hash(Hashing.sha256()).toString();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
if (GeyserImpl.getInstance().getConfig().isDebugMode()) {
|
if (GeyserImpl.getInstance().config().debugMode()) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -280,7 +283,7 @@ public class DumpInfo {
|
|||||||
public record ExtensionInfo(boolean enabled, String name, String version, String apiVersion, String main, List<String> authors) {
|
public record ExtensionInfo(boolean enabled, String name, String version, String apiVersion, String main, List<String> authors) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public record GitInfo(String buildNumber, @JsonProperty("git.commit.id.abbrev") String commitHashAbbrev, @JsonProperty("git.commit.id") String commitHash,
|
public record GitInfo(String buildNumber, @SerializedName("git.commit.id.abbrev") String commitHashAbbrev, @SerializedName("git.commit.id") String commitHash,
|
||||||
@JsonProperty("git.branch") String branchName, @JsonProperty("git.remote.origin.url") String originUrl) {
|
@SerializedName("git.branch") String branchName, @SerializedName("git.remote.origin.url") String originUrl) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -71,7 +71,7 @@ public record EntityDefinition<T extends Entity>(EntityFactory<T> factory, Entit
|
|||||||
|
|
||||||
if (translator.acceptedType() != metadata.getType()) {
|
if (translator.acceptedType() != metadata.getType()) {
|
||||||
GeyserImpl.getInstance().getLogger().warning("Metadata ID " + metadata.getId() + " was received with type " + metadata.getType() + " but we expected " + translator.acceptedType() + " for " + entity.getDefinition().entityType());
|
GeyserImpl.getInstance().getLogger().warning("Metadata ID " + metadata.getId() + " was received with type " + metadata.getType() + " but we expected " + translator.acceptedType() + " for " + entity.getDefinition().entityType());
|
||||||
if (GeyserImpl.getInstance().getConfig().isDebugMode()) {
|
if (GeyserImpl.getInstance().config().debugMode()) {
|
||||||
GeyserImpl.getInstance().getLogger().debug(metadata.toString());
|
GeyserImpl.getInstance().getLogger().debug(metadata.toString());
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
@ -185,7 +185,7 @@ public class Entity implements GeyserEntity {
|
|||||||
|
|
||||||
flagsDirty = false;
|
flagsDirty = false;
|
||||||
|
|
||||||
if (session.getGeyser().getConfig().isDebugMode() && PRINT_ENTITY_SPAWN_DEBUG) {
|
if (session.getGeyser().config().debugMode() && PRINT_ENTITY_SPAWN_DEBUG) {
|
||||||
EntityType type = definition.entityType();
|
EntityType type = definition.entityType();
|
||||||
String name = type != null ? type.name() : getClass().getSimpleName();
|
String name = type != null ? type.name() : getClass().getSimpleName();
|
||||||
session.getGeyser().getLogger().debug("Spawned entity " + name + " at location " + position + " with id " + geyserId + " (java id " + entityId + ")");
|
session.getGeyser().getLogger().debug("Spawned entity " + name + " at location " + position + " with id " + geyserId + " (java id " + entityId + ")");
|
||||||
|
@ -342,7 +342,7 @@ public final class ClickPlan {
|
|||||||
} else if (action.click.actionType == ContainerActionType.MOVE_TO_HOTBAR_SLOT) {
|
} else if (action.click.actionType == ContainerActionType.MOVE_TO_HOTBAR_SLOT) {
|
||||||
stateIdIncrements = 1;
|
stateIdIncrements = 1;
|
||||||
} else {
|
} else {
|
||||||
if (session.getGeyser().getConfig().isDebugMode()) {
|
if (session.getGeyser().config().debugMode()) {
|
||||||
session.getGeyser().getLogger().debug("Not sure how to handle state ID hack in crafting table: " + plan);
|
session.getGeyser().getLogger().debug("Not sure how to handle state ID hack in crafting table: " + plan);
|
||||||
}
|
}
|
||||||
stateIdIncrements = 1;
|
stateIdIncrements = 1;
|
||||||
|
@ -90,7 +90,7 @@ public class UpstreamPacketHandler extends LoggingPacketHandler {
|
|||||||
super(geyser, session);
|
super(geyser, session);
|
||||||
|
|
||||||
ZlibCompression compression = new ZlibCompression(Zlib.RAW);
|
ZlibCompression compression = new ZlibCompression(Zlib.RAW);
|
||||||
compression.setLevel(this.geyser.getConfig().getBedrock().getCompressionLevel());
|
compression.setLevel(this.geyser.config().bedrock().compressionLevel());
|
||||||
this.compressionStrategy = new SimpleCompressionStrategy(compression);
|
this.compressionStrategy = new SimpleCompressionStrategy(compression);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -211,7 +211,7 @@ public class UpstreamPacketHandler extends LoggingPacketHandler {
|
|||||||
header.uuid().toString(), header.version().toString(), codec.size(), pack.contentKey(),
|
header.uuid().toString(), header.version().toString(), codec.size(), pack.contentKey(),
|
||||||
"", header.uuid().toString(), false, false));
|
"", header.uuid().toString(), false, false));
|
||||||
}
|
}
|
||||||
resourcePacksInfo.setForcedToAccept(GeyserImpl.getInstance().getConfig().isForceResourcePacks());
|
resourcePacksInfo.setForcedToAccept(GeyserImpl.getInstance().config().forceResourcePacks());
|
||||||
session.sendUpstreamPacket(resourcePacksInfo);
|
session.sendUpstreamPacket(resourcePacksInfo);
|
||||||
|
|
||||||
GeyserLocale.loadGeyserLocale(session.locale());
|
GeyserLocale.loadGeyserLocale(session.locale());
|
||||||
@ -222,7 +222,7 @@ public class UpstreamPacketHandler extends LoggingPacketHandler {
|
|||||||
public PacketSignal handle(ResourcePackClientResponsePacket packet) {
|
public PacketSignal handle(ResourcePackClientResponsePacket packet) {
|
||||||
switch (packet.getStatus()) {
|
switch (packet.getStatus()) {
|
||||||
case COMPLETED:
|
case COMPLETED:
|
||||||
if (geyser.getConfig().getRemote().authType() != AuthType.ONLINE) {
|
if (geyser.config().java().authType() != AuthType.ONLINE) {
|
||||||
session.authenticate(session.getAuthData().name());
|
session.authenticate(session.getAuthData().name());
|
||||||
} else if (!couldLoginUserByName(session.getAuthData().name())) {
|
} else if (!couldLoginUserByName(session.getAuthData().name())) {
|
||||||
// We must spawn the white world
|
// We must spawn the white world
|
||||||
@ -247,7 +247,7 @@ public class UpstreamPacketHandler extends LoggingPacketHandler {
|
|||||||
stackPacket.getResourcePacks().add(new ResourcePackStackPacket.Entry(header.uuid().toString(), header.version().toString(), ""));
|
stackPacket.getResourcePacks().add(new ResourcePackStackPacket.Entry(header.uuid().toString(), header.version().toString(), ""));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GeyserImpl.getInstance().getConfig().isAddNonBedrockItems()) {
|
if (GeyserImpl.getInstance().config().addNonBedrockItems()) {
|
||||||
// Allow custom items to work
|
// Allow custom items to work
|
||||||
stackPacket.getExperiments().add(new ExperimentData("data_driven_items", true));
|
stackPacket.getExperiments().add(new ExperimentData("data_driven_items", true));
|
||||||
}
|
}
|
||||||
@ -273,7 +273,7 @@ public class UpstreamPacketHandler extends LoggingPacketHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean couldLoginUserByName(String bedrockUsername) {
|
private boolean couldLoginUserByName(String bedrockUsername) {
|
||||||
if (geyser.getConfig().getSavedUserLogins().contains(bedrockUsername)) {
|
if (geyser.config().savedUserLogins().contains(bedrockUsername)) {
|
||||||
String refreshToken = geyser.refreshTokenFor(bedrockUsername);
|
String refreshToken = geyser.refreshTokenFor(bedrockUsername);
|
||||||
if (refreshToken != null) {
|
if (refreshToken != null) {
|
||||||
geyser.getLogger().info(GeyserLocale.getLocaleStringLog("geyser.auth.stored_credentials", session.getAuthData().name()));
|
geyser.getLogger().info(GeyserLocale.getLocaleStringLog("geyser.auth.stored_credentials", session.getAuthData().name()));
|
||||||
|
@ -27,7 +27,7 @@ package org.geysermc.geyser.network.netty;
|
|||||||
|
|
||||||
import io.netty.channel.ChannelFuture;
|
import io.netty.channel.ChannelFuture;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import org.geysermc.geyser.GeyserBootstrap;
|
import org.geysermc.geyser.GeyserPluginBootstrap;
|
||||||
|
|
||||||
import java.net.SocketAddress;
|
import java.net.SocketAddress;
|
||||||
|
|
||||||
@ -49,8 +49,8 @@ public abstract class GeyserInjector {
|
|||||||
/**
|
/**
|
||||||
* @param bootstrap the bootstrap of the Geyser instance.
|
* @param bootstrap the bootstrap of the Geyser instance.
|
||||||
*/
|
*/
|
||||||
public void initializeLocalChannel(GeyserBootstrap bootstrap) {
|
public void initializeLocalChannel(GeyserPluginBootstrap bootstrap) {
|
||||||
if (!bootstrap.getGeyserConfig().isUseDirectConnection()) {
|
if (!bootstrap.config().useDirectConnection()) {
|
||||||
bootstrap.getGeyserLogger().debug("Disabling direct injection!");
|
bootstrap.getGeyserLogger().debug("Disabling direct injection!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -71,9 +71,9 @@ public abstract class GeyserInjector {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The method to implement that is called by {@link #initializeLocalChannel(GeyserBootstrap)} wrapped around a try/catch.
|
* The method to implement that is called by {@link #initializeLocalChannel(GeyserPluginBootstrap)} wrapped around a try/catch.
|
||||||
*/
|
*/
|
||||||
protected abstract void initializeLocalChannel0(GeyserBootstrap bootstrap) throws Exception;
|
protected abstract void initializeLocalChannel0(GeyserPluginBootstrap bootstrap) throws Exception;
|
||||||
|
|
||||||
public void shutdown() {
|
public void shutdown() {
|
||||||
if (localChannel != null && localChannel.channel().isOpen()) {
|
if (localChannel != null && localChannel.channel().isOpen()) {
|
||||||
|
@ -53,7 +53,7 @@ import org.cloudburstmc.protocol.bedrock.BedrockPong;
|
|||||||
import org.geysermc.geyser.GeyserImpl;
|
import org.geysermc.geyser.GeyserImpl;
|
||||||
import org.geysermc.geyser.api.event.connection.ConnectionRequestEvent;
|
import org.geysermc.geyser.api.event.connection.ConnectionRequestEvent;
|
||||||
import org.geysermc.geyser.command.defaults.ConnectionTestCommand;
|
import org.geysermc.geyser.command.defaults.ConnectionTestCommand;
|
||||||
import org.geysermc.geyser.configuration.GeyserConfiguration;
|
import org.geysermc.geyser.configuration.GeyserConfig;
|
||||||
import org.geysermc.geyser.event.type.GeyserBedrockPingEventImpl;
|
import org.geysermc.geyser.event.type.GeyserBedrockPingEventImpl;
|
||||||
import org.geysermc.geyser.network.CIDRMatcher;
|
import org.geysermc.geyser.network.CIDRMatcher;
|
||||||
import org.geysermc.geyser.network.GameProtocol;
|
import org.geysermc.geyser.network.GameProtocol;
|
||||||
@ -66,14 +66,18 @@ import org.geysermc.geyser.ping.IGeyserPingPassthrough;
|
|||||||
import org.geysermc.geyser.skin.SkinProvider;
|
import org.geysermc.geyser.skin.SkinProvider;
|
||||||
import org.geysermc.geyser.text.GeyserLocale;
|
import org.geysermc.geyser.text.GeyserLocale;
|
||||||
import org.geysermc.geyser.translator.text.MessageTranslator;
|
import org.geysermc.geyser.translator.text.MessageTranslator;
|
||||||
|
import org.geysermc.geyser.util.WebUtils;
|
||||||
|
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.function.IntFunction;
|
import java.util.function.IntFunction;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import static org.cloudburstmc.netty.channel.raknet.RakConstants.DEFAULT_GLOBAL_PACKET_LIMIT;
|
import static org.cloudburstmc.netty.channel.raknet.RakConstants.DEFAULT_GLOBAL_PACKET_LIMIT;
|
||||||
import static org.cloudburstmc.netty.channel.raknet.RakConstants.DEFAULT_PACKET_LIMIT;
|
import static org.cloudburstmc.netty.channel.raknet.RakConstants.DEFAULT_PACKET_LIMIT;
|
||||||
@ -135,7 +139,7 @@ public final class GeyserServer {
|
|||||||
this.listenCount = 1;
|
this.listenCount = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.geyser.getConfig().getBedrock().isEnableProxyProtocol()) {
|
if (this.geyser.config().bedrock().enableProxyProtocol()) {
|
||||||
this.proxiedAddresses = ExpiringMap.builder()
|
this.proxiedAddresses = ExpiringMap.builder()
|
||||||
.expiration(30 + 1, TimeUnit.MINUTES)
|
.expiration(30 + 1, TimeUnit.MINUTES)
|
||||||
.expirationPolicy(ExpirationPolicy.ACCESSED).build();
|
.expirationPolicy(ExpirationPolicy.ACCESSED).build();
|
||||||
@ -144,11 +148,11 @@ public final class GeyserServer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// It's set to 0 only if no system property or manual config value was set
|
// It's set to 0 only if no system property or manual config value was set
|
||||||
if (geyser.getConfig().getBedrock().broadcastPort() == 0) {
|
if (geyser.config().bedrock().broadcastPort() == 0) {
|
||||||
geyser.getConfig().getBedrock().setBroadcastPort(geyser.getConfig().getBedrock().port());
|
geyser.config().bedrock().broadcastPort(geyser.config().bedrock().port());
|
||||||
}
|
}
|
||||||
|
|
||||||
this.broadcastPort = geyser.getConfig().getBedrock().broadcastPort();
|
this.broadcastPort = geyser.config().bedrock().broadcastPort();
|
||||||
}
|
}
|
||||||
|
|
||||||
public CompletableFuture<Void> bind(InetSocketAddress address) {
|
public CompletableFuture<Void> bind(InetSocketAddress address) {
|
||||||
@ -170,12 +174,12 @@ public final class GeyserServer {
|
|||||||
.addAfter(RakServerOfflineHandler.NAME, RakPingHandler.NAME, new RakPingHandler(this));
|
.addAfter(RakServerOfflineHandler.NAME, RakPingHandler.NAME, new RakPingHandler(this));
|
||||||
|
|
||||||
// Add proxy handler
|
// Add proxy handler
|
||||||
boolean isProxyProtocol = this.geyser.getConfig().getBedrock().isEnableProxyProtocol();
|
boolean isProxyProtocol = this.geyser.config().bedrock().enableProxyProtocol();
|
||||||
if (isProxyProtocol) {
|
if (isProxyProtocol) {
|
||||||
channel.pipeline().addFirst("proxy-protocol-decoder", new ProxyServerHandler());
|
channel.pipeline().addFirst("proxy-protocol-decoder", new ProxyServerHandler());
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean isWhitelistedProxyProtocol = isProxyProtocol && !this.geyser.getConfig().getBedrock().getProxyProtocolWhitelistedIPs().isEmpty();
|
boolean isWhitelistedProxyProtocol = isProxyProtocol && !this.geyser.config().bedrock().proxyProtocolWhitelistedIps().isEmpty();
|
||||||
if (Boolean.parseBoolean(System.getProperty("Geyser.RakRateLimitingDisabled", "false")) || isWhitelistedProxyProtocol) {
|
if (Boolean.parseBoolean(System.getProperty("Geyser.RakRateLimitingDisabled", "false")) || isWhitelistedProxyProtocol) {
|
||||||
// We would already block any non-whitelisted IP addresses in onConnectionRequest so we can remove the rate limiter
|
// We would already block any non-whitelisted IP addresses in onConnectionRequest so we can remove the rate limiter
|
||||||
channel.pipeline().remove(RakServerRateLimiter.NAME);
|
channel.pipeline().remove(RakServerRateLimiter.NAME);
|
||||||
@ -205,7 +209,7 @@ public final class GeyserServer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private ServerBootstrap createBootstrap() {
|
private ServerBootstrap createBootstrap() {
|
||||||
if (this.geyser.getConfig().isDebugMode()) {
|
if (this.geyser.config().debugMode()) {
|
||||||
this.geyser.getLogger().debug("EventLoop type: " + TRANSPORT.datagramChannel());
|
this.geyser.getLogger().debug("EventLoop type: " + TRANSPORT.datagramChannel());
|
||||||
if (TRANSPORT.datagramChannel() == NioDatagramChannel.class) {
|
if (TRANSPORT.datagramChannel() == NioDatagramChannel.class) {
|
||||||
if (System.getProperties().contains("disableNativeEventLoop")) {
|
if (System.getProperties().contains("disableNativeEventLoop")) {
|
||||||
@ -220,7 +224,7 @@ public final class GeyserServer {
|
|||||||
|
|
||||||
GeyserServerInitializer serverInitializer = new GeyserServerInitializer(this.geyser);
|
GeyserServerInitializer serverInitializer = new GeyserServerInitializer(this.geyser);
|
||||||
playerGroup = serverInitializer.getEventLoopGroup();
|
playerGroup = serverInitializer.getEventLoopGroup();
|
||||||
this.geyser.getLogger().debug("Setting MTU to " + this.geyser.getConfig().getMtu());
|
this.geyser.getLogger().debug("Setting MTU to " + this.geyser.config().mtu());
|
||||||
|
|
||||||
int rakPacketLimit = positivePropOrDefault("Geyser.RakPacketLimit", DEFAULT_PACKET_LIMIT);
|
int rakPacketLimit = positivePropOrDefault("Geyser.RakPacketLimit", DEFAULT_PACKET_LIMIT);
|
||||||
this.geyser.getLogger().debug("Setting RakNet packet limit to " + rakPacketLimit);
|
this.geyser.getLogger().debug("Setting RakNet packet limit to " + rakPacketLimit);
|
||||||
@ -235,7 +239,7 @@ public final class GeyserServer {
|
|||||||
.channelFactory(RakChannelFactory.server(TRANSPORT.datagramChannel()))
|
.channelFactory(RakChannelFactory.server(TRANSPORT.datagramChannel()))
|
||||||
.group(group, childGroup)
|
.group(group, childGroup)
|
||||||
.option(RakChannelOption.RAK_HANDLE_PING, true)
|
.option(RakChannelOption.RAK_HANDLE_PING, true)
|
||||||
.option(RakChannelOption.RAK_MAX_MTU, this.geyser.getConfig().getMtu())
|
.option(RakChannelOption.RAK_MAX_MTU, this.geyser.config().mtu())
|
||||||
.option(RakChannelOption.RAK_PACKET_LIMIT, rakPacketLimit)
|
.option(RakChannelOption.RAK_PACKET_LIMIT, rakPacketLimit)
|
||||||
.option(RakChannelOption.RAK_GLOBAL_PACKET_LIMIT, rakGlobalPacketLimit)
|
.option(RakChannelOption.RAK_GLOBAL_PACKET_LIMIT, rakGlobalPacketLimit)
|
||||||
.option(RakChannelOption.RAK_SEND_COOKIE, rakSendCookie)
|
.option(RakChannelOption.RAK_SEND_COOKIE, rakSendCookie)
|
||||||
@ -243,10 +247,10 @@ public final class GeyserServer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean onConnectionRequest(InetSocketAddress inetSocketAddress) {
|
public boolean onConnectionRequest(InetSocketAddress inetSocketAddress) {
|
||||||
List<String> allowedProxyIPs = geyser.getConfig().getBedrock().getProxyProtocolWhitelistedIPs();
|
List<String> allowedProxyIPs = geyser.config().bedrock().proxyProtocolWhitelistedIps();
|
||||||
if (geyser.getConfig().getBedrock().isEnableProxyProtocol() && !allowedProxyIPs.isEmpty()) {
|
if (geyser.config().bedrock().enableProxyProtocol() && !allowedProxyIPs.isEmpty()) {
|
||||||
boolean isWhitelistedIP = false;
|
boolean isWhitelistedIP = false;
|
||||||
for (CIDRMatcher matcher : geyser.getConfig().getBedrock().getWhitelistedIPsMatchers()) {
|
for (CIDRMatcher matcher : getWhitelistedIPsMatchers()) {
|
||||||
if (matcher.matches(inetSocketAddress.getAddress())) {
|
if (matcher.matches(inetSocketAddress.getAddress())) {
|
||||||
isWhitelistedIP = true;
|
isWhitelistedIP = true;
|
||||||
break;
|
break;
|
||||||
@ -260,8 +264,8 @@ public final class GeyserServer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
String ip;
|
String ip;
|
||||||
if (geyser.getConfig().isLogPlayerIpAddresses()) {
|
if (geyser.config().logPlayerIpAddresses()) {
|
||||||
if (geyser.getConfig().getBedrock().isEnableProxyProtocol()) {
|
if (geyser.config().bedrock().enableProxyProtocol()) {
|
||||||
ip = this.proxiedAddresses.getOrDefault(inetSocketAddress, inetSocketAddress).toString();
|
ip = this.proxiedAddresses.getOrDefault(inetSocketAddress, inetSocketAddress).toString();
|
||||||
} else {
|
} else {
|
||||||
ip = inetSocketAddress.toString();
|
ip = inetSocketAddress.toString();
|
||||||
@ -287,10 +291,10 @@ public final class GeyserServer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public BedrockPong onQuery(Channel channel, InetSocketAddress inetSocketAddress) {
|
public BedrockPong onQuery(Channel channel, InetSocketAddress inetSocketAddress) {
|
||||||
if (geyser.getConfig().isDebugMode() && PRINT_DEBUG_PINGS) {
|
if (geyser.config().debugMode() && PRINT_DEBUG_PINGS) {
|
||||||
String ip;
|
String ip;
|
||||||
if (geyser.getConfig().isLogPlayerIpAddresses()) {
|
if (geyser.config().logPlayerIpAddresses()) {
|
||||||
if (geyser.getConfig().getBedrock().isEnableProxyProtocol()) {
|
if (geyser.config().bedrock().enableProxyProtocol()) {
|
||||||
ip = this.proxiedAddresses.getOrDefault(inetSocketAddress, inetSocketAddress).toString();
|
ip = this.proxiedAddresses.getOrDefault(inetSocketAddress, inetSocketAddress).toString();
|
||||||
} else {
|
} else {
|
||||||
ip = inetSocketAddress.toString();
|
ip = inetSocketAddress.toString();
|
||||||
@ -301,10 +305,10 @@ public final class GeyserServer {
|
|||||||
geyser.getLogger().debug(GeyserLocale.getLocaleStringLog("geyser.network.pinged", ip));
|
geyser.getLogger().debug(GeyserLocale.getLocaleStringLog("geyser.network.pinged", ip));
|
||||||
}
|
}
|
||||||
|
|
||||||
GeyserConfiguration config = geyser.getConfig();
|
GeyserConfig config = geyser.config();
|
||||||
|
|
||||||
GeyserPingInfo pingInfo = null;
|
GeyserPingInfo pingInfo = null;
|
||||||
if (config.isPassthroughMotd() || config.isPassthroughPlayerCounts()) {
|
if (config.passthroughMotd() || config.passthroughPlayerCounts()) {
|
||||||
IGeyserPingPassthrough pingPassthrough = geyser.getBootstrap().getGeyserPingPassthrough();
|
IGeyserPingPassthrough pingPassthrough = geyser.getBootstrap().getGeyserPingPassthrough();
|
||||||
if (pingPassthrough != null) {
|
if (pingPassthrough != null) {
|
||||||
pingInfo = pingPassthrough.getPingInformation(inetSocketAddress);
|
pingInfo = pingPassthrough.getPingInformation(inetSocketAddress);
|
||||||
@ -321,25 +325,25 @@ public final class GeyserServer {
|
|||||||
.ipv6Port(this.broadcastPort)
|
.ipv6Port(this.broadcastPort)
|
||||||
.serverId(channel.config().getOption(RakChannelOption.RAK_GUID));
|
.serverId(channel.config().getOption(RakChannelOption.RAK_GUID));
|
||||||
|
|
||||||
if (config.isPassthroughMotd() && pingInfo != null && pingInfo.getDescription() != null) {
|
if (config.passthroughMotd() && pingInfo != null && pingInfo.getDescription() != null) {
|
||||||
String[] motd = MessageTranslator.convertMessageLenient(pingInfo.getDescription()).split("\n");
|
String[] motd = MessageTranslator.convertMessageLenient(pingInfo.getDescription()).split("\n");
|
||||||
String mainMotd = (motd.length > 0) ? motd[0] : config.getBedrock().primaryMotd(); // First line of the motd.
|
String mainMotd = (motd.length > 0) ? motd[0] : config.bedrock().primaryMotd(); // First line of the motd.
|
||||||
String subMotd = (motd.length > 1) ? motd[1] : config.getBedrock().secondaryMotd(); // Second line of the motd if present, otherwise default.
|
String subMotd = (motd.length > 1) ? motd[1] : config.bedrock().secondaryMotd(); // Second line of the motd if present, otherwise default.
|
||||||
|
|
||||||
pong.motd(mainMotd.trim());
|
pong.motd(mainMotd.trim());
|
||||||
pong.subMotd(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.subMotd(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.
|
||||||
} else {
|
} else {
|
||||||
pong.motd(config.getBedrock().primaryMotd());
|
pong.motd(config.bedrock().primaryMotd());
|
||||||
pong.subMotd(config.getBedrock().secondaryMotd());
|
pong.subMotd(config.bedrock().secondaryMotd());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Placed here to prevent overriding values set in the ping event.
|
// Placed here to prevent overriding values set in the ping event.
|
||||||
if (config.isPassthroughPlayerCounts() && pingInfo != null) {
|
if (config.passthroughPlayerCounts() && pingInfo != null) {
|
||||||
pong.playerCount(pingInfo.getPlayers().getOnline());
|
pong.playerCount(pingInfo.getPlayers().getOnline());
|
||||||
pong.maximumPlayerCount(pingInfo.getPlayers().getMax());
|
pong.maximumPlayerCount(pingInfo.getPlayers().getMax());
|
||||||
} else {
|
} else {
|
||||||
pong.playerCount(geyser.getSessionManager().getSessions().size());
|
pong.playerCount(geyser.getSessionManager().getSessions().size());
|
||||||
pong.maximumPlayerCount(config.getMaxPlayers());
|
pong.maximumPlayerCount(config.maxPlayers());
|
||||||
}
|
}
|
||||||
|
|
||||||
this.geyser.eventBus().fire(new GeyserBedrockPingEventImpl(pong, inetSocketAddress));
|
this.geyser.eventBus().fire(new GeyserBedrockPingEventImpl(pong, inetSocketAddress));
|
||||||
@ -390,6 +394,35 @@ public final class GeyserServer {
|
|||||||
return pong;
|
return pong;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private List<CIDRMatcher> whitelistedIPsMatchers = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Unmodifiable list of {@link CIDRMatcher}s from {@link GeyserConfig.BedrockConfig#proxyProtocolWhitelistedIps()}
|
||||||
|
*/
|
||||||
|
public List<CIDRMatcher> getWhitelistedIPsMatchers() {
|
||||||
|
// Effective Java, Third Edition; Item 83: Use lazy initialization judiciously
|
||||||
|
List<CIDRMatcher> matchers = this.whitelistedIPsMatchers;
|
||||||
|
if (matchers == null) {
|
||||||
|
synchronized (this) {
|
||||||
|
// Check if proxyProtocolWhitelistedIPs contains URLs we need to fetch and parse by line
|
||||||
|
List<String> whitelistedCIDRs = new ArrayList<>();
|
||||||
|
for (String ip: geyser.config().bedrock().proxyProtocolWhitelistedIps()) {
|
||||||
|
if (!ip.startsWith("http")) {
|
||||||
|
whitelistedCIDRs.add(ip);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
WebUtils.getLineStream(ip).forEach(whitelistedCIDRs::add);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.whitelistedIPsMatchers = matchers = whitelistedCIDRs.stream()
|
||||||
|
.map(CIDRMatcher::new)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Collections.unmodifiableList(matchers);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the throwable from the given supplier, or the throwable caught while calling the supplier.
|
* @return the throwable from the given supplier, or the throwable caught while calling the supplier.
|
||||||
*/
|
*/
|
||||||
|
@ -78,7 +78,7 @@ public class SkullResourcePackManager {
|
|||||||
|
|
||||||
Path packPath = cachePath.resolve("player_skulls.mcpack");
|
Path packPath = cachePath.resolve("player_skulls.mcpack");
|
||||||
File packFile = packPath.toFile();
|
File packFile = packPath.toFile();
|
||||||
if (BlockRegistries.CUSTOM_SKULLS.get().isEmpty() || !GeyserImpl.getInstance().getConfig().isAddNonBedrockItems()) {
|
if (BlockRegistries.CUSTOM_SKULLS.get().isEmpty() || !GeyserImpl.getInstance().config().addNonBedrockItems()) {
|
||||||
packFile.delete(); // No need to keep resource pack
|
packFile.delete(); // No need to keep resource pack
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -161,7 +161,7 @@ public class SkullResourcePackManager {
|
|||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
GeyserImpl.getInstance().getLogger().debug("Unable to clean up skull skin cache.");
|
GeyserImpl.getInstance().getLogger().debug("Unable to clean up skull skin cache.");
|
||||||
if (GeyserImpl.getInstance().getConfig().isDebugMode()) {
|
if (GeyserImpl.getInstance().config().debugMode()) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -65,10 +65,10 @@ public class GeyserLegacyPingPassthrough implements IGeyserPingPassthrough, Runn
|
|||||||
* @return GeyserPingPassthrough, or null if not initialized
|
* @return GeyserPingPassthrough, or null if not initialized
|
||||||
*/
|
*/
|
||||||
public static @Nullable IGeyserPingPassthrough init(GeyserImpl geyser) {
|
public static @Nullable IGeyserPingPassthrough init(GeyserImpl geyser) {
|
||||||
if (geyser.getConfig().isPassthroughMotd() || geyser.getConfig().isPassthroughPlayerCounts()) {
|
if (geyser.config().passthroughMotd() || geyser.config().passthroughPlayerCounts()) {
|
||||||
GeyserLegacyPingPassthrough pingPassthrough = new GeyserLegacyPingPassthrough(geyser);
|
GeyserLegacyPingPassthrough pingPassthrough = new GeyserLegacyPingPassthrough(geyser);
|
||||||
// Ensure delay is not zero
|
// Ensure delay is not zero
|
||||||
int interval = (geyser.getConfig().getPingPassthroughInterval() == 0) ? 1 : geyser.getConfig().getPingPassthroughInterval();
|
int interval = (geyser.config().pingPassthroughInterval() == 0) ? 1 : geyser.config().pingPassthroughInterval();
|
||||||
geyser.getLogger().debug("Scheduling ping passthrough at an interval of " + interval + " second(s).");
|
geyser.getLogger().debug("Scheduling ping passthrough at an interval of " + interval + " second(s).");
|
||||||
geyser.getScheduledThread().scheduleAtFixedRate(pingPassthrough, 1, interval, TimeUnit.SECONDS);
|
geyser.getScheduledThread().scheduleAtFixedRate(pingPassthrough, 1, interval, TimeUnit.SECONDS);
|
||||||
return pingPassthrough;
|
return pingPassthrough;
|
||||||
@ -84,8 +84,8 @@ public class GeyserLegacyPingPassthrough implements IGeyserPingPassthrough, Runn
|
|||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
try (Socket socket = new Socket()) {
|
try (Socket socket = new Socket()) {
|
||||||
String address = geyser.getConfig().getRemote().address();
|
String address = geyser.config().java().address();
|
||||||
int port = geyser.getConfig().getRemote().port();
|
int port = geyser.config().java().port();
|
||||||
InetSocketAddress endpoint = new InetSocketAddress(address, port);
|
InetSocketAddress endpoint = new InetSocketAddress(address, port);
|
||||||
socket.connect(endpoint, 5000);
|
socket.connect(endpoint, 5000);
|
||||||
|
|
||||||
@ -102,7 +102,7 @@ public class GeyserLegacyPingPassthrough implements IGeyserPingPassthrough, Runn
|
|||||||
byte[] buffer;
|
byte[] buffer;
|
||||||
|
|
||||||
try (DataOutputStream dataOutputStream = new DataOutputStream(socket.getOutputStream())) {
|
try (DataOutputStream dataOutputStream = new DataOutputStream(socket.getOutputStream())) {
|
||||||
if (geyser.getConfig().getRemote().isUseProxyProtocol()) {
|
if (geyser.config().java().useProxyProtocol()) {
|
||||||
// HAProxy support
|
// HAProxy support
|
||||||
// Based on https://github.com/netty/netty/blob/d8ad931488f6b942dabe28ecd6c399b4438da0a8/codec-haproxy/src/main/java/io/netty/handler/codec/haproxy/HAProxyMessageEncoder.java#L78
|
// Based on https://github.com/netty/netty/blob/d8ad931488f6b942dabe28ecd6c399b4438da0a8/codec-haproxy/src/main/java/io/netty/handler/codec/haproxy/HAProxyMessageEncoder.java#L78
|
||||||
dataOutputStream.write(HAPROXY_BINARY_PREFIX);
|
dataOutputStream.write(HAPROXY_BINARY_PREFIX);
|
||||||
|
@ -70,7 +70,7 @@ public class PacketTranslatorRegistry<T> extends AbstractMappedRegistry<Class<?
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
if (GeyserImpl.getInstance().getConfig().isDebugMode()) {
|
if (GeyserImpl.getInstance().config().debugMode()) {
|
||||||
if (!IGNORED_PACKETS.contains(clazz)) {
|
if (!IGNORED_PACKETS.contains(clazz)) {
|
||||||
GeyserImpl.getInstance().getLogger().debug("Could not find packet for " + (packet.toString().length() > 25 ? packet.getClass().getSimpleName() : packet));
|
GeyserImpl.getInstance().getLogger().debug("Could not find packet for " + (packet.toString().length() > 25 ? packet.getClass().getSimpleName() : packet));
|
||||||
}
|
}
|
||||||
|
@ -90,7 +90,7 @@ public class CustomBlockRegistryPopulator {
|
|||||||
* @param stage the stage to populate
|
* @param stage the stage to populate
|
||||||
*/
|
*/
|
||||||
public static void populate(Stage stage) {
|
public static void populate(Stage stage) {
|
||||||
if (!GeyserImpl.getInstance().getConfig().isAddNonBedrockItems()) {
|
if (!GeyserImpl.getInstance().config().addNonBedrockItems()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,7 +55,7 @@ public class CustomSkullRegistryPopulator {
|
|||||||
SkullResourcePackManager.SKULL_SKINS.clear(); // Remove skins after reloading
|
SkullResourcePackManager.SKULL_SKINS.clear(); // Remove skins after reloading
|
||||||
BlockRegistries.CUSTOM_SKULLS.set(Object2ObjectMaps.emptyMap());
|
BlockRegistries.CUSTOM_SKULLS.set(Object2ObjectMaps.emptyMap());
|
||||||
|
|
||||||
if (!GeyserImpl.getInstance().getConfig().isAddNonBedrockItems()) {
|
if (!GeyserImpl.getInstance().config().addNonBedrockItems()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,7 +65,6 @@ public class CustomSkullRegistryPopulator {
|
|||||||
Path skullConfigPath = bootstrap.getConfigFolder().resolve("custom-skulls.yml");
|
Path skullConfigPath = bootstrap.getConfigFolder().resolve("custom-skulls.yml");
|
||||||
File skullConfigFile = FileUtils.fileOrCopiedFromResource(skullConfigPath.toFile(), "custom-skulls.yml", Function.identity(), bootstrap);
|
File skullConfigFile = FileUtils.fileOrCopiedFromResource(skullConfigPath.toFile(), "custom-skulls.yml", Function.identity(), bootstrap);
|
||||||
skullConfig = FileUtils.loadConfigNew(skullConfigFile, GeyserCustomSkullConfiguration.class);
|
skullConfig = FileUtils.loadConfigNew(skullConfigFile, GeyserCustomSkullConfiguration.class);
|
||||||
System.out.println(skullConfig);
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
GeyserImpl.getInstance().getLogger().severe(GeyserLocale.getLocaleStringLog("geyser.config.failed"), e);
|
GeyserImpl.getInstance().getLogger().severe(GeyserLocale.getLocaleStringLog("geyser.config.failed"), e);
|
||||||
return;
|
return;
|
||||||
|
@ -129,7 +129,7 @@ public class ItemRegistryPopulator {
|
|||||||
throw new AssertionError("Unable to load Bedrock item components", e);
|
throw new AssertionError("Unable to load Bedrock item components", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean customItemsAllowed = GeyserImpl.getInstance().getConfig().isAddNonBedrockItems();
|
boolean customItemsAllowed = GeyserImpl.getInstance().config().addNonBedrockItems();
|
||||||
|
|
||||||
// List values here is important compared to HashSet - we need to preserve the order of what's given to us
|
// List values here is important compared to HashSet - we need to preserve the order of what's given to us
|
||||||
// (as of 1.19.2 Java) to replicate some edge cases in Java predicate behavior where it checks from the bottom
|
// (as of 1.19.2 Java) to replicate some edge cases in Java predicate behavior where it checks from the bottom
|
||||||
|
@ -28,7 +28,7 @@ package org.geysermc.geyser.scoreboard;
|
|||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.geysermc.geyser.GeyserImpl;
|
import org.geysermc.geyser.GeyserImpl;
|
||||||
import org.geysermc.geyser.configuration.GeyserConfiguration;
|
import org.geysermc.geyser.configuration.GeyserConfig;
|
||||||
import org.geysermc.geyser.session.GeyserSession;
|
import org.geysermc.geyser.session.GeyserSession;
|
||||||
import org.geysermc.geyser.session.cache.WorldCache;
|
import org.geysermc.geyser.session.cache.WorldCache;
|
||||||
import org.geysermc.geyser.text.GeyserLocale;
|
import org.geysermc.geyser.text.GeyserLocale;
|
||||||
@ -46,9 +46,9 @@ public final class ScoreboardUpdater extends Thread {
|
|||||||
private static final boolean DEBUG_ENABLED;
|
private static final boolean DEBUG_ENABLED;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
GeyserConfiguration config = GeyserImpl.getInstance().getConfig();
|
GeyserConfig config = GeyserImpl.getInstance().config();
|
||||||
FIRST_SCORE_PACKETS_PER_SECOND_THRESHOLD = Math.min(config.getScoreboardPacketThreshold(), SECOND_SCORE_PACKETS_PER_SECOND_THRESHOLD);
|
FIRST_SCORE_PACKETS_PER_SECOND_THRESHOLD = Math.min(config.scoreboardPacketThreshold(), SECOND_SCORE_PACKETS_PER_SECOND_THRESHOLD);
|
||||||
DEBUG_ENABLED = config.isDebugMode();
|
DEBUG_ENABLED = config.debugMode();
|
||||||
}
|
}
|
||||||
|
|
||||||
private final GeyserImpl geyser = GeyserImpl.getInstance();
|
private final GeyserImpl geyser = GeyserImpl.getInstance();
|
||||||
|
@ -46,17 +46,52 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
import org.checkerframework.common.value.qual.IntRange;
|
import org.checkerframework.common.value.qual.IntRange;
|
||||||
import org.cloudburstmc.math.vector.*;
|
import org.cloudburstmc.math.vector.Vector2f;
|
||||||
|
import org.cloudburstmc.math.vector.Vector2i;
|
||||||
|
import org.cloudburstmc.math.vector.Vector3d;
|
||||||
|
import org.cloudburstmc.math.vector.Vector3f;
|
||||||
|
import org.cloudburstmc.math.vector.Vector3i;
|
||||||
import org.cloudburstmc.nbt.NbtMap;
|
import org.cloudburstmc.nbt.NbtMap;
|
||||||
import org.cloudburstmc.protocol.bedrock.BedrockDisconnectReasons;
|
import org.cloudburstmc.protocol.bedrock.BedrockDisconnectReasons;
|
||||||
import org.cloudburstmc.protocol.bedrock.BedrockServerSession;
|
import org.cloudburstmc.protocol.bedrock.BedrockServerSession;
|
||||||
import org.cloudburstmc.protocol.bedrock.data.*;
|
import org.cloudburstmc.protocol.bedrock.data.Ability;
|
||||||
|
import org.cloudburstmc.protocol.bedrock.data.AbilityLayer;
|
||||||
|
import org.cloudburstmc.protocol.bedrock.data.AuthoritativeMovementMode;
|
||||||
|
import org.cloudburstmc.protocol.bedrock.data.ChatRestrictionLevel;
|
||||||
|
import org.cloudburstmc.protocol.bedrock.data.ExperimentData;
|
||||||
|
import org.cloudburstmc.protocol.bedrock.data.GamePublishSetting;
|
||||||
|
import org.cloudburstmc.protocol.bedrock.data.GameRuleData;
|
||||||
|
import org.cloudburstmc.protocol.bedrock.data.GameType;
|
||||||
|
import org.cloudburstmc.protocol.bedrock.data.PlayerPermission;
|
||||||
|
import org.cloudburstmc.protocol.bedrock.data.SoundEvent;
|
||||||
|
import org.cloudburstmc.protocol.bedrock.data.SpawnBiomeType;
|
||||||
import org.cloudburstmc.protocol.bedrock.data.command.CommandEnumData;
|
import org.cloudburstmc.protocol.bedrock.data.command.CommandEnumData;
|
||||||
import org.cloudburstmc.protocol.bedrock.data.command.CommandPermission;
|
import org.cloudburstmc.protocol.bedrock.data.command.CommandPermission;
|
||||||
import org.cloudburstmc.protocol.bedrock.data.command.SoftEnumUpdateType;
|
import org.cloudburstmc.protocol.bedrock.data.command.SoftEnumUpdateType;
|
||||||
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
|
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
|
||||||
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
|
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
|
||||||
import org.cloudburstmc.protocol.bedrock.packet.*;
|
import org.cloudburstmc.protocol.bedrock.packet.AvailableEntityIdentifiersPacket;
|
||||||
|
import org.cloudburstmc.protocol.bedrock.packet.BedrockPacket;
|
||||||
|
import org.cloudburstmc.protocol.bedrock.packet.BiomeDefinitionListPacket;
|
||||||
|
import org.cloudburstmc.protocol.bedrock.packet.CameraPresetsPacket;
|
||||||
|
import org.cloudburstmc.protocol.bedrock.packet.ChunkRadiusUpdatedPacket;
|
||||||
|
import org.cloudburstmc.protocol.bedrock.packet.CraftingDataPacket;
|
||||||
|
import org.cloudburstmc.protocol.bedrock.packet.CreativeContentPacket;
|
||||||
|
import org.cloudburstmc.protocol.bedrock.packet.EmoteListPacket;
|
||||||
|
import org.cloudburstmc.protocol.bedrock.packet.GameRulesChangedPacket;
|
||||||
|
import org.cloudburstmc.protocol.bedrock.packet.ItemComponentPacket;
|
||||||
|
import org.cloudburstmc.protocol.bedrock.packet.LevelSoundEvent2Packet;
|
||||||
|
import org.cloudburstmc.protocol.bedrock.packet.PlayStatusPacket;
|
||||||
|
import org.cloudburstmc.protocol.bedrock.packet.SetTimePacket;
|
||||||
|
import org.cloudburstmc.protocol.bedrock.packet.StartGamePacket;
|
||||||
|
import org.cloudburstmc.protocol.bedrock.packet.SyncEntityPropertyPacket;
|
||||||
|
import org.cloudburstmc.protocol.bedrock.packet.TextPacket;
|
||||||
|
import org.cloudburstmc.protocol.bedrock.packet.TransferPacket;
|
||||||
|
import org.cloudburstmc.protocol.bedrock.packet.UpdateAbilitiesPacket;
|
||||||
|
import org.cloudburstmc.protocol.bedrock.packet.UpdateAdventureSettingsPacket;
|
||||||
|
import org.cloudburstmc.protocol.bedrock.packet.UpdateAttributesPacket;
|
||||||
|
import org.cloudburstmc.protocol.bedrock.packet.UpdateClientInputLocksPacket;
|
||||||
|
import org.cloudburstmc.protocol.bedrock.packet.UpdateSoftEnumPacket;
|
||||||
import org.cloudburstmc.protocol.common.DefinitionRegistry;
|
import org.cloudburstmc.protocol.common.DefinitionRegistry;
|
||||||
import org.cloudburstmc.protocol.common.util.OptionalBoolean;
|
import org.cloudburstmc.protocol.common.util.OptionalBoolean;
|
||||||
import org.geysermc.api.util.BedrockPlatform;
|
import org.geysermc.api.util.BedrockPlatform;
|
||||||
@ -80,7 +115,6 @@ import org.geysermc.geyser.api.network.AuthType;
|
|||||||
import org.geysermc.geyser.api.network.RemoteServer;
|
import org.geysermc.geyser.api.network.RemoteServer;
|
||||||
import org.geysermc.geyser.api.util.PlatformType;
|
import org.geysermc.geyser.api.util.PlatformType;
|
||||||
import org.geysermc.geyser.command.GeyserCommandSource;
|
import org.geysermc.geyser.command.GeyserCommandSource;
|
||||||
import org.geysermc.geyser.configuration.EmoteOffhandWorkaroundOption;
|
|
||||||
import org.geysermc.geyser.configuration.GeyserConfiguration;
|
import org.geysermc.geyser.configuration.GeyserConfiguration;
|
||||||
import org.geysermc.geyser.entity.EntityDefinitions;
|
import org.geysermc.geyser.entity.EntityDefinitions;
|
||||||
import org.geysermc.geyser.entity.GeyserEntityData;
|
import org.geysermc.geyser.entity.GeyserEntityData;
|
||||||
@ -107,7 +141,22 @@ import org.geysermc.geyser.registry.type.BlockMappings;
|
|||||||
import org.geysermc.geyser.registry.type.ItemMappings;
|
import org.geysermc.geyser.registry.type.ItemMappings;
|
||||||
import org.geysermc.geyser.session.auth.AuthData;
|
import org.geysermc.geyser.session.auth.AuthData;
|
||||||
import org.geysermc.geyser.session.auth.BedrockClientData;
|
import org.geysermc.geyser.session.auth.BedrockClientData;
|
||||||
import org.geysermc.geyser.session.cache.*;
|
import org.geysermc.geyser.session.cache.AdvancementsCache;
|
||||||
|
import org.geysermc.geyser.session.cache.BookEditCache;
|
||||||
|
import org.geysermc.geyser.session.cache.ChunkCache;
|
||||||
|
import org.geysermc.geyser.session.cache.EntityCache;
|
||||||
|
import org.geysermc.geyser.session.cache.EntityEffectCache;
|
||||||
|
import org.geysermc.geyser.session.cache.FormCache;
|
||||||
|
import org.geysermc.geyser.session.cache.LodestoneCache;
|
||||||
|
import org.geysermc.geyser.session.cache.PistonCache;
|
||||||
|
import org.geysermc.geyser.session.cache.PreferencesCache;
|
||||||
|
import org.geysermc.geyser.session.cache.RegistryCache;
|
||||||
|
import org.geysermc.geyser.session.cache.SkullCache;
|
||||||
|
import org.geysermc.geyser.session.cache.StructureBlockCache;
|
||||||
|
import org.geysermc.geyser.session.cache.TagCache;
|
||||||
|
import org.geysermc.geyser.session.cache.TeleportCache;
|
||||||
|
import org.geysermc.geyser.session.cache.WorldBorder;
|
||||||
|
import org.geysermc.geyser.session.cache.WorldCache;
|
||||||
import org.geysermc.geyser.skin.FloodgateSkinUploader;
|
import org.geysermc.geyser.skin.FloodgateSkinUploader;
|
||||||
import org.geysermc.geyser.text.GeyserLocale;
|
import org.geysermc.geyser.text.GeyserLocale;
|
||||||
import org.geysermc.geyser.text.MinecraftLocale;
|
import org.geysermc.geyser.text.MinecraftLocale;
|
||||||
@ -119,7 +168,11 @@ import org.geysermc.geyser.util.EntityUtils;
|
|||||||
import org.geysermc.geyser.util.LoginEncryptionUtils;
|
import org.geysermc.geyser.util.LoginEncryptionUtils;
|
||||||
import org.geysermc.mcprotocollib.network.BuiltinFlags;
|
import org.geysermc.mcprotocollib.network.BuiltinFlags;
|
||||||
import org.geysermc.mcprotocollib.network.Session;
|
import org.geysermc.mcprotocollib.network.Session;
|
||||||
import org.geysermc.mcprotocollib.network.event.session.*;
|
import org.geysermc.mcprotocollib.network.event.session.ConnectedEvent;
|
||||||
|
import org.geysermc.mcprotocollib.network.event.session.DisconnectedEvent;
|
||||||
|
import org.geysermc.mcprotocollib.network.event.session.PacketErrorEvent;
|
||||||
|
import org.geysermc.mcprotocollib.network.event.session.PacketSendingEvent;
|
||||||
|
import org.geysermc.mcprotocollib.network.event.session.SessionAdapter;
|
||||||
import org.geysermc.mcprotocollib.network.packet.Packet;
|
import org.geysermc.mcprotocollib.network.packet.Packet;
|
||||||
import org.geysermc.mcprotocollib.network.tcp.TcpClientSession;
|
import org.geysermc.mcprotocollib.network.tcp.TcpClientSession;
|
||||||
import org.geysermc.mcprotocollib.network.tcp.TcpSession;
|
import org.geysermc.mcprotocollib.network.tcp.TcpSession;
|
||||||
@ -154,7 +207,16 @@ import java.net.ConnectException;
|
|||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.util.*;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.BitSet;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Queue;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.UUID;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||||
import java.util.concurrent.ScheduledFuture;
|
import java.util.concurrent.ScheduledFuture;
|
||||||
@ -600,12 +662,8 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
|
|||||||
this.spawned = false;
|
this.spawned = false;
|
||||||
this.loggedIn = false;
|
this.loggedIn = false;
|
||||||
|
|
||||||
if (geyser.getConfig().getEmoteOffhandWorkaround() != EmoteOffhandWorkaroundOption.NO_EMOTES) {
|
|
||||||
this.emotes = new HashSet<>();
|
this.emotes = new HashSet<>();
|
||||||
geyser.getSessionManager().getSessions().values().forEach(player -> this.emotes.addAll(player.getEmotes()));
|
geyser.getSessionManager().getSessions().values().forEach(player -> this.emotes.addAll(player.getEmotes()));
|
||||||
} else {
|
|
||||||
this.emotes = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.remoteServer = geyser.defaultRemoteServer();
|
this.remoteServer = geyser.defaultRemoteServer();
|
||||||
}
|
}
|
||||||
@ -618,7 +676,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
|
|||||||
sentSpawnPacket = true;
|
sentSpawnPacket = true;
|
||||||
syncEntityProperties();
|
syncEntityProperties();
|
||||||
|
|
||||||
if (GeyserImpl.getInstance().getConfig().isAddNonBedrockItems()) {
|
if (GeyserImpl.getInstance().config().addNonBedrockItems()) {
|
||||||
ItemComponentPacket componentPacket = new ItemComponentPacket();
|
ItemComponentPacket componentPacket = new ItemComponentPacket();
|
||||||
componentPacket.getItems().addAll(itemMappings.getComponentItemData());
|
componentPacket.getItems().addAll(itemMappings.getComponentItemData());
|
||||||
upstream.sendPacket(componentPacket);
|
upstream.sendPacket(componentPacket);
|
||||||
@ -870,11 +928,11 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
|
|||||||
// Disable automatic creation of a new TcpClientSession when transferring - we don't use that functionality.
|
// Disable automatic creation of a new TcpClientSession when transferring - we don't use that functionality.
|
||||||
this.downstream.getSession().setFlag(MinecraftConstants.FOLLOW_TRANSFERS, false);
|
this.downstream.getSession().setFlag(MinecraftConstants.FOLLOW_TRANSFERS, false);
|
||||||
|
|
||||||
if (geyser.getConfig().getRemote().isUseProxyProtocol()) {
|
if (geyser.config().java().useProxyProtocol()) {
|
||||||
downstream.setFlag(BuiltinFlags.ENABLE_CLIENT_PROXY_PROTOCOL, true);
|
downstream.setFlag(BuiltinFlags.ENABLE_CLIENT_PROXY_PROTOCOL, true);
|
||||||
downstream.setFlag(BuiltinFlags.CLIENT_PROXIED_ADDRESS, upstream.getAddress());
|
downstream.setFlag(BuiltinFlags.CLIENT_PROXIED_ADDRESS, upstream.getAddress());
|
||||||
}
|
}
|
||||||
if (geyser.getConfig().isForwardPlayerPing()) {
|
if (geyser.config().forwardPlayerPing()) {
|
||||||
// Let Geyser handle sending the keep alive
|
// Let Geyser handle sending the keep alive
|
||||||
downstream.setFlag(MinecraftConstants.AUTOMATIC_KEEP_ALIVE_MANAGEMENT, false);
|
downstream.setFlag(MinecraftConstants.AUTOMATIC_KEEP_ALIVE_MANAGEMENT, false);
|
||||||
}
|
}
|
||||||
@ -943,7 +1001,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
|
|||||||
ClientIntentionPacket intentionPacket = event.getPacket();
|
ClientIntentionPacket intentionPacket = event.getPacket();
|
||||||
|
|
||||||
String address;
|
String address;
|
||||||
if (geyser.getConfig().getRemote().isForwardHost()) {
|
if (geyser.config().java().forwardHostname()) {
|
||||||
address = clientData.getServerAddress().split(":")[0];
|
address = clientData.getServerAddress().split(":")[0];
|
||||||
} else {
|
} else {
|
||||||
address = intentionPacket.getHostname();
|
address = intentionPacket.getHostname();
|
||||||
@ -1035,7 +1093,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
|
|||||||
} else {
|
} else {
|
||||||
GeyserImpl.getInstance().getLogger().error("An exception occurred: ", cause);
|
GeyserImpl.getInstance().getLogger().error("An exception occurred: ", cause);
|
||||||
}
|
}
|
||||||
if (geyser.getConfig().isDebugMode()) {
|
if (geyser.config().debugMode()) {
|
||||||
cause.printStackTrace();
|
cause.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1058,7 +1116,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
|
|||||||
@Override
|
@Override
|
||||||
public void packetError(PacketErrorEvent event) {
|
public void packetError(PacketErrorEvent event) {
|
||||||
geyser.getLogger().warning(GeyserLocale.getLocaleStringLog("geyser.network.downstream_error", event.getCause().getMessage()));
|
geyser.getLogger().warning(GeyserLocale.getLocaleStringLog("geyser.network.downstream_error", event.getCause().getMessage()));
|
||||||
if (geyser.getConfig().isDebugMode())
|
if (geyser.config().debugMode())
|
||||||
event.getCause().printStackTrace();
|
event.getCause().printStackTrace();
|
||||||
event.setSuppress(true);
|
event.setSuppress(true);
|
||||||
}
|
}
|
||||||
@ -1090,7 +1148,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
|
|||||||
} else {
|
} else {
|
||||||
// Downstream's disconnect will fire an event that prints a log message
|
// Downstream's disconnect will fire an event that prints a log message
|
||||||
// Otherwise, we print a message here
|
// Otherwise, we print a message here
|
||||||
String address = geyser.getConfig().isLogPlayerIpAddresses() ? upstream.getAddress().getAddress().toString() : "<IP address withheld>";
|
String address = geyser.config().logPlayerIpAddresses() ? upstream.getAddress().getAddress().toString() : "<IP address withheld>";
|
||||||
geyser.getLogger().info(GeyserLocale.getLocaleStringLog("geyser.network.disconnect", address, reason));
|
geyser.getLogger().info(GeyserLocale.getLocaleStringLog("geyser.network.disconnect", address, reason));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1482,7 +1540,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
|
|||||||
startGamePacket.setLevelGameType(GameType.SURVIVAL);
|
startGamePacket.setLevelGameType(GameType.SURVIVAL);
|
||||||
startGamePacket.setDifficulty(1);
|
startGamePacket.setDifficulty(1);
|
||||||
startGamePacket.setDefaultSpawn(Vector3i.ZERO);
|
startGamePacket.setDefaultSpawn(Vector3i.ZERO);
|
||||||
startGamePacket.setAchievementsDisabled(!geyser.getConfig().isXboxAchievementsEnabled());
|
startGamePacket.setAchievementsDisabled(!geyser.config().xboxAchievementsEnabled());
|
||||||
startGamePacket.setCurrentTick(-1);
|
startGamePacket.setCurrentTick(-1);
|
||||||
startGamePacket.setEduEditionOffers(0);
|
startGamePacket.setEduEditionOffers(0);
|
||||||
startGamePacket.setEduFeaturesEnabled(false);
|
startGamePacket.setEduFeaturesEnabled(false);
|
||||||
@ -1492,7 +1550,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
|
|||||||
startGamePacket.setBroadcastingToLan(true);
|
startGamePacket.setBroadcastingToLan(true);
|
||||||
startGamePacket.setPlatformBroadcastMode(GamePublishSetting.PUBLIC);
|
startGamePacket.setPlatformBroadcastMode(GamePublishSetting.PUBLIC);
|
||||||
startGamePacket.setXblBroadcastMode(GamePublishSetting.PUBLIC);
|
startGamePacket.setXblBroadcastMode(GamePublishSetting.PUBLIC);
|
||||||
startGamePacket.setCommandsEnabled(!geyser.getConfig().isXboxAchievementsEnabled());
|
startGamePacket.setCommandsEnabled(!geyser.config().xboxAchievementsEnabled());
|
||||||
startGamePacket.setTexturePacksRequired(false);
|
startGamePacket.setTexturePacksRequired(false);
|
||||||
startGamePacket.setBonusChestEnabled(false);
|
startGamePacket.setBonusChestEnabled(false);
|
||||||
startGamePacket.setStartingWithMap(false);
|
startGamePacket.setStartingWithMap(false);
|
||||||
@ -1510,7 +1568,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
|
|||||||
startGamePacket.setEducationProductionId("");
|
startGamePacket.setEducationProductionId("");
|
||||||
startGamePacket.setForceExperimentalGameplay(OptionalBoolean.empty());
|
startGamePacket.setForceExperimentalGameplay(OptionalBoolean.empty());
|
||||||
|
|
||||||
String serverName = geyser.getConfig().getBedrock().serverName();
|
String serverName = geyser.config().bedrock().serverName();
|
||||||
startGamePacket.setLevelId(serverName);
|
startGamePacket.setLevelId(serverName);
|
||||||
startGamePacket.setLevelName(serverName);
|
startGamePacket.setLevelName(serverName);
|
||||||
|
|
||||||
@ -1634,7 +1692,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
|
|||||||
public void sendDownstreamPacket(Packet packet, ProtocolState intendedState) {
|
public void sendDownstreamPacket(Packet packet, ProtocolState intendedState) {
|
||||||
// protocol can be null when we're not yet logged in (online auth)
|
// protocol can be null when we're not yet logged in (online auth)
|
||||||
if (protocol == null) {
|
if (protocol == null) {
|
||||||
if (geyser.getConfig().isDebugMode()) {
|
if (geyser.config().debugMode()) {
|
||||||
geyser.getLogger().debug("Tried to send downstream packet with no downstream session!");
|
geyser.getLogger().debug("Tried to send downstream packet with no downstream session!");
|
||||||
Thread.dumpStack();
|
Thread.dumpStack();
|
||||||
}
|
}
|
||||||
@ -1660,7 +1718,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
|
|||||||
if (channel == null) {
|
if (channel == null) {
|
||||||
// Channel is only null before the connection has initialized
|
// Channel is only null before the connection has initialized
|
||||||
geyser.getLogger().warning("Tried to send a packet to the Java server too early!");
|
geyser.getLogger().warning("Tried to send a packet to the Java server too early!");
|
||||||
if (geyser.getConfig().isDebugMode()) {
|
if (geyser.config().debugMode()) {
|
||||||
Thread.dumpStack();
|
Thread.dumpStack();
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@ -2051,7 +2109,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
|
|||||||
|
|
||||||
private void softEnumPacket(String name, SoftEnumUpdateType type, String enums) {
|
private void softEnumPacket(String name, SoftEnumUpdateType type, String enums) {
|
||||||
// There is no need to send command enums if command suggestions are disabled
|
// There is no need to send command enums if command suggestions are disabled
|
||||||
if (!this.geyser.getConfig().isCommandSuggestions()) {
|
if (!this.geyser.config().commandSuggestions()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
UpdateSoftEnumPacket packet = new UpdateSoftEnumPacket();
|
UpdateSoftEnumPacket packet = new UpdateSoftEnumPacket();
|
||||||
|
@ -25,93 +25,97 @@
|
|||||||
|
|
||||||
package org.geysermc.geyser.session.auth;
|
package org.geysermc.geyser.session.auth;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
import com.google.gson.JsonDeserializationContext;
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
import com.google.gson.JsonDeserializer;
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
import com.google.gson.JsonElement;
|
||||||
|
import com.google.gson.JsonParseException;
|
||||||
|
import com.google.gson.annotations.JsonAdapter;
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
import org.geysermc.floodgate.util.DeviceOs;
|
import org.geysermc.floodgate.util.DeviceOs;
|
||||||
import org.geysermc.floodgate.util.InputMode;
|
import org.geysermc.floodgate.util.InputMode;
|
||||||
import org.geysermc.floodgate.util.UiProfile;
|
import org.geysermc.floodgate.util.UiProfile;
|
||||||
|
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
|
||||||
@Getter
|
@Getter
|
||||||
public final class BedrockClientData {
|
public final class BedrockClientData {
|
||||||
@JsonProperty(value = "GameVersion")
|
@SerializedName(value = "GameVersion")
|
||||||
private String gameVersion;
|
private String gameVersion;
|
||||||
@JsonProperty(value = "ServerAddress")
|
@SerializedName(value = "ServerAddress")
|
||||||
private String serverAddress;
|
private String serverAddress;
|
||||||
@JsonProperty(value = "ThirdPartyName")
|
@SerializedName(value = "ThirdPartyName")
|
||||||
private String username;
|
private String username;
|
||||||
@JsonProperty(value = "LanguageCode")
|
@SerializedName(value = "LanguageCode")
|
||||||
private String languageCode;
|
private String languageCode;
|
||||||
|
|
||||||
@JsonProperty(value = "SkinId")
|
@SerializedName(value = "SkinId")
|
||||||
private String skinId;
|
private String skinId;
|
||||||
@JsonProperty(value = "SkinData")
|
@SerializedName(value = "SkinData")
|
||||||
private String skinData;
|
private String skinData;
|
||||||
@JsonProperty(value = "SkinImageHeight")
|
@SerializedName(value = "SkinImageHeight")
|
||||||
private int skinImageHeight;
|
private int skinImageHeight;
|
||||||
@JsonProperty(value = "SkinImageWidth")
|
@SerializedName(value = "SkinImageWidth")
|
||||||
private int skinImageWidth;
|
private int skinImageWidth;
|
||||||
@JsonProperty(value = "CapeId")
|
@SerializedName(value = "CapeId")
|
||||||
private String capeId;
|
private String capeId;
|
||||||
@JsonProperty(value = "CapeData")
|
@SerializedName(value = "CapeData")
|
||||||
|
@JsonAdapter(value = StringToByteDeserializer.class)
|
||||||
private byte[] capeData;
|
private byte[] capeData;
|
||||||
@JsonProperty(value = "CapeImageHeight")
|
@SerializedName(value = "CapeImageHeight")
|
||||||
private int capeImageHeight;
|
private int capeImageHeight;
|
||||||
@JsonProperty(value = "CapeImageWidth")
|
@SerializedName(value = "CapeImageWidth")
|
||||||
private int capeImageWidth;
|
private int capeImageWidth;
|
||||||
@JsonProperty(value = "CapeOnClassicSkin")
|
@SerializedName(value = "CapeOnClassicSkin")
|
||||||
private boolean capeOnClassicSkin;
|
private boolean capeOnClassicSkin;
|
||||||
@JsonProperty(value = "SkinResourcePatch")
|
@SerializedName(value = "SkinResourcePatch")
|
||||||
private String geometryName;
|
private String geometryName;
|
||||||
@JsonProperty(value = "SkinGeometryData")
|
@SerializedName(value = "SkinGeometryData")
|
||||||
private String geometryData;
|
private String geometryData;
|
||||||
@JsonProperty(value = "PersonaSkin")
|
@SerializedName(value = "PersonaSkin")
|
||||||
private boolean personaSkin;
|
private boolean personaSkin;
|
||||||
@JsonProperty(value = "PremiumSkin")
|
@SerializedName(value = "PremiumSkin")
|
||||||
private boolean premiumSkin;
|
private boolean premiumSkin;
|
||||||
|
|
||||||
@JsonProperty(value = "DeviceId")
|
@SerializedName(value = "DeviceId")
|
||||||
private String deviceId;
|
private String deviceId;
|
||||||
@JsonProperty(value = "DeviceModel")
|
@SerializedName(value = "DeviceModel")
|
||||||
private String deviceModel;
|
private String deviceModel;
|
||||||
@JsonProperty(value = "DeviceOS")
|
@SerializedName(value = "DeviceOS")
|
||||||
private DeviceOs deviceOs;
|
private DeviceOs deviceOs;
|
||||||
@JsonProperty(value = "UIProfile")
|
@SerializedName(value = "UIProfile")
|
||||||
private UiProfile uiProfile;
|
private UiProfile uiProfile;
|
||||||
@JsonProperty(value = "GuiScale")
|
@SerializedName(value = "GuiScale")
|
||||||
private int guiScale;
|
private int guiScale;
|
||||||
@JsonProperty(value = "CurrentInputMode")
|
@SerializedName(value = "CurrentInputMode")
|
||||||
private InputMode currentInputMode;
|
private InputMode currentInputMode;
|
||||||
@JsonProperty(value = "DefaultInputMode")
|
@SerializedName(value = "DefaultInputMode")
|
||||||
private InputMode defaultInputMode;
|
private InputMode defaultInputMode;
|
||||||
@JsonProperty("PlatformOnlineId")
|
@SerializedName("PlatformOnlineId")
|
||||||
private String platformOnlineId;
|
private String platformOnlineId;
|
||||||
@JsonProperty(value = "PlatformOfflineId")
|
@SerializedName(value = "PlatformOfflineId")
|
||||||
private String platformOfflineId;
|
private String platformOfflineId;
|
||||||
@JsonProperty(value = "SelfSignedId")
|
@SerializedName(value = "SelfSignedId")
|
||||||
private UUID selfSignedId;
|
private UUID selfSignedId;
|
||||||
@JsonProperty(value = "ClientRandomId")
|
@SerializedName(value = "ClientRandomId")
|
||||||
private long clientRandomId;
|
private long clientRandomId;
|
||||||
|
|
||||||
@JsonProperty(value = "ArmSize")
|
@SerializedName(value = "ArmSize")
|
||||||
private String armSize;
|
private String armSize;
|
||||||
@JsonProperty(value = "SkinAnimationData")
|
@SerializedName(value = "SkinAnimationData")
|
||||||
private String skinAnimationData;
|
private String skinAnimationData;
|
||||||
@JsonProperty(value = "SkinColor")
|
@SerializedName(value = "SkinColor")
|
||||||
private String skinColor;
|
private String skinColor;
|
||||||
@JsonProperty(value = "ThirdPartyNameOnly")
|
@SerializedName(value = "ThirdPartyNameOnly")
|
||||||
private boolean thirdPartyNameOnly;
|
private boolean thirdPartyNameOnly;
|
||||||
@JsonProperty(value = "PlayFabId")
|
@SerializedName(value = "PlayFabId")
|
||||||
private String playFabId;
|
private String playFabId;
|
||||||
|
|
||||||
@JsonIgnore
|
|
||||||
@Setter
|
@Setter
|
||||||
private String originalString = null;
|
private transient String originalString = null;
|
||||||
|
|
||||||
public DeviceOs getDeviceOs() {
|
public DeviceOs getDeviceOs() {
|
||||||
return deviceOs != null ? deviceOs : DeviceOs.UNKNOWN;
|
return deviceOs != null ? deviceOs : DeviceOs.UNKNOWN;
|
||||||
@ -128,4 +132,11 @@ public final class BedrockClientData {
|
|||||||
public UiProfile getUiProfile() {
|
public UiProfile getUiProfile() {
|
||||||
return uiProfile != null ? uiProfile : UiProfile.CLASSIC;
|
return uiProfile != null ? uiProfile : UiProfile.CLASSIC;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static final class StringToByteDeserializer implements JsonDeserializer<byte[]> {
|
||||||
|
@Override
|
||||||
|
public byte[] deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
|
||||||
|
return json.getAsString().getBytes(StandardCharsets.UTF_8);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -54,15 +54,16 @@ public class PreferencesCache {
|
|||||||
private boolean prefersCustomSkulls;
|
private boolean prefersCustomSkulls;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Which CooldownType the client prefers. Initially set to {@link CooldownUtils#getDefaultShowCooldown()}.
|
* Which CooldownType the client prefers. Initially set to the config default.
|
||||||
*/
|
*/
|
||||||
@Setter
|
@Setter
|
||||||
private CooldownUtils.CooldownType cooldownPreference = CooldownUtils.getDefaultShowCooldown();
|
private CooldownUtils.CooldownType cooldownPreference;
|
||||||
|
|
||||||
public PreferencesCache(GeyserSession session) {
|
public PreferencesCache(GeyserSession session) {
|
||||||
this.session = session;
|
this.session = session;
|
||||||
|
|
||||||
prefersCustomSkulls = session.getGeyser().getConfig().isAllowCustomSkulls();
|
prefersCustomSkulls = session.getGeyser().config().allowCustomSkulls();
|
||||||
|
cooldownPreference = session.getGeyser().config().showCooldown();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -74,7 +75,7 @@ public class PreferencesCache {
|
|||||||
* {@link GeyserConfiguration#isShowCoordinates()} is disabled
|
* {@link GeyserConfiguration#isShowCoordinates()} is disabled
|
||||||
*/
|
*/
|
||||||
public void updateShowCoordinates() {
|
public void updateShowCoordinates() {
|
||||||
allowShowCoordinates = !session.isReducedDebugInfo() && session.getGeyser().getConfig().isShowCoordinates();
|
allowShowCoordinates = !session.isReducedDebugInfo() && session.getGeyser().config().showCoordinates();
|
||||||
session.sendGameRule("showcoordinates", allowShowCoordinates && prefersShowCoordinates);
|
session.sendGameRule("showcoordinates", allowShowCoordinates && prefersShowCoordinates);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -82,6 +83,6 @@ public class PreferencesCache {
|
|||||||
* @return true if the session prefers custom skulls, and the config allows them.
|
* @return true if the session prefers custom skulls, and the config allows them.
|
||||||
*/
|
*/
|
||||||
public boolean showCustomSkulls() {
|
public boolean showCustomSkulls() {
|
||||||
return prefersCustomSkulls && session.getGeyser().getConfig().isAllowCustomSkulls();
|
return prefersCustomSkulls && session.getGeyser().config().allowCustomSkulls();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -74,11 +74,11 @@ public class SkullCache {
|
|||||||
|
|
||||||
public SkullCache(GeyserSession session) {
|
public SkullCache(GeyserSession session) {
|
||||||
this.session = session;
|
this.session = session;
|
||||||
this.maxVisibleSkulls = session.getGeyser().getConfig().getMaxVisibleCustomSkulls();
|
this.maxVisibleSkulls = session.getGeyser().config().maxVisibleCustomSkulls();
|
||||||
this.cullingEnabled = this.maxVisibleSkulls != -1;
|
this.cullingEnabled = this.maxVisibleSkulls != -1;
|
||||||
|
|
||||||
// Normal skulls are not rendered beyond 64 blocks
|
// Normal skulls are not rendered beyond 64 blocks
|
||||||
int distance = Math.min(session.getGeyser().getConfig().getCustomSkullRenderDistance(), 64);
|
int distance = Math.min(session.getGeyser().config().customSkullRenderDistance(), 64);
|
||||||
this.skullRenderDistanceSquared = distance * distance;
|
this.skullRenderDistanceSquared = distance * distance;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -98,7 +98,7 @@ public class SkullCache {
|
|||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
session.getGeyser().getLogger().debug("Player skull with invalid Skin tag: " + position + " Textures: " + texturesProperty);
|
session.getGeyser().getLogger().debug("Player skull with invalid Skin tag: " + position + " Textures: " + texturesProperty);
|
||||||
if (GeyserImpl.getInstance().getConfig().isDebugMode()) {
|
if (GeyserImpl.getInstance().config().debugMode()) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,11 +25,9 @@
|
|||||||
|
|
||||||
package org.geysermc.geyser.skin;
|
package org.geysermc.geyser.skin;
|
||||||
|
|
||||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
import com.google.gson.JsonArray;
|
||||||
import com.fasterxml.jackson.databind.JsonNode;
|
import com.google.gson.JsonObject;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.google.gson.JsonSyntaxException;
|
||||||
import com.fasterxml.jackson.databind.node.ArrayNode;
|
|
||||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import org.geysermc.floodgate.pluginmessage.PluginMessageChannels;
|
import org.geysermc.floodgate.pluginmessage.PluginMessageChannels;
|
||||||
import org.geysermc.floodgate.util.WebsocketEventType;
|
import org.geysermc.floodgate.util.WebsocketEventType;
|
||||||
@ -37,6 +35,7 @@ import org.geysermc.geyser.Constants;
|
|||||||
import org.geysermc.geyser.GeyserImpl;
|
import org.geysermc.geyser.GeyserImpl;
|
||||||
import org.geysermc.geyser.GeyserLogger;
|
import org.geysermc.geyser.GeyserLogger;
|
||||||
import org.geysermc.geyser.session.GeyserSession;
|
import org.geysermc.geyser.session.GeyserSession;
|
||||||
|
import org.geysermc.geyser.util.JsonUtils;
|
||||||
import org.geysermc.geyser.util.PluginMessageUtils;
|
import org.geysermc.geyser.util.PluginMessageUtils;
|
||||||
import org.java_websocket.client.WebSocketClient;
|
import org.java_websocket.client.WebSocketClient;
|
||||||
import org.java_websocket.handshake.ServerHandshake;
|
import org.java_websocket.handshake.ServerHandshake;
|
||||||
@ -52,7 +51,6 @@ import java.util.concurrent.ThreadLocalRandom;
|
|||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
public final class FloodgateSkinUploader {
|
public final class FloodgateSkinUploader {
|
||||||
private final ObjectMapper JACKSON = new ObjectMapper();
|
|
||||||
private final List<String> skinQueue = new ArrayList<>();
|
private final List<String> skinQueue = new ArrayList<>();
|
||||||
|
|
||||||
private final GeyserLogger logger;
|
private final GeyserLogger logger;
|
||||||
@ -79,15 +77,14 @@ public final class FloodgateSkinUploader {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onMessage(String message) {
|
public void onMessage(String message) {
|
||||||
// The reason why I don't like Jackson
|
|
||||||
try {
|
try {
|
||||||
JsonNode node = JACKSON.readTree(message);
|
JsonObject node = JsonUtils.parseJson(message);
|
||||||
if (node.has("error")) {
|
if (node.has("error")) {
|
||||||
logger.error("Got an error: " + node.get("error").asText());
|
logger.error("Got an error: " + node.get("error").getAsString());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int typeId = node.get("event_id").asInt();
|
int typeId = node.get("event_id").getAsInt();
|
||||||
WebsocketEventType type = WebsocketEventType.fromId(typeId);
|
WebsocketEventType type = WebsocketEventType.fromId(typeId);
|
||||||
if (type == null) {
|
if (type == null) {
|
||||||
logger.warning(String.format(
|
logger.warning(String.format(
|
||||||
@ -98,11 +95,11 @@ public final class FloodgateSkinUploader {
|
|||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case SUBSCRIBER_CREATED:
|
case SUBSCRIBER_CREATED:
|
||||||
id = node.get("id").asInt();
|
id = node.get("id").getAsInt();
|
||||||
verifyCode = node.get("verify_code").asText();
|
verifyCode = node.get("verify_code").getAsString();
|
||||||
break;
|
break;
|
||||||
case SUBSCRIBER_COUNT:
|
case SUBSCRIBER_COUNT:
|
||||||
subscribersCount = node.get("subscribers_count").asInt();
|
subscribersCount = node.get("subscribers_count").getAsInt();
|
||||||
break;
|
break;
|
||||||
case SKIN_UPLOADED:
|
case SKIN_UPLOADED:
|
||||||
// if Geyser is the only subscriber we have send it to the server manually
|
// if Geyser is the only subscriber we have send it to the server manually
|
||||||
@ -111,19 +108,19 @@ public final class FloodgateSkinUploader {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
String xuid = node.get("xuid").asText();
|
String xuid = node.get("xuid").getAsString();
|
||||||
GeyserSession session = geyser.connectionByXuid(xuid);
|
GeyserSession session = geyser.connectionByXuid(xuid);
|
||||||
|
|
||||||
if (session != null) {
|
if (session != null) {
|
||||||
if (!node.get("success").asBoolean()) {
|
if (!node.get("success").getAsBoolean()) {
|
||||||
logger.info("Failed to upload skin for " + session.bedrockUsername());
|
logger.info("Failed to upload skin for " + session.bedrockUsername());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonNode data = node.get("data");
|
JsonObject data = node.getAsJsonObject("data");
|
||||||
|
|
||||||
String value = data.get("value").asText();
|
String value = data.get("value").getAsString();
|
||||||
String signature = data.get("signature").asText();
|
String signature = data.get("signature").getAsString();
|
||||||
|
|
||||||
byte[] bytes = (value + '\0' + signature)
|
byte[] bytes = (value + '\0' + signature)
|
||||||
.getBytes(StandardCharsets.UTF_8);
|
.getBytes(StandardCharsets.UTF_8);
|
||||||
@ -131,8 +128,8 @@ public final class FloodgateSkinUploader {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case LOG_MESSAGE:
|
case LOG_MESSAGE:
|
||||||
String logMessage = node.get("message").asText();
|
String logMessage = node.get("message").getAsString();
|
||||||
switch (node.get("priority").asInt()) {
|
switch (node.get("priority").getAsInt()) {
|
||||||
case -1 -> logger.debug("Got a message from skin uploader: " + logMessage);
|
case -1 -> logger.debug("Got a message from skin uploader: " + logMessage);
|
||||||
case 0 -> logger.info("Got a message from skin uploader: " + logMessage);
|
case 0 -> logger.info("Got a message from skin uploader: " + logMessage);
|
||||||
case 1 -> logger.error("Got a message from skin uploader: " + logMessage);
|
case 1 -> logger.error("Got a message from skin uploader: " + logMessage);
|
||||||
@ -150,20 +147,19 @@ public final class FloodgateSkinUploader {
|
|||||||
@Override
|
@Override
|
||||||
public void onClose(int code, String reason, boolean remote) {
|
public void onClose(int code, String reason, boolean remote) {
|
||||||
if (reason != null && !reason.isEmpty()) {
|
if (reason != null && !reason.isEmpty()) {
|
||||||
// The reason why I don't like Jackson
|
|
||||||
try {
|
try {
|
||||||
JsonNode node = JACKSON.readTree(reason);
|
JsonObject node = JsonUtils.parseJson(reason);
|
||||||
// info means that the uploader itself did nothing wrong
|
// info means that the uploader itself did nothing wrong
|
||||||
if (node.has("info")) {
|
if (node.has("info")) {
|
||||||
String info = node.get("info").asText();
|
String info = node.get("info").getAsString();
|
||||||
logger.debug("Got disconnected from the skin uploader: " + info);
|
logger.debug("Got disconnected from the skin uploader: " + info);
|
||||||
}
|
}
|
||||||
// error means that the uploader did something wrong
|
// error means that the uploader did something wrong
|
||||||
if (node.has("error")) {
|
if (node.has("error")) {
|
||||||
String error = node.get("error").asText();
|
String error = node.get("error").getAsString();
|
||||||
logger.info("Got disconnected from the skin uploader: " + error);
|
logger.info("Got disconnected from the skin uploader: " + error);
|
||||||
}
|
}
|
||||||
} catch (JsonProcessingException ignored) {
|
} catch (JsonSyntaxException ignored) {
|
||||||
// ignore invalid json
|
// ignore invalid json
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.error("Error while handling onClose", e);
|
logger.error("Error while handling onClose", e);
|
||||||
@ -195,20 +191,13 @@ public final class FloodgateSkinUploader {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ObjectNode node = JACKSON.createObjectNode();
|
JsonObject node = new JsonObject();
|
||||||
ArrayNode chainDataNode = JACKSON.createArrayNode();
|
JsonArray chainDataNode = new JsonArray();
|
||||||
chainData.forEach(chainDataNode::add);
|
chainData.forEach(chainDataNode::add);
|
||||||
node.set("chain_data", chainDataNode);
|
node.add("chain_data", chainDataNode);
|
||||||
node.put("client_data", clientData);
|
node.addProperty("client_data", clientData);
|
||||||
|
|
||||||
// The reason why I don't like Jackson
|
String jsonString = node.toString();
|
||||||
String jsonString;
|
|
||||||
try {
|
|
||||||
jsonString = JACKSON.writeValueAsString(node);
|
|
||||||
} catch (Exception e) {
|
|
||||||
logger.error("Failed to upload skin", e);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (client.isOpen()) {
|
if (client.isOpen()) {
|
||||||
client.send(jsonString);
|
client.send(jsonString);
|
||||||
|
@ -25,7 +25,8 @@
|
|||||||
|
|
||||||
package org.geysermc.geyser.skin;
|
package org.geysermc.geyser.skin;
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.JsonNode;
|
import com.google.gson.JsonObject;
|
||||||
|
import com.google.gson.JsonPrimitive;
|
||||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
import org.cloudburstmc.nbt.NbtMap;
|
import org.cloudburstmc.nbt.NbtMap;
|
||||||
import org.cloudburstmc.nbt.NbtType;
|
import org.cloudburstmc.nbt.NbtType;
|
||||||
@ -43,6 +44,7 @@ import org.geysermc.geyser.entity.type.player.SkullPlayerEntity;
|
|||||||
import org.geysermc.geyser.session.GeyserSession;
|
import org.geysermc.geyser.session.GeyserSession;
|
||||||
import org.geysermc.geyser.session.auth.BedrockClientData;
|
import org.geysermc.geyser.session.auth.BedrockClientData;
|
||||||
import org.geysermc.geyser.text.GeyserLocale;
|
import org.geysermc.geyser.text.GeyserLocale;
|
||||||
|
import org.geysermc.geyser.util.JsonUtils;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
@ -194,7 +196,7 @@ public class SkinManager {
|
|||||||
|
|
||||||
public static void handleBedrockSkin(PlayerEntity playerEntity, BedrockClientData clientData) {
|
public static void handleBedrockSkin(PlayerEntity playerEntity, BedrockClientData clientData) {
|
||||||
GeyserImpl geyser = GeyserImpl.getInstance();
|
GeyserImpl geyser = GeyserImpl.getInstance();
|
||||||
if (geyser.getConfig().isDebugMode()) {
|
if (geyser.config().debugMode()) {
|
||||||
geyser.getLogger().info(GeyserLocale.getLocaleStringLog("geyser.skin.bedrock.register", playerEntity.getUsername(), playerEntity.getUuid()));
|
geyser.getLogger().info(GeyserLocale.getLocaleStringLog("geyser.skin.bedrock.register", playerEntity.getUsername(), playerEntity.getUuid()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -208,7 +210,7 @@ public class SkinManager {
|
|||||||
if (skinBytes.length <= (128 * 128 * 4) && !clientData.isPersonaSkin()) {
|
if (skinBytes.length <= (128 * 128 * 4) && !clientData.isPersonaSkin()) {
|
||||||
SkinProvider.storeBedrockSkin(playerEntity.getUuid(), clientData.getSkinId(), skinBytes);
|
SkinProvider.storeBedrockSkin(playerEntity.getUuid(), clientData.getSkinId(), skinBytes);
|
||||||
SkinProvider.storeBedrockGeometry(playerEntity.getUuid(), geometryNameBytes, geometryBytes);
|
SkinProvider.storeBedrockGeometry(playerEntity.getUuid(), geometryNameBytes, geometryBytes);
|
||||||
} else if (geyser.getConfig().isDebugMode()) {
|
} else if (geyser.config().debugMode()) {
|
||||||
geyser.getLogger().info(GeyserLocale.getLocaleStringLog("geyser.skin.bedrock.fail", playerEntity.getUsername()));
|
geyser.getLogger().info(GeyserLocale.getLocaleStringLog("geyser.skin.bedrock.fail", playerEntity.getUsername()));
|
||||||
geyser.getLogger().debug("The size of '" + playerEntity.getUsername() + "' skin is: " + clientData.getSkinImageWidth() + "x" + clientData.getSkinImageHeight());
|
geyser.getLogger().debug("The size of '" + playerEntity.getUsername() + "' skin is: " + clientData.getSkinImageWidth() + "x" + clientData.getSkinImageHeight());
|
||||||
}
|
}
|
||||||
@ -246,7 +248,7 @@ public class SkinManager {
|
|||||||
return loadFromJson(skinDataValue);
|
return loadFromJson(skinDataValue);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
GeyserImpl.getInstance().getLogger().debug("Something went wrong while processing skin for tag " + tag);
|
GeyserImpl.getInstance().getLogger().debug("Something went wrong while processing skin for tag " + tag);
|
||||||
if (GeyserImpl.getInstance().getConfig().isDebugMode()) {
|
if (GeyserImpl.getInstance().config().debugMode()) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
@ -274,7 +276,7 @@ public class SkinManager {
|
|||||||
} else {
|
} else {
|
||||||
GeyserImpl.getInstance().getLogger().debug("Something went wrong while processing skin for " + entity.getUsername() + " with Value: " + texturesProperty);
|
GeyserImpl.getInstance().getLogger().debug("Something went wrong while processing skin for " + entity.getUsername() + " with Value: " + texturesProperty);
|
||||||
}
|
}
|
||||||
if (GeyserImpl.getInstance().getConfig().isDebugMode()) {
|
if (GeyserImpl.getInstance().config().debugMode()) {
|
||||||
exception.printStackTrace();
|
exception.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -282,30 +284,25 @@ public class SkinManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static @Nullable GameProfileData loadFromJson(String encodedJson) throws IOException, IllegalArgumentException {
|
public static @Nullable GameProfileData loadFromJson(String encodedJson) throws IOException, IllegalArgumentException {
|
||||||
// TODO use GameProfile method.
|
JsonObject skinObject;
|
||||||
JsonNode skinObject;
|
|
||||||
try {
|
try {
|
||||||
skinObject = GeyserImpl.JSON_MAPPER.readTree(new String(Base64.getDecoder().decode(encodedJson), StandardCharsets.UTF_8));
|
skinObject = JsonUtils.parseJson(new String(Base64.getDecoder().decode(encodedJson), StandardCharsets.UTF_8));
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
GeyserImpl.getInstance().getLogger().debug("Invalid base64 encoded skin entry: " + encodedJson);
|
GeyserImpl.getInstance().getLogger().debug("Invalid base64 encoded skin entry: " + encodedJson);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonNode textures = skinObject.get("textures");
|
if (!(skinObject.get("textures") instanceof JsonObject textures)) {
|
||||||
|
|
||||||
if (textures == null) {
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonNode skinTexture = textures.get("SKIN");
|
if (!(textures.get("SKIN") instanceof JsonObject skinTexture)) {
|
||||||
if (skinTexture == null) {
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
String skinUrl;
|
String skinUrl;
|
||||||
JsonNode skinUrlNode = skinTexture.get("url");
|
if (skinTexture.get("url") instanceof JsonPrimitive skinUrlNode && skinUrlNode.isString()) {
|
||||||
if (skinUrlNode != null && skinUrlNode.isTextual()) {
|
skinUrl = skinUrlNode.getAsString().replace("http://", "https://");
|
||||||
skinUrl = skinUrlNode.asText().replace("http://", "https://");
|
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -322,11 +319,9 @@ public class SkinManager {
|
|||||||
boolean isAlex = skinTexture.has("metadata");
|
boolean isAlex = skinTexture.has("metadata");
|
||||||
|
|
||||||
String capeUrl = null;
|
String capeUrl = null;
|
||||||
JsonNode capeTexture = textures.get("CAPE");
|
if (textures.get("CAPE") instanceof JsonObject capeTexture) {
|
||||||
if (capeTexture != null) {
|
if (capeTexture.get("url") instanceof JsonPrimitive capeUrlNode && capeUrlNode.isString()) {
|
||||||
JsonNode capeUrlNode = capeTexture.get("url");
|
capeUrl = capeUrlNode.getAsString().replace("http://", "https://");
|
||||||
if (capeUrlNode != null && capeUrlNode.isTextual()) {
|
|
||||||
capeUrl = capeUrlNode.asText().replace("http://", "https://");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -126,11 +126,6 @@ public class SkinProvider {
|
|||||||
WEARING_CUSTOM_SKULL = new SkinGeometry("{\"geometry\" :{\"default\" :\"geometry.humanoid.wearingCustomSkull\"}}", wearingCustomSkull);
|
WEARING_CUSTOM_SKULL = new SkinGeometry("{\"geometry\" :{\"default\" :\"geometry.humanoid.wearingCustomSkull\"}}", wearingCustomSkull);
|
||||||
String wearingCustomSkullSlim = new String(FileUtils.readAllBytes("bedrock/skin/geometry.humanoid.wearingCustomSkullSlim.json"), StandardCharsets.UTF_8);
|
String wearingCustomSkullSlim = new String(FileUtils.readAllBytes("bedrock/skin/geometry.humanoid.wearingCustomSkullSlim.json"), StandardCharsets.UTF_8);
|
||||||
WEARING_CUSTOM_SKULL_SLIM = new SkinGeometry("{\"geometry\" :{\"default\" :\"geometry.humanoid.wearingCustomSkullSlim\"}}", wearingCustomSkullSlim);
|
WEARING_CUSTOM_SKULL_SLIM = new SkinGeometry("{\"geometry\" :{\"default\" :\"geometry.humanoid.wearingCustomSkullSlim\"}}", wearingCustomSkullSlim);
|
||||||
|
|
||||||
GeyserImpl geyser = GeyserImpl.getInstance();
|
|
||||||
if (geyser.getConfig().isAllowThirdPartyEars() || geyser.getConfig().isAllowThirdPartyCapes()) {
|
|
||||||
geyser.getLogger().warning("Third-party ears/capes have been removed from Geyser, if you still wish to have this functionality please use the extension: https://github.com/GeyserMC/ThirdPartyCosmetics");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ExecutorService getExecutorService() {
|
public static ExecutorService getExecutorService() {
|
||||||
@ -149,7 +144,7 @@ public class SkinProvider {
|
|||||||
|
|
||||||
public static void registerCacheImageTask(GeyserImpl geyser) {
|
public static void registerCacheImageTask(GeyserImpl geyser) {
|
||||||
// Schedule Daily Image Expiry if we are caching them
|
// Schedule Daily Image Expiry if we are caching them
|
||||||
if (geyser.getConfig().getCacheImages() > 0) {
|
if (geyser.config().cacheImages() > 0) {
|
||||||
geyser.getScheduledThread().scheduleAtFixedRate(() -> {
|
geyser.getScheduledThread().scheduleAtFixedRate(() -> {
|
||||||
File cacheFolder = GeyserImpl.getInstance().getBootstrap().getConfigFolder().resolve("cache").resolve("images").toFile();
|
File cacheFolder = GeyserImpl.getInstance().getBootstrap().getConfigFolder().resolve("cache").resolve("images").toFile();
|
||||||
if (!cacheFolder.exists()) {
|
if (!cacheFolder.exists()) {
|
||||||
@ -157,7 +152,7 @@ public class SkinProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int count = 0;
|
int count = 0;
|
||||||
final long expireTime = ((long) GeyserImpl.getInstance().getConfig().getCacheImages()) * ((long)1000 * 60 * 60 * 24);
|
final long expireTime = ((long) GeyserImpl.getInstance().config().cacheImages()) * ((long)1000 * 60 * 60 * 24);
|
||||||
for (File imageFile : Objects.requireNonNull(cacheFolder.listFiles())) {
|
for (File imageFile : Objects.requireNonNull(cacheFolder.listFiles())) {
|
||||||
if (imageFile.lastModified() < System.currentTimeMillis() - expireTime) {
|
if (imageFile.lastModified() < System.currentTimeMillis() - expireTime) {
|
||||||
//noinspection ResultOfMethodCallIgnored
|
//noinspection ResultOfMethodCallIgnored
|
||||||
@ -188,7 +183,7 @@ public class SkinProvider {
|
|||||||
Cape cape = null;
|
Cape cape = null;
|
||||||
SkinGeometry geometry = SkinGeometry.WIDE;
|
SkinGeometry geometry = SkinGeometry.WIDE;
|
||||||
|
|
||||||
if (GeyserImpl.getInstance().getConfig().getRemote().authType() != AuthType.ONLINE) {
|
if (GeyserImpl.getInstance().config().java().authType() != AuthType.ONLINE) {
|
||||||
// Let's see if this player is a Bedrock player, and if so, let's pull their skin.
|
// Let's see if this player is a Bedrock player, and if so, let's pull their skin.
|
||||||
GeyserSession session = GeyserImpl.getInstance().connectionByUuid(uuid);
|
GeyserSession session = GeyserImpl.getInstance().connectionByUuid(uuid);
|
||||||
if (session != null) {
|
if (session != null) {
|
||||||
@ -427,7 +422,7 @@ public class SkinProvider {
|
|||||||
GeyserImpl.getInstance().getLogger().debug("Downloaded " + imageUrl);
|
GeyserImpl.getInstance().getLogger().debug("Downloaded " + imageUrl);
|
||||||
|
|
||||||
// Write to cache if we are allowed
|
// Write to cache if we are allowed
|
||||||
if (GeyserImpl.getInstance().getConfig().getCacheImages() > 0) {
|
if (GeyserImpl.getInstance().config().cacheImages() > 0) {
|
||||||
imageFile.getParentFile().mkdirs();
|
imageFile.getParentFile().mkdirs();
|
||||||
try {
|
try {
|
||||||
ImageIO.write(image, "png", imageFile);
|
ImageIO.write(image, "png", imageFile);
|
||||||
@ -496,7 +491,7 @@ public class SkinProvider {
|
|||||||
return properties.get(0).getAsJsonObject().get("value").getAsString();
|
return properties.get(0).getAsJsonObject().get("value").getAsString();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
GeyserImpl.getInstance().getLogger().debug("Unable to request textures for " + uuid);
|
GeyserImpl.getInstance().getLogger().debug("Unable to request textures for " + uuid);
|
||||||
if (GeyserImpl.getInstance().getConfig().isDebugMode()) {
|
if (GeyserImpl.getInstance().config().debugMode()) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
@ -515,7 +510,6 @@ public class SkinProvider {
|
|||||||
try {
|
try {
|
||||||
// Offline skin, or no present UUID
|
// Offline skin, or no present UUID
|
||||||
JsonObject node = WebUtils.getJson("https://api.mojang.com/users/profiles/minecraft/" + username);
|
JsonObject node = WebUtils.getJson("https://api.mojang.com/users/profiles/minecraft/" + username);
|
||||||
System.out.println(node);
|
|
||||||
JsonElement id = node.get("id");
|
JsonElement id = node.get("id");
|
||||||
if (id == null) {
|
if (id == null) {
|
||||||
GeyserImpl.getInstance().getLogger().debug("No UUID found in Mojang response for " + username);
|
GeyserImpl.getInstance().getLogger().debug("No UUID found in Mojang response for " + username);
|
||||||
@ -523,7 +517,7 @@ public class SkinProvider {
|
|||||||
}
|
}
|
||||||
return id.getAsString();
|
return id.getAsString();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
if (GeyserImpl.getInstance().getConfig().isDebugMode()) {
|
if (GeyserImpl.getInstance().config().debugMode()) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
@ -80,8 +80,8 @@ public class GeyserLocale {
|
|||||||
* Finalize the default locale, now that we know what the default locale should be.
|
* Finalize the default locale, now that we know what the default locale should be.
|
||||||
*/
|
*/
|
||||||
public static void finalizeDefaultLocale(GeyserImpl geyser) {
|
public static void finalizeDefaultLocale(GeyserImpl geyser) {
|
||||||
String newDefaultLocale = geyser.getConfig().getDefaultLocale();
|
String newDefaultLocale = geyser.config().defaultLocale();
|
||||||
if (newDefaultLocale == null) {
|
if ("system".equals(newDefaultLocale)) {
|
||||||
// We want to use the system locale which is already loaded
|
// We want to use the system locale which is already loaded
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -207,7 +207,7 @@ public abstract class InventoryTranslator {
|
|||||||
case PLACE: {
|
case PLACE: {
|
||||||
TransferItemStackRequestAction transferAction = (TransferItemStackRequestAction) action;
|
TransferItemStackRequestAction transferAction = (TransferItemStackRequestAction) action;
|
||||||
if (!(checkNetId(session, inventory, transferAction.getSource()) && checkNetId(session, inventory, transferAction.getDestination()))) {
|
if (!(checkNetId(session, inventory, transferAction.getSource()) && checkNetId(session, inventory, transferAction.getDestination()))) {
|
||||||
if (session.getGeyser().getConfig().isDebugMode()) {
|
if (session.getGeyser().config().debugMode()) {
|
||||||
session.getGeyser().getLogger().error("DEBUG: About to reject TAKE/PLACE request made by " + session.bedrockUsername());
|
session.getGeyser().getLogger().error("DEBUG: About to reject TAKE/PLACE request made by " + session.bedrockUsername());
|
||||||
dumpStackRequestDetails(session, inventory, transferAction.getSource(), transferAction.getDestination());
|
dumpStackRequestDetails(session, inventory, transferAction.getSource(), transferAction.getDestination());
|
||||||
}
|
}
|
||||||
@ -312,7 +312,7 @@ public abstract class InventoryTranslator {
|
|||||||
ItemStackRequestSlotData destination = swapAction.getDestination();
|
ItemStackRequestSlotData destination = swapAction.getDestination();
|
||||||
|
|
||||||
if (!(checkNetId(session, inventory, source) && checkNetId(session, inventory, destination))) {
|
if (!(checkNetId(session, inventory, source) && checkNetId(session, inventory, destination))) {
|
||||||
if (session.getGeyser().getConfig().isDebugMode()) {
|
if (session.getGeyser().config().debugMode()) {
|
||||||
session.getGeyser().getLogger().error("DEBUG: About to reject SWAP request made by " + session.bedrockUsername());
|
session.getGeyser().getLogger().error("DEBUG: About to reject SWAP request made by " + session.bedrockUsername());
|
||||||
dumpStackRequestDetails(session, inventory, source, destination);
|
dumpStackRequestDetails(session, inventory, source, destination);
|
||||||
}
|
}
|
||||||
@ -807,7 +807,7 @@ public abstract class InventoryTranslator {
|
|||||||
* as bad (false).
|
* as bad (false).
|
||||||
*/
|
*/
|
||||||
protected static ItemStackResponse rejectRequest(ItemStackRequest request, boolean throwError) {
|
protected static ItemStackResponse rejectRequest(ItemStackRequest request, boolean throwError) {
|
||||||
if (throwError && GeyserImpl.getInstance().getConfig().isDebugMode()) {
|
if (throwError && GeyserImpl.getInstance().config().debugMode()) {
|
||||||
new Throwable("DEBUGGING: ItemStackRequest rejected " + request.toString()).printStackTrace();
|
new Throwable("DEBUGGING: ItemStackRequest rejected " + request.toString()).printStackTrace();
|
||||||
}
|
}
|
||||||
return new ItemStackResponse(ItemStackResponseStatus.ERROR, request.getRequestId(), Collections.emptyList());
|
return new ItemStackResponse(ItemStackResponseStatus.ERROR, request.getRequestId(), Collections.emptyList());
|
||||||
|
@ -120,7 +120,7 @@ public class SkullBlockEntityTranslator extends BlockEntityTranslator implements
|
|||||||
return skull.getBlockDefinition();
|
return skull.getBlockDefinition();
|
||||||
} catch (InterruptedException | ExecutionException e) {
|
} catch (InterruptedException | ExecutionException e) {
|
||||||
session.getGeyser().getLogger().debug("Failed to acquire textures for custom skull: " + blockPosition + " " + javaNbt);
|
session.getGeyser().getLogger().debug("Failed to acquire textures for custom skull: " + blockPosition + " " + javaNbt);
|
||||||
if (GeyserImpl.getInstance().getConfig().isDebugMode()) {
|
if (GeyserImpl.getInstance().config().debugMode()) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,6 @@
|
|||||||
package org.geysermc.geyser.translator.protocol.bedrock;
|
package org.geysermc.geyser.translator.protocol.bedrock;
|
||||||
|
|
||||||
import org.cloudburstmc.protocol.bedrock.packet.EmoteListPacket;
|
import org.cloudburstmc.protocol.bedrock.packet.EmoteListPacket;
|
||||||
import org.geysermc.geyser.configuration.EmoteOffhandWorkaroundOption;
|
|
||||||
import org.geysermc.geyser.session.GeyserSession;
|
import org.geysermc.geyser.session.GeyserSession;
|
||||||
import org.geysermc.geyser.translator.protocol.PacketTranslator;
|
import org.geysermc.geyser.translator.protocol.PacketTranslator;
|
||||||
import org.geysermc.geyser.translator.protocol.Translator;
|
import org.geysermc.geyser.translator.protocol.Translator;
|
||||||
@ -36,10 +35,6 @@ public class BedrockEmoteListTranslator extends PacketTranslator<EmoteListPacket
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void translate(GeyserSession session, EmoteListPacket packet) {
|
public void translate(GeyserSession session, EmoteListPacket packet) {
|
||||||
if (session.getGeyser().getConfig().getEmoteOffhandWorkaround() == EmoteOffhandWorkaroundOption.NO_EMOTES) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
session.refreshEmotes(packet.getPieceIds());
|
session.refreshEmotes(packet.getPieceIds());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -169,7 +169,7 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator<Inve
|
|||||||
final Vector3i packetBlockPosition = packet.getBlockPosition();
|
final Vector3i packetBlockPosition = packet.getBlockPosition();
|
||||||
Vector3i blockPos = BlockUtils.getBlockPosition(packetBlockPosition, packet.getBlockFace());
|
Vector3i blockPos = BlockUtils.getBlockPosition(packetBlockPosition, packet.getBlockFace());
|
||||||
|
|
||||||
if (session.getGeyser().getConfig().isDisableBedrockScaffolding()) {
|
if (session.getGeyser().config().disableBedrockScaffolding()) {
|
||||||
float yaw = session.getPlayerEntity().getYaw();
|
float yaw = session.getPlayerEntity().getYaw();
|
||||||
boolean isGodBridging = switch (packet.getBlockFace()) {
|
boolean isGodBridging = switch (packet.getBlockFace()) {
|
||||||
case 2 -> yaw <= -135f || yaw > 135f;
|
case 2 -> yaw <= -135f || yaw > 135f;
|
||||||
|
@ -47,7 +47,7 @@ public class BedrockNetworkStackLatencyTranslator extends PacketTranslator<Netwo
|
|||||||
public void translate(GeyserSession session, NetworkStackLatencyPacket packet) {
|
public void translate(GeyserSession session, NetworkStackLatencyPacket packet) {
|
||||||
// negative timestamps are used as hack to fix the url image loading bug
|
// negative timestamps are used as hack to fix the url image loading bug
|
||||||
if (packet.getTimestamp() >= 0) {
|
if (packet.getTimestamp() >= 0) {
|
||||||
if (session.getGeyser().getConfig().isForwardPlayerPing()) {
|
if (session.getGeyser().config().forwardPlayerPing()) {
|
||||||
// use our cached value because
|
// use our cached value because
|
||||||
// a) bedrock can be inaccurate with the value returned
|
// a) bedrock can be inaccurate with the value returned
|
||||||
// b) playstation replies with a different magnitude than other platforms
|
// b) playstation replies with a different magnitude than other platforms
|
||||||
|
@ -45,7 +45,7 @@ public class BedrockSetLocalPlayerAsInitializedTranslator extends PacketTranslat
|
|||||||
|
|
||||||
if (session.remoteServer().authType() == AuthType.ONLINE) {
|
if (session.remoteServer().authType() == AuthType.ONLINE) {
|
||||||
if (!session.isLoggedIn()) {
|
if (!session.isLoggedIn()) {
|
||||||
if (session.getGeyser().getConfig().getSavedUserLogins().contains(session.bedrockUsername())) {
|
if (session.getGeyser().config().savedUserLogins().contains(session.bedrockUsername())) {
|
||||||
if (session.getGeyser().refreshTokenFor(session.bedrockUsername()) == null) {
|
if (session.getGeyser().refreshTokenFor(session.bedrockUsername()) == null) {
|
||||||
LoginEncryptionUtils.buildAndShowConsentWindow(session);
|
LoginEncryptionUtils.buildAndShowConsentWindow(session);
|
||||||
} else {
|
} else {
|
||||||
|
@ -27,7 +27,6 @@ package org.geysermc.geyser.translator.protocol.bedrock.entity.player;
|
|||||||
|
|
||||||
import org.cloudburstmc.protocol.bedrock.packet.EmotePacket;
|
import org.cloudburstmc.protocol.bedrock.packet.EmotePacket;
|
||||||
import org.geysermc.geyser.api.event.bedrock.ClientEmoteEvent;
|
import org.geysermc.geyser.api.event.bedrock.ClientEmoteEvent;
|
||||||
import org.geysermc.geyser.configuration.EmoteOffhandWorkaroundOption;
|
|
||||||
import org.geysermc.geyser.entity.type.Entity;
|
import org.geysermc.geyser.entity.type.Entity;
|
||||||
import org.geysermc.geyser.entity.type.player.PlayerEntity;
|
import org.geysermc.geyser.entity.type.player.PlayerEntity;
|
||||||
import org.geysermc.geyser.session.GeyserSession;
|
import org.geysermc.geyser.session.GeyserSession;
|
||||||
@ -39,15 +38,6 @@ public class BedrockEmoteTranslator extends PacketTranslator<EmotePacket> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void translate(GeyserSession session, EmotePacket packet) {
|
public void translate(GeyserSession session, EmotePacket packet) {
|
||||||
if (session.getGeyser().getConfig().getEmoteOffhandWorkaround() != EmoteOffhandWorkaroundOption.DISABLED) {
|
|
||||||
// Activate the workaround - we should trigger the offhand now
|
|
||||||
session.requestOffhandSwap();
|
|
||||||
|
|
||||||
if (session.getGeyser().getConfig().getEmoteOffhandWorkaround() == EmoteOffhandWorkaroundOption.NO_EMOTES) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// For the future: could have a method that exposes which players will see the emote
|
// For the future: could have a method that exposes which players will see the emote
|
||||||
ClientEmoteEvent event = new ClientEmoteEvent(session, packet.getEmoteId());
|
ClientEmoteEvent event = new ClientEmoteEvent(session, packet.getEmoteId());
|
||||||
session.getGeyser().eventBus().fire(event);
|
session.getGeyser().eventBus().fire(event);
|
||||||
|
@ -113,7 +113,7 @@ public class JavaCommandsTranslator extends PacketTranslator<ClientboundCommands
|
|||||||
@Override
|
@Override
|
||||||
public void translate(GeyserSession session, ClientboundCommandsPacket packet) {
|
public void translate(GeyserSession session, ClientboundCommandsPacket packet) {
|
||||||
// Don't send command suggestions if they are disabled
|
// Don't send command suggestions if they are disabled
|
||||||
if (!session.getGeyser().getConfig().isCommandSuggestions()) {
|
if (!session.getGeyser().config().commandSuggestions()) {
|
||||||
session.getGeyser().getLogger().debug("Not sending translated command suggestions as they are disabled.");
|
session.getGeyser().getLogger().debug("Not sending translated command suggestions as they are disabled.");
|
||||||
|
|
||||||
// Send an empty packet so Bedrock doesn't override /help with its own, built-in help command.
|
// Send an empty packet so Bedrock doesn't override /help with its own, built-in help command.
|
||||||
|
@ -39,7 +39,7 @@ public class JavaKeepAliveTranslator extends PacketTranslator<ClientboundKeepAli
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void translate(GeyserSession session, ClientboundKeepAlivePacket packet) {
|
public void translate(GeyserSession session, ClientboundKeepAlivePacket packet) {
|
||||||
if (!session.getGeyser().getConfig().isForwardPlayerPing()) {
|
if (!session.getGeyser().config().forwardPlayerPing()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// We use this once the client replies (see BedrockNetworkStackLatencyTranslator)
|
// We use this once the client replies (see BedrockNetworkStackLatencyTranslator)
|
||||||
|
@ -132,7 +132,7 @@ public class JavaUpdateRecipesTranslator extends PacketTranslator<ClientboundUpd
|
|||||||
case STONECUTTING -> {
|
case STONECUTTING -> {
|
||||||
StoneCuttingRecipeData stoneCuttingData = (StoneCuttingRecipeData) recipe.getData();
|
StoneCuttingRecipeData stoneCuttingData = (StoneCuttingRecipeData) recipe.getData();
|
||||||
if (stoneCuttingData.getIngredient().getOptions().length == 0) {
|
if (stoneCuttingData.getIngredient().getOptions().length == 0) {
|
||||||
if (GeyserImpl.getInstance().getConfig().isDebugMode()) {
|
if (GeyserImpl.getInstance().config().debugMode()) {
|
||||||
GeyserImpl.getInstance().getLogger().debug("Received broken stone cutter recipe: " + stoneCuttingData + " " +
|
GeyserImpl.getInstance().getLogger().debug("Received broken stone cutter recipe: " + stoneCuttingData + " " +
|
||||||
recipe.getIdentifier() + " " + Registries.JAVA_ITEMS.get().get(stoneCuttingData.getResult().getId()).javaIdentifier());
|
recipe.getIdentifier() + " " + Registries.JAVA_ITEMS.get().get(stoneCuttingData.getResult().getId()).javaIdentifier());
|
||||||
}
|
}
|
||||||
|
@ -45,7 +45,7 @@ public class JavaSetEntityDataTranslator extends PacketTranslator<ClientboundSet
|
|||||||
EntityDefinition<?> definition = entity.getDefinition();
|
EntityDefinition<?> definition = entity.getDefinition();
|
||||||
for (EntityMetadata<?, ?> metadata : packet.getMetadata()) {
|
for (EntityMetadata<?, ?> metadata : packet.getMetadata()) {
|
||||||
if (metadata.getId() >= definition.translators().size()) {
|
if (metadata.getId() >= definition.translators().size()) {
|
||||||
if (session.getGeyser().getConfig().isDebugMode()) {
|
if (session.getGeyser().config().debugMode()) {
|
||||||
// Minecraft client just ignores these
|
// Minecraft client just ignores these
|
||||||
session.getGeyser().getLogger().warning("Metadata ID " + metadata.getId() + " is out of bounds of known entity metadata size " + definition.translators().size() + " for entity type " + entity.getDefinition().entityType());
|
session.getGeyser().getLogger().warning("Metadata ID " + metadata.getId() + " is out of bounds of known entity metadata size " + definition.translators().size() + " for entity type " + entity.getDefinition().entityType());
|
||||||
session.getGeyser().getLogger().debug(metadata.toString());
|
session.getGeyser().getLogger().debug(metadata.toString());
|
||||||
|
@ -91,7 +91,7 @@ public class JavaPlayerPositionTranslator extends PacketTranslator<ClientboundPl
|
|||||||
|
|
||||||
ChunkUtils.updateChunkPosition(session, pos.toInt());
|
ChunkUtils.updateChunkPosition(session, pos.toInt());
|
||||||
|
|
||||||
if (session.getGeyser().getConfig().isDebugMode()) {
|
if (session.getGeyser().config().debugMode()) {
|
||||||
session.getGeyser().getLogger().debug("Spawned player at " + packet.getX() + " " + packet.getY() + " " + packet.getZ());
|
session.getGeyser().getLogger().debug("Spawned player at " + packet.getX() + " " + packet.getY() + " " + packet.getZ());
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
@ -357,7 +357,7 @@ public class MessageTranslator {
|
|||||||
textPacket.setMessage(MessageTranslator.convertMessage(withDecoration.build(), session.locale()));
|
textPacket.setMessage(MessageTranslator.convertMessage(withDecoration.build(), session.locale()));
|
||||||
} else {
|
} else {
|
||||||
session.getGeyser().getLogger().debug("Likely illegal chat type detection found.");
|
session.getGeyser().getLogger().debug("Likely illegal chat type detection found.");
|
||||||
if (session.getGeyser().getConfig().isDebugMode()) {
|
if (session.getGeyser().config().debugMode()) {
|
||||||
Thread.dumpStack();
|
Thread.dumpStack();
|
||||||
}
|
}
|
||||||
textPacket.setMessage(MessageTranslator.convertMessage(message, session.locale()));
|
textPacket.setMessage(MessageTranslator.convertMessage(message, session.locale()));
|
||||||
|
@ -38,22 +38,12 @@ import java.util.concurrent.TimeUnit;
|
|||||||
* Much of the work here is from the wonderful folks from <a href="https://github.com/ViaVersion/ViaRewind">ViaRewind</a>
|
* Much of the work here is from the wonderful folks from <a href="https://github.com/ViaVersion/ViaRewind">ViaRewind</a>
|
||||||
*/
|
*/
|
||||||
public class CooldownUtils {
|
public class CooldownUtils {
|
||||||
private static CooldownType DEFAULT_SHOW_COOLDOWN;
|
|
||||||
|
|
||||||
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. If the cooldown is not disabled, the sent type is the cooldownPreference in {@link PreferencesCache}
|
* 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
|
* @param session GeyserSession
|
||||||
*/
|
*/
|
||||||
public static void sendCooldown(GeyserSession session) {
|
public static void sendCooldown(GeyserSession session) {
|
||||||
if (DEFAULT_SHOW_COOLDOWN == CooldownType.DISABLED) return;
|
if (session.getGeyser().config().showCooldown() == CooldownType.DISABLED) return;
|
||||||
CooldownType sessionPreference = session.getPreferencesCache().getCooldownPreference();
|
CooldownType sessionPreference = session.getPreferencesCache().getCooldownPreference();
|
||||||
if (sessionPreference == CooldownType.DISABLED) return;
|
if (sessionPreference == CooldownType.DISABLED) return;
|
||||||
|
|
||||||
@ -161,10 +151,6 @@ public class CooldownUtils {
|
|||||||
* @return The converted CooldownType
|
* @return The converted CooldownType
|
||||||
*/
|
*/
|
||||||
public static CooldownType getByName(String name) {
|
public static CooldownType getByName(String name) {
|
||||||
if (name.equalsIgnoreCase("true")) { // Backwards config compatibility
|
|
||||||
return CooldownType.TITLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (CooldownType type : VALUES) {
|
for (CooldownType type : VALUES) {
|
||||||
if (type.name().equalsIgnoreCase(name)) {
|
if (type.name().equalsIgnoreCase(name)) {
|
||||||
return type;
|
return type;
|
||||||
|
@ -179,7 +179,7 @@ public class InventoryUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static boolean canStack(GeyserItemStack item1, GeyserItemStack item2) {
|
public static boolean canStack(GeyserItemStack item1, GeyserItemStack item2) {
|
||||||
if (GeyserImpl.getInstance().getConfig().isDebugMode())
|
if (GeyserImpl.getInstance().config().debugMode())
|
||||||
canStackDebug(item1, item2);
|
canStackDebug(item1, item2);
|
||||||
if (item1.isEmpty() || item2.isEmpty())
|
if (item1.isEmpty() || item2.isEmpty())
|
||||||
return false;
|
return false;
|
||||||
@ -231,7 +231,7 @@ public class InventoryUtils {
|
|||||||
|
|
||||||
private static ItemDefinition getUnusableSpaceBlockDefinition(int protocolVersion) {
|
private static ItemDefinition getUnusableSpaceBlockDefinition(int protocolVersion) {
|
||||||
ItemMappings mappings = Registries.ITEMS.forVersion(protocolVersion);
|
ItemMappings mappings = Registries.ITEMS.forVersion(protocolVersion);
|
||||||
String unusableSpaceBlock = GeyserImpl.getInstance().getConfig().getUnusableSpaceBlock();
|
String unusableSpaceBlock = GeyserImpl.getInstance().config().unusableSpaceBlock();
|
||||||
ItemDefinition itemDefinition = mappings.getDefinition(unusableSpaceBlock);
|
ItemDefinition itemDefinition = mappings.getDefinition(unusableSpaceBlock);
|
||||||
|
|
||||||
if (itemDefinition == null) {
|
if (itemDefinition == null) {
|
||||||
|
@ -48,6 +48,10 @@ public final class JsonUtils {
|
|||||||
return (JsonObject) new JsonParser().parse(new InputStreamReader(stream));
|
return (JsonObject) new JsonParser().parse(new InputStreamReader(stream));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static JsonObject parseJson(String s) {
|
||||||
|
return (JsonObject) new JsonParser().parse(s);
|
||||||
|
}
|
||||||
|
|
||||||
public static <T> T fromJson(InputStream stream, Type type) {
|
public static <T> T fromJson(InputStream stream, Type type) {
|
||||||
return GeyserImpl.GSON.fromJson(new InputStreamReader(stream), type);
|
return GeyserImpl.GSON.fromJson(new InputStreamReader(stream), type);
|
||||||
}
|
}
|
||||||
|
@ -25,9 +25,6 @@
|
|||||||
|
|
||||||
package org.geysermc.geyser.util;
|
package org.geysermc.geyser.util;
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
|
||||||
import com.fasterxml.jackson.databind.JsonNode;
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
||||||
import com.github.steveice10.mc.auth.service.MsaAuthenticationService;
|
import com.github.steveice10.mc.auth.service.MsaAuthenticationService;
|
||||||
import org.cloudburstmc.protocol.bedrock.packet.LoginPacket;
|
import org.cloudburstmc.protocol.bedrock.packet.LoginPacket;
|
||||||
import org.cloudburstmc.protocol.bedrock.packet.ServerToClientHandshakePacket;
|
import org.cloudburstmc.protocol.bedrock.packet.ServerToClientHandshakePacket;
|
||||||
@ -53,8 +50,6 @@ import java.util.List;
|
|||||||
import java.util.function.BiConsumer;
|
import java.util.function.BiConsumer;
|
||||||
|
|
||||||
public class LoginEncryptionUtils {
|
public class LoginEncryptionUtils {
|
||||||
private static final ObjectMapper JSON_MAPPER = new ObjectMapper().disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
|
|
||||||
|
|
||||||
private static boolean HAS_SENT_ENCRYPTION_MESSAGE = false;
|
private static boolean HAS_SENT_ENCRYPTION_MESSAGE = false;
|
||||||
|
|
||||||
public static void encryptPlayerConnection(GeyserSession session, LoginPacket loginPacket) {
|
public static void encryptPlayerConnection(GeyserSession session, LoginPacket loginPacket) {
|
||||||
@ -69,7 +64,7 @@ public class LoginEncryptionUtils {
|
|||||||
|
|
||||||
geyser.getLogger().debug(String.format("Is player data signed? %s", result.signed()));
|
geyser.getLogger().debug(String.format("Is player data signed? %s", result.signed()));
|
||||||
|
|
||||||
if (!result.signed() && !session.getGeyser().getConfig().isEnableProxyConnections()) {
|
if (!result.signed() && !session.getGeyser().config().enableProxyConnections()) {
|
||||||
session.disconnect(GeyserLocale.getLocaleStringLog("geyser.network.remote.invalid_xbox_account"));
|
session.disconnect(GeyserLocale.getLocaleStringLog("geyser.network.remote.invalid_xbox_account"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -85,8 +80,7 @@ public class LoginEncryptionUtils {
|
|||||||
throw new IllegalStateException("Client data isn't signed by the given chain data");
|
throw new IllegalStateException("Client data isn't signed by the given chain data");
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonNode clientDataJson = JSON_MAPPER.readTree(clientDataPayload);
|
BedrockClientData data = JsonUtils.fromJson(clientDataPayload, BedrockClientData.class);
|
||||||
BedrockClientData data = JSON_MAPPER.convertValue(clientDataJson, BedrockClientData.class);
|
|
||||||
data.setOriginalString(clientData);
|
data.setOriginalString(clientData);
|
||||||
session.setClientData(data);
|
session.setClientData(data);
|
||||||
|
|
||||||
@ -94,7 +88,7 @@ public class LoginEncryptionUtils {
|
|||||||
startEncryptionHandshake(session, identityPublicKey);
|
startEncryptionHandshake(session, identityPublicKey);
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
// An error can be thrown on older Java 8 versions about an invalid key
|
// An error can be thrown on older Java 8 versions about an invalid key
|
||||||
if (geyser.getConfig().isDebugMode()) {
|
if (geyser.config().debugMode()) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -213,7 +207,7 @@ public class LoginEncryptionUtils {
|
|||||||
.append("\n%xbox.signin.enterCode\n")
|
.append("\n%xbox.signin.enterCode\n")
|
||||||
.append(ChatColor.GREEN)
|
.append(ChatColor.GREEN)
|
||||||
.append(msCode.user_code);
|
.append(msCode.user_code);
|
||||||
int timeout = session.getGeyser().getConfig().getPendingAuthenticationTimeout();
|
int timeout = session.getGeyser().config().pendingAuthenticationTimeout();
|
||||||
if (timeout != 0) {
|
if (timeout != 0) {
|
||||||
message.append("\n\n")
|
message.append("\n\n")
|
||||||
.append(ChatColor.RESET)
|
.append(ChatColor.RESET)
|
||||||
|
@ -1,447 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2019-2022 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.geyser.util;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.JsonNode;
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
||||||
import com.fasterxml.jackson.databind.node.ArrayNode;
|
|
||||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
|
||||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
|
||||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
|
||||||
import org.geysermc.geyser.GeyserImpl;
|
|
||||||
|
|
||||||
import javax.net.ssl.HttpsURLConnection;
|
|
||||||
import java.io.ByteArrayOutputStream;
|
|
||||||
import java.io.DataOutputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.net.URL;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.concurrent.Callable;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import java.util.logging.Level;
|
|
||||||
import java.util.logging.Logger;
|
|
||||||
import java.util.zip.GZIPOutputStream;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* bStats collects some data for plugin authors.
|
|
||||||
* <p>
|
|
||||||
* Check out <a href="https://bStats.org/">bStats</a> to learn more about bStats!
|
|
||||||
*/
|
|
||||||
public class Metrics {
|
|
||||||
|
|
||||||
// The version of this bStats class
|
|
||||||
public static final int B_STATS_VERSION = 1;
|
|
||||||
|
|
||||||
// The url to which the data is sent
|
|
||||||
private static final String URL = "https://bStats.org/submitData/server-implementation";
|
|
||||||
|
|
||||||
// Should failed requests be logged?
|
|
||||||
private static boolean logFailedRequests = false;
|
|
||||||
|
|
||||||
// The logger for the failed requests
|
|
||||||
private static Logger logger = Logger.getLogger("bStats");
|
|
||||||
|
|
||||||
// The name of the server software
|
|
||||||
private final String name;
|
|
||||||
|
|
||||||
// The uuid of the server
|
|
||||||
private final String serverUUID;
|
|
||||||
|
|
||||||
// A list with all custom charts
|
|
||||||
private final List<CustomChart> charts = new ArrayList<>();
|
|
||||||
|
|
||||||
private final static ObjectMapper mapper = new ObjectMapper();
|
|
||||||
|
|
||||||
private final GeyserImpl geyser;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class constructor.
|
|
||||||
*
|
|
||||||
* @param geyser The Geyser instance
|
|
||||||
* @param name The name of the server software.
|
|
||||||
* @param serverUUID The uuid of the server.
|
|
||||||
* @param logFailedRequests Whether failed requests should be logged or not.
|
|
||||||
* @param logger The logger for the failed requests.
|
|
||||||
*/
|
|
||||||
public Metrics(GeyserImpl geyser, String name, String serverUUID, boolean logFailedRequests, Logger logger) {
|
|
||||||
this.geyser = geyser;
|
|
||||||
this.name = name;
|
|
||||||
this.serverUUID = serverUUID;
|
|
||||||
Metrics.logFailedRequests = logFailedRequests;
|
|
||||||
Metrics.logger = logger;
|
|
||||||
|
|
||||||
// Start submitting the data
|
|
||||||
startSubmitting();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a custom chart.
|
|
||||||
*
|
|
||||||
* @param chart The chart to add.
|
|
||||||
*/
|
|
||||||
public void addCustomChart(CustomChart chart) {
|
|
||||||
if (chart == null) {
|
|
||||||
throw new IllegalArgumentException("Chart cannot be null!");
|
|
||||||
}
|
|
||||||
charts.add(chart);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Starts the Scheduler which submits our data every 30 minutes.
|
|
||||||
*/
|
|
||||||
private void startSubmitting() {
|
|
||||||
geyser.getScheduledThread().scheduleAtFixedRate(this::submitData, 1, 30, TimeUnit.MINUTES);
|
|
||||||
// Submit the data every 30 minutes, first time after 1 minutes to give other plugins enough time to start
|
|
||||||
// WARNING: Changing the frequency has no effect but your plugin WILL be blocked/deleted!
|
|
||||||
// WARNING: Just don't do it!
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the plugin specific data.
|
|
||||||
*
|
|
||||||
* @return The plugin specific data.
|
|
||||||
*/
|
|
||||||
private ObjectNode getPluginData() {
|
|
||||||
ObjectNode data = mapper.createObjectNode();
|
|
||||||
|
|
||||||
data.put("pluginName", name); // Append the name of the server software
|
|
||||||
data.put("pluginVersion", GeyserImpl.VERSION); // Append the name of the server software
|
|
||||||
|
|
||||||
ArrayNode customCharts = mapper.createArrayNode();
|
|
||||||
for (CustomChart customChart : charts) {
|
|
||||||
// Add the data of the custom charts
|
|
||||||
JsonNode chart = customChart.getRequestJsonNode();
|
|
||||||
if (chart == null) { // If the chart is null, we skip it
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
customCharts.add(chart);
|
|
||||||
}
|
|
||||||
data.set("customCharts", customCharts);
|
|
||||||
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the server specific data.
|
|
||||||
*
|
|
||||||
* @return The server specific data.
|
|
||||||
*/
|
|
||||||
private ObjectNode getServerData() {
|
|
||||||
// OS specific data
|
|
||||||
String osName = System.getProperty("os.name");
|
|
||||||
String osArch = System.getProperty("os.arch");
|
|
||||||
String osVersion = System.getProperty("os.version");
|
|
||||||
int coreCount = Runtime.getRuntime().availableProcessors();
|
|
||||||
|
|
||||||
ObjectNode data = mapper.createObjectNode();
|
|
||||||
|
|
||||||
data.put("serverUUID", serverUUID);
|
|
||||||
|
|
||||||
data.put("osName", osName);
|
|
||||||
data.put("osArch", osArch);
|
|
||||||
data.put("osVersion", osVersion);
|
|
||||||
data.put("coreCount", coreCount);
|
|
||||||
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Collects the data and sends it afterwards.
|
|
||||||
*/
|
|
||||||
private void submitData() {
|
|
||||||
final ObjectNode data = getServerData();
|
|
||||||
|
|
||||||
ArrayNode pluginData = mapper.createArrayNode();
|
|
||||||
pluginData.add(getPluginData());
|
|
||||||
data.putPOJO("plugins", pluginData);
|
|
||||||
|
|
||||||
new Thread(() -> {
|
|
||||||
try {
|
|
||||||
// We are still in the Thread of the timer, so nothing get blocked :)
|
|
||||||
sendData(data);
|
|
||||||
} catch (Exception e) {
|
|
||||||
// Something went wrong! :(
|
|
||||||
if (logFailedRequests) {
|
|
||||||
logger.log(Level.WARNING, "Could not submit stats of " + name, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}).start();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sends the data to the bStats server.
|
|
||||||
*
|
|
||||||
* @param data The data to send.
|
|
||||||
* @throws Exception If the request failed.
|
|
||||||
*/
|
|
||||||
private static void sendData(ObjectNode data) throws Exception {
|
|
||||||
if (data == null) {
|
|
||||||
throw new IllegalArgumentException("Data cannot be null!");
|
|
||||||
}
|
|
||||||
HttpsURLConnection connection = (HttpsURLConnection) new URL(URL).openConnection();
|
|
||||||
|
|
||||||
// Compress the data to save bandwidth
|
|
||||||
byte[] compressedData = compress(data.toString());
|
|
||||||
|
|
||||||
// Add headers
|
|
||||||
connection.setRequestMethod("POST");
|
|
||||||
connection.addRequestProperty("Accept", "application/json");
|
|
||||||
connection.addRequestProperty("Connection", "close");
|
|
||||||
connection.addRequestProperty("Content-Encoding", "gzip"); // We gzip our request
|
|
||||||
connection.addRequestProperty("Content-Length", String.valueOf(compressedData.length));
|
|
||||||
connection.setRequestProperty("Content-Type", "application/json"); // We send our data in JSON format
|
|
||||||
connection.setRequestProperty("User-Agent", "MC-Server/" + B_STATS_VERSION);
|
|
||||||
|
|
||||||
// Send data
|
|
||||||
connection.setDoOutput(true);
|
|
||||||
DataOutputStream outputStream = new DataOutputStream(connection.getOutputStream());
|
|
||||||
outputStream.write(compressedData);
|
|
||||||
outputStream.flush();
|
|
||||||
outputStream.close();
|
|
||||||
|
|
||||||
connection.getInputStream().close(); // We don't care about the response - Just send our data :)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gzips the given String.
|
|
||||||
*
|
|
||||||
* @param str The string to gzip.
|
|
||||||
* @return The gzipped String.
|
|
||||||
* @throws IOException If the compression failed.
|
|
||||||
*/
|
|
||||||
private static byte @NonNull [] compress(final @NonNull String str) throws IOException {
|
|
||||||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
|
||||||
GZIPOutputStream gzip = new GZIPOutputStream(outputStream);
|
|
||||||
gzip.write(str.getBytes(StandardCharsets.UTF_8));
|
|
||||||
gzip.close();
|
|
||||||
return outputStream.toByteArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents a custom chart.
|
|
||||||
*/
|
|
||||||
public static abstract class CustomChart {
|
|
||||||
|
|
||||||
// The id of the chart
|
|
||||||
final String chartId;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class constructor.
|
|
||||||
*
|
|
||||||
* @param chartId The id of the chart.
|
|
||||||
*/
|
|
||||||
CustomChart(String chartId) {
|
|
||||||
if (chartId == null || chartId.isEmpty()) {
|
|
||||||
throw new IllegalArgumentException("ChartId cannot be null or empty!");
|
|
||||||
}
|
|
||||||
this.chartId = chartId;
|
|
||||||
}
|
|
||||||
|
|
||||||
private @Nullable ObjectNode getRequestJsonNode() {
|
|
||||||
ObjectNode chart = new ObjectMapper().createObjectNode();
|
|
||||||
chart.put("chartId", chartId);
|
|
||||||
try {
|
|
||||||
ObjectNode data = getChartData();
|
|
||||||
if (data == null) {
|
|
||||||
// If the data is null we don't send the chart.
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
chart.putPOJO("data", data);
|
|
||||||
} catch (Throwable t) {
|
|
||||||
if (logFailedRequests) {
|
|
||||||
logger.log(Level.WARNING, "Failed to get data for custom chart with id " + chartId, t);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return chart;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
protected abstract ObjectNode getChartData() throws Exception;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents a custom simple pie.
|
|
||||||
*/
|
|
||||||
public static class SimplePie extends CustomChart {
|
|
||||||
|
|
||||||
private final Callable<String> callable;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class constructor.
|
|
||||||
*
|
|
||||||
* @param chartId The id of the chart.
|
|
||||||
* @param callable The callable which is used to request the chart data.
|
|
||||||
*/
|
|
||||||
public SimplePie(String chartId, Callable<String> callable) {
|
|
||||||
super(chartId);
|
|
||||||
this.callable = callable;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected @Nullable ObjectNode getChartData() throws Exception {
|
|
||||||
ObjectNode data = mapper.createObjectNode();
|
|
||||||
String value = callable.call();
|
|
||||||
if (value == null || value.isEmpty()) {
|
|
||||||
// Null = skip the chart
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
data.put("value", value);
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents a custom advanced pie.
|
|
||||||
*/
|
|
||||||
public static class AdvancedPie extends CustomChart {
|
|
||||||
|
|
||||||
private final Callable<Map<String, Integer>> callable;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class constructor.
|
|
||||||
*
|
|
||||||
* @param chartId The id of the chart.
|
|
||||||
* @param callable The callable which is used to request the chart data.
|
|
||||||
*/
|
|
||||||
public AdvancedPie(String chartId, Callable<Map<String, Integer>> callable) {
|
|
||||||
super(chartId);
|
|
||||||
this.callable = callable;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected @Nullable ObjectNode getChartData() throws Exception {
|
|
||||||
ObjectNode data = mapper.createObjectNode();
|
|
||||||
ObjectNode values = mapper.createObjectNode();
|
|
||||||
Map<String, Integer> map = callable.call();
|
|
||||||
if (map == null || map.isEmpty()) {
|
|
||||||
// Null = skip the chart
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
boolean allSkipped = true;
|
|
||||||
for (Map.Entry<String, Integer> entry : map.entrySet()) {
|
|
||||||
if (entry.getValue() == 0) {
|
|
||||||
continue; // Skip this invalid
|
|
||||||
}
|
|
||||||
allSkipped = false;
|
|
||||||
values.put(entry.getKey(), entry.getValue());
|
|
||||||
}
|
|
||||||
if (allSkipped) {
|
|
||||||
// Null = skip the chart
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
data.putPOJO("values", values);
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents a custom drilldown pie.
|
|
||||||
*/
|
|
||||||
public static class DrilldownPie extends CustomChart {
|
|
||||||
|
|
||||||
private final Callable<Map<String, Map<String, Integer>>> callable;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class constructor.
|
|
||||||
*
|
|
||||||
* @param chartId The id of the chart.
|
|
||||||
* @param callable The callable which is used to request the chart data.
|
|
||||||
*/
|
|
||||||
public DrilldownPie(String chartId, Callable<Map<String, Map<String, Integer>>> callable) {
|
|
||||||
super(chartId);
|
|
||||||
this.callable = callable;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @Nullable ObjectNode getChartData() throws Exception {
|
|
||||||
ObjectNode data = mapper.createObjectNode();
|
|
||||||
ObjectNode values = mapper.createObjectNode();
|
|
||||||
Map<String, Map<String, Integer>> map = callable.call();
|
|
||||||
if (map == null || map.isEmpty()) {
|
|
||||||
// Null = skip the chart
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
boolean reallyAllSkipped = true;
|
|
||||||
for (Map.Entry<String, Map<String, Integer>> entryValues : map.entrySet()) {
|
|
||||||
ObjectNode value = mapper.createObjectNode();
|
|
||||||
boolean allSkipped = true;
|
|
||||||
for (Map.Entry<String, Integer> valueEntry : map.get(entryValues.getKey()).entrySet()) {
|
|
||||||
value.put(valueEntry.getKey(), valueEntry.getValue());
|
|
||||||
allSkipped = false;
|
|
||||||
}
|
|
||||||
if (!allSkipped) {
|
|
||||||
reallyAllSkipped = false;
|
|
||||||
values.putPOJO(entryValues.getKey(), value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (reallyAllSkipped) {
|
|
||||||
// Null = skip the chart
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
data.putPOJO("values", values);
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents a custom single line chart.
|
|
||||||
*/
|
|
||||||
public static class SingleLineChart extends CustomChart {
|
|
||||||
|
|
||||||
private final Callable<Integer> callable;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class constructor.
|
|
||||||
*
|
|
||||||
* @param chartId The id of the chart.
|
|
||||||
* @param callable The callable which is used to request the chart data.
|
|
||||||
*/
|
|
||||||
public SingleLineChart(String chartId, Callable<Integer> callable) {
|
|
||||||
super(chartId);
|
|
||||||
this.callable = callable;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected @Nullable ObjectNode getChartData() throws Exception {
|
|
||||||
ObjectNode data = mapper.createObjectNode();
|
|
||||||
int value = callable.call();
|
|
||||||
if (value == 0) {
|
|
||||||
// Null = skip the chart
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
data.put("value", value);
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -51,8 +51,8 @@ public class SettingsUtils {
|
|||||||
|
|
||||||
// Let's store these to avoid issues
|
// Let's store these to avoid issues
|
||||||
boolean showCoordinates = session.getPreferencesCache().isAllowShowCoordinates();
|
boolean showCoordinates = session.getPreferencesCache().isAllowShowCoordinates();
|
||||||
boolean cooldownShown = CooldownUtils.getDefaultShowCooldown() != CooldownUtils.CooldownType.DISABLED;
|
boolean cooldownShown = session.getGeyser().config().showCooldown() != CooldownUtils.CooldownType.DISABLED;
|
||||||
boolean customSkulls = session.getGeyser().getConfig().isAllowCustomSkulls();
|
boolean customSkulls = session.getGeyser().config().allowCustomSkulls();
|
||||||
|
|
||||||
// Only show the client title if any of the client settings are available
|
// Only show the client title if any of the client settings are available
|
||||||
boolean showClientSettings = showCoordinates || cooldownShown || customSkulls;
|
boolean showClientSettings = showCoordinates || cooldownShown || customSkulls;
|
||||||
|
@ -199,7 +199,7 @@ public class WebUtils {
|
|||||||
return ((String) attr.get(0)).split(" ");
|
return ((String) attr.get(0)).split(" ");
|
||||||
}
|
}
|
||||||
} catch (Exception | NoClassDefFoundError ex) { // Check for a NoClassDefFoundError to prevent Android crashes
|
} catch (Exception | NoClassDefFoundError ex) { // Check for a NoClassDefFoundError to prevent Android crashes
|
||||||
if (geyser.getConfig().isDebugMode()) {
|
if (geyser.config().debugMode()) {
|
||||||
geyser.getLogger().debug("Exception while trying to find an SRV record for the remote host.");
|
geyser.getLogger().debug("Exception while trying to find an SRV record for the remote host.");
|
||||||
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
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
[versions]
|
[versions]
|
||||||
base-api = "1.0.0-SNAPSHOT"
|
base-api = "1.0.0-SNAPSHOT"
|
||||||
|
bstats = "3.0.2"
|
||||||
cumulus = "1.1.2"
|
cumulus = "1.1.2"
|
||||||
configurate = "4.2.0-GeyserMC-SNAPSHOT"
|
configurate = "4.2.0-GeyserMC-SNAPSHOT"
|
||||||
erosion = "1.1-20240515.191456-1"
|
erosion = "1.1-20240515.191456-1"
|
||||||
@ -130,6 +131,8 @@ protocol-connection = { group = "org.cloudburstmc.protocol", name = "bedrock-con
|
|||||||
|
|
||||||
math = { group = "org.cloudburstmc.math", name = "immutable", version = "2.0" }
|
math = { group = "org.cloudburstmc.math", name = "immutable", version = "2.0" }
|
||||||
|
|
||||||
|
bstats = { group = "org.bstats", name = "bstats-base", version.ref = "bstats"}
|
||||||
|
|
||||||
# plugins
|
# plugins
|
||||||
indra = { group = "net.kyori", name = "indra-common", version.ref = "indra" }
|
indra = { group = "net.kyori", name = "indra-common", version.ref = "indra" }
|
||||||
shadow = { group = "com.github.johnrengelman", name = "shadow", version.ref = "shadow" }
|
shadow = { group = "com.github.johnrengelman", name = "shadow", version.ref = "shadow" }
|
||||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren