feat: start rewrite

This commit is contained in:
TheClashFruit 2024-04-26 20:28:58 +02:00
parent 3d4d8b9982
commit 62a8d78d2c
Signed by: TheClashFruit
GPG key ID: 09BB24C34C2F3204
26 changed files with 25 additions and 916 deletions

View file

@ -14,11 +14,6 @@ repositories {
url = "https://hub.spigotmc.org/nexus/content/repositories/snapshots/"
}
maven {
name = "Vault"
url = "https://nexus.hc.to/content/repositories/pub_releases"
}
maven {
name = "Sonatype"
url = "https://oss.sonatype.org/content/repositories/snapshots/"
@ -30,12 +25,10 @@ dependencies {
testImplementation 'org.junit.jupiter:junit-jupiter'
shadow implementation("org.spigotmc:spigot-api:${project.bukkit_version}")
shadow implementation("net.milkbowl.vault:VaultAPI:1.5")
implementation 'org.eclipse.jetty:jetty-server:9.4.52.v20230823'
implementation 'org.eclipse.jetty:jetty-servlet:9.4.52.v20230823'
implementation 'org.eclipse.jetty.websocket:websocket-server:9.4.52.v20230823'
implementation 'org.eclipse.jetty.websocket:websocket-servlet:9.4.52.v20230823'
implementation 'org.eclipse.jetty:jetty-server:12.0.8'
implementation 'org.eclipse.jetty.ee10:jetty-ee10-servlet:12.0.8'
implementation 'org.eclipse.jetty.ee10.websocket:jetty-ee10-websocket-jetty-server:12.0.8'
implementation 'javax.servlet:javax.servlet-api:4.0.1'
implementation 'javax.websocket:javax.websocket-api:1.1'

View file

@ -1,2 +1,2 @@
bukkit_version = 1.8.8-R0.1-SNAPSHOT
plugin_version = 2.0.0-alpha+mc1.8.8
bukkit_version = 1.9.4-R0.1-SNAPSHOT
plugin_version = 2.0.0-alpha+mc1.9.4

View file

@ -0,0 +1,16 @@
package me.theclashfruit.crss;
import org.bukkit.plugin.java.JavaPlugin;
public class CRSSPlugin extends JavaPlugin {
@Override
public void onEnable() {
getLogger().info("Plugin enabled!");
}
@Override
public void onDisable() {
getLogger().info("Plugin disabled!");
}
}

View file

@ -1,121 +0,0 @@
package me.theclashfruit.crss;
import me.theclashfruit.crss.api.ChatServlet;
import me.theclashfruit.crss.api.GatewaySocket;
import me.theclashfruit.crss.api.PlayersServlet;
import me.theclashfruit.crss.api.StatusServlet;
import me.theclashfruit.crss.commands.BalanceCommand;
import me.theclashfruit.crss.listener.ChatListener;
import me.theclashfruit.crss.listener.PlayerJoinListener;
import me.theclashfruit.crss.listener.SleepingListener;
import me.theclashfruit.crss.map.MapServlet;
import me.theclashfruit.crss.models.SocketData;
import me.theclashfruit.crss.models.SocketMessage;
import net.milkbowl.vault.economy.Economy;
import org.bukkit.plugin.PluginManager;
import org.bukkit.plugin.RegisteredServiceProvider;
import org.bukkit.plugin.java.JavaPlugin;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.servlet.ServletHandler;
import java.io.File;
import java.util.Arrays;
public class Plugin extends JavaPlugin {
GatewaySocket chatSocket;
Server server = new Server(25580);
Connector connector = new ServerConnector(server);
ServletHandler handler = new ServletHandler();
private static Economy economy = null;
@Override
public void onEnable() {
getLogger().info("Plugin enabled!");
saveDefaultConfig();
PluginManager pluginManager = getServer().getPluginManager();
if (!setupEconomy()) {
getLogger().severe("Vault not found! Disabling plugin.");
// pluginManager.disablePlugin(this);
}
// create api server
// ContextHandler context = new ContextHandler(new ApiHandler(), "/v1");
if(getConfig().getBoolean("web.api.enabled")) {
handler.addServletWithMapping(ChatServlet.class, "/api/v1/gateway");
handler.addServletWithMapping(PlayersServlet.class, "/api/v1/players");
handler.addServletWithMapping(StatusServlet.class, "/api/v1/status");
}
if(getConfig().getBoolean("web.map.enabled")) {
handler.addServletWithMapping(MapServlet.class, "/map");
if (!new File(this.getDataFolder(), getConfig().getString("web.map.path")).exists())
new File(this.getDataFolder(), getConfig().getString("web.map.path")).mkdirs();
}
server.addConnector(connector);
server.setHandler(handler);
if (!new File(this.getDataFolder(), "/natives").exists())
new File(this.getDataFolder(), "/natives").mkdirs();
try {
if(getConfig().getBoolean("web.enabled"))
server.start();
} catch (Exception e) {
throw new RuntimeException(e);
}
// register events
pluginManager.registerEvents(new SleepingListener(), this);
pluginManager.registerEvents(new ChatListener(), this);
pluginManager.registerEvents(new PlayerJoinListener(), this);
// register commands
getCommand("balance").setExecutor(new BalanceCommand());
}
@Override
public void onDisable() {
getLogger().info("Plugin disabled!");
// stop chat socket
try {
GatewaySocket.broadcast(new SocketMessage(
"serverStop",
new SocketData(
null,
"Server stopped.",
false
)
));
server.stop();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private boolean setupEconomy() {
RegisteredServiceProvider<Economy> economyProvider = getServer().getServicesManager().getRegistration(net.milkbowl.vault.economy.Economy.class);
if (economyProvider != null)
economy = economyProvider.getProvider();
return (economy != null);
}
public static Economy getEconomy() {
return economy;
}
}

View file

@ -1,15 +0,0 @@
package me.theclashfruit.crss.api;
import org.eclipse.jetty.websocket.servlet.WebSocketServlet;
import org.eclipse.jetty.websocket.servlet.WebSocketServletFactory;
import javax.servlet.annotation.WebServlet;
@WebServlet(name = "Chat WebSocket API")
public class ChatServlet extends WebSocketServlet {
@Override
public void configure(WebSocketServletFactory factory) {
factory.register(GatewaySocket.class);
}
}

View file

@ -1,74 +0,0 @@
package me.theclashfruit.crss.api;
import com.google.gson.Gson;
import me.theclashfruit.crss.models.GatewayConnection;
import me.theclashfruit.crss.models.SocketData;
import me.theclashfruit.crss.models.SocketMessage;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.annotations.*;
import javax.websocket.EncodeException;
import java.io.IOException;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
import static org.bukkit.Bukkit.getLogger;
@WebSocket
public class GatewaySocket {
private static final Set<GatewaySocket> gatewayConnections = new CopyOnWriteArraySet<>();
private Session session;
@OnWebSocketConnect
public void onConnect(Session session) throws IOException {
this.session = session;
gatewayConnections.add(this);
}
@OnWebSocketMessage
public void onMessage(String message) throws IOException, EncodeException {
getLogger().info(message);
try {
Gson gson = new Gson();
GatewayConnection socketMessage = gson.fromJson(message, GatewayConnection.class);
getLogger().info(socketMessage.getClientName());
for (String subscription : socketMessage.getSubscriptions()) {
getLogger().info(subscription);
}
} catch (Exception e) {
getLogger().throwing(GatewaySocket.class.getName(), "WebSocket", e);
}
}
@OnWebSocketClose
public void onClose(int statusCode, String reason) throws IOException {
gatewayConnections.remove(this);
}
@OnWebSocketError
public void onError(Throwable throwable) {
getLogger().throwing(GatewaySocket.class.getName(), "WebSocket", throwable);
}
public static void broadcast(SocketMessage message) {
gatewayConnections.forEach(endpoint -> {
try {
Gson gson = new Gson();
endpoint
.session
.getRemote()
.sendString(
gson.toJson(message)
);
} catch (IOException e) {
getLogger().throwing(GatewaySocket.class.getName(), "WebSocket", e);
}
});
}
}

View file

@ -1,46 +0,0 @@
package me.theclashfruit.crss.api;
import com.google.gson.Gson;
import me.theclashfruit.crss.models.PlayerList;
import me.theclashfruit.crss.models.PlayerLocation;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet(name = "Players API")
public class PlayersServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("application/json");
Gson gson = new Gson();
var onlinePlayers =Bukkit.getOnlinePlayers().toArray();
PlayerList[] playerList = new PlayerList[onlinePlayers.length];
for (int i = 0; i < onlinePlayers.length; i++) {
Player player = (Player) onlinePlayers[i];
playerList[i] = new PlayerList(
player.getUniqueId().toString(),
player.getDisplayName(),
player.getGameMode().getValue(),
player.getWorld().getName(),
new PlayerLocation(
player.getLocation().getX(),
player.getLocation().getY(),
player.getLocation().getZ()
)
);
}
response.setStatus(HttpServletResponse.SC_OK);
response.getWriter().println(gson.toJson(playerList));
}
}

View file

@ -1,32 +0,0 @@
package me.theclashfruit.crss.api;
import com.google.gson.Gson;
import me.theclashfruit.crss.models.Status;
import org.bukkit.Bukkit;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet(name = "Status API")
public class StatusServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("application/json");
Gson gson = new Gson();
Status status = new Status(
true,
Bukkit.getBukkitVersion(),
Bukkit.getOnlinePlayers().toArray().length,
Bukkit.getMaxPlayers(),
Bukkit.getMotd()
);
response.setStatus(HttpServletResponse.SC_OK);
response.getWriter().println(gson.toJson(status));
}
}

