mirror of
https://github.com/Artillex-Studios/AxMinions.git
synced 2024-11-26 12:15:57 +01:00
Tickers for folia and bukkit
This commit is contained in:
parent
05fb844b76
commit
39cf3051ea
@ -41,11 +41,11 @@ public final class AxMinionsCommand {
|
||||
.withPermission("axminions.command.debug.spawn")
|
||||
.executesPlayer((sender, args) -> {
|
||||
Location location = LocationUtils.toBlockCenter(sender.getLocation());
|
||||
MinionData data = new MinionData(0, MinionTypes.parse("miner"), new Level(1, 20, new Skin("cool", Map.ofEntries(Map.entry(EquipmentSlot.BOOTS, WrappedItemStack.wrap(new ItemStack(Material.DIAMOND_BOOTS))), Map.entry(EquipmentSlot.LEGGINGS, WrappedItemStack.wrap(new ItemStack(Material.DIAMOND_LEGGINGS))), Map.entry(EquipmentSlot.CHEST_PLATE, WrappedItemStack.wrap(new ItemStack(Material.DIAMOND_CHESTPLATE))), Map.entry(EquipmentSlot.HELMET, WrappedItemStack.wrap(new ItemStack(Material.DIAMOND_HELMET))), Map.entry(EquipmentSlot.MAIN_HAND, WrappedItemStack.wrap(new ItemStack(Material.DIAMOND_PICKAXE))), Map.entry(EquipmentSlot.OFF_HAND, WrappedItemStack.wrap(new ItemStack(Material.AIR)))))), new ItemStack(Material.DIAMOND_HOE), new Skin("cool", Map.ofEntries(Map.entry(EquipmentSlot.BOOTS, WrappedItemStack.wrap(new ItemStack(Material.DIAMOND_BOOTS))), Map.entry(EquipmentSlot.LEGGINGS, WrappedItemStack.wrap(new ItemStack(Material.DIAMOND_LEGGINGS))), Map.entry(EquipmentSlot.CHEST_PLATE, WrappedItemStack.wrap(new ItemStack(Material.DIAMOND_CHESTPLATE))), Map.entry(EquipmentSlot.HELMET, WrappedItemStack.wrap(new ItemStack(Material.DIAMOND_HELMET))), Map.entry(EquipmentSlot.MAIN_HAND, WrappedItemStack.wrap(new ItemStack(Material.DIAMOND_PICKAXE))), Map.entry(EquipmentSlot.OFF_HAND, WrappedItemStack.wrap(new ItemStack(Material.AIR))))), new HashMap<>());
|
||||
MinionData data = new MinionData(0, MinionTypes.parse("miner"), new Level(1, 80, new Skin("cool", Map.ofEntries(Map.entry(EquipmentSlot.BOOTS, WrappedItemStack.wrap(new ItemStack(Material.DIAMOND_BOOTS))), Map.entry(EquipmentSlot.LEGGINGS, WrappedItemStack.wrap(new ItemStack(Material.DIAMOND_LEGGINGS))), Map.entry(EquipmentSlot.CHEST_PLATE, WrappedItemStack.wrap(new ItemStack(Material.DIAMOND_CHESTPLATE))), Map.entry(EquipmentSlot.HELMET, WrappedItemStack.wrap(new ItemStack(Material.DIAMOND_HELMET))), Map.entry(EquipmentSlot.MAIN_HAND, WrappedItemStack.wrap(new ItemStack(Material.DIAMOND_PICKAXE))), Map.entry(EquipmentSlot.OFF_HAND, WrappedItemStack.wrap(new ItemStack(Material.AIR)))))), new ItemStack(Material.DIAMOND_HOE), new Skin("cool", Map.ofEntries(Map.entry(EquipmentSlot.BOOTS, WrappedItemStack.wrap(new ItemStack(Material.DIAMOND_BOOTS))), Map.entry(EquipmentSlot.LEGGINGS, WrappedItemStack.wrap(new ItemStack(Material.DIAMOND_LEGGINGS))), Map.entry(EquipmentSlot.CHEST_PLATE, WrappedItemStack.wrap(new ItemStack(Material.DIAMOND_CHESTPLATE))), Map.entry(EquipmentSlot.HELMET, WrappedItemStack.wrap(new ItemStack(Material.DIAMOND_HELMET))), Map.entry(EquipmentSlot.MAIN_HAND, WrappedItemStack.wrap(new ItemStack(Material.DIAMOND_PICKAXE))), Map.entry(EquipmentSlot.OFF_HAND, WrappedItemStack.wrap(new ItemStack(Material.AIR))))), new HashMap<>());
|
||||
Minion minion = new Minion(location, data);
|
||||
minion.spawn();
|
||||
MinionArea area = MinionWorldCache.getArea(location.getWorld());
|
||||
area.load(minion);
|
||||
MinionWorldCache.add(minion);
|
||||
area.startTicking(location.getChunk());
|
||||
})
|
||||
)
|
||||
|
@ -1,6 +1,7 @@
|
||||
package com.artillexstudios.axminions.exception;
|
||||
|
||||
public class MinionTickFailException extends IllegalStateException {
|
||||
// We don't always care about the stacktrace
|
||||
public static final MinionTickFailException INSTANCE = new MinionTickFailException();
|
||||
|
||||
public MinionTickFailException() {
|
||||
|
@ -22,6 +22,7 @@ public final class Minion {
|
||||
private final AtomicBoolean needsSaving = new AtomicBoolean(false);
|
||||
private int tick = 0;
|
||||
private int armTick = 0;
|
||||
private boolean ticking = false;
|
||||
private MinionData minionData;
|
||||
|
||||
public Minion(Location location, MinionData data) {
|
||||
@ -40,7 +41,7 @@ public final class Minion {
|
||||
if (Config.SHOW_HAND_ANIMATION) {
|
||||
if (this.armTick >= 20) return;
|
||||
ArmorStandMeta meta = (ArmorStandMeta) this.entity.meta();
|
||||
meta.metadata().set(Accessors.RIGHT_ARM_ROTATION, new EulerAngle((double) (-2 + this.armTick) / 10, 0, 0));
|
||||
meta.metadata().set(Accessors.RIGHT_ARM_ROTATION, new EulerAngle((-2 + ((double) this.armTick / 10)), 0, 0));
|
||||
this.armTick += 2;
|
||||
}
|
||||
return;
|
||||
@ -48,7 +49,6 @@ public final class Minion {
|
||||
|
||||
this.tick = 0;
|
||||
if (Config.SHOW_HAND_ANIMATION & this.minionData.type().tick(this)) {
|
||||
// TODO: Animation
|
||||
this.armTick = 0;
|
||||
}
|
||||
}
|
||||
@ -74,6 +74,10 @@ public final class Minion {
|
||||
return this.minionData.skin();
|
||||
}
|
||||
|
||||
public MinionType type() {
|
||||
return this.minionData.type();
|
||||
}
|
||||
|
||||
public void spawn() {
|
||||
this.entity.spawn();
|
||||
}
|
||||
@ -90,6 +94,14 @@ public final class Minion {
|
||||
return this.location;
|
||||
}
|
||||
|
||||
public boolean ticking() {
|
||||
return this.ticking;
|
||||
}
|
||||
|
||||
public void ticking(boolean ticking) {
|
||||
this.ticking = ticking;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
|
@ -1,6 +1,7 @@
|
||||
package com.artillexstudios.axminions.minions;
|
||||
|
||||
import com.artillexstudios.axminions.utils.LogUtils;
|
||||
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
|
||||
import org.bukkit.World;
|
||||
|
||||
import java.util.Collection;
|
||||
@ -8,6 +9,7 @@ import java.util.IdentityHashMap;
|
||||
|
||||
public final class MinionWorldCache {
|
||||
private static final IdentityHashMap<World, MinionArea> worlds = new IdentityHashMap<>();
|
||||
private static final ObjectArrayList<Minion> minions = new ObjectArrayList<>();
|
||||
|
||||
public static void loadArea(World world) {
|
||||
if (worlds.containsKey(world)) {
|
||||
@ -18,6 +20,18 @@ public final class MinionWorldCache {
|
||||
worlds.put(world, new MinionArea());
|
||||
}
|
||||
|
||||
public static void add(Minion minion) {
|
||||
minions.add(minion);
|
||||
MinionArea area = worlds.get(minion.location().getWorld());
|
||||
area.load(minion);
|
||||
}
|
||||
|
||||
public static void remove(Minion minion) {
|
||||
minions.remove(minion);
|
||||
MinionArea area = worlds.get(minion.location().getWorld());
|
||||
area.remove(minion);
|
||||
}
|
||||
|
||||
public static MinionArea getArea(World world) {
|
||||
return worlds.get(world);
|
||||
}
|
||||
@ -26,6 +40,10 @@ public final class MinionWorldCache {
|
||||
return worlds.remove(world);
|
||||
}
|
||||
|
||||
public static ObjectArrayList<Minion> minions() {
|
||||
return minions;
|
||||
}
|
||||
|
||||
public static Collection<MinionArea> worlds() {
|
||||
return worlds.values();
|
||||
}
|
||||
|
@ -98,12 +98,12 @@ public final class CompiledAction {
|
||||
try {
|
||||
effect.dispatch(minion, collected);
|
||||
} catch (MinionTickFailException exception) {
|
||||
LogUtils.warn("An unexpected error occurred while ticking minion {} at {}!", minion, minion.location(), exception);
|
||||
LogUtils.warn("An unexpected error occurred while ticking minion {} at {}!", minion.type().name(), minion.location(), exception);
|
||||
throw exception;
|
||||
}
|
||||
}
|
||||
});
|
||||
// TODO: Return false if the actions can't be ran
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -6,7 +6,6 @@ import com.artillexstudios.axminions.minions.actions.effects.Effect;
|
||||
import com.artillexstudios.axminions.utils.ItemCollection;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.Registry;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
@ -29,7 +28,7 @@ public class BreakEffect extends Effect<Location, ItemCollection> {
|
||||
World world = argument.getWorld();
|
||||
|
||||
if (world == null) {
|
||||
throw MinionTickFailException.INSTANCE;
|
||||
throw new MinionTickFailException("World is null!");
|
||||
}
|
||||
|
||||
world.setBlockData(argument, AIR);
|
||||
|
@ -1,5 +1,6 @@
|
||||
package com.artillexstudios.axminions.minions.actions.effects.implementation;
|
||||
|
||||
import com.artillexstudios.axminions.exception.MinionTickFailException;
|
||||
import com.artillexstudios.axminions.minions.Minion;
|
||||
import com.artillexstudios.axminions.minions.actions.effects.Effect;
|
||||
import com.artillexstudios.axminions.utils.ItemCollection;
|
||||
@ -18,7 +19,7 @@ public class DropAtMinionEffect extends Effect<ItemCollection, ItemCollection> {
|
||||
public ItemCollection run(Minion minion, ItemCollection argument) {
|
||||
World world = minion.location().getWorld();
|
||||
if (world == null) {
|
||||
return ItemCollection.EMPTY;
|
||||
throw new MinionTickFailException("World is null!");
|
||||
}
|
||||
|
||||
for (ItemStack itemStack : argument.items()) {
|
||||
|
@ -4,53 +4,38 @@ import com.artillexstudios.axapi.scheduler.ScheduledTask;
|
||||
import com.artillexstudios.axapi.scheduler.Scheduler;
|
||||
import com.artillexstudios.axminions.jfr.MinionTickEvent;
|
||||
import com.artillexstudios.axminions.minions.Minion;
|
||||
import com.artillexstudios.axminions.minions.MinionArea;
|
||||
import com.artillexstudios.axminions.minions.MinionTicker;
|
||||
import com.artillexstudios.axminions.minions.MinionWorldCache;
|
||||
import com.artillexstudios.axminions.utils.ChunkPos;
|
||||
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
|
||||
|
||||
// TODO: Add a list with all minions, add a ticking boolean to minions
|
||||
public final class BukkitMinionTicker implements MinionTicker {
|
||||
private static ScheduledTask task;
|
||||
private ScheduledTask task;
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
task = Scheduler.get().runTimer(() -> {
|
||||
this.task = Scheduler.get().runTimer(() -> {
|
||||
MinionTickEvent event = new MinionTickEvent();
|
||||
event.begin();
|
||||
for (MinionArea world : MinionWorldCache.worlds()) {
|
||||
world.forEachPos(position -> {
|
||||
if (!position.isTicking()) return;
|
||||
|
||||
tickChunk(position);
|
||||
});
|
||||
final ObjectArrayList<Minion> minions = MinionWorldCache.minions();
|
||||
final int minionSize = minions.size();
|
||||
for (int i = 0; i < minionSize; i++) {
|
||||
final Minion minion = minions.get(i);
|
||||
if (!minion.ticking()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
minion.tick();
|
||||
}
|
||||
event.commit();
|
||||
}, 1, 1);
|
||||
}
|
||||
|
||||
private static void tickChunk(ChunkPos position) {
|
||||
ObjectArrayList<Minion> minions = position.minions();
|
||||
int minionSize = minions.size();
|
||||
if (minionSize == 0) return;
|
||||
|
||||
Minion first = minions.get(0);
|
||||
Scheduler.get().executeAt(first.location(), () -> {
|
||||
// We already have the first, why not tick it?
|
||||
first.tick();
|
||||
|
||||
for (int i = 1; i < minionSize; i++) {
|
||||
Minion minion = minions.get(i);
|
||||
minion.tick();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancel() {
|
||||
if (task != null && !task.isCancelled()) {
|
||||
task.cancel();
|
||||
if (this.task != null && !this.task.isCancelled()) {
|
||||
this.task.cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,16 +1,55 @@
|
||||
package com.artillexstudios.axminions.minions.ticker;
|
||||
|
||||
import com.artillexstudios.axapi.scheduler.ScheduledTask;
|
||||
import com.artillexstudios.axapi.scheduler.Scheduler;
|
||||
import com.artillexstudios.axminions.jfr.MinionTickEvent;
|
||||
import com.artillexstudios.axminions.minions.Minion;
|
||||
import com.artillexstudios.axminions.minions.MinionArea;
|
||||
import com.artillexstudios.axminions.minions.MinionTicker;
|
||||
import com.artillexstudios.axminions.minions.MinionWorldCache;
|
||||
import com.artillexstudios.axminions.utils.ChunkPos;
|
||||
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
|
||||
|
||||
public final class FoliaMinionTicker implements MinionTicker {
|
||||
private ScheduledTask task;
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
this.task = Scheduler.get().runTimer(() -> {
|
||||
MinionTickEvent event = new MinionTickEvent();
|
||||
event.begin();
|
||||
for (MinionArea world : MinionWorldCache.worlds()) {
|
||||
world.forEachPos(position -> {
|
||||
if (!position.isTicking()) return;
|
||||
|
||||
tickChunk(position);
|
||||
});
|
||||
}
|
||||
event.commit();
|
||||
}, 1, 1);
|
||||
}
|
||||
|
||||
private void tickChunk(ChunkPos position) {
|
||||
ObjectArrayList<Minion> minions = position.minions();
|
||||
int minionSize = minions.size();
|
||||
if (minionSize == 0) return;
|
||||
|
||||
Minion first = minions.get(0);
|
||||
Scheduler.get().executeAt(first.location(), () -> {
|
||||
// We already have the first, why not tick it?
|
||||
first.tick();
|
||||
|
||||
for (int i = 1; i < minionSize; i++) {
|
||||
Minion minion = minions.get(i);
|
||||
minion.tick();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancel() {
|
||||
|
||||
if (this.task != null && !this.task.isCancelled()) {
|
||||
this.task.cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -9,6 +9,10 @@ public record ChunkPos(int x, int z, AtomicBoolean ticking, ObjectArrayList<Mini
|
||||
|
||||
public void ticking(boolean ticking) {
|
||||
this.ticking.set(ticking);
|
||||
|
||||
for (Minion minion : this.minions) {
|
||||
minion.ticking(ticking);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isTicking() {
|
||||
|
Loading…
Reference in New Issue
Block a user