├── .gitignore
├── .idea
├── .name
├── compiler.xml
├── copyright
│ └── profiles_settings.xml
├── encodings.xml
├── misc.xml
├── modules.xml
├── scopes
│ └── scope_settings.xml
├── uiDesigner.xml
└── vcs.xml
├── BungeeServerManager.iml
├── LICENSE
├── README.md
├── pom.xml
└── src
└── main
├── java
└── pw
│ └── teg
│ └── bsm
│ ├── BungeeServerManager.java
│ ├── api
│ ├── ServerManagerAPI.java
│ └── events
│ │ ├── ServerAddEvent.java
│ │ ├── ServerEvent.java
│ │ ├── ServerModifiedEvent.java
│ │ └── ServerRemoveEvent.java
│ ├── commands
│ └── ServerManagerCommand.java
│ └── util
│ ├── ConfigHelper.java
│ └── ServerHelper.java
└── resources
└── plugin.yml
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | # Created by https://www.gitignore.io/api/macos,maven,windows,intellij+all
3 | # Edit at https://www.gitignore.io/?templates=macos,maven,windows,intellij+all
4 |
5 | ### Intellij+all ###
6 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm
7 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
8 |
9 | # User-specific stuff
10 | .idea/**/workspace.xml
11 | .idea/**/tasks.xml
12 | .idea/**/usage.statistics.xml
13 | .idea/**/dictionaries
14 | .idea/**/shelf
15 |
16 | # Generated files
17 | .idea/**/contentModel.xml
18 |
19 | # Sensitive or high-churn files
20 | .idea/**/dataSources/
21 | .idea/**/dataSources.ids
22 | .idea/**/dataSources.local.xml
23 | .idea/**/sqlDataSources.xml
24 | .idea/**/dynamic.xml
25 | .idea/**/uiDesigner.xml
26 | .idea/**/dbnavigator.xml
27 |
28 | # Gradle
29 | .idea/**/gradle.xml
30 | .idea/**/libraries
31 |
32 | # Gradle and Maven with auto-import
33 | # When using Gradle or Maven with auto-import, you should exclude module files,
34 | # since they will be recreated, and may cause churn. Uncomment if using
35 | # auto-import.
36 | .idea/modules.xml
37 | .idea/*.iml
38 | .idea/modules
39 | *.iml
40 | *.ipr
41 |
42 | # CMake
43 | cmake-build-*/
44 |
45 | # Mongo Explorer plugin
46 | .idea/**/mongoSettings.xml
47 |
48 | # File-based project format
49 | *.iws
50 |
51 | # IntelliJ
52 | out/
53 |
54 | # mpeltonen/sbt-idea plugin
55 | .idea_modules/
56 |
57 | # JIRA plugin
58 | atlassian-ide-plugin.xml
59 |
60 | # Cursive Clojure plugin
61 | .idea/replstate.xml
62 |
63 | # Crashlytics plugin (for Android Studio and IntelliJ)
64 | com_crashlytics_export_strings.xml
65 | crashlytics.properties
66 | crashlytics-build.properties
67 | fabric.properties
68 |
69 | # Editor-based Rest Client
70 | .idea/httpRequests
71 |
72 | # Android studio 3.1+ serialized cache file
73 | .idea/caches/build_file_checksums.ser
74 |
75 | ### Intellij+all Patch ###
76 | # Ignores the whole .idea folder and all .iml files
77 | # See https://github.com/joeblau/gitignore.io/issues/186 and https://github.com/joeblau/gitignore.io/issues/360
78 |
79 | .idea/
80 |
81 | # Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-249601023
82 |
83 | *.iml
84 | modules.xml
85 | .idea/misc.xml
86 | *.ipr
87 |
88 | # Sonarlint plugin
89 | .idea/sonarlint
90 |
91 | ### macOS ###
92 | # General
93 | .DS_Store
94 | .AppleDouble
95 | .LSOverride
96 |
97 | # Icon must end with two \r
98 | Icon
99 |
100 | # Thumbnails
101 | ._*
102 |
103 | # Files that might appear in the root of a volume
104 | .DocumentRevisions-V100
105 | .fseventsd
106 | .Spotlight-V100
107 | .TemporaryItems
108 | .Trashes
109 | .VolumeIcon.icns
110 | .com.apple.timemachine.donotpresent
111 |
112 | # Directories potentially created on remote AFP share
113 | .AppleDB
114 | .AppleDesktop
115 | Network Trash Folder
116 | Temporary Items
117 | .apdisk
118 |
119 | ### Maven ###
120 | target/
121 | pom.xml.tag
122 | pom.xml.releaseBackup
123 | pom.xml.versionsBackup
124 | pom.xml.next
125 | release.properties
126 | dependency-reduced-pom.xml
127 | buildNumber.properties
128 | .mvn/timing.properties
129 | .mvn/wrapper/maven-wrapper.jar
130 | .flattened-pom.xml
131 |
132 | ### Windows ###
133 | # Windows thumbnail cache files
134 | Thumbs.db
135 | Thumbs.db:encryptable
136 | ehthumbs.db
137 | ehthumbs_vista.db
138 |
139 | # Dump file
140 | *.stackdump
141 |
142 | # Folder config file
143 | [Dd]esktop.ini
144 |
145 | # Recycle Bin used on file shares
146 | $RECYCLE.BIN/
147 |
148 | # Windows Installer files
149 | *.cab
150 | *.msi
151 | *.msix
152 | *.msm
153 | *.msp
154 |
155 | # Windows shortcuts
156 | *.lnk
157 |
158 | # End of https://www.gitignore.io/api/macos,maven,windows,intellij+all
--------------------------------------------------------------------------------
/.idea/.name:
--------------------------------------------------------------------------------
1 | BungeeServerManager
--------------------------------------------------------------------------------
/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/.idea/copyright/profiles_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/.idea/encodings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 | Android
60 |
61 |
62 | Android Lint
63 |
64 |
65 | Code maturity issues
66 |
67 |
68 | Code style issues
69 |
70 |
71 | Control FlowGroovy
72 |
73 |
74 | Control flow issues
75 |
76 |
77 | Data flow issuesGroovy
78 |
79 |
80 | Error handling
81 |
82 |
83 | General
84 |
85 |
86 | Groovy
87 |
88 |
89 | J2ME issues
90 |
91 |
92 | Java language level issues
93 |
94 |
95 | Java language level migration aids
96 |
97 |
98 | Javadoc issues
99 |
100 |
101 | Memory issues
102 |
103 |
104 | Performance issues
105 |
106 |
107 | Plugin DevKit
108 |
109 |
110 | Portability issues
111 |
112 |
113 | Potentially confusing code constructsGroovy
114 |
115 |
116 | Probable bugs
117 |
118 |
119 | Probable bugsGroovy
120 |
121 |
122 | Security issues
123 |
124 |
125 | Threading issues
126 |
127 |
128 | Threading issuesGroovy
129 |
130 |
131 | Validity issuesGroovy
132 |
133 |
134 | XPath
135 |
136 |
137 | XSLT
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 | 1.7
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 | 1.7
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/scopes/scope_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/.idea/uiDesigner.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | -
6 |
7 |
8 | -
9 |
10 |
11 | -
12 |
13 |
14 | -
15 |
16 |
17 | -
18 |
19 |
20 |
21 |
22 |
23 | -
24 |
25 |
26 |
27 |
28 |
29 | -
30 |
31 |
32 |
33 |
34 |
35 | -
36 |
37 |
38 |
39 |
40 |
41 | -
42 |
43 |
44 |
45 |
46 | -
47 |
48 |
49 |
50 |
51 | -
52 |
53 |
54 |
55 |
56 | -
57 |
58 |
59 |
60 |
61 | -
62 |
63 |
64 |
65 |
66 | -
67 |
68 |
69 |
70 |
71 | -
72 |
73 |
74 | -
75 |
76 |
77 |
78 |
79 | -
80 |
81 |
82 |
83 |
84 | -
85 |
86 |
87 |
88 |
89 | -
90 |
91 |
92 |
93 |
94 | -
95 |
96 |
97 |
98 |
99 | -
100 |
101 |
102 | -
103 |
104 |
105 | -
106 |
107 |
108 | -
109 |
110 |
111 | -
112 |
113 |
114 |
115 |
116 | -
117 |
118 |
119 | -
120 |
121 |
122 |
123 |
124 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/BungeeServerManager.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 Tavon
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # BungeeServerManager
2 | Add, remove, and edit servers without restarting BungeeCord!
3 |
4 | Have you ever wanted to add or remove a server, change an ip address or port, or even change the motd without restarting BungeeCord? Well now you can! (yw)
5 |
6 | ### Download
7 | Download here on Spigot: http://www.spigotmc.org/resources/bungeeservermanager.7388/
8 |
9 | ### Installing
10 | Just drag the plugin file into your BungeeCord's plugin server.
11 |
12 | ### Permissions
13 | There's only one permission: `servermanager.use`
14 |
15 | ### Commands
16 | 
17 |
18 | ### FAQ
19 | ###### Where's the config?
20 | There is no configuration for this plugin, if you have any suggestions feel free to let me know.
21 |
22 | ###### What happens to players on a server that I remove?
23 | Players that are on a server that you remove are transported to the `fallback-server` set in BungeeCord's config.
24 |
25 | ###### My question isn't in the FAQ, what should I do?
26 | Create an issue with your question.
27 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 |
8 | UTF-8
9 | 1.7
10 | 1.7
11 |
12 |
13 | pw.teg
14 | BungeeServerManager
15 | 1.1.3-SNAPSHOT
16 |
17 |
18 |
19 | bungeecord-repo
20 | https://oss.sonatype.org/content/repositories/snapshots
21 |
22 |
23 |
24 |
25 |
26 | net.md-5
27 | bungeecord-api
28 | 1.15-SNAPSHOT
29 |
30 |
31 |
32 |
33 | BungeeServerManager
34 | src/main/java
35 |
36 |
37 | true
38 | src/main/resources
39 |
40 | *.yml
41 | *.jar
42 | **/*.yml
43 |
44 |
45 |
46 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/src/main/java/pw/teg/bsm/BungeeServerManager.java:
--------------------------------------------------------------------------------
1 | package pw.teg.bsm;
2 |
3 | import net.md_5.bungee.api.plugin.Plugin;
4 | import pw.teg.bsm.api.ServerManagerAPI;
5 | import pw.teg.bsm.commands.ServerManagerCommand;
6 |
7 | public class BungeeServerManager extends Plugin {
8 |
9 | private static BungeeServerManager instance;
10 | private static ServerManagerAPI api;
11 |
12 | @Override
13 | public void onEnable() {
14 | instance = this;
15 |
16 | api = new ServerManagerAPI();
17 |
18 | getProxy().getPluginManager().registerCommand(this, new ServerManagerCommand());
19 |
20 | }
21 |
22 | public static BungeeServerManager get() {
23 | return instance;
24 | }
25 |
26 | public static ServerManagerAPI getApi() {
27 | return api;
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/main/java/pw/teg/bsm/api/ServerManagerAPI.java:
--------------------------------------------------------------------------------
1 | package pw.teg.bsm.api;
2 |
3 | import net.md_5.bungee.api.ProxyServer;
4 | import net.md_5.bungee.api.config.ServerInfo;
5 | import pw.teg.bsm.api.events.ServerAddEvent;
6 | import pw.teg.bsm.api.events.ServerRemoveEvent;
7 | import pw.teg.bsm.util.ServerHelper;
8 |
9 | import java.net.InetSocketAddress;
10 | import java.util.Collection;
11 |
12 | public class ServerManagerAPI {
13 |
14 | public boolean addServer(String name, InetSocketAddress ipAddress, String motd, boolean restricted) {
15 | if (ServerHelper.getServerInfo(name) != null) {
16 | return false;
17 | }
18 |
19 | ServerInfo serverInfo = ProxyServer.getInstance().constructServerInfo(name, ipAddress, motd, restricted);
20 | ServerAddEvent addEvent = new ServerAddEvent(serverInfo, null);
21 |
22 | if (addEvent.isCancelled()) {
23 | return false;
24 | }
25 |
26 | ServerHelper.addServer(addEvent.getServerModified());
27 | return true;
28 | }
29 |
30 | public boolean removeServer(String name) {
31 | ServerInfo serverInfo = ServerHelper.getServerInfo(name);
32 |
33 | if (serverInfo == null) {
34 | return false;
35 | }
36 |
37 | ServerRemoveEvent addEvent = new ServerRemoveEvent(serverInfo, null);
38 |
39 | if (addEvent.isCancelled()) {
40 | return false;
41 | }
42 |
43 | ServerHelper.removeServer(addEvent.getServerModified().getName());
44 | return true;
45 | }
46 |
47 | public boolean serverExists(String name) {
48 | return ServerHelper.serverExists(name);
49 | }
50 |
51 | public Collection listServers() {
52 | return ServerHelper.getServers().values();
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/src/main/java/pw/teg/bsm/api/events/ServerAddEvent.java:
--------------------------------------------------------------------------------
1 | package pw.teg.bsm.api.events;
2 |
3 | import net.md_5.bungee.api.CommandSender;
4 | import net.md_5.bungee.api.config.ServerInfo;
5 | import net.md_5.bungee.api.plugin.Cancellable;
6 |
7 | public class ServerAddEvent extends ServerEvent implements Cancellable {
8 |
9 | private CommandSender sender;
10 | private boolean cancelled;
11 |
12 | public ServerAddEvent(ServerInfo serverModified, CommandSender sender) {
13 | super(serverModified);
14 | this.sender = sender;
15 | }
16 |
17 | public CommandSender getSender() {
18 | return sender;
19 | }
20 |
21 | @Override
22 | public boolean isCancelled() {
23 | return cancelled;
24 | }
25 |
26 | @Override
27 | public void setCancelled(boolean cancelled) {
28 | this.cancelled = cancelled;
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/main/java/pw/teg/bsm/api/events/ServerEvent.java:
--------------------------------------------------------------------------------
1 | package pw.teg.bsm.api.events;
2 |
3 | import net.md_5.bungee.api.config.ServerInfo;
4 | import net.md_5.bungee.api.plugin.Event;
5 |
6 | public abstract class ServerEvent extends Event {
7 |
8 | private ServerInfo serverModified;
9 |
10 | public ServerEvent(ServerInfo serverModified) {
11 | this.serverModified = serverModified;
12 | }
13 |
14 | public ServerInfo getServerModified() {
15 | return serverModified;
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/main/java/pw/teg/bsm/api/events/ServerModifiedEvent.java:
--------------------------------------------------------------------------------
1 | package pw.teg.bsm.api.events;
2 |
3 | import net.md_5.bungee.api.CommandSender;
4 | import net.md_5.bungee.api.config.ServerInfo;
5 | import net.md_5.bungee.api.plugin.Cancellable;
6 |
7 | public class ServerModifiedEvent extends ServerEvent implements Cancellable {
8 |
9 | private CommandSender sender;
10 | private ServerField modified;
11 | private T newValue;
12 | private boolean cancelled;
13 |
14 | public ServerModifiedEvent(ServerInfo serverModified, CommandSender sender, ServerField modified, T newValue) {
15 | super(serverModified);
16 | this.sender = sender;
17 | this.modified = modified;
18 | this.newValue = newValue;
19 | }
20 |
21 | public CommandSender getSender() {
22 | return sender;
23 | }
24 |
25 | public ServerField getModified() {
26 | return modified;
27 | }
28 |
29 | public T getNewValue() {
30 | return newValue;
31 | }
32 |
33 | public void setNewValue(T newValue) {
34 | this.newValue = newValue;
35 | }
36 |
37 | @Override
38 | public boolean isCancelled() {
39 | return cancelled;
40 | }
41 |
42 | @Override
43 | public void setCancelled(boolean cancelled) {
44 | this.cancelled = cancelled;
45 | }
46 |
47 | public enum ServerField {
48 | NAME, IP, MOTD, RESTRICTED
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/main/java/pw/teg/bsm/api/events/ServerRemoveEvent.java:
--------------------------------------------------------------------------------
1 | package pw.teg.bsm.api.events;
2 |
3 | import net.md_5.bungee.api.CommandSender;
4 | import net.md_5.bungee.api.config.ServerInfo;
5 | import net.md_5.bungee.api.plugin.Cancellable;
6 |
7 | public class ServerRemoveEvent extends ServerEvent implements Cancellable {
8 |
9 | private CommandSender sender;
10 | private boolean cancelled;
11 |
12 | public ServerRemoveEvent(ServerInfo serverModified, CommandSender sender) {
13 | super(serverModified);
14 | this.sender = sender;
15 | }
16 |
17 | public CommandSender getSender() {
18 | return sender;
19 | }
20 |
21 | @Override
22 | public boolean isCancelled() {
23 | return cancelled;
24 | }
25 |
26 | @Override
27 | public void setCancelled(boolean cancelled) {
28 | this.cancelled = cancelled;
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/main/java/pw/teg/bsm/commands/ServerManagerCommand.java:
--------------------------------------------------------------------------------
1 | package pw.teg.bsm.commands;
2 |
3 | import com.google.common.base.Joiner;
4 | import net.md_5.bungee.Util;
5 | import net.md_5.bungee.api.ChatColor;
6 | import net.md_5.bungee.api.CommandSender;
7 | import net.md_5.bungee.api.ProxyServer;
8 | import net.md_5.bungee.api.chat.*;
9 | import net.md_5.bungee.api.config.ListenerInfo;
10 | import net.md_5.bungee.api.config.ServerInfo;
11 | import net.md_5.bungee.api.plugin.Command;
12 | import pw.teg.bsm.BungeeServerManager;
13 | import pw.teg.bsm.api.events.ServerAddEvent;
14 | import pw.teg.bsm.api.events.ServerModifiedEvent;
15 | import pw.teg.bsm.api.events.ServerRemoveEvent;
16 | import pw.teg.bsm.util.ConfigHelper;
17 | import pw.teg.bsm.util.ServerHelper;
18 |
19 | import java.net.InetSocketAddress;
20 | import java.net.SocketAddress;
21 | import java.util.*;
22 |
23 | public class ServerManagerCommand extends Command {
24 |
25 | private final String prefix = ChatColor.GRAY + "[" + ChatColor.GREEN + "ServerManager" + ChatColor.GRAY + "] ";
26 |
27 | public ServerManagerCommand() {
28 | super("servermanager", "servermanager.use", "svm");
29 | }
30 |
31 | @Override
32 | public void execute(CommandSender sender, String[] args) {
33 | if (args.length == 0) {
34 | sendHelp(sender);
35 | return;
36 | }
37 |
38 | if (args[0].equalsIgnoreCase("help")) {
39 | sendHelp(sender);
40 | return;
41 | }
42 |
43 | if (args[0].equalsIgnoreCase("list")) {
44 | if (ServerHelper.getServers().isEmpty()) {
45 | sender.sendMessage(TextComponent.fromLegacyText(prefix + "No servers."));
46 | return;
47 | }
48 |
49 | sender.sendMessage(TextComponent.fromLegacyText(prefix + "Servers: " + ChatColor.GREEN + Joiner.on(ChatColor.GRAY + ", " + ChatColor.GREEN).join(ServerHelper.getServers().keySet())));
50 | return;
51 | }
52 |
53 | if (args[0].equalsIgnoreCase("info")) {
54 | if (args.length < 2) {
55 | sendUsage(sender, "/svm info ");
56 | return;
57 | }
58 |
59 | if (!ServerHelper.serverExists(args[1])) {
60 | sender.sendMessage(TextComponent.fromLegacyText(prefix + "The server " + ChatColor.GREEN + args[1] + ChatColor.GRAY + " does not exist."));
61 | return;
62 | }
63 |
64 | ServerInfo info = ServerHelper.getServerInfo(args[1]);
65 |
66 | if (info == null) {
67 | sender.sendMessage(TextComponent.fromLegacyText(prefix + "The server " + ChatColor.GREEN + args[1] + ChatColor.GRAY + " does not exist."));
68 | return;
69 | }
70 |
71 | Set forcedHosts = new HashSet<>();
72 |
73 | for (ListenerInfo listenerInfo : BungeeServerManager.get().getProxy().getConfig().getListeners()) {
74 | for (Map.Entry entry : listenerInfo.getForcedHosts().entrySet()) {
75 | if (entry.getValue().equalsIgnoreCase(info.getName())) {
76 | forcedHosts.add(entry.getKey());
77 | }
78 | }
79 | }
80 |
81 | sender.sendMessage(TextComponent.fromLegacyText(ChatColor.GRAY + "--- " + ChatColor.GREEN + info.getName() + " Info" + ChatColor.GRAY + " ---"));
82 | sender.sendMessage(TextComponent.fromLegacyText(ChatColor.GREEN + "Name: " + ChatColor.GRAY + info.getName()));
83 | sender.sendMessage(TextComponent.fromLegacyText(ChatColor.GREEN + "Address: " + ChatColor.GRAY + ConfigHelper.socketAddressToString(info.getSocketAddress())));
84 | sender.sendMessage(TextComponent.fromLegacyText(ChatColor.GREEN + "Motd: " + ChatColor.GRAY + info.getMotd()));
85 | sender.sendMessage(TextComponent.fromLegacyText(ChatColor.GREEN + "Restricted: " + ChatColor.GRAY + info.isRestricted()));
86 | sender.sendMessage(TextComponent.fromLegacyText(ChatColor.GREEN + "Player Count: " + ChatColor.GRAY + info.getPlayers().size()));
87 | if (!forcedHosts.isEmpty()) {
88 | sender.sendMessage(TextComponent.fromLegacyText(ChatColor.GREEN + "Forced Hosts: " + ChatColor.GRAY + Joiner.on(", ").join(forcedHosts)));
89 | }
90 | sender.sendMessage(TextComponent.fromLegacyText(ChatColor.GRAY + "--------"));
91 | return;
92 | }
93 |
94 | if (args[0].equalsIgnoreCase("add")) {
95 | if (args.length < 2) {
96 | sendUsage(sender, "/svm add [hostname]");
97 | return;
98 | }
99 |
100 | if (ServerHelper.serverExists(args[1])) {
101 | sender.sendMessage(TextComponent.fromLegacyText(prefix + "The server " + ChatColor.GREEN + args[1] + ChatColor.GRAY + " already exists."));
102 | return;
103 | }
104 |
105 | SocketAddress address = new InetSocketAddress(22565);
106 | boolean customAddress = false;
107 |
108 | if (args.length >= 3) {
109 | address = getIp(args[2]);
110 | customAddress = true;
111 |
112 | if (address == null) {
113 | sender.sendMessage(TextComponent.fromLegacyText(prefix + "Invalid address " + ChatColor.GREEN + args[2] + ChatColor.GRAY + ". Here's an example: " + ChatColor.GREEN + "127.0.0.1:25565"));
114 | return;
115 | }
116 | }
117 |
118 | ServerInfo info = ProxyServer.getInstance().constructServerInfo(args[1], address, "", false);
119 | ServerAddEvent addEvent = new ServerAddEvent(info, sender);
120 |
121 | BungeeServerManager.get().getProxy().getPluginManager().callEvent(addEvent);
122 |
123 | if (addEvent.isCancelled()) {
124 | return;
125 | }
126 |
127 | ServerHelper.addServer(addEvent.getServerModified());
128 | sender.sendMessage(TextComponent.fromLegacyText(prefix + "Added a server with the name " +
129 | ChatColor.GREEN + addEvent.getServerModified().getName() + (customAddress ? " and address " +
130 | ChatColor.GREEN + args[2] + ChatColor.GREEN + "." : "")));
131 | return;
132 | }
133 |
134 | if (args[0].equalsIgnoreCase("remove")) {
135 | if (args.length < 2) {
136 | sendUsage(sender, "/svm remove ");
137 | return;
138 | }
139 |
140 | if (!ServerHelper.serverExists(args[1])) {
141 | sender.sendMessage(TextComponent.fromLegacyText(prefix + "The server " + ChatColor.GREEN + args[1] + ChatColor.GRAY + " does not exist."));
142 | return;
143 | }
144 |
145 | ServerRemoveEvent removeEvent = new ServerRemoveEvent(ServerHelper.getServerInfo(args[1]), sender);
146 |
147 | BungeeServerManager.get().getProxy().getPluginManager().callEvent(removeEvent);
148 |
149 | if (removeEvent.isCancelled()) {
150 | return;
151 | }
152 |
153 | ServerHelper.removeServer(removeEvent.getServerModified().getName());
154 | sender.sendMessage(TextComponent.fromLegacyText(prefix + "Removed the server " + ChatColor.GREEN + removeEvent.getServerModified().getName()));
155 | return;
156 | }
157 |
158 | if (args[0].equalsIgnoreCase("edit")) {
159 | if (args.length < 2) {
160 | sendUsage(sender, "/svm edit ");
161 | return;
162 | }
163 |
164 | ServerInfo info = ServerHelper.getServerInfo(args[1]);
165 |
166 | if (info == null) {
167 | sender.sendMessage(TextComponent.fromLegacyText(prefix + "The server " + ChatColor.GREEN + args[1] + ChatColor.GRAY + " does not exist."));
168 | return;
169 | }
170 |
171 | if (args.length == 2) {
172 | sendEditMenu(sender, info.getName());
173 | return;
174 | }
175 |
176 | if (args[2].equalsIgnoreCase("name")) {
177 | if (args.length < 4) {
178 | sendUsage(sender, "/svm edit " + info.getName() + " name ");
179 | return;
180 | }
181 |
182 | ServerModifiedEvent modifiedEvent = new ServerModifiedEvent<>(info, sender, ServerModifiedEvent.ServerField.NAME, args[3]);
183 |
184 | BungeeServerManager.get().getProxy().getPluginManager().callEvent(modifiedEvent);
185 |
186 | if (modifiedEvent.isCancelled()) {
187 | return;
188 | }
189 |
190 | info = modifiedEvent.getServerModified();
191 |
192 | ServerHelper.removeServer(info.getName());
193 | ServerHelper.addServer(ProxyServer.getInstance().constructServerInfo(modifiedEvent.getNewValue(), info.getSocketAddress(), info.getMotd(), false));
194 | sender.sendMessage(TextComponent.fromLegacyText(prefix + "Renamed " + ChatColor.GREEN + info.getName() + ChatColor.GRAY + " to " + ChatColor.GREEN + modifiedEvent.getNewValue() + ChatColor.GRAY + "."));
195 | return;
196 | }
197 |
198 | if (args[2].equalsIgnoreCase("ip")) {
199 | if (args.length < 4) {
200 | sendUsage(sender, "/svm edit " + info.getName() + " ip ");
201 | return;
202 | }
203 |
204 | SocketAddress address = getIp(args[3]);
205 |
206 | if (address == null) {
207 | sender.sendMessage(TextComponent.fromLegacyText(prefix + "Invalid address " + ChatColor.GREEN + args[3] + ChatColor.GRAY + ". Here's an example: " + ChatColor.GREEN + "127.0.0.1:25565"));
208 | return;
209 | }
210 |
211 | ServerModifiedEvent modifiedEvent = new ServerModifiedEvent<>(ServerHelper.getServerInfo(args[1]), sender, ServerModifiedEvent.ServerField.IP, address);
212 |
213 | BungeeServerManager.get().getProxy().getPluginManager().callEvent(modifiedEvent);
214 |
215 | if (modifiedEvent.isCancelled()) {
216 | return;
217 | }
218 |
219 | info = modifiedEvent.getServerModified();
220 |
221 | ServerHelper.removeServer(info.getName());
222 | ServerHelper.addServer(ProxyServer.getInstance().constructServerInfo(info.getName(), modifiedEvent.getNewValue(), info.getMotd(), false));
223 | sender.sendMessage(TextComponent.fromLegacyText(prefix + "Set the address of " + ChatColor.GREEN + info.getName() + ChatColor.GRAY + " to " + ChatColor.GREEN + args[3] + ChatColor.GRAY + "."));
224 | return;
225 | }
226 |
227 | if (args[2].equalsIgnoreCase("motd")) {
228 | if (args.length < 4) {
229 | sendUsage(sender, "/svm edit " + info.getName() + " motd ");
230 | return;
231 | }
232 |
233 | StringBuilder builder = new StringBuilder();
234 |
235 | for (int i = 3; i < args.length; i++) {
236 | builder.append(args[i]).append(" ");
237 | }
238 |
239 | ServerModifiedEvent modifiedEvent = new ServerModifiedEvent<>(info, sender, ServerModifiedEvent.ServerField.MOTD, ChatColor.translateAlternateColorCodes('&', builder.toString().trim()));
240 |
241 | BungeeServerManager.get().getProxy().getPluginManager().callEvent(modifiedEvent);
242 |
243 | if (modifiedEvent.isCancelled()) {
244 | return;
245 | }
246 |
247 | info = modifiedEvent.getServerModified();
248 |
249 | ServerHelper.removeServer(info.getName());
250 | ServerHelper.addServer(ProxyServer.getInstance().constructServerInfo(info.getName(), info.getSocketAddress(), modifiedEvent.getNewValue(), false));
251 | sender.sendMessage(TextComponent.fromLegacyText(prefix + "Set the motd of " + ChatColor.GREEN + info.getName() + ChatColor.GRAY + " to " + ChatColor.GREEN + ChatColor.translateAlternateColorCodes('&', builder.toString().trim()) + ChatColor.GRAY + "."));
252 | return;
253 | }
254 |
255 | if (args[2].equalsIgnoreCase("restricted")) {
256 | if (args.length < 4) {
257 | sendUsage(sender, "/svm edit " + info.getName() + " restricted ");
258 | return;
259 | }
260 |
261 | ServerModifiedEvent modifiedEvent = new ServerModifiedEvent<>(info, sender, ServerModifiedEvent.ServerField.RESTRICTED, Boolean.parseBoolean(args[3]));
262 |
263 | BungeeServerManager.get().getProxy().getPluginManager().callEvent(modifiedEvent);
264 |
265 | if (modifiedEvent.isCancelled()) {
266 | return;
267 | }
268 |
269 | info = modifiedEvent.getServerModified();
270 |
271 | ServerHelper.removeServer(info.getName());
272 | ServerHelper.addServer(ProxyServer.getInstance().constructServerInfo(info.getName(), info.getSocketAddress(), info.getMotd(), modifiedEvent.getNewValue()));
273 | sender.sendMessage(TextComponent.fromLegacyText(prefix + "Set the restriction of " + ChatColor.GREEN + info.getName() + ChatColor.GRAY + " to " + ChatColor.GREEN + Boolean.parseBoolean(args[3]) + ChatColor.GRAY + "."));
274 | return;
275 | }
276 |
277 | if (args[2].equalsIgnoreCase("domain")) {
278 | if (args.length < 5 || (!args[3].equalsIgnoreCase("add") && !args[3].equalsIgnoreCase("remove"))) {
279 | sendUsage(sender, "/svm edit " + info.getName() + " domain ");
280 | return;
281 | }
282 |
283 | boolean addingDomain = args[3].equalsIgnoreCase("add");
284 | final SocketAddress address = getIp(args[4]);
285 |
286 | if (address == null) {
287 | sender.sendMessage(TextComponent.fromLegacyText(prefix + "Invalid address " + ChatColor.GREEN + args[4] + ChatColor.GRAY + ". Here's an example: " + ChatColor.GREEN + "pvp.md-5.net"));
288 | return;
289 | }
290 |
291 | String socketAddressStr = ConfigHelper.socketAddressToString(address, false);
292 |
293 | if (addingDomain) {
294 | ConfigHelper.addForcedHost(address, info);
295 |
296 | for (ListenerInfo listenerInfo : BungeeServerManager.get().getProxy().getConfig().getListeners()) {
297 | listenerInfo.getForcedHosts().put(socketAddressStr, info.getName());
298 | }
299 |
300 | sender.sendMessage(TextComponent.fromLegacyText(prefix + "Added forced host of " + ChatColor.GREEN +
301 | socketAddressStr + ChatColor.GRAY + " for server " + ChatColor.GREEN +
302 | info.getName() + ChatColor.GRAY + "."));
303 | } else {
304 | boolean found = false;
305 |
306 | ConfigHelper.removeForcedHost(address, info);
307 |
308 | for (ListenerInfo listenerInfo : BungeeServerManager.get().getProxy().getConfig().getListeners()) {
309 | String targetServer = listenerInfo.getForcedHosts().get(socketAddressStr);
310 |
311 | if (targetServer != null && targetServer.equalsIgnoreCase(info.getName())) {
312 | listenerInfo.getForcedHosts().remove(socketAddressStr);
313 | found = true;
314 | }
315 | }
316 |
317 | if (found) {
318 | sender.sendMessage(TextComponent.fromLegacyText(prefix + "Removed forced host of " +
319 | ChatColor.GREEN + socketAddressStr + ChatColor.GRAY + " for server " +
320 | ChatColor.GREEN + info.getName() + ChatColor.GRAY + "."));
321 | } else {
322 | sender.sendMessage(TextComponent.fromLegacyText(prefix + "Could not find forced host of " +
323 | ChatColor.GREEN + socketAddressStr + ChatColor.GRAY + " for server " +
324 | ChatColor.GREEN + info.getName() + ChatColor.GRAY + "."));
325 | }
326 | }
327 | return;
328 | }
329 |
330 | sender.sendMessage(TextComponent.fromLegacyText(prefix + "Unknown argument " + ChatColor.GREEN + args[2] + ChatColor.GRAY + " use " + ChatColor.GREEN + "/svm edit " + info.getName() + ChatColor.GRAY + " for help."));
331 | return;
332 | }
333 |
334 | sender.sendMessage(TextComponent.fromLegacyText(prefix + "Unknown argument " + ChatColor.GREEN + args[0] + ChatColor.GRAY + " use " + ChatColor.GREEN + "/svm help" + ChatColor.GRAY + " for help."));
335 | }
336 |
337 | private void sendHelp(CommandSender sender) {
338 | sender.sendMessage(TextComponent.fromLegacyText(prefix + "Help:"));
339 | sender.sendMessage(getHelpString("/svm help", "Display this help menu"));
340 | sender.sendMessage(getHelpString("/svm list", "List servers"));
341 | sender.sendMessage(getHelpString("/svm info ", "Display info about a server"));
342 | sender.sendMessage(getHelpString("/svm add [hostname]", "Add a server to BungeeCord"));
343 | sender.sendMessage(getHelpString("/svm remove ", "Remove a server from BungeeCord"));
344 | sender.sendMessage(getHelpString("/svm edit ", "Edit a server's information"));
345 | }
346 |
347 | private BaseComponent[] getHelpString(String command, String info) {
348 | return new ComponentBuilder(ChatColor.GREEN + command + ChatColor.GRAY + " - " + info)
349 | .event(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, command))
350 | .event(new HoverEvent(HoverEvent.Action.SHOW_TEXT, TextComponent.fromLegacyText(ChatColor.GREEN + "Click to execute this command")))
351 | .create();
352 | }
353 |
354 | private void sendUsage(CommandSender sender, String usage) {
355 | sender.sendMessage(new ComponentBuilder(prefix + "Correct usage: " + ChatColor.GREEN + usage)
356 | .event(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, "command"))
357 | .event(new HoverEvent(HoverEvent.Action.SHOW_TEXT, TextComponent.fromLegacyText(ChatColor.GREEN + "Click to execute this command")))
358 | .create());
359 | }
360 |
361 | private void sendEditMenu(CommandSender sender, String serverName) {
362 | sender.sendMessage(TextComponent.fromLegacyText(prefix + " Edit Help:"));
363 | sender.sendMessage(getHelpString("/svm edit " + serverName + " name ", "Change this server's name"));
364 | sender.sendMessage(getHelpString("/svm edit " + serverName + " ip ", "Change this server's address"));
365 | sender.sendMessage(getHelpString("/svm edit " + serverName + " motd ", "Change this server's motd"));
366 | sender.sendMessage(getHelpString("/svm edit " + serverName + " restricted ", "Change this server's restricted flag"));
367 | sender.sendMessage(getHelpString("/svm edit " + serverName + " domain ", "Add or remove a forced host for this server"));
368 | }
369 |
370 | private SocketAddress getIp(String input) {
371 | try {
372 | return Util.getAddr(input);
373 | } catch (IllegalArgumentException exec) {
374 | return null;
375 | }
376 | }
377 | }
378 |
--------------------------------------------------------------------------------
/src/main/java/pw/teg/bsm/util/ConfigHelper.java:
--------------------------------------------------------------------------------
1 | package pw.teg.bsm.util;
2 |
3 | import io.netty.channel.unix.DomainSocketAddress;
4 | import net.md_5.bungee.api.ChatColor;
5 | import net.md_5.bungee.api.ProxyServer;
6 | import net.md_5.bungee.api.config.ServerInfo;
7 | import net.md_5.bungee.config.Configuration;
8 | import net.md_5.bungee.config.YamlConfiguration;
9 | import pw.teg.bsm.BungeeServerManager;
10 |
11 | import java.io.*;
12 | import java.net.InetSocketAddress;
13 | import java.net.SocketAddress;
14 | import java.util.ArrayList;
15 | import java.util.List;
16 | import java.util.Map;
17 | import java.util.concurrent.TimeUnit;
18 |
19 | public class ConfigHelper {
20 |
21 | private static File file;
22 | private static Configuration bungeeConfig;
23 | private static boolean locked; // TODO: This is dumb. Writes are lost when locked
24 |
25 | static {
26 | // Plugins are loaded before the config (on first run) so uhhhhh, here we go
27 | setupConfig();
28 |
29 | if (locked) {
30 | ProxyServer.getInstance().getScheduler().schedule(BungeeServerManager.get(), new Runnable() {
31 | @Override
32 | public void run() {
33 | setupConfig();
34 | }
35 | }, 5L, TimeUnit.SECONDS);
36 | }
37 | }
38 |
39 | public static String socketAddressToString(SocketAddress socketAddress) {
40 | return socketAddressToString(socketAddress, true);
41 | }
42 |
43 | public static String socketAddressToString(SocketAddress socketAddress, boolean appendPort) {
44 | String addressString;
45 |
46 | if (socketAddress instanceof DomainSocketAddress) {
47 | addressString = "unix:" + ((DomainSocketAddress) socketAddress).path();
48 | } else if (socketAddress instanceof InetSocketAddress) {
49 | InetSocketAddress inetAddress = (InetSocketAddress) socketAddress;
50 |
51 | addressString = inetAddress.getHostString();
52 |
53 | if (appendPort) {
54 | addressString += ":" + inetAddress.getPort();
55 | }
56 | } else {
57 | addressString = socketAddress.toString();
58 | }
59 |
60 | return addressString;
61 | }
62 |
63 | public static void addToConfig(ServerInfo serverInfo) {
64 | if (locked) {
65 | return;
66 | }
67 |
68 | bungeeConfig.set("servers." + serverInfo.getName() + ".motd", serverInfo.getMotd().replace(ChatColor.COLOR_CHAR, '&'));
69 | bungeeConfig.set("servers." + serverInfo.getName() + ".address", socketAddressToString(serverInfo.getSocketAddress()));
70 | bungeeConfig.set("servers." + serverInfo.getName() + ".restricted", serverInfo.isRestricted());
71 | saveConfig();
72 | }
73 |
74 | public static void removeFromConfig(ServerInfo serverInfo) {
75 | removeFromConfig(serverInfo.getName());
76 | }
77 |
78 | public static void removeFromConfig(String name) {
79 | if (locked) {
80 | return;
81 | }
82 |
83 | bungeeConfig.set("servers." + name, null);
84 | saveConfig();
85 | }
86 |
87 | public static void addForcedHost(SocketAddress host, ServerInfo server) {
88 | changeForcedHost(host, false, server);
89 | }
90 |
91 | public static void removeForcedHost(SocketAddress host, ServerInfo server) {
92 | changeForcedHost(host, true, server);
93 | }
94 |
95 | private static void changeForcedHost(SocketAddress host, boolean remove, ServerInfo server) {
96 | if (locked) {
97 | return;
98 | }
99 |
100 | List> listeners = bungeeConfig.getList("listeners");
101 | List