├── .gitignore ├── API ├── src │ └── main │ │ └── java │ │ └── me │ │ └── metallicgoat │ │ └── tweaksaddon │ │ └── api │ │ ├── package-info.java │ │ ├── unsafe │ │ ├── package-info.java │ │ └── MBedwarsTweaksAPILayer.java │ │ ├── events │ │ ├── package-info.java │ │ ├── gentiers │ │ │ ├── package-info.java │ │ │ ├── GenTiersActionEvent.java │ │ │ ├── GenTiersScheduleEvent.java │ │ │ └── SuddenDeathDragonTargetEvent.java │ │ ├── PostConfigLoadEvent.java │ │ └── PreConfigsLoadEvent.java │ │ ├── gentiers │ │ ├── package-info.java │ │ ├── GenTierActionType.java │ │ ├── GenTierHandler.java │ │ ├── SuddenDeathDragon.java │ │ ├── GenTierLevel.java │ │ └── GenTierState.java │ │ └── GenTiersAPI.java └── pom.xml ├── MBedwarsTweaks ├── libs │ └── public │ │ ├── PrestigeAddonAPI-1.2.0.jar │ │ └── HotbarManager-1.0-SNAPSHOT.jar ├── src │ └── main │ │ ├── resources │ │ ├── messages.yml │ │ └── plugin.yml │ │ └── java │ │ └── me │ │ └── metallicgoat │ │ └── tweaksaddon │ │ ├── gentiers │ │ ├── handlers │ │ │ ├── BaseGenTierHandler.java │ │ │ ├── GameOverHandler.java │ │ │ ├── BedDestroyHandler.java │ │ │ ├── SpawnerUpgradeHandler.java │ │ │ └── SuddenDeathHandler.java │ │ └── dragons │ │ │ ├── SuddenDeathUpgrade.java │ │ │ └── DragonUtil.java │ │ ├── tweaks │ │ ├── playerlimitbypass │ │ │ ├── PlayerLimitBypassPaper.java │ │ │ └── PlayerLimitBypass.java │ │ ├── explosives │ │ │ ├── FireballThrowEffects.java │ │ │ ├── DisableFireballOutsideArena.java │ │ │ ├── FireballBlockBreakWhitelist.java │ │ │ ├── TNTIgniteCountdown.java │ │ │ ├── FireballUseCoolDown.java │ │ │ └── ExplosiveFallDamageMultiplier.java │ │ ├── advancedswords │ │ │ ├── BuyGroupTracker.java │ │ │ ├── AntiDrop.java │ │ │ ├── DegradingBuyGroups.java │ │ │ ├── ReplaceToolOnBuy.java │ │ │ ├── ReplaceSwordOnBuy.java │ │ │ ├── AntiChest.java │ │ │ ├── AlwaysSword.java │ │ │ └── ToolSwordHelper.java │ │ ├── messages │ │ │ ├── FinalKillSuffix.java │ │ │ ├── TeamEliminate.java │ │ │ ├── BuyMessage.java │ │ │ ├── CustomBedBreakMessage.java │ │ │ └── TopKillerMessage.java │ │ ├── misc │ │ │ ├── BlockArenaStats.java │ │ │ ├── PearlSoundBroadcast.java │ │ │ ├── PermanentEffects.java │ │ │ ├── EmptyContainers.java │ │ │ ├── HeightCap.java │ │ │ ├── PlaceBlocksOnBed.java │ │ │ ├── RemoveInvisOnDamage.java │ │ │ ├── LootDropAtEliminatedTeamBase.java │ │ │ ├── LockTeamChest.java │ │ │ └── WorldBorderResize.java │ │ ├── spawners │ │ │ ├── AFKSpawners.java │ │ │ ├── DisableEmptyGenerators.java │ │ │ └── SpawnerUpgrade.java │ │ ├── cosmetic │ │ │ ├── SpongeParticles.java │ │ │ ├── HealPoolParticles.java │ │ │ ├── InvisFootstepsParticles.java │ │ │ └── PlaceholderUpdating.java │ │ └── spectialitems │ │ │ ├── SpecialItemCooldown.java │ │ │ └── TrackerDistance.java │ │ ├── utils │ │ ├── Console.java │ │ ├── NMSClass.java │ │ ├── CachedArenaIdentifier.java │ │ ├── UpdateChecker.java │ │ └── Util.java │ │ ├── commands │ │ └── SpecialItemCommand.java │ │ ├── integration │ │ ├── DependType.java │ │ ├── DependencyLoader.java │ │ └── hooks │ │ │ └── PrestigesLevelOnExperienceBar.java │ │ ├── impl │ │ └── api │ │ │ └── ImplMBedwarsTweaksAPILayer.java │ │ ├── config │ │ ├── SwordsToolsConfig.java │ │ ├── ConfigLoader.java │ │ └── GenTiersConfig.java │ │ ├── MBedwarsTweaksPlugin.java │ │ └── MBedwarsTweaksAddon.java └── pom.xml ├── pom.xml ├── .github └── workflows │ └── maven.yml └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | # Project exclude paths 2 | /target/ 3 | /MBedwarsTweaks/libs/private 4 | /.idea/ 5 | MBedwarsTweaks.iml 6 | /MBedwarsTweaks/target/ 7 | /API/target/ -------------------------------------------------------------------------------- /API/src/main/java/me/metallicgoat/tweaksaddon/api/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * The root package of the MBedwarsTweaks API 3 | */ 4 | package me.metallicgoat.tweaksaddon.api; -------------------------------------------------------------------------------- /MBedwarsTweaks/libs/public/PrestigeAddonAPI-1.2.0.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MetallicGoat/MBedwarsTweaks/HEAD/MBedwarsTweaks/libs/public/PrestigeAddonAPI-1.2.0.jar -------------------------------------------------------------------------------- /MBedwarsTweaks/libs/public/HotbarManager-1.0-SNAPSHOT.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MetallicGoat/MBedwarsTweaks/HEAD/MBedwarsTweaks/libs/public/HotbarManager-1.0-SNAPSHOT.jar -------------------------------------------------------------------------------- /API/src/main/java/me/metallicgoat/tweaksaddon/api/unsafe/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Do not use classes in this package 3 | */ 4 | package me.metallicgoat.tweaksaddon.api.unsafe; -------------------------------------------------------------------------------- /API/src/main/java/me/metallicgoat/tweaksaddon/api/events/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Contains all events fired by MBedwarsTweaks 3 | */ 4 | package me.metallicgoat.tweaksaddon.api.events; -------------------------------------------------------------------------------- /API/src/main/java/me/metallicgoat/tweaksaddon/api/gentiers/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Classes relevant to the operation of the GenTiers system 3 | */ 4 | package me.metallicgoat.tweaksaddon.api.gentiers; -------------------------------------------------------------------------------- /API/src/main/java/me/metallicgoat/tweaksaddon/api/events/gentiers/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Contains all events related to the GenTiers system 3 | */ 4 | package me.metallicgoat.tweaksaddon.api.events.gentiers; -------------------------------------------------------------------------------- /MBedwarsTweaks/src/main/resources/messages.yml: -------------------------------------------------------------------------------- 1 | Tweaks_SuddenDeath_Upgrade_Name: "Sudden Death" 2 | Tweaks_SuddenDeath_Upgrade_Description: 3 | - "After all beds are destroyed" 4 | - "a dragon will spawn in to" 5 | - "help defend your team" -------------------------------------------------------------------------------- /MBedwarsTweaks/src/main/resources/plugin.yml: -------------------------------------------------------------------------------- 1 | name: MBedwarsTweaks 2 | version: 5.0.0-Beta2 3 | author: MetallicGoat 4 | main: me.metallicgoat.tweaksaddon.MBedwarsTweaksPlugin 5 | description: Adds some extra customizability to MBedwars 6 | api-version: 1.13 7 | depend: [ MBedwars ] 8 | softdepend: [ PlaceholderAPI, MBedwarsHotbarManager, PrestigeAddon ] -------------------------------------------------------------------------------- /MBedwarsTweaks/src/main/java/me/metallicgoat/tweaksaddon/gentiers/handlers/BaseGenTierHandler.java: -------------------------------------------------------------------------------- 1 | package me.metallicgoat.tweaksaddon.gentiers.handlers; 2 | 3 | import me.metallicgoat.tweaksaddon.MBedwarsTweaksPlugin; 4 | import me.metallicgoat.tweaksaddon.api.gentiers.GenTierHandler; 5 | import org.bukkit.plugin.Plugin; 6 | 7 | public abstract class BaseGenTierHandler extends GenTierHandler { 8 | 9 | @Override 10 | public Plugin getPlugin() { 11 | return MBedwarsTweaksPlugin.getInstance(); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 4.0.0 6 | me.metallicgoat.tweaksaddon 7 | MBedwarsTweaksParent 8 | 5.0.0-Beta2 9 | pom 10 | 11 | 12 | API 13 | MBedwarsTweaks 14 | 15 | -------------------------------------------------------------------------------- /.github/workflows/maven.yml: -------------------------------------------------------------------------------- 1 | name: Java CI with Maven 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: [ master ] 8 | 9 | jobs: 10 | build: 11 | name: Build with Maven 12 | runs-on: ubuntu-latest 13 | 14 | steps: 15 | - name: Checkout code 16 | uses: actions/checkout@v4 17 | 18 | - name: Set up JDK 11 19 | uses: actions/setup-java@v4 20 | with: 21 | java-version: '11' 22 | distribution: 'temurin' 23 | cache: maven 24 | 25 | - name: Build with Maven 26 | run: mvn -B package --file pom.xml 27 | -------------------------------------------------------------------------------- /MBedwarsTweaks/src/main/java/me/metallicgoat/tweaksaddon/tweaks/playerlimitbypass/PlayerLimitBypassPaper.java: -------------------------------------------------------------------------------- 1 | package me.metallicgoat.tweaksaddon.tweaks.playerlimitbypass; 2 | 3 | import io.papermc.paper.event.player.PlayerServerFullCheckEvent; 4 | import me.metallicgoat.tweaksaddon.config.MainConfig; 5 | import org.bukkit.event.EventHandler; 6 | import org.bukkit.event.Listener; 7 | 8 | public class PlayerLimitBypassPaper implements Listener { 9 | 10 | @EventHandler 11 | public void onServerFullCheck(PlayerServerFullCheckEvent event) { 12 | if (MainConfig.player_limit_bypass) { 13 | event.allow(true); 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /MBedwarsTweaks/src/main/java/me/metallicgoat/tweaksaddon/tweaks/playerlimitbypass/PlayerLimitBypass.java: -------------------------------------------------------------------------------- 1 | package me.metallicgoat.tweaksaddon.tweaks.playerlimitbypass; 2 | 3 | import me.metallicgoat.tweaksaddon.config.MainConfig; 4 | import org.bukkit.event.EventHandler; 5 | import org.bukkit.event.Listener; 6 | import org.bukkit.event.player.PlayerLoginEvent; 7 | 8 | public class PlayerLimitBypass implements Listener { 9 | 10 | @EventHandler 11 | public void onPlayerLoginEvent(PlayerLoginEvent event) { 12 | if (MainConfig.player_limit_bypass && event.getResult() == PlayerLoginEvent.Result.KICK_FULL) { 13 | event.allow(); 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /MBedwarsTweaks/src/main/java/me/metallicgoat/tweaksaddon/gentiers/handlers/GameOverHandler.java: -------------------------------------------------------------------------------- 1 | package me.metallicgoat.tweaksaddon.gentiers.handlers; 2 | 3 | import de.marcely.bedwars.api.arena.Arena; 4 | import me.metallicgoat.tweaksaddon.api.gentiers.GenTierActionType; 5 | import me.metallicgoat.tweaksaddon.api.gentiers.GenTierLevel; 6 | 7 | public class GameOverHandler extends BaseGenTierHandler { 8 | 9 | @Override 10 | public void run(GenTierLevel level, Arena arena) { 11 | 12 | } 13 | 14 | @Override 15 | public String getId() { 16 | return GenTierActionType.GAME_OVER.getDefaultHandlerId(); 17 | } 18 | 19 | @Override 20 | public GenTierActionType getActionType() { 21 | return GenTierActionType.GAME_OVER; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /MBedwarsTweaks/src/main/java/me/metallicgoat/tweaksaddon/tweaks/explosives/FireballThrowEffects.java: -------------------------------------------------------------------------------- 1 | package me.metallicgoat.tweaksaddon.tweaks.explosives; 2 | 3 | import de.marcely.bedwars.api.event.player.PlayerUseSpecialItemEvent; 4 | import me.metallicgoat.tweaksaddon.config.MainConfig; 5 | import org.bukkit.event.EventHandler; 6 | import org.bukkit.event.Listener; 7 | 8 | public class FireballThrowEffects implements Listener { 9 | 10 | @EventHandler 11 | public void onPlayerUseSpecialItem(PlayerUseSpecialItemEvent event) { 12 | if (!MainConfig.fireball_throw_effects_enabled || !event.getSpecialItem().getId().equalsIgnoreCase("Fireball")) 13 | return; 14 | 15 | MainConfig.fireball_throw_effects.forEach(potionEffect -> event.getPlayer().addPotionEffect(potionEffect)); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /MBedwarsTweaks/src/main/java/me/metallicgoat/tweaksaddon/tweaks/explosives/DisableFireballOutsideArena.java: -------------------------------------------------------------------------------- 1 | package me.metallicgoat.tweaksaddon.tweaks.explosives; 2 | 3 | import de.marcely.bedwars.api.BedwarsAPI; 4 | import de.marcely.bedwars.api.arena.Arena; 5 | import org.bukkit.entity.Player; 6 | import org.bukkit.event.EventHandler; 7 | import org.bukkit.event.Listener; 8 | import org.bukkit.event.entity.ProjectileHitEvent; 9 | import org.bukkit.projectiles.ProjectileSource; 10 | 11 | public class DisableFireballOutsideArena implements Listener { 12 | 13 | // TODO config? 14 | @EventHandler 15 | public void onImpact(ProjectileHitEvent event) { 16 | final ProjectileSource shooter = event.getEntity().getShooter(); 17 | 18 | if (shooter instanceof Player) { 19 | final Player player = (Player) shooter; 20 | final Arena arena = BedwarsAPI.getGameAPI().getArenaByPlayer(player); 21 | 22 | if (arena != null && !arena.isInside(event.getEntity().getLocation())) { 23 | event.getEntity().remove(); 24 | } 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /MBedwarsTweaks/src/main/java/me/metallicgoat/tweaksaddon/tweaks/explosives/FireballBlockBreakWhitelist.java: -------------------------------------------------------------------------------- 1 | package me.metallicgoat.tweaksaddon.tweaks.explosives; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | import me.metallicgoat.tweaksaddon.config.MainConfig; 6 | import org.bukkit.block.Block; 7 | import org.bukkit.entity.EntityType; 8 | import org.bukkit.event.EventHandler; 9 | import org.bukkit.event.Listener; 10 | import org.bukkit.event.entity.EntityExplodeEvent; 11 | 12 | public class FireballBlockBreakWhitelist implements Listener { 13 | 14 | @EventHandler 15 | public void onEntityExplode(EntityExplodeEvent event) { 16 | if (!MainConfig.fireball_whitelist_enabled || event.isCancelled() || event.getEntityType() != EntityType.FIREBALL) 17 | return; 18 | 19 | final List blockListCopy = new ArrayList<>(event.blockList()); 20 | 21 | for (Block block : blockListCopy) { 22 | if (MainConfig.fireball_whitelist_blocks.contains(block.getType())) 23 | event.blockList().remove(block); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /API/src/main/java/me/metallicgoat/tweaksaddon/api/events/PostConfigLoadEvent.java: -------------------------------------------------------------------------------- 1 | package me.metallicgoat.tweaksaddon.api.events; 2 | 3 | import org.bukkit.event.Event; 4 | import org.bukkit.event.HandlerList; 5 | 6 | 7 | /** 8 | * Called after the plugin configuration files have been loaded or reloaded. 9 | */ 10 | public class PostConfigLoadEvent extends Event { 11 | 12 | private static final HandlerList HANDLERS = new HandlerList(); 13 | 14 | private final boolean firstLoad; 15 | 16 | public PostConfigLoadEvent(boolean firstLoad) { 17 | this.firstLoad = firstLoad; 18 | } 19 | 20 | /** 21 | * Whether this event represents the first time the configuration has been loaded. 22 | * 23 | * @return {@code true} if it was the first time the config was loaded (Plugin just enabled) 24 | */ 25 | public boolean isFirstLoad() { 26 | return this.firstLoad; 27 | } 28 | 29 | @Override 30 | public HandlerList getHandlers() { 31 | return HANDLERS; 32 | } 33 | 34 | public static HandlerList getHandlerList() { 35 | return HANDLERS; 36 | } 37 | } -------------------------------------------------------------------------------- /API/src/main/java/me/metallicgoat/tweaksaddon/api/events/PreConfigsLoadEvent.java: -------------------------------------------------------------------------------- 1 | package me.metallicgoat.tweaksaddon.api.events; 2 | 3 | 4 | import org.bukkit.event.Event; 5 | import org.bukkit.event.HandlerList; 6 | 7 | /** 8 | * Called directly before the plugin configuration files have are being loaded or reloaded. 9 | */ 10 | public class PreConfigsLoadEvent extends Event { 11 | 12 | private static final HandlerList HANDLERS = new HandlerList(); 13 | 14 | private final boolean firstLoad; 15 | 16 | public PreConfigsLoadEvent(boolean firstLoad) { 17 | this.firstLoad = firstLoad; 18 | } 19 | 20 | /** 21 | * Whether this event represents the first time the configuration has been loaded. 22 | * 23 | * @return {@code true} if it was the first time the config was loaded (Plugin just enabled) 24 | */ 25 | public boolean isFirstLoad() { 26 | return this.firstLoad; 27 | } 28 | 29 | @Override 30 | public HandlerList getHandlers() { 31 | return HANDLERS; 32 | } 33 | 34 | public static HandlerList getHandlerList() { 35 | return HANDLERS; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /MBedwarsTweaks/src/main/java/me/metallicgoat/tweaksaddon/utils/Console.java: -------------------------------------------------------------------------------- 1 | package me.metallicgoat.tweaksaddon.utils; 2 | 3 | import me.metallicgoat.tweaksaddon.MBedwarsTweaksPlugin; 4 | 5 | public class Console { 6 | 7 | public static void printError(String error) { 8 | MBedwarsTweaksPlugin.getInstance().getLogger().severe(error); 9 | } 10 | 11 | public static void printWarn(String warn) { 12 | MBedwarsTweaksPlugin.getInstance().getLogger().warning(warn); 13 | } 14 | 15 | public static void printInfo(String info) { 16 | MBedwarsTweaksPlugin.getInstance().getLogger().info(info); 17 | } 18 | 19 | public static void printWarn(String... strings) { 20 | for (String s : strings) 21 | printWarn(s); 22 | } 23 | 24 | public static void printInfo(String... strings) { 25 | for (String s : strings) 26 | printInfo(s); 27 | } 28 | 29 | public static void printConfigWarn(String warn, String config) { 30 | printWarn("[Config-" + config + "] " + warn); 31 | } 32 | 33 | public static void printConfigInfo(String info, String config) { 34 | printInfo("[Config-" + config + "] " + info); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /MBedwarsTweaks/src/main/java/me/metallicgoat/tweaksaddon/tweaks/advancedswords/BuyGroupTracker.java: -------------------------------------------------------------------------------- 1 | package me.metallicgoat.tweaksaddon.tweaks.advancedswords; 2 | 3 | import de.marcely.bedwars.api.game.shop.BuyGroup; 4 | import java.util.HashMap; 5 | import java.util.Map; 6 | import java.util.UUID; 7 | import org.bukkit.entity.Player; 8 | 9 | public class BuyGroupTracker { 10 | 11 | private final Map> trackBuyGroupMap = new HashMap<>(); 12 | 13 | public void upgradeLevel(BuyGroup group, int newLevel, Player player) { 14 | setBuyGroupLevel(player, group.getName(), newLevel); 15 | } 16 | 17 | public int getBuyGroupLevel(Player player, String buyGroup) { 18 | final Map map = trackBuyGroupMap.get(player.getUniqueId()); 19 | 20 | if (map == null) 21 | return 0; 22 | 23 | return map.getOrDefault(buyGroup, 0); 24 | } 25 | 26 | public void setBuyGroupLevel(Player player, String buyGroup, int level) { 27 | final Map map = this.trackBuyGroupMap.computeIfAbsent( 28 | player.getUniqueId(), 29 | g0 -> new HashMap<>()); 30 | 31 | map.put(buyGroup, level); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /MBedwarsTweaks/src/main/java/me/metallicgoat/tweaksaddon/tweaks/advancedswords/AntiDrop.java: -------------------------------------------------------------------------------- 1 | package me.metallicgoat.tweaksaddon.tweaks.advancedswords; 2 | 3 | import de.marcely.bedwars.api.BedwarsAPI; 4 | import de.marcely.bedwars.api.arena.Arena; 5 | import de.marcely.bedwars.api.arena.ArenaStatus; 6 | import me.metallicgoat.tweaksaddon.config.SwordsToolsConfig; 7 | import org.bukkit.entity.Player; 8 | import org.bukkit.event.EventHandler; 9 | import org.bukkit.event.Listener; 10 | import org.bukkit.event.player.PlayerDropItemEvent; 11 | 12 | public class AntiDrop implements Listener { 13 | 14 | @EventHandler 15 | public void onToolDrop(PlayerDropItemEvent event) { 16 | if (!SwordsToolsConfig.anti_drop_enabled) 17 | return; 18 | 19 | final Player player = event.getPlayer(); 20 | final Arena arena = BedwarsAPI.getGameAPI().getArenaByPlayer(player); 21 | 22 | // If player is trying to dop a tool he shouldn't, cancel event 23 | if (arena == null || arena.getStatus() != ArenaStatus.RUNNING) 24 | return; 25 | 26 | if (SwordsToolsConfig.anti_drop_materials.contains(event.getItemDrop().getItemStack().getType()) 27 | && ToolSwordHelper.isNotToIgnore(event.getItemDrop().getItemStack())) { 28 | 29 | event.setCancelled(true); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /MBedwarsTweaks/src/main/java/me/metallicgoat/tweaksaddon/tweaks/messages/FinalKillSuffix.java: -------------------------------------------------------------------------------- 1 | package me.metallicgoat.tweaksaddon.tweaks.messages; 2 | 3 | import de.marcely.bedwars.api.BedwarsAPI; 4 | import de.marcely.bedwars.api.arena.Arena; 5 | import de.marcely.bedwars.api.arena.Team; 6 | import de.marcely.bedwars.api.event.player.PlayerIngameDeathEvent; 7 | import de.marcely.bedwars.api.message.Message; 8 | import me.metallicgoat.tweaksaddon.config.MainConfig; 9 | import org.bukkit.entity.Player; 10 | import org.bukkit.event.EventHandler; 11 | import org.bukkit.event.Listener; 12 | 13 | public class FinalKillSuffix implements Listener { 14 | 15 | @EventHandler 16 | public void onPlayerDeath(PlayerIngameDeathEvent e) { 17 | if (!MainConfig.final_kill_suffix_enabled) 18 | return; 19 | 20 | final Player p = e.getPlayer(); 21 | final Arena arena = BedwarsAPI.getGameAPI().getArenaByPlayer(p); 22 | 23 | if (arena == null) 24 | return; 25 | 26 | final Team team = arena.getPlayerTeam(p); 27 | final Message message = e.getDeathMessage(); 28 | 29 | if (arena.isBedDestroyed(team) && message != null) { 30 | final String finalMessage = (message.done(false) + MainConfig.final_kill_suffix); 31 | e.setDeathMessage(Message.build(finalMessage)); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /MBedwarsTweaks/src/main/java/me/metallicgoat/tweaksaddon/tweaks/messages/TeamEliminate.java: -------------------------------------------------------------------------------- 1 | package me.metallicgoat.tweaksaddon.tweaks.messages; 2 | 3 | import de.marcely.bedwars.api.arena.Arena; 4 | import de.marcely.bedwars.api.arena.Team; 5 | import de.marcely.bedwars.api.event.arena.TeamEliminateEvent; 6 | import de.marcely.bedwars.api.message.Message; 7 | import me.metallicgoat.tweaksaddon.config.MainConfig; 8 | import org.bukkit.ChatColor; 9 | import org.bukkit.event.EventHandler; 10 | import org.bukkit.event.Listener; 11 | 12 | public class TeamEliminate implements Listener { 13 | 14 | @EventHandler 15 | public void onEliminate(TeamEliminateEvent event) { 16 | if (!MainConfig.team_eliminate_message_enabled) 17 | return; 18 | 19 | final Arena arena = event.getArena(); 20 | final Team team = event.getTeam(); 21 | final String teamName = ChatColor.stripColor(team.getDisplayName()); 22 | final String teamColor = String.valueOf(team.getBungeeChatColor()); 23 | 24 | for (String message : MainConfig.team_eliminate_message) { 25 | final String messageFormatted = Message.build(message) 26 | .placeholder("team-name", teamName) 27 | .placeholder("team-color", teamColor) 28 | .done(); 29 | 30 | arena.broadcast(messageFormatted); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /MBedwarsTweaks/src/main/java/me/metallicgoat/tweaksaddon/tweaks/misc/BlockArenaStats.java: -------------------------------------------------------------------------------- 1 | package me.metallicgoat.tweaksaddon.tweaks.misc; 2 | 3 | import de.marcely.bedwars.api.GameAPI; 4 | import de.marcely.bedwars.api.arena.Arena; 5 | import de.marcely.bedwars.api.event.player.PlayerStatChangeEvent; 6 | import me.metallicgoat.tweaksaddon.utils.CachedArenaIdentifier; 7 | import me.metallicgoat.tweaksaddon.config.MainConfig; 8 | import org.bukkit.Bukkit; 9 | import org.bukkit.entity.Player; 10 | import org.bukkit.event.EventHandler; 11 | import org.bukkit.event.Listener; 12 | 13 | public class BlockArenaStats implements Listener { 14 | 15 | @EventHandler 16 | public void onStatUpdate(PlayerStatChangeEvent event) { 17 | if (!MainConfig.block_stat_change_enabled || MainConfig.block_stat_change_arenas.isEmpty()) 18 | return; 19 | 20 | final Player player = Bukkit.getPlayer(event.getStats().getPlayerUUID()); 21 | final Arena playerArena = player != null ? GameAPI.get().getArenaByPlayer(player) : null; 22 | 23 | if (playerArena == null) 24 | return; 25 | 26 | for (CachedArenaIdentifier arenaIdentifier : MainConfig.block_stat_change_arenas) { 27 | if (arenaIdentifier.includes(playerArena)) { 28 | event.setCancelled(true); 29 | return; 30 | } 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /API/src/main/java/me/metallicgoat/tweaksaddon/api/gentiers/GenTierActionType.java: -------------------------------------------------------------------------------- 1 | package me.metallicgoat.tweaksaddon.api.gentiers; 2 | 3 | /** 4 | * Represents the different types of Gen Tier Actions 5 | */ 6 | public enum GenTierActionType { 7 | 8 | /** 9 | * Affects drop rates of in game spawners 10 | */ 11 | GEN_UPGRADE, 12 | 13 | /** 14 | * Destroys all remaining beds within an arena 15 | */ 16 | BED_DESTROY, 17 | 18 | /** 19 | * Spawns in dragons to aid in ending the game faster 20 | */ 21 | SUDDEN_DEATH, 22 | 23 | /** 24 | * The tier that officially ends the game 25 | */ 26 | GAME_OVER, 27 | 28 | /** 29 | * Custom Gen Tier Action 30 | */ 31 | PLUGIN; 32 | 33 | private final String defaultHandlerId; 34 | 35 | GenTierActionType() { 36 | this.defaultHandlerId = GenTierActionType.this.name().toLowerCase().replace("_", "-"); 37 | } 38 | 39 | /** 40 | * Get the default handler Id for this action type 41 | * 42 | * @return The default handler Id 43 | * @throws UnsupportedOperationException if this action type is PLUGIN 44 | */ 45 | public String getDefaultHandlerId() { 46 | if (this == GenTierActionType.PLUGIN) 47 | throw new UnsupportedOperationException("PLUGIN does not have a default handler Id!"); 48 | 49 | return defaultHandlerId; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /MBedwarsTweaks/src/main/java/me/metallicgoat/tweaksaddon/gentiers/handlers/BedDestroyHandler.java: -------------------------------------------------------------------------------- 1 | package me.metallicgoat.tweaksaddon.gentiers.handlers; 2 | 3 | import de.marcely.bedwars.api.arena.Arena; 4 | import de.marcely.bedwars.api.arena.BedDestructionInfo; 5 | import de.marcely.bedwars.api.arena.Team; 6 | import de.marcely.bedwars.api.message.Message; 7 | import me.metallicgoat.tweaksaddon.api.gentiers.GenTierActionType; 8 | import me.metallicgoat.tweaksaddon.api.gentiers.GenTierLevel; 9 | import me.metallicgoat.tweaksaddon.config.MainConfig; 10 | 11 | public class BedDestroyHandler extends BaseGenTierHandler { 12 | 13 | @Override 14 | public void run(GenTierLevel level, Arena arena) { 15 | // Break all beds in an arena & run team upgrades 16 | for (Team team : arena.getEnabledTeams()) { 17 | final BedDestructionInfo info = BedDestructionInfo.construct(team); 18 | 19 | info.setDestroyerName(Message.build(level.getTierName()).done()); 20 | 21 | arena.destroyBedNaturally(info); 22 | } 23 | 24 | // Broadcast Message 25 | if (!MainConfig.auto_bed_break_message_enabled) 26 | return; 27 | 28 | for (String s : MainConfig.auto_bed_break_message) 29 | arena.broadcast(Message.build(s)); 30 | } 31 | 32 | @Override 33 | public String getId() { 34 | return GenTierActionType.BED_DESTROY.getDefaultHandlerId(); 35 | } 36 | 37 | @Override 38 | public GenTierActionType getActionType() { 39 | return GenTierActionType.BED_DESTROY; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /MBedwarsTweaks/src/main/java/me/metallicgoat/tweaksaddon/utils/NMSClass.java: -------------------------------------------------------------------------------- 1 | package me.metallicgoat.tweaksaddon.utils; 2 | 3 | import de.marcely.bedwars.tools.NMSHelper; 4 | import org.bukkit.Bukkit; 5 | import org.bukkit.World; 6 | 7 | public class NMSClass { 8 | 9 | public static void disableDragonSound() throws Exception { 10 | final int serverVersion = NMSHelper.get().getVersion(); 11 | final String craftBukkitPackage = Bukkit.getServer().getClass().getPackage().getName(); 12 | 13 | final Class craftWorldClass = Class.forName(craftBukkitPackage + ".CraftWorld"); 14 | final Class spigotConfigClass = Class.forName("org.spigotmc.SpigotWorldConfig"); 15 | final Class nmsWorldClass; 16 | 17 | if (serverVersion > 16) { 18 | nmsWorldClass = Class.forName("net.minecraft.world.level.World"); 19 | 20 | } else { 21 | final String serverString = "v1_" + serverVersion + "_R" + NMSHelper.get().getRevision(); 22 | 23 | nmsWorldClass = Class.forName("net.minecraft.server." + serverString + ".World"); 24 | } 25 | 26 | for (World world : Bukkit.getWorlds()) { 27 | final Object craftWorld = craftWorldClass.cast(world); 28 | final Object nmsWorld = craftWorldClass.getMethod("getHandle").invoke(craftWorld); 29 | final Object worldConfig = nmsWorldClass.getField("spigotConfig").get(nmsWorld); 30 | 31 | // set value to 1 to disable (0 is global) 32 | spigotConfigClass.getField("dragonDeathSoundRadius").set(worldConfig, 1); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /MBedwarsTweaks/src/main/java/me/metallicgoat/tweaksaddon/tweaks/misc/PearlSoundBroadcast.java: -------------------------------------------------------------------------------- 1 | package me.metallicgoat.tweaksaddon.tweaks.misc; 2 | 3 | import de.marcely.bedwars.api.GameAPI; 4 | import de.marcely.bedwars.api.arena.Arena; 5 | import de.marcely.bedwars.tools.Helper; 6 | import de.marcely.bedwars.tools.VarSound; 7 | import me.metallicgoat.tweaksaddon.config.MainConfig; 8 | import org.bukkit.entity.Player; 9 | import org.bukkit.event.EventHandler; 10 | import org.bukkit.event.Listener; 11 | import org.bukkit.event.player.PlayerTeleportEvent; 12 | 13 | public class PearlSoundBroadcast implements Listener { 14 | 15 | @SuppressWarnings("ConstantConditions") // null warning for the sound 16 | private final static VarSound PEARL_SOUND = VarSound.from(Helper.get().getSoundByName("ENTITY_ENDERMAN_TELEPORT")); 17 | 18 | @EventHandler 19 | public void onEntityTeleportEvent(PlayerTeleportEvent event) { 20 | if (!MainConfig.broadcast_ender_pearl_sound || event.getCause() != PlayerTeleportEvent.TeleportCause.ENDER_PEARL) 21 | return; 22 | 23 | final Player teleporter = event.getPlayer(); 24 | final Arena arena = GameAPI.get().getArenaByPlayer(teleporter); 25 | 26 | if (arena == null) 27 | return; 28 | 29 | for (Player player : arena.getPlayers()) { 30 | // "Most sounds can be heard 16 blocks away" (Try 12 it gets quieter) 31 | // https://minecraft.wiki/w/Sound 32 | if (player.getLocation().distance(event.getTo()) > 12) { 33 | PEARL_SOUND.play(player); 34 | } 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /MBedwarsTweaks/src/main/java/me/metallicgoat/tweaksaddon/gentiers/dragons/SuddenDeathUpgrade.java: -------------------------------------------------------------------------------- 1 | package me.metallicgoat.tweaksaddon.gentiers.dragons; 2 | 3 | import de.marcely.bedwars.api.event.player.PlayerTriggerUpgradeEvent; 4 | import de.marcely.bedwars.api.game.upgrade.UpgradeTriggerHandler; 5 | import de.marcely.bedwars.api.message.Message; 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | import me.metallicgoat.tweaksaddon.MBedwarsTweaksPlugin; 9 | import me.metallicgoat.tweaksaddon.gentiers.GenTiers; 10 | import me.metallicgoat.tweaksaddon.utils.Util; 11 | import org.bukkit.command.CommandSender; 12 | 13 | public class SuddenDeathUpgrade extends UpgradeTriggerHandler { 14 | 15 | public static final UpgradeTriggerHandler INSTANCE = new SuddenDeathUpgrade(); 16 | 17 | SuddenDeathUpgrade() { 18 | super("sudden-death", false, MBedwarsTweaksPlugin.getInstance()); 19 | } 20 | 21 | @Override 22 | public void onTrigger(PlayerTriggerUpgradeEvent event) { 23 | if (event.isCancelled()) 24 | return; 25 | 26 | GenTiers.getState(event.getArena()).setDragonBought(event.getTeam(), true); 27 | } 28 | 29 | @Override 30 | public String getName(CommandSender sender) { 31 | return Message.buildByKey("Tweaks_SuddenDeath_Upgrade_Name").done(sender, false); 32 | } 33 | 34 | @Override 35 | public List getDescriptionLines(CommandSender sender) { 36 | final String msg = Message.buildByKey("Tweaks_SuddenDeath_Upgrade_Description").done(sender, false); 37 | 38 | return msg != null ? Util.getLines(msg) : new ArrayList<>(); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /API/src/main/java/me/metallicgoat/tweaksaddon/api/unsafe/MBedwarsTweaksAPILayer.java: -------------------------------------------------------------------------------- 1 | package me.metallicgoat.tweaksaddon.api.unsafe; 2 | 3 | import de.marcely.bedwars.api.arena.Arena; 4 | import de.marcely.bedwars.api.arena.Team; 5 | import de.marcely.bedwars.api.game.upgrade.UpgradeTriggerHandler; 6 | import me.metallicgoat.tweaksaddon.api.gentiers.GenTierHandler; 7 | import me.metallicgoat.tweaksaddon.api.gentiers.GenTierLevel; 8 | import me.metallicgoat.tweaksaddon.api.gentiers.GenTierState; 9 | import me.metallicgoat.tweaksaddon.api.gentiers.SuddenDeathDragon; 10 | import java.util.Collection; 11 | import java.util.List; 12 | 13 | 14 | /** 15 | * 16 | * Do NOT use this class! 17 | * This is not API and is subject to change at any time 18 | * 19 | */ 20 | 21 | @Deprecated 22 | public abstract class MBedwarsTweaksAPILayer { 23 | 24 | public static MBedwarsTweaksAPILayer INSTANCE; 25 | 26 | public abstract List getDragons(Arena arena, Team team); 27 | 28 | public abstract GenTierState getGenTierState(Arena arena); 29 | 30 | public abstract void registerGenTierHandler(GenTierHandler handler); 31 | 32 | public abstract void unregisterGenTierHandler(String id); 33 | 34 | public abstract GenTierHandler getGenTierHandlerById(String id); 35 | 36 | public abstract Collection getGenTierHandlers(); 37 | 38 | public abstract Collection getGenTierLevels(); 39 | 40 | public abstract GenTierLevel getGenTierLevel(int lvl); 41 | 42 | public abstract UpgradeTriggerHandler getSuddenDeathUpgrade(); 43 | 44 | public abstract void reloadGenTierConfig(); 45 | 46 | } 47 | -------------------------------------------------------------------------------- /MBedwarsTweaks/src/main/java/me/metallicgoat/tweaksaddon/commands/SpecialItemCommand.java: -------------------------------------------------------------------------------- 1 | package me.metallicgoat.tweaksaddon.commands; 2 | 3 | import de.marcely.bedwars.api.GameAPI; 4 | import de.marcely.bedwars.api.command.CommandHandler; 5 | import de.marcely.bedwars.api.command.SubCommand; 6 | import java.util.List; 7 | import me.metallicgoat.tweaksaddon.MBedwarsTweaksPlugin; 8 | import org.bukkit.command.CommandSender; 9 | import org.bukkit.plugin.Plugin; 10 | import org.jetbrains.annotations.Nullable; 11 | 12 | public class SpecialItemCommand implements CommandHandler { 13 | 14 | private SubCommand command; 15 | 16 | @Override 17 | public Plugin getPlugin() { 18 | return MBedwarsTweaksPlugin.getInstance(); 19 | } 20 | 21 | @Override 22 | public void onRegister(SubCommand subCommand) { 23 | this.command = subCommand; 24 | this.command.setOnlyForPlayers(false); 25 | this.command.setUsage(""); 26 | this.command.setAliases("specialids", "showspecialitems", "specialitems"); 27 | } 28 | 29 | @Override 30 | public void onFire(CommandSender commandSender, String s, String[] strings) { 31 | final StringBuilder builder = new StringBuilder(); 32 | 33 | // Send him a list of special items. 34 | if (strings.length > 0) 35 | return; 36 | 37 | GameAPI.get().getSpecialItems().forEach(specialItem -> 38 | builder.append(specialItem.getId()).append(", ") 39 | ); 40 | 41 | commandSender.sendMessage(builder.toString()); 42 | } 43 | 44 | @Override 45 | public @Nullable List onAutocomplete(CommandSender commandSender, String[] strings) { 46 | return null; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /MBedwarsTweaks/src/main/java/me/metallicgoat/tweaksaddon/gentiers/handlers/SpawnerUpgradeHandler.java: -------------------------------------------------------------------------------- 1 | package me.metallicgoat.tweaksaddon.gentiers.handlers; 2 | 3 | import de.marcely.bedwars.api.arena.Arena; 4 | import de.marcely.bedwars.api.game.spawner.Spawner; 5 | import de.marcely.bedwars.api.game.spawner.SpawnerDurationModifier; 6 | import me.metallicgoat.tweaksaddon.MBedwarsTweaksPlugin; 7 | import me.metallicgoat.tweaksaddon.api.gentiers.GenTierActionType; 8 | import me.metallicgoat.tweaksaddon.api.gentiers.GenTierLevel; 9 | import me.metallicgoat.tweaksaddon.config.MainConfig; 10 | import me.metallicgoat.tweaksaddon.gentiers.GenTiers; 11 | 12 | public class SpawnerUpgradeHandler extends BaseGenTierHandler { 13 | 14 | @Override 15 | public void run(GenTierLevel level, Arena arena) { 16 | // For all spawners 17 | for (Spawner spawner : arena.getSpawners()) { 18 | if (level.getType() != null && spawner.getDropType() == level.getType()) { 19 | // Set drop time 20 | if (level.getSpeed() != null) 21 | spawner.addDropDurationModifier("GEN_UPGRADE", MBedwarsTweaksPlugin.getInstance(), SpawnerDurationModifier.Operation.SET, level.getSpeed()); 22 | 23 | // Set new limit 24 | if (level.getLimit() != null) 25 | spawner.setMaxNearbyItems(level.getLimit()); 26 | 27 | // Add custom Holo tiles 28 | if (MainConfig.gen_tiers_custom_holo_enabled) 29 | GenTiers.formatHoloTiles(level.getHoloName(), spawner); 30 | 31 | } 32 | } 33 | } 34 | 35 | @Override 36 | public String getId() { 37 | return GenTierActionType.GEN_UPGRADE.getDefaultHandlerId(); 38 | } 39 | 40 | @Override 41 | public GenTierActionType getActionType() { 42 | return GenTierActionType.GEN_UPGRADE; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /API/src/main/java/me/metallicgoat/tweaksaddon/api/gentiers/GenTierHandler.java: -------------------------------------------------------------------------------- 1 | package me.metallicgoat.tweaksaddon.api.gentiers; 2 | 3 | import de.marcely.bedwars.api.arena.Arena; 4 | import me.metallicgoat.tweaksaddon.api.unsafe.MBedwarsTweaksAPILayer; 5 | import org.bukkit.plugin.Plugin; 6 | 7 | /** 8 | * Represents a handler for a gen tier occurance. 9 | * 10 | * @see me.metallicgoat.tweaksaddon.api.GenTiersAPI#registerHandler(GenTierHandler) 11 | */ 12 | public abstract class GenTierHandler { 13 | 14 | /** 15 | * Called when the gen tier's time elapsed and it is being run. 16 | * 17 | * @param level the gen tier level being run 18 | * @param arena the arena the gen tier is being run in 19 | */ 20 | public abstract void run(GenTierLevel level, Arena arena); 21 | 22 | /** 23 | * Get the plugin which registered this handler 24 | * 25 | * @return the plugin which registered this handler 26 | */ 27 | public abstract Plugin getPlugin(); 28 | 29 | /** 30 | * Get the unique id of this handler as used in configs 31 | * 32 | * @return the unique id of this handler 33 | */ 34 | public abstract String getId(); 35 | 36 | /** 37 | * Get the type of action this handler performs 38 | *

