From 25ae612a305f6d2e873d5f4e0e5f15a42657d8a0 Mon Sep 17 00:00:00 2001 From: yuesha-yc Date: Sun, 8 Dec 2024 07:48:31 -0800 Subject: [PATCH] Introduce data-driven plant temperature part 3 --- .../content/climate/WorldTemperature.java | 9 +- .../content/climate/data/PlantTempData.java | 8 +- .../climate/event/ClimateCommonEvents.java | 5 +- .../climate/tooltips/PlantTempStats.java | 144 ++++++++---------- .../frostedheart/util/FHTooltipHelper.java | 25 +++ .../assets/frostedheart/lang/zh_cn.json | 8 +- .../temperature/plant/beetroots.json | 4 +- .../temperature/plant/rye_block.json | 4 +- .../frostedheart/temperature/plant/wheat.json | 2 +- .../temperature/plant/white_turnip_block.json | 4 +- .../plant/wolfberry_bush_block.json | 4 +- 11 files changed, 116 insertions(+), 101 deletions(-) diff --git a/src/main/java/com/teammoeg/frostedheart/content/climate/WorldTemperature.java b/src/main/java/com/teammoeg/frostedheart/content/climate/WorldTemperature.java index 11d8d832f..f860c8f77 100644 --- a/src/main/java/com/teammoeg/frostedheart/content/climate/WorldTemperature.java +++ b/src/main/java/com/teammoeg/frostedheart/content/climate/WorldTemperature.java @@ -34,8 +34,11 @@ import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.BonemealableBlock; import net.minecraft.world.level.levelgen.Heightmap; +import net.minecraftforge.common.IPlantable; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import javax.annotation.Nonnull; + /** * World Temperature API on the server side. * @@ -367,11 +370,13 @@ public static int wind(LevelReader w) { return 0; } + @Nonnull public static PlantTempData getPlantDataWithDefault(Block block) { PlantTempData data = FHDataManager.getPlantData(block); - if (data == null && block instanceof BonemealableBlock) { + // We can't really do any instanceof check here, since so many potential blocks + // may be invoked with the crop event. + if (data == null) return new PlantTempData(); - } return data; } diff --git a/src/main/java/com/teammoeg/frostedheart/content/climate/data/PlantTempData.java b/src/main/java/com/teammoeg/frostedheart/content/climate/data/PlantTempData.java index c3a41dcd6..105ba3b2f 100644 --- a/src/main/java/com/teammoeg/frostedheart/content/climate/data/PlantTempData.java +++ b/src/main/java/com/teammoeg/frostedheart/content/climate/data/PlantTempData.java @@ -30,16 +30,16 @@ public class PlantTempData { public static final float DEFAULT_BONEMEAL_TEMP = 10; public static final float DEFAULT_GROW_TEMP = 0; public static final float DEFAULT_SURVIVE_TEMP = -10; - public static final float DEFAULT_BONEMEAL_MAX_TEMP = 30; - public static final float DEFAULT_GROW_MAX_TEMP = 50; - public static final float DEFAULT_SURVIVE_MAX_TEMP = 50; + public static final float DEFAULT_BONEMEAL_MAX_TEMP = 40; + public static final float DEFAULT_GROW_MAX_TEMP = 40; + public static final float DEFAULT_SURVIVE_MAX_TEMP = 40; public static final boolean DEFAULT_SNOW_VULNERABLE = true; public static final boolean DEFAULT_BLIZZARD_VULNERABLE = true; public static final MapCodec CODEC=RecordCodecBuilder.mapCodec(t->t.group( // min CodecUtil.defaultValue(Codec.FLOAT,DEFAULT_BONEMEAL_TEMP).fieldOf("min_fertilize").forGetter(o->o.minFertilize), - CodecUtil.defaultValue(Codec.FLOAT,DEFAULT_BONEMEAL_TEMP).fieldOf("min_grow").forGetter(o->o.minGrow), + CodecUtil.defaultValue(Codec.FLOAT,DEFAULT_GROW_TEMP).fieldOf("min_grow").forGetter(o->o.minGrow), CodecUtil.defaultValue(Codec.FLOAT,DEFAULT_SURVIVE_TEMP).fieldOf("min_survive").forGetter(o->o.minSurvive), // max CodecUtil.defaultValue(Codec.FLOAT,DEFAULT_BONEMEAL_MAX_TEMP).fieldOf("max_fertilize").forGetter(o->o.maxFertilize), diff --git a/src/main/java/com/teammoeg/frostedheart/content/climate/event/ClimateCommonEvents.java b/src/main/java/com/teammoeg/frostedheart/content/climate/event/ClimateCommonEvents.java index 8d9dcab7c..64db15c8b 100644 --- a/src/main/java/com/teammoeg/frostedheart/content/climate/event/ClimateCommonEvents.java +++ b/src/main/java/com/teammoeg/frostedheart/content/climate/event/ClimateCommonEvents.java @@ -180,7 +180,10 @@ public static void beforeCropGrow(BlockEvent.CropGrowEvent.Pre event) { event.setResult(Event.Result.DENY); } if (status.willDie()) { - FHUtils.setToAirPreserveFluid(level, event.getPos()); + if (level.getBlockState(pos.below()).is(Blocks.FARMLAND)) { + level.setBlock(pos.below(), Blocks.DIRT.defaultBlockState(), 2); + } + level.setBlock(pos, Blocks.DEAD_BUSH.defaultBlockState(), 2); event.setResult(Event.Result.DENY); } } diff --git a/src/main/java/com/teammoeg/frostedheart/content/climate/tooltips/PlantTempStats.java b/src/main/java/com/teammoeg/frostedheart/content/climate/tooltips/PlantTempStats.java index 38b3ec54e..4d4c015bc 100644 --- a/src/main/java/com/teammoeg/frostedheart/content/climate/tooltips/PlantTempStats.java +++ b/src/main/java/com/teammoeg/frostedheart/content/climate/tooltips/PlantTempStats.java @@ -7,6 +7,7 @@ import com.teammoeg.frostedheart.content.climate.data.PlantTempData; import com.teammoeg.frostedheart.infrastructure.data.FHDataManager; import com.teammoeg.frostedheart.util.FHTooltipHelper; +import com.teammoeg.frostedheart.util.MathUtils; import com.teammoeg.frostedheart.util.lang.Components; import com.teammoeg.frostedheart.util.lang.Lang; import com.teammoeg.frostedheart.util.lang.LangBuilder; @@ -18,6 +19,8 @@ import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.BonemealableBlock; +import net.minecraftforge.common.IPlantable; import net.minecraftforge.event.entity.player.ItemTooltipEvent; import org.jetbrains.annotations.Nullable; @@ -34,7 +37,13 @@ public PlantTempStats(Block block) { public static PlantTempStats create(Item item) { if (item instanceof BlockItem blockItem) { Block block = blockItem.getBlock(); - return new PlantTempStats(block); + // TODO: I don't know better way to do this + // In general, BonemeableBlock is growable + // IPlantable is plantable + // but there are exceptions... + if (block instanceof BonemealableBlock || block instanceof IPlantable) { + return new PlantTempStats(block); + } } return null; } @@ -50,94 +59,67 @@ public void modify(ItemTooltipEvent context) { } + public static LangBuilder getTempProgressBar(float min, float max) { + // remap from -30 to 30 to 0 to 6 + int low = Mth.ceil(Mth.clampedMap(min, -30, 30, 0, 6)); + int high = Mth.ceil(Mth.clampedMap(max, -30, 30, 0, 6)); + + // bar + String s = FHTooltipHelper.makeProgressBarInterval(6, low, high); + String s1 = s.substring(0, 3); + String s2 = s.substring(3); + + LangBuilder builder = Lang.builder() + .add(Lang.text(TemperatureDisplayHelper.toTemperatureFloatString(min)) + .style(min <= 0 ? ChatFormatting.AQUA : ChatFormatting.GOLD)) + .add(Lang.text(" - ").style(ChatFormatting.GRAY)) + .add(Lang.text(TemperatureDisplayHelper.toTemperatureFloatString(max)) + .style(max <= 0 ? ChatFormatting.AQUA : ChatFormatting.GOLD)) + .add(Lang.text(" ")) + .add(Lang.text(s1).style(ChatFormatting.AQUA)) + .add(Lang.text(s2).style(ChatFormatting.GOLD)); + + return builder; + } public static List getStats(Block block, ItemStack stack, Player player) { List list = new ArrayList<>(); PlantTempData data = WorldTemperature.getPlantDataWithDefault(block); - if (data != null) { - // maps 0-10 to 0-3 - int barlength = 3; - float barfactor = 0.1F; - - float minSurviveTemp = (Math.round(data.getMinSurvive() * 10)) / 10.0F; - float maxSurviveTemp = (Math.round(data.getMaxSurvive() * 10)) / 10.0F; - Lang.translate("tooltip", "temp.plant.survive").style(ChatFormatting.GRAY).addTo(list); - int maxProgress = Mth.ceil(Mth.clamp(Math.abs(maxSurviveTemp) * barfactor, 0, barlength)); - int minProgress = Mth.ceil(Mth.clamp(Math.abs(minSurviveTemp) * barfactor, 0, barlength)); - - LangBuilder builder = Lang.builder() - .add(Lang.text(TemperatureDisplayHelper.toTemperatureFloatString(minSurviveTemp)) - .style(minSurviveTemp <= 0 ? ChatFormatting.AQUA : ChatFormatting.GOLD)) - .add(Lang.text(" - ").style(ChatFormatting.GRAY)) - .add(Lang.text(TemperatureDisplayHelper.toTemperatureFloatString(maxSurviveTemp)) - .style(maxSurviveTemp <= 0 ? ChatFormatting.AQUA : ChatFormatting.GOLD)) - .add(Lang.text(" ")) - .add(Lang.text(FHTooltipHelper.makeProgressBarReversed(barlength, minProgress)) - .style(minSurviveTemp <= 0 ? ChatFormatting.AQUA : ChatFormatting.GOLD)) - .add(Lang.text(FHTooltipHelper.makeProgressBar(barlength, maxProgress)) - .style(maxSurviveTemp <= 0 ? ChatFormatting.AQUA : ChatFormatting.GOLD)); - builder.addTo(list); - - float minGrowTemp = (Math.round(data.getMinGrow() * 10)) / 10.0F; - float maxGrowTemp = (Math.round(data.getMaxGrow() * 10)) / 10.0F; - Lang.translate("tooltip", "temp.plant.grow").style(ChatFormatting.GRAY).addTo(list); - maxProgress = Mth.ceil(Mth.clamp(Math.abs(maxGrowTemp) * barfactor, 0, barlength)); - minProgress = Mth.ceil(Mth.clamp(Math.abs(minGrowTemp) * barfactor, 0, barlength)); - builder = Lang.builder() - .add(Lang.text(TemperatureDisplayHelper.toTemperatureFloatString(minGrowTemp)) - .style(minGrowTemp <= 0 ? ChatFormatting.AQUA : ChatFormatting.GOLD)) - .add(Lang.text(" - ").style(ChatFormatting.GRAY)) - .add(Lang.text(TemperatureDisplayHelper.toTemperatureFloatString(maxGrowTemp)) - .style(maxGrowTemp <= 0 ? ChatFormatting.AQUA : ChatFormatting.GOLD)) - .add(Lang.text(" ")) - .add(Lang.text(FHTooltipHelper.makeProgressBarReversed(barlength, minProgress)) - .style(minGrowTemp <= 0 ? ChatFormatting.AQUA : ChatFormatting.GOLD)) - .add(Lang.text(FHTooltipHelper.makeProgressBar(barlength, maxProgress)) - .style(maxGrowTemp <= 0 ? ChatFormatting.AQUA : ChatFormatting.GOLD)); - builder.addTo(list); - - float minFertilizeTemp = (Math.round(data.getMinFertilize() * 10)) / 10.0F; - float maxFertilizeTemp = (Math.round(data.getMaxFertilize() * 10)) / 10.0F; + boolean bonemealable = block instanceof BonemealableBlock; + + Lang.translate("tooltip", "temp.plant.survive").style(ChatFormatting.GRAY).addTo(list); + getTempProgressBar(data.getMinSurvive(), data.getMaxSurvive()).addTo(list); + + Lang.translate("tooltip", "temp.plant.grow").style(ChatFormatting.GRAY).addTo(list); + getTempProgressBar(data.getMinGrow(), data.getMaxGrow()).addTo(list); + + if (bonemealable) { Lang.translate("tooltip", "temp.plant.fertilize").style(ChatFormatting.GRAY).addTo(list); - maxProgress = Mth.ceil(Mth.clamp(Math.abs(maxFertilizeTemp) * barfactor, 0, barlength)); - minProgress = Mth.ceil(Mth.clamp(Math.abs(minFertilizeTemp) * barfactor, 0, barlength)); - builder = Lang.builder() - .add(Lang.text(TemperatureDisplayHelper.toTemperatureFloatString(minFertilizeTemp)) - .style(minFertilizeTemp <= 0 ? ChatFormatting.AQUA : ChatFormatting.GOLD)) - .add(Lang.text(" - ").style(ChatFormatting.GRAY)) - .add(Lang.text(TemperatureDisplayHelper.toTemperatureFloatString(maxFertilizeTemp)) - .style(maxFertilizeTemp <= 0 ? ChatFormatting.AQUA : ChatFormatting.GOLD)) - .add(Lang.text(" ")) - .add(Lang.text(FHTooltipHelper.makeProgressBarReversed(barlength, minProgress)) - .style(minFertilizeTemp <= 0 ? ChatFormatting.AQUA : ChatFormatting.GOLD)) - .add(Lang.text(FHTooltipHelper.makeProgressBar(barlength, maxProgress)) - .style(maxFertilizeTemp <= 0 ? ChatFormatting.AQUA : ChatFormatting.GOLD)); - builder.addTo(list); - - - boolean vulnerableSnow = data.isSnowVulnerable(); - if (vulnerableSnow) { - Lang.translate("tooltip", "temp.plant.snow_vulnerable") - .style(ChatFormatting.RED) - .addTo(list); - } else { - Lang.translate("tooltip", "temp.plant.snow_resistant") - .style(ChatFormatting.GREEN) - .addTo(list); - } + getTempProgressBar(data.getMinFertilize(), data.getMaxFertilize()).addTo(list); + } - boolean vulnerableBlizzard = data.isBlizzardVulnerable(); - if (vulnerableBlizzard) { - Lang.translate("tooltip", "temp.plant.blizzard_vulnerable") - .style(ChatFormatting.RED) - .addTo(list); - } else { - Lang.translate("tooltip", "temp.plant.blizzard_resistant") - .style(ChatFormatting.GREEN) - .addTo(list); - } + boolean vulnerableSnow = data.isSnowVulnerable(); + if (vulnerableSnow) { + Lang.translate("tooltip", "temp.plant.snow_vulnerable") + .style(ChatFormatting.RED) + .addTo(list); + } else { + Lang.translate("tooltip", "temp.plant.snow_resistant") + .style(ChatFormatting.GREEN) + .addTo(list); + } + boolean vulnerableBlizzard = data.isBlizzardVulnerable(); + if (vulnerableBlizzard) { + Lang.translate("tooltip", "temp.plant.blizzard_vulnerable") + .style(ChatFormatting.RED) + .addTo(list); + } else { + Lang.translate("tooltip", "temp.plant.blizzard_resistant") + .style(ChatFormatting.GREEN) + .addTo(list); } + return list; } } diff --git a/src/main/java/com/teammoeg/frostedheart/util/FHTooltipHelper.java b/src/main/java/com/teammoeg/frostedheart/util/FHTooltipHelper.java index 7572b315d..6f47fedb7 100644 --- a/src/main/java/com/teammoeg/frostedheart/util/FHTooltipHelper.java +++ b/src/main/java/com/teammoeg/frostedheart/util/FHTooltipHelper.java @@ -21,4 +21,29 @@ public static String makeProgressBarReversed(int length, int filledLength) { bar += "\u2588"; return bar; } + + // make progress bar, filling from left to right, but with a starting offset, left of which is not filled + public static String makeProgressBarOffset(int length, int filledLength, int offset) { + String bar = ""; + int emptySpaces = length - filledLength - offset; + for (int i = 0; i < offset; i++) + bar += "\u2592"; + for (int i = 0; i < filledLength; i++) + bar += "\u2588"; + for (int i = 0; i < emptySpaces; i++) + bar += "\u2592"; + return bar; + } + + // use the method above to take two interval bounds [min, max] and a bar length, and fill the bar accordingly + /** + * Make a progress bar with a given length, filled from left to right, with interval bounds [min, max] + * @param length should be greater than max + * @param min the lower bound of the interval + * @param max the upper bound of the interval + * @return a string representing the progress bar + */ + public static String makeProgressBarInterval(int length, int min, int max) { + return makeProgressBarOffset(length, max - min, min); + } } diff --git a/src/main/resources/assets/frostedheart/lang/zh_cn.json b/src/main/resources/assets/frostedheart/lang/zh_cn.json index d6326e32b..12f63d2fa 100644 --- a/src/main/resources/assets/frostedheart/lang/zh_cn.json +++ b/src/main/resources/assets/frostedheart/lang/zh_cn.json @@ -896,12 +896,12 @@ "item.frostedheart.yellow_advanced_thermos": "Yellow Advanced Thermos", "item.frostedheart.yellow_thermos": "Yellow Thermos", "tooltip.frostedheart.temp.equipment": "When Equipped: ", - "tooltip.frostedheart.temp.plant.blizzard_vulnerable": "无法抵御暴风雪", + "tooltip.frostedheart.temp.plant.blizzard_vulnerable": "无法抵御暴风雪(需要遮蔽)", "tooltip.frostedheart.temp.plant.fertilize": "可施肥于:", - "tooltip.frostedheart.temp.plant.grow": "可生长区于:", - "tooltip.frostedheart.temp.plant.snow_vulnerable": "无法抵御雪天", + "tooltip.frostedheart.temp.plant.grow": "可生长于:", + "tooltip.frostedheart.temp.plant.snow_vulnerable": "无法抵御降雪(需要遮蔽)", "tooltip.frostedheart.temp.plant.survive": "可存活于:", - "tooltip.frostedheart.temp.plant.snow_resistant": "可抵御雪天", + "tooltip.frostedheart.temp.plant.snow_resistant": "可抵御降雪", "tooltip.frostedheart.temp.plant.blizzard_resistant": "可抵御暴风雪", "itemGroup.frostedheart.misc": "Frosted Heart: Miscellaneous", "itemGroup.frostedheart.ingredients": "Frosted Heart: Ingredients", diff --git a/src/main/resources/data/frostedheart/temperature/plant/beetroots.json b/src/main/resources/data/frostedheart/temperature/plant/beetroots.json index a95a382ce..14f8e50d6 100644 --- a/src/main/resources/data/frostedheart/temperature/plant/beetroots.json +++ b/src/main/resources/data/frostedheart/temperature/plant/beetroots.json @@ -4,8 +4,8 @@ "min_grow": -20, "min_fertilize": -10, "max_survive": 30, - "max_grow": 20, - "max_fertilize": 10, + "max_grow": 30, + "max_fertilize": 30, "snow_vulnerable": false, "blizzard_vulnerable": true } \ No newline at end of file diff --git a/src/main/resources/data/frostedheart/temperature/plant/rye_block.json b/src/main/resources/data/frostedheart/temperature/plant/rye_block.json index 6f5b5a6bc..557021da1 100644 --- a/src/main/resources/data/frostedheart/temperature/plant/rye_block.json +++ b/src/main/resources/data/frostedheart/temperature/plant/rye_block.json @@ -4,8 +4,8 @@ "min_grow": -20, "min_fertilize": -10, "max_survive": 30, - "max_grow": 20, - "max_fertilize": 10, + "max_grow": 30, + "max_fertilize": 30, "snow_vulnerable": false, "blizzard_vulnerable": true } \ No newline at end of file diff --git a/src/main/resources/data/frostedheart/temperature/plant/wheat.json b/src/main/resources/data/frostedheart/temperature/plant/wheat.json index c786a2299..f92dca202 100644 --- a/src/main/resources/data/frostedheart/temperature/plant/wheat.json +++ b/src/main/resources/data/frostedheart/temperature/plant/wheat.json @@ -5,7 +5,7 @@ "min_fertilize": 20, "max_survive": 40, "max_grow": 30, - "max_fertilize": 20, + "max_fertilize": 30, "snow_vulnerable": true, "blizzard_vulnerable": true } \ No newline at end of file diff --git a/src/main/resources/data/frostedheart/temperature/plant/white_turnip_block.json b/src/main/resources/data/frostedheart/temperature/plant/white_turnip_block.json index 47cc762e8..4b9bfa082 100644 --- a/src/main/resources/data/frostedheart/temperature/plant/white_turnip_block.json +++ b/src/main/resources/data/frostedheart/temperature/plant/white_turnip_block.json @@ -4,8 +4,8 @@ "min_grow": -20, "min_fertilize": -10, "max_survive": 30, - "max_grow": 20, - "max_fertilize": 10, + "max_grow": 30, + "max_fertilize": 30, "snow_vulnerable": false, "blizzard_vulnerable": true } \ No newline at end of file diff --git a/src/main/resources/data/frostedheart/temperature/plant/wolfberry_bush_block.json b/src/main/resources/data/frostedheart/temperature/plant/wolfberry_bush_block.json index 275ef9015..b7b60571a 100644 --- a/src/main/resources/data/frostedheart/temperature/plant/wolfberry_bush_block.json +++ b/src/main/resources/data/frostedheart/temperature/plant/wolfberry_bush_block.json @@ -4,8 +4,8 @@ "min_grow": -20, "min_fertilize": -10, "max_survive": 30, - "max_grow": 20, - "max_fertilize": 10, + "max_grow": 30, + "max_fertilize": 30, "snow_vulnerable": false, "blizzard_vulnerable": true } \ No newline at end of file