Skip to content
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
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
<div align="center">
<h1>SharedStats</h1>
<p>Share your health and food level with the players in your group.</p>
<p>
<a href="https://www.curseforge.com/minecraft/bukkit-plugins/sharedstats/preview"><img src="https://wsrv.nl/?url=https%3A%2F%2Fcdn.jsdelivr.net%2Fnpm%2F%40intergrav%2Fdevins-badges%403%2Fassets%2Fcozy%2Favailable%2Fcurseforge_vector.svg&amp;n=-1" alt="Available on CurseForge"></a>
<a href="https://modrinth.com/plugin/sharedstats"><img src="https://wsrv.nl/?url=https%3A%2F%2Fcdn.jsdelivr.net%2Fnpm%2F%40intergrav%2Fdevins-badges%403%2Fassets%2Fcozy%2Favailable%2Fmodrinth_vector.svg&amp;n=-1" alt="Available on Modrinth"></a>
</p>
</div>

## Commands
Expand All @@ -15,6 +19,7 @@
| `/sharedgroup start` | Start the game and stat synchronization | OP, group owner |
| `/sharedgroup stop` | Stop an active game without deleting the group | Group owner |
| `/sharedgroup players` | List the online players in your group | Group member |
| `/sharedgroup leaderboard` | Show the group's death leaderboard during a game | Group member |
| `/sharedgroup version` | Display the plugin version | None |

## What remains to be done
Expand Down
14 changes: 14 additions & 0 deletions src/main/java/fr/korastrip/paperplugin/Utils.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package fr.korastrip.paperplugin;

import io.papermc.paper.util.Tick;

import java.time.Duration;