View file

@ -1,16 +0,0 @@
package me.theclashfruit.crss.commands;
import me.theclashfruit.crss.Plugin;
import org.bukkit.ChatColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
public class BalanceCommand implements CommandExecutor {
@Override
public boolean onCommand(CommandSender commandSender, Command command, String s, String[] strings) {
commandSender.sendMessage("Your balance is: " + Plugin.getEconomy().getBalance(commandSender.getName()));
return true;
}
}

View file

@ -1,82 +0,0 @@
package me.theclashfruit.crss.listener;
import me.theclashfruit.crss.api.GatewaySocket;
import me.theclashfruit.crss.models.*;
import me.theclashfruit.crss.util.StringUtil;
import org.bukkit.ChatColor;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.PlayerDeathEvent;
import org.bukkit.event.player.PlayerChatEvent;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.event.server.ServerCommandEvent;
public class ChatListener implements Listener {
@EventHandler
public void onChat(PlayerChatEvent event) {
GatewaySocket.broadcast(new SocketMessage(
"chatMessage",
new SocketData(
event.getPlayer().getName(),
event.getMessage(),
false
)
));
}
@EventHandler
public void onJoin(PlayerJoinEvent event) {
GatewaySocket.broadcast(new SocketMessage(
"playerJoin",
new SocketData(
null,
event.getPlayer().getName() + " joined the game.",
false
)
));
}
@EventHandler
public void onQuit(PlayerQuitEvent event) {
GatewaySocket.broadcast(new SocketMessage(
"playerQuit",
new SocketData(
null,
event.getPlayer().getName() + " left the game.",
false
)
));
}
@EventHandler
public void onDeath(PlayerDeathEvent event) {
GatewaySocket.broadcast(new SocketMessage(
"playerDeath",
new SocketData(
null,
event.getDeathMessage(),
false
)
));
}
@EventHandler
public void onServerCommand(ServerCommandEvent event) {
switch (StringUtil.getFirstPartBeforeSpace(event.getCommand())) {
case "say":
GatewaySocket.broadcast(new SocketMessage(
"serverSay",
new SocketData(
null,
ChatColor.stripColor(event.getCommand().substring(4)),
false
)
));
break;
default:
break;
}
}
}

