/* * CraftBook Copyright (C) 2010-2017 sk89q <http://www.sk89q.com> * CraftBook Copyright (C) 2011-2017 me4502 <http://www.me4502.com> * CraftBook Copyright (C) Contributors * * This program is free software: you can redistribute it and/or modify it under the terms of the GNU 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 General Public License for more details. * * You should have received a copy of the GNU General Public License along with this program. If not, * see <http://www.gnu.org/licenses/>. */ package com.sk89q.craftbook.sponge.mechanics; import com.google.common.reflect.TypeToken; import com.google.inject.Inject; import com.me4502.modularframework.module.Module; import com.me4502.modularframework.module.guice.ModuleConfiguration; import com.sk89q.craftbook.core.util.ConfigValue; import com.sk89q.craftbook.core.util.CraftBookException; import com.sk89q.craftbook.core.util.PermissionNode; import com.sk89q.craftbook.core.util.RegexUtil; import com.sk89q.craftbook.core.util.documentation.DocumentationProvider; import com.sk89q.craftbook.sponge.mechanics.types.SpongeSignMechanic; import com.sk89q.craftbook.sponge.util.SignUtil; import com.sk89q.craftbook.sponge.util.SpongePermissionNode; import ninja.leaping.configurate.ConfigurationNode; import org.spongepowered.api.Sponge; import org.spongepowered.api.block.BlockTypes; import org.spongepowered.api.block.tileentity.Sign; import org.spongepowered.api.entity.living.player.Player; import org.spongepowered.api.event.Listener; import org.spongepowered.api.event.block.InteractBlockEvent; import org.spongepowered.api.event.cause.NamedCause; import org.spongepowered.api.event.filter.cause.Named; import org.spongepowered.api.service.permission.PermissionDescription; import org.spongepowered.api.text.Text; import org.spongepowered.api.text.format.TextColors; import org.spongepowered.api.util.Direction; import org.spongepowered.api.world.Location; import org.spongepowered.api.world.World; import java.util.List; import javax.annotation.Nullable; @Module(id = "teleporter", name = "Teleporter", onEnable="onInitialize", onDisable="onDisable") public class Teleporter extends SpongeSignMechanic implements DocumentationProvider { @Inject @ModuleConfiguration public ConfigurationNode config; private ConfigValue<Boolean> allowButtons = new ConfigValue<>("allow-buttons", "Allow teleporters to be controlled by buttons opposite the sign.", true); private ConfigValue<Boolean> requireSign = new ConfigValue<>("require-sign", "Require a teleport sign at the destination.", true); private ConfigValue<Double> maxRange = new ConfigValue<>("max-range", "The max range of the teleport, or -1 for infinite.", -1d, TypeToken.of(Double.class)); private SpongePermissionNode createPermissions = new SpongePermissionNode("craftbook.teleporter", "Allows the user to create Teleporters", PermissionDescription.ROLE_STAFF); private SpongePermissionNode usePermissions = new SpongePermissionNode("craftbook.teleporter.use", "Allows the user to use Teleporters", PermissionDescription.ROLE_USER); @Override public void onInitialize() throws CraftBookException { super.onInitialize(); allowButtons.load(config); requireSign.load(config); maxRange.load(config); createPermissions.register(); usePermissions.register(); } @SuppressWarnings("ResultOfMethodCallIgnored") @Override public boolean verifyLines(Location<World> location, List<Text> lines, @Nullable Player player) { String line3Raw = SignUtil.getTextRaw(lines.get(2)); if (line3Raw.trim().isEmpty() || line3Raw.equalsIgnoreCase("ARRIVAL")) { lines.set(2, Text.of("ARRIVAL")); } else { String[] pos = RegexUtil.COLON_PATTERN.split(line3Raw); if (pos.length <= 2) { if (player != null) { player.sendMessage(Text.of("mech.teleport.invalidcoords")); } return false; } else { try { Double.parseDouble(pos[0]); Double.parseDouble(pos[1]); Double.parseDouble(pos[2]); } catch (NumberFormatException e) { if (player != null) { player.sendMessage(Text.of("mech.teleport.invalidcoords")); } return false; } } } return super.verifyLines(location, lines, player); } @Listener public void onPlayerInteract(InteractBlockEvent.Secondary.MainHand event, @Named(NamedCause.SOURCE) Player player) { event.getTargetBlock().getLocation().ifPresent((location) -> { Location<World> signLocation = location; if (allowButtons.getValue() && signLocation.getBlockType() == BlockTypes.STONE_BUTTON || signLocation.getBlockType() == BlockTypes.WOODEN_BUTTON) { Direction backDir = SignUtil.getBack(signLocation); signLocation = signLocation.getRelative(backDir).getRelative(backDir); } if (SignUtil.isSign(signLocation)) { Sign sign = (Sign) signLocation.getTileEntity().get(); if (isMechanicSign(sign)) { if (!usePermissions.hasPermission(player)) { player.sendMessage(Text.of(TextColors.RED, "You don't have permission to use this mechanic!")); return; } String destinationTest = SignUtil.getTextRaw(sign, 2); if (destinationTest.equals("ARRIVAL")) { player.sendMessage(Text.of("You can only arrive here.")); return; } String[] pos = RegexUtil.COLON_PATTERN.split(destinationTest); if (pos.length <= 2) { player.sendMessage(Text.of("mech.teleport.invalidcoords")); return; } double x, y, z; try { x = Double.parseDouble(pos[0]); y= Double.parseDouble(pos[1]); z = Double.parseDouble(pos[2]); } catch(NumberFormatException e) { player.sendMessage(Text.of("mech.teleport.invalidcoords")); return; } Location<World> destinationLocation = signLocation.getExtent().getLocation(x, y, z); if (requireSign.getValue() && !(SignUtil.isSign(destinationLocation) && isMechanicSign((Sign) destinationLocation.getTileEntity().get()))) { player.sendMessage(Text.of("Missing sign at destination.")); return; } if (maxRange.getValue() >= 0 && destinationLocation.getPosition().distanceSquared(signLocation.getPosition()) > maxRange.getValue() * maxRange.getValue()) { player.sendMessage(Text.of("Destination too far away.")); return; } Location<World> safeLocation = Sponge.getGame().getTeleportHelper().getSafeLocation(destinationLocation).orElse(null); if (safeLocation != null) { player.setLocation(safeLocation); String destinationName = SignUtil.getTextRaw(sign, 0); if (destinationName.isEmpty()) { player.sendMessage(Text.of("You've teleported.")); } else { player.sendMessage(Text.of("You are now at " + destinationName)); } } else { player.sendMessage(Text.of("Destination Obstructed")); } } } }); } @Override public String[] getValidSigns() { return new String[]{ "[Teleporter]" }; } @Override public SpongePermissionNode getCreatePermission() { return createPermissions; } @Override public String getPath() { return "mechanics/teleporter"; } @Override public PermissionNode[] getPermissionNodes() { return new PermissionNode[] { createPermissions, usePermissions }; } @Override public ConfigValue<?>[] getConfigurationNodes() { return new ConfigValue[] { allowButtons, requireSign, maxRange }; } }