diff --git a/src/main/java/dev/elijahr/CollabVM4j/CollabVMClient.java b/src/main/java/dev/elijahr/CollabVM4j/CollabVMClient.java index d94d40e..fe9c2f0 100644 --- a/src/main/java/dev/elijahr/CollabVM4j/CollabVMClient.java +++ b/src/main/java/dev/elijahr/CollabVM4j/CollabVMClient.java @@ -31,6 +31,8 @@ public class CollabVMClient { private BufferedImage _framebuffer; private TurnQueue _currentTurnQueue; private TurnStatus _turnStatus; + private ResetVote _currentVote; + private boolean _usesAccountAuth; // Futures private CompletableFuture _loginFuture; @@ -47,10 +49,12 @@ public class CollabVMClient { _debug = debug; _connected = false; _connectedToNode = false; + _usesAccountAuth = false; _username = null; _rank = Rank.Unregistered; _permissions = Permissions.None(); _turnStatus = TurnStatus.None; + _currentVote = new ResetVote(0, 0, ResetVoteStatus.None, 0); _currentTurnQueue = new TurnQueue(null, null, new User[0]); _node = null; _url = url; @@ -62,14 +66,95 @@ public class CollabVMClient { _socket.addHeader("Origin", "https://computernewb.com"); } - // Public methods + + /** + * Connects to the CollabVM server + */ public void connect() { _socket.connect(); } + /** + * Encode and send a Guacamole instruction to the server + * @param args The arguments to send to the server + */ + public void sendGuac(String... args) { + if (_debug) System.out.println("Sending message: " + Guacutils.Encode(args)); + _socket.send(Guacutils.Encode(args)); + } + + /** + * Log in to an account using a token + * @param token The token to use to log in + * @return A CompletableFuture that will complete when the login attempt is finished + */ + public CompletableFuture loginAccount(String token) { + this._loginFuture = new CompletableFuture<>(); + this.sendGuac("login", token); + return this._loginFuture; + } + + + // Getters and setters + + /** + * If not connected, sets the username to request when connecting. + * If connected, sends a rename instruction to the server + * @param username The username to rename to + */ + public void setUsername(String username) { + if (_connected) + this.sendGuac("rename", username); + // Don't set the username if we're connected until the server confirms the rename + else + this._username = username; + } + + /** + * @return The current username of the client + */ + public String getUsername() { return this._username; } + + /** + * Sets the node to connect to during the handshake + * @param node The node to connect to + * @throws IllegalStateException if the client is already connected to a node + */ + public void setNode(String node) { + if (this._node != null) throw new IllegalStateException("Cannot switch nodes after connecting. Disconnect the client first."); + if (_connected) + this.sendGuac("connect", node); + this._node = node; + } + + /** + * @return The current node the client is connected to + */ + public String getNode() { return this._node; } + + /** + * @return A list of users currently in the VM + */ + public User[] getUsers() { return this._users.toArray(new User[0]); } + + /** + * @return A copy of the entire VM screen + */ + public BufferedImage getFramebuffer() { + BufferedImage img = new BufferedImage(_framebuffer.getWidth(), _framebuffer.getHeight(), BufferedImage.TYPE_INT_ARGB); + img.getGraphics().drawImage(_framebuffer, 0, 0, null); + return img; + } + + /** + * Sets the event handler for the client + * @param handler The event handler to set + */ + public void setEventHandler(CollabVMEventHandler handler) { this._eventHandler = handler; } + // WebSocket event handlers - public void onWsOpen(ServerHandshake serverHandshake) { + void onWsOpen(ServerHandshake serverHandshake) { _connected = true; if (_username != null) this.sendGuac("rename", this._username); @@ -80,7 +165,7 @@ public class CollabVMClient { _eventHandler.OnOpen(); } - public void onWsMessage(String msg) { + void onWsMessage(String msg) { String[] msgArr; try { msgArr = Guacutils.Decode(msg); @@ -228,47 +313,50 @@ public class CollabVMClient { this._loginFuture.complete(new AccountLoginResult(success, success ? null : msgArr[2])); break; } + case "auth": { + this._usesAccountAuth = true; + _eventHandler.OnUsesAccountAuth(msgArr[1]); + } + case "vote": { + switch (msgArr[1]) { + case "0": + if (msgArr.length < 4) return; + // Intentional fallthrough + case "1": + this._currentVote = new ResetVote( + Integer.parseInt(msgArr[3]), + Integer.parseInt(msgArr[4]), msgArr[1].equals("0") ? ResetVoteStatus.Started : ResetVoteStatus.Update, + Integer.parseInt(msgArr[2]) + ); + this._eventHandler.OnVoteUpdate(this._currentVote); + break; + case "2": + this._currentVote = new ResetVote(0, 0, ResetVoteStatus.None, 0); + this._eventHandler.OnVoteEnded(); + break; + case "3": + this._eventHandler.OnVoteCooldown(Integer.parseInt(msgArr[2])); + break; + } + break; + } + case "admin": { + switch (msgArr[1]) { + + } + break; + } } } - - public CompletableFuture loginAccount(String token) { - this._loginFuture = new CompletableFuture<>(); - this.sendGuac("login", token); - return this._loginFuture; - } - public void onWsClose(int code, String reason, boolean remote) { + void onWsClose(int code, String reason, boolean remote) { _connectedToNode = false; _connected = false; + _usesAccountAuth = false; _eventHandler.OnConnectionClosed(); } - public void onWsError(Exception ex) { + void onWsError(Exception ex) { _connected = false; + _connectedToNode = false; + _usesAccountAuth = false; } - public void sendGuac(String... args) { - if (_debug) System.out.println("Sending message: " + Guacutils.Encode(args)); - _socket.send(Guacutils.Encode(args)); - } - // Getters and setters - public void setUsername(String username) { - if (_connected) - this.sendGuac("rename", username); - // Don't set the username if we're connected until the server confirms the rename - else - this._username = username; - } - public String getUsername() { return this._username; } - public void setNode(String node) { - if (this._node != null) throw new RuntimeException("Cannot switch nodes after connecting. Disconnect the client first."); - if (_connected) - this.sendGuac("connect", node); - this._node = node; - } - public String getNode() { return this._node; } - public User[] getUsers() { return this._users.toArray(new User[0]); } - public BufferedImage getFramebuffer() { - BufferedImage img = new BufferedImage(_framebuffer.getWidth(), _framebuffer.getHeight(), BufferedImage.TYPE_INT_ARGB); - img.getGraphics().drawImage(_framebuffer, 0, 0, null); - return img; - } - public void setEventHandler(CollabVMEventHandler handler) { this._eventHandler = handler; } } diff --git a/src/main/java/dev/elijahr/CollabVM4j/CollabVMEventHandler.java b/src/main/java/dev/elijahr/CollabVM4j/CollabVMEventHandler.java index 1514624..c601968 100644 --- a/src/main/java/dev/elijahr/CollabVM4j/CollabVMEventHandler.java +++ b/src/main/java/dev/elijahr/CollabVM4j/CollabVMEventHandler.java @@ -14,9 +14,10 @@ public interface CollabVMEventHandler { default void OnUserRenamed(String oldName, String newName, User user) {} default void OnUserJoined(User user) {} default void OnUserLeft(User user) {} - default void OnVoteUpdate() {} + default void OnVoteUpdate(ResetVote vote) {} default void OnVoteEnded() {} default void OnVoteCooldown(int cooldown) {} default void OnTurnUpdate(TurnQueue queue) {} default void OnConnectionClosed() {} + default void OnUsesAccountAuth(String authServerURL) {} } diff --git a/src/main/java/dev/elijahr/CollabVM4j/CollabVMWebSocket.java b/src/main/java/dev/elijahr/CollabVM4j/CollabVMWebSocket.java index 791690d..e5b864c 100644 --- a/src/main/java/dev/elijahr/CollabVM4j/CollabVMWebSocket.java +++ b/src/main/java/dev/elijahr/CollabVM4j/CollabVMWebSocket.java @@ -8,6 +8,9 @@ import org.java_websocket.protocols.Protocol; import java.net.URI; import java.util.Collections; +/** + * Wrapper class to avoid having CollabVMClient directly extend WebSocketClient + */ class CollabVMWebSocket extends WebSocketClient { private CollabVMClient _owner; diff --git a/src/main/java/dev/elijahr/CollabVM4j/ResetVote.java b/src/main/java/dev/elijahr/CollabVM4j/ResetVote.java new file mode 100644 index 0000000..e117a1b --- /dev/null +++ b/src/main/java/dev/elijahr/CollabVM4j/ResetVote.java @@ -0,0 +1,14 @@ +package dev.elijahr.CollabVM4j; + +public class ResetVote { + public Integer Yes; + public Integer No; + public ResetVoteStatus Status; + public Integer TimeToVoteEnd; + public ResetVote(Integer yes, Integer no, ResetVoteStatus status, Integer timeToVoteEnd) { + Yes = yes; + No = no; + Status = status; + TimeToVoteEnd = timeToVoteEnd; + } +} diff --git a/src/main/java/dev/elijahr/CollabVM4j/ResetVoteStatus.java b/src/main/java/dev/elijahr/CollabVM4j/ResetVoteStatus.java new file mode 100644 index 0000000..baff854 --- /dev/null +++ b/src/main/java/dev/elijahr/CollabVM4j/ResetVoteStatus.java @@ -0,0 +1,7 @@ +package dev.elijahr.CollabVM4j; + +public enum ResetVoteStatus { + Started, + Update, + None +}