View file

@ -1,20 +0,0 @@
package me.theclashfruit.crss.listener;
import me.theclashfruit.crss.Plugin;
import net.milkbowl.vault.economy.Economy;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
public class PlayerJoinListener implements Listener {
private Economy economy = Plugin.getEconomy();
@EventHandler
public void onPlayerJoin(PlayerJoinEvent event) {
Player player = event.getPlayer();
if (!economy.hasAccount(player))
economy.createPlayerAccount(player);
}
}

View file

@ -1,46 +0,0 @@
package me.theclashfruit.crss.listener;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.event.player.PlayerMoveEvent;
import org.bukkit.plugin.Plugin;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerBedEnterEvent;
import org.bukkit.plugin.PluginManager;
import java.util.concurrent.atomic.AtomicInteger;
import static org.bukkit.Bukkit.getServer;
public class SleepingListener implements Listener {
Plugin plugin = getServer().getPluginManager().getPlugin("CRSS");
FileConfiguration config = plugin.getConfig();
@EventHandler
public void playerBedEnterEvent(PlayerBedEnterEvent event) {
World world = event.getBed().getWorld();
AtomicInteger sleeping = new AtomicInteger();
int players = world.getPlayers().size();
int sleepingPercentage = config.getInt("gameRules.playerSleepingPercentage");
world.getPlayers().forEach(player -> {
if(player.isSleeping())
sleeping.incrementAndGet();
});
if(sleeping.get() >= players * sleepingPercentage / 100) {
long rTime = 24000 - world.getTime();
world.setFullTime(world.getFullTime() + rTime);
if(world.isThundering() || world.hasStorm()) {
world.setThundering(false);
world.setStorm(false);
}
}
}
}

