generated from KessokuTeaTime/Example-Mod
-
Notifications
You must be signed in to change notification settings - Fork 1
/
NightConfigSerializer.java
148 lines (126 loc) · 5.43 KB
/
NightConfigSerializer.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
package band.kessokuteatime.nightautoconfig.config;
import band.kessokuteatime.nightautoconfig.NightAutoConfig;
import band.kessokuteatime.nightautoconfig.config.base.ConfigType;
import band.kessokuteatime.nightautoconfig.serde.NightDeserializers;
import band.kessokuteatime.nightautoconfig.serde.NightSerializers;
import band.kessokuteatime.nightautoconfig.util.AnnotationUtil;
import com.electronwill.nightconfig.core.Config;
import com.electronwill.nightconfig.core.file.FileConfig;
import com.electronwill.nightconfig.core.file.GenericBuilder;
import com.electronwill.nightconfig.core.serde.ObjectDeserializer;
import com.electronwill.nightconfig.core.serde.ObjectSerializer;
import com.electronwill.nightconfig.core.serde.annotations.SerdeDefault;
import me.shedaniel.autoconfig.ConfigData;
import me.shedaniel.autoconfig.serializer.ConfigSerializer;
import me.shedaniel.autoconfig.util.Utils;
import org.jetbrains.annotations.NotNull;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.function.UnaryOperator;
public class NightConfigSerializer<T extends ConfigData> implements ConfigSerializer<T> {
protected final me.shedaniel.autoconfig.annotation.Config definition;
protected final Class<T> configClass;
protected final ConfigType type;
protected final GenericBuilder<Config, FileConfig> builder;
public record Builder(ConfigType type, UnaryOperator<GenericBuilder<Config, FileConfig>> genericBuilder) {
public Builder(ConfigType type) {
this(type, UnaryOperator.identity());
}
public Builder type(ConfigType type) {
return new Builder(type, genericBuilder);
}
public Builder then(UnaryOperator<GenericBuilder<Config, FileConfig>> then) {
return new Builder(type, b -> then.apply(genericBuilder.apply(b)));
}
public <T extends ConfigData> NightConfigSerializer<T> build(
me.shedaniel.autoconfig.annotation.Config definition, Class<T> configClass
) {
return new NightConfigSerializer<>(
definition, configClass, type,
genericBuilder.apply(FileConfig.builder(type.getConfigPath(definition)))
);
}
}
public NightConfigSerializer(
me.shedaniel.autoconfig.annotation.Config definition,
Class<T> configClass, ConfigType type, GenericBuilder<Config, FileConfig> builder
) {
this.definition = definition;
this.configClass = configClass;
this.type = type;
this.builder = builder;
}
@Override
public void serialize(@NotNull T t) throws SerializationException {
Path path = type.getConfigPath(definition);
try {
createFile(path);
} catch (IOException e) {
throw new SerializationException(e);
}
try {
FileConfig config = serializer(configClass).serializeFields(t, builder::build).checked();
config.save();
config.close();
} catch (Exception e) {
NightAutoConfig.LOGGER.error(
"Serialization failed for config {}! This will cause the program to stop writing anything to the file.",
type.getRelativeConfigPath(definition)
);
NightAutoConfig.LOGGER.error(e.getMessage(), e);
}
}
@Override
public T deserialize() throws SerializationException {
Path path = type.getConfigPath(definition);
try {
createFile(path);
} catch (IOException e) {
throw new SerializationException(e);
}
try {
FileConfig config = builder.build();
config.load();
if (config.isEmpty()) {
return createDefault();
} else {
return deserializer(configClass).deserializeFields(config, this::createDefault);
}
} catch (Exception e) {
NightAutoConfig.LOGGER.error(
"Deserialization failed for config {}! This will cause the program to ignore the existing modifications and use default values. This might be caused by a missing of {} on restricting value fallbacks.",
type.getRelativeConfigPath(definition),
SerdeDefault.class
);
NightAutoConfig.LOGGER.error(e.getMessage(), e);
return createDefault();
}
}
@Override
public T createDefault() {
return Utils.constructUnsafely(configClass);
}
private void createFile(Path path) throws IOException {
if (!Files.exists(path)) {
Files.createDirectories(path.getParent());
Files.createFile(path);
}
}
private ObjectSerializer serializer(Class<?> cls) {
var builder = ObjectSerializer.builder();
NightSerializers.provideToBuilder(builder);
// Register serializer providers
var providers = AnnotationUtil.getSerializerProviders(cls);
providers.forEach(builder::withSerializerProvider);
return builder.build();
}
private ObjectDeserializer deserializer(Class<?> cls) {
var builder = ObjectDeserializer.builder();
NightDeserializers.provideToBuilder(builder);
// Register deserializer providers
var providers = AnnotationUtil.getDeserializerProviders(cls);
providers.forEach(builder::withDeserializerProvider);
return builder.build();
}
}