diff --git a/pom.xml b/pom.xml
index 0e7aa61..e5d2a07 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
de.luuuuuis
PrivateServer
- 0.9
+ 0.10
@@ -88,7 +88,7 @@
provided
-
+
org.spigotmc
spigot
@@ -96,6 +96,15 @@
provided
+
+
+ org.projectlombok
+ lombok
+ 1.18.12
+ provided
+
+
+
net.jitse
diff --git a/src/main/java/de/luuuuuis/privateserver/bungee/PrivateServer.java b/src/main/java/de/luuuuuis/privateserver/bungee/PrivateServer.java
index 8d0087f..ce13985 100644
--- a/src/main/java/de/luuuuuis/privateserver/bungee/PrivateServer.java
+++ b/src/main/java/de/luuuuuis/privateserver/bungee/PrivateServer.java
@@ -4,23 +4,23 @@
import com.google.gson.GsonBuilder;
import de.luuuuuis.privateserver.bungee.commands.PrivateServerCmd;
import de.luuuuuis.privateserver.bungee.events.DisconnectListener;
+import de.luuuuuis.privateserver.bungee.events.PluginMessageReceive;
import de.luuuuuis.privateserver.bungee.events.ServerSwitch;
import de.luuuuuis.privateserver.bungee.events.TabComplete;
import de.luuuuuis.privateserver.bungee.util.CloudServer;
import de.luuuuuis.privateserver.bungee.util.Config;
import de.luuuuuis.privateserver.bungee.util.Metrics;
import de.luuuuuis.privateserver.bungee.util.Updater;
+import lombok.Getter;
import net.md_5.bungee.api.plugin.Plugin;
import net.md_5.bungee.api.plugin.PluginManager;
public class PrivateServer extends Plugin {
public static final Gson GSON = new GsonBuilder().setPrettyPrinting().create();
+ @Getter
private static PrivateServer instance;
- public static PrivateServer getInstance() {
- return instance;
- }
@Override
public void onDisable() {
@@ -54,6 +54,7 @@ public void onEnable() {
//updater
new Updater();
+
//commands
PluginManager pluginManager = getProxy().getPluginManager();
pluginManager.registerCommand(this, new PrivateServerCmd());
@@ -61,8 +62,14 @@ public void onEnable() {
pluginManager.registerListener(this, new ServerSwitch());
pluginManager.registerListener(this, new DisconnectListener());
+ // receive plugin messages and execute spigot commands on BungeeCord
+ getProxy().registerChannel("pv:cmd");
+ pluginManager.registerListener(this, new PluginMessageReceive());
+
+
/*
bStats Metrics https://github.com/Bastian/bStats-Metrics/blob/master/bstats-bungeecord/src/examples/java/ExamplePlugin.java
+ Available here: https://bstats.org/plugin/bungeecord/PrivateServer/8521
to disable these metrics change the bStats config and copy it into you template folder but please don't :C
*/
Metrics metrics = new Metrics(this, 8521);
diff --git a/src/main/java/de/luuuuuis/privateserver/bungee/commands/PrivateServerCmd.java b/src/main/java/de/luuuuuis/privateserver/bungee/commands/PrivateServerCmd.java
index 6b2c265..499d1fc 100644
--- a/src/main/java/de/luuuuuis/privateserver/bungee/commands/PrivateServerCmd.java
+++ b/src/main/java/de/luuuuuis/privateserver/bungee/commands/PrivateServerCmd.java
@@ -163,7 +163,7 @@ public void execute(CommandSender sender, String[] strings) {
Invitee invitee = Invitee.getInvitee(p, CloudServer.getCloudServer(strings[1]));
if (invitee == null) {
- CloudServer cs = CloudServer.getCloudServers().stream().filter(cloudServer1 -> cloudServer1.getOwner().getUniqueId().equals(p.getUniqueId())).findFirst().orElse(null);
+ CloudServer cs = CloudServer.getCloudServers().stream().filter(cloudServer1 -> cloudServer1.getOwner().getPlayer().getUniqueId().equals(p.getUniqueId())).findFirst().orElse(null);
if (cs != null) {
playerExecutorBridge.sendPlayer(cloudPlayer, cs.getName());
return;
diff --git a/src/main/java/de/luuuuuis/privateserver/bungee/events/PluginMessageReceive.java b/src/main/java/de/luuuuuis/privateserver/bungee/events/PluginMessageReceive.java
new file mode 100644
index 0000000..a7cd28c
--- /dev/null
+++ b/src/main/java/de/luuuuuis/privateserver/bungee/events/PluginMessageReceive.java
@@ -0,0 +1,31 @@
+package de.luuuuuis.privateserver.bungee.events;
+
+import com.google.common.io.ByteArrayDataInput;
+import com.google.common.io.ByteStreams;
+import net.md_5.bungee.api.ProxyServer;
+import net.md_5.bungee.api.connection.ProxiedPlayer;
+import net.md_5.bungee.api.event.PluginMessageEvent;
+import net.md_5.bungee.api.plugin.Listener;
+import net.md_5.bungee.event.EventHandler;
+
+public class PluginMessageReceive implements Listener {
+
+ /**
+ * access and execute every privateserver command on bungee. No need to check anything on spigot cause bungee does :3
+ *
+ * @param e event
+ */
+ @EventHandler
+ public void onReceive(PluginMessageEvent e) {
+ if (!e.getTag().equals("pv:cmd")) return;
+
+ @SuppressWarnings("UnstableApiUsage") ByteArrayDataInput in = ByteStreams.newDataInput(e.getData());
+ String utf_in = in.readUTF();
+ if (!(e.getReceiver() instanceof ProxiedPlayer)) return; // ah shit, i guess,,,
+
+ ProxiedPlayer player = (ProxiedPlayer) e.getReceiver();
+
+ ProxyServer.getInstance().getPluginManager().dispatchCommand(player, "privateserver " + utf_in);
+ }
+
+}
diff --git a/src/main/java/de/luuuuuis/privateserver/bungee/util/CloudServer.java b/src/main/java/de/luuuuuis/privateserver/bungee/util/CloudServer.java
index 1c95d7d..f1055a1 100644
--- a/src/main/java/de/luuuuuis/privateserver/bungee/util/CloudServer.java
+++ b/src/main/java/de/luuuuuis/privateserver/bungee/util/CloudServer.java
@@ -6,6 +6,8 @@
import de.dytanic.cloudnet.lib.server.template.Template;
import de.dytanic.cloudnet.lib.server.template.TemplateResource;
import de.dytanic.cloudnet.lib.utility.document.Document;
+import lombok.Getter;
+import lombok.Setter;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.chat.TextComponent;
import net.md_5.bungee.api.connection.ProxiedPlayer;
@@ -13,12 +15,14 @@
import java.util.*;
import java.util.stream.Collectors;
+@Getter
public class CloudServer {
private final static List cloudServers = new ArrayList<>();
private final String group;
private final Owner owner;
private final ServerGroupMode groupMode;
+ @Setter
private String template = Config.getInstance().getTemplate();
private String name;
@@ -44,7 +48,7 @@ public void start() {
CloudAPI.getInstance().startGameServer(CloudAPI.getInstance().getServerGroupData(group),
- new ServerConfig(true, "null", new Document("uniqueId", owner.getUniqueId()), System.currentTimeMillis()),
+ new ServerConfig(true, "null", new Document("uniqueId", owner.getPlayer().getUniqueId()), System.currentTimeMillis()),
Config.getInstance().getMemory(),
new String[0],
new Template(template, TemplateResource.LOCAL, null, new String[0], Collections.emptyList()),
@@ -110,6 +114,12 @@ private boolean isAllowed() {
return false;
}
+ // check if user has permission to start this group
+ if (!owner.getPlayer().hasPermission("privateserver.start." + group)) {
+ owner.sendMessage(Config.getInstance().getPrefix() + "You are not allowed to start this group.");
+ return false;
+ }
+
return true;
}
@@ -124,9 +134,6 @@ private String createName() {
return name;
}
- public void setTemplate(String template) {
- this.template = template;
- }
public List getPlayers() {
return CloudAPI.getInstance().getServerInfo(name).getPlayers();
@@ -136,9 +143,6 @@ public int getMaxPlayers() {
return CloudAPI.getInstance().getServerInfo(name).getMaxPlayers();
}
- public String getName() {
- return name;
- }
public void setName(int ID) {
if (cloudServers.stream().noneMatch(server -> server.getName().equals(server.getOwner().getPlayer().getName() + "-" + ID))) {
@@ -146,17 +150,5 @@ public void setName(int ID) {
}
}
- public String getGroup() {
- return group;
- }
-
- public ServerGroupMode getGroupMode() {
- return groupMode;
- }
-
- public Owner getOwner() {
- return owner;
- }
-
}
diff --git a/src/main/java/de/luuuuuis/privateserver/bungee/util/Config.java b/src/main/java/de/luuuuuis/privateserver/bungee/util/Config.java
index dcdf7d8..4b7f91e 100644
--- a/src/main/java/de/luuuuuis/privateserver/bungee/util/Config.java
+++ b/src/main/java/de/luuuuuis/privateserver/bungee/util/Config.java
@@ -1,6 +1,7 @@
package de.luuuuuis.privateserver.bungee.util;
import de.luuuuuis.privateserver.bungee.PrivateServer;
+import lombok.Getter;
import java.io.File;
import java.io.FileReader;
@@ -12,6 +13,7 @@
import java.util.HashMap;
import java.util.Objects;
+@Getter
public class Config {
private static Config instance;
@@ -65,32 +67,4 @@ private static void read(String path) {
e.printStackTrace();
}
}
-
- public String getPrefix() {
- return prefix;
- }
-
- public String getTemplate() {
- return template;
- }
-
- public HashMap getMessages() {
- return messages;
- }
-
- public ArrayList getGroups() {
- return groups;
- }
-
- public int getMaxServersRunning() {
- return maxServersRunning;
- }
-
- public int getMaxServersPerUser() {
- return maxServersPerUser;
- }
-
- public int getMemory() {
- return memory;
- }
}
\ No newline at end of file
diff --git a/src/main/java/de/luuuuuis/privateserver/bungee/util/Invitee.java b/src/main/java/de/luuuuuis/privateserver/bungee/util/Invitee.java
index 39b64e2..1e7e521 100644
--- a/src/main/java/de/luuuuuis/privateserver/bungee/util/Invitee.java
+++ b/src/main/java/de/luuuuuis/privateserver/bungee/util/Invitee.java
@@ -1,5 +1,6 @@
package de.luuuuuis.privateserver.bungee.util;
+import lombok.Getter;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.chat.ClickEvent;
import net.md_5.bungee.api.chat.ComponentBuilder;
@@ -12,6 +13,7 @@
import java.util.ArrayList;
import java.util.List;
+@Getter
public class Invitee {
private final static List invitees = new ArrayList<>();
@@ -74,16 +76,4 @@ public void revoke() {
public void sendMessage(String message) {
player.sendMessage(TextComponent.fromLegacyText(message));
}
-
- public Owner getOwner() {
- return owner;
- }
-
- public ProxiedPlayer getPlayer() {
- return player;
- }
-
- public CloudServer getCloudServer() {
- return cloudServer;
- }
}
diff --git a/src/main/java/de/luuuuuis/privateserver/bungee/util/Owner.java b/src/main/java/de/luuuuuis/privateserver/bungee/util/Owner.java
index c7cfb03..1b802af 100644
--- a/src/main/java/de/luuuuuis/privateserver/bungee/util/Owner.java
+++ b/src/main/java/de/luuuuuis/privateserver/bungee/util/Owner.java
@@ -3,6 +3,7 @@
import de.dytanic.cloudnet.api.CloudAPI;
import de.dytanic.cloudnet.api.player.PlayerExecutorBridge;
import de.dytanic.cloudnet.lib.player.CloudPlayer;
+import lombok.Getter;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.chat.TextComponent;
import net.md_5.bungee.api.config.ServerInfo;
@@ -10,8 +11,8 @@
import java.util.ArrayList;
import java.util.List;
-import java.util.UUID;
+@Getter
public class Owner {
private final static List owners = new ArrayList<>();
@@ -45,21 +46,25 @@ public static Owner getOwner(ProxiedPlayer player) {
* @param cloudServer the CloudServer you want to send the player
*/
public void sendTitle(CloudServer cloudServer) {
- Thread th = new Thread(() -> {
+ new Thread(() -> {
//send title & to server
int i = 0;
- while (CloudAPI.getInstance().getServerInfo(cloudServer.getName()) == null || !CloudAPI.getInstance().getServerInfo(cloudServer.getName()).isOnline()) {
+ while (CloudAPI.getInstance().getServerInfo(cloudServer.getName()) == null ||
+ !CloudAPI.getInstance().getServerInfo(cloudServer.getName()).isOnline()) {
i++;
StringBuilder dots = new StringBuilder();
for (int j = 0; j < i; j++) {
dots.append(".");
}
- playerExecutorBridge.sendTitle(cloudPlayer, "", String.format(Config.getInstance().getMessages().get("startingTitle").toString(), dots), 0, 20, 0);
+ playerExecutorBridge.sendTitle(cloudPlayer, "",
+ String.format(Config.getInstance().getMessages().get("startingTitle").toString(), dots),
+ 0, 20, 0);
if (i >= 3) i = 0;
try {
+ //noinspection BusyWait
Thread.sleep(750);
} catch (InterruptedException e) {
e.printStackTrace();
@@ -67,8 +72,7 @@ public void sendTitle(CloudServer cloudServer) {
}
sendPlayer(cloudServer);
- });
- th.start();
+ }).start();
}
private void sendPlayer(CloudServer cloudServer) {
@@ -93,16 +97,38 @@ public void removeServer(CloudServer cloudServer) {
if (servers.isEmpty())
owners.remove(this);
}
+}
- public UUID getUniqueId() {
- return player.getUniqueId();
- }
-
- public ProxiedPlayer getPlayer() {
- return player;
- }
- public List getServers() {
- return servers;
- }
-}
+//@Data class Task implements Callable {
+//
+// private final PlayerExecutorBridge playerExecutorBridge;
+// private final CloudPlayer cloudPlayer;
+// private final CloudServer cloudServer;
+//
+// @Override
+// public Boolean call() throws InterruptedException {
+//
+// //send title
+// int i = 0;
+// do {
+// i++;
+// StringBuilder dots = new StringBuilder();
+// for (int j = 0; j < i; j++) {
+// dots.append(".");
+// }
+//
+// playerExecutorBridge.sendTitle(cloudPlayer, "", String.format(Config.getInstance().getMessages().get("startingTitle").toString(), dots), 0, 20, 0);
+//
+// if (i >= 3) i = 0;
+//
+//
+// Thread.sleep(750);
+// } while ((CloudAPI.getInstance().getServerInfo(cloudServer.getName()) == null
+// || !CloudAPI.getInstance().getServerInfo(cloudServer.getName()).isOnline())
+// && !Thread.interrupted());
+//
+// return true;
+// }
+//
+//}
\ No newline at end of file
diff --git a/src/main/java/de/luuuuuis/privateserver/spigot/PrivateServer.java b/src/main/java/de/luuuuuis/privateserver/spigot/PrivateServer.java
index 2602e6d..12f2dc9 100644
--- a/src/main/java/de/luuuuuis/privateserver/spigot/PrivateServer.java
+++ b/src/main/java/de/luuuuuis/privateserver/spigot/PrivateServer.java
@@ -2,10 +2,12 @@
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
+import de.dytanic.cloudnet.bridge.CloudServer;
+import de.luuuuuis.privateserver.spigot.commands.PrivateServerCmd;
import de.luuuuuis.privateserver.spigot.events.JoinListener;
-import de.luuuuuis.privateserver.spigot.events.NPCListener;
import de.luuuuuis.privateserver.spigot.util.Config;
import de.luuuuuis.privateserver.spigot.util.Owner;
+import lombok.Getter;
import net.jitse.npclib.NPCLib;
import org.bukkit.plugin.PluginManager;
import org.bukkit.plugin.java.JavaPlugin;
@@ -13,13 +15,14 @@
public class PrivateServer extends JavaPlugin {
public static final Gson GSON = new GsonBuilder().setPrettyPrinting().create();
+
+ @Getter
private static PrivateServer instance;
+ @Getter
private Owner owner;
+ @Getter
private NPCLib npcLib;
- public static PrivateServer getInstance() {
- return instance;
- }
@Override
public void onEnable() {
@@ -33,16 +36,18 @@ public void onEnable() {
// init Owner
owner = new Owner();
+
PluginManager pluginManager = getServer().getPluginManager();
pluginManager.registerEvents(new JoinListener(), this);
- pluginManager.registerEvents(new NPCListener(this), this);
- }
- public Owner getOwner() {
- return owner;
- }
+ getServer().getMessenger().registerOutgoingPluginChannel(this, "pv:cmd");
+ getCommand("privateserver").setExecutor(new PrivateServerCmd());
+
+ // Listener for NPCs
+ //pluginManager.registerEvents(new NPCListener(this), this);
- public NPCLib getNpcLib() {
- return npcLib;
+ // prevents the server from starting new servers when changing state to ingame-mode
+ CloudServer.getInstance().setAllowAutoStart(false);
}
-}
+
+}
\ No newline at end of file
diff --git a/src/main/java/de/luuuuuis/privateserver/spigot/commands/PrivateServerCmd.java b/src/main/java/de/luuuuuis/privateserver/spigot/commands/PrivateServerCmd.java
new file mode 100644
index 0000000..c1dbce1
--- /dev/null
+++ b/src/main/java/de/luuuuuis/privateserver/spigot/commands/PrivateServerCmd.java
@@ -0,0 +1,38 @@
+package de.luuuuuis.privateserver.spigot.commands;
+
+import com.google.common.io.ByteArrayDataOutput;
+import com.google.common.io.ByteStreams;
+import de.luuuuuis.privateserver.spigot.PrivateServer;
+import org.bukkit.command.Command;
+import org.bukkit.command.CommandExecutor;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+
+public class PrivateServerCmd implements CommandExecutor {
+
+ /**
+ * Send a message via "BungeeCord Plugin Messaging Channel" to the BungeeCord server to execute a privateserver
+ * command. This could be useful if you want to have an armorstand in your lobby to click and execute a command
+ * on the BungeeCord server
+ *
+ * @param sender sender (Player !Server is not able to send plugin messages!)
+ * @param command command
+ * @param s label
+ * @param strings args
+ * @return boolean
+ */
+ @Override
+ public boolean onCommand(CommandSender sender, Command command, String s, String[] strings) {
+ if (!(sender instanceof Player)) return false;
+ if (strings.length < 1) return false;
+
+ Player p = (Player) sender;
+
+ @SuppressWarnings("UnstableApiUsage") ByteArrayDataOutput output = ByteStreams.newDataOutput();
+ output.writeUTF(String.join(" ", strings));
+
+ p.sendPluginMessage(PrivateServer.getInstance(), "pv:cmd", output.toByteArray());
+
+ return false;
+ }
+}
diff --git a/src/main/java/de/luuuuuis/privateserver/spigot/events/NPCListener.java b/src/main/java/de/luuuuuis/privateserver/spigot/events/NPCListener.java
index 2d61f97..91516c2 100644
--- a/src/main/java/de/luuuuuis/privateserver/spigot/events/NPCListener.java
+++ b/src/main/java/de/luuuuuis/privateserver/spigot/events/NPCListener.java
@@ -24,10 +24,11 @@
import java.util.Map;
import java.util.Objects;
+@Deprecated
public class NPCListener implements Listener {
private final PrivateServer privateServer;
- private final Map npcs = new HashMap<>();
+ private final Map NPCs = new HashMap<>();
public NPCListener(PrivateServer privateServer) {
this.privateServer = privateServer;
@@ -47,7 +48,7 @@ public void onJoin(PlayerJoinEvent e) {
npc.create();
npc.show(p);
- npcs.put(p, npc);
+ NPCs.put(p, npc);
// Sets head rotation for the npc if the player is in a range of 15 blocks
// Author: @yanjulang
@@ -109,19 +110,20 @@ public byte toAngle(float value) {
public void onQuit(PlayerQuitEvent e) {
Player p = e.getPlayer();
- NPC npc = npcs.get(p);
+ NPC npc = NPCs.get(p);
npc.destroy();
- npcs.remove(p);
+ NPCs.remove(p);
}
@EventHandler
public void onInteract(NPCInteractEvent e) {
- NPC npc = npcs.get(e.getWhoClicked());
+ NPC npc = NPCs.get(e.getWhoClicked());
if (e.getNPC().equals(npc)) {
-
+ // do things with NPC. (e.g. open inv)
}
}
+
}
diff --git a/src/main/java/de/luuuuuis/privateserver/spigot/util/Config.java b/src/main/java/de/luuuuuis/privateserver/spigot/util/Config.java
index d9a0a8e..430abd5 100644
--- a/src/main/java/de/luuuuuis/privateserver/spigot/util/Config.java
+++ b/src/main/java/de/luuuuuis/privateserver/spigot/util/Config.java
@@ -1,6 +1,7 @@
package de.luuuuuis.privateserver.spigot.util;
import de.luuuuuis.privateserver.spigot.PrivateServer;
+import lombok.Getter;
import java.io.File;
import java.io.FileReader;
@@ -13,17 +14,15 @@
public class Config {
+ @Getter
private static Config instance;
+ @Getter
private final ArrayList permissions;
public Config(ArrayList permissions) {
this.permissions = permissions;
}
- public static Config getInstance() {
- return instance;
- }
-
public synchronized static void init(File dataFolder) {
String config = dataFolder.getPath() + "/config.json";
if (Files.notExists(Paths.get(config))) {
@@ -55,8 +54,4 @@ private static void read(String path) {
}
}
- public ArrayList getPermissions() {
- return permissions;
- }
-
}
\ No newline at end of file
diff --git a/src/main/java/de/luuuuuis/privateserver/spigot/util/Owner.java b/src/main/java/de/luuuuuis/privateserver/spigot/util/Owner.java
index 1f170ae..b01180d 100644
--- a/src/main/java/de/luuuuuis/privateserver/spigot/util/Owner.java
+++ b/src/main/java/de/luuuuuis/privateserver/spigot/util/Owner.java
@@ -1,21 +1,26 @@
package de.luuuuuis.privateserver.spigot.util;
import de.dytanic.cloudnet.api.CloudAPI;
+import de.dytanic.cloudnet.bridge.CloudServer;
import de.dytanic.cloudnet.lib.player.CloudPlayer;
import de.dytanic.cloudnet.lib.player.permission.PermissionEntity;
import de.luuuuuis.privateserver.spigot.PrivateServer;
+import lombok.Getter;
+import lombok.Setter;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import java.util.UUID;
+@Getter
public class Owner {
private final UUID uuid;
+ @Setter
private Player player;
public Owner() {
- this.uuid = CloudAPI.getInstance().getServerInfo(CloudAPI.getInstance().getServerId()).getServerConfig().getProperties().getObject("uniqueId", UUID.class);
+ this.uuid = CloudServer.getInstance().getServerConfig().getProperties().getObject("uniqueId", UUID.class);
}
/**
@@ -39,16 +44,4 @@ public void setPermissionsWithDelay() {
cloudPlayer.setPermissionEntity(new Permission(uuid, permissionEntity.getPermissions(), permissionEntity.getPrefix(), permissionEntity.getSuffix(), permissionEntity.getGroups()));
}, 1);
}
-
- public Player getPlayer() {
- return player;
- }
-
- public void setPlayer(Player player) {
- this.player = player;
- }
-
- public UUID getUuid() {
- return uuid;
- }
}
diff --git a/src/main/resources/bungee.yml b/src/main/resources/bungee.yml
index 8b8daad..2b11aa4 100644
--- a/src/main/resources/bungee.yml
+++ b/src/main/resources/bungee.yml
@@ -1,5 +1,5 @@
name: PrivateServer
-version: "0.9"
+version: "0.10"
main: de.luuuuuis.privateserver.bungee.PrivateServer
author: Luuuuuis
depends:
diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml
index 33bb2b9..95ecfa7 100644
--- a/src/main/resources/plugin.yml
+++ b/src/main/resources/plugin.yml
@@ -1,8 +1,14 @@
name: PrivateServer
-version: "0.9"
+version: "0.10"
main: de.luuuuuis.privateserver.spigot.PrivateServer
author: Luuuuuis
depends:
- CloudNetAPI
description: Start private servers for CloudNet 2
website: https://github.com/Luuuuuis/PrivateServer
+
+commands:
+ privateserver:
+ description: private server command on the spigot server
+ aliases:
+ - pv