diff --git a/src/main/java/com/volmit/iris/Iris.java b/src/main/java/com/volmit/iris/Iris.java
index bfca9c085..02f73a71e 100644
--- a/src/main/java/com/volmit/iris/Iris.java
+++ b/src/main/java/com/volmit/iris/Iris.java
@@ -134,6 +134,7 @@ public class Iris extends VolmitPlugin implements Listener {
super.onEnable();
Bukkit.getPluginManager().registerEvents(this, this);
J.s(this::lateBind);
+ splash();
}
public static void callEvent(Event e) {
@@ -165,7 +166,6 @@ public class Iris extends VolmitPlugin implements Listener {
J.a(() -> PaperLib.suggestPaper(this));
J.a(() -> IO.delete(getTemp()));
J.a(this::bstats);
- J.a(this::splash, 20);
J.ar(this::checkConfigHotload, 60);
J.sr(this::tickQueue, 0);
J.s(this::setupPapi);
diff --git a/src/main/java/com/volmit/iris/core/command/CommandIrisDebug.java b/src/main/java/com/volmit/iris/core/command/CommandIrisDebug.java
index 184948e03..838e8473d 100644
--- a/src/main/java/com/volmit/iris/core/command/CommandIrisDebug.java
+++ b/src/main/java/com/volmit/iris/core/command/CommandIrisDebug.java
@@ -21,10 +21,14 @@ package com.volmit.iris.core.command;
import com.volmit.iris.Iris;
import com.volmit.iris.core.IrisSettings;
import com.volmit.iris.util.collection.KList;
+import com.volmit.iris.util.plugin.Command;
import com.volmit.iris.util.plugin.MortarCommand;
import com.volmit.iris.util.plugin.VolmitSender;
public class CommandIrisDebug extends MortarCommand {
+ @Command
+ private CommandIrisDebugSpawnerBoost boost;
+
public CommandIrisDebug() {
super("debug", "dbg");
requiresPermission(Iris.perm.studio);
diff --git a/src/main/java/com/volmit/iris/core/command/CommandIrisDebugSpawnerBoost.java b/src/main/java/com/volmit/iris/core/command/CommandIrisDebugSpawnerBoost.java
new file mode 100644
index 000000000..67a4aed2b
--- /dev/null
+++ b/src/main/java/com/volmit/iris/core/command/CommandIrisDebugSpawnerBoost.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.core.command;
+
+import com.volmit.iris.Iris;
+import com.volmit.iris.core.IrisSettings;
+import com.volmit.iris.core.tools.IrisToolbelt;
+import com.volmit.iris.engine.IrisEngine;
+import com.volmit.iris.util.collection.KList;
+import com.volmit.iris.util.plugin.MortarCommand;
+import com.volmit.iris.util.plugin.VolmitSender;
+
+public class CommandIrisDebugSpawnerBoost extends MortarCommand {
+ public CommandIrisDebugSpawnerBoost() {
+ super("charge", "zzt");
+ requiresPermission(Iris.perm.studio);
+ setDescription("Charge spawner energy");
+ setCategory("Studio");
+ }
+
+
+ @Override
+ public void addTabOptions(VolmitSender sender, String[] args, KList list) {
+
+ }
+
+ @Override
+ public boolean handle(VolmitSender sender, String[] args) {
+ ((IrisEngine)
+ IrisToolbelt.access(sender.player().getWorld()).getEngineAccess(sender.player().getLocation().getBlockY())).getWorldManager().chargeEnergy();
+ return true;
+ }
+
+ @Override
+ protected String getArgsUsage() {
+ return " [|,&,^,>>,<<,%] ";
+ }
+}
diff --git a/src/main/java/com/volmit/iris/engine/IrisWorldManager.java b/src/main/java/com/volmit/iris/engine/IrisWorldManager.java
index 6a2c07bb1..916e52da0 100644
--- a/src/main/java/com/volmit/iris/engine/IrisWorldManager.java
+++ b/src/main/java/com/volmit/iris/engine/IrisWorldManager.java
@@ -25,6 +25,7 @@ import com.volmit.iris.engine.framework.EngineAssignedWorldManager;
import com.volmit.iris.engine.object.biome.IrisBiome;
import com.volmit.iris.engine.object.block.IrisBlockDrops;
import com.volmit.iris.engine.object.common.IRare;
+import com.volmit.iris.engine.object.engine.IrisEngineChunkData;
import com.volmit.iris.engine.object.engine.IrisEngineData;
import com.volmit.iris.engine.object.engine.IrisEngineSpawnerCooldown;
import com.volmit.iris.engine.object.entity.IrisEntitySpawn;
@@ -61,6 +62,8 @@ public class IrisWorldManager extends EngineAssignedWorldManager {
private int entityCount = 0;
private final ChronoLatch cl;
private final ChronoLatch ecl;
+ private final ChronoLatch cln;
+ private long charge = 0;
private int actuallySpawned = 0;
private int cooldown = 0;
private List precount = new KList<>();
@@ -69,12 +72,14 @@ public class IrisWorldManager extends EngineAssignedWorldManager {
super(null);
cl = null;
ecl = null;
+ cln = null;
chunkCooldowns = null;
looper = null;
}
public IrisWorldManager(Engine engine) {
super(engine);
+ cln = new ChronoLatch(60000);
cl = new ChronoLatch(3000);
ecl = new ChronoLatch(250);
chunkCooldowns = new KMap<>();
@@ -82,6 +87,16 @@ public class IrisWorldManager extends EngineAssignedWorldManager {
looper = new Looper() {
@Override
protected long loop() {
+ if(M.ms() < charge)
+ {
+ energy += 70;
+ }
+
+ if(cln.flip())
+ {
+ engine.getEngineData().cleanup(getEngine());
+ }
+
if (precount != null) {
entityCount = 0;
for (Entity i : precount) {
@@ -137,7 +152,6 @@ public class IrisWorldManager extends EngineAssignedWorldManager {
J.s(() -> precount = getEngine().getWorld().realWorld().getEntities());
}
- int maxGroups = 1;
int chunkCooldownSeconds = 60;
for (Long i : chunkCooldowns.k()) {
@@ -158,7 +172,7 @@ public class IrisWorldManager extends EngineAssignedWorldManager {
Chunk c = cc[RNG.r.nextInt(cc.length)];
IrisBiome biome = getEngine().getSurfaceBiome(c);
IrisRegion region = getEngine().getRegion(c);
- spawnIn(c, biome, region, maxGroups);
+ spawnIn(c, biome, region);
chunkCooldowns.put(Cache.key(c), M.ms());
}
@@ -170,15 +184,9 @@ public class IrisWorldManager extends EngineAssignedWorldManager {
energy = M.clip(energy, 1D, 1000D);
}
- private void spawnIn(Chunk c, IrisBiome biome, IrisRegion region, int max) {
- for (Entity i : c.getEntities()) {
- if (i instanceof LivingEntity) {
- return;
- }
- }
-
+ private void spawnIn(Chunk c, IrisBiome biome, IrisRegion region) {
//@builder
- spawnRandomly(Stream.concat(Stream.concat(
+ IrisEntitySpawn v = spawnRandomly(Stream.concat(Stream.concat(
getData().getSpawnerLoader()
.loadAll(getDimension().getEntitySpawners())
.shuffleCopy(RNG.r).stream().filter(this::canSpawn),
@@ -197,16 +205,65 @@ public class IrisWorldManager extends EngineAssignedWorldManager {
.shuffleCopy(RNG.r).stream().filter(this::canSpawn)
.flatMap(this::stream)))
.collect(Collectors.toList()))
- .popRandom(RNG.r, max).forEach((i) -> spawn(c, i));
+ .popRandom(RNG.r);
+
+ if(v != null && v.getReferenceSpawner() != null)
+ {
+ int maxEntCount = v.getReferenceSpawner().getMaxEntitiesPerChunk();
+
+ for (Entity i : c.getEntities()) {
+ if (i instanceof LivingEntity) {
+ if(-maxEntCount <= 0)
+ {
+ return;
+ }
+ }
+ }
+
+ spawn(c, v);
+ }
//@done
}
private void spawn(Chunk c, IrisEntitySpawn i) {
- int s = i.spawn(getEngine(), c, RNG.r);
- actuallySpawned += s;
- if (s > 0) {
- getCooldown(i.getReferenceSpawner()).spawn(getEngine());
- energy -= s * ((i.getEnergyMultiplier() * i.getReferenceSpawner().getEnergyMultiplier() * 1));
+ boolean allow = true;
+
+ if(!i.getReferenceSpawner().getMaximumRatePerChunk().isInfinite())
+ {
+ allow = false;
+ IrisEngineChunkData cd = getEngine().getEngineData().getChunk(c.getX(), c.getZ());
+ IrisEngineSpawnerCooldown sc = null;
+ for(IrisEngineSpawnerCooldown j : cd.getCooldowns())
+ {
+ if(j.getSpawner().equals(i.getReferenceSpawner().getLoadKey()))
+ {
+ sc = j;
+ break;
+ }
+ }
+
+ if(sc == null)
+ {
+ sc = new IrisEngineSpawnerCooldown();
+ sc.setSpawner(i.getReferenceSpawner().getLoadKey());
+ cd.getCooldowns().add(sc);
+ }
+
+ if(sc.canSpawn(i.getReferenceSpawner().getMaximumRatePerChunk()))
+ {
+ sc.spawn(getEngine());
+ allow = true;
+ }
+ }
+
+ if(allow)
+ {
+ int s = i.spawn(getEngine(), c, RNG.r);
+ actuallySpawned += s;
+ if (s > 0) {
+ getCooldown(i.getReferenceSpawner()).spawn(getEngine());
+ energy -= s * ((i.getEnergyMultiplier() * i.getReferenceSpawner().getEnergyMultiplier() * 1));
+ }
}
}
@@ -278,6 +335,11 @@ public class IrisWorldManager extends EngineAssignedWorldManager {
fixEnergy();
}
+ @Override
+ public void chargeEnergy() {
+ charge = M.ms() + 3000;
+ }
+
@Override
public void onBlockBreak(BlockBreakEvent e) {
if (e.getBlock().getWorld().equals(getTarget().getWorld().realWorld()) && getEngine().contains(e.getBlock().getLocation())) {
diff --git a/src/main/java/com/volmit/iris/engine/framework/EngineWorldManager.java b/src/main/java/com/volmit/iris/engine/framework/EngineWorldManager.java
index e025f23ac..e80c2ab53 100644
--- a/src/main/java/com/volmit/iris/engine/framework/EngineWorldManager.java
+++ b/src/main/java/com/volmit/iris/engine/framework/EngineWorldManager.java
@@ -43,4 +43,6 @@ public interface EngineWorldManager {
void onBlockPlace(BlockPlaceEvent e);
void onChunkLoad(Chunk e, boolean generated);
+
+ void chargeEnergy();
}
diff --git a/src/main/java/com/volmit/iris/engine/object/basic/IrisRate.java b/src/main/java/com/volmit/iris/engine/object/basic/IrisRate.java
index bedd1b312..d7c8f93d1 100644
--- a/src/main/java/com/volmit/iris/engine/object/basic/IrisRate.java
+++ b/src/main/java/com/volmit/iris/engine/object/basic/IrisRate.java
@@ -48,4 +48,8 @@ public class IrisRate {
public ChronoLatch toChronoLatch() {
return new ChronoLatch(getInterval());
}
+
+ public boolean isInfinite() {
+ return per.toMilliseconds() == 0;
+ }
}
diff --git a/src/main/java/com/volmit/iris/engine/object/engine/IrisEngineChunkData.java b/src/main/java/com/volmit/iris/engine/object/engine/IrisEngineChunkData.java
new file mode 100644
index 000000000..d16ad785f
--- /dev/null
+++ b/src/main/java/com/volmit/iris/engine/object/engine/IrisEngineChunkData.java
@@ -0,0 +1,47 @@
+/*
+ * 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.engine.object.engine;
+
+import com.volmit.iris.engine.framework.Engine;
+import com.volmit.iris.engine.object.spawners.IrisSpawner;
+import com.volmit.iris.util.collection.KList;
+import lombok.Data;
+
+@Data
+public class IrisEngineChunkData {
+ private long chunk;
+ private KList cooldowns = new KList<>();
+
+ public void cleanup(Engine engine)
+ {
+ for(IrisEngineSpawnerCooldown i : getCooldowns().copy())
+ {
+ IrisSpawner sp = engine.getData().getSpawnerLoader().load(i.getSpawner());
+
+ if(sp == null || i.canSpawn(sp.getMaximumRate()))
+ {
+ getCooldowns().remove(i);
+ }
+ }
+ }
+
+ public boolean isEmpty() {
+ return cooldowns.isEmpty();
+ }
+}
diff --git a/src/main/java/com/volmit/iris/engine/object/engine/IrisEngineData.java b/src/main/java/com/volmit/iris/engine/object/engine/IrisEngineData.java
index f85efe3e4..0252346e1 100644
--- a/src/main/java/com/volmit/iris/engine/object/engine/IrisEngineData.java
+++ b/src/main/java/com/volmit/iris/engine/object/engine/IrisEngineData.java
@@ -18,6 +18,10 @@
package com.volmit.iris.engine.object.engine;
+import com.volmit.iris.engine.data.cache.Cache;
+import com.volmit.iris.engine.framework.Engine;
+import com.volmit.iris.engine.object.meta.IrisEnchantment;
+import com.volmit.iris.engine.object.spawners.IrisSpawner;
import com.volmit.iris.util.collection.KList;
import lombok.Data;
@@ -25,4 +29,51 @@ import lombok.Data;
public class IrisEngineData {
private IrisEngineStatistics statistics = new IrisEngineStatistics();
private KList spawnerCooldowns = new KList<>();
+ private KList chunks = new KList<>();
+
+ public void removeChunk(int x, int z)
+ {
+ long k = Cache.key(x, z);
+ chunks.removeWhere((i) -> i.getChunk() == k);
+ }
+
+ public IrisEngineChunkData getChunk(int x, int z)
+ {
+ long k = Cache.key(x, z);
+
+ for(IrisEngineChunkData i : chunks)
+ {
+ if(i.getChunk() == k)
+ {
+ return i;
+ }
+ }
+
+ IrisEngineChunkData c = new IrisEngineChunkData();
+ c.setChunk(k);
+ chunks.add(c);
+ return c;
+ }
+
+ public void cleanup(Engine engine) {
+ for(IrisEngineSpawnerCooldown i : getSpawnerCooldowns().copy())
+ {
+ IrisSpawner sp = engine.getData().getSpawnerLoader().load(i.getSpawner());
+
+ if(sp == null || i.canSpawn(sp.getMaximumRate()))
+ {
+ getSpawnerCooldowns().remove(i);
+ }
+ }
+
+ for(IrisEngineChunkData i : chunks.copy())
+ {
+ i.cleanup(engine);
+
+ if(i.isEmpty())
+ {
+ getChunks().remove(i);
+ }
+ }
+ }
}
diff --git a/src/main/java/com/volmit/iris/engine/object/engine/IrisEngineSpawnerCooldown.java b/src/main/java/com/volmit/iris/engine/object/engine/IrisEngineSpawnerCooldown.java
index 5fa28dbef..12de56329 100644
--- a/src/main/java/com/volmit/iris/engine/object/engine/IrisEngineSpawnerCooldown.java
+++ b/src/main/java/com/volmit/iris/engine/object/engine/IrisEngineSpawnerCooldown.java
@@ -25,7 +25,7 @@ import lombok.Data;
@Data
public class IrisEngineSpawnerCooldown {
- private long lastSpawn;
+ private long lastSpawn = 0;
private String spawner;
public void spawn(Engine engine) {
diff --git a/src/main/java/com/volmit/iris/engine/object/spawners/IrisSpawner.java b/src/main/java/com/volmit/iris/engine/object/spawners/IrisSpawner.java
index 762fa32f9..116f2afdb 100644
--- a/src/main/java/com/volmit/iris/engine/object/spawners/IrisSpawner.java
+++ b/src/main/java/com/volmit/iris/engine/object/spawners/IrisSpawner.java
@@ -48,6 +48,9 @@ public class IrisSpawner extends IrisRegistrant {
@Desc("The energy multiplier when calculating spawn energy usage")
private double energyMultiplier = 1;
+ @Desc("This spawner will not spawn in a given chunk if that chunk has more than the defined amount of living entities.")
+ private int maxEntitiesPerChunk = 1;
+
@Desc("The block of 24 hour time to contain this spawn in.")
private IrisTimeBlock timeBlock = new IrisTimeBlock();
@@ -57,6 +60,9 @@ public class IrisSpawner extends IrisRegistrant {
@Desc("The maximum rate this spawner can fire")
private IrisRate maximumRate = new IrisRate();
+ @Desc("The maximum rate this spawner can fire on a specific chunk")
+ private IrisRate maximumRatePerChunk = new IrisRate();
+
@Desc("Where should these spawns be placed")
private IrisSpawnGroup group = IrisSpawnGroup.NORMAL;
diff --git a/src/main/java/com/volmit/iris/util/plugin/MortarCommand.java b/src/main/java/com/volmit/iris/util/plugin/MortarCommand.java
index ccb29caa7..8c6302c3d 100644
--- a/src/main/java/com/volmit/iris/util/plugin/MortarCommand.java
+++ b/src/main/java/com/volmit/iris/util/plugin/MortarCommand.java
@@ -91,7 +91,7 @@ public abstract class MortarCommand implements ICommand {
b = true;
- sender.sendMessage("" + C.GREEN + i.getNode() + " " + C.WHITE + "" + i.getArgsUsage() + C.GRAY + " - " + i.getDescription());
+ sender.sendMessage("" + C.GREEN + i.getNode() + " " + "" + (getArgsUsage().trim().isEmpty() ? "" : (C.WHITE + i.getArgsUsage())) + C.GRAY + " - " + i.getDescription());
}
if (!b) {
diff --git a/src/main/java/com/volmit/iris/util/plugin/VolmitSender.java b/src/main/java/com/volmit/iris/util/plugin/VolmitSender.java
index 735734f73..62f26e546 100644
--- a/src/main/java/com/volmit/iris/util/plugin/VolmitSender.java
+++ b/src/main/java/com/volmit/iris/util/plugin/VolmitSender.java
@@ -188,6 +188,12 @@ public class VolmitSender implements CommandSender {
@Override
public void sendMessage(String message) {
+ if(message.contains(""))
+ {
+ s.sendMessage(message.replaceAll("\\Q\\E", ""));
+ return;
+ }
+
try
{
String t = C.translateAlternateColorCodes('&', getTag() + message);
@@ -198,6 +204,10 @@ public class VolmitSender implements CommandSender {
catch(Throwable e)
{
+ String t = C.translateAlternateColorCodes('&', getTag() + message);
+ String a = C.aura(t, IrisSettings.get().getGeneral().getSpinh(), IrisSettings.get().getGeneral().getSpins(), IrisSettings.get().getGeneral().getSpinb());
+
+ Iris.debug("Failure to parse " + a);
s.sendMessage(C.translateAlternateColorCodes('&', getTag() + message));
}
}