Skip to content

Commit

Permalink
#1401: Add a config option to accept old keys in registry get calls
Browse files Browse the repository at this point in the history
  • Loading branch information
DerFrZocker authored and md-5 committed May 28, 2024
1 parent a437019 commit 94e44ec
Show file tree
Hide file tree
Showing 8 changed files with 60 additions and 7 deletions.
23 changes: 23 additions & 0 deletions src/main/java/org/bukkit/craftbukkit/CraftServer.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.google.common.base.Charsets;
import com.google.common.base.Function;
import com.google.common.base.Joiner;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterators;
Expand Down Expand Up @@ -302,6 +303,7 @@ public final class CraftServer implements Server {
public boolean ignoreVanillaPermissions = false;
private final List<CraftPlayer> playerView;
public int reloadCount;
public Set<String> activeCompatibilities = Collections.emptySet();

static {
ConfigurationSerialization.registerClass(CraftOfflinePlayer.class);
Expand Down Expand Up @@ -377,6 +379,7 @@ public CraftPlayer apply(EntityPlayer player) {
TicketType.PLUGIN.timeout = configuration.getInt("chunk-gc.period-in-ticks");
minimumAPI = ApiVersion.getOrCreateVersion(configuration.getString("settings.minimum-api"));
loadIcon();
loadCompatibilities();

// Set map color cache
if (configuration.getBoolean("settings.use-map-color-cache")) {
Expand Down Expand Up @@ -420,6 +423,25 @@ private void saveCommandsConfig() {
}
}

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() {
pluginManager.registerInterface(JavaPluginLoader.class);

Expand Down Expand Up @@ -896,6 +918,7 @@ public void reload() {
printSaveWarning = false;
console.autosavePeriod = configuration.getInt("ticks-per.autosave");
loadIcon();
loadCompatibilities();

try {
playerList.getIpBans().load();
Expand Down
2 changes: 2 additions & 0 deletions src/main/java/org/bukkit/craftbukkit/legacy/FieldRename.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import org.bukkit.craftbukkit.legacy.fieldrename.FieldRenameData;
import org.bukkit.craftbukkit.legacy.reroute.DoNotReroute;
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.RerouteStatic;
import org.bukkit.craftbukkit.util.ApiVersion;
Expand Down Expand Up @@ -55,6 +56,7 @@ public static <T extends Enum<T>> T valueOf(Class<T> enumClass, String name, @In
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) {
// We don't have version-specific changes, so just use current, and don't inject a version
return CraftRegistry.get(registry, namespacedKey, ApiVersion.CURRENT);
Expand Down
Original file line number Diff line number Diff line change
@@ -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();
}
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,11 @@ public static RerouteMethodData buildFromMethod(Method method) {

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);
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package org.bukkit.craftbukkit.legacy.reroute;

import java.util.List;
import org.jetbrains.annotations.Nullable;
import org.objectweb.asm.Type;

public record RerouteMethodData(String source, Type sourceDesc, Type sourceOwner, String sourceName,
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) {
}
13 changes: 9 additions & 4 deletions src/main/java/org/bukkit/craftbukkit/util/Commodore.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.List;
Expand Down Expand Up @@ -117,7 +118,7 @@ private static void convert(File in, File out) {
byte[] b = ByteStreams.toByteArray(is);

if (entry.getName().endsWith(".class")) {
b = convert(b, "dummy", ApiVersion.NONE);
b = convert(b, "dummy", ApiVersion.NONE, Collections.emptySet());
entry = new JarEntry(entry.getName());
}

Expand All @@ -135,7 +136,7 @@ private static void convert(File in, File out) {
}
}

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);
ClassReader cr = new ClassReader(b);
ClassWriter cw = new ClassWriter(cr, 0);
Expand Down Expand Up @@ -385,7 +386,7 @@ private void handleMethod(MethodPrinter visitor, int opcode, String owner, Strin
}

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);
rerouteMethodData.add(data);
});
Expand Down Expand Up @@ -555,7 +556,7 @@ The question then becomes one about performance (since this is not the most perf
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)
*/
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);
Class<?> ownerClass;
try {
Expand All @@ -578,6 +579,10 @@ public static boolean rerouteMethods(Map<String, RerouteMethodData> rerouteMetho
continue;
}

if (data.requiredCompatibility() != null && !activeCompatibilities.contains(data.requiredCompatibility())) {
return false;
}

consumer.accept(data);
return true;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
import org.bukkit.craftbukkit.CraftEquipmentSlot;
import org.bukkit.craftbukkit.CraftFeatureFlag;
import org.bukkit.craftbukkit.CraftRegistry;
import org.bukkit.craftbukkit.CraftServer;
import org.bukkit.craftbukkit.attribute.CraftAttribute;
import org.bukkit.craftbukkit.attribute.CraftAttributeInstance;
import org.bukkit.craftbukkit.block.data.CraftBlockData;
Expand Down Expand Up @@ -323,7 +324,7 @@ public static boolean isLegacy(PluginDescriptionFile pdf) {
@Override
public byte[] processClass(PluginDescriptionFile pdf, String path, byte[] clazz) {
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) {
Bukkit.getLogger().log(Level.SEVERE, "Fatal error trying to convert " + pdf.getFullName() + ":" + path, ex);
}
Expand Down
2 changes: 2 additions & 0 deletions src/main/resources/configurations/bukkit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ settings:
shutdown-message: Server closed
minimum-api: none
use-map-color-cache: true
compatibility:
allow-old-keys-in-registry: false
spawn-limits:
monsters: 70
animals: 10
Expand Down

0 comments on commit 94e44ec

Please sign in to comment.