mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2025-07-18 10:12:53 +00:00
Can you smell the rot?
This commit is contained in:
parent
2ffd1e6e47
commit
a8a87e7f79
@ -1,91 +0,0 @@
|
||||
/*
|
||||
* 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.core.tools;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.engine.framework.IrisAccess;
|
||||
import com.volmit.iris.engine.framework.IrisAccessProvider;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import com.volmit.iris.util.plugin.VolmitSender;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
@SuppressWarnings("ALL")
|
||||
public class IrisWorlds {
|
||||
private static final KMap<String, IrisAccess> provisioned = new KMap<>();
|
||||
|
||||
public static void register(World w, IrisAccess p) {
|
||||
provisioned.put(w.getUID().toString(), p);
|
||||
}
|
||||
|
||||
public static boolean isIrisWorld(World world) {
|
||||
if (world == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (provisioned.containsKey(world.getUID().toString())) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return world.getGenerator() instanceof IrisAccess || world.getGenerator() instanceof IrisAccessProvider;
|
||||
}
|
||||
|
||||
public static IrisAccess access(World world) {
|
||||
if (isIrisWorld(world)) {
|
||||
if (provisioned.containsKey(world.getUID().toString())) {
|
||||
return provisioned.get(world.getUID().toString());
|
||||
}
|
||||
|
||||
return world.getGenerator() instanceof IrisAccessProvider ? (((IrisAccessProvider) world.getGenerator()).getAccess()) : ((IrisAccess) world.getGenerator());
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static boolean evacuate(World world) {
|
||||
for (World i : Bukkit.getWorlds()) {
|
||||
if (!i.getName().equals(world.getName())) {
|
||||
for (Player j : world.getPlayers()) {
|
||||
new VolmitSender(j, Iris.instance.getTag()).sendMessage("You have been evacuated from this world.");
|
||||
j.teleport(i.getSpawnLocation());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean evacuate(World world, String m) {
|
||||
for (World i : Bukkit.getWorlds()) {
|
||||
if (!i.getName().equals(world.getName())) {
|
||||
for (Player j : world.getPlayers()) {
|
||||
new VolmitSender(j, Iris.instance.getTag()).sendMessage("You have been evacuated from this world. " + m);
|
||||
j.teleport(i.getSpawnLocation());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
@ -1,288 +0,0 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.IrisSettings;
|
||||
import com.volmit.iris.core.project.loader.IrisData;
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.engine.framework.EngineCompound;
|
||||
import com.volmit.iris.engine.framework.EngineData;
|
||||
import com.volmit.iris.engine.framework.EngineTarget;
|
||||
import com.volmit.iris.engine.object.basic.IrisPosition;
|
||||
import com.volmit.iris.engine.object.common.IrisWorld;
|
||||
import com.volmit.iris.engine.object.dimensional.IrisDimension;
|
||||
import com.volmit.iris.engine.object.dimensional.IrisDimensionIndex;
|
||||
import com.volmit.iris.util.atomics.AtomicRollingSequence;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import com.volmit.iris.util.documentation.BlockCoordinates;
|
||||
import com.volmit.iris.util.documentation.ChunkCoordinates;
|
||||
import com.volmit.iris.util.format.C;
|
||||
import com.volmit.iris.util.format.Form;
|
||||
import com.volmit.iris.util.hunk.Hunk;
|
||||
import com.volmit.iris.util.parallel.MultiBurst;
|
||||
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.bukkit.block.Biome;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.world.WorldSaveEvent;
|
||||
import org.bukkit.generator.BlockPopulator;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
|
||||
public class IrisEngineCompound implements EngineCompound {
|
||||
@Getter
|
||||
private final IrisWorld world;
|
||||
|
||||
private final AtomicRollingSequence wallClock;
|
||||
|
||||
private Engine defaultEngine;
|
||||
|
||||
@Getter
|
||||
private final EngineData engineMetadata;
|
||||
|
||||
private final Engine[] engines;
|
||||
|
||||
@Getter
|
||||
private final MultiBurst burster;
|
||||
|
||||
@Getter
|
||||
private final KList<BlockPopulator> populators;
|
||||
|
||||
@Getter
|
||||
private final IrisDimension rootDimension;
|
||||
|
||||
@Getter
|
||||
private final int threadCount = -1;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
private boolean studio;
|
||||
|
||||
public IrisEngineCompound(IrisWorld world, IrisDimension rootDimension, IrisData data, int maximumThreads) {
|
||||
wallClock = new AtomicRollingSequence(32);
|
||||
this.rootDimension = rootDimension;
|
||||
Iris.info("Initializing Engine Composite for " + world.name());
|
||||
this.world = world;
|
||||
engineMetadata = EngineData.load(getEngineMetadataFile());
|
||||
engineMetadata.setDimension(rootDimension.getLoadKey());
|
||||
engineMetadata.setLastVersion(Iris.instance.getDescription().getVersion());
|
||||
|
||||
saveEngineMetadata();
|
||||
populators = new KList<>();
|
||||
|
||||
if (rootDimension.getDimensionalComposite().isEmpty()) {
|
||||
burster = null;
|
||||
// TODO: WARNING HEIGHT
|
||||
engines = new Engine[]{new IrisEngine(new EngineTarget(world, rootDimension, data, 256, maximumThreads), this, 0)};
|
||||
defaultEngine = engines[0];
|
||||
} else {
|
||||
double totalWeight = 0D;
|
||||
engines = new Engine[rootDimension.getDimensionalComposite().size()];
|
||||
burster = engines.length > 1 ? new MultiBurst("Iris Compound " + rootDimension.getName(), IrisSettings.get().getConcurrency().getEngineThreadPriority(), engines.length) : null;
|
||||
int threadDist = (Math.max(2, maximumThreads - engines.length)) / engines.length;
|
||||
|
||||
if ((threadDist * engines.length) + engines.length > maximumThreads) {
|
||||
Iris.warn("Using " + ((threadDist * engines.length) + engines.length) + " threads instead of the configured " + maximumThreads + " maximum thread count due to the requirements of this dimension!");
|
||||
}
|
||||
|
||||
for (IrisDimensionIndex i : rootDimension.getDimensionalComposite()) {
|
||||
totalWeight += i.getWeight();
|
||||
}
|
||||
|
||||
int buf = 0;
|
||||
|
||||
for (int i = 0; i < engines.length; i++) {
|
||||
IrisDimensionIndex index = rootDimension.getDimensionalComposite().get(i);
|
||||
IrisDimension dimension = data.getDimensionLoader().load(index.getDimension());
|
||||
// TODO: WARNING HEIGHT
|
||||
engines[i] = new IrisEngine(new EngineTarget(world, dimension, data.copy(), (int) Math.floor(256D * (index.getWeight() / totalWeight)), index.isInverted(), threadDist), this, i);
|
||||
engines[i].setMinHeight(buf);
|
||||
buf += engines[i].getHeight();
|
||||
|
||||
if (index.isPrimary()) {
|
||||
defaultEngine = engines[i];
|
||||
}
|
||||
}
|
||||
|
||||
if (defaultEngine == null) {
|
||||
defaultEngine = engines[0];
|
||||
}
|
||||
}
|
||||
|
||||
for (Engine i : engines) {
|
||||
if (i instanceof BlockPopulator) {
|
||||
populators.add((BlockPopulator) i);
|
||||
}
|
||||
}
|
||||
|
||||
Iris.instance.registerListener(this);
|
||||
}
|
||||
|
||||
public List<IrisPosition> getStrongholdPositions() {
|
||||
return engineMetadata.getStrongholdPositions();
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void on(WorldSaveEvent e) {
|
||||
if (world != null && e.getWorld().equals(world)) {
|
||||
save();
|
||||
}
|
||||
}
|
||||
|
||||
public void printMetrics(CommandSender sender) {
|
||||
KMap<String, Double> totals = new KMap<>();
|
||||
KMap<String, Double> weights = new KMap<>();
|
||||
double masterWallClock = wallClock.getAverage();
|
||||
|
||||
for (int i = 0; i < getSize(); i++) {
|
||||
Engine e = getEngine(i);
|
||||
KMap<String, Double> timings = e.getMetrics().pull();
|
||||
double totalWeight = 0;
|
||||
double wallClock = e.getMetrics().getTotal().getAverage();
|
||||
|
||||
for (double j : timings.values()) {
|
||||
totalWeight += j;
|
||||
}
|
||||
|
||||
for (String j : timings.k()) {
|
||||
weights.put(e.getName() + "[" + e.getIndex() + "]." + j, (wallClock / totalWeight) * timings.get(j));
|
||||
}
|
||||
|
||||
totals.put(e.getName() + "[" + e.getIndex() + "]", wallClock);
|
||||
}
|
||||
|
||||
double mtotals = 0;
|
||||
|
||||
for (double i : totals.values()) {
|
||||
mtotals += i;
|
||||
}
|
||||
|
||||
for (String i : totals.k()) {
|
||||
totals.put(i, (masterWallClock / mtotals) * totals.get(i));
|
||||
}
|
||||
|
||||
double v = 0;
|
||||
|
||||
for (double i : weights.values()) {
|
||||
v += i;
|
||||
}
|
||||
|
||||
for (String i : weights.k()) {
|
||||
weights.put(i, weights.get(i) / v);
|
||||
}
|
||||
|
||||
sender.sendMessage("Total: " + C.BOLD + C.WHITE + Form.duration(masterWallClock, 0));
|
||||
|
||||
for (String i : totals.k()) {
|
||||
sender.sendMessage(" Engine " + C.UNDERLINE + C.GREEN + i + C.RESET + ": " + C.BOLD + C.WHITE + Form.duration(totals.get(i), 0));
|
||||
}
|
||||
|
||||
sender.sendMessage("Details: ");
|
||||
|
||||
for (String i : weights.sortKNumber().reverse()) {
|
||||
String befb = C.UNDERLINE + "" + C.GREEN + "" + i.split("\\Q[\\E")[0] + C.RESET + C.GRAY + "[";
|
||||
String num = C.GOLD + i.split("\\Q[\\E")[1].split("]")[0] + C.RESET + C.GRAY + "].";
|
||||
String afb = C.ITALIC + "" + C.AQUA + i.split("\\Q]\\E")[1].substring(1) + C.RESET + C.GRAY;
|
||||
|
||||
sender.sendMessage(" " + befb + num + afb + ": " + C.BOLD + C.WHITE + Form.pc(weights.get(i), 0));
|
||||
}
|
||||
}
|
||||
|
||||
private File getEngineMetadataFile() {
|
||||
return new File(world.worldFolder(), "iris/engine-metadata.json");
|
||||
}
|
||||
|
||||
@ChunkCoordinates
|
||||
@Override
|
||||
public void generate(int x, int z, Hunk<BlockData> blocks, Hunk<BlockData> postblocks, Hunk<Biome> biomes, boolean multicore) {
|
||||
recycle();
|
||||
PrecisionStopwatch p = PrecisionStopwatch.start();
|
||||
if (engines.length == 1 && !getEngine(0).getTarget().isInverted()) {
|
||||
engines[0].generate(x, z, blocks, biomes, multicore);
|
||||
} else {
|
||||
int i;
|
||||
int offset = 0;
|
||||
|
||||
for (i = 0; i < engines.length; i++) {
|
||||
Engine engine = engines[i];
|
||||
int doffset = offset;
|
||||
int height = engine.getTarget().getHeight();
|
||||
Hunk<BlockData> cblock = Hunk.newArrayHunk(16, height, 16);
|
||||
Hunk<Biome> cbiome = Hunk.newArrayHunk(16, height, 16);
|
||||
|
||||
if (engine.getTarget().isInverted()) {
|
||||
cblock = cblock.invertY();
|
||||
cbiome = cbiome.invertY();
|
||||
}
|
||||
|
||||
engine.generate(x, z, cblock, cbiome, multicore);
|
||||
blocks.insert(0, doffset, 0, cblock);
|
||||
biomes.insert(0, doffset, 0, cbiome);
|
||||
offset += height;
|
||||
}
|
||||
}
|
||||
|
||||
wallClock.put(p.getMilliseconds());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSize() {
|
||||
return engines.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Engine getEngine(int index) {
|
||||
return engines[index];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveEngineMetadata() {
|
||||
engineMetadata.save(getEngineMetadataFile());
|
||||
}
|
||||
|
||||
@BlockCoordinates
|
||||
@Override
|
||||
public IrisData getData(int height) {
|
||||
return getEngineForHeight(height).getData();
|
||||
}
|
||||
|
||||
//TODO: FAIL
|
||||
@Override
|
||||
public boolean isFailing() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Engine getDefaultEngine() {
|
||||
return defaultEngine;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hotload() {
|
||||
for (int i = 0; i < getSize(); i++) {
|
||||
getEngine(i).hotload();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,810 +0,0 @@
|
||||
/*
|
||||
* 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.framework;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.IrisSettings;
|
||||
import com.volmit.iris.core.nms.INMS;
|
||||
import com.volmit.iris.core.pregenerator.PregenListener;
|
||||
import com.volmit.iris.core.pregenerator.PregenTask;
|
||||
import com.volmit.iris.core.project.loader.IrisData;
|
||||
import com.volmit.iris.engine.IrisEngineCompound;
|
||||
import com.volmit.iris.engine.data.chunk.MCATerrainChunk;
|
||||
import com.volmit.iris.engine.data.chunk.TerrainChunk;
|
||||
import com.volmit.iris.engine.framework.headless.HeadlessGenerator;
|
||||
import com.volmit.iris.engine.object.basic.IrisPosition;
|
||||
import com.volmit.iris.engine.object.biome.IrisBiome;
|
||||
import com.volmit.iris.engine.object.common.IrisWorld;
|
||||
import com.volmit.iris.engine.object.dimensional.IrisDimension;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import com.volmit.iris.util.data.B;
|
||||
import com.volmit.iris.util.format.C;
|
||||
import com.volmit.iris.util.format.Form;
|
||||
import com.volmit.iris.util.hunk.Hunk;
|
||||
import com.volmit.iris.util.io.ReactiveFolder;
|
||||
import com.volmit.iris.util.math.M;
|
||||
import com.volmit.iris.util.nbt.mca.NBTWorld;
|
||||
import com.volmit.iris.util.nbt.tag.CompoundTag;
|
||||
import com.volmit.iris.util.parallel.BurstExecutor;
|
||||
import com.volmit.iris.util.parallel.MultiBurst;
|
||||
import com.volmit.iris.util.plugin.VolmitSender;
|
||||
import com.volmit.iris.util.reflect.V;
|
||||
import com.volmit.iris.util.scheduling.ChronoLatch;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
import com.volmit.iris.util.scheduling.Looper;
|
||||
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
|
||||
import io.netty.util.internal.ConcurrentSet;
|
||||
import lombok.Getter;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.block.Biome;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.generator.BlockPopulator;
|
||||
import org.bukkit.generator.ChunkGenerator;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
public class EngineCompositeGenerator extends ChunkGenerator implements IrisAccess {
|
||||
private static final BlockData ERROR_BLOCK = Material.RED_GLAZED_TERRACOTTA.createBlockData();
|
||||
private final AtomicReference<EngineCompound> compound = new AtomicReference<>();
|
||||
private final AtomicBoolean initialized;
|
||||
private final String dimensionQuery;
|
||||
private final boolean production;
|
||||
private final KList<BlockPopulator> populators;
|
||||
private long mst = 0;
|
||||
private HeadlessGenerator headlessGenerator;
|
||||
private NBTWorld nbtWorld;
|
||||
private int generated = 0;
|
||||
private int lgenerated = 0;
|
||||
private final ChronoLatch hotloadcd;
|
||||
@Getter
|
||||
private double generatedPerSecond = 0;
|
||||
private ReactiveFolder hotloader = null;
|
||||
private IrisWorld cworld = null;
|
||||
private final Looper ticker;
|
||||
private final Looper cleaner;
|
||||
private int hotloaderMisses = 0;
|
||||
private long lastHotloadTime = 100;
|
||||
|
||||
public EngineCompositeGenerator() {
|
||||
this(null, true);
|
||||
}
|
||||
|
||||
public EngineCompositeGenerator(String query, boolean production) {
|
||||
super();
|
||||
ticker = new Looper() {
|
||||
@Override
|
||||
protected long loop() {
|
||||
PrecisionStopwatch p = PrecisionStopwatch.start();
|
||||
if (!tickHotloader()) {
|
||||
hotloaderMisses++;
|
||||
} else {
|
||||
hotloaderMisses = 0;
|
||||
}
|
||||
lastHotloadTime += p.getMilliseconds();
|
||||
lastHotloadTime /= 2;
|
||||
|
||||
return 120 + (lastHotloadTime / 2) + Math.min(hotloaderMisses * 125, 1375);
|
||||
}
|
||||
};
|
||||
ticker.setPriority(Thread.MIN_PRIORITY);
|
||||
ticker.setName("Iris Project Manager");
|
||||
|
||||
cleaner = new Looper() {
|
||||
@Override
|
||||
protected long loop() {
|
||||
if (getComposite() != null) {
|
||||
getComposite().clean();
|
||||
}
|
||||
|
||||
return 10000;
|
||||
}
|
||||
};
|
||||
cleaner.setPriority(Thread.MIN_PRIORITY);
|
||||
cleaner.setName("Iris Parallax Manager");
|
||||
cleaner.start();
|
||||
|
||||
if (isStudio()) {
|
||||
ticker.start();
|
||||
}
|
||||
|
||||
hotloadcd = new ChronoLatch(3500);
|
||||
mst = M.ms();
|
||||
this.production = production;
|
||||
this.dimensionQuery = query;
|
||||
initialized = new AtomicBoolean(false);
|
||||
populators = new KList<BlockPopulator>().qadd(new BlockPopulator() {
|
||||
@Override
|
||||
public void populate(World world, Random random, Chunk chunk) {
|
||||
if (compound.get() != null) {
|
||||
for (BlockPopulator i : compound.get().getPopulators()) {
|
||||
i.populate(world, random, chunk);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hotload() {
|
||||
if (isStudio()) {
|
||||
Iris.proj.updateWorkspace();
|
||||
getData().dump();
|
||||
J.s(() -> {
|
||||
try {
|
||||
for (Player i : getTarget().getWorld().getPlayers()) {
|
||||
new VolmitSender(i, Iris.instance.getTag()).sendMessage("Dimension Hotloaded");
|
||||
i.playSound(i.getLocation(), Sound.BLOCK_COPPER_PLACE, 1f, 1.25f);
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
Iris.reportError(e);
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
getComposite().close();
|
||||
initialized.lazySet(false);
|
||||
|
||||
if (cworld != null) {
|
||||
initialize(cworld);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean tickHotloader() {
|
||||
if (getComposite() == null || isClosed()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!initialized.get()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
if (hotloader != null) {
|
||||
return hotloader.check();
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
Iris.reportError(e);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private synchronized IrisDimension getDimension(IrisWorld world) {
|
||||
String query = dimensionQuery;
|
||||
query = Iris.linkMultiverseCore.getWorldNameType(world.name(), query);
|
||||
|
||||
IrisDimension dim = null;
|
||||
|
||||
if (query == null) {
|
||||
File iris = new File(world.worldFolder(), "iris");
|
||||
|
||||
if (iris.exists() && iris.isDirectory()) {
|
||||
for (File i : iris.listFiles()) {
|
||||
// Look for v1 location
|
||||
if (i.isDirectory() && i.getName().equals("dimensions")) {
|
||||
for (File j : i.listFiles()) {
|
||||
if (j.isFile() && j.getName().endsWith(".json")) {
|
||||
query = j.getName().replaceAll("\\Q.json\\E", "");
|
||||
Iris.error("Found v1 install. Please create a new world, this will cause chunks to change in your existing iris worlds!");
|
||||
throw new RuntimeException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Look for v2 location
|
||||
else if (i.isFile() && i.getName().equals("engine-metadata.json")) {
|
||||
EngineData metadata = EngineData.load(i);
|
||||
query = metadata.getDimension();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (query == null) {
|
||||
Iris.error("Cannot find iris dimension data for world: " + world.name() + "! Assuming " + IrisSettings.get().getGenerator().getDefaultWorldType() + "!");
|
||||
query = IrisSettings.get().getGenerator().getDefaultWorldType();
|
||||
}
|
||||
|
||||
dim = IrisData.loadAnyDimension(query);
|
||||
|
||||
if (dim == null) {
|
||||
Iris.proj.downloadSearch(new VolmitSender(Bukkit.getConsoleSender(), Iris.instance.getTag()), query, false);
|
||||
dim = IrisData.loadAnyDimension(query);
|
||||
|
||||
if (dim == null) {
|
||||
throw new RuntimeException("Cannot find dimension: " + query);
|
||||
} else {
|
||||
Iris.info("Download pack: " + query);
|
||||
}
|
||||
}
|
||||
|
||||
if (production) {
|
||||
IrisDimension od = dim;
|
||||
dim = new IrisData(getDataFolder(world)).getDimensionLoader().load(od.getLoadKey());
|
||||
|
||||
if (dim == null) {
|
||||
Iris.info("Installing Iris pack " + od.getName() + " into world " + world.name() + "...");
|
||||
Iris.proj.installIntoWorld(new VolmitSender(Bukkit.getConsoleSender(), Iris.instance.getTag()), od.getLoadKey(), world.worldFolder());
|
||||
dim = new IrisData(getDataFolder(world)).getDimensionLoader().load(od.getLoadKey());
|
||||
|
||||
if (dim == null) {
|
||||
throw new RuntimeException("Cannot find dimension: " + query);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return dim;
|
||||
}
|
||||
|
||||
private synchronized IrisDimension getDimension(String world) {
|
||||
String query = dimensionQuery;
|
||||
IrisDimension dim = null;
|
||||
|
||||
if (query == null) {
|
||||
File iris = new File(world + "/iris");
|
||||
|
||||
if (iris.exists() && iris.isDirectory()) {
|
||||
for (File i : Objects.requireNonNull(iris.listFiles())) {
|
||||
// Look for v1 location
|
||||
if (i.isDirectory() && i.getName().equals("dimensions")) {
|
||||
for (File j : Objects.requireNonNull(i.listFiles())) {
|
||||
if (j.isFile() && j.getName().endsWith(".json")) {
|
||||
query = j.getName().replaceAll("\\Q.json\\E", "");
|
||||
Iris.error("Found v1 install. Please create a new world, this will cause chunks to change in your existing iris worlds!");
|
||||
throw new RuntimeException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Look for v2 location
|
||||
else if (i.isFile() && i.getName().equals("engine-metadata.json")) {
|
||||
EngineData metadata = EngineData.load(i);
|
||||
query = metadata.getDimension();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (query == null) {
|
||||
Iris.error("Cannot find iris dimension data for world: " + world + "! Assuming " + IrisSettings.get().getGenerator().getDefaultWorldType() + "!");
|
||||
query = IrisSettings.get().getGenerator().getDefaultWorldType();
|
||||
}
|
||||
|
||||
dim = IrisData.loadAnyDimension(query);
|
||||
|
||||
if (dim == null) {
|
||||
Iris.proj.downloadSearch(new VolmitSender(Bukkit.getConsoleSender(), Iris.instance.getTag()), query, false);
|
||||
dim = IrisData.loadAnyDimension(query);
|
||||
|
||||
if (dim == null) {
|
||||
throw new RuntimeException("Cannot find dimension: " + query);
|
||||
} else {
|
||||
Iris.info("Download pack: " + query);
|
||||
}
|
||||
}
|
||||
|
||||
if (production) {
|
||||
IrisDimension od = dim;
|
||||
dim = new IrisData(getDataFolder(world)).getDimensionLoader().load(od.getLoadKey());
|
||||
|
||||
if (dim == null) {
|
||||
Iris.info("Installing Iris pack " + od.getName() + " into world " + world + "...");
|
||||
Iris.proj.installIntoWorld(new VolmitSender(Bukkit.getConsoleSender(), Iris.instance.getTag()), od.getLoadKey(), new File(world));
|
||||
dim = new IrisData(getDataFolder(world)).getDimensionLoader().load(od.getLoadKey());
|
||||
|
||||
if (dim == null) {
|
||||
throw new RuntimeException("Cannot find dimension: " + query);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Iris.info(world + " is configured to generate " + dim.getName() + "!");
|
||||
|
||||
return dim;
|
||||
}
|
||||
|
||||
public synchronized void initialize(IrisWorld world) {
|
||||
if (initialized.get()) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
initialized.set(true);
|
||||
IrisDimension dim = getDimension(world);
|
||||
IrisData data = production ? new IrisData(getDataFolder(world)) : dim.getLoader().copy();
|
||||
compound.set(new IrisEngineCompound(world, dim, data, IrisSettings.getThreadCount(IrisSettings.get().getConcurrency().getEngineThreadCount())));
|
||||
compound.get().setStudio(!production);
|
||||
populators.clear();
|
||||
populators.addAll(compound.get().getPopulators());
|
||||
hotloader = new ReactiveFolder(data.getDataFolder(), (a, c, d) -> hotload());
|
||||
cworld = world;
|
||||
|
||||
if (isStudio()) {
|
||||
dim.installDataPack(() -> data, Iris.instance.getDatapacksFolder());
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
Iris.reportError(e);
|
||||
e.printStackTrace();
|
||||
Iris.error("FAILED TO INITIALIZE DIMENSION FROM " + world.toString());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Place strongholds in the world
|
||||
*/
|
||||
public void placeStrongholds(World world) {
|
||||
EngineData metadata = getComposite().getEngineMetadata();
|
||||
// TODO: In nms class, not here. Also it doesnt work
|
||||
if (metadata.getStrongholdPositions() == null || metadata.getStrongholdPositions().size() == 0) {
|
||||
|
||||
List<IrisPosition> strongholds = new ArrayList<>();
|
||||
Object nmsWorld = new V(world).invoke("getHandle");
|
||||
Object chunkProvider = new V(nmsWorld).invoke("getChunkProvider");
|
||||
Object chunkGenerator = new V(chunkProvider).invoke("getChunkGenerator");
|
||||
try {
|
||||
Class<?> clazz = Class.forName("net.minecraft.world.level.chunk.ChunkGenerator");
|
||||
Class<?> clazzSG = Class.forName("net.minecraft.world.level.levelgen.feature.StructureGenerator");
|
||||
Class<?> clazzBP = Class.forName("net.minecraft.core.BlockPosition");
|
||||
@SuppressWarnings("rawtypes") Constructor bpCon = clazzBP.getConstructor(int.class, int.class, int.class);
|
||||
|
||||
//By default, we place 9 strongholds. One near 0,0 and 8 all around it at about 10_000 blocks out
|
||||
int[][] coords = {{0, 0}, {7000, -7000}, {10000, 0}, {7000, 7000}, {0, 10000}, {-7000, 7000}, {-10000, 0}, {-7000, -7000}, {0, -10000}};
|
||||
|
||||
//Set of stronghold locations so we don't place 2 strongholds at the same location
|
||||
Set<Long> existing = new ConcurrentSet<>();
|
||||
Set<CompletableFuture<Object>> futures = new HashSet<>();
|
||||
for (int[] currCoords : coords) {
|
||||
//Create a NMS BlockPosition
|
||||
Object blockPosToTest = bpCon.newInstance(currCoords[0], 0, currCoords[1]);
|
||||
//Create a CompletableFuture so we can track once the sync code is complete
|
||||
|
||||
CompletableFuture<Object> future = new CompletableFuture<>();
|
||||
futures.add(future);
|
||||
|
||||
//We have to run this code synchronously because it uses NMS
|
||||
J.s(() -> {
|
||||
try {
|
||||
Object o = getBP(clazz, clazzSG, clazzBP, nmsWorld, blockPosToTest, chunkGenerator);
|
||||
future.complete(o);
|
||||
} catch (Exception e) {
|
||||
Iris.reportError(e);
|
||||
e.printStackTrace();
|
||||
future.complete(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
CompletableFuture<Void> all = CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]));
|
||||
all.thenAccept((_void) -> { //Once all futures for all 9 strongholds have completed
|
||||
for (CompletableFuture<Object> future : futures) {
|
||||
try {
|
||||
Object pos = future.getNow(null);
|
||||
if (pos != null) {
|
||||
IrisPosition ipos = new IrisPosition((int) new V(pos, false).invoke("getX"), (int) new V(pos,
|
||||
false).invoke("getY"), (int) new V(pos, false).invoke("getZ"));
|
||||
long xz = (((long) ipos.getX()) << 32) | (ipos.getZ() & 0xffffffffL);
|
||||
if (existing.contains(xz)) return; //Make sure we don't double up on stronghold locs
|
||||
existing.add(xz);
|
||||
strongholds.add(ipos);
|
||||
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Iris.reportError(e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
StringBuilder positions = new StringBuilder();
|
||||
for (IrisPosition pos : strongholds) {
|
||||
positions.append("(").append(pos.getX()).append(",").append(pos.getY()).append(",").append(pos.getZ()).append(") ");
|
||||
}
|
||||
Iris.info("Strongholds (" + strongholds.size() + ") found at [" + positions + "]");
|
||||
|
||||
metadata.setStrongholdPositions(strongholds);
|
||||
getComposite().saveEngineMetadata();
|
||||
});
|
||||
|
||||
} catch (Exception e) {
|
||||
Iris.reportError(e);
|
||||
strongholds.add(new IrisPosition(1337, 32, -1337));
|
||||
metadata.setStrongholdPositions(strongholds);
|
||||
Iris.warn("Couldn't properly find the stronghold position for this world. Is this headless mode? Are you not using 1.16 or higher?");
|
||||
Iris.warn(" -> Setting default stronghold position");
|
||||
e.printStackTrace();
|
||||
StringBuilder positions = new StringBuilder();
|
||||
for (IrisPosition pos : strongholds) {
|
||||
positions.append("(").append(pos.getX()).append(",").append(pos.getY()).append(",").append(pos.getZ()).append(") ");
|
||||
}
|
||||
Iris.info("Strongholds (" + metadata.getStrongholdPositions().size() + ") found at [" + positions + "]");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get BlockPosition for nearest stronghold from the provided position
|
||||
*/
|
||||
private Object getBP(Class<?> clazz, Class<?> clazzSG, Class<?> clazzBP, Object nmsWorld, Object pos, Object chunkGenerator) throws NoSuchFieldException, NoSuchMethodException, IllegalAccessException, InvocationTargetException {
|
||||
final String stronghold = "k"; //1.17_01 mapping
|
||||
|
||||
Object structureGeneratorStronghold = clazzSG.getDeclaredField(stronghold).get(null);
|
||||
Method getNearestGeneratedFeature = clazz.getDeclaredMethod("findNearestMapFeature",
|
||||
nmsWorld.getClass(),
|
||||
clazzSG,
|
||||
clazzBP,
|
||||
int.class,
|
||||
boolean.class
|
||||
);
|
||||
return getNearestGeneratedFeature.invoke(chunkGenerator,
|
||||
nmsWorld,
|
||||
structureGeneratorStronghold,
|
||||
pos,
|
||||
100,
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
private File getDataFolder(IrisWorld world) {
|
||||
return new File(world.worldFolder(), "iris/pack");
|
||||
}
|
||||
|
||||
private File getDataFolder(String world) {
|
||||
return new File(world + "/iris/pack");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ChunkData generateChunkData(World world, Random ignored, int x, int z, BiomeGrid biome) {
|
||||
try {
|
||||
PrecisionStopwatch ps = PrecisionStopwatch.start();
|
||||
TerrainChunk tc = TerrainChunk.create(world, biome);
|
||||
IrisWorld ww = (getComposite() == null || getComposite().getWorld() == null) ? IrisWorld.fromWorld(world) : getComposite().getWorld();
|
||||
generateChunkRawData(ww, x, z, tc, true).run();
|
||||
|
||||
if (!getComposite().getWorld().hasRealWorld()) {
|
||||
getComposite().getWorld().bind(world);
|
||||
}
|
||||
|
||||
generated++;
|
||||
ps.end();
|
||||
|
||||
if (IrisSettings.get().getGeneral().isDebug()) {
|
||||
Iris.debug("Chunk " + C.GREEN + x + "," + z + C.LIGHT_PURPLE + " in " + C.YELLOW + Form.duration(ps.getMillis(), 2) + C.LIGHT_PURPLE + " Rate: " + C.BLUE + Form.f(getGeneratedPerSecond(), 0) + "/s");
|
||||
}
|
||||
|
||||
return tc.getRaw();
|
||||
} catch (Throwable e) {
|
||||
Iris.error("======================================");
|
||||
e.printStackTrace();
|
||||
Iris.reportErrorChunk(x, z, e, "CHUNK");
|
||||
Iris.error("======================================");
|
||||
|
||||
ChunkData d = Bukkit.createChunkData(world);
|
||||
|
||||
for (int i = 0; i < 16; i++) {
|
||||
for (int j = 0; j < 16; j++) {
|
||||
d.setBlock(i, 0, j, ERROR_BLOCK);
|
||||
}
|
||||
}
|
||||
|
||||
return d;
|
||||
}
|
||||
}
|
||||
|
||||
public void assignHeadlessGenerator(HeadlessGenerator headlessGenerator) {
|
||||
this.headlessGenerator = headlessGenerator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HeadlessGenerator getHeadlessGenerator() {
|
||||
return headlessGenerator;
|
||||
}
|
||||
|
||||
public void assignHeadlessNBTWriter(NBTWorld writer) {
|
||||
this.nbtWorld = writer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NBTWorld getHeadlessNBTWriter() {
|
||||
return nbtWorld;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void directWriteMCA(IrisWorld w, int x, int z, NBTWorld writer, MultiBurst burst) {
|
||||
directWriteMCA(w, x, z, writer, burst, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void directWriteMCA(IrisWorld w, int x, int z, NBTWorld writer, MultiBurst burst, PregenListener l) {
|
||||
BurstExecutor e = burst.burst(1024);
|
||||
|
||||
PregenTask.iterateRegion(x, z, (ii, jj) -> e.queue(() -> {
|
||||
if (l != null) {
|
||||
l.onChunkGenerating(ii, jj);
|
||||
}
|
||||
directWriteChunk(w, ii, jj, writer);
|
||||
if (l != null) {
|
||||
l.onChunkGenerated(ii, jj);
|
||||
}
|
||||
}));
|
||||
|
||||
e.complete();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void directWriteChunk(IrisWorld w, int x, int z, NBTWorld writer) {
|
||||
try {
|
||||
int ox = x << 4;
|
||||
int oz = z << 4;
|
||||
com.volmit.iris.util.nbt.mca.Chunk chunk = writer.getChunk(x, z);
|
||||
generateChunkRawData(w, x, z, MCATerrainChunk.builder()
|
||||
.writer(writer).ox(ox).oz(oz).mcaChunk(chunk)
|
||||
.minHeight(w.minHeight()).maxHeight(w.maxHeight())
|
||||
.injector((xx, yy, zz, biomeBase) -> chunk.setBiomeAt(ox + xx, yy, oz + zz,
|
||||
INMS.get().getTrueBiomeBaseId(biomeBase)))
|
||||
.build(), false).run();
|
||||
} catch (Throwable e) {
|
||||
Iris.error("======================================");
|
||||
e.printStackTrace();
|
||||
Iris.reportErrorChunk(x, z, e, "MCA");
|
||||
Iris.error("======================================");
|
||||
com.volmit.iris.util.nbt.mca.Chunk chunk = writer.getChunk(x, z);
|
||||
CompoundTag c = NBTWorld.getCompound(ERROR_BLOCK);
|
||||
for (int i = 0; i < 16; i++) {
|
||||
for (int j = 0; j < 16; j++) {
|
||||
chunk.setBlockStateAt(i, 0, j, c, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Runnable generateChunkRawData(IrisWorld world, int x, int z, TerrainChunk tc, boolean multicore) {
|
||||
initialize(world);
|
||||
tickMetrics();
|
||||
|
||||
Hunk<BlockData> blocks = Hunk.view((ChunkData) tc);
|
||||
Hunk<Biome> biomes = Hunk.view((BiomeGrid) tc);
|
||||
Hunk<BlockData> post = Hunk.newAtomicHunk(biomes.getWidth(), biomes.getHeight(), biomes.getDepth());
|
||||
compound.get().generate(x * 16, z * 16, blocks, post, biomes, multicore);
|
||||
|
||||
return () -> blocks.insertSoftly(0, 0, 0, post, (b) -> b == null || B.isAirOrFluid(b));
|
||||
}
|
||||
|
||||
private void tickMetrics() {
|
||||
if (M.ms() - mst > 1000) {
|
||||
generatedPerSecond = (double) (generated - lgenerated) / ((double) (M.ms() - mst) / 1000D);
|
||||
mst = M.ms();
|
||||
lgenerated = generated;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canSpawn(World world, int x, int z) {
|
||||
return super.canSpawn(world, x, z);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public List<BlockPopulator> getDefaultPopulators(World world) {
|
||||
return populators;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Location getFixedSpawnLocation(World world, Random random) {
|
||||
return super.getFixedSpawnLocation(world, random);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isParallelCapable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldGenerateCaves() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldGenerateDecorations() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldGenerateMobs() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldGenerateStructures() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public static EngineCompositeGenerator newStudioWorld(String dimension) {
|
||||
return new EngineCompositeGenerator(dimension, false);
|
||||
}
|
||||
|
||||
public static EngineCompositeGenerator newProductionWorld(String dimension) {
|
||||
return new EngineCompositeGenerator(dimension, true);
|
||||
}
|
||||
|
||||
public static EngineCompositeGenerator newProductionWorld() {
|
||||
return new EngineCompositeGenerator(null, true);
|
||||
}
|
||||
|
||||
public EngineCompound getComposite() {
|
||||
return compound.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public IrisBiome getBiome(int x, int z) {
|
||||
return getBiome(x, 0, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IrisBiome getCaveBiome(int x, int z) {
|
||||
return getCaveBiome(x, 0, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getGenerated() {
|
||||
return generated;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void printMetrics(CommandSender sender) {
|
||||
getComposite().printMetrics(sender);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IrisBiome getBiome(int x, int y, int z) {
|
||||
// TODO: REMOVE GET ABS BIOME OR THIS ONE
|
||||
return getEngineAccess(y).getBiome(x, y - getComposite().getEngineForHeight(y).getMinHeight(), z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IrisBiome getCaveBiome(int x, int y, int z) {
|
||||
return getEngineAccess(y).getCaveBiome(x, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public GeneratorAccess getEngineAccess(int y) {
|
||||
return getComposite().getEngineForHeight(y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IrisData getData() {
|
||||
if (getCompound() == null) {
|
||||
return null;
|
||||
}
|
||||
return getComposite().getData();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHeight(int x, int y, int z) {
|
||||
return getEngineAccess(y).getHeight(x, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getThreadCount() {
|
||||
return getComposite().getThreadCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void changeThreadCount(int m) {
|
||||
// TODO: DO IT
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
if (isStudio()) {
|
||||
ticker.interrupt();
|
||||
}
|
||||
|
||||
cleaner.interrupt();
|
||||
|
||||
if (getComposite() != null) {
|
||||
getComposite().close();
|
||||
|
||||
if (isStudio() && getComposite().getWorld().hasRealWorld()) {
|
||||
getComposite().getWorld().evacuate();
|
||||
Bukkit.unloadWorld(getComposite().getWorld().realWorld(), !isStudio());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isClosed() {
|
||||
try {
|
||||
return getComposite().getEngine(0).isClosed();
|
||||
} catch (Throwable e) {
|
||||
Iris.reportError(e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public EngineTarget getTarget() {
|
||||
try {
|
||||
return getComposite().getEngine(0).getTarget();
|
||||
} catch (NullPointerException e) {
|
||||
Iris.reportError(e);
|
||||
Iris.info("Failed to get composite engine. Please re-create the world in case you notice issues");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public EngineCompound getCompound() {
|
||||
return getComposite();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFailing() {
|
||||
if (getComposite() == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return getComposite().isFailing();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isStudio() {
|
||||
return !production;
|
||||
}
|
||||
|
||||
public boolean isVanillaCaves() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public KList<IrisBiome> getAllBiomes(String worldName) {
|
||||
if (getComposite() != null) {
|
||||
return getComposite().getAllBiomes();
|
||||
} else {
|
||||
KMap<String, IrisBiome> v = new KMap<>();
|
||||
IrisDimension dim = getDimension(worldName);
|
||||
dim.getAllAnyBiomes().forEach((i) -> v.put(i.getLoadKey(), i));
|
||||
|
||||
try {
|
||||
dim.getDimensionalComposite().forEach((m) -> IrisData.loadAnyDimension(m.getDimension()).getAllAnyBiomes().forEach((i) -> v.put(i.getLoadKey(), i)));
|
||||
} catch (Throwable ignored) {
|
||||
Iris.reportError(ignored);
|
||||
|
||||
}
|
||||
|
||||
Iris.info("Injecting " + v.size() + " biomes into the NMS World Chunk Provider (Iris)");
|
||||
|
||||
return v.v();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,169 +0,0 @@
|
||||
/*
|
||||
* 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.framework;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.project.loader.IrisData;
|
||||
import com.volmit.iris.engine.actuator.IrisTerrainNormalActuator;
|
||||
import com.volmit.iris.engine.object.basic.IrisPosition;
|
||||
import com.volmit.iris.engine.object.biome.IrisBiome;
|
||||
import com.volmit.iris.engine.object.common.IrisWorld;
|
||||
import com.volmit.iris.engine.object.dimensional.IrisDimension;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import com.volmit.iris.util.data.DataProvider;
|
||||
import com.volmit.iris.util.hunk.Hunk;
|
||||
import com.volmit.iris.util.parallel.MultiBurst;
|
||||
import org.bukkit.block.Biome;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.generator.BlockPopulator;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface EngineCompound extends Listener, Hotloadable, DataProvider {
|
||||
IrisDimension getRootDimension();
|
||||
|
||||
void generate(int x, int z, Hunk<BlockData> blocks, Hunk<BlockData> postblocks, Hunk<Biome> biomes, boolean multicore);
|
||||
|
||||
IrisWorld getWorld();
|
||||
|
||||
List<IrisPosition> getStrongholdPositions();
|
||||
|
||||
void printMetrics(CommandSender sender);
|
||||
|
||||
int getSize();
|
||||
|
||||
default int getHeight() {
|
||||
// TODO: WARNING HEIGHT
|
||||
return 256;
|
||||
}
|
||||
|
||||
Engine getEngine(int index);
|
||||
|
||||
MultiBurst getBurster();
|
||||
|
||||
EngineData getEngineMetadata();
|
||||
|
||||
void saveEngineMetadata();
|
||||
|
||||
KList<BlockPopulator> getPopulators();
|
||||
|
||||
default Engine getEngineForHeight(int height) {
|
||||
if (getSize() == 1) {
|
||||
return getEngine(0);
|
||||
}
|
||||
|
||||
int buf = 0;
|
||||
|
||||
for (int i = 0; i < getSize(); i++) {
|
||||
Engine e = getEngine(i);
|
||||
buf += e.getHeight();
|
||||
|
||||
if (buf >= height) {
|
||||
return e;
|
||||
}
|
||||
}
|
||||
|
||||
return getEngine(getSize() - 1);
|
||||
}
|
||||
|
||||
default void recycle() {
|
||||
for (int i = 0; i < getSize(); i++) {
|
||||
getEngine(i).recycle();
|
||||
}
|
||||
}
|
||||
|
||||
default void save() {
|
||||
saveEngineMetadata();
|
||||
for (int i = 0; i < getSize(); i++) {
|
||||
getEngine(i).save();
|
||||
}
|
||||
}
|
||||
|
||||
default void saveNOW() {
|
||||
saveEngineMetadata();
|
||||
for (int i = 0; i < getSize(); i++) {
|
||||
getEngine(i).saveNow();
|
||||
}
|
||||
}
|
||||
|
||||
IrisData getData(int height);
|
||||
|
||||
default IrisData getData() {
|
||||
return getData(0);
|
||||
}
|
||||
|
||||
default void close() {
|
||||
for (int i = 0; i < getSize(); i++) {
|
||||
getEngine(i).close();
|
||||
}
|
||||
}
|
||||
|
||||
boolean isFailing();
|
||||
|
||||
int getThreadCount();
|
||||
|
||||
boolean isStudio();
|
||||
|
||||
void setStudio(boolean std);
|
||||
|
||||
default void clean() {
|
||||
for (int i = 0; i < getSize(); i++) {
|
||||
getEngine(i).clean();
|
||||
}
|
||||
}
|
||||
|
||||
Engine getDefaultEngine();
|
||||
|
||||
default KList<IrisBiome> getAllBiomes() {
|
||||
KMap<String, IrisBiome> v = new KMap<>();
|
||||
|
||||
IrisDimension dim = getRootDimension();
|
||||
dim.getAllBiomes(this).forEach((i) -> v.put(i.getLoadKey(), i));
|
||||
|
||||
try {
|
||||
dim.getDimensionalComposite().forEach((m) -> getData().getDimensionLoader().load(m.getDimension()).getAllBiomes(this).forEach((i) -> v.put(i.getLoadKey(), i)));
|
||||
} catch (Throwable ignored) {
|
||||
Iris.reportError(ignored);
|
||||
|
||||
}
|
||||
|
||||
return v.v();
|
||||
}
|
||||
|
||||
default int getLowestBedrock() {
|
||||
int f = Integer.MAX_VALUE;
|
||||
|
||||
for (int i = 0; i < getSize(); i++) {
|
||||
Engine e = getEngine(i);
|
||||
|
||||
if (e.getDimension().isBedrock()) {
|
||||
int m = ((IrisTerrainNormalActuator) e.getTerrainActuator()).getLastBedrock();
|
||||
|
||||
if (f > m) {
|
||||
f = m;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return f;
|
||||
}
|
||||
}
|
@ -1,287 +0,0 @@
|
||||
/*
|
||||
* 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.framework;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.pregenerator.PregenListener;
|
||||
import com.volmit.iris.core.project.loader.IrisData;
|
||||
import com.volmit.iris.engine.framework.headless.HeadlessGenerator;
|
||||
import com.volmit.iris.engine.object.biome.IrisBiome;
|
||||
import com.volmit.iris.engine.object.common.IrisWorld;
|
||||
import com.volmit.iris.engine.object.regional.IrisRegion;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.data.DataProvider;
|
||||
import com.volmit.iris.util.math.M;
|
||||
import com.volmit.iris.util.math.RNG;
|
||||
import com.volmit.iris.util.nbt.mca.NBTWorld;
|
||||
import com.volmit.iris.util.parallel.MultiBurst;
|
||||
import com.volmit.iris.util.scheduling.ChronoLatch;
|
||||
import com.volmit.iris.util.scheduling.J;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@SuppressWarnings("EmptyMethod")
|
||||
public interface IrisAccess extends Hotloadable, DataProvider {
|
||||
|
||||
HeadlessGenerator getHeadlessGenerator();
|
||||
|
||||
default boolean isHeadless() {
|
||||
return getHeadlessGenerator() != null;
|
||||
}
|
||||
|
||||
NBTWorld getHeadlessNBTWriter();
|
||||
|
||||
void directWriteMCA(IrisWorld w, int x, int z, NBTWorld writer, MultiBurst burst);
|
||||
|
||||
void directWriteMCA(IrisWorld w, int x, int z, NBTWorld writer, MultiBurst burst, PregenListener listener);
|
||||
|
||||
void directWriteChunk(IrisWorld w, int x, int z, NBTWorld writer);
|
||||
|
||||
int getGenerated();
|
||||
|
||||
double getGeneratedPerSecond();
|
||||
|
||||
void printMetrics(CommandSender sender);
|
||||
|
||||
/**
|
||||
* Ignores the world, just uses the position
|
||||
*
|
||||
* @param l the location
|
||||
* @return the biome
|
||||
*/
|
||||
default IrisBiome getBiome(Location l) {
|
||||
return getBiome(l.toVector());
|
||||
}
|
||||
|
||||
default IrisRegion getRegion(int x, int y, int z) {
|
||||
return getEngineAccess(y).getRegion(x, z);
|
||||
}
|
||||
|
||||
default IrisRegion getRegion(Location l) {
|
||||
return getRegion(l.getBlockX(), l.getBlockY(), l.getBlockZ());
|
||||
}
|
||||
|
||||
default IrisBiome getBiome(Vector l) {
|
||||
return getBiome(l.getBlockX(), l.getBlockY(), l.getBlockZ());
|
||||
}
|
||||
|
||||
IrisBiome getBiome(int x, int y, int z);
|
||||
|
||||
IrisBiome getCaveBiome(int x, int y, int z);
|
||||
|
||||
IrisBiome getBiome(int x, int z);
|
||||
|
||||
IrisBiome getCaveBiome(int x, int z);
|
||||
|
||||
GeneratorAccess getEngineAccess(int y);
|
||||
|
||||
IrisData getData();
|
||||
|
||||
int getHeight(int x, int y, int z);
|
||||
|
||||
int getThreadCount();
|
||||
|
||||
void changeThreadCount(int m);
|
||||
|
||||
void close();
|
||||
|
||||
boolean isClosed();
|
||||
|
||||
EngineTarget getTarget();
|
||||
|
||||
EngineCompound getCompound();
|
||||
|
||||
boolean isFailing();
|
||||
|
||||
boolean isStudio();
|
||||
|
||||
default Location lookForBiome(IrisBiome biome, long timeout, Consumer<Integer> triesc) {
|
||||
if (!getCompound().getWorld().hasRealWorld()) {
|
||||
Iris.error("Cannot GOTO without a bound world (headless mode)");
|
||||
return null;
|
||||
}
|
||||
|
||||
ChronoLatch cl = new ChronoLatch(250, false);
|
||||
long s = M.ms();
|
||||
int cpus = (Runtime.getRuntime().availableProcessors());
|
||||
KList<Engine> engines = new KList<>();
|
||||
for (int i = 0; i < getCompound().getSize(); i++) {
|
||||
Engine e = getCompound().getEngine(i);
|
||||
if (e.getDimension().getAllBiomes(e).contains(biome)) {
|
||||
engines.add(e);
|
||||
}
|
||||
}
|
||||
|
||||
if (engines.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
AtomicInteger tries = new AtomicInteger(0);
|
||||
AtomicBoolean found = new AtomicBoolean(false);
|
||||
AtomicBoolean running = new AtomicBoolean(true);
|
||||
AtomicReference<Location> location = new AtomicReference<>();
|
||||
for (int i = 0; i < cpus; i++) {
|
||||
J.a(() -> {
|
||||
try {
|
||||
Engine e;
|
||||
IrisBiome b;
|
||||
int x, z;
|
||||
|
||||
while (!found.get() && running.get()) {
|
||||
try {
|
||||
synchronized (engines) {
|
||||
e = engines.getRandom();
|
||||
x = RNG.r.i(-29999970, 29999970);
|
||||
z = RNG.r.i(-29999970, 29999970);
|
||||
b = e.getSurfaceBiome(x, z);
|
||||
}
|
||||
|
||||
if (b != null && b.getLoadKey() == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (b != null && b.getLoadKey().equals(biome.getLoadKey())) {
|
||||
found.lazySet(true);
|
||||
location.lazySet(new Location(e.getWorld().realWorld(), x, e.getHeight(x, z), z));
|
||||
}
|
||||
|
||||
tries.getAndIncrement();
|
||||
} catch (Throwable ex) {
|
||||
Iris.reportError(ex);
|
||||
ex.printStackTrace();
|
||||
return;
|
||||
}
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
Iris.reportError(e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
while (!found.get() || location.get() == null) {
|
||||
J.sleep(50);
|
||||
|
||||
if (cl.flip()) {
|
||||
triesc.accept(tries.get());
|
||||
}
|
||||
|
||||
if (M.ms() - s > timeout) {
|
||||
running.set(false);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
running.set(false);
|
||||
return location.get();
|
||||
}
|
||||
|
||||
default Location lookForRegion(IrisRegion reg, long timeout, Consumer<Integer> triesc) {
|
||||
if (!getCompound().getWorld().hasRealWorld()) {
|
||||
Iris.error("Cannot GOTO without a bound world (headless mode)");
|
||||
return null;
|
||||
}
|
||||
|
||||
ChronoLatch cl = new ChronoLatch(3000, false);
|
||||
long s = M.ms();
|
||||
int cpus = (Runtime.getRuntime().availableProcessors());
|
||||
KList<Engine> engines = new KList<>();
|
||||
for (int i = 0; i < getCompound().getSize(); i++) {
|
||||
Engine e = getCompound().getEngine(i);
|
||||
if (e.getDimension().getRegions().contains(reg.getLoadKey())) {
|
||||
engines.add(e);
|
||||
}
|
||||
}
|
||||
|
||||
if (engines.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
AtomicInteger tries = new AtomicInteger(0);
|
||||
AtomicBoolean found = new AtomicBoolean(false);
|
||||
AtomicBoolean running = new AtomicBoolean(true);
|
||||
AtomicReference<Location> location = new AtomicReference<>();
|
||||
|
||||
for (int i = 0; i < cpus; i++) {
|
||||
J.a(() -> {
|
||||
Engine e;
|
||||
IrisRegion b;
|
||||
int x, z;
|
||||
|
||||
while (!found.get() && running.get()) {
|
||||
try {
|
||||
e = engines.getRandom();
|
||||
x = RNG.r.i(-29999970, 29999970);
|
||||
z = RNG.r.i(-29999970, 29999970);
|
||||
b = e.getRegion(x, z);
|
||||
|
||||
if (b != null && b.getLoadKey() != null && b.getLoadKey().equals(reg.getLoadKey())) {
|
||||
found.lazySet(true);
|
||||
location.lazySet(new Location(e.getWorld().realWorld(), x, e.getHeight(x, z) + e.getMinHeight(), z));
|
||||
}
|
||||
|
||||
tries.getAndIncrement();
|
||||
} catch (Throwable xe) {
|
||||
Iris.reportError(xe);
|
||||
xe.printStackTrace();
|
||||
return;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
while (!found.get() || location.get() != null) {
|
||||
J.sleep(50);
|
||||
|
||||
if (cl.flip()) {
|
||||
triesc.accept(tries.get());
|
||||
}
|
||||
|
||||
if (M.ms() - s > timeout) {
|
||||
triesc.accept(tries.get());
|
||||
running.set(false);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
triesc.accept(tries.get());
|
||||
running.set(false);
|
||||
return location.get();
|
||||
}
|
||||
|
||||
default int getParallaxChunkCount() {
|
||||
int v = 0;
|
||||
|
||||
for (int i = 0; i < getCompound().getSize(); i++) {
|
||||
v += getCompound().getEngine(i).getParallax().getChunkCount();
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
default double getHeight(Location l) {
|
||||
return getHeight(l.getBlockX(), l.getBlockY(), l.getBlockZ());
|
||||
}
|
||||
}
|
@ -1,93 +0,0 @@
|
||||
/*
|
||||
* 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.framework.headless;
|
||||
|
||||
import com.volmit.iris.core.IrisSettings;
|
||||
import com.volmit.iris.core.pregenerator.PregenListener;
|
||||
import com.volmit.iris.engine.framework.EngineCompositeGenerator;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import com.volmit.iris.util.math.Position2;
|
||||
import com.volmit.iris.util.nbt.mca.MCAUtil;
|
||||
import com.volmit.iris.util.nbt.mca.NBTWorld;
|
||||
import com.volmit.iris.util.parallel.MultiBurst;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
@Data
|
||||
public class HeadlessGenerator {
|
||||
private static KList<Position2> EMPTYPOINTS = new KList<>();
|
||||
private final HeadlessWorld world;
|
||||
private final EngineCompositeGenerator generator;
|
||||
private final NBTWorld writer;
|
||||
private final MultiBurst burst;
|
||||
|
||||
public HeadlessGenerator(HeadlessWorld world) {
|
||||
this.world = world;
|
||||
burst = new MultiBurst("Iris Headless Generator", 9, IrisSettings.getThreadCount(IrisSettings.get().getConcurrency().getPregenThreadCount()));
|
||||
writer = new NBTWorld(world.getWorld().worldFolder());
|
||||
generator = new EngineCompositeGenerator(world.getDimension().getLoadKey(), !world.isStudio());
|
||||
generator.assignHeadlessGenerator(this);
|
||||
generator.assignHeadlessNBTWriter(writer);
|
||||
generator.initialize(world.getWorld());
|
||||
}
|
||||
|
||||
public void generateChunk(int x, int z) {
|
||||
generator.directWriteChunk(world.getWorld(), x, z, writer);
|
||||
}
|
||||
|
||||
public void generateRegion(int x, int z) {
|
||||
generator.directWriteMCA(world.getWorld(), x, z, writer, burst);
|
||||
}
|
||||
|
||||
public void generateRegion(int x, int z, PregenListener listener) {
|
||||
generator.directWriteMCA(world.getWorld(), x, z, writer, burst, listener);
|
||||
}
|
||||
|
||||
public File generateRegionToFile(int x, int z, PregenListener listener) {
|
||||
generateRegionToFile(x, z, listener);
|
||||
flush();
|
||||
return writer.getRegionFile(x, z);
|
||||
}
|
||||
|
||||
public void flush() {
|
||||
writer.flushNow();
|
||||
}
|
||||
|
||||
public void save() {
|
||||
writer.save();
|
||||
}
|
||||
|
||||
public void close() {
|
||||
burst.shutdownAndAwait();
|
||||
generator.close();
|
||||
writer.close();
|
||||
}
|
||||
|
||||
public KList<Position2> getChunksInRegion(int x, int z) {
|
||||
try {
|
||||
return MCAUtil.sampleChunkPositions(writer.getRegionFile(x, z));
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return EMPTYPOINTS;
|
||||
}
|
||||
}
|
@ -1,88 +0,0 @@
|
||||
/*
|
||||
* 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.framework.headless;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.project.loader.IrisData;
|
||||
import com.volmit.iris.core.tools.IrisWorlds;
|
||||
import com.volmit.iris.engine.framework.EngineCompositeGenerator;
|
||||
import com.volmit.iris.engine.object.common.IrisWorld;
|
||||
import com.volmit.iris.engine.object.dimensional.IrisDimension;
|
||||
import com.volmit.iris.util.plugin.VolmitSender;
|
||||
import lombok.Data;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.WorldCreator;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
@Data
|
||||
@SuppressWarnings("ResultOfMethodCallIgnored")
|
||||
public class HeadlessWorld {
|
||||
private final IrisDimension dimension;
|
||||
private final String worldName;
|
||||
private final IrisWorld world;
|
||||
private boolean studio = false;
|
||||
|
||||
public HeadlessWorld(String worldName, IrisDimension dimension, long seed) {
|
||||
this(worldName, dimension, seed, false);
|
||||
}
|
||||
|
||||
public HeadlessWorld(String worldName, IrisDimension dimension, long seed, boolean studio) {
|
||||
this.worldName = worldName;
|
||||
this.dimension = dimension;
|
||||
this.studio = studio;
|
||||
world = IrisWorld.builder()
|
||||
.environment(dimension.getEnvironment())
|
||||
.worldFolder(new File(worldName))
|
||||
.seed(seed)
|
||||
.maxHeight(256)
|
||||
.minHeight(0)
|
||||
.name(worldName)
|
||||
.build();
|
||||
world.worldFolder().mkdirs();
|
||||
new File(world.worldFolder(), "region").mkdirs();
|
||||
|
||||
if (!studio && !new File(world.worldFolder(), "iris").exists()) {
|
||||
Iris.proj.installIntoWorld(new VolmitSender(Bukkit.getConsoleSender(), Iris.instance.getTag("Headless")), dimension.getLoadKey(), world.worldFolder());
|
||||
}
|
||||
}
|
||||
|
||||
public HeadlessGenerator generate() {
|
||||
return new HeadlessGenerator(this);
|
||||
}
|
||||
|
||||
public World load() {
|
||||
World w = new WorldCreator(worldName)
|
||||
.environment(dimension.getEnvironment())
|
||||
.seed(world.seed())
|
||||
.generator(new EngineCompositeGenerator(dimension.getLoadKey(), !studio))
|
||||
.createWorld();
|
||||
world.realWorld(w);
|
||||
return w;
|
||||
}
|
||||
|
||||
public static HeadlessWorld from(World world) {
|
||||
return new HeadlessWorld(world.getName(), IrisWorlds.access(world).getTarget().getDimension(), world.getSeed());
|
||||
}
|
||||
|
||||
public static HeadlessWorld from(String name, String dimension, long seed) {
|
||||
return new HeadlessWorld(name, IrisData.loadAnyDimension(dimension), seed);
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user