From 36f7ce9a02290fcd937b6b09b847a88e0b08bc0c Mon Sep 17 00:00:00 2001 From: haykam821 <24855774+haykam821@users.noreply.github.com> Date: Mon, 24 Jun 2024 00:56:34 -0400 Subject: [PATCH] Add teams --- .../game/BeaconBreakersConfig.java | 12 +- .../game/BeaconBreakersSidebar.java | 6 +- .../game/phase/BeaconBreakersActivePhase.java | 172 +++++++++--------- .../phase/BeaconBreakersWaitingPhase.java | 11 +- .../game/player/PlayerEntry.java | 55 +++--- .../game/player/team/MultipleTeamEntry.java | 113 ++++++++++++ .../game/player/team/SingleTeamEntry.java | 69 +++++++ .../game/player/team/TeamEntry.java | 96 ++++++++++ .../amplified_beacon_breakers_2_teams.json | 29 +++ .../amplified_beacon_breakers_4_teams.json | 43 +++++ ...eacon_breakers_keep_inventory_2_teams.json | 30 +++ ...eacon_breakers_keep_inventory_4_teams.json | 44 +++++ ...mplified_beacon_breakers_tiny_2_teams.json | 32 ++++ ...mplified_beacon_breakers_tiny_4_teams.json | 46 +++++ .../games/end_beacon_breakers_2_teams.json | 28 +++ .../games/end_beacon_breakers_4_teams.json | 42 +++++ ...eacon_breakers_keep_inventory_2_teams.json | 29 +++ ...eacon_breakers_keep_inventory_4_teams.json | 43 +++++ .../end_beacon_breakers_tiny_2_teams.json | 31 ++++ .../end_beacon_breakers_tiny_4_teams.json | 45 +++++ .../games/nether_beacon_breakers_2_teams.json | 28 +++ .../games/nether_beacon_breakers_4_teams.json | 42 +++++ ...eacon_breakers_keep_inventory_2_teams.json | 29 +++ ...eacon_breakers_keep_inventory_4_teams.json | 43 +++++ .../nether_beacon_breakers_tiny_2_teams.json | 31 ++++ .../nether_beacon_breakers_tiny_4_teams.json | 45 +++++ .../standard_beacon_breakers_2_teams.json | 29 +++ .../standard_beacon_breakers_4_teams.json | 43 +++++ ...eacon_breakers_keep_inventory_2_teams.json | 30 +++ ...eacon_breakers_keep_inventory_4_teams.json | 44 +++++ ...standard_beacon_breakers_tiny_2_teams.json | 32 ++++ ...standard_beacon_breakers_tiny_4_teams.json | 46 +++++ .../data/beaconbreakers/lang/en_us.json | 42 +++++ 33 files changed, 1338 insertions(+), 122 deletions(-) create mode 100644 src/main/java/io/github/haykam821/beaconbreakers/game/player/team/MultipleTeamEntry.java create mode 100644 src/main/java/io/github/haykam821/beaconbreakers/game/player/team/SingleTeamEntry.java create mode 100644 src/main/java/io/github/haykam821/beaconbreakers/game/player/team/TeamEntry.java create mode 100644 src/main/resources/data/beaconbreakers/games/amplified_beacon_breakers_2_teams.json create mode 100644 src/main/resources/data/beaconbreakers/games/amplified_beacon_breakers_4_teams.json create mode 100644 src/main/resources/data/beaconbreakers/games/amplified_beacon_breakers_keep_inventory_2_teams.json create mode 100644 src/main/resources/data/beaconbreakers/games/amplified_beacon_breakers_keep_inventory_4_teams.json create mode 100644 src/main/resources/data/beaconbreakers/games/amplified_beacon_breakers_tiny_2_teams.json create mode 100644 src/main/resources/data/beaconbreakers/games/amplified_beacon_breakers_tiny_4_teams.json create mode 100644 src/main/resources/data/beaconbreakers/games/end_beacon_breakers_2_teams.json create mode 100644 src/main/resources/data/beaconbreakers/games/end_beacon_breakers_4_teams.json create mode 100644 src/main/resources/data/beaconbreakers/games/end_beacon_breakers_keep_inventory_2_teams.json create mode 100644 src/main/resources/data/beaconbreakers/games/end_beacon_breakers_keep_inventory_4_teams.json create mode 100644 src/main/resources/data/beaconbreakers/games/end_beacon_breakers_tiny_2_teams.json create mode 100644 src/main/resources/data/beaconbreakers/games/end_beacon_breakers_tiny_4_teams.json create mode 100644 src/main/resources/data/beaconbreakers/games/nether_beacon_breakers_2_teams.json create mode 100644 src/main/resources/data/beaconbreakers/games/nether_beacon_breakers_4_teams.json create mode 100644 src/main/resources/data/beaconbreakers/games/nether_beacon_breakers_keep_inventory_2_teams.json create mode 100644 src/main/resources/data/beaconbreakers/games/nether_beacon_breakers_keep_inventory_4_teams.json create mode 100644 src/main/resources/data/beaconbreakers/games/nether_beacon_breakers_tiny_2_teams.json create mode 100644 src/main/resources/data/beaconbreakers/games/nether_beacon_breakers_tiny_4_teams.json create mode 100644 src/main/resources/data/beaconbreakers/games/standard_beacon_breakers_2_teams.json create mode 100644 src/main/resources/data/beaconbreakers/games/standard_beacon_breakers_4_teams.json create mode 100644 src/main/resources/data/beaconbreakers/games/standard_beacon_breakers_keep_inventory_2_teams.json create mode 100644 src/main/resources/data/beaconbreakers/games/standard_beacon_breakers_keep_inventory_4_teams.json create mode 100644 src/main/resources/data/beaconbreakers/games/standard_beacon_breakers_tiny_2_teams.json create mode 100644 src/main/resources/data/beaconbreakers/games/standard_beacon_breakers_tiny_4_teams.json diff --git a/src/main/java/io/github/haykam821/beaconbreakers/game/BeaconBreakersConfig.java b/src/main/java/io/github/haykam821/beaconbreakers/game/BeaconBreakersConfig.java index 08a1fe4..f616767 100644 --- a/src/main/java/io/github/haykam821/beaconbreakers/game/BeaconBreakersConfig.java +++ b/src/main/java/io/github/haykam821/beaconbreakers/game/BeaconBreakersConfig.java @@ -1,5 +1,7 @@ package io.github.haykam821.beaconbreakers.game; +import java.util.Optional; + import com.mojang.serialization.Codec; import com.mojang.serialization.codecs.RecordCodecBuilder; @@ -8,12 +10,14 @@ import net.minecraft.util.math.intprovider.ConstantIntProvider; import net.minecraft.util.math.intprovider.IntProvider; import xyz.nucleoid.plasmid.game.common.config.PlayerConfig; +import xyz.nucleoid.plasmid.game.common.team.GameTeamList; public class BeaconBreakersConfig { public static final Codec CODEC = RecordCodecBuilder.create(instance -> { return instance.group( PlayerConfig.CODEC.fieldOf("players").forGetter(BeaconBreakersConfig::getPlayerConfig), BeaconBreakersMapConfig.CODEC.fieldOf("map").forGetter(BeaconBreakersConfig::getMapConfig), + GameTeamList.CODEC.optionalFieldOf("teams").forGetter(BeaconBreakersConfig::getTeams), IntProvider.NON_NEGATIVE_CODEC.optionalFieldOf("ticks_until_close", ConstantIntProvider.create(SharedConstants.TICKS_PER_SECOND * 10)).forGetter(BeaconBreakersConfig::getTicksUntilClose), Codec.INT.optionalFieldOf("invulnerability", 2 * 60 * 20).forGetter(BeaconBreakersConfig::getInvulnerability), Codec.BOOL.optionalFieldOf("keep_inventory", false).forGetter(BeaconBreakersConfig::shouldKeepInventory), @@ -23,14 +27,16 @@ public class BeaconBreakersConfig { private final PlayerConfig playerConfig; private final BeaconBreakersMapConfig mapConfig; + private final Optional teams; private final IntProvider ticksUntilClose; private final int invulnerability; private final boolean keepInventory; private final boolean allowSelfBreaking; - public BeaconBreakersConfig(PlayerConfig playerConfig, BeaconBreakersMapConfig mapConfig, IntProvider ticksUntilClose, int invulnerability, boolean keepInventory, boolean allowSelfBreaking) { + public BeaconBreakersConfig(PlayerConfig playerConfig, BeaconBreakersMapConfig mapConfig, Optional teams, IntProvider ticksUntilClose, int invulnerability, boolean keepInventory, boolean allowSelfBreaking) { this.playerConfig = playerConfig; this.mapConfig = mapConfig; + this.teams = teams; this.ticksUntilClose = ticksUntilClose; this.invulnerability = invulnerability; this.keepInventory = keepInventory; @@ -45,6 +51,10 @@ public BeaconBreakersMapConfig getMapConfig() { return this.mapConfig; } + public Optional getTeams() { + return this.teams; + } + public IntProvider getTicksUntilClose() { return this.ticksUntilClose; } diff --git a/src/main/java/io/github/haykam821/beaconbreakers/game/BeaconBreakersSidebar.java b/src/main/java/io/github/haykam821/beaconbreakers/game/BeaconBreakersSidebar.java index faa8e30..ec74bb6 100644 --- a/src/main/java/io/github/haykam821/beaconbreakers/game/BeaconBreakersSidebar.java +++ b/src/main/java/io/github/haykam821/beaconbreakers/game/BeaconBreakersSidebar.java @@ -1,7 +1,7 @@ package io.github.haykam821.beaconbreakers.game; import io.github.haykam821.beaconbreakers.game.phase.BeaconBreakersActivePhase; -import io.github.haykam821.beaconbreakers.game.player.PlayerEntry; +import io.github.haykam821.beaconbreakers.game.player.team.TeamEntry; import net.minecraft.text.Text; import xyz.nucleoid.plasmid.game.common.GlobalWidgets; import xyz.nucleoid.plasmid.game.common.widget.SidebarWidget; @@ -21,8 +21,8 @@ public BeaconBreakersSidebar(GlobalWidgets widgets, BeaconBreakersActivePhase ph public void update() { this.widget.set(content -> { - for (PlayerEntry player : this.phase.getPlayers()) { - content.add(player.getSidebarEntryText()); + for (TeamEntry team : this.phase.getTeams()) { + content.add(team.getSidebarEntryText()); } }); } diff --git a/src/main/java/io/github/haykam821/beaconbreakers/game/phase/BeaconBreakersActivePhase.java b/src/main/java/io/github/haykam821/beaconbreakers/game/phase/BeaconBreakersActivePhase.java index f8adb24..e329e55 100644 --- a/src/main/java/io/github/haykam821/beaconbreakers/game/phase/BeaconBreakersActivePhase.java +++ b/src/main/java/io/github/haykam821/beaconbreakers/game/phase/BeaconBreakersActivePhase.java @@ -1,11 +1,8 @@ package io.github.haykam821.beaconbreakers.game.phase; import java.util.Iterator; +import java.util.List; import java.util.Optional; -import java.util.Set; -import java.util.stream.Collectors; - -import com.google.common.collect.Sets; import io.github.haykam821.beaconbreakers.Main; import io.github.haykam821.beaconbreakers.game.BeaconBreakersConfig; @@ -16,6 +13,9 @@ import io.github.haykam821.beaconbreakers.game.map.BeaconBreakersMapConfig; import io.github.haykam821.beaconbreakers.game.player.BeaconPlacement; import io.github.haykam821.beaconbreakers.game.player.PlayerEntry; +import io.github.haykam821.beaconbreakers.game.player.team.MultipleTeamEntry; +import io.github.haykam821.beaconbreakers.game.player.team.SingleTeamEntry; +import io.github.haykam821.beaconbreakers.game.player.team.TeamEntry; import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.block.RespawnAnchorBlock; @@ -45,6 +45,8 @@ 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.team.TeamManager; +import xyz.nucleoid.plasmid.game.common.team.TeamSelectionLobby; import xyz.nucleoid.plasmid.game.event.GameActivityEvents; import xyz.nucleoid.plasmid.game.event.GamePlayerEvents; import xyz.nucleoid.plasmid.game.player.PlayerOffer; @@ -61,14 +63,14 @@ public class BeaconBreakersActivePhase { private final ServerWorld world; private final BeaconBreakersMap map; private final BeaconBreakersConfig config; - private final Set players; + private final List teams; private final InvulnerabilityTimerBar bar; private final BeaconBreakersSidebar sidebar; private boolean singleplayer; private int ticksUntilClose = -1; private int invulnerability; - public BeaconBreakersActivePhase(GameSpace gameSpace, ServerWorld world, GlobalWidgets widgets, BeaconBreakersMap map, BeaconBreakersConfig config, Set players) { + public BeaconBreakersActivePhase(GameSpace gameSpace, ServerWorld world, TeamSelectionLobby teamSelection, TeamManager teamManager, GlobalWidgets widgets, BeaconBreakersMap map, BeaconBreakersConfig config) { this.gameSpace = gameSpace; this.world = world; this.map = map; @@ -76,18 +78,20 @@ public BeaconBreakersActivePhase(GameSpace gameSpace, ServerWorld world, GlobalW this.sidebar = new BeaconBreakersSidebar(widgets, this); this.bar = new InvulnerabilityTimerBar(this, widgets); - this.players = players.stream().map(player -> { - return new PlayerEntry(player, this); - }).collect(Collectors.toSet()); + + this.teams = config.getTeams() + .map(teams -> MultipleTeamEntry.allocate(this, gameSpace.getPlayers(), teamSelection, teamManager, teams)) + .orElseGet(() -> SingleTeamEntry.ofAll(this, gameSpace.getPlayers())); this.invulnerability = this.config.getInvulnerability(); } - public static void open(GameSpace gameSpace, ServerWorld world, BeaconBreakersMap map, BeaconBreakersConfig config) { + public static void open(GameSpace gameSpace, ServerWorld world, TeamSelectionLobby teamSelection, BeaconBreakersMap map, BeaconBreakersConfig config) { gameSpace.setActivity(activity -> { + TeamManager teamManager = TeamManager.addTo(activity); GlobalWidgets widgets = GlobalWidgets.addTo(activity); - Set players = Sets.newHashSet(gameSpace.getPlayers()); - BeaconBreakersActivePhase active = new BeaconBreakersActivePhase(gameSpace, world, widgets, map, config, players); + + BeaconBreakersActivePhase active = new BeaconBreakersActivePhase(gameSpace, world, teamSelection, teamManager, widgets, map, config); activity.allow(GameRuleType.BLOCK_DROPS); activity.allow(GameRuleType.CRAFTING); @@ -111,14 +115,20 @@ public static void open(GameSpace gameSpace, ServerWorld world, BeaconBreakersMa } private void enable() { - this.singleplayer = this.players.size() == 1; + this.singleplayer = this.teams.size() == 1; - for (PlayerEntry entry : this.players) { - ServerPlayerEntity player = entry.getPlayer(); - - if (player != null) { - entry.initializePlayer(); - BeaconBreakersActivePhase.spawn(this.world, this.map, this.config.getMapConfig(), player); + for (TeamEntry team : this.teams) { + if (team.isEliminated()) { + throw new IllegalStateException("Team should not be immediately eliminated"); + } + + for (PlayerEntry entry : team.getPlayers()) { + ServerPlayerEntity player = entry.getPlayer(); + + if (player != null) { + entry.initializePlayer(); + BeaconBreakersActivePhase.spawn(this.world, this.map, this.config.getMapConfig(), player); + } } } @@ -148,25 +158,25 @@ private void tick() { } } - Iterator iterator = this.players.iterator(); - while (iterator.hasNext()) { - PlayerEntry entry = iterator.next(); + Iterator iterator = this.teams.iterator(); + boolean sidebarDirty = false; - if (entry.tick()) { - ServerPlayerEntity player = entry.getPlayer(); - - if (player != null) { - this.setSpectator(player); - } + while (iterator.hasNext()) { + TeamEntry entry = iterator.next(); + entry.tick(); - this.sendEliminateMessage(entry); + if (entry.isEliminated()) { iterator.remove(); - this.sidebar.update(); + sidebarDirty = true; } } + + if (sidebarDirty) { + this.sidebar.update(); + } - if (this.players.size() < 2) { - if (this.players.size() == 1 && this.singleplayer) return; + if (this.teams.size() < 2) { + if (this.teams.size() == 1 && this.singleplayer) return; this.gameSpace.getPlayers().sendMessage(this.getEndingMessage().formatted(Formatting.GOLD)); this.ticksUntilClose = this.config.getTicksUntilClose().get(this.world.getRandom()); @@ -178,9 +188,9 @@ public boolean isGameEnding() { } private MutableText getEndingMessage() { - if (this.players.size() == 1) { - PlayerEntry winner = this.players.iterator().next(); - return Text.translatable("text.beaconbreakers.win", winner.getName()); + if (this.teams.size() == 1) { + TeamEntry winner = this.teams.iterator().next(); + return winner.getWinMessage(); } return Text.translatable("text.beaconbreakers.win.none"); } @@ -189,30 +199,35 @@ private void setSpectator(ServerPlayerEntity player) { player.changeGameMode(GameMode.SPECTATOR); } - private void sendEliminateMessage(PlayerEntry entry) { - if (this.isGameEnding()) { - return; + public void applyEliminationToPlayer(PlayerEntry entry) { + ServerPlayerEntity player = entry.getPlayer(); + + if (player != null) { + this.setSpectator(player); } - this.gameSpace.getPlayers().sendMessage(Text.translatable("text.beaconbreakers.eliminate", entry.getName()).formatted(Formatting.RED)); + if (!this.isGameEnding()) { + this.gameSpace.getPlayers().sendMessage(Text.translatable("text.beaconbreakers.eliminate", entry.getName()).formatted(Formatting.RED)); + } } private void eliminate(PlayerEntry entry) { - ServerPlayerEntity player = entry.getPlayer(); + this.applyEliminationToPlayer(entry); - if (player != null) { - this.setSpectator(player); - } + TeamEntry team = entry.getTeam(); + team.removePlayer(entry); - this.sendEliminateMessage(entry); - this.players.remove(entry); - this.sidebar.update(); + if (team.isEliminated() && this.teams.remove(team)) { + this.sidebar.update(); + } } private PlayerEntry getEntryFromPlayer(ServerPlayerEntity player) { - for (PlayerEntry entry : this.players) { - if (player.equals(entry.getPlayer())) { - return entry; + for (TeamEntry team : this.teams) { + for (PlayerEntry entry : team.getPlayers()) { + if (player.equals(entry.getPlayer())) { + return entry; + } } } return null; @@ -221,18 +236,20 @@ private PlayerEntry getEntryFromPlayer(ServerPlayerEntity player) { private PlayerOfferResult offerPlayer(PlayerOffer offer) { ServerPlayerEntity player = offer.player(); - for (PlayerEntry entry : this.players) { - if (player.getUuid().equals(entry.getUuid())) { - Vec3d spawnPos = this.getRespawnPos(entry); + for (TeamEntry team : this.teams) { + for (PlayerEntry entry : team.getPlayers()) { + if (player.getUuid().equals(entry.getUuid())) { + Vec3d spawnPos = this.getRespawnPos(entry); - if (spawnPos == null) { - spawnPos = BeaconBreakersActivePhase.getSpawnPos(world, map, this.config.getMapConfig(), player); - } + if (spawnPos == null) { + spawnPos = BeaconBreakersActivePhase.getSpawnPos(world, map, this.config.getMapConfig(), player); + } - return offer.accept(this.world, spawnPos).and(() -> { - entry.restorePlayer(player); - entry.initializePlayer(); - }); + return offer.accept(this.world, spawnPos).and(() -> { + entry.restorePlayer(player); + entry.initializePlayer(); + }); + } } } @@ -251,7 +268,7 @@ private void removePlayer(ServerPlayerEntity player) { } private Vec3d getRespawnPos(PlayerEntry entry) { - if (!(entry.getBeacon() instanceof BeaconPlacement.Placed placed)) { + if (!(entry.getTeam().getBeacon() instanceof BeaconPlacement.Placed placed)) { return null; } @@ -345,25 +362,13 @@ private void breakBeacon(PlayerEntry breaker, BlockPos pos, boolean explosion) { boolean found = false; - for (PlayerEntry entry : this.players) { + for (TeamEntry entry : this.teams) { if (entry.getBeacon().isAt(pos)) { entry.setBeacon(BeaconPlacement.Broken.INSTANCE); this.gameSpace.getPlayers().playSound(SoundEvents.BLOCK_GLASS_BREAK, SoundCategory.PLAYERS, 1, 1); - String translationKey = "text.beaconbreakers.beacon_break"; - if (explosion) translationKey += ".explosion"; - - MutableText message; - Text playerName = entry.getName(); - - if (breaker == null) { - message = Text.translatable(translationKey + ".unattributed", playerName); - } else { - Text breakerName = breaker.getName(); - message = Text.translatable(translationKey, playerName, breakerName); - } - + MutableText message = entry.getBeaconBreakMessage(breaker, explosion); this.gameSpace.getPlayers().sendMessage(message.formatted(Formatting.RED)); found = true; @@ -381,17 +386,18 @@ private ActionResult onBreakBlock(ServerPlayerEntity player, ServerWorld world, if (entry == null) return ActionResult.PASS; BlockState state = world.getBlockState(pos); + TeamEntry team = entry.getTeam(); - if (entry.getBeacon().isAt(pos)) { + if (team.getBeacon().isAt(pos)) { if (this.invulnerability > 0) { - entry.setBeacon(BeaconPlacement.Unplaced.INSTANCE); + team.setBeacon(BeaconPlacement.Unplaced.INSTANCE); world.setBlockState(pos, state.getFluidState().getBlockState()); entry.giveRespawnBeacon(); this.sidebar.update(); } else if (!this.config.shouldAllowSelfBreaking()) { - player.sendMessage(Text.translatable("text.beaconbreakers.cannot_break_own_beacon").formatted(Formatting.RED), false); + player.sendMessage(team.getCannotBreakOwnBeaconMessage().formatted(Formatting.RED), false); } return ActionResult.FAIL; @@ -417,13 +423,15 @@ private void afterBlockPlace(BlockPos pos, World world, ServerPlayerEntity playe PlayerEntry entry = this.getEntryFromPlayer(player); if (entry == null) return; - if (!(entry.getBeacon() instanceof BeaconPlacement.Unplaced)) return; + TeamEntry team = entry.getTeam(); + + if (!(team.getBeacon() instanceof BeaconPlacement.Unplaced)) return; if (!this.map.getBox().contains(pos)) { entry.sendMessage(Text.translatable("text.beaconbreakers.cannot_place_out_of_bounds_beacon").formatted(Formatting.RED), false); return; } - entry.setBeacon(new BeaconPlacement.Placed(pos)); + team.setBeacon(new BeaconPlacement.Placed(pos)); this.sidebar.update(); } @@ -450,7 +458,7 @@ private void onExplosionDetonated(Explosion explosion, boolean particles) { } // Prevent players from blowing up their own beacons - if (!this.config.shouldAllowSelfBreaking() && entry != null && entry.getBeacon().isAt(pos)) { + if (!this.config.shouldAllowSelfBreaking() && entry != null && entry.getTeam().getBeacon().isAt(pos)) { iterator.remove(); continue; } @@ -489,8 +497,8 @@ public int getInvulnerability() { return this.invulnerability; } - public Set getPlayers() { - return this.players; + public Iterable getTeams() { + return this.teams; } public static Vec3d getSpawnPos(ServerWorld world, BeaconBreakersMap map, BeaconBreakersMapConfig mapConfig, ServerPlayerEntity player) { diff --git a/src/main/java/io/github/haykam821/beaconbreakers/game/phase/BeaconBreakersWaitingPhase.java b/src/main/java/io/github/haykam821/beaconbreakers/game/phase/BeaconBreakersWaitingPhase.java index 45ff935..520c49d 100644 --- a/src/main/java/io/github/haykam821/beaconbreakers/game/phase/BeaconBreakersWaitingPhase.java +++ b/src/main/java/io/github/haykam821/beaconbreakers/game/phase/BeaconBreakersWaitingPhase.java @@ -17,6 +17,7 @@ import xyz.nucleoid.plasmid.game.GameResult; import xyz.nucleoid.plasmid.game.GameSpace; import xyz.nucleoid.plasmid.game.common.GameWaitingLobby; +import xyz.nucleoid.plasmid.game.common.team.TeamSelectionLobby; import xyz.nucleoid.plasmid.game.event.GameActivityEvents; import xyz.nucleoid.plasmid.game.event.GamePlayerEvents; import xyz.nucleoid.plasmid.game.player.PlayerOffer; @@ -28,12 +29,14 @@ public class BeaconBreakersWaitingPhase { private final GameSpace gameSpace; private final ServerWorld world; + private final TeamSelectionLobby teamSelection; private final BeaconBreakersMap map; private final BeaconBreakersConfig config; - public BeaconBreakersWaitingPhase(GameSpace gameSpace, ServerWorld world, BeaconBreakersMap map, BeaconBreakersConfig config) { + public BeaconBreakersWaitingPhase(GameSpace gameSpace, ServerWorld world, TeamSelectionLobby teamSelection, BeaconBreakersMap map, BeaconBreakersConfig config) { this.gameSpace = gameSpace; this.world = world; + this.teamSelection = teamSelection; this.map = map; this.config = config; } @@ -50,7 +53,9 @@ public static GameOpenProcedure open(GameOpenContext conte .setGenerator(map.getChunkGenerator()); return context.openWithWorld(worldConfig, (activity, world) -> { - BeaconBreakersWaitingPhase waiting = new BeaconBreakersWaitingPhase(activity.getGameSpace(), world, map, config); + TeamSelectionLobby teamSelection = config.getTeams().isPresent() ? TeamSelectionLobby.addTo(activity, config.getTeams().get()) : null; + + BeaconBreakersWaitingPhase waiting = new BeaconBreakersWaitingPhase(activity.getGameSpace(), world, teamSelection, map, config); GameWaitingLobby.addTo(activity, config.getPlayerConfig()); // Rules @@ -72,7 +77,7 @@ public static GameOpenProcedure open(GameOpenContext conte } private GameResult requestStart() { - BeaconBreakersActivePhase.open(this.gameSpace, this.world, this.map, this.config); + BeaconBreakersActivePhase.open(this.gameSpace, this.world, this.teamSelection, this.map, this.config); return GameResult.ok(); } diff --git a/src/main/java/io/github/haykam821/beaconbreakers/game/player/PlayerEntry.java b/src/main/java/io/github/haykam821/beaconbreakers/game/player/PlayerEntry.java index 136904d..5ee4758 100644 --- a/src/main/java/io/github/haykam821/beaconbreakers/game/player/PlayerEntry.java +++ b/src/main/java/io/github/haykam821/beaconbreakers/game/player/PlayerEntry.java @@ -4,7 +4,7 @@ import java.util.UUID; import io.github.haykam821.beaconbreakers.Main; -import io.github.haykam821.beaconbreakers.game.phase.BeaconBreakersActivePhase; +import io.github.haykam821.beaconbreakers.game.player.team.TeamEntry; import net.minecraft.block.Block; import net.minecraft.entity.effect.StatusEffectInstance; import net.minecraft.entity.effect.StatusEffects; @@ -12,24 +12,21 @@ import net.minecraft.registry.Registries; import net.minecraft.registry.entry.RegistryEntry; import net.minecraft.registry.entry.RegistryEntryList; -import net.minecraft.screen.ScreenTexts; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.text.Text; import net.minecraft.world.GameMode; +import xyz.nucleoid.plasmid.util.InventoryUtil; public class PlayerEntry { private ServerPlayerEntity player; private UUID uuid; private Text name; - private String sidebarName; - private final BeaconBreakersActivePhase phase; + private final TeamEntry team; - private BeaconPlacement beacon = BeaconPlacement.Unplaced.INSTANCE; - - public PlayerEntry(ServerPlayerEntity player, BeaconBreakersActivePhase phase) { + public PlayerEntry(ServerPlayerEntity player, TeamEntry team) { this.player = player; - this.phase = phase; + this.team = team; } /** @@ -37,33 +34,29 @@ public PlayerEntry(ServerPlayerEntity player, BeaconBreakersActivePhase phase) { */ public boolean tick() { if (this.player == null) { - return this.phase.getInvulnerability() == 0; + return this.team.getPhase().getInvulnerability() == 0; } - return !this.phase.getMap().getBox().contains(player.getBlockPos()); + return !this.team.getPhase().getMap().getBox().contains(player.getBlockPos()); } public void removePlayer() { this.uuid = this.player.getUuid(); - this.name = this.player.getDisplayName(); - this.sidebarName = this.player.getNameForScoreboard(); this.player = null; } public void restorePlayer(ServerPlayerEntity player) { this.uuid = null; - this.name = null; - this.sidebarName = null; this.player = player; } public void giveRespawnBeacon() { if (this.player == null) return; - if (!(this.beacon instanceof BeaconPlacement.Unplaced)) return; + if (!(this.team.getBeacon() instanceof BeaconPlacement.Unplaced)) return; Optional> maybeBeacons = Registries.BLOCK.getEntryList(Main.RESPAWN_BEACONS); if (maybeBeacons.isPresent()) { @@ -75,12 +68,20 @@ public void giveRespawnBeacon() { } public void initializePlayer() { + if (this.player == null) return; + this.player.changeGameMode(GameMode.SURVIVAL); - this.giveRespawnBeacon(); + InventoryUtil.clear(player); + + if (this.player == this.team.getMainPlayer().getPlayer()) { + this.giveRespawnBeacon(); + } + + int invulnerability = this.team.getPhase().getInvulnerability(); - this.player.addStatusEffect(new StatusEffectInstance(StatusEffects.INVISIBILITY, this.phase.getInvulnerability(), 1, true, false)); - this.player.addStatusEffect(new StatusEffectInstance(StatusEffects.SATURATION, this.phase.getInvulnerability(), 127, true, false)); + this.player.addStatusEffect(new StatusEffectInstance(StatusEffects.INVISIBILITY, invulnerability, 1, true, false)); + this.player.addStatusEffect(new StatusEffectInstance(StatusEffects.SATURATION, invulnerability, 127, true, false)); } public void dropInventory() { @@ -101,10 +102,6 @@ public Text getName() { return this.player == null ? this.name : this.player.getDisplayName(); } - private String getSidebarName() { - return this.player == null ? this.sidebarName : this.player.getNameForScoreboard(); - } - public ServerPlayerEntity getPlayer() { return this.player; } @@ -113,20 +110,12 @@ public UUID getUuid() { return this.uuid; } - public BeaconPlacement getBeacon() { - return this.beacon; - } - - public void setBeacon(BeaconPlacement beacon) { - this.beacon = beacon; - } - - public Text getSidebarEntryText() { - return Text.empty().append(this.beacon.getSidebarEntryIcon()).append(ScreenTexts.SPACE).append(this.getSidebarName()); + public TeamEntry getTeam() { + return this.team; } @Override public String toString() { - return "PlayerEntry{player=" + this.getPlayer() + ", beacon=" + this.beacon + "}"; + return "PlayerEntry{player=" + this.getPlayer() + ", team=" + this.team + "}"; } } \ No newline at end of file diff --git a/src/main/java/io/github/haykam821/beaconbreakers/game/player/team/MultipleTeamEntry.java b/src/main/java/io/github/haykam821/beaconbreakers/game/player/team/MultipleTeamEntry.java new file mode 100644 index 0000000..d3a028a --- /dev/null +++ b/src/main/java/io/github/haykam821/beaconbreakers/game/player/team/MultipleTeamEntry.java @@ -0,0 +1,113 @@ +package io.github.haykam821.beaconbreakers.game.player.team; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import io.github.haykam821.beaconbreakers.game.phase.BeaconBreakersActivePhase; +import io.github.haykam821.beaconbreakers.game.player.PlayerEntry; +import net.minecraft.scoreboard.Team; +import net.minecraft.text.MutableText; +import net.minecraft.text.Text; +import xyz.nucleoid.plasmid.game.common.team.GameTeam; +import xyz.nucleoid.plasmid.game.common.team.GameTeamConfig; +import xyz.nucleoid.plasmid.game.common.team.GameTeamKey; +import xyz.nucleoid.plasmid.game.common.team.GameTeamList; +import xyz.nucleoid.plasmid.game.common.team.TeamManager; +import xyz.nucleoid.plasmid.game.common.team.TeamSelectionLobby; +import xyz.nucleoid.plasmid.game.player.PlayerSet; + +public class MultipleTeamEntry extends TeamEntry { + private final List players = new ArrayList<>(); + + private final TeamManager teamManager; + private final GameTeam team; + + private MultipleTeamEntry(BeaconBreakersActivePhase phase, TeamManager teamManager, GameTeam team) { + super(phase); + + this.teamManager = teamManager; + this.team = team; + } + + // Messages + + @Override + protected Text getName() { + return this.team.config().name(); + } + + @Override + protected String getBeaconBreakTranslationKey() { + return super.getBeaconBreakTranslationKey() + ".team"; + } + + @Override + public MutableText getCannotBreakOwnBeaconMessage() { + return Text.translatable("text.beaconbreakers.cannot_break_own_beacon.team"); + } + + @Override + public MutableText getWinMessage() { + return Text.translatable("text.beaconbreakers.win.team", this.getName()); + } + + // Players + + @Override + public void addPlayer(PlayerEntry player) { + this.players.add(player); + this.teamManager.addPlayerTo(player.getPlayer(), this.team.key()); + } + + @Override + public void removePlayer(PlayerEntry player) { + this.players.remove(player); + } + + @Override + public Collection getPlayers() { + return this.players; + } + + @Override + public PlayerEntry getMainPlayer() { + return this.players.get(0); + } + + // Helpers + + /** + * Creates a team entry for multiple players by adding a game team to a team manager. + */ + public static TeamEntry of(BeaconBreakersActivePhase phase, TeamManager teamManager, GameTeam initialTeam) { + GameTeamConfig teamConfig = GameTeamConfig.builder(initialTeam.config()) + .setFriendlyFire(false) + .setCollision(Team.CollisionRule.PUSH_OTHER_TEAMS) + .build(); + + GameTeam team = initialTeam.withConfig(teamConfig); + teamManager.addTeam(team.key(), teamConfig); + + return new MultipleTeamEntry(phase, teamManager, team); + } + + public static List allocate(BeaconBreakersActivePhase phase, PlayerSet players, TeamSelectionLobby teamSelection, TeamManager teamManager, GameTeamList teams) { + Map teamsByKey = new HashMap<>(); + + teamSelection.allocate(players, (teamKey, player) -> { + TeamEntry team = teamsByKey.computeIfAbsent(teamKey, teamKeyx -> { + GameTeam initialTeam = teams.byKey(teamKeyx); + return of(phase, teamManager, initialTeam); + }); + + team.addPlayer(new PlayerEntry(player, team)); + }); + + return teamsByKey.values().stream() + .collect(Collectors.toCollection(ArrayList::new)); + } +} \ No newline at end of file diff --git a/src/main/java/io/github/haykam821/beaconbreakers/game/player/team/SingleTeamEntry.java b/src/main/java/io/github/haykam821/beaconbreakers/game/player/team/SingleTeamEntry.java new file mode 100644 index 0000000..2b91c43 --- /dev/null +++ b/src/main/java/io/github/haykam821/beaconbreakers/game/player/team/SingleTeamEntry.java @@ -0,0 +1,69 @@ +package io.github.haykam821.beaconbreakers.game.player.team; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +import io.github.haykam821.beaconbreakers.game.phase.BeaconBreakersActivePhase; +import io.github.haykam821.beaconbreakers.game.player.PlayerEntry; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.text.Text; +import xyz.nucleoid.plasmid.game.player.PlayerSet; + +public class SingleTeamEntry extends TeamEntry { + private PlayerEntry player = null; + + private SingleTeamEntry(BeaconBreakersActivePhase phase) { + super(phase); + } + + // Messages + + @Override + protected Text getName() { + return this.player.getName(); + } + + // Players + + @Override + public void addPlayer(PlayerEntry player) { + if (this.player != null) { + throw new IllegalStateException("SingleTeamEntry can only have one player"); + } + + this.player = player; + } + + @Override + public void removePlayer(PlayerEntry player) { + this.player = null; + } + + @Override + public Collection getPlayers() { + return this.player == null ? Set.of() : Set.of(this.player); + } + + @Override + public PlayerEntry getMainPlayer() { + return this.player; + } + + // Helpers + + private static TeamEntry of(BeaconBreakersActivePhase phase, ServerPlayerEntity player) { + TeamEntry team = new SingleTeamEntry(phase); + team.addPlayer(new PlayerEntry(player, team)); + + return team; + } + + public static List ofAll(BeaconBreakersActivePhase phase, PlayerSet players) { + return players.stream() + .map(player -> SingleTeamEntry.of(phase, player)) + .collect(Collectors.toCollection(ArrayList::new)); + } +} diff --git a/src/main/java/io/github/haykam821/beaconbreakers/game/player/team/TeamEntry.java b/src/main/java/io/github/haykam821/beaconbreakers/game/player/team/TeamEntry.java new file mode 100644 index 0000000..12c9bd0 --- /dev/null +++ b/src/main/java/io/github/haykam821/beaconbreakers/game/player/team/TeamEntry.java @@ -0,0 +1,96 @@ +package io.github.haykam821.beaconbreakers.game.player.team; + +import java.util.Collection; +import java.util.Iterator; + +import io.github.haykam821.beaconbreakers.game.phase.BeaconBreakersActivePhase; +import io.github.haykam821.beaconbreakers.game.player.BeaconPlacement; +import io.github.haykam821.beaconbreakers.game.player.PlayerEntry; +import net.minecraft.screen.ScreenTexts; +import net.minecraft.text.MutableText; +import net.minecraft.text.Text; + +public abstract class TeamEntry { + private final BeaconBreakersActivePhase phase; + + private BeaconPlacement beacon = BeaconPlacement.Unplaced.INSTANCE; + + protected TeamEntry(BeaconBreakersActivePhase phase) { + this.phase = phase; + } + + public final BeaconBreakersActivePhase getPhase() { + return this.phase; + } + + public final BeaconPlacement getBeacon() { + return this.beacon; + } + + public final void setBeacon(BeaconPlacement beacon) { + this.beacon = beacon; + } + + public final void tick() { + Iterator iterator = this.getPlayers().iterator(); + + while (iterator.hasNext()) { + PlayerEntry entry = iterator.next(); + + if (entry.tick()) { + this.getPhase().applyEliminationToPlayer(entry); + iterator.remove(); + } + } + } + + // Messages + + protected abstract Text getName(); + + public final Text getSidebarEntryText() { + return Text.empty().append(this.beacon.getSidebarEntryIcon()).append(ScreenTexts.SPACE).append(this.getName()); + } + + protected String getBeaconBreakTranslationKey() { + return "text.beaconbreakers.beacon_break"; + } + + public final MutableText getBeaconBreakMessage(PlayerEntry breaker, boolean explosion) { + String translationKey = this.getBeaconBreakTranslationKey(); + if (explosion) translationKey += ".explosion"; + + Text name = this.getName(); + + if (breaker == null) { + return Text.translatable(translationKey + ".unattributed", name); + } else { + return Text.translatable(translationKey, name, breaker.getName()); + } + } + + public MutableText getCannotBreakOwnBeaconMessage() { + return Text.translatable("text.beaconbreakers.cannot_break_own_beacon"); + } + + public MutableText getWinMessage() { + return Text.translatable("text.beaconbreakers.win", this.getName()); + } + + // Players + + public abstract void addPlayer(PlayerEntry player); + + public abstract void removePlayer(PlayerEntry player); + + public abstract Collection getPlayers(); + + /** + * {@return the player that receives the team's beacon to place} + */ + public abstract PlayerEntry getMainPlayer(); + + public final boolean isEliminated() { + return this.getPlayers().isEmpty(); + } +} diff --git a/src/main/resources/data/beaconbreakers/games/amplified_beacon_breakers_2_teams.json b/src/main/resources/data/beaconbreakers/games/amplified_beacon_breakers_2_teams.json new file mode 100644 index 0000000..6b6be69 --- /dev/null +++ b/src/main/resources/data/beaconbreakers/games/amplified_beacon_breakers_2_teams.json @@ -0,0 +1,29 @@ +{ + "type": "beaconbreakers:beacon_breakers", + "map": { + "dimension_options": "minecraft:overworld", + "preset": "minecraft:amplified", + "excluded_biomes": "#minecraft:is_ocean" + }, + "players": { + "min": 1, + "max": 32, + "threshold": 4 + }, + "teams": [ + { + "key": "red", + "name": { + "translate": "color.minecraft.red" + }, + "color": "red" + }, + { + "key": "blue", + "name": { + "translate": "color.minecraft.blue" + }, + "color": "blue" + } + ] +} diff --git a/src/main/resources/data/beaconbreakers/games/amplified_beacon_breakers_4_teams.json b/src/main/resources/data/beaconbreakers/games/amplified_beacon_breakers_4_teams.json new file mode 100644 index 0000000..ee6b856 --- /dev/null +++ b/src/main/resources/data/beaconbreakers/games/amplified_beacon_breakers_4_teams.json @@ -0,0 +1,43 @@ +{ + "type": "beaconbreakers:beacon_breakers", + "map": { + "dimension_options": "minecraft:overworld", + "preset": "minecraft:amplified", + "excluded_biomes": "#minecraft:is_ocean" + }, + "players": { + "min": 1, + "max": 32, + "threshold": 4 + }, + "teams": [ + { + "key": "red", + "name": { + "translate": "color.minecraft.red" + }, + "color": "red" + }, + { + "key": "green", + "name": { + "translate": "color.minecraft.green" + }, + "color": "green" + }, + { + "key": "blue", + "name": { + "translate": "color.minecraft.blue" + }, + "color": "blue" + }, + { + "key": "yellow", + "name": { + "translate": "color.minecraft.yellow" + }, + "color": "yellow" + } + ] +} diff --git a/src/main/resources/data/beaconbreakers/games/amplified_beacon_breakers_keep_inventory_2_teams.json b/src/main/resources/data/beaconbreakers/games/amplified_beacon_breakers_keep_inventory_2_teams.json new file mode 100644 index 0000000..b1a07c4 --- /dev/null +++ b/src/main/resources/data/beaconbreakers/games/amplified_beacon_breakers_keep_inventory_2_teams.json @@ -0,0 +1,30 @@ +{ + "type": "beaconbreakers:beacon_breakers", + "map": { + "dimension_options": "minecraft:overworld", + "preset": "minecraft:amplified", + "excluded_biomes": "#minecraft:is_ocean" + }, + "players": { + "min": 1, + "max": 32, + "threshold": 4 + }, + "teams": [ + { + "key": "red", + "name": { + "translate": "color.minecraft.red" + }, + "color": "red" + }, + { + "key": "blue", + "name": { + "translate": "color.minecraft.blue" + }, + "color": "blue" + } + ], + "keep_inventory": true +} diff --git a/src/main/resources/data/beaconbreakers/games/amplified_beacon_breakers_keep_inventory_4_teams.json b/src/main/resources/data/beaconbreakers/games/amplified_beacon_breakers_keep_inventory_4_teams.json new file mode 100644 index 0000000..651bd30 --- /dev/null +++ b/src/main/resources/data/beaconbreakers/games/amplified_beacon_breakers_keep_inventory_4_teams.json @@ -0,0 +1,44 @@ +{ + "type": "beaconbreakers:beacon_breakers", + "map": { + "dimension_options": "minecraft:overworld", + "preset": "minecraft:amplified", + "excluded_biomes": "#minecraft:is_ocean" + }, + "players": { + "min": 1, + "max": 32, + "threshold": 4 + }, + "teams": [ + { + "key": "red", + "name": { + "translate": "color.minecraft.red" + }, + "color": "red" + }, + { + "key": "green", + "name": { + "translate": "color.minecraft.green" + }, + "color": "green" + }, + { + "key": "blue", + "name": { + "translate": "color.minecraft.blue" + }, + "color": "blue" + }, + { + "key": "yellow", + "name": { + "translate": "color.minecraft.yellow" + }, + "color": "yellow" + } + ], + "keep_inventory": true +} diff --git a/src/main/resources/data/beaconbreakers/games/amplified_beacon_breakers_tiny_2_teams.json b/src/main/resources/data/beaconbreakers/games/amplified_beacon_breakers_tiny_2_teams.json new file mode 100644 index 0000000..4c9e16a --- /dev/null +++ b/src/main/resources/data/beaconbreakers/games/amplified_beacon_breakers_tiny_2_teams.json @@ -0,0 +1,32 @@ +{ + "type": "beaconbreakers:beacon_breakers", + "map": { + "dimension_options": "minecraft:overworld", + "preset": "minecraft:amplified", + "excluded_biomes": "#minecraft:is_ocean", + "x": 5, + "z": 5 + }, + "players": { + "min": 1, + "max": 32, + "threshold": 4 + }, + "teams": [ + { + "key": "red", + "name": { + "translate": "color.minecraft.red" + }, + "color": "red" + }, + { + "key": "blue", + "name": { + "translate": "color.minecraft.blue" + }, + "color": "blue" + } + ], + "keep_inventory": true +} diff --git a/src/main/resources/data/beaconbreakers/games/amplified_beacon_breakers_tiny_4_teams.json b/src/main/resources/data/beaconbreakers/games/amplified_beacon_breakers_tiny_4_teams.json new file mode 100644 index 0000000..73c4d90 --- /dev/null +++ b/src/main/resources/data/beaconbreakers/games/amplified_beacon_breakers_tiny_4_teams.json @@ -0,0 +1,46 @@ +{ + "type": "beaconbreakers:beacon_breakers", + "map": { + "dimension_options": "minecraft:overworld", + "preset": "minecraft:amplified", + "excluded_biomes": "#minecraft:is_ocean", + "x": 5, + "z": 5 + }, + "players": { + "min": 1, + "max": 32, + "threshold": 4 + }, + "teams": [ + { + "key": "red", + "name": { + "translate": "color.minecraft.red" + }, + "color": "red" + }, + { + "key": "green", + "name": { + "translate": "color.minecraft.green" + }, + "color": "green" + }, + { + "key": "blue", + "name": { + "translate": "color.minecraft.blue" + }, + "color": "blue" + }, + { + "key": "yellow", + "name": { + "translate": "color.minecraft.yellow" + }, + "color": "yellow" + } + ], + "keep_inventory": true +} diff --git a/src/main/resources/data/beaconbreakers/games/end_beacon_breakers_2_teams.json b/src/main/resources/data/beaconbreakers/games/end_beacon_breakers_2_teams.json new file mode 100644 index 0000000..57e1527 --- /dev/null +++ b/src/main/resources/data/beaconbreakers/games/end_beacon_breakers_2_teams.json @@ -0,0 +1,28 @@ +{ + "type": "beaconbreakers:beacon_breakers", + "map": { + "dimension_options": "minecraft:the_end", + "preset": "minecraft:normal" + }, + "players": { + "min": 1, + "max": 32, + "threshold": 4 + }, + "teams": [ + { + "key": "red", + "name": { + "translate": "color.minecraft.red" + }, + "color": "red" + }, + { + "key": "blue", + "name": { + "translate": "color.minecraft.blue" + }, + "color": "blue" + } + ] +} diff --git a/src/main/resources/data/beaconbreakers/games/end_beacon_breakers_4_teams.json b/src/main/resources/data/beaconbreakers/games/end_beacon_breakers_4_teams.json new file mode 100644 index 0000000..d16c6eb --- /dev/null +++ b/src/main/resources/data/beaconbreakers/games/end_beacon_breakers_4_teams.json @@ -0,0 +1,42 @@ +{ + "type": "beaconbreakers:beacon_breakers", + "map": { + "dimension_options": "minecraft:the_end", + "preset": "minecraft:normal" + }, + "players": { + "min": 1, + "max": 32, + "threshold": 4 + }, + "teams": [ + { + "key": "red", + "name": { + "translate": "color.minecraft.red" + }, + "color": "red" + }, + { + "key": "green", + "name": { + "translate": "color.minecraft.green" + }, + "color": "green" + }, + { + "key": "blue", + "name": { + "translate": "color.minecraft.blue" + }, + "color": "blue" + }, + { + "key": "yellow", + "name": { + "translate": "color.minecraft.yellow" + }, + "color": "yellow" + } + ] +} diff --git a/src/main/resources/data/beaconbreakers/games/end_beacon_breakers_keep_inventory_2_teams.json b/src/main/resources/data/beaconbreakers/games/end_beacon_breakers_keep_inventory_2_teams.json new file mode 100644 index 0000000..67efd99 --- /dev/null +++ b/src/main/resources/data/beaconbreakers/games/end_beacon_breakers_keep_inventory_2_teams.json @@ -0,0 +1,29 @@ +{ + "type": "beaconbreakers:beacon_breakers", + "map": { + "dimension_options": "minecraft:the_end", + "preset": "minecraft:normal" + }, + "players": { + "min": 1, + "max": 32, + "threshold": 4 + }, + "teams": [ + { + "key": "red", + "name": { + "translate": "color.minecraft.red" + }, + "color": "red" + }, + { + "key": "blue", + "name": { + "translate": "color.minecraft.blue" + }, + "color": "blue" + } + ], + "keep_inventory": true +} diff --git a/src/main/resources/data/beaconbreakers/games/end_beacon_breakers_keep_inventory_4_teams.json b/src/main/resources/data/beaconbreakers/games/end_beacon_breakers_keep_inventory_4_teams.json new file mode 100644 index 0000000..0c77b90 --- /dev/null +++ b/src/main/resources/data/beaconbreakers/games/end_beacon_breakers_keep_inventory_4_teams.json @@ -0,0 +1,43 @@ +{ + "type": "beaconbreakers:beacon_breakers", + "map": { + "dimension_options": "minecraft:the_end", + "preset": "minecraft:normal" + }, + "players": { + "min": 1, + "max": 32, + "threshold": 4 + }, + "teams": [ + { + "key": "red", + "name": { + "translate": "color.minecraft.red" + }, + "color": "red" + }, + { + "key": "green", + "name": { + "translate": "color.minecraft.green" + }, + "color": "green" + }, + { + "key": "blue", + "name": { + "translate": "color.minecraft.blue" + }, + "color": "blue" + }, + { + "key": "yellow", + "name": { + "translate": "color.minecraft.yellow" + }, + "color": "yellow" + } + ], + "keep_inventory": true +} diff --git a/src/main/resources/data/beaconbreakers/games/end_beacon_breakers_tiny_2_teams.json b/src/main/resources/data/beaconbreakers/games/end_beacon_breakers_tiny_2_teams.json new file mode 100644 index 0000000..10a0220 --- /dev/null +++ b/src/main/resources/data/beaconbreakers/games/end_beacon_breakers_tiny_2_teams.json @@ -0,0 +1,31 @@ +{ + "type": "beaconbreakers:beacon_breakers", + "map": { + "dimension_options": "minecraft:the_end", + "preset": "minecraft:normal", + "x": 5, + "z": 5 + }, + "players": { + "min": 1, + "max": 32, + "threshold": 4 + }, + "teams": [ + { + "key": "red", + "name": { + "translate": "color.minecraft.red" + }, + "color": "red" + }, + { + "key": "blue", + "name": { + "translate": "color.minecraft.blue" + }, + "color": "blue" + } + ], + "keep_inventory": true +} diff --git a/src/main/resources/data/beaconbreakers/games/end_beacon_breakers_tiny_4_teams.json b/src/main/resources/data/beaconbreakers/games/end_beacon_breakers_tiny_4_teams.json new file mode 100644 index 0000000..747d444 --- /dev/null +++ b/src/main/resources/data/beaconbreakers/games/end_beacon_breakers_tiny_4_teams.json @@ -0,0 +1,45 @@ +{ + "type": "beaconbreakers:beacon_breakers", + "map": { + "dimension_options": "minecraft:the_end", + "preset": "minecraft:normal", + "x": 5, + "z": 5 + }, + "players": { + "min": 1, + "max": 32, + "threshold": 4 + }, + "teams": [ + { + "key": "red", + "name": { + "translate": "color.minecraft.red" + }, + "color": "red" + }, + { + "key": "green", + "name": { + "translate": "color.minecraft.green" + }, + "color": "green" + }, + { + "key": "blue", + "name": { + "translate": "color.minecraft.blue" + }, + "color": "blue" + }, + { + "key": "yellow", + "name": { + "translate": "color.minecraft.yellow" + }, + "color": "yellow" + } + ], + "keep_inventory": true +} diff --git a/src/main/resources/data/beaconbreakers/games/nether_beacon_breakers_2_teams.json b/src/main/resources/data/beaconbreakers/games/nether_beacon_breakers_2_teams.json new file mode 100644 index 0000000..a4b8ac7 --- /dev/null +++ b/src/main/resources/data/beaconbreakers/games/nether_beacon_breakers_2_teams.json @@ -0,0 +1,28 @@ +{ + "type": "beaconbreakers:beacon_breakers", + "map": { + "dimension_options": "minecraft:the_nether", + "preset": "minecraft:normal" + }, + "players": { + "min": 1, + "max": 32, + "threshold": 4 + }, + "teams": [ + { + "key": "red", + "name": { + "translate": "color.minecraft.red" + }, + "color": "red" + }, + { + "key": "blue", + "name": { + "translate": "color.minecraft.blue" + }, + "color": "blue" + } + ] +} diff --git a/src/main/resources/data/beaconbreakers/games/nether_beacon_breakers_4_teams.json b/src/main/resources/data/beaconbreakers/games/nether_beacon_breakers_4_teams.json new file mode 100644 index 0000000..59761cd --- /dev/null +++ b/src/main/resources/data/beaconbreakers/games/nether_beacon_breakers_4_teams.json @@ -0,0 +1,42 @@ +{ + "type": "beaconbreakers:beacon_breakers", + "map": { + "dimension_options": "minecraft:the_nether", + "preset": "minecraft:normal" + }, + "players": { + "min": 1, + "max": 32, + "threshold": 4 + }, + "teams": [ + { + "key": "red", + "name": { + "translate": "color.minecraft.red" + }, + "color": "red" + }, + { + "key": "green", + "name": { + "translate": "color.minecraft.green" + }, + "color": "green" + }, + { + "key": "blue", + "name": { + "translate": "color.minecraft.blue" + }, + "color": "blue" + }, + { + "key": "yellow", + "name": { + "translate": "color.minecraft.yellow" + }, + "color": "yellow" + } + ] +} diff --git a/src/main/resources/data/beaconbreakers/games/nether_beacon_breakers_keep_inventory_2_teams.json b/src/main/resources/data/beaconbreakers/games/nether_beacon_breakers_keep_inventory_2_teams.json new file mode 100644 index 0000000..25d4a58 --- /dev/null +++ b/src/main/resources/data/beaconbreakers/games/nether_beacon_breakers_keep_inventory_2_teams.json @@ -0,0 +1,29 @@ +{ + "type": "beaconbreakers:beacon_breakers", + "map": { + "dimension_options": "minecraft:the_nether", + "preset": "minecraft:normal" + }, + "players": { + "min": 1, + "max": 32, + "threshold": 4 + }, + "teams": [ + { + "key": "red", + "name": { + "translate": "color.minecraft.red" + }, + "color": "red" + }, + { + "key": "blue", + "name": { + "translate": "color.minecraft.blue" + }, + "color": "blue" + } + ], + "keep_inventory": true +} diff --git a/src/main/resources/data/beaconbreakers/games/nether_beacon_breakers_keep_inventory_4_teams.json b/src/main/resources/data/beaconbreakers/games/nether_beacon_breakers_keep_inventory_4_teams.json new file mode 100644 index 0000000..7967851 --- /dev/null +++ b/src/main/resources/data/beaconbreakers/games/nether_beacon_breakers_keep_inventory_4_teams.json @@ -0,0 +1,43 @@ +{ + "type": "beaconbreakers:beacon_breakers", + "map": { + "dimension_options": "minecraft:the_nether", + "preset": "minecraft:normal" + }, + "players": { + "min": 1, + "max": 32, + "threshold": 4 + }, + "teams": [ + { + "key": "red", + "name": { + "translate": "color.minecraft.red" + }, + "color": "red" + }, + { + "key": "green", + "name": { + "translate": "color.minecraft.green" + }, + "color": "green" + }, + { + "key": "blue", + "name": { + "translate": "color.minecraft.blue" + }, + "color": "blue" + }, + { + "key": "yellow", + "name": { + "translate": "color.minecraft.yellow" + }, + "color": "yellow" + } + ], + "keep_inventory": true +} diff --git a/src/main/resources/data/beaconbreakers/games/nether_beacon_breakers_tiny_2_teams.json b/src/main/resources/data/beaconbreakers/games/nether_beacon_breakers_tiny_2_teams.json new file mode 100644 index 0000000..c491800 --- /dev/null +++ b/src/main/resources/data/beaconbreakers/games/nether_beacon_breakers_tiny_2_teams.json @@ -0,0 +1,31 @@ +{ + "type": "beaconbreakers:beacon_breakers", + "map": { + "dimension_options": "minecraft:the_nether", + "preset": "minecraft:normal", + "x": 5, + "z": 5 + }, + "players": { + "min": 1, + "max": 32, + "threshold": 4 + }, + "teams": [ + { + "key": "red", + "name": { + "translate": "color.minecraft.red" + }, + "color": "red" + }, + { + "key": "blue", + "name": { + "translate": "color.minecraft.blue" + }, + "color": "blue" + } + ], + "keep_inventory": true +} diff --git a/src/main/resources/data/beaconbreakers/games/nether_beacon_breakers_tiny_4_teams.json b/src/main/resources/data/beaconbreakers/games/nether_beacon_breakers_tiny_4_teams.json new file mode 100644 index 0000000..5d240e9 --- /dev/null +++ b/src/main/resources/data/beaconbreakers/games/nether_beacon_breakers_tiny_4_teams.json @@ -0,0 +1,45 @@ +{ + "type": "beaconbreakers:beacon_breakers", + "map": { + "dimension_options": "minecraft:the_nether", + "preset": "minecraft:normal", + "x": 5, + "z": 5 + }, + "players": { + "min": 1, + "max": 32, + "threshold": 4 + }, + "teams": [ + { + "key": "red", + "name": { + "translate": "color.minecraft.red" + }, + "color": "red" + }, + { + "key": "green", + "name": { + "translate": "color.minecraft.green" + }, + "color": "green" + }, + { + "key": "blue", + "name": { + "translate": "color.minecraft.blue" + }, + "color": "blue" + }, + { + "key": "yellow", + "name": { + "translate": "color.minecraft.yellow" + }, + "color": "yellow" + } + ], + "keep_inventory": true +} diff --git a/src/main/resources/data/beaconbreakers/games/standard_beacon_breakers_2_teams.json b/src/main/resources/data/beaconbreakers/games/standard_beacon_breakers_2_teams.json new file mode 100644 index 0000000..dc03bb1 --- /dev/null +++ b/src/main/resources/data/beaconbreakers/games/standard_beacon_breakers_2_teams.json @@ -0,0 +1,29 @@ +{ + "type": "beaconbreakers:beacon_breakers", + "map": { + "dimension_options": "minecraft:overworld", + "preset": "minecraft:normal", + "excluded_biomes": "#minecraft:is_ocean" + }, + "players": { + "min": 1, + "max": 32, + "threshold": 4 + }, + "teams": [ + { + "key": "red", + "name": { + "translate": "color.minecraft.red" + }, + "color": "red" + }, + { + "key": "blue", + "name": { + "translate": "color.minecraft.blue" + }, + "color": "blue" + } + ] +} diff --git a/src/main/resources/data/beaconbreakers/games/standard_beacon_breakers_4_teams.json b/src/main/resources/data/beaconbreakers/games/standard_beacon_breakers_4_teams.json new file mode 100644 index 0000000..5622206 --- /dev/null +++ b/src/main/resources/data/beaconbreakers/games/standard_beacon_breakers_4_teams.json @@ -0,0 +1,43 @@ +{ + "type": "beaconbreakers:beacon_breakers", + "map": { + "dimension_options": "minecraft:overworld", + "preset": "minecraft:normal", + "excluded_biomes": "#minecraft:is_ocean" + }, + "players": { + "min": 1, + "max": 32, + "threshold": 4 + }, + "teams": [ + { + "key": "red", + "name": { + "translate": "color.minecraft.red" + }, + "color": "red" + }, + { + "key": "green", + "name": { + "translate": "color.minecraft.green" + }, + "color": "green" + }, + { + "key": "blue", + "name": { + "translate": "color.minecraft.blue" + }, + "color": "blue" + }, + { + "key": "yellow", + "name": { + "translate": "color.minecraft.yellow" + }, + "color": "yellow" + } + ] +} diff --git a/src/main/resources/data/beaconbreakers/games/standard_beacon_breakers_keep_inventory_2_teams.json b/src/main/resources/data/beaconbreakers/games/standard_beacon_breakers_keep_inventory_2_teams.json new file mode 100644 index 0000000..5e100ad --- /dev/null +++ b/src/main/resources/data/beaconbreakers/games/standard_beacon_breakers_keep_inventory_2_teams.json @@ -0,0 +1,30 @@ +{ + "type": "beaconbreakers:beacon_breakers", + "map": { + "dimension_options": "minecraft:overworld", + "preset": "minecraft:normal", + "excluded_biomes": "#minecraft:is_ocean" + }, + "players": { + "min": 1, + "max": 32, + "threshold": 4 + }, + "teams": [ + { + "key": "red", + "name": { + "translate": "color.minecraft.red" + }, + "color": "red" + }, + { + "key": "blue", + "name": { + "translate": "color.minecraft.blue" + }, + "color": "blue" + } + ], + "keep_inventory": true +} diff --git a/src/main/resources/data/beaconbreakers/games/standard_beacon_breakers_keep_inventory_4_teams.json b/src/main/resources/data/beaconbreakers/games/standard_beacon_breakers_keep_inventory_4_teams.json new file mode 100644 index 0000000..8c5ae90 --- /dev/null +++ b/src/main/resources/data/beaconbreakers/games/standard_beacon_breakers_keep_inventory_4_teams.json @@ -0,0 +1,44 @@ +{ + "type": "beaconbreakers:beacon_breakers", + "map": { + "dimension_options": "minecraft:overworld", + "preset": "minecraft:normal", + "excluded_biomes": "#minecraft:is_ocean" + }, + "players": { + "min": 1, + "max": 32, + "threshold": 4 + }, + "teams": [ + { + "key": "red", + "name": { + "translate": "color.minecraft.red" + }, + "color": "red" + }, + { + "key": "green", + "name": { + "translate": "color.minecraft.green" + }, + "color": "green" + }, + { + "key": "blue", + "name": { + "translate": "color.minecraft.blue" + }, + "color": "blue" + }, + { + "key": "yellow", + "name": { + "translate": "color.minecraft.yellow" + }, + "color": "yellow" + } + ], + "keep_inventory": true +} diff --git a/src/main/resources/data/beaconbreakers/games/standard_beacon_breakers_tiny_2_teams.json b/src/main/resources/data/beaconbreakers/games/standard_beacon_breakers_tiny_2_teams.json new file mode 100644 index 0000000..0c91a2f --- /dev/null +++ b/src/main/resources/data/beaconbreakers/games/standard_beacon_breakers_tiny_2_teams.json @@ -0,0 +1,32 @@ +{ + "type": "beaconbreakers:beacon_breakers", + "map": { + "dimension_options": "minecraft:overworld", + "preset": "minecraft:normal", + "excluded_biomes": "#minecraft:is_ocean", + "x": 5, + "z": 5 + }, + "players": { + "min": 1, + "max": 32, + "threshold": 4 + }, + "teams": [ + { + "key": "red", + "name": { + "translate": "color.minecraft.red" + }, + "color": "red" + }, + { + "key": "blue", + "name": { + "translate": "color.minecraft.blue" + }, + "color": "blue" + } + ], + "keep_inventory": true +} diff --git a/src/main/resources/data/beaconbreakers/games/standard_beacon_breakers_tiny_4_teams.json b/src/main/resources/data/beaconbreakers/games/standard_beacon_breakers_tiny_4_teams.json new file mode 100644 index 0000000..79ddf68 --- /dev/null +++ b/src/main/resources/data/beaconbreakers/games/standard_beacon_breakers_tiny_4_teams.json @@ -0,0 +1,46 @@ +{ + "type": "beaconbreakers:beacon_breakers", + "map": { + "dimension_options": "minecraft:overworld", + "preset": "minecraft:normal", + "excluded_biomes": "#minecraft:is_ocean", + "x": 5, + "z": 5 + }, + "players": { + "min": 1, + "max": 32, + "threshold": 4 + }, + "teams": [ + { + "key": "red", + "name": { + "translate": "color.minecraft.red" + }, + "color": "red" + }, + { + "key": "green", + "name": { + "translate": "color.minecraft.green" + }, + "color": "green" + }, + { + "key": "blue", + "name": { + "translate": "color.minecraft.blue" + }, + "color": "blue" + }, + { + "key": "yellow", + "name": { + "translate": "color.minecraft.yellow" + }, + "color": "yellow" + } + ], + "keep_inventory": true +} diff --git a/src/main/resources/data/beaconbreakers/lang/en_us.json b/src/main/resources/data/beaconbreakers/lang/en_us.json index 6f635ac..d68ceea 100644 --- a/src/main/resources/data/beaconbreakers/lang/en_us.json +++ b/src/main/resources/data/beaconbreakers/lang/en_us.json @@ -1,33 +1,75 @@ { "game.beaconbreakers.amplified_beacon_breakers": "Amplified Beacon Breakers", + "game.beaconbreakers.amplified_beacon_breakers_2_teams": "Amplified Beacon Breakers: 2 Teams", + "game.beaconbreakers.amplified_beacon_breakers_4_teams": "Amplified Beacon Breakers: 4 Teams", "game.beaconbreakers.amplified_beacon_breakers_keep_inventory": "Amplified Beacon Breakers with Keep Inventory", + "game.beaconbreakers.amplified_beacon_breakers_keep_inventory_2_teams": "Amplified Beacon Breakers with Keep Inventory: 2 Teams", + "game.beaconbreakers.amplified_beacon_breakers_keep_inventory_4_teams": "Amplified Beacon Breakers with Keep Inventory: 4 Teams", "game.beaconbreakers.amplified_beacon_breakers_tiny": "Tiny Amplified Beacon Breakers", + "game.beaconbreakers.amplified_beacon_breakers_tiny_2_teams": "Tiny Amplified Beacon Breakers: 2 Teams", + "game.beaconbreakers.amplified_beacon_breakers_tiny_4_teams": "Tiny Amplified Beacon Breakers: 4 Teams", "game.beaconbreakers.caves_beacon_breakers": "Caves Beacon Breakers", + "game.beaconbreakers.caves_beacon_breakers_2_teams": "Caves Beacon Breakers: 2 Teams", + "game.beaconbreakers.caves_beacon_breakers_4_teams": "Caves Beacon Breakers: 4 Teams", "game.beaconbreakers.caves_beacon_breakers_keep_inventory": "Caves Beacon Breakers with Keep Inventory", + "game.beaconbreakers.caves_beacon_breakers_keep_inventory_2_teams": "Caves Beacon Breakers with Keep Inventory: 2 Teams", + "game.beaconbreakers.caves_beacon_breakers_keep_inventory_4_teams": "Caves Beacon Breakers with Keep Inventory: 4 Teams", "game.beaconbreakers.caves_beacon_breakers_tiny": "Tiny Caves Beacon Breakers", + "game.beaconbreakers.caves_beacon_breakers_tiny_2_teams": "Tiny Caves Beacon Breakers: 2 Teams", + "game.beaconbreakers.caves_beacon_breakers_tiny_4_teams": "Tiny Caves Beacon Breakers: 4 Teams", "game.beaconbreakers.end_beacon_breakers": "End Beacon Breakers", + "game.beaconbreakers.end_beacon_breakers_2_teams": "End Beacon Breakers: 2 Teams", + "game.beaconbreakers.end_beacon_breakers_4_teams": "End Beacon Breakers: 4 Teams", "game.beaconbreakers.end_beacon_breakers_keep_inventory": "End Beacon Breakers with Keep Inventory", + "game.beaconbreakers.end_beacon_breakers_keep_inventory_2_teams": "End Beacon Breakers with Keep Inventory: 2 Teams", + "game.beaconbreakers.end_beacon_breakers_keep_inventory_4_teams": "End Beacon Breakers with Keep Inventory: 4 Teams", "game.beaconbreakers.end_beacon_breakers_tiny": "Tiny End Beacon Breakers", + "game.beaconbreakers.end_beacon_breakers_tiny_2_teams": "Tiny End Beacon Breakers: 2 Teams", + "game.beaconbreakers.end_beacon_breakers_tiny_4_teams": "Tiny End Beacon Breakers: 4 Teams", "game.beaconbreakers.floating_islands_beacon_breakers": "Floating Islands Beacon Breakers", + "game.beaconbreakers.floating_islands_beacon_breakers_2_teams": "Floating Islands Beacon Breakers: 2 Teams", + "game.beaconbreakers.floating_islands_beacon_breakers_4_teams": "Floating Islands Beacon Breakers: 4 Teams", "game.beaconbreakers.floating_islands_beacon_breakers_keep_inventory": "Floating Islands Beacon Breakers with Keep Inventory", + "game.beaconbreakers.floating_islands_beacon_breakers_keep_inventory_2_teams": "Floating Islands Beacon Breakers with Keep Inventory: 2 Teams", + "game.beaconbreakers.floating_islands_beacon_breakers_keep_inventory_4_teams": "Floating Islands Beacon Breakers with Keep Inventory: 4 Teams", "game.beaconbreakers.floating_islands_beacon_breakers_tiny": "Tiny Floating Islands Beacon Breakers", + "game.beaconbreakers.floating_islands_beacon_breakers_tiny_2_teams": "Tiny Floating Islands Beacon Breakers: 2 Teams", + "game.beaconbreakers.floating_islands_beacon_breakers_tiny_4_teams": "Tiny Floating Islands Beacon Breakers: 4 Teams", "game.beaconbreakers.nether_beacon_breakers": "Nether Beacon Breakers", + "game.beaconbreakers.nether_beacon_breakers_2_teams": "Nether Beacon Breakers: 2 Teams", + "game.beaconbreakers.nether_beacon_breakers_4_teams": "Nether Beacon Breakers: 4 Teams", "game.beaconbreakers.nether_beacon_breakers_keep_inventory": "Nether Beacon Breakers with Keep Inventory", + "game.beaconbreakers.nether_beacon_breakers_keep_inventory_2_teams": "Nether Beacon Breakers with Keep Inventory: 2 Teams", + "game.beaconbreakers.nether_beacon_breakers_keep_inventory_4_teams": "Nether Beacon Breakers with Keep Inventory: 4 Teams", "game.beaconbreakers.nether_beacon_breakers_tiny": "Tiny Nether Beacon Breakers", + "game.beaconbreakers.nether_beacon_breakers_tiny_2_teams": "Tiny Nether Beacon Breakers: 2 Teams", + "game.beaconbreakers.nether_beacon_breakers_tiny_4_teams": "Tiny Nether Beacon Breakers: 4 Teams", "game.beaconbreakers.standard_beacon_breakers": "Beacon Breakers", + "game.beaconbreakers.standard_beacon_breakers_2_teams": "Beacon Breakers: 2 Teams", + "game.beaconbreakers.standard_beacon_breakers_4_teams": "Beacon Breakers: 4 Teams", "game.beaconbreakers.standard_beacon_breakers_keep_inventory": "Beacon Breakers with Keep Inventory", + "game.beaconbreakers.standard_beacon_breakers_keep_inventory_2_teams": "Beacon Breakers with Keep Inventory: 2 Teams", + "game.beaconbreakers.standard_beacon_breakers_keep_inventory_4_teams": "Beacon Breakers with Keep Inventory: 4 Teams", "game.beaconbreakers.standard_beacon_breakers_tiny": "Tiny Beacon Breakers", + "game.beaconbreakers.standard_beacon_breakers_tiny_2_teams": "Tiny Beacon Breakers: 2 Teams", + "game.beaconbreakers.standard_beacon_breakers_tiny_4_teams": "Tiny Beacon Breakers: 4 Teams", "gameType.beaconbreakers.beacon_breakers": "Beacon Breakers", "text.beaconbreakers.eliminate": "%s has been eliminated!", "text.beaconbreakers.invulnerability.title": "Remaining Invulnerability", "text.beaconbreakers.invulnerability.ended": "Beacons are no longer invulnerable to mining.", "text.beaconbreakers.win": "%s has won the game!", "text.beaconbreakers.win.none": "Nobody won the game!", + "text.beaconbreakers.win.team": "The %s team has won the game!", "text.beaconbreakers.beacon_break": "%s's beacon was broken by %s!", "text.beaconbreakers.beacon_break.explosion": "%s's beacon was blown up by %s!", "text.beaconbreakers.beacon_break.explosion.unattributed": "%s's beacon was blown up!", + "text.beaconbreakers.beacon_break.team": "The %s team's beacon was broken by %s!", + "text.beaconbreakers.beacon_break.team.explosion": "The %s team's beacon was blown up by %s!", + "text.beaconbreakers.beacon_break.team.explosion.unattributed": "The %s team's beacon was blown up!", + "text.beaconbreakers.beacon_break.team.unattributed": "The %s team's beacon was broken!", "text.beaconbreakers.beacon_break.unattributed": "%s's beacon was broken!", "text.beaconbreakers.cannot_break_own_beacon": "You cannot break your own beacon after the invulnerability period has ended.", + "text.beaconbreakers.cannot_break_own_beacon.team": "You cannot break your own team's beacon after the invulnerability period has ended.", "text.beaconbreakers.cannot_break_invulnerable_beacon": "You cannot break a beacon during the invulnerability period.", "text.beaconbreakers.cannot_place_out_of_bounds_beacon": "You cannot place a beacon outside of the map." } \ No newline at end of file