2021-06-23 19:54:58 +00:00
|
|
|
package net.seanomik.tamablefoxes.util;
|
2020-09-08 18:40:43 +00:00
|
|
|
|
2021-06-23 23:12:49 +00:00
|
|
|
import net.seanomik.tamablefoxes.util.io.Config;
|
2021-06-23 19:54:58 +00:00
|
|
|
import net.seanomik.tamablefoxes.util.io.LanguageConfig;
|
2020-09-10 16:29:47 +00:00
|
|
|
import org.bukkit.Bukkit;
|
|
|
|
import org.bukkit.ChatColor;
|
2021-07-19 03:12:38 +00:00
|
|
|
import sun.misc.Unsafe;
|
|
|
|
|
|
|
|
import sun.misc.Unsafe;
|
2020-09-10 16:29:47 +00:00
|
|
|
|
2020-09-08 18:40:43 +00:00
|
|
|
import java.lang.reflect.Field;
|
|
|
|
import java.lang.reflect.Modifier;
|
2021-07-19 03:12:38 +00:00
|
|
|
import java.security.AccessController;
|
|
|
|
import java.security.PrivilegedAction;
|
2020-09-08 18:40:43 +00:00
|
|
|
|
|
|
|
public final class FieldHelper {
|
2021-07-19 03:12:38 +00:00
|
|
|
public static void setFieldUsingUnsafe(final Field field, final Object object, final Object newValue) {
|
|
|
|
try {
|
|
|
|
field.setAccessible(true);
|
|
|
|
int fieldModifiersMask = field.getModifiers();
|
|
|
|
boolean isFinalModifierPresent = (fieldModifiersMask & Modifier.FINAL) == Modifier.FINAL;
|
|
|
|
if (isFinalModifierPresent) {
|
|
|
|
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
|
|
|
|
try {
|
|
|
|
sun.misc.Unsafe unsafe = getUnsafe();
|
|
|
|
long offset = unsafe.objectFieldOffset(field);
|
|
|
|
setFieldUsingUnsafe(object, field.getType(), offset, newValue, unsafe);
|
|
|
|
return null;
|
|
|
|
} catch (Throwable t) {
|
|
|
|
throw new RuntimeException(t);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
try {
|
|
|
|
field.set(object, newValue);
|
|
|
|
} catch (IllegalAccessException ex) {
|
|
|
|
throw new RuntimeException(ex);
|
|
|
|
}
|
2021-06-14 16:33:45 +00:00
|
|
|
}
|
2021-07-19 03:12:38 +00:00
|
|
|
} catch (SecurityException ex) {
|
|
|
|
throw new RuntimeException(ex);
|
2021-06-14 16:33:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-07-19 03:12:38 +00:00
|
|
|
private static sun.misc.Unsafe getUnsafe() throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException {
|
|
|
|
Field field = sun.misc.Unsafe.class.getDeclaredField("theUnsafe");
|
|
|
|
field.setAccessible(true);
|
|
|
|
return (sun.misc.Unsafe) field.get(null);
|
|
|
|
}
|
2021-06-14 16:33:45 +00:00
|
|
|
|
2021-07-19 03:12:38 +00:00
|
|
|
private static void setFieldUsingUnsafe(Object base, Class type, long offset, Object newValue, Unsafe unsafe) {
|
|
|
|
if (type == Integer.TYPE) {
|
|
|
|
unsafe.putInt(base, offset, ((Integer) newValue));
|
|
|
|
} else if (type == Short.TYPE) {
|
|
|
|
unsafe.putShort(base, offset, ((Short) newValue));
|
|
|
|
} else if (type == Long.TYPE) {
|
|
|
|
unsafe.putLong(base, offset, ((Long) newValue));
|
|
|
|
} else if (type == Byte.TYPE) {
|
|
|
|
unsafe.putByte(base, offset, ((Byte) newValue));
|
|
|
|
} else if (type == Boolean.TYPE) {
|
|
|
|
unsafe.putBoolean(base, offset, ((Boolean) newValue));
|
|
|
|
} else if (type == Float.TYPE) {
|
|
|
|
unsafe.putFloat(base, offset, ((Float) newValue));
|
|
|
|
} else if (type == Double.TYPE) {
|
|
|
|
unsafe.putDouble(base, offset, ((Double) newValue));
|
|
|
|
} else if (type == Character.TYPE) {
|
|
|
|
unsafe.putChar(base, offset, ((Character) newValue));
|
2021-06-14 16:33:45 +00:00
|
|
|
} else {
|
2021-07-19 03:12:38 +00:00
|
|
|
unsafe.putObject(base, offset, newValue);
|
2020-09-08 18:40:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|