From 988a0bd2456146816377851c31be40b2ba50ebac Mon Sep 17 00:00:00 2001 From: MTaningco Date: Mon, 30 Sep 2024 10:38:44 -0700 Subject: [PATCH 1/2] Add README changes. Add startingSeason config. --- README.md | 71 ++++++++- .../lucaargolo/seasons/FabricSeasons.java | 142 +++++++++--------- .../seasons/commands/SeasonCommand.java | 42 +++++- .../lucaargolo/seasons/utils/ModConfig.java | 16 ++ 4 files changed, 193 insertions(+), 78 deletions(-) diff --git a/README.md b/README.md index cd544d4..94a5d9e 100644 --- a/README.md +++ b/README.md @@ -15,8 +15,75 @@

-## Features -For a complete list of features please check the mods [official page](https://www.curseforge.com/minecraft/mc-mods/fabric-seasons) +## Description + +Fabric Seasons adds four seasons to Minecraft, each lasting 28 in-game days (configurable). The current season is defined by the world time (using `/time set 0` will reset to day 1 of Spring). Each season has its own changes. Spring will match the original biome colors and biome behaviors. + +The mod has 2 components: + +- Server: If installed on the server, biomes will have different temperatures. This enables weather changes like snowing and block freezing in the winter. The server component also contains seasonal crops, allowing crops to grow at different speeds according to the season. +- Client: If installed on the client, biomes will have different colormaps according to the current season. This is just a visual change and it will not physically impact your world in any form. + +To get the full experience, it is recommended that you install the mod on both the server and the client. + +All biomes are grouped in 5 categories with the following characteristics: + +- Permanently Frozen Biomes (`temp ≤ -0.51`): Permanently frozen year-round +- Usually Frozen Biomes (`temp ≤ 0.15`): Becomes ice free in the Summer +- Temperate Biomes (`temp ≤ 0.49`): Ice free in the Spring and Summer +- Usually Ice Free Biomes (`temp ≤ 0.79`): Only freezes in the Winter +- Ice Free Biomes (`temp > 0.79`): Ice free year-round, will also allow rain in the Winter + +

+ + + +

+ +Only overworld biomes can have this seasonality, which can be configured in `config/seasons.json` + +*Please note that this mod melts / applies freezing blocks and snow **within simulation distance**. This means that anything outside is unaffected by the seasons unless if you travel to these blocks. It is currently not possible to globally melt or freeze blocks outside of this distance. It is possible to mitigate this by temporarily increasing the `randomTickSpeed`. Otherwise if you want to completely avoid this limitation, set `doTemperatureChanges` in the config file to `false`.* + +## Configurations + +Fabric Seasons can be configured in your instance's `config` folder. The file is called `seasons.json`. To apply your own changes to the configuration, please restart your client. +| Config Variable | Description | Default +| -------- | ------- | ------- +| springLength / summerLength / fallLength / winterLength | The integer for the length of a season in "game ticks" (672000 game ticks == 33600 in-game seconds == 28 in-game days) | 672000 +| startingSeason | The starting season of the year. Only applicable when `isSeasonLocked` is `false` and `isSeasonTiedWithSystemTime` is `false`. Valid values are `SPRING`, `SUMMER`, `FALL`, or `WINTER`. | "SPRING" +| isSeasonLocked | Flag to lock the season | false +| lockedSeason | The season to lock if `isSeasonLocked` is true. Valid values are `SPRING`, `SUMMER`, `FALL`, or `WINTER`.| "SPRING" +| dimensionAllowList | The list of dimensions to allow seasons. This may be useful for multiplayer. A valid value would be one in the format of `":"`. | ["minecraft:overworld"] +| doTemperatureChanges | Flag that modifies precipitation and freezing on biomes. **Setting to false essentially disables any biome behavior or aesthetic changes year round.** | true +| shouldSnowyBiomesMeltInSummer | Flag that determines if "Usually Freezing Biomes" should melt during Summer | true +| shouldIceNearWaterMelt | When true, ice will melt in an ice-free biome regardless of being placed by a player when it is beside a water source or flowing water. When false, default ice behavior occurs. | false +| biomeDenyList | The list of biomes that keep it's original temperature and freezing behavior year-round. A valid value would be one in the format of `":"`. | ["terralith:glacial_chasm", "minecraft:frozen_ocean", "minecraft:deep_frozen_ocean", "minecraft:ocean", "minecraft:deep_ocean", "minecraft:cold_ocean", "minecraft:deep_cold_ocean", "minecraft:lukewarm_ocean", "minecraft:deep_lukewarm_ocean", "minecraft:warm_ocean"] +| biomeForceSnowInWinterList | The list of biomes to force freezing during the winter season. A valid value would be one in the format of `":"`. | ["minecraft:plains", "minecraft:sunflower_plains", "minecraft:stony_peaks"] +| isSeasonTiedWithSystemTime | Flag that determines if the seasons should be synced to real world seasonal cycles | false +| isInNorthHemisphere | Only used if `isSeasonTiedWithSystemTime` is set to true. Determines if the player is situated in the North Hemisphere to properly calculate the seasons. | true +| isFallAndSpringReversed | By default, there are more biomes that snow over during Fall. Setting this to true will reverse it, so that more biomes snow over in the Spring compared to Fall. | false +| isSeasonMessingCrops | Flag that determines if the seasons should change the default growth rate | true +| isSeasonMessingBonemeal | Flag that determines if the seasons should change the default bonemeal behavior | false +| doCropsGrowNormallyUnderground | Flag that determines if crops underground should have default behavior. Underground is considered to be sky light level of 0. | false +| doAnimalsBreedInWinter | Flag that determines if animals should be able to breed during the winter | true +| notifyCompat | Flag that determines if a message should be sent when a mod has a compatibility addon and you do not have it installed | true +| debugCommandEnabled | Only useful in development environments | false + +## Crop Growth + +Crops will grow at **different speeds** depending on the current season. + +