39 | * Custom handlers should always return {@link GenTierActionType#PLUGIN} 40 | *

41 | * 42 | * @return the type of action this handler performs 43 | */ 44 | public GenTierActionType getActionType() { 45 | return GenTierActionType.PLUGIN; 46 | } 47 | 48 | /** 49 | * Check if this handler is currently registered 50 | * 51 | * @return true if this handler is registered 52 | */ 53 | public final boolean isRegistered() { 54 | return MBedwarsTweaksAPILayer.INSTANCE.getGenTierHandlers().contains(this); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /API/src/main/java/me/metallicgoat/tweaksaddon/api/gentiers/SuddenDeathDragon.java: -------------------------------------------------------------------------------- 1 | package me.metallicgoat.tweaksaddon.api.gentiers; 2 | 3 | 4 | import de.marcely.bedwars.api.arena.Arena; 5 | import de.marcely.bedwars.api.arena.Team; 6 | import org.bukkit.Location; 7 | import org.bukkit.entity.EnderDragon; 8 | import org.bukkit.entity.Entity; 9 | 10 | /** 11 | * Represents a Sudden Death Dragon spawned by the Gen Tier system. 12 | */ 13 | public interface SuddenDeathDragon { 14 | 15 | /** 16 | * The Bukkit entity used to power this dragon 17 | * 18 | * @return a Bukkit EnderDragon 19 | */ 20 | EnderDragon getDragon(); 21 | 22 | /** 23 | * The arena which this Dragon is active in 24 | * 25 | * @return the Arena the Dragon is playing in 26 | */ 27 | Arena getArena(); 28 | 29 | /** 30 | * The Dragon's Team 31 | * 32 | * @return The team the dragon is playing for 33 | */ 34 | Team getTeam(); 35 | 36 | /** 37 | * The location the dragon is currently targeting 38 | * 39 | * @return the dragons taget location 40 | */ 41 | Location getDragonTargetLocation(); 42 | 43 | /** 44 | * Change the location the Dragon is targeting 45 | * 46 | * @param location where the dragon should target 47 | */ 48 | void setDragonTarget(Location location); 49 | 50 | /** 51 | * Change the entity which the Dragon is targeting 52 | * 53 | * @param entity who the dragon should target 54 | */ 55 | void setDragonTarget(Entity entity); 56 | 57 | /** 58 | * Removes this dragon anf ends the corresponding tasks 59 | */ 60 | void remove(); 61 | 62 | /** 63 | * Check if this dragon is still active 64 | * 65 | * @return true if the dragon is still active, false otherwise 66 | */ 67 | boolean exists(); 68 | } 69 | -------------------------------------------------------------------------------- /MBedwarsTweaks/src/main/java/me/metallicgoat/tweaksaddon/tweaks/misc/PermanentEffects.java: -------------------------------------------------------------------------------- 1 | package me.metallicgoat.tweaksaddon.tweaks.misc; 2 | 3 | import de.marcely.bedwars.api.arena.Arena; 4 | import de.marcely.bedwars.api.event.arena.RoundStartEvent; 5 | import de.marcely.bedwars.api.event.player.PlayerIngamePostRespawnEvent; 6 | import java.util.Map; 7 | import me.metallicgoat.tweaksaddon.config.MainConfig; 8 | import me.metallicgoat.tweaksaddon.utils.CachedArenaIdentifier; 9 | import org.bukkit.entity.Player; 10 | import org.bukkit.event.EventHandler; 11 | import org.bukkit.event.Listener; 12 | import org.bukkit.potion.PotionEffect; 13 | import org.jetbrains.annotations.Nullable; 14 | 15 | public class PermanentEffects implements Listener { 16 | 17 | @EventHandler 18 | public void onRoundStart(RoundStartEvent event) { 19 | final Arena arena = event.getArena(); 20 | final PotionEffect effect = getArenaEffects(arena); 21 | 22 | if (!MainConfig.permanent_effects_enabled || effect == null) 23 | return; 24 | 25 | for (Player player : arena.getPlayers()) 26 | player.addPotionEffect(effect); 27 | } 28 | 29 | @EventHandler 30 | public void onPostRespawn(PlayerIngamePostRespawnEvent event) { 31 | final Arena arena = event.getArena(); 32 | final PotionEffect effect = getArenaEffects(arena); 33 | 34 | if (!MainConfig.permanent_effects_enabled || effect == null) 35 | return; 36 | 37 | event.getPlayer().addPotionEffect(effect); 38 | } 39 | 40 | public @Nullable PotionEffect getArenaEffects(Arena arena) { 41 | for (Map.Entry entry : MainConfig.permanent_effects_arenas.entrySet()) { 42 | if (entry.getKey().includes(arena)) { 43 | return entry.getValue(); 44 | } 45 | } 46 | 47 | return null; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /MBedwarsTweaks/src/main/java/me/metallicgoat/tweaksaddon/tweaks/spawners/AFKSpawners.java: -------------------------------------------------------------------------------- 1 | package me.metallicgoat.tweaksaddon.tweaks.spawners; 2 | 3 | import de.marcely.bedwars.api.GameAPI; 4 | import de.marcely.bedwars.api.arena.Arena; 5 | import de.marcely.bedwars.api.arena.ArenaStatus; 6 | import de.marcely.bedwars.api.event.player.PlayerPickupDropEvent; 7 | import de.marcely.bedwars.api.event.player.PlayerQuitArenaEvent; 8 | import java.util.IdentityHashMap; 9 | import java.util.Map; 10 | import me.metallicgoat.tweaksaddon.config.MainConfig; 11 | import org.bukkit.entity.Player; 12 | import org.bukkit.event.EventHandler; 13 | import org.bukkit.event.Listener; 14 | import org.bukkit.event.player.PlayerMoveEvent; 15 | 16 | public class AFKSpawners implements Listener { 17 | 18 | private final Map moveTimes = new IdentityHashMap<>(); 19 | 20 | @EventHandler 21 | public void onPlayerMove(PlayerMoveEvent event) { 22 | if (!MainConfig.afk_spawners_enabled) 23 | return; 24 | 25 | final Arena arena = GameAPI.get().getArenaByPlayer(event.getPlayer()); 26 | 27 | if (arena == null || arena.getStatus() != ArenaStatus.RUNNING) 28 | return; 29 | 30 | moveTimes.put(event.getPlayer(), System.currentTimeMillis()); 31 | } 32 | 33 | @EventHandler 34 | public void onPlayerLeave(PlayerQuitArenaEvent event) { 35 | if (!MainConfig.afk_spawners_enabled) 36 | return; 37 | 38 | moveTimes.remove(event.getPlayer()); 39 | } 40 | 41 | @EventHandler 42 | public void onSpawnerPickup(PlayerPickupDropEvent event) { 43 | if (!MainConfig.afk_spawners_enabled || event.isCancelled()) 44 | return; 45 | 46 | final Player player = event.getPlayer(); 47 | 48 | if (!moveTimes.containsKey(player)) 49 | return; 50 | 51 | final long secsSinceLastMove = (System.currentTimeMillis() - moveTimes.get(player)) / 1000; 52 | 53 | if (secsSinceLastMove > MainConfig.afk_spawners_time) 54 | event.setCancelled(true); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /MBedwarsTweaks/src/main/java/me/metallicgoat/tweaksaddon/tweaks/explosives/TNTIgniteCountdown.java: -------------------------------------------------------------------------------- 1 | package me.metallicgoat.tweaksaddon.tweaks.explosives; 2 | 3 | import de.marcely.bedwars.api.GameAPI; 4 | import de.marcely.bedwars.api.message.Message; 5 | import java.text.DecimalFormat; 6 | import me.metallicgoat.tweaksaddon.MBedwarsTweaksPlugin; 7 | import me.metallicgoat.tweaksaddon.config.MainConfig; 8 | import org.bukkit.entity.EntityType; 9 | import org.bukkit.entity.TNTPrimed; 10 | import org.bukkit.event.EventHandler; 11 | import org.bukkit.event.Listener; 12 | import org.bukkit.event.entity.EntitySpawnEvent; 13 | import org.bukkit.scheduler.BukkitRunnable; 14 | 15 | public class TNTIgniteCountdown implements Listener { 16 | 17 | private static final DecimalFormat decimalFormat = new DecimalFormat("0.00"); 18 | 19 | // Place a countdown on TNT when it is ignited 20 | @EventHandler 21 | public void onEntitySpawnEvent(EntitySpawnEvent event) { 22 | if (!MainConfig.tnt_ignite_timer_enabled 23 | || GameAPI.get().getArenaByLocation(event.getLocation()) == null 24 | || event.getEntity().getType() != EntityType.PRIMED_TNT) 25 | return; 26 | 27 | final TNTPrimed entity = (TNTPrimed) event.getEntity(); 28 | 29 | entity.setCustomNameVisible(true); 30 | 31 | final BukkitRunnable runnable = new BukkitRunnable() { 32 | @Override 33 | public void run() { 34 | if (!entity.isValid() || entity.getFuseTicks() <= 0) { 35 | cancel(); 36 | return; 37 | } 38 | 39 | // Second to two decimal places 40 | final double seconds = ((double) entity.getFuseTicks()) / 20D; 41 | final String secondsString = decimalFormat.format(seconds); 42 | 43 | entity.setCustomName(Message.build(MainConfig.tnt_ignite_timer_title).placeholder("seconds", secondsString).done()); 44 | } 45 | }; 46 | 47 | runnable.runTaskTimer(MBedwarsTweaksPlugin.getInstance(), 0L, 1L); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /MBedwarsTweaks/src/main/java/me/metallicgoat/tweaksaddon/tweaks/messages/BuyMessage.java: -------------------------------------------------------------------------------- 1 | package me.metallicgoat.tweaksaddon.tweaks.messages; 2 | 3 | import de.marcely.bedwars.api.event.player.PlayerBuyInShopEvent; 4 | import de.marcely.bedwars.api.game.shop.ShopItem; 5 | import de.marcely.bedwars.api.game.shop.product.ItemShopProduct; 6 | import de.marcely.bedwars.api.game.shop.product.ShopProduct; 7 | import de.marcely.bedwars.api.message.Message; 8 | import me.metallicgoat.tweaksaddon.config.MainConfig; 9 | import org.bukkit.entity.Player; 10 | import org.bukkit.event.EventHandler; 11 | import org.bukkit.event.EventPriority; 12 | import org.bukkit.event.Listener; 13 | import org.bukkit.inventory.ItemStack; 14 | 15 | public class BuyMessage implements Listener { 16 | 17 | @EventHandler(priority = EventPriority.HIGH) 18 | public void onBuyEvent(PlayerBuyInShopEvent event) { 19 | if (!MainConfig.buy_message_enabled || !event.getProblems().isEmpty()) 20 | return; 21 | 22 | final Player p = event.getPlayer(); 23 | final String product = event.getItem().getDisplayName(); 24 | final int amount = getAmount(event.getItem()); 25 | final String strAmount = Integer.toString(getAmount(event.getItem())); 26 | final String baseMessage = amount == 0 ? MainConfig.buy_message_amountless : MainConfig.buy_message; // e.g. if command is used as product, amount would be 0 27 | 28 | Message.build(baseMessage) 29 | .placeholder("product", product) 30 | .placeholder("amount", strAmount) 31 | .send(p); 32 | } 33 | 34 | private int getAmount(ShopItem item) { 35 | int count = 0; 36 | for (ShopProduct rawProduct : item.getProducts()) { 37 | if (rawProduct instanceof ItemShopProduct) { 38 | final ItemStack[] is = ((ItemShopProduct) rawProduct).getItemStacks(); 39 | for (ItemStack itemStack : is) { 40 | count += itemStack.getAmount(); 41 | } 42 | } 43 | } 44 | return count; 45 | } 46 | } -------------------------------------------------------------------------------- /MBedwarsTweaks/src/main/java/me/metallicgoat/tweaksaddon/tweaks/advancedswords/DegradingBuyGroups.java: -------------------------------------------------------------------------------- 1 | package me.metallicgoat.tweaksaddon.tweaks.advancedswords; 2 | 3 | import de.marcely.bedwars.api.GameAPI; 4 | import de.marcely.bedwars.api.arena.Arena; 5 | import de.marcely.bedwars.api.arena.Team; 6 | import de.marcely.bedwars.api.event.player.PlayerIngamePostRespawnEvent; 7 | import de.marcely.bedwars.api.game.shop.BuyGroup; 8 | import de.marcely.bedwars.api.game.shop.ShopItem; 9 | import java.util.Collection; 10 | import me.metallicgoat.tweaksaddon.config.SwordsToolsConfig; 11 | import org.bukkit.entity.Player; 12 | import org.bukkit.event.EventHandler; 13 | import org.bukkit.event.Listener; 14 | 15 | public class DegradingBuyGroups implements Listener { 16 | 17 | @EventHandler 18 | public void onPostRespawn(PlayerIngamePostRespawnEvent event) { 19 | if (!SwordsToolsConfig.degrading_buygroups_enabled) 20 | return; 21 | 22 | final Player player = event.getPlayer(); 23 | final Arena arena = event.getArena(); 24 | 25 | for (String name : SwordsToolsConfig.degrading_buygroups) { 26 | final BuyGroup buyGroup = GameAPI.get().getBuyGroup(name); 27 | 28 | if (buyGroup == null) 29 | continue; 30 | 31 | final BuyGroupTracker tracker = ToolSwordHelper.getBuyGroupTracker(arena); 32 | int newLevel = tracker.getBuyGroupLevel(player, name); 33 | 34 | if (buyGroup.getLevels().contains(newLevel - 1)) 35 | newLevel--; 36 | 37 | tracker.setBuyGroupLevel(player, name, newLevel); 38 | arena.setBuyGroupLevel(player, buyGroup, newLevel); 39 | 40 | // Give items 41 | final Collection shopItems = buyGroup.getItems(newLevel); 42 | 43 | if (shopItems == null) 44 | continue; 45 | 46 | final Team team = arena.getPlayerTeam(player); 47 | 48 | for (ShopItem item : shopItems) 49 | ToolSwordHelper.givePlayerShopItem(arena, team, player, item); 50 | } 51 | } 52 | } -------------------------------------------------------------------------------- /MBedwarsTweaks/src/main/java/me/metallicgoat/tweaksaddon/tweaks/misc/EmptyContainers.java: -------------------------------------------------------------------------------- 1 | package me.metallicgoat.tweaksaddon.tweaks.misc; 2 | 3 | import de.marcely.bedwars.api.BedwarsAPI; 4 | import de.marcely.bedwars.api.arena.Arena; 5 | import de.marcely.bedwars.tools.Helper; 6 | import me.metallicgoat.tweaksaddon.MBedwarsTweaksPlugin; 7 | import me.metallicgoat.tweaksaddon.config.MainConfig; 8 | import org.bukkit.Bukkit; 9 | import org.bukkit.Material; 10 | import org.bukkit.entity.Player; 11 | import org.bukkit.event.EventHandler; 12 | import org.bukkit.event.Listener; 13 | import org.bukkit.event.player.PlayerBucketEmptyEvent; 14 | import org.bukkit.event.player.PlayerItemConsumeEvent; 15 | import org.bukkit.inventory.ItemStack; 16 | 17 | public class EmptyContainers implements Listener { 18 | 19 | @EventHandler 20 | public void onBucketEmpty(PlayerBucketEmptyEvent event) { 21 | if (!MainConfig.remove_empty_buckets) 22 | return; 23 | 24 | final Player player = event.getPlayer(); 25 | final Arena arena = BedwarsAPI.getGameAPI().getArenaByPlayer(player); 26 | 27 | if (arena == null) 28 | return; 29 | 30 | // Uses isSimilar to remove ItemStacks (weird but works) 31 | Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(MBedwarsTweaksPlugin.getInstance(), () -> 32 | Helper.get().takeItems(player, new ItemStack(Material.BUCKET), 1), 1); 33 | } 34 | 35 | @EventHandler 36 | public void onConsume(PlayerItemConsumeEvent event) { 37 | if (!MainConfig.remove_empty_potions || event.getItem().getType() != Material.POTION) 38 | return; 39 | 40 | final Player player = event.getPlayer(); 41 | final Arena arena = BedwarsAPI.getGameAPI().getArenaByPlayer(player); 42 | 43 | if (arena == null) 44 | return; 45 | 46 | // Uses isSimilar to remove ItemStacks (weird but works) 47 | Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(MBedwarsTweaksPlugin.getInstance(), () -> 48 | Helper.get().takeItems(player, new ItemStack(Material.GLASS_BOTTLE), 1), 1); 49 | } 50 | } -------------------------------------------------------------------------------- /MBedwarsTweaks/src/main/java/me/metallicgoat/tweaksaddon/integration/DependType.java: -------------------------------------------------------------------------------- 1 | package me.metallicgoat.tweaksaddon.integration; 2 | 3 | import lombok.Getter; 4 | import me.metallicgoat.tweaksaddon.utils.Console; 5 | import me.metallicgoat.tweaksaddon.MBedwarsTweaksPlugin; 6 | import me.metallicgoat.tweaksaddon.integration.hooks.PrestigesLevelOnExperienceBar; 7 | import org.bukkit.Bukkit; 8 | import org.bukkit.event.Listener; 9 | import org.bukkit.plugin.PluginManager; 10 | 11 | @Getter 12 | public enum DependType { 13 | PLACEHOLDER_API("PlaceholderAPI"), 14 | HOTBAR_MANAGER("MBedwarsHotbarManager"), 15 | PRESTIGE_ADDON("PrestigeAddon", PrestigesLevelOnExperienceBar.class); 16 | 17 | @Getter 18 | private boolean isEnabled = false; 19 | private final String name; 20 | private final Class[] listenerClasses; 21 | 22 | DependType(String name) { 23 | this.name = name; 24 | this.listenerClasses = null; 25 | } 26 | 27 | DependType(String name, Class... listener) { 28 | this.name = name; 29 | this.listenerClasses = listener; 30 | } 31 | 32 | // Sets isEnabled state, and registers hooks if they are there 33 | // TODO Do we need to unregister listeners if plugin is disabled? 34 | public void tryLoad() { 35 | final PluginManager manager = Bukkit.getServer().getPluginManager(); 36 | 37 | isEnabled = manager.isPluginEnabled(name); 38 | 39 | if (isEnabled && listenerClasses != null) { 40 | try { 41 | for (Class listenerClass : listenerClasses) 42 | manager.registerEvents((Listener) listenerClass.getDeclaredConstructors()[0].newInstance(), MBedwarsTweaksPlugin.getInstance()); 43 | 44 | } catch (Exception e) { 45 | Console.printError("Failed to hook load soft dependency '" + name + "'. This is a bug!"); 46 | } 47 | } 48 | } 49 | 50 | public static DependType getTypeByName(String name) { 51 | for (DependType type : DependType.values()) 52 | if (type.name.equalsIgnoreCase(name)) 53 | return type; 54 | 55 | return null; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /MBedwarsTweaks/src/main/java/me/metallicgoat/tweaksaddon/integration/DependencyLoader.java: -------------------------------------------------------------------------------- 1 | package me.metallicgoat.tweaksaddon.integration; 2 | 3 | import me.metallicgoat.tweaksaddon.utils.Console; 4 | import me.metallicgoat.tweaksaddon.MBedwarsTweaksPlugin; 5 | import me.metallicgoat.tweaksaddon.Placeholders; 6 | import org.bukkit.Bukkit; 7 | import org.bukkit.event.EventHandler; 8 | import org.bukkit.event.Listener; 9 | import org.bukkit.event.server.PluginDisableEvent; 10 | import org.bukkit.event.server.PluginEnableEvent; 11 | 12 | public class DependencyLoader implements Listener { 13 | 14 | public static void loadAll() { 15 | if (Bukkit.getPluginManager().isPluginEnabled("FireBallKnockback")) { 16 | Console.printInfo("I noticed you are using my Fireball jumping addon. " + 17 | "As of 5.0.13, you do not need it anymore! Fireball jumping " + 18 | "is now built into core MBedwars. Features such as throw cooldown and throw " + 19 | "effects have been added to this addon (MBedwarsTweaks). - MetallicGoat" 20 | ); 21 | } 22 | 23 | for (DependType type : DependType.values()) { 24 | type.tryLoad(); 25 | 26 | if (type == DependType.PLACEHOLDER_API) { 27 | if (type.isEnabled()) 28 | new Placeholders(MBedwarsTweaksPlugin.getInstance()).register(); 29 | else 30 | Console.printInfo("PlaceholderAPI was not Found! PAPI placeholders won't work!"); 31 | } 32 | } 33 | } 34 | 35 | private void updateLoadedState(String pluginName, boolean enabled) { 36 | final DependType type = DependType.getTypeByName(pluginName); 37 | 38 | // Is this one of our soft depends? 39 | if (type == null) 40 | return; 41 | 42 | type.tryLoad(); 43 | } 44 | 45 | @EventHandler 46 | public void onDependLoad(PluginEnableEvent event) { 47 | updateLoadedState(event.getPlugin().getName(), true); 48 | } 49 | 50 | @EventHandler 51 | public void onDependUnload(PluginDisableEvent event) { 52 | updateLoadedState(event.getPlugin().getName(), false); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # MBedwarsTweaks 3 | Extra Tweaks & Features for MBedwars 4 | 5 | ## Support 6 | [**Discord Support**](https://discord.gg/RC2mtdcEdD) 7 | 8 | ## Purpose 9 | This addon was originally created to add niche features requested by the community, 10 | as well as features to mimic the behavior of other popular severs hosting bedwars. 11 | Most of the features included were deemed to be to minor to be included in the main plugin. 12 | By default, this addon is configured to mimic the behavior of the popular server 'Hypixel'. 13 | When selecting the 'Hypixel Layout' on the MBedwars setup, this addon will automatically 14 | be installed and configured. 15 | 16 | ## Features 17 | 18 | MBedwarsTweaks offers a large amount extra configuration, here are just a few tweaks and features it offers: 19 | #### 1. Extra Configurations for Swords and Tools 20 | - Replace swords on buy 21 | - Prevent players from 'chesting' certain items 22 | - Prevent players from dropping certain items 23 | - Allow tools to be downgraded after death 24 | 25 | #### 2. Gen-Tiers 26 | - PAPI placeholders for tiers 27 | - Allows you to create custom generator tiers (Including with custom spawners) 28 | - Automatic bed destruction 29 | - 'Sudden Death' dragons 30 | 31 | #### 3. Cosmetic Features 32 | - Friendly Villagers (They look at you!) 33 | - Heal-Pool particles 34 | - Sponge place particles 35 | 36 | #### 4. Explosives Configurations 37 | - Explosive fall damage multiplier 38 | - Fireball block break whitelist 39 | - Fireball throw cool down and effects 40 | - TNT Countdown Hologram 41 | 42 | #### 5. Spawner Configs 43 | - Prevent spawner pickup when AFK 44 | - Disable unused spawners 45 | - Emerald spawner upgrade 46 | 47 | #### 6. Extra Messages 48 | - Top Killers message 49 | - Final kill suffix 50 | - Buy in shop messages 51 | 52 | #### 7. Misc Configs 53 | - Remove empty buckets and potion bottles 54 | - Remove invisibility on damage 55 | - Forced scoreboard updating 56 | - Permanent arena effects 57 | - Block stat tracking in certain arenas 58 | - Lock team chests 59 | - Broadcast ender pearl sounds 60 | - Shrink world borders 61 | 62 | #### 8. So much more! 63 | -------------------------------------------------------------------------------- /MBedwarsTweaks/src/main/java/me/metallicgoat/tweaksaddon/tweaks/advancedswords/ReplaceToolOnBuy.java: -------------------------------------------------------------------------------- 1 | package me.metallicgoat.tweaksaddon.tweaks.advancedswords; 2 | 3 | import de.marcely.bedwars.api.GameAPI; 4 | import de.marcely.bedwars.api.event.player.PlayerBuyInShopEvent; 5 | import de.marcely.bedwars.api.game.shop.BuyGroup; 6 | import de.marcely.bedwars.api.game.shop.product.ItemShopProduct; 7 | import me.metallicgoat.tweaksaddon.config.SwordsToolsConfig; 8 | import org.bukkit.entity.Player; 9 | import org.bukkit.event.EventHandler; 10 | import org.bukkit.event.Listener; 11 | import org.bukkit.inventory.ItemStack; 12 | import org.bukkit.inventory.PlayerInventory; 13 | 14 | public class ReplaceToolOnBuy implements Listener { 15 | 16 | @EventHandler 17 | public void onToolBuy(PlayerBuyInShopEvent event) { 18 | if (!SwordsToolsConfig.advanced_tool_replacement_enabled) 19 | return; 20 | 21 | final BuyGroup group = event.getItem().getBuyGroup(); 22 | 23 | // If enabled, and item has buy-group 24 | if (group != null 25 | && event.getProblems().isEmpty() 26 | && SwordsToolsConfig.advanced_tool_replacement_buygroups.contains(group.getName())) { 27 | 28 | clearOld(group, event.getItem().getBuyGroupLevel(), event.getPlayer()); 29 | } 30 | } 31 | 32 | private void clearOld(BuyGroup purchasedGroup, int level, Player player) { 33 | final PlayerInventory inv = player.getInventory(); 34 | 35 | for (int i = 0; i < player.getInventory().getSize(); i++) { 36 | final ItemStack is = inv.getItem(i); 37 | 38 | if (is == null) 39 | continue; 40 | 41 | final ItemShopProduct invProduct = GameAPI.get().getItemShopProduct(is); 42 | 43 | if (invProduct == null || invProduct.getItem().getBuyGroupLevel() >= level) 44 | continue; 45 | 46 | final BuyGroup checkingGroup = invProduct.getItem().getBuyGroup(); 47 | 48 | // Check names, not instance (cloneable). Names are unique 49 | if (checkingGroup == null || !checkingGroup.getName().equals(purchasedGroup.getName())) 50 | continue; 51 | 52 | // Remove items 53 | inv.setItem(i, null); 54 | } 55 | } 56 | } -------------------------------------------------------------------------------- /API/src/main/java/me/metallicgoat/tweaksaddon/api/events/gentiers/GenTiersActionEvent.java: -------------------------------------------------------------------------------- 1 | package me.metallicgoat.tweaksaddon.api.events.gentiers; 2 | 3 | import de.marcely.bedwars.api.arena.Arena; 4 | import de.marcely.bedwars.api.event.arena.ArenaEvent; 5 | import lombok.Getter; 6 | import lombok.Setter; 7 | import me.metallicgoat.tweaksaddon.api.gentiers.GenTierLevel; 8 | import me.metallicgoat.tweaksaddon.api.gentiers.GenTierState; 9 | import org.bukkit.event.Event; 10 | import org.bukkit.event.HandlerList; 11 | 12 | /** 13 | * Called when enough time has passed to execute the scheduled gen tier upgrade in an arena. 14 | *

15 | * This event is not called for {@link me.metallicgoat.tweaksaddon.api.gentiers.GenTierActionType#GAME_OVER}, 16 | * as that one immediately changes the remaining round time after its {@link GenTiersScheduleEvent}. 17 | *

18 | */ 19 | public class GenTiersActionEvent extends Event implements ArenaEvent { 20 | 21 | private static final HandlerList HANDLERS = new HandlerList(); 22 | 23 | private final GenTierState arenaState; 24 | private final GenTierLevel tier; 25 | 26 | @Getter @Setter 27 | private boolean executingHandlers; 28 | @Getter @Setter 29 | private boolean broadcastingEarn; 30 | 31 | public GenTiersActionEvent(GenTierState arenaState, GenTierLevel tier, boolean executeHandlers, boolean broadcastEarn) { 32 | this.arenaState = arenaState; 33 | this.tier = tier; 34 | this.executingHandlers = executeHandlers; 35 | this.broadcastingEarn = broadcastEarn; 36 | } 37 | 38 | @Override 39 | public Arena getArena() { 40 | return this.arenaState.getArena(); 41 | } 42 | 43 | /** 44 | * Get the state of the gen tiers in the arena. 45 | * 46 | * @return the current gen tier state of the arena 47 | */ 48 | public GenTierState getArenaState() { 49 | return this.arenaState; 50 | } 51 | 52 | /** 53 | * Get the tier level that is being applied. 54 | * 55 | * @return the tier level being applied 56 | */ 57 | public GenTierLevel getTier() { 58 | return this.tier; 59 | } 60 | 61 | @Override 62 | public HandlerList getHandlers() { 63 | return HANDLERS; 64 | } 65 | 66 | public static HandlerList getHandlerList() { 67 | return HANDLERS; 68 | } 69 | } -------------------------------------------------------------------------------- /MBedwarsTweaks/src/main/java/me/metallicgoat/tweaksaddon/tweaks/explosives/FireballUseCoolDown.java: -------------------------------------------------------------------------------- 1 | package me.metallicgoat.tweaksaddon.tweaks.explosives; 2 | 3 | import de.marcely.bedwars.api.event.player.PlayerUseSpecialItemEvent; 4 | import de.marcely.bedwars.api.game.specialitem.SpecialItemType; 5 | import de.marcely.bedwars.tools.NMSHelper; 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | import me.metallicgoat.tweaksaddon.MBedwarsTweaksPlugin; 9 | import me.metallicgoat.tweaksaddon.config.MainConfig; 10 | import org.bukkit.Bukkit; 11 | import org.bukkit.Material; 12 | import org.bukkit.entity.HumanEntity; 13 | import org.bukkit.entity.LivingEntity; 14 | import org.bukkit.entity.Player; 15 | import org.bukkit.event.EventHandler; 16 | import org.bukkit.event.Listener; 17 | import org.bukkit.inventory.ItemStack; 18 | 19 | public class FireballUseCoolDown implements Listener { 20 | 21 | private final List coolDownPlayers = new ArrayList<>(); 22 | 23 | @EventHandler 24 | public void onPlayerUseSpecialItem(PlayerUseSpecialItemEvent event) { 25 | if (!MainConfig.fireball_cooldown_enabled || event.getSpecialItem().getType() != SpecialItemType.FIREBALL) 26 | return; 27 | 28 | final Player player = event.getPlayer(); 29 | 30 | // Remove restriction when in a vehicle to support dragon rider (from Cosmetics addon) 31 | if (player.isInsideVehicle() && player.getVehicle() instanceof LivingEntity) 32 | return; 33 | 34 | if (this.coolDownPlayers.contains(player)) { 35 | event.setCancelled(true); 36 | return; 37 | } 38 | 39 | this.coolDownPlayers.add(player); 40 | 41 | Bukkit.getServer().getScheduler().runTaskLater(MBedwarsTweaksPlugin.getInstance(), () -> 42 | this.coolDownPlayers.remove(player), MainConfig.fireball_cooldown_time); 43 | 44 | // Visual cooldown 45 | if (MainConfig.fireball_cooldown_visually && NMSHelper.get().getVersion() >= 12) { 46 | final ItemStack is = event.getSpecialItem().getItemStack(); 47 | 48 | try { 49 | HumanEntity.class.getMethod("setCooldown", Material.class, int.class) 50 | .invoke(player, is.getType(), (int) MainConfig.fireball_cooldown_time); 51 | } catch (Exception e) { 52 | e.printStackTrace(); 53 | } 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /MBedwarsTweaks/src/main/java/me/metallicgoat/tweaksaddon/tweaks/misc/HeightCap.java: -------------------------------------------------------------------------------- 1 | package me.metallicgoat.tweaksaddon.tweaks.misc; 2 | 3 | import de.marcely.bedwars.api.BedwarsAPI; 4 | import de.marcely.bedwars.api.arena.Arena; 5 | import de.marcely.bedwars.api.arena.ArenaStatus; 6 | import de.marcely.bedwars.api.message.Message; 7 | import java.util.Map; 8 | import me.metallicgoat.tweaksaddon.utils.CachedArenaIdentifier; 9 | import me.metallicgoat.tweaksaddon.config.MainConfig; 10 | import org.bukkit.Location; 11 | import org.bukkit.entity.Player; 12 | import org.bukkit.event.Cancellable; 13 | import org.bukkit.event.EventHandler; 14 | import org.bukkit.event.EventPriority; 15 | import org.bukkit.event.Listener; 16 | import org.bukkit.event.block.BlockPlaceEvent; 17 | import org.bukkit.event.player.PlayerBucketEmptyEvent; 18 | 19 | public class HeightCap implements Listener { 20 | 21 | @EventHandler(priority = EventPriority.HIGH) 22 | public void onBuild(BlockPlaceEvent event) { 23 | if (!MainConfig.custom_height_cap_enabled) 24 | return; 25 | 26 | cancelIfOutOfBounds(event, event.getPlayer(), event.getBlockPlaced().getLocation()); 27 | } 28 | 29 | @EventHandler(priority = EventPriority.HIGH) 30 | public void onBucketEmpty(PlayerBucketEmptyEvent event) { 31 | if (!MainConfig.custom_height_cap_enabled) 32 | return; 33 | 34 | cancelIfOutOfBounds(event, event.getPlayer(), event.getBlockClicked().getRelative(event.getBlockFace()).getLocation()); 35 | } 36 | 37 | private void cancelIfOutOfBounds(Cancellable event, Player player, Location location) { 38 | if (event.isCancelled()) 39 | return; 40 | 41 | final Arena arena = BedwarsAPI.getGameAPI().getArenaByPlayer(player); 42 | 43 | if (arena == null || arena.getStatus() != ArenaStatus.RUNNING) 44 | return; 45 | 46 | for (Map.Entry arenaHeight : MainConfig.custom_height_cap_arenas.entrySet()) { 47 | if (arenaHeight.getKey().includes(arena) && arenaHeight.getValue() != null) { 48 | 49 | if (location.getY() > arenaHeight.getValue()) { 50 | player.sendMessage(Message.build(MainConfig.custom_height_cap_warn).done()); 51 | event.setCancelled(true); 52 | return; 53 | } 54 | } 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /MBedwarsTweaks/src/main/java/me/metallicgoat/tweaksaddon/integration/hooks/PrestigesLevelOnExperienceBar.java: -------------------------------------------------------------------------------- 1 | package me.metallicgoat.tweaksaddon.integration.hooks; 2 | 3 | import de.marcely.bedwars.api.event.arena.RoundEndEvent; 4 | import de.marcely.bedwars.api.event.player.PlayerIngamePostRespawnEvent; 5 | import de.marcely.bedwars.tools.Helper; 6 | import java.util.Optional; 7 | import java.util.function.Consumer; 8 | import me.metallicgoat.tweaksaddon.config.MainConfig; 9 | import me.tvhee.prestigesaddon.api.PrestigeAddonAPI; 10 | import me.tvhee.prestigesaddon.api.PrestigePlayer; 11 | import org.bukkit.Bukkit; 12 | import org.bukkit.entity.Player; 13 | import org.bukkit.event.EventHandler; 14 | import org.bukkit.event.Listener; 15 | 16 | public class PrestigesLevelOnExperienceBar implements Listener { 17 | 18 | private final PrestigeAddonAPI prestigeAddonAPI; 19 | 20 | public PrestigesLevelOnExperienceBar() { 21 | prestigeAddonAPI = (PrestigeAddonAPI) Bukkit.getServer().getPluginManager().getPlugin("PrestigeAddon"); 22 | } 23 | 24 | @EventHandler 25 | public void onArenaStart(RoundEndEvent event) { 26 | // TODO: HARSH - Check if rejoinable players are also stored in #getPlayers 27 | for (Player player : event.getArena().getPlayers()) 28 | setPlayerLevel(player); 29 | } 30 | 31 | // This will get called when the player rejoins too 32 | @EventHandler 33 | public void onPlayerPostRespawn(PlayerIngamePostRespawnEvent event) { 34 | setPlayerLevel(event.getPlayer()); 35 | } 36 | 37 | private void setPlayerLevel(Player player) { 38 | // Check Enabled 39 | if (!MainConfig.prestiges_level_on_exp_bar) 40 | return; 41 | 42 | getPrestigePlayer(player, data -> { 43 | player.setLevel(data.getStars()); 44 | player.setExp(data.getProgress() / 100F); // It goes from 0 - 100 45 | }); 46 | } 47 | 48 | private void getPrestigePlayer(Player player, Consumer callback) { 49 | { 50 | final Optional cached = prestigeAddonAPI.getPlayerDataSync(player); 51 | 52 | if (cached.isPresent()) { 53 | callback.accept(cached.get()); 54 | return; 55 | } 56 | } 57 | 58 | prestigeAddonAPI.getPlayerData( 59 | player, 60 | data -> Helper.get().synchronize(() -> callback.accept(data)) 61 | ); 62 | } 63 | } -------------------------------------------------------------------------------- /MBedwarsTweaks/src/main/java/me/metallicgoat/tweaksaddon/tweaks/advancedswords/ReplaceSwordOnBuy.java: -------------------------------------------------------------------------------- 1 | package me.metallicgoat.tweaksaddon.tweaks.advancedswords; 2 | 3 | import de.marcely.bedwars.api.event.player.PlayerBuyInShopEvent; 4 | import de.marcely.bedwars.api.game.shop.product.ItemShopProduct; 5 | import de.marcely.bedwars.api.game.shop.product.ShopProduct; 6 | import me.metallicgoat.tweaksaddon.config.SwordsToolsConfig; 7 | import org.bukkit.entity.Player; 8 | import org.bukkit.event.EventHandler; 9 | import org.bukkit.event.EventPriority; 10 | import org.bukkit.event.Listener; 11 | import org.bukkit.inventory.ItemStack; 12 | import org.bukkit.inventory.PlayerInventory; 13 | 14 | public class ReplaceSwordOnBuy implements Listener { 15 | 16 | @EventHandler(priority = EventPriority.HIGH) 17 | public void onSwordBuy(PlayerBuyInShopEvent event) { 18 | if (!SwordsToolsConfig.replace_sword_on_buy_enabled || !event.getProblems().isEmpty()) 19 | return; 20 | 21 | final Player player = event.getPlayer(); 22 | final PlayerInventory pi = player.getInventory(); 23 | 24 | // Checks if player bought a sword 25 | for (ShopProduct rawProduct : event.getItem().getProducts()) { 26 | if (!(rawProduct instanceof ItemShopProduct)) 27 | continue; 28 | 29 | final ItemStack[] givenAll = ((ItemShopProduct) rawProduct).getItemStacks(); 30 | 31 | for (ItemStack given : givenAll) { 32 | if (!ToolSwordHelper.isSword(given.getType()) || !ToolSwordHelper.isNotToIgnore(given)) 33 | continue; 34 | 35 | // Clear Wooden Swords 36 | // TODO check ignore list for wood swords 37 | if (!SwordsToolsConfig.replace_sword_on_buy_all_type) { 38 | pi.remove(ToolSwordHelper.WOOD_SWORD); 39 | break; 40 | } 41 | 42 | final ItemStack[] contents = pi.getContents(); 43 | 44 | for (int i=0; i getDragons(Arena arena, Team team) { 22 | return DragonUtil.getDragons(arena, team); 23 | } 24 | 25 | @Override 26 | public GenTierState getGenTierState(Arena arena) { 27 | return GenTiers.getState(arena); 28 | } 29 | 30 | @Override 31 | public void registerGenTierHandler(GenTierHandler handler) { 32 | Util.registerGenTierHandler(handler); 33 | } 34 | 35 | @Override 36 | public void unregisterGenTierHandler(String id) { 37 | Util.unregisterGenTierHandler(id); 38 | } 39 | 40 | @Override 41 | public GenTierHandler getGenTierHandlerById(String id) { 42 | return Util.getGenTierHandlerById(id); 43 | } 44 | 45 | @Override 46 | public Collection getGenTierHandlers() { 47 | return Util.getGenTierHandlers(); 48 | } 49 | 50 | @Override 51 | public Collection getGenTierLevels() { 52 | return GenTiersConfig.gen_tier_levels.values(); 53 | } 54 | 55 | @Override 56 | public GenTierLevel getGenTierLevel(int lvl) { 57 | return GenTiersConfig.gen_tier_levels.get(lvl); 58 | } 59 | 60 | @Override 61 | public UpgradeTriggerHandler getSuddenDeathUpgrade() { 62 | return SuddenDeathUpgrade.INSTANCE; 63 | } 64 | 65 | @Override 66 | public void reloadGenTierConfig() { 67 | GenTiersConfig.load(); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /MBedwarsTweaks/src/main/java/me/metallicgoat/tweaksaddon/tweaks/messages/CustomBedBreakMessage.java: -------------------------------------------------------------------------------- 1 | package me.metallicgoat.tweaksaddon.tweaks.messages; 2 | 3 | import de.marcely.bedwars.api.BedwarsAPI; 4 | import de.marcely.bedwars.api.arena.Arena; 5 | import de.marcely.bedwars.api.arena.Team; 6 | import de.marcely.bedwars.api.event.arena.ArenaBedBreakEvent; 7 | import de.marcely.bedwars.api.message.Message; 8 | import me.metallicgoat.tweaksaddon.config.MainConfig; 9 | import org.bukkit.ChatColor; 10 | import org.bukkit.entity.Player; 11 | import org.bukkit.event.EventHandler; 12 | import org.bukkit.event.Listener; 13 | 14 | public class CustomBedBreakMessage implements Listener { 15 | 16 | @EventHandler 17 | public void onBedBreak(ArenaBedBreakEvent event) { 18 | if (!MainConfig.custom_bed_break_message_enabled) 19 | return; 20 | 21 | final Arena arena = event.getArena(); 22 | final Team team = event.getTeam(); 23 | final Player destroyer = event.getPlayer(); 24 | 25 | event.setPlayingSound(true); 26 | 27 | // Send our overriding custom title 28 | if (MainConfig.bed_destroy_title_enabled) { 29 | event.setSendingTitle(false); 30 | 31 | for (Player p : arena.getPlayersInTeam(team)) { 32 | BedwarsAPI.getNMSHelper().showTitle(p, 33 | Message.build(MainConfig.bed_destroy_title).done(), 34 | Message.build(MainConfig.bed_destroy_subtitle).done(), 35 | 60, 15, 15); 36 | } 37 | } 38 | 39 | // Send public message 40 | if (destroyer == null) 41 | return; 42 | 43 | final String teamName = team.getDisplayName(); 44 | final String playerName = BedwarsAPI.getHelper().getPlayerDisplayName(destroyer); 45 | final String destroyerColor = arena.getPlayerTeam(destroyer) != null ? String.valueOf(arena.getPlayerTeam(destroyer).getBungeeChatColor()) : ""; 46 | final String destroyerTeam = arena.getPlayerTeam(destroyer) != null ? ChatColor.stripColor(arena.getPlayerTeam(destroyer).getDisplayName()) : ""; 47 | 48 | final Message message = Message.build(MainConfig.custom_bed_break_message) 49 | .placeholder("team-name", teamName) 50 | .placeholder("team-color", String.valueOf(team.getBungeeChatColor())) 51 | .placeholder("destroyer-name", playerName) 52 | .placeholder("destroyer-team-name", destroyerTeam) 53 | .placeholder("destroyer-color", destroyerColor); 54 | 55 | event.setChatMessage(message); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /MBedwarsTweaks/src/main/java/me/metallicgoat/tweaksaddon/utils/CachedArenaIdentifier.java: -------------------------------------------------------------------------------- 1 | package me.metallicgoat.tweaksaddon.utils; 2 | 3 | import de.marcely.bedwars.api.GameAPI; 4 | import de.marcely.bedwars.api.arena.Arena; 5 | import de.marcely.bedwars.api.arena.picker.ArenaPickerAPI; 6 | import de.marcely.bedwars.api.arena.picker.condition.ArenaCondition; 7 | import java.util.Collection; 8 | import java.util.Collections; 9 | import java.util.stream.Collectors; 10 | import lombok.Getter; 11 | 12 | /** 13 | * This class is used to cache the arena conditions. 14 | * It is used to avoid parsing the condition every time we need to check if an arena is included. 15 | * Handy for some configs + support for "ALL-ARENAS" from the old tweaks era 16 | */ 17 | public class CachedArenaIdentifier { 18 | 19 | @Getter 20 | private final String originalString; 21 | 22 | private boolean cached = false; 23 | 24 | private final boolean allArenas; 25 | private Arena arena; 26 | private ArenaCondition arenaCondition; 27 | 28 | public CachedArenaIdentifier(String originalString) { 29 | this.originalString = originalString; 30 | this.allArenas = originalString.equalsIgnoreCase("ALL-ARENAS"); 31 | } 32 | 33 | public boolean includes(Arena arena) { 34 | cacheIfNeeded(); 35 | 36 | return this.allArenas || (this.arena != null && this.arena == arena) || (this.arenaCondition != null && this.arenaCondition.check(arena)); 37 | } 38 | 39 | public Collection getArenas() { 40 | cacheIfNeeded(); 41 | 42 | if (this.allArenas) 43 | return GameAPI.get().getArenas(); 44 | 45 | if (this.arena != null) 46 | return Collections.singleton(this.arena); 47 | 48 | if (this.arenaCondition != null) { 49 | return GameAPI.get().getArenas().stream() 50 | .filter(arena -> this.arenaCondition.check(arena)) 51 | .collect(Collectors.toList()); 52 | } 53 | 54 | return Collections.emptyList(); 55 | } 56 | 57 | private void cacheIfNeeded() { 58 | if (this.cached || this.allArenas) 59 | return; 60 | 61 | this.cached = true; 62 | 63 | final Arena arenaByName = GameAPI.get().getArenaByName(this.originalString); 64 | 65 | if (arenaByName != null) { 66 | this.arena = arenaByName; 67 | 68 | } else { 69 | try { 70 | arenaCondition = ArenaPickerAPI.get().parseCondition(this.originalString); 71 | 72 | } catch (Exception ignored) { 73 | } 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /MBedwarsTweaks/src/main/java/me/metallicgoat/tweaksaddon/tweaks/spawners/DisableEmptyGenerators.java: -------------------------------------------------------------------------------- 1 | package me.metallicgoat.tweaksaddon.tweaks.spawners; 2 | 3 | 4 | import de.marcely.bedwars.api.arena.Arena; 5 | import de.marcely.bedwars.api.arena.Team; 6 | import de.marcely.bedwars.api.event.arena.RoundStartEvent; 7 | import de.marcely.bedwars.api.event.arena.TeamEliminateEvent; 8 | import de.marcely.bedwars.api.game.spawner.Spawner; 9 | import de.marcely.bedwars.api.game.spawner.SpawnerDurationModifier; 10 | import de.marcely.bedwars.tools.location.XYZYP; 11 | import me.metallicgoat.tweaksaddon.MBedwarsTweaksPlugin; 12 | import me.metallicgoat.tweaksaddon.config.MainConfig; 13 | import org.bukkit.Location; 14 | import org.bukkit.event.EventHandler; 15 | import org.bukkit.event.Listener; 16 | 17 | public class DisableEmptyGenerators implements Listener { 18 | 19 | @EventHandler 20 | public void onRoundStart(RoundStartEvent event) { 21 | if (!MainConfig.disable_empty_generators) 22 | return; 23 | 24 | final Arena arena = event.getArena(); 25 | 26 | for (Team team : arena.getEnabledTeams()) { 27 | if (arena.getPlayersInTeam(team).isEmpty()) { 28 | disableGens(arena, team, false); 29 | } 30 | } 31 | } 32 | 33 | @EventHandler 34 | public void onEliminate(TeamEliminateEvent event){ 35 | if (!MainConfig.disable_eliminated_team_generators) 36 | return; 37 | 38 | final Arena arena = event.getArena(); 39 | 40 | disableGens(arena, event.getTeam(), true); 41 | } 42 | 43 | private void disableGens(Arena arena, Team team, boolean teamElimination) { 44 | final XYZYP spawnXYZP = arena.getTeamSpawn(team); 45 | 46 | if (spawnXYZP == null) 47 | return; 48 | 49 | final Location spawnPoint = spawnXYZP.toLocation(arena.getGameWorld()); 50 | 51 | for (Spawner spawner : arena.getSpawners()) { 52 | 53 | // If the spawner is in the whitelist, we do not disable it. 54 | if (!MainConfig.disable_empty_generators_spawners.contains(spawner.getDropType())) 55 | continue; 56 | 57 | final Location spawnerLoc = spawner.getLocation().toLocation(arena.getGameWorld()); 58 | 59 | if (spawnerLoc.distanceSquared(spawnPoint) < MainConfig.disable_empty_generators_range * MainConfig.disable_empty_generators_range) { 60 | spawner.addDropDurationModifier( 61 | teamElimination ? "TEAM_ELIMINATED_DISABLED": "EMPTY_TEAM_DISABLED", 62 | MBedwarsTweaksPlugin.getInstance(), SpawnerDurationModifier.Operation.SET, 999999 63 | ); 64 | } 65 | } 66 | } 67 | } 68 | 69 | -------------------------------------------------------------------------------- /MBedwarsTweaks/src/main/java/me/metallicgoat/tweaksaddon/utils/UpdateChecker.java: -------------------------------------------------------------------------------- 1 | package me.metallicgoat.tweaksaddon.utils; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.InputStreamReader; 5 | import java.net.HttpURLConnection; 6 | import java.net.URL; 7 | import java.util.regex.Matcher; 8 | import java.util.regex.Pattern; 9 | 10 | public class UpdateChecker { 11 | 12 | public static void checkForUpdate(String currentVersion) { 13 | try { 14 | final URL url = new URL("https://api.github.com/repos/MetallicGoat/MBedwarsTweaks/releases/latest"); 15 | final HttpURLConnection con = (HttpURLConnection) url.openConnection(); 16 | con.setRequestMethod("GET"); 17 | 18 | final BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream())); 19 | final StringBuilder response = new StringBuilder(); 20 | 21 | String inputLine; 22 | 23 | while ((inputLine = in.readLine()) != null) 24 | response.append(inputLine); 25 | 26 | in.close(); 27 | con.disconnect(); 28 | 29 | final String latestVersion = parseVersion(response.toString()); 30 | 31 | if (latestVersion == null) { 32 | printFail(); 33 | return; 34 | } 35 | 36 | if (!latestVersion.equals(currentVersion)) 37 | printNewUpdate(latestVersion); 38 | 39 | } catch (Exception e) { 40 | printFail(); 41 | } 42 | } 43 | 44 | private static void printNewUpdate(String newVersion) { 45 | Console.printWarn( 46 | "-----------------------------------------------------------------", 47 | "We found an update! Version " + newVersion + " is available for download here:", 48 | "https://github.com/MetallicGoat/MBedwarsTweaks/releases/latest", 49 | "-----------------------------------------------------------------" 50 | ); 51 | } 52 | 53 | private static void printFail() { 54 | Console.printWarn( 55 | "-----------------------------------------------------------------", 56 | "Failed to check for Tweaks updates! Check your server's internet connection.", 57 | "Update checks on startup can be disabled in the config.yml", 58 | "-----------------------------------------------------------------" 59 | ); 60 | } 61 | 62 | private static String parseVersion(String jsonResponse) { 63 | final Pattern pattern = Pattern.compile("\"tag_name\":\"([^\"]+)\""); 64 | final Matcher matcher = pattern.matcher(jsonResponse); 65 | 66 | if (matcher.find()) 67 | return matcher.group(1).replace("v", ""); 68 | 69 | return null; 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /MBedwarsTweaks/src/main/java/me/metallicgoat/tweaksaddon/tweaks/misc/PlaceBlocksOnBed.java: -------------------------------------------------------------------------------- 1 | package me.metallicgoat.tweaksaddon.tweaks.misc; 2 | 3 | import de.marcely.bedwars.api.BedwarsAPI; 4 | import de.marcely.bedwars.api.arena.Arena; 5 | import de.marcely.bedwars.api.arena.Team; 6 | import de.marcely.bedwars.tools.PersistentBlockData; 7 | import me.metallicgoat.tweaksaddon.config.MainConfig; 8 | import org.bukkit.Bukkit; 9 | import org.bukkit.Material; 10 | import org.bukkit.block.Block; 11 | import org.bukkit.block.BlockFace; 12 | import org.bukkit.entity.Player; 13 | import org.bukkit.event.EventHandler; 14 | import org.bukkit.event.Listener; 15 | import org.bukkit.event.block.Action; 16 | import org.bukkit.event.block.BlockPlaceEvent; 17 | import org.bukkit.event.player.PlayerInteractEvent; 18 | import org.bukkit.inventory.ItemStack; 19 | 20 | public class PlaceBlocksOnBed implements Listener { 21 | 22 | @EventHandler 23 | public void onBlockPlace(PlayerInteractEvent event) { 24 | if (!MainConfig.allow_block_place_on_bed || event.getAction() != Action.RIGHT_CLICK_BLOCK || !event.isBlockInHand()) 25 | return; 26 | 27 | final Player player = event.getPlayer(); 28 | final ItemStack itemStack = event.getItem(); 29 | final Arena arena = BedwarsAPI.getGameAPI().getArenaByPlayer(player); 30 | final Team team = arena != null ? arena.getPlayerTeam(player) : null; 31 | final Block block = event.getClickedBlock(); 32 | final BlockFace face = event.getBlockFace(); 33 | 34 | if (arena == null || 35 | itemStack == null || 36 | !itemStack.getType().isBlock() || 37 | block == null || 38 | face == null || 39 | team == null || 40 | !block.getType().name().contains("BED")) 41 | return; 42 | 43 | final Block placeBlockLoc = block.getRelative(face); 44 | 45 | if (placeBlockLoc.getType() != Material.AIR || !arena.canPlaceBlockAt(placeBlockLoc)) 46 | return; 47 | 48 | // Dye the block (1.8 -> 1.12 support) 49 | final PersistentBlockData data = PersistentBlockData.fromMaterial(itemStack.getType()); 50 | 51 | // Place it 52 | data.getDyedData(team.getDyeColor()).place(placeBlockLoc, true); 53 | arena.setBlockPlayerPlaced(placeBlockLoc, true); 54 | itemStack.setAmount(itemStack.getAmount() - 1); // take item, as it not an actual event 55 | 56 | // Calls the bukkit event (for MBedwars & other plugins/addons) 57 | final BlockPlaceEvent placeEvent = new BlockPlaceEvent(placeBlockLoc, placeBlockLoc.getState(), block, itemStack, player, true); 58 | Bukkit.getPluginManager().callEvent(placeEvent); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /MBedwarsTweaks/src/main/java/me/metallicgoat/tweaksaddon/tweaks/misc/RemoveInvisOnDamage.java: -------------------------------------------------------------------------------- 1 | package me.metallicgoat.tweaksaddon.tweaks.misc; 2 | 3 | import de.marcely.bedwars.api.BedwarsAPI; 4 | import de.marcely.bedwars.api.GameAPI; 5 | import de.marcely.bedwars.api.arena.Arena; 6 | import de.marcely.bedwars.api.arena.Team; 7 | import java.util.UUID; 8 | import me.metallicgoat.tweaksaddon.config.MainConfig; 9 | import org.bukkit.Bukkit; 10 | import org.bukkit.entity.Entity; 11 | import org.bukkit.entity.EntityType; 12 | import org.bukkit.entity.Player; 13 | import org.bukkit.event.EventHandler; 14 | import org.bukkit.event.EventPriority; 15 | import org.bukkit.event.Listener; 16 | import org.bukkit.event.entity.EntityDamageByEntityEvent; 17 | import org.bukkit.event.entity.EntityDamageEvent; 18 | import org.bukkit.potion.PotionEffectType; 19 | 20 | public class RemoveInvisOnDamage implements Listener { 21 | 22 | @EventHandler(priority = EventPriority.HIGH) 23 | public void onEntityDamage(EntityDamageEvent event) { 24 | if (!MainConfig.remove_invis_ondamage_enabled || event.isCancelled() || event.getDamage() == 0) 25 | return; 26 | 27 | if (event.getEntity().getType() == EntityType.PLAYER) { 28 | final Player player = (Player) event.getEntity(); 29 | final Arena arena = BedwarsAPI.getGameAPI().getArenaByPlayer(player); 30 | 31 | // Is the damage what we be looking for??? 32 | if (arena != null && MainConfig.remove_invis_damge_causes.contains(event.getCause())) { 33 | boolean damagedCausedByTeam = false; 34 | 35 | // Is the damage from us or a team member??? 36 | if (event instanceof EntityDamageByEntityEvent) { 37 | final EntityDamageByEntityEvent damageByEntityEvent = (EntityDamageByEntityEvent) event; 38 | final Entity damager = damageByEntityEvent.getDamager(); 39 | 40 | // Get the owner of the fireball/tnt/gaurddog etc 41 | final UUID uuid = GameAPI.get().getCompanionOwner(damager); 42 | final Player damagerOwner = uuid != null ? Bukkit.getPlayer(uuid) : null; 43 | final Arena damagerArena = damagerOwner != null ? BedwarsAPI.getGameAPI().getArenaByPlayer(damagerOwner) : null; 44 | final Team damagerTeam = damagerArena != null ? damagerArena.getPlayerTeam(damagerOwner) : null; 45 | 46 | if (arena.getPlayerTeam(player) == damagerTeam) { 47 | damagedCausedByTeam = true; 48 | } 49 | } 50 | 51 | // Only remove if caused by non-team member 52 | if (!damagedCausedByTeam) { 53 | player.removePotionEffect(PotionEffectType.INVISIBILITY); 54 | } 55 | } 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /API/pom.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 4.0.0 6 | API 7 | jar 8 | 9 | 10 | me.metallicgoat.tweaksaddon 11 | MBedwarsTweaksParent 12 | 5.0.0-Beta2 13 | 14 | 15 | 16 | 17 | spigot-repo 18 | https://hub.spigotmc.org/nexus/content/repositories/snapshots/ 19 | 20 | 21 | mbedwars-repo 22 | https://repo.marcely.de/repository/maven-public/ 23 | 24 | 25 | placeholderapi 26 | https://repo.extendedclip.com/content/repositories/placeholderapi/ 27 | 28 | 29 | 30 | 31 | 32 | org.jetbrains 33 | annotations 34 | 26.0.2 35 | provided 36 | 37 | 38 | org.spigotmc 39 | spigot-api 40 | 1.12.2-R0.1-SNAPSHOT 41 | provided 42 | 43 | 44 | de.marcely.bedwars 45 | API 46 | 5.5.6-Beta3 47 | provided 48 | 49 | 50 | org.projectlombok 51 | lombok 52 | 1.18.32 53 | compile 54 | 55 | 56 | 57 | 58 | 8 59 | 8 60 | UTF-8 61 | 62 | 63 | 64 | 65 | 66 | org.apache.maven.plugins 67 | maven-source-plugin 68 | 3.3.1 69 | 70 | 71 | attach-sources 72 | verify 73 | 74 | jar-no-fork 75 | 76 | 77 | 78 | me/metallicgoat/tweaksaddon/api/unsafe/** 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /MBedwarsTweaks/src/main/java/me/metallicgoat/tweaksaddon/gentiers/dragons/DragonUtil.java: -------------------------------------------------------------------------------- 1 | package me.metallicgoat.tweaksaddon.gentiers.dragons; 2 | 3 | import de.marcely.bedwars.api.arena.Arena; 4 | import de.marcely.bedwars.api.arena.Team; 5 | import de.marcely.bedwars.api.game.spawner.Spawner; 6 | import de.marcely.bedwars.tools.location.XYZYP; 7 | import java.util.ArrayList; 8 | import java.util.Collections; 9 | import java.util.List; 10 | import java.util.concurrent.CopyOnWriteArrayList; 11 | import java.util.stream.Collectors; 12 | 13 | import me.metallicgoat.tweaksaddon.api.gentiers.SuddenDeathDragon; 14 | import me.metallicgoat.tweaksaddon.utils.Util; 15 | import org.bukkit.Location; 16 | import org.bukkit.World; 17 | import org.jetbrains.annotations.Nullable; 18 | 19 | public class DragonUtil { 20 | 21 | public static final List runningDragons = new CopyOnWriteArrayList<>(); 22 | 23 | // Find optimal spot to spawn the dwwwagoon 24 | public static @Nullable Location getDragonSpawn(Arena arena, World world, Team team) { 25 | if (team != null) { 26 | final XYZYP spawn = arena.getTeamSpawn(team); 27 | 28 | if (spawn != null) 29 | return spawn.toLocation(world).add(0, 30, 0); 30 | 31 | } else { 32 | final XYZYP spawn = arena.getSpectatorSpawn(); 33 | 34 | if (spawn != null && arena.isInside(spawn)) 35 | return spawn.toLocation(world); 36 | } 37 | 38 | return null; 39 | } 40 | 41 | public static List getRelevantStaticTargets(Arena arena, @Nullable Team team, World world) { 42 | final XYZYP teamSpawn = team != null ? arena.getTeamSpawn(team) : null; 43 | final List targets = new ArrayList<>(Util.getAllTeamSpawns(arena, world, team)); 44 | 45 | for (Spawner spawner : arena.getSpawners()) { 46 | final Location location = spawner.getLocation().toLocation(world); 47 | 48 | // ignore iron and gold spawners + spawners that are to close to the dragon's team's home base 49 | if (!spawner.getDropType().getId().equals("iron") && 50 | !spawner.getDropType().getId().equals("gold") && 51 | (teamSpawn == null || spawner.getLocation().toLocation(world).distance(teamSpawn.toLocation(world)) > 20)) 52 | targets.add(location); 53 | } 54 | 55 | return Collections.unmodifiableList(targets); 56 | } 57 | 58 | public static List getDragons(@Nullable Arena arena, @Nullable Team team) { 59 | if (arena == null) 60 | return Collections.unmodifiableList(runningDragons); 61 | 62 | return Collections.unmodifiableList(runningDragons.stream().filter((dragon -> team == null || dragon.getTeam() == team)).collect(Collectors.toList())); 63 | } 64 | 65 | public static void killAllDragons() { 66 | for (SuddenDeathDragonImpl task : new ArrayList<>(runningDragons)) 67 | task.remove(); 68 | 69 | runningDragons.clear(); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /MBedwarsTweaks/src/main/java/me/metallicgoat/tweaksaddon/tweaks/misc/LootDropAtEliminatedTeamBase.java: -------------------------------------------------------------------------------- 1 | package me.metallicgoat.tweaksaddon.tweaks.misc; 2 | 3 | import de.marcely.bedwars.api.arena.Arena; 4 | import de.marcely.bedwars.api.arena.Team; 5 | import de.marcely.bedwars.api.event.arena.TeamEliminateEvent; 6 | import de.marcely.bedwars.api.event.player.PlayerKillPlayerEvent; 7 | import de.marcely.bedwars.api.game.spawner.Spawner; 8 | import java.util.Comparator; 9 | import java.util.Optional; 10 | import me.metallicgoat.tweaksaddon.config.MainConfig; 11 | import org.bukkit.Location; 12 | import org.bukkit.World; 13 | import org.bukkit.entity.Player; 14 | import org.bukkit.event.EventHandler; 15 | import org.bukkit.event.Listener; 16 | import org.bukkit.inventory.Inventory; 17 | import org.bukkit.inventory.ItemStack; 18 | 19 | public class LootDropAtEliminatedTeamBase implements Listener { 20 | 21 | @EventHandler 22 | public void onEliminate(TeamEliminateEvent event) { 23 | final Team team = event.getTeam(); 24 | final Arena arena = event.getArena(); 25 | final Inventory inventory = arena.getTeamPrivateInventory(team); 26 | final World gameWorld = arena.getGameWorld(); 27 | 28 | if (gameWorld == null || inventory == null || !MainConfig.personal_team_loot_drop || event.causesEnd()) 29 | return; 30 | 31 | // Simply drop 32 | dropItemsOnGen(arena, inventory, gameWorld, team); 33 | } 34 | 35 | @EventHandler 36 | public void onFinalKill(PlayerKillPlayerEvent event) { 37 | final Arena arena = event.getArena(); 38 | final Player player = event.getPlayer(); 39 | final Team team = arena.getPlayerTeam(player); 40 | final Inventory inventory = arena.getPlayerPrivateInventory(player); 41 | 42 | if (!MainConfig.personal_loot_drop || !event.isFatalDeath() || inventory == null || 43 | inventory.getContents() == null || inventory.getContents().length == 0) 44 | return; 45 | 46 | // Checked all the If's above. 47 | dropItemsOnGen(arena, inventory, arena.getGameWorld(), team); 48 | } 49 | 50 | private void dropItemsOnGen(Arena arena, Inventory inventory, World gameWorld, Team team) { 51 | final Optional closestSpawner = arena.getSpawners().stream().min(Comparator.comparing(spawner1 -> spawner1.getLocation().distance(arena.getTeamSpawn(team)))); 52 | 53 | if (inventory.getContents() == null || inventory.getContents().length == 0 || !closestSpawner.isPresent()) 54 | return; 55 | 56 | final Location locationToDropItems = closestSpawner.get().getLocation().toLocation(gameWorld); 57 | 58 | for (ItemStack itemStack : inventory.getContents()) { 59 | if (itemStack == null || MainConfig.personal_loot_blocked_items.contains(itemStack.getType())) 60 | continue; 61 | 62 | // Naturally gives an authentic animation. 63 | gameWorld.dropItemNaturally(locationToDropItems, itemStack); 64 | } 65 | 66 | if (MainConfig.personal_team_loot_drop_strike_lightning_enabled) 67 | gameWorld.strikeLightningEffect(locationToDropItems); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /API/src/main/java/me/metallicgoat/tweaksaddon/api/events/gentiers/GenTiersScheduleEvent.java: -------------------------------------------------------------------------------- 1 | package me.metallicgoat.tweaksaddon.api.events.gentiers; 2 | 3 | import de.marcely.bedwars.api.arena.Arena; 4 | import de.marcely.bedwars.api.event.arena.ArenaEvent; 5 | import de.marcely.bedwars.tools.Validate; 6 | import java.time.Duration; 7 | import lombok.Getter; 8 | import lombok.Setter; 9 | import me.metallicgoat.tweaksaddon.api.gentiers.GenTierLevel; 10 | import me.metallicgoat.tweaksaddon.api.gentiers.GenTierState; 11 | import org.bukkit.event.Cancellable; 12 | import org.bukkit.event.Event; 13 | import org.bukkit.event.HandlerList; 14 | 15 | /** 16 | * Called when a gen tier upgrade is scheduled to occur in an arena. 17 | *

18 | * This occurs either when the arena starts or when a previous tier upgrade has completed. 19 | *

20 | */ 21 | public class GenTiersScheduleEvent extends Event implements ArenaEvent, Cancellable { 22 | 23 | private static final HandlerList HANDLERS = new HandlerList(); 24 | 25 | private final GenTierState arenaState; 26 | 27 | private GenTierLevel nextTier; 28 | private Duration delay; 29 | 30 | @Getter @Setter 31 | private boolean cancelled = false; 32 | 33 | public GenTiersScheduleEvent(GenTierState arenaState, GenTierLevel nextTier, Duration delay) { 34 | this.arenaState = arenaState; 35 | this.nextTier = nextTier; 36 | this.delay = delay; 37 | } 38 | 39 | @Override 40 | public Arena getArena() { 41 | return this.arenaState.getArena(); 42 | } 43 | 44 | /** 45 | * Get the state of the gen tiers in the arena. 46 | * 47 | * @return the current gen tier state of the arena 48 | */ 49 | public GenTierState getArenaState() { 50 | return this.arenaState; 51 | } 52 | 53 | /** 54 | * Get the next tier level that the arena will upgrade to. 55 | * 56 | * @return the next tier level to be applied after the delay 57 | */ 58 | public GenTierLevel getNextTier() { 59 | return this.nextTier; 60 | } 61 | 62 | /** 63 | * Sets the next tier level that the arena will upgrade to. 64 | * 65 | * @param nextTier the next tier level to set after the delay 66 | */ 67 | public void setNextTier(GenTierLevel nextTier) { 68 | Validate.notNull(nextTier, "nextTier"); 69 | 70 | this.nextTier = nextTier; 71 | } 72 | 73 | /** 74 | * Get the delay before the initial tier happens. 75 | * 76 | * @return the delay before the first tier upgrade 77 | */ 78 | public Duration getDelay() { 79 | return this.delay; 80 | } 81 | 82 | /** 83 | * Sets the delay before the initial tier happens. 84 | * 85 | * @param delay the delay to set 86 | */ 87 | public void setDelay(Duration delay) { 88 | Validate.notNull(delay, "delay"); 89 | 90 | this.delay = delay; 91 | } 92 | 93 | @Override 94 | public HandlerList getHandlers() { 95 | return HANDLERS; 96 | } 97 | 98 | public static HandlerList getHandlerList() { 99 | return HANDLERS; 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /MBedwarsTweaks/src/main/java/me/metallicgoat/tweaksaddon/tweaks/cosmetic/SpongeParticles.java: -------------------------------------------------------------------------------- 1 | package me.metallicgoat.tweaksaddon.tweaks.cosmetic; 2 | 3 | import de.marcely.bedwars.api.BedwarsAPI; 4 | import de.marcely.bedwars.api.arena.Arena; 5 | import de.marcely.bedwars.tools.VarParticle; 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | import me.metallicgoat.tweaksaddon.MBedwarsTweaksPlugin; 9 | import me.metallicgoat.tweaksaddon.config.MainConfig; 10 | import org.bukkit.Location; 11 | import org.bukkit.Material; 12 | import org.bukkit.block.Block; 13 | import org.bukkit.event.EventHandler; 14 | import org.bukkit.event.EventPriority; 15 | import org.bukkit.event.Listener; 16 | import org.bukkit.event.block.BlockPlaceEvent; 17 | import org.bukkit.scheduler.BukkitRunnable; 18 | 19 | public class SpongeParticles implements Listener { 20 | 21 | @EventHandler(priority = EventPriority.HIGHEST) 22 | public void onSpongePlace(BlockPlaceEvent e) { 23 | final Arena arena = BedwarsAPI.getGameAPI().getArenaByPlayer(e.getPlayer()); 24 | final Block block = e.getBlock(); 25 | 26 | if (!MainConfig.sponge_particles_enabled || 27 | e.isCancelled() || 28 | arena == null || 29 | arena.getGameWorld() == null || 30 | !block.getType().equals(Material.SPONGE)) 31 | return; 32 | 33 | new SpongeParticleTask(block).runTaskTimer(MBedwarsTweaksPlugin.getInstance(), 0L, 8L); 34 | } 35 | 36 | private static class SpongeParticleTask extends BukkitRunnable { 37 | 38 | private final Block block; 39 | private int radius = 1; 40 | 41 | public SpongeParticleTask(Block block) { 42 | this.block = block; 43 | } 44 | 45 | @Override 46 | public void run() { 47 | if (radius > 4) { 48 | cancel(); 49 | return; 50 | } 51 | 52 | for (Location location : getParticles(block.getLocation(), radius)) { 53 | VarParticle.PARTICLE_CLOUD.play(location); 54 | VarParticle.PARTICLE_CLOUD.play(location.add(.15, .15, .15)); 55 | } 56 | 57 | radius++; 58 | } 59 | 60 | @Override 61 | public void cancel() { 62 | if (MainConfig.sponge_particles_remove_sponge_after_complete 63 | && block.getType().name().contains("SPONGE")) { // SPONGE or WET_SPONGE (also changes across versions) 64 | 65 | block.setType(Material.AIR); 66 | } 67 | 68 | super.cancel(); 69 | } 70 | 71 | public List getParticles(Location start, int radius) { 72 | final List locations = new ArrayList<>(); 73 | 74 | for (double x = start.getX() - radius; x <= start.getX() + radius; x++) { 75 | for (double y = start.getY() - radius; y <= start.getY() + radius; y++) { 76 | for (double z = start.getZ() - radius; z <= start.getZ() + radius; z++) { 77 | final Location location = new Location(start.getWorld(), x + .5, y + .5, z + .5); 78 | 79 | if (location.getBlock().getType() == Material.AIR) 80 | locations.add(location); 81 | } 82 | } 83 | } 84 | 85 | return locations; 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /MBedwarsTweaks/src/main/java/me/metallicgoat/tweaksaddon/tweaks/misc/LockTeamChest.java: -------------------------------------------------------------------------------- 1 | package me.metallicgoat.tweaksaddon.tweaks.misc; 2 | 3 | import de.marcely.bedwars.api.GameAPI; 4 | import de.marcely.bedwars.api.arena.Arena; 5 | import de.marcely.bedwars.api.arena.ArenaStatus; 6 | import de.marcely.bedwars.api.arena.Team; 7 | import de.marcely.bedwars.api.event.player.PlayerOpenArenaChestEvent; 8 | import de.marcely.bedwars.api.message.Message; 9 | import de.marcely.bedwars.tools.location.XYZYP; 10 | import me.metallicgoat.tweaksaddon.config.MainConfig; 11 | import org.bukkit.Location; 12 | import org.bukkit.block.Block; 13 | import org.bukkit.entity.Player; 14 | import org.bukkit.event.EventHandler; 15 | import org.bukkit.event.Listener; 16 | import org.bukkit.event.block.Action; 17 | import org.bukkit.event.player.PlayerInteractEvent; 18 | import org.jetbrains.annotations.Nullable; 19 | 20 | public class LockTeamChest implements Listener { 21 | 22 | @EventHandler 23 | public void playerOpenArenaChest(PlayerOpenArenaChestEvent event) { 24 | if (!MainConfig.lock_team_chest_enabled) 25 | return; 26 | 27 | if (check(event.getPlayer(), event.getArena(), event.getTeam(), event.getChestBlock())) 28 | event.setCancelled(true); 29 | } 30 | 31 | @EventHandler 32 | public void playerInteract(PlayerInteractEvent event) { 33 | // in case the given material was configured to not be a personal chest, 34 | // but shall still be locked 35 | if (!MainConfig.lock_team_chest_enabled) 36 | return; 37 | if (event.getAction() != Action.RIGHT_CLICK_BLOCK) 38 | return; 39 | 40 | final Player player = event.getPlayer(); 41 | final Arena arena = GameAPI.get().getArenaByPlayer(player); 42 | 43 | if (arena == null || arena.getStatus() != ArenaStatus.RUNNING) 44 | return; 45 | 46 | final Team playerTeam = arena.getPlayerTeam(player); 47 | 48 | if (check(player, arena, playerTeam, event.getClickedBlock())) 49 | event.setCancelled(true); 50 | } 51 | 52 | private boolean check(Player player, Arena arena, Team playerTeam, Block block) { 53 | if (!MainConfig.lock_team_chest_materials.contains(block.getType())) 54 | return false; 55 | 56 | final Team chestTeam = getChestTeam(arena, block); 57 | 58 | if (chestTeam != null && !arena.getPlayersInTeam(chestTeam).isEmpty() && chestTeam != playerTeam) { 59 | Message.build(MainConfig.lock_team_chest_fail_open) 60 | .placeholder("team-name", chestTeam.getDisplayName()) 61 | .placeholder("team", chestTeam.getDisplayName()) 62 | .send(player); 63 | return true; 64 | } 65 | 66 | return false; 67 | } 68 | 69 | @Nullable 70 | private Team getChestTeam(Arena arena, Block chest) { 71 | if (arena.getGameWorld() == chest.getWorld()) { 72 | for (Team team : arena.getEnabledTeams()) { 73 | final XYZYP spawn = arena.getTeamSpawn(team); 74 | 75 | if (spawn != null) { 76 | final Location bukkitSpawn = spawn.toLocation(arena.getGameWorld()); 77 | 78 | if (MainConfig.lock_team_chest_range >= bukkitSpawn.distance(chest.getLocation())) { 79 | return team; 80 | } 81 | } 82 | } 83 | } 84 | 85 | return null; 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /API/src/main/java/me/metallicgoat/tweaksaddon/api/events/gentiers/SuddenDeathDragonTargetEvent.java: -------------------------------------------------------------------------------- 1 | package me.metallicgoat.tweaksaddon.api.events.gentiers; 2 | 3 | import de.marcely.bedwars.api.arena.Arena; 4 | import de.marcely.bedwars.api.event.arena.ArenaEvent; 5 | import de.marcely.bedwars.tools.Validate; 6 | import lombok.Getter; 7 | import lombok.Setter; 8 | import me.metallicgoat.tweaksaddon.api.gentiers.SuddenDeathDragon; 9 | import org.bukkit.Location; 10 | import org.bukkit.entity.Entity; 11 | import org.bukkit.event.Cancellable; 12 | import org.bukkit.event.Event; 13 | import org.bukkit.event.HandlerList; 14 | import org.jetbrains.annotations.Nullable; 15 | 16 | public class SuddenDeathDragonTargetEvent extends Event implements ArenaEvent, Cancellable { 17 | 18 | private static final HandlerList HANDLERS = new HandlerList(); 19 | 20 | @Getter 21 | private final Arena arena; 22 | @Getter 23 | private final SuddenDeathDragon dragon; 24 | @Getter 25 | private Entity targetEntity; 26 | @Getter 27 | private final Entity previousTargetEntity; 28 | @Getter 29 | private final boolean previouslyTargetingEntity; 30 | @Getter 31 | private boolean targetingEntity; 32 | @Getter 33 | private Location targetLocation; 34 | @Getter 35 | private final Location previousTargetLocation; 36 | @Getter @Setter 37 | private boolean cancelled = false; 38 | 39 | public SuddenDeathDragonTargetEvent( 40 | Arena arena, 41 | SuddenDeathDragon dragon, 42 | @Nullable Entity targetEntity, 43 | Location targetLocation, 44 | Location previousTargetLocation, 45 | Entity previousTargetEntity, 46 | boolean previouslyTargetingEntity 47 | ) { 48 | this.arena = arena; 49 | this.dragon = dragon; 50 | this.targetEntity = targetEntity; 51 | this.targetLocation = targetLocation; 52 | this.previousTargetLocation = previousTargetLocation; 53 | this.previousTargetEntity = previousTargetEntity; 54 | this.previouslyTargetingEntity = previouslyTargetingEntity; 55 | } 56 | 57 | /** 58 | * Change the entity which the dragon is targeting 59 | * NOTE: The entity must be in the same world as the dragon 60 | * 61 | * @param targetEntity to target 62 | */ 63 | public void setTargetEntity(Entity targetEntity) { 64 | Validate.isTrue(targetEntity == null || (targetEntity.isValid() && targetEntity.getWorld() == this.dragon.getDragon().getWorld()), "Target entity must be in the same world as the dragon"); 65 | 66 | this.targetEntity = targetEntity; 67 | this.targetLocation = targetEntity.getLocation(); 68 | } 69 | 70 | /** 71 | * Change the location which the dragon is targeting 72 | * NOTE: The location must be in the same world as the dragon 73 | * 74 | * @param targetLocation to target 75 | */ 76 | public void setTargetLocation(Location targetLocation) { 77 | Validate.isTrue(targetLocation == null || targetLocation.getWorld() == this.dragon.getDragon().getWorld(), "Target location must be as the dragon's world"); 78 | 79 | this.targetLocation = targetLocation; 80 | } 81 | 82 | 83 | @Override 84 | public HandlerList getHandlers() { 85 | return HANDLERS; 86 | } 87 | 88 | public static HandlerList getHandlerList() { 89 | return HANDLERS; 90 | } 91 | } -------------------------------------------------------------------------------- /MBedwarsTweaks/src/main/java/me/metallicgoat/tweaksaddon/config/SwordsToolsConfig.java: -------------------------------------------------------------------------------- 1 | package me.metallicgoat.tweaksaddon.config; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Arrays; 5 | import java.util.List; 6 | import me.metallicgoat.tweaksaddon.config.ConfigManager.Config; 7 | import org.bukkit.Material; 8 | 9 | public class SwordsToolsConfig { 10 | 11 | @Config( 12 | description = { 13 | "Items that cannot be placed inside chests" 14 | } 15 | ) 16 | public static boolean anti_chest_enabled = false; 17 | @Config public static List anti_chest_materials = new ArrayList<>(MainConfig.getDefaultMaterials()); 18 | 19 | @Config( 20 | description = { 21 | "Items that cannot be dropped on the ground" 22 | } 23 | ) 24 | public static boolean anti_drop_enabled = true; 25 | @Config public static List anti_drop_materials = new ArrayList<>(MainConfig.getDefaultMaterials()); 26 | 27 | @Config( 28 | description = { 29 | "When you die with a tool, you will get one tier lower when you respawn", 30 | "WARNING: May not work properly with keep-on-death enabled" 31 | } 32 | ) 33 | public static boolean degrading_buygroups_enabled = false; 34 | @Config public static List degrading_buygroups = new ArrayList<>(Arrays.asList("pickaxe", "axe")); 35 | 36 | @Config( 37 | description = { 38 | "With this feature enabled players can only have one tool of a specific type at a time", 39 | "Players will not be able to downgrade their tool if the is enabled", 40 | "If force ordered is true, players MUST buy every tier in order" 41 | } 42 | ) 43 | public static boolean advanced_tool_replacement_enabled = false; 44 | @Config public static boolean advanced_tool_replacement_force_ordered = false; 45 | @Config public static String advanced_tool_replacement_force_ordered_problem = "&cYou need to have a previous tier first"; 46 | @Config public static List advanced_tool_replacement_buygroups = new ArrayList<>(Arrays.asList("pickaxe", "axe")); 47 | 48 | @Config( 49 | description = { 50 | "Removes a Wooden-Sword if you buy a better sword", 51 | "If 'all-type' is set to TRUE, ALL sword types will get replaced", 52 | "If false, only wooden swords will get replaced (Like Hypixel)" 53 | } 54 | ) 55 | public static boolean replace_sword_on_buy_enabled = false; 56 | @Config public static boolean replace_sword_on_buy_all_type = false; 57 | 58 | @Config( 59 | description = { 60 | "Chest: If you add your sword to a chest, and have no other sword, you will be given a wooden sword (Like Hypixel)", 61 | "Drop: Gives players a Wooden Sword if no sword is detected, after they drop a sword (Like Hypixel)" 62 | } 63 | ) 64 | public static boolean always_sword_chest_enabled = false; 65 | @Config public static boolean always_sword_drop_enabled = false; 66 | 67 | @Config( 68 | description = { 69 | "Add Items here that you do not want to be effected by Advanced Swords and Tools", 70 | "For example, A CUSTOM special item that is Golden Sword", 71 | "ADD ITEMS BY THEIR DISPLAY NAME (DO NOT include color codes)" 72 | } 73 | ) 74 | public static List tools_swords_do_not_effect = new ArrayList<>(); 75 | 76 | } 77 | -------------------------------------------------------------------------------- /MBedwarsTweaks/src/main/java/me/metallicgoat/tweaksaddon/tweaks/spectialitems/SpecialItemCooldown.java: -------------------------------------------------------------------------------- 1 | package me.metallicgoat.tweaksaddon.tweaks.spectialitems; 2 | 3 | import de.marcely.bedwars.api.event.player.PlayerUseSpecialItemEvent; 4 | import de.marcely.bedwars.tools.NMSHelper; 5 | import java.time.Instant; 6 | import java.util.HashMap; 7 | import java.util.Map; 8 | import java.util.UUID; 9 | import lombok.AllArgsConstructor; 10 | import lombok.EqualsAndHashCode; 11 | import me.metallicgoat.tweaksaddon.MBedwarsTweaksPlugin; 12 | import me.metallicgoat.tweaksaddon.config.MainConfig; 13 | import org.bukkit.Bukkit; 14 | import org.bukkit.Material; 15 | import org.bukkit.entity.HumanEntity; 16 | import org.bukkit.entity.Player; 17 | import org.bukkit.event.EventHandler; 18 | import org.bukkit.event.EventPriority; 19 | import org.bukkit.event.Listener; 20 | import org.bukkit.inventory.ItemStack; 21 | 22 | public class SpecialItemCooldown implements Listener { 23 | 24 | private final Map cooldowns = new HashMap<>(); 25 | 26 | @EventHandler(priority = EventPriority.LOW) 27 | public void onSpecialItemUse(PlayerUseSpecialItemEvent event) { 28 | final Player player = event.getPlayer(); 29 | final UUID uuid = player.getUniqueId(); 30 | final String itemId = event.getSpecialItem().getId(); 31 | 32 | // Try item specific value 33 | Double customCooldown = MainConfig.special_items_custom_cooldowns.get(itemId); 34 | 35 | // Fall back on default value 36 | if (customCooldown == null) 37 | customCooldown = MainConfig.special_items_cooldown; 38 | 39 | // No cooldown 40 | if (customCooldown <= 0D) 41 | return; 42 | 43 | final CooldownEntry entry = new CooldownEntry(uuid, itemId); 44 | final Instant now = Instant.now(); 45 | 46 | // Check existing cooldown 47 | // Use instants to avoid issues with low TPS 48 | { 49 | final Instant elapsesTime = this.cooldowns.computeIfPresent(entry, (g0, time) -> { 50 | return now.isAfter(time) ? null : time; 51 | }); 52 | 53 | if (elapsesTime != null) { 54 | event.setCancelled(true); 55 | return; 56 | } 57 | } 58 | 59 | // Apply coolown 60 | final Instant elapsesTime = now.plusMillis((long) (customCooldown * 1000D)); 61 | 62 | this.cooldowns.put(entry, elapsesTime); 63 | setVisualCooldown(player, event.getSpecialItem().getItemStack(), customCooldown); 64 | 65 | Bukkit.getScheduler().runTaskLater(MBedwarsTweaksPlugin.getInstance(), () -> 66 | this.cooldowns.remove(entry, elapsesTime /* important */), 67 | (long) (20D * customCooldown)); 68 | } 69 | 70 | private static void setVisualCooldown(Player player, ItemStack itemStack, double cooldownSeconds) { 71 | if (NMSHelper.get().getVersion() >= 12) { 72 | try { 73 | final int cooldownTicks = (int) (cooldownSeconds * 20); 74 | 75 | HumanEntity.class.getMethod("setCooldown", Material.class, int.class).invoke( 76 | player, 77 | itemStack.getType(), 78 | cooldownTicks 79 | ); 80 | 81 | } catch (Exception e) { 82 | e.printStackTrace(); 83 | } 84 | } 85 | } 86 | 87 | 88 | @AllArgsConstructor 89 | @EqualsAndHashCode 90 | private static class CooldownEntry { 91 | 92 | private final UUID playerUUID; 93 | private final String specialItemId; 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /MBedwarsTweaks/src/main/java/me/metallicgoat/tweaksaddon/tweaks/explosives/ExplosiveFallDamageMultiplier.java: -------------------------------------------------------------------------------- 1 | package me.metallicgoat.tweaksaddon.tweaks.explosives; 2 | 3 | import de.marcely.bedwars.api.GameAPI; 4 | import de.marcely.bedwars.api.arena.Arena; 5 | import de.marcely.bedwars.api.event.player.PlayerQuitArenaEvent; 6 | import java.util.IdentityHashMap; 7 | import me.metallicgoat.tweaksaddon.MBedwarsTweaksPlugin; 8 | import me.metallicgoat.tweaksaddon.config.MainConfig; 9 | import org.bukkit.Bukkit; 10 | import org.bukkit.entity.EntityType; 11 | import org.bukkit.entity.Explosive; 12 | import org.bukkit.entity.Player; 13 | import org.bukkit.event.EventHandler; 14 | import org.bukkit.event.Listener; 15 | import org.bukkit.event.entity.EntityDamageByEntityEvent; 16 | import org.bukkit.event.entity.EntityDamageEvent; 17 | import org.bukkit.scheduler.BukkitTask; 18 | 19 | import java.util.Map; 20 | 21 | public class ExplosiveFallDamageMultiplier implements Listener { 22 | 23 | private final Map explodedPlayers = new IdentityHashMap<>(); 24 | 25 | @EventHandler 26 | public void onDamage(EntityDamageEvent event) { 27 | if (event.getCause() != EntityDamageEvent.DamageCause.FALL || !(event.getEntity() instanceof Player)) 28 | return; 29 | 30 | final Player player = (Player) event.getEntity(); 31 | 32 | if (!this.explodedPlayers.containsKey(player)) 33 | return; 34 | 35 | final ExplodeInfo info = this.explodedPlayers.remove(player); 36 | final boolean isFireball = info.isFireball; 37 | 38 | info.removeTask.cancel(); 39 | 40 | if (isFireball) 41 | event.setDamage(event.getDamage() * MainConfig.fireball_fall_damage_multiplier); 42 | else 43 | event.setDamage(event.getDamage() * MainConfig.tnt_fall_damage_multiplier); 44 | } 45 | 46 | @EventHandler 47 | public void onPlayerQuit(PlayerQuitArenaEvent event) { 48 | final ExplodeInfo explodeInfo = this.explodedPlayers.remove(event.getPlayer()); 49 | 50 | if (explodeInfo != null) 51 | explodeInfo.removeTask.cancel(); 52 | } 53 | 54 | @EventHandler 55 | public void onEntityDamageByEntityEvent(EntityDamageByEntityEvent event) { 56 | if (!(event.getDamager() instanceof Explosive) || !(event.getEntity() instanceof Player)) 57 | return; 58 | 59 | final Player player = (Player) event.getEntity(); 60 | final Arena arena = GameAPI.get().getArenaByPlayer(player); 61 | final boolean isFireBall = event.getDamager().getType() == EntityType.FIREBALL; 62 | 63 | // Arena is null, or feature not enabled 64 | if (arena == null || (isFireBall && MainConfig.fireball_fall_damage_multiplier == 1) || (!isFireBall && MainConfig.tnt_fall_damage_multiplier == 1)) 65 | return; 66 | 67 | // Reset the timer if its already going 68 | if (this.explodedPlayers.containsKey(player)) 69 | this.explodedPlayers.remove(player).removeTask.cancel(); 70 | 71 | final BukkitTask removeTask = Bukkit.getScheduler().runTaskLater(MBedwarsTweaksPlugin.getInstance(), () -> this.explodedPlayers.remove(player), 8 * 20); 72 | this.explodedPlayers.put(player, new ExplodeInfo(isFireBall, removeTask)); 73 | } 74 | 75 | private static class ExplodeInfo { 76 | final boolean isFireball; 77 | final BukkitTask removeTask; 78 | 79 | ExplodeInfo(boolean isFireball, BukkitTask removeTask) { 80 | this.isFireball = isFireball; 81 | this.removeTask = removeTask; 82 | } 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /MBedwarsTweaks/src/main/java/me/metallicgoat/tweaksaddon/tweaks/cosmetic/HealPoolParticles.java: -------------------------------------------------------------------------------- 1 | package me.metallicgoat.tweaksaddon.tweaks.cosmetic; 2 | 3 | import de.marcely.bedwars.api.arena.Arena; 4 | import de.marcely.bedwars.api.arena.ArenaStatus; 5 | import de.marcely.bedwars.api.arena.Team; 6 | import de.marcely.bedwars.api.event.player.PlayerBuyUpgradeEvent; 7 | import de.marcely.bedwars.api.game.upgrade.UpgradeTriggerHandler; 8 | import de.marcely.bedwars.api.game.upgrade.UpgradeTriggerHandlerType; 9 | import de.marcely.bedwars.tools.VarParticle; 10 | import de.marcely.bedwars.tools.location.XYZYP; 11 | import java.util.Collection; 12 | import me.metallicgoat.tweaksaddon.MBedwarsTweaksPlugin; 13 | import me.metallicgoat.tweaksaddon.config.MainConfig; 14 | import org.bukkit.Location; 15 | import org.bukkit.entity.Player; 16 | import org.bukkit.event.EventHandler; 17 | import org.bukkit.event.EventPriority; 18 | import org.bukkit.event.Listener; 19 | import org.bukkit.scheduler.BukkitRunnable; 20 | 21 | public class HealPoolParticles implements Listener { 22 | 23 | @EventHandler(priority = EventPriority.MONITOR) 24 | public void onUpgradeBuy(PlayerBuyUpgradeEvent event) { 25 | if (!MainConfig.heal_pool_particle_enabled || !event.getProblems().isEmpty() || MainConfig.heal_pool_particle_type == null) 26 | return; 27 | 28 | final UpgradeTriggerHandler handler = event.getUpgradeLevel().getTriggerHandler(); 29 | 30 | if (handler == null || handler.getType() != UpgradeTriggerHandlerType.HEAL_POOL) 31 | return; 32 | 33 | final Team team = event.getTeam(); 34 | final Arena arena = event.getArena(); 35 | final XYZYP teamSpawn = arena.getTeamSpawn(team); 36 | 37 | if (teamSpawn == null) 38 | return; 39 | 40 | final VarParticle particle = MainConfig.heal_pool_particle_type.clone(); 41 | final int volume = MainConfig.heal_pool_particle_range*3*2; 42 | final int count = Math.max(1, volume/4); 43 | 44 | particle.setOffset( 45 | MainConfig.heal_pool_particle_range, 46 | MainConfig.heal_pool_particle_range, 47 | MainConfig.heal_pool_particle_range 48 | ); 49 | particle.setCount(count); 50 | 51 | new HealPoolParticlesTask(arena, team, teamSpawn.toLocation(arena.getGameWorld()), particle).start(); 52 | } 53 | 54 | 55 | 56 | private static class HealPoolParticlesTask extends BukkitRunnable { 57 | 58 | private final Arena arena; 59 | private final Team team; 60 | private final Location teamSpawn; 61 | private final VarParticle particle; 62 | 63 | public HealPoolParticlesTask(Arena arena, Team team, Location teamSpawn, VarParticle particle) { 64 | this.arena = arena; 65 | this.team = team; 66 | this.teamSpawn = teamSpawn; 67 | this.particle = particle; 68 | } 69 | 70 | public void start() { 71 | if (this.arena.getStatus() == ArenaStatus.RUNNING) 72 | runTaskTimerAsynchronously(MBedwarsTweaksPlugin.getInstance(), 0L, 20L); 73 | } 74 | 75 | @Override 76 | public void run() { 77 | if (this.arena.getStatus() != ArenaStatus.RUNNING) { 78 | cancel(); 79 | return; 80 | } 81 | 82 | if (MainConfig.heal_pool_particle_team_view_only) { 83 | final Collection members = this.arena.getPlayersInTeam(this.team); 84 | 85 | for (Player member : members) 86 | this.particle.play(this.teamSpawn, member); 87 | 88 | } else { 89 | this.particle.play(this.teamSpawn); 90 | } 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /API/src/main/java/me/metallicgoat/tweaksaddon/api/gentiers/GenTierLevel.java: -------------------------------------------------------------------------------- 1 | package me.metallicgoat.tweaksaddon.api.gentiers; 2 | 3 | import de.marcely.bedwars.api.GameAPI; 4 | import de.marcely.bedwars.api.arena.Arena; 5 | import de.marcely.bedwars.api.game.spawner.DropType; 6 | import de.marcely.bedwars.api.message.Message; 7 | import java.time.Duration; 8 | import lombok.AllArgsConstructor; 9 | import lombok.Data; 10 | import me.metallicgoat.tweaksaddon.api.unsafe.MBedwarsTweaksAPILayer; 11 | import org.bukkit.Sound; 12 | import org.bukkit.entity.Player; 13 | import org.jetbrains.annotations.Nullable; 14 | 15 | @Data 16 | @AllArgsConstructor 17 | public class GenTierLevel { 18 | 19 | private final int tier; 20 | private final String tierName; // Display Name 21 | @Nullable 22 | private final String holoName; // Example '&eTier &cII' 23 | @Nullable 24 | private final String typeId; // Spawners with this drop-type should update 25 | private final GenTierHandler handler; // Action (eg bed break or upgrade) 26 | private final Duration time; // Time until the update happens (After Last Event) 27 | @Nullable 28 | private final Double speed; // New drop speed 29 | @Nullable 30 | private final Integer limit; // New drop speed 31 | @Nullable 32 | private final String earnMessage; // The chat message displayed on update 33 | @Nullable 34 | private final Sound earnSound; // Sound played when a tier is earned 35 | 36 | public GenTierLevel( 37 | int tier, 38 | String tierName, 39 | GenTierHandler handler, 40 | Duration time, 41 | @Nullable String earnMessage, 42 | @Nullable Sound earnSound) { 43 | 44 | this(tier, 45 | tierName, 46 | null, 47 | null, 48 | handler, 49 | time, 50 | null, 51 | null, 52 | earnMessage, 53 | earnSound); 54 | } 55 | 56 | /** 57 | * Plays the sound, and broadcasts the message of this gen tier. 58 | * Used when this level becomes active 59 | * 60 | * @param arena where this level is active on 61 | */ 62 | public void broadcastEarn(Arena arena) { 63 | if (this.earnSound != null) { 64 | for (Player p : arena.getPlayers()) 65 | p.playSound(p.getLocation(), this.earnSound, 1F, 1F); 66 | } 67 | 68 | if (this.earnMessage != null) 69 | arena.broadcast(Message.build(this.earnMessage)); 70 | 71 | } 72 | 73 | /** 74 | * Returns the DropType of the spawners this level will affect 75 | * Will return null is level does not affect as spawner (i.e. Bread break tier) 76 | * 77 | * @return the DropType this level aims to affect if applicable 78 | */ 79 | @Nullable 80 | public DropType getType() { 81 | return GameAPI.get().getDropTypeById(this.typeId); 82 | } 83 | 84 | /** 85 | * Gets the next level after this one has been reached. 86 | * 87 | * @return the next GenTierLevel, or null if this is the highest level 88 | */ 89 | @Nullable 90 | public GenTierLevel getNextLevel() { 91 | return MBedwarsTweaksAPILayer.INSTANCE.getGenTierLevel(this.tier + 1); 92 | } 93 | 94 | /** 95 | * Gets the previous level before this one has been reached. 96 | * 97 | * @return the previous GenTierLevel, or null if this is the first level 98 | */ 99 | @Nullable 100 | public GenTierLevel getPreviousLevel() { 101 | return MBedwarsTweaksAPILayer.INSTANCE.getGenTierLevel(this.tier - 1); 102 | } 103 | } -------------------------------------------------------------------------------- /API/src/main/java/me/metallicgoat/tweaksaddon/api/gentiers/GenTierState.java: -------------------------------------------------------------------------------- 1 | package me.metallicgoat.tweaksaddon.api.gentiers; 2 | 3 | import de.marcely.bedwars.api.arena.Arena; 4 | import de.marcely.bedwars.api.arena.Team; 5 | import java.time.Duration; 6 | import org.jetbrains.annotations.Nullable; 7 | 8 | /** 9 | * Represents the current state of the gen tier system in an arena. 10 | */ 11 | public interface GenTierState { 12 | 13 | /** 14 | * Get the arena this GenTierState belongs to. 15 | * 16 | * @return The arena this GenTierState belongs to. 17 | */ 18 | Arena getArena(); 19 | 20 | /** 21 | * Check if the gen tier system is currently active in this arena. 22 | * 23 | * @return true if the gen tier system is active, false otherwise. 24 | */ 25 | boolean isValid(); 26 | 27 | /** 28 | * Check whether a team has bought a team has bought the sudden-death upgrade. 29 | *

30 | * As a result, a dragon will be spawned for the team on sudden death. 31 | *

32 | * 33 | * @param team The team to check. 34 | * @return true if the team has bought the sudden-death upgrade, false otherwise. 35 | */ 36 | boolean hasBoughtDragon(Team team); 37 | 38 | /** 39 | * Set whether a team has bought the sudden-death upgrade. 40 | *

41 | * As a result, a dragon will be spawned for the team on sudden death. 42 | *

43 | * 44 | * @param team The team to set. 45 | * @param state The state to set. 46 | */ 47 | void setDragonBought(Team team, boolean state); 48 | 49 | /** 50 | * Get the remaining time until the next gen tier level is reached. 51 | *

52 | * Doesn't go below {@link Duration#ZERO}. Might stay at zero for a very short 53 | * time (max a few seconds) if the server is lagging and the scheduler didn't catch up yet. 54 | *

55 | * 56 | * @return The remaining time until the next gen tier level is reached, or null if there is no next gen tier level. 57 | */ 58 | @Nullable 59 | Duration getRemainingNextTier(); 60 | 61 | /** 62 | * Set the remaining time until the next gen tier level is reached. 63 | * 64 | * @param duration The duration to set 65 | * @throws IllegalStateException if there is no next gen tier level 66 | */ 67 | void setRemainingNextTier(Duration duration); 68 | 69 | /** 70 | * Get the tier level that already has been reached. 71 | * 72 | * @return the current gen tier level, or null if no gen tier level has been reached yet 73 | */ 74 | @Nullable 75 | GenTierLevel getCurrentTier(); 76 | 77 | /** 78 | * Get the next gen tier level that will be reached. 79 | * 80 | * @return the next gen tier level, or null if there is no next gen tier level 81 | */ 82 | @Nullable 83 | GenTierLevel getNextTier(); 84 | 85 | /** 86 | * Schedule the next gen tier level to be reached. 87 | * 88 | * @param level the next gen tier level to be reached 89 | */ 90 | void scheduleNextTier(GenTierLevel level); 91 | 92 | /** 93 | * Schedule the next gen tier level to be reached. 94 | * 95 | * @param level the next gen tier level to be reached 96 | * @param time the duration until the next gen tier level is reached 97 | */ 98 | void scheduleNextTier(GenTierLevel level, Duration time); 99 | 100 | /** 101 | * Cancel the current gen tier progression and stops any further. 102 | */ 103 | void cancelTiers(); 104 | } -------------------------------------------------------------------------------- /MBedwarsTweaks/src/main/java/me/metallicgoat/tweaksaddon/tweaks/misc/WorldBorderResize.java: -------------------------------------------------------------------------------- 1 | package me.metallicgoat.tweaksaddon.tweaks.misc; 2 | 3 | import de.marcely.bedwars.api.arena.Arena; 4 | import de.marcely.bedwars.api.arena.ArenaPersistentStorage; 5 | import de.marcely.bedwars.api.arena.ArenaStatus; 6 | import de.marcely.bedwars.api.arena.RegenerationType; 7 | import de.marcely.bedwars.api.event.arena.ArenaStatusChangeEvent; 8 | import de.marcely.bedwars.api.event.arena.ArenaUnloadEvent; 9 | import de.marcely.bedwars.api.event.arena.RoundStartEvent; 10 | import java.util.HashMap; 11 | import java.util.Map; 12 | import java.util.Optional; 13 | import me.metallicgoat.tweaksaddon.MBedwarsTweaksPlugin; 14 | import me.metallicgoat.tweaksaddon.config.MainConfig; 15 | import org.bukkit.Bukkit; 16 | import org.bukkit.WorldBorder; 17 | import org.bukkit.event.EventHandler; 18 | import org.bukkit.event.EventPriority; 19 | import org.bukkit.event.Listener; 20 | import org.bukkit.scheduler.BukkitTask; 21 | 22 | public class WorldBorderResize implements Listener { 23 | 24 | private static final String KEY_ORIGINAL_SIZE = "tweaks:world_border_original_size"; 25 | 26 | private final Map activeTasks = new HashMap<>(); 27 | 28 | @EventHandler 29 | public void onRoundStart(RoundStartEvent event) { 30 | start(event.getArena()); 31 | } 32 | 33 | @EventHandler(priority = EventPriority.MONITOR) 34 | public void onRoundStop(ArenaStatusChangeEvent event) { 35 | if (event.getNewStatus() != ArenaStatus.RUNNING) 36 | cancel(event.getArena()); 37 | } 38 | 39 | @EventHandler 40 | public void onArenaUnload(ArenaUnloadEvent event) { 41 | cancel(event.getArena()); 42 | } 43 | 44 | private void start(Arena arena) { 45 | if (!MainConfig.world_border_resize_enabled || arena.getRegenerationType() != RegenerationType.WORLD) 46 | return; 47 | if (arena.getGameWorld().getWorldBorder().getSize() >= 100_000) // probably vanilla border (disabled) 48 | return; 49 | 50 | cancel(arena); 51 | 52 | final BukkitTask scheduler = Bukkit.getScheduler().runTaskLater( 53 | MBedwarsTweaksPlugin.getInstance(), 54 | () -> resize(arena), 55 | 20L * MainConfig.world_border_resize_start_time); 56 | 57 | this.activeTasks.put(arena, scheduler); 58 | } 59 | 60 | private void resize(Arena arena) { 61 | final WorldBorder border = arena.getGameWorld().getWorldBorder(); 62 | 63 | // store original size 64 | { 65 | final ArenaPersistentStorage storage = arena.getPersistentStorage(); 66 | 67 | storage.setSynchronizedFlag(KEY_ORIGINAL_SIZE, false); 68 | storage.set(KEY_ORIGINAL_SIZE, border.getSize()); 69 | storage.saveAsync(); 70 | } 71 | 72 | // tell bukkit to resize 73 | border.setSize( 74 | border.getSize()*(MainConfig.world_border_resize_scale/100D), 75 | MainConfig.world_border_resize_duration); 76 | 77 | // clean up 78 | this.activeTasks.remove(arena); 79 | } 80 | 81 | private void cancel(Arena arena) { 82 | if (!MainConfig.world_border_resize_enabled) 83 | return; 84 | 85 | // cancel scheduler 86 | { 87 | final BukkitTask scheduler = this.activeTasks.remove(arena); 88 | 89 | if (scheduler != null) 90 | scheduler.cancel(); 91 | } 92 | 93 | // restore border size 94 | { 95 | final ArenaPersistentStorage storage = arena.getPersistentStorage(); 96 | final Optional originalSize = storage.getDouble(KEY_ORIGINAL_SIZE); 97 | 98 | if (originalSize.isPresent()) { 99 | final WorldBorder border = arena.getGameWorld().getWorldBorder(); 100 | 101 | border.setSize(originalSize.get(), 1); 102 | storage.remove(KEY_ORIGINAL_SIZE); 103 | } 104 | } 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /MBedwarsTweaks/src/main/java/me/metallicgoat/tweaksaddon/gentiers/handlers/SuddenDeathHandler.java: -------------------------------------------------------------------------------- 1 | package me.metallicgoat.tweaksaddon.gentiers.handlers; 2 | 3 | import de.marcely.bedwars.api.arena.Arena; 4 | import de.marcely.bedwars.api.arena.Team; 5 | import de.marcely.bedwars.api.game.spawner.Spawner; 6 | import de.marcely.bedwars.tools.location.XYZ; 7 | import java.util.List; 8 | import me.metallicgoat.tweaksaddon.api.gentiers.GenTierActionType; 9 | import me.metallicgoat.tweaksaddon.api.gentiers.GenTierLevel; 10 | import me.metallicgoat.tweaksaddon.config.MainConfig; 11 | import me.metallicgoat.tweaksaddon.gentiers.GenTiers; 12 | import me.metallicgoat.tweaksaddon.gentiers.dragons.SuddenDeathDragonImpl; 13 | import me.metallicgoat.tweaksaddon.utils.Util; 14 | import org.bukkit.Location; 15 | import org.bukkit.Material; 16 | import org.bukkit.World; 17 | 18 | public class SuddenDeathHandler extends BaseGenTierHandler { 19 | 20 | @Override 21 | public void run(GenTierLevel level, Arena arena) { 22 | final Location middle = getArenaMid(arena); 23 | 24 | if (!arena.isInside(middle)) 25 | throw new RuntimeException("Failed to find the center of an Arena!"); 26 | 27 | // Spawn Team Dragons 28 | for (Team team : arena.getEnabledTeams()) { 29 | if (arena.getPlayersInTeam(team).isEmpty()) 30 | continue; 31 | 32 | // Spawn Default Dragon 33 | if (MainConfig.default_sudden_death_dragon_enabled) 34 | SuddenDeathDragonImpl.createNewDragon(arena, team, middle); 35 | 36 | // Spawn extra dragon 37 | if (GenTiers.getState(arena).hasBoughtDragon(team)) 38 | SuddenDeathDragonImpl.createNewDragon(arena, team, middle); 39 | } 40 | 41 | // Destroy all Generators 42 | for (Spawner spawner : arena.getSpawners()) { 43 | final Location location = spawner.getLocation().toLocation(arena.getGameWorld()).add(0, 3, 0); 44 | 45 | int i = 5; 46 | 47 | while (location.subtract(0, 1, 0).getBlock().getType() != Material.AIR || i > 0){ 48 | location.getBlock().setType(Material.AIR); 49 | i--; 50 | } 51 | } 52 | } 53 | 54 | private Location getArenaMid(Arena arena) { 55 | final World world = arena.getGameWorld(); 56 | 57 | if (world == null) 58 | throw new RuntimeException("Cannot spawn a dragon in an arena with no world!?!?!?!"); 59 | 60 | final XYZ max = arena.getMaxRegionCorner(); 61 | final XYZ min = arena.getMinRegionCorner(); 62 | 63 | Location location = null; 64 | 65 | if (min != null && max != null) { 66 | location = new Location( 67 | world, 68 | (max.getX() + min.getX()) / 2, 69 | (max.getY() + min.getY()) / 2, 70 | (max.getZ() + min.getZ()) / 2 71 | ); 72 | } 73 | 74 | if (location == null) 75 | location = findAverageLocation(Util.getAllTeamSpawns(arena, world, null), world); 76 | 77 | return location; 78 | } 79 | 80 | // Find the middle using a bunch of points in the arena 81 | public Location findAverageLocation(List locations, World world) { 82 | if (locations == null || locations.isEmpty()) { 83 | return null; 84 | } 85 | 86 | double totalX = 0; 87 | double totalY = 0; 88 | double totalZ = 0; 89 | 90 | for (Location loc : locations) { 91 | totalX += loc.getX(); 92 | totalY += loc.getY(); 93 | totalZ += loc.getZ(); 94 | } 95 | 96 | int numberOfLocations = locations.size(); 97 | 98 | return new Location( 99 | world, 100 | totalX / numberOfLocations, 101 | totalY / numberOfLocations, 102 | totalZ / numberOfLocations 103 | ); 104 | } 105 | 106 | @Override 107 | public String getId() { 108 | return GenTierActionType.SUDDEN_DEATH.getDefaultHandlerId(); 109 | } 110 | 111 | @Override 112 | public GenTierActionType getActionType() { 113 | return GenTierActionType.SUDDEN_DEATH; 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /MBedwarsTweaks/src/main/java/me/metallicgoat/tweaksaddon/tweaks/cosmetic/InvisFootstepsParticles.java: -------------------------------------------------------------------------------- 1 | package me.metallicgoat.tweaksaddon.tweaks.cosmetic; 2 | 3 | import de.marcely.bedwars.api.GameAPI; 4 | import de.marcely.bedwars.api.arena.Arena; 5 | import de.marcely.bedwars.api.event.player.PlayerQuitArenaEvent; 6 | import de.marcely.bedwars.tools.NMSHelper; 7 | import me.metallicgoat.tweaksaddon.MBedwarsTweaksPlugin; 8 | import me.metallicgoat.tweaksaddon.config.MainConfig; 9 | import org.bukkit.Bukkit; 10 | import org.bukkit.Effect; 11 | import org.bukkit.Location; 12 | import org.bukkit.Material; 13 | import org.bukkit.entity.Player; 14 | import org.bukkit.event.EventHandler; 15 | import org.bukkit.event.Listener; 16 | import org.bukkit.event.player.PlayerMoveEvent; 17 | import org.bukkit.potion.PotionEffectType; 18 | import org.bukkit.scheduler.BukkitTask; 19 | import org.jetbrains.annotations.Nullable; 20 | 21 | import java.util.IdentityHashMap; 22 | import java.util.Map; 23 | 24 | // ONLY FOR 1.8.8 -> 1.12.2 25 | public class InvisFootstepsParticles implements Listener { 26 | 27 | private final Map playerMoveTimes = new IdentityHashMap<>(); 28 | private BukkitTask task = null; 29 | 30 | @EventHandler 31 | public void onPlayerMove(PlayerMoveEvent event) { 32 | if (!MainConfig.play_footsteps_with_invis || NMSHelper.get().getVersion() > 12) 33 | return; 34 | 35 | final Player player = event.getPlayer(); 36 | final Arena arena = GameAPI.get().getArenaByPlayer(player); 37 | 38 | if (arena == null || arena.getSpectators().contains(player) || !player.hasPotionEffect(PotionEffectType.INVISIBILITY)) 39 | return; 40 | 41 | this.playerMoveTimes.put(player, System.currentTimeMillis()); 42 | 43 | startTaskIfNeeded(); 44 | } 45 | 46 | @EventHandler 47 | public void onPlayerQuit(PlayerQuitArenaEvent event) { 48 | if (!MainConfig.play_footsteps_with_invis || NMSHelper.get().getVersion() > 12) 49 | return; 50 | 51 | this.playerMoveTimes.remove(event.getPlayer()); 52 | 53 | stopTaskIfEmpty(); 54 | } 55 | 56 | @SuppressWarnings("deprecation") // Player#playEffect() 57 | private void startTaskIfNeeded() { 58 | if (this.task != null) 59 | return; 60 | 61 | this.task = Bukkit.getScheduler().runTaskTimer(MBedwarsTweaksPlugin.getInstance(), () -> { 62 | // Play particle if player moved within 2 seconds 63 | this.playerMoveTimes.entrySet().removeIf(entry -> { 64 | final Player player = entry.getKey(); 65 | final Arena arena = GameAPI.get().getArenaByPlayer(player); 66 | 67 | if (!player.hasPotionEffect(PotionEffectType.INVISIBILITY) || arena == null || arena.getSpectators().contains(player)) 68 | return true; 69 | 70 | if (System.currentTimeMillis() - entry.getValue() < 200) { 71 | final Location loc = getSuitableParticleLocation(player); 72 | 73 | if (loc != null) 74 | player.playEffect(loc, Effect.FOOTSTEP, 1); 75 | 76 | } 77 | 78 | return false; 79 | }); 80 | 81 | stopTaskIfEmpty(); 82 | 83 | }, 0, 7); 84 | } 85 | 86 | private void stopTaskIfEmpty() { 87 | if (!this.playerMoveTimes.isEmpty()) 88 | return; 89 | 90 | if (this.task != null) { 91 | this.task.cancel(); 92 | this.task = null; 93 | } 94 | } 95 | 96 | @Nullable 97 | private Location getSuitableParticleLocation(Player player) { 98 | final Location location = player.getLocation().clone(); 99 | 100 | int i = 0; 101 | Material blockType = location.getBlock().getRelative(0, -1, 0).getType(); 102 | 103 | while (blockType == Material.AIR && i < 2) { 104 | location.add(0, -1, 0); 105 | blockType = location.getBlock().getRelative(0, -1, 0).getType(); 106 | i++; 107 | } 108 | 109 | if (blockType == Material.AIR) 110 | return null; 111 | 112 | location.setY(Math.floor(location.getY()) + 0.05); 113 | 114 | return location; 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /MBedwarsTweaks/src/main/java/me/metallicgoat/tweaksaddon/tweaks/advancedswords/AntiChest.java: -------------------------------------------------------------------------------- 1 | package me.metallicgoat.tweaksaddon.tweaks.advancedswords; 2 | 3 | import de.marcely.bedwars.api.BedwarsAPI; 4 | import me.metallicgoat.tweaksaddon.config.SwordsToolsConfig; 5 | import me.metallicgoat.tweaksaddon.utils.Util; 6 | import org.bukkit.entity.HumanEntity; 7 | import org.bukkit.entity.Player; 8 | import org.bukkit.event.EventHandler; 9 | import org.bukkit.event.Listener; 10 | import org.bukkit.event.inventory.InventoryAction; 11 | import org.bukkit.event.inventory.InventoryClickEvent; 12 | import org.bukkit.event.inventory.InventoryDragEvent; 13 | import org.bukkit.inventory.Inventory; 14 | import org.bukkit.inventory.ItemStack; 15 | 16 | public class AntiChest implements Listener { 17 | 18 | @EventHandler 19 | public void onShiftClick(InventoryClickEvent e) { 20 | if (!SwordsToolsConfig.anti_chest_enabled) 21 | return; 22 | 23 | if (e.getInventory().getSize() > 26) { 24 | if (e.getClick().isShiftClick() && inArena((Player) e.getWhoClicked())) { 25 | final Inventory clicked = e.getClickedInventory(); 26 | 27 | if (clicked == e.getWhoClicked().getInventory()) { 28 | final ItemStack clickedOn = e.getCurrentItem(); 29 | 30 | if (clickedOn != null 31 | && SwordsToolsConfig.anti_chest_materials.contains(clickedOn.getType()) 32 | && ToolSwordHelper.isNotToIgnore(clickedOn)) { 33 | e.setCancelled(true); 34 | } 35 | } 36 | } 37 | } 38 | } 39 | 40 | @EventHandler 41 | public void onInventoryClick(InventoryClickEvent e) { 42 | if (!SwordsToolsConfig.anti_chest_enabled) 43 | return; 44 | 45 | final Inventory clicked = e.getClickedInventory(); 46 | if (!(e.getInventory().getSize() > 26)) 47 | return; 48 | 49 | if (e.getAction() == InventoryAction.HOTBAR_SWAP || e.getAction() == InventoryAction.HOTBAR_MOVE_AND_READD) { 50 | final HumanEntity player = e.getWhoClicked(); 51 | final Inventory inventory = player != null ? player.getInventory() : null; 52 | 53 | if (inventory != null && clicked != inventory) { 54 | final int swapSlot = e.getHotbarButton(); 55 | ItemStack movingItem = null; 56 | 57 | if (e.getClick().name().equals("SWAP_OFFHAND")) 58 | movingItem = Util.getItemInOffHand(player); 59 | 60 | else if (swapSlot >= 0) 61 | movingItem = inventory.getItem(swapSlot); 62 | 63 | if (movingItem != null 64 | && SwordsToolsConfig.anti_chest_materials.contains(movingItem.getType()) 65 | && ToolSwordHelper.isNotToIgnore(movingItem)) { 66 | e.setCancelled(true); 67 | return; 68 | } 69 | } 70 | } 71 | 72 | if (clicked != e.getWhoClicked().getInventory() && inArena((Player) e.getWhoClicked())) { 73 | // The cursor item is going into the top inventory 74 | final ItemStack onCursor = e.getCursor(); 75 | if (onCursor != null 76 | && SwordsToolsConfig.anti_chest_materials.contains(onCursor.getType()) 77 | && ToolSwordHelper.isNotToIgnore(onCursor)) { 78 | e.setCancelled(true); 79 | } 80 | } 81 | } 82 | 83 | @EventHandler 84 | public void onInventoryDrag(InventoryDragEvent e) { 85 | if (!SwordsToolsConfig.anti_chest_enabled) 86 | return; 87 | 88 | final ItemStack dragged = e.getOldCursor(); 89 | if (SwordsToolsConfig.anti_chest_materials.contains(dragged.getType()) 90 | && inArena((Player) e.getWhoClicked()) 91 | && ToolSwordHelper.isNotToIgnore(dragged)) { 92 | 93 | final int inventorySize = e.getInventory().getSize(); 94 | for (int i : e.getRawSlots()) { 95 | if (i < inventorySize) { 96 | e.setCancelled(true); 97 | break; 98 | } 99 | } 100 | } 101 | } 102 | 103 | private boolean inArena(Player p) { 104 | return BedwarsAPI.getGameAPI().getArenaByPlayer(p) != null; 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /MBedwarsTweaks/src/main/java/me/metallicgoat/tweaksaddon/tweaks/cosmetic/PlaceholderUpdating.java: -------------------------------------------------------------------------------- 1 | package me.metallicgoat.tweaksaddon.tweaks.cosmetic; 2 | 3 | import de.marcely.bedwars.api.BedwarsAPI; 4 | import de.marcely.bedwars.api.arena.Arena; 5 | import de.marcely.bedwars.api.arena.ArenaStatus; 6 | import de.marcely.bedwars.api.event.arena.ArenaDeleteEvent; 7 | import de.marcely.bedwars.api.event.arena.ArenaStatusChangeEvent; 8 | import de.marcely.bedwars.api.event.player.PlayerJoinArenaEvent; 9 | import de.marcely.bedwars.api.event.player.PlayerQuitArenaEvent; 10 | import de.marcely.bedwars.api.message.Message; 11 | import de.marcely.bedwars.tools.Helper; 12 | import java.util.Map; 13 | import java.util.concurrent.ConcurrentHashMap; 14 | import me.metallicgoat.tweaksaddon.MBedwarsTweaksPlugin; 15 | import me.metallicgoat.tweaksaddon.config.MainConfig; 16 | import org.bukkit.Bukkit; 17 | import org.bukkit.entity.Player; 18 | import org.bukkit.event.EventHandler; 19 | import org.bukkit.event.EventPriority; 20 | import org.bukkit.event.Listener; 21 | import org.bukkit.scheduler.BukkitTask; 22 | 23 | public class PlaceholderUpdating implements Listener { 24 | 25 | private final Map tickingArenas = new ConcurrentHashMap<>(); 26 | 27 | private BukkitTask createScheduler(Arena arena) { 28 | long delay = 0; 29 | 30 | switch (arena.getStatus()) { 31 | case LOBBY: 32 | case END_LOBBY: 33 | delay = (int) Math.max(0, (arena.getLobbyTimeRemaining()%1)*20D); 34 | break; 35 | case RUNNING: 36 | delay = arena.getRunningTime().toMillis()/50; 37 | break; 38 | } 39 | 40 | return Bukkit.getServer().getScheduler().runTaskTimerAsynchronously(MBedwarsTweaksPlugin.getInstance(), () -> { 41 | if (arena.getStatus() == ArenaStatus.RUNNING && MainConfig.scoreboard_updating_enabled_in_game) 42 | arena.updateScoreboard(); 43 | else if (arena.getStatus() == ArenaStatus.LOBBY && MainConfig.scoreboard_updating_enabled_in_lobby) 44 | arena.updateScoreboard(); 45 | 46 | if ((arena.getStatus() == ArenaStatus.RUNNING && MainConfig.custom_action_bar_in_game) || 47 | (arena.getStatus() == ArenaStatus.LOBBY && MainConfig.custom_action_bar_in_lobby)) { 48 | 49 | for (Player player : arena.getPlayers()) 50 | BedwarsAPI.getNMSHelper().showActionbar(player, Message.build(Helper.get().replacePAPIPlaceholders(MainConfig.custom_action_bar_message, player)).done()); 51 | } 52 | }, delay, 20L); 53 | } 54 | 55 | private void startScheduler(Arena arena) { 56 | if (!arena.exists()) 57 | return; 58 | 59 | this.tickingArenas.computeIfAbsent(arena, this::createScheduler); 60 | } 61 | 62 | private void stopScheduler(Arena arena) { 63 | final BukkitTask task = this.tickingArenas.remove(arena); 64 | 65 | if (task != null) 66 | task.cancel(); 67 | } 68 | 69 | @EventHandler 70 | public void onPlayerJoin(PlayerJoinArenaEvent event) { 71 | final Arena arena = event.getArena(); 72 | 73 | if (arena.getPlayers().size() >= 2) // already added 74 | return; 75 | 76 | startScheduler(arena); 77 | } 78 | 79 | @EventHandler 80 | public void onPlayerLeave(PlayerQuitArenaEvent event) { 81 | final Arena arena = event.getArena(); 82 | 83 | if (!arena.getPlayers().isEmpty()) // not empty yet 84 | return; 85 | 86 | stopScheduler(arena); 87 | } 88 | 89 | @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) 90 | public void onArenaStatusChange(ArenaStatusChangeEvent event) { 91 | // resync scheduler 92 | final Arena arena = event.getArena(); 93 | final ArenaStatus newStatus = event.getNewStatus(); 94 | 95 | if (newStatus != ArenaStatus.RUNNING && newStatus != ArenaStatus.END_LOBBY) 96 | return; 97 | 98 | Bukkit.getScheduler().runTaskLaterAsynchronously(MBedwarsTweaksPlugin.getInstance(), () -> { 99 | stopScheduler(arena); 100 | startScheduler(arena); 101 | }, 1); 102 | } 103 | 104 | @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) 105 | public void onArenaDeleteEvent(ArenaDeleteEvent event) { 106 | stopScheduler(event.getArena()); 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /MBedwarsTweaks/src/main/java/me/metallicgoat/tweaksaddon/MBedwarsTweaksPlugin.java: -------------------------------------------------------------------------------- 1 | package me.metallicgoat.tweaksaddon; 2 | 3 | import de.marcely.bedwars.api.BedwarsAPI; 4 | import lombok.Getter; 5 | import me.metallicgoat.tweaksaddon.api.events.PostConfigLoadEvent; 6 | import me.metallicgoat.tweaksaddon.api.events.PreConfigsLoadEvent; 7 | import me.metallicgoat.tweaksaddon.config.ConfigLoader; 8 | import me.metallicgoat.tweaksaddon.config.MainConfig; 9 | import me.metallicgoat.tweaksaddon.gentiers.dragons.DragonUtil; 10 | import me.metallicgoat.tweaksaddon.integration.DependencyLoader; 11 | import me.metallicgoat.tweaksaddon.tweaks.advancedswords.ToolSwordHelper; 12 | import me.metallicgoat.tweaksaddon.utils.Console; 13 | import me.metallicgoat.tweaksaddon.utils.Metrics; 14 | import me.metallicgoat.tweaksaddon.utils.NMSClass; 15 | import me.metallicgoat.tweaksaddon.utils.UpdateChecker; 16 | import me.metallicgoat.tweaksaddon.utils.Util; 17 | import org.bukkit.Bukkit; 18 | import org.bukkit.plugin.PluginDescriptionFile; 19 | import org.bukkit.plugin.java.JavaPlugin; 20 | 21 | public class MBedwarsTweaksPlugin extends JavaPlugin { 22 | 23 | public static final int MIN_MBEDWARS_API_VER = 205; 24 | public static final String MIN_MBEDWARS_VER_NAME = "5.5.5"; 25 | 26 | @Getter 27 | private static MBedwarsTweaksPlugin instance; 28 | @Getter 29 | private static MBedwarsTweaksAddon addon; 30 | 31 | @Override 32 | public void onEnable() { 33 | instance = this; 34 | 35 | if (!checkMBedwars()) 36 | return; 37 | if (!registerAddon()) 38 | return; 39 | 40 | new Metrics(this, 11928); 41 | 42 | Util.init(); 43 | 44 | addon.registerMessageMappings(); 45 | addon.registerEvents(); 46 | addon.registerUpgrades(); 47 | addon.registerCommands(); 48 | 49 | final PluginDescriptionFile pdf = this.getDescription(); 50 | 51 | Console.printInfo( 52 | "------------------------------", 53 | pdf.getName() + " For MBedwars", 54 | "By: " + pdf.getAuthors(), 55 | "Version: " + pdf.getVersion(), 56 | "------------------------------" 57 | ); 58 | 59 | loadTweaks(true); 60 | } 61 | 62 | public void loadTweaks(boolean firstLoad) { 63 | BedwarsAPI.onReady(() -> { 64 | DependencyLoader.loadAll(); 65 | 66 | { 67 | final PreConfigsLoadEvent preConfigsLoadEvent = new PreConfigsLoadEvent(firstLoad); 68 | Bukkit.getPluginManager().callEvent(preConfigsLoadEvent); 69 | 70 | ConfigLoader.loadTweaksConfigs(this); 71 | 72 | final PostConfigLoadEvent postConfigLoadEvent = new PostConfigLoadEvent(firstLoad); 73 | Bukkit.getPluginManager().callEvent(postConfigLoadEvent); 74 | } 75 | 76 | ToolSwordHelper.load(); 77 | 78 | if (MainConfig.disable_dragon_death_sound) { 79 | try { 80 | NMSClass.disableDragonSound(); 81 | } catch (Exception e) { 82 | Console.printWarn( 83 | "============================================", 84 | "Failed to disable dragon death sounds! You may want to disable them in your spigot.yml", 85 | "============================================" 86 | ); 87 | } 88 | } 89 | 90 | // Check Update Async 91 | if (MainConfig.check_update_on_load) 92 | Bukkit.getScheduler().runTaskAsynchronously(this, () -> UpdateChecker.checkForUpdate(this.getDescription().getVersion())); 93 | 94 | }); 95 | } 96 | 97 | @Override 98 | public void onDisable() { 99 | DragonUtil.killAllDragons(); 100 | } 101 | 102 | private boolean checkMBedwars() { 103 | try { 104 | final Class apiClass = Class.forName("de.marcely.bedwars.api.BedwarsAPI"); 105 | final int apiVersion = (int) apiClass.getMethod("getAPIVersion").invoke(null); 106 | 107 | if (apiVersion < MIN_MBEDWARS_API_VER) 108 | throw new IllegalStateException(); 109 | } catch (Exception e) { 110 | getLogger().warning("Sorry, your installed version of MBedwars is not supported. Please install at least v" + MIN_MBEDWARS_VER_NAME); 111 | Bukkit.getPluginManager().disablePlugin(this); 112 | 113 | return false; 114 | } 115 | 116 | return true; 117 | } 118 | 119 | private boolean registerAddon() { 120 | addon = new MBedwarsTweaksAddon(this); 121 | 122 | if (!addon.register()) { 123 | getLogger().warning("It seems like this addon has already been loaded. Please delete duplicates and try again."); 124 | Bukkit.getPluginManager().disablePlugin(this); 125 | 126 | return false; 127 | } 128 | 129 | return true; 130 | } 131 | } -------------------------------------------------------------------------------- /MBedwarsTweaks/src/main/java/me/metallicgoat/tweaksaddon/tweaks/advancedswords/AlwaysSword.java: -------------------------------------------------------------------------------- 1 | package me.metallicgoat.tweaksaddon.tweaks.advancedswords; 2 | 3 | import de.marcely.bedwars.api.BedwarsAPI; 4 | import de.marcely.bedwars.api.GameAPI; 5 | import de.marcely.bedwars.api.arena.Arena; 6 | import de.marcely.bedwars.api.arena.ArenaStatus; 7 | import me.metallicgoat.tweaksaddon.MBedwarsTweaksPlugin; 8 | import me.metallicgoat.tweaksaddon.config.SwordsToolsConfig; 9 | import org.bukkit.Bukkit; 10 | import org.bukkit.GameMode; 11 | import org.bukkit.entity.Player; 12 | import org.bukkit.event.EventHandler; 13 | import org.bukkit.event.Listener; 14 | import org.bukkit.event.inventory.InventoryClickEvent; 15 | import org.bukkit.event.player.PlayerDropItemEvent; 16 | import org.bukkit.event.player.PlayerPickupItemEvent; 17 | import org.bukkit.inventory.Inventory; 18 | import org.bukkit.inventory.ItemStack; 19 | import org.bukkit.inventory.PlayerInventory; 20 | import org.bukkit.scheduler.BukkitTask; 21 | 22 | import java.util.IdentityHashMap; 23 | import java.util.Map; 24 | 25 | public class AlwaysSword implements Listener { 26 | 27 | final Map runningTasks = new IdentityHashMap<>(); 28 | 29 | @EventHandler 30 | public void onClick(InventoryClickEvent e) { 31 | if (!SwordsToolsConfig.always_sword_drop_enabled) 32 | return; 33 | 34 | final Player player = (Player) e.getWhoClicked(); 35 | final Arena arena = BedwarsAPI.getGameAPI().getArenaByPlayer(player); 36 | 37 | if (arena != null 38 | && arena.getStatus() == ArenaStatus.RUNNING 39 | && player.getGameMode() != GameMode.SPECTATOR) { 40 | 41 | if (runningTasks.containsKey(player)) 42 | runningTasks.get(player).cancel(); 43 | 44 | runningTasks.put(player, Bukkit.getServer().getScheduler().runTaskLater((MBedwarsTweaksPlugin.getInstance()), () -> { 45 | final Arena currArena = GameAPI.get().getArenaByPlayer(player); 46 | 47 | if (currArena != arena || !arena.getPlayers().contains(player) || arena.getSpectators().contains(player)) { 48 | runningTasks.remove(player); 49 | return; 50 | } 51 | 52 | final Inventory pi = player.getInventory(); 53 | final int i = ToolSwordHelper.getSwordsAmount(player); 54 | 55 | if (i >= 2) { 56 | for (ItemStack itemStack : pi.getContents()) { 57 | if (itemStack != null 58 | && itemStack.getType() == ToolSwordHelper.WOOD_SWORD 59 | && ToolSwordHelper.isNotToIgnore(itemStack)) { 60 | 61 | pi.remove(itemStack); 62 | 63 | if (!ToolSwordHelper.hasBetterSword(player)) 64 | break; 65 | } 66 | } 67 | // Give player a wood sword if they don't have one 68 | } else if (i == 0 && 69 | (e.getCurrentItem() == null || e.getCurrentItem() != null && !e.getCurrentItem().getType().name().endsWith("SWORD") && ToolSwordHelper.isNotToIgnore(e.getCurrentItem())) && 70 | (e.getCursor() == null || e.getCursor() != null && !e.getCursor().getType().name().endsWith("SWORD") && ToolSwordHelper.isNotToIgnore(e.getCursor()))) { 71 | 72 | pi.addItem(ToolSwordHelper.getDefaultWoodSword(player, arena)); 73 | } 74 | 75 | runningTasks.remove(player); 76 | }, 25L)); 77 | } 78 | } 79 | 80 | @EventHandler 81 | public void giveSwordOnDrop(PlayerDropItemEvent event) { 82 | if (!SwordsToolsConfig.always_sword_drop_enabled) 83 | return; 84 | 85 | final Player player = event.getPlayer(); 86 | final Arena arena = BedwarsAPI.getGameAPI().getArenaByPlayer(player); 87 | final PlayerInventory pi = player.getInventory(); 88 | 89 | if (arena == null || arena.getStatus() != ArenaStatus.RUNNING) 90 | return; 91 | 92 | if (event.getItemDrop().getItemStack().getType() == ToolSwordHelper.WOOD_SWORD) { 93 | event.setCancelled(true); 94 | return; 95 | } 96 | 97 | if (ToolSwordHelper.getSwordsAmount(event.getPlayer()) == 0) { 98 | final ItemStack is = ToolSwordHelper.getDefaultWoodSword(player, arena); 99 | 100 | // tries to put sword in slot player dropped sword from 101 | if (pi.getItem(pi.getHeldItemSlot()) == null) 102 | pi.setItem(pi.getHeldItemSlot(), is); 103 | else 104 | pi.addItem(is); 105 | } 106 | } 107 | 108 | @EventHandler 109 | public void replaceSwordOnCollect(PlayerPickupItemEvent event) { 110 | if (!SwordsToolsConfig.always_sword_drop_enabled) 111 | return; 112 | 113 | final Player player = event.getPlayer(); 114 | final Arena arena = BedwarsAPI.getGameAPI().getArenaByPlayer(player); 115 | final ItemStack sword = event.getItem().getItemStack(); 116 | 117 | if (arena != null && 118 | ToolSwordHelper.isSword(sword.getType()) && 119 | ToolSwordHelper.isNotToIgnore(sword)) { 120 | 121 | final PlayerInventory pi = player.getInventory(); 122 | 123 | if (pi.contains(ToolSwordHelper.WOOD_SWORD)) 124 | pi.remove(ToolSwordHelper.WOOD_SWORD); 125 | 126 | pi.addItem(sword); 127 | event.getItem().remove(); 128 | event.setCancelled(true); 129 | } 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /MBedwarsTweaks/pom.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 4.0.0 6 | MBedwarsTweaks 7 | jar 8 | 9 | 10 | me.metallicgoat.tweaksaddon 11 | MBedwarsTweaksParent 12 | 5.0.0-Beta2 13 | 14 | 15 | 16 | 17 | spigot-repo 18 | https://hub.spigotmc.org/nexus/content/repositories/snapshots/ 19 | 20 | 21 | papermc 22 | https://repo.papermc.io/repository/maven-public/ 23 | 24 | 25 | mbedwars-repo 26 | https://repo.marcely.de/repository/maven-public/ 27 | 28 | 29 | placeholderapi 30 | https://repo.extendedclip.com/content/repositories/placeholderapi/ 31 | 32 | 33 | 34 | 35 | 36 | me.metallicgoat.tweaksaddon 37 | API 38 | 5.0.0-Beta2 39 | compile 40 | 41 | 42 | org.jetbrains 43 | annotations 44 | 26.0.2 45 | provided 46 | 47 | 48 | org.spigotmc 49 | spigot-api 50 | 1.8.8-R0.1-SNAPSHOT 51 | provided 52 | 53 | 54 | io.papermc.paper 55 | paper-api 56 | 1.21.10-R0.1-SNAPSHOT 57 | provided 58 | 59 | 60 | me.clip 61 | placeholderapi 62 | 2.11.7 63 | provided 64 | 65 | 66 | de.marcely.bedwars 67 | API 68 | 5.5.6-Beta4 69 | provided 70 | 71 | 72 | me.metallicgoat.hotbarmanageraddon 73 | API 74 | 1.0 75 | system 76 | ${basedir}/libs/public/HotbarManager-1.0-SNAPSHOT.jar 77 | 78 | 79 | me.tvhee 80 | PrestigesAddon 81 | 1.2.0 82 | system 83 | ${basedir}/libs/public/PrestigeAddonAPI-1.2.0.jar 84 | 85 | 86 | org.projectlombok 87 | lombok 88 | 1.18.38 89 | compile 90 | 91 | 92 | 93 | 94 | 8 95 | 8 96 | 97 | 98 | 99 | 100 | 101 | org.apache.maven.plugins 102 | maven-shade-plugin 103 | 3.6.1 104 | 105 | false 106 | 107 | 108 | me.metallicgoat.tweaksaddon:API 109 | 110 | **/* 111 | 112 | 113 | 114 | 115 | 116 | me.metallicgoat.tweaksaddon:API 117 | 118 | 119 | 120 | 121 | 122 | package 123 | 124 | shade 125 | 126 | 127 | 128 | 129 | 130 | 131 | -------------------------------------------------------------------------------- /MBedwarsTweaks/src/main/java/me/metallicgoat/tweaksaddon/tweaks/messages/TopKillerMessage.java: -------------------------------------------------------------------------------- 1 | package me.metallicgoat.tweaksaddon.tweaks.messages; 2 | 3 | import de.marcely.bedwars.api.arena.Arena; 4 | import de.marcely.bedwars.api.arena.QuitPlayerMemory; 5 | import de.marcely.bedwars.api.event.arena.ArenaDeleteEvent; 6 | import de.marcely.bedwars.api.event.arena.RoundEndEvent; 7 | import de.marcely.bedwars.api.event.arena.RoundStartEvent; 8 | import de.marcely.bedwars.api.message.Message; 9 | import de.marcely.bedwars.api.player.DefaultPlayerStatSet; 10 | import de.marcely.bedwars.api.player.PlayerDataAPI; 11 | import de.marcely.bedwars.api.player.PlayerStats; 12 | import java.util.ArrayList; 13 | import java.util.Collection; 14 | import java.util.Comparator; 15 | import java.util.HashMap; 16 | import java.util.IdentityHashMap; 17 | import java.util.LinkedHashMap; 18 | import java.util.List; 19 | import java.util.Map; 20 | import java.util.Optional; 21 | import java.util.UUID; 22 | import java.util.stream.Collectors; 23 | import me.metallicgoat.tweaksaddon.config.MainConfig; 24 | import org.bukkit.Bukkit; 25 | import org.bukkit.OfflinePlayer; 26 | import org.bukkit.entity.Player; 27 | import org.bukkit.event.EventHandler; 28 | import org.bukkit.event.EventPriority; 29 | import org.bukkit.event.Listener; 30 | 31 | public class TopKillerMessage implements Listener { 32 | 33 | public Map> arenaPlayers = new IdentityHashMap<>(); 34 | 35 | @EventHandler 36 | public void onRoundStart(RoundStartEvent event) { 37 | if (!MainConfig.top_killer_message_enabled) 38 | return; 39 | 40 | final Arena arena = event.getArena(); 41 | final List players = new ArrayList<>(); 42 | 43 | for (Player player : arena.getPlayers()) 44 | players.add(player.getUniqueId()); 45 | 46 | arenaPlayers.put(arena, players); 47 | } 48 | 49 | @EventHandler 50 | public void onGameOver(RoundEndEvent event) { 51 | if (!MainConfig.top_killer_message_enabled) 52 | return; 53 | 54 | final Arena arena = event.getArena(); 55 | final Map nameIntMap = new HashMap<>(); 56 | 57 | // Online Players 58 | for (UUID player : arenaPlayers.get(arena)) 59 | addStatsToMap(nameIntMap, player); 60 | 61 | // Offline Players 62 | for (QuitPlayerMemory memory : arena.getQuitPlayerMemories()) 63 | addStatsToMap(nameIntMap, memory.getUniqueId()); 64 | 65 | printMessage(arena, sortHashMapByValue(nameIntMap)); 66 | arenaPlayers.remove(arena); 67 | } 68 | 69 | @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) 70 | public void onArenaDeleteEvent(ArenaDeleteEvent event) { 71 | arenaPlayers.remove(event.getArena()); 72 | } 73 | 74 | // TODO this bad 75 | private void printMessage(Arena arena, Map playerIntegerMap) { 76 | final List formattedList = new ArrayList<>(); 77 | 78 | // There is Killers 79 | if (!playerIntegerMap.isEmpty()) { 80 | for (String line : MainConfig.top_killer_pre_lines) 81 | formattedList.add(Message.build(line)); 82 | 83 | int place = 1; 84 | for (UUID uuid : playerIntegerMap.keySet()) { 85 | final String text = MainConfig.top_killer_lines.get(place); 86 | 87 | if (text == null) 88 | continue; 89 | 90 | final OfflinePlayer player = Bukkit.getOfflinePlayer(uuid); 91 | 92 | formattedList.add(Message.build(text) 93 | .placeholder("killer-name", player.getName()) 94 | .placeholder("killer-display-name", player.getName()) 95 | .placeholder("kill-amount", playerIntegerMap.get(uuid)) 96 | ); 97 | 98 | place++; 99 | } 100 | 101 | for (String line : MainConfig.top_killer_sub_lines) 102 | formattedList.add(Message.build(line)); 103 | 104 | // There are no killers 105 | } else { 106 | if (MainConfig.no_top_killer_message_enabled) 107 | return; 108 | 109 | for (String line : MainConfig.no_top_killer_message) 110 | formattedList.add(Message.build(line)); 111 | } 112 | 113 | broadcast(arena, formattedList); 114 | } 115 | 116 | public LinkedHashMap sortHashMapByValue(Map hm) { 117 | return hm.entrySet() 118 | .stream() 119 | .sorted(Map.Entry.comparingByValue(Comparator.reverseOrder())) 120 | .collect(Collectors.toMap( 121 | Map.Entry::getKey, 122 | Map.Entry::getValue, 123 | (e1, e2) -> e1, 124 | LinkedHashMap::new 125 | )); 126 | } 127 | 128 | private void addStatsToMap(Map nameIntMap, UUID player) { 129 | if (player == null) 130 | return; 131 | 132 | final Optional stats = PlayerDataAPI.get().getStatsCached(player); 133 | 134 | if (!stats.isPresent()) 135 | return; 136 | 137 | final int kills = DefaultPlayerStatSet.KILLS.getValue(stats.get().getGameStats()).intValue(); 138 | 139 | if (kills > 0) 140 | nameIntMap.put(player, kills); 141 | } 142 | 143 | private void broadcast(Arena arena, List message) { 144 | if (message == null || (message.size() == 1 && message.get(0).done(false).isEmpty())) 145 | return; 146 | 147 | for (Message line : message) 148 | arena.broadcast(line); 149 | } 150 | } 151 | -------------------------------------------------------------------------------- /MBedwarsTweaks/src/main/java/me/metallicgoat/tweaksaddon/tweaks/spawners/SpawnerUpgrade.java: -------------------------------------------------------------------------------- 1 | package me.metallicgoat.tweaksaddon.tweaks.spawners; 2 | 3 | import de.marcely.bedwars.api.GameAPI; 4 | import de.marcely.bedwars.api.arena.Arena; 5 | import de.marcely.bedwars.api.arena.ArenaStatus; 6 | import de.marcely.bedwars.api.arena.Team; 7 | import de.marcely.bedwars.api.event.arena.ArenaDeleteEvent; 8 | import de.marcely.bedwars.api.event.arena.ArenaStatusChangeEvent; 9 | import de.marcely.bedwars.api.event.player.PlayerBuyUpgradeEvent; 10 | import de.marcely.bedwars.api.game.spawner.DropType; 11 | import de.marcely.bedwars.api.game.spawner.Spawner; 12 | import de.marcely.bedwars.api.game.upgrade.UpgradeLevel; 13 | import de.marcely.bedwars.api.game.upgrade.UpgradeTriggerHandler; 14 | import de.marcely.bedwars.api.game.upgrade.UpgradeTriggerHandlerType; 15 | import me.metallicgoat.tweaksaddon.MBedwarsTweaksPlugin; 16 | import me.metallicgoat.tweaksaddon.config.MainConfig; 17 | import org.bukkit.Location; 18 | import org.bukkit.event.EventHandler; 19 | import org.bukkit.event.EventPriority; 20 | import org.bukkit.event.Listener; 21 | import org.bukkit.scheduler.BukkitRunnable; 22 | import org.bukkit.scheduler.BukkitTask; 23 | 24 | import java.util.ArrayList; 25 | import java.util.List; 26 | import java.util.Map; 27 | import java.util.concurrent.ConcurrentHashMap; 28 | import java.util.concurrent.CopyOnWriteArrayList; 29 | 30 | public class SpawnerUpgrade implements Listener { 31 | 32 | public static Map> runningTasks = new ConcurrentHashMap<>(); 33 | 34 | @EventHandler(priority = EventPriority.MONITOR) 35 | public void onPlayerBuyUpgrade(PlayerBuyUpgradeEvent event) { 36 | final Arena arena = event.getArena(); 37 | final Team team = event.getTeam(); 38 | final UpgradeLevel level = event.getUpgradeLevel(); 39 | final UpgradeTriggerHandler handler = level.getTriggerHandler(); 40 | 41 | // Check enable 42 | if (!MainConfig.advanced_forge_enabled || arena == null || team == null || handler == null || !event.getProblems().isEmpty()) 43 | return; 44 | 45 | // Check upgrade type 46 | if (handler.getType() != UpgradeTriggerHandlerType.SPAWNER_MULTIPLIER) 47 | return; 48 | 49 | // Check whether he reached the required level 50 | final UpgradeLevel oldLevel = event.getUpgradeState().getCurrentUpgradeLevel(level.getUpgrade()); 51 | 52 | if (oldLevel != null && oldLevel.getLevel() >= MainConfig.advanced_forge_level) 53 | return; 54 | 55 | if (level.getLevel() < MainConfig.advanced_forge_level) 56 | return; 57 | 58 | // Start upgrade 59 | final BukkitTask task = (new SpawnerUpgradeTask(arena, team)).runTaskTimer( 60 | MBedwarsTweaksPlugin.getInstance(), 61 | 80, 62 | 20L * MainConfig.advanced_forge_drop_rate); 63 | final List arenaTasks = runningTasks.get(arena); 64 | 65 | if (arenaTasks != null) 66 | arenaTasks.add(task); 67 | else { 68 | final List list = new CopyOnWriteArrayList<>(); 69 | list.add(task); 70 | runningTasks.put(arena, list); 71 | } 72 | } 73 | 74 | @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) 75 | public void onArenaStatusChangeEvent(ArenaStatusChangeEvent event) { 76 | if (event.getOldStatus() == ArenaStatus.RUNNING) 77 | removeArena(event.getArena()); 78 | } 79 | 80 | @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) 81 | public void onArenaDeleteEvent(ArenaDeleteEvent event) { 82 | removeArena(event.getArena()); 83 | } 84 | 85 | private void removeArena(Arena arena) { 86 | final List tasks = runningTasks.remove(arena); 87 | 88 | if (tasks == null) 89 | return; 90 | 91 | for (BukkitTask task : tasks) 92 | task.cancel(); 93 | } 94 | 95 | 96 | 97 | private static class SpawnerUpgradeTask extends BukkitRunnable { 98 | private final Arena arena; 99 | private final Location baseLocation; 100 | private final DropType dropType = GameAPI.get().getDropTypeById(MainConfig.advanced_forge_new_drop); 101 | private final DropType affectingType = GameAPI.get().getDropTypeById(MainConfig.advanced_forge_effected_spawner); 102 | 103 | public SpawnerUpgradeTask(Arena arena, Team team) { 104 | this.arena = arena; 105 | this.baseLocation = arena.getTeamSpawn(team).toLocation(arena.getGameWorld()); 106 | } 107 | 108 | @Override 109 | public void run() { 110 | if (arena.getStatus() != ArenaStatus.RUNNING) { 111 | cancel(); 112 | return; 113 | } 114 | 115 | if (affectingType == null || dropType == null) 116 | return; 117 | 118 | for (Spawner spawner : getAffectingSpawners()) 119 | spawner.drop(false, dropType.getDroppingMaterials()); 120 | } 121 | 122 | private List getAffectingSpawners() { 123 | final List spawnerList = new ArrayList<>(); 124 | 125 | for (Spawner spawner : this.arena.getSpawners()) { 126 | if (spawner.getDropType() != affectingType) 127 | continue; 128 | 129 | if (baseLocation.distance(spawner.getLocation().toLocation(this.arena.getGameWorld())) <= MainConfig.advanced_forge_range) 130 | spawnerList.add(spawner); 131 | } 132 | 133 | return spawnerList; 134 | } 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /MBedwarsTweaks/src/main/java/me/metallicgoat/tweaksaddon/tweaks/spectialitems/TrackerDistance.java: -------------------------------------------------------------------------------- 1 | package me.metallicgoat.tweaksaddon.tweaks.spectialitems; 2 | 3 | import de.marcely.bedwars.api.GameAPI; 4 | import de.marcely.bedwars.api.arena.Arena; 5 | import de.marcely.bedwars.api.arena.ArenaStatus; 6 | import de.marcely.bedwars.api.arena.Team; 7 | import de.marcely.bedwars.api.event.arena.ArenaStatusChangeEvent; 8 | import de.marcely.bedwars.api.event.arena.RoundStartEvent; 9 | import de.marcely.bedwars.api.game.specialitem.SpecialItem; 10 | import de.marcely.bedwars.api.game.specialitem.SpecialItemType; 11 | import de.marcely.bedwars.api.message.Message; 12 | import de.marcely.bedwars.tools.NMSHelper; 13 | import de.marcely.bedwars.tools.Pair; 14 | import java.text.DecimalFormat; 15 | import java.util.List; 16 | import java.util.concurrent.CopyOnWriteArrayList; 17 | import me.metallicgoat.tweaksaddon.MBedwarsTweaksPlugin; 18 | import me.metallicgoat.tweaksaddon.config.MainConfig; 19 | import me.metallicgoat.tweaksaddon.utils.Util; 20 | import org.bukkit.GameMode; 21 | import org.bukkit.entity.Player; 22 | import org.bukkit.event.EventHandler; 23 | import org.bukkit.event.EventPriority; 24 | import org.bukkit.event.Listener; 25 | import org.bukkit.inventory.ItemStack; 26 | import org.bukkit.scheduler.BukkitRunnable; 27 | import org.bukkit.scheduler.BukkitTask; 28 | import org.jetbrains.annotations.Nullable; 29 | 30 | public class TrackerDistance implements Listener { 31 | 32 | private static final DecimalFormat DECIMAL_FORMAT = new DecimalFormat("#.#"); 33 | 34 | private final List tickingArenas = new CopyOnWriteArrayList<>(); 35 | private BukkitTask task = null; 36 | 37 | @EventHandler 38 | public void onRoundStart(RoundStartEvent event) { 39 | if (!MainConfig.tracker_hotbar_message_enabled) 40 | return; 41 | 42 | tickingArenas.add(event.getArena()); 43 | 44 | if (task == null) 45 | startTask(); 46 | 47 | } 48 | 49 | // Stop checkin' when no ticking arenas 50 | @EventHandler(priority = EventPriority.MONITOR) 51 | public void onArenaStatusChange(ArenaStatusChangeEvent event) { 52 | if (event.getArena().getStatus() == ArenaStatus.RUNNING) 53 | return; 54 | 55 | tickingArenas.remove(event.getArena()); 56 | 57 | if (tickingArenas.isEmpty() && task != null) { 58 | task.cancel(); 59 | task = null; 60 | } 61 | } 62 | 63 | private void startTask() { 64 | if (task != null) 65 | task.cancel(); 66 | 67 | task = new BukkitRunnable() { 68 | @Override 69 | public void run() { 70 | for (Arena arena : tickingArenas) { 71 | 72 | if (arena.getStatus() != ArenaStatus.RUNNING) 73 | continue; 74 | 75 | for (Player player : arena.getPlayers()) { 76 | final boolean holdingTracker = isTracker(player.getItemInHand()) || isTracker(Util.getItemInOffHand(player)); 77 | 78 | if (!holdingTracker) 79 | continue; 80 | 81 | final Team playerTeam = arena.getPlayerTeam(player); 82 | final Pair nearestEnemy = getNearestEnemy(arena, player, playerTeam); 83 | 84 | if (nearestEnemy.getKey() == null) { 85 | // No enemies found message 86 | sendHotbarMessage(player, Message.build(MainConfig.tracker_hotbar_message_no_enemies)); 87 | return; 88 | } 89 | 90 | final Team enemyTeam = arena.getPlayerTeam(nearestEnemy.getKey()); 91 | 92 | if (enemyTeam == null) { 93 | throw new RuntimeException("Player Tracker Error: Enemy team is null"); 94 | } 95 | 96 | // Send distance message 97 | sendHotbarMessage(player, Message.build(MainConfig.tracker_hotbar_message) 98 | .placeholder("distance", DECIMAL_FORMAT.format(nearestEnemy.getValue())) 99 | .placeholder("team-color", enemyTeam.getBungeeChatColor()) 100 | .placeholder("team", enemyTeam.getDisplayName(player))); 101 | } 102 | } 103 | } 104 | }.runTaskTimer(MBedwarsTweaksPlugin.getInstance(), 20L, 20L); 105 | } 106 | 107 | private void sendHotbarMessage(Player player, Message message) { 108 | final String string = message.done(player); 109 | 110 | if (string.isEmpty()) 111 | return; 112 | 113 | NMSHelper.get().showActionbar(player, string); 114 | } 115 | 116 | private Pair getNearestEnemy(Arena arena, Player player, Team playerTeam) { 117 | Player nearest = null; 118 | double nearestDistance = Double.MAX_VALUE; 119 | 120 | for (Player possibleEnemy : arena.getPlayers()) { 121 | if (playerTeam == arena.getPlayerTeam(possibleEnemy) || possibleEnemy.getGameMode() == GameMode.SPECTATOR) 122 | continue; 123 | 124 | final double distance = possibleEnemy.getLocation().distance(player.getLocation()); 125 | 126 | if (distance < nearestDistance) { 127 | nearest = possibleEnemy; 128 | nearestDistance = distance; 129 | } 130 | } 131 | 132 | return new Pair<>(nearest, nearestDistance); 133 | } 134 | 135 | private boolean isTracker(@Nullable ItemStack itemStack) { 136 | if (itemStack == null) 137 | return false; 138 | 139 | final SpecialItem item = GameAPI.get().getSpecialItem(itemStack); 140 | 141 | return item != null && item.getType() == SpecialItemType.TRACKER; 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /MBedwarsTweaks/src/main/java/me/metallicgoat/tweaksaddon/utils/Util.java: -------------------------------------------------------------------------------- 1 | package me.metallicgoat.tweaksaddon.utils; 2 | 3 | import de.marcely.bedwars.api.GameAPI; 4 | import de.marcely.bedwars.api.arena.Arena; 5 | import de.marcely.bedwars.api.arena.Team; 6 | import de.marcely.bedwars.api.arena.picker.ArenaPickerAPI; 7 | import de.marcely.bedwars.api.game.spawner.DropType; 8 | import de.marcely.bedwars.tools.Helper; 9 | import de.marcely.bedwars.tools.NMSHelper; 10 | import de.marcely.bedwars.tools.location.XYZYP; 11 | import java.lang.reflect.Method; 12 | import me.metallicgoat.tweaksaddon.api.gentiers.GenTierActionType; 13 | import me.metallicgoat.tweaksaddon.api.gentiers.GenTierHandler; 14 | import me.metallicgoat.tweaksaddon.api.unsafe.MBedwarsTweaksAPILayer; 15 | import me.metallicgoat.tweaksaddon.gentiers.handlers.BedDestroyHandler; 16 | import me.metallicgoat.tweaksaddon.gentiers.handlers.GameOverHandler; 17 | import me.metallicgoat.tweaksaddon.gentiers.handlers.SpawnerUpgradeHandler; 18 | import me.metallicgoat.tweaksaddon.gentiers.handlers.SuddenDeathHandler; 19 | import me.metallicgoat.tweaksaddon.impl.api.ImplMBedwarsTweaksAPILayer; 20 | import org.bukkit.Location; 21 | import org.bukkit.Material; 22 | import org.bukkit.World; 23 | import org.bukkit.entity.HumanEntity; 24 | import org.bukkit.inventory.ItemStack; 25 | import org.bukkit.inventory.PlayerInventory; 26 | import org.jetbrains.annotations.Nullable; 27 | 28 | import java.util.ArrayList; 29 | import java.util.Arrays; 30 | import java.util.Collection; 31 | import java.util.Collections; 32 | import java.util.HashMap; 33 | import java.util.List; 34 | 35 | public class Util { 36 | 37 | private static final HashMap handlersById = new HashMap<>(); 38 | 39 | private static Method GET_ITEM_IN_OFF_HAND_METHOD = null; 40 | 41 | public static void init() { 42 | MBedwarsTweaksAPILayer.INSTANCE = new ImplMBedwarsTweaksAPILayer(); 43 | 44 | registerDefaultGenTierHandlers(); 45 | 46 | if (NMSHelper.get().getVersion() == 8) 47 | return; 48 | 49 | try { 50 | GET_ITEM_IN_OFF_HAND_METHOD = PlayerInventory.class.getDeclaredMethod("getItemInOffHand", null); 51 | } catch (Exception e) { 52 | e.printStackTrace(); 53 | } 54 | } 55 | 56 | private static void registerDefaultGenTierHandlers() { 57 | registerGenTierHandler(new BedDestroyHandler()); 58 | registerGenTierHandler(new GameOverHandler()); 59 | registerGenTierHandler(new SpawnerUpgradeHandler()); 60 | registerGenTierHandler(new SuddenDeathHandler()); 61 | } 62 | 63 | public static void registerGenTierHandler(GenTierHandler handler) { 64 | if (handlersById.containsKey(handler.getId())) { 65 | throw new IllegalStateException("GenTierHandler already registered"); 66 | } 67 | 68 | handlersById.put(handler.getId().toLowerCase(), handler); 69 | } 70 | 71 | public static void unregisterGenTierHandler(String id) { 72 | handlersById.remove(id); 73 | } 74 | 75 | public static GenTierHandler getGenTierHandlerById(String id) { 76 | return handlersById.get(id); 77 | } 78 | 79 | public static Collection getGenTierHandlers() { 80 | return handlersById.values(); 81 | } 82 | 83 | public static @Nullable ItemStack getItemInOffHand(HumanEntity player) { 84 | if (GET_ITEM_IN_OFF_HAND_METHOD == null) 85 | return null; 86 | 87 | try { 88 | return (ItemStack) GET_ITEM_IN_OFF_HAND_METHOD.invoke(player.getInventory()); 89 | } catch (Exception e) { 90 | e.printStackTrace(); 91 | } 92 | 93 | return null; 94 | } 95 | 96 | public static Collection parseArenas(String arenaKey) { 97 | if (arenaKey.equalsIgnoreCase("ALL-ARENAS")) { 98 | return GameAPI.get().getArenas(); 99 | } 100 | 101 | final Arena arenaByName = GameAPI.get().getArenaByName(arenaKey); 102 | 103 | if (arenaByName != null) 104 | return Collections.singleton(arenaByName); 105 | 106 | try { 107 | return ArenaPickerAPI.get().getArenasByCondition(arenaKey); 108 | } catch (Exception ignored) { 109 | return Collections.emptyList(); 110 | } 111 | } 112 | 113 | public static @Nullable DropType getDropType(String id) { 114 | return GameAPI.get().getDropTypeById(id); 115 | } 116 | 117 | public static boolean isInteger(String s) { 118 | try { 119 | Integer.valueOf(s); 120 | return true; 121 | } catch (NumberFormatException e) { 122 | return false; 123 | } 124 | } 125 | 126 | public static List getAllTeamSpawns(Arena arena, World world, Team ignoreTeam) { 127 | final List targets = new ArrayList<>(); 128 | 129 | for (Team currTeam : arena.getEnabledTeams()) { 130 | if (currTeam == ignoreTeam) 131 | continue; 132 | 133 | final XYZYP spawn = arena.getTeamSpawn(currTeam); 134 | 135 | if (spawn != null) 136 | targets.add(spawn.toLocation(world)); 137 | } 138 | 139 | return targets; 140 | } 141 | 142 | public static List buildMaterialList(String... materials) { 143 | final List materialList = new ArrayList<>(); 144 | 145 | for (String material : materials) { 146 | final Material mat = Helper.get().getMaterialByName(material); 147 | 148 | if (mat != null) 149 | materialList.add(mat); 150 | } 151 | 152 | return materialList; 153 | } 154 | 155 | public static List getLines(String string) { 156 | final String[] parts = string.split("\\\\n"); 157 | return Arrays.asList(parts); 158 | } 159 | } 160 | -------------------------------------------------------------------------------- /API/src/main/java/me/metallicgoat/tweaksaddon/api/GenTiersAPI.java: -------------------------------------------------------------------------------- 1 | package me.metallicgoat.tweaksaddon.api; 2 | 3 | import de.marcely.bedwars.api.arena.Arena; 4 | import de.marcely.bedwars.api.arena.Team; 5 | import de.marcely.bedwars.api.game.upgrade.UpgradeTriggerHandler; 6 | import de.marcely.bedwars.tools.Validate; 7 | import java.util.Collections; 8 | import me.metallicgoat.tweaksaddon.api.gentiers.GenTierHandler; 9 | import me.metallicgoat.tweaksaddon.api.gentiers.GenTierLevel; 10 | import me.metallicgoat.tweaksaddon.api.gentiers.GenTierState; 11 | import me.metallicgoat.tweaksaddon.api.gentiers.SuddenDeathDragon; 12 | import me.metallicgoat.tweaksaddon.api.unsafe.MBedwarsTweaksAPILayer; 13 | import org.jetbrains.annotations.Nullable; 14 | 15 | import java.util.Collection; 16 | import java.util.List; 17 | 18 | /** 19 | * Represents the API to interact with the Gen Tiers system of MBedwars Tweaks 20 | */ 21 | public class GenTiersAPI { 22 | 23 | /** 24 | * Get the dragons for a specific team in an arena. 25 | * 26 | * @param arena The arena which we are truing to get the dragons 27 | * @param team The team which the dragon belongs to 28 | * @return A list of actively running SuddenDeathDragons 29 | */ 30 | public static List getDragons(Arena arena, Team team) { 31 | Validate.notNull(arena, "arena"); 32 | Validate.notNull(team, "team"); 33 | 34 | return MBedwarsTweaksAPILayer.INSTANCE.getDragons(arena, team); 35 | } 36 | 37 | /** 38 | * Get the dragons for arena. 39 | * 40 | * @param arena The arena which we are truing to get the dragons 41 | * @return A list of actively running SuddenDeathDragons 42 | */ 43 | public static List getDragons(Arena arena) { 44 | Validate.notNull(arena, "arena"); 45 | 46 | return MBedwarsTweaksAPILayer.INSTANCE.getDragons(arena, null); 47 | } 48 | 49 | /** 50 | * Get all existing dragons. 51 | * 52 | * @return A list of actively running SuddenDeathDragons 53 | */ 54 | public static List getDragons() { 55 | return MBedwarsTweaksAPILayer.INSTANCE.getDragons(null, null); 56 | } 57 | 58 | /** 59 | * Get the GenTierState of an arena 60 | * Will return null if the gen tier system is not running in the specified arena 61 | * 62 | * @param arena the arena where we are grabbing the GenTierState from 63 | * @return The GenTierState of the corresponding arena 64 | */ 65 | @Nullable 66 | public static GenTierState getState(Arena arena) { 67 | Validate.notNull(arena, "arena"); 68 | 69 | return MBedwarsTweaksAPILayer.INSTANCE.getGenTierState(arena); 70 | } 71 | 72 | /** 73 | * Get all configured Gen Tiers 74 | * 75 | * @return An unmodifiable collection of all configured Gen Tiers 76 | */ 77 | public static Collection getTiers() { 78 | return Collections.unmodifiableCollection(MBedwarsTweaksAPILayer.INSTANCE.getGenTierLevels()); 79 | } 80 | 81 | /** 82 | * Get a specific Gen Tier by its level 83 | * 84 | * @param level The level of the Gen Tier you are trying to get 85 | * @return The Gen Tier of the corresponding level 86 | */ 87 | @Nullable 88 | public static GenTierLevel getTier(int level) { 89 | return MBedwarsTweaksAPILayer.INSTANCE.getGenTierLevel(level); 90 | } 91 | 92 | /** 93 | * Get the first Gen Tier (level 1) 94 | * 95 | * @return The Gen Tier of level 1 96 | */ 97 | @Nullable 98 | public static GenTierLevel getFirstTier() { 99 | return MBedwarsTweaksAPILayer.INSTANCE.getGenTierLevel(1); 100 | } 101 | 102 | /** 103 | * Register a custom GenTierHandler! You will need to implement the GenTierHandler 104 | * 105 | * @param handler The GenTier you are registering 106 | */ 107 | public static void registerHandler(GenTierHandler handler) { 108 | Validate.notNull(handler, "handler"); 109 | 110 | MBedwarsTweaksAPILayer.INSTANCE.registerGenTierHandler(handler); 111 | } 112 | 113 | /** 114 | * Unregisters a Gen Tier Handler. Using this you could replace internal handlers 115 | * 116 | * @param id The id of the handler 117 | */ 118 | public static void unregisterHandler(String id) { 119 | Validate.notNull(id, "id"); 120 | 121 | MBedwarsTweaksAPILayer.INSTANCE.unregisterGenTierHandler(id); 122 | } 123 | 124 | /** 125 | * Gets a GenTierHandler by its id 126 | * 127 | * @param id The id of the handler 128 | */ 129 | @Nullable 130 | public static GenTierHandler getHandlerById(String id) { 131 | Validate.notNull(id, "id"); 132 | 133 | return MBedwarsTweaksAPILayer.INSTANCE.getGenTierHandlerById(id); 134 | } 135 | 136 | /** 137 | * Get all registered GenTierHandlers 138 | * 139 | * @return all registered GenTierHandlers 140 | */ 141 | public static Collection getHandlers() { 142 | return MBedwarsTweaksAPILayer.INSTANCE.getGenTierHandlers(); 143 | } 144 | 145 | /** 146 | * Get the trigger handler used for the sudden death team upgrade. 147 | * 148 | * @return The singletone UpgradeTriggerHandler instance for the sudden death upgrade 149 | */ 150 | public static UpgradeTriggerHandler getSuddenDeathUpgrade() { 151 | return MBedwarsTweaksAPILayer.INSTANCE.getSuddenDeathUpgrade(); 152 | } 153 | 154 | /** 155 | * Reloads the gen-tiers config and applies any changes made to it 156 | *

157 | * Note: This will NOT update any arenas that are currently running the gen tier system, 158 | * and as a result might cause weird states for active arenas. 159 | * Runs IO on the same thread that it was called on. 160 | *

161 | */ 162 | public static void reloadConfig() { 163 | MBedwarsTweaksAPILayer.INSTANCE.reloadGenTierConfig(); 164 | } 165 | } -------------------------------------------------------------------------------- /MBedwarsTweaks/src/main/java/me/metallicgoat/tweaksaddon/config/ConfigLoader.java: -------------------------------------------------------------------------------- 1 | package me.metallicgoat.tweaksaddon.config; 2 | 3 | import de.marcely.bedwars.api.configuration.ConfigurationAPI; 4 | import de.marcely.bedwars.api.event.ConfigsLoadEvent; 5 | import de.marcely.bedwars.tools.Helper; 6 | import java.time.Duration; 7 | import me.metallicgoat.tweaksaddon.MBedwarsTweaksPlugin; 8 | import me.metallicgoat.tweaksaddon.api.GenTiersAPI; 9 | import me.metallicgoat.tweaksaddon.api.gentiers.GenTierHandler; 10 | import me.metallicgoat.tweaksaddon.config.ConfigManager.FileType; 11 | import me.metallicgoat.tweaksaddon.api.gentiers.GenTierLevel; 12 | import me.metallicgoat.tweaksaddon.api.gentiers.GenTierActionType; 13 | import me.metallicgoat.tweaksaddon.utils.Console; 14 | import me.metallicgoat.tweaksaddon.utils.Util; 15 | import org.bukkit.Material; 16 | import org.bukkit.event.EventHandler; 17 | import org.bukkit.event.Listener; 18 | 19 | import java.util.ArrayList; 20 | import java.util.Arrays; 21 | import java.util.HashMap; 22 | 23 | public class ConfigLoader implements Listener { 24 | 25 | @EventHandler 26 | public void onConfigLoad(ConfigsLoadEvent event) { 27 | if (!event.isStartup()) { 28 | MBedwarsTweaksPlugin.getInstance().loadTweaks(false); // Reload tweaks 29 | } 30 | } 31 | 32 | public static void loadTweaksConfigs(MBedwarsTweaksPlugin plugin) { 33 | final long start = System.currentTimeMillis(); 34 | 35 | final boolean defaultDropTypesExist = ( 36 | Util.getDropType("iron") != null 37 | && Util.getDropType("gold") != null 38 | && Util.getDropType("diamond") != null 39 | && Util.getDropType("emerald") != null 40 | ); 41 | 42 | // Replace with these values if we know defaults are still setup 43 | if (defaultDropTypesExist) { 44 | MainConfig.gen_tiers_start_spawners = new ArrayList<>(Arrays.asList( 45 | Util.getDropType("emerald"), 46 | Util.getDropType("diamond") 47 | )); 48 | 49 | MainConfig.disable_empty_generators_spawners = new ArrayList<>(Arrays.asList( 50 | Util.getDropType("iron"), 51 | Util.getDropType("gold") 52 | )); 53 | } 54 | 55 | GenTiersConfig.gen_tier_levels = getDefaultGenTiers(); 56 | 57 | ConfigManager.load(plugin, MainConfig.class, FileType.MAIN); 58 | ConfigManager.load(plugin, SwordsToolsConfig.class, FileType.SWORDS_TOOLS); 59 | GenTiersConfig.load(); // We load gen tiers a special way 60 | 61 | overrideMBedwarsConfigs(); 62 | 63 | final long end = System.currentTimeMillis(); 64 | 65 | Console.printInfo("Configs loaded in " + (end - start) + "ms."); 66 | } 67 | 68 | public static HashMap getDefaultGenTiers() { 69 | final GenTierHandler genUpgradeHandler = GenTiersAPI.getHandlerById(GenTierActionType.GEN_UPGRADE.getDefaultHandlerId()); 70 | 71 | return new HashMap() {{ 72 | put(1, new GenTierLevel( 73 | 1, 74 | "Diamond II", "&eTier &cII", 75 | "diamond", 76 | genUpgradeHandler, Duration.ofMinutes(6), 30D, null, 77 | "&bDiamond Generators &ehave been upgraded to Tier &4II", 78 | null 79 | )); 80 | put(2, new GenTierLevel( 81 | 2, 82 | "Emerald II", "&eTier &cII", 83 | "emerald", 84 | genUpgradeHandler, Duration.ofMinutes(6), 40D, null, 85 | "&aEmerald Generators &ehave been upgraded to Tier &4II", 86 | null 87 | )); 88 | put(3, new GenTierLevel( 89 | 3, 90 | "Diamond III", "&eTier &cIII", 91 | "diamond", 92 | genUpgradeHandler, Duration.ofMinutes(6), 20D, null, 93 | "&bDiamond Generators &ehave been upgraded to Tier &4III", 94 | null 95 | )); 96 | put(4, new GenTierLevel( 97 | 4, 98 | "Emerald III", "&eTier &cIII", 99 | "emerald", 100 | genUpgradeHandler, Duration.ofMinutes(6), 30D, null, 101 | "&aEmerald Generators &ehave been upgraded to Tier &4III", 102 | null 103 | )); 104 | put(5, new GenTierLevel(5, "Bed Destroy", GenTiersAPI.getHandlerById(GenTierActionType.BED_DESTROY.getDefaultHandlerId()), Duration.ofMinutes(5), null, null)); 105 | put(6, new GenTierLevel(6, "Sudden Death", GenTiersAPI.getHandlerById(GenTierActionType.SUDDEN_DEATH.getDefaultHandlerId()), Duration.ofMinutes(10), null, null)); 106 | put(7, new GenTierLevel(7, "Game Over", GenTiersAPI.getHandlerById(GenTierActionType.GAME_OVER.getDefaultHandlerId()), Duration.ofMinutes(10), null, null)); 107 | }}; 108 | } 109 | 110 | private static void overrideMBedwarsConfigs() { 111 | // Configure MBedwars to work like our old feature did 112 | if (MainConfig.personal_ender_chests_enabled) { 113 | try { 114 | final boolean teamchestEnabled = (boolean) ConfigurationAPI.get().getValue("teamchest-enabled"); 115 | final Material teamchestBlock = (Material) ConfigurationAPI.get().getValue("teamchest-block"); 116 | 117 | if (teamchestEnabled && teamchestBlock == Helper.get().getMaterialByName("ENDER_CHEST")) { 118 | ConfigurationAPI.get().setValue("teamchest-enabled", false); 119 | Console.printWarn( 120 | "WARNING: You have \"personal-ender-chests-enabled\" enabled. This setting will be removed in the future, as it is already possible in MBedwars.", 121 | "Open your MBedwars config.yml, and either set \"teamchest-enabled\" to false, or set \"teamchest-block\" to CHEST.", 122 | "Currently, we are using the MBedwars configuration api to override these values for you, but we may not do this in the future." 123 | ); 124 | } 125 | 126 | } catch (IllegalArgumentException e) { 127 | Console.printWarn("Failed to apply personal ender chests. Try updating MBedwars, or disabling \"personal-ender-chests-enabled\""); 128 | } 129 | } 130 | 131 | if (MainConfig.tracker_hotbar_message_enabled) { 132 | try { 133 | final boolean mbedwarsActionbarEnabled = (boolean) ConfigurationAPI.get().getValue("actionbar-enabled"); 134 | 135 | if (mbedwarsActionbarEnabled) { 136 | ConfigurationAPI.get().setValue("actionbar-enabled", false); 137 | Console.printWarn( 138 | "NOTE: You have \"tracker-hotbar-message-enabled\" enabled. This setting will interfere with the MBedwars's \"actionbar-enabled\" config.", 139 | "We have automatically disabled the MBedwars actionbar, however you may want to disable it yourself in the MBedwars config.yml." 140 | ); 141 | } 142 | 143 | } catch (IllegalArgumentException e) { 144 | Console.printWarn("Failed to apply tracker hotbar message. Try updating MBedwars, or disabling \"tracker-hotbar-message-enabled\""); 145 | } 146 | } 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /MBedwarsTweaks/src/main/java/me/metallicgoat/tweaksaddon/MBedwarsTweaksAddon.java: -------------------------------------------------------------------------------- 1 | package me.metallicgoat.tweaksaddon; 2 | 3 | import de.marcely.bedwars.api.BedwarsAPI; 4 | import de.marcely.bedwars.api.BedwarsAddon; 5 | import de.marcely.bedwars.api.GameAPI; 6 | import de.marcely.bedwars.api.command.CommandHandler; 7 | import de.marcely.bedwars.api.command.CommandsCollection; 8 | import de.marcely.bedwars.api.command.SubCommand; 9 | import de.marcely.bedwars.api.message.DefaultMessageMappings; 10 | import de.marcely.bedwars.api.message.MessageAPI; 11 | import me.metallicgoat.tweaksaddon.commands.SpecialItemCommand; 12 | import me.metallicgoat.tweaksaddon.config.ConfigLoader; 13 | import me.metallicgoat.tweaksaddon.gentiers.GenTiers; 14 | import me.metallicgoat.tweaksaddon.gentiers.dragons.SuddenDeathUpgrade; 15 | import me.metallicgoat.tweaksaddon.integration.DependencyLoader; 16 | import me.metallicgoat.tweaksaddon.tweaks.advancedswords.*; 17 | import me.metallicgoat.tweaksaddon.tweaks.cosmetic.*; 18 | import me.metallicgoat.tweaksaddon.tweaks.explosives.*; 19 | import me.metallicgoat.tweaksaddon.tweaks.messages.*; 20 | import me.metallicgoat.tweaksaddon.tweaks.misc.*; 21 | import me.metallicgoat.tweaksaddon.tweaks.playerlimitbypass.PlayerLimitBypass; 22 | import me.metallicgoat.tweaksaddon.tweaks.playerlimitbypass.PlayerLimitBypassPaper; 23 | import me.metallicgoat.tweaksaddon.tweaks.spawners.*; 24 | import me.metallicgoat.tweaksaddon.tweaks.spectialitems.*; 25 | import me.metallicgoat.tweaksaddon.utils.Console; 26 | import org.bukkit.plugin.PluginManager; 27 | 28 | public class MBedwarsTweaksAddon extends BedwarsAddon { 29 | 30 | private final MBedwarsTweaksPlugin plugin; 31 | 32 | public MBedwarsTweaksAddon(MBedwarsTweaksPlugin plugin) { 33 | super(plugin); 34 | 35 | this.plugin = plugin; 36 | } 37 | 38 | public void registerMessageMappings() { 39 | try { 40 | MessageAPI.get().registerDefaultMappings( 41 | DefaultMessageMappings.loadInternalYAML(this.plugin, this.plugin.getResource("messages.yml")) 42 | ); 43 | } catch (Exception e) { 44 | e.printStackTrace(); 45 | } 46 | } 47 | 48 | public void registerEvents() { 49 | final MBedwarsTweaksPlugin plugin = MBedwarsTweaksPlugin.getInstance(); 50 | final PluginManager manager = plugin.getServer().getPluginManager(); 51 | 52 | // CONTRIBUTORS: PLEASE READ 53 | // NOTE: Please keep the following categories and classes in alphabetical order 54 | // NOTE: If you are adding support for your own plugin, please add your class to the hooks folder 55 | 56 | // Advanced Swords 57 | manager.registerEvents(new AlwaysSword(), plugin); 58 | manager.registerEvents(new AntiChest(), plugin); 59 | manager.registerEvents(new AntiDrop(), plugin); 60 | manager.registerEvents(new DegradingBuyGroups(), plugin); 61 | manager.registerEvents(new ReplaceSwordOnBuy(), plugin); 62 | manager.registerEvents(new ReplaceToolOnBuy(), plugin); 63 | manager.registerEvents(new ToolSwordHelper(), plugin); 64 | 65 | // Cosmetic 66 | manager.registerEvents(new FriendlyVillagers(), plugin); 67 | manager.registerEvents(new HealPoolParticles(), plugin); 68 | manager.registerEvents(new InvisFootstepsParticles(), plugin); 69 | manager.registerEvents(new PlaceholderUpdating(), plugin); 70 | manager.registerEvents(new SpongeParticles(), plugin); 71 | 72 | // Explosives 73 | manager.registerEvents(new DisableFireballOutsideArena(), plugin); 74 | manager.registerEvents(new ExplosiveFallDamageMultiplier(), plugin); 75 | manager.registerEvents(new FireballBlockBreakWhitelist(), plugin); 76 | manager.registerEvents(new FireballThrowEffects(), plugin); 77 | manager.registerEvents(new FireballUseCoolDown(), plugin); 78 | manager.registerEvents(new TNTIgniteCountdown(), plugin); 79 | 80 | // Messages 81 | manager.registerEvents(new BuyMessage(), plugin); 82 | manager.registerEvents(new CustomBedBreakMessage(), plugin); 83 | manager.registerEvents(new FinalKillSuffix(), plugin); 84 | manager.registerEvents(new TeamEliminate(), plugin); 85 | manager.registerEvents(new TopKillerMessage(), plugin); 86 | 87 | // Misc 88 | manager.registerEvents(new BlockArenaStats(), plugin); 89 | manager.registerEvents(new EmptyContainers(), plugin); 90 | manager.registerEvents(new HeightCap(), plugin); 91 | manager.registerEvents(new LockTeamChest(), plugin); 92 | manager.registerEvents(new PearlSoundBroadcast(), plugin); 93 | manager.registerEvents(new PermanentEffects(), plugin); 94 | manager.registerEvents(new PlaceBlocksOnBed(), plugin); 95 | manager.registerEvents(new RemoveInvisOnDamage(), plugin); 96 | manager.registerEvents(new WorldBorderResize(), plugin); 97 | manager.registerEvents(new LootDropAtEliminatedTeamBase(), plugin); 98 | //manager.registerEvents(new TieBreaker(), plugin); 99 | 100 | // Spawners 101 | manager.registerEvents(new AFKSpawners(), plugin); 102 | manager.registerEvents(new DisableEmptyGenerators(), plugin); 103 | manager.registerEvents(new SpawnerUpgrade(), plugin); 104 | 105 | // Special Items 106 | manager.registerEvents(new SpecialItemCooldown(), plugin); 107 | manager.registerEvents(new TrackerDistance(), plugin); 108 | 109 | // Gen Tiers 110 | manager.registerEvents(new GenTiers(), plugin); 111 | 112 | // Server Events 113 | manager.registerEvents(new ConfigLoader(), plugin); 114 | manager.registerEvents(new DependencyLoader(), plugin); 115 | 116 | // Version Specific Events 117 | try { 118 | Class.forName("io.papermc.paper.event.player.PlayerServerFullCheckEvent"); 119 | manager.registerEvents(new PlayerLimitBypass(), plugin); 120 | } catch (ClassNotFoundException ignored) { 121 | manager.registerEvents(new PlayerLimitBypassPaper(), plugin); 122 | } 123 | } 124 | 125 | public void registerCommands() { 126 | final CommandsCollection commands = BedwarsAPI.getRootCommandsCollection(); 127 | 128 | // Commands in tools commands collection 129 | { 130 | final SubCommand tools = commands.getCommand("tools"); 131 | 132 | if (tools instanceof CommandsCollection) { 133 | final CommandsCollection toolsCollection = (CommandsCollection) tools; 134 | 135 | registerCommand("showspecialitems", toolsCollection, new SpecialItemCommand()); 136 | 137 | } else { 138 | Console.printWarn("Failed to register command showspecialitems in \"/bw tools\" commands collection. "); 139 | } 140 | } 141 | } 142 | 143 | public void registerCommand(String name, CommandsCollection collection, CommandHandler handler) { 144 | final SubCommand command = collection.addCommand(name); 145 | 146 | if (command == null) { 147 | Console.printWarn("Failed to register command " + name + ". Possible interference with another plugin?"); 148 | return; 149 | } 150 | 151 | command.setHandler(handler); 152 | } 153 | 154 | 155 | public void registerUpgrades() { 156 | GameAPI.get().registerUpgradeTriggerHandler(SuddenDeathUpgrade.INSTANCE); 157 | } 158 | 159 | @Override 160 | public String getName() { 161 | return plugin.getName(); 162 | } 163 | } 164 | -------------------------------------------------------------------------------- /MBedwarsTweaks/src/main/java/me/metallicgoat/tweaksaddon/config/GenTiersConfig.java: -------------------------------------------------------------------------------- 1 | package me.metallicgoat.tweaksaddon.config; 2 | 3 | import de.marcely.bedwars.tools.Helper; 4 | import de.marcely.bedwars.tools.YamlConfigurationDescriptor; 5 | import java.io.File; 6 | import java.time.Duration; 7 | import java.time.temporal.ChronoUnit; 8 | import java.util.HashMap; 9 | import java.util.Map; 10 | import me.metallicgoat.tweaksaddon.api.gentiers.GenTierHandler; 11 | import me.metallicgoat.tweaksaddon.utils.Console; 12 | import me.metallicgoat.tweaksaddon.MBedwarsTweaksPlugin; 13 | import me.metallicgoat.tweaksaddon.api.gentiers.GenTierLevel; 14 | import me.metallicgoat.tweaksaddon.api.gentiers.GenTierActionType; 15 | import me.metallicgoat.tweaksaddon.utils.Util; 16 | import org.bukkit.Sound; 17 | import org.bukkit.configuration.ConfigurationSection; 18 | import org.bukkit.configuration.file.FileConfiguration; 19 | import org.bukkit.configuration.file.YamlConfiguration; 20 | 21 | public class GenTiersConfig { 22 | 23 | public static Map gen_tier_levels = new HashMap<>(); 24 | 25 | public static void load() { 26 | synchronized (ConfigLoader.class) { 27 | try { 28 | loadUnchecked(); 29 | } catch (Exception e) { 30 | e.printStackTrace(); 31 | } 32 | } 33 | } 34 | 35 | private static void loadUnchecked() throws Exception { 36 | final String pluginVer = MBedwarsTweaksPlugin.getInstance().getDescription().getVersion(); 37 | final File file = new File(MBedwarsTweaksPlugin.getAddon().getDataFolder(), "gen-tiers.yml"); 38 | 39 | if (!file.exists()) { 40 | save(file, pluginVer); 41 | return; 42 | } 43 | 44 | // load it 45 | final FileConfiguration config = new YamlConfiguration(); 46 | 47 | try { 48 | config.load(file); 49 | } catch (Exception e) { 50 | e.printStackTrace(); 51 | } 52 | 53 | // read it 54 | final String configVer = config.getString("version"); 55 | final ConfigurationSection tiersSection = config.getConfigurationSection("Gen-Tiers"); 56 | 57 | if (tiersSection != null) { 58 | gen_tier_levels.clear(); 59 | 60 | int i = 1; 61 | for (String levelNumString : tiersSection.getKeys(false)) { 62 | final int levelNum = i++; 63 | 64 | final ConfigurationSection section = tiersSection.getConfigurationSection(levelNumString); 65 | 66 | final String tierName = section.getString("Tier-Name"); 67 | String genTierHandlerId = section.getString("Handler-Id"); 68 | final String typeString = section.getString("Drop-Type"); 69 | final double speed = section.getDouble("Drop-Speed"); 70 | final int limit = section.getInt("Max-Nearby-Items", -1); 71 | final double time = section.getDouble("Time"); 72 | String message = section.getString("Message"); 73 | final String soundString = section.getString("Earn-Sound"); 74 | String holoName = section.getString("Holo-Usage"); 75 | 76 | message = message == null || message.isEmpty() ? null : message; 77 | 78 | { 79 | // OLD VALUES 80 | if (holoName == null) 81 | holoName = section.getString("Tier-Level"); 82 | 83 | if (genTierHandlerId == null) 84 | genTierHandlerId = section.getString("Action"); 85 | } 86 | 87 | // TODO Validate other values not null 88 | if (genTierHandlerId == null) { 89 | Console.printConfigWarn("Failed to load tier: [" + tierName + "]. Handler-Id is null", "gen-tiers"); 90 | continue; 91 | } 92 | 93 | final GenTierHandler handler = Util.getGenTierHandlerById(genTierHandlerId.toLowerCase()); 94 | 95 | if (handler == null) { 96 | Console.printConfigWarn("Failed to load tier: [" + tierName + "]. Handler-Id '" + genTierHandlerId + "' is invalid. Has it been registered?", "gen-tiers"); 97 | continue; 98 | } 99 | 100 | Sound earnSound = null; 101 | 102 | if (soundString != null) 103 | earnSound = Helper.get().getSoundByName(soundString); 104 | 105 | if (handler.getActionType() == GenTierActionType.GEN_UPGRADE) { 106 | 107 | final GenTierLevel genTierLevel = new GenTierLevel( 108 | levelNum, 109 | tierName, 110 | holoName, 111 | typeString, 112 | handler, 113 | Duration.ofSeconds((long) (time * 60D)), 114 | speed, 115 | limit > 0 ? limit : null, 116 | message, 117 | earnSound 118 | ); 119 | 120 | gen_tier_levels.put(levelNum, genTierLevel); 121 | 122 | } else { 123 | final GenTierLevel genTierLevel = new GenTierLevel( 124 | levelNum, 125 | tierName, 126 | handler, 127 | Duration.ofSeconds((long) (time * 60D)), 128 | message, 129 | earnSound 130 | ); 131 | 132 | gen_tier_levels.put(levelNum, genTierLevel); 133 | } 134 | } 135 | } 136 | 137 | // auto update file if newer version 138 | if (!pluginVer.equals(configVer)) { 139 | updateOldConfigs(config); 140 | save(file, pluginVer); 141 | } 142 | } 143 | 144 | private static void save(File file, String pluginVer) throws Exception { 145 | final YamlConfigurationDescriptor config = new YamlConfigurationDescriptor(); 146 | 147 | config.addComment("Used for Auto Updating. Do not Change! (Unless you know what you are doing)"); 148 | config.set("version", pluginVer); 149 | 150 | config.addEmptyLine(); 151 | config.addComment("MAKE SURE Gen-Tiers are enabled in the config.yml!"); 152 | config.addEmptyLine(); 153 | 154 | config.addComment("PAPI-Usage (The value used in our PAPI Placeholders during this tier)"); 155 | config.addComment("Holo-Usage (The values used in holos during this tier)"); 156 | config.addComment("Action (gen-upgrade, bed-destroy, sudden-death, game-over)"); 157 | config.addComment("Time (time in minutes until action - NOTE time starts after the last action)"); 158 | config.addComment("Message (chat message sent on trigger)"); 159 | config.addComment("Earn-Sound (sound played on trigger) (You have to add this config if you want it)"); 160 | config.addEmptyLine(); 161 | config.addComment("--- Spawner Only --- "); 162 | config.addComment("Type (Type of spawner that will be updated)"); 163 | config.addComment("Speed (How often an item drops (in seconds))"); 164 | config.addComment("Max-Nearby-Items (how many items the spawner will produce before it goes on hold)"); 165 | 166 | config.addEmptyLine(); 167 | 168 | int i = 1; 169 | for (Map.Entry entry : gen_tier_levels.entrySet()) { 170 | 171 | if (entry.getKey() == null || entry.getValue() == null) 172 | continue; 173 | 174 | final GenTierLevel level = entry.getValue(); 175 | final String configKey = "Gen-Tiers." + (i++) + "."; 176 | 177 | config.set(configKey + "Handler-Id", level.getHandler().getId()); 178 | config.set(configKey + "Time", level.getTime().get(ChronoUnit.SECONDS)/60D); 179 | config.set(configKey + "Tier-Name", level.getTierName()); 180 | 181 | if (level.getHandler().getActionType() == GenTierActionType.GEN_UPGRADE) { 182 | config.set(configKey + "Holo-Usage", level.getHoloName()); 183 | config.set(configKey + "Drop-Type", level.getTypeId()); 184 | config.set(configKey + "Drop-Speed", level.getSpeed()); 185 | 186 | if (level.getLimit() != null) 187 | config.set(configKey + "Max-Nearby-Items", level.getLimit()); 188 | } 189 | 190 | if (level.getEarnMessage() != null) 191 | config.set(configKey + "Message", level.getEarnMessage()); 192 | 193 | if (level.getEarnSound() != null) 194 | config.set(configKey + "Earn-Sound", level.getEarnSound().name()); 195 | } 196 | 197 | config.save(file); 198 | } 199 | 200 | private static void updateOldConfigs(FileConfiguration config) { 201 | // No updates yet :) 202 | } 203 | } 204 | -------------------------------------------------------------------------------- /MBedwarsTweaks/src/main/java/me/metallicgoat/tweaksaddon/tweaks/advancedswords/ToolSwordHelper.java: -------------------------------------------------------------------------------- 1 | package me.metallicgoat.tweaksaddon.tweaks.advancedswords; 2 | 3 | import de.marcely.bedwars.api.GameAPI; 4 | import de.marcely.bedwars.api.arena.Arena; 5 | import de.marcely.bedwars.api.arena.ArenaStatus; 6 | import de.marcely.bedwars.api.arena.Team; 7 | import de.marcely.bedwars.api.event.arena.ArenaDeleteEvent; 8 | import de.marcely.bedwars.api.event.arena.ArenaStatusChangeEvent; 9 | import de.marcely.bedwars.api.event.arena.RoundStartEvent; 10 | import de.marcely.bedwars.api.event.player.PlayerBuyInShopEvent; 11 | import de.marcely.bedwars.api.game.shop.BuyGroup; 12 | import de.marcely.bedwars.api.game.shop.ShopItem; 13 | import de.marcely.bedwars.api.game.shop.product.ItemShopProduct; 14 | import de.marcely.bedwars.api.game.shop.product.ShopProduct; 15 | import de.marcely.bedwars.tools.Helper; 16 | import java.util.IdentityHashMap; 17 | import java.util.Map; 18 | import me.metallicgoat.hotbarmanageraddon.HotbarManagerTools; 19 | import me.metallicgoat.tweaksaddon.integration.DependType; 20 | import me.metallicgoat.tweaksaddon.MBedwarsTweaksPlugin; 21 | import me.metallicgoat.tweaksaddon.config.SwordsToolsConfig; 22 | import org.bukkit.Bukkit; 23 | import org.bukkit.ChatColor; 24 | import org.bukkit.Material; 25 | import org.bukkit.entity.Player; 26 | import org.bukkit.event.EventHandler; 27 | import org.bukkit.event.EventPriority; 28 | import org.bukkit.event.Listener; 29 | import org.bukkit.inventory.Inventory; 30 | import org.bukkit.inventory.ItemStack; 31 | import org.bukkit.inventory.meta.ItemMeta; 32 | 33 | public class ToolSwordHelper implements Listener { 34 | 35 | private static final Map buyGroupTrackerMap = new IdentityHashMap<>(); 36 | public static Material WOOD_SWORD; 37 | 38 | public static void load() { 39 | // Get wooden sword given on spawn 40 | { 41 | Material sword = Helper.get().getMaterialByName("WOODEN_SWORD"); 42 | 43 | if (sword == null) 44 | sword = Material.AIR; 45 | 46 | WOOD_SWORD = sword; 47 | } 48 | } 49 | 50 | @EventHandler 51 | public static void onRoundStart(RoundStartEvent event) { 52 | final Arena arena = event.getArena(); 53 | 54 | buyGroupTrackerMap.put(arena, new BuyGroupTracker()); 55 | } 56 | 57 | @EventHandler 58 | public void onShopBuy(PlayerBuyInShopEvent event) { 59 | final BuyGroup group = event.getItem().getBuyGroup(); 60 | 61 | if (group == null || !event.getProblems().isEmpty()) 62 | return; 63 | 64 | final BuyGroupTracker tracker = buyGroupTrackerMap.get(event.getArena()); 65 | 66 | if(tracker != null) 67 | tracker.upgradeLevel(group, event.getItem().getBuyGroupLevel(), event.getPlayer()); 68 | } 69 | 70 | @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) 71 | public void onArenaStatusChangeEvent(ArenaStatusChangeEvent event) { 72 | if (event.getOldStatus() == ArenaStatus.RUNNING) 73 | removeArena(event.getArena()); 74 | } 75 | 76 | @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) 77 | public void onArenaDeleteEvent(ArenaDeleteEvent event) { 78 | removeArena(event.getArena()); 79 | } 80 | 81 | private void removeArena(Arena arena) { 82 | buyGroupTrackerMap.remove(arena); 83 | } 84 | 85 | public static BuyGroupTracker getBuyGroupTracker(Arena arena) { 86 | if(arena == null || !buyGroupTrackerMap.containsKey(arena)) 87 | return new BuyGroupTracker(); 88 | 89 | return buyGroupTrackerMap.get(arena); 90 | } 91 | 92 | public static ItemStack getDefaultWoodSword(Player player, Arena arena) { 93 | if (player == null || arena == null) 94 | return new ItemStack(WOOD_SWORD); 95 | 96 | final Team team = arena.getPlayerTeam(player); 97 | if (team == null) 98 | return new ItemStack(WOOD_SWORD); 99 | 100 | for (ItemStack is : arena.getItemsGivenOnSpawn(player, team, true, true)) { 101 | if (is.getType() == WOOD_SWORD) 102 | return is.clone(); 103 | } 104 | 105 | return new ItemStack(WOOD_SWORD); 106 | } 107 | 108 | public static boolean isSword(Material material) { 109 | return material.name().contains("SWORD"); 110 | } 111 | 112 | public static boolean isTool(Material material) { 113 | return material.name().contains("AXE"); 114 | } 115 | 116 | public static boolean isAxe(Material material) { 117 | return isTool(material) && !material.name().contains("_AXE"); 118 | } 119 | 120 | public static boolean isPickaxe(Material material) { 121 | return material.name().contains("_PICKAXE"); 122 | } 123 | 124 | public static int getSwordToolLevel(Material tool) { 125 | 126 | final String toolName = tool.name(); 127 | 128 | if (toolName.contains("WOOD")) { 129 | return 1; 130 | } else if (toolName.contains("STONE")) { 131 | return 2; 132 | } else if (toolName.contains("IRON")) { 133 | return 3; 134 | } else if (toolName.contains("GOLD")) { 135 | return 4; 136 | } else if (toolName.contains("DIAMOND")) { 137 | return 5; 138 | } else if (toolName.contains("NETHERITE")) { 139 | return 6; 140 | } else { 141 | return 0; 142 | } 143 | } 144 | 145 | public static Material getToolInShopProduct(ShopItem shopItem) { 146 | for (ShopProduct rawProduct : shopItem.getProducts()) { 147 | if (!(rawProduct instanceof ItemShopProduct)) 148 | continue; 149 | 150 | final ItemStack[] is = ((ItemShopProduct) rawProduct).getItemStacks(); 151 | for (ItemStack item : is) { 152 | if (!isTool(item.getType()) || !isNotToIgnore(ChatColor.stripColor(shopItem.getDisplayName()))) 153 | continue; 154 | 155 | return item.getType(); 156 | } 157 | } 158 | return Material.AIR; 159 | } 160 | 161 | // Some items may look like a sword, but not be one. Example: Special Items 162 | public static boolean isNotToIgnore(ItemStack itemStack) { 163 | final ItemMeta meta = itemStack.getItemMeta(); 164 | boolean isNotToIgnore = true; 165 | if (meta != null) { 166 | for (String s : SwordsToolsConfig.tools_swords_do_not_effect) { 167 | if (s.equals(ChatColor.stripColor(meta.getDisplayName())) && !s.equals("")) { 168 | isNotToIgnore = false; 169 | } 170 | } 171 | } 172 | return isNotToIgnore; 173 | } 174 | 175 | public static boolean isNotToIgnore(String name) { 176 | boolean isNotToIgnore = true; 177 | for (String s : SwordsToolsConfig.tools_swords_do_not_effect) { 178 | final String formatted = ChatColor.translateAlternateColorCodes('&', s); 179 | if (formatted.equals(name) && !s.equals("")) { 180 | isNotToIgnore = false; 181 | } 182 | } 183 | return isNotToIgnore; 184 | } 185 | 186 | // Checks how many swords a player has 187 | public static int getSwordsAmount(Player player) { 188 | int count = 0; 189 | for (ItemStack item : player.getInventory().getContents()) { 190 | if (item != null && isSword(item.getType()) 191 | && ToolSwordHelper.isNotToIgnore(item)) { 192 | count++; 193 | } 194 | } 195 | return count; 196 | } 197 | 198 | // returns true if a player has a sword that is better than wood 199 | public static boolean hasBetterSword(Player player) { 200 | final Inventory pi = player.getInventory(); 201 | for (ItemStack itemStack : pi.getContents()) { 202 | if (itemStack != null 203 | && isSword(itemStack.getType()) 204 | && isNotToIgnore(itemStack) 205 | && itemStack.getType() == ToolSwordHelper.WOOD_SWORD) { 206 | 207 | return true; 208 | } 209 | } 210 | return false; 211 | } 212 | 213 | public static void givePlayerShopItem(Arena arena, Team team, Player player, ShopItem item) { 214 | Bukkit.getScheduler().runTaskLater(MBedwarsTweaksPlugin.getInstance(), () -> item.getProducts().forEach(shopProduct -> { 215 | if (DependType.HOTBAR_MANAGER.isEnabled()) { 216 | for (ShopProduct product : item.getProducts()) { 217 | for (ItemStack itemStack : product.getGivingItems(player, team, arena, 1)) 218 | HotbarManagerTools.giveItemsProperly(itemStack, player, item.getPage(), null, true); 219 | } 220 | } else { 221 | shopProduct.give(player, arena.getPlayerTeam(player), arena, 1); 222 | } 223 | }), 1L); 224 | } 225 | } 226 | --------------------------------------------------------------------------------