Skip to content

Commit

Permalink
feat(chat): add /me, /say and /tellraw command messages (closes #…
Browse files Browse the repository at this point in the history
…51) (#53)

fix(chat): correct `teleport` message placeholders in config
  • Loading branch information
axieum authored Aug 11, 2022
1 parent 1859c69 commit 7eea724
Show file tree
Hide file tree
Showing 7 changed files with 370 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,11 @@
import net.minecraft.network.message.MessageType;
import net.minecraft.network.message.SignedMessage;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.command.ServerCommandSource;
import net.minecraft.server.filter.FilteredMessage;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.text.Text;
import net.minecraft.util.crash.CrashReport;
import net.minecraft.util.registry.RegistryKey;

Expand Down Expand Up @@ -250,6 +252,36 @@ public static final class Minecraft
}
});

/**
* Called when a player sent an in-game message via the {@code /me} command.
*/
public static final Event<EmoteCommand> EMOTE_COMMAND =
EventFactory.createArrayBacked(EmoteCommand.class, callbacks -> (st, source, action) -> {
for (EmoteCommand callback : callbacks) {
callback.onEmoteCommandPlaceholder(st, source, action);
}
});

/**
* Called when an admin broadcast an in-game message via the {@code /say} command.
*/
public static final Event<SayCommand> SAY_COMMAND =
EventFactory.createArrayBacked(SayCommand.class, callbacks -> (st, source, action) -> {
for (SayCommand callback : callbacks) {
callback.onSayCommandPlaceholder(st, source, action);
}
});

/**
* Called when an admin broadcast an in-game message to all players via the {@code /tellraw @a} command.
*/
public static final Event<TellRawCommand> TELLRAW_COMMAND =
EventFactory.createArrayBacked(TellRawCommand.class, callbacks -> (st, source, action) -> {
for (TellRawCommand callback : callbacks) {
callback.onTellRawCommandPlaceholder(st, source, action);
}
});

@FunctionalInterface
public interface ServerStarting
{
Expand Down Expand Up @@ -402,5 +434,60 @@ public interface PlayerDeath
*/
void onPlayerDeathPlaceholder(StringTemplate template, ServerPlayerEntity player, DamageSource source);
}

@FunctionalInterface
public interface EmoteCommand
{
/**
* Called when a player sent an in-game message via the {@code /me}
* command.
*
* @param template mutable string template
* @param source source of the command, e.g. a player
* @param action received message contents
* @see net.minecraft.network.message.MessageType#EMOTE_COMMAND
* @see net.fabricmc.fabric.api.message.v1.ServerMessageEvents#COMMAND_MESSAGE
*/
void onEmoteCommandPlaceholder(
StringTemplate template,
ServerCommandSource source,
FilteredMessage<SignedMessage> action
);
}

@FunctionalInterface
public interface SayCommand
{
/**
* Called when an admin broadcast an in-game message via the
* {@code /say} command.
*
* @param template mutable string template
* @param source source of the message, e.g. a player
* @param action received message contents
* @see net.minecraft.network.message.MessageType#SAY_COMMAND
* @see net.fabricmc.fabric.api.message.v1.ServerMessageEvents#COMMAND_MESSAGE
*/
void onSayCommandPlaceholder(
StringTemplate template,
ServerCommandSource source,
FilteredMessage<SignedMessage> action
);
}

