diff --git a/src/main/java/com/volmit/iris/core/service/BoardSVC.java b/src/main/java/com/volmit/iris/core/service/BoardSVC.java index f8c76991e..9fb7bf550 100644 --- a/src/main/java/com/volmit/iris/core/service/BoardSVC.java +++ b/src/main/java/com/volmit/iris/core/service/BoardSVC.java @@ -152,6 +152,12 @@ public class BoardSVC implements IrisService, BoardProvider { v.add(C.LIGHT_PURPLE + "Tasks" + C.GRAY + ": " + Form.f(Iris.jobCount())); } + if(engine.getBlockUpdatesPerSecond() > 0) + { + v.add("&7&m------------------"); + v.add(C.LIGHT_PURPLE + "BUD/s" + C.GRAY + ": " + Form.f(engine.getBlockUpdatesPerSecond())); + } + v.add("&7&m------------------"); return v; diff --git a/src/main/java/com/volmit/iris/engine/IrisEngine.java b/src/main/java/com/volmit/iris/engine/IrisEngine.java index f47a63364..8065d624c 100644 --- a/src/main/java/com/volmit/iris/engine/IrisEngine.java +++ b/src/main/java/com/volmit/iris/engine/IrisEngine.java @@ -68,6 +68,8 @@ import java.util.concurrent.atomic.AtomicLong; @Data public class IrisEngine implements Engine { + private final AtomicInteger bud; + private final AtomicInteger buds; private final AtomicInteger generated; private final AtomicInteger generatedLast; private final AtomicDouble perSecond; @@ -77,6 +79,7 @@ public class IrisEngine implements Engine { private EngineEffects effects; private final EngineMantle mantle; private final ChronoLatch perSecondLatch; + private final ChronoLatch perSecondBudLatch; private EngineExecutionEnvironment execution; private EngineWorldManager worldManager; private volatile int parallelism; @@ -105,12 +108,15 @@ public class IrisEngine implements Engine { public IrisEngine(EngineTarget target, boolean studio) { this.studio = studio; this.target = target; + bud = new AtomicInteger(0); + buds = new AtomicInteger(0); metrics = new EngineMetrics(32); cleanLatch = new ChronoLatch(Math.max(10000, Math.min(IrisSettings.get().getParallax() .getParallaxChunkEvictionMS(), IrisSettings.get().getParallax().getParallaxRegionEvictionMS()))); generatedLast = new AtomicInteger(0); perSecond = new AtomicDouble(0); perSecondLatch = new ChronoLatch(1000, false); + perSecondBudLatch = new ChronoLatch(1000, false); wallClock = new AtomicRollingSequence(32); lastGPS = new AtomicLong(M.ms()); generated = new AtomicInteger(0); @@ -130,6 +136,12 @@ public class IrisEngine implements Engine { } private void tickRandomPlayer() { + if(perSecondBudLatch.flip()) + { + buds.set(bud.get()); + bud.set(0); + } + if (effects != null) { effects.tickRandomPlayer(); } @@ -272,6 +284,11 @@ public class IrisEngine implements Engine { } } + @Override + public int getBlockUpdatesPerSecond() { + return buds.get(); + } + public void printMetrics(CommandSender sender) { KMap totals = new KMap<>(); KMap weights = new KMap<>(); @@ -444,6 +461,11 @@ public class IrisEngine implements Engine { } } + @Override + public void blockUpdatedMetric() { + bud.incrementAndGet(); + } + @Override public IrisBiome getFocus() { if (getDimension().getFocus() == null || getDimension().getFocus().trim().isEmpty()) { diff --git a/src/main/java/com/volmit/iris/engine/IrisWorldManager.java b/src/main/java/com/volmit/iris/engine/IrisWorldManager.java index f1e44cb64..0af3cea33 100644 --- a/src/main/java/com/volmit/iris/engine/IrisWorldManager.java +++ b/src/main/java/com/volmit/iris/engine/IrisWorldManager.java @@ -38,6 +38,7 @@ import com.volmit.iris.util.mantle.Mantle; import com.volmit.iris.util.mantle.MantleFlag; 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.scheduling.ChronoLatch; import com.volmit.iris.util.scheduling.J; import com.volmit.iris.util.scheduling.Looper; @@ -154,6 +155,7 @@ public class IrisWorldManager extends EngineAssignedWorldManager { private void updateChunks() { for (Player i : getEngine().getWorld().realWorld().getPlayers()) { int r = 2; + Chunk c = i.getLocation().getChunk(); for (int x = -r; x <= r; x++) { for (int z = -r; z <= r; z++) { @@ -216,6 +218,12 @@ public class IrisWorldManager extends EngineAssignedWorldManager { } Chunk c = cc[RNG.r.nextInt(cc.length)]; + + if(!c.isLoaded() || !Chunks.isSafe(c.getWorld(), c.getX(), c.getZ())) + { + continue; + } + spawnIn(c, false); chunkCooldowns.put(Cache.key(c), M.ms()); } diff --git a/src/main/java/com/volmit/iris/engine/framework/Engine.java b/src/main/java/com/volmit/iris/engine/framework/Engine.java index f71671982..d09894662 100644 --- a/src/main/java/com/volmit/iris/engine/framework/Engine.java +++ b/src/main/java/com/volmit/iris/engine/framework/Engine.java @@ -86,6 +86,8 @@ import java.util.function.Consumer; public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdater, Renderer, Hotloadable { IrisComplex getComplex(); + int getBlockUpdatesPerSecond(); + void printMetrics(CommandSender sender); EngineMantle getMantle(); @@ -230,6 +232,8 @@ public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdat } + void blockUpdatedMetric(); + @ChunkCoordinates @Override default void updateChunk(Chunk c) { @@ -298,7 +302,7 @@ public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdat default void update(int x, int y, int z, Chunk c, RNG rf) { Block block = c.getBlock(x, y, z); BlockData data = block.getBlockData(); - + blockUpdatedMetric(); if (B.isStorage(data)) { RNG rx = rf.nextParallelRNG(BlockPosition.toLong(x, y, z)); InventorySlotType slot = null; diff --git a/src/main/java/com/volmit/iris/engine/framework/EngineAssignedWorldManager.java b/src/main/java/com/volmit/iris/engine/framework/EngineAssignedWorldManager.java index c8b56ef7c..b2eb86d01 100644 --- a/src/main/java/com/volmit/iris/engine/framework/EngineAssignedWorldManager.java +++ b/src/main/java/com/volmit/iris/engine/framework/EngineAssignedWorldManager.java @@ -125,6 +125,17 @@ public abstract class EngineAssignedWorldManager extends EngineAssignedComponent @EventHandler public void on(ChunkLoadEvent e) { + + try + { + throw new RuntimeException("WHO FUCKIN DUN IT?"); + } + + catch(Throwable ee) + { + ee.printStackTrace(); + } + if (e.getChunk().getWorld().equals(getTarget().getWorld().realWorld())) { onChunkLoad(e.getChunk(), e.isNewChunk()); } diff --git a/src/main/java/com/volmit/iris/engine/object/entity/IrisEntity.java b/src/main/java/com/volmit/iris/engine/object/entity/IrisEntity.java index 9a75b95a5..8c372672d 100644 --- a/src/main/java/com/volmit/iris/engine/object/entity/IrisEntity.java +++ b/src/main/java/com/volmit/iris/engine/object/entity/IrisEntity.java @@ -35,6 +35,7 @@ import com.volmit.iris.util.format.C; import com.volmit.iris.util.json.JSONObject; 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; @@ -173,6 +174,11 @@ public class IrisEntity extends IrisRegistrant { } public Entity spawn(Engine gen, Location at, RNG rng) { + if(!Chunks.isSafe(at)) + { + return null; + } + if (isSpawnEffectRiseOutOfGround()) { Location b = at.clone(); double sy = b.getY() - 5; @@ -182,6 +188,11 @@ public class IrisEntity extends IrisRegistrant { Entity ee = doSpawn(at); + if(ee == null && !Chunks.isSafe(at)) + { + return null; + } + if (!spawnerScript.isEmpty() && ee == null) { synchronized (this) { gen.getExecution().getAPI().setLocation(at); @@ -331,15 +342,22 @@ public class IrisEntity extends IrisRegistrant { } } - if (isSpawnEffectRiseOutOfGround() && e instanceof LivingEntity) { + if (Chunks.hasPlayersNearby(at) && isSpawnEffectRiseOutOfGround() && e instanceof LivingEntity) { Location start = at.clone(); e.setInvulnerable(true); ((LivingEntity) e).setAI(false); ((LivingEntity) e).setCollidable(false); ((LivingEntity) e).setNoDamageTicks(100000); - + AtomicInteger t = new AtomicInteger(0); AtomicInteger v = new AtomicInteger(0); v.set(J.sr(() -> { + if(t.get() > 100) + { + J.csr(v.get()); + return; + } + + 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()); @@ -376,6 +394,11 @@ public class IrisEntity extends IrisRegistrant { } private Entity doSpawn(Location at) { + if(!Chunks.isSafe(at)) + { + return null; + } + if (type.equals(EntityType.UNKNOWN)) { return null; } diff --git a/src/main/java/com/volmit/iris/util/decree/DecreeSystem.java b/src/main/java/com/volmit/iris/util/decree/DecreeSystem.java index 0a8bfd498..dd2c66794 100644 --- a/src/main/java/com/volmit/iris/util/decree/DecreeSystem.java +++ b/src/main/java/com/volmit/iris/util/decree/DecreeSystem.java @@ -70,7 +70,6 @@ public interface DecreeSystem extends CommandExecutor, TabCompleter { return v; } - @Override default boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { if (!sender.hasPermission("iris.all")) { diff --git a/src/main/java/com/volmit/iris/util/plugin/Chunks.java b/src/main/java/com/volmit/iris/util/plugin/Chunks.java new file mode 100644 index 000000000..5ba3b0dbc --- /dev/null +++ b/src/main/java/com/volmit/iris/util/plugin/Chunks.java @@ -0,0 +1,54 @@ +/* + * Iris is a World Generator for Minecraft Bukkit Servers + * Copyright (c) 2021 Arcane Arts (Volmit Software) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.volmit.iris.util.plugin; + +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.entity.Player; + +public class Chunks { + public static boolean isSafe(World w, int x, int z) + { + return w.isChunkLoaded(x, z) + && w.isChunkLoaded(x+1, z) + && w.isChunkLoaded(x, z+1) + && w.isChunkLoaded(x-1, z) + && w.isChunkLoaded(x, z-1) + && w.isChunkLoaded(x-1, z-1) + && w.isChunkLoaded(x+1, z+1) + && w.isChunkLoaded(x+1, z-1) + && w.isChunkLoaded(x-1, z+1); + } + + public static boolean isSafe(Location l) + { + return isSafe(l.getWorld(), l.getBlockX() >> 4, l.getBlockZ() >> 4); + } + + public static boolean hasPlayersNearby(Location at) { + try{ + return !at.getWorld().getNearbyEntities(at, 32, 32, 32, (i) -> i instanceof Player).isEmpty(); + } + + catch(Throwable ignored) + { + return false; + } + } +}