From 8c266b7fd97e22ddce38144cbaa031db109892ef Mon Sep 17 00:00:00 2001 From: SamB440 Date: Sat, 9 Oct 2021 19:30:54 +0100 Subject: [PATCH] Add our own region integration! --- .../api/integrations/IntegrationType.java | 6 +- .../data/region/ConfiguredRegion.java | 3 +- .../islandearth/rpgregions/utils/XSound.java | 1108 ++++++++++------- .../rpgregions/RPGRegionsIntegration.java | 47 - .../islandearth/rpgregions/RPGRegions.java | 119 +- .../rpgregions/RPGRegionsIntegration.java | 199 +++ .../rpgregions/region/CuboidRegion.java | 16 + .../rpgregions/region/PolyRegion.java | 27 + .../rpgregions/region/RPGRegionsRegion.java | 51 + .../RPGRegionsIntegrationCommand.java | 110 ++ .../rpgregions/gson/AbstractAdapter.java | 1 + .../managers/RPGRegionsManagers.java | 4 +- 12 files changed, 1114 insertions(+), 577 deletions(-) delete mode 100644 modern/src/main/java/net/islandearth/rpgregions/api/integrations/rpgregions/RPGRegionsIntegration.java create mode 100644 rpgregions/src/main/java/net/islandearth/rpgregions/api/integrations/rpgregions/RPGRegionsIntegration.java create mode 100644 rpgregions/src/main/java/net/islandearth/rpgregions/api/integrations/rpgregions/region/CuboidRegion.java create mode 100644 rpgregions/src/main/java/net/islandearth/rpgregions/api/integrations/rpgregions/region/PolyRegion.java create mode 100644 rpgregions/src/main/java/net/islandearth/rpgregions/api/integrations/rpgregions/region/RPGRegionsRegion.java create mode 100644 rpgregions/src/main/java/net/islandearth/rpgregions/commands/RPGRegionsIntegrationCommand.java diff --git a/api/src/main/java/net/islandearth/rpgregions/api/integrations/IntegrationType.java b/api/src/main/java/net/islandearth/rpgregions/api/integrations/IntegrationType.java index c94581f..82ff9c4 100644 --- a/api/src/main/java/net/islandearth/rpgregions/api/integrations/IntegrationType.java +++ b/api/src/main/java/net/islandearth/rpgregions/api/integrations/IntegrationType.java @@ -8,11 +8,11 @@ import org.bukkit.plugin.java.JavaPlugin; import java.util.Optional; public enum IntegrationType { - WORLDGUARD_LEGACY("WorldGuard", "worldguard.WorldGuardLegacyIntegration"), WORLDGUARD("WorldGuard", "worldguard.WorldGuardIntegration"), RESIDENCE("Residence", "residence.ResidenceIntegration"), GRIEFPREVENTION("GriefPrevention", "griefprevention.GriefPreventionIntegration"), - ULTRAREGIONS("UltraRegions", "ultraregions.UltraRegionsIntegration"); + ULTRAREGIONS("UltraRegions", "ultraregions.UltraRegionsIntegration"), + RPGREGIONS("RPGRegions", "rpgregions.RPGRegionsIntegration"); private final String plugin; private final String path; @@ -25,7 +25,7 @@ public enum IntegrationType { public Optional get(IRPGRegionsAPI plugin) throws ClassNotFoundException { if (plugin.getManagers() != null && plugin.getManagers().getIntegrationManager() != null) throw new UnsupportedOperationException("IntegrationManager already loaded"); plugin.getLogger().info("Loading IntegrationManager implementation..."); - if (Bukkit.getPluginManager().getPlugin(this.plugin) == null) { + if (!this.plugin.equals("RPGRegions") && Bukkit.getPluginManager().getPlugin(this.plugin) == null) { return Optional.empty(); } diff --git a/api/src/main/java/net/islandearth/rpgregions/managers/data/region/ConfiguredRegion.java b/api/src/main/java/net/islandearth/rpgregions/managers/data/region/ConfiguredRegion.java index 2eb8ed0..5e2355f 100644 --- a/api/src/main/java/net/islandearth/rpgregions/managers/data/region/ConfiguredRegion.java +++ b/api/src/main/java/net/islandearth/rpgregions/managers/data/region/ConfiguredRegion.java @@ -11,7 +11,6 @@ import net.islandearth.rpgregions.regenerate.Regenerate; import net.islandearth.rpgregions.requirements.RegionRequirement; import net.islandearth.rpgregions.rewards.DiscoveryReward; import net.islandearth.rpgregions.translation.Translations; -import net.islandearth.rpgregions.utils.XSound; import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.Location; @@ -85,7 +84,7 @@ public class ConfiguredRegion { this.id = id; this.customName = customName; this.rewards = rewards; - this.sound = XSound.UI_TOAST_CHALLENGE_COMPLETE.parseSound(); + this.sound = Sound.UI_TOAST_CHALLENGE_COMPLETE; Optional defaultIcon = Optional.of(Material.valueOf(RPGRegionsAPI.getAPI().getConfig().getString("settings.server.gui.default_region_icon"))); this.icon = defaultIcon.map(Enum::name).orElseGet(Material.TOTEM_OF_UNDYING::name); this.undiscoveredIcon = defaultIcon.map(Enum::name).orElseGet(Material.TOTEM_OF_UNDYING::name); diff --git a/api/src/main/java/net/islandearth/rpgregions/utils/XSound.java b/api/src/main/java/net/islandearth/rpgregions/utils/XSound.java index 9f51ba3..00ff910 100644 --- a/api/src/main/java/net/islandearth/rpgregions/utils/XSound.java +++ b/api/src/main/java/net/islandearth/rpgregions/utils/XSound.java @@ -1,32 +1,45 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2021 Crypto Morin + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR + * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE + * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ package net.islandearth.rpgregions.utils; import com.google.common.base.Enums; import com.google.common.base.Strings; -import com.google.common.cache.Cache; -import com.google.common.cache.CacheBuilder; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.Validate; import org.apache.commons.lang.WordUtils; import org.bukkit.Instrument; import org.bukkit.Location; -import org.bukkit.Material; import org.bukkit.Note; import org.bukkit.Sound; import org.bukkit.entity.Entity; import org.bukkit.entity.Player; import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.scheduler.BukkitRunnable; -import org.jetbrains.annotations.Nullable; +import org.bukkit.scheduler.BukkitTask; import javax.annotation.Nonnull; -import java.util.Arrays; -import java.util.EnumSet; -import java.util.Locale; -import java.util.Objects; -import java.util.Optional; +import javax.annotation.Nullable; +import java.util.*; import java.util.concurrent.CompletableFuture; -import java.util.concurrent.TimeUnit; -import java.util.regex.Pattern; /** * XSound - Universal Minecraft Sound Support
@@ -44,18 +57,48 @@ import java.util.regex.Pattern; * play command: https://minecraft.gamepedia.com/Commands/play * * @author Crypto Morin - * @version 3.0.0 + * @version 7.0.0 * @see Sound */ -@Deprecated public enum XSound { + AMBIENT_BASALT_DELTAS_ADDITIONS, + AMBIENT_BASALT_DELTAS_LOOP, + AMBIENT_BASALT_DELTAS_MOOD, AMBIENT_CAVE("AMBIENCE_CAVE"), + AMBIENT_CRIMSON_FOREST_ADDITIONS, + AMBIENT_CRIMSON_FOREST_LOOP, + AMBIENT_CRIMSON_FOREST_MOOD, + AMBIENT_NETHER_WASTES_ADDITIONS, + AMBIENT_NETHER_WASTES_LOOP, + AMBIENT_NETHER_WASTES_MOOD, + AMBIENT_SOUL_SAND_VALLEY_ADDITIONS, + AMBIENT_SOUL_SAND_VALLEY_LOOP, + AMBIENT_SOUL_SAND_VALLEY_MOOD, AMBIENT_UNDERWATER_ENTER, AMBIENT_UNDERWATER_EXIT, AMBIENT_UNDERWATER_LOOP("AMBIENT_UNDERWATER_EXIT"), AMBIENT_UNDERWATER_LOOP_ADDITIONS("AMBIENT_UNDERWATER_EXIT"), AMBIENT_UNDERWATER_LOOP_ADDITIONS_RARE("AMBIENT_UNDERWATER_EXIT"), AMBIENT_UNDERWATER_LOOP_ADDITIONS_ULTRA_RARE("AMBIENT_UNDERWATER_EXIT"), + AMBIENT_WARPED_FOREST_ADDITIONS, + AMBIENT_WARPED_FOREST_LOOP, + AMBIENT_WARPED_FOREST_MOOD, + BLOCK_AMETHYST_BLOCK_BREAK, + BLOCK_AMETHYST_BLOCK_CHIME, + BLOCK_AMETHYST_BLOCK_FALL, + BLOCK_AMETHYST_BLOCK_HIT, + BLOCK_AMETHYST_BLOCK_PLACE, + BLOCK_AMETHYST_BLOCK_STEP, + BLOCK_AMETHYST_CLUSTER_BREAK, + BLOCK_AMETHYST_CLUSTER_FALL, + BLOCK_AMETHYST_CLUSTER_HIT, + BLOCK_AMETHYST_CLUSTER_PLACE, + BLOCK_AMETHYST_CLUSTER_STEP, + BLOCK_ANCIENT_DEBRIS_BREAK, + BLOCK_ANCIENT_DEBRIS_FALL, + BLOCK_ANCIENT_DEBRIS_HIT, + BLOCK_ANCIENT_DEBRIS_PLACE, + BLOCK_ANCIENT_DEBRIS_STEP, BLOCK_ANVIL_BREAK("ANVIL_BREAK"), BLOCK_ANVIL_DESTROY, BLOCK_ANVIL_FALL, @@ -64,6 +107,16 @@ public enum XSound { BLOCK_ANVIL_PLACE("BLOCK_ANVIL_FALL"), BLOCK_ANVIL_STEP("BLOCK_ANVIL_FALL"), BLOCK_ANVIL_USE("ANVIL_USE"), + BLOCK_AZALEA_BREAK, + BLOCK_AZALEA_FALL, + BLOCK_AZALEA_HIT, + BLOCK_AZALEA_LEAVES_BREAK, + BLOCK_AZALEA_LEAVES_FALL, + BLOCK_AZALEA_LEAVES_HIT, + BLOCK_AZALEA_LEAVES_PLACE, + BLOCK_AZALEA_LEAVES_STEP, + BLOCK_AZALEA_PLACE, + BLOCK_AZALEA_STEP, BLOCK_BAMBOO_BREAK, BLOCK_BAMBOO_FALL, BLOCK_BAMBOO_HIT, @@ -74,6 +127,11 @@ public enum XSound { BLOCK_BAMBOO_STEP, BLOCK_BARREL_CLOSE, BLOCK_BARREL_OPEN, + BLOCK_BASALT_BREAK, + BLOCK_BASALT_FALL, + BLOCK_BASALT_HIT, + BLOCK_BASALT_PLACE, + BLOCK_BASALT_STEP, BLOCK_BEACON_ACTIVATE, BLOCK_BEACON_AMBIENT, BLOCK_BEACON_DEACTIVATE("BLOCK_BEACON_AMBIENT"), @@ -85,14 +143,50 @@ public enum XSound { BLOCK_BEEHIVE_WORK, BLOCK_BELL_RESONATE, BLOCK_BELL_USE, + BLOCK_BIG_DRIPLEAF_BREAK, + BLOCK_BIG_DRIPLEAF_FALL, + BLOCK_BIG_DRIPLEAF_HIT, + BLOCK_BIG_DRIPLEAF_PLACE, + BLOCK_BIG_DRIPLEAF_STEP, + BLOCK_BIG_DRIPLEAF_TILT_DOWN, + BLOCK_BIG_DRIPLEAF_TILT_UP, BLOCK_BLASTFURNACE_FIRE_CRACKLE, + BLOCK_BONE_BLOCK_BREAK, + BLOCK_BONE_BLOCK_FALL, + BLOCK_BONE_BLOCK_HIT, + BLOCK_BONE_BLOCK_PLACE, + BLOCK_BONE_BLOCK_STEP, BLOCK_BREWING_STAND_BREW, BLOCK_BUBBLE_COLUMN_BUBBLE_POP, BLOCK_BUBBLE_COLUMN_UPWARDS_AMBIENT, BLOCK_BUBBLE_COLUMN_UPWARDS_INSIDE, BLOCK_BUBBLE_COLUMN_WHIRLPOOL_AMBIENT, BLOCK_BUBBLE_COLUMN_WHIRLPOOL_INSIDE, + BLOCK_CAKE_ADD_CANDLE, + BLOCK_CALCITE_BREAK, + BLOCK_CALCITE_FALL, + BLOCK_CALCITE_HIT, + BLOCK_CALCITE_PLACE, + BLOCK_CALCITE_STEP, BLOCK_CAMPFIRE_CRACKLE, + BLOCK_CANDLE_AMBIENT, + BLOCK_CANDLE_BREAK, + BLOCK_CANDLE_EXTINGUISH, + BLOCK_CANDLE_FALL, + BLOCK_CANDLE_HIT, + BLOCK_CANDLE_PLACE, + BLOCK_CANDLE_STEP, + BLOCK_CAVE_VINES_BREAK, + BLOCK_CAVE_VINES_FALL, + BLOCK_CAVE_VINES_HIT, + BLOCK_CAVE_VINES_PICK_BERRIES, + BLOCK_CAVE_VINES_PLACE, + BLOCK_CAVE_VINES_STEP, + BLOCK_CHAIN_BREAK, + BLOCK_CHAIN_FALL, + BLOCK_CHAIN_HIT, + BLOCK_CHAIN_PLACE, + BLOCK_CHAIN_STEP, BLOCK_CHEST_CLOSE("CHEST_CLOSE", "ENTITY_CHEST_CLOSE"), BLOCK_CHEST_LOCKED, BLOCK_CHEST_OPEN("CHEST_OPEN", "ENTITY_CHEST_OPEN"), @@ -108,15 +202,40 @@ public enum XSound { BLOCK_CONDUIT_AMBIENT_SHORT, BLOCK_CONDUIT_ATTACK_TARGET, BLOCK_CONDUIT_DEACTIVATE, + BLOCK_COPPER_BREAK, + BLOCK_COPPER_FALL, + BLOCK_COPPER_HIT, + BLOCK_COPPER_PLACE, + BLOCK_COPPER_STEP, BLOCK_CORAL_BLOCK_BREAK, BLOCK_CORAL_BLOCK_FALL, BLOCK_CORAL_BLOCK_HIT, BLOCK_CORAL_BLOCK_PLACE, BLOCK_CORAL_BLOCK_STEP, BLOCK_CROP_BREAK, + BLOCK_DEEPSLATE_BREAK, + BLOCK_DEEPSLATE_BRICKS_BREAK, + BLOCK_DEEPSLATE_BRICKS_FALL, + BLOCK_DEEPSLATE_BRICKS_HIT, + BLOCK_DEEPSLATE_BRICKS_PLACE, + BLOCK_DEEPSLATE_BRICKS_STEP, + BLOCK_DEEPSLATE_FALL, + BLOCK_DEEPSLATE_HIT, + BLOCK_DEEPSLATE_PLACE, + BLOCK_DEEPSLATE_STEP, + BLOCK_DEEPSLATE_TILES_BREAK, + BLOCK_DEEPSLATE_TILES_FALL, + BLOCK_DEEPSLATE_TILES_HIT, + BLOCK_DEEPSLATE_TILES_PLACE, + BLOCK_DEEPSLATE_TILES_STEP, BLOCK_DISPENSER_DISPENSE, BLOCK_DISPENSER_FAIL, BLOCK_DISPENSER_LAUNCH, + BLOCK_DRIPSTONE_BLOCK_BREAK, + BLOCK_DRIPSTONE_BLOCK_FALL, + BLOCK_DRIPSTONE_BLOCK_HIT, + BLOCK_DRIPSTONE_BLOCK_PLACE, + BLOCK_DRIPSTONE_BLOCK_STEP, BLOCK_ENCHANTMENT_TABLE_USE, BLOCK_ENDER_CHEST_CLOSE, BLOCK_ENDER_CHEST_OPEN, @@ -127,7 +246,22 @@ public enum XSound { BLOCK_FENCE_GATE_OPEN, BLOCK_FIRE_AMBIENT("FIRE"), BLOCK_FIRE_EXTINGUISH("FIZZ"), + BLOCK_FLOWERING_AZALEA_BREAK, + BLOCK_FLOWERING_AZALEA_FALL, + BLOCK_FLOWERING_AZALEA_HIT, + BLOCK_FLOWERING_AZALEA_PLACE, + BLOCK_FLOWERING_AZALEA_STEP, + BLOCK_FUNGUS_BREAK, + BLOCK_FUNGUS_FALL, + BLOCK_FUNGUS_HIT, + BLOCK_FUNGUS_PLACE, + BLOCK_FUNGUS_STEP, BLOCK_FURNACE_FIRE_CRACKLE, + BLOCK_GILDED_BLACKSTONE_BREAK, + BLOCK_GILDED_BLACKSTONE_FALL, + BLOCK_GILDED_BLACKSTONE_HIT, + BLOCK_GILDED_BLACKSTONE_PLACE, + BLOCK_GILDED_BLACKSTONE_STEP, BLOCK_GLASS_BREAK("GLASS"), BLOCK_GLASS_FALL, BLOCK_GLASS_HIT, @@ -144,6 +278,11 @@ public enum XSound { BLOCK_GRAVEL_PLACE, BLOCK_GRAVEL_STEP("STEP_GRAVEL"), BLOCK_GRINDSTONE_USE, + BLOCK_HANGING_ROOTS_BREAK, + BLOCK_HANGING_ROOTS_FALL, + BLOCK_HANGING_ROOTS_HIT, + BLOCK_HANGING_ROOTS_PLACE, + BLOCK_HANGING_ROOTS_STEP, BLOCK_HONEY_BLOCK_BREAK, BLOCK_HONEY_BLOCK_FALL, BLOCK_HONEY_BLOCK_HIT, @@ -164,11 +303,20 @@ public enum XSound { BLOCK_LANTERN_HIT, BLOCK_LANTERN_PLACE, BLOCK_LANTERN_STEP, + BLOCK_LARGE_AMETHYST_BUD_BREAK, + BLOCK_LARGE_AMETHYST_BUD_PLACE, BLOCK_LAVA_AMBIENT("LAVA"), BLOCK_LAVA_EXTINGUISH, BLOCK_LAVA_POP("LAVA_POP"), BLOCK_LEVER_CLICK, BLOCK_LILY_PAD_PLACE("BLOCK_WATERLILY_PLACE"), + BLOCK_LODESTONE_BREAK, + BLOCK_LODESTONE_FALL, + BLOCK_LODESTONE_HIT, + BLOCK_LODESTONE_PLACE, + BLOCK_LODESTONE_STEP, + BLOCK_MEDIUM_AMETHYST_BUD_BREAK, + BLOCK_MEDIUM_AMETHYST_BUD_PLACE, BLOCK_METAL_BREAK, BLOCK_METAL_FALL, BLOCK_METAL_HIT, @@ -176,165 +324,16 @@ public enum XSound { BLOCK_METAL_PRESSURE_PLATE_CLICK_OFF("BLOCK_METAL_PRESSUREPLATE_CLICK_OFF"), BLOCK_METAL_PRESSURE_PLATE_CLICK_ON("BLOCK_METAL_PRESSUREPLATE_CLICK_ON"), BLOCK_METAL_STEP, - BLOCK_NETHER_WART_BREAK, - BLOCK_NOTE_BLOCK_BANJO, - BLOCK_NOTE_BLOCK_BASEDRUM("NOTE_BASS_DRUM", "BLOCK_NOTE_BASEDRUM"), - BLOCK_NOTE_BLOCK_BASS("NOTE_BASS", "BLOCK_NOTE_BASS"), - BLOCK_NOTE_BLOCK_BELL("BLOCK_NOTE_BELL"), - BLOCK_NOTE_BLOCK_BIT, - BLOCK_NOTE_BLOCK_CHIME("BLOCK_NOTE_CHIME"), - BLOCK_NOTE_BLOCK_COW_BELL, - BLOCK_NOTE_BLOCK_DIDGERIDOO, - BLOCK_NOTE_BLOCK_FLUTE("BLOCK_NOTE_FLUTE"), - BLOCK_NOTE_BLOCK_GUITAR("NOTE_BASS_GUITAR", "BLOCK_NOTE_GUITAR"), - BLOCK_NOTE_BLOCK_HARP("NOTE_PIANO", "BLOCK_NOTE_HARP"), - BLOCK_NOTE_BLOCK_HAT("NOTE_STICKS", "BLOCK_NOTE_HAT"), - BLOCK_NOTE_BLOCK_IRON_XYLOPHONE, - BLOCK_NOTE_BLOCK_PLING("NOTE_PLING", "BLOCK_NOTE_PLING"), - BLOCK_NOTE_BLOCK_SNARE("NOTE_SNARE_DRUM", "BLOCK_NOTE_SNARE"), - BLOCK_NOTE_BLOCK_XYLOPHONE("BLOCK_NOTE_XYLOPHONE"), - BLOCK_PISTON_CONTRACT("PISTON_RETRACT"), - BLOCK_PISTON_EXTEND("PISTON_EXTEND"), - BLOCK_PORTAL_AMBIENT("PORTAL"), - BLOCK_PORTAL_TRAVEL("PORTAL_TRAVEL"), - BLOCK_PORTAL_TRIGGER("PORTAL_TRIGGER"), - BLOCK_PUMPKIN_CARVE, - BLOCK_REDSTONE_TORCH_BURNOUT, - BLOCK_SAND_BREAK("DIG_SAND"), - BLOCK_SAND_FALL, - BLOCK_SAND_HIT, - BLOCK_SAND_PLACE, - BLOCK_SAND_STEP("STEP_SAND"), - BLOCK_SCAFFOLDING_BREAK, - BLOCK_SCAFFOLDING_FALL, - BLOCK_SCAFFOLDING_HIT, - BLOCK_SCAFFOLDING_PLACE, - BLOCK_SCAFFOLDING_STEP, - BLOCK_SHULKER_BOX_CLOSE, - BLOCK_SHULKER_BOX_OPEN, - BLOCK_SLIME_BLOCK_BREAK("BLOCK_SLIME_BREAK"), - BLOCK_SLIME_BLOCK_FALL("BLOCK_SLIME_FALL"), - BLOCK_SLIME_BLOCK_HIT("BLOCK_SLIME_HIT"), - BLOCK_SLIME_BLOCK_PLACE("BLOCK_SLIME_PLACE"), - BLOCK_SLIME_BLOCK_STEP("BLOCK_SLIME_STEP"), - BLOCK_SMOKER_SMOKE, - BLOCK_SNOW_BREAK("DIG_SNOW"), - BLOCK_SNOW_FALL, - BLOCK_SNOW_HIT, - BLOCK_SNOW_PLACE, - BLOCK_SNOW_STEP("STEP_SNOW"), - BLOCK_STONE_BREAK("DIG_STONE"), - BLOCK_STONE_BUTTON_CLICK_OFF, - BLOCK_STONE_BUTTON_CLICK_ON, - BLOCK_STONE_FALL, - BLOCK_STONE_HIT, - BLOCK_STONE_PLACE, - BLOCK_STONE_PRESSURE_PLATE_CLICK_OFF("BLOCK_STONE_PRESSUREPLATE_CLICK_OFF"), - BLOCK_STONE_PRESSURE_PLATE_CLICK_ON("BLOCK_STONE_PRESSUREPLATE_CLICK_ON"), - BLOCK_STONE_STEP("STEP_STONE"), - BLOCK_SWEET_BERRY_BUSH_BREAK, - BLOCK_SWEET_BERRY_BUSH_PLACE, - BLOCK_TRIPWIRE_ATTACH, - BLOCK_TRIPWIRE_CLICK_OFF, - BLOCK_TRIPWIRE_CLICK_ON, - BLOCK_TRIPWIRE_DETACH, - BLOCK_WATER_AMBIENT("WATER"), - BLOCK_WET_GRASS_BREAK, - BLOCK_WET_GRASS_FALL, - BLOCK_WET_GRASS_HIT, - BLOCK_WET_GRASS_PLACE("BLOCK_WET_GRASS_HIT"), - BLOCK_WET_GRASS_STEP("BLOCK_WET_GRASS_HIT"), - BLOCK_WOODEN_BUTTON_CLICK_OFF("WOOD_CLICK", "BLOCK_WOOD_BUTTON_CLICK_OFF"), - BLOCK_WOODEN_BUTTON_CLICK_ON("WOOD_CLICK", "BLOCK_WOOD_BUTTON_CLICK_ON"), - BLOCK_WOODEN_DOOR_CLOSE("DOOR_CLOSE"), - BLOCK_WOODEN_DOOR_OPEN("DOOR_OPEN"), - BLOCK_WOODEN_PRESSURE_PLATE_CLICK_OFF("BLOCK_WOOD_PRESSUREPLATE_CLICK_OFF"), - BLOCK_WOODEN_PRESSURE_PLATE_CLICK_ON("BLOCK_WOOD_PRESSUREPLATE_CLICK_ON"), - BLOCK_WOODEN_TRAPDOOR_CLOSE, - BLOCK_WOODEN_TRAPDOOR_OPEN, - BLOCK_WOOD_BREAK("DIG_WOOD"), - BLOCK_WOOD_FALL, - BLOCK_WOOD_HIT, - BLOCK_WOOD_PLACE, - BLOCK_WOOD_STEP("STEP_WOOD"), - BLOCK_WOOL_BREAK("DIG_WOOL", "BLOCK_CLOTH_BREAK"), - BLOCK_WOOL_FALL, - BLOCK_WOOL_HIT("BLOCK_WOOL_FALL"), - BLOCK_WOOL_PLACE("BLOCK_WOOL_FALL"), - BLOCK_WOOL_STEP("STEP_WOOL", "BLOCK_CLOTH_STEP"), - ENCHANT_THORNS_HIT, - ENTITY_ARMOR_STAND_BREAK("ENTITY_ARMORSTAND_BREAK"), - ENTITY_ARMOR_STAND_FALL("ENTITY_ARMORSTAND_FALL"), - ENTITY_ARMOR_STAND_HIT("ENTITY_ARMORSTAND_HIT"), - ENTITY_ARMOR_STAND_PLACE("ENTITY_ARMORSTAND_PLACE"), - ENTITY_ARROW_HIT("ARROW_HIT"), - ENTITY_ARROW_HIT_PLAYER, - ENTITY_ARROW_SHOOT("SHOOT_ARROW"), - ENTITY_BAT_AMBIENT("BAT_IDLE"), - ENTITY_BAT_DEATH("BAT_DEATH"), - ENTITY_BAT_HURT("BAT_HURT"), - ENTITY_BAT_LOOP("BAT_LOOP"), - ENTITY_BAT_TAKEOFF("BAT_TAKEOFF"), - ENTITY_BEE_DEATH, - ENTITY_BEE_HURT, - ENTITY_BEE_LOOP, - ENTITY_BEE_LOOP_AGGRESSIVE, - ENTITY_BEE_POLLINATE, - ENTITY_BEE_STING, - ENTITY_BLAZE_AMBIENT("BLAZE_BREATH"), - ENTITY_BLAZE_BURN, - ENTITY_BLAZE_DEATH("BLAZE_DEATH"), - ENTITY_BLAZE_HURT("BLAZE_HIT"), - ENTITY_BLAZE_SHOOT, - ENTITY_BOAT_PADDLE_LAND, - AMBIENT_BASALT_DELTAS_ADDITIONS, - AMBIENT_BASALT_DELTAS_LOOP, - AMBIENT_BASALT_DELTAS_MOOD, - AMBIENT_CRIMSON_FOREST_ADDITIONS, - AMBIENT_CRIMSON_FOREST_LOOP, - AMBIENT_CRIMSON_FOREST_MOOD, - AMBIENT_NETHER_WASTES_ADDITIONS, - AMBIENT_NETHER_WASTES_LOOP, - AMBIENT_NETHER_WASTES_MOOD, - AMBIENT_SOUL_SAND_VALLEY_ADDITIONS, - AMBIENT_SOUL_SAND_VALLEY_LOOP, - AMBIENT_SOUL_SAND_VALLEY_MOOD, - ENTITY_BOAT_PADDLE_WATER, - ENTITY_CAT_AMBIENT("CAT_MEOW"), - ENTITY_CAT_BEG_FOR_FOOD, - AMBIENT_WARPED_FOREST_ADDITIONS, - AMBIENT_WARPED_FOREST_LOOP, - AMBIENT_WARPED_FOREST_MOOD, - BLOCK_ANCIENT_DEBRIS_BREAK, - BLOCK_ANCIENT_DEBRIS_FALL, - BLOCK_ANCIENT_DEBRIS_HIT, - BLOCK_ANCIENT_DEBRIS_PLACE, - BLOCK_ANCIENT_DEBRIS_STEP, - BLOCK_BASALT_BREAK, - BLOCK_BASALT_FALL, - BLOCK_BASALT_HIT, - BLOCK_BASALT_PLACE, - BLOCK_BASALT_STEP, - BLOCK_BONE_BLOCK_BREAK, - BLOCK_BONE_BLOCK_FALL, - BLOCK_BONE_BLOCK_HIT, - BLOCK_BONE_BLOCK_PLACE, - BLOCK_BONE_BLOCK_STEP, - BLOCK_CHAIN_BREAK, - BLOCK_CHAIN_FALL, - BLOCK_CHAIN_HIT, - BLOCK_CHAIN_PLACE, - BLOCK_CHAIN_STEP, - BLOCK_FUNGUS_BREAK, - BLOCK_FUNGUS_FALL, - BLOCK_FUNGUS_HIT, - BLOCK_FUNGUS_PLACE, - BLOCK_FUNGUS_STEP, - BLOCK_LODESTONE_BREAK, - BLOCK_LODESTONE_FALL, - BLOCK_LODESTONE_HIT, - BLOCK_LODESTONE_PLACE, - BLOCK_LODESTONE_STEP, + BLOCK_MOSS_BREAK, + BLOCK_MOSS_CARPET_BREAK, + BLOCK_MOSS_CARPET_FALL, + BLOCK_MOSS_CARPET_HIT, + BLOCK_MOSS_CARPET_PLACE, + BLOCK_MOSS_CARPET_STEP, + BLOCK_MOSS_FALL, + BLOCK_MOSS_HIT, + BLOCK_MOSS_PLACE, + BLOCK_MOSS_STEP, BLOCK_NETHERITE_BLOCK_BREAK, BLOCK_NETHERITE_BLOCK_FALL, BLOCK_NETHERITE_BLOCK_HIT, @@ -365,26 +364,112 @@ public enum XSound { BLOCK_NETHER_SPROUTS_HIT, BLOCK_NETHER_SPROUTS_PLACE, BLOCK_NETHER_SPROUTS_STEP, + BLOCK_NETHER_WART_BREAK, + BLOCK_NOTE_BLOCK_BANJO, + BLOCK_NOTE_BLOCK_BASEDRUM("NOTE_BASS_DRUM", "BLOCK_NOTE_BASEDRUM"), + BLOCK_NOTE_BLOCK_BASS("NOTE_BASS", "BLOCK_NOTE_BASS"), + BLOCK_NOTE_BLOCK_BELL("BLOCK_NOTE_BELL"), + BLOCK_NOTE_BLOCK_BIT, + BLOCK_NOTE_BLOCK_CHIME("BLOCK_NOTE_CHIME"), + BLOCK_NOTE_BLOCK_COW_BELL, + BLOCK_NOTE_BLOCK_DIDGERIDOO, + BLOCK_NOTE_BLOCK_FLUTE("BLOCK_NOTE_FLUTE"), + BLOCK_NOTE_BLOCK_GUITAR("NOTE_BASS_GUITAR", "BLOCK_NOTE_GUITAR"), + BLOCK_NOTE_BLOCK_HARP("NOTE_PIANO", "BLOCK_NOTE_HARP"), + BLOCK_NOTE_BLOCK_HAT("NOTE_STICKS", "BLOCK_NOTE_HAT"), + BLOCK_NOTE_BLOCK_IRON_XYLOPHONE, + BLOCK_NOTE_BLOCK_PLING("NOTE_PLING", "BLOCK_NOTE_PLING"), + BLOCK_NOTE_BLOCK_SNARE("NOTE_SNARE_DRUM", "BLOCK_NOTE_SNARE"), + BLOCK_NOTE_BLOCK_XYLOPHONE("BLOCK_NOTE_XYLOPHONE"), BLOCK_NYLIUM_BREAK, BLOCK_NYLIUM_FALL, BLOCK_NYLIUM_HIT, BLOCK_NYLIUM_PLACE, BLOCK_NYLIUM_STEP, + BLOCK_PISTON_CONTRACT("PISTON_RETRACT"), + BLOCK_PISTON_EXTEND("PISTON_EXTEND"), + BLOCK_POINTED_DRIPSTONE_BREAK, + BLOCK_POINTED_DRIPSTONE_DRIP_LAVA, + BLOCK_POINTED_DRIPSTONE_DRIP_LAVA_INTO_CAULDRON, + BLOCK_POINTED_DRIPSTONE_DRIP_WATER, + BLOCK_POINTED_DRIPSTONE_DRIP_WATER_INTO_CAULDRON, + BLOCK_POINTED_DRIPSTONE_FALL, + BLOCK_POINTED_DRIPSTONE_HIT, + BLOCK_POINTED_DRIPSTONE_LAND, + BLOCK_POINTED_DRIPSTONE_PLACE, + BLOCK_POINTED_DRIPSTONE_STEP, + BLOCK_POLISHED_DEEPSLATE_BREAK, + BLOCK_POLISHED_DEEPSLATE_FALL, + BLOCK_POLISHED_DEEPSLATE_HIT, + BLOCK_POLISHED_DEEPSLATE_PLACE, + BLOCK_POLISHED_DEEPSLATE_STEP, + BLOCK_PORTAL_AMBIENT("PORTAL"), + BLOCK_PORTAL_TRAVEL("PORTAL_TRAVEL"), + BLOCK_PORTAL_TRIGGER("PORTAL_TRIGGER"), + BLOCK_POWDER_SNOW_BREAK, + BLOCK_POWDER_SNOW_FALL, + BLOCK_POWDER_SNOW_HIT, + BLOCK_POWDER_SNOW_PLACE, + BLOCK_POWDER_SNOW_STEP, + BLOCK_PUMPKIN_CARVE, + BLOCK_REDSTONE_TORCH_BURNOUT, BLOCK_RESPAWN_ANCHOR_AMBIENT, BLOCK_RESPAWN_ANCHOR_CHARGE, BLOCK_RESPAWN_ANCHOR_DEPLETE, BLOCK_RESPAWN_ANCHOR_SET_SPAWN, + BLOCK_ROOTED_DIRT_BREAK, + BLOCK_ROOTED_DIRT_FALL, + BLOCK_ROOTED_DIRT_HIT, + BLOCK_ROOTED_DIRT_PLACE, + BLOCK_ROOTED_DIRT_STEP, BLOCK_ROOTS_BREAK, BLOCK_ROOTS_FALL, BLOCK_ROOTS_HIT, BLOCK_ROOTS_PLACE, BLOCK_ROOTS_STEP, + BLOCK_SAND_BREAK("DIG_SAND"), + BLOCK_SAND_FALL, + BLOCK_SAND_HIT, + BLOCK_SAND_PLACE, + BLOCK_SAND_STEP("STEP_SAND"), + BLOCK_SCAFFOLDING_BREAK, + BLOCK_SCAFFOLDING_FALL, + BLOCK_SCAFFOLDING_HIT, + BLOCK_SCAFFOLDING_PLACE, + BLOCK_SCAFFOLDING_STEP, + BLOCK_SCULK_SENSOR_BREAK, + BLOCK_SCULK_SENSOR_CLICKING, + BLOCK_SCULK_SENSOR_CLICKING_STOP, + BLOCK_SCULK_SENSOR_FALL, + BLOCK_SCULK_SENSOR_HIT, + BLOCK_SCULK_SENSOR_PLACE, + BLOCK_SCULK_SENSOR_STEP, BLOCK_SHROOMLIGHT_BREAK, BLOCK_SHROOMLIGHT_FALL, BLOCK_SHROOMLIGHT_HIT, BLOCK_SHROOMLIGHT_PLACE, BLOCK_SHROOMLIGHT_STEP, + BLOCK_SHULKER_BOX_CLOSE, + BLOCK_SHULKER_BOX_OPEN, + BLOCK_SLIME_BLOCK_BREAK("BLOCK_SLIME_BREAK"), + BLOCK_SLIME_BLOCK_FALL("BLOCK_SLIME_FALL"), + BLOCK_SLIME_BLOCK_HIT("BLOCK_SLIME_HIT"), + BLOCK_SLIME_BLOCK_PLACE("BLOCK_SLIME_PLACE"), + BLOCK_SLIME_BLOCK_STEP("BLOCK_SLIME_STEP"), + BLOCK_SMALL_AMETHYST_BUD_BREAK, + BLOCK_SMALL_AMETHYST_BUD_PLACE, + BLOCK_SMALL_DRIPLEAF_BREAK, + BLOCK_SMALL_DRIPLEAF_FALL, + BLOCK_SMALL_DRIPLEAF_HIT, + BLOCK_SMALL_DRIPLEAF_PLACE, + BLOCK_SMALL_DRIPLEAF_STEP, BLOCK_SMITHING_TABLE_USE, + BLOCK_SMOKER_SMOKE, + BLOCK_SNOW_BREAK("DIG_SNOW"), + BLOCK_SNOW_FALL, + BLOCK_SNOW_HIT, + BLOCK_SNOW_PLACE, + BLOCK_SNOW_STEP("STEP_SNOW"), BLOCK_SOUL_SAND_BREAK, BLOCK_SOUL_SAND_FALL, BLOCK_SOUL_SAND_HIT, @@ -395,68 +480,111 @@ public enum XSound { BLOCK_SOUL_SOIL_HIT, BLOCK_SOUL_SOIL_PLACE, BLOCK_SOUL_SOIL_STEP, + BLOCK_SPORE_BLOSSOM_BREAK, + BLOCK_SPORE_BLOSSOM_FALL, + BLOCK_SPORE_BLOSSOM_HIT, + BLOCK_SPORE_BLOSSOM_PLACE, + BLOCK_SPORE_BLOSSOM_STEP, BLOCK_STEM_BREAK, BLOCK_STEM_FALL, BLOCK_STEM_HIT, BLOCK_STEM_PLACE, BLOCK_STEM_STEP, + BLOCK_STONE_BREAK("DIG_STONE"), + BLOCK_STONE_BUTTON_CLICK_OFF, + BLOCK_STONE_BUTTON_CLICK_ON, + BLOCK_STONE_FALL, + BLOCK_STONE_HIT, + BLOCK_STONE_PLACE, + BLOCK_STONE_PRESSURE_PLATE_CLICK_OFF("BLOCK_STONE_PRESSUREPLATE_CLICK_OFF"), + BLOCK_STONE_PRESSURE_PLATE_CLICK_ON("BLOCK_STONE_PRESSUREPLATE_CLICK_ON"), + BLOCK_STONE_STEP("STEP_STONE"), + BLOCK_SWEET_BERRY_BUSH_BREAK, + BLOCK_SWEET_BERRY_BUSH_PICK_BERRIES("ITEM_SWEET_BERRIES_PICK_FROM_BUSH"), + BLOCK_SWEET_BERRY_BUSH_PLACE, + BLOCK_TRIPWIRE_ATTACH, + BLOCK_TRIPWIRE_CLICK_OFF, + BLOCK_TRIPWIRE_CLICK_ON, + BLOCK_TRIPWIRE_DETACH, + BLOCK_TUFF_BREAK, + BLOCK_TUFF_FALL, + BLOCK_TUFF_HIT, + BLOCK_TUFF_PLACE, + BLOCK_TUFF_STEP, + BLOCK_VINE_BREAK, + BLOCK_VINE_FALL, + BLOCK_VINE_HIT, + BLOCK_VINE_PLACE, BLOCK_VINE_STEP, BLOCK_WART_BLOCK_BREAK, BLOCK_WART_BLOCK_FALL, BLOCK_WART_BLOCK_HIT, BLOCK_WART_BLOCK_PLACE, BLOCK_WART_BLOCK_STEP, - ENTITY_DONKEY_EAT, - ENTITY_FOX_TELEPORT, - ENTITY_HOGLIN_AMBIENT, - ENTITY_HOGLIN_ANGRY, - ENTITY_HOGLIN_ATTACK, - ENTITY_HOGLIN_CONVERTED_TO_ZOMBIFIED, - ENTITY_HOGLIN_DEATH, - ENTITY_HOGLIN_HURT, - ENTITY_HOGLIN_RETREAT, - ENTITY_HOGLIN_STEP, - ENTITY_MULE_EAT, - ENTITY_MULE_ANGRY, - ENTITY_PARROT_IMITATE_HOGLIN, - ENTITY_PARROT_IMITATE_PIGLIN, - ENTITY_PARROT_IMITATE_ZOGLIN, - ENTITY_PIGLIN_ADMIRING_ITEM, - ENTITY_PIGLIN_AMBIENT, - ENTITY_PIGLIN_ANGRY, - ENTITY_PIGLIN_CELEBRATE, - ENTITY_PIGLIN_CONVERTED_TO_ZOMBIFIED, - ENTITY_PIGLIN_DEATH, - ENTITY_PIGLIN_HURT, - ENTITY_PIGLIN_JEALOUS, - ENTITY_PIGLIN_RETREAT, - ENTITY_PIGLIN_STEP, - ENTITY_SNOW_GOLEM_SHEAR, - ENTITY_STRIDER_AMBIENT, - ENTITY_STRIDER_DEATH, - ENTITY_STRIDER_EAT, - ENTITY_STRIDER_HAPPY, - ENTITY_STRIDER_HURT, - ENTITY_STRIDER_RETREAT, - ENTITY_STRIDER_SADDLE, - ENTITY_STRIDER_STEP, - ENTITY_STRIDER_STEP_LAVA, - ENTITY_ZOGLIN_AMBIENT, - ENTITY_ZOGLIN_ANGRY, - ENTITY_ZOGLIN_ATTACK, - ENTITY_ZOGLIN_DEATH, - ENTITY_ZOGLIN_HURT, - ENTITY_ZOGLIN_STEP, + BLOCK_WATER_AMBIENT("WATER"), BLOCK_WEEPING_VINES_BREAK, BLOCK_WEEPING_VINES_FALL, BLOCK_WEEPING_VINES_HIT, BLOCK_WEEPING_VINES_PLACE, BLOCK_WEEPING_VINES_STEP, - BLOCK_GILDED_BLACKSTONE_BREAK, - BLOCK_GILDED_BLACKSTONE_FALL, - BLOCK_GILDED_BLACKSTONE_HIT, - BLOCK_GILDED_BLACKSTONE_PLACE, - BLOCK_GILDED_BLACKSTONE_STEP, + BLOCK_WET_GRASS_BREAK, + BLOCK_WET_GRASS_FALL, + BLOCK_WET_GRASS_HIT, + BLOCK_WET_GRASS_PLACE("BLOCK_WET_GRASS_HIT"), + BLOCK_WET_GRASS_STEP("BLOCK_WET_GRASS_HIT"), + BLOCK_WOODEN_BUTTON_CLICK_OFF("WOOD_CLICK", "BLOCK_WOOD_BUTTON_CLICK_OFF"), + BLOCK_WOODEN_BUTTON_CLICK_ON("WOOD_CLICK", "BLOCK_WOOD_BUTTON_CLICK_ON"), + BLOCK_WOODEN_DOOR_CLOSE("DOOR_CLOSE"), + BLOCK_WOODEN_DOOR_OPEN("DOOR_OPEN"), + BLOCK_WOODEN_PRESSURE_PLATE_CLICK_OFF("BLOCK_WOOD_PRESSUREPLATE_CLICK_OFF"), + BLOCK_WOODEN_PRESSURE_PLATE_CLICK_ON("BLOCK_WOOD_PRESSUREPLATE_CLICK_ON"), + BLOCK_WOODEN_TRAPDOOR_CLOSE, + BLOCK_WOODEN_TRAPDOOR_OPEN, + BLOCK_WOOD_BREAK("DIG_WOOD"), + BLOCK_WOOD_FALL, + BLOCK_WOOD_HIT, + BLOCK_WOOD_PLACE, + BLOCK_WOOD_STEP("STEP_WOOD"), + BLOCK_WOOL_BREAK("DIG_WOOL", "BLOCK_CLOTH_BREAK"), + BLOCK_WOOL_FALL, + BLOCK_WOOL_HIT("BLOCK_WOOL_FALL"), + BLOCK_WOOL_PLACE("BLOCK_WOOL_FALL"), + BLOCK_WOOL_STEP("STEP_WOOL", "BLOCK_CLOTH_STEP"), + ENCHANT_THORNS_HIT, + ENTITY_ARMOR_STAND_BREAK("ENTITY_ARMORSTAND_BREAK"), + ENTITY_ARMOR_STAND_FALL("ENTITY_ARMORSTAND_FALL"), + ENTITY_ARMOR_STAND_HIT("ENTITY_ARMORSTAND_HIT"), + ENTITY_ARMOR_STAND_PLACE("ENTITY_ARMORSTAND_PLACE"), + ENTITY_ARROW_HIT("ARROW_HIT"), + ENTITY_ARROW_HIT_PLAYER("SUCCESSFUL_HIT"), + ENTITY_ARROW_SHOOT("SHOOT_ARROW"), + ENTITY_AXOLOTL_ATTACK, + ENTITY_AXOLOTL_DEATH, + ENTITY_AXOLOTL_HURT, + ENTITY_AXOLOTL_IDLE_AIR, + ENTITY_AXOLOTL_IDLE_WATER, + ENTITY_AXOLOTL_SPLASH, + ENTITY_AXOLOTL_SWIM, + ENTITY_BAT_AMBIENT("BAT_IDLE"), + ENTITY_BAT_DEATH("BAT_DEATH"), + ENTITY_BAT_HURT("BAT_HURT"), + ENTITY_BAT_LOOP("BAT_LOOP"), + ENTITY_BAT_TAKEOFF("BAT_TAKEOFF"), + ENTITY_BEE_DEATH, + ENTITY_BEE_HURT, + ENTITY_BEE_LOOP, + ENTITY_BEE_LOOP_AGGRESSIVE, + ENTITY_BEE_POLLINATE, + ENTITY_BEE_STING, + ENTITY_BLAZE_AMBIENT("BLAZE_BREATH"), + ENTITY_BLAZE_BURN, + ENTITY_BLAZE_DEATH("BLAZE_DEATH"), + ENTITY_BLAZE_HURT("BLAZE_HIT"), + ENTITY_BLAZE_SHOOT, + ENTITY_BOAT_PADDLE_LAND, + ENTITY_BOAT_PADDLE_WATER, + ENTITY_CAT_AMBIENT("CAT_MEOW"), + ENTITY_CAT_BEG_FOR_FOOD, ENTITY_CAT_DEATH, ENTITY_CAT_EAT, ENTITY_CAT_HISS("CAT_HISS"), @@ -495,6 +623,7 @@ public enum XSound { ENTITY_DONKEY_ANGRY("DONKEY_ANGRY"), ENTITY_DONKEY_CHEST, ENTITY_DONKEY_DEATH("DONKEY_DEATH"), + ENTITY_DONKEY_EAT, ENTITY_DONKEY_HURT("DONKEY_HIT"), ENTITY_DRAGON_FIREBALL_EXPLODE("ENTITY_ENDERDRAGON_FIREBALL_EXPLODE"), ENTITY_DROWNED_AMBIENT, @@ -567,6 +696,7 @@ public enum XSound { ENTITY_FOX_SLEEP, ENTITY_FOX_SNIFF, ENTITY_FOX_SPIT, + ENTITY_FOX_TELEPORT, ENTITY_GENERIC_BIG_FALL("FALL_BIG"), ENTITY_GENERIC_BURN, ENTITY_GENERIC_DEATH, @@ -584,6 +714,32 @@ public enum XSound { ENTITY_GHAST_SCREAM("GHAST_SCREAM"), ENTITY_GHAST_SHOOT("GHAST_FIREBALL"), ENTITY_GHAST_WARN("GHAST_CHARGE"), + ENTITY_GLOW_ITEM_FRAME_ADD_ITEM, + ENTITY_GLOW_ITEM_FRAME_BREAK, + ENTITY_GLOW_ITEM_FRAME_PLACE, + ENTITY_GLOW_ITEM_FRAME_REMOVE_ITEM, + ENTITY_GLOW_ITEM_FRAME_ROTATE_ITEM, + ENTITY_GLOW_SQUID_AMBIENT, + ENTITY_GLOW_SQUID_DEATH, + ENTITY_GLOW_SQUID_HURT, + ENTITY_GLOW_SQUID_SQUIRT, + ENTITY_GOAT_AMBIENT, + ENTITY_GOAT_DEATH, + ENTITY_GOAT_EAT, + ENTITY_GOAT_HURT, + ENTITY_GOAT_LONG_JUMP, + ENTITY_GOAT_MILK, + ENTITY_GOAT_PREPARE_RAM, + ENTITY_GOAT_RAM_IMPACT, + ENTITY_GOAT_SCREAMING_AMBIENT, + ENTITY_GOAT_SCREAMING_DEATH, + ENTITY_GOAT_SCREAMING_EAT, + ENTITY_GOAT_SCREAMING_HURT, + ENTITY_GOAT_SCREAMING_LONG_JUMP, + ENTITY_GOAT_SCREAMING_MILK, + ENTITY_GOAT_SCREAMING_PREPARE_RAM, + ENTITY_GOAT_SCREAMING_RAM_IMPACT, + ENTITY_GOAT_STEP, ENTITY_GUARDIAN_AMBIENT, ENTITY_GUARDIAN_AMBIENT_LAND, ENTITY_GUARDIAN_ATTACK, @@ -592,6 +748,14 @@ public enum XSound { ENTITY_GUARDIAN_FLOP, ENTITY_GUARDIAN_HURT, ENTITY_GUARDIAN_HURT_LAND, + ENTITY_HOGLIN_AMBIENT, + ENTITY_HOGLIN_ANGRY, + ENTITY_HOGLIN_ATTACK, + ENTITY_HOGLIN_CONVERTED_TO_ZOMBIFIED, + ENTITY_HOGLIN_DEATH, + ENTITY_HOGLIN_HURT, + ENTITY_HOGLIN_RETREAT, + ENTITY_HOGLIN_STEP, ENTITY_HORSE_AMBIENT("HORSE_IDLE"), ENTITY_HORSE_ANGRY("HORSE_ANGRY"), ENTITY_HORSE_ARMOR("HORSE_ARMOR"), @@ -658,6 +822,7 @@ public enum XSound { ENTITY_MAGMA_CUBE_SQUISH("MAGMACUBE_WALK", "ENTITY_MAGMACUBE_SQUISH"), ENTITY_MAGMA_CUBE_SQUISH_SMALL("MAGMACUBE_WALK2", "ENTITY_SMALL_MAGMACUBE_SQUISH"), ENTITY_MINECART_INSIDE("MINECART_INSIDE"), + ENTITY_MINECART_INSIDE_UNDERWATER, ENTITY_MINECART_RIDING("MINECART_BASE"), ENTITY_MOOSHROOM_CONVERT, ENTITY_MOOSHROOM_EAT, @@ -665,8 +830,10 @@ public enum XSound { ENTITY_MOOSHROOM_SHEAR, ENTITY_MOOSHROOM_SUSPICIOUS_MILK, ENTITY_MULE_AMBIENT, + ENTITY_MULE_ANGRY, ENTITY_MULE_CHEST("ENTITY_MULE_AMBIENT"), ENTITY_MULE_DEATH("ENTITY_MULE_AMBIENT"), + ENTITY_MULE_EAT, ENTITY_MULE_HURT("ENTITY_MULE_AMBIENT"), ENTITY_OCELOT_AMBIENT, ENTITY_OCELOT_DEATH, @@ -693,17 +860,26 @@ public enum XSound { ENTITY_PARROT_IMITATE_CREEPER, ENTITY_PARROT_IMITATE_DROWNED, ENTITY_PARROT_IMITATE_ELDER_GUARDIAN, + /** + * Removed in 1.15 + */ ENTITY_PARROT_IMITATE_ENDERMAN, ENTITY_PARROT_IMITATE_ENDERMITE, ENTITY_PARROT_IMITATE_ENDER_DRAGON, ENTITY_PARROT_IMITATE_EVOKER, ENTITY_PARROT_IMITATE_GHAST, ENTITY_PARROT_IMITATE_GUARDIAN, + ENTITY_PARROT_IMITATE_HOGLIN, ENTITY_PARROT_IMITATE_HUSK, ENTITY_PARROT_IMITATE_ILLUSIONER, ENTITY_PARROT_IMITATE_MAGMA_CUBE, ENTITY_PARROT_IMITATE_PHANTOM, + ENTITY_PARROT_IMITATE_PIGLIN, + ENTITY_PARROT_IMITATE_PIGLIN_BRUTE, ENTITY_PARROT_IMITATE_PILLAGER, + /** + * Removed in 1.15 + */ ENTITY_PARROT_IMITATE_POLAR_BEAR, ENTITY_PARROT_IMITATE_RAVAGER, ENTITY_PARROT_IMITATE_SHULKER, @@ -717,7 +893,11 @@ public enum XSound { ENTITY_PARROT_IMITATE_WITCH, ENTITY_PARROT_IMITATE_WITHER, ENTITY_PARROT_IMITATE_WITHER_SKELETON, + /** + * Removed in 1.15 + */ ENTITY_PARROT_IMITATE_WOLF, + ENTITY_PARROT_IMITATE_ZOGLIN, ENTITY_PARROT_IMITATE_ZOMBIE, ENTITY_PARROT_IMITATE_ZOMBIE_VILLAGER, ENTITY_PARROT_STEP, @@ -727,6 +907,22 @@ public enum XSound { ENTITY_PHANTOM_FLAP, ENTITY_PHANTOM_HURT, ENTITY_PHANTOM_SWOOP, + ENTITY_PIGLIN_ADMIRING_ITEM, + ENTITY_PIGLIN_AMBIENT, + ENTITY_PIGLIN_ANGRY, + ENTITY_PIGLIN_BRUTE_AMBIENT, + ENTITY_PIGLIN_BRUTE_ANGRY, + ENTITY_PIGLIN_BRUTE_CONVERTED_TO_ZOMBIFIED, + ENTITY_PIGLIN_BRUTE_DEATH, + ENTITY_PIGLIN_BRUTE_HURT, + ENTITY_PIGLIN_BRUTE_STEP, + ENTITY_PIGLIN_CELEBRATE, + ENTITY_PIGLIN_CONVERTED_TO_ZOMBIFIED, + ENTITY_PIGLIN_DEATH, + ENTITY_PIGLIN_HURT, + ENTITY_PIGLIN_JEALOUS, + ENTITY_PIGLIN_RETREAT, + ENTITY_PIGLIN_STEP, ENTITY_PIG_AMBIENT("PIG_IDLE"), ENTITY_PIG_DEATH("PIG_DEATH"), ENTITY_PIG_HURT, @@ -748,6 +944,7 @@ public enum XSound { ENTITY_PLAYER_DEATH, ENTITY_PLAYER_HURT("HURT_FLESH"), ENTITY_PLAYER_HURT_DROWN, + ENTITY_PLAYER_HURT_FREEZE, ENTITY_PLAYER_HURT_ON_FIRE, ENTITY_PLAYER_HURT_SWEET_BERRY_BUSH, ENTITY_PLAYER_LEVELUP("LEVEL_UP"), @@ -805,6 +1002,7 @@ public enum XSound { ENTITY_SILVERFISH_HURT("SILVERFISH_HIT"), ENTITY_SILVERFISH_STEP("SILVERFISH_WALK"), ENTITY_SKELETON_AMBIENT("SKELETON_IDLE"), + ENTITY_SKELETON_CONVERTED_TO_STRAY, ENTITY_SKELETON_DEATH("SKELETON_DEATH"), ENTITY_SKELETON_HORSE_AMBIENT("HORSE_SKELETON_IDLE"), ENTITY_SKELETON_HORSE_AMBIENT_WATER, @@ -830,6 +1028,7 @@ public enum XSound { ENTITY_SNOW_GOLEM_AMBIENT("ENTITY_SNOWMAN_AMBIENT"), ENTITY_SNOW_GOLEM_DEATH("ENTITY_SNOWMAN_DEATH"), ENTITY_SNOW_GOLEM_HURT("ENTITY_SNOWMAN_HURT"), + ENTITY_SNOW_GOLEM_SHEAR, ENTITY_SNOW_GOLEM_SHOOT("ENTITY_SNOWMAN_SHOOT"), ENTITY_SPIDER_AMBIENT("SPIDER_IDLE"), ENTITY_SPIDER_DEATH("SPIDER_DEATH"), @@ -845,6 +1044,15 @@ public enum XSound { ENTITY_STRAY_DEATH, ENTITY_STRAY_HURT, ENTITY_STRAY_STEP, + ENTITY_STRIDER_AMBIENT, + ENTITY_STRIDER_DEATH, + ENTITY_STRIDER_EAT, + ENTITY_STRIDER_HAPPY, + ENTITY_STRIDER_HURT, + ENTITY_STRIDER_RETREAT, + ENTITY_STRIDER_SADDLE, + ENTITY_STRIDER_STEP, + ENTITY_STRIDER_STEP_LAVA, ENTITY_TNT_PRIMED("FUSE"), ENTITY_TROPICAL_FISH_AMBIENT, ENTITY_TROPICAL_FISH_DEATH, @@ -925,6 +1133,12 @@ public enum XSound { ENTITY_WOLF_SHAKE("WOLF_SHAKE"), ENTITY_WOLF_STEP("WOLF_WALK"), ENTITY_WOLF_WHINE("WOLF_WHINE"), + ENTITY_ZOGLIN_AMBIENT, + ENTITY_ZOGLIN_ANGRY, + ENTITY_ZOGLIN_ATTACK, + ENTITY_ZOGLIN_DEATH, + ENTITY_ZOGLIN_HURT, + ENTITY_ZOGLIN_STEP, ENTITY_ZOMBIE_AMBIENT("ZOMBIE_IDLE"), ENTITY_ZOMBIE_ATTACK_IRON_DOOR("ZOMBIE_METAL"), ENTITY_ZOMBIE_ATTACK_WOODEN_DOOR("ZOMBIE_WOOD", "ENTITY_ZOMBIE_ATTACK_DOOR_WOOD"), @@ -937,14 +1151,6 @@ public enum XSound { ENTITY_ZOMBIE_HORSE_HURT("HORSE_ZOMBIE_HIT"), ENTITY_ZOMBIE_HURT("ZOMBIE_HURT"), ENTITY_ZOMBIE_INFECT("ZOMBIE_INFECT"), - ITEM_ARMOR_EQUIP_NETHERITE, - ITEM_LODESTONE_COMPASS_LOCK, - MUSIC_DISC_PIGSTEP, - - ENTITY_ZOMBIFIED_PIGLIN_AMBIENT("ZOMBE_PIG_IDLE", "ENTITY_ZOMBIE_PIG_AMBIENT", "ENTITY_ZOMBIE_PIGMAN_AMBIENT"), - ENTITY_ZOMBIFIED_PIGLIN_ANGRY("ZOMBIE_PIG_ANGRY", "ENTITY_ZOMBIE_PIG_ANGRY", "ENTITY_ZOMBIE_PIGMAN_ANGRY"), - ENTITY_ZOMBIFIED_PIGLIN_DEATH("ZOMBIE_PIG_DEATH", "ENTITY_ZOMBIE_PIG_DEATH", "ENTITY_ZOMBIE_PIGMAN_DEATH"), - ENTITY_ZOMBIFIED_PIGLIN_HURT("ZOMBIE_PIG_HURT", "ENTITY_ZOMBIE_PIG_HURT", "ENTITY_ZOMBIE_PIGMAN_HURT"), ENTITY_ZOMBIE_STEP("ZOMBIE_WALK"), ENTITY_ZOMBIE_VILLAGER_AMBIENT, ENTITY_ZOMBIE_VILLAGER_CONVERTED("ZOMBIE_UNFECT"), @@ -952,6 +1158,10 @@ public enum XSound { ENTITY_ZOMBIE_VILLAGER_DEATH, ENTITY_ZOMBIE_VILLAGER_HURT, ENTITY_ZOMBIE_VILLAGER_STEP, + ENTITY_ZOMBIFIED_PIGLIN_AMBIENT("ZOMBIE_PIG_IDLE", "ENTITY_ZOMBIE_PIG_AMBIENT", "ENTITY_ZOMBIE_PIGMAN_AMBIENT"), + ENTITY_ZOMBIFIED_PIGLIN_ANGRY("ZOMBIE_PIG_ANGRY", "ENTITY_ZOMBIE_PIG_ANGRY", "ENTITY_ZOMBIE_PIGMAN_ANGRY"), + ENTITY_ZOMBIFIED_PIGLIN_DEATH("ZOMBIE_PIG_DEATH", "ENTITY_ZOMBIE_PIG_DEATH", "ENTITY_ZOMBIE_PIGMAN_DEATH"), + ENTITY_ZOMBIFIED_PIGLIN_HURT("ZOMBIE_PIG_HURT", "ENTITY_ZOMBIE_PIG_HURT", "ENTITY_ZOMBIE_PIGMAN_HURT"), EVENT_RAID_HORN, ITEM_ARMOR_EQUIP_CHAIN, ITEM_ARMOR_EQUIP_DIAMOND, @@ -960,19 +1170,27 @@ public enum XSound { ITEM_ARMOR_EQUIP_GOLD, ITEM_ARMOR_EQUIP_IRON, ITEM_ARMOR_EQUIP_LEATHER, + ITEM_ARMOR_EQUIP_NETHERITE, ITEM_ARMOR_EQUIP_TURTLE, + ITEM_AXE_SCRAPE, ITEM_AXE_STRIP, + ITEM_AXE_WAX_OFF, + ITEM_BONE_MEAL_USE, ITEM_BOOK_PAGE_TURN, ITEM_BOOK_PUT, ITEM_BOTTLE_EMPTY, ITEM_BOTTLE_FILL, ITEM_BOTTLE_FILL_DRAGONBREATH, ITEM_BUCKET_EMPTY, + ITEM_BUCKET_EMPTY_AXOLOTL, ITEM_BUCKET_EMPTY_FISH, ITEM_BUCKET_EMPTY_LAVA, + ITEM_BUCKET_EMPTY_POWDER_SNOW, ITEM_BUCKET_FILL, + ITEM_BUCKET_FILL_AXOLOTL, ITEM_BUCKET_FILL_FISH, ITEM_BUCKET_FILL_LAVA, + ITEM_BUCKET_FILL_POWDER_SNOW, ITEM_CHORUS_FRUIT_TELEPORT, ITEM_CROP_PLANT, ITEM_CROSSBOW_HIT, @@ -983,16 +1201,22 @@ public enum XSound { ITEM_CROSSBOW_QUICK_CHARGE_2, ITEM_CROSSBOW_QUICK_CHARGE_3, ITEM_CROSSBOW_SHOOT, + ITEM_DYE_USE, ITEM_ELYTRA_FLYING, ITEM_FIRECHARGE_USE, ITEM_FLINTANDSTEEL_USE("FIRE_IGNITE"), + ITEM_GLOW_INK_SAC_USE, ITEM_HOE_TILL, + ITEM_HONEYCOMB_WAX_ON, ITEM_HONEY_BOTTLE_DRINK, + ITEM_INK_SAC_USE, + ITEM_LODESTONE_COMPASS_LOCK, ITEM_NETHER_WART_PLANT, ITEM_SHIELD_BLOCK, ITEM_SHIELD_BREAK, ITEM_SHOVEL_FLATTEN, - ITEM_SWEET_BERRIES_PICK_FROM_BUSH, + ITEM_SPYGLASS_STOP_USING, + ITEM_SPYGLASS_USE, ITEM_TOTEM_USE, ITEM_TRIDENT_HIT, ITEM_TRIDENT_HIT_GROUND, @@ -1012,6 +1236,7 @@ public enum XSound { MUSIC_DISC_FAR("RECORD_FAR"), MUSIC_DISC_MALL("RECORD_MALL"), MUSIC_DISC_MELLOHI("RECORD_MELLOHI"), + MUSIC_DISC_PIGSTEP, MUSIC_DISC_STAL("RECORD_STAL"), MUSIC_DISC_STRAD("RECORD_STRAD"), MUSIC_DISC_WAIT("RECORD_WAIT"), @@ -1021,12 +1246,12 @@ public enum XSound { MUSIC_GAME, MUSIC_MENU, MUSIC_NETHER_BASALT_DELTAS("MUSIC_NETHER"), - PARTICLE_SOUL_ESCAPE, MUSIC_NETHER_CRIMSON_FOREST, MUSIC_NETHER_NETHER_WASTES, MUSIC_NETHER_SOUL_SAND_VALLEY, MUSIC_NETHER_WARPED_FOREST, MUSIC_UNDER_WATER, + PARTICLE_SOUL_ESCAPE, UI_BUTTON_CLICK("CLICK"), UI_CARTOGRAPHY_TABLE_TAKE_RESULT, UI_LOOM_SELECT_PATTERN, @@ -1039,91 +1264,94 @@ public enum XSound { WEATHER_RAIN("AMBIENCE_RAIN"), WEATHER_RAIN_ABOVE; - /** - * An immutable cached list of {@link XSound#values()} to avoid allocating memory for + * Cached list of {@link XSound#values()} to avoid allocating memory for * calling the method every time. * * @since 2.0.0 */ - public static final EnumSet VALUES = EnumSet.allOf(XSound.class); - /** - * Guava (Google Core Libraries for Java)'s cache for performance and timed caches. - * Caches the parsed {@link Sound} objects instead of string. Because it has to go through catching exceptions again - * since {@link Sound} class doesn't have a method like {@link Material#getMaterial(String)}. - * So caching these would be more efficient. - * - * @since 2.0.0 - */ - private static final Cache> CACHE = CacheBuilder.newBuilder() - .expireAfterAccess(10, TimeUnit.MINUTES) - .softValues() - .build(); - /** - * Pre-compiled RegEx pattern. - * Include both replacements to avoid creating string multiple times and multiple RegEx checks. - * - * @since 1.0.0 - */ - private static final Pattern FORMAT_PATTERN = Pattern.compile("\\d+|\\W+"); - private static final Pattern DOUBLE_SPACE = Pattern.compile(" +"); - private final String[] legacy; + public static final XSound[] VALUES = values(); - XSound(String... legacy) { - this.legacy = legacy; + public static final float DEFAULT_VOLUME = 1.0f, DEFAULT_PITCH = 1.0f; + + @Nullable + private final Sound sound; + + XSound(@Nonnull String... legacies) { + Sound bukkitSound = Data.BUKKIT_NAMES.get(this.name()); + if (bukkitSound == null) { + for (String legacy : legacies) { + bukkitSound = Data.BUKKIT_NAMES.get(legacy); + if (bukkitSound != null) break; + } + } + this.sound = bukkitSound; + + Data.NAMES.put(this.name(), this); + for (String legacy : legacies) { + Data.NAMES.putIfAbsent(legacy, this); + } } /** * Attempts to build the string like an enum name.
* Removes all the spaces, numbers and extra non-English characters. Also removes some config/in-game based strings. + * While this method is hard to maintain, it's extremely efficient. It's approximately more than x5 times faster than + * the normal RegEx + String Methods approach for both formatted and unformatted material names. * - * @param name the sound name to modify. - * @return a Sound enum name. + * @param name the sound name to format. + * + * @return an enum name. * @since 1.0.0 */ @Nonnull private static String format(@Nonnull String name) { - return FORMAT_PATTERN.matcher( - name.trim().replace('-', '_').replace(' ', '_')).replaceAll("").toUpperCase(Locale.ENGLISH); - } + int len = name.length(); + char[] chs = new char[len]; + int count = 0; + boolean appendUnderline = false; - /** - * Checks if XSound enum and the legacy names contains a sound with this name. - * - * @param sound name of the sound - * @return true if XSound enum has this sound. - * @since 1.0.0 - */ - public static boolean contains(@Nonnull String sound) { - Validate.notEmpty(sound, "Cannot check for null or empty sound name"); - sound = format(sound); + for (int i = 0; i < len; i++) { + char ch = name.charAt(i); - for (XSound sounds : VALUES) - if (sounds.name().equals(sound) || sounds.anyMatchLegacy(sound)) return true; - return false; + if (!appendUnderline && count != 0 && (ch == '-' || ch == ' ' || ch == '_') && chs[count] != '_') appendUnderline = true; + else { + boolean number = false; + // A few sounds have numbers in them. + if ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') || (number = (ch >= '0' && ch <= '9'))) { + if (appendUnderline) { + chs[count++] = '_'; + appendUnderline = false; + } + + if (number) chs[count++] = ch; + else chs[count++] = (char) (ch & 0x5f); + } + } + } + + return new String(chs, 0, count); } /** * Parses the XSound with the given name. * * @param sound the name of the sound. + * * @return a matched XSound. * @since 1.0.0 */ @Nonnull public static Optional matchXSound(@Nonnull String sound) { Validate.notEmpty(sound, "Cannot match XSound of a null or empty sound name"); - sound = format(sound); - - for (XSound sounds : VALUES) - if (sounds.name().equals(sound) || sounds.anyMatchLegacy(sound)) return Optional.of(sounds); - return Optional.empty(); + return Optional.ofNullable(Data.NAMES.get(format(sound))); } /** * Parses the XSound with the given bukkit sound. * * @param sound the Bukkit sound. + * * @return a matched sound. * @throws IllegalArgumentException may be thrown as an unexpected exception. * @since 2.0.0 @@ -1131,27 +1359,50 @@ public enum XSound { @Nonnull public static XSound matchXSound(@Nonnull Sound sound) { Objects.requireNonNull(sound, "Cannot match XSound of a null sound"); - return matchXSound(sound.name()) - .orElseThrow(() -> new IllegalArgumentException("Unsupported Sound: " + sound.name())); + return Objects.requireNonNull(Data.NAMES.get(sound.name()), () -> "Unsupported sound: " + sound.name()); } /** + * A quick async way to play a sound from the config. + * + * @param player the player to play the sound to. + * @param sound the sound to play to the player. + * * @see #play(Location, String) * @since 1.0.0 */ @Nonnull - public static CompletableFuture play(@Nullable Player player, @Nullable String sound) { + public static CompletableFuture play(@Nonnull Player player, @Nullable String sound) { Objects.requireNonNull(player, "Cannot play sound to null player"); - return parse(player, player.getLocation(), sound, true); + return CompletableFuture.supplyAsync(() -> { + Record record = parse(sound); + if (record == null) return null; + record.forPlayer(player).play(); + return record; + }).exceptionally(x -> { + x.printStackTrace(); + return null; + }); } /** + * A quick async way to play a sound from the config. + * * @see #play(Location, String) * @since 3.0.0 */ @Nonnull public static CompletableFuture play(@Nonnull Location location, @Nullable String sound) { - return parse(null, location, sound, true); + Objects.requireNonNull(location, "Cannot play sound to null location"); + return CompletableFuture.supplyAsync(() -> { + Record record = parse(sound); + if (record == null) return null; + record.atLocation(location).play(); + return record; + }).exceptionally(x -> { + x.printStackTrace(); + return null; + }); } /** @@ -1170,68 +1421,54 @@ public enum XSound { *

* This will also ignore {@code none} and {@code null} strings. *

- * Format: [LOC:]Sound, [Volume], [Pitch]
- * Where {@code LOC:} will play the sound at the location if a player is specified. + * Format: [~]Sound, [Volume], [Pitch]
+ * Where {@code ~} prefix will play the sound at the location even if a player is specified. * A sound played at a location will be heard by everyone around. - * Comma separators are optional. *

* Examples: *

*

-     *     LOC:ENTITY_PLAYER_BURP, 2.5f, 0.5
+     *     ~ENTITY_PLAYER_BURP, 2.5f, 0.5
      *     ENTITY_PLAYER_BURP, 0.5, 1f
-     *     BURP 0.5f 1
+     *     BURP, 0.5f, 1
      *     MUSIC_END, 10f
-     *     none
-     *     null
+     *     ~MUSIC_END, 10
+     *     none (case-insensitive)
+     *     null (~ in yml)
      * 
+ *

* - * @param player the only player to play the sound to if requested to do so. - * @param location the location to play the sound to. - * @param sound the string of the sound with volume and pitch (if needed). - * @param play if the sound should be played right away. - * @since 3.0.0 + * @param sound the string of the sound with volume and pitch (if needed). + * + * @since 7.0.0 */ - @Nonnull - public static CompletableFuture parse(@Nullable Player player, @Nonnull Location location, @Nullable String sound, boolean play) { - Objects.requireNonNull(player, "Cannot play sound to null location"); + @Nullable + public static Record parse(@Nullable String sound) { if (Strings.isNullOrEmpty(sound) || sound.equalsIgnoreCase("none")) return null; + String[] split = StringUtils.split(StringUtils.deleteWhitespace(sound), ','); - return CompletableFuture.supplyAsync(() -> { - String[] split = StringUtils.contains(sound, ',') ? - StringUtils.split(StringUtils.deleteWhitespace(sound), ',') : - StringUtils.split(DOUBLE_SPACE.matcher(sound).replaceAll(" "), ' '); + String name = split[0]; + boolean playAtLocation; + if (name.charAt(0) == '~') { + name = name.substring(1); + playAtLocation = true; + } else playAtLocation = false; - String name = split[0]; - boolean playForEveryone = player == null; - if (!playForEveryone && StringUtils.startsWithIgnoreCase(name, "loc:")) { - name = name.substring(4); - playForEveryone = true; + Optional soundType = matchXSound(name); + if (!soundType.isPresent()) return null; + + float volume = DEFAULT_VOLUME; + float pitch = DEFAULT_PITCH; + + try { + if (split.length > 1) { + volume = Float.parseFloat(split[1]); + if (split.length > 2) pitch = Float.parseFloat(split[2]); } - Optional typeOpt = matchXSound(name); - if (!typeOpt.isPresent()) return null; - Sound type = typeOpt.get().parseSound(); - if (type == null) return null; + } catch (NumberFormatException ignored) { + } - float volume = 1.0f; - float pitch = 1.0f; - - try { - if (split.length > 1) { - volume = Float.parseFloat(split[1]); - if (split.length > 2) pitch = Float.parseFloat(split[2]); - } - } catch (NumberFormatException ignored) { - } - - Record record = new Record(type, player, location, volume, pitch, playForEveryone); - if (play) record.play(); - return record; - }).exceptionally((ex) -> { - System.err.println("Could not play sound for string: " + sound); - ex.printStackTrace(); - return null; - }); + return new Record(soundType.get(), null, null, volume, pitch, playAtLocation); } /** @@ -1243,25 +1480,62 @@ public enum XSound { * affected by this. * * @param player the player to stop all the sounds from. + * * @see #stopSound(Player) * @since 2.0.0 */ - public static CompletableFuture stopMusic(@Nonnull Player player) { + public static void stopMusic(@Nonnull Player player) { Objects.requireNonNull(player, "Cannot stop playing musics from null player"); // We don't need to cache because it's rarely used. - EnumSet musics = EnumSet.of(MUSIC_CREATIVE, MUSIC_CREDITS, + XSound[] musics = { + MUSIC_CREATIVE, MUSIC_CREDITS, MUSIC_DISC_11, MUSIC_DISC_13, MUSIC_DISC_BLOCKS, MUSIC_DISC_CAT, MUSIC_DISC_CHIRP, MUSIC_DISC_FAR, MUSIC_DISC_MALL, MUSIC_DISC_MELLOHI, MUSIC_DISC_STAL, MUSIC_DISC_STRAD, MUSIC_DISC_WAIT, MUSIC_DISC_WARD, - MUSIC_DRAGON, MUSIC_END, MUSIC_GAME, MUSIC_MENU, MUSIC_NETHER_BASALT_DELTAS, MUSIC_UNDER_WATER); + MUSIC_DRAGON, MUSIC_END, MUSIC_GAME, MUSIC_MENU, MUSIC_NETHER_BASALT_DELTAS, MUSIC_UNDER_WATER, + MUSIC_NETHER_CRIMSON_FOREST, MUSIC_NETHER_WARPED_FOREST + }; - return CompletableFuture.runAsync(() -> { - for (XSound music : musics) { - Sound sound = music.parseSound(); - if (sound != null) player.stopSound(sound); + for (XSound music : musics) { + Sound sound = music.parseSound(); + if (sound != null) player.stopSound(sound); + } + } + + /** + * Plays an instrument's notes in an ascending form. + * This method is not really relevant to this utility class, but a nice feature. + * + * @param plugin the plugin handling schedulers. + * @param player the player to play the note from. + * @param playTo the entity to play the note to. + * @param instrument the instrument. + * @param ascendLevel the ascend level of notes. Can only be positive and not higher than 7 + * @param delay the delay between each play. + * + * @return the async task handling the operation. + * @since 2.0.0 + */ + @Nonnull + public static BukkitTask playAscendingNote(@Nonnull JavaPlugin plugin, @Nonnull Player player, @Nonnull Entity playTo, @Nonnull Instrument instrument, + int ascendLevel, int delay) { + Objects.requireNonNull(player, "Cannot play note from null player"); + Objects.requireNonNull(playTo, "Cannot play note to null entity"); + + Validate.isTrue(ascendLevel > 0, "Note ascend level cannot be lower than 1"); + Validate.isTrue(ascendLevel <= 7, "Note ascend level cannot be greater than 7"); + Validate.isTrue(delay > 0, "Delay ticks must be at least 1"); + + return new BukkitRunnable() { + int repeating = ascendLevel; + + @Override + public void run() { + player.playNote(playTo.getLocation(), instrument, Note.natural(1, Note.Tone.values()[ascendLevel - repeating])); + if (repeating-- == 0) cancel(); } - }); + }.runTaskTimerAsynchronously(plugin, 0, delay); } /** @@ -1274,17 +1548,6 @@ public enum XSound { return WordUtils.capitalize(this.name().replace('_', ' ').toLowerCase(Locale.ENGLISH)); } - /** - * Gets all the previous sound names used for this sound. - * - * @return a list of legacy sound names. - * @since 1.0.0 - */ - @Nonnull - public String[] getLegacy() { - return legacy; - } - /** * Parses the XSound as a {@link Sound} based on the server version. * @@ -1292,26 +1555,8 @@ public enum XSound { * @since 1.0.0 */ @Nullable - @SuppressWarnings({"Guava", "OptionalAssignedToNull"}) public Sound parseSound() { - com.google.common.base.Optional cachedSound = CACHE.getIfPresent(this); - if (cachedSound != null) return cachedSound.orNull(); - com.google.common.base.Optional sound; - - // Since Sound class doesn't have a getSound() method we'll use Guava so - // it can cache it for us. - sound = Enums.getIfPresent(Sound.class, this.name()); - - if (!sound.isPresent()) { - for (String legacy : this.legacy) { - sound = Enums.getIfPresent(Sound.class, legacy); - if (sound.isPresent()) break; - } - } - - // Put nulls too, because there's no point of parsing them again if it's going to give us null again. - CACHE.put(this, sound); - return sound.orNull(); + return this.sound; } /** @@ -1330,18 +1575,6 @@ public enum XSound { return this.parseSound() != null; } - /** - * Checks if the given string matches any of this sound's legacy sound names. - * - * @param name the sound name to check - * @return true if it's one of the legacy names. - * @since 1.0.0 - */ - public boolean anyMatchLegacy(@Nonnull String name) { - Validate.notEmpty(name, "Cannot check for legacy name for null or empty sound name"); - return Arrays.asList(this.legacy).contains(format(name)); - } - /** * Plays a sound repeatedly with the given delay at a moving target's location. * @@ -1351,17 +1584,20 @@ public enum XSound { * @param pitch the pitch of the sound. * @param repeat the amount of times to repeat playing. * @param delay the delay between each repeat. + * + * @return the async task handling this operation. * @see #play(Location, float, float) * @since 2.0.0 */ - public void playRepeatedly(JavaPlugin plugin, Entity entity, float volume, float pitch, int repeat, int delay) { + @Nonnull + public BukkitTask playRepeatedly(@Nonnull JavaPlugin plugin, @Nonnull Entity entity, float volume, float pitch, int repeat, int delay) { Objects.requireNonNull(plugin, "Cannot play repeating sound from null plugin"); Objects.requireNonNull(entity, "Cannot play repeating sound at null location"); Validate.isTrue(repeat > 0, "Cannot repeat playing sound " + repeat + " times"); Validate.isTrue(delay > 0, "Delay ticks must be at least 1"); - new BukkitRunnable() { + return new BukkitRunnable() { int repeating = repeat; @Override @@ -1372,47 +1608,16 @@ public enum XSound { }.runTaskTimer(plugin, 0, delay); } - /** - * Plays an instrument's notes in an ascending form. - * This method is not really relevant to this utility class, but a nice feature. - * - * @param plugin the plugin handling schedulers. - * @param player the player to play the note from. - * @param playTo the entity to play the note to. - * @param instrument the instrument. - * @param ascendLevel the ascend level of notes. Can only be positive and not higher than 7 - * @param delay the delay between each play. - * @since 2.0.0 - */ - public void playAscendingNote(@Nonnull JavaPlugin plugin, @Nonnull Player player, @Nonnull Entity playTo, Instrument instrument, int ascendLevel, int delay) { - Objects.requireNonNull(player, "Cannot play note from null player"); - Objects.requireNonNull(playTo, "Cannot play note to null entity"); - - Validate.isTrue(ascendLevel > 0, "Note ascend level cannot be lower than 1"); - Validate.isTrue(ascendLevel <= 7, "Note ascend level cannot be greater than 7"); - Validate.isTrue(delay > 0, "Delay ticks must be at least 1"); - - new BukkitRunnable() { - int repeating = ascendLevel; - - @Override - public void run() { - player.playNote(playTo.getLocation(), instrument, Note.natural(1, Note.Tone.values()[ascendLevel - repeating])); - if (repeating-- == 0) cancel(); - } - }.runTaskTimerAsynchronously(plugin, 0, delay); - } - /** * Stops playing the specified sound from the player. * * @param player the player to stop playing the sound to. + * * @see #stopMusic(Player) * @since 2.0.0 */ public void stopSound(@Nonnull Player player) { Objects.requireNonNull(player, "Cannot stop playing sound from null player"); - Sound sound = this.parseSound(); if (sound != null) player.stopSound(sound); } @@ -1421,10 +1626,11 @@ public enum XSound { * Plays a normal sound to an entity. * * @param entity the entity to play the sound to. + * * @since 1.0.0 */ public void play(@Nonnull Entity entity) { - play(entity, 1.0f, 1.0f); + play(entity, DEFAULT_VOLUME, DEFAULT_PITCH); } /** @@ -1433,14 +1639,14 @@ public enum XSound { * @param entity the entity to play the sound to. * @param volume the volume of the sound, 1 is normal. * @param pitch the pitch of the sound, 0 is normal. + * * @since 1.0.0 */ public void play(@Nonnull Entity entity, float volume, float pitch) { Objects.requireNonNull(entity, "Cannot play sound to a null entity"); if (entity instanceof Player) { Sound sound = this.parseSound(); - if (sound == null) return; - ((Player) entity).playSound(entity.getLocation(), sound, volume, pitch); + if (sound != null) ((Player) entity).playSound(entity.getLocation(), sound, volume, pitch); } else { play(entity.getLocation(), volume, pitch); } @@ -1450,10 +1656,11 @@ public enum XSound { * Plays a normal sound in a location. * * @param location the location to play the sound in. + * * @since 2.0.0 */ public void play(@Nonnull Location location) { - play(location, 1.0f, 1.0f); + play(location, DEFAULT_VOLUME, DEFAULT_PITCH); } /** @@ -1462,13 +1669,37 @@ public enum XSound { * @param location the location to play this sound. * @param volume the volume of the sound, 1 is normal. * @param pitch the pitch of the sound, 0 is normal. + * * @since 2.0.0 */ public void play(@Nonnull Location location, float volume, float pitch) { Objects.requireNonNull(location, "Cannot play sound to null location"); Sound sound = this.parseSound(); - if (sound == null) return; - location.getWorld().playSound(location, sound, volume, pitch); + if (sound != null) location.getWorld().playSound(location, sound, volume, pitch); + } + + /** + * Used for datas that need to be accessed during enum initilization. + * + * @since 5.0.0 + */ + private static final class Data { + /** + * Just for enum initialization. + * + * @since 5.0.0 + */ + private static final WeakHashMap BUKKIT_NAMES = new WeakHashMap<>(); + /** + * We don't want to use {@link Enums#getIfPresent(Class, String)} to avoid a few checks. + * + * @since 3.1.0 + */ + private static final Map NAMES = new HashMap<>(); + + static { + for (Sound sound : Sound.values()) BUKKIT_NAMES.put(sound.name(), sound); + } } /** @@ -1477,15 +1708,15 @@ public enum XSound { * @since 3.0.0 */ public static class Record { - public final Sound sound; - public final Player player; - public final Location location; + @Nonnull public final XSound sound; public final float volume; public final float pitch; - public final boolean playAtLocation; + public boolean playAtLocation; + @Nullable public Player player; + @Nullable public Location location; - public Record(Sound sound, Player player, Location location, float volume, float pitch, boolean playAtLocation) { - this.sound = sound; + public Record(@Nonnull XSound sound, @Nullable Player player, @Nullable Location location, float volume, float pitch, boolean playAtLocation) { + this.sound = Objects.requireNonNull(sound, "Sound cannot be null"); this.player = player; this.location = location; this.volume = volume; @@ -1493,12 +1724,29 @@ public enum XSound { this.playAtLocation = playAtLocation; } + public Record forPlayer(@Nullable Player player) { + this.player = player; + return this; + } + + public Record atLocation(@Nullable Location location) { + this.location = location; + return this; + } + + public Record forPlayerAtLocation(@Nullable Player player, @Nullable Location location) { + this.player = player; + this.location = location; + return this; + } + /** * Plays the sound with the given options and updating the players location. * * @since 3.0.0 */ public void play() { + if (player == null && location == null) throw new IllegalStateException("Cannot play sound when there is no location available"); play(player == null ? location : player.getLocation()); } @@ -1506,11 +1754,13 @@ public enum XSound { * Plays the sound with the updated location. * * @param updatedLocation the upated location. + * * @since 3.0.0 */ - public void play(Location updatedLocation) { - if (playAtLocation) location.getWorld().playSound(updatedLocation, sound, volume, pitch); - else if (player.isOnline()) player.playSound(updatedLocation, sound, volume, pitch); + public void play(@Nonnull Location updatedLocation) { + Objects.requireNonNull(updatedLocation, "Cannot play sound at null location"); + if (playAtLocation || player == null) location.getWorld().playSound(updatedLocation, sound.parseSound(), volume, pitch); + else player.playSound(updatedLocation, sound.parseSound(), volume, pitch); } } -} \ No newline at end of file +} diff --git a/modern/src/main/java/net/islandearth/rpgregions/api/integrations/rpgregions/RPGRegionsIntegration.java b/modern/src/main/java/net/islandearth/rpgregions/api/integrations/rpgregions/RPGRegionsIntegration.java deleted file mode 100644 index 585d917..0000000 --- a/modern/src/main/java/net/islandearth/rpgregions/api/integrations/rpgregions/RPGRegionsIntegration.java +++ /dev/null @@ -1,47 +0,0 @@ -package net.islandearth.rpgregions.api.integrations.rpgregions; - -import net.islandearth.rpgregions.api.integrations.IntegrationManager; -import net.islandearth.rpgregions.managers.data.region.ConfiguredRegion; -import org.bukkit.Location; -import org.bukkit.World; -import org.bukkit.event.player.PlayerMoveEvent; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; -import java.util.Set; - -public class RPGRegionsIntegration implements IntegrationManager { - - @Override - public boolean isInRegion(Location location) { - return false; - } - - @Override - public void handleMove(PlayerMoveEvent pme) { - - } - - @Override - public Optional getPrioritisedRegion(Location location) { - return null; - } - - @Override - public boolean exists(World location, String region) { - return false; - } - - @Override - public Set getAllRegionNames(World world) { - return null; - } - - @Override - public @NotNull List getBoundingBoxPoints(Location regionLocation, @Nullable String regionId) { - return new ArrayList<>(); // TODO - } -} diff --git a/rpgregions/src/main/java/net/islandearth/rpgregions/RPGRegions.java b/rpgregions/src/main/java/net/islandearth/rpgregions/RPGRegions.java index 1e0c760..6b8cb33 100644 --- a/rpgregions/src/main/java/net/islandearth/rpgregions/RPGRegions.java +++ b/rpgregions/src/main/java/net/islandearth/rpgregions/RPGRegions.java @@ -12,6 +12,8 @@ import net.islandearth.languagy.api.language.LanguagyPluginHook; import net.islandearth.languagy.api.language.Translator; import net.islandearth.rpgregions.api.IRPGRegionsAPI; import net.islandearth.rpgregions.api.RPGRegionsAPI; +import net.islandearth.rpgregions.api.integrations.rpgregions.RPGRegionsIntegration; +import net.islandearth.rpgregions.api.integrations.rpgregions.region.RPGRegionsRegion; import net.islandearth.rpgregions.commands.DiscoveriesCommand; import net.islandearth.rpgregions.commands.RPGRegionsCommand; import net.islandearth.rpgregions.commands.RPGRegionsDebugCommand; @@ -53,7 +55,6 @@ import net.islandearth.rpgregions.rewards.RegionRewardRegistry; import net.islandearth.rpgregions.rewards.TeleportReward; import net.islandearth.rpgregions.tasks.DynmapTask; import net.islandearth.rpgregions.translation.Translations; -import net.islandearth.rpgregions.utils.XSound; import org.bstats.bukkit.Metrics; import org.bstats.charts.SimplePie; import org.bstats.charts.SingleLineChart; @@ -61,7 +62,6 @@ import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.OfflinePlayer; -import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; import org.bukkit.plugin.PluginManager; @@ -72,14 +72,19 @@ import org.jetbrains.annotations.NotNull; import java.io.File; import java.io.IOException; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; +import java.util.Optional; import java.util.concurrent.ExecutionException; import java.util.logging.Level; public final class RPGRegions extends JavaPlugin implements IRPGRegionsAPI, LanguagyPluginHook { private RPGRegionsManagers managers; + private PaperCommandManager commandManager; + + public PaperCommandManager getCommandManager() { + return commandManager; + } @Override public Translator getTranslator() { @@ -94,6 +99,7 @@ public final class RPGRegions extends JavaPlugin implements IRPGRegionsAPI, Lang RPGRegionsAPI.setAPI(this); this.createConfig(); this.generateLang(); + this.commandManager = new PaperCommandManager(this); try { this.managers = new RPGRegionsManagers(this); } catch (ReflectiveOperationException | IOException | CouldNotStartException e) { @@ -109,6 +115,11 @@ public final class RPGRegions extends JavaPlugin implements IRPGRegionsAPI, Lang this.hook(this); this.registerTasks(); this.registerMetrics(); + + // Tell integration to enable + if (managers.getIntegrationManager() instanceof RPGRegionsIntegration rpgRegionsIntegration) { + rpgRegionsIntegration.onEnable(); + } } @Override @@ -127,6 +138,11 @@ public final class RPGRegions extends JavaPlugin implements IRPGRegionsAPI, Lang } }); + // Tell integration to save + if (managers.getIntegrationManager() instanceof RPGRegionsIntegration rpgRegionsIntegration) { + rpgRegionsIntegration.onDisable(); + } + // Save all region configs managers.getRegionsCache().getConfiguredRegions().forEach((id, region) -> region.save(this)); } @@ -145,94 +161,7 @@ public final class RPGRegions extends JavaPlugin implements IRPGRegionsAPI, Lang } private void createConfig() { - // TODO move this logic to another class - it's getting too long! - FileConfiguration config = this.getConfig(); - String header; - String eol = System.getProperty("line.separator"); - header = "This is the config for RPGRegions." + eol; - header += "------ Useful information ------" + eol; - header += "Documentation can be found at https://fortitude.islandearth.net" + eol; - header += "Sounds can be found at https://hub.spigotmc.org/javadocs/spigot/org/bukkit/Sound.html" + eol; - header += "------ Support ------" + eol; - header += "Found a bug? Create an issue at https://gitlab.com/SamB440/rpgregions-2/issues" + eol; - header += "Need help? Join our discord at https://discord.gg/fh62mxU" + eol; - header += "------ Setting explanation ------" + eol; - header += "See wiki for more detailed information." + eol; - header += " search-offline-players: Tab complete will list offline players where possible. This can cause lag with lots of offline players due to Bukkit loading all of their data." + eol; - header += " worlds.forceload: Forcefully load worlds on startup to ensure RPGRegions recognises them. ONLY ENABLE IF YOU KNOW WHAT YOU ARE DOING!" + eol; - header += " settings.metrics.send_custom_info: Disable if experiencing bStats lag spikes."; - config.options().header(header); - config.addDefault("settings.metrics.send_custom_info", true); - config.addDefault("settings.dev.debug", false); - config.addDefault("settings.integration.name", getIntegration()); - config.addDefault("settings.external.dynmap", true); - config.addDefault("settings.storage.mode", "file"); - config.addDefault("settings.sql.host", "localhost"); - config.addDefault("settings.sql.port", 3306); - config.addDefault("settings.sql.db", "RPGRegions"); - config.addDefault("settings.sql.user", "user"); - config.addDefault("settings.sql.pass", "pass"); - config.addDefault("settings.server.tabcomplete.search-offline-players", true); - config.addDefault("settings.server.discoveries.discovered.name-colour", "GREEN"); - config.addDefault("settings.server.discoveries.undiscovered.name-colour", "RED"); - config.addDefault("settings.server.discoveries.date.format", "dd-MM-yyyy HH:mm:ss"); - config.addDefault("settings.server.discoveries.discovered.title.fadein", 20); - config.addDefault("settings.server.discoveries.discovered.title.stay", 60); - config.addDefault("settings.server.discoveries.discovered.title.fadeout", 20); - config.addDefault("settings.server.discoveries.discovered.sound.name", XSound.UI_TOAST_CHALLENGE_COMPLETE.name()); - config.addDefault("settings.server.discoveries.discovered.sound.pitch", 1); - config.addDefault("settings.server.discoveries.discovered.title.animation_speed", 20); - config.addDefault("settings.server.discoveries.discovered.title.cooldown", 0); - config.addDefault("settings.server.gui.default_region_icon", Material.TOTEM_OF_UNDYING.name()); - config.addDefault("settings.server.gui.general.rows", 6); - config.addDefault("settings.server.gui.back.posX", 0); - config.addDefault("settings.server.gui.back.posY", 5); - config.addDefault("settings.server.gui.back.length", 1); - config.addDefault("settings.server.gui.back.height", 1); - config.addDefault("settings.server.gui.forward.posX", 8); - config.addDefault("settings.server.gui.forward.posY", 5); - config.addDefault("settings.server.gui.forward.length", 1); - config.addDefault("settings.server.gui.forward.height", 1); - config.addDefault("settings.server.gui.exit.posX", 4); - config.addDefault("settings.server.gui.exit.posY", 5); - config.addDefault("settings.server.gui.exit.length", 1); - config.addDefault("settings.server.gui.exit.height", 1); - config.addDefault("settings.server.gui.exit.command", ""); - config.addDefault("settings.server.gui.exit.show", true); - config.addDefault("settings.server.gui.pane.posX", 1); - config.addDefault("settings.server.gui.pane.posY", 1); - config.addDefault("settings.server.gui.pane.length", 7); - config.addDefault("settings.server.gui.pane.height", 4); - config.addDefault("settings.server.gui.outlinePane.posX", 0); - config.addDefault("settings.server.gui.outlinePane.posY", 0); - config.addDefault("settings.server.gui.outlinePane.length", 9); - config.addDefault("settings.server.gui.outlinePane.height", 6); - config.addDefault("settings.server.gui.outlinePane.show", true); - config.addDefault("settings.server.gui.outlinePane.mask", Arrays.asList( - "111111111", - "100000001", - "100000001", - "100000001", - "100000001", - "111111111")); - config.addDefault("settings.server.gui.innerPane.posX", 1); - config.addDefault("settings.server.gui.innerPane.posY", 1); - config.addDefault("settings.server.gui.innerPane.length", 7); - config.addDefault("settings.server.gui.innerPane.height", 4); - config.addDefault("settings.server.gui.innerPane.show", true); - config.addDefault("settings.server.gui.innerPane.mask", Arrays.asList( - "1111111", - "1111111", - "1111111", - "1111111")); - config.addDefault("settings.server.gui.forward.forward", Material.ARROW.name()); - config.addDefault("settings.server.gui.back.back", Material.ARROW.name()); - config.addDefault("settings.server.gui.exit.exit", Material.BARRIER.name()); - config.addDefault("settings.server.gui.outlinePane.outlinePane", Material.GRAY_STAINED_GLASS_PANE.name()); - config.addDefault("settings.server.gui.innerPane.innerPane", Material.WHITE_STAINED_GLASS_PANE.name()); - config.addDefault("settings.server.worlds.forceload", false); - config.options().copyDefaults(true); - saveConfig(); + saveDefaultConfig(); // Moved to config.yml } private void registerListeners() { @@ -244,11 +173,12 @@ public final class RPGRegions extends JavaPlugin implements IRPGRegionsAPI, Lang } private void registerCommands() { - PaperCommandManager manager = new PaperCommandManager(this); + final PaperCommandManager manager = commandManager; manager.enableUnstableAPI("help"); manager.getCommandCompletions().registerAsyncCompletion("regions", context -> ImmutableList.copyOf(getManagers().getRegionsCache().getConfiguredRegions().keySet())); manager.getCommandCompletions().registerAsyncCompletion("integration-regions", context -> ImmutableList.copyOf(this.getManagers().getIntegrationManager().getAllRegionNames(context.getPlayer().getWorld()))); manager.getCommandCompletions().registerAsyncCompletion("async", context -> ImmutableList.of("--async")); + manager.getCommandCompletions().registerAsyncCompletion("region-types", context -> ImmutableList.of("Cuboid", "Poly")); manager.getCommandCompletions().registerAsyncCompletion("offline-players", context -> { List players = new ArrayList<>(); if (!getConfig().getBoolean("settings.server.tabcomplete.search-offline-players")) { @@ -338,6 +268,7 @@ public final class RPGRegions extends JavaPlugin implements IRPGRegionsAPI, Lang .registerTypeAdapter(DiscoveryReward.class, new AbstractAdapter(null)) .registerTypeAdapter(RegionEffect.class, new AbstractAdapter(null)) .registerTypeAdapter(RegionRequirement.class, new AbstractAdapter(null)) + .registerTypeAdapter(RPGRegionsRegion.class, new AbstractAdapter(null)) .registerTypeHierarchyAdapter(PotionEffect.class, new PotionEffectAdapter(this)) .registerTypeHierarchyAdapter(ItemStack.class, new ItemStackAdapter()) .registerTypeHierarchyAdapter(Location.class, new LocationAdapter()) @@ -363,7 +294,7 @@ public final class RPGRegions extends JavaPlugin implements IRPGRegionsAPI, Lang } else if (Bukkit.getPluginManager().getPlugin("UltraRegions") != null) { return "UltraRegions"; } - return "WorldGuard"; + return "RPGRegions"; } private void registerTasks() { @@ -403,7 +334,7 @@ public final class RPGRegions extends JavaPlugin implements IRPGRegionsAPI, Lang @Override public void debug(String debug) { - this.debug(debug, Level.INFO); + if (debug()) this.debug(debug, Level.INFO); } public void debug(String debug, Level level) { diff --git a/rpgregions/src/main/java/net/islandearth/rpgregions/api/integrations/rpgregions/RPGRegionsIntegration.java b/rpgregions/src/main/java/net/islandearth/rpgregions/api/integrations/rpgregions/RPGRegionsIntegration.java new file mode 100644 index 0000000..e494042 --- /dev/null +++ b/rpgregions/src/main/java/net/islandearth/rpgregions/api/integrations/rpgregions/RPGRegionsIntegration.java @@ -0,0 +1,199 @@ +package net.islandearth.rpgregions.api.integrations.rpgregions; + +import co.aikar.commands.InvalidCommandArgument; +import com.google.gson.Gson; +import net.islandearth.rpgregions.RPGRegions; +import net.islandearth.rpgregions.api.IRPGRegionsAPI; +import net.islandearth.rpgregions.api.events.RegionsEnterEvent; +import net.islandearth.rpgregions.api.integrations.rpgregions.region.RPGRegionsRegion; +import net.islandearth.rpgregions.api.integrations.IntegrationManager; +import net.islandearth.rpgregions.commands.RPGRegionsIntegrationCommand; +import net.islandearth.rpgregions.managers.data.region.ConfiguredRegion; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.entity.Player; +import org.bukkit.event.player.PlayerMoveEvent; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; +import java.io.Reader; +import java.io.Writer; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; + +public class RPGRegionsIntegration implements IntegrationManager { + + private final IRPGRegionsAPI plugin; + private final Map regions; + + public RPGRegionsIntegration(IRPGRegionsAPI plugin) { + this.plugin = plugin; + this.regions = new HashMap<>(); + if (plugin instanceof RPGRegions rpgRegions) { + rpgRegions.getCommandManager().getCommandContexts().registerContext(RPGRegionsRegion.class, context -> { + String id = context.popFirstArg(); + if (rpgRegions.getManagers().getIntegrationManager() instanceof RPGRegionsIntegration rpgRegionsIntegration) { + Optional region = rpgRegionsIntegration.getRegion(id); + if (region.isPresent()) { + return region.get(); + } + } + throw new InvalidCommandArgument("Could not find a region with that id."); + }); + rpgRegions.getCommandManager().registerCommand(new RPGRegionsIntegrationCommand(rpgRegions)); + } + plugin.getLogger().info("RPGRegions region integration has been enabled."); + } + + /* + * API METHODS + */ + + public Set getRegions(final Location location) { + List foundRegions = new ArrayList<>(); + for (RPGRegionsRegion region : regions.values()) { + if (region.isWithinBounds(location)) foundRegions.add(region); + } + return Set.copyOf(foundRegions); + } + + public Optional getRegion(final String name) { + return Optional.ofNullable(regions.get(name)); + } + + public void addRegion(final RPGRegionsRegion region) { + regions.put(region.getName(), region); + } + + public void removeRegion(final RPGRegionsRegion region) { + this.removeRegion(region.getName()); + } + + public void removeRegion(final String name) { + regions.remove(name); + } + + /* + * OVERRIDES + */ + + @Override + public boolean isInRegion(Location location) { + for (RPGRegionsRegion region : regions.values()) { + if (region.isWithinBounds(location)) { + return true; + } + } + return false; + } + + @Override + public void handleMove(PlayerMoveEvent pme) { + if (pme.getTo() == null) return; + plugin.debug("Handling movement"); + Player player = pme.getPlayer(); + int oldX = pme.getFrom().getBlockX(); + int oldY = pme.getFrom().getBlockY(); + int oldZ = pme.getFrom().getBlockZ(); + int x = pme.getTo().getBlockX(); + int y = pme.getTo().getBlockY(); + int z = pme.getTo().getBlockZ(); + Set oldRegions = this.getRegions(new Location(player.getWorld(), oldX, oldY, oldZ)); + Set regions = this.getRegions(new Location(player.getWorld(), x, y, z)); + + Optional configuredRegion = getPrioritisedRegion(pme.getTo()); + configuredRegion.ifPresent(prioritisedRegion -> { + plugin.debug("Priority region found"); + plugin.debug("Old: " + oldRegions); + plugin.debug("New: " + regions); + List stringRegions = new ArrayList<>(); + regions.forEach(region -> { + if (!prioritisedRegion.getId().equals(region.getName()) + && checkRequirements(pme, region.getName())) stringRegions.add(region.getName()); + }); + + if (checkRequirements(pme, prioritisedRegion.getId())) { + plugin.debug("Requirements passed, calling"); + stringRegions.add(0, prioritisedRegion.getId()); + Bukkit.getPluginManager().callEvent(new RegionsEnterEvent(player, stringRegions, !oldRegions.equals(regions))); + } + }); + } + + @Override + public Optional getPrioritisedRegion(Location location) { + RPGRegionsRegion highest = null; + for (String key : regions.keySet()) { + final RPGRegionsRegion region = regions.get(key); + if (region.isWithinBounds(location) && (highest == null || region.getPriority() > highest.getPriority())) { + highest = region; + } + } + return highest == null ? Optional.empty() : plugin.getManagers().getRegionsCache().getConfiguredRegion(highest.getName()); + } + + @Override + public boolean exists(World location, String region) { + return regions.containsKey(region); + } + + @Override + public Set getAllRegionNames(World world) { + return regions.keySet(); + } + + @Override + public @NotNull List getBoundingBoxPoints(Location regionLocation, @Nullable String regionId) { + for (RPGRegionsRegion region : regions.values()) { + if (region.isWithinBounds(regionLocation)) { + return region.getPoints(); + } + } + return new ArrayList<>(); + } + + public void onEnable() { + File regionsDir = new File(plugin.getDataFolder() + File.separator + "integration" + File.separator + "regions"); + if (!regionsDir.exists()) regionsDir.mkdirs(); + for (File file : regionsDir.listFiles()) { + try (Reader reader = new FileReader(file)) { + Gson gson = plugin.getGson(); + RPGRegionsRegion region = gson.fromJson(reader, RPGRegionsRegion.class); + if (region == null) continue; + regions.put(region.getName(), region); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + public void onDisable() { + save(); + } + + public void save() { + File regionsDir = new File(plugin.getDataFolder() + File.separator + "integration" + File.separator + "regions"); + if (!regionsDir.exists()) regionsDir.mkdirs(); + + regions.forEach((name, region) -> { + File file = new File(regionsDir + File.separator + name + ".json"); + try (Writer writer = new FileWriter(file)) { + Gson gson = plugin.getGson(); + gson.toJson(region, RPGRegionsRegion.class, writer); + writer.flush(); + } catch (IOException e) { + e.printStackTrace(); + } + }); + } +} diff --git a/rpgregions/src/main/java/net/islandearth/rpgregions/api/integrations/rpgregions/region/CuboidRegion.java b/rpgregions/src/main/java/net/islandearth/rpgregions/api/integrations/rpgregions/region/CuboidRegion.java new file mode 100644 index 0000000..7a60046 --- /dev/null +++ b/rpgregions/src/main/java/net/islandearth/rpgregions/api/integrations/rpgregions/region/CuboidRegion.java @@ -0,0 +1,16 @@ +package net.islandearth.rpgregions.api.integrations.rpgregions.region; + +import org.bukkit.Location; + +public class CuboidRegion extends RPGRegionsRegion { + + public CuboidRegion(final String name) { + super(name); + } + + @Override + public boolean isWithinBounds(Location location) { + if (getPoints().size() < 2) return false; + return location.toVector().isInAABB(getPoints().get(0).toVector(), getPoints().get(1).toVector()); + } +} diff --git a/rpgregions/src/main/java/net/islandearth/rpgregions/api/integrations/rpgregions/region/PolyRegion.java b/rpgregions/src/main/java/net/islandearth/rpgregions/api/integrations/rpgregions/region/PolyRegion.java new file mode 100644 index 0000000..9ca470d --- /dev/null +++ b/rpgregions/src/main/java/net/islandearth/rpgregions/api/integrations/rpgregions/region/PolyRegion.java @@ -0,0 +1,27 @@ +package net.islandearth.rpgregions.api.integrations.rpgregions.region; + +import org.bukkit.Location; + +import java.awt.*; +import java.util.ArrayList; +import java.util.List; + +public class PolyRegion extends RPGRegionsRegion { + + public PolyRegion(final String name) { + super(name); + } + + @Override + public boolean isWithinBounds(Location location) { + if (getPoints().size() < 2) return false; + List xPoints = new ArrayList<>(); + List yPoints = new ArrayList<>(); + getPoints().forEach(point -> { + xPoints.add(point.getBlockX()); + yPoints.add(point.getBlockY()); + }); + Polygon polygon = new Polygon(xPoints.stream().mapToInt(Integer::intValue).toArray(), yPoints.stream().mapToInt(Integer::intValue).toArray(), xPoints.size()); + return polygon.contains(location.getX(), location.getZ()); + } +} diff --git a/rpgregions/src/main/java/net/islandearth/rpgregions/api/integrations/rpgregions/region/RPGRegionsRegion.java b/rpgregions/src/main/java/net/islandearth/rpgregions/api/integrations/rpgregions/region/RPGRegionsRegion.java new file mode 100644 index 0000000..909cf5c --- /dev/null +++ b/rpgregions/src/main/java/net/islandearth/rpgregions/api/integrations/rpgregions/region/RPGRegionsRegion.java @@ -0,0 +1,51 @@ +package net.islandearth.rpgregions.api.integrations.rpgregions.region; + +import com.google.common.collect.ImmutableList; +import org.bukkit.Location; +import org.bukkit.entity.Player; + +import java.util.ArrayList; +import java.util.List; + +public abstract class RPGRegionsRegion { + + private final String name; + private final List points; + private int priority; + + public RPGRegionsRegion(final String name) { + this.name = name; + this.points = new ArrayList<>(); + this.priority = 1; + } + + public String getName() { + return name; + } + + public int getPriority() { + return priority; + } + + public void setPriority(int priority) { + this.priority = priority; + } + + public ImmutableList getPoints() { + return ImmutableList.copyOf(points); + } + + public void addPoint(final Location location) { + this.points.add(location); + } + + public void removePoint(final Location location) { + this.points.remove(location); + } + + public boolean isWithinBounds(final Player player) { + return this.isWithinBounds(player.getLocation()); + } + + public abstract boolean isWithinBounds(final Location location); +} diff --git a/rpgregions/src/main/java/net/islandearth/rpgregions/commands/RPGRegionsIntegrationCommand.java b/rpgregions/src/main/java/net/islandearth/rpgregions/commands/RPGRegionsIntegrationCommand.java new file mode 100644 index 0000000..ea01a32 --- /dev/null +++ b/rpgregions/src/main/java/net/islandearth/rpgregions/commands/RPGRegionsIntegrationCommand.java @@ -0,0 +1,110 @@ +package net.islandearth.rpgregions.commands; + +import co.aikar.commands.BaseCommand; +import co.aikar.commands.CommandHelp; +import co.aikar.commands.annotation.CommandAlias; +import co.aikar.commands.annotation.CommandCompletion; +import co.aikar.commands.annotation.Default; +import co.aikar.commands.annotation.HelpCommand; +import co.aikar.commands.annotation.Subcommand; +import net.islandearth.rpgregions.RPGRegions; +import net.islandearth.rpgregions.api.integrations.rpgregions.RPGRegionsIntegration; +import net.islandearth.rpgregions.api.integrations.rpgregions.region.CuboidRegion; +import net.islandearth.rpgregions.api.integrations.rpgregions.region.PolyRegion; +import net.islandearth.rpgregions.api.integrations.rpgregions.region.RPGRegionsRegion; +import org.bukkit.ChatColor; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import java.util.Locale; +import java.util.Optional; + +@CommandAlias("rpgri|rpgrintegration") +public class RPGRegionsIntegrationCommand extends BaseCommand { + + private final RPGRegions plugin; + + public RPGRegionsIntegrationCommand(final RPGRegions plugin) { + this.plugin = plugin; + } + + @Default + public void onDefault(CommandSender sender) { + sender.sendMessage(ChatColor.GREEN + "RPGRegions region integration is enabled. Type /rpgri help for help."); + } + + @HelpCommand + @Subcommand("help") + public void onHelp(final CommandHelp commandHelp) { + commandHelp.showHelp(); + } + + @Subcommand("list") + public void onList(final CommandSender sender) { + RPGRegionsIntegration integration = (RPGRegionsIntegration) plugin.getManagers().getIntegrationManager(); + integration.getAllRegionNames(null).forEach(name -> sender.sendMessage(ChatColor.GREEN + "- " + name)); + } + + @Subcommand("info") + @CommandCompletion("@regions") + public void onInfo(final CommandSender sender, final String name) { + RPGRegionsIntegration integration = (RPGRegionsIntegration) plugin.getManagers().getIntegrationManager(); + Optional region = integration.getRegion(name); + if (region.isPresent()) { + sender.sendMessage(ChatColor.GREEN + "Name: " + ChatColor.WHITE + region.get().getName()); + sender.sendMessage(ChatColor.GREEN + "Priority: " + ChatColor.WHITE + region.get().getPriority()); + sender.sendMessage(ChatColor.GREEN + "Points for " + region.get().getName() + ":"); + region.get().getPoints().forEach(point -> sender.sendMessage(" " + point.toString())); + return; + } + sender.sendMessage(ChatColor.RED + "Region " + name + " does not exist!"); + } + + @Subcommand("save") + public void onSave(final CommandSender sender) { + RPGRegionsIntegration integration = (RPGRegionsIntegration) plugin.getManagers().getIntegrationManager(); + integration.save(); + sender.sendMessage(ChatColor.GREEN + "Regions saved."); + } + + @Subcommand("create") + @CommandCompletion("@regions @region-types") + public void onCreate(final CommandSender sender, final String name, final String regionType) { + RPGRegionsRegion region = switch (regionType.toLowerCase(Locale.ENGLISH)) { + case "cuboid" -> new CuboidRegion(name); + case "poly" -> new PolyRegion(name); + default -> null; + }; + + if (region == null) { + sender.sendMessage(ChatColor.RED + "A region of the type " + regionType + " cannot be found!"); + return; + } + + RPGRegionsIntegration integration = (RPGRegionsIntegration) plugin.getManagers().getIntegrationManager(); + integration.addRegion(region); + sender.sendMessage(ChatColor.GREEN + "Created region " + name + "."); + } + + @Subcommand("delete") + @CommandCompletion("@regions") + public void onDelete(final CommandSender sender, final RPGRegionsRegion region) { + RPGRegionsIntegration integration = (RPGRegionsIntegration) plugin.getManagers().getIntegrationManager(); + integration.removeRegion(region); + sender.sendMessage(ChatColor.GREEN + "Region " + region.getName() + " has been removed."); + } + + @Subcommand("addpos") + @CommandCompletion("@regions") + public void onAddPos(final Player player, final RPGRegionsRegion region) { + region.addPoint(player.getLocation()); + player.sendMessage(ChatColor.GREEN + "Added point to " + region.getName() + "."); + } + + @Subcommand("setpriority") + @CommandCompletion("@regions @range:20") + public void onSetPriority(final Player player, final RPGRegionsRegion region, final int priority) { + region.setPriority(priority); + player.sendMessage(ChatColor.GREEN + "Set priority of " + region.getName() + " to " + priority + "."); + } +} diff --git a/rpgregions/src/main/java/net/islandearth/rpgregions/gson/AbstractAdapter.java b/rpgregions/src/main/java/net/islandearth/rpgregions/gson/AbstractAdapter.java index d176119..839282d 100644 --- a/rpgregions/src/main/java/net/islandearth/rpgregions/gson/AbstractAdapter.java +++ b/rpgregions/src/main/java/net/islandearth/rpgregions/gson/AbstractAdapter.java @@ -35,6 +35,7 @@ public class AbstractAdapter implements JsonSerializer, JsonDeserializer