@FunctionalInterface
public interface TellRawCommand
{
/**
* Called when an admin broadcast an in-game message to *all*
* players via the {@code /tellraw @a} command.
*
* @param template mutable string template
* @param source source of the message, e.g. a player
* @param message received message contents
* @see net.minecraft.network.message.MessageType#TELLRAW_COMMAND
*/
void onTellRawCommandPlaceholder(StringTemplate template, ServerCommandSource source, Text message);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package me.axieum.mcmod.minecord.api.chat.event.minecraft;

import net.minecraft.server.command.ServerCommandSource;
import net.minecraft.text.Text;

import net.fabricmc.fabric.api.event.Event;
import net.fabricmc.fabric.api.event.EventFactory;

public interface TellRawMessageCallback
{
/**
* Called when a server (or player) broadcasts a {@code /tellraw} command
* message to *all* players.
*/
Event<TellRawMessageCallback> EVENT =
EventFactory.createArrayBacked(TellRawMessageCallback.class, callbacks -> (message, source) -> {
for (TellRawMessageCallback callback : callbacks) {
callback.onTellRawCommandMessage(message, source);
}
});

/**
* Called when a server (or player) broadcasts a {@code /tellraw} command
* message to *all* players.
*
* @param message broadcast message with message decorators applied if applicable
* @param source command source that sent the message
*/
void onTellRawCommandMessage(Text message, ServerCommandSource source);
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import me.axieum.mcmod.minecord.api.addon.MinecordAddon;
import me.axieum.mcmod.minecord.api.chat.event.minecraft.EntityDeathEvents;
import me.axieum.mcmod.minecord.api.chat.event.minecraft.GrantCriterionCallback;
import me.axieum.mcmod.minecord.api.chat.event.minecraft.TellRawMessageCallback;
import me.axieum.mcmod.minecord.api.event.ServerShutdownCallback;
import me.axieum.mcmod.minecord.impl.chat.callback.discord.MessageReactionListener;
import me.axieum.mcmod.minecord.impl.chat.callback.discord.MessageReceivedListener;
Expand Down Expand Up @@ -97,6 +98,11 @@ public void onInitializeServer()

// A named animal/monster (with name tag) died
EntityDeathEvents.ANIMAL_MONSTER.register(new EntityDeathCallback());
// A player sent an in-game message via the '/me' command
// An admin broadcast an in-game message via the '/say' command
ServerMessageEvents.COMMAND_MESSAGE.register(new ServerMessageCallback());
// An admin broadcast an in-game message to all players via the '/tellraw' command
TellRawMessageCallback.EVENT.register(new ServerMessageCallback());
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,26 @@
package me.axieum.mcmod.minecord.impl.chat.callback.minecraft;

import org.jetbrains.annotations.Nullable;

import net.minecraft.network.message.MessageType;
import net.minecraft.network.message.SignedMessage;
import net.minecraft.server.command.ServerCommandSource;
import net.minecraft.server.filter.FilteredMessage;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.text.Text;
import net.minecraft.util.registry.RegistryKey;

import net.fabricmc.fabric.api.message.v1.ServerMessageEvents.ChatMessage;
import net.fabricmc.fabric.api.message.v1.ServerMessageEvents.CommandMessage;

import me.axieum.mcmod.minecord.api.Minecord;
import me.axieum.mcmod.minecord.api.chat.event.ChatPlaceholderEvents;
import me.axieum.mcmod.minecord.api.chat.event.minecraft.TellRawMessageCallback;
import me.axieum.mcmod.minecord.api.util.StringTemplate;
import me.axieum.mcmod.minecord.api.util.StringUtils;
import me.axieum.mcmod.minecord.impl.chat.util.DiscordDispatcher;

public class ServerMessageCallback implements ChatMessage
public class ServerMessageCallback implements ChatMessage, CommandMessage, TellRawMessageCallback
{
@Override
public void onChatMessage(
Expand Down Expand Up @@ -51,4 +57,127 @@ public void onChatMessage(
entry -> entry.discord.chat != null && entry.hasWorld(player.world));
});
}

@Override
public void onCommandMessage(
FilteredMessage<SignedMessage> message, ServerCommandSource source, RegistryKey<MessageType> typeKey
)
{
if (MessageType.EMOTE_COMMAND.equals(typeKey)) {
// '/me <action>'
onEmoteCommandMessage(message, source);
} else if (MessageType.SAY_COMMAND.equals(typeKey)) {
// '/say <message>'
onSayCommandMessage(message, source);
}
}

/**
* Called when a player broadcasts a {@code /me} command message to all
* players.
*
* @param message broadcast message with message decorators applied if
* applicable
* @param source command source that sent the message
*/
public void onEmoteCommandMessage(FilteredMessage<SignedMessage> message, ServerCommandSource source)
{
Minecord.getInstance().getJDA().ifPresent(jda -> {
final @Nullable ServerPlayerEntity player = source.getPlayer();

/*
* Prepare a message template.
*/

final StringTemplate st = new StringTemplate();

// The player's username
st.add("username", player != null ? player.getName().getString() : null);
// The player's display name
st.add("player", player != null ? player.getDisplayName().getString() : null);
// The name of the world the player logged into
st.add("world", player != null ? StringUtils.getWorldName(source.getWorld()) : null);
// The formatted message contents
st.add("action", StringUtils.minecraftToDiscord(
message.filteredOrElse(message.raw()).getContent().getString()
));

ChatPlaceholderEvents.Minecraft.EMOTE_COMMAND.invoker().onEmoteCommandPlaceholder(st, source, message);

/*
* Dispatch the message.
*/

DiscordDispatcher.dispatch((embed, entry) ->
embed.setContent(st.format(entry.discord.emote)),
entry -> entry.discord.emote != null && (player == null || entry.hasWorld(source.getWorld())));
});
}

/**
* Called when a server (or player) broadcasts a {@code /say} command
* message to all players.
*
* @param message broadcast message with message decorators applied if
* applicable
* @param source command source that sent the message
*/
public void onSayCommandMessage(FilteredMessage<SignedMessage> message, ServerCommandSource source)
{
Minecord.getInstance().getJDA().ifPresent(jda -> {
final @Nullable ServerPlayerEntity player = source.getPlayer();

/*
* Prepare a message template.
*/

final StringTemplate st = new StringTemplate();

// The player's username
st.add("username", player != null ? player.getName().getString() : null);
// The player's display name
st.add("player", player != null ? player.getDisplayName().getString() : null);
// The name of the world the player logged into
st.add("world", player != null ? StringUtils.getWorldName(source.getWorld()) : null);
// The formatted message contents
st.add("message", StringUtils.minecraftToDiscord(
message.filteredOrElse(message.raw()).getContent().getString()
));

ChatPlaceholderEvents.Minecraft.SAY_COMMAND.invoker().onSayCommandPlaceholder(st, source, message);

/*
* Dispatch the message.
*/

DiscordDispatcher.dispatch((embed, entry) ->
embed.setContent(st.format(entry.discord.say)),
entry -> entry.discord.say != null && (player == null || entry.hasWorld(source.getWorld())));
});
}

@Override
public void onTellRawCommandMessage(Text message, ServerCommandSource source)
{
Minecord.getInstance().getJDA().ifPresent(jda -> {
/*
* Prepare a message template.
*/

final StringTemplate st = new StringTemplate();

// The formatted message contents
st.add("message", StringUtils.minecraftToDiscord(message.getString()));

ChatPlaceholderEvents.Minecraft.TELLRAW_COMMAND.invoker().onTellRawCommandPlaceholder(st, source, message);

/*
* Dispatch the message.
*/

DiscordDispatcher.dispatch((embed, entry) ->
embed.setContent(st.format(entry.discord.tellraw)),
entry -> entry.discord.tellraw != null);
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,31 @@ public static class ChatEntrySchema
/**
* Discord events configuration schema.
*/
@SuppressWarnings("checkstyle:linelength")
public static class DiscordSchema
{
@Comment("""
A player sent an in-game chat message
Usages: ${username}, ${player}, ${message} and ${world}""")
public String chat = "`${world}` **${player}** > ${message}";

@Comment("""
A player sent an in-game message via the '/me' command
Note: there is no player or world if sent from a command block or console!
Usages: ${username}, ${player}, ${action} and ${world}""")
public String emote = "`${world:-∞}` **${player:-Server}** _${action}_";

@Comment("""
An admin broadcast an in-game message via the '/say' command
Note: there is no player or world if sent from a command block or console!
Usages: ${username}, ${player}, ${message} and ${world}""")
public String say = "**[${player:-Server}]** ${message}";

@Comment("""
An admin broadcast an in-game message to all players via the '/tellraw @a' command
Usages: ${message}""")
public String tellraw = "${message}";

@Comment("""
A player had died
Usages: ${username}, ${player}, ${cause}, ${world}, ${x}, ${y}, ${z}, ${score} and ${exp}""")
Expand All @@ -64,8 +82,8 @@ public static class DiscordSchema

@Comment("""
A player teleported to another dimension
Usages: ${username}, ${player}, ${origin} and ${destination}""")
public String teleport = "**${player}** entered ${destination}. :cyclone:";
Usages: ${username}, ${player}, ${world}, ${x}, ${y}, ${z}, ${origin}, ${origin_x}, ${origin_y} and ${origin_z}""")
public String teleport = "**${player}** entered ${world}. :cyclone:";

@Comment("""
A player joined the game
Expand Down
Loading

0 comments on commit 7eea724

Please sign in to comment.