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`)
|
- PaperMC 1.21.x (API version `1.21`)
|
||||||
- Java 21
|
- Java 21
|
||||||
- No other plugins required. Optional soft-dependencies: PlaceholderAPI, Vault.
|
- No other plugins required. Optional soft-dependencies: PlaceholderAPI, Vault, WorldEdit.
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
@@ -97,6 +97,14 @@ Commands that require a physical location (`setlobby`, `setspawn`, `setspectator
|
|||||||
### Floor selection details
|
### Floor selection details
|
||||||
|
|
||||||
- `pos1` / `pos2` define the two opposite corners of the rectangular floor region (any Y).
|
- `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
|
- `setfloor` only changes which materials are *allowed* to be used/regenerated — it does not
|
||||||
touch blocks in the world.
|
touch blocks in the world.
|
||||||
- `generate` is the step that actually writes a random layout (biased evenly across the
|
- `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.papermc.io/repository/maven-public/' }
|
||||||
maven { url = 'https://repo.extendedclip.com/content/repositories/placeholderapi/' }
|
maven { url = 'https://repo.extendedclip.com/content/repositories/placeholderapi/' }
|
||||||
maven { url = 'https://jitpack.io' }
|
maven { url = 'https://jitpack.io' }
|
||||||
|
maven { url = 'https://maven.enginehub.org/repo/' }
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
@@ -25,6 +26,15 @@ dependencies {
|
|||||||
compileOnly('com.github.MilkBowl:VaultAPI:1.7') {
|
compileOnly('com.github.MilkBowl:VaultAPI:1.7') {
|
||||||
exclude group: 'org.bukkit', module: 'bukkit'
|
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 'org.xerial:sqlite-jdbc:3.47.1.0'
|
||||||
implementation 'com.mysql:mysql-connector-j:9.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.logic.ArenaPhase;
|
||||||
import us.tss3.blockparty.persistence.PlayerStats;
|
import us.tss3.blockparty.persistence.PlayerStats;
|
||||||
import us.tss3.blockparty.session.PlayerSession;
|
import us.tss3.blockparty.session.PlayerSession;
|
||||||
|
import us.tss3.blockparty.worldedit.WorldEditHook;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -219,7 +220,16 @@ public class BlockPartyCommand implements CommandExecutor, TabCompleter {
|
|||||||
private void pos1(CommandSender sender, String[] args) {
|
private void pos1(CommandSender sender, String[] args) {
|
||||||
if (!requireAdmin(sender, "blockparty.admin.setup") || !requirePlayer(sender)) return;
|
if (!requireAdmin(sender, "blockparty.admin.setup") || !requirePlayer(sender)) return;
|
||||||
withArena(sender, args, arena -> {
|
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().setPos1(new int[]{loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()});
|
||||||
arena.getConfig().setWorldName(loc.getWorld().getName());
|
arena.getConfig().setWorldName(loc.getWorld().getName());
|
||||||
plugin.getArenaManager().save(arena);
|
plugin.getArenaManager().save(arena);
|
||||||
@@ -230,13 +240,36 @@ public class BlockPartyCommand implements CommandExecutor, TabCompleter {
|
|||||||
private void pos2(CommandSender sender, String[] args) {
|
private void pos2(CommandSender sender, String[] args) {
|
||||||
if (!requireAdmin(sender, "blockparty.admin.setup") || !requirePlayer(sender)) return;
|
if (!requireAdmin(sender, "blockparty.admin.setup") || !requirePlayer(sender)) return;
|
||||||
withArena(sender, args, arena -> {
|
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()});
|
arena.getConfig().setPos2(new int[]{loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()});
|
||||||
plugin.getArenaManager().save(arena);
|
plugin.getArenaManager().save(arena);
|
||||||
sender.sendMessage(plugin.getMessages().get("admin.pos2-set", Map.of("arena", arena.getConfig().getName())));
|
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) {
|
private void setFloor(CommandSender sender, String[] args) {
|
||||||
if (!requireAdmin(sender, "blockparty.admin.setup")) return;
|
if (!requireAdmin(sender, "blockparty.admin.setup")) return;
|
||||||
// /bp setfloor <arena> <mat1,mat2,...>
|
// /bp setfloor <arena> <mat1,mat2,...>
|
||||||
|
|||||||
@@ -65,6 +65,10 @@ public class ConfigManager {
|
|||||||
return config.getBoolean("integrations.vault", true);
|
return config.getBoolean("integrations.vault", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isWorldEditEnabled() {
|
||||||
|
return config.getBoolean("integrations.worldedit", true);
|
||||||
|
}
|
||||||
|
|
||||||
public List<String> getDefaultFloorMaterials() {
|
public List<String> getDefaultFloorMaterials() {
|
||||||
return config.getStringList("default-floor-materials");
|
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
|
placeholderapi: true
|
||||||
# If false, money rewards are skipped even when Vault is installed (console commands are unaffected).
|
# If false, money rewards are skipped even when Vault is installed (console commands are unaffected).
|
||||||
vault: true
|
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>"
|
billboard-removed: "<green>Billboard removed for '%arena%'.</green>"
|
||||||
pos1-set: "<green>Position 1 set for '%arena%'.</green>"
|
pos1-set: "<green>Position 1 set for '%arena%'.</green>"
|
||||||
pos2-set: "<green>Position 2 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-set: "<green>Floor palette for '%arena%' set to %count% material(s).</green>"
|
||||||
floor-generated: "<green>Floor generated for '%arena%'.</green>"
|
floor-generated: "<green>Floor generated for '%arena%'.</green>"
|
||||||
reloaded: "<green>BlockParty configuration reloaded.</green>"
|
reloaded: "<green>BlockParty configuration reloaded.</green>"
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ main: us.tss3.blockparty.BlockPartyPlugin
|
|||||||
api-version: '1.21'
|
api-version: '1.21'
|
||||||
author: tss3
|
author: tss3
|
||||||
description: Colored-floor elimination minigame.
|
description: Colored-floor elimination minigame.
|
||||||
softdepend: [PlaceholderAPI, Vault]
|
softdepend: [PlaceholderAPI, Vault, WorldEdit]
|
||||||
|
|
||||||
commands:
|
commands:
|
||||||
blockparty:
|
blockparty:
|
||||||
|
|||||||
Reference in New Issue
Block a user