Per chunk spawner cooldowns

This commit is contained in:
Daniel Mills
2021-08-06 22:11:17 -04:00
parent d1e8d52f5c
commit 9d251f94e5
12 changed files with 259 additions and 19 deletions

View File

@@ -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())) {

View File

@@ -43,4 +43,6 @@ public interface EngineWorldManager {
void onBlockPlace(BlockPlaceEvent e);
void onChunkLoad(Chunk e, boolean generated);
void chargeEnergy();
}

View File

@@ -48,4 +48,8 @@ public class IrisRate {
public ChronoLatch toChronoLatch() {
return new ChronoLatch(getInterval());
}
public boolean isInfinite() {
return per.toMilliseconds() == 0;
}
}

View File

@@ -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();
}
}

View File

@@ -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);
}
}
}
}

View File

@@ -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) {

View File

@@ -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;