Start PlanBungee

This commit is contained in:
Rsl1122 2017-08-25 15:21:09 +03:00
parent fa7f9327b5
commit 614dd18ffb
12 changed files with 281 additions and 34 deletions

View File

@ -15,15 +15,27 @@
<id>plan-snapshot-repo</id> <id>plan-snapshot-repo</id>
<url>http://repo.fuzzlemann.de/artifactory/libs-snapshot/</url> <url>http://repo.fuzzlemann.de/artifactory/libs-snapshot/</url>
</repository> </repository>
<repository>
<id>bungeecord-repo</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
</repository>
</repositories> </repositories>
<dependencies> <dependencies>
<!-- PaperSpigot 1.12 built with BuildTools for Database classes.--> <!-- PaperSpigot 1.12 -->
<dependency> <dependency>
<groupId>com.destroystokyo.paper</groupId> <groupId>com.destroystokyo.paper</groupId>
<artifactId>paper</artifactId> <artifactId>paper</artifactId>
<version>1.12-R0.1-20170725.202533-1</version> <version>1.12-R0.1-20170725.202533-1</version>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<!-- BungeeCord -->
<dependency>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-api</artifactId>
<version>1.12-SNAPSHOT</version>
<type>jar</type>
<scope>provided</scope>
</dependency>
<!-- Framework for easier plugin development--> <!-- Framework for easier plugin development-->
<dependency> <dependency>
<groupId>com.djrapitops</groupId> <groupId>com.djrapitops</groupId>

View File

