Skip to content

Commit

Permalink
Adding flags and full setup
Browse files Browse the repository at this point in the history
  • Loading branch information
RedstoneFuture committed Oct 13, 2024
1 parent 5680457 commit 943cff8
Show file tree
Hide file tree
Showing 20 changed files with 974 additions and 0 deletions.
50 changes: 50 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# RedWorldguardFlags
New helpful [WorldGuard](https://dev.bukkit.org/projects/worldguard) Flags provided and supported by the [RedstoneWorld](https://redstoneworld.de) development team.

## Flags

### Used Flag-Types

| Type | Description | Example |
|----------------|-------------------------------------------------------------------------------------------------|------------------|
| Boolean | Specify a normal boolean value via `allow` or `deny`. | `allow` |
| List of Blocks | Define a list of blocks with the extended spelling support of Minecraft objects by this plugin. | `stone,tag=beds` |

### Extended Object List

- `MATERIAL` names
- `MATERIAL` names with wildcards via "*"
- Regex via "r="
- Material-Tag starting with "#" or "tag=" (see <a href="https://jd.papermc.io/paper/1.21.1/org/bukkit/Tag.html">PaperMC Java-Doc</a> and
<a href="https://minecraft.wiki/w/Tag">Minecraft-Wiki</a> for the tag lists)

| Flag | Type | Description | Default State |
|----------------------------|--------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------|
| `dispense-nbt-spawneggs` | Boolean | Toggles whether spawn-eggs with custom NBT data will be dispensed. | allow |
| `vehicle-entity-collision` | Boolean | Toggles whether players or mobs can collide with vehicles, so the vehicle will not move. | allow |
| `lectern-book-place` | Boolean | Toggles whether players can place books on lecterns. (subordinate to the "build" / "block-place" flag) | allow |
| `spawnegg-use` | Boolean | Toggles whether entities can spawn when a player uses spawn-eggs. (overrides the "mob-spawning" flag, subordinate to the "build" flag) | allow |
| `spawnegg-dispense` | Boolean | Toggles whether entities can spawn when a dispenser dispense spawn-eggs. (overrides the "mob-spawning" flag) | allow |
| `elytra-use` | Boolean | Toggles whether players can fly with the Elytra. (subordinate to the "interact" flag) | allow |
| `allow-fishing` | Boolean | Toggles whether players can fish. | allow |
| `boat-breakthrough` | Boolean | Toggles whether boats can destroy hanging entities. | allow |
| `allow-trading` | Boolean | Toggles whether players can trade with a villager or wandering trader. (subordinate to the "interact" flag) | allow |
| `entity-target` | Boolean | Toggles whether entities can set other entities as their target (e.g. for attacking) within their target-range. Activating it afterwards is useless, as the event can only be canceled at the beginning. | allow |
| `fire-burning-out` | Boolean | Toggles whether an ignited `fire` / `soul_fire` stays lit forever or can go out. | allow |
| `allow-place-blocks` | List of Blocks | Specifies which blocks can be place. ¹ (subordinate to the "build" / "block-place" flag and specified the restriction) | `[]` |
| `deny-place-blocks` | List of Blocks | Specifies which blocks can _not_ be place. ¹ (subordinate to the "build" / "block-place" flag and specified the restriction) | `[]` |
| `allow-break-blocks` | List of Blocks | Specifies which blocks can be break. ¹ (subordinate to the "build" / "block-break" flag and specified the restriction) | `[]` |
| `deny-break-blocks` | List of Blocks | Specifies which blocks can _not_ be break. ¹ (subordinate to the "build" / "block-break" flag and specified the restriction) | `[]` |
| `reset-blocks` | Integer (Seconds) | Activate a block reset after a specified time. If the value is ≤ 0, the flag is ignored. | _null_ |

¹ If no definition is found, the default case is like the Vanilla behavior: allowed for all blocks (if the player still has building rights). As soon as a block has been defined, the flag is considered a whitelist and everything else is disallowed. For empty entries, the next lower region is requested as usual (inheritance without a combination). The DENY definition is queried before the ALLOW definition, which should be taken into account if the block definition overlaps!

## License
This project is licensed under the permissive [Apache 2.0 License](LICENSE).

## Development

### Event handling

- `event.setCancelled(false);` means that the event will continue to be processed by WorldGuard in this context.
- `event.setCancelled(true);` means that the event is canceled and WorldGuard does not continue to do anything natively.
82 changes: 82 additions & 0 deletions src/main/java/de/redstoneworld/redworldguardflags/Flags.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package de.redstoneworld.redworldguardflags;

import com.sk89q.worldguard.WorldGuard;
import com.sk89q.worldguard.protection.flags.Flag;
import com.sk89q.worldguard.protection.flags.IntegerFlag;
import com.sk89q.worldguard.protection.flags.SetFlag;
import com.sk89q.worldguard.protection.flags.StateFlag;
import com.sk89q.worldguard.protection.flags.registry.FlagConflictException;
import com.sk89q.worldguard.protection.flags.registry.FlagRegistry;
import de.redstoneworld.redworldguardflags.types.StringFlag;

import java.util.logging.Level;

public class Flags {

private final RedWorldGuardFlags plugin;


public Flags(RedWorldGuardFlags plugin) {
this.plugin = plugin;
}

public enum FlagEnum {

DISPENSE_NBT_SPAWNEGGS (new StateFlag("dispense-nbt-spawneggs", true)),
VEHICLE_ENTITY_COLLISION (new StateFlag("vehicle-entity-collision", true)),
LECTERN_BOOK_PLACE (new StateFlag("lectern-book-place", true)),
SPAWNEGG_USE (new StateFlag("spawnegg-use", true)),
SPAWNEGG_DISPENSE (new StateFlag("spawnegg-dispense", true)),
ELYTRA_USE (new StateFlag("elytra-use", true)),
ALLOW_FISHING (new StateFlag("allow-fishing", true)),
BOAT_BREAKTHROUGH (new StateFlag("boat-breakthrough", true)),
ALLOW_TRADING (new StateFlag("allow-trading", true)),
ENTITY_TARGET (new StateFlag("entity-target", true)),
FIRE_BURNING_OUT (new StateFlag("fire-burning-out", true)),

ALLOW_PLACE_BLOCKS (StringFlag.ALLOW_PLACE = new SetFlag<>("allow-place-blocks", new StringFlag(null, null))),
DENY_PLACE_BLOCKS (StringFlag.DENY_PLACE = new SetFlag<>("deny-place-blocks", new StringFlag(null, null))),
ALLOW_BREAK_BLOCKS (StringFlag.ALLOW_BREAK = new SetFlag<>("allow-break-blocks", new StringFlag(null, null))),
DENY_BREAK_BLOCKS (StringFlag.DENY_BREAK = new SetFlag<>("deny-break-blocks", new StringFlag(null, null))),

RESET_BLOCKS (new IntegerFlag("reset-blocks", null));


private final Flag<?> flag;

FlagEnum(Flag<?> flagObject) {
flag = flagObject;
}

public Flag<?> getFlagObj() {
return flag;
}
}

/**
* This method registers all WorldGuard flags that
* are handled with this plugin.
*/
public void registerWorldGuardFlags() {

for (Flags.FlagEnum value : Flags.FlagEnum.values()) {
this.registerFlag(value.getFlagObj());
}
}

/**
* Registering a new WorldGuard flag
*
* @param flag (type of "Flag") the new WorldGuard flag for the registration
*/
private void registerFlag(Flag<?> flag) {
FlagRegistry registry = WorldGuard.getInstance().getFlagRegistry();

try {
registry.register(flag);
} catch (FlagConflictException e) {
plugin.getLogger().log(Level.SEVERE, "Flag: " + flag.getName() + " could not be registered!");
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/**
* This is a plugin that adds some new
* WorldGuard flags as a WorldGuard add-on.
*
* @author Robert Rauh alias RedstoneFuture
*/

package de.redstoneworld.redworldguardflags;

import de.redstoneworld.redworldguardflags.listener.misc.*;
import de.redstoneworld.redworldguardflags.listener.building.BlockBreak;
import de.redstoneworld.redworldguardflags.listener.building.BlockPlace;
import io.papermc.lib.PaperLib;
import org.bukkit.plugin.PluginManager;
import org.bukkit.plugin.java.JavaPlugin;

public class RedWorldGuardFlags extends JavaPlugin {

public void onEnable() {

registerEvents();
}

public void onLoad() {
Flags flags = new Flags(this);
flags.registerWorldGuardFlags();

}

public void onDisable() {

}

private void registerEvents() {
PluginManager pluginMgn = getServer().getPluginManager();

// register Events with Bukkit:
pluginMgn.registerEvents(new BlockBreak(this), this);
pluginMgn.registerEvents(new BlockPlace(this), this);

pluginMgn.registerEvents(new BlockDispense(this), this);
pluginMgn.registerEvents(new BlockFade(this), this);
pluginMgn.registerEvents(new CreatureSpawn(this), this);
pluginMgn.registerEvents(new EntityTargetLivingEntity(this), this);
pluginMgn.registerEvents(new EntityToggleGlide(this), this);
pluginMgn.registerEvents(new HangingBreak(this), this);
pluginMgn.registerEvents(new LecternBookPlace(this), this);
pluginMgn.registerEvents(new PlayerFish(this), this);
pluginMgn.registerEvents(new VehicleEntityCollision(this), this);


// register Events with PaperMC:
PaperLib.suggestPaper(this);

if (PaperLib.isPaper()) {
pluginMgn.registerEvents(new PlayerTrade(this), this);
}

}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package de.redstoneworld.redworldguardflags.listener.building;

import com.sk89q.worldguard.LocalPlayer;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import com.sk89q.worldguard.protection.ApplicableRegionSet;
import de.redstoneworld.redworldguardflags.Flags;
import de.redstoneworld.redworldguardflags.RedWorldGuardFlags;
import de.redstoneworld.redworldguardflags.types.StringFlag;
import de.redstoneworld.redworldguardflags.util.BukkitUtil;
import de.redstoneworld.redworldguardflags.util.WorldGuardUtil;
import de.redstoneworld.redutilities.material.MaterialHelper;
import org.bukkit.Material;
import org.bukkit.block.BlockState;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.scheduler.BukkitRunnable;

import java.util.Set;

public class BlockBreak implements Listener {

private final RedWorldGuardFlags plugin;

public BlockBreak(RedWorldGuardFlags plugin) {
this.plugin = plugin;
}

@EventHandler(priority = EventPriority.HIGH)
public void onBlockBreak(BlockBreakEvent event) {
LocalPlayer localPlayer = WorldGuardPlugin.inst().wrapPlayer(event.getPlayer());
Material targetMaterial = event.getBlock().getType();

if (!WorldGuardUtil.isRestrictedWorld(localPlayer.getWorld()) || WorldGuardUtil.hasWorldBypassPermission(localPlayer)) return;

ApplicableRegionSet set = WorldGuardUtil.getRegionSet(event.getBlock().getLocation());

// Get the resulting MATERIAL list from the flag definition.
Set<Material> allowBreak = MaterialHelper.getMaterials(set.queryValue(null, StringFlag.ALLOW_BREAK));
Set<Material> denyBreak = MaterialHelper.getMaterials(set.queryValue(null, StringFlag.DENY_BREAK));

if ((denyBreak != null) && (denyBreak.contains(targetMaterial))) {
event.setCancelled(true);
plugin.getLogger().info("Cancelled block-break because of the regional '" + Flags.FlagEnum.DENY_BREAK_BLOCKS.getFlagObj().getName()
+ "' flag result.");
return;
}

if ((allowBreak != null) && (!allowBreak.contains(targetMaterial))) {
event.setCancelled(true);
plugin.getLogger().info("Cancelled block-break because it was not found in the regional '"
+ Flags.FlagEnum.ALLOW_BREAK_BLOCKS.getFlagObj().getName() + "' flag result.");
return;
}

int resetDelay = (int) set.queryValue(null, Flags.FlagEnum.RESET_BLOCKS.getFlagObj());
if (resetDelay > 0) {
BlockState blockStateCache = event.getBlock().getState();

plugin.getLogger().info("Allow temporary block-break because of the regional '" + Flags.FlagEnum.RESET_BLOCKS.getFlagObj().getName()
+ "' flag result.");

new BukkitRunnable() {
public void run() {

BukkitUtil.resetBlock(blockStateCache, event.getBlock().getLocation());

}
}.runTaskLater(plugin, resetDelay * 20L);

return;
}

plugin.getLogger().info("Allow block-break because of the regional '" + Flags.FlagEnum.ALLOW_BREAK_BLOCKS.getFlagObj().getName()
+ "' flag result.");

}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package de.redstoneworld.redworldguardflags.listener.building;

import com.sk89q.worldguard.LocalPlayer;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import com.sk89q.worldguard.protection.ApplicableRegionSet;
import de.redstoneworld.redworldguardflags.Flags;
import de.redstoneworld.redworldguardflags.RedWorldGuardFlags;
import de.redstoneworld.redworldguardflags.types.StringFlag;
import de.redstoneworld.redworldguardflags.util.BukkitUtil;
import de.redstoneworld.redworldguardflags.util.WorldGuardUtil;
import de.redstoneworld.redutilities.material.MaterialHelper;
import org.bukkit.Material;
import org.bukkit.block.BlockState;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.scheduler.BukkitRunnable;

import java.util.Set;

public class BlockPlace implements Listener {

private final RedWorldGuardFlags plugin;

public BlockPlace(RedWorldGuardFlags plugin) {
this.plugin = plugin;
}

@EventHandler(priority = EventPriority.HIGH)
public void onBlockPlace(BlockPlaceEvent event) {
LocalPlayer localPlayer = WorldGuardPlugin.inst().wrapPlayer(event.getPlayer());
Material targetMaterial = event.getBlock().getType();

if (!WorldGuardUtil.isRestrictedWorld(localPlayer.getWorld()) || WorldGuardUtil.hasWorldBypassPermission(localPlayer)) return;

ApplicableRegionSet set = WorldGuardUtil.getRegionSet(event.getBlock().getLocation());

// Get the resulting MATERIAL list from the flag definition.
Set<Material> allowPlace = MaterialHelper.getMaterials(set.queryValue(null, StringFlag.ALLOW_PLACE));
Set<Material> denyPlace = MaterialHelper.getMaterials(set.queryValue(null, StringFlag.DENY_PLACE));

if ((denyPlace != null) && (denyPlace.contains(targetMaterial))) {
event.setCancelled(true);
plugin.getLogger().info("Cancelled block-place because of the regional '" + Flags.FlagEnum.DENY_PLACE_BLOCKS.getFlagObj().getName()
+ "' flag result.");
return;
}

if ((allowPlace != null) && (!allowPlace.contains(targetMaterial))) {
event.setCancelled(true);
plugin.getLogger().info("Cancelled block-place because it was not found in the regional '"
+ Flags.FlagEnum.ALLOW_PLACE_BLOCKS.getFlagObj().getName() + "' flag result.");
return;
}

int resetDelay = (int) set.queryValue(null, Flags.FlagEnum.RESET_BLOCKS.getFlagObj());
if (resetDelay > 0) {
BlockState blockStateCache = event.getBlockReplacedState();

plugin.getLogger().info("Allow temporary block-place because of the regional '" + Flags.FlagEnum.RESET_BLOCKS.getFlagObj().getName()
+ "' flag result.");

new BukkitRunnable() {
public void run() {

BukkitUtil.resetBlock(blockStateCache, event.getBlock().getLocation());

}
}.runTaskLater(plugin, resetDelay * 20L);

return;
}

plugin.getLogger().info("Allow block-place because of the regional '" + Flags.FlagEnum.ALLOW_PLACE_BLOCKS.getFlagObj().getName()
+ "' flag result.");

}

}
Loading

0 comments on commit 943cff8

Please sign in to comment.