mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2025-07-19 18:55:18 +00:00
568 lines
11 KiB
Java
568 lines
11 KiB
Java
package com.volmit.iris.gen;
|
|
|
|
import java.awt.Color;
|
|
import java.io.IOException;
|
|
import java.util.Random;
|
|
|
|
import org.bukkit.Bukkit;
|
|
import org.bukkit.Chunk;
|
|
import org.bukkit.Location;
|
|
import org.bukkit.block.data.BlockData;
|
|
import org.bukkit.entity.Player;
|
|
import org.bukkit.event.block.BlockDropItemEvent;
|
|
import org.bukkit.event.entity.EntitySpawnEvent;
|
|
import org.bukkit.inventory.ItemStack;
|
|
|
|
import com.volmit.iris.Iris;
|
|
import com.volmit.iris.IrisSettings;
|
|
import com.volmit.iris.gen.atomics.AtomicRegionData;
|
|
import com.volmit.iris.gen.scaffold.IrisContext;
|
|
import com.volmit.iris.gen.scaffold.IrisGenConfiguration;
|
|
import com.volmit.iris.gen.scaffold.TerrainChunk;
|
|
import com.volmit.iris.gen.scaffold.TerrainTarget;
|
|
import com.volmit.iris.gui.Renderer;
|
|
import com.volmit.iris.noise.CNG;
|
|
import com.volmit.iris.object.IrisBiome;
|
|
import com.volmit.iris.object.IrisBlockDrops;
|
|
import com.volmit.iris.object.IrisDimension;
|
|
import com.volmit.iris.object.IrisEffect;
|
|
import com.volmit.iris.object.IrisEntityInitialSpawn;
|
|
import com.volmit.iris.object.IrisEntitySpawnOverride;
|
|
import com.volmit.iris.object.IrisRegion;
|
|
import com.volmit.iris.util.Form;
|
|
import com.volmit.iris.util.IrisStructureResult;
|
|
import com.volmit.iris.util.KList;
|
|
import com.volmit.iris.util.PrecisionStopwatch;
|
|
import com.volmit.iris.util.RNG;
|
|
|
|
import lombok.Data;
|
|
import lombok.EqualsAndHashCode;
|
|
|
|
@Data
|
|
@EqualsAndHashCode(callSuper = false)
|
|
public class IrisTerrainProvider extends SkyTerrainProvider implements IrisContext
|
|
{
|
|
private IrisBiome hb = null;
|
|
private IrisRegion hr = null;
|
|
private boolean spawnable = false;
|
|
|
|
public IrisTerrainProvider(IrisGenConfiguration config)
|
|
{
|
|
super(config.getTarget(), config.getDimension(), config.getThreads());
|
|
}
|
|
|
|
public IrisTerrainProvider(TerrainTarget t, String dimensionName, int threads)
|
|
{
|
|
super(t, dimensionName, threads);
|
|
}
|
|
|
|
public IrisTerrainProvider(TerrainTarget t, String dimensionName)
|
|
{
|
|
super(t, dimensionName, 16);
|
|
}
|
|
|
|
public IrisTerrainProvider(TerrainTarget t, int tc)
|
|
{
|
|
super(t, "", tc);
|
|
}
|
|
|
|
public void hotload()
|
|
{
|
|
onHotload();
|
|
}
|
|
|
|
public void retry()
|
|
{
|
|
if(isFailing())
|
|
{
|
|
setFailing(false);
|
|
hotload();
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void generate(Random no, int x, int z, TerrainChunk terrain)
|
|
{
|
|
PrecisionStopwatch s = PrecisionStopwatch.start();
|
|
super.generate(no, x, z, terrain);
|
|
s.end();
|
|
getMetrics().getTotal().put(s.getMilliseconds());
|
|
}
|
|
|
|
@Override
|
|
protected void onGenerate(RNG random, int x, int z, TerrainChunk terrain)
|
|
{
|
|
super.onGenerate(random, x, z, terrain);
|
|
}
|
|
|
|
public void onInit(RNG rng)
|
|
{
|
|
try
|
|
{
|
|
super.onInit(rng);
|
|
}
|
|
|
|
catch(Throwable e)
|
|
{
|
|
fail(e);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public IrisBiome getBiome(int x, int z)
|
|
{
|
|
return sampleBiome(x, z);
|
|
}
|
|
|
|
@Override
|
|
public IrisRegion getRegion(int x, int z)
|
|
{
|
|
return sampleRegion(x, z);
|
|
}
|
|
|
|
@Override
|
|
public int getHeight(int x, int z)
|
|
{
|
|
return sampleHeight(x, z);
|
|
}
|
|
|
|
@Override
|
|
public void onTick(int ticks)
|
|
{
|
|
spawnable = true;
|
|
super.onTick(ticks);
|
|
for(Player i : getTarget().getPlayers())
|
|
{
|
|
Location l = i.getLocation();
|
|
IrisRegion r = sampleRegion(l.getBlockX(), l.getBlockZ());
|
|
IrisBiome b = sampleTrueBiome(l.getBlockX(), l.getBlockY(), l.getBlockZ());
|
|
|
|
for(IrisEffect j : r.getEffects())
|
|
{
|
|
j.apply(i, this);
|
|
}
|
|
|
|
for(IrisEffect j : b.getEffects())
|
|
{
|
|
j.apply(i, this);
|
|
}
|
|
}
|
|
}
|
|
|
|
@Override
|
|
protected void onClose()
|
|
{
|
|
super.onClose();
|
|
|
|
try
|
|
{
|
|
getParallaxMap().saveAll();
|
|
getParallaxMap().getLoadedChunks().clear();
|
|
getParallaxMap().getLoadedRegions().clear();
|
|
}
|
|
|
|
catch(IOException e)
|
|
{
|
|
e.printStackTrace();
|
|
}
|
|
|
|
setSliverCache(null);
|
|
Iris.info("Closing Iris Dimension " + getTarget().getName());
|
|
}
|
|
|
|
@Override
|
|
protected void onFailure(Throwable e)
|
|
{
|
|
|
|
}
|
|
|
|
@Override
|
|
protected void onChunkLoaded(Chunk c)
|
|
{
|
|
|
|
}
|
|
|
|
@Override
|
|
protected void onChunkUnloaded(Chunk c)
|
|
{
|
|
|
|
}
|
|
|
|
@Override
|
|
protected void onPlayerJoin(Player p)
|
|
{
|
|
if(getDimension().getResourcePack().trim().isEmpty())
|
|
{
|
|
return;
|
|
}
|
|
|
|
p.setResourcePack(getDimension().getResourcePack());
|
|
}
|
|
|
|
@Override
|
|
public void onPlayerLeft(Player p)
|
|
{
|
|
super.onPlayerLeft(p);
|
|
}
|
|
|
|
@Override
|
|
public void onHotloaded()
|
|
{
|
|
if(!IrisSettings.get().isStudio())
|
|
{
|
|
return;
|
|
}
|
|
|
|
if(!isHotloadable())
|
|
{
|
|
Bukkit.getScheduler().scheduleSyncDelayedTask(Iris.instance, this::onHotloaded);
|
|
return;
|
|
}
|
|
|
|
CNG.creates = 0;
|
|
getData().dump();
|
|
getCache().drop();
|
|
onHotload();
|
|
Iris.proj.updateWorkspace(Iris.proj.getWorkspaceFile(getDimension().getLoadKey()));
|
|
}
|
|
|
|
public long guessMemoryUsage()
|
|
{
|
|
long bytes = 1024 * 1024 * (8 + (getThreads() / 3));
|
|
|
|
for(AtomicRegionData i : getParallaxMap().getLoadedRegions().values())
|
|
{
|
|
bytes += i.guessMemoryUsage();
|
|
}
|
|
|
|
bytes += getCache().getSize() * 65;
|
|
bytes += getParallaxMap().getLoadedChunks().size() * 256 * 4 * 460;
|
|
bytes += getSliverBuffer() * 220;
|
|
bytes += 823 * getData().getObjectLoader().getTotalStorage();
|
|
|
|
return bytes / 2;
|
|
}
|
|
|
|
public Renderer createRenderer()
|
|
{
|
|
return (x, z) -> render(x, z);
|
|
}
|
|
|
|
private Color render(double x, double z)
|
|
{
|
|
int ix = (int) x;
|
|
int iz = (int) z;
|
|
double height = getTerrainHeight(ix, iz);
|
|
IrisRegion region = sampleRegion(ix, iz);
|
|
IrisBiome biome = sampleTrueBiome(ix, iz);
|
|
|
|
if(biome.getCachedColor() != null)
|
|
{
|
|
return biome.getCachedColor();
|
|
}
|
|
|
|
float shift = (biome.hashCode() % 32) / 32f / 14f;
|
|
float shift2 = (region.hashCode() % 9) / 9f / 14f;
|
|
shift -= shift2;
|
|
float sat = 0;
|
|
float h = (biome.isLand() ? 0.233f : 0.644f) - shift;
|
|
float s = 0.25f + shift + sat;
|
|
float b = (float) (Math.max(0, Math.min(height + getFluidHeight(), 255)) / 255);
|
|
|
|
Color c = Color.getHSBColor(h, s, b);
|
|
|
|
return c;
|
|
|
|
}
|
|
|
|
public String textFor(double x, double z)
|
|
{
|
|
int ix = (int) x;
|
|
int iz = (int) z;
|
|
double height = getTerrainHeight(ix, iz);
|
|
IrisRegion region = sampleRegion(ix, iz);
|
|
IrisBiome biome = sampleTrueBiome(ix, iz);
|
|
hb = biome;
|
|
hr = region;
|
|
return biome.getName() + " (" + Form.capitalizeWords(biome.getInferredType().name().toLowerCase().replaceAll("\\Q_\\E", " ") + ") in " + region.getName() + "\nY: " + (int) height);
|
|
}
|
|
|
|
public void saveAllParallax()
|
|
{
|
|
try
|
|
{
|
|
getParallaxMap().saveAll();
|
|
}
|
|
|
|
catch(IOException e)
|
|
{
|
|
e.printStackTrace();
|
|
}
|
|
}
|
|
|
|
@Override
|
|
protected void handleDrops(BlockDropItemEvent e)
|
|
{
|
|
int x = e.getBlock().getX();
|
|
int y = e.getBlock().getY();
|
|
int z = e.getBlock().getZ();
|
|
IrisDimension dim = getDimension();
|
|
IrisRegion reg = sampleRegion(x, z);
|
|
IrisBiome bio = sampleTrueBiome(x, z);
|
|
IrisBiome cbio = y < getFluidHeight() ? sampleTrueBiome(x, y, z) : null;
|
|
|
|
if(cbio != null && bio.equals(cbio))
|
|
{
|
|
cbio = null;
|
|
}
|
|
|
|
if(dim.getBlockDrops().isEmpty() && reg.getBlockDrops().isEmpty() && bio.getBlockDrops().isEmpty())
|
|
{
|
|
return;
|
|
}
|
|
|
|
BlockData data = e.getBlockState().getBlockData();
|
|
KList<ItemStack> drops = new KList<>();
|
|
boolean skipParents = false;
|
|
|
|
if(!skipParents && cbio != null)
|
|
{
|
|
for(IrisBlockDrops i : cbio.getBlockDrops())
|
|
{
|
|
if(i.shouldDropFor(data, getData()))
|
|
{
|
|
if(!skipParents && i.isSkipParents())
|
|
{
|
|
skipParents = true;
|
|
}
|
|
|
|
if(i.isReplaceVanillaDrops())
|
|
{
|
|
e.getItems().clear();
|
|
}
|
|
|
|
i.fillDrops(isDev(), drops);
|
|
}
|
|
}
|
|
}
|
|
|
|
if(!skipParents)
|
|
{
|
|
for(IrisBlockDrops i : bio.getBlockDrops())
|
|
{
|
|
if(i.shouldDropFor(data, getData()))
|
|
{
|
|
if(!skipParents && i.isSkipParents())
|
|
{
|
|
skipParents = true;
|
|
}
|
|
|
|
if(i.isReplaceVanillaDrops())
|
|
{
|
|
e.getItems().clear();
|
|
}
|
|
|
|
i.fillDrops(isDev(), drops);
|
|
}
|
|
}
|
|
}
|
|
|
|
if(!skipParents)
|
|
{
|
|
for(IrisBlockDrops i : reg.getBlockDrops())
|
|
{
|
|
if(i.shouldDropFor(data, getData()))
|
|
{
|
|
if(!skipParents && i.isSkipParents())
|
|
{
|
|
skipParents = true;
|
|
}
|
|
|
|
if(i.isReplaceVanillaDrops())
|
|
{
|
|
e.getItems().clear();
|
|
}
|
|
|
|
i.fillDrops(isDev(), drops);
|
|
}
|
|
}
|
|
}
|
|
|
|
if(!skipParents)
|
|
{
|
|
for(IrisBlockDrops i : dim.getBlockDrops())
|
|
{
|
|
if(i.shouldDropFor(data, getData()))
|
|
{
|
|
if(i.isReplaceVanillaDrops())
|
|
{
|
|
e.getItems().clear();
|
|
}
|
|
|
|
i.fillDrops(isDev(), drops);
|
|
}
|
|
}
|
|
}
|
|
|
|
if(drops.isNotEmpty())
|
|
{
|
|
Location l = e.getBlock().getLocation();
|
|
|
|
for(ItemStack i : drops)
|
|
{
|
|
e.getBlock().getWorld().dropItemNaturally(l, i);
|
|
}
|
|
}
|
|
}
|
|
|
|
public void spawnInitials(Chunk c, RNG rng)
|
|
{
|
|
int x = (c.getX() * 16) + rng.nextInt(15);
|
|
int z = (c.getZ() * 16) + rng.nextInt(15);
|
|
int y = getCarvedHeight(x, z) + 1;
|
|
IrisDimension dim = getDimension();
|
|
IrisRegion region = sampleRegion(x, z);
|
|
IrisBiome above = sampleTrueBiome(x, z);
|
|
|
|
IrisStructureResult res = getStructure(x, y, z);
|
|
|
|
if(res != null && res.getTile() != null)
|
|
{
|
|
trySpawn(res.getTile().getEntityInitialSpawns(), c, rng);
|
|
}
|
|
|
|
if(res != null && res.getStructure() != null)
|
|
{
|
|
trySpawn(res.getStructure().getEntityInitialSpawns(), c, rng);
|
|
|
|
}
|
|
|
|
trySpawn(above.getEntityInitialSpawns(), c, rng);
|
|
trySpawn(region.getEntityInitialSpawns(), c, rng);
|
|
trySpawn(dim.getEntityInitialSpawns(), c, rng);
|
|
}
|
|
|
|
@Override
|
|
protected void onSpawn(EntitySpawnEvent e)
|
|
{
|
|
if(isSpawnable())
|
|
{
|
|
int x = e.getEntity().getLocation().getBlockX();
|
|
int y = e.getEntity().getLocation().getBlockY();
|
|
int z = e.getEntity().getLocation().getBlockZ();
|
|
IrisDimension dim = getDimension();
|
|
IrisRegion region = sampleRegion(x, z);
|
|
IrisBiome above = sampleTrueBiome(x, z);
|
|
IrisBiome below = sampleTrueBiome(x, y, z);
|
|
|
|
if(above.getLoadKey().equals(below.getLoadKey()))
|
|
{
|
|
below = null;
|
|
}
|
|
|
|
IrisStructureResult res = getStructure(x, y, z);
|
|
|
|
if(res != null && res.getTile() != null)
|
|
{
|
|
if(trySpawn(res.getTile().getEntitySpawnOverrides(), e))
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
if(res != null && res.getStructure() != null)
|
|
{
|
|
if(trySpawn(res.getStructure().getEntitySpawnOverrides(), e))
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
|
|
private boolean trySpawn(KList<IrisEntitySpawnOverride> s, EntitySpawnEvent e)
|
|
{
|
|
for(IrisEntitySpawnOverride i : s)
|
|
{
|
|
setSpawnable(false);
|
|
|
|
if(i.on(this, e.getLocation(), e.getEntityType(), e) != null)
|
|
{
|
|
e.setCancelled(true);
|
|
e.getEntity().remove();
|
|
return true;
|
|
}
|
|
|
|
else
|
|
{
|
|
setSpawnable(true);
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
private void trySpawn(KList<IrisEntityInitialSpawn> s, Chunk c, RNG rng)
|
|
{
|
|
for(IrisEntityInitialSpawn i : s)
|
|
{
|
|
i.spawn(this, c, rng);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public boolean canSpawn(int x, int z)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
public boolean shouldGenerateCaves()
|
|
{
|
|
return getDimension().isVanillaCaves();
|
|
}
|
|
|
|
@Override
|
|
public boolean shouldGenerateVanillaStructures()
|
|
{
|
|
return getDimension().isVanillaStructures();
|
|
}
|
|
|
|
@Override
|
|
public boolean shouldGenerateMobs()
|
|
{
|
|
// TODO Auto-generated method stub
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
public boolean shouldGenerateDecorations()
|
|
{
|
|
// TODO Auto-generated method stub
|
|
return false;
|
|
}
|
|
}
|