diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5937b35 --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +/nbproject/private/ +/dist/lib/ +/test-in-spigot.bat +/lib/ +/target/ +/build/ +/dist/ \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..5a2684c --- /dev/null +++ b/README.md @@ -0,0 +1,16 @@ +# WGItemFrameBreakFlags + +Requires Worldguard 7 and a 1.16+ server. Other configurations are untested. + +This plugin was specifically made because if the following behavior in spigot https://hub.spigotmc.org/jira/browse/SPIGOT-3999 +which means Worldguard does not catch Physics events causes by Boats, as well as other Removal Causes ( https://hub.spigotmc.org/javadocs/bukkit/org/bukkit/event/hanging/HangingBreakEvent.RemoveCause.html ) + +This plugin serves to cover these specific cases by adding flags for each but cannot and will not implement any more exhaustive checks on the source of the event. + + +Adds: + +* `default-item-frame-destroy` for unknown causes +* `explosion-item-frame-destroy` for explosion-caused item frame destruction +* `obstruction-item-frame-destroy` for when block placement would cause the item frame to break +* `physics-item-frame-destroy` for when physics or bounding boxes (like those of a Boat) cause the item frame to break. \ No newline at end of file diff --git a/licenseheader.txt b/licenseheader.txt new file mode 100644 index 0000000..9d3d499 --- /dev/null +++ b/licenseheader.txt @@ -0,0 +1,5 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/ . + */ \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..8b04296 --- /dev/null +++ b/pom.xml @@ -0,0 +1,238 @@ + + 4.0.0 + + com.github.crashdemons + WGItemFrameBreakFlags + 0.0.1-SNAPSHOT + jar + + WGItemFrameBreakFlags + + + UTF-8 + + + + + mojang + Mojang's Repository + https://libraries.minecraft.net/ + + + spigot-repo + https://hub.spigotmc.org/nexus/content/repositories/snapshots/ + + + md_5-releases + http://repo.md-5.net/content/repositories/releases/ + + + spigot-group-repo + https://hub.spigotmc.org/nexus/content/groups/public/ + + + crashdemons-repo + https://meme.tips/java-repos/ + + + sk89q-repo + http://maven.sk89q.com/repo/ + + + + + + org.spigotmc + spigot-api + 1.16.5-R0.1-SNAPSHOT + + + + com.sk89q.worldguard + worldguard-bukkit + 7.0.4 + + + org.bukkit + bukkit + + + org.spigotmc + spigot-api + + + + + + + org.jetbrains + annotations-java5 + 15.0 + + + junit + junit + 4.13.1 + jar + test + + + org.powermock + powermock-module-junit4 + 2.0.7 + jar + test + + + org.powermock + powermock-api-mockito2 + 2.0.7 + jar + test + + + org.mockito + mockito-core + 3.5.11 + test + + + org.powermock + powermock-api-mockito-common + 1.7.4 + test + + + + + + + ${project.name}-${project.version} + + + ${basedir}/src/main/resources + true + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + 1.8 + 1.8 + true + + **/package-info.java + + + **/package-info.java + + + -Xlint:all + + + + + maven-jar-plugin + 3.2.0 + + + + Maven + ${project.name} + ${project.version} + ${project.groupId} + ${project.organization.name} + + + + + + + + org.codehaus.mojo + versions-maven-plugin + 2.2 + + + org.bukkit + org.spigotmc + + + + + versions + validate + + true + + + use-latest-versions + + + + + + + maven-antrun-plugin + 1.8 + + + package + + + + + + + run + + + + + + + + + + org.eclipse.m2e + lifecycle-mapping + 1.0.0 + + + + + + org.codehaus.mojo + versions-maven-plugin + [2.2,) + + use-latest-versions + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/java/com/github/crashdemons/wgitemframebreakflags/WGItemFrameBreakFlagsPlugin.java b/src/main/java/com/github/crashdemons/wgitemframebreakflags/WGItemFrameBreakFlagsPlugin.java new file mode 100644 index 0000000..65da875 --- /dev/null +++ b/src/main/java/com/github/crashdemons/wgitemframebreakflags/WGItemFrameBreakFlagsPlugin.java @@ -0,0 +1,198 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/ . + */ +package com.github.crashdemons.wgitemframebreakflags; + +import com.sk89q.worldedit.bukkit.BukkitAdapter; +import com.sk89q.worldguard.LocalPlayer; +import com.sk89q.worldguard.WorldGuard; +import com.sk89q.worldguard.bukkit.WorldGuardPlugin; +import com.sk89q.worldguard.protection.flags.StateFlag; +import com.sk89q.worldguard.protection.flags.registry.FlagConflictException; +import com.sk89q.worldguard.protection.flags.registry.FlagRegistry; +import com.sk89q.worldguard.protection.regions.RegionQuery; +import java.util.ArrayList; +import java.util.HashMap; +import org.bukkit.ChatColor; +import org.bukkit.Location; +import org.bukkit.entity.Entity; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.Hanging; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.hanging.HangingBreakByEntityEvent; +import org.bukkit.event.hanging.HangingBreakEvent; +import org.bukkit.plugin.Plugin; +import org.bukkit.plugin.java.JavaPlugin; + +/** + * The main plugin class for WGItemFrameBreakFlagsPlugin + * + * @author crash + */ +public class WGItemFrameBreakFlagsPlugin extends JavaPlugin implements Listener { + public WGItemFrameBreakFlagsPlugin instance = null; + + WorldGuardPlugin wgp = null; + WorldGuard wg = null; + + private static final String SUFFIX_DESTROY = "-destroy"; + private static final EntityType[] SUPPORTED_HANGING_ENTITIES = new EntityType[]{EntityType.ITEM_FRAME,EntityType.PAINTING}; + + private static final HashMap> causeFlagMap = new HashMap<>(); + private static final ArrayList flags = new ArrayList<>(); + + + static{ + for(HangingBreakEvent.RemoveCause cause : HangingBreakEvent.RemoveCause.values()){ + if(cause==HangingBreakEvent.RemoveCause.ENTITY) continue;//entity-item-frame-destroy already handled by WorldGuard. + HashMap entityMap = new HashMap<>(); + for(EntityType hangingType : SUPPORTED_HANGING_ENTITIES){ + String flagName = getFlagName(cause,hangingType); + StateFlag flag = new StateFlag(flagName,true); + entityMap.put(hangingType, flag); + flags.add(flag); + } + causeFlagMap.put(cause, entityMap); + } + } + + private static String getCauseName(HangingBreakEvent.RemoveCause cause){ + return cause.name().toLowerCase().replace("_", "-"); + } + private static String getEntityName(EntityType hangingType){ + return hangingType.name().toLowerCase().replace("_", "-"); + } + private static String getFlagName(HangingBreakEvent.RemoveCause cause, EntityType hangingType){ + return getCauseName(cause)+"-"+getEntityName(hangingType)+SUFFIX_DESTROY; + } + + private static StateFlag getRelevantFlag(HangingBreakEvent.RemoveCause cause, EntityType hangingType){ + HashMap entityFlagMap = causeFlagMap.get(cause); + if(entityFlagMap==null) return null; + return entityFlagMap.get(hangingType); + } + + public WorldGuard getWorldGuard(){ return wg; } + public WorldGuardPlugin getWorldGuardPlugin(){ return wgp; } + + private WorldGuardPlugin findWorldGuardPlugin() { + Plugin plugin = getServer().getPluginManager().getPlugin("WorldGuard"); + + // WorldGuard may not be loaded + if (plugin == null || !(plugin instanceof WorldGuardPlugin)) { + return null; // Maybe you want throw an exception instead + } + + return (WorldGuardPlugin) plugin; + } + + + private boolean wgInit(){ + wgp = findWorldGuardPlugin(); + wg = WorldGuard.getInstance(); + if(wgp==null || wg==null){ + return false; + } + + FlagRegistry registry = wg.getFlagRegistry(); + try { + // register our flag with the registry + for(StateFlag flag : flags){ + registry.register(flag); + } + return true; + } catch (FlagConflictException e) { + // some other plugin registered a flag by the same name already. + // you may want to re-register with a different name, but this + // could cause issues with saved flags in region files. it's better + // to print a message to let the server admin know of the conflict + getLogger().severe("Could not register WG flags due to a conflict with another plugin"); + return false; + } + } + + private boolean pluginInit(){ + return true; + } + + + @Override + public void onLoad() { + instance = this; + if(!wgInit()) return; + //Do Stuff here + } + + @Override + public void onEnable() { + //Do Stuff here + //if(getConfig().getBoolean("dothething")){ } + if(!pluginInit()) return; + getServer().getPluginManager().registerEvents(this, this); + getLogger().info("Enabled."); + + } + + @Override + public void onDisable() { + //saveConfig(); + + //Cleanup here + getLogger().info("Disabled."); + } + + /* + //Example command handler + @Override + public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) { + if (!cmd.getName().equalsIgnoreCase("YourCommand")) { + return false; + } + if (!sender.hasPermission("yourplugin.yourpermission")) { + sender.sendMessage("You do not have permission for this command."); + return true; + } + + //Do stuff + return false; + }*/ + + + //Example event handler + @EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST) + public void onHangingBreak(HangingBreakEvent event) { + Player causePlayer = null; + Entity causeEntity = null; + HangingBreakEvent.RemoveCause cause = event.getCause(); + if(cause==HangingBreakEvent.RemoveCause.ENTITY) return;//this is already handled by WorldGuard + if(event instanceof HangingBreakByEntityEvent){//probably can't run because of the above check anyway + HangingBreakByEntityEvent eevent = (HangingBreakByEntityEvent) event; + causeEntity = eevent.getRemover(); + if(causeEntity instanceof Player) causePlayer = (Player) causeEntity; + } + + Hanging hangingEntity = event.getEntity(); + Location loc = hangingEntity.getLocation(); + + LocalPlayer wgPlayer = causePlayer==null? null : getWorldGuardPlugin().wrapPlayer(causePlayer); + + StateFlag flag = getRelevantFlag(cause,hangingEntity.getType()); + + com.sk89q.worldedit.util.Location wgLoc = BukkitAdapter.adapt(loc); + RegionQuery query = getWorldGuard().getPlatform().getRegionContainer().createQuery(); + StateFlag.State state = query.queryState(wgLoc, wgPlayer, flag); + StateFlag.State warningstate = StateFlag.State.ALLOW;//query.queryState(wgLoc, wgPlayer, FLAG_ITEM_FRAME_BREAK_WARNING); + if(state==StateFlag.State.DENY){ + if(warningstate!=StateFlag.State.DENY && causePlayer!=null){ + causePlayer.sendMessage(ChatColor.RED+"Hey! "+ChatColor.GRAY+"Sorry, but you can't break that here."); + } + event.setCancelled(true); + } + } + +} diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml new file mode 100644 index 0000000..f73f9ff --- /dev/null +++ b/src/main/resources/plugin.yml @@ -0,0 +1,25 @@ +name: WGItemFrameBreakFlags +main: com.github.crashdemons.wgitemframebreakflags.WGItemFrameBreakFlagsPlugin +version: ${project.version} +author: com.github.crashdemons +api-version: 1.13 +description: Example Plugin + +depend: [ WorldGuard ] + + +#commands: +# YourCommand: +# usage: "/ " +# description: Example command +# aliases: [yourcommandalias] +# permission: yourplugin.yourpermission +#permissions: +# YourSpigotPlugin.*: +# description: Gives all Example Permissions +# default: false +# children: +# yourplugin.yourpermission: true +# yourplugin.yourpermission: +# description: Gives access to the example command +# default: op