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

Refactor Channels #1306

Draft
wants to merge 1 commit into
base: dev
Choose a base branch
from
Draft

Refactor Channels #1306

wants to merge 1 commit into from

Conversation

dentmaged
Copy link
Contributor

This PR refactors channels and adds some new features:

  • A new Channel class that allows other plugins (such as PGMSquads) to implement custom channels
  • A proper broadcasts API
  • /msg <target> is now a channel, and therefore can be set to your default - messages will be sent to your selected target without running /msg or /r
  • Suggestions when starting a message with a channel shortcut now work
  • Messages sent in admin or global chat during a cycle will be visible to all viewers (at the moment, messages can be lost as some players are in old Match, and others in the new Match)

Signed-off-by: William Jeffcock <[email protected]>
@dentmaged dentmaged changed the title Refactor channels Refactor Channels Mar 4, 2024
import tc.oc.pgm.util.Players;
import tc.oc.pgm.util.named.NameStyle;

public interface Channel<T> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could extend Adventure's Audience.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

given the extra overhead that a channel implies, it probably shouldn't.
You don't want someone treating this like it was just another casual audience, when it may not act like one at all (eg: requirement for a target to send within the channel). Effectively speaking the only channel that could properly implement audience would be global chat

import tc.oc.pgm.util.Players;
import tc.oc.pgm.util.named.NameStyle;

public interface Channel<T> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This API needs to be fully documented, explaining each method's purpose and params

return getViewers(target);
}

default void sendMessage(ChannelMessageEvent<T> event) {}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
default void sendMessage(ChannelMessageEvent<T> event) {}
void sendMessage(ChannelMessageEvent<T> event);

either force the downstream to implement this, or have an actual default impl, but don't just leave an empty no-op method for something this critical.
I'd personally advocate for having a default impl here, just like broadcastMessage has


default void sendMessage(ChannelMessageEvent<T> event) {}

default Component formatMessage(T target, @Nullable MatchPlayer sender, Component message) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i believe this method should not default to global-chat behavior, force downstream to implement it too

}

default void registerCommand(PaperCommandManager<CommandSender> manager) {
String name = getAliases()[0];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if aliases is an empty array, this throws an out of bounds exception. Throw your own illegal argument exception instead

Comment on lines +69 to +70
String[] aliases = new String[getAliases().length - 1];
System.arraycopy(getAliases(), 1, aliases, 0, aliases.length);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs to go into some util, you could also use Arrays.copyOfRange:

Suggested change
String[] aliases = new String[getAliases().length - 1];
System.arraycopy(getAliases(), 1, aliases, 0, aliases.length);
String[] aliases = Arrays.copyOfRange(getAliases(), 1, getAliases().length);

Comment on lines +140 to +175
manager
.commandBuilder("msg", "tell")
.argument(
StringArgument.<CommandSender, MatchPlayer>ofType(
TypeToken.get(MatchPlayer.class), "target")
.withParser(
manager
.getParserRegistry()
.createParser(
TypeToken.get(MatchPlayer.class), ParserParameters.empty())
.orElseThrow(IllegalStateException::new))
.build())
.handler(
context -> {
MatchPlayer sender =
context.inject(MatchPlayer.class).orElseThrow(IllegalStateException::new);
final MatchPlayer target = context.<MatchPlayer>get("target");
setSelectedTarget(sender, target);
PGM.get().getChannelManager().setChannel(sender, this);
}));

manager.command(
manager
.commandBuilder("msg", "tell")
.argument(
StringArgument.<CommandSender, MatchPlayer>ofType(
TypeToken.get(MatchPlayer.class), "target")
.withParser(
manager
.getParserRegistry()
.createParser(
TypeToken.get(MatchPlayer.class), ParserParameters.empty())
.orElseThrow(IllegalStateException::new))
.build())
.argument(
StringArgument.<CommandSender>builder("message")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can chain commands like these.

after the .handler(context -> ...) you can append the next .argument and another .handler. The first handler is used if the command is up to the first argument, the second is used when the command also has the 2nd param


@Override
public Map<String, Object> processChatShortcut(MatchPlayer sender, String message) {
if (message.length() == 1) throw usage("/msg <player> [message]");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if it's a shortcut, it probably isn't a /command syntax

if (message.length() == 1) throw usage("/msg <player> [message]");
Map<String, Object> arguments = new HashMap<String, Object>();

int spaceIndex = message.indexOf(" ");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
int spaceIndex = message.indexOf(" ");
int spaceIndex = message.indexOf(' ');


SettingValue option = sender.getSettings().getValue(SettingKey.MESSAGE);
if (option.equals(SettingValue.MESSAGE_OFF))
throw exception("command.message.disabled", text("/toggle dm", NamedTextColor.RED));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could be made into a clickable text to toggle

}

for (MatchPlayer viewer : getMatch().getPlayers()) {
if (shouldShowTouched(toucher.getParty(), viewer.getParty())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pretty sure this is a behavior change with matches with +2 teams. Before it would show this to all players in a team that had touched, while now it will only show to the team that touched.
Eg, a 4-team DTC map:
Blue touches red core <- Blue is notified
Green touches red core <- Before, both green and blue are notified, now only green is.

@Pablete1234 Pablete1234 marked this pull request as draft March 5, 2024 00:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

3 participants