From dc1c1587ad9787a61bc0b336524ea164a43127f3 Mon Sep 17 00:00:00 2001 From: iHDeveloper <20463031+iHDeveloper@users.noreply.github.com> Date: Thu, 7 Jan 2021 03:53:01 +0300 Subject: [PATCH] feat(discord): Implement party size - fix: can't hide start timestamp --- .../discordrpc/DiscordRPCBuffer.java | 46 ++++++++++++++ .../discordrpc/DiscordRPCSubSystem.java | 19 ++++++ .../discordrpc/DiscordRPCSystem.java | 60 ++++++++++++++++--- .../discordrpc/DiscordRPCThread.java | 25 ++++++-- 4 files changed, 137 insertions(+), 13 deletions(-) diff --git a/subsystems/DiscordRPC/src/main/java/org/terasology/engine/subsystem/discordrpc/DiscordRPCBuffer.java b/subsystems/DiscordRPC/src/main/java/org/terasology/engine/subsystem/discordrpc/DiscordRPCBuffer.java index e08ddb5056b..9e5428cba0c 100644 --- a/subsystems/DiscordRPC/src/main/java/org/terasology/engine/subsystem/discordrpc/DiscordRPCBuffer.java +++ b/subsystems/DiscordRPC/src/main/java/org/terasology/engine/subsystem/discordrpc/DiscordRPCBuffer.java @@ -14,8 +14,14 @@ public final class DiscordRPCBuffer { private String details; private String state; private OffsetDateTime startTimestamp; + private int partySize; + private int partyMax; private boolean changed; + public DiscordRPCBuffer() { + reset(); + } + /** * Resets the buffer data */ @@ -24,6 +30,8 @@ public synchronized void reset() { this.state = null; this.startTimestamp = null; this.changed = true; + this.partySize = -1; + this.partyMax = -1; } /** @@ -82,6 +90,44 @@ public synchronized OffsetDateTime getStartTimestamp() { return startTimestamp; } + /** + * Sets the current party size + * + * @param partySize The current party size + */ + public synchronized void setPartySize(int partySize) { + this.partySize = partySize; + this.changed = true; + } + + /** + * Returns the current party size + * + * @return The party size + */ + public synchronized int getPartySize() { + return partySize; + } + + /** + * Sets the maximum number of the players in the party + * + * @param partyMax The number of the players + */ + public synchronized void setPartyMax(int partyMax) { + this.partyMax = partyMax; + this.changed = true; + } + + /** + * Returns the maximum number of players in the party + * + * @return The maximum number of players in the party + */ + public synchronized int getPartyMax() { + return partyMax; + } + /** * Check if the buffer has changed * diff --git a/subsystems/DiscordRPC/src/main/java/org/terasology/engine/subsystem/discordrpc/DiscordRPCSubSystem.java b/subsystems/DiscordRPC/src/main/java/org/terasology/engine/subsystem/discordrpc/DiscordRPCSubSystem.java index 8c725fb0ffa..d9b13e82427 100644 --- a/subsystems/DiscordRPC/src/main/java/org/terasology/engine/subsystem/discordrpc/DiscordRPCSubSystem.java +++ b/subsystems/DiscordRPC/src/main/java/org/terasology/engine/subsystem/discordrpc/DiscordRPCSubSystem.java @@ -141,6 +141,25 @@ public static void setStartTimestamp(OffsetDateTime timestamp) { getInstance().thread.getBuffer().setStartTimestamp(timestamp); } + /** + * Sets the party information on the buffer + * + * @param size The number of the players in the party + * @param max The maximum number of the players in the party + */ + public static void setPartyInfo(int size, int max) { + DiscordRPCBuffer buffer = getInstance().thread.getBuffer(); + buffer.setPartySize(size); + buffer.setPartyMax(max); + } + + /** + * Resets the party information on the buffer + */ + public static void resetPartyInfo() { + setPartyInfo(-1, -1); + } + private static DiscordRPCSubSystem getInstance() { return instance; } diff --git a/subsystems/DiscordRPC/src/main/java/org/terasology/engine/subsystem/discordrpc/DiscordRPCSystem.java b/subsystems/DiscordRPC/src/main/java/org/terasology/engine/subsystem/discordrpc/DiscordRPCSystem.java index 946ba0721ec..ccd210c80ac 100644 --- a/subsystems/DiscordRPC/src/main/java/org/terasology/engine/subsystem/discordrpc/DiscordRPCSystem.java +++ b/subsystems/DiscordRPC/src/main/java/org/terasology/engine/subsystem/discordrpc/DiscordRPCSystem.java @@ -2,6 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 package org.terasology.engine.subsystem.discordrpc; +import org.terasology.entitySystem.entity.EntityManager; import org.terasology.entitySystem.entity.EntityRef; import org.terasology.entitySystem.event.ReceiveEvent; import org.terasology.entitySystem.systems.BaseComponentSystem; @@ -9,7 +10,11 @@ import org.terasology.entitySystem.systems.RegisterSystem; import org.terasology.game.Game; import org.terasology.logic.afk.AfkEvent; +import org.terasology.logic.delay.DelayManager; +import org.terasology.logic.delay.PeriodicActionTriggeredEvent; import org.terasology.logic.players.LocalPlayer; +import org.terasology.logic.players.event.LocalPlayerInitializedEvent; +import org.terasology.network.ClientComponent; import org.terasology.network.NetworkMode; import org.terasology.network.NetworkSystem; import org.terasology.registry.In; @@ -24,6 +29,8 @@ */ @RegisterSystem(RegisterMode.CLIENT) public final class DiscordRPCSystem extends BaseComponentSystem { + private static final String UPDATE_PARTY_SIZE_ID = "discord-rpc:party-size"; + private static final long UPDATE_PARTY_SIZE_PERIOD = 25L * 1000L; @In private Game game; @@ -34,30 +41,53 @@ public final class DiscordRPCSystem extends BaseComponentSystem { @In private NetworkSystem networkSystem; + @In + private EntityManager entityManager; + + @In + private DelayManager delayManager; + + private int onlinePlayers; + @Override public void initialise() { + onlinePlayers = 1; + DiscordRPCSubSystem.discover(); } @Override public void preBegin() { DiscordRPCSubSystem.setGameplayName("Custom"); - DiscordRPCSubSystem.setState(getPartyState()); + DiscordRPCSubSystem.setState(null); DiscordRPCSubSystem.setStartTimestamp(null); } @Override public void postBegin() { DiscordRPCSubSystem.setStartTimestamp(OffsetDateTime.now()); + setPartyState(); } @Override public void shutdown() { + if (delayManager.hasPeriodicAction(player.getClientEntity(), UPDATE_PARTY_SIZE_ID)) { + delayManager.cancelPeriodicAction(player.getClientEntity(), UPDATE_PARTY_SIZE_ID); + } + DiscordRPCSubSystem.reset(); DiscordRPCSubSystem.setState("In Main Menu"); DiscordRPCSubSystem.setStartTimestamp(null); } + @ReceiveEvent + public void onPlayerInitialized(LocalPlayerInitializedEvent event, EntityRef player) { + /* Adds the periodic action when the player is hosting or playing online to update party size */ + if (networkSystem.getMode() != NetworkMode.NONE) { + delayManager.addPeriodicAction(player, UPDATE_PARTY_SIZE_ID, 0, UPDATE_PARTY_SIZE_PERIOD); + } + } + @ReceiveEvent public void onAfk(AfkEvent event, EntityRef entityRef) { if (isServer() && player.getClientEntity().equals(entityRef)) { @@ -66,22 +96,38 @@ public void onAfk(AfkEvent event, EntityRef entityRef) { if (event.isAfk()) { DiscordRPCSubSystem.setState("Idle"); - DiscordRPCSubSystem.setStartTimestamp(null); + DiscordRPCSubSystem.resetPartyInfo(); } else { - DiscordRPCSubSystem.setState(getPartyState()); - DiscordRPCSubSystem.setStartTimestamp(OffsetDateTime.now()); + setPartyState(); } } - public String getPartyState() { - NetworkMode networkMode = networkSystem.getMode(); + @ReceiveEvent + public void onPeriodicTrigger(PeriodicActionTriggeredEvent event, EntityRef entity) { + if (event.getActionId().equals(UPDATE_PARTY_SIZE_ID)) { + onlinePlayers = 0; + entityManager.getEntitiesWith(ClientComponent.class).forEach(ignored -> onlinePlayers++); + DiscordRPCSubSystem.setPartyInfo(onlinePlayers, 99); + } + } + + private void setPartyState() { + final NetworkMode networkMode = networkSystem.getMode(); + String mode = "Playing Online"; if (networkMode == NetworkMode.DEDICATED_SERVER) { mode = "Hosting"; } else if (networkMode == NetworkMode.NONE) { mode = "Playing Solo"; + DiscordRPCSubSystem.setPartyInfo(1, 1); + } + + DiscordRPCSubSystem.setState(mode); + if (networkMode != NetworkMode.NONE) { + + /* The player is playing online or hosting a game */ + DiscordRPCSubSystem.setPartyInfo(onlinePlayers, 99); } - return mode; } private boolean isServer() { diff --git a/subsystems/DiscordRPC/src/main/java/org/terasology/engine/subsystem/discordrpc/DiscordRPCThread.java b/subsystems/DiscordRPC/src/main/java/org/terasology/engine/subsystem/discordrpc/DiscordRPCThread.java index b0acfa73e3f..85f651f411c 100644 --- a/subsystems/DiscordRPC/src/main/java/org/terasology/engine/subsystem/discordrpc/DiscordRPCThread.java +++ b/subsystems/DiscordRPC/src/main/java/org/terasology/engine/subsystem/discordrpc/DiscordRPCThread.java @@ -251,12 +251,25 @@ public synchronized DiscordRPCBuffer getBuffer() { } private RichPresence build() { - return new RichPresence.Builder() - .setLargeImage(DISCORD_APP_DEFAULT_IMAGE) - .setDetails(buffer.getDetails()) - .setState(buffer.getState()) - .setStartTimestamp(buffer.getStartTimestamp()) - .build(); + RichPresence.Builder builder = new RichPresence.Builder() + .setLargeImage(DISCORD_APP_DEFAULT_IMAGE); + + if (buffer.getDetails() != null) + builder.setDetails(buffer.getDetails()); + + if (buffer.getState() != null) + builder.setState(buffer.getState()); + + if (buffer.getStartTimestamp() != null) + builder.setStartTimestamp(buffer.getStartTimestamp()); + + int partySize = buffer.getPartySize(); + int partyMax = buffer.getPartyMax(); + if (partySize > 0 && partyMax > 0) { + builder.setParty("null", partySize, partyMax); + } + + return builder.build(); } private void reset(boolean resetConnection) {