Compare commits

...

2 Commits

2 changed files with 67 additions and 12 deletions

View File

@ -73,13 +73,13 @@ public abstract class PaperBrigadierCommand extends BrigadierCommand<CommandSour
RootCommandNode<CommandSourceStack> wrappedRoot = vanillaPaperDispatcher.getRoot();
ReflectClass<?> apiMirrorRootNodeClass = Reflect.ofClassOfInstance(wrappedRoot);
try {
RootCommandNode<?> actualRoot = ((CommandDispatcher<?>) apiMirrorRootNodeClass.method("getDispatcher").invoke(wrappedRoot)).getRoot();
RootCommandNode<?> unwrappedRoot = ((CommandDispatcher<?>) apiMirrorRootNodeClass.method("getDispatcher").invoke(wrappedRoot)).getRoot();
Reflect.ofClass(CommandNode.class).field("unwrappedCached").setValue(wrappedRoot, actualRoot);
Reflect.ofClass(CommandNode.class).field("wrappedCached").setValue(actualRoot, wrappedRoot);
Reflect.ofClass(CommandNode.class).field("unwrappedCached").setValue(wrappedRoot, unwrappedRoot);
Reflect.ofClass(CommandNode.class).field("wrappedCached").setValue(unwrappedRoot, wrappedRoot);
} catch (InvocationTargetException|IllegalAccessException|NoSuchMethodException|NoSuchFieldException e) {
Log.severe("Unable to trick the Paper/Brigadier unwrapper to properly handle redirecting to root command node.", e);
Log.severe("Unable to trick the Paper/Brigadier unwrapper to properly handle commands redirecting to root command node.", e);
}
}
}
@ -183,6 +183,7 @@ public abstract class PaperBrigadierCommand extends BrigadierCommand<CommandSour
}
registeredAliases = new HashSet<>(event.registrar().register(commandNode, description, List.of(aliases)));
doPostRegistrationFixes();
if (registrationPolicy == RegistrationPolicy.ALL) {
// enforce registration of aliases
@ -233,6 +234,43 @@ public abstract class PaperBrigadierCommand extends BrigadierCommand<CommandSour
}
private void doPostRegistrationFixes() {
postRegistrationFixNode(new HashSet<>(), commandNode);
}
private void postRegistrationFixNode(Set<CommandNode<CommandSourceStack>> fixedNodes, CommandNode<CommandSourceStack> originalNode) {
if (originalNode instanceof RootCommandNode)
return;
if (fixedNodes.contains(originalNode))
return;
fixedNodes.add(originalNode);
if (originalNode.getRedirect() != null) {
try {
ReflectClass<CommandNode> cmdNodeClass = Reflect.ofClass(CommandNode.class);
CommandNode<CommandSourceStack> unwrappedNode = (CommandNode<CommandSourceStack>) cmdNodeClass.field("unwrappedCached").getValue(originalNode);
if (unwrappedNode != null) {
cmdNodeClass.field("modifier").setValue(unwrappedNode, cmdNodeClass.field("modifier").getValue(originalNode));
cmdNodeClass.field("forks").setValue(unwrappedNode, cmdNodeClass.field("forks").getValue(originalNode));
}
} catch (IllegalAccessException | NoSuchFieldException e) {
throw new RuntimeException(e);
}
postRegistrationFixNode(fixedNodes, originalNode.getRedirect());
}
else {
try {
for (CommandNode<CommandSourceStack> child : originalNode.getChildren())
postRegistrationFixNode(fixedNodes, child);
} catch (UnsupportedOperationException ignored) {
// in case getChildren is not possible (vanilla commands are wrapped by Paper API)
}
}
}
private static LiteralCommandNode<CommandSourceStack> getAliasNode(CommandNode<CommandSourceStack> commandNode, String alias) {
return LiteralArgumentBuilder.<CommandSourceStack>literal(alias)
.requires(commandNode.getRequirement())

View File

@ -9,7 +9,7 @@ import java.lang.reflect.Modifier;
*/
public final class ReflectField<T> extends ReflectMember<T, String, Field, NoSuchFieldException> {
/* Those fields are used to modify the value of a static variable. Depending on the current Java version,
/* Those fields are used to modify the value of a final variable. Depending on the current Java version,
* one of them will be used for this purpose.
*/
private static sun.misc.Unsafe sunMiscUnsafeInstance;
@ -122,13 +122,30 @@ public final class ReflectField<T> extends ReflectMember<T, String, Field, NoSuc
// if the field is final, we have to do some unsafe stuff :/
if (sunMiscUnsafeInstance != null) { // Java >= 16
// set the value of the field, directly in the memory
if (Modifier.isStatic(realModifiers)) {
long offset = sunMiscUnsafeInstance.staticFieldOffset(f);
sunMiscUnsafeInstance.putObject(sunMiscUnsafeInstance.staticFieldBase(f), offset, value);
} else {
long offset = sunMiscUnsafeInstance.objectFieldOffset(f);
sunMiscUnsafeInstance.putObject(instance, offset, value);
}
Object unsafeObjInstance = Modifier.isStatic(realModifiers)
? sunMiscUnsafeInstance.staticFieldBase(f)
: instance;
long offset = Modifier.isStatic(realModifiers)
? sunMiscUnsafeInstance.staticFieldOffset(f)
: sunMiscUnsafeInstance.objectFieldOffset(f);
if (char.class.isAssignableFrom(f.getType()))
sunMiscUnsafeInstance.putChar(unsafeObjInstance, offset, (char)value);
else if (byte.class.isAssignableFrom(f.getType()))
sunMiscUnsafeInstance.putByte(unsafeObjInstance, offset, (byte)value);
else if (short.class.isAssignableFrom(f.getType()))
sunMiscUnsafeInstance.putShort(unsafeObjInstance, offset, (short)value);
else if (int.class.isAssignableFrom(f.getType()))
sunMiscUnsafeInstance.putInt(unsafeObjInstance, offset, (int)value);
else if (long.class.isAssignableFrom(f.getType()))
sunMiscUnsafeInstance.putLong(unsafeObjInstance, offset, (long)value);
else if (boolean.class.isAssignableFrom(f.getType()))
sunMiscUnsafeInstance.putBoolean(unsafeObjInstance, offset, (boolean)value);
else if (float.class.isAssignableFrom(f.getType()))
sunMiscUnsafeInstance.putFloat(unsafeObjInstance, offset, (float)value);
else if (double.class.isAssignableFrom(f.getType()))
sunMiscUnsafeInstance.putDouble(unsafeObjInstance, offset, (double)value);
else
sunMiscUnsafeInstance.putObject(unsafeObjInstance, offset, value);
} else { // Java < 16
// change the modifier in the Field instance so the method #set(instance, value) doesn't throw an exception
try {