package eu.mikroskeem.utils.bukkit.fakeplugin; import eu.mikroskeem.shuriken.reflect.Reflect; import eu.mikroskeem.shuriken.reflect.simple.SimpleReflect; import eu.mikroskeem.shuriken.reflect.wrappers.ClassWrapper; import lombok.Getter; import org.bukkit.Bukkit; import org.bukkit.plugin.Plugin; import org.bukkit.plugin.SimplePluginManager; 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; if(plugin.getServer().getPluginManager().getClass() != SimplePluginManager.class){ throw new RuntimeException("Server PluginManager is not SimplePluginManager"); } isPaper = SimpleReflect.getMethod(Bukkit.class, "getTPS", double[].class) != null; try { ClassWrapper spm = Reflect.wrapClass(SimplePluginManager.class) .setClassInstance(plugin.getServer().getPluginManager()); plugins = (List) checkNotNull(spm.getField("plugins", List.class).orElse(null)).read(); lookupNames = (Map) checkNotNull(spm.getField("lookupNames", Map.class).orElse(null)).read(); } catch (Exception e){ e.printStackTrace(); 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); } */ }