Skip to content

Commit

Permalink
Usage of GameStates, Sidebar implementation and game closes when time…
Browse files Browse the repository at this point in the history
… limit is reached
  • Loading branch information
ellieisjelly committed Jan 5, 2024
1 parent 6dc849a commit 5cb3095
Show file tree
Hide file tree
Showing 5 changed files with 118 additions and 14 deletions.
2 changes: 2 additions & 0 deletions src/main/java/me/ellieis/Sabotage/game/GameStates.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
public enum GameStates {
// waiting for players
LOBBY_WAITING,
// countdown before grace period
COUNTDOWN,
// grace period to collect chests
// saboteurs / detectives not picked yet
GRACE_PERIOD,
Expand Down
9 changes: 8 additions & 1 deletion src/main/java/me/ellieis/Sabotage/game/SabotageConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,22 @@ public class SabotageConfig {
private final Identifier map;
private final int countdownTime;
private final int gracePeriod;
private final int timeLimit;
private final PlayerConfig playerConfig;
public static final Codec<SabotageConfig> CODEC = RecordCodecBuilder.create(instance -> {
return instance.group(
Identifier.CODEC.fieldOf("map").forGetter(SabotageConfig::getMap),
Codec.INT.fieldOf("countdown_time").forGetter(SabotageConfig::getCountdownTime),
Codec.INT.fieldOf("grace_period").forGetter(SabotageConfig::getGracePeriod),
Codec.INT.fieldOf("time_limit").forGetter(SabotageConfig::getTimeLimit),
PlayerConfig.CODEC.fieldOf("players").forGetter(SabotageConfig::getPlayerConfig)
).apply(instance, SabotageConfig::new);
});
public SabotageConfig(Identifier map, int countdownTime, int gracePeriod, PlayerConfig playerConfig) {
public SabotageConfig(Identifier map, int countdownTime, int gracePeriod, int timeLimit, PlayerConfig playerConfig) {
this.map = map;
this.countdownTime = countdownTime;
this.gracePeriod = gracePeriod;
this.timeLimit = timeLimit;
this.playerConfig = playerConfig;
}

Expand All @@ -33,6 +36,10 @@ public int getGracePeriod() {
return gracePeriod;
}

public int getTimeLimit() {
return timeLimit;
}

public PlayerConfig getPlayerConfig() {
return this.playerConfig;
}
Expand Down
112 changes: 100 additions & 12 deletions src/main/java/me/ellieis/Sabotage/game/phase/SabotageActive.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@
import com.google.common.collect.ImmutableSet;
import eu.pb4.sidebars.api.Sidebar;
import eu.pb4.sidebars.api.lines.SidebarLine;
import me.ellieis.Sabotage.game.GameStates;
import me.ellieis.Sabotage.game.SabotageConfig;
import me.ellieis.Sabotage.game.map.SabotageMap;
import net.minecraft.network.packet.s2c.play.PositionFlag;
import net.minecraft.screen.ScreenTexts;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.sound.SoundCategory;
Expand All @@ -14,6 +16,7 @@
import net.minecraft.util.Formatting;
import net.minecraft.util.math.Vec3d;
import xyz.nucleoid.plasmid.game.GameActivity;
import xyz.nucleoid.plasmid.game.GameCloseReason;
import xyz.nucleoid.plasmid.game.GameSpace;
import xyz.nucleoid.plasmid.game.common.GlobalWidgets;
import xyz.nucleoid.plasmid.game.common.widget.SidebarWidget;
Expand All @@ -23,10 +26,8 @@
import xyz.nucleoid.plasmid.game.rule.GameRuleType;
import xyz.nucleoid.plasmid.util.PlayerRef;

import java.util.ArrayList;
import java.util.List;
import java.util.Collections;
import java.util.Set;
import java.util.*;
import java.util.concurrent.TimeUnit;

public class SabotageActive {
private final SabotageConfig config;
Expand All @@ -37,6 +38,7 @@ public class SabotageActive {
private boolean countdown = false;
private long startTime;
private GameActivity activity;
private GameStates gameState = GameStates.COUNTDOWN;
private final MutablePlayerSet saboteurs;
private final MutablePlayerSet detectives;
private final MutablePlayerSet innocents;
Expand Down Expand Up @@ -76,6 +78,66 @@ private static void rules(GameActivity activity) {
activity.deny(GameRuleType.CRAFTING);
}

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;
String seconds = Long.toString(timeLeft % 60);
if (seconds.length() == 1) {
// Pad seconds with an extra 0 when only one digit
// If someone knows a better way to do this, be my guest
seconds = "0" + seconds;
}
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)));
}

public void setSidebars() {
this.saboteurSidebar = this.widgets.addSidebar(Text.translatable("gameType.sabotage.sabotage").formatted(Formatting.GOLD));
saboteurSidebar.setPriority(Sidebar.Priority.MEDIUM);
this.detectiveSidebar = this.widgets.addSidebar(Text.translatable("gameType.sabotage.sabotage").formatted(Formatting.GOLD));
detectiveSidebar.setPriority(Sidebar.Priority.MEDIUM);
this.innocentSidebar = this.widgets.addSidebar(Text.translatable("gameType.sabotage.sabotage").formatted(Formatting.GOLD));
innocentSidebar.setPriority(Sidebar.Priority.MEDIUM);

// saboteurs
saboteurSidebar.addLines(ScreenTexts.EMPTY,
Text.translatable("sabotage.sidebar.role", Text.translatable("sabotage.saboteur").formatted(Formatting.RED)),
Text.translatable("sabotage.sidebar.role.desc", Text.translatable("sabotage.innocents").formatted(Formatting.GREEN)),
ScreenTexts.EMPTY,
// this will be where the time left is located
ScreenTexts.EMPTY
);

// detectives
detectiveSidebar.addLines(ScreenTexts.EMPTY,
Text.translatable("sabotage.sidebar.role", Text.translatable("sabotage.detective").formatted(Formatting.DARK_BLUE)),
Text.translatable("sabotage.sidebar.role.desc", Text.translatable("sabotage.saboteurs").formatted(Formatting.RED)),
ScreenTexts.EMPTY,
// this will be where the time left is located
ScreenTexts.EMPTY
);

// innocents
innocentSidebar.addLines(ScreenTexts.EMPTY,
Text.translatable("sabotage.sidebar.role", Text.translatable("sabotage.innocent").formatted(Formatting.GREEN)),
Text.translatable("sabotage.sidebar.role.desc", Text.translatable("sabotage.saboteurs").formatted(Formatting.RED)),
ScreenTexts.EMPTY,
// this will be where the time left is located
ScreenTexts.EMPTY
);

gameSpace.getPlayers().forEach(plr -> {
saboteurSidebar.removePlayer(plr);
detectiveSidebar.removePlayer(plr);
innocentSidebar.removePlayer(plr);
});
saboteurs.forEach(plr -> saboteurSidebar.addPlayer(plr));
detectives.forEach(plr -> detectiveSidebar.addPlayer(plr));
innocents.forEach(plr -> innocentSidebar.addPlayer(plr));
updateSidebars();
}

public void pickRoles() {
PlayerSet plrs = this.gameSpace.getPlayers();
int playerCount = plrs.size();
Expand Down Expand Up @@ -106,12 +168,18 @@ public void pickRoles() {
this.saboteurs.showTitle(Text.translatable("sabotage.role_reveal", Text.translatable("sabotage.saboteur").formatted(Formatting.RED)), 10, 80, 10);
this.saboteurs.playSound(SoundEvents.ENTITY_ILLUSIONER_CAST_SPELL);
this.saboteurs.playSound(SoundEvents.AMBIENT_SOUL_SAND_VALLEY_MOOD.value());
setSidebars();
}
public void Start() {
this.gameStarted = true;
this.gameState = GameStates.ACTIVE;
pickRoles();
gameStartedRules(this.activity);
}

public void End() {
this.gameState = GameStates.ENDED;
rules(this.activity);
}
public static void Open(GameSpace gameSpace, ServerWorld world, SabotageMap map, SabotageConfig config) {
gameSpace.setActivity(activity -> {
SabotageActive game = new SabotageActive(config, gameSpace, map, world);
Expand All @@ -138,15 +206,15 @@ public static void Open(GameSpace gameSpace, ServerWorld world, SabotageMap map,

public void onTick() {
long time = this.world.getTime();
if (!gameStarted) {
if (this.countdown) {
switch(this.gameState) {
case COUNTDOWN -> {
if (time % 20 == 0) {
// second has passed
PlayerSet plrs = this.gameSpace.getPlayers();
int secondsSinceStart = (int) Math.floor((time / 20) - (this.startTime / 20));
int countdownTime = this.config.getCountdownTime();
if (secondsSinceStart >= countdownTime) {
this.countdown = false;
this.gameState = GameStates.GRACE_PERIOD;
plrs.playSound(SoundEvents.BLOCK_RESPAWN_ANCHOR_CHARGE);
plrs.sendMessage(Text.translatable("sabotage.game_start", this.config.getGracePeriod()).formatted(Formatting.GOLD));
} else {
Expand All @@ -162,8 +230,9 @@ public void onTick() {
// Teleport without changing the pitch and yaw
plr.networkHandler.requestTeleport(pos.getX(), pos.getY(), pos.getZ(), plr.getYaw(), plr.getPitch(), flags);
}
} else {
// to-do: implement grace period
}

case GRACE_PERIOD -> {
int secondsSinceStart = (int) Math.floor((time / 20) - (this.startTime / 20)) - this.config.getCountdownTime();
int gracePeriod = this.config.getGracePeriod();
if (secondsSinceStart >= gracePeriod) {
Expand All @@ -173,8 +242,27 @@ public void onTick() {
this.globalSidebar.setLine(SidebarLine.create(0, Text.translatable("sabotage.sidebar.grace_period." + ((secondsLeft == 1) ? "singular" : "plural"), secondsLeft)));
}
}
} else {
// to-do: implement game loop

case ACTIVE -> {
// to-do: implement game loop
if (time % 20 == 0) {
double timePassed = Math.floor((world.getTime() / 20) - (startTime / 20)) - config.getCountdownTime() - config.getGracePeriod();
// second has passed
if (timePassed >= config.getTimeLimit()) {
End();
return;
}
updateSidebars();
}
}

case ENDED -> {
// to-do: countdown before ending
gameSpace.close(GameCloseReason.FINISHED);
}
default -> {
// unknown state, noop.
}
}
}
}
1 change: 1 addition & 0 deletions src/main/resources/data/sabotage/games/sabotage.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"map": "sabotage:lobby",
"countdown_time": 5,
"grace_period": 15,
"time_limit": 15,
"players": {
"min": 1,
"max": 64,
Expand Down
8 changes: 7 additions & 1 deletion src/main/resources/data/sabotage/lang/en_us.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,15 @@
"sabotage.sidebar.countdown": "Get ready!",
"sabotage.sidebar.grace_period.plural": "You have %s seconds left.",
"sabotage.sidebar.grace_period.singular": "You have %s second left.",
"sabotage.sidebar.role": "Your role is: %s",
"sabotage.sidebar.role.desc": "Find and kill all %s",
"sabotage.sidebar.time_left": "Time left: %02d:%02d",
"sabotage.game_start": "The game has started! You have %s seconds to collect items, gear, or hide. Your roles will be selected after the grace period.",
"sabotage.role_reveal": "You are a %s",
"sabotage.innocent": "Innocent",
"sabotage.innocents": "Innocents",
"sabotage.detective": "Detective",
"sabotage.saboteur": "Saboteur"
"sabotage.detectives": "Detectives",
"sabotage.saboteur": "Saboteur",
"sabotage.saboteurs": "Saboteurs"
}

0 comments on commit 5cb3095

Please sign in to comment.