Skip to content

Commit 75af797

Browse files
authored
fix: extract new config option for deleting disk history on logout (#2772)
* fix: extract new config option for deleting disk history on logout - fixes #2663 * Copyto is nullable
1 parent 06bf710 commit 75af797

File tree

3 files changed

+69
-20
lines changed

3 files changed

+69
-20
lines changed

worldedit-core/src/main/java/com/fastasyncworldedit/core/configuration/Config.java

Lines changed: 64 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import com.sk89q.worldedit.internal.util.LogManagerCompat;
77
import org.apache.logging.log4j.Logger;
88

9+
import javax.annotation.Nullable;
910
import java.io.ByteArrayOutputStream;
1011
import java.io.File;
1112
import java.io.PrintWriter;
@@ -18,6 +19,7 @@
1819
import java.lang.reflect.InvocationTargetException;
1920
import java.lang.reflect.Modifier;
2021
import java.lang.reflect.ParameterizedType;
22+
import java.util.AbstractMap;
2123
import java.util.ArrayList;
2224
import java.util.Arrays;
2325
import java.util.Collection;
@@ -31,10 +33,15 @@ public class Config {
3133
private static final Logger LOGGER = LogManagerCompat.getLogger();
3234

3335
private final Map<String, Object> removedKeyVals = new HashMap<>();
36+
@Nullable
37+
private Map<String, Map.Entry<String, Object>> copyTo = new HashMap<>();
38+
private boolean performCopyTo = false;
3439
private List<String> existingMigrateNodes = null;
3540

3641
public Config() {
37-
save(new PrintWriter(new ByteArrayOutputStream(0)), getClass(), this, 0);
42+
// This is now definitely required as the save -> load -> save order means the @CopiedFrom annotated fields work
43+
save(new PrintWriter(new ByteArrayOutputStream(0)), getClass(), this, 0, null);
44+
performCopyTo = true;
3845
}
3946

4047
/**
@@ -60,11 +67,12 @@ private <T> T get(String key, Class<?> root) {
6067

6168
/**
6269
* Set the value of a specific node. Probably throws some error if you supply non existing keys or invalid values.
70+
* This should only be called during loading of a config file
6371
*
6472
* @param key config node
6573
* @param value value
6674
*/
67-
private void set(String key, Object value, Class<?> root) {
75+
private void setLoadedNode(String key, Object value, Class<?> root) {
6876
String[] split = key.split("\\.");
6977
Object instance = getInstance(split, root);
7078
if (instance != null) {
@@ -74,8 +82,18 @@ private void set(String key, Object value, Class<?> root) {
7482
if (field.getAnnotation(Final.class) != null) {
7583
return;
7684
}
85+
if (copyTo != null) {
86+
copyTo.remove(key); // Remove if the config field is already written
87+
final Object finalValue = value;
88+
copyTo.replaceAll((copyToNode, entry) -> {
89+
if (!key.equals(entry.getKey())) {
90+
return entry;
91+
}
92+
return new AbstractMap.SimpleEntry<>(key, finalValue);
93+
});
94+
}
7795
Migrate migrate = field.getAnnotation(Migrate.class);
78-
if (existingMigrateNodes != null && migrate != null) {
96+
if (migrate != null) {
7997
existingMigrateNodes.add(migrate.value());
8098
}
8199
if (field.getType() == String.class && !(value instanceof String)) {
@@ -90,8 +108,9 @@ private void set(String key, Object value, Class<?> root) {
90108
}
91109
}
92110
removedKeyVals.put(key, value);
93-
LOGGER.error(
94-
"Failed to set config option: {}: {} | {} | {}.yml. This is likely because it was removed.",
111+
LOGGER.warn(
112+
"Failed to set config option: {}: {} | {} | {}.yml. This is likely because it was removed or was set with an " +
113+
"invalid value.",
95114
key,
96115
value,
97116
instance,
@@ -110,7 +129,7 @@ public boolean load(File file) {
110129
if (value instanceof MemorySection) {
111130
continue;
112131
}
113-
set(key, value, getClass());
132+
setLoadedNode(key, value, getClass());
114133
}
115134
for (String node : existingMigrateNodes) {
116135
removedKeyVals.remove(node);
@@ -133,7 +152,7 @@ public void save(File file) {
133152
}
134153
PrintWriter writer = new PrintWriter(file);
135154
Object instance = this;
136-
save(writer, getClass(), instance, 0);
155+
save(writer, getClass(), instance, 0, null);
137156
writer.close();
138157
} catch (Throwable e) {
139158
LOGGER.error("Failed to save config file: {}", file, e);
@@ -190,7 +209,7 @@ public void save(File file) {
190209
}
191210

192211
/**
193-
* Indicates that a field should be instantiated / created.
212+
* Indicates that a field should be migrated from a node that is deleted
194213
*
195214
* @since 2.10.0
196215
*/
@@ -202,6 +221,19 @@ public void save(File file) {
202221

203222
}
204223

224+
/**
225+
* Indicates that a field's default value should match another input if the config is otherwise already generated
226+
*
227+
* @since TODO
228+
*/
229+
@Retention(RetentionPolicy.RUNTIME)
230+
@Target({ElementType.FIELD})
231+
public @interface CopiedFrom {
232+
233+
String value();
234+
235+
}
236+
205237
@Ignore // This is not part of the config
206238
public static class ConfigBlock<T> {
207239

@@ -254,7 +286,7 @@ private String toYamlString(Object value, String spacing) {
254286
return value != null ? value.toString() : "null";
255287
}
256288

257-
private void save(PrintWriter writer, Class<?> clazz, final Object instance, int indent) {
289+
private void save(PrintWriter writer, Class<?> clazz, final Object instance, int indent, String parentNode) {
258290
try {
259291
String CTRF = System.lineSeparator();
260292
String spacing = StringMan.repeat(" ", indent);
@@ -274,7 +306,7 @@ private void save(PrintWriter writer, Class<?> clazz, final Object instance, int
274306
}
275307
if (current == ConfigBlock.class) {
276308
current = (Class<?>) ((ParameterizedType) (field.getGenericType())).getActualTypeArguments()[0];
277-
handleConfigBlockSave(writer, instance, indent, field, spacing, CTRF, current);
309+
handleConfigBlockSave(writer, instance, indent, field, spacing, CTRF, current, parentNode);
278310
continue;
279311
} else if (!removedKeyVals.isEmpty()) {
280312
Migrate migrate = field.getAnnotation(Migrate.class);
@@ -283,6 +315,17 @@ private void save(PrintWriter writer, Class<?> clazz, final Object instance, int
283315
field.set(instance, value);
284316
}
285317
}
318+
CopiedFrom copiedFrom;
319+
if (copyTo != null && (copiedFrom = field.getAnnotation(CopiedFrom.class)) != null) {
320+
String node = toNodeName(field.getName());
321+
node = parentNode == null ? node : parentNode + "." + node;
322+
Map.Entry<String, Object> entry = copyTo.remove(node);
323+
if (entry == null) {
324+
copyTo.put(node,new AbstractMap.SimpleEntry<>(copiedFrom.value(), null));
325+
} else {
326+
field.set(instance, entry.getValue());
327+
}
328+
}
286329
Create create = field.getAnnotation(Create.class);
287330
if (create != null) {
288331
Object value = field.get(instance);
@@ -296,11 +339,12 @@ private void save(PrintWriter writer, Class<?> clazz, final Object instance, int
296339
writer.write(spacing + "# " + commentLine + CTRF);
297340
}
298341
}
299-
writer.write(spacing + toNodeName(current.getSimpleName()) + ":" + CTRF);
342+
String node = toNodeName(current.getSimpleName());
343+
writer.write(spacing + node + ":" + CTRF);
300344
if (value == null) {
301345
field.set(instance, value = current.getDeclaredConstructor().newInstance());
302346
}
303-
save(writer, current, value, indent + 2);
347+
save(writer, current, value, indent + 2, parentNode == null ? node : parentNode + "." + node);
304348
} else {
305349
writer.write(spacing + toNodeName(field.getName() + ": ") + toYamlString(
306350
field.get(instance),
@@ -311,6 +355,10 @@ private void save(PrintWriter writer, Class<?> clazz, final Object instance, int
311355
} catch (Throwable e) {
312356
LOGGER.error("Failed to save config file", e);
313357
}
358+
if (parentNode == null && performCopyTo) {
359+
performCopyTo = false;
360+
copyTo = null;
361+
}
314362
}
315363

316364
private <T> void handleConfigBlockSave(
@@ -320,7 +368,8 @@ private <T> void handleConfigBlockSave(
320368
Field field,
321369
String spacing,
322370
String CTRF,
323-
Class<T> current
371+
Class<T> current,
372+
String parentNode
324373
) throws IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchMethodException {
325374
Comment comment = current.getAnnotation(Comment.class);
326375
if (comment != null) {
@@ -330,6 +379,7 @@ private <T> void handleConfigBlockSave(
330379
}
331380
BlockName blockNames = current.getAnnotation(BlockName.class);
332381
if (blockNames != null) {
382+
String node = toNodeName(current.getSimpleName());
333383
writer.write(spacing + toNodeName(current.getSimpleName()) + ":" + CTRF);
334384
ConfigBlock<T> configBlock = (ConfigBlock<T>) field.get(instance);
335385
if (configBlock == null || configBlock.getInstances().isEmpty()) {
@@ -343,7 +393,7 @@ private <T> void handleConfigBlockSave(
343393
for (Map.Entry<String, T> entry : configBlock.getRaw().entrySet()) {
344394
String key = entry.getKey();
345395
writer.write(spacing + " " + toNodeName(key) + ":" + CTRF);
346-
save(writer, current, entry.getValue(), indent + 4);
396+
save(writer, current, entry.getValue(), indent + 4, parentNode == null ? node : parentNode + "." + node);
347397
}
348398
}
349399
}

worldedit-core/src/main/java/com/fastasyncworldedit/core/configuration/Settings.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -518,6 +518,9 @@ public static class HISTORY {
518518
public int DELETE_AFTER_DAYS = 7;
519519
@Comment("Delete history in memory on logout (does not effect disk)")
520520
public boolean DELETE_ON_LOGOUT = true;
521+
@Comment("Delete history on disk on logout")
522+
@CopiedFrom("history.delete-on-logout")
523+
public boolean DELETE_DISK_ON_LOGOUT = false;
521524
@Comment({
522525
"If history should be enabled by default for plugins using WorldEdit:",
523526
" - It is faster to have disabled",

worldedit-core/src/main/java/com/sk89q/worldedit/entity/Player.java

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,19 +22,15 @@
2222
import com.fastasyncworldedit.core.Fawe;
2323
import com.fastasyncworldedit.core.configuration.Caption;
2424
import com.fastasyncworldedit.core.configuration.Settings;
25-
import com.fastasyncworldedit.core.extent.clipboard.DiskOptimizedClipboard;
2625
import com.fastasyncworldedit.core.internal.exception.FaweClipboardVersionMismatchException;
2726
import com.fastasyncworldedit.core.regions.FaweMaskManager;
2827
import com.fastasyncworldedit.core.util.MainUtil;
29-
import com.sk89q.worldedit.EmptyClipboardException;
3028
import com.sk89q.worldedit.IncompleteRegionException;
3129
import com.sk89q.worldedit.LocalSession;
3230
import com.sk89q.worldedit.WorldEdit;
3331
import com.sk89q.worldedit.WorldEditException;
3432
import com.sk89q.worldedit.blocks.BaseItemStack;
3533
import com.sk89q.worldedit.extension.platform.Actor;
36-
import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;
37-
import com.sk89q.worldedit.extent.clipboard.Clipboard;
3834
import com.sk89q.worldedit.extent.inventory.BlockBag;
3935
import com.sk89q.worldedit.function.mask.Mask;
4036
import com.sk89q.worldedit.internal.util.DeprecationUtil;
@@ -43,7 +39,6 @@
4339
import com.sk89q.worldedit.math.Vector3;
4440
import com.sk89q.worldedit.regions.Region;
4541
import com.sk89q.worldedit.regions.RegionSelector;
46-
import com.sk89q.worldedit.session.ClipboardHolder;
4742
import com.sk89q.worldedit.util.Direction;
4843
import com.sk89q.worldedit.util.HandSide;
4944
import com.sk89q.worldedit.util.Location;
@@ -432,7 +427,8 @@ default void unregister() {
432427
} else if (Settings.settings().CLIPBOARD.DELETE_ON_LOGOUT) {
433428
session.setClipboard(null);
434429
}
435-
if (Settings.settings().HISTORY.DELETE_ON_LOGOUT) {
430+
if (!Settings.settings().HISTORY.USE_DISK && Settings.settings().HISTORY.DELETE_ON_LOGOUT
431+
|| Settings.settings().HISTORY.USE_DISK && Settings.settings().HISTORY.DELETE_DISK_ON_LOGOUT) {
436432
session.clearHistory();
437433
}
438434
}

0 commit comments

Comments
 (0)