From e461c1e1999c58faf769788e370aa100dff3c7ab Mon Sep 17 00:00:00 2001 From: Julian Krings Date: Sat, 14 Jun 2025 19:35:28 +0200 Subject: [PATCH] fix updater and mob spawning instantly failing --- .../volmit/iris/engine/IrisWorldManager.java | 48 ++-- .../volmit/iris/engine/framework/Engine.java | 9 +- .../volmit/iris/engine/object/IrisEntity.java | 227 +++++++----------- .../iris/engine/object/IrisEntitySpawn.java | 32 ++- .../iris/engine/object/IrisSurface.java | 6 +- .../iris/engine/object/LegacyTileData.java | 4 +- 6 files changed, 150 insertions(+), 176 deletions(-) diff --git a/core/src/main/java/com/volmit/iris/engine/IrisWorldManager.java b/core/src/main/java/com/volmit/iris/engine/IrisWorldManager.java index 95ba698c9..c115898fc 100644 --- a/core/src/main/java/com/volmit/iris/engine/IrisWorldManager.java +++ b/core/src/main/java/com/volmit/iris/engine/IrisWorldManager.java @@ -188,9 +188,11 @@ public class IrisWorldManager extends EngineAssignedWorldManager { for (Player i : getEngine().getWorld().realWorld().getPlayers()) { int r = 1; + int cX = i.getLocation().getBlockX() >> 4; + int cZ = i.getLocation().getBlockZ() >> 4; for (int x = -r; x <= r; x++) { for (int z = -r; z <= r; z++) { - mantle.getChunk(i.getLocation().getChunk()).flag(MantleFlag.DISCOVERED, true); + mantle.getChunk(cX + x, cZ + z).flag(MantleFlag.DISCOVERED, true); } } } @@ -200,20 +202,22 @@ public class IrisWorldManager extends EngineAssignedWorldManager { for (Player i : getEngine().getWorld().realWorld().getPlayers()) { int r = 1; - Chunk c = i.getLocation().getChunk(); - for (int x = -r; x <= r; x++) { - for (int z = -r; z <= r; z++) { - if (c.getWorld().isChunkLoaded(c.getX() + x, c.getZ() + z) && Chunks.isSafe(getEngine().getWorld().realWorld(), c.getX() + x, c.getZ() + z)) { + Iris.scheduler.entity(i).run(() -> { + Chunk c = i.getLocation().getChunk(); + for (int x = -r; x <= r; x++) { + for (int z = -r; z <= r; z++) { + int cX = c.getX() + x; + int cZ = c.getZ() + z; + if (!c.getWorld().isChunkLoaded(cX, cZ) || !Chunks.isSafe(getEngine().getWorld().realWorld(), cX, cZ)) + continue; if (IrisSettings.get().getWorld().isPostLoadBlockUpdates()) { - getEngine().updateChunk(c.getWorld().getChunkAt(c.getX() + x, c.getZ() + z)); + getEngine().updateChunk(c.getWorld().getChunkAt(cX, cZ)); } if (IrisSettings.get().getWorld().isMarkerEntitySpawningSystem()) { - Chunk cx = getEngine().getWorld().realWorld().getChunkAt(c.getX() + x, c.getZ() + z); - int finalX = c.getX() + x; - int finalZ = c.getZ() + z; - J.a(() -> getMantle().raiseFlag(finalX, finalZ, MantleFlag.INITIAL_SPAWNED_MARKER, + Chunk cx = getEngine().getWorld().realWorld().getChunkAt(cX, cZ); + J.a(() -> getMantle().raiseFlag(cX, cZ, MantleFlag.INITIAL_SPAWNED_MARKER, () -> { J.a(() -> spawnIn(cx, true), RNG.r.i(5, 200)); getSpawnersFromMarkers(cx).forEach((blockf, spawners) -> { @@ -229,7 +233,7 @@ public class IrisWorldManager extends EngineAssignedWorldManager { } } } - } + }, null); } } @@ -532,19 +536,17 @@ public class IrisWorldManager extends EngineAssignedWorldManager { IrisPosition pos = new IrisPosition((c.getX() << 4) + x, y, (c.getZ() << 4) + z); if (mark.isEmptyAbove()) { - AtomicBoolean remove = new AtomicBoolean(false); + Boolean remove = Iris.scheduler.region() + .run(c.getWorld(), c.getX(), c.getZ(), () -> c.getBlock(x, y + 1, z).getType().isSolid() || c.getBlock(x, y + 2, z).getType().isSolid()) + .result() + .exceptionally(e -> { + Iris.reportError(e); + e.printStackTrace(); + return false; + }) + .join(); - try { - J.sfut(() -> { - if (c.getBlock(x, y + 1, z).getBlockData().getMaterial().isSolid() || c.getBlock(x, y + 2, z).getBlockData().getMaterial().isSolid()) { - remove.set(true); - } - }).get(); - } catch (InterruptedException | ExecutionException e) { - e.printStackTrace(); - } - - if (remove.get()) { + if (remove == Boolean.TRUE) { b.add(pos); return; } diff --git a/core/src/main/java/com/volmit/iris/engine/framework/Engine.java b/core/src/main/java/com/volmit/iris/engine/framework/Engine.java index 010628b7d..68172d92f 100644 --- a/core/src/main/java/com/volmit/iris/engine/framework/Engine.java +++ b/core/src/main/java/com/volmit/iris/engine/framework/Engine.java @@ -293,20 +293,21 @@ public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdat try { Semaphore semaphore = new Semaphore(3); chunk.raiseFlag(MantleFlag.ETCHED, () -> { - chunk.raiseFlag(MantleFlag.TILE, run(semaphore, () -> J.s(() -> { + var region = Iris.scheduler.region(); + chunk.raiseFlag(MantleFlag.TILE, run(semaphore, () -> region.run(c.getWorld(), c.getX(), c.getZ(), () -> { mantle.iterateChunk(c.getX(), c.getZ(), TileWrapper.class, (x, y, z, v) -> { int betterY = y + getWorld().minHeight(); if (!TileData.setTileState(c.getBlock(x, betterY, z), v.getData())) Iris.warn("Failed to set tile entity data at [%d %d %d | %s] for tile %s!", x, betterY, z, c.getBlock(x, betterY, z).getBlockData().getMaterial().getKey(), v.getData().getMaterial().name()); }); }))); - chunk.raiseFlag(MantleFlag.CUSTOM, run(semaphore, () -> J.s(() -> { + chunk.raiseFlag(MantleFlag.CUSTOM, run(semaphore, () -> region.run(c.getWorld(), c.getX(), c.getZ(), () -> { mantle.iterateChunk(c.getX(), c.getZ(), Identifier.class, (x, y, z, v) -> { Iris.service(ExternalDataSVC.class).processUpdate(this, c.getBlock(x & 15, y + getWorld().minHeight(), z & 15), v); }); }))); - chunk.raiseFlag(MantleFlag.UPDATE, run(semaphore, () -> J.s(() -> { + chunk.raiseFlag(MantleFlag.UPDATE, run(semaphore, () -> region.runDelayed(c.getWorld(), c.getX(), c.getZ(), () -> { PrecisionStopwatch p = PrecisionStopwatch.start(); KMap updates = new KMap<>(); RNG r = new RNG(Cache.key(c.getX(), c.getZ())); @@ -353,7 +354,7 @@ public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdat }); mantle.deleteChunkSlice(c.getX(), c.getZ(), MatterUpdate.class); getMetrics().getUpdates().put(p.getMilliseconds()); - }, RNG.r.i(0, 20)))); + }, RNG.r.i(1, 20)))); }); try { diff --git a/core/src/main/java/com/volmit/iris/engine/object/IrisEntity.java b/core/src/main/java/com/volmit/iris/engine/object/IrisEntity.java index 109d9a9c1..414ed285a 100644 --- a/core/src/main/java/com/volmit/iris/engine/object/IrisEntity.java +++ b/core/src/main/java/com/volmit/iris/engine/object/IrisEntity.java @@ -31,8 +31,6 @@ import com.volmit.iris.util.math.M; import com.volmit.iris.util.math.RNG; import com.volmit.iris.util.plugin.Chunks; import com.volmit.iris.util.plugin.VolmitSender; -import com.volmit.iris.util.scheduling.J; -import com.volmit.iris.util.scheduling.PrecisionStopwatch; import lombok.AllArgsConstructor; import lombok.Data; import lombok.EqualsAndHashCode; @@ -48,13 +46,11 @@ import org.bukkit.inventory.ItemStack; import org.bukkit.loot.LootContext; import org.bukkit.loot.LootTable; import org.bukkit.loot.Lootable; -import org.bukkit.util.Vector; import java.util.Collection; import java.util.Random; -import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicReference; import static com.volmit.iris.util.data.registry.Particles.ITEM; @@ -181,37 +177,33 @@ public class IrisEntity extends IrisRegistrant { return spawn(gen, at, new RNG(at.hashCode())); } - public Entity spawn(Engine gen, Location at, RNG rng) { + public Entity spawn(Engine gen, final Location at, RNG rng) { + if (!Iris.scheduler.isOwnedByCurrentRegion(at)) { + try { + final Location finalAt = at; + return Iris.scheduler.region().run(at, () -> spawn(gen, finalAt, rng)) + .result() + .get(500, TimeUnit.MILLISECONDS); + } catch (Throwable e) { + return null; + } + } + if (!Chunks.isSafe(at)) { return null; } - if (isSpawnEffectRiseOutOfGround()) { - AtomicReference f = new AtomicReference<>(at); - try { - J.sfut(() -> { - if (Chunks.hasPlayersNearby(f.get())) { - Location b = f.get().clone(); - Location start = new Location(b.getWorld(), b.getX(), b.getY() - 5, b.getZ()); - f.set(start); - } - }).get(); - } catch (InterruptedException e) { - e.printStackTrace(); - } catch (ExecutionException e) { - e.printStackTrace(); - } - at = f.get(); + if (isSpawnEffectRiseOutOfGround() && Chunks.hasPlayersNearby(at)) { + at.add(0, -5, 0); } Entity ee = doSpawn(at); - - if (ee == null && !Chunks.isSafe(at)) { + if (ee == null) { return null; } if (!spawnerScript.isEmpty() && ee == null) { synchronized (this) { - gen.getExecution().getAPI().setLocation(at); + gen.getExecution().getAPI().setLocation(at.clone()); try { ee = (Entity) gen.getExecution().evaluate(spawnerScript); } catch (Throwable ex) { @@ -240,109 +232,96 @@ public class IrisEntity extends IrisRegistrant { int gg = 0; for (IrisEntity i : passengers) { - Entity passenger = i.spawn(gen, at, rng.nextParallelRNG(234858 + gg++)); - if (!Bukkit.isPrimaryThread()) { - J.s(() -> e.addPassenger(passenger)); - } + e.addPassenger(i.spawn(gen, at, rng.nextParallelRNG(234858 + gg++))); } - if (e instanceof Attributable) { - Attributable a = (Attributable) e; - + if (e instanceof Attributable attributable) { for (IrisAttributeModifier i : getAttributes()) { - i.apply(rng, a); + i.apply(rng, attributable); } } - if (e instanceof Lootable) { - Lootable l = (Lootable) e; + if (e instanceof Lootable lootable && getLoot().getTables().isNotEmpty()) { + lootable.setLootTable(new LootTable() { + @Override + public NamespacedKey getKey() { + return new NamespacedKey(Iris.instance, "loot-" + IrisEntity.this.hashCode()); + } - if (getLoot().getTables().isNotEmpty()) { - Location finalAt = at; - l.setLootTable(new LootTable() { - @Override - public NamespacedKey getKey() { - return new NamespacedKey(Iris.instance, "loot-" + IrisEntity.this.hashCode()); + @Override + public Collection populateLoot(Random random, LootContext context) { + KList items = new KList<>(); + + for (String fi : getLoot().getTables()) { + IrisLootTable i = gen.getData().getLootLoader().load(fi); + items.addAll(i.getLoot(gen.isStudio(), rng.nextParallelRNG(345911), InventorySlotType.STORAGE, at.getWorld(), at.getBlockX(), at.getBlockY(), at.getBlockZ())); } - @Override - public Collection populateLoot(Random random, LootContext context) { - KList items = new KList<>(); + return items; + } - for (String fi : getLoot().getTables()) { - IrisLootTable i = gen.getData().getLootLoader().load(fi); - items.addAll(i.getLoot(gen.isStudio(), rng.nextParallelRNG(345911), InventorySlotType.STORAGE, finalAt.getWorld(), finalAt.getBlockX(), finalAt.getBlockY(), finalAt.getBlockZ())); - } - - return items; + @Override + public void fillInventory(Inventory inventory, Random random, LootContext context) { + for (ItemStack i : populateLoot(random, context)) { + inventory.addItem(i); } - @Override - public void fillInventory(Inventory inventory, Random random, LootContext context) { - for (ItemStack i : populateLoot(random, context)) { - inventory.addItem(i); - } - - gen.scramble(inventory, rng); - } - }); - } + gen.scramble(inventory, rng); + } + }); } - if (e instanceof LivingEntity) { - LivingEntity l = (LivingEntity) e; - l.setAI(isAi()); - l.setCanPickupItems(isPickupItems()); + if (e instanceof LivingEntity living) { + living.setAI(isAi()); + living.setCanPickupItems(isPickupItems()); if (getLeashHolder() != null) { - l.setLeashHolder(getLeashHolder().spawn(gen, at, rng.nextParallelRNG(234548))); + living.setLeashHolder(getLeashHolder().spawn(gen, at, rng.nextParallelRNG(234548))); } - l.setRemoveWhenFarAway(isRemovable()); + living.setRemoveWhenFarAway(isRemovable()); if (getHelmet() != null && rng.i(1, getHelmet().getRarity()) == 1) { - l.getEquipment().setHelmet(getHelmet().get(gen.isStudio(), rng)); + living.getEquipment().setHelmet(getHelmet().get(gen.isStudio(), rng)); } if (getChestplate() != null && rng.i(1, getChestplate().getRarity()) == 1) { - l.getEquipment().setChestplate(getChestplate().get(gen.isStudio(), rng)); + living.getEquipment().setChestplate(getChestplate().get(gen.isStudio(), rng)); } if (getLeggings() != null && rng.i(1, getLeggings().getRarity()) == 1) { - l.getEquipment().setLeggings(getLeggings().get(gen.isStudio(), rng)); + living.getEquipment().setLeggings(getLeggings().get(gen.isStudio(), rng)); } if (getBoots() != null && rng.i(1, getBoots().getRarity()) == 1) { - l.getEquipment().setBoots(getBoots().get(gen.isStudio(), rng)); + living.getEquipment().setBoots(getBoots().get(gen.isStudio(), rng)); } if (getMainHand() != null && rng.i(1, getMainHand().getRarity()) == 1) { - l.getEquipment().setItemInMainHand(getMainHand().get(gen.isStudio(), rng)); + living.getEquipment().setItemInMainHand(getMainHand().get(gen.isStudio(), rng)); } if (getOffHand() != null && rng.i(1, getOffHand().getRarity()) == 1) { - l.getEquipment().setItemInOffHand(getOffHand().get(gen.isStudio(), rng)); + living.getEquipment().setItemInOffHand(getOffHand().get(gen.isStudio(), rng)); } } - if (e instanceof Ageable && isBaby()) { - ((Ageable) e).setBaby(); + if (e instanceof Ageable ageable && isBaby()) { + ageable.setBaby(); } - if (e instanceof Panda) { - ((Panda) e).setMainGene(getPandaMainGene()); - ((Panda) e).setMainGene(getPandaHiddenGene()); + if (e instanceof Panda panda) { + panda.setMainGene(getPandaMainGene()); + panda.setMainGene(getPandaHiddenGene()); } - if (e instanceof Villager) { - Villager villager = (Villager) e; + if (e instanceof Villager villager) { villager.setRemoveWhenFarAway(false); - Iris.scheduler.entity(villager).run(() -> villager.setPersistent(true), null); + villager.setPersistent(true); } - if (e instanceof Mob) { - Mob m = (Mob) e; - m.setAware(isAware()); + if (e instanceof Mob mob) { + mob.setAware(isAware()); } if (spawnEffect != null) { @@ -365,40 +344,35 @@ public class IrisEntity extends IrisRegistrant { rawCommands.forEach(r -> r.run(fat)); } - Location finalAt1 = at; + if (isSpawnEffectRiseOutOfGround() && e instanceof LivingEntity living && Chunks.hasPlayersNearby(at)) { + e.setInvulnerable(true); + living.setAI(false); + living.setCollidable(false); + living.setNoDamageTicks(100000); + AtomicInteger t = new AtomicInteger(0); + Iris.scheduler.region().runAtFixedRate(at, task -> { + if (t.get() > 100) { + task.cancel(); + return; + } - J.s(() -> { - if (isSpawnEffectRiseOutOfGround() && e instanceof LivingEntity && Chunks.hasPlayersNearby(finalAt1)) { - Location start = finalAt1.clone(); - e.setInvulnerable(true); - ((LivingEntity) e).setAI(false); - ((LivingEntity) e).setCollidable(false); - ((LivingEntity) e).setNoDamageTicks(100000); - AtomicInteger t = new AtomicInteger(0); - Iris.scheduler.global().runAtFixedRate(task -> { - if (t.get() > 100) { - task.cancel(); - return; + t.incrementAndGet(); + if (e.getLocation().getBlock().getType().isSolid() || living.getEyeLocation().getBlock().getType().isSolid()) { + Iris.scheduler.teleportAsync(e, at.add(0, 0.1, 0)); + ItemStack itemCrackData = new ItemStack(living.getEyeLocation().clone().subtract(0, 2, 0).getBlock().getBlockData().getMaterial()); + e.getWorld().spawnParticle(ITEM, living.getEyeLocation(), 6, 0.2, 0.4, 0.2, 0.06f, itemCrackData); + if (M.r(0.2)) { + e.getWorld().playSound(e.getLocation(), Sound.BLOCK_CHORUS_FLOWER_GROW, 0.8f, 0.1f); } - - t.incrementAndGet(); - if (e.getLocation().getBlock().getType().isSolid() || ((LivingEntity) e).getEyeLocation().getBlock().getType().isSolid()) { - e.teleport(start.add(new Vector(0, 0.1, 0))); - ItemStack itemCrackData = new ItemStack(((LivingEntity) e).getEyeLocation().clone().subtract(0, 2, 0).getBlock().getBlockData().getMaterial()); - e.getWorld().spawnParticle(ITEM, ((LivingEntity) e).getEyeLocation(), 6, 0.2, 0.4, 0.2, 0.06f, itemCrackData); - if (M.r(0.2)) { - e.getWorld().playSound(e.getLocation(), Sound.BLOCK_CHORUS_FLOWER_GROW, 0.8f, 0.1f); - } - } else { - task.cancel(); - ((LivingEntity) e).setNoDamageTicks(0); - ((LivingEntity) e).setCollidable(true); - ((LivingEntity) e).setAI(true); - e.setInvulnerable(false); - } - }, 1, 1); - } - }); + } else { + task.cancel(); + living.setNoDamageTicks(0); + living.setCollidable(true); + living.setAI(true); + e.setInvulnerable(false); + } + }, 1, 1); + } return e; @@ -428,29 +402,6 @@ public class IrisEntity extends IrisRegistrant { return null; } - if (!Bukkit.isPrimaryThread()) { - // Someone called spawn (worldedit maybe?) on a non server thread - // Due to the structure of iris, we will call it sync and busy wait until it's done. - AtomicReference ae = new AtomicReference<>(); - - try { - J.s(() -> ae.set(doSpawn(at))); - } catch (Throwable e) { - return null; - } - PrecisionStopwatch p = PrecisionStopwatch.start(); - - while (ae.get() == null) { - J.sleep(25); - - if (p.getMilliseconds() > 500) { - return null; - } - } - - return ae.get(); - } - if (isSpecialType()) { if (specialType.toLowerCase().startsWith("mythicmobs:")) { return Iris.linkMythicMobs.spawnMob(specialType.substring(11), at); diff --git a/core/src/main/java/com/volmit/iris/engine/object/IrisEntitySpawn.java b/core/src/main/java/com/volmit/iris/engine/object/IrisEntitySpawn.java index a0eb9500d..b68f8a69b 100644 --- a/core/src/main/java/com/volmit/iris/engine/object/IrisEntitySpawn.java +++ b/core/src/main/java/com/volmit/iris/engine/object/IrisEntitySpawn.java @@ -36,8 +36,14 @@ import org.bukkit.Chunk; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.World; +import org.bukkit.block.data.BlockData; import org.bukkit.entity.Entity; +import java.util.concurrent.Semaphore; +import java.util.concurrent.atomic.AtomicBoolean; + +import static com.volmit.iris.Iris.scheduler; + @Snippet("entity-spawn") @Accessors(chain = true) @NoArgsConstructor @@ -164,8 +170,15 @@ public class IrisEntitySpawn implements IRare { return null; } - if (!ignoreSurfaces && !irisEntity.getSurface().matches(at.clone().subtract(0, 1, 0).getBlock())) { - return null; + if (!ignoreSurfaces) { + Location block = at.clone().subtract(0, 1, 0); + BlockData data = scheduler.region() + .run(block, () -> block.getBlock().getBlockData()) + .result() + .join(); + if (!irisEntity.getSurface().matches(data)) { + return null; + } } Vector3d boundingBox = INMS.get().getBoundingbox(irisEntity.getType()); @@ -199,15 +212,22 @@ public class IrisEntitySpawn implements IRare { int startZ = center.getBlockZ() - (int) (boundingBox.z / 2); int endZ = center.getBlockZ() + (int) (boundingBox.z / 2); + var region = scheduler.region(); + var lock = new Semaphore(Integer.MAX_VALUE, true); + var bool = new AtomicBoolean(true); for (int x = startX; x <= endX; x++) { for (int y = startY; y <= endY; y++) { for (int z = startZ; z <= endZ; z++) { - if (world.getBlockAt(x, y, z).getType() != Material.AIR) { - return false; - } + Location l = new Location(world, x, y, z); + lock.acquireUninterruptibly(); + region.run(l, () -> { + if (!bool.get()) return false; + return bool.compareAndSet(true, l.getBlock().getType() == Material.AIR); + }).result().exceptionally(f -> false).thenRun(lock::release); } } } - return true; + lock.acquireUninterruptibly(Integer.MAX_VALUE); + return bool.get(); } } diff --git a/core/src/main/java/com/volmit/iris/engine/object/IrisSurface.java b/core/src/main/java/com/volmit/iris/engine/object/IrisSurface.java index e8a2e2e3c..885ba95f5 100644 --- a/core/src/main/java/com/volmit/iris/engine/object/IrisSurface.java +++ b/core/src/main/java/com/volmit/iris/engine/object/IrisSurface.java @@ -20,7 +20,7 @@ package com.volmit.iris.engine.object; import com.volmit.iris.engine.object.annotations.Desc; import org.bukkit.Material; -import org.bukkit.block.Block; +import org.bukkit.block.data.BlockData; import org.bukkit.block.data.Waterlogged; @Desc("The type of surface entities should spawn on") @@ -47,8 +47,8 @@ public enum IrisSurface { * @param state The blockstate * @return True if it matches */ - public boolean matches(Block state) { - Material type = state.getType(); + public boolean matches(BlockData state) { + Material type = state.getMaterial(); if (type.isSolid()) { return this == LAND || this == OVERWORLD || (this == ANIMAL && (type == Material.GRASS_BLOCK || type == Material.DIRT diff --git a/core/src/main/java/com/volmit/iris/engine/object/LegacyTileData.java b/core/src/main/java/com/volmit/iris/engine/object/LegacyTileData.java index 7cbcc094c..e5509581a 100644 --- a/core/src/main/java/com/volmit/iris/engine/object/LegacyTileData.java +++ b/core/src/main/java/com/volmit/iris/engine/object/LegacyTileData.java @@ -1,10 +1,10 @@ package com.volmit.iris.engine.object; +import com.volmit.iris.Iris; import com.volmit.iris.core.nms.container.Pair; import com.volmit.iris.engine.data.cache.AtomicCache; import com.volmit.iris.util.collection.KList; import com.volmit.iris.util.collection.KMap; -import com.volmit.iris.util.scheduling.J; import lombok.AllArgsConstructor; import lombok.EqualsAndHashCode; import lombok.NonNull; @@ -80,7 +80,7 @@ public class LegacyTileData extends TileData { @Override public void toBukkit(Block block) { - J.s(() -> handler.toBukkit(block)); + Iris.scheduler.region().run(block.getLocation(), () -> handler.toBukkit(block)); } @Override