feat: add #hotbar mask and pattern (#2769)

- closes #2765
This commit is contained in:
Jordan 2024-06-13 20:31:34 +02:00 committed by GitHub
parent 9843bb0188
commit 865cc55a0e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 143 additions and 0 deletions

View File

@ -192,6 +192,9 @@ public class BukkitPlayerBlockBag extends BlockBag implements SlottableBlockBag
@Override @Override
public BaseItem getItem(int slot) { public BaseItem getItem(int slot) {
loadInventory(); loadInventory();
if (items[slot] == null) {
return null;
}
return BukkitAdapter.adapt(items[slot]); return BukkitAdapter.adapt(items[slot]);
} }

View File

@ -0,0 +1,72 @@
package com.fastasyncworldedit.core.extension.factory.parser.common;
import com.fastasyncworldedit.core.configuration.Caption;
import com.fastasyncworldedit.core.extent.inventory.SlottableBlockBag;
import com.fastasyncworldedit.core.limit.FaweLimit;
import com.google.common.collect.ImmutableList;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.blocks.BaseItem;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extension.input.DisallowedUsageException;
import com.sk89q.worldedit.extension.input.InputParseException;
import com.sk89q.worldedit.extension.input.ParserContext;
import com.sk89q.worldedit.extent.inventory.BlockBag;
import com.sk89q.worldedit.internal.registry.SimpleInputParser;
import com.sk89q.worldedit.util.formatting.text.TextComponent;
import com.sk89q.worldedit.world.block.BlockType;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
public abstract class HotbarParser<T> extends SimpleInputParser<T> {
private final List<String> aliases = ImmutableList.of("#hotbar");
protected HotbarParser(final WorldEdit worldEdit) {
super(worldEdit);
}
@Override
public List<String> getMatchedAliases() {
return aliases;
}
protected List<BlockType> getBlockTypes(ParserContext context) {
Player player = context.requirePlayer();
BlockBag bag = player.getInventoryBlockBag();
if (!(bag instanceof final SlottableBlockBag slottable)) {
// Matches DefaultBlockParser
throw new InputParseException(Caption.of("fawe.error.unsupported"));
}
List<BlockType> types = new ArrayList<>();
FaweLimit limit = player.getLimit();
boolean anyBlock = player.hasPermission("worldedit.anyblock");
for (int slot = 0; slot < 9; slot++) {
BaseItem item = slottable.getItem(slot);
if (item != null && item.getType().hasBlockType()) {
BlockType type = item.getType().getBlockType();
if (!anyBlock && worldEdit.getConfiguration().disallowedBlocks.contains(type.id().toLowerCase(Locale.ROOT))) {
throw new DisallowedUsageException(Caption.of(
"worldedit.error.disallowed-block",
TextComponent.of(type.getId())
));
}
if (!limit.isUnlimited()) {
if (limit.DISALLOWED_BLOCKS.contains(type.id().toLowerCase(Locale.ROOT))) {
throw new DisallowedUsageException(Caption.of(
"fawe.error.limit.disallowed-block",
TextComponent.of(type.getId())
));
}
}
types.add(type);
}
}
if (types.isEmpty()) {
throw new InputParseException(Caption.of("fawe.error.no-valid-on-hotbar"));
}
return types;
}
}

View File

@ -0,0 +1,20 @@
package com.fastasyncworldedit.core.extension.factory.parser.mask;
import com.fastasyncworldedit.core.extension.factory.parser.common.HotbarParser;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.extension.input.ParserContext;
import com.sk89q.worldedit.function.mask.BlockTypeMask;
import com.sk89q.worldedit.function.mask.Mask;
public class HotbarMaskParser extends HotbarParser<Mask> {
public HotbarMaskParser(WorldEdit worldEdit) {
super(worldEdit);
}
@Override
public Mask parseFromSimpleInput(String input, ParserContext context) {
return new BlockTypeMask(context.getExtent(), getBlockTypes(context));
}
}

View File

@ -0,0 +1,26 @@
package com.fastasyncworldedit.core.extension.factory.parser.pattern;
import com.fastasyncworldedit.core.extension.factory.parser.common.HotbarParser;
import com.fastasyncworldedit.core.math.random.TrueRandom;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.extension.input.ParserContext;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.function.pattern.RandomPattern;
import com.sk89q.worldedit.world.block.BlockType;
public class HotbarPatternParser extends HotbarParser<Pattern> {
public HotbarPatternParser(WorldEdit worldEdit) {
super(worldEdit);
}
@Override
public Pattern parseFromSimpleInput(String input, ParserContext context) {
RandomPattern random = new RandomPattern(new TrueRandom());
for (BlockType type : getBlockTypes(context)) {
random.add(type, 1);
}
return random;
}
}

