From b4423d183319df2df0217d51261747d33d8aa3b7 Mon Sep 17 00:00:00 2001 From: oddlama Date: Thu, 14 Nov 2024 12:33:26 +0100 Subject: [PATCH] fix: don't allow non-full blocks as portal style blocks, and add an additional blacklist (fixes #209, #210) --- .../org/oddlama/vane/portals/Portals.java | 283 ++++----- .../oddlama/vane/portals/menu/StyleMenu.java | 577 ++++++++---------- .../vane/trifles/FastWalkingListener.java | 4 +- 3 files changed, 396 insertions(+), 468 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 1f337e4ea..f23e2a0f6 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 @@ -54,6 +54,7 @@ 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.ConfigMaterialSet; import org.oddlama.vane.annotation.lang.LangMessage; import org.oddlama.vane.annotation.persistent.Persistent; import org.oddlama.vane.core.functional.Consumer2; @@ -96,15 +97,13 @@ public class Portals extends Module { PersistentSerializer.deserializers.put(Style.class, Style::deserialize); } + @ConfigMaterialSet(def = { Material.PISTON, Material.STICKY_PISTON }, desc = "Materials which may not be used to decorate portals.") + public Set config_blacklisted_materials; + // TODO better and more default styles - @ConfigMaterialMapMapMap( - def = { - @ConfigMaterialMapMapMapEntry( - key = "vane_portals:portal_style_default", - value = { - @ConfigMaterialMapMapEntry( - key = "active", - value = { + @ConfigMaterialMapMapMap(def = { + @ConfigMaterialMapMapMapEntry(key = "vane_portals:portal_style_default", value = { + @ConfigMaterialMapMapEntry(key = "active", value = { @ConfigMaterialMapEntry(key = "boundary_1", value = Material.OBSIDIAN), @ConfigMaterialMapEntry(key = "boundary_2", value = Material.OBSIDIAN), @ConfigMaterialMapEntry(key = "boundary_3", value = Material.OBSIDIAN), @@ -113,11 +112,8 @@ public class Portals extends Module { @ConfigMaterialMapEntry(key = "console", value = Material.ENCHANTING_TABLE), @ConfigMaterialMapEntry(key = "origin", value = Material.OBSIDIAN), @ConfigMaterialMapEntry(key = "portal", value = Material.END_GATEWAY), - } - ), - @ConfigMaterialMapMapEntry( - key = "inactive", - value = { + }), + @ConfigMaterialMapMapEntry(key = "inactive", value = { @ConfigMaterialMapEntry(key = "boundary_1", value = Material.OBSIDIAN), @ConfigMaterialMapEntry(key = "boundary_2", value = Material.OBSIDIAN), @ConfigMaterialMapEntry(key = "boundary_3", value = Material.OBSIDIAN), @@ -126,16 +122,10 @@ public class Portals extends Module { @ConfigMaterialMapEntry(key = "console", value = Material.ENCHANTING_TABLE), @ConfigMaterialMapEntry(key = "origin", value = Material.OBSIDIAN), @ConfigMaterialMapEntry(key = "portal", value = Material.AIR), - } - ), - } - ), - @ConfigMaterialMapMapMapEntry( - key = "vane_portals:portal_style_aqua", - value = { - @ConfigMaterialMapMapEntry( - key = "active", - value = { + }), + }), + @ConfigMaterialMapMapMapEntry(key = "vane_portals:portal_style_aqua", value = { + @ConfigMaterialMapMapEntry(key = "active", value = { @ConfigMaterialMapEntry(key = "boundary_1", value = Material.DARK_PRISMARINE), @ConfigMaterialMapEntry(key = "boundary_2", value = Material.WARPED_PLANKS), @ConfigMaterialMapEntry(key = "boundary_3", value = Material.SEA_LANTERN), @@ -144,11 +134,8 @@ public class Portals extends Module { @ConfigMaterialMapEntry(key = "console", value = Material.ENCHANTING_TABLE), @ConfigMaterialMapEntry(key = "origin", value = Material.DARK_PRISMARINE), @ConfigMaterialMapEntry(key = "portal", value = Material.END_GATEWAY), - } - ), - @ConfigMaterialMapMapEntry( - key = "inactive", - value = { + }), + @ConfigMaterialMapMapEntry(key = "inactive", value = { @ConfigMaterialMapEntry(key = "boundary_1", value = Material.DARK_PRISMARINE), @ConfigMaterialMapEntry(key = "boundary_2", value = Material.WARPED_PLANKS), @ConfigMaterialMapEntry(key = "boundary_3", value = Material.PRISMARINE_BRICKS), @@ -157,43 +144,21 @@ public class Portals extends Module { @ConfigMaterialMapEntry(key = "console", value = Material.ENCHANTING_TABLE), @ConfigMaterialMapEntry(key = "origin", value = Material.DARK_PRISMARINE), @ConfigMaterialMapEntry(key = "portal", value = Material.AIR), - } - ), - } - ), - }, - desc = "Portal style definitions. Must provide a material for each portal block type and activation state. The default style may be overridden." - ) + }), + }), + }, desc = "Portal style definitions. Must provide a material for each portal block type and activation state. The default style may be overridden.") public Map>> config_styles; - @ConfigLong( - def = 10000, - min = 1000, - max = 110000, - desc = "Delay in milliseconds after which two connected portals will automatically be disabled. Purple end-gateway beams do not show up until the maximum value of 110 seconds." - ) + @ConfigLong(def = 10000, min = 1000, max = 110000, desc = "Delay in milliseconds after which two connected portals will automatically be disabled. Purple end-gateway beams do not show up until the maximum value of 110 seconds.") public long config_deactivation_delay; - @ConfigExtendedMaterial( - def = "vane:decoration_end_portal_orb", - desc = "The default portal icon. Also accepts heads from the head library." - ) + @ConfigExtendedMaterial(def = "vane:decoration_end_portal_orb", desc = "The default portal icon. Also accepts heads from the head library.") public ExtendedMaterial config_default_icon; - @ConfigDouble( - def = 0.9, - min = 0.0, - max = 1.0, - desc = "Volume for the portal activation sound effect. 0 to disable." - ) + @ConfigDouble(def = 0.9, min = 0.0, max = 1.0, desc = "Volume for the portal activation sound effect. 0 to disable.") public double config_volume_activation; - @ConfigDouble( - def = 1.0, - min = 0.0, - max = 1.0, - desc = "Volume for the portal deactivation sound effect. 0 to disable." - ) + @ConfigDouble(def = 1.0, min = 0.0, max = 1.0, desc = "Volume for the portal deactivation sound effect. 0 to disable.") public double config_volume_deactivation; @LangMessage @@ -231,7 +196,8 @@ public class Portals extends Module { // All loaded styles public Map styles = new HashMap<>(); - // Cache possible area materials. This is fine as only predefined styles can change this. + // Cache possible area materials. This is fine as only predefined styles can + // change this. public Set portal_area_materials = new HashSet<>(); // Track console items @@ -261,43 +227,40 @@ public Portals() { blue_map_layer = new PortalBlueMapLayer(this); // Register admin permission - admin_permission = - new Permission( + admin_permission = new Permission( "vane." + get_module().get_name() + ".admin", "Allows administration of any portal", - PermissionDefault.OP - ); + PermissionDefault.OP); get_module().register_permission(admin_permission); // TODO legacy, remove in v2. persistent_storage_manager.add_migration_to( - 2, - "Portal visibility GROUP_INTERNAL was added. This is a no-op.", - json -> {} - ); + 2, + "Portal visibility GROUP_INTERNAL was added. This is a no-op.", + json -> { + }); } @SuppressWarnings("unchecked") private void register_entities() { get_module().core.unfreeze_registries(); register_entity( - NamespacedKey.minecraft("item"), - namespace(), - "floating_item", - EntityType.Builder.of(FloatingItem::new, MobCategory.MISC).sized(0.0f, 0.0f) - ); + NamespacedKey.minecraft("item"), + namespace(), + "floating_item", + EntityType.Builder.of(FloatingItem::new, MobCategory.MISC).sized(0.0f, 0.0f)); } private static long block_key(final Block block) { return (block.getY() << 8) - | ((block.getX() & 0xF) << 4) - | ((block.getZ() & 0xF)); + | ((block.getX() & 0xF) << 4) + | ((block.getZ() & 0xF)); } private static Block unpack_block_key(final Chunk chunk, long block_key) { - int y = (int)(block_key >> 8); - int x = (int)((block_key >> 4) & 0xF); - int z = (int)(block_key & 0xF); + int y = (int) (block_key >> 8); + int x = (int) ((block_key >> 4) & 0xF); + int z = (int) (block_key & 0xF); return chunk.getBlock(x, y, z); } @@ -361,8 +324,7 @@ public void set_is_in_same_region_group_callback(final 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 - ) { + final Function2 callback) { player_can_use_portals_in_region_group_of_callback = callback; } @@ -416,11 +378,11 @@ public void remove_portal(final Portal portal) { if (Objects.equals(other.target_id(), portal.id())) { other.target_id(null); other - .blocks() - .stream() - .filter(pb -> pb.type() == PortalBlock.Type.CONSOLE) - .filter(pb -> console_floating_items.containsKey(pb.block())) - .forEach(pb -> update_console_item(other, pb.block())); + .blocks() + .stream() + .filter(pb -> pb.type() == PortalBlock.Type.CONSOLE) + .filter(pb -> console_floating_items.containsKey(pb.block())) + .forEach(pb -> update_console_item(other, pb.block())); } } @@ -429,23 +391,21 @@ public void remove_portal(final Portal portal) { // Close and taint all related open menus get_module().core.menu_manager.for_each_open((player, menu) -> { - if ( - menu.tag() instanceof PortalMenuTag && - Objects.equals(((PortalMenuTag) menu.tag()).portal_id(), portal.id()) - ) { - menu.taint(); - menu.close(player); - } - }); + if (menu.tag() instanceof PortalMenuTag && + Objects.equals(((PortalMenuTag) menu.tag()).portal_id(), portal.id())) { + menu.taint(); + menu.close(player); + } + }); // Remove map marker remove_marker(portal.id()); // Play sound portal - .spawn() - .getWorld() - .playSound(portal.spawn(), Sound.ENTITY_ENDER_EYE_DEATH, SoundCategory.BLOCKS, 1.0f, 1.0f); + .spawn() + .getWorld() + .playSound(portal.spawn(), Sound.ENTITY_ENDER_EYE_DEATH, SoundCategory.BLOCKS, 1.0f, 1.0f); } public void add_new_portal(final Portal portal) { @@ -456,9 +416,9 @@ public void add_new_portal(final Portal portal) { // Play sound portal - .spawn() - .getWorld() - .playSound(portal.spawn(), Sound.ENTITY_ENDER_EYE_DEATH, SoundCategory.BLOCKS, 1.0f, 2.0f); + .spawn() + .getWorld() + .playSound(portal.spawn(), Sound.ENTITY_ENDER_EYE_DEATH, SoundCategory.BLOCKS, 1.0f, 2.0f); } public void index_portal(final Portal portal) { @@ -471,21 +431,37 @@ public void index_portal(final Portal portal) { public Collection all_available_portals() { return portals.values().stream() - .filter(p -> p.spawn().isWorldLoaded()) - .collect(Collectors.toList()); + .filter(p -> p.spawn().isWorldLoaded()) + .collect(Collectors.toList()); } public void remove_portal_block(final PortalBlock portal_block) { // Restore original block switch (portal_block.type()) { - case ORIGIN: portal_block.block().setType(constructor.config_material_origin); break; - case CONSOLE: portal_block.block().setType(constructor.config_material_console); break; - case BOUNDARY_1: portal_block.block().setType(constructor.config_material_boundary_1); break; - case BOUNDARY_2: portal_block.block().setType(constructor.config_material_boundary_2); break; - case BOUNDARY_3: portal_block.block().setType(constructor.config_material_boundary_3); break; - case BOUNDARY_4: portal_block.block().setType(constructor.config_material_boundary_4); break; - case BOUNDARY_5: portal_block.block().setType(constructor.config_material_boundary_5); break; - case PORTAL: portal_block.block().setType(constructor.config_material_portal_area); break; + case ORIGIN: + portal_block.block().setType(constructor.config_material_origin); + break; + case CONSOLE: + portal_block.block().setType(constructor.config_material_console); + break; + case BOUNDARY_1: + portal_block.block().setType(constructor.config_material_boundary_1); + break; + case BOUNDARY_2: + portal_block.block().setType(constructor.config_material_boundary_2); + break; + case BOUNDARY_3: + portal_block.block().setType(constructor.config_material_boundary_3); + break; + case BOUNDARY_4: + portal_block.block().setType(constructor.config_material_boundary_4); + break; + case BOUNDARY_5: + portal_block.block().setType(constructor.config_material_boundary_5); + break; + case PORTAL: + portal_block.block().setType(constructor.config_material_portal_area); + break; } // Remove console item if a block is a console @@ -511,7 +487,8 @@ public void remove_portal_block(final PortalBlock portal_block) { // Spawn effect if not portal area if (portal_block.type() != PortalBlock.Type.PORTAL) { portal_block.block().getWorld() - .spawnParticle(Particle.ENCHANT, portal_block.block().getLocation().add(0.5, 0.5, 0.5), 50, 0.0, 0.0, 0.0, 1.0); + .spawnParticle(Particle.ENCHANT, portal_block.block().getLocation().add(0.5, 0.5, 0.5), 50, 0.0, + 0.0, 0.0, 1.0); } } @@ -533,7 +510,8 @@ public void add_new_portal_block(final Portal portal, final PortalBlock portal_b // Spawn effect if not portal area if (portal_block.type() != PortalBlock.Type.PORTAL) { portal_block.block().getWorld() - .spawnParticle(Particle.PORTAL, portal_block.block().getLocation().add(0.5, 0.5, 0.5), 50, 0.0, 0.0, 0.0, 1.0); + .spawnParticle(Particle.PORTAL, portal_block.block().getLocation().add(0.5, 0.5, 0.5), 50, 0.0, 0.0, + 0.0, 1.0); } } @@ -606,7 +584,8 @@ public Portal controlled_portal(final Block block) { return root_portal; } - // Find adjacent console blocks in full 3x3x3 cube, which will make this block a controlling block + // Find adjacent console blocks in full 3x3x3 cube, which will make this block a + // controlling block for (final var adj : adjacent_blocks_3d(block)) { final var portal_block = portal_block_for(adj); if (portal_block != null && portal_block.type() == PortalBlock.Type.CONSOLE) { @@ -710,9 +689,8 @@ public void disconnect_portals(final Portal src, final Portal dst) { private void start_disable_task(final Portal portal, final Portal target) { stop_disable_task(portal, target); final var task = schedule_task( - new PortalDisableRunnable(portal, target), - ms_to_ticks(config_deactivation_delay) - ); + new PortalDisableRunnable(portal, target), + ms_to_ticks(config_deactivation_delay)); disable_tasks.put(portal.id(), task); disable_tasks.put(target.id(), task); } @@ -848,8 +826,8 @@ public void update_console_item(final Portal portal, final Block block) { var console_item = console_floating_items.get(block); final boolean is_new; if (console_item == null) { - console_item = - new FloatingItem(block.getWorld(), block.getX() + 0.5, block.getY() + 1.2, block.getZ() + 0.5); + console_item = new FloatingItem(block.getWorld(), block.getX() + 0.5, block.getY() + 1.2, + block.getZ() + 0.5); is_new = true; } else { is_new = false; @@ -872,9 +850,8 @@ public void remove_console_item(final Block block) { } private void for_each_console_block_in_chunk( - final Chunk chunk, - final Consumer2 consumer - ) { + final Chunk chunk, + final Consumer2 consumer) { final var portal_blocks_in_chunk = portal_blocks_in_chunk_in_world.get(chunk.getWorld().getUID()); if (portal_blocks_in_chunk == null) { return; @@ -907,12 +884,11 @@ public void on_monitor_chunk_load(final ChunkLoadEvent event) { // Enable all consoles in this chunk for_each_console_block_in_chunk( - chunk, - (block, console) -> { - final var portal = portal_for(console.portal_id()); - update_console_item(portal, block); - } - ); + chunk, + (block, console) -> { + final var portal = portal_for(console.portal_id()); + update_console_item(portal, block); + }); } public void update_marker(final Portal portal) { @@ -955,14 +931,14 @@ public void load_persistent_data(final World world) { // Load all currently stored portals. final var pdc_portals = data.getKeys().stream() - .filter(key -> key.toString().startsWith(storage_portal_prefix)) - .map(key -> StringUtils.removeStart(key.toString(), storage_portal_prefix)) - .map(uuid -> UUID.fromString(uuid)) - .collect(Collectors.toSet()); + .filter(key -> key.toString().startsWith(storage_portal_prefix)) + .map(key -> StringUtils.removeStart(key.toString(), storage_portal_prefix)) + .map(uuid -> UUID.fromString(uuid)) + .collect(Collectors.toSet()); for (final var portal_id : pdc_portals) { final var json_bytes = data.get(NamespacedKey.fromString(storage_portal_prefix + portal_id.toString()), - PersistentDataType.BYTE_ARRAY); + PersistentDataType.BYTE_ARRAY); try { final var portal = PersistentSerializer.from_json(Portal.class, new JSONObject(new String(json_bytes))); index_portal(portal); @@ -970,7 +946,8 @@ public void load_persistent_data(final World world) { log.log(Level.SEVERE, "error while serializing persistent data!", e); } } - log.log(Level.INFO, "Loaded " + pdc_portals.size() + " portals for world " + world.getName() + "(" + world.getUID() + ")"); + log.log(Level.INFO, + "Loaded " + pdc_portals.size() + " portals for world " + world.getName() + "(" + world.getUID() + ")"); // Convert portals from legacy storage final Set remove_from_legacy_storage = new HashSet<>(); @@ -1001,12 +978,11 @@ public void load_persistent_data(final World world) { // to this function, and it can't be synchronized without annoying the server. for (final var chunk : world.getLoadedChunks()) { for_each_console_block_in_chunk( - chunk, - (block, console) -> { - final var portal = portal_for(console.portal_id()); - update_console_item(portal, block); - } - ); + chunk, + (block, console) -> { + final var portal = portal_for(console.portal_id()); + update_console_item(portal, block); + }); } // Save if we had any conversions @@ -1021,29 +997,30 @@ public void update_persistent_data(final World world) { // Update invalidated portals portals.values().stream() - .filter(x -> x.invalidated && x.spawn_world().equals(world.getUID())) - .forEach(portal -> { - try { - final var json = PersistentSerializer.to_json(Portal.class, portal); - data.set(NamespacedKey.fromString(storage_portal_prefix + portal.id().toString()), - PersistentDataType.BYTE_ARRAY, json.toString().getBytes()); - } catch (IOException e) { - log.log(Level.SEVERE, "error while serializing persistent data!", e); - return; - } + .filter(x -> x.invalidated && x.spawn_world().equals(world.getUID())) + .forEach(portal -> { + try { + final var json = PersistentSerializer.to_json(Portal.class, portal); + data.set(NamespacedKey.fromString(storage_portal_prefix + portal.id().toString()), + PersistentDataType.BYTE_ARRAY, json.toString().getBytes()); + } catch (IOException e) { + log.log(Level.SEVERE, "error while serializing persistent data!", e); + return; + } - portal.invalidated = false; - }); + portal.invalidated = false; + }); // Get all currently stored portals. final var stored_portals = data.getKeys().stream() - .filter(key -> key.toString().startsWith(storage_portal_prefix)) - .map(key -> StringUtils.removeStart(key.toString(), storage_portal_prefix)) - .map(uuid -> UUID.fromString(uuid)) - .collect(Collectors.toSet()); + .filter(key -> key.toString().startsWith(storage_portal_prefix)) + .map(key -> StringUtils.removeStart(key.toString(), storage_portal_prefix)) + .map(uuid -> UUID.fromString(uuid)) + .collect(Collectors.toSet()); // Remove all portals that no longer exist - Sets.difference(stored_portals, portals.keySet()).forEach(id -> data.remove(NamespacedKey.fromString(storage_portal_prefix + id.toString()))); + Sets.difference(stored_portals, portals.keySet()) + .forEach(id -> data.remove(NamespacedKey.fromString(storage_portal_prefix + id.toString()))); } private class PortalDisableRunnable implements Runnable { diff --git a/vane-portals/src/main/java/org/oddlama/vane/portals/menu/StyleMenu.java b/vane-portals/src/main/java/org/oddlama/vane/portals/menu/StyleMenu.java index 812167a83..de21153ed 100644 --- a/vane-portals/src/main/java/org/oddlama/vane/portals/menu/StyleMenu.java +++ b/vane-portals/src/main/java/org/oddlama/vane/portals/menu/StyleMenu.java @@ -111,155 +111,119 @@ public class StyleMenu extends ModuleComponent { public StyleMenu(Context context) { super(context.namespace("style")); final var ctx = get_context(); - item_block_console_active = - new TranslatedItemStack<>( + item_block_console_active = new TranslatedItemStack<>( ctx, "block_console_active", Material.BARRIER, 1, - "Used to select active console block." - ); - item_block_origin_active = - new TranslatedItemStack<>( + "Used to select active console block."); + item_block_origin_active = new TranslatedItemStack<>( ctx, "block_origin_active", Material.BARRIER, 1, - "Used to select active origin block." - ); - item_block_portal_active = - new TranslatedItemStack<>( + "Used to select active origin block."); + item_block_portal_active = new TranslatedItemStack<>( ctx, "block_portal_active", Material.BARRIER, 1, - "Used to select active portal area block. Defaults to end gateway if unset." - ); - item_block_boundary_1_active = - new TranslatedItemStack<>( + "Used to select active portal area block. Defaults to end gateway if unset."); + item_block_boundary_1_active = new TranslatedItemStack<>( ctx, "block_boundary_1_active", Material.BARRIER, 1, - "Used to select active boundary variant 1 block." - ); - item_block_boundary_2_active = - new TranslatedItemStack<>( + "Used to select active boundary variant 1 block."); + item_block_boundary_2_active = new TranslatedItemStack<>( ctx, "block_boundary_2_active", Material.BARRIER, 1, - "Used to select active boundary variant 2 block." - ); - item_block_boundary_3_active = - new TranslatedItemStack<>( + "Used to select active boundary variant 2 block."); + item_block_boundary_3_active = new TranslatedItemStack<>( ctx, "block_boundary_3_active", Material.BARRIER, 1, - "Used to select active boundary variant 3 block." - ); - item_block_boundary_4_active = - new TranslatedItemStack<>( + "Used to select active boundary variant 3 block."); + item_block_boundary_4_active = new TranslatedItemStack<>( ctx, "block_boundary_4_active", Material.BARRIER, 1, - "Used to select active boundary variant 4 block." - ); - item_block_boundary_5_active = - new TranslatedItemStack<>( + "Used to select active boundary variant 4 block."); + item_block_boundary_5_active = new TranslatedItemStack<>( ctx, "block_boundary_5_active", Material.BARRIER, 1, - "Used to select active boundary variant 5 block." - ); - item_block_console_inactive = - new TranslatedItemStack<>( + "Used to select active boundary variant 5 block."); + item_block_console_inactive = new TranslatedItemStack<>( ctx, "block_console_inactive", Material.BARRIER, 1, - "Used to select inactive console block." - ); - item_block_origin_inactive = - new TranslatedItemStack<>( + "Used to select inactive console block."); + item_block_origin_inactive = new TranslatedItemStack<>( ctx, "block_origin_inactive", Material.BARRIER, 1, - "Used to select inactive origin block." - ); - item_block_portal_inactive = - new TranslatedItemStack<>( + "Used to select inactive origin block."); + item_block_portal_inactive = new TranslatedItemStack<>( ctx, "block_portal_inactive", Material.BARRIER, 1, - "Used to select inactive portal area block." - ); - item_block_boundary_1_inactive = - new TranslatedItemStack<>( + "Used to select inactive portal area block."); + item_block_boundary_1_inactive = new TranslatedItemStack<>( ctx, "block_boundary_1_inactive", Material.BARRIER, 1, - "Used to select inactive boundary variant 1 block." - ); - item_block_boundary_2_inactive = - new TranslatedItemStack<>( + "Used to select inactive boundary variant 1 block."); + item_block_boundary_2_inactive = new TranslatedItemStack<>( ctx, "block_boundary_2_inactive", Material.BARRIER, 1, - "Used to select inactive boundary variant 2 block." - ); - item_block_boundary_3_inactive = - new TranslatedItemStack<>( + "Used to select inactive boundary variant 2 block."); + item_block_boundary_3_inactive = new TranslatedItemStack<>( ctx, "block_boundary_3_inactive", Material.BARRIER, 1, - "Used to select inactive boundary variant 3 block." - ); - item_block_boundary_4_inactive = - new TranslatedItemStack<>( + "Used to select inactive boundary variant 3 block."); + item_block_boundary_4_inactive = new TranslatedItemStack<>( ctx, "block_boundary_4_inactive", Material.BARRIER, 1, - "Used to select inactive boundary variant 4 block." - ); - item_block_boundary_5_inactive = - new TranslatedItemStack<>( + "Used to select inactive boundary variant 4 block."); + item_block_boundary_5_inactive = new TranslatedItemStack<>( ctx, "block_boundary_5_inactive", Material.BARRIER, 1, - "Used to select inactive boundary variant 5 block." - ); + "Used to select inactive boundary variant 5 block."); item_accept = new TranslatedItemStack<>(ctx, "accept", Material.LIME_TERRACOTTA, 1, "Used to apply the style."); item_reset = new TranslatedItemStack<>(ctx, "reset", Material.MILK_BUCKET, 1, "Used to reset any changes."); - item_select_defined = - new TranslatedItemStack<>( + item_select_defined = new TranslatedItemStack<>( ctx, "select_defined", Material.ITEM_FRAME, 1, - "Used to select a defined style from the configuration." - ); - item_select_style = - new TranslatedItemStack<>( + "Used to select a defined style from the configuration."); + item_select_style = new TranslatedItemStack<>( ctx, "select_style", Material.ITEM_FRAME, 1, - "Used to represent a defined style in the selector menu." - ); - item_cancel = - new TranslatedItemStack<>(ctx, "cancel", Material.RED_TERRACOTTA, 1, "Used to abort style selection."); + "Used to represent a defined style in the selector menu."); + item_cancel = new TranslatedItemStack<>(ctx, "cancel", Material.RED_TERRACOTTA, 1, + "Used to abort style selection."); } public Menu create(final Portal portal, final Player player, final Menu previous) { @@ -272,186 +236,159 @@ public Menu create(final Portal portal, final Player player, final Menu previous style_container.style = portal.copy_style(get_module(), null); style_menu.add( - menu_item_block_selector( - portal, - style_container, - 0, - item_block_console_inactive, - get_module().constructor.config_material_console, - lang_select_block_console_inactive_title.str(), - PortalBlock.Type.CONSOLE, - false - ) - ); + menu_item_block_selector( + portal, + style_container, + 0, + item_block_console_inactive, + get_module().constructor.config_material_console, + lang_select_block_console_inactive_title.str(), + PortalBlock.Type.CONSOLE, + false)); style_menu.add( - menu_item_block_selector( - portal, - style_container, - 1, - item_block_origin_inactive, - get_module().constructor.config_material_origin, - lang_select_block_origin_inactive_title.str(), - PortalBlock.Type.ORIGIN, - false - ) - ); + menu_item_block_selector( + portal, + style_container, + 1, + item_block_origin_inactive, + get_module().constructor.config_material_origin, + lang_select_block_origin_inactive_title.str(), + PortalBlock.Type.ORIGIN, + false)); style_menu.add( - menu_item_block_selector( - portal, - style_container, - 2, - item_block_portal_inactive, - get_module().constructor.config_material_portal_area, - lang_select_block_portal_inactive_title.str(), - PortalBlock.Type.PORTAL, - false - ) - ); + menu_item_block_selector( + portal, + style_container, + 2, + item_block_portal_inactive, + get_module().constructor.config_material_portal_area, + lang_select_block_portal_inactive_title.str(), + PortalBlock.Type.PORTAL, + false)); style_menu.add( - menu_item_block_selector( - portal, - style_container, - 4, - item_block_boundary_1_inactive, - get_module().constructor.config_material_boundary_1, - lang_select_block_boundary_1_inactive_title.str(), - PortalBlock.Type.BOUNDARY_1, - false - ) - ); + menu_item_block_selector( + portal, + style_container, + 4, + item_block_boundary_1_inactive, + get_module().constructor.config_material_boundary_1, + lang_select_block_boundary_1_inactive_title.str(), + PortalBlock.Type.BOUNDARY_1, + false)); style_menu.add( - menu_item_block_selector( - portal, - style_container, - 5, - item_block_boundary_2_inactive, - get_module().constructor.config_material_boundary_2, - lang_select_block_boundary_2_inactive_title.str(), - PortalBlock.Type.BOUNDARY_2, - false - ) - ); + menu_item_block_selector( + portal, + style_container, + 5, + item_block_boundary_2_inactive, + get_module().constructor.config_material_boundary_2, + lang_select_block_boundary_2_inactive_title.str(), + PortalBlock.Type.BOUNDARY_2, + false)); style_menu.add( - menu_item_block_selector( - portal, - style_container, - 6, - item_block_boundary_3_inactive, - get_module().constructor.config_material_boundary_3, - lang_select_block_boundary_3_inactive_title.str(), - PortalBlock.Type.BOUNDARY_3, - false - ) - ); + menu_item_block_selector( + portal, + style_container, + 6, + item_block_boundary_3_inactive, + get_module().constructor.config_material_boundary_3, + lang_select_block_boundary_3_inactive_title.str(), + PortalBlock.Type.BOUNDARY_3, + false)); style_menu.add( - menu_item_block_selector( - portal, - style_container, - 7, - item_block_boundary_4_inactive, - get_module().constructor.config_material_boundary_4, - lang_select_block_boundary_4_inactive_title.str(), - PortalBlock.Type.BOUNDARY_4, - false - ) - ); + menu_item_block_selector( + portal, + style_container, + 7, + item_block_boundary_4_inactive, + get_module().constructor.config_material_boundary_4, + lang_select_block_boundary_4_inactive_title.str(), + PortalBlock.Type.BOUNDARY_4, + false)); style_menu.add( - menu_item_block_selector( - portal, - style_container, - 8, - item_block_boundary_5_inactive, - get_module().constructor.config_material_boundary_5, - lang_select_block_boundary_5_inactive_title.str(), - PortalBlock.Type.BOUNDARY_5, - false - ) - ); + menu_item_block_selector( + portal, + style_container, + 8, + item_block_boundary_5_inactive, + get_module().constructor.config_material_boundary_5, + lang_select_block_boundary_5_inactive_title.str(), + PortalBlock.Type.BOUNDARY_5, + false)); style_menu.add( - menu_item_block_selector( - portal, - style_container, - columns, - item_block_console_active, - get_module().constructor.config_material_console, - lang_select_block_console_active_title.str(), - PortalBlock.Type.CONSOLE, - true - ) - ); + menu_item_block_selector( + portal, + style_container, + columns, + item_block_console_active, + get_module().constructor.config_material_console, + lang_select_block_console_active_title.str(), + PortalBlock.Type.CONSOLE, + true)); style_menu.add( - menu_item_block_selector( - portal, - style_container, - columns + 1, - item_block_origin_active, - get_module().constructor.config_material_origin, - lang_select_block_origin_active_title.str(), - PortalBlock.Type.ORIGIN, - true - ) - ); - // style_menu.add(menu_item_block_selector(portal, style_container, 1 * columns + 2, item_block_portal_active, get_module().constructor.config_material_portal_area, lang_select_block_portal_active_title.str(), PortalBlock.Type.PORTAL, true)); + menu_item_block_selector( + portal, + style_container, + columns + 1, + item_block_origin_active, + get_module().constructor.config_material_origin, + lang_select_block_origin_active_title.str(), + PortalBlock.Type.ORIGIN, + true)); + // style_menu.add(menu_item_block_selector(portal, style_container, 1 * columns + // + 2, item_block_portal_active, + // get_module().constructor.config_material_portal_area, + // lang_select_block_portal_active_title.str(), PortalBlock.Type.PORTAL, true)); style_menu.add( - menu_item_block_selector( - portal, - style_container, - columns + 4, - item_block_boundary_1_active, - get_module().constructor.config_material_boundary_1, - lang_select_block_boundary_1_active_title.str(), - PortalBlock.Type.BOUNDARY_1, - true - ) - ); + menu_item_block_selector( + portal, + style_container, + columns + 4, + item_block_boundary_1_active, + get_module().constructor.config_material_boundary_1, + lang_select_block_boundary_1_active_title.str(), + PortalBlock.Type.BOUNDARY_1, + true)); style_menu.add( - menu_item_block_selector( - portal, - style_container, - columns + 5, - item_block_boundary_2_active, - get_module().constructor.config_material_boundary_2, - lang_select_block_boundary_2_active_title.str(), - PortalBlock.Type.BOUNDARY_2, - true - ) - ); + menu_item_block_selector( + portal, + style_container, + columns + 5, + item_block_boundary_2_active, + get_module().constructor.config_material_boundary_2, + lang_select_block_boundary_2_active_title.str(), + PortalBlock.Type.BOUNDARY_2, + true)); style_menu.add( - menu_item_block_selector( - portal, - style_container, - columns + 6, - item_block_boundary_3_active, - get_module().constructor.config_material_boundary_3, - lang_select_block_boundary_3_active_title.str(), - PortalBlock.Type.BOUNDARY_3, - true - ) - ); + menu_item_block_selector( + portal, + style_container, + columns + 6, + item_block_boundary_3_active, + get_module().constructor.config_material_boundary_3, + lang_select_block_boundary_3_active_title.str(), + PortalBlock.Type.BOUNDARY_3, + true)); style_menu.add( - menu_item_block_selector( - portal, - style_container, - columns + 7, - item_block_boundary_4_active, - get_module().constructor.config_material_boundary_4, - lang_select_block_boundary_4_active_title.str(), - PortalBlock.Type.BOUNDARY_4, - true - ) - ); + menu_item_block_selector( + portal, + style_container, + columns + 7, + item_block_boundary_4_active, + get_module().constructor.config_material_boundary_4, + lang_select_block_boundary_4_active_title.str(), + PortalBlock.Type.BOUNDARY_4, + true)); style_menu.add( - menu_item_block_selector( - portal, - style_container, - columns + 8, - item_block_boundary_5_active, - get_module().constructor.config_material_boundary_5, - lang_select_block_boundary_5_active_title.str(), - PortalBlock.Type.BOUNDARY_5, - true - ) - ); + menu_item_block_selector( + portal, + style_container, + columns + 8, + item_block_boundary_5_active, + get_module().constructor.config_material_boundary_5, + lang_select_block_boundary_5_active_title.str(), + PortalBlock.Type.BOUNDARY_5, + true)); style_menu.add(menu_item_accept(portal, style_container, previous)); style_menu.add(menu_item_reset(portal, style_container)); @@ -463,10 +400,9 @@ public Menu create(final Portal portal, final Player player, final Menu previous } private static ItemStack item_for_type( - final StyleContainer style_container, - final boolean active, - final PortalBlock.Type type - ) { + final StyleContainer style_container, + final boolean active, + final PortalBlock.Type type) { if (active && type == PortalBlock.Type.PORTAL) { return new ItemStack(Material.AIR); } @@ -514,6 +450,26 @@ private MenuWidget menu_item_block_selector( if (item == null || !(item.getType().isBlock() && item.getType().isSolid())) { return null; } + + // Nothing from the blacklist + if (get_module().config_blacklisted_materials.contains(item.getType())) { + return null; + } + + // Must be a block (should be given at this point) + var block = item.getType().asBlockType(); + if (block == null) { + return null; + } + + // Must be a full block with one AABB of extent (1,1,1) + var blockdata = block.createBlockData(); + var voxelshape = blockdata.getCollisionShape(player.getLocation()); + var bbs = voxelshape.getBoundingBoxes(); + if (bbs.size() != 1 || !bbs.stream().allMatch(x -> x.getWidthX() == 1.0 && x.getWidthZ() == 1.0 && x.getHeight() == 1.0)) { + return null; + } + // Always select one item.setAmount(1); return item; @@ -537,40 +493,37 @@ public void item(final ItemStack item) { } private MenuWidget menu_item_accept( - final Portal portal, - final StyleContainer style_container, - final Menu previous - ) { + final Portal portal, + final StyleContainer style_container, + final Menu previous) { return new MenuItem( 3 * columns, - item_accept.item(), - (player, menu, self) -> { - menu.close(player); - - final var settings_event = new PortalChangeSettingsEvent(player, portal, false); - get_module().getServer().getPluginManager().callEvent(settings_event); - if (settings_event.isCancelled() && !player.hasPermission(get_module().admin_permission)) { - return ClickResult.ERROR; - } - - portal.style(style_container.style); - portal.update_blocks(get_module()); - previous.open(player); - return ClickResult.SUCCESS; - } - ); + item_accept.item(), + (player, menu, self) -> { + menu.close(player); + + final var settings_event = new PortalChangeSettingsEvent(player, portal, false); + get_module().getServer().getPluginManager().callEvent(settings_event); + if (settings_event.isCancelled() && !player.hasPermission(get_module().admin_permission)) { + return ClickResult.ERROR; + } + + portal.style(style_container.style); + portal.update_blocks(get_module()); + previous.open(player); + return ClickResult.SUCCESS; + }); } private MenuWidget menu_item_reset(final Portal portal, final StyleContainer style_container) { return new MenuItem( - 3 * columns + 3, - item_reset.item(), - (player, menu, self) -> { - style_container.style = portal.copy_style(get_module(), null); - menu.update(); - return ClickResult.SUCCESS; - } - ); + 3 * columns + 3, + item_reset.item(), + (player, menu, self) -> { + style_container.style = portal.copy_style(get_module(), null); + menu.update(); + return ClickResult.SUCCESS; + }); } private MenuWidget menu_item_select_defined(final Portal portal, final StyleContainer style_container) { @@ -584,56 +537,54 @@ private MenuWidget menu_item_select_defined(final Portal portal, final StyleCont }; return new MenuItem( - 3 * columns + 4, - item_select_defined.item(), - (player, menu, self) -> { - menu.close(player); - final var all_styles = new ArrayList<>(get_module().styles.values()); - final var filter = new Filter.StringFilter