Entity logic

This commit is contained in:
Daniel Mills 2021-08-04 01:07:07 -04:00
parent 008da9467f
commit c5ac347538
7 changed files with 172 additions and 45 deletions

View File

@ -33,7 +33,11 @@ import com.volmit.iris.util.format.Form;
import com.volmit.iris.util.math.RollingSequence;
import com.volmit.iris.util.scheduling.ChronoLatch;
import com.volmit.iris.util.scheduling.J;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.boss.BarColor;
import org.bukkit.boss.BarStyle;
import org.bukkit.boss.BossBar;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
@ -43,12 +47,13 @@ import java.util.List;
public class IrisBoardManager implements BoardProvider, Listener {
private BossBar energyBar;
private final BoardManager manager;
private String mem = "...";
public final RollingSequence hits = new RollingSequence(20);
public final RollingSequence tp = new RollingSequence(100);
private final ChronoLatch cl = new ChronoLatch(1000);
private final ChronoLatch ecl = new ChronoLatch(50);
public IrisBoardManager() {
Iris.instance.registerListener(this);
@ -57,6 +62,7 @@ public class IrisBoardManager implements BoardProvider, Listener {
.boardProvider(this)
.scoreDirection(ScoreDirection.DOWN)
.build());
energyBar = Bukkit.createBossBar("Spawner Energy " + 0, BarColor.BLUE, BarStyle.SOLID);
//@done
}
@ -74,8 +80,11 @@ public class IrisBoardManager implements BoardProvider, Listener {
if (isIrisWorld(p.getWorld())) {
manager.remove(p);
manager.setup(p);
energyBar.removePlayer(p);
energyBar.addPlayer(p);
} else {
manager.remove(p);
energyBar.removePlayer(p);
}
}
@ -110,6 +119,11 @@ public class IrisBoardManager implements BoardProvider, Listener {
}
Engine engine = g.getCompound().getEngineForHeight(y);
if(ecl.flip())
{
energyBar.setProgress(Math.min(1000D, engine.getWorldManager().getEnergy()) / 1000D);
energyBar.setTitle("Spawner Energy: " + Form.f((int)Math.min(1000D, engine.getWorldManager().getEnergy())));
}
int parallaxChunks = 0;
int parallaxRegions = 0;
@ -141,9 +155,9 @@ public class IrisBoardManager implements BoardProvider, Listener {
v.add(C.AQUA + "Biome" + C.GRAY + ": " + engine.getBiome(x, y, z).getName());
v.add(C.AQUA + "Height" + C.GRAY + ": " + Math.round(engine.getHeight(x, z)));
v.add(C.AQUA + "Slope" + C.GRAY + ": " + Form.f(engine.getFramework().getComplex().getSlopeStream().get(x, z), 2));
v.add(C.AQUA + "Features " + C.GRAY + ": " + Form.f(f.size()));
v.add(C.AQUA + "R: " + C.GRAY + ": " + engine.getFramework().getComplex().getRegionIDStream().get(x, z).toString().replaceAll("\\Q-\\E", ""));
v.add(C.AQUA + "B: " + C.GRAY + ": " + engine.getFramework().getComplex().getBaseBiomeIDStream().get(x, z).toString().replaceAll("\\Q-\\E", ""));
v.add(C.AQUA + "Features" + C.GRAY + ": " + Form.f(f.size()));
v.add(C.AQUA + "Energy" + C.GRAY + ": " + Form.f(engine.getWorldManager().getEnergy(), 0));
v.add(C.AQUA + "Sat" + C.GRAY + ": " + Form.f(engine.getWorldManager().getEntityCount()) + "e / " + Form.f(engine.getWorldManager().getChunkCount()) + "c (" + Form.pc(engine.getWorldManager().getEntitySaturation(), 0) + ")");
}
if (Iris.jobCount() > 0) {
@ -159,5 +173,6 @@ public class IrisBoardManager implements BoardProvider, Listener {
public void disable() {
manager.onDisable();
energyBar.removeAll();
}
}

View File

@ -18,7 +18,7 @@
package com.volmit.iris.engine;
import com.volmit.iris.core.IrisSettings;
import com.volmit.iris.Iris;
import com.volmit.iris.engine.cache.Cache;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.framework.EngineAssignedWorldManager;
@ -28,11 +28,17 @@ import com.volmit.iris.engine.object.engine.IrisEngineData;
import com.volmit.iris.engine.object.engine.IrisEngineSpawnerCooldown;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.collection.KMap;
import com.volmit.iris.util.format.Form;
import com.volmit.iris.util.math.M;
import com.volmit.iris.util.math.RNG;
import com.volmit.iris.util.scheduling.ChronoLatch;
import com.volmit.iris.util.scheduling.J;
import com.volmit.iris.util.scheduling.Looper;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.bukkit.Chunk;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.inventory.ItemStack;
@ -43,35 +49,81 @@ import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@EqualsAndHashCode(callSuper = true)
@Data
public class IrisWorldManager extends EngineAssignedWorldManager {
private final int art;
private final Looper looper;
private final KMap<Long, Long> chunkCooldowns;
private double energy = 25;
private int entityCount = 0;
private final ChronoLatch cl;
private final ChronoLatch ecl;
private int actuallySpawned = 0;
private int cooldown = 0;
public IrisWorldManager() {
super(null);
cl = null;
ecl = null;
chunkCooldowns = null;
looper = null;
}
public IrisWorldManager(Engine engine) {
super(engine);
cl = new ChronoLatch(5000);
cl = new ChronoLatch(1000);
ecl = new ChronoLatch(250);
chunkCooldowns = new KMap<>();
art = J.ar(this::onAsyncTick, 7);
energy = 25;
looper = new Looper() {
@Override
protected long loop() {
if(energy < 650)
{
if(ecl.flip())
{
energy *= 1.03;
fixEnergy();
}
}
onAsyncTick();
return 50;
}
};
looper.setPriority(Thread.MIN_PRIORITY);
looper.setName("Iris World Manager");
looper.start();
}
private void onAsyncTick() {
private boolean onAsyncTick() {
actuallySpawned = 0;
if (!getEngine().getWorld().hasRealWorld()) {
return;
if(energy < 35)
{
J.sleep(200);
return false;
}
if ((double) entityCount / (getEngine().getWorld().realWorld().getLoadedChunks().length + 1) > 1) {
return;
if (!getEngine().getWorld().hasRealWorld()) {
Iris.debug("Can't spawn. No real world");
J.sleep(10000);
return false;
}
double epx = getEntitySaturation();
if (epx > 1) {
Iris.debug("Can't spawn. The entity per chunk ratio is at " + Form.pc(epx, 2) + " > 100% (total entities " + entityCount + ")");
J.sleep(5000);
return false;
}
if (cl.flip()) {
J.s(() -> entityCount = getEngine().getWorld().realWorld().getEntities().size());
}
int maxGroups = 3;
int maxGroups = 1;
int chunkCooldownSeconds = 60;
for (Long i : chunkCooldowns.k()) {
@ -80,28 +132,39 @@ public class IrisWorldManager extends EngineAssignedWorldManager {
}
}
int spawnBuffer = 32;
int spawnBuffer = RNG.r.i(2, 12);
for (Chunk c : getEngine().getWorld().realWorld().getLoadedChunks()) {
if (spawnBuffer-- < 0) {
break;
Chunk[] cc = getEngine().getWorld().realWorld().getLoadedChunks();
while(spawnBuffer-- > 0)
{
if(cc.length == 0)
{
Iris.debug("Can't spawn. No chunks!");
return false;
}
Chunk c = cc[RNG.r.nextInt(cc.length)];
IrisBiome biome = getEngine().getSurfaceBiome(c);
IrisRegion region = getEngine().getRegion(c);
spawnIn(c, biome, region, maxGroups);
chunkCooldowns.put(Cache.key(c), M.ms());
}
if (actuallySpawned <= 0) {
J.sleep(5000);
}
energy -= (actuallySpawned / 2D);
return actuallySpawned > 0;
}
private void fixEnergy() {
energy = M.clip(energy, 1D, 1000D);
}
private void spawnIn(Chunk c, IrisBiome biome, IrisRegion region, int max) {
if (c.getEntities().length > 2) {
return;
for(Entity i : c.getEntities())
{
if(i instanceof LivingEntity)
{
return;
}
}
//@builder
@ -129,9 +192,11 @@ public class IrisWorldManager extends EngineAssignedWorldManager {
}
private void spawn(Chunk c, IrisEntitySpawn i) {
if (i.spawn(getEngine(), c, RNG.r)) {
actuallySpawned++;
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) - 1);
}
}
@ -182,17 +247,6 @@ public class IrisWorldManager extends EngineAssignedWorldManager {
return cd;
}
public KMap<UUID, KList<Chunk>> mapChunkBiomes() {
KMap<UUID, KList<Chunk>> data = new KMap<>();
for (Chunk i : getEngine().getWorld().realWorld().getLoadedChunks()) {
data.compute(getEngine().getBiomeID(i.getX() << 4, i.getZ() << 4),
(k, v) -> v != null ? v : new KList<>()).add(i);
}
return data;
}
@Override
public void onTick() {
@ -203,6 +257,21 @@ public class IrisWorldManager extends EngineAssignedWorldManager {
getEngine().getParallax().saveAll();
}
@Override
public void onChunkLoad(Chunk e, boolean generated) {
if(generated)
{
energy += 1.2;
}
else
{
energy += 0.3;
}
fixEnergy();
}
@Override
public void onBlockBreak(BlockBreakEvent e) {
if (e.getBlock().getWorld().equals(getTarget().getWorld().realWorld()) && getEngine().contains(e.getBlock().getLocation())) {
@ -267,6 +336,16 @@ public class IrisWorldManager extends EngineAssignedWorldManager {
@Override
public void close() {
super.close();
J.car(art);
looper.interrupt();
}
@Override
public int getChunkCount() {
return getEngine().getWorld().realWorld().getLoadedChunks().length;
}
@Override
public double getEntitySaturation() {
return (double) entityCount / (getEngine().getWorld().realWorld().getLoadedChunks().length + 1) * 1.665;
}
}

View File

@ -20,16 +20,23 @@ package com.volmit.iris.engine.framework;
import com.volmit.iris.Iris;
import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.event.world.ChunkLoadEvent;
import org.bukkit.event.world.WorldSaveEvent;
import org.bukkit.event.world.WorldUnloadEvent;
public abstract class EngineAssignedWorldManager extends EngineAssignedComponent implements EngineWorldManager, Listener {
private final int taskId;
public EngineAssignedWorldManager() {
super(null, null);
taskId = -1;
}
public EngineAssignedWorldManager(Engine engine) {
super(engine, "World");
Iris.instance.registerListener(this);
@ -64,6 +71,13 @@ public abstract class EngineAssignedWorldManager extends EngineAssignedComponent
}
}
@EventHandler
public void on(ChunkLoadEvent e) {
if (e.getChunk().getWorld().equals(getTarget().getWorld().realWorld())) {
onChunkLoad(e.getChunk(), e.isNewChunk());
}
}
@Override
public void close() {
super.close();

View File

@ -18,6 +18,7 @@
package com.volmit.iris.engine.framework;
import org.bukkit.Chunk;
import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.event.block.BlockPlaceEvent;
@ -25,6 +26,14 @@ import org.bukkit.event.block.BlockPlaceEvent;
public interface EngineWorldManager {
void close();
double getEnergy();
int getEntityCount();
int getChunkCount();
double getEntitySaturation();
void onTick();
void onSave();
@ -32,4 +41,6 @@ public interface EngineWorldManager {
void onBlockBreak(BlockBreakEvent e);
void onBlockPlace(BlockPlaceEvent e);
void onChunkLoad(Chunk e, boolean generated);
}

View File

@ -52,6 +52,9 @@ public class IrisEntitySpawn implements IRare {
@Desc("The entity")
private String entity = "";
@Desc("The energy multiplier when calculating spawn energy usage")
private double energyMultiplier = 1;
@MinNumber(1)
@Desc("The 1 in RARITY chance for this entity to spawn")
private int rarity = 1;
@ -68,7 +71,7 @@ public class IrisEntitySpawn implements IRare {
private final transient AtomicCache<RNG> rng = new AtomicCache<>();
private final transient AtomicCache<IrisEntity> ent = new AtomicCache<>();
public boolean spawn(Engine gen, Chunk c, RNG rng) {
public int spawn(Engine gen, Chunk c, RNG rng) {
int spawns = minSpawns == maxSpawns ? minSpawns : rng.i(Math.min(minSpawns, maxSpawns), Math.max(minSpawns, maxSpawns));
int s = 0;
@ -108,7 +111,7 @@ public class IrisEntitySpawn implements IRare {
}
}
return s > 0;
return s;
}
public IrisEntity getRealEntity(Engine g) {

View File

@ -39,6 +39,9 @@ public class IrisSpawner extends IrisRegistrant {
@Desc("The entity spawns to add")
private KList<IrisEntitySpawn> spawns = new KList<>();
@Desc("The energy multiplier when calculating spawn energy usage")
private double energyMultiplier = 1;
@Desc("The block of 24 hour time to contain this spawn in.")
private IrisTimeBlock timeBlock = new IrisTimeBlock();

View File

@ -30,7 +30,9 @@ import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.function.Function;
@AllArgsConstructor
@ -68,7 +70,7 @@ public class ParallaxChunkMeta {
pcm.setMaxObject(din.readInt());
pcm.setMinObject(din.readInt());
pcm.setCount(din.readInt());
pcm.setFeatures(newList());
pcm.setFeatures(newSet());
int c = din.readInt();
for (int i = 0; i < c; i++) {
@ -88,13 +90,13 @@ public class ParallaxChunkMeta {
private int maxObject = -1;
private int minObject = -1;
private int count;
private List<IrisFeaturePositional> features;
private Set<IrisFeaturePositional> features;
private static List<IrisFeaturePositional> newList() {
return new CopyOnWriteArrayList<>();
private static Set<IrisFeaturePositional> newSet() {
return new CopyOnWriteArraySet<>();
}
public ParallaxChunkMeta() {
this(false, false, false, false, false, false, -1, -1, 0, newList());
this(false, false, false, false, false, false, -1, -1, 0, newSet());
}
}