View File

@ -25,6 +25,7 @@ import com.fastasyncworldedit.core.extension.factory.parser.mask.AngleMaskParser
import com.fastasyncworldedit.core.extension.factory.parser.mask.BesideMaskParser; import com.fastasyncworldedit.core.extension.factory.parser.mask.BesideMaskParser;
import com.fastasyncworldedit.core.extension.factory.parser.mask.ExtremaMaskParser; import com.fastasyncworldedit.core.extension.factory.parser.mask.ExtremaMaskParser;
import com.fastasyncworldedit.core.extension.factory.parser.mask.FalseMaskParser; import com.fastasyncworldedit.core.extension.factory.parser.mask.FalseMaskParser;
import com.fastasyncworldedit.core.extension.factory.parser.mask.HotbarMaskParser;
import com.fastasyncworldedit.core.extension.factory.parser.mask.LiquidMaskParser; import com.fastasyncworldedit.core.extension.factory.parser.mask.LiquidMaskParser;
import com.fastasyncworldedit.core.extension.factory.parser.mask.ROCAngleMaskParser; import com.fastasyncworldedit.core.extension.factory.parser.mask.ROCAngleMaskParser;
import com.fastasyncworldedit.core.extension.factory.parser.mask.RadiusMaskParser; import com.fastasyncworldedit.core.extension.factory.parser.mask.RadiusMaskParser;
@ -110,6 +111,7 @@ public final class MaskFactory extends AbstractFactory<Mask> {
register(new BesideMaskParser(worldEdit)); register(new BesideMaskParser(worldEdit));
register(new ExtremaMaskParser(worldEdit)); register(new ExtremaMaskParser(worldEdit));
register(new FalseMaskParser(worldEdit)); register(new FalseMaskParser(worldEdit));
register(new HotbarMaskParser(worldEdit));
register(new LiquidMaskParser(worldEdit)); register(new LiquidMaskParser(worldEdit));
register(new RadiusMaskParser(worldEdit)); register(new RadiusMaskParser(worldEdit));
register(new RichOffsetMaskParser(worldEdit)); register(new RichOffsetMaskParser(worldEdit));

View File

@ -20,6 +20,7 @@
package com.sk89q.worldedit.extension.factory; package com.sk89q.worldedit.extension.factory;
import com.fastasyncworldedit.core.configuration.Caption; import com.fastasyncworldedit.core.configuration.Caption;
import com.fastasyncworldedit.core.extension.factory.parser.mask.HotbarMaskParser;
import com.fastasyncworldedit.core.extension.factory.parser.pattern.AngleColorPatternParser; import com.fastasyncworldedit.core.extension.factory.parser.pattern.AngleColorPatternParser;
import com.fastasyncworldedit.core.extension.factory.parser.pattern.AverageColorPatternParser; import com.fastasyncworldedit.core.extension.factory.parser.pattern.AverageColorPatternParser;
import com.fastasyncworldedit.core.extension.factory.parser.pattern.BiomePatternParser; import com.fastasyncworldedit.core.extension.factory.parser.pattern.BiomePatternParser;
@ -30,6 +31,7 @@ import com.fastasyncworldedit.core.extension.factory.parser.pattern.DarkenPatter
import com.fastasyncworldedit.core.extension.factory.parser.pattern.DesaturatePatternParser; import com.fastasyncworldedit.core.extension.factory.parser.pattern.DesaturatePatternParser;
import com.fastasyncworldedit.core.extension.factory.parser.pattern.ExistingPatternParser; import com.fastasyncworldedit.core.extension.factory.parser.pattern.ExistingPatternParser;
import com.fastasyncworldedit.core.extension.factory.parser.pattern.ExpressionPatternParser; import com.fastasyncworldedit.core.extension.factory.parser.pattern.ExpressionPatternParser;
import com.fastasyncworldedit.core.extension.factory.parser.pattern.HotbarPatternParser;
import com.fastasyncworldedit.core.extension.factory.parser.pattern.LightenPatternParser; import com.fastasyncworldedit.core.extension.factory.parser.pattern.LightenPatternParser;
import com.fastasyncworldedit.core.extension.factory.parser.pattern.Linear2DPatternParser; import com.fastasyncworldedit.core.extension.factory.parser.pattern.Linear2DPatternParser;
import com.fastasyncworldedit.core.extension.factory.parser.pattern.Linear3DPatternParser; import com.fastasyncworldedit.core.extension.factory.parser.pattern.Linear3DPatternParser;
@ -116,6 +118,7 @@ public final class PatternFactory extends AbstractFactory<Pattern> {
register(new DesaturatePatternParser(worldEdit)); register(new DesaturatePatternParser(worldEdit));
register(new ExistingPatternParser(worldEdit)); register(new ExistingPatternParser(worldEdit));
register(new ExpressionPatternParser(worldEdit)); register(new ExpressionPatternParser(worldEdit));
register(new HotbarPatternParser(worldEdit));
register(new LightenPatternParser(worldEdit)); register(new LightenPatternParser(worldEdit));
register(new Linear2DPatternParser(worldEdit)); register(new Linear2DPatternParser(worldEdit));
register(new Linear3DPatternParser(worldEdit)); register(new Linear3DPatternParser(worldEdit));

View File

@ -23,6 +23,7 @@ import com.fastasyncworldedit.core.configuration.Caption;
import com.sk89q.worldedit.IncompleteRegionException; import com.sk89q.worldedit.IncompleteRegionException;
import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extension.factory.MaskFactory; import com.sk89q.worldedit.extension.factory.MaskFactory;
import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.extension.platform.Capability; import com.sk89q.worldedit.extension.platform.Capability;
@ -217,6 +218,20 @@ public class ParserContext {
return actor; return actor;
} }
/**
* Get the {@link Player} set on this context.
*
* @return a player
* @throws InputParseException thrown if no {@link Actor} is set
*/
public Player requirePlayer() throws InputParseException {
Actor actor = getActor();
if (!(actor instanceof Player player)) {
throw new InputParseException(Caption.of("worldedit.error.missing-player"));
}
return player;
}
/** /**
* Returns whether there should be restrictions (as a result of * Returns whether there should be restrictions (as a result of
* limits or permissions) considered when parsing the input. * limits or permissions) considered when parsing the input.

View File

@ -139,6 +139,7 @@
"fawe.error.occurred-continuing": "Ignorable error occurred during edit: {0}", "fawe.error.occurred-continuing": "Ignorable error occurred during edit: {0}",
"fawe.error.limit.max-brush-radius": "Maximum brush radius in limit: {0}", "fawe.error.limit.max-brush-radius": "Maximum brush radius in limit: {0}",
"fawe.error.limit.max-radius": "Maximum radius in limit: {0}", "fawe.error.limit.max-radius": "Maximum radius in limit: {0}",
"fawe.error.no-valid-on-hotbar": "No valid block types on hotbar",
"fawe.cancel.count": "Cancelled {0} edits.", "fawe.cancel.count": "Cancelled {0} edits.",
"fawe.cancel.reason.confirm": "Use //confirm to execute {0}", "fawe.cancel.reason.confirm": "Use //confirm to execute {0}",
"fawe.cancel.reason.confirm.region": "Your selection is large ({0} -> {1}, containing {3} blocks). Use //confirm to execute {2}", "fawe.cancel.reason.confirm.region": "Your selection is large ({0} -> {1}, containing {3} blocks). Use //confirm to execute {2}",
@ -240,6 +241,7 @@
"worldedit.error.missing-session": "No LocalSession is known", "worldedit.error.missing-session": "No LocalSession is known",
"worldedit.error.missing-world": "You need to provide a world (Try //world)", "worldedit.error.missing-world": "You need to provide a world (Try //world)",
"worldedit.error.missing-actor": "No actor is known", "worldedit.error.missing-actor": "No actor is known",
"worldedit.error.missing-player": "No player is known",
"worldedit.error.no-file-selected": "No file selected.", "worldedit.error.no-file-selected": "No file selected.",
"worldedit.error.file-resolution.outside-root": "Path is outside allowable root", "worldedit.error.file-resolution.outside-root": "Path is outside allowable root",
"worldedit.error.file-resolution.resolve-failed": "Failed to resolve path", "worldedit.error.file-resolution.resolve-failed": "Failed to resolve path",