Skip to content

Commit

Permalink
Restructure Configs and add support for NeoForge's Config GUI (#8166)
Browse files Browse the repository at this point in the history
- Adds support for editing our configs using the config GUI, and for translating their contents. #5794
- Restructure organization of entries within individual config files. This unfortunately will cause all configs to get reset as I removed a parent level node in order to make the config GUI easier to navigate.
- Fixes Mekanism's Additions description translation not being used in game
- Flip Mekanism Addition's voice key is toggle config to a push to talk config option. (Same default behavior, just is a bit better of a name)
- Slightly lowered the default `dumpExcessKeepRatio` config value (from `0.9` to `0.85`)
  • Loading branch information
pupnewfster authored Aug 23, 2024
1 parent 710d867 commit a11d886
Show file tree
Hide file tree
Showing 126 changed files with 7,328 additions and 1,164 deletions.
14 changes: 11 additions & 3 deletions src/additions/java/mekanism/additions/client/AdditionsClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,26 @@
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import mekanism.additions.client.voice.VoiceClient;
import mekanism.additions.common.MekanismAdditions;
import mekanism.additions.common.config.MekanismAdditionsConfig;
import mekanism.common.Mekanism;
import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.ClientPacketListener;
import net.neoforged.api.distmarker.Dist;
import net.neoforged.fml.ModContainer;
import net.neoforged.fml.common.Mod;
import net.neoforged.neoforge.client.gui.ConfigurationScreen;
import net.neoforged.neoforge.client.gui.IConfigScreenFactory;

