mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2025-07-19 18:55:18 +00:00
Probably wise to quicksave
This commit is contained in:
parent
3e892f30ca
commit
b15b640652
@ -2,18 +2,26 @@ 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.collection.KMap;
|
||||
import com.volmit.iris.util.data.Cuboid;
|
||||
import com.volmit.iris.util.math.BlockPosition;
|
||||
import com.volmit.iris.util.math.RNG;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import com.volmit.iris.util.math.Vector2d;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.block.Block;
|
||||
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.Objects;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public class TreeManager implements Listener {
|
||||
|
||||
@ -58,24 +66,16 @@ public class TreeManager implements Listener {
|
||||
Iris.debug("Sapling grew @ " + event.getLocation() + " for " + event.getSpecies().name() + " usedBoneMeal is " + event.isFromBonemeal());
|
||||
|
||||
// Calculate size, type & placement
|
||||
IrisTreeType type = IrisTreeType.fromTreeType(event.getSpecies());
|
||||
KMap<IrisTreeSize, KList<KList<Location>>> sizes = IrisTreeSize.getValidSizes(event.getLocation());
|
||||
KList<IrisTreeSize> keys = sizes.k();
|
||||
Cuboid saplingPlane = getSaplings(event.getLocation(), blockData -> event.getLocation().getBlock().getBlockData().equals(blockData), event.getWorld());
|
||||
|
||||
// Check if any were returned
|
||||
if (keys.isEmpty()) {
|
||||
Iris.debug(this.getClass().getName() + " found no matching sapling sizes for the grow event, which should be impossible (considering ONE is an option)");
|
||||
if (saplingPlane == null) {
|
||||
Iris.debug(this.getClass().getName() + " found no matching sapling sizes for the grow event, which should be impossible (considering the one that grew is an option)");
|
||||
return;
|
||||
}
|
||||
|
||||
// Find best object placement based on sizes
|
||||
IrisObjectPlacement placement = null;
|
||||
IrisTreeSize bestSize = null;
|
||||
while (placement == null && keys.isNotEmpty()){
|
||||
bestSize = IrisTreeSize.bestSizeInSizes(keys);
|
||||
keys.remove(bestSize);
|
||||
placement = getObjectPlacement(worldAccess, event.getLocation(), type, bestSize);
|
||||
}
|
||||
IrisObjectPlacement placement = getObjectPlacement(worldAccess, event.getLocation(), event.getSpecies(), null);
|
||||
|
||||
// If none were found, just exit
|
||||
if (placement == null) {
|
||||
@ -87,43 +87,48 @@ public class TreeManager implements Listener {
|
||||
event.setCancelled(true);
|
||||
|
||||
// Delete existing saplings
|
||||
sizes.get(bestSize).forEach(row -> row.forEach(location -> location.getBlock().setType(Material.AIR)));
|
||||
saplingPlane.forEach(block -> block.setType(Material.AIR));
|
||||
|
||||
// Get object from placer
|
||||
IrisObject f = worldAccess.getData().getObjectLoader().load(placement.getPlace().getRandom(RNG.r));
|
||||
IrisObject object = worldAccess.getData().getObjectLoader().load(placement.getPlace().getRandom(RNG.r));
|
||||
|
||||
// TODO: Implement placer
|
||||
/*
|
||||
// Create object placer
|
||||
IObjectPlacer placer = new IObjectPlacer(){
|
||||
|
||||
@Override
|
||||
public int getHighest(int x, int z) {
|
||||
return 0;
|
||||
return event.getWorld().getHighestBlockYAt(x, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHighest(int x, int z, boolean ignoreFluid) {
|
||||
return 0;
|
||||
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);
|
||||
|
||||
// Set the block
|
||||
b.setBlockData(d, false);
|
||||
|
||||
// Tell bukkit what you're doing here
|
||||
//TODO event.getBlockStates().add(b.getState());
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockData get(int x, int y, int z) {
|
||||
return null;
|
||||
return event.getWorld().getBlockAt(x, y, z).getBlockData();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPreventingDecay() {
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSolid(int x, int y, int z) {
|
||||
return false;
|
||||
return get(x,y,z).getMaterial().isSolid();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -133,7 +138,7 @@ public class TreeManager implements Listener {
|
||||
|
||||
@Override
|
||||
public int getFluidHeight() {
|
||||
return 0;
|
||||
return ((Engine)worldAccess.getEngineAccess(event.getLocation().getBlockY())).getDimension().getFluidHeight();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -146,22 +151,15 @@ public class TreeManager implements Listener {
|
||||
|
||||
}
|
||||
};
|
||||
*/
|
||||
|
||||
// TODO: Figure out how to place without wrecking claims, other builds, etc.
|
||||
// Especially with large object
|
||||
|
||||
// Place the object with the placer
|
||||
/*
|
||||
f.place(
|
||||
event.getLocation() // TODO: Place the object at the right location (one of the center positions)
|
||||
object.place(
|
||||
saplingPlane.getCenter(),
|
||||
placer,
|
||||
placement,
|
||||
RNG.r,
|
||||
Objects.requireNonNull(IrisWorlds.access(event.getWorld())).getData()
|
||||
Objects.requireNonNull(worldAccess).getData()
|
||||
);
|
||||
*/
|
||||
f.place(event.getLocation());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -172,24 +170,26 @@ public class TreeManager implements Listener {
|
||||
* @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, IrisTreeType type, IrisTreeSize size) {
|
||||
private IrisObjectPlacement getObjectPlacement(IrisAccess worldAccess, Location location, TreeType type, IrisTreeSize size) {
|
||||
|
||||
KList<IrisObjectPlacement> placements = 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));
|
||||
|
||||
// Add more or find any in the region
|
||||
if (worldAccess.getCompound().getRootDimension().getTreeSettings().getMode().equals(IrisTreeModes.ALL) || placements.isEmpty()){
|
||||
if (isUseAll || placements.isEmpty()){
|
||||
IrisRegion region = worldAccess.getCompound().getDefaultEngine().getRegion(location.getBlockX(), location.getBlockZ());
|
||||
placements.addAll(matchObjectPlacements(region.getObjects(), size, type));
|
||||
}
|
||||
|
||||
// Add more or find any in the dimension
|
||||
if (worldAccess.getCompound().getRootDimension().getTreeSettings().getMode().equals(IrisTreeModes.ALL) || placements.isEmpty()){
|
||||
placements.addAll(matchObjectPlacements(worldAccess.getCompound().getRootDimension().getObjects(), size, type));
|
||||
}
|
||||
// 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;
|
||||
@ -202,14 +202,90 @@ public class TreeManager implements Listener {
|
||||
* @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, IrisTreeType type) {
|
||||
KList<IrisObjectPlacement> objectPlacements = new KList<>();
|
||||
objects.stream()
|
||||
.filter(objectPlacement -> objectPlacement.getTreeOptions().isEnabled())
|
||||
.filter(objectPlacement -> objectPlacement.getTreeOptions().getTrees().stream().anyMatch(irisTree ->
|
||||
irisTree.getSizes().stream().anyMatch(treeSize -> treeSize == IrisTreeSize.ANY || treeSize == size) &&
|
||||
irisTree.getTreeTypes().stream().anyMatch(treeType -> treeType == IrisTreeType.ANY || treeType == type)))
|
||||
.forEach(objectPlacements::add);
|
||||
return objectPlacements;
|
||||
private KList<IrisObjectPlacement> matchObjectPlacements(KList<IrisObjectPlacement> objects, IrisTreeSize size, TreeType type) {
|
||||
|
||||
Predicate<IrisTree> isValid = irisTree -> (
|
||||
irisTree.isAnySize() || irisTree.getSizes().stream().anyMatch(treeSize -> treeSize == IrisTreeSize.ANY || treeSize == size)) && (
|
||||
irisTree.isAnyTree() || irisTree.getTreeTypes().stream().anyMatch(treeType -> treeType == 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 null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -150,8 +150,9 @@ public class IrisObjectPlacement {
|
||||
@Desc("The loot tables to apply to these objects")
|
||||
private KList<IrisObjectLoot> loot = new KList<>();
|
||||
|
||||
@Desc("Tree growth overrides for these object placements")
|
||||
private IrisTreeOptions treeOptions = new IrisTreeOptions();
|
||||
@Desc("This objects overrides these trees when they grow...")
|
||||
@ArrayType(min = 1, type = IrisTree.class)
|
||||
private KList<IrisTree> trees = new KList<>();
|
||||
|
||||
public IrisObjectPlacement toPlacement(String... place) {
|
||||
IrisObjectPlacement p = new IrisObjectPlacement();
|
||||
|
@ -1,6 +1,5 @@
|
||||
package com.volmit.iris.engine.object;
|
||||
|
||||
import com.volmit.iris.core.TreeManager;
|
||||
import com.volmit.iris.engine.object.annotations.*;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import lombok.AllArgsConstructor;
|
||||
@ -18,11 +17,17 @@ public class IrisTree {
|
||||
|
||||
@Required
|
||||
@Desc("The types of trees overwritten by this object")
|
||||
@ArrayType(min = 1, type = IrisTreeType.class)
|
||||
private KList<IrisTreeType> treeTypes;
|
||||
@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;
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
package com.volmit.iris.engine.object;
|
||||
|
||||
import com.volmit.iris.engine.object.annotations.ArrayType;
|
||||
import com.volmit.iris.engine.object.annotations.Desc;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
@Accessors(chain = true)
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Desc("Tree replace options for this object placer")
|
||||
@Data
|
||||
public class IrisTreeOptions {
|
||||
|
||||
@Desc("Toggles this object placer's tree overrides")
|
||||
private boolean enabled = false;
|
||||
|
||||
@Desc("Tree overrides affected by these object placements")
|
||||
@ArrayType(min = 1, type = IrisTree.class)
|
||||
private KList<IrisTree> trees = new KList<>();
|
||||
}
|
@ -1,69 +0,0 @@
|
||||
package com.volmit.iris.engine.object;
|
||||
|
||||
import com.volmit.iris.engine.object.annotations.Desc;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.bukkit.TreeType;
|
||||
|
||||
@Accessors(chain = true)
|
||||
@NoArgsConstructor
|
||||
@Desc("Tree Types")
|
||||
public enum IrisTreeType {
|
||||
|
||||
@Desc("Oak tree (BIG_TREE, TREE)")
|
||||
OAK,
|
||||
|
||||
@Desc("Spruce tree (MEGA_REDWOOD, REDWOOD, SWAMP, TALL_REDWOOD)")
|
||||
SPRUCE,
|
||||
|
||||
@Desc("Birch tree (BIRCH, TALL_BIRCH)")
|
||||
BIRCH,
|
||||
|
||||
@Desc("Jungle tree (JUNGLE, SMALL_JUNGLE)")
|
||||
JUNGLE,
|
||||
|
||||
@Desc("Big red mushroom; short and fat")
|
||||
RED_MUSHROOM,
|
||||
|
||||
@Desc("Big brown mushroom; tall and umbrella-like")
|
||||
BROWN_MUSHROOM,
|
||||
|
||||
@Desc("Acacia tree")
|
||||
ACACIA,
|
||||
|
||||
@Desc("Dark Oak tree")
|
||||
DARK_OAK,
|
||||
|
||||
@Desc("Large crimson fungus native to the nether")
|
||||
CRIMSON_FUNGUS,
|
||||
|
||||
@Desc("Large warped fungus native to the nether")
|
||||
WARPED_FUNGUS,
|
||||
|
||||
@Desc("Tree with large roots which grows above lush caves")
|
||||
AZALEA,
|
||||
|
||||
@Desc("Any tree type (all will match, including mushrooms & nether trees")
|
||||
ANY,
|
||||
|
||||
@Desc("The fallback type for all other non-supported growth events")
|
||||
NONE;
|
||||
|
||||
public static IrisTreeType fromTreeType(TreeType type){
|
||||
return switch(type){
|
||||
case BIG_TREE, TREE -> IrisTreeType.OAK;
|
||||
case MEGA_REDWOOD, REDWOOD, SWAMP, TALL_REDWOOD -> IrisTreeType.SPRUCE;
|
||||
case BIRCH, TALL_BIRCH -> IrisTreeType.BIRCH;
|
||||
case JUNGLE, SMALL_JUNGLE -> IrisTreeType.JUNGLE;
|
||||
case RED_MUSHROOM -> IrisTreeType.RED_MUSHROOM;
|
||||
case BROWN_MUSHROOM -> IrisTreeType.BROWN_MUSHROOM;
|
||||
case ACACIA -> IrisTreeType.ACACIA;
|
||||
case DARK_OAK -> IrisTreeType.DARK_OAK;
|
||||
case CRIMSON_FUNGUS -> IrisTreeType.CRIMSON_FUNGUS;
|
||||
case WARPED_FUNGUS -> IrisTreeType.WARPED_FUNGUS;
|
||||
case AZALEA -> IrisTreeType.AZALEA;
|
||||
//case COCOA_TREE, CHORUS_PLANT, JUNGLE_BUSH -> IrisSaplingType.NONE;
|
||||
default -> IrisTreeType.NONE;
|
||||
};
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user