Skip to content

Commit

Permalink
feat: start adding event system, small lang fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
ZakShearman committed Mar 10, 2024
1 parent 8a43dce commit 2b289da
Show file tree
Hide file tree
Showing 21 changed files with 253 additions and 52 deletions.
2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ dependencies {
annotationProcessor("com.velocitypowered:velocity-api:3.2.0-SNAPSHOT")
implementation("net.kyori:adventure-text-minimessage:4.14.0")

implementation("dev.emortal.api:common-proto-sdk:cfb6fa4")
implementation("dev.emortal.api:common-proto-sdk:1797f88")
implementation("dev.emortal.api:agones-sdk:1.0.7")
implementation("dev.emortal.api:live-config-parser:8f566b9")
implementation("dev.emortal.api:module-system:1.0.0")
Expand Down
42 changes: 37 additions & 5 deletions src/main/java/dev/emortal/velocity/lang/ChatMessages.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import com.velocitypowered.api.permission.Tristate;
import dev.emortal.api.model.mcplayer.OnlinePlayer;
import dev.emortal.api.model.party.EventData;
import dev.emortal.api.utils.ProtoTimestampConverter;
import dev.emortal.velocity.misc.command.ListCommand;
import net.kyori.adventure.audience.Audience;
import net.kyori.adventure.text.Component;
Expand All @@ -14,13 +16,20 @@
import net.kyori.adventure.text.minimessage.MiniMessage;
import org.jetbrains.annotations.NotNull;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

public interface ChatMessages {
SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");

Args0 GENERIC_ERROR = () -> red("An error occurred");
Args0 ERROR_NO_SKIN = () -> red("You don't have a skin. This doesn't work???");
Args0 ERROR_INVALID_TIME_FORMAT = () -> red("Invalid time format. Must be in ISO-8601 format (yyyy-MM-ddTHH:mm:ss e.g. 2022-01-01T12:00:00)");
Args1<String> ERROR_INVALID_TIME_FORMAT_ARG = arg -> red("Invalid time format at %s. Must be in ISO-8601 format (yyyy-MM-ddTHH:mm:ss e.g. 2022-01-01T12:00:00)".formatted(arg));
Args1<String> ERROR_TIME_IN_PAST_ARG = arg -> red("Invalid time. %s is in the past".formatted(arg));

Args1<String> PLAYER_NOT_FOUND = username -> red("Player " + username + " not found");
Args1<String> PLAYER_NOT_ONLINE = username -> red("Player " + username + " is not online");
Expand Down Expand Up @@ -113,19 +122,42 @@ public interface ChatMessages {
Args1<String> ERROR_PLAYER_INVITED_TO_PARTY = username -> red(username + " has already been invited to your party");
Args1<String> ERROR_PLAYER_IN_THIS_PARTY = username -> red(username + " is already in the party");
Args0 ERROR_YOU_NOT_INVITED_TO_PARTY = () -> red("You are not invited to this party");
Args0 ERROR_ALREADY_IN_PARTY = () -> miniMessage("<red>You are already in a party. Use <click:run_command:/party leave>/party leave</click> to leave");
Args0 ERROR_ALREADY_IN_SAME_PARTY = () -> miniMessage("<red>You are already in the same party.");
Args0 ERROR_CANNOT_KICK_LEADER = () -> red("You cannot kick the party leader");
Args1<String> ERROR_PLAYER_NOT_IN_PARTY = username -> red(username + " is not in your party");
Args0 ERROR_CANNOT_LEAVE_AS_LEADER = () -> Component.text()
.append(red("You are the leader of the party")).appendNewline()
.append(red("Use '/party disband' to disband the party or '/party leader <player>' to transfer leadership"))
.build();
Args0 ERROR_YOU_NOT_IN_PARTY = () -> red("You are not in a party");

// /party broadcast
Args0 PARTY_BROADCAST_PARTY_CLOSED = () -> miniMessage("<red>Your party must be open to broadcast a message. Use <click:run_command:/party open><u>/party open</u></click> to open your party");
Args1<String> PARTY_BROADCAST_MESSAGE = leaderUsername -> miniMessage("<green>" + leaderUsername + " is hosting a party. <click:run_command:/party join " + leaderUsername + ">Click <u>here</u> to join!</click>");

// Event
Args0 ERROR_EVENT_INVALID_ID = () -> red("Invalid event ID. Must satisfy the following: (3 <= id.length() <= 16)");
Args0 EVENT_CREATE_USAGE = () -> red("""
"Usage: /event create <id> <showTime> <startTime>
showTime and startTime must be in ISO-8601 format (yyyy-MM-ddTHH:mm:ss e.g. 2022-01-01T12:00:00)""");
Args1<EventData> EVENT_VALUE = event -> miniMessage("""
<light_purple>ID: </light_purple>%s
<light_purple>Owner ID: </light_purple>%s
<light_purple>Owner Username: </light_purple>%s
<light_purple>Display At: </light_purple>%s
<light_purple>Start At: </light_purple>%s
<light_purple>---""".formatted(event.getId(), event.getOwnerId(), event.getOwnerUsername(),
DATE_FORMAT.format(Date.from(ProtoTimestampConverter.fromProto(event.getDisplayTime()))),
DATE_FORMAT.format(Date.from(ProtoTimestampConverter.fromProto(event.getStartTime())))));
Args1<List<EventData>> EVENT_DATA_LIST = events -> {
TextComponent.Builder builder = Component.text()
.append(Component.text("Events (" + events.size() + "):", NamedTextColor.LIGHT_PURPLE)).appendNewline();

for (EventData event : events) {
builder.append(Component.text(" " + event.getId(), NamedTextColor.LIGHT_PURPLE).hoverEvent(HoverEvent.showText(EVENT_VALUE.get(event)))).appendNewline();
}

return builder.build();
};
Args1<EventData> EVENT_CREATED = event -> green("Event created:").appendNewline().append(EVENT_VALUE.get(event));
Args1<String> ERROR_EVENT_ALREADY_EXISTS = id -> red("And event with the ID '" + id + "' already exists");

Args1<String> ROLE_CREATED = role -> green("Role " + role + " created");
Args4<String, Integer, Integer, Component> ROLE_DESCRIPTION = (id, priority, permissions, displayName) ->
Component.text().color(NamedTextColor.LIGHT_PURPLE)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,17 @@
import com.velocitypowered.api.event.connection.PostLoginEvent;
import com.velocitypowered.api.event.player.ServerConnectedEvent;
import com.velocitypowered.api.proxy.Player;
import com.velocitypowered.api.util.GameProfile;
import dev.emortal.api.message.common.PlayerConnectMessage;
import dev.emortal.api.message.common.PlayerDisconnectMessage;
import dev.emortal.api.message.common.PlayerSwitchServerMessage;
import dev.emortal.api.model.common.PlayerSkin;
import dev.emortal.api.utils.kafka.FriendlyKafkaProducer;
import dev.emortal.velocity.Environment;
import dev.emortal.velocity.utils.SkinUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;

final class PlayerUpdateListener {
private static final String KAFKA_CONNECTIONS_TOPIC = "mc-connections";
private static final Logger LOGGER = LoggerFactory.getLogger(PlayerUpdateListener.class);
Expand All @@ -34,7 +31,7 @@ final class PlayerUpdateListener {
private void onPlayerLogin(@NotNull PostLoginEvent event) {
Player player = event.getPlayer();

PlayerSkin skin = this.getSkin(player);
PlayerSkin skin = SkinUtils.getProtoSkin(player);
if (skin == null) {
LOGGER.warn("Player {} has no skin", player.getUsername());
}
Expand All @@ -49,21 +46,6 @@ private void onPlayerLogin(@NotNull PostLoginEvent event) {
this.kafkaProducer.produceAndForget(KAFKA_CONNECTIONS_TOPIC, messageBuilder.build());
}

private @Nullable PlayerSkin getSkin(@NotNull Player player) {
List<GameProfile.Property> properties = player.getGameProfileProperties();

for (GameProfile.Property property : properties) {
if (!property.getName().equals("textures")) continue;

return PlayerSkin.newBuilder()
.setTexture(property.getValue())
.setSignature(property.getSignature())
.build();
}

return null;
}

@Subscribe
private void onPlayerDisconnect(@NotNull DisconnectEvent event) {
Player player = event.getPlayer();
Expand Down
4 changes: 3 additions & 1 deletion src/main/java/dev/emortal/velocity/party/PartyModule.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
import dev.emortal.velocity.messaging.MessagingModule;
import dev.emortal.velocity.module.VelocityModule;
import dev.emortal.velocity.module.VelocityModuleEnvironment;
import dev.emortal.velocity.party.commands.PartyCommand;
import dev.emortal.velocity.party.commands.event.EventCommand;
import dev.emortal.velocity.party.commands.party.PartyCommand;
import dev.emortal.velocity.party.notifier.ChatPartyUpdateNotifier;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
Expand All @@ -34,6 +35,7 @@ public boolean onLoad() {
new PartyUpdateListener(cache, super.adapters().playerProvider(), new ChatPartyUpdateNotifier(super.adapters().playerProvider()), messaging);

super.registerCommand(new PartyCommand(service, super.playerResolver(), super.adapters().commandManager().usernameSuggesters(), messaging.getKafkaProducer()));
super.registerCommand(new EventCommand(service));
return true;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package dev.emortal.velocity.party.commands.event;

import com.mojang.brigadier.arguments.StringArgumentType;
import com.mojang.brigadier.context.CommandContext;
import com.velocitypowered.api.command.CommandSource;
import dev.emortal.api.service.party.PartyService;
import dev.emortal.velocity.command.EmortalCommand;
import dev.emortal.velocity.lang.ChatMessages;
import dev.emortal.velocity.party.commands.event.subs.CreateSub;
import dev.emortal.velocity.party.commands.event.subs.ListSub;

public class EventCommand extends EmortalCommand {

public EventCommand(PartyService partyService) {
super("event");

super.setCondition(source -> source.hasPermission("command.event"));

// List
ListSub listSub = new ListSub(partyService);
super.setDefaultExecutor(listSub);
super.addSyntax(listSub, literal("list"));

// Create
super.addSyntax(this::createUsage, literal("create"));
super.addSyntax(this::createUsage, literal("create"), literal("help"));
super.addSyntax(new CreateSub(partyService), literal("create"), argument("id", StringArgumentType.word()),
argument("showTime", StringArgumentType.word()), argument("startTime", StringArgumentType.word()));
}

private void createUsage(CommandContext<CommandSource> context) {
ChatMessages.EVENT_CREATE_USAGE.send(context.getSource());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
package dev.emortal.velocity.party.commands.event.subs;

import com.velocitypowered.api.command.CommandSource;
import com.velocitypowered.api.proxy.Player;
import dev.emortal.api.model.common.PlayerSkin;
import dev.emortal.api.model.party.EventData;
import dev.emortal.api.service.party.PartyService;
import dev.emortal.velocity.command.ArgumentProvider;
import dev.emortal.velocity.command.EmortalCommandExecutor;
import dev.emortal.velocity.lang.ChatMessages;
import dev.emortal.velocity.utils.SkinUtils;
import io.grpc.Status;
import io.grpc.StatusRuntimeException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;

public class CreateSub implements EmortalCommandExecutor {
private static final @NotNull Logger LOGGER = LoggerFactory.getLogger(CreateSub.class);

private final @NotNull PartyService partyService;

public CreateSub(@NotNull PartyService partyService) {
this.partyService = partyService;
}

@Override
public void execute(@NotNull CommandSource source, @NotNull ArgumentProvider arguments) {
if (!(source instanceof Player player)) return;

String id = arguments.getArgument("id", String.class);
if (id.length() < 3 || id.length() > 32) {
ChatMessages.ERROR_EVENT_INVALID_ID.send(source);
return;
}

PlayerSkin skin = SkinUtils.getProtoSkin(player);
if (skin == null) {
ChatMessages.ERROR_NO_SKIN.send(player);
return;
}

String showTimeStr = arguments.getArgument("showTime", String.class);
Instant showTime;
try {
showTime = this.parseStrTime(showTimeStr);
} catch (DateTimeParseException unused) {
ChatMessages.ERROR_INVALID_TIME_FORMAT_ARG.send(player, "showTime");
return;
}

String startTimeStr = arguments.getArgument("startTime", String.class);
Instant startTime;
try {
startTime = this.parseStrTime(startTimeStr);
} catch (DateTimeParseException unused) {
ChatMessages.ERROR_INVALID_TIME_FORMAT_ARG.send(player, "startTime");
return;
}

Instant timeNow = Instant.now().minusSeconds(60);
if (timeNow.isAfter(startTime)) {
ChatMessages.ERROR_TIME_IN_PAST_ARG.send(player, "startTime");
return;
}

EventData createdEvent;
try {
createdEvent = this.partyService.createEvent(id, player.getUniqueId(), player.getUsername(), skin, showTime, startTime);
} catch (StatusRuntimeException ex) {
if (ex.getStatus().getCode() == Status.Code.ALREADY_EXISTS) {
ChatMessages.ERROR_EVENT_ALREADY_EXISTS.send(player, id);
return;
}

ChatMessages.GENERIC_ERROR.send(player);
LOGGER.error("Failed to create event", ex);
return;
}

ChatMessages.EVENT_CREATED.send(player, createdEvent);
}

private Instant parseStrTime(@Nullable String input) {
if (input == null) return null;
if (input.equals("now")) return Instant.now();

return LocalDateTime.parse(input, DateTimeFormatter.ISO_LOCAL_DATE_TIME)
.atZone(ZoneId.of("Europe/London"))
.toInstant();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package dev.emortal.velocity.party.commands.event.subs;

import com.velocitypowered.api.command.CommandSource;
import dev.emortal.api.service.party.PartyService;
import dev.emortal.velocity.command.ArgumentProvider;
import dev.emortal.velocity.command.EmortalCommandExecutor;
import dev.emortal.velocity.lang.ChatMessages;
import org.jetbrains.annotations.NotNull;

public class ListSub implements EmortalCommandExecutor {
private final @NotNull PartyService partyService;

public ListSub(@NotNull PartyService partyService) {
this.partyService = partyService;
}

@Override
public void execute(@NotNull CommandSource source, @NotNull ArgumentProvider arguments) {
ChatMessages.EVENT_DATA_LIST.send(source, this.partyService.listEvents());
}
}
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
package dev.emortal.velocity.party.commands;
package dev.emortal.velocity.party.commands.party;

import com.mojang.brigadier.arguments.StringArgumentType;
import dev.emortal.api.service.party.PartyService;
import dev.emortal.api.utils.kafka.FriendlyKafkaProducer;
import dev.emortal.velocity.command.EmortalCommand;
import dev.emortal.velocity.lang.ChatMessages;
import dev.emortal.velocity.party.commands.subs.PartyBroadcastSub;
import dev.emortal.velocity.party.commands.subs.PartyCloseSub;
import dev.emortal.velocity.party.commands.subs.PartyDisbandSub;
import dev.emortal.velocity.party.commands.subs.PartyInviteSub;
import dev.emortal.velocity.party.commands.subs.PartyJoinSub;
import dev.emortal.velocity.party.commands.subs.PartyKickSub;
import dev.emortal.velocity.party.commands.subs.PartyLeaderSub;
import dev.emortal.velocity.party.commands.subs.PartyLeaveSub;
import dev.emortal.velocity.party.commands.subs.PartyListSub;
import dev.emortal.velocity.party.commands.subs.PartyOpenSub;
import dev.emortal.velocity.party.commands.subs.PartySettingsSub;
import dev.emortal.velocity.party.commands.party.subs.PartyBroadcastSub;
import dev.emortal.velocity.party.commands.party.subs.PartyCloseSub;
import dev.emortal.velocity.party.commands.party.subs.PartyDisbandSub;
import dev.emortal.velocity.party.commands.party.subs.PartyInviteSub;
import dev.emortal.velocity.party.commands.party.subs.PartyJoinSub;
import dev.emortal.velocity.party.commands.party.subs.PartyKickSub;
import dev.emortal.velocity.party.commands.party.subs.PartyLeaderSub;
import dev.emortal.velocity.party.commands.party.subs.PartyLeaveSub;
import dev.emortal.velocity.party.commands.party.subs.PartyListSub;
import dev.emortal.velocity.party.commands.party.subs.PartyOpenSub;
import dev.emortal.velocity.party.commands.party.subs.PartySettingsSub;
import dev.emortal.velocity.player.resolver.PlayerResolver;
import dev.emortal.velocity.player.suggestions.UsernameSuggesterProvider;
import dev.emortal.velocity.utils.CommandUtils;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package dev.emortal.velocity.party.commands.subs;
package dev.emortal.velocity.party.commands.party.subs;

import com.velocitypowered.api.command.CommandSource;
import com.velocitypowered.api.proxy.Player;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package dev.emortal.velocity.party.commands.subs;
package dev.emortal.velocity.party.commands.party.subs;

import com.velocitypowered.api.command.CommandSource;
import com.velocitypowered.api.proxy.Player;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package dev.emortal.velocity.party.commands.subs;
package dev.emortal.velocity.party.commands.party.subs;

import com.velocitypowered.api.command.CommandSource;
import com.velocitypowered.api.proxy.Player;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package dev.emortal.velocity.party.commands.subs;
package dev.emortal.velocity.party.commands.party.subs;

import com.velocitypowered.api.command.CommandSource;
import com.velocitypowered.api.proxy.Player;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package dev.emortal.velocity.party.commands.subs;
package dev.emortal.velocity.party.commands.party.subs;

import com.velocitypowered.api.command.CommandSource;
import com.velocitypowered.api.proxy.Player;
Expand Down Expand Up @@ -63,7 +63,7 @@ public void execute(@NotNull CommandSource source, @NotNull ArgumentProvider arg
case JoinPartyResult.Success ignored -> ChatMessages.YOU_JOINED_PARTY.send(player, target.username());
case JoinPartyResult.Error error -> {
switch (error) {
case ALREADY_IN_PARTY -> ChatMessages.ERROR_ALREADY_IN_PARTY.send(player);
case ALREADY_IN_SAME_PARTY -> ChatMessages.ERROR_ALREADY_IN_SAME_PARTY.send(player);
case NOT_INVITED -> ChatMessages.ERROR_YOU_NOT_INVITED_TO_PARTY.send(player);
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package dev.emortal.velocity.party.commands.subs;
package dev.emortal.velocity.party.commands.party.subs;

import com.velocitypowered.api.command.CommandSource;
import com.velocitypowered.api.proxy.Player;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package dev.emortal.velocity.party.commands.subs;
package dev.emortal.velocity.party.commands.party.subs;

import com.velocitypowered.api.command.CommandSource;
import com.velocitypowered.api.proxy.Player;
Expand Down
Loading

0 comments on commit 2b289da

Please sign in to comment.