Compare commits
6 Commits
feautre/pl
...
master
Author | SHA1 | Date | |
---|---|---|---|
a3a75bb8ee | |||
61f4dc90dc | |||
aafeb9fe34 | |||
6d8b291b2f | |||
244bb32d70 | |||
d247953546 |
15
.woodpecker.yml
Normal file
15
.woodpecker.yml
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
pipeline:
|
||||||
|
build:
|
||||||
|
image: maven:3-openjdk-18-slim
|
||||||
|
commands:
|
||||||
|
- mvn package
|
||||||
|
release:
|
||||||
|
image: plugins/gitea-release
|
||||||
|
settings:
|
||||||
|
api_key:
|
||||||
|
from_secret: GITEA_KEY
|
||||||
|
base_url: https://gitea.malloc.hackerbots.net/
|
||||||
|
files:
|
||||||
|
- ./target/*.jar
|
||||||
|
when:
|
||||||
|
event: tag
|
13
pom.xml
13
pom.xml
@ -4,7 +4,7 @@
|
|||||||
<groupId>us.camin.regions</groupId>
|
<groupId>us.camin.regions</groupId>
|
||||||
<artifactId>Regions</artifactId>
|
<artifactId>Regions</artifactId>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
<version>0.3.1</version>
|
<version>0.4.0</version>
|
||||||
<name>regions</name>
|
<name>regions</name>
|
||||||
<url>http://maven.apache.org</url>
|
<url>http://maven.apache.org</url>
|
||||||
<properties>
|
<properties>
|
||||||
@ -46,6 +46,12 @@
|
|||||||
<version>2.0</version>
|
<version>2.0</version>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.angeschossen</groupId>
|
||||||
|
<artifactId>LandsAPI</artifactId>
|
||||||
|
<version>6.15.0</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>commons-codec</groupId>
|
<groupId>commons-codec</groupId>
|
||||||
<artifactId>commons-codec</artifactId>
|
<artifactId>commons-codec</artifactId>
|
||||||
@ -171,7 +177,10 @@
|
|||||||
<id>papermc</id>
|
<id>papermc</id>
|
||||||
<url>http://papermc.io/repo/repository/maven-public/</url>
|
<url>http://papermc.io/repo/repository/maven-public/</url>
|
||||||
</repository>
|
</repository>
|
||||||
<repository><id>pl3x-repo</id><url>http://repo.pl3x.net/</url></repository>
|
<repository>
|
||||||
|
<id>jitpack.io</id>
|
||||||
|
<url>https://jitpack.io</url>
|
||||||
|
</repository>
|
||||||
<repository><id>dynmap-repo</id><url>http://repo.mikeprimm.com/</url></repository>
|
<repository><id>dynmap-repo</id><url>http://repo.mikeprimm.com/</url></repository>
|
||||||
<repository><id>imagej</id><url>http://maven.imagej.net/content/repositories/public/</url></repository>
|
<repository><id>imagej</id><url>http://maven.imagej.net/content/repositories/public/</url></repository>
|
||||||
</repositories>
|
</repositories>
|
||||||
|
@ -111,7 +111,11 @@ public class Plugin extends JavaPlugin {
|
|||||||
this.getDataFolder().mkdir();
|
this.getDataFolder().mkdir();
|
||||||
File regionConfigFile = new File(this.getDataFolder(), "regions.yml");
|
File regionConfigFile = new File(this.getDataFolder(), "regions.yml");
|
||||||
Configuration regionConf = YamlConfiguration.loadConfiguration(regionConfigFile);
|
Configuration regionConf = YamlConfiguration.loadConfiguration(regionConfigFile);
|
||||||
m_regions.loadRegions(regionConf);
|
try {
|
||||||
|
m_regions.loadRegions(regionConf);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.log(Level.SEVERE, "Could not load regions config! You risk overwriting and losing data!", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void saveRegions() {
|
public void saveRegions() {
|
||||||
|
@ -37,13 +37,72 @@ import us.camin.regions.events.RegionRemoveEvent;
|
|||||||
import us.camin.regions.geometry.RegionSet;
|
import us.camin.regions.geometry.RegionSet;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
|
||||||
|
import me.angeschossen.lands.api.land.Land;
|
||||||
|
import me.angeschossen.lands.api.land.Area;
|
||||||
|
import me.angeschossen.lands.api.flags.Flags;
|
||||||
|
import me.angeschossen.lands.api.integration.LandsIntegration;
|
||||||
|
|
||||||
public class RegionManager {
|
public class RegionManager {
|
||||||
|
|
||||||
|
private final LandsIntegration m_lands;
|
||||||
|
|
||||||
|
public enum ValidationResult {
|
||||||
|
VALID,
|
||||||
|
UNKNOWN,
|
||||||
|
NO_PERMISSION,
|
||||||
|
TOO_CLOSE,
|
||||||
|
BAD_NAME,
|
||||||
|
}
|
||||||
|
|
||||||
|
public String validateRegionName(String name, Location location) {
|
||||||
|
Land thisLand = m_lands.getLand(location);
|
||||||
|
if (thisLand == null) {
|
||||||
|
return name;
|
||||||
|
} else {
|
||||||
|
return thisLand.getName();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ValidationResult validateAnchorPoint(Player player, Location location, String proposedName) {
|
||||||
|
// Require basic permission
|
||||||
|
if (!player.hasPermission("regions.create")) {
|
||||||
|
return ValidationResult.NO_PERMISSION;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allow admins to create regions in unclaimed land
|
||||||
|
Area thisArea = m_lands.getAreaByLoc(location);
|
||||||
|
if (thisArea == null) {
|
||||||
|
if (proposedName == null) {
|
||||||
|
return ValidationResult.BAD_NAME;
|
||||||
|
} else if (player.hasPermission("regions.create.bypass")) {
|
||||||
|
return ValidationResult.VALID;
|
||||||
|
} else {
|
||||||
|
return ValidationResult.NO_PERMISSION;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// For claimed land, require claiming perms to place post
|
||||||
|
if (!thisArea.hasFlag(player, Flags.LAND_CLAIM, false)) {
|
||||||
|
return ValidationResult.NO_PERMISSION;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure this is the only region post for this region
|
||||||
|
for (Region region : regionsForWorld(location.getWorld())) {
|
||||||
|
Land thatLand = m_lands.getLand(region.interactLocation());
|
||||||
|
if (thatLand != null && thatLand.getId() == thisArea.getLand().getId()) {
|
||||||
|
return ValidationResult.TOO_CLOSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ValidationResult.VALID;
|
||||||
|
}
|
||||||
|
|
||||||
Logger log = Logger.getLogger("Regions.RegionManager");
|
Logger log = Logger.getLogger("Regions.RegionManager");
|
||||||
private Map<String, RegionSet> m_regions;
|
private Map<String, RegionSet> m_regions;
|
||||||
private Server m_server;
|
private Server m_server;
|
||||||
public RegionManager(Plugin plugin, Server server) {
|
public RegionManager(Plugin plugin, Server server) {
|
||||||
m_server = server;
|
m_server = server;
|
||||||
|
m_lands = new LandsIntegration(plugin);
|
||||||
log.setLevel(Level.ALL);
|
log.setLevel(Level.ALL);
|
||||||
clear();
|
clear();
|
||||||
}
|
}
|
||||||
|
@ -60,13 +60,11 @@ public class RegionPostItemWatcher implements Listener {
|
|||||||
ShapedRecipe anchorRecipe = new ShapedRecipe(anchorKey, m_theAnchor);
|
ShapedRecipe anchorRecipe = new ShapedRecipe(anchorKey, m_theAnchor);
|
||||||
anchorRecipe.shape("DDD", "DGD", "DDD");
|
anchorRecipe.shape("DDD", "DGD", "DDD");
|
||||||
anchorRecipe.setIngredient('D', new RecipeChoice.ExactChoice(m_theChargeItem));
|
anchorRecipe.setIngredient('D', new RecipeChoice.ExactChoice(m_theChargeItem));
|
||||||
anchorRecipe.setIngredient('G', Material.LANTERN);
|
anchorRecipe.setIngredient('G', Material.SOUL_LANTERN);
|
||||||
|
|
||||||
NamespacedKey compassKey = new NamespacedKey(m_plugin, "region_post_compass");
|
NamespacedKey compassKey = new NamespacedKey(m_plugin, "region_post_compass");
|
||||||
ShapedRecipe compassRecipe = new ShapedRecipe(compassKey, m_theCompass);
|
ShapedRecipe compassRecipe = new ShapedRecipe(compassKey, m_theCompass);
|
||||||
// Uses four fewer charges, slightly cheaper.
|
// Uses four fewer charges, slightly cheaper.
|
||||||
// TODO: Maybe we just want this to be glowstone instead of effectively 4
|
|
||||||
// ghast tears?
|
|
||||||
compassRecipe.shape(" D ", " G ", " ");
|
compassRecipe.shape(" D ", " G ", " ");
|
||||||
compassRecipe.setIngredient('D', new RecipeChoice.ExactChoice(m_theChargeItem));
|
compassRecipe.setIngredient('D', new RecipeChoice.ExactChoice(m_theChargeItem));
|
||||||
compassRecipe.setIngredient('G', Material.COMPASS);
|
compassRecipe.setIngredient('G', Material.COMPASS);
|
||||||
@ -96,6 +94,7 @@ public class RegionPostItemWatcher implements Listener {
|
|||||||
meta.setLore(lore);
|
meta.setLore(lore);
|
||||||
meta.addEnchant(Enchantment.SOUL_SPEED, 1, true);
|
meta.addEnchant(Enchantment.SOUL_SPEED, 1, true);
|
||||||
meta.addItemFlags(ItemFlag.HIDE_ENCHANTS);
|
meta.addItemFlags(ItemFlag.HIDE_ENCHANTS);
|
||||||
|
meta.setCustomModelData(93199);
|
||||||
stack.setItemMeta(meta);
|
stack.setItemMeta(meta);
|
||||||
return stack;
|
return stack;
|
||||||
}
|
}
|
||||||
@ -109,6 +108,7 @@ public class RegionPostItemWatcher implements Listener {
|
|||||||
meta.addItemFlags(ItemFlag.HIDE_ENCHANTS);
|
meta.addItemFlags(ItemFlag.HIDE_ENCHANTS);
|
||||||
meta.addEnchant(Enchantment.SOUL_SPEED, 1, true);
|
meta.addEnchant(Enchantment.SOUL_SPEED, 1, true);
|
||||||
meta.setDisplayName("Region Post Charge");
|
meta.setDisplayName("Region Post Charge");
|
||||||
|
meta.setCustomModelData(93197);
|
||||||
stack.setItemMeta(meta);
|
stack.setItemMeta(meta);
|
||||||
return stack;
|
return stack;
|
||||||
}
|
}
|
||||||
@ -122,6 +122,7 @@ public class RegionPostItemWatcher implements Listener {
|
|||||||
meta.addEnchant(Enchantment.SOUL_SPEED, 1, true);
|
meta.addEnchant(Enchantment.SOUL_SPEED, 1, true);
|
||||||
meta.setLore(lore);
|
meta.setLore(lore);
|
||||||
meta.setDisplayName("Region Post Anchor");
|
meta.setDisplayName("Region Post Anchor");
|
||||||
|
meta.setCustomModelData(93198);
|
||||||
stack.setItemMeta(meta);
|
stack.setItemMeta(meta);
|
||||||
return stack;
|
return stack;
|
||||||
}
|
}
|
||||||
@ -185,28 +186,32 @@ public class RegionPostItemWatcher implements Listener {
|
|||||||
ItemStack compassItem = createCompass(nearest);
|
ItemStack compassItem = createCompass(nearest);
|
||||||
player.setItemInHand(compassItem);
|
player.setItemInHand(compassItem);
|
||||||
player.sendMessage("Now tracking " + nearest.name());
|
player.sendMessage("Now tracking " + nearest.name());
|
||||||
} else if (!event.isCancelled() && isRegionCreateItem(handStack, player) && event.getAction() == Action.RIGHT_CLICK_BLOCK && !event.getClickedBlock().getType().isInteractable() && player.hasPermission("regions.create")) {
|
} else if (!event.isCancelled() && isRegionCreateItem(handStack, player) && event.getAction() == Action.RIGHT_CLICK_BLOCK && !event.getClickedBlock().getType().isInteractable()) {
|
||||||
event.setUseItemInHand(Event.Result.DENY);
|
event.setUseItemInHand(Event.Result.DENY);
|
||||||
event.setCancelled(true);
|
event.setCancelled(true);
|
||||||
if (meta.getDisplayName().equals("") || meta.getDisplayName().equals("Region Post Anchor")) {
|
String postName = meta.getDisplayName();
|
||||||
player.sendMessage("You must first give this item a name!");
|
if (postName.equals("") || postName.equals("Region Post Anchor")) {
|
||||||
|
postName = null;
|
||||||
|
}
|
||||||
|
postName = m_manager.validateRegionName(postName, event.getClickedBlock().getLocation());
|
||||||
|
RegionManager.ValidationResult result = m_manager.validateAnchorPoint(player, event.getClickedBlock().getLocation(), postName);
|
||||||
|
if (result == RegionManager.ValidationResult.VALID) {
|
||||||
|
Region r = new Region(postName, event.getClickedBlock().getRelative(event.getBlockFace()).getLocation());
|
||||||
|
m_plugin.getServer().getScheduler().runTask(m_plugin, () -> {
|
||||||
|
RegionPostBuilder builder = new RegionPostBuilder(r, m_plugin);
|
||||||
|
builder.build();
|
||||||
|
});
|
||||||
|
handStack.setAmount(handStack.getAmount()-1);
|
||||||
|
player.setItemInHand(handStack);
|
||||||
|
m_plugin.regionManager().addRegion(r);
|
||||||
|
m_plugin.saveRegions();
|
||||||
|
player.sendMessage("You established the region "+r.coloredName());
|
||||||
|
} else if (result == RegionManager.ValidationResult.TOO_CLOSE) {
|
||||||
|
player.sendMessage("You are too close to another region post!");
|
||||||
|
} else if (result == RegionManager.ValidationResult.BAD_NAME) {
|
||||||
|
player.sendMessage("You must first give this item a better name.");
|
||||||
} else {
|
} else {
|
||||||
Region nearest = m_manager.nearestRegion(event.getClickedBlock().getLocation());
|
player.sendMessage("You aren't allowed to create a region here.");
|
||||||
if (nearest != null && event.getClickedBlock().getLocation().distance(nearest.interactLocation()) < 500) {
|
|
||||||
int distance = 500 - (int)event.getClickedBlock().getLocation().distance(nearest.interactLocation());
|
|
||||||
player.sendMessage("You are " + distance + " blocks too close to the region post for " + nearest.name() + ".");
|
|
||||||
} else {
|
|
||||||
Region r = new Region(meta.getDisplayName(), event.getClickedBlock().getRelative(event.getBlockFace()).getLocation());
|
|
||||||
m_plugin.getServer().getScheduler().runTask(m_plugin, () -> {
|
|
||||||
RegionPostBuilder builder = new RegionPostBuilder(r, m_plugin);
|
|
||||||
builder.build();
|
|
||||||
});
|
|
||||||
handStack.setAmount(handStack.getAmount()-1);
|
|
||||||
player.setItemInHand(handStack);
|
|
||||||
m_plugin.regionManager().addRegion(r);
|
|
||||||
m_plugin.saveRegions();
|
|
||||||
player.sendMessage("You established the region "+r.coloredName());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -131,7 +131,7 @@ public class BorderMesh {
|
|||||||
DelaunayTriangulator mesh = new DelaunayTriangulator(regionPoints);
|
DelaunayTriangulator mesh = new DelaunayTriangulator(regionPoints);
|
||||||
try {
|
try {
|
||||||
mesh.triangulate();
|
mesh.triangulate();
|
||||||
log.info("Mesh triangulated!");
|
log.fine("Mesh triangulated!");
|
||||||
} catch (NullPointerException e) {
|
} catch (NullPointerException e) {
|
||||||
log.warning("Got a null pointer when triangulating, skipping world.");
|
log.warning("Got a null pointer when triangulating, skipping world.");
|
||||||
return false;
|
return false;
|
||||||
@ -173,7 +173,7 @@ public class BorderMesh {
|
|||||||
for(Region region : m_regions) {
|
for(Region region : m_regions) {
|
||||||
ArrayList<Vector2D> points = new ArrayList<Vector2D>();
|
ArrayList<Vector2D> points = new ArrayList<Vector2D>();
|
||||||
HashSet<Region> allNeighbors = new HashSet<Region>();
|
HashSet<Region> allNeighbors = new HashSet<Region>();
|
||||||
log.info("Executing voronoi transform...");
|
log.fine("Executing voronoi transform...");
|
||||||
for(Triangle tri : triangleSoup) {
|
for(Triangle tri : triangleSoup) {
|
||||||
if (tri.region == region) {
|
if (tri.region == region) {
|
||||||
for (Region neighbor : m_regions) {
|
for (Region neighbor : m_regions) {
|
||||||
|
@ -92,13 +92,19 @@ public class PlayerInventoryTeleporter implements Listener {
|
|||||||
if (event.getClickedInventory() == neighborInv) {
|
if (event.getClickedInventory() == neighborInv) {
|
||||||
ItemMeta meta = event.getCurrentItem().getItemMeta();
|
ItemMeta meta = event.getCurrentItem().getItemMeta();
|
||||||
Material mat = event.getCurrentItem().getType();
|
Material mat = event.getCurrentItem().getType();
|
||||||
if (mat == Material.BEDROCK || mat == Material.COMPASS || mat == Material.LANTERN) {
|
final String selectedName = meta.getDisplayName();
|
||||||
|
if (mat == Material.BEDROCK || mat == Material.COMPASS || mat == Material.LANTERN || mat == Material.SOUL_LANTERN) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
m_plugin.getServer().getScheduler().runTask(m_plugin, () -> event.getView().close());
|
|
||||||
Region nearest = m_manager.nearestRegion(player.getLocation());
|
Region nearest = m_manager.nearestRegion(player.getLocation());
|
||||||
|
|
||||||
final String selectedName = meta.getDisplayName();
|
if (selectedName == nearest.name()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_plugin.getServer().getScheduler().runTask(m_plugin, () -> event.getView().close());
|
||||||
|
|
||||||
final Optional<Region> destination = m_plugin.regionManager().regionsForWorld(player.getLocation().getWorld())
|
final Optional<Region> destination = m_plugin.regionManager().regionsForWorld(player.getLocation().getWorld())
|
||||||
.stream()
|
.stream()
|
||||||
.filter((r) -> r.name().equals(selectedName))
|
.filter((r) -> r.name().equals(selectedName))
|
||||||
@ -213,7 +219,7 @@ public class PlayerInventoryTeleporter implements Listener {
|
|||||||
}
|
}
|
||||||
ItemStack chargesItem = new ItemStack(event.region.charges() == 0 ? Material.SOUL_LANTERN : Material.LANTERN);
|
ItemStack chargesItem = new ItemStack(event.region.charges() == 0 ? Material.SOUL_LANTERN : Material.LANTERN);
|
||||||
ItemMeta meta = chargesItem.getItemMeta();
|
ItemMeta meta = chargesItem.getItemMeta();
|
||||||
meta.setDisplayName(ChatColor.BOLD + "Region Post Configuration");
|
meta.setDisplayName(ChatColor.BOLD + "Region Post Charges");
|
||||||
ArrayList<String> lore = new ArrayList<String>();
|
ArrayList<String> lore = new ArrayList<String>();
|
||||||
lore.add(ChatColor.WHITE + "Name: "+event.region.coloredName());
|
lore.add(ChatColor.WHITE + "Name: "+event.region.coloredName());
|
||||||
lore.add(ChatColor.WHITE + "Visits: " + ChatColor.YELLOW + event.region.visits());
|
lore.add(ChatColor.WHITE + "Visits: " + ChatColor.YELLOW + event.region.visits());
|
||||||
@ -223,7 +229,18 @@ public class PlayerInventoryTeleporter implements Listener {
|
|||||||
meta.addEnchant(Enchantment.SOUL_SPEED, 1, true);
|
meta.addEnchant(Enchantment.SOUL_SPEED, 1, true);
|
||||||
chargesItem.setItemMeta(meta);
|
chargesItem.setItemMeta(meta);
|
||||||
// 22 Is the middle of the bottom row
|
// 22 Is the middle of the bottom row
|
||||||
neighborInventory.setItem(22, chargesItem);
|
neighborInventory.setItem(23, chargesItem);
|
||||||
|
|
||||||
|
ItemStack iconItem = event.region.icon();
|
||||||
|
meta = iconItem.getItemMeta();
|
||||||
|
meta.setDisplayName(event.region.name());
|
||||||
|
lore = new ArrayList<String>();
|
||||||
|
lore.add(ChatColor.BOLD + "This is the region's current banner icon.");
|
||||||
|
lore.add(ChatColor.ITALIC + "Right-click the region post with a banner to change it");
|
||||||
|
meta.setLore(lore);
|
||||||
|
meta.addItemFlags(ItemFlag.HIDE_ENCHANTS);
|
||||||
|
iconItem.setItemMeta(meta);
|
||||||
|
neighborInventory.setItem(21, iconItem);
|
||||||
|
|
||||||
event.player.openInventory(neighborInventory);
|
event.player.openInventory(neighborInventory);
|
||||||
}
|
}
|
||||||
|
@ -3,8 +3,8 @@ main: us.camin.regions.Plugin
|
|||||||
author: Torrie Fischer <tdfischer@hackerbots.net>
|
author: Torrie Fischer <tdfischer@hackerbots.net>
|
||||||
website: http://hackerbots.net/
|
website: http://hackerbots.net/
|
||||||
version: ${version}
|
version: ${version}
|
||||||
api-version: 1.16
|
api-version: 1.19
|
||||||
softdepend: [dynmap, ProtocolLib, Pl3xMap]
|
softdepend: [dynmap, ProtocolLib, Lands]
|
||||||
commands:
|
commands:
|
||||||
regions:
|
regions:
|
||||||
description: "List available regions."
|
description: "List available regions."
|
||||||
@ -21,6 +21,7 @@ permissions:
|
|||||||
description: Allows use of all regions permissions
|
description: Allows use of all regions permissions
|
||||||
children:
|
children:
|
||||||
regions.create: true
|
regions.create: true
|
||||||
|
regions.create.bypass: true
|
||||||
regions.commands.*: true
|
regions.commands.*: true
|
||||||
regions.regen.*: true
|
regions.regen.*: true
|
||||||
regions.bypass.*: true
|
regions.bypass.*: true
|
||||||
@ -37,6 +38,9 @@ permissions:
|
|||||||
regions.create:
|
regions.create:
|
||||||
default: true
|
default: true
|
||||||
description: Create a region with a region item
|
description: Create a region with a region item
|
||||||
|
regions.create.bypass:
|
||||||
|
default: op
|
||||||
|
description: Bypass anything preventing creation of a new region
|
||||||
regions.setbanner:
|
regions.setbanner:
|
||||||
default: true
|
default: true
|
||||||
description: Allows setting a region post banner
|
description: Allows setting a region post banner
|
||||||
|
Loading…
Reference in New Issue
Block a user