Config class with utf-8 works in 1.12 but not in 1.8?

Discussion in 'Spigot Plugin Development' started by sumsar1812, Jul 3, 2018.

  1. Hi,

    So I got this class to handle custom configs, i basicly just followed this: https://bukkit.gamepedia.com/Configuration_API_Reference

    Made a few modifications so I could use the same class for the creating new configs and ended up with this:

    Code (Java):
    public class ConfigHandler {
        JavaPlugin main;
        File configFile = null;
        private FileConfiguration config = null;
        private String configName = "";

        public ConfigHandler(JavaPlugin mn, String configName) {
            this.configName = configName;
            main = mn;
            try {
                createConfigIfNotExists(configName);
            } catch (IOException e) {
                e.printStackTrace();
            }
            reloadCustomConfig();
        }

        public void reloadCustomConfig() {
            if (configFile == null) {
                configFile = new File(getDataFolder(), configName);
            }
            config = YamlConfiguration.loadConfiguration(configFile);
            // Look for defaults in the jar
            YamlConfiguration defConfig;
            try {
                defConfig = YamlConfiguration.loadConfiguration(new InputStreamReader(new FileInputStream(configFile), "UTF8"));
                config.setDefaults(defConfig);
            } catch (UnsupportedEncodingException | FileNotFoundException e) {
                e.printStackTrace();
            }

        }

        private FileConfiguration getConfig() {
            if (config == null) {
                reloadCustomConfig();
            }
            return config;
        }
        public void saveConfig() {
            if (config == null || config == null) {
                return;
            }
            try {
                getConfig().save(configFile);
            } catch (IOException ex) {
                main.getLogger().log(Level.SEVERE, "Could not save config to " + configFile, ex);
            }
        }
        private void saveDefaultConfig() {
            if (configFile == null) {
                configFile = new File(getDataFolder(), configName);
            }
            if (!configFile.exists()) {
                main.saveResource(configName, false);
            }
        }
        public Integer getInt(String key, boolean isLog) {
            if (getConfig().contains(key))
                return getConfig().getInt(key);
            if (isLog)
                main.getLogger().info("Could not locate " + key + " in the config.yml inside of the " + main.getName()
                        + " folder! (Try generating a new one by deleting the current)");
            return null;
        }
        public Double getDouble(String key) {
            return getDouble(key,true);
        }
        public Double getDouble(String key, boolean isLog) {
            if (getConfig().contains(key))
                return getConfig().getDouble(key);
            if (isLog)
                main.getLogger().info("Could not locate " + key + " in the config.yml inside of the " + main.getName()
                        + " folder! (Try generating a new one by deleting the current)");
            return null;
        }
        public Boolean getBoolean(String key) {
            if (getConfig().contains(key))
                return getConfig().getBoolean(key);
            main.getLogger().info("Could not locate " + key + " in the config.yml inside of the " + main.getName()
                    + " folder! (Try generating a new one by deleting the current)");
            return null;
        }

        public String getString(String key) {
            return (getString(key,true));
        }
        public String getString(String key, Boolean logOn) {
            if (getConfig().contains(key)) {
                return ChatColor.translateAlternateColorCodes('&',getConfig().getString(key));
            }
            if (logOn) {
                main.getLogger().info("Could not locate " + key + " in the config.yml inside of the " + main.getName()
                        + " folder! (Try generating a new one by deleting the current)");
            }
            return null;
        }

        public List<String> getStringList(String key, Boolean isLog) {
            if (getConfig().contains(key))
                return getConfig().getStringList(key);
            if (isLog)
                main.getLogger().info("Could not locate " + key + " in the config.yml inside of the " + main.getName()
                        + " folder! (Try generating a new one by deleting the current)");
            return null;
        }

        public ConfigurationSection getConfigSection(String path) {
            return getConfig().getConfigurationSection(path);
        }

        public void createConfigIfNotExists(String configName) throws IOException {
            File pluginFolder = new File("plugins" + System.getProperty("file.separator") + main.getName());
            if (pluginFolder.exists() == false) {
                pluginFolder.mkdir();
            }

            File configFile = new File("plugins" + System.getProperty("file.separator") + main.getName()
                    + System.getProperty("file.separator") + configName);
            if (configFile.exists() == false) {
                main.getLogger().info("No config file found! Creating new one...");
                saveDefaultConfig();
            }
            try {
                main.getLogger().info("Loading the config file...");
                getConfig().load(configFile);

            } catch (Exception e) {
                main.getLogger().severe(
                        "Could not load the config file! You need to regenerate the config! Error: " + e.getMessage());
                e.printStackTrace();
            }
        }

        private String getDataFolder() {
            return "plugins" + System.getProperty("file.separator") + main.getName() + System.getProperty("file.separator");
        }
    Reading from the config "works" in all versions I have tested but I can't read utf-8 characters (in this case æ ø å) on a 1.8 minecraft server but it does however work on a 1.12 server, anyone have an idea to why this is ?
     
  2. Inb4 all the replies that'll say something along the lines of "That's what'll happen when you use a 4-year-old version that isn't actively supported."
    (really though many small bugs like this exist in 1.8 versions of spigot, I'd recommend updating your server past it).
     
    • Like Like x 1
  3. Because 1.8 sucks. Update your server and drop support for 1.8 like the rest of us.
     
  4. I use this class for UTFConfigs

    Code (Java):
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.OutputStreamWriter;
    import java.io.Writer;
    import java.lang.reflect.Field;
    import java.lang.reflect.Modifier;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.logging.Level;

    import org.apache.commons.lang.Validate;
    import org.bukkit.Bukkit;
    import org.bukkit.configuration.InvalidConfigurationException;
    import org.bukkit.configuration.file.YamlConfiguration;
    import org.bukkit.craftbukkit.libs.jline.internal.InputStreamReader;
    import org.bukkit.entity.Player;
    import org.yaml.snakeyaml.DumperOptions;
    import org.yaml.snakeyaml.Yaml;
    import org.yaml.snakeyaml.representer.Representer;

    import com.google.common.base.Charsets;
    import com.google.common.io.Files;

    public class UTFConfig extends YamlConfiguration {

        public UTFConfig(File file) {
            try {
                load(file);
            } catch (IOException | InvalidConfigurationException e) {
                Bukkit.getLogger().log(Level.SEVERE, "Could not load Configuration " + file.getName(), e);
            }
        }

        @Override
        public void save(File file) throws IOException {
            Validate.notNull(file, "File can't be null");
            Files.createParentDirs(file);
            String data = this.saveToString();
            Writer writer = new OutputStreamWriter(new FileOutputStream(file), Charsets.UTF_8);

            try {
                writer.write(data);
            } finally {writer.close();}
        }

        @Override
        public String saveToString() {
            try {
                Field optionField = Reflections.getField(getClass(), "yamlOptions");
                Field representerField = Reflections.getField(getClass(), "yamlRepresenter");
                Field yamlField = Reflections.getField(getClass(), "yaml");

                if(optionField != null && representerField != null && yamlField != null) {
                    optionField.setAccessible(true);
                    representerField.setAccessible(true);
                    yamlField.setAccessible(true);

                    DumperOptions yamlOptions = (DumperOptions) optionField.get(this);
                    Representer yamlRepresenter = (Representer) representerField.get(this);
                    Yaml yaml = (Yaml) yamlField.get(this);
                    DumperOptions.FlowStyle flow = DumperOptions.FlowStyle.BLOCK;

                    yamlOptions.setIndent(this.options().indent());
                    yamlOptions.setDefaultFlowStyle(flow);
                    yamlOptions.setAllowUnicode(true);
                    yamlRepresenter.setDefaultFlowStyle(flow);

                    String header = this.buildHeader();
                    String dump = yaml.dump(this.getValues(false));

                    if(dump.equals("{}\n"))dump = "";
                    return header + dump;
                }
            } catch (Exception e) {
                Bukkit.getLogger().log(Level.SEVERE, "Error in converting Configuration to String", e);
            }
            return "Error: Cannot be saved to String";
        }

        @Override
        public void load(File file) throws IOException, InvalidConfigurationException {
            Validate.notNull(file, "File can't be null");
            this.load(new InputStreamReader(new FileInputStream(file), Charsets.UTF_8));
        }

        public static class Reflections {

            public static final Field modifiers = getField( Field.class, "modifiers" );

            public Reflections() {
                setAccessible( true, modifiers );
            }

            public Class< ? > getNMSClass( String name ) {
                String version = Bukkit.getServer().getClass().getPackage().getName().split( "\\." )[ 3 ];
                try {
                    return Class.forName( "net.minecraft.server." + version + "." + name );
                } catch ( Exception e ) {
                    return null;
                }
            }

            public Class< ? > getBukkitClass( String name ) {
                try {
                    String version = Bukkit.getServer().getClass().getPackage().getName().split( "\\." )[ 3 ];
                    return Class.forName( "org.bukkit.craftbukkit." + version + "." + name );
                } catch( Exception ex ) {
                    return null;
                }
            }

            public void sendPacket( Player to, Object packet ) {
                try {
                    Object playerHandle = to.getClass().getMethod( "getHandle" ).invoke( to );
                    Object playerConnection = playerHandle.getClass().getField( "playerConnection" ).get( playerHandle );
                    playerConnection.getClass().getMethod( "sendPacket", getNMSClass( "Packet" ) ).invoke( playerConnection, packet );
                } catch ( Exception e ) {
                    Bukkit.getLogger().log(Level.INFO, "Could not send Packet to Player " + to.getName(), e);
                }
            }

            public void setField( Object change, String name, Object to ) {
                try {
                    Field field = getField( change.getClass(), name );
                    if(field != null) {
                        setAccessible( true, field );
                        field.set( change, to );
                        setAccessible( false, field);
                    }
                } catch( Exception ex ) {
                    Bukkit.getLogger().log(Level.SEVERE, "Could not set Value " + to.getClass().getName() + " in Field " + name + " in Class " + change.getClass().getName(), ex);
                }
            }

            public static void setAccessible( boolean state, Field... fields ) {
                try {
                    for( Field field : fields ) {
                        field.setAccessible( state );
                        if( Modifier.isFinal( field.getModifiers() ) ) {
                            field.setAccessible(true);
                            modifiers.set( field, field.getModifiers() & ~Modifier.FINAL );
                        }
                    }
                } catch( Exception ex ) {
                    Bukkit.getLogger().log(Level.WARNING, "Could not set Fields accessible", ex);
                }
            }

            public static Field getField( Class< ? > clazz, String name ) {
                Field field = null;
                for( Field f : getFields( clazz ) ) {
                    if(f.getName().equals( name )) field = f;
                }
                return field;
            }

            public static List< Field > getFields( Class< ? > clazz ) {
                List< Field > buf = new ArrayList<>();

                do {
                    try {
                        for( Field f : clazz.getDeclaredFields() )
                          buf.add( f );
                    } catch( Exception ex ) {}
                } while( ( clazz = clazz.getSuperclass() ) != null );

                return buf;
            }

            public String getVersion() {
                return Bukkit.getServer().getClass().getPackage().getName().split( "\\." )[ 3 ];
            }
        }
    }