mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2026-06-17 14:21:33 +00:00
+1
-1
@@ -24,7 +24,7 @@ plugins {
|
|||||||
id "de.undercouch.download" version "5.0.1"
|
id "de.undercouch.download" version "5.0.1"
|
||||||
}
|
}
|
||||||
|
|
||||||
version '2.2.4-1.19' // Needs to be version specific
|
version '2.2.5-1.19' // Needs to be version specific
|
||||||
def nmsVersion = "1.19"
|
def nmsVersion = "1.19"
|
||||||
def apiVersion = '1.19'
|
def apiVersion = '1.19'
|
||||||
def spigotJarVersion = '1.19-R0.1-SNAPSHOT'
|
def spigotJarVersion = '1.19-R0.1-SNAPSHOT'
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import com.volmit.iris.core.ServerConfigurator;
|
|||||||
import com.volmit.iris.core.link.*;
|
import com.volmit.iris.core.link.*;
|
||||||
import com.volmit.iris.core.loader.IrisData;
|
import com.volmit.iris.core.loader.IrisData;
|
||||||
import com.volmit.iris.core.nms.INMS;
|
import com.volmit.iris.core.nms.INMS;
|
||||||
|
import com.volmit.iris.core.pregenerator.LazyPregenerator;
|
||||||
import com.volmit.iris.core.service.StudioSVC;
|
import com.volmit.iris.core.service.StudioSVC;
|
||||||
import com.volmit.iris.core.tools.IrisToolbelt;
|
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||||
import com.volmit.iris.engine.EnginePanic;
|
import com.volmit.iris.engine.EnginePanic;
|
||||||
@@ -404,6 +405,7 @@ public class Iris extends VolmitPlugin implements Listener {
|
|||||||
J.s(() -> {
|
J.s(() -> {
|
||||||
J.a(() -> PaperLib.suggestPaper(this));
|
J.a(() -> PaperLib.suggestPaper(this));
|
||||||
J.a(() -> IO.delete(getTemp()));
|
J.a(() -> IO.delete(getTemp()));
|
||||||
|
J.a(LazyPregenerator::loadLazyGenerators, 100);
|
||||||
J.a(this::bstats);
|
J.a(this::bstats);
|
||||||
J.ar(this::checkConfigHotload, 60);
|
J.ar(this::checkConfigHotload, 60);
|
||||||
J.sr(this::tickQueue, 0);
|
J.sr(this::tickQueue, 0);
|
||||||
|
|||||||
@@ -38,14 +38,16 @@ import com.volmit.iris.util.parallel.MultiBurst;
|
|||||||
import com.volmit.iris.util.plugin.VolmitSender;
|
import com.volmit.iris.util.plugin.VolmitSender;
|
||||||
import com.volmit.iris.util.scheduling.J;
|
import com.volmit.iris.util.scheduling.J;
|
||||||
import com.volmit.iris.util.scheduling.jobs.QueueJob;
|
import com.volmit.iris.util.scheduling.jobs.QueueJob;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.Chunk;
|
import org.bukkit.Chunk;
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.concurrent.Future;
|
import java.util.concurrent.Future;
|
||||||
|
|
||||||
@Decree(name = "iris", aliases = {"ir", "irs", "i"}, description = "Basic Command")
|
@Decree(name = "iris", aliases = {"ir", "irs"}, description = "Basic Command")
|
||||||
public class CommandIris implements DecreeExecutor {
|
public class CommandIris implements DecreeExecutor {
|
||||||
private CommandStudio studio;
|
private CommandStudio studio;
|
||||||
private CommandPregen pregen;
|
private CommandPregen pregen;
|
||||||
@@ -96,6 +98,37 @@ public class CommandIris implements DecreeExecutor {
|
|||||||
sender().sendMessage(C.GREEN + "Successfully created your world!");
|
sender().sendMessage(C.GREEN + "Successfully created your world!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Decree(description = "Remove an Iris world", aliases = {"del", "rm"}, sync = true)
|
||||||
|
public void remove(
|
||||||
|
@Param(description = "The world to remove")
|
||||||
|
World world,
|
||||||
|
@Param(description = "Whether to also remove the folder (if set to false, just does not load the world)", defaultValue = "true")
|
||||||
|
boolean delete
|
||||||
|
) {
|
||||||
|
if (!IrisToolbelt.isIrisWorld(world)) {
|
||||||
|
sender().sendMessage(C.RED + "This is not an Iris world. Iris worlds: " + String.join(", ", Bukkit.getServer().getWorlds().stream().filter(IrisToolbelt::isIrisWorld).map(World::getName).toList()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sender().sendMessage(C.GREEN + "Removing world: " + world.getName());
|
||||||
|
try {
|
||||||
|
if (IrisToolbelt.removeWorld(world)) {
|
||||||
|
sender().sendMessage(C.GREEN + "Successfully removed " + world.getName() + " from bukkit.yml");
|
||||||
|
} else {
|
||||||
|
sender().sendMessage(C.YELLOW + "Looks like the world was already removed from bukkit.yml");
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
sender().sendMessage(C.RED + "Failed to save bukkit.yml because of " + e.getMessage());
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
IrisToolbelt.evacuate(world, "Deleting world");
|
||||||
|
Bukkit.unloadWorld(world, false);
|
||||||
|
if (delete && world.getWorldFolder().delete()) {
|
||||||
|
sender().sendMessage(C.GREEN + "Successfully removed world folder");
|
||||||
|
} else {
|
||||||
|
sender().sendMessage(C.RED + "Failed to remove world folder");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Decree(description = "Print version information")
|
@Decree(description = "Print version information")
|
||||||
public void version() {
|
public void version() {
|
||||||
sender().sendMessage(C.GREEN + "Iris v" + Iris.instance.getDescription().getVersion() + " by Volmit Software");
|
sender().sendMessage(C.GREEN + "Iris v" + Iris.instance.getDescription().getVersion() + " by Volmit Software");
|
||||||
|
|||||||
@@ -83,7 +83,6 @@ public class PregeneratorJob implements PregenListener {
|
|||||||
this.pregenerator = new IrisPregenerator(task, method, this);
|
this.pregenerator = new IrisPregenerator(task, method, this);
|
||||||
max = new Position2(0, 0);
|
max = new Position2(0, 0);
|
||||||
min = new Position2(0, 0);
|
min = new Position2(0, 0);
|
||||||
KList<Runnable> draw = new KList<>();
|
|
||||||
task.iterateRegions((xx, zz) -> {
|
task.iterateRegions((xx, zz) -> {
|
||||||
min.setX(Math.min(xx << 5, min.getX()));
|
min.setX(Math.min(xx << 5, min.getX()));
|
||||||
min.setZ(Math.min(zz << 5, min.getZ()));
|
min.setZ(Math.min(zz << 5, min.getZ()));
|
||||||
|
|||||||
@@ -0,0 +1,178 @@
|
|||||||
|
package com.volmit.iris.core.pregenerator;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import com.volmit.iris.Iris;
|
||||||
|
import com.volmit.iris.util.format.Form;
|
||||||
|
import com.volmit.iris.util.io.IO;
|
||||||
|
import com.volmit.iris.util.math.Position2;
|
||||||
|
import com.volmit.iris.util.math.Spiraler;
|
||||||
|
import com.volmit.iris.util.scheduling.ChronoLatch;
|
||||||
|
import com.volmit.iris.util.scheduling.J;
|
||||||
|
import io.papermc.lib.PaperLib;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.World;
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.Listener;
|
||||||
|
import org.bukkit.event.world.WorldUnloadEvent;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
|
public class LazyPregenerator extends Thread implements Listener
|
||||||
|
{
|
||||||
|
private final LazyPregenJob job;
|
||||||
|
private final File destination;
|
||||||
|
private final int maxPosition;
|
||||||
|
private final World world;
|
||||||
|
private final long rate;
|
||||||
|
private final ChronoLatch latch;
|
||||||
|
|
||||||
|
public LazyPregenerator(LazyPregenJob job, File destination)
|
||||||
|
{
|
||||||
|
this.job = job;
|
||||||
|
this.destination = destination;
|
||||||
|
this.maxPosition = new Spiraler(job.getRadiusBlocks() * 2, job.getRadiusBlocks() * 2, (x, z) -> {}).count();
|
||||||
|
this.world = Bukkit.getWorld(job.getWorld());
|
||||||
|
this.rate = Math.round((1D / (job.chunksPerMinute / 60D)) * 1000D);
|
||||||
|
this.latch = new ChronoLatch(60000);
|
||||||
|
}
|
||||||
|
|
||||||
|
public LazyPregenerator(File file) throws IOException {
|
||||||
|
this(new Gson().fromJson(IO.readAll(file), LazyPregenJob.class), file);
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void on(WorldUnloadEvent e)
|
||||||
|
{
|
||||||
|
if(e.getWorld().equals(world)) {
|
||||||
|
interrupt();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void run()
|
||||||
|
{
|
||||||
|
while(!interrupted()) {
|
||||||
|
J.sleep(rate);
|
||||||
|
tick();
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
saveNow();
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void tick() {
|
||||||
|
if(latch.flip())
|
||||||
|
{
|
||||||
|
save();
|
||||||
|
Iris.info("LazyGen: " + world.getName() + " RTT: " + Form.duration((Math.pow((job.radiusBlocks / 16D), 2) / job.chunksPerMinute) * 60 * 1000, 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
if(job.getPosition() >= maxPosition)
|
||||||
|
{
|
||||||
|
if(job.isHealing())
|
||||||
|
{
|
||||||
|
int pos = (job.getHealingPosition() + 1) % maxPosition;
|
||||||
|
job.setHealingPosition(pos);
|
||||||
|
tickRegenerate(getChunk(pos));
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Iris.verbose("Completed Lazy Gen!");
|
||||||
|
interrupt();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int pos = job.getPosition() + 1;
|
||||||
|
job.setPosition(pos);
|
||||||
|
tickGenerate(getChunk(pos));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void tickGenerate(Position2 chunk) {
|
||||||
|
if(PaperLib.isPaper()) {
|
||||||
|
PaperLib.getChunkAtAsync(world, chunk.getX(), chunk.getZ(), true).thenAccept((i) -> Iris.verbose("Generated Async " + chunk));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
J.s(() -> world.getChunkAt(chunk.getX(), chunk.getZ()));
|
||||||
|
Iris.verbose("Generated " + chunk);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void tickRegenerate(Position2 chunk) {
|
||||||
|
J.s(() -> world.regenerateChunk(chunk.getX(), chunk.getZ()));
|
||||||
|
Iris.verbose("Regenerated " + chunk);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Position2 getChunk(int position)
|
||||||
|
{
|
||||||
|
int p = -1;
|
||||||
|
AtomicInteger xx = new AtomicInteger();
|
||||||
|
AtomicInteger zz = new AtomicInteger();
|
||||||
|
Spiraler s = new Spiraler(job.getRadiusBlocks() * 2, job.getRadiusBlocks() * 2, (x, z) -> {
|
||||||
|
xx.set(x);
|
||||||
|
zz.set(z);
|
||||||
|
});
|
||||||
|
|
||||||
|
while(s.hasNext() && p++ < position) {
|
||||||
|
s.next();
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Position2(xx.get(), zz.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void save()
|
||||||
|
{
|
||||||
|
J.a(() -> {
|
||||||
|
try {
|
||||||
|
saveNow();
|
||||||
|
}
|
||||||
|
|
||||||
|
catch (Throwable e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void saveNow() throws IOException {
|
||||||
|
IO.writeAll(this.destination, new Gson().toJson(job));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void loadLazyGenerators()
|
||||||
|
{
|
||||||
|
for(World i : Bukkit.getWorlds())
|
||||||
|
{
|
||||||
|
File lazygen = new File(i.getWorldFolder(), "lazygen.json");
|
||||||
|
|
||||||
|
if(lazygen.exists()) {
|
||||||
|
try {
|
||||||
|
LazyPregenerator p = new LazyPregenerator(lazygen);
|
||||||
|
p.start();
|
||||||
|
Iris.info("Started Lazy Pregenerator: " + p.job);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
public static class LazyPregenJob
|
||||||
|
{
|
||||||
|
private String world;
|
||||||
|
@Builder.Default private int healingPosition = 0;
|
||||||
|
@Builder.Default private boolean healing = false;
|
||||||
|
@Builder.Default private int chunksPerMinute = 32; // 48 hours is roughly 5000 radius
|
||||||
|
@Builder.Default private int radiusBlocks = 5000;
|
||||||
|
@Builder.Default private int position = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -231,4 +231,18 @@ public class IrisCreator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean removeFromBukkitYml(String name) throws IOException {
|
||||||
|
YamlConfiguration yml = YamlConfiguration.loadConfiguration(BUKKIT_YML);
|
||||||
|
ConfigurationSection section = yml.getConfigurationSection("worlds");
|
||||||
|
if (section == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
section.set(name, null);
|
||||||
|
if (section.getValues(false).keySet().stream().noneMatch(k -> section.get(k) != null)) {
|
||||||
|
yml.set("worlds", null);
|
||||||
|
}
|
||||||
|
yml.save(BUKKIT_YML);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ import org.bukkit.block.data.BlockData;
|
|||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@@ -221,7 +222,6 @@ public class IrisToolbelt {
|
|||||||
new VolmitSender(j, Iris.instance.getTag()).sendMessage("You have been evacuated from this world. " + m);
|
new VolmitSender(j, Iris.instance.getTag()).sendMessage("You have been evacuated from this world. " + m);
|
||||||
j.teleport(i.getSpawnLocation());
|
j.teleport(i.getSpawnLocation());
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -248,4 +248,8 @@ public class IrisToolbelt {
|
|||||||
if(e == null) {return;}
|
if(e == null) {return;}
|
||||||
e.getEngine().getMantle().getMantle().remove(x, y - world.getMinHeight(), z, of);
|
e.getEngine().getMantle().getMantle().remove(x, y - world.getMinHeight(), z, of);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean removeWorld(World world) throws IOException {
|
||||||
|
return IrisCreator.removeFromBukkitYml(world.getName());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ public class IrisSurfaceDecorator extends IrisEngineDecorator {
|
|||||||
bd = decorator.getBlockData100(biome, getRng(), realX, height, realZ, getData());
|
bd = decorator.getBlockData100(biome, getRng(), realX, height, realZ, getData());
|
||||||
|
|
||||||
if(!underwater) {
|
if(!underwater) {
|
||||||
if(!canGoOn(bd, bdx)) {
|
if(!canGoOn(bd, bdx) && !decorator.isForcePlace()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -72,8 +72,9 @@ public class IrisSurfaceDecorator extends IrisEngineDecorator {
|
|||||||
((Bisected) bd).setHalf(Bisected.Half.BOTTOM);
|
((Bisected) bd).setHalf(Bisected.Half.BOTTOM);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(decorator.getForceBlock() != null)
|
||||||
|
data.set(x, height, z, decorator.getForceBlock().getBlockData(getData()));
|
||||||
data.set(x, height + 1, z, bd);
|
data.set(x, height + 1, z, bd);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if(height < getDimension().getFluidHeight()) {
|
if(height < getDimension().getFluidHeight()) {
|
||||||
max = getDimension().getFluidHeight();
|
max = getDimension().getFluidHeight();
|
||||||
|
|||||||
@@ -53,6 +53,8 @@ public class IrisDecorator {
|
|||||||
private IrisGeneratorStyle variance = NoiseStyle.STATIC.style();
|
private IrisGeneratorStyle variance = NoiseStyle.STATIC.style();
|
||||||
@Desc("Forcefully place this decorant anywhere it is supposed to go even if it should not go on a specific surface block. For example, you could force tallgrass to place on top of stone by using this.")
|
@Desc("Forcefully place this decorant anywhere it is supposed to go even if it should not go on a specific surface block. For example, you could force tallgrass to place on top of stone by using this.")
|
||||||
private boolean forcePlace = false;
|
private boolean forcePlace = false;
|
||||||
|
@Desc("Forced the surface block of this decorant to be the specified block. Assumes forcePlace.")
|
||||||
|
private IrisBlockData forceBlock;
|
||||||
@DependsOn({"scaleStack", "stackMin", "stackMax"})
|
@DependsOn({"scaleStack", "stackMin", "stackMax"})
|
||||||
@Desc("If stackMax is set to true, use this to limit its max height for large caverns")
|
@Desc("If stackMax is set to true, use this to limit its max height for large caverns")
|
||||||
private int absoluteMaxStack = 30;
|
private int absoluteMaxStack = 30;
|
||||||
|
|||||||
@@ -799,7 +799,7 @@ public class IrisObject extends IrisRegistrant {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(config.isWaterloggable() && yy <= placer.getFluidHeight() && data instanceof Waterlogged) {
|
if((config.isWaterloggable() || config.isUnderwater()) && yy <= placer.getFluidHeight() && data instanceof Waterlogged) {
|
||||||
((Waterlogged) data).setWaterlogged(true);
|
((Waterlogged) data).setWaterlogged(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -849,6 +849,7 @@ public class IrisObject extends IrisRegistrant {
|
|||||||
BlockVector i = g.clone();
|
BlockVector i = g.clone();
|
||||||
i = config.getRotation().rotate(i.clone(), spinx, spiny, spinz).clone();
|
i = config.getRotation().rotate(i.clone(), spinx, spiny, spinz).clone();
|
||||||
i = config.getTranslate().translate(i.clone(), config.getRotation(), spinx, spiny, spinz).clone();
|
i = config.getTranslate().translate(i.clone(), config.getRotation(), spinx, spiny, spinz).clone();
|
||||||
|
d = config.getRotation().rotate(d, spinx, spiny, spinz);
|
||||||
|
|
||||||
if(i.getBlockY() != lowest)
|
if(i.getBlockY() != lowest)
|
||||||
continue;
|
continue;
|
||||||
@@ -882,7 +883,7 @@ public class IrisObject extends IrisRegistrant {
|
|||||||
|
|
||||||
int highest = placer.getHighest(xx, zz, getLoader(), true);
|
int highest = placer.getHighest(xx, zz, getLoader(), true);
|
||||||
|
|
||||||
if(config.isWaterloggable() && highest <= placer.getFluidHeight() && d instanceof Waterlogged)
|
if((config.isWaterloggable() || config.isUnderwater()) && highest <= placer.getFluidHeight() && d instanceof Waterlogged)
|
||||||
((Waterlogged) d).setWaterlogged(true);
|
((Waterlogged) d).setWaterlogged(true);
|
||||||
|
|
||||||
if(yv >= 0 && config.isBottom())
|
if(yv >= 0 && config.isBottom())
|
||||||
|
|||||||
@@ -75,4 +75,14 @@ public class Spiraler {
|
|||||||
z += dz;
|
z += dz;
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int count() {
|
||||||
|
int c = 0;
|
||||||
|
while(hasNext()) {
|
||||||
|
next();
|
||||||
|
c++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ libraries:
|
|||||||
- bsf:bsf:2.4.0
|
- bsf:bsf:2.4.0
|
||||||
commands:
|
commands:
|
||||||
iris:
|
iris:
|
||||||
aliases: [ ir, irs, i ]
|
aliases: [ ir, irs]
|
||||||
api-version: ${apiversion}
|
api-version: ${apiversion}
|
||||||
hotload-dependencies: false
|
hotload-dependencies: false
|
||||||
softdepend: [ "Oraxen", "ItemsAdder", "IrisFeller", "WorldEdit", "PlaceholderAPI"]
|
softdepend: [ "Oraxen", "ItemsAdder", "IrisFeller", "WorldEdit", "PlaceholderAPI"]
|
||||||
Reference in New Issue
Block a user