View file

@ -1,23 +0,0 @@
package me.theclashfruit.crss.map;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet(name = "Map Tile Servlet")
public class MapServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
response.setContentType("text/plain");
/*
MapUtils mapUtils = new MapUtils();
mapUtils.generateTiles();
*/
response.setStatus(HttpServletResponse.SC_OK);
response.getWriter().println("Hello, World!");
}
}

View file

@ -1,90 +0,0 @@
package me.theclashfruit.crss.map;
import me.theclashfruit.crss.util.FileUtil;
import org.bukkit.plugin.Plugin;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import static org.bukkit.Bukkit.getLogger;
import static org.bukkit.Bukkit.getServer;
public class MapUtils {
Plugin plugin = getServer().getPluginManager().getPlugin("CRSS");
public void generateTiles() {
plugin.getConfig().getStringList("web.map.worlds").forEach(world -> {
try {
String unminedPath =
String.format(
"%s/natives/unmined/unmined-cli",
plugin.getDataFolder()
);
String worldFolder =
getServer().getWorld(world).getWorldFolder().getAbsolutePath().replace("./", "");
String outputPath =
String.format(
"%s/tmp/%s",
plugin.getDataFolder(),
world
);
String finalOutputPath =
outputPath.replace(
"tmp",
plugin.getConfig().getString("web.map.path")
);
String mapSettingPath =
String.format(
"%s/unmined_settings.json",
plugin.getDataFolder()
);
if(!new File(unminedPath).exists())
throw new RuntimeException("Unmined CLI not found!");
Process process = Runtime
.getRuntime()
.exec(
String.format(
"%s web render --imageformat png --world %s --output %s --mapsettings %s --zoomout 4",
unminedPath,
worldFolder,
outputPath,
mapSettingPath
)
);
BufferedReader stdInput = new BufferedReader(new InputStreamReader(process.getInputStream()));
BufferedReader stdError = new BufferedReader(new InputStreamReader(process.getErrorStream()));
String lines;
while ((lines = stdInput.readLine()) != null) {
getLogger().info(lines);
}
while ((lines = stdError.readLine()) != null) {
getLogger().severe(lines);
}
if(new File(finalOutputPath).exists())
FileUtil.deleteDirectory(new File(finalOutputPath));
Files.move(Paths.get(new File(outputPath, "tiles").getAbsolutePath()), Paths.get(new File(finalOutputPath).getAbsolutePath()), StandardCopyOption.REPLACE_EXISTING);
FileUtil.deleteDirectory(new File(outputPath));
} catch (IOException e) {
getLogger().severe("Error while generating map tiles!");
getLogger().severe(e.toString());
}
});
}
}

