From 0a37c4cda6972012f27c2e7daa385093961ec890 Mon Sep 17 00:00:00 2001 From: oddlama Date: Sat, 13 Mar 2021 16:26:33 +0100 Subject: [PATCH 01/40] Begin implementation of regions --- .../org/oddlama/vane/regions/Regions.java | 122 +++++++++++++++++- .../regions/region/EnvironmentSetting.java | 26 ++++ .../oddlama/vane/regions/region/Region.java | 74 +++++++++++ .../vane/regions/region/RegionExtent.java | 66 ++++++++++ .../vane/regions/region/RegionGroup.java | 103 +++++++++++++++ .../org/oddlama/vane/regions/region/Role.java | 95 ++++++++++++++ .../vane/regions/region/RoleSetting.java | 23 ++++ 7 files changed, 508 insertions(+), 1 deletion(-) create mode 100644 vane-regions/src/main/java/org/oddlama/vane/regions/region/EnvironmentSetting.java create mode 100644 vane-regions/src/main/java/org/oddlama/vane/regions/region/Region.java create mode 100644 vane-regions/src/main/java/org/oddlama/vane/regions/region/RegionExtent.java create mode 100644 vane-regions/src/main/java/org/oddlama/vane/regions/region/RegionGroup.java create mode 100644 vane-regions/src/main/java/org/oddlama/vane/regions/region/Role.java create mode 100644 vane-regions/src/main/java/org/oddlama/vane/regions/region/RoleSetting.java diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/Regions.java b/vane-regions/src/main/java/org/oddlama/vane/regions/Regions.java index c2c19233c..95a356805 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/Regions.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/Regions.java @@ -1,8 +1,128 @@ package org.oddlama.vane.regions; +import static org.oddlama.vane.util.BlockUtil.adjacent_blocks_3d; +import static org.oddlama.vane.util.BlockUtil.unpack; +import static org.oddlama.vane.util.ItemUtil.name_item; +import static org.oddlama.vane.util.Nms.item_handle; +import static org.oddlama.vane.util.Nms.register_entity; +import static org.oddlama.vane.util.Nms.spawn; +import static org.oddlama.vane.util.Util.ms_to_ticks; +import static org.oddlama.vane.util.Util.namespaced_key; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.UUID; + +import net.md_5.bungee.api.chat.BaseComponent; +import net.minecraft.server.v1_16_R3.BlockPosition; +import net.minecraft.server.v1_16_R3.EntityTypes; +import net.minecraft.server.v1_16_R3.EnumCreatureType; + +import org.bukkit.Chunk; +import org.bukkit.Material; +import org.bukkit.NamespacedKey; +import org.bukkit.Particle; +import org.bukkit.Sound; +import org.bukkit.SoundCategory; +import org.bukkit.block.Block; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.world.ChunkLoadEvent; +import org.bukkit.event.world.ChunkUnloadEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.scheduler.BukkitTask; +import org.bukkit.util.Vector; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + import org.oddlama.vane.annotation.VaneModule; +import org.oddlama.vane.annotation.config.ConfigExtendedMaterial; +import org.oddlama.vane.annotation.config.ConfigLong; +import org.oddlama.vane.annotation.config.ConfigMaterialMapEntry; +import org.oddlama.vane.annotation.config.ConfigMaterialMapMapEntry; +import org.oddlama.vane.annotation.config.ConfigMaterialMapMapMap; +import org.oddlama.vane.annotation.config.ConfigMaterialMapMapMapEntry; +import org.oddlama.vane.annotation.lang.LangMessage; +import org.oddlama.vane.annotation.persistent.Persistent; +import org.oddlama.vane.core.functional.Consumer2; +import org.oddlama.vane.core.lang.TranslatedMessage; +import org.oddlama.vane.core.material.ExtendedMaterial; import org.oddlama.vane.core.module.Module; +import org.oddlama.vane.core.persistent.PersistentSerializer; +import org.oddlama.vane.util.LazyBlock; -@VaneModule(name = "regions", bstats = 8643, config_version = 1, lang_version = 1, storage_version = 1) +@VaneModule(name = "regions", bstats = 8643, config_version = 2, lang_version = 2, storage_version = 1) public class Regions extends Module { + // + // ┌───────────────────────┐ + // ┌────────────┐ is ┌───────────────┐ ┌───────────────────────┐ | belongs to ┌─────────────────┐ + // | Player 1 | ────> | [Role] Admin | ───┬──> | [RegionGroup] Default |─┘ <───┬─────── | [Region] MyHome | + // └────────────┘ └───────────────┘ | └───────────────────────┘ | └─────────────────┘ + // | | + // ┌────────────┐ in ┌───────────────┐ | | ┌─────────────────────┐ + // | Player 2 | ────> | [Role] Friend | ───┤ (are roles of) └─────── | [Region] Drecksloch | + // └────────────┘ └───────────────┘ | └─────────────────────┘ + // | + // ┌────────────┐ in ┌───────────────┐ | + // | Any Player | ────> | [Role] Others | ───┘ + // └────────────┘ └───────────────┘ + // + // General Menu: /rg + // row 1: General + // 1. create new region + // 2. create new group + // 5. all regions where i am admin + // 6. all groups where i am admin + // 8. shortcut to current region group if any + // 9. shortcut to current region if any + // + // + // Menu: Region + // 1. edit name + // 2. set group + // 3. delete + // + // Menu: Group + // 1. edit name + // 2. add role + // 3. roles + // 3. delete + // + // Menu: Role + // 1. edit name (if not special) + // 2. players (if not others) + // 2. delete role (if not special) + + // Primary storage for all regions (region.id → region) + @Persistent + private Map storage_regions = new HashMap<>(); + // Primary storage for all region_groups (region_group.id → region_group) + @Persistent + private Map storage_region_groups = new HashMap<>(); + // Primary storage for the default region groups for new regions created by a player (player_uuid → region_group.id) + @Persistent + private Map storage_default_region_group = new HashMap<>(); + + // Per-chunk lookup cache + private Map> regions_for_chunk = new HashMap<>(); + + public Regions() { + //menus = new RegionMenuGroup(this); + //dynmap_layer = new RegionDynmapLayer(this); + } + + public void add_region_group(final RegionGroup group) { + storage_region_groups.put(group.id(), group); + mark_persistent_storage_dirty(); + } + + public void add_region(final Region region) { + storage_regions.put(region.id(), region); + mark_persistent_storage_dirty(); + } } diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/region/EnvironmentSetting.java b/vane-regions/src/main/java/org/oddlama/vane/regions/region/EnvironmentSetting.java new file mode 100644 index 000000000..a17bcacd3 --- /dev/null +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/region/EnvironmentSetting.java @@ -0,0 +1,26 @@ +package org.oddlama.vane.regions.region; + +public enum EnvironmentSetting { + // Spawning + ANIMALS(true), + MONSTERS(false), + + // Hazards + EXPLOSIONS(false), + FIRE_SPREAD(false), + PVP(true), + + // Environment + TRAMPLE(false), + VINE_GROWTH(false), + ; + + private boolean def; + private EnvironmentSetting(final boolean def) { + this.def = def; + } + + public boolean default_value() { + return def; + } +} diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/region/Region.java b/vane-regions/src/main/java/org/oddlama/vane/regions/region/Region.java new file mode 100644 index 000000000..ad99cb92e --- /dev/null +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/region/Region.java @@ -0,0 +1,74 @@ +package org.oddlama.vane.regions.region; + +import static org.oddlama.vane.core.persistent.PersistentSerializer.from_json; +import static org.oddlama.vane.core.persistent.PersistentSerializer.to_json; + +import static org.oddlama.vane.util.BlockUtil.adjacent_blocks_3d; +import static org.oddlama.vane.util.BlockUtil.unpack; +import static org.oddlama.vane.util.ItemUtil.name_item; +import static org.oddlama.vane.util.Nms.item_handle; +import static org.oddlama.vane.util.Nms.register_entity; +import static org.oddlama.vane.util.Nms.spawn; +import static org.oddlama.vane.util.Util.ms_to_ticks; +import static org.oddlama.vane.util.Util.namespaced_key; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.UUID; + +import net.md_5.bungee.api.chat.BaseComponent; +import net.minecraft.server.v1_16_R3.BlockPosition; +import net.minecraft.server.v1_16_R3.EntityTypes; +import net.minecraft.server.v1_16_R3.EnumCreatureType; + +import org.bukkit.Chunk; +import org.bukkit.Material; +import org.bukkit.NamespacedKey; +import org.bukkit.Particle; +import org.bukkit.Sound; +import org.bukkit.SoundCategory; +import org.bukkit.block.Block; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.world.ChunkLoadEvent; +import org.bukkit.event.world.ChunkUnloadEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.scheduler.BukkitTask; +import org.bukkit.util.Vector; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import org.oddlama.vane.annotation.VaneModule; +import org.oddlama.vane.annotation.config.ConfigExtendedMaterial; +import org.oddlama.vane.annotation.config.ConfigLong; +import org.oddlama.vane.annotation.config.ConfigMaterialMapEntry; +import org.oddlama.vane.annotation.config.ConfigMaterialMapMapEntry; +import org.oddlama.vane.annotation.config.ConfigMaterialMapMapMap; +import org.oddlama.vane.annotation.config.ConfigMaterialMapMapMapEntry; +import org.oddlama.vane.annotation.lang.LangMessage; +import org.oddlama.vane.annotation.persistent.Persistent; +import org.oddlama.vane.core.functional.Consumer2; +import org.oddlama.vane.core.lang.TranslatedMessage; +import org.oddlama.vane.core.material.ExtendedMaterial; +import org.oddlama.vane.core.module.Module; +import org.oddlama.vane.core.persistent.PersistentSerializer; +import org.oddlama.vane.util.LazyBlock; +import org.oddlama.vane.regions.Regions; + +public class Region { + private UUID id; + private String name; + private RegionExtent extent; + private UUID region_group; + private RegionGroup cached_region_group; + + public boolean is_block_inside(final Block block) { + // check world + // check + } +} diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/region/RegionExtent.java b/vane-regions/src/main/java/org/oddlama/vane/regions/region/RegionExtent.java new file mode 100644 index 000000000..c78a24177 --- /dev/null +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/region/RegionExtent.java @@ -0,0 +1,66 @@ +package org.oddlama.vane.regions.region; + +import static org.oddlama.vane.core.persistent.PersistentSerializer.from_json; +import static org.oddlama.vane.core.persistent.PersistentSerializer.to_json; + +import static org.oddlama.vane.util.BlockUtil.adjacent_blocks_3d; +import static org.oddlama.vane.util.BlockUtil.unpack; +import static org.oddlama.vane.util.ItemUtil.name_item; +import static org.oddlama.vane.util.Nms.item_handle; +import static org.oddlama.vane.util.Nms.register_entity; +import static org.oddlama.vane.util.Nms.spawn; +import static org.oddlama.vane.util.Util.ms_to_ticks; +import static org.oddlama.vane.util.Util.namespaced_key; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.UUID; + +import net.md_5.bungee.api.chat.BaseComponent; +import net.minecraft.server.v1_16_R3.BlockPosition; +import net.minecraft.server.v1_16_R3.EntityTypes; +import net.minecraft.server.v1_16_R3.EnumCreatureType; + +import org.bukkit.Chunk; +import org.bukkit.Material; +import org.bukkit.NamespacedKey; +import org.bukkit.Particle; +import org.bukkit.Sound; +import org.bukkit.SoundCategory; +import org.bukkit.block.Block; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.world.ChunkLoadEvent; +import org.bukkit.event.world.ChunkUnloadEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.scheduler.BukkitTask; +import org.bukkit.util.Vector; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import org.oddlama.vane.annotation.VaneModule; +import org.oddlama.vane.annotation.config.ConfigExtendedMaterial; +import org.oddlama.vane.annotation.config.ConfigLong; +import org.oddlama.vane.annotation.config.ConfigMaterialMapEntry; +import org.oddlama.vane.annotation.config.ConfigMaterialMapMapEntry; +import org.oddlama.vane.annotation.config.ConfigMaterialMapMapMap; +import org.oddlama.vane.annotation.config.ConfigMaterialMapMapMapEntry; +import org.oddlama.vane.annotation.lang.LangMessage; +import org.oddlama.vane.annotation.persistent.Persistent; +import org.oddlama.vane.core.functional.Consumer2; +import org.oddlama.vane.core.lang.TranslatedMessage; +import org.oddlama.vane.core.material.ExtendedMaterial; +import org.oddlama.vane.core.module.Module; +import org.oddlama.vane.core.persistent.PersistentSerializer; +import org.oddlama.vane.util.LazyBlock; +import org.oddlama.vane.regions.Regions; + +public class RegionExtent { + private LazyBlock from; + private LazyBlock to; +} diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/region/RegionGroup.java b/vane-regions/src/main/java/org/oddlama/vane/regions/region/RegionGroup.java new file mode 100644 index 000000000..daee60926 --- /dev/null +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/region/RegionGroup.java @@ -0,0 +1,103 @@ +package org.oddlama.vane.regions.region; + +import static org.oddlama.vane.core.persistent.PersistentSerializer.from_json; +import static org.oddlama.vane.core.persistent.PersistentSerializer.to_json; + +import static org.oddlama.vane.util.BlockUtil.adjacent_blocks_3d; +import static org.oddlama.vane.util.BlockUtil.unpack; +import static org.oddlama.vane.util.ItemUtil.name_item; +import static org.oddlama.vane.util.Nms.item_handle; +import static org.oddlama.vane.util.Nms.register_entity; +import static org.oddlama.vane.util.Nms.spawn; +import static org.oddlama.vane.util.Util.ms_to_ticks; +import static org.oddlama.vane.util.Util.namespaced_key; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.UUID; + +import net.md_5.bungee.api.chat.BaseComponent; +import net.minecraft.server.v1_16_R3.BlockPosition; +import net.minecraft.server.v1_16_R3.EntityTypes; +import net.minecraft.server.v1_16_R3.EnumCreatureType; + +import org.bukkit.Chunk; +import org.bukkit.Material; +import org.bukkit.NamespacedKey; +import org.bukkit.Particle; +import org.bukkit.Sound; +import org.bukkit.SoundCategory; +import org.bukkit.block.Block; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.world.ChunkLoadEvent; +import org.bukkit.event.world.ChunkUnloadEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.scheduler.BukkitTask; +import org.bukkit.util.Vector; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import org.oddlama.vane.annotation.VaneModule; +import org.oddlama.vane.annotation.config.ConfigExtendedMaterial; +import org.oddlama.vane.annotation.config.ConfigLong; +import org.oddlama.vane.annotation.config.ConfigMaterialMapEntry; +import org.oddlama.vane.annotation.config.ConfigMaterialMapMapEntry; +import org.oddlama.vane.annotation.config.ConfigMaterialMapMapMap; +import org.oddlama.vane.annotation.config.ConfigMaterialMapMapMapEntry; +import org.oddlama.vane.annotation.lang.LangMessage; +import org.oddlama.vane.annotation.persistent.Persistent; +import org.oddlama.vane.core.functional.Consumer2; +import org.oddlama.vane.core.lang.TranslatedMessage; +import org.oddlama.vane.core.material.ExtendedMaterial; +import org.oddlama.vane.core.module.Module; +import org.oddlama.vane.core.persistent.PersistentSerializer; +import org.oddlama.vane.util.LazyBlock; +import org.oddlama.vane.regions.Regions; + +public class RegionGroup { + private UUID id; + private UUID owner; + + private Map roles = new HashMap<>(); + private Map player_to_role = new HashMap<>(); + private UUID role_others; + + private Map settings = new HashMap<>(); + + private RegionGroup(final UUID owner) { + this.id = UUID.randomUUID(); + this.owner = owner; + + // Add admins role + final var admins = new Role("[admins]", Role.RoleType.ADMINS); + this.add_role(admins); + + // Add others role + final var others = new Role("[others]", Role.RoleType.OTHERS); + this.add_role(others); + this.role_others = others.id(); + + // Set setting defaults + for (var es : EnvironmentSetting.values()) { + this.settings.put(es.name(), es.default_value()); + } + } + + public void add_role(final Role role) { + this.roles.put(role.id(), role); + } + + public Role get_role(final UUID player) { + return roles.get(player_to_role.getOrDefault(player, role_others)); + } + + public RegionGroup create_default_region_group(final UUID owner) { + return new RegionGroup(owner); + } +} diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/region/Role.java b/vane-regions/src/main/java/org/oddlama/vane/regions/region/Role.java new file mode 100644 index 000000000..e2d5fb5da --- /dev/null +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/region/Role.java @@ -0,0 +1,95 @@ +package org.oddlama.vane.regions.region; + +import static org.oddlama.vane.core.persistent.PersistentSerializer.from_json; +import static org.oddlama.vane.core.persistent.PersistentSerializer.to_json; + +import static org.oddlama.vane.util.BlockUtil.adjacent_blocks_3d; +import static org.oddlama.vane.util.BlockUtil.unpack; +import static org.oddlama.vane.util.ItemUtil.name_item; +import static org.oddlama.vane.util.Nms.item_handle; +import static org.oddlama.vane.util.Nms.register_entity; +import static org.oddlama.vane.util.Nms.spawn; +import static org.oddlama.vane.util.Util.ms_to_ticks; +import static org.oddlama.vane.util.Util.namespaced_key; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.UUID; + +import net.md_5.bungee.api.chat.BaseComponent; +import net.minecraft.server.v1_16_R3.BlockPosition; +import net.minecraft.server.v1_16_R3.EntityTypes; +import net.minecraft.server.v1_16_R3.EnumCreatureType; + +import org.bukkit.Chunk; +import org.bukkit.Material; +import org.bukkit.NamespacedKey; +import org.bukkit.Particle; +import org.bukkit.Sound; +import org.bukkit.SoundCategory; +import org.bukkit.block.Block; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.world.ChunkLoadEvent; +import org.bukkit.event.world.ChunkUnloadEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.scheduler.BukkitTask; +import org.bukkit.util.Vector; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import org.oddlama.vane.annotation.VaneModule; +import org.oddlama.vane.annotation.config.ConfigExtendedMaterial; +import org.oddlama.vane.annotation.config.ConfigLong; +import org.oddlama.vane.annotation.config.ConfigMaterialMapEntry; +import org.oddlama.vane.annotation.config.ConfigMaterialMapMapEntry; +import org.oddlama.vane.annotation.config.ConfigMaterialMapMapMap; +import org.oddlama.vane.annotation.config.ConfigMaterialMapMapMapEntry; +import org.oddlama.vane.annotation.lang.LangMessage; +import org.oddlama.vane.annotation.persistent.Persistent; +import org.oddlama.vane.core.functional.Consumer2; +import org.oddlama.vane.core.lang.TranslatedMessage; +import org.oddlama.vane.core.material.ExtendedMaterial; +import org.oddlama.vane.core.module.Module; +import org.oddlama.vane.core.persistent.PersistentSerializer; +import org.oddlama.vane.util.LazyBlock; +import org.oddlama.vane.regions.Regions; + +public class Role { + public enum RoleType { + ADMINS, + OTHERS, + NORMAL; + } + + private UUID id; + private String name; + private RoleType role_type; + private HashMap settings = new HashMap<>(); + + public Role(final String name, final RoleType role_type) { + this.id = UUID.randomUUID(); + this.name = name; + this.role_type = role_type; + for (final var rs : RoleSetting.values()) { + this.settings.put(rs.name(), rs.default_value(role_type == RoleType.ADMINS)); + } + } + + public UUID id() { + return id; + } + + public String name() { + return name; + } + + public RoleType role_type() { + return role_type; + } +} diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/region/RoleSetting.java b/vane-regions/src/main/java/org/oddlama/vane/regions/region/RoleSetting.java new file mode 100644 index 000000000..a97288604 --- /dev/null +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/region/RoleSetting.java @@ -0,0 +1,23 @@ +package org.oddlama.vane.regions.region; + +public enum RoleSetting { + ADMIN(false, true), + BUILD(false, true), + USE(false, true), + CONTAINER(false, true), + ; + + private boolean def; + private boolean def_admin; + private RoleSetting(final boolean def, final boolean def_admin) { + this.def = def; + this.def_admin = def_admin; + } + + public boolean default_value(final boolean admin) { + if (admin) { + return def_admin; + } + return def; + } +} From ee41b625f1d9cf3c8dba648c5b87ec6ef20c93b2 Mon Sep 17 00:00:00 2001 From: oddlama Date: Sat, 13 Mar 2021 16:47:42 +0100 Subject: [PATCH 02/40] Add Role and RegionGroup (de)serializers --- .../org/oddlama/vane/regions/Regions.java | 16 +++++++ .../vane/regions/region/RegionGroup.java | 42 ++++++++++++++++++- .../org/oddlama/vane/regions/region/Role.java | 31 +++++++++++++- 3 files changed, 85 insertions(+), 4 deletions(-) diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/Regions.java b/vane-regions/src/main/java/org/oddlama/vane/regions/Regions.java index 95a356805..7fa1a68e4 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/Regions.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/Regions.java @@ -98,6 +98,22 @@ public class Regions extends Module { // 2. players (if not others) // 2. delete role (if not special) + // Add (de-)serializers + static { + PersistentSerializer.serializers.put(EnvironmentSetting.class, x -> ((EnvironmentSetting)x).name()); + PersistentSerializer.deserializers.put(EnvironmentSetting.class, x -> EnvironmentSetting.valueOf((String)x)); + PersistentSerializer.serializers.put(RoleSetting.class, x -> ((RoleSetting)x).name()); + PersistentSerializer.deserializers.put(RoleSetting.class, x -> RoleSetting.valueOf((String)x)); + PersistentSerializer.serializers.put(Role.class, Role::serialize); + PersistentSerializer.deserializers.put(Role.class, Role::deserialize); + PersistentSerializer.serializers.put(Role.RoleType.class, x -> ((Role.RoleType)x).name()); + PersistentSerializer.deserializers.put(Role.RoleType.class, x -> Role.RoleType.valueOf((String)x)); + PersistentSerializer.serializers.put(RegionGroup.class, RegionGroup::serialize); + PersistentSerializer.deserializers.put(RegionGroup.class, RegionGroup::deserialize); + PersistentSerializer.serializers.put(Region.class, Region::serialize); + PersistentSerializer.deserializers.put(Region.class, Region::deserialize); + } + // Primary storage for all regions (region.id → region) @Persistent private Map storage_regions = new HashMap<>(); diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/region/RegionGroup.java b/vane-regions/src/main/java/org/oddlama/vane/regions/region/RegionGroup.java index daee60926..8211e7dde 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/region/RegionGroup.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/region/RegionGroup.java @@ -61,6 +61,44 @@ import org.oddlama.vane.regions.Regions; public class RegionGroup { + public static Object serialize(@NotNull final Object o) throws IOException { + final var region_group = (RegionGroup)o; + final var json = new JSONObject(); + json.put("id", to_json(UUID.class, region_group.id)); + json.put("owner", to_json(UUID.class, region_group.owner)); + try { + json.put("roles", to_json(RegionGroup.class.getDeclaredField("roles"), region_group.roles)); + } catch (NoSuchFieldException e) { throw new RuntimeException("Invalid field. This is a bug.", e); } + try { + json.put("player_to_role", to_json(RegionGroup.class.getDeclaredField("player_to_role"), region_group.player_to_role)); + } catch (NoSuchFieldException e) { throw new RuntimeException("Invalid field. This is a bug.", e); } + json.put("role_others", to_json(UUID.class, region_group.role_others)); + try { + json.put("settings", to_json(RegionGroup.class.getDeclaredField("settings"), region_group.settings)); + } catch (NoSuchFieldException e) { throw new RuntimeException("Invalid field. This is a bug.", e); } + + return json; + } + + @SuppressWarnings("unchecked") + public static RegionGroup deserialize(@NotNull final Object o) throws IOException { + final var json = (JSONObject)o; + final var region_group = new RegionGroup(); + region_group.id = from_json(UUID.class, json.get("id")); + region_group.owner = from_json(UUID.class, json.get("owner")); + try { + region_group.roles = (Map)from_json(RegionGroup.class.getDeclaredField("roles"), json.get("roles")); + } catch (NoSuchFieldException e) { throw new RuntimeException("Invalid field. This is a bug.", e); } + try { + region_group.player_to_role = (Map)from_json(RegionGroup.class.getDeclaredField("player_to_role"), json.get("player_to_role")); + } catch (NoSuchFieldException e) { throw new RuntimeException("Invalid field. This is a bug.", e); } + region_group.role_others = from_json(UUID.class, json.get("role_others")); + try { + region_group.settings = (Map)from_json(RegionGroup.class.getDeclaredField("settings"), json.get("settings")); + } catch (NoSuchFieldException e) { throw new RuntimeException("Invalid field. This is a bug.", e); } + return region_group; + } + private UUID id; private UUID owner; @@ -68,7 +106,7 @@ public class RegionGroup { private Map player_to_role = new HashMap<>(); private UUID role_others; - private Map settings = new HashMap<>(); + private Map settings = new HashMap<>(); private RegionGroup(final UUID owner) { this.id = UUID.randomUUID(); @@ -85,7 +123,7 @@ private RegionGroup(final UUID owner) { // Set setting defaults for (var es : EnvironmentSetting.values()) { - this.settings.put(es.name(), es.default_value()); + this.settings.put(es, es.default_value()); } } diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/region/Role.java b/vane-regions/src/main/java/org/oddlama/vane/regions/region/Role.java index e2d5fb5da..8f4ecc3ca 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/region/Role.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/region/Role.java @@ -67,17 +67,44 @@ public enum RoleType { NORMAL; } + public static Object serialize(@NotNull final Object o) throws IOException { + final var role = (Role)o; + final var json = new JSONObject(); + json.put("id", to_json(UUID.class, role.id)); + json.put("name", to_json(String.class, role.name)); + json.put("role_type", to_json(RoleType.class, role.role_type)); + try { + json.put("settings", to_json(Role.class.getDeclaredField("settings"), role.settings)); + } catch (NoSuchFieldException e) { throw new RuntimeException("Invalid field. This is a bug.", e); } + + return json; + } + + @SuppressWarnings("unchecked") + public static Role deserialize(@NotNull final Object o) throws IOException { + final var json = (JSONObject)o; + final var role = new Role(); + role.id = from_json(UUID.class, json.get("id")); + role.name = from_json(String.class, json.get("name")); + role.role_type = from_json(RoleType.class, json.get("role_type")); + try { + role.settings = (Map)from_json(Role.class.getDeclaredField("settings"), json.get("settings")); + } catch (NoSuchFieldException e) { throw new RuntimeException("Invalid field. This is a bug.", e); } + return role; + } + private UUID id; private String name; private RoleType role_type; - private HashMap settings = new HashMap<>(); + private Map settings = new HashMap<>(); + private Role() { } public Role(final String name, final RoleType role_type) { this.id = UUID.randomUUID(); this.name = name; this.role_type = role_type; for (final var rs : RoleSetting.values()) { - this.settings.put(rs.name(), rs.default_value(role_type == RoleType.ADMINS)); + this.settings.put(rs, rs.default_value(role_type == RoleType.ADMINS)); } } From 13488618b79c19e410932ae96f0a8a7f36c0f0b2 Mon Sep 17 00:00:00 2001 From: oddlama Date: Sat, 13 Mar 2021 17:21:13 +0100 Subject: [PATCH 03/40] Added region extent (de)serializer --- .../org/oddlama/vane/regions/Regions.java | 6 +- .../oddlama/vane/regions/region/Region.java | 36 +++++++++-- .../vane/regions/region/RegionExtent.java | 63 ++++++++++++++++++- .../vane/regions/region/RegionGroup.java | 9 +-- 4 files changed, 102 insertions(+), 12 deletions(-) diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/Regions.java b/vane-regions/src/main/java/org/oddlama/vane/regions/Regions.java index 7fa1a68e4..be454879c 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/Regions.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/Regions.java @@ -112,6 +112,8 @@ public class Regions extends Module { PersistentSerializer.deserializers.put(RegionGroup.class, RegionGroup::deserialize); PersistentSerializer.serializers.put(Region.class, Region::serialize); PersistentSerializer.deserializers.put(Region.class, Region::deserialize); + PersistentSerializer.serializers.put(RegionExtent.class, RegionExtent::serialize); + PersistentSerializer.deserializers.put(RegionExtent.class, RegionExtent::deserialize); } // Primary storage for all regions (region.id → region) @@ -124,8 +126,8 @@ public class Regions extends Module { @Persistent private Map storage_default_region_group = new HashMap<>(); - // Per-chunk lookup cache - private Map> regions_for_chunk = new HashMap<>(); + // Per-chunk lookup cache (world_id → chunk_key → [possible regions]) + private Map>> regions_for_chunk = new HashMap<>(); public Regions() { //menus = new RegionMenuGroup(this); diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/region/Region.java b/vane-regions/src/main/java/org/oddlama/vane/regions/region/Region.java index ad99cb92e..1febd2dc8 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/region/Region.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/region/Region.java @@ -61,14 +61,42 @@ import org.oddlama.vane.regions.Regions; public class Region { + public static Object serialize(@NotNull final Object o) throws IOException { + final var region = (Region)o; + final var json = new JSONObject(); + json.put("id", to_json(UUID.class, region.id)); + json.put("name", to_json(String.class, region.name)); + json.put("owner", to_json(UUID.class, region.owner)); + json.put("region_group", to_json(UUID.class, region.region_group)); + json.put("extent", to_json(RegionExtent.class, region.extent)); + return json; + } + + @SuppressWarnings("unchecked") + public static Region deserialize(@NotNull final Object o) throws IOException { + final var json = (JSONObject)o; + final var region = new Region(); + region.id = from_json(UUID.class, json.get("id")); + region.name = from_json(String.class, json.get("name")); + region.owner = from_json(UUID.class, json.get("owner")); + region.region_group = from_json(UUID.class, json.get("region_group")); + region.extent = from_json(RegionExtent.class, json.get("extent")); + return region; + } + private UUID id; private String name; + private UUID owner; private RegionExtent extent; private UUID region_group; - private RegionGroup cached_region_group; - public boolean is_block_inside(final Block block) { - // check world - // check + private RegionGroup cached_region_group; + public RegionGroup group() { + if (cached_region_group == null) { + cached_region_group = Regions.get_region_group(region_group); + } + return cached_region_group; } + + public RegionExtent extent() { return extent; } } diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/region/RegionExtent.java b/vane-regions/src/main/java/org/oddlama/vane/regions/region/RegionExtent.java index c78a24177..ac80e28c7 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/region/RegionExtent.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/region/RegionExtent.java @@ -61,6 +61,65 @@ import org.oddlama.vane.regions.Regions; public class RegionExtent { - private LazyBlock from; - private LazyBlock to; + public static Object serialize(@NotNull final Object o) throws IOException { + final var region_extent = (RegionExtent)o; + final var json = new JSONObject(); + json.put("min", to_json(LazyBlock.class, region_extent.min)); + json.put("max", to_json(LazyBlock.class, region_extent.max)); + return json; + } + + public static RegionExtent deserialize(@NotNull final Object o) throws IOException { + final var json = (JSONObject)o; + final var min = from_json(LazyBlock.class, json.get("min")); + final var max = from_json(LazyBlock.class, json.get("max")); + return new RegionExtent(min, max); + } + + // Both inclusive, so we don't run into errors with + // blocks outside of the world (ymax_height). + // Also, coordinates are sorted, so min is always the smaller coordinate on each axis. + // For each x,y,z: min.[x,y,z] <= max.[x,y,z] + private LazyBlock min; // inclusive + private LazyBlock max; // inclusive + + public RegionExtent(final LazyBlock min, final LazyBlock max) { + this.min = min; + this.max = max; + } + + public RegionExtent(final Block from, final Block to) { + if (!from.getWorld().equals(to.getWorld())) { + throw new RuntimeException("Invalid region extent across dimensions!"); + } + + // Sort coordinates along axes. + this.min = new LazyBlock(new Block(from.getWorld(), + Math.min(from.getX(), to.getX()), + Math.min(from.getY(), to.getY()), + Math.min(from.getZ(), to.getZ()))); + this.max = new LazyBlock(new Block(from.getWorld(), + Math.max(from.getX(), to.getX()), + Math.max(from.getY(), to.getY()), + Math.max(from.getZ(), to.getZ()))); + } + + public Block min() { return min.block(); } + public Block max() { return max.block(); } + + public boolean is_block_inside(final Block block) { + if (!block.getWorld().equals(min().getWorld())) { + return false; + } + + // TODO check + } + + public boolean intersects_chunk(final Chunk chunk) { + if (!chunk.getWorld().equals(min().getWorld())) { + return false; + } + + // TODO return true iff any block inside extent is inside chunk. + } } diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/region/RegionGroup.java b/vane-regions/src/main/java/org/oddlama/vane/regions/region/RegionGroup.java index 8211e7dde..30fbc17a0 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/region/RegionGroup.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/region/RegionGroup.java @@ -108,6 +108,7 @@ public static RegionGroup deserialize(@NotNull final Object o) throws IOExceptio private Map settings = new HashMap<>(); + private RegionGroup() { } private RegionGroup(final UUID owner) { this.id = UUID.randomUUID(); this.owner = owner; @@ -127,6 +128,10 @@ private RegionGroup(final UUID owner) { } } + public static RegionGroup create_default_region_group(final UUID owner) { + return new RegionGroup(owner); + } + public void add_role(final Role role) { this.roles.put(role.id(), role); } @@ -134,8 +139,4 @@ public void add_role(final Role role) { public Role get_role(final UUID player) { return roles.get(player_to_role.getOrDefault(player, role_others)); } - - public RegionGroup create_default_region_group(final UUID owner) { - return new RegionGroup(owner); - } } From e31e4f4846e553f0c64fc7ac625a6cccb6551178 Mon Sep 17 00:00:00 2001 From: oddlama Date: Sat, 13 Mar 2021 18:30:19 +0100 Subject: [PATCH 04/40] Add region intersection tests --- .../vane/regions/region/RegionExtent.java | 67 ++++++++++++++++++- 1 file changed, 65 insertions(+), 2 deletions(-) diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/region/RegionExtent.java b/vane-regions/src/main/java/org/oddlama/vane/regions/region/RegionExtent.java index ac80e28c7..932ac23b0 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/region/RegionExtent.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/region/RegionExtent.java @@ -112,7 +112,46 @@ public boolean is_block_inside(final Block block) { return false; } - // TODO check + final var l = min(); + final var h = max(); + return block.getX() >= l.getX() && block.getX() <= h.getX() + && block.getY() >= l.getY() && block.getY() <= h.getY() + && block.getZ() >= l.getZ() && block.getZ() <= h.getZ(); + } + + public boolean intersects_extent(final RegionExtent other) { + if (!min().getWorld().equals(other.min().getWorld())) { + return false; + } + + final var l1 = min(); + final var h1 = max(); + final var l2 = other.min(); + final var h2 = other.max(); + + // Compute global min and max for each axis + final var llx = Math.min(l1.getX(), l2.getX()); + final var lly = Math.min(l1.getY(), l2.getY()); + final var llz = Math.min(l1.getZ(), l2.getZ()); + final var hhx = Math.max(h1.getX(), h2.getX()); + final var hhy = Math.max(h1.getY(), h2.getY()); + final var hhz = Math.max(h1.getZ(), h2.getZ()); + + // Compute global extent length + final var extent_global_x = (hhx - llx) + 1; + final var extent_global_y = (hhy - lly) + 1; + final var extent_global_z = (hhz - llz) + 1; + + // Compute sum of local extent lengths + final var extent_sum_x = (h2.getX() - l2.getX()) + (h1.getX() - l1.getX()) + 2; + final var extent_sum_y = (h2.getY() - l2.getY()) + (h1.getY() - l1.getY()) + 2; + final var extent_sum_z = (h2.getZ() - l2.getZ()) + (h1.getZ() - l1.getZ()) + 2; + + // It intersects exactly when: + // for all a in axis: global_extent(a) < individual_extent_sum(a) + return extent_global_x < extent_sum_x + && extent_global_y < extent_sum_y + && extent_global_z < extent_sum_z; } public boolean intersects_chunk(final Chunk chunk) { @@ -120,6 +159,30 @@ public boolean intersects_chunk(final Chunk chunk) { return false; } - // TODO return true iff any block inside extent is inside chunk. + final var l1 = min(); + final var h1 = max(); + final var l2x = chunk.getX() * 16; + final var l2z = chunk.getZ() * 16; + final var h2x = (chunk.getX() + 1) * 16 - 1; + final var h2z = (chunk.getZ() + 1) * 16 - 1; + + // Compute global min and max for each axis + final var llx = Math.min(l1.getX(), l2x); + final var llz = Math.min(l1.getZ(), l2z); + final var hhx = Math.max(h1.getX(), h2x); + final var hhz = Math.max(h1.getZ(), h2z); + + // Compute global extent length + final var extent_global_x = (hhx - llx) + 1; + final var extent_global_z = (hhz - llz) + 1; + + // Compute sum of local extent lengths + final var extent_sum_x = (h2x - l2x) + (h1.getX() - l1.getX()) + 2; + final var extent_sum_z = (h2z - l2z) + (h1.getZ() - l1.getZ()) + 2; + + // It intersects exactly when: + // for all a in axis: global_extent(a) < individual_extent_sum(a) + return extent_global_x < extent_sum_x + && extent_global_z < extent_sum_z; } } From 76d57e856200c54e14611ae5d8d469ce4e3fac1f Mon Sep 17 00:00:00 2001 From: oddlama Date: Sun, 14 Mar 2021 15:04:08 +0100 Subject: [PATCH 05/40] Added region index generation and lookup --- vane-regions/build.gradle | 3 + .../org/oddlama/vane/regions/Regions.java | 177 +++++++++++++++++- .../oddlama/vane/regions/region/Region.java | 15 +- .../vane/regions/region/RegionExtent.java | 22 ++- .../vane/regions/region/RegionGroup.java | 6 + .../org/oddlama/vane/regions/region/Role.java | 3 + vane-regions/src/main/resources/plugin.yml | 1 + 7 files changed, 216 insertions(+), 11 deletions(-) create mode 100644 vane-regions/build.gradle diff --git a/vane-regions/build.gradle b/vane-regions/build.gradle new file mode 100644 index 000000000..34b580e36 --- /dev/null +++ b/vane-regions/build.gradle @@ -0,0 +1,3 @@ +dependencies { + implementation group: 'us.dynmap', name: 'dynmap-api', version: '3.1-SNAPSHOT'; +} diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/Regions.java b/vane-regions/src/main/java/org/oddlama/vane/regions/Regions.java index be454879c..cb8c7837c 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/Regions.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/Regions.java @@ -13,6 +13,7 @@ import java.util.Collection; import java.util.HashMap; import java.util.HashSet; +import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Set; @@ -37,6 +38,7 @@ import org.bukkit.inventory.ItemStack; import org.bukkit.scheduler.BukkitTask; import org.bukkit.util.Vector; +import org.bukkit.Location; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -54,6 +56,13 @@ import org.oddlama.vane.core.material.ExtendedMaterial; import org.oddlama.vane.core.module.Module; import org.oddlama.vane.core.persistent.PersistentSerializer; +import org.oddlama.vane.regions.region.Region; +import org.oddlama.vane.regions.region.RegionGroup; +import org.oddlama.vane.regions.region.Role; +import org.oddlama.vane.regions.region.RegionExtent; +import org.oddlama.vane.regions.region.RoleSetting; +import org.oddlama.vane.regions.region.EnvironmentSetting; + import org.oddlama.vane.util.LazyBlock; @VaneModule(name = "regions", bstats = 8643, config_version = 2, lang_version = 2, storage_version = 1) @@ -81,7 +90,6 @@ public class Regions extends Module { // 8. shortcut to current region group if any // 9. shortcut to current region if any // - // // Menu: Region // 1. edit name // 2. set group @@ -91,12 +99,12 @@ public class Regions extends Module { // 1. edit name // 2. add role // 3. roles - // 3. delete + // 4. delete // // Menu: Role // 1. edit name (if not special) // 2. players (if not others) - // 2. delete role (if not special) + // 3. delete role (if not special) // Add (de-)serializers static { @@ -127,20 +135,181 @@ public class Regions extends Module { private Map storage_default_region_group = new HashMap<>(); // Per-chunk lookup cache (world_id → chunk_key → [possible regions]) - private Map>> regions_for_chunk = new HashMap<>(); + private Map>> regions_in_chunk_in_world = new HashMap<>(); public Regions() { //menus = new RegionMenuGroup(this); //dynmap_layer = new RegionDynmapLayer(this); } + public void on_enable() { + for (var region : storage_regions.values()) { + index_add_region(region); + } + } + public void add_region_group(final RegionGroup group) { storage_region_groups.put(group.id(), group); mark_persistent_storage_dirty(); } + public boolean can_remove_region_group(final RegionGroup group) { + // Returns true if this region group is unused and can be removed. + + // If this region group is the fallback default group, it is permanent! + if (storage_default_region_group.values().contains(group.id())) { + return false; + } + + // If any region uses this group, we can't remove it. + if (storage_regions.values().stream().anyMatch( + r -> r.region_group_id().equals(group.id()))) { + return false; + } + + return true; + } + + public void remove_region_group(final RegionGroup group) { + // Assert that this region group is unused. + if (!can_remove_region_group(group)) { + return; + } + + // Remove region group from storage + if (storage_region_groups.remove(region_group.id()) == null) { + // Was already removed + return; + } + + mark_persistent_storage_dirty(); + } + + public RegionGroup get_region_group(UUID region_group) { + return storage_region_groups.get(region_group); + } + public void add_region(final Region region) { storage_regions.put(region.id(), region); mark_persistent_storage_dirty(); + + // Index region for fast lookup + index_add_region(region); + + // Create dynmap marker + dynmap_layer.update_marker(portal); + } + + public void remove_region(final Region region) { + // Remove region from storage + if (storage_regions.remove(region.id()) == null) { + // Was already removed + return; + } + + mark_persistent_storage_dirty(); + + // Remove region from index + index_remove_region(region); + } + + private void index_add_region(final Region region) { + // Adds the region to the lookup map at all intersecting chunks + final var min = region.extent().min(); + final var max = region.extent().max(); + + final var world_id = min.getWorld().getUID(); + var regions_in_chunk = regions_in_chunk_in_world.get(world_id); + if (regions_in_chunk == null) { + regions_in_chunk = new HashMap>(); + regions_in_chunk_in_world.put(world_id, regions_in_chunk); + } + + final var min_chunk = min.getChunk(); + final var max_chunk = max.getChunk(); + + // Iterate all the chunks which intersect the region + for (int cx = min_chunk.getX(); cx <= max_chunk.getX(); ++cx) { + for (int cz = min_chunk.getZ(); cz <= max_chunk.getZ(); ++cz) { + final var chunk_key = Chunk.getChunkKey(cx, cz); + var possible_regions = regions_in_chunk.get(chunk_key); + if (possible_regions == null) { + possible_regions = new ArrayList(); + regions_in_chunk.put(chunk_key, possible_regions); + } + possible_regions.add(region); + } + } + } + + private void index_remove_region(final Region region) { + // Removes the region from the lookup map at all intersecting chunks + final var min = region.extent().min(); + final var max = region.extent().max(); + + final var world_id = min.getWorld().getUID(); + final var regions_in_chunk = regions_in_chunk_in_world.get(world_id); + if (regions_in_chunk == null) { + return; + } + + final var min_chunk = min.getChunk(); + final var max_chunk = max.getChunk(); + + // Iterate all the chunks which intersect the region + for (int cx = min_chunk.getX(); cx <= max_chunk.getX(); ++cx) { + for (int cz = min_chunk.getZ(); cz <= max_chunk.getZ(); ++cz) { + final var chunk_key = Chunk.getChunkKey(cx, cz); + final var possible_regions = regions_in_chunk.get(chunk_key); + if (possible_regions == null) { + continue; + } + possible_regions.remove(region); + } + } + } + + public Region region_at(final Location loc) { + final var world_id = loc.getWorld().getUID(); + final var regions_in_chunk = regions_in_chunk_in_world.get(world_id); + if (regions_in_chunk == null) { + return null; + } + + final var chunk_key = loc.getChunk().getChunkKey(); + final var possible_regions = regions_in_chunk.get(chunk_key); + if (possible_regions == null) { + return null; + } + + for (final var region : possible_regions) { + if (region.extent().is_inside(loc)) { + return region; + } + } + + return null; + } + + public Region region_at(final Block block) { + final var world_id = block.getWorld().getUID(); + final var regions_in_chunk = regions_in_chunk_in_world.get(world_id); + if (regions_in_chunk == null) { + return null; + } + + final var chunk_key = block.getChunk().getChunkKey(); + final var possible_regions = regions_in_chunk.get(chunk_key); + if (possible_regions == null) { + return null; + } + + for (final var region : possible_regions) { + if (region.extent().is_inside(block)) { + return region; + } + } + + return null; } } diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/region/Region.java b/vane-regions/src/main/java/org/oddlama/vane/regions/region/Region.java index 1febd2dc8..a61b28cc0 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/region/Region.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/region/Region.java @@ -12,6 +12,9 @@ import static org.oddlama.vane.util.Util.ms_to_ticks; import static org.oddlama.vane.util.Util.namespaced_key; +import org.oddlama.vane.external.json.JSONObject; + +import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; @@ -90,13 +93,17 @@ public static Region deserialize(@NotNull final Object o) throws IOException { private RegionExtent extent; private UUID region_group; + public UUID id() { return id; } + public String name() { return name; } + public UUID owner() { return owner; } + public RegionExtent extent() { return extent; } + private RegionGroup cached_region_group; - public RegionGroup group() { + public UUID region_group_id() { return region_group; } + public RegionGroup region_group(final Regions regions) { if (cached_region_group == null) { - cached_region_group = Regions.get_region_group(region_group); + cached_region_group = regions.get_region_group(region_group); } return cached_region_group; } - - public RegionExtent extent() { return extent; } } diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/region/RegionExtent.java b/vane-regions/src/main/java/org/oddlama/vane/regions/region/RegionExtent.java index 932ac23b0..6885606dc 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/region/RegionExtent.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/region/RegionExtent.java @@ -12,6 +12,9 @@ import static org.oddlama.vane.util.Util.ms_to_ticks; import static org.oddlama.vane.util.Util.namespaced_key; +import org.oddlama.vane.external.json.JSONObject; + +import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; @@ -33,6 +36,7 @@ import org.bukkit.Sound; import org.bukkit.SoundCategory; import org.bukkit.block.Block; +import org.bukkit.Location; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.world.ChunkLoadEvent; @@ -94,11 +98,11 @@ public RegionExtent(final Block from, final Block to) { } // Sort coordinates along axes. - this.min = new LazyBlock(new Block(from.getWorld(), + this.min = new LazyBlock(from.getWorld().getBlockAt( Math.min(from.getX(), to.getX()), Math.min(from.getY(), to.getY()), Math.min(from.getZ(), to.getZ()))); - this.max = new LazyBlock(new Block(from.getWorld(), + this.max = new LazyBlock(from.getWorld().getBlockAt( Math.max(from.getX(), to.getX()), Math.max(from.getY(), to.getY()), Math.max(from.getZ(), to.getZ()))); @@ -107,7 +111,19 @@ public RegionExtent(final Block from, final Block to) { public Block min() { return min.block(); } public Block max() { return max.block(); } - public boolean is_block_inside(final Block block) { + public boolean is_inside(final Location loc) { + if (!loc.getWorld().equals(min().getWorld())) { + return false; + } + + final var l = min(); + final var h = max(); + return loc.getX() >= l.getX() && loc.getX() < (h.getX() + 1) + && loc.getY() >= l.getY() && loc.getY() < (h.getY() + 1) + && loc.getZ() >= l.getZ() && loc.getZ() < (h.getZ() + 1); + } + + public boolean is_inside(final Block block) { if (!block.getWorld().equals(min().getWorld())) { return false; } diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/region/RegionGroup.java b/vane-regions/src/main/java/org/oddlama/vane/regions/region/RegionGroup.java index 30fbc17a0..76dd36aa6 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/region/RegionGroup.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/region/RegionGroup.java @@ -12,6 +12,9 @@ import static org.oddlama.vane.util.Util.ms_to_ticks; import static org.oddlama.vane.util.Util.namespaced_key; +import org.oddlama.vane.external.json.JSONObject; + +import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; @@ -132,6 +135,9 @@ public static RegionGroup create_default_region_group(final UUID owner) { return new RegionGroup(owner); } + public UUID id() { return id; } + public UUID owner() { return owner; } + public void add_role(final Role role) { this.roles.put(role.id(), role); } diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/region/Role.java b/vane-regions/src/main/java/org/oddlama/vane/regions/region/Role.java index 8f4ecc3ca..0cff9ca5a 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/region/Role.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/region/Role.java @@ -12,6 +12,7 @@ import static org.oddlama.vane.util.Util.ms_to_ticks; import static org.oddlama.vane.util.Util.namespaced_key; +import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; @@ -60,6 +61,8 @@ import org.oddlama.vane.util.LazyBlock; import org.oddlama.vane.regions.Regions; +import org.oddlama.vane.external.json.JSONObject; + public class Role { public enum RoleType { ADMINS, diff --git a/vane-regions/src/main/resources/plugin.yml b/vane-regions/src/main/resources/plugin.yml index ec4374ef4..0699efa45 100644 --- a/vane-regions/src/main/resources/plugin.yml +++ b/vane-regions/src/main/resources/plugin.yml @@ -6,6 +6,7 @@ authors: [oddlama] website: 'https://github.com/oddlama/vane' depend: [vane-core] +softdepend: [dynmap] main: org.oddlama.vane.regions.Regions database: false From d093e5974e1123ef99414fdc974230947ac09742 Mon Sep 17 00:00:00 2001 From: oddlama Date: Sun, 14 Mar 2021 15:47:24 +0100 Subject: [PATCH 06/40] Added EnvironmentSetting and RoleSetting enforcer listeners (just some events for now to test) --- .../RegionEnvironmentSettingEnforcer.java | 62 +++++++++++++++++++ .../regions/RegionRoleSettingEnforcer.java | 62 +++++++++++++++++++ .../org/oddlama/vane/regions/Regions.java | 17 +++++ .../vane/regions/region/RegionGroup.java | 17 +++-- .../org/oddlama/vane/regions/region/Role.java | 15 ++--- 5 files changed, 158 insertions(+), 15 deletions(-) create mode 100644 vane-regions/src/main/java/org/oddlama/vane/regions/RegionEnvironmentSettingEnforcer.java create mode 100644 vane-regions/src/main/java/org/oddlama/vane/regions/RegionRoleSettingEnforcer.java diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/RegionEnvironmentSettingEnforcer.java b/vane-regions/src/main/java/org/oddlama/vane/regions/RegionEnvironmentSettingEnforcer.java new file mode 100644 index 000000000..a3b3173ea --- /dev/null +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/RegionEnvironmentSettingEnforcer.java @@ -0,0 +1,62 @@ +package org.oddlama.vane.regions; + +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.block.BlockBreakEvent; +import org.bukkit.event.block.BlockPistonExtendEvent; +import org.bukkit.event.block.BlockPistonRetractEvent; +import org.bukkit.event.block.BlockPlaceEvent; +import org.bukkit.event.entity.EntityChangeBlockEvent; +import org.bukkit.event.entity.EntityExplodeEvent; + +import org.oddlama.vane.core.Listener; +import org.oddlama.vane.core.module.Context; +import org.oddlama.vane.regions.region.EnvironmentSetting; + +import org.bukkit.block.Block; +import org.bukkit.Location; + +public class RegionEnvironmentSettingEnforcer extends Listener { + public RegionEnvironmentSettingEnforcer(Context context) { + super(context); + } + + public boolean check_setting_at(final Location location, final EnvironmentSetting setting, final boolean check_against) { + final var region = get_module().region_at(location); + if (region == null) { + return false; + } + + final var group = region.region_group(get_module()); + return group.get_setting(setting) == check_against; + } + + public boolean check_setting_at(final Block block, final EnvironmentSetting setting, final boolean check_against) { + final var region = get_module().region_at(block); + if (region == null) { + return false; + } + + final var group = region.region_group(get_module()); + return group.get_setting(setting) == check_against; + } + + @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + public void on_entity_explode(final EntityExplodeEvent event) { + // Prevent explosions from removing region blocks + final var it = event.blockList().iterator(); + while (it.hasNext()) { + if (check_setting_at(it.next(), EnvironmentSetting.EXPLOSIONS, false)) { + it.remove(); + } + } + } + + @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + public void on_entity_change_block(final EntityChangeBlockEvent event) { + // Prevent entities from changing region blocks + if (check_setting_at(event.getBlock(), EnvironmentSetting.MONSTERS, false)) { + event.setCancelled(true); + } + } +} diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/RegionRoleSettingEnforcer.java b/vane-regions/src/main/java/org/oddlama/vane/regions/RegionRoleSettingEnforcer.java new file mode 100644 index 000000000..8c92bce0b --- /dev/null +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/RegionRoleSettingEnforcer.java @@ -0,0 +1,62 @@ +package org.oddlama.vane.regions; + +import java.util.UUID; + +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.block.BlockBreakEvent; +import org.bukkit.event.block.BlockPistonExtendEvent; +import org.bukkit.event.block.BlockPistonRetractEvent; +import org.bukkit.event.block.BlockPlaceEvent; +import org.bukkit.event.entity.EntityChangeBlockEvent; +import org.bukkit.event.entity.EntityExplodeEvent; + +import org.bukkit.block.Block; +import org.bukkit.Location; +import org.bukkit.entity.Player; + +import org.oddlama.vane.core.Listener; +import org.oddlama.vane.core.module.Context; +import org.oddlama.vane.regions.region.RoleSetting; + +public class RegionRoleSettingEnforcer extends Listener { + public RegionRoleSettingEnforcer(Context context) { + super(context); + } + + public boolean check_setting_at(final Location location, final Player player, final RoleSetting setting, final boolean check_against) { + final var region = get_module().region_at(location); + if (region == null) { + return false; + } + + final var group = region.region_group(get_module()); + return group.get_role(player.getUniqueId()).get_setting(setting) == check_against; + } + + public boolean check_setting_at(final Block block, final Player player, final RoleSetting setting, final boolean check_against) { + final var region = get_module().region_at(block); + if (region == null) { + return false; + } + + final var group = region.region_group(get_module()); + return group.get_role(player.getUniqueId()).get_setting(setting) == check_against; + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void on_block_break(final BlockBreakEvent event) { + // Prevent breaking of region blocks + if (check_setting_at(event.getBlock(), event.getPlayer(), RoleSetting.BUILD, false)) { + event.setCancelled(true); + } + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void on_block_place(final BlockPlaceEvent event) { + // Prevent (re-)placing of region blocks + if (check_setting_at(event.getBlock(), event.getPlayer(), RoleSetting.BUILD, false)) { + event.setCancelled(true); + } + } +} diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/Regions.java b/vane-regions/src/main/java/org/oddlama/vane/regions/Regions.java index cb8c7837c..958fd1e0a 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/Regions.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/Regions.java @@ -140,6 +140,8 @@ public class Regions extends Module { public Regions() { //menus = new RegionMenuGroup(this); //dynmap_layer = new RegionDynmapLayer(this); + new RegionEnvironmentSettingEnforcer(this); + new RegionRoleSettingEnforcer(this); } public void on_enable() { @@ -312,4 +314,19 @@ public Region region_at(final Block block) { return null; } + + public RegionGroup get_or_create_default_region_group(final UUID owner) { + var region_group = storage_default_region_group.get(owner); + if (region_group == null) { + // Create and save owners's default group + region_group = new RegionGroup("[default]", owner); + add_region_group(region_group); + + // Set group as the default + storage_default_region_group.put(owner, region_group.id()); + mark_persistent_storage_dirty(); + } + + return region_group; + } } diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/region/RegionGroup.java b/vane-regions/src/main/java/org/oddlama/vane/regions/region/RegionGroup.java index 76dd36aa6..ac71d7568 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/region/RegionGroup.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/region/RegionGroup.java @@ -68,6 +68,7 @@ public static Object serialize(@NotNull final Object o) throws IOException { final var region_group = (RegionGroup)o; final var json = new JSONObject(); json.put("id", to_json(UUID.class, region_group.id)); + json.put("name", to_json(String.class, region_group.name)); json.put("owner", to_json(UUID.class, region_group.owner)); try { json.put("roles", to_json(RegionGroup.class.getDeclaredField("roles"), region_group.roles)); @@ -88,6 +89,7 @@ public static RegionGroup deserialize(@NotNull final Object o) throws IOExceptio final var json = (JSONObject)o; final var region_group = new RegionGroup(); region_group.id = from_json(UUID.class, json.get("id")); + region_group.name = from_json(String.class, json.get("name")); region_group.owner = from_json(UUID.class, json.get("owner")); try { region_group.roles = (Map)from_json(RegionGroup.class.getDeclaredField("roles"), json.get("roles")); @@ -103,6 +105,7 @@ public static RegionGroup deserialize(@NotNull final Object o) throws IOExceptio } private UUID id; + private String name; private UUID owner; private Map roles = new HashMap<>(); @@ -112,8 +115,9 @@ public static RegionGroup deserialize(@NotNull final Object o) throws IOExceptio private Map settings = new HashMap<>(); private RegionGroup() { } - private RegionGroup(final UUID owner) { + private RegionGroup(final String name, final UUID owner) { this.id = UUID.randomUUID(); + this.name = name; this.owner = owner; // Add admins role @@ -125,18 +129,21 @@ private RegionGroup(final UUID owner) { this.add_role(others); this.role_others = others.id(); + // Add owner to admins + this.player_to_role.put(owner, admins.id()); + // Set setting defaults for (var es : EnvironmentSetting.values()) { this.settings.put(es, es.default_value()); } } - public static RegionGroup create_default_region_group(final UUID owner) { - return new RegionGroup(owner); - } - public UUID id() { return id; } + public String name() { return name; } public UUID owner() { return owner; } + public boolean get_setting(final EnvironmentSetting setting) { + return settings.getOrDefault(setting, setting.default_value()); + } public void add_role(final Role role) { this.roles.put(role.id(), role); diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/region/Role.java b/vane-regions/src/main/java/org/oddlama/vane/regions/region/Role.java index 0cff9ca5a..bf81db87d 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/region/Role.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/region/Role.java @@ -111,15 +111,10 @@ public Role(final String name, final RoleType role_type) { } } - public UUID id() { - return id; - } - - public String name() { - return name; - } - - public RoleType role_type() { - return role_type; + public UUID id() { return id; } + public String name() { return name; } + public RoleType role_type() { return role_type; } + public boolean get_setting(final RoleSetting setting) { + return settings.getOrDefault(setting, setting.default_value(false)); } } From 72ce03a1ce3033c8fe4d132ee9289f0600fc64e6 Mon Sep 17 00:00:00 2001 From: oddlama Date: Sun, 14 Mar 2021 15:55:36 +0100 Subject: [PATCH 07/40] Fix RegionGroup private ctor permission --- .../regions/RegionRoleSettingEnforcer.java | 6 ----- .../org/oddlama/vane/regions/Regions.java | 26 ++++++++++--------- .../vane/regions/region/RegionGroup.java | 2 +- 3 files changed, 15 insertions(+), 19 deletions(-) diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/RegionRoleSettingEnforcer.java b/vane-regions/src/main/java/org/oddlama/vane/regions/RegionRoleSettingEnforcer.java index 8c92bce0b..318dce50a 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/RegionRoleSettingEnforcer.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/RegionRoleSettingEnforcer.java @@ -1,15 +1,9 @@ package org.oddlama.vane.regions; -import java.util.UUID; - import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.block.BlockBreakEvent; -import org.bukkit.event.block.BlockPistonExtendEvent; -import org.bukkit.event.block.BlockPistonRetractEvent; import org.bukkit.event.block.BlockPlaceEvent; -import org.bukkit.event.entity.EntityChangeBlockEvent; -import org.bukkit.event.entity.EntityExplodeEvent; import org.bukkit.block.Block; import org.bukkit.Location; diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/Regions.java b/vane-regions/src/main/java/org/oddlama/vane/regions/Regions.java index 958fd1e0a..134a44f49 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/Regions.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/Regions.java @@ -179,7 +179,7 @@ public void remove_region_group(final RegionGroup group) { } // Remove region group from storage - if (storage_region_groups.remove(region_group.id()) == null) { + if (storage_region_groups.remove(group.id()) == null) { // Was already removed return; } @@ -187,7 +187,7 @@ public void remove_region_group(final RegionGroup group) { mark_persistent_storage_dirty(); } - public RegionGroup get_region_group(UUID region_group) { + public RegionGroup get_region_group(final UUID region_group) { return storage_region_groups.get(region_group); } @@ -199,7 +199,7 @@ public void add_region(final Region region) { index_add_region(region); // Create dynmap marker - dynmap_layer.update_marker(portal); + //dynmap_layer.update_marker(region); } public void remove_region(final Region region) { @@ -316,17 +316,19 @@ public Region region_at(final Block block) { } public RegionGroup get_or_create_default_region_group(final UUID owner) { - var region_group = storage_default_region_group.get(owner); - if (region_group == null) { - // Create and save owners's default group - region_group = new RegionGroup("[default]", owner); - add_region_group(region_group); - - // Set group as the default - storage_default_region_group.put(owner, region_group.id()); - mark_persistent_storage_dirty(); + final var region_group_id = storage_default_region_group.get(owner); + if (region_group_id != null) { + return get_region_group(region_group_id); } + // Create and save owners's default group + final var region_group = new RegionGroup("[default]", owner); + add_region_group(region_group); + + // Set group as the default + storage_default_region_group.put(owner, region_group.id()); + mark_persistent_storage_dirty(); + return region_group; } } diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/region/RegionGroup.java b/vane-regions/src/main/java/org/oddlama/vane/regions/region/RegionGroup.java index ac71d7568..5b63f12af 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/region/RegionGroup.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/region/RegionGroup.java @@ -115,7 +115,7 @@ public static RegionGroup deserialize(@NotNull final Object o) throws IOExceptio private Map settings = new HashMap<>(); private RegionGroup() { } - private RegionGroup(final String name, final UUID owner) { + public RegionGroup(final String name, final UUID owner) { this.id = UUID.randomUUID(); this.name = name; this.owner = owner; From 763570fe2a4276091e0b627e076e424c77bb4419 Mon Sep 17 00:00:00 2001 From: oddlama Date: Sun, 14 Mar 2021 18:08:30 +0100 Subject: [PATCH 08/40] WIP: Create main menu, add region selection mode --- .../org/oddlama/vane/regions/Regions.java | 58 ++++- .../oddlama/vane/regions/commands/Region.java | 33 +++ .../menu/EnterRegionGroupNameMenu.java | 40 ++++ .../regions/menu/EnterRegionNameMenu.java | 40 ++++ .../vane/regions/menu/EnterRoleNameMenu.java | 40 ++++ .../oddlama/vane/regions/menu/MainMenu.java | 215 ++++++++++++++++++ .../vane/regions/menu/RegionGroupMenuTag.java | 15 ++ .../vane/regions/menu/RegionMenuGroup.java | 24 ++ .../vane/regions/menu/RegionMenuTag.java | 15 ++ .../vane/regions/region/RegionSelection.java | 96 ++++++++ .../vane/regions/region/RoleSetting.java | 1 + 11 files changed, 567 insertions(+), 10 deletions(-) create mode 100644 vane-regions/src/main/java/org/oddlama/vane/regions/commands/Region.java create mode 100644 vane-regions/src/main/java/org/oddlama/vane/regions/menu/EnterRegionGroupNameMenu.java create mode 100644 vane-regions/src/main/java/org/oddlama/vane/regions/menu/EnterRegionNameMenu.java create mode 100644 vane-regions/src/main/java/org/oddlama/vane/regions/menu/EnterRoleNameMenu.java create mode 100644 vane-regions/src/main/java/org/oddlama/vane/regions/menu/MainMenu.java create mode 100644 vane-regions/src/main/java/org/oddlama/vane/regions/menu/RegionGroupMenuTag.java create mode 100644 vane-regions/src/main/java/org/oddlama/vane/regions/menu/RegionMenuGroup.java create mode 100644 vane-regions/src/main/java/org/oddlama/vane/regions/menu/RegionMenuTag.java create mode 100644 vane-regions/src/main/java/org/oddlama/vane/regions/region/RegionSelection.java diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/Regions.java b/vane-regions/src/main/java/org/oddlama/vane/regions/Regions.java index 134a44f49..1e0d115a6 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/Regions.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/Regions.java @@ -39,6 +39,7 @@ import org.bukkit.scheduler.BukkitTask; import org.bukkit.util.Vector; import org.bukkit.Location; +import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -58,9 +59,13 @@ import org.oddlama.vane.core.persistent.PersistentSerializer; import org.oddlama.vane.regions.region.Region; import org.oddlama.vane.regions.region.RegionGroup; +import org.oddlama.vane.regions.region.RegionSelection; import org.oddlama.vane.regions.region.Role; import org.oddlama.vane.regions.region.RegionExtent; import org.oddlama.vane.regions.region.RoleSetting; +import org.oddlama.vane.regions.menu.RegionGroupMenuTag; +import org.oddlama.vane.regions.menu.RegionMenuGroup; +import org.oddlama.vane.regions.menu.RegionMenuTag; import org.oddlama.vane.regions.region.EnvironmentSetting; import org.oddlama.vane.util.LazyBlock; @@ -81,15 +86,6 @@ public class Regions extends Module { // | Any Player | ────> | [Role] Others | ───┘ // └────────────┘ └───────────────┘ // - // General Menu: /rg - // row 1: General - // 1. create new region - // 2. create new group - // 5. all regions where i am admin - // 6. all groups where i am admin - // 8. shortcut to current region group if any - // 9. shortcut to current region if any - // // Menu: Region // 1. edit name // 2. set group @@ -136,9 +132,20 @@ public class Regions extends Module { // Per-chunk lookup cache (world_id → chunk_key → [possible regions]) private Map>> regions_in_chunk_in_world = new HashMap<>(); + // A map containing the current extent for each player who is currently selecting a region + // No key → Player not in selection mode + // extent.min or extent.max null → Selection mode active, but no selection has been made yet + private Map regions_selections = new HashMap<>(); + + @LangMessage public TranslatedMessage lang_start_region_selection; + + public RegionMenuGroup menus; public Regions() { - //menus = new RegionMenuGroup(this); + menus = new RegionMenuGroup(this); + + new org.oddlama.vane.regions.commands.Region(this); + //dynmap_layer = new RegionDynmapLayer(this); new RegionEnvironmentSettingEnforcer(this); new RegionRoleSettingEnforcer(this); @@ -150,6 +157,19 @@ public void on_enable() { } } + public boolean is_selecting_region(final Player player) { + return regions_selections.containsKey(player.getUniqueId()); + } + + public void cancel_region_selection(final Player player) { + regions_selections.remove(player.getUniqueId()); + } + + public void start_region_selection(final Player player) { + regions_selections.put(player.getUniqueId(), new RegionSelection(this)); + lang_start_region_selection.send(player); + } + public void add_region_group(final RegionGroup group) { storage_region_groups.put(group.id(), group); mark_persistent_storage_dirty(); @@ -185,6 +205,15 @@ public void remove_region_group(final RegionGroup group) { } mark_persistent_storage_dirty(); + + // Close and taint all related open menus + get_module().core.menu_manager.for_each_open((player, menu) -> { + if (menu.tag() instanceof RegionGroupMenuTag + && Objects.equals(((RegionGroupMenuTag)menu.tag()).region_group_id(), group.id())) { + menu.taint(); + menu.close(player); + } + }); } public RegionGroup get_region_group(final UUID region_group) { @@ -211,6 +240,15 @@ public void remove_region(final Region region) { mark_persistent_storage_dirty(); + // Close and taint all related open menus + get_module().core.menu_manager.for_each_open((player, menu) -> { + if (menu.tag() instanceof RegionMenuTag + && Objects.equals(((RegionMenuTag)menu.tag()).region_id(), region.id())) { + menu.taint(); + menu.close(player); + } + }); + // Remove region from index index_remove_region(region); } diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/commands/Region.java b/vane-regions/src/main/java/org/oddlama/vane/regions/commands/Region.java new file mode 100644 index 000000000..ac494ade5 --- /dev/null +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/commands/Region.java @@ -0,0 +1,33 @@ +package org.oddlama.vane.regions.commands; + +import java.util.Collections; + +import org.bukkit.OfflinePlayer; +import org.bukkit.command.CommandSender; +import org.bukkit.permissions.PermissionDefault; +import org.bukkit.entity.Player; + +import org.oddlama.vane.annotation.command.Aliases; +import org.oddlama.vane.annotation.command.Name; +import org.oddlama.vane.annotation.lang.LangMessage; +import org.oddlama.vane.core.command.Command; +import org.oddlama.vane.core.lang.TranslatedMessage; +import org.oddlama.vane.core.module.Context; +import org.oddlama.vane.regions.Regions; + +@Name("region") +@Aliases({"regions", "rg"}) +public class Region extends Command { + public Region(Context context) { + super(context); + + // Add help + params().fixed("help").ignore_case().exec(this::print_help); + // Command parameters + params().exec_player(this::open_menu); + } + + private void open_menu(Player player) { + get_module().menus.main_menu.create(player).open(player); + } +} diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/menu/EnterRegionGroupNameMenu.java b/vane-regions/src/main/java/org/oddlama/vane/regions/menu/EnterRegionGroupNameMenu.java new file mode 100644 index 000000000..67c8789e3 --- /dev/null +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/menu/EnterRegionGroupNameMenu.java @@ -0,0 +1,40 @@ +package org.oddlama.vane.regions.menu; + +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +import org.oddlama.vane.annotation.config.ConfigMaterial; +import org.oddlama.vane.annotation.lang.LangMessage; +import org.oddlama.vane.core.functional.Function2; +import org.oddlama.vane.core.lang.TranslatedMessage; +import org.oddlama.vane.core.menu.Menu.ClickResult; +import org.oddlama.vane.core.menu.Menu; +import org.oddlama.vane.core.menu.MenuFactory; +import org.oddlama.vane.core.module.Context; +import org.oddlama.vane.core.module.ModuleComponent; +import org.oddlama.vane.regions.Regions; + +public class EnterRegionGroupNameMenu extends ModuleComponent { + @LangMessage public TranslatedMessage lang_title; + @ConfigMaterial(def = Material.GLOBE_BANNER_PATTERN, desc = "The item used to name region groups.") + public Material config_material; + + public EnterRegionGroupNameMenu(Context context) { + super(context.namespace("enter_region_group_name")); + } + + public Menu create(final Player player, final Function2 on_click) { + return create(player, "Group Name", on_click); + } + + public Menu create(final Player player, final String default_name, final Function2 on_click) { + return MenuFactory.anvil_string_input(get_context(), player, lang_title.str(), new ItemStack(config_material), default_name, (p, menu, name) -> { + menu.close(p); + return on_click.apply(p, name); + }); + } + + @Override public void on_enable() {} + @Override public void on_disable() {} +} diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/menu/EnterRegionNameMenu.java b/vane-regions/src/main/java/org/oddlama/vane/regions/menu/EnterRegionNameMenu.java new file mode 100644 index 000000000..a9adf7611 --- /dev/null +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/menu/EnterRegionNameMenu.java @@ -0,0 +1,40 @@ +package org.oddlama.vane.regions.menu; + +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +import org.oddlama.vane.annotation.config.ConfigMaterial; +import org.oddlama.vane.annotation.lang.LangMessage; +import org.oddlama.vane.core.functional.Function2; +import org.oddlama.vane.core.lang.TranslatedMessage; +import org.oddlama.vane.core.menu.Menu.ClickResult; +import org.oddlama.vane.core.menu.Menu; +import org.oddlama.vane.core.menu.MenuFactory; +import org.oddlama.vane.core.module.Context; +import org.oddlama.vane.core.module.ModuleComponent; +import org.oddlama.vane.regions.Regions; + +public class EnterRegionNameMenu extends ModuleComponent { + @LangMessage public TranslatedMessage lang_title; + @ConfigMaterial(def = Material.MAP, desc = "The item used to name regions.") + public Material config_material; + + public EnterRegionNameMenu(Context context) { + super(context.namespace("enter_region_name")); + } + + public Menu create(final Player player, final Function2 on_click) { + return create(player, "Region Name", on_click); + } + + public Menu create(final Player player, final String default_name, final Function2 on_click) { + return MenuFactory.anvil_string_input(get_context(), player, lang_title.str(), new ItemStack(config_material), default_name, (p, menu, name) -> { + menu.close(p); + return on_click.apply(p, name); + }); + } + + @Override public void on_enable() {} + @Override public void on_disable() {} +} diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/menu/EnterRoleNameMenu.java b/vane-regions/src/main/java/org/oddlama/vane/regions/menu/EnterRoleNameMenu.java new file mode 100644 index 000000000..a3601745e --- /dev/null +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/menu/EnterRoleNameMenu.java @@ -0,0 +1,40 @@ +package org.oddlama.vane.regions.menu; + +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +import org.oddlama.vane.annotation.config.ConfigMaterial; +import org.oddlama.vane.annotation.lang.LangMessage; +import org.oddlama.vane.core.functional.Function2; +import org.oddlama.vane.core.lang.TranslatedMessage; +import org.oddlama.vane.core.menu.Menu.ClickResult; +import org.oddlama.vane.core.menu.Menu; +import org.oddlama.vane.core.menu.MenuFactory; +import org.oddlama.vane.core.module.Context; +import org.oddlama.vane.core.module.ModuleComponent; +import org.oddlama.vane.regions.Regions; + +public class EnterRoleNameMenu extends ModuleComponent { + @LangMessage public TranslatedMessage lang_title; + @ConfigMaterial(def = Material.BOOK, desc = "The item used to name roles.") + public Material config_material; + + public EnterRoleNameMenu(Context context) { + super(context.namespace("enter_role_name")); + } + + public Menu create(final Player player, final Function2 on_click) { + return create(player, "Role Name", on_click); + } + + public Menu create(final Player player, final String default_name, final Function2 on_click) { + return MenuFactory.anvil_string_input(get_context(), player, lang_title.str(), new ItemStack(config_material), default_name, (p, menu, name) -> { + menu.close(p); + return on_click.apply(p, name); + }); + } + + @Override public void on_enable() {} + @Override public void on_disable() {} +} diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/menu/MainMenu.java b/vane-regions/src/main/java/org/oddlama/vane/regions/menu/MainMenu.java new file mode 100644 index 000000000..3fcadd164 --- /dev/null +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/menu/MainMenu.java @@ -0,0 +1,215 @@ +package org.oddlama.vane.regions.menu; + +import static org.oddlama.vane.util.Util.namespaced_key; + +import java.util.Objects; +import java.util.stream.Collectors; + +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +import org.oddlama.vane.annotation.lang.LangMessage; +import org.oddlama.vane.core.config.TranslatedItemStack; +import org.oddlama.vane.core.lang.TranslatedMessage; +import org.oddlama.vane.core.menu.Filter; +import org.oddlama.vane.core.menu.Menu.ClickResult; +import org.oddlama.vane.core.menu.Menu; +import org.oddlama.vane.core.menu.MenuFactory; +import org.oddlama.vane.core.menu.MenuItem; +import org.oddlama.vane.core.menu.MenuWidget; +import org.oddlama.vane.core.module.Context; +import org.oddlama.vane.core.module.ModuleComponent; +import org.oddlama.vane.regions.Regions; +import org.oddlama.vane.regions.region.Region; + +public class MainMenu extends ModuleComponent { + @LangMessage public TranslatedMessage lang_title; + @LangMessage public TranslatedMessage lang_unlink_console_confirm_title; + @LangMessage public TranslatedMessage lang_destroy_region_confirm_title; + @LangMessage public TranslatedMessage lang_select_target_title; + @LangMessage public TranslatedMessage lang_filter_regions_title; + + public TranslatedItemStack item_create_region_start_selection; + public TranslatedItemStack item_create_region_invalid_selection; + public TranslatedItemStack item_create_region_valid_selection; + public TranslatedItemStack item_cancel_selection; + public TranslatedItemStack item_current_region; + public TranslatedItemStack item_list_regions; + public TranslatedItemStack item_create_region_group; + public TranslatedItemStack item_current_region_group; + public TranslatedItemStack item_list_region_groups; + + public MainMenu(Context context) { + super(context.namespace("main")); + + final var ctx = get_context(); + item_create_region_start_selection = new TranslatedItemStack<>(ctx, "create_region_start_selection", Material.WRITABLE_BOOK, 1, "Used to start creating a new region selection."); + item_create_region_invalid_selection = new TranslatedItemStack<>(ctx, "create_region_invalid_selection", Material.BARRIER, 1, "Used to indicate an invalid selection."); + item_create_region_valid_selection = new TranslatedItemStack<>(ctx, "create_region_valid_selection", Material.WRITABLE_BOOK, 1, "Used to create a new region with the current selection."); + item_cancel_selection = new TranslatedItemStack<>(ctx, "cancel_selection", Material.RED_TERRACOTTA, 1, "Used to cancel region selection."); + item_list_regions = new TranslatedItemStack<>(ctx, "list_regions", Material.COMPASS, 1, "Used to select a region the player may administrate."); + item_current_region = new TranslatedItemStack<>(ctx, "current_region", Material.FILLED_MAP, 1, "Used to access the region the player currently stands in."); + item_create_region_group = new TranslatedItemStack<>(ctx, "create_region_group", Material.WRITABLE_BOOK, 1, "Used to create a new region group."); + item_list_region_groups = new TranslatedItemStack<>(ctx, "list_region_groups", Material.COMPASS, 1, "Used to select a region group the player may administrate."); + item_current_region_group = new TranslatedItemStack<>(ctx, "current_region_group", Material.GLOBE_BANNER_PATTERN, 1, "Used to access the region group associated with the region the player currently stands in."); + } + + public Menu create(final Player player) { + final var columns = 9; + final var title = lang_title.str(); + final var main_menu = new Menu(get_context(), Bukkit.createInventory(null, columns, title)); + + final var selection_mode = false; //TODO + final var region = get_module().region_at(player.getLocation()); + + // Check if target selection would be allowed + if (selection_mode) { + main_menu.add(menu_item_create_region()); + main_menu.add(menu_item_cancel_selection()); + } else { + main_menu.add(menu_item_start_selection()); + main_menu.add(menu_item_list_regions()); + if (region != null) { + main_menu.add(menu_item_current_region(region)); + } + } + + main_menu.add(menu_item_create_region_group()); + main_menu.add(menu_item_list_region_groups()); + if (region != null) { + main_menu.add(menu_item_current_region_group(region.group(get_module()))); + } + + return main_menu; + } + + private MenuWidget menu_item_start_selection() { + return new MenuItem(0, item_create_region_start_selection.item(), (player, menu, self) -> { + menu.close(player); + get_module().start_region_selection(player); + return ClickResult.SUCCESS; + }); + } + + private MenuWidget menu_item_select_target(final Region region) { + return new MenuItem(4, null, (player, menu, self) -> { + if (region.target_locked()) { + return ClickResult.ERROR; + } else { + menu.close(player); + final var all_regions = get_module().all_regions() + .stream() + .filter(p -> { + switch (p.visibility()) { + case PUBLIC: return true; + case GROUP: return false; // TODO group visibility + case PRIVATE: return player.getUniqueId().equals(p.owner()); + } + return false; + }) + .filter(p -> !Objects.equals(p.id(), region.id())) + .sorted(new Region.TargetSelectionComparator(player)) + .collect(Collectors.toList()); + + final var filter = new Filter.StringFilter((p, str) -> p.name().toLowerCase().contains(str)); + MenuFactory.generic_selector(get_context(), player, lang_select_target_title.str(), lang_filter_regions_title.str(), all_regions, + p -> { + final var dist = p.spawn().toVector().setY(0.0).distance(player.getLocation().toVector().setY(0.0)); + return item_select_target_region.alternative(get_module().icon_for(p), "§a§l" + p.name(), "§6" + String.format("%.1f", dist), "§b" + p.spawn().getWorld().getName()); + }, + filter, + (player2, m, t) -> { + m.close(player2); + + final var select_target_event = new RegionSelectTargetEvent(player, region, t, false); + get_module().getServer().getPluginManager().callEvent(select_target_event); + if (select_target_event.isCancelled()) { + get_module().lang_select_target_restricted.send(player2); + return ClickResult.ERROR; + } + + region.target_id(t.id()); + + // Update region block to reflect new target on consoles + region.update_blocks(get_module()); + mark_persistent_storage_dirty(); + return ClickResult.SUCCESS; + }, player2 -> { + menu.open(player2); + }).tag(new RegionMenuTag(region.id())).open(player); + return ClickResult.SUCCESS; + } + }) { + @Override + public void item(final ItemStack item) { + final var target = region.target(get_module()); + final var target_name = "§a" + (target == null ? "None" : target.name()); + if (region.target_locked()) { + super.item(item_select_target_locked.item(target_name)); + } else { + super.item(item_select_target.item(target_name)); + } + } + }; + } + + private MenuWidget menu_item_unlink_console(final Region region, final Block console) { + return new MenuItem(7, item_unlink_console.item(), (player, menu, self) -> { + menu.close(player); + MenuFactory.confirm(get_context(), lang_unlink_console_confirm_title.str(), + item_unlink_console_confirm_accept.item(), (player2) -> { + // Call event + final var event = new RegionUnlinkConsoleEvent(player2, region, false); + get_module().getServer().getPluginManager().callEvent(event); + if (event.isCancelled()) { + get_module().lang_unlink_restricted.send(player2); + return ClickResult.ERROR; + } + + final var region_block = region.region_block_for(console); + if (region_block == null) { + // Console was likely already removed by another player + return ClickResult.ERROR; + } + + get_module().remove_region_block(region, region_block); + return ClickResult.SUCCESS; + }, item_unlink_console_confirm_cancel.item(), (player2) -> { + menu.open(player2); + }) + .tag(new RegionMenuTag(region.id())) + .open(player); + return ClickResult.SUCCESS; + }); + } + + private MenuWidget menu_item_destroy_region(final Region region) { + return new MenuItem(8, item_destroy_region.item(), (player, menu, self) -> { + menu.close(player); + MenuFactory.confirm(get_context(), lang_destroy_region_confirm_title.str(), + item_destroy_region_confirm_accept.item(), (player2) -> { + // Call event + final var event = new RegionDestroyEvent(player2, region, false); + get_module().getServer().getPluginManager().callEvent(event); + if (event.isCancelled()) { + get_module().lang_destroy_restricted.send(player2); + return ClickResult.ERROR; + } + + get_module().remove_region(region); + return ClickResult.SUCCESS; + }, item_destroy_region_confirm_cancel.item(), (player2) -> { + menu.open(player2); + }) + .tag(new RegionMenuTag(region.id())) + .open(player); + return ClickResult.SUCCESS; + }); + } + + @Override public void on_enable() {} + @Override public void on_disable() {} +} diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RegionGroupMenuTag.java b/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RegionGroupMenuTag.java new file mode 100644 index 000000000..48d369ee3 --- /dev/null +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RegionGroupMenuTag.java @@ -0,0 +1,15 @@ +package org.oddlama.vane.regions.menu; + +import java.util.UUID; + +public class RegionGroupMenuTag { + private UUID region_group_id = null; + + public RegionGroupMenuTag(final UUID region_group_id) { + this.region_group_id = region_group_id; + } + + public UUID region_group_id() { + return region_group_id; + } +} diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RegionMenuGroup.java b/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RegionMenuGroup.java new file mode 100644 index 000000000..5d93e7ee9 --- /dev/null +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RegionMenuGroup.java @@ -0,0 +1,24 @@ +package org.oddlama.vane.regions.menu; + +import org.oddlama.vane.core.module.Context; +import org.oddlama.vane.core.module.ModuleComponent; +import org.oddlama.vane.regions.Regions; + +public class RegionMenuGroup extends ModuleComponent { + public EnterRegionNameMenu enter_region_name_menu; + public EnterRegionGroupNameMenu enter_region_group_name_menu; + public EnterRoleNameMenu enter_role_name_menu; + public MainMenu main_menu; + + public RegionMenuGroup(Context context) { + super(context.namespace("menus")); + + enter_region_name_menu = new EnterRegionNameMenu(get_context()); + enter_region_group_name_menu = new EnterRegionGroupNameMenu(get_context()); + enter_role_name_menu = new EnterRoleNameMenu(get_context()); + main_menu = new MainMenu(get_context()); + } + + @Override public void on_enable() {} + @Override public void on_disable() {} +} diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RegionMenuTag.java b/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RegionMenuTag.java new file mode 100644 index 000000000..acd80c637 --- /dev/null +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RegionMenuTag.java @@ -0,0 +1,15 @@ +package org.oddlama.vane.regions.menu; + +import java.util.UUID; + +public class RegionMenuTag { + private UUID region_id = null; + + public RegionMenuTag(final UUID region_id) { + this.region_id = region_id; + } + + public UUID region_id() { + return region_id; + } +} diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/region/RegionSelection.java b/vane-regions/src/main/java/org/oddlama/vane/regions/region/RegionSelection.java new file mode 100644 index 000000000..8696b20bd --- /dev/null +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/region/RegionSelection.java @@ -0,0 +1,96 @@ +package org.oddlama.vane.regions.region; + +import static org.oddlama.vane.core.persistent.PersistentSerializer.from_json; +import static org.oddlama.vane.core.persistent.PersistentSerializer.to_json; + +import static org.oddlama.vane.util.BlockUtil.adjacent_blocks_3d; +import static org.oddlama.vane.util.BlockUtil.unpack; +import static org.oddlama.vane.util.ItemUtil.name_item; +import static org.oddlama.vane.util.Nms.item_handle; +import static org.oddlama.vane.util.Nms.register_entity; +import static org.oddlama.vane.util.Nms.spawn; +import static org.oddlama.vane.util.Util.ms_to_ticks; +import static org.oddlama.vane.util.Util.namespaced_key; + +import org.oddlama.vane.external.json.JSONObject; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.UUID; + +import net.md_5.bungee.api.chat.BaseComponent; +import net.minecraft.server.v1_16_R3.BlockPosition; +import net.minecraft.server.v1_16_R3.EntityTypes; +import net.minecraft.server.v1_16_R3.EnumCreatureType; + +import org.bukkit.Chunk; +import org.bukkit.Material; +import org.bukkit.NamespacedKey; +import org.bukkit.Particle; +import org.bukkit.Sound; +import org.bukkit.SoundCategory; +import org.bukkit.block.Block; +import org.bukkit.Location; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.world.ChunkLoadEvent; +import org.bukkit.event.world.ChunkUnloadEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.scheduler.BukkitTask; +import org.bukkit.util.Vector; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import org.oddlama.vane.annotation.VaneModule; +import org.oddlama.vane.annotation.config.ConfigExtendedMaterial; +import org.oddlama.vane.annotation.config.ConfigLong; +import org.oddlama.vane.annotation.config.ConfigMaterialMapEntry; +import org.oddlama.vane.annotation.config.ConfigMaterialMapMapEntry; +import org.oddlama.vane.annotation.config.ConfigMaterialMapMapMap; +import org.oddlama.vane.annotation.config.ConfigMaterialMapMapMapEntry; +import org.oddlama.vane.annotation.lang.LangMessage; +import org.oddlama.vane.annotation.persistent.Persistent; +import org.oddlama.vane.core.functional.Consumer2; +import org.oddlama.vane.core.lang.TranslatedMessage; +import org.oddlama.vane.core.material.ExtendedMaterial; +import org.oddlama.vane.core.module.Module; +import org.oddlama.vane.core.persistent.PersistentSerializer; +import org.oddlama.vane.util.LazyBlock; +import org.oddlama.vane.regions.Regions; + +public class RegionSelection { + private Regions regions; + private Block primary = null; + private Block secondary = null; + + public RegionSelection(final Regions regions) { + this.regions = regions; + } + + public void set_primary(final Block block) { + primary = block; + } + + public void set_secondary(final Block block) { + secondary = block; + } + + public boolean is_valid() { + // not null, worlds match, size at least X, at max Z + return false; + } + + public RegionExtent to_extent() { + if (!is_valid()) { + return null; + } + + return new RegionExtent(primary, secondary); + } +} diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/region/RoleSetting.java b/vane-regions/src/main/java/org/oddlama/vane/regions/region/RoleSetting.java index a97288604..18f277394 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/region/RoleSetting.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/region/RoleSetting.java @@ -5,6 +5,7 @@ public enum RoleSetting { BUILD(false, true), USE(false, true), CONTAINER(false, true), + PORTAL(false, true), ; private boolean def; From 2f572d74f0218f3e9ee4b08b6f3832eee962b2ed Mon Sep 17 00:00:00 2001 From: oddlama Date: Mon, 15 Mar 2021 01:49:27 +0100 Subject: [PATCH 09/40] Added first menus and english localization --- .../org/oddlama/vane/regions/Regions.java | 18 +- .../menu/EnterRegionGroupNameMenu.java | 2 +- .../regions/menu/EnterRegionNameMenu.java | 2 +- .../vane/regions/menu/EnterRoleNameMenu.java | 2 +- .../oddlama/vane/regions/menu/MainMenu.java | 184 +++++++++--------- vane-regions/src/main/resources/lang-de.yml | 2 +- vane-regions/src/main/resources/lang-en.yml | 129 +++++++++++- 7 files changed, 233 insertions(+), 106 deletions(-) diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/Regions.java b/vane-regions/src/main/java/org/oddlama/vane/regions/Regions.java index 1e0d115a6..ab94a6ada 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/Regions.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/Regions.java @@ -157,17 +157,25 @@ public void on_enable() { } } - public boolean is_selecting_region(final Player player) { - return regions_selections.containsKey(player.getUniqueId()); + public Collection all_regions() { + return storage_regions.values(); + } + + public void start_region_selection(final Player player) { + regions_selections.put(player.getUniqueId(), new RegionSelection(this)); + lang_start_region_selection.send(player); } public void cancel_region_selection(final Player player) { regions_selections.remove(player.getUniqueId()); } - public void start_region_selection(final Player player) { - regions_selections.put(player.getUniqueId(), new RegionSelection(this)); - lang_start_region_selection.send(player); + public boolean is_selecting_region(final Player player) { + return regions_selections.containsKey(player.getUniqueId()); + } + + public RegionSelection get_region_selection(final Player player) { + return regions_selections.get(player.getUniqueId()); } public void add_region_group(final RegionGroup group) { diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/menu/EnterRegionGroupNameMenu.java b/vane-regions/src/main/java/org/oddlama/vane/regions/menu/EnterRegionGroupNameMenu.java index 67c8789e3..865bf4b1f 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/menu/EnterRegionGroupNameMenu.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/menu/EnterRegionGroupNameMenu.java @@ -25,7 +25,7 @@ public EnterRegionGroupNameMenu(Context context) { } public Menu create(final Player player, final Function2 on_click) { - return create(player, "Group Name", on_click); + return create(player, "Group", on_click); } public Menu create(final Player player, final String default_name, final Function2 on_click) { diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/menu/EnterRegionNameMenu.java b/vane-regions/src/main/java/org/oddlama/vane/regions/menu/EnterRegionNameMenu.java index a9adf7611..35fefd8af 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/menu/EnterRegionNameMenu.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/menu/EnterRegionNameMenu.java @@ -25,7 +25,7 @@ public EnterRegionNameMenu(Context context) { } public Menu create(final Player player, final Function2 on_click) { - return create(player, "Region Name", on_click); + return create(player, "Region", on_click); } public Menu create(final Player player, final String default_name, final Function2 on_click) { diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/menu/EnterRoleNameMenu.java b/vane-regions/src/main/java/org/oddlama/vane/regions/menu/EnterRoleNameMenu.java index a3601745e..6ede293a6 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/menu/EnterRoleNameMenu.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/menu/EnterRoleNameMenu.java @@ -25,7 +25,7 @@ public EnterRoleNameMenu(Context context) { } public Menu create(final Player player, final Function2 on_click) { - return create(player, "Role Name", on_click); + return create(player, "Role", on_click); } public Menu create(final Player player, final String default_name, final Function2 on_click) { diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/menu/MainMenu.java b/vane-regions/src/main/java/org/oddlama/vane/regions/menu/MainMenu.java index 3fcadd164..b729f3060 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/menu/MainMenu.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/menu/MainMenu.java @@ -24,6 +24,9 @@ import org.oddlama.vane.core.module.ModuleComponent; import org.oddlama.vane.regions.Regions; import org.oddlama.vane.regions.region.Region; +import org.oddlama.vane.regions.region.RegionGroup; +import org.oddlama.vane.regions.region.RegionSelection; +import org.oddlama.vane.regions.region.RoleSetting; public class MainMenu extends ModuleComponent { @LangMessage public TranslatedMessage lang_title; @@ -38,9 +41,11 @@ public class MainMenu extends ModuleComponent { public TranslatedItemStack item_cancel_selection; public TranslatedItemStack item_current_region; public TranslatedItemStack item_list_regions; + public TranslatedItemStack item_select_region; public TranslatedItemStack item_create_region_group; public TranslatedItemStack item_current_region_group; public TranslatedItemStack item_list_region_groups; + public TranslatedItemStack item_select_region_group; public MainMenu(Context context) { super(context.namespace("main")); @@ -51,10 +56,12 @@ public MainMenu(Context context) { item_create_region_valid_selection = new TranslatedItemStack<>(ctx, "create_region_valid_selection", Material.WRITABLE_BOOK, 1, "Used to create a new region with the current selection."); item_cancel_selection = new TranslatedItemStack<>(ctx, "cancel_selection", Material.RED_TERRACOTTA, 1, "Used to cancel region selection."); item_list_regions = new TranslatedItemStack<>(ctx, "list_regions", Material.COMPASS, 1, "Used to select a region the player may administrate."); + item_select_region = new TranslatedItemStack<>(ctx, "select_region", Material.FILLED_MAP, 1, "Used to represent a region in the region selection list."); item_current_region = new TranslatedItemStack<>(ctx, "current_region", Material.FILLED_MAP, 1, "Used to access the region the player currently stands in."); item_create_region_group = new TranslatedItemStack<>(ctx, "create_region_group", Material.WRITABLE_BOOK, 1, "Used to create a new region group."); item_list_region_groups = new TranslatedItemStack<>(ctx, "list_region_groups", Material.COMPASS, 1, "Used to select a region group the player may administrate."); item_current_region_group = new TranslatedItemStack<>(ctx, "current_region_group", Material.GLOBE_BANNER_PATTERN, 1, "Used to access the region group associated with the region the player currently stands in."); + item_select_region_group = new TranslatedItemStack<>(ctx, "select_region_group", Material.GLOBE_BANNER_PATTERN, 1, "Used to represent a region group in the region group selection list."); } public Menu create(final Player player) { @@ -62,12 +69,16 @@ public Menu create(final Player player) { final var title = lang_title.str(); final var main_menu = new Menu(get_context(), Bukkit.createInventory(null, columns, title)); - final var selection_mode = false; //TODO + final var selection_mode = get_module().is_selecting_region(player); final var region = get_module().region_at(player.getLocation()); + if (region != null) { + main_menu.tag(new RegionMenuTag(region.id())); + } // Check if target selection would be allowed if (selection_mode) { - main_menu.add(menu_item_create_region()); + final var selection = get_module().get_region_selection(player); + main_menu.add(menu_item_create_region(selection)); main_menu.add(menu_item_cancel_selection()); } else { main_menu.add(menu_item_start_selection()); @@ -80,7 +91,7 @@ public Menu create(final Player player) { main_menu.add(menu_item_create_region_group()); main_menu.add(menu_item_list_region_groups()); if (region != null) { - main_menu.add(menu_item_current_region_group(region.group(get_module()))); + main_menu.add(menu_item_current_region_group(region.region_group(get_module()))); } return main_menu; @@ -94,118 +105,99 @@ private MenuWidget menu_item_start_selection() { }); } - private MenuWidget menu_item_select_target(final Region region) { - return new MenuItem(4, null, (player, menu, self) -> { - if (region.target_locked()) { - return ClickResult.ERROR; - } else { + private MenuWidget menu_item_cancel_selection() { + return new MenuItem(1, item_cancel_selection.item(), (player, menu, self) -> { + menu.close(player); + get_module().cancel_region_selection(player); + return ClickResult.SUCCESS; + }); + } + + private MenuWidget menu_item_create_region(final RegionSelection selection) { + return new MenuItem(0, null, (player, menu, self) -> { + if (selection.is_valid()) { menu.close(player); - final var all_regions = get_module().all_regions() - .stream() - .filter(p -> { - switch (p.visibility()) { - case PUBLIC: return true; - case GROUP: return false; // TODO group visibility - case PRIVATE: return player.getUniqueId().equals(p.owner()); - } - return false; - }) - .filter(p -> !Objects.equals(p.id(), region.id())) - .sorted(new Region.TargetSelectionComparator(player)) - .collect(Collectors.toList()); - - final var filter = new Filter.StringFilter((p, str) -> p.name().toLowerCase().contains(str)); - MenuFactory.generic_selector(get_context(), player, lang_select_target_title.str(), lang_filter_regions_title.str(), all_regions, - p -> { - final var dist = p.spawn().toVector().setY(0.0).distance(player.getLocation().toVector().setY(0.0)); - return item_select_target_region.alternative(get_module().icon_for(p), "§a§l" + p.name(), "§6" + String.format("%.1f", dist), "§b" + p.spawn().getWorld().getName()); - }, - filter, - (player2, m, t) -> { - m.close(player2); - - final var select_target_event = new RegionSelectTargetEvent(player, region, t, false); - get_module().getServer().getPluginManager().callEvent(select_target_event); - if (select_target_event.isCancelled()) { - get_module().lang_select_target_restricted.send(player2); - return ClickResult.ERROR; - } - - region.target_id(t.id()); - - // Update region block to reflect new target on consoles - region.update_blocks(get_module()); - mark_persistent_storage_dirty(); - return ClickResult.SUCCESS; - }, player2 -> { - menu.open(player2); - }).tag(new RegionMenuTag(region.id())).open(player); + + get_module().menus.enter_region_name_menu.create(player, (player2, name) -> { + return ClickResult.SUCCESS; + }).on_natural_close(player2 -> { + menu.open(player2); + }).open(player); + return ClickResult.SUCCESS; + } else { + return ClickResult.ERROR; } }) { @Override public void item(final ItemStack item) { - final var target = region.target(get_module()); - final var target_name = "§a" + (target == null ? "None" : target.name()); - if (region.target_locked()) { - super.item(item_select_target_locked.item(target_name)); + if (selection.is_valid()) { + // TODO show x or checkmark (doesn't intersect existing, cost) + super.item(item_create_region_valid_selection.item( + "§b1","§b2","§b3" + )); } else { - super.item(item_select_target.item(target_name)); + super.item(item_create_region_invalid_selection.item( + "§a✓", + "§c✗✕", + "§c✗✕", + "§a✓", + "§a✓", + "§b1", "§b2", "§b3", + "§b4", "§b5", "§b6", + "§b7", "§b8", "§b9" + )); } } }; } - private MenuWidget menu_item_unlink_console(final Region region, final Block console) { - return new MenuItem(7, item_unlink_console.item(), (player, menu, self) -> { + private MenuWidget menu_item_list_regions() { + return new MenuItem(1, item_list_regions.item(), (player, menu, self) -> { menu.close(player); - MenuFactory.confirm(get_context(), lang_unlink_console_confirm_title.str(), - item_unlink_console_confirm_accept.item(), (player2) -> { - // Call event - final var event = new RegionUnlinkConsoleEvent(player2, region, false); - get_module().getServer().getPluginManager().callEvent(event); - if (event.isCancelled()) { - get_module().lang_unlink_restricted.send(player2); - return ClickResult.ERROR; - } - - final var region_block = region.region_block_for(console); - if (region_block == null) { - // Console was likely already removed by another player - return ClickResult.ERROR; - } - - get_module().remove_region_block(region, region_block); + final var all_regions = get_module().all_regions() + .stream() + .filter(r -> r.region_group(get_module()) + .get_role(player.getUniqueId()) + .get_setting(RoleSetting.ADMIN)) + .sorted((a, b) -> a.name().compareToIgnoreCase(b.name())) + .collect(Collectors.toList()); + + final var filter = new Filter.StringFilter((r, str) -> r.name().toLowerCase().contains(str)); + MenuFactory.generic_selector(get_context(), player, lang_select_target_title.str(), lang_filter_regions_title.str(), all_regions, + r -> item_select_region.item("§a§l" + r.name()), + filter, + (player2, m, region) -> { + m.close(player2); + // TODO get_module().menus.region_menu.create(player2, region).open(player2); return ClickResult.SUCCESS; - }, item_unlink_console_confirm_cancel.item(), (player2) -> { + }, player2 -> { menu.open(player2); - }) - .tag(new RegionMenuTag(region.id())) - .open(player); + }).open(player); return ClickResult.SUCCESS; }); } - private MenuWidget menu_item_destroy_region(final Region region) { - return new MenuItem(8, item_destroy_region.item(), (player, menu, self) -> { - menu.close(player); - MenuFactory.confirm(get_context(), lang_destroy_region_confirm_title.str(), - item_destroy_region_confirm_accept.item(), (player2) -> { - // Call event - final var event = new RegionDestroyEvent(player2, region, false); - get_module().getServer().getPluginManager().callEvent(event); - if (event.isCancelled()) { - get_module().lang_destroy_restricted.send(player2); - return ClickResult.ERROR; - } - - get_module().remove_region(region); - return ClickResult.SUCCESS; - }, item_destroy_region_confirm_cancel.item(), (player2) -> { - menu.open(player2); - }) - .tag(new RegionMenuTag(region.id())) - .open(player); + private MenuWidget menu_item_current_region(final Region region) { + return new MenuItem(2, item_current_region.item(), (player, menu, self) -> { + return ClickResult.SUCCESS; + }); + } + + private MenuWidget menu_item_create_region_group() { + return new MenuItem(6, item_create_region_group.item(), (player, menu, self) -> { + return ClickResult.SUCCESS; + }); + } + + private MenuWidget menu_item_list_region_groups() { + return new MenuItem(7, item_list_region_groups.item(), (player, menu, self) -> { + return ClickResult.SUCCESS; + }); + } + + private MenuWidget menu_item_current_region_group(final RegionGroup region_group) { + return new MenuItem(8, item_current_region_group.item(), (player, menu, self) -> { return ClickResult.SUCCESS; }); } diff --git a/vane-regions/src/main/resources/lang-de.yml b/vane-regions/src/main/resources/lang-de.yml index 623252a6d..a9855eb67 100644 --- a/vane-regions/src/main/resources/lang-de.yml +++ b/vane-regions/src/main/resources/lang-de.yml @@ -12,7 +12,7 @@ # DO NOT CHANGE! The version of this language file. Used to determine # if the file needs to be updated. -version: 1 +version: 2 # The corresponding language code used in resource packs. Used for # resource pack generation. Typically this is a combination of the # language code (ISO 639) and the country code (ISO 3166). diff --git a/vane-regions/src/main/resources/lang-en.yml b/vane-regions/src/main/resources/lang-en.yml index 1ce538784..4490ce217 100644 --- a/vane-regions/src/main/resources/lang-en.yml +++ b/vane-regions/src/main/resources/lang-en.yml @@ -12,8 +12,135 @@ # DO NOT CHANGE! The version of this language file. Used to determine # if the file needs to be updated. -version: 1 +version: 2 # The corresponding language code used in resource packs. Used for # resource pack generation. Typically this is a combination of the # language code (ISO 639) and the country code (ISO 3166). resource_pack_lang_code: 'en_us' + +# This message is sent when the player needs to select an area for +# a new region. +start_region_selection: "§aChoose an area by selecting two blocks via §bleft-§a and §bright-click§a with an empty hand." + +dynmap: + # The label for the dynmap layer + layer_label: "Regions" + # The label for the dynmap markers + # %1$s: Region name + marker_label: "%1$s" + +menus: + # Settings for the region group naming menu. + enter_region_group_name: + # The title for the naming menu. + title: "§8§lEnter Region Group Name" + + # Settings for the region naming menu. + enter_region_name: + # The title for the naming menu. + title: "§8§lEnter Region Name" + + # Settings for the role naming menu. + enter_role_name: + # The title for the naming menu. + title: "§8§lEnter Role Name" + + # Settings for the main menu. + main: + # The title for the main menu. + title: "§8§lManage Regions" + # The item used to start a new region selection. + create_region_start_selection: + name: "§a§lCreate Region" + lore: + - "" + - "§7Starts a new region selection. With an empty hand," + - "§6left-click§7 to select the first block and" + - "§6right-click§7 to select the second block. The" + - "§7volume between the blocks will become the region." + # This item is shown when the selection is invalid + # %1$s: Checkmark: primary block set + # %2$s: Checkmark: secondary block set + # %3$s: Checkmark: minimum area condition met + # %4$s: Checkmark: not bigger than + # %5$s: Checkmark: doesn't interact existing region + # %6$s: Selection extent X + # %7$s: Selection extent Y + # %8$s: Selection extent Z + # %9$s: min extent X + # %10$s: min extent Y + # %11$s: min extent Z + # %12$s: max extent X + # %13$s: max extent Y + # %14$s: max extent Z + create_region_invalid_selection: + name: "§c§lInvalid Selection" + lore: + - "" + - "§6Your selection (%6$s x %7$s x %8$s) is invalid!" + - "§6It must meet the following requirements:" + - "§7- %1$s Primary block set" + - "§7- %2$s Secondary block set" + - "§7- %5$s Doesn't intersect existing region" + - "§7- %3$s Covers minimum area (%9$s x %10$s x %11$s)" + - "§7- %4$s Not bigger than (%12$s x %13$s x %14$s)" + # This item is shown when the selection is valid + # %1$s: Selection extent X + # %2$s: Selection extent Y + # %3$s: Selection extent Z + create_region_valid_selection: + name: "§a§lCreate Region" + lore: + - "" + - "§7Your selection (%1$s x %2$s x %3$s) is valid." + - "§7Create a new region by clinking this item." + # This item is used to cancel a pending selection. + cancel_selection: + name: "§c§lCancel Selection" + lore: [] + # This item is used to select a region where the player is administrator. + list_regions: + name: "§b§lSelect Region" + lore: [] + # This item is used to represent a region in the selection menu. + # %1$s: Region name + select_region: + name: "%1$s" + lore: [] + # This item is a shortcut to select the region the player is standing in. + # %1$s: Region name + current_region: + name: "§b§lCurrent Region" + lore: + - "" + - "§7Region: %1$s" + - "" + - "§7Select the region you are standing in." + # This item is used to create a new region group. + create_region_group: + name: "§a§lCreate Region Group" + lore: + - "" + - "§7Create a new §bregion group§7. Region groups" + - "§7are used to set permissions for players" + - "§7by assigning them roles. All regions in" + - "§7a region group will share these permissions" + # This item is used to select a region group. + list_region_groups: + name: "§b§lSelect region group" + lore: [] + # This item is a shortcut to select the region group of the region the player is standing in. + # %1$s: Region group name + current_region_group: + name: "§b§lCurrent Region Group" + lore: + - "" + - "§7Region Group: %1$s" + - "" + - "§7Select the region group of the" + - "§7region you are standing in." + # This item is used to represent a region group in the selection menu. + # %1$s: Region group name + select_region_group: + name: "%1$s" + lore: [] From b92185b798d7265e3e187678394006804a7d9126 Mon Sep 17 00:00:00 2001 From: oddlama Date: Mon, 15 Mar 2021 14:37:28 +0100 Subject: [PATCH 10/40] Added region selection listener and in-menu validity indication --- .../vane/regions/RegionSelectionListener.java | 78 +++++++++++++++++++ .../org/oddlama/vane/regions/Regions.java | 16 ++++ .../oddlama/vane/regions/menu/MainMenu.java | 70 +++++++++++++---- .../vane/regions/region/RegionSelection.java | 53 ++++++++++--- vane-regions/src/main/resources/lang-en.yml | 52 ++++++++++--- 5 files changed, 236 insertions(+), 33 deletions(-) create mode 100644 vane-regions/src/main/java/org/oddlama/vane/regions/RegionSelectionListener.java diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/RegionSelectionListener.java b/vane-regions/src/main/java/org/oddlama/vane/regions/RegionSelectionListener.java new file mode 100644 index 000000000..8261fb6c8 --- /dev/null +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/RegionSelectionListener.java @@ -0,0 +1,78 @@ +package org.oddlama.vane.regions; + +import org.bukkit.event.Event; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.block.BlockBreakEvent; +import org.bukkit.event.block.BlockPlaceEvent; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.inventory.EquipmentSlot; +import org.bukkit.Material; + +import org.bukkit.block.Block; +import org.bukkit.Location; +import org.bukkit.entity.Player; + +import org.oddlama.vane.annotation.lang.LangMessage; +import org.oddlama.vane.core.lang.TranslatedMessage; +import org.oddlama.vane.core.Listener; +import org.oddlama.vane.core.module.Context; +import org.oddlama.vane.regions.region.RoleSetting; + +public class RegionSelectionListener extends Listener { + @LangMessage public TranslatedMessage lang_select_primary_block; + @LangMessage public TranslatedMessage lang_select_secondary_block; + + public RegionSelectionListener(Context context) { + super(context); + } + + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = false) + public void on_player_interact(final PlayerInteractEvent event) { + // Require main hand event + if (event.getHand() != EquipmentSlot.HAND) { + return; + } + + // Require empty hand + if (event.getItem() != null) { + return; + } + + final var player = event.getPlayer(); + final var selection = get_module().get_region_selection(player); + if (selection == null) { + return; + } + + if (player.getEquipment().getItemInMainHand().getType() != Material.AIR || + player.getEquipment().getItemInOffHand().getType() != Material.AIR) { + return; + } + + final var block = event.getClickedBlock(); + switch (event.getAction()) { + default: + return; + + case LEFT_CLICK_BLOCK: + selection.primary = block; + lang_select_primary_block.send(player, + "§b" + block.getX(), + "§b" + block.getY(), + "§b" + block.getZ()); + break; + + case RIGHT_CLICK_BLOCK: + selection.secondary = block; + lang_select_secondary_block.send(player, + "§b" + block.getX(), + "§b" + block.getY(), + "§b" + block.getZ()); + break; + } + + event.setUseInteractedBlock(Event.Result.DENY); + event.setUseItemInHand(Event.Result.DENY); + } +} diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/Regions.java b/vane-regions/src/main/java/org/oddlama/vane/regions/Regions.java index ab94a6ada..5745a64d7 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/Regions.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/Regions.java @@ -58,6 +58,7 @@ import org.oddlama.vane.core.module.Module; import org.oddlama.vane.core.persistent.PersistentSerializer; import org.oddlama.vane.regions.region.Region; +import org.oddlama.vane.annotation.config.ConfigInt; import org.oddlama.vane.regions.region.RegionGroup; import org.oddlama.vane.regions.region.RegionSelection; import org.oddlama.vane.regions.region.Role; @@ -120,6 +121,20 @@ public class Regions extends Module { PersistentSerializer.deserializers.put(RegionExtent.class, RegionExtent::deserialize); } + @ConfigInt(def = 4, min = 1, desc = "Minimum region extent in x direction.") + public int config_min_region_extent_x; + @ConfigInt(def = 4, min = 1, desc = "Minimum region extent in y direction.") + public int config_min_region_extent_y; + @ConfigInt(def = 4, min = 1, desc = "Minimum region extent in z direction.") + public int config_min_region_extent_z; + + @ConfigInt(def = 2048, min = 1, desc = "Maximum region extent in x direction.") + public int config_max_region_extent_x; + @ConfigInt(def = 2048, min = 1, desc = "Maximum region extent in y direction.") + public int config_max_region_extent_y; + @ConfigInt(def = 2048, min = 1, desc = "Maximum region extent in z direction.") + public int config_max_region_extent_z; + // Primary storage for all regions (region.id → region) @Persistent private Map storage_regions = new HashMap<>(); @@ -149,6 +164,7 @@ public Regions() { //dynmap_layer = new RegionDynmapLayer(this); new RegionEnvironmentSettingEnforcer(this); new RegionRoleSettingEnforcer(this); + new RegionSelectionListener(this); } public void on_enable() { diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/menu/MainMenu.java b/vane-regions/src/main/java/org/oddlama/vane/regions/menu/MainMenu.java index b729f3060..53fb9ea44 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/menu/MainMenu.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/menu/MainMenu.java @@ -30,9 +30,7 @@ public class MainMenu extends ModuleComponent { @LangMessage public TranslatedMessage lang_title; - @LangMessage public TranslatedMessage lang_unlink_console_confirm_title; - @LangMessage public TranslatedMessage lang_destroy_region_confirm_title; - @LangMessage public TranslatedMessage lang_select_target_title; + @LangMessage public TranslatedMessage lang_select_region_title; @LangMessage public TranslatedMessage lang_filter_regions_title; public TranslatedItemStack item_create_region_start_selection; @@ -132,20 +130,64 @@ private MenuWidget menu_item_create_region(final RegionSelection selection) { @Override public void item(final ItemStack item) { if (selection.is_valid()) { - // TODO show x or checkmark (doesn't intersect existing, cost) + final var dx = 1 + Math.abs(selection.primary.getX() - selection.secondary.getX()); + final var dy = 1 + Math.abs(selection.primary.getY() - selection.secondary.getY()); + final var dz = 1 + Math.abs(selection.primary.getZ() - selection.secondary.getZ()); super.item(item_create_region_valid_selection.item( - "§b1","§b2","§b3" + "§a" + dx, + "§a" + dy, + "§a" + dz )); } else { + boolean is_primary_set = selection.primary != null; + boolean is_secondary_set = selection.secondary != null; + boolean same_world = selection.primary.getWorld().equals(selection.secondary.getWorld()); + is_secondary_set &= same_world; + + boolean minimum_satisified, maximum_satisfied; + String sdx, sdy, sdz; + if (is_primary_set && is_secondary_set) { + final var dx = 1 + Math.abs(selection.primary.getX() - selection.secondary.getX()); + final var dy = 1 + Math.abs(selection.primary.getY() - selection.secondary.getY()); + final var dz = 1 + Math.abs(selection.primary.getZ() - selection.secondary.getZ()); + sdx = Integer.toString(dx); + sdy = Integer.toString(dy); + sdz = Integer.toString(dz); + + minimum_satisified = + dx >= get_module().config_min_region_extent_x && + dy >= get_module().config_min_region_extent_y && + dz >= get_module().config_min_region_extent_z; + maximum_satisfied = + dx <= get_module().config_max_region_extent_x && + dy <= get_module().config_max_region_extent_y && + dz <= get_module().config_max_region_extent_z; + } else { + sdx = "§7?"; + sdy = "§7?"; + sdz = "§7?"; + minimum_satisified = false; + maximum_satisfied = false; + } + + final var extent_color = minimum_satisified && maximum_satisfied ? "§a" : "§c"; + final var no_intersection = !selection.intersects_existing(); + super.item(item_create_region_invalid_selection.item( - "§a✓", - "§c✗✕", - "§c✗✕", - "§a✓", - "§a✓", - "§b1", "§b2", "§b3", - "§b4", "§b5", "§b6", - "§b7", "§b8", "§b9" + is_primary_set ? "§a✓" : "§c✗✕", + is_secondary_set ? "§a✓" : "§c✗✕", + no_intersection ? "§a✓" : "§c✗✕", + minimum_satisified ? "§a✓" : "§c✗✕", + maximum_satisfied ? "§a✓" : "§c✗✕", + extent_color + sdx, + extent_color + sdy, + extent_color + sdz, + "§b" + get_module().config_min_region_extent_x, + "§b" + get_module().config_min_region_extent_y, + "§b" + get_module().config_min_region_extent_z, + "§b" + get_module().config_max_region_extent_x, + "§b" + get_module().config_max_region_extent_y, + "§b" + get_module().config_max_region_extent_z )); } } @@ -164,7 +206,7 @@ private MenuWidget menu_item_list_regions() { .collect(Collectors.toList()); final var filter = new Filter.StringFilter((r, str) -> r.name().toLowerCase().contains(str)); - MenuFactory.generic_selector(get_context(), player, lang_select_target_title.str(), lang_filter_regions_title.str(), all_regions, + MenuFactory.generic_selector(get_context(), player, lang_select_region_title.str(), lang_filter_regions_title.str(), all_regions, r -> item_select_region.item("§a§l" + r.name()), filter, (player2, m, region) -> { diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/region/RegionSelection.java b/vane-regions/src/main/java/org/oddlama/vane/regions/region/RegionSelection.java index 8696b20bd..6dd59a0ee 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/region/RegionSelection.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/region/RegionSelection.java @@ -66,24 +66,59 @@ public class RegionSelection { private Regions regions; - private Block primary = null; - private Block secondary = null; + public Block primary = null; + public Block secondary = null; public RegionSelection(final Regions regions) { this.regions = regions; } - public void set_primary(final Block block) { - primary = block; - } + public boolean intersects_existing() { + final var extent = new RegionExtent(primary, secondary); + for (final var r : regions.all_regions()) { + if (!r.extent().min().getWorld().equals(primary.getWorld())) { + continue; + } + + if (extent.intersects_extent(r.extent())) { + return true; + } + } - public void set_secondary(final Block block) { - secondary = block; + return false; } public boolean is_valid() { - // not null, worlds match, size at least X, at max Z - return false; + // Both blocks set + if (primary == null || secondary == null) { + return false; + } + + // Worlds match + if (!primary.getWorld().equals(secondary.getWorld())) { + return false; + } + + final var dx = 1 + Math.abs(primary.getX() - secondary.getX()); + final var dy = 1 + Math.abs(primary.getY() - secondary.getY()); + final var dz = 1 + Math.abs(primary.getZ() - secondary.getZ()); + + // min <= extent <= max + if (dx < regions.config_min_region_extent_x || + dy < regions.config_min_region_extent_y || + dz < regions.config_min_region_extent_z || + dx > regions.config_max_region_extent_x || + dy > regions.config_max_region_extent_y || + dz > regions.config_max_region_extent_z) { + return false; + } + + // Assert that it doesn't intersect an existing region + if (intersects_existing()) { + return false; + } + + return true; } public RegionExtent to_extent() { diff --git a/vane-regions/src/main/resources/lang-en.yml b/vane-regions/src/main/resources/lang-en.yml index 4490ce217..acee9e490 100644 --- a/vane-regions/src/main/resources/lang-en.yml +++ b/vane-regions/src/main/resources/lang-en.yml @@ -21,6 +21,23 @@ resource_pack_lang_code: 'en_us' # This message is sent when the player needs to select an area for # a new region. start_region_selection: "§aChoose an area by selecting two blocks via §bleft-§a and §bright-click§a with an empty hand." +# This message is sent when the player selects the primary block +# for a new region. +# %1$s: Block X +# %2$s: Block Y +# %3$s: Block Z +select_primary_block: "§aSelected (%1$s§a, %2$s§a, %3$s§a) as primary block." +# This message is sent when the player selects the secondary block +# for a new region. +# %1$s: Block X +# %2$s: Block Y +# %3$s: Block Z +select_secondary_block: "§aSelected (%1$s§a, %2$s§a, %3$s§a) as secondary block." + +command_region: + usage: "%1$s" + description: "Open the region management menu." + help: "Execute to open the region management menu." dynmap: # The label for the dynmap layer @@ -49,6 +66,7 @@ menus: main: # The title for the main menu. title: "§8§lManage Regions" + # The item used to start a new region selection. create_region_start_selection: name: "§a§lCreate Region" @@ -58,12 +76,13 @@ menus: - "§6left-click§7 to select the first block and" - "§6right-click§7 to select the second block. The" - "§7volume between the blocks will become the region." + # This item is shown when the selection is invalid # %1$s: Checkmark: primary block set # %2$s: Checkmark: secondary block set - # %3$s: Checkmark: minimum area condition met - # %4$s: Checkmark: not bigger than - # %5$s: Checkmark: doesn't interact existing region + # %3$s: Checkmark: doesn't interact existing region + # %4$s: Checkmark: minimum area condition met + # %5$s: Checkmark: not bigger than max # %6$s: Selection extent X # %7$s: Selection extent Y # %8$s: Selection extent Z @@ -77,13 +96,14 @@ menus: name: "§c§lInvalid Selection" lore: - "" - - "§6Your selection (%6$s x %7$s x %8$s) is invalid!" + - "§6Your selection (%6$s§6 x %7$s§6 x %8$s§6) is invalid!" - "§6It must meet the following requirements:" - - "§7- %1$s Primary block set" - - "§7- %2$s Secondary block set" - - "§7- %5$s Doesn't intersect existing region" - - "§7- %3$s Covers minimum area (%9$s x %10$s x %11$s)" - - "§7- %4$s Not bigger than (%12$s x %13$s x %14$s)" + - "§7- %1$s§7 Primary block set" + - "§7- %2$s§7 Secondary block set" + - "§7- %3$s§7 Doesn't intersect existing region" + - "§7- %4$s§7 Covers minimum area (%9$s§7 x %10$s§7 x %11$s§7)" + - "§7- %5$s§7 Not bigger than (%12$s§7 x %13$s§7 x %14$s§7)" + # This item is shown when the selection is valid # %1$s: Selection extent X # %2$s: Selection extent Y @@ -92,21 +112,29 @@ menus: name: "§a§lCreate Region" lore: - "" - - "§7Your selection (%1$s x %2$s x %3$s) is valid." + - "§7Your selection (%1$s§7 x %2$s§7 x %3$s§7) is valid." - "§7Create a new region by clinking this item." + # This item is used to cancel a pending selection. cancel_selection: name: "§c§lCancel Selection" lore: [] + # This item is used to select a region where the player is administrator. list_regions: name: "§b§lSelect Region" lore: [] + + # The title for the region selection menu + select_region_title: "§8§lSelect Region" + # The title for the region selection menu filter + filter_regions_title: "§8§lFilter Regions" # This item is used to represent a region in the selection menu. # %1$s: Region name select_region: name: "%1$s" lore: [] + # This item is a shortcut to select the region the player is standing in. # %1$s: Region name current_region: @@ -116,6 +144,7 @@ menus: - "§7Region: %1$s" - "" - "§7Select the region you are standing in." + # This item is used to create a new region group. create_region_group: name: "§a§lCreate Region Group" @@ -125,10 +154,12 @@ menus: - "§7are used to set permissions for players" - "§7by assigning them roles. All regions in" - "§7a region group will share these permissions" + # This item is used to select a region group. list_region_groups: name: "§b§lSelect region group" lore: [] + # This item is a shortcut to select the region group of the region the player is standing in. # %1$s: Region group name current_region_group: @@ -139,6 +170,7 @@ menus: - "" - "§7Select the region group of the" - "§7region you are standing in." + # This item is used to represent a region group in the selection menu. # %1$s: Region group name select_region_group: From 6fc6f2c3d910de888dc1b18aad760ab9e0748ddb Mon Sep 17 00:00:00 2001 From: oddlama Date: Mon, 15 Mar 2021 16:48:33 +0100 Subject: [PATCH 11/40] Added barebones region, region group, and role menu --- .../java/org/oddlama/vane/util/ItemUtil.java | 9 + .../org/oddlama/vane/regions/Regions.java | 17 ++ .../oddlama/vane/regions/menu/MainMenu.java | 53 +++--- .../vane/regions/menu/RegionGroupMenu.java | 150 +++++++++++++++ .../oddlama/vane/regions/menu/RegionMenu.java | 136 ++++++++++++++ .../vane/regions/menu/RegionMenuGroup.java | 6 + .../oddlama/vane/regions/menu/RoleMenu.java | 172 ++++++++++++++++++ .../oddlama/vane/regions/region/Region.java | 13 +- .../vane/regions/region/RegionGroup.java | 15 ++ .../vane/regions/region/RegionSelection.java | 21 ++- .../org/oddlama/vane/regions/region/Role.java | 1 + vane-regions/src/main/resources/lang-de.yml | 102 +++++++++++ vane-regions/src/main/resources/lang-en.yml | 52 ++++-- 13 files changed, 701 insertions(+), 46 deletions(-) create mode 100644 vane-regions/src/main/java/org/oddlama/vane/regions/menu/RegionGroupMenu.java create mode 100644 vane-regions/src/main/java/org/oddlama/vane/regions/menu/RegionMenu.java create mode 100644 vane-regions/src/main/java/org/oddlama/vane/regions/menu/RoleMenu.java diff --git a/vane-core/src/main/java/org/oddlama/vane/util/ItemUtil.java b/vane-core/src/main/java/org/oddlama/vane/util/ItemUtil.java index 0580616f5..938bd7ec1 100644 --- a/vane-core/src/main/java/org/oddlama/vane/util/ItemUtil.java +++ b/vane-core/src/main/java/org/oddlama/vane/util/ItemUtil.java @@ -21,6 +21,7 @@ import org.bukkit.Bukkit; import org.bukkit.Material; +import org.bukkit.OfflinePlayer; import org.bukkit.craftbukkit.v1_16_R3.enchantments.CraftEnchantment; import org.bukkit.enchantments.Enchantment; import org.bukkit.entity.Player; @@ -214,6 +215,14 @@ public int compare(final ItemStack a, final ItemStack b) { } } + public static ItemStack skull_for_player(final OfflinePlayer player) { + final var item = new ItemStack(Material.PLAYER_HEAD); + final var meta = (SkullMeta)item.getItemMeta(); + meta.setOwningPlayer(player); + item.setItemMeta(meta); + return item; + } + public static ItemStack skull_with_texture(final String name, final String base64_texture) { final var profile = Bukkit.createProfile(SKULL_OWNER); profile.setProperty(new ProfileProperty("textures", base64_texture)); diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/Regions.java b/vane-regions/src/main/java/org/oddlama/vane/regions/Regions.java index 5745a64d7..e43309c84 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/Regions.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/Regions.java @@ -177,6 +177,10 @@ public Collection all_regions() { return storage_regions.values(); } + public Collection all_region_groups() { + return storage_region_groups.values(); + } + public void start_region_selection(final Player player) { regions_selections.put(player.getUniqueId(), new RegionSelection(this)); lang_start_region_selection.send(player); @@ -244,6 +248,19 @@ public RegionGroup get_region_group(final UUID region_group) { return storage_region_groups.get(region_group); } + public boolean create_region_from_selection(final Player player, final String name) { + final var selection = get_region_selection(player); + if (!selection.is_valid(player)) { + return false; + } + + final var def_region_group = get_or_create_default_region_group(player.getUniqueId()); + final var region = new Region(name, player.getUniqueId(), selection.extent(), def_region_group.id()); + add_region(region); + cancel_region_selection(player); + return true; + } + public void add_region(final Region region) { storage_regions.put(region.id(), region); mark_persistent_storage_dirty(); diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/menu/MainMenu.java b/vane-regions/src/main/java/org/oddlama/vane/regions/menu/MainMenu.java index 53fb9ea44..9b163e791 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/menu/MainMenu.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/menu/MainMenu.java @@ -53,7 +53,7 @@ public MainMenu(Context context) { item_create_region_invalid_selection = new TranslatedItemStack<>(ctx, "create_region_invalid_selection", Material.BARRIER, 1, "Used to indicate an invalid selection."); item_create_region_valid_selection = new TranslatedItemStack<>(ctx, "create_region_valid_selection", Material.WRITABLE_BOOK, 1, "Used to create a new region with the current selection."); item_cancel_selection = new TranslatedItemStack<>(ctx, "cancel_selection", Material.RED_TERRACOTTA, 1, "Used to cancel region selection."); - item_list_regions = new TranslatedItemStack<>(ctx, "list_regions", Material.COMPASS, 1, "Used to select a region the player may administrate."); + item_list_regions = new TranslatedItemStack<>(ctx, "list_regions", Material.COMPASS, 1, "Used to select a region the player owns."); item_select_region = new TranslatedItemStack<>(ctx, "select_region", Material.FILLED_MAP, 1, "Used to represent a region in the region selection list."); item_current_region = new TranslatedItemStack<>(ctx, "current_region", Material.FILLED_MAP, 1, "Used to access the region the player currently stands in."); item_create_region_group = new TranslatedItemStack<>(ctx, "create_region_group", Material.WRITABLE_BOOK, 1, "Used to create a new region group."); @@ -76,7 +76,7 @@ public Menu create(final Player player) { // Check if target selection would be allowed if (selection_mode) { final var selection = get_module().get_region_selection(player); - main_menu.add(menu_item_create_region(selection)); + main_menu.add(menu_item_create_region(player, selection)); main_menu.add(menu_item_cancel_selection()); } else { main_menu.add(menu_item_start_selection()); @@ -111,13 +111,17 @@ private MenuWidget menu_item_cancel_selection() { }); } - private MenuWidget menu_item_create_region(final RegionSelection selection) { + private MenuWidget menu_item_create_region(final Player final_player, final RegionSelection selection) { return new MenuItem(0, null, (player, menu, self) -> { - if (selection.is_valid()) { + if (selection.is_valid(final_player)) { menu.close(player); get_module().menus.enter_region_name_menu.create(player, (player2, name) -> { - return ClickResult.SUCCESS; + if (get_module().create_region_from_selection(final_player, name)) { + return ClickResult.SUCCESS; + } else { + return ClickResult.ERROR; + } }).on_natural_close(player2 -> { menu.open(player2); }).open(player); @@ -129,24 +133,29 @@ private MenuWidget menu_item_create_region(final RegionSelection selection) { }) { @Override public void item(final ItemStack item) { - if (selection.is_valid()) { + if (selection.is_valid(final_player)) { final var dx = 1 + Math.abs(selection.primary.getX() - selection.secondary.getX()); final var dy = 1 + Math.abs(selection.primary.getY() - selection.secondary.getY()); final var dz = 1 + Math.abs(selection.primary.getZ() - selection.secondary.getZ()); super.item(item_create_region_valid_selection.item( "§a" + dx, "§a" + dy, - "§a" + dz + "§a" + dz, + "§b" + get_module().config_min_region_extent_x, + "§b" + get_module().config_min_region_extent_y, + "§b" + get_module().config_min_region_extent_z, + "§b" + get_module().config_max_region_extent_x, + "§b" + get_module().config_max_region_extent_y, + "§b" + get_module().config_max_region_extent_z )); } else { boolean is_primary_set = selection.primary != null; boolean is_secondary_set = selection.secondary != null; - boolean same_world = selection.primary.getWorld().equals(selection.secondary.getWorld()); - is_secondary_set &= same_world; + boolean same_world = is_primary_set && is_secondary_set && selection.primary.getWorld().equals(selection.secondary.getWorld()); - boolean minimum_satisified, maximum_satisfied; + boolean minimum_satisified, maximum_satisfied, no_intersection, can_afford; String sdx, sdy, sdz; - if (is_primary_set && is_secondary_set) { + if (is_primary_set && is_secondary_set && same_world) { final var dx = 1 + Math.abs(selection.primary.getX() - selection.secondary.getX()); final var dy = 1 + Math.abs(selection.primary.getY() - selection.secondary.getY()); final var dz = 1 + Math.abs(selection.primary.getZ() - selection.secondary.getZ()); @@ -162,23 +171,27 @@ public void item(final ItemStack item) { dx <= get_module().config_max_region_extent_x && dy <= get_module().config_max_region_extent_y && dz <= get_module().config_max_region_extent_z; + no_intersection = !selection.intersects_existing(); + can_afford = selection.can_afford(final_player); } else { sdx = "§7?"; sdy = "§7?"; sdz = "§7?"; minimum_satisified = false; maximum_satisfied = false; + no_intersection = true; + can_afford = false; } final var extent_color = minimum_satisified && maximum_satisfied ? "§a" : "§c"; - final var no_intersection = !selection.intersects_existing(); - super.item(item_create_region_invalid_selection.item( - is_primary_set ? "§a✓" : "§c✗✕", - is_secondary_set ? "§a✓" : "§c✗✕", - no_intersection ? "§a✓" : "§c✗✕", - minimum_satisified ? "§a✓" : "§c✗✕", - maximum_satisfied ? "§a✓" : "§c✗✕", + is_primary_set ? "§a✓" : "§c✕", + is_secondary_set ? "§a✓" : "§c✕", + same_world ? "§a✓" : "§c✕", + no_intersection ? "§a✓" : "§c✕", + minimum_satisified ? "§a✓" : "§c✕", + maximum_satisfied ? "§a✓" : "§c✕", + can_afford ? "§a✓" : "§c✕", extent_color + sdx, extent_color + sdy, extent_color + sdz, @@ -199,9 +212,7 @@ private MenuWidget menu_item_list_regions() { menu.close(player); final var all_regions = get_module().all_regions() .stream() - .filter(r -> r.region_group(get_module()) - .get_role(player.getUniqueId()) - .get_setting(RoleSetting.ADMIN)) + .filter(r -> player.getUniqueId().equals(r.owner())) .sorted((a, b) -> a.name().compareToIgnoreCase(b.name())) .collect(Collectors.toList()); diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RegionGroupMenu.java b/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RegionGroupMenu.java new file mode 100644 index 000000000..abded9cdc --- /dev/null +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RegionGroupMenu.java @@ -0,0 +1,150 @@ +package org.oddlama.vane.regions.menu; + +import static org.oddlama.vane.util.Util.namespaced_key; + +import java.util.Objects; +import java.util.stream.Collectors; + +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +import org.oddlama.vane.annotation.lang.LangMessage; +import org.oddlama.vane.core.config.TranslatedItemStack; +import org.oddlama.vane.core.lang.TranslatedMessage; +import org.oddlama.vane.core.menu.Filter; +import org.oddlama.vane.core.menu.Menu.ClickResult; +import org.oddlama.vane.core.menu.Menu; +import org.oddlama.vane.core.menu.MenuFactory; +import org.oddlama.vane.core.menu.MenuItem; +import org.oddlama.vane.core.menu.MenuWidget; +import org.oddlama.vane.core.module.Context; +import org.oddlama.vane.core.module.ModuleComponent; +import org.oddlama.vane.regions.Regions; +import org.oddlama.vane.regions.region.Region; +import org.oddlama.vane.regions.region.RegionGroup; +import org.oddlama.vane.regions.region.RegionSelection; +import org.oddlama.vane.regions.region.RoleSetting; +import org.oddlama.vane.regions.region.Role; + +public class RegionGroupMenu extends ModuleComponent { + @LangMessage public TranslatedMessage lang_title; + @LangMessage public TranslatedMessage lang_select_role_title; + @LangMessage public TranslatedMessage lang_filter_roles_title; + + public TranslatedItemStack item_rename; + public TranslatedItemStack item_delete; + public TranslatedItemStack item_environment_settings; + public TranslatedItemStack item_create_role; + public TranslatedItemStack item_list_roles; + public TranslatedItemStack item_select_role; + + public RegionGroupMenu(Context context) { + super(context.namespace("region_group")); + + final var ctx = get_context(); + item_rename = new TranslatedItemStack<>(ctx, "rename", Material.NAME_TAG, 1, "Used to rename the region group."); + item_delete = new TranslatedItemStack<>(ctx, "delete", namespaced_key("vane", "decoration_tnt_1"), 1, "Used to delete this region group."); + // TODO icon... + item_environment_settings = new TranslatedItemStack<>(ctx, "environment_settings", Material.FLOWER_POT, 1, "Used to open the environment settings."); + item_create_role = new TranslatedItemStack<>(ctx, "create_role", Material.WRITABLE_BOOK, 1, "Used to create a new role."); + item_list_roles = new TranslatedItemStack<>(ctx, "list_roles", Material.GLOBE_BANNER_PATTERN, 1, "Used to list all defined roles."); + item_select_role = new TranslatedItemStack<>(ctx, "select_role", Material.GLOBE_BANNER_PATTERN, 1, "Used to represent a role in the role selection list."); + } + + public Menu create(final RegionGroup group, final Player player) { + final var columns = 9; + final var title = lang_title.str(); + final var region_group_menu = new Menu(get_context(), Bukkit.createInventory(null, columns, title)); + region_group_menu.tag(new RegionGroupMenuTag(group.id())); + + final var is_owner = player.getUniqueId().equals(group.owner()); + if (is_owner) { + region_group_menu.add(menu_item_rename(group)); + region_group_menu.add(menu_item_delete(group)); + } + + region_group_menu.add(menu_item_environment_settings(group)); + region_group_menu.add(menu_item_create_role(group)); + region_group_menu.add(menu_item_list_roles(group)); + + return region_group_menu; + } + + private MenuWidget menu_item_rename(final RegionGroup group) { + return new MenuItem(0, item_rename.item(), (player, menu, self) -> { + menu.close(player); + + get_module().menus.enter_region_group_name_menu.create(player, group.name(), (player2, name) -> { + group.name(name); + mark_persistent_storage_dirty(); + + // Open new menu because of possibly changed title + get_module().menus.region_group_menu.create(group, player2).open(player2); + return ClickResult.SUCCESS; + }).on_natural_close(player2 -> { + // Open new menu because of possibly changed title + get_module().menus.region_group_menu.create(group, player2).open(player2); + }).open(player); + + return ClickResult.SUCCESS; + }); + } + + private MenuWidget menu_item_delete(final RegionGroup group) { + final var orphan_checkbox = group.is_orphan(get_module()) ? "§a✓" : "§c✕"; + return new MenuItem(1, item_delete.item(orphan_checkbox), (player, menu, self) -> { + if (!player.getUniqueId().equals(group.owner())) { + return ClickResult.ERROR; + } + + if (!group.is_orphan(get_module())) { + return ClickResult.ERROR; + } + + get_module().remove_region_group(group); + return ClickResult.SUCCESS; + }); + // TODO item show if removable + } + + private MenuWidget menu_item_environment_settings(final RegionGroup group) { + return new MenuItem(4, item_environment_settings.item(), (player, menu, self) -> { + return ClickResult.SUCCESS; + }); + } + + private MenuWidget menu_item_create_role(final RegionGroup group) { + return new MenuItem(7, item_create_role.item(), (player, menu, self) -> { + return ClickResult.SUCCESS; + }); + } + + private MenuWidget menu_item_list_roles(final RegionGroup group) { + return new MenuItem(8, item_list_roles.item(), (player, menu, self) -> { + menu.close(player); + final var all_roles = group.roles() + .stream() + .sorted((a, b) -> a.name().compareToIgnoreCase(b.name())) + .collect(Collectors.toList()); + + final var filter = new Filter.StringFilter((r, str) -> r.name().toLowerCase().contains(str)); + MenuFactory.generic_selector(get_context(), player, lang_select_role_title.str(), lang_filter_roles_title.str(), all_roles, + r -> item_select_role.item("§a§l" + r.name()), + filter, + (player2, m, role) -> { + m.close(player2); + // TODO get_module().menus.role_menu.create(player2, role).open(player2); + return ClickResult.SUCCESS; + }, player2 -> { + menu.open(player2); + }).open(player); + return ClickResult.SUCCESS; + }); + } + + @Override public void on_enable() {} + @Override public void on_disable() {} +} diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RegionMenu.java b/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RegionMenu.java new file mode 100644 index 000000000..057bc1ff1 --- /dev/null +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RegionMenu.java @@ -0,0 +1,136 @@ +package org.oddlama.vane.regions.menu; + +import static org.oddlama.vane.util.Util.namespaced_key; + +import java.util.Objects; +import java.util.stream.Collectors; + +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +import org.oddlama.vane.annotation.lang.LangMessage; +import org.oddlama.vane.core.config.TranslatedItemStack; +import org.oddlama.vane.core.lang.TranslatedMessage; +import org.oddlama.vane.core.menu.Filter; +import org.oddlama.vane.core.menu.Menu.ClickResult; +import org.oddlama.vane.core.menu.Menu; +import org.oddlama.vane.core.menu.MenuFactory; +import org.oddlama.vane.core.menu.MenuItem; +import org.oddlama.vane.core.menu.MenuWidget; +import org.oddlama.vane.core.module.Context; +import org.oddlama.vane.core.module.ModuleComponent; +import org.oddlama.vane.regions.Regions; +import org.oddlama.vane.regions.region.Region; +import org.oddlama.vane.regions.region.RegionGroup; +import org.oddlama.vane.regions.region.RegionSelection; +import org.oddlama.vane.regions.region.RoleSetting; + +public class RegionMenu extends ModuleComponent { + @LangMessage public TranslatedMessage lang_title; + @LangMessage public TranslatedMessage lang_select_region_group_title; + @LangMessage public TranslatedMessage lang_filter_region_groups_title; + + public TranslatedItemStack item_rename; + public TranslatedItemStack item_delete; + public TranslatedItemStack item_assign_region_group; + public TranslatedItemStack item_select_region_group; + + public RegionMenu(Context context) { + super(context.namespace("region")); + + final var ctx = get_context(); + item_rename = new TranslatedItemStack<>(ctx, "rename", Material.NAME_TAG, 1, "Used to rename the region."); + item_delete = new TranslatedItemStack<>(ctx, "delete", namespaced_key("vane", "decoration_tnt_1"), 1, "Used to delete this region."); + item_assign_region_group = new TranslatedItemStack<>(ctx, "assign_region_group", Material.GLOBE_BANNER_PATTERN, 1, "Used to assign a region group."); + item_select_region_group = new TranslatedItemStack<>(ctx, "select_region_group", Material.GLOBE_BANNER_PATTERN, 1, "Used to represent a region group in the region group assignment list."); + } + + public Menu create(final Region region, final Player player) { + final var columns = 9; + final var title = lang_title.str(); + final var region_menu = new Menu(get_context(), Bukkit.createInventory(null, columns, title)); + region_menu.tag(new RegionMenuTag(region.id())); + + final var is_owner = player.getUniqueId().equals(region.owner()); + if (is_owner) { + region_menu.add(menu_item_rename(region)); + region_menu.add(menu_item_delete(region)); + region_menu.add(menu_item_assign_region_group(region)); + } + + return region_menu; + } + + private MenuWidget menu_item_rename(final Region region) { + return new MenuItem(0, item_rename.item(), (player, menu, self) -> { + menu.close(player); + if (!player.getUniqueId().equals(region.owner())) { + return ClickResult.ERROR; + } + + get_module().menus.enter_region_name_menu.create(player, region.name(), (player2, name) -> { + region.name(name); + mark_persistent_storage_dirty(); + + // Open new menu because of possibly changed title + get_module().menus.region_menu.create(region, player2).open(player2); + return ClickResult.SUCCESS; + }).on_natural_close(player2 -> { + // Open new menu because of possibly changed title + get_module().menus.region_menu.create(region, player2).open(player2); + }).open(player); + + return ClickResult.SUCCESS; + }); + } + + private MenuWidget menu_item_delete(final Region region) { + return new MenuItem(1, item_delete.item(), (player, menu, self) -> { + if (!player.getUniqueId().equals(region.owner())) { + return ClickResult.ERROR; + } + + get_module().remove_region(region); + return ClickResult.SUCCESS; + }); + // TODO item show if removable + } + + private MenuWidget menu_item_assign_region_group(final Region region) { + return new MenuItem(2, item_assign_region_group.item(), (player, menu, self) -> { + menu.close(player); + final var all_region_groups = get_module().all_region_groups() + .stream() + .filter(g -> player.getUniqueId().equals(g.owner()) + || g.get_role(player.getUniqueId()) + .get_setting(RoleSetting.ADMIN)) + .sorted((a, b) -> a.name().compareToIgnoreCase(b.name())) + .collect(Collectors.toList()); + + final var filter = new Filter.StringFilter((r, str) -> r.name().toLowerCase().contains(str)); + MenuFactory.generic_selector(get_context(), player, lang_select_region_group_title.str(), lang_filter_region_groups_title.str(), all_region_groups, + r -> item_select_region_group.item("§a§l" + r.name()), + filter, + (player2, m, group) -> { + if (!player2.getUniqueId().equals(region.owner())) { + return ClickResult.ERROR; + } + + m.close(player2); + region.region_group_id(group.id()); + mark_persistent_storage_dirty(); + menu.open(player2); + return ClickResult.SUCCESS; + }, player2 -> { + menu.open(player2); + }).open(player); + return ClickResult.SUCCESS; + }); + } + + @Override public void on_enable() {} + @Override public void on_disable() {} +} diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RegionMenuGroup.java b/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RegionMenuGroup.java index 5d93e7ee9..2b4bdb9f6 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RegionMenuGroup.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RegionMenuGroup.java @@ -9,6 +9,9 @@ public class RegionMenuGroup extends ModuleComponent { public EnterRegionGroupNameMenu enter_region_group_name_menu; public EnterRoleNameMenu enter_role_name_menu; public MainMenu main_menu; + public RegionGroupMenu region_group_menu; + public RegionMenu region_menu; + public RoleMenu role_menu; public RegionMenuGroup(Context context) { super(context.namespace("menus")); @@ -17,6 +20,9 @@ public RegionMenuGroup(Context context) { enter_region_group_name_menu = new EnterRegionGroupNameMenu(get_context()); enter_role_name_menu = new EnterRoleNameMenu(get_context()); main_menu = new MainMenu(get_context()); + region_group_menu = new RegionGroupMenu(get_context()); + region_menu = new RegionMenu(get_context()); + role_menu = new RoleMenu(get_context()); } @Override public void on_enable() {} diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RoleMenu.java b/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RoleMenu.java new file mode 100644 index 000000000..97f36f373 --- /dev/null +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RoleMenu.java @@ -0,0 +1,172 @@ +package org.oddlama.vane.regions.menu; + +import static org.oddlama.vane.util.Util.namespaced_key; + +import java.util.Objects; +import java.util.Arrays; +import java.util.stream.Collectors; + +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +import org.oddlama.vane.annotation.lang.LangMessage; +import org.oddlama.vane.core.config.TranslatedItemStack; +import org.oddlama.vane.core.lang.TranslatedMessage; +import org.oddlama.vane.core.menu.Filter; +import org.oddlama.vane.core.menu.Menu.ClickResult; +import org.oddlama.vane.core.menu.Menu; +import org.oddlama.vane.core.menu.MenuFactory; +import org.oddlama.vane.core.menu.MenuItem; +import org.oddlama.vane.core.menu.MenuWidget; +import org.oddlama.vane.core.module.Context; +import org.oddlama.vane.core.module.ModuleComponent; +import org.oddlama.vane.regions.Regions; +import org.oddlama.vane.regions.region.Region; +import org.oddlama.vane.regions.region.RegionGroup; +import org.oddlama.vane.regions.region.RegionSelection; +import org.oddlama.vane.regions.region.Role; +import org.oddlama.vane.regions.region.RoleSetting; +import org.oddlama.vane.util.ItemUtil; + +public class RoleMenu extends ModuleComponent { + @LangMessage public TranslatedMessage lang_title; + @LangMessage public TranslatedMessage lang_select_assign_player_title; + @LangMessage public TranslatedMessage lang_select_remove_player_title; + @LangMessage public TranslatedMessage lang_filter_players_title; + + public TranslatedItemStack item_rename; + public TranslatedItemStack item_delete; + public TranslatedItemStack item_role_settings; + public TranslatedItemStack item_assign_player; + public TranslatedItemStack item_remove_player; + public TranslatedItemStack item_select_player; + + public RoleMenu(Context context) { + super(context.namespace("role")); + + final var ctx = get_context(); + item_rename = new TranslatedItemStack<>(ctx, "rename", Material.NAME_TAG, 1, "Used to rename the role."); + item_delete = new TranslatedItemStack<>(ctx, "delete", namespaced_key("vane", "decoration_tnt_1"), 1, "Used to delete this role."); + // TODO icon... + item_role_settings = new TranslatedItemStack<>(ctx, "role_settings", Material.FLOWER_POT, 1, "Used to open the role settings."); + item_assign_player = new TranslatedItemStack<>(ctx, "assign_player", Material.PLAYER_HEAD, 1, "Used to assign players to this role."); + item_remove_player = new TranslatedItemStack<>(ctx, "remove_player", Material.PLAYER_HEAD, 1, "Used to remove players from this role."); + item_select_player = new TranslatedItemStack<>(ctx, "select_player", Material.PLAYER_HEAD, 1, "Used to represent a player in the role assignment/removal list."); + } + + public Menu create(final RegionGroup group, final Role role, final Player player) { + final var columns = 9; + final var title = lang_title.str(); + final var role_menu = new Menu(get_context(), Bukkit.createInventory(null, columns, title)); + + final var is_admin = player.getUniqueId().equals(group.owner()) + || group.get_role(player.getUniqueId()) + .get_setting(RoleSetting.ADMIN); + + if (is_admin && role.role_type() == Role.RoleType.NORMAL) { + role_menu.add(menu_item_rename(group, role)); + role_menu.add(menu_item_delete(group, role)); + } + + role_menu.add(menu_item_role_settings(role)); + if (role.role_type() != Role.RoleType.OTHERS) { + role_menu.add(menu_item_assign_player(group, role)); + role_menu.add(menu_item_remove_player(group, role)); + } + + return role_menu; + } + + private MenuWidget menu_item_rename(final RegionGroup group, final Role role) { + return new MenuItem(0, item_rename.item(), (player, menu, self) -> { + menu.close(player); + + get_module().menus.enter_role_name_menu.create(player, role.name(), (player2, name) -> { + role.name(name); + mark_persistent_storage_dirty(); + + // Open new menu because of possibly changed title + get_module().menus.role_menu.create(group, role, player2).open(player2); + return ClickResult.SUCCESS; + }).on_natural_close(player2 -> { + // Open new menu because of possibly changed title + get_module().menus.role_menu.create(group, role, player2).open(player2); + }).open(player); + + return ClickResult.SUCCESS; + }); + } + + private MenuWidget menu_item_delete(final RegionGroup group, final Role role) { + return new MenuItem(1, item_delete.item(), (player, menu, self) -> { + group.remove_role(role.id()); + mark_persistent_storage_dirty(); + return ClickResult.SUCCESS; + }); + } + + private MenuWidget menu_item_role_settings(final Role role) { + return new MenuItem(4, item_role_settings.item(), (player, menu, self) -> { + return ClickResult.SUCCESS; + }); + } + + private MenuWidget menu_item_assign_player(final RegionGroup group, final Role role) { + return new MenuItem(7, item_assign_player.item(), (player, menu, self) -> { + menu.close(player); + final var all_players = Arrays.stream(get_module().getServer().getOfflinePlayers()) + .sorted((a, b) -> { + int c = Boolean.compare(b.isOnline(), a.isOnline()); + if (c != 0) { return c; } + return a.getName().compareToIgnoreCase(b.getName()); + }) + .collect(Collectors.toList()); + + final var filter = new Filter.StringFilter((p, str) -> p.getName().toLowerCase().contains(str)); + MenuFactory.generic_selector(get_context(), player, lang_select_assign_player_title.str(), lang_filter_players_title.str(), all_players, + p -> item_select_player.alternative(ItemUtil.skull_for_player(p), "§a§l" + p.getName()), + filter, + (player2, m, p) -> { + m.close(player2); + // TODO assing + return ClickResult.SUCCESS; + }, player2 -> { + menu.open(player2); + }).open(player); + return ClickResult.SUCCESS; + }); + } + + private MenuWidget menu_item_remove_player(final RegionGroup group, final Role role) { + return new MenuItem(8, item_remove_player.item(), (player, menu, self) -> { + menu.close(player); + final var all_players = Arrays.stream(get_module().getServer().getOfflinePlayers()) + .sorted((a, b) -> { + int c = Boolean.compare(b.isOnline(), a.isOnline()); + if (c != 0) { return c; } + return a.getName().compareToIgnoreCase(b.getName()); + }) + .collect(Collectors.toList()); + + final var filter = new Filter.StringFilter((p, str) -> p.getName().toLowerCase().contains(str)); + MenuFactory.generic_selector(get_context(), player, lang_select_remove_player_title.str(), lang_filter_players_title.str(), all_players, + p -> item_select_player.alternative(ItemUtil.skull_for_player(p), "§a§l" + p.getName()), + filter, + (player2, m, p) -> { + m.close(player2); + // TODO remove + return ClickResult.SUCCESS; + }, player2 -> { + menu.open(player2); + }).open(player); + return ClickResult.SUCCESS; + }); + } + + @Override public void on_enable() {} + @Override public void on_disable() {} +} diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/region/Region.java b/vane-regions/src/main/java/org/oddlama/vane/regions/region/Region.java index a61b28cc0..098e8209d 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/region/Region.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/region/Region.java @@ -87,6 +87,15 @@ public static Region deserialize(@NotNull final Object o) throws IOException { return region; } + private Region() {} + public Region(final String name, final UUID owner, final RegionExtent extent, final UUID region_group) { + this.id = UUID.randomUUID(); + this.name = name; + this.owner = owner; + this.extent = extent; + this.region_group = region_group; + } + private UUID id; private String name; private UUID owner; @@ -95,11 +104,13 @@ public static Region deserialize(@NotNull final Object o) throws IOException { public UUID id() { return id; } public String name() { return name; } + public void name(final String name) { this.name = name; } public UUID owner() { return owner; } public RegionExtent extent() { return extent; } - private RegionGroup cached_region_group; + private RegionGroup cached_region_group = null; public UUID region_group_id() { return region_group; } + public void region_group_id(final UUID region_group) { this.region_group = region_group; } public RegionGroup region_group(final Regions regions) { if (cached_region_group == null) { cached_region_group = regions.get_region_group(region_group); diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/region/RegionGroup.java b/vane-regions/src/main/java/org/oddlama/vane/regions/region/RegionGroup.java index 5b63f12af..6fe7e15bf 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/region/RegionGroup.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/region/RegionGroup.java @@ -140,6 +140,7 @@ public RegionGroup(final String name, final UUID owner) { public UUID id() { return id; } public String name() { return name; } + public void name(final String name) { this.name = name; } public UUID owner() { return owner; } public boolean get_setting(final EnvironmentSetting setting) { return settings.getOrDefault(setting, setting.default_value()); @@ -152,4 +153,18 @@ public void add_role(final Role role) { public Role get_role(final UUID player) { return roles.get(player_to_role.getOrDefault(player, role_others)); } + + public void remove_role(final UUID role_id) { + player_to_role.values().removeIf(r -> role_id.equals(r)); + roles.remove(role_id); + } + + public Collection roles() { + return roles.values(); + } + + public boolean is_orphan(final Regions region) { + // TODO + return false; + } } diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/region/RegionSelection.java b/vane-regions/src/main/java/org/oddlama/vane/regions/region/RegionSelection.java index 6dd59a0ee..439ea1ae8 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/region/RegionSelection.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/region/RegionSelection.java @@ -37,6 +37,7 @@ import org.bukkit.SoundCategory; import org.bukkit.block.Block; import org.bukkit.Location; +import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.world.ChunkLoadEvent; @@ -74,7 +75,7 @@ public RegionSelection(final Regions regions) { } public boolean intersects_existing() { - final var extent = new RegionExtent(primary, secondary); + final var extent = extent(); for (final var r : regions.all_regions()) { if (!r.extent().min().getWorld().equals(primary.getWorld())) { continue; @@ -88,7 +89,12 @@ public boolean intersects_existing() { return false; } - public boolean is_valid() { + public boolean can_afford(final Player player) { + // TODO + return true; + } + + public boolean is_valid(final Player player) { // Both blocks set if (primary == null || secondary == null) { return false; @@ -118,14 +124,15 @@ public boolean is_valid() { return false; } + // Check that the player can afford it + if (!can_afford(player)) { + return false; + } + return true; } - public RegionExtent to_extent() { - if (!is_valid()) { - return null; - } - + public RegionExtent extent() { return new RegionExtent(primary, secondary); } } diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/region/Role.java b/vane-regions/src/main/java/org/oddlama/vane/regions/region/Role.java index bf81db87d..79045199b 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/region/Role.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/region/Role.java @@ -113,6 +113,7 @@ public Role(final String name, final RoleType role_type) { public UUID id() { return id; } public String name() { return name; } + public void name(final String name) { this.name = name; } public RoleType role_type() { return role_type; } public boolean get_setting(final RoleSetting setting) { return settings.getOrDefault(setting, setting.default_value(false)); diff --git a/vane-regions/src/main/resources/lang-de.yml b/vane-regions/src/main/resources/lang-de.yml index a9855eb67..b6df21260 100644 --- a/vane-regions/src/main/resources/lang-de.yml +++ b/vane-regions/src/main/resources/lang-de.yml @@ -17,3 +17,105 @@ version: 2 # resource pack generation. Typically this is a combination of the # language code (ISO 639) and the country code (ISO 3166). resource_pack_lang_code: 'de_de' + +start_region_selection: "§aChoose an area by selecting two blocks via §bleft-§a and §bright-click§a with an empty hand." +select_primary_block: "§aSelected (%1$s§a, %2$s§a, %3$s§a) as primary block." +select_secondary_block: "§aSelected (%1$s§a, %2$s§a, %3$s§a) as secondary block." + +command_region: + usage: "%1$s" + description: "Open the region management menu." + help: "Execute to open the region management menu." + +dynmap: + layer_label: "Regions" + marker_label: "%1$s" + +menus: + enter_region_group_name: + title: "§8§lEnter Region Group Name" + + enter_region_name: + title: "§8§lEnter Region Name" + + enter_role_name: + title: "§8§lEnter Role Name" + + main: + title: "§8§lManage Regions" + + create_region_start_selection: + name: "§a§lCreate Region" + lore: + - "" + - "§7Starts a new region selection. With an empty hand," + - "§6left-click§7 to select the first block and" + - "§6right-click§7 to select the second block. The" + - "§7volume between the blocks will become the region." + + create_region_invalid_selection: + name: "§c§lInvalid Selection" + lore: + - "" + - "§6Your selection (%6$s§6 x %7$s§6 x %8$s§6) is invalid!" + - "§6It must meet the following requirements:" + - "§7- %1$s§7 Primary block set" + - "§7- %2$s§7 Secondary block set" + - "§7- %3$s§7 Doesn't intersect existing region" + - "§7- %4$s§7 Covers minimum area (%9$s§7 x %10$s§7 x %11$s§7)" + - "§7- %5$s§7 Not bigger than (%12$s§7 x %13$s§7 x %14$s§7)" + + create_region_valid_selection: + name: "§a§lCreate Region" + lore: + - "" + - "§7Your selection (%1$s§7 x %2$s§7 x %3$s§7) is valid." + - "§7Create a new region by clinking this item." + + cancel_selection: + name: "§c§lCancel Selection" + lore: [] + + list_regions: + name: "§b§lSelect Region" + lore: [] + + select_region_title: "§8§lSelect Region" + filter_regions_title: "§8§lFilter Regions" + select_region: + name: "%1$s" + lore: [] + + current_region: + name: "§b§lCurrent Region" + lore: + - "" + - "§7Region: %1$s" + - "" + - "§7Select the region you are standing in." + + create_region_group: + name: "§a§lCreate Region Group" + lore: + - "" + - "§7Create a new §bregion group§7. Region groups" + - "§7are used to set permissions for players" + - "§7by assigning them roles. All regions in" + - "§7a region group will share these permissions" + + list_region_groups: + name: "§b§lSelect region group" + lore: [] + + current_region_group: + name: "§b§lCurrent Region Group" + lore: + - "" + - "§7Region Group: %1$s" + - "" + - "§7Select the region group of the" + - "§7region you are standing in." + + select_region_group: + name: "%1$s" + lore: [] diff --git a/vane-regions/src/main/resources/lang-en.yml b/vane-regions/src/main/resources/lang-en.yml index acee9e490..e4b5d43bf 100644 --- a/vane-regions/src/main/resources/lang-en.yml +++ b/vane-regions/src/main/resources/lang-en.yml @@ -80,40 +80,58 @@ menus: # This item is shown when the selection is invalid # %1$s: Checkmark: primary block set # %2$s: Checkmark: secondary block set - # %3$s: Checkmark: doesn't interact existing region - # %4$s: Checkmark: minimum area condition met - # %5$s: Checkmark: not bigger than max - # %6$s: Selection extent X - # %7$s: Selection extent Y - # %8$s: Selection extent Z - # %9$s: min extent X - # %10$s: min extent Y - # %11$s: min extent Z - # %12$s: max extent X - # %13$s: max extent Y - # %14$s: max extent Z + # %3$s: Checkmark: same world + # %4$s: Checkmark: doesn't interact existing region + # %5$s: Checkmark: minimum area condition met + # %6$s: Checkmark: not bigger than max + # %7$s: Checkmark: can afford + # %8$s: Selection extent X + # %9$s: Selection extent Y + # %10$s: Selection extent Z + # %11$s: min extent X + # %12$s: min extent Y + # %13$s: min extent Z + # %14$s: max extent X + # %15$s: max extent Y + # %16$s: max extent Z create_region_invalid_selection: name: "§c§lInvalid Selection" lore: - "" - - "§6Your selection (%6$s§6 x %7$s§6 x %8$s§6) is invalid!" + - "§6Your selection (%8$s§6 x %9$s§6 x %10$s§6) is invalid!" - "§6It must meet the following requirements:" - "§7- %1$s§7 Primary block set" - "§7- %2$s§7 Secondary block set" - - "§7- %3$s§7 Doesn't intersect existing region" - - "§7- %4$s§7 Covers minimum area (%9$s§7 x %10$s§7 x %11$s§7)" - - "§7- %5$s§7 Not bigger than (%12$s§7 x %13$s§7 x %14$s§7)" + - "§7- %3$s§7 Blocks are in same world" + - "§7- %4$s§7 Doesn't intersect existing region" + - "§7- %5$s§7 Covers minimum area (%11$s§7 x %12$s§7 x %13$s§7)" + - "§7- %6$s§7 Not bigger than (%14$s§7 x %15$s§7 x %16$s§7)" + - "§7- %7$s§7 Can afford" # This item is shown when the selection is valid # %1$s: Selection extent X # %2$s: Selection extent Y # %3$s: Selection extent Z + # %4$s: min extent X + # %5$s: min extent Y + # %6$s: min extent Z + # %7$s: max extent X + # %8$s: max extent Y + # %9$s: max extent Z create_region_valid_selection: name: "§a§lCreate Region" lore: - "" - "§7Your selection (%1$s§7 x %2$s§7 x %3$s§7) is valid." - - "§7Create a new region by clinking this item." + - "§7Click here to create a new region." + - "" + - "§7- §a✓ Primary block set" + - "§7- §a✓ Secondary block set" + - "§7- §a✓ Blocks are in same world" + - "§7- §a✓ Doesn't intersect existing region" + - "§7- §a✓ Covers minimum area (%4$s§7 x %5$s§7 x %6$s§7)" + - "§7- §a✓ Not bigger than (%7$s§7 x %8$s§7 x %9$s§7)" + - "§7- §a✓ Can afford" # This item is used to cancel a pending selection. cancel_selection: From 0480655f736457403ef8d224965944943857aad5 Mon Sep 17 00:00:00 2001 From: oddlama Date: Mon, 15 Mar 2021 17:00:38 +0100 Subject: [PATCH 12/40] English localization for RegionMenu --- vane-portals/src/main/resources/lang-en.yml | 5 ++- .../oddlama/vane/regions/menu/RegionMenu.java | 32 ++++++++++----- vane-regions/src/main/resources/lang-en.yml | 39 +++++++++++++++++++ 3 files changed, 65 insertions(+), 11 deletions(-) diff --git a/vane-portals/src/main/resources/lang-en.yml b/vane-portals/src/main/resources/lang-en.yml index aff6c3003..4b879cb0f 100644 --- a/vane-portals/src/main/resources/lang-en.yml +++ b/vane-portals/src/main/resources/lang-en.yml @@ -332,9 +332,12 @@ menus: - "§7Current: %1$s" - "§8Target selection is currently §6§lLOCKED§r§8!" - # The item used to open the portal's target selector. select_target_title: "§8§lSelect Target Portal" filter_portals_title: "§8§lFilter Portals" + # The item used to represent a target portal. + # %1$s: Portal name + # %2$s: Portal distance + # %3$s: Portal world select_target_portal: name: "%1$s" lore: diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RegionMenu.java b/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RegionMenu.java index 057bc1ff1..4352d3e99 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RegionMenu.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RegionMenu.java @@ -30,11 +30,14 @@ public class RegionMenu extends ModuleComponent { @LangMessage public TranslatedMessage lang_title; + @LangMessage public TranslatedMessage lang_delete_confirm_title; @LangMessage public TranslatedMessage lang_select_region_group_title; @LangMessage public TranslatedMessage lang_filter_region_groups_title; public TranslatedItemStack item_rename; public TranslatedItemStack item_delete; + public TranslatedItemStack item_delete_confirm_accept; + public TranslatedItemStack item_delete_confirm_cancel; public TranslatedItemStack item_assign_region_group; public TranslatedItemStack item_select_region_group; @@ -42,15 +45,17 @@ public RegionMenu(Context context) { super(context.namespace("region")); final var ctx = get_context(); - item_rename = new TranslatedItemStack<>(ctx, "rename", Material.NAME_TAG, 1, "Used to rename the region."); - item_delete = new TranslatedItemStack<>(ctx, "delete", namespaced_key("vane", "decoration_tnt_1"), 1, "Used to delete this region."); - item_assign_region_group = new TranslatedItemStack<>(ctx, "assign_region_group", Material.GLOBE_BANNER_PATTERN, 1, "Used to assign a region group."); - item_select_region_group = new TranslatedItemStack<>(ctx, "select_region_group", Material.GLOBE_BANNER_PATTERN, 1, "Used to represent a region group in the region group assignment list."); + item_rename = new TranslatedItemStack<>(ctx, "rename", Material.NAME_TAG, 1, "Used to rename the region."); + item_delete = new TranslatedItemStack<>(ctx, "delete", namespaced_key("vane", "decoration_tnt_1"), 1, "Used to delete this region."); + item_delete_confirm_accept = new TranslatedItemStack<>(ctx, "delete_confirm_accept", namespaced_key("vane", "decoration_tnt_1"), 1, "Used to confirm deleting the region."); + item_delete_confirm_cancel = new TranslatedItemStack<>(ctx, "delete_confirm_cancel", Material.PRISMARINE_SHARD, 1, "Used to cancel deleting the region."); + item_assign_region_group = new TranslatedItemStack<>(ctx, "assign_region_group", Material.GLOBE_BANNER_PATTERN, 1, "Used to assign a region group."); + item_select_region_group = new TranslatedItemStack<>(ctx, "select_region_group", Material.GLOBE_BANNER_PATTERN, 1, "Used to represent a region group in the region group assignment list."); } public Menu create(final Region region, final Player player) { final var columns = 9; - final var title = lang_title.str(); + final var title = lang_title.str("§5§l" + region.name()); final var region_menu = new Menu(get_context(), Bukkit.createInventory(null, columns, title)); region_menu.tag(new RegionMenuTag(region.id())); @@ -89,14 +94,21 @@ private MenuWidget menu_item_rename(final Region region) { private MenuWidget menu_item_delete(final Region region) { return new MenuItem(1, item_delete.item(), (player, menu, self) -> { - if (!player.getUniqueId().equals(region.owner())) { - return ClickResult.ERROR; - } + MenuFactory.confirm(get_context(), lang_delete_confirm_title.str(), + item_delete_confirm_accept.item(), (player2) -> { + if (!player2.getUniqueId().equals(region.owner())) { + return ClickResult.ERROR; + } - get_module().remove_region(region); + get_module().remove_region(region); + return ClickResult.SUCCESS; + }, item_delete_confirm_cancel.item(), (player2) -> { + menu.open(player2); + }) + .tag(new RegionMenuTag(region.id())) + .open(player); return ClickResult.SUCCESS; }); - // TODO item show if removable } private MenuWidget menu_item_assign_region_group(final Region region) { diff --git a/vane-regions/src/main/resources/lang-en.yml b/vane-regions/src/main/resources/lang-en.yml index e4b5d43bf..d4b911d30 100644 --- a/vane-regions/src/main/resources/lang-en.yml +++ b/vane-regions/src/main/resources/lang-en.yml @@ -194,3 +194,42 @@ menus: select_region_group: name: "%1$s" lore: [] + + # Settings for the region menu. + region: + # The title for the region menu. + # %1$s: Region name + title: "§8§lRegion: %1$s" + + # The item used to rename a region. + rename: + name: "§b§lRename Region" + lore: [] + + # The item used to delete a region. + rename: + name: "§c§lDelete Region" + lore: [] + # The title for the delete confirmation dialog. + delete_confirm_title: "§c§lDelete region?" + # The item to accept deleting. + delete_confirm_accept: + name: "§c§lDELETE REGION" + lore: [] + # The item to cance deleting. + delete_confirm_cancel: + name: "§a§lCancel" + lore: [] + + # The item used to open the list of region groups to assign the region to one + assign_region_group: + name: "§b§lAssign Group" + lore: [] + + select_region_group_title: "§8§lSelect Region Group" + filter_region_groups_title: "§8§lFilter Region Groups" + # The item used to represent a region group. + # %1$s: Region group name + select_region_group: + name: "%1$s" + lore: [] From 1b5cdf7e1cc2cf3c2c1e9cb55fa39fc7744dd01a Mon Sep 17 00:00:00 2001 From: oddlama Date: Mon, 15 Mar 2021 17:10:43 +0100 Subject: [PATCH 13/40] Added english lang for RegionGroupMenu --- .../vane/regions/menu/RegionGroupMenu.java | 37 ++++++++---- .../oddlama/vane/regions/menu/RegionMenu.java | 1 + vane-regions/src/main/resources/lang-en.yml | 58 ++++++++++++++++++- 3 files changed, 83 insertions(+), 13 deletions(-) diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RegionGroupMenu.java b/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RegionGroupMenu.java index abded9cdc..2f3847182 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RegionGroupMenu.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RegionGroupMenu.java @@ -31,11 +31,14 @@ public class RegionGroupMenu extends ModuleComponent { @LangMessage public TranslatedMessage lang_title; + @LangMessage public TranslatedMessage lang_delete_confirm_title; @LangMessage public TranslatedMessage lang_select_role_title; @LangMessage public TranslatedMessage lang_filter_roles_title; public TranslatedItemStack item_rename; public TranslatedItemStack item_delete; + public TranslatedItemStack item_delete_confirm_accept; + public TranslatedItemStack item_delete_confirm_cancel; public TranslatedItemStack item_environment_settings; public TranslatedItemStack item_create_role; public TranslatedItemStack item_list_roles; @@ -45,13 +48,15 @@ public RegionGroupMenu(Context context) { super(context.namespace("region_group")); final var ctx = get_context(); - item_rename = new TranslatedItemStack<>(ctx, "rename", Material.NAME_TAG, 1, "Used to rename the region group."); - item_delete = new TranslatedItemStack<>(ctx, "delete", namespaced_key("vane", "decoration_tnt_1"), 1, "Used to delete this region group."); + item_rename = new TranslatedItemStack<>(ctx, "rename", Material.NAME_TAG, 1, "Used to rename the region group."); + item_delete = new TranslatedItemStack<>(ctx, "delete", namespaced_key("vane", "decoration_tnt_1"), 1, "Used to delete this region group."); + item_delete_confirm_accept = new TranslatedItemStack<>(ctx, "delete_confirm_accept", namespaced_key("vane", "decoration_tnt_1"), 1, "Used to confirm deleting the region group."); + item_delete_confirm_cancel = new TranslatedItemStack<>(ctx, "delete_confirm_cancel", Material.PRISMARINE_SHARD, 1, "Used to cancel deleting the region group."); // TODO icon... - item_environment_settings = new TranslatedItemStack<>(ctx, "environment_settings", Material.FLOWER_POT, 1, "Used to open the environment settings."); - item_create_role = new TranslatedItemStack<>(ctx, "create_role", Material.WRITABLE_BOOK, 1, "Used to create a new role."); - item_list_roles = new TranslatedItemStack<>(ctx, "list_roles", Material.GLOBE_BANNER_PATTERN, 1, "Used to list all defined roles."); - item_select_role = new TranslatedItemStack<>(ctx, "select_role", Material.GLOBE_BANNER_PATTERN, 1, "Used to represent a role in the role selection list."); + item_environment_settings = new TranslatedItemStack<>(ctx, "environment_settings", Material.FLOWER_POT, 1, "Used to open the environment settings."); + item_create_role = new TranslatedItemStack<>(ctx, "create_role", Material.WRITABLE_BOOK, 1, "Used to create a new role."); + item_list_roles = new TranslatedItemStack<>(ctx, "list_roles", Material.GLOBE_BANNER_PATTERN, 1, "Used to list all defined roles."); + item_select_role = new TranslatedItemStack<>(ctx, "select_role", Material.GLOBE_BANNER_PATTERN, 1, "Used to represent a role in the role selection list."); } public Menu create(final RegionGroup group, final Player player) { @@ -96,18 +101,26 @@ private MenuWidget menu_item_rename(final RegionGroup group) { private MenuWidget menu_item_delete(final RegionGroup group) { final var orphan_checkbox = group.is_orphan(get_module()) ? "§a✓" : "§c✕"; return new MenuItem(1, item_delete.item(orphan_checkbox), (player, menu, self) -> { - if (!player.getUniqueId().equals(group.owner())) { - return ClickResult.ERROR; - } - if (!group.is_orphan(get_module())) { return ClickResult.ERROR; } - get_module().remove_region_group(group); + menu.close(player); + MenuFactory.confirm(get_context(), lang_delete_confirm_title.str(), + item_delete_confirm_accept.item(), (player2) -> { + if (!player2.getUniqueId().equals(group.owner())) { + return ClickResult.ERROR; + } + + get_module().remove_region_group(group); + return ClickResult.SUCCESS; + }, item_delete_confirm_cancel.item(), (player2) -> { + menu.open(player2); + }) + .tag(new RegionMenuTag(region.id())) + .open(player); return ClickResult.SUCCESS; }); - // TODO item show if removable } private MenuWidget menu_item_environment_settings(final RegionGroup group) { diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RegionMenu.java b/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RegionMenu.java index 4352d3e99..b9f2c5abc 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RegionMenu.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RegionMenu.java @@ -94,6 +94,7 @@ private MenuWidget menu_item_rename(final Region region) { private MenuWidget menu_item_delete(final Region region) { return new MenuItem(1, item_delete.item(), (player, menu, self) -> { + menu.close(player); MenuFactory.confirm(get_context(), lang_delete_confirm_title.str(), item_delete_confirm_accept.item(), (player2) -> { if (!player2.getUniqueId().equals(region.owner())) { diff --git a/vane-regions/src/main/resources/lang-en.yml b/vane-regions/src/main/resources/lang-en.yml index d4b911d30..43221215e 100644 --- a/vane-regions/src/main/resources/lang-en.yml +++ b/vane-regions/src/main/resources/lang-en.yml @@ -207,7 +207,7 @@ menus: lore: [] # The item used to delete a region. - rename: + delete: name: "§c§lDelete Region" lore: [] # The title for the delete confirmation dialog. @@ -233,3 +233,59 @@ menus: select_region_group: name: "%1$s" lore: [] + + # Settings for the region group menu. + region_group: + # The title for the region group menu. + # %1$s: Region name + title: "§8§lGroup: %1$s" + + # The item used to rename a region group. + rename: + name: "§b§lRename Region" + lore: [] + + # The item used to delete a region group. + # %1$s: Checkmark: No region uses this group + delete: + name: "§c§lDelete Region Group" + lore: + - "" + - "§6Deletion requirements:" + - "§7- %1$s §7No region uses this group" + # The title for the delete confirmation dialog. + delete_confirm_title: "§c§lDelete region group?" + # The item to accept deleting. + delete_confirm_accept: + name: "§c§lDELETE REGION GROUP" + lore: [] + # The item to cance deleting. + delete_confirm_cancel: + name: "§a§lCancel" + lore: [] + + # The item used to open the environment settings menu. + environment_settings: + name: "§b§lEnvironment Settings" + lore: [] + + # This item is used to create a new role. + create_role: + name: "§a§lCreate Role" + lore: + - "" + - "§7Create a new §brole§7. Roles are" + - "§7to set permissions for groups of players." + + # This item is used to open the role menu for a role. + list_roles: + name: "§b§lRoles" + lore: [] + + select_role_title: "§8§lSelect Role" + filter_roless_title: "§8§lFilter Roles" + # This item is used to represent a role in the selection menu. + # %1$s: Role name + select_role: + name: "%1$s" + lore: [] From 8ea1a03e58e9234defa8c12ac353662994b642a7 Mon Sep 17 00:00:00 2001 From: oddlama Date: Mon, 15 Mar 2021 17:33:54 +0100 Subject: [PATCH 14/40] Added english lang for Role menu --- .../vane/regions/menu/RegionGroupMenu.java | 16 ++--- .../oddlama/vane/regions/menu/RoleMenu.java | 46 +++++++----- .../vane/regions/region/RegionGroup.java | 1 + vane-regions/src/main/resources/lang-en.yml | 70 ++++++++++++++++--- 4 files changed, 91 insertions(+), 42 deletions(-) diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RegionGroupMenu.java b/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RegionGroupMenu.java index 2f3847182..108d9fee7 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RegionGroupMenu.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RegionGroupMenu.java @@ -39,7 +39,6 @@ public class RegionGroupMenu extends ModuleComponent { public TranslatedItemStack item_delete; public TranslatedItemStack item_delete_confirm_accept; public TranslatedItemStack item_delete_confirm_cancel; - public TranslatedItemStack item_environment_settings; public TranslatedItemStack item_create_role; public TranslatedItemStack item_list_roles; public TranslatedItemStack item_select_role; @@ -52,8 +51,6 @@ public RegionGroupMenu(Context context) { item_delete = new TranslatedItemStack<>(ctx, "delete", namespaced_key("vane", "decoration_tnt_1"), 1, "Used to delete this region group."); item_delete_confirm_accept = new TranslatedItemStack<>(ctx, "delete_confirm_accept", namespaced_key("vane", "decoration_tnt_1"), 1, "Used to confirm deleting the region group."); item_delete_confirm_cancel = new TranslatedItemStack<>(ctx, "delete_confirm_cancel", Material.PRISMARINE_SHARD, 1, "Used to cancel deleting the region group."); - // TODO icon... - item_environment_settings = new TranslatedItemStack<>(ctx, "environment_settings", Material.FLOWER_POT, 1, "Used to open the environment settings."); item_create_role = new TranslatedItemStack<>(ctx, "create_role", Material.WRITABLE_BOOK, 1, "Used to create a new role."); item_list_roles = new TranslatedItemStack<>(ctx, "list_roles", Material.GLOBE_BANNER_PATTERN, 1, "Used to list all defined roles."); item_select_role = new TranslatedItemStack<>(ctx, "select_role", Material.GLOBE_BANNER_PATTERN, 1, "Used to represent a role in the role selection list."); @@ -71,9 +68,9 @@ public Menu create(final RegionGroup group, final Player player) { region_group_menu.add(menu_item_delete(group)); } - region_group_menu.add(menu_item_environment_settings(group)); region_group_menu.add(menu_item_create_role(group)); region_group_menu.add(menu_item_list_roles(group)); + // TODO integrate settings directly return region_group_menu; } @@ -117,20 +114,15 @@ private MenuWidget menu_item_delete(final RegionGroup group) { }, item_delete_confirm_cancel.item(), (player2) -> { menu.open(player2); }) - .tag(new RegionMenuTag(region.id())) + .tag(new RegionGroupMenuTag(group.id())) .open(player); return ClickResult.SUCCESS; }); } - private MenuWidget menu_item_environment_settings(final RegionGroup group) { - return new MenuItem(4, item_environment_settings.item(), (player, menu, self) -> { - return ClickResult.SUCCESS; - }); - } - private MenuWidget menu_item_create_role(final RegionGroup group) { return new MenuItem(7, item_create_role.item(), (player, menu, self) -> { + // TODO return ClickResult.SUCCESS; }); } @@ -149,7 +141,7 @@ private MenuWidget menu_item_list_roles(final RegionGroup group) { filter, (player2, m, role) -> { m.close(player2); - // TODO get_module().menus.role_menu.create(player2, role).open(player2); + get_module().menus.role_menu.create(group, role, player2).open(player2); return ClickResult.SUCCESS; }, player2 -> { menu.open(player2); diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RoleMenu.java b/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RoleMenu.java index 97f36f373..2fd4e08eb 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RoleMenu.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RoleMenu.java @@ -34,13 +34,15 @@ public class RoleMenu extends ModuleComponent { @LangMessage public TranslatedMessage lang_title; + @LangMessage public TranslatedMessage lang_delete_confirm_title; @LangMessage public TranslatedMessage lang_select_assign_player_title; @LangMessage public TranslatedMessage lang_select_remove_player_title; @LangMessage public TranslatedMessage lang_filter_players_title; public TranslatedItemStack item_rename; public TranslatedItemStack item_delete; - public TranslatedItemStack item_role_settings; + public TranslatedItemStack item_delete_confirm_accept; + public TranslatedItemStack item_delete_confirm_cancel; public TranslatedItemStack item_assign_player; public TranslatedItemStack item_remove_player; public TranslatedItemStack item_select_player; @@ -49,13 +51,13 @@ public RoleMenu(Context context) { super(context.namespace("role")); final var ctx = get_context(); - item_rename = new TranslatedItemStack<>(ctx, "rename", Material.NAME_TAG, 1, "Used to rename the role."); - item_delete = new TranslatedItemStack<>(ctx, "delete", namespaced_key("vane", "decoration_tnt_1"), 1, "Used to delete this role."); - // TODO icon... - item_role_settings = new TranslatedItemStack<>(ctx, "role_settings", Material.FLOWER_POT, 1, "Used to open the role settings."); - item_assign_player = new TranslatedItemStack<>(ctx, "assign_player", Material.PLAYER_HEAD, 1, "Used to assign players to this role."); - item_remove_player = new TranslatedItemStack<>(ctx, "remove_player", Material.PLAYER_HEAD, 1, "Used to remove players from this role."); - item_select_player = new TranslatedItemStack<>(ctx, "select_player", Material.PLAYER_HEAD, 1, "Used to represent a player in the role assignment/removal list."); + item_rename = new TranslatedItemStack<>(ctx, "rename", Material.NAME_TAG, 1, "Used to rename the role."); + item_delete = new TranslatedItemStack<>(ctx, "delete", namespaced_key("vane", "decoration_tnt_1"), 1, "Used to delete this role."); + item_delete_confirm_accept = new TranslatedItemStack<>(ctx, "delete_confirm_accept", namespaced_key("vane", "decoration_tnt_1"), 1, "Used to confirm deleting the role."); + item_delete_confirm_cancel = new TranslatedItemStack<>(ctx, "delete_confirm_cancel", Material.PRISMARINE_SHARD, 1, "Used to cancel deleting the role."); + item_assign_player = new TranslatedItemStack<>(ctx, "assign_player", Material.PLAYER_HEAD, 1, "Used to assign players to this role."); + item_remove_player = new TranslatedItemStack<>(ctx, "remove_player", Material.PLAYER_HEAD, 1, "Used to remove players from this role."); + item_select_player = new TranslatedItemStack<>(ctx, "select_player", Material.PLAYER_HEAD, 1, "Used to represent a player in the role assignment/removal list."); } public Menu create(final RegionGroup group, final Role role, final Player player) { @@ -72,11 +74,11 @@ public Menu create(final RegionGroup group, final Role role, final Player player role_menu.add(menu_item_delete(group, role)); } - role_menu.add(menu_item_role_settings(role)); if (role.role_type() != Role.RoleType.OTHERS) { role_menu.add(menu_item_assign_player(group, role)); role_menu.add(menu_item_remove_player(group, role)); } + // TODO integrate settings directly return role_menu; } @@ -103,14 +105,16 @@ private MenuWidget menu_item_rename(final RegionGroup group, final Role role) { private MenuWidget menu_item_delete(final RegionGroup group, final Role role) { return new MenuItem(1, item_delete.item(), (player, menu, self) -> { - group.remove_role(role.id()); - mark_persistent_storage_dirty(); - return ClickResult.SUCCESS; - }); - } - - private MenuWidget menu_item_role_settings(final Role role) { - return new MenuItem(4, item_role_settings.item(), (player, menu, self) -> { + menu.close(player); + MenuFactory.confirm(get_context(), lang_delete_confirm_title.str(), + item_delete_confirm_accept.item(), (player2) -> { + group.remove_role(role.id()); + mark_persistent_storage_dirty(); + return ClickResult.SUCCESS; + }, item_delete_confirm_cancel.item(), (player2) -> { + menu.open(player2); + }) + .open(player); return ClickResult.SUCCESS; }); } @@ -119,6 +123,7 @@ private MenuWidget menu_item_assign_player(final RegionGroup group, final Role r return new MenuItem(7, item_assign_player.item(), (player, menu, self) -> { menu.close(player); final var all_players = Arrays.stream(get_module().getServer().getOfflinePlayers()) + .filter(p -> !role.id().equals(group.player_to_role().get(p.getUniqueId()))) .sorted((a, b) -> { int c = Boolean.compare(b.isOnline(), a.isOnline()); if (c != 0) { return c; } @@ -131,7 +136,8 @@ private MenuWidget menu_item_assign_player(final RegionGroup group, final Role r p -> item_select_player.alternative(ItemUtil.skull_for_player(p), "§a§l" + p.getName()), filter, (player2, m, p) -> { - m.close(player2); + all_players.remove(p); + m.update(); // TODO assing return ClickResult.SUCCESS; }, player2 -> { @@ -145,6 +151,7 @@ private MenuWidget menu_item_remove_player(final RegionGroup group, final Role r return new MenuItem(8, item_remove_player.item(), (player, menu, self) -> { menu.close(player); final var all_players = Arrays.stream(get_module().getServer().getOfflinePlayers()) + .filter(p -> role.id().equals(group.player_to_role().get(p.getUniqueId()))) .sorted((a, b) -> { int c = Boolean.compare(b.isOnline(), a.isOnline()); if (c != 0) { return c; } @@ -157,7 +164,8 @@ private MenuWidget menu_item_remove_player(final RegionGroup group, final Role r p -> item_select_player.alternative(ItemUtil.skull_for_player(p), "§a§l" + p.getName()), filter, (player2, m, p) -> { - m.close(player2); + all_players.remove(p); + m.update(); // TODO remove return ClickResult.SUCCESS; }, player2 -> { diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/region/RegionGroup.java b/vane-regions/src/main/java/org/oddlama/vane/regions/region/RegionGroup.java index 6fe7e15bf..0be6d471f 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/region/RegionGroup.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/region/RegionGroup.java @@ -150,6 +150,7 @@ public void add_role(final Role role) { this.roles.put(role.id(), role); } + public Map player_to_role() { return player_to_role; } public Role get_role(final UUID player) { return roles.get(player_to_role.getOrDefault(player, role_others)); } diff --git a/vane-regions/src/main/resources/lang-en.yml b/vane-regions/src/main/resources/lang-en.yml index 43221215e..a8009abdf 100644 --- a/vane-regions/src/main/resources/lang-en.yml +++ b/vane-regions/src/main/resources/lang-en.yml @@ -216,7 +216,7 @@ menus: delete_confirm_accept: name: "§c§lDELETE REGION" lore: [] - # The item to cance deleting. + # The item to cancel deleting. delete_confirm_cancel: name: "§a§lCancel" lore: [] @@ -237,18 +237,18 @@ menus: # Settings for the region group menu. region_group: # The title for the region group menu. - # %1$s: Region name + # %1$s: Region group name title: "§8§lGroup: %1$s" # The item used to rename a region group. rename: - name: "§b§lRename Region" + name: "§b§lRename Group" lore: [] # The item used to delete a region group. # %1$s: Checkmark: No region uses this group delete: - name: "§c§lDelete Region Group" + name: "§c§lDelete Group" lore: - "" - "§6Deletion requirements:" @@ -259,16 +259,11 @@ menus: delete_confirm_accept: name: "§c§lDELETE REGION GROUP" lore: [] - # The item to cance deleting. + # The item to cancel deleting. delete_confirm_cancel: name: "§a§lCancel" lore: [] - # The item used to open the environment settings menu. - environment_settings: - name: "§b§lEnvironment Settings" - lore: [] - # This item is used to create a new role. create_role: name: "§a§lCreate Role" @@ -283,9 +278,62 @@ menus: lore: [] select_role_title: "§8§lSelect Role" - filter_roless_title: "§8§lFilter Roles" + filter_roles_title: "§8§lFilter Roles" # This item is used to represent a role in the selection menu. # %1$s: Role name select_role: name: "%1$s" lore: [] + + # Settings for the role menu. + role: + # The title for the role menu. + # %1$s: Role name + title: "§8§lGroup: %1$s" + + # The item used to rename a role. + rename: + name: "§b§lRename Role" + lore: [] + + # The item used to delete a role. + delete: + name: "§c§lDelete Role" + lore: [] + # The title for the delete confirmation dialog. + delete_confirm_title: "§c§lDelete role?" + # The item to accept deleting. + delete_confirm_accept: + name: "§c§lDELETE ROLE" + lore: [] + # The item to cancel deleting. + delete_confirm_cancel: + name: "§a§lCancel" + lore: [] + + # This item is used to open the player assignment menu for a role. + assign_player: + name: "§b§lAssign Players" + lore: + - "" + - "§7Assign players to this role by clicking on them." + - "§7If the player had a different role before, they will" + - "§7be reassigned to this role. The list will only show" + - "§7players that are not already assigned to this role." + - "§7You can remove players by using the §bRemove Player§7 menu." + # This item is used to open the player removing menu for a role. + remove_player: + name: "§b§lRemove Players" + - "" + - "§7Remove players from this role by clicking on them." + - "§7This means they will have no assigned role afterwards" + - "§7and will be handled by the catch-all role §6[others]" + + select_assign_player_title: "§8§lAssign Players" + select_remove_player_title: "§8§lRemove Players" + filter_players_title: "§8§lFilter Players" + # This item is used to represent a player in the selection menu. + # %1$s: Player name + select_player: + name: "%1$s" + lore: [] From 289f48ad99141d0201d44ee11c8094fe5f8d3737 Mon Sep 17 00:00:00 2001 From: oddlama Date: Mon, 15 Mar 2021 17:45:06 +0100 Subject: [PATCH 15/40] Added actions for current region/region group and selected region --- vane-portals/src/main/resources/lang-en.yml | 2 +- .../oddlama/vane/regions/menu/MainMenu.java | 6 +- vane-regions/src/main/resources/lang-de.yml | 229 +++++++++++++++++- vane-regions/src/main/resources/lang-en.yml | 15 +- 4 files changed, 238 insertions(+), 14 deletions(-) diff --git a/vane-portals/src/main/resources/lang-en.yml b/vane-portals/src/main/resources/lang-en.yml index 4b879cb0f..176ebd518 100644 --- a/vane-portals/src/main/resources/lang-en.yml +++ b/vane-portals/src/main/resources/lang-en.yml @@ -355,7 +355,7 @@ menus: unlink_console_confirm_accept: name: "§c§lUNLINK CONSOLE" lore: [] - # The item to cance unlinking. + # The item to cancel unlinking. unlink_console_confirm_cancel: name: "§a§lCancel" lore: [] diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/menu/MainMenu.java b/vane-regions/src/main/java/org/oddlama/vane/regions/menu/MainMenu.java index 9b163e791..d39824325 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/menu/MainMenu.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/menu/MainMenu.java @@ -222,7 +222,7 @@ private MenuWidget menu_item_list_regions() { filter, (player2, m, region) -> { m.close(player2); - // TODO get_module().menus.region_menu.create(player2, region).open(player2); + get_module().menus.region_menu.create(region, player2).open(player2); return ClickResult.SUCCESS; }, player2 -> { menu.open(player2); @@ -233,6 +233,8 @@ private MenuWidget menu_item_list_regions() { private MenuWidget menu_item_current_region(final Region region) { return new MenuItem(2, item_current_region.item(), (player, menu, self) -> { + menu.close(player); + get_module().menus.region_menu.create(region, player).open(player); return ClickResult.SUCCESS; }); } @@ -251,6 +253,8 @@ private MenuWidget menu_item_list_region_groups() { private MenuWidget menu_item_current_region_group(final RegionGroup region_group) { return new MenuItem(8, item_current_region_group.item(), (player, menu, self) -> { + menu.close(player); + get_module().menus.region_group_menu.create(region_group, player).open(player); return ClickResult.SUCCESS; }); } diff --git a/vane-regions/src/main/resources/lang-de.yml b/vane-regions/src/main/resources/lang-de.yml index b6df21260..ba322dabc 100644 --- a/vane-regions/src/main/resources/lang-de.yml +++ b/vane-regions/src/main/resources/lang-de.yml @@ -18,8 +18,20 @@ version: 2 # language code (ISO 639) and the country code (ISO 3166). resource_pack_lang_code: 'de_de' +# This message is sent when the player needs to select an area for +# a new region. start_region_selection: "§aChoose an area by selecting two blocks via §bleft-§a and §bright-click§a with an empty hand." +# This message is sent when the player selects the primary block +# for a new region. +# %1$s: Block X +# %2$s: Block Y +# %3$s: Block Z select_primary_block: "§aSelected (%1$s§a, %2$s§a, %3$s§a) as primary block." +# This message is sent when the player selects the secondary block +# for a new region. +# %1$s: Block X +# %2$s: Block Y +# %3$s: Block Z select_secondary_block: "§aSelected (%1$s§a, %2$s§a, %3$s§a) as secondary block." command_region: @@ -28,22 +40,34 @@ command_region: help: "Execute to open the region management menu." dynmap: + # The label for the dynmap layer layer_label: "Regions" + # The label for the dynmap markers + # %1$s: Region name marker_label: "%1$s" menus: + # Settings for the region group naming menu. enter_region_group_name: + # The title for the naming menu. title: "§8§lEnter Region Group Name" + # Settings for the region naming menu. enter_region_name: + # The title for the naming menu. title: "§8§lEnter Region Name" + # Settings for the role naming menu. enter_role_name: + # The title for the naming menu. title: "§8§lEnter Role Name" + # Settings for the main menu. main: + # The title for the main menu. title: "§8§lManage Regions" + # The item used to start a new region selection. create_region_start_selection: name: "§a§lCreate Region" lore: @@ -53,39 +77,84 @@ menus: - "§6right-click§7 to select the second block. The" - "§7volume between the blocks will become the region." + # This item is shown when the selection is invalid + # %1$s: Checkmark: primary block set + # %2$s: Checkmark: secondary block set + # %3$s: Checkmark: same world + # %4$s: Checkmark: doesn't interact existing region + # %5$s: Checkmark: minimum area condition met + # %6$s: Checkmark: not bigger than max + # %7$s: Checkmark: can afford + # %8$s: Selection extent X + # %9$s: Selection extent Y + # %10$s: Selection extent Z + # %11$s: min extent X + # %12$s: min extent Y + # %13$s: min extent Z + # %14$s: max extent X + # %15$s: max extent Y + # %16$s: max extent Z create_region_invalid_selection: name: "§c§lInvalid Selection" lore: - "" - - "§6Your selection (%6$s§6 x %7$s§6 x %8$s§6) is invalid!" + - "§6Your selection (%8$s§6 x %9$s§6 x %10$s§6) is invalid!" - "§6It must meet the following requirements:" - "§7- %1$s§7 Primary block set" - "§7- %2$s§7 Secondary block set" - - "§7- %3$s§7 Doesn't intersect existing region" - - "§7- %4$s§7 Covers minimum area (%9$s§7 x %10$s§7 x %11$s§7)" - - "§7- %5$s§7 Not bigger than (%12$s§7 x %13$s§7 x %14$s§7)" + - "§7- %3$s§7 Blocks are in same world" + - "§7- %4$s§7 Doesn't intersect existing region" + - "§7- %5$s§7 Covers minimum area (%11$s§7 x %12$s§7 x %13$s§7)" + - "§7- %6$s§7 Not bigger than (%14$s§7 x %15$s§7 x %16$s§7)" + - "§7- %7$s§7 Can afford" + # This item is shown when the selection is valid + # %1$s: Selection extent X + # %2$s: Selection extent Y + # %3$s: Selection extent Z + # %4$s: min extent X + # %5$s: min extent Y + # %6$s: min extent Z + # %7$s: max extent X + # %8$s: max extent Y + # %9$s: max extent Z create_region_valid_selection: name: "§a§lCreate Region" lore: - "" - "§7Your selection (%1$s§7 x %2$s§7 x %3$s§7) is valid." - - "§7Create a new region by clinking this item." + - "§7Click here to create a new region." + - "" + - "§7- §a✓ Primary block set" + - "§7- §a✓ Secondary block set" + - "§7- §a✓ Blocks are in same world" + - "§7- §a✓ Doesn't intersect existing region" + - "§7- §a✓ Covers minimum area (%4$s§7 x %5$s§7 x %6$s§7)" + - "§7- §a✓ Not bigger than (%7$s§7 x %8$s§7 x %9$s§7)" + - "§7- §a✓ Can afford" + # This item is used to cancel a pending selection. cancel_selection: name: "§c§lCancel Selection" lore: [] + # This item is used to select a region where the player is administrator. list_regions: name: "§b§lSelect Region" lore: [] + # The title for the region selection menu select_region_title: "§8§lSelect Region" + # The title for the region selection menu filter filter_regions_title: "§8§lFilter Regions" + # This item is used to represent a region in the selection menu. + # %1$s: Region name select_region: name: "%1$s" lore: [] + # This item is a shortcut to select the region the player is standing in. + # %1$s: Region name current_region: name: "§b§lCurrent Region" lore: @@ -94,6 +163,7 @@ menus: - "" - "§7Select the region you are standing in." + # This item is used to create a new region group. create_region_group: name: "§a§lCreate Region Group" lore: @@ -103,10 +173,13 @@ menus: - "§7by assigning them roles. All regions in" - "§7a region group will share these permissions" + # This item is used to select a region group. list_region_groups: name: "§b§lSelect region group" lore: [] + # This item is a shortcut to select the region group of the region the player is standing in. + # %1$s: Region group name current_region_group: name: "§b§lCurrent Region Group" lore: @@ -116,6 +189,152 @@ menus: - "§7Select the region group of the" - "§7region you are standing in." + # This item is used to represent a region group in the selection menu. + # %1$s: Region group name select_region_group: name: "%1$s" lore: [] + + # Settings for the region menu. + region: + # The title for the region menu. + # %1$s: Region name + title: "§8§lRegion: %1$s" + + # The item used to rename a region. + rename: + name: "§b§lRename Region" + lore: [] + + # The item used to delete a region. + delete: + name: "§c§lDelete Region" + lore: [] + # The title for the delete confirmation dialog. + delete_confirm_title: "§c§lDelete region?" + # The item to accept deleting. + delete_confirm_accept: + name: "§c§lDELETE REGION" + lore: [] + # The item to cancel deleting. + delete_confirm_cancel: + name: "§a§lCancel" + lore: [] + + # The item used to open the list of region groups to assign the region to one + assign_region_group: + name: "§b§lAssign Group" + lore: [] + + select_region_group_title: "§8§lSelect Region Group" + filter_region_groups_title: "§8§lFilter Region Groups" + # The item used to represent a region group. + # %1$s: Region group name + select_region_group: + name: "%1$s" + lore: [] + + # Settings for the region group menu. + region_group: + # The title for the region group menu. + # %1$s: Region group name + title: "§8§lGroup: %1$s" + + # The item used to rename a region group. + rename: + name: "§b§lRename Group" + lore: [] + + # The item used to delete a region group. + # %1$s: Checkmark: No region uses this group + delete: + name: "§c§lDelete Group" + lore: + - "" + - "§6Deletion requirements:" + - "§7- %1$s §7No region uses this group" + # The title for the delete confirmation dialog. + delete_confirm_title: "§c§lDelete region group?" + # The item to accept deleting. + delete_confirm_accept: + name: "§c§lDELETE REGION GROUP" + lore: [] + # The item to cancel deleting. + delete_confirm_cancel: + name: "§a§lCancel" + lore: [] + + # This item is used to create a new role. + create_role: + name: "§a§lCreate Role" + lore: + - "" + - "§7Create a new §brole§7. Roles are" + - "§7to set permissions for groups of players." + + # This item is used to open the role menu for a role. + list_roles: + name: "§b§lRoles" + lore: [] + + select_role_title: "§8§lSelect Role" + filter_roles_title: "§8§lFilter Roles" + # This item is used to represent a role in the selection menu. + # %1$s: Role name + select_role: + name: "%1$s" + lore: [] + + # Settings for the role menu. + role: + # The title for the role menu. + # %1$s: Role name + title: "§8§lGroup: %1$s" + + # The item used to rename a role. + rename: + name: "§b§lRename Role" + lore: [] + + # The item used to delete a role. + delete: + name: "§c§lDelete Role" + lore: [] + # The title for the delete confirmation dialog. + delete_confirm_title: "§c§lDelete role?" + # The item to accept deleting. + delete_confirm_accept: + name: "§c§lDELETE ROLE" + lore: [] + # The item to cancel deleting. + delete_confirm_cancel: + name: "§a§lCancel" + lore: [] + + # This item is used to open the player assignment menu for a role. + assign_player: + name: "§b§lAssign Players" + lore: + - "" + - "§7Assign players to this role by clicking on them." + - "§7If the player had a different role before, they will" + - "§7be reassigned to this role. The list will only show" + - "§7players that are not already assigned to this role." + - "§7You can remove players by using the §bRemove Player§7 menu." + # This item is used to open the player removing menu for a role. + remove_player: + name: "§b§lRemove Players" + lore: + - "" + - "§7Remove players from this role by clicking on them." + - "§7This means they will have no assigned role afterwards" + - "§7and will be handled by the catch-all role §6[others]" + + select_assign_player_title: "§8§lAssign Players" + select_remove_player_title: "§8§lRemove Players" + filter_players_title: "§8§lFilter Players" + # This item is used to represent a player in the selection menu. + # %1$s: Player name + select_player: + name: "%1$s" + lore: [] diff --git a/vane-regions/src/main/resources/lang-en.yml b/vane-regions/src/main/resources/lang-en.yml index a8009abdf..bb2d1a552 100644 --- a/vane-regions/src/main/resources/lang-en.yml +++ b/vane-regions/src/main/resources/lang-en.yml @@ -125,13 +125,13 @@ menus: - "§7Your selection (%1$s§7 x %2$s§7 x %3$s§7) is valid." - "§7Click here to create a new region." - "" - - "§7- §a✓ Primary block set" - - "§7- §a✓ Secondary block set" - - "§7- §a✓ Blocks are in same world" - - "§7- §a✓ Doesn't intersect existing region" - - "§7- §a✓ Covers minimum area (%4$s§7 x %5$s§7 x %6$s§7)" - - "§7- §a✓ Not bigger than (%7$s§7 x %8$s§7 x %9$s§7)" - - "§7- §a✓ Can afford" + - "§7- §a✓§7 Primary block set" + - "§7- §a✓§7 Secondary block set" + - "§7- §a✓§7 Blocks are in same world" + - "§7- §a✓§7 Doesn't intersect existing region" + - "§7- §a✓§7 Covers minimum area (%4$s§7 x %5$s§7 x %6$s§7)" + - "§7- §a✓§7 Not bigger than (%7$s§7 x %8$s§7 x %9$s§7)" + - "§7- §a✓§7 Can afford" # This item is used to cancel a pending selection. cancel_selection: @@ -324,6 +324,7 @@ menus: # This item is used to open the player removing menu for a role. remove_player: name: "§b§lRemove Players" + lore: - "" - "§7Remove players from this role by clicking on them." - "§7This means they will have no assigned role afterwards" From 20c30e91dd55f3bd8dfc94256cc148166c802970 Mon Sep 17 00:00:00 2001 From: oddlama Date: Mon, 15 Mar 2021 18:05:16 +0100 Subject: [PATCH 16/40] Implemented region group creation and listing --- .../oddlama/vane/regions/menu/MainMenu.java | 32 +++++++++++++++++++ vane-regions/src/main/resources/lang-de.yml | 16 ++++++---- vane-regions/src/main/resources/lang-en.yml | 2 ++ 3 files changed, 43 insertions(+), 7 deletions(-) diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/menu/MainMenu.java b/vane-regions/src/main/java/org/oddlama/vane/regions/menu/MainMenu.java index d39824325..c7260c345 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/menu/MainMenu.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/menu/MainMenu.java @@ -32,6 +32,8 @@ public class MainMenu extends ModuleComponent { @LangMessage public TranslatedMessage lang_title; @LangMessage public TranslatedMessage lang_select_region_title; @LangMessage public TranslatedMessage lang_filter_regions_title; + @LangMessage public TranslatedMessage lang_select_region_group_title; + @LangMessage public TranslatedMessage lang_filter_region_groups_title; public TranslatedItemStack item_create_region_start_selection; public TranslatedItemStack item_create_region_invalid_selection; @@ -241,12 +243,42 @@ private MenuWidget menu_item_current_region(final Region region) { private MenuWidget menu_item_create_region_group() { return new MenuItem(6, item_create_region_group.item(), (player, menu, self) -> { + menu.close(player); + get_module().menus.enter_region_group_name_menu.create(player, (player2, name) -> { + final var group = new RegionGroup(name, player2.getUniqueId()); + get_module().add_region_group(group); + get_module().menus.region_group_menu.create(group, player).open(player); + return ClickResult.SUCCESS; + }).on_natural_close(player2 -> { + menu.open(player2); + }).open(player); + return ClickResult.SUCCESS; }); } private MenuWidget menu_item_list_region_groups() { return new MenuItem(7, item_list_region_groups.item(), (player, menu, self) -> { + menu.close(player); + final var all_region_groups = get_module().all_region_groups() + .stream() + .filter(g -> player.getUniqueId().equals(g.owner()) + || g.get_role(player.getUniqueId()) + .get_setting(RoleSetting.ADMIN)) + .sorted((a, b) -> a.name().compareToIgnoreCase(b.name())) + .collect(Collectors.toList()); + + final var filter = new Filter.StringFilter((r, str) -> r.name().toLowerCase().contains(str)); + MenuFactory.generic_selector(get_context(), player, lang_select_region_group_title.str(), lang_filter_region_groups_title.str(), all_region_groups, + r -> item_select_region_group.item("§a§l" + r.name()), + filter, + (player2, m, group) -> { + m.close(player2); + get_module().menus.region_group_menu.create(group, player).open(player); + return ClickResult.SUCCESS; + }, player2 -> { + menu.open(player2); + }).open(player); return ClickResult.SUCCESS; }); } diff --git a/vane-regions/src/main/resources/lang-de.yml b/vane-regions/src/main/resources/lang-de.yml index ba322dabc..af8b998bf 100644 --- a/vane-regions/src/main/resources/lang-de.yml +++ b/vane-regions/src/main/resources/lang-de.yml @@ -125,13 +125,13 @@ menus: - "§7Your selection (%1$s§7 x %2$s§7 x %3$s§7) is valid." - "§7Click here to create a new region." - "" - - "§7- §a✓ Primary block set" - - "§7- §a✓ Secondary block set" - - "§7- §a✓ Blocks are in same world" - - "§7- §a✓ Doesn't intersect existing region" - - "§7- §a✓ Covers minimum area (%4$s§7 x %5$s§7 x %6$s§7)" - - "§7- §a✓ Not bigger than (%7$s§7 x %8$s§7 x %9$s§7)" - - "§7- §a✓ Can afford" + - "§7- §a✓§7 Primary block set" + - "§7- §a✓§7 Secondary block set" + - "§7- §a✓§7 Blocks are in same world" + - "§7- §a✓§7 Doesn't intersect existing region" + - "§7- §a✓§7 Covers minimum area (%4$s§7 x %5$s§7 x %6$s§7)" + - "§7- §a✓§7 Not bigger than (%7$s§7 x %8$s§7 x %9$s§7)" + - "§7- §a✓§7 Can afford" # This item is used to cancel a pending selection. cancel_selection: @@ -189,6 +189,8 @@ menus: - "§7Select the region group of the" - "§7region you are standing in." + select_region_group_title: "§8§lSelect Region Group" + filter_region_groups_title: "§8§lFilter Region Groups" # This item is used to represent a region group in the selection menu. # %1$s: Region group name select_region_group: diff --git a/vane-regions/src/main/resources/lang-en.yml b/vane-regions/src/main/resources/lang-en.yml index bb2d1a552..bbf0d461b 100644 --- a/vane-regions/src/main/resources/lang-en.yml +++ b/vane-regions/src/main/resources/lang-en.yml @@ -189,6 +189,8 @@ menus: - "§7Select the region group of the" - "§7region you are standing in." + select_region_group_title: "§8§lSelect Region Group" + filter_region_groups_title: "§8§lFilter Region Groups" # This item is used to represent a region group in the selection menu. # %1$s: Region group name select_region_group: From 8f86101dc89ff4c55dae4035f67cf7c71c261733 Mon Sep 17 00:00:00 2001 From: oddlama Date: Mon, 15 Mar 2021 18:07:50 +0100 Subject: [PATCH 17/40] Delay region indexing to after world load --- .../src/main/java/org/oddlama/vane/regions/Regions.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/Regions.java b/vane-regions/src/main/java/org/oddlama/vane/regions/Regions.java index e43309c84..670816150 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/Regions.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/Regions.java @@ -167,12 +167,17 @@ public Regions() { new RegionSelectionListener(this); } - public void on_enable() { + public void delayed_on_enable() { for (var region : storage_regions.values()) { index_add_region(region); } } + @Override + public void on_enable() { + schedule_next_tick(this::delayed_on_enable); + } + public Collection all_regions() { return storage_regions.values(); } From a4d1da98479e28ea143f578feb199a585b9be930 Mon Sep 17 00:00:00 2001 From: oddlama Date: Mon, 15 Mar 2021 18:17:18 +0100 Subject: [PATCH 18/40] Implemented region group orphanage detection --- .../org/oddlama/vane/regions/menu/RegionGroupMenu.java | 7 ++++++- .../main/java/org/oddlama/vane/regions/menu/RoleMenu.java | 7 ++++++- .../java/org/oddlama/vane/regions/region/RegionGroup.java | 7 ++++--- vane-regions/src/main/resources/lang-en.yml | 2 +- 4 files changed, 17 insertions(+), 6 deletions(-) diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RegionGroupMenu.java b/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RegionGroupMenu.java index 108d9fee7..9438d2bc8 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RegionGroupMenu.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RegionGroupMenu.java @@ -58,7 +58,7 @@ public RegionGroupMenu(Context context) { public Menu create(final RegionGroup group, final Player player) { final var columns = 9; - final var title = lang_title.str(); + final var title = lang_title.str(group.name()); final var region_group_menu = new Menu(get_context(), Bukkit.createInventory(null, columns, title)); region_group_menu.tag(new RegionGroupMenuTag(group.id())); @@ -72,6 +72,11 @@ public Menu create(final RegionGroup group, final Player player) { region_group_menu.add(menu_item_list_roles(group)); // TODO integrate settings directly + region_group_menu.on_natural_close(player2 -> + get_module().menus.main_menu + .create(player2) + .open(player2)); + return region_group_menu; } diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RoleMenu.java b/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RoleMenu.java index 2fd4e08eb..c197bb46c 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RoleMenu.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RoleMenu.java @@ -62,7 +62,7 @@ public RoleMenu(Context context) { public Menu create(final RegionGroup group, final Role role, final Player player) { final var columns = 9; - final var title = lang_title.str(); + final var title = lang_title.str(role.name()); final var role_menu = new Menu(get_context(), Bukkit.createInventory(null, columns, title)); final var is_admin = player.getUniqueId().equals(group.owner()) @@ -80,6 +80,11 @@ public Menu create(final RegionGroup group, final Role role, final Player player } // TODO integrate settings directly + role_menu.on_natural_close(player2 -> + get_module().menus.region_group_menu + .create(group, player2) + .open(player2)); + return role_menu; } diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/region/RegionGroup.java b/vane-regions/src/main/java/org/oddlama/vane/regions/region/RegionGroup.java index 0be6d471f..a6e55f7f3 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/region/RegionGroup.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/region/RegionGroup.java @@ -164,8 +164,9 @@ public Collection roles() { return roles.values(); } - public boolean is_orphan(final Regions region) { - // TODO - return false; + public boolean is_orphan(final Regions regions) { + return !regions.all_regions() + .stream() + .anyMatch(r -> id.equals(r.region_group_id())); } } diff --git a/vane-regions/src/main/resources/lang-en.yml b/vane-regions/src/main/resources/lang-en.yml index bbf0d461b..6841d5e2b 100644 --- a/vane-regions/src/main/resources/lang-en.yml +++ b/vane-regions/src/main/resources/lang-en.yml @@ -175,7 +175,7 @@ menus: # This item is used to select a region group. list_region_groups: - name: "§b§lSelect region group" + name: "§b§lSelect Region Group" lore: [] # This item is a shortcut to select the region group of the region the player is standing in. From de266f3b58e2560a3b29d3c2ce309fac3e9724f3 Mon Sep 17 00:00:00 2001 From: oddlama Date: Mon, 15 Mar 2021 19:58:40 +0100 Subject: [PATCH 19/40] Implemented menus for region role settings --- README.md | 10 +-- .../oddlama/vane/regions/menu/MainMenu.java | 6 +- .../vane/regions/menu/RegionGroupMenu.java | 14 +++- .../oddlama/vane/regions/menu/RoleMenu.java | 77 ++++++++++++++++--- .../org/oddlama/vane/regions/region/Role.java | 10 +++ vane-regions/src/main/resources/lang-de.yml | 37 +++++++++ vane-regions/src/main/resources/lang-en.yml | 37 +++++++++ 7 files changed, 168 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index 1eed55316..cfa96d249 100644 --- a/README.md +++ b/README.md @@ -87,15 +87,15 @@ If you don't want a certain feature, simply disable it. - [x] Build portals of arbitrary shape and orientation to get around easily (even horizontal!) - [x] Correctly retains velocity of players, so you can fly through it - [x] Apply different styles to portals so they fit your building style -- [ ] Integrates with regions to control portal connection access - [x] Dynmap integration shows icons for global portals #### Regions (vane-regions) -- [ ] Players can buy an arbitrarily shaped patch of land, and may control certain environmental conditions and player permissions for that area -- [ ] Server-owned regions can be used to protect gobal areas (e.g. spawn). -- [ ] Visual selection of any 2D polygon shape with arbitrary heights. -- [ ] Seamless integration into chest-like menus instead of commands. +- [x] Players can buy a patch of land, and may control certain environmental conditions and player permissions for that area +- [x] Regions created by admins can be used to protect gobal areas (e.g. spawn). +- [x] Seamless integration into chest-like menus instead of commands. +- [x] Integrates with portals to allow only players witha the portal permission to operate portals in the region +- [ ] Visual region selection indicator #### Proxy plugin (vane-waterfall) diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/menu/MainMenu.java b/vane-regions/src/main/java/org/oddlama/vane/regions/menu/MainMenu.java index c7260c345..05323cb5f 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/menu/MainMenu.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/menu/MainMenu.java @@ -242,7 +242,7 @@ private MenuWidget menu_item_current_region(final Region region) { } private MenuWidget menu_item_create_region_group() { - return new MenuItem(6, item_create_region_group.item(), (player, menu, self) -> { + return new MenuItem(7, item_create_region_group.item(), (player, menu, self) -> { menu.close(player); get_module().menus.enter_region_group_name_menu.create(player, (player2, name) -> { final var group = new RegionGroup(name, player2.getUniqueId()); @@ -258,7 +258,7 @@ private MenuWidget menu_item_create_region_group() { } private MenuWidget menu_item_list_region_groups() { - return new MenuItem(7, item_list_region_groups.item(), (player, menu, self) -> { + return new MenuItem(8, item_list_region_groups.item(), (player, menu, self) -> { menu.close(player); final var all_region_groups = get_module().all_region_groups() .stream() @@ -284,7 +284,7 @@ private MenuWidget menu_item_list_region_groups() { } private MenuWidget menu_item_current_region_group(final RegionGroup region_group) { - return new MenuItem(8, item_current_region_group.item(), (player, menu, self) -> { + return new MenuItem(6, item_current_region_group.item(), (player, menu, self) -> { menu.close(player); get_module().menus.region_group_menu.create(region_group, player).open(player); return ClickResult.SUCCESS; diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RegionGroupMenu.java b/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RegionGroupMenu.java index 9438d2bc8..ea6b9a1f7 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RegionGroupMenu.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RegionGroupMenu.java @@ -58,14 +58,17 @@ public RegionGroupMenu(Context context) { public Menu create(final RegionGroup group, final Player player) { final var columns = 9; - final var title = lang_title.str(group.name()); + final var title = lang_title.str("§5§l" + group.name()); final var region_group_menu = new Menu(get_context(), Bukkit.createInventory(null, columns, title)); region_group_menu.tag(new RegionGroupMenuTag(group.id())); final var is_owner = player.getUniqueId().equals(group.owner()); if (is_owner) { region_group_menu.add(menu_item_rename(group)); - region_group_menu.add(menu_item_delete(group)); + // Delete only if this isn't the default group + if (!get_module().get_or_create_default_region_group(player.getUniqueId()).id().equals(group.id())) { + region_group_menu.add(menu_item_delete(group)); + } } region_group_menu.add(menu_item_create_role(group)); @@ -114,6 +117,11 @@ private MenuWidget menu_item_delete(final RegionGroup group) { return ClickResult.ERROR; } + // Assert that this isn't the default group + if (get_module().get_or_create_default_region_group(player2.getUniqueId()).id().equals(group.id())) { + return ClickResult.ERROR; + } + get_module().remove_region_group(group); return ClickResult.SUCCESS; }, item_delete_confirm_cancel.item(), (player2) -> { @@ -142,7 +150,7 @@ private MenuWidget menu_item_list_roles(final RegionGroup group) { final var filter = new Filter.StringFilter((r, str) -> r.name().toLowerCase().contains(str)); MenuFactory.generic_selector(get_context(), player, lang_select_role_title.str(), lang_filter_roles_title.str(), all_roles, - r -> item_select_role.item("§a§l" + r.name()), + r -> item_select_role.item(r.color() + "§l" + r.name()), filter, (player2, m, role) -> { m.close(player2); diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RoleMenu.java b/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RoleMenu.java index c197bb46c..6aaf44fff 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RoleMenu.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RoleMenu.java @@ -47,23 +47,40 @@ public class RoleMenu extends ModuleComponent { public TranslatedItemStack item_remove_player; public TranslatedItemStack item_select_player; + public TranslatedItemStack item_setting_toggle_on; + public TranslatedItemStack item_setting_toggle_off; + public TranslatedItemStack item_setting_info_admin; + public TranslatedItemStack item_setting_info_build; + public TranslatedItemStack item_setting_info_use; + public TranslatedItemStack item_setting_info_container; + public TranslatedItemStack item_setting_info_portal; + public RoleMenu(Context context) { super(context.namespace("role")); final var ctx = get_context(); - item_rename = new TranslatedItemStack<>(ctx, "rename", Material.NAME_TAG, 1, "Used to rename the role."); - item_delete = new TranslatedItemStack<>(ctx, "delete", namespaced_key("vane", "decoration_tnt_1"), 1, "Used to delete this role."); - item_delete_confirm_accept = new TranslatedItemStack<>(ctx, "delete_confirm_accept", namespaced_key("vane", "decoration_tnt_1"), 1, "Used to confirm deleting the role."); - item_delete_confirm_cancel = new TranslatedItemStack<>(ctx, "delete_confirm_cancel", Material.PRISMARINE_SHARD, 1, "Used to cancel deleting the role."); - item_assign_player = new TranslatedItemStack<>(ctx, "assign_player", Material.PLAYER_HEAD, 1, "Used to assign players to this role."); - item_remove_player = new TranslatedItemStack<>(ctx, "remove_player", Material.PLAYER_HEAD, 1, "Used to remove players from this role."); - item_select_player = new TranslatedItemStack<>(ctx, "select_player", Material.PLAYER_HEAD, 1, "Used to represent a player in the role assignment/removal list."); + item_rename = new TranslatedItemStack<>(ctx, "rename", Material.NAME_TAG, 1, "Used to rename the role."); + item_delete = new TranslatedItemStack<>(ctx, "delete", namespaced_key("vane", "decoration_tnt_1"), 1, "Used to delete this role."); + item_delete_confirm_accept = new TranslatedItemStack<>(ctx, "delete_confirm_accept", namespaced_key("vane", "decoration_tnt_1"), 1, "Used to confirm deleting the role."); + item_delete_confirm_cancel = new TranslatedItemStack<>(ctx, "delete_confirm_cancel", Material.PRISMARINE_SHARD, 1, "Used to cancel deleting the role."); + item_assign_player = new TranslatedItemStack<>(ctx, "assign_player", Material.PLAYER_HEAD, 1, "Used to assign players to this role."); + item_remove_player = new TranslatedItemStack<>(ctx, "remove_player", Material.PLAYER_HEAD, 1, "Used to remove players from this role."); + item_select_player = new TranslatedItemStack<>(ctx, "select_player", Material.PLAYER_HEAD, 1, "Used to represent a player in the role assignment/removal list."); + + item_setting_toggle_on = new TranslatedItemStack<>(ctx, "setting_toggle_on", Material.GREEN_TERRACOTTA, 1, "Used to represent a toggle button with current state on."); + item_setting_toggle_off = new TranslatedItemStack<>(ctx, "setting_toggle_off", Material.RED_TERRACOTTA, 1, "Used to represent a toggle button with current state off."); + item_setting_info_admin = new TranslatedItemStack<>(ctx, "setting_admin_info", Material.GOLDEN_APPLE, 1, "Used to represent the info for the admin setting."); + item_setting_info_build = new TranslatedItemStack<>(ctx, "setting_build_info", Material.IRON_PICKAXE, 1, "Used to represent the info for the build setting."); + item_setting_info_use = new TranslatedItemStack<>(ctx, "setting_use_info", Material.DARK_OAK_DOOR, 1, "Used to represent the info for the use setting."); + item_setting_info_container = new TranslatedItemStack<>(ctx, "setting_container_info", Material.CHEST, 1, "Used to represent the info for the container setting."); + item_setting_info_portal = new TranslatedItemStack<>(ctx, "setting_portal_info", Material.ENDER_PEARL, 1, "Used to represent the info for the portal setting."); } public Menu create(final RegionGroup group, final Role role, final Player player) { final var columns = 9; - final var title = lang_title.str(role.name()); - final var role_menu = new Menu(get_context(), Bukkit.createInventory(null, columns, title)); + final var rows = 3; + final var title = lang_title.str(role.color() + "§l" + role.name()); + final var role_menu = new Menu(get_context(), Bukkit.createInventory(null, rows * columns, title)); final var is_admin = player.getUniqueId().equals(group.owner()) || group.get_role(player.getUniqueId()) @@ -78,7 +95,16 @@ public Menu create(final RegionGroup group, final Role role, final Player player role_menu.add(menu_item_assign_player(group, role)); role_menu.add(menu_item_remove_player(group, role)); } - // TODO integrate settings directly + + add_menu_item_setting(role_menu, role, 0, item_setting_info_admin, RoleSetting.ADMIN); + add_menu_item_setting(role_menu, role, 2, item_setting_info_build, RoleSetting.BUILD); + add_menu_item_setting(role_menu, role, 4, item_setting_info_use, RoleSetting.USE); + add_menu_item_setting(role_menu, role, 5, item_setting_info_container, RoleSetting.CONTAINER); + add_menu_item_setting(role_menu, role, 8, item_setting_info_portal, RoleSetting.PORTAL); + + // TODO g money + // TODO g pportal ontegratoin + // TODO g listeners role_menu.on_natural_close(player2 -> get_module().menus.region_group_menu @@ -143,7 +169,7 @@ private MenuWidget menu_item_assign_player(final RegionGroup group, final Role r (player2, m, p) -> { all_players.remove(p); m.update(); - // TODO assing + group.player_to_role().put(p.getUniqueId(), role.id()); return ClickResult.SUCCESS; }, player2 -> { menu.open(player2); @@ -171,7 +197,7 @@ private MenuWidget menu_item_remove_player(final RegionGroup group, final Role r (player2, m, p) -> { all_players.remove(p); m.update(); - // TODO remove + group.player_to_role().remove(p.getUniqueId()); return ClickResult.SUCCESS; }, player2 -> { menu.open(player2); @@ -180,6 +206,33 @@ private MenuWidget menu_item_remove_player(final RegionGroup group, final Role r }); } + private void add_menu_item_setting(final Menu role_menu, final Role role, final int col, final TranslatedItemStack item_info, final RoleSetting setting) { + role_menu.add(new MenuItem(1 * 9 + col, item_info.item(), (player, menu, self) -> { + return ClickResult.IGNORE; + })); + + role_menu.add(new MenuItem(2 * 9 + col, null, (player, menu, self) -> { + if (setting == RoleSetting.ADMIN) { + // Admin setting is immutable + return ClickResult.ERROR; + } + + role.settings().put(setting, !role.get_setting(setting)); + mark_persistent_storage_dirty(); + menu.update(); + return ClickResult.SUCCESS; + }) { + @Override + public void item(final ItemStack item) { + if (role.get_setting(setting)) { + super.item(item_setting_toggle_on.item()); + } else { + super.item(item_setting_toggle_off.item()); + } + } + }); + } + @Override public void on_enable() {} @Override public void on_disable() {} } diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/region/Role.java b/vane-regions/src/main/java/org/oddlama/vane/regions/region/Role.java index 79045199b..698d726e1 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/region/Role.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/region/Role.java @@ -115,7 +115,17 @@ public Role(final String name, final RoleType role_type) { public String name() { return name; } public void name(final String name) { this.name = name; } public RoleType role_type() { return role_type; } + public Map settings() { return settings; } public boolean get_setting(final RoleSetting setting) { return settings.getOrDefault(setting, setting.default_value(false)); } + + public String color() { + switch (role_type) { + case ADMINS: return "§c"; + case OTHERS: return "§a"; + default: + case NORMAL: return "§b"; + } + } } diff --git a/vane-regions/src/main/resources/lang-de.yml b/vane-regions/src/main/resources/lang-de.yml index af8b998bf..2dfadcb65 100644 --- a/vane-regions/src/main/resources/lang-de.yml +++ b/vane-regions/src/main/resources/lang-de.yml @@ -293,6 +293,43 @@ menus: # %1$s: Role name title: "§8§lGroup: %1$s" + setting_toggle_on: + name: "§a§lENABLED" + lore: [] + setting_toggle_off: + name: "§c§lDISABLED" + lore: [] + setting_admin_info: + name: "§b§lAdmin" + lore: + - "" + - "§7The admin flag cannot be toggled" + - "§7and is only set for the admin group." + setting_build_info: + name: "§b§lBuild" + lore: + - "" + - "§7Allows building and mining blocks." + setting_use_info: + name: "§b§lUse Things" + lore: + - "" + - "§7Allows using various things like doors," + - "§7levers, buttons or redstone components." + - "§7Also controls §6view-access§7 to inventories." + setting_container_info: + name: "§b§lContainers" + lore: + - "" + - "§7Allows interaction with inventories." + - "§7Without this flag, nothing can be taken" + - "§7from or put into inventories." + setting_portal_info: + name: "§b§lUse Portals" + lore: + - "" + - "§7Allows interacting with portals." + # The item used to rename a role. rename: name: "§b§lRename Role" diff --git a/vane-regions/src/main/resources/lang-en.yml b/vane-regions/src/main/resources/lang-en.yml index 6841d5e2b..76009b766 100644 --- a/vane-regions/src/main/resources/lang-en.yml +++ b/vane-regions/src/main/resources/lang-en.yml @@ -293,6 +293,43 @@ menus: # %1$s: Role name title: "§8§lGroup: %1$s" + setting_toggle_on: + name: "§a§lENABLED" + lore: [] + setting_toggle_off: + name: "§c§lDISABLED" + lore: [] + setting_admin_info: + name: "§b§lAdmin" + lore: + - "" + - "§7The admin flag cannot be toggled" + - "§7and is only set for the admin group." + setting_build_info: + name: "§b§lBuild" + lore: + - "" + - "§7Allows building and mining blocks." + setting_use_info: + name: "§b§lUse Things" + lore: + - "" + - "§7Allows using various things like doors," + - "§7levers, buttons or redstone components." + - "§7Also controls §6view-access§7 to inventories." + setting_container_info: + name: "§b§lContainers" + lore: + - "" + - "§7Allows interaction with inventories." + - "§7Without this flag, nothing can be taken" + - "§7from or put into inventories." + setting_portal_info: + name: "§b§lUse Portals" + lore: + - "" + - "§7Allows interacting with portals." + # The item used to rename a role. rename: name: "§b§lRename Role" From beede6e52e011111655edde9c6091e16bcbd9d10 Mon Sep 17 00:00:00 2001 From: oddlama Date: Mon, 15 Mar 2021 20:28:57 +0100 Subject: [PATCH 20/40] Added environment setting toggles to the menu --- README.md | 1 + .../vane/regions/menu/RegionGroupMenu.java | 82 ++++++++++++++++--- .../oddlama/vane/regions/menu/RoleMenu.java | 11 +-- .../vane/regions/region/RegionGroup.java | 1 + vane-regions/src/main/resources/lang-de.yml | 54 ++++++++++-- vane-regions/src/main/resources/lang-en.yml | 52 ++++++++++-- 6 files changed, 174 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index cfa96d249..a708b3d32 100644 --- a/README.md +++ b/README.md @@ -95,6 +95,7 @@ If you don't want a certain feature, simply disable it. - [x] Regions created by admins can be used to protect gobal areas (e.g. spawn). - [x] Seamless integration into chest-like menus instead of commands. - [x] Integrates with portals to allow only players witha the portal permission to operate portals in the region +- [x] Integrates with dynmap to make regions visible on the online map - [ ] Visual region selection indicator #### Proxy plugin (vane-waterfall) diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RegionGroupMenu.java b/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RegionGroupMenu.java index ea6b9a1f7..ef9327b74 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RegionGroupMenu.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RegionGroupMenu.java @@ -26,7 +26,7 @@ import org.oddlama.vane.regions.region.Region; import org.oddlama.vane.regions.region.RegionGroup; import org.oddlama.vane.regions.region.RegionSelection; -import org.oddlama.vane.regions.region.RoleSetting; +import org.oddlama.vane.regions.region.EnvironmentSetting; import org.oddlama.vane.regions.region.Role; public class RegionGroupMenu extends ModuleComponent { @@ -43,23 +43,44 @@ public class RegionGroupMenu extends ModuleComponent { public TranslatedItemStack item_list_roles; public TranslatedItemStack item_select_role; + public TranslatedItemStack item_setting_toggle_on; + public TranslatedItemStack item_setting_toggle_off; + public TranslatedItemStack item_setting_info_animals; + public TranslatedItemStack item_setting_info_monsters; + public TranslatedItemStack item_setting_info_explosions; + public TranslatedItemStack item_setting_info_fire_spread; + public TranslatedItemStack item_setting_info_pvp; + public TranslatedItemStack item_setting_info_trample; + public TranslatedItemStack item_setting_info_vine_growth; + public RegionGroupMenu(Context context) { super(context.namespace("region_group")); final var ctx = get_context(); - item_rename = new TranslatedItemStack<>(ctx, "rename", Material.NAME_TAG, 1, "Used to rename the region group."); - item_delete = new TranslatedItemStack<>(ctx, "delete", namespaced_key("vane", "decoration_tnt_1"), 1, "Used to delete this region group."); - item_delete_confirm_accept = new TranslatedItemStack<>(ctx, "delete_confirm_accept", namespaced_key("vane", "decoration_tnt_1"), 1, "Used to confirm deleting the region group."); - item_delete_confirm_cancel = new TranslatedItemStack<>(ctx, "delete_confirm_cancel", Material.PRISMARINE_SHARD, 1, "Used to cancel deleting the region group."); - item_create_role = new TranslatedItemStack<>(ctx, "create_role", Material.WRITABLE_BOOK, 1, "Used to create a new role."); - item_list_roles = new TranslatedItemStack<>(ctx, "list_roles", Material.GLOBE_BANNER_PATTERN, 1, "Used to list all defined roles."); - item_select_role = new TranslatedItemStack<>(ctx, "select_role", Material.GLOBE_BANNER_PATTERN, 1, "Used to represent a role in the role selection list."); + item_rename = new TranslatedItemStack<>(ctx, "rename", Material.NAME_TAG, 1, "Used to rename the region group."); + item_delete = new TranslatedItemStack<>(ctx, "delete", namespaced_key("vane", "decoration_tnt_1"), 1, "Used to delete this region group."); + item_delete_confirm_accept = new TranslatedItemStack<>(ctx, "delete_confirm_accept", namespaced_key("vane", "decoration_tnt_1"), 1, "Used to confirm deleting the region group."); + item_delete_confirm_cancel = new TranslatedItemStack<>(ctx, "delete_confirm_cancel", Material.PRISMARINE_SHARD, 1, "Used to cancel deleting the region group."); + item_create_role = new TranslatedItemStack<>(ctx, "create_role", Material.WRITABLE_BOOK, 1, "Used to create a new role."); + item_list_roles = new TranslatedItemStack<>(ctx, "list_roles", Material.GLOBE_BANNER_PATTERN, 1, "Used to list all defined roles."); + item_select_role = new TranslatedItemStack<>(ctx, "select_role", Material.GLOBE_BANNER_PATTERN, 1, "Used to represent a role in the role selection list."); + + item_setting_toggle_on = new TranslatedItemStack<>(ctx, "setting_toggle_on", Material.GREEN_TERRACOTTA, 1, "Used to represent a toggle button with current state on."); + item_setting_toggle_off = new TranslatedItemStack<>(ctx, "setting_toggle_off", Material.RED_TERRACOTTA, 1, "Used to represent a toggle button with current state off."); + item_setting_info_animals = new TranslatedItemStack<>(ctx, "setting_info_animals", namespaced_key("vane", "baby_pig_2"), 1, "Used to represent the info for the animals setting."); + item_setting_info_monsters = new TranslatedItemStack<>(ctx, "setting_info_monsters", Material.ZOMBIE_HEAD, 1, "Used to represent the info for the monsters setting."); + item_setting_info_explosions = new TranslatedItemStack<>(ctx, "setting_info_explosions", namespaced_key("vane", "creeper_with_tnt_2"), 1, "Used to represent the info for the explosions setting."); + item_setting_info_fire_spread = new TranslatedItemStack<>(ctx, "setting_info_fire_spread", Material.CAMPFIRE, 1, "Used to represent the info for the fire spread setting."); + item_setting_info_pvp = new TranslatedItemStack<>(ctx, "setting_info_pvp", Material.IRON_SWORD, 1, "Used to represent the info for the pvp setting."); + item_setting_info_trample = new TranslatedItemStack<>(ctx, "setting_info_trample", Material.FARMLAND, 1, "Used to represent the info for the trample setting."); + item_setting_info_vine_growth = new TranslatedItemStack<>(ctx, "setting_info_vine_growth", Material.VINE, 1, "Used to represent the info for the vine growth setting."); } public Menu create(final RegionGroup group, final Player player) { final var columns = 9; + final var rows = 3; final var title = lang_title.str("§5§l" + group.name()); - final var region_group_menu = new Menu(get_context(), Bukkit.createInventory(null, columns, title)); + final var region_group_menu = new Menu(get_context(), Bukkit.createInventory(null, rows * columns, title)); region_group_menu.tag(new RegionGroupMenuTag(group.id())); final var is_owner = player.getUniqueId().equals(group.owner()); @@ -73,7 +94,14 @@ public Menu create(final RegionGroup group, final Player player) { region_group_menu.add(menu_item_create_role(group)); region_group_menu.add(menu_item_list_roles(group)); - // TODO integrate settings directly + + add_menu_item_setting(region_group_menu, group, 0, item_setting_info_animals, EnvironmentSetting.ANIMALS); + add_menu_item_setting(region_group_menu, group, 1, item_setting_info_monsters, EnvironmentSetting.MONSTERS); + add_menu_item_setting(region_group_menu, group, 3, item_setting_info_explosions, EnvironmentSetting.EXPLOSIONS); + add_menu_item_setting(region_group_menu, group, 4, item_setting_info_fire_spread, EnvironmentSetting.FIRE_SPREAD); + add_menu_item_setting(region_group_menu, group, 5, item_setting_info_pvp, EnvironmentSetting.PVP); + add_menu_item_setting(region_group_menu, group, 7, item_setting_info_trample, EnvironmentSetting.TRAMPLE); + add_menu_item_setting(region_group_menu, group, 8, item_setting_info_vine_growth, EnvironmentSetting.VINE_GROWTH); region_group_menu.on_natural_close(player2 -> get_module().menus.main_menu @@ -135,7 +163,17 @@ private MenuWidget menu_item_delete(final RegionGroup group) { private MenuWidget menu_item_create_role(final RegionGroup group) { return new MenuItem(7, item_create_role.item(), (player, menu, self) -> { - // TODO + menu.close(player); + get_module().menus.enter_role_name_menu.create(player, (player2, name) -> { + final var role = new Role(name, Role.RoleType.NORMAL); + group.add_role(role); + mark_persistent_storage_dirty(); + get_module().menus.role_menu.create(group, role, player).open(player); + return ClickResult.SUCCESS; + }).on_natural_close(player2 -> { + menu.open(player2); + }).open(player); + return ClickResult.SUCCESS; }); } @@ -163,6 +201,28 @@ private MenuWidget menu_item_list_roles(final RegionGroup group) { }); } + private void add_menu_item_setting(final Menu region_group_menu, final RegionGroup group, final int col, final TranslatedItemStack item_info, final EnvironmentSetting setting) { + region_group_menu.add(new MenuItem(1 * 9 + col, item_info.item(), (player, menu, self) -> { + return ClickResult.IGNORE; + })); + + region_group_menu.add(new MenuItem(2 * 9 + col, null, (player, menu, self) -> { + group.settings().put(setting, !group.get_setting(setting)); + mark_persistent_storage_dirty(); + menu.update(); + return ClickResult.SUCCESS; + }) { + @Override + public void item(final ItemStack item) { + if (group.get_setting(setting)) { + super.item(item_setting_toggle_on.item()); + } else { + super.item(item_setting_toggle_off.item()); + } + } + }); + } + @Override public void on_enable() {} @Override public void on_disable() {} } diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RoleMenu.java b/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RoleMenu.java index 6aaf44fff..6e51043ac 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RoleMenu.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RoleMenu.java @@ -69,11 +69,11 @@ public RoleMenu(Context context) { item_setting_toggle_on = new TranslatedItemStack<>(ctx, "setting_toggle_on", Material.GREEN_TERRACOTTA, 1, "Used to represent a toggle button with current state on."); item_setting_toggle_off = new TranslatedItemStack<>(ctx, "setting_toggle_off", Material.RED_TERRACOTTA, 1, "Used to represent a toggle button with current state off."); - item_setting_info_admin = new TranslatedItemStack<>(ctx, "setting_admin_info", Material.GOLDEN_APPLE, 1, "Used to represent the info for the admin setting."); - item_setting_info_build = new TranslatedItemStack<>(ctx, "setting_build_info", Material.IRON_PICKAXE, 1, "Used to represent the info for the build setting."); - item_setting_info_use = new TranslatedItemStack<>(ctx, "setting_use_info", Material.DARK_OAK_DOOR, 1, "Used to represent the info for the use setting."); - item_setting_info_container = new TranslatedItemStack<>(ctx, "setting_container_info", Material.CHEST, 1, "Used to represent the info for the container setting."); - item_setting_info_portal = new TranslatedItemStack<>(ctx, "setting_portal_info", Material.ENDER_PEARL, 1, "Used to represent the info for the portal setting."); + item_setting_info_admin = new TranslatedItemStack<>(ctx, "setting_info_admin", Material.GOLDEN_APPLE, 1, "Used to represent the info for the admin setting."); + item_setting_info_build = new TranslatedItemStack<>(ctx, "setting_info_build", Material.IRON_PICKAXE, 1, "Used to represent the info for the build setting."); + item_setting_info_use = new TranslatedItemStack<>(ctx, "setting_info_use", Material.DARK_OAK_DOOR, 1, "Used to represent the info for the use setting."); + item_setting_info_container = new TranslatedItemStack<>(ctx, "setting_info_container", Material.CHEST, 1, "Used to represent the info for the container setting."); + item_setting_info_portal = new TranslatedItemStack<>(ctx, "setting_info_portal", Material.ENDER_PEARL, 1, "Used to represent the info for the portal setting."); } public Menu create(final RegionGroup group, final Role role, final Player player) { @@ -105,6 +105,7 @@ public Menu create(final RegionGroup group, final Role role, final Player player // TODO g money // TODO g pportal ontegratoin // TODO g listeners + // TODO g dynmap role_menu.on_natural_close(player2 -> get_module().menus.region_group_menu diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/region/RegionGroup.java b/vane-regions/src/main/java/org/oddlama/vane/regions/region/RegionGroup.java index a6e55f7f3..b32d0aa57 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/region/RegionGroup.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/region/RegionGroup.java @@ -142,6 +142,7 @@ public RegionGroup(final String name, final UUID owner) { public String name() { return name; } public void name(final String name) { this.name = name; } public UUID owner() { return owner; } + public Map settings() { return settings; } public boolean get_setting(final EnvironmentSetting setting) { return settings.getOrDefault(setting, setting.default_value()); } diff --git a/vane-regions/src/main/resources/lang-de.yml b/vane-regions/src/main/resources/lang-de.yml index 2dfadcb65..a5bef6e4d 100644 --- a/vane-regions/src/main/resources/lang-de.yml +++ b/vane-regions/src/main/resources/lang-de.yml @@ -175,7 +175,7 @@ menus: # This item is used to select a region group. list_region_groups: - name: "§b§lSelect region group" + name: "§b§lSelect Region Group" lore: [] # This item is a shortcut to select the region group of the region the player is standing in. @@ -242,6 +242,48 @@ menus: # %1$s: Region group name title: "§8§lGroup: %1$s" + setting_toggle_on: + name: "§a§lENABLED" + lore: [] + setting_toggle_off: + name: "§c§lDISABLED" + lore: [] + setting_info_animals: + name: "§b§lAnimals" + lore: + - "" + - "§7Controls animal / neutral mob spawns." + setting_info_monsters: + name: "§b§lMonsters" + lore: + - "" + - "§7Controls monsters / hostile mob spawns." + setting_info_explosions: + name: "§b§lExplosions" + lore: + - "" + - "§7Controls all types of explosions." + setting_info_fire_spread: + name: "§b§lFire Spread" + lore: + - "" + - "§7Controls whether fire spreads." + setting_info_pvp: + name: "§b§lPVP" + lore: + - "" + - "§7Controls whether PVP combat is allowed." + setting_info_trample: + name: "§b§lTrampling" + lore: + - "" + - "§7Controls whether farmland can be trampled." + setting_info_vine_growth: + name: "§b§lVine Growth" + lore: + - "" + - "§7Controls whether vines grow in the region." + # The item used to rename a region group. rename: name: "§b§lRename Group" @@ -299,32 +341,32 @@ menus: setting_toggle_off: name: "§c§lDISABLED" lore: [] - setting_admin_info: + setting_info_admin: name: "§b§lAdmin" lore: - "" - "§7The admin flag cannot be toggled" - "§7and is only set for the admin group." - setting_build_info: + setting_info_build: name: "§b§lBuild" lore: - "" - "§7Allows building and mining blocks." - setting_use_info: + setting_info_use: name: "§b§lUse Things" lore: - "" - "§7Allows using various things like doors," - "§7levers, buttons or redstone components." - "§7Also controls §6view-access§7 to inventories." - setting_container_info: + setting_info_container: name: "§b§lContainers" lore: - "" - "§7Allows interaction with inventories." - "§7Without this flag, nothing can be taken" - "§7from or put into inventories." - setting_portal_info: + setting_info_portal: name: "§b§lUse Portals" lore: - "" diff --git a/vane-regions/src/main/resources/lang-en.yml b/vane-regions/src/main/resources/lang-en.yml index 76009b766..546358fff 100644 --- a/vane-regions/src/main/resources/lang-en.yml +++ b/vane-regions/src/main/resources/lang-en.yml @@ -242,6 +242,48 @@ menus: # %1$s: Region group name title: "§8§lGroup: %1$s" + setting_toggle_on: + name: "§a§lENABLED" + lore: [] + setting_toggle_off: + name: "§c§lDISABLED" + lore: [] + setting_info_animals: + name: "§b§lAnimals" + lore: + - "" + - "§7Controls animal / neutral mob spawns." + setting_info_monsters: + name: "§b§lMonsters" + lore: + - "" + - "§7Controls monsters / hostile mob spawns." + setting_info_explosions: + name: "§b§lExplosions" + lore: + - "" + - "§7Controls all types of explosions." + setting_info_fire_spread: + name: "§b§lFire Spread" + lore: + - "" + - "§7Controls whether fire spreads." + setting_info_pvp: + name: "§b§lPVP" + lore: + - "" + - "§7Controls whether PVP combat is allowed." + setting_info_trample: + name: "§b§lTrampling" + lore: + - "" + - "§7Controls whether farmland can be trampled." + setting_info_vine_growth: + name: "§b§lVine Growth" + lore: + - "" + - "§7Controls whether vines grow in the region." + # The item used to rename a region group. rename: name: "§b§lRename Group" @@ -299,32 +341,32 @@ menus: setting_toggle_off: name: "§c§lDISABLED" lore: [] - setting_admin_info: + setting_info_admin: name: "§b§lAdmin" lore: - "" - "§7The admin flag cannot be toggled" - "§7and is only set for the admin group." - setting_build_info: + setting_info_build: name: "§b§lBuild" lore: - "" - "§7Allows building and mining blocks." - setting_use_info: + setting_info_use: name: "§b§lUse Things" lore: - "" - "§7Allows using various things like doors," - "§7levers, buttons or redstone components." - "§7Also controls §6view-access§7 to inventories." - setting_container_info: + setting_info_container: name: "§b§lContainers" lore: - "" - "§7Allows interaction with inventories." - "§7Without this flag, nothing can be taken" - "§7from or put into inventories." - setting_portal_info: + setting_info_portal: name: "§b§lUse Portals" lore: - "" From 084814b0f5874f414b448c91220be105fa3226cc Mon Sep 17 00:00:00 2001 From: oddlama Date: Tue, 16 Mar 2021 02:33:24 +0100 Subject: [PATCH 21/40] Implemented currency cost for regions --- .../org/oddlama/vane/regions/Regions.java | 35 ++++++++++--------- .../oddlama/vane/regions/menu/MainMenu.java | 9 +++-- .../vane/regions/menu/RegionGroupMenu.java | 18 +++++----- .../oddlama/vane/regions/menu/RegionMenu.java | 9 +++++ .../vane/regions/region/RegionSelection.java | 17 +++++++-- vane-regions/src/main/resources/lang-en.yml | 6 ++-- 6 files changed, 63 insertions(+), 31 deletions(-) diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/Regions.java b/vane-regions/src/main/java/org/oddlama/vane/regions/Regions.java index 670816150..f3167258e 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/Regions.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/Regions.java @@ -8,6 +8,8 @@ import static org.oddlama.vane.util.Nms.spawn; import static org.oddlama.vane.util.Util.ms_to_ticks; import static org.oddlama.vane.util.Util.namespaced_key; +import static org.oddlama.vane.util.PlayerUtil.give_items; +import static org.oddlama.vane.util.PlayerUtil.take_items; import java.util.ArrayList; import java.util.Collection; @@ -59,6 +61,8 @@ import org.oddlama.vane.core.persistent.PersistentSerializer; import org.oddlama.vane.regions.region.Region; import org.oddlama.vane.annotation.config.ConfigInt; +import org.oddlama.vane.annotation.config.ConfigDouble; +import org.oddlama.vane.annotation.config.ConfigMaterial; import org.oddlama.vane.regions.region.RegionGroup; import org.oddlama.vane.regions.region.RegionSelection; import org.oddlama.vane.regions.region.Role; @@ -86,22 +90,6 @@ public class Regions extends Module { // ┌────────────┐ in ┌───────────────┐ | // | Any Player | ────> | [Role] Others | ───┘ // └────────────┘ └───────────────┘ - // - // Menu: Region - // 1. edit name - // 2. set group - // 3. delete - // - // Menu: Group - // 1. edit name - // 2. add role - // 3. roles - // 4. delete - // - // Menu: Role - // 1. edit name (if not special) - // 2. players (if not others) - // 3. delete role (if not special) // Add (de-)serializers static { @@ -135,6 +123,13 @@ public class Regions extends Module { @ConfigInt(def = 2048, min = 1, desc = "Maximum region extent in z direction.") public int config_max_region_extent_z; + @ConfigMaterial(def = Material.DIAMOND, desc = "The currency material for regions.") + public Material config_currency; + @ConfigDouble(def = 1.0, min = 0.0, desc = "The base amount of currency required to buy an area equal to one chunk (256 blocks).") + public double config_cost_xz_base; + @ConfigDouble(def = 1.15, min = 1.0, desc = "The multiplicator determines how much the cost increases for each additional 16 blocks of height. A region of height h will cost multiplicator^(h / 16.0) * base_amount. Rounding is applied at the end.") + public double config_cost_y_multiplicator; + // Primary storage for all regions (region.id → region) @Persistent private Map storage_regions = new HashMap<>(); @@ -259,6 +254,14 @@ public boolean create_region_from_selection(final Player player, final String na return false; } + // Take currency items + final var price = selection.price(); + final var map = new HashMap(); + map.put(new ItemStack(config_currency), price); + if (price > 0 && !take_items(player, map)) { + return false; + } + final var def_region_group = get_or_create_default_region_group(player.getUniqueId()); final var region = new Region(name, player.getUniqueId(), selection.extent(), def_region_group.id()); add_region(region); diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/menu/MainMenu.java b/vane-regions/src/main/java/org/oddlama/vane/regions/menu/MainMenu.java index 05323cb5f..b3c0391d2 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/menu/MainMenu.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/menu/MainMenu.java @@ -148,7 +148,8 @@ public void item(final ItemStack item) { "§b" + get_module().config_min_region_extent_z, "§b" + get_module().config_max_region_extent_x, "§b" + get_module().config_max_region_extent_y, - "§b" + get_module().config_max_region_extent_z + "§b" + get_module().config_max_region_extent_z, + "§a" + selection.price() + " §b" + String.valueOf(get_module().config_currency).toLowerCase() )); } else { boolean is_primary_set = selection.primary != null; @@ -157,6 +158,7 @@ public void item(final ItemStack item) { boolean minimum_satisified, maximum_satisfied, no_intersection, can_afford; String sdx, sdy, sdz; + String price; if (is_primary_set && is_secondary_set && same_world) { final var dx = 1 + Math.abs(selection.primary.getX() - selection.secondary.getX()); final var dy = 1 + Math.abs(selection.primary.getY() - selection.secondary.getY()); @@ -175,6 +177,7 @@ public void item(final ItemStack item) { dz <= get_module().config_max_region_extent_z; no_intersection = !selection.intersects_existing(); can_afford = selection.can_afford(final_player); + price = (can_afford ? "§a" : "$§") + selection.price() + " §b" + String.valueOf(get_module().config_currency).toLowerCase(); } else { sdx = "§7?"; sdy = "§7?"; @@ -183,6 +186,7 @@ public void item(final ItemStack item) { maximum_satisfied = false; no_intersection = true; can_afford = false; + price = "§7?"; } final var extent_color = minimum_satisified && maximum_satisfied ? "§a" : "§c"; @@ -202,7 +206,8 @@ public void item(final ItemStack item) { "§b" + get_module().config_min_region_extent_z, "§b" + get_module().config_max_region_extent_x, "§b" + get_module().config_max_region_extent_y, - "§b" + get_module().config_max_region_extent_z + "§b" + get_module().config_max_region_extent_z, + price )); } } diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RegionGroupMenu.java b/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RegionGroupMenu.java index ef9327b74..9d8c6ffcf 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RegionGroupMenu.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RegionGroupMenu.java @@ -65,15 +65,15 @@ public RegionGroupMenu(Context context) { item_list_roles = new TranslatedItemStack<>(ctx, "list_roles", Material.GLOBE_BANNER_PATTERN, 1, "Used to list all defined roles."); item_select_role = new TranslatedItemStack<>(ctx, "select_role", Material.GLOBE_BANNER_PATTERN, 1, "Used to represent a role in the role selection list."); - item_setting_toggle_on = new TranslatedItemStack<>(ctx, "setting_toggle_on", Material.GREEN_TERRACOTTA, 1, "Used to represent a toggle button with current state on."); - item_setting_toggle_off = new TranslatedItemStack<>(ctx, "setting_toggle_off", Material.RED_TERRACOTTA, 1, "Used to represent a toggle button with current state off."); - item_setting_info_animals = new TranslatedItemStack<>(ctx, "setting_info_animals", namespaced_key("vane", "baby_pig_2"), 1, "Used to represent the info for the animals setting."); - item_setting_info_monsters = new TranslatedItemStack<>(ctx, "setting_info_monsters", Material.ZOMBIE_HEAD, 1, "Used to represent the info for the monsters setting."); - item_setting_info_explosions = new TranslatedItemStack<>(ctx, "setting_info_explosions", namespaced_key("vane", "creeper_with_tnt_2"), 1, "Used to represent the info for the explosions setting."); - item_setting_info_fire_spread = new TranslatedItemStack<>(ctx, "setting_info_fire_spread", Material.CAMPFIRE, 1, "Used to represent the info for the fire spread setting."); - item_setting_info_pvp = new TranslatedItemStack<>(ctx, "setting_info_pvp", Material.IRON_SWORD, 1, "Used to represent the info for the pvp setting."); - item_setting_info_trample = new TranslatedItemStack<>(ctx, "setting_info_trample", Material.FARMLAND, 1, "Used to represent the info for the trample setting."); - item_setting_info_vine_growth = new TranslatedItemStack<>(ctx, "setting_info_vine_growth", Material.VINE, 1, "Used to represent the info for the vine growth setting."); + item_setting_toggle_on = new TranslatedItemStack<>(ctx, "setting_toggle_on", Material.GREEN_TERRACOTTA, 1, "Used to represent a toggle button with current state on."); + item_setting_toggle_off = new TranslatedItemStack<>(ctx, "setting_toggle_off", Material.RED_TERRACOTTA, 1, "Used to represent a toggle button with current state off."); + item_setting_info_animals = new TranslatedItemStack<>(ctx, "setting_info_animals", namespaced_key("vane", "animals_baby_pig_2"), 1, "Used to represent the info for the animals setting."); + item_setting_info_monsters = new TranslatedItemStack<>(ctx, "setting_info_monsters", Material.ZOMBIE_HEAD, 1, "Used to represent the info for the monsters setting."); + item_setting_info_explosions = new TranslatedItemStack<>(ctx, "setting_info_explosions", namespaced_key("vane", "monsters_creeper_with_tnt_2"), 1, "Used to represent the info for the explosions setting."); + item_setting_info_fire_spread = new TranslatedItemStack<>(ctx, "setting_info_fire_spread", Material.CAMPFIRE, 1, "Used to represent the info for the fire spread setting."); + item_setting_info_pvp = new TranslatedItemStack<>(ctx, "setting_info_pvp", Material.IRON_SWORD, 1, "Used to represent the info for the pvp setting."); + item_setting_info_trample = new TranslatedItemStack<>(ctx, "setting_info_trample", Material.FARMLAND, 1, "Used to represent the info for the trample setting."); + item_setting_info_vine_growth = new TranslatedItemStack<>(ctx, "setting_info_vine_growth", Material.VINE, 1, "Used to represent the info for the vine growth setting."); } public Menu create(final RegionGroup group, final Player player) { diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RegionMenu.java b/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RegionMenu.java index b9f2c5abc..5395f7926 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RegionMenu.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RegionMenu.java @@ -1,6 +1,7 @@ package org.oddlama.vane.regions.menu; import static org.oddlama.vane.util.Util.namespaced_key; +import static org.oddlama.vane.util.PlayerUtil.give_items; import java.util.Objects; import java.util.stream.Collectors; @@ -102,6 +103,14 @@ private MenuWidget menu_item_delete(final Region region) { } get_module().remove_region(region); + + // Give back money + final var temp_sel = new RegionSelection(get_module()); + temp_sel.primary = region.extent().min(); + temp_sel.secondary = region.extent().max(); + + final var price = temp_sel.price(); + give_items(player2, new ItemStack(get_module().config_currency), price); return ClickResult.SUCCESS; }, item_delete_confirm_cancel.item(), (player2) -> { menu.open(player2); diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/region/RegionSelection.java b/vane-regions/src/main/java/org/oddlama/vane/regions/region/RegionSelection.java index 439ea1ae8..8cb2ff3ae 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/region/RegionSelection.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/region/RegionSelection.java @@ -8,6 +8,7 @@ import static org.oddlama.vane.util.ItemUtil.name_item; import static org.oddlama.vane.util.Nms.item_handle; import static org.oddlama.vane.util.Nms.register_entity; +import static org.oddlama.vane.util.PlayerUtil.has_items; import static org.oddlama.vane.util.Nms.spawn; import static org.oddlama.vane.util.Util.ms_to_ticks; import static org.oddlama.vane.util.Util.namespaced_key; @@ -89,9 +90,21 @@ public boolean intersects_existing() { return false; } + public int price() { + final var dx = 1 + Math.abs(primary.getX() - secondary.getX()); + final var dy = 1 + Math.abs(primary.getY() - secondary.getY()); + final var dz = 1 + Math.abs(primary.getZ() - secondary.getZ()); + return (int)(Math.pow(regions.config_cost_y_multiplicator, dy / 16.0) * regions.config_cost_xz_base * dx * dz); + } + public boolean can_afford(final Player player) { - // TODO - return true; + final var price = price(); + if (price <= 0) { + return true; + } + final var map = new HashMap(); + map.put(new ItemStack(regions.config_currency), price); + return has_items(player, map); } public boolean is_valid(final Player player) { diff --git a/vane-regions/src/main/resources/lang-en.yml b/vane-regions/src/main/resources/lang-en.yml index 546358fff..cc9e9c472 100644 --- a/vane-regions/src/main/resources/lang-en.yml +++ b/vane-regions/src/main/resources/lang-en.yml @@ -94,6 +94,7 @@ menus: # %14$s: max extent X # %15$s: max extent Y # %16$s: max extent Z + # %17$s: price and currency create_region_invalid_selection: name: "§c§lInvalid Selection" lore: @@ -106,7 +107,7 @@ menus: - "§7- %4$s§7 Doesn't intersect existing region" - "§7- %5$s§7 Covers minimum area (%11$s§7 x %12$s§7 x %13$s§7)" - "§7- %6$s§7 Not bigger than (%14$s§7 x %15$s§7 x %16$s§7)" - - "§7- %7$s§7 Can afford" + - "§7- %7$s§7 Can afford (%17$s§7)" # This item is shown when the selection is valid # %1$s: Selection extent X @@ -118,6 +119,7 @@ menus: # %7$s: max extent X # %8$s: max extent Y # %9$s: max extent Z + # %10$s: price and currency create_region_valid_selection: name: "§a§lCreate Region" lore: @@ -131,7 +133,7 @@ menus: - "§7- §a✓§7 Doesn't intersect existing region" - "§7- §a✓§7 Covers minimum area (%4$s§7 x %5$s§7 x %6$s§7)" - "§7- §a✓§7 Not bigger than (%7$s§7 x %8$s§7 x %9$s§7)" - - "§7- §a✓§7 Can afford" + - "§7- §a✓§7 Can afford (%10$s§7)" # This item is used to cancel a pending selection. cancel_selection: From 219de2524794a70d3397e0cd11ae986d775baa8b Mon Sep 17 00:00:00 2001 From: oddlama Date: Tue, 16 Mar 2021 15:47:38 +0100 Subject: [PATCH 22/40] Implemented region setting enforcement --- .../RegionEnvironmentSettingEnforcer.java | 178 +++++++++++++++- .../regions/RegionRoleSettingEnforcer.java | 199 +++++++++++++++++- .../vane/regions/menu/RegionGroupMenu.java | 16 +- .../oddlama/vane/regions/menu/RoleMenu.java | 1 - .../regions/region/EnvironmentSetting.java | 2 +- vane-regions/src/main/resources/lang-en.yml | 6 +- 6 files changed, 385 insertions(+), 17 deletions(-) diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/RegionEnvironmentSettingEnforcer.java b/vane-regions/src/main/java/org/oddlama/vane/regions/RegionEnvironmentSettingEnforcer.java index a3b3173ea..a4eed65ec 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/RegionEnvironmentSettingEnforcer.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/RegionEnvironmentSettingEnforcer.java @@ -1,13 +1,47 @@ package org.oddlama.vane.regions; +import org.bukkit.entity.Animals; +import org.bukkit.entity.Entity; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.ItemFrame; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Monster; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.block.BlockBreakEvent; +import org.bukkit.event.block.Action; +import org.bukkit.entity.Player; +import org.bukkit.entity.Projectile; import org.bukkit.event.block.BlockPistonExtendEvent; import org.bukkit.event.block.BlockPistonRetractEvent; import org.bukkit.event.block.BlockPlaceEvent; import org.bukkit.event.entity.EntityChangeBlockEvent; import org.bukkit.event.entity.EntityExplodeEvent; +import org.bukkit.event.block.BlockBurnEvent; +import org.bukkit.event.block.BlockExplodeEvent; +import org.bukkit.event.block.BlockIgniteEvent; +import org.bukkit.event.block.BlockMultiPlaceEvent; +import org.bukkit.event.block.BlockPlaceEvent; +import org.bukkit.event.block.BlockSpreadEvent; +import org.bukkit.event.block.LeavesDecayEvent; +import org.bukkit.event.entity.CreatureSpawnEvent; +import org.bukkit.event.entity.EntityDamageByEntityEvent; +import org.bukkit.event.entity.EntityExplodeEvent; +import org.bukkit.event.entity.PotionSplashEvent; +import org.bukkit.event.hanging.HangingBreakByEntityEvent; +import org.bukkit.event.hanging.HangingBreakEvent; +import org.bukkit.event.hanging.HangingPlaceEvent; +import org.bukkit.event.player.PlayerArmorStandManipulateEvent; +import org.bukkit.event.player.PlayerBucketEmptyEvent; +import org.bukkit.event.player.PlayerBucketFillEvent; +import org.bukkit.event.player.PlayerInteractEntityEvent; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.event.player.PlayerKickEvent; +import org.bukkit.event.player.PlayerQuitEvent; +import org.bukkit.event.world.StructureGrowEvent; +import org.bukkit.inventory.EquipmentSlot; +import org.bukkit.inventory.ItemStack; +import org.bukkit.projectiles.ProjectileSource; import org.oddlama.vane.core.Listener; import org.oddlama.vane.core.module.Context; @@ -15,6 +49,7 @@ import org.bukkit.block.Block; import org.bukkit.Location; +import org.bukkit.Material; public class RegionEnvironmentSettingEnforcer extends Listener { public RegionEnvironmentSettingEnforcer(Context context) { @@ -41,7 +76,18 @@ public boolean check_setting_at(final Block block, final EnvironmentSetting sett return group.get_setting(setting) == check_against; } - @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void on_block_explode(final BlockExplodeEvent event) { + // Prevent explosions from removing region blocks + final var it = event.blockList().iterator(); + while (it.hasNext()) { + if (check_setting_at(it.next(), EnvironmentSetting.EXPLOSIONS, false)) { + it.remove(); + } + } + } + + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) public void on_entity_explode(final EntityExplodeEvent event) { // Prevent explosions from removing region blocks final var it = event.blockList().iterator(); @@ -52,11 +98,139 @@ public void on_entity_explode(final EntityExplodeEvent event) { } } - @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) public void on_entity_change_block(final EntityChangeBlockEvent event) { // Prevent entities from changing region blocks if (check_setting_at(event.getBlock(), EnvironmentSetting.MONSTERS, false)) { event.setCancelled(true); } } + + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void on_block_burn(final BlockBurnEvent event) { + if (check_setting_at(event.getBlock(), EnvironmentSetting.FIRE, false)) { + event.setCancelled(true); + } + } + + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void on_block_spread(final BlockSpreadEvent event) { + EnvironmentSetting setting; + switch (event.getNewState().getType()) { + default: + return; + + case FIRE: setting = EnvironmentSetting.FIRE; break; + case VINE: setting = EnvironmentSetting.VINE_GROWTH; break; + } + + if (check_setting_at(event.getBlock(), setting, false)) { + event.setCancelled(true); + } + } + + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void on_creature_spawn(final CreatureSpawnEvent event) { + // Only cancel natural spawns and alike + switch (event.getSpawnReason()) { + case JOCKEY: + case MOUNT: + case NATURAL: + break; + + default: + return; + } + + final var entity = event.getEntity(); + if (entity instanceof Monster) { + if (check_setting_at(event.getLocation(), EnvironmentSetting.MONSTERS, false)) { + event.setCancelled(true); + } + } else if (entity instanceof Animals) { + if (check_setting_at(event.getLocation(), EnvironmentSetting.ANIMALS, false)) { + event.setCancelled(true); + } + } + } + + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void on_entity_damage_by_entity(final EntityDamageByEntityEvent event) { + final var damaged = event.getEntity(); + final var damager = event.getDamager(); + + switch (damaged.getType()) { + case PLAYER: break; + default: return; + } + + final Player player_damaged = (Player)damaged; + final Player player_damager; + if (damager instanceof Player) { + player_damager = (Player)damager; + } else if (damager instanceof Projectile && ((Projectile)damager).getShooter() instanceof Player) { + player_damager = (Player)((Projectile)damager).getShooter(); + } else { + return; + } + + if (player_damager != null && player_damaged != player_damager && ( + check_setting_at(player_damaged.getLocation(), EnvironmentSetting.PVP, false) || + check_setting_at(player_damager.getLocation(), EnvironmentSetting.PVP, false)) + ) { + event.setCancelled(true); + } + } + + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void on_hanging_break_event(final HangingBreakEvent event) { + switch (event.getCause()) { + default: return; + case ENTITY: return; // Handeled by on_hanging_break_by_entity + case EXPLOSION: { + if (check_setting_at(event.getEntity().getLocation(), EnvironmentSetting.EXPLOSIONS, false)) { + event.setCancelled(true); + } + return; + } + } + } + + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void on_player_interact(final PlayerInteractEvent event) { + if (event.getAction() != Action.PHYSICAL) { + return; + } + + final var block = event.getClickedBlock(); + if (block != null && block.getType() == Material.FARMLAND) { + if (check_setting_at(block, EnvironmentSetting.TRAMPLE, false)) { + event.setCancelled(true); + } + } + } + + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void on_potion_splash(final PotionSplashEvent event) { + // Only if a player threw the potion check for PVP + if (!(event.getEntity().getShooter() instanceof Player)) { + return; + } + + final var thrower = (Player)event.getEntity().getShooter(); + final var source_pvp_restricted = check_setting_at(thrower.getLocation(), EnvironmentSetting.PVP, false); + + // Cancel all damage to players if either thrower or damaged is + // inside no-PVP region + for (final var target : event.getAffectedEntities()) { + if (!(target instanceof Player)) { + continue; + } + + if (source_pvp_restricted || check_setting_at(target.getLocation(), EnvironmentSetting.PVP, false)) { + event.setIntensity(target, 0); + return; + } + } + } } diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/RegionRoleSettingEnforcer.java b/vane-regions/src/main/java/org/oddlama/vane/regions/RegionRoleSettingEnforcer.java index 318dce50a..bec18b1f7 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/RegionRoleSettingEnforcer.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/RegionRoleSettingEnforcer.java @@ -1,11 +1,52 @@ package org.oddlama.vane.regions; +import org.bukkit.Tag; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.block.BlockBreakEvent; +import org.bukkit.entity.Animals; +import org.bukkit.entity.ChestedHorse; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.entity.Entity; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.ItemFrame; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Minecart; +import org.bukkit.entity.Monster; +import org.bukkit.entity.Player; +import org.bukkit.entity.Projectile; +import org.bukkit.event.block.BlockPlaceEvent; +import org.bukkit.event.block.BlockBreakEvent; +import org.bukkit.event.block.BlockBurnEvent; +import org.bukkit.event.block.BlockExplodeEvent; +import org.bukkit.event.block.BlockIgniteEvent; +import org.bukkit.event.block.BlockMultiPlaceEvent; import org.bukkit.event.block.BlockPlaceEvent; +import org.bukkit.event.block.BlockSpreadEvent; +import org.bukkit.event.block.LeavesDecayEvent; +import org.bukkit.event.entity.CreatureSpawnEvent; +import org.bukkit.event.entity.EntityDamageByEntityEvent; +import org.bukkit.event.entity.EntityExplodeEvent; +import org.bukkit.event.inventory.InventoryInteractEvent; +import org.bukkit.event.entity.PotionSplashEvent; +import org.bukkit.event.hanging.HangingBreakByEntityEvent; +import org.bukkit.event.hanging.HangingBreakEvent; +import org.bukkit.event.hanging.HangingPlaceEvent; +import org.bukkit.event.player.PlayerArmorStandManipulateEvent; +import org.bukkit.event.player.PlayerBucketEmptyEvent; +import org.bukkit.event.player.PlayerBucketFillEvent; +import org.bukkit.event.player.PlayerInteractEntityEvent; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.event.player.PlayerKickEvent; +import org.bukkit.event.player.PlayerQuitEvent; +import org.bukkit.event.world.StructureGrowEvent; +import org.bukkit.inventory.EquipmentSlot; +import org.bukkit.inventory.ItemStack; +import org.bukkit.projectiles.ProjectileSource; import org.bukkit.block.Block; +import org.bukkit.block.Container; import org.bukkit.Location; import org.bukkit.entity.Player; @@ -38,7 +79,7 @@ public boolean check_setting_at(final Block block, final Player player, final Ro return group.get_role(player.getUniqueId()).get_setting(setting) == check_against; } - @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) public void on_block_break(final BlockBreakEvent event) { // Prevent breaking of region blocks if (check_setting_at(event.getBlock(), event.getPlayer(), RoleSetting.BUILD, false)) { @@ -46,11 +87,165 @@ public void on_block_break(final BlockBreakEvent event) { } } - @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) public void on_block_place(final BlockPlaceEvent event) { // Prevent (re-)placing of region blocks if (check_setting_at(event.getBlock(), event.getPlayer(), RoleSetting.BUILD, false)) { event.setCancelled(true); } } + + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void on_entity_damage_by_entity(final EntityDamageByEntityEvent event) { + final var damaged = event.getEntity(); + final var damager = event.getDamager(); + + switch (damaged.getType()) { + default: + return; + + case ARMOR_STAND: { + if (!(damager instanceof Player)) { + break; + } + + final var player_damager = (Player)damager; + if (check_setting_at(damaged.getLocation().getBlock(), player_damager, RoleSetting.BUILD, false)) { + event.setCancelled(true); + } + return; + } + + case ITEM_FRAME: { + if (!(damager instanceof Player)) { + break; + } + + final var player_damager = (Player)damager; + final var item_frame = (ItemFrame)damaged; + final var item = item_frame.getItem(); + if (item != null && item.getType() != Material.AIR) { + // This is a player taking the item out of an item-frame + if (check_setting_at(damaged.getLocation().getBlock(), player_damager, RoleSetting.CONTAINER, false)) { + event.setCancelled(true); + } + } + return; + } + } + } + + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void on_hanging_break_by_entity(final HangingBreakByEntityEvent event) { + final Entity remover = event.getRemover(); + Player player = null; + + if (remover instanceof Player) { + player = (Player)remover; + } else if (remover instanceof Projectile) { + final var projectile = (Projectile)remover; + final var shooter = projectile.getShooter(); + if (shooter instanceof Player) { + player = (Player)shooter; + } + } + + if (player != null && check_setting_at(event.getEntity().getLocation(), player, RoleSetting.BUILD, false)) { + event.setCancelled(true); + } + } + + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void on_hanging_place(final HangingPlaceEvent event) { + if (check_setting_at(event.getEntity().getLocation(), event.getPlayer(), RoleSetting.BUILD, false)) { + event.setCancelled(true); + } + } + + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void on_player_armor_stand_manipulate(final PlayerArmorStandManipulateEvent event) { + if (check_setting_at(event.getRightClicked().getLocation(), event.getPlayer(), RoleSetting.BUILD, false)) { + event.setCancelled(true); + } + } + + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void on_player_bucket_empty(final PlayerBucketEmptyEvent event) { + if (check_setting_at(event.getBlockClicked(), event.getPlayer(), RoleSetting.BUILD, false)) { + event.setCancelled(true); + } + } + + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void on_player_bucket_fill(final PlayerBucketFillEvent event) { + if (check_setting_at(event.getBlockClicked(), event.getPlayer(), RoleSetting.BUILD, false)) { + event.setCancelled(true); + } + } + + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void on_player_interact_entity(final PlayerInteractEntityEvent event) { + final var entity = event.getRightClicked(); + if (entity == null || entity.getType() != EntityType.ITEM_FRAME) { + return; + } + + // Place or rotate item + if (check_setting_at(entity.getLocation(), event.getPlayer(), RoleSetting.CONTAINER, false)) { + event.setCancelled(true); + } + } + + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void on_player_interact(final PlayerInteractEvent event) { + final var player = event.getPlayer(); + final var block = event.getClickedBlock(); + if (block == null) { + return; + } + + switch (event.getAction()) { + default: return; + case PHYSICAL: { + if (Tag.PRESSURE_PLATES.isTagged(block.getType())) { + if (check_setting_at(block, player, RoleSetting.USE, false)) { + event.setCancelled(true); + } + } else if (block.getType() == Material.TRIPWIRE) { + if (check_setting_at(block, player, RoleSetting.USE, false)) { + event.setCancelled(true); + } + } + return; + } + + case RIGHT_CLICK_BLOCK: { + if (check_setting_at(block, player, RoleSetting.USE, false)) { + event.setCancelled(true); + } + return; + } + } + } + + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void on_player_inventory_interact(final InventoryInteractEvent event) { + final var clicker = event.getWhoClicked(); + if (!(clicker instanceof Player)) { + return; + } + + final var inventory = event.getInventory(); + if (inventory.getLocation() == null || inventory.getHolder() == null) { + // Inventory is virtual / transient + return; + } + + final var holder = inventory.getHolder(); + if (holder instanceof Container || holder instanceof ChestedHorse || holder instanceof Minecart) { + if (check_setting_at(inventory.getLocation(), (Player)clicker, RoleSetting.CONTAINER, false)) { + event.setCancelled(true); + } + } + } } diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RegionGroupMenu.java b/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RegionGroupMenu.java index 9d8c6ffcf..e5da42f93 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RegionGroupMenu.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RegionGroupMenu.java @@ -48,7 +48,7 @@ public class RegionGroupMenu extends ModuleComponent { public TranslatedItemStack item_setting_info_animals; public TranslatedItemStack item_setting_info_monsters; public TranslatedItemStack item_setting_info_explosions; - public TranslatedItemStack item_setting_info_fire_spread; + public TranslatedItemStack item_setting_info_fire; public TranslatedItemStack item_setting_info_pvp; public TranslatedItemStack item_setting_info_trample; public TranslatedItemStack item_setting_info_vine_growth; @@ -67,12 +67,12 @@ public RegionGroupMenu(Context context) { item_setting_toggle_on = new TranslatedItemStack<>(ctx, "setting_toggle_on", Material.GREEN_TERRACOTTA, 1, "Used to represent a toggle button with current state on."); item_setting_toggle_off = new TranslatedItemStack<>(ctx, "setting_toggle_off", Material.RED_TERRACOTTA, 1, "Used to represent a toggle button with current state off."); - item_setting_info_animals = new TranslatedItemStack<>(ctx, "setting_info_animals", namespaced_key("vane", "animals_baby_pig_2"), 1, "Used to represent the info for the animals setting."); - item_setting_info_monsters = new TranslatedItemStack<>(ctx, "setting_info_monsters", Material.ZOMBIE_HEAD, 1, "Used to represent the info for the monsters setting."); - item_setting_info_explosions = new TranslatedItemStack<>(ctx, "setting_info_explosions", namespaced_key("vane", "monsters_creeper_with_tnt_2"), 1, "Used to represent the info for the explosions setting."); - item_setting_info_fire_spread = new TranslatedItemStack<>(ctx, "setting_info_fire_spread", Material.CAMPFIRE, 1, "Used to represent the info for the fire spread setting."); - item_setting_info_pvp = new TranslatedItemStack<>(ctx, "setting_info_pvp", Material.IRON_SWORD, 1, "Used to represent the info for the pvp setting."); - item_setting_info_trample = new TranslatedItemStack<>(ctx, "setting_info_trample", Material.FARMLAND, 1, "Used to represent the info for the trample setting."); + item_setting_info_animals = new TranslatedItemStack<>(ctx, "setting_info_animals", namespaced_key("vane", "animals_baby_pig_2"), 1, "Used to represent the info for the animals setting."); + item_setting_info_monsters = new TranslatedItemStack<>(ctx, "setting_info_monsters", Material.ZOMBIE_HEAD, 1, "Used to represent the info for the monsters setting."); + item_setting_info_explosions = new TranslatedItemStack<>(ctx, "setting_info_explosions", namespaced_key("vane", "monsters_creeper_with_tnt_2"), 1, "Used to represent the info for the explosions setting."); + item_setting_info_fire = new TranslatedItemStack<>(ctx, "setting_info_fire", Material.CAMPFIRE, 1, "Used to represent the info for the fire setting."); + item_setting_info_pvp = new TranslatedItemStack<>(ctx, "setting_info_pvp", Material.IRON_SWORD, 1, "Used to represent the info for the pvp setting."); + item_setting_info_trample = new TranslatedItemStack<>(ctx, "setting_info_trample", Material.FARMLAND, 1, "Used to represent the info for the trample setting."); item_setting_info_vine_growth = new TranslatedItemStack<>(ctx, "setting_info_vine_growth", Material.VINE, 1, "Used to represent the info for the vine growth setting."); } @@ -98,7 +98,7 @@ public Menu create(final RegionGroup group, final Player player) { add_menu_item_setting(region_group_menu, group, 0, item_setting_info_animals, EnvironmentSetting.ANIMALS); add_menu_item_setting(region_group_menu, group, 1, item_setting_info_monsters, EnvironmentSetting.MONSTERS); add_menu_item_setting(region_group_menu, group, 3, item_setting_info_explosions, EnvironmentSetting.EXPLOSIONS); - add_menu_item_setting(region_group_menu, group, 4, item_setting_info_fire_spread, EnvironmentSetting.FIRE_SPREAD); + add_menu_item_setting(region_group_menu, group, 4, item_setting_info_fire, EnvironmentSetting.FIRE); add_menu_item_setting(region_group_menu, group, 5, item_setting_info_pvp, EnvironmentSetting.PVP); add_menu_item_setting(region_group_menu, group, 7, item_setting_info_trample, EnvironmentSetting.TRAMPLE); add_menu_item_setting(region_group_menu, group, 8, item_setting_info_vine_growth, EnvironmentSetting.VINE_GROWTH); diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RoleMenu.java b/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RoleMenu.java index 6e51043ac..329ce09f8 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RoleMenu.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RoleMenu.java @@ -102,7 +102,6 @@ public Menu create(final RegionGroup group, final Role role, final Player player add_menu_item_setting(role_menu, role, 5, item_setting_info_container, RoleSetting.CONTAINER); add_menu_item_setting(role_menu, role, 8, item_setting_info_portal, RoleSetting.PORTAL); - // TODO g money // TODO g pportal ontegratoin // TODO g listeners // TODO g dynmap diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/region/EnvironmentSetting.java b/vane-regions/src/main/java/org/oddlama/vane/regions/region/EnvironmentSetting.java index a17bcacd3..471e3f57b 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/region/EnvironmentSetting.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/region/EnvironmentSetting.java @@ -7,7 +7,7 @@ public enum EnvironmentSetting { // Hazards EXPLOSIONS(false), - FIRE_SPREAD(false), + FIRE(false), PVP(true), // Environment diff --git a/vane-regions/src/main/resources/lang-en.yml b/vane-regions/src/main/resources/lang-en.yml index cc9e9c472..22969e965 100644 --- a/vane-regions/src/main/resources/lang-en.yml +++ b/vane-regions/src/main/resources/lang-en.yml @@ -265,11 +265,11 @@ menus: lore: - "" - "§7Controls all types of explosions." - setting_info_fire_spread: - name: "§b§lFire Spread" + setting_info_fire: + name: "§b§lFire" lore: - "" - - "§7Controls whether fire spreads." + - "§7Controls whether fire burns blocks and spreads." setting_info_pvp: name: "§b§lPVP" lore: From 1612d7845dfb9ea86a90967db823c304c14e7c4c Mon Sep 17 00:00:00 2001 From: oddlama Date: Tue, 16 Mar 2021 16:49:36 +0100 Subject: [PATCH 23/40] Added portals <-> regions integration, portals can now check if a portal has the same region group as another portal. regions will now prevent some portal events from happening based on region settings. --- .../vane/portals/PortalConstructor.java | 2 +- .../org/oddlama/vane/portals/Portals.java | 20 +++ .../portals/event/PortalLinkConsoleEvent.java | 8 +- .../portals/event/PortalOpenConsoleEvent.java | 11 +- .../event/PortalUnlinkConsoleEvent.java | 9 +- .../vane/portals/menu/ConsoleMenu.java | 6 +- .../vane/portals/menu/SettingsMenu.java | 8 +- .../oddlama/vane/portals/portal/Portal.java | 2 +- vane-portals/src/main/resources/lang-en.yml | 2 +- vane-regions/build.gradle | 1 + .../regions/RegionRoleSettingEnforcer.java | 127 ++++++++++++++++++ .../org/oddlama/vane/regions/Regions.java | 16 +++ .../oddlama/vane/regions/menu/RoleMenu.java | 4 - .../vane/regions/region/RegionGroup.java | 12 +- .../vane/regions/region/RoleSetting.java | 2 +- vane-regions/src/main/resources/plugin.yml | 2 +- 16 files changed, 210 insertions(+), 22 deletions(-) diff --git a/vane-portals/src/main/java/org/oddlama/vane/portals/PortalConstructor.java b/vane-portals/src/main/java/org/oddlama/vane/portals/PortalConstructor.java index e0a008071..1ca469a37 100644 --- a/vane-portals/src/main/java/org/oddlama/vane/portals/PortalConstructor.java +++ b/vane-portals/src/main/java/org/oddlama/vane/portals/PortalConstructor.java @@ -168,7 +168,7 @@ private boolean can_link_console(final Player player, final List blocks, } // Call event - final var event = new PortalLinkConsoleEvent(player, blocks, check_only, existing_portal); + final var event = new PortalLinkConsoleEvent(player, console, blocks, check_only, existing_portal); get_module().getServer().getPluginManager().callEvent(event); if (event.isCancelled()) { lang_link_restricted.send(player); diff --git a/vane-portals/src/main/java/org/oddlama/vane/portals/Portals.java b/vane-portals/src/main/java/org/oddlama/vane/portals/Portals.java index 8e5da0a0f..43394dfb9 100644 --- a/vane-portals/src/main/java/org/oddlama/vane/portals/Portals.java +++ b/vane-portals/src/main/java/org/oddlama/vane/portals/Portals.java @@ -9,6 +9,7 @@ import static org.oddlama.vane.util.Util.ms_to_ticks; import static org.oddlama.vane.util.Util.namespaced_key; +import org.oddlama.vane.core.functional.Function2; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; @@ -234,6 +235,25 @@ public void on_config_change() { } } + // A lightweight callback to the regions module, if it is installed. + // Lifting the callback storage into the portals module saves us + // from having to ship regions api with this module. + private Function2 regions_group_visible_callback = null; + public void set_regions_group_visible_callback(final Function2 callback) { + regions_group_visible_callback = callback; + } + + public boolean is_regions_group_visible(final Portal src, final Portal dst) { + if (regions_group_visible_callback == null) { + return true; + } + return regions_group_visible_callback.apply(src, dst); + } + + public boolean is_regions_installed() { + return regions_group_visible_callback != null; + } + public Style style(final NamespacedKey key) { final var s = styles.get(key); if (s == null) { diff --git a/vane-portals/src/main/java/org/oddlama/vane/portals/event/PortalLinkConsoleEvent.java b/vane-portals/src/main/java/org/oddlama/vane/portals/event/PortalLinkConsoleEvent.java index ddd96eed4..419687600 100644 --- a/vane-portals/src/main/java/org/oddlama/vane/portals/event/PortalLinkConsoleEvent.java +++ b/vane-portals/src/main/java/org/oddlama/vane/portals/event/PortalLinkConsoleEvent.java @@ -14,12 +14,14 @@ public class PortalLinkConsoleEvent extends PortalEvent { private static final HandlerList handlers = new HandlerList(); private Player player; private Portal portal; + private Block console; private List portal_blocks; private boolean check_only; private boolean cancel_if_not_owner = true; - public PortalLinkConsoleEvent(final Player player, final List portal_blocks, boolean check_only, @Nullable final Portal portal) { + public PortalLinkConsoleEvent(final Player player, final Block console, final List portal_blocks, boolean check_only, @Nullable final Portal portal) { this.player = player; + this.console = console; this.portal_blocks = portal_blocks; this.check_only = check_only; this.portal = portal; @@ -33,6 +35,10 @@ public Player getPlayer() { return player; } + public Block getConsole() { + return console; + } + public List getPortalBlocks() { return portal_blocks; } diff --git a/vane-portals/src/main/java/org/oddlama/vane/portals/event/PortalOpenConsoleEvent.java b/vane-portals/src/main/java/org/oddlama/vane/portals/event/PortalOpenConsoleEvent.java index ad10fc71e..b3271ee11 100644 --- a/vane-portals/src/main/java/org/oddlama/vane/portals/event/PortalOpenConsoleEvent.java +++ b/vane-portals/src/main/java/org/oddlama/vane/portals/event/PortalOpenConsoleEvent.java @@ -5,17 +5,18 @@ import org.bukkit.block.Block; import org.bukkit.entity.Player; import org.bukkit.event.HandlerList; +import org.oddlama.vane.portals.portal.Portal; public class PortalOpenConsoleEvent extends PortalEvent { private static final HandlerList handlers = new HandlerList(); private Player player; private Block console; - private UUID portal_id; + private Portal portal; - public PortalOpenConsoleEvent(final Player player, final Block console, final UUID portal_id) { + public PortalOpenConsoleEvent(final Player player, final Block console, final Portal portal) { this.player = player; this.console = console; - this.portal_id = portal_id; + this.portal = portal; } public Player getPlayer() { @@ -26,8 +27,8 @@ public Block getConsole() { return console; } - public UUID getPortalId() { - return portal_id; + public Portal getPortal() { + return portal; } public HandlerList getHandlers() { diff --git a/vane-portals/src/main/java/org/oddlama/vane/portals/event/PortalUnlinkConsoleEvent.java b/vane-portals/src/main/java/org/oddlama/vane/portals/event/PortalUnlinkConsoleEvent.java index 2b1dbd7cc..e397a9572 100644 --- a/vane-portals/src/main/java/org/oddlama/vane/portals/event/PortalUnlinkConsoleEvent.java +++ b/vane-portals/src/main/java/org/oddlama/vane/portals/event/PortalUnlinkConsoleEvent.java @@ -1,5 +1,6 @@ package org.oddlama.vane.portals.event; +import org.bukkit.block.Block; import org.bukkit.entity.Player; import org.bukkit.event.HandlerList; @@ -8,12 +9,14 @@ public class PortalUnlinkConsoleEvent extends PortalEvent { private static final HandlerList handlers = new HandlerList(); private Player player; + private Block console; private Portal portal; private boolean check_only; private boolean cancel_if_not_owner = true; - public PortalUnlinkConsoleEvent(final Player player, final Portal portal, boolean check_only) { + public PortalUnlinkConsoleEvent(final Player player, final Block console, final Portal portal, boolean check_only) { this.player = player; + this.console = console; this.portal = portal; this.check_only = check_only; } @@ -26,6 +29,10 @@ public Player getPlayer() { return player; } + public Block getConsole() { + return console; + } + public Portal getPortal() { return portal; } diff --git a/vane-portals/src/main/java/org/oddlama/vane/portals/menu/ConsoleMenu.java b/vane-portals/src/main/java/org/oddlama/vane/portals/menu/ConsoleMenu.java index 46dee6e3b..8e4315000 100644 --- a/vane-portals/src/main/java/org/oddlama/vane/portals/menu/ConsoleMenu.java +++ b/vane-portals/src/main/java/org/oddlama/vane/portals/menu/ConsoleMenu.java @@ -84,7 +84,7 @@ public Menu create(final Portal portal, final Player player, final Block console } // Check if unlink would be allowed - final var unlink_event = new PortalUnlinkConsoleEvent(player, portal, true); + final var unlink_event = new PortalUnlinkConsoleEvent(player, console, portal, true); get_module().getServer().getPluginManager().callEvent(unlink_event); if (!unlink_event.isCancelled()) { console_menu.add(menu_item_unlink_console(portal, console)); @@ -126,7 +126,7 @@ private MenuWidget menu_item_select_target(final Portal portal) { .filter(p -> { switch (p.visibility()) { case PUBLIC: return true; - case GROUP: return false; // TODO group visibility + case GROUP: return get_module().is_regions_group_visible(portal, p); case PRIVATE: return player.getUniqueId().equals(p.owner()); } return false; @@ -183,7 +183,7 @@ private MenuWidget menu_item_unlink_console(final Portal portal, final Block con MenuFactory.confirm(get_context(), lang_unlink_console_confirm_title.str(), item_unlink_console_confirm_accept.item(), (player2) -> { // Call event - final var event = new PortalUnlinkConsoleEvent(player2, portal, false); + final var event = new PortalUnlinkConsoleEvent(player2, console, portal, false); get_module().getServer().getPluginManager().callEvent(event); if (event.isCancelled()) { get_module().lang_unlink_restricted.send(player2); diff --git a/vane-portals/src/main/java/org/oddlama/vane/portals/menu/SettingsMenu.java b/vane-portals/src/main/java/org/oddlama/vane/portals/menu/SettingsMenu.java index 831415595..8c5cfcb40 100644 --- a/vane-portals/src/main/java/org/oddlama/vane/portals/menu/SettingsMenu.java +++ b/vane-portals/src/main/java/org/oddlama/vane/portals/menu/SettingsMenu.java @@ -156,7 +156,13 @@ private MenuWidget menu_item_visibility(final Portal portal) { return ClickResult.ERROR; } - portal.visibility(event.getClick() == ClickType.RIGHT ? portal.visibility().prev() : portal.visibility().next()); + Portal.Visibility new_vis; + // If regions is not installed, we need to skip group visibility. + do { + new_vis = event.getClick() == ClickType.RIGHT ? portal.visibility().prev() : portal.visibility().next(); + } while (new_vis == Portal.Visibility.GROUP && !get_module().is_regions_installed()); + + portal.visibility(new_vis); get_module().update_portal_visibility(portal); mark_persistent_storage_dirty(); menu.update(); diff --git a/vane-portals/src/main/java/org/oddlama/vane/portals/portal/Portal.java b/vane-portals/src/main/java/org/oddlama/vane/portals/portal/Portal.java index 1cea32b00..e4bc207fa 100644 --- a/vane-portals/src/main/java/org/oddlama/vane/portals/portal/Portal.java +++ b/vane-portals/src/main/java/org/oddlama/vane/portals/portal/Portal.java @@ -298,7 +298,7 @@ public void update_blocks(final Portals portals) { public boolean open_console(final Portals portals, final Player player, final Block console) { // Call event - final var event = new PortalOpenConsoleEvent(player, console, id()); + final var event = new PortalOpenConsoleEvent(player, console, this); portals.getServer().getPluginManager().callEvent(event); if (event.isCancelled()) { return false; diff --git a/vane-portals/src/main/resources/lang-en.yml b/vane-portals/src/main/resources/lang-en.yml index 176ebd518..ad36cbeea 100644 --- a/vane-portals/src/main/resources/lang-en.yml +++ b/vane-portals/src/main/resources/lang-en.yml @@ -135,7 +135,7 @@ menus: # This item is used to cycle visibility and indicate group visibility. visibility_group: name: "§b§lToggle Visibility" - lore: ["", "§bCurrent: §e§lGroup§r"] + lore: ["", "§bCurrent: §e§lRegion Group§r"] # This item is used to cycle visibility and indicate private visibility. visibility_private: diff --git a/vane-regions/build.gradle b/vane-regions/build.gradle index 34b580e36..1ff6e3cbe 100644 --- a/vane-regions/build.gradle +++ b/vane-regions/build.gradle @@ -1,3 +1,4 @@ dependencies { + implementation project(':vane-portals'); implementation group: 'us.dynmap', name: 'dynmap-api', version: '3.1-SNAPSHOT'; } diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/RegionRoleSettingEnforcer.java b/vane-regions/src/main/java/org/oddlama/vane/regions/RegionRoleSettingEnforcer.java index bec18b1f7..5b7fdc275 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/RegionRoleSettingEnforcer.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/RegionRoleSettingEnforcer.java @@ -52,6 +52,15 @@ import org.oddlama.vane.core.Listener; import org.oddlama.vane.core.module.Context; +import org.oddlama.vane.portals.event.PortalActivateEvent; +import org.oddlama.vane.portals.event.PortalChangeSettingsEvent; +import org.oddlama.vane.portals.event.PortalConstructEvent; +import org.oddlama.vane.portals.event.PortalDeactivateEvent; +import org.oddlama.vane.portals.event.PortalDestroyEvent; +import org.oddlama.vane.portals.event.PortalLinkConsoleEvent; +import org.oddlama.vane.portals.event.PortalOpenConsoleEvent; +import org.oddlama.vane.portals.event.PortalSelectTargetEvent; +import org.oddlama.vane.portals.event.PortalUnlinkConsoleEvent; import org.oddlama.vane.regions.region.RoleSetting; public class RegionRoleSettingEnforcer extends Listener { @@ -248,4 +257,122 @@ public void on_player_inventory_interact(final InventoryInteractEvent event) { } } } + + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void on_portal_activate(final PortalActivateEvent event) { + if (check_setting_at(event.getPortal().spawn(), event.getPlayer(), RoleSetting.PORTAL, false)) { + event.setCancelled(true); + } + } + + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void on_portal_deactivate(final PortalDeactivateEvent event) { + if (check_setting_at(event.getPortal().spawn(), event.getPlayer(), RoleSetting.PORTAL, false)) { + event.setCancelled(true); + } + } + + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void on_portal_construct(final PortalConstructEvent event) { + // We have to check all blocks here, because otherwise players + // could "steal" boundary blocks from unowned regions + for (final var block : event.getBoundary().all_blocks()) { + // Portals in regions may only be constructed by region administrators + if (check_setting_at(block, event.getPlayer(), RoleSetting.ADMIN, false)) { + event.setCancelled(true); + return; + } + } + } + + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void on_portal_destroy(final PortalDestroyEvent event) { + // We do NOT have to check all blocks here, because + // an existing portal with its spawn inside a region + // that the player controls can be considered proof of authority. + if (check_setting_at(event.getPortal().spawn(), event.getPlayer(), RoleSetting.ADMIN, false)) { + // Portals in regions may only be destroyed by region administrators + event.setCancelled(true); + } + } + + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void on_portal_link_console(final PortalLinkConsoleEvent event) { + // Portals in regions may only be administrated by region administrators + // Check permission on console + if (check_setting_at(event.getConsole(), event.getPlayer(), RoleSetting.ADMIN, false)) { + event.setCancelled(true); + return; + } + + // Check permission on portal if any + if (event.getPortal() != null && check_setting_at(event.getPortal().spawn(), event.getPlayer(), RoleSetting.ADMIN, false)) { + event.setCancelled(true); + return; + } + } + + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void on_portal_unlink_console(final PortalUnlinkConsoleEvent event) { + // Portals in regions may only be administrated by region administrators + // Check permission on console + if (check_setting_at(event.getConsole(), event.getPlayer(), RoleSetting.ADMIN, false)) { + event.setCancelled(true); + return; + } + + // Check permission on portal + if (check_setting_at(event.getPortal().spawn(), event.getPlayer(), RoleSetting.ADMIN, false)) { + event.setCancelled(true); + return; + } + } + + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void on_portal_open_console(final PortalOpenConsoleEvent event) { + // Check permission on console + if (check_setting_at(event.getConsole(), event.getPlayer(), RoleSetting.PORTAL, false)) { + event.setCancelled(true); + return; + } + + // Check permission on portal + if (check_setting_at(event.getPortal().spawn(), event.getPlayer(), RoleSetting.PORTAL, false)) { + event.setCancelled(true); + return; + } + } + + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void on_portal_select_target(final PortalSelectTargetEvent event) { + // Check permission on source portal + if (check_setting_at(event.getPortal().spawn(), event.getPlayer(), RoleSetting.PORTAL, false)) { + event.setCancelled(true); + return; + } + + // Check permission on target portal + if (check_setting_at(event.getTarget().spawn(), event.getPlayer(), RoleSetting.PORTAL, false)) { + event.setCancelled(true); + return; + } + } + + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void on_portal_change_settings(final PortalChangeSettingsEvent event) { + final var region = get_module().region_at(event.getPortal().spawn()); + if (region == null) { + return; + } + + // Portals in regions may be administrated by region administrators, + // not only be the owner + event.setCancelIfNotOwner(false); + + // Now check if the player has the permission + final var group = region.region_group(get_module()); + if (!group.get_role(event.getPlayer().getUniqueId()).get_setting(RoleSetting.ADMIN)) { + event.setCancelled(true); + } + } } diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/Regions.java b/vane-regions/src/main/java/org/oddlama/vane/regions/Regions.java index f3167258e..9cfa79a63 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/Regions.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/Regions.java @@ -59,6 +59,7 @@ import org.oddlama.vane.core.material.ExtendedMaterial; import org.oddlama.vane.core.module.Module; import org.oddlama.vane.core.persistent.PersistentSerializer; +import org.oddlama.vane.portals.Portals; import org.oddlama.vane.regions.region.Region; import org.oddlama.vane.annotation.config.ConfigInt; import org.oddlama.vane.annotation.config.ConfigDouble; @@ -77,6 +78,8 @@ @VaneModule(name = "regions", bstats = 8643, config_version = 2, lang_version = 2, storage_version = 1) public class Regions extends Module { + // TODO g dynmap + // TODO g visual // // ┌───────────────────────┐ // ┌────────────┐ is ┌───────────────┐ ┌───────────────────────┐ | belongs to ┌─────────────────┐ @@ -170,6 +173,19 @@ public void delayed_on_enable() { @Override public void on_enable() { + final var portals = (Portals)getServer().getPluginManager().getPlugin("vane-portals"); + + // Register callback to portals module so portals + // can find out if two portals are in the same region group + portals.set_regions_group_visible_callback((src, dst) -> { + final var reg_dst = region_at(dst.spawn()); + if (reg_dst == null) { + return true; + } + final var reg_src = region_at(src.spawn()); + return reg_dst.region_group_id().equals(reg_src.region_group_id()); + }); + schedule_next_tick(this::delayed_on_enable); } diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RoleMenu.java b/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RoleMenu.java index 329ce09f8..45fcd1c71 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RoleMenu.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RoleMenu.java @@ -102,10 +102,6 @@ public Menu create(final RegionGroup group, final Role role, final Player player add_menu_item_setting(role_menu, role, 5, item_setting_info_container, RoleSetting.CONTAINER); add_menu_item_setting(role_menu, role, 8, item_setting_info_portal, RoleSetting.PORTAL); - // TODO g pportal ontegratoin - // TODO g listeners - // TODO g dynmap - role_menu.on_natural_close(player2 -> get_module().menus.region_group_menu .create(group, player2) diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/region/RegionGroup.java b/vane-regions/src/main/java/org/oddlama/vane/regions/region/RegionGroup.java index b32d0aa57..876fd4f62 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/region/RegionGroup.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/region/RegionGroup.java @@ -121,14 +121,22 @@ public RegionGroup(final String name, final UUID owner) { this.owner = owner; // Add admins role - final var admins = new Role("[admins]", Role.RoleType.ADMINS); + final var admins = new Role("[Admins]", Role.RoleType.ADMINS); this.add_role(admins); // Add others role - final var others = new Role("[others]", Role.RoleType.OTHERS); + final var others = new Role("[Others]", Role.RoleType.OTHERS); this.add_role(others); this.role_others = others.id(); + // Add friends role + final var friends = new Role("Friends", Role.RoleType.NORMAL); + friends.settings().put(RoleSetting.BUILD, true); + friends.settings().put(RoleSetting.USE, true); + friends.settings().put(RoleSetting.CONTAINER, true); + friends.settings().put(RoleSetting.PORTAL, true); + this.add_role(friends); + // Add owner to admins this.player_to_role.put(owner, admins.id()); diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/region/RoleSetting.java b/vane-regions/src/main/java/org/oddlama/vane/regions/region/RoleSetting.java index 18f277394..6c1e383ac 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/region/RoleSetting.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/region/RoleSetting.java @@ -3,7 +3,7 @@ public enum RoleSetting { ADMIN(false, true), BUILD(false, true), - USE(false, true), + USE(true, true), CONTAINER(false, true), PORTAL(false, true), ; diff --git a/vane-regions/src/main/resources/plugin.yml b/vane-regions/src/main/resources/plugin.yml index 0699efa45..19828a653 100644 --- a/vane-regions/src/main/resources/plugin.yml +++ b/vane-regions/src/main/resources/plugin.yml @@ -5,7 +5,7 @@ description: Regions module for vane authors: [oddlama] website: 'https://github.com/oddlama/vane' -depend: [vane-core] +depend: [vane-core, vane-portals] softdepend: [dynmap] main: org.oddlama.vane.regions.Regions From b34cb7c1dd2ece76741c8e57ad4c9c0fc2b0d28a Mon Sep 17 00:00:00 2001 From: oddlama Date: Tue, 16 Mar 2021 18:24:01 +0100 Subject: [PATCH 24/40] Added region visualization via particles. Cancel region selection when player quits. Reset target portals on visibility change to group if necessary. --- .../org/oddlama/vane/portals/Portals.java | 11 +- .../org/oddlama/vane/regions/Regions.java | 127 +++++++++++++++++- 2 files changed, 131 insertions(+), 7 deletions(-) diff --git a/vane-portals/src/main/java/org/oddlama/vane/portals/Portals.java b/vane-portals/src/main/java/org/oddlama/vane/portals/Portals.java index 43394dfb9..009a75232 100644 --- a/vane-portals/src/main/java/org/oddlama/vane/portals/Portals.java +++ b/vane-portals/src/main/java/org/oddlama/vane/portals/Portals.java @@ -674,13 +674,20 @@ public void update_portal_icon(final Portal portal) { public void update_portal_visibility(final Portal portal) { // Replace references to the portal everywhere, if visibility // has changed. - if (portal.visibility() != Portal.Visibility.PUBLIC) { + if (portal.visibility() == Portal.Visibility.PRIVATE) { for (final var other : storage_portals.values()) { if (Objects.equals(other.target_id(), portal.id())) { other.target_id(null); } } - // TODO don't hide for group access + } else if (portal.visibility() == Portal.Visibility.GROUP) { + // Remove from portals outside of the group + for (final var other : storage_portals.values()) { + if (Objects.equals(other.target_id(), portal.id()) && + !is_regions_group_visible(other, portal)) { + other.target_id(null); + } + } } // Update dynmap marker diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/Regions.java b/vane-regions/src/main/java/org/oddlama/vane/regions/Regions.java index 9cfa79a63..417abda87 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/Regions.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/Regions.java @@ -1,6 +1,7 @@ package org.oddlama.vane.regions; import static org.oddlama.vane.util.BlockUtil.adjacent_blocks_3d; +import org.bukkit.event.player.PlayerQuitEvent; import static org.oddlama.vane.util.BlockUtil.unpack; import static org.oddlama.vane.util.ItemUtil.name_item; import static org.oddlama.vane.util.Nms.item_handle; @@ -27,11 +28,14 @@ import net.minecraft.server.v1_16_R3.EnumCreatureType; import org.bukkit.Chunk; +import org.bukkit.Color; import org.bukkit.Material; import org.bukkit.NamespacedKey; import org.bukkit.Particle; import org.bukkit.Sound; import org.bukkit.SoundCategory; +import org.bukkit.World; +import org.bukkit.Particle.DustOptions; import org.bukkit.block.Block; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; @@ -148,7 +152,7 @@ public class Regions extends Module { // A map containing the current extent for each player who is currently selecting a region // No key → Player not in selection mode // extent.min or extent.max null → Selection mode active, but no selection has been made yet - private Map regions_selections = new HashMap<>(); + private Map region_selections = new HashMap<>(); @LangMessage public TranslatedMessage lang_start_region_selection; @@ -187,6 +191,8 @@ public void on_enable() { }); schedule_next_tick(this::delayed_on_enable); + // Every second: Visualize selections + schedule_task_timer(this::visualize_selections, 1l, 20l); } public Collection all_regions() { @@ -198,20 +204,125 @@ public Collection all_region_groups() { } public void start_region_selection(final Player player) { - regions_selections.put(player.getUniqueId(), new RegionSelection(this)); + region_selections.put(player.getUniqueId(), new RegionSelection(this)); lang_start_region_selection.send(player); } public void cancel_region_selection(final Player player) { - regions_selections.remove(player.getUniqueId()); + region_selections.remove(player.getUniqueId()); } public boolean is_selecting_region(final Player player) { - return regions_selections.containsKey(player.getUniqueId()); + return region_selections.containsKey(player.getUniqueId()); } public RegionSelection get_region_selection(final Player player) { - return regions_selections.get(player.getUniqueId()); + return region_selections.get(player.getUniqueId()); + } + + private static final int visualize_max_particels = 20000; + private static final int visualize_particles_per_block = 12; + private static final double visualize_stddev_compensation = 0.25; + private static final DustOptions visualize_dust_invalid = new DustOptions(Color.fromRGB(200, 60, 11), 0.0f); + private static final DustOptions visualize_dust_valid = new DustOptions(Color.fromRGB(120, 220, 60), 0.0f); + + private void visualize_edge(final World world, final BlockPosition c1, final BlockPosition c2, final boolean valid) { + // Unfortunately, particle spawns are normal distributed. + // To still have a good visualization, we need to calculate a stddev that looks + // good. Empirically we chose a 1/2 of the radius. + final double mx = (c1.getX() + c2.getX()) / 2.0 + 0.5; + final double my = (c1.getY() + c2.getY()) / 2.0 + 0.5; + final double mz = (c1.getZ() + c2.getZ()) / 2.0 + 0.5; + double dx = Math.abs(c1.getX() - c2.getX()); + double dy = Math.abs(c1.getY() - c2.getY()); + double dz = Math.abs(c1.getZ() - c2.getZ()); + final double len = dx + dy + dz; + final int count = Math.min(visualize_max_particels, (int)(visualize_particles_per_block * len)); + + // Compensate for using normal distributed particles + dx *= visualize_stddev_compensation; + dy *= visualize_stddev_compensation; + dz *= visualize_stddev_compensation; + + // Spawn base particles + world.spawnParticle(Particle.END_ROD, + mx, my, mz, + count, + dx, dy, dz, + 0.0, // speed + null, // data + true); // force + + // Spawn colored particles indicating validity + world.spawnParticle(Particle.REDSTONE, + mx, my, mz, + count, + dx, dy, dz, + 0.0, // speed + valid ? visualize_dust_valid : visualize_dust_invalid, // data + true); // force + } + + private void visualize_selections() { + for (final var selection_owner : region_selections.keySet()) { + final var selection = region_selections.get(selection_owner); + if (selection == null) { + continue; + } + + // Get player for selection + final var offline_player = getServer().getOfflinePlayer(selection_owner); + if (!offline_player.isOnline()) { + continue; + } + final var player = offline_player.getPlayer(); + + // Both blocks set + if (selection.primary == null || selection.secondary == null) { + continue; + } + + // Worlds match + if (!selection.primary.getWorld().equals(selection.secondary.getWorld())) { + continue; + } + + // Extent is visualizable. Prepare parameters. + final var world = selection.primary.getWorld(); + // Check if selection is valid + final var valid = selection.is_valid(player); + + final var lx = Math.min(selection.primary.getX(), selection.secondary.getX()); + final var ly = Math.min(selection.primary.getY(), selection.secondary.getY()); + final var lz = Math.min(selection.primary.getZ(), selection.secondary.getZ()); + final var hx = Math.max(selection.primary.getX(), selection.secondary.getX()); + final var hy = Math.max(selection.primary.getY(), selection.secondary.getY()); + final var hz = Math.max(selection.primary.getZ(), selection.secondary.getZ()); + + // Corners + final var A = new BlockPosition(lx, ly, lz); + final var B = new BlockPosition(hx, ly, lz); + final var C = new BlockPosition(hx, hy, lz); + final var D = new BlockPosition(lx, hy, lz); + final var E = new BlockPosition(lx, ly, hz); + final var F = new BlockPosition(hx, ly, hz); + final var G = new BlockPosition(hx, hy, hz); + final var H = new BlockPosition(lx, hy, hz); + + // Visualize each edge + visualize_edge(world, A, B, valid); + visualize_edge(world, B, C, valid); + visualize_edge(world, C, D, valid); + visualize_edge(world, D, A, valid); + visualize_edge(world, E, F, valid); + visualize_edge(world, F, G, valid); + visualize_edge(world, G, H, valid); + visualize_edge(world, H, E, valid); + visualize_edge(world, A, E, valid); + visualize_edge(world, B, F, valid); + visualize_edge(world, C, G, valid); + visualize_edge(world, D, H, valid); + } } public void add_region_group(final RegionGroup group) { @@ -434,4 +545,10 @@ public RegionGroup get_or_create_default_region_group(final UUID owner) { return region_group; } + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void on_player_quit(final PlayerQuitEvent event) { + // Remove pending selection + cancel_region_selection(event.getPlayer()); + } } From 9ba5afdd6ed3ecb8ed57c29e35e1aa314d17e9fe Mon Sep 17 00:00:00 2001 From: oddlama Date: Tue, 16 Mar 2021 18:26:45 +0100 Subject: [PATCH 25/40] Removed superfluous selection messages --- .../vane/regions/RegionSelectionListener.java | 11 ----------- .../main/java/org/oddlama/vane/regions/Regions.java | 1 - vane-regions/src/main/resources/lang-en.yml | 12 ------------ 3 files changed, 24 deletions(-) diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/RegionSelectionListener.java b/vane-regions/src/main/java/org/oddlama/vane/regions/RegionSelectionListener.java index 8261fb6c8..1bb26d8ec 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/RegionSelectionListener.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/RegionSelectionListener.java @@ -20,9 +20,6 @@ import org.oddlama.vane.regions.region.RoleSetting; public class RegionSelectionListener extends Listener { - @LangMessage public TranslatedMessage lang_select_primary_block; - @LangMessage public TranslatedMessage lang_select_secondary_block; - public RegionSelectionListener(Context context) { super(context); } @@ -57,18 +54,10 @@ public void on_player_interact(final PlayerInteractEvent event) { case LEFT_CLICK_BLOCK: selection.primary = block; - lang_select_primary_block.send(player, - "§b" + block.getX(), - "§b" + block.getY(), - "§b" + block.getZ()); break; case RIGHT_CLICK_BLOCK: selection.secondary = block; - lang_select_secondary_block.send(player, - "§b" + block.getX(), - "§b" + block.getY(), - "§b" + block.getZ()); break; } diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/Regions.java b/vane-regions/src/main/java/org/oddlama/vane/regions/Regions.java index 417abda87..74b501c76 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/Regions.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/Regions.java @@ -83,7 +83,6 @@ @VaneModule(name = "regions", bstats = 8643, config_version = 2, lang_version = 2, storage_version = 1) public class Regions extends Module { // TODO g dynmap - // TODO g visual // // ┌───────────────────────┐ // ┌────────────┐ is ┌───────────────┐ ┌───────────────────────┐ | belongs to ┌─────────────────┐ diff --git a/vane-regions/src/main/resources/lang-en.yml b/vane-regions/src/main/resources/lang-en.yml index 22969e965..80ed76eff 100644 --- a/vane-regions/src/main/resources/lang-en.yml +++ b/vane-regions/src/main/resources/lang-en.yml @@ -21,18 +21,6 @@ resource_pack_lang_code: 'en_us' # This message is sent when the player needs to select an area for # a new region. start_region_selection: "§aChoose an area by selecting two blocks via §bleft-§a and §bright-click§a with an empty hand." -# This message is sent when the player selects the primary block -# for a new region. -# %1$s: Block X -# %2$s: Block Y -# %3$s: Block Z -select_primary_block: "§aSelected (%1$s§a, %2$s§a, %3$s§a) as primary block." -# This message is sent when the player selects the secondary block -# for a new region. -# %1$s: Block X -# %2$s: Block Y -# %3$s: Block Z -select_secondary_block: "§aSelected (%1$s§a, %2$s§a, %3$s§a) as secondary block." command_region: usage: "%1$s" From c5dcaf092d8e865452bc0cbae1a1ed0b2a1361ae Mon Sep 17 00:00:00 2001 From: oddlama Date: Tue, 16 Mar 2021 20:37:10 +0100 Subject: [PATCH 26/40] Implemented dymap markers for regions --- .../portals/PortalDynmapLayerDelegate.java | 4 +- .../vane/regions/RegionDynmapLayer.java | 90 +++++++++++ .../regions/RegionDynmapLayerDelegate.java | 152 ++++++++++++++++++ .../org/oddlama/vane/regions/Regions.java | 11 +- .../oddlama/vane/regions/menu/RegionMenu.java | 3 + .../vane/regions/region/RegionSelection.java | 2 +- vane-regions/src/main/resources/lang-de.yml | 26 +-- 7 files changed, 262 insertions(+), 26 deletions(-) create mode 100644 vane-regions/src/main/java/org/oddlama/vane/regions/RegionDynmapLayer.java create mode 100644 vane-regions/src/main/java/org/oddlama/vane/regions/RegionDynmapLayerDelegate.java diff --git a/vane-portals/src/main/java/org/oddlama/vane/portals/PortalDynmapLayerDelegate.java b/vane-portals/src/main/java/org/oddlama/vane/portals/PortalDynmapLayerDelegate.java index c273be24c..ba2492477 100644 --- a/vane-portals/src/main/java/org/oddlama/vane/portals/PortalDynmapLayerDelegate.java +++ b/vane-portals/src/main/java/org/oddlama/vane/portals/PortalDynmapLayerDelegate.java @@ -103,8 +103,8 @@ public void update_marker(final Portal portal) { return; } - // Only public portals - if (portal.visibility() != Portal.Visibility.PUBLIC) { + // Don't show private portals + if (portal.visibility() == Portal.Visibility.PRIVATE) { remove_marker(portal.id()); return; } diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/RegionDynmapLayer.java b/vane-regions/src/main/java/org/oddlama/vane/regions/RegionDynmapLayer.java new file mode 100644 index 000000000..94d481475 --- /dev/null +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/RegionDynmapLayer.java @@ -0,0 +1,90 @@ +package org.oddlama.vane.regions; + +import java.util.UUID; + +import org.oddlama.vane.annotation.config.ConfigBoolean; +import org.oddlama.vane.annotation.config.ConfigDouble; +import org.oddlama.vane.annotation.config.ConfigInt; +import org.oddlama.vane.annotation.lang.LangMessage; +import org.oddlama.vane.core.lang.TranslatedMessage; +import org.oddlama.vane.core.module.Context; +import org.oddlama.vane.core.module.ModuleComponent; +import org.oddlama.vane.regions.region.Region; + +public class RegionDynmapLayer extends ModuleComponent { + public static final String LAYER_ID = "vane_regions.regions"; + + @ConfigInt(def = 35, min = 0, desc = "Layer ordering priority.") + public int config_layer_priority; + @ConfigBoolean(def = false, desc = "If the layer should be hidden by default.") + public boolean config_layer_hide; + + @ConfigInt(def = 0x259df9, min = 0, desc = "Area marker fill color (0xRRGGBB).") + public int config_fill_color; + @ConfigDouble(def = 0.05, min = 0.0, max = 1.0, desc = "Area marker fill opacity.") + public double config_fill_opacity; + + @ConfigInt(def = 2, min = 1, desc = "Area marker line weight.") + public int config_line_weight; + @ConfigInt(def = 0x259df9/*0xf9bd25*/, min = 0, desc = "Area marker line color (0xRRGGBB).") + public int config_line_color; + @ConfigDouble(def = 1.0, min = 0.0, max = 1.0, desc = "Area marker line opacity.") + public double config_line_opacity; + + @LangMessage public TranslatedMessage lang_layer_label; + @LangMessage public TranslatedMessage lang_marker_label; + + private RegionDynmapLayerDelegate delegate = null; + + public RegionDynmapLayer(final Context context) { + super(context.group("dynmap", "Enable dynmap integration. Regions will then be shown on a separate dynmap layer.")); + } + + public void delayed_on_enable() { + final var plugin = get_module().getServer().getPluginManager().getPlugin("dynmap"); + if (plugin == null) { + return; + } + + delegate = new RegionDynmapLayerDelegate(this); + delegate.on_enable(plugin); + } + + @Override + public void on_enable() { + schedule_next_tick(this::delayed_on_enable); + } + + @Override + public void on_disable() { + if (delegate != null) { + delegate.on_disable(); + delegate = null; + } + } + + + public void update_marker(final Region region) { + if (delegate != null) { + delegate.update_marker(region); + } + } + + public void remove_marker(final UUID region_id) { + if (delegate != null) { + delegate.remove_marker(region_id); + } + } + + public void remove_marker(final String marker_id) { + if (delegate != null) { + delegate.remove_marker(marker_id); + } + } + + public void update_all_markers() { + if (delegate != null) { + delegate.update_all_markers(); + } + } +} diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/RegionDynmapLayerDelegate.java b/vane-regions/src/main/java/org/oddlama/vane/regions/RegionDynmapLayerDelegate.java new file mode 100644 index 000000000..f8cc21df0 --- /dev/null +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/RegionDynmapLayerDelegate.java @@ -0,0 +1,152 @@ +package org.oddlama.vane.regions; + +import java.util.HashSet; +import java.util.UUID; +import java.util.logging.Level; + +import org.bukkit.plugin.Plugin; + +import org.dynmap.DynmapAPI; +import org.dynmap.markers.Marker; +import org.dynmap.markers.MarkerAPI; +import org.dynmap.markers.MarkerIcon; +import org.dynmap.markers.MarkerSet; + +import org.oddlama.vane.regions.Regions; +import org.oddlama.vane.regions.region.Region; + +public class RegionDynmapLayerDelegate { + private RegionDynmapLayer parent = null; + + private DynmapAPI dynmap_api = null; + private MarkerAPI marker_api = null; + private boolean dynmap_enabled = false; + + private MarkerSet marker_set = null; + + public RegionDynmapLayerDelegate(final RegionDynmapLayer parent) { + this.parent = parent; + } + + public Regions get_module() { + return parent.get_module(); + } + + public void on_enable(final Plugin plugin) { + try { + dynmap_api = (DynmapAPI)plugin; + marker_api = dynmap_api.getMarkerAPI(); + } catch (Exception e) { + get_module().log.log(Level.WARNING, "Error while enabling dynmap integration!", e); + return; + } + + if (marker_api == null) { + return; + } + + get_module().log.info("Enabling dynmap integration"); + dynmap_enabled = true; + create_or_load_layer(); + } + + public void on_disable() { + if (!dynmap_enabled) { + return; + } + + get_module().log.info("Disabling dynmap integration"); + dynmap_enabled = false; + dynmap_api = null; + marker_api = null; + } + + private void create_or_load_layer() { + // Create or retrieve layer + marker_set = marker_api.getMarkerSet(RegionDynmapLayer.LAYER_ID); + if (marker_set == null) { + marker_set = marker_api.createMarkerSet(RegionDynmapLayer.LAYER_ID, parent.lang_layer_label.str(), null, false); + } + + if (marker_set == null) { + get_module().log.severe("Failed to create dynmap region marker set!"); + return; + } + + // Update attributes + marker_set.setMarkerSetLabel(parent.lang_layer_label.str()); + marker_set.setLayerPriority(parent.config_layer_priority); + marker_set.setHideByDefault(parent.config_layer_hide); + + // Initial update + update_all_markers(); + } + + private String id_for(final UUID region_id) { + return region_id.toString(); + } + + private String id_for(final Region region) { + return id_for(region.id()); + } + + public void update_marker(final Region region) { + if (!dynmap_enabled) { + return; + } + + final var min = region.extent().min(); + final var max = region.extent().max(); + final var world_name = min.getWorld().getName(); + final var marker_id = id_for(region); + final var marker_label = parent.lang_marker_label.str(region.name()); + + final var xs = new double[] { min.getX(), max.getX() + 1 }; + final var zs = new double[] { min.getZ(), max.getZ() + 1 }; + final var area = marker_set.createAreaMarker(marker_id, marker_label, false, world_name, xs, zs, false); + area.setRangeY(max.getY() + 1, min.getY()); + area.setLineStyle(parent.config_line_weight, parent.config_line_opacity, parent.config_line_color); + area.setFillStyle(parent.config_fill_opacity, parent.config_fill_color); + } + + public void remove_marker(final UUID region_id) { + remove_marker(id_for(region_id)); + } + + public void remove_marker(final String marker_id) { + if (!dynmap_enabled || marker_id == null) { + return; + } + + remove_marker(marker_set.findMarker(marker_id)); + } + + public void remove_marker(final Marker marker) { + if (!dynmap_enabled || marker == null) { + return; + } + + marker.deleteMarker(); + } + + public void update_all_markers() { + if (!dynmap_enabled) { + return; + } + + // Update all existing + final var id_set = new HashSet(); + for (final var region : get_module().all_regions()) { + id_set.add(id_for(region)); + update_marker(region); + } + + // Remove orphaned + for (final var marker : marker_set.getMarkers()) { + final var id = marker.getMarkerID(); + if (id != null && !id_set.contains(id)) { + remove_marker(marker); + } + } + } +} diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/Regions.java b/vane-regions/src/main/java/org/oddlama/vane/regions/Regions.java index 74b501c76..40a60b4e6 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/Regions.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/Regions.java @@ -82,7 +82,6 @@ @VaneModule(name = "regions", bstats = 8643, config_version = 2, lang_version = 2, storage_version = 1) public class Regions extends Module { - // TODO g dynmap // // ┌───────────────────────┐ // ┌────────────┐ is ┌───────────────┐ ┌───────────────────────┐ | belongs to ┌─────────────────┐ @@ -131,7 +130,7 @@ public class Regions extends Module { @ConfigMaterial(def = Material.DIAMOND, desc = "The currency material for regions.") public Material config_currency; - @ConfigDouble(def = 1.0, min = 0.0, desc = "The base amount of currency required to buy an area equal to one chunk (256 blocks).") + @ConfigDouble(def = 2.0, min = 0.0, desc = "The base amount of currency required to buy an area equal to one chunk (256 blocks).") public double config_cost_xz_base; @ConfigDouble(def = 1.15, min = 1.0, desc = "The multiplicator determines how much the cost increases for each additional 16 blocks of height. A region of height h will cost multiplicator^(h / 16.0) * base_amount. Rounding is applied at the end.") public double config_cost_y_multiplicator; @@ -156,16 +155,17 @@ public class Regions extends Module { @LangMessage public TranslatedMessage lang_start_region_selection; public RegionMenuGroup menus; + public RegionDynmapLayer dynmap_layer; public Regions() { menus = new RegionMenuGroup(this); new org.oddlama.vane.regions.commands.Region(this); - //dynmap_layer = new RegionDynmapLayer(this); new RegionEnvironmentSettingEnforcer(this); new RegionRoleSettingEnforcer(this); new RegionSelectionListener(this); + dynmap_layer = new RegionDynmapLayer(this); } public void delayed_on_enable() { @@ -403,7 +403,7 @@ public void add_region(final Region region) { index_add_region(region); // Create dynmap marker - //dynmap_layer.update_marker(region); + dynmap_layer.update_marker(region); } public void remove_region(final Region region) { @@ -426,6 +426,9 @@ public void remove_region(final Region region) { // Remove region from index index_remove_region(region); + + // Remove dynmap marker + dynmap_layer.remove_marker(region.id()); } private void index_add_region(final Region region) { diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RegionMenu.java b/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RegionMenu.java index 5395f7926..beae1a831 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RegionMenu.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RegionMenu.java @@ -81,6 +81,9 @@ private MenuWidget menu_item_rename(final Region region) { region.name(name); mark_persistent_storage_dirty(); + // Update dynmap marker + get_module().dynmap_layer.update_marker(region); + // Open new menu because of possibly changed title get_module().menus.region_menu.create(region, player2).open(player2); return ClickResult.SUCCESS; diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/region/RegionSelection.java b/vane-regions/src/main/java/org/oddlama/vane/regions/region/RegionSelection.java index 8cb2ff3ae..24c50ead4 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/region/RegionSelection.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/region/RegionSelection.java @@ -94,7 +94,7 @@ public int price() { final var dx = 1 + Math.abs(primary.getX() - secondary.getX()); final var dy = 1 + Math.abs(primary.getY() - secondary.getY()); final var dz = 1 + Math.abs(primary.getZ() - secondary.getZ()); - return (int)(Math.pow(regions.config_cost_y_multiplicator, dy / 16.0) * regions.config_cost_xz_base * dx * dz); + return (int)Math.ceil(Math.pow(regions.config_cost_y_multiplicator, dy / 16.0) * regions.config_cost_xz_base / 256.0 * dx * dz); } public boolean can_afford(final Player player) { diff --git a/vane-regions/src/main/resources/lang-de.yml b/vane-regions/src/main/resources/lang-de.yml index a5bef6e4d..a82c2a137 100644 --- a/vane-regions/src/main/resources/lang-de.yml +++ b/vane-regions/src/main/resources/lang-de.yml @@ -18,21 +18,7 @@ version: 2 # language code (ISO 639) and the country code (ISO 3166). resource_pack_lang_code: 'de_de' -# This message is sent when the player needs to select an area for -# a new region. start_region_selection: "§aChoose an area by selecting two blocks via §bleft-§a and §bright-click§a with an empty hand." -# This message is sent when the player selects the primary block -# for a new region. -# %1$s: Block X -# %2$s: Block Y -# %3$s: Block Z -select_primary_block: "§aSelected (%1$s§a, %2$s§a, %3$s§a) as primary block." -# This message is sent when the player selects the secondary block -# for a new region. -# %1$s: Block X -# %2$s: Block Y -# %3$s: Block Z -select_secondary_block: "§aSelected (%1$s§a, %2$s§a, %3$s§a) as secondary block." command_region: usage: "%1$s" @@ -94,6 +80,7 @@ menus: # %14$s: max extent X # %15$s: max extent Y # %16$s: max extent Z + # %17$s: price and currency create_region_invalid_selection: name: "§c§lInvalid Selection" lore: @@ -106,7 +93,7 @@ menus: - "§7- %4$s§7 Doesn't intersect existing region" - "§7- %5$s§7 Covers minimum area (%11$s§7 x %12$s§7 x %13$s§7)" - "§7- %6$s§7 Not bigger than (%14$s§7 x %15$s§7 x %16$s§7)" - - "§7- %7$s§7 Can afford" + - "§7- %7$s§7 Can afford (%17$s§7)" # This item is shown when the selection is valid # %1$s: Selection extent X @@ -118,6 +105,7 @@ menus: # %7$s: max extent X # %8$s: max extent Y # %9$s: max extent Z + # %10$s: price and currency create_region_valid_selection: name: "§a§lCreate Region" lore: @@ -131,7 +119,7 @@ menus: - "§7- §a✓§7 Doesn't intersect existing region" - "§7- §a✓§7 Covers minimum area (%4$s§7 x %5$s§7 x %6$s§7)" - "§7- §a✓§7 Not bigger than (%7$s§7 x %8$s§7 x %9$s§7)" - - "§7- §a✓§7 Can afford" + - "§7- §a✓§7 Can afford (%10$s§7)" # This item is used to cancel a pending selection. cancel_selection: @@ -263,11 +251,11 @@ menus: lore: - "" - "§7Controls all types of explosions." - setting_info_fire_spread: - name: "§b§lFire Spread" + setting_info_fire: + name: "§b§lFire" lore: - "" - - "§7Controls whether fire spreads." + - "§7Controls whether fire burns blocks and spreads." setting_info_pvp: name: "§b§lPVP" lore: From 691ef475badfe0e0a520412d9c802a960f90f9b0 Mon Sep 17 00:00:00 2001 From: oddlama Date: Tue, 16 Mar 2021 20:38:57 +0100 Subject: [PATCH 27/40] Fix area marker update problem --- .../org/oddlama/vane/regions/RegionDynmapLayerDelegate.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/RegionDynmapLayerDelegate.java b/vane-regions/src/main/java/org/oddlama/vane/regions/RegionDynmapLayerDelegate.java index f8cc21df0..83f3b7d9d 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/RegionDynmapLayerDelegate.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/RegionDynmapLayerDelegate.java @@ -95,6 +95,9 @@ public void update_marker(final Region region) { return; } + // Area markers can't be updated. + remove_marker(region.id()); + final var min = region.extent().min(); final var max = region.extent().max(); final var world_name = min.getWorld().getName(); From 65db2970752ff2f006ea9ba658cb41823fde6b56 Mon Sep 17 00:00:00 2001 From: oddlama Date: Tue, 16 Mar 2021 21:16:21 +0100 Subject: [PATCH 28/40] Added german translation for regions --- README.md | 2 +- .../org/oddlama/vane/regions/Regions.java | 1 + .../oddlama/vane/regions/menu/MainMenu.java | 4 +- vane-regions/src/main/resources/lang-de.yml | 343 +++++++----------- vane-regions/src/main/resources/lang-en.yml | 14 +- 5 files changed, 137 insertions(+), 227 deletions(-) diff --git a/README.md b/README.md index a708b3d32..9bcc5dbf8 100644 --- a/README.md +++ b/README.md @@ -96,7 +96,7 @@ If you don't want a certain feature, simply disable it. - [x] Seamless integration into chest-like menus instead of commands. - [x] Integrates with portals to allow only players witha the portal permission to operate portals in the region - [x] Integrates with dynmap to make regions visible on the online map -- [ ] Visual region selection indicator +- [x] Visual region selection indicator #### Proxy plugin (vane-waterfall) diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/Regions.java b/vane-regions/src/main/java/org/oddlama/vane/regions/Regions.java index 40a60b4e6..61d04fb6f 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/Regions.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/Regions.java @@ -222,6 +222,7 @@ public RegionSelection get_region_selection(final Player player) { private static final int visualize_max_particels = 20000; private static final int visualize_particles_per_block = 12; private static final double visualize_stddev_compensation = 0.25; + // TODO color ded private static final DustOptions visualize_dust_invalid = new DustOptions(Color.fromRGB(200, 60, 11), 0.0f); private static final DustOptions visualize_dust_valid = new DustOptions(Color.fromRGB(120, 220, 60), 0.0f); diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/menu/MainMenu.java b/vane-regions/src/main/java/org/oddlama/vane/regions/menu/MainMenu.java index b3c0391d2..413a6a265 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/menu/MainMenu.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/menu/MainMenu.java @@ -239,7 +239,7 @@ private MenuWidget menu_item_list_regions() { } private MenuWidget menu_item_current_region(final Region region) { - return new MenuItem(2, item_current_region.item(), (player, menu, self) -> { + return new MenuItem(2, item_current_region.item("§a§l" + region.name()), (player, menu, self) -> { menu.close(player); get_module().menus.region_menu.create(region, player).open(player); return ClickResult.SUCCESS; @@ -289,7 +289,7 @@ private MenuWidget menu_item_list_region_groups() { } private MenuWidget menu_item_current_region_group(final RegionGroup region_group) { - return new MenuItem(6, item_current_region_group.item(), (player, menu, self) -> { + return new MenuItem(6, item_current_region_group.item("§a§l" + region_group.name()), (player, menu, self) -> { menu.close(player); get_module().menus.region_group_menu.create(region_group, player).open(player); return ClickResult.SUCCESS; diff --git a/vane-regions/src/main/resources/lang-de.yml b/vane-regions/src/main/resources/lang-de.yml index a82c2a137..d5394e23c 100644 --- a/vane-regions/src/main/resources/lang-de.yml +++ b/vane-regions/src/main/resources/lang-de.yml @@ -22,388 +22,297 @@ start_region_selection: "§aChoose an area by selecting two blocks via §bleft- command_region: usage: "%1$s" - description: "Open the region management menu." - help: "Execute to open the region management menu." + description: "Öffnet das Regions-Management-Menü." + help: "Ausführen um das Regins-Management-Menü zu öffnen." dynmap: - # The label for the dynmap layer - layer_label: "Regions" - # The label for the dynmap markers - # %1$s: Region name + layer_label: "Regionen" marker_label: "%1$s" menus: - # Settings for the region group naming menu. enter_region_group_name: - # The title for the naming menu. - title: "§8§lEnter Region Group Name" + title: "§8§lRegions-Gruppe benennen" - # Settings for the region naming menu. enter_region_name: - # The title for the naming menu. - title: "§8§lEnter Region Name" + title: "§8§lRegion benennen" - # Settings for the role naming menu. enter_role_name: - # The title for the naming menu. - title: "§8§lEnter Role Name" + title: "§8§lRolle benennen" - # Settings for the main menu. main: - # The title for the main menu. - title: "§8§lManage Regions" + title: "§8§lRegions-Management" - # The item used to start a new region selection. create_region_start_selection: - name: "§a§lCreate Region" + name: "§a§lRegion erstellen" lore: - "" - - "§7Starts a new region selection. With an empty hand," - - "§6left-click§7 to select the first block and" - - "§6right-click§7 to select the second block. The" - - "§7volume between the blocks will become the region." - - # This item is shown when the selection is invalid - # %1$s: Checkmark: primary block set - # %2$s: Checkmark: secondary block set - # %3$s: Checkmark: same world - # %4$s: Checkmark: doesn't interact existing region - # %5$s: Checkmark: minimum area condition met - # %6$s: Checkmark: not bigger than max - # %7$s: Checkmark: can afford - # %8$s: Selection extent X - # %9$s: Selection extent Y - # %10$s: Selection extent Z - # %11$s: min extent X - # %12$s: min extent Y - # %13$s: min extent Z - # %14$s: max extent X - # %15$s: max extent Y - # %16$s: max extent Z - # %17$s: price and currency + - "§7Beginnt eine neue Regionsauswahl. Mit leerer Hand," + - "§6links-clicke§7 um den ersten block auszuwählen and" + - "§6rechts-clicke§7 um den zweiten block auszuwählen." + - "§7Das Volumen dazwischen wird die Region." + create_region_invalid_selection: - name: "§c§lInvalid Selection" + name: "§c§lUnzulässige Auswahl" lore: - "" - - "§6Your selection (%8$s§6 x %9$s§6 x %10$s§6) is invalid!" - - "§6It must meet the following requirements:" - - "§7- %1$s§7 Primary block set" - - "§7- %2$s§7 Secondary block set" - - "§7- %3$s§7 Blocks are in same world" - - "§7- %4$s§7 Doesn't intersect existing region" - - "§7- %5$s§7 Covers minimum area (%11$s§7 x %12$s§7 x %13$s§7)" - - "§7- %6$s§7 Not bigger than (%14$s§7 x %15$s§7 x %16$s§7)" - - "§7- %7$s§7 Can afford (%17$s§7)" - - # This item is shown when the selection is valid - # %1$s: Selection extent X - # %2$s: Selection extent Y - # %3$s: Selection extent Z - # %4$s: min extent X - # %5$s: min extent Y - # %6$s: min extent Z - # %7$s: max extent X - # %8$s: max extent Y - # %9$s: max extent Z - # %10$s: price and currency + - "§6Deine Auswahl (%8$s§6 x %9$s§6 x %10$s§6) ist unzulässig!" + - "§6Folgende Anforderungen müssen erfüllt sein:" + - "§7- %1$s§7 Erster block gesetzt" + - "§7- %2$s§7 Zweiter block gesetzt" + - "§7- %3$s§7 Blöcke sind in der selben Welt" + - "§7- %4$s§7 Schneidet keine vorhandene Region" + - "§7- %5$s§7 Größer gleich (%11$s§7 x %12$s§7 x %13$s§7)" + - "§7- %6$s§7 Kleiner gleich (%14$s§7 x %15$s§7 x %16$s§7)" + - "§7- %7$s§7 Außreichend Währung im Inventar (%17$s§7)" + create_region_valid_selection: - name: "§a§lCreate Region" + name: "§a§lRegion erstellen" lore: - "" - - "§7Your selection (%1$s§7 x %2$s§7 x %3$s§7) is valid." - - "§7Click here to create a new region." + - "§7Deine Auswahl (%1$s§7 x %2$s§7 x %3$s§7) is zulässig." + - "§7Clicke hier um eine neue Region zu erstellen." - "" - - "§7- §a✓§7 Primary block set" - - "§7- §a✓§7 Secondary block set" - - "§7- §a✓§7 Blocks are in same world" - - "§7- §a✓§7 Doesn't intersect existing region" - - "§7- §a✓§7 Covers minimum area (%4$s§7 x %5$s§7 x %6$s§7)" - - "§7- §a✓§7 Not bigger than (%7$s§7 x %8$s§7 x %9$s§7)" - - "§7- §a✓§7 Can afford (%10$s§7)" - - # This item is used to cancel a pending selection. + - "§7- §a✓§7 Erster block gesetzt" + - "§7- §a✓§7 Zweiter block gesetzt" + - "§7- §a✓§7 Blöcke sind in der selben Welt" + - "§7- §a✓§7 Schneidet keine vorhandene Region" + - "§7- §a✓§7 Größer gleich (%11$s§7 x %12$s§7 x %13$s§7)" + - "§7- §a✓§7 Kleiner gleich (%14$s§7 x %15$s§7 x %16$s§7)" + - "§7- §a✓§7 Außreichend Währung im Inventar (%17$s§7)" + cancel_selection: - name: "§c§lCancel Selection" + name: "§c§lAuswahl abbrechen" lore: [] - # This item is used to select a region where the player is administrator. list_regions: - name: "§b§lSelect Region" + name: "§b§lRegion auswählen" lore: [] - # The title for the region selection menu - select_region_title: "§8§lSelect Region" - # The title for the region selection menu filter - filter_regions_title: "§8§lFilter Regions" - # This item is used to represent a region in the selection menu. - # %1$s: Region name + select_region_title: "§8§lRegion auswählen" + filter_regions_title: "§8§lRegionen filtern" select_region: name: "%1$s" lore: [] - # This item is a shortcut to select the region the player is standing in. - # %1$s: Region name current_region: - name: "§b§lCurrent Region" + name: "§b§lAktuelle Region" lore: - "" - "§7Region: %1$s" - "" - - "§7Select the region you are standing in." + - "§7Wählt die Region aus, in der du dich gerade befindest." - # This item is used to create a new region group. create_region_group: - name: "§a§lCreate Region Group" + name: "§a§lRegions-Gruppe erstellen" lore: - "" - - "§7Create a new §bregion group§7. Region groups" - - "§7are used to set permissions for players" - - "§7by assigning them roles. All regions in" - - "§7a region group will share these permissions" + - "§7Erstelle eine neue new §bRegions-Gruppe§7. Regions-Gruppen" + - "§7werden verwendet um Rechte an Spieler zu vergeben," + - "§7indem diesen Rollen zugewiesen werden. Alle Regionen in" + - "§7einer Regions-Gruppe teilen diese Einstellungen." - # This item is used to select a region group. list_region_groups: - name: "§b§lSelect Region Group" + name: "§b§lRegions-Gruppe auswählen" lore: [] - # This item is a shortcut to select the region group of the region the player is standing in. - # %1$s: Region group name current_region_group: - name: "§b§lCurrent Region Group" + name: "§b§lAktuelle Regions-Gruppe" lore: - "" - - "§7Region Group: %1$s" + - "§7Regions-Gruppe: %1$s" - "" - - "§7Select the region group of the" - - "§7region you are standing in." + - "§7Wählt die Regions-Gruppe aus," + - "§7in der du dich gerade befindest." - select_region_group_title: "§8§lSelect Region Group" - filter_region_groups_title: "§8§lFilter Region Groups" - # This item is used to represent a region group in the selection menu. - # %1$s: Region group name + select_region_group_title: "§8§lRegions-Gruppe auswählen" + filter_region_groups_title: "§8§lRegions-Gruppen filtern" select_region_group: name: "%1$s" lore: [] - # Settings for the region menu. region: - # The title for the region menu. - # %1$s: Region name title: "§8§lRegion: %1$s" - # The item used to rename a region. rename: - name: "§b§lRename Region" + name: "§b§lRegion Umbenennen" lore: [] - # The item used to delete a region. delete: - name: "§c§lDelete Region" + name: "§c§lRegion Entfernen" lore: [] - # The title for the delete confirmation dialog. - delete_confirm_title: "§c§lDelete region?" - # The item to accept deleting. + delete_confirm_title: "§c§lRegion entfernen?" delete_confirm_accept: - name: "§c§lDELETE REGION" + name: "§c§lREGION ENTFERNEN" lore: [] - # The item to cancel deleting. delete_confirm_cancel: - name: "§a§lCancel" + name: "§a§lAbbrechen" lore: [] - # The item used to open the list of region groups to assign the region to one assign_region_group: - name: "§b§lAssign Group" + name: "§b§lGruppe zuweisen" lore: [] - select_region_group_title: "§8§lSelect Region Group" - filter_region_groups_title: "§8§lFilter Region Groups" - # The item used to represent a region group. - # %1$s: Region group name + select_region_group_title: "§8§lRegions-Gruppe auswählen" + filter_region_groups_title: "§8§lRegions-Gruppen filtern" select_region_group: name: "%1$s" lore: [] - # Settings for the region group menu. region_group: - # The title for the region group menu. - # %1$s: Region group name - title: "§8§lGroup: %1$s" + title: "§8§lGruppe: %1$s" setting_toggle_on: - name: "§a§lENABLED" + name: "§a§lAN" lore: [] setting_toggle_off: - name: "§c§lDISABLED" + name: "§c§lAUS" lore: [] setting_info_animals: - name: "§b§lAnimals" + name: "§b§lTiere" lore: - "" - - "§7Controls animal / neutral mob spawns." + - "§7Kontrolliert ob Tiere spawnen." setting_info_monsters: - name: "§b§lMonsters" + name: "§b§lMonster" lore: - "" - - "§7Controls monsters / hostile mob spawns." + - "§7Kontrolliert ob Monster / feindliche Mobs spawnen." setting_info_explosions: - name: "§b§lExplosions" + name: "§b§lExplosionen" lore: - "" - - "§7Controls all types of explosions." + - "§7Kontrolliert alle Arten von Explosionen." setting_info_fire: - name: "§b§lFire" + name: "§b§lFeuer" lore: - "" - - "§7Controls whether fire burns blocks and spreads." + - "§7Kontrolliert ob Feuer Blöcke verbrennt und sich verbreitet." setting_info_pvp: name: "§b§lPVP" lore: - "" - - "§7Controls whether PVP combat is allowed." + - "§7Kontrolliert ob PVP-Kämpfe möglich sind." setting_info_trample: - name: "§b§lTrampling" + name: "§b§lZertrampeln" lore: - "" - - "§7Controls whether farmland can be trampled." + - "§7Kontrolliert ob Acker zertrampelt werden können." setting_info_vine_growth: - name: "§b§lVine Growth" + name: "§b§lRanken" lore: - "" - - "§7Controls whether vines grow in the region." + - "§7Kontrolliert ob Ranken in dieser Region wachsen." - # The item used to rename a region group. rename: - name: "§b§lRename Group" + name: "§b§lGruppe Umbenennen" lore: [] - # The item used to delete a region group. - # %1$s: Checkmark: No region uses this group delete: - name: "§c§lDelete Group" + name: "§c§lGruppe Entfernen" lore: - "" - - "§6Deletion requirements:" - - "§7- %1$s §7No region uses this group" - # The title for the delete confirmation dialog. - delete_confirm_title: "§c§lDelete region group?" - # The item to accept deleting. + - "§6Vorraussetzungen:" + - "§7- %1$s §7Keine Region verwendet diese Gruppe" + delete_confirm_title: "§c§lRegions-Gruppe entfernen?" delete_confirm_accept: - name: "§c§lDELETE REGION GROUP" + name: "§c§lREGIONS-GRUPPE ENTFERNEN" lore: [] - # The item to cancel deleting. delete_confirm_cancel: - name: "§a§lCancel" + name: "§a§lAbbrechen" lore: [] - # This item is used to create a new role. create_role: - name: "§a§lCreate Role" + name: "§a§lRolle Erstellen" lore: - "" - - "§7Create a new §brole§7. Roles are" - - "§7to set permissions for groups of players." + - "§7Erstellt eine neue §bRolle§7. Rollen werden" + - "§7verwendet, um mehreren Spielern Rechte zuzuweisen." - # This item is used to open the role menu for a role. list_roles: - name: "§b§lRoles" + name: "§b§lRollen" lore: [] - select_role_title: "§8§lSelect Role" - filter_roles_title: "§8§lFilter Roles" - # This item is used to represent a role in the selection menu. - # %1$s: Role name + select_role_title: "§8§lRolle auswählen" + filter_roles_title: "§8§lRollen filtern" select_role: name: "%1$s" lore: [] - # Settings for the role menu. role: - # The title for the role menu. - # %1$s: Role name - title: "§8§lGroup: %1$s" + title: "§8§lGruppe: %1$s" setting_toggle_on: - name: "§a§lENABLED" + name: "§a§lAN" lore: [] setting_toggle_off: - name: "§c§lDISABLED" + name: "§c§lAUS" lore: [] setting_info_admin: name: "§b§lAdmin" lore: - "" - - "§7The admin flag cannot be toggled" - - "§7and is only set for the admin group." + - "§7Die Admin-berechtigung kann nicht geändert werden," + - "§7und ist nur für die Admin-gruppe aktiviert." setting_info_build: - name: "§b§lBuild" + name: "§b§lBauen" lore: - "" - - "§7Allows building and mining blocks." + - "§7Kontrolliert, ob Blöcke gesetzt und abgebaut werden können." setting_info_use: - name: "§b§lUse Things" + name: "§b§lDinge verwenden" lore: - "" - - "§7Allows using various things like doors," - - "§7levers, buttons or redstone components." - - "§7Also controls §6view-access§7 to inventories." + - "§7Kontrolliert, ob Dinge wie Türen, Schalter," + - "§7Knöpfe, Redstone-Komponenten, ... verwendet werden können." + - "§7Kontrolliert außerdem §6Lese-Zugriff§7 auf Inventare." setting_info_container: - name: "§b§lContainers" + name: "§b§lInventare" lore: - "" - - "§7Allows interaction with inventories." - - "§7Without this flag, nothing can be taken" - - "§7from or put into inventories." + - "§7Erlaubt modifizierende Interaktion mit Inventaren." + - "§7Ohne diese Einstellung kann nichts aus Inventaren" + - "§7genommen oder hineingelegt werden." setting_info_portal: - name: "§b§lUse Portals" + name: "§b§lPortale Verwenden" lore: - "" - - "§7Allows interacting with portals." + - "§7Kontrolliert, ob mit Portalen interagiert werden kann." - # The item used to rename a role. rename: - name: "§b§lRename Role" + name: "§b§lRolle Umbenennen" lore: [] - # The item used to delete a role. delete: - name: "§c§lDelete Role" + name: "§c§lRolle Entfernen" lore: [] - # The title for the delete confirmation dialog. - delete_confirm_title: "§c§lDelete role?" - # The item to accept deleting. + delete_confirm_title: "§c§lRolle entfernen?" delete_confirm_accept: - name: "§c§lDELETE ROLE" + name: "§c§lROLLE ENTFERNEN" lore: [] - # The item to cancel deleting. delete_confirm_cancel: - name: "§a§lCancel" + name: "§a§lAbbrechen" lore: [] - # This item is used to open the player assignment menu for a role. assign_player: - name: "§b§lAssign Players" + name: "§b§lSpieler Zuweisen" lore: - "" - - "§7Assign players to this role by clicking on them." - - "§7If the player had a different role before, they will" - - "§7be reassigned to this role. The list will only show" - - "§7players that are not already assigned to this role." - - "§7You can remove players by using the §bRemove Player§7 menu." - # This item is used to open the player removing menu for a role. + - "§7Weise Spieler dieser Rolle zu, indem du sie anklickst." + - "§7Wenn ein Spieler vorher einer andere Rolle zugewiesen war," + - "§7wird seine Zuweisung zu dieser Rolle geändert. Diese Liste zeigt" + - "§7nur Spieler, welche nicht bereits dieser Rolle zugewiesen sind. Du kannst" + - "§7Spieler wieder entfernen indem du das §bSpieler Entfernen§7 Menü verwendest." remove_player: - name: "§b§lRemove Players" + name: "§b§lSpieler Entfernen" lore: - "" - - "§7Remove players from this role by clicking on them." - - "§7This means they will have no assigned role afterwards" - - "§7and will be handled by the catch-all role §6[others]" - - select_assign_player_title: "§8§lAssign Players" - select_remove_player_title: "§8§lRemove Players" - filter_players_title: "§8§lFilter Players" - # This item is used to represent a player in the selection menu. - # %1$s: Player name + - "§7Entferne Spieler von dieser Rolle, indem du sie anklickst." + - "§7Dies bedeutet, dass diesen danach keine Rolle zugewiesen ist" + - "§7und sie von der Auffang-Rolle §6[others]§7 verwaltet werden." + + select_assign_player_title: "§8§lSpieler zuweisen" + select_remove_player_title: "§8§lSpieler entfernen" + filter_players_title: "§8§lSpieler filtern" select_player: name: "%1$s" lore: [] diff --git a/vane-regions/src/main/resources/lang-en.yml b/vane-regions/src/main/resources/lang-en.yml index 80ed76eff..483f5ffcd 100644 --- a/vane-regions/src/main/resources/lang-en.yml +++ b/vane-regions/src/main/resources/lang-en.yml @@ -242,12 +242,12 @@ menus: name: "§b§lAnimals" lore: - "" - - "§7Controls animal / neutral mob spawns." + - "§7Controls animal mob spawns." setting_info_monsters: name: "§b§lMonsters" lore: - "" - - "§7Controls monsters / hostile mob spawns." + - "§7Controls monsters (hostile mob) spawns." setting_info_explosions: name: "§b§lExplosions" lore: @@ -303,7 +303,7 @@ menus: name: "§a§lCreate Role" lore: - "" - - "§7Create a new §brole§7. Roles are" + - "§7Create a new §brole§7. Roles are used" - "§7to set permissions for groups of players." # This item is used to open the role menu for a role. @@ -353,7 +353,7 @@ menus: name: "§b§lContainers" lore: - "" - - "§7Allows interaction with inventories." + - "§7Allows modifying interactions with inventories." - "§7Without this flag, nothing can be taken" - "§7from or put into inventories." setting_info_portal: @@ -401,9 +401,9 @@ menus: - "§7This means they will have no assigned role afterwards" - "§7and will be handled by the catch-all role §6[others]" - select_assign_player_title: "§8§lAssign Players" - select_remove_player_title: "§8§lRemove Players" - filter_players_title: "§8§lFilter Players" + select_assign_player_title: "§8§lAssign players" + select_remove_player_title: "§8§lRemove players" + filter_players_title: "§8§lFilter players" # This item is used to represent a player in the selection menu. # %1$s: Player name select_player: From f59b5d668f910737eb16306beff96aaadd05264d Mon Sep 17 00:00:00 2001 From: oddlama Date: Tue, 16 Mar 2021 21:32:44 +0100 Subject: [PATCH 29/40] Open main menu after closing region menu --- .../main/java/org/oddlama/vane/regions/menu/RegionMenu.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RegionMenu.java b/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RegionMenu.java index beae1a831..e8c77c45d 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RegionMenu.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RegionMenu.java @@ -67,6 +67,11 @@ public Menu create(final Region region, final Player player) { region_menu.add(menu_item_assign_region_group(region)); } + region_menu.on_natural_close(player2 -> + get_module().menus.main_menu + .create(player2) + .open(player2)); + return region_menu; } From 132eb12d0d2db438c8c36da3457c751f633a0bc1 Mon Sep 17 00:00:00 2001 From: oddlama Date: Tue, 16 Mar 2021 21:55:13 +0100 Subject: [PATCH 30/40] Dust Options fixed --- .../src/main/java/org/oddlama/vane/regions/Regions.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/Regions.java b/vane-regions/src/main/java/org/oddlama/vane/regions/Regions.java index 61d04fb6f..05a229177 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/Regions.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/Regions.java @@ -222,9 +222,8 @@ public RegionSelection get_region_selection(final Player player) { private static final int visualize_max_particels = 20000; private static final int visualize_particles_per_block = 12; private static final double visualize_stddev_compensation = 0.25; - // TODO color ded - private static final DustOptions visualize_dust_invalid = new DustOptions(Color.fromRGB(200, 60, 11), 0.0f); - private static final DustOptions visualize_dust_valid = new DustOptions(Color.fromRGB(120, 220, 60), 0.0f); + private static final DustOptions visualize_dust_invalid = new DustOptions(Color.fromRGB(220, 60, 11), 1.0f); + private static final DustOptions visualize_dust_valid = new DustOptions(Color.fromRGB(120, 220, 60), 1.0f); private void visualize_edge(final World world, final BlockPosition c1, final BlockPosition c2, final boolean valid) { // Unfortunately, particle spawns are normal distributed. From 1a993ffd2eb4951f0f5dfd711b1bde3f0fe37eb9 Mon Sep 17 00:00:00 2001 From: oddlama Date: Tue, 16 Mar 2021 22:00:59 +0100 Subject: [PATCH 31/40] Fix null check on target portal permission check --- .../org/oddlama/vane/regions/RegionRoleSettingEnforcer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/RegionRoleSettingEnforcer.java b/vane-regions/src/main/java/org/oddlama/vane/regions/RegionRoleSettingEnforcer.java index 5b7fdc275..ddc646fe6 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/RegionRoleSettingEnforcer.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/RegionRoleSettingEnforcer.java @@ -352,7 +352,7 @@ public void on_portal_select_target(final PortalSelectTargetEvent event) { } // Check permission on target portal - if (check_setting_at(event.getTarget().spawn(), event.getPlayer(), RoleSetting.PORTAL, false)) { + if (event.getTarget() != null && event.getTarget().spawn(), event.getPlayer(), RoleSetting.PORTAL, false)) { event.setCancelled(true); return; } From 012e47439ebdd25f90445fc038d261a5b14e9c9b Mon Sep 17 00:00:00 2001 From: oddlama Date: Tue, 16 Mar 2021 22:05:07 +0100 Subject: [PATCH 32/40] Fix deleted syntax token --- .../org/oddlama/vane/regions/RegionRoleSettingEnforcer.java | 2 +- .../src/main/java/org/oddlama/vane/regions/Regions.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/RegionRoleSettingEnforcer.java b/vane-regions/src/main/java/org/oddlama/vane/regions/RegionRoleSettingEnforcer.java index ddc646fe6..f44b9d893 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/RegionRoleSettingEnforcer.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/RegionRoleSettingEnforcer.java @@ -352,7 +352,7 @@ public void on_portal_select_target(final PortalSelectTargetEvent event) { } // Check permission on target portal - if (event.getTarget() != null && event.getTarget().spawn(), event.getPlayer(), RoleSetting.PORTAL, false)) { + if (event.getTarget() != null && check_setting_at(event.getTarget().spawn(), event.getPlayer(), RoleSetting.PORTAL, false)) { event.setCancelled(true); return; } diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/Regions.java b/vane-regions/src/main/java/org/oddlama/vane/regions/Regions.java index 05a229177..4a5201e41 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/Regions.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/Regions.java @@ -222,7 +222,7 @@ public RegionSelection get_region_selection(final Player player) { private static final int visualize_max_particels = 20000; private static final int visualize_particles_per_block = 12; private static final double visualize_stddev_compensation = 0.25; - private static final DustOptions visualize_dust_invalid = new DustOptions(Color.fromRGB(220, 60, 11), 1.0f); + private static final DustOptions visualize_dust_invalid = new DustOptions(Color.fromRGB(230, 60, 11), 1.0f); private static final DustOptions visualize_dust_valid = new DustOptions(Color.fromRGB(120, 220, 60), 1.0f); private void visualize_edge(final World world, final BlockPosition c1, final BlockPosition c2, final boolean valid) { From 3cb99e4acc093b8375fabc4af5fece014778f633 Mon Sep 17 00:00:00 2001 From: oddlama Date: Tue, 16 Mar 2021 22:20:23 +0100 Subject: [PATCH 33/40] - Deny OpenConsole -> dont get enchantment table menu. - Fix NPE in region portal check - Show name of player in their default group - Owner may always administrate their portals --- .../oddlama/vane/portals/PortalActivator.java | 5 ++-- .../regions/RegionRoleSettingEnforcer.java | 25 +++++++++++++++++++ .../org/oddlama/vane/regions/Regions.java | 16 ++++++++---- .../vane/regions/menu/RegionGroupMenu.java | 4 +-- 4 files changed, 41 insertions(+), 9 deletions(-) diff --git a/vane-portals/src/main/java/org/oddlama/vane/portals/PortalActivator.java b/vane-portals/src/main/java/org/oddlama/vane/portals/PortalActivator.java index 389912f7f..1927d335f 100644 --- a/vane-portals/src/main/java/org/oddlama/vane/portals/PortalActivator.java +++ b/vane-portals/src/main/java/org/oddlama/vane/portals/PortalActivator.java @@ -40,12 +40,13 @@ public void on_player_interact_console(final PlayerInteractEvent event) { return; } + event.setUseInteractedBlock(Event.Result.DENY); + event.setUseItemInHand(Event.Result.DENY); + final var player = event.getPlayer(); final var portal = get_module().portal_for(portal_block); if (portal.open_console(get_module(), player, block)) { swing_arm(player, event.getHand()); - event.setUseInteractedBlock(Event.Result.DENY); - event.setUseItemInHand(Event.Result.DENY); } } diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/RegionRoleSettingEnforcer.java b/vane-regions/src/main/java/org/oddlama/vane/regions/RegionRoleSettingEnforcer.java index f44b9d893..6c678efc7 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/RegionRoleSettingEnforcer.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/RegionRoleSettingEnforcer.java @@ -287,6 +287,11 @@ public void on_portal_construct(final PortalConstructEvent event) { @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) public void on_portal_destroy(final PortalDestroyEvent event) { + if (event.getPortal().owner().equals(event.getPlayer().getUniqueId())) { + // Owner may always use their portals + return; + } + // We do NOT have to check all blocks here, because // an existing portal with its spawn inside a region // that the player controls can be considered proof of authority. @@ -298,6 +303,11 @@ public void on_portal_destroy(final PortalDestroyEvent event) { @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) public void on_portal_link_console(final PortalLinkConsoleEvent event) { + if (event.getPortal() != null && event.getPortal().owner().equals(event.getPlayer().getUniqueId())) { + // Owner may always use their portals + return; + } + // Portals in regions may only be administrated by region administrators // Check permission on console if (check_setting_at(event.getConsole(), event.getPlayer(), RoleSetting.ADMIN, false)) { @@ -314,6 +324,11 @@ public void on_portal_link_console(final PortalLinkConsoleEvent event) { @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) public void on_portal_unlink_console(final PortalUnlinkConsoleEvent event) { + if (event.getPortal().owner().equals(event.getPlayer().getUniqueId())) { + // Owner may always use their portals + return; + } + // Portals in regions may only be administrated by region administrators // Check permission on console if (check_setting_at(event.getConsole(), event.getPlayer(), RoleSetting.ADMIN, false)) { @@ -330,6 +345,11 @@ public void on_portal_unlink_console(final PortalUnlinkConsoleEvent event) { @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) public void on_portal_open_console(final PortalOpenConsoleEvent event) { + if (event.getPortal().owner().equals(event.getPlayer().getUniqueId())) { + // Owner may always use their portals + return; + } + // Check permission on console if (check_setting_at(event.getConsole(), event.getPlayer(), RoleSetting.PORTAL, false)) { event.setCancelled(true); @@ -345,6 +365,11 @@ public void on_portal_open_console(final PortalOpenConsoleEvent event) { @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) public void on_portal_select_target(final PortalSelectTargetEvent event) { + if (event.getPortal().owner().equals(event.getPlayer().getUniqueId())) { + // Owner may always use their portals + return; + } + // Check permission on source portal if (check_setting_at(event.getPortal().spawn(), event.getPlayer(), RoleSetting.PORTAL, false)) { event.setCancelled(true); diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/Regions.java b/vane-regions/src/main/java/org/oddlama/vane/regions/Regions.java index 4a5201e41..3900c727f 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/Regions.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/Regions.java @@ -183,9 +183,14 @@ public void on_enable() { portals.set_regions_group_visible_callback((src, dst) -> { final var reg_dst = region_at(dst.spawn()); if (reg_dst == null) { + // Destination has group -> show all return true; } final var reg_src = region_at(src.spawn()); + if (reg_src == null) { + // Can't look inside groups from outside + return false; + } return reg_dst.region_group_id().equals(reg_src.region_group_id()); }); @@ -388,7 +393,7 @@ public boolean create_region_from_selection(final Player player, final String na return false; } - final var def_region_group = get_or_create_default_region_group(player.getUniqueId()); + final var def_region_group = get_or_create_default_region_group(player); final var region = new Region(name, player.getUniqueId(), selection.extent(), def_region_group.id()); add_region(region); cancel_region_selection(player); @@ -531,18 +536,19 @@ public Region region_at(final Block block) { return null; } - public RegionGroup get_or_create_default_region_group(final UUID owner) { - final var region_group_id = storage_default_region_group.get(owner); + public RegionGroup get_or_create_default_region_group(final Player owner) { + final var owner_id = owner.getUniqueId(); + final var region_group_id = storage_default_region_group.get(owner_id); if (region_group_id != null) { return get_region_group(region_group_id); } // Create and save owners's default group - final var region_group = new RegionGroup("[default]", owner); + final var region_group = new RegionGroup("[default] " + owner.getName(), owner_id); add_region_group(region_group); // Set group as the default - storage_default_region_group.put(owner, region_group.id()); + storage_default_region_group.put(owner_id, region_group.id()); mark_persistent_storage_dirty(); return region_group; diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RegionGroupMenu.java b/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RegionGroupMenu.java index e5da42f93..bc53cb4e0 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RegionGroupMenu.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RegionGroupMenu.java @@ -87,7 +87,7 @@ public Menu create(final RegionGroup group, final Player player) { if (is_owner) { region_group_menu.add(menu_item_rename(group)); // Delete only if this isn't the default group - if (!get_module().get_or_create_default_region_group(player.getUniqueId()).id().equals(group.id())) { + if (!get_module().get_or_create_default_region_group(player).id().equals(group.id())) { region_group_menu.add(menu_item_delete(group)); } } @@ -146,7 +146,7 @@ private MenuWidget menu_item_delete(final RegionGroup group) { } // Assert that this isn't the default group - if (get_module().get_or_create_default_region_group(player2.getUniqueId()).id().equals(group.id())) { + if (get_module().get_or_create_default_region_group(player2).id().equals(group.id())) { return ClickResult.ERROR; } From ad13bb90abd1a6aa5cc80b4c676eee6efcad3b7c Mon Sep 17 00:00:00 2001 From: oddlama Date: Tue, 16 Mar 2021 22:45:27 +0100 Subject: [PATCH 34/40] Implemented additional portal visibility GROUP_INTERNAL (vs GROUP), the former allows only portals in the same region to see each outher, while the latter allows people with portal use permission in the same region to see the portal --- .../org/oddlama/vane/portals/Portals.java | 72 ++++++++++++------- .../vane/portals/menu/ConsoleMenu.java | 8 ++- .../vane/portals/menu/SettingsMenu.java | 27 +++---- .../oddlama/vane/portals/portal/Portal.java | 5 ++ vane-portals/src/main/resources/lang-de.yml | 8 ++- vane-portals/src/main/resources/lang-en.yml | 9 ++- .../org/oddlama/vane/regions/Regions.java | 25 ++++--- 7 files changed, 101 insertions(+), 53 deletions(-) diff --git a/vane-portals/src/main/java/org/oddlama/vane/portals/Portals.java b/vane-portals/src/main/java/org/oddlama/vane/portals/Portals.java index 009a75232..fc43f9539 100644 --- a/vane-portals/src/main/java/org/oddlama/vane/portals/Portals.java +++ b/vane-portals/src/main/java/org/oddlama/vane/portals/Portals.java @@ -12,6 +12,7 @@ import org.oddlama.vane.core.functional.Function2; import java.util.ArrayList; import java.util.Collection; +import org.bukkit.entity.Player; import java.util.HashMap; import java.util.HashSet; import java.util.Map; @@ -64,7 +65,7 @@ import org.oddlama.vane.portals.portal.PortalBlockLookup; import org.oddlama.vane.portals.portal.Style; -@VaneModule(name = "portals", bstats = 8642, config_version = 1, lang_version = 1, storage_version = 1) +@VaneModule(name = "portals", bstats = 8642, config_version = 2, lang_version = 2, storage_version = 2) public class Portals extends Module { // Add (de-)serializers static { @@ -182,6 +183,8 @@ public Portals() { constructor = new PortalConstructor(this); new PortalTeleporter(this); dynmap_layer = new PortalDynmapLayer(this); + + persistent_storage_manager.add_migration_to(2, "Portal visibility GROUP_INTERNAL was added. This is a no-op.", (json) -> {}); } @SuppressWarnings("unchecked") @@ -235,23 +238,35 @@ public void on_config_change() { } } - // A lightweight callback to the regions module, if it is installed. + // Lightweight callbacks to the regions module, if it is installed. // Lifting the callback storage into the portals module saves us // from having to ship regions api with this module. - private Function2 regions_group_visible_callback = null; - public void set_regions_group_visible_callback(final Function2 callback) { - regions_group_visible_callback = callback; + private Function2 is_in_same_region_group_callback = null; + public void set_is_in_same_region_group_callback(final Function2 callback) { + is_in_same_region_group_callback = callback; + } + + private Function2 player_can_use_portals_in_region_group_of_callback = null; + public void set_player_can_use_portals_in_region_group_of_callback(final Function2 callback) { + player_can_use_portals_in_region_group_of_callback = callback; + } + + public boolean is_in_same_region_group(final Portal a, final Portal b) { + if (is_in_same_region_group_callback == null) { + return true; + } + return is_in_same_region_group_callback.apply(a, b); } - public boolean is_regions_group_visible(final Portal src, final Portal dst) { - if (regions_group_visible_callback == null) { + public boolean player_can_use_portals_in_region_group_of(final Player player, final Portal portal) { + if (player_can_use_portals_in_region_group_of_callback == null) { return true; } - return regions_group_visible_callback.apply(src, dst); + return player_can_use_portals_in_region_group_of_callback.apply(player, portal); } public boolean is_regions_installed() { - return regions_group_visible_callback != null; + return is_in_same_region_group_callback != null; } public Style style(final NamespacedKey key) { @@ -554,12 +569,12 @@ public void disconnect_portals(final Portal src, final Portal dst) { src.on_disconnect(this, dst); dst.on_disconnect(this, src); - // Reset target id's if the target portal was private - if (dst.visibility() == Portal.Visibility.PRIVATE) { + // Reset target id's if the target portal was transient + if (dst.visibility().is_transient_target()) { src.target_id(null); mark_persistent_storage_dirty(); } - if (src.visibility() == Portal.Visibility.PRIVATE) { + if (src.visibility().is_transient_target()) { dst.target_id(null); mark_persistent_storage_dirty(); } @@ -674,20 +689,29 @@ public void update_portal_icon(final Portal portal) { public void update_portal_visibility(final Portal portal) { // Replace references to the portal everywhere, if visibility // has changed. - if (portal.visibility() == Portal.Visibility.PRIVATE) { - for (final var other : storage_portals.values()) { - if (Objects.equals(other.target_id(), portal.id())) { - other.target_id(null); + switch (portal.visibility()) { + case PRIVATE: + case GROUP: + // Not visible from outside, these are transient. + for (final var other : storage_portals.values()) { + if (Objects.equals(other.target_id(), portal.id())) { + other.target_id(null); + } } - } - } else if (portal.visibility() == Portal.Visibility.GROUP) { - // Remove from portals outside of the group - for (final var other : storage_portals.values()) { - if (Objects.equals(other.target_id(), portal.id()) && - !is_regions_group_visible(other, portal)) { - other.target_id(null); + break; + + case GROUP_INTERNAL: + // Remove from portals outside of the group + for (final var other : storage_portals.values()) { + if (Objects.equals(other.target_id(), portal.id()) && + !is_in_same_region_group(other, portal)) { + other.target_id(null); + } } - } + break; + + default: // Nothing to do + break; } // Update dynmap marker diff --git a/vane-portals/src/main/java/org/oddlama/vane/portals/menu/ConsoleMenu.java b/vane-portals/src/main/java/org/oddlama/vane/portals/menu/ConsoleMenu.java index 8e4315000..fb0bc4768 100644 --- a/vane-portals/src/main/java/org/oddlama/vane/portals/menu/ConsoleMenu.java +++ b/vane-portals/src/main/java/org/oddlama/vane/portals/menu/ConsoleMenu.java @@ -5,6 +5,7 @@ import java.util.Objects; import java.util.stream.Collectors; +import org.bukkit.entity.Player; import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.block.Block; @@ -125,9 +126,10 @@ private MenuWidget menu_item_select_target(final Portal portal) { .stream() .filter(p -> { switch (p.visibility()) { - case PUBLIC: return true; - case GROUP: return get_module().is_regions_group_visible(portal, p); - case PRIVATE: return player.getUniqueId().equals(p.owner()); + case PUBLIC: return true; + case GROUP: return get_module().player_can_use_portals_in_region_group_of(player, p); + case GROUP_INTERNAL: return get_module().is_in_same_region_group(portal, p); + case PRIVATE: return player.getUniqueId().equals(p.owner()); } return false; }) diff --git a/vane-portals/src/main/java/org/oddlama/vane/portals/menu/SettingsMenu.java b/vane-portals/src/main/java/org/oddlama/vane/portals/menu/SettingsMenu.java index 8c5cfcb40..cc4ad450f 100644 --- a/vane-portals/src/main/java/org/oddlama/vane/portals/menu/SettingsMenu.java +++ b/vane-portals/src/main/java/org/oddlama/vane/portals/menu/SettingsMenu.java @@ -32,6 +32,7 @@ public class SettingsMenu extends ModuleComponent { public TranslatedItemStack item_select_style; public TranslatedItemStack item_visibility_public; public TranslatedItemStack item_visibility_group; + public TranslatedItemStack item_visibility_group_internal; public TranslatedItemStack item_visibility_private; public TranslatedItemStack item_target_lock_on; public TranslatedItemStack item_target_lock_off; @@ -41,15 +42,16 @@ public SettingsMenu(Context context) { super(context.namespace("settings")); final var ctx = get_context(); - item_rename = new TranslatedItemStack<>(ctx, "rename", Material.NAME_TAG, 1, "Used to rename the portal."); - item_select_icon = new TranslatedItemStack<>(ctx, "select_icon", namespaced_key("vane", "decoration_end_portal_orb"), 1, "Used to select the portal's icon."); - item_select_style = new TranslatedItemStack<>(ctx, "select_style", Material.ITEM_FRAME, 1, "Used to change the portal's style."); - item_visibility_public = new TranslatedItemStack<>(ctx, "visibility_public", Material.ENDER_EYE, 1, "Used to change and indicate public visibility."); - item_visibility_group = new TranslatedItemStack<>(ctx, "visibility_group", Material.ENDER_PEARL, 1, "Used to change and indicate group visibility."); - item_visibility_private = new TranslatedItemStack<>(ctx, "visibility_private", Material.FIREWORK_STAR, 1, "Used to change and indicate private visibility."); - item_target_lock_on = new TranslatedItemStack<>(ctx, "target_lock_on", Material.SLIME_BALL, 1, "Used to toggle and indicate enabled target lock."); - item_target_lock_off = new TranslatedItemStack<>(ctx, "target_lock_off", Material.SNOWBALL, 1, "Used to toggle and indicate disabled target lock."); - item_back = new TranslatedItemStack<>(ctx, "back", Material.PRISMARINE_SHARD, 1, "Used to go back to the previous menu."); + item_rename = new TranslatedItemStack<>(ctx, "rename", Material.NAME_TAG, 1, "Used to rename the portal."); + item_select_icon = new TranslatedItemStack<>(ctx, "select_icon", namespaced_key("vane", "decoration_end_portal_orb"), 1, "Used to select the portal's icon."); + item_select_style = new TranslatedItemStack<>(ctx, "select_style", Material.ITEM_FRAME, 1, "Used to change the portal's style."); + item_visibility_public = new TranslatedItemStack<>(ctx, "visibility_public", Material.ENDER_EYE, 1, "Used to change and indicate public visibility."); + item_visibility_group = new TranslatedItemStack<>(ctx, "visibility_group", Material.ENDER_PEARL, 1, "Used to change and indicate group visibility."); + item_visibility_group_internal = new TranslatedItemStack<>(ctx, "visibility_group_internal", Material.FIRE_CHARGE, 1, "Used to change and indicate group internal visibility."); + item_visibility_private = new TranslatedItemStack<>(ctx, "visibility_private", Material.FIREWORK_STAR, 1, "Used to change and indicate private visibility."); + item_target_lock_on = new TranslatedItemStack<>(ctx, "target_lock_on", Material.SLIME_BALL, 1, "Used to toggle and indicate enabled target lock."); + item_target_lock_off = new TranslatedItemStack<>(ctx, "target_lock_off", Material.SNOWBALL, 1, "Used to toggle and indicate disabled target lock."); + item_back = new TranslatedItemStack<>(ctx, "back", Material.PRISMARINE_SHARD, 1, "Used to go back to the previous menu."); } // HINT: We don't capture the previous menu and open a new one on exit, @@ -171,9 +173,10 @@ private MenuWidget menu_item_visibility(final Portal portal) { @Override public void item(final ItemStack item) { switch (portal.visibility()) { - case PUBLIC: super.item(item_visibility_public.item()); break; - case GROUP: super.item(item_visibility_group.item()); break; - case PRIVATE: super.item(item_visibility_private.item()); break; + case PUBLIC: super.item(item_visibility_public.item()); break; + case GROUP: super.item(item_visibility_group.item()); break; + case GROUP_INTERNAL: super.item(item_visibility_group_internal.item()); break; + case PRIVATE: super.item(item_visibility_private.item()); break; } } }; diff --git a/vane-portals/src/main/java/org/oddlama/vane/portals/portal/Portal.java b/vane-portals/src/main/java/org/oddlama/vane/portals/portal/Portal.java index e4bc207fa..ce0b2f223 100644 --- a/vane-portals/src/main/java/org/oddlama/vane/portals/portal/Portal.java +++ b/vane-portals/src/main/java/org/oddlama/vane/portals/portal/Portal.java @@ -323,6 +323,7 @@ public String toString() { public static enum Visibility { PUBLIC, GROUP, + GROUP_INTERNAL, PRIVATE; public Visibility prev() { @@ -339,6 +340,10 @@ public Visibility next() { final var next = (ordinal() + 1) % values().length; return values()[next]; } + + public boolean is_transient_target() { + return this == GROUP || this == PRIVATE; + } } public static class TargetSelectionComparator implements Comparator { diff --git a/vane-portals/src/main/resources/lang-de.yml b/vane-portals/src/main/resources/lang-de.yml index 26e21da59..2d2b6c56b 100644 --- a/vane-portals/src/main/resources/lang-de.yml +++ b/vane-portals/src/main/resources/lang-de.yml @@ -12,7 +12,7 @@ # DO NOT CHANGE! The version of this language file. Used to determine # if the file needs to be updated. -version: 1 +version: 2 # The corresponding language code used in resource packs. Used for # resource pack generation. Typically this is a combination of the # language code (ISO 639) and the country code (ISO 3166). @@ -81,7 +81,11 @@ menus: visibility_group: name: "§b§lSichtbarkeit umschalten" - lore: ["", "§bAktuell: §e§lGruppe§r"] + lore: ["", "§bAktuell: §e§lGruppe (Mitglieder)§r"] + + visibility_group_internal: + name: "§b§lSichtbarkeit umschalten" + lore: ["", "§bAktuell: §e§lGruppe (Nur intern sichtbar)§r"] visibility_private: name: "§b§lSichtbarkeit umschalten" diff --git a/vane-portals/src/main/resources/lang-en.yml b/vane-portals/src/main/resources/lang-en.yml index ad36cbeea..a847f9341 100644 --- a/vane-portals/src/main/resources/lang-en.yml +++ b/vane-portals/src/main/resources/lang-en.yml @@ -12,7 +12,7 @@ # DO NOT CHANGE! The version of this language file. Used to determine # if the file needs to be updated. -version: 1 +version: 2 # The corresponding language code used in resource packs. Used for # resource pack generation. Typically this is a combination of the # language code (ISO 639) and the country code (ISO 3166). @@ -135,7 +135,12 @@ menus: # This item is used to cycle visibility and indicate group visibility. visibility_group: name: "§b§lToggle Visibility" - lore: ["", "§bCurrent: §e§lRegion Group§r"] + lore: ["", "§bCurrent: §e§lRegion Group (members)§r"] + + # This item is used to cycle visibility and indicate group visibility. + visibility_group_internal: + name: "§b§lToggle Visibility" + lore: ["", "§bCurrent: §e§lRegion Group (only visible internally)§r"] # This item is used to cycle visibility and indicate private visibility. visibility_private: diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/Regions.java b/vane-regions/src/main/java/org/oddlama/vane/regions/Regions.java index 3900c727f..f829e81b4 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/Regions.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/Regions.java @@ -180,18 +180,23 @@ public void on_enable() { // Register callback to portals module so portals // can find out if two portals are in the same region group - portals.set_regions_group_visible_callback((src, dst) -> { - final var reg_dst = region_at(dst.spawn()); - if (reg_dst == null) { - // Destination has group -> show all - return true; + portals.set_is_in_same_region_group_callback((a, b) -> { + final var reg_a = region_at(a.spawn()); + final var reg_b = region_at(b.spawn()); + if (reg_a == null || reg_b == null) { + return reg_a == reg_b; } - final var reg_src = region_at(src.spawn()); - if (reg_src == null) { - // Can't look inside groups from outside - return false; + return reg_a.region_group_id().equals(reg_b.region_group_id()); + }); + + portals.set_player_can_use_portals_in_region_group_of_callback((player, portal) -> { + final var region = region_at(portal.spawn()); + if (region == null) { + // No region -> no restriction. + return true; } - return reg_dst.region_group_id().equals(reg_src.region_group_id()); + final var group = region.region_group(get_module()); + return group.get_role(player.getUniqueId()).get_setting(RoleSetting.PORTAL); }); schedule_next_tick(this::delayed_on_enable); From 992492170519c74e5b122e702e51f9842a21b49e Mon Sep 17 00:00:00 2001 From: oddlama Date: Tue, 16 Mar 2021 22:52:04 +0100 Subject: [PATCH 35/40] Owners may get into their portal settings anytime. --- .../org/oddlama/vane/regions/RegionRoleSettingEnforcer.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/RegionRoleSettingEnforcer.java b/vane-regions/src/main/java/org/oddlama/vane/regions/RegionRoleSettingEnforcer.java index 6c678efc7..d47dee8b0 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/RegionRoleSettingEnforcer.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/RegionRoleSettingEnforcer.java @@ -385,6 +385,11 @@ public void on_portal_select_target(final PortalSelectTargetEvent event) { @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) public void on_portal_change_settings(final PortalChangeSettingsEvent event) { + if (event.getPortal().owner().equals(event.getPlayer().getUniqueId())) { + // Owner may always use their portals + return; + } + final var region = get_module().region_at(event.getPortal().spawn()); if (region == null) { return; From b079d707e495d1081a437f06525ff926ef25239d Mon Sep 17 00:00:00 2001 From: oddlama Date: Tue, 16 Mar 2021 22:53:59 +0100 Subject: [PATCH 36/40] Skip all group visibilities if region is not installed --- .../main/java/org/oddlama/vane/portals/menu/SettingsMenu.java | 2 +- .../src/main/java/org/oddlama/vane/portals/portal/Portal.java | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/vane-portals/src/main/java/org/oddlama/vane/portals/menu/SettingsMenu.java b/vane-portals/src/main/java/org/oddlama/vane/portals/menu/SettingsMenu.java index cc4ad450f..72f7ae899 100644 --- a/vane-portals/src/main/java/org/oddlama/vane/portals/menu/SettingsMenu.java +++ b/vane-portals/src/main/java/org/oddlama/vane/portals/menu/SettingsMenu.java @@ -162,7 +162,7 @@ private MenuWidget menu_item_visibility(final Portal portal) { // If regions is not installed, we need to skip group visibility. do { new_vis = event.getClick() == ClickType.RIGHT ? portal.visibility().prev() : portal.visibility().next(); - } while (new_vis == Portal.Visibility.GROUP && !get_module().is_regions_installed()); + } while (new_vis.requires_regions() && !get_module().is_regions_installed()); portal.visibility(new_vis); get_module().update_portal_visibility(portal); diff --git a/vane-portals/src/main/java/org/oddlama/vane/portals/portal/Portal.java b/vane-portals/src/main/java/org/oddlama/vane/portals/portal/Portal.java index ce0b2f223..39abe3032 100644 --- a/vane-portals/src/main/java/org/oddlama/vane/portals/portal/Portal.java +++ b/vane-portals/src/main/java/org/oddlama/vane/portals/portal/Portal.java @@ -344,6 +344,10 @@ public Visibility next() { public boolean is_transient_target() { return this == GROUP || this == PRIVATE; } + + public boolean requires_regions() { + return this == GROUP || this == GROUP_INTERNAL; + } } public static class TargetSelectionComparator implements Comparator { From 1834251dcf46a72ca2e4de2e6278890f13637111 Mon Sep 17 00:00:00 2001 From: oddlama Date: Tue, 16 Mar 2021 22:59:18 +0100 Subject: [PATCH 37/40] Update portal consoles after transient target deletion --- .../src/main/java/org/oddlama/vane/portals/Portals.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/vane-portals/src/main/java/org/oddlama/vane/portals/Portals.java b/vane-portals/src/main/java/org/oddlama/vane/portals/Portals.java index fc43f9539..b231a40d5 100644 --- a/vane-portals/src/main/java/org/oddlama/vane/portals/Portals.java +++ b/vane-portals/src/main/java/org/oddlama/vane/portals/Portals.java @@ -572,10 +572,12 @@ public void disconnect_portals(final Portal src, final Portal dst) { // Reset target id's if the target portal was transient if (dst.visibility().is_transient_target()) { src.target_id(null); + src.update_blocks(this); mark_persistent_storage_dirty(); } if (src.visibility().is_transient_target()) { dst.target_id(null); + dst.update_blocks(this); mark_persistent_storage_dirty(); } From dfa1c5c3fc1e3b6165f0032321aaf0d761536336 Mon Sep 17 00:00:00 2001 From: oddlama Date: Tue, 16 Mar 2021 23:11:18 +0100 Subject: [PATCH 38/40] Well if we ignore cancelled events we cant uncancel them lel --- .../regions/RegionRoleSettingEnforcer.java | 24 +++++++++++++------ 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/RegionRoleSettingEnforcer.java b/vane-regions/src/main/java/org/oddlama/vane/regions/RegionRoleSettingEnforcer.java index d47dee8b0..91a9be3e6 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/RegionRoleSettingEnforcer.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/RegionRoleSettingEnforcer.java @@ -301,13 +301,19 @@ public void on_portal_destroy(final PortalDestroyEvent event) { } } - @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = false) public void on_portal_link_console(final PortalLinkConsoleEvent event) { if (event.getPortal() != null && event.getPortal().owner().equals(event.getPlayer().getUniqueId())) { // Owner may always use their portals return; } + if (get_module().region_at(event.getPortal().spawn()) != null) { + // Portals in regions may be administrated by region administrators, + // not only be the owner + event.setCancelIfNotOwner(false); + } + // Portals in regions may only be administrated by region administrators // Check permission on console if (check_setting_at(event.getConsole(), event.getPlayer(), RoleSetting.ADMIN, false)) { @@ -322,13 +328,19 @@ public void on_portal_link_console(final PortalLinkConsoleEvent event) { } } - @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = false) public void on_portal_unlink_console(final PortalUnlinkConsoleEvent event) { if (event.getPortal().owner().equals(event.getPlayer().getUniqueId())) { // Owner may always use their portals return; } + if (get_module().region_at(event.getPortal().spawn()) != null) { + // Portals in regions may be administrated by region administrators, + // not only be the owner + event.setCancelIfNotOwner(false); + } + // Portals in regions may only be administrated by region administrators // Check permission on console if (check_setting_at(event.getConsole(), event.getPlayer(), RoleSetting.ADMIN, false)) { @@ -383,15 +395,14 @@ public void on_portal_select_target(final PortalSelectTargetEvent event) { } } - @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = false) public void on_portal_change_settings(final PortalChangeSettingsEvent event) { if (event.getPortal().owner().equals(event.getPlayer().getUniqueId())) { // Owner may always use their portals return; } - final var region = get_module().region_at(event.getPortal().spawn()); - if (region == null) { + if (get_module().region_at(event.getPortal().spawn()) == null) { return; } @@ -400,8 +411,7 @@ public void on_portal_change_settings(final PortalChangeSettingsEvent event) { event.setCancelIfNotOwner(false); // Now check if the player has the permission - final var group = region.region_group(get_module()); - if (!group.get_role(event.getPlayer().getUniqueId()).get_setting(RoleSetting.ADMIN)) { + if (check_setting_at(event.getPortal().spawn(), event.getPlayer(), RoleSetting.ADMIN, false)) { event.setCancelled(true); } } From ed925dead3ba49581eaa7dd63a869f7499c59aad Mon Sep 17 00:00:00 2001 From: oddlama Date: Tue, 16 Mar 2021 23:42:26 +0100 Subject: [PATCH 39/40] Fix double chests not container --- .../regions/RegionRoleSettingEnforcer.java | 22 +++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/RegionRoleSettingEnforcer.java b/vane-regions/src/main/java/org/oddlama/vane/regions/RegionRoleSettingEnforcer.java index 91a9be3e6..789e034f5 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/RegionRoleSettingEnforcer.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/RegionRoleSettingEnforcer.java @@ -28,6 +28,8 @@ import org.bukkit.event.entity.CreatureSpawnEvent; import org.bukkit.event.entity.EntityDamageByEntityEvent; import org.bukkit.event.entity.EntityExplodeEvent; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.event.inventory.InventoryDragEvent; import org.bukkit.event.inventory.InventoryInteractEvent; import org.bukkit.event.entity.PotionSplashEvent; import org.bukkit.event.hanging.HangingBreakByEntityEvent; @@ -47,6 +49,7 @@ import org.bukkit.block.Block; import org.bukkit.block.Container; +import org.bukkit.block.DoubleChest; import org.bukkit.Location; import org.bukkit.entity.Player; @@ -205,7 +208,9 @@ public void on_player_interact_entity(final PlayerInteractEntityEvent event) { } } - @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + // The EventPriority is HIGH, so this is executed AFTER the portals try + // to activate, which is a seperate permission. + @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) public void on_player_interact(final PlayerInteractEvent event) { final var player = event.getPlayer(); final var block = event.getClickedBlock(); @@ -237,7 +242,6 @@ public void on_player_interact(final PlayerInteractEvent event) { } } - @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) public void on_player_inventory_interact(final InventoryInteractEvent event) { final var clicker = event.getWhoClicked(); if (!(clicker instanceof Player)) { @@ -251,13 +255,23 @@ public void on_player_inventory_interact(final InventoryInteractEvent event) { } final var holder = inventory.getHolder(); - if (holder instanceof Container || holder instanceof ChestedHorse || holder instanceof Minecart) { + if (holder instanceof DoubleChest || holder instanceof Container || holder instanceof Minecart) { if (check_setting_at(inventory.getLocation(), (Player)clicker, RoleSetting.CONTAINER, false)) { event.setCancelled(true); } } } + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void on_player_inventory_click(final InventoryClickEvent event) { + on_player_inventory_interact(event); + } + + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) + public void on_player_inventory_drag(final InventoryDragEvent event) { + on_player_inventory_interact(event); + } + @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) public void on_portal_activate(final PortalActivateEvent event) { if (check_setting_at(event.getPortal().spawn(), event.getPlayer(), RoleSetting.PORTAL, false)) { @@ -308,7 +322,7 @@ public void on_portal_link_console(final PortalLinkConsoleEvent event) { return; } - if (get_module().region_at(event.getPortal().spawn()) != null) { + if (event.getPortal() != null && get_module().region_at(event.getPortal().spawn()) != null) { // Portals in regions may be administrated by region administrators, // not only be the owner event.setCancelIfNotOwner(false); From 87f250682490028c4ed6654d017a34c2ff192c15 Mon Sep 17 00:00:00 2001 From: oddlama Date: Tue, 16 Mar 2021 23:45:27 +0100 Subject: [PATCH 40/40] Organize imports --- .../vane/admin/commands/SlimeChunk.java | 1 - .../org/oddlama/vane/bedtime/Bedtime.java | 2 +- .../bedtime/BedtimeDynmapLayerDelegate.java | 2 +- .../vane/enchantments/Enchantments.java | 1 - .../org/oddlama/vane/portals/Portals.java | 4 +- .../portals/event/PortalOpenConsoleEvent.java | 3 +- .../vane/portals/menu/ConsoleMenu.java | 1 - .../regions/RegionDynmapLayerDelegate.java | 1 - .../RegionEnvironmentSettingEnforcer.java | 38 ++---------- .../regions/RegionRoleSettingEnforcer.java | 41 +++---------- .../vane/regions/RegionSelectionListener.java | 11 +--- .../org/oddlama/vane/regions/Regions.java | 56 ++++------------- .../oddlama/vane/regions/commands/Region.java | 7 --- .../oddlama/vane/regions/menu/MainMenu.java | 4 -- .../vane/regions/menu/RegionGroupMenu.java | 6 +- .../oddlama/vane/regions/menu/RegionMenu.java | 4 +- .../oddlama/vane/regions/menu/RoleMenu.java | 4 -- .../oddlama/vane/regions/region/Region.java | 54 +---------------- .../vane/regions/region/RegionExtent.java | 58 ++---------------- .../vane/regions/region/RegionGroup.java | 52 +--------------- .../vane/regions/region/RegionSelection.java | 60 +------------------ .../org/oddlama/vane/regions/region/Role.java | 51 ---------------- 22 files changed, 43 insertions(+), 418 deletions(-) diff --git a/vane-admin/src/main/java/org/oddlama/vane/admin/commands/SlimeChunk.java b/vane-admin/src/main/java/org/oddlama/vane/admin/commands/SlimeChunk.java index ac82a11fe..fb5844f93 100644 --- a/vane-admin/src/main/java/org/oddlama/vane/admin/commands/SlimeChunk.java +++ b/vane-admin/src/main/java/org/oddlama/vane/admin/commands/SlimeChunk.java @@ -1,7 +1,6 @@ package org.oddlama.vane.admin.commands; import org.bukkit.entity.Player; -import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause; import org.oddlama.vane.admin.Admin; import org.oddlama.vane.annotation.command.Name; diff --git a/vane-bedtime/src/main/java/org/oddlama/vane/bedtime/Bedtime.java b/vane-bedtime/src/main/java/org/oddlama/vane/bedtime/Bedtime.java index 7a8932f31..733fe95d6 100644 --- a/vane-bedtime/src/main/java/org/oddlama/vane/bedtime/Bedtime.java +++ b/vane-bedtime/src/main/java/org/oddlama/vane/bedtime/Bedtime.java @@ -11,9 +11,9 @@ import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; -import org.bukkit.event.player.PlayerQuitEvent; import org.bukkit.event.player.PlayerBedEnterEvent; import org.bukkit.event.player.PlayerBedLeaveEvent; +import org.bukkit.event.player.PlayerQuitEvent; import org.oddlama.vane.annotation.VaneModule; import org.oddlama.vane.annotation.config.ConfigDouble; diff --git a/vane-bedtime/src/main/java/org/oddlama/vane/bedtime/BedtimeDynmapLayerDelegate.java b/vane-bedtime/src/main/java/org/oddlama/vane/bedtime/BedtimeDynmapLayerDelegate.java index 793262c70..969b322c2 100644 --- a/vane-bedtime/src/main/java/org/oddlama/vane/bedtime/BedtimeDynmapLayerDelegate.java +++ b/vane-bedtime/src/main/java/org/oddlama/vane/bedtime/BedtimeDynmapLayerDelegate.java @@ -4,8 +4,8 @@ import java.util.UUID; import java.util.logging.Level; -import org.bukkit.plugin.Plugin; import org.bukkit.OfflinePlayer; +import org.bukkit.plugin.Plugin; import org.dynmap.DynmapAPI; import org.dynmap.markers.Marker; diff --git a/vane-enchantments/src/main/java/org/oddlama/vane/enchantments/Enchantments.java b/vane-enchantments/src/main/java/org/oddlama/vane/enchantments/Enchantments.java index 64f531719..4051cd862 100644 --- a/vane-enchantments/src/main/java/org/oddlama/vane/enchantments/Enchantments.java +++ b/vane-enchantments/src/main/java/org/oddlama/vane/enchantments/Enchantments.java @@ -14,7 +14,6 @@ import org.bukkit.event.inventory.PrepareAnvilEvent; import org.bukkit.event.player.PlayerInteractEntityEvent; import org.bukkit.event.world.LootGenerateEvent; -import org.bukkit.inventory.meta.EnchantmentStorageMeta; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.Merchant; import org.bukkit.inventory.MerchantRecipe; diff --git a/vane-portals/src/main/java/org/oddlama/vane/portals/Portals.java b/vane-portals/src/main/java/org/oddlama/vane/portals/Portals.java index b231a40d5..771b040cf 100644 --- a/vane-portals/src/main/java/org/oddlama/vane/portals/Portals.java +++ b/vane-portals/src/main/java/org/oddlama/vane/portals/Portals.java @@ -9,10 +9,8 @@ import static org.oddlama.vane.util.Util.ms_to_ticks; import static org.oddlama.vane.util.Util.namespaced_key; -import org.oddlama.vane.core.functional.Function2; import java.util.ArrayList; import java.util.Collection; -import org.bukkit.entity.Player; import java.util.HashMap; import java.util.HashSet; import java.util.Map; @@ -32,6 +30,7 @@ import org.bukkit.Sound; import org.bukkit.SoundCategory; import org.bukkit.block.Block; +import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.world.ChunkLoadEvent; @@ -52,6 +51,7 @@ import org.oddlama.vane.annotation.lang.LangMessage; import org.oddlama.vane.annotation.persistent.Persistent; import org.oddlama.vane.core.functional.Consumer2; +import org.oddlama.vane.core.functional.Function2; import org.oddlama.vane.core.lang.TranslatedMessage; import org.oddlama.vane.core.material.ExtendedMaterial; import org.oddlama.vane.core.module.Module; diff --git a/vane-portals/src/main/java/org/oddlama/vane/portals/event/PortalOpenConsoleEvent.java b/vane-portals/src/main/java/org/oddlama/vane/portals/event/PortalOpenConsoleEvent.java index b3271ee11..5a098f5b7 100644 --- a/vane-portals/src/main/java/org/oddlama/vane/portals/event/PortalOpenConsoleEvent.java +++ b/vane-portals/src/main/java/org/oddlama/vane/portals/event/PortalOpenConsoleEvent.java @@ -1,10 +1,9 @@ package org.oddlama.vane.portals.event; -import java.util.UUID; - import org.bukkit.block.Block; import org.bukkit.entity.Player; import org.bukkit.event.HandlerList; + import org.oddlama.vane.portals.portal.Portal; public class PortalOpenConsoleEvent extends PortalEvent { diff --git a/vane-portals/src/main/java/org/oddlama/vane/portals/menu/ConsoleMenu.java b/vane-portals/src/main/java/org/oddlama/vane/portals/menu/ConsoleMenu.java index fb0bc4768..2eeea4a5b 100644 --- a/vane-portals/src/main/java/org/oddlama/vane/portals/menu/ConsoleMenu.java +++ b/vane-portals/src/main/java/org/oddlama/vane/portals/menu/ConsoleMenu.java @@ -5,7 +5,6 @@ import java.util.Objects; import java.util.stream.Collectors; -import org.bukkit.entity.Player; import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.block.Block; diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/RegionDynmapLayerDelegate.java b/vane-regions/src/main/java/org/oddlama/vane/regions/RegionDynmapLayerDelegate.java index 83f3b7d9d..27b7c610c 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/RegionDynmapLayerDelegate.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/RegionDynmapLayerDelegate.java @@ -9,7 +9,6 @@ import org.dynmap.DynmapAPI; import org.dynmap.markers.Marker; import org.dynmap.markers.MarkerAPI; -import org.dynmap.markers.MarkerIcon; import org.dynmap.markers.MarkerSet; import org.oddlama.vane.regions.Regions; diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/RegionEnvironmentSettingEnforcer.java b/vane-regions/src/main/java/org/oddlama/vane/regions/RegionEnvironmentSettingEnforcer.java index a4eed65ec..d875f8a9e 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/RegionEnvironmentSettingEnforcer.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/RegionEnvironmentSettingEnforcer.java @@ -1,56 +1,30 @@ package org.oddlama.vane.regions; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.Block; import org.bukkit.entity.Animals; -import org.bukkit.entity.Entity; -import org.bukkit.entity.EntityType; -import org.bukkit.entity.ItemFrame; -import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Monster; +import org.bukkit.entity.Player; +import org.bukkit.entity.Projectile; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; -import org.bukkit.event.block.BlockBreakEvent; import org.bukkit.event.block.Action; -import org.bukkit.entity.Player; -import org.bukkit.entity.Projectile; -import org.bukkit.event.block.BlockPistonExtendEvent; -import org.bukkit.event.block.BlockPistonRetractEvent; -import org.bukkit.event.block.BlockPlaceEvent; -import org.bukkit.event.entity.EntityChangeBlockEvent; -import org.bukkit.event.entity.EntityExplodeEvent; import org.bukkit.event.block.BlockBurnEvent; import org.bukkit.event.block.BlockExplodeEvent; -import org.bukkit.event.block.BlockIgniteEvent; -import org.bukkit.event.block.BlockMultiPlaceEvent; -import org.bukkit.event.block.BlockPlaceEvent; import org.bukkit.event.block.BlockSpreadEvent; -import org.bukkit.event.block.LeavesDecayEvent; import org.bukkit.event.entity.CreatureSpawnEvent; +import org.bukkit.event.entity.EntityChangeBlockEvent; import org.bukkit.event.entity.EntityDamageByEntityEvent; import org.bukkit.event.entity.EntityExplodeEvent; import org.bukkit.event.entity.PotionSplashEvent; -import org.bukkit.event.hanging.HangingBreakByEntityEvent; import org.bukkit.event.hanging.HangingBreakEvent; -import org.bukkit.event.hanging.HangingPlaceEvent; -import org.bukkit.event.player.PlayerArmorStandManipulateEvent; -import org.bukkit.event.player.PlayerBucketEmptyEvent; -import org.bukkit.event.player.PlayerBucketFillEvent; -import org.bukkit.event.player.PlayerInteractEntityEvent; import org.bukkit.event.player.PlayerInteractEvent; -import org.bukkit.event.player.PlayerKickEvent; -import org.bukkit.event.player.PlayerQuitEvent; -import org.bukkit.event.world.StructureGrowEvent; -import org.bukkit.inventory.EquipmentSlot; -import org.bukkit.inventory.ItemStack; -import org.bukkit.projectiles.ProjectileSource; import org.oddlama.vane.core.Listener; import org.oddlama.vane.core.module.Context; import org.oddlama.vane.regions.region.EnvironmentSetting; -import org.bukkit.block.Block; -import org.bukkit.Location; -import org.bukkit.Material; - public class RegionEnvironmentSettingEnforcer extends Listener { public RegionEnvironmentSettingEnforcer(Context context) { super(context); diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/RegionRoleSettingEnforcer.java b/vane-regions/src/main/java/org/oddlama/vane/regions/RegionRoleSettingEnforcer.java index 789e034f5..caf625444 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/RegionRoleSettingEnforcer.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/RegionRoleSettingEnforcer.java @@ -1,57 +1,32 @@ package org.oddlama.vane.regions; -import org.bukkit.Tag; -import org.bukkit.event.EventHandler; -import org.bukkit.event.EventPriority; -import org.bukkit.event.block.BlockBreakEvent; -import org.bukkit.entity.Animals; -import org.bukkit.entity.ChestedHorse; import org.bukkit.Location; import org.bukkit.Material; +import org.bukkit.Tag; +import org.bukkit.block.Block; +import org.bukkit.block.Container; +import org.bukkit.block.DoubleChest; import org.bukkit.entity.Entity; import org.bukkit.entity.EntityType; import org.bukkit.entity.ItemFrame; -import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Minecart; -import org.bukkit.entity.Monster; import org.bukkit.entity.Player; import org.bukkit.entity.Projectile; -import org.bukkit.event.block.BlockPlaceEvent; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; import org.bukkit.event.block.BlockBreakEvent; -import org.bukkit.event.block.BlockBurnEvent; -import org.bukkit.event.block.BlockExplodeEvent; -import org.bukkit.event.block.BlockIgniteEvent; -import org.bukkit.event.block.BlockMultiPlaceEvent; import org.bukkit.event.block.BlockPlaceEvent; -import org.bukkit.event.block.BlockSpreadEvent; -import org.bukkit.event.block.LeavesDecayEvent; -import org.bukkit.event.entity.CreatureSpawnEvent; import org.bukkit.event.entity.EntityDamageByEntityEvent; -import org.bukkit.event.entity.EntityExplodeEvent; +import org.bukkit.event.hanging.HangingBreakByEntityEvent; +import org.bukkit.event.hanging.HangingPlaceEvent; import org.bukkit.event.inventory.InventoryClickEvent; import org.bukkit.event.inventory.InventoryDragEvent; import org.bukkit.event.inventory.InventoryInteractEvent; -import org.bukkit.event.entity.PotionSplashEvent; -import org.bukkit.event.hanging.HangingBreakByEntityEvent; -import org.bukkit.event.hanging.HangingBreakEvent; -import org.bukkit.event.hanging.HangingPlaceEvent; import org.bukkit.event.player.PlayerArmorStandManipulateEvent; import org.bukkit.event.player.PlayerBucketEmptyEvent; import org.bukkit.event.player.PlayerBucketFillEvent; import org.bukkit.event.player.PlayerInteractEntityEvent; import org.bukkit.event.player.PlayerInteractEvent; -import org.bukkit.event.player.PlayerKickEvent; -import org.bukkit.event.player.PlayerQuitEvent; -import org.bukkit.event.world.StructureGrowEvent; -import org.bukkit.inventory.EquipmentSlot; -import org.bukkit.inventory.ItemStack; -import org.bukkit.projectiles.ProjectileSource; - -import org.bukkit.block.Block; -import org.bukkit.block.Container; -import org.bukkit.block.DoubleChest; -import org.bukkit.Location; -import org.bukkit.entity.Player; import org.oddlama.vane.core.Listener; import org.oddlama.vane.core.module.Context; diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/RegionSelectionListener.java b/vane-regions/src/main/java/org/oddlama/vane/regions/RegionSelectionListener.java index 1bb26d8ec..33d5fad37 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/RegionSelectionListener.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/RegionSelectionListener.java @@ -1,23 +1,14 @@ package org.oddlama.vane.regions; +import org.bukkit.Material; import org.bukkit.event.Event; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; -import org.bukkit.event.block.BlockBreakEvent; -import org.bukkit.event.block.BlockPlaceEvent; import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.inventory.EquipmentSlot; -import org.bukkit.Material; - -import org.bukkit.block.Block; -import org.bukkit.Location; -import org.bukkit.entity.Player; -import org.oddlama.vane.annotation.lang.LangMessage; -import org.oddlama.vane.core.lang.TranslatedMessage; import org.oddlama.vane.core.Listener; import org.oddlama.vane.core.module.Context; -import org.oddlama.vane.regions.region.RoleSetting; public class RegionSelectionListener extends Listener { public RegionSelectionListener(Context context) { diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/Regions.java b/vane-regions/src/main/java/org/oddlama/vane/regions/Regions.java index f829e81b4..7860dd73d 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/Regions.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/Regions.java @@ -1,84 +1,52 @@ package org.oddlama.vane.regions; -import static org.oddlama.vane.util.BlockUtil.adjacent_blocks_3d; -import org.bukkit.event.player.PlayerQuitEvent; -import static org.oddlama.vane.util.BlockUtil.unpack; -import static org.oddlama.vane.util.ItemUtil.name_item; -import static org.oddlama.vane.util.Nms.item_handle; -import static org.oddlama.vane.util.Nms.register_entity; -import static org.oddlama.vane.util.Nms.spawn; -import static org.oddlama.vane.util.Util.ms_to_ticks; -import static org.oddlama.vane.util.Util.namespaced_key; -import static org.oddlama.vane.util.PlayerUtil.give_items; import static org.oddlama.vane.util.PlayerUtil.take_items; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; -import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Set; import java.util.UUID; -import net.md_5.bungee.api.chat.BaseComponent; import net.minecraft.server.v1_16_R3.BlockPosition; -import net.minecraft.server.v1_16_R3.EntityTypes; -import net.minecraft.server.v1_16_R3.EnumCreatureType; import org.bukkit.Chunk; import org.bukkit.Color; +import org.bukkit.Location; import org.bukkit.Material; -import org.bukkit.NamespacedKey; +import org.bukkit.Particle.DustOptions; import org.bukkit.Particle; -import org.bukkit.Sound; -import org.bukkit.SoundCategory; import org.bukkit.World; -import org.bukkit.Particle.DustOptions; import org.bukkit.block.Block; +import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; -import org.bukkit.event.world.ChunkLoadEvent; -import org.bukkit.event.world.ChunkUnloadEvent; +import org.bukkit.event.player.PlayerQuitEvent; import org.bukkit.inventory.ItemStack; -import org.bukkit.scheduler.BukkitTask; -import org.bukkit.util.Vector; -import org.bukkit.Location; -import org.bukkit.entity.Player; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import org.oddlama.vane.annotation.VaneModule; -import org.oddlama.vane.annotation.config.ConfigExtendedMaterial; -import org.oddlama.vane.annotation.config.ConfigLong; -import org.oddlama.vane.annotation.config.ConfigMaterialMapEntry; -import org.oddlama.vane.annotation.config.ConfigMaterialMapMapEntry; -import org.oddlama.vane.annotation.config.ConfigMaterialMapMapMap; -import org.oddlama.vane.annotation.config.ConfigMaterialMapMapMapEntry; +import org.oddlama.vane.annotation.config.ConfigDouble; +import org.oddlama.vane.annotation.config.ConfigInt; +import org.oddlama.vane.annotation.config.ConfigMaterial; import org.oddlama.vane.annotation.lang.LangMessage; import org.oddlama.vane.annotation.persistent.Persistent; -import org.oddlama.vane.core.functional.Consumer2; import org.oddlama.vane.core.lang.TranslatedMessage; -import org.oddlama.vane.core.material.ExtendedMaterial; import org.oddlama.vane.core.module.Module; import org.oddlama.vane.core.persistent.PersistentSerializer; import org.oddlama.vane.portals.Portals; +import org.oddlama.vane.regions.menu.RegionGroupMenuTag; +import org.oddlama.vane.regions.menu.RegionMenuGroup; +import org.oddlama.vane.regions.menu.RegionMenuTag; +import org.oddlama.vane.regions.region.EnvironmentSetting; import org.oddlama.vane.regions.region.Region; -import org.oddlama.vane.annotation.config.ConfigInt; -import org.oddlama.vane.annotation.config.ConfigDouble; -import org.oddlama.vane.annotation.config.ConfigMaterial; +import org.oddlama.vane.regions.region.RegionExtent; import org.oddlama.vane.regions.region.RegionGroup; import org.oddlama.vane.regions.region.RegionSelection; import org.oddlama.vane.regions.region.Role; -import org.oddlama.vane.regions.region.RegionExtent; import org.oddlama.vane.regions.region.RoleSetting; -import org.oddlama.vane.regions.menu.RegionGroupMenuTag; -import org.oddlama.vane.regions.menu.RegionMenuGroup; -import org.oddlama.vane.regions.menu.RegionMenuTag; -import org.oddlama.vane.regions.region.EnvironmentSetting; - -import org.oddlama.vane.util.LazyBlock; @VaneModule(name = "regions", bstats = 8643, config_version = 2, lang_version = 2, storage_version = 1) public class Regions extends Module { diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/commands/Region.java b/vane-regions/src/main/java/org/oddlama/vane/regions/commands/Region.java index ac494ade5..ddfb1d75f 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/commands/Region.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/commands/Region.java @@ -1,17 +1,10 @@ package org.oddlama.vane.regions.commands; -import java.util.Collections; - -import org.bukkit.OfflinePlayer; -import org.bukkit.command.CommandSender; -import org.bukkit.permissions.PermissionDefault; import org.bukkit.entity.Player; import org.oddlama.vane.annotation.command.Aliases; import org.oddlama.vane.annotation.command.Name; -import org.oddlama.vane.annotation.lang.LangMessage; import org.oddlama.vane.core.command.Command; -import org.oddlama.vane.core.lang.TranslatedMessage; import org.oddlama.vane.core.module.Context; import org.oddlama.vane.regions.Regions; diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/menu/MainMenu.java b/vane-regions/src/main/java/org/oddlama/vane/regions/menu/MainMenu.java index 413a6a265..398390f78 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/menu/MainMenu.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/menu/MainMenu.java @@ -1,13 +1,9 @@ package org.oddlama.vane.regions.menu; -import static org.oddlama.vane.util.Util.namespaced_key; - -import java.util.Objects; import java.util.stream.Collectors; import org.bukkit.Bukkit; import org.bukkit.Material; -import org.bukkit.block.Block; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RegionGroupMenu.java b/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RegionGroupMenu.java index bc53cb4e0..452f5d949 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RegionGroupMenu.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RegionGroupMenu.java @@ -2,12 +2,10 @@ import static org.oddlama.vane.util.Util.namespaced_key; -import java.util.Objects; import java.util.stream.Collectors; import org.bukkit.Bukkit; import org.bukkit.Material; -import org.bukkit.block.Block; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; @@ -23,10 +21,8 @@ import org.oddlama.vane.core.module.Context; import org.oddlama.vane.core.module.ModuleComponent; import org.oddlama.vane.regions.Regions; -import org.oddlama.vane.regions.region.Region; -import org.oddlama.vane.regions.region.RegionGroup; -import org.oddlama.vane.regions.region.RegionSelection; import org.oddlama.vane.regions.region.EnvironmentSetting; +import org.oddlama.vane.regions.region.RegionGroup; import org.oddlama.vane.regions.region.Role; public class RegionGroupMenu extends ModuleComponent { diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RegionMenu.java b/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RegionMenu.java index e8c77c45d..18fb7a3dc 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RegionMenu.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RegionMenu.java @@ -1,14 +1,12 @@ package org.oddlama.vane.regions.menu; -import static org.oddlama.vane.util.Util.namespaced_key; import static org.oddlama.vane.util.PlayerUtil.give_items; +import static org.oddlama.vane.util.Util.namespaced_key; -import java.util.Objects; import java.util.stream.Collectors; import org.bukkit.Bukkit; import org.bukkit.Material; -import org.bukkit.block.Block; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RoleMenu.java b/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RoleMenu.java index 45fcd1c71..548f715a9 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RoleMenu.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/menu/RoleMenu.java @@ -2,13 +2,11 @@ import static org.oddlama.vane.util.Util.namespaced_key; -import java.util.Objects; import java.util.Arrays; import java.util.stream.Collectors; import org.bukkit.Bukkit; import org.bukkit.Material; -import org.bukkit.block.Block; import org.bukkit.OfflinePlayer; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; @@ -25,9 +23,7 @@ import org.oddlama.vane.core.module.Context; import org.oddlama.vane.core.module.ModuleComponent; import org.oddlama.vane.regions.Regions; -import org.oddlama.vane.regions.region.Region; import org.oddlama.vane.regions.region.RegionGroup; -import org.oddlama.vane.regions.region.RegionSelection; import org.oddlama.vane.regions.region.Role; import org.oddlama.vane.regions.region.RoleSetting; import org.oddlama.vane.util.ItemUtil; diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/region/Region.java b/vane-regions/src/main/java/org/oddlama/vane/regions/region/Region.java index 098e8209d..05de2996f 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/region/Region.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/region/Region.java @@ -3,64 +3,12 @@ import static org.oddlama.vane.core.persistent.PersistentSerializer.from_json; import static org.oddlama.vane.core.persistent.PersistentSerializer.to_json; -import static org.oddlama.vane.util.BlockUtil.adjacent_blocks_3d; -import static org.oddlama.vane.util.BlockUtil.unpack; -import static org.oddlama.vane.util.ItemUtil.name_item; -import static org.oddlama.vane.util.Nms.item_handle; -import static org.oddlama.vane.util.Nms.register_entity; -import static org.oddlama.vane.util.Nms.spawn; -import static org.oddlama.vane.util.Util.ms_to_ticks; -import static org.oddlama.vane.util.Util.namespaced_key; - -import org.oddlama.vane.external.json.JSONObject; - import java.io.IOException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Objects; -import java.util.Set; import java.util.UUID; -import net.md_5.bungee.api.chat.BaseComponent; -import net.minecraft.server.v1_16_R3.BlockPosition; -import net.minecraft.server.v1_16_R3.EntityTypes; -import net.minecraft.server.v1_16_R3.EnumCreatureType; - -import org.bukkit.Chunk; -import org.bukkit.Material; -import org.bukkit.NamespacedKey; -import org.bukkit.Particle; -import org.bukkit.Sound; -import org.bukkit.SoundCategory; -import org.bukkit.block.Block; -import org.bukkit.event.EventHandler; -import org.bukkit.event.EventPriority; -import org.bukkit.event.world.ChunkLoadEvent; -import org.bukkit.event.world.ChunkUnloadEvent; -import org.bukkit.inventory.ItemStack; -import org.bukkit.scheduler.BukkitTask; -import org.bukkit.util.Vector; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.oddlama.vane.annotation.VaneModule; -import org.oddlama.vane.annotation.config.ConfigExtendedMaterial; -import org.oddlama.vane.annotation.config.ConfigLong; -import org.oddlama.vane.annotation.config.ConfigMaterialMapEntry; -import org.oddlama.vane.annotation.config.ConfigMaterialMapMapEntry; -import org.oddlama.vane.annotation.config.ConfigMaterialMapMapMap; -import org.oddlama.vane.annotation.config.ConfigMaterialMapMapMapEntry; -import org.oddlama.vane.annotation.lang.LangMessage; -import org.oddlama.vane.annotation.persistent.Persistent; -import org.oddlama.vane.core.functional.Consumer2; -import org.oddlama.vane.core.lang.TranslatedMessage; -import org.oddlama.vane.core.material.ExtendedMaterial; -import org.oddlama.vane.core.module.Module; -import org.oddlama.vane.core.persistent.PersistentSerializer; -import org.oddlama.vane.util.LazyBlock; +import org.oddlama.vane.external.json.JSONObject; import org.oddlama.vane.regions.Regions; public class Region { diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/region/RegionExtent.java b/vane-regions/src/main/java/org/oddlama/vane/regions/region/RegionExtent.java index 6885606dc..69cc6c51c 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/region/RegionExtent.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/region/RegionExtent.java @@ -3,66 +3,16 @@ import static org.oddlama.vane.core.persistent.PersistentSerializer.from_json; import static org.oddlama.vane.core.persistent.PersistentSerializer.to_json; -import static org.oddlama.vane.util.BlockUtil.adjacent_blocks_3d; -import static org.oddlama.vane.util.BlockUtil.unpack; -import static org.oddlama.vane.util.ItemUtil.name_item; -import static org.oddlama.vane.util.Nms.item_handle; -import static org.oddlama.vane.util.Nms.register_entity; -import static org.oddlama.vane.util.Nms.spawn; -import static org.oddlama.vane.util.Util.ms_to_ticks; -import static org.oddlama.vane.util.Util.namespaced_key; - -import org.oddlama.vane.external.json.JSONObject; - import java.io.IOException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import java.util.UUID; - -import net.md_5.bungee.api.chat.BaseComponent; -import net.minecraft.server.v1_16_R3.BlockPosition; -import net.minecraft.server.v1_16_R3.EntityTypes; -import net.minecraft.server.v1_16_R3.EnumCreatureType; import org.bukkit.Chunk; -import org.bukkit.Material; -import org.bukkit.NamespacedKey; -import org.bukkit.Particle; -import org.bukkit.Sound; -import org.bukkit.SoundCategory; -import org.bukkit.block.Block; import org.bukkit.Location; -import org.bukkit.event.EventHandler; -import org.bukkit.event.EventPriority; -import org.bukkit.event.world.ChunkLoadEvent; -import org.bukkit.event.world.ChunkUnloadEvent; -import org.bukkit.inventory.ItemStack; -import org.bukkit.scheduler.BukkitTask; -import org.bukkit.util.Vector; +import org.bukkit.block.Block; + import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import org.oddlama.vane.annotation.VaneModule; -import org.oddlama.vane.annotation.config.ConfigExtendedMaterial; -import org.oddlama.vane.annotation.config.ConfigLong; -import org.oddlama.vane.annotation.config.ConfigMaterialMapEntry; -import org.oddlama.vane.annotation.config.ConfigMaterialMapMapEntry; -import org.oddlama.vane.annotation.config.ConfigMaterialMapMapMap; -import org.oddlama.vane.annotation.config.ConfigMaterialMapMapMapEntry; -import org.oddlama.vane.annotation.lang.LangMessage; -import org.oddlama.vane.annotation.persistent.Persistent; -import org.oddlama.vane.core.functional.Consumer2; -import org.oddlama.vane.core.lang.TranslatedMessage; -import org.oddlama.vane.core.material.ExtendedMaterial; -import org.oddlama.vane.core.module.Module; -import org.oddlama.vane.core.persistent.PersistentSerializer; + +import org.oddlama.vane.external.json.JSONObject; import org.oddlama.vane.util.LazyBlock; -import org.oddlama.vane.regions.Regions; public class RegionExtent { public static Object serialize(@NotNull final Object o) throws IOException { diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/region/RegionGroup.java b/vane-regions/src/main/java/org/oddlama/vane/regions/region/RegionGroup.java index 876fd4f62..37f318ded 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/region/RegionGroup.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/region/RegionGroup.java @@ -3,64 +3,16 @@ import static org.oddlama.vane.core.persistent.PersistentSerializer.from_json; import static org.oddlama.vane.core.persistent.PersistentSerializer.to_json; -import static org.oddlama.vane.util.BlockUtil.adjacent_blocks_3d; -import static org.oddlama.vane.util.BlockUtil.unpack; -import static org.oddlama.vane.util.ItemUtil.name_item; -import static org.oddlama.vane.util.Nms.item_handle; -import static org.oddlama.vane.util.Nms.register_entity; -import static org.oddlama.vane.util.Nms.spawn; -import static org.oddlama.vane.util.Util.ms_to_ticks; -import static org.oddlama.vane.util.Util.namespaced_key; - -import org.oddlama.vane.external.json.JSONObject; - import java.io.IOException; -import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; -import java.util.HashSet; import java.util.Map; -import java.util.Objects; import java.util.Set; import java.util.UUID; -import net.md_5.bungee.api.chat.BaseComponent; -import net.minecraft.server.v1_16_R3.BlockPosition; -import net.minecraft.server.v1_16_R3.EntityTypes; -import net.minecraft.server.v1_16_R3.EnumCreatureType; - -import org.bukkit.Chunk; -import org.bukkit.Material; -import org.bukkit.NamespacedKey; -import org.bukkit.Particle; -import org.bukkit.Sound; -import org.bukkit.SoundCategory; -import org.bukkit.block.Block; -import org.bukkit.event.EventHandler; -import org.bukkit.event.EventPriority; -import org.bukkit.event.world.ChunkLoadEvent; -import org.bukkit.event.world.ChunkUnloadEvent; -import org.bukkit.inventory.ItemStack; -import org.bukkit.scheduler.BukkitTask; -import org.bukkit.util.Vector; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import org.oddlama.vane.annotation.VaneModule; -import org.oddlama.vane.annotation.config.ConfigExtendedMaterial; -import org.oddlama.vane.annotation.config.ConfigLong; -import org.oddlama.vane.annotation.config.ConfigMaterialMapEntry; -import org.oddlama.vane.annotation.config.ConfigMaterialMapMapEntry; -import org.oddlama.vane.annotation.config.ConfigMaterialMapMapMap; -import org.oddlama.vane.annotation.config.ConfigMaterialMapMapMapEntry; -import org.oddlama.vane.annotation.lang.LangMessage; -import org.oddlama.vane.annotation.persistent.Persistent; -import org.oddlama.vane.core.functional.Consumer2; -import org.oddlama.vane.core.lang.TranslatedMessage; -import org.oddlama.vane.core.material.ExtendedMaterial; -import org.oddlama.vane.core.module.Module; -import org.oddlama.vane.core.persistent.PersistentSerializer; -import org.oddlama.vane.util.LazyBlock; + +import org.oddlama.vane.external.json.JSONObject; import org.oddlama.vane.regions.Regions; public class RegionGroup { diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/region/RegionSelection.java b/vane-regions/src/main/java/org/oddlama/vane/regions/region/RegionSelection.java index 24c50ead4..aba76ca5d 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/region/RegionSelection.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/region/RegionSelection.java @@ -1,69 +1,13 @@ package org.oddlama.vane.regions.region; -import static org.oddlama.vane.core.persistent.PersistentSerializer.from_json; -import static org.oddlama.vane.core.persistent.PersistentSerializer.to_json; - -import static org.oddlama.vane.util.BlockUtil.adjacent_blocks_3d; -import static org.oddlama.vane.util.BlockUtil.unpack; -import static org.oddlama.vane.util.ItemUtil.name_item; -import static org.oddlama.vane.util.Nms.item_handle; -import static org.oddlama.vane.util.Nms.register_entity; import static org.oddlama.vane.util.PlayerUtil.has_items; -import static org.oddlama.vane.util.Nms.spawn; -import static org.oddlama.vane.util.Util.ms_to_ticks; -import static org.oddlama.vane.util.Util.namespaced_key; -import org.oddlama.vane.external.json.JSONObject; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collection; import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import java.util.UUID; - -import net.md_5.bungee.api.chat.BaseComponent; -import net.minecraft.server.v1_16_R3.BlockPosition; -import net.minecraft.server.v1_16_R3.EntityTypes; -import net.minecraft.server.v1_16_R3.EnumCreatureType; - -import org.bukkit.Chunk; -import org.bukkit.Material; -import org.bukkit.NamespacedKey; -import org.bukkit.Particle; -import org.bukkit.Sound; -import org.bukkit.SoundCategory; + import org.bukkit.block.Block; -import org.bukkit.Location; import org.bukkit.entity.Player; -import org.bukkit.event.EventHandler; -import org.bukkit.event.EventPriority; -import org.bukkit.event.world.ChunkLoadEvent; -import org.bukkit.event.world.ChunkUnloadEvent; import org.bukkit.inventory.ItemStack; -import org.bukkit.scheduler.BukkitTask; -import org.bukkit.util.Vector; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import org.oddlama.vane.annotation.VaneModule; -import org.oddlama.vane.annotation.config.ConfigExtendedMaterial; -import org.oddlama.vane.annotation.config.ConfigLong; -import org.oddlama.vane.annotation.config.ConfigMaterialMapEntry; -import org.oddlama.vane.annotation.config.ConfigMaterialMapMapEntry; -import org.oddlama.vane.annotation.config.ConfigMaterialMapMapMap; -import org.oddlama.vane.annotation.config.ConfigMaterialMapMapMapEntry; -import org.oddlama.vane.annotation.lang.LangMessage; -import org.oddlama.vane.annotation.persistent.Persistent; -import org.oddlama.vane.core.functional.Consumer2; -import org.oddlama.vane.core.lang.TranslatedMessage; -import org.oddlama.vane.core.material.ExtendedMaterial; -import org.oddlama.vane.core.module.Module; -import org.oddlama.vane.core.persistent.PersistentSerializer; -import org.oddlama.vane.util.LazyBlock; + import org.oddlama.vane.regions.Regions; public class RegionSelection { diff --git a/vane-regions/src/main/java/org/oddlama/vane/regions/region/Role.java b/vane-regions/src/main/java/org/oddlama/vane/regions/region/Role.java index 698d726e1..63da10a8b 100644 --- a/vane-regions/src/main/java/org/oddlama/vane/regions/region/Role.java +++ b/vane-regions/src/main/java/org/oddlama/vane/regions/region/Role.java @@ -3,63 +3,12 @@ import static org.oddlama.vane.core.persistent.PersistentSerializer.from_json; import static org.oddlama.vane.core.persistent.PersistentSerializer.to_json; -import static org.oddlama.vane.util.BlockUtil.adjacent_blocks_3d; -import static org.oddlama.vane.util.BlockUtil.unpack; -import static org.oddlama.vane.util.ItemUtil.name_item; -import static org.oddlama.vane.util.Nms.item_handle; -import static org.oddlama.vane.util.Nms.register_entity; -import static org.oddlama.vane.util.Nms.spawn; -import static org.oddlama.vane.util.Util.ms_to_ticks; -import static org.oddlama.vane.util.Util.namespaced_key; - import java.io.IOException; -import java.util.ArrayList; -import java.util.Collection; import java.util.HashMap; -import java.util.HashSet; import java.util.Map; -import java.util.Objects; -import java.util.Set; import java.util.UUID; -import net.md_5.bungee.api.chat.BaseComponent; -import net.minecraft.server.v1_16_R3.BlockPosition; -import net.minecraft.server.v1_16_R3.EntityTypes; -import net.minecraft.server.v1_16_R3.EnumCreatureType; - -import org.bukkit.Chunk; -import org.bukkit.Material; -import org.bukkit.NamespacedKey; -import org.bukkit.Particle; -import org.bukkit.Sound; -import org.bukkit.SoundCategory; -import org.bukkit.block.Block; -import org.bukkit.event.EventHandler; -import org.bukkit.event.EventPriority; -import org.bukkit.event.world.ChunkLoadEvent; -import org.bukkit.event.world.ChunkUnloadEvent; -import org.bukkit.inventory.ItemStack; -import org.bukkit.scheduler.BukkitTask; -import org.bukkit.util.Vector; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import org.oddlama.vane.annotation.VaneModule; -import org.oddlama.vane.annotation.config.ConfigExtendedMaterial; -import org.oddlama.vane.annotation.config.ConfigLong; -import org.oddlama.vane.annotation.config.ConfigMaterialMapEntry; -import org.oddlama.vane.annotation.config.ConfigMaterialMapMapEntry; -import org.oddlama.vane.annotation.config.ConfigMaterialMapMapMap; -import org.oddlama.vane.annotation.config.ConfigMaterialMapMapMapEntry; -import org.oddlama.vane.annotation.lang.LangMessage; -import org.oddlama.vane.annotation.persistent.Persistent; -import org.oddlama.vane.core.functional.Consumer2; -import org.oddlama.vane.core.lang.TranslatedMessage; -import org.oddlama.vane.core.material.ExtendedMaterial; -import org.oddlama.vane.core.module.Module; -import org.oddlama.vane.core.persistent.PersistentSerializer; -import org.oddlama.vane.util.LazyBlock; -import org.oddlama.vane.regions.Regions; import org.oddlama.vane.external.json.JSONObject;