Skip to content

Commit

Permalink
Add leave message, add events to modify join and leave messages
Browse files Browse the repository at this point in the history
  • Loading branch information
Patbox committed Dec 15, 2024
1 parent 0035663 commit 2d1831c
Show file tree
Hide file tree
Showing 9 changed files with 156 additions and 12 deletions.
15 changes: 15 additions & 0 deletions src/main/java/xyz/nucleoid/plasmid/api/game/GameTexts.java
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,10 @@ public static MutableText success(ServerPlayerEntity player) {
return Text.translatable("text.plasmid.game.join", player.getDisplayName());
}

public static MutableText successSpectator(ServerPlayerEntity player) {
return Text.translatable("text.plasmid.game.join.spectate", player.getDisplayName());
}

public static MutableText link(GameSpace gameSpace) {
var hover = Text.translatable("text.plasmid.join_link_hover", GameConfig.name(gameSpace.getMetadata().sourceConfig()));

Expand Down Expand Up @@ -166,6 +170,17 @@ public static MutableText participantsOnly() {
}
}

public static final class Leave {
public static MutableText participant(ServerPlayerEntity player) {
return Text.translatable("text.plasmid.game.leave", player.getDisplayName());
}

public static MutableText spectator(ServerPlayerEntity player) {
return Text.translatable("text.plasmid.game.leave.spectate", player.getDisplayName());
}
}