@Mod(value = MekanismAdditions.MODID, dist = Dist.CLIENT)
public class AdditionsClient {

private AdditionsClient() {
}

private static VoiceClient voiceClient;

public AdditionsClient(ModContainer container) {
container.registerExtensionPoint(IConfigScreenFactory.class, ConfigurationScreen::new);
}

public static void reset() {
if (voiceClient != null) {
voiceClient.disconnect();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
public class AdditionsKeyHandler {

public static final KeyMapping voiceKey = new MekKeyBindingBuilder().description(AdditionsLang.KEY_VOICE).keyCode(GLFW.GLFW_KEY_U)
.toggleable(MekanismAdditionsConfig.client.voiceKeyIsToggle::getOrDefault).build();
.toggleable(() -> !MekanismAdditionsConfig.client.pushToTalk.getOrDefault()).build();

public static void registerKeybindings(RegisterKeyMappingsEvent event) {
ClientRegistrationUtil.registerKeyBindings(event, voiceKey);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,14 @@ public class AdditionsClientConfig extends BaseMekanismConfig {

private final ModConfigSpec configSpec;

public final CachedBooleanValue voiceKeyIsToggle;
public final CachedBooleanValue pushToTalk;

AdditionsClientConfig() {
ModConfigSpec.Builder builder = new ModConfigSpec.Builder();
builder.comment("Mekanism Additions Client Config. This config only exists on the client.").push("additions-client");

voiceKeyIsToggle = CachedBooleanValue.wrap(this, builder.comment("If the voice server is enabled and voiceKeyIsToggle is also enabled, the voice key will "
+ "act as a toggle instead of requiring to be held while talking.")
.define("voiceKeyIsToggle", false));
builder.pop();
pushToTalk = CachedBooleanValue.wrap(this, AdditionsConfigTranslations.CLIENT_PUSH_TO_TALK.applyToBuilder(builder)
.define("pushToTalk", true));

configSpec = builder.build();
}

Expand All @@ -27,6 +25,11 @@ public String getFileName() {
return "additions-client";
}

@Override
public String getTranslation() {
return "Client Config";
}

@Override
public ModConfigSpec getConfigSpec() {
return configSpec;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
import java.util.EnumMap;
import java.util.List;
import java.util.Map;
import mekanism.additions.common.config.AdditionsConfigTranslations.BabySpawnTranslations;
import mekanism.additions.common.entity.baby.BabyType;
import mekanism.additions.common.registries.AdditionsEntityTypes;
import mekanism.api.functions.ConstantPredicates;
import mekanism.common.config.BaseMekanismConfig;
import mekanism.common.config.IMekanismConfig;
import mekanism.common.config.value.CachedBooleanValue;
Expand All @@ -17,6 +17,7 @@
import net.minecraft.SharedConstants;
import net.minecraft.core.Holder;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.Mth;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.level.biome.MobSpawnSettings;
Expand All @@ -37,42 +38,51 @@ public class AdditionsConfig extends BaseMekanismConfig {

AdditionsConfig() {
ModConfigSpec.Builder builder = new ModConfigSpec.Builder();
builder.comment("Mekanism Additions Config. This config is synced between server and client.").push("additions");

obsidianTNTDelay = CachedIntValue.wrap(this, builder.comment("Fuse time for Obsidian TNT.")
.defineInRange("obsidianTNTDelay", 5 * SharedConstants.TICKS_PER_SECOND, 0, Integer.MAX_VALUE));
obsidianTNTBlastRadius = CachedFloatValue.wrap(this, builder.comment("Radius of the explosion of Obsidian TNT.")
.defineInRange("obsidianTNTBlastRadius", 12, 0.1, 1_000));
AdditionsConfigTranslations.SERVER_OBSIDIAN_TNT.applyToBuilder(builder).push("obsidian_tnt");
obsidianTNTDelay = CachedIntValue.wrap(this, AdditionsConfigTranslations.SERVER_OBSIDIAN_DELAY.applyToBuilder(builder)
.defineInRange("delay", 5 * SharedConstants.TICKS_PER_SECOND, 0, Integer.MAX_VALUE));
obsidianTNTBlastRadius = CachedFloatValue.wrap(this, AdditionsConfigTranslations.SERVER_OBSIDIAN_RADIUS.applyToBuilder(builder)
.defineInRange("blastRadius", 12, 0.1, 1_000));
builder.pop();

AdditionsConfigTranslations.SERVER_VOICE.applyToBuilder(builder).push("voice_server");
voiceServerEnabled = CachedBooleanValue.wrap(this, AdditionsConfigTranslations.SERVER_VOICE_ENABLED.applyToBuilder(builder)
.worldRestart()
.define("enabled", false));
voicePort = CachedIntValue.wrap(this, AdditionsConfigTranslations.SERVER_VOICE_PORT.applyToBuilder(builder)
.defineInRange("voicePort", 36_123, 1, 65_535));
builder.pop();

AdditionsConfigTranslations.SERVER_BABY.applyToBuilder(builder).push("baby_mobs");
babyArrowDamageMultiplier = CachedDoubleValue.wrap(this, AdditionsConfigTranslations.SERVER_BABY_ARROW_DAMAGE.applyToBuilder(builder)
.defineInRange("arrowDamageMultiplier", 0.25, 0.1, 10));

babyArrowDamageMultiplier = CachedDoubleValue.wrap(this, builder.comment("Damage multiplier of arrows shot by baby mobs.")
.defineInRange("babyArrowDamageMultiplier", 0.25, 0.1, 10));

voiceServerEnabled = CachedBooleanValue.wrap(this, builder.comment("Enables the voice server for Walkie Talkies.").worldRestart()
.define("voiceServerEnabled", false));
voicePort = CachedIntValue.wrap(this, builder.comment("TCP port for the Voice server to listen on.")
.defineInRange("VoicePort", 36_123, 1, 65_535));

builder.comment("Config options regarding spawning of entities.").push("spawning");
addBabyTypeConfig(BabyType.BOGGED, builder, AdditionsEntityTypes.BABY_BOGGED, EntityType.BOGGED);
addBabyTypeConfig(BabyType.CREEPER, builder, AdditionsEntityTypes.BABY_CREEPER, EntityType.CREEPER);
addBabyTypeConfig(BabyType.ENDERMAN, builder, AdditionsEntityTypes.BABY_ENDERMAN, EntityType.ENDERMAN);
addBabyTypeConfig(BabyType.SKELETON, builder, AdditionsEntityTypes.BABY_SKELETON, EntityType.SKELETON);
addBabyTypeConfig(BabyType.STRAY, builder, AdditionsEntityTypes.BABY_STRAY, EntityType.STRAY);
addBabyTypeConfig(BabyType.WITHER_SKELETON, builder, AdditionsEntityTypes.BABY_WITHER_SKELETON, EntityType.WITHER_SKELETON);
builder.pop(2);
builder.pop();

configSpec = builder.build();
}

private void addBabyTypeConfig(BabyType type, ModConfigSpec.Builder builder, Holder<EntityType<?>> entityTypeProvider, EntityType<?> parentType) {
spawnConfigs.put(type, new SpawnConfig(this, builder, "baby " + type.getSerializedName().replace('_', ' '),
entityTypeProvider, parentType));
spawnConfigs.put(type, new SpawnConfig(this, builder, "baby_" + type.getSerializedName(), entityTypeProvider, parentType));
}

@Override
public String getFileName() {
return "additions";
}

@Override
public String getTranslation() {
return "General Config";
}

@Override
public ModConfigSpec getConfigSpec() {
return configSpec;
Expand All @@ -90,9 +100,9 @@ public SpawnConfig getConfig(BabyType babyType) {
public static class SpawnConfig {

public final CachedBooleanValue shouldSpawn;
public final CachedDoubleValue weightPercentage;
public final CachedDoubleValue minSizePercentage;
public final CachedDoubleValue maxSizePercentage;
public final CachedDoubleValue weightPercentage;
public final CachedDoubleValue spawnCostPerEntityPercentage;
public final CachedDoubleValue maxSpawnCostPercentage;
public final CachedResourceLocationListValue biomeBlackList;
Expand All @@ -103,29 +113,31 @@ public static class SpawnConfig {
private SpawnConfig(IMekanismConfig config, ModConfigSpec.Builder builder, String name, Holder<EntityType<?>> entityType, EntityType<?> parentType) {
this.entityType = entityType;
this.parentType = parentType;
builder.comment("Config options regarding " + name + ".").push(name.replace(" ", "-"));
this.shouldSpawn = CachedBooleanValue.wrap(config, builder.comment("Enable the spawning of " + name + ". Think baby zombies.")
BabySpawnTranslations translations = BabySpawnTranslations.create(name);

translations.topLevel().applyToBuilder(builder).push(name);
this.shouldSpawn = CachedBooleanValue.wrap(config, translations.shouldSpawn().applyToBuilder(builder)
.worldRestart()
.define("shouldSpawn", true));
this.weightPercentage = CachedDoubleValue.wrap(config, builder.comment("The multiplier for weight of " + name + " spawns, compared to the adult mob.")
.worldRestart()
.defineInRange("weightPercentage", 0.05, 0, 100));
this.minSizePercentage = CachedDoubleValue.wrap(config, builder.comment("The multiplier for minimum group size of " + name + " spawns, compared to the adult mob.")
this.minSizePercentage = CachedDoubleValue.wrap(config, translations.minSize().applyToBuilder(builder)
.worldRestart()
.defineInRange("minSizePercentage", 0.5, 0, 100));
this.maxSizePercentage = CachedDoubleValue.wrap(config, builder.comment("The multiplier for maximum group size of " + name + " spawns, compared to the adult mob.")
this.maxSizePercentage = CachedDoubleValue.wrap(config, translations.maxSize().applyToBuilder(builder)
.worldRestart()
.defineInRange("maxSizePercentage", 0.5, 0, 100));
this.spawnCostPerEntityPercentage = CachedDoubleValue.wrap(config, builder.comment("The multiplier for spawn cost per entity of " + name + " spawns, compared to the adult mob.")
this.weightPercentage = CachedDoubleValue.wrap(config, translations.weight().applyToBuilder(builder)
.worldRestart()
.defineInRange("weightPercentage", 0.05, 0, 100));
this.spawnCostPerEntityPercentage = CachedDoubleValue.wrap(config, translations.costPerEntity().applyToBuilder(builder)
.worldRestart()
.defineInRange("spawnCostPerEntityPercentage", 1D, 0, 100));
this.maxSpawnCostPercentage = CachedDoubleValue.wrap(config, builder.comment("The multiplier for max spawn cost of " + name + " spawns, compared to the adult mob.")
this.maxSpawnCostPercentage = CachedDoubleValue.wrap(config, translations.maxCost().applyToBuilder(builder)
.worldRestart()
.defineInRange("maxSpawnCostPercentage", 1D, 0, 100));
this.biomeBlackList = CachedResourceLocationListValue.define(config, builder.comment("The list of biome ids that " + name + " will not spawn in even if the normal mob variant can spawn.")
.worldRestart(), "biomeBlackList", ConstantPredicates.alwaysTrue());
this.structureBlackList = CachedResourceLocationListValue.define(config, builder.comment("The list of structure ids that " + name + " will not spawn in even if the normal mob variant can spawn.")
.worldRestart(), "structureBlackList", BuiltInRegistries.STRUCTURE_TYPE::containsKey);
this.biomeBlackList = CachedResourceLocationListValue.define(config, translations.biomeBlacklist().applyToBuilder(builder)
.worldRestart(), "biomeBlackList", ResourceLocation.withDefaultNamespace("plains"));
this.structureBlackList = CachedResourceLocationListValue.define(config, translations.structureBlacklist().applyToBuilder(builder)
.worldRestart(), "structureBlackList", ResourceLocation.withDefaultNamespace("fortress"), BuiltInRegistries.STRUCTURE_TYPE::containsKey);
builder.pop();
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
package mekanism.additions.common.config;

import mekanism.additions.common.MekanismAdditions;
import mekanism.common.config.IConfigTranslation;
import mekanism.common.util.text.TextUtils;
import net.minecraft.Util;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

public enum AdditionsConfigTranslations implements IConfigTranslation {
//Client Config
CLIENT_PUSH_TO_TALK("client.push_to_talk", "Push to Talk",
"If the voice server is enabled and pushToTalk is disabled, the voice key will act as a toggle instead of requiring to be held while talking."),

//Server config
SERVER_OBSIDIAN_TNT("server.obsidian_tnt", "Obsidian TNT", "Settings for configuring Obsidian TNT", true),
SERVER_OBSIDIAN_DELAY("server.obsidian_tnt.delay", "Fuse Time", "Fuse time in ticks for Obsidian TNT. Vanilla TNT has a fuse of 80 ticks (4 seconds)."),
SERVER_OBSIDIAN_RADIUS("server.obsidian_tnt.radius", "Radius", "Radius of the explosion of Obsidian TNT. Vanilla TNT has a radius of 4."),

SERVER_VOICE("server.voice", "Voice Server", "Settings for configuring the Voice Server", true),
SERVER_VOICE_ENABLED("server.voice.enabled", "Enabled", "Enables the voice server for Walkie Talkies."),
SERVER_VOICE_PORT("server.voice.port", "TCP Port", "TCP port for the Voice server to listen on."),

SERVER_BABY("server.baby", "Baby Mobs", "Settings for configuring values relating to baby mobs", true),
SERVER_BABY_ARROW_DAMAGE("server.baby.arrow_damage_multiplier", "Arrow Damage Multiplier", "Damage multiplier of arrows shot by baby mobs."),

;

private final String key;
private final String title;
private final String tooltip;
@Nullable
private final String button;

AdditionsConfigTranslations(String path, String title, String tooltip) {
this(path, title, tooltip, false);
}

AdditionsConfigTranslations(String path, String title, String tooltip, boolean isSection) {
this(path, title, tooltip, IConfigTranslation.getSectionTitle(title, isSection));
}

AdditionsConfigTranslations(String path, String title, String tooltip, @Nullable String button) {
this.key = Util.makeDescriptionId("configuration", MekanismAdditions.rl(path));
this.title = title;
this.tooltip = tooltip;
this.button = button;
}

@NotNull
@Override
public String getTranslationKey() {
return key;
}

@Override
public String title() {
return title;
}

@Override
public String tooltip() {
return tooltip;
}

@Nullable
@Override
public String button() {
return button;
}

public record BabySpawnTranslations(
IConfigTranslation topLevel,
IConfigTranslation shouldSpawn,
IConfigTranslation minSize,
IConfigTranslation maxSize,
IConfigTranslation weight,
IConfigTranslation costPerEntity,
IConfigTranslation maxCost,
IConfigTranslation biomeBlacklist,
IConfigTranslation structureBlacklist
) {

public IConfigTranslation[] toArray() {
return new IConfigTranslation[]{topLevel, shouldSpawn, minSize, maxSize, weight, costPerEntity, maxCost, biomeBlacklist, structureBlacklist};
}

private static String getKey(String name, String path) {
return Util.makeDescriptionId("configuration", MekanismAdditions.rl("server.baby.spawning." + name + "." + path));
}

public static BabySpawnTranslations create(String key) {
String name = TextUtils.formatAndCapitalize(key);
return new BabySpawnTranslations(
new ConfigTranslation(getKey(key, "top_level"), name, "Config options regarding the spawning of " + name + ".", "Edit Spawn Settings"),
new ConfigTranslation(getKey(key, "should_spawn"), "Should Spawn", "Enable the spawning of " + name + ". Think baby zombies."),
new ConfigTranslation(getKey(key, "min_size"), "Min Group Size", "The multiplier for minimum group size of " + name + " spawns, compared to the adult mob."),
new ConfigTranslation(getKey(key, "max_size"), "Max Group Size", "The multiplier for maximum group size of " + name + " spawns, compared to the adult mob."),
new ConfigTranslation(getKey(key, "weight"), "Weight Multiplier", "The multiplier for weight of " + name + " spawns, compared to the adult mob."),
new ConfigTranslation(getKey(key, "cost_per_entity"), "Cost Per Entity Multiplier", "The multiplier for spawn cost per entity of " + name + " spawns, compared to the adult mob."),
new ConfigTranslation(getKey(key, "max_cost"), "Max Cost Multiplier", "The multiplier for max spawn cost of " + name + " spawns, compared to the adult mob."),
new ConfigTranslation(getKey(key, "biome_blacklist"),
"Biome Blacklist", "The list of biome ids that " + name + " will not spawn in even if the normal mob variant can spawn.",
"Edit Blacklist"
),
new ConfigTranslation(getKey(key, "structure_blacklist"), "Structure Blacklist",
"The list of structure ids that " + name + " will not spawn in even if the normal mob variant can spawn.",
"Edit Blacklist"
)
);
}

}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package mekanism.additions.common.config;

import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import mekanism.additions.common.MekanismAdditions;
Expand All @@ -26,4 +28,8 @@ public static void registerConfigs(ModContainer modContainer) {
public static void onConfigLoad(ModConfigEvent configEvent) {
MekanismConfigHelper.onConfigLoad(configEvent, MekanismAdditions.MODID, KNOWN_CONFIGS);
}

public static Collection<IMekanismConfig> getConfigs() {
return Collections.unmodifiableCollection(KNOWN_CONFIGS.values());
}
}
2 changes: 1 addition & 1 deletion src/additions/resources/META-INF/neoforge.mods.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ license="MIT"
authors="Aidancbrady, Thommy101, Thiakil, pupnewfster, dizzyd"
credits="unpairedbracket, CyanideX, Ridanisaurus and many others"
logoFile="logo.png"
description='''Additions module for Mekanism, contains things that don't quite fit in the other modules.'''
description='''Additions module for Mekanism, contains miscellaneous things that do not thematically fit in the other modules.'''

[[dependencies.mekanismadditions]]
modId="mekanism"
Expand Down
4 changes: 2 additions & 2 deletions src/api/java/mekanism/api/RelativeSide.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import java.util.function.IntFunction;
import mekanism.api.annotations.NothingNullByDefault;
import mekanism.api.text.APILang;
import mekanism.api.text.IHasTranslationKey;
import mekanism.api.text.IHasTranslationKey.IHasEnumNameTranslationKey;
import mekanism.api.text.ILangEntry;
import net.minecraft.core.Direction;
import net.minecraft.network.codec.ByteBufCodecs;
Expand All @@ -15,7 +15,7 @@
import net.minecraft.util.StringRepresentable;

@NothingNullByDefault
public enum RelativeSide implements IHasTranslationKey, StringRepresentable {
public enum RelativeSide implements IHasEnumNameTranslationKey, StringRepresentable {
FRONT(APILang.FRONT),
LEFT(APILang.LEFT),
RIGHT(APILang.RIGHT),
Expand Down
Loading

0 comments on commit a11d886

Please sign in to comment.