Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix: Extensions should specify geyser api version instead of base api version #3880

Merged
merged 19 commits into from
Jul 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
69bae4f
let extensions specify geyser api version instead of base api version
onebeastchris Jun 15, 2023
123ae7d
fix spacing, @link formatting, properly check for compat
onebeastchris Jun 16, 2023
1994c6c
Merge branch 'master' into extension-api-check
onebeastchris Jun 16, 2023
c233e7a
Merge remote-tracking branch 'upstream/master' into extension-api-check
onebeastchris Jun 17, 2023
18e3c3b
Proper warning, update to API changes to also check patch version
onebeastchris Jun 17, 2023
c4bd589
Merge branch 'master' into extension-api-check
onebeastchris Jun 17, 2023
8ec4e8f
Merge remote-tracking branch 'origin/extension-api-check' into extens…
onebeastchris Jun 17, 2023
04ecadc
Merge branch 'master' into extension-api-check
Konicai Jun 18, 2023
7cf06ad
Bump base-api version
Konicai Jun 19, 2023
11b6ce6
Merge branch 'master' into extension-api-check
onebeastchris Jun 20, 2023
507819d
Merge remote-tracking branch 'upstream/master' into extension-api-check
onebeastchris Jul 10, 2024
4e68ca0
adapt to new base api changes
onebeastchris Jul 10, 2024
434ee13
Actually bump to 2.4.1
onebeastchris Jul 10, 2024
19c065d
Update api/src/main/java/org/geysermc/geyser/api/extension/ExtensionD…
onebeastchris Jul 10, 2024
c6301b3
Address reviews
onebeastchris Jul 13, 2024
cbcfb85
Merge remote-tracking branch 'refs/remotes/upstream/api/2.4.1' into e…
onebeastchris Jul 15, 2024
74bd0bb
Address reviews
onebeastchris Jul 15, 2024
0d91e59
Update to latest base api changes; proper extension *human* version c…
onebeastchris Jul 20, 2024
093ef4b
no need to apply a plugin, that's the default
onebeastchris Jul 31, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 17 additions & 1 deletion api/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,8 +1,24 @@
plugins {
// Allow blossom to mark sources root of templates
idea
id("geyser.publish-conventions")
alias(libs.plugins.blossom)
}

dependencies {
api(libs.base.api)
api(libs.math)
}
}

version = property("version")!!
val apiVersion = (version as String).removeSuffix("-SNAPSHOT")

sourceSets {
main {
blossom {
javaSources {
property("version", apiVersion)
}
}
}
}
53 changes: 53 additions & 0 deletions api/src/main/java-templates/org.geysermc.geyser.api/BuildData.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*
* Copyright (c) 2024 GeyserMC. http://geysermc.org
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author GeyserMC
* @link https://github.com/GeyserMC/Geyser
*/

package org.geysermc.geyser.api;

import org.geysermc.api.util.ApiVersion;

/**
* Not a public API. For internal use only. May change without notice.
* This class is processed before compilation to insert build properties.
*/
class BuildData {
static final String VERSION = "{{ version }}";
static final ApiVersion API_VERSION;

static {
String[] parts = VERSION.split("\\.");
if (parts.length != 3) {
throw new RuntimeException("Invalid api version: " + VERSION);
}

try {
int human = Integer.parseInt(parts[0]);
int major = Integer.parseInt(parts[1]);
int minor = Integer.parseInt(parts[2]);
API_VERSION = new ApiVersion(human, major, minor);
} catch (Exception e) {
throw new RuntimeException("Invalid api version: " + VERSION, e);
}
}
}
11 changes: 11 additions & 0 deletions api/src/main/java/org/geysermc/geyser/api/GeyserApi.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import org.checkerframework.checker.nullness.qual.Nullable;
import org.geysermc.api.Geyser;
import org.geysermc.api.GeyserApiBase;
import org.geysermc.api.util.ApiVersion;
import org.geysermc.geyser.api.command.CommandSource;
import org.geysermc.geyser.api.connection.GeyserConnection;
import org.geysermc.geyser.api.event.EventBus;
Expand Down Expand Up @@ -169,4 +170,14 @@ public interface GeyserApi extends GeyserApiBase {
static GeyserApi api() {
return Geyser.api(GeyserApi.class);
}

/**
* Returns the {@link ApiVersion} representing the current Geyser api version.
* See the <a href="https://github.com/geysermc/api/blob/master/geyser-versioning.md">Geyser version outline</a>)
*
* @return the current geyser api version
*/
default ApiVersion geyserApiVersion() {
return BuildData.API_VERSION;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -59,33 +59,46 @@ public interface ExtensionDescription {
String main();

/**
* Gets the extension's major api version
* Represents the human api version that the extension requires.
* See the <a href="https://github.com/geysermc/api/blob/master/geyser-versioning.md">Geyser version outline</a>)
* for more details on the Geyser API version.
*
* @return the extension's major api version
* @return the extension's requested human api version
*/
int humanApiVersion();

/**
* Represents the major api version that the extension requires.
* See the <a href="https://github.com/geysermc/api/blob/master/geyser-versioning.md">Geyser version outline</a>)
* for more details on the Geyser API version.
*
* @return the extension's requested major api version
*/
int majorApiVersion();

/**
* Gets the extension's minor api version
* Represents the minor api version that the extension requires.
* See the <a href="https://github.com/geysermc/api/blob/master/geyser-versioning.md">Geyser version outline</a>)
* for more details on the Geyser API version.
*
* @return the extension's minor api version
* @return the extension's requested minor api version
*/
int minorApiVersion();

/**
* Gets the extension's patch api version
*
* @return the extension's patch api version
* No longer in use. Geyser is now using an adaption of the romantic versioning scheme.
* See <a href="https://github.com/geysermc/api/blob/master/geyser-versioning.md">here</a> for details.
*/
int patchApiVersion();
@Deprecated(forRemoval = true)
default int patchApiVersion() {
return minorApiVersion();
}

/**
* Gets the extension's api version.
*
* @return the extension's api version
* Returns the extension's requested Geyser Api version.
*/
default String apiVersion() {
return majorApiVersion() + "." + minorApiVersion() + "." + patchApiVersion();
return humanApiVersion() + "." + majorApiVersion() + "." + minorApiVersion();
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,9 @@
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 {

Expand Down Expand Up @@ -82,9 +82,9 @@ public static GeyserExtensionDescription fromYaml(Reader reader) throws InvalidD
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) {
Expand All @@ -94,7 +94,7 @@ public static GeyserExtensionDescription fromYaml(Reader reader) throws InvalidD
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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,18 +29,28 @@
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;
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;
Expand Down Expand Up @@ -176,16 +186,22 @@ protected void loadAllExtensions(@NonNull ExtensionManager extensionManager) {
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;
}

// 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;
// Check whether an extensions' requested api version is compatible
ApiVersion.Compatibility compatibility = GeyserApi.api().geyserApiVersion().supportsRequestedVersion(
description.humanApiVersion(),
description.majorApiVersion(),
description.minorApiVersion()
);

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);
Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@ org.gradle.vfs.watch=false

group=org.geysermc
id=geyser
version=2.4.0-SNAPSHOT
version=2.4.1-SNAPSHOT
description=Allows for players from Minecraft: Bedrock Edition to join Minecraft: Java Edition servers.
2 changes: 1 addition & 1 deletion gradle/libs.versions.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[versions]
base-api = "1.0.0-SNAPSHOT"
base-api = "1.0.1-SNAPSHOT"
cumulus = "1.1.2"
erosion = "1.1-20240515.191456-1"
events = "1.1-SNAPSHOT"
Expand Down