|
6 | 6 | import com.lovetropics.minigames.common.core.game.behavior.event.GamePlayerEvents;
|
7 | 7 | import com.lovetropics.minigames.common.core.game.player.PlayerRole;
|
8 | 8 | import com.lovetropics.minigames.common.core.game.player.PlayerRoleSelections;
|
| 9 | +import com.lovetropics.minigames.common.core.game.state.statistics.PlayerKey; |
| 10 | +import com.lovetropics.minigames.common.core.game.state.team.GameTeamKey; |
| 11 | +import com.lovetropics.minigames.common.core.game.state.team.TeamState; |
| 12 | +import com.mojang.serialization.Codec; |
9 | 13 | import com.mojang.serialization.MapCodec;
|
10 | 14 | import com.mojang.serialization.codecs.RecordCodecBuilder;
|
| 15 | +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; |
| 16 | +import net.minecraft.server.level.ServerPlayer; |
11 | 17 |
|
12 |
| -public record JoinLateWithRoleBehavior(PlayerRole role) implements IGameBehavior { |
| 18 | +import javax.annotation.Nullable; |
| 19 | +import java.util.Map; |
| 20 | + |
| 21 | +public record JoinLateWithRoleBehavior(PlayerRole role, boolean allowRejoin) implements IGameBehavior { |
13 | 22 | public static final MapCodec<JoinLateWithRoleBehavior> CODEC = RecordCodecBuilder.mapCodec(i -> i.group(
|
14 |
| - PlayerRole.CODEC.fieldOf("role").forGetter(c -> c.role) |
| 23 | + PlayerRole.CODEC.fieldOf("role").forGetter(c -> c.role), |
| 24 | + Codec.BOOL.optionalFieldOf("allow_rejoin", false).forGetter(c -> c.allowRejoin) |
15 | 25 | ).apply(i, JoinLateWithRoleBehavior::new));
|
16 | 26 |
|
17 | 27 | @Override
|
18 | 28 | public void register(final IGamePhase game, final EventRegistrar events) {
|
| 29 | + final TeamState teams = game.instanceState().getOrNull(TeamState.KEY); |
| 30 | + final Map<PlayerKey, OldParticipant> oldParticipants = new Object2ObjectOpenHashMap<>(); |
| 31 | + |
19 | 32 | events.listen(GamePlayerEvents.SELECT_ROLE_ON_JOIN, player -> {
|
| 33 | + // Let the player be a spectator if they really want to |
20 | 34 | final PlayerRoleSelections roleSelections = game.lobby().getPlayers().getRoleSelections();
|
21 | 35 | if (roleSelections.getSelectedRoleFor(player.id()) == PlayerRole.SPECTATOR) {
|
22 | 36 | return PlayerRole.SPECTATOR;
|
23 |
| - } else { |
24 |
| - return role; |
25 | 37 | }
|
| 38 | + |
| 39 | + OldParticipant oldParticipant = oldParticipants.remove(player); |
| 40 | + if (allowRejoin && oldParticipant != null) { |
| 41 | + // Yes, ok - we're not supposed to fetch the player before they join. |
| 42 | + // But this whole player setup process is jank, and it's 5 days to the event. I made this mess, I can make it worse! |
| 43 | + final ServerPlayer playerEntity = game.lobby().getPlayers().getPlayerBy(player.id()); |
| 44 | + if (playerEntity != null && teams != null && oldParticipant.team != null) { |
| 45 | + teams.addPlayerTo(playerEntity, oldParticipant.team); |
| 46 | + } |
| 47 | + return PlayerRole.PARTICIPANT; |
| 48 | + } |
| 49 | + |
| 50 | + return role; |
26 | 51 | });
|
| 52 | + |
| 53 | + if (allowRejoin) { |
| 54 | + events.listen(GamePlayerEvents.SET_ROLE, (player, role, lastRole) -> { |
| 55 | + final PlayerKey playerKey = PlayerKey.from(player); |
| 56 | + if (role == PlayerRole.PARTICIPANT) { |
| 57 | + final GameTeamKey team = teams != null ? teams.getTeamForPlayer(player) : null; |
| 58 | + oldParticipants.put(playerKey, new OldParticipant(team)); |
| 59 | + } else if (lastRole == PlayerRole.PARTICIPANT) { |
| 60 | + oldParticipants.remove(playerKey); |
| 61 | + } |
| 62 | + }); |
| 63 | + } |
| 64 | + } |
| 65 | + |
| 66 | + private record OldParticipant(@Nullable GameTeamKey team) { |
27 | 67 | }
|
28 | 68 | }
|
0 commit comments