Fix the scuffed usage of LinkedList and ArrayList for list setting types
This commit is contained in:
parent
498e4e2d6c
commit
0b8fa3ffe3
@ -18,6 +18,7 @@
|
|||||||
package baritone.api;
|
package baritone.api;
|
||||||
|
|
||||||
import baritone.api.utils.SettingsUtil;
|
import baritone.api.utils.SettingsUtil;
|
||||||
|
import baritone.api.utils.TypeUtils;
|
||||||
import net.minecraft.block.Block;
|
import net.minecraft.block.Block;
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.init.Blocks;
|
import net.minecraft.init.Blocks;
|
||||||
@ -27,6 +28,9 @@ import net.minecraft.util.text.ITextComponent;
|
|||||||
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
|
import java.lang.reflect.Parameter;
|
||||||
|
import java.lang.reflect.ParameterizedType;
|
||||||
|
import java.lang.reflect.Type;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
@ -150,7 +154,7 @@ public final class Settings {
|
|||||||
/**
|
/**
|
||||||
* Blocks that Baritone will attempt to avoid (Used in avoidance)
|
* Blocks that Baritone will attempt to avoid (Used in avoidance)
|
||||||
*/
|
*/
|
||||||
public final Setting<LinkedList<Block>> blocksToAvoid = new Setting<>(new LinkedList<>(Arrays.asList(
|
public final Setting<List<Block>> blocksToAvoid = new Setting<>(new ArrayList<>(Arrays.asList(
|
||||||
// Leave Empty by Default
|
// Leave Empty by Default
|
||||||
)));
|
)));
|
||||||
|
|
||||||
@ -789,11 +793,12 @@ public final class Settings {
|
|||||||
*/
|
*/
|
||||||
public final List<Setting<?>> allSettings;
|
public final List<Setting<?>> allSettings;
|
||||||
|
|
||||||
|
public final Map<Setting<?>, Type> settingTypes;
|
||||||
|
|
||||||
public final class Setting<T> {
|
public final class Setting<T> {
|
||||||
public T value;
|
public T value;
|
||||||
public final T defaultValue;
|
public final T defaultValue;
|
||||||
private String name;
|
private String name;
|
||||||
private final Class<T> klass;
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private Setting(T value) {
|
private Setting(T value) {
|
||||||
@ -802,7 +807,6 @@ public final class Settings {
|
|||||||
}
|
}
|
||||||
this.value = value;
|
this.value = value;
|
||||||
this.defaultValue = value;
|
this.defaultValue = value;
|
||||||
this.klass = (Class<T>) value.getClass();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -820,7 +824,8 @@ public final class Settings {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Class<T> getValueClass() {
|
public Class<T> getValueClass() {
|
||||||
return klass;
|
// noinspection unchecked
|
||||||
|
return (Class<T>) TypeUtils.resolveBaseClass(getType());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -834,14 +839,21 @@ public final class Settings {
|
|||||||
public void reset() {
|
public void reset() {
|
||||||
value = defaultValue;
|
value = defaultValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final Type getType() {
|
||||||
|
return settingTypes.get(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// here be dragons
|
// here be dragons
|
||||||
|
|
||||||
Settings() {
|
Settings() {
|
||||||
Field[] temp = getClass().getFields();
|
Field[] temp = getClass().getFields();
|
||||||
HashMap<String, Setting<?>> tmpByName = new HashMap<>();
|
|
||||||
List<Setting<?>> tmpAll = new ArrayList<>();
|
Map<String, Setting<?>> tmpByName = new HashMap<>();
|
||||||
|
List<Setting<?>> tmpAll = new ArrayList<>();
|
||||||
|
Map<Setting<?>, Type> tmpSettingTypes = new HashMap<>();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
for (Field field : temp) {
|
for (Field field : temp) {
|
||||||
if (field.getType().equals(Setting.class)) {
|
if (field.getType().equals(Setting.class)) {
|
||||||
@ -854,13 +866,15 @@ public final class Settings {
|
|||||||
}
|
}
|
||||||
tmpByName.put(name, setting);
|
tmpByName.put(name, setting);
|
||||||
tmpAll.add(setting);
|
tmpAll.add(setting);
|
||||||
|
tmpSettingTypes.put(setting, ((ParameterizedType) field.getGenericType()).getActualTypeArguments()[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (IllegalAccessException e) {
|
} catch (IllegalAccessException e) {
|
||||||
throw new IllegalStateException(e);
|
throw new IllegalStateException(e);
|
||||||
}
|
}
|
||||||
byLowerName = Collections.unmodifiableMap(tmpByName);
|
byLowerName = Collections.unmodifiableMap(tmpByName);
|
||||||
allSettings = Collections.unmodifiableList(tmpAll);
|
allSettings = Collections.unmodifiableList(tmpAll);
|
||||||
|
settingTypes = Collections.unmodifiableMap(tmpSettingTypes);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
|
@ -21,12 +21,13 @@ import baritone.api.Settings;
|
|||||||
import net.minecraft.block.Block;
|
import net.minecraft.block.Block;
|
||||||
import net.minecraft.item.Item;
|
import net.minecraft.item.Item;
|
||||||
import net.minecraft.util.EnumFacing;
|
import net.minecraft.util.EnumFacing;
|
||||||
import net.minecraft.util.ResourceLocation;
|
|
||||||
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.BufferedWriter;
|
import java.io.BufferedWriter;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.lang.reflect.ParameterizedType;
|
||||||
|
import java.lang.reflect.Type;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
@ -36,7 +37,6 @@ import java.util.function.Function;
|
|||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
|
||||||
|
|
||||||
import static net.minecraft.client.Minecraft.getMinecraft;
|
import static net.minecraft.client.Minecraft.getMinecraft;
|
||||||
|
|
||||||
@ -45,8 +45,6 @@ public class SettingsUtil {
|
|||||||
private static final Path SETTINGS_PATH = getMinecraft().gameDir.toPath().resolve("baritone").resolve("settings.txt");
|
private static final Path SETTINGS_PATH = getMinecraft().gameDir.toPath().resolve("baritone").resolve("settings.txt");
|
||||||
private static final Pattern SETTING_PATTERN = Pattern.compile("^(?<setting>[^ ]+) +(?<value>[^ ]+)"); // 2 words separated by spaces
|
private static final Pattern SETTING_PATTERN = Pattern.compile("^(?<setting>[^ ]+) +(?<value>[^ ]+)"); // 2 words separated by spaces
|
||||||
|
|
||||||
private static final Map<Class<?>, SettingsIO> map;
|
|
||||||
|
|
||||||
private static boolean isComment(String line) {
|
private static boolean isComment(String line) {
|
||||||
return line.startsWith("#") || line.startsWith("//");
|
return line.startsWith("#") || line.startsWith("//");
|
||||||
}
|
}
|
||||||
@ -120,11 +118,11 @@ public class SettingsUtil {
|
|||||||
if (setting.getName().equals("logger")) {
|
if (setting.getName().equals("logger")) {
|
||||||
return "logger";
|
return "logger";
|
||||||
}
|
}
|
||||||
SettingsIO io = map.get(setting.getValueClass());
|
Parser io = Parser.getParser(setting.getType());
|
||||||
if (io == null) {
|
if (io == null) {
|
||||||
throw new IllegalStateException("Missing " + setting.getValueClass() + " " + setting.getName());
|
throw new IllegalStateException("Missing " + setting.getValueClass() + " " + setting.getName());
|
||||||
}
|
}
|
||||||
return setting.getName() + " " + io.toString.apply(setting.value);
|
return setting.getName() + " " + io.toString(new ParserContext(setting), setting.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void parseAndApply(Settings settings, String settingName, String settingValue) throws IllegalStateException, NumberFormatException {
|
public static void parseAndApply(Settings settings, String settingName, String settingValue) throws IllegalStateException, NumberFormatException {
|
||||||
@ -133,47 +131,126 @@ public class SettingsUtil {
|
|||||||
throw new IllegalStateException("No setting by that name");
|
throw new IllegalStateException("No setting by that name");
|
||||||
}
|
}
|
||||||
Class intendedType = setting.getValueClass();
|
Class intendedType = setting.getValueClass();
|
||||||
SettingsIO ioMethod = map.get(intendedType);
|
Parser ioMethod = Parser.getParser(setting.getType());
|
||||||
Object parsed = ioMethod.parser.apply(settingValue);
|
Object parsed = ioMethod.parse(new ParserContext(setting), settingValue);
|
||||||
if (!intendedType.isInstance(parsed)) {
|
if (!intendedType.isInstance(parsed)) {
|
||||||
throw new IllegalStateException(ioMethod + " parser returned incorrect type, expected " + intendedType + " got " + parsed + " which is " + parsed.getClass());
|
throw new IllegalStateException(ioMethod + " parser returned incorrect type, expected " + intendedType + " got " + parsed + " which is " + parsed.getClass());
|
||||||
}
|
}
|
||||||
setting.value = parsed;
|
setting.value = parsed;
|
||||||
}
|
}
|
||||||
|
|
||||||
private enum SettingsIO {
|
private interface ISettingParser<T> {
|
||||||
|
|
||||||
|
T parse(ParserContext context, String raw);
|
||||||
|
|
||||||
|
String toString(ParserContext context, T value);
|
||||||
|
|
||||||
|
boolean accepts(Type type);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class ParserContext {
|
||||||
|
|
||||||
|
private final Settings.Setting<?> setting;
|
||||||
|
|
||||||
|
public ParserContext(Settings.Setting<?> setting) {
|
||||||
|
this.setting = setting;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Settings.Setting<?> getSetting() {
|
||||||
|
return this.setting;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private enum Parser implements ISettingParser {
|
||||||
|
|
||||||
DOUBLE(Double.class, Double::parseDouble),
|
DOUBLE(Double.class, Double::parseDouble),
|
||||||
BOOLEAN(Boolean.class, Boolean::parseBoolean),
|
BOOLEAN(Boolean.class, Boolean::parseBoolean),
|
||||||
INTEGER(Integer.class, Integer::parseInt),
|
INTEGER(Integer.class, Integer::parseInt),
|
||||||
FLOAT(Float.class, Float::parseFloat),
|
FLOAT(Float.class,Float::parseFloat),
|
||||||
LONG(Long.class, Long::parseLong),
|
LONG(Long.class, Long::parseLong),
|
||||||
|
ENUMFACING(EnumFacing.class, EnumFacing::byName),
|
||||||
|
COLOR(
|
||||||
|
Color.class,
|
||||||
|
str -> new Color(Integer.parseInt(str.split(",")[0]), Integer.parseInt(str.split(",")[1]), Integer.parseInt(str.split(",")[2])),
|
||||||
|
color -> color.getRed() + "," + color.getGreen() + "," + color.getBlue()
|
||||||
|
),
|
||||||
|
BLOCK(
|
||||||
|
Block.class,
|
||||||
|
str -> BlockUtils.stringToBlockRequired(str.trim()),
|
||||||
|
BlockUtils::blockToString
|
||||||
|
),
|
||||||
|
ITEM(
|
||||||
|
Item.class,
|
||||||
|
str -> Item.getByNameOrId(str.trim()),
|
||||||
|
item -> Item.REGISTRY.getNameForObject(item).toString()
|
||||||
|
),
|
||||||
|
LIST() {
|
||||||
|
|
||||||
BLOCK_LIST(LinkedList.class, str -> Stream.of(str.split(",")).map(String::trim).map(BlockUtils::stringToBlockRequired).collect(Collectors.toCollection(LinkedList::new)), list -> ((LinkedList<Block>) list).stream().map(BlockUtils::blockToString).collect(Collectors.joining(","))),
|
@Override
|
||||||
ITEM_LIST(ArrayList.class, str -> Stream.of(str.split(",")).map(String::trim).map(Item::getByNameOrId).collect(Collectors.toCollection(ArrayList::new)), list -> ((ArrayList<Item>) list).stream().map(Item.REGISTRY::getNameForObject).map(ResourceLocation::toString).collect(Collectors.joining(","))),
|
public Object parse(ParserContext context, String raw) {
|
||||||
COLOR(Color.class, str -> new Color(Integer.parseInt(str.split(",")[0]), Integer.parseInt(str.split(",")[1]), Integer.parseInt(str.split(",")[2])), color -> color.getRed() + "," + color.getGreen() + "," + color.getBlue()),
|
Type type = ((ParameterizedType) context.getSetting().getType()).getActualTypeArguments()[0];
|
||||||
ENUMFACING(EnumFacing.class, EnumFacing::byName);
|
Parser parser = Parser.getParser(type);
|
||||||
|
|
||||||
|
return Arrays.stream(raw.split(","))
|
||||||
|
.map(s -> parser.parse(context, s))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
Class<?> klass;
|
@Override
|
||||||
Function<String, Object> parser;
|
public String toString(ParserContext context, Object value) {
|
||||||
Function<Object, String> toString;
|
Type type = ((ParameterizedType) context.getSetting().getType()).getActualTypeArguments()[0];
|
||||||
|
Parser parser = Parser.getParser(type);
|
||||||
|
|
||||||
<T> SettingsIO(Class<T> klass, Function<String, T> parser) {
|
return ((List<?>) value).stream()
|
||||||
|
.map(o -> parser.toString(context, o))
|
||||||
|
.collect(Collectors.joining(","));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean accepts(Type type) {
|
||||||
|
return List.class.isAssignableFrom(TypeUtils.resolveBaseClass(type));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private final Class<?> klass;
|
||||||
|
private final Function<String, Object> parser;
|
||||||
|
private final Function<Object, String> toString;
|
||||||
|
|
||||||
|
Parser() {
|
||||||
|
this.klass = null;
|
||||||
|
this.parser = null;
|
||||||
|
this.toString = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
<T> Parser(Class<T> klass, Function<String, T> parser) {
|
||||||
this(klass, parser, Object::toString);
|
this(klass, parser, Object::toString);
|
||||||
}
|
}
|
||||||
|
|
||||||
<T> SettingsIO(Class<T> klass, Function<String, T> parser, Function<T, String> toString) {
|
<T> Parser(Class<T> klass, Function<String, T> parser, Function<T, String> toString) {
|
||||||
this.klass = klass;
|
this.klass = klass;
|
||||||
this.parser = parser::apply;
|
this.parser = parser::apply;
|
||||||
this.toString = x -> toString.apply((T) x);
|
this.toString = x -> toString.apply((T) x);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
static {
|
@Override
|
||||||
HashMap<Class<?>, SettingsIO> tempMap = new HashMap<>();
|
public Object parse(ParserContext context, String raw) {
|
||||||
for (SettingsIO type : SettingsIO.values()) {
|
return this.parser.apply(raw);
|
||||||
tempMap.put(type.klass, type);
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString(ParserContext context, Object value) {
|
||||||
|
return this.toString.apply(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean accepts(Type type) {
|
||||||
|
return type instanceof Class && this.klass.isAssignableFrom((Class) type);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Parser getParser(Type type) {
|
||||||
|
return Arrays.stream(values())
|
||||||
|
.filter(parser -> parser.accepts(type))
|
||||||
|
.findFirst().orElse(null);
|
||||||
}
|
}
|
||||||
map = Collections.unmodifiableMap(tempMap);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
44
src/api/java/baritone/api/utils/TypeUtils.java
Normal file
44
src/api/java/baritone/api/utils/TypeUtils.java
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of Baritone.
|
||||||
|
*
|
||||||
|
* Baritone is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Baritone is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package baritone.api.utils;
|
||||||
|
|
||||||
|
import java.lang.reflect.ParameterizedType;
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Brady
|
||||||
|
* @since 4/20/2019
|
||||||
|
*/
|
||||||
|
public final class TypeUtils {
|
||||||
|
|
||||||
|
private TypeUtils() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolves the "base type" for the specified type. For example, if the specified
|
||||||
|
* type is {@code List<String>}, then {@code List.class} will be returned. If the
|
||||||
|
* specified type is already a class, then it is directly returned.
|
||||||
|
*
|
||||||
|
* @param type The type to resolve
|
||||||
|
* @return The base class
|
||||||
|
*/
|
||||||
|
public static Class<?> resolveBaseClass(Type type) {
|
||||||
|
return type instanceof Class ? (Class<?>) type
|
||||||
|
: type instanceof ParameterizedType ? (Class<?>) ((ParameterizedType) type).getRawType()
|
||||||
|
: null;
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user