mirror of
https://github.com/GeyserMC/Geyser.git
synced 2024-08-14 23:57:35 +00:00
Added javadocs & fixed API version & more
This commit is contained in:
parent
6757437193
commit
805f7f666a
10 changed files with 214 additions and 154 deletions
|
@ -1,51 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2019-2022 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.extension;
|
|
||||||
|
|
||||||
import org.geysermc.api.GeyserApiBase;
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.InputStream;
|
|
||||||
|
|
||||||
public interface Extension {
|
|
||||||
void onLoad();
|
|
||||||
void onEnable();
|
|
||||||
void onDisable();
|
|
||||||
|
|
||||||
boolean isEnabled();
|
|
||||||
boolean isDisabled();
|
|
||||||
|
|
||||||
File dataFolder();
|
|
||||||
ExtensionDescription description();
|
|
||||||
String name();
|
|
||||||
|
|
||||||
InputStream getResource(String filename);
|
|
||||||
void saveResource(String filename, boolean replace);
|
|
||||||
|
|
||||||
ClassLoader classLoader();
|
|
||||||
ExtensionLoader extensionLoader();
|
|
||||||
ExtensionLogger logger();
|
|
||||||
GeyserApiBase geyserApi();
|
|
||||||
}
|
|
|
@ -25,12 +25,41 @@
|
||||||
|
|
||||||
package org.geysermc.geyser.api.extension;
|
package org.geysermc.geyser.api.extension;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.List;
|
||||||
|
|
||||||
public interface ExtensionDescription {
|
public interface ExtensionDescription {
|
||||||
|
/**
|
||||||
|
* Gets the extension's name
|
||||||
|
*
|
||||||
|
* @return the extension's name
|
||||||
|
*/
|
||||||
String name();
|
String name();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the extension's main class
|
||||||
|
*
|
||||||
|
* @return the extension's main class
|
||||||
|
*/
|
||||||
String main();
|
String main();
|
||||||
List<String> ApiVersions();
|
|
||||||
|
/**
|
||||||
|
* Gets the extension's api version
|
||||||
|
*
|
||||||
|
* @return the extension's api version
|
||||||
|
*/
|
||||||
|
String ApiVersion();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the extension's description
|
||||||
|
*
|
||||||
|
* @return the extension's description
|
||||||
|
*/
|
||||||
String version();
|
String version();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the extension's authors
|
||||||
|
*
|
||||||
|
* @return the extension's authors
|
||||||
|
*/
|
||||||
List<String> authors();
|
List<String> authors();
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,15 +27,47 @@ package org.geysermc.geyser.api.extension;
|
||||||
|
|
||||||
import org.geysermc.geyser.api.extension.exception.InvalidDescriptionException;
|
import org.geysermc.geyser.api.extension.exception.InvalidDescriptionException;
|
||||||
import org.geysermc.geyser.api.extension.exception.InvalidExtensionException;
|
import org.geysermc.geyser.api.extension.exception.InvalidExtensionException;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
|
||||||
public interface ExtensionLoader {
|
public interface ExtensionLoader {
|
||||||
|
/**
|
||||||
|
* Loads an extension from a given file
|
||||||
|
*
|
||||||
|
* @param file the file to load the extension from
|
||||||
|
* @return the loaded extension
|
||||||
|
* @throws InvalidExtensionException
|
||||||
|
*/
|
||||||
GeyserExtension loadExtension(File file) throws InvalidExtensionException;
|
GeyserExtension loadExtension(File file) throws InvalidExtensionException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets an extension's description from a given file
|
||||||
|
*
|
||||||
|
* @param file the file to get the description from
|
||||||
|
* @return the extension's description
|
||||||
|
* @throws InvalidDescriptionException
|
||||||
|
*/
|
||||||
ExtensionDescription extensionDescription(File file) throws InvalidDescriptionException;
|
ExtensionDescription extensionDescription(File file) throws InvalidDescriptionException;
|
||||||
Pattern[] extensionFilters();
|
|
||||||
|
/**
|
||||||
|
* Gets a class by its name from the extension's classloader
|
||||||
|
*
|
||||||
|
* @param name the name of the class
|
||||||
|
* @return the class
|
||||||
|
* @throws ClassNotFoundException
|
||||||
|
*/
|
||||||
Class<?> classByName(final String name) throws ClassNotFoundException;
|
Class<?> classByName(final String name) throws ClassNotFoundException;
|
||||||
void enableExtension(Extension extension);
|
|
||||||
void disableExtension(Extension extension);
|
/**
|
||||||
|
* Enables an extension
|
||||||
|
*
|
||||||
|
* @param extension the extension to enable
|
||||||
|
*/
|
||||||
|
void enableExtension(GeyserExtension extension);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disables an extension
|
||||||
|
*
|
||||||
|
* @param extension the extension to disable
|
||||||
|
*/
|
||||||
|
void disableExtension(GeyserExtension extension);
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,7 @@ package org.geysermc.geyser.api.extension;
|
||||||
public interface ExtensionLogger {
|
public interface ExtensionLogger {
|
||||||
/**
|
/**
|
||||||
* Get the logger prefix
|
* Get the logger prefix
|
||||||
|
*
|
||||||
* @return the logger prefix
|
* @return the logger prefix
|
||||||
*/
|
*/
|
||||||
String prefix();
|
String prefix();
|
||||||
|
|
|
@ -30,34 +30,52 @@ import java.io.*;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.net.URLConnection;
|
import java.net.URLConnection;
|
||||||
|
|
||||||
public class GeyserExtension implements Extension {
|
public class GeyserExtension {
|
||||||
private boolean initialized = false;
|
private boolean initialized = false;
|
||||||
private boolean enabled = false;
|
private boolean enabled = false;
|
||||||
private File file = null;
|
private File file = null;
|
||||||
private File dataFolder = null;
|
private File dataFolder = null;
|
||||||
private ClassLoader classLoader = null;
|
private ClassLoader classLoader = null;
|
||||||
private ExtensionLoader loader;
|
private ExtensionLoader loader = null;
|
||||||
private ExtensionLogger logger;
|
private ExtensionLogger logger = null;
|
||||||
private ExtensionDescription description = null;
|
private ExtensionDescription description = null;
|
||||||
private GeyserApiBase api = null;
|
private GeyserApiBase api = null;
|
||||||
|
|
||||||
@Override
|
/**
|
||||||
|
* Called when the extension is loaded
|
||||||
|
*/
|
||||||
public void onLoad() {
|
public void onLoad() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
/**
|
||||||
|
* Called when the extension is enabled
|
||||||
|
*/
|
||||||
public void onEnable() {
|
public void onEnable() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
/**
|
||||||
|
* Called when the extension is disabled
|
||||||
|
*/
|
||||||
public void onDisable() {
|
public void onDisable() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
/**
|
||||||
|
* Gets if the extension is enabled
|
||||||
|
*
|
||||||
|
* @return true if the extension is enabled
|
||||||
|
*/
|
||||||
public boolean isEnabled() {
|
public boolean isEnabled() {
|
||||||
return this.enabled;
|
return this.enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets if the extension is enabled
|
||||||
|
*
|
||||||
|
* @return true if the extension is enabled
|
||||||
|
*/
|
||||||
public void setEnabled(boolean value) {
|
public void setEnabled(boolean value) {
|
||||||
if (this.enabled != value) {
|
if (this.enabled != value) {
|
||||||
this.enabled = value;
|
this.enabled = value;
|
||||||
|
@ -69,27 +87,34 @@ public class GeyserExtension implements Extension {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
/**
|
||||||
public boolean isDisabled() {
|
* Gets the extension's data folder
|
||||||
return !this.enabled;
|
*
|
||||||
}
|
* @return the extension's data folder
|
||||||
|
*/
|
||||||
@Override
|
|
||||||
public File dataFolder() {
|
public File dataFolder() {
|
||||||
return this.dataFolder;
|
return this.dataFolder;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
/**
|
||||||
|
* Gets the extension's description
|
||||||
|
*
|
||||||
|
* @return the extension's description
|
||||||
|
*/
|
||||||
public ExtensionDescription description() {
|
public ExtensionDescription description() {
|
||||||
return this.description;
|
return this.description;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
/**
|
||||||
|
* Gets the extension's name
|
||||||
|
*
|
||||||
|
* @return the extension's name
|
||||||
|
*/
|
||||||
public String name() {
|
public String name() {
|
||||||
return this.description.name();
|
return this.description.name();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void init(GeyserApiBase api, ExtensionLogger logger, ExtensionLoader loader, ExtensionDescription description, File dataFolder, File file) {
|
public void init(GeyserApiBase api, ExtensionLoader loader, ExtensionLogger logger, ExtensionDescription description, File dataFolder, File file) {
|
||||||
if (!this.initialized) {
|
if (!this.initialized) {
|
||||||
this.initialized = true;
|
this.initialized = true;
|
||||||
this.file = file;
|
this.file = file;
|
||||||
|
@ -102,7 +127,12 @@ public class GeyserExtension implements Extension {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
/**
|
||||||
|
* Gets a resource from the extension jar file
|
||||||
|
*
|
||||||
|
* @param filename the file name
|
||||||
|
* @return the input stream
|
||||||
|
*/
|
||||||
public InputStream getResource(String filename) {
|
public InputStream getResource(String filename) {
|
||||||
if (filename == null) {
|
if (filename == null) {
|
||||||
throw new IllegalArgumentException("Filename cannot be null");
|
throw new IllegalArgumentException("Filename cannot be null");
|
||||||
|
@ -123,7 +153,12 @@ public class GeyserExtension implements Extension {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
/**
|
||||||
|
* Saves a resource from the extension jar file to the extension's data folder
|
||||||
|
*
|
||||||
|
* @param filename the file name
|
||||||
|
* @param replace whether to replace the file if it already exists
|
||||||
|
*/
|
||||||
public void saveResource(String filename, boolean replace) {
|
public void saveResource(String filename, boolean replace) {
|
||||||
if (filename == null || filename.equals("")) {
|
if (filename == null || filename.equals("")) {
|
||||||
throw new IllegalArgumentException("ResourcePath cannot be null or empty");
|
throw new IllegalArgumentException("ResourcePath cannot be null or empty");
|
||||||
|
@ -161,22 +196,38 @@ public class GeyserExtension implements Extension {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
/**
|
||||||
|
* Gets the extension's class loader
|
||||||
|
*
|
||||||
|
* @return the extension's class loader
|
||||||
|
*/
|
||||||
public ClassLoader classLoader() {
|
public ClassLoader classLoader() {
|
||||||
return this.classLoader;
|
return this.classLoader;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
/**
|
||||||
|
* Gets the extension's loader
|
||||||
|
*
|
||||||
|
* @return the extension's loader
|
||||||
|
*/
|
||||||
public ExtensionLoader extensionLoader() {
|
public ExtensionLoader extensionLoader() {
|
||||||
return this.loader;
|
return this.loader;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
/**
|
||||||
|
* Gets the extension's logger
|
||||||
|
*
|
||||||
|
* @return the extension's logger
|
||||||
|
*/
|
||||||
public ExtensionLogger logger() {
|
public ExtensionLogger logger() {
|
||||||
return this.logger;
|
return this.logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
/**
|
||||||
|
* Gets the {@link GeyserApiBase} instance
|
||||||
|
*
|
||||||
|
* @return the {@link GeyserApiBase} instance
|
||||||
|
*/
|
||||||
public GeyserApiBase geyserApi() {
|
public GeyserApiBase geyserApi() {
|
||||||
return this.api;
|
return this.api;
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,9 @@
|
||||||
|
|
||||||
package org.geysermc.geyser.api.extension.exception;
|
package org.geysermc.geyser.api.extension.exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Thrown when an extension's description is invalid.
|
||||||
|
*/
|
||||||
public class InvalidDescriptionException extends Exception {
|
public class InvalidDescriptionException extends Exception {
|
||||||
public InvalidDescriptionException(Throwable cause) {
|
public InvalidDescriptionException(Throwable cause) {
|
||||||
super(cause);
|
super(cause);
|
||||||
|
|
|
@ -25,6 +25,9 @@
|
||||||
|
|
||||||
package org.geysermc.geyser.api.extension.exception;
|
package org.geysermc.geyser.api.extension.exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Thrown when an extension is invalid.
|
||||||
|
*/
|
||||||
public class InvalidExtensionException extends Exception {
|
public class InvalidExtensionException extends Exception {
|
||||||
public InvalidExtensionException(Throwable cause) {
|
public InvalidExtensionException(Throwable cause) {
|
||||||
super(cause);
|
super(cause);
|
||||||
|
|
|
@ -33,7 +33,7 @@ import java.util.*;
|
||||||
public class GeyserExtensionDescription implements org.geysermc.geyser.api.extension.ExtensionDescription {
|
public class GeyserExtensionDescription implements org.geysermc.geyser.api.extension.ExtensionDescription {
|
||||||
private String name;
|
private String name;
|
||||||
private String main;
|
private String main;
|
||||||
private List<String> api;
|
private String api;
|
||||||
private String version;
|
private String version;
|
||||||
private final List<String> authors = new ArrayList<>();
|
private final List<String> authors = new ArrayList<>();
|
||||||
|
|
||||||
|
@ -47,19 +47,18 @@ public class GeyserExtensionDescription implements org.geysermc.geyser.api.exten
|
||||||
private void loadMap(Map<String, Object> yamlMap) throws InvalidDescriptionException {
|
private void loadMap(Map<String, Object> yamlMap) throws InvalidDescriptionException {
|
||||||
this.name = ((String) yamlMap.get("name")).replaceAll("[^A-Za-z0-9 _.-]", "");
|
this.name = ((String) yamlMap.get("name")).replaceAll("[^A-Za-z0-9 _.-]", "");
|
||||||
if (this.name.equals("")) {
|
if (this.name.equals("")) {
|
||||||
throw new InvalidDescriptionException("Invalid extension name");
|
throw new InvalidDescriptionException("Invalid extension name, cannot be empty");
|
||||||
}
|
}
|
||||||
this.name = this.name.replace(" ", "_");
|
this.name = this.name.replace(" ", "_");
|
||||||
this.version = String.valueOf(yamlMap.get("version"));
|
this.version = String.valueOf(yamlMap.get("version"));
|
||||||
this.main = (String) yamlMap.get("main");
|
this.main = (String) yamlMap.get("main");
|
||||||
|
|
||||||
Object api = yamlMap.get("api");
|
Object api = yamlMap.get("api");
|
||||||
if (api instanceof List) {
|
if (api instanceof String) {
|
||||||
this.api = (List<String>) api;
|
this.api = (String) api;
|
||||||
} else {
|
} else {
|
||||||
List<String> list = new ArrayList<>();
|
this.api = "0.0.0";
|
||||||
list.add((String) api);
|
throw new InvalidDescriptionException("Invalid api version format, should be a string: major.minor.patch");
|
||||||
this.api = list;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (yamlMap.containsKey("author")) {
|
if (yamlMap.containsKey("author")) {
|
||||||
|
@ -67,7 +66,11 @@ public class GeyserExtensionDescription implements org.geysermc.geyser.api.exten
|
||||||
}
|
}
|
||||||
|
|
||||||
if (yamlMap.containsKey("authors")) {
|
if (yamlMap.containsKey("authors")) {
|
||||||
this.authors.addAll((Collection<? extends String>) yamlMap.get("authors"));
|
try {
|
||||||
|
this.authors.addAll((Collection<? extends String>) yamlMap.get("authors"));
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new InvalidDescriptionException("Invalid authors format, should be a list of strings", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,7 +85,7 @@ public class GeyserExtensionDescription implements org.geysermc.geyser.api.exten
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<String> ApiVersions() {
|
public String ApiVersion() {
|
||||||
return api;
|
return api;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,6 @@ package org.geysermc.geyser.extension;
|
||||||
|
|
||||||
import org.geysermc.api.Geyser;
|
import org.geysermc.api.Geyser;
|
||||||
import org.geysermc.geyser.GeyserImpl;
|
import org.geysermc.geyser.GeyserImpl;
|
||||||
import org.geysermc.geyser.api.extension.Extension;
|
|
||||||
import org.geysermc.geyser.api.extension.ExtensionLoader;
|
import org.geysermc.geyser.api.extension.ExtensionLoader;
|
||||||
import org.geysermc.geyser.api.extension.GeyserExtension;
|
import org.geysermc.geyser.api.extension.GeyserExtension;
|
||||||
import org.geysermc.geyser.api.extension.exception.InvalidDescriptionException;
|
import org.geysermc.geyser.api.extension.exception.InvalidDescriptionException;
|
||||||
|
@ -80,7 +79,7 @@ public class GeyserExtensionLoader implements ExtensionLoader {
|
||||||
|
|
||||||
private void setup(GeyserExtension extension, GeyserExtensionDescription description, File dataFolder, File file) {
|
private void setup(GeyserExtension extension, GeyserExtensionDescription description, File dataFolder, File file) {
|
||||||
GeyserExtensionLogger logger = new GeyserExtensionLogger(GeyserImpl.getInstance().getLogger(), description.name());
|
GeyserExtensionLogger logger = new GeyserExtensionLogger(GeyserImpl.getInstance().getLogger(), description.name());
|
||||||
extension.init(Geyser.api(), logger, this, description, dataFolder, file);
|
extension.init(Geyser.api(), this, logger, description, dataFolder, file);
|
||||||
extension.onLoad();
|
extension.onLoad();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,7 +130,6 @@ public class GeyserExtensionLoader implements ExtensionLoader {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Pattern[] extensionFilters() {
|
public Pattern[] extensionFilters() {
|
||||||
return new Pattern[] { Pattern.compile("^.+\\.jar$") };
|
return new Pattern[] { Pattern.compile("^.+\\.jar$") };
|
||||||
}
|
}
|
||||||
|
@ -152,33 +150,29 @@ public class GeyserExtensionLoader implements ExtensionLoader {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setClass(String name, final Class<?> clazz) {
|
void setClass(String name, final Class<?> clazz) {
|
||||||
if(!classes.containsKey(name)) {
|
if(!classes.containsKey(name)) {
|
||||||
classes.put(name,clazz);
|
classes.put(name,clazz);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void removeClass(String name) {
|
void removeClass(String name) {
|
||||||
Class<?> clazz = classes.remove(name);
|
Class<?> clazz = classes.remove(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void enableExtension(Extension extension) {
|
public void enableExtension(GeyserExtension extension) {
|
||||||
if (extension instanceof GeyserExtension) {
|
if (!extension.isEnabled()) {
|
||||||
if(!extension.isEnabled()) {
|
GeyserImpl.getInstance().getLogger().info("Enabled extension " + extension.description().name());
|
||||||
GeyserImpl.getInstance().getLogger().info("Enabled extension " + extension.description().name());
|
extension.setEnabled(true);
|
||||||
((GeyserExtension) extension).setEnabled(true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void disableExtension(Extension extension) {
|
public void disableExtension(GeyserExtension extension) {
|
||||||
if (extension instanceof GeyserExtension) {
|
if (extension.isEnabled()) {
|
||||||
if(extension.isEnabled()) {
|
GeyserImpl.getInstance().getLogger().info("Disabled extension " + extension.description().name());
|
||||||
GeyserImpl.getInstance().getLogger().info("Disabled extension " + extension.description().name());
|
extension.setEnabled(false);
|
||||||
((GeyserExtension) extension).setEnabled(false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,9 +26,9 @@
|
||||||
package org.geysermc.geyser.extension;
|
package org.geysermc.geyser.extension;
|
||||||
|
|
||||||
import org.geysermc.geyser.GeyserImpl;
|
import org.geysermc.geyser.GeyserImpl;
|
||||||
import org.geysermc.geyser.api.extension.Extension;
|
|
||||||
import org.geysermc.geyser.api.extension.ExtensionDescription;
|
import org.geysermc.geyser.api.extension.ExtensionDescription;
|
||||||
import org.geysermc.geyser.api.extension.GeyserExtension;
|
import org.geysermc.geyser.api.extension.GeyserExtension;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.lang.reflect.Constructor;
|
import java.lang.reflect.Constructor;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
@ -37,35 +37,34 @@ import java.util.regex.Pattern;
|
||||||
public class GeyserExtensionManager {
|
public class GeyserExtensionManager {
|
||||||
private static GeyserExtensionManager geyserExtensionManager = null;
|
private static GeyserExtensionManager geyserExtensionManager = null;
|
||||||
|
|
||||||
protected Map<String, Extension> extensions = new LinkedHashMap<>();
|
protected Map<String, GeyserExtension> extensions = new LinkedHashMap<>();
|
||||||
protected Map<Pattern, GeyserExtensionLoader> fileAssociations = new HashMap<>();
|
protected Map<Pattern, GeyserExtensionLoader> fileAssociations = new HashMap<>();
|
||||||
|
|
||||||
public static void init() {
|
public static void init() {
|
||||||
GeyserImpl.getInstance().getLogger().info("Loading extensions...");
|
GeyserImpl.getInstance().getLogger().info("Loading extensions...");
|
||||||
|
|
||||||
geyserExtensionManager = new GeyserExtensionManager();
|
geyserExtensionManager = new GeyserExtensionManager();
|
||||||
geyserExtensionManager.registerInterface(GeyserExtensionLoader.class);
|
geyserExtensionManager.registerInterface(GeyserExtensionLoader.class);
|
||||||
geyserExtensionManager.loadExtensions(new File("extensions"));
|
geyserExtensionManager.loadExtensions(new File("extensions"));
|
||||||
GeyserImpl.getInstance().getLogger().info("Loaded " + geyserExtensionManager.extensions.size() + " extensions.");
|
|
||||||
|
|
||||||
for (Extension extension : geyserExtensionManager.getExtensions().values()) {
|
String plural = geyserExtensionManager.extensions.size() == 1 ? "" : "s";
|
||||||
if (!extension.isEnabled()) {
|
GeyserImpl.getInstance().getLogger().info("Loaded " + geyserExtensionManager.extensions.size() + " extension" + plural);
|
||||||
geyserExtensionManager.enableExtension(extension);
|
|
||||||
}
|
geyserExtensionManager.enableExtensions();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static GeyserExtensionManager getExtensionManager() {
|
public static GeyserExtensionManager getExtensionManager() {
|
||||||
return geyserExtensionManager;
|
return geyserExtensionManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Extension getExtension(String name) {
|
public GeyserExtension getExtension(String name) {
|
||||||
if (this.extensions.containsKey(name)) {
|
if (this.extensions.containsKey(name)) {
|
||||||
return this.extensions.get(name);
|
return this.extensions.get(name);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<String, Extension> getExtensions() {
|
public Map<String, GeyserExtension> getExtensions() {
|
||||||
return this.extensions;
|
return this.extensions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,8 +123,8 @@ public class GeyserExtensionManager {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<String, Extension> loadExtensions(File dictionary) {
|
public Map<String, GeyserExtension> loadExtensions(File dictionary) {
|
||||||
if (GeyserImpl.VERSION.equalsIgnoreCase("dev")) {
|
if (GeyserImpl.VERSION.equalsIgnoreCase("dev")) { // If your IDE says this is always true, ignore it, it isn't.
|
||||||
GeyserImpl.getInstance().getLogger().error("Cannot load extensions in a development environment, aborting extension loading");
|
GeyserImpl.getInstance().getLogger().error("Cannot load extensions in a development environment, aborting extension loading");
|
||||||
return new HashMap<>();
|
return new HashMap<>();
|
||||||
}
|
}
|
||||||
|
@ -134,6 +133,8 @@ public class GeyserExtensionManager {
|
||||||
return new HashMap<>();
|
return new HashMap<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String[] apiVersion = GeyserImpl.VERSION.split("\\.");
|
||||||
|
|
||||||
if (!dictionary.exists()) {
|
if (!dictionary.exists()) {
|
||||||
dictionary.mkdir();
|
dictionary.mkdir();
|
||||||
}
|
}
|
||||||
|
@ -142,7 +143,7 @@ public class GeyserExtensionManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, File> extensions = new LinkedHashMap<>();
|
Map<String, File> extensions = new LinkedHashMap<>();
|
||||||
Map<String, Extension> loadedExtensions = new LinkedHashMap<>();
|
Map<String, GeyserExtension> loadedExtensions = new LinkedHashMap<>();
|
||||||
|
|
||||||
for (final GeyserExtensionLoader loader : this.fileAssociations.values()) {
|
for (final GeyserExtensionLoader loader : this.fileAssociations.values()) {
|
||||||
for (File file : dictionary.listFiles((dir, name) -> {
|
for (File file : dictionary.listFiles((dir, name) -> {
|
||||||
|
@ -167,47 +168,35 @@ public class GeyserExtensionManager {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean compatible = false;
|
try {
|
||||||
|
//Check the format: majorVersion.minorVersion.patch
|
||||||
for (String version : description.ApiVersions()) {
|
if (!Pattern.matches("^[0-9]+\\.[0-9]+\\.[0-9]+$", description.ApiVersion())) {
|
||||||
try {
|
throw new IllegalArgumentException();
|
||||||
//Check the format: majorVersion.minorVersion.patch
|
|
||||||
if (!Pattern.matches("^[0-9]+\\.[0-9]+\\.[0-9]+$", version)) {
|
|
||||||
throw new IllegalArgumentException();
|
|
||||||
}
|
|
||||||
} catch (NullPointerException | IllegalArgumentException e) {
|
|
||||||
GeyserImpl.getInstance().getLogger().error("Could't load extension " + name + ": Wrong API format");
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
} catch (NullPointerException | IllegalArgumentException e) {
|
||||||
String[] versionArray = version.split("\\.");
|
GeyserImpl.getInstance().getLogger().error("Couldn't load extension " + name + ": Wrong API version format, should be 'majorVersion.minorVersion.patch', current version: " + apiVersion[0] + "." + apiVersion[1]);
|
||||||
String[] apiVersion = GeyserImpl.VERSION.split("\\.");
|
continue;
|
||||||
|
|
||||||
//Completely different API version
|
|
||||||
if (!Objects.equals(Integer.valueOf(versionArray[0]), Integer.valueOf(apiVersion[0]))) {
|
|
||||||
GeyserImpl.getInstance().getLogger().error("Couldn't load extension " + name + ": Wrong API version, current version: " + apiVersion[0] + "." + apiVersion[1]);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
//If the extension requires new API features, being backwards compatible
|
|
||||||
if (Integer.parseInt(versionArray[1]) > Integer.parseInt(apiVersion[1])) {
|
|
||||||
GeyserImpl.getInstance().getLogger().error("Couldn't load extension " + name + ": Wrong API version, current version: " + apiVersion[0] + "." + apiVersion[1]);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
compatible = true;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!compatible) {
|
String[] versionArray = description.ApiVersion().split("\\.");
|
||||||
GeyserImpl.getInstance().getLogger().error("Couldn't load extension " + name +": Incompatible API version");
|
|
||||||
|
//Completely different API version
|
||||||
|
if (!Objects.equals(Integer.valueOf(versionArray[0]), Integer.valueOf(apiVersion[0]))) {
|
||||||
|
GeyserImpl.getInstance().getLogger().error("Couldn't load extension " + name + ": Wrong API version, current version: " + apiVersion[0] + "." + apiVersion[1]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
//If the extension requires new API features, being backwards compatible
|
||||||
|
if (Integer.parseInt(versionArray[1]) > Integer.parseInt(apiVersion[1])) {
|
||||||
|
GeyserImpl.getInstance().getLogger().error("Couldn't load extension " + name + ": Wrong API version, current version: " + apiVersion[0] + "." + apiVersion[1]);
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
extensions.put(name, file);
|
extensions.put(name, file);
|
||||||
loadedExtensions.put(name, this.loadExtension(file, this.fileAssociations));
|
loadedExtensions.put(name, this.loadExtension(file, this.fileAssociations));
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
GeyserImpl.getInstance().getLogger().error("Couldn't load " +file.getName()+ " in folder " + dictionary + ": ", e);
|
GeyserImpl.getInstance().getLogger().error("Couldn't load " + file.getName() + " in folder " + dictionary.getAbsolutePath() + ": ", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -215,7 +204,7 @@ public class GeyserExtensionManager {
|
||||||
return loadedExtensions;
|
return loadedExtensions;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void enableExtension(Extension extension) {
|
public void enableExtension(GeyserExtension extension) {
|
||||||
if (!extension.isEnabled()) {
|
if (!extension.isEnabled()) {
|
||||||
try {
|
try {
|
||||||
extension.extensionLoader().enableExtension(extension);
|
extension.extensionLoader().enableExtension(extension);
|
||||||
|
@ -226,7 +215,7 @@ public class GeyserExtensionManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void disableExtension(Extension extension) {
|
public void disableExtension(GeyserExtension extension) {
|
||||||
if (extension.isEnabled()) {
|
if (extension.isEnabled()) {
|
||||||
try {
|
try {
|
||||||
extension.extensionLoader().disableExtension(extension);
|
extension.extensionLoader().disableExtension(extension);
|
||||||
|
@ -236,8 +225,14 @@ public class GeyserExtensionManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void enableExtensions() {
|
||||||
|
for (GeyserExtension extension : this.getExtensions().values()) {
|
||||||
|
this.enableExtension(extension);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void disableExtensions() {
|
public void disableExtensions() {
|
||||||
for (Extension extension : this.getExtensions().values()) {
|
for (GeyserExtension extension : this.getExtensions().values()) {
|
||||||
this.disableExtension(extension);
|
this.disableExtension(extension);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue