diff --git a/src/main/java/me/ellieis/Sabotage/game/custom/blocks/SabotageChest.java b/src/main/java/me/ellieis/Sabotage/game/custom/blocks/SabotageChest.java index 52ca787..676294e 100644 --- a/src/main/java/me/ellieis/Sabotage/game/custom/blocks/SabotageChest.java +++ b/src/main/java/me/ellieis/Sabotage/game/custom/blocks/SabotageChest.java @@ -3,6 +3,7 @@ import com.google.common.util.concurrent.AtomicDouble; import eu.pb4.polymer.core.api.block.PolymerBlock; import me.ellieis.Sabotage.Sabotage; +import me.ellieis.Sabotage.game.GameStates; import me.ellieis.Sabotage.game.phase.SabotageActive; import net.minecraft.block.*; import net.minecraft.block.entity.BlockEntity; @@ -83,17 +84,17 @@ public Block getPolymerBlock(BlockState state) { @Override public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity plr, Hand hand, BlockHitResult hit) { - boolean isInGame = false; + SabotageActive game = null; - for (SabotageActive game : Sabotage.activeGames) { - if (game.getWorld().equals(world)) { - isInGame = true; + for (SabotageActive activeGame : Sabotage.activeGames) { + if (activeGame.getWorld().equals(world)) { + game = activeGame; break; } } - if (isInGame) { - plr.playSound(SoundEvents.BLOCK_CHEST_CLOSE, SoundCategory.BLOCKS, 1, 1.2f); + if (game != null && game.gameState != GameStates.COUNTDOWN) { + world.playSound(null, pos, SoundEvents.BLOCK_CHEST_CLOSE, SoundCategory.BLOCKS, 1, 1.2f); plr.getInventory().insertStack(getItemDrop()); world.setBlockState(pos, Blocks.AIR.getDefaultState()); } diff --git a/src/main/java/me/ellieis/Sabotage/game/custom/blocks/TesterSign.java b/src/main/java/me/ellieis/Sabotage/game/custom/blocks/TesterSign.java index a987762..3659853 100644 --- a/src/main/java/me/ellieis/Sabotage/game/custom/blocks/TesterSign.java +++ b/src/main/java/me/ellieis/Sabotage/game/custom/blocks/TesterSign.java @@ -13,6 +13,7 @@ import net.minecraft.text.Text; import net.minecraft.util.ActionResult; import net.minecraft.util.DyeColor; +import net.minecraft.util.Formatting; import net.minecraft.util.Hand; import net.minecraft.util.hit.BlockHitResult; import net.minecraft.util.math.BlockPos; @@ -33,9 +34,12 @@ public Block getPolymerBlock(BlockState state) { public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) { // to-do: tester functionality if (!world.isClient()) { + ServerPlayerEntity plr = (ServerPlayerEntity) player; for (SabotageActive game : Sabotage.activeGames) { if (game.getWorld().equals(world)) { - game.testEntity((ServerPlayerEntity) player); + if (!game.testEntity(plr)) { + plr.sendMessage(Text.translatable("sabotage.tester.fail").formatted(Formatting.YELLOW)); + } break; } } diff --git a/src/main/java/me/ellieis/Sabotage/game/phase/SabotageActive.java b/src/main/java/me/ellieis/Sabotage/game/phase/SabotageActive.java index 3326f99..5e15242 100644 --- a/src/main/java/me/ellieis/Sabotage/game/phase/SabotageActive.java +++ b/src/main/java/me/ellieis/Sabotage/game/phase/SabotageActive.java @@ -80,7 +80,7 @@ public class SabotageActive { private long startTime; private long endTime; private GameActivity activity; - private GameStates gameState = GameStates.COUNTDOWN; + public GameStates gameState = GameStates.COUNTDOWN; private GlobalWidgets widgets; private SidebarWidget globalSidebar; private SidebarWidget innocentSidebar; @@ -322,6 +322,107 @@ public EndReason checkWinCondition() { } return EndReason.NONE; } + + private void changeTesterWool(Roles role) { + Block wool = (role == Roles.SABOTEUR) ? Blocks.RED_WOOL : + (role == Roles.DETECTIVE) ? Blocks.BLUE_WOOL : + (role == Roles.INNOCENT) ? Blocks.GREEN_WOOL : Blocks.WHITE_WOOL; + for (BlockPos testerWool : map.getTesterWools()) { + world.setBlockState(testerWool, wool.getDefaultState()); + } + taskScheduler.addTask(new Task((int) (world.getTime() + 200), (gameSpace) -> { + for (BlockPos testerWool : map.getTesterWools()) { + world.setBlockState(testerWool, Blocks.WHITE_WOOL.getDefaultState()); + } + isTesterOnCooldown = false; + })); + + } + + // portable tester onlu + public void testEntity(ServerPlayerEntity plr, LivingEntity entity) { + if (plr.isSpectator() || entity.isSpectator()) return; + if (plr.hasStatusEffect(StatusEffects.SLOWNESS) || entity.hasStatusEffect(StatusEffects.SLOWNESS)) { + // either player is already testing or being tested, abort + return; + } + Roles role = getPlayerRole(plr); + if (role == Roles.DETECTIVE) { + if (entity.isPlayer()) { + final ServerPlayerEntity playerEntity = (ServerPlayerEntity) entity; + plr.addStatusEffect(new StatusEffectInstance(StatusEffects.BLINDNESS, 100)); + plr.addStatusEffect(new StatusEffectInstance(StatusEffects.SLOWNESS, 200)); + playerEntity.addStatusEffect(new StatusEffectInstance(StatusEffects.BLINDNESS, 100)); + playerEntity.addStatusEffect(new StatusEffectInstance(StatusEffects.SLOWNESS, 200)); + int revealTime = (int) world.getTime() + 200; + Consumer func = (gameSpace) -> { + Roles plrRole = getPlayerRole(playerEntity); + gameSpace.getPlayers().sendMessage( + Text.translatable("sabotage.detective_shears_reveal", + playerEntity.getName(), + Text.translatable("sabotage." + ( + (plrRole == Roles.SABOTEUR) ? "saboteur" : + (plrRole == Roles.DETECTIVE) ? "detective" : "innocent") + ).formatted(getRoleColor(plrRole)))); + }; + taskScheduler.addTask(new Task(revealTime, func)); + } + } + } + + // tester only + public boolean testEntity(ServerPlayerEntity plr) { + if (plr.isSpectator()) return true; + if (gameState == GameStates.ACTIVE) { + if (isTesterOnCooldown) { + return false; + } + isTesterOnCooldown = true; + plr.addStatusEffect(new StatusEffectInstance(StatusEffects.BLINDNESS, 100)); + plr.addStatusEffect(new StatusEffectInstance(StatusEffects.SLOWNESS, 200)); + for (BlockPos blockPos : map.getTesterCloseRegion().getBounds()) { + world.setBlockState(blockPos, Blocks.IRON_BARS.getDefaultState()); + } + world.playSound(null, plr.getBlockPos(), SoundEvents.BLOCK_IRON_DOOR_CLOSE, SoundCategory.BLOCKS, 1, 0.5f); + gameSpace.getPlayers().sendMessage(Text.translatable("sabotage.tester.message", plr.getName(), 10).formatted(Formatting.YELLOW)); + int revealTime = (int) world.getTime() + 200; + Consumer reminder = (gameSpace) -> { + gameSpace.getPlayers().sendMessage(Text.translatable("sabotage.tester.message", plr.getName(), 5).formatted(Formatting.YELLOW)); + }; + Consumer reveal = (gameSpace) -> { + Roles plrRole = getPlayerRole(plr); + // isTesterOnCooldown is changed in this method + changeTesterWool(plrRole); + for (BlockPos blockPos : map.getTesterCloseRegion().getBounds()) { + world.setBlockState(blockPos, Blocks.AIR.getDefaultState()); + } + world.playSound(null, plr.getBlockPos(), SoundEvents.BLOCK_IRON_DOOR_OPEN, SoundCategory.BLOCKS, 1, 0.5f); + }; + taskScheduler.addTask(new Task(revealTime - 100, reminder)); + taskScheduler.addTask(new Task(revealTime, reveal)); + } + return true; + } + private void awardPlayerKill(ServerPlayerEntity attacker, ServerPlayerEntity plr, Roles plrRole, int innocentKarma, int detectiveKarma, int saboteurKarma) { + // attacker is confirmed innocent or detective + switch(plrRole) { + case INNOCENT -> { + karmaManager.decrementKarma(attacker, innocentKarma); + attacker.sendMessage(createAttackerKillMessage(plr, -innocentKarma)); + } + + case DETECTIVE -> { + karmaManager.decrementKarma(attacker, detectiveKarma); + attacker.sendMessage(createAttackerKillMessage(plr, -detectiveKarma)); + } + + case SABOTEUR -> { + karmaManager.incrementKarma(attacker, saboteurKarma); + attacker.sendMessage(createAttackerKillMessage(plr, saboteurKarma)); + } + } + } + public void Start() { gameState = GameStates.ACTIVE; pickRoles(); @@ -521,88 +622,6 @@ private void onPlayerRemove(ServerPlayerEntity plr) { } } } - private void changeTesterWool(Roles role) { - Block wool = (role == Roles.SABOTEUR) ? Blocks.RED_WOOL : - (role == Roles.DETECTIVE) ? Blocks.BLUE_WOOL : - (role == Roles.INNOCENT) ? Blocks.GREEN_WOOL : Blocks.WHITE_WOOL; - for (BlockPos testerWool : map.getTesterWools()) { - world.setBlockState(testerWool, wool.getDefaultState()); - } - taskScheduler.addTask(new Task((int) (world.getTime() + 200), (gameSpace) -> { - for (BlockPos testerWool : map.getTesterWools()) { - world.setBlockState(testerWool, Blocks.WHITE_WOOL.getDefaultState()); - } - })); - - } - - // portable tester onlu - public void testEntity(ServerPlayerEntity plr, LivingEntity entity) { - Roles role = getPlayerRole(plr); - if (role == Roles.DETECTIVE) { - if (entity.isPlayer()) { - final ServerPlayerEntity playerEntity = (ServerPlayerEntity) entity; - plr.addStatusEffect(new StatusEffectInstance(StatusEffects.BLINDNESS, 40)); - plr.addStatusEffect(new StatusEffectInstance(StatusEffects.SLOWNESS, 100)); - playerEntity.addStatusEffect(new StatusEffectInstance(StatusEffects.BLINDNESS, 100)); - playerEntity.addStatusEffect(new StatusEffectInstance(StatusEffects.SLOWNESS, 200)); - int revealTime = (int) world.getTime() + 200; - Consumer func = (gameSpace) -> { - Roles plrRole = getPlayerRole(playerEntity); - gameSpace.getPlayers().sendMessage( - Text.translatable("sabotage.detective_shears_reveal", - playerEntity.getName(), - Text.translatable("sabotage." + ( - (plrRole == Roles.SABOTEUR) ? "saboteur" : - (plrRole == Roles.DETECTIVE) ? "detective" : "innocent") - ).formatted(getRoleColor(plrRole)))); - }; - taskScheduler.addTask(new Task(revealTime, func)); - } - } - } - - // tester only - public void testEntity(ServerPlayerEntity plr) { - if (gameState == GameStates.ACTIVE) { - if (isTesterOnCooldown) { - return; - } - plr.addStatusEffect(new StatusEffectInstance(StatusEffects.BLINDNESS, 100)); - plr.addStatusEffect(new StatusEffectInstance(StatusEffects.SLOWNESS, 200)); - for (BlockPos blockPos : map.getTesterCloseRegion().getBounds()) { - world.setBlockState(blockPos, Blocks.IRON_BARS.getDefaultState()); - } - int revealTime = (int) world.getTime() + 200; - Consumer func = (gameSpace) -> { - Roles plrRole = getPlayerRole(plr); - changeTesterWool(plrRole); - for (BlockPos blockPos : map.getTesterCloseRegion().getBounds()) { - world.setBlockState(blockPos, Blocks.AIR.getDefaultState()); - } - }; - taskScheduler.addTask(new Task(revealTime, func)); - } - } - private void awardPlayerKill(ServerPlayerEntity attacker, ServerPlayerEntity plr, Roles plrRole, int innocentKarma, int detectiveKarma, int saboteurKarma) { - // attacker is confirmed innocent or detective - switch(plrRole) { - case INNOCENT -> { - karmaManager.decrementKarma(attacker, innocentKarma); - attacker.sendMessage(createAttackerKillMessage(plr, -innocentKarma)); - } - - case DETECTIVE -> { - karmaManager.decrementKarma(attacker, detectiveKarma); - attacker.sendMessage(createAttackerKillMessage(plr, -detectiveKarma)); - } - - case SABOTEUR -> { - karmaManager.incrementKarma(attacker, saboteurKarma); - attacker.sendMessage(createAttackerKillMessage(plr, saboteurKarma)); - } - } - } public void onTick() { long time = world.getTime(); diff --git a/src/main/resources/data/sabotage/games/village.json b/src/main/resources/data/sabotage/games/village.json index 73ff1f8..ee0480e 100644 --- a/src/main/resources/data/sabotage/games/village.json +++ b/src/main/resources/data/sabotage/games/village.json @@ -5,7 +5,7 @@ "grace_period": 15, "time_limit": 1200, "end_delay": 10, - "chest_count": 50, + "chest_count": 125, "innocent": { "innocent_karma_penalty": 20, "detective_karma_penalty": 100, diff --git a/src/main/resources/data/sabotage/lang/en_us.json b/src/main/resources/data/sabotage/lang/en_us.json index 90babf3..c4b3382 100644 --- a/src/main/resources/data/sabotage/lang/en_us.json +++ b/src/main/resources/data/sabotage/lang/en_us.json @@ -12,6 +12,8 @@ "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.tester.message": "%s is being tested. Check back in %s seconds for the result", + "sabotage.tester.fail": "This tester is on cooldown. Try again in a few seconds.", "sabotage.detective_shears_reveal": "%s was a %s!", "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.game_end": "The game has ended! The following players were saboteurs: %s", diff --git a/src/main/resources/data/sabotage/map_templates/village.nbt b/src/main/resources/data/sabotage/map_templates/village.nbt index 3ff80bf..9649a2b 100644 Binary files a/src/main/resources/data/sabotage/map_templates/village.nbt and b/src/main/resources/data/sabotage/map_templates/village.nbt differ