simplified code: shared entity tagging, world name scheme, less boilerplate

New EntityTagUtil replaces the three copies of the tag/find/remove
logic for display and interaction entities. The pixel world naming
scheme (build, parse, recognize) now lives in one place in
PixelBlockWorld with a cached base path instead of allocating on every
event. getPixels works with int arithmetic instead of two Location
allocations per cell, setBuildingPlatform lost its copy-pasted loops
and rebuilds the flower list only once, SubCommand is an abstract base
class instead of an interface with 12 trivial getters, and dead
methods were removed.
This commit is contained in:
2026-07-23 22:59:00 +02:00
parent a024e42b80
commit 0aa098ae8f
9 changed files with 129 additions and 133 deletions
@@ -9,9 +9,9 @@ public record PixelBlockConfiguration(
boolean onlyEditableByOwner boolean onlyEditableByOwner
) { ) {
public static void setDefaults(FileConfiguration config) { public static void setDefaults(FileConfiguration config) {
config.addDefault(Keys.PixelsPerBlock.key, 16); config.addDefault(Keys.PixelsPerBlock.getKey(), 16);
config.addDefault(Keys.OnlyBreakableByOwners.key, false); config.addDefault(Keys.OnlyBreakableByOwners.getKey(), false);
config.addDefault(Keys.OnlyEditableByOwners.key, true); config.addDefault(Keys.OnlyEditableByOwners.getKey(), true);
config.options().copyDefaults(true); config.options().copyDefaults(true);
} }
@@ -5,11 +5,7 @@ import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener; import org.bukkit.event.Listener;
import org.bukkit.event.inventory.CraftItemEvent; import org.bukkit.event.inventory.CraftItemEvent;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.persistence.PersistentDataContainer;
import org.bukkit.persistence.PersistentDataType;
import java.util.Objects;
import java.util.UUID; import java.util.UUID;
public class CraftPixelBlockListener implements Listener { public class CraftPixelBlockListener implements Listener {
@@ -17,14 +13,10 @@ public class CraftPixelBlockListener implements Listener {
public void onCraft(CraftItemEvent event) { public void onCraft(CraftItemEvent event) {
ItemStack result = event.getInventory().getResult(); ItemStack result = event.getInventory().getResult();
if(result == null) return; if(result == null) return;
ItemMeta itemMeta = result.getItemMeta();
PersistentDataContainer dataContainer = itemMeta.getPersistentDataContainer();
if(!dataContainer.has(PixelBlockItem.idProperty)) return;
String currentId = dataContainer.get(PixelBlockItem.idProperty, PersistentDataType.STRING);
Objects.requireNonNull(currentId);
if(!UUID.fromString(currentId).equals(PixelBlockItem.emptyBlockUUID)) return;
dataContainer.set(PixelBlockItem.idProperty, PersistentDataType.STRING, UUID.randomUUID().toString()); PixelBlockItem.BlockInfo info = PixelBlockItem.getBlockInfo(result);
result.setItemMeta(itemMeta); if(info == null || !info.id().equals(PixelBlockItem.emptyBlockUUID)) return;
PixelBlockItem.setBlockId(result, UUID.randomUUID());
} }
} }
@@ -38,20 +38,14 @@ public class PixelBlock {
private final UUID blockUUID; private final UUID blockUUID;
public static @Nullable PixelBlock getPixelBlockFromBlockWorld(World world) { public static @Nullable PixelBlock getPixelBlockFromBlockWorld(World world) {
UUID worldUUID = PixelBlockWorld.getUUIDFromWorld(world);
if(worldUUID == null) return null;
return Main.pixelBlocks.stream() return Main.pixelBlocks.stream()
.filter(block -> block.blockUUID.equals(getUUIDFromWorld(world))) .filter(block -> block.blockUUID.equals(worldUUID))
.findFirst() .findFirst()
.orElse(null); .orElse(null);
} }
public static @Nullable UUID getUUIDFromWorld(@NotNull World world) {
try {
return UUID.fromString(List.of(world.getName().split("/")).getLast());
} catch(IllegalArgumentException e) {
return null;
}
}
public static boolean exists(@NotNull UUID blockUUID) { public static boolean exists(@NotNull UUID blockUUID) {
return Main.pixelBlocks.stream().anyMatch(pixelBlock -> pixelBlock.blockUUID.equals(blockUUID)); return Main.pixelBlocks.stream().anyMatch(pixelBlock -> pixelBlock.blockUUID.equals(blockUUID));
} }
@@ -1,16 +1,14 @@
package eu.mhsl.minecraft.pixelblocks.pixelblock; package eu.mhsl.minecraft.pixelblocks.pixelblock;
import eu.mhsl.minecraft.pixelblocks.Main; import eu.mhsl.minecraft.pixelblocks.Main;
import eu.mhsl.minecraft.pixelblocks.utils.EntityTagUtil;
import eu.mhsl.minecraft.pixelblocks.utils.MinMaxUtil; import eu.mhsl.minecraft.pixelblocks.utils.MinMaxUtil;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.NamespacedKey; import org.bukkit.NamespacedKey;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType; import org.bukkit.entity.EntityType;
import org.bukkit.entity.Interaction; import org.bukkit.entity.Interaction;
import org.bukkit.persistence.PersistentDataType;
import java.util.List; import java.util.List;
import java.util.Objects;
public class PixelBlockHitbox { public class PixelBlockHitbox {
private static final NamespacedKey hitboxOfTag = new NamespacedKey(Main.plugin(), "hitbox_of"); private static final NamespacedKey hitboxOfTag = new NamespacedKey(Main.plugin(), "hitbox_of");
@@ -29,7 +27,7 @@ public class PixelBlockHitbox {
Interaction interaction; Interaction interaction;
if (pixels.size() <= 5) { if (pixels.size() <= 5) {
interaction = (Interaction) absoluteLocation.getWorld().spawnEntity( interaction = (Interaction) absoluteLocation.getWorld().spawnEntity(
absoluteLocation.clone().add(0.5, -0, 0.5), absoluteLocation.clone().add(0.5, 0, 0.5),
EntityType.INTERACTION EntityType.INTERACTION
); );
interaction.setInteractionHeight(1); interaction.setInteractionHeight(1);
@@ -45,7 +43,7 @@ public class PixelBlockHitbox {
Location spawnLocation = absoluteLocation.clone().add( Location spawnLocation = absoluteLocation.clone().add(
((startingX+endingX)/2+0.5)/pixelsPerBlock, ((startingX+endingX)/2+0.5)/pixelsPerBlock,
(startingY/pixelsPerBlock)-0, startingY/pixelsPerBlock,
((startingZ+endingZ)/2+0.5)/pixelsPerBlock ((startingZ+endingZ)/2+0.5)/pixelsPerBlock
); );
@@ -81,19 +79,10 @@ public class PixelBlockHitbox {
interaction.setInteractionWidth(width); interaction.setInteractionWidth(width);
} }
interaction.getPersistentDataContainer() EntityTagUtil.tag(interaction, hitboxOfTag, this.parentBlock.getBlockUUID());
.set(hitboxOfTag, PersistentDataType.STRING, this.parentBlock.getBlockUUID().toString());
} }
public void destroy() { public void destroy() {
this.parentBlock.getPixelBlockLocation().getNearbyEntitiesByType(Interaction.class, 1) EntityTagUtil.removeTagged(this.parentBlock.getPixelBlockLocation(), Interaction.class, hitboxOfTag, this.parentBlock.getBlockUUID());
.stream()
.filter(interaction -> interaction.getPersistentDataContainer().has(hitboxOfTag))
.filter(interaction -> Objects.equals(
interaction.getPersistentDataContainer().get(hitboxOfTag, PersistentDataType.STRING),
parentBlock.getBlockUUID().toString()
))
.forEach(Entity::remove);
} }
} }
@@ -1,21 +1,18 @@
package eu.mhsl.minecraft.pixelblocks.pixelblock; package eu.mhsl.minecraft.pixelblocks.pixelblock;
import eu.mhsl.minecraft.pixelblocks.Main; import eu.mhsl.minecraft.pixelblocks.Main;
import eu.mhsl.minecraft.pixelblocks.utils.EntityTagUtil;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.NamespacedKey; import org.bukkit.NamespacedKey;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType; import org.bukkit.entity.EntityType;
import org.bukkit.entity.ItemDisplay; import org.bukkit.entity.ItemDisplay;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.bukkit.persistence.PersistentDataHolder;
import org.bukkit.persistence.PersistentDataType;
import org.bukkit.util.Transformation; import org.bukkit.util.Transformation;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Objects;
import java.util.UUID; import java.util.UUID;
public class PixelBlockPlaceholder { public class PixelBlockPlaceholder {
@@ -67,20 +64,10 @@ public class PixelBlockPlaceholder {
displayContainer.setItemStack(ItemStack.of(Material.WHITE_STAINED_GLASS)); displayContainer.setItemStack(ItemStack.of(Material.WHITE_STAINED_GLASS));
placeholders.add(displayContainer); placeholders.add(displayContainer);
placeholders.stream() placeholders.forEach(placeholder -> EntityTagUtil.tag(placeholder, placeholderOfTag, parentBlockUUID));
.map(PersistentDataHolder::getPersistentDataContainer)
.forEach(container -> container.set(placeholderOfTag, PersistentDataType.STRING, parentBlockUUID.toString()));
} }
public void destroy() { public void destroy() {
this.parentBlock.getPixelBlockLocation() EntityTagUtil.removeTagged(this.parentBlock.getPixelBlockLocation(), ItemDisplay.class, placeholderOfTag, this.parentBlock.getBlockUUID());
.getNearbyEntitiesByType(ItemDisplay.class, 1)
.stream()
.filter(itemDisplay -> itemDisplay.getPersistentDataContainer().has(placeholderOfTag))
.filter(itemDisplay -> Objects.equals(
itemDisplay.getPersistentDataContainer().get(placeholderOfTag, PersistentDataType.STRING),
parentBlock.getBlockUUID().toString()
))
.forEach(Entity::remove);
} }
} }
@@ -4,6 +4,7 @@ import eu.mhsl.minecraft.pixelblocks.Main;
import eu.mhsl.minecraft.pixelblocks.utils.Direction; import eu.mhsl.minecraft.pixelblocks.utils.Direction;
import eu.mhsl.minecraft.pixelblocks.utils.LocationUtil; import eu.mhsl.minecraft.pixelblocks.utils.LocationUtil;
import org.bukkit.*; import org.bukkit.*;
import org.bukkit.block.Block;
import org.bukkit.block.BlockState; import org.bukkit.block.BlockState;
import org.bukkit.block.data.BlockData; import org.bukkit.block.data.BlockData;
import org.bukkit.block.data.Directional; import org.bukkit.block.data.Directional;
@@ -20,6 +21,7 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.Random; import java.util.Random;
import java.util.UUID;
public class PixelBlockWorld { public class PixelBlockWorld {
private final PixelBlock parentPixelBlock; private final PixelBlock parentPixelBlock;
@@ -28,16 +30,28 @@ public class PixelBlockWorld {
int worldGrassBorderWidth = 10; int worldGrassBorderWidth = 10;
int pixelsPerBlock = Main.configuration().pixelsPerBlock(); int pixelsPerBlock = Main.configuration().pixelsPerBlock();
// Kapselt das Namensschema der Pixelwelten: <dataFolder>/worlds/<blockUUID>
private static String worldsBasePath;
private static @NotNull String getWorldsBasePath() {
if(worldsBasePath == null) {
worldsBasePath = Main.plugin().getDataFolder().getPath() + File.separator + "worlds";
}
return worldsBasePath;
}
public static boolean isPixelWorld(@NotNull World world) { public static boolean isPixelWorld(@NotNull World world) {
return world.getName().startsWith(Main.plugin().getDataFolder().getPath()); return world.getName().startsWith(getWorldsBasePath());
} }
public static @NotNull List<World> getOtherWorlds() { public static @Nullable UUID getUUIDFromWorld(@NotNull World world) {
return Bukkit.getWorlds().stream().filter(w -> !PixelBlockWorld.isPixelWorld(w)).toList(); if(!isPixelWorld(world)) return null;
} String worldName = world.getName();
try {
public static @NotNull List<World> getPixelBlockWorlds() { return UUID.fromString(worldName.substring(worldName.lastIndexOf(File.separatorChar) + 1));
return Bukkit.getWorlds().stream().filter(PixelBlockWorld::isPixelWorld).toList(); } catch(IllegalArgumentException e) {
return null;
}
} }
public PixelBlockWorld(PixelBlock parentPixelBlock) { public PixelBlockWorld(PixelBlock parentPixelBlock) {
@@ -55,7 +69,7 @@ public class PixelBlockWorld {
} }
public @NotNull String getWorldPathName() { public @NotNull String getWorldPathName() {
return Main.plugin().getDataFolder().getPath() + File.separator + "worlds" + File.separator + this.parentPixelBlock.getBlockUUID(); return getWorldsBasePath() + File.separator + this.parentPixelBlock.getBlockUUID();
} }
public @NotNull Location getSpawnLocation() { public @NotNull Location getSpawnLocation() {
@@ -78,10 +92,6 @@ public class PixelBlockWorld {
return new Location(this.world, 0, -60, 0); return new Location(this.world, 0, -60, 0);
} }
public @NotNull Location getBuildOriginEnd() {
return getBuildOrigin().add(pixelsPerBlock, pixelsPerBlock, pixelsPerBlock);
}
public @NotNull Location getBorderOrigin() { public @NotNull Location getBorderOrigin() {
return getBuildOrigin().subtract(1, 1, 1); return getBuildOrigin().subtract(1, 1, 1);
} }
@@ -99,31 +109,32 @@ public class PixelBlockWorld {
public List<PixelData> getPixels(Direction direction) { public List<PixelData> getPixels(Direction direction) {
List<PixelData> pixelData = new ArrayList<>(); List<PixelData> pixelData = new ArrayList<>();
Location origin = this.getBuildOrigin();
int max = pixelsPerBlock - 1;
for(int x = 0; x < pixelsPerBlock; x++) { for(int x = 0; x < pixelsPerBlock; x++) {
for(int y = 0; y < pixelsPerBlock; y++) { for(int y = 0; y < pixelsPerBlock; y++) {
for(int z = 0; z < pixelsPerBlock; z++) { for(int z = 0; z < pixelsPerBlock; z++) {
Location relativeLocation = new Location(world, x, y, z); int blockX = switch(direction) {
case south -> x;
case north -> max - x;
case east -> max - z;
case west -> z;
};
int blockZ = switch(direction) {
case south -> z;
case north -> max - z;
case east -> x;
case west -> max - x;
};
Block block = this.world.getBlockAt(origin.getBlockX() + blockX, origin.getBlockY() + y, origin.getBlockZ() + blockZ);
BlockData blockData = block.getBlockData();
if(blockData.getMaterial().isAir()) continue;
Location blockLocation = this.getBuildOrigin();
switch(direction) {
case south ->
blockLocation.add(relativeLocation.x(), relativeLocation.y(), relativeLocation.z());
case north ->
blockLocation.add((pixelsPerBlock - 1) - relativeLocation.x(), relativeLocation.y(), (pixelsPerBlock - 1) - relativeLocation.z());
case east ->
blockLocation.add((pixelsPerBlock - 1) - relativeLocation.z(), relativeLocation.y(), relativeLocation.x());
case west ->
blockLocation.add(relativeLocation.z(), relativeLocation.y(), (pixelsPerBlock - 1) - relativeLocation.x());
}
BlockData blockData = blockLocation.getBlock().getBlockData();
@Nullable Directional directional = blockData instanceof Directional face ? face : null; @Nullable Directional directional = blockData instanceof Directional face ? face : null;
@Nullable Rotatable rotatable = blockData instanceof Rotatable rotation ? rotation : null; @Nullable Rotatable rotatable = blockData instanceof Rotatable rotation ? rotation : null;
BlockState state = blockLocation.getBlock().getState(); pixelData.add(new PixelData(new Vector(x, y, z), blockData, directional, rotatable, block.getState(), (double) 1 / pixelsPerBlock));
if(!blockData.getMaterial().isAir()) {
pixelData.add(new PixelData(relativeLocation.toVector(), blockData, directional, rotatable, state, (double) 1 / pixelsPerBlock));
}
} }
} }
} }
@@ -156,27 +167,38 @@ public class PixelBlockWorld {
return world; return world;
} }
private static final List<Material> FLOWERS = List.of(
Material.DANDELION,
Material.POPPY,
Material.BLUE_ORCHID,
Material.ALLIUM,
Material.AZURE_BLUET,
Material.RED_TULIP,
Material.ORANGE_TULIP,
Material.WHITE_TULIP,
Material.CORNFLOWER,
Material.LILY_OF_THE_VALLEY,
Material.SHORT_GRASS,
Material.TALL_GRASS
);
private void setBuildingPlatform() { private void setBuildingPlatform() {
Bukkit.getScheduler().runTask(Main.plugin(), () -> { Bukkit.getScheduler().runTask(Main.plugin(), () -> {
for(int x = 0; x < (pixelsPerBlock + 2) + 2 * worldGrassBorderWidth; x++) { int platformSize = (pixelsPerBlock + 2) + 2 * worldGrassBorderWidth;
for(int z = 0; z < (pixelsPerBlock + 2) + 2 * worldGrassBorderWidth; z++) { Location platformOrigin = this.getPlatformOrigin();
getPlatformOrigin().add(x, 0, z).getBlock().setType(Material.GRASS_BLOCK); for(int x = 0; x < platformSize; x++) {
} for(int z = 0; z < platformSize; z++) {
} platformOrigin.clone().add(x, 0, z).getBlock().setType(Material.GRASS_BLOCK);
for(int x = 0; x < (pixelsPerBlock + 2) + 2 * worldGrassBorderWidth; x++) { platformOrigin.clone().add(x, -1, z).getBlock().setType(Material.DIRT);
for(int z = 0; z < (pixelsPerBlock + 2) + 2 * worldGrassBorderWidth; z++) {
getPlatformOrigin().add(x, -1, z).getBlock().setType(Material.DIRT);
} }
} }
for(int x = 0; x < (pixelsPerBlock + 2); x++) { int borderSize = pixelsPerBlock + 2;
for(int z = 0; z < (pixelsPerBlock + 2); z++) { Location borderOrigin = this.getBorderOrigin();
Location currentLocation = getBorderOrigin().add(x, 0, z); for(int x = 0; x < borderSize; x++) {
for(int z = 0; z < borderSize; z++) {
if(currentLocation.x() == getBorderOrigin().x() || currentLocation.z() == getBorderOrigin().z()) { if(x == 0 || z == 0 || x == borderSize - 1 || z == borderSize - 1) {
currentLocation.getBlock().setType(Material.RED_CONCRETE); borderOrigin.clone().add(x, 0, z).getBlock().setType(Material.RED_CONCRETE);
} else if(currentLocation.x() == getBorderOrigin().x() + (pixelsPerBlock + 1) || currentLocation.z() == getBorderOrigin().z() + (pixelsPerBlock + 1)) {
currentLocation.getBlock().setType(Material.RED_CONCRETE);
} }
} }
} }
@@ -186,37 +208,23 @@ public class PixelBlockWorld {
if(allowPlacements(location)) return; if(allowPlacements(location)) return;
if(!location.clone().subtract(0, 1, 0).getBlock().getType().equals(Material.GRASS_BLOCK)) return; if(!location.clone().subtract(0, 1, 0).getBlock().getType().equals(Material.GRASS_BLOCK)) return;
List<Material> flowers = List.of( if(FLOWERS.contains(location.getBlock().getType())) location.getBlock().setType(Material.AIR);
Material.DANDELION,
Material.POPPY,
Material.BLUE_ORCHID,
Material.ALLIUM,
Material.AZURE_BLUET,
Material.RED_TULIP,
Material.ORANGE_TULIP,
Material.WHITE_TULIP,
Material.CORNFLOWER,
Material.LILY_OF_THE_VALLEY,
Material.SHORT_GRASS,
Material.TALL_GRASS
);
if(flowers.contains(location.getBlock().getType())) location.getBlock().setType(Material.AIR);
if(!location.getBlock().getType().equals(Material.AIR)) return; if(!location.getBlock().getType().equals(Material.AIR)) return;
if(random.nextInt(30) == 0) { if(random.nextInt(30) == 0) {
Material randomFlower = flowers.get(random.nextInt(flowers.size())); location.getBlock().setType(FLOWERS.get(random.nextInt(FLOWERS.size())));
location.getBlock().setType(randomFlower);
} }
}); });
Location portalLocation = this.getPortalLocation();
for(int x = 0; x < 4; x++) { for(int x = 0; x < 4; x++) {
for(int y = 0; y < 5; y++) { for(int y = 0; y < 5; y++) {
getPortalLocation().add(x, y, 0).getBlock().setType(Material.OBSIDIAN); portalLocation.clone().add(x, y, 0).getBlock().setType(Material.OBSIDIAN);
} }
} }
for(int x = 1; x < 3; x++) { for(int x = 1; x < 3; x++) {
for(int y = 1; y < 4; y++) { for(int y = 1; y < 4; y++) {
getPortalLocation().add(x, y, 0).getBlock().setType(Material.NETHER_PORTAL); portalLocation.clone().add(x, y, 0).getBlock().setType(Material.NETHER_PORTAL);
} }
} }
}); });
@@ -2,6 +2,7 @@ package eu.mhsl.minecraft.pixelblocks.pixelblock;
import eu.mhsl.minecraft.pixelblocks.Main; import eu.mhsl.minecraft.pixelblocks.Main;
import eu.mhsl.minecraft.pixelblocks.utils.Direction; import eu.mhsl.minecraft.pixelblocks.utils.Direction;
import eu.mhsl.minecraft.pixelblocks.utils.EntityTagUtil;
import eu.mhsl.minecraft.pixelblocks.utils.ListUtil; import eu.mhsl.minecraft.pixelblocks.utils.ListUtil;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.NamespacedKey; import org.bukkit.NamespacedKey;
@@ -16,7 +17,6 @@ import org.bukkit.block.data.type.EnderChest;
import org.bukkit.entity.BlockDisplay; import org.bukkit.entity.BlockDisplay;
import org.bukkit.entity.Entity; import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType; import org.bukkit.entity.EntityType;
import org.bukkit.persistence.PersistentDataType;
import org.bukkit.util.Transformation; import org.bukkit.util.Transformation;
import org.bukkit.util.Vector; import org.bukkit.util.Vector;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@@ -24,7 +24,6 @@ import org.jetbrains.annotations.Nullable;
import org.joml.Vector3d; import org.joml.Vector3d;
import java.util.List; import java.util.List;
import java.util.Objects;
public class Pixels { public class Pixels {
private static final NamespacedKey pixelOfTag = new NamespacedKey(Main.plugin(), "pixel_of"); private static final NamespacedKey pixelOfTag = new NamespacedKey(Main.plugin(), "pixel_of");
@@ -61,18 +60,16 @@ public class Pixels {
transform.getTranslation().set(centerOffset.mul(-1)); transform.getTranslation().set(centerOffset.mul(-1));
entity.setTransformation(transform); entity.setTransformation(transform);
entity.getPersistentDataContainer().set(pixelOfTag, PersistentDataType.STRING, this.parentBlock.getBlockUUID().toString()); EntityTagUtil.tag(entity, pixelOfTag, this.parentBlock.getBlockUUID());
} }
public void destroy() { public void destroy() {
List<BlockDisplay> entities = parentBlock.getPixelBlockLocation().getNearbyEntitiesByType(BlockDisplay.class, 1) List<BlockDisplay> entities = EntityTagUtil.findTagged(
.stream() this.parentBlock.getPixelBlockLocation(),
.filter(blockDisplay -> blockDisplay.getPersistentDataContainer().has(pixelOfTag)) BlockDisplay.class,
.filter(blockDisplay -> Objects.equals( pixelOfTag,
blockDisplay.getPersistentDataContainer().get(pixelOfTag, PersistentDataType.STRING), this.parentBlock.getBlockUUID()
parentBlock.getBlockUUID().toString() );
))
.toList();
ListUtil.splitListInParts(10, entities) ListUtil.splitListInParts(10, entities)
.forEach(pixels -> parentBlock.getBlockTaskChain() .forEach(pixels -> parentBlock.getBlockTaskChain()
@@ -0,0 +1,29 @@
package eu.mhsl.minecraft.pixelblocks.utils;
import org.bukkit.Location;
import org.bukkit.NamespacedKey;
import org.bukkit.entity.Entity;
import org.bukkit.persistence.PersistentDataType;
import org.jetbrains.annotations.NotNull;
import java.util.List;
import java.util.Objects;
import java.util.UUID;
public class EntityTagUtil {
public static void tag(@NotNull Entity entity, @NotNull NamespacedKey key, @NotNull UUID id) {
entity.getPersistentDataContainer().set(key, PersistentDataType.STRING, id.toString());
}
public static <T extends Entity> @NotNull List<T> findTagged(@NotNull Location center, @NotNull Class<T> type, @NotNull NamespacedKey key, @NotNull UUID id) {
String idString = id.toString();
return center.getNearbyEntitiesByType(type, 1)
.stream()
.filter(entity -> Objects.equals(entity.getPersistentDataContainer().get(key, PersistentDataType.STRING), idString))
.toList();
}
public static <T extends Entity> void removeTagged(@NotNull Location center, @NotNull Class<T> type, @NotNull NamespacedKey key, @NotNull UUID id) {
findTagged(center, type, key, id).forEach(Entity::remove);
}
}
@@ -14,7 +14,7 @@ public class EventCanceling {
if(!PixelBlockWorld.isPixelWorld(world)) return; if(!PixelBlockWorld.isPixelWorld(world)) return;
@Nullable PixelBlock pixelBlock = PixelBlock.getPixelBlockFromBlockWorld(world); @Nullable PixelBlock pixelBlock = PixelBlock.getPixelBlockFromBlockWorld(world);
if(pixelBlock == null) { if(pixelBlock == null) {
Main.logger().warning("Cancelling place event because PixelBlock could not be found: " + world.getName()); Main.logger().warning("Cancelling %s event because PixelBlock '%s' could not be found!".formatted(event.getClass().getSimpleName(), world.getName()));
event.setCancelled(true); event.setCancelled(true);
return; return;
} }