diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/VoxelBrushManager.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/VoxelBrushManager.java index 5dee002a..086a595c 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/VoxelBrushManager.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/VoxelBrushManager.java @@ -111,12 +111,6 @@ public static VoxelBrushManager initialize() { //brushManager.registerSniperBrush(StencilBrush.class, "st", "stencil"); //brushManager.registerSniperBrush(StencilListBrush.class, "sl", "stencillist"); - - - //these brushes have an unknown status - //brushManager.registerSniperBrush(SnowConeBrush.class, "snow", "snowcone"); - //brushManager.registerSniperBrush(SpiralStaircaseBrush.class, "sstair", "spiralstaircase"); - return getInstance(); } @@ -154,15 +148,15 @@ private static BrushData blendVoxelDiscBrush() { } private static BrushData blobBrush() { - return new BrushBuilder().name("Splatblob").alias("blob", "splatblob").setSupplier(BlobBrush::new).setPermission("voxelsniper.brush.splatblob").build(); + return new BrushBuilder().name("Splatblob").alias("blob", "splatblob").setSupplier(BlobBrush::new).setPermission("voxelsniper.brush.blob").build(); } private static BrushData blockResetBrush() { - return new BrushBuilder().name("Blockresetbrush").alias("brb", "blockresetbrush").setSupplier(BlockResetBrush::new).setPermission("voxelsniper.brush.blockresetbrush").build(); + return new BrushBuilder().name("Blockresetbrush").alias("brb", "blockresetbrush").setSupplier(BlockResetBrush::new).setPermission("voxelsniper.brush.blockreset").build(); } private static BrushData blockResetSurfaceBrush() { - return new BrushBuilder().name("Blockresetbrushsurface").alias("brbs", "blockresetbrushsurface").setSupplier(BlockResetSurfaceBrush::new).setPermission("voxelsniper.brush.blockresetbrushsurface").build(); + return new BrushBuilder().name("Blockresetbrushsurface").alias("brbs", "blockresetbrushsurface").setSupplier(BlockResetSurfaceBrush::new).setPermission("voxelsniper.brush.blockresetsurface").build(); } private static BrushData canyonBrush() { @@ -206,7 +200,7 @@ private static BrushData discFaceBrush() { } private static BrushData domeBrush() { - return new BrushBuilder().name("Domebrush").alias("dome", "domebrush").setSupplier(DomeBrush::new).setPermission("voxelsniper.brush.domebrush").build(); + return new BrushBuilder().name("Domebrush").alias("dome", "domebrush").setSupplier(DomeBrush::new).setPermission("voxelsniper.brush.dome").build(); } private static BrushData drainBrush() { @@ -254,11 +248,11 @@ private static BrushData generateTreeBrush() { } private static BrushData jaggedLineBrush() { - return new BrushBuilder().name("Jagged").alias("j", "jagged").setSupplier(JaggedLineBrush::new).setPermission("voxelsniper.brush.jagged").build(); + return new BrushBuilder().name("Jagged").alias("j", "jagged").setSupplier(JaggedLineBrush::new).setPermission("voxelsniper.brush.jaggedline").build(); } private static BrushData jockeyBrush() { - return new BrushBuilder().name("jockey").setSupplier(JockeyBrush::new).setPermission("voxelsniper.brush.jockey").build(); + return new BrushBuilder().name("jockey").alias("jockey").setSupplier(JockeyBrush::new).setPermission("voxelsniper.brush.jockey").build(); } private static BrushData lightningBrush() { @@ -334,7 +328,7 @@ private static BrushData shellVoxelBrush() { } private static BrushData signOverwriteBrush() { - return new BrushBuilder().name("Signoverwriter").alias("sio", "signoverwriter").setSupplier(SignOverwriteBrush::new).setPermission("voxelsniper.brush.signoverwriter").build(); + return new BrushBuilder().name("Signoverwriter").alias("sio", "signoverwriter").setSupplier(SignOverwriteBrush::new).setPermission("voxelsniper.brush.signoverwrite").build(); } private static BrushData snipeBrush() { @@ -342,11 +336,11 @@ private static BrushData snipeBrush() { } private static BrushData splatterBallBrush() { - return new BrushBuilder().name("Splatball").alias("sb", "splatball").setSupplier(SplatterBallBrush::new).setPermission("voxelsniper.brush.splatball").build(); + return new BrushBuilder().name("Splatball").alias("sb", "splatball").setSupplier(SplatterBallBrush::new).setPermission("voxelsniper.brush.splatterball").build(); } private static BrushData splatterDiscBrush() { - return new BrushBuilder().name("Splatdisc").alias("sd", "splatdisc").setSupplier(SplatterDiscBrush::new).setPermission("voxelsniper.brush.splatdisc").build(); + return new BrushBuilder().name("Splatdisc").alias("sd", "splatdisc").setSupplier(SplatterDiscBrush::new).setPermission("voxelsniper.brush.splatterdisc").build(); } private static BrushData splatterOverlayBrush() { @@ -362,7 +356,7 @@ private static BrushData splatterVoxelBrush() { } private static BrushData splatterVoxelDiscBrush() { - return new BrushBuilder().name("Splatvoxeldisc").alias("svd", "splatvoxeldisc").setSupplier(SplatterVoxelDiscBrush::new).setPermission("voxelsniper.brush.splatvoxeldisc").build(); + return new BrushBuilder().name("Splatvoxeldisc").alias("svd", "splatvoxeldisc").setSupplier(SplatterVoxelDiscBrush::new).setPermission("voxelsniper.brush.splattervoxeldisc").build(); } private static BrushData threePointCircleBrush() { @@ -409,6 +403,8 @@ private static BrushData warpBrush() { * @param brushData The brush data to register. */ public void registerSniperBrush(@NotNull BrushData brushData) { + if (brushData.getAliases().isEmpty()) + throw new IllegalArgumentException("BrushData for brush " + brushData.getName() + " does not have aliases"); for (String handle : brushData.getAliases()) { brushes.put(handle.toLowerCase(), brushData); } diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/SignOverwriteBrush.java b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/SignOverwriteBrush.java index af1a2fd1..4683add0 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/SignOverwriteBrush.java +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/SignOverwriteBrush.java @@ -4,6 +4,7 @@ import com.github.kevindagame.snipe.SnipeData; import com.github.kevindagame.snipe.Undo; import com.github.kevindagame.util.Messages; +import com.github.kevindagame.util.Utils; import com.github.kevindagame.util.VoxelMessage; import com.github.kevindagame.util.brushOperation.BlockStateOperation; import com.github.kevindagame.util.brushOperation.CustomOperation; @@ -18,6 +19,7 @@ import java.io.FileWriter; import java.io.IOException; import java.util.Arrays; +import java.util.HashMap; import java.util.List; import java.util.Objects; @@ -267,6 +269,31 @@ private int parseSignLineFromParam(final String[] params, final int lineNumber, return i; } + @NotNull + @Override + public List registerArguments() { + return Utils.unmodifiableList("-1", "-2", "-3", "-4", "-clear", "-c", "-clearall", "-ca", "-multiple", "-m", "-s", "-save", "-o", "-open", "info"); + } + + @NotNull + @Override + public HashMap> registerArgumentValues() { + HashMap> args = new HashMap<>(); + + for (int i = 1; i < 5; i++) { + args.put("-" + i, Utils.unmodifiableList("[text]")); + } + + args.put("-multiple", Utils.unmodifiableList("on", "off", "yes", "no")); + args.put("-m", Utils.unmodifiableList("on", "off", "yes", "no")); + + for (String e : new String[]{"s", "save", "o", "open"}) { + args.put("-" + e, Utils.unmodifiableList("name")); + } + + return args; + } + private void displayBuffer(final SnipeData v) { v.sendMessage(Messages.SIGN_BUFFER_TEXT_SET); for (int i = 0; i < this.signTextLines.length; i++) { diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/polymorphic/property/PerformerProperty.kt b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/polymorphic/property/PerformerProperty.kt index 48c96d97..a13c0fc6 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/polymorphic/property/PerformerProperty.kt +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/polymorphic/property/PerformerProperty.kt @@ -3,9 +3,8 @@ package com.github.kevindagame.brush.polymorphic.property import com.github.kevindagame.brush.perform.BasePerformer import com.github.kevindagame.brush.perform.Performer import com.github.kevindagame.brush.perform.pMaterial -import com.github.kevindagame.util.Utils -class PerformerProperty : PolyProperty("performer", "Set the performer", pMaterial(), aliases = Utils.unmodifiableList("P")) { +class PerformerProperty : PolyProperty("performer", "Set the performer", pMaterial(), aliases = listOf("P")) { override fun set(value: String?) { val newPerfomer = Performer.getPerformer(value) ?: return this.value = newPerfomer diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/polymorphic/property/PolyProperty.kt b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/polymorphic/property/PolyProperty.kt index 6bcf4f07..0b764891 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/polymorphic/property/PolyProperty.kt +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/brush/polymorphic/property/PolyProperty.kt @@ -1,8 +1,6 @@ package com.github.kevindagame.brush.polymorphic.property -import com.github.kevindagame.util.Utils - -abstract class PolyProperty(val name: String, val description: String, val default: T, val aliases: List = Utils.unmodifiableList()) { +abstract class PolyProperty(val name: String, val description: String, val default: T, val aliases: List = listOf()) { var value: T = default fun get(): T { diff --git a/VoxelSniperCore/src/main/java/com/github/kevindagame/util/Utils.kt b/VoxelSniperCore/src/main/java/com/github/kevindagame/util/Utils.kt index ba5c509d..a2ad1cf6 100644 --- a/VoxelSniperCore/src/main/java/com/github/kevindagame/util/Utils.kt +++ b/VoxelSniperCore/src/main/java/com/github/kevindagame/util/Utils.kt @@ -3,19 +3,24 @@ package com.github.kevindagame.util import java.util.* object Utils { + @JvmStatic fun unmodifiableList(): List { - return Collections.unmodifiableList(ArrayList()) + return listOf() } + @JvmStatic fun unmodifiableList(arg: T): List { - return Collections.unmodifiableList(newArrayList(arg)) + return listOf(arg) + } + + @JvmStatic + fun unmodifiableList(vararg args: T): List { + return listOf(*args) } @JvmStatic fun newArrayList(vararg args: T): List { - val lst: MutableList = ArrayList() - lst.addAll(args) - return lst + return mutableListOf(*args) } @JvmStatic diff --git a/VoxelSniperCore/src/main/resources/permissions.yml b/VoxelSniperCore/src/main/resources/permissions.yml index b0c8ff48..2eeabe38 100644 --- a/VoxelSniperCore/src/main/resources/permissions.yml +++ b/VoxelSniperCore/src/main/resources/permissions.yml @@ -47,8 +47,6 @@ permissions: - name: voxelsniper.brush.overlay - name: voxelsniper.brush.painting - name: voxelsniper.brush.pull -- name: voxelsniper.brush.punish -- name: voxelsniper.brush.randomerode - name: voxelsniper.brush.regeneratechunk - name: voxelsniper.brush.ring - name: voxelsniper.brush.rot2d @@ -57,24 +55,19 @@ permissions: - name: voxelsniper.brush.ruler - name: voxelsniper.brush.scanner - name: voxelsniper.brush.set -- name: voxelsniper.brush.setredstoneflip -- name: voxelsniper.brush.setredstonerotate - name: voxelsniper.brush.shellball - name: voxelsniper.brush.shellset - name: voxelsniper.brush.shellvoxel - name: voxelsniper.brush.signoverwrite - name: voxelsniper.brush.snipe -- name: voxelsniper.brush.snowcone -- name: voxelsniper.brush.spiralstaircase - name: voxelsniper.brush.splatterball - name: voxelsniper.brush.splatterdisc - name: voxelsniper.brush.splatteroverlay - name: voxelsniper.brush.splattervoxel - name: voxelsniper.brush.splattervoxeldisc - name: voxelsniper.brush.spline -- name: voxelsniper.brush.stamp -- name: voxelsniper.brush.stencil -- name: voxelsniper.brush.stencillist +#- name: voxelsniper.brush.stencil +#- name: voxelsniper.brush.stencillist - name: voxelsniper.brush.threepointcircle - name: voxelsniper.brush.treesnipe - name: voxelsniper.brush.triangle diff --git a/VoxelSniperCore/src/test/java/com/github/kevindagame/voxelsniper/BrushesTest.java b/VoxelSniperCore/src/test/java/com/github/kevindagame/voxelsniper/BrushesTest.java index 606e3f54..847cb8c1 100644 --- a/VoxelSniperCore/src/test/java/com/github/kevindagame/voxelsniper/BrushesTest.java +++ b/VoxelSniperCore/src/test/java/com/github/kevindagame/voxelsniper/BrushesTest.java @@ -9,6 +9,9 @@ import com.github.kevindagame.brush.perform.Performer; import com.github.kevindagame.brush.perform.PerformerBrush; import com.github.kevindagame.voxelsniper.biome.VoxelBiome; +import com.github.kevindagame.voxelsniper.permissions.Permission; +import com.github.kevindagame.voxelsniper.permissions.PermissionLoader; + import org.junit.Assert; import org.junit.Before; import org.junit.Test; @@ -149,4 +152,49 @@ public void testPerformerBrushesArgumentValuesOverloading() { } System.out.println("Performer Arguments VALUES Test OK!"); } + + @Test + public void testBrushPermissions() { + // Load all brushes and permissions + VoxelBrushManager brushes = VoxelBrushManager.initialize(); + PermissionLoader permissions = PermissionLoader.getInstance(); + permissions.load(); + + // check that every brush has a permission and that permission is registered in the permissions.yml file + for (BrushData brushData : brushes.getRegisteredBrushesMap().values()) { + Assert.assertNotNull("Brush permission must not be null (brush: " + brushData.getName() + ")", brushData.getPermission()); + Permission permissionNode = permissions.getPermission(brushData.getPermission()); + Assert.assertNotNull("Brush permission must be in permissions.yml (brush: " + brushData.getName() + ")", permissionNode); + } + } + + @Test + public void testBrushPermissionsUsed() { + // Load all brushes and permissions + VoxelBrushManager brushes = VoxelBrushManager.initialize(); + PermissionLoader permissions = PermissionLoader.getInstance(); + permissions.load(); + + List usedBrushPermissions = brushes.getRegisteredBrushesMap().values().stream().map(BrushData::getPermission).toList(); + System.out.println(Arrays.toString(usedBrushPermissions.toArray(String[]::new))); + for (Permission p : permissions.getAllPermissions() ) { + var name = p.getName(); + if (name.startsWith("voxelsniper.brush.") && !name.endsWith(".*")) + Assert.assertTrue("Brush permission is unused: " + name, usedBrushPermissions.contains(name)); + } + } + + @Test + public void testDuplicateBrushHandles() { + VoxelBrushManager brushes = VoxelBrushManager.initialize(); + // put this into a hashset to remove duplicates (e.g. any brush that registers more than one alias) + Set brushDatas = new HashSet<>(brushes.getRegisteredBrushesMap().values()); + List usedHandles = new ArrayList<>(); + for (BrushData brushData : brushDatas) { + for (String handle : brushData.getAliases()) { + Assert.assertFalse("Brush handle '" + handle + "' is used more than once!", usedHandles.contains(handle)); + usedHandles.add(handle); + } + } + } } diff --git a/VoxelSniperForge/src/main/java/com/github/kevindagame/voxelsniperforge/blockstate/ExtendedBlockState.java b/VoxelSniperForge/src/main/java/com/github/kevindagame/voxelsniperforge/blockstate/ExtendedBlockState.java index e1bf5e44..6470d2f8 100644 --- a/VoxelSniperForge/src/main/java/com/github/kevindagame/voxelsniperforge/blockstate/ExtendedBlockState.java +++ b/VoxelSniperForge/src/main/java/com/github/kevindagame/voxelsniperforge/blockstate/ExtendedBlockState.java @@ -1,5 +1,11 @@ package com.github.kevindagame.voxelsniperforge.blockstate; +import com.github.kevindagame.voxelsniperforge.block.ForgeBlock; +import com.github.kevindagame.voxelsniperforge.mixin.MixinBlockStateBase; + +/** + * This interface is used in mixin to implement ignorePhysics (see {@link MixinBlockStateBase} and {@link ForgeBlock}) + */ public interface ExtendedBlockState { void setShouldUpdate(boolean shouldUpdate); diff --git a/VoxelSniperForge/src/main/java/com/github/kevindagame/voxelsniperforge/blockstate/sign/ForgeSign.java b/VoxelSniperForge/src/main/java/com/github/kevindagame/voxelsniperforge/blockstate/sign/ForgeSign.java index 996565c9..8c7d15c4 100644 --- a/VoxelSniperForge/src/main/java/com/github/kevindagame/voxelsniperforge/blockstate/sign/ForgeSign.java +++ b/VoxelSniperForge/src/main/java/com/github/kevindagame/voxelsniperforge/blockstate/sign/ForgeSign.java @@ -4,6 +4,10 @@ import com.github.kevindagame.voxelsniperforge.block.ForgeBlock; import com.github.kevindagame.voxelsniperforge.blockstate.ForgeBlockState; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; +import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; +import net.minecraft.network.chat.MutableComponent; import net.minecraft.world.level.block.entity.SignBlockEntity; import net.minecraft.world.level.block.state.BlockState; @@ -18,18 +22,27 @@ public ForgeSign(ForgeBlock block, BlockState blockState, SignBlockEntity tileEn this.tileEntity = tileEntity; } - @NotNull - private static String translateColorCodesToAmpersand(@NotNull String textToTranslate) { - throw new UnsupportedOperationException("Not implemented yet"); - } - @Override public void setLine(int line, String signText) { - throw new UnsupportedOperationException("Not implemented yet"); + boolean front = true; + Component comp = LegacyComponentSerializer.legacyAmpersand().deserialize(signText); + var text = tileEntity.getFrontText().setMessage(line, toNative(comp)); + tileEntity.setText(text, front); } @Override public String getLine(int line) { - throw new UnsupportedOperationException("Not implemented yet"); + boolean filtered = false; + Component text = fromNative(tileEntity.getFrontText().getMessage(line, filtered)); + return LegacyComponentSerializer.legacyAmpersand().serialize(text); + } + + public static MutableComponent toNative(@NotNull Component component) { + if (component == Component.empty()) return net.minecraft.network.chat.Component.empty(); + return net.minecraft.network.chat.Component.Serializer.fromJson(GsonComponentSerializer.gson().serialize(component)); + } + + public static Component fromNative(@NotNull net.minecraft.network.chat.Component component) { + return GsonComponentSerializer.gson().deserialize(net.minecraft.network.chat.Component.Serializer.toJson(component)); } } diff --git a/VoxelSniperForge/src/main/java/com/github/kevindagame/voxelsniperforge/entity/Painting/ForgePainting.java b/VoxelSniperForge/src/main/java/com/github/kevindagame/voxelsniperforge/entity/Painting/ForgePainting.java index 5fa7be95..4db92437 100644 --- a/VoxelSniperForge/src/main/java/com/github/kevindagame/voxelsniperforge/entity/Painting/ForgePainting.java +++ b/VoxelSniperForge/src/main/java/com/github/kevindagame/voxelsniperforge/entity/Painting/ForgePainting.java @@ -4,7 +4,6 @@ import com.github.kevindagame.voxelsniperforge.entity.ForgeEntity; import java.util.List; -import java.util.Objects; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.decoration.Painting; @@ -34,8 +33,6 @@ public boolean setArtId(int id) { @Override public int getArtId() { - String[] values = paintingVariants.stream().map(Objects::toString).toArray(String[]::new); - var variant = ((Painting) this.getEntity()).getVariant().get(); var key = ForgeRegistries.PAINTING_VARIANTS.getKey(variant); var idx = paintingVariants.indexOf(key);