227 lines
7.9 KiB
Java
227 lines
7.9 KiB
Java
package world.bentobox.boxed.generators.chunks;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.Arrays;
|
|
import java.util.Collection;
|
|
import java.util.HashMap;
|
|
import java.util.List;
|
|
import java.util.Objects;
|
|
import java.util.Random;
|
|
|
|
import org.bukkit.Chunk;
|
|
import org.bukkit.ChunkSnapshot;
|
|
import org.bukkit.Location;
|
|
import org.bukkit.World;
|
|
import org.bukkit.block.Banner;
|
|
import org.bukkit.block.Block;
|
|
import org.bukkit.block.BlockState;
|
|
import org.bukkit.block.CreatureSpawner;
|
|
import org.bukkit.block.Sign;
|
|
import org.bukkit.entity.AbstractHorse;
|
|
import org.bukkit.entity.Ageable;
|
|
import org.bukkit.entity.ChestedHorse;
|
|
import org.bukkit.entity.Horse;
|
|
import org.bukkit.entity.LivingEntity;
|
|
import org.bukkit.entity.Player;
|
|
import org.bukkit.entity.Tameable;
|
|
import org.bukkit.entity.Villager;
|
|
import org.bukkit.generator.BiomeProvider;
|
|
import org.bukkit.generator.BlockPopulator;
|
|
import org.bukkit.generator.WorldInfo;
|
|
import org.bukkit.inventory.InventoryHolder;
|
|
import org.bukkit.inventory.ItemStack;
|
|
import org.bukkit.material.Colorable;
|
|
import org.bukkit.util.Vector;
|
|
|
|
import world.bentobox.bentobox.blueprints.dataobjects.BlueprintBlock;
|
|
import world.bentobox.bentobox.blueprints.dataobjects.BlueprintCreatureSpawner;
|
|
import world.bentobox.bentobox.blueprints.dataobjects.BlueprintEntity;
|
|
import world.bentobox.boxed.Boxed;
|
|
|
|
/**
|
|
* Chunk generator for all environments
|
|
* @author tastybento
|
|
*
|
|
*/
|
|
public class BoxedChunkGenerator extends AbstractBoxedChunkGenerator {
|
|
|
|
private final BlockPopulator boxedBlockPopulator;
|
|
|
|
public BoxedChunkGenerator(Boxed addon) {
|
|
super(addon);
|
|
boxedBlockPopulator = new BoxedBlockPopulator(addon);
|
|
}
|
|
|
|
@Override
|
|
public BiomeProvider getDefaultBiomeProvider(WorldInfo worldInfo) {
|
|
return addon.getBoxedBiomeProvider();
|
|
}
|
|
|
|
@Override
|
|
public List<BlockPopulator> getDefaultPopulators(World world) {
|
|
// Only add it once
|
|
if (!world.getPopulators().contains(boxedBlockPopulator)) {
|
|
world.getPopulators().add(boxedBlockPopulator);
|
|
}
|
|
return world.getPopulators();
|
|
}
|
|
|
|
@Override
|
|
protected List<EntityData> getEnts(Chunk chunk) {
|
|
return this.setEntities(Arrays.stream(chunk.getEntities())
|
|
.filter(Objects::nonNull)
|
|
.filter(e -> !(e instanceof Player))
|
|
.filter(e -> e instanceof LivingEntity)
|
|
.map(LivingEntity.class::cast)
|
|
.toList());
|
|
}
|
|
|
|
@Override
|
|
protected List<ChestData> getTileEnts(Chunk chunk) {
|
|
return Arrays.stream(chunk.getTileEntities()).map(t -> new ChestData(getLocInChunk(t.getLocation()), this.getBluePrintBlock(t.getBlock()))).toList();
|
|
}
|
|
|
|
|
|
private List<EntityData> setEntities(Collection<LivingEntity> entities) {
|
|
List<EntityData> bpEnts = new ArrayList<>();
|
|
for (LivingEntity entity: entities) {
|
|
BlueprintEntity bpe = new BlueprintEntity();
|
|
bpe.setType(entity.getType());
|
|
bpe.setCustomName(entity.getCustomName());
|
|
if (entity instanceof Villager villager) {
|
|
setVillager(villager, bpe);
|
|
}
|
|
if (entity instanceof Colorable c) {
|
|
if (c.getColor() != null) {
|
|
bpe.setColor(c.getColor());
|
|
}
|
|
}
|
|
if (entity instanceof Tameable) {
|
|
bpe.setTamed(((Tameable)entity).isTamed());
|
|
}
|
|
if (entity instanceof ChestedHorse) {
|
|
bpe.setChest(((ChestedHorse)entity).isCarryingChest());
|
|
}
|
|
// Only set if child. Most animals are adults
|
|
if (entity instanceof Ageable && !((Ageable)entity).isAdult()) {
|
|
bpe.setAdult(false);
|
|
}
|
|
if (entity instanceof AbstractHorse horse) {
|
|
bpe.setDomestication(horse.getDomestication());
|
|
bpe.setInventory(new HashMap<>());
|
|
for (int i = 0; i < horse.getInventory().getSize(); i++) {
|
|
ItemStack item = horse.getInventory().getItem(i);
|
|
if (item != null) {
|
|
bpe.getInventory().put(i, item);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (entity instanceof Horse horse) {
|
|
bpe.setStyle(horse.getStyle());
|
|
}
|
|
bpEnts.add(new EntityData(getLocInChunk(entity.getLocation()), bpe));
|
|
}
|
|
return bpEnts;
|
|
}
|
|
|
|
// Get the location in the chunk
|
|
private Vector getLocInChunk(Location l) {
|
|
// Have to use Math function because java % doesn't work correctly IMO with negatives
|
|
return new Vector(Math.floorMod(l.getBlockX(),16), l.getBlockY(), Math.floorMod(l.getBlockZ(), 16));
|
|
|
|
}
|
|
|
|
/**
|
|
* Set the villager stats
|
|
* @param v - villager
|
|
* @param bpe - Blueprint Entity
|
|
*/
|
|
private void setVillager(Villager v, BlueprintEntity bpe) {
|
|
bpe.setExperience(v.getVillagerExperience());
|
|
bpe.setLevel(v.getVillagerLevel());
|
|
bpe.setProfession(v.getProfession());
|
|
bpe.setVillagerType(v.getVillagerType());
|
|
}
|
|
|
|
/**
|
|
* Converts the block into a BluePrintBlock that can be pasted later
|
|
* @param block - block to convert
|
|
* @return Blueprint block
|
|
*/
|
|
private BlueprintBlock getBluePrintBlock(Block block) {
|
|
// Block state
|
|
BlockState blockState = block.getState();
|
|
BlueprintBlock b = new BlueprintBlock(block.getBlockData().getAsString());
|
|
|
|
// Signs
|
|
if (blockState instanceof Sign sign) {
|
|
b.setSignLines(Arrays.asList(sign.getLines()));
|
|
b.setGlowingText(sign.isGlowingText());
|
|
}
|
|
|
|
// Chests
|
|
if (blockState instanceof InventoryHolder ih) {
|
|
b.setInventory(new HashMap<>());
|
|
for (int i = 0; i < ih.getInventory().getSize(); i++) {
|
|
ItemStack item = ih.getInventory().getItem(i);
|
|
if (item != null) {
|
|
b.getInventory().put(i, item);
|
|
}
|
|
}
|
|
}
|
|
// Spawner type
|
|
if (blockState instanceof CreatureSpawner spawner) {
|
|
b.setCreatureSpawner(getSpawner(spawner));
|
|
}
|
|
|
|
// Banners
|
|
if (blockState instanceof Banner banner) {
|
|
b.setBannerPatterns(banner.getPatterns());
|
|
}
|
|
|
|
return b;
|
|
}
|
|
|
|
private BlueprintCreatureSpawner getSpawner(CreatureSpawner spawner) {
|
|
BlueprintCreatureSpawner cs = new BlueprintCreatureSpawner();
|
|
cs.setSpawnedType(spawner.getSpawnedType());
|
|
cs.setDelay(spawner.getDelay());
|
|
cs.setMaxNearbyEntities(spawner.getMaxNearbyEntities());
|
|
cs.setMaxSpawnDelay(spawner.getMaxSpawnDelay());
|
|
cs.setMinSpawnDelay(spawner.getMinSpawnDelay());
|
|
cs.setRequiredPlayerRange(spawner.getRequiredPlayerRange());
|
|
cs.setSpawnRange(spawner.getSpawnRange());
|
|
return cs;
|
|
}
|
|
|
|
@Override
|
|
public void generateNoise(WorldInfo worldInfo, Random r, int chunkX, int chunkZ, ChunkData cd) {
|
|
int height = worldInfo.getMaxHeight();
|
|
int minY = worldInfo.getMinHeight();
|
|
int xx = repeatCalc(chunkX);
|
|
int zz = repeatCalc(chunkZ);
|
|
ChunkStore chunk = this.getChunk(xx,zz);
|
|
if (chunk == null) {
|
|
// This should never be needed because islands should abut each other
|
|
//cd.setRegion(0, minY, 0, 16, 0, 16, Material.WATER);
|
|
//BentoBox.getInstance().logError("No chunks found for " + xx + " " + zz);
|
|
return;
|
|
}
|
|
// Copy the chunk
|
|
copyChunkVerbatim(cd, chunk.snapshot(), minY, height);
|
|
|
|
}
|
|
|
|
private void copyChunkVerbatim(ChunkData cd, ChunkSnapshot chunk, int minY, int height) {
|
|
for (int x = 0; x < 16; x ++) {
|
|
for (int z = 0; z < 16; z++) {
|
|
for (int y = minY; y < height; y++) {
|
|
cd.setBlock(x, y, z, chunk.getBlockData(x, y, z));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|