This commit is contained in:
Daniel Mills 2021-07-31 12:23:35 -04:00
parent 8cd94f976c
commit 16de60f82d
16 changed files with 299 additions and 135 deletions

View File

@ -40,6 +40,7 @@ public class IrisDataManager {
private ResourceLoader<IrisJigsawPool> jigsawPoolLoader; private ResourceLoader<IrisJigsawPool> jigsawPoolLoader;
private ResourceLoader<IrisJigsawStructure> jigsawStructureLoader; private ResourceLoader<IrisJigsawStructure> jigsawStructureLoader;
private ResourceLoader<IrisEntity> entityLoader; private ResourceLoader<IrisEntity> entityLoader;
private ResourceLoader<IrisSpawner> spawnerLoader;
private ResourceLoader<IrisMod> modLoader; private ResourceLoader<IrisMod> modLoader;
private ResourceLoader<IrisBlockData> blockLoader; private ResourceLoader<IrisBlockData> blockLoader;
private ObjectResourceLoader objectLoader; private ObjectResourceLoader objectLoader;
@ -67,6 +68,7 @@ public class IrisDataManager {
this.biomeLoader = null; this.biomeLoader = null;
this.modLoader = null; this.modLoader = null;
this.dimensionLoader = null; this.dimensionLoader = null;
this.spawnerLoader = null;
this.jigsawPoolLoader = null; this.jigsawPoolLoader = null;
this.jigsawPieceLoader = null; this.jigsawPieceLoader = null;
this.generatorLoader = null; this.generatorLoader = null;
@ -91,6 +93,7 @@ public class IrisDataManager {
File packs = dataFolder; File packs = dataFolder;
packs.mkdirs(); packs.mkdirs();
this.lootLoader = new ResourceLoader<>(packs, this, "loot", "Loot", IrisLootTable.class); this.lootLoader = new ResourceLoader<>(packs, this, "loot", "Loot", IrisLootTable.class);
this.spawnerLoader = new ResourceLoader<>(packs, this, "spawners", "Spawner", IrisSpawner.class);
this.entityLoader = new ResourceLoader<>(packs, this, "entities", "Entity", IrisEntity.class); this.entityLoader = new ResourceLoader<>(packs, this, "entities", "Entity", IrisEntity.class);
this.regionLoader = new ResourceLoader<>(packs, this, "regions", "Region", IrisRegion.class); this.regionLoader = new ResourceLoader<>(packs, this, "regions", "Region", IrisRegion.class);
this.biomeLoader = new ResourceLoader<>(packs, this, "biomes", "Biome", IrisBiome.class); this.biomeLoader = new ResourceLoader<>(packs, this, "biomes", "Biome", IrisBiome.class);
@ -112,6 +115,7 @@ public class IrisDataManager {
blockLoader.clearCache(); blockLoader.clearCache();
lootLoader.clearCache(); lootLoader.clearCache();
objectLoader.clearCache(); objectLoader.clearCache();
spawnerLoader.clearCache();
jigsawPieceLoader.clearCache(); jigsawPieceLoader.clearCache();
jigsawPoolLoader.clearCache(); jigsawPoolLoader.clearCache();
modLoader.clearCache(); modLoader.clearCache();
@ -132,6 +136,7 @@ public class IrisDataManager {
entityLoader.clearList(); entityLoader.clearList();
biomeLoader.clearList(); biomeLoader.clearList();
modLoader.clearList(); modLoader.clearList();
spawnerLoader.clearList();
regionLoader.clearList(); regionLoader.clearList();
dimensionLoader.clearList(); dimensionLoader.clearList();
generatorLoader.clearList(); generatorLoader.clearList();
@ -173,6 +178,10 @@ public class IrisDataManager {
return loadAny(key, (dm) -> dm.getBlockLoader().load(key, false)); return loadAny(key, (dm) -> dm.getBlockLoader().load(key, false));
} }
public static IrisSpawner loadAnySpaner(String key) {
return loadAny(key, (dm) -> dm.getSpawnerLoader().load(key, false));
}
public static IrisRegion loadAnyRegion(String key) { public static IrisRegion loadAnyRegion(String key) {
return loadAny(key, (dm) -> dm.getRegionLoader().load(key, false)); return loadAny(key, (dm) -> dm.getRegionLoader().load(key, false));
} }

View File

@ -474,6 +474,7 @@ public class IrisProject {
KSet<IrisRegion> regions = new KSet<>(); KSet<IrisRegion> regions = new KSet<>();
KSet<IrisBiome> biomes = new KSet<>(); KSet<IrisBiome> biomes = new KSet<>();
KSet<IrisEntity> entities = new KSet<>(); KSet<IrisEntity> entities = new KSet<>();
KSet<IrisSpawner> spawners = new KSet<>();
KSet<IrisGenerator> generators = new KSet<>(); KSet<IrisGenerator> generators = new KSet<>();
KSet<IrisLootTable> loot = new KSet<>(); KSet<IrisLootTable> loot = new KSet<>();
KSet<IrisBlockData> blocks = new KSet<>(); KSet<IrisBlockData> blocks = new KSet<>();
@ -503,13 +504,9 @@ public class IrisProject {
}); });
dimension.getLoot().getTables().forEach((i) -> loot.add(dm.getLootLoader().load(i))); dimension.getLoot().getTables().forEach((i) -> loot.add(dm.getLootLoader().load(i)));
regions.forEach((i) -> biomes.addAll(i.getAllBiomes(null))); regions.forEach((i) -> biomes.addAll(i.getAllBiomes(null)));
biomes.forEach((i) -> i.getGenerators().forEach((j) -> generators.add(j.getCachedGenerator(null))));
regions.forEach((r) -> r.getLoot().getTables().forEach((i) -> loot.add(dm.getLootLoader().load(i)))); regions.forEach((r) -> r.getLoot().getTables().forEach((i) -> loot.add(dm.getLootLoader().load(i))));
biomes.forEach((r) -> r.getLoot().getTables().forEach((i) -> loot.add(dm.getLootLoader().load(i)))); regions.forEach((r) -> r.getEntitySpawners().forEach((sp) -> spawners.add(dm.getSpawnerLoader().load(sp))));
biomes.forEach((r) -> r.getEntitySpawnOverrides().forEach((sp) -> entities.add(dm.getEntityLoader().load(sp.getEntity())))); dimension.getEntitySpawners().forEach((sp) -> spawners.add(dm.getSpawnerLoader().load(sp)));
regions.forEach((r) -> r.getEntitySpawnOverrides().forEach((sp) -> entities.add(dm.getEntityLoader().load(sp.getEntity()))));
dimension.getEntitySpawnOverrides().forEach((sp) -> entities.add(dm.getEntityLoader().load(sp.getEntity())));
biomes.forEach((r) -> r.getEntityInitialSpawns().forEach((sp) -> entities.add(dm.getEntityLoader().load(sp.getEntity()))));
for (int f = 0; f < IrisSettings.get().getGenerator().getMaxBiomeChildDepth(); f++) { for (int f = 0; f < IrisSettings.get().getGenerator().getMaxBiomeChildDepth(); f++) {
biomes.copy().forEach((r) -> { biomes.copy().forEach((r) -> {
@ -521,8 +518,10 @@ public class IrisProject {
}); });
} }
regions.forEach((r) -> r.getEntityInitialSpawns().forEach((sp) -> entities.add(dm.getEntityLoader().load(sp.getEntity())))); biomes.forEach((i) -> i.getGenerators().forEach((j) -> generators.add(j.getCachedGenerator(null))));
dimension.getEntityInitialSpawns().forEach((sp) -> entities.add(dm.getEntityLoader().load(sp.getEntity()))); biomes.forEach((r) -> r.getLoot().getTables().forEach((i) -> loot.add(dm.getLootLoader().load(i))));
biomes.forEach((r) -> r.getEntitySpawners().forEach((sp) -> spawners.add(dm.getSpawnerLoader().load(sp))));
spawners.forEach((i) -> i.getSpawns().forEach((j) -> entities.add(dm.getEntityLoader().load(j.getEntity()))));
KMap<String, String> renameObjects = new KMap<>(); KMap<String, String> renameObjects = new KMap<>();
String a; String a;
StringBuilder b = new StringBuilder(); StringBuilder b = new StringBuilder();

View File

@ -187,7 +187,21 @@ public class SchemaBuilder {
fancyType = "Mythic Mob Type"; fancyType = "Mythic Mob Type";
prop.put("$ref", "#/definitions/" + key); prop.put("$ref", "#/definitions/" + key);
description.add(SYMBOL_TYPE__N + " Must be a valid Mythic Mob Type (use ctrl+space for auto complete!) Define mythic mobs with the mythic mobs plugin configuration files."); description.add(SYMBOL_TYPE__N + " Must be a valid Mythic Mob Type (use ctrl+space for auto complete!) Define mythic mobs with the mythic mobs plugin configuration files.");
} else if (k.isAnnotationPresent(RegistryListBlockType.class)) { }
else if (k.isAnnotationPresent(RegistryListSpawner.class)) {
String key = "enum-reg-spawner";
if (!definitions.containsKey(key)) {
JSONObject j = new JSONObject();
j.put("enum", new JSONArray(data.getSpawnerLoader().getPossibleKeys()));
definitions.put(key, j);
}
fancyType = "Iris Spawner";
prop.put("$ref", "#/definitions/" + key);
description.add(SYMBOL_TYPE__N + " Must be a valid Spawner (use ctrl+space for auto complete!)");
}
else if (k.isAnnotationPresent(RegistryListBlockType.class)) {
String key = "enum-block-type"; String key = "enum-block-type";
if (!definitions.containsKey(key)) { if (!definitions.containsKey(key)) {
@ -463,7 +477,23 @@ public class SchemaBuilder {
items.put("$ref", "#/definitions/" + key); items.put("$ref", "#/definitions/" + key);
prop.put("items", items); prop.put("items", items);
description.add(SYMBOL_TYPE__N + " Must be a valid Biome (use ctrl+space for auto complete!)"); description.add(SYMBOL_TYPE__N + " Must be a valid Biome (use ctrl+space for auto complete!)");
} else if (k.isAnnotationPresent(RegistryListMythical.class)) { }
else if (k.isAnnotationPresent(RegistryListSpawner.class)) {
fancyType = "List of Iris Spawners";
String key = "enum-reg-spawner";
if (!definitions.containsKey(key)) {
JSONObject j = new JSONObject();
j.put("enum", new JSONArray(data.getSpawnerLoader().getPossibleKeys()));
definitions.put(key, j);
}
JSONObject items = new JSONObject();
items.put("$ref", "#/definitions/" + key);
prop.put("items", items);
description.add(SYMBOL_TYPE__N + " Must be a valid Spawner (use ctrl+space for auto complete!)");
}
else if (k.isAnnotationPresent(RegistryListMythical.class)) {
fancyType = "List of Mythic Mob Types"; fancyType = "List of Mythic Mob Types";
String key = "enum-reg-mythical"; String key = "enum-reg-mythical";

View File

@ -210,7 +210,7 @@ public class IrisComplex implements DataProvider {
baseBiomeStream = focus != null ? ProceduralStream.of((x, z) -> focus, baseBiomeStream = focus != null ? ProceduralStream.of((x, z) -> focus,
Interpolated.of(a -> 0D, a -> focus)) : Interpolated.of(a -> 0D, a -> focus)) :
bridgeStream.convertAware2D((t, x, z) -> inferredStreams.get(t).get(x, z)) bridgeStream.convertAware2D((t, x, z) -> inferredStreams.get(t).get(x, z))
.cache2D(cacheSize); .convertAware2D(this::implode).cache2D(cacheSize);
heightStream = ProceduralStream.of((x, z) -> { heightStream = ProceduralStream.of((x, z) -> {
IrisBiome b = focus != null ? focus : baseBiomeStream.get(x, z); IrisBiome b = focus != null ? focus : baseBiomeStream.get(x, z);
return getHeight(engine, b, x, z, engine.getWorld().seed(), true); return getHeight(engine, b, x, z, engine.getWorld().seed(), true);
@ -470,4 +470,29 @@ public class IrisComplex implements DataProvider {
generators.add(cachedGenerator); generators.add(cachedGenerator);
} }
private IrisBiome implode(IrisBiome b, Double x, Double z) {
if (b.getChildren().isEmpty()) {
return b;
}
return implode(b, x, z, 3);
}
private IrisBiome implode(IrisBiome b, Double x, Double z, int max) {
if (max < 0) {
return b;
}
if (b.getChildren().isEmpty()) {
return b;
}
CNG childCell = b.getChildrenGenerator(rng, 123, b.getChildShrinkFactor());
KList<IrisBiome> chx = b.getRealChildren(this).copy();
chx.add(b);
IrisBiome biome = childCell.fitRarity(chx, x, z);
biome.setInferredType(b.getInferredType());
return implode(biome, x, z, max - 1);
}
} }

View File

@ -221,7 +221,6 @@ public class IrisEngine extends BlockPopulator implements Engine {
@ChunkCoordinates @ChunkCoordinates
@Override @Override
public void populate(@NotNull World world, @NotNull Random random, @NotNull Chunk c) { public void populate(@NotNull World world, @NotNull Random random, @NotNull Chunk c) {
getWorldManager().spawnInitialEntities(c);
updateChunk(c); updateChunk(c);
placeTiles(c); placeTiles(c);
} }

View File

@ -19,28 +19,129 @@
package com.volmit.iris.engine; package com.volmit.iris.engine;
import com.volmit.iris.Iris; import com.volmit.iris.Iris;
import com.volmit.iris.core.IrisSettings;
import com.volmit.iris.engine.cache.Cache;
import com.volmit.iris.engine.framework.Engine; import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.framework.EngineAssignedWorldManager; import com.volmit.iris.engine.framework.EngineAssignedWorldManager;
import com.volmit.iris.engine.object.*; import com.volmit.iris.engine.object.*;
import com.volmit.iris.util.collection.KList; 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.documentation.ChunkCoordinates;
import com.volmit.iris.util.math.M;
import com.volmit.iris.util.math.RNG; import com.volmit.iris.util.math.RNG;
import com.volmit.iris.util.scheduling.J; import com.volmit.iris.util.scheduling.J;
import org.bukkit.Chunk; import org.bukkit.Chunk;
import org.bukkit.Location;
import org.bukkit.event.block.BlockBreakEvent; import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.event.block.BlockPlaceEvent; import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.event.entity.EntitySpawnEvent; import org.bukkit.event.entity.EntitySpawnEvent;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import java.util.function.Supplier;
public class IrisWorldManager extends EngineAssignedWorldManager { public class IrisWorldManager extends EngineAssignedWorldManager {
private boolean spawnable; private boolean spawnable;
private final int art;
private final KMap<UUID, Long> spawnCooldowns;
public IrisWorldManager(Engine engine) { public IrisWorldManager(Engine engine) {
super(engine); super(engine);
spawnCooldowns = new KMap<>();
spawnable = true; spawnable = true;
art = J.ar(this::onAsyncTick, 200);
}
private void onAsyncTick() {
int biomeBaseCooldownMinutes = 2;
int biomeSpawnedCooldownMinutes = 3;
int biomeNotSpawnedCooldownMinutes = 5;
for(UUID i : spawnCooldowns.k())
{
if(M.ms() - spawnCooldowns.get(i) > TimeUnit.MINUTES.toMillis(biomeBaseCooldownMinutes))
{
spawnCooldowns.remove(i);
}
}
KMap<UUID, KList<Chunk>> data = new KMap<>();
int spawnBuffer = 8;
for(UUID i : data.k().shuffleCopy(RNG.r))
{
if(spawnCooldowns.containsKey(i))
{
continue;
}
if(spawnBuffer-- < 0)
{
break;
}
spawnCooldowns.put(i, spawnIn(data.get(i).getRandom(), i) ?
(M.ms() + TimeUnit.MINUTES.toMillis(biomeSpawnedCooldownMinutes)) :
(M.ms() + TimeUnit.MINUTES.toMillis(biomeNotSpawnedCooldownMinutes)));
}
}
private boolean spawnIn(Chunk c, UUID id) {
if(c.getEntities().length > 16)
{
return false;
}
return new KList<Supplier<Boolean>>(() -> {
IrisBiome biome = getEngine().getSurfaceBiome(c.getX() << 4, c.getZ() << 4);
for(IrisSpawner i : getData().getSpawnerLoader().loadAll(biome.getEntitySpawners()).shuffleCopy(RNG.r))
{
if(i.spawnInChunk(getEngine(), c))
{
Iris.debug("Spawning Biome Entities in Chunk " + c.getX() + "," + c.getZ() + " Biome ID: " + id);
return true;
}
}
return false;
}, () -> {
IrisRegion region = getEngine().getRegion(c.getX() << 4, c.getZ() << 4);
for(IrisSpawner i : getData().getSpawnerLoader().loadAll(region.getEntitySpawners()).shuffleCopy(RNG.r))
{
if(i.spawnInChunk(getEngine(), c))
{
Iris.debug("Spawning Region Entities in Chunk " + c.getX() + "," + c.getZ() + " Biome ID: " + id);
return true;
}
}
return false;
}, () -> {
for(IrisSpawner i : getData().getSpawnerLoader().loadAll(getDimension().getEntitySpawners()).shuffleCopy(RNG.r))
{
if(i.spawnInChunk(getEngine(), c))
{
Iris.debug("Spawning Dimension Entities in Chunk " + c.getX() + "," + c.getZ() + " Biome ID: " + id);
return true;
}
}
return false;
}).getRandom().get();
}
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 @Override
@ -53,87 +154,6 @@ public class IrisWorldManager extends EngineAssignedWorldManager {
getEngine().getParallax().saveAll(); getEngine().getParallax().saveAll();
} }
@ChunkCoordinates
@Override
public void spawnInitialEntities(Chunk c) {
RNG rng = new RNG(Cache.key(c));
getEngine().getParallaxAccess().getEntitiesR(c.getX(), c.getZ()).iterateSync((x, y, z, e) -> {
if (e != null) {
IrisEntity en = getData().getEntityLoader().load(e);
if (en != null) {
en.spawn(getEngine(), new Location(c.getWorld(), x + (c.getX() << 4), y, z + (c.getZ() << 4)));
}
}
});
int x = (c.getX() * 16) + rng.nextInt(15);
int z = (c.getZ() * 16) + rng.nextInt(15);
int y = getEngine().getHeight(x, z) + 1;
IrisDimension dim = getDimension();
IrisRegion region = getEngine().getRegion(x, z);
IrisBiome above = getEngine().getSurfaceBiome(x, z);
trySpawn(above.getEntityInitialSpawns(), c, rng);
trySpawn(region.getEntityInitialSpawns(), c, rng);
trySpawn(dim.getEntityInitialSpawns(), c, rng);
}
@Override
public void onEntitySpawn(EntitySpawnEvent e) {
if (getTarget().getWorld() == null || !e.getEntity().getWorld().equals(getTarget().getWorld().realWorld())) {
return;
}
try {
if (!IrisSettings.get().getGenerator().isSystemEntitySpawnOverrides()) {
return;
}
int x = e.getEntity().getLocation().getBlockX();
int y = e.getEntity().getLocation().getBlockY();
int z = e.getEntity().getLocation().getBlockZ();
J.a(() ->
{
if (spawnable) {
IrisDimension dim = getDimension();
IrisRegion region = getEngine().getRegion(x, z);
IrisBiome above = getEngine().getSurfaceBiome(x, z);
IrisBiome bbelow = getEngine().getBiome(x, y, z);
if (above.getLoadKey().equals(bbelow.getLoadKey())) {
bbelow = null;
}
IrisBiome below = bbelow;
J.s(() ->
{
if (below != null) {
if (trySpawn(below.getEntitySpawnOverrides(), e)) {
return;
}
}
if (trySpawn(above.getEntitySpawnOverrides(), e)) {
return;
}
if (trySpawn(region.getEntitySpawnOverrides(), e)) {
return;
}
if (trySpawn(dim.getEntitySpawnOverrides(), e)) {
return;
}
});
}
});
} catch (Throwable ee) {
Iris.reportError(ee);
}
}
private boolean trySpawn(KList<IrisEntitySpawnOverride> s, EntitySpawnEvent e) { private boolean trySpawn(KList<IrisEntitySpawnOverride> s, EntitySpawnEvent e) {
for (IrisEntitySpawnOverride i : s) { for (IrisEntitySpawnOverride i : s) {
spawnable = false; spawnable = false;
@ -151,8 +171,8 @@ public class IrisWorldManager extends EngineAssignedWorldManager {
} }
@ChunkCoordinates @ChunkCoordinates
private void trySpawn(KList<IrisEntityInitialSpawn> s, Chunk c, RNG rng) { private void trySpawn(KList<IrisEntitySpawn> s, Chunk c, RNG rng) {
for (IrisEntityInitialSpawn i : s) { for (IrisEntitySpawn i : s) {
i.spawn(getEngine(), c, rng); i.spawn(getEngine(), c, rng);
} }
} }
@ -230,4 +250,11 @@ public class IrisWorldManager extends EngineAssignedWorldManager {
public void onBlockPlace(BlockPlaceEvent e) { public void onBlockPlace(BlockPlaceEvent e) {
} }
@Override
public void close()
{
super.close();
J.car(art);
}
} }

View File

@ -49,6 +49,7 @@ import org.bukkit.inventory.ItemStack;
import java.awt.*; import java.awt.*;
import java.util.Arrays; import java.util.Arrays;
import java.util.UUID;
public interface Engine extends DataProvider, Fallible, GeneratorAccess, LootProvider, BlockUpdater, Renderer, Hotloadable { public interface Engine extends DataProvider, Fallible, GeneratorAccess, LootProvider, BlockUpdater, Renderer, Hotloadable {
void close(); void close();
@ -65,6 +66,11 @@ public interface Engine extends DataProvider, Fallible, GeneratorAccess, LootPro
void setParallelism(int parallelism); void setParallelism(int parallelism);
default UUID getBiomeID(int x, int z)
{
return getFramework().getComplex().getBaseBiomeIDStream().get(x, z);
}
int getParallelism(); int getParallelism();
EngineTarget getTarget(); EngineTarget getTarget();

View File

@ -51,13 +51,6 @@ public abstract class EngineAssignedWorldManager extends EngineAssignedComponent
} }
} }
@EventHandler
public void on(EntitySpawnEvent e) {
if (e.getEntity().getWorld().equals(getTarget().getWorld().realWorld())) {
onEntitySpawn(e);
}
}
@EventHandler @EventHandler
public void on(BlockBreakEvent e) { public void on(BlockBreakEvent e) {
if (e.getPlayer().getWorld().equals(getTarget().getWorld().realWorld())) { if (e.getPlayer().getWorld().equals(getTarget().getWorld().realWorld())) {

View File

@ -18,23 +18,17 @@
package com.volmit.iris.engine.framework; package com.volmit.iris.engine.framework;
import org.bukkit.Chunk;
import org.bukkit.event.block.BlockBreakEvent; import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.event.block.BlockPlaceEvent; import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.event.entity.EntitySpawnEvent;
@SuppressWarnings("EmptyMethod") @SuppressWarnings("EmptyMethod")
public interface EngineWorldManager { public interface EngineWorldManager {
void close(); void close();
void onEntitySpawn(EntitySpawnEvent e);
void onTick(); void onTick();
void onSave(); void onSave();
void spawnInitialEntities(Chunk chunk);
void onBlockBreak(BlockBreakEvent e); void onBlockBreak(BlockBreakEvent e);
void onBlockPlace(BlockPlaceEvent e); void onBlockPlace(BlockPlaceEvent e);

View File

@ -26,6 +26,8 @@ import com.volmit.iris.engine.object.IrisObjectPlacement;
import com.volmit.iris.engine.object.IrisRegion; import com.volmit.iris.engine.object.IrisRegion;
import com.volmit.iris.engine.parallax.ParallaxAccess; import com.volmit.iris.engine.parallax.ParallaxAccess;
import java.util.UUID;
public interface GeneratorAccess extends DataProvider, Renderer { public interface GeneratorAccess extends DataProvider, Renderer {
IrisRegion getRegion(int x, int z); IrisRegion getRegion(int x, int z);

View File

@ -64,17 +64,15 @@ public class IrisBiome extends IrisRegistrant implements IRare {
@Desc("If the biome type custom is defined, specify this") @Desc("If the biome type custom is defined, specify this")
private KList<IrisBiomeCustom> customDerivitives; private KList<IrisBiomeCustom> customDerivitives;
@Desc("Entity spawns to override or add to this biome. Anytime an entity spawns, it has a chance to be replaced as one of these overrides.") @Desc("Spawn Entities in this area over time. Iris will continually replenish these mobs just like vanilla does.")
@ArrayType(min = 1, type = IrisEntitySpawnOverride.class) @ArrayType(min = 1, type = String.class)
private KList<IrisEntitySpawnOverride> entitySpawnOverrides = new KList<>(); @RegistryListSpawner
private KList<String> entitySpawners = new KList<>();
@Desc("Add random chances for terrain features") @Desc("Add random chances for terrain features")
@ArrayType(min = 1, type = IrisFeaturePotential.class) @ArrayType(min = 1, type = IrisFeaturePotential.class)
private KList<IrisFeaturePotential> features = new KList<>(); private KList<IrisFeaturePotential> features = new KList<>();
@Desc("Entity spawns during generation")
@ArrayType(min = 1, type = IrisEntityInitialSpawn.class)
private KList<IrisEntityInitialSpawn> entityInitialSpawns = new KList<>();
@ArrayType(min = 1, type = IrisEffect.class) @ArrayType(min = 1, type = IrisEffect.class)
@Desc("Effects are ambient effects such as potion effects, random sounds, or even particles around each player. All of these effects are played via packets so two players won't see/hear each others effects.\nDue to performance reasons, effects will play around the player even if where the effect was played is no longer in the biome the player is in.") @Desc("Effects are ambient effects such as potion effects, random sounds, or even particles around each player. All of these effects are played via packets so two players won't see/hear each others effects.\nDue to performance reasons, effects will play around the player even if where the effect was played is no longer in the biome the player is in.")

View File

@ -80,18 +80,15 @@ public class IrisDimension extends IrisRegistrant {
@Desc("Upon joining this world, Iris will send a resource pack request to the client. If they have previously selected yes, it will auto-switch depending on which dimension they go to.") @Desc("Upon joining this world, Iris will send a resource pack request to the client. If they have previously selected yes, it will auto-switch depending on which dimension they go to.")
private String resourcePack = ""; private String resourcePack = "";
@Desc("Entity spawns to override or add to this dimension") @Desc("Spawn Entities in this dimension over time. Iris will continually replenish these mobs just like vanilla does.")
@ArrayType(min = 1, type = IrisEntitySpawnOverride.class) @ArrayType(min = 1, type = String.class)
private KList<IrisEntitySpawnOverride> entitySpawnOverrides = new KList<>(); @RegistryListSpawner
private KList<String> entitySpawners = new KList<>();
@Desc("Add specific features in exact positions") @Desc("Add specific features in exact positions")
@ArrayType(min = 1, type = IrisFeaturePositional.class) @ArrayType(min = 1, type = IrisFeaturePositional.class)
private KList<IrisFeaturePositional> specificFeatures = new KList<>(); private KList<IrisFeaturePositional> specificFeatures = new KList<>();
@Desc("Entity spawns during generation")
@ArrayType(min = 1, type = IrisEntityInitialSpawn.class)
private KList<IrisEntityInitialSpawn> entityInitialSpawns = new KList<>();
@Desc("Add random chances for terrain features") @Desc("Add random chances for terrain features")
@ArrayType(min = 1, type = IrisFeaturePotential.class) @ArrayType(min = 1, type = IrisFeaturePotential.class)
private KList<IrisFeaturePotential> features = new KList<>(); private KList<IrisFeaturePotential> features = new KList<>();

View File

@ -39,7 +39,7 @@ import org.bukkit.entity.Entity;
@AllArgsConstructor @AllArgsConstructor
@Desc("Represents an entity spawn during initial chunk generation") @Desc("Represents an entity spawn during initial chunk generation")
@Data @Data
public class IrisEntityInitialSpawn { public class IrisEntitySpawn {
@RegistryListEntity @RegistryListEntity
@Required @Required
@Desc("The entity") @Desc("The entity")
@ -60,7 +60,7 @@ public class IrisEntityInitialSpawn {
private final transient AtomicCache<RNG> rng = new AtomicCache<>(); private final transient AtomicCache<RNG> rng = new AtomicCache<>();
private final transient AtomicCache<IrisEntity> ent = new AtomicCache<>(); private final transient AtomicCache<IrisEntity> ent = new AtomicCache<>();
public void spawn(Engine gen, Chunk c, RNG rng) { public boolean spawn(Engine gen, Chunk c, RNG rng) {
int spawns = rng.i(1, rarity) == 1 ? rng.i(minSpawns, maxSpawns) : 0; int spawns = rng.i(1, rarity) == 1 ? rng.i(minSpawns, maxSpawns) : 0;
if (spawns > 0) { if (spawns > 0) {
@ -70,7 +70,11 @@ public class IrisEntityInitialSpawn {
int h = gen.getHeight(x, z) + gen.getMinHeight(); int h = gen.getHeight(x, z) + gen.getMinHeight();
spawn100(gen, new Location(c.getWorld(), x, h, z)); spawn100(gen, new Location(c.getWorld(), x, h, z));
} }
return true;
} }
return false;
} }
public IrisEntity getRealEntity(Engine g) { public IrisEntity getRealEntity(Engine g) {
@ -91,10 +95,12 @@ public class IrisEntityInitialSpawn {
private Entity spawn100(Engine g, Location at) { private Entity spawn100(Engine g, Location at) {
try { try {
return getRealEntity(g).spawn(g, at.clone().add(0.5, 1, 0.5), rng.aquire(() -> new RNG(g.getTarget().getWorld().seed() + 4))); 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)));
} catch (Throwable e) { } catch (Throwable e) {
Iris.reportError(e); Iris.reportError(e);
Iris.debug("Failed to retrieve real entity @ " + at); Iris.error("Failed to retrieve real entity @ " + at);
return null; return null;
} }
} }

View File

@ -67,13 +67,10 @@ public class IrisRegion extends IrisRegistrant implements IRare {
@Desc("Effects are ambient effects such as potion effects, random sounds, or even particles around each player. All of these effects are played via packets so two players won't see/hear each others effects.\nDue to performance reasons, effects will play arround the player even if where the effect was played is no longer in the biome the player is in.") @Desc("Effects are ambient effects such as potion effects, random sounds, or even particles around each player. All of these effects are played via packets so two players won't see/hear each others effects.\nDue to performance reasons, effects will play arround the player even if where the effect was played is no longer in the biome the player is in.")
private KList<IrisEffect> effects = new KList<>(); private KList<IrisEffect> effects = new KList<>();
@Desc("Entity spawns to override or add to this region") @Desc("Spawn Entities in this region over time. Iris will continually replenish these mobs just like vanilla does.")
@ArrayType(min = 1, type = IrisEntitySpawnOverride.class) @ArrayType(min = 1, type = String.class)
private KList<IrisEntitySpawnOverride> entitySpawnOverrides = new KList<>(); @RegistryListSpawner
private KList<String> entitySpawners = new KList<>();
@Desc("Entity spawns during generation")
@ArrayType(min = 1, type = IrisEntityInitialSpawn.class)
private KList<IrisEntityInitialSpawn> entityInitialSpawns = new KList<>();
@MinNumber(1) @MinNumber(1)
@MaxNumber(128) @MaxNumber(128)

View File

@ -0,0 +1,51 @@
/*
* 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;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.object.annotations.*;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.math.RNG;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import org.bukkit.Chunk;
@EqualsAndHashCode(callSuper = true)
@Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
@Desc("Represents an entity spawn during initial chunk generation")
@Data
public class IrisSpawner extends IrisRegistrant {
@ArrayType(min = 1, type = IrisEntitySpawn.class)
@Desc("The entity spawns to add")
private KList<IrisEntitySpawn> spawns = new KList<>();
public boolean spawnInChunk(Engine engine, Chunk c) {
if(spawns.isEmpty())
{
return false;
}
return spawns.getRandom().spawn(engine, c, RNG.r);
}
}

View File

@ -0,0 +1,31 @@
/*
* 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.annotations;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
@Retention(RUNTIME)
@Target({PARAMETER, TYPE, FIELD})
public @interface RegistryListSpawner {
}