public static final class Kick {
public static MutableText kick(ServerCommandSource source, ServerPlayerEntity target) {
return source.isExecutedByPlayer() ? kickBy(source.getPlayer(), target) : kick(target);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,8 @@ public static GameWaitingLobby addTo(GameActivity activity, WaitingLobbyConfig p
activity.listen(GamePlayerEvents.OFFER, lobby::offerPlayer);
activity.listen(GamePlayerEvents.ADD, lobby::onAddPlayer);
activity.listen(GamePlayerEvents.REMOVE, lobby::onRemovePlayer);
activity.listen(GamePlayerEvents.JOIN_MESSAGE, lobby::onJoinMessage);
activity.listen(GamePlayerEvents.LEAVE_MESSAGE, lobby::onLeaveMessage);
activity.listen(GameWaitingLobbyEvents.BUILD_UI_LAYOUT, lobby::onBuildUiLayout);

activity.listen(GameActivityEvents.STATE_UPDATE, lobby::updateState);
Expand All @@ -118,6 +120,52 @@ public static GameWaitingLobby addTo(GameActivity activity, WaitingLobbyConfig p
return lobby;
}

@Nullable
private Text onJoinMessage(ServerPlayerEntity player, Text currentText, Text defaultText) {
if (currentText == null || (this.playerConfig.thresholdPlayers() == 1 && this.playerConfig.minPlayers() == 1) || this.playerConfig.playerConfig().maxPlayers().isEmpty() || this.gameSpace.getPlayers().spectators().contains(player)) {
return currentText;
}
var count = this.gameSpace.getPlayers().participants().size();
var canStart = count >= this.playerConfig.minPlayers() && (this.isActiveFull(this.gameSpace.getPlayers().size()) || this.isReady(count));

if (canStart) {
return currentText;
}

var required = Math.max(Math.min(this.playerConfig.thresholdPlayers(),
this.gameSpace.getServer().getCurrentPlayerCount()
), this.playerConfig.minPlayers()) - count;

return Text.empty()
.append(currentText)
.append(" ")
.append(Text.translatable("text.plasmid.game.waiting_lobby.players_needed_to_start", required).formatted(Formatting.YELLOW));
}

@Nullable
private Text onLeaveMessage(ServerPlayerEntity player, Text currentText, Text defaultText) {
if (currentText == null || (this.playerConfig.thresholdPlayers() == 1 && this.playerConfig.minPlayers() == 1) || this.playerConfig.playerConfig().maxPlayers().isEmpty() || this.gameSpace.getPlayers().spectators().contains(player)) {
return currentText;
}

var count = this.gameSpace.getPlayers().participants().size() - 1;
var canStart = count >= this.playerConfig.minPlayers() && (this.isActiveFull(this.gameSpace.getPlayers().size() - 1) || this.isReady(count));


if (canStart) {
return currentText;
}

var required = Math.max(Math.min(this.playerConfig.thresholdPlayers(),
this.gameSpace.getServer().getCurrentPlayerCount()
), this.playerConfig.minPlayers()) - count;

return Text.empty()
.append(currentText)
.append(" ")
.append(Text.translatable("text.plasmid.game.waiting_lobby.players_needed_to_start", required).formatted(Formatting.YELLOW));
}

private GameSpaceState.Builder updateState(GameSpaceState.Builder builder) {
return builder.state(this.getTargetCountdownDuration() != -1 ? GameSpaceState.State.STARTING : GameSpaceState.State.WAITING);
}
Expand Down Expand Up @@ -240,9 +288,9 @@ private long getTargetCountdownDuration() {
}

if (this.gameSpace.getPlayers().participants().size() >= this.playerConfig.minPlayers()) {
if (this.isActiveFull()) {
if (this.isActiveFull(this.gameSpace.getPlayers().size())) {
return countdown.fullSeconds() * 20L;
} else if (this.isReady()) {
} else if (this.isReady(this.gameSpace.getPlayers().participants().size())) {
return countdown.readySeconds() * 20L;
}
}
Expand Down Expand Up @@ -317,22 +365,22 @@ private long getRemainingTicks(long time) {
return Math.max(this.countdownStart + this.countdownDuration - time, 0);
}

private boolean isReady() {
return this.gameSpace.getPlayers().participants().size() >= this.playerConfig.thresholdPlayers();
private boolean isReady(int count) {
return count >= this.playerConfig.thresholdPlayers();
}

private boolean isFull() {
return this.limiter.isFull();
}

private boolean isActiveFull() {
private boolean isActiveFull(int count) {
if (this.isFull()) {
return true;
}

// if all players on the server are in this lobby
var server = this.gameSpace.getServer();
if (this.gameSpace.getPlayers().size() >= server.getCurrentPlayerCount()) {
if (count >= server.getCurrentPlayerCount()) {
return true;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.text.Text;
import org.jetbrains.annotations.Nullable;
import xyz.nucleoid.plasmid.api.game.GameSpace;
import xyz.nucleoid.plasmid.api.game.player.JoinAcceptor;
import xyz.nucleoid.plasmid.api.game.player.JoinAcceptorResult;
Expand Down Expand Up @@ -161,6 +162,44 @@ public final class GamePlayerEvents {
}
});

/**
* Called when join message of {@link ServerPlayerEntity} is created.
* Can be used to manipulate it in game.
* This event is invoked after game handles player being added, but before the global join event
*
* Event returns a Text to set it or {@code null} to disable it.
*/
public static final StimulusEvent<JoinMessage> JOIN_MESSAGE = StimulusEvent.create(JoinMessage.class, ctx -> (player, current, defaultText) -> {
try {
for (var listener : ctx.getListeners()) {
current = listener.onJoinMessageCreation(player, current, defaultText);
}
return current;
} catch (Throwable throwable) {
ctx.handleException(throwable);
return defaultText;
}
});

/**
* Called when leave message of {@link ServerPlayerEntity} is created.
* Can be used to manipulate it in game.
* This event is invoked before game handles player being removed
* Event returns a Text to set it or {@code null} to disable it.
*/
public static final StimulusEvent<LeaveMessage> LEAVE_MESSAGE = StimulusEvent.create(LeaveMessage.class, ctx -> (player, current, defaultText) -> {
try {
for (var listener : ctx.getListeners()) {
current = listener.onLeaveMessageCreation(player, current, defaultText);
}
return current;
} catch (Throwable throwable) {
ctx.handleException(throwable);
return defaultText;
}
});

public interface Add {
void onAddPlayer(ServerPlayerEntity player);
}
Expand All @@ -180,4 +219,14 @@ public interface Accept {
public interface Name {
Text onDisplayNameCreation(ServerPlayerEntity player, Text currentText, Text vanillaText);
}

public interface JoinMessage {
@Nullable
Text onJoinMessageCreation(ServerPlayerEntity player, @Nullable Text currentText, Text defaultText);
}

public interface LeaveMessage {
@Nullable
Text onLeaveMessageCreation(ServerPlayerEntity player, @Nullable Text currentText, Text defaultText);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -225,20 +225,36 @@ void onAddPlayer(ServerPlayerEntity player) {

this.lifecycle.onAddPlayer(this, player);

var joinMessage = GameTexts.Join.success(player)
.formatted(Formatting.YELLOW);
this.players.sendMessage(joinMessage);

var spectator = this.players.spectators().contains(player);
Text joinMessage = (spectator ? GameTexts.Join.successSpectator(player) : GameTexts.Join.success(player)).formatted(Formatting.YELLOW);
joinMessage = this.state.invoker(GamePlayerEvents.JOIN_MESSAGE).onJoinMessageCreation(player, joinMessage, joinMessage);
GameEvents.PLAYER_JOIN.invoker().onPlayerJoin(this, player);

if (joinMessage != null) {
this.players.sendMessage(joinMessage);
}
}

void onPlayerRemove(ServerPlayerEntity player) {
var spectator = this.players.spectators().contains(player);
Text leaveMessage = (spectator ? GameTexts.Leave.spectator(player) : GameTexts.Leave.participant(player)).formatted(Formatting.YELLOW);
leaveMessage = this.state.invoker(GamePlayerEvents.LEAVE_MESSAGE).onLeaveMessageCreation(player, leaveMessage, leaveMessage);

this.state.invoker(GamePlayerEvents.LEAVE).onRemovePlayer(player);
this.state.invoker(GamePlayerEvents.REMOVE).onRemovePlayer(player);

this.lifecycle.onRemovePlayer(this, player);

GameEvents.PLAYER_LEFT.invoker().onPlayerLeft(this, player);
this.manager.removePlayerFromGameSpace(this, player);

if (leaveMessage != null) {
for (var receiver : this.players) {
if (receiver != player) {
receiver.sendMessage(leaveMessage);
}
}
}
}

void onAddWorld(RuntimeWorldHandle worldHandle) {
Expand Down
4 changes: 4 additions & 0 deletions src/main/resources/data/plasmid/lang/en_us.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,12 @@
"text.plasmid.game.portal.disconnect.entity": "Disconnected '%1$s' from all portals",
"text.plasmid.game.portal.player_count": "%s players",
"text.plasmid.game.join": "%s has joined the game lobby!",
"text.plasmid.game.join.spectate": "%s is spectating the game lobby!",
"text.plasmid.game.join.error": "An unexpected exception occurred while joining game!",
"text.plasmid.game.join.no_game_open": "No games are open!",
"text.plasmid.game.join.party.error": "%s players were unable to join this game!",
"text.plasmid.game.leave": "%s has left the game lobby!",
"text.plasmid.game.leave.spectate": "%s is no longer spectating the game lobby!",
"text.plasmid.game.kick": "%s was kicked from the game!",
"text.plasmid.game.kick.by": "%s was kicked from the game by %s!",
"text.plasmid.game.list": "Registered games:",
Expand All @@ -60,6 +63,7 @@
"text.plasmid.game.waiting_lobby.bar.waiting": "Waiting for players...",
"text.plasmid.game.waiting_lobby.leave_game": "Leave Game",
"text.plasmid.game.waiting_lobby.sidebar.players": "Players: %s%s%s",
"text.plasmid.game.waiting_lobby.players_needed_to_start": "%s more player(s) is needed to start!",
"text.plasmid.join_result.already_joined": "You have already joined this game!",
"text.plasmid.join_result.error": "An unexpected error occurred while adding you to this game!",
"text.plasmid.join_result.generic_error": "You cannot join this game!",
Expand Down
3 changes: 3 additions & 0 deletions src/testmod/java/xyz/nucleoid/plasmid/test/JankGame.java
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,9 @@ public static GameOpenProcedure open(GameOpenContext<TestConfig> context) {
return EventResult.DENY;
});

activity.listen(GamePlayerEvents.JOIN_MESSAGE, (player, text, text2) -> null);
activity.listen(GamePlayerEvents.LEAVE_MESSAGE, (player, text, text2) -> null);

activity.listen(GameActivityEvents.REQUEST_START, () -> startGame(activity.getGameSpace()));

});
Expand Down
4 changes: 3 additions & 1 deletion src/testmod/java/xyz/nucleoid/plasmid/test/TestConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,14 @@
import net.minecraft.registry.RegistryCodecs;
import net.minecraft.registry.RegistryKeys;
import net.minecraft.registry.entry.RegistryEntryList;
import xyz.nucleoid.plasmid.api.game.common.config.WaitingLobbyConfig;

import java.util.Optional;

public record TestConfig(int integer, BlockState state, Optional<RegistryEntryList<Item>> items, int teamCount) {
public record TestConfig(int integer, WaitingLobbyConfig players, BlockState state, Optional<RegistryEntryList<Item>> items, int teamCount) {
public static final MapCodec<TestConfig> CODEC = RecordCodecBuilder.mapCodec(i -> i.group(
Codec.INT.optionalFieldOf("integer", 0).forGetter(TestConfig::integer),
WaitingLobbyConfig.CODEC.optionalFieldOf("players", new WaitingLobbyConfig(1, 99)).forGetter(TestConfig::players),
BlockState.CODEC.optionalFieldOf("state", Blocks.BLUE_STAINED_GLASS.getDefaultState()).forGetter(TestConfig::state),
RegistryCodecs.entryList(RegistryKeys.ITEM).optionalFieldOf("items").forGetter(TestConfig::items),
Codec.INT.optionalFieldOf("team_count", 0).forGetter(TestConfig::teamCount)
Expand Down
2 changes: 1 addition & 1 deletion src/testmod/java/xyz/nucleoid/plasmid/test/TestGame.java
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ public static GameOpenProcedure open(GameOpenContext<TestConfig> context) {
})
);

GameWaitingLobby.addTo(activity, new WaitingLobbyConfig(1, 99));
GameWaitingLobby.addTo(activity, context.config().players());

int teamCount = context.config().teamCount();

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "testmod:test",
"players": {
"max": 16,
"min": 2
}
}

0 comments on commit 2d1831c

Please sign in to comment.