Unknown hace 5 años
padre
commit
b288ff9bf9
Se han modificado 23 ficheros con 455 adiciones y 103 borrados
  1. 1 1
      gradle.properties
  2. 25 21
      src/main/java/me/shedaniel/clothconfig2/ClothConfigInitializer.java
  3. 3 1
      src/main/java/me/shedaniel/clothconfig2/api/ConfigBuilder.java
  4. 2 0
      src/main/java/me/shedaniel/clothconfig2/api/ConfigEntryBuilder.java
  5. 0 6
      src/main/java/me/shedaniel/clothconfig2/impl/ConfigBuilderImpl.java
  6. 1 1
      src/main/java/me/shedaniel/clothconfig2/impl/ConfigCategoryImpl.java
  7. 14 0
      src/main/java/me/shedaniel/clothconfig2/impl/ConfigEntryBuilderImpl.java
  8. 12 5
      src/main/java/me/shedaniel/clothconfig2/impl/builders/BooleanToggleBuilder.java
  9. 12 5
      src/main/java/me/shedaniel/clothconfig2/impl/builders/DoubleFieldBuilder.java
  10. 46 5
      src/main/java/me/shedaniel/clothconfig2/impl/builders/DoubleListBuilder.java
  11. 12 5
      src/main/java/me/shedaniel/clothconfig2/impl/builders/EnumSelectorBuilder.java
  12. 12 5
      src/main/java/me/shedaniel/clothconfig2/impl/builders/FloatFieldBuilder.java
  13. 45 4
      src/main/java/me/shedaniel/clothconfig2/impl/builders/FloatListBuilder.java
  14. 12 5
      src/main/java/me/shedaniel/clothconfig2/impl/builders/IntFieldBuilder.java
  15. 46 5
      src/main/java/me/shedaniel/clothconfig2/impl/builders/IntListBuilder.java
  16. 14 7
      src/main/java/me/shedaniel/clothconfig2/impl/builders/IntSliderBuilder.java
  17. 11 4
      src/main/java/me/shedaniel/clothconfig2/impl/builders/LongFieldBuilder.java
  18. 45 4
      src/main/java/me/shedaniel/clothconfig2/impl/builders/LongListBuilder.java
  19. 15 7
      src/main/java/me/shedaniel/clothconfig2/impl/builders/LongSliderBuilder.java
  20. 70 0
      src/main/java/me/shedaniel/clothconfig2/impl/builders/StringFieldBuilder.java
  21. 35 4
      src/main/java/me/shedaniel/clothconfig2/impl/builders/StringListBuilder.java
  22. 10 4
      src/main/java/me/shedaniel/clothconfig2/impl/builders/SubCategoryBuilder.java
  23. 12 4
      src/main/java/me/shedaniel/clothconfig2/impl/builders/TextFieldBuilder.java

+ 1 - 1
gradle.properties

@@ -2,5 +2,5 @@ minecraft_version=1.14.2
 yarn_version=1.14.2+build.2
 fabric_loader_version=0.4.7+build.147
 fabric_version=0.3.0-pre+build.165
-mod_version=0.4.3
+mod_version=0.5.0
 modmenu_version=1.7.6+build.115

+ 25 - 21
src/main/java/me/shedaniel/clothconfig2/ClothConfigInitializer.java

@@ -27,27 +27,31 @@ public class ClothConfigInitializer implements ClientModInitializer {
                 Class<?> clazz = Class.forName("io.github.prospector.modmenu.api.ModMenuApi");
                 Method method = clazz.getMethod("addConfigOverride", String.class, Runnable.class);
                 method.invoke(null, "cloth-config2", (Runnable) () -> {
-                    ConfigBuilder builder = ConfigBuilder.create().setParentScreen(MinecraftClient.getInstance().currentScreen).setTitle("Cloth Mod Config Demo");
-                    builder.setDefaultBackgroundTexture(new Identifier("minecraft:textures/block/oak_planks.png"));
-                    ConfigCategory playZone = builder.getOrCreateCategory("Play Zone");
-                    ConfigEntryBuilder entryBuilder = ConfigEntryBuilder.create();
-                    playZone.addEntry(entryBuilder.startBooleanToggle("Simple Boolean", false).buildEntry());
-                    playZone.addEntry(entryBuilder.startTextField("Simple Boolean", "ab").setDefaultValue(() -> "ab").buildEntry());
-                    playZone.addEntry(entryBuilder.startLongSlider("Long Slider", 0, -10, 10).setDefaultValue(() -> 0l).buildEntry());
-                    playZone.addEntry(entryBuilder.startIntList("Int List", Arrays.asList(1, 6, 14, 1414)).setTooltip("this is a bad tooltip").setSaveConsumer(integers -> integers.forEach(System.out::println)).setDefaultValue(Arrays.asList(1, 6, 14, 1414)).build());
-                    playZone.addEntry(entryBuilder.startStrList("Party Member List", Arrays.asList("Tim", "Daniel", "John")).setTooltip("A list of party members.").setDefaultValue(Arrays.asList("Tim", "Daniel", "John")).build());
-                    playZone.addEntry(entryBuilder.startIntField("Integer Field", 2).setDefaultValue(() -> 2).setMin(2).setMax(99).buildEntry());
-                    SubCategoryBuilder randomCategory = entryBuilder.startSubCategory("Random Sub-Category");
-                    randomCategory.add(entryBuilder.startTextDescription("§7This is a promotional message brought to you by Danielshe. Shop your favorite Lil Tater at store.liltater.com!").setTooltipSupplier(() -> Optional.of(new String[]{"This is an example tooltip."})).buildEntry());
-                    randomCategory.add(entryBuilder.startSubCategory("Sub-Sub-Category", ImmutableList.of(entryBuilder.startEnumSelector("Enum Field No. 1", DemoEnum.class, DemoEnum.CONSTANT_2).setDefaultValue(() -> DemoEnum.CONSTANT_1).buildEntry(), entryBuilder.startEnumSelector("Enum Field No. 2", DemoEnum.class, DemoEnum.CONSTANT_2).setDefaultValue(() -> DemoEnum.CONSTANT_1).buildEntry())).buildEntry());
-                    for(int i = 0; i < 10; i++)
-                        randomCategory.add(entryBuilder.startIntSlider("Integer Slider No. " + (i + 1), 0, -99, 99).buildEntry());
-                    playZone.addEntry(randomCategory.buildEntry());
-                    ConfigCategory enumZone = builder.getOrCreateCategory("Enum Zone");
-                    enumZone.setCategoryBackground(new Identifier("minecraft:textures/block/stone.png"));
-                    enumZone.addEntry(entryBuilder.startEnumSelector("Enum Field", DemoEnum.class, DemoEnum.CONSTANT_2).setDefaultValue(() -> DemoEnum.CONSTANT_1).buildEntry());
-                    ConfigCategory partyZone = builder.getOrCreateCategory("Party Zone");
-                    MinecraftClient.getInstance().openScreen(builder.build());
+                    try {
+                        ConfigBuilder builder = ConfigBuilder.create().setParentScreen(MinecraftClient.getInstance().currentScreen).setTitle("Cloth Mod Config Demo");
+                        builder.setDefaultBackgroundTexture(new Identifier("minecraft:textures/block/oak_planks.png"));
+                        ConfigCategory playZone = builder.getOrCreateCategory("Play Zone");
+                        ConfigEntryBuilder entryBuilder = ConfigEntryBuilder.create();
+                        playZone.addEntry(entryBuilder.startBooleanToggle("Simple Boolean", false).buildEntry());
+                        playZone.addEntry(entryBuilder.startStrField("Simple Boolean", "ab").setDefaultValue(() -> "ab").buildEntry());
+                        playZone.addEntry(entryBuilder.startLongSlider("Long Slider", 0, -10, 10).setDefaultValue(() -> 0l).buildEntry());
+                        playZone.addEntry(entryBuilder.startIntList("Int List", Arrays.asList(1, 6, 14, 1414)).setTooltip("this is a bad tooltip").setSaveConsumer(integers -> integers.forEach(System.out::println)).setDefaultValue(Arrays.asList(1, 6, 14, 1414)).build());
+                        playZone.addEntry(entryBuilder.startStrList("Party Member List", Arrays.asList("Tim", "Daniel", "John")).setTooltip("A list of party members.").setDefaultValue(Arrays.asList("Tim", "Daniel", "John")).build());
+                        playZone.addEntry(entryBuilder.startIntField("Integer Field", 2).setDefaultValue(() -> 2).setMin(2).setMax(99).buildEntry());
+                        SubCategoryBuilder randomCategory = entryBuilder.startSubCategory("Random Sub-Category");
+                        randomCategory.add(entryBuilder.startTextDescription("§7This is a promotional message brought to you by Danielshe. Shop your favorite Lil Tater at store.liltater.com!").setTooltipSupplier(() -> Optional.of(new String[]{"This is an example tooltip."})).buildEntry());
+                        randomCategory.add(entryBuilder.startSubCategory("Sub-Sub-Category", ImmutableList.of(entryBuilder.startEnumSelector("Enum Field No. 1", DemoEnum.class, DemoEnum.CONSTANT_2).setDefaultValue(() -> DemoEnum.CONSTANT_1).buildEntry(), entryBuilder.startEnumSelector("Enum Field No. 2", DemoEnum.class, DemoEnum.CONSTANT_2).setDefaultValue(() -> DemoEnum.CONSTANT_1).buildEntry())).buildEntry());
+                        for(int i = 0; i < 10; i++)
+                            randomCategory.add(entryBuilder.startIntSlider("Integer Slider No. " + (i + 1), 0, -99, 99).buildEntry());
+                        playZone.addEntry(randomCategory.buildEntry());
+                        ConfigCategory enumZone = builder.getOrCreateCategory("Enum Zone");
+                        enumZone.setCategoryBackground(new Identifier("minecraft:textures/block/stone.png"));
+                        enumZone.addEntry(entryBuilder.startEnumSelector("Enum Field", DemoEnum.class, DemoEnum.CONSTANT_2).setDefaultValue(() -> DemoEnum.CONSTANT_1).buildEntry());
+                        ConfigCategory partyZone = builder.getOrCreateCategory("Party Zone");
+                        MinecraftClient.getInstance().openScreen(builder.build());
+                    } catch (Throwable throwable) {
+                        throwable.printStackTrace();
+                    }
                 });
             } catch (Exception e) {
                 ClothConfigInitializer.LOGGER.error("[ClothConfig] Failed to add test config override for ModMenu!", e);

+ 3 - 1
src/main/java/me/shedaniel/clothconfig2/api/ConfigBuilder.java

@@ -70,7 +70,9 @@ public interface ConfigBuilder {
     
     ConfigBuilder setAfterInitConsumer(Consumer<Screen> afterInitConsumer);
     
-    ConfigEntryBuilderImpl getEntryBuilder();
+    default ConfigEntryBuilderImpl getEntryBuilder() {
+        return ConfigEntryBuilderImpl.create();
+    }
     
     Screen build();
     

+ 2 - 0
src/main/java/me/shedaniel/clothconfig2/api/ConfigEntryBuilder.java

@@ -31,6 +31,8 @@ public interface ConfigEntryBuilder {
     
     BooleanToggleBuilder startBooleanToggle(String fieldNameKey, boolean value);
     
+    StringFieldBuilder startStrField(String fieldNameKey, String value);
+    
     TextFieldBuilder startTextField(String fieldNameKey, String value);
     
     TextDescriptionBuilder startTextDescription(String value);

+ 0 - 6
src/main/java/me/shedaniel/clothconfig2/impl/ConfigBuilderImpl.java

@@ -29,18 +29,12 @@ public class ConfigBuilderImpl implements ConfigBuilder {
     private Consumer<Screen> afterInitConsumer = screen -> {};
     private Map<String, Identifier> categoryBackground = Maps.newHashMap();
     private Map<String, List<Pair<String, Object>>> dataMap = Maps.newLinkedHashMap();
-    private ConfigEntryBuilderImpl entryBuilder = ConfigEntryBuilderImpl.create();
     
     @Deprecated
     public ConfigBuilderImpl() {
     
     }
     
-    @Override
-    public ConfigEntryBuilderImpl getEntryBuilder() {
-        return entryBuilder;
-    }
-    
     @Override
     public ConfigBuilder setAfterInitConsumer(Consumer<Screen> afterInitConsumer) {
         this.afterInitConsumer = afterInitConsumer;

+ 1 - 1
src/main/java/me/shedaniel/clothconfig2/impl/ConfigCategoryImpl.java

@@ -15,7 +15,7 @@ public class ConfigCategoryImpl implements ConfigCategory {
     private Supplier<List<Pair<String, Object>>> listSupplier;
     private Consumer<Identifier> backgroundConsumer;
     
-    public ConfigCategoryImpl(Consumer<Identifier> backgroundConsumer, Supplier<List<Pair<String, Object>>> listSupplier) {
+    ConfigCategoryImpl(Consumer<Identifier> backgroundConsumer, Supplier<List<Pair<String, Object>>> listSupplier) {
         this.listSupplier = listSupplier;
         this.backgroundConsumer = backgroundConsumer;
     }

+ 14 - 0
src/main/java/me/shedaniel/clothconfig2/impl/ConfigEntryBuilderImpl.java

@@ -18,6 +18,15 @@ public class ConfigEntryBuilderImpl implements ConfigEntryBuilder {
         return new ConfigEntryBuilderImpl();
     }
     
+    public static ConfigEntryBuilderImpl createImmutable() {
+        return new ConfigEntryBuilderImpl() {
+            @Override
+            public ConfigEntryBuilder setResetButtonKey(String resetButtonKey) {
+                throw new UnsupportedOperationException("This is an immutable entry builder!");
+            }
+        };
+    }
+    
     @Override
     public String getResetButtonKey() {
         return resetButtonKey;
@@ -71,6 +80,11 @@ public class ConfigEntryBuilderImpl implements ConfigEntryBuilder {
         return new BooleanToggleBuilder(resetButtonKey, fieldNameKey, value);
     }
     
+    @Override
+    public StringFieldBuilder startStrField(String fieldNameKey, String value) {
+        return new StringFieldBuilder(resetButtonKey, fieldNameKey, value);
+    }
+    
     @Override
     public TextFieldBuilder startTextField(String fieldNameKey, String value) {
         return new TextFieldBuilder(resetButtonKey, fieldNameKey, value);

+ 12 - 5
src/main/java/me/shedaniel/clothconfig2/impl/builders/BooleanToggleBuilder.java

@@ -11,7 +11,7 @@ import java.util.function.Supplier;
 public class BooleanToggleBuilder extends FieldBuilder<Boolean, BooleanListEntry> {
     
     private Consumer<Boolean> saveConsumer = null;
-    private Supplier<Optional<String[]>> tooltipSupplier = null;
+    private Function<Boolean, Optional<String[]>> tooltipSupplier = bool -> Optional.empty();
     private boolean value;
     private Function<Boolean, String> yesNoTextSupplier = bool -> bool ? "§aYes" : "§cNo";
     
@@ -40,18 +40,23 @@ public class BooleanToggleBuilder extends FieldBuilder<Boolean, BooleanListEntry
         return this;
     }
     
-    public BooleanToggleBuilder setTooltipSupplier(Supplier<Optional<String[]>> tooltipSupplier) {
+    public BooleanToggleBuilder setTooltipSupplier(Function<Boolean, Optional<String[]>> tooltipSupplier) {
         this.tooltipSupplier = tooltipSupplier;
         return this;
     }
     
+    public BooleanToggleBuilder setTooltipSupplier(Supplier<Optional<String[]>> tooltipSupplier) {
+        this.tooltipSupplier = bool -> tooltipSupplier.get();
+        return this;
+    }
+    
     public BooleanToggleBuilder setTooltip(Optional<String[]> tooltip) {
-        this.tooltipSupplier = () -> tooltip;
+        this.tooltipSupplier = bool -> tooltip;
         return this;
     }
     
     public BooleanToggleBuilder setTooltip(String... tooltip) {
-        this.tooltipSupplier = () -> Optional.ofNullable(tooltip);
+        this.tooltipSupplier = bool -> Optional.ofNullable(tooltip);
         return this;
     }
     
@@ -63,12 +68,14 @@ public class BooleanToggleBuilder extends FieldBuilder<Boolean, BooleanListEntry
     
     @Override
     public BooleanListEntry build() {
-        return new BooleanListEntry(getFieldNameKey(), value, getResetButtonKey(), defaultValue, saveConsumer, tooltipSupplier, isRequireRestart()) {
+        BooleanListEntry entry = new BooleanListEntry(getFieldNameKey(), value, getResetButtonKey(), defaultValue, saveConsumer, null, isRequireRestart()) {
             @Override
             public String getYesNoText(boolean bool) {
                 return yesNoTextSupplier.apply(bool);
             }
         };
+        entry.setTooltipSupplier(() -> tooltipSupplier.apply(entry.getValue()));
+        return entry;
     }
     
 }

+ 12 - 5
src/main/java/me/shedaniel/clothconfig2/impl/builders/DoubleFieldBuilder.java

@@ -4,12 +4,13 @@ import me.shedaniel.clothconfig2.gui.entries.DoubleListEntry;
 
 import java.util.Optional;
 import java.util.function.Consumer;
+import java.util.function.Function;
 import java.util.function.Supplier;
 
 public class DoubleFieldBuilder extends FieldBuilder<Double, DoubleListEntry> {
     
     private Consumer<Double> saveConsumer = null;
-    private Supplier<Optional<String[]>> tooltipSupplier = null;
+    private Function<Double, Optional<String[]>> tooltipSupplier = d -> Optional.empty();
     private double value;
     private Double min = null, max = null;
     
@@ -58,28 +59,34 @@ public class DoubleFieldBuilder extends FieldBuilder<Double, DoubleListEntry> {
         return this;
     }
     
-    public DoubleFieldBuilder setTooltipSupplier(Supplier<Optional<String[]>> tooltipSupplier) {
+    public DoubleFieldBuilder setTooltipSupplier(Function<Double, Optional<String[]>> tooltipSupplier) {
         this.tooltipSupplier = tooltipSupplier;
         return this;
     }
     
+    public DoubleFieldBuilder setTooltipSupplier(Supplier<Optional<String[]>> tooltipSupplier) {
+        this.tooltipSupplier = d -> tooltipSupplier.get();
+        return this;
+    }
+    
     public DoubleFieldBuilder setTooltip(Optional<String[]> tooltip) {
-        this.tooltipSupplier = () -> tooltip;
+        this.tooltipSupplier = d -> tooltip;
         return this;
     }
     
     public DoubleFieldBuilder setTooltip(String... tooltip) {
-        this.tooltipSupplier = () -> Optional.ofNullable(tooltip);
+        this.tooltipSupplier = d -> Optional.ofNullable(tooltip);
         return this;
     }
     
     @Override
     public DoubleListEntry build() {
-        DoubleListEntry entry = new DoubleListEntry(getFieldNameKey(), value, getResetButtonKey(), defaultValue, saveConsumer, tooltipSupplier, isRequireRestart());
+        DoubleListEntry entry = new DoubleListEntry(getFieldNameKey(), value, getResetButtonKey(), defaultValue, saveConsumer, null, isRequireRestart());
         if (min != null)
             entry.setMinimum(min);
         if (max != null)
             entry.setMaximum(max);
+        entry.setTooltipSupplier(() -> tooltipSupplier.apply(entry.getValue()));
         return entry;
     }
     

+ 46 - 5
src/main/java/me/shedaniel/clothconfig2/impl/builders/DoubleListBuilder.java

@@ -2,6 +2,7 @@ package me.shedaniel.clothconfig2.impl.builders;
 
 import me.shedaniel.clothconfig2.gui.entries.BaseListEntry;
 import me.shedaniel.clothconfig2.gui.entries.DoubleListListEntry;
+import net.minecraft.client.resource.language.I18n;
 
 import java.util.List;
 import java.util.Optional;
@@ -12,17 +13,39 @@ import java.util.function.Supplier;
 public class DoubleListBuilder extends FieldBuilder<List<Double>, DoubleListListEntry> {
     
     private Consumer<List<Double>> saveConsumer = null;
-    private Supplier<Optional<String[]>> tooltipSupplier = null;
+    private Function<List<Double>, Optional<String[]>> tooltipSupplier = list -> Optional.empty();
     private List<Double> value;
     private boolean expended = false;
     private Double min = null, max = null;
     private Function<BaseListEntry, DoubleListListEntry.DoubleListCell> createNewInstance;
+    private String addTooltip = I18n.translate("text.cloth-config.list.add"), removeTooltip = I18n.translate("text.cloth-config.list.remove");
+    private boolean deleteButtonEnabled = true, insertInFront = true;
     
     public DoubleListBuilder(String resetButtonKey, String fieldNameKey, List<Double> value) {
         super(resetButtonKey, fieldNameKey);
         this.value = value;
     }
     
+    public DoubleListBuilder setDeleteButtonEnabled(boolean deleteButtonEnabled) {
+        this.deleteButtonEnabled = deleteButtonEnabled;
+        return this;
+    }
+    
+    public DoubleListBuilder setInsertInFront(boolean insertInFront) {
+        this.insertInFront = insertInFront;
+        return this;
+    }
+    
+    public DoubleListBuilder setAddButtonTooltip(String addTooltip) {
+        this.addTooltip = addTooltip;
+        return this;
+    }
+    
+    public DoubleListBuilder setRemoveButtonTooltip(String removeTooltip) {
+        this.removeTooltip = removeTooltip;
+        return this;
+    }
+    
     public DoubleListBuilder requireRestart() {
         requireRestart(true);
         return this;
@@ -73,30 +96,48 @@ public class DoubleListBuilder extends FieldBuilder<List<Double>, DoubleListList
         return this;
     }
     
-    public DoubleListBuilder setTooltipSupplier(Supplier<Optional<String[]>> tooltipSupplier) {
+    public DoubleListBuilder setTooltipSupplier(Function<List<Double>, Optional<String[]>> tooltipSupplier) {
         this.tooltipSupplier = tooltipSupplier;
         return this;
     }
     
+    public DoubleListBuilder setTooltipSupplier(Supplier<Optional<String[]>> tooltipSupplier) {
+        this.tooltipSupplier = list -> tooltipSupplier.get();
+        return this;
+    }
+    
     public DoubleListBuilder setTooltip(Optional<String[]> tooltip) {
-        this.tooltipSupplier = () -> tooltip;
+        this.tooltipSupplier = list -> tooltip;
         return this;
     }
     
     public DoubleListBuilder setTooltip(String... tooltip) {
-        this.tooltipSupplier = () -> Optional.ofNullable(tooltip);
+        this.tooltipSupplier = list -> Optional.ofNullable(tooltip);
         return this;
     }
     
     @Override
     public DoubleListListEntry build() {
-        DoubleListListEntry entry = new DoubleListListEntry(getFieldNameKey(), value, expended, tooltipSupplier, saveConsumer, defaultValue, getResetButtonKey(), isRequireRestart());
+        DoubleListListEntry entry = new DoubleListListEntry(getFieldNameKey(), value, expended, null, saveConsumer, defaultValue, getResetButtonKey(), isRequireRestart()) {
+            @Override
+            public boolean isDeleteButtonEnabled() {
+                return deleteButtonEnabled;
+            }
+            
+            @Override
+            public boolean insertInFront() {
+                return insertInFront;
+            }
+        };
         if (min != null)
             entry.setMinimum(min);
         if (max != null)
             entry.setMaximum(max);
         if (createNewInstance != null)
             entry.setCreateNewInstance(createNewInstance);
+        entry.setTooltipSupplier(() -> tooltipSupplier.apply(entry.getValue()));
+        entry.setAddTooltip(addTooltip);
+        entry.setAddTooltip(removeTooltip);
         return entry;
     }
     

+ 12 - 5
src/main/java/me/shedaniel/clothconfig2/impl/builders/EnumSelectorBuilder.java

@@ -11,7 +11,7 @@ import java.util.function.Supplier;
 public class EnumSelectorBuilder<T extends Enum<?>> extends FieldBuilder<T, EnumListEntry<T>> {
     
     private Consumer<T> saveConsumer = null;
-    private Supplier<Optional<String[]>> tooltipSupplier = null;
+    private Function<T, Optional<String[]>> tooltipSupplier = e -> Optional.empty();
     private T value;
     private Class<T> clazz;
     private Function<Enum, String> enumNameProvider = EnumListEntry.DEFAULT_NAME_PROVIDER;
@@ -45,18 +45,23 @@ public class EnumSelectorBuilder<T extends Enum<?>> extends FieldBuilder<T, Enum
         return this;
     }
     
-    public EnumSelectorBuilder setTooltipSupplier(Supplier<Optional<String[]>> tooltipSupplier) {
+    public EnumSelectorBuilder setTooltipSupplier(Function<T, Optional<String[]>> tooltipSupplier) {
         this.tooltipSupplier = tooltipSupplier;
         return this;
     }
     
+    public EnumSelectorBuilder setTooltipSupplier(Supplier<Optional<String[]>> tooltipSupplier) {
+        this.tooltipSupplier = e -> tooltipSupplier.get();
+        return this;
+    }
+    
     public EnumSelectorBuilder setTooltip(Optional<String[]> tooltip) {
-        this.tooltipSupplier = () -> tooltip;
+        this.tooltipSupplier = e -> tooltip;
         return this;
     }
     
     public EnumSelectorBuilder setTooltip(String... tooltip) {
-        this.tooltipSupplier = () -> Optional.ofNullable(tooltip);
+        this.tooltipSupplier = e -> Optional.ofNullable(tooltip);
         return this;
     }
     
@@ -68,7 +73,9 @@ public class EnumSelectorBuilder<T extends Enum<?>> extends FieldBuilder<T, Enum
     
     @Override
     public EnumListEntry<T> build() {
-        return new EnumListEntry<T>(getFieldNameKey(), clazz, value, getResetButtonKey(), defaultValue, saveConsumer, enumNameProvider, tooltipSupplier, isRequireRestart());
+        EnumListEntry<T> entry = new EnumListEntry<>(getFieldNameKey(), clazz, value, getResetButtonKey(), defaultValue, saveConsumer, enumNameProvider, null, isRequireRestart());
+        entry.setTooltipSupplier(() -> tooltipSupplier.apply(entry.getValue()));
+        return entry;
     }
     
 }

+ 12 - 5
src/main/java/me/shedaniel/clothconfig2/impl/builders/FloatFieldBuilder.java

@@ -4,12 +4,13 @@ import me.shedaniel.clothconfig2.gui.entries.FloatListEntry;
 
 import java.util.Optional;
 import java.util.function.Consumer;
+import java.util.function.Function;
 import java.util.function.Supplier;
 
 public class FloatFieldBuilder extends FieldBuilder<Float, FloatListEntry> {
     
     private Consumer<Float> saveConsumer = null;
-    private Supplier<Optional<String[]>> tooltipSupplier = null;
+    private Function<Float, Optional<String[]>> tooltipSupplier = f -> Optional.empty();
     private float value;
     private Float min = null, max = null;
     
@@ -38,18 +39,23 @@ public class FloatFieldBuilder extends FieldBuilder<Float, FloatListEntry> {
         return this;
     }
     
-    public FloatFieldBuilder setTooltipSupplier(Supplier<Optional<String[]>> tooltipSupplier) {
+    public FloatFieldBuilder setTooltipSupplier(Function<Float, Optional<String[]>> tooltipSupplier) {
         this.tooltipSupplier = tooltipSupplier;
         return this;
     }
     
+    public FloatFieldBuilder setTooltipSupplier(Supplier<Optional<String[]>> tooltipSupplier) {
+        this.tooltipSupplier = f -> tooltipSupplier.get();
+        return this;
+    }
+    
     public FloatFieldBuilder setTooltip(Optional<String[]> tooltip) {
-        this.tooltipSupplier = () -> tooltip;
+        this.tooltipSupplier = f -> tooltip;
         return this;
     }
     
     public FloatFieldBuilder setTooltip(String... tooltip) {
-        this.tooltipSupplier = () -> Optional.ofNullable(tooltip);
+        this.tooltipSupplier = f -> Optional.ofNullable(tooltip);
         return this;
     }
     
@@ -75,11 +81,12 @@ public class FloatFieldBuilder extends FieldBuilder<Float, FloatListEntry> {
     
     @Override
     public FloatListEntry build() {
-        FloatListEntry entry = new FloatListEntry(getFieldNameKey(), value, getResetButtonKey(), defaultValue, saveConsumer, tooltipSupplier, isRequireRestart());
+        FloatListEntry entry = new FloatListEntry(getFieldNameKey(), value, getResetButtonKey(), defaultValue, saveConsumer, null, isRequireRestart());
         if (min != null)
             entry.setMinimum(min);
         if (max != null)
             entry.setMaximum(max);
+        entry.setTooltipSupplier(() -> tooltipSupplier.apply(entry.getValue()));
         return entry;
     }
     

+ 45 - 4
src/main/java/me/shedaniel/clothconfig2/impl/builders/FloatListBuilder.java

@@ -2,6 +2,7 @@ package me.shedaniel.clothconfig2.impl.builders;
 
 import me.shedaniel.clothconfig2.gui.entries.BaseListEntry;
 import me.shedaniel.clothconfig2.gui.entries.FloatListListEntry;
+import net.minecraft.client.resource.language.I18n;
 
 import java.util.List;
 import java.util.Optional;
@@ -12,17 +13,39 @@ import java.util.function.Supplier;
 public class FloatListBuilder extends FieldBuilder<List<Float>, FloatListListEntry> {
     
     private Consumer<List<Float>> saveConsumer = null;
-    private Supplier<Optional<String[]>> tooltipSupplier = null;
+    private Function<List<Float>, Optional<String[]>> tooltipSupplier = list -> Optional.empty();
     private List<Float> value;
     private boolean expended = false;
     private Float min = null, max = null;
     private Function<BaseListEntry, FloatListListEntry.FloatListCell> createNewInstance;
+    private String addTooltip = I18n.translate("text.cloth-config.list.add"), removeTooltip = I18n.translate("text.cloth-config.list.remove");
+    private boolean deleteButtonEnabled = true, insertInFront = true;
     
     public FloatListBuilder(String resetButtonKey, String fieldNameKey, List<Float> value) {
         super(resetButtonKey, fieldNameKey);
         this.value = value;
     }
     
+    public FloatListBuilder setDeleteButtonEnabled(boolean deleteButtonEnabled) {
+        this.deleteButtonEnabled = deleteButtonEnabled;
+        return this;
+    }
+    
+    public FloatListBuilder setInsertInFront(boolean insertInFront) {
+        this.insertInFront = insertInFront;
+        return this;
+    }
+    
+    public FloatListBuilder setAddButtonTooltip(String addTooltip) {
+        this.addTooltip = addTooltip;
+        return this;
+    }
+    
+    public FloatListBuilder setRemoveButtonTooltip(String removeTooltip) {
+        this.removeTooltip = removeTooltip;
+        return this;
+    }
+    
     public FloatListBuilder requireRestart() {
         requireRestart(true);
         return this;
@@ -74,29 +97,47 @@ public class FloatListBuilder extends FieldBuilder<List<Float>, FloatListListEnt
     }
     
     public FloatListBuilder setTooltipSupplier(Supplier<Optional<String[]>> tooltipSupplier) {
+        this.tooltipSupplier = list -> tooltipSupplier.get();
+        return this;
+    }
+    
+    public FloatListBuilder setTooltipSupplier(Function<List<Float>, Optional<String[]>> tooltipSupplier) {
         this.tooltipSupplier = tooltipSupplier;
         return this;
     }
     
     public FloatListBuilder setTooltip(Optional<String[]> tooltip) {
-        this.tooltipSupplier = () -> tooltip;
+        this.tooltipSupplier = list -> tooltip;
         return this;
     }
     
     public FloatListBuilder setTooltip(String... tooltip) {
-        this.tooltipSupplier = () -> Optional.ofNullable(tooltip);
+        this.tooltipSupplier = list -> Optional.ofNullable(tooltip);
         return this;
     }
     
     @Override
     public FloatListListEntry build() {
-        FloatListListEntry entry = new FloatListListEntry(getFieldNameKey(), value, expended, tooltipSupplier, saveConsumer, defaultValue, getResetButtonKey(), isRequireRestart());
+        FloatListListEntry entry = new FloatListListEntry(getFieldNameKey(), value, expended, null, saveConsumer, defaultValue, getResetButtonKey(), isRequireRestart()) {
+            @Override
+            public boolean isDeleteButtonEnabled() {
+                return deleteButtonEnabled;
+            }
+            
+            @Override
+            public boolean insertInFront() {
+                return insertInFront;
+            }
+        };
         if (min != null)
             entry.setMinimum(min);
         if (max != null)
             entry.setMaximum(max);
         if (createNewInstance != null)
             entry.setCreateNewInstance(createNewInstance);
+        entry.setTooltipSupplier(() -> tooltipSupplier.apply(entry.getValue()));
+        entry.setAddTooltip(addTooltip);
+        entry.setAddTooltip(removeTooltip);
         return entry;
     }
     

+ 12 - 5
src/main/java/me/shedaniel/clothconfig2/impl/builders/IntFieldBuilder.java

@@ -4,12 +4,13 @@ import me.shedaniel.clothconfig2.gui.entries.IntegerListEntry;
 
 import java.util.Optional;
 import java.util.function.Consumer;
+import java.util.function.Function;
 import java.util.function.Supplier;
 
 public class IntFieldBuilder extends FieldBuilder<Integer, IntegerListEntry> {
     
     private Consumer<Integer> saveConsumer = null;
-    private Supplier<Optional<String[]>> tooltipSupplier = null;
+    private Function<Integer, Optional<String[]>> tooltipSupplier = i -> Optional.empty();
     private int value;
     private Integer min = null, max = null;
     
@@ -38,18 +39,23 @@ public class IntFieldBuilder extends FieldBuilder<Integer, IntegerListEntry> {
         return this;
     }
     
-    public IntFieldBuilder setTooltipSupplier(Supplier<Optional<String[]>> tooltipSupplier) {
+    public IntFieldBuilder setTooltipSupplier(Function<Integer, Optional<String[]>> tooltipSupplier) {
         this.tooltipSupplier = tooltipSupplier;
         return this;
     }
     
+    public IntFieldBuilder setTooltipSupplier(Supplier<Optional<String[]>> tooltipSupplier) {
+        this.tooltipSupplier = i -> tooltipSupplier.get();
+        return this;
+    }
+    
     public IntFieldBuilder setTooltip(Optional<String[]> tooltip) {
-        this.tooltipSupplier = () -> tooltip;
+        this.tooltipSupplier = i -> tooltip;
         return this;
     }
     
     public IntFieldBuilder setTooltip(String... tooltip) {
-        this.tooltipSupplier = () -> Optional.ofNullable(tooltip);
+        this.tooltipSupplier = i -> Optional.ofNullable(tooltip);
         return this;
     }
     
@@ -75,11 +81,12 @@ public class IntFieldBuilder extends FieldBuilder<Integer, IntegerListEntry> {
     
     @Override
     public IntegerListEntry build() {
-        IntegerListEntry entry = new IntegerListEntry(getFieldNameKey(), value, getResetButtonKey(), defaultValue, saveConsumer, tooltipSupplier, isRequireRestart());
+        IntegerListEntry entry = new IntegerListEntry(getFieldNameKey(), value, getResetButtonKey(), defaultValue, saveConsumer, null, isRequireRestart());
         if (min != null)
             entry.setMinimum(min);
         if (max != null)
             entry.setMaximum(max);
+        entry.setTooltipSupplier(() -> tooltipSupplier.apply(entry.getValue()));
         return entry;
     }
     

+ 46 - 5
src/main/java/me/shedaniel/clothconfig2/impl/builders/IntListBuilder.java

@@ -2,6 +2,7 @@ package me.shedaniel.clothconfig2.impl.builders;
 
 import me.shedaniel.clothconfig2.gui.entries.BaseListEntry;
 import me.shedaniel.clothconfig2.gui.entries.IntegerListListEntry;
+import net.minecraft.client.resource.language.I18n;
 
 import java.util.List;
 import java.util.Optional;
@@ -12,17 +13,39 @@ import java.util.function.Supplier;
 public class IntListBuilder extends FieldBuilder<List<Integer>, IntegerListListEntry> {
     
     private Consumer<List<Integer>> saveConsumer = null;
-    private Supplier<Optional<String[]>> tooltipSupplier = null;
+    private Function<List<Integer>, Optional<String[]>> tooltipSupplier = list -> Optional.empty();
     private List<Integer> value;
     private boolean expended = false;
     private Integer min = null, max = null;
     private Function<BaseListEntry, IntegerListListEntry.IntegerListCell> createNewInstance;
+    private String addTooltip = I18n.translate("text.cloth-config.list.add"), removeTooltip = I18n.translate("text.cloth-config.list.remove");
+    private boolean deleteButtonEnabled = true, insertInFront = true;
     
     public IntListBuilder(String resetButtonKey, String fieldNameKey, List<Integer> value) {
         super(resetButtonKey, fieldNameKey);
         this.value = value;
     }
     
+    public IntListBuilder setDeleteButtonEnabled(boolean deleteButtonEnabled) {
+        this.deleteButtonEnabled = deleteButtonEnabled;
+        return this;
+    }
+    
+    public IntListBuilder setInsertInFront(boolean insertInFront) {
+        this.insertInFront = insertInFront;
+        return this;
+    }
+    
+    public IntListBuilder setAddButtonTooltip(String addTooltip) {
+        this.addTooltip = addTooltip;
+        return this;
+    }
+    
+    public IntListBuilder setRemoveButtonTooltip(String removeTooltip) {
+        this.removeTooltip = removeTooltip;
+        return this;
+    }
+    
     public IntListBuilder requireRestart() {
         requireRestart(true);
         return this;
@@ -73,30 +96,48 @@ public class IntListBuilder extends FieldBuilder<List<Integer>, IntegerListListE
         return this;
     }
     
-    public IntListBuilder setTooltipSupplier(Supplier<Optional<String[]>> tooltipSupplier) {
+    public IntListBuilder setTooltipSupplier(Function<List<Integer>, Optional<String[]>> tooltipSupplier) {
         this.tooltipSupplier = tooltipSupplier;
         return this;
     }
     
+    public IntListBuilder setTooltipSupplier(Supplier<Optional<String[]>> tooltipSupplier) {
+        this.tooltipSupplier = list -> tooltipSupplier.get();
+        return this;
+    }
+    
     public IntListBuilder setTooltip(Optional<String[]> tooltip) {
-        this.tooltipSupplier = () -> tooltip;
+        this.tooltipSupplier = list -> tooltip;
         return this;
     }
     
     public IntListBuilder setTooltip(String... tooltip) {
-        this.tooltipSupplier = () -> Optional.ofNullable(tooltip);
+        this.tooltipSupplier = list -> Optional.ofNullable(tooltip);
         return this;
     }
     
     @Override
     public IntegerListListEntry build() {
-        IntegerListListEntry entry = new IntegerListListEntry(getFieldNameKey(), value, expended, tooltipSupplier, saveConsumer, defaultValue, getResetButtonKey(), isRequireRestart());
+        IntegerListListEntry entry = new IntegerListListEntry(getFieldNameKey(), value, expended, null, saveConsumer, defaultValue, getResetButtonKey(), isRequireRestart()) {
+            @Override
+            public boolean isDeleteButtonEnabled() {
+                return deleteButtonEnabled;
+            }
+            
+            @Override
+            public boolean insertInFront() {
+                return insertInFront;
+            }
+        };
         if (min != null)
             entry.setMinimum(min);
         if (max != null)
             entry.setMaximum(max);
         if (createNewInstance != null)
             entry.setCreateNewInstance(createNewInstance);
+        entry.setTooltipSupplier(() -> tooltipSupplier.apply(entry.getValue()));
+        entry.setAddTooltip(addTooltip);
+        entry.setAddTooltip(removeTooltip);
         return entry;
     }
     

+ 14 - 7
src/main/java/me/shedaniel/clothconfig2/impl/builders/IntSliderBuilder.java

@@ -10,7 +10,7 @@ import java.util.function.Supplier;
 public class IntSliderBuilder extends FieldBuilder<Integer, IntegerSliderEntry> {
     
     private Consumer<Integer> saveConsumer = null;
-    private Supplier<Optional<String[]>> tooltipSupplier = null;
+    private Function<Integer, Optional<String[]>> tooltipSupplier = i -> Optional.empty();
     private int value, max, min;
     private Function<Integer, String> textGetter = null;
     
@@ -46,18 +46,23 @@ public class IntSliderBuilder extends FieldBuilder<Integer, IntegerSliderEntry>
         return this;
     }
     
-    public IntSliderBuilder setTooltipSupplier(Supplier<Optional<String[]>> tooltipSupplier) {
+    public IntSliderBuilder setTooltipSupplier(Function<Integer, Optional<String[]>> tooltipSupplier) {
         this.tooltipSupplier = tooltipSupplier;
         return this;
     }
     
+    public IntSliderBuilder setTooltipSupplier(Supplier<Optional<String[]>> tooltipSupplier) {
+        this.tooltipSupplier = i -> tooltipSupplier.get();
+        return this;
+    }
+    
     public IntSliderBuilder setTooltip(Optional<String[]> tooltip) {
-        this.tooltipSupplier = () -> tooltip;
+        this.tooltipSupplier = i -> tooltip;
         return this;
     }
     
     public IntSliderBuilder setTooltip(String... tooltip) {
-        this.tooltipSupplier = () -> Optional.ofNullable(tooltip);
+        this.tooltipSupplier = i -> Optional.ofNullable(tooltip);
         return this;
     }
     
@@ -73,9 +78,11 @@ public class IntSliderBuilder extends FieldBuilder<Integer, IntegerSliderEntry>
     
     @Override
     public IntegerSliderEntry build() {
-        if (textGetter == null)
-            return new IntegerSliderEntry(getFieldNameKey(), min, max, value, getResetButtonKey(), defaultValue, saveConsumer, tooltipSupplier, isRequireRestart());
-        return new IntegerSliderEntry(getFieldNameKey(), min, max, value, getResetButtonKey(), defaultValue, saveConsumer, tooltipSupplier, isRequireRestart()).setTextGetter(textGetter);
+        IntegerSliderEntry entry = new IntegerSliderEntry(getFieldNameKey(), min, max, value, getResetButtonKey(), defaultValue, saveConsumer, null, isRequireRestart());
+        if (textGetter != null)
+            entry.setTextGetter(textGetter);
+        entry.setTooltipSupplier(() -> tooltipSupplier.apply(entry.getValue()));
+        return entry;
     }
     
 }

+ 11 - 4
src/main/java/me/shedaniel/clothconfig2/impl/builders/LongFieldBuilder.java

@@ -4,12 +4,13 @@ import me.shedaniel.clothconfig2.gui.entries.LongListEntry;
 
 import java.util.Optional;
 import java.util.function.Consumer;
+import java.util.function.Function;
 import java.util.function.Supplier;
 
 public class LongFieldBuilder extends FieldBuilder<Long, LongListEntry> {
     
     private Consumer<Long> saveConsumer = null;
-    private Supplier<Optional<String[]>> tooltipSupplier = null;
+    private Function<Long, Optional<String[]>> tooltipSupplier = l -> Optional.empty();
     private long value;
     private Long min = null, max = null;
     
@@ -39,17 +40,22 @@ public class LongFieldBuilder extends FieldBuilder<Long, LongListEntry> {
     }
     
     public LongFieldBuilder setTooltipSupplier(Supplier<Optional<String[]>> tooltipSupplier) {
+        this.tooltipSupplier = l -> tooltipSupplier.get();
+        return this;
+    }
+    
+    public LongFieldBuilder setTooltipSupplier(Function<Long, Optional<String[]>> tooltipSupplier) {
         this.tooltipSupplier = tooltipSupplier;
         return this;
     }
     
     public LongFieldBuilder setTooltip(Optional<String[]> tooltip) {
-        this.tooltipSupplier = () -> tooltip;
+        this.tooltipSupplier = l -> tooltip;
         return this;
     }
     
     public LongFieldBuilder setTooltip(String... tooltip) {
-        this.tooltipSupplier = () -> Optional.ofNullable(tooltip);
+        this.tooltipSupplier = l -> Optional.ofNullable(tooltip);
         return this;
     }
     
@@ -75,11 +81,12 @@ public class LongFieldBuilder extends FieldBuilder<Long, LongListEntry> {
     
     @Override
     public LongListEntry build() {
-        LongListEntry entry = new LongListEntry(getFieldNameKey(), value, getResetButtonKey(), defaultValue, saveConsumer, tooltipSupplier, isRequireRestart());
+        LongListEntry entry = new LongListEntry(getFieldNameKey(), value, getResetButtonKey(), defaultValue, saveConsumer, null, isRequireRestart());
         if (min != null)
             entry.setMinimum(min);
         if (max != null)
             entry.setMaximum(max);
+        entry.setTooltipSupplier(() -> tooltipSupplier.apply(entry.getValue()));
         return entry;
     }
     

+ 45 - 4
src/main/java/me/shedaniel/clothconfig2/impl/builders/LongListBuilder.java

@@ -2,6 +2,7 @@ package me.shedaniel.clothconfig2.impl.builders;
 
 import me.shedaniel.clothconfig2.gui.entries.BaseListEntry;
 import me.shedaniel.clothconfig2.gui.entries.LongListListEntry;
+import net.minecraft.client.resource.language.I18n;
 
 import java.util.List;
 import java.util.Optional;
@@ -12,17 +13,39 @@ import java.util.function.Supplier;
 public class LongListBuilder extends FieldBuilder<List<Long>, LongListListEntry> {
     
     private Consumer<List<Long>> saveConsumer = null;
-    private Supplier<Optional<String[]>> tooltipSupplier = null;
+    private Function<List<Long>, Optional<String[]>> tooltipSupplier = list -> Optional.empty();
     private List<Long> value;
     private boolean expended = false;
     private Long min = null, max = null;
     private Function<BaseListEntry, LongListListEntry.LongListCell> createNewInstance;
+    private String addTooltip = I18n.translate("text.cloth-config.list.add"), removeTooltip = I18n.translate("text.cloth-config.list.remove");
+    private boolean deleteButtonEnabled = true, insertInFront = true;
     
     public LongListBuilder(String resetButtonKey, String fieldNameKey, List<Long> value) {
         super(resetButtonKey, fieldNameKey);
         this.value = value;
     }
     
+    public LongListBuilder setDeleteButtonEnabled(boolean deleteButtonEnabled) {
+        this.deleteButtonEnabled = deleteButtonEnabled;
+        return this;
+    }
+    
+    public LongListBuilder setInsertInFront(boolean insertInFront) {
+        this.insertInFront = insertInFront;
+        return this;
+    }
+    
+    public LongListBuilder setAddButtonTooltip(String addTooltip) {
+        this.addTooltip = addTooltip;
+        return this;
+    }
+    
+    public LongListBuilder setRemoveButtonTooltip(String removeTooltip) {
+        this.removeTooltip = removeTooltip;
+        return this;
+    }
+    
     public LongListBuilder requireRestart() {
         requireRestart(true);
         return this;
@@ -74,29 +97,47 @@ public class LongListBuilder extends FieldBuilder<List<Long>, LongListListEntry>
     }
     
     public LongListBuilder setTooltipSupplier(Supplier<Optional<String[]>> tooltipSupplier) {
+        this.tooltipSupplier = list -> tooltipSupplier.get();
+        return this;
+    }
+    
+    public LongListBuilder setTooltipSupplier(Function<List<Long>, Optional<String[]>> tooltipSupplier) {
         this.tooltipSupplier = tooltipSupplier;
         return this;
     }
     
     public LongListBuilder setTooltip(Optional<String[]> tooltip) {
-        this.tooltipSupplier = () -> tooltip;
+        this.tooltipSupplier = list -> tooltip;
         return this;
     }
     
     public LongListBuilder setTooltip(String... tooltip) {
-        this.tooltipSupplier = () -> Optional.ofNullable(tooltip);
+        this.tooltipSupplier = list -> Optional.ofNullable(tooltip);
         return this;
     }
     
     @Override
     public LongListListEntry build() {
-        LongListListEntry entry = new LongListListEntry(getFieldNameKey(), value, expended, tooltipSupplier, saveConsumer, defaultValue, getResetButtonKey(), isRequireRestart());
+        LongListListEntry entry = new LongListListEntry(getFieldNameKey(), value, expended, null, saveConsumer, defaultValue, getResetButtonKey(), isRequireRestart()) {
+            @Override
+            public boolean isDeleteButtonEnabled() {
+                return deleteButtonEnabled;
+            }
+            
+            @Override
+            public boolean insertInFront() {
+                return insertInFront;
+            }
+        };
         if (min != null)
             entry.setMinimum(min);
         if (max != null)
             entry.setMaximum(max);
         if (createNewInstance != null)
             entry.setCreateNewInstance(createNewInstance);
+        entry.setTooltipSupplier(() -> tooltipSupplier.apply(entry.getValue()));
+        entry.setAddTooltip(addTooltip);
+        entry.setAddTooltip(removeTooltip);
         return entry;
     }
     

+ 15 - 7
src/main/java/me/shedaniel/clothconfig2/impl/builders/LongSliderBuilder.java

@@ -10,7 +10,7 @@ import java.util.function.Supplier;
 public class LongSliderBuilder extends FieldBuilder<Long, LongSliderEntry> {
     
     private Consumer<Long> saveConsumer = null;
-    private Supplier<Optional<String[]>> tooltipSupplier = null;
+    private Function<Long, Optional<String[]>> tooltipSupplier = l -> Optional.empty();
     private long value, max, min;
     private Function<Long, String> textGetter = null;
     
@@ -46,26 +46,34 @@ public class LongSliderBuilder extends FieldBuilder<Long, LongSliderEntry> {
         return this;
     }
     
-    public LongSliderBuilder setTooltipSupplier(Supplier<Optional<String[]>> tooltipSupplier) {
+    public LongSliderBuilder setTooltipSupplier(Function<Long, Optional<String[]>> tooltipSupplier) {
         this.tooltipSupplier = tooltipSupplier;
         return this;
     }
     
+    public LongSliderBuilder setTooltipSupplier(Supplier<Optional<String[]>> tooltipSupplier) {
+        this.tooltipSupplier = i -> tooltipSupplier.get();
+        return this;
+    }
+    
     public LongSliderBuilder setTooltip(Optional<String[]> tooltip) {
-        this.tooltipSupplier = () -> tooltip;
+        this.tooltipSupplier = i -> tooltip;
         return this;
     }
     
     public LongSliderBuilder setTooltip(String... tooltip) {
-        this.tooltipSupplier = () -> Optional.ofNullable(tooltip);
+        this.tooltipSupplier = i -> Optional.ofNullable(tooltip);
         return this;
     }
     
+    
     @Override
     public LongSliderEntry build() {
-        if (textGetter == null)
-            return new LongSliderEntry(getFieldNameKey(), min, max, value, saveConsumer, getResetButtonKey(), defaultValue, tooltipSupplier, isRequireRestart());
-        return new LongSliderEntry(getFieldNameKey(), min, max, value, saveConsumer, getResetButtonKey(), defaultValue, tooltipSupplier, isRequireRestart()).setTextGetter(textGetter);
+        LongSliderEntry entry = new LongSliderEntry(getFieldNameKey(), min, max, value, saveConsumer, getResetButtonKey(), defaultValue, null, isRequireRestart());
+        if (textGetter != null)
+            entry.setTextGetter(textGetter);
+        entry.setTooltipSupplier(() -> tooltipSupplier.apply(entry.getValue()));
+        return entry;
     }
     
 }

+ 70 - 0
src/main/java/me/shedaniel/clothconfig2/impl/builders/StringFieldBuilder.java

@@ -0,0 +1,70 @@
+package me.shedaniel.clothconfig2.impl.builders;
+
+import me.shedaniel.clothconfig2.gui.entries.StringListEntry;
+
+import java.util.Objects;
+import java.util.Optional;
+import java.util.function.Consumer;
+import java.util.function.Function;
+import java.util.function.Supplier;
+
+public class StringFieldBuilder extends FieldBuilder<String, StringListEntry> {
+    
+    private Consumer<String> saveConsumer = null;
+    private Function<String, Optional<String[]>> tooltipSupplier = str -> Optional.empty();
+    private String value;
+    
+    public StringFieldBuilder(String resetButtonKey, String fieldNameKey, String value) {
+        super(resetButtonKey, fieldNameKey);
+        Objects.requireNonNull(value);
+        this.value = value;
+    }
+    
+    public StringFieldBuilder requireRestart() {
+        requireRestart(true);
+        return this;
+    }
+    
+    public StringFieldBuilder setSaveConsumer(Consumer<String> saveConsumer) {
+        this.saveConsumer = saveConsumer;
+        return this;
+    }
+    
+    public StringFieldBuilder setDefaultValue(Supplier<String> defaultValue) {
+        this.defaultValue = defaultValue;
+        return this;
+    }
+    
+    public StringFieldBuilder setDefaultValue(String defaultValue) {
+        this.defaultValue = () -> Objects.requireNonNull(defaultValue);
+        return this;
+    }
+    
+    public StringFieldBuilder setTooltipSupplier(Supplier<Optional<String[]>> tooltipSupplier) {
+        this.tooltipSupplier = str -> tooltipSupplier.get();
+        return this;
+    }
+    
+    public StringFieldBuilder setTooltipSupplier(Function<String, Optional<String[]>> tooltipSupplier) {
+        this.tooltipSupplier = tooltipSupplier;
+        return this;
+    }
+    
+    public StringFieldBuilder setTooltip(Optional<String[]> tooltip) {
+        this.tooltipSupplier = str -> tooltip;
+        return this;
+    }
+    
+    public StringFieldBuilder setTooltip(String... tooltip) {
+        this.tooltipSupplier = str -> Optional.ofNullable(tooltip);
+        return this;
+    }
+    
+    @Override
+    public StringListEntry build() {
+        StringListEntry entry = new StringListEntry(getFieldNameKey(), value, getResetButtonKey(), defaultValue, saveConsumer, null, isRequireRestart());
+        entry.setTooltipSupplier(() -> tooltipSupplier.apply(entry.getValue()));
+        return entry;
+    }
+    
+}

+ 35 - 4
src/main/java/me/shedaniel/clothconfig2/impl/builders/StringListBuilder.java

@@ -2,6 +2,7 @@ package me.shedaniel.clothconfig2.impl.builders;
 
 import me.shedaniel.clothconfig2.gui.entries.BaseListEntry;
 import me.shedaniel.clothconfig2.gui.entries.StringListListEntry;
+import net.minecraft.client.resource.language.I18n;
 
 import java.util.List;
 import java.util.Optional;
@@ -12,16 +13,38 @@ import java.util.function.Supplier;
 public class StringListBuilder extends FieldBuilder<List<String>, StringListListEntry> {
     
     private Consumer<List<String>> saveConsumer = null;
-    private Supplier<Optional<String[]>> tooltipSupplier = null;
+    private Function<List<String>, Optional<String[]>> tooltipSupplier = list -> Optional.empty();
     private List<String> value;
     private boolean expended = false;
     private Function<BaseListEntry, StringListListEntry.StringListCell> createNewInstance;
+    private String addTooltip = I18n.translate("text.cloth-config.list.add"), removeTooltip = I18n.translate("text.cloth-config.list.remove");
+    private boolean deleteButtonEnabled = true, insertInFront = true;
     
     public StringListBuilder(String resetButtonKey, String fieldNameKey, List<String> value) {
         super(resetButtonKey, fieldNameKey);
         this.value = value;
     }
     
+    public StringListBuilder setDeleteButtonEnabled(boolean deleteButtonEnabled) {
+        this.deleteButtonEnabled = deleteButtonEnabled;
+        return this;
+    }
+    
+    public StringListBuilder setInsertInFront(boolean insertInFront) {
+        this.insertInFront = insertInFront;
+        return this;
+    }
+    
+    public StringListBuilder setAddButtonTooltip(String addTooltip) {
+        this.addTooltip = addTooltip;
+        return this;
+    }
+    
+    public StringListBuilder setRemoveButtonTooltip(String removeTooltip) {
+        this.removeTooltip = removeTooltip;
+        return this;
+    }
+    
     public StringListBuilder requireRestart() {
         requireRestart(true);
         return this;
@@ -53,25 +76,33 @@ public class StringListBuilder extends FieldBuilder<List<String>, StringListList
     }
     
     public StringListBuilder setTooltipSupplier(Supplier<Optional<String[]>> tooltipSupplier) {
+        this.tooltipSupplier = list -> tooltipSupplier.get();
+        return this;
+    }
+    
+    public StringListBuilder setTooltipSupplier(Function<List<String>, Optional<String[]>> tooltipSupplier) {
         this.tooltipSupplier = tooltipSupplier;
         return this;
     }
     
     public StringListBuilder setTooltip(Optional<String[]> tooltip) {
-        this.tooltipSupplier = () -> tooltip;
+        this.tooltipSupplier = list -> tooltip;
         return this;
     }
     
     public StringListBuilder setTooltip(String... tooltip) {
-        this.tooltipSupplier = () -> Optional.ofNullable(tooltip);
+        this.tooltipSupplier = list -> Optional.ofNullable(tooltip);
         return this;
     }
     
     @Override
     public StringListListEntry build() {
-        StringListListEntry entry = new StringListListEntry(getFieldNameKey(), value, expended, tooltipSupplier, saveConsumer, defaultValue, getResetButtonKey(), isRequireRestart());
+        StringListListEntry entry = new StringListListEntry(getFieldNameKey(), value, expended, null, saveConsumer, defaultValue, getResetButtonKey(), isRequireRestart());
         if (createNewInstance != null)
             entry.setCreateNewInstance(createNewInstance);
+        entry.setTooltipSupplier(() -> tooltipSupplier.apply(entry.getValue()));
+        entry.setAddTooltip(addTooltip);
+        entry.setAddTooltip(removeTooltip);
         return entry;
     }
     

+ 10 - 4
src/main/java/me/shedaniel/clothconfig2/impl/builders/SubCategoryBuilder.java

@@ -5,12 +5,13 @@ import me.shedaniel.clothconfig2.api.AbstractConfigListEntry;
 import me.shedaniel.clothconfig2.gui.entries.SubCategoryListEntry;
 
 import java.util.*;
+import java.util.function.Function;
 import java.util.function.Supplier;
 
 public class SubCategoryBuilder extends FieldBuilder<Object, SubCategoryListEntry> implements List<AbstractConfigListEntry> {
     
     private List<AbstractConfigListEntry> entries;
-    private Supplier<Optional<String[]>> tooltipSupplier = null;
+    private Function<List<AbstractConfigListEntry>, Optional<String[]>> tooltipSupplier = list -> Optional.empty();
     private boolean expended = false;
     
     public SubCategoryBuilder(String resetButtonKey, String fieldNameKey) {
@@ -24,17 +25,22 @@ public class SubCategoryBuilder extends FieldBuilder<Object, SubCategoryListEntr
     }
     
     public SubCategoryBuilder setTooltipSupplier(Supplier<Optional<String[]>> tooltipSupplier) {
+        this.tooltipSupplier = list -> tooltipSupplier.get();
+        return this;
+    }
+    
+    public SubCategoryBuilder setTooltipSupplier(Function<List<AbstractConfigListEntry>, Optional<String[]>> tooltipSupplier) {
         this.tooltipSupplier = tooltipSupplier;
         return this;
     }
     
     public SubCategoryBuilder setTooltip(Optional<String[]> tooltip) {
-        this.tooltipSupplier = () -> tooltip;
+        this.tooltipSupplier = list -> tooltip;
         return this;
     }
     
     public SubCategoryBuilder setTooltip(String... tooltip) {
-        this.tooltipSupplier = () -> Optional.ofNullable(tooltip);
+        this.tooltipSupplier = list -> Optional.ofNullable(tooltip);
         return this;
     }
     
@@ -46,7 +52,7 @@ public class SubCategoryBuilder extends FieldBuilder<Object, SubCategoryListEntr
     @Override
     public SubCategoryListEntry build() {
         SubCategoryListEntry entry = new SubCategoryListEntry(getFieldNameKey(), entries, expended);
-        entry.setTooltipSupplier(tooltipSupplier);
+        entry.setTooltipSupplier(() -> tooltipSupplier.apply(entry.getValue()));
         return entry;
     }
     

+ 12 - 4
src/main/java/me/shedaniel/clothconfig2/impl/builders/TextFieldBuilder.java

@@ -5,12 +5,13 @@ import me.shedaniel.clothconfig2.gui.entries.StringListEntry;
 import java.util.Objects;
 import java.util.Optional;
 import java.util.function.Consumer;
+import java.util.function.Function;
 import java.util.function.Supplier;
 
 public class TextFieldBuilder extends FieldBuilder<String, StringListEntry> {
     
     private Consumer<String> saveConsumer = null;
-    private Supplier<Optional<String[]>> tooltipSupplier = null;
+    private Function<String, Optional<String[]>> tooltipSupplier = str -> Optional.empty();
     private String value;
     
     public TextFieldBuilder(String resetButtonKey, String fieldNameKey, String value) {
@@ -40,23 +41,30 @@ public class TextFieldBuilder extends FieldBuilder<String, StringListEntry> {
     }
     
     public TextFieldBuilder setTooltipSupplier(Supplier<Optional<String[]>> tooltipSupplier) {
+        this.tooltipSupplier = str -> tooltipSupplier.get();
+        return this;
+    }
+    
+    public TextFieldBuilder setTooltipSupplier(Function<String, Optional<String[]>> tooltipSupplier) {
         this.tooltipSupplier = tooltipSupplier;
         return this;
     }
     
     public TextFieldBuilder setTooltip(Optional<String[]> tooltip) {
-        this.tooltipSupplier = () -> tooltip;
+        this.tooltipSupplier = str -> tooltip;
         return this;
     }
     
     public TextFieldBuilder setTooltip(String... tooltip) {
-        this.tooltipSupplier = () -> Optional.ofNullable(tooltip);
+        this.tooltipSupplier = str -> Optional.ofNullable(tooltip);
         return this;
     }
     
     @Override
     public StringListEntry build() {
-        return new StringListEntry(getFieldNameKey(), value, getResetButtonKey(), defaultValue, saveConsumer, tooltipSupplier, isRequireRestart());
+        StringListEntry entry = new StringListEntry(getFieldNameKey(), value, getResetButtonKey(), defaultValue, saveConsumer, null, isRequireRestart());
+        entry.setTooltipSupplier(() -> tooltipSupplier.apply(entry.getValue()));
+        return entry;
     }
     
 }