#1401: Add a config option to accept old keys in registry get calls

This commit is contained in:
DerFrZocker 2024-05-29 06:45:14 +10:00 committed by md_5
parent a43701920b
commit 94e44ec934
No known key found for this signature in database
GPG Key ID: E8E901AC7C617C11
8 changed files with 60 additions and 7 deletions

View File

@ -2,6 +2,7 @@ package org.bukkit.craftbukkit;
import com.google.common.base.Charsets; import com.google.common.base.Charsets;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.base.Joiner;
import com.google.common.base.Preconditions; import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterators; import com.google.common.collect.Iterators;
@ -302,6 +303,7 @@ public final class CraftServer implements Server {
public boolean ignoreVanillaPermissions = false; public boolean ignoreVanillaPermissions = false;
private final List<CraftPlayer> playerView; private final List<CraftPlayer> playerView;
public int reloadCount; public int reloadCount;
public Set<String> activeCompatibilities = Collections.emptySet();
static { static {
ConfigurationSerialization.registerClass(CraftOfflinePlayer.class); ConfigurationSerialization.registerClass(CraftOfflinePlayer.class);
@ -377,6 +379,7 @@ public final class CraftServer implements Server {
TicketType.PLUGIN.timeout = configuration.getInt("chunk-gc.period-in-ticks"); TicketType.PLUGIN.timeout = configuration.getInt("chunk-gc.period-in-ticks");
minimumAPI = ApiVersion.getOrCreateVersion(configuration.getString("settings.minimum-api")); minimumAPI = ApiVersion.getOrCreateVersion(configuration.getString("settings.minimum-api"));
loadIcon(); loadIcon();
loadCompatibilities();
// Set map color cache // Set map color cache
if (configuration.getBoolean("settings.use-map-color-cache")) { if (configuration.getBoolean("settings.use-map-color-cache")) {
@ -420,6 +423,25 @@ public final class CraftServer implements Server {
} }
} }
private void loadCompatibilities() {
ConfigurationSection compatibilities = configuration.getConfigurationSection("settings.compatibility");
if (compatibilities == null) {
activeCompatibilities = Collections.emptySet();
return;
}
activeCompatibilities = compatibilities
.getKeys(false)
.stream()
.filter(compatibilities::getBoolean)
.collect(Collectors.toSet());
if (!activeCompatibilities.isEmpty()) {
logger.info("Using following compatibilities: `" + Joiner.on("`, `").join(activeCompatibilities) + "`, this will affect performance and other plugins behavior.");
logger.info("Only use when necessary and prefer updating plugins if possible.");
}
}
public void loadPlugins() { public void loadPlugins() {
pluginManager.registerInterface(JavaPluginLoader.class); pluginManager.registerInterface(JavaPluginLoader.class);
@ -896,6 +918,7 @@ public final class CraftServer implements Server {
printSaveWarning = false; printSaveWarning = false;
console.autosavePeriod = configuration.getInt("ticks-per.autosave"); console.autosavePeriod = configuration.getInt("ticks-per.autosave");
loadIcon(); loadIcon();
loadCompatibilities();
try { try {
playerList.getIpBans().load(); playerList.getIpBans().load();

View File

@ -12,6 +12,7 @@ import org.bukkit.craftbukkit.CraftRegistry;
import org.bukkit.craftbukkit.legacy.fieldrename.FieldRenameData; import org.bukkit.craftbukkit.legacy.fieldrename.FieldRenameData;
import org.bukkit.craftbukkit.legacy.reroute.DoNotReroute; import org.bukkit.craftbukkit.legacy.reroute.DoNotReroute;
import org.bukkit.craftbukkit.legacy.reroute.InjectPluginVersion; import org.bukkit.craftbukkit.legacy.reroute.InjectPluginVersion;
import org.bukkit.craftbukkit.legacy.reroute.RequireCompatibility;
import org.bukkit.craftbukkit.legacy.reroute.RerouteMethodName; import org.bukkit.craftbukkit.legacy.reroute.RerouteMethodName;
import org.bukkit.craftbukkit.legacy.reroute.RerouteStatic; import org.bukkit.craftbukkit.legacy.reroute.RerouteStatic;
import org.bukkit.craftbukkit.util.ApiVersion; import org.bukkit.craftbukkit.util.ApiVersion;
@ -55,6 +56,7 @@ public class FieldRename {
return Enum.valueOf(enumClass, rename(apiVersion, enumClass.getName().replace('.', '/'), name)); return Enum.valueOf(enumClass, rename(apiVersion, enumClass.getName().replace('.', '/'), name));
} }
@RequireCompatibility("allow-old-keys-in-registry")
public static <T extends Keyed> T get(Registry<T> registry, NamespacedKey namespacedKey) { public static <T extends Keyed> T get(Registry<T> registry, NamespacedKey namespacedKey) {
// We don't have version-specific changes, so just use current, and don't inject a version // We don't have version-specific changes, so just use current, and don't inject a version
return CraftRegistry.get(registry, namespacedKey, ApiVersion.CURRENT); return CraftRegistry.get(registry, namespacedKey, ApiVersion.CURRENT);

View File

@ -0,0 +1,13 @@
package org.bukkit.craftbukkit.legacy.reroute;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface RequireCompatibility {
String value();
}

View File

@ -112,6 +112,11 @@ public class RerouteBuilder {
boolean inBukkit = !method.isAnnotationPresent(NotInBukkit.class); boolean inBukkit = !method.isAnnotationPresent(NotInBukkit.class);
return new RerouteMethodData(methodKey, sourceDesc, sourceOwner, methodName, rerouteStatic != null, targetType, Type.getInternalName(method.getDeclaringClass()), method.getName(), arguments, rerouteReturn, inBukkit); String requiredCompatibility = null;
if (method.isAnnotationPresent(RequireCompatibility.class)) {
requiredCompatibility = method.getAnnotation(RequireCompatibility.class).value();
}
return new RerouteMethodData(methodKey, sourceDesc, sourceOwner, methodName, rerouteStatic != null, targetType, Type.getInternalName(method.getDeclaringClass()), method.getName(), arguments, rerouteReturn, inBukkit, requiredCompatibility);
} }
} }

View File

@ -1,9 +1,11 @@
package org.bukkit.craftbukkit.legacy.reroute; package org.bukkit.craftbukkit.legacy.reroute;
import java.util.List; import java.util.List;
import org.jetbrains.annotations.Nullable;
import org.objectweb.asm.Type; import org.objectweb.asm.Type;
public record RerouteMethodData(String source, Type sourceDesc, Type sourceOwner, String sourceName, public record RerouteMethodData(String source, Type sourceDesc, Type sourceOwner, String sourceName,
boolean staticReroute, Type targetType, String targetOwner, String targetName, boolean staticReroute, Type targetType, String targetOwner, String targetName,
List<RerouteArgument> arguments, RerouteReturn rerouteReturn, boolean isInBukkit) { List<RerouteArgument> arguments, RerouteReturn rerouteReturn, boolean isInBukkit,
@Nullable String requiredCompatibility) {
} }

View File

@ -6,6 +6,7 @@ import java.io.FileOutputStream;
import java.io.InputStream; import java.io.InputStream;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
@ -117,7 +118,7 @@ public class Commodore {
byte[] b = ByteStreams.toByteArray(is); byte[] b = ByteStreams.toByteArray(is);
if (entry.getName().endsWith(".class")) { if (entry.getName().endsWith(".class")) {
b = convert(b, "dummy", ApiVersion.NONE); b = convert(b, "dummy", ApiVersion.NONE, Collections.emptySet());
entry = new JarEntry(entry.getName()); entry = new JarEntry(entry.getName());
} }
@ -135,7 +136,7 @@ public class Commodore {
} }
} }
public static byte[] convert(byte[] b, final String pluginName, final ApiVersion pluginVersion) { public static byte[] convert(byte[] b, final String pluginName, final ApiVersion pluginVersion, final Set<String> activeCompatibilities) {
final boolean modern = pluginVersion.isNewerThanOrSameAs(ApiVersion.FLATTENING); final boolean modern = pluginVersion.isNewerThanOrSameAs(ApiVersion.FLATTENING);
ClassReader cr = new ClassReader(b); ClassReader cr = new ClassReader(b);
ClassWriter cw = new ClassWriter(cr, 0); ClassWriter cw = new ClassWriter(cr, 0);
@ -385,7 +386,7 @@ public class Commodore {
} }
private boolean checkReroute(MethodPrinter visitor, Map<String, RerouteMethodData> rerouteMethodDataMap, int opcode, String owner, String name, String desc, Type samMethodType, Type instantiatedMethodType) { private boolean checkReroute(MethodPrinter visitor, Map<String, RerouteMethodData> rerouteMethodDataMap, int opcode, String owner, String name, String desc, Type samMethodType, Type instantiatedMethodType) {
return rerouteMethods(rerouteMethodDataMap, opcode == Opcodes.INVOKESTATIC || opcode == Opcodes.H_INVOKESTATIC, owner, name, desc, data -> { return rerouteMethods(activeCompatibilities, rerouteMethodDataMap, opcode == Opcodes.INVOKESTATIC || opcode == Opcodes.H_INVOKESTATIC, owner, name, desc, data -> {
visitor.visit(Opcodes.INVOKESTATIC, className, buildMethodName(data), buildMethodDesc(data), isInterface, samMethodType, instantiatedMethodType); visitor.visit(Opcodes.INVOKESTATIC, className, buildMethodName(data), buildMethodDesc(data), isInterface, samMethodType, instantiatedMethodType);
rerouteMethodData.add(data); rerouteMethodData.add(data);
}); });
@ -555,7 +556,7 @@ public class Commodore {
But since it is only applied for each class and method call once when they get first loaded, it should not be that bad. But since it is only applied for each class and method call once when they get first loaded, it should not be that bad.
(Although some load time testing could be done) (Although some load time testing could be done)
*/ */
public static boolean rerouteMethods(Map<String, RerouteMethodData> rerouteMethodDataMap, boolean staticCall, String owner, String name, String desc, Consumer<RerouteMethodData> consumer) { public static boolean rerouteMethods(Set<String> activeCompatibilities, Map<String, RerouteMethodData> rerouteMethodDataMap, boolean staticCall, String owner, String name, String desc, Consumer<RerouteMethodData> consumer) {
Type ownerType = Type.getObjectType(owner); Type ownerType = Type.getObjectType(owner);
Class<?> ownerClass; Class<?> ownerClass;
try { try {
@ -578,6 +579,10 @@ public class Commodore {
continue; continue;
} }
if (data.requiredCompatibility() != null && !activeCompatibilities.contains(data.requiredCompatibility())) {
return false;
}
consumer.accept(data); consumer.accept(data);
return true; return true;
} }

View File

@ -53,6 +53,7 @@ import org.bukkit.block.data.BlockData;
import org.bukkit.craftbukkit.CraftEquipmentSlot; import org.bukkit.craftbukkit.CraftEquipmentSlot;
import org.bukkit.craftbukkit.CraftFeatureFlag; import org.bukkit.craftbukkit.CraftFeatureFlag;
import org.bukkit.craftbukkit.CraftRegistry; import org.bukkit.craftbukkit.CraftRegistry;
import org.bukkit.craftbukkit.CraftServer;
import org.bukkit.craftbukkit.attribute.CraftAttribute; import org.bukkit.craftbukkit.attribute.CraftAttribute;
import org.bukkit.craftbukkit.attribute.CraftAttributeInstance; import org.bukkit.craftbukkit.attribute.CraftAttributeInstance;
import org.bukkit.craftbukkit.block.data.CraftBlockData; import org.bukkit.craftbukkit.block.data.CraftBlockData;
@ -323,7 +324,7 @@ public final class CraftMagicNumbers implements UnsafeValues {
@Override @Override
public byte[] processClass(PluginDescriptionFile pdf, String path, byte[] clazz) { public byte[] processClass(PluginDescriptionFile pdf, String path, byte[] clazz) {
try { try {
clazz = Commodore.convert(clazz, pdf.getName(), ApiVersion.getOrCreateVersion(pdf.getAPIVersion())); clazz = Commodore.convert(clazz, pdf.getName(), ApiVersion.getOrCreateVersion(pdf.getAPIVersion()), ((CraftServer) Bukkit.getServer()).activeCompatibilities);
} catch (Exception ex) { } catch (Exception ex) {
Bukkit.getLogger().log(Level.SEVERE, "Fatal error trying to convert " + pdf.getFullName() + ":" + path, ex); Bukkit.getLogger().log(Level.SEVERE, "Fatal error trying to convert " + pdf.getFullName() + ":" + path, ex);
} }

View File

@ -23,6 +23,8 @@ settings:
shutdown-message: Server closed shutdown-message: Server closed
minimum-api: none minimum-api: none
use-map-color-cache: true use-map-color-cache: true
compatibility:
allow-old-keys-in-registry: false
spawn-limits: spawn-limits:
monsters: 70 monsters: 70
animals: 10 animals: 10