View file

@ -1,27 +0,0 @@
package me.theclashfruit.crss.models;
public class GatewayConnection {
private String clientName;
private String[] subscriptions;
public GatewayConnection(String clientName, String[] subscriptions) {
this.clientName = clientName;
this.subscriptions = subscriptions;
}
public String getClientName() {
return clientName;
}
public String[] getSubscriptions() {
return subscriptions;
}
public void setClientName(String clientName) {
this.clientName = clientName;
}
public void setSubscriptions(String[] subscriptions) {
this.subscriptions = subscriptions;
}
}

View file

@ -1,59 +0,0 @@
package me.theclashfruit.crss.models;
import org.bukkit.World;
public class PlayerList {
private String uniqueId;
private String displayName;
private int gameMode;
private String world;
private PlayerLocation location;
public PlayerList(String uniqueId, String displayName, int gameMode, String world, PlayerLocation location) {
this.uniqueId = uniqueId;
this.displayName = displayName;
this.gameMode = gameMode;
this.world = world;
this.location = location;
}
public String getUniqueId() {
return uniqueId;
}
public String getDisplayName() {
return displayName;
}
public int getGameMode() {
return gameMode;
}
public String getWorld() {
return world;
}
public PlayerLocation getLocation() {
return location;
}
public void setUniqueId(String uniqueId) {
this.uniqueId = uniqueId;
}
public void setDisplayName(String displayName) {
this.displayName = displayName;
}
public void setGameMode(int gameMode) {
this.gameMode = gameMode;
}
public void setWorld(String world) {
this.world = world;
}
public void setLocation(PlayerLocation location) {
this.location = location;
}
}

View file

@ -1,37 +0,0 @@
package me.theclashfruit.crss.models;
public class PlayerLocation {
private double x;
private double y;
private double z;
public PlayerLocation(double x, double y, double z) {
this.x = x;
this.y = y;
this.z = z;
}
public double getX() {
return x;
}
public double getY() {
return y;
}
public double getZ() {
return z;
}
public void setX(double x) {
this.x = x;
}
public void setY(double y) {
this.y = y;
}
public void setZ(double z) {
this.z = z;
}
}

View file

@ -1,37 +0,0 @@
package me.theclashfruit.crss.models;
public class SocketData {
private String username;
private String message;
private Boolean isSystemMessage;
public SocketData(String username, String message, Boolean isSystemMessage) {
this.username = username;
this.message = message;
this.isSystemMessage = isSystemMessage;
}
public String getUsername() {
return username;
}
public String getMessage() {
return message;
}
public Boolean getIsSystemMessage() {
return isSystemMessage;
}
public void setUsername(String username) {
this.username = username;
}
public void setMessage(String message) {
this.message = message;
}
public void setIsSystemMessage(Boolean isSystemMessage) {
this.isSystemMessage = isSystemMessage;
}
}

View file

@ -1,27 +0,0 @@
package me.theclashfruit.crss.models;
public class SocketMessage {
private String event;
private SocketData data;
public SocketMessage(String event, SocketData data) {
this.event = event;
this.data = data;
}
public String getEvent() {
return event;
}
public SocketData getData() {
return data;
}
public void setEvent(String event) {
this.event = event;
}
public void setData(SocketData data) {
this.data = data;
}
}

View file

