diff --git a/src/main/java/com/portingdeadmods/nautec/NTRegistries.java b/src/main/java/com/portingdeadmods/nautec/NTRegistries.java index 454534e3..b5fbaa16 100644 --- a/src/main/java/com/portingdeadmods/nautec/NTRegistries.java +++ b/src/main/java/com/portingdeadmods/nautec/NTRegistries.java @@ -20,7 +20,7 @@ public final class NTRegistries { ResourceKey.createRegistryKey(ResourceLocation.fromNamespaceAndPath(Nautec.MODID, "multiblock")); public static final ResourceKey>> BACTERIA_SERIALIZER_KEY = ResourceKey.createRegistryKey(ResourceLocation.fromNamespaceAndPath(Nautec.MODID, "bacteria_serializer")); - public static final ResourceKey>> BACTERIA_STATS_SERIALIZER_KEY = + public static final ResourceKey>> BACTERIA_STATS_SERIALIZER_KEY = ResourceKey.createRegistryKey(ResourceLocation.fromNamespaceAndPath(Nautec.MODID, "bacteria_stats_serializer")); public static final ResourceKey> BACTERIA_KEY = ResourceKey.createRegistryKey(ResourceLocation.fromNamespaceAndPath(Nautec.MODID, "bacteria")); @@ -29,5 +29,5 @@ public final class NTRegistries { public static final Registry AUGMENT_SLOT = new RegistryBuilder<>(AUGMENT_SLOT_KEY).create(); public static final Registry MULTIBLOCK = new RegistryBuilder<>(MULTIBLOCK_KEY).create(); public static final Registry> BACTERIA_SERIALIZER = new RegistryBuilder<>(BACTERIA_SERIALIZER_KEY).create(); - public static final Registry> BACTERIA_STATS_SERIALIZER = new RegistryBuilder<>(BACTERIA_STATS_SERIALIZER_KEY).sync(true).create(); + public static final Registry> BACTERIA_STATS_SERIALIZER = new RegistryBuilder<>(BACTERIA_STATS_SERIALIZER_KEY).sync(true).create(); } diff --git a/src/main/java/com/portingdeadmods/nautec/api/bacteria/BacteriaInstance.java b/src/main/java/com/portingdeadmods/nautec/api/bacteria/BacteriaInstance.java index 4330f7cc..8c180b74 100644 --- a/src/main/java/com/portingdeadmods/nautec/api/bacteria/BacteriaInstance.java +++ b/src/main/java/com/portingdeadmods/nautec/api/bacteria/BacteriaInstance.java @@ -2,7 +2,7 @@ import com.mojang.serialization.Codec; import com.mojang.serialization.codecs.RecordCodecBuilder; -import com.portingdeadmods.nautec.content.bacteria.CollapsedStats; +import com.portingdeadmods.nautec.content.bacteria.SimpleCollapsedStats; import com.portingdeadmods.nautec.content.bacteria.SimpleBacteriaStats; import com.portingdeadmods.nautec.registries.NTBacterias; import com.portingdeadmods.nautec.utils.BacteriaHelper; @@ -17,37 +17,37 @@ public final class BacteriaInstance { public static final Codec CODEC = RecordCodecBuilder.create(instance -> instance.group( Bacteria.BACTERIA_TYPE_CODEC.fieldOf("bacteria").forGetter(BacteriaInstance::getBacteria), Codec.LONG.fieldOf("amount").forGetter(BacteriaInstance::getAmount), - CollapsedStats.CODEC.fieldOf("stats").forGetter(BacteriaInstance::getStats) + CollapsedBacteriaStats.CODEC.fieldOf("stats").forGetter(BacteriaInstance::getStats) ).apply(instance, BacteriaInstance::new)); public static final StreamCodec STREAM_CODEC = StreamCodec.composite( Bacteria.BACTERIA_TYPE_STREAM_CODEC, BacteriaInstance::getBacteria, ByteBufCodecs.VAR_LONG, BacteriaInstance::getAmount, - CollapsedStats.STREAM_CODEC, + CollapsedBacteriaStats.STREAM_CODEC, BacteriaInstance::getStats, BacteriaInstance::new ); private final ResourceKey bacteria; private long amount; - private CollapsedStats stats; + private CollapsedBacteriaStats stats; public BacteriaInstance(ResourceKey bacteria, HolderLookup.Provider lookup) { this(bacteria, 1, BacteriaHelper.getBacteria(lookup, bacteria).initialStats()); } - public BacteriaInstance(ResourceKey bacteria, BacteriaStats stats) { + public BacteriaInstance(ResourceKey bacteria, BacteriaStats stats) { this(bacteria, 1, stats); } - public BacteriaInstance(ResourceKey bacteria, long amount, BacteriaStats stats) { + public BacteriaInstance(ResourceKey bacteria, long amount, BacteriaStats stats) { this.bacteria = bacteria; this.amount = amount; this.stats = stats.collapse(); } - public BacteriaInstance(ResourceKey bacteria, long amount, CollapsedStats stats) { + public BacteriaInstance(ResourceKey bacteria, long amount, CollapsedBacteriaStats stats) { this.bacteria = bacteria; this.amount = amount; this.stats = stats; @@ -65,11 +65,11 @@ public ResourceKey getBacteria() { return bacteria; } - public void setStats(CollapsedStats stats) { + public void setStats(CollapsedBacteriaStats stats) { this.stats = stats; } - public CollapsedStats getStats() { + public CollapsedBacteriaStats getStats() { return this.stats; } diff --git a/src/main/java/com/portingdeadmods/nautec/api/bacteria/BacteriaStats.java b/src/main/java/com/portingdeadmods/nautec/api/bacteria/BacteriaStats.java index 04a2c824..2eead58f 100644 --- a/src/main/java/com/portingdeadmods/nautec/api/bacteria/BacteriaStats.java +++ b/src/main/java/com/portingdeadmods/nautec/api/bacteria/BacteriaStats.java @@ -2,32 +2,31 @@ import com.mojang.serialization.Codec; import com.portingdeadmods.nautec.NTRegistries; -import com.portingdeadmods.nautec.content.bacteria.CollapsedStats; +import com.portingdeadmods.nautec.utils.ranges.FloatRange; +import com.portingdeadmods.nautec.utils.ranges.IntRange; import net.minecraft.network.RegistryFriendlyByteBuf; -import net.minecraft.network.chat.Component; import net.minecraft.network.codec.ByteBufCodecs; import net.minecraft.network.codec.StreamCodec; import java.util.List; -public interface BacteriaStats { - Codec CODEC = +public interface BacteriaStats { + Codec> CODEC = NTRegistries.BACTERIA_STATS_SERIALIZER.byNameCodec().dispatch(BacteriaStats::getSerializer, BacteriaStatsSerializer::mapCodec); - StreamCodec STREAM_CODEC = + StreamCodec> STREAM_CODEC = ByteBufCodecs.registry(NTRegistries.BACTERIA_STATS_SERIALIZER_KEY).dispatch(BacteriaStats::getSerializer, BacteriaStatsSerializer::streamCodec); + FloatRange growthRate(); - List growthRate(); + FloatRange mutationResistance(); - List mutationResistance(); + FloatRange productionRate(); - List productionRate(); + IntRange lifespan(); - List lifespan(); - - CollapsedStats collapse(); + C collapse(); int color(); - BacteriaStatsSerializer getSerializer(); + BacteriaStatsSerializer getSerializer(); } diff --git a/src/main/java/com/portingdeadmods/nautec/api/bacteria/BacteriaStatsSerializer.java b/src/main/java/com/portingdeadmods/nautec/api/bacteria/BacteriaStatsSerializer.java index 881f30f5..f3d24289 100644 --- a/src/main/java/com/portingdeadmods/nautec/api/bacteria/BacteriaStatsSerializer.java +++ b/src/main/java/com/portingdeadmods/nautec/api/bacteria/BacteriaStatsSerializer.java @@ -4,8 +4,12 @@ import net.minecraft.network.RegistryFriendlyByteBuf; import net.minecraft.network.codec.StreamCodec; -public interface BacteriaStatsSerializer { +public interface BacteriaStatsSerializer> { MapCodec mapCodec(); StreamCodec streamCodec(); + + MapCodec collapsedMapCodec(); + + StreamCodec collapsedStreamCodec(); } \ No newline at end of file diff --git a/src/main/java/com/portingdeadmods/nautec/api/bacteria/CollapsedBacteriaStats.java b/src/main/java/com/portingdeadmods/nautec/api/bacteria/CollapsedBacteriaStats.java new file mode 100644 index 00000000..962f1d41 --- /dev/null +++ b/src/main/java/com/portingdeadmods/nautec/api/bacteria/CollapsedBacteriaStats.java @@ -0,0 +1,16 @@ +package com.portingdeadmods.nautec.api.bacteria; + +import com.mojang.serialization.Codec; +import com.portingdeadmods.nautec.NTRegistries; +import net.minecraft.network.RegistryFriendlyByteBuf; +import net.minecraft.network.codec.ByteBufCodecs; +import net.minecraft.network.codec.StreamCodec; + +public interface CollapsedBacteriaStats { + Codec CODEC = + NTRegistries.BACTERIA_STATS_SERIALIZER.byNameCodec().dispatch(CollapsedBacteriaStats::getSerializer, BacteriaStatsSerializer::collapsedMapCodec); + StreamCodec STREAM_CODEC = + ByteBufCodecs.registry(NTRegistries.BACTERIA_STATS_SERIALIZER_KEY).dispatch(CollapsedBacteriaStats::getSerializer, BacteriaStatsSerializer::collapsedStreamCodec); + + BacteriaStatsSerializer getSerializer(); +} diff --git a/src/main/java/com/portingdeadmods/nautec/api/client/screen/NTMachineScreen.java b/src/main/java/com/portingdeadmods/nautec/api/client/screen/NTMachineScreen.java new file mode 100644 index 00000000..f9726c6e --- /dev/null +++ b/src/main/java/com/portingdeadmods/nautec/api/client/screen/NTMachineScreen.java @@ -0,0 +1,95 @@ +package com.portingdeadmods.nautec.api.client.screen; + +import com.portingdeadmods.nautec.api.blockentities.ContainerBlockEntity; +import com.portingdeadmods.nautec.api.menu.NTMachineMenu; +import com.portingdeadmods.nautec.api.menu.slots.SlotBacteriaStorage; +import com.portingdeadmods.nautec.api.menu.slots.SlotFluidHandler; +import net.minecraft.ChatFormatting; +import net.minecraft.client.gui.Font; +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.player.Inventory; +import net.neoforged.neoforge.fluids.FluidStack; +import org.jetbrains.annotations.NotNull; + +import java.text.NumberFormat; +import java.util.List; + +public abstract class NTMachineScreen extends AbstractContainerScreen> { + private SlotFluidHandler hoveredFluidHandlerSlot; + private SlotBacteriaStorage hoveredBacteriaStorageSlot; + + private final NumberFormat nf = NumberFormat.getIntegerInstance(); + + public NTMachineScreen(NTMachineMenu menu, Inventory playerInventory, Component title) { + super(menu, playerInventory, title); + + this.titleLabelY = 4; + this.imageHeight = 174; + } + + @Override + public void render(GuiGraphics pGuiGraphics, int pMouseX, int pMouseY, float pPartialTick) { + renderBackground(pGuiGraphics, pMouseX, pMouseX, pPartialTick); + super.render(pGuiGraphics, pMouseX, pMouseY, pPartialTick); + renderTooltip(pGuiGraphics, pMouseX, pMouseY); + + hoverFluidSlot(pMouseX, pMouseY); + + hoverBacteriaSlot(pMouseX, pMouseY); + + Font font = minecraft.font; + if (this.hoveredBacteriaStorageSlot != null) { + SimpleCollapsedStats + pGuiGraphics.renderComponentTooltip(font, List.of(Component.literal("Bacteria Storage")), pMouseX, pMouseY); + } + + if (this.hoveredFluidHandlerSlot != null) { + FluidStack fluid = this.hoveredFluidHandlerSlot.getFluidStack(); + pGuiGraphics.renderComponentTooltip(font, List.of( + fluid.getHoverName(), + Component.literal("%s / %s mb".formatted( + nf.format(fluid.getAmount()), + nf.format(this.hoveredFluidHandlerSlot.getFluidCapacity())) + ).withStyle(ChatFormatting.GRAY) + ), pMouseX, pMouseY); + } + } + + private void hoverFluidSlot(int pMouseX, int pMouseY) { + for (SlotFluidHandler fSlot : menu.getFluidTankSlots()) { + if (isHovering(fSlot.getX(), fSlot.getY(), fSlot.getWidth(), fSlot.getHeight(), pMouseX, pMouseY)) { + this.hoveredFluidHandlerSlot = fSlot; + return; + } + } + this.hoveredFluidHandlerSlot = null; + } + + private void hoverBacteriaSlot(int pMouseX, int pMouseY) { + for (SlotBacteriaStorage bSlot : menu.getBacteriaStorageSlots()) { + if (isHovering(bSlot.getX(), bSlot.getY(), bSlot.getWidth(), bSlot.getHeight(), pMouseX, pMouseY)) { + this.hoveredBacteriaStorageSlot = bSlot; + return; + } + } + this.hoveredBacteriaStorageSlot = null; + } + + @Override + protected void renderBg(GuiGraphics guiGraphics, float delta, int mouseX, int mouseY) { + guiGraphics.blit(getBackgroundTexture(), leftPos, topPos, 0, 0, imageWidth, imageHeight); + } + + public abstract @NotNull ResourceLocation getBackgroundTexture(); + + public SlotFluidHandler getHoveredFluidHandlerSlot() { + return hoveredFluidHandlerSlot; + } + + public SlotBacteriaStorage getHoveredBacteriaStorageSlot() { + return hoveredBacteriaStorageSlot; + } +} diff --git a/src/main/java/com/portingdeadmods/nautec/api/menu/NTMachineMenu.java b/src/main/java/com/portingdeadmods/nautec/api/menu/NTMachineMenu.java new file mode 100644 index 00000000..f76aa45c --- /dev/null +++ b/src/main/java/com/portingdeadmods/nautec/api/menu/NTMachineMenu.java @@ -0,0 +1,40 @@ +package com.portingdeadmods.nautec.api.menu; + +import com.portingdeadmods.nautec.api.blockentities.ContainerBlockEntity; +import com.portingdeadmods.nautec.api.menu.slots.SlotBacteriaStorage; +import com.portingdeadmods.nautec.api.menu.slots.SlotFluidHandler; +import net.minecraft.core.NonNullList; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.inventory.MenuType; +import org.jetbrains.annotations.NotNull; + +public abstract class NTMachineMenu extends NTAbstractContainerMenu { + private final NonNullList fluidTankSlots; + private final NonNullList bacteriaStorageSlots; + + public NTMachineMenu(MenuType menuType, int containerId, @NotNull Inventory inv, @NotNull T blockEntity) { + super(menuType, containerId, inv, blockEntity); + + addPlayerInventory(inv, 92); + addPlayerHotbar(inv, 150); + + this.fluidTankSlots = NonNullList.create(); + this.bacteriaStorageSlots = NonNullList.create(); + } + + public void addFluidHandlerSlot(SlotFluidHandler slot) { + this.fluidTankSlots.add(slot); + } + + public void addBacteriaStorageSlot(SlotBacteriaStorage slot) { + this.bacteriaStorageSlots.add(slot); + } + + public NonNullList getFluidTankSlots() { + return fluidTankSlots; + } + + public NonNullList getBacteriaStorageSlots() { + return bacteriaStorageSlots; + } +} diff --git a/src/main/java/com/portingdeadmods/nautec/api/menu/slots/AbstractSlot.java b/src/main/java/com/portingdeadmods/nautec/api/menu/slots/AbstractSlot.java new file mode 100644 index 00000000..e370d9f6 --- /dev/null +++ b/src/main/java/com/portingdeadmods/nautec/api/menu/slots/AbstractSlot.java @@ -0,0 +1,24 @@ +package com.portingdeadmods.nautec.api.menu.slots; + +import net.neoforged.neoforge.fluids.capability.IFluidHandler; + +public abstract class AbstractSlot { + protected final int slot; + public int index; + protected final int x; + protected final int y; + + public AbstractSlot(int index, int x, int y) { + this.slot = index; + this.x = x; + this.y = y; + } + + public int getX() { + return x; + } + + public int getY() { + return y; + } +} diff --git a/src/main/java/com/portingdeadmods/nautec/api/menu/slots/SlotBacteriaStorage.java b/src/main/java/com/portingdeadmods/nautec/api/menu/slots/SlotBacteriaStorage.java new file mode 100644 index 00000000..ea382525 --- /dev/null +++ b/src/main/java/com/portingdeadmods/nautec/api/menu/slots/SlotBacteriaStorage.java @@ -0,0 +1,26 @@ +package com.portingdeadmods.nautec.api.menu.slots; + +import com.portingdeadmods.nautec.capabilities.bacteria.IBacteriaStorage; + +public class SlotBacteriaStorage extends AbstractSlot { + private static final int WIDTH = 18; + private static final int HEIGHT = 18; + private final IBacteriaStorage bacteriaStorage; + + public SlotBacteriaStorage(IBacteriaStorage bacteriaStorage, int index, int x, int y) { + super(index, x, y); + this.bacteriaStorage = bacteriaStorage; + } + + public IBacteriaStorage getBacteriaStorage() { + return bacteriaStorage; + } + + public int getWidth() { + return WIDTH; + } + + public int getHeight() { + return HEIGHT; + } +} diff --git a/src/main/java/com/portingdeadmods/nautec/api/menu/slots/SlotFluidHandler.java b/src/main/java/com/portingdeadmods/nautec/api/menu/slots/SlotFluidHandler.java new file mode 100644 index 00000000..2b7396a6 --- /dev/null +++ b/src/main/java/com/portingdeadmods/nautec/api/menu/slots/SlotFluidHandler.java @@ -0,0 +1,37 @@ +package com.portingdeadmods.nautec.api.menu.slots; + +import net.neoforged.neoforge.fluids.FluidStack; +import net.neoforged.neoforge.fluids.capability.IFluidHandler; + +public class SlotFluidHandler extends AbstractSlot { + private final IFluidHandler fluidHandler; + private final int width; + private final int height; + + public SlotFluidHandler(IFluidHandler fluidHandler, int index, int x, int y, int width, int height) { + super(index, x, y); + this.fluidHandler = fluidHandler; + this.width = width; + this.height = height; + } + + public FluidStack getFluidStack() { + return fluidHandler.getFluidInTank(slot); + } + + public int getFluidCapacity() { + return fluidHandler.getTankCapacity(slot); + } + + public int getWidth() { + return width; + } + + public int getHeight() { + return height; + } + + public IFluidHandler getFluidHandler() { + return fluidHandler; + } +} diff --git a/src/main/java/com/portingdeadmods/nautec/capabilities/bacteria/IBacteriaStorage.java b/src/main/java/com/portingdeadmods/nautec/capabilities/bacteria/IBacteriaStorage.java index 7e26ca44..df8a37fb 100644 --- a/src/main/java/com/portingdeadmods/nautec/capabilities/bacteria/IBacteriaStorage.java +++ b/src/main/java/com/portingdeadmods/nautec/capabilities/bacteria/IBacteriaStorage.java @@ -1,8 +1,7 @@ package com.portingdeadmods.nautec.capabilities.bacteria; import com.portingdeadmods.nautec.api.bacteria.BacteriaInstance; -import com.portingdeadmods.nautec.api.bacteria.BacteriaStats; -import com.portingdeadmods.nautec.content.bacteria.CollapsedStats; +import com.portingdeadmods.nautec.content.bacteria.SimpleCollapsedStats; import java.util.function.UnaryOperator; @@ -13,8 +12,8 @@ public interface IBacteriaStorage { int getBacteriaSlots(); - default void modifyStats(int slot, UnaryOperator statsModifier) { + default void modifyStats(int slot, UnaryOperator statsModifier) { BacteriaInstance bacteriaInstance = getBacteria(slot); - CollapsedStats newStats = statsModifier.apply(bacteriaInstance.getStats()); + SimpleCollapsedStats newStats = statsModifier.apply(bacteriaInstance.getStats()); } } diff --git a/src/main/java/com/portingdeadmods/nautec/client/screen/BioReactorScreen.java b/src/main/java/com/portingdeadmods/nautec/client/screen/BioReactorScreen.java index 63b44b63..cba3c72a 100644 --- a/src/main/java/com/portingdeadmods/nautec/client/screen/BioReactorScreen.java +++ b/src/main/java/com/portingdeadmods/nautec/client/screen/BioReactorScreen.java @@ -2,17 +2,19 @@ import com.portingdeadmods.nautec.Nautec; import com.portingdeadmods.nautec.api.client.screen.NTAbstractContainerScreen; +import com.portingdeadmods.nautec.api.client.screen.NTMachineScreen; import com.portingdeadmods.nautec.api.menu.NTAbstractContainerMenu; +import com.portingdeadmods.nautec.api.menu.NTMachineMenu; import com.portingdeadmods.nautec.content.blockentities.multiblock.controller.BioReactorBlockEntity; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.player.Inventory; import org.jetbrains.annotations.NotNull; -public class BioReactorScreen extends NTAbstractContainerScreen { +public class BioReactorScreen extends NTMachineScreen { public static final ResourceLocation TEXTURE = ResourceLocation.fromNamespaceAndPath(Nautec.MODID, "textures/gui/bio_reactor.png"); - public BioReactorScreen(NTAbstractContainerMenu menu, Inventory playerInventory, Component title) { + public BioReactorScreen(NTMachineMenu menu, Inventory playerInventory, Component title) { super(menu, playerInventory, title); this.titleLabelY = 4; this.imageHeight = 174; diff --git a/src/main/java/com/portingdeadmods/nautec/client/screen/MixerScreen.java b/src/main/java/com/portingdeadmods/nautec/client/screen/MixerScreen.java index 1301ecbb..1be8933c 100644 --- a/src/main/java/com/portingdeadmods/nautec/client/screen/MixerScreen.java +++ b/src/main/java/com/portingdeadmods/nautec/client/screen/MixerScreen.java @@ -1,18 +1,18 @@ package com.portingdeadmods.nautec.client.screen; import com.portingdeadmods.nautec.Nautec; -import com.portingdeadmods.nautec.api.client.screen.NTAbstractContainerScreen; -import com.portingdeadmods.nautec.api.menu.NTAbstractContainerMenu; +import com.portingdeadmods.nautec.api.client.screen.NTMachineScreen; +import com.portingdeadmods.nautec.api.menu.NTMachineMenu; import com.portingdeadmods.nautec.content.blockentities.MixerBlockEntity; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.player.Inventory; import org.jetbrains.annotations.NotNull; -public class MixerScreen extends NTAbstractContainerScreen { +public class MixerScreen extends NTMachineScreen { public static final ResourceLocation TEXTURE = Nautec.rl("textures/gui/mixer.png"); - public MixerScreen(NTAbstractContainerMenu menu, Inventory playerInventory, Component title) { + public MixerScreen(NTMachineMenu menu, Inventory playerInventory, Component title) { super(menu, playerInventory, title); this.titleLabelY = 4; this.imageHeight = 174; diff --git a/src/main/java/com/portingdeadmods/nautec/content/bacteria/SimpleBacteriaStats.java b/src/main/java/com/portingdeadmods/nautec/content/bacteria/SimpleBacteriaStats.java index a6887106..b4ba04d4 100644 --- a/src/main/java/com/portingdeadmods/nautec/content/bacteria/SimpleBacteriaStats.java +++ b/src/main/java/com/portingdeadmods/nautec/content/bacteria/SimpleBacteriaStats.java @@ -3,30 +3,29 @@ import com.mojang.serialization.Codec; import com.mojang.serialization.MapCodec; import com.mojang.serialization.codecs.RecordCodecBuilder; -import com.portingdeadmods.nautec.Nautec; import com.portingdeadmods.nautec.api.bacteria.BacteriaStats; import com.portingdeadmods.nautec.api.bacteria.BacteriaStatsSerializer; -import com.portingdeadmods.nautec.utils.ComponentUtils; -import com.portingdeadmods.nautec.utils.MathUtils; -import com.portingdeadmods.nautec.utils.RNGUtils; import com.portingdeadmods.nautec.utils.codec.CodecUtils; -import net.minecraft.ChatFormatting; +import com.portingdeadmods.nautec.utils.ranges.FloatRange; +import com.portingdeadmods.nautec.utils.ranges.IntRange; import net.minecraft.network.RegistryFriendlyByteBuf; -import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.MutableComponent; import net.minecraft.network.codec.ByteBufCodecs; import net.minecraft.network.codec.StreamCodec; import java.util.List; -import static com.portingdeadmods.nautec.NTConfig.*; - -public record SimpleBacteriaStats(List growthRate, - List mutationResistance, - List productionRate, - List lifespan, - int color) implements BacteriaStats { - public static final SimpleBacteriaStats EMPTY = new SimpleBacteriaStats(List.of(0F, 0F), List.of(0F, 0F), List.of(0F, 0F), List.of(1200, 2400), -1); +public record SimpleBacteriaStats(FloatRange growthRate, + FloatRange mutationResistance, + FloatRange productionRate, + IntRange lifespan, + int color) implements BacteriaStats { + public static final SimpleBacteriaStats EMPTY = new SimpleBacteriaStats( + FloatRange.of(0F, 0F), + FloatRange.of(0F, 0F), + FloatRange.of(0F, 0F), + IntRange.of(1200, 2400), + -1 + ); public static final MapCodec CODEC = RecordCodecBuilder.mapCodec( instance -> instance.group( Codec.list(Codec.FLOAT).fieldOf("growth_rate").forGetter(SimpleBacteriaStats::growthRate), @@ -51,8 +50,8 @@ public record SimpleBacteriaStats(List growthRate, ); @Override - public CollapsedStats collapse() { - return CollapsedStats.from(this); + public SimpleCollapsedStats collapse() { + return SimpleCollapsedStats.from(this); } @Override diff --git a/src/main/java/com/portingdeadmods/nautec/content/bacteria/CollapsedStats.java b/src/main/java/com/portingdeadmods/nautec/content/bacteria/SimpleCollapsedStats.java similarity index 70% rename from src/main/java/com/portingdeadmods/nautec/content/bacteria/CollapsedStats.java rename to src/main/java/com/portingdeadmods/nautec/content/bacteria/SimpleCollapsedStats.java index 901d641b..fcfa2f6b 100644 --- a/src/main/java/com/portingdeadmods/nautec/content/bacteria/CollapsedStats.java +++ b/src/main/java/com/portingdeadmods/nautec/content/bacteria/SimpleCollapsedStats.java @@ -4,6 +4,7 @@ import com.mojang.serialization.MapCodec; import com.mojang.serialization.codecs.RecordCodecBuilder; import com.portingdeadmods.nautec.api.bacteria.BacteriaStats; +import com.portingdeadmods.nautec.api.bacteria.CollapsedBacteriaStats; import com.portingdeadmods.nautec.utils.ComponentUtils; import com.portingdeadmods.nautec.utils.MathUtils; import com.portingdeadmods.nautec.utils.RNGUtils; @@ -21,74 +22,75 @@ /** * Collapses the ranges of a {@link BacteriaStats} instance. + * * @param growthRate * @param mutationResistance * @param productionRate * @param lifespan * @param color */ -public record CollapsedStats(float growthRate, - float mutationResistance, - float productionRate, - int lifespan, - int color) { - - public static CollapsedStats from(BacteriaStats stats) { - return new CollapsedStats( - RNGUtils.uniformRandFloat(stats.growthRate().get(0), stats.growthRate().get(1)), - RNGUtils.uniformRandFloat(stats.mutationResistance().get(0), stats.mutationResistance().get(1)), - RNGUtils.uniformRandFloat(stats.productionRate().get(0), stats.productionRate().get(1)), - RNGUtils.uniformRandInt(stats.lifespan().get(0), stats.lifespan().get(1)), +public record SimpleCollapsedStats(float growthRate, + float mutationResistance, + float productionRate, + int lifespan, + int color) implements CollapsedBacteriaStats { + public static final SimpleCollapsedStats EMPTY = new SimpleCollapsedStats(0, 0, 0, 0, -1); + + public static SimpleCollapsedStats from(BacteriaStats stats) { + return new SimpleCollapsedStats( + RNGUtils.uniformRandFloat(stats.growthRate()), + RNGUtils.uniformRandFloat(stats.mutationResistance()), + RNGUtils.uniformRandFloat(stats.productionRate()), + RNGUtils.uniformRandInt(stats.lifespan()), stats.color() ); } - public static final CollapsedStats EMPTY = new CollapsedStats(0, 0, 0, 0, -1); - - public CollapsedStats getMaxStats() { return new CollapsedStats( - bacteriaGrowthRateCap, - bacteriaMutationResistanceCap, - bacteriaProductionRateCap, - bacteriaLifespanCap, - this.color - ); + public SimpleCollapsedStats getMaxStats() { + return new SimpleCollapsedStats( + bacteriaGrowthRateCap, + bacteriaMutationResistanceCap, + bacteriaProductionRateCap, + bacteriaLifespanCap, + this.color + ); } - public static final MapCodec CODEC = + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec( instance -> instance.group( - Codec.FLOAT.fieldOf("growth_rate").forGetter(CollapsedStats::growthRate), - Codec.FLOAT.fieldOf("mutation_resistance").forGetter(CollapsedStats::mutationResistance), - Codec.FLOAT.fieldOf("production_rate").forGetter(CollapsedStats::productionRate), - Codec.INT.fieldOf("lifespan").forGetter(CollapsedStats::lifespan), - Codec.INT.fieldOf("color").forGetter(CollapsedStats::color) - ).apply(instance, CollapsedStats::new) + Codec.FLOAT.fieldOf("growth_rate").forGetter(SimpleCollapsedStats::growthRate), + Codec.FLOAT.fieldOf("mutation_resistance").forGetter(SimpleCollapsedStats::mutationResistance), + Codec.FLOAT.fieldOf("production_rate").forGetter(SimpleCollapsedStats::productionRate), + Codec.INT.fieldOf("lifespan").forGetter(SimpleCollapsedStats::lifespan), + Codec.INT.fieldOf("color").forGetter(SimpleCollapsedStats::color) + ).apply(instance, SimpleCollapsedStats::new) ); - public static final StreamCodec STREAM_CODEC = + public static final StreamCodec STREAM_CODEC = StreamCodec.composite( ByteBufCodecs.FLOAT, - CollapsedStats::growthRate, + SimpleCollapsedStats::growthRate, ByteBufCodecs.FLOAT, - CollapsedStats::mutationResistance, + SimpleCollapsedStats::mutationResistance, ByteBufCodecs.FLOAT, - CollapsedStats::productionRate, + SimpleCollapsedStats::productionRate, ByteBufCodecs.INT, - CollapsedStats::lifespan, + SimpleCollapsedStats::lifespan, ByteBufCodecs.INT, - CollapsedStats::color, - CollapsedStats::new + SimpleCollapsedStats::color, + SimpleCollapsedStats::new ); public static class Serializer { public static final Serializer INSTANCE = new Serializer(); - public MapCodec mapCodec() { - return CollapsedStats.CODEC; + public MapCodec mapCodec() { + return SimpleCollapsedStats.CODEC; } - public StreamCodec streamCodec() { - return CollapsedStats.STREAM_CODEC; + public StreamCodec streamCodec() { + return SimpleCollapsedStats.STREAM_CODEC; } } @@ -96,46 +98,46 @@ public static Serializer getSerializer() { return Serializer.INSTANCE; } - public CollapsedStats rollGrowthRate() { + public SimpleCollapsedStats rollGrowthRate() { float newGR = growthRate + (RNGUtils.floatInRangeOf(growthRate) / (10 * (1 + mutationResistance))); newGR = Math.max(newGR, 0); newGR = Math.min(newGR, bacteriaGrowthRateCap); - return new CollapsedStats(newGR, mutationResistance, productionRate, lifespan, color); + return new SimpleCollapsedStats(newGR, mutationResistance, productionRate, lifespan, color); } - public CollapsedStats rollMutationResistance() { + public SimpleCollapsedStats rollMutationResistance() { float newMR = mutationResistance + RNGUtils.biasedInRange(0, 0.1f, mutationResistance / bacteriaMutationResistanceCap) / 10 * (bacteriaMutationResistanceCap - mutationResistance); newMR = Math.max(newMR, 0); - return new CollapsedStats(growthRate, newMR, productionRate, lifespan, color); + return new SimpleCollapsedStats(growthRate, newMR, productionRate, lifespan, color); } - public CollapsedStats rollProductionRate() { + public SimpleCollapsedStats rollProductionRate() { float newPR = productionRate + RNGUtils.floatInRangeOf(productionRate) / 10 * (1 + mutationResistance); newPR = Math.max(newPR, 0); newPR = Math.min(newPR, bacteriaProductionRateCap); - return new CollapsedStats(growthRate, mutationResistance, newPR, lifespan, color); + return new SimpleCollapsedStats(growthRate, mutationResistance, newPR, lifespan, color); } - public CollapsedStats rollLifespan() { + public SimpleCollapsedStats rollLifespan() { int newLS = lifespan + (int) (RNGUtils.uniformRandInt(-100, 100) / (1 + mutationResistance)); newLS = Math.max(newLS, 0); newLS = Math.min(newLS, bacteriaLifespanCap); - return new CollapsedStats(growthRate, mutationResistance, productionRate, newLS, color); + return new SimpleCollapsedStats(growthRate, mutationResistance, productionRate, newLS, color); } - public CollapsedStats rollStats() { + public SimpleCollapsedStats rollStats() { return rollGrowthRate().rollMutationResistance().rollProductionRate().rollLifespan(); } // TODO: Might wanna move this to SimpleBacteriaInstance - public CollapsedStats grow() { + public SimpleCollapsedStats grow() { // float newCS = colonySize + RNGUtils.floatInRangeOf(0, growthRate); // newCS = Math.min(newCS, bacteriaColonySizeCap); // @@ -143,14 +145,14 @@ public CollapsedStats grow() { return this; } - public CollapsedStats shrink() { + public SimpleCollapsedStats shrink() { // float newCS = colonySize - colonySize * RNGUtils.uniformRandFloat(25) - 1; // return new BacteriaStats(growthRate, mutationResistance, productionRate, newCS, lifespan, color); return this; } - public CollapsedStats copy() { - return new CollapsedStats(growthRate, mutationResistance, productionRate, lifespan, color); + public SimpleCollapsedStats copy() { + return new SimpleCollapsedStats(growthRate, mutationResistance, productionRate, lifespan, color); } public List statsTooltip() { diff --git a/src/main/java/com/portingdeadmods/nautec/content/menus/BioReactorMenu.java b/src/main/java/com/portingdeadmods/nautec/content/menus/BioReactorMenu.java index 38cc9f76..f150d62f 100644 --- a/src/main/java/com/portingdeadmods/nautec/content/menus/BioReactorMenu.java +++ b/src/main/java/com/portingdeadmods/nautec/content/menus/BioReactorMenu.java @@ -1,13 +1,16 @@ package com.portingdeadmods.nautec.content.menus; import com.portingdeadmods.nautec.api.menu.NTAbstractContainerMenu; +import com.portingdeadmods.nautec.api.menu.NTMachineMenu; +import com.portingdeadmods.nautec.api.menu.slots.SlotBacteriaStorage; import com.portingdeadmods.nautec.content.blockentities.multiblock.controller.BioReactorBlockEntity; import com.portingdeadmods.nautec.registries.NTMenuTypes; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.world.entity.player.Inventory; +import net.neoforged.neoforge.items.SlotItemHandler; import org.jetbrains.annotations.NotNull; -public class BioReactorMenu extends NTAbstractContainerMenu { +public class BioReactorMenu extends NTMachineMenu { public BioReactorMenu(int containerId, Inventory inv, FriendlyByteBuf extraData) { this(containerId, inv, (BioReactorBlockEntity) inv.player.level().getBlockEntity(extraData.readBlockPos())); } @@ -15,12 +18,14 @@ public BioReactorMenu(int containerId, Inventory inv, FriendlyByteBuf extraData) public BioReactorMenu(int containerId, @NotNull Inventory inv, @NotNull BioReactorBlockEntity blockEntity) { super(NTMenuTypes.BIO_REACTOR.get(), containerId, inv, blockEntity); - addPlayerInventory(inv, 92); - addPlayerHotbar(inv, 150); + for (int i = 0; i < 3; i++) { + addBacteriaStorageSlot(new SlotBacteriaStorage(blockEntity.getBacteriaStorage(), i, 20, 20 + i * 30)); + addSlot(new SlotItemHandler(blockEntity.getItemHandler(), i, 107, 12 + i * 22)); + } } @Override protected int getMergeableSlotCount() { - return 2; + return 3; } } diff --git a/src/main/java/com/portingdeadmods/nautec/content/menus/MixerMenu.java b/src/main/java/com/portingdeadmods/nautec/content/menus/MixerMenu.java index d1eddaed..0dfe5b25 100644 --- a/src/main/java/com/portingdeadmods/nautec/content/menus/MixerMenu.java +++ b/src/main/java/com/portingdeadmods/nautec/content/menus/MixerMenu.java @@ -1,14 +1,15 @@ package com.portingdeadmods.nautec.content.menus; -import com.portingdeadmods.nautec.api.menu.NTAbstractContainerMenu; +import com.portingdeadmods.nautec.api.menu.NTMachineMenu; +import com.portingdeadmods.nautec.api.menu.slots.SlotFluidHandler; import com.portingdeadmods.nautec.content.blockentities.MixerBlockEntity; -import com.portingdeadmods.nautec.content.blockentities.MutatorBlockEntity; import com.portingdeadmods.nautec.registries.NTMenuTypes; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.world.entity.player.Inventory; +import net.neoforged.neoforge.items.SlotItemHandler; import org.jetbrains.annotations.NotNull; -public class MixerMenu extends NTAbstractContainerMenu { +public class MixerMenu extends NTMachineMenu { public MixerMenu(int containerId, Inventory inv, FriendlyByteBuf extraData) { this(containerId, inv, (MixerBlockEntity) inv.player.level().getBlockEntity(extraData.readBlockPos())); } @@ -16,8 +17,14 @@ public MixerMenu(int containerId, Inventory inv, FriendlyByteBuf extraData) { public MixerMenu(int containerId, @NotNull Inventory inv, @NotNull MixerBlockEntity blockEntity) { super(NTMenuTypes.MIXER.get(), containerId, inv, blockEntity); - addPlayerInventory(inv, 92); - addPlayerHotbar(inv, 150); + for (int i = 0; i < 4; i++) { + addSlot(new SlotItemHandler(blockEntity.getItemHandler(), i, 29 + i * (4 + 18), 12)); + } + + addSlot(new SlotItemHandler(blockEntity.getItemHandler(), 4, 29 + 2 * (4 + 18) - 11, 67)); + + addFluidHandlerSlot(new SlotFluidHandler(blockEntity.getFluidHandler(), 0, 80, 20, 20, 20)); + addFluidHandlerSlot(new SlotFluidHandler(blockEntity.getSecondaryFluidHandler(), 0, 80, 60, 20, 20)); } @Override diff --git a/src/main/java/com/portingdeadmods/nautec/utils/RNGUtils.java b/src/main/java/com/portingdeadmods/nautec/utils/RNGUtils.java index 2ab417c4..4eb10c60 100644 --- a/src/main/java/com/portingdeadmods/nautec/utils/RNGUtils.java +++ b/src/main/java/com/portingdeadmods/nautec/utils/RNGUtils.java @@ -1,10 +1,17 @@ package com.portingdeadmods.nautec.utils; +import com.portingdeadmods.nautec.utils.ranges.FloatRange; +import com.portingdeadmods.nautec.utils.ranges.IntRange; + public final class RNGUtils { public static float random() { return (float) Math.random(); } + public static int uniformRandInt(IntRange range) { + return uniformRandInt(range.getMin(), range.getMax()); + } + public static int uniformRandInt(int min, int max) { return (int) (Math.random() * (max - min + 1) + min); } @@ -13,6 +20,10 @@ public static int uniformRandInt(int max) { return uniformRandInt(0, max); } + public static float uniformRandFloat(FloatRange range) { + return uniformRandFloat(range.getMin(), range.getMax()); + } + public static float uniformRandFloat(float min, float max) { return (float) Math.random() * (max - min) + min; } diff --git a/src/main/java/com/portingdeadmods/nautec/utils/ranges/AbstractRange.java b/src/main/java/com/portingdeadmods/nautec/utils/ranges/AbstractRange.java new file mode 100644 index 00000000..012cdc92 --- /dev/null +++ b/src/main/java/com/portingdeadmods/nautec/utils/ranges/AbstractRange.java @@ -0,0 +1,56 @@ +package com.portingdeadmods.nautec.utils.ranges; + +import com.mojang.serialization.Codec; +import com.mojang.serialization.MapCodec; +import com.mojang.serialization.codecs.RecordCodecBuilder; +import io.netty.buffer.ByteBuf; +import net.minecraft.network.RegistryFriendlyByteBuf; +import net.minecraft.network.codec.ByteBufCodecs; +import net.minecraft.network.codec.StreamCodec; + +import java.util.Collection; +import java.util.function.BiFunction; + +public abstract class AbstractRange { + private final T min; + private final T max; + private final Collection possibleValues; + + protected AbstractRange(T minInclusive, T maxInclusive) { + this.min = minInclusive; + this.max = maxInclusive; + this.possibleValues = collectPossibleValues(); + } + + public T getMin() { + return min; + } + + public T getMax() { + return max; + } + + public Collection getPossibleValues() { + return possibleValues; + } + + protected abstract Collection collectPossibleValues(); + + // Constructs a pair out of the range and uses that for encoding + public static > MapCodec rangeMapCodec(Codec codec, BiFunction constructor) { + return RecordCodecBuilder.mapCodec(instance -> instance.group( + codec.fieldOf("min").forGetter(SELF::getMin), + codec.fieldOf("max").forGetter(SELF::getMax) + ).apply(instance, constructor)); + } + + public static >StreamCodec rangeStreamCodec(StreamCodec streamCodec, BiFunction constructor) { + return StreamCodec.composite( + streamCodec, + SELF::getMin, + streamCodec, + SELF::getMax, + constructor + ); + } +} diff --git a/src/main/java/com/portingdeadmods/nautec/utils/ranges/FloatRange.java b/src/main/java/com/portingdeadmods/nautec/utils/ranges/FloatRange.java new file mode 100644 index 00000000..4db3b0e1 --- /dev/null +++ b/src/main/java/com/portingdeadmods/nautec/utils/ranges/FloatRange.java @@ -0,0 +1,37 @@ +package com.portingdeadmods.nautec.utils.ranges; + +import com.google.common.collect.ImmutableList; +import com.mojang.serialization.Codec; +import com.mojang.serialization.MapCodec; +import it.unimi.dsi.fastutil.floats.FloatArrayList; +import it.unimi.dsi.fastutil.floats.FloatList; +import it.unimi.dsi.fastutil.ints.IntArrayList; +import it.unimi.dsi.fastutil.ints.IntList; +import net.minecraft.network.RegistryFriendlyByteBuf; +import net.minecraft.network.codec.ByteBufCodecs; +import net.minecraft.network.codec.StreamCodec; + +import java.util.Collection; +import java.util.List; + +public class FloatRange extends AbstractRange{ + public static final MapCodec MAP_CODEC = rangeMapCodec(Codec.FLOAT, FloatRange::new); + public static final StreamCodec STREAM_CODEC = rangeStreamCodec(ByteBufCodecs.FLOAT, FloatRange::new); + + protected FloatRange(Float minInclusive, Float maxInclusive) { + super(minInclusive, maxInclusive); + } + + @Override + protected Collection collectPossibleValues() { + FloatList values = new FloatArrayList((int) Math.abs(getMax() - getMin()) + 1); + for (float i = getMin(); i < getMax(); i++) { + values.add(i); + } + return ImmutableList.copyOf(values); + } + + public static FloatRange of(float min, float max) { + return new FloatRange(min, max); + } +} diff --git a/src/main/java/com/portingdeadmods/nautec/utils/ranges/IntRange.java b/src/main/java/com/portingdeadmods/nautec/utils/ranges/IntRange.java new file mode 100644 index 00000000..6d67bb1d --- /dev/null +++ b/src/main/java/com/portingdeadmods/nautec/utils/ranges/IntRange.java @@ -0,0 +1,34 @@ +package com.portingdeadmods.nautec.utils.ranges; + +import com.google.common.collect.ImmutableList; +import com.mojang.serialization.Codec; +import com.mojang.serialization.MapCodec; +import it.unimi.dsi.fastutil.ints.IntArrayList; +import it.unimi.dsi.fastutil.ints.IntList; +import net.minecraft.network.RegistryFriendlyByteBuf; +import net.minecraft.network.codec.ByteBufCodecs; +import net.minecraft.network.codec.StreamCodec; + +import java.util.Collection; + +public class IntRange extends AbstractRange { + public static final MapCodec MAP_CODEC = rangeMapCodec(Codec.INT, IntRange::new); + public static final StreamCodec STREAM_CODEC = rangeStreamCodec(ByteBufCodecs.INT, IntRange::new); + + protected IntRange(Integer min, Integer max) { + super(min, max); + } + + @Override + protected Collection collectPossibleValues() { + IntList values = new IntArrayList(Math.abs(getMax() - getMin()) + 1); + for (int i = getMin(); i < getMax(); i++) { + values.add(i); + } + return ImmutableList.copyOf(values); + } + + public static IntRange of(int min, int max) { + return new IntRange(min, max); + } +} diff --git a/src/main/resources/assets/nautec/textures/gui/bio_reactor.png b/src/main/resources/assets/nautec/textures/gui/bio_reactor.png index 75e4d934..9a5132cd 100644 Binary files a/src/main/resources/assets/nautec/textures/gui/bio_reactor.png and b/src/main/resources/assets/nautec/textures/gui/bio_reactor.png differ