aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/client/java/world/anhgelus/molehunt/client/MolehuntClient.java72
-rw-r--r--src/client/java/world/anhgelus/molehunt/client/mixin/NoCustomizableSkinOverlay.java66
-rw-r--r--src/client/java/world/anhgelus/molehunt/client/mixin/NoNametags.java10
-rw-r--r--src/client/java/world/anhgelus/molehunt/client/mixin/NoPlayerListHud.java10
-rw-r--r--src/client/java/world/anhgelus/molehunt/client/mixin/NoSkin.java22
-rw-r--r--src/client/resources/assets/molehunt/lang/en_us.json54
-rw-r--r--src/client/resources/assets/molehunt/lang/fr_fr.json54
-rw-r--r--src/client/resources/molehunt.client.mixins.json26
-rw-r--r--src/main/java/world/anhgelus/molehunt/Molehunt.java364
-rw-r--r--src/main/java/world/anhgelus/molehunt/config/Config.java262
-rw-r--r--src/main/java/world/anhgelus/molehunt/config/ConfigPayload.java26
-rw-r--r--src/main/java/world/anhgelus/molehunt/config/SimpleConfig.java408
-rw-r--r--src/main/java/world/anhgelus/molehunt/game/Game.java348
-rw-r--r--src/main/java/world/anhgelus/molehunt/game/GamePayload.java22
-rw-r--r--src/main/java/world/anhgelus/molehunt/mixin/NoJoinLeaveMessage.java12
-rw-r--r--src/main/java/world/anhgelus/molehunt/mixin/NoMsgCommand.java8
-rw-r--r--src/main/java/world/anhgelus/molehunt/mixin/NoPortals.java10
-rw-r--r--src/main/java/world/anhgelus/molehunt/mixin/WorldTimerAccess.java60
-rw-r--r--src/main/java/world/anhgelus/molehunt/timer/TickTask.java118
-rw-r--r--src/main/java/world/anhgelus/molehunt/timer/TimerAccess.java110
-rw-r--r--src/main/java/world/anhgelus/molehunt/utils/TimeUtils.java55
-rw-r--r--src/main/resources/fabric.mod.json69
-rw-r--r--src/main/resources/molehunt.mixins.json26
23 files changed, 1106 insertions, 1106 deletions
diff --git a/src/client/java/world/anhgelus/molehunt/client/MolehuntClient.java b/src/client/java/world/anhgelus/molehunt/client/MolehuntClient.java
index 18aca76..d479674 100644
--- a/src/client/java/world/anhgelus/molehunt/client/MolehuntClient.java
+++ b/src/client/java/world/anhgelus/molehunt/client/MolehuntClient.java
@@ -10,40 +10,40 @@ import world.anhgelus.molehunt.game.GamePayload;
public class MolehuntClient implements ClientModInitializer {
- public static final Logger LOGGER = LoggerFactory.getLogger(Molehunt.MOD_ID + " - client");
-
- private static boolean SHOW_SKINS = false;
- private static boolean SHOW_NAMETAGS = false;
- private static boolean SHOW_TAB = false;
-
- private static boolean GAME_STARTED = false;
-
- public static boolean showSkins() {
- return SHOW_SKINS;
- }
-
- public static boolean showNameTags() {
- return SHOW_NAMETAGS;
- }
-
- public static boolean showTab() {
- return SHOW_TAB;
- }
-
- public static boolean gameStarted() {
- return GAME_STARTED;
- }
-
- @Override
- public void onInitializeClient() {
- LOGGER.info("Initializing client");
- ClientPlayNetworking.registerGlobalReceiver(ConfigPayload.ID, (payload, context) -> {
- SHOW_SKINS = payload.showSkins();
- SHOW_NAMETAGS = payload.showNametags();
- SHOW_TAB = payload.showTab();
- });
- ClientPlayNetworking.registerGlobalReceiver(GamePayload.ID, (payload, context) -> {
- GAME_STARTED = payload.gameLaunched();
- });
- }
+ public static final Logger LOGGER = LoggerFactory.getLogger(Molehunt.MOD_ID + " - client");
+
+ private static boolean SHOW_SKINS = false;
+ private static boolean SHOW_NAMETAGS = false;
+ private static boolean SHOW_TAB = false;
+
+ private static boolean GAME_STARTED = false;
+
+ public static boolean showSkins() {
+ return SHOW_SKINS;
+ }
+
+ public static boolean showNameTags() {
+ return SHOW_NAMETAGS;
+ }
+
+ public static boolean showTab() {
+ return SHOW_TAB;
+ }
+
+ public static boolean gameStarted() {
+ return GAME_STARTED;
+ }
+
+ @Override
+ public void onInitializeClient() {
+ LOGGER.info("Initializing client");
+ ClientPlayNetworking.registerGlobalReceiver(ConfigPayload.ID, (payload, context) -> {
+ SHOW_SKINS = payload.showSkins();
+ SHOW_NAMETAGS = payload.showNametags();
+ SHOW_TAB = payload.showTab();
+ });
+ ClientPlayNetworking.registerGlobalReceiver(GamePayload.ID, (payload, context) -> {
+ GAME_STARTED = payload.gameLaunched();
+ });
+ }
}
diff --git a/src/client/java/world/anhgelus/molehunt/client/mixin/NoCustomizableSkinOverlay.java b/src/client/java/world/anhgelus/molehunt/client/mixin/NoCustomizableSkinOverlay.java
index c394dd3..95d85d9 100644
--- a/src/client/java/world/anhgelus/molehunt/client/mixin/NoCustomizableSkinOverlay.java
+++ b/src/client/java/world/anhgelus/molehunt/client/mixin/NoCustomizableSkinOverlay.java
@@ -15,41 +15,41 @@ import world.anhgelus.molehunt.client.MolehuntClient;
@Mixin(Options.class)
public abstract class NoCustomizableSkinOverlay {
- @Unique
- private static int fullParts;
+ @Unique
+ private static int fullParts;
- static {
- for (PlayerModelPart part : PlayerModelPart.values()) {
- fullParts |= part.getMask();
- }
- }
-
- @Shadow
- protected Minecraft minecraft;
+ static {
+ for (PlayerModelPart part : PlayerModelPart.values()) {
+ fullParts |= part.getMask();
+ }
+ }
- @Inject(at = @At("HEAD"), method = "setModelPart", cancellable = true)
- public void togglePlayerModelPart(PlayerModelPart part, boolean enabled, CallbackInfo ci) {
- if (MolehuntClient.showSkins()) return;
- ci.cancel();
- }
+ @Shadow
+ protected Minecraft minecraft;
- @Inject(at = @At("RETURN"), method = "buildPlayerInformation", cancellable = true)
- public void buildPlayerInformation(CallbackInfoReturnable<ClientInformation> cir) {
- if (MolehuntClient.showSkins()) return;
- final var opts = (Options) (Object) this;
+ @Inject(at = @At("HEAD"), method = "setModelPart", cancellable = true)
+ public void togglePlayerModelPart(PlayerModelPart part, boolean enabled, CallbackInfo ci) {
+ if (MolehuntClient.showSkins()) return;
+ ci.cancel();
+ }
- cir.setReturnValue(
- new ClientInformation(
- opts.languageCode,
- opts.renderDistance().get(),
- opts.chatVisibility().get(),
- opts.chatColors().get(),
- fullParts,
- opts.mainHand().get(),
- this.minecraft.isTextFilteringEnabled(),
- opts.allowServerListing().get(),
- opts.particles().get()
- )
- );
- }
+ @Inject(at = @At("RETURN"), method = "buildPlayerInformation", cancellable = true)
+ public void buildPlayerInformation(CallbackInfoReturnable<ClientInformation> cir) {
+ if (MolehuntClient.showSkins()) return;
+ final var opts = (Options) (Object) this;
+
+ cir.setReturnValue(
+ new ClientInformation(
+ opts.languageCode,
+ opts.renderDistance().get(),
+ opts.chatVisibility().get(),
+ opts.chatColors().get(),
+ fullParts,
+ opts.mainHand().get(),
+ this.minecraft.isTextFilteringEnabled(),
+ opts.allowServerListing().get(),
+ opts.particles().get()
+ )
+ );
+ }
}
diff --git a/src/client/java/world/anhgelus/molehunt/client/mixin/NoNametags.java b/src/client/java/world/anhgelus/molehunt/client/mixin/NoNametags.java
index 937f45e..a50c3e3 100644
--- a/src/client/java/world/anhgelus/molehunt/client/mixin/NoNametags.java
+++ b/src/client/java/world/anhgelus/molehunt/client/mixin/NoNametags.java
@@ -12,9 +12,9 @@ import world.anhgelus.molehunt.client.MolehuntClient;
@Mixin(EntityRenderer.class)
public class NoNametags<T extends Entity, S extends EntityRenderState> {
- @Inject(at = @At("HEAD"), method = "shouldShowName", cancellable = true)
- private void renderLabelOrNot(T entity, double distanceToCameraSq, CallbackInfoReturnable<Boolean> cir) {
- if (!(entity instanceof Player) || MolehuntClient.showNameTags() || !MolehuntClient.gameStarted()) return;
- cir.setReturnValue(false);
- }
+ @Inject(at = @At("HEAD"), method = "shouldShowName", cancellable = true)
+ private void renderLabelOrNot(T entity, double distanceToCameraSq, CallbackInfoReturnable<Boolean> cir) {
+ if (!(entity instanceof Player) || MolehuntClient.showNameTags() || !MolehuntClient.gameStarted()) return;
+ cir.setReturnValue(false);
+ }
} \ No newline at end of file
diff --git a/src/client/java/world/anhgelus/molehunt/client/mixin/NoPlayerListHud.java b/src/client/java/world/anhgelus/molehunt/client/mixin/NoPlayerListHud.java
index c235b00..c846e7d 100644
--- a/src/client/java/world/anhgelus/molehunt/client/mixin/NoPlayerListHud.java
+++ b/src/client/java/world/anhgelus/molehunt/client/mixin/NoPlayerListHud.java
@@ -9,9 +9,9 @@ import world.anhgelus.molehunt.client.MolehuntClient;
@Mixin(PlayerTabOverlay.class)
public class NoPlayerListHud {
- @Inject(at = @At("HEAD"), method = "setVisible", cancellable = true)
- public void render(CallbackInfo ci) {
- if (MolehuntClient.showTab() || !MolehuntClient.gameStarted()) return;
- ci.cancel();
- }
+ @Inject(at = @At("HEAD"), method = "setVisible", cancellable = true)
+ public void render(CallbackInfo ci) {
+ if (MolehuntClient.showTab() || !MolehuntClient.gameStarted()) return;
+ ci.cancel();
+ }
}
diff --git a/src/client/java/world/anhgelus/molehunt/client/mixin/NoSkin.java b/src/client/java/world/anhgelus/molehunt/client/mixin/NoSkin.java
index fd5a8a1..7007948 100644
--- a/src/client/java/world/anhgelus/molehunt/client/mixin/NoSkin.java
+++ b/src/client/java/world/anhgelus/molehunt/client/mixin/NoSkin.java
@@ -14,15 +14,15 @@ import world.anhgelus.molehunt.client.MolehuntClient;
@Mixin(AbstractClientPlayer.class)
public class NoSkin {
- @Inject(at = @At("HEAD"), method = "getSkin", cancellable = true)
- public void getSkin(CallbackInfoReturnable<PlayerSkin> cir) {
- if (MolehuntClient.showSkins() || !MolehuntClient.gameStarted()) return;
- cir.setReturnValue(new PlayerSkin(
- new ClientAsset.ResourceTexture(Identifier.fromNamespaceAndPath(Molehunt.MOD_ID, "skin")),
- null,
- null,
- PlayerModelType.WIDE,
- true
- ));
- }
+ @Inject(at = @At("HEAD"), method = "getSkin", cancellable = true)
+ public void getSkin(CallbackInfoReturnable<PlayerSkin> cir) {
+ if (MolehuntClient.showSkins() || !MolehuntClient.gameStarted()) return;
+ cir.setReturnValue(new PlayerSkin(
+ new ClientAsset.ResourceTexture(Identifier.fromNamespaceAndPath(Molehunt.MOD_ID, "skin")),
+ null,
+ null,
+ PlayerModelType.WIDE,
+ true
+ ));
+ }
}
diff --git a/src/client/resources/assets/molehunt/lang/en_us.json b/src/client/resources/assets/molehunt/lang/en_us.json
index 9c10680..393d6dd 100644
--- a/src/client/resources/assets/molehunt/lang/en_us.json
+++ b/src/client/resources/assets/molehunt/lang/en_us.json
@@ -1,29 +1,29 @@
{
- "commands.molehunt.error.game_not_started": "The Molehunt game has not been started yet.",
- "commands.molehunt.error.game_already_started": "The Molehunt game has already been started yet.",
- "commands.molehunt.timer.show": "Showing Molehunt timer.",
- "commands.molehunt.timer.hide": "Hiding Molehunt timer.",
- "commands.molehunt.role.mole": "§cYou are a Mole.\nKill all the survivors before the timer runs out.",
- "commands.molehunt.role.mole.list": "§eThe moles are: %s",
- "commands.molehunt.role.survivor": "§aYou are not the Mole. \nSurvive until the timer runs out, and try to discover who's the Mole.",
- "commands.molehunt.role.survivor.mole_count": "§eThere are %d §emoles among you.",
- "commands.molehunt.stop.success": "The Molehunt game has been stopped.",
- "molehunt.game.end.suspense.title": "§eAnd the winners are...",
- "molehunt.game.end.winners.moles.title": "§cThe Moles!",
- "molehunt.game.end.winners.survivors.title": "§aNot the Moles!",
- "molehunt.game.end.winners.subtitle": "§6The Moles were %s",
- "molehunt.game.start.suspense": "§eYou are...",
- "molehunt.game.start.mole.title": "§cThe Mole!",
- "molehunt.game.start.mole.subtitle": "§eGet the list of moles with §6/molehunt role§e.",
- "molehunt.game.start.survivor.title": "§aNot the Mole!",
- "molehunt.game.start.survivor.subtitle": "§eTry to survive and find out who's the mole!",
- "gamerule.molehunt:gameDuration": "Molehunt: Duration of a game",
- "gamerule.molehunt:molePercentage": "Molehunt: Percentage of Mole",
- "gamerule.molehunt:moleCount": "Molehunt: Number of Mole",
- "gamerule.molehunt:showNametags": "Molehunt: Show players' nametag",
- "gamerule.molehunt:showTab": "Molehunt: Enable the tab",
- "gamerule.molehunt:showSkins": "Molehunt: Show players' skin",
- "gamerule.molehunt:initialWorldSize": "Molehunt: Initial world size",
- "gamerule.molehunt:finalWorldSize": "Molehunt: Final world size",
- "gamerule.molehunt:borderMovingStartingTimeOffsetMinutes": "Molehunt: Time before moving the borders"
+ "commands.molehunt.error.game_not_started": "The Molehunt game has not been started yet.",
+ "commands.molehunt.error.game_already_started": "The Molehunt game has already been started yet.",
+ "commands.molehunt.timer.show": "Showing Molehunt timer.",
+ "commands.molehunt.timer.hide": "Hiding Molehunt timer.",
+ "commands.molehunt.role.mole": "§cYou are a Mole.\nKill all the survivors before the timer runs out.",
+ "commands.molehunt.role.mole.list": "§eThe moles are: %s",
+ "commands.molehunt.role.survivor": "§aYou are not the Mole. \nSurvive until the timer runs out, and try to discover who's the Mole.",
+ "commands.molehunt.role.survivor.mole_count": "§eThere are %d §emoles among you.",
+ "commands.molehunt.stop.success": "The Molehunt game has been stopped.",
+ "molehunt.game.end.suspense.title": "§eAnd the winners are...",
+ "molehunt.game.end.winners.moles.title": "§cThe Moles!",
+ "molehunt.game.end.winners.survivors.title": "§aNot the Moles!",
+ "molehunt.game.end.winners.subtitle": "§6The Moles were %s",
+ "molehunt.game.start.suspense": "§eYou are...",
+ "molehunt.game.start.mole.title": "§cThe Mole!",
+ "molehunt.game.start.mole.subtitle": "§eGet the list of moles with §6/molehunt role§e.",
+ "molehunt.game.start.survivor.title": "§aNot the Mole!",
+ "molehunt.game.start.survivor.subtitle": "§eTry to survive and find out who's the mole!",
+ "gamerule.molehunt:gameDuration": "Molehunt: Duration of a game",
+ "gamerule.molehunt:molePercentage": "Molehunt: Percentage of Mole",
+ "gamerule.molehunt:moleCount": "Molehunt: Number of Mole",
+ "gamerule.molehunt:showNametags": "Molehunt: Show players' nametag",
+ "gamerule.molehunt:showTab": "Molehunt: Enable the tab",
+ "gamerule.molehunt:showSkins": "Molehunt: Show players' skin",
+ "gamerule.molehunt:initialWorldSize": "Molehunt: Initial world size",
+ "gamerule.molehunt:finalWorldSize": "Molehunt: Final world size",
+ "gamerule.molehunt:borderMovingStartingTimeOffsetMinutes": "Molehunt: Time before moving the borders"
} \ No newline at end of file
diff --git a/src/client/resources/assets/molehunt/lang/fr_fr.json b/src/client/resources/assets/molehunt/lang/fr_fr.json
index c481d76..b66060e 100644
--- a/src/client/resources/assets/molehunt/lang/fr_fr.json
+++ b/src/client/resources/assets/molehunt/lang/fr_fr.json
@@ -1,29 +1,29 @@
{
- "commands.molehunt.error.game_not_started": "La partie de Molehunt n'a pas encore commencé.",
- "commands.molehunt.error.game_already_started": "La partie de Molehunt a déjà été lancée.",
- "commands.molehunt.timer.show": "Le timer est maintenant affiché.",
- "commands.molehunt.timer.hide": "Le timer est maintenant caché.",
- "commands.molehunt.role.mole": "§cVous êtes une taupe.\nTuez tous les survivants avant la fin de la partie..",
- "commands.molehunt.role.mole.list": "§eLes taupes sont : %s",
- "commands.molehunt.role.survivor": "§aVous n'êtes pas la taupe. \nSurvivez jusqu'à la fin, et découvrez qui sont les moles.",
- "commands.molehunt.role.survivor.mole_count": "§eIl y a %d §etaupes parmi vous.",
- "commands.molehunt.stop.success": "La partie de Molehunt a été arrêtée.",
- "molehunt.game.end.suspense.title": "§eEt les gagnants sont...",
- "molehunt.game.end.winners.moles.title": "§cLes Taupes !",
- "molehunt.game.end.winners.survivors.title": "§aPas les Taupes !",
- "molehunt.game.end.winners.subtitle": "§Les Taupes sont",
- "molehunt.game.start.suspense": "§eVous êtes...",
- "molehunt.game.start.mole.title": "§cLa Taupe !",
- "molehunt.game.start.mole.subtitle": "§eRécupérer la liste des taupes avec §6/molehunt moles",
- "molehunt.game.start.survivor.title": "§aPas la taupe!",
- "molehunt.game.start.survivor.subtitle": "§eEssaye de survivre et de trouver qui est la taupe !",
- "gamerule.molehunt:gameDuration": "Molehunt : Durée d'une partie",
- "gamerule.molehunt:molePercentage": "Molehunt : Pourcentage de Taupes",
- "gamerule.molehunt:moleCount": "Molehunt : Nombre de Taupes",
- "gamerule.molehunt:showNametags": "Molehunt : Affiche les nametags des joueurs",
- "gamerule.molehunt:showTab": "Molehunt : Active la liste des joueurs",
- "gamerule.molehunt:showSkins": "Molehunt : Affiche les skins des joueurs",
- "gamerule.molehunt:initialWorldSize": "Molehunt : Taille initiale du monde",
- "gamerule.molehunt:finalWorldSize": "Molehunt : Taille finale du monde",
- "gamerule.molehunt:borderMovingStartingTimeOffsetMinutes": "Molehunt : Temps avant de bouger les bordures du monde"
+ "commands.molehunt.error.game_not_started": "La partie de Molehunt n'a pas encore commencé.",
+ "commands.molehunt.error.game_already_started": "La partie de Molehunt a déjà été lancée.",
+ "commands.molehunt.timer.show": "Le timer est maintenant affiché.",
+ "commands.molehunt.timer.hide": "Le timer est maintenant caché.",
+ "commands.molehunt.role.mole": "§cVous êtes une taupe.\nTuez tous les survivants avant la fin de la partie..",
+ "commands.molehunt.role.mole.list": "§eLes taupes sont : %s",
+ "commands.molehunt.role.survivor": "§aVous n'êtes pas la taupe. \nSurvivez jusqu'à la fin, et découvrez qui sont les moles.",
+ "commands.molehunt.role.survivor.mole_count": "§eIl y a %d §etaupes parmi vous.",
+ "commands.molehunt.stop.success": "La partie de Molehunt a été arrêtée.",
+ "molehunt.game.end.suspense.title": "§eEt les gagnants sont...",
+ "molehunt.game.end.winners.moles.title": "§cLes Taupes !",
+ "molehunt.game.end.winners.survivors.title": "§aPas les Taupes !",
+ "molehunt.game.end.winners.subtitle": "§Les Taupes sont",
+ "molehunt.game.start.suspense": "§eVous êtes...",
+ "molehunt.game.start.mole.title": "§cLa Taupe !",
+ "molehunt.game.start.mole.subtitle": "§eRécupérer la liste des taupes avec §6/molehunt moles",
+ "molehunt.game.start.survivor.title": "§aPas la taupe!",
+ "molehunt.game.start.survivor.subtitle": "§eEssaye de survivre et de trouver qui est la taupe !",
+ "gamerule.molehunt:gameDuration": "Molehunt : Durée d'une partie",
+ "gamerule.molehunt:molePercentage": "Molehunt : Pourcentage de Taupes",
+ "gamerule.molehunt:moleCount": "Molehunt : Nombre de Taupes",
+ "gamerule.molehunt:showNametags": "Molehunt : Affiche les nametags des joueurs",
+ "gamerule.molehunt:showTab": "Molehunt : Active la liste des joueurs",
+ "gamerule.molehunt:showSkins": "Molehunt : Affiche les skins des joueurs",
+ "gamerule.molehunt:initialWorldSize": "Molehunt : Taille initiale du monde",
+ "gamerule.molehunt:finalWorldSize": "Molehunt : Taille finale du monde",
+ "gamerule.molehunt:borderMovingStartingTimeOffsetMinutes": "Molehunt : Temps avant de bouger les bordures du monde"
} \ No newline at end of file
diff --git a/src/client/resources/molehunt.client.mixins.json b/src/client/resources/molehunt.client.mixins.json
index 7b9c0f4..b966891 100644
--- a/src/client/resources/molehunt.client.mixins.json
+++ b/src/client/resources/molehunt.client.mixins.json
@@ -1,15 +1,15 @@
{
- "required": true,
- "minVersion": "0.8",
- "package": "world.anhgelus.molehunt.client.mixin",
- "compatibilityLevel": "JAVA_21",
- "client": [
- "NoCustomizableSkinOverlay",
- "NoNametags",
- "NoPlayerListHud",
- "NoSkin"
- ],
- "injectors": {
- "defaultRequire": 1
- }
+ "required": true,
+ "minVersion": "0.8",
+ "package": "world.anhgelus.molehunt.client.mixin",
+ "compatibilityLevel": "JAVA_21",
+ "client": [
+ "NoCustomizableSkinOverlay",
+ "NoNametags",
+ "NoPlayerListHud",
+ "NoSkin"
+ ],
+ "injectors": {
+ "defaultRequire": 1
+ }
}
diff --git a/src/main/java/world/anhgelus/molehunt/Molehunt.java b/src/main/java/world/anhgelus/molehunt/Molehunt.java
index 12bd3b9..f3153d5 100644
--- a/src/main/java/world/anhgelus/molehunt/Molehunt.java
+++ b/src/main/java/world/anhgelus/molehunt/Molehunt.java
@@ -39,186 +39,186 @@ import static net.minecraft.commands.Commands.literal;
public class Molehunt implements ModInitializer {
- public static final String MOD_ID = "molehunt";
- public static final Logger LOGGER = LoggerFactory.getLogger(MOD_ID);
- public static final SimpleConfig CONFIG_FILE = Config.configFile(MOD_ID);
- public static final GameRule<Integer> GAME_DURATION = GameRuleBuilder
- .forInteger(CONFIG_FILE.getOrDefault("game_duration", 90))
- .category(GameRuleCategory.MISC)
- .buildAndRegister(Identifier.fromNamespaceAndPath(MOD_ID, "game_duration_minutes"));
- public static final GameRule<Integer> MOLE_PERCENTAGE = GameRuleBuilder
- .forInteger(CONFIG_FILE.getOrDefault("mole_percentage", 25))
- .range(0, 100)
- .category(GameRuleCategory.MISC)
- .buildAndRegister(Identifier.fromNamespaceAndPath(MOD_ID, "mole_percentage"));
- public static final GameRule<Integer> MOLE_COUNT = GameRuleBuilder
- .forInteger(CONFIG_FILE.getOrDefault("mole_count", -1))
- .category(GameRuleCategory.MISC)
- .buildAndRegister(Identifier.fromNamespaceAndPath(MOD_ID, "mole_count"));
- public static final GameRule<Boolean> SHOW_NAMETAGS = GameRuleBuilder
- .forBoolean(CONFIG_FILE.getOrDefault("show_nametags", false))
- .category(GameRuleCategory.MISC)
- .buildAndRegister(Identifier.fromNamespaceAndPath(MOD_ID, "show_nametags"));
- public static final GameRule<Boolean> SHOW_TAB = GameRuleBuilder
- .forBoolean(CONFIG_FILE.getOrDefault("show_tab", false))
- .category(GameRuleCategory.MISC)
- .buildAndRegister(Identifier.fromNamespaceAndPath(MOD_ID, "show_tab"));
- public static final GameRule<Boolean> SHOW_SKINS = GameRuleBuilder
- .forBoolean(CONFIG_FILE.getOrDefault("show_skins", false))
- .category(GameRuleCategory.MISC)
- .buildAndRegister(Identifier.fromNamespaceAndPath(MOD_ID, "show_skins"));
- public static final GameRule<Integer> INITIAL_WORLD_SIZE = GameRuleBuilder
- .forInteger(CONFIG_FILE.getOrDefault("initial_world_size", 600))
- .minValue(0)
- .category(GameRuleCategory.MISC)
- .buildAndRegister(Identifier.fromNamespaceAndPath(MOD_ID, "initial_world_size"));
- public static final GameRule<Integer> FINAL_WORLD_SIZE = GameRuleBuilder
- .forInteger(CONFIG_FILE.getOrDefault("final_world_size", 100))
- .minValue(0)
- .category(GameRuleCategory.MISC)
- .buildAndRegister(Identifier.fromNamespaceAndPath(MOD_ID, "final_world_size"));
- public static final GameRule<Integer> MOVING_STARTING_TIME_OFFSET = GameRuleBuilder
- .forInteger(CONFIG_FILE.getOrDefault("border_moving_starting_time_offset", 30))
- .minValue(0)
- .category(GameRuleCategory.MISC)
- .buildAndRegister(Identifier.fromNamespaceAndPath(MOD_ID, "border_moving_starting_time_offset_minutes"));
- public static final GameRule<Boolean> ENABLE_PORTALS = GameRuleBuilder
- .forBoolean(CONFIG_FILE.getOrDefault("enable_portals", false))
- .category(GameRuleCategory.MISC)
- .buildAndRegister(Identifier.fromNamespaceAndPath(MOD_ID, "enable_portals"));
- public static final GameRule<Boolean> FOOD_ON_START = GameRuleBuilder
- .forBoolean(CONFIG_FILE.getOrDefault("food_on_start", true))
- .category(GameRuleCategory.MISC)
- .buildAndRegister(Identifier.fromNamespaceAndPath(MOD_ID, "food_on_start"));
- public static Config CONFIG;
- public static HashMap<UUID, Boolean> timerVisibility = new HashMap<>();
-
- static {
- GameRuleEvents.changeCallback(SHOW_NAMETAGS).register(Molehunt::sendConfigPayload);
- GameRuleEvents.changeCallback(SHOW_TAB).register(Molehunt::sendConfigPayload);
- GameRuleEvents.changeCallback(SHOW_SKINS).register(Molehunt::sendConfigPayload);
- }
-
- public Game game;
-
- private static <T> void sendConfigPayload(T v, MinecraftServer server) {
- if (CONFIG == null) return;
- CONFIG.sendConfigPayload();
- }
-
- @Override
- public void onInitialize() {
- LOGGER.info("Initializing Molehunt");
-
- final var command = literal("molehunt");
- command.then(literal("start")
- .requires(Commands.hasPermission(Commands.LEVEL_GAMEMASTERS))
- .executes(context -> {
- if (game != null && game.started())
- throw (new SimpleCommandExceptionType(
- Component.translatable("commands.molehunt.error.game_already_started")
- )).create();
- game = new Game(context.getSource().getServer());
- game.start();
- return Command.SINGLE_SUCCESS;
- }));
- command.then(literal("timer").requires(CommandSourceStack::isPlayer).then(
- literal("show").executes(context -> {
- var player = context.getSource().getPlayer();
- assert player != null;
-
- timerVisibility.put(player.getUUID(), true);
- context.getSource().sendSuccess(() -> Component.translatable("commands.molehunt.timer.show"), false);
-
- if (game == null || !game.started()) {
- player.connection.send(new ClientboundSetActionBarTextPacket(
- Component.translatable("commands.molehunt.error.game_not_started").withStyle(ChatFormatting.RED)
- ));
- } else {
- player.connection.send(new ClientboundSetActionBarTextPacket(Component.translationArg(game.getRemainingText())));
- }
-
- return Command.SINGLE_SUCCESS;
- })
- ).then(
- literal("hide").executes(context -> {
- var player = context.getSource().getPlayer();
- assert player != null;
-
- timerVisibility.put(player.getUUID(), false);
- context.getSource().sendSuccess(() -> Component.translatable("commands.molehunt.timer.hide"), false);
- return Command.SINGLE_SUCCESS;
- })
- ));
- command.then(literal("role")
- .requires(CommandSourceStack::isPlayer)
- .executes(context -> {
- if (game == null || !game.started())
- throw (new SimpleCommandExceptionType(
- Component.translatable("commands.molehunt.error.game_not_started")
- )).create();
-
- final var source = context.getSource();
- final var player = source.getPlayer();
- assert player != null;
-
- if (game.isMole(player)) {
- source.sendSuccess(
- () -> Component.translatable("commands.molehunt.role.mole")
- .append("\n\n")
- .append(Component.translatable("commands.molehunt.role.mole.list", game.getMolesAsString())),
- false);
- } else if (player.isSpectator()) {
- source.sendSuccess(
- () -> Component.translatable("commands.molehunt.role.survivor.mole_count", game.getMoles().size()),
- false);
- } else {
- source.sendSuccess(
- () -> Component.translatable("commands.molehunt.role.survivor")
- .append("\n\n")
- .append(Component.translatable("commands.molehunt.role.survivor.mole_count", game.getMoles().size())),
- false);
- }
-
- return Command.SINGLE_SUCCESS;
- }));
- command.then(literal("stop")
- .requires(Commands.hasPermission(Commands.LEVEL_GAMEMASTERS))
- .executes(_ -> {
- if (game == null || !game.started())
- throw (new SimpleCommandExceptionType(
- Component.translatable("commands.molehunt.error.game_not_started")
- )).create();
-
- game.stop();
-
- return Command.SINGLE_SUCCESS;
- }));
-
- ServerLifecycleEvents.SERVER_STARTED.register(server -> CONFIG = new Config(server));
-
- CommandRegistrationCallback.EVENT.register((dispatcher, _, _) -> dispatcher.register(command));
-
- ServerMessageEvents.ALLOW_CHAT_MESSAGE.register((_, _, _) -> false);
-
- ServerLivingEntityEvents.AFTER_DEATH.register((entity, _) -> {
- if (!(entity instanceof ServerPlayer) || game == null) return;
- if (!game.started()) return;
- if (game.wonByMoles()) game.end();
- });
-
- ServerPlayerEvents.AFTER_RESPAWN.register((_, newPlayer, _) -> {
- if (game == null) return;
- if (!game.started()) return;
- newPlayer.setGameMode(GameType.SPECTATOR);
- });
-
- ServerPlayConnectionEvents.JOIN.register((_, sender, _) -> {
- sender.sendPacket(new ConfigPayload(CONFIG.nametagsEnabled(), CONFIG.skinsEnabled(), CONFIG.tabEnabled()));
- sender.sendPacket(new GamePayload(game != null && game.started()));
- });
-
- PayloadTypeRegistry.clientboundPlay().register(ConfigPayload.ID, ConfigPayload.CODEC);
- PayloadTypeRegistry.clientboundPlay().register(GamePayload.ID, GamePayload.CODEC);
- }
+ public static final String MOD_ID = "molehunt";
+ public static final Logger LOGGER = LoggerFactory.getLogger(MOD_ID);
+ public static final SimpleConfig CONFIG_FILE = Config.configFile(MOD_ID);
+ public static final GameRule<Integer> GAME_DURATION = GameRuleBuilder
+ .forInteger(CONFIG_FILE.getOrDefault("game_duration", 90))
+ .category(GameRuleCategory.MISC)
+ .buildAndRegister(Identifier.fromNamespaceAndPath(MOD_ID, "game_duration_minutes"));
+ public static final GameRule<Integer> MOLE_PERCENTAGE = GameRuleBuilder
+ .forInteger(CONFIG_FILE.getOrDefault("mole_percentage", 25))
+ .range(0, 100)
+ .category(GameRuleCategory.MISC)
+ .buildAndRegister(Identifier.fromNamespaceAndPath(MOD_ID, "mole_percentage"));
+ public static final GameRule<Integer> MOLE_COUNT = GameRuleBuilder
+ .forInteger(CONFIG_FILE.getOrDefault("mole_count", -1))
+ .category(GameRuleCategory.MISC)
+ .buildAndRegister(Identifier.fromNamespaceAndPath(MOD_ID, "mole_count"));
+ public static final GameRule<Boolean> SHOW_NAMETAGS = GameRuleBuilder
+ .forBoolean(CONFIG_FILE.getOrDefault("show_nametags", false))
+ .category(GameRuleCategory.MISC)
+ .buildAndRegister(Identifier.fromNamespaceAndPath(MOD_ID, "show_nametags"));
+ public static final GameRule<Boolean> SHOW_TAB = GameRuleBuilder
+ .forBoolean(CONFIG_FILE.getOrDefault("show_tab", false))
+ .category(GameRuleCategory.MISC)
+ .buildAndRegister(Identifier.fromNamespaceAndPath(MOD_ID, "show_tab"));
+ public static final GameRule<Boolean> SHOW_SKINS = GameRuleBuilder
+ .forBoolean(CONFIG_FILE.getOrDefault("show_skins", false))
+ .category(GameRuleCategory.MISC)
+ .buildAndRegister(Identifier.fromNamespaceAndPath(MOD_ID, "show_skins"));
+ public static final GameRule<Integer> INITIAL_WORLD_SIZE = GameRuleBuilder
+ .forInteger(CONFIG_FILE.getOrDefault("initial_world_size", 600))
+ .minValue(0)
+ .category(GameRuleCategory.MISC)
+ .buildAndRegister(Identifier.fromNamespaceAndPath(MOD_ID, "initial_world_size"));
+ public static final GameRule<Integer> FINAL_WORLD_SIZE = GameRuleBuilder
+ .forInteger(CONFIG_FILE.getOrDefault("final_world_size", 100))
+ .minValue(0)
+ .category(GameRuleCategory.MISC)
+ .buildAndRegister(Identifier.fromNamespaceAndPath(MOD_ID, "final_world_size"));
+ public static final GameRule<Integer> MOVING_STARTING_TIME_OFFSET = GameRuleBuilder
+ .forInteger(CONFIG_FILE.getOrDefault("border_moving_starting_time_offset", 30))
+ .minValue(0)
+ .category(GameRuleCategory.MISC)
+ .buildAndRegister(Identifier.fromNamespaceAndPath(MOD_ID, "border_moving_starting_time_offset_minutes"));
+ public static final GameRule<Boolean> ENABLE_PORTALS = GameRuleBuilder
+ .forBoolean(CONFIG_FILE.getOrDefault("enable_portals", false))
+ .category(GameRuleCategory.MISC)
+ .buildAndRegister(Identifier.fromNamespaceAndPath(MOD_ID, "enable_portals"));
+ public static final GameRule<Boolean> FOOD_ON_START = GameRuleBuilder
+ .forBoolean(CONFIG_FILE.getOrDefault("food_on_start", true))
+ .category(GameRuleCategory.MISC)
+ .buildAndRegister(Identifier.fromNamespaceAndPath(MOD_ID, "food_on_start"));
+ public static Config CONFIG;
+ public static HashMap<UUID, Boolean> timerVisibility = new HashMap<>();
+
+ static {
+ GameRuleEvents.changeCallback(SHOW_NAMETAGS).register(Molehunt::sendConfigPayload);
+ GameRuleEvents.changeCallback(SHOW_TAB).register(Molehunt::sendConfigPayload);
+ GameRuleEvents.changeCallback(SHOW_SKINS).register(Molehunt::sendConfigPayload);
+ }
+
+ public Game game;
+
+ private static <T> void sendConfigPayload(T v, MinecraftServer server) {
+ if (CONFIG == null) return;
+ CONFIG.sendConfigPayload();
+ }
+
+ @Override
+ public void onInitialize() {
+ LOGGER.info("Initializing Molehunt");
+
+ final var command = literal("molehunt");
+ command.then(literal("start")
+ .requires(Commands.hasPermission(Commands.LEVEL_GAMEMASTERS))
+ .executes(context -> {
+ if (game != null && game.started())
+ throw (new SimpleCommandExceptionType(
+ Component.translatable("commands.molehunt.error.game_already_started")
+ )).create();
+ game = new Game(context.getSource().getServer());
+ game.start();
+ return Command.SINGLE_SUCCESS;
+ }));
+ command.then(literal("timer").requires(CommandSourceStack::isPlayer).then(
+ literal("show").executes(context -> {
+ var player = context.getSource().getPlayer();
+ assert player != null;
+
+ timerVisibility.put(player.getUUID(), true);
+ context.getSource().sendSuccess(() -> Component.translatable("commands.molehunt.timer.show"), false);
+
+ if (game == null || !game.started()) {
+ player.connection.send(new ClientboundSetActionBarTextPacket(
+ Component.translatable("commands.molehunt.error.game_not_started").withStyle(ChatFormatting.RED)
+ ));
+ } else {
+ player.connection.send(new ClientboundSetActionBarTextPacket(Component.translationArg(game.getRemainingText())));
+ }
+
+ return Command.SINGLE_SUCCESS;
+ })
+ ).then(
+ literal("hide").executes(context -> {
+ var player = context.getSource().getPlayer();
+ assert player != null;
+
+ timerVisibility.put(player.getUUID(), false);
+ context.getSource().sendSuccess(() -> Component.translatable("commands.molehunt.timer.hide"), false);
+ return Command.SINGLE_SUCCESS;
+ })
+ ));
+ command.then(literal("role")
+ .requires(CommandSourceStack::isPlayer)
+ .executes(context -> {
+ if (game == null || !game.started())
+ throw (new SimpleCommandExceptionType(
+ Component.translatable("commands.molehunt.error.game_not_started")
+ )).create();
+
+ final var source = context.getSource();
+ final var player = source.getPlayer();
+ assert player != null;
+
+ if (game.isMole(player)) {
+ source.sendSuccess(
+ () -> Component.translatable("commands.molehunt.role.mole")
+ .append("\n\n")
+ .append(Component.translatable("commands.molehunt.role.mole.list", game.getMolesAsString())),
+ false);
+ } else if (player.isSpectator()) {
+ source.sendSuccess(
+ () -> Component.translatable("commands.molehunt.role.survivor.mole_count", game.getMoles().size()),
+ false);
+ } else {
+ source.sendSuccess(
+ () -> Component.translatable("commands.molehunt.role.survivor")
+ .append("\n\n")
+ .append(Component.translatable("commands.molehunt.role.survivor.mole_count", game.getMoles().size())),
+ false);
+ }
+
+ return Command.SINGLE_SUCCESS;
+ }));
+ command.then(literal("stop")
+ .requires(Commands.hasPermission(Commands.LEVEL_GAMEMASTERS))
+ .executes(_ -> {
+ if (game == null || !game.started())
+ throw (new SimpleCommandExceptionType(
+ Component.translatable("commands.molehunt.error.game_not_started")
+ )).create();
+
+ game.stop();
+
+ return Command.SINGLE_SUCCESS;
+ }));
+
+ ServerLifecycleEvents.SERVER_STARTED.register(server -> CONFIG = new Config(server));
+
+ CommandRegistrationCallback.EVENT.register((dispatcher, _, _) -> dispatcher.register(command));
+
+ ServerMessageEvents.ALLOW_CHAT_MESSAGE.register((_, _, _) -> false);
+
+ ServerLivingEntityEvents.AFTER_DEATH.register((entity, _) -> {
+ if (!(entity instanceof ServerPlayer) || game == null) return;
+ if (!game.started()) return;
+ if (game.wonByMoles()) game.end();
+ });
+
+ ServerPlayerEvents.AFTER_RESPAWN.register((_, newPlayer, _) -> {
+ if (game == null) return;
+ if (!game.started()) return;
+ newPlayer.setGameMode(GameType.SPECTATOR);
+ });
+
+ ServerPlayConnectionEvents.JOIN.register((_, sender, _) -> {
+ sender.sendPacket(new ConfigPayload(CONFIG.nametagsEnabled(), CONFIG.skinsEnabled(), CONFIG.tabEnabled()));
+ sender.sendPacket(new GamePayload(game != null && game.started()));
+ });
+
+ PayloadTypeRegistry.clientboundPlay().register(ConfigPayload.ID, ConfigPayload.CODEC);
+ PayloadTypeRegistry.clientboundPlay().register(GamePayload.ID, GamePayload.CODEC);
+ }
}
diff --git a/src/main/java/world/anhgelus/molehunt/config/Config.java b/src/main/java/world/anhgelus/molehunt/config/Config.java
index c9d04af..ee46e4b 100644
--- a/src/main/java/world/anhgelus/molehunt/config/Config.java
+++ b/src/main/java/world/anhgelus/molehunt/config/Config.java
@@ -6,135 +6,135 @@ import world.anhgelus.molehunt.Molehunt;
public class Config {
- private final MinecraftServer server;
-
- public Config(MinecraftServer server) {
- this.server = server;
-
- sendConfigPayload(nametagsEnabled(), skinsEnabled(), tabEnabled());
- }
-
- public void sendConfigPayload() {
- final var payload = new ConfigPayload(nametagsEnabled(), skinsEnabled(), tabEnabled());
- server.getPlayerList().getPlayers().forEach(p -> ServerPlayNetworking.send(p, payload));
- }
-
- public void sendConfigPayload(boolean showNametags, boolean showSkins, boolean showTab) {
- final var payload = new ConfigPayload(showNametags, showSkins, showTab);
- server.getPlayerList().getPlayers().forEach(p -> ServerPlayNetworking.send(p, payload));
- }
-
- public int getGameDuration() {
- return server.overworld().getGameRules().get(Molehunt.GAME_DURATION);
- }
-
- public int getMolePercentage() {
- return server.overworld().getGameRules().get(Molehunt.MOLE_PERCENTAGE);
- }
-
- public int getMoleCount() {
- return server.overworld().getGameRules().get(Molehunt.MOLE_COUNT);
- }
-
- public boolean nametagsEnabled() {
- return server.overworld().getGameRules().get(Molehunt.SHOW_NAMETAGS);
- }
-
- public boolean skinsEnabled() {
- return server.overworld().getGameRules().get(Molehunt.SHOW_SKINS);
- }
-
- public boolean tabEnabled() {
- return server.overworld().getGameRules().get(Molehunt.SHOW_TAB);
- }
-
- public int getInitialWorldSize() {
- return server.overworld().getGameRules().get(Molehunt.INITIAL_WORLD_SIZE);
- }
-
- public int getFinalWorldSize() {
- return server.overworld().getGameRules().get(Molehunt.FINAL_WORLD_SIZE);
- }
-
- public int getBorderShrinkingStartingTimeOffset() {
- return server.overworld().getGameRules().get(Molehunt.MOVING_STARTING_TIME_OFFSET);
- }
-
- public boolean portalsEnabled() {
- return server.overworld().getGameRules().get(Molehunt.ENABLE_PORTALS);
- }
-
- public boolean foodOnStart() {
- return server.overworld().getGameRules().get(Molehunt.FOOD_ON_START);
- }
-
- public static SimpleConfig configFile(String fileName) {
- return SimpleConfig.of(fileName).provider(Config::defaultConfig).request();
- }
-
- private static String defaultConfig(String s) {
- return """
- # Molehunt mod configuration file
- # To regenerate the default configuration, delete, move or rename this file.
-
- # Game settings
-
- # The duration of a molehunt game, in minutes.
- # Default: 90 minutes (1 hour 30 minutes).
- game_duration = 90
-
- # Mole percentage.
- # For example, a mole percentage of 25% will get 1 mole every 4 players.
- # Default: 25 %.
- mole_percentage = 25
-
- # Mole count (absolute).
- # This setting will overwrite the mole_percentage setting.
- # If set below 0, this setting is disabled.
- # Default: -1.
- mole_count = -1
-
- # Give food on start
- # Default: true
- food_on_start = true
-
-
- # Client-side settings (applies to all players)
-
- # Show nametags
- # Default: false
- show_nametags = false
-
- # Show skins
- # Default: false
- show_skins = false
-
- # Show tab
- # Default: false
- show_tab = false
-
-
- # World border settings
-
- # Initial world size (in blocks).
- # Default: 600 blocks.
- initial_world_size = 600
-
- # Final world size (in blocks).
- # Default: 100 blocks.
- final_world_size = 100
-
- # Moving starting time offset (in minutes)
- # The time before starting to move the world borders.
- # If this value is greater than the game duration, borders will never move.
- # Default: 30 minutes.
- border_moving_starting_time_offset = 30
-
- # Other
-
- # Enable portals (nether, end, end gateway).
- # Default: false.
- enable_portals = false
- """;
- }
+ private final MinecraftServer server;
+
+ public Config(MinecraftServer server) {
+ this.server = server;
+
+ sendConfigPayload(nametagsEnabled(), skinsEnabled(), tabEnabled());
+ }
+
+ public static SimpleConfig configFile(String fileName) {
+ return SimpleConfig.of(fileName).provider(Config::defaultConfig).request();
+ }
+
+ private static String defaultConfig(String s) {
+ return """
+ # Molehunt mod configuration file
+ # To regenerate the default configuration, delete, move or rename this file.
+
+ # Game settings
+
+ # The duration of a molehunt game, in minutes.
+ # Default: 90 minutes (1 hour 30 minutes).
+ game_duration = 90
+
+ # Mole percentage.
+ # For example, a mole percentage of 25% will get 1 mole every 4 players.
+ # Default: 25 %.
+ mole_percentage = 25
+
+ # Mole count (absolute).
+ # This setting will overwrite the mole_percentage setting.
+ # If set below 0, this setting is disabled.
+ # Default: -1.
+ mole_count = -1
+
+ # Give food on start
+ # Default: true
+ food_on_start = true
+
+
+ # Client-side settings (applies to all players)
+
+ # Show nametags
+ # Default: false
+ show_nametags = false
+
+ # Show skins
+ # Default: false
+ show_skins = false
+
+ # Show tab
+ # Default: false
+ show_tab = false
+
+
+ # World border settings
+
+ # Initial world size (in blocks).
+ # Default: 600 blocks.
+ initial_world_size = 600
+
+ # Final world size (in blocks).
+ # Default: 100 blocks.
+ final_world_size = 100
+
+ # Moving starting time offset (in minutes)
+ # The time before starting to move the world borders.
+ # If this value is greater than the game duration, borders will never move.
+ # Default: 30 minutes.
+ border_moving_starting_time_offset = 30
+
+ # Other
+
+ # Enable portals (nether, end, end gateway).
+ # Default: false.
+ enable_portals = false
+ """;
+ }
+
+ public void sendConfigPayload() {
+ final var payload = new ConfigPayload(nametagsEnabled(), skinsEnabled(), tabEnabled());
+ server.getPlayerList().getPlayers().forEach(p -> ServerPlayNetworking.send(p, payload));
+ }
+
+ public void sendConfigPayload(boolean showNametags, boolean showSkins, boolean showTab) {
+ final var payload = new ConfigPayload(showNametags, showSkins, showTab);
+ server.getPlayerList().getPlayers().forEach(p -> ServerPlayNetworking.send(p, payload));
+ }
+
+ public int getGameDuration() {
+ return server.overworld().getGameRules().get(Molehunt.GAME_DURATION);
+ }
+
+ public int getMolePercentage() {
+ return server.overworld().getGameRules().get(Molehunt.MOLE_PERCENTAGE);
+ }
+
+ public int getMoleCount() {
+ return server.overworld().getGameRules().get(Molehunt.MOLE_COUNT);
+ }
+
+ public boolean nametagsEnabled() {
+ return server.overworld().getGameRules().get(Molehunt.SHOW_NAMETAGS);
+ }
+
+ public boolean skinsEnabled() {
+ return server.overworld().getGameRules().get(Molehunt.SHOW_SKINS);
+ }
+
+ public boolean tabEnabled() {
+ return server.overworld().getGameRules().get(Molehunt.SHOW_TAB);
+ }
+
+ public int getInitialWorldSize() {
+ return server.overworld().getGameRules().get(Molehunt.INITIAL_WORLD_SIZE);
+ }
+
+ public int getFinalWorldSize() {
+ return server.overworld().getGameRules().get(Molehunt.FINAL_WORLD_SIZE);
+ }
+
+ public int getBorderShrinkingStartingTimeOffset() {
+ return server.overworld().getGameRules().get(Molehunt.MOVING_STARTING_TIME_OFFSET);
+ }
+
+ public boolean portalsEnabled() {
+ return server.overworld().getGameRules().get(Molehunt.ENABLE_PORTALS);
+ }
+
+ public boolean foodOnStart() {
+ return server.overworld().getGameRules().get(Molehunt.FOOD_ON_START);
+ }
}
diff --git a/src/main/java/world/anhgelus/molehunt/config/ConfigPayload.java b/src/main/java/world/anhgelus/molehunt/config/ConfigPayload.java
index 2388d09..950bec8 100644
--- a/src/main/java/world/anhgelus/molehunt/config/ConfigPayload.java
+++ b/src/main/java/world/anhgelus/molehunt/config/ConfigPayload.java
@@ -9,19 +9,19 @@ import org.jetbrains.annotations.NotNull;
import world.anhgelus.molehunt.Molehunt;
public record ConfigPayload(boolean showNametags, boolean showSkins, boolean showTab) implements CustomPacketPayload {
- public static final Identifier CONFIG_PACKET_ID = Identifier.fromNamespaceAndPath(Molehunt.MOD_ID, "config");
+ public static final Identifier CONFIG_PACKET_ID = Identifier.fromNamespaceAndPath(Molehunt.MOD_ID, "config");
- public static final CustomPacketPayload.Type<ConfigPayload> ID = new CustomPacketPayload.Type<>(CONFIG_PACKET_ID);
- public static final StreamCodec<RegistryFriendlyByteBuf, ConfigPayload> CODEC = StreamCodec.composite(
- ByteBufCodecs.BOOL, ConfigPayload::showNametags,
- ByteBufCodecs.BOOL, ConfigPayload::showSkins,
- ByteBufCodecs.BOOL, ConfigPayload::showTab,
- ConfigPayload::new
- );
+ public static final CustomPacketPayload.Type<ConfigPayload> ID = new CustomPacketPayload.Type<>(CONFIG_PACKET_ID);
+ public static final StreamCodec<RegistryFriendlyByteBuf, ConfigPayload> CODEC = StreamCodec.composite(
+ ByteBufCodecs.BOOL, ConfigPayload::showNametags,
+ ByteBufCodecs.BOOL, ConfigPayload::showSkins,
+ ByteBufCodecs.BOOL, ConfigPayload::showTab,
+ ConfigPayload::new
+ );
- @Override
- @NotNull
- public Type<? extends CustomPacketPayload> type() {
- return ID;
- }
+ @Override
+ @NotNull
+ public Type<? extends CustomPacketPayload> type() {
+ return ID;
+ }
}
diff --git a/src/main/java/world/anhgelus/molehunt/config/SimpleConfig.java b/src/main/java/world/anhgelus/molehunt/config/SimpleConfig.java
index a44ffaa..84e485b 100644
--- a/src/main/java/world/anhgelus/molehunt/config/SimpleConfig.java
+++ b/src/main/java/world/anhgelus/molehunt/config/SimpleConfig.java
@@ -38,209 +38,209 @@ import java.util.Scanner;
public class SimpleConfig {
- private static final Logger LOGGER = LogManager.getLogger("SimpleConfig");
- private final HashMap<String, String> config = new HashMap<>();
- private final ConfigRequest request;
- private boolean broken = false;
-
- private SimpleConfig(ConfigRequest request) {
- this.request = request;
- String identifier = "Config '" + request.filename + "'";
-
- if (!request.file.exists()) {
- LOGGER.info("{} is missing, generating default one...", identifier);
-
- try {
- createConfig();
- } catch (IOException e) {
- LOGGER.error("{} failed to generate!", identifier);
- LOGGER.trace(e);
- broken = true;
- }
- }
-
- if (!broken) {
- try {
- loadConfig();
- } catch (Exception e) {
- LOGGER.error("{} failed to load!", identifier);
- LOGGER.trace(e);
- broken = true;
- }
- }
-
- }
-
- /**
- * Creates new config request object, ideally `namespace`
- * should be the name of the mod id of the requesting mod
- *
- * @param filename - name of the config file
- * @return new config request object
- */
- public static ConfigRequest of(String filename) {
- Path path = FabricLoader.getInstance().getConfigDir();
- return new ConfigRequest(path.resolve(filename + ".properties").toFile(), filename);
- }
-
- private void createConfig() throws IOException {
- // try creating missing files
- final var parent = request.file.getParentFile();
- if (parent == null) throw new IOException("Cannot get parent file of the config");
- parent.mkdirs();
- Files.createFile(request.file.toPath());
-
- // write default config data
- PrintWriter writer = new PrintWriter(request.file, StandardCharsets.UTF_8);
- writer.write(request.getConfig());
- writer.close();
-
- }
-
- private void loadConfig() throws IOException {
- Scanner reader = new Scanner(request.file);
- for (int line = 1; reader.hasNextLine(); line++) {
- parseConfigEntry(reader.nextLine(), line);
- }
- }
-
- private void parseConfigEntry(String entry, int line) {
- if (!entry.isEmpty() && !entry.startsWith("#")) {
- String[] parts = entry.split("=", 2);
- if (parts.length == 2) {
- config.put(parts[0].stripTrailing(), parts[1].strip());
- } else {
- throw new RuntimeException("Syntax error in config file on line " + line + "!");
- }
- }
- }
-
- private String get(String key) {
- return config.get(key);
- }
-
- /**
- * Returns string value from config corresponding to the given
- * key, or the default string if the key is missing.
- *
- * @return value corresponding to the given key, or the default value
- */
- public String getOrDefault(String key, String def) {
- String val = get(key);
- return val == null ? def : val;
- }
-
- /**
- * Returns integer value from config corresponding to the given
- * key, or the default integer if the key is missing or invalid.
- *
- * @return value corresponding to the given key, or the default value
- */
- public int getOrDefault(String key, int def) {
- try {
- return Integer.parseInt(get(key));
- } catch (Exception e) {
- return def;
- }
- }
-
- /**
- * Returns boolean value from config corresponding to the given
- * key, or the default boolean if the key is missing.
- *
- * @return value corresponding to the given key, or the default value
- */
- public boolean getOrDefault(String key, boolean def) {
- String val = get(key);
- if (val != null) {
- return val.equalsIgnoreCase("true");
- }
-
- return def;
- }
-
- /**
- * Returns double value from config corresponding to the given
- * key, or the default string if the key is missing or invalid.
- *
- * @return value corresponding to the given key, or the default value
- */
- public double getOrDefault(String key, double def) {
- try {
- return Double.parseDouble(get(key));
- } catch (Exception e) {
- return def;
- }
- }
-
- /**
- * If any error occurred during loading or reading from the config
- * a 'broken' flag is set, indicating that the config's state
- * is undefined and should be discarded using `delete()`
- *
- * @return the 'broken' flag of the configuration
- */
- public boolean isBroken() {
- return broken;
- }
-
- /**
- * deletes the config file from the filesystem
- *
- * @return true if the operation was successful
- */
- public boolean delete() {
- LOGGER.warn("Config '{}' was removed from existence! Restart the game to regenerate it.", request.filename);
- return request.file.delete();
- }
-
- public interface DefaultConfig {
- static String empty(String namespace) {
- return "";
- }
-
- String get(String namespace);
- }
-
- public static class ConfigRequest {
-
- private final File file;
- private final String filename;
- private DefaultConfig provider;
-
- private ConfigRequest(File file, String filename) {
- this.file = file;
- this.filename = filename;
- this.provider = DefaultConfig::empty;
- }
-
- /**
- * Sets the default config provider, used to generate the
- * config if it's missing.
- *
- * @param provider default config provider
- * @return current config request object
- * @see DefaultConfig
- */
- public ConfigRequest provider(DefaultConfig provider) {
- this.provider = provider;
- return this;
- }
-
- /**
- * Loads the config from the filesystem.
- *
- * @return config object
- * @see SimpleConfig
- */
- public SimpleConfig request() {
- return new SimpleConfig(this);
- }
-
- private String getConfig() {
- return provider.get(filename) + "\n";
- }
-
- }
+ private static final Logger LOGGER = LogManager.getLogger("SimpleConfig");
+ private final HashMap<String, String> config = new HashMap<>();
+ private final ConfigRequest request;
+ private boolean broken = false;
+
+ private SimpleConfig(ConfigRequest request) {
+ this.request = request;
+ String identifier = "Config '" + request.filename + "'";
+
+ if (!request.file.exists()) {
+ LOGGER.info("{} is missing, generating default one...", identifier);
+
+ try {
+ createConfig();
+ } catch (IOException e) {
+ LOGGER.error("{} failed to generate!", identifier);
+ LOGGER.trace(e);
+ broken = true;
+ }
+ }
+
+ if (!broken) {
+ try {
+ loadConfig();
+ } catch (Exception e) {
+ LOGGER.error("{} failed to load!", identifier);
+ LOGGER.trace(e);
+ broken = true;
+ }
+ }
+
+ }
+
+ /**
+ * Creates new config request object, ideally `namespace`
+ * should be the name of the mod id of the requesting mod
+ *
+ * @param filename - name of the config file
+ * @return new config request object
+ */
+ public static ConfigRequest of(String filename) {
+ Path path = FabricLoader.getInstance().getConfigDir();
+ return new ConfigRequest(path.resolve(filename + ".properties").toFile(), filename);
+ }
+
+ private void createConfig() throws IOException {
+ // try creating missing files
+ final var parent = request.file.getParentFile();
+ if (parent == null) throw new IOException("Cannot get parent file of the config");
+ parent.mkdirs();
+ Files.createFile(request.file.toPath());
+
+ // write default config data
+ PrintWriter writer = new PrintWriter(request.file, StandardCharsets.UTF_8);
+ writer.write(request.getConfig());
+ writer.close();
+
+ }
+
+ private void loadConfig() throws IOException {
+ Scanner reader = new Scanner(request.file);
+ for (int line = 1; reader.hasNextLine(); line++) {
+ parseConfigEntry(reader.nextLine(), line);
+ }
+ }
+
+ private void parseConfigEntry(String entry, int line) {
+ if (!entry.isEmpty() && !entry.startsWith("#")) {
+ String[] parts = entry.split("=", 2);
+ if (parts.length == 2) {
+ config.put(parts[0].stripTrailing(), parts[1].strip());
+ } else {
+ throw new RuntimeException("Syntax error in config file on line " + line + "!");
+ }
+ }
+ }
+
+ private String get(String key) {
+ return config.get(key);
+ }
+
+ /**
+ * Returns string value from config corresponding to the given
+ * key, or the default string if the key is missing.
+ *
+ * @return value corresponding to the given key, or the default value
+ */
+ public String getOrDefault(String key, String def) {
+ String val = get(key);
+ return val == null ? def : val;
+ }
+
+ /**
+ * Returns integer value from config corresponding to the given
+ * key, or the default integer if the key is missing or invalid.
+ *
+ * @return value corresponding to the given key, or the default value
+ */
+ public int getOrDefault(String key, int def) {
+ try {
+ return Integer.parseInt(get(key));
+ } catch (Exception e) {
+ return def;
+ }
+ }
+
+ /**
+ * Returns boolean value from config corresponding to the given
+ * key, or the default boolean if the key is missing.
+ *
+ * @return value corresponding to the given key, or the default value
+ */
+ public boolean getOrDefault(String key, boolean def) {
+ String val = get(key);
+ if (val != null) {
+ return val.equalsIgnoreCase("true");
+ }
+
+ return def;
+ }
+
+ /**
+ * Returns double value from config corresponding to the given
+ * key, or the default string if the key is missing or invalid.
+ *
+ * @return value corresponding to the given key, or the default value
+ */
+ public double getOrDefault(String key, double def) {
+ try {
+ return Double.parseDouble(get(key));
+ } catch (Exception e) {
+ return def;
+ }
+ }
+
+ /**
+ * If any error occurred during loading or reading from the config
+ * a 'broken' flag is set, indicating that the config's state
+ * is undefined and should be discarded using `delete()`
+ *
+ * @return the 'broken' flag of the configuration
+ */
+ public boolean isBroken() {
+ return broken;
+ }
+
+ /**
+ * deletes the config file from the filesystem
+ *
+ * @return true if the operation was successful
+ */
+ public boolean delete() {
+ LOGGER.warn("Config '{}' was removed from existence! Restart the game to regenerate it.", request.filename);
+ return request.file.delete();
+ }
+
+ public interface DefaultConfig {
+ static String empty(String namespace) {
+ return "";
+ }
+
+ String get(String namespace);
+ }
+
+ public static class ConfigRequest {
+
+ private final File file;
+ private final String filename;
+ private DefaultConfig provider;
+
+ private ConfigRequest(File file, String filename) {
+ this.file = file;
+ this.filename = filename;
+ this.provider = DefaultConfig::empty;
+ }
+
+ /**
+ * Sets the default config provider, used to generate the
+ * config if it's missing.
+ *
+ * @param provider default config provider
+ * @return current config request object
+ * @see DefaultConfig
+ */
+ public ConfigRequest provider(DefaultConfig provider) {
+ this.provider = provider;
+ return this;
+ }
+
+ /**
+ * Loads the config from the filesystem.
+ *
+ * @return config object
+ * @see SimpleConfig
+ */
+ public SimpleConfig request() {
+ return new SimpleConfig(this);
+ }
+
+ private String getConfig() {
+ return provider.get(filename) + "\n";
+ }
+
+ }
} \ No newline at end of file
diff --git a/src/main/java/world/anhgelus/molehunt/game/Game.java b/src/main/java/world/anhgelus/molehunt/game/Game.java
index 5f4513d..9f44f77 100644
--- a/src/main/java/world/anhgelus/molehunt/game/Game.java
+++ b/src/main/java/world/anhgelus/molehunt/game/Game.java
@@ -22,178 +22,184 @@ import world.anhgelus.molehunt.utils.TimeUtils;
import java.util.*;
import java.util.concurrent.ThreadLocalRandom;
import java.util.stream.Collectors;
+import java.util.stream.Stream;
public class Game {
- public final int DEFAULT_TIME = Molehunt.CONFIG.getGameDuration() * 60;
- private final MinecraftServer server;
- private final List<UUID> moles = new ArrayList<>();
- private final ClientboundSetTitlesAnimationPacket timing = new ClientboundSetTitlesAnimationPacket(20, 40, 20);
- private boolean started = false;
- private int remaining = DEFAULT_TIME;
-
- public Game(MinecraftServer server) {
- this.server = server;
- }
-
- public void start() {
- final int n = Molehunt.CONFIG.getMoleCount() < 0
- ? Math.floorDiv(server.getPlayerCount(), Math.floorDiv(100, Molehunt.CONFIG.getMolePercentage()))
- : Molehunt.CONFIG.getMoleCount();
-
- final var playerManager = server.getPlayerList();
-
- final var players = new ArrayList<>(playerManager.getPlayers());
- for (int i = 0; i < n && !players.isEmpty(); i++) {
- final var r = ThreadLocalRandom.current().nextInt(0, players.size());
- final var mole = players.get(r);
- moles.add(mole.getUUID());
- players.remove(r);
- }
-
- final var gamerules = server.overworld().getGameRules();
- // immutable gamerules
- gamerules.set(GameRules.SHOW_DEATH_MESSAGES, false, server);
- gamerules.set(GameRules.SHOW_ADVANCEMENT_MESSAGES, false, server);
- // gamerules for the start
- gamerules.set(GameRules.IMMEDIATE_RESPAWN, true, server);
-
- final var timer = TimerAccess.getTimerFromOverworld(server);
-
- final var worldBorder = server.overworld().getWorldBorder();
- worldBorder.setSize(Molehunt.CONFIG.getInitialWorldSize());
- if (Molehunt.CONFIG.getBorderShrinkingStartingTimeOffset() < Molehunt.CONFIG.getGameDuration()) {
- timer.dds_runTask(new TickTask(() -> worldBorder.lerpSizeBetween(
- Molehunt.CONFIG.getInitialWorldSize(),
- Molehunt.CONFIG.getFinalWorldSize(),
- (long) (Molehunt.CONFIG.getGameDuration() - Molehunt.CONFIG.getBorderShrinkingStartingTimeOffset()) * 60 * 1000,
- 0L
- ), (long) Molehunt.CONFIG.getBorderShrinkingStartingTimeOffset() * 60 * 1000));
- }
-
- final var title = new ClientboundSetTitleTextPacket(Component.translatable("molehunt.game.start.suspense"));
- playerManager.getPlayers().forEach(p -> {
- p.getInventory().clearContent();
- p.kill(p.level());
- p.connection.send(timing);
- p.connection.send(title);
- p.setGameMode(GameType.SURVIVAL);
- if (Molehunt.CONFIG.foodOnStart()) p.addItem(new ItemStack(Items.COOKED_BEEF, 64));
- });
-
- server.setDefaultGameType(GameType.SPECTATOR);
-
- timer.dds_runTask(new TickTask(() -> {
- playerManager.getPlayers().forEach(p -> {
- p.connection.send(timing);
- if (moles.contains(p.getUUID())) {
- p.connection.send(new ClientboundSetTitleTextPacket(Component.translatable("molehunt.game.start.mole.title")));
- p.connection.send(new ClientboundSetSubtitleTextPacket(Component.translatable("molehunt.game.start.mole.subtitle")));
- } else {
- p.connection.send(new ClientboundSetTitleTextPacket(Component.translatable("molehunt.game.start.survivor.title")));
- p.connection.send(new ClientboundSetSubtitleTextPacket(Component.translatable("molehunt.game.start.survivor.subtitle")));
- }
- // reset health and food level
- p.setHealth(p.getMaxHealth());
- p.getFoodData().setFoodLevel(20);
- p.getFoodData().setSaturation(5.0f);
- });
- // reset gamerules after the start
- gamerules.set(GameRules.IMMEDIATE_RESPAWN, false, server);
- // reset time and weather
- final var overworld = server.overworld();
- server.clockManager()
- .setTotalTicks(overworld.getLevel().dimensionType().defaultClock().orElseThrow(), 0);
- overworld.resetWeatherCycle();
- changeState(true);
- timer.dds_runTask(new TickTask(() -> {
- remaining--;
- playerManager.getPlayers().forEach(player -> {
- if (Molehunt.timerVisibility.getOrDefault(player.getUUID(), true)) {
- player.connection.send(new ClientboundSetActionBarTextPacket(Component.translationArg(getRemainingText())));
- }
- });
- playerManager.broadcastAll(timing);
- if (remaining == 0) end();
- }, 5 * 1000, 1000));
- }, 4 * 1000));
- }
-
- public void stop() {
- server.getPlayerList().broadcastSystemMessage(Component.translatable("commands.molehunt.stop.success"), false);
- end();
- }
-
- public void end() {
- final var timer = TimerAccess.getTimerFromOverworld(server);
- timer.dds_cancel();
-
- final var worldBorder = server.overworld().getWorldBorder();
- // Stops the border shrinking.
- worldBorder.setSize(worldBorder.getSize());
-
- changeState(false);
- final var pm = server.getPlayerList();
- final var winnerSuspense = new ClientboundSetTitleTextPacket(Component.translatable("molehunt.game.end.suspense.title"));
- pm.getPlayers().forEach(p -> {
- p.connection.send(timing);
- p.connection.send(winnerSuspense);
- p.setGameMode(GameType.CREATIVE);
- });
-
- timer.dds_runTask(new TickTask(() -> {
- ClientboundSetTitleTextPacket winner;
- if (wonByMoles()) {
- winner = new ClientboundSetTitleTextPacket(Component.translatable("molehunt.game.end.winners.moles.title"));
- } else {
- winner = new ClientboundSetTitleTextPacket(Component.translatable("molehunt.game.end.winners.survivors.title"));
- }
- pm.broadcastAll(new ClientboundSetSubtitleTextPacket(Component.translatable("molehunt.game.end.winners.subtitle", getMolesAsString())));
- pm.broadcastAll(winner);
- pm.broadcastAll(timing);
- moles.clear();
- }, 4 * 1000));
- }
-
- public Component getRemainingText() {
- return Component.nullToEmpty("§c" + TimeUtils.toTime(remaining));
- }
-
- public List<ServerPlayer> getMoles() {
- return moles.stream()
- .map(uuid -> server.getPlayerList().getPlayer(uuid))
- .filter(Objects::nonNull)
- .filter(p -> !p.isSpectator())
- .toList();
- }
-
- public String getMolesAsString() {
- return getMoles().stream()
- .map(Player::getDisplayName)
- .map(Object::toString)
- .collect(Collectors.joining(", "));
- }
-
- public boolean isMole(ServerPlayer player) {
- return moles.contains(player.getUUID());
- }
-
- public boolean wonByMoles() {
- return new HashSet<>(moles).containsAll(
- server.getPlayerList().getPlayers().stream()
- .filter(p -> p.gameMode.isSurvival())
- .map(Entity::getUUID)
- .collect(Collectors.toSet())
- );
- }
-
- public boolean started() {
- return started;
- }
-
- private void changeState(boolean hasStarted) {
- started = hasStarted;
- final var payload = new GamePayload(hasStarted);
- server.getPlayerList().getPlayers().forEach(p -> ServerPlayNetworking.send(p, payload));
- }
+ public final int DEFAULT_TIME = Molehunt.CONFIG.getGameDuration() * 60;
+ private final MinecraftServer server;
+ private final List<UUID> moles = new ArrayList<>();
+ private final ClientboundSetTitlesAnimationPacket timing = new ClientboundSetTitlesAnimationPacket(20, 40, 20);
+ private boolean started = false;
+ private int remaining = DEFAULT_TIME;
+
+ public Game(MinecraftServer server) {
+ this.server = server;
+ }
+
+ public void start() {
+ final int n = Molehunt.CONFIG.getMoleCount() < 0
+ ? Math.floorDiv(server.getPlayerCount(), Math.floorDiv(100, Molehunt.CONFIG.getMolePercentage()))
+ : Molehunt.CONFIG.getMoleCount();
+
+ final var playerManager = server.getPlayerList();
+
+ final var players = new ArrayList<>(playerManager.getPlayers());
+ for (int i = 0; i < n && !players.isEmpty(); i++) {
+ final var r = ThreadLocalRandom.current().nextInt(0, players.size());
+ final var mole = players.get(r);
+ moles.add(mole.getUUID());
+ players.remove(r);
+ }
+
+ final var gamerules = server.overworld().getGameRules();
+ // immutable gamerules
+ gamerules.set(GameRules.SHOW_DEATH_MESSAGES, false, server);
+ gamerules.set(GameRules.SHOW_ADVANCEMENT_MESSAGES, false, server);
+ // gamerules for the start
+ gamerules.set(GameRules.IMMEDIATE_RESPAWN, true, server);
+
+ final var timer = TimerAccess.getTimerFromOverworld(server);
+
+ final var worldBorder = server.overworld().getWorldBorder();
+ worldBorder.setSize(Molehunt.CONFIG.getInitialWorldSize());
+ if (Molehunt.CONFIG.getBorderShrinkingStartingTimeOffset() < Molehunt.CONFIG.getGameDuration()) {
+ timer.dds_runTask(new TickTask(() -> worldBorder.lerpSizeBetween(
+ Molehunt.CONFIG.getInitialWorldSize(),
+ Molehunt.CONFIG.getFinalWorldSize(),
+ (Molehunt.CONFIG.getGameDuration() - Molehunt.CONFIG.getBorderShrinkingStartingTimeOffset()) * 60 * 20L,
+ 0L
+ ), Molehunt.CONFIG.getBorderShrinkingStartingTimeOffset() * 60 * 20L));
+ }
+
+ final var title = new ClientboundSetTitleTextPacket(Component.translatable("molehunt.game.start.suspense"));
+ playerManager.getPlayers().forEach(p -> {
+ p.getInventory().clearContent();
+ p.kill(p.level());
+ p.connection.send(timing);
+ p.connection.send(title);
+ p.setGameMode(GameType.SURVIVAL);
+ if (Molehunt.CONFIG.foodOnStart()) p.addItem(new ItemStack(Items.COOKED_BEEF, 64));
+ });
+
+ server.setDefaultGameType(GameType.SPECTATOR);
+
+ timer.dds_runTask(new TickTask(() -> {
+ playerManager.getPlayers().forEach(p -> {
+ p.connection.send(timing);
+ if (moles.contains(p.getUUID())) {
+ p.connection.send(new ClientboundSetTitleTextPacket(Component.translatable("molehunt.game.start.mole.title")));
+ p.connection.send(new ClientboundSetSubtitleTextPacket(Component.translatable("molehunt.game.start.mole.subtitle")));
+ } else {
+ p.connection.send(new ClientboundSetTitleTextPacket(Component.translatable("molehunt.game.start.survivor.title")));
+ p.connection.send(new ClientboundSetSubtitleTextPacket(Component.translatable("molehunt.game.start.survivor.subtitle")));
+ }
+ // reset health and food level
+ p.setHealth(p.getMaxHealth());
+ p.getFoodData().setFoodLevel(20);
+ p.getFoodData().setSaturation(5.0f);
+ });
+ // reset gamerules after the start
+ gamerules.set(GameRules.IMMEDIATE_RESPAWN, false, server);
+ // reset time and weather
+ final var overworld = server.overworld();
+ server.clockManager()
+ .setTotalTicks(overworld.getLevel().dimensionType().defaultClock().orElseThrow(), 0);
+ overworld.resetWeatherCycle();
+ changeState(true);
+ timer.dds_runTask(new TickTask(() -> {
+ remaining--;
+ playerManager.getPlayers().forEach(player -> {
+ if (Molehunt.timerVisibility.getOrDefault(player.getUUID(), true)) {
+ player.connection.send(new ClientboundSetActionBarTextPacket(Component.translationArg(getRemainingText())));
+ }
+ });
+ playerManager.broadcastAll(timing);
+ if (remaining == 0) end();
+ }, 5 * 1000, 1000));
+ }, 4 * 1000));
+ }
+
+ public void stop() {
+ server.getPlayerList().broadcastSystemMessage(Component.translatable("commands.molehunt.stop.success"), false);
+ end();
+ }
+
+ public void end() {
+ final var timer = TimerAccess.getTimerFromOverworld(server);
+ timer.dds_cancel();
+
+ final var worldBorder = server.overworld().getWorldBorder();
+ // Stops the border shrinking.
+ worldBorder.setSize(worldBorder.getSize());
+
+ changeState(false);
+ final var pm = server.getPlayerList();
+ final var winnerSuspense = new ClientboundSetTitleTextPacket(Component.translatable("molehunt.game.end.suspense.title"));
+ pm.getPlayers().forEach(p -> {
+ p.connection.send(timing);
+ p.connection.send(winnerSuspense);
+ p.setGameMode(GameType.CREATIVE);
+ });
+
+ timer.dds_runTask(new TickTask(() -> {
+ ClientboundSetTitleTextPacket winner;
+ if (wonByMoles()) {
+ winner = new ClientboundSetTitleTextPacket(Component.translatable("molehunt.game.end.winners.moles.title"));
+ } else {
+ winner = new ClientboundSetTitleTextPacket(Component.translatable("molehunt.game.end.winners.survivors.title"));
+ }
+ pm.broadcastAll(new ClientboundSetSubtitleTextPacket(Component.translatable("molehunt.game.end.winners.subtitle", getMolesAsString())));
+ pm.broadcastAll(winner);
+ pm.broadcastAll(timing);
+ moles.clear();
+ }, 4 * 1000));
+ }
+
+ public Component getRemainingText() {
+ return Component.nullToEmpty("§c" + TimeUtils.toTime(remaining));
+ }
+
+ private Stream<ServerPlayer> getMoles() {
+ return moles.stream()
+ .map(uuid -> server.getPlayerList().getPlayer(uuid))
+ .filter(Objects::nonNull)
+ .filter(p -> p.gameMode.isSurvival());
+ }
+
+ public int getMolesCount() {
+ return getMoles().toArray().length;
+ }
+
+ public String getMolesAsString() {
+ return getMoles().map(Player::getDisplayName)
+ .map(Object::toString)
+ .collect(Collectors.joining(", "));
+ }
+
+ public boolean isMole(ServerPlayer player) {
+ return moles.contains(player.getUUID());
+ }
+
+ public boolean wonByMoles() {
+ final var moles = getMoles().map(Player::getUUID).toList();
+ return !moles.isEmpty() && new HashSet<>(moles).containsAll(
+ server.getPlayerList()
+ .getPlayers()
+ .stream()
+ .filter(p -> p.gameMode.isSurvival())
+ .map(Entity::getUUID)
+ .toList()
+ );
+ }
+
+ private void changeState(boolean hasStarted) {
+ started = hasStarted;
+ final var payload = new GamePayload(hasStarted);
+ server.getPlayerList().getPlayers().forEach(p -> ServerPlayNetworking.send(p, payload));
+ }
+
+ public boolean started() {
+ return started;
+ }
}
diff --git a/src/main/java/world/anhgelus/molehunt/game/GamePayload.java b/src/main/java/world/anhgelus/molehunt/game/GamePayload.java
index 3a32e1c..f654115 100644
--- a/src/main/java/world/anhgelus/molehunt/game/GamePayload.java
+++ b/src/main/java/world/anhgelus/molehunt/game/GamePayload.java
@@ -9,17 +9,17 @@ import org.jetbrains.annotations.NotNull;
import world.anhgelus.molehunt.Molehunt;
public record GamePayload(boolean gameLaunched) implements CustomPacketPayload {
- public static final Identifier GAME_PACKET_ID = Identifier.fromNamespaceAndPath(Molehunt.MOD_ID, "game");
+ public static final Identifier GAME_PACKET_ID = Identifier.fromNamespaceAndPath(Molehunt.MOD_ID, "game");
- public static final CustomPacketPayload.Type<GamePayload> ID = new CustomPacketPayload.Type<>(GAME_PACKET_ID);
- public static final StreamCodec<RegistryFriendlyByteBuf, GamePayload> CODEC = StreamCodec.composite(
- ByteBufCodecs.BOOL, GamePayload::gameLaunched,
- GamePayload::new
- );
+ public static final CustomPacketPayload.Type<GamePayload> ID = new CustomPacketPayload.Type<>(GAME_PACKET_ID);
+ public static final StreamCodec<RegistryFriendlyByteBuf, GamePayload> CODEC = StreamCodec.composite(
+ ByteBufCodecs.BOOL, GamePayload::gameLaunched,
+ GamePayload::new
+ );
- @Override
- @NotNull
- public Type<? extends CustomPacketPayload> type() {
- return ID;
- }
+ @Override
+ @NotNull
+ public Type<? extends CustomPacketPayload> type() {
+ return ID;
+ }
}
diff --git a/src/main/java/world/anhgelus/molehunt/mixin/NoJoinLeaveMessage.java b/src/main/java/world/anhgelus/molehunt/mixin/NoJoinLeaveMessage.java
index 0771981..e1992fe 100644
--- a/src/main/java/world/anhgelus/molehunt/mixin/NoJoinLeaveMessage.java
+++ b/src/main/java/world/anhgelus/molehunt/mixin/NoJoinLeaveMessage.java
@@ -9,10 +9,10 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(PlayerList.class)
public class NoJoinLeaveMessage {
- @Inject(at = @At("HEAD"), method = "broadcastSystemMessage*", cancellable = true)
- public void broadcastNoJoinLeaveMessage(final Component message, final boolean overlay, CallbackInfo ci) {
- final var content = message.getContents().toString();
- if (content.startsWith("translation{key='multiplayer.player.joined") ||
- content.startsWith("translation{key='multiplayer.player.left")) ci.cancel();
- }
+ @Inject(at = @At("HEAD"), method = "broadcastSystemMessage*", cancellable = true)
+ public void broadcastNoJoinLeaveMessage(final Component message, final boolean overlay, CallbackInfo ci) {
+ final var content = message.getContents().toString();
+ if (content.startsWith("translation{key='multiplayer.player.joined") ||
+ content.startsWith("translation{key='multiplayer.player.left")) ci.cancel();
+ }
}
diff --git a/src/main/java/world/anhgelus/molehunt/mixin/NoMsgCommand.java b/src/main/java/world/anhgelus/molehunt/mixin/NoMsgCommand.java
index b68773e..cef2f59 100644
--- a/src/main/java/world/anhgelus/molehunt/mixin/NoMsgCommand.java
+++ b/src/main/java/world/anhgelus/molehunt/mixin/NoMsgCommand.java
@@ -10,8 +10,8 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(MsgCommand.class)
public class NoMsgCommand {
- @Inject(at = @At("HEAD"), method = "register", cancellable = true)
- private static void register(CommandDispatcher<CommandSourceStack> dispatcher, CallbackInfo ci) {
- ci.cancel();
- }
+ @Inject(at = @At("HEAD"), method = "register", cancellable = true)
+ private static void register(CommandDispatcher<CommandSourceStack> dispatcher, CallbackInfo ci) {
+ ci.cancel();
+ }
}
diff --git a/src/main/java/world/anhgelus/molehunt/mixin/NoPortals.java b/src/main/java/world/anhgelus/molehunt/mixin/NoPortals.java
index 74504fe..acad2ba 100644
--- a/src/main/java/world/anhgelus/molehunt/mixin/NoPortals.java
+++ b/src/main/java/world/anhgelus/molehunt/mixin/NoPortals.java
@@ -11,9 +11,9 @@ import world.anhgelus.molehunt.Molehunt;
@Mixin(PortalProcessor.class)
public class NoPortals {
- @Inject(at = @At("HEAD"), method = "processPortalTeleportation", cancellable = true)
- public void disableTick(ServerLevel world, Entity entity, boolean canUsePortals, CallbackInfoReturnable<Boolean> cir) {
- if (Molehunt.CONFIG == null || Molehunt.CONFIG.portalsEnabled()) return;
- cir.setReturnValue(false);
- }
+ @Inject(at = @At("HEAD"), method = "processPortalTeleportation", cancellable = true)
+ public void disableTick(ServerLevel world, Entity entity, boolean canUsePortals, CallbackInfoReturnable<Boolean> cir) {
+ if (Molehunt.CONFIG == null || Molehunt.CONFIG.portalsEnabled()) return;
+ cir.setReturnValue(false);
+ }
}
diff --git a/src/main/java/world/anhgelus/molehunt/mixin/WorldTimerAccess.java b/src/main/java/world/anhgelus/molehunt/mixin/WorldTimerAccess.java
index cd8a1b4..a299d7f 100644
--- a/src/main/java/world/anhgelus/molehunt/mixin/WorldTimerAccess.java
+++ b/src/main/java/world/anhgelus/molehunt/mixin/WorldTimerAccess.java
@@ -1,6 +1,6 @@
package world.anhgelus.molehunt.mixin;
-import net.minecraft.server.world.ServerWorld;
+import net.minecraft.server.level.ServerLevel;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
@@ -12,34 +12,34 @@ import java.util.ArrayList;
import java.util.List;
import java.util.function.BooleanSupplier;
-@Mixin(ServerWorld.class)
+@Mixin(ServerLevel.class)
public class WorldTimerAccess implements TimerAccess {
- @Unique
- private final List<TickTask> tasks = new ArrayList<>();
-
- @Unique
- private final List<TimerAccess.TickTask> tasksToAdd = new ArrayList<>();
-
- @Inject(method = "tick", at = @At("TAIL"))
- private void onTick(BooleanSupplier shouldKeepTicking, CallbackInfo ci) {
- tasks.stream().filter(TickTask::isRunning).forEach(TickTask::tick);
- tasks.addAll(tasksToAdd);
- tasksToAdd.clear();
- }
-
- @Override
- public void dds_runTask(TimerAccess.TickTask task) {
- tasksToAdd.add(task);
- }
-
- @Override
- public void dds_cancel() {
- tasks.stream().filter(TickTask::isRunning).forEach(TickTask::cancel);
- tasks.clear();
- }
-
- @Override
- public List<TickTask> dds_getTasks() {
- return tasks.stream().filter(TickTask::isRunning).toList();
- }
+ @Unique
+ private final List<TickTask> tasks = new ArrayList<>();
+
+ @Unique
+ private final List<TimerAccess.TickTask> tasksToAdd = new ArrayList<>();
+
+ @Inject(method = "tick", at = @At("TAIL"))
+ private void onTick(BooleanSupplier shouldKeepTicking, CallbackInfo ci) {
+ tasks.stream().filter(TickTask::isRunning).forEach(TickTask::tick);
+ tasks.addAll(tasksToAdd);
+ tasksToAdd.clear();
+ }
+
+ @Override
+ public void dds_runTask(TimerAccess.TickTask task) {
+ tasksToAdd.add(task);
+ }
+
+ @Override
+ public void dds_cancel() {
+ tasks.stream().filter(TickTask::isRunning).forEach(TickTask::cancel);
+ tasks.clear();
+ }
+
+ @Override
+ public List<TickTask> dds_getTasks() {
+ return tasks.stream().filter(TickTask::isRunning).toList();
+ }
} \ No newline at end of file
diff --git a/src/main/java/world/anhgelus/molehunt/timer/TickTask.java b/src/main/java/world/anhgelus/molehunt/timer/TickTask.java
index 8c74b89..1cc83e2 100644
--- a/src/main/java/world/anhgelus/molehunt/timer/TickTask.java
+++ b/src/main/java/world/anhgelus/molehunt/timer/TickTask.java
@@ -4,69 +4,69 @@ package world.anhgelus.molehunt.timer;
* Represents a complete task called each tick
*/
public class TickTask implements TimerAccess.TickTask {
- public final long ticksDelay;
- public final long ticksRepeat;
- public final boolean repeating;
- public final TimerAccess.Task task;
- private boolean cancelled = false;
- private long currentTicking;
+ public final long ticksDelay;
+ public final long ticksRepeat;
+ public final boolean repeating;
+ public final TimerAccess.Task task;
+ private boolean cancelled = false;
+ private long currentTicking;
- /**
- * Create a new repeating TickTask
- *
- * @param task Task to run after the delay or the repeat time
- * @param ticksDelay Delay before the first task's run
- * @param ticksRepeat Repeat each tick (if the repeat is 0, it will repeat each tick, if it is below 0, it will not repeat)
- * @throws IllegalArgumentException if ticksDelay is below 0
- */
- public TickTask(TimerAccess.Task task, long ticksDelay, long ticksRepeat) {
- if (ticksDelay < 0) throw new IllegalArgumentException("Ticks delay must be non-negative");
- this.ticksDelay = ticksDelay;
- this.ticksRepeat = ticksRepeat;
- this.task = task;
- repeating = ticksRepeat >= 0;
- currentTicking = ticksDelay;
- }
+ /**
+ * Create a new repeating TickTask
+ *
+ * @param task Task to run after the delay or the repeat time
+ * @param ticksDelay Delay before the first task's run
+ * @param ticksRepeat Repeat each tick (if the repeat is 0, it will repeat each tick, if it is below 0, it will not repeat)
+ * @throws IllegalArgumentException if ticksDelay is below 0
+ */
+ public TickTask(TimerAccess.Task task, long ticksDelay, long ticksRepeat) {
+ if (ticksDelay < 0) throw new IllegalArgumentException("Ticks delay must be non-negative");
+ this.ticksDelay = ticksDelay;
+ this.ticksRepeat = ticksRepeat;
+ this.task = task;
+ repeating = ticksRepeat >= 0;
+ currentTicking = ticksDelay;
+ }
- /**
- * Create a new delayed TickTask
- *
- * @param task Task to run after the delay or the repeat time
- * @param ticksDelay Delay before the first task's run
- * @throws IllegalArgumentException if ticksDelay or if ticksRepeat is below 0
- */
- public TickTask(TimerAccess.Task task, long ticksDelay) {
- if (ticksDelay < 0) throw new IllegalArgumentException("Ticks delay must be non-negative");
- this.ticksDelay = ticksDelay;
- this.ticksRepeat = -1;
- this.task = task;
- repeating = false;
- currentTicking = ticksDelay;
- }
+ /**
+ * Create a new delayed TickTask
+ *
+ * @param task Task to run after the delay or the repeat time
+ * @param ticksDelay Delay before the first task's run
+ * @throws IllegalArgumentException if ticksDelay or if ticksRepeat is below 0
+ */
+ public TickTask(TimerAccess.Task task, long ticksDelay) {
+ if (ticksDelay < 0) throw new IllegalArgumentException("Ticks delay must be non-negative");
+ this.ticksDelay = ticksDelay;
+ this.ticksRepeat = -1;
+ this.task = task;
+ repeating = false;
+ currentTicking = ticksDelay;
+ }
- public void tick() {
- if (--currentTicking > 0) return;
- task.run();
- if (repeating) {
- currentTicking = ticksRepeat;
- } else {
- cancel();
- }
- }
+ public void tick() {
+ if (--currentTicking > 0) return;
+ task.run();
+ if (repeating) {
+ currentTicking = ticksRepeat;
+ } else {
+ cancel();
+ }
+ }
- public long cancel() {
- if (cancelled) throw new IllegalStateException("Task already cancelled");
- cancelled = true;
- return currentTicking;
- }
+ public long cancel() {
+ if (cancelled) throw new IllegalStateException("Task already cancelled");
+ cancelled = true;
+ return currentTicking;
+ }
- public boolean isRunning() {
- return !cancelled;
- }
+ public boolean isRunning() {
+ return !cancelled;
+ }
- @Override
- public long getTickingBeforeRun() {
- if (cancelled) return -1;
- return currentTicking;
- }
+ @Override
+ public long getTickingBeforeRun() {
+ if (cancelled) return -1;
+ return currentTicking;
+ }
} \ No newline at end of file
diff --git a/src/main/java/world/anhgelus/molehunt/timer/TimerAccess.java b/src/main/java/world/anhgelus/molehunt/timer/TimerAccess.java
index 2e02b12..59453e3 100644
--- a/src/main/java/world/anhgelus/molehunt/timer/TimerAccess.java
+++ b/src/main/java/world/anhgelus/molehunt/timer/TimerAccess.java
@@ -1,65 +1,61 @@
package world.anhgelus.molehunt.timer;
import net.minecraft.server.MinecraftServer;
-import net.minecraft.world.World;
import java.util.List;
public interface TimerAccess {
- /**
- * Get the timer linked to the overworld
- *
- * @param server Current server
- * @return TimerAccess linked to the overworld
- */
- static TimerAccess getTimerFromOverworld(MinecraftServer server) {
- final var timer = (TimerAccess) server.getWorld(World.OVERWORLD);
- if (timer == null)
- throw new NullPointerException("Impossible to get TimerAccess from the overworld (it is null)");
- return timer;
- }
-
- /**
- * Run a task (called each tick ticked)
- *
- * @param task Task to run
- */
- void dds_runTask(TimerAccess.TickTask task);
-
- void dds_cancel();
-
- /**
- * @return All non-cancelled tasks
- */
- List<TickTask> dds_getTasks();
-
- interface TickTask {
- /**
- * Tick the task
- */
- void tick();
-
- /**
- * Cancel the task
- *
- * @return the remaining ticks before the run of the Task
- * @throws IllegalStateException if the task is already cancelled
- */
- long cancel();
-
- boolean isRunning();
-
- /**
- * @return the number of ticks before run of the task (if the task is cancelled, returns -1)
- */
- long getTickingBeforeRun();
- }
-
- /**
- * Represents a task to run after ticking
- */
- @FunctionalInterface
- interface Task {
- void run();
- }
+ /**
+ * Get the timer linked to the overworld
+ *
+ * @param server Current server
+ * @return TimerAccess linked to the overworld
+ */
+ static TimerAccess getTimerFromOverworld(MinecraftServer server) {
+ return (TimerAccess) server.overworld();
+ }
+
+ /**
+ * Run a task (called each tick ticked)
+ *
+ * @param task Task to run
+ */
+ void dds_runTask(TimerAccess.TickTask task);
+
+ void dds_cancel();
+
+ /**
+ * @return All non-cancelled tasks
+ */
+ List<TickTask> dds_getTasks();
+
+ interface TickTask {
+ /**
+ * Tick the task
+ */
+ void tick();
+
+ /**
+ * Cancel the task
+ *
+ * @return the remaining ticks before the run of the Task
+ * @throws IllegalStateException if the task is already cancelled
+ */
+ long cancel();
+
+ boolean isRunning();
+
+ /**
+ * @return the number of ticks before run of the task (if the task is cancelled, returns -1)
+ */
+ long getTickingBeforeRun();
+ }
+
+ /**
+ * Represents a task to run after ticking
+ */
+ @FunctionalInterface
+ interface Task {
+ void run();
+ }
}
diff --git a/src/main/java/world/anhgelus/molehunt/utils/TimeUtils.java b/src/main/java/world/anhgelus/molehunt/utils/TimeUtils.java
index ac3c116..4d69e0a 100644
--- a/src/main/java/world/anhgelus/molehunt/utils/TimeUtils.java
+++ b/src/main/java/world/anhgelus/molehunt/utils/TimeUtils.java
@@ -3,34 +3,33 @@ package world.anhgelus.molehunt.utils;
import org.jetbrains.annotations.NotNull;
public class TimeUtils {
+ public static Time toTime(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);
+ }
- public record Time(long hours, long minutes, long seconds) {
- public @NotNull String toString() {
- return padLeft(hours) + ":" +
- padLeft(minutes) + ":" +
- padLeft(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));
+ }
- public static Time toTime(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));
- }
+ public record Time(long hours, long minutes, long seconds) {
+ public @NotNull String toString() {
+ return padLeft(hours) + ":" +
+ padLeft(minutes) + ":" +
+ padLeft(seconds);
+ }
+ }
}
diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json
index 09a65fe..43d56c8 100644
--- a/src/main/resources/fabric.mod.json
+++ b/src/main/resources/fabric.mod.json
@@ -1,37 +1,36 @@
{
- "schemaVersion": 1,
- "id": "molehunt",
- "version": "${version}",
- "name": "Molehunt",
- "description": "Molehunt mod",
- "authors": [
- "Anhgelus Morhtuuzh"
- ],
- "contact": {},
- "license": "AGPL-3.0",
- "icon": "assets/molehunt/icon.png",
- "environment": "*",
- "entrypoints": {
- "client": [
- "world.anhgelus.molehunt.client.MolehuntClient"
- ],
- "server": [
-
- ],
- "main": [
- "world.anhgelus.molehunt.Molehunt"
- ]
- },
- "mixins": [
- "molehunt.mixins.json",
- {
- "config": "molehunt.client.mixins.json",
- "environment": "client"
- }
- ],
- "depends": {
- "fabricloader": ">=${loader_version}",
- "fabric-api": "*",
- "minecraft": "${minecraft_version}"
- }
+ "schemaVersion": 1,
+ "id": "molehunt",
+ "version": "${version}",
+ "name": "Molehunt",
+ "description": "Molehunt mod",
+ "authors": [
+ "Anhgelus Morhtuuzh"
+ ],
+ "contact": {},
+ "license": "AGPL-3.0",
+ "icon": "assets/molehunt/icon.png",
+ "environment": "*",
+ "entrypoints": {
+ "client": [
+ "world.anhgelus.molehunt.client.MolehuntClient"
+ ],
+ "server": [
+ ],
+ "main": [
+ "world.anhgelus.molehunt.Molehunt"
+ ]
+ },
+ "mixins": [
+ "molehunt.mixins.json",
+ {
+ "config": "molehunt.client.mixins.json",
+ "environment": "client"
+ }
+ ],
+ "depends": {
+ "fabricloader": ">=${loader_version}",
+ "fabric-api": "*",
+ "minecraft": "${minecraft_version}"
+ }
}
diff --git a/src/main/resources/molehunt.mixins.json b/src/main/resources/molehunt.mixins.json
index 2dc5bb9..8013886 100644
--- a/src/main/resources/molehunt.mixins.json
+++ b/src/main/resources/molehunt.mixins.json
@@ -1,15 +1,15 @@
{
- "required": true,
- "minVersion": "0.8",
- "package": "world.anhgelus.molehunt.mixin",
- "compatibilityLevel": "JAVA_21",
- "mixins": [
- "NoJoinLeaveMessage",
- "NoMsgCommand",
- "NoPortals",
- "WorldTimerAccess"
- ],
- "injectors": {
- "defaultRequire": 1
- }
+ "required": true,
+ "minVersion": "0.8",
+ "package": "world.anhgelus.molehunt.mixin",
+ "compatibilityLevel": "JAVA_21",
+ "mixins": [
+ "NoJoinLeaveMessage",
+ "NoMsgCommand",
+ "NoPortals",
+ "WorldTimerAccess"
+ ],
+ "injectors": {
+ "defaultRequire": 1
+ }
}