Make tag mutable

This commit is contained in:
Jesse Boyd 2018-08-03 12:51:07 +10:00
parent 12265521c8
commit 1c6097454f
No known key found for this signature in database
GPG Key ID: 59F1DE6293AF6E1F
3 changed files with 44 additions and 9 deletions

View File

@ -7,11 +7,8 @@ import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;
import java.util.ArrayList; import java.util.*;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import sun.reflect.ConstructorAccessor; import sun.reflect.ConstructorAccessor;
import sun.reflect.FieldAccessor; import sun.reflect.FieldAccessor;
import sun.reflect.ReflectionFactory; import sun.reflect.ReflectionFactory;
@ -28,6 +25,10 @@ public class ReflectionUtils {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public static <T extends Enum<?>> T addEnum(Class<T> enumType, String enumName) { public static <T extends Enum<?>> T addEnum(Class<T> enumType, String enumName) {
return addEnum(enumType, enumName, new Class<?>[]{} , new Object[]{});
}
public static <T extends Enum<?>> T addEnum(Class<T> enumType, String enumName, Class<?>[] additionalTypes, Object[] additionalValues) {
// 0. Sanity checks // 0. Sanity checks
if (!Enum.class.isAssignableFrom(enumType)) { if (!Enum.class.isAssignableFrom(enumType)) {
@ -54,8 +55,8 @@ public class ReflectionUtils {
T newValue = (T) makeEnum(enumType, // The target enum class T newValue = (T) makeEnum(enumType, // The target enum class
enumName, // THE NEW ENUM INSTANCE TO BE DYNAMICALLY ADDED enumName, // THE NEW ENUM INSTANCE TO BE DYNAMICALLY ADDED
values.size(), values.size(),
new Class<?>[]{}, // can be used to pass values to the enum constuctor additionalTypes, // can be used to pass values to the enum constuctor
new Object[]{}); // can be used to pass values to the enum constuctor additionalValues); // can be used to pass values to the enum constuctor
// 4. add new value // 4. add new value
values.add(newValue); values.add(newValue);
@ -73,6 +74,31 @@ public class ReflectionUtils {
} }
} }
public static <T extends Enum<?>> void clearEnum(Class<T> enumType) {
// 0. Sanity checks
if (!Enum.class.isAssignableFrom(enumType)) {
throw new RuntimeException("class " + enumType + " is not an instance of Enum");
}
// 1. Lookup "$VALUES" holder in enum class and get previous enum instances
Field valuesField = null;
Field[] fields = enumType.getDeclaredFields();
for (Field field : fields) {
if (field.getName().contains("$VALUES")) {
valuesField = field;
break;
}
}
AccessibleObject.setAccessible(new Field[]{valuesField}, true);
try {
setFailsafeFieldValue(valuesField, null, Array.newInstance(enumType, 0));
// 6. Clean enum cache
cleanEnumCache(enumType);
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e.getMessage(), e);
}
}
private static Object makeEnum(Class<?> enumClass, String value, int ordinal, private static Object makeEnum(Class<?> enumClass, String value, int ordinal,
Class<?>[] additionalTypes, Object[] additionalValues) throws Exception { Class<?>[] additionalTypes, Object[] additionalValues) throws Exception {
Object[] parms = new Object[additionalValues.length + 2]; Object[] parms = new Object[additionalValues.length + 2];
@ -134,9 +160,12 @@ public class ReflectionUtils {
blankField(enumClass, "enumConstants"); // IBM JDK blankField(enumClass, "enumConstants"); // IBM JDK
} }
private static Class<?> UNMODIFIABLE_MAP = Collections.unmodifiableMap(Collections.EMPTY_MAP).getClass();
public static <T, V> Map<T, V> getMap(Map<T, V> map) { public static <T, V> Map<T, V> getMap(Map<T, V> map) {
try { try {
Class<? extends Map> clazz = map.getClass(); Class<? extends Map> clazz = map.getClass();
if (clazz != UNMODIFIABLE_MAP) return map;
Field m = clazz.getDeclaredField("m"); Field m = clazz.getDeclaredField("m");
m.setAccessible(true); m.setAccessible(true);
return (Map<T, V>) m.get(map); return (Map<T, V>) m.get(map);

View File

@ -19,7 +19,7 @@ public final class CompoundTag extends Tag {
*/ */
public CompoundTag(Map<String, Tag> value) { public CompoundTag(Map<String, Tag> value) {
super(); super();
this.value = Collections.unmodifiableMap(value); this.value = value;
} }
@Override @Override

View File

@ -162,7 +162,13 @@ public class HistoryCommands extends MethodCommands {
BBC.COMMAND_SYNTAX.send(player, "/frb " + user + " " + radius + " <time>"); BBC.COMMAND_SYNTAX.send(player, "/frb " + user + " " + radius + " <time>");
return; return;
} }
radius = Math.max(Math.min(500, radius), 0); radius = Math.max(radius, 0);
if (radius > 500) {
if (!player.hasPermission("fawe.admin")) {
BBC.WORLDEDIT_CANCEL_REASON_MAX_CHECKS.send(player);
return;
}
}
final World world = player.getWorld(); final World world = player.getWorld();
WorldVector origin = player.getPosition(); WorldVector origin = player.getPosition();
Vector bot = origin.subtract(radius, radius, radius); Vector bot = origin.subtract(radius, radius, radius);