public class Utils
{

public static int toTick(int seconds) {
return Tick.tick().fromDuration(Duration.ofSeconds(seconds));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,9 @@ public LiteralCommandNode<CommandSourceStack> create() {
.then(new Stop(plugin).build())
.then(new Version(plugin).build())
.then(new Remove(plugin).build())
.then(new Remove(plugin).build())
.then(new Revoke(plugin).build())
.then(new Players(plugin).build())
.then(new Stats(plugin).build())
.build();

}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
package fr.korastrip.paperplugin.commands.group;

import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import com.mojang.brigadier.context.CommandContext;
import fr.korastrip.paperplugin.Config;
import fr.korastrip.paperplugin.SharedStats;
import fr.korastrip.paperplugin.enums.ErrorMessage;
import io.papermc.paper.command.brigadier.CommandSourceStack;
import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Entity;

public abstract class GroupSubCommand {
public record ContextResult(CommandSender sender, Entity entity) {}
protected final SharedStats plugin;
protected final String name;
protected final String description;
Expand All @@ -28,6 +34,21 @@ public String getDescription() {
return description;
}

public ContextResult getContext(CommandContext<CommandSourceStack> context) {
CommandSender sender = context.getSource().getSender();
Entity executor = context.getSource().getExecutor();
return new ContextResult(sender, executor);
}

public int generateError(String message, CommandSender player, TagResolver... resolvers) {
player.sendRichMessage("<red>" + message + "</red>", resolvers);
return 0;
}

public int generateError(ErrorMessage error, CommandSender player) {
return this.generateError(error.getMessage(), player);
}

public String getUsage() {
return usage;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,10 @@
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import fr.korastrip.paperplugin.SharedStats;
import fr.korastrip.paperplugin.commands.group.GroupSubCommand;
import fr.korastrip.paperplugin.enums.ErrorMessage;
import fr.korastrip.paperplugin.model.SharedGroup;
import io.papermc.paper.command.brigadier.CommandSourceStack;
import io.papermc.paper.command.brigadier.Commands;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;

import java.util.UUID;
Expand All @@ -24,24 +23,22 @@ public LiteralArgumentBuilder<CommandSourceStack> build() {
return Commands.literal(this.name)
.requires(source -> source.getSender().isOp())
.executes(context -> {
CommandSender sender = context.getSource().getSender();
Entity executor = context.getSource().getExecutor();
ContextResult ctx = this.getContext(context);
SharedGroup group = this.plugin.getGroup();

if (!(executor instanceof Player player)) {
if (!(ctx.entity() instanceof Player player)) {
return Command.SINGLE_SUCCESS;
}

if(!group.getPlayersId().isEmpty()) {
sender.sendRichMessage("<red>A group already exists. You cannot create another one.</red>");
return Command.SINGLE_SUCCESS;
return this.generateError(ErrorMessage.GROUP_ALREADY_EXISTS, ctx.sender());
}

UUID playerUUID = player.getUniqueId();
group.addPlayer(playerUUID);
group.setOwnerUuid(playerUUID);

sender.sendRichMessage("<green>Your group has been created.</green>\n<white>Invite players with <gold>/sharedgroup invite [player]</gold>.</white>");
ctx.sender().sendRichMessage("<green>Your group has been created.</green>\n<white>Invite players with <gold>/sharedgroup invite [player]</gold>.</white>");
return Command.SINGLE_SUCCESS;
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@
import io.papermc.paper.command.brigadier.CommandSourceStack;
import io.papermc.paper.command.brigadier.Commands;
import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;

import java.util.List;
Expand All @@ -24,10 +22,9 @@ public LiteralArgumentBuilder<CommandSourceStack> build() {

return Commands.literal("help").executes(context -> {

CommandSender sender = context.getSource().getSender();
Entity executor = context.getSource().getExecutor();
ContextResult ctx = this.getContext(context);

if (!(executor instanceof Player)) {
if (!(ctx.entity() instanceof Player)) {
return Command.SINGLE_SUCCESS;
}

Expand All @@ -39,10 +36,11 @@ public LiteralArgumentBuilder<CommandSourceStack> build() {
new Start(plugin),
new Stop(plugin),
new Players(plugin),
new Version(plugin)
new Version(plugin),
new Stats(plugin)
);

commands.forEach(command -> sender.sendRichMessage("<gold><usage></gold><white>: <description></white>", Placeholder.unparsed("description", command.getDescription()), Placeholder.unparsed("usage", command.getUsage())));
commands.forEach(command -> ctx.sender().sendRichMessage("<gold><usage></gold><white>: <description></white>", Placeholder.unparsed("description", command.getDescription()), Placeholder.unparsed("usage", command.getUsage())));

return Command.SINGLE_SUCCESS;
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,14 @@
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import fr.korastrip.paperplugin.SharedStats;
import fr.korastrip.paperplugin.commands.group.GroupSubCommand;
import fr.korastrip.paperplugin.enums.ErrorMessage;
import fr.korastrip.paperplugin.model.SharedGroup;
import io.papermc.paper.command.brigadier.CommandSourceStack;
import io.papermc.paper.command.brigadier.Commands;
import io.papermc.paper.command.brigadier.argument.ArgumentTypes;
import io.papermc.paper.command.brigadier.argument.resolvers.selector.PlayerSelectorArgumentResolver;
import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder;
import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;

import java.util.NoSuchElementException;
Expand All @@ -30,27 +29,23 @@ public LiteralArgumentBuilder<CommandSourceStack> build() {
return Commands.literal("invite")
.then(Commands.argument("player", ArgumentTypes.player())
.executes(context -> {
CommandSender sender = context.getSource().getSender();
Entity executor = context.getSource().getExecutor();
ContextResult ctx = this.getContext(context);
SharedGroup group = this.plugin.getGroup();

if (!(executor instanceof Player player)) {
if (!(ctx.entity() instanceof Player player)) {
return Command.SINGLE_SUCCESS;
}

if (group.getPlayersId().isEmpty()) {
sender.sendRichMessage("<red>There is no group. Create one with <gold>/sharedgroup create</gold>.</red>");
return Command.SINGLE_SUCCESS;
return this.generateError(ErrorMessage.NO_GROUP, ctx.sender());
}

if (!player.getUniqueId().equals(group.getOwnerUuid())) {
sender.sendRichMessage("<red>You cannot invite a player because you are not the owner.</red>");
return Command.SINGLE_SUCCESS;
return this.generateError(ErrorMessage.NOT_OWNER, ctx.sender());
}

if (group.getIsPlaying()) {
sender.sendRichMessage("<red>You cannot invite a player after the game has started.</red>");
return Command.SINGLE_SUCCESS;
return this.generateError(ErrorMessage.GAME_RUNNING, ctx.sender());
}

final PlayerSelectorArgumentResolver resolver = context.getArgument("player", PlayerSelectorArgumentResolver.class);
Expand All @@ -59,21 +54,19 @@ public LiteralArgumentBuilder<CommandSourceStack> build() {
try {
target = resolver.resolve(context.getSource()).getFirst();
} catch (CommandSyntaxException | NoSuchElementException e) {
sender.sendRichMessage("<red>Player not found.</red>");
return 0;
return this.generateError(ErrorMessage.PLAYER_NOT_FOUND, ctx.sender());
}

if (group.getPlayersId().contains(target.getUniqueId())) {
sender.sendRichMessage("<red>This player is already in the group.</red>");
return Command.SINGLE_SUCCESS;
return this.generateError(ErrorMessage.PLAYER_ALREADY_IN_GROUP, ctx.sender());
}

group.addPlayer(target.getUniqueId());

TagResolver.Single playerName = Placeholder.component("player", target.displayName());

target.sendRichMessage("<green>You have been added to the group.</green> <white>Wait for the owner to start the game.</white>");
sender.sendRichMessage("<green><gold><player></gold> has been added to the group.</green>", playerName);
ctx.sender().sendRichMessage("<green><gold><player></gold> has been added to the group.</green>", playerName);

return Command.SINGLE_SUCCESS;
}))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import fr.korastrip.paperplugin.SharedStats;
import fr.korastrip.paperplugin.commands.group.GroupSubCommand;
import fr.korastrip.paperplugin.enums.ErrorMessage;
import fr.korastrip.paperplugin.model.SharedGroup;
import io.papermc.paper.command.brigadier.CommandSourceStack;
import io.papermc.paper.command.brigadier.Commands;
import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;

public class Players extends GroupSubCommand {
Expand All @@ -21,16 +21,15 @@ public Players(SharedStats plugin) {
public LiteralArgumentBuilder<CommandSourceStack> build() {
return Commands.literal("players").executes(context -> {

Entity executor = context.getSource().getExecutor();
ContextResult ctx = this.getContext(context);
SharedGroup group = this.plugin.getGroup();

if (!(executor instanceof Player player)) {
if (!(ctx.entity() instanceof Player player)) {
return Command.SINGLE_SUCCESS;
}

if (!group.getPlayersId().contains(player.getUniqueId())) {
player.sendRichMessage("<red>You do not have permission to use this command.</red>");
return 0;
return this.generateError(ErrorMessage.NOT_IN_GROUP, player);
}

var players = group.getOnlinePlayers();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,15 @@
import com.mojang.brigadier.Command;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import fr.korastrip.paperplugin.Config;
import fr.korastrip.paperplugin.SharedStats;
import fr.korastrip.paperplugin.commands.group.GroupSubCommand;
import fr.korastrip.paperplugin.enums.ErrorMessage;
import fr.korastrip.paperplugin.model.SharedGroup;
import io.papermc.paper.command.brigadier.CommandSourceStack;
import io.papermc.paper.command.brigadier.Commands;
import io.papermc.paper.command.brigadier.argument.ArgumentTypes;
import io.papermc.paper.command.brigadier.argument.resolvers.selector.PlayerSelectorArgumentResolver;
import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;

import java.util.NoSuchElementException;
Expand All @@ -29,27 +27,23 @@ public LiteralArgumentBuilder<CommandSourceStack> build() {
return Commands.literal("remove")
.then(Commands.argument("player", ArgumentTypes.player())
.executes(context -> {
CommandSender sender = context.getSource().getSender();
Entity executor = context.getSource().getExecutor();
ContextResult ctx = this.getContext(context);
SharedGroup group = this.plugin.getGroup();

if (!(executor instanceof Player player)) {
if (!(ctx.entity() instanceof Player player)) {
return Command.SINGLE_SUCCESS;
}

if (group.getPlayersId().isEmpty()) {
sender.sendRichMessage("<red>There is no group. Create one with <gold>/sharedgroup create</gold>.</red>");
return Command.SINGLE_SUCCESS;
return this.generateError(ErrorMessage.NO_GROUP, ctx.sender());
}

if (!group.getOwnerUuid().equals(player.getUniqueId())) {
sender.sendRichMessage("<red>You do not have permission to use this command.</red>");
return Command.SINGLE_SUCCESS;
return this.generateError(ErrorMessage.NOT_OWNER, ctx.sender());
}

if (group.getIsPlaying()) {
sender.sendRichMessage("<red>You cannot remove a player during the game.</red>");
return 0;
return this.generateError(ErrorMessage.GAME_RUNNING, ctx.sender());
}

final PlayerSelectorArgumentResolver resolver = context.getArgument("player", PlayerSelectorArgumentResolver.class);
Expand All @@ -58,22 +52,19 @@ public LiteralArgumentBuilder<CommandSourceStack> build() {
try {
target = resolver.resolve(context.getSource()).getFirst();
} catch (CommandSyntaxException | NoSuchElementException e) {
sender.sendRichMessage("<red>Player not found.</red>");
return 0;
return this.generateError(ErrorMessage.PLAYER_NOT_FOUND, ctx.sender());
}

if (target.getUniqueId().equals(player.getUniqueId())) {
sender.sendRichMessage("<red>You cannot remove yourself. Use <gold>/" + Config.PREFIX + " revoke</gold> instead.</red>");
return Command.SINGLE_SUCCESS;
return this.generateError(ErrorMessage.CANNOT_REMOVE_YOURSELF, ctx.sender());
}

if (!group.getPlayersId().contains(target.getUniqueId())) {
sender.sendRichMessage("<red>This player is not in the group.</red>");
return Command.SINGLE_SUCCESS;
return this.generateError(ErrorMessage.PLAYER_NOT_IN_GROUP, ctx.sender());
}

group.removePlayer(target.getUniqueId());
sender.sendRichMessage("<green><gold><player></gold> has been removed from your group.</green>", Placeholder.component("player", target.displayName()));
ctx.sender().sendRichMessage("<green><gold><player></gold> has been removed from your group.</green>", Placeholder.component("player", target.displayName()));
target.sendRichMessage("<white>You have been removed from the group by <gold><player></gold>.</white>", Placeholder.component("player", player.displayName()));

return Command.SINGLE_SUCCESS;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import fr.korastrip.paperplugin.SharedStats;
import fr.korastrip.paperplugin.commands.group.GroupSubCommand;
import fr.korastrip.paperplugin.enums.ErrorMessage;
import fr.korastrip.paperplugin.model.SharedGroup;
import io.papermc.paper.command.brigadier.CommandSourceStack;
import io.papermc.paper.command.brigadier.Commands;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;

public class Revoke extends GroupSubCommand {
Expand All @@ -21,16 +21,15 @@ public LiteralArgumentBuilder<CommandSourceStack> build() {
return Commands.literal("revoke")
.executes(context -> {

Entity executor = context.getSource().getExecutor();
ContextResult ctx = this.getContext(context);
SharedGroup group = this.plugin.getGroup();

if (!(executor instanceof Player player)) {
if (!(ctx.entity() instanceof Player player)) {
return Command.SINGLE_SUCCESS;
}

if (!player.getUniqueId().equals(group.getOwnerUuid())) {
player.sendRichMessage("<red>You do not have permission to use this command.</red>");
return Command.SINGLE_SUCCESS;
return this.generateError(ErrorMessage.NOT_OWNER, player);
}

group.getOnlinePlayers().forEach(p -> {
Expand Down
Loading
Loading