Fix infinite spawning bug

This commit is contained in:
cyberpwn
2021-08-29 10:25:52 -04:00
parent 7997d52df5
commit 04c44de145
8 changed files with 131 additions and 4 deletions
@@ -152,6 +152,12 @@ public class BoardSVC implements IrisService, BoardProvider {
v.add(C.LIGHT_PURPLE + "Tasks" + C.GRAY + ": " + Form.f(Iris.jobCount())); 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------------------"); v.add("&7&m------------------");
return v; return v;
@@ -68,6 +68,8 @@ import java.util.concurrent.atomic.AtomicLong;
@Data @Data
public class IrisEngine implements Engine { public class IrisEngine implements Engine {
private final AtomicInteger bud;
private final AtomicInteger buds;
private final AtomicInteger generated; private final AtomicInteger generated;
private final AtomicInteger generatedLast; private final AtomicInteger generatedLast;
private final AtomicDouble perSecond; private final AtomicDouble perSecond;
@@ -77,6 +79,7 @@ public class IrisEngine implements Engine {
private EngineEffects effects; private EngineEffects effects;
private final EngineMantle mantle; private final EngineMantle mantle;
private final ChronoLatch perSecondLatch; private final ChronoLatch perSecondLatch;
private final ChronoLatch perSecondBudLatch;
private EngineExecutionEnvironment execution; private EngineExecutionEnvironment execution;
private EngineWorldManager worldManager; private EngineWorldManager worldManager;
private volatile int parallelism; private volatile int parallelism;
@@ -105,12 +108,15 @@ public class IrisEngine implements Engine {
public IrisEngine(EngineTarget target, boolean studio) { public IrisEngine(EngineTarget target, boolean studio) {
this.studio = studio; this.studio = studio;
this.target = target; this.target = target;
bud = new AtomicInteger(0);
buds = new AtomicInteger(0);
metrics = new EngineMetrics(32); metrics = new EngineMetrics(32);
cleanLatch = new ChronoLatch(Math.max(10000, Math.min(IrisSettings.get().getParallax() cleanLatch = new ChronoLatch(Math.max(10000, Math.min(IrisSettings.get().getParallax()
.getParallaxChunkEvictionMS(), IrisSettings.get().getParallax().getParallaxRegionEvictionMS()))); .getParallaxChunkEvictionMS(), IrisSettings.get().getParallax().getParallaxRegionEvictionMS())));
generatedLast = new AtomicInteger(0); generatedLast = new AtomicInteger(0);
perSecond = new AtomicDouble(0); perSecond = new AtomicDouble(0);
perSecondLatch = new ChronoLatch(1000, false); perSecondLatch = new ChronoLatch(1000, false);
perSecondBudLatch = new ChronoLatch(1000, false);
wallClock = new AtomicRollingSequence(32); wallClock = new AtomicRollingSequence(32);
lastGPS = new AtomicLong(M.ms()); lastGPS = new AtomicLong(M.ms());
generated = new AtomicInteger(0); generated = new AtomicInteger(0);
@@ -130,6 +136,12 @@ public class IrisEngine implements Engine {
} }
private void tickRandomPlayer() { private void tickRandomPlayer() {
if(perSecondBudLatch.flip())
{
buds.set(bud.get());
bud.set(0);
}
if (effects != null) { if (effects != null) {
effects.tickRandomPlayer(); effects.tickRandomPlayer();
} }
@@ -272,6 +284,11 @@ public class IrisEngine implements Engine {
} }
} }
@Override
public int getBlockUpdatesPerSecond() {
return buds.get();
}
public void printMetrics(CommandSender sender) { public void printMetrics(CommandSender sender) {
KMap<String, Double> totals = new KMap<>(); KMap<String, Double> totals = new KMap<>();
KMap<String, Double> weights = new KMap<>(); KMap<String, Double> weights = new KMap<>();
@@ -444,6 +461,11 @@ public class IrisEngine implements Engine {
} }
} }
@Override
public void blockUpdatedMetric() {
bud.incrementAndGet();
}
@Override @Override
public IrisBiome getFocus() { public IrisBiome getFocus() {
if (getDimension().getFocus() == null || getDimension().getFocus().trim().isEmpty()) { if (getDimension().getFocus() == null || getDimension().getFocus().trim().isEmpty()) {
@@ -38,6 +38,7 @@ import com.volmit.iris.util.mantle.Mantle;
import com.volmit.iris.util.mantle.MantleFlag; import com.volmit.iris.util.mantle.MantleFlag;
import com.volmit.iris.util.math.M; import com.volmit.iris.util.math.M;
import com.volmit.iris.util.math.RNG; 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.ChronoLatch;
import com.volmit.iris.util.scheduling.J; import com.volmit.iris.util.scheduling.J;
import com.volmit.iris.util.scheduling.Looper; import com.volmit.iris.util.scheduling.Looper;
@@ -154,6 +155,7 @@ public class IrisWorldManager extends EngineAssignedWorldManager {
private void updateChunks() { private void updateChunks() {
for (Player i : getEngine().getWorld().realWorld().getPlayers()) { for (Player i : getEngine().getWorld().realWorld().getPlayers()) {
int r = 2; int r = 2;
Chunk c = i.getLocation().getChunk(); Chunk c = i.getLocation().getChunk();
for (int x = -r; x <= r; x++) { for (int x = -r; x <= r; x++) {
for (int z = -r; z <= r; z++) { for (int z = -r; z <= r; z++) {
@@ -216,6 +218,12 @@ public class IrisWorldManager extends EngineAssignedWorldManager {
} }
Chunk c = cc[RNG.r.nextInt(cc.length)]; Chunk c = cc[RNG.r.nextInt(cc.length)];
if(!c.isLoaded() || !Chunks.isSafe(c.getWorld(), c.getX(), c.getZ()))
{
continue;
}
spawnIn(c, false); spawnIn(c, false);
chunkCooldowns.put(Cache.key(c), M.ms()); chunkCooldowns.put(Cache.key(c), M.ms());
} }
@@ -86,6 +86,8 @@ import java.util.function.Consumer;
public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdater, Renderer, Hotloadable { public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdater, Renderer, Hotloadable {
IrisComplex getComplex(); IrisComplex getComplex();
int getBlockUpdatesPerSecond();
void printMetrics(CommandSender sender); void printMetrics(CommandSender sender);
EngineMantle getMantle(); EngineMantle getMantle();
@@ -230,6 +232,8 @@ public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdat
} }
void blockUpdatedMetric();
@ChunkCoordinates @ChunkCoordinates
@Override @Override
default void updateChunk(Chunk c) { 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) { default void update(int x, int y, int z, Chunk c, RNG rf) {
Block block = c.getBlock(x, y, z); Block block = c.getBlock(x, y, z);
BlockData data = block.getBlockData(); BlockData data = block.getBlockData();
blockUpdatedMetric();
if (B.isStorage(data)) { if (B.isStorage(data)) {
RNG rx = rf.nextParallelRNG(BlockPosition.toLong(x, y, z)); RNG rx = rf.nextParallelRNG(BlockPosition.toLong(x, y, z));
InventorySlotType slot = null; InventorySlotType slot = null;
@@ -125,6 +125,17 @@ public abstract class EngineAssignedWorldManager extends EngineAssignedComponent
@EventHandler @EventHandler
public void on(ChunkLoadEvent e) { 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())) { if (e.getChunk().getWorld().equals(getTarget().getWorld().realWorld())) {
onChunkLoad(e.getChunk(), e.isNewChunk()); onChunkLoad(e.getChunk(), e.isNewChunk());
} }
@@ -35,6 +35,7 @@ import com.volmit.iris.util.format.C;
import com.volmit.iris.util.json.JSONObject; import com.volmit.iris.util.json.JSONObject;
import com.volmit.iris.util.math.M; import com.volmit.iris.util.math.M;
import com.volmit.iris.util.math.RNG; 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.plugin.VolmitSender;
import com.volmit.iris.util.scheduling.J; import com.volmit.iris.util.scheduling.J;
import com.volmit.iris.util.scheduling.PrecisionStopwatch; 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) { public Entity spawn(Engine gen, Location at, RNG rng) {
if(!Chunks.isSafe(at))
{
return null;
}
if (isSpawnEffectRiseOutOfGround()) { if (isSpawnEffectRiseOutOfGround()) {
Location b = at.clone(); Location b = at.clone();
double sy = b.getY() - 5; double sy = b.getY() - 5;
@@ -182,6 +188,11 @@ public class IrisEntity extends IrisRegistrant {
Entity ee = doSpawn(at); Entity ee = doSpawn(at);
if(ee == null && !Chunks.isSafe(at))
{
return null;
}
if (!spawnerScript.isEmpty() && ee == null) { if (!spawnerScript.isEmpty() && ee == null) {
synchronized (this) { synchronized (this) {
gen.getExecution().getAPI().setLocation(at); 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(); Location start = at.clone();
e.setInvulnerable(true); e.setInvulnerable(true);
((LivingEntity) e).setAI(false); ((LivingEntity) e).setAI(false);
((LivingEntity) e).setCollidable(false); ((LivingEntity) e).setCollidable(false);
((LivingEntity) e).setNoDamageTicks(100000); ((LivingEntity) e).setNoDamageTicks(100000);
AtomicInteger t = new AtomicInteger(0);
AtomicInteger v = new AtomicInteger(0); AtomicInteger v = new AtomicInteger(0);
v.set(J.sr(() -> { 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()) { if (e.getLocation().getBlock().getType().isSolid() || ((LivingEntity) e).getEyeLocation().getBlock().getType().isSolid()) {
e.teleport(start.add(new Vector(0, 0.1, 0))); 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()); 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) { private Entity doSpawn(Location at) {
if(!Chunks.isSafe(at))
{
return null;
}
if (type.equals(EntityType.UNKNOWN)) { if (type.equals(EntityType.UNKNOWN)) {
return null; return null;
} }
@@ -70,7 +70,6 @@ public interface DecreeSystem extends CommandExecutor, TabCompleter {
return v; return v;
} }
@Override @Override
default boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { default boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
if (!sender.hasPermission("iris.all")) { if (!sender.hasPermission("iris.all")) {
@@ -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 <https://www.gnu.org/licenses/>.
*/
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;
}
}
}