package eu.mikroskeem.utils.bukkit.fakeplugin; import eu.mikroskeem.utils.reflect.Reflect; import lombok.Getter; import org.bukkit.Bukkit; import org.bukkit.plugin.Plugin; import org.bukkit.plugin.SimplePluginManager; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.List; import java.util.Locale; import java.util.Map; import static com.google.common.base.Preconditions.checkNotNull; public class FakePluginFactory { private final List fakePlugins = new ArrayList<>(); private final Plugin plugin; private final List plugins; @Getter private final Map lookupNames; private final boolean isPaper; @SuppressWarnings("unchecked") public FakePluginFactory(Plugin parentPlugin){ this.plugin = parentPlugin; Field lookupNamesField, pluginsField; if(plugin.getServer().getPluginManager().getClass() != SimplePluginManager.class){ throw new RuntimeException("Server PluginManager is not SimplePluginManager"); } isPaper = Reflect.getMethod(Bukkit.class, "getTPS") != null; try { pluginsField = checkNotNull(Reflect.getField( SimplePluginManager.class, "plugins")); lookupNamesField = checkNotNull(Reflect.getField( SimplePluginManager.class, "lookupNames")); plugins = (List) checkNotNull(Reflect.readField(pluginsField, plugin.getServer().getPluginManager())); lookupNames = (Map) checkNotNull(Reflect.readField(lookupNamesField, plugin.getServer().getPluginManager())); } catch (NullPointerException e){ throw new RuntimeException("Failed to get 'plugins' and 'lookupNames' field!"); } } @SuppressWarnings("unchecked") public synchronized T newPlugin(String name, String version, String mainClass){ T fakePlugin = (T) new AbstractFakePlugin(plugin, name, version, mainClass, null, null){}; fakePlugins.add(fakePlugin); return fakePlugin; } public synchronized void addPlugin(T plugin){ /* Note: took me 5 hours to realize lookupNames map keys are lower case (on PaperSpigot) * Note 2: Took me another 5 hours to realize lower case lookupNames keys are *only* on PaperSpigot */ String lookupName = isPaper?plugin.getName().toLowerCase(Locale.ENGLISH):plugin.getName(); lookupNames.put(lookupName, plugin); plugins.add(plugin); fakePlugins.add(plugin); } public synchronized void removePlugin(T plugin){ if (plugins.contains(plugin)) plugins.remove(plugin); if (lookupNames.containsKey(plugin.getName())) { String lookupName = isPaper?plugin.getName().toLowerCase(Locale.ENGLISH):plugin.getName(); lookupNames.remove(lookupName); } if (fakePlugins.contains(plugin)) fakePlugins.remove(plugin); } /* Note: Not needed, SimplePluginManager handles plugin removal already synchronized void removeAllPlugins() { fakePlugins.forEach(this::removePlugin); } */ }