Compare commits
3 Commits
Dockable-C
...
master
Author | SHA1 | Date | |
---|---|---|---|
ee99312a12 | |||
545e7bacc6 | |||
b142b6d05e |
19
README.md
19
README.md
@ -1,13 +1,14 @@
|
||||
# Minecraft-Server-Launcher
|
||||
I originally created this software in 2013 using AutoIt. After learning Java, I recreated it in Java.
|
||||
The original version can be found at: https://archive.knarcraft.net/Scripts/BungeeMinecraftServerLauncher/
|
||||
This version's goal is to do everything the original does, just better. The original is 1595 lines of code repetition
|
||||
and dirty code. I had no prior programming experience when I first started working on the original, which is why it
|
||||
|
||||
I originally created this software in 2013 using AutoIt. After learning Java, I recreated it in Java. The original
|
||||
version can be found at: https://archive.knarcraft.net/Scripts/BungeeMinecraftServerLauncher/
|
||||
This version's goal is to do everything the original does, just better. The original is 1595 lines of code repetition
|
||||
and dirty code. I had no prior programming experience when I first started working on the original, which is why it
|
||||
became such a mess.
|
||||
|
||||
The software is in a fully working stage with a functional updater. The software is still in beta because there are still
|
||||
a lot of things I want to change and small annoyances. The software is fully portable. Make sure to put it in its own
|
||||
folder as it will create lots of files.
|
||||
The software is in a fully working stage with a functional updater. The software is still in beta because there are
|
||||
still a lot of things I want to change and small annoyances. The software is fully portable. Make sure to put it in its
|
||||
own folder as it will create lots of files.
|
||||
|
||||
The updater will move the new version to minecraft-server-launcher.jar, so you should rename the downloaded
|
||||
file to this if it's named something else to avoid confusion.
|
||||
The updater will move the new version to minecraft-server-launcher.jar, so you should rename the downloaded file to this
|
||||
if it's named something else to avoid confusion.
|
@ -1,3 +1,3 @@
|
||||
As this is a personal one-man project, I prefer to stay in charge of the code.
|
||||
I appreciate code fixing mistakes, or code improvements, but the software's functionality or purpose, should not be changed.
|
||||
I might change anything at any time, so you might want to keep that in mind before doing big changes yourself.
|
||||
As this is a personal one-man project, I prefer to stay in charge of the code. I appreciate code fixing mistakes, or
|
||||
code improvements, but the software's functionality or purpose, should not be changed. I might change anything at any
|
||||
time, so you might want to keep that in mind before doing big changes yourself.
|
||||
|
@ -1,6 +1,7 @@
|
||||
Fixes # .
|
||||
|
||||
Proposed changes:
|
||||
|
||||
-
|
||||
-
|
||||
-
|
||||
|
@ -1,10 +1,10 @@
|
||||
package net.knarcraft.minecraftserverlauncher.utility;
|
||||
package net.knarcraft.minecraftserverlauncher.server;
|
||||
|
||||
import net.knarcraft.minecraftserverlauncher.Main;
|
||||
import net.knarcraft.minecraftserverlauncher.profile.ServerLauncherController;
|
||||
import net.knarcraft.minecraftserverlauncher.server.ServerVersionContainer;
|
||||
import net.knarcraft.minecraftserverlauncher.userinterface.GUI;
|
||||
import net.knarcraft.minecraftserverlauncher.userinterface.ServerLauncherGUI;
|
||||
import net.knarcraft.minecraftserverlauncher.utility.CommonFunctions;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.BufferedWriter;
|
@ -377,7 +377,8 @@ public class Server {
|
||||
if (Integer.parseInt(serverVersion.split("\\.")[1]) >= 17) {
|
||||
return controller.getJavaCommand();
|
||||
}
|
||||
} catch (NumberFormatException ignored) {}
|
||||
} catch (NumberFormatException ignored) {
|
||||
}
|
||||
}
|
||||
return controller.getOldJavaCommand();
|
||||
}
|
||||
|
@ -311,7 +311,7 @@ public class ServerVersionContainer {
|
||||
/**
|
||||
* Sets the current version for a given paper version
|
||||
*
|
||||
* @param mapKey <p>The version key to set version for</p>
|
||||
* @param mapKey <p>The version key to set version for</p>
|
||||
* @param newValue <p>The new current version</p>
|
||||
*/
|
||||
public void setPaperVersion(String mapKey, String newValue) {
|
||||
|
@ -2,8 +2,8 @@ package net.knarcraft.minecraftserverlauncher.server.servertypes;
|
||||
|
||||
import net.knarcraft.minecraftserverlauncher.Main;
|
||||
import net.knarcraft.minecraftserverlauncher.profile.ServerLauncherController;
|
||||
import net.knarcraft.minecraftserverlauncher.server.JarBuilder;
|
||||
import net.knarcraft.minecraftserverlauncher.userinterface.GUI;
|
||||
import net.knarcraft.minecraftserverlauncher.utility.JarBuilder;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.file.Paths;
|
||||
|
@ -50,13 +50,21 @@ public class Waterfall extends AbstractServerType {
|
||||
public boolean downloadJar(String folder, String version) throws IOException {
|
||||
String file = this.getName() + version + ".jar";
|
||||
File filePath = new File(folder + file);
|
||||
String newestVersion = stringBetween(readRemoteFile(versionURL + version), srcStart, srcEnd);
|
||||
String fullURL = downloadURL + version + "/" + newestVersion + "/download";
|
||||
String versionFileContents = readRemoteFile(versionURL + version);
|
||||
String[] versions = stringBetween(versionFileContents, srcStart, srcEnd).split(",");
|
||||
String newestVersion = versions[versions.length - 1];
|
||||
String oldVersion = oldVersionFunction.apply(version);
|
||||
|
||||
//The file is already the newest version
|
||||
if (filePath.isFile() && newestVersion.equals(oldVersion)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
//Get necessary information for downloading the latest version
|
||||
String newestVersionInfoURL = versionURL + version + "/builds/" + newestVersion;
|
||||
String fileName = stringBetween(readRemoteFile(newestVersionInfoURL), "\"name\":\"", "\"");
|
||||
String fullURL = downloadURL + version + "/builds/" + newestVersion + "/downloads/" + fileName;
|
||||
|
||||
//The new jar file could not be downloaded
|
||||
if (!downloadFile(fullURL, Paths.get(filePath.toURI()))) {
|
||||
return false;
|
||||
@ -64,4 +72,5 @@ public class Waterfall extends AbstractServerType {
|
||||
versionUpdateFunction.accept(version, newestVersion);
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -51,7 +51,7 @@ public class BackupGUI implements ActionListener {
|
||||
JPanel panel = new JPanel();
|
||||
panel.setLayout(new BoxLayout(panel, BoxLayout.PAGE_AXIS));
|
||||
panel.add(progressTextArea);
|
||||
panel.add(Box.createRigidArea(new Dimension(0,5)));
|
||||
panel.add(Box.createRigidArea(new Dimension(0, 5)));
|
||||
panel.add(progressBar);
|
||||
|
||||
JPanel buttonPane = new JPanel();
|
||||
@ -71,7 +71,7 @@ public class BackupGUI implements ActionListener {
|
||||
/**
|
||||
* Updates information about the backup progress
|
||||
*
|
||||
* @param infoText <p>The text to display</p>
|
||||
* @param infoText <p>The text to display</p>
|
||||
* @param progressPercent <p>The new percent of the progress bar</p>
|
||||
*/
|
||||
public static void updateProgress(String infoText, int progressPercent) {
|
||||
|
@ -17,6 +17,7 @@ public class CloseTabActionListener implements ActionListener {
|
||||
|
||||
/**
|
||||
* Instantiates a new close tab action listener
|
||||
*
|
||||
* @param tabPane <p>The tab pane containing all tabs</p>
|
||||
* @param tabName <p>The name of the tab connected to this action listener</p>
|
||||
*/
|
||||
|
@ -33,6 +33,7 @@ public class ControlPanelTab implements ActionListener {
|
||||
|
||||
/**
|
||||
* Sets the text of the status label
|
||||
*
|
||||
* @param text <p>The new text of the status label</p>
|
||||
*/
|
||||
public void setStatusText(String text) {
|
||||
|
@ -1,35 +0,0 @@
|
||||
package net.knarcraft.minecraftserverlauncher.userinterface;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
/**
|
||||
* An extended JTabbedPane with dockable tabs
|
||||
*/
|
||||
public class JDockableTabbedPane extends JTabbedPane {
|
||||
|
||||
private String tabbedPaneId;
|
||||
|
||||
public JDockableTabbedPane(String tabbedPaneId) {
|
||||
super();
|
||||
this.tabbedPaneId = tabbedPaneId;
|
||||
}
|
||||
|
||||
public JDockableTabbedPane(String tabbedPaneId, int tabPlacement) {
|
||||
super(tabPlacement);
|
||||
this.tabbedPaneId = tabbedPaneId;
|
||||
}
|
||||
|
||||
public JDockableTabbedPane(String tabbedPaneId, int tabPlacement, int tabLayoutPolicy) {
|
||||
super(tabPlacement, tabLayoutPolicy);
|
||||
this.tabbedPaneId = tabbedPaneId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the id of this tabbed pane
|
||||
* @return <p>The id of this tabbed pane</p>
|
||||
*/
|
||||
public String getTabbedPaneId() {
|
||||
return tabbedPaneId;
|
||||
}
|
||||
|
||||
}
|
@ -93,6 +93,7 @@ public class ServerLauncherGUI extends MessageHandler implements ActionListener,
|
||||
|
||||
/**
|
||||
* Gets this GUI's control panel tab
|
||||
*
|
||||
* @return <p>The control panel tab for this GUI</p>
|
||||
*/
|
||||
public ControlPanelTab getControlPanelTab() {
|
||||
@ -168,7 +169,7 @@ public class ServerLauncherGUI extends MessageHandler implements ActionListener,
|
||||
addServerTabButton.addActionListener(this);
|
||||
addServerPaneButton = getAddServerButton(false);
|
||||
addServerPaneButton.addActionListener(this);
|
||||
|
||||
|
||||
tabContentsPanel.add(addServerTabButton);
|
||||
tabPanel.add(addServerPaneButton);
|
||||
serversPane.setTabComponentAt(serversPane.getTabCount() - 1, tabPanel);
|
||||
@ -176,6 +177,7 @@ public class ServerLauncherGUI extends MessageHandler implements ActionListener,
|
||||
|
||||
/**
|
||||
* Gets a button for adding a new server
|
||||
*
|
||||
* @param displayButtonStyle <p>Whether to show or hide the button's style</p>
|
||||
* @return <p>A new add server button</p>
|
||||
*/
|
||||
@ -193,7 +195,6 @@ public class ServerLauncherGUI extends MessageHandler implements ActionListener,
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param serverName <p>The name of the server/tab to add a close button to</p>
|
||||
*/
|
||||
private void addCloseButtonToServerTab(String serverName) {
|
||||
|
@ -164,7 +164,7 @@ public class ServerLauncherMenu implements ActionListener {
|
||||
* Creates a checkbox menu item
|
||||
*
|
||||
* @param itemName <p>The name of the new checkbox item</p>
|
||||
* @param parent <p>The parent menu the item belongs to</p>
|
||||
* @param parent <p>The parent menu the item belongs to</p>
|
||||
* @return <p>The created checkbox menu item</p>
|
||||
*/
|
||||
private JCheckBoxMenuItem createCheckBoxMenuItem(String itemName, JMenu parent) {
|
||||
@ -178,7 +178,7 @@ public class ServerLauncherMenu implements ActionListener {
|
||||
* Creates a menu item
|
||||
*
|
||||
* @param itemName <p>The name of the new item</p>
|
||||
* @param parent <p>The parent menu the item belongs to</p>
|
||||
* @param parent <p>The parent menu the item belongs to</p>
|
||||
* @return <p>The created menu item</p>
|
||||
*/
|
||||
private JMenuItem createMenuItem(String itemName, JMenu parent) {
|
||||
@ -190,6 +190,7 @@ public class ServerLauncherMenu implements ActionListener {
|
||||
|
||||
/**
|
||||
* Asks the user for the new Java path
|
||||
*
|
||||
* @param old <p>Whether asking for the path to the old java version</p>
|
||||
*/
|
||||
private void configureJava(boolean old) {
|
||||
|
@ -1,61 +0,0 @@
|
||||
package net.knarcraft.minecraftserverlauncher.userinterface;
|
||||
|
||||
import javax.swing.event.MouseInputAdapter;
|
||||
import java.awt.*;
|
||||
import java.awt.event.MouseEvent;
|
||||
|
||||
/**
|
||||
* A listener for detecting the dragging of a tab to make it dock or undock
|
||||
*/
|
||||
public class TabDragListener extends MouseInputAdapter {
|
||||
|
||||
Point dragStartPoint;
|
||||
Component draggedComponent;
|
||||
String draggedTabTitle;
|
||||
JDockableTabbedPane tabbedPaneToListenTo;
|
||||
|
||||
public TabDragListener(JDockableTabbedPane tabbedPaneToListenTo) {
|
||||
this.tabbedPaneToListenTo = tabbedPaneToListenTo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mousePressed(MouseEvent e) {
|
||||
dragStartPoint = e.getPoint();
|
||||
|
||||
//Loop through tabbed panes to find the dragged one
|
||||
for (int i = 0; i < tabbedPaneToListenTo.getTabCount(); i++) {
|
||||
Rectangle bounds = tabbedPaneToListenTo.getBoundsAt(i);
|
||||
if (bounds.contains(dragStartPoint)) {
|
||||
draggedComponent = tabbedPaneToListenTo.getComponentAt(i);
|
||||
draggedTabTitle = tabbedPaneToListenTo.getTitleAt(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseDragged(MouseEvent e) {
|
||||
Point dragEndPoint = e.getPoint();
|
||||
if (draggedComponent != null) {
|
||||
// check for a significant drag
|
||||
//TODO: Check if tab is dragged onto another JDockableTabbedPane with the same id
|
||||
if (Math.abs(dragEndPoint.getY() - dragStartPoint.getY()) > 30) {
|
||||
|
||||
//TODO: Undock by creating a new JDockableTabbedPane with the same id
|
||||
//TODO: If dragging onto another JDockableTabbedPane with the same id, combine
|
||||
//TODO: Make the listener keep track of all its created windows
|
||||
//TODO: If a child window is closed, dock its tab to the main window
|
||||
//TODO: Keep track of the original window vs. the child window
|
||||
//undock(draggedComponent, draggedTabTitle);
|
||||
draggedComponent = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseReleased(MouseEvent arg0) {
|
||||
draggedComponent = null;
|
||||
draggedTabTitle = null;
|
||||
}
|
||||
|
||||
}
|
@ -22,11 +22,15 @@ import java.util.stream.Stream;
|
||||
/**
|
||||
* A helper class for performing server backup
|
||||
*/
|
||||
public class BackupUtil {
|
||||
public final class BackupUtil {
|
||||
|
||||
private static boolean backupAborted;
|
||||
private static boolean backupRunning = false;
|
||||
|
||||
private BackupUtil() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Aborts the currently running backup
|
||||
*/
|
||||
@ -44,7 +48,7 @@ public class BackupUtil {
|
||||
* @throws IOException <p>If we can't start a file stream</p>
|
||||
*/
|
||||
private static long backupFolder(File source, File destination, long backupFileSize,
|
||||
long alreadyCopied) throws IOException {
|
||||
long alreadyCopied) throws IOException {
|
||||
if (backupAborted) {
|
||||
return 0L;
|
||||
}
|
||||
@ -136,8 +140,9 @@ public class BackupUtil {
|
||||
|
||||
/**
|
||||
* Performs the actual backup after checks have passed and necessary info is available
|
||||
* @param gui <p>The GUI to use for informing the user</p>
|
||||
* @param serverFolders <p>The folders of the servers to backup</p>
|
||||
*
|
||||
* @param gui <p>The GUI to use for informing the user</p>
|
||||
* @param serverFolders <p>The folders of the servers to backup</p>
|
||||
* @param backupFileSize <p>The total size of the folders to backup</p>
|
||||
*/
|
||||
private static void performBackup(GUI gui, List<List<File>> serverFolders, long backupFileSize) {
|
||||
@ -164,10 +169,10 @@ public class BackupUtil {
|
||||
/**
|
||||
* Backs up the files for a single server
|
||||
*
|
||||
* @param gui <p>The GUI to use for informing the user</p>
|
||||
* @param serverFolder <p>The server's input and output folders</p>
|
||||
* @param gui <p>The GUI to use for informing the user</p>
|
||||
* @param serverFolder <p>The server's input and output folders</p>
|
||||
* @param backupFileSize <p>The total size of the files to backup</p>
|
||||
* @param alreadyCopied <p>The amount of bytes already copied</p>
|
||||
* @param alreadyCopied <p>The amount of bytes already copied</p>
|
||||
* @return <p>The new amount of bytes copied</p>
|
||||
*/
|
||||
private static long backupServerFiles(GUI gui, List<File> serverFolder, long backupFileSize, long alreadyCopied) {
|
||||
|
@ -126,6 +126,7 @@ public final class CommonFunctions {
|
||||
|
||||
/**
|
||||
* Gets a buffered writer for writing to a given file
|
||||
*
|
||||
* @param path <p>The path to the file to write to</p>
|
||||
* @return <p>A buffered writer for writing to the file</p>
|
||||
* @throws FileNotFoundException <p>If the file does not exist</p>
|
||||
@ -149,8 +150,8 @@ public final class CommonFunctions {
|
||||
/**
|
||||
* Writes text to a file and adds a trailing newline
|
||||
*
|
||||
* @param path <p>The path of the file to write to</p>
|
||||
* @param text <p>The text to write</p>
|
||||
* @param path <p>The path of the file to write to</p>
|
||||
* @param text <p>The text to write</p>
|
||||
* @throws IOException <p>If unable to write to the file</p>
|
||||
*/
|
||||
public static void writeFile(String path, String text) throws IOException {
|
||||
@ -243,7 +244,6 @@ public final class CommonFunctions {
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Validates that a name is not empty and does not contain invalid characters
|
||||
*
|
||||
@ -259,7 +259,7 @@ public final class CommonFunctions {
|
||||
*
|
||||
* @param target <p>The folder to delete from</p>
|
||||
*/
|
||||
static void removeFilesRecursively(File target) {
|
||||
public static void removeFilesRecursively(File target) {
|
||||
File[] oldFiles = target.listFiles();
|
||||
if (oldFiles == null) {
|
||||
throw new IllegalArgumentException("Unable to list files in directory");
|
||||
|
@ -1,2 +1,2 @@
|
||||
beta
|
||||
1.4.0
|
||||
1.4.3
|
|
@ -1,11 +1,11 @@
|
||||
Vanilla;Latest,Snapshot,1.17.1,1.16.5,1.15.2,1.14.4,1.13.2,1.12.2,1.11.2,1.10.2,1.9.4,1.8.9,1.7.10,1.6.4,1.5.2,1.4.7,1.3.2,1.2.5;https://launchermeta.mojang.com/mc/game/version_manifest.json;"release":";";https://s3.amazonaws.com/Minecraft.Download/versions/
|
||||
Vanilla;Latest,Snapshot,1.18.1,1.17.1,1.16.5,1.15.2,1.14.4,1.13.2,1.12.2,1.11.2,1.10.2,1.9.4,1.8.9,1.7.10,1.6.4,1.5.2,1.4.7,1.3.2,1.2.5;https://launchermeta.mojang.com/mc/game/version_manifest.json;"release":";";https://s3.amazonaws.com/Minecraft.Download/versions/
|
||||
Spigot;Latest,1.17.1,1.16.5,1.15.2,1.14.4,1.13.2,1.12.2,1.11.2,1.10.2,1.9.4,1.9.4,1.8.8,1.7.10,1.6.4-R2.1,1.5.2-R1.1,1.4.7-R1.1;https://static.knarcraft.net/archive/downloads/minecraftserverjars/Spigot/;spigot-
|
||||
Paper;1.17.1,1.16.5,1.15.2,1.14.4,1.13.2,1.12.2,1.11.2,1.10.2,1.9.4,1.8.8;https://papermc.io/api/v1/paper/;"latest":;,;https://papermc.io/api/v1/paper/
|
||||
Paper;1.18.1,1.17.1,1.16.5,1.15.2,1.14.4,1.13.2,1.12.2,1.11.2,1.10.2,1.9.4,1.8.8;https://papermc.io/api/v2/projects/paper/versions/;"builds":[;];https://papermc.io/api/v2/projects/paper/versions/
|
||||
#SpongeVanilla;1.12.2,1.11.2,1.10.2,1.8.9;https://dl-api.spongepowered.org/v1/org.spongepowered/spongevanilla/downloads?type=stable&minecraft=;"version":";",;https://repo.spongepowered.org/maven/org/spongepowered/spongevanilla/;/spongevanilla-
|
||||
Craftbukkit;Latest,1.17.1,1.16.5,1.15.2,1.14.4,1.13.2,1.12.2,1.11.2,1.10.2,1.9.4,1.8.8,1.7.10-R0.1,1.6.4-R2.0,1.5.2-R1.0,1.4.6-R0.3,1.3.2-R3.0,1.2.5-R2.0,1.1-R6,1.0.1-R1,b1.8.1,b1.7.3;https://static.knarcraft.net/archive/downloads/minecraftserverjars/Bukkit/;craftbukkit-
|
||||
#SpongeForge;1.12.2,1.11.2,1.10.2;https://dl-api.spongepowered.org/v1/org.spongepowered/spongeforge/downloads?type=stable&minecraft=;"version":";",;https://repo.spongepowered.org/maven/org/spongepowered/spongeforge/;/spongeforge-
|
||||
MCPCplus;1.6.4,1.6.2,1.5.2,1.4.7;https://static.knarcraft.net/archive/downloads/minecraftserverjars/MCPC+/;mcpcplus
|
||||
Bungee;Latest,1.7.10,1.6.4,1.5.2,1.4.7;https://ci.md-5.net/job/BungeeCord/lastSuccessfulBuild/artifact/bootstrap/target/;Artifacts of BungeeCord #; ;http://ci.md-5.net/job/BungeeCord/lastSuccessfulBuild/artifact/bootstrap/target/BungeeCord.jar;https://static.knarcraft.net/archive/downloads/minecraftserverjars/BungeeCord/;BungeeCord-
|
||||
Waterfall;1.17,1.16,1.15,1.14,1.13,1.12,1.11;https://papermc.io/api/v1/waterfall/;"latest":;,;https://papermc.io/api/v1/waterfall/
|
||||
Travertine;1.16,1.15,1.14,1.13,1.12;https://papermc.io/api/v1/travertine/;"latest":;,;https://papermc.io/api/v1/travertine/
|
||||
Waterfall;1.18,1.17,1.16,1.15,1.14,1.13,1.12,1.11;https://papermc.io/api/v2/projects/waterfall/versions/;"builds":[;];https://papermc.io/api/v2/projects/waterfall/versions/
|
||||
Travertine;1.16,1.15,1.14,1.13,1.12;https://papermc.io/api/v2/projects/travertine/versions/;"builds":[;];https://papermc.io/api/v2/projects/travertine/versions/
|
||||
Custom;
|
Can't render this file because it contains an unexpected character in line 1 and column 200.
|
@ -1,8 +1,9 @@
|
||||
package net.knarcraft.minecraftserverlauncher.utility;
|
||||
package net.knarcraft.minecraftserverlauncher.server;
|
||||
|
||||
import net.knarcraft.minecraftserverlauncher.Main;
|
||||
import net.knarcraft.minecraftserverlauncher.profile.ServerLauncherController;
|
||||
import net.knarcraft.minecraftserverlauncher.userinterface.FakeGUI;
|
||||
import net.knarcraft.minecraftserverlauncher.utility.CommonFunctions;
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
Loading…
Reference in New Issue
Block a user