mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2025-07-18 10:12:53 +00:00
Fixes
This commit is contained in:
parent
9a11021560
commit
6b97acdb50
@ -23,6 +23,7 @@ import com.volmit.iris.core.IrisSettings;
|
||||
import com.volmit.iris.engine.framework.*;
|
||||
import com.volmit.iris.engine.hunk.Hunk;
|
||||
import com.volmit.iris.engine.object.*;
|
||||
import com.volmit.iris.engine.object.engine.IrisEngineData;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import com.volmit.iris.util.documentation.BlockCoordinates;
|
||||
@ -86,9 +87,12 @@ public class IrisEngine extends BlockPopulator implements Engine {
|
||||
@Getter
|
||||
private double maxBiomeDecoratorDensity;
|
||||
|
||||
private IrisEngineData engineData;
|
||||
|
||||
public IrisEngine(EngineTarget target, EngineCompound compound, int index) {
|
||||
Iris.info("Initializing Engine: " + target.getWorld().name() + "/" + target.getDimension().getLoadKey() + " (" + target.getHeight() + " height)");
|
||||
metrics = new EngineMetrics(32);
|
||||
engineData = new IrisEngineData();
|
||||
this.target = target;
|
||||
this.framework = new IrisEngineFramework(this);
|
||||
worldManager = new IrisWorldManager(this);
|
||||
@ -218,6 +222,16 @@ public class IrisEngine extends BlockPopulator implements Engine {
|
||||
close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveProperties() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public IrisEngineData getEngineData() {
|
||||
return engineData;
|
||||
}
|
||||
|
||||
@ChunkCoordinates
|
||||
@Override
|
||||
public void populate(@NotNull World world, @NotNull Random random, @NotNull Chunk c) {
|
||||
|
@ -22,11 +22,16 @@ import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.engine.framework.EngineAssignedWorldManager;
|
||||
import com.volmit.iris.engine.object.*;
|
||||
import com.volmit.iris.engine.object.common.IRare;
|
||||
import com.volmit.iris.engine.object.engine.IrisEngineData;
|
||||
import com.volmit.iris.engine.object.engine.IrisEngineSpawnerCooldown;
|
||||
import com.volmit.iris.engine.stream.convert.SelectionStream;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import com.volmit.iris.util.documentation.ChunkCoordinates;
|
||||
import com.volmit.iris.util.math.M;
|
||||
import com.volmit.iris.util.math.RNG;
|
||||
import com.volmit.iris.util.reflect.V;
|
||||
import com.volmit.iris.util.scheduling.ChronoLatch;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
import org.bukkit.Chunk;
|
||||
@ -35,9 +40,12 @@ import org.bukkit.event.block.BlockPlaceEvent;
|
||||
import org.bukkit.event.entity.EntitySpawnEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class IrisWorldManager extends EngineAssignedWorldManager {
|
||||
private boolean spawnable;
|
||||
@ -45,15 +53,17 @@ public class IrisWorldManager extends EngineAssignedWorldManager {
|
||||
private final KMap<UUID, Long> spawnCooldowns;
|
||||
private int entityCount = 0;
|
||||
private ChronoLatch cl = new ChronoLatch(5000);
|
||||
private int actuallySpawned = 0;
|
||||
|
||||
public IrisWorldManager(Engine engine) {
|
||||
super(engine);
|
||||
spawnCooldowns = new KMap<>();
|
||||
spawnable = true;
|
||||
art = J.ar(this::onAsyncTick, 7);
|
||||
art = J.ar(this::onAsyncTick, 20);
|
||||
}
|
||||
|
||||
private void onAsyncTick() {
|
||||
actuallySpawned = 0;
|
||||
if (!getEngine().getWorld().hasRealWorld()) {
|
||||
return;
|
||||
}
|
||||
@ -68,25 +78,20 @@ public class IrisWorldManager extends EngineAssignedWorldManager {
|
||||
J.s(() -> entityCount = getEngine().getWorld().realWorld().getEntities().size());
|
||||
}
|
||||
|
||||
int biomeBaseCooldownSeconds = 1;
|
||||
int biomeSpawnedCooldownSeconds = 0;
|
||||
int biomeNotSpawnedCooldownSeconds = 1;
|
||||
int actuallySpawned = 0;
|
||||
int maxGroups = 3;
|
||||
int biomeBaseCooldownSeconds = 15;
|
||||
|
||||
for(UUID i : spawnCooldowns.k())
|
||||
{
|
||||
if(M.ms() - spawnCooldowns.get(i) > TimeUnit.SECONDS.toMillis(biomeBaseCooldownSeconds))
|
||||
{
|
||||
spawnCooldowns.remove(i);
|
||||
Iris.debug("Biome " + i.toString() + " is off cooldown");
|
||||
}
|
||||
}
|
||||
|
||||
KMap<UUID, KList<Chunk>> data = mapChunkBiomes();
|
||||
int spawnBuffer = 32;
|
||||
|
||||
Iris.debug("Checking " + data.size() + " Loaded Biomes for new spawns...");
|
||||
|
||||
for(UUID i : data.k().shuffleCopy(RNG.r))
|
||||
{
|
||||
if(spawnCooldowns.containsKey(i))
|
||||
@ -99,19 +104,10 @@ public class IrisWorldManager extends EngineAssignedWorldManager {
|
||||
break;
|
||||
}
|
||||
|
||||
Iris.debug(" Spawning for " + i.toString());
|
||||
|
||||
for(int ig = 0; ig < data.get(i).size() / 8; ig++)
|
||||
{
|
||||
boolean g = spawnIn(data.get(i).getRandom(), i);
|
||||
spawnCooldowns.put(i, g ?
|
||||
(M.ms() + TimeUnit.SECONDS.toMillis(biomeSpawnedCooldownSeconds)) :
|
||||
(M.ms() + TimeUnit.SECONDS.toMillis(biomeNotSpawnedCooldownSeconds)));
|
||||
|
||||
if(g)
|
||||
{
|
||||
actuallySpawned++;
|
||||
}
|
||||
spawnIn(data.get(i).getRandom(), i, maxGroups);
|
||||
spawnCooldowns.put(i, M.ms());
|
||||
}
|
||||
}
|
||||
|
||||
@ -121,51 +117,88 @@ public class IrisWorldManager extends EngineAssignedWorldManager {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean spawnIn(Chunk c, UUID id) {
|
||||
private void spawnIn(Chunk c, UUID id, int max) {
|
||||
if(c.getEntities().length > 2)
|
||||
{
|
||||
Iris.debug(" Not spawning in " + id.toString() + " (" + c.getX() + ", " + c.getZ() + "). More than 2 entities in this chunk.");
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
return new KList<Supplier<Boolean>>(() -> {
|
||||
IrisBiome biome = getEngine().getSurfaceBiome(c.getX() << 4, c.getZ() << 4);
|
||||
//@builder
|
||||
puffen(Stream.concat(getData().getSpawnerLoader().loadAll(getDimension().getEntitySpawners())
|
||||
.shuffleCopy(RNG.r).stream().filter(this::canSpawn)
|
||||
.flatMap(this::stream),
|
||||
Stream.concat(getData().getSpawnerLoader()
|
||||
.loadAll(getEngine().getRegion(c.getX() << 4, c.getZ() << 4).getEntitySpawners())
|
||||
.shuffleCopy(RNG.r).stream().filter(this::canSpawn)
|
||||
.flatMap(this::stream),
|
||||
getData().getSpawnerLoader()
|
||||
.loadAll(getEngine().getSurfaceBiome(c.getX() << 4, c.getZ() << 4).getEntitySpawners())
|
||||
.shuffleCopy(RNG.r).stream().filter(this::canSpawn)
|
||||
.flatMap(this::stream)))
|
||||
.collect(Collectors.toList()))
|
||||
.popRandom(RNG.r, max).forEach((i) -> spawn(c, id, i));
|
||||
//@done
|
||||
}
|
||||
|
||||
for(IrisSpawner i : getData().getSpawnerLoader().loadAll(biome.getEntitySpawners()).shuffleCopy(RNG.r))
|
||||
private void spawn(Chunk c, UUID id, IrisEntitySpawn i) {
|
||||
if(i.spawn(getEngine(), c, RNG.r))
|
||||
{
|
||||
if(i.spawnInChunk(getEngine(), c))
|
||||
{
|
||||
Iris.debug(" Spawning Biome Entities in Chunk " + c.getX() + "," + c.getZ() + " Biome ID: " + id);
|
||||
return true;
|
||||
actuallySpawned++;
|
||||
getCooldown(i.getReferenceSpawner()).spawn(getEngine());
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}, () -> {
|
||||
IrisRegion region = getEngine().getRegion(c.getX() << 4, c.getZ() << 4);
|
||||
private Stream<IrisEntitySpawn> stream(IrisSpawner s)
|
||||
{
|
||||
for(IrisEntitySpawn i : s.getSpawns())
|
||||
{
|
||||
i.setReferenceSpawner(s);
|
||||
}
|
||||
|
||||
for(IrisSpawner i : getData().getSpawnerLoader().loadAll(region.getEntitySpawners()).shuffleCopy(RNG.r))
|
||||
return s.getSpawns().stream();
|
||||
}
|
||||
|
||||
private KList<IrisEntitySpawn> puffen(List<IrisEntitySpawn> types)
|
||||
{
|
||||
if(i.spawnInChunk(getEngine(), c))
|
||||
KList<IrisEntitySpawn> rarityTypes = new KList<>();
|
||||
int totalRarity = 0;
|
||||
for (IrisEntitySpawn i : types) {
|
||||
totalRarity += IRare.get(i);
|
||||
}
|
||||
|
||||
for (IrisEntitySpawn i : types) {
|
||||
rarityTypes.addMultiple(i, totalRarity / IRare.get(i));
|
||||
}
|
||||
|
||||
return rarityTypes;
|
||||
}
|
||||
|
||||
public boolean canSpawn(IrisSpawner i)
|
||||
{
|
||||
Iris.debug(" Spawning Region Entities in Chunk " + c.getX() + "," + c.getZ() + " Biome ID: " + id);
|
||||
return true;
|
||||
return i.isValid(getEngine().getWorld().realWorld()) && getCooldown(i).canSpawn(i.getMaximumRate());
|
||||
}
|
||||
|
||||
private IrisEngineSpawnerCooldown getCooldown(IrisSpawner i)
|
||||
{
|
||||
IrisEngineData ed = getEngine().getEngineData();
|
||||
IrisEngineSpawnerCooldown cd = null;
|
||||
|
||||
for (IrisEngineSpawnerCooldown j : ed.getSpawnerCooldowns()) {
|
||||
if (j.getSpawner().equals(i.getLoadKey()))
|
||||
{
|
||||
cd = j;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}, () -> {
|
||||
for(IrisSpawner i : getData().getSpawnerLoader().loadAll(getDimension().getEntitySpawners()).shuffleCopy(RNG.r))
|
||||
if(cd == null)
|
||||
{
|
||||
if(i.spawnInChunk(getEngine(), c))
|
||||
{
|
||||
Iris.debug(" Spawning Dimension Entities in Chunk " + c.getX() + "," + c.getZ() + " Biome ID: " + id);
|
||||
return true;
|
||||
}
|
||||
cd = new IrisEngineSpawnerCooldown();
|
||||
cd.setSpawner(i.getLoadKey());
|
||||
cd.setLastSpawn(M.ms() - i.getMaximumRate().getInterval());
|
||||
ed.getSpawnerCooldowns().add(cd);
|
||||
}
|
||||
|
||||
return false;
|
||||
}).getRandom().get();
|
||||
return cd;
|
||||
}
|
||||
|
||||
public KMap<UUID, KList<Chunk>> mapChunkBiomes()
|
||||
@ -191,29 +224,6 @@ public class IrisWorldManager extends EngineAssignedWorldManager {
|
||||
getEngine().getParallax().saveAll();
|
||||
}
|
||||
|
||||
private boolean trySpawn(KList<IrisEntitySpawnOverride> s, EntitySpawnEvent e) {
|
||||
for (IrisEntitySpawnOverride i : s) {
|
||||
spawnable = false;
|
||||
|
||||
if (i.on(getEngine(), e.getLocation(), e.getEntityType(), e) != null) {
|
||||
e.setCancelled(true);
|
||||
e.getEntity().remove();
|
||||
return true;
|
||||
} else {
|
||||
spawnable = true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@ChunkCoordinates
|
||||
private void trySpawn(KList<IrisEntitySpawn> s, Chunk c, RNG rng) {
|
||||
for (IrisEntitySpawn i : s) {
|
||||
i.spawn(getEngine(), c, rng);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBlockBreak(BlockBreakEvent e) {
|
||||
if(e.getBlock().getWorld().equals(getTarget().getWorld().realWorld()) && getEngine().contains(e.getBlock().getLocation()))
|
||||
|
@ -28,6 +28,7 @@ import com.volmit.iris.engine.data.DataProvider;
|
||||
import com.volmit.iris.engine.hunk.Hunk;
|
||||
import com.volmit.iris.engine.object.*;
|
||||
import com.volmit.iris.engine.object.common.IrisWorld;
|
||||
import com.volmit.iris.engine.object.engine.IrisEngineData;
|
||||
import com.volmit.iris.engine.parallax.ParallaxAccess;
|
||||
import com.volmit.iris.engine.parallel.MultiBurst;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
@ -403,8 +404,7 @@ public interface Engine extends DataProvider, Fallible, GeneratorAccess, LootPro
|
||||
|
||||
void hotloading();
|
||||
|
||||
default void saveProperties()
|
||||
{
|
||||
void saveProperties();
|
||||
|
||||
}
|
||||
IrisEngineData getEngineData();
|
||||
}
|
||||
|
@ -32,9 +32,11 @@ import lombok.experimental.Accessors;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Particle;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.potion.PotionEffect;
|
||||
import org.bukkit.potion.PotionEffectType;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
@Accessors(chain = true)
|
||||
@NoArgsConstructor
|
||||
@ -254,4 +256,40 @@ public class IrisEffect {
|
||||
true, false, false)));
|
||||
}
|
||||
}
|
||||
|
||||
public void apply(Entity p) {
|
||||
if (!canTick()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (RNG.r.nextInt(chance) != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (sound != null) {
|
||||
Location part = p.getLocation().clone().add(RNG.r.i(-soundDistance, soundDistance), RNG.r.i(-soundDistance, soundDistance), RNG.r.i(-soundDistance, soundDistance));
|
||||
|
||||
J.s(() -> p.getWorld().playSound(part, getSound(), (float) volume, (float) RNG.r.d(minPitch, maxPitch)));
|
||||
}
|
||||
|
||||
if (particleEffect != null) {
|
||||
Location part = p.getLocation().clone().add(0, 0.25, 0).add(new Vector(1,1,1).multiply(RNG.r.d())).subtract(new Vector(1,1,1).multiply(RNG.r.d()));
|
||||
part.add(RNG.r.d(), 0, RNG.r.d());
|
||||
if (extra != 0) {
|
||||
J.s(() -> p.getWorld().spawnParticle(particleEffect, part.getX(), part.getY() + RNG.r.i(particleOffset),
|
||||
part.getZ(),
|
||||
particleCount,
|
||||
randomAltX ? RNG.r.d(-particleAltX, particleAltX) : particleAltX,
|
||||
randomAltY ? RNG.r.d(-particleAltY, particleAltY) : particleAltY,
|
||||
randomAltZ ? RNG.r.d(-particleAltZ, particleAltZ) : particleAltZ,
|
||||
extra));
|
||||
} else {
|
||||
J.s(() -> p.getWorld().spawnParticle(particleEffect, part.getX(), part.getY() + RNG.r.i(particleOffset), part.getZ(),
|
||||
particleCount,
|
||||
randomAltX ? RNG.r.d(-particleAltX, particleAltX) : particleAltX,
|
||||
randomAltY ? RNG.r.d(-particleAltY, particleAltY) : particleAltY,
|
||||
randomAltZ ? RNG.r.d(-particleAltZ, particleAltZ) : particleAltZ));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -129,6 +129,9 @@ public class IrisEntity extends IrisRegistrant {
|
||||
@Desc("If specified, this entity will be leashed by this entity. I.e. THIS ENTITY Leashed by SPECIFIED. This has no effect on EnderDragons, Withers, Players, or Bats.Non-living entities excluding leashes will not persist as leashholders.")
|
||||
private IrisEntity leashHolder = null;
|
||||
|
||||
@Desc("If specified, this entity will spawn with an effect")
|
||||
private IrisEffect spawnEffect = null;
|
||||
|
||||
@Desc("The main gene for a panda if the entity type is a panda")
|
||||
private Gene pandaMainGene = Gene.NORMAL;
|
||||
|
||||
@ -150,7 +153,6 @@ public class IrisEntity extends IrisRegistrant {
|
||||
e.setGravity(isGravity());
|
||||
e.setInvulnerable(isInvulnerable());
|
||||
e.setSilent(isSilent());
|
||||
e.setPersistent(true);
|
||||
|
||||
int gg = 0;
|
||||
for (IrisEntity i : passengers) {
|
||||
@ -257,6 +259,11 @@ public class IrisEntity extends IrisRegistrant {
|
||||
m.setAware(isAware());
|
||||
}
|
||||
|
||||
if(spawnEffect != null)
|
||||
{
|
||||
spawnEffect.apply(e);
|
||||
}
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
|
@ -27,6 +27,7 @@ import com.volmit.iris.engine.object.annotations.MinNumber;
|
||||
import com.volmit.iris.engine.object.annotations.RegistryListEntity;
|
||||
import com.volmit.iris.engine.object.annotations.Required;
|
||||
import com.volmit.iris.engine.object.common.IRare;
|
||||
import com.volmit.iris.util.format.C;
|
||||
import com.volmit.iris.util.math.RNG;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
import lombok.AllArgsConstructor;
|
||||
@ -60,6 +61,7 @@ public class IrisEntitySpawn implements IRare {
|
||||
@Desc("The max of this entity to spawn")
|
||||
private int maxSpawns = 1;
|
||||
|
||||
private transient IrisSpawner referenceSpawner;
|
||||
private final transient AtomicCache<RNG> rng = new AtomicCache<>();
|
||||
private final transient AtomicCache<IrisEntity> ent = new AtomicCache<>();
|
||||
|
||||
@ -99,8 +101,13 @@ public class IrisEntitySpawn implements IRare {
|
||||
private Entity spawn100(Engine g, Location at) {
|
||||
try {
|
||||
Location l = at.clone().add(0.5, 1, 0.5);
|
||||
Iris.debug(" Spawned " + "Entity<" + getEntity() + "> at " + l.getBlockX() + "," + l.getBlockY() + "," + l.getBlockZ());
|
||||
return getRealEntity(g).spawn(g, l, rng.aquire(() -> new RNG(g.getTarget().getWorld().seed() + 4)));
|
||||
Entity e = getRealEntity(g).spawn(g, l, rng.aquire(() -> new RNG(g.getTarget().getWorld().seed() + 4)));
|
||||
if(e != null)
|
||||
{
|
||||
Iris.debug("Spawned " + C.DARK_AQUA + "Entity<" + getEntity() + "> " + C.GREEN + e.getType() + C.LIGHT_PURPLE + " @ " + C.GRAY + e.getLocation().getX() + ", " + e.getLocation().getY() + ", " + e.getLocation().getZ());
|
||||
}
|
||||
|
||||
return e;
|
||||
} catch (Throwable e) {
|
||||
Iris.reportError(e);
|
||||
Iris.error(" Failed to retrieve real entity @ " + at);
|
||||
|
@ -43,7 +43,7 @@ public class IrisRate {
|
||||
|
||||
public long getInterval()
|
||||
{
|
||||
long t = per.getMilliseconds() / amount;
|
||||
long t = per.getMilliseconds() / (amount == 0 ? 1 : amount);
|
||||
return Math.abs(t <= 0 ? 1 : t);
|
||||
}
|
||||
|
||||
|
@ -18,7 +18,9 @@
|
||||
|
||||
package com.volmit.iris.engine.object;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.engine.object.annotations.Desc;
|
||||
import com.volmit.iris.util.math.CDou;
|
||||
import lombok.Data;
|
||||
import org.bukkit.World;
|
||||
|
||||
@ -33,24 +35,19 @@ public class IrisTimeBlock {
|
||||
|
||||
public boolean isWithin(World world)
|
||||
{
|
||||
return isWithin(world.getTime() / 1000D);
|
||||
return isWithin(((world.getTime() / 1000D)+6)%24);
|
||||
}
|
||||
|
||||
public boolean isWithin(double hour)
|
||||
{
|
||||
if(startHour == endHour)
|
||||
{
|
||||
if(endHour == -1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return endHour != -1;
|
||||
}
|
||||
|
||||
if(startHour > endHour)
|
||||
{
|
||||
return !(hour >= startHour && hour <= endHour);
|
||||
return hour >= startHour || hour <= endHour;
|
||||
}
|
||||
|
||||
return hour >= startHour && hour <= endHour;
|
||||
|
@ -41,8 +41,8 @@ public enum IrisWeather {
|
||||
return switch(this)
|
||||
{
|
||||
case NONE -> world.isClearWeather();
|
||||
case DOWNFALL -> world.hasStorm() && world.isThundering();
|
||||
case DOWNFALL_WITH_THUNDER -> world.hasStorm();
|
||||
case DOWNFALL -> world.hasStorm();
|
||||
case DOWNFALL_WITH_THUNDER -> world.hasStorm() && world.isThundering();
|
||||
case ANY -> true;
|
||||
};
|
||||
}
|
||||
|
@ -18,10 +18,11 @@
|
||||
|
||||
package com.volmit.iris.engine.object.engine;
|
||||
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class IrisEngineData
|
||||
{
|
||||
|
||||
private KList<IrisEngineSpawnerCooldown> spawnerCooldowns = new KList<>();
|
||||
}
|
||||
|
@ -305,9 +305,13 @@ public interface ProceduralStream<T> extends ProceduralLayer, Interpolated<T> {
|
||||
@SuppressWarnings("unchecked")
|
||||
default <V> ProceduralStream<V> selectRarity(V... types) {
|
||||
KList<V> rarityTypes = new KList<>();
|
||||
int totalRarity = 0;
|
||||
for (V i : types) {
|
||||
totalRarity += IRare.get(i);
|
||||
}
|
||||
|
||||
for (V i : types) {
|
||||
rarityTypes.addMultiple(i, IRare.get(i));
|
||||
rarityTypes.addMultiple(i, totalRarity / IRare.get(i));
|
||||
}
|
||||
|
||||
return new SelectionStream<V>(this, rarityTypes);
|
||||
|
@ -472,6 +472,18 @@ public class KList<T> extends ArrayList<T> implements List<T> {
|
||||
return remove(M.irand(0, last()));
|
||||
}
|
||||
|
||||
public T popRandom(RNG rng) {
|
||||
if (isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (size() == 1) {
|
||||
return pop();
|
||||
}
|
||||
|
||||
return remove(rng.i(0, last()));
|
||||
}
|
||||
|
||||
public static KList<String> fromJSONAny(JSONArray oo) {
|
||||
KList<String> s = new KList<String>();
|
||||
|
||||
@ -613,6 +625,23 @@ public class KList<T> extends ArrayList<T> implements List<T> {
|
||||
return get(M.irand(0, last()));
|
||||
}
|
||||
|
||||
public KList<T> popRandom(RNG rng, int c)
|
||||
{
|
||||
KList<T> m = new KList<>();
|
||||
|
||||
for(int i = 0; i < c; i++)
|
||||
{
|
||||
if(isEmpty())
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
m.add(popRandom());
|
||||
}
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
public T getRandom(RNG rng) {
|
||||
if (isEmpty()) {
|
||||
return null;
|
||||
|
Loading…
x
Reference in New Issue
Block a user