Mirror von
https://github.com/IntellectualSites/FastAsyncWorldEdit.git
synchronisiert 2024-12-27 19:30:07 +01:00
Initial experimental work on Folia support
Dieser Commit ist enthalten in:
Ursprung
fbb8a9b944
Commit
0faaaa55ee
@ -2,6 +2,7 @@ package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R1;
|
||||
|
||||
import com.fastasyncworldedit.bukkit.adapter.FaweAdapter;
|
||||
import com.fastasyncworldedit.bukkit.adapter.NMSRelighterFactory;
|
||||
import com.fastasyncworldedit.core.Fawe;
|
||||
import com.fastasyncworldedit.core.FaweCache;
|
||||
import com.fastasyncworldedit.core.entity.LazyBaseEntity;
|
||||
import com.fastasyncworldedit.core.extent.processor.lighting.RelighterFactory;
|
||||
@ -240,7 +241,12 @@ public final class PaperweightFaweAdapter extends FaweAdapter<net.minecraft.nbt.
|
||||
int y = location.getBlockY();
|
||||
int z = location.getBlockZ();
|
||||
final ServerLevel handle = getServerLevel(location.getWorld());
|
||||
LevelChunk chunk = handle.getChunk(x >> 4, z >> 4);
|
||||
LevelChunk chunk;
|
||||
if (Fawe.isTickThread()) {
|
||||
chunk = handle.getChunk(x >> 4, z >> 4);
|
||||
} else {
|
||||
chunk = TaskManager.taskManager().syncAt(() -> handle.getChunk(x >> 4, z >> 4), BukkitAdapter.adapt(location));
|
||||
}
|
||||
final BlockPos blockPos = new BlockPos(x, y, z);
|
||||
final net.minecraft.world.level.block.state.BlockState blockData = chunk.getBlockState(blockPos);
|
||||
BlockState state = adapt(blockData);
|
||||
|
@ -59,7 +59,8 @@ public class PaperweightFaweWorldNativeAccess implements WorldNativeAccess<Level
|
||||
this.level = level;
|
||||
// Use the actual tick as minecraft-defined so we don't try to force blocks into the world when the server's already lagging.
|
||||
// - With the caveat that we don't want to have too many cached changed (1024) so we'd flush those at 1024 anyway.
|
||||
this.lastTick = new AtomicInteger(MinecraftServer.currentTick);
|
||||
// TODO
|
||||
this.lastTick = new AtomicInteger(0);
|
||||
}
|
||||
|
||||
private Level getLevel() {
|
||||
|
@ -11,10 +11,14 @@ import com.fastasyncworldedit.core.util.MathMan;
|
||||
import com.fastasyncworldedit.core.util.ReflectionUtils;
|
||||
import com.fastasyncworldedit.core.util.TaskManager;
|
||||
import com.mojang.datafixers.util.Either;
|
||||
import com.sk89q.worldedit.bukkit.BukkitAdapter;
|
||||
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
|
||||
import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter;
|
||||
import com.sk89q.worldedit.bukkit.adapter.Refraction;
|
||||
import com.sk89q.worldedit.internal.util.LogManagerCompat;
|
||||
import com.sk89q.worldedit.math.Vector3;
|
||||
import com.sk89q.worldedit.util.Location;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
import com.sk89q.worldedit.world.biome.BiomeType;
|
||||
import com.sk89q.worldedit.world.biome.BiomeTypes;
|
||||
import com.sk89q.worldedit.world.block.BlockState;
|
||||
@ -383,13 +387,19 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
|
||||
);
|
||||
}
|
||||
nearbyPlayers(nmsWorld, coordIntPair).forEach(p -> p.connection.send(packet));
|
||||
});
|
||||
}, toLocation(nmsWorld, coordIntPair));
|
||||
}
|
||||
|
||||
private static List<ServerPlayer> nearbyPlayers(ServerLevel serverLevel, ChunkPos coordIntPair) {
|
||||
return serverLevel.getChunkSource().chunkMap.getPlayers(coordIntPair, false);
|
||||
}
|
||||
|
||||
public static Location toLocation(ServerLevel serverLevel, ChunkPos chunkPos) {
|
||||
final World adapt = BukkitAdapter.adapt(serverLevel.getWorld());
|
||||
final Vector3 pos = Vector3.at(chunkPos.getMinBlockX(), 0, chunkPos.getMinBlockZ());
|
||||
return new Location(adapt, pos);
|
||||
}
|
||||
|
||||
/*
|
||||
NMS conversion
|
||||
*/
|
||||
|
@ -11,6 +11,8 @@ import com.fastasyncworldedit.bukkit.regions.ResidenceFeature;
|
||||
import com.fastasyncworldedit.bukkit.regions.TownyFeature;
|
||||
import com.fastasyncworldedit.bukkit.regions.WorldGuardFeature;
|
||||
import com.fastasyncworldedit.bukkit.util.BukkitTaskManager;
|
||||
import com.fastasyncworldedit.bukkit.util.FoliaTaskManager;
|
||||
import com.fastasyncworldedit.core.util.FoliaSupport;
|
||||
import com.fastasyncworldedit.bukkit.util.ItemUtil;
|
||||
import com.fastasyncworldedit.bukkit.util.MinecraftVersion;
|
||||
import com.fastasyncworldedit.bukkit.util.image.BukkitImageViewer;
|
||||
@ -63,6 +65,7 @@ public class FaweBukkit implements IFawe, Listener {
|
||||
private ItemUtil itemUtil;
|
||||
private Preloader preloader;
|
||||
private volatile boolean keepUnloaded;
|
||||
private static final Thread startingThread = Thread.currentThread();
|
||||
|
||||
public FaweBukkit(Plugin plugin) {
|
||||
this.plugin = plugin;
|
||||
@ -74,7 +77,7 @@ public class FaweBukkit implements IFawe, Listener {
|
||||
} catch (Throwable e) {
|
||||
LOGGER.error("Brush Listener Failed", e);
|
||||
}
|
||||
if (PaperLib.isPaper() && Settings.settings().EXPERIMENTAL.DYNAMIC_CHUNK_RENDERING > 1) {
|
||||
if (!FoliaSupport.isFolia() && PaperLib.isPaper() && Settings.settings().EXPERIMENTAL.DYNAMIC_CHUNK_RENDERING > 1) {
|
||||
new RenderListener(plugin);
|
||||
}
|
||||
} catch (final Throwable e) {
|
||||
@ -89,20 +92,22 @@ public class FaweBukkit implements IFawe, Listener {
|
||||
platformAdapter = new NMSAdapter();
|
||||
|
||||
//PlotSquared support is limited to Spigot/Paper as of 02/20/2020
|
||||
TaskManager.taskManager().later(this::setupPlotSquared, 0);
|
||||
// TODO plotsquared support
|
||||
// TaskManager.taskManager().later(this::setupPlotSquared, 0);
|
||||
|
||||
// TODO moved out of task below??
|
||||
Bukkit.getPluginManager().registerEvents(FaweBukkit.this, FaweBukkit.this.plugin);
|
||||
// Registered delayed Event Listeners
|
||||
TaskManager.taskManager().task(() -> {
|
||||
/*TaskManager.taskManager().task(() -> {
|
||||
// Fix for ProtocolSupport
|
||||
Settings.settings().PROTOCOL_SUPPORT_FIX =
|
||||
Bukkit.getPluginManager().isPluginEnabled("ProtocolSupport");
|
||||
|
||||
// This class
|
||||
Bukkit.getPluginManager().registerEvents(FaweBukkit.this, FaweBukkit.this.plugin);
|
||||
|
||||
// The tick limiter
|
||||
new ChunkListener9();
|
||||
});
|
||||
});*/
|
||||
|
||||
// Warn if small-edits are enabled with extended world heights
|
||||
if (version.isEqualOrHigherThan(MinecraftVersion.CAVES_18) && Settings.settings().HISTORY.SMALL_EDITS) {
|
||||
@ -192,6 +197,9 @@ public class FaweBukkit implements IFawe, Listener {
|
||||
*/
|
||||
@Override
|
||||
public TaskManager getTaskManager() {
|
||||
if (FoliaSupport.isFolia()) {
|
||||
return new FoliaTaskManager();
|
||||
}
|
||||
return new BukkitTaskManager(plugin);
|
||||
}
|
||||
|
||||
@ -312,6 +320,14 @@ public class FaweBukkit implements IFawe, Listener {
|
||||
return platformAdapter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTickThread() {
|
||||
if (FoliaSupport.isFolia()) {
|
||||
return FoliaSupport.isTickThread();
|
||||
}
|
||||
return Thread.currentThread() == startingThread;
|
||||
}
|
||||
|
||||
private void setupPlotSquared() {
|
||||
Plugin plotSquared = this.plugin.getServer().getPluginManager().getPlugin("PlotSquared");
|
||||
if (plotSquared == null) {
|
||||
|
@ -1,6 +1,7 @@
|
||||
package com.fastasyncworldedit.bukkit.listener;
|
||||
|
||||
import com.fastasyncworldedit.bukkit.FaweBukkit;
|
||||
import com.fastasyncworldedit.core.util.FoliaSupport;
|
||||
import com.fastasyncworldedit.core.Fawe;
|
||||
import com.fastasyncworldedit.core.configuration.Settings;
|
||||
import com.fastasyncworldedit.core.util.FaweTimer;
|
||||
@ -59,6 +60,9 @@ public abstract class ChunkListener implements Listener {
|
||||
Settings.settings().TICK_LIMITER.FALLING, Settings.settings().TICK_LIMITER.ITEMS};
|
||||
|
||||
public ChunkListener() {
|
||||
if (FoliaSupport.isFolia()) {
|
||||
return;
|
||||
}
|
||||
if (Settings.settings().TICK_LIMITER.ENABLED) {
|
||||
PluginManager plm = Bukkit.getPluginManager();
|
||||
Plugin plugin = Fawe.<FaweBukkit>platform().getPlugin();
|
||||
|
@ -1,10 +1,14 @@
|
||||
package com.fastasyncworldedit.bukkit.util;
|
||||
|
||||
import com.fastasyncworldedit.core.util.TaskManager;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.util.Location;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class BukkitTaskManager extends TaskManager {
|
||||
|
||||
@ -34,11 +38,21 @@ public class BukkitTaskManager extends TaskManager {
|
||||
this.plugin.getServer().getScheduler().runTask(this.plugin, runnable).getTaskId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void task(@NotNull final Runnable runnable, @NotNull final Location context) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void later(@Nonnull final Runnable runnable, final int delay) {
|
||||
this.plugin.getServer().getScheduler().runTaskLater(this.plugin, runnable, delay).getTaskId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void later(@NotNull final Runnable runnable, final Location location, final int delay) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void laterAsync(@Nonnull final Runnable runnable, final int delay) {
|
||||
this.plugin.getServer().getScheduler().runTaskLaterAsynchronously(this.plugin, runnable, delay);
|
||||
@ -51,4 +65,16 @@ public class BukkitTaskManager extends TaskManager {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO
|
||||
|
||||
@Override
|
||||
public <T> T syncAt(final Supplier<T> supplier, final Location context) {
|
||||
return sync(supplier);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T syncWith(final Supplier<T> supplier, final Player context) {
|
||||
return sync(supplier);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,206 @@
|
||||
package com.fastasyncworldedit.bukkit.util;
|
||||
|
||||
import com.fastasyncworldedit.core.util.TaskManager;
|
||||
import com.sk89q.worldedit.bukkit.BukkitAdapter;
|
||||
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
|
||||
import com.sk89q.worldedit.entity.Entity;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.util.Location;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodType;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.FutureTask;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import static java.lang.invoke.MethodHandles.dropReturn;
|
||||
import static java.lang.invoke.MethodHandles.explicitCastArguments;
|
||||
import static java.lang.invoke.MethodHandles.filterArguments;
|
||||
import static java.lang.invoke.MethodHandles.insertArguments;
|
||||
import static java.lang.invoke.MethodType.methodType;
|
||||
|
||||
public class FoliaTaskManager extends TaskManager {
|
||||
|
||||
private final ScheduledExecutorService backgroundExecutor = Executors.newSingleThreadScheduledExecutor();
|
||||
private final AtomicInteger idCounter = new AtomicInteger();
|
||||
|
||||
@Override
|
||||
public int repeat(@NotNull final Runnable runnable, final int interval) {
|
||||
return fail();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int repeatAsync(@NotNull final Runnable runnable, final int interval) {
|
||||
backgroundExecutor.scheduleAtFixedRate(runnable, 0, ticksToMs(interval), TimeUnit.MILLISECONDS);
|
||||
return idCounter.getAndIncrement();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void async(@NotNull final Runnable runnable) {
|
||||
backgroundExecutor.submit(runnable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void task(@NotNull final Runnable runnable) {
|
||||
fail();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void task(@NotNull final Runnable runnable, @NotNull final Location context) {
|
||||
SchedulerAdapter.executeForLocation(context, runnable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void later(@NotNull final Runnable runnable, final int delay) {
|
||||
fail();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void later(@NotNull final Runnable runnable, final Location location, final int delay) {
|
||||
fail("Not implemented");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void laterAsync(@NotNull final Runnable runnable, final int delay) {
|
||||
backgroundExecutor.schedule(runnable, ticksToMs(delay), TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancel(final int task) {
|
||||
fail("Not implemented");
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T syncAt(final Supplier<T> supplier, final Location context) {
|
||||
FutureTask<T> task = new FutureTask<>(supplier::get);
|
||||
SchedulerAdapter.executeForLocation(context, task);
|
||||
try {
|
||||
return task.get();
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T syncWith(final Supplier<T> supplier, final Player context) {
|
||||
FutureTask<T> task = new FutureTask<>(supplier::get);
|
||||
SchedulerAdapter.executeForEntity(context, task);
|
||||
try {
|
||||
return task.get();
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private int ticksToMs(int ticks) {
|
||||
// 1 tick = 50ms
|
||||
return ticks * 50;
|
||||
}
|
||||
|
||||
private <T> T fail() {
|
||||
return fail("No main thread present");
|
||||
}
|
||||
|
||||
private <T> T fail(String message) {
|
||||
throw new UnsupportedOperationException(message);
|
||||
}
|
||||
|
||||
private static class SchedulerAdapter {
|
||||
|
||||
private static final MethodHandle EXECUTE_FOR_LOCATION;
|
||||
private static final MethodHandle EXECUTE_FOR_PLAYER;
|
||||
|
||||
private static final MethodType LOCATION_EXECUTE_TYPE = methodType(
|
||||
void.class,
|
||||
Plugin.class,
|
||||
org.bukkit.Location.class,
|
||||
Runnable.class
|
||||
);
|
||||
|
||||
private static final MethodType ENTITY_EXECUTE_TYPE = methodType(
|
||||
boolean.class,
|
||||
Plugin.class,
|
||||
Runnable.class,
|
||||
Runnable.class,
|
||||
long.class
|
||||
);
|
||||
|
||||
static {
|
||||
final Plugin pluginInstance = WorldEditPlugin.getInstance();
|
||||
final MethodHandles.Lookup lookup = MethodHandles.lookup();
|
||||
|
||||
MethodHandle executeForLocation;
|
||||
|
||||
MethodHandle executeForPlayer;
|
||||
try {
|
||||
Class<?> regionisedSchedulerClass = Class.forName("io.papermc.paper.threadedregions.scheduler.RegionisedScheduler");
|
||||
final Method method = Bukkit.class.getDeclaredMethod("getRegionScheduler");
|
||||
executeForLocation = lookup.findVirtual(
|
||||
regionisedSchedulerClass,
|
||||
"execute",
|
||||
LOCATION_EXECUTE_TYPE
|
||||
);
|
||||
executeForLocation = executeForLocation.bindTo(method.invoke(null));
|
||||
executeForLocation = executeForLocation.bindTo(pluginInstance);
|
||||
|
||||
Class<?> entitySchedulerClass = Class.forName("io.papermc.paper.threadedregions.scheduler.EntityScheduler");
|
||||
executeForPlayer = lookup.findVirtual(
|
||||
entitySchedulerClass,
|
||||
"execute",
|
||||
ENTITY_EXECUTE_TYPE
|
||||
);
|
||||
// (ES, P, R, R, L)Z (ES, R, R, L)Z
|
||||
executeForPlayer = insertArguments(executeForPlayer, 1, pluginInstance);
|
||||
// (ES, R1, R2, L)Z -> (ES, R1)Z
|
||||
executeForPlayer = insertArguments(executeForPlayer, 2, null, 0);
|
||||
// (ES, R1)Z -> (ES, R1)V
|
||||
executeForPlayer = dropReturn(executeForPlayer);
|
||||
MethodHandle getScheduler = lookup.findVirtual(
|
||||
org.bukkit.entity.Entity.class,
|
||||
"getScheduler",
|
||||
methodType(entitySchedulerClass)
|
||||
);
|
||||
// (ES, R1)V -> (E, R1)V
|
||||
executeForPlayer = filterArguments(executeForPlayer, 0, getScheduler);
|
||||
MethodType finalType = methodType(void.class, org.bukkit.entity.Player.class, Runnable.class);
|
||||
// (ES, R1)V -> (P, R1)V
|
||||
executeForPlayer = explicitCastArguments(executeForPlayer, finalType);
|
||||
} catch (Throwable throwable) {
|
||||
throw new AssertionError(throwable);
|
||||
}
|
||||
EXECUTE_FOR_LOCATION = executeForLocation;
|
||||
EXECUTE_FOR_PLAYER = executeForPlayer;
|
||||
}
|
||||
|
||||
static void executeForLocation(Location location, Runnable task) {
|
||||
try {
|
||||
EXECUTE_FOR_LOCATION.invokeExact(BukkitAdapter.adapt(location), task);
|
||||
} catch (Error | RuntimeException e) {
|
||||
throw e;
|
||||
} catch (Throwable other) {
|
||||
throw new RuntimeException(other);
|
||||
}
|
||||
}
|
||||
static void executeForEntity(Player player, Runnable task) {
|
||||
// TODO task might not be run if player retires
|
||||
try {
|
||||
EXECUTE_FOR_PLAYER.invokeExact(BukkitAdapter.adapt(player), task);
|
||||
} catch (Error | RuntimeException e) {
|
||||
throw e;
|
||||
} catch (Throwable other) {
|
||||
throw new RuntimeException(other);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -161,7 +161,7 @@ public class BukkitPlayer extends AbstractPlayerActor {
|
||||
public void giveItem(BaseItemStack itemStack) {
|
||||
final PlayerInventory inv = player.getInventory();
|
||||
ItemStack newItem = BukkitAdapter.adapt(itemStack);
|
||||
TaskManager.taskManager().sync(() -> {
|
||||
TaskManager.taskManager().syncWith(() -> {
|
||||
if (itemStack.getType().getId().equalsIgnoreCase(WorldEdit.getInstance().getConfiguration().wandItem)) {
|
||||
inv.remove(newItem);
|
||||
}
|
||||
@ -183,7 +183,7 @@ public class BukkitPlayer extends AbstractPlayerActor {
|
||||
}
|
||||
player.updateInventory();
|
||||
return null;
|
||||
});
|
||||
}, this);
|
||||
}
|
||||
//FAWE end
|
||||
|
||||
@ -240,14 +240,15 @@ public class BukkitPlayer extends AbstractPlayerActor {
|
||||
}
|
||||
org.bukkit.World finalWorld = world;
|
||||
//FAWE end
|
||||
return TaskManager.taskManager().sync(() -> player.teleport(new Location(
|
||||
// TODO async teleport?
|
||||
return TaskManager.taskManager().syncWith(() -> player.teleport(new Location(
|
||||
finalWorld,
|
||||
pos.getX(),
|
||||
pos.getY(),
|
||||
pos.getZ(),
|
||||
yaw,
|
||||
pitch
|
||||
)));
|
||||
)), this);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -6,6 +6,7 @@ import com.fastasyncworldedit.core.queue.implementation.QueueHandler;
|
||||
import com.fastasyncworldedit.core.util.CachedTextureUtil;
|
||||
import com.fastasyncworldedit.core.util.CleanTextureUtil;
|
||||
import com.fastasyncworldedit.core.util.FaweTimer;
|
||||
import com.fastasyncworldedit.core.util.FoliaSupport;
|
||||
import com.fastasyncworldedit.core.util.MainUtil;
|
||||
import com.fastasyncworldedit.core.util.MemUtil;
|
||||
import com.fastasyncworldedit.core.util.RandomTextureUtil;
|
||||
@ -129,14 +130,17 @@ public class Fawe {
|
||||
this.timer = new FaweTimer();
|
||||
|
||||
// Delayed worldedit setup
|
||||
TaskManager.taskManager().later(() -> {
|
||||
// TODO support again
|
||||
/*TaskManager.taskManager().later(() -> {
|
||||
try {
|
||||
WEManager.weManager().addManagers(Fawe.this.implementation.getMaskManagers());
|
||||
} catch (Throwable ignored) {
|
||||
}
|
||||
}, 0);
|
||||
}, 0);*/
|
||||
|
||||
if (!FoliaSupport.isFolia()) {
|
||||
TaskManager.taskManager().repeat(timer, 1);
|
||||
}
|
||||
|
||||
clipboardExecutor = new KeyQueuedExecutorService<>(new ThreadPoolExecutor(
|
||||
1,
|
||||
@ -206,10 +210,15 @@ public class Fawe {
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static boolean isMainThread() {
|
||||
return instance == null || instance.thread == Thread.currentThread();
|
||||
}
|
||||
|
||||
public static boolean isTickThread() {
|
||||
return instance == null || instance.implementation.isTickThread();
|
||||
}
|
||||
|
||||
/**
|
||||
* Non-api. Handles an input FAWE exception if not already handled, given the input boolean array.
|
||||
* Looks at the {@link FaweException.Type} and decides what to do (rethrows if we want to attempt to show the error to the
|
||||
|
@ -49,4 +49,6 @@ public interface IFawe {
|
||||
|
||||
FAWEPlatformAdapterImpl getPlatformAdapter();
|
||||
|
||||
boolean isTickThread();
|
||||
|
||||
}
|
||||
|
@ -17,6 +17,7 @@ import com.fastasyncworldedit.core.util.collection.CleanableThreadLocal;
|
||||
import com.fastasyncworldedit.core.util.task.FaweForkJoinWorkerThreadFactory;
|
||||
import com.fastasyncworldedit.core.wrappers.WorldWrapper;
|
||||
import com.google.common.util.concurrent.Futures;
|
||||
import com.sk89q.worldedit.util.Location;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
@ -90,13 +91,14 @@ public abstract class QueueHandler implements Trimable, Runnable {
|
||||
private long allocate = 50;
|
||||
|
||||
protected QueueHandler() {
|
||||
TaskManager.taskManager().repeat(this, 1);
|
||||
// TODO make main thread independent
|
||||
// TaskManager.taskManager().repeat(this, 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (!Fawe.isMainThread()) {
|
||||
throw new IllegalStateException("Not main thread");
|
||||
if (!Fawe.isTickThread()) {
|
||||
throw new IllegalStateException("Not ticking thread");
|
||||
}
|
||||
if (!syncTasks.isEmpty()) {
|
||||
long currentAllocate = getAllocate();
|
||||
|
@ -0,0 +1,38 @@
|
||||
package com.fastasyncworldedit.core.util;
|
||||
|
||||
public final class FoliaSupport {
|
||||
private FoliaSupport() {
|
||||
|
||||
}
|
||||
|
||||
private static final boolean IS_FOLIA;
|
||||
private static final Class<?> TICK_THREAD_CLASS;
|
||||
static {
|
||||
boolean isFolia = false;
|
||||
try {
|
||||
// Assume API is present
|
||||
Class.forName("io.papermc.paper.threadedregions.scheduler.EntityScheduler");
|
||||
isFolia = true;
|
||||
} catch (Exception unused) {
|
||||
|
||||
}
|
||||
IS_FOLIA = isFolia;
|
||||
Class<?> tickThreadClass = String.class; // thread will never be instance of String
|
||||
if (IS_FOLIA) {
|
||||
try {
|
||||
tickThreadClass = Class.forName("io.papermc.paper.util.TickThread");
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
TICK_THREAD_CLASS = tickThreadClass;
|
||||
}
|
||||
|
||||
public static boolean isFolia() {
|
||||
return IS_FOLIA;
|
||||
}
|
||||
|
||||
public static boolean isTickThread() {
|
||||
return TICK_THREAD_CLASS.isInstance(Thread.currentThread());
|
||||
}
|
||||
}
|
@ -4,7 +4,10 @@ import com.fastasyncworldedit.core.Fawe;
|
||||
import com.fastasyncworldedit.core.configuration.Settings;
|
||||
import com.fastasyncworldedit.core.queue.implementation.QueueHandler;
|
||||
import com.fastasyncworldedit.core.util.task.RunnableVal;
|
||||
import com.sk89q.worldedit.entity.Entity;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.internal.util.LogManagerCompat;
|
||||
import com.sk89q.worldedit.util.Location;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
@ -52,6 +55,7 @@ public abstract class TaskManager {
|
||||
* @param runnable the task to run
|
||||
* @param interval in ticks
|
||||
*/
|
||||
@Deprecated
|
||||
public abstract int repeat(@Nonnull final Runnable runnable, final int interval);
|
||||
|
||||
/**
|
||||
@ -75,7 +79,14 @@ public abstract class TaskManager {
|
||||
*
|
||||
* @param runnable the task to run
|
||||
*/
|
||||
@Deprecated
|
||||
public abstract void task(@Nonnull final Runnable runnable);
|
||||
/**
|
||||
* Run a task on the main thread.
|
||||
*
|
||||
* @param runnable the task to run
|
||||
*/
|
||||
public abstract void task(@Nonnull final Runnable runnable, @Nonnull Location contextLocation);
|
||||
|
||||
/**
|
||||
* Get the public ForkJoinPool.
|
||||
@ -159,6 +170,7 @@ public abstract class TaskManager {
|
||||
/**
|
||||
* Disable async catching for a specific task.
|
||||
*/
|
||||
@Deprecated
|
||||
public void runUnsafe(Runnable run) {
|
||||
QueueHandler queue = Fawe.instance().getQueueHandler();
|
||||
queue.startUnsafe(Fawe.isMainThread());
|
||||
@ -191,6 +203,7 @@ public abstract class TaskManager {
|
||||
*
|
||||
* @param runnable the task to run
|
||||
*/
|
||||
@Deprecated
|
||||
public void taskNowMain(@Nonnull final Runnable runnable) {
|
||||
if (Fawe.isMainThread()) {
|
||||
runnable.run();
|
||||
@ -215,6 +228,7 @@ public abstract class TaskManager {
|
||||
* @param runnable the task to run.
|
||||
* @param async whether the task should run on the main thread
|
||||
*/
|
||||
@Deprecated
|
||||
public void taskSoonMain(@Nonnull final Runnable runnable, boolean async) {
|
||||
if (async) {
|
||||
async(runnable);
|
||||
@ -230,7 +244,9 @@ public abstract class TaskManager {
|
||||
* @param runnable the task to run
|
||||
* @param delay in ticks
|
||||
*/
|
||||
@Deprecated
|
||||
public abstract void later(@Nonnull final Runnable runnable, final int delay);
|
||||
public abstract void later(@Nonnull final Runnable runnable, Location location, final int delay);
|
||||
|
||||
/**
|
||||
* Run a task later asynchronously.
|
||||
@ -255,6 +271,7 @@ public abstract class TaskManager {
|
||||
* @param task the task to run on each object
|
||||
* @param whenDone when the object task completes
|
||||
*/
|
||||
@Deprecated
|
||||
public <T> void objectTask(Collection<T> objects, final RunnableVal<T> task, final Runnable whenDone) {
|
||||
final Iterator<T> iterator = objects.iterator();
|
||||
task(new Runnable() {
|
||||
@ -307,6 +324,7 @@ public abstract class TaskManager {
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void taskWhenFree(@Nonnull Runnable run) {
|
||||
if (Fawe.isMainThread()) {
|
||||
run.run();
|
||||
@ -320,6 +338,7 @@ public abstract class TaskManager {
|
||||
* - Useful if you need to access something from the Bukkit API from another thread<br>
|
||||
* - Usually wait time is around 25ms<br>
|
||||
*/
|
||||
@Deprecated
|
||||
public <T> T syncWhenFree(@Nonnull final RunnableVal<T> function) {
|
||||
if (Fawe.isMainThread()) {
|
||||
function.run();
|
||||
@ -337,6 +356,7 @@ public abstract class TaskManager {
|
||||
* - Useful if you need to access something from the Bukkit API from another thread<br>
|
||||
* - Usually wait time is around 25ms<br>
|
||||
*/
|
||||
@Deprecated
|
||||
public <T> T syncWhenFree(@Nonnull final Supplier<T> supplier) {
|
||||
if (Fawe.isMainThread()) {
|
||||
return supplier.get();
|
||||
@ -353,6 +373,7 @@ public abstract class TaskManager {
|
||||
* - Useful if you need to access something from the Bukkit API from another thread<br>
|
||||
* - Usually wait time is around 25ms
|
||||
*/
|
||||
@Deprecated
|
||||
public <T> T sync(@Nonnull final RunnableVal<T> function) {
|
||||
return sync((Supplier<T>) function);
|
||||
}
|
||||
@ -362,6 +383,7 @@ public abstract class TaskManager {
|
||||
* - Useful if you need to access something from the Bukkit API from another thread<br>
|
||||
* - Usually wait time is around 25ms<br>
|
||||
*/
|
||||
@Deprecated
|
||||
public <T> T sync(final Supplier<T> function) {
|
||||
if (Fawe.isMainThread()) {
|
||||
return function.get();
|
||||
@ -373,4 +395,8 @@ public abstract class TaskManager {
|
||||
}
|
||||
}
|
||||
|
||||
public abstract <T> T syncAt(Supplier<T> supplier, Location context);
|
||||
|
||||
public abstract <T> T syncWith(Supplier<T> supplier, Player context);
|
||||
|
||||
}
|
||||
|
@ -58,12 +58,12 @@ public class AsyncPlayer extends PlayerProxy {
|
||||
|
||||
@Override
|
||||
public void findFreePosition() {
|
||||
TaskManager.taskManager().sync(new RunnableVal<Boolean>() {
|
||||
TaskManager.taskManager().syncWith(new RunnableVal<Boolean>() {
|
||||
@Override
|
||||
public void run(Boolean value) {
|
||||
getBasePlayer().findFreePosition();
|
||||
}
|
||||
});
|
||||
}, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren