Config.java 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. package me.lortseam.completeconfig.data;
  2. import lombok.AccessLevel;
  3. import lombok.Getter;
  4. import lombok.NonNull;
  5. import lombok.extern.log4j.Log4j2;
  6. import me.lortseam.completeconfig.api.ConfigContainer;
  7. import me.lortseam.completeconfig.text.TranslationKey;
  8. import me.lortseam.completeconfig.io.ConfigSource;
  9. import net.fabricmc.api.EnvType;
  10. import net.fabricmc.api.Environment;
  11. import net.fabricmc.loader.api.FabricLoader;
  12. import net.fabricmc.loader.api.metadata.ModMetadata;
  13. import java.util.Arrays;
  14. import java.util.LinkedHashSet;
  15. import java.util.Objects;
  16. @Log4j2(topic = "CompleteConfig")
  17. public final class Config extends BaseCollection {
  18. static {
  19. Runtime.getRuntime().addShutdownHook(new Thread(() -> {
  20. for (Config config : ConfigRegistry.getConfigs()) {
  21. if (config.saveOnExit) {
  22. config.save();
  23. }
  24. }
  25. }));
  26. }
  27. /**
  28. * Creates a new config builder for the specified mod.
  29. *
  30. * @param modId the ID of the mod creating the config
  31. */
  32. public static Builder builder(@NonNull String modId) {
  33. if (!FabricLoader.getInstance().isModLoaded(modId)) {
  34. throw new IllegalArgumentException("Mod " + modId + " is not loaded");
  35. }
  36. return new Builder(modId);
  37. }
  38. @Getter(AccessLevel.PACKAGE)
  39. private final ConfigSource source;
  40. @Environment(EnvType.CLIENT)
  41. private TranslationKey branchedTranslation;
  42. private final boolean saveOnExit;
  43. private Config(ConfigSource source, ConfigContainer[] children, boolean saveOnExit) {
  44. this.source = source;
  45. this.saveOnExit = saveOnExit;
  46. resolve(children);
  47. }
  48. public ModMetadata getMod() {
  49. return FabricLoader.getInstance().getModContainer(source.getModId()).get().getMetadata();
  50. }
  51. @Override
  52. public TranslationKey getTranslation() {
  53. if (translation == null) {
  54. translation = TranslationKey.from(source);
  55. }
  56. return translation;
  57. }
  58. @Environment(EnvType.CLIENT)
  59. public TranslationKey getBranchedTranslation() {
  60. if (branchedTranslation == null) {
  61. branchedTranslation = getTranslation().append(source.getBranch());
  62. }
  63. return branchedTranslation;
  64. }
  65. private void load() {
  66. source.load(this);
  67. }
  68. public void save() {
  69. source.save(this);
  70. }
  71. @Log4j2(topic = "CompleteConfig")
  72. public final static class Builder {
  73. private final String modId;
  74. private String[] branch = new String[0];
  75. private final LinkedHashSet<ConfigContainer> children = new LinkedHashSet<>();
  76. private boolean main;
  77. private boolean saveOnExit;
  78. private Builder(String modId) {
  79. this.modId = modId;
  80. }
  81. /**
  82. * Sets the branch. Every config of a mod needs a unique branch, therefore setting a branch is only required
  83. * when using more than one config.
  84. *
  85. * <p>The branch determines the location of the config's save file.
  86. *
  87. * @param branch the branch
  88. * @return this builder
  89. */
  90. public Builder setBranch(@NonNull String[] branch) {
  91. Arrays.stream(branch).forEach(Objects::requireNonNull);
  92. this.branch = branch;
  93. return this;
  94. }
  95. /**
  96. * Adds one or more containers to the config.
  97. *
  98. * @param containers one or more containers
  99. * @return this builder
  100. */
  101. public Builder add(@NonNull ConfigContainer... containers) {
  102. for (ConfigContainer container : containers) {
  103. if (!children.add(Objects.requireNonNull(container))) {
  104. throw new IllegalArgumentException("Duplicate container " + container.getClass().getSimpleName());
  105. }
  106. }
  107. return this;
  108. }
  109. /**
  110. * Sets a flag to save the config when the game closes.
  111. *
  112. * @return this builder
  113. */
  114. public Builder saveOnExit() {
  115. saveOnExit = true;
  116. return this;
  117. }
  118. /**
  119. * Registers the config as main mod config.
  120. *
  121. * @return this builder
  122. */
  123. public Builder main() {
  124. main = true;
  125. return this;
  126. }
  127. /**
  128. * Creates and loads the config.
  129. *
  130. * @return the created config, or null if empty
  131. */
  132. public Config build() {
  133. Config config = null;
  134. if (!children.isEmpty()) {
  135. config = new Config(new ConfigSource(modId, branch), children.toArray(new ConfigContainer[0]), saveOnExit);
  136. }
  137. if (config == null || config.isEmpty()) {
  138. logger.warn("Empty config: " + modId + " " + Arrays.toString(branch));
  139. return null;
  140. }
  141. ConfigRegistry.register(config, main || branch.length == 0 && !ConfigRegistry.getMainConfig(modId).isPresent());
  142. config.load();
  143. return config;
  144. }
  145. }
  146. }