Add optional WorldEdit soft-dependency; use its wand selection for pos1/pos2
Build / build (push) Successful in 1m19s
Build / build (push) Successful in 1m19s
This commit is contained in:
@@ -10,7 +10,7 @@ slightly faster round. Last player standing wins.
|
||||
|
||||
- PaperMC 1.21.x (API version `1.21`)
|
||||
- Java 21
|
||||
- No other plugins required. Optional soft-dependencies: PlaceholderAPI, Vault.
|
||||
- No other plugins required. Optional soft-dependencies: PlaceholderAPI, Vault, WorldEdit.
|
||||
|
||||
## Installation
|
||||
|
||||
@@ -97,6 +97,14 @@ Commands that require a physical location (`setlobby`, `setspawn`, `setspectator
|
||||
### Floor selection details
|
||||
|
||||
- `pos1` / `pos2` define the two opposite corners of the rectangular floor region (any Y).
|
||||
If [WorldEdit](https://enginehub.org/worldedit) is installed and you have an active WorldEdit
|
||||
selection (made with the wand — left-click for position 1, right-click for position 2, or
|
||||
`//pos1` / `//pos2`), running `/bp pos1 <arena>` / `/bp pos2 <arena>` adopts that selection's
|
||||
corners directly instead of your standing location — no need to physically stand at each
|
||||
corner. This is entirely optional: without a WorldEdit selection (or without WorldEdit
|
||||
installed at all), the commands fall back to your current location exactly as before. Disable
|
||||
it with `integrations.worldedit: false` in `config.yml` if you'd rather always use your
|
||||
location even when WorldEdit is present.
|
||||
- `setfloor` only changes which materials are *allowed* to be used/regenerated — it does not
|
||||
touch blocks in the world.
|
||||
- `generate` is the step that actually writes a random layout (biased evenly across the
|
||||
|
||||
@@ -17,6 +17,7 @@ repositories {
|
||||
maven { url = 'https://repo.papermc.io/repository/maven-public/' }
|
||||
maven { url = 'https://repo.extendedclip.com/content/repositories/placeholderapi/' }
|
||||
maven { url = 'https://jitpack.io' }
|
||||
maven { url = 'https://maven.enginehub.org/repo/' }
|
||||
}
|
||||
|
||||
dependencies {
|
||||
@@ -25,6 +26,15 @@ dependencies {
|
||||
compileOnly('com.github.MilkBowl:VaultAPI:1.7') {
|
||||
exclude group: 'org.bukkit', module: 'bukkit'
|
||||
}
|
||||
// transitive = false: we only need WorldEdit's API types at compile time (it's never
|
||||
// shaded/bundled - the real WorldEdit plugin provides everything at runtime), and its
|
||||
// transitive deps pin strict versions of guava/gson/fastutil that conflict with paper-api's.
|
||||
compileOnly('com.sk89q.worldedit:worldedit-bukkit:7.3.8') {
|
||||
transitive = false
|
||||
}
|
||||
compileOnly('com.sk89q.worldedit:worldedit-core:7.3.8') {
|
||||
transitive = false
|
||||
}
|
||||
implementation 'org.xerial:sqlite-jdbc:3.47.1.0'
|
||||
implementation 'com.mysql:mysql-connector-j:9.1.0'
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ import us.tss3.blockparty.config.ArenaConfig;
|
||||
import us.tss3.blockparty.logic.ArenaPhase;
|
||||
import us.tss3.blockparty.persistence.PlayerStats;
|
||||
import us.tss3.blockparty.session.PlayerSession;
|
||||
import us.tss3.blockparty.worldedit.WorldEditHook;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -219,7 +220,16 @@ public class BlockPartyCommand implements CommandExecutor, TabCompleter {
|
||||
private void pos1(CommandSender sender, String[] args) {
|
||||
if (!requireAdmin(sender, "blockparty.admin.setup") || !requirePlayer(sender)) return;
|
||||
withArena(sender, args, arena -> {
|
||||
Location loc = ((Player) sender).getLocation();
|
||||
Player player = (Player) sender;
|
||||
WorldEditHook.Corners selection = worldEditSelection(player);
|
||||
if (selection != null) {
|
||||
arena.getConfig().setPos1(selection.min());
|
||||
arena.getConfig().setWorldName(selection.worldName());
|
||||
plugin.getArenaManager().save(arena);
|
||||
sender.sendMessage(plugin.getMessages().get("admin.pos1-set-we", Map.of("arena", arena.getConfig().getName())));
|
||||
return;
|
||||
}
|
||||
Location loc = player.getLocation();
|
||||
arena.getConfig().setPos1(new int[]{loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()});
|
||||
arena.getConfig().setWorldName(loc.getWorld().getName());
|
||||
plugin.getArenaManager().save(arena);
|
||||
@@ -230,13 +240,36 @@ public class BlockPartyCommand implements CommandExecutor, TabCompleter {
|
||||
private void pos2(CommandSender sender, String[] args) {
|
||||
if (!requireAdmin(sender, "blockparty.admin.setup") || !requirePlayer(sender)) return;
|
||||
withArena(sender, args, arena -> {
|
||||
Location loc = ((Player) sender).getLocation();
|
||||
Player player = (Player) sender;
|
||||
WorldEditHook.Corners selection = worldEditSelection(player);
|
||||
if (selection != null) {
|
||||
arena.getConfig().setPos2(selection.max());
|
||||
plugin.getArenaManager().save(arena);
|
||||
sender.sendMessage(plugin.getMessages().get("admin.pos2-set-we", Map.of("arena", arena.getConfig().getName())));
|
||||
return;
|
||||
}
|
||||
Location loc = player.getLocation();
|
||||
arena.getConfig().setPos2(new int[]{loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()});
|
||||
plugin.getArenaManager().save(arena);
|
||||
sender.sendMessage(plugin.getMessages().get("admin.pos2-set", Map.of("arena", arena.getConfig().getName())));
|
||||
});
|
||||
}
|
||||
|
||||
/** Returns the player's active WorldEdit selection if the WorldEdit plugin is installed,
|
||||
* the integration is enabled, and they have one - otherwise null so callers fall back to
|
||||
* the player's standing location. WorldEdit classes are only referenced once its plugin
|
||||
* is confirmed present, so a server without WorldEdit installed never loads them. */
|
||||
private WorldEditHook.Corners worldEditSelection(Player player) {
|
||||
if (!plugin.getConfigManager().isWorldEditEnabled() || Bukkit.getPluginManager().getPlugin("WorldEdit") == null) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return WorldEditHook.getSelection(player);
|
||||
} catch (Throwable t) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private void setFloor(CommandSender sender, String[] args) {
|
||||
if (!requireAdmin(sender, "blockparty.admin.setup")) return;
|
||||
// /bp setfloor <arena> <mat1,mat2,...>
|
||||
|
||||
@@ -65,6 +65,10 @@ public class ConfigManager {
|
||||
return config.getBoolean("integrations.vault", true);
|
||||
}
|
||||
|
||||
public boolean isWorldEditEnabled() {
|
||||
return config.getBoolean("integrations.worldedit", true);
|
||||
}
|
||||
|
||||
public List<String> getDefaultFloorMaterials() {
|
||||
return config.getStringList("default-floor-materials");
|
||||
}
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
package us.tss3.blockparty.worldedit;
|
||||
|
||||
import com.sk89q.worldedit.LocalSession;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.bukkit.BukkitAdapter;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
/**
|
||||
* Reads a player's active WorldEdit selection (made with the WE wand / {@code //pos1} and
|
||||
* {@code //pos2}) so BlockParty's floor-region commands can adopt it directly instead of
|
||||
* requiring the player to stand at each corner separately. This class is only ever touched
|
||||
* once the caller has confirmed the WorldEdit plugin is actually present (see
|
||||
* BlockPartyCommand#worldEditSelection), so a server without WorldEdit installed never
|
||||
* attempts to load these classes.
|
||||
*/
|
||||
public final class WorldEditHook {
|
||||
|
||||
private WorldEditHook() {
|
||||
}
|
||||
|
||||
/** Two opposite corners of a cuboid selection, plus the world they're in. */
|
||||
public record Corners(int[] min, int[] max, String worldName) {
|
||||
}
|
||||
|
||||
/** Returns the player's current WorldEdit cuboid selection corners, or null if they have
|
||||
* no active/complete selection (or anything about the lookup fails). */
|
||||
public static Corners getSelection(Player player) {
|
||||
try {
|
||||
LocalSession session = WorldEdit.getInstance().getSessionManager().get(BukkitAdapter.adapt(player));
|
||||
Region region = session.getSelection(BukkitAdapter.adapt(player.getWorld()));
|
||||
BlockVector3 min = region.getMinimumPoint();
|
||||
BlockVector3 max = region.getMaximumPoint();
|
||||
return new Corners(
|
||||
new int[]{min.x(), min.y(), min.z()},
|
||||
new int[]{max.x(), max.y(), max.z()},
|
||||
player.getWorld().getName());
|
||||
} catch (Exception ex) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -80,3 +80,6 @@ integrations:
|
||||
placeholderapi: true
|
||||
# If false, money rewards are skipped even when Vault is installed (console commands are unaffected).
|
||||
vault: true
|
||||
# If true (default) and WorldEdit is installed, /blockparty pos1 and pos2 use your active
|
||||
# WorldEdit wand selection instead of your standing location, when you have one selected.
|
||||
worldedit: true
|
||||
|
||||
@@ -24,6 +24,8 @@ admin:
|
||||
billboard-removed: "<green>Billboard removed for '%arena%'.</green>"
|
||||
pos1-set: "<green>Position 1 set for '%arena%'.</green>"
|
||||
pos2-set: "<green>Position 2 set for '%arena%'.</green>"
|
||||
pos1-set-we: "<green>Position 1 set for '%arena%' from your WorldEdit selection.</green>"
|
||||
pos2-set-we: "<green>Position 2 set for '%arena%' from your WorldEdit selection.</green>"
|
||||
floor-set: "<green>Floor palette for '%arena%' set to %count% material(s).</green>"
|
||||
floor-generated: "<green>Floor generated for '%arena%'.</green>"
|
||||
reloaded: "<green>BlockParty configuration reloaded.</green>"
|
||||
|
||||
@@ -4,7 +4,7 @@ main: us.tss3.blockparty.BlockPartyPlugin
|
||||
api-version: '1.21'
|
||||
author: tss3
|
||||
description: Colored-floor elimination minigame.
|
||||
softdepend: [PlaceholderAPI, Vault]
|
||||
softdepend: [PlaceholderAPI, Vault, WorldEdit]
|
||||
|
||||
commands:
|
||||
blockparty:
|
||||
|
||||
Reference in New Issue
Block a user