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
+ 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