@ -1,6 +1,9 @@
package main.java.com.djrapitops.plan; package main.java.com.djrapitops.plan;
import com.djrapitops.plugin.utilities.Compatibility;
import com.djrapitops.plugin.utilities.log.DebugInfo; import com.djrapitops.plugin.utilities.log.DebugInfo;
import com.djrapitops.plugin.utilities.log.PluginLog;
import main.java.com.djrapitops.plan.bungee.PlanBungee;
import main.java.com.djrapitops.plan.utilities.MiscUtils; import main.java.com.djrapitops.plan.utilities.MiscUtils;
import java.util.Collection; import java.util.Collection;
@ -28,7 +31,7 @@ public class Log {
* @param message "Message" will show up as [INFO][Plan]: Message * @param message "Message" will show up as [INFO][Plan]: Message
*/ */
public static void info(String message) { public static void info(String message) {
Plan.getInstance().getPluginLogger().info(message); getPluginLogger().info(message);
} }
/** /**
@ -37,7 +40,7 @@ public class Log {
* @param message Message to send. * @param message Message to send.
*/ */
public static void infoColor(String message) { public static void infoColor(String message) {
Plan.getInstance().getPluginLogger().infoColor(message); getPluginLogger().infoColor(message);
} }
/** /**
@ -46,7 +49,7 @@ public class Log {
* @param message "Message" will show up as [ERROR][Plan]: Message * @param message "Message" will show up as [ERROR][Plan]: Message
*/ */
public static void error(String message) { public static void error(String message) {
Plan.getInstance().getPluginLogger().error(message); getPluginLogger().error(message);
} }
/** /**
@ -55,7 +58,7 @@ public class Log {
* @param message "Message" will show up as [INFO][Plan]: [DEBUG] Message * @param message "Message" will show up as [INFO][Plan]: [DEBUG] Message
*/ */
public static void debug(String message) { public static void debug(String message) {
Plan.getInstance().getPluginLogger().debug(message); getPluginLogger().debug(message);
} }
@ -93,7 +96,7 @@ public class Log {
* @return full debug complex so far. * @return full debug complex so far.
*/ */
public static DebugInfo getDebug(String task) { public static DebugInfo getDebug(String task) {
return Plan.getInstance().getPluginLogger().getDebug(task); return getPluginLogger().getDebug(task);
} }
/** /**
@ -122,7 +125,7 @@ public class Log {
* @param e {@code Throwable}, eg NullPointerException * @param e {@code Throwable}, eg NullPointerException
*/ */
public static void toLog(String source, Throwable e) { public static void toLog(String source, Throwable e) {
Plan.getInstance().getPluginLogger().toLog(source, e); getPluginLogger().toLog(source, e);
} }
/** /**
@ -134,4 +137,12 @@ public class Log {
public static void toLog(String source, Collection<Throwable> e) { public static void toLog(String source, Collection<Throwable> e) {
Plan.getInstance().getPluginLogger().toLog(source, e); Plan.getInstance().getPluginLogger().toLog(source, e);
} }
private static PluginLog getPluginLogger() {
if (Compatibility.isBukkitAvailable()) {
return Plan.getInstance().getPluginLogger();
} else {
return PlanBungee.getInstance().getPluginLogger();
}
}
} }

View File

@ -27,6 +27,7 @@ import com.djrapitops.plugin.task.ITask;
import com.djrapitops.plugin.task.RunnableFactory; import com.djrapitops.plugin.task.RunnableFactory;
import com.djrapitops.plugin.utilities.Verify; import com.djrapitops.plugin.utilities.Verify;
import main.java.com.djrapitops.plan.api.API; import main.java.com.djrapitops.plan.api.API;
import main.java.com.djrapitops.plan.api.IPlan;
import main.java.com.djrapitops.plan.command.PlanCommand; import main.java.com.djrapitops.plan.command.PlanCommand;
import main.java.com.djrapitops.plan.command.commands.RegisterCommandFilter; import main.java.com.djrapitops.plan.command.commands.RegisterCommandFilter;
import main.java.com.djrapitops.plan.data.additional.HookHandler; import main.java.com.djrapitops.plan.data.additional.HookHandler;
@ -51,6 +52,7 @@ import org.apache.logging.log4j.LogManager;
import org.bukkit.ChatColor; import org.bukkit.ChatColor;
import java.util.HashSet; import java.util.HashSet;
import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
@ -63,7 +65,7 @@ import java.util.UUID;
* @author Rsl1122 * @author Rsl1122
* @since 1.0.0 * @since 1.0.0
*/ */
public class Plan extends BukkitPlugin<Plan> { public class Plan extends BukkitPlugin<Plan> implements IPlan {
private API api; private API api;
@ -165,6 +167,8 @@ public class Plan extends BukkitPlugin<Plan> {
infoManager = new InformationManager(this); infoManager = new InformationManager(this);
webServer.setInfoManager(infoManager); webServer.setInfoManager(infoManager);
Benchmark.stop("Enable", "WebServer Initialization");
registerListeners(); registerListeners();
registerTasks(); registerTasks();
@ -270,6 +274,12 @@ public class Plan extends BukkitPlugin<Plan> {
webServer.stop(); webServer.stop();
} }
List<Processor> processors = processingQueue.stopAndReturnLeftovers();
Log.info("Processing unprocessed processors. (" + processors.size() + ")"); // TODO Move to Locale
for (Processor processor : processors) {
processor.process();
}
getServer().getScheduler().cancelTasks(this); getServer().getScheduler().cancelTasks(this);
if (Verify.notNull(infoManager, db)) { if (Verify.notNull(infoManager, db)) {

View File

@ -1,7 +1,5 @@
package main.java.com.djrapitops.plan; package main.java.com.djrapitops.plan;
import org.bukkit.Server;
/** /**
* Class responsible for holding server variable values that do not change * Class responsible for holding server variable values that do not change
* without a reload. * without a reload.
@ -11,6 +9,10 @@ import org.bukkit.Server;
*/ */
public class ServerVariableHolder { public class ServerVariableHolder {
private final String name;
private final int port;
private final String version;
private final String implVersion;
private final String ip; private final String ip;
private final boolean usingPaper; private final boolean usingPaper;
@ -19,14 +21,29 @@ public class ServerVariableHolder {
* *
* @param server instance the plugin is running on. * @param server instance the plugin is running on.
*/ */
public ServerVariableHolder(Server server) { public ServerVariableHolder(org.bukkit.Server server) {
ip = server.getIp(); ip = server.getIp();
name = server.getName();
port = server.getPort();
version = server.getVersion();
implVersion = server.getBukkitVersion();
String serverName = server.getName(); String serverName = server.getName();
usingPaper = serverName.equals("Paper") usingPaper = serverName.equals("Paper")
|| serverName.equals("TacoSpigot"); //Fork of Paper || serverName.equals("TacoSpigot"); //Fork of Paper
} }
public ServerVariableHolder(net.md_5.bungee.api.ProxyServer server) {
ip = "";
name = server.getName();
port = -1;
version = server.getVersion();
implVersion = server.getVersion();
String serverName = "BungeeCord";
usingPaper = false;
}
/** /**
* Ip string in server.properties. * Ip string in server.properties.
* *
@ -44,4 +61,20 @@ public class ServerVariableHolder {
public boolean isUsingPaper() { public boolean isUsingPaper() {
return usingPaper; return usingPaper;
} }
public String getName() {
return name;
}
public int getPort() {
return port;
}
public String getVersion() {
return version;
}
public String getImplVersion() {
return implVersion;
}
} }

View File

@ -0,0 +1,45 @@
/*
* Licence is provided in the jar as license.yml also here:
* https://github.com/Rsl1122/Plan-PlayerAnalytics/blob/master/Plan/src/main/resources/license.yml
*/
package main.java.com.djrapitops.plan.api;
import com.djrapitops.plugin.IPlugin;
import main.java.com.djrapitops.plan.ServerVariableHolder;
import main.java.com.djrapitops.plan.database.Database;
import main.java.com.djrapitops.plan.systems.info.InformationManager;
import main.java.com.djrapitops.plan.systems.info.server.ServerInfoManager;
import main.java.com.djrapitops.plan.systems.processing.Processor;
import main.java.com.djrapitops.plan.systems.queue.ProcessingQueue;
import main.java.com.djrapitops.plan.systems.webserver.WebServer;
import org.bukkit.configuration.file.FileConfiguration;
import java.io.File;
import java.io.InputStream;
/**
* //TODO Class Javadoc Comment
*
* @author Rsl1122
*/
public interface IPlan extends IPlugin {
public Database getDB();
public ServerVariableHolder getVariable();
public ServerInfoManager getServerInfoManager();
public InformationManager getInfoManager();
public WebServer getWebServer();
public File getDataFolder();
public ProcessingQueue getProcessingQueue();
public void addToProcessQueue(Processor... processors);
public InputStream getResource(String resource);
public FileConfiguration getConfig(); // TODO Abstract Config to APF
}

View File

@ -0,0 +1,125 @@
/*
* Licence is provided in the jar as license.yml also here:
* https://github.com/Rsl1122/Plan-PlayerAnalytics/blob/master/Plan/src/main/resources/license.yml
*/
package main.java.com.djrapitops.plan.bungee;
import com.djrapitops.plugin.BungeePlugin;
import com.djrapitops.plugin.settings.ColorScheme;
import main.java.com.djrapitops.plan.Log;
import main.java.com.djrapitops.plan.ServerVariableHolder;
import main.java.com.djrapitops.plan.api.IPlan;
import main.java.com.djrapitops.plan.database.Database;
import main.java.com.djrapitops.plan.systems.info.InformationManager;
import main.java.com.djrapitops.plan.systems.info.server.ServerInfoManager;
import main.java.com.djrapitops.plan.systems.processing.Processor;
import main.java.com.djrapitops.plan.systems.queue.ProcessingQueue;
import main.java.com.djrapitops.plan.systems.webserver.WebServer;
import main.java.com.djrapitops.plan.utilities.Benchmark;
import net.md_5.bungee.api.ChatColor;
import java.io.InputStream;
import java.util.List;
/**
* //TODO Class Javadoc Comment
*
* @author Rsl1122
*/
public class PlanBungee extends BungeePlugin<PlanBungee> implements IPlan {
private WebServer webServer;
private Database db;
private ServerInfoManager serverInfoManager;
private InformationManager infoManager;
private ServerVariableHolder variableHolder;
private ProcessingQueue processingQueue;
public PlanBungee() {
}
@Override
public void onEnable() {
super.setInstance(this);
super.setColorScheme(new ColorScheme(ChatColor.GREEN, ChatColor.GRAY, ChatColor.WHITE));
super.setLogPrefix("[Plan]");
super.setUpdateCheckUrl("https://raw.githubusercontent.com/Rsl1122/Plan-PlayerAnalytics/master/Plan/src/main/resources/plugin.yml");
super.setUpdateUrl("https://www.spigotmc.org/resources/plan-player-analytics.32536/");
super.onEnableDefaultTasks();
Benchmark.start("WebServer Initialization");
webServer = new WebServer(this);
webServer.initServer();
if (!webServer.isEnabled()) {
Log.error("WebServer was not successfully initialized.");
}
serverInfoManager = new ServerInfoManager(this);
infoManager = new InformationManager(this);
webServer.setInfoManager(infoManager);
Benchmark.stop("Enable", "WebServer Initialization");
processingQueue = new ProcessingQueue();
}
public static PlanBungee getInstance() {
return getInstance(PlanBungee.class);
}
@Override
public void onDisable() {
List<Processor> processors = processingQueue.stopAndReturnLeftovers();
Log.info("Processing unprocessed processors. (" + processors.size() + ")");
for (Processor processor : processors) {
processor.process();
}
}
@Override
public Database getDB() {
return db;
}
@Override
public ServerInfoManager getServerInfoManager() {
return serverInfoManager;
}
@Override
public InformationManager getInfoManager() {
return infoManager;
}
@Override
public WebServer getWebServer() {
return webServer;
}
@Override
public ProcessingQueue getProcessingQueue() {
return processingQueue;
}
@Override
public void addToProcessQueue(Processor... processors) {
for (Processor processor : processors) {
processingQueue.addToQueue(processor);
}
}
@Override
public InputStream getResource(String resource) {
return getResourceAsStream(resource);
}
@Override
public ServerVariableHolder getVariable() {
return variableHolder;
}
}

View File

@ -5,8 +5,8 @@ import com.djrapitops.plugin.settings.DefaultMessages;
import com.djrapitops.plugin.utilities.Verify; import com.djrapitops.plugin.utilities.Verify;
import main.java.com.djrapitops.plan.Log; import main.java.com.djrapitops.plan.Log;
import main.java.com.djrapitops.plan.Permissions; import main.java.com.djrapitops.plan.Permissions;
import main.java.com.djrapitops.plan.Plan;
import main.java.com.djrapitops.plan.Settings; import main.java.com.djrapitops.plan.Settings;
import main.java.com.djrapitops.plan.api.IPlan;
import main.java.com.djrapitops.plan.utilities.Benchmark; import main.java.com.djrapitops.plan.utilities.Benchmark;
import main.java.com.djrapitops.plan.utilities.comparators.LocaleEntryComparator; import main.java.com.djrapitops.plan.utilities.comparators.LocaleEntryComparator;
import main.java.com.djrapitops.plan.utilities.comparators.StringLengthComparator; import main.java.com.djrapitops.plan.utilities.comparators.StringLengthComparator;
@ -35,10 +35,10 @@ import java.util.stream.Collectors;
*/ */
public class Locale { public class Locale {
private final Plan plugin; private final IPlan plugin;
private final Map<Msg, Message> messages; private final Map<Msg, Message> messages;
public Locale(Plan plugin) { public Locale(IPlan plugin) {
LocaleHolder.setLocale(this); LocaleHolder.setLocale(this);
this.plugin = plugin; this.plugin = plugin;
messages = new EnumMap<>(Msg.class); messages = new EnumMap<>(Msg.class);

View File

@ -6,6 +6,7 @@ package main.java.com.djrapitops.plan.systems.info;
import com.djrapitops.plugin.command.ISender; import com.djrapitops.plugin.command.ISender;
import main.java.com.djrapitops.plan.Plan; import main.java.com.djrapitops.plan.Plan;
import main.java.com.djrapitops.plan.bungee.PlanBungee;
import main.java.com.djrapitops.plan.command.commands.AnalyzeCommand; import main.java.com.djrapitops.plan.command.commands.AnalyzeCommand;
import main.java.com.djrapitops.plan.data.AnalysisData; import main.java.com.djrapitops.plan.data.AnalysisData;
import main.java.com.djrapitops.plan.database.Database; import main.java.com.djrapitops.plan.database.Database;
@ -27,16 +28,16 @@ import java.util.UUID;
*/ */
public class InformationManager { public class InformationManager {
// TODO Class that manages ALL information for API, WebAPI requests, Command Caching etc. // TODO Class that manages ALL information for API, WebAPI requests, Command Caching etc.
private final Plan plugin; private Plan plugin;
private final Database db; private Database db;
private final DataCache dataCache; private DataCache dataCache;
private boolean usingBungeeWebServer; private boolean usingBungeeWebServer;
private String webServerAddress; private String webServerAddress;
private final Set<ISender> analysisNotification; private Set<ISender> analysisNotification;
private final Analysis analysis; private Analysis analysis;
private AnalysisData analysisData; private AnalysisData analysisData;
private String analysisPluginsTab; private String analysisPluginsTab;
private Long refreshDate; private Long refreshDate;
@ -57,6 +58,10 @@ public class InformationManager {
} }
} }
public InformationManager(PlanBungee plugin) {
// TODO Init info manager.
}
public void attemptBungeeConnection() { public void attemptBungeeConnection() {
// TODO WebAPI bungee connection check // TODO WebAPI bungee connection check
} }

View File

@ -7,10 +7,12 @@ package main.java.com.djrapitops.plan.systems.info.server;
import main.java.com.djrapitops.plan.Log; import main.java.com.djrapitops.plan.Log;
import main.java.com.djrapitops.plan.Plan; import main.java.com.djrapitops.plan.Plan;
import main.java.com.djrapitops.plan.ServerVariableHolder;
import main.java.com.djrapitops.plan.Settings; import main.java.com.djrapitops.plan.Settings;
import main.java.com.djrapitops.plan.api.IPlan;
import main.java.com.djrapitops.plan.bungee.PlanBungee;
import main.java.com.djrapitops.plan.database.Database; import main.java.com.djrapitops.plan.database.Database;
import main.java.com.djrapitops.plan.database.tables.ServerTable; import main.java.com.djrapitops.plan.database.tables.ServerTable;
import org.bukkit.Server;
import org.bukkit.configuration.InvalidConfigurationException; import org.bukkit.configuration.InvalidConfigurationException;
import java.io.IOException; import java.io.IOException;
@ -27,7 +29,7 @@ import java.util.UUID;
*/ */
public class ServerInfoManager { public class ServerInfoManager {
private final Plan plugin; private final IPlan plugin;
private ServerInfo serverInfo; private ServerInfo serverInfo;
private ServerInfoFile serverInfoFile; private ServerInfoFile serverInfoFile;
private final ServerTable serverTable; private final ServerTable serverTable;
@ -60,6 +62,11 @@ public class ServerInfoManager {
} }
} }
public ServerInfoManager(PlanBungee plugin) {
this.plugin = plugin;
serverTable = plugin.getDB().getServerTable();
}
private void updateDbInfo(UUID serverUUID) throws SQLException, IOException { private void updateDbInfo(UUID serverUUID) throws SQLException, IOException {
Optional<Integer> serverID = serverTable.getServerID(serverUUID); Optional<Integer> serverID = serverTable.getServerID(serverUUID);
if (!serverID.isPresent()) { if (!serverID.isPresent()) {
@ -77,7 +84,7 @@ public class ServerInfoManager {
} }
private void registerServer() throws SQLException, IOException { private void registerServer() throws SQLException, IOException {
registerServer(generateNewUUID(plugin.getServer())); registerServer(generateNewUUID(plugin.getVariable()));
} }
private void registerServer(UUID serverUUID) throws SQLException, IOException { private void registerServer(UUID serverUUID) throws SQLException, IOException {
@ -96,8 +103,8 @@ public class ServerInfoManager {
serverInfoFile.saveInfo(serverInfo, new ServerInfo(id, serverUUID, name, webAddress)); serverInfoFile.saveInfo(serverInfo, new ServerInfo(id, serverUUID, name, webAddress));
} }
private UUID generateNewUUID(Server server) { private UUID generateNewUUID(ServerVariableHolder variableHolder) {
String seed = server.getName() + server.getIp() + server.getPort() + server.getVersion() + server.getBukkitVersion(); String seed = variableHolder.getName() + variableHolder.getIp() + variableHolder.getPort() + variableHolder.getVersion() + variableHolder.getImplVersion();
return UUID.nameUUIDFromBytes(seed.getBytes()); return UUID.nameUUIDFromBytes(seed.getBytes());
} }

View File

@ -5,6 +5,7 @@ import com.sun.net.httpserver.*;
import main.java.com.djrapitops.plan.Log; import main.java.com.djrapitops.plan.Log;
import main.java.com.djrapitops.plan.Plan; import main.java.com.djrapitops.plan.Plan;
import main.java.com.djrapitops.plan.Settings; import main.java.com.djrapitops.plan.Settings;
import main.java.com.djrapitops.plan.api.IPlan;
import main.java.com.djrapitops.plan.data.WebUser; import main.java.com.djrapitops.plan.data.WebUser;
import main.java.com.djrapitops.plan.database.tables.SecurityTable; import main.java.com.djrapitops.plan.database.tables.SecurityTable;
import main.java.com.djrapitops.plan.locale.Locale; import main.java.com.djrapitops.plan.locale.Locale;
@ -47,7 +48,7 @@ import java.util.zip.GZIPOutputStream;
*/ */
public class WebServer { public class WebServer {
private final Plan plugin; private final IPlan plugin;
private InformationManager infoManager; private InformationManager infoManager;
private final int port; private final int port;
@ -57,11 +58,10 @@ public class WebServer {
private boolean usingHttps = false; private boolean usingHttps = false;
/** /**
* Class Constructor.
* *
* @param plugin Current instance of Plan * @param plugin
*/ */
public WebServer(Plan plugin) { public WebServer(IPlan plugin) {
this.plugin = plugin; this.plugin = plugin;
this.port = Settings.WEBSERVER_PORT.getNumber(); this.port = Settings.WEBSERVER_PORT.getNumber();
@ -411,7 +411,7 @@ public class WebServer {
String page = args[1]; String page = args[1];
switch (page) { switch (page) {
case "players": case "players":
return PageCache.loadPage("players", () -> new PlayersPageResponse(plugin)); return PageCache.loadPage("players", PlayersPageResponse::new);
case "player": case "player":
return playerResponse(args); return playerResponse(args);
case "server": case "server":
@ -451,7 +451,7 @@ public class WebServer {
case 0: case 0:
return serverResponse(); return serverResponse();
case 1: case 1:
return PageCache.loadPage("players", () -> new PlayersPageResponse(plugin)); return PageCache.loadPage("players", PlayersPageResponse::new);
case 2: case 2:
return playerResponse(new String[]{"", "", user.getName()}); return playerResponse(new String[]{"", "", user.getName()});
default: default:

View File

@ -1,6 +1,5 @@
package main.java.com.djrapitops.plan.systems.webserver.response; package main.java.com.djrapitops.plan.systems.webserver.response;
import main.java.com.djrapitops.plan.Plan;
import main.java.com.djrapitops.plan.data.UserInfo; import main.java.com.djrapitops.plan.data.UserInfo;
import main.java.com.djrapitops.plan.utilities.comparators.UserDataNameComparator; import main.java.com.djrapitops.plan.utilities.comparators.UserDataNameComparator;
import main.java.com.djrapitops.plan.utilities.html.Html; import main.java.com.djrapitops.plan.utilities.html.Html;
@ -14,7 +13,7 @@ import java.util.List;
*/ */
public class PlayersPageResponse extends Response { public class PlayersPageResponse extends Response {
public PlayersPageResponse(Plan plugin) { public PlayersPageResponse() {
super.setHeader("HTTP/1.1 200 OK"); super.setHeader("HTTP/1.1 200 OK");
// super.setContent(buildContent(plugin.getInspectCache().getCachedUserData())); // super.setContent(buildContent(plugin.getInspectCache().getCachedUserData()));
} }

View File

@ -2,8 +2,8 @@ package main.java.com.djrapitops.plan.utilities.file;
import com.djrapitops.plugin.utilities.Verify; import com.djrapitops.plugin.utilities.Verify;
import main.java.com.djrapitops.plan.Plan; import main.java.com.djrapitops.plan.Plan;
import main.java.com.djrapitops.plan.api.IPlan;
import main.java.com.djrapitops.plan.utilities.MiscUtils; import main.java.com.djrapitops.plan.utilities.MiscUtils;
import org.bukkit.plugin.java.JavaPlugin;
import java.io.File; import java.io.File;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
@ -49,7 +49,7 @@ public class FileUtil {
} }
} }
public static List<String> lines(JavaPlugin plugin, String resource) throws IOException { public static List<String> lines(IPlan plugin, String resource) throws IOException {
List<String> lines = new ArrayList<>(); List<String> lines = new ArrayList<>();
Scanner scanner = null; Scanner scanner = null;
try (InputStream inputStream = plugin.getResource(resource)) { try (InputStream inputStream = plugin.getResource(resource)) {