193 lines
7.2 KiB
Java
193 lines
7.2 KiB
Java
/*
|
|
* Minecraft Forge
|
|
* Copyright (c) 2016-2018.
|
|
*
|
|
* This library 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 version 2.1
|
|
* of the License.
|
|
*
|
|
* This library 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 this library; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
|
|
package net.minecraftforge.fml.common.discovery.json;
|
|
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.function.Function;
|
|
|
|
import org.objectweb.asm.Type;
|
|
|
|
import com.google.common.base.MoreObjects;
|
|
import com.google.common.collect.Lists;
|
|
import com.google.common.collect.Maps;
|
|
|
|
import net.minecraftforge.fml.common.FMLLog;
|
|
import net.minecraftforge.fml.loading.moddiscovery.ModAnnotation.EnumHolder;
|
|
|
|
//Package private, modders shouldn't access this. Do it through ASMDataTable.
|
|
class ASMInfo
|
|
{
|
|
String name;
|
|
String[] interfaces;
|
|
List<Annotation> annotations;
|
|
private Map<Integer, Annotation> byID;
|
|
|
|
public Annotation getSubAnnotation(int id)
|
|
{
|
|
if (byID == null)
|
|
{
|
|
byID = Maps.newHashMap();
|
|
annotations.forEach(a -> { if (a.id != null) byID.put(a.id, a); });
|
|
}
|
|
return byID.get(id);
|
|
}
|
|
|
|
@Override
|
|
public String toString()
|
|
{
|
|
return MoreObjects.toStringHelper("")
|
|
.add("name", name)
|
|
.add("itf", interfaces)
|
|
.add("ann", annotations)
|
|
.toString();
|
|
}
|
|
|
|
public enum TargetType { CLASS, FIELD, METHOD, SUBTYPE };
|
|
public enum ValueType
|
|
{
|
|
BOOL(Boolean::valueOf, v -> {boolean[] ret = new boolean[v.length]; for (int x = 0; x < v.length; x++) ret[x] = Boolean.parseBoolean(v[x]); return ret; }),
|
|
BYTE(Byte::valueOf, v -> {byte[] ret = new byte[v.length]; for (int x = 0; x < v.length; x++) ret[x] = Byte.parseByte(v[x]); return ret; }),
|
|
CHAR(x -> x.charAt(0), v -> {char[] ret = new char[v.length]; for (int x = 0; x < v.length; x++) ret[x] = v[x].charAt(0); return ret; }),
|
|
SHORT(Short::valueOf, v -> {short[] ret = new short[v.length]; for (int x = 0; x < v.length; x++) ret[x] = Short.parseShort(v[x]); return ret; }),
|
|
INT(Integer::valueOf, v -> {int[] ret = new int[v.length]; for (int x = 0; x < v.length; x++) ret[x] = Integer.parseInt(v[x]); return ret; }),
|
|
LONG(Long::valueOf, v -> {long[] ret = new long[v.length]; for (int x = 0; x < v.length; x++) ret[x] = Long.parseLong(v[x]); return ret; }),
|
|
FLOAT(Float::valueOf, v -> {float[] ret = new float[v.length]; for (int x = 0; x < v.length; x++) ret[x] = Float.parseFloat(v[x]); return ret; }),
|
|
DOUBLE(Double::valueOf, v -> {double[] ret = new double[v.length]; for (int x = 0; x < v.length; x++) ret[x] = Double.parseDouble(v[x]); return ret; }),
|
|
STRING(x -> x, x -> x),
|
|
CLASS(Type::getType, v -> {Type[] ret = new Type[v.length]; for (int x = 0; x < v.length; x++) ret[x] = Type.getType(v[x]); return ret; }),
|
|
ENUM(ValueType::getEnumHolder, v -> {List<EnumHolder> ret = Lists.newArrayList(); for (int x = 0; x < v.length; x++) ret.add(ValueType.getEnumHolder(v[x])); return ret; }),
|
|
ANNOTATION(null, null),
|
|
NULL(x -> null, x -> null);
|
|
|
|
public final Function<String, Object> single;
|
|
public final Function<String[], Object> array;
|
|
|
|
private ValueType(Function<String, Object> single, Function<String[], Object> array)
|
|
{
|
|
this.single = single;
|
|
this.array = array;
|
|
}
|
|
|
|
private static EnumHolder getEnumHolder(String value)
|
|
{
|
|
int idx = value.lastIndexOf('/');
|
|
if (idx <= 1)
|
|
throw new IllegalArgumentException("Can not create a EnumHolder for value: " + value);
|
|
String field = value.substring(idx + 1);
|
|
value = value.substring(0, idx);
|
|
idx = value.indexOf(';'); //Legacy internal name.
|
|
value = value.substring(1, idx);
|
|
return new EnumHolder(value, field);
|
|
}
|
|
};
|
|
|
|
static class Annotation
|
|
{
|
|
TargetType type;
|
|
String name;
|
|
String target;
|
|
Integer id;
|
|
ValueHolder value;
|
|
Map<String, ValueHolder> values;
|
|
private Map<String, Object> _values;
|
|
|
|
public Map<String, Object> getValues(ASMInfo pool)
|
|
{
|
|
if (_values == null)
|
|
{
|
|
_values = Maps.newHashMap();
|
|
if (values != null)
|
|
values.forEach((k, v) -> _values.put(k, v.get(pool)));
|
|
else
|
|
_values.put("value", value == null ? null : value.get(pool));
|
|
}
|
|
|
|
return _values;
|
|
}
|
|
|
|
@Override
|
|
public String toString()
|
|
{
|
|
return MoreObjects.toStringHelper("")
|
|
.add("type", type)
|
|
.add("name", name)
|
|
.add("target", target)
|
|
.add("id", id)
|
|
.add("value", value)
|
|
.toString();
|
|
}
|
|
}
|
|
|
|
static class ValueHolder
|
|
{
|
|
ValueType type;
|
|
String value;
|
|
String[] values;
|
|
|
|
private Object _value;
|
|
|
|
private ValueType getType()
|
|
{
|
|
return type == null ? ValueType.STRING : type;
|
|
}
|
|
|
|
public Object get(ASMInfo pool)
|
|
{
|
|
if (_value == null)
|
|
{
|
|
if (values != null)
|
|
{
|
|
if (type == ValueType.ANNOTATION)
|
|
{
|
|
List<Map<String, Object>> list = Lists.newArrayList();
|
|
_value = list;
|
|
|
|
for (String s : values)
|
|
{
|
|
Annotation sub = pool.getSubAnnotation(Integer.parseInt(s));
|
|
if (sub == null)
|
|
FMLLog.log.error("Invalid Sub-Annotation in Annotation JSON: " + s);
|
|
else
|
|
list.add(sub.getValues(pool));
|
|
}
|
|
}
|
|
else
|
|
_value = getType().array.apply(values);
|
|
}
|
|
else
|
|
{
|
|
if (type == ValueType.ANNOTATION)
|
|
{
|
|
Annotation sub = pool.getSubAnnotation(Integer.parseInt(value));
|
|
if (sub == null)
|
|
FMLLog.log.error("Invalid Sub-Annotation in Annotation JSON: " + value);
|
|
else
|
|
_value = sub.getValues(pool);
|
|
}
|
|
else
|
|
_value = getType().single.apply(value);
|
|
}
|
|
}
|
|
return _value;
|
|
}
|
|
}
|
|
}
|