mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2025-07-18 10:12:53 +00:00
Per chunk spawner cooldowns
This commit is contained in:
parent
d1e8d52f5c
commit
9d251f94e5
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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.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<String> 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 "<number> [|,&,^,>>,<<,%] <other>";
|
||||
}
|
||||
}
|
@ -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<Entity> 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())) {
|
||||
|
@ -43,4 +43,6 @@ public interface EngineWorldManager {
|
||||
void onBlockPlace(BlockPlaceEvent e);
|
||||
|
||||
void onChunkLoad(Chunk e, boolean generated);
|
||||
|
||||
void chargeEnergy();
|
||||
}
|
||||
|
@ -48,4 +48,8 @@ public class IrisRate {
|
||||
public ChronoLatch toChronoLatch() {
|
||||
return new ChronoLatch(getInterval());
|
||||
}
|
||||
|
||||
public boolean isInfinite() {
|
||||
return per.toMilliseconds() == 0;
|
||||
}
|
||||
}
|
||||
|
@ -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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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<IrisEngineSpawnerCooldown> 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();
|
||||
}
|
||||
}
|
@ -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<IrisEngineSpawnerCooldown> spawnerCooldowns = new KList<>();
|
||||
private KList<IrisEngineChunkData> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
||||
|
@ -91,7 +91,7 @@ public abstract class MortarCommand implements ICommand {
|
||||
|
||||
b = true;
|
||||
|
||||
sender.sendMessage("" + C.GREEN + i.getNode() + " " + C.WHITE + "<font:minecraft:uniform>" + i.getArgsUsage() + C.GRAY + " - " + i.getDescription());
|
||||
sender.sendMessage("" + C.GREEN + i.getNode() + " " + "<font:minecraft:uniform>" + (getArgsUsage().trim().isEmpty() ? "" : (C.WHITE + i.getArgsUsage())) + C.GRAY + " - " + i.getDescription());
|
||||
}
|
||||
|
||||
if (!b) {
|
||||
|
@ -188,6 +188,12 @@ public class VolmitSender implements CommandSender {
|
||||
|
||||
@Override
|
||||
public void sendMessage(String message) {
|
||||
if(message.contains("<NOMINI>"))
|
||||
{
|
||||
s.sendMessage(message.replaceAll("\\Q<NOMINI>\\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("<NOMINI>Failure to parse " + a);
|
||||
s.sendMessage(C.translateAlternateColorCodes('&', getTag() + message));
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user