@ -1,57 +0,0 @@
package me.theclashfruit.crss.models;
public class Status {
private Boolean status;
private String version;
private int players;
private int maxPlayers;
private String motd;
public Status(Boolean status, String version, int players, int maxPlayers, String motd) {
this.status = status;
this.version = version;
this.players = players;
this.maxPlayers = maxPlayers;
this.motd = motd;
}
public Boolean getStatus() {
return status;
}
public String getVersion() {
return version;
}
public int getPlayers() {
return players;
}
public int getMaxPlayers() {
return maxPlayers;
}
public String getMotd() {
return motd;
}
public void setStatus(Boolean status) {
this.status = status;
}
public void setVersion(String version) {
this.version = version;
}
public void setPlayers(int players) {
this.players = players;
}
public void setMaxPlayers(int maxPlayers) {
this.maxPlayers = maxPlayers;
}
public void setMotd(String motd) {
this.motd = motd;
}
}

View file

@ -1,15 +0,0 @@
package me.theclashfruit.crss.util;
import java.io.File;
public class FileUtil {
public static boolean deleteDirectory(File directoryToBeDeleted) {
File[] allContents = directoryToBeDeleted.listFiles();
if (allContents != null) {
for (File file : allContents) {
deleteDirectory(file);
}
}
return directoryToBeDeleted.delete();
}
}

View file

@ -1,33 +0,0 @@
package me.theclashfruit.crss.util;
import com.google.gson.Gson;
import me.theclashfruit.crss.models.SocketMessage;
import javax.websocket.DecodeException;
import javax.websocket.Decoder;
import javax.websocket.EndpointConfig;
public class MessageDecoder implements Decoder.Text<SocketMessage> {
private static final Gson gson = new Gson();
@Override
public SocketMessage decode(String s) throws DecodeException {
return gson.fromJson(s, SocketMessage.class);
}
@Override
public boolean willDecode(String s) {
return (s != null);
}
@Override
public void init(EndpointConfig endpointConfig) {
// Custom initialization logic
}
@Override
public void destroy() {
// Close resources
}
}

View file

@ -1,28 +0,0 @@
package me.theclashfruit.crss.util;
import com.google.gson.Gson;
import me.theclashfruit.crss.models.SocketMessage;
import javax.websocket.EncodeException;
import javax.websocket.Encoder;
import javax.websocket.EndpointConfig;
public class MessageEncoder implements Encoder.Text<SocketMessage> {
private static final Gson gson = new Gson();
@Override
public String encode(SocketMessage message) throws EncodeException {
return gson.toJson(message);
}
@Override
public void init(EndpointConfig endpointConfig) {
// Custom initialization logic
}
@Override
public void destroy() {
// Close resources
}
}

View file

@ -1,8 +0,0 @@
package me.theclashfruit.crss.util;
public interface StringUtil {
static String getFirstPartBeforeSpace(String input) {
int index = input.contains(" ") ? input.indexOf(" ") : 0;
return input.substring(0, index);
}
}

View file

@ -13,7 +13,7 @@ import java.nio.file.Paths;
* <p>
* This class is used to run the server in development mode.
* </p>
* <p>Copyright 2023-2024 TheClashFruit</p>
* <p>Copyright (c) 2023-2024 TheClashFruit</p>
*/
public class DevRunner {
public static void main(String[] args) throws IOException {
@ -25,7 +25,7 @@ public class DevRunner {
ProcessBuilder pb = new ProcessBuilder();
pb.command("cmd", "/c", "start", "java", "-Xms128M", "-XX:MaxRAMPercentage=95.0", "-jar", "server.jar");
pb.command("cmd", "/c", "start", "java", "-Xms128M", "-XX:MaxRAMPercentage=95.0", "-jar", "server.jar", "nogui");
pb.directory(runDir);
pb.start();

View file

@ -1,15 +1,8 @@
name: CRSS
main: me.theclashfruit.crss.Plugin
main: me.theclashfruit.crss.CRSSPlugin
version: ${version}
database: true
author: TheClashFruit
commands:
balance:
description: Check your balance
usage: /balance
load: POSTWORLD
depend:
- Vault
load: POSTWORLD