This commit is contained in:
Brian Neumann-Fopiano
2026-07-14 11:44:00 -04:00
parent 45230c0689
commit 55b7460b9a
4 changed files with 119 additions and 10 deletions
@@ -117,7 +117,7 @@ public class BlockSignal {
e.setTicksLived(1);
e.teleport(tg.clone());
e.setVelocity(new Vector(0, 0, 0));
})) {
}, 0, this::cancel)) {
cancel();
}
}
@@ -0,0 +1,82 @@
/*
* 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 art.arcane.iris.core.service;
import art.arcane.iris.util.common.plugin.IrisService;
import org.bukkit.NamespacedKey;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.world.EntitiesLoadEvent;
import org.bukkit.persistence.PersistentDataContainer;
import org.bukkit.persistence.PersistentDataType;
public class EntityRiseSVC implements IrisService {
private static final NamespacedKey RISE_STAMP = new NamespacedKey("iris", "rise_restore");
@Override
public void onEnable() {
}
@Override
public void onDisable() {
}
public static void stamp(Entity entity, boolean invulnerable, boolean ai, boolean collidable) {
byte flags = 0;
if (invulnerable) {
flags |= 1;
}
if (ai) {
flags |= 2;
}
if (collidable) {
flags |= 4;
}
entity.getPersistentDataContainer().set(RISE_STAMP, PersistentDataType.BYTE, flags);
}
public static void clearStamp(Entity entity) {
entity.getPersistentDataContainer().remove(RISE_STAMP);
}
@EventHandler(priority = EventPriority.MONITOR)
public void on(EntitiesLoadEvent e) {
for (Entity entity : e.getEntities()) {
restoreStranded(entity);
}
}
private static void restoreStranded(Entity entity) {
PersistentDataContainer container = entity.getPersistentDataContainer();
Byte flags = container.get(RISE_STAMP, PersistentDataType.BYTE);
if (flags == null) {
return;
}
container.remove(RISE_STAMP);
entity.setInvulnerable((flags & 1) != 0);
if (entity instanceof LivingEntity living) {
living.setAI((flags & 2) != 0);
living.setCollidable((flags & 4) != 0);
living.setNoDamageTicks(0);
}
}
}
@@ -22,6 +22,7 @@ import art.arcane.iris.spi.IrisServices;
import art.arcane.iris.core.IrisSettings;
import art.arcane.iris.core.link.Identifier;
import art.arcane.iris.core.loader.IrisRegistrant;
import art.arcane.iris.core.service.EntityRiseSVC;
import art.arcane.iris.core.service.ExternalDataSVC;
import art.arcane.iris.engine.framework.Engine;
import art.arcane.iris.engine.platform.EngineBukkitOps;
@@ -389,16 +390,18 @@ public class IrisEntity extends IrisRegistrant {
boolean originalAi = living.hasAI();
boolean originalCollidable = living.isCollidable();
int originalNoDamageTicks = living.getNoDamageTicks();
EntityRiseSVC.stamp(e, originalInvulnerable, originalAi, originalCollidable);
e.setInvulnerable(true);
living.setAI(false);
living.setCollidable(false);
living.setNoDamageTicks(100000);
Runnable restore = () -> restoreRiseState(e, living, originalInvulnerable, originalAi,
originalCollidable, originalNoDamageTicks);
AtomicInteger t = new AtomicInteger(0);
Runnable[] loop = new Runnable[1];
loop[0] = () -> {
if (t.get() > 100 || e.isDead()) {
restoreRiseState(e, living, originalInvulnerable, originalAi,
originalCollidable, originalNoDamageTicks);
restore.run();
return;
}
@@ -410,16 +413,16 @@ public class IrisEntity extends IrisRegistrant {
if (M.r(0.2)) {
e.getWorld().playSound(e.getLocation(), Sound.BLOCK_CHORUS_FLOWER_GROW, 0.8f, 0.1f);
}
if (!J.runEntity(e, loop[0], 1)) {
restoreRiseState(e, living, originalInvulnerable, originalAi,
originalCollidable, originalNoDamageTicks);
if (!J.runEntity(e, loop[0], 1, restore)) {
restore.run();
}
} else {
restoreRiseState(e, living, originalInvulnerable, originalAi,
originalCollidable, originalNoDamageTicks);
restore.run();
}
};
J.runEntity(e, loop[0]);
if (!J.runEntity(e, loop[0], 0, restore)) {
restore.run();
}
}
});
@@ -433,6 +436,7 @@ public class IrisEntity extends IrisRegistrant {
living.setCollidable(collidable);
living.setAI(ai);
entity.setInvulnerable(invulnerable);
EntityRiseSVC.clearStamp(entity);
}
private int surfaceY(Location l) {
@@ -498,7 +502,7 @@ public class IrisEntity extends IrisRegistrant {
private static final class BukkitOps {
private static void persistVillager(Villager villager) {
J.runEntity(villager, () -> villager.setPersistent(true), 1);
villager.setPersistent(true);
}
private static void bindLoot(IrisEntity entity, Engine gen, Lootable l, Location finalAt, RNG rng) {
@@ -258,6 +258,29 @@ public class J {
return true;
}
public static boolean runEntity(Entity entity, Runnable runnable, int delayTicks, Runnable retired) {
if (retired == null) {
return runEntity(entity, runnable, delayTicks);
}
if (entity == null || runnable == null) {
return false;
}
if (isFolia()) {
return FoliaScheduler.runEntity(BukkitPlatform.plugin(), entity, runnable, Math.max(0, delayTicks), retired);
}
Runnable guarded = () -> {
if (entity.isValid()) {
runnable.run();
} else {
retired.run();
}
};
return runEntity(entity, guarded, delayTicks);
}
public static boolean runRegion(World world, int chunkX, int chunkZ, Runnable runnable) {
if (world == null || runnable == null) {
return false;