mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2026-04-02 22:06:17 +00:00
@@ -182,10 +182,14 @@ tasks {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val templateSource = file("src/main/templates")
|
val templateSource = file("src/main/templates")
|
||||||
val templateDest = layout.buildDirectory.dir("generated/sources/templates")
|
val templateDest = layout.buildDirectory.dir("generated/sources/templates")!!
|
||||||
val generateTemplates = tasks.register<Copy>("generateTemplates") {
|
val generateTemplates = tasks.register<Copy>("generateTemplates") {
|
||||||
inputs.properties(
|
inputs.properties(
|
||||||
"environment" to if (project.hasProperty("release")) "production" else "development",
|
"environment" to when {
|
||||||
|
project.hasProperty("release") -> "production"
|
||||||
|
project.hasProperty("argghh") -> "Argghh!"
|
||||||
|
else -> "development"
|
||||||
|
},
|
||||||
"commit" to provider {
|
"commit" to provider {
|
||||||
val res = runCatching { project.extensions.getByType<Grgit>().head().id }
|
val res = runCatching { project.extensions.getByType<Grgit>().head().id }
|
||||||
res.getOrDefault("")
|
res.getOrDefault("")
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ public class IrisData implements ExclusionStrategy, TypeAdapterFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void dereference() {
|
public static void dereference() {
|
||||||
dataLoaders.v().forEach(IrisData::cleanupEngine);
|
dataLoaders.values().forEach(IrisData::cleanupEngine);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int cacheSize() {
|
public static int cacheSize() {
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import com.volmit.iris.core.IrisSettings;
|
|||||||
import com.volmit.iris.core.link.Identifier;
|
import com.volmit.iris.core.link.Identifier;
|
||||||
import com.volmit.iris.core.loader.IrisData;
|
import com.volmit.iris.core.loader.IrisData;
|
||||||
import com.volmit.iris.core.service.ExternalDataSVC;
|
import com.volmit.iris.core.service.ExternalDataSVC;
|
||||||
|
import com.volmit.iris.engine.data.cache.Cache;
|
||||||
import com.volmit.iris.engine.framework.Engine;
|
import com.volmit.iris.engine.framework.Engine;
|
||||||
import com.volmit.iris.engine.framework.EngineAssignedWorldManager;
|
import com.volmit.iris.engine.framework.EngineAssignedWorldManager;
|
||||||
import com.volmit.iris.engine.object.*;
|
import com.volmit.iris.engine.object.*;
|
||||||
@@ -57,13 +58,10 @@ import org.bukkit.event.block.BlockPlaceEvent;
|
|||||||
import org.bukkit.event.player.PlayerTeleportEvent;
|
import org.bukkit.event.player.PlayerTeleportEvent;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
|
||||||
import java.lang.ref.WeakReference;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.*;
|
||||||
import java.util.concurrent.ExecutionException;
|
|
||||||
import java.util.concurrent.Future;
|
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
@@ -81,6 +79,8 @@ public class IrisWorldManager extends EngineAssignedWorldManager {
|
|||||||
private final ChronoLatch cln;
|
private final ChronoLatch cln;
|
||||||
private final ChronoLatch chunkUpdater;
|
private final ChronoLatch chunkUpdater;
|
||||||
private final ChronoLatch chunkDiscovery;
|
private final ChronoLatch chunkDiscovery;
|
||||||
|
private final KMap<Long, Future<?>> cleanup = new KMap<>();
|
||||||
|
private final ScheduledExecutorService cleanupService;
|
||||||
private double energy = 25;
|
private double energy = 25;
|
||||||
private int entityCount = 0;
|
private int entityCount = 0;
|
||||||
private long charge = 0;
|
private long charge = 0;
|
||||||
@@ -98,6 +98,7 @@ public class IrisWorldManager extends EngineAssignedWorldManager {
|
|||||||
looper = null;
|
looper = null;
|
||||||
chunkUpdater = null;
|
chunkUpdater = null;
|
||||||
chunkDiscovery = null;
|
chunkDiscovery = null;
|
||||||
|
cleanupService = null;
|
||||||
id = -1;
|
id = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -109,6 +110,11 @@ public class IrisWorldManager extends EngineAssignedWorldManager {
|
|||||||
cl = new ChronoLatch(3000);
|
cl = new ChronoLatch(3000);
|
||||||
ecl = new ChronoLatch(250);
|
ecl = new ChronoLatch(250);
|
||||||
clw = new ChronoLatch(1000, true);
|
clw = new ChronoLatch(1000, true);
|
||||||
|
cleanupService = Executors.newSingleThreadScheduledExecutor(runnable -> {
|
||||||
|
var thread = new Thread(runnable, "Iris Mantle Cleanup " + getTarget().getWorld().name());
|
||||||
|
thread.setPriority(Thread.MIN_PRIORITY);
|
||||||
|
return thread;
|
||||||
|
});
|
||||||
id = engine.getCacheID();
|
id = engine.getCacheID();
|
||||||
energy = 25;
|
energy = 25;
|
||||||
looper = new Looper() {
|
looper = new Looper() {
|
||||||
@@ -122,10 +128,6 @@ public class IrisWorldManager extends EngineAssignedWorldManager {
|
|||||||
getEngine().getWorld().tryGetRealWorld();
|
getEngine().getWorld().tryGetRealWorld();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IrisSettings.get().getWorld().isMarkerEntitySpawningSystem() && !IrisSettings.get().getWorld().isAnbientEntitySpawningSystem()) {
|
|
||||||
return 3000;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (getEngine().getWorld().hasRealWorld()) {
|
if (getEngine().getWorld().hasRealWorld()) {
|
||||||
if (getEngine().getWorld().getPlayers().isEmpty()) {
|
if (getEngine().getWorld().getPlayers().isEmpty()) {
|
||||||
return 5000;
|
return 5000;
|
||||||
@@ -139,6 +141,13 @@ public class IrisWorldManager extends EngineAssignedWorldManager {
|
|||||||
discoverChunks();
|
discoverChunks();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cln.flip()) {
|
||||||
|
engine.getEngineData().cleanup(getEngine());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!IrisSettings.get().getWorld().isMarkerEntitySpawningSystem() && !IrisSettings.get().getWorld().isAnbientEntitySpawningSystem()) {
|
||||||
|
return 3000;
|
||||||
|
}
|
||||||
|
|
||||||
if (getDimension().isInfiniteEnergy()) {
|
if (getDimension().isInfiniteEnergy()) {
|
||||||
energy += 1000;
|
energy += 1000;
|
||||||
@@ -150,10 +159,6 @@ public class IrisWorldManager extends EngineAssignedWorldManager {
|
|||||||
fixEnergy();
|
fixEnergy();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cln.flip()) {
|
|
||||||
engine.getEngineData().cleanup(getEngine());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (precount != null) {
|
if (precount != null) {
|
||||||
entityCount = 0;
|
entityCount = 0;
|
||||||
for (Entity i : precount) {
|
for (Entity i : precount) {
|
||||||
@@ -181,7 +186,7 @@ public class IrisWorldManager extends EngineAssignedWorldManager {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
looper.setPriority(Thread.MIN_PRIORITY);
|
looper.setPriority(Thread.MIN_PRIORITY);
|
||||||
looper.setName("Iris World Manager");
|
looper.setName("Iris World Manager " + getTarget().getWorld().name());
|
||||||
looper.start();
|
looper.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -425,16 +430,14 @@ public class IrisWorldManager extends EngineAssignedWorldManager {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var ref = new WeakReference<>(e.getWorld());
|
|
||||||
int cX = e.getX(), cZ = e.getZ();
|
int cX = e.getX(), cZ = e.getZ();
|
||||||
J.s(() -> {
|
Long key = Cache.key(e);
|
||||||
World world = ref.get();
|
cleanup.put(key, cleanupService.schedule(() -> {
|
||||||
if (world == null || !world.isChunkLoaded(cX, cZ))
|
cleanup.remove(key);
|
||||||
return;
|
|
||||||
energy += 0.3;
|
energy += 0.3;
|
||||||
fixEnergy();
|
fixEnergy();
|
||||||
getEngine().cleanupMantleChunk(cX, cZ);
|
getEngine().cleanupMantleChunk(cX, cZ);
|
||||||
}, IrisSettings.get().getPerformance().mantleCleanupDelay);
|
}, Math.max(IrisSettings.get().getPerformance().mantleCleanupDelay * 50L, 0), TimeUnit.MILLISECONDS));
|
||||||
|
|
||||||
if (generated) {
|
if (generated) {
|
||||||
//INMS.get().injectBiomesFromMantle(e, getMantle());
|
//INMS.get().injectBiomesFromMantle(e, getMantle());
|
||||||
@@ -458,6 +461,14 @@ public class IrisWorldManager extends EngineAssignedWorldManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onChunkUnload(Chunk e) {
|
||||||
|
final var future = cleanup.remove(Cache.key(e));
|
||||||
|
if (future != null) {
|
||||||
|
future.cancel(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void spawn(IrisPosition block, IrisSpawner spawner, boolean initial) {
|
private void spawn(IrisPosition block, IrisSpawner spawner, boolean initial) {
|
||||||
if (getEngine().isClosed()) {
|
if (getEngine().isClosed()) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -1000,7 +1000,7 @@ public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdat
|
|||||||
|
|
||||||
default void cleanupMantleChunk(int x, int z) {
|
default void cleanupMantleChunk(int x, int z) {
|
||||||
if (IrisSettings.get().getPerformance().isTrimMantleInStudio() || !isStudio()) {
|
if (IrisSettings.get().getPerformance().isTrimMantleInStudio() || !isStudio()) {
|
||||||
J.a(() -> getMantle().cleanupChunk(x, z));
|
getMantle().cleanupChunk(x, z);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ import org.bukkit.event.block.BlockBreakEvent;
|
|||||||
import org.bukkit.event.block.BlockPlaceEvent;
|
import org.bukkit.event.block.BlockPlaceEvent;
|
||||||
import org.bukkit.event.player.PlayerInteractEvent;
|
import org.bukkit.event.player.PlayerInteractEvent;
|
||||||
import org.bukkit.event.world.ChunkLoadEvent;
|
import org.bukkit.event.world.ChunkLoadEvent;
|
||||||
|
import org.bukkit.event.world.ChunkUnloadEvent;
|
||||||
import org.bukkit.event.world.WorldSaveEvent;
|
import org.bukkit.event.world.WorldSaveEvent;
|
||||||
import org.bukkit.event.world.WorldUnloadEvent;
|
import org.bukkit.event.world.WorldUnloadEvent;
|
||||||
import org.bukkit.inventory.EquipmentSlot;
|
import org.bukkit.inventory.EquipmentSlot;
|
||||||
@@ -125,6 +126,13 @@ public abstract class EngineAssignedWorldManager extends EngineAssignedComponent
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void on(ChunkUnloadEvent e) {
|
||||||
|
if (e.getChunk().getWorld().equals(getTarget().getWorld().realWorld())) {
|
||||||
|
onChunkUnload(e.getChunk());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void close() {
|
public void close() {
|
||||||
super.close();
|
super.close();
|
||||||
|
|||||||
@@ -45,6 +45,8 @@ public interface EngineWorldManager {
|
|||||||
|
|
||||||
void onChunkLoad(Chunk e, boolean generated);
|
void onChunkLoad(Chunk e, boolean generated);
|
||||||
|
|
||||||
|
void onChunkUnload(Chunk e);
|
||||||
|
|
||||||
void chargeEnergy();
|
void chargeEnergy();
|
||||||
|
|
||||||
void teleportAsync(PlayerTeleportEvent e);
|
void teleportAsync(PlayerTeleportEvent e);
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ import com.volmit.iris.util.matter.Matter;
|
|||||||
import com.volmit.iris.util.matter.MatterCavern;
|
import com.volmit.iris.util.matter.MatterCavern;
|
||||||
import com.volmit.iris.util.matter.TileWrapper;
|
import com.volmit.iris.util.matter.TileWrapper;
|
||||||
import com.volmit.iris.util.noise.CNG;
|
import com.volmit.iris.util.noise.CNG;
|
||||||
|
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import org.bukkit.block.data.BlockData;
|
import org.bukkit.block.data.BlockData;
|
||||||
import org.bukkit.util.Vector;
|
import org.bukkit.util.Vector;
|
||||||
@@ -62,7 +63,7 @@ public class MantleWriter implements IObjectPlacer, AutoCloseable {
|
|||||||
this.mantle = mantle;
|
this.mantle = mantle;
|
||||||
this.radius = radius * 2;
|
this.radius = radius * 2;
|
||||||
final int d = this.radius + 1;
|
final int d = this.radius + 1;
|
||||||
this.cachedChunks = multicore ? new KMap<>(d * d, 0.75f, Math.max(32, Runtime.getRuntime().availableProcessors() * 4)) : new HashMap<>(d * d);
|
this.cachedChunks = multicore ? new KMap<>(d * d, 0.75f, Math.max(32, Runtime.getRuntime().availableProcessors() * 4)) : new Long2ObjectOpenHashMap<>(d * d);
|
||||||
this.x = x;
|
this.x = x;
|
||||||
this.z = z;
|
this.z = z;
|
||||||
|
|
||||||
|
|||||||
@@ -63,14 +63,20 @@ public class IrisContext {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void dereference() {
|
public static synchronized void dereference() {
|
||||||
for (Thread i : context.k()) {
|
var it = context.entrySet().iterator();
|
||||||
if (!i.isAlive() || context.get(i).engine.isClosed()) {
|
while (it.hasNext()) {
|
||||||
if (context.get(i).engine.isClosed()) {
|
var entry = it.next();
|
||||||
Iris.debug("Dereferenced Context<Engine> " + i.getName() + " " + i.threadId());
|
var thread = entry.getKey();
|
||||||
}
|
var context = entry.getValue();
|
||||||
|
if (thread == null || context == null) {
|
||||||
|
it.remove();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
context.remove(i);
|
if (!thread.isAlive() || context.engine.isClosed()) {
|
||||||
|
Iris.debug("Dereferenced Context<Engine> " + thread.getName() + " " + thread.threadId());
|
||||||
|
it.remove();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,6 +24,10 @@ public class AtomicBooleanArray implements Serializable {
|
|||||||
AA.setVolatile(array, index, newValue);
|
AA.setVolatile(array, index, newValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final boolean getAndSet(int index, boolean newValue) {
|
||||||
|
return (boolean) AA.getAndSet(array, index, newValue);
|
||||||
|
}
|
||||||
|
|
||||||
public final boolean compareAndSet(int index, boolean expectedValue, boolean newValue) {
|
public final boolean compareAndSet(int index, boolean expectedValue, boolean newValue) {
|
||||||
return (boolean) AA.compareAndSet(array, index, expectedValue, newValue);
|
return (boolean) AA.compareAndSet(array, index, expectedValue, newValue);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,13 +27,21 @@ interface MatterGenerator {
|
|||||||
|
|
||||||
mantle.write(engine.mantle, x, z, radius, multicore).use { writer ->
|
mantle.write(engine.mantle, x, z, radius, multicore).use { writer ->
|
||||||
for (pair in components) {
|
for (pair in components) {
|
||||||
radius(x, z, pair.b) { x, z ->
|
runBlocking {
|
||||||
for (c in pair.a) {
|
radius(x, z, pair.b) { x, z ->
|
||||||
launch(multicore) {
|
val mc = writer.acquireChunk(x, z)
|
||||||
writer.acquireChunk(x, z)
|
if (mc.isFlagged(MantleFlag.PLANNED))
|
||||||
.raiseFlagSuspend(MantleFlag.PLANNED, c.flag) {
|
return@radius
|
||||||
|
|
||||||
|
for (c in pair.a) {
|
||||||
|
if (mc.isFlagged(c.flag))
|
||||||
|
continue
|
||||||
|
|
||||||
|
launch(multicore) {
|
||||||
|
mc.raiseFlagSuspend(c.flag) {
|
||||||
c.generateLayer(writer, x, z, context)
|
c.generateLayer(writer, x, z, context)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -46,7 +54,7 @@ interface MatterGenerator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private inline fun radius(x: Int, z: Int, radius: Int, crossinline task: suspend CoroutineScope.(Int, Int) -> Unit) = runBlocking {
|
private inline fun radius(x: Int, z: Int, radius: Int, crossinline task: (Int, Int) -> Unit) {
|
||||||
for (i in -radius..radius) {
|
for (i in -radius..radius) {
|
||||||
for (j in -radius..radius) {
|
for (j in -radius..radius) {
|
||||||
task(x + i, z + j)
|
task(x + i, z + j)
|
||||||
|
|||||||
@@ -49,19 +49,15 @@ abstract class FlaggedChunk() {
|
|||||||
flags.set(flag.ordinal(), value)
|
flags.set(flag.ordinal(), value)
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun raiseFlagSuspend(guard: MantleFlag?, flag: MantleFlag, task: suspend () -> Unit) {
|
suspend fun raiseFlagSuspend(flag: MantleFlag, task: suspend () -> Unit) {
|
||||||
if (isClosed()) throw IllegalStateException("Chunk is closed!")
|
if (isClosed()) throw IllegalStateException("Chunk is closed!")
|
||||||
if (guard != null && isFlagged(guard)) return
|
if (isFlagged(flag)) return
|
||||||
|
|
||||||
locks[flag.ordinal()].withLock {
|
locks[flag.ordinal()].withLock {
|
||||||
if (flags.compareAndSet(flag.ordinal(), false, true)) {
|
if (isFlagged(flag)) return
|
||||||
try {
|
task()
|
||||||
task()
|
if (flags.getAndSet(flag.ordinal(), true))
|
||||||
} catch (e: Throwable) {
|
throw IllegalStateException("Flag ${flag.name()} was already set after task ran!")
|
||||||
flags.set(flag.ordinal(), false)
|
|
||||||
throw e
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user