How to add new Moderators and explaining how they are defined.
The Basics
Moderators change or modify the values provided by fuel rods. You do not need to have any of these for a reactor to run, but they are recommended.
If you are a kubejs dev who merely needs to know how to add new Moderators, only the first two sections of this page will be useful.
StartupEvents.registry("block", event => {
event.create('niobium_modified_silicon_carbide_moderator', 'phoenixcore:fission_moderator')
.displayName('Nb-SiC Moderator')
.EUBoost(15) // Handles how much each moderator boosts eu generation.
.fuelDiscount(5) // Improves efficiency of fuels by extending time between each use.
.tier(4) // Used for explosion scaling + primary-moderator selection.
.moderatorMaterial(() => GTMaterials.get('niobium_modified_silicon_carbide')) // Used for some internal names.
.texture('kubejs:block/fission/niobium_sic_moderator');
// Moderators don’t require an active texture.
});
Understanding how to actually use the moderators
These blocks are designed to complement the fuel rods as stated above. It is best to design moderators around certain fuel rods, rather than fuel rods around moderators.
This is where non-linear paths really shine. Unlike the other components, moderator values are not tied togethor. You can mix and match any values here.
For example, you could make a moderator that gives a big eu boost but adds so little fuel discount that it isn't really worth it.
Or you could give one a big tier, adding a lot more parallel and risk in the explosion, and has good fuel discount but a quite bad eu boost.
Understanding the classes
Now, back to talking about Moderator Blocks.
They are registered in two parts, an interface named IFissionModeratorType and a block class named FissionModeratorBlock.
package net.phoenix.core.integration.phoenix_fission.api.block;
import com.gregtechceu.gtceu.api.data.chemical.material.Material;
import com.gregtechceu.gtceu.common.data.GTMaterials;
import net.minecraft.resources.ResourceLocation;
import net.minecraftforge.common.util.Lazy;
import net.phoenix.core.PhoenixAPI;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Arrays;
import java.util.Comparator;
public interface IFissionModeratorType {
@NotNull
String getName();
default int getTintColor() {
return 0xFFFFFFFF;
}
int getEUBoost();
int getFuelDiscount();
default double getHeatMultiplier() {
return getTier() * 0.5;
}
default int getParallelBonus() {
return getTier();
}
int getTier();
ResourceLocation getTexture();
Material getMaterial();
Lazy<IFissionModeratorType[]> ALL_FISSION_MODERATORS_SORTED = Lazy
.of(() -> PhoenixAPI.FISSION_MODERATORS.keySet().stream()
.sorted(Comparator.comparingInt(IFissionModeratorType::getFuelDiscount))
.toArray(IFissionModeratorType[]::new));
@Nullable
static IFissionModeratorType getMinRequiredType(int requiredTemperature) {
return Arrays.stream(ALL_FISSION_MODERATORS_SORTED.get())
.filter(moderatorType -> moderatorType.getFuelDiscount() >= requiredTemperature)
.findFirst().orElse(null);
}
}
FissionModeratorBlock and any other classes using the same logic.
getName. This controls the registry name of theModerator Block.getTintColor. Correctly not working attempt atauto tintingblocks, one day it will be real.getEUBoost. This controls the amount ofboosteachModerator Blockapplies to the amount ofEUgiven by a running reactor.getFuelDiscount. This controls the amount offuel discounteachModerator Blockapplies to a running reactor.getHeatMultiplier. This controls the amount ofheat multipliereachModerator Blockapplies to a running reactor.getParallelBonus. This controls the amount ofadded paralleleachModerator Blockapplies to a running reactor.getTier. This handles primaryModerator Blocklogic,parallel bonus, andheat boostperModerator Block. Also contributes toexplosionstrenght.getMaterial. Controls the gtm material linked to it, used for some internal names.
Then, finally, we have the api call. ALL_FISSION_MODERATORS_SORTED is passed to be stored by the PhoenixAPI class. This allows us to pass every class using this interface to the predicate.
package net.phoenix.core.common.block;
import com.gregtechceu.gtceu.api.block.ActiveBlock;
import com.gregtechceu.gtceu.utils.GTUtil;
import net.minecraft.ChatFormatting;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.StringRepresentable;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.TooltipFlag;
import net.minecraft.world.level.BlockGetter;
import net.phoenix.core.PhoenixFission;
import net.phoenix.core.integration.phoenix_fission.api.block.IFissionModeratorType;
import lombok.Getter;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import javax.annotation.ParametersAreNonnullByDefault;
@Getter
@ParametersAreNonnullByDefault
public class FissionModeratorBlock extends ActiveBlock {
private final IFissionModeratorType moderatorType;
public FissionModeratorBlock(Properties properties, IFissionModeratorType moderatorType) {
super(properties);
this.moderatorType = moderatorType;
}
@Override
public void appendHoverText(ItemStack stack, @Nullable BlockGetter level,
List<Component> tooltip, TooltipFlag flag) {
if (!GTUtil.isShiftDown()) {
tooltip.add(Component.translatable("block.phoenix_fission.fission_moderator.shift")
.withStyle(ChatFormatting.GRAY));
return;
}
tooltip.add(Component.translatable("block.phoenix_fission.fission_moderator.info_header"));
tooltip.add(Component.translatable("block.phoenix_fission.fission_moderator.boost",
moderatorType.getEUBoost()));
tooltip.add(Component.translatable("block.phoenix_fission.fission_moderator.fuel_discount",
moderatorType.getFuelDiscount()));
}
public enum FissionModeratorTypes implements StringRepresentable, IFissionModeratorType {
MODERATOR_GRAPHITE(
"graphite_moderator",
1, 3, 1,
PhoenixFission.id("block/fission/graphite_moderator"),
0xFFB07CFF);
@Getter
@NotNull
private final String name;
@Getter
private final int EUBoost;
@Getter
private final int fuelDiscount;
@Getter
private final int tier;
@Getter
@NotNull
private final ResourceLocation texture;
@Getter
private final int tintColor;
FissionModeratorTypes(String name, int EUBoost, int fuelDiscount, int tier,
ResourceLocation texture, int tintColor) {
this.name = name;
this.EUBoost = EUBoost;
this.fuelDiscount = fuelDiscount;
this.tier = tier;
this.texture = texture;
this.tintColor = tintColor;
}
@Override
public @NotNull String getSerializedName() {
return name;
}
@Override
public int getTintColor() {
return tintColor;
}
@Override
public Material getMaterial() {
return GTMaterials.NULL;
}
}
}
For completeness, we will assume you already know how to make active blocks in the gtm api. So we will focus on what makes this actually unique.
Tooltips
Shiftto show the full info, helps to keep inventory cleaner.- The
eu boostof theModerator Block. - The
fuel discountof theModerator Block.
Values
String name. AStringdesigned to hold the registration name of theModerator Block, still needs to follow a-z, 0–9.int EUBoost. Anintdesigned to hold the amount ofeuBoostof theModerator Block.int fuelDiscount. Anintdesigned to hold the amount offuelDiscountof theModerator Block.int tier. Anintdesigned to hold thetierof theModerator Block, handlesprimary moderatorlogic in reactor.int tintColor. Currently, doesn't do anything, just put 0xFFFFFF.