diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index 1b257268..37161ffd 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -27,10 +27,11 @@ body: description: Which server version version you using? If your server version is not listed, it is not supported. Update to a supported version first. multiple: false options: + - '1.21.3' + - '1.21.1' + - '1.20.6' + - '1.20.4' - '1.20.2' - - '1.19.4' - - '1.18.2' - - '1.17.1' validations: required: true diff --git a/.github/workflows/crowdin.yml b/.github/workflows/crowdin.yml index 58401139..dcfdd105 100644 --- a/.github/workflows/crowdin.yml +++ b/.github/workflows/crowdin.yml @@ -14,7 +14,7 @@ jobs: - name: Checkout uses: actions/checkout@v4 - name: crowdin action - uses: crowdin/github-action@v2.3.0 + uses: crowdin/github-action@v2.4.0 with: upload_translations: false download_translations: true diff --git a/build.gradle.kts b/build.gradle.kts index 84ccb1c0..ecc0a86f 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -18,7 +18,7 @@ plugins { } java { - toolchain.languageVersion.set(JavaLanguageVersion.of(17)) + toolchain.languageVersion.set(JavaLanguageVersion.of(21)) } repositories { @@ -29,7 +29,7 @@ repositories { dependencies { implementation(platform("com.intellectualsites.bom:bom-newest:1.51")) // Platform expectations - compileOnly("io.papermc.paper:paper-api") + compileOnly(libs.paper) compileOnly("org.apache.logging.log4j:log4j-api") // Annotations @@ -54,7 +54,7 @@ dependencies { } tasks.compileJava.configure { - options.release.set(17) + options.release.set(21) } configurations.all { @@ -69,7 +69,7 @@ bukkit { main = "com.thevoxelbox.voxelsniper.VoxelSniperPlugin" authors = listOf("Empire92", "przerwap", "MikeMatrix", "Gavjenks", "giltwist", "psanker", "Deamon5550", "DivineRage", "pitcer", "jaqobb", "NotMyFault", "Aurelien30000") - apiVersion = "1.13" + apiVersion = "1.20" version = project.version.toString() softDepend = listOf("VoxelModPackPlugin") depend = listOf("FastAsyncWorldEdit") @@ -207,7 +207,7 @@ nexusPublishing { } // Keep in sync with FAWE versions -val supportedVersions = listOf("1.19.4", "1.20", "1.20.1", "1.20.4", "1.20.6") +val supportedVersions = listOf("1.20.2", "1.20.4", "1.20.6", "1.21.3") modrinth { token.set(System.getenv("MODRINTH_TOKEN")) @@ -254,7 +254,7 @@ tasks { val artifact = ((JsonSlurper().parse(lastSuccessfulBuildUrl) as Map<*, *>)["artifacts"] as List<*>) .map { it as Map<*, *> } .map { it["fileName"] as String } - .first { it -> it.contains("Bukkit") } + .first { it -> it.contains("Paper") } project.ext["faweArtifact"] = artifact } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index f83a3af7..2f5a8f60 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -12,12 +12,16 @@ nexus = "2.0.0" minotaur = "2.8.7" hangar = "0.1.2" runPaper = "2.3.1" +paperApi = "1.21.3-R0.1-SNAPSHOT" [libraries] # Annotations annotations = { group = "org.jetbrains", name = "annotations", version.ref = "annotations" } +# Paper +paper = { group = "io.papermc.paper", name = "paper-api", version.ref = "paperApi" } + # Cloud command system cloudcore = { group = "cloud.commandframework", name = "cloud-core", version.ref = "cloud" } cloudannotations = { group = "cloud.commandframework", name = "cloud-annotations", version.ref = "cloud" } diff --git a/src/main/java/com/thevoxelbox/voxelsniper/brush/type/performer/PunishBrush.java b/src/main/java/com/thevoxelbox/voxelsniper/brush/type/performer/PunishBrush.java index 41863b4c..1fc1217a 100644 --- a/src/main/java/com/thevoxelbox/voxelsniper/brush/type/performer/PunishBrush.java +++ b/src/main/java/com/thevoxelbox/voxelsniper/brush/type/performer/PunishBrush.java @@ -18,6 +18,8 @@ import com.thevoxelbox.voxelsniper.util.message.VoxelSniperText; import org.bukkit.Bukkit; import org.bukkit.Location; +import org.bukkit.NamespacedKey; +import org.bukkit.Registry; import org.bukkit.World; import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; @@ -29,6 +31,7 @@ import java.util.Arrays; import java.util.List; import java.util.Locale; +import java.util.Objects; import java.util.Random; @RequireToolkit @@ -214,9 +217,6 @@ public void handleArrowAction(Snipe snipe) { @Override public void handleGunpowderAction(Snipe snipe) { ToolkitProperties toolkitProperties = snipe.getToolkitProperties(); - SnipeMessenger messenger = snipe.createMessenger(); - Sniper sniper = snipe.getSniper(); - Player player = sniper.getPlayer(); int brushSize = toolkitProperties.getBrushSize(); int brushSizeSquare = brushSize * brushSize; World world = BukkitAdapter.adapt(getEditSession().getWorld()); @@ -227,10 +227,10 @@ public void handleGunpowderAction(Snipe snipe) { Location location = entity.getLocation(); if (location.distanceSquared(targetLocation) < brushSizeSquare) { entity.setFireTicks(0); - entity.removePotionEffect(PotionEffectType.BLINDNESS); - entity.removePotionEffect(PotionEffectType.CONFUSION); - entity.removePotionEffect(PotionEffectType.SLOW); - entity.removePotionEffect(PotionEffectType.JUMP); + entity.removePotionEffect(Objects.requireNonNull(Registry.EFFECT.get(NamespacedKey.minecraft("blindness")))); + entity.removePotionEffect(Objects.requireNonNull(Registry.EFFECT.get(NamespacedKey.minecraft("nausea")))); + entity.removePotionEffect(Objects.requireNonNull(Registry.EFFECT.get(NamespacedKey.minecraft("slowness")))); + entity.removePotionEffect(Objects.requireNonNull(Registry.EFFECT.get(NamespacedKey.minecraft("jump_boost")))); } } } @@ -241,28 +241,73 @@ private void applyPunishment(LivingEntity entity, Snipe snipe) { case FIRE -> entity.setFireTicks(TICKS_PER_SECOND * this.punishDuration); case LIGHTNING -> entity.getWorld() .strikeLightning(entity.getLocation()); - case BLINDNESS -> addEffect(entity, PotionEffectType.BLINDNESS); - case DRUNK -> addEffect(entity, PotionEffectType.CONFUSION); - case SLOW -> addEffect(entity, PotionEffectType.SLOW); - case JUMP -> addEffect(entity, PotionEffectType.JUMP); - case ABSORPTION -> addEffect(entity, PotionEffectType.ABSORPTION); - case DAMAGE_RESISTANCE -> addEffect(entity, PotionEffectType.DAMAGE_RESISTANCE); - case FAST_DIGGING -> addEffect(entity, PotionEffectType.FAST_DIGGING); - case FIRE_RESISTANCE -> addEffect(entity, PotionEffectType.FIRE_RESISTANCE); - case HEAL -> addEffect(entity, PotionEffectType.HEAL); - case HEALTH_BOOST -> addEffect(entity, PotionEffectType.HEALTH_BOOST); - case HUNGER -> addEffect(entity, PotionEffectType.HUNGER); - case INCREASE_DAMAGE -> addEffect(entity, PotionEffectType.INCREASE_DAMAGE); - case INVISIBILITY -> addEffect(entity, PotionEffectType.INVISIBILITY); - case NIGHT_VISION -> addEffect(entity, PotionEffectType.NIGHT_VISION); - case POISON -> addEffect(entity, PotionEffectType.POISON); - case REGENERATION -> addEffect(entity, PotionEffectType.REGENERATION); - case SATURATION -> addEffect(entity, PotionEffectType.SATURATION); - case SLOW_DIGGING -> addEffect(entity, PotionEffectType.SLOW_DIGGING); - case SPEED -> addEffect(entity, PotionEffectType.SPEED); - case WATER_BREATHING -> addEffect(entity, PotionEffectType.WATER_BREATHING); - case WEAKNESS -> addEffect(entity, PotionEffectType.WEAKNESS); - case WITHER -> addEffect(entity, PotionEffectType.WITHER); + case BLINDNESS -> addEffect( + entity, + Registry.EFFECT.get(NamespacedKey.minecraft("blindness")) + ); + case DRUNK -> addEffect(entity, Registry.EFFECT.get(NamespacedKey.minecraft("nausea"))); + case SLOW -> addEffect(entity, Registry.EFFECT.get(NamespacedKey.minecraft("slowness"))); + case JUMP -> addEffect( + entity, + Registry.EFFECT.get(NamespacedKey.minecraft("jump_boost")) + ); + case ABSORPTION -> addEffect( + entity, + Registry.EFFECT.get(NamespacedKey.minecraft("absorption")) + ); + case DAMAGE_RESISTANCE -> addEffect( + entity, + Registry.EFFECT.get(NamespacedKey.minecraft("resistance")) + ); + case FAST_DIGGING -> addEffect(entity, Registry.EFFECT.get(NamespacedKey.minecraft("haste"))); + case FIRE_RESISTANCE -> addEffect( + entity, + Registry.EFFECT.get(NamespacedKey.minecraft("fire_resistance")) + ); + case HEAL -> addEffect( + entity, + Registry.EFFECT.get(NamespacedKey.minecraft("instant_health")) + ); + case HEALTH_BOOST -> addEffect( + entity, + Registry.EFFECT.get(NamespacedKey.minecraft("health_boost")) + ); + case HUNGER -> addEffect(entity, Registry.EFFECT.get(NamespacedKey.minecraft("hunger"))); + case INCREASE_DAMAGE -> addEffect( + entity, + Registry.EFFECT.get(NamespacedKey.minecraft("strenght")) + ); + case INVISIBILITY -> addEffect( + entity, + Registry.EFFECT.get(NamespacedKey.minecraft("invisibility")) + ); + case NIGHT_VISION -> addEffect( + entity, + Registry.EFFECT.get(NamespacedKey.minecraft("night_vision")) + ); + case POISON -> addEffect(entity, Registry.EFFECT.get(NamespacedKey.minecraft("poison"))); + case REGENERATION -> addEffect( + entity, + Registry.EFFECT.get(NamespacedKey.minecraft("regeneration")) + ); + case SATURATION -> addEffect( + entity, + Registry.EFFECT.get(NamespacedKey.minecraft("saturation")) + ); + case SLOW_DIGGING -> addEffect( + entity, + Registry.EFFECT.get(NamespacedKey.minecraft("mining_fatigue")) + ); + case SPEED -> addEffect(entity, Registry.EFFECT.get(NamespacedKey.minecraft("speed"))); + case WATER_BREATHING -> addEffect( + entity, + Registry.EFFECT.get(NamespacedKey.minecraft("water_breathing")) + ); + case WEAKNESS -> addEffect( + entity, + Registry.EFFECT.get(NamespacedKey.minecraft("weakness")) + ); + case WITHER -> addEffect(entity, Registry.EFFECT.get(NamespacedKey.minecraft("wither"))); case KILL -> entity.setHealth(0.0d); case RANDOMTP -> { Random random = new Random(); @@ -272,10 +317,10 @@ private void applyPunishment(LivingEntity entity, Snipe snipe) { entity.teleport(targetLocation); } case ALL_POTION -> { - addEffect(entity, PotionEffectType.BLINDNESS); - addEffect(entity, PotionEffectType.CONFUSION); - addEffect(entity, PotionEffectType.SLOW); - addEffect(entity, PotionEffectType.JUMP); + addEffect(entity, Registry.EFFECT.get(NamespacedKey.minecraft("blindness"))); + addEffect(entity, Registry.EFFECT.get(NamespacedKey.minecraft("nausea"))); + addEffect(entity, Registry.EFFECT.get(NamespacedKey.minecraft("slowness"))); + addEffect(entity, Registry.EFFECT.get(NamespacedKey.minecraft("jump_boost"))); } case FORCE -> { Vector playerVector = Vectors.toBukkit(getTargetBlock()); diff --git a/src/main/java/com/thevoxelbox/voxelsniper/command/argument/AbstractPatternArgument.java b/src/main/java/com/thevoxelbox/voxelsniper/command/argument/AbstractPatternArgument.java index 2773673c..ef245a0e 100644 --- a/src/main/java/com/thevoxelbox/voxelsniper/command/argument/AbstractPatternArgument.java +++ b/src/main/java/com/thevoxelbox/voxelsniper/command/argument/AbstractPatternArgument.java @@ -41,7 +41,7 @@ public AbstractPatternArgument(VoxelSniperPlugin plugin, AbstractFactory fact } protected List suggestPatterns(CommandContext commandContext, String input) { - return factory.getSuggestions(input); + return factory.getSuggestions(input, new ParserContext()); } protected BrushPattern parsePattern(CommandContext commandContext, Queue inputQueue) { diff --git a/src/main/java/com/thevoxelbox/voxelsniper/command/argument/VoxelListBlocksArgument.java b/src/main/java/com/thevoxelbox/voxelsniper/command/argument/VoxelListBlocksArgument.java index 32a16dca..96f15503 100644 --- a/src/main/java/com/thevoxelbox/voxelsniper/command/argument/VoxelListBlocksArgument.java +++ b/src/main/java/com/thevoxelbox/voxelsniper/command/argument/VoxelListBlocksArgument.java @@ -36,7 +36,7 @@ public VoxelListBlocksArgument(VoxelSniperPlugin plugin) { @Suggestions("voxel-list-block_suggestions") public List suggestVoxelListBlocks(CommandContext commandContext, String input) { return WorldEdit.getInstance().getBlockFactory() - .getSuggestions(input.startsWith("-") ? input.substring(1) : input).stream() + .getSuggestions(input.startsWith("-") ? input.substring(1) : input, new ParserContext()).stream() .flatMap(id -> Stream.of(id, "-" + id)) .toList(); } diff --git a/src/main/java/com/thevoxelbox/voxelsniper/command/executor/PaintExecutor.java b/src/main/java/com/thevoxelbox/voxelsniper/command/executor/PaintExecutor.java index 4156803a..a5e0656a 100644 --- a/src/main/java/com/thevoxelbox/voxelsniper/command/executor/PaintExecutor.java +++ b/src/main/java/com/thevoxelbox/voxelsniper/command/executor/PaintExecutor.java @@ -9,10 +9,14 @@ import com.thevoxelbox.voxelsniper.sniper.Sniper; import com.thevoxelbox.voxelsniper.util.ArtHelper; import org.bukkit.Art; +import org.bukkit.NamespacedKey; +import org.bukkit.Registry; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.Optional; + @CommandMethod(value = "paint") @CommandDescription("Change the selected painting to another painting.") @CommandPermission("voxelsniper.sniper") @@ -43,10 +47,20 @@ public void onPaintBack( @CommandMethod("") public void onPaintArt( final @NotNull Sniper sniper, - final @Nullable @Argument("art") Art art + final @Nullable @Argument("art") String art ) { Player player = sniper.getPlayer(); - ArtHelper.paint(player, art); + + Registry artRegistry = Registry.ART; + + ArtHelper.paint( + player, + Optional.ofNullable(art) + .flatMap(a -> Optional.ofNullable(NamespacedKey.fromString(a)) + .map(artRegistry::get) + ) + .orElse(null) + ); } } diff --git a/src/main/java/com/thevoxelbox/voxelsniper/util/ArtHelper.java b/src/main/java/com/thevoxelbox/voxelsniper/util/ArtHelper.java index 0387344f..043146e4 100644 --- a/src/main/java/com/thevoxelbox/voxelsniper/util/ArtHelper.java +++ b/src/main/java/com/thevoxelbox/voxelsniper/util/ArtHelper.java @@ -1,10 +1,12 @@ package com.thevoxelbox.voxelsniper.util; +import com.fastasyncworldedit.core.Fawe; import com.fastasyncworldedit.core.configuration.Caption; import com.thevoxelbox.voxelsniper.util.message.VoxelSniperText; import org.bukkit.Art; import org.bukkit.Chunk; import org.bukkit.Location; +import org.bukkit.Registry; import org.bukkit.block.Block; import org.bukkit.entity.Entity; import org.bukkit.entity.EntityType; @@ -12,6 +14,8 @@ import org.bukkit.entity.Player; import org.jetbrains.annotations.Nullable; +import java.util.List; + public final class ArtHelper { private ArtHelper() { @@ -44,15 +48,24 @@ public static void paintAuto(Player player, boolean back) { VoxelSniperText.print(player, Caption.of("voxelsniper.art.paint.no-match")); return; } + + Registry artRegistry = Registry.ART; + + List arts = artRegistry.stream().toList(); + Art bestMatchArt = bestMatch.getArt(); - int ordinal = bestMatchArt.ordinal() + (back ? -1 : 1); - if (ordinal < 0 || ordinal >= Art.values().length) { + int index = arts.indexOf(bestMatchArt) + (back ? -1 : 1); + if (index < 0 || index >= arts.size()) { VoxelSniperText.print(player, Caption.of("voxelsniper.art.paint.final-painting")); return; } - Art ordinalArt = Art.values()[ordinal]; - bestMatch.setArt(ordinalArt); - VoxelSniperText.print(player, Caption.of("voxelsniper.art.paint.set", ordinalArt)); + + Art ordinalArt = arts.get(index); + // snipe is called asynchronously, #setArt modifies the world via Bukkit API and needs to be run on ticking thread + Fawe.instance().getQueueHandler().sync(() -> { + bestMatch.setArt(ordinalArt); + VoxelSniperText.print(player, Caption.of("voxelsniper.art.paint.set", ordinalArt)); + }); } @Nullable diff --git a/src/main/java/com/thevoxelbox/voxelsniper/util/material/MaterialSets.java b/src/main/java/com/thevoxelbox/voxelsniper/util/material/MaterialSets.java index 8fe1c35a..3c77fdf7 100644 --- a/src/main/java/com/thevoxelbox/voxelsniper/util/material/MaterialSets.java +++ b/src/main/java/com/thevoxelbox/voxelsniper/util/material/MaterialSets.java @@ -45,7 +45,7 @@ public final class MaterialSets { .with(BlockCategories.FLOWERS) .with(MUSHROOMS) .with(STEMS) - .add(BlockTypes.GRASS) + .add(BlockTypes.GRASS_BLOCK) .add(BlockTypes.TALL_GRASS) .add(BlockTypes.DEAD_BUSH) .add(BlockTypes.WHEAT)