Skip to content

Commit

Permalink
detect and track online time through 2b2t queue skips
Browse files Browse the repository at this point in the history
  • Loading branch information
rfresh2 committed Nov 15, 2024
1 parent 5491bb2 commit 7261557
Show file tree
Hide file tree
Showing 8 changed files with 44 additions and 11 deletions.
21 changes: 19 additions & 2 deletions src/main/java/com/zenith/Proxy.java
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,11 @@ public class Proxy {
protected final AtomicReference<ServerSession> currentPlayer = new AtomicReference<>();
protected final FastArrayList<ServerSession> activeConnections = new FastArrayList<>(ServerSession.class);
private boolean inQueue = false;
private boolean didQueueSkip = false;
private int queuePosition = 0;
@Setter @Nullable private Instant connectTime;
private Instant disconnectTime = Instant.now();
private OptionalLong prevOnlineSeconds = OptionalLong.empty();
private Optional<Boolean> isPrio = Optional.empty();
@Getter private final AtomicBoolean loggingIn = new AtomicBoolean(false);
@Setter @NotNull private AutoUpdater autoUpdater = NoOpAutoUpdater.INSTANCE;
Expand Down Expand Up @@ -119,6 +121,7 @@ public void initEventHandlers() {
of(StartQueueEvent.class, this::handleStartQueueEvent),
of(QueuePositionUpdateEvent.class, this::handleQueuePositionUpdateEvent),
of(QueueCompleteEvent.class, this::handleQueueCompleteEvent),
of(QueueSkipEvent.class, this::handleQueueSkipEvent),
of(PlayerOnlineEvent.class, this::handlePlayerOnlineEvent),
of(PrioStatusEvent.class, this::handlePrioStatusEvent),
of(PrivateMessageSendEvent.class, this::handlePrivateMessageSendEvent)
Expand Down Expand Up @@ -638,7 +641,7 @@ public void twoB2tTimeLimitKickWarningTick() {
|| !isOnlineOn2b2tForAtLeastDuration(twoB2tTimeLimit.minusMinutes(10L))
) return;
final ServerSession playerConnection = this.currentPlayer.get();
final Duration durationUntilKick = twoB2tTimeLimit.minus(Duration.ofSeconds(Proxy.getInstance().getOnlineTimeSeconds()));
final Duration durationUntilKick = twoB2tTimeLimit.minus(Duration.ofSeconds(Proxy.getInstance().getOnlineTimeSecondsWithQueueSkip()));
if (durationUntilKick.isNegative()) return; // sanity check just in case 2b's plugin changes
var actionBarPacket = new ClientboundSetActionBarTextPacket(
ComponentSerializer.minimessage((durationUntilKick.toMinutes() <= 3 ? "<red>" : "<blue>") + twoB2tTimeLimit.toHours() + "hr kick in: " + durationUntilKick.toMinutes() + "m"));
Expand Down Expand Up @@ -673,14 +676,24 @@ public long getOnlineTimeSeconds() {
: 0L;
}

public long getOnlineTimeSecondsWithQueueSkip() {
return !inQueue && didQueueSkip && prevOnlineSeconds.isPresent()
? getOnlineTimeSeconds() + prevOnlineSeconds.getAsLong()
: getOnlineTimeSeconds();
}

public String getOnlineTimeString() {
return Queue.getEtaStringFromSeconds(getOnlineTimeSeconds());
return Queue.getEtaStringFromSeconds(getOnlineTimeSecondsWithQueueSkip());
}

public void handleDisconnectEvent(DisconnectEvent event) {
CACHE.reset(CacheResetType.FULL);
this.disconnectTime = Instant.now();
this.prevOnlineSeconds = inQueue
? OptionalLong.empty()
: OptionalLong.of(Duration.between(this.connectTime, this.disconnectTime).toSeconds());
this.inQueue = false;
this.didQueueSkip = false;
this.queuePosition = 0;
TPS.reset();
if (!DISCORD.isRunning()
Expand Down Expand Up @@ -724,6 +737,10 @@ public void handleQueueCompleteEvent(QueueCompleteEvent event) {
this.connectTime = Instant.now();
}

public void handleQueueSkipEvent(QueueSkipEvent event) {
this.didQueueSkip = true;
}

public void handlePlayerOnlineEvent(PlayerOnlineEvent event) {
if (this.isPrio.isEmpty())
// assume we are prio if we skipped queuing
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public LiteralArgumentBuilder<CommandContext> register() {
EXECUTOR.execute(() -> {
Proxy.getInstance().disconnect(SYSTEM_DISCONNECT);
MODULE.get(AutoReconnect.class).cancelAutoReconnect();
Proxy.getInstance().connect();
MODULE.get(AutoReconnect.class).scheduleAutoReconnect(2);
});
});
}
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/com/zenith/discord/DiscordEventListener.java
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ public void handleDisconnectEvent(DisconnectEvent event) {
.addField("Reason", event.reason(), false)
.addField("Why?", category.getWikiURL(), false)
.addField("Category", category.toString(), false)
.addField("Online Duration", formatDuration(event.onlineDuration()), false)
.addField("Online Duration", formatDuration(event.onlineDurationWithQueueSkip()), false)
.errorColor();
if (Proxy.getInstance().isOn2b2t()
&& !Proxy.getInstance().isPrio()
Expand Down
7 changes: 4 additions & 3 deletions src/main/java/com/zenith/event/proxy/DisconnectEvent.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,15 @@ public record DisconnectEvent(
String reason,
boolean manualDisconnect,
Duration onlineDuration,
Duration onlineDurationWithQueueSkip,
boolean wasInQueue,
int queuePosition
) {
public DisconnectEvent(String reason, final Duration onlineDuration, boolean wasInQueue, int queuePosition) {
this(reason, (Shared.MANUAL_DISCONNECT.equals(reason)), onlineDuration, wasInQueue, queuePosition);
public DisconnectEvent(String reason, final Duration onlineDuration, Duration onlineDurationWithQueueSkip, boolean wasInQueue, int queuePosition) {
this(reason, (Shared.MANUAL_DISCONNECT.equals(reason)), onlineDuration, onlineDurationWithQueueSkip, wasInQueue, queuePosition);
}

public DisconnectEvent(String reason) {
this(reason, Duration.ZERO, false, 0);
this(reason, Duration.ZERO, Duration.ZERO, false, 0);
}
}
6 changes: 6 additions & 0 deletions src/main/java/com/zenith/event/proxy/QueueSkipEvent.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.zenith.event.proxy;

// note: this may be posted before StartQueueEvent
public record QueueSkipEvent() {
public static final QueueSkipEvent INSTANCE = new QueueSkipEvent();
}
2 changes: 1 addition & 1 deletion src/main/java/com/zenith/module/impl/AutoReconnect.java
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ private void delayBeforeReconnect(int delaySeconds) {
final int countdown = delaySeconds;
EVENT_BUS.postAsync(new AutoReconnectEvent(countdown));
// random jitter to help prevent multiple clients from logging in at the same time
Wait.wait((((int) (Math.random() * 5))) % 10);
Wait.waitRandomMs(5000);
for (int i = countdown; i > 0; i-=10) {
info("Reconnecting in {}s", i);
Wait.wait(10);
Expand Down
3 changes: 2 additions & 1 deletion src/main/java/com/zenith/network/client/ClientSession.java
Original file line number Diff line number Diff line change
Expand Up @@ -165,9 +165,10 @@ public void callDisconnected(Component reason, Throwable cause) {
}
CLIENT_LOG.info("Disconnected: {}", reasonStr);
var onlineDuration = Duration.ofSeconds(Proxy.getInstance().getOnlineTimeSeconds());
var onlineDurationWithQueueSkip = Duration.ofSeconds(Proxy.getInstance().getOnlineTimeSecondsWithQueueSkip());
// stop processing packets before we reset the client cache to avoid race conditions
getClientEventLoop().shutdownGracefully(0L, 15L, TimeUnit.SECONDS).awaitUninterruptibly();
EVENT_BUS.post(new DisconnectEvent(reasonStr, onlineDuration, Proxy.getInstance().isInQueue(), Proxy.getInstance().getQueuePosition()));
EVENT_BUS.post(new DisconnectEvent(reasonStr, onlineDuration, onlineDurationWithQueueSkip, Proxy.getInstance().isInQueue(), Proxy.getInstance().getQueuePosition()));
}

public EventLoop getClientEventLoop() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.zenith.Proxy;
import com.zenith.event.proxy.DeathMessageEvent;
import com.zenith.event.proxy.QueueSkipEvent;
import com.zenith.event.proxy.SelfDeathMessageEvent;
import com.zenith.event.proxy.ServerChatReceivedEvent;
import com.zenith.feature.deathmessages.DeathMessageParseResult;
Expand All @@ -11,6 +12,7 @@
import com.zenith.util.ComponentSerializer;
import lombok.NonNull;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import net.kyori.adventure.text.format.TextColor;
import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.ClientboundSystemChatPacket;

Expand All @@ -35,10 +37,10 @@ public boolean applyAsync(@NonNull ClientboundSystemChatPacket packet, @NonNull
final Component component = packet.getContent();
final String messageString = ComponentSerializer.serializePlain(component);
Optional<DeathMessageParseResult> deathMessage = Optional.empty();
if (!messageString.startsWith("<") && Proxy.getInstance().isOn2b2t())
deathMessage = parseDeathMessage2b2t(component, deathMessage, messageString);
String senderName = null;
String whisperTarget = null;
if (!messageString.startsWith("<") && Proxy.getInstance().isOn2b2t())
deathMessage = parseDeathMessage2b2t(component, deathMessage, messageString);
if (messageString.startsWith("<")) {
senderName = extractSenderNameNormalChat(messageString);
} else if (deathMessage.isEmpty()) {
Expand All @@ -59,6 +61,12 @@ public boolean applyAsync(@NonNull ClientboundSystemChatPacket packet, @NonNull
messageString,
Optional.ofNullable(whisperTarget).flatMap(t -> CACHE.getTabListCache().getFromName(t)),
deathMessage));
if (Proxy.getInstance().isOn2b2t()
&& "Reconnecting to server 2b2t.".equals(messageString)
&& NamedTextColor.GOLD.equals(component.style().color())) {
CLIENT_LOG.info("Queue Skip Detected");
EVENT_BUS.postAsync(QueueSkipEvent.INSTANCE);
}
} catch (final Exception e) {
CLIENT_LOG.error("Caught exception in ChatHandler. Packet: {}", packet, e);
}
Expand Down

0 comments on commit 7261557

Please sign in to comment.