mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2026-01-04 15:41:30 +00:00
Compare commits
35 Commits
2.3.0-1.19
...
2.3.2-1.19
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a248962f1b | ||
|
|
afa8fad8e9 | ||
|
|
4c423bb493 | ||
|
|
e660fe9e1e | ||
|
|
23c1d12e73 | ||
|
|
9cf2785626 | ||
|
|
b8b65c7e3e | ||
|
|
dcb467280a | ||
|
|
6aa802b42d | ||
|
|
d78f6ca589 | ||
|
|
493f8e0cc0 | ||
|
|
119563c553 | ||
|
|
2d61e6af66 | ||
|
|
aa1be934a9 | ||
|
|
f9c98b0a60 | ||
|
|
bd66fa3bf5 | ||
|
|
380f191f6a | ||
|
|
7e217b5fba | ||
|
|
c4a516a858 | ||
|
|
bdf181e348 | ||
|
|
f4ea1343b4 | ||
|
|
a37ccddd38 | ||
|
|
243ef8c0be | ||
|
|
00d099383b | ||
|
|
dda3f0b8e9 | ||
|
|
00f4d8b1ee | ||
|
|
2f5198d533 | ||
|
|
148261f876 | ||
|
|
60843b3bb9 | ||
|
|
2ad9a525bd | ||
|
|
78e9f21439 | ||
|
|
a66d60eaea | ||
|
|
3aa3c13477 | ||
|
|
cc850522e6 | ||
|
|
6d28f57f88 |
@@ -24,7 +24,7 @@ plugins {
|
||||
id "de.undercouch.download" version "5.0.1"
|
||||
}
|
||||
|
||||
version '2.2.19-1.19.2' // Needs to be version specific
|
||||
version '2.3.2-1.19.2' // Needs to be version specific
|
||||
def nmsVersion = "1.19.2" //[NMS]
|
||||
def apiVersion = '1.19'
|
||||
def specialSourceVersion = '1.11.0' //[NMS]
|
||||
|
||||
@@ -20,7 +20,6 @@ pluginManagement {
|
||||
mavenLocal()
|
||||
mavenCentral()
|
||||
gradlePluginPortal()
|
||||
maven { url "https://dl.cloudsmith.io/public/arcane/archive/maven/" }
|
||||
}
|
||||
}
|
||||
rootProject.name = 'Iris'
|
||||
@@ -23,7 +23,9 @@ import com.google.gson.JsonParseException;
|
||||
import com.google.gson.JsonParser;
|
||||
import com.volmit.iris.core.IrisSettings;
|
||||
import com.volmit.iris.core.ServerConfigurator;
|
||||
import com.volmit.iris.core.link.*;
|
||||
import com.volmit.iris.core.link.IrisPapiExpansion;
|
||||
import com.volmit.iris.core.link.MultiverseCoreLink;
|
||||
import com.volmit.iris.core.link.MythicMobsLink;
|
||||
import com.volmit.iris.core.loader.IrisData;
|
||||
import com.volmit.iris.core.nms.INMS;
|
||||
import com.volmit.iris.core.pregenerator.LazyPregenerator;
|
||||
@@ -41,7 +43,10 @@ import com.volmit.iris.util.exceptions.IrisException;
|
||||
import com.volmit.iris.util.format.C;
|
||||
import com.volmit.iris.util.format.Form;
|
||||
import com.volmit.iris.util.function.NastyRunnable;
|
||||
import com.volmit.iris.util.io.*;
|
||||
import com.volmit.iris.util.io.FileWatcher;
|
||||
import com.volmit.iris.util.io.IO;
|
||||
import com.volmit.iris.util.io.InstanceState;
|
||||
import com.volmit.iris.util.io.JarScanner;
|
||||
import com.volmit.iris.util.math.M;
|
||||
import com.volmit.iris.util.math.RNG;
|
||||
import com.volmit.iris.util.parallel.MultiBurst;
|
||||
@@ -56,11 +61,7 @@ import com.volmit.iris.util.scheduling.ShurikenQueue;
|
||||
import io.papermc.lib.PaperLib;
|
||||
import net.kyori.adventure.platform.bukkit.BukkitAudiences;
|
||||
import net.kyori.adventure.text.serializer.ComponentSerializer;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.WorldCreator;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
@@ -82,12 +83,11 @@ import java.lang.annotation.Annotation;
|
||||
import java.net.URL;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
@SuppressWarnings("CanBeFinal")
|
||||
public class Iris extends VolmitPlugin implements Listener {
|
||||
|
||||
public static final String OVERWORLD_TAG = "2086";
|
||||
public static final String OVERWORLD_TAG = "2087";
|
||||
|
||||
private static final Queue<Runnable> syncJobs = new ShurikenQueue<>();
|
||||
|
||||
|
||||
@@ -165,130 +165,6 @@ public class CommandStudio implements DecreeExecutor {
|
||||
}
|
||||
}
|
||||
|
||||
@Decree(description = "Clean an Iris Project, optionally beautifying JSON & fixing block ids with missing keys. Also rebuilds the vscode schemas. ")
|
||||
public void clean(
|
||||
@Param(description = "The project to update", contextual = true)
|
||||
IrisDimension project,
|
||||
|
||||
@Param(defaultValue = "true", description = "Filters all valid JSON files with a beautifier (indentation: 4)")
|
||||
boolean beautify,
|
||||
|
||||
@Param(name = "fix-ids", defaultValue = "true", description = "Fixes any block ids used such as \"dirt\" will be converted to \"minecraft:dirt\"")
|
||||
boolean fixIds,
|
||||
|
||||
@Param(name = "rewrite-objects", defaultValue = "false", description = "Imports all objects and re-writes them cleaning up positions & block data in the process.")
|
||||
boolean rewriteObjects
|
||||
) {
|
||||
KList<Job> jobs = new KList<>();
|
||||
KList<File> files = new KList<File>();
|
||||
files(Iris.instance.getDataFolder("packs", project.getLoadKey()), files);
|
||||
MultiBurst burst = MultiBurst.burst;
|
||||
|
||||
jobs.add(new SingleJob("Updating Workspace", () -> {
|
||||
if(!new IrisProject(Iris.service(StudioSVC.class).getWorkspaceFolder(project.getLoadKey())).updateWorkspace()) {
|
||||
sender().sendMessage(C.GOLD + "Invalid project: " + project.getLoadKey() + ". Try deleting the code-workspace file and try again.");
|
||||
}
|
||||
J.sleep(250);
|
||||
}));
|
||||
|
||||
sender().sendMessage("Files: " + files.size());
|
||||
|
||||
if(fixIds) {
|
||||
QueueJob<File> r = new QueueJob<>() {
|
||||
@Override
|
||||
public void execute(File f) {
|
||||
try {
|
||||
JSONObject p = new JSONObject(IO.readAll(f));
|
||||
fixBlocks(p);
|
||||
J.sleep(1);
|
||||
IO.writeAll(f, p.toString(4));
|
||||
|
||||
} catch(IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Fixing IDs";
|
||||
}
|
||||
};
|
||||
|
||||
r.queue(files);
|
||||
jobs.add(r);
|
||||
}
|
||||
|
||||
if(beautify) {
|
||||
QueueJob<File> r = new QueueJob<>() {
|
||||
@Override
|
||||
public void execute(File f) {
|
||||
try {
|
||||
JSONObject p = new JSONObject(IO.readAll(f));
|
||||
IO.writeAll(f, p.toString(4));
|
||||
J.sleep(1);
|
||||
} catch(IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Beautify";
|
||||
}
|
||||
};
|
||||
|
||||
r.queue(files);
|
||||
jobs.add(r);
|
||||
}
|
||||
|
||||
if(rewriteObjects) {
|
||||
QueueJob<Runnable> q = new QueueJob<>() {
|
||||
@Override
|
||||
public void execute(Runnable runnable) {
|
||||
runnable.run();
|
||||
J.sleep(50);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Rewriting Objects";
|
||||
}
|
||||
};
|
||||
|
||||
IrisData data = IrisData.get(Iris.service(StudioSVC.class).getWorkspaceFolder(project.getLoadKey()));
|
||||
for(String f : data.getObjectLoader().getPossibleKeys()) {
|
||||
Future<?> gg = burst.complete(() -> {
|
||||
File ff = data.getObjectLoader().findFile(f);
|
||||
IrisObject oo = new IrisObject(0, 0, 0);
|
||||
try {
|
||||
oo.read(ff);
|
||||
} catch(Throwable e) {
|
||||
Iris.error("FAILER TO READ: " + f);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
oo.write(ff);
|
||||
} catch(IOException e) {
|
||||
Iris.error("FAILURE TO WRITE: " + oo.getLoadFile());
|
||||
}
|
||||
});
|
||||
|
||||
q.queue(() -> {
|
||||
try {
|
||||
gg.get();
|
||||
} catch(InterruptedException | ExecutionException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
jobs.add(q);
|
||||
}
|
||||
|
||||
new JobCollection("Cleaning", jobs).execute(sender());
|
||||
}
|
||||
|
||||
@Decree(description = "Get the version of a pack")
|
||||
public void version(
|
||||
@Param(defaultValue = "default", description = "The dimension get the version of", aliases = "dim", contextual = true)
|
||||
|
||||
@@ -205,8 +205,7 @@ public class PregeneratorJob implements PregenListener {
|
||||
renderer.l = new ReentrantLock();
|
||||
renderer.frame = frame;
|
||||
renderer.job = this;
|
||||
renderer.func = (c, b) ->
|
||||
{
|
||||
renderer.func = (c, b) -> {
|
||||
renderer.l.lock();
|
||||
renderer.order.add(() -> renderer.draw(c, b, renderer.bg));
|
||||
renderer.l.unlock();
|
||||
@@ -238,10 +237,6 @@ public class PregeneratorJob implements PregenListener {
|
||||
|
||||
@Override
|
||||
public void onChunkGenerating(int x, int z) {
|
||||
if(engine != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
draw(x, z, COLOR_GENERATING);
|
||||
}
|
||||
|
||||
|
||||
@@ -18,9 +18,11 @@
|
||||
|
||||
package com.volmit.iris.core.nms;
|
||||
|
||||
import com.volmit.iris.util.mantle.Mantle;
|
||||
import com.volmit.iris.util.nbt.mca.palette.MCABiomeContainer;
|
||||
import com.volmit.iris.util.nbt.mca.palette.MCAPaletteAccess;
|
||||
import com.volmit.iris.util.nbt.tag.CompoundTag;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.WorldCreator;
|
||||
@@ -56,6 +58,8 @@ public interface INMSBinding {
|
||||
Object getCustomBiomeBaseFor(String mckey);
|
||||
Object getCustomBiomeBaseHolderFor(String mckey);
|
||||
|
||||
int getBiomeBaseIdForKey(String key);
|
||||
|
||||
String getKeyForBiomeBase(Object biomeBase);
|
||||
|
||||
Object getBiomeBase(World world, Biome biome);
|
||||
@@ -83,4 +87,6 @@ public interface INMSBinding {
|
||||
}
|
||||
|
||||
MCAPaletteAccess createPalette();
|
||||
|
||||
void injectBiomesFromMantle(Chunk e, Mantle mantle);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,155 @@
|
||||
package com.volmit.iris.core.nms.v19_2;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.engine.data.cache.AtomicCache;
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.engine.object.IrisBiome;
|
||||
import com.volmit.iris.engine.object.IrisBiomeCustom;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import com.volmit.iris.util.math.RNG;
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.core.RegistryAccess;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
import net.minecraft.world.level.biome.BiomeSource;
|
||||
import net.minecraft.world.level.biome.Climate;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.craftbukkit.v1_19_R1.CraftServer;
|
||||
import org.bukkit.craftbukkit.v1_19_R1.CraftWorld;
|
||||
import org.bukkit.craftbukkit.v1_19_R1.block.CraftBlock;
|
||||
import org.bukkit.craftbukkit.v1_19_R1.generator.CustomChunkGenerator;
|
||||
import org.bukkit.craftbukkit.v1_19_R1.generator.InternalChunkGenerator;
|
||||
import org.bukkit.generator.BiomeProvider;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class CustomBiomeSource extends BiomeSource {
|
||||
private final long seed;
|
||||
private final Engine engine;
|
||||
private final Registry<Biome> biomeCustomRegistry;
|
||||
private final Registry<Biome> biomeRegistry;
|
||||
private final AtomicCache<RegistryAccess> registryAccess = new AtomicCache<>();
|
||||
private final RNG rng;
|
||||
private final KMap<String, Holder<Biome>> customBiomes;
|
||||
|
||||
public CustomBiomeSource(long seed, Engine engine, World world) {
|
||||
super(getAllBiomes(
|
||||
((RegistryAccess) getFor(RegistryAccess.Frozen.class, ((CraftServer) Bukkit.getServer()).getHandle().getServer()))
|
||||
.registry(Registry.BIOME_REGISTRY).orElse(null),
|
||||
((CraftWorld) world).getHandle().registryAccess().registry(Registry.BIOME_REGISTRY).orElse(null),
|
||||
engine));
|
||||
this.engine = engine;
|
||||
this.seed = seed;
|
||||
this.biomeCustomRegistry = registry().registry(Registry.BIOME_REGISTRY).orElse(null);
|
||||
this.biomeRegistry = ((CraftWorld) world).getHandle().registryAccess().registry(Registry.BIOME_REGISTRY).orElse(null);
|
||||
this.rng = new RNG(engine.getSeedManager().getBiome());
|
||||
this.customBiomes = fillCustomBiomes(biomeCustomRegistry, engine);
|
||||
}
|
||||
|
||||
private KMap<String, Holder<Biome>> fillCustomBiomes(Registry<Biome> customRegistry, Engine engine) {
|
||||
KMap<String, Holder<Biome>> m = new KMap<>();
|
||||
|
||||
for(IrisBiome i : engine.getAllBiomes()) {
|
||||
if(i.isCustom()) {
|
||||
for(IrisBiomeCustom j : i.getCustomDerivitives()) {
|
||||
m.put(j.getId(), customRegistry.getHolder(customRegistry.getResourceKey(customRegistry
|
||||
.get(new ResourceLocation(engine.getDimension().getLoadKey() + ":" + j.getId()))).get()).get());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
private static List<Holder<Biome>> getAllBiomes(Registry<Biome> customRegistry, Registry<Biome> registry, Engine engine) {
|
||||
List<Holder<Biome>> b = new ArrayList<>();
|
||||
|
||||
for(IrisBiome i : engine.getAllBiomes()) {
|
||||
if(i.isCustom()) {
|
||||
for(IrisBiomeCustom j : i.getCustomDerivitives()) {
|
||||
b.add(customRegistry.getHolder(customRegistry.getResourceKey(customRegistry
|
||||
.get(new ResourceLocation(engine.getDimension().getLoadKey() + ":" + j.getId()))).get()).get());
|
||||
}
|
||||
} else {
|
||||
b.add(CraftBlock.biomeToBiomeBase(registry, i.getVanillaDerivative()));
|
||||
}
|
||||
}
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
private RegistryAccess registry() {
|
||||
return registryAccess.aquire(() -> (RegistryAccess) getFor(RegistryAccess.Frozen.class, ((CraftServer) Bukkit.getServer()).getHandle().getServer()));
|
||||
}
|
||||
|
||||
private static Object getFor(Class<?> type, Object source) {
|
||||
Object o = fieldFor(type, source);
|
||||
|
||||
if(o != null) {
|
||||
return o;
|
||||
}
|
||||
|
||||
return invokeFor(type, source);
|
||||
}
|
||||
|
||||
private static Object fieldFor(Class<?> returns, Object in) {
|
||||
return fieldForClass(returns, in.getClass(), in);
|
||||
}
|
||||
|
||||
|
||||
private static Object invokeFor(Class<?> returns, Object in) {
|
||||
for(Method i : in.getClass().getMethods()) {
|
||||
if(i.getReturnType().equals(returns)) {
|
||||
i.setAccessible(true);
|
||||
try {
|
||||
Iris.debug("[NMS] Found " + returns.getSimpleName() + " in " + in.getClass().getSimpleName() + "." + i.getName() + "()");
|
||||
return i.invoke(in);
|
||||
} catch(Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static <T> T fieldForClass(Class<T> returnType, Class<?> sourceType, Object in) {
|
||||
for(Field i : sourceType.getDeclaredFields()) {
|
||||
if(i.getType().equals(returnType)) {
|
||||
i.setAccessible(true);
|
||||
try {
|
||||
Iris.debug("[NMS] Found " + returnType.getSimpleName() + " in " + sourceType.getSimpleName() + "." + i.getName());
|
||||
return (T) i.get(in);
|
||||
} catch(IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Codec<? extends BiomeSource> codec() {
|
||||
throw new UnsupportedOperationException("Not supported");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Holder<Biome> getNoiseBiome(int x, int y, int z, Climate.Sampler sampler) {
|
||||
int m = (y - engine.getMinHeight()) << 2;
|
||||
IrisBiome ib = engine.getComplex().getTrueBiomeStream().get(x << 2, z << 2);
|
||||
if(ib.isCustom()) {
|
||||
return customBiomes.get(ib.getCustomBiome(rng, x << 2, m, z << 2).getId());
|
||||
} else {
|
||||
org.bukkit.block.Biome v = ib.getSkyBiome(rng, x << 2, m, z << 2);
|
||||
return CraftBlock.biomeToBiomeBase(biomeRegistry, v);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -23,6 +23,9 @@ import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.nms.INMSBinding;
|
||||
import com.volmit.iris.engine.data.cache.AtomicCache;
|
||||
import com.volmit.iris.util.collection.KMap;
|
||||
import com.volmit.iris.util.hunk.Hunk;
|
||||
import com.volmit.iris.util.mantle.Mantle;
|
||||
import com.volmit.iris.util.matter.MatterBiomeInject;
|
||||
import com.volmit.iris.util.nbt.io.NBTUtil;
|
||||
import com.volmit.iris.util.nbt.mca.NBTWorld;
|
||||
import com.volmit.iris.util.nbt.mca.palette.MCABiomeContainer;
|
||||
@@ -37,20 +40,20 @@ import com.volmit.iris.util.nbt.mca.palette.MCAWrappedPalettedContainer;
|
||||
import com.volmit.iris.util.nbt.tag.CompoundTag;
|
||||
import it.unimi.dsi.fastutil.objects.Object2IntMap;
|
||||
import net.minecraft.core.*;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.nbt.NbtIo;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
import net.minecraft.world.level.chunk.LevelChunk;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.block.Biome;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
|
||||
|
||||
import org.bukkit.craftbukkit.v1_19_R1.CraftChunk;
|
||||
import org.bukkit.craftbukkit.v1_19_R1.CraftServer;
|
||||
import org.bukkit.craftbukkit.v1_19_R1.CraftWorld;
|
||||
import org.bukkit.craftbukkit.v1_19_R1.block.data.CraftBlockData;
|
||||
@@ -161,23 +164,7 @@ public class NMSBinding19_2 implements INMSBinding {
|
||||
|
||||
@Override
|
||||
public Object getBiomeBaseFromId(int id) {
|
||||
try {
|
||||
return byIdRef.aquire(() -> {
|
||||
for(Method i : IdMap.class.getDeclaredMethods()) {
|
||||
if(i.getParameterCount() == 1 && i.getParameterTypes()[0].equals(int.class)) {
|
||||
Iris.info("[NMS] Found byId method in " + IdMap.class.getSimpleName() + "." + i.getName() + "(int) => " + Biome.class.getSimpleName());
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
Iris.error("Cannot find byId method!");
|
||||
return null;
|
||||
}).invoke(getCustomBiomeRegistry(), id);
|
||||
} catch(IllegalAccessException | InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return null;
|
||||
return getCustomBiomeRegistry().getHolder(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -192,7 +179,7 @@ public class NMSBinding19_2 implements INMSBinding {
|
||||
|
||||
@Override
|
||||
public int getTrueBiomeBaseId(Object biomeBase) {
|
||||
return getCustomBiomeRegistry().getId((net.minecraft.world.level.biome.Biome) biomeBase);
|
||||
return getCustomBiomeRegistry().getId(((Holder<net.minecraft.world.level.biome.Biome>) biomeBase).value());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -214,6 +201,10 @@ public class NMSBinding19_2 implements INMSBinding {
|
||||
return getCustomBiomeRegistry().getHolder(getTrueBiomeBaseId(getCustomBiomeRegistry().get(new ResourceLocation(mckey)))).get();
|
||||
}
|
||||
|
||||
public int getBiomeBaseIdForKey(String key) {
|
||||
return getCustomBiomeRegistry().getId(getCustomBiomeRegistry().get(new ResourceLocation(key)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getKeyForBiomeBase(Object biomeBase) {
|
||||
return getCustomBiomeRegistry().getKey((net.minecraft.world.level.biome.Biome) biomeBase).getPath(); // something, not something:something
|
||||
@@ -221,7 +212,8 @@ public class NMSBinding19_2 implements INMSBinding {
|
||||
|
||||
@Override
|
||||
public Object getBiomeBase(World world, Biome biome) {
|
||||
return getBiomeBase(((CraftWorld) world).getHandle().registryAccess().registry(Registry.BIOME_REGISTRY).orElse(null), biome);
|
||||
return org.bukkit.craftbukkit.v1_19_R1.block.CraftBlock.biomeToBiomeBase(((CraftWorld) world).getHandle()
|
||||
.registryAccess().registry(Registry.BIOME_REGISTRY).orElse(null), biome);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -333,6 +325,12 @@ public class NMSBinding19_2 implements INMSBinding {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void setBiomes(int cx, int cz, World world, Hunk<Object> biomes) {
|
||||
LevelChunk c = ((CraftWorld)world).getHandle().getChunk(cx, cz);
|
||||
biomes.iterateSync((x,y,z,b) -> c.setBiome(x, y, z, (Holder<net.minecraft.world.level.biome.Biome>)b));
|
||||
c.setUnsaved(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void forceBiomeInto(int x, int y, int z, Object somethingVeryDirty, ChunkGenerator.BiomeGrid chunk) {
|
||||
try {
|
||||
@@ -391,6 +389,26 @@ public class NMSBinding19_2 implements INMSBinding {
|
||||
i -> ((CraftBlockData) NBTWorld.getBlockData(i)).getState());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void injectBiomesFromMantle(Chunk e, Mantle mantle) {
|
||||
LevelChunk chunk = ((CraftChunk)e).getHandle();
|
||||
AtomicInteger c = new AtomicInteger();
|
||||
AtomicInteger r = new AtomicInteger();
|
||||
mantle.iterateChunk(e.getX(), e.getZ(), MatterBiomeInject.class, (x,y,z,b) -> {
|
||||
if(b != null) {
|
||||
if(b.isCustom()) {
|
||||
chunk.setBiome(x, y, z, getCustomBiomeRegistry().getHolder(b.getBiomeId()).get());
|
||||
c.getAndIncrement();
|
||||
}
|
||||
|
||||
else {
|
||||
chunk.setBiome(x, y, z, (Holder<net.minecraft.world.level.biome.Biome>) getBiomeBase(e.getWorld(), b.getBiome()));
|
||||
r.getAndIncrement();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static Object getFor(Class<?> type, Object source) {
|
||||
Object o = fieldFor(type, source);
|
||||
|
||||
|
||||
@@ -20,9 +20,11 @@ package com.volmit.iris.core.nms.v1X;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.nms.INMSBinding;
|
||||
import com.volmit.iris.util.mantle.Mantle;
|
||||
import com.volmit.iris.util.nbt.mca.palette.MCABiomeContainer;
|
||||
import com.volmit.iris.util.nbt.mca.palette.MCAPaletteAccess;
|
||||
import com.volmit.iris.util.nbt.tag.CompoundTag;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Biome;
|
||||
@@ -57,6 +59,11 @@ public class NMSBinding1X implements INMSBinding {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void injectBiomesFromMantle(Chunk e, Mantle mantle) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deserializeTile(CompoundTag s, Location newPosition) {
|
||||
|
||||
@@ -117,6 +124,11 @@ public class NMSBinding1X implements INMSBinding {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBiomeBaseIdForKey(String key) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getKeyForBiomeBase(Object biomeBase) {
|
||||
return null;
|
||||
|
||||
@@ -56,12 +56,11 @@ public class IrisPregenerator {
|
||||
private final KSet<Position2> retry;
|
||||
private final KSet<Position2> net;
|
||||
private final ChronoLatch cl;
|
||||
private final Semaphore limiter;
|
||||
private final ChronoLatch saveLatch = new ChronoLatch(30000);
|
||||
|
||||
public IrisPregenerator(PregenTask task, PregeneratorMethod generator, PregenListener listener) {
|
||||
this.listener = listenify(listener);
|
||||
cl = new ChronoLatch(5000);
|
||||
limiter = new Semaphore(Runtime.getRuntime().availableProcessors());
|
||||
generatedRegions = new KSet<>();
|
||||
this.shutdown = new AtomicBoolean(false);
|
||||
this.paused = new AtomicBoolean(false);
|
||||
@@ -166,32 +165,27 @@ public class IrisPregenerator {
|
||||
boolean hit = false;
|
||||
if(generator.supportsRegions(x, z, listener) && regions) {
|
||||
hit = true;
|
||||
try {
|
||||
limiter.acquire();
|
||||
listener.onRegionGenerating(x, z);
|
||||
generator.generateRegion(x, z, listener);
|
||||
limiter.release();
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
listener.onRegionGenerating(x, z);
|
||||
generator.generateRegion(x, z, listener);
|
||||
} else if(!regions) {
|
||||
hit = true;
|
||||
listener.onRegionGenerating(x, z);
|
||||
PregenTask.iterateRegion(x, z, (xx, zz) -> {
|
||||
try {
|
||||
limiter.acquire();
|
||||
generator.generateChunk(xx, zz, listener);
|
||||
limiter.release();
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
while(paused.get() && !shutdown.get()) {
|
||||
J.sleep(50);
|
||||
}
|
||||
});
|
||||
|
||||
generator.generateChunk(xx, zz, listener);});
|
||||
}
|
||||
|
||||
if(hit) {
|
||||
listener.onRegionGenerated(x, z);
|
||||
listener.onSaving();
|
||||
generator.save();
|
||||
|
||||
if(saveLatch.flip()) {
|
||||
listener.onSaving();
|
||||
generator.save();
|
||||
}
|
||||
|
||||
generatedRegions.add(pos);
|
||||
checkRegions();
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ public class PregenTask {
|
||||
}
|
||||
|
||||
public static void iterateRegion(int xr, int zr, Spiraled s) {
|
||||
iterateRegion(xr, zr, s, new Position2(0, 0));
|
||||
iterateRegion(xr, zr, s, new Position2(-(xr << 5), -(zr << 5)));
|
||||
}
|
||||
|
||||
private static KList<Position2> computeOrder(Position2 pull) {
|
||||
|
||||
@@ -31,6 +31,8 @@ import io.papermc.lib.PaperLib;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.World;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
public class AsyncPregenMethod implements PregeneratorMethod {
|
||||
@@ -68,18 +70,44 @@ public class AsyncPregenMethod implements PregeneratorMethod {
|
||||
|
||||
private void completeChunk(int x, int z, PregenListener listener) {
|
||||
try {
|
||||
PaperLib.getChunkAtAsync(world, x, z, true).get();
|
||||
listener.onChunkGenerated(x, z);
|
||||
listener.onChunkCleaned(x, z);
|
||||
future.add(PaperLib.getChunkAtAsync(world, x, z, true).thenApply((i) -> {
|
||||
if(i == null) {
|
||||
|
||||
}
|
||||
|
||||
listener.onChunkGenerated(x, z);
|
||||
listener.onChunkCleaned(x, z);
|
||||
return 0;
|
||||
}));
|
||||
} catch(Throwable e) {
|
||||
e.printStackTrace();
|
||||
J.sleep(5);
|
||||
future.add(burst.complete(() -> completeChunk(x, z, listener)));
|
||||
}
|
||||
}
|
||||
|
||||
private void waitForChunksPartial(int maxWaiting) {
|
||||
future.removeWhere(Objects::isNull);
|
||||
|
||||
while(future.size() > maxWaiting) {
|
||||
try {
|
||||
Future<?> i = future.remove(0);
|
||||
|
||||
if(i == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
i.get();
|
||||
} catch(Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void waitForChunks() {
|
||||
for(Future<?> i : future.copy()) {
|
||||
if(i == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
i.get();
|
||||
future.remove(i);
|
||||
@@ -87,6 +115,8 @@ public class AsyncPregenMethod implements PregeneratorMethod {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
future.removeWhere(Objects::isNull);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -107,7 +137,7 @@ public class AsyncPregenMethod implements PregeneratorMethod {
|
||||
|
||||
@Override
|
||||
public void save() {
|
||||
waitForChunks();
|
||||
waitForChunksPartial(256);
|
||||
unloadAndSaveAllChunks();
|
||||
}
|
||||
|
||||
@@ -123,11 +153,10 @@ public class AsyncPregenMethod implements PregeneratorMethod {
|
||||
|
||||
@Override
|
||||
public void generateChunk(int x, int z, PregenListener listener) {
|
||||
if(future.size() > IrisSettings.getThreadCount(IrisSettings.get().getConcurrency().getParallelism())) { // TODO: FIX
|
||||
waitForChunks();
|
||||
}
|
||||
|
||||
listener.onChunkGenerating(x, z);
|
||||
if(future.size() > 256) {
|
||||
waitForChunksPartial(256);
|
||||
}
|
||||
future.add(burst.complete(() -> completeChunk(x, z, listener)));
|
||||
}
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ public class StudioSVC implements IrisService {
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
J.a(() -> {
|
||||
J.s(() -> {
|
||||
String pack = IrisSettings.get().getGenerator().getDefaultWorldType();
|
||||
File f = IrisPack.packsPack(pack);
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ package com.volmit.iris.engine;
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.IrisSettings;
|
||||
import com.volmit.iris.core.loader.IrisData;
|
||||
import com.volmit.iris.core.nms.INMS;
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.engine.framework.EngineAssignedWorldManager;
|
||||
import com.volmit.iris.engine.object.*;
|
||||
@@ -31,14 +32,14 @@ import com.volmit.iris.util.format.Form;
|
||||
import com.volmit.iris.util.mantle.Mantle;
|
||||
import com.volmit.iris.util.mantle.MantleFlag;
|
||||
import com.volmit.iris.util.math.M;
|
||||
import com.volmit.iris.util.math.Position2;
|
||||
import com.volmit.iris.util.math.RNG;
|
||||
import com.volmit.iris.util.matter.MatterBiomeInject;
|
||||
import com.volmit.iris.util.matter.MatterMarker;
|
||||
import com.volmit.iris.util.parallel.MultiBurst;
|
||||
import com.volmit.iris.util.plugin.Chunks;
|
||||
import com.volmit.iris.util.plugin.VolmitSender;
|
||||
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.*;
|
||||
import com.volmit.iris.util.scheduling.jobs.QueueJob;
|
||||
import io.papermc.lib.PaperLib;
|
||||
import lombok.Data;
|
||||
@@ -81,6 +82,7 @@ public class IrisWorldManager extends EngineAssignedWorldManager {
|
||||
private int actuallySpawned = 0;
|
||||
private int cooldown = 0;
|
||||
private List<Entity> precount = new KList<>();
|
||||
private KSet<Position2> injectBiomes = new KSet<>();
|
||||
|
||||
public IrisWorldManager() {
|
||||
super(null);
|
||||
@@ -463,6 +465,10 @@ public class IrisWorldManager extends EngineAssignedWorldManager {
|
||||
getEngine().getMantle().save();
|
||||
}
|
||||
|
||||
public void requestBiomeInject(Position2 p) {
|
||||
injectBiomes.add(p);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChunkLoad(Chunk e, boolean generated) {
|
||||
if(getEngine().isClosed()) {
|
||||
@@ -472,6 +478,10 @@ public class IrisWorldManager extends EngineAssignedWorldManager {
|
||||
energy += 0.3;
|
||||
fixEnergy();
|
||||
getEngine().cleanupMantleChunk(e.getX(), e.getZ());
|
||||
|
||||
if(generated) {
|
||||
//INMS.get().injectBiomesFromMantle(e, getMantle());
|
||||
}
|
||||
}
|
||||
|
||||
private void spawn(IrisPosition block, IrisSpawner spawner, boolean initial) {
|
||||
|
||||
@@ -18,9 +18,7 @@
|
||||
|
||||
package com.volmit.iris.engine.actuator;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.nms.INMS;
|
||||
import com.volmit.iris.engine.data.chunk.TerrainChunk;
|
||||
import com.volmit.iris.engine.framework.Engine;
|
||||
import com.volmit.iris.engine.framework.EngineAssignedActuator;
|
||||
import com.volmit.iris.engine.object.IrisBiome;
|
||||
@@ -28,15 +26,12 @@ import com.volmit.iris.engine.object.IrisBiomeCustom;
|
||||
import com.volmit.iris.util.context.ChunkContext;
|
||||
import com.volmit.iris.util.documentation.BlockCoordinates;
|
||||
import com.volmit.iris.util.hunk.Hunk;
|
||||
import com.volmit.iris.util.hunk.view.BiomeGridHunkHolder;
|
||||
import com.volmit.iris.util.hunk.view.BiomeGridHunkView;
|
||||
import com.volmit.iris.util.math.RNG;
|
||||
import com.volmit.iris.util.parallel.BurstExecutor;
|
||||
import com.volmit.iris.util.matter.MatterBiomeInject;
|
||||
import com.volmit.iris.util.matter.slices.BiomeInjectMatter;
|
||||
import com.volmit.iris.util.scheduling.ChronoLatch;
|
||||
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
|
||||
import io.papermc.lib.PaperLib;
|
||||
import org.bukkit.block.Biome;
|
||||
import org.bukkit.generator.ChunkGenerator;
|
||||
|
||||
public class IrisBiomeActuator extends EngineAssignedActuator<Biome> {
|
||||
private final RNG rng;
|
||||
@@ -48,75 +43,34 @@ public class IrisBiomeActuator extends EngineAssignedActuator<Biome> {
|
||||
}
|
||||
|
||||
@BlockCoordinates
|
||||
private boolean injectBiome(Hunk<Biome> h, int x, int y, int z, Object bb) {
|
||||
@Override
|
||||
public void onActuate(int x, int z, Hunk<Biome> h, boolean multicore, ChunkContext context) {
|
||||
try {
|
||||
if(h instanceof BiomeGridHunkView hh) {
|
||||
ChunkGenerator.BiomeGrid g = hh.getChunk();
|
||||
if(g instanceof TerrainChunk) {
|
||||
((TerrainChunk) g).getBiomeBaseInjector().setBiome(x, y, z, bb);
|
||||
} else {
|
||||
hh.forceBiomeBaseInto(x, y, z, bb);
|
||||
PrecisionStopwatch p = PrecisionStopwatch.start();
|
||||
|
||||
int m = 0;
|
||||
for(int xf = 0; xf < h.getWidth(); xf++) {
|
||||
IrisBiome ib;
|
||||
for(int zf = 0; zf < h.getDepth(); zf++) {
|
||||
ib = context.getBiome().get(xf, zf);
|
||||
MatterBiomeInject matter = null;
|
||||
|
||||
if(ib.isCustom()) {
|
||||
IrisBiomeCustom custom = ib.getCustomBiome(rng, x, 0, z);
|
||||
matter = BiomeInjectMatter.get(INMS.get().getBiomeBaseIdForKey(getDimension().getLoadKey() + ":" + custom.getId()));
|
||||
} else {
|
||||
Biome v = ib.getSkyBiome(rng, x, 0, z);
|
||||
matter = BiomeInjectMatter.get(v);
|
||||
}
|
||||
|
||||
getEngine().getMantle().getMantle().set(x + xf, 0, z + zf, matter);
|
||||
m++;
|
||||
}
|
||||
return true;
|
||||
} else if(h instanceof BiomeGridHunkHolder hh) {
|
||||
ChunkGenerator.BiomeGrid g = hh.getChunk();
|
||||
if(g instanceof TerrainChunk) {
|
||||
((TerrainChunk) g).getBiomeBaseInjector().setBiome(x, y, z, bb);
|
||||
} else {
|
||||
hh.forceBiomeBaseInto(x, y, z, bb);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
getEngine().getMetrics().getBiome().put(p.getMilliseconds());
|
||||
} catch(Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@BlockCoordinates
|
||||
@Override
|
||||
public void onActuate(int x, int z, Hunk<Biome> h, boolean multicore, ChunkContext context) {
|
||||
PrecisionStopwatch p = PrecisionStopwatch.start();
|
||||
|
||||
for(int xf = 0; xf < h.getWidth(); xf++) {
|
||||
IrisBiome ib;
|
||||
for(int zf = 0; zf < h.getDepth(); zf++) {
|
||||
ib = context.getBiome().get(xf, zf);
|
||||
int maxHeight = (int) (getComplex().getFluidHeight() + ib.getMaxWithObjectHeight(getData()));
|
||||
if(ib.isCustom()) {
|
||||
try {
|
||||
IrisBiomeCustom custom = ib.getCustomBiome(rng, x, 0, z);
|
||||
Object biomeBase = INMS.get().getCustomBiomeBaseHolderFor(getDimension().getLoadKey() + ":" + custom.getId());
|
||||
|
||||
if(biomeBase == null || !injectBiome(h, x, 0, z, biomeBase)) {
|
||||
throw new RuntimeException("Cant inject biome!");
|
||||
}
|
||||
|
||||
for(int i = 0; i < maxHeight; i++) {
|
||||
injectBiome(h, xf, i, zf, biomeBase);
|
||||
}
|
||||
} catch(Throwable e) {
|
||||
Iris.reportError(e);
|
||||
Biome v = ib.getSkyBiome(rng, x, 0, z);
|
||||
for(int i = 0; i < maxHeight; i++) {
|
||||
h.set(xf, i, zf, v);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Biome v = ib.getSkyBiome(rng, x, 0, z);
|
||||
|
||||
if(v != null) {
|
||||
for(int i = 0; i < maxHeight; i++) {
|
||||
h.set(xf, i, zf, v);
|
||||
}
|
||||
} else if(cl.flip()) {
|
||||
Iris.error("No biome provided for " + ib.getLoadKey());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getEngine().getMetrics().getBiome().put(p.getMilliseconds());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ public class LinkedTerrainChunk implements TerrainChunk {
|
||||
private final BiomeGrid storage;
|
||||
private ChunkData rawChunkData;
|
||||
@Setter
|
||||
private boolean unsafe = false;
|
||||
private boolean unsafe = true;
|
||||
|
||||
public LinkedTerrainChunk(World world) {
|
||||
this(null, Bukkit.createChunkData(world));
|
||||
|
||||
@@ -77,8 +77,9 @@ public class IrisSurfaceDecorator extends IrisEngineDecorator {
|
||||
((Bisected) bd).setHalf(Bisected.Half.BOTTOM);
|
||||
}
|
||||
|
||||
data.set(x, height + 1, z, fixFaces(bd, x, height + 1, z));
|
||||
|
||||
if(!B.isAir(data.get(x, height + 1, z))) {
|
||||
data.set(x, height + 1, z, fixFaces(bd, x, height + 1, z));
|
||||
}
|
||||
} else {
|
||||
if(height < getDimension().getFluidHeight()) {
|
||||
max = getDimension().getFluidHeight();
|
||||
|
||||
@@ -513,7 +513,7 @@ public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdat
|
||||
|
||||
@BlockCoordinates
|
||||
default IrisBiome getBiome(Location l) {
|
||||
return getBiome(l.getBlockX(), l.getBlockY(), l.getBlockZ());
|
||||
return getBiome(l.getBlockX(), l.getBlockY() - getWorld().minHeight() , l.getBlockZ());
|
||||
}
|
||||
|
||||
@BlockCoordinates
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
package com.volmit.iris.engine.framework;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.IrisSettings;
|
||||
import com.volmit.iris.engine.object.IrisBiome;
|
||||
import com.volmit.iris.engine.object.IrisEffect;
|
||||
import com.volmit.iris.engine.object.IrisRegion;
|
||||
@@ -48,6 +49,9 @@ public class EnginePlayer {
|
||||
public void tick() {
|
||||
sample();
|
||||
|
||||
if(!IrisSettings.get().getWorld().isEffectSystem())
|
||||
return;
|
||||
|
||||
J.a(() -> {
|
||||
if(region != null) {
|
||||
for(IrisEffect j : region.getEffects()) {
|
||||
|
||||
@@ -52,7 +52,6 @@ public class ModeOverworld extends IrisEngineMode implements EngineMode {
|
||||
EngineStage sPerfection = (x, z, k, p, m, c) -> perfection.modify(x, z, k, m, c);
|
||||
|
||||
registerStage(burst(
|
||||
sBiome,
|
||||
sGenMatter,
|
||||
sTerrain
|
||||
));
|
||||
|
||||
@@ -32,6 +32,7 @@ import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.generator.WorldInfo;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Collection;
|
||||
@@ -109,6 +110,14 @@ public class IrisWorld {
|
||||
}
|
||||
}
|
||||
|
||||
public void bind(WorldInfo worldInfo) {
|
||||
name(worldInfo.getName())
|
||||
.worldFolder(new File(worldInfo.getName()))
|
||||
.minHeight(worldInfo.getMinHeight())
|
||||
.maxHeight(worldInfo.getMaxHeight())
|
||||
.environment(worldInfo.getEnvironment());
|
||||
}
|
||||
|
||||
public void bind(World world) {
|
||||
if(hasRealWorld()) {
|
||||
return;
|
||||
|
||||
@@ -20,6 +20,7 @@ package com.volmit.iris.engine.platform;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.core.loader.IrisData;
|
||||
import com.volmit.iris.core.nms.v19_2.CustomBiomeSource;
|
||||
import com.volmit.iris.core.service.StudioSVC;
|
||||
import com.volmit.iris.engine.IrisEngine;
|
||||
import com.volmit.iris.engine.data.chunk.TerrainChunk;
|
||||
@@ -44,37 +45,55 @@ import com.volmit.iris.util.stream.utility.ProfiledStream;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Setter;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.level.ServerLevelAccessor;
|
||||
import net.minecraft.world.level.WorldGenLevel;
|
||||
import org.apache.commons.lang3.reflect.FieldUtils;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.HeightMap;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Biome;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.craftbukkit.v1_19_R1.CraftServer;
|
||||
import org.bukkit.craftbukkit.v1_19_R1.CraftWorld;
|
||||
import org.bukkit.craftbukkit.v1_19_R1.generator.CustomChunkGenerator;
|
||||
import org.bukkit.craftbukkit.v1_19_R1.generator.InternalChunkGenerator;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.world.WorldInitEvent;
|
||||
import org.bukkit.generator.BiomeProvider;
|
||||
import org.bukkit.generator.BlockPopulator;
|
||||
import org.bukkit.generator.ChunkGenerator;
|
||||
import org.bukkit.generator.WorldInfo;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import sun.misc.Unsafe;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.Semaphore;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
public class BukkitChunkGenerator extends ChunkGenerator implements PlatformChunkGenerator {
|
||||
public class BukkitChunkGenerator extends ChunkGenerator implements PlatformChunkGenerator, Listener {
|
||||
private static final int LOAD_LOCKS = Runtime.getRuntime().availableProcessors() * 4;
|
||||
private final Semaphore loadLock;
|
||||
private final IrisWorld world;
|
||||
private final File dataLocation;
|
||||
private final String dimensionKey;
|
||||
private final ReactiveFolder folder;
|
||||
private final ReentrantLock lock = new ReentrantLock();
|
||||
private final KList<BlockPopulator> populators;
|
||||
private final ChronoLatch hotloadChecker;
|
||||
private final AtomicBoolean setup;
|
||||
@@ -98,6 +117,49 @@ public class BukkitChunkGenerator extends ChunkGenerator implements PlatformChun
|
||||
this.dataLocation = dataLocation;
|
||||
this.dimensionKey = dimensionKey;
|
||||
this.folder = new ReactiveFolder(dataLocation, (_a, _b, _c) -> hotload());
|
||||
Bukkit.getServer().getPluginManager().registerEvents(this, Iris.instance);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onWorldInit(WorldInitEvent event) {
|
||||
try {
|
||||
if(world.name().equals(event.getWorld().getName()) && world.getRawWorldSeed() == event.getWorld().getSeed()) {
|
||||
ServerLevel serverLevel = ((CraftWorld)event.getWorld()).getHandle();
|
||||
Engine engine = getEngine(event.getWorld());
|
||||
Class<?> clazz = serverLevel.getChunkSource().chunkMap.generator.getClass();
|
||||
Field biomeSource = getField(clazz, "c");
|
||||
biomeSource.setAccessible(true);
|
||||
Field unsafeField = Unsafe.class.getDeclaredField("theUnsafe");
|
||||
unsafeField.setAccessible(true);
|
||||
Unsafe unsafe = (Unsafe) unsafeField.get(null);
|
||||
CustomBiomeSource customBiomeSource = new CustomBiomeSource(event.getWorld().getSeed(), engine, event.getWorld());
|
||||
unsafe.putObject(biomeSource.get(serverLevel.getChunkSource().chunkMap.generator), unsafe.objectFieldOffset(biomeSource), customBiomeSource);
|
||||
biomeSource.set(serverLevel.getChunkSource().chunkMap.generator, customBiomeSource);
|
||||
Iris.info("Injected Iris Biome Source into " + event.getWorld().getName());
|
||||
}
|
||||
|
||||
else {
|
||||
Iris.info("World " + event.getWorld().getName() + " is not an Iris world in this context");
|
||||
}
|
||||
}
|
||||
|
||||
catch(Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private static Field getField(Class clazz, String fieldName)
|
||||
throws NoSuchFieldException {
|
||||
try {
|
||||
return clazz.getDeclaredField(fieldName);
|
||||
} catch (NoSuchFieldException e) {
|
||||
Class superClass = clazz.getSuperclass();
|
||||
if (superClass == null) {
|
||||
throw e;
|
||||
} else {
|
||||
return getField(superClass, fieldName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void setupEngine() {
|
||||
@@ -197,34 +259,41 @@ public class BukkitChunkGenerator extends ChunkGenerator implements PlatformChun
|
||||
}
|
||||
}
|
||||
|
||||
private Engine getEngine(World world) {
|
||||
private Engine getEngine(WorldInfo world) {
|
||||
if(setup.get()) {
|
||||
return getEngine();
|
||||
}
|
||||
|
||||
synchronized(this) {
|
||||
getWorld().setRawWorldSeed(world.getSeed());
|
||||
setupEngine();
|
||||
this.hotloader = studio ? new Looper() {
|
||||
@Override
|
||||
protected long loop() {
|
||||
if(hotloadChecker.flip()) {
|
||||
folder.check();
|
||||
}
|
||||
lock.lock();
|
||||
|
||||
return 250;
|
||||
}
|
||||
} : null;
|
||||
|
||||
if(studio) {
|
||||
hotloader.setPriority(Thread.MIN_PRIORITY);
|
||||
hotloader.start();
|
||||
hotloader.setName(getTarget().getWorld().name() + " Hotloader");
|
||||
}
|
||||
|
||||
setup.set(true);
|
||||
if(setup.get())
|
||||
{
|
||||
return getEngine();
|
||||
}
|
||||
|
||||
|
||||
setup.set(true);
|
||||
getWorld().setRawWorldSeed(world.getSeed());
|
||||
setupEngine();
|
||||
this.hotloader = studio ? new Looper() {
|
||||
@Override
|
||||
protected long loop() {
|
||||
if(hotloadChecker.flip()) {
|
||||
folder.check();
|
||||
}
|
||||
|
||||
return 250;
|
||||
}
|
||||
} : null;
|
||||
|
||||
if(studio) {
|
||||
hotloader.setPriority(Thread.MIN_PRIORITY);
|
||||
hotloader.start();
|
||||
hotloader.setName(getTarget().getWorld().name() + " Hotloader");
|
||||
}
|
||||
|
||||
lock.unlock();
|
||||
|
||||
return engine;
|
||||
}
|
||||
|
||||
@@ -273,46 +342,45 @@ public class BukkitChunkGenerator extends ChunkGenerator implements PlatformChun
|
||||
getEngine(world);
|
||||
}
|
||||
|
||||
private final AtomicInteger a = new AtomicInteger(0);
|
||||
|
||||
@Override
|
||||
public @NotNull ChunkData generateChunkData(@NotNull World world, @NotNull Random ignored, int x, int z, @NotNull BiomeGrid biome) {
|
||||
public void generateNoise(@NotNull WorldInfo world, @NotNull Random random, int x, int z, @NotNull ChunkGenerator.ChunkData d) {
|
||||
try {
|
||||
getEngine(world);
|
||||
computeStudioGenerator();
|
||||
TerrainChunk tc = TerrainChunk.create(world, biome);
|
||||
TerrainChunk tc = TerrainChunk.create(d, new IrisBiomeStorage());
|
||||
this.world.bind(world);
|
||||
|
||||
if(studioGenerator != null) {
|
||||
studioGenerator.generateChunk(getEngine(), tc, x, z);
|
||||
} else {
|
||||
ChunkDataHunkHolder blocks = new ChunkDataHunkHolder(tc);
|
||||
BiomeGridHunkHolder biomes = new BiomeGridHunkHolder(tc, tc.getMinHeight(), tc.getMaxHeight());
|
||||
getEngine().generate(x << 4, z << 4, blocks, biomes, true);
|
||||
getEngine().generate(x << 4, z << 4, blocks, biomes, false);
|
||||
blocks.apply();
|
||||
biomes.apply();
|
||||
}
|
||||
|
||||
ChunkData c = tc.getRaw();
|
||||
Iris.debug("Generated " + x + " " + z);
|
||||
|
||||
return c;
|
||||
} 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, Material.RED_GLAZED_TERRACOTTA.createBlockData());
|
||||
}
|
||||
}
|
||||
|
||||
return d;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBaseHeight(@NotNull WorldInfo worldInfo, @NotNull Random random, int x, int z, @NotNull HeightMap heightMap) {
|
||||
return 4;
|
||||
}
|
||||
|
||||
private void computeStudioGenerator() {
|
||||
if(!getEngine().getDimension().getStudioMode().equals(lastMode)) {
|
||||
lastMode = getEngine().getDimension().getStudioMode();
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.volmit.iris.engine.platform;
|
||||
|
||||
import org.bukkit.block.Biome;
|
||||
import org.bukkit.generator.ChunkGenerator;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class DummyBiomeGrid implements ChunkGenerator.BiomeGrid {
|
||||
@NotNull
|
||||
@Override
|
||||
public Biome getBiome(int x, int z) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Biome getBiome(int x, int y, int z) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBiome(int x, int z, @NotNull Biome bio) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBiome(int x, int y, int z, @NotNull Biome bio) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.volmit.iris.engine.platform;
|
||||
|
||||
import com.volmit.iris.Iris;
|
||||
import com.volmit.iris.util.collection.KList;
|
||||
import org.bukkit.block.Biome;
|
||||
import org.bukkit.generator.BiomeProvider;
|
||||
|
||||
@@ -568,7 +568,7 @@ public class Form {
|
||||
}
|
||||
|
||||
if(ms / 1000.0 / 60.0 / 60.0 / 24.0 < 7) {
|
||||
return Form.f(ms / 1000.0 / 60.0 / 24.0, prec) + " days";
|
||||
return Form.f(ms / 1000.0 / 60.0 / 60.0 / 24.0, prec) + " days";
|
||||
}
|
||||
|
||||
return Form.f(ms, prec) + "ms";
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 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.util.matter;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import org.bukkit.block.Biome;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
public class MatterBiomeInject {
|
||||
private final boolean custom;
|
||||
private final Integer biomeId;
|
||||
private final Biome biome;
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Bukkit Servers
|
||||
* Copyright (c) 2022 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.util.matter.slices;
|
||||
|
||||
import com.volmit.iris.util.data.palette.Palette;
|
||||
import com.volmit.iris.util.matter.MatterBiomeInject;
|
||||
import com.volmit.iris.util.matter.MatterCavern;
|
||||
import com.volmit.iris.util.matter.Sliced;
|
||||
import org.bukkit.block.Biome;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
@Sliced
|
||||
public class BiomeInjectMatter extends RawMatter<MatterBiomeInject> {
|
||||
public BiomeInjectMatter() {
|
||||
this(1, 1, 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Palette<MatterBiomeInject> getGlobalPalette() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public BiomeInjectMatter(int width, int height, int depth) {
|
||||
super(width, height, depth, MatterBiomeInject.class);
|
||||
}
|
||||
|
||||
public static MatterBiomeInject get(Biome biome)
|
||||
{
|
||||
return get(false, 0, biome);
|
||||
}
|
||||
|
||||
public static MatterBiomeInject get(int customBiome) {
|
||||
return get(true, customBiome, null);
|
||||
}
|
||||
|
||||
public static MatterBiomeInject get(boolean custom, int customBiome, Biome biome) {
|
||||
return new MatterBiomeInject(custom, customBiome, biome);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeNode(MatterBiomeInject b, DataOutputStream dos) throws IOException {
|
||||
dos.writeBoolean(b.isCustom());
|
||||
|
||||
if(b.isCustom()) {
|
||||
dos.writeShort(b.getBiomeId());
|
||||
}
|
||||
|
||||
else {
|
||||
dos.writeByte(b.getBiome().ordinal());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public MatterBiomeInject readNode(DataInputStream din) throws IOException {
|
||||
boolean b = din.readBoolean();
|
||||
int id = b ? din.readShort() : 0;
|
||||
Biome biome = !b ? Biome.values()[din.readByte()] : Biome.PLAINS;
|
||||
|
||||
return new MatterBiomeInject(b, id, biome);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user