|
|
|
|
@@ -19,16 +19,17 @@
|
|
|
|
|
|
|
|
|
|
package com.sk89q.worldedit.fabric;
|
|
|
|
|
|
|
|
|
|
import static com.google.common.base.Preconditions.checkNotNull;
|
|
|
|
|
import static com.sk89q.worldedit.fabric.FabricAdapter.adaptPlayer;
|
|
|
|
|
|
|
|
|
|
import com.mojang.brigadier.CommandDispatcher;
|
|
|
|
|
import com.sk89q.worldedit.LocalSession;
|
|
|
|
|
import com.sk89q.worldedit.WorldEdit;
|
|
|
|
|
import com.sk89q.worldedit.event.platform.PlatformReadyEvent;
|
|
|
|
|
import com.sk89q.worldedit.event.platform.SessionIdleEvent;
|
|
|
|
|
import com.sk89q.worldedit.extension.platform.Capability;
|
|
|
|
|
import com.sk89q.worldedit.extension.platform.Platform;
|
|
|
|
|
import com.sk89q.worldedit.extension.platform.PlatformManager;
|
|
|
|
|
import com.sk89q.worldedit.fabric.net.handler.WECUIPacketHandler;
|
|
|
|
|
import com.sk89q.worldedit.internal.anvil.ChunkDeleter;
|
|
|
|
|
import com.sk89q.worldedit.util.Location;
|
|
|
|
|
import com.sk89q.worldedit.internal.util.LogManagerCompat;
|
|
|
|
|
import com.sk89q.worldedit.world.biome.BiomeType;
|
|
|
|
|
import com.sk89q.worldedit.world.block.BlockCategory;
|
|
|
|
|
import com.sk89q.worldedit.world.block.BlockType;
|
|
|
|
|
@@ -36,41 +37,50 @@ import com.sk89q.worldedit.world.entity.EntityType;
|
|
|
|
|
import com.sk89q.worldedit.world.item.ItemCategory;
|
|
|
|
|
import com.sk89q.worldedit.world.item.ItemType;
|
|
|
|
|
import net.fabricmc.api.ModInitializer;
|
|
|
|
|
import net.fabricmc.fabric.api.command.v1.CommandRegistrationCallback;
|
|
|
|
|
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents;
|
|
|
|
|
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents;
|
|
|
|
|
import net.fabricmc.fabric.api.event.player.AttackBlockCallback;
|
|
|
|
|
import net.fabricmc.fabric.api.event.player.UseBlockCallback;
|
|
|
|
|
import net.fabricmc.fabric.api.event.player.UseItemCallback;
|
|
|
|
|
import net.fabricmc.fabric.api.event.server.ServerStartCallback;
|
|
|
|
|
import net.fabricmc.fabric.api.event.server.ServerStopCallback;
|
|
|
|
|
import net.fabricmc.fabric.api.event.server.ServerTickCallback;
|
|
|
|
|
import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents;
|
|
|
|
|
import net.fabricmc.loader.api.FabricLoader;
|
|
|
|
|
import net.fabricmc.loader.api.ModContainer;
|
|
|
|
|
import net.minecraft.entity.player.PlayerEntity;
|
|
|
|
|
import net.minecraft.item.ItemStack;
|
|
|
|
|
import net.minecraft.server.MinecraftServer;
|
|
|
|
|
import net.minecraft.server.command.ServerCommandSource;
|
|
|
|
|
import net.minecraft.server.network.ServerPlayNetworkHandler;
|
|
|
|
|
import net.minecraft.server.network.ServerPlayerEntity;
|
|
|
|
|
import net.minecraft.tag.BlockTags;
|
|
|
|
|
import net.minecraft.tag.ItemTags;
|
|
|
|
|
import net.minecraft.util.ActionResult;
|
|
|
|
|
import net.minecraft.util.Hand;
|
|
|
|
|
import net.minecraft.util.Identifier;
|
|
|
|
|
import net.minecraft.util.TypedActionResult;
|
|
|
|
|
import net.minecraft.util.hit.BlockHitResult;
|
|
|
|
|
import net.minecraft.util.math.BlockPos;
|
|
|
|
|
import net.minecraft.util.math.Direction;
|
|
|
|
|
import net.minecraft.util.registry.Registry;
|
|
|
|
|
import net.minecraft.world.World;
|
|
|
|
|
import org.apache.logging.log4j.LogManager;
|
|
|
|
|
import org.apache.logging.log4j.Logger;
|
|
|
|
|
|
|
|
|
|
import java.io.File;
|
|
|
|
|
import java.io.IOException;
|
|
|
|
|
import java.io.UncheckedIOException;
|
|
|
|
|
import java.nio.file.Files;
|
|
|
|
|
import java.nio.file.Path;
|
|
|
|
|
|
|
|
|
|
import static com.google.common.base.Preconditions.checkNotNull;
|
|
|
|
|
import static com.sk89q.worldedit.fabric.FabricAdapter.adaptPlayer;
|
|
|
|
|
import static com.sk89q.worldedit.internal.anvil.ChunkDeleter.DELCHUNKS_FILE_NAME;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* The Fabric implementation of WorldEdit.
|
|
|
|
|
*/
|
|
|
|
|
public class FabricWorldEdit implements ModInitializer {
|
|
|
|
|
|
|
|
|
|
private static final Logger LOGGER = LogManagerCompat.getLogger();
|
|
|
|
|
private static final Logger LOGGER = LogManager.getLogger();
|
|
|
|
|
public static final String MOD_ID = "worldedit";
|
|
|
|
|
public static final String CUI_PLUGIN_CHANNEL = "cui";
|
|
|
|
|
|
|
|
|
|
@@ -91,11 +101,11 @@ public class FabricWorldEdit implements ModInitializer {
|
|
|
|
|
@Override
|
|
|
|
|
public void onInitialize() {
|
|
|
|
|
this.container = FabricLoader.getInstance().getModContainer("worldedit").orElseThrow(
|
|
|
|
|
() -> new IllegalStateException("WorldEdit mod missing in Fabric")
|
|
|
|
|
() -> new IllegalStateException("WorldEdit mod missing in Fabric")
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// Setup working directory
|
|
|
|
|
workingDir = new File(FabricLoader.getInstance().getConfigDirectory(), "worldedit").toPath();
|
|
|
|
|
workingDir = FabricLoader.getInstance().getConfigDir().resolve("worldedit");
|
|
|
|
|
if (!Files.exists(workingDir)) {
|
|
|
|
|
try {
|
|
|
|
|
Files.createDirectory(workingDir);
|
|
|
|
|
@@ -106,24 +116,55 @@ public class FabricWorldEdit implements ModInitializer {
|
|
|
|
|
|
|
|
|
|
WECUIPacketHandler.init();
|
|
|
|
|
|
|
|
|
|
ServerTickCallback.EVENT.register(ThreadSafeCache.getInstance());
|
|
|
|
|
ServerStartCallback.EVENT.register(this::onStartServer);
|
|
|
|
|
ServerStopCallback.EVENT.register(this::onStopServer);
|
|
|
|
|
ServerTickEvents.END_SERVER_TICK.register(ThreadSafeCache.getInstance());
|
|
|
|
|
CommandRegistrationCallback.EVENT.register(this::registerCommands);
|
|
|
|
|
ServerLifecycleEvents.SERVER_STARTING.register(this::onStartingServer);
|
|
|
|
|
ServerLifecycleEvents.SERVER_STARTED.register(this::onStartServer);
|
|
|
|
|
ServerLifecycleEvents.SERVER_STOPPING.register(this::onStopServer);
|
|
|
|
|
ServerPlayConnectionEvents.DISCONNECT.register(this::onPlayerDisconnect);
|
|
|
|
|
AttackBlockCallback.EVENT.register(this::onLeftClickBlock);
|
|
|
|
|
UseBlockCallback.EVENT.register(this::onRightClickBlock);
|
|
|
|
|
UseItemCallback.EVENT.register(this::onRightClickAir);
|
|
|
|
|
LOGGER.info("WorldEdit for Fabric (version " + getInternalVersion() + ") is loaded");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void registerCommands(CommandDispatcher<ServerCommandSource> dispatcher, boolean dedicated) {
|
|
|
|
|
PlatformManager manager = WorldEdit.getInstance().getPlatformManager();
|
|
|
|
|
if (manager.getPlatforms().isEmpty()) {
|
|
|
|
|
// We'll register as part of our platform initialization later.
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// This is a re-register (due to /reload), we must add our commands now
|
|
|
|
|
|
|
|
|
|
Platform commandsPlatform = manager.queryCapability(Capability.USER_COMMANDS);
|
|
|
|
|
if (commandsPlatform != platform || !platform.isHookingEvents()) {
|
|
|
|
|
// We're not in control of commands/events -- do not re-register.
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
platform.setNativeDispatcher(dispatcher);
|
|
|
|
|
platform.registerCommands(manager.getPlatformCommandManager().getCommandManager());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void setupPlatform(MinecraftServer server) {
|
|
|
|
|
this.platform = new FabricPlatform(this, server);
|
|
|
|
|
|
|
|
|
|
WorldEdit.getInstance().getPlatformManager().register(platform);
|
|
|
|
|
|
|
|
|
|
this.provider = new FabricPermissionsProvider.VanillaPermissionsProvider(platform);
|
|
|
|
|
this.provider = getInitialPermissionsProvider();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void setupRegistries() {
|
|
|
|
|
private FabricPermissionsProvider getInitialPermissionsProvider() {
|
|
|
|
|
try {
|
|
|
|
|
Class.forName("me.lucko.fabric.api.permissions.v0.Permissions", false, getClass().getClassLoader());
|
|
|
|
|
return new FabricPermissionsProvider.LuckoFabricPermissionsProvider(platform);
|
|
|
|
|
} catch (ClassNotFoundException ignored) {
|
|
|
|
|
// fallback to vanilla
|
|
|
|
|
}
|
|
|
|
|
return new FabricPermissionsProvider.VanillaPermissionsProvider(platform);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void setupRegistries(MinecraftServer server) {
|
|
|
|
|
// Blocks
|
|
|
|
|
for (Identifier name : Registry.BLOCK.getIds()) {
|
|
|
|
|
if (BlockType.REGISTRY.get(name.toString()) == null) {
|
|
|
|
|
@@ -144,31 +185,42 @@ public class FabricWorldEdit implements ModInitializer {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// Biomes
|
|
|
|
|
for (Identifier name : Registry.BIOME.getIds()) {
|
|
|
|
|
for (Identifier name : server.getRegistryManager().get(Registry.BIOME_KEY).getIds()) {
|
|
|
|
|
if (BiomeType.REGISTRY.get(name.toString()) == null) {
|
|
|
|
|
BiomeType.REGISTRY.register(name.toString(), new BiomeType(name.toString()));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// Tags
|
|
|
|
|
for (Identifier name : BlockTags.getContainer().getKeys()) {
|
|
|
|
|
for (Identifier name : BlockTags.getTagGroup().getTagIds()) {
|
|
|
|
|
if (BlockCategory.REGISTRY.get(name.toString()) == null) {
|
|
|
|
|
BlockCategory.REGISTRY.register(name.toString(), new BlockCategory(name.toString()));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
for (Identifier name : ItemTags.getContainer().getKeys()) {
|
|
|
|
|
for (Identifier name : ItemTags.getTagGroup().getTagIds()) {
|
|
|
|
|
if (ItemCategory.REGISTRY.get(name.toString()) == null) {
|
|
|
|
|
ItemCategory.REGISTRY.register(name.toString(), new ItemCategory(name.toString()));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void onStartingServer(MinecraftServer minecraftServer) {
|
|
|
|
|
final Path delChunks = workingDir.resolve(DELCHUNKS_FILE_NAME);
|
|
|
|
|
if (Files.exists(delChunks)) {
|
|
|
|
|
ChunkDeleter.runFromFile(delChunks, true);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void onStartServer(MinecraftServer minecraftServer) {
|
|
|
|
|
FabricAdapter.setServer(minecraftServer);
|
|
|
|
|
setupPlatform(minecraftServer);
|
|
|
|
|
setupRegistries();
|
|
|
|
|
setupRegistries(minecraftServer);
|
|
|
|
|
|
|
|
|
|
config = new FabricConfiguration(this);
|
|
|
|
|
config.load();
|
|
|
|
|
WorldEdit.getInstance().getEventBus().post(new PlatformReadyEvent());
|
|
|
|
|
minecraftServer.reloadResources(
|
|
|
|
|
minecraftServer.getDataPackManager().getEnabledNames()
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void onStopServer(MinecraftServer minecraftServer) {
|
|
|
|
|
@@ -198,8 +250,9 @@ public class FabricWorldEdit implements ModInitializer {
|
|
|
|
|
blockPos.getY(),
|
|
|
|
|
blockPos.getZ()
|
|
|
|
|
);
|
|
|
|
|
com.sk89q.worldedit.util.Direction weDirection = FabricAdapter.adaptEnumFacing(direction);
|
|
|
|
|
|
|
|
|
|
if (we.handleBlockLeftClick(player, pos)) {
|
|
|
|
|
if (we.handleBlockLeftClick(player, pos, weDirection)) {
|
|
|
|
|
return ActionResult.SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -210,12 +263,6 @@ public class FabricWorldEdit implements ModInitializer {
|
|
|
|
|
return ActionResult.PASS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void onLeftClickAir(PlayerEntity playerEntity, World world, Hand hand) {
|
|
|
|
|
WorldEdit we = WorldEdit.getInstance();
|
|
|
|
|
FabricPlayer player = adaptPlayer((ServerPlayerEntity) playerEntity);
|
|
|
|
|
we.handleArmSwing(player);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private ActionResult onRightClickBlock(PlayerEntity playerEntity, World world, Hand hand, BlockHitResult blockHitResult) {
|
|
|
|
|
if (shouldSkip() || hand == Hand.OFF_HAND || world.isClient) {
|
|
|
|
|
return ActionResult.PASS;
|
|
|
|
|
@@ -229,8 +276,9 @@ public class FabricWorldEdit implements ModInitializer {
|
|
|
|
|
blockHitResult.getBlockPos().getY(),
|
|
|
|
|
blockHitResult.getBlockPos().getZ()
|
|
|
|
|
);
|
|
|
|
|
com.sk89q.worldedit.util.Direction direction = FabricAdapter.adaptEnumFacing(blockHitResult.getSide());
|
|
|
|
|
|
|
|
|
|
if (we.handleBlockRightClick(player, pos)) {
|
|
|
|
|
if (we.handleBlockRightClick(player, pos, direction)) {
|
|
|
|
|
return ActionResult.SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -241,23 +289,29 @@ public class FabricWorldEdit implements ModInitializer {
|
|
|
|
|
return ActionResult.PASS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private ActionResult onRightClickAir(PlayerEntity playerEntity, World world, Hand hand) {
|
|
|
|
|
private TypedActionResult<ItemStack> onRightClickAir(PlayerEntity playerEntity, World world, Hand hand) {
|
|
|
|
|
ItemStack stackInHand = playerEntity.getStackInHand(hand);
|
|
|
|
|
if (shouldSkip() || hand == Hand.OFF_HAND || world.isClient) {
|
|
|
|
|
return ActionResult.PASS;
|
|
|
|
|
return TypedActionResult.pass(stackInHand);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
WorldEdit we = WorldEdit.getInstance();
|
|
|
|
|
FabricPlayer player = adaptPlayer((ServerPlayerEntity) playerEntity);
|
|
|
|
|
|
|
|
|
|
if (we.handleRightClick(player)) {
|
|
|
|
|
return ActionResult.SUCCESS;
|
|
|
|
|
return TypedActionResult.success(stackInHand);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ActionResult.PASS;
|
|
|
|
|
return TypedActionResult.pass(stackInHand);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// TODO Pass empty left click to server
|
|
|
|
|
|
|
|
|
|
private void onPlayerDisconnect(ServerPlayNetworkHandler handler, MinecraftServer server) {
|
|
|
|
|
WorldEdit.getInstance().getEventBus()
|
|
|
|
|
.post(new SessionIdleEvent(new FabricPlayer.SessionKeyImpl(handler.player)));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get the configuration.
|
|
|
|
|
*
|
|
|
|
|
@@ -303,8 +357,8 @@ public class FabricWorldEdit implements ModInitializer {
|
|
|
|
|
*
|
|
|
|
|
* @return the working directory
|
|
|
|
|
*/
|
|
|
|
|
public File getWorkingDir() {
|
|
|
|
|
return this.workingDir.toFile();
|
|
|
|
|
public Path getWorkingDir() {
|
|
|
|
|
return this.workingDir;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|