mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2025-07-18 18:23:06 +00:00
Merge pull request #434 from CocoTheOwner/saplingOverrides
Add sapling / tree overrides WIP
This commit is contained in:
commit
83b4f645db
@ -78,6 +78,7 @@ public class Iris extends VolmitPlugin implements Listener {
|
|||||||
public static BKLink linkBK;
|
public static BKLink linkBK;
|
||||||
public static MultiverseCoreLink linkMultiverseCore;
|
public static MultiverseCoreLink linkMultiverseCore;
|
||||||
public static MythicMobsLink linkMythicMobs;
|
public static MythicMobsLink linkMythicMobs;
|
||||||
|
public static TreeManager saplingManager;
|
||||||
private static final Queue<Runnable> syncJobs = new ShurikenQueue<>();
|
private static final Queue<Runnable> syncJobs = new ShurikenQueue<>();
|
||||||
public static IrisCompat compat;
|
public static IrisCompat compat;
|
||||||
public static FileWatcher configWatcher;
|
public static FileWatcher configWatcher;
|
||||||
@ -181,6 +182,7 @@ public class Iris extends VolmitPlugin implements Listener {
|
|||||||
linkMultiverseCore = new MultiverseCoreLink();
|
linkMultiverseCore = new MultiverseCoreLink();
|
||||||
linkBK = new BKLink();
|
linkBK = new BKLink();
|
||||||
linkMythicMobs = new MythicMobsLink();
|
linkMythicMobs = new MythicMobsLink();
|
||||||
|
saplingManager = new TreeManager();
|
||||||
edit = new EditManager();
|
edit = new EditManager();
|
||||||
configWatcher = new FileWatcher(getDataFile("settings.json"));
|
configWatcher = new FileWatcher(getDataFile("settings.json"));
|
||||||
J.a(() -> IO.delete(getTemp()));
|
J.a(() -> IO.delete(getTemp()));
|
||||||
|
318
src/main/java/com/volmit/iris/core/TreeManager.java
Normal file
318
src/main/java/com/volmit/iris/core/TreeManager.java
Normal file
@ -0,0 +1,318 @@
|
|||||||
|
package com.volmit.iris.core;
|
||||||
|
|
||||||
|
import com.volmit.iris.Iris;
|
||||||
|
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||||
|
import com.volmit.iris.engine.framework.Engine;
|
||||||
|
import com.volmit.iris.engine.framework.IrisAccess;
|
||||||
|
import com.volmit.iris.engine.object.*;
|
||||||
|
import com.volmit.iris.engine.object.common.IObjectPlacer;
|
||||||
|
import com.volmit.iris.engine.object.tile.TileData;
|
||||||
|
import com.volmit.iris.util.collection.KList;
|
||||||
|
import com.volmit.iris.util.data.Cuboid;
|
||||||
|
import com.volmit.iris.util.math.BlockPosition;
|
||||||
|
import com.volmit.iris.util.math.RNG;
|
||||||
|
import com.volmit.iris.util.math.Vector2d;
|
||||||
|
import com.volmit.iris.util.scheduling.J;
|
||||||
|
import org.bukkit.*;
|
||||||
|
import org.bukkit.block.Block;
|
||||||
|
import org.bukkit.block.BlockState;
|
||||||
|
import org.bukkit.block.TileState;
|
||||||
|
import org.bukkit.block.data.BlockData;
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.Listener;
|
||||||
|
import org.bukkit.event.world.StructureGrowEvent;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
|
public class TreeManager implements Listener {
|
||||||
|
|
||||||
|
public TreeManager() {
|
||||||
|
Iris.instance.registerListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**This function does the following
|
||||||
|
* <br>1. Is the sapling growing in an Iris world? No -> exit</br>
|
||||||
|
* <br>2. Is the Iris world accessible? No -> exit</br>
|
||||||
|
* <br>3. Is the sapling overwriting setting on in that dimension? No -> exit</br>
|
||||||
|
* <br>4. Check biome, region and dimension for overrides for that sapling type -> Found -> use</br>
|
||||||
|
* <br>5. Exit if none are found, cancel event if one or more are.</br>
|
||||||
|
* @param event Checks the given event for sapling overrides
|
||||||
|
*/
|
||||||
|
@EventHandler
|
||||||
|
public void onStructureGrowEvent(StructureGrowEvent event) {
|
||||||
|
|
||||||
|
Iris.debug(this.getClass().getName() + " received a structure grow event");
|
||||||
|
|
||||||
|
// Must be iris world
|
||||||
|
if (!IrisToolbelt.isIrisWorld(event.getWorld())) {
|
||||||
|
Iris.debug(this.getClass().getName() + " passed it off to vanilla since not an Iris world");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get world access
|
||||||
|
IrisAccess worldAccess = IrisToolbelt.access(event.getWorld());
|
||||||
|
if (worldAccess == null) {
|
||||||
|
Iris.debug(this.getClass().getName() + " passed it off to vanilla because could not get IrisAccess for this world");
|
||||||
|
Iris.reportError(new NullPointerException(event.getWorld().getName() + " could not be accessed despite being an Iris world"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return null if not enabled
|
||||||
|
if (!worldAccess.getCompound().getRootDimension().getTreeSettings().isEnabled()) {
|
||||||
|
Iris.debug(this.getClass().getName() + " cancelled because tree overrides are disabled");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Iris.debug("Sapling grew @ " + event.getLocation() + " for " + event.getSpecies().name() + " usedBoneMeal is " + event.isFromBonemeal());
|
||||||
|
|
||||||
|
// Calculate size, type & placement
|
||||||
|
// TODO: Patch algorithm to retrieve saplings, as it's not working as intended (only ever returns 1x1)
|
||||||
|
Cuboid saplingPlane = getSaplings(event.getLocation(), blockData -> event.getLocation().getBlock().getBlockData().equals(blockData), event.getWorld());
|
||||||
|
Iris.debug("Sapling plane is: " + saplingPlane.getSizeX() + " by " + saplingPlane.getSizeZ());
|
||||||
|
|
||||||
|
// Find best object placement based on sizes
|
||||||
|
IrisObjectPlacement placement = getObjectPlacement(worldAccess, event.getLocation(), event.getSpecies(), new IrisTreeSize(1, 1));
|
||||||
|
|
||||||
|
// If none were found, just exit
|
||||||
|
if (placement == null) {
|
||||||
|
Iris.debug(this.getClass().getName() + " had options but did not manage to find objectPlacements for them");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete existing saplings
|
||||||
|
saplingPlane.forEach(block -> block.setType(Material.AIR));
|
||||||
|
|
||||||
|
// Get object from placer
|
||||||
|
IrisObject object = worldAccess.getData().getObjectLoader().load(placement.getPlace().getRandom(RNG.r));
|
||||||
|
|
||||||
|
// List of new blocks
|
||||||
|
List<BlockState> blockStateList = new KList<>();
|
||||||
|
saplingPlane.forEach(b -> blockStateList.add(b.getState()));
|
||||||
|
|
||||||
|
// Create object placer
|
||||||
|
IObjectPlacer placer = new IObjectPlacer() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getHighest(int x, int z) {
|
||||||
|
return event.getWorld().getHighestBlockYAt(x, z);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getHighest(int x, int z, boolean ignoreFluid) {
|
||||||
|
return event.getWorld().getHighestBlockYAt(x, z, ignoreFluid ? HeightMap.OCEAN_FLOOR : HeightMap.WORLD_SURFACE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void set(int x, int y, int z, BlockData d) {
|
||||||
|
Block b = event.getWorld().getBlockAt(x, y, z);
|
||||||
|
BlockState state = b.getState();
|
||||||
|
state.setBlockData(d);
|
||||||
|
blockStateList.add(b.getState());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BlockData get(int x, int y, int z) {
|
||||||
|
return event.getWorld().getBlockAt(x, y, z).getBlockData();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isPreventingDecay() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isSolid(int x, int y, int z) {
|
||||||
|
return get(x,y,z).getMaterial().isSolid();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isUnderwater(int x, int z) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getFluidHeight() {
|
||||||
|
Engine engine;
|
||||||
|
if (worldAccess.getCompound().getSize() > 1) {
|
||||||
|
engine = worldAccess.getCompound().getEngine(0);
|
||||||
|
} else {
|
||||||
|
engine = (Engine) worldAccess.getCompound().getRootDimension();
|
||||||
|
}
|
||||||
|
return engine.getDimension().getFluidHeight();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isDebugSmartBore() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setTile(int xx, int yy, int zz, TileData<? extends TileState> tile) {
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// TODO: Prevent placing on claimed blocks (however that's defined, idk)
|
||||||
|
|
||||||
|
// TODO: Prevent placing object when overriding blocks
|
||||||
|
|
||||||
|
// Place the object with the placer
|
||||||
|
object.place(
|
||||||
|
saplingPlane.getCenter(),
|
||||||
|
placer,
|
||||||
|
placement,
|
||||||
|
RNG.r,
|
||||||
|
Objects.requireNonNull(worldAccess).getData()
|
||||||
|
);
|
||||||
|
|
||||||
|
// Cancel the vanilla placement
|
||||||
|
event.setCancelled(true);
|
||||||
|
|
||||||
|
// Queue sync task
|
||||||
|
J.s(() -> {
|
||||||
|
|
||||||
|
// Send out a new event
|
||||||
|
StructureGrowEvent iGrow = new StructureGrowEvent(event.getLocation(), event.getSpecies(), event.isFromBonemeal(), event.getPlayer(), blockStateList);
|
||||||
|
Bukkit.getServer().getPluginManager().callEvent(iGrow);
|
||||||
|
|
||||||
|
// Check if blocks need to be updated
|
||||||
|
if(!iGrow.isCancelled()){
|
||||||
|
for (BlockState block : iGrow.getBlocks()) {
|
||||||
|
block.update(true, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds a single object placement (which may contain more than one object) for the requirements species, location & size
|
||||||
|
* @param worldAccess The world to access (check for biome, region, dimension, etc)
|
||||||
|
* @param location The location of the growth event (For biome/region finding)
|
||||||
|
* @param type The bukkit TreeType to match
|
||||||
|
* @param size The size of the sapling area
|
||||||
|
* @return An object placement which contains the matched tree, or null if none were found / it's disabled.
|
||||||
|
*/
|
||||||
|
private IrisObjectPlacement getObjectPlacement(IrisAccess worldAccess, Location location, TreeType type, IrisTreeSize size) {
|
||||||
|
|
||||||
|
KList<IrisObjectPlacement> placements = new KList<>();
|
||||||
|
KList<IrisObjectPlacement> allObjects = new KList<>();
|
||||||
|
boolean isUseAll = ((Engine)worldAccess.getEngineAccess(location.getBlockY())).getDimension().getTreeSettings().getMode().equals(IrisTreeModes.ALL);
|
||||||
|
|
||||||
|
// Retrieve objectPlacements of type `species` from biome
|
||||||
|
IrisBiome biome = worldAccess.getBiome(location.getBlockX(), location.getBlockY(), location.getBlockZ());
|
||||||
|
placements.addAll(matchObjectPlacements(biome.getObjects(), size, type));
|
||||||
|
allObjects.addAll(biome.getObjects());
|
||||||
|
|
||||||
|
// Add more or find any in the region
|
||||||
|
if (isUseAll || placements.isEmpty()){
|
||||||
|
IrisRegion region = worldAccess.getCompound().getDefaultEngine().getRegion(location.getBlockX(), location.getBlockZ());
|
||||||
|
placements.addAll(matchObjectPlacements(region.getObjects(), size, type));
|
||||||
|
allObjects.addAll(region.getObjects());
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Add more or find any in the dimension
|
||||||
|
// Add object placer to dimension
|
||||||
|
// if (isUseAll || placements.isEmpty()){
|
||||||
|
// placements.addAll(matchObjectPlacements(worldAccess.getCompound().getRootDimension().getObjects(), size, type));
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Check if no matches were found, return a random one if they are
|
||||||
|
return placements.isNotEmpty() ? placements.getRandom(RNG.r) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filters out mismatches and returns matches
|
||||||
|
* @param objects The object placements to check
|
||||||
|
* @param size The size of the sapling area to filter with
|
||||||
|
* @param type The type of the tree to filter with
|
||||||
|
* @return A list of objectPlacements that matched. May be empty.
|
||||||
|
*/
|
||||||
|
private KList<IrisObjectPlacement> matchObjectPlacements(KList<IrisObjectPlacement> objects, IrisTreeSize size, TreeType type) {
|
||||||
|
|
||||||
|
Predicate<IrisTree> isValid = irisTree -> (
|
||||||
|
irisTree.isAnySize() || irisTree.getSizes().stream().anyMatch(treeSize -> treeSize.doesMatch(size))) && (
|
||||||
|
irisTree.isAnyTree() || irisTree.getTreeTypes().stream().anyMatch(treeType -> treeType.equals(type)));
|
||||||
|
|
||||||
|
objects.removeIf(objectPlacement -> objectPlacement.getTrees().stream().noneMatch(isValid));
|
||||||
|
|
||||||
|
return objects;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the Cuboid of sapling sizes at a location & blockData predicate
|
||||||
|
* @param at this location
|
||||||
|
* @param valid with this blockData predicate
|
||||||
|
* @param world the world to check in
|
||||||
|
* @return A cuboid containing only saplings
|
||||||
|
*/
|
||||||
|
public Cuboid getSaplings(Location at, Predicate<BlockData> valid, World world) {
|
||||||
|
KList<BlockPosition> blockPositions = new KList<>();
|
||||||
|
grow(at.getWorld(), new BlockPosition(at.getBlockX(), at.getBlockY(), at.getBlockZ()), valid, blockPositions);
|
||||||
|
BlockPosition a = new BlockPosition(Integer.MIN_VALUE, Integer.MIN_VALUE, Integer.MIN_VALUE);
|
||||||
|
BlockPosition b = new BlockPosition(Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE);
|
||||||
|
|
||||||
|
// Maximise the block position in x and z to get max cuboid bounds
|
||||||
|
for(BlockPosition blockPosition : blockPositions)
|
||||||
|
{
|
||||||
|
a.max(blockPosition);
|
||||||
|
b.min(blockPosition);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a cuboid with the size calculated before
|
||||||
|
Cuboid cuboid = new Cuboid(a.toBlock(world).getLocation(), b.toBlock(world).getLocation());
|
||||||
|
boolean cuboidIsValid = true;
|
||||||
|
|
||||||
|
// Loop while the cuboid is larger than 2
|
||||||
|
while(Math.min(cuboid.getSizeX(), cuboid.getSizeZ()) > 0)
|
||||||
|
{
|
||||||
|
checking:
|
||||||
|
for(int i = cuboid.getLowerX(); i < cuboid.getUpperX(); i++)
|
||||||
|
{
|
||||||
|
for(int j = cuboid.getLowerY(); j < cuboid.getUpperY(); j++)
|
||||||
|
{
|
||||||
|
for(int k = cuboid.getLowerZ(); k < cuboid.getUpperZ(); k++)
|
||||||
|
{
|
||||||
|
if(!blockPositions.contains(new BlockPosition(i,j,k)))
|
||||||
|
{
|
||||||
|
cuboidIsValid = false;
|
||||||
|
break checking;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return this cuboid if it's valid
|
||||||
|
if(cuboidIsValid)
|
||||||
|
{
|
||||||
|
return cuboid;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Inset the cuboid and try again (revalidate)
|
||||||
|
cuboid = cuboid.inset(Cuboid.CuboidDirection.Horizontal, 1);
|
||||||
|
cuboidIsValid = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Cuboid(at, at);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Grows the blockPosition list by means of checking neighbours in
|
||||||
|
* @param world the world to check in
|
||||||
|
* @param center the location of this position
|
||||||
|
* @param valid validation on blockData to check block with
|
||||||
|
* @param l list of block positions to add new neighbors too
|
||||||
|
*/
|
||||||
|
private void grow(World world, BlockPosition center, Predicate<BlockData> valid, KList<BlockPosition> l) {
|
||||||
|
// Make sure size is less than 50, the block to check isn't already in, and make sure the blockData still matches
|
||||||
|
if(l.size() <= 50 && !l.contains(center) && valid.test(center.toBlock(world).getBlockData()))
|
||||||
|
{
|
||||||
|
l.add(center);
|
||||||
|
grow(world, center.add(1, 0, 0), valid, l);
|
||||||
|
grow(world, center.add(-1, 0, 0), valid, l);
|
||||||
|
grow(world, center.add(0, 0, 1), valid, l);
|
||||||
|
grow(world, center.add(0, 0, -1), valid, l);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -49,6 +49,7 @@ public class DustRevealer {
|
|||||||
|
|
||||||
if (a.getObject(block.getX(), block.getY(), block.getZ()) != null) {
|
if (a.getObject(block.getX(), block.getY(), block.getZ()) != null) {
|
||||||
sender.sendMessage("Found object " + a.getObject(block.getX(), block.getY(), block.getZ()));
|
sender.sendMessage("Found object " + a.getObject(block.getX(), block.getY(), block.getZ()));
|
||||||
|
Iris.info(sender.getName() + " found object " + a.getObject(block.getX(), block.getY(), block.getZ()));
|
||||||
J.a(() -> {
|
J.a(() -> {
|
||||||
new DustRevealer(a, world, new BlockPosition(block.getX(), block.getY(), block.getZ()), a.getObject(block.getX(), block.getY(), block.getZ()), new KList<>());
|
new DustRevealer(a, world, new BlockPosition(block.getX(), block.getY(), block.getZ()), a.getObject(block.getX(), block.getY(), block.getZ()), new KList<>());
|
||||||
});
|
});
|
||||||
|
@ -77,7 +77,7 @@ public class IrisBiome extends IrisRegistrant implements IRare {
|
|||||||
private KList<IrisEntityInitialSpawn> entityInitialSpawns = new KList<>();
|
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 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 around 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<>();
|
||||||
|
|
||||||
@DependsOn({"biomeStyle", "biomeZoom", "biomeScatter"})
|
@DependsOn({"biomeStyle", "biomeZoom", "biomeScatter"})
|
||||||
|
@ -70,6 +70,10 @@ public class IrisDimension extends IrisRegistrant {
|
|||||||
@Desc("Improves the biome grid variation by shuffling the cell grid more depending on the seed. This makes biomes across multiple seeds look far different than before.")
|
@Desc("Improves the biome grid variation by shuffling the cell grid more depending on the seed. This makes biomes across multiple seeds look far different than before.")
|
||||||
private boolean aggressiveBiomeReshuffle = false;
|
private boolean aggressiveBiomeReshuffle = false;
|
||||||
|
|
||||||
|
@Desc("Tree growth override settings")
|
||||||
|
private IrisTreeSettings treeSettings = new IrisTreeSettings();
|
||||||
|
|
||||||
|
|
||||||
@Desc("Instead of a flat bottom, applies a clamp (using this noise style) to the bottom instead of a flat bottom. Useful for carving out center-dimensions in a dimension composite world.")
|
@Desc("Instead of a flat bottom, applies a clamp (using this noise style) to the bottom instead of a flat bottom. Useful for carving out center-dimensions in a dimension composite world.")
|
||||||
private IrisShapedGeneratorStyle undercarriage = null;
|
private IrisShapedGeneratorStyle undercarriage = null;
|
||||||
|
|
||||||
|
@ -416,6 +416,10 @@ public class IrisObject extends IrisRegistrant {
|
|||||||
return place(x, yv, z, placer, config, rng, null, null, rdata);
|
return place(x, yv, z, placer, config, rng, null, null, rdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int place(Location loc, IObjectPlacer placer, IrisObjectPlacement config, RNG rng, IrisDataManager rdata) {
|
||||||
|
return place(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ(), placer, config, rng, rdata);
|
||||||
|
}
|
||||||
|
|
||||||
public int place(int x, int yv, int z, IObjectPlacer oplacer, IrisObjectPlacement config, RNG rng, Consumer<BlockPosition> listener, CarveResult c, IrisDataManager rdata) {
|
public int place(int x, int yv, int z, IObjectPlacer oplacer, IrisObjectPlacement config, RNG rng, Consumer<BlockPosition> listener, CarveResult c, IrisDataManager rdata) {
|
||||||
IObjectPlacer placer = (config.getHeightmap() != null) ? new IObjectPlacer() {
|
IObjectPlacer placer = (config.getHeightmap() != null) ? new IObjectPlacer() {
|
||||||
final long s = rng.nextLong() + yv + z - x;
|
final long s = rng.nextLong() + yv + z - x;
|
||||||
|
@ -62,7 +62,6 @@ public class IrisObjectPlacement {
|
|||||||
@Desc("The maximum layer level of a snow filter overtop of this placement. Set to 0 to disable. Max of 1.")
|
@Desc("The maximum layer level of a snow filter overtop of this placement. Set to 0 to disable. Max of 1.")
|
||||||
private double snow = 0;
|
private double snow = 0;
|
||||||
|
|
||||||
@Required
|
|
||||||
@MinNumber(0)
|
@MinNumber(0)
|
||||||
@MaxNumber(1)
|
@MaxNumber(1)
|
||||||
@Desc("The chance for this to place in a chunk. If you need multiple per chunk, set this to 1 and use density.")
|
@Desc("The chance for this to place in a chunk. If you need multiple per chunk, set this to 1 and use density.")
|
||||||
@ -147,6 +146,10 @@ public class IrisObjectPlacement {
|
|||||||
@Desc("The loot tables to apply to these objects")
|
@Desc("The loot tables to apply to these objects")
|
||||||
private KList<IrisObjectLoot> loot = new KList<>();
|
private KList<IrisObjectLoot> loot = new KList<>();
|
||||||
|
|
||||||
|
@Desc("This object / these objects override the following trees when they grow...")
|
||||||
|
@ArrayType(min = 1, type = IrisTree.class)
|
||||||
|
private KList<IrisTree> trees = new KList<>();
|
||||||
|
|
||||||
public IrisObjectPlacement toPlacement(String... place) {
|
public IrisObjectPlacement toPlacement(String... place) {
|
||||||
IrisObjectPlacement p = new IrisObjectPlacement();
|
IrisObjectPlacement p = new IrisObjectPlacement();
|
||||||
p.setPlace(new KList<>(place));
|
p.setPlace(new KList<>(place));
|
||||||
|
@ -20,8 +20,10 @@ package com.volmit.iris.engine.object;
|
|||||||
|
|
||||||
import com.volmit.iris.engine.object.annotations.Desc;
|
import com.volmit.iris.engine.object.annotations.Desc;
|
||||||
|
|
||||||
@Desc("The terrain mode used to tell iris how to generate land")
|
@Desc("Terrain modes are used to decide the generator type currently used")
|
||||||
public enum IrisTerrainMode {
|
public enum IrisTerrainMode {
|
||||||
|
@Desc("Normal terrain, similar to the vanilla overworld")
|
||||||
NORMAL,
|
NORMAL,
|
||||||
|
@Desc("Island terrain, more similar to the end, but endless possibilities!")
|
||||||
ISLANDS
|
ISLANDS
|
||||||
}
|
}
|
||||||
|
33
src/main/java/com/volmit/iris/engine/object/IrisTree.java
Normal file
33
src/main/java/com/volmit/iris/engine/object/IrisTree.java
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
package com.volmit.iris.engine.object;
|
||||||
|
|
||||||
|
import com.volmit.iris.engine.object.annotations.*;
|
||||||
|
import com.volmit.iris.util.collection.KList;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.experimental.Accessors;
|
||||||
|
import org.bukkit.TreeType;
|
||||||
|
|
||||||
|
@Accessors(chain = true)
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
@Desc("Tree replace options for this object placer")
|
||||||
|
@Data
|
||||||
|
public class IrisTree {
|
||||||
|
|
||||||
|
@Required
|
||||||
|
@Desc("The types of trees overwritten by this object")
|
||||||
|
@ArrayType(min = 1, type = TreeType.class)
|
||||||
|
private KList<TreeType> treeTypes;
|
||||||
|
|
||||||
|
@Desc("If enabled, overrides any TreeType")
|
||||||
|
private boolean anyTree = false;
|
||||||
|
|
||||||
|
@Required
|
||||||
|
@Desc("The size of the square of saplings this applies to (2 means a 2 * 2 sapling area)")
|
||||||
|
@ArrayType(min = 1, type = IrisTreeSize.class)
|
||||||
|
private KList<IrisTreeSize> sizes = new KList<>();
|
||||||
|
|
||||||
|
@Desc("If enabled, overrides trees of any size")
|
||||||
|
private boolean anySize;
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
package com.volmit.iris.engine.object;
|
||||||
|
|
||||||
|
import com.volmit.iris.engine.object.annotations.Desc;
|
||||||
|
|
||||||
|
@Desc("Sapling override object picking options")
|
||||||
|
public enum IrisTreeModes {
|
||||||
|
@Desc("Check biome, then region, then dimension, pick the first one that has options")
|
||||||
|
FIRST,
|
||||||
|
|
||||||
|
@Desc("Check biome, regions, and dimensions, and pick any option from the total list")
|
||||||
|
ALL
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
package com.volmit.iris.engine.object;
|
||||||
|
|
||||||
|
import com.volmit.iris.engine.object.annotations.Desc;
|
||||||
|
import com.volmit.iris.engine.object.annotations.Required;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
|
@Accessors(chain = true)
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
@Desc("Tree growth override settings")
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = false)
|
||||||
|
public class IrisTreeSettings {
|
||||||
|
|
||||||
|
@Required
|
||||||
|
@Desc("Turn replacing on and off")
|
||||||
|
boolean enabled = false;
|
||||||
|
|
||||||
|
@Desc("Object picking modes")
|
||||||
|
IrisTreeModes mode = IrisTreeModes.FIRST;
|
||||||
|
}
|
@ -0,0 +1,33 @@
|
|||||||
|
package com.volmit.iris.engine.object;
|
||||||
|
|
||||||
|
import com.volmit.iris.engine.object.annotations.Desc;
|
||||||
|
import com.volmit.iris.engine.object.annotations.Required;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
|
@Accessors(chain = true)
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@Desc("Sapling override object picking options")
|
||||||
|
@Data
|
||||||
|
public class IrisTreeSize {
|
||||||
|
|
||||||
|
@Required
|
||||||
|
@Desc("The width of the sapling area")
|
||||||
|
int width = 1;
|
||||||
|
|
||||||
|
@Required
|
||||||
|
@Desc("The depth of the sapling area")
|
||||||
|
int depth = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Does the size match
|
||||||
|
* @param size the size to check match
|
||||||
|
* @return true if it matches (fits within width and depth)
|
||||||
|
*/
|
||||||
|
public boolean doesMatch(IrisTreeSize size){
|
||||||
|
return (width == size.getWidth() && depth == size.getDepth()) || (depth == size.getWidth() && width == size.getDepth());
|
||||||
|
}
|
||||||
|
}
|
@ -20,7 +20,7 @@ package com.volmit.iris.engine.object;
|
|||||||
|
|
||||||
import com.volmit.iris.engine.object.annotations.Desc;
|
import com.volmit.iris.engine.object.annotations.Desc;
|
||||||
|
|
||||||
@Desc("A loot mode is used to descrive what to do with the existing loot layers before adding this loot. Using ADD will simply add this table to the building list of tables (i.e. add dimension tables, region tables then biome tables). By using clear or replace, you remove the parent tables before and add just your tables.")
|
@Desc("A loot mode is used to describe what to do with the existing loot layers before adding this loot. Using ADD will simply add this table to the building list of tables (i.e. add dimension tables, region tables then biome tables). By using clear or replace, you remove the parent tables before and add just your tables.")
|
||||||
public enum LootMode {
|
public enum LootMode {
|
||||||
@Desc("Add to the existing parent loot tables")
|
@Desc("Add to the existing parent loot tables")
|
||||||
ADD,
|
ADD,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user