Implemented Players, CpuUsage, RamUsage Commands. Updated README
This commit is contained in:
33
README.md
33
README.md
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
# WebConsole
|
# WebConsole
|
||||||
|
|
||||||
WebConsole is a Spigot plugin for Minecraft 1.14 that enables you to view your server console and manage your server from anywhere. It creates a WebSocket server in the background used by the web interface to send commands, receive your console log and manage your server.
|
WebConsole is a Spigot plugin for Minecraft 1.8-1.14 that enables you to view your server console and manage your server from anywhere. It creates a WebSocket server in the background used by the web interface to send commands, receive your console log and manage your server.
|
||||||
|
|
||||||
Dont worry about privacy: all data is stored in your browser offline and your PC will connect directly to your minecraft server. No intermediary web servers, just you and your server.
|
Dont worry about privacy: all data is stored in your browser offline and your PC will connect directly to your minecraft server. No intermediary web servers, just you and your server.
|
||||||
|
|
||||||
@ -67,34 +67,5 @@ WebConsole does not support PEM certificates, so you will need to convert it to
|
|||||||
|
|
||||||
## Technical information
|
## Technical information
|
||||||
|
|
||||||
### WebSocket commands
|
You can find how client and server comunicate [here](https://github.com/mesacarlos/WebConsole/wiki/WebSocket-commands-and-responses)
|
||||||
|
|
||||||
The following tables represent how server communicates with the client(s), something like a language between them.
|
|
||||||
|
|
||||||
|
|
||||||
#### Websocket Server -> Client
|
|
||||||
|
|
||||||
Server communicate with all connected clients using JSON. The following table shows all possible JSON variables.
|
|
||||||
|
|
||||||
| Variable |Meaning |
|
|
||||||
|---------------------|-----------------------------------------------------------------------------|
|
|
||||||
| status |Status code (as integer), representing response type. See listing below* |
|
|
||||||
| statusDescription |Status description (as String) describing response type. |
|
|
||||||
| respondsTo |`(Optional)` Original command sent by client which triggered this response|
|
|
||||||
| message |Response content |
|
|
||||||
|
|
||||||
*Status codes are listed below:
|
|
||||||
- **010**: Console output.
|
|
||||||
- **200**: Ok/Processed.
|
|
||||||
- **400**: Unknown command.
|
|
||||||
- **401**: Login required/Not logged in.
|
|
||||||
|
|
||||||
|
|
||||||
#### Client -> Websocket Server
|
|
||||||
|
|
||||||
Clients can communicate with server using commands. The following table shows existing commands.
|
|
||||||
|
|
||||||
| Code |Meaning |Extra info |
|
|
||||||
|---------------------|-----------------------------------------|--------------|
|
|
||||||
|LOGIN *(password)* |Login to start communication with server | |
|
|
||||||
|EXEC *(command)* |Run desired command in Minecraft Server |Login required|
|
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
name: WebConsole
|
name: WebConsole
|
||||||
main: com.mesacarlos.webconsole.WebConsole
|
main: com.mesacarlos.webconsole.WebConsole
|
||||||
version: 1.0
|
version: 1.1
|
||||||
description: WebSockets-based web console
|
description: WebSockets-based web console
|
||||||
api-version: 1.14
|
|
||||||
author: Carlos Mesa
|
author: Carlos Mesa
|
||||||
commands:
|
commands:
|
4
pom.xml
4
pom.xml
@ -4,7 +4,7 @@
|
|||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<groupId>WebConsole</groupId>
|
<groupId>WebConsole</groupId>
|
||||||
<artifactId>WebConsole</artifactId>
|
<artifactId>WebConsole</artifactId>
|
||||||
<version>1.0</version>
|
<version>1.1</version>
|
||||||
<build>
|
<build>
|
||||||
<sourceDirectory>src</sourceDirectory>
|
<sourceDirectory>src</sourceDirectory>
|
||||||
<plugins>
|
<plugins>
|
||||||
@ -59,7 +59,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.spigotmc</groupId>
|
<groupId>org.spigotmc</groupId>
|
||||||
<artifactId>spigot-api</artifactId>
|
<artifactId>spigot-api</artifactId>
|
||||||
<version>1.14.2-R0.1-SNAPSHOT</version>
|
<version>1.8.8-R0.1-SNAPSHOT</version>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<!-- WebSockets Server Dependency -->
|
<!-- WebSockets Server Dependency -->
|
||||||
|
@ -4,10 +4,7 @@ import java.io.File;
|
|||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.security.KeyManagementException;
|
|
||||||
import java.security.KeyStore;
|
import java.security.KeyStore;
|
||||||
import java.security.KeyStoreException;
|
|
||||||
import java.security.UnrecoverableKeyException;
|
|
||||||
|
|
||||||
import javax.net.ssl.KeyManagerFactory;
|
import javax.net.ssl.KeyManagerFactory;
|
||||||
import javax.net.ssl.SSLContext;
|
import javax.net.ssl.SSLContext;
|
||||||
@ -78,8 +75,7 @@ public class WebConsole extends JavaPlugin {
|
|||||||
/**
|
/**
|
||||||
* Start WebSocket server
|
* Start WebSocket server
|
||||||
*/
|
*/
|
||||||
private void startWS() throws Exception,
|
private void startWS() throws Exception {
|
||||||
KeyStoreException, UnrecoverableKeyException, KeyManagementException {
|
|
||||||
// Create WebSocket server
|
// Create WebSocket server
|
||||||
server = new WSServer(this, new InetSocketAddress(config.getString("host"), config.getInt("port")));
|
server = new WSServer(this, new InetSocketAddress(config.getString("host"), config.getInt("port")));
|
||||||
|
|
||||||
|
@ -7,7 +7,10 @@ public class CommandFactory {
|
|||||||
public static HashMap<String, WSCommand> getCommandsHashMap() {
|
public static HashMap<String, WSCommand> getCommandsHashMap() {
|
||||||
HashMap<String, WSCommand> commands = new HashMap<String, WSCommand>();
|
HashMap<String, WSCommand> commands = new HashMap<String, WSCommand>();
|
||||||
commands.put("LOGIN", new LogInCommand());
|
commands.put("LOGIN", new LogInCommand());
|
||||||
commands.put("EXEC", new ExecuteCmdCommand());
|
commands.put("EXEC", new ExecCommand());
|
||||||
|
commands.put("PLAYERS", new PlayersCommand());
|
||||||
|
commands.put("CPUUSAGE", new CpuUsageCommand());
|
||||||
|
commands.put("RAMUSAGE", new RamUsageCommand());
|
||||||
return commands;
|
return commands;
|
||||||
}
|
}
|
||||||
}
|
}
|
51
src/com/mesacarlos/webconsole/command/CpuUsageCommand.java
Normal file
51
src/com/mesacarlos/webconsole/command/CpuUsageCommand.java
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
package com.mesacarlos.webconsole.command;
|
||||||
|
|
||||||
|
import java.lang.management.ManagementFactory;
|
||||||
|
|
||||||
|
import javax.management.Attribute;
|
||||||
|
import javax.management.AttributeList;
|
||||||
|
import javax.management.MBeanServer;
|
||||||
|
import javax.management.ObjectName;
|
||||||
|
|
||||||
|
import org.java_websocket.WebSocket;
|
||||||
|
|
||||||
|
import com.mesacarlos.webconsole.json.CpuUsage;
|
||||||
|
import com.mesacarlos.webconsole.websockets.WSServer;
|
||||||
|
|
||||||
|
public class CpuUsageCommand implements WSCommand {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(WSServer wsServer, WebSocket conn, String params) {
|
||||||
|
try {
|
||||||
|
double usage = getProcessCpuLoad();
|
||||||
|
wsServer.sendToClient(conn, new CpuUsage("Usage is " + usage + "%", usage));
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check out usage for the whole system
|
||||||
|
* Got from https://stackoverflow.com/questions/18489273/how-to-get-percentage-of-cpu-usage-of-os-from-java
|
||||||
|
* @return CPU Usage for the whole system
|
||||||
|
* @throws Exception Something went wrong
|
||||||
|
*/
|
||||||
|
public double getProcessCpuLoad() throws Exception {
|
||||||
|
MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
|
||||||
|
ObjectName name = ObjectName.getInstance("java.lang:type=OperatingSystem");
|
||||||
|
AttributeList list = mbs.getAttributes(name, new String[] {"SystemCpuLoad"});
|
||||||
|
|
||||||
|
if (list.isEmpty())
|
||||||
|
return Double.NaN;
|
||||||
|
|
||||||
|
Attribute att = (Attribute) list.get(0);
|
||||||
|
Double value = (Double) att.getValue();
|
||||||
|
|
||||||
|
// usually takes a couple of seconds before we get real values
|
||||||
|
if (value == -1.0)
|
||||||
|
return Double.NaN;
|
||||||
|
// returns a percentage value with 1 decimal point precision
|
||||||
|
return ((int) (value * 1000) / 10.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -8,7 +8,7 @@ import org.java_websocket.WebSocket;
|
|||||||
|
|
||||||
import com.mesacarlos.webconsole.websockets.WSServer;
|
import com.mesacarlos.webconsole.websockets.WSServer;
|
||||||
|
|
||||||
public class ExecuteCmdCommand implements WSCommand {
|
public class ExecCommand implements WSCommand {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void execute(WSServer wsServer, WebSocket conn, String command) {
|
public void execute(WSServer wsServer, WebSocket conn, String command) {
|
19
src/com/mesacarlos/webconsole/command/PlayersCommand.java
Normal file
19
src/com/mesacarlos/webconsole/command/PlayersCommand.java
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
package com.mesacarlos.webconsole.command;
|
||||||
|
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.java_websocket.WebSocket;
|
||||||
|
|
||||||
|
import com.mesacarlos.webconsole.json.Players;
|
||||||
|
import com.mesacarlos.webconsole.websockets.WSServer;
|
||||||
|
|
||||||
|
public class PlayersCommand implements WSCommand{
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(WSServer wsServer, WebSocket conn, String params) {
|
||||||
|
int connectedPlayers = Bukkit.getOnlinePlayers().size();
|
||||||
|
int maxPlayers = Bukkit.getMaxPlayers();
|
||||||
|
|
||||||
|
wsServer.sendToClient(conn, new Players("Currently " + connectedPlayers + " connected players for a maximum of " + maxPlayers, connectedPlayers, maxPlayers));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
21
src/com/mesacarlos/webconsole/command/RamUsageCommand.java
Normal file
21
src/com/mesacarlos/webconsole/command/RamUsageCommand.java
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
package com.mesacarlos.webconsole.command;
|
||||||
|
|
||||||
|
import org.java_websocket.WebSocket;
|
||||||
|
|
||||||
|
import com.mesacarlos.webconsole.json.RamUsage;
|
||||||
|
import com.mesacarlos.webconsole.websockets.WSServer;
|
||||||
|
|
||||||
|
public class RamUsageCommand implements WSCommand {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(WSServer wsServer, WebSocket conn, String params) {
|
||||||
|
Runtime r = Runtime.getRuntime();
|
||||||
|
|
||||||
|
int free = (int) r.freeMemory()/1024/1024;
|
||||||
|
int max = (int) r.maxMemory()/1024/1024;
|
||||||
|
int used = max - free;
|
||||||
|
|
||||||
|
wsServer.sendToClient(conn, new RamUsage(free + "free, " + used + " used," + max + " maximum memmory", free, used, max));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -19,11 +19,6 @@ public class ConsoleOutput implements JSONOutput{
|
|||||||
return message;
|
return message;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getRespondsTo() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toJSON() {
|
public String toJSON() {
|
||||||
JsonObject object = new JsonObject();
|
JsonObject object = new JsonObject();
|
||||||
|
42
src/com/mesacarlos/webconsole/json/CpuUsage.java
Normal file
42
src/com/mesacarlos/webconsole/json/CpuUsage.java
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
package com.mesacarlos.webconsole.json;
|
||||||
|
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
|
||||||
|
public class CpuUsage implements JSONOutput{
|
||||||
|
private String message;
|
||||||
|
private double usage;
|
||||||
|
|
||||||
|
public CpuUsage(String message, double usage) {
|
||||||
|
this.message = message;
|
||||||
|
this.usage = usage;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getStatusCode() {
|
||||||
|
return 1001;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getMessage() {
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets system CPU Usage
|
||||||
|
* @return Global CPU Usage
|
||||||
|
*/
|
||||||
|
public double getUsage() {
|
||||||
|
return usage;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toJSON() {
|
||||||
|
JsonObject object = new JsonObject();
|
||||||
|
object.addProperty("status", getStatusCode());
|
||||||
|
object.addProperty("statusDescription", "Cpu Usage");
|
||||||
|
object.addProperty("usage", getUsage());
|
||||||
|
object.addProperty("message", getMessage());
|
||||||
|
return object.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -7,13 +7,6 @@ public interface JSONOutput {
|
|||||||
*/
|
*/
|
||||||
int getStatusCode();
|
int getStatusCode();
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the command sended by client who created this response.
|
|
||||||
* In case of a server-generated response (like ConsoleOutput), this will be null
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
String getRespondsTo();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Explanatory message of this response
|
* Explanatory message of this response
|
||||||
* @return Explanatory message of this response
|
* @return Explanatory message of this response
|
||||||
|
@ -19,11 +19,6 @@ public class LoginRequired implements JSONOutput{
|
|||||||
return message;
|
return message;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getRespondsTo() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toJSON() {
|
public String toJSON() {
|
||||||
JsonObject object = new JsonObject();
|
JsonObject object = new JsonObject();
|
||||||
|
45
src/com/mesacarlos/webconsole/json/Players.java
Normal file
45
src/com/mesacarlos/webconsole/json/Players.java
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
package com.mesacarlos.webconsole.json;
|
||||||
|
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
|
||||||
|
public class Players implements JSONOutput{
|
||||||
|
private String message;
|
||||||
|
private int connectedPlayers;
|
||||||
|
private int maxPlayers;
|
||||||
|
|
||||||
|
public Players(String message, int connectedPlayers, int maxPlayers) {
|
||||||
|
this.message = message;
|
||||||
|
this.connectedPlayers = connectedPlayers;
|
||||||
|
this.maxPlayers = maxPlayers;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getStatusCode() {
|
||||||
|
return 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getMessage() {
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getConnectedPlayers() {
|
||||||
|
return connectedPlayers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMaxPlayers() {
|
||||||
|
return maxPlayers;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toJSON() {
|
||||||
|
JsonObject object = new JsonObject();
|
||||||
|
object.addProperty("status", getStatusCode());
|
||||||
|
object.addProperty("statusDescription", "Players");
|
||||||
|
object.addProperty("connectedPlayers", getConnectedPlayers());
|
||||||
|
object.addProperty("maxPlayers", getMaxPlayers());
|
||||||
|
object.addProperty("message", getMessage());
|
||||||
|
return object.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -25,8 +25,11 @@ public class Processed implements JSONOutput{
|
|||||||
return message;
|
return message;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
/**
|
||||||
public String getRespondsTo() {
|
* The command that originated this response
|
||||||
|
* @return WebSockets full command and parameters
|
||||||
|
*/
|
||||||
|
private String getRespondsTo() {
|
||||||
return respondsTo;
|
return respondsTo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
64
src/com/mesacarlos/webconsole/json/RamUsage.java
Normal file
64
src/com/mesacarlos/webconsole/json/RamUsage.java
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
package com.mesacarlos.webconsole.json;
|
||||||
|
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
|
||||||
|
public class RamUsage implements JSONOutput {
|
||||||
|
private String message;
|
||||||
|
private int free;
|
||||||
|
private int used;
|
||||||
|
private int max;
|
||||||
|
|
||||||
|
public RamUsage(String message, int free, int used, int max) {
|
||||||
|
this.message = message;
|
||||||
|
this.free = free;
|
||||||
|
this.used = used;
|
||||||
|
this.max = max;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getStatusCode() {
|
||||||
|
return 1002;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getMessage() {
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Free amount of RAM, in MB
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public int getFree() {
|
||||||
|
return free;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used amount of RAM, in MB
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public int getUsed() {
|
||||||
|
return used;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Max amount of RAM, in MB
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public int getMax() {
|
||||||
|
return max;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toJSON() {
|
||||||
|
JsonObject object = new JsonObject();
|
||||||
|
object.addProperty("status", getStatusCode());
|
||||||
|
object.addProperty("statusDescription", "RAM Usage");
|
||||||
|
object.addProperty("free", getFree());
|
||||||
|
object.addProperty("total", getUsed());
|
||||||
|
object.addProperty("max", getMax());
|
||||||
|
object.addProperty("message", getMessage());
|
||||||
|
return object.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -2,11 +2,11 @@ package com.mesacarlos.webconsole.json;
|
|||||||
|
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
|
|
||||||
public class UnknownWSCmd implements JSONOutput{
|
public class UnknownCommand implements JSONOutput{
|
||||||
private String message;
|
private String message;
|
||||||
private String respondsTo;
|
private String respondsTo;
|
||||||
|
|
||||||
public UnknownWSCmd(String message, String respondsTo) {
|
public UnknownCommand(String message, String respondsTo) {
|
||||||
this.message = message;
|
this.message = message;
|
||||||
this.respondsTo = respondsTo;
|
this.respondsTo = respondsTo;
|
||||||
}
|
}
|
||||||
@ -21,7 +21,10 @@ public class UnknownWSCmd implements JSONOutput{
|
|||||||
return message;
|
return message;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
/**
|
||||||
|
* The command that originated this response
|
||||||
|
* @return WebSockets full command and parameters
|
||||||
|
*/
|
||||||
public String getRespondsTo() {
|
public String getRespondsTo() {
|
||||||
return respondsTo;
|
return respondsTo;
|
||||||
}
|
}
|
@ -16,7 +16,7 @@ import com.mesacarlos.webconsole.json.ConsoleOutput;
|
|||||||
import com.mesacarlos.webconsole.json.JSONOutput;
|
import com.mesacarlos.webconsole.json.JSONOutput;
|
||||||
import com.mesacarlos.webconsole.json.LoginRequired;
|
import com.mesacarlos.webconsole.json.LoginRequired;
|
||||||
import com.mesacarlos.webconsole.json.Processed;
|
import com.mesacarlos.webconsole.json.Processed;
|
||||||
import com.mesacarlos.webconsole.json.UnknownWSCmd;
|
import com.mesacarlos.webconsole.json.UnknownCommand;
|
||||||
import com.mesacarlos.webconsole.util.LoginManager;
|
import com.mesacarlos.webconsole.util.LoginManager;
|
||||||
|
|
||||||
public class WSServer extends WebSocketServer {
|
public class WSServer extends WebSocketServer {
|
||||||
@ -50,7 +50,7 @@ public class WSServer extends WebSocketServer {
|
|||||||
|
|
||||||
if (cmd == null) {
|
if (cmd == null) {
|
||||||
//Command does not exist
|
//Command does not exist
|
||||||
sendToClient(conn, new UnknownWSCmd("Unknown command", message));
|
sendToClient(conn, new UnknownCommand("Unknown command", message));
|
||||||
Bukkit.getLogger().info(
|
Bukkit.getLogger().info(
|
||||||
"[WebConsole] Signal '" + message + "' was not processed since is not valid. Is your plugin/web interface up to date?");
|
"[WebConsole] Signal '" + message + "' was not processed since is not valid. Is your plugin/web interface up to date?");
|
||||||
} else if (!LoginManager.getInstance().isLoggedIn(conn.getRemoteSocketAddress())
|
} else if (!LoginManager.getInstance().isLoggedIn(conn.getRemoteSocketAddress())
|
||||||
|
Reference in New Issue
Block a user