Skip to content

Commit

Permalink
Game end conditions and players can join mid-game
Browse files Browse the repository at this point in the history
  • Loading branch information
ellieisjelly committed Jan 5, 2024
1 parent 084f162 commit 892fd19
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 15 deletions.
3 changes: 2 additions & 1 deletion src/main/java/me/ellieis/Sabotage/game/EndReason.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@
public enum EndReason {
SABOTEUR_WIN,
INNOCENT_WIN,
TIMEOUT
TIMEOUT,
NONE
}
96 changes: 82 additions & 14 deletions src/main/java/me/ellieis/Sabotage/game/phase/SabotageActive.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,10 @@
import xyz.nucleoid.plasmid.game.common.GlobalWidgets;
import xyz.nucleoid.plasmid.game.common.widget.SidebarWidget;
import xyz.nucleoid.plasmid.game.event.GameActivityEvents;
import xyz.nucleoid.plasmid.game.event.GamePlayerEvents;
import xyz.nucleoid.plasmid.game.player.MutablePlayerSet;
import xyz.nucleoid.plasmid.game.player.PlayerOffer;
import xyz.nucleoid.plasmid.game.player.PlayerOfferResult;
import xyz.nucleoid.plasmid.game.player.PlayerSet;
import xyz.nucleoid.plasmid.game.rule.GameRuleType;
import xyz.nucleoid.plasmid.util.PlayerRef;
Expand Down Expand Up @@ -103,6 +106,16 @@ private static String getPlayerNamesInSet(PlayerSet plrs) {
}
return result;
}

private PlayerSet getAlivePlayers() {
MutablePlayerSet plrs = gameSpace.getPlayers().copy(gameSpace.getServer());
plrs.forEach(plr -> {
if (plr.isSpectator()) {
plrs.remove(plr);
}
});
return plrs;
}
public void updateSidebars() {
long timeLeft = (long) Math.abs(Math.floor((world.getTime() / 20) - (startTime / 20)) - config.getCountdownTime() - config.getGracePeriod() - config.getTimeLimit());
long minutes = timeLeft / 60;
Expand All @@ -115,6 +128,7 @@ public void updateSidebars() {
saboteurSidebar.setLine(SidebarLine.create(0, Text.translatable("sabotage.sidebar.time_left", minutes, seconds))); saboteurSidebar.setLine(SidebarLine.create(0, Text.translatable("sabotage.sidebar.time_left", minutes, seconds)));
detectiveSidebar.setLine(SidebarLine.create(0, Text.translatable("sabotage.sidebar.time_left", minutes, seconds)));
innocentSidebar.setLine(SidebarLine.create(0, Text.translatable("sabotage.sidebar.time_left", minutes, seconds)));
globalSidebar.setLine(SidebarLine.create(0, Text.translatable("sabotage.sidebar.time_left", minutes, seconds)));
}

public void setSidebars() {
Expand Down Expand Up @@ -152,6 +166,9 @@ public void setSidebars() {
ScreenTexts.EMPTY
);

// global (spectators and dead players)
globalSidebar.setLine(0, Text.empty());

gameSpace.getPlayers().forEach(plr -> {
saboteurSidebar.removePlayer(plr);
detectiveSidebar.removePlayer(plr);
Expand All @@ -164,7 +181,7 @@ public void setSidebars() {
}

public void pickRoles() {
PlayerSet plrs = gameSpace.getPlayers();
PlayerSet plrs = getAlivePlayers();
int playerCount = plrs.size();
// need to make a new list from .toList to make it mutable
List<ServerPlayerEntity> plrList = new ArrayList<>(plrs.stream().toList());
Expand Down Expand Up @@ -218,12 +235,19 @@ private Text createAttackerKillMessage(ServerPlayerEntity plr, int karma) {
plr.getName().copy().formatted(victimColor),
Text.literal("(" + karma + " karma)").formatted((karma >= 0) ? Formatting.GREEN : Formatting.RED)).formatted(Formatting.YELLOW);
}

public EndReason checkWinCondition() {
if (saboteurs.isEmpty()) {
return EndReason.INNOCENT_WIN;
} else if (innocents.isEmpty() && detectives.isEmpty()) {
return EndReason.SABOTEUR_WIN;
}
return EndReason.NONE;
}
public void Start() {
gameState = GameStates.ACTIVE;
pickRoles();
gameStartedRules(activity);
gameSpace.getPlayers().forEach(plr -> {
getAlivePlayers().forEach(plr -> {
karmaManager.setKarma(plr, 20);
plr.setExperiencePoints(plr.getNextLevelExperience() - 1);
});
Expand All @@ -243,12 +267,15 @@ public static void Open(GameSpace gameSpace, ServerWorld world, SabotageMap map,
game.globalSidebar = game.widgets.addSidebar(Text.translatable("gameType.sabotage.sabotage").formatted(Formatting.GOLD));
game.globalSidebar.setPriority(Sidebar.Priority.LOW);
game.globalSidebar.setLine(SidebarLine.create(0, Text.translatable("sabotage.sidebar.countdown")));

rules(activity);
activity.listen(GameActivityEvents.TICK, game::onTick);
activity.listen(PlayerDeathEvent.EVENT, game::onDeath);
activity.listen(ReplacePlayerChatEvent.EVENT, game::onChat);
PlayerSet plrs = game.gameSpace.getPlayers();
activity.listen(GamePlayerEvents.REMOVE, game::onPlayerRemove);
activity.listen(GamePlayerEvents.OFFER, game::onOffer);

PlayerSet plrs = game.gameSpace.getPlayers();
plrs.showTitle(Text.literal(Integer.toString(game.config.getCountdownTime())).formatted(Formatting.GOLD), 20);
plrs.playSound(SoundEvents.BLOCK_NOTE_BLOCK_HARP.value(), SoundCategory.PLAYERS, 1.0F, 2.0F);
plrs.forEach(plr -> {
Expand All @@ -263,6 +290,7 @@ private boolean onChat(ServerPlayerEntity plr, SignedMessage signedMessage, Mess
detectives.sendMessage(Text.literal("<" + plr.getName().getString() + "> ").formatted(Formatting.YELLOW).append(signedMessage.getContent().copy().formatted(Formatting.RESET)));
innocents.sendMessage(Text.literal("<" + plr.getName().getString() + "> ").formatted(Formatting.YELLOW).append(signedMessage.getContent().copy().formatted(Formatting.RESET)));
saboteurs.sendMessage(Text.literal("<" + plr.getName().getString() + "> ").formatted(getRoleColor(getPlayerRole(plr))).append(signedMessage.getContent().copy().formatted(Formatting.RESET)));
// I have no idea what this is (or what it does), docs said to use it so I'm using it
SentMessage.of(signedMessage);
return true;
}
Expand All @@ -271,10 +299,9 @@ private boolean onChat(ServerPlayerEntity plr, SignedMessage signedMessage, Mess

private ActionResult onDeath(ServerPlayerEntity plr, DamageSource damageSource) {
Entity entityAttacker = damageSource.getAttacker();

Roles plrRole = getPlayerRole(plr);
plr.changeGameMode(GameMode.SPECTATOR);
if (entityAttacker instanceof ServerPlayerEntity attacker) {
Roles plrRole = getPlayerRole(plr);
Roles attackerRole = getPlayerRole(attacker);
// surely there's a better way to do this..
switch(attackerRole) {
Expand Down Expand Up @@ -310,16 +337,57 @@ private ActionResult onDeath(ServerPlayerEntity plr, DamageSource damageSource)
}
}

MutablePlayerSet plrs = new MutablePlayerSet(gameSpace.getServer());
gameSpace.getPlayers().forEach(player -> {
if (!player.equals(entityAttacker)) {
plrs.add(player);
if (plrRole == Roles.SABOTEUR) {
saboteurs.remove(plr);
} else if (plrRole == Roles.DETECTIVE) {
detectives.remove(plr);
} else if (plrRole == Roles.INNOCENT) {
innocents.remove(plr);
}

EndReason endReason = checkWinCondition();
if (endReason != EndReason.NONE) {
End(endReason);
} else {
MutablePlayerSet plrs = gameSpace.getPlayers().copy(gameSpace.getServer());
if (entityAttacker instanceof ServerPlayerEntity attacker) {
plrs.remove(attacker);
}
});
plrs.sendMessage(Text.translatable("sabotage.kill_message", plr.getName(), plrs.size()).formatted(Formatting.YELLOW));

plrs.sendMessage(Text.translatable("sabotage.kill_message", plr.getName(), plrs.size()).formatted(Formatting.YELLOW));
}
return ActionResult.FAIL;
}

private PlayerOfferResult onOffer(PlayerOffer offer) {
ServerPlayerEntity plr = offer.player();
return offer.accept(this.world, new Vec3d(0.0, 66.0, 0.0)).and(() -> {
// player joined after game start, so they're technically dead
plr.changeGameMode(GameMode.SPECTATOR);
});
}

private void onPlayerRemove(ServerPlayerEntity plr) {
Roles role = getPlayerRole(plr);
if (role == Roles.SABOTEUR) {
saboteurs.remove(plr);
} else if (role == Roles.DETECTIVE) {
detectives.remove(plr);
} else if (role == Roles.INNOCENT) {
innocents.remove(plr);
}

if (role != Roles.NONE) {
EndReason endReason = checkWinCondition();
if (endReason != EndReason.NONE) {
End(endReason);
} else {
PlayerSet plrs = getAlivePlayers();
plrs.sendMessage(Text.translatable("sabotage.kill_message", plr.getName(), plrs.size() - 1).formatted(Formatting.YELLOW));
}
}
}

private void awardPlayerKill(ServerPlayerEntity attacker, ServerPlayerEntity plr, Roles plrRole, int innocentKarma, int detectiveKarma, int saboteurKarma) {
// attacker is confirmed innocent or detective
switch(plrRole) {
Expand Down Expand Up @@ -359,7 +427,7 @@ public void onTick() {
}
}
// Make sure players don't move during countdown
for (ServerPlayerEntity plr : gameSpace.getPlayers()) {
for (ServerPlayerEntity plr : getAlivePlayers()) {
Vec3d pos = map.getPlayerSpawns().get(new PlayerRef(plr.getUuid()));
// Set X and Y as relative so it will send 0 change when we pass yaw (yaw - yaw = 0) and pitch
Set<PositionFlag> flags = ImmutableSet.of(PositionFlag.X_ROT, PositionFlag.Y_ROT);
Expand Down Expand Up @@ -391,7 +459,7 @@ public void onTick() {
}
updateSidebars();
double factor = ((timeLimit - timePassed) / timeLimit);
gameSpace.getPlayers().forEach(plr -> {
getAlivePlayers().forEach(plr -> {
plr.setExperiencePoints((int) (plr.getNextLevelExperience() * factor));
});
}
Expand Down

0 comments on commit 892fd19

Please sign in to comment.