Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fully implement chat/whisper spying #421

Merged
merged 6 commits into from
Aug 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
import net.draycia.carbon.common.command.commands.PartyCommands;
import net.draycia.carbon.common.command.commands.ReloadCommand;
import net.draycia.carbon.common.command.commands.ReplyCommand;
import net.draycia.carbon.common.command.commands.SpyCommand;
import net.draycia.carbon.common.command.commands.ToggleMessagesCommand;
import net.draycia.carbon.common.command.commands.UnignoreCommand;
import net.draycia.carbon.common.command.commands.UnmuteCommand;
Expand All @@ -73,6 +74,7 @@
import net.draycia.carbon.common.listeners.Listener;
import net.draycia.carbon.common.listeners.MessagePacketHandler;
import net.draycia.carbon.common.listeners.MuteHandler;
import net.draycia.carbon.common.listeners.PartyChatSpyHandler;
import net.draycia.carbon.common.listeners.PingHandler;
import net.draycia.carbon.common.listeners.RadiusListener;
import net.draycia.carbon.common.messages.CarbonMessageRenderer;
Expand Down Expand Up @@ -217,6 +219,7 @@ private void configureListeners() {
listeners.addBinding().to(ItemLinkHandler.class);
listeners.addBinding().to(MessagePacketHandler.class);
listeners.addBinding().to(MuteHandler.class);
listeners.addBinding().to(PartyChatSpyHandler.class);
listeners.addBinding().to(PingHandler.class);
listeners.addBinding().to(RadiusListener.class);
}
Expand All @@ -235,6 +238,7 @@ private void configureCommands() {
commands.addBinding().to(NicknameCommand.class).in(Scopes.SINGLETON);
commands.addBinding().to(ReloadCommand.class).in(Scopes.SINGLETON);
commands.addBinding().to(ReplyCommand.class).in(Scopes.SINGLETON);
commands.addBinding().to(SpyCommand.class).in(Scopes.SINGLETON);
commands.addBinding().to(ToggleMessagesCommand.class).in(Scopes.SINGLETON);
commands.addBinding().to(UnignoreCommand.class).in(Scopes.SINGLETON);
commands.addBinding().to(UnmuteCommand.class).in(Scopes.SINGLETON);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
/*
* CarbonChat
*
* Copyright (c) 2024 Josua Parks (Vicarious)
* Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.draycia.carbon.common.command.commands;

import com.google.inject.Inject;
import net.draycia.carbon.api.users.CarbonPlayer;
import net.draycia.carbon.common.command.CarbonCommand;
import net.draycia.carbon.common.command.CommandSettings;
import net.draycia.carbon.common.command.Commander;
import net.draycia.carbon.common.command.PlayerCommander;
import net.draycia.carbon.common.messages.CarbonMessages;
import net.kyori.adventure.key.Key;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.framework.qual.DefaultQualifier;
import org.incendo.cloud.CommandManager;

import static org.incendo.cloud.minecraft.extras.RichDescription.richDescription;
import static org.incendo.cloud.parser.standard.BooleanParser.booleanParser;

@DefaultQualifier(NonNull.class)
public final class SpyCommand extends CarbonCommand {

private final CommandManager<Commander> commandManager;
private final CarbonMessages carbonMessages;

@Inject
public SpyCommand(
final CommandManager<Commander> commandManager,
final CarbonMessages carbonMessages
) {
this.commandManager = commandManager;
this.carbonMessages = carbonMessages;
}

@Override
public CommandSettings defaultCommandSettings() {
return new CommandSettings("spy");
}

@Override
public Key key() {
return Key.key("carbon", "spy");
}

@Override
public void init() {
final var command = this.commandManager.commandBuilder(this.commandSettings().name(), this.commandSettings().aliases())
.optional("enabled", booleanParser())
.permission("carbon.spy")
.senderType(PlayerCommander.class)
.commandDescription(richDescription(this.carbonMessages.commandSpyDescription()))
.handler(handler -> {
final CarbonPlayer sender = handler.sender().carbonPlayer();

boolean enabled = !sender.spying();

if (handler.contains("enabled")) {
enabled = handler.get("enabled");
}

sender.spying(enabled);
if (enabled) {
this.carbonMessages.commandSpyEnabled(sender);
} else {
this.carbonMessages.commandSpyDisabled(sender);
}
})
.build();

this.commandManager.command(command);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,10 @@ public void whisper(
this.messages.whisperRecipient(SourcedAudience.of(sender, recipient), senderUsername, senderDisplayName, recipientUsername, recipientDisplayName, privateChatEvent.message())
);
}
this.messages.whisperConsoleLog(this.server.console(), senderUsername, senderDisplayName, recipientUsername, recipientDisplayName, privateChatEvent.message());
WhisperCommand.broadcastWhisperSpy(this.server, this.messages, senderUsername, senderDisplayName,
recipientUsername, recipientDisplayName, privateChatEvent.message());
this.messages.whisperConsoleLog(this.server.console(), senderUsername, senderDisplayName,
recipientUsername, recipientDisplayName, privateChatEvent.message());

final @Nullable Sound messageSound = this.configManager.primaryConfig().messageSound();
if (localRecipient && messageSound != null) {
Expand Down Expand Up @@ -260,6 +263,7 @@ public void handlePacket(final WhisperPacket packet) {
SourcedAudience.of(sender, recipient).sendMessage(
this.messages.whisperRecipient(SourcedAudience.of(sender, recipient), senderUsername, senderDisplayName, recipientUsername, recipientDisplayName, packet.message())
);
WhisperCommand.broadcastWhisperSpy(this.server, this.messages, senderUsername, senderDisplayName, recipientUsername, recipientDisplayName, packet.message());
this.messages.whisperConsoleLog(this.server.console(), senderUsername, senderDisplayName, recipientUsername, recipientDisplayName, packet.message());
final @Nullable Sound messageSound = this.configManager.primaryConfig().messageSound();
if (messageSound != null) {
Expand All @@ -272,4 +276,21 @@ public void handlePacket(final WhisperPacket packet) {
}
}

public static void broadcastWhisperSpy(
final CarbonServer server,
final CarbonMessages messages,
final String senderUsername,
final Component senderDisplayName,
final String recipientUsername,
final Component recipientDisplayName,
final Component message
) {
for (final CarbonPlayer player : server.players()) {
if (player.spying() && !player.username().equals(senderUsername) && !player.username().equals(recipientUsername)) {
messages.whisperRecipientSpy(player, senderUsername,
senderDisplayName, recipientUsername, recipientDisplayName, message);
}
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* CarbonChat
*
* Copyright (c) 2024 Josua Parks (Vicarious)
* Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.draycia.carbon.common.listeners;

import com.google.inject.Inject;
import java.util.Set;
import java.util.UUID;
import net.draycia.carbon.api.CarbonServer;
import net.draycia.carbon.api.event.CarbonEventHandler;
import net.draycia.carbon.api.event.events.CarbonChatEvent;
import net.draycia.carbon.api.users.CarbonPlayer;
import net.draycia.carbon.api.users.Party;
import net.draycia.carbon.common.channels.PartyChatChannel;
import net.draycia.carbon.common.messages.CarbonMessages;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.checkerframework.framework.qual.DefaultQualifier;

@DefaultQualifier(NonNull.class)
public class PartyChatSpyHandler implements Listener {

@Inject
public PartyChatSpyHandler(final CarbonEventHandler events, final CarbonMessages messages, final CarbonServer server) {
events.subscribe(CarbonChatEvent.class, 100, false, event -> {
if (!(event.chatChannel() instanceof PartyChatChannel)) {
return;
}

final @Nullable Party party = event.sender().party().get();
final Set<UUID> members = party == null ? Set.of() : party.members();

for (final CarbonPlayer player : server.players()) {
if (player.spying() && !members.contains(player.uuid())) {
messages.partySpy(player, event.message());
}
}
});
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
package net.draycia.carbon.common.listeners;

import com.google.inject.Inject;
import java.util.ArrayList;
import java.util.List;
import net.draycia.carbon.api.event.CarbonEventHandler;
import net.draycia.carbon.api.event.events.CarbonChatEvent;
import net.draycia.carbon.api.users.CarbonPlayer;
Expand All @@ -46,14 +48,22 @@ public RadiusListener(
return;
}

final List<CarbonPlayer> spyingPlayers = new ArrayList<>();

if (radius == 0) {
event.recipients().removeIf(audience -> {
if (audience.equals(event.sender())) {
return false;
}

if (audience instanceof CarbonPlayer carbonPlayer) {
return !carbonPlayer.sameWorldAs(event.sender());
final boolean sameWorld = carbonPlayer.sameWorldAs(event.sender());

if (!sameWorld && carbonPlayer.spying()) {
spyingPlayers.add(carbonPlayer);
}

return !sameWorld;
}

return false;
Expand All @@ -66,18 +76,32 @@ public RadiusListener(

if (audience instanceof CarbonPlayer carbonPlayer) {
if (!event.sender().sameWorldAs(carbonPlayer)) {
if (carbonPlayer.spying()) {
spyingPlayers.add(carbonPlayer);
}
return true;
}

final double distance = carbonPlayer.distanceSquaredFrom(event.sender());
return distance > (radius * radius);
final boolean outOfRange = distance > (radius * radius);

if (outOfRange && carbonPlayer.spying()) {
spyingPlayers.add(carbonPlayer);
}

return outOfRange;
}

return false;
});
}
if (event.recipients().size() <= 2 && event.chatChannel().emptyRadiusRecipientsMessage()) { // the player and cosole
carbonMessages.emptyRecipients(event.sender());
return;
}

for (final CarbonPlayer player : spyingPlayers) {
carbonMessages.radiusSpy(player, event.message());
}
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ public interface CarbonMessages {
@Message("channel.radius.empty_recipients")
void emptyRecipients(final Audience audience);

@Message("channel.radius.spy")
void radiusSpy(Audience audience, Component message);

@Message("channel.not_found")
void channelNotFound(final Audience audience);

Expand Down Expand Up @@ -127,6 +130,16 @@ Component whisperRecipient(
Component message
);

@Message("whisper.from.spy")
void whisperRecipientSpy(
Audience audience,
String senderUsername,
Component senderDisplayName,
String recipientUsername,
Component recipientDisplayName,
Component message
);

@Message("whisper.console")
void whisperConsoleLog(
Audience audience,
Expand Down Expand Up @@ -254,6 +267,21 @@ void nicknameErrorCharacterLimit(
@Message("config.reload.failed")
void configReloadFailed(final Audience audience);

/*
* =============================================================
* ========================== Spying ===========================
* =============================================================
*/

@Message("command.spy.enabled")
void commandSpyEnabled(final Audience audience);

@Message("command.spy.disabled")
void commandSpyDisabled(final Audience audience);

@Message("command.spy.description")
Component commandSpyDescription();

/*
* =============================================================
* ====================== Cloud Messages =======================
Expand Down Expand Up @@ -522,6 +550,9 @@ void errorCommandCommandExecution(
@Message("party.cannot_use_channel")
Component cannotUsePartyChannel(Audience audience);

@Message("party.spy")
void partySpy(Audience audience, Component message);

@Message("deletemessage.prefix")
Component deleteMessagePrefix();

Expand Down
4 changes: 4 additions & 0 deletions common/src/main/resources/locale/messages-en_US.properties
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,12 @@ command.party.accept.description=Accept party invites.
command.party.leave.description=Leave your current party.
command.party.already_in_party=<display_name><red> is already in your party.
command.party.disband.description=Disband your current party.
command.spy.enabled=<green>Spying is now enabled.
command.spy.disabled=<red>Spying is now disabled.
party.player_joined=<display_name><green> joined your party.
party.player_left=<display_name><green> left your party.
party.cannot_use_channel=<red>You must join a party to use this channel.
party.spy=[Spy]<message>
config.reload.failed=<red>Config failed to reload
config.reload.success=<green>Config reloaded successfully
error.command.argument_parsing=<red>Invalid command argument: <gray><throwable_message>
Expand Down Expand Up @@ -134,6 +137,7 @@ whisper.console=<gold>[<green><sender_display_name></green>] -> [<green><recipie
whisper.continue.target_missing=<red>You have no one to whisper
whisper.error=<red>Failed to send private message
whisper.from=<click:suggest_command:'/whisper <sender_username> '><hover:show_text:'Click to start a reply'><gold>[<green><sender_display_name></green>] -> [<green>You</green>] <message>
whisper.from.spy=<red>SPY [</red><green><sender_display_name></green>]<red> -> [</red><green><recipient_display_name></green><red>]</red> <message>
whisper.ignored_by_target=<red><target> <red>is ignoring you
whisper.ignoring_target=<red>You are ignoring <target>
whisper.ignoring_all=<red>You cannot send messages while they are ignored!
Expand Down