Skip to content
Permalink
Browse files

Merge pull request #517 from EngineHub/feature/watchdog-ticking

Tick the watchdog on world actions
  • Loading branch information...
kenzierocks committed Sep 30, 2019
2 parents a515ed0 + 91f92a4 commit d8d25fbff1dbd0ec7022cc8e47db500598013d7d
Showing with 418 additions and 17 deletions.
  1. +15 −0 worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitServerInterface.java
  2. +38 −0 worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitWatchdog.java
  3. +13 −0 worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/BukkitImplAdapter.java
  4. BIN worldedit-bukkit/src/main/resources/worldedit-adapters.jar
  5. +37 −0 worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java
  6. +19 −15 worldedit-core/src/main/java/com/sk89q/worldedit/LocalSession.java
  7. +25 −0 worldedit-core/src/main/java/com/sk89q/worldedit/command/GeneralCommands.java
  8. +3 −0 worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/EnumConverter.java
  9. +24 −0 worldedit-core/src/main/java/com/sk89q/worldedit/command/util/HookMode.java
  10. +9 −0 worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/Platform.java
  11. +29 −0 worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/Watchdog.java
  12. +95 −0 worldedit-core/src/main/java/com/sk89q/worldedit/extent/world/WatchdogTickingExtent.java
  13. +12 −0 worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/FabricPlatform.java
  14. +45 −0 worldedit-fabric/src/main/java/com/sk89q/worldedit/fabric/mixin/MixinMinecraftServer.java
  15. +3 −2 worldedit-fabric/src/main/resources/worldedit.mixins.json
  16. +2 −0 worldedit-forge/build.gradle.kts
  17. +10 −0 worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgePlatform.java
  18. +38 −0 worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeWatchdog.java
  19. +1 −0 worldedit-forge/src/main/resources/META-INF/accesstransformer.cfg
@@ -28,6 +28,8 @@
import com.sk89q.worldedit.extension.platform.Capability;
import com.sk89q.worldedit.extension.platform.MultiUserPlatform;
import com.sk89q.worldedit.extension.platform.Preference;
import com.sk89q.worldedit.extension.platform.Watchdog;
import com.sk89q.worldedit.util.concurrency.LazyReference;
import com.sk89q.worldedit.world.DataFixer;
import com.sk89q.worldedit.world.registry.Registries;
import org.bukkit.Bukkit;
@@ -52,6 +54,14 @@
public WorldEditPlugin plugin;
private CommandRegistration dynamicCommands;
private boolean hookingEvents;
private final LazyReference<Watchdog> watchdog = LazyReference.from(() -> {
if (plugin.getBukkitImplAdapter() != null) {
return plugin.getBukkitImplAdapter().supportsWatchdog()
? new BukkitWatchdog(plugin.getBukkitImplAdapter())
: null;
}
return null;
});

public BukkitServerInterface(WorldEditPlugin plugin, Server server) {
this.plugin = plugin;
@@ -103,6 +113,11 @@ public int schedule(long delay, long period, Runnable task) {
return Bukkit.getScheduler().scheduleSyncRepeatingTask(plugin, task, delay, period);
}

@Override
public Watchdog getWatchdog() {
return watchdog.getValue();
}

@Override
public List<com.sk89q.worldedit.world.World> getWorlds() {
List<World> worlds = server.getWorlds();
@@ -0,0 +1,38 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* 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 <http://www.gnu.org/licenses/>.
*/

package com.sk89q.worldedit.bukkit;

import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter;
import com.sk89q.worldedit.extension.platform.Watchdog;

class BukkitWatchdog implements Watchdog {

private final BukkitImplAdapter adapter;

BukkitWatchdog(BukkitImplAdapter adapter) {
this.adapter = adapter;
}

@Override
public void tick() {
adapter.tickWatchdog();
}

}
@@ -62,6 +62,19 @@
@Nullable
DataFixer getDataFixer();

/**
* @return {@code true} if {@link #tickWatchdog()} is implemented
*/
default boolean supportsWatchdog() {
return false;
}

/**
* Tick the server watchdog, if possible.
*/
default void tickWatchdog() {
}

/**
* Get the block at the given location.
*
Binary file not shown.
@@ -22,6 +22,8 @@
import com.sk89q.worldedit.entity.BaseEntity;
import com.sk89q.worldedit.entity.Entity;
import com.sk89q.worldedit.event.extent.EditSessionEvent;
import com.sk89q.worldedit.extension.platform.Capability;
import com.sk89q.worldedit.extension.platform.Watchdog;
import com.sk89q.worldedit.extent.ChangeSetExtent;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.extent.MaskingExtent;
@@ -38,6 +40,7 @@
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.RegionMaskingFilter;
import com.sk89q.worldedit.function.biome.BiomeReplace;
@@ -188,6 +191,7 @@ public String getDisplayName() {
private final MultiStageReorder reorderExtent;
private final MaskingExtent maskingExtent;
private final BlockChangeLimiter changeLimiter;
private final List<WatchdogTickingExtent> watchdogExtents = new ArrayList<>(2);

private final Extent bypassReorderHistory;
private final Extent bypassHistory;
@@ -214,10 +218,18 @@ public String getDisplayName() {
this.world = world;

if (world != null) {
Watchdog watchdog = WorldEdit.getInstance().getPlatformManager()
.queryCapability(Capability.GAME_HOOKS).getWatchdog();
Extent extent;

// These extents are ALWAYS used
extent = fastModeExtent = new FastModeExtent(world, false);
if (watchdog != null) {
// Reset watchdog before world placement
WatchdogTickingExtent watchdogExtent = new WatchdogTickingExtent(extent, watchdog);
extent = watchdogExtent;
watchdogExtents.add(watchdogExtent);
}
extent = survivalExtent = new SurvivalModeExtent(extent, world);
extent = new BlockQuirkExtent(extent, world);
extent = new ChunkLoadingExtent(extent, world);
@@ -230,6 +242,13 @@ public String getDisplayName() {
extent = reorderExtent = new MultiStageReorder(extent, false);
extent = chunkBatchingExtent = new ChunkBatchingExtent(extent);
extent = wrapExtent(extent, eventBus, event, Stage.BEFORE_REORDER);
if (watchdog != null) {
// reset before buffering extents, since they may buffer all changes
// before the world-placement reset can happen, and still cause halts
WatchdogTickingExtent watchdogExtent = new WatchdogTickingExtent(extent, watchdog);
extent = watchdogExtent;
watchdogExtents.add(watchdogExtent);
}
this.bypassHistory = new DataValidatorExtent(extent, world);

// These extents can be skipped by calling smartSetBlock()
@@ -536,6 +555,24 @@ public void disableBuffering() {
}
}

/**
* 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);
}

/**
* 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.
*
@@ -102,6 +102,7 @@
private transient EditSession.ReorderMode reorderMode = EditSession.ReorderMode.MULTI_STAGE;
private transient List<Countable<BlockState>> lastDistribution;
private transient World worldOverride;
private transient boolean tickingWatchdog = false;

// Saved properties
private String lastScript;
@@ -238,12 +239,7 @@ public EditSession undo(@Nullable BlockBag newBlockBag, Actor actor) {
EditSession editSession = history.get(historyPointer);
try (EditSession newEditSession = WorldEdit.getInstance().getEditSessionFactory()
.getEditSession(editSession.getWorld(), -1, newBlockBag, actor)) {
newEditSession.enableStandardMode();
newEditSession.setReorderMode(reorderMode);
newEditSession.setFastMode(fastMode);
if (newEditSession.getSurvivalExtent() != null) {
newEditSession.getSurvivalExtent().setStripNbt(!actor.hasPermission("worldedit.setnbt"));
}
prepareEditingExtents(editSession, actor);
editSession.undo(newEditSession);
}
return editSession;
@@ -266,12 +262,7 @@ public EditSession redo(@Nullable BlockBag newBlockBag, Actor actor) {
EditSession editSession = history.get(historyPointer);
try (EditSession newEditSession = WorldEdit.getInstance().getEditSessionFactory()
.getEditSession(editSession.getWorld(), -1, newBlockBag, actor)) {
newEditSession.enableStandardMode();
newEditSession.setReorderMode(reorderMode);
newEditSession.setFastMode(fastMode);
if (newEditSession.getSurvivalExtent() != null) {
newEditSession.getSurvivalExtent().setStripNbt(!actor.hasPermission("worldedit.setnbt"));
}
prepareEditingExtents(editSession, actor);
editSession.redo(newEditSession);
}
++historyPointer;
@@ -294,6 +285,14 @@ public void setWorldOverride(@Nullable World worldOverride) {
this.worldOverride = worldOverride;
}

public boolean isTickingWatchdog() {
return tickingWatchdog;
}

public void setTickingWatchdog(boolean tickingWatchdog) {
this.tickingWatchdog = tickingWatchdog;
}

/**
* Get the default region selector.
*
@@ -945,14 +944,19 @@ public EditSession createEditSession(Actor actor) {
}
Request.request().setEditSession(editSession);

editSession.setMask(mask);
prepareEditingExtents(editSession, actor);

return editSession;
}

private void prepareEditingExtents(EditSession editSession, Actor actor) {
editSession.setFastMode(fastMode);
editSession.setReorderMode(reorderMode);
editSession.setMask(mask);
if (editSession.getSurvivalExtent() != null) {
editSession.getSurvivalExtent().setStripNbt(!actor.hasPermission("worldedit.setnbt"));
}

return editSession;
editSession.setTickingWatchdog(tickingWatchdog);
}

/**
@@ -26,10 +26,12 @@
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.platform.Actor;
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;
@@ -198,6 +200,29 @@ public void world(Actor actor, LocalSession session,
}
}

@Command(
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"},
@@ -21,6 +21,7 @@

import com.google.common.collect.ImmutableSet;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.command.util.HookMode;
import com.sk89q.worldedit.util.TreeGenerator;
import org.enginehub.piston.CommandManager;
import org.enginehub.piston.converter.ArgumentConverter;
@@ -46,6 +47,8 @@ public static void register(CommandManager commandManager) {
full(EditSession.ReorderMode.class,
r -> ImmutableSet.of(r.getDisplayName()),
null));
commandManager.registerConverter(Key.of(HookMode.class),
basic(HookMode.class));
}

private static <E extends Enum<E>> ArgumentConverter<E> basic(Class<E> enumClass) {
@@ -0,0 +1,24 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* 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 <http://www.gnu.org/licenses/>.
*/

package com.sk89q.worldedit.command.util;

public enum HookMode {
ACTIVE, INACTIVE
}
@@ -83,6 +83,15 @@
*/
int schedule(long delay, long period, Runnable task);

/**
* Get the watchdog service.
*
* @return the watchdog service, or {@code null} if none
*/
default @Nullable Watchdog getWatchdog() {
return null;
}

/**
* Get a list of available or loaded worlds.
*
@@ -0,0 +1,29 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* 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 <http://www.gnu.org/licenses/>.
*/

package com.sk89q.worldedit.extension.platform;

/**
* Interface to a {@link Platform}'s watchdog service.
*/
public interface Watchdog {

void tick();

}

0 comments on commit d8d25fb

Please sign in to comment.
You can’t perform that action at this time.