diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java b/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java index 0e249e316..704fe803c 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java @@ -47,9 +47,18 @@ import com.sk89q.worldedit.extent.ChangeSetExtent; import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.extent.MaskingExtent; import com.sk89q.worldedit.extent.PassthroughExtent; +import com.sk89q.worldedit.extent.cache.LastAccessExtentCache; import com.sk89q.worldedit.extent.inventory.BlockBag; import com.sk89q.worldedit.extent.inventory.BlockBagExtent; +import com.sk89q.worldedit.extent.reorder.ChunkBatchingExtent; +import com.sk89q.worldedit.extent.reorder.MultiStageReorder; +import com.sk89q.worldedit.extent.validation.BlockChangeLimiter; +import com.sk89q.worldedit.extent.validation.DataValidatorExtent; +import com.sk89q.worldedit.extent.world.BlockQuirkExtent; +import com.sk89q.worldedit.extent.world.ChunkLoadingExtent; +import com.sk89q.worldedit.extent.world.FastModeExtent; import com.sk89q.worldedit.extent.world.SurvivalModeExtent; +import com.sk89q.worldedit.extent.world.WatchdogTickingExtent; import com.sk89q.worldedit.function.GroundFunction; import com.sk89q.worldedit.function.RegionFunction; import com.sk89q.worldedit.function.block.BlockReplace; @@ -112,6 +121,7 @@ import com.sk89q.worldedit.util.Countable; import com.sk89q.worldedit.util.Direction; import com.sk89q.worldedit.util.TreeGenerator; import com.sk89q.worldedit.util.eventbus.EventBus; +import com.sk89q.worldedit.world.NullWorld; import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.block.BaseBlock; @@ -722,6 +732,29 @@ public class EditSession extends PassthroughExtent implements AutoCloseable { disableQueue(); } + /** + * Check if this session will tick the watchdog. + * + * @return {@code true} if any watchdog extent is enabled + */ + public boolean isTickingWatchdog() { + /* + return watchdogExtents.stream().anyMatch(WatchdogTickingExtent::isEnabled); + */ + return false; + } + + /** + * Set all watchdog extents to the given mode. + */ + public void setTickingWatchdog(boolean active) { + /* + for (WatchdogTickingExtent extent : watchdogExtents) { + extent.setEnabled(active); + } + */ + } + /** * Get the number of blocks changed, including repeated block changes. * diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/LocalSession.java b/worldedit-core/src/main/java/com/sk89q/worldedit/LocalSession.java index eae29d382..15849e7fc 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/LocalSession.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/LocalSession.java @@ -155,6 +155,7 @@ public class LocalSession implements TextureHolder { private transient BlockVector3 cuiTemporaryBlock; private transient List> lastDistribution; private transient World worldOverride; + private transient boolean tickingWatchdog = false; private transient boolean loadDefaults = true; @@ -604,18 +605,12 @@ public class LocalSession implements TextureHolder { this.worldOverride = worldOverride; } - public void unregisterTools(Player player) { - synchronized (tools) { - for (Tool tool : tools.values()) { - if (tool instanceof BrushTool) { - ((BrushTool) tool).clear(player); - } - } - } + public boolean isTickingWatchdog() { + return tickingWatchdog; } - public int getSize() { - return history.size(); + public void setTickingWatchdog(boolean tickingWatchdog) { + this.tickingWatchdog = tickingWatchdog; } /** @@ -1459,6 +1454,7 @@ public class LocalSession implements TextureHolder { if (transform != null) { editSession.addTransform(transform); } + editSession.setTickingWatchdog(tickingWatchdog); return editSession; } @@ -1598,5 +1594,13 @@ public class LocalSession implements TextureHolder { this.transform = transform; } - + public void unregisterTools(Player player) { + synchronized (tools) { + for (Tool tool : tools.values()) { + if (tool instanceof BrushTool) { + ((BrushTool) tool).clear(player); + } + } + } + } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/GeneralCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/GeneralCommands.java index 21e0a8bad..f9fccfe8f 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/GeneralCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/GeneralCommands.java @@ -37,12 +37,15 @@ import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.command.util.CommandPermissions; import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator; +import com.sk89q.worldedit.command.util.HookMode; +import com.sk89q.worldedit.command.util.WorldEditAsyncCommandBuilder; import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.extension.input.DisallowedUsageException; import com.sk89q.worldedit.extension.input.InputParseException; import com.sk89q.worldedit.extension.input.ParserContext; import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.extent.clipboard.Clipboard; +import com.sk89q.worldedit.extension.platform.Capability; import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.util.formatting.component.PaginationBox; import com.sk89q.worldedit.util.formatting.text.Component; @@ -209,10 +212,33 @@ public class GeneralCommands { // } @Command( - name = "gmask", - aliases = {"/gmask"}, - descFooter = "The global destination mask applies to all edits you do and masks based on the destination blocks (i.e., the blocks in the world).", - desc = "Set the global mask" + name = "/watchdog", + desc = "Changes watchdog hook state.", + descFooter = "This is dependent on platform implementation. " + + "Not all platforms support watchdog hooks, or contain a watchdog." + ) + @CommandPermissions("worldedit.watchdog") + public void watchdog(Actor actor, LocalSession session, + @Arg(desc = "The mode to set the watchdog hook to", def = "") + HookMode hookMode) { + if (WorldEdit.getInstance().getPlatformManager().queryCapability(Capability.GAME_HOOKS).getWatchdog() == null) { + actor.printError("This platform has no watchdog hook."); + return; + } + boolean previousMode = session.isTickingWatchdog(); + if (hookMode != null && (hookMode == HookMode.ACTIVE) == previousMode) { + actor.printError("Watchdog hook already " + (previousMode ? "active" : "inactive") + "."); + return; + } + session.setTickingWatchdog(!previousMode); + actor.print("Watchdog hook now " + (previousMode ? "inactive" : "active") + "."); + } + + @Command( + name = "gmask", + aliases = {"/gmask"}, + descFooter = "The global destination mask applies to all edits you do and masks based on the destination blocks (i.e., the blocks in the world).", + desc = "Set the global mask" ) @CommandPermissions({"worldedit.global-mask", "worldedit.mask.global"}) public void gmask(Actor actor, LocalSession session, @Arg(desc = "The mask to set", def = "") Mask mask) { diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/EnumConverter.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/EnumConverter.java index 0ba67a994..8b68b4132 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/EnumConverter.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/EnumConverter.java @@ -49,9 +49,8 @@ public final class EnumConverter { r -> ImmutableSet.of(r.getDisplayName()), null)); commandManager.registerConverter(Key.of(HookMode.class), - basic(HookMode.class)); + basic(HookMode.class)); commandManager.registerConverter(Key.of(Scroll.Action.class), - basic(Scroll.Action.class)); } private static > ArgumentConverter basic(Class enumClass) { diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/HookMode.java~7e3fc6c8e... Disable watchdog ticking by default, __watchdog to turn on b/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/HookMode.java~7e3fc6c8e... Disable watchdog ticking by default, __watchdog to turn on new file mode 100644 index 000000000..113a45613 --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/HookMode.java~7e3fc6c8e... Disable watchdog ticking by default, __watchdog to turn on @@ -0,0 +1,24 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * Copyright (C) WorldEdit team and contributors + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser 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 Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.sk89q.worldedit.command.util; + +public enum HookMode { + ACTIVE, INACTIVE +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/world/WatchdogTickingExtent.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/world/WatchdogTickingExtent.java index bb06fb29f..78ddc9db8 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/world/WatchdogTickingExtent.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/world/WatchdogTickingExtent.java @@ -38,7 +38,12 @@ import javax.annotation.Nullable; */ public class WatchdogTickingExtent extends AbstractDelegateExtent { + // Number of operations we run per tick to the watchdog + private static final int OPS_PER_TICK = 100; + private final Watchdog watchdog; + private boolean enabled; + private int ops; /** * Create a new instance. @@ -51,22 +56,40 @@ public class WatchdogTickingExtent extends AbstractDelegateExtent { this.watchdog = watchdog; } + public boolean isEnabled() { + return enabled; + } + + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + + private void onOperation() { + if (enabled) { + ops++; + if (ops == OPS_PER_TICK) { + watchdog.tick(); + ops = 0; + } + } + } + @Override public > boolean setBlock(BlockVector3 location, T block) throws WorldEditException { - watchdog.tick(); + onOperation(); return super.setBlock(location, block); } @Nullable @Override public Entity createEntity(Location location, BaseEntity entity) { - watchdog.tick(); + onOperation(); return super.createEntity(location, entity); } @Override public boolean setBiome(BlockVector2 position, BiomeType biome) { - watchdog.tick(); + onOperation(); return super.setBiome(position, biome); } } diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricPlatform.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricPlatform.java index 00c63f4e4..f67fdcc59 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricPlatform.java +++ b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricPlatform.java @@ -34,6 +34,7 @@ import net.minecraft.SharedConstants; import net.minecraft.server.MinecraftServer; import net.minecraft.server.PlayerManager; import net.minecraft.server.dedicated.DedicatedServer; +import net.minecraft.server.dedicated.MinecraftDedicatedServer; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.world.ServerWorld; import net.minecraft.util.Identifier; @@ -64,8 +65,8 @@ class FabricPlatform extends AbstractPlatform implements MultiUserPlatform { this.mod = mod; this.server = server; this.dataFixer = new FabricDataFixer(getDataVersion()); - this.watchdog = server instanceof DedicatedServer - ? new FabricWatchdog((MixinMinecraftServer) (Object) server) : null; + this.watchdog = server instanceof MinecraftDedicatedServer + ? new FabricWatchdog((MinecraftDedicatedServer) server) : null; } boolean isHookingEvents() { diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricWatchdog.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricWatchdog.java index 554e14b9d..b0f25c685 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricWatchdog.java +++ b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricWatchdog.java @@ -1,19 +1,39 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * Copyright (C) WorldEdit team and contributors + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser 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 Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + package com.sk89q.worldedit.fabric; import com.sk89q.worldedit.extension.platform.Watchdog; import com.sk89q.worldedit.fabric.mixin.MixinMinecraftServer; +import net.minecraft.server.dedicated.MinecraftDedicatedServer; import net.minecraft.util.SystemUtil; class FabricWatchdog implements Watchdog { - private final MixinMinecraftServer server; + private final MinecraftDedicatedServer server; - FabricWatchdog(MixinMinecraftServer server) { + FabricWatchdog(MinecraftDedicatedServer server) { this.server = server; } @Override public void tick() { - server.timeReference = SystemUtil.getMeasuringTimeMs(); + ((MixinMinecraftServer) (Object) server).timeReference = SystemUtil.getMeasuringTimeMs(); } } diff --git a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/mixin/MixinMinecraftServer.java b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/mixin/MixinMinecraftServer.java index 597871cea..de54985b8 100644 --- a/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/mixin/MixinMinecraftServer.java +++ b/worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/mixin/MixinMinecraftServer.java @@ -1,3 +1,22 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * Copyright (C) WorldEdit team and contributors + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser 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 Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + package com.sk89q.worldedit.fabric.mixin; import net.minecraft.server.MinecraftServer; @@ -11,8 +30,8 @@ import org.spongepowered.asm.mixin.Shadow; @Mixin(MinecraftServer.class) public abstract class MixinMinecraftServer extends NonBlockingThreadExecutor implements SnooperListener, CommandOutput, AutoCloseable, Runnable { - public MixinMinecraftServer(String string_1) { - super(string_1); + public MixinMinecraftServer(String name) { + super(name); } @Shadow