From 7f09ec7abaa9bb6b8325f56250562c97d7d3a799 Mon Sep 17 00:00:00 2001 From: anhgelus Date: Wed, 21 Aug 2024 23:31:37 +0000 Subject: feat(game): create game and command to manage it --- src/main/java/world/anhgelus/molehunt/Game.java | 119 ++++++++++++++++++++- .../java/world/anhgelus/molehunt/Molehunt.java | 49 +++++++++ .../world/anhgelus/molehunt/utils/TimeUtils.java | 53 ++++++++- src/main/resources/molehunt.mixins.json | 1 - 4 files changed, 217 insertions(+), 5 deletions(-) (limited to 'src/main') diff --git a/src/main/java/world/anhgelus/molehunt/Game.java b/src/main/java/world/anhgelus/molehunt/Game.java index f084bfd..537055c 100644 --- a/src/main/java/world/anhgelus/molehunt/Game.java +++ b/src/main/java/world/anhgelus/molehunt/Game.java @@ -1,2 +1,117 @@ -package world.anhgelus.molehunt;public class Game { -} +package world.anhgelus.molehunt; + +import net.minecraft.network.packet.s2c.play.OverlayMessageS2CPacket; +import net.minecraft.network.packet.s2c.play.SubtitleS2CPacket; +import net.minecraft.network.packet.s2c.play.TitleFadeS2CPacket; +import net.minecraft.network.packet.s2c.play.TitleS2CPacket; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.text.Text; +import net.minecraft.world.GameRules; +import world.anhgelus.molehunt.utils.TimeUtils; + +import java.util.*; +import java.util.concurrent.ThreadLocalRandom; + +public class Game { + + final private Timer timer = new Timer(); + final public static int DEFAULT_TIME = 90*60; // 1:30 + private int remaining = DEFAULT_TIME; + + final private MinecraftServer server; + + final private List moles = new ArrayList<>(); + + public Game(MinecraftServer server) { + this.server = server; + } + + public void start() { + final int n = (server.getCurrentPlayerCount() - server.getCurrentPlayerCount() % 4)/4; + final var playerManager = server.getPlayerManager(); + final var players = playerManager.getPlayerList(); + for (int i = 0; i < n; i++) { + final var r = ThreadLocalRandom.current().nextInt(0, players.size()); + final var mole = players.get(r); + if (mole == null) throw new IllegalStateException("Mole is null!"); + moles.add(mole); + players.remove(r); + } + + server.getGameRules().get(GameRules.SHOW_DEATH_MESSAGES).set(false, server); + server.getGameRules().get(GameRules.ANNOUNCE_ADVANCEMENTS).set(false, server); + + final var title = new TitleS2CPacket(Text.of("You are...")); + final var timing = new TitleFadeS2CPacket(20, 40, 20); + playerManager.getPlayerList().forEach(p -> { + p.networkHandler.sendPacket(timing); + p.networkHandler.sendPacket(title); + }); + timer.schedule(new TimerTask() { + @Override + public void run() { + playerManager.getPlayerList().forEach(p -> { + p.networkHandler.sendPacket(timing); + if (moles.contains(p)) { + p.networkHandler.sendPacket(new TitleS2CPacket(Text.of("The Mole!"))); + p.networkHandler.sendPacket(new SubtitleS2CPacket(Text.of("get the list of moles with /molehunt moles"))); + } else { + p.networkHandler.sendPacket(new TitleS2CPacket(Text.of("Not the Mole!"))); + } + }); + server.getOverworld().setTimeOfDay(0); + timer.scheduleAtFixedRate(new TimerTask() { + @Override + public void run() { + remaining--; + playerManager.sendToAll(new OverlayMessageS2CPacket(Text.of(getShortRemainingText()))); + if (remaining == 0) { + end(); + } + } + }, 1000L, 1000L); + timer.scheduleAtFixedRate(new TimerTask() { + @Override + public void run() { + playerManager.broadcast(getRemainingText(), false); + } + }, 10*60*1000L, 10*60*1000L); + } + }, 4*1000); + } + + public void stop() { + server.getPlayerManager().broadcast(Text.of("Game stopped"), false); + end(); + } + + public void end() { + timer.cancel(); + // affiche les gagnants + } + + public int getRemaining() { + return remaining; + } + + public Text getRemainingText() { + return Text.of("Time remaining: "+ TimeUtils.printTime(remaining)); + } + + public Text getShortRemainingText() { + return Text.of("§c" + TimeUtils.printShortTime(remaining)); + } + + public List getMoles() { + return moles; + } + + public boolean isAMole(ServerPlayerEntity player) { + return moles.contains(player); + } + + public boolean gameFinished() { + return new HashSet<>(moles).containsAll(server.getPlayerManager().getPlayerList()); + } +} diff --git a/src/main/java/world/anhgelus/molehunt/Molehunt.java b/src/main/java/world/anhgelus/molehunt/Molehunt.java index a1333a4..4edaf24 100644 --- a/src/main/java/world/anhgelus/molehunt/Molehunt.java +++ b/src/main/java/world/anhgelus/molehunt/Molehunt.java @@ -1,16 +1,65 @@ package world.anhgelus.molehunt; +import com.mojang.brigadier.Command; +import com.mojang.brigadier.arguments.StringArgumentType; import net.fabricmc.api.ModInitializer; +import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback; +import net.fabricmc.fabric.api.entity.event.v1.ServerLivingEntityEvents; +import net.fabricmc.fabric.api.message.v1.ServerMessageEvents; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.text.Text; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.Objects; +import java.util.stream.Collectors; + +import static net.minecraft.server.command.CommandManager.literal; + + public class Molehunt implements ModInitializer { public static final String MOD_ID = "molehunt"; public static final Logger LOGGER = LoggerFactory.getLogger(MOD_ID); + public Game game; @Override public void onInitialize() { LOGGER.info("Initializing Molehunt"); + + final var command = literal("molehunt"); + command.then(literal("start").requires(source -> source.hasPermissionLevel(1)).executes(context -> { + game = new Game(context.getSource().getServer()); + game.start(); + return Command.SINGLE_SUCCESS; + })); + command.then(literal("time").executes(context -> { + context.getSource().sendFeedback(() -> game.getRemainingText(), false); + return Command.SINGLE_SUCCESS; + })); + command.then(literal("moles").requires(source -> { + if (game == null) { + return false; + } + return game.isAMole(source.getPlayer()); + }).executes(context -> { + context.getSource().sendFeedback(() -> Text.literal( + "List of moles: " + game.getMoles().stream().map(ServerPlayerEntity::getDisplayName).filter(Objects::nonNull).map(Text::toString).collect(Collectors.joining(", "))), + false); + return Command.SINGLE_SUCCESS; + })); + command.then(literal("stop").requires(source -> source.hasPermissionLevel(1)).executes(context -> { + game.stop(); + return Command.SINGLE_SUCCESS; + })); + + CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> dispatcher.register(command)); + +// ServerMessageEvents.ALLOW_CHAT_MESSAGE.register((message, sender, params) -> false); + + ServerLivingEntityEvents.AFTER_DEATH.register((entity, damageSource) -> { + if (!(entity instanceof ServerPlayerEntity)) return; + if (game.gameFinished()) game.end(); + }); } } diff --git a/src/main/java/world/anhgelus/molehunt/utils/TimeUtils.java b/src/main/java/world/anhgelus/molehunt/utils/TimeUtils.java index 8db8eb0..859f574 100644 --- a/src/main/java/world/anhgelus/molehunt/utils/TimeUtils.java +++ b/src/main/java/world/anhgelus/molehunt/utils/TimeUtils.java @@ -1,2 +1,51 @@ -package world.anhgelus.molehunt.utils;public class TimeUtils { -} +package world.anhgelus.molehunt.utils; + +public class TimeUtils { + + private record Time(long hours, long minutes, long seconds) {} + + public static String printTime(long time) { + final var pt = generateTime(time); + + StringBuilder sb = new StringBuilder(); + if (pt.hours != 0) { + sb.append(pt.hours).append(" hours "); + } + if (pt.minutes != 0 || pt.hours != 0) { + sb.append(pt.minutes).append(" minutes "); + } + sb.append(pt.seconds).append(" seconds"); + + return sb.toString(); + } + + public static String printShortTime(long time) { + final var pt = generateTime(time); + + return padLeft(pt.hours) + ":" + + padLeft(pt.minutes) + ":" + + padLeft(pt.seconds); + } + + private static Time generateTime(long time) { + long hours = 0; + if (time > 3600) { + hours = Math.floorDiv(time, 3600); + } + long minutes = 0; + if (hours != 0 || time > 60) { + minutes = Math.floorDiv(time - hours * 3600, 60); + } + long seconds = (long) Math.floor(time - hours * 3600 - minutes * 60); + return new Time(hours, minutes, seconds); + } + + private static String padLeft(long n) { + if (n < 10 && n != 0) { + return "0" + Math.round(n); + } else if (n == 0) { + return "00"; + } + return Long.toString(Math.round(n)); + } +} diff --git a/src/main/resources/molehunt.mixins.json b/src/main/resources/molehunt.mixins.json index a691723..5b76af8 100644 --- a/src/main/resources/molehunt.mixins.json +++ b/src/main/resources/molehunt.mixins.json @@ -4,7 +4,6 @@ "package": "world.anhgelus.molehunt.mixin", "compatibilityLevel": "JAVA_21", "mixins": [ - "NoPlayerList" ], "injectors": { "defaultRequire": 1 -- cgit v1.2.3