diff --git a/src/main/java/com/portingdeadmods/nautec/NTConfig.java b/src/main/java/com/portingdeadmods/nautec/NTConfig.java index e11c0062..1b137c5f 100644 --- a/src/main/java/com/portingdeadmods/nautec/NTConfig.java +++ b/src/main/java/com/portingdeadmods/nautec/NTConfig.java @@ -76,6 +76,27 @@ public final class NTConfig { .comment("The y depth the fisher checks for water") .defineInRange("fisherDepth", 2, 1, Integer.MAX_VALUE); + // Biology + private static final ModConfigSpec.DoubleValue BACTERIA_GROWTH_RATE_CAP = BUILDER + .comment("The maximum rate at which bacteria can grow") + .defineInRange("bacteriaGrowthRateCap", 5, 0, Float.MAX_VALUE); + + private static final ModConfigSpec.DoubleValue BACTERIA_PRODUCTION_RATE_CAP = BUILDER + .comment("The maximum rate at which bacteria can produce") + .defineInRange("bacteriaProductionRateCap", 2, 0, Float.MAX_VALUE); + + private static final ModConfigSpec.DoubleValue BACTERIA_MUTATION_RESISTANCE_CAP = BUILDER + .comment("The maximum rate at which bacteria can resist mutation") + .defineInRange("bacteriaMutationResistanceCap", 1, 0, Float.MAX_VALUE); + + private static final ModConfigSpec.DoubleValue BACTERIA_COLONY_SIZE_CAP = BUILDER + .comment("The maximum size a bacteria colony can grow to") + .defineInRange("bacteriaColonySizeCap", 100d, 0, Float.MAX_VALUE); + + private static final ModConfigSpec.IntValue BACTERIA_LIFESPAN_CAP = BUILDER + .comment("The maximum lifespan of a bacteria colony") + .defineInRange("bacteriaLifespanCap", 24000, 0, Integer.MAX_VALUE); + static final ModConfigSpec SPEC = BUILDER.build(); public static int kelpHeight; @@ -102,6 +123,13 @@ public final class NTConfig { public static int fisherRunDuration; public static int fisherRadius; public static int fisherDepth; + + public static float bacteriaGrowthRateCap; + public static float bacteriaProductionRateCap; + public static float bacteriaMutationResistanceCap; + public static float bacteriaColonySizeCap; + public static int bacteriaLifespanCap; + @SubscribeEvent static void onLoad(final ModConfigEvent event) { kelpHeight = KELP_HEIGHT.get(); @@ -129,6 +157,12 @@ static void onLoad(final ModConfigEvent event) { fisherRunDuration = FISHER_DURATION.getAsInt(); fisherDepth = FISHER_DEPTH.getAsInt(); fisherRadius = FISHER_RADIUS.getAsInt(); + + bacteriaGrowthRateCap = (float) BACTERIA_GROWTH_RATE_CAP.getAsDouble(); + bacteriaProductionRateCap = (float) BACTERIA_PRODUCTION_RATE_CAP.getAsDouble(); + bacteriaMutationResistanceCap = (float) BACTERIA_MUTATION_RESISTANCE_CAP.getAsDouble(); + bacteriaColonySizeCap = (float) BACTERIA_COLONY_SIZE_CAP.getAsDouble(); + bacteriaLifespanCap = BACTERIA_LIFESPAN_CAP.get(); } } diff --git a/src/main/java/com/portingdeadmods/nautec/api/bacteria/BaseBacteriaStats.java b/src/main/java/com/portingdeadmods/nautec/api/bacteria/BaseBacteriaStats.java index a0045bfe..0205d49a 100644 --- a/src/main/java/com/portingdeadmods/nautec/api/bacteria/BaseBacteriaStats.java +++ b/src/main/java/com/portingdeadmods/nautec/api/bacteria/BaseBacteriaStats.java @@ -14,9 +14,22 @@ public interface BaseBacteriaStats { float productionRate(); + float colonySize(); + int lifespan(); int color(); List statsTooltip(); + + // Mutator + BaseBacteriaStats rollGrowthRate(); + BaseBacteriaStats rollMutationResistance(); + BaseBacteriaStats rollProductionRate(); + BaseBacteriaStats rollLifespan(); + BaseBacteriaStats rollStats(); + + // Incubator + BaseBacteriaStats grow(); + BaseBacteriaStats shrink(); } diff --git a/src/main/java/com/portingdeadmods/nautec/content/bacteria/BacteriaStats.java b/src/main/java/com/portingdeadmods/nautec/content/bacteria/BacteriaStats.java index 4b3f3aec..7a2aef01 100644 --- a/src/main/java/com/portingdeadmods/nautec/content/bacteria/BacteriaStats.java +++ b/src/main/java/com/portingdeadmods/nautec/content/bacteria/BacteriaStats.java @@ -3,6 +3,8 @@ import com.mojang.serialization.Codec; import com.mojang.serialization.codecs.RecordCodecBuilder; import com.portingdeadmods.nautec.api.bacteria.BaseBacteriaStats; +import com.portingdeadmods.nautec.utils.ComponentUtils; +import com.portingdeadmods.nautec.utils.RNGUtils; import com.portingdeadmods.nautec.utils.codec.CodecUtils; import net.minecraft.network.RegistryFriendlyByteBuf; import net.minecraft.network.chat.Component; @@ -10,12 +12,15 @@ import net.minecraft.network.codec.StreamCodec; import net.minecraft.world.item.Item; +import static com.portingdeadmods.nautec.NTConfig.*; + import java.util.List; public record BacteriaStats(Item resource, float growthRate, float mutationResistance, float productionRate, + float colonySize, int lifespan, int color) implements BaseBacteriaStats { public static final Codec CODEC = RecordCodecBuilder.create( @@ -24,6 +29,7 @@ public record BacteriaStats(Item resource, Codec.FLOAT.fieldOf("growth_rate").forGetter(BacteriaStats::growthRate), Codec.FLOAT.fieldOf("mutation_resistance").forGetter(BacteriaStats::mutationResistance), Codec.FLOAT.fieldOf("production_rate").forGetter(BacteriaStats::productionRate), + Codec.FLOAT.fieldOf("colony_size").forGetter(BacteriaStats::colonySize), Codec.INT.fieldOf("lifespan").forGetter(BacteriaStats::lifespan), Codec.INT.fieldOf("color").forGetter(BacteriaStats::color) ).apply(instance, BacteriaStats::new) @@ -38,6 +44,8 @@ public record BacteriaStats(Item resource, BacteriaStats::mutationResistance, ByteBufCodecs.FLOAT, BacteriaStats::productionRate, + ByteBufCodecs.FLOAT, + BacteriaStats::colonySize, ByteBufCodecs.INT, BacteriaStats::lifespan, ByteBufCodecs.INT, @@ -48,8 +56,62 @@ public record BacteriaStats(Item resource, @Override public List statsTooltip() { return List.of( - Component.literal("Resource: "+resource.getDefaultInstance().getDisplayName().getString()), - Component.literal("Growth Rate: "+growthRate) + ComponentUtils.stringStatShow("Resource", resource.getDefaultInstance().getDisplayName().getString()), + ComponentUtils.countableStatShow("Growth Rate", growthRate, bacteriaGrowthRateCap), + ComponentUtils.countableStatShow("Mutation Resistance", mutationResistance, bacteriaMutationResistanceCap), + ComponentUtils.countableStatShow("Production Rate", productionRate, bacteriaProductionRateCap), + ComponentUtils.countableStatShow("Colony Size", colonySize, bacteriaColonySizeCap), + ComponentUtils.countableStatShow("Lifespan", lifespan, bacteriaLifespanCap) ); } + + @Override + public BaseBacteriaStats rollGrowthRate() { + float newGR = growthRate + (RNGUtils.floatInRangeOf(growthRate) / (10 * (1 + mutationResistance))); + newGR = Math.min(newGR, bacteriaGrowthRateCap); + + return new BacteriaStats(resource, newGR, mutationResistance, productionRate, colonySize, lifespan, color); + } + + @Override + public BaseBacteriaStats rollMutationResistance() { + float newMR = mutationResistance + RNGUtils.biasedInRange(0, 0.1f, mutationResistance) / 10 * (bacteriaMutationResistanceCap - mutationResistance); + + return new BacteriaStats(resource, growthRate, newMR, productionRate, colonySize, lifespan, color); + } + + @Override + public BaseBacteriaStats rollProductionRate() { + float newPR = productionRate + RNGUtils.floatInRangeOf(productionRate) / 10 * (1 + mutationResistance); + newPR = Math.min(newPR, bacteriaProductionRateCap); + + return new BacteriaStats(resource, growthRate, mutationResistance, newPR, colonySize, lifespan, color); + } + + @Override + public BaseBacteriaStats rollLifespan() { + int newLS = lifespan + (int) (RNGUtils.uniformRandInt(-10, 10) / (1 + mutationResistance)); + newLS = Math.min(newLS, bacteriaLifespanCap); + + return new BacteriaStats(resource, growthRate, mutationResistance, productionRate, colonySize, newLS, color); + } + + @Override + public BaseBacteriaStats rollStats() { + return rollGrowthRate().rollMutationResistance().rollProductionRate().rollLifespan(); + } + + @Override + public BaseBacteriaStats grow() { + float newCS = colonySize + RNGUtils.floatInRangeOf(0, growthRate); + newCS = Math.min(newCS, bacteriaColonySizeCap); + + return new BacteriaStats(resource, growthRate, mutationResistance, productionRate, newCS, lifespan, color); + } + + @Override + public BaseBacteriaStats shrink() { + float newCS = colonySize - colonySize * RNGUtils.uniformRandFloat(25) - 1; + return new BacteriaStats(resource, growthRate, mutationResistance, productionRate, newCS, lifespan, color); + } } diff --git a/src/main/java/com/portingdeadmods/nautec/content/bacteria/SimpleBacteria.java b/src/main/java/com/portingdeadmods/nautec/content/bacteria/SimpleBacteria.java index 804f3893..7dc52751 100644 --- a/src/main/java/com/portingdeadmods/nautec/content/bacteria/SimpleBacteria.java +++ b/src/main/java/com/portingdeadmods/nautec/content/bacteria/SimpleBacteria.java @@ -50,6 +50,7 @@ public static class Builder { private float growthRate; private float mutationResistance; private float productionRate; + private float colonySize; private int lifespan; private int color; @@ -73,6 +74,11 @@ public Builder productionRate(float productionRate) { return this; } + public Builder colonySize(float colonySize) { + this.colonySize = colonySize; + return this; + } + public Builder lifespan(int lifespan) { this.lifespan = lifespan; return this; @@ -84,7 +90,7 @@ public Builder color(int color) { } public Bacteria build(ResourceLocation location) { - return new SimpleBacteria(new BacteriaStats(resource, growthRate, mutationResistance, productionRate, lifespan, color)); + return new SimpleBacteria(new BacteriaStats(resource, growthRate, mutationResistance, productionRate, colonySize, lifespan, color)); } } } diff --git a/src/main/java/com/portingdeadmods/nautec/content/menus/BacterialAnalyzerMenu.java b/src/main/java/com/portingdeadmods/nautec/content/menus/BacterialAnalyzerMenu.java index b27211a9..48859732 100644 --- a/src/main/java/com/portingdeadmods/nautec/content/menus/BacterialAnalyzerMenu.java +++ b/src/main/java/com/portingdeadmods/nautec/content/menus/BacterialAnalyzerMenu.java @@ -17,7 +17,7 @@ public BacterialAnalyzerMenu(int containerId, Inventory inv, FriendlyByteBuf ext public BacterialAnalyzerMenu(int containerId, @NotNull Inventory inv, @NotNull BacterialAnalyzerBlockEntity blockEntity) { super(NTMenuTypes.BACTERIAL_ANALYZER.get(), containerId, inv, blockEntity); - // Catalyst + // Input Slot addSlot(new SlotItemHandler(blockEntity.getItemHandler(), 0, 80, 35)); addPlayerInventory(inv, 84); diff --git a/src/main/java/com/portingdeadmods/nautec/utils/ComponentUtils.java b/src/main/java/com/portingdeadmods/nautec/utils/ComponentUtils.java new file mode 100644 index 00000000..15f34498 --- /dev/null +++ b/src/main/java/com/portingdeadmods/nautec/utils/ComponentUtils.java @@ -0,0 +1,30 @@ +package com.portingdeadmods.nautec.utils; + +import net.minecraft.ChatFormatting; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; + +public final class ComponentUtils { + public static MutableComponent colored(String text, ChatFormatting col) { + return Component.literal(text).withStyle(col); + } + + public static MutableComponent countableStatShow(String name, Number val, Number max) { + MutableComponent mc1 = colored(name, ChatFormatting.YELLOW) + .append(Component.literal(": ").withStyle(ChatFormatting.WHITE)); + + if (val.doubleValue() < max.doubleValue()) { + mc1.append(colored(val.toString(), ChatFormatting.GREEN)); + } else { + mc1.append(colored(val.toString(), ChatFormatting.RED)); + } + + return mc1; + } + + public static MutableComponent stringStatShow(String name, String val) { + return colored(name, ChatFormatting.YELLOW) + .append(Component.literal(": ").withStyle(ChatFormatting.WHITE)) + .append(colored(val, ChatFormatting.GREEN)); + } +} diff --git a/src/main/java/com/portingdeadmods/nautec/utils/RNGUtils.java b/src/main/java/com/portingdeadmods/nautec/utils/RNGUtils.java index 46978fb2..71969cf3 100644 --- a/src/main/java/com/portingdeadmods/nautec/utils/RNGUtils.java +++ b/src/main/java/com/portingdeadmods/nautec/utils/RNGUtils.java @@ -1,6 +1,10 @@ package com.portingdeadmods.nautec.utils; public final class RNGUtils { + public static float random() { + return (float) Math.random(); + } + public static int uniformRandInt(int min, int max) { return (int) (Math.random() * (max - min + 1) + min); } @@ -9,28 +13,28 @@ public static int uniformRandInt(int max) { return uniformRandInt(0, max); } - public static double uniformRandDouble(double min, double max) { - return Math.random() * (max - min) + min; + public static float uniformRandFloat(float min, float max) { + return (float) Math.random() * (max - min) + min; } - public static double uniformRandDouble(double max) { - return uniformRandDouble(0, max); + public static float uniformRandFloat(float max) { + return uniformRandFloat(0, max); } public static int intInRangeOf(int val, int range) { - return (int) (uniformRandInt(-val, val) * Math.random() + range); + return (int) (uniformRandInt(-val, val) * random() + range); } - public static int intInRangeOf(int val) { - return intInRangeOf(val, 0); + public static int intInRangeOf(int range) { + return intInRangeOf(0, range); } - public static double doubleInRangeOf(double val, double range) { - return uniformRandDouble(-val, val) * Math.random() + range; + public static float floatInRangeOf(float val, float range) { + return uniformRandFloat(-val, val) * random() + range; } - public static double doubleInRangeOf(double val) { - return doubleInRangeOf(val, 0); + public static float floatInRangeOf(float range) { + return floatInRangeOf(0, range); } /* @@ -38,18 +42,32 @@ public static double doubleInRangeOf(double val) { * 1 -> always in the positive range * 0 -> neutral */ - public static double biasedInRangeOf(double val, double range, double bias) { - double absBias = Math.abs(bias); + public static float biasedInRangeOf(float val, float range, float bias) { + float absBias = Math.abs(bias); if (bias < 0) { - return uniformRandDouble(-range, range * (1 - absBias)) + val; + return uniformRandFloat(-range, range * (1 - absBias)) + val; } else if (bias > 0) { - return uniformRandDouble(-range * (1 - absBias), range) + val; + return uniformRandFloat(-range * (1 - absBias), range) + val; } - return uniformRandDouble(-range, range) + val; + return uniformRandFloat(-range, range) + val; } - public static double biasedInRangeOf(double range, double bias) { + public static float biasedInRangeOf(float range, float bias) { return biasedInRangeOf(0, range, bias); } + + public static float biasedInRange(float rangeStart, float rangeEnd, float bias) { + float absBias = Math.abs(bias); + float middlePoint = (rangeStart + rangeEnd) / 2; + + float left = middlePoint - rangeStart; + float right = rangeEnd - middlePoint; + + if (bias < 0) { + return uniformRandFloat(left, right * (1 - absBias)) + middlePoint; + } else if (bias > 0) { + return uniformRandFloat(left * (1 - absBias), right) + middlePoint; + } + } }