From 5d2db397c49e5b526154b66daa2cd9d8d05a403d Mon Sep 17 00:00:00 2001 From: zml Date: Tue, 20 Dec 2022 20:01:43 -0800 Subject: [PATCH] yaml: whitespace/comment fixes --- .../configurate/yaml/MergeTag.java | 26 ++++ .../configurate/yaml/ScalarStyle.java | 2 +- .../spongepowered/configurate/yaml/Tag.java | 10 +- .../configurate/yaml/Yaml11Tags.java | 15 +-- .../yaml/YamlConfigurationLoader.java | 10 +- .../configurate/yaml/YamlParserComposer.java | 34 ++++-- .../configurate/yaml/YamlVisitor.java | 46 ++++--- .../configurate/yaml/IntegrationTests.groovy | 6 +- .../yaml/YamlParserComposerTest.groovy | 11 +- .../configurate/yaml/YamlTest.groovy | 52 +++++--- .../configurate/yaml/essx-example.yml | 112 +++++++++--------- .../configurate/yaml/essx-legacy.yml | 2 +- .../configurate/yaml/mobcleaner-example.yml | 8 ++ 13 files changed, 204 insertions(+), 130 deletions(-) create mode 100644 format/yaml/src/main/java/org/spongepowered/configurate/yaml/MergeTag.java diff --git a/format/yaml/src/main/java/org/spongepowered/configurate/yaml/MergeTag.java b/format/yaml/src/main/java/org/spongepowered/configurate/yaml/MergeTag.java new file mode 100644 index 000000000..664cc66ce --- /dev/null +++ b/format/yaml/src/main/java/org/spongepowered/configurate/yaml/MergeTag.java @@ -0,0 +1,26 @@ +/* + * Configurate + * Copyright (C) zml and Configurate contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.spongepowered.configurate.yaml; + +final class MergeTag { + + static final MergeTag INSTANCE = new MergeTag(); + + private MergeTag() { + } + +} diff --git a/format/yaml/src/main/java/org/spongepowered/configurate/yaml/ScalarStyle.java b/format/yaml/src/main/java/org/spongepowered/configurate/yaml/ScalarStyle.java index e4a64aff0..4c462e2dc 100644 --- a/format/yaml/src/main/java/org/spongepowered/configurate/yaml/ScalarStyle.java +++ b/format/yaml/src/main/java/org/spongepowered/configurate/yaml/ScalarStyle.java @@ -113,7 +113,7 @@ static ScalarStyle fromSnakeYaml(final DumperOptions.ScalarStyle style) { } static { - for (ScalarStyle style : values()) { + for (final ScalarStyle style : values()) { BY_SNAKE.put(style.snake, style); } } diff --git a/format/yaml/src/main/java/org/spongepowered/configurate/yaml/Tag.java b/format/yaml/src/main/java/org/spongepowered/configurate/yaml/Tag.java index 40fc2d9de..8dd8ffdd4 100644 --- a/format/yaml/src/main/java/org/spongepowered/configurate/yaml/Tag.java +++ b/format/yaml/src/main/java/org/spongepowered/configurate/yaml/Tag.java @@ -69,7 +69,12 @@ public String toString(final String own) { this(tagUri, supportedTypes, pattern, null); } - Scalar(final URI tagUri, final Set> supportedTypes, final @Nullable Pattern pattern, final @Nullable ScalarStyle preferredScalarStyle) { + Scalar( + final URI tagUri, + final Set> supportedTypes, + final @Nullable Pattern pattern, + final @Nullable ScalarStyle preferredScalarStyle + ) { super(tagUri, supportedTypes); this.pattern = pattern; this.preferredScalarStyle = preferredScalarStyle; @@ -89,7 +94,8 @@ public String toString(final String own) { } /** - * Get the preferred scalar style to use for this type, when none is specifically used. + * Get the preferred scalar style to use for this type, when none is + * specifically used. * * @return the preferred scalar style * @since 4.2.0 diff --git a/format/yaml/src/main/java/org/spongepowered/configurate/yaml/Yaml11Tags.java b/format/yaml/src/main/java/org/spongepowered/configurate/yaml/Yaml11Tags.java index 6b0420168..5a319df9d 100644 --- a/format/yaml/src/main/java/org/spongepowered/configurate/yaml/Yaml11Tags.java +++ b/format/yaml/src/main/java/org/spongepowered/configurate/yaml/Yaml11Tags.java @@ -73,15 +73,16 @@ public String toString(final byte[] own) { * * @implNote Canonically, these are y|n in YAML 1.1, but because YAML 1.2 * will only support true|false, we will treat those as the default - * output format. + * output format. We also modify the regex to only automatically match + * true/false and on/off in order to avoid cases of confusion (such as + * the classic Norway problem). * @see tag:yaml.org,2002:bool * @since 4.2.0 */ public static final Tag.Scalar BOOL = new Tag.Scalar( yamlOrg("bool"), UnmodifiableCollections.toSet(Boolean.class), - Pattern.compile("y|Y|yes|Yes|YES|n|N|no|No|NO" - + "|true|True|TRUE|false|False|FALSE" + Pattern.compile("true|True|TRUE|false|False|FALSE" + "|on|On|ON|off|Off|OFF") ) { private final Set trues = UnmodifiableCollections.toSet( @@ -189,13 +190,13 @@ public String toString(final Number own) { // used as map key, where the next node will be a reference that should be merged in to this node @Override - public Object fromString(final String input) throws ParsingException { - throw new ParsingException(ParsingException.UNKNOWN_POS, ParsingException.UNKNOWN_POS, null, "Merge keys are not yet implemented", null); + public Object fromString(final String input) { + return MergeTag.INSTANCE; } @Override - public String toString(final Object own) { - return own.toString(); + public String toString(final Object own) throws ParsingException { + throw new ParsingException(ParsingException.UNKNOWN_POS, ParsingException.UNKNOWN_POS, null, "Merge keys cannot be serialized", null); } }; diff --git a/format/yaml/src/main/java/org/spongepowered/configurate/yaml/YamlConfigurationLoader.java b/format/yaml/src/main/java/org/spongepowered/configurate/yaml/YamlConfigurationLoader.java index 59b79208f..5e8696fc4 100644 --- a/format/yaml/src/main/java/org/spongepowered/configurate/yaml/YamlConfigurationLoader.java +++ b/format/yaml/src/main/java/org/spongepowered/configurate/yaml/YamlConfigurationLoader.java @@ -30,8 +30,8 @@ import org.spongepowered.configurate.util.UnmodifiableCollections; import org.yaml.snakeyaml.DumperOptions; import org.yaml.snakeyaml.LoaderOptions; -import org.yaml.snakeyaml.reader.StreamReader; import org.yaml.snakeyaml.events.DocumentStartEvent; +import org.yaml.snakeyaml.reader.StreamReader; import java.io.BufferedReader; import java.io.Writer; @@ -210,6 +210,8 @@ protected void populate(final LoaderOptionSource options) { if (declared != null) { this.style = declared; } + + this.enableComments = options.getBoolean(false, "yaml", "comments-enabled"); } /** @@ -317,7 +319,6 @@ public YamlConfigurationLoader build() { private final DumperOptions options; private final YamlVisitor visitor; private final @Nullable NodeStyle defaultNodeStyle; - private final boolean enableComments; private YamlConfigurationLoader(final Builder builder) { super(builder, new CommentHandler[] {CommentHandlers.HASH}); @@ -326,19 +327,18 @@ private YamlConfigurationLoader(final Builder builder) { opts.setDefaultFlowStyle(NodeStyle.asSnakeYaml(builder.nodeStyle())); opts.setProcessComments(builder.commentsEnabled()); this.defaultNodeStyle = builder.nodeStyle(); - this.enableComments = builder.commentsEnabled(); this.options = opts; this.loader = new LoaderOptions() .setAcceptTabs(true) .setProcessComments(builder.commentsEnabled()); this.loader.setCodePointLimit(Integer.MAX_VALUE); - this.visitor = new YamlVisitor(this.enableComments, true, Yaml11Tags.REPOSITORY); + this.visitor = new YamlVisitor(true, Yaml11Tags.REPOSITORY); } @Override protected void loadInternal(final CommentedConfigurationNode node, final BufferedReader reader) throws ParsingException { // Match the superclass implementation, except we substitute our own scanner implementation - final YamlParserComposer parser = new YamlParserComposer(new StreamReader(reader), this.loader, Yaml11Tags.REPOSITORY, this.enableComments); + final YamlParserComposer parser = new YamlParserComposer(new StreamReader(reader), this.loader, Yaml11Tags.REPOSITORY); parser.singleDocumentStream(node); } diff --git a/format/yaml/src/main/java/org/spongepowered/configurate/yaml/YamlParserComposer.java b/format/yaml/src/main/java/org/spongepowered/configurate/yaml/YamlParserComposer.java index 31d5d2d30..1763af4c2 100644 --- a/format/yaml/src/main/java/org/spongepowered/configurate/yaml/YamlParserComposer.java +++ b/format/yaml/src/main/java/org/spongepowered/configurate/yaml/YamlParserComposer.java @@ -66,7 +66,6 @@ final class YamlParserComposer extends ParserImpl { private static final int FRAME_STACK_INCREMENT = 8; private @Nullable StringBuilder commentCollector; - private final boolean processComments; private final boolean stripLeadingCommentWhitespace = true; final Map aliases = new HashMap<>(); final TagRepository tags; @@ -75,9 +74,8 @@ final class YamlParserComposer extends ParserImpl { private Frame[] frames = new Frame[INITIAL_STACK_SIZE]; private int framePointer = -1; - YamlParserComposer(final StreamReader reader, final LoaderOptions opts, final TagRepository tags, final boolean enableComments) { + YamlParserComposer(final StreamReader reader, final LoaderOptions opts, final TagRepository tags) { super(new ScannerImpl(reader, opts)); - this.processComments = enableComments; this.tags = tags; } @@ -226,6 +224,9 @@ static class Frame { static final int SUPPRESS_COMMENTS = 1; // whether to associate comment events with this node static final int SAVE_NODE = 1 << 1; // don't clear node when popping + static final int MERGE_REFERENCE_VALUE = 1 << 2; // when values have an anchor + + static final int UNINHERITABLE_FLAGS = MERGE_REFERENCE_VALUE; @MonotonicNonNull ComposerState state; @@ -236,13 +237,13 @@ static class Frame { * tag resolution.

*/ @Nullable Tag resolvedTag; - ConfigurationNode node; + @MonotonicNonNull ConfigurationNode node; int flags; void init(final ComposerState state, final Frame parent) { this.state = state; this.node = parent.node; - this.flags = parent.flags; + this.flags = parent.flags & ~UNINHERITABLE_FLAGS; this.resolvedTag = null; } @@ -323,10 +324,6 @@ void applyComment(final @Nullable String comment, final ConfigurationNode node) } void collectComments() { - if (!this.processComments) { - return; - } - while (this.peekEvent().is(Event.ID.Comment)) { final CommentEvent event = (CommentEvent) this.getEvent(); if (event.getCommentType() != CommentType.BLANK_LINE) { @@ -342,6 +339,10 @@ void collectComments() { } else { commentCollector.append(event.getValue()); } + } else if (this.commentCollector != null + && this.commentCollector.length() > 0 + && this.peekEvent().is(Event.ID.Comment)) { // mid-comment blank line + this.commentCollector.append("\n"); } } } @@ -607,6 +608,11 @@ public Frame accept(final Frame head, final YamlParserComposer self) throws Pars if (keyHolder == null) { throw new IllegalStateException("null keyHolder"); } + // if merge key, set a flag on the next value state + if (keyHolder.ownHint(YamlConfigurationLoader.TAG) == Yaml11Tags.MERGE) { + head.addFlag(Frame.MERGE_REFERENCE_VALUE); + } + final @Nullable Object key = keyHolder.raw(); if (key == null) { throw head.makeError(self.scanner.peekToken().getStartMark(), "'null' is not permitted as a mapping key", null); @@ -683,8 +689,14 @@ private Alias() { if (target == null) { throw head.makeError(event.getStartMark(), "Unknown anchor '" + event.getAnchor() + "'", null); } - head.node.from(target); // TODO: Reference node types - head.node.hint(YamlConfigurationLoader.ANCHOR_ID, null); // don't duplicate alias + final ConfigurationNode into; + if (head.hasFlag(Frame.MERGE_REFERENCE_VALUE)) { + into = head.node.parent(); + } else { + into = head.node; + } + into.from(target); // TODO: Reference node types + into.hint(YamlConfigurationLoader.ANCHOR_ID, null); // don't duplicate alias return null; } diff --git a/format/yaml/src/main/java/org/spongepowered/configurate/yaml/YamlVisitor.java b/format/yaml/src/main/java/org/spongepowered/configurate/yaml/YamlVisitor.java index 39b815be6..038beeebf 100644 --- a/format/yaml/src/main/java/org/spongepowered/configurate/yaml/YamlVisitor.java +++ b/format/yaml/src/main/java/org/spongepowered/configurate/yaml/YamlVisitor.java @@ -52,7 +52,7 @@ final class YamlVisitor implements ConfigurationVisitor && this.enableComments) { + if (node instanceof CommentedConfigurationNodeIntermediary<@NonNull ?> && state.options.isProcessComments()) { final @Nullable String comment = ((CommentedConfigurationNodeIntermediary<@NonNull ?>) node).comment(); if (comment != null) { - if (this.shouldPadComments && node != state.start && !node.parent().isList()) { - // todo: try and avoid emitting a blank line when we're the first element of a mapping? - state.emit(WHITESPACE); + if (this.shouldPadComments && node != state.start) { + if (!state.first) { + if (!node.parent().isList()) { + state.emit(WHITESPACE); + } + } else { + state.first = false; + } } for (final String line : COMMENT_SPLIT.split(comment, -1)) { if (line.isEmpty()) { @@ -111,13 +114,14 @@ public void enterNode(final ConfigurationNode node, final State state) throws Co @Override public void enterMappingNode(final ConfigurationNode node, final State state) throws ConfigurateException { final TagRepository.AnalyzedTag analysis = this.tags.analyze(node); + state.first = true; state.emit(new MappingStartEvent( this.anchor(node), analysis.actual().tagUri().toString(), analysis.implicit(), null, null, - NodeStyle.asSnakeYaml(this.determineStyle(node, state)) + NodeStyle.asSnakeYaml(state.determineStyle(node)) )); } @@ -130,7 +134,7 @@ public void enterListNode(final ConfigurationNode node, final State state) throw analysis.implicit(), null, null, - NodeStyle.asSnakeYaml(this.determineStyle(node, state)) + NodeStyle.asSnakeYaml(state.determineStyle(node)) )); } @@ -168,6 +172,7 @@ public void enterScalarNode(final ConfigurationNode node, final State state) thr @Override public void exitMappingNode(final ConfigurationNode node, final State state) throws ConfigurateException { + state.first = false; // only true if empty map state.emit(MAPPING_END); } @@ -181,29 +186,32 @@ public Void endVisit(final State state) { return null; } - private @Nullable NodeStyle determineStyle(final ConfigurationNode node, final State state) { - // todo: some basic rules: - // - if a node has any children with comments, convert it to block style - // - when the default style is `AUTO` and `flowLevel` == 0, - final @Nullable NodeStyle style = node.hint(YamlConfigurationLoader.NODE_STYLE); - return style == null ? state.defaultStyle : style; - } - private @Nullable String anchor(final ConfigurationNode node) { return node.hint(YamlConfigurationLoader.ANCHOR_ID); } - static class State { + static final class State { private final Emitter emit; + final DumperOptions options; @Nullable ConfigurationNode start; final @Nullable NodeStyle defaultStyle; ConfigurationNode mapKeyHolder; + boolean first; // reset to true at the beginning of each mapping node State(final DumperOptions options, final Writer writer, final @Nullable NodeStyle defaultStyle) { this.emit = new Emitter(writer, options); + this.options = options; this.defaultStyle = defaultStyle; } + @Nullable NodeStyle determineStyle(final ConfigurationNode node) { + // todo: some basic rules: + // - if a node has any children with comments, convert it to block style + // - when the default style is `AUTO` and `flowLevel` == 0, + final @Nullable NodeStyle style = node.hint(YamlConfigurationLoader.NODE_STYLE); + return style == null ? this.defaultStyle : style; + } + public void emit(final Event event) throws ConfigurateException { try { this.emit.emit(event); diff --git a/format/yaml/src/test/groovy/org/spongepowered/configurate/yaml/IntegrationTests.groovy b/format/yaml/src/test/groovy/org/spongepowered/configurate/yaml/IntegrationTests.groovy index 70d77e33a..54729b001 100644 --- a/format/yaml/src/test/groovy/org/spongepowered/configurate/yaml/IntegrationTests.groovy +++ b/format/yaml/src/test/groovy/org/spongepowered/configurate/yaml/IntegrationTests.groovy @@ -28,7 +28,7 @@ class IntegrationTests implements YamlTest { @Test void testEssentialsXDefault() { - def input = this.class.getResourceAsStream("essx-example.yml").text + def input = this.class.getResourceAsStream("essx-example.yml").getText('utf-8') def node = parseString(input) def serialized = dump(node) @@ -38,7 +38,7 @@ class IntegrationTests implements YamlTest { @Test void testEssentialsXLegacy() { - def input = this.class.getResourceAsStream("essx-legacy.yml").text + def input = this.class.getResourceAsStream("essx-legacy.yml").getText('utf-8') def node = parseString(input) def serialized = dump(node) @@ -48,7 +48,7 @@ class IntegrationTests implements YamlTest { @Test void testMobCleaner() { - def input = this.class.getResourceAsStream("mobcleaner-example.yml").text + def input = this.class.getResourceAsStream("mobcleaner-example.yml").getText('utf-8') def node = parseString(input) def serialized = dump(node) diff --git a/format/yaml/src/test/groovy/org/spongepowered/configurate/yaml/YamlParserComposerTest.groovy b/format/yaml/src/test/groovy/org/spongepowered/configurate/yaml/YamlParserComposerTest.groovy index a07568110..983dd1731 100644 --- a/format/yaml/src/test/groovy/org/spongepowered/configurate/yaml/YamlParserComposerTest.groovy +++ b/format/yaml/src/test/groovy/org/spongepowered/configurate/yaml/YamlParserComposerTest.groovy @@ -191,8 +191,6 @@ class YamlParserComposerTest implements YamlTest { # - def """ - println dump(result) - assertThat(result.node('hello').comment()) .isEqualTo("the greetings") } @@ -200,13 +198,12 @@ class YamlParserComposerTest implements YamlTest { // Test that implicit tags are resolved properly @Test - @Disabled("not yet implemented") void testMergeKey() { def result = parseString """\ src: &ref old: merged dest: - >>: *ref + <<: *ref new: added """.stripIndent(true) @@ -219,7 +216,7 @@ class YamlParserComposerTest implements YamlTest { } @Test - void testYIsBooleanForSomeReason() { + void testYIsNotBoolean() { def result = parseString """\ asVal: y y: asKey @@ -229,9 +226,9 @@ class YamlParserComposerTest implements YamlTest { extracting { it.virtual() } .is(false) extracting { it.raw() } - .isEqualTo(true) + .isEqualTo("y") } - assertThat(result.node(true)).with { + assertThat(result.node("y")).with { extracting { it.virtual() } .is(false) extracting { it.raw() } diff --git a/format/yaml/src/test/groovy/org/spongepowered/configurate/yaml/YamlTest.groovy b/format/yaml/src/test/groovy/org/spongepowered/configurate/yaml/YamlTest.groovy index c92588aff..3f9a81291 100644 --- a/format/yaml/src/test/groovy/org/spongepowered/configurate/yaml/YamlTest.groovy +++ b/format/yaml/src/test/groovy/org/spongepowered/configurate/yaml/YamlTest.groovy @@ -19,6 +19,9 @@ package org.spongepowered.configurate.yaml import static org.junit.jupiter.api.Assertions.assertNotNull import org.spongepowered.configurate.CommentedConfigurationNode +import org.yaml.snakeyaml.LoaderOptions +import org.yaml.snakeyaml.events.CollectionEndEvent +import org.yaml.snakeyaml.events.CollectionStartEvent import org.yaml.snakeyaml.parser.ParserImpl import org.yaml.snakeyaml.reader.StreamReader import org.yaml.snakeyaml.scanner.ScannerImpl @@ -27,17 +30,13 @@ trait YamlTest { CommentedConfigurationNode parseString(final String input) { // Print events - def scanner = new ScannerImpl(new StreamReader(input)) - scanner.parseComments = true - scanner.acceptTabs = true - def parser = new ParserImpl(scanner) - - while (true) { - println parser.getEvent() - if (!parser.peekEvent()) break + def loaderOpts = new LoaderOptions().tap { + processComments = true + acceptTabs = true } + this.dumpEvents(new StreamReader(input), loaderOpts) - final YamlParserComposer loader = new YamlParserComposer(new StreamReader(input), Yaml11Tags.REPOSITORY, true) + final YamlParserComposer loader = new YamlParserComposer(new StreamReader(input), loaderOpts, Yaml11Tags.REPOSITORY) final CommentedConfigurationNode result = CommentedConfigurationNode.root() loader.singleDocumentStream(result) return result @@ -45,26 +44,43 @@ trait YamlTest { CommentedConfigurationNode parseResource(final URL url) { // Print events + def loaderOpts = new LoaderOptions().tap { + processComments = true + acceptTabs = true + } url.openStream().withReader('UTF-8') {reader -> - def scanner = new ScannerImpl(new StreamReader(reader)) - scanner.parseComments = true - scanner.acceptTabs = true - def parser = new ParserImpl(scanner) - while (true) { - println parser.getEvent() - if (!parser.peekEvent()) break - } + this.dumpEvents(new StreamReader(reader), loaderOpts) } assertNotNull(url, "Expected resource is missing") url.openStream().withReader('UTF-8') { reader -> - final YamlParserComposer loader = new YamlParserComposer(new StreamReader(reader), Yaml11Tags.REPOSITORY, true) + final YamlParserComposer loader = new YamlParserComposer(new StreamReader(reader), loaderOpts, Yaml11Tags.REPOSITORY) final CommentedConfigurationNode result = CommentedConfigurationNode.root() loader.singleDocumentStream(result) return result } } + private void dumpEvents(StreamReader reader, LoaderOptions loaderOpts) { + def scanner = new ScannerImpl(reader, loaderOpts) + def parser = new ParserImpl(scanner) + int indentLevel = 0 + while (true) { + if (parser.peekEvent() instanceof CollectionEndEvent) { + indentLevel-- + } + indentLevel.times { + print " " + } + if (parser.peekEvent() instanceof CollectionStartEvent) { + indentLevel++ + } + + println parser.getEvent() + if (!parser.peekEvent()) break + } + } + String dump(final CommentedConfigurationNode input) { return dump(input, null) } diff --git a/format/yaml/src/test/resources/org/spongepowered/configurate/yaml/essx-example.yml b/format/yaml/src/test/resources/org/spongepowered/configurate/yaml/essx-example.yml index 382d9ac6f..76ed4502f 100644 --- a/format/yaml/src/test/resources/org/spongepowered/configurate/yaml/essx-example.yml +++ b/format/yaml/src/test/resources/org/spongepowered/configurate/yaml/essx-example.yml @@ -51,23 +51,23 @@ change-displayname: true # When this option is enabled, the (tab) player list will be updated with the displayname. # The value of change-displayname (above) has to be true. -#change-playerlist: true +# change-playerlist: true # When EssentialsChat.jar isn't used, force essentials to add the prefix and suffix from permission plugins to displayname. # This setting is ignored if EssentialsChat.jar is used, and defaults to 'true'. # The value of change-displayname (above) has to be true. # Do not edit this setting unless you know what you are doing! -#add-prefix-suffix: false +# add-prefix-suffix: false # When this option is enabled, player prefixes will be shown in the playerlist. # This feature only works for Minecraft version 1.8 and higher. # This value of change-playerlist has to be true -#add-prefix-in-playerlist: true +# add-prefix-in-playerlist: true # When this option is enabled, player suffixes will be shown in the playerlist. -# This feature only works for Minecraft version 1.8 and higher. +# This feature only works for Minecraft version 1.8 and higher. # This value of change-playerlist has to be true -#add-suffix-in-playerlist: true +# add-suffix-in-playerlist: true # If the teleport destination is unsafe, should players be teleported to the nearest safe location? # If this is set to true, Essentials will attempt to teleport players close to the intended destination. @@ -350,30 +350,30 @@ use-nbt-serialization-in-createkit: false # Color is not an actual sign, it's for enabling using color codes on signs, when the correct permissions are given. enabledSigns: - #- color - #- balance - #- buy - #- sell - #- trade - #- free - #- warp - #- kit - #- mail - #- enchant - #- gamemode - #- heal - #- info - #- spawnmob - #- repair - #- time - #- weather - #- anvil - #- cartography - #- disposal - #- grindstone - #- loom - #- smithing - #- workbench + # - color + # - balance + # - buy + # - sell + # - trade + # - free + # - warp + # - kit + # - mail + # - enchant + # - gamemode + # - heal + # - info + # - spawnmob + # - repair + # - time + # - weather + # - anvil + # - cartography + # - disposal + # - grindstone + # - loom + # - smithing + # - workbench # How many times per second can Essentials signs be interacted with per player. # Values should be between 1-20, 20 being virtually no lag protection. @@ -392,7 +392,7 @@ allow-old-id-signs: false # # See https://github.com/drtshock/Essentials/pull/699 for more information. unprotected-sign-names: - #- kit + # - kit # Backup runs a custom batch/bash command at a specified interval. # The server will save the world before executing the backup command, and disable @@ -406,7 +406,7 @@ backup: # Unless you add a valid backup command or script here, this feature will be useless. # Use 'save-all' to simply force regular world saving without backup. # The example command below utilizes rdiff-backup: https://rdiff-backup.net/ - #command: 'rdiff-backup World1 backups/World1' + # command: 'rdiff-backup World1 backups/World1' # Set this true to enable permission per warp. per-warp-permission: false @@ -416,14 +416,14 @@ per-warp-permission: false # Detailed instructions and examples can be found on the wiki: http://wiki.ess3.net/wiki/List list: # To merge groups, list the groups you wish to merge - #Staff: owner admin moderator + # Staff: owner admin moderator Admins: owner admin # To limit groups, set a max user limit - #builder: 20 + # builder: 20 # To hide groups, set the group as hidden - #default: hidden + # default: hidden # Uncomment the line below to simply list all players with no grouping - #Players: '*' + # Players: '*' # Displays real names in /list next to players who are using a nickname. real-names-on-list: false @@ -436,7 +436,7 @@ debug: false # For example, to set language to English, set locale to en, to use the file "messages_en.properties". # Don't forget to remove the # in front of the line. # For more information, visit http://wiki.ess3.net/wiki/Locale -#locale: en +# locale: en # Turn off god mode when people leave the server. remove-god-on-disconnect: false @@ -485,7 +485,7 @@ sleep-ignores-afk-players: true # Users with the permission node essentials.sleepingignored will always be ignored. sleep-ignores-vanished-player: true -# Set the player's list name when they are AFK. This is none by default which specifies that Essentials +# Set the player's list name when they are AFK. This is none by default which specifies that Essentials # should not interfere with the AFK player's list name. # You may use color codes, use {USERNAME} the player's name or {PLAYER} for the player's displayname. afk-list-name: "none" @@ -522,7 +522,7 @@ allow-silent-join-quit: false # or set this to "" to hide the message entirely. # Available placeholders: -# {PLAYER} - The player's displayname. +# {PLAYER} - The player's displayname. # {USERNAME} - The player's username. # {PREFIX} - The player's prefix. # {SUFFIX} - The player's suffix. @@ -538,7 +538,7 @@ custom-quit-message: "none" # Set this to "none" to use the the "custom-join-message" above for every join. # Available placeholders: -# {PLAYER} - The player's displayname. +# {PLAYER} - The player's displayname. # {USERNAME} - The player's username. # {OLDUSERNAME} - The player's old username. # {PREFIX} - The player's prefix. @@ -586,20 +586,20 @@ repair-enchanted: true # Warning: Mixing and overleveling some enchantments can cause issues with clients, servers and plugins. unsafe-enchantments: false -#Do you want Essentials to keep track of previous location for /back in the teleport listener? -#If you set this to true any plugin that uses teleport will have the previous location registered. +# Do you want Essentials to keep track of previous location for /back in the teleport listener? +# If you set this to true any plugin that uses teleport will have the previous location registered. register-back-in-listener: false -#Delay to wait before people can cause attack damage after logging in. +# Delay to wait before people can cause attack damage after logging in. login-attack-delay: 5 -#Set the max fly speed, values range from 0.1 to 1.0 +# Set the max fly speed, values range from 0.1 to 1.0 max-fly-speed: 0.8 -#Set the max walk speed, values range from 0.1 to 1.0 +# Set the max walk speed, values range from 0.1 to 1.0 max-walk-speed: 0.8 -#Set the maximum amount of mail that can be sent within a minute. +# Set the maximum amount of mail that can be sent within a minute. mails-per-minute: 1000 # Set the maximum time /mute can be used for in seconds. @@ -674,8 +674,8 @@ delay-motd: 0 # A list of commands that should have their complementary confirm commands enabled by default. # This is empty by default, for the latest list of valid commands see the latest source config.yml. default-enabled-confirm-commands: -#- pay -#- clearinventory +# - pay +# - clearinventory # Where should Essentials teleport players when they are freed from jail? # You can set to "back" to have them teleported to where they were before they were jailed, "spawn" to have them @@ -780,12 +780,12 @@ starting-balance: 0 # Some commands like /repair have sub-costs, check the wiki for more information. command-costs: # /example costs $1000 PER USE - #example: 1000 + # example: 1000 # /kit tools costs $1500 PER USE - #kit-tools: 1500 + # kit-tools: 1500 # Set this to a currency symbol you want to use. -# Remember, if you want to use special characters in this document, +# Remember, if you want to use special characters in this document, # such as accented letters, you MUST save the file as UTF-8, not ANSI. currency-symbol: '$' @@ -822,7 +822,7 @@ show-zero-baltop: true # The format of currency, excluding symbols. See currency-symbol-format-locale for symbol configuration. # # "#,##0.00" is how the majority of countries display currency. -#currency-format: "#,##0.00" +# currency-format: "#,##0.00" # Format currency symbols. Some locales use , and . interchangeably. # Some formats do not display properly in-game due to faulty Minecraft font rendering. @@ -830,7 +830,7 @@ show-zero-baltop: true # For 1.234,50 use de-DE # For 1,234.50 use en-US # For 1'234,50 use fr-ch -#currency-symbol-format-locale: en-US +# currency-symbol-format-locale: en-US ############################################################ # +------------------------------------------------------+ # @@ -895,7 +895,7 @@ chat: # If you are using group formats make sure to remove the '#' to allow the setting to be read. # Note: Group names are case-sensitive so you must match them up with your permission plugin. - + # You can use permissions to control whether players can use formatting codes in their chat messages. # See https://essentialsx.net/wiki/Color-Permissions.html for more information. @@ -1112,7 +1112,7 @@ newbies: # Should we announce to the server when someone logs in for the first time? # If so, use this format, replacing {DISPLAYNAME} with the player name. # If not, set to '' - #announce-format: '' + # announce-format: '' announce-format: '&dWelcome {DISPLAYNAME}&d to the server!' # When we spawn for the first time, which spawnpoint do we use? @@ -1121,7 +1121,7 @@ newbies: # Do we want to give users anything on first join? Set to '' to disable # This kit will be given regardless of cost and permissions, and will not trigger the kit delay. - #kit: '' + # kit: '' kit: tools # What priority should we use for handling respawns? @@ -1152,7 +1152,7 @@ respawn-at-anchor: false spawn-on-join: false # The following value of `guests` states that all players in group `guests` will be teleported to spawn when joining. #spawn-on-join: guests -# The following list value states that all players in group `guests` and `admin` are to be teleported to spawn when joining. +# The following list value states that all players in group `guests` and `admin` are to be teleported to spawn when joining. #spawn-on-join: #- guests #- admin diff --git a/format/yaml/src/test/resources/org/spongepowered/configurate/yaml/essx-legacy.yml b/format/yaml/src/test/resources/org/spongepowered/configurate/yaml/essx-legacy.yml index 88c2743e5..00f9e55d2 100644 --- a/format/yaml/src/test/resources/org/spongepowered/configurate/yaml/essx-legacy.yml +++ b/format/yaml/src/test/resources/org/spongepowered/configurate/yaml/essx-legacy.yml @@ -725,4 +725,4 @@ respawn-listener-priority: high # When users die, should they respawn at their first home or bed, instead of the spawnpoint? respawn-at-home: false -# End of file <-- No seriously, you're done with configuration. \ No newline at end of file +# End of file <-- No seriously, you're done with configuration. diff --git a/format/yaml/src/test/resources/org/spongepowered/configurate/yaml/mobcleaner-example.yml b/format/yaml/src/test/resources/org/spongepowered/configurate/yaml/mobcleaner-example.yml index 93885e67d..3a3a9d803 100644 --- a/format/yaml/src/test/resources/org/spongepowered/configurate/yaml/mobcleaner-example.yml +++ b/format/yaml/src/test/resources/org/spongepowered/configurate/yaml/mobcleaner-example.yml @@ -31,6 +31,7 @@ worlds: - SQUID - WOLF - ZOMBIE + # Should only entities with a specific spawn reason be removed? # Setting this to false will check for any spawn reason spawn-reason: @@ -66,12 +67,15 @@ nearby-entities: # This is useful to only remove large groups of entities while leaving smaller entity groups alone # Using this would prevent every entity from being removed then just respawning again naturally enabled: true + # Only apply to worlds with the mob spawning gamerule enabled? gamerule-enabled-only: false + # The distance in blocks that the plugin should check for extra entities x: 3 y: 3 z: 3 + # How many additional entities must be around the first entity to be removed? count: 4 @@ -84,6 +88,7 @@ remove-named: false messages: # Should there be action bar messages? actionbar: true + # Should there be chat messages? chat: false actionbar-message: "&6&lCommon entities will be removed in &e&l{SECONDS} &6&lsecond{S}!" @@ -111,12 +116,15 @@ commands: low-tps: # Should the entity removal task be triggered when the TPS is low? enabled: false + # Below what TPS should the plugin remove the entities? threshold: 17 + # Should the plugin remove the entities instantly or trigger the countdown? # Warning: If the TPS is too low and remove-instantly is false, the plugin may # not be able to remove the entities before the server crashes remove-instantly: true + # Should there be a chat message sent to players with the `entityclearer.lowtps` # permission stating that the TPS is low? chat: true