Extensions should specify geyser api version in the extension.yml (#3880)

* let extensions specify geyser api version instead of base api version

* fix spacing, @link formatting, properly check for compat

* Proper warning, update to API changes to also check patch version

* Bump base-api version

* adapt to new base api changes

* Actually bump to 2.4.1

* Update api/src/main/java/org/geysermc/geyser/api/extension/ExtensionDescription.java

* Address reviews

* Address reviews

* Update to latest base api changes; proper extension *human* version checking

* no need to apply a plugin, that's the default

---------

Co-authored-by: Konicai <71294714+Konicai@users.noreply.github.com>
This commit is contained in:
chris 2024-08-01 00:11:13 +02:00 committed by Konicai
parent 03187b6139
commit f3ba5848c2
8 changed files with 141 additions and 32 deletions

View file

@ -43,9 +43,9 @@ import java.util.regex.Pattern;
public record GeyserExtensionDescription(@NonNull String id,
@NonNull String name,
@NonNull String main,
int humanApiVersion,
int majorApiVersion,
int minorApiVersion,
int patchApiVersion,
@NonNull String version,
@NonNull List<String> authors) implements ExtensionDescription {
@ -82,9 +82,9 @@ public record GeyserExtensionDescription(@NonNull String id,
throw new InvalidDescriptionException(GeyserLocale.getLocaleStringLog("geyser.extensions.load.failed_api_format", name, apiVersion));
}
String[] api = apiVersion.split("\\.");
int majorApi = Integer.parseUnsignedInt(api[0]);
int minorApi = Integer.parseUnsignedInt(api[1]);
int patchApi = Integer.parseUnsignedInt(api[2]);
int humanApi = Integer.parseUnsignedInt(api[0]);
int majorApi = Integer.parseUnsignedInt(api[1]);
int minorApi = Integer.parseUnsignedInt(api[2]);
List<String> authors = new ArrayList<>();
if (source.author != null) {
@ -94,7 +94,7 @@ public record GeyserExtensionDescription(@NonNull String id,
authors.addAll(source.authors);
}
return new GeyserExtensionDescription(id, name, main, majorApi, minorApi, patchApi, version, authors);
return new GeyserExtensionDescription(id, name, main, humanApi, majorApi, minorApi, version, authors);
}
@NonNull

View file

@ -29,10 +29,15 @@ import it.unimi.dsi.fastutil.objects.Object2ObjectMap;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import lombok.RequiredArgsConstructor;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.geysermc.api.Geyser;
import org.geysermc.api.util.ApiVersion;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.api.GeyserApi;
import org.geysermc.geyser.api.event.ExtensionEventBus;
import org.geysermc.geyser.api.extension.*;
import org.geysermc.geyser.api.extension.Extension;
import org.geysermc.geyser.api.extension.ExtensionDescription;
import org.geysermc.geyser.api.extension.ExtensionLoader;
import org.geysermc.geyser.api.extension.ExtensionLogger;
import org.geysermc.geyser.api.extension.ExtensionManager;
import org.geysermc.geyser.api.extension.exception.InvalidDescriptionException;
import org.geysermc.geyser.api.extension.exception.InvalidExtensionException;
import org.geysermc.geyser.extension.event.GeyserExtensionEventBus;
@ -40,7 +45,12 @@ import org.geysermc.geyser.text.GeyserLocale;
import java.io.IOException;
import java.io.Reader;
import java.nio.file.*;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
@ -176,16 +186,22 @@ public class GeyserExtensionLoader extends ExtensionLoader {
return;
}
// Completely different API version
if (description.majorApiVersion() != Geyser.api().majorApiVersion()) {
GeyserImpl.getInstance().getLogger().error(GeyserLocale.getLocaleStringLog("geyser.extensions.load.failed_api_version", name, description.apiVersion()));
return;
}
// Check whether an extensions' requested api version is compatible
ApiVersion.Compatibility compatibility = GeyserApi.api().geyserApiVersion().supportsRequestedVersion(
description.humanApiVersion(),
description.majorApiVersion(),
description.minorApiVersion()
);
// If the extension requires new API features, being backwards compatible
if (description.minorApiVersion() > Geyser.api().minorApiVersion()) {
GeyserImpl.getInstance().getLogger().error(GeyserLocale.getLocaleStringLog("geyser.extensions.load.failed_api_version", name, description.apiVersion()));
return;
if (compatibility != ApiVersion.Compatibility.COMPATIBLE) {
// Workaround for the switch to the Geyser API version instead of the Base API version in extensions
if (compatibility == ApiVersion.Compatibility.HUMAN_DIFFER && description.humanApiVersion() == 1) {
GeyserImpl.getInstance().getLogger().warning("The extension %s requested the Base API version %s, which is deprecated in favor of specifying the Geyser API version. Please update the extension, or contact its developer."
.formatted(name, description.apiVersion()));
} else {
GeyserImpl.getInstance().getLogger().error(GeyserLocale.getLocaleStringLog("geyser.extensions.load.failed_api_version", name, description.apiVersion()));
return;
}
}
GeyserExtensionContainer container = this.loadExtension(path, description);