PageRenderTime 28ms CodeModel.GetById 9ms app.highlight 15ms RepoModel.GetById 1ms app.codeStats 0ms

/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgeWorldEdit.java

http://github.com/sk89q/worldedit
Java | 353 lines | 243 code | 46 blank | 64 comment | 50 complexity | 74a38150331467a7e7718e53c77eeefc MD5 | raw file
  1/*
  2 * WorldEdit, a Minecraft world manipulation toolkit
  3 * Copyright (C) sk89q <http://www.sk89q.com>
  4 * Copyright (C) WorldEdit team and contributors
  5 *
  6 * This program is free software: you can redistribute it and/or modify it
  7 * under the terms of the GNU Lesser General Public License as published by the
  8 * Free Software Foundation, either version 3 of the License, or
  9 * (at your option) any later version.
 10 *
 11 * This program is distributed in the hope that it will be useful, but WITHOUT
 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
 14 * for more details.
 15 *
 16 * You should have received a copy of the GNU Lesser General Public License
 17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 18 */
 19
 20package com.sk89q.worldedit.forge;
 21
 22import com.mojang.brigadier.ParseResults;
 23import com.mojang.brigadier.exceptions.CommandSyntaxException;
 24import com.sk89q.worldedit.LocalSession;
 25import com.sk89q.worldedit.WorldEdit;
 26import com.sk89q.worldedit.event.platform.PlatformReadyEvent;
 27import com.sk89q.worldedit.extension.platform.Platform;
 28import com.sk89q.worldedit.forge.net.handler.InternalPacketHandler;
 29import com.sk89q.worldedit.forge.net.handler.WECUIPacketHandler;
 30import com.sk89q.worldedit.forge.net.packet.LeftClickAirEventMessage;
 31import com.sk89q.worldedit.forge.proxy.ClientProxy;
 32import com.sk89q.worldedit.forge.proxy.CommonProxy;
 33import com.sk89q.worldedit.forge.proxy.ServerProxy;
 34import com.sk89q.worldedit.internal.anvil.ChunkDeleter;
 35import com.sk89q.worldedit.util.Location;
 36import com.sk89q.worldedit.world.biome.BiomeType;
 37import com.sk89q.worldedit.world.block.BlockCategory;
 38import com.sk89q.worldedit.world.block.BlockType;
 39import com.sk89q.worldedit.world.entity.EntityType;
 40import com.sk89q.worldedit.world.item.ItemCategory;
 41import com.sk89q.worldedit.world.item.ItemType;
 42import net.minecraft.command.CommandSource;
 43import net.minecraft.entity.player.ServerPlayerEntity;
 44import net.minecraft.tags.BlockTags;
 45import net.minecraft.tags.ItemTags;
 46import net.minecraft.util.Hand;
 47import net.minecraft.util.ResourceLocation;
 48import net.minecraft.world.World;
 49import net.minecraftforge.common.MinecraftForge;
 50import net.minecraftforge.event.CommandEvent;
 51import net.minecraftforge.event.entity.player.PlayerInteractEvent;
 52import net.minecraftforge.event.entity.player.PlayerInteractEvent.LeftClickEmpty;
 53import net.minecraftforge.eventbus.api.Event;
 54import net.minecraftforge.eventbus.api.IEventBus;
 55import net.minecraftforge.eventbus.api.SubscribeEvent;
 56import net.minecraftforge.fml.DistExecutor;
 57import net.minecraftforge.fml.ModContainer;
 58import net.minecraftforge.fml.ModLoadingContext;
 59import net.minecraftforge.fml.common.Mod;
 60import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
 61import net.minecraftforge.fml.event.server.FMLServerAboutToStartEvent;
 62import net.minecraftforge.fml.event.server.FMLServerStartedEvent;
 63import net.minecraftforge.fml.event.server.FMLServerStoppingEvent;
 64import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
 65import net.minecraftforge.fml.loading.FMLPaths;
 66import net.minecraftforge.registries.ForgeRegistries;
 67import org.apache.logging.log4j.LogManager;
 68import org.apache.logging.log4j.Logger;
 69
 70import java.io.File;
 71import java.io.IOException;
 72import java.io.UncheckedIOException;
 73import java.nio.file.Files;
 74import java.nio.file.Path;
 75
 76import static com.google.common.base.Preconditions.checkNotNull;
 77import static com.sk89q.worldedit.forge.ForgeAdapter.adaptPlayer;
 78import static com.sk89q.worldedit.internal.anvil.ChunkDeleter.DELCHUNKS_FILE_NAME;
 79
 80/**
 81 * The Forge implementation of WorldEdit.
 82 */
 83@Mod(ForgeWorldEdit.MOD_ID)
 84public class ForgeWorldEdit {
 85
 86    private static final Logger LOGGER = LogManager.getLogger();
 87    public static final String MOD_ID = "worldedit";
 88    public static final String CUI_PLUGIN_CHANNEL = "cui";
 89
 90    private ForgePermissionsProvider provider;
 91
 92    public static ForgeWorldEdit inst;
 93
 94    public static CommonProxy proxy = DistExecutor.runForDist(() -> ClientProxy::new, () -> ServerProxy::new);
 95
 96    private ForgePlatform platform;
 97    private ForgeConfiguration config;
 98    private Path workingDir;
 99
100    private ModContainer container;
101
102    public ForgeWorldEdit() {
103        inst = this;
104
105        IEventBus modBus = FMLJavaModLoadingContext.get().getModEventBus();
106        modBus.addListener(this::init);
107
108        MinecraftForge.EVENT_BUS.register(ThreadSafeCache.getInstance());
109        MinecraftForge.EVENT_BUS.register(this);
110    }
111
112    private void init(FMLCommonSetupEvent event) {
113        this.container = ModLoadingContext.get().getActiveContainer();
114
115        // Setup working directory
116        workingDir = FMLPaths.CONFIGDIR.get().resolve("worldedit");
117        if (!Files.exists(workingDir)) {
118            try {
119                Files.createDirectory(workingDir);
120            } catch (IOException e) {
121                throw new UncheckedIOException(e);
122            }
123        }
124
125        WECUIPacketHandler.init();
126        InternalPacketHandler.init();
127        proxy.registerHandlers();
128
129        LOGGER.info("WorldEdit for Forge (version " + getInternalVersion() + ") is loaded");
130    }
131
132    private void setupPlatform() {
133        this.platform = new ForgePlatform(this);
134
135        WorldEdit.getInstance().getPlatformManager().register(platform);
136
137//  TODO      if (ModList.get().isLoaded("sponge")) {
138//            this.provider = new ForgePermissionsProvider.SpongePermissionsProvider();
139//        } else {
140        this.provider = new ForgePermissionsProvider.VanillaPermissionsProvider(platform);
141//        }
142    }
143
144    private void setupRegistries() {
145        // Blocks
146        for (ResourceLocation name : ForgeRegistries.BLOCKS.getKeys()) {
147            if (BlockType.REGISTRY.get(name.toString()) == null) {
148                BlockType.REGISTRY.register(name.toString(), new BlockType(name.toString(),
149                    input -> ForgeAdapter.adapt(ForgeAdapter.adapt(input.getBlockType()).getDefaultState())));
150            }
151        }
152        // Items
153        for (ResourceLocation name : ForgeRegistries.ITEMS.getKeys()) {
154            if (ItemType.REGISTRY.get(name.toString()) == null) {
155                ItemType.REGISTRY.register(name.toString(), new ItemType(name.toString()));
156            }
157        }
158        // Entities
159        for (ResourceLocation name : ForgeRegistries.ENTITIES.getKeys()) {
160            if (EntityType.REGISTRY.get(name.toString()) == null) {
161                EntityType.REGISTRY.register(name.toString(), new EntityType(name.toString()));
162            }
163        }
164        // Biomes
165        for (ResourceLocation name : ForgeRegistries.BIOMES.getKeys()) {
166            if (BiomeType.REGISTRY.get(name.toString()) == null) {
167                BiomeType.REGISTRY.register(name.toString(), new BiomeType(name.toString()));
168            }
169        }
170        // Tags
171        for (ResourceLocation name : BlockTags.getCollection().getRegisteredTags()) {
172            if (BlockCategory.REGISTRY.get(name.toString()) == null) {
173                BlockCategory.REGISTRY.register(name.toString(), new BlockCategory(name.toString()));
174            }
175        }
176        for (ResourceLocation name : ItemTags.getCollection().getRegisteredTags()) {
177            if (ItemCategory.REGISTRY.get(name.toString()) == null) {
178                ItemCategory.REGISTRY.register(name.toString(), new ItemCategory(name.toString()));
179            }
180        }
181    }
182
183    @SubscribeEvent
184    public void serverAboutToStart(FMLServerAboutToStartEvent event) {
185        final Path delChunks = workingDir.resolve(DELCHUNKS_FILE_NAME);
186        if (Files.exists(delChunks)) {
187            ChunkDeleter.runFromFile(delChunks, true);
188        }
189    }
190
191    @SubscribeEvent
192    public void serverStopping(FMLServerStoppingEvent event) {
193        WorldEdit worldEdit = WorldEdit.getInstance();
194        worldEdit.getSessionManager().unload();
195        worldEdit.getPlatformManager().unregister(platform);
196    }
197
198    @SubscribeEvent
199    public void serverStarted(FMLServerStartedEvent event) {
200        setupPlatform();
201        setupRegistries();
202
203        config = new ForgeConfiguration(this);
204        config.load();
205        WorldEdit.getInstance().getEventBus().post(new PlatformReadyEvent());
206    }
207
208    @SubscribeEvent
209    public void onPlayerInteract(PlayerInteractEvent event) {
210        if (platform == null) {
211            return;
212        }
213
214        if (!platform.isHookingEvents())
215            return; // We have to be told to catch these events
216
217        if (event.getWorld().isRemote && event instanceof LeftClickEmpty) {
218            // catch LCE, pass it to server
219            InternalPacketHandler.getHandler().sendToServer(new LeftClickAirEventMessage());
220            return;
221        }
222
223        boolean isLeftDeny = event instanceof PlayerInteractEvent.LeftClickBlock
224                && ((PlayerInteractEvent.LeftClickBlock) event)
225                        .getUseItem() == Event.Result.DENY;
226        boolean isRightDeny =
227                event instanceof PlayerInteractEvent.RightClickBlock
228                        && ((PlayerInteractEvent.RightClickBlock) event)
229                                .getUseItem() == Event.Result.DENY;
230        if (isLeftDeny || isRightDeny || event.getEntity().world.isRemote || event.getHand() == Hand.OFF_HAND) {
231            return;
232        }
233
234        WorldEdit we = WorldEdit.getInstance();
235        ForgePlayer player = adaptPlayer((ServerPlayerEntity) event.getPlayer());
236        ForgeWorld world = getWorld(event.getPlayer().world);
237
238        if (event instanceof PlayerInteractEvent.LeftClickEmpty) {
239            we.handleArmSwing(player); // this event cannot be canceled
240        } else if (event instanceof PlayerInteractEvent.LeftClickBlock) {
241            Location pos = new Location(world, event.getPos().getX(), event.getPos().getY(), event.getPos().getZ());
242
243            if (we.handleBlockLeftClick(player, pos)) {
244                event.setCanceled(true);
245            }
246
247            if (we.handleArmSwing(player)) {
248                event.setCanceled(true);
249            }
250        } else if (event instanceof PlayerInteractEvent.RightClickBlock) {
251            Location pos = new Location(world, event.getPos().getX(), event.getPos().getY(), event.getPos().getZ());
252
253            if (we.handleBlockRightClick(player, pos)) {
254                event.setCanceled(true);
255            }
256
257            if (we.handleRightClick(player)) {
258                event.setCanceled(true);
259            }
260        } else if (event instanceof PlayerInteractEvent.RightClickItem) {
261            if (we.handleRightClick(player)) {
262                event.setCanceled(true);
263            }
264        }
265    }
266
267    @SubscribeEvent
268    public void onCommandEvent(CommandEvent event) throws CommandSyntaxException {
269        ParseResults<CommandSource> parseResults = event.getParseResults();
270        if (!(parseResults.getContext().getSource().getEntity() instanceof ServerPlayerEntity)) {
271            return;
272        }
273        ServerPlayerEntity player = parseResults.getContext().getSource().asPlayer();
274        if (player.world.isRemote()) {
275            return;
276        }
277        if (parseResults.getContext().getCommand() != CommandWrapper.FAKE_COMMAND) {
278            return;
279        }
280        event.setCanceled(true);
281        WorldEdit.getInstance().getEventBus().post(new com.sk89q.worldedit.event.platform.CommandEvent(
282            adaptPlayer(parseResults.getContext().getSource().asPlayer()),
283            parseResults.getReader().getString()
284        ));
285    }
286
287    /**
288     * Get the configuration.
289     *
290     * @return the Forge configuration
291     */
292    ForgeConfiguration getConfig() {
293        return this.config;
294    }
295
296    /**
297     * Get the session for a player.
298     *
299     * @param player the player
300     * @return the session
301     */
302    public LocalSession getSession(ServerPlayerEntity player) {
303        checkNotNull(player);
304        return WorldEdit.getInstance().getSessionManager().get(adaptPlayer(player));
305    }
306
307    /**
308     * Get the WorldEdit proxy for the given world.
309     *
310     * @param world the world
311     * @return the WorldEdit world
312     */
313    public ForgeWorld getWorld(World world) {
314        checkNotNull(world);
315        return new ForgeWorld(world);
316    }
317
318    /**
319     * Get the WorldEdit proxy for the platform.
320     *
321     * @return the WorldEdit platform
322     */
323    public Platform getPlatform() {
324        return this.platform;
325    }
326
327    /**
328     * Get the working directory where WorldEdit's files are stored.
329     *
330     * @return the working directory
331     */
332    public File getWorkingDir() {
333        return this.workingDir.toFile();
334    }
335
336    /**
337     * Get the version of the WorldEdit-for-Forge implementation.
338     *
339     * @return a version string
340     */
341    String getInternalVersion() {
342        return container.getModInfo().getVersion().toString();
343    }
344
345    public void setPermissionsProvider(ForgePermissionsProvider provider) {
346        this.provider = provider;
347    }
348
349    public ForgePermissionsProvider getPermissionsProvider() {
350        return provider;
351    }
352
353}