diff --git a/pom.xml b/pom.xml index 1e812fb..e2c5be2 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ dev.koifysh archipelago-client - 0.1.13 + 0.1.18 Archipelago Java Library Library to connect to an Archipelago Server @@ -48,7 +48,7 @@ com.google.code.gson gson - 2.8.9 + 2.11.0 org.apache.httpcomponents.client5 @@ -60,11 +60,6 @@ httpcore5 5.2 - - org.slf4j - slf4j-nop - 1.7.30 - diff --git a/src/main/java/dev/koifysh/archipelago/Client.java b/src/main/java/dev/koifysh/archipelago/Client.java index 312fe58..d093885 100644 --- a/src/main/java/dev/koifysh/archipelago/Client.java +++ b/src/main/java/dev/koifysh/archipelago/Client.java @@ -338,19 +338,6 @@ public void scoutLocations(ArrayList locationIDs) { webSocket.scoutLocation(locationIDs); } - /** - * Called when the server wishes to display a message to the user. - *
- * Deprecated use {@link dev.koifysh.archipelago.events.PrintJSONEvent} instead - * @see dev.koifysh.archipelago.events.PrintJSONEvent - * @param apPrint list of message segments. - * @param type the type of the received message. - * @param player int id of the sending player. - * @param item the network item that is involved with the message. - */ - @Deprecated - public abstract void onPrintJson(APPrint apPrint, String type, int player, NetworkItem item); - public abstract void onError(Exception ex); public abstract void onClose(String Reason, int attemptingReconnect); diff --git a/src/main/java/dev/koifysh/archipelago/EventManager.java b/src/main/java/dev/koifysh/archipelago/EventManager.java index 3f6d1da..6fbd71c 100644 --- a/src/main/java/dev/koifysh/archipelago/EventManager.java +++ b/src/main/java/dev/koifysh/archipelago/EventManager.java @@ -5,6 +5,7 @@ import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.lang.reflect.Modifier; import java.util.HashMap; import java.util.Map; @@ -24,17 +25,39 @@ public class EventManager { */ public void registerListener(Object listener) { for (Method method : listener.getClass().getMethods()) { - if (!method.isAnnotationPresent(ArchipelagoEventListener.class)) - continue; - if (method.getParameterTypes().length != 1) - continue; - if (!Event.class.isAssignableFrom(method.getParameterTypes()[0])) - continue; + if (isEventListenerMethod(listener, method)) continue; registeredListeners.put(method, listener); } } + /** + * Use to unregister for Events that come from the Archipelago server. + * supplied Object must have at least 1 method annotated with {@link ArchipelagoEventListener} + * and have 1 parameter that extends {@link Event} + * @param listener the object containing a listener method. + */ + public void unRegisterListener(Object listener) { + for (Method method : listener.getClass().getMethods()) { + if (isEventListenerMethod(listener, method)) continue; + + registeredListeners.remove(method, listener); + } + } + + private boolean isEventListenerMethod(Object listener, Method method) { + if(listener instanceof Class) + if (!Modifier.isStatic(method.getModifiers())) + return true; + if (!method.isAnnotationPresent(ArchipelagoEventListener.class)) + return true; + if (method.getParameterTypes().length != 1) + return true; + if (!Event.class.isAssignableFrom(method.getParameterTypes()[0])) + return true; + return false; + } + public void callEvent(final Event event) { for (Map.Entry methodObjectEntry : registeredListeners.entrySet()) { Method method = methodObjectEntry.getKey(); diff --git a/src/main/java/dev/koifysh/archipelago/ItemManager.java b/src/main/java/dev/koifysh/archipelago/ItemManager.java index 2a7276e..9766d00 100644 --- a/src/main/java/dev/koifysh/archipelago/ItemManager.java +++ b/src/main/java/dev/koifysh/archipelago/ItemManager.java @@ -34,7 +34,7 @@ public void receiveItems(ArrayList ids, int index) { item.itemName = dp.getItem(item.itemID, client.getGame()); item.locationName = dp.getLocation(item.locationID, client.getSlotInfo().get(item.playerID).game); item.playerName = client.getRoomInfo().getPlayer(myTeam,item.playerID).alias; - client.getEventManager().callEvent(new ReceiveItemEvent(item, index)); + client.getEventManager().callEvent(new ReceiveItemEvent(item, i+1)); } this.index = receivedItems.size(); diff --git a/src/main/java/dev/koifysh/archipelago/Print/APPrint.java b/src/main/java/dev/koifysh/archipelago/Print/APPrint.java index 822a508..9462b11 100644 --- a/src/main/java/dev/koifysh/archipelago/Print/APPrint.java +++ b/src/main/java/dev/koifysh/archipelago/Print/APPrint.java @@ -9,7 +9,7 @@ public class APPrint { public APPrintPart[] parts; @SerializedName("type") - public String type; + public APPrintJsonType type; @SerializedName("receiving") public int receiving; diff --git a/src/main/java/dev/koifysh/archipelago/Print/APPrintJsonType.java b/src/main/java/dev/koifysh/archipelago/Print/APPrintJsonType.java new file mode 100644 index 0000000..ce1458c --- /dev/null +++ b/src/main/java/dev/koifysh/archipelago/Print/APPrintJsonType.java @@ -0,0 +1,102 @@ +package dev.koifysh.archipelago.Print; + +import com.google.gson.annotations.SerializedName; + +public enum APPrintJsonType { + + /** + * A player received an item. + */ + @SerializedName("ItemSend") + ItemSend, + + /** + * A player used the `!getitem` command. + */ + @SerializedName("ItemCheat") + ItemCheat, + + /** + * A player hinted. + */ + @SerializedName("Hint") + Hint, + + /** + * A player connected. + */ + @SerializedName("Join") + Join, + + /** + * A player disconnected. + */ + @SerializedName("Part") + Part, + + /** + * A player sent a chat message. + */ + @SerializedName("Chat") + Chat, + + /** + * The server broadcast a message. + */ + @SerializedName("ServerChat") + ServerChat, + + /** + * The client has triggered a tutorial message, such as when first connecting. + */ + @SerializedName("entrance_name") + Tutorial, + + /** + * A player changed their tags. + */ + @SerializedName("TagsChanged") + TagsChanged, + + /** + * Someone (usually the client) entered an ! command. + */ + @SerializedName("CommandResult") + CommandResult, + + /** + * The client entered an !admin command. + */ + @SerializedName("AdminCommandResult") + AdminCommandResult, + + /** + * A player reached their goal. + */ + @SerializedName("Goal") + Goal, + + /** + * A player released the remaining items in their world. + */ + @SerializedName("Release") + Release, + + /** + * A player collected the remaining items for their world. + */ + @SerializedName("Collect") + Collect, + + /** + * The current server countdown has progressed. + */ + @SerializedName("Countdown") + Countdown, + + /** + * The Message type was not set, or is invalid. + */ + Unknown + +} diff --git a/src/main/java/dev/koifysh/archipelago/WebSocket.java b/src/main/java/dev/koifysh/archipelago/WebSocket.java index cdd814b..a66c191 100644 --- a/src/main/java/dev/koifysh/archipelago/WebSocket.java +++ b/src/main/java/dev/koifysh/archipelago/WebSocket.java @@ -5,6 +5,8 @@ import com.google.gson.JsonElement; import com.google.gson.JsonParser; import dev.koifysh.archipelago.Print.APPrint; +import dev.koifysh.archipelago.Print.APPrintJsonType; +import dev.koifysh.archipelago.Print.APPrintPart; import dev.koifysh.archipelago.Print.APPrintType; import dev.koifysh.archipelago.helper.DeathLink; import dev.koifysh.archipelago.network.APPacket; @@ -19,6 +21,7 @@ import dev.koifysh.archipelago.events.*; import dev.koifysh.archipelago.network.server.*; +import dev.koifysh.archipelago.parts.NetworkSlot; import org.apache.hc.core5.net.URIBuilder; import org.java_websocket.client.WebSocketClient; import org.java_websocket.handshake.ServerHandshake; @@ -66,8 +69,8 @@ public void onMessage(String message) { JsonArray cmdList = element.getAsJsonArray(); - for (int i = 0; cmdList.size() > i; ++i) { - JsonElement packet = cmdList.get(i); + for (int commandNumber = 0; cmdList.size() > commandNumber; ++commandNumber) { + JsonElement packet = cmdList.get(commandNumber); //parse the packet first to see what command has been sent. APPacket cmd = gson.fromJson(packet, APPacket.class); @@ -102,10 +105,19 @@ public void onMessage(String message) { client.setTeam(connectedPacket.team); client.setSlot(connectedPacket.slot); + connectedPacket.slotInfo.put(0, new NetworkSlot("Archipelago", "Archipelago", NetworkSlot.flags.SPECTATOR)); client.setSlotInfo(connectedPacket.slotInfo); client.getRoomInfo().networkPlayers.addAll(connectedPacket.players); - client.getRoomInfo().networkPlayers.add(new NetworkPlayer(connectedPacket.team, 0, "Archipelago")); + int teams = 1; + OptionalInt teamsOptional = client.getRoomInfo().networkPlayers.stream().mapToInt(player -> player.team).max(); + if (teamsOptional.isPresent()) { + teams = teamsOptional.getAsInt() + 1; + } + for (int i = 0; i < teams; i++) { + client.getRoomInfo().networkPlayers.add( new NetworkPlayer(i, 0, "Archipelago")); + } + client.setAlias(client.getRoomInfo().getPlayer(connectedPacket.team, connectedPacket.slot).alias); JsonElement slotData = packet.getAsJsonObject().get("slot_data"); @@ -129,7 +141,7 @@ public void onMessage(String message) { } break; case ConnectionRefused: - ConnectionRefusedPacket error = gson.fromJson(cmdList.get(i), ConnectionRefusedPacket.class); + ConnectionRefusedPacket error = gson.fromJson(cmdList.get(commandNumber), ConnectionRefusedPacket.class); client.getEventManager().callEvent(new ConnectionResultEvent(error.errors[0])); break; case DataPackage: @@ -142,27 +154,28 @@ public void onMessage(String message) { case PrintJSON: LOGGER.finest("PrintJSON packet"); APPrint print = gson.fromJson(packet, APPrint.class); + if (print.type == null) print.type = APPrintJsonType.Unknown; //filter though all player IDs and replace id with alias. - for (int p = 0; print.parts.length > p; ++p) { - if (print.parts[p].type == APPrintType.playerID) { - int playerID = Integer.parseInt((print.parts[p].text)); - NetworkPlayer player = client.getRoomInfo().getPlayer(client.getTeam(), playerID); + for (int partNumber = 0; print.parts.length > partNumber; ++partNumber) { + APPrintPart part = print.parts[partNumber]; - print.parts[p].text = player.alias; - } else if (print.parts[p].type == APPrintType.itemID) { - long itemID = Long.parseLong(print.parts[p].text); - print.parts[p].text = client.getDataPackage().getItem(itemID, client.getSlotInfo().get(print.parts[i].player).game); - } else if (print.parts[p].type == APPrintType.locationID) { - long locationID = Long.parseLong(print.parts[p].text); - print.parts[p].text = client.getDataPackage().getLocation(locationID, client.getSlotInfo().get(print.parts[i].player).game); + if (part.type == APPrintType.playerID) { + int playerID = Integer.parseInt(part.text); + NetworkPlayer player = client.getRoomInfo().getPlayer(client.getTeam(), playerID); + part.text = player.alias; + } + else if (part.type == APPrintType.itemID) { + long itemID = Long.parseLong(part.text); + part.text = client.getDataPackage().getItem(itemID, client.getSlotInfo().get(part.player).game); + } + else if (part.type == APPrintType.locationID) { + long locationID = Long.parseLong(part.text); + part.text = client.getDataPackage().getLocation(locationID, client.getSlotInfo().get(part.player).game); } } client.getEventManager().callEvent(new PrintJSONEvent(print, print.type, print.receiving, print.item)); - //todo: remove next version - client.onPrintJson(print, print.type, print.receiving, print.item); - break; case RoomUpdate: RoomUpdatePacket updatePacket = gson.fromJson(packet, RoomUpdatePacket.class); @@ -205,15 +218,14 @@ public void onMessage(String message) { } } } catch (Exception e) { - LOGGER.warning("Error proccessing incoming packet: "); - e.printStackTrace(); + LOGGER.warning("Error proccessing incoming packet: " + e.getMessage()); + //e.printStackTrace(); } } private void updateRoom(RoomUpdatePacket updateRoomPacket) { if (!updateRoomPacket.networkPlayers.isEmpty()) { client.getRoomInfo().networkPlayers = updateRoomPacket.networkPlayers; - client.getRoomInfo().networkPlayers.add(new NetworkPlayer(client.getTeam(), 0, "Archipelago")); } client.setHintPoints(updateRoomPacket.hintPoints); @@ -316,8 +328,8 @@ public void onError(Exception ex) { return; } client.onError(ex); - LOGGER.log(Level.WARNING, "Error in websocket connection"); - ex.printStackTrace(); + LOGGER.log(Level.WARNING, "Error in websocket connection: " + ex.getMessage()); + //ex.printStackTrace(); } public void connect(boolean allowDowngrade) { diff --git a/src/main/java/dev/koifysh/archipelago/events/PrintJSONEvent.java b/src/main/java/dev/koifysh/archipelago/events/PrintJSONEvent.java index 01f639d..3ecf040 100644 --- a/src/main/java/dev/koifysh/archipelago/events/PrintJSONEvent.java +++ b/src/main/java/dev/koifysh/archipelago/events/PrintJSONEvent.java @@ -1,6 +1,7 @@ package dev.koifysh.archipelago.events; import dev.koifysh.archipelago.Print.APPrint; +import dev.koifysh.archipelago.Print.APPrintJsonType; import dev.koifysh.archipelago.parts.NetworkItem; /** @@ -9,7 +10,7 @@ public class PrintJSONEvent implements Event { public APPrint apPrint; - public String type; + public APPrintJsonType type; public int player; public NetworkItem item; @@ -19,7 +20,7 @@ public class PrintJSONEvent implements Event { * @param player int id of the sending player. * @param item the network item that is involved with the message. */ - public PrintJSONEvent(APPrint apPrint, String type, int player, NetworkItem item) { + public PrintJSONEvent(APPrint apPrint, APPrintJsonType type, int player, NetworkItem item) { this.apPrint = apPrint; this.type = type; this.player = player; diff --git a/src/main/java/dev/koifysh/archipelago/parts/NetworkSlot.java b/src/main/java/dev/koifysh/archipelago/parts/NetworkSlot.java index bd494f4..813d210 100644 --- a/src/main/java/dev/koifysh/archipelago/parts/NetworkSlot.java +++ b/src/main/java/dev/koifysh/archipelago/parts/NetworkSlot.java @@ -38,4 +38,10 @@ public static class flags { public final static int GROUP = 0b100; } + + public NetworkSlot(String name, String game, int type) { + this.name = name; + this.game = game; + this.type = type; + } }