+ +

+ +Each **individual crop** will have a **pre-configured growth speed** for one of the four seasons, this is controlled by a datapack and can be changed by the user if they want. + +

+ +

+ +Please refer to online tutorials on **how to make a datapack**. Make sure that your `pack_format` is of the correct version for your particular Minecraft Version. If you are lost, there is an example datapack found in the **pinned messages** of the Discord channel. ## License Distributed under the Mozilla Public License 2.0. See `LICENSE` for more information. diff --git a/src/main/java/io/github/lucaargolo/seasons/FabricSeasons.java b/src/main/java/io/github/lucaargolo/seasons/FabricSeasons.java index 1bbed9f..7087218 100644 --- a/src/main/java/io/github/lucaargolo/seasons/FabricSeasons.java +++ b/src/main/java/io/github/lucaargolo/seasons/FabricSeasons.java @@ -152,38 +152,50 @@ public static ReplacedMeltablesState getReplacedMeltablesState(ServerWorld world } public static long getTimeToNextSeason(World world) { - return getTimeToNextSeason(world, false); - } - - public static long getTimeToNextSeason(World world, boolean ignoreDimension) { + long springLength = CONFIG.getSpringLength(); + long summerLength = CONFIG.getSummerLength(); + long fallLength = CONFIG.getFallLength(); + long winterLength = CONFIG.getWinterLength(); RegistryKey dimension = world.getRegistryKey(); - if ((ignoreDimension || CONFIG.isValidInDimension(dimension)) && !CONFIG.isSeasonLocked()) { + if (CONFIG.isValidInDimension(dimension) && !CONFIG.isSeasonLocked()) { if(CONFIG.isSeasonTiedWithSystemTime()) { return getTimeToNextSystemSeason() * 24000; } - long springTime = world.getTimeOfDay() % CONFIG.getYearLength(); - long summerTime = springTime - CONFIG.getSpringLength(); - long fallTime = summerTime - CONFIG.getSummerLength(); - long winterTime = fallTime - CONFIG.getFallLength(); - - long seasonTime = switch (getCurrentSeason(world)) { - case SPRING -> springTime; - case SUMMER -> summerTime; - case FALL -> fallTime; - case WINTER -> winterTime; + + Season currentSeason = getCurrentSeason(world); + + int[] seasonLengthArray = new int[]{springLength, summerLength, fallLength, winterLength}; + Season[] seasonArray = new Season[]{Season.SPRING, Season.SUMMER, Season.FALL, Season.WINTER}; + + int startSeasonIndex = switch (CONFIG.getStartingSeason()) { + case SPRING -> 0; + case SUMMER -> 1; + case FALL -> 2; + case WINTER -> 3; }; - return getCurrentSeason(world).getSeasonLength() - seasonTime; + + long season1LimitYTD = seasonLengthArray[startSeasonIndex]; + long season2LimitYTD = season1LimitYTD + seasonLengthArray[(startSeasonIndex + 1) % 4]; + long season3LimitYTD = season2LimitYTD + seasonLengthArray[(startSeasonIndex + 2) % 4]; + long yearLength = season3LimitYTD + seasonLengthArray[(startSeasonIndex + 3) % 4]; + long timeOfYear = world.getTimeOfDay() % yearLength; + + if(currentSeason == seasonArray[startSeasonIndex]) { + return season1LimitYTD - timeOfYear; + } else if(currentSeason == seasonArray[(startSeasonIndex + 1) % 4]) { + return season2LimitYTD - timeOfYear; + } else if (currentSeason == seasonArray[(startSeasonIndex + 2) % 4]) { + return season3LimitYTD - timeOfYear; + } else if (currentSeason == seasonArray[(startSeasonIndex + 3) % 4]) { + return yearLength - timeOfYear; + } } return Long.MAX_VALUE; } - public static Season getNextSeason(World world) { - return getNextSeason(world, false); - } - - public static Season getNextSeason(World world, boolean ignoreDimension) { + public static Season getNextSeason(World world, Season currentSeason) { RegistryKey dimension = world.getRegistryKey(); - if (ignoreDimension || CONFIG.isValidInDimension(dimension)) { + if (CONFIG.isValidInDimension(dimension)) { if(CONFIG.isSeasonLocked()) { return CONFIG.getLockedSeason(); } @@ -191,65 +203,53 @@ public static Season getNextSeason(World world, boolean ignoreDimension) { return getCurrentSystemSeason().getNext(); } - long springTime = world.getTimeOfDay() % CONFIG.getYearLength(); - long summerTime = springTime - CONFIG.getSpringLength(); - long fallTime = summerTime - CONFIG.getSummerLength(); - long winterTime = fallTime - CONFIG.getFallLength(); - - long seasonTime = switch (getCurrentSeason(world)) { - case SPRING -> CONFIG.getSpringLength() - springTime; - case SUMMER -> CONFIG.getSummerLength() - summerTime; - case FALL -> CONFIG.getFallLength() - fallTime; - case WINTER -> CONFIG.getWinterLength() - winterTime; + return switch (getCurrentSeason(world)) { + case SPRING -> Season.SUMMER; + case SUMMER -> Season.FALL; + case FALL -> Season.WINTER; + case WINTER -> Season.SPRING; }; - - long worldTime = world.getTimeOfDay() + seasonTime; - - springTime = worldTime % CONFIG.getYearLength(); - summerTime = springTime - CONFIG.getSpringLength(); - fallTime = summerTime - CONFIG.getSummerLength(); - winterTime = fallTime - CONFIG.getFallLength(); - - if(winterTime >= 0 && CONFIG.getWinterLength() > 0) { - return Season.WINTER; - }else if(fallTime >= 0 && CONFIG.getFallLength() > 0) { - return Season.FALL; - }else if(summerTime >= 0 && CONFIG.getSummerLength() > 0) { - return Season.SUMMER; - }else if(springTime >= 0 && CONFIG.getSpringLength() > 0) { - return Season.SPRING; - } } return Season.SPRING; } public static Season getCurrentSeason(World world) { - return getCurrentSeason(world, false); - } - - public static Season getCurrentSeason(World world, boolean ignoreDimension) { + long springLength = CONFIG.getSpringLength(); + long summerLength = CONFIG.getSummerLength(); + long fallLength = CONFIG.getFallLength(); + long winterLength = CONFIG.getWinterLength(); RegistryKey dimension = world.getRegistryKey(); - if (ignoreDimension || CONFIG.isValidInDimension(dimension)) { + if (CONFIG.isValidInDimension(dimension)) { if(CONFIG.isSeasonLocked()) { return CONFIG.getLockedSeason(); - } - if(CONFIG.isSeasonTiedWithSystemTime()) { + }else if(CONFIG.isSeasonTiedWithSystemTime()) { return getCurrentSystemSeason(); - } - - long springTime = world.getTimeOfDay() % CONFIG.getYearLength(); - long summerTime = springTime - CONFIG.getSpringLength(); - long fallTime = summerTime - CONFIG.getSummerLength(); - long winterTime = fallTime - CONFIG.getFallLength(); - - if(winterTime >= 0 && CONFIG.getWinterLength() > 0) { - return Season.WINTER; - }else if(fallTime >= 0 && CONFIG.getFallLength() > 0) { - return Season.FALL; - }else if(summerTime >= 0 && CONFIG.getSummerLength() > 0) { - return Season.SUMMER; - }else if(springTime >= 0 && CONFIG.getSpringLength() > 0) { - return Season.SPRING; + }else if(CONFIG.isValidStartingSeason() && springLength >= 0 && summerLength >= 0 && fallLength >= 0 && winterLength >= 0) { + int[] seasonLengthArray = new int[]{springLength, summerLength, fallLength, winterLength}; + Season[] seasonArray = new Season[]{Season.SPRING, Season.SUMMER, Season.FALL, Season.WINTER}; + + int startSeasonIndex = switch (CONFIG.getStartingSeason()) { + case SPRING -> 0; + case SUMMER -> 1; + case FALL -> 2; + case WINTER -> 3; + }; + + long season1LimitYTD = seasonLengthArray[startSeasonIndex]; + long season2LimitYTD = season1LimitYTD + seasonLengthArray[(startSeasonIndex + 1) % 4]; + long season3LimitYTD = season2LimitYTD + seasonLengthArray[(startSeasonIndex + 2) % 4]; + long yearLength = season3LimitYTD + seasonLengthArray[(startSeasonIndex + 3) % 4]; + long timeOfYear = world.getTimeOfDay() % yearLength; + + if(timeOfYear < season1LimitYTD) { + return seasonArray[startSeasonIndex]; + } else if(timeOfYear < season2LimitYTD) { + return seasonArray[(startSeasonIndex + 1) % 4]; + } else if (timeOfYear < season3LimitYTD) { + return seasonArray[(startSeasonIndex + 2) % 4]; + } else if (timeOfYear < yearLength) { + return seasonArray[(startSeasonIndex + 3) % 4]; + } } } return Season.SPRING; diff --git a/src/main/java/io/github/lucaargolo/seasons/commands/SeasonCommand.java b/src/main/java/io/github/lucaargolo/seasons/commands/SeasonCommand.java index 115000c..2a16c0e 100644 --- a/src/main/java/io/github/lucaargolo/seasons/commands/SeasonCommand.java +++ b/src/main/java/io/github/lucaargolo/seasons/commands/SeasonCommand.java @@ -16,23 +16,55 @@ public static void register(CommandDispatcher dispatcher) { dispatcher.register(CommandManager.literal("season") .then(CommandManager.literal("set").requires((source) -> source.hasPermissionLevel(2)) .then(CommandManager.literal("spring") - .executes(context -> TimeCommand.executeSet(context.getSource(), 0)) + .executes( + context -> TimeCommand.executeSet(context.getSource(), + switch(FabricSeasons.CONFIG.getStartingSeason()) { + case SPRING -> 0; + case WINTER -> FabricSeasons.CONFIG.getWinterLength(); + case FALL -> FabricSeasons.CONFIG.getFallLength() + FabricSeasons.CONFIG.getWinterLength(); + case SUMMER -> FabricSeasons.CONFIG.getSummerLength() + FabricSeasons.CONFIG.getFallLength() + FabricSeasons.CONFIG.getWinterLength(); + } + )) ) .then(CommandManager.literal("summer") - .executes(context -> TimeCommand.executeSet(context.getSource(), FabricSeasons.CONFIG.getSpringLength())) + .executes(context -> TimeCommand.executeSet( + context.getSource(), + switch(FabricSeasons.CONFIG.getStartingSeason()) { + case SUMMER -> 0; + case SPRING -> FabricSeasons.CONFIG.getSpringLength(); + case WINTER -> FabricSeasons.CONFIG.getWinterLength() + FabricSeasons.CONFIG.getSpringLength(); + case FALL -> FabricSeasons.CONFIG.getFallLength() + FabricSeasons.CONFIG.getWinterLength() + FabricSeasons.CONFIG.getSpringLength(); + } + )) ) .then(CommandManager.literal("fall") - .executes(context -> TimeCommand.executeSet(context.getSource(), FabricSeasons.CONFIG.getSpringLength() + FabricSeasons.CONFIG.getSummerLength())) + .executes(context -> TimeCommand.executeSet( + context.getSource(), + switch(FabricSeasons.CONFIG.getStartingSeason()) { + case FALL -> 0; + case SUMMER -> FabricSeasons.CONFIG.getSummerLength(); + case SPRING -> FabricSeasons.CONFIG.getSpringLength() + FabricSeasons.CONFIG.getSummerLength(); + case WINTER -> FabricSeasons.CONFIG.getWinterLength() + FabricSeasons.CONFIG.getSpringLength() + FabricSeasons.CONFIG.getSummerLength(); + } + )) ) .then(CommandManager.literal("winter") - .executes(context -> TimeCommand.executeSet(context.getSource(), FabricSeasons.CONFIG.getSpringLength() + FabricSeasons.CONFIG.getSummerLength() + FabricSeasons.CONFIG.getFallLength())) + .executes(context -> TimeCommand.executeSet( + context.getSource(), + switch(FabricSeasons.CONFIG.getStartingSeason()) { + case WINTER -> 0; + case FALL -> FabricSeasons.CONFIG.getFallLength(); + case SUMMER -> FabricSeasons.CONFIG.getSummerLength() + FabricSeasons.CONFIG.getFallLength(); + case SPRING -> FabricSeasons.CONFIG.getSpringLength() + FabricSeasons.CONFIG.getSummerLength() + FabricSeasons.CONFIG.getFallLength(); + } + )) ) ) .then(CommandManager.literal("query") .executes(context -> { World world = context.getSource().getWorld(); Season currentSeason = FabricSeasons.getCurrentSeason(world); - Season nextSeason = FabricSeasons.getNextSeason(world); + Season nextSeason = FabricSeasons.getNextSeason(world, currentSeason); long ticksLeft = FabricSeasons.getTimeToNextSeason(world); context.getSource().sendFeedback(() -> Text.translatable("commands.seasons.query_1", Text.translatable(currentSeason.getTranslationKey()).formatted(currentSeason.getFormatting()) diff --git a/src/main/java/io/github/lucaargolo/seasons/utils/ModConfig.java b/src/main/java/io/github/lucaargolo/seasons/utils/ModConfig.java index dac0107..45aac65 100644 --- a/src/main/java/io/github/lucaargolo/seasons/utils/ModConfig.java +++ b/src/main/java/io/github/lucaargolo/seasons/utils/ModConfig.java @@ -22,6 +22,8 @@ private static class SeasonLength { } + private Season startingSeason = Season.SPRING; + private SeasonLength seasonLength = new SeasonLength(); private SeasonLock seasonLock = new SeasonLock(); @@ -151,6 +153,20 @@ public Season getLockedSeason() { return seasonLock.lockedSeason; } + public Season getStartingSeason() { + return startingSeason; + } + + public boolean isValidStartingSeason() { + return switch(startingSeason) { + case SPRING -> true; + case SUMMER -> true; + case FALL -> true; + case WINTER -> true; + default -> false; + }; + } + public boolean isValidInDimension(RegistryKey dimension) { return dimensionAllowlist.contains(dimension.getValue().toString()); } From 2fdb871f62d019d229d6dc71042b671834633c01 Mon Sep 17 00:00:00 2001 From: MTaningco Date: Mon, 30 Sep 2024 12:29:51 -0700 Subject: [PATCH 2/2] Fix minor error. Bump to 2.4.2-BETA. --- gradle.properties | 2 +- src/main/java/io/github/lucaargolo/seasons/FabricSeasons.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/gradle.properties b/gradle.properties index 554a8a8..0d7c90a 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,7 +9,7 @@ modrinth_version=2.8.7 github_api_version=1.314 # Mod Properties -mod_version=2.4.1-BETA+1.20 +mod_version=2.4.2-BETA+1.20 maven_group=io.github.lucaargolo # Fabric Properties diff --git a/src/main/java/io/github/lucaargolo/seasons/FabricSeasons.java b/src/main/java/io/github/lucaargolo/seasons/FabricSeasons.java index 7087218..bae832d 100644 --- a/src/main/java/io/github/lucaargolo/seasons/FabricSeasons.java +++ b/src/main/java/io/github/lucaargolo/seasons/FabricSeasons.java @@ -164,7 +164,7 @@ public static long getTimeToNextSeason(World world) { Season currentSeason = getCurrentSeason(world); - int[] seasonLengthArray = new int[]{springLength, summerLength, fallLength, winterLength}; + long[] seasonLengthArray = new long[]{springLength, summerLength, fallLength, winterLength}; Season[] seasonArray = new Season[]{Season.SPRING, Season.SUMMER, Season.FALL, Season.WINTER}; int startSeasonIndex = switch (CONFIG.getStartingSeason()) { @@ -225,7 +225,7 @@ public static Season getCurrentSeason(World world) { }else if(CONFIG.isSeasonTiedWithSystemTime()) { return getCurrentSystemSeason(); }else if(CONFIG.isValidStartingSeason() && springLength >= 0 && summerLength >= 0 && fallLength >= 0 && winterLength >= 0) { - int[] seasonLengthArray = new int[]{springLength, summerLength, fallLength, winterLength}; + long[] seasonLengthArray = new long[]{springLength, summerLength, fallLength, winterLength}; Season[] seasonArray = new Season[]{Season.SPRING, Season.SUMMER, Season.FALL, Season.WINTER}; int startSeasonIndex = switch (CONFIG.getStartingSeason()) {