├── .gitattributes ├── src └── main │ ├── java │ └── net │ │ └── poweredbyhate │ │ └── wildtp │ │ ├── PostWildTeleportEvent.java │ │ ├── BlurredBlockBreakEvent.java │ │ ├── CNNListener.java │ │ ├── NoobieListener.java │ │ ├── CodeACertainBallWillStealEvent.java │ │ ├── PreWildTeleportEvent.java │ │ ├── OuchieListener.java │ │ ├── WildTPListener.java │ │ ├── GeeYouEye.java │ │ ├── TooCool2Teleport.java │ │ ├── WildSignListener.java │ │ ├── ChecKar.java │ │ ├── AdminsGoneWild.java │ │ ├── WildWarrantTax.java │ │ ├── TooWildForEnums.java │ │ ├── CommandsGoneWild.java │ │ ├── WildTP.java │ │ ├── WorldConfig.java │ │ ├── TeleportGoneWild.java │ │ ├── PortalzGoneWild.java │ │ └── Metricsa.java │ └── resources │ ├── plugin.yml │ └── config.yml ├── .gitignore ├── appveyor.yml ├── README.md ├── pom.xml ├── docs ├── index.html └── old.bbcode └── LICENSE.md /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | *.sln merge=union 7 | *.csproj merge=union 8 | *.vbproj merge=union 9 | *.fsproj merge=union 10 | *.dbproj merge=union 11 | 12 | # Standard to msysgit 13 | *.doc diff=astextplain 14 | *.DOC diff=astextplain 15 | *.docx diff=astextplain 16 | *.DOCX diff=astextplain 17 | *.dot diff=astextplain 18 | *.DOT diff=astextplain 19 | *.pdf diff=astextplain 20 | *.PDF diff=astextplain 21 | *.rtf diff=astextplain 22 | *.RTF diff=astextplain 23 | -------------------------------------------------------------------------------- /src/main/java/net/poweredbyhate/wildtp/PostWildTeleportEvent.java: -------------------------------------------------------------------------------- 1 | package net.poweredbyhate.wildtp; 2 | 3 | import org.bukkit.entity.Player; 4 | import org.bukkit.event.Event; 5 | import org.bukkit.event.HandlerList; 6 | 7 | /** 8 | * Created by Lax on 5/9/2016. 9 | */ 10 | public class PostWildTeleportEvent extends Event { 11 | private static final HandlerList panHandlers = new HandlerList(); 12 | 13 | Player wildLing; 14 | WorldConfig wc; 15 | 16 | public PostWildTeleportEvent(Player p, WorldConfig c) { 17 | wildLing = p; 18 | wc = c; 19 | } 20 | 21 | @Override 22 | public HandlerList getHandlers() { 23 | return panHandlers; 24 | } 25 | 26 | public static HandlerList getHandlerList() { 27 | return panHandlers; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/net/poweredbyhate/wildtp/BlurredBlockBreakEvent.java: -------------------------------------------------------------------------------- 1 | package net.poweredbyhate.wildtp; 2 | 3 | import org.bukkit.block.Block; 4 | import org.bukkit.entity.Player; 5 | import org.bukkit.event.Cancellable; 6 | import org.bukkit.event.block.BlockBreakEvent; 7 | 8 | /** 9 | * Created on 7/9/2017. 10 | * 11 | * "My camera don't focus on fake" 12 | * 13 | * @author RoboMWM 14 | */ 15 | public class BlurredBlockBreakEvent extends BlockBreakEvent implements Cancellable 16 | { 17 | private boolean exposed = false; 18 | BlurredBlockBreakEvent(Block theBlock, Player player) 19 | { 20 | super(theBlock, player); 21 | } 22 | 23 | public void setExposed(boolean exposed) 24 | { 25 | this.exposed = exposed; 26 | } 27 | 28 | public boolean isExposed() 29 | { 30 | return exposed; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/net/poweredbyhate/wildtp/CNNListener.java: -------------------------------------------------------------------------------- 1 | package net.poweredbyhate.wildtp; 2 | 3 | import org.bukkit.event.EventHandler; 4 | import org.bukkit.event.EventPriority; 5 | import org.bukkit.event.Listener; 6 | 7 | /** 8 | * Created on 7/9/2017. 9 | * 10 | * The trustworthy and truthful CNN 11 | * https://twitter.com/theblaze/status/882758680327966721 12 | * 13 | * @author RoboMWM 14 | */ 15 | public class CNNListener implements Listener 16 | { 17 | @EventHandler(priority = EventPriority.HIGH) 18 | void russia(BlurredBlockBreakEvent event) 19 | { 20 | event.setExposed(event.isCancelled()); 21 | event.setCancelled(true); 22 | } 23 | @EventHandler(priority = EventPriority.HIGH) 24 | void blaseyFord(CodeACertainBallWillStealEvent event) 25 | { 26 | event.setExposed(event.isCancelled()); 27 | event.setCancelled(true); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/net/poweredbyhate/wildtp/NoobieListener.java: -------------------------------------------------------------------------------- 1 | package net.poweredbyhate.wildtp; 2 | 3 | import static net.poweredbyhate.wildtp.WildTP.instace; 4 | import org.bukkit.entity.Player; 5 | import org.bukkit.event.EventHandler; 6 | import org.bukkit.event.Listener; 7 | import org.bukkit.event.player.PlayerJoinEvent; 8 | import org.bukkit.scheduler.BukkitRunnable; 9 | import net.poweredbyhate.wildtp.TeleportGoneWild.Trigger; 10 | 11 | /** 12 | * Created on 7/9/2017. 13 | * 14 | * @author RoboMWM 15 | */ 16 | public class NoobieListener implements Listener { 17 | @EventHandler 18 | private void onNewbJoin(final PlayerJoinEvent event) { 19 | final Player p = event.getPlayer(); 20 | if (p.hasPlayedBefore()) return; 21 | 22 | new BukkitRunnable() { 23 | @Override 24 | public void run() { 25 | new TeleportGoneWild(Trigger.JOIN, p).WildTeleport(); 26 | } 27 | }.runTaskLater(instace, 1L); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/net/poweredbyhate/wildtp/CodeACertainBallWillStealEvent.java: -------------------------------------------------------------------------------- 1 | package net.poweredbyhate.wildtp; 2 | 3 | import org.bukkit.Location; 4 | import org.bukkit.Material; 5 | import org.bukkit.block.BlockFace; 6 | import org.bukkit.entity.Player; 7 | import org.bukkit.event.block.BlockPlaceEvent; 8 | import org.bukkit.inventory.EquipmentSlot; 9 | import org.bukkit.inventory.ItemStack; 10 | 11 | /** 12 | * Created on 10/8/2018. 13 | * 14 | * "I was here first" 15 | * 16 | * @author RoboMWM 17 | */ 18 | public class CodeACertainBallWillStealEvent extends BlockPlaceEvent 19 | { 20 | private boolean qballNoSwiping; 21 | public CodeACertainBallWillStealEvent(Location page, Player player) 22 | { 23 | super(page.getBlock(), page.getBlock().getState(), page.getBlock().getRelative(BlockFace.DOWN), new ItemStack(Material.AIR), new JohnBonifield(player), false, EquipmentSlot.OFF_HAND); 24 | } 25 | 26 | public void setExposed(boolean exposed) 27 | { 28 | this.qballNoSwiping = exposed; 29 | } 30 | 31 | public boolean isExposed() 32 | { 33 | return qballNoSwiping; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | *.iml 3 | target/ 4 | *.class 5 | 6 | # Mobile Tools for Java (J2ME) 7 | .mtj.tmp/ 8 | 9 | # Package Files # 10 | *.jar 11 | *.war 12 | *.ear 13 | 14 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 15 | hs_err_pid* 16 | 17 | # ========================= 18 | # Operating System Files 19 | # ========================= 20 | 21 | # OSX 22 | # ========================= 23 | 24 | .DS_Store 25 | .AppleDouble 26 | .LSOverride 27 | 28 | # Icon must end with two \r 29 | Icon 30 | 31 | # Thumbnails 32 | ._* 33 | 34 | # Files that might appear on external disk 35 | .Spotlight-V100 36 | .Trashes 37 | 38 | # Directories potentially created on remote AFP share 39 | .AppleDB 40 | .AppleDesktop 41 | Network Trash Folder 42 | Temporary Items 43 | .apdisk 44 | 45 | # Windows 46 | # ========================= 47 | 48 | # Windows image file caches 49 | Thumbs.db 50 | ehthumbs.db 51 | 52 | # Folder config file 53 | Desktop.ini 54 | 55 | # Recycle Bin used on file shares 56 | $RECYCLE.BIN/ 57 | 58 | # Windows Installer files 59 | *.cab 60 | *.msi 61 | *.msm 62 | *.msp 63 | !lib/GriefPrevention.jar 64 | .classpath 65 | .project 66 | .settings -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | version: '{build}' 2 | skip_tags: true 3 | clone_depth: 10 4 | environment: 5 | matrix: 6 | - JAVA_HOME: C:\Program Files\Java\jdk1.8.0 7 | branches: 8 | only: 9 | - master 10 | except: 11 | - gh-pages 12 | os: Windows Server 2012 13 | install: 14 | - ps: | 15 | Add-Type -AssemblyName System.IO.Compression.FileSystem 16 | if (!(Test-Path -Path "C:\maven" )) { 17 | (new-object System.Net.WebClient).DownloadFile('http://www.us.apache.org/dist/maven/maven-3/3.2.5/binaries/apache-maven-3.2.5-bin.zip', 'C:\maven-bin.zip') 18 | [System.IO.Compression.ZipFile]::ExtractToDirectory("C:\maven-bin.zip", "C:\maven") 19 | } 20 | - cmd: SET PATH=C:\maven\apache-maven-3.2.5\bin;%JAVA_HOME%\bin;%PATH:C:\Ruby193\bin;=% 21 | - cmd: SET MAVEN_OPTS=-XX:MaxPermSize=2g -Xmx4g 22 | - cmd: SET JAVA_OPTS=-XX:MaxPermSize=2g -Xmx4g 23 | - cmd: SET M2_HOME=C:\maven\apache-maven-3.2.5 24 | - cmd: mvn --version 25 | - cmd: java -version 26 | build_script: 27 | - mvn clean package -B -Dmaven.test.skip=true 28 | test_script: 29 | - mvn clean install --batch-mode -Pqulice 30 | cache: 31 | - C:\maven\ 32 | - C:\Users\appveyor\.m2 33 | artifacts: 34 | - path: target/WildTP.jar 35 | name: WildTP -------------------------------------------------------------------------------- /src/main/java/net/poweredbyhate/wildtp/PreWildTeleportEvent.java: -------------------------------------------------------------------------------- 1 | package net.poweredbyhate.wildtp; 2 | 3 | import org.bukkit.Location; 4 | import org.bukkit.entity.Player; 5 | import org.bukkit.event.Cancellable; 6 | import org.bukkit.event.Event; 7 | import org.bukkit.event.HandlerList; 8 | import net.poweredbyhate.wildtp.TeleportGoneWild.Trigger; 9 | 10 | /** 11 | * Created by John on 5/10/2016. 12 | */ 13 | public class PreWildTeleportEvent extends Event implements Cancellable { 14 | private boolean cancelled = false; 15 | 16 | private static final HandlerList panHandlers = new HandlerList(); 17 | 18 | Location locoLocation; 19 | Player wildLing; 20 | Trigger brush; 21 | WorldConfig wc; 22 | 23 | public PreWildTeleportEvent(Player p, Location location, WorldConfig c, Trigger t) { 24 | wildLing = p; 25 | locoLocation = location; 26 | brush = t; 27 | wc = c; 28 | } 29 | 30 | @Override 31 | public HandlerList getHandlers() { 32 | return panHandlers; 33 | } 34 | 35 | public static HandlerList getHandlerList() { 36 | return panHandlers; 37 | } 38 | 39 | @Override 40 | public boolean isCancelled() { 41 | return cancelled; 42 | } 43 | 44 | @Override 45 | public void setCancelled(boolean b) { 46 | this.cancelled = b; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/net/poweredbyhate/wildtp/OuchieListener.java: -------------------------------------------------------------------------------- 1 | package net.poweredbyhate.wildtp; 2 | 3 | import java.util.HashMap; 4 | import java.util.UUID; 5 | import org.bukkit.Bukkit; 6 | import org.bukkit.entity.Player; 7 | import org.bukkit.event.EventHandler; 8 | import org.bukkit.event.Listener; 9 | import org.bukkit.event.entity.EntityDamageEvent; 10 | 11 | /** 12 | * Created by RoboMWM on 5/15/2016. 13 | */ 14 | public class OuchieListener implements Listener { 15 | private static HashMap dr0pp3dPuhlayars = new HashMap(); 16 | 17 | @EventHandler(ignoreCancelled = true) 18 | private void onPlayerTryingToBreakLegs(EntityDamageEvent ouch) { 19 | if (!(ouch.getEntity() instanceof Player) || ouch.getCause() != EntityDamageEvent.DamageCause.FALL) return; 20 | 21 | UUID id = ouch.getEntity().getUniqueId(); 22 | 23 | if (dr0pp3dPuhlayars.containsKey(id)) { 24 | Bukkit.getScheduler().cancelTask(dr0pp3dPuhlayars.remove(id)); 25 | ouch.setCancelled(true); 26 | } 27 | } 28 | 29 | static void plsSaveDisDood(final Player player) { 30 | UUID id = player.getUniqueId(); 31 | 32 | TooCool2Teleport.microwave(player); 33 | 34 | dr0pp3dPuhlayars.put(id, Bukkit.getScheduler().scheduleSyncDelayedTask(WildTP.instace, new Runnable() { 35 | @Override 36 | public void run() { 37 | dr0pp3dPuhlayars.remove(id); 38 | } 39 | }, 400L)); 40 | } 41 | 42 | static void doodWhrsMyCar(UUID sweet) { 43 | if (dr0pp3dPuhlayars.containsKey(sweet)) Bukkit.getScheduler().cancelTask(dr0pp3dPuhlayars.remove(sweet)); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/net/poweredbyhate/wildtp/WildTPListener.java: -------------------------------------------------------------------------------- 1 | package net.poweredbyhate.wildtp; 2 | 3 | 4 | import org.bukkit.Bukkit; 5 | import org.bukkit.Location; 6 | import org.bukkit.Sound; 7 | import org.bukkit.SoundCategory; 8 | import org.bukkit.World; 9 | import org.bukkit.entity.Player; 10 | import org.bukkit.event.EventHandler; 11 | import org.bukkit.event.Listener; 12 | import org.bukkit.event.player.PlayerQuitEvent; 13 | import net.poweredbyhate.wildtp.TeleportGoneWild.Trigger; 14 | 15 | /** 16 | * Created by John on 5/11/2016. 17 | */ 18 | public class WildTPListener implements Listener { 19 | static boolean chargePlayer(Player p, WorldConfig wc, Trigger t, boolean proceed) { 20 | if (WildTP.econ == null) return true; 21 | 22 | if (wc.cost == 0 || ChecKar.bypass("cost", p, wc, t)) return true; 23 | 24 | if (WildTP.econ.getBalance(p) < wc.cost) return false; 25 | 26 | if (proceed && !WildTP.econ.withdrawPlayer(p, wc.cost).transactionSuccess()) { 27 | p.sendMessage(TooWildForEnums.translate(TooWildForEnums.NO_MONEY)); 28 | 29 | return false; 30 | } 31 | 32 | return true; 33 | } 34 | 35 | @EventHandler 36 | private void onCoward(PlayerQuitEvent ev) { 37 | TeleportGoneWild.cure(ev.getPlayer()); 38 | } 39 | 40 | @EventHandler 41 | private void onPreTeleport(PreWildTeleportEvent ev) { 42 | if (!chargePlayer(ev.wildLing, ev.wc, ev.brush, true))ev.setCancelled(true); 43 | } 44 | 45 | @EventHandler 46 | private void onPostTele(PostWildTeleportEvent ev) { 47 | Location lok = ev.wildLing.getLocation(); 48 | World plaza = lok.getWorld(); 49 | 50 | TeleportGoneWild.cure(ev.wildLing); 51 | 52 | if (ev.wc.doCommandz) { 53 | String p = ev.wildLing.getName(), x = "" + lok.getBlockX(), z = "" + lok.getBlockZ(); 54 | 55 | for (String c : ev.wc.commando) 56 | Bukkit.dispatchCommand(Bukkit.getConsoleSender(), 57 | c.replace("%PLAYER%", p).replace("%X%", x).replace("%Z%", z)); 58 | } 59 | 60 | 61 | String sound = WildTP.instace.getConfig().getString("Sound"); 62 | if (sound == null || sound.isEmpty()) 63 | return; 64 | 65 | try 66 | { 67 | String volume = WildTP.instace.getConfig().getString("Volume"); 68 | plaza.playSound(lok, Sound.valueOf(sound), SoundCategory.MASTER, Float.parseFloat(String.valueOf(volume)), 1); 69 | WildTP.debug("Playing da sound of " + sound + " with volume or radius of " + volume); 70 | } 71 | catch (IllegalArgumentException boop) 72 | { 73 | WildTP.debug(sound + " is not a valid sound."); 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/main/java/net/poweredbyhate/wildtp/GeeYouEye.java: -------------------------------------------------------------------------------- 1 | package net.poweredbyhate.wildtp; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Arrays; 5 | import org.bukkit.Bukkit; 6 | import org.bukkit.Material; 7 | import org.bukkit.entity.Player; 8 | import org.bukkit.event.EventHandler; 9 | import org.bukkit.event.Listener; 10 | import org.bukkit.event.inventory.InventoryClickEvent; 11 | import org.bukkit.inventory.Inventory; 12 | import org.bukkit.inventory.InventoryHolder; 13 | import org.bukkit.inventory.ItemStack; 14 | import org.bukkit.inventory.meta.ItemMeta; 15 | import net.poweredbyhate.wildtp.TeleportGoneWild.Trigger; 16 | 17 | /** 18 | * Created by Lax on 5/7/2016. 19 | */ 20 | public class GeeYouEye implements Listener { 21 | void openMenu(Player p) { 22 | Inventory inv = Bukkit.createInventory(new IInventoryHolder(), 9, "&9Unnecessary Feature"); 23 | inv.setItem(4, createItem(Material.SUNFLOWER, 1, "§aWild Teleport", "Teleport to the wild!")); 24 | p.openInventory(inv); 25 | } 26 | 27 | @EventHandler 28 | private void onClick(InventoryClickEvent ev) { 29 | if (ev == null || ev.getInventory() == null || ev.getView() == null) //https://www.spigotmc.org/threads/wilderness-tp.145440/page-12#post-2394343 30 | return; 31 | 32 | if (ev.getInventory().getHolder() instanceof IInventoryHolder) 33 | { 34 | ev.setCancelled(true); 35 | 36 | if (ev.getView().getTitle().contains("Unnecessary Feature") 37 | && ev.getInventory().getItem(ev.getRawSlot()).getItemMeta().getDisplayName().toLowerCase() 38 | .contains("wild teleport")) { 39 | ev.getWhoClicked().closeInventory(); 40 | new TeleportGoneWild(Trigger.GUI, (Player) ev.getWhoClicked()).WildTeleport(); 41 | } 42 | } 43 | } 44 | 45 | private ItemStack createItem(Material material, int amount, String displayname, String lore) { 46 | ItemStack i = new ItemStack(material, amount); 47 | ItemMeta im = i.getItemMeta(); 48 | im.setDisplayName(displayname); 49 | 50 | ArrayList loreList = new ArrayList(); 51 | String[] lores = lore.split("/"); 52 | loreList.addAll(Arrays.asList(lores)); 53 | 54 | im.setLore(loreList); 55 | i.setItemMeta(im); 56 | return i; 57 | } 58 | 59 | /** 60 | * Created by Lax on 5/7/2016. 61 | * . 62 | * Converted to internal class by arboriginal on 11/10/2019, 63 | * as only used here and only one method, one instruction 64 | */ 65 | private class IInventoryHolder implements InventoryHolder { 66 | @Override 67 | public Inventory getInventory() { 68 | return Bukkit.createInventory(null, 54); 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![Wilderness-Tp](http://i.imgur.com/4eq40Xf.png) 2 | 3 | decompile it for learning purpose only 4 | 5 | pull request r free2help contribute. 6 | 7 | --- 8 | 9 | ## What is Wilderness-Tp? 10 | 11 | Wilderness-Tp (aka WildTP, or simply "wild") is a [Minecraft](https://www.minecraft.net) "RTP" (Random TelePortation) plugin for [Spigot](https://www.spigotmc.org) or [Paper](https://papermc.io) servers (paper is recommended to take advantage of lag-reducing features). It allows players to teleport them randomly in the map. 12 | 13 | **Main features:** 14 | * Compatible with all region/claim protection plugins 15 | * Random locations and worlds 16 | * Lightweight & performant 17 | * Allows to create RTP signs 18 | * Easy to use 19 | * Chuck Norris has not find any bugs in it!!! 20 | 21 | **Official plugin pages:** (where the plugin and its features are detailled) 22 | * On **Bukkit.org**: [dev.bukkit.org/projects/wildernesstp-the-one-true-wildtp](https://dev.bukkit.org/projects/wildernesstp-the-one-true-wildtp) 23 | * On **Spigot.org**: [spigotmc.org/resources/wilderness-tp.22853](https://www.spigotmc.org/resources/wilderness-tp.22853/) 24 | 25 | ## How to install? 26 | 27 | There r no dependencies, so you simply have to drop the jar file into your plugin directory, den restart ur server. 28 | A default config file will be created for you, without extra charges, into the plugins/Wild folder. 29 | 30 | ## Configuration, permissions & commands 31 | 32 | * All **configuration parameters** are explained in the online [default config.yml file](https://github.com/AcmeProject/WildernessTp/blob/master/src/main/resources/config.yml). 33 | * All **permissions** and **commands** are listed with a short description in the [plugin.yml file](https://github.com/AcmeProject/WildernessTp/blob/master/src/main/resources/plugin.yml). 34 | 35 | ## Hooks with other plugins 36 | 37 | * [GriefPrevention](https://www.spigotmc.org/resources/griefprevention.1884/) RTPs can take claims in consideration. 38 | * Works with any other claim plugin too without any hooks! 39 | * [Vault](https://www.spigotmc.org/resources/vault.34315/) RTPs can cost money. 40 | * [WorldBorder](https://www.spigotmc.org/resources/worldborder.60905/) RTPs can be bound by the world border. 41 | 42 | ## Have a question / A bug to report ? 43 | 44 | We have an [IRC channel](https://kiwiirc.com/client/irc.spi.gt/#wilderness-tp) and a [Dumcord](https://discord.gg/XjW6Kuk33g) 45 | 46 | You can discuss and ask questions about Wilderness-Tp in the [plugin thread](https://www.spigotmc.org/threads/wilderness-tp.145440/). If you find a bug, please use the [bug tracker](https://github.com/AcmeProject/WildernessTp/issues). Don't forget to give details to reproduce, your configuration, ... Also include plugin and server exact versions. 47 | 48 | ## How to contribute? 49 | 50 | As the source of this plugin is [hosted on Github](https://github.com/AcmeProject/WildernessTp), you are free to send [pull requests](https://github.com/AcmeProject/WildernessTp/pulls). 51 | 52 | **If you like the plugin, you can make a donation with this [RoboMWM Patreon](http://r.robomwm.com/patreon) link.** 53 | -------------------------------------------------------------------------------- /src/main/java/net/poweredbyhate/wildtp/TooCool2Teleport.java: -------------------------------------------------------------------------------- 1 | package net.poweredbyhate.wildtp; 2 | 3 | import static net.poweredbyhate.wildtp.WildTP.instace; 4 | import java.util.HashMap; 5 | import java.util.UUID; 6 | import org.bukkit.Location; 7 | import org.bukkit.entity.Player; 8 | import org.bukkit.event.EventHandler; 9 | import org.bukkit.event.Listener; 10 | import org.bukkit.event.player.PlayerMoveEvent; 11 | import org.bukkit.potion.PotionEffect; 12 | import org.bukkit.scheduler.BukkitRunnable; 13 | import org.bukkit.scheduler.BukkitTask; 14 | 15 | /** 16 | * Created by RoboMWM on 5/28/2016. 17 | */ 18 | public class TooCool2Teleport implements Listener { 19 | static HashMap coldPlayers = new HashMap(); 20 | static HashMap coldTaxs = new HashMap(); 21 | static HashMap boobools = new HashMap(); 22 | static HashMap sauces = new HashMap(); 23 | 24 | static void addPlayer(Player player, boolean[] tips, PotionEffect[] dishes, BukkitTask taxs) { 25 | UUID coffee = player.getUniqueId(); 26 | 27 | if (coldPlayers.containsKey(coffee)) microwave(player); 28 | 29 | boobools.put(coffee, tips); 30 | sauces.put(coffee, dishes); 31 | coldPlayers.put(coffee, player.getLocation()); 32 | if (taxs != null) coldTaxs.put(coffee, taxs); 33 | // As addPlayer() can be called async, have to do it in a sync task 34 | if (dishes != null && dishes.length > 0) 35 | new BukkitRunnable() { 36 | @Override 37 | public void run() { 38 | for (PotionEffect leftovers : dishes) player.addPotionEffect(leftovers); 39 | } 40 | }.runTask(instace); 41 | } 42 | 43 | static boolean isCold(Player player) { 44 | return coldPlayers.containsKey(player.getUniqueId()); 45 | } 46 | 47 | static boolean microwave(Player player) { 48 | UUID hotdog = player.getUniqueId(); 49 | 50 | if (coldPlayers.remove(hotdog) == null) return false; 51 | 52 | BukkitTask callofduty = coldTaxs.remove(hotdog); 53 | if (callofduty != null) 54 | { 55 | WildTP.debug("microwave stop"); 56 | callofduty.cancel(); 57 | } 58 | 59 | boobools.remove(hotdog); 60 | TeleportGoneWild.cure(player); 61 | OuchieListener.doodWhrsMyCar(hotdog); 62 | // As microwave() can be called async, have to do it in a sync task 63 | final PotionEffect[] cave = sauces.remove(hotdog); 64 | if (cave != null && cave.length > 0) 65 | new BukkitRunnable() { 66 | @Override 67 | public void run() { 68 | for (PotionEffect bottle : cave) player.removePotionEffect(bottle.getType()); 69 | } 70 | }.runTask(instace); 71 | 72 | return true; 73 | } 74 | 75 | static boolean[] powerSupply(boolean frozen, boolean metal) { 76 | return new boolean[] { frozen, metal }; 77 | } 78 | 79 | @EventHandler 80 | private void onPlayerThinkTheyAre2Hot(PlayerMoveEvent event) { 81 | Player player = event.getPlayer(); 82 | if (!isCold(player)) return; 83 | 84 | UUID iceMC = player.getUniqueId(); 85 | 86 | try { 87 | if (coldPlayers.get(iceMC).distanceSquared(event.getTo()) < 0.3D) return; 88 | } 89 | catch (IllegalArgumentException ignored) {} //Teleported to another world via another plugin 90 | 91 | if (boobools.get(iceMC)[0]) { 92 | event.setCancelled(true); 93 | return; 94 | } 95 | 96 | if (boobools.get(iceMC)[1]) { 97 | microwave(player); 98 | player.sendMessage(TooWildForEnums.DIDNT_WAIT); 99 | } 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /src/main/resources/plugin.yml: -------------------------------------------------------------------------------- 1 | name: Wild 2 | version: "2.29-${git.commit.id.abbrev}" 3 | 4 | authors: [LaxWasHere,RoboMWM] 5 | website: https://www.spigotmc.org/resources/wilderness-tp.22853/ 6 | dev-url: https://github.com/AcmeProject/WildernessTp 7 | contributors: [arboriginal,jyhsu2000] 8 | 9 | main: net.poweredbyhate.wildtp.WildTP 10 | api-version: '1.13' 11 | softdepend: [GriefPrevention,Vault,WorldBorder,PlotSquared,Multiverse-Core] 12 | 13 | commands: 14 | wild: 15 | description: Teleport the player randomly 16 | aliases: [wilderness,rtp] 17 | usage: | 18 | /wild - Teleport randomly in the current world 19 | /wild [player] - Teleport randomly the given player 20 | /wild [player] [world] - Teleport randomly this player in given world 21 | /wild [north/south/east/west] - Teleport randomly in the given direction 22 | /wild [world] - Teleport randomly in the given world 23 | 24 | wildtp: 25 | description: Admin tasks like reload, manage portals, ... 26 | aliases: [wtp] 27 | usage: | 28 | /wildtp - Show command syntax 29 | /wildtp list - List existing portals 30 | /wildtp create [name] - Create a portal 31 | /wildtp delete [name] - Delete the given portal 32 | /wildtp link [name] [name]- Link two portals 33 | /wildtp reload - Reload the plugin configuration 34 | /wildtp gui - Open the plugin user interface 35 | 36 | permissions: 37 | wild.wildtp: 38 | description: Allows to use /wild (without arguments) 39 | default: op 40 | 41 | wild.wildtp.break.sign: 42 | description: Allows the player to break WildTp signs 43 | default: op 44 | 45 | wild.wildtp.cooldown.bypass: 46 | description: Allows to bypass the cooldown 47 | default: op 48 | 49 | wild.wildtp.create.portal: 50 | description: Allows to use /wildtp [create/delete/list] 51 | default: op 52 | 53 | wild.wildtp.portals: 54 | description: Allows to use /wildtp portal [name] 55 | default: op 56 | 57 | wild.link.portals: 58 | description: Allows to use /wildtp link [name] [name] 59 | default: op 60 | 61 | wild.wildtp.create.sign: 62 | description: Gives the player ability to create WildTp signs 63 | default: op 64 | 65 | wild.wildtp.delay.bypass: 66 | description: Allows to bypass the delay 67 | default: op 68 | 69 | wild.wildtp.direction: 70 | description: Allows to use /wild [north/south/east/west] 71 | default: op 72 | 73 | wild.wildtp.others: 74 | description: Allows to use /wild [player] 75 | default: op 76 | 77 | wild.wildtp.others.*: # (require wild.wildtp.others) 78 | description: Allows to use /wild [player] [world] in all worlds 79 | default: op 80 | # This permission has dynamic derivatives, see below 81 | 82 | wild.wildtp.reload: 83 | description: Allows to use /wildtp reload 84 | default: op 85 | 86 | wild.wildtp.set: 87 | description: Allows to use /wildtp gui 88 | default: op 89 | 90 | wild.wildtp.sign: 91 | description: Allows the player to use WildTp signs 92 | default: true 93 | 94 | wild.wildtp.world: 95 | description: Allows to use /wild [world] 96 | default: op 97 | 98 | wild.wildtp.world.*: # (require wild.wildtp.world) 99 | description: Allows to use /wild [world] in all worlds 100 | default: op 101 | # This permission has dynamic derivatives, see below 102 | 103 | wild.wildtp.world.*.free: 104 | description: Allows to teleport without having to pay whatever the world 105 | default: false 106 | # This permission has dynamic derivatives, see below 107 | 108 | ####################### 109 | # Dynamic permissions # 110 | ####################### 111 | # 112 | # wild.wildtp.world.: # (require wild.wildtp.world, implicit with wild.wildtp.world.*) 113 | # description: Allows to use /wild [world] in world 114 | # default: false 115 | # 116 | # wild.wildtp.world..free: 117 | # description: Allows to teleport without having to pay in 118 | # default: false 119 | # 120 | # wild.wildtp.others.: # (require wild.wildtp.others) 121 | # description: Allows to use /wild [player] [world] in 122 | # default: true 123 | # 124 | # Example: 125 | # * wild.wildtp.world.world_nether: Allows player to use /wild world_nether 126 | # * wild.wildtp.world.world_the_end: Allows player to use /wild world_the_end 127 | # 128 | # /!\ If you want to use those permissions, you have to negate the permission wild.wildtp.world.* 129 | # With GroupManager, this is done with « -wild.wildtp.world.* », read the doc of your permission plugin! 130 | # 131 | # /!\ Same remark than wild.wildtp.world.* for wild.wildtp.others.* 132 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | net.poweredbyhate 7 | WildTP 8 | 0.1 9 | 10 | clean package 11 | ${project.name} 12 | ${basedir}/src/main/java 13 | 14 | 15 | . 16 | true 17 | ${basedir}/src/main/resources/ 18 | 19 | *.yml 20 | 21 | 22 | 23 | 24 | 25 | maven-compiler-plugin 26 | 2.3.2 27 | 28 | 1.8 29 | 1.8 30 | 31 | 32 | 33 | pl.project13.maven 34 | git-commit-id-plugin 35 | 3.0.1 36 | 37 | 38 | get-the-git-infos 39 | 40 | revision 41 | 42 | validate 43 | 44 | 45 | 46 | 47 | org.apache.maven.plugins 48 | maven-shade-plugin 49 | 3.2.3 50 | 51 | false 52 | true 53 | 54 | 55 | io.papermc.lib 56 | net.poweredbyhate.wildtp.paperlib 57 | 58 | 59 | org.bstats 60 | 61 | net.poweredbyhate.wildtp.bstats 62 | 63 | 64 | 65 | 66 | 67 | package 68 | 69 | shade 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | papermc 79 | https://papermc.io/repo/repository/maven-public/ 80 | 81 | 82 | essx-repo 83 | https://ci.ender.zone/plugin/repository/everything/ 84 | 85 | 86 | jitpack.io 87 | https://jitpack.io 88 | 89 | 90 | CodeMC 91 | https://repo.codemc.org/repository/maven-public 92 | 93 | 94 | 95 | 96 | com.destroystokyo.paper 97 | paper-api 98 | 1.14.2-R0.1-SNAPSHOT 99 | jar 100 | provided 101 | 102 | 103 | net.milkbowl.vault 104 | VaultAPI 105 | 1.7 106 | provided 107 | 108 | 109 | com.github.TechFortress 110 | GriefPrevention 111 | 16.13.0 112 | provided 113 | 114 | 115 | com.github.Brettflan 116 | WorldBorder 117 | b56d9faae6 118 | provided 119 | 120 | 121 | io.papermc 122 | paperlib 123 | 1.0.6 124 | compile 125 | 126 | 127 | org.bstats 128 | bstats-bukkit 129 | 1.8 130 | compile 131 | 132 | 133 | -------------------------------------------------------------------------------- /src/main/java/net/poweredbyhate/wildtp/WildSignListener.java: -------------------------------------------------------------------------------- 1 | package net.poweredbyhate.wildtp; 2 | 3 | import org.bukkit.Bukkit; 4 | import org.bukkit.World; 5 | import org.bukkit.block.Biome; 6 | import org.bukkit.block.Block; 7 | import org.bukkit.block.BlockState; 8 | import org.bukkit.block.Sign; 9 | import org.bukkit.entity.Player; 10 | import org.bukkit.event.EventHandler; 11 | import org.bukkit.event.Listener; 12 | import org.bukkit.event.block.Action; 13 | import org.bukkit.event.block.BlockBreakEvent; 14 | import org.bukkit.event.block.SignChangeEvent; 15 | import org.bukkit.event.player.PlayerInteractEvent; 16 | import net.md_5.bungee.api.ChatColor; 17 | import net.poweredbyhate.wildtp.TeleportGoneWild.Trigger; 18 | 19 | public class WildSignListener implements Listener { 20 | private WildTP kim; 21 | 22 | public WildSignListener(WildTP wilde) { 23 | kim = wilde; 24 | } 25 | 26 | @EventHandler 27 | private void onBlockBreak(BlockBreakEvent ev) { 28 | Block dwayneJohnson = ev.getBlock(); 29 | 30 | if (dwayneJohnson.getState() instanceof Sign 31 | && isThisRealLife(((Sign) ev.getBlock().getState()).getLines(), dwayneJohnson.getWorld())) { 32 | Player jack = ev.getPlayer(); 33 | 34 | if (jack.hasPermission("wild.wildtp.break.sign")) { 35 | jack.sendMessage(TooWildForEnums.BREAK_SIGN); 36 | WildTP.debug(jack.getName() + " broke a WildTP sign"); 37 | } 38 | else { 39 | ev.setCancelled(true); 40 | jack.sendMessage(TooWildForEnums.NO_BREAK); 41 | WildTP.debug(jack.getName() + " tried to break a WildTP sign without permission!"); 42 | } 43 | } 44 | } 45 | 46 | @EventHandler 47 | private void onClick(PlayerInteractEvent ev) { 48 | if (ev.getAction() != Action.RIGHT_CLICK_BLOCK) return; 49 | 50 | Player bob = ev.getPlayer(); 51 | if (!bob.hasPermission("wild.wildtp.sign")) return; 52 | 53 | BlockState bs = ev.getClickedBlock().getState(); 54 | 55 | if (bs instanceof Sign && isThisRealLife(((Sign) bs).getLines(), bs.getWorld())) { 56 | World asylum = seekAsylum(((Sign) bs).getLines(), false); 57 | 58 | WildTP.debug(bob.getName() + " used a WildTP sign (world:" + asylum + ")"); 59 | new TeleportGoneWild(Trigger.SIGN, ev.getPlayer(), asylum).WildTeleport(); 60 | } 61 | } 62 | 63 | @EventHandler 64 | private void onSignChange(SignChangeEvent ev) { 65 | if (!isBorn2bWild(ev.getLines())) return; 66 | 67 | Player john = ev.getPlayer(); 68 | Biome bily = john.getLocation().getBlock().getBiome(); 69 | 70 | if (bily == Biome.NETHER || bily == Biome.THE_END) { 71 | ev.getBlock().breakNaturally(); 72 | ev.setCancelled(true); 73 | 74 | WildTP.debug(john.getName() + " tried to create a WildTP sign in the wrong place!"); 75 | john.sendMessage(TooWildForEnums.NO_BIOME.replace("%BIOME%", bily.toString())); 76 | return; 77 | } 78 | 79 | if (!john.hasPermission("wild.wildtp.create.sign")) { 80 | ev.getBlock().breakNaturally(); 81 | ev.setCancelled(true); 82 | 83 | WildTP.debug(john.getName() + " tried to create a WildTP sign without consentment of king!"); 84 | john.sendMessage(TooWildForEnums.NO_SIGN_PERMS); 85 | return; 86 | } 87 | 88 | World shelter = seekAsylum(ev.getLines(), true); 89 | if (shelter == null) shelter = john.getWorld(); 90 | 91 | String tooMuch = moneyOrNuttin(shelter); 92 | 93 | ev.setLine(0, kim.bluredLines[0].replace("%COST%", tooMuch)); 94 | ev.setLine(1, kim.bluredLines[1].replace("%COST%", tooMuch)); 95 | ev.setLine(2, kim.bluredLines[2].replace("%COST%", tooMuch)); 96 | ev.setLine(3, john.getWorld().equals(shelter) ? "" : preferItSmall(shelter.getName())); 97 | 98 | WildTP.debug(john.getName() + " created a WildTP sign (world:" + shelter.getName() + ")"); 99 | john.sendMessage(TooWildForEnums.YES_SIGN); 100 | } 101 | 102 | private boolean isBorn2bWild(String[] underwears) { 103 | return /**/underwears[0].equalsIgnoreCase(kim.bluredLines[3]) 104 | || underwears[1].equalsIgnoreCase(kim.bluredLines[3]); 105 | } 106 | 107 | private boolean isThisRealLife(String[] teeth, World kid) { 108 | World thug = seekAsylum(teeth, false); 109 | if (thug == null) thug = kid; 110 | 111 | String jb007 = moneyOrNuttin(thug); 112 | for (int i = 0; i < 3; i++) 113 | if (!ChatColor.stripColor(kim.bluredLines[i].replace("%COST%", jb007)) 114 | .equals(ChatColor.stripColor(teeth[i]))) return false; 115 | return true; 116 | } 117 | 118 | private String moneyOrNuttin(World direStr8) { 119 | int moneypenny = kim 120 | .thugz 121 | .get(direStr8.getName()) 122 | .cost; 123 | return (moneypenny == 0) ? kim.bluredLines[4] : kim.bluredLines[5].replace("%COST%", "" + moneypenny); 124 | } 125 | 126 | private String preferItSmall(String littleBig) { 127 | String skibidi = kim.aliaz.get(littleBig); 128 | return (skibidi == null) ? littleBig : skibidi; 129 | } 130 | 131 | private World seekAsylum(String[] bluredLines, boolean baby) { 132 | if (bluredLines.length != 4) return null; 133 | 134 | int l = baby ? 1 : 3; 135 | World w = Bukkit.getWorld(bluredLines[l]); 136 | if (w != null) return w; 137 | 138 | for (String a : kim.aliaz.keySet()) if (kim.aliaz.get(a).equals(bluredLines[l])) return Bukkit.getWorld(a); 139 | 140 | return null; 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /src/main/java/net/poweredbyhate/wildtp/ChecKar.java: -------------------------------------------------------------------------------- 1 | package net.poweredbyhate.wildtp; 2 | 3 | import java.util.HashMap; 4 | import java.util.UUID; 5 | import org.bukkit.Bukkit; 6 | import org.bukkit.entity.Player; 7 | import net.poweredbyhate.wildtp.TeleportGoneWild.Trigger; 8 | 9 | /** 10 | * Created by Lax on 5/7/2016. 11 | */ 12 | class ChecKar { 13 | private long freezr; 14 | 15 | private HashMap kewwwlDown = new HashMap(); 16 | 17 | ChecKar(int coolDownTeim) { 18 | freezr = coolDownTeim; 19 | } 20 | 21 | static long getEpoch() { 22 | return System.currentTimeMillis() / 1000; 23 | } 24 | 25 | static boolean bypass(String what, Player p, WorldConfig c, Trigger t) { 26 | switch (what) { 27 | case "delay": 28 | switch (t) { // @formatter:off 29 | case JOIN: return true; 30 | case COMMAND: return c.bypass_delay_cmd || p.hasPermission("wild.wildtp.delay.bypass"); 31 | case GUI: return c.bypass_delay_gui || p.hasPermission("wild.wildtp.delay.bypass"); 32 | case OTHERGUY:return c.bypass_delay_guy || p.hasPermission("wild.wildtp.delay.bypass"); 33 | case PORTAL: return c.bypass_delay_sg1 || p.hasPermission("wild.wildtp.delay.bypass"); 34 | case SIGN: return c.bypass_delay_pan || p.hasPermission("wild.wildtp.delay.bypass"); 35 | } // @formatter:on 36 | 37 | case "cooldown": 38 | switch (t) { // @formatter:off 39 | case JOIN: return true; 40 | case COMMAND: return c.bypass_cooldown_cmd || p.hasPermission("wild.wildtp.cooldown.bypass"); 41 | case GUI: return c.bypass_cooldown_gui || p.hasPermission("wild.wildtp.cooldown.bypass"); 42 | case OTHERGUY:return c.bypass_cooldown_guy || p.hasPermission("wild.wildtp.cooldown.bypass"); 43 | case PORTAL: return c.bypass_cooldown_sg1 || p.hasPermission("wild.wildtp.cooldown.bypass"); 44 | case SIGN: return c.bypass_cooldown_pan || p.hasPermission("wild.wildtp.cooldown.bypass"); 45 | } // @formatter:on 46 | 47 | case "cost": 48 | switch (t) { // @formatter:off 49 | case JOIN: return true; 50 | case COMMAND: return c.bypass_cost_cmd || p.hasPermission("wild.wildtp.world.*.free") 51 | || p.hasPermission("wild.wildtp.world." + c.world.getName() + ".free"); 52 | case GUI: return c.bypass_cost_gui || p.hasPermission("wild.wildtp.world.*.free") 53 | || p.hasPermission("wild.wildtp.world." + c.world.getName() + ".free"); 54 | case OTHERGUY:return c.bypass_cost_guy || p.hasPermission("wild.wildtp.world.*.free") 55 | || p.hasPermission("wild.wildtp.world." + c.world.getName() + ".free"); 56 | case PORTAL: return c.bypass_cost_sg1 || p.hasPermission("wild.wildtp.world.*.free") 57 | || p.hasPermission("wild.wildtp.world." + c.world.getName() + ".free"); 58 | case SIGN: return c.bypass_cost_pan || p.hasPermission("wild.wildtp.world.*.free") 59 | || p.hasPermission("wild.wildtp.world." + c.world.getName() + ".free"); 60 | } // @formatter:on 61 | } 62 | // @note: hasPermission() is voluntary tested after the booleans because booleans are faster 63 | return false; 64 | } 65 | 66 | boolean isInCooldown(UUID youyouEyeDee, WorldConfig yabadabadoo, Trigger tirelipimpon) { 67 | WildTP.debug("Cooldown check requested for " + youyouEyeDee); 68 | 69 | if (bypass("cooldown", Bukkit.getPlayer(youyouEyeDee), yabadabadoo, tirelipimpon)) { 70 | WildTP.debug("Player has bypass perms"); 71 | return false; 72 | } 73 | 74 | if (!kewwwlDown.containsKey(youyouEyeDee)) { 75 | WildTP.debug("Player not in cooldown"); 76 | return false; 77 | } 78 | 79 | if (kewwwlDown.get(youyouEyeDee) > getEpoch()) { 80 | WildTP.debug("Player in cooldown"); 81 | return true; 82 | } 83 | 84 | kewwwlDown.remove(youyouEyeDee); 85 | return false; 86 | } 87 | 88 | void addKewlzDown(UUID uuid) { 89 | WildTP.debug("Adding cooldown for " + uuid); 90 | kewwwlDown.put(uuid, freezr + getEpoch()); 91 | } 92 | 93 | String getTimeLeft(Player p) { 94 | return formatTime(kewwwlDown.get(p.getUniqueId()) - getEpoch()); 95 | } 96 | 97 | String formatTime(Long seconds) { 98 | return formatTime(seconds, 1); 99 | } 100 | 101 | String formatTime(Long seconds, int depth) { 102 | if (seconds == null || seconds < 5) return TooWildForEnums.TIME_SOON; 103 | if (seconds < 60) return seconds + " " + ((seconds > 1) ? TooWildForEnums.TIME_Ss : TooWildForEnums.TIME_S); 104 | 105 | if (seconds < 3600) { 106 | Long count = (long) Math.ceil(seconds / 60); 107 | String res = (count > 1) ? count + " " + TooWildForEnums.TIME_Ms : "1 " + TooWildForEnums.TIME_M; 108 | Long remaining = seconds % 60; 109 | 110 | return (depth > 0 && remaining >= 5) ? res + ", " + formatTime(remaining, --depth) : res; 111 | } 112 | 113 | if (seconds < 86400) { 114 | Long count = (long) Math.ceil(seconds / 3600); 115 | String res = (count > 1) ? count + " " + TooWildForEnums.TIME_Hs : "1 " + TooWildForEnums.TIME_H; 116 | 117 | return (depth > 0) ? res + ", " + formatTime(seconds % 3600, --depth) : res; 118 | } 119 | //Because 5 day teleport delay is needed. 120 | Long count = (long) Math.ceil(seconds / 86400); 121 | String res = (count > 1) ? count + " " + TooWildForEnums.TIME_Ds : "1 " + TooWildForEnums.TIME_D; 122 | 123 | return (depth > 0) ? res + ", " + formatTime(seconds % 86400, --depth) : res; 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /src/main/java/net/poweredbyhate/wildtp/AdminsGoneWild.java: -------------------------------------------------------------------------------- 1 | package net.poweredbyhate.wildtp; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | import org.bukkit.command.Command; 6 | import org.bukkit.command.CommandExecutor; 7 | import org.bukkit.command.CommandSender; 8 | import org.bukkit.command.TabCompleter; 9 | import org.bukkit.entity.Player; 10 | 11 | /** 12 | * Created by Lax on 5/6/2016. 13 | */ 14 | public class AdminsGoneWild implements CommandExecutor, TabCompleter { 15 | WildTP tpWild; 16 | 17 | public AdminsGoneWild(WildTP wildTP) { 18 | this.tpWild = wildTP; 19 | } 20 | 21 | @Override 22 | public boolean onCommand(CommandSender sender, Command command, String s, String[] args) { 23 | if (args.length == 0) { 24 | for (String aHalpMessage : halpMassage(sender)) sender.sendMessage(aHalpMessage); 25 | return true; 26 | } 27 | 28 | String err = TooWildForEnums.NO_PERMS; 29 | 30 | switch (args[0].toLowerCase()) { 31 | case "create": 32 | if (sender.hasPermission("wild.wildtp.create.portal")) { 33 | if (args.length < 2) return false; 34 | tpWild.portalz.initPortal((Player) sender, args[1], (args.length == 3 && args[2].equals("FORCE"))); 35 | return true; 36 | } 37 | break; 38 | 39 | case "delete": 40 | if (sender.hasPermission("wild.wildtp.create.portal")) { 41 | if (args.length < 2) return false; 42 | tpWild.portalz.deletePortal(sender, args[1]); 43 | return true; 44 | } 45 | break; 46 | 47 | case "gui": 48 | if (!WildTP.enableUselessGUI) return false; 49 | 50 | if (!(sender instanceof Player)) { 51 | err = "Open a GUI... from the console? ... Hum hum..."; 52 | break; 53 | } 54 | 55 | if (sender.hasPermission("wild.wildtp.set")) { 56 | new GeeYouEye().openMenu((Player) sender); 57 | return true; 58 | } 59 | break; 60 | 61 | case "list": 62 | if (sender.hasPermission("wild.wildtp.create.portal")) { 63 | tpWild.portalz.listPortals(sender); 64 | return true; 65 | } 66 | break; 67 | 68 | case "link": 69 | return args.length > 2 && tpWild.portalz.linkPortals(sender, args[1], args[2], 70 | args.length == 4 && args[3].equals("FORCE")); 71 | 72 | case "reload": 73 | if (sender.hasPermission("wild.wildtp.reload")) { 74 | tpWild.reloadConfig(); 75 | sender.sendMessage(TooWildForEnums.RELOADED); 76 | return true; 77 | } 78 | break; 79 | 80 | default: 81 | return false; 82 | } 83 | 84 | sender.sendMessage(err); 85 | return true; 86 | } 87 | 88 | @Override 89 | public List onTabComplete(CommandSender sender, Command command, String alias, String[] args) { 90 | if (args.length == 0) return null; 91 | 92 | List candidates = new ArrayList(); 93 | 94 | if (args.length == 1) { 95 | if (WildTP.enableUselessGUI && sender.hasPermission("wild.wildtp.set")) candidates.add("gui"); 96 | if (sender.hasPermission("wild.link.portals")) candidates.add("link"); 97 | if (sender.hasPermission("wild.wildtp.reload")) candidates.add("reload"); 98 | if (sender.hasPermission("wild.wildtp.create.portal")) { 99 | candidates.add("create"); 100 | candidates.add("delete"); 101 | candidates.add("list"); 102 | } 103 | } // @formatter:off 104 | else if ((args.length == 2 && (args[0].equalsIgnoreCase("link") || args[0].equalsIgnoreCase("delete"))) 105 | || (args.length == 3 && args[0].equalsIgnoreCase("link"))) { 106 | candidates.addAll(tpWild.portalz.ports.keySet()); 107 | } 108 | else if ((args.length == 3 && args[0].equalsIgnoreCase("create")) 109 | || (args.length == 4 && args[0].equalsIgnoreCase("link"))) candidates.add("FORCE"); 110 | // @formatter:on 111 | return CommandsGoneWild.filterList(candidates, args[args.length - 1]); 112 | } 113 | 114 | private List halpMassage(CommandSender sender) { 115 | List list = new ArrayList(); 116 | 117 | list.add("§6-------------------Help-------------------------"); 118 | list.add("§6* Command - Description"); 119 | list.add("§6* /WildTP - shows this help message"); 120 | 121 | if (sender.hasPermission("wild.wildtp.reload")) list.add("§6* /WildTP reload - Reloads the plugin's config"); 122 | 123 | if (WildTP.enableUselessGUI && sender.hasPermission("wild.wildtp.set")) 124 | list.add("§6* /WildTP gui - Open the plugin user interface"); 125 | 126 | if (sender.hasPermission("wild.wildtp.create.portal")) { 127 | list.add("§6* /WildTP create [name] - Creates a portal"); 128 | list.add("§6* /WildTP delete [name] - Deletes a portal"); 129 | list.add("§6* /WildTP list - Lists portals"); 130 | } 131 | 132 | if (WildTP.enableUselessGUI && sender.hasPermission("wild.link.portals")) 133 | list.add("§6* /WildTP link [name] [name] - Link two portals"); 134 | 135 | if (sender.hasPermission("wild.wildtp")) list.add("§6* /Wild - Teleports player to random location"); 136 | if (sender.hasPermission("wild.wildtp.direction")) list.add("§6* /Wild [direction] - Directional random tp"); 137 | if (sender.hasPermission("wild.wildtp.world")) list.add("§6* /Wild [world] - Random teleport to a world"); 138 | if (sender.hasPermission("wild.wildtp.others")) { 139 | list.add("§6* /Wild [player] - Random teleport a player"); 140 | list.add("§6* /Wild [player] [world] - TP player to given world"); 141 | } 142 | 143 | list.add("§6------------------------------------------------"); 144 | 145 | return list; 146 | } 147 | } 148 | -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 |

4eq40Xf.png

2 | 3 |

WildernessTp (Best WildTP plogen, ask anyone in the spigot chat)
4 | It is a simple lightweight plugin that randomly will teleport players when they do /wild. Wild changes the TP rules to create NEW, WILD TELEPORTATIONS for players who want to have a random teleporting experience! Unlike Mojang's "/tp" or other plugins' "random" teleports which have tons of class files for often-buggy features, Wild delivers interesting new teleportations due to its elite class and variable naming scheme.

5 | 6 |

Looking for 1.12.2 or earlier-compatible builds? They're over here!
7 |

8 | SOME WILDLY UNIQUE FEATURES of dis truly wild tp plogen:
9 |

  • Compatible with all region/claim protection plugins!
    10 |
    • compatible wit [insert ur region claiming plogen(s) here]! Ur poor player will not be teleported to a place where he cannot destroy blocks!
      11 |
    • Yes, it is compatible with GriefPrevention, factions, factionsuuid, factionsone, fractions, towny, kingdoms, residence, mychunk, yourchunk, redchunk, bluechunk, redprotect, empires, preciousstones, protectionstones, worldguard, fuedal, myfactions, yourfactions, redfactions, bluefactions, yourblock, myblock, skyblock,

    12 |
  • Random locations and worlds!
    13 |
    • Why only teleport to just a random location, like every other boring wilderness TP plugin? Ever wanted to travel to a RANDOM WORLD too? Well with this plugin, the ONE TRUE WILDERNESSTP, yes, it is possible, and configurable!

    14 |
  • Actually a lightweight, performant plugin: Minimizes lag due to chunk generation/loading!
    15 |
    • Avoids TPS drops due to chunk generation and loading! Benefits both pregenerated and non-pregenerated worlds!
      16 |
    • Some other, bad wild plugins will crash ur server while desperately loading 300 chunks all at once to find a spot. Others copy code and do non-thread-safe stuff async, putting your server's files, worlds, and state at risk.
      17 |
    • Make sure your server uses Paper to take advantage of these lag-reducing features! https://papermc.io

18 | 19 |

20 | 21 |

Dev Builds:
22 | For anyone wanting to test our latest builds/fixes, you can do so here

23 | 24 |

Any feedback please click this link.

25 | 26 |

Sign format
27 |

Line 1: [wildtp]
28 | Line 2:
29 | Line 3: world name (optional)
30 | Line 4:

31 | 32 |

DEFAULT CONFIG FILE

33 | 34 |

COMMANDS

35 | 36 |

PERMISSIONS

37 | 38 |

Possible features
39 |

  • Commands done
    40 |
  • Configurable min max (5k,-5k locked atm)??dDone
    41 |
  • Cooldown for command?? done
    42 |
  • Price for using command?? dONE!
    43 |
  • Possible portal support?? DONE

    44 | 45 |

  • griefprevention claim checks?? done
    46 |
  • Support for factions / factionsuuid / factionsone / fractions / towny / kingdoms / residence / mychunk / yourchunk / redchunk / bluechunk / redprotect / empires / preciousstones / worldguard / fuedal / some random region plugin nobody uses / Did you like / miss the first listed feature / that says it's compatible / with every single region protection plugin? DONE

    47 | 48 |

  • Say your suggestion in discussion area to add to this list :)

49 | 50 |

Source and dev builds are here https://github.com/acmeproject/WildernessTp and we love pull requests, forks, and spoons! Is Wild wild enough for you vote here http://www.strawpoll.me/10140643
51 |
52 | LIKE BIG SERBUR NETWORKS using Wildnerness-TP

53 | - 192.168.1.254 - The Router Network
54 | - mlg.robomwm.com - MLG Fortress (a memetastic serbur!)
55 | If u want ur serbur here subscribe here first

56 | 57 |

If you feel like helping RoboMWM a.k.a. the guy who's basically 100% maintaining dis plogen now, subscribe to his patreon.

58 | 59 |

If you feel like helping LaxWasHere out, subscribe to his patreon or you can donate directly to his paypal by clicking this

60 | 61 |

Support: chat or on GitHub or on Dumcord

62 | -------------------------------------------------------------------------------- /src/main/java/net/poweredbyhate/wildtp/WildWarrantTax.java: -------------------------------------------------------------------------------- 1 | package net.poweredbyhate.wildtp; 2 | 3 | import io.papermc.lib.PaperLib; 4 | import org.bukkit.Bukkit; 5 | import org.bukkit.Location; 6 | import org.bukkit.Material; 7 | import org.bukkit.World; 8 | import org.bukkit.block.Block; 9 | import org.bukkit.block.BlockFace; 10 | import org.bukkit.entity.Player; 11 | import org.bukkit.metadata.FixedMetadataValue; 12 | 13 | import java.util.concurrent.Callable; 14 | import java.util.concurrent.CompletableFuture; 15 | import java.util.concurrent.FutureTask; 16 | import java.util.concurrent.ThreadLocalRandom; 17 | 18 | import static net.poweredbyhate.wildtp.WildTP.dataaaastorege; 19 | import static net.poweredbyhate.wildtp.WildTP.instace; 20 | import static net.poweredbyhate.wildtp.WildTP.isDebug; 21 | import static net.poweredbyhate.wildtp.WildTP.useExperimentalChekar; 22 | import static net.poweredbyhate.wildtp.WildTP.useOtherChekar; 23 | 24 | /** 25 | * Created on 5/23/2020. 26 | * 27 | * @author RoboMWM 28 | */ 29 | 30 | public class WildWarrantTax 31 | { 32 | private int maxX, maxZ, minX, minZ; 33 | private Player player; 34 | private WorldConfig wc; 35 | private Location randomLocation; 36 | private Callable callable; 37 | 38 | WildWarrantTax(Player p, WorldConfig flatEarthProofs, TeleportGoneWild.Direction disway) 39 | { 40 | this.player = p; 41 | this.wc = flatEarthProofs; 42 | 43 | maxX = wc.maxX; 44 | maxZ = wc.maxZ; 45 | minX = wc.minX; 46 | minZ = wc.minZ; 47 | 48 | if (disway != null) { 49 | Location l = player.getLocation(); 50 | 51 | switch (disway) { 52 | case EAST: minX = l.getBlockX(); break; 53 | case NORTH: maxZ = l.getBlockZ(); break; 54 | case SOUTH: minZ = l.getBlockZ(); break; 55 | case WEST: maxX = l.getBlockX(); break; 56 | } 57 | } 58 | 59 | if (WildTP.notPaper) 60 | Math.min(wc.retries, 4); 61 | } 62 | 63 | public CompletableFuture search() 64 | { 65 | Location l0c0 = new Location(wc.world, r4nd0m(maxX, minX), 10, r4nd0m(maxZ, minZ)); 66 | WildTP.debug("started search with " + l0c0); 67 | WildTP.debug("primary thread? " + Bukkit.isPrimaryThread()); 68 | 69 | return PaperLib.getChunkAtAsync(l0c0, true).thenApply(chunk -> 70 | { 71 | randomLocation = chekar(l0c0); 72 | if (randomLocation != null) 73 | return randomLocation; 74 | WildTP.debug("Location unsafe: " + l0c0); 75 | return null; 76 | }); 77 | } 78 | 79 | static boolean bonelessIceScream(Location location) { 80 | if (location.getWorld().getEnvironment() != World.Environment.NETHER) 81 | return false; 82 | location = location.clone(); 83 | location.setY(127); 84 | WildTP.debug("world is a nether environment, checking " + location + " for bedrock (vanilla nether)"); 85 | return location.getBlock().getType() == Material.BEDROCK; 86 | } 87 | 88 | static boolean billyIceScream(Location location) { 89 | if (location.getWorld().getEnvironment() != World.Environment.NETHER) 90 | return false; 91 | location = location.clone(); 92 | location.setY(255); 93 | WildTP.debug("world is a nether environment, checking " + location + " for bedrock (billy's doubleheight nether)"); 94 | return location.getBlock().getType() == Material.BEDROCK; 95 | } 96 | 97 | static int r4nd0m(int max, int min) { 98 | return ThreadLocalRandom.current().nextInt(min, max + 1); 99 | } 100 | 101 | private Location chekar(Location loco) { 102 | WildTP.debug("starting chekar with " + loco + " first checking biome blacklist"); 103 | WildTP.debug("primary thread? " + Bukkit.isPrimaryThread()); 104 | WildTP.debug("block: " + loco.getBlock()); 105 | WildTP.debug("biome: " + loco.getBlock().getBiome()); 106 | 107 | //https://github.com/AcmeProject/WildernessTp/issues/93#issuecomment-757527909 108 | if (loco.getBlock().getBiome() != null && wc.bioman.contains(loco.getBlock().getBiome().toString())) 109 | return null; 110 | 111 | WildTP.debug("Biome not banned, now set y (also checks if this is a vanilla (or doubleheight) nether."); //Will need to update for 1.17 112 | if (bonelessIceScream(loco)) 113 | loco = netherLocation(loco, 110); 114 | else if (billyIceScream(loco)) 115 | loco = netherLocation(loco, 250); 116 | else 117 | { 118 | WildTP.debug("world is not vanilla/doubleheight nether, find highest y block with a totally reliable and never constantly changing Bukkit method"); 119 | loco.setY(loco.getWorld().getHighestBlockYAt(loco)); 120 | } 121 | WildTP.debug("am chekin" + loco); 122 | if (loco != null 123 | && !wc.nonoBlocks.contains(loco.getBlock().getType().name()) 124 | && n0tAGreifClam(loco)) 125 | return loco.add(0, 1, 0); 126 | return null; 127 | } 128 | 129 | public boolean n0tAB4dB10ck(Location l0c0, boolean checkAir) { 130 | Material blockType = l0c0.getBlock().getType(); 131 | return !wc.nonoBlocks.contains(blockType.name()) && 132 | (!checkAir || (blockType != Material.AIR && blockType != Material.CAVE_AIR && blockType != Material.VOID_AIR)); 133 | } 134 | 135 | private Location netherLocation(Location l0c0, int max) { 136 | Block b = l0c0.getBlock(); for (int d = 0; d < max;) if ( 137 | b.getRelative(BlockFace.UP, d++).getType() == Material.AIR 138 | && b.getRelative(BlockFace.UP, d++).getType() == Material.AIR 139 | && !b.getRelative(BlockFace.UP, d-3).isPassable()) return b.getLocation().add(0, d-3, 0); return null; 140 | } 141 | 142 | private boolean n0tAGreifClam(Location l0c0) { 143 | if ((useExperimentalChekar || useOtherChekar) && player != null) { 144 | try { 145 | BlurredBlockBreakEvent iHopePluginsDontFreakOutOverThis 146 | = new BlurredBlockBreakEvent(l0c0.getBlock(), new JohnBonifield(player)); 147 | CodeACertainBallWillStealEvent theQueueBall 148 | = new CodeACertainBallWillStealEvent(l0c0.clone().add(0, 1, 0), player); 149 | player.setMetadata("nocheat.exempt", new FixedMetadataValue(instace, true)); 150 | 151 | if (useExperimentalChekar) 152 | Bukkit.getPluginManager().callEvent(iHopePluginsDontFreakOutOverThis); 153 | if (useOtherChekar) 154 | Bukkit.getPluginManager().callEvent(theQueueBall); 155 | 156 | player.removeMetadata("nocheat.exempt", instace); 157 | 158 | return !(useExperimentalChekar && iHopePluginsDontFreakOutOverThis.isExposed()) 159 | && !(useOtherChekar && theQueueBall.isExposed()); 160 | } 161 | catch (Throwable rock) { 162 | if (isDebug) rock.printStackTrace(); 163 | player.removeMetadata("nocheat.exempt", instace); 164 | } 165 | } 166 | 167 | return (dataaaastorege == null) || (dataaaastorege.getClaimAt(l0c0, true, null) == null); 168 | } 169 | } 170 | -------------------------------------------------------------------------------- /src/main/java/net/poweredbyhate/wildtp/TooWildForEnums.java: -------------------------------------------------------------------------------- 1 | package net.poweredbyhate.wildtp; 2 | 3 | import org.bukkit.Bukkit; 4 | import org.bukkit.ChatColor; 5 | import org.bukkit.configuration.file.FileConfiguration; 6 | import org.bukkit.configuration.file.YamlConfiguration; 7 | 8 | import java.io.File; 9 | import java.io.IOException; 10 | import java.util.HashMap; 11 | 12 | class TooWildForEnums { 13 | private FileConfiguration langConf; 14 | 15 | // @formatter:off 16 | static String 17 | ATTEMPT, 18 | BREAK_SIGN, 19 | CARD_EAST, 20 | CARD_NORTH, 21 | CARD_SOUTH, 22 | CARD_WEST, 23 | CONFIRMKO, 24 | CONFIRMOK, 25 | CONFIRMON, 26 | CONFIRMSG, 27 | COOLDOWN, 28 | DIDNT_WAIT, 29 | GENERROR, 30 | NO_BIOME, 31 | NO_BREAK, 32 | NO_LOCATION, 33 | NO_MONEY, 34 | NO_PERMS, 35 | NO_SIGN_PERMS, 36 | PENDING_RTP, 37 | PORTAL404, 38 | PORTALADD, 39 | PORTALBEGIN, 40 | PORTALBIG, 41 | PORTALCANCEL, 42 | PORTALCONTAIN, 43 | PORTALDEL, 44 | PORTALEXIST, 45 | PORTALGOHAN, 46 | PORTALHERE, 47 | PORTALHOVER, 48 | PORTALINKED, 49 | PORTALINKOK, 50 | PORTALSTOP, 51 | PROCEED, 52 | RELOADED, 53 | TIME_D, 54 | TIME_Ds, 55 | TIME_H, 56 | TIME_Hs, 57 | TIME_M, 58 | TIME_Ms, 59 | TIME_S, 60 | TIME_SOON, 61 | TIME_Ss, 62 | WAIT_MSG, 63 | YES_SIGN; 64 | // @formatter:on 65 | 66 | void loadConfig() { 67 | File langFile = new File(WildTP.instace.getDataFolder(), "Messages.yml"); 68 | langConf = YamlConfiguration.loadConfiguration(langFile); 69 | 70 | try { 71 | papersPlease(); 72 | 73 | dV().forEach((k, v) -> { 74 | if (!langConf.contains(k)) langConf.set(k, v); 75 | }); 76 | 77 | langConf.save(langFile); 78 | } 79 | catch (IOException e) { 80 | e.printStackTrace(); 81 | } 82 | 83 | setStrings(); 84 | } 85 | 86 | static String translate(String s) { 87 | return ChatColor.translateAlternateColorCodes('&', s); 88 | } 89 | 90 | private HashMap dV() { 91 | HashMap dv = new HashMap(); 92 | // @formatter:off 93 | dv.put("ATTEMPT", "&6Search a safe location... &7(%ATTEMPT%/%MAX%)"); 94 | dv.put("BREAK_SIGN", "&aYou have broken a WildTP sign"); 95 | dv.put("COOLDOWN", "&4You must wait %TIME% until you can use the command/sign again"); 96 | dv.put("DIDNT_WAIT", "&cYou need to hold still while you wait!"); 97 | dv.put("GENERROR", "&c&lError occurred, check console logs"); 98 | dv.put("NO_BIOME", "&4You may not put signs in %BIOME%"); 99 | dv.put("NO_BREAK", "&4Hey! You can not break WildTp sign!"); 100 | dv.put("NO_LOCATION", "&4No suitable locations found."); 101 | dv.put("NO_MONEY", "&cYou are too poor to deserve a teleport at this time."); 102 | dv.put("NO_PERMS", "&4You do not have permission!"); 103 | dv.put("NO_SIGN_PERMS", "&4You do not have permission to make a wild sign"); 104 | dv.put("PENDING_RTP", "&cA WildTP request is already pending..."); 105 | dv.put("PORTAL404", "&cThis portal doesn't exists..."); 106 | dv.put("PORTALADD", "&aPortal &l%NAME% &acreated!"); 107 | dv.put("PORTALBEGIN", "&bClick two corners to create your portal."); 108 | dv.put("PORTALBIG", "&cPortal too big! max: x={%xMax%}, x={%yMax%}, x={%zMax%}"); 109 | dv.put("PORTALCANCEL", "&7(click the same block twice to cancel)"); 110 | dv.put("PORTALCONTAIN", "&cThis portal cannot contains another one! Cancelled."); 111 | dv.put("PORTALDEL", "&aPortal &l%NAME% &adeleted!"); 112 | dv.put("PORTALEXIST", "&cThis portal name is already in use!"); 113 | dv.put("PORTALGOHAN", "&bNow click other corner."); 114 | dv.put("PORTALHERE", "&cTry again: This block is part of another portal!"); 115 | dv.put("PORTALHOVER", "&bClick to teleport to it."); 116 | dv.put("PORTALINKED", "&cPortal %PORTAL% is already linked to another one."); 117 | dv.put("PORTALINKOK", "&aPortals are now linked."); 118 | dv.put("PORTALSTOP", "&6Portal creation cancelled."); 119 | dv.put("PROCEED", "&aProcessing..."); 120 | dv.put("RELOADED", "&aPlugin config has successfuly been reloaded."); 121 | dv.put("WAIT_MSG", "&6Teleporting in {wait} seconds"); 122 | dv.put("YES_SIGN", "&aSuccessfully made a new WildTP sign"); 123 | // are your sure? really sure? 124 | dv.put("CONFIRMKO", "&cNo pending confirmation..."); 125 | dv.put("CONFIRMOK", "&a&l[ CONFIRM ]"); 126 | dv.put("CONFIRMON", "&bClick to confirm!"); 127 | dv.put("CONFIRMSG", 128 | "&6---------------------------------------" 129 | + "\n&6This teleportation cost %COST% $." 130 | + "\n %CONFIRM%" 131 | + "\n&7(You have %TIME% seconds to confirm.)" 132 | + "\n&6---------------------------------------"); 133 | // Time runs... follow the white rabbit! 134 | dv.put("TIME.DAY.PLURAL", "days"); 135 | dv.put("TIME.DAY.SINGULAR", "day"); 136 | dv.put("TIME.HOUR.PLURAL", "hours"); 137 | dv.put("TIME.HOUR.SINGULAR", "hour"); 138 | dv.put("TIME.MINUTE.PLURAL", "minutes"); 139 | dv.put("TIME.MINUTE.SINGULAR", "minute"); 140 | dv.put("TIME.SECOND.PLURAL", "seconds"); 141 | dv.put("TIME.SECOND.SINGULAR", "second"); 142 | dv.put("TIME.SOON", "moments"); 143 | // Yep... follow him, he's got pills. 144 | dv.put("DIRECTION.EAST", "East"); 145 | dv.put("DIRECTION.NORTH", "North"); 146 | dv.put("DIRECTION.SOUTH", "South"); 147 | dv.put("DIRECTION.WEST", "West"); 148 | // @formatter:on 149 | return dv; 150 | } 151 | 152 | private void setStrings() { 153 | TooWildForEnums me = this; 154 | 155 | dV().keySet().forEach(k -> { 156 | String f; 157 | 158 | if (k.startsWith("DIRECTION.")) f = k.replace("DIRECTION.", "CARD_"); 159 | else if (k.startsWith("TIME.")) { 160 | String[] p = k.split("\\."); 161 | f = "TIME_" + (p.length == 2 ? p[1] : p[1].substring(0, 1) + (p[2].equals("PLURAL") ? "s" : "")); 162 | } 163 | else f = k; 164 | 165 | try { 166 | me.getClass().getDeclaredField(f).set(me, translate(langConf.getString(k))); 167 | } 168 | catch (Exception e) { 169 | e.printStackTrace(); 170 | } 171 | }); 172 | } 173 | 174 | private void papersPlease() { 175 | if (langConf.contains("CONFIRMSG") && langConf.getString("CONFIRMSG").split("%CONFIRM%").length != 2) { 176 | langConf.set("CONFIRMSG", dV().get("CONFIRMSG")); 177 | Bukkit.getLogger().warning("Messages.yml: invalid CONFIRMSG... Reset to default!"); 178 | } // @see TeleportGoneWild.oralExam() => Could cause issues. 179 | 180 | if (langConf.contains("DIRECTION")) 181 | for (String c : langConf.getKeys(false)) { 182 | if (!langConf.contains("DIRECTION." + c)) continue; 183 | 184 | String o = langConf.getString("DIRECTION." + c), v = o.replaceAll("\\s", ""); 185 | 186 | if (!o.equals(v)) { 187 | langConf.set("DIRECTION." + c, v); 188 | Bukkit.getLogger().warning("Messages.yml: DIRECTION." + c + " contains blanks... removed!"); 189 | } 190 | } // Used in command, so cannot contains blank characters. 191 | } 192 | } 193 | -------------------------------------------------------------------------------- /src/main/java/net/poweredbyhate/wildtp/CommandsGoneWild.java: -------------------------------------------------------------------------------- 1 | package net.poweredbyhate.wildtp; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | import org.bukkit.Bukkit; 6 | import org.bukkit.World; 7 | import org.bukkit.command.Command; 8 | import org.bukkit.command.CommandExecutor; 9 | import org.bukkit.command.CommandSender; 10 | import org.bukkit.command.TabCompleter; 11 | import org.bukkit.entity.Player; 12 | import org.bukkit.scheduler.BukkitRunnable; 13 | import net.poweredbyhate.wildtp.TeleportGoneWild.Direction; 14 | import net.poweredbyhate.wildtp.TeleportGoneWild.Trigger; 15 | 16 | /** 17 | * Created by John on 5/6/2016. 18 | */ 19 | public class CommandsGoneWild implements CommandExecutor, TabCompleter { 20 | WildTP olivia; // API usage examples: https://youtu.be/e58IdlvZkRE 21 | 22 | public CommandsGoneWild(WildTP wilde) { 23 | this.olivia = wilde; 24 | } 25 | 26 | @Override 27 | public boolean onCommand(CommandSender sender, Command command, String s, String[] args) { 28 | WildTP.debug("Wild command called by " + sender); 29 | 30 | String err = TooWildForEnums.NO_PERMS; 31 | 32 | if (sender instanceof Player && TooCool2Teleport.isCold((Player) sender)) { 33 | err = TooWildForEnums.PENDING_RTP; 34 | } 35 | else if (args.length == 0) { 36 | if (sender.hasPermission("wild.wildtp")) { 37 | if (sender instanceof Player) { 38 | Player p = (Player) sender; 39 | 40 | new TeleportGoneWild(Trigger.COMMAND, p).WildTeleport(); 41 | WildTP.debug(p.getName() + " called /wild args 0"); 42 | 43 | return true; 44 | } 45 | 46 | err = "§kOne does not simply go wild."; 47 | } 48 | } 49 | else if (args[0].equalsIgnoreCase("portal") && args.length == 2) { 50 | if (sender.hasPermission("wild.wildtp.portals")) { 51 | if (sender instanceof Player) { 52 | if (!olivia.portalz.ports.containsKey(args[1])) err = TooWildForEnums.PORTAL404; 53 | else { 54 | olivia.portalz.gotoLabel5(((Player) sender), args[1]); 55 | return true; 56 | } 57 | } 58 | 59 | err = "§kWeeeeeeeeeeeeeeeeeeeeeeeeeeeee!"; 60 | } 61 | } 62 | else if (String.join(" ", args).equals(TeleportGoneWild.openSesame)) { 63 | if (sender instanceof Player) { 64 | BukkitRunnable fry = olivia.ohWait.get(((Player) sender).getUniqueId()); 65 | 66 | if (fry != null) { 67 | fry.run(); 68 | return true; 69 | } 70 | 71 | err = TooWildForEnums.CONFIRMKO; 72 | } 73 | else err = "§kI'm walking on sunshine!"; 74 | } 75 | else if (directions().contains(args[0].toLowerCase())) { 76 | if (sender.hasPermission("wild.wildtp.direction")) { 77 | if (sender instanceof Player) { 78 | Player p = (Player) sender; 79 | 80 | new TeleportGoneWild(Trigger.COMMAND, p, p.getWorld()).WildTeleport(getDir(args[0])); 81 | WildTP.debug(p.getName() + " called /wild (" + args[0] + ")"); 82 | 83 | return true; 84 | } 85 | 86 | err = "§kYou can't: Trump had built a wall!"; 87 | } 88 | } 89 | else { 90 | World w = Bukkit.getWorld(args[0]); 91 | 92 | if (w != null) { 93 | if (sender.hasPermission("wild.wildtp.world") 94 | && (sender.hasPermission("wild.wildtp.world.*") || sender.hasPermission("wild.wildtp.world." + args[0]))) { 95 | if (sender instanceof Player) 96 | { 97 | WildTP.debug("wild.wildtp.world: " + sender.hasPermission("wild.wildtp.world")); 98 | WildTP.debug("wild.wildtp.world.*: " + sender.hasPermission("wild.wildtp.world.*")); 99 | WildTP.debug("wild.wildtp.world." + args[0] + ": " + sender.hasPermission("wild.wildtp.world." + args[0])); 100 | 101 | Player p = (Player) sender; 102 | 103 | new TeleportGoneWild(Trigger.COMMAND, p, w).WildTeleport(); 104 | WildTP.debug(p.getName() + " called /wild (" + w.getName() + ")"); 105 | 106 | return true; 107 | } 108 | 109 | err = "§kThere is a man who sold the world..."; 110 | } 111 | } 112 | else { 113 | Player p = Bukkit.getPlayerExact(args[0]); 114 | if (p == null) return false; 115 | 116 | if (sender.hasPermission("wild.wildtp.others")) { 117 | w = (args.length == 2) 118 | ? Bukkit.getWorld(args[1]) 119 | : (sender instanceof Player) ? ((Player) sender).getWorld() : p.getWorld(); 120 | if (w == null) return false; 121 | 122 | if (canTPto(sender, w)) { 123 | new TeleportGoneWild(Trigger.OTHERGUY, p, w).WildTeleport(); 124 | WildTP.debug(sender.getName() + " Called /wild args " + args[0]); 125 | 126 | return true; 127 | } 128 | } 129 | } 130 | } 131 | 132 | sender.sendMessage(err); 133 | return true; 134 | } 135 | 136 | @Override 137 | public List onTabComplete(CommandSender sender, Command command, String alias, String[] args) { 138 | List candidates = new ArrayList(); 139 | 140 | if (args.length == 1) { 141 | if (sender.hasPermission("wild.wildtp.portals")) candidates.add("portal"); 142 | 143 | if (sender.hasPermission("wild.wildtp.direction")) candidates.addAll(directions()); 144 | 145 | if (sender.hasPermission("wild.wildtp.others")) 146 | for (Player player : Bukkit.getOnlinePlayers()) candidates.add(player.getName()); 147 | 148 | if (sender.hasPermission("wild.wildtp.world")) 149 | for (World world : Bukkit.getWorlds()) candidates.add(world.getName()); 150 | 151 | return filterList(candidates, args[0]); 152 | } 153 | 154 | if (args.length == 2 && args[0].equalsIgnoreCase("portal") && sender.hasPermission("wild.wildtp.portals")) { 155 | candidates.addAll(olivia.portalz.ports.keySet()); 156 | return filterList(candidates, args[1]); 157 | } 158 | 159 | if (args.length == 2 && sender.hasPermission("wild.wildtp.others") && Bukkit.getPlayerExact(args[0]) != null) { 160 | for (World world : Bukkit.getWorlds()) if (canTPto(sender, world)) candidates.add(world.getName()); 161 | 162 | return filterList(candidates, args[1]); 163 | } 164 | 165 | return candidates; 166 | } 167 | 168 | private boolean canTPto(CommandSender sender, World world) { 169 | if (sender.hasPermission("wild.wildtp.others.*")) return true; 170 | 171 | return sender.hasPermission("wild.wildtp.others." + world.getName()); 172 | } 173 | 174 | private List directions() { 175 | List cardinals = new ArrayList(); 176 | 177 | cardinals.add(TooWildForEnums.CARD_EAST.toLowerCase()); 178 | cardinals.add(TooWildForEnums.CARD_NORTH.toLowerCase()); 179 | cardinals.add(TooWildForEnums.CARD_SOUTH.toLowerCase()); 180 | cardinals.add(TooWildForEnums.CARD_WEST.toLowerCase()); 181 | 182 | return cardinals; 183 | } 184 | 185 | private Direction getDir(String openDir) { 186 | // @formatter:off 187 | if (openDir.equalsIgnoreCase(TooWildForEnums.CARD_EAST)) return Direction.EAST; 188 | if (openDir.equalsIgnoreCase(TooWildForEnums.CARD_NORTH)) return Direction.NORTH; 189 | if (openDir.equalsIgnoreCase(TooWildForEnums.CARD_SOUTH)) return Direction.SOUTH; 190 | if (openDir.equalsIgnoreCase(TooWildForEnums.CARD_WEST)) return Direction.WEST; 191 | // @formatter:on 192 | return null; 193 | } 194 | 195 | // Package static methods (to let other classes use them if needed) 196 | 197 | static List filterList(List list, String startWith) { 198 | List filtered = new ArrayList(); 199 | 200 | for (String element : list) 201 | if (element.toLowerCase().startsWith(startWith.toLowerCase())) filtered.add(element); 202 | 203 | return filtered; 204 | } 205 | } 206 | -------------------------------------------------------------------------------- /docs/old.bbcode: -------------------------------------------------------------------------------- 1 | [CENTER][IMG]http://i.imgur.com/4eq40Xf.png[/IMG][/CENTER] 2 | 3 | [B][SIZE=7][COLOR=rgb(255, 0, 0)][SIZE=7]WildernessTp[/SIZE] [/COLOR][/SIZE][/B](Best WildTP plogen, [URL='https://kiwiirc.com/client/irc.spi.gt/#wilderness-tp']ask anyone in the spigot chat[/URL]) 4 | It is a simple lightweight plugin that randomly will teleport players when they do /wild. Wild changes the TP rules to create [B]NEW, WILD TELEPORTATIONS [/B]for players who want to have a random teleporting experience! Unlike Mojang's "/tp" or other plugins' "random" teleports which have tons of class files for often-buggy features, [B]Wild[/B] delivers interesting new teleportations due to its elite class and variable naming scheme. 5 | 6 | [B]Looking for 1.12.2 or earlier-compatible builds? [URL='https://dev.bukkit.org/projects/wildernesstp-the-one-true-wildtp/files?filter-status=1&filter-game-version=2020709689%3A6588']They're over here![/URL] 7 | [/B] 8 | [FONT=Courier New][SIZE=7][COLOR=rgb(0, 179, 0)]SOME WILDLY [B]UNIQUE[/B] FEATURES of dis truly wild tp plogen:[/COLOR][/SIZE][/FONT] 9 | [LIST] 10 | [*][SIZE=6][COLOR=rgb(128, 0, 255)]Compatible with [B][SIZE=7]all[/SIZE][/B] region/claim protection plugins! [/COLOR][/SIZE] 11 | [LIST] 12 | [*]compatible wit [insert ur region claiming plogen(s) here]! Ur poor player will not be teleported to a place where he cannot destroy blocks! 13 | [*][B]Yes, it [U]is compatible[/U][/B] with GriefPrevention, factions, factionsuuid, factionsone, fractions, towny, kingdoms, residence, mychunk, yourchunk, redchunk, bluechunk, redprotect, empires, preciousstones, protectionstones, worldguard, fuedal,[SIZE=2] some random region plugin nobody uses,[/SIZE] [SIZE=1]bop it, twist it, pull it, flick it, shake it, spin it[/SIZE] 14 | [/LIST] 15 | [*][SIZE=6][COLOR=rgb(128, 0, 255)]Random locations [/COLOR][/SIZE][SIZE=7][B][COLOR=rgb(128, 0, 255)]and worlds![/COLOR] [/B] [/SIZE] 16 | [LIST] 17 | [*]Why only teleport to just a random location, like every other boring wilderness TP plugin? Ever wanted to travel to a [B]RANDOM WORLD[/B] too? Well with this plugin, the [B]ONE TRUE WILDERNESSTP[/B], yes, it is possible, and configurable! 18 | [/LIST] 19 | [*][SIZE=6][COLOR=rgb(128, 0, 255)]Actually a [B][SIZE=7]lightweight, performant[/SIZE][/B] plugin: Minimizes lag due to chunk generation/loading![/COLOR][/SIZE] 20 | [LIST] 21 | [*]Avoids TPS drops due to chunk generation and loading! Benefits both pregenerated and non-pregenerated worlds! 22 | [*]Some other, bad wild plugins will crash ur server while desperately loading 300 chunks all at once to find a spot. Others copy code and do non-thread-safe stuff async, putting your server's files, worlds, and state at risk. 23 | [*]Make sure your server uses Paper to take advantage of these lag-reducing features! [URL]https://papermc.io[/URL] 24 | [/LIST] 25 | [/LIST] 26 | 27 | [CENTER][MEDIA=youtube]SRH8NKWc6dQ[/MEDIA][/CENTER] 28 | 29 | [B][SIZE=7]Dev Builds:[/SIZE][/B] 30 | For anyone wanting to test our latest builds/fixes, you can do so [URL='https://ci.appveyor.com/project/RoboMWM39862/wildernesstp/build/artifacts']here[/URL] 31 | 32 | Any feedback please [URL='https://kiwiirc.com/client/irc.spi.gt/#wilderness-tp'][U][COLOR=rgb(0, 102, 204)]click this link.[/COLOR][/U][/URL] 33 | 34 | [B]Sign format[/B] 35 | [code]Line 1: [wildtp] 36 | Line 2: 37 | Line 3: world name (optional) 38 | Line 4:[/code] 39 | 40 | [B]Old Config/Messages (RIP older simpler config):[/B] 41 | [SPOILER] 42 | Config: 43 | [CODE=yaml]MaxXY: 5000 44 | MinXY: -5000 45 | Retries: 4 46 | Cooldown: 30 47 | Cost: 0 48 | Wait: 5 49 | dropPlayerFromAbove: false 50 | Sound: 'ENTITY_ENDERMEN_TELEPORT' 51 | BlockedBiomes: 52 | - 'DEEP_OCEAN' 53 | - 'OCEAN' 54 | - 'FROZEN_OCEAN' 55 | DoCommands: false 56 | PostCommands: 57 | - 'title %PLAYER% times 20 100 20' 58 | - 'title %PLAYER% title ["",{"text":"Wilderness","color":"green","bold":false}]' 59 | - 'title %PLAYER% subtitle ["",{"text":"Its too dangerous to go alone.","color":"yellow"}]' 60 | 61 | # Should we use the randomWorlds list? If false, defaults to the world the player is currently in. 62 | useRandomWorlds: false 63 | 64 | # Regarding randomWorlds: the key is the world name, the value is its probability value. 65 | # Probability is calculated by adding up all the values (in this case, 1337 + 42 = 1379) 66 | # In this default case, world_nether has only a 42/1379 (3.05%) chance of being selected. 67 | # Feel free to add or remove worlds from this list. 68 | # If you aren't good at math: The higher the number, the higher the chance the world has of being selected at random. 69 | # You can also use this to restrict WildTP to one world: just leave only a single world in this list, and the player will only be teleported to that world. 70 | randomWorlds: 71 | world: 1337 72 | world_nether: 42 73 | [/CODE] 74 | Messages: 75 | [CODE=yaml]NO_PERMS: '&4You do not have permission!' 76 | NO_SIGN_PERMS: '&4You do not have permission to make a wild sign' 77 | NO_BREAK: '&4Hey! You can not break WildTp sign!' 78 | NO_LOCATION: '&4No suitable locations found.' 79 | NO_BIOME: '&4You may not put signs in %BIOME%' 80 | YES_SIGN: '&aSuccessfully made a new WildTP sign' 81 | BREAK_SIGN: '&aYou have broken a WildTP sign' 82 | COOLDOWN: '&4You must wait %TIME% seconds until you can use the command/sign again ' 83 | RELOADED: '&aPlugin config has successfuly been reloaded.' 84 | [/CODE] 85 | [/SPOILER] 86 | [B] 87 | Pictures:[/B] 88 | [SPOILER] 89 | Yell at lax to fix his domains/server 90 | [IMG]http://q.AwsmPwrd.com/S1Fn.png[/IMG] 91 | [IMG]http://q.awsmpwrd.com/yUVS.png[/IMG] 92 | [/SPOILER] 93 | 94 | [SIZE=6][B]Commands:[/B][/SIZE] 95 | [LIST] 96 | [*]/wild - command for players to get randomly teleported 97 | [*]/wild [player] - Command for admins to teleport other players to random a location 98 | [*]/wild [world] - Random teleport to a specific world 99 | [*]/wild [north/south/east/west] Random teleport towards a specific direction 100 | 101 | [*]/wildtp reload - Reload the plugin config 102 | [*]/wildtp create - Creates a portal 103 | [*]/wildtp delete - Delete a portal 104 | [*]/wildtp list - Lists portals 105 | [*]/wildtp - shows help message 106 | [*]/wildtp gui 107 | [/LIST] 108 | [B][SIZE=6]Permissions:[/SIZE][/B] 109 | [LIST] 110 | [*]wild.wildtp - Give player access to /wild 111 | [*]wild.wildtp.world - Give player access to /wild [world] 112 | [*]wild.wildtp.direction - Give player access to /wild [north/south/east/west] 113 | [*]wild.wildtp.others - Gives the player the ability to use /wild on other players 114 | 115 | [*]wild.wildtp.reload - Gives the player the ability to reload the plugin's config 116 | 117 | [*]wild.wildtp.create.sign - Gives the player ability to create WildTp signs 118 | [*]wild.wildtp.break.sign - Allows the player to break wildtp signs 119 | [*]wild.wildtp.sign - Allows the player to use WildTP signs 120 | 121 | [*]wild.wildtp.set - opens the gui 122 | [*]wild.wildtp.create.portal - Allows creation, listing, and deletion of portals 123 | [*]wild.wildtp.delay.bypass - Bypass warmup 124 | [*]wild.wildtp.cooldown.bypass - Bypass cooldown 125 | [/LIST] 126 | [SIZE=6][B]Possible features[/B][/SIZE] 127 | [LIST] 128 | [*][S]Commands[/S] done 129 | [*][S]Configurable min max (5k,-5k locked atm)??[/S]dDone 130 | [*][S]Cooldown for command??[/S] done 131 | [*][S]Price for using command??[/S] dONE! 132 | [*][S]Possible portal support??[/S] DONE 133 | 134 | [*][S]griefprevention claim checks??[/S] done 135 | [*][S]Support for factions / factionsuuid / factionsone / fractions / towny / kingdoms / residence / mychunk / yourchunk / redchunk / bluechunk / redprotect / empires / preciousstones / worldguard / fuedal / some random region plugin nobody uses / Did you like / miss the first listed feature / that says it's compatible / with every single region protection plugin?[/S] [B][SIZE=7]DONE[/SIZE][/B] 136 | 137 | [*]Say your suggestion in discussion area to add to this list :) 138 | [/LIST] 139 | 140 | 141 | Source and dev builds are here [URL]https://github.com/acmeproject/WildernessTp[/URL] and we love pull requests, forks, and spoons! Is Wild wild enough for you vote here [URL]http://www.strawpoll.me/10140643[/URL] 142 | [B] 143 | LIKE BIG SERBUR NETWORKS using Wildnerness-TP[/B] 144 | [SPOILER] 145 | - 192.168.1.254 - The Router Network 146 | - mlg.robomwm.com - MLG Fortress (a memetastic serbur!) 147 | 148 | 149 | If u want ur serbur here [URL='https://patreon.com/RoboMWM']subscribe here first[/URL] 150 | [/SPOILER] 151 | 152 | If you feel like helping RoboMWM a.k.a. the guy who's basically 100% maintaining dis plogen now, subscribe to his [URL='http://patreon.com/robomwm']patreon[/URL]. 153 | 154 | If you feel like helping LaxWasHere out, subscribe to his [URL='https://www.patreon.com/LaxWasHere']patreon[/URL] or you can donate directly to his paypal by clicking [URL='http://paypal.me/LaxWasHere']this[/URL] 155 | 156 | [SIZE=5]Support: [URL='https://kiwiirc.com/client/irc.spi.gt/#wilderness-tp']chat[/URL] or on [URL='https://github.com/AcmeProject/WildernessTp']GitHub[/URL] or on [URL='https://discord.gg/XjW6Kuk33g']Dumcord[/URL][/SIZE] 157 | -------------------------------------------------------------------------------- /src/main/java/net/poweredbyhate/wildtp/WildTP.java: -------------------------------------------------------------------------------- 1 | package net.poweredbyhate.wildtp; 2 | 3 | import java.io.IOException; 4 | import java.util.HashMap; 5 | import java.util.UUID; 6 | import java.util.concurrent.Callable; 7 | 8 | import org.bstats.bukkit.Metrics; 9 | import org.bukkit.Bukkit; 10 | import org.bukkit.Location; 11 | import org.bukkit.World; 12 | import org.bukkit.configuration.ConfigurationSection; 13 | import org.bukkit.configuration.file.FileConfiguration; 14 | import org.bukkit.plugin.RegisteredServiceProvider; 15 | import org.bukkit.plugin.java.JavaPlugin; 16 | import org.bukkit.scheduler.BukkitRunnable; 17 | import me.ryanhamshire.GriefPrevention.DataStore; 18 | import me.ryanhamshire.GriefPrevention.GriefPrevention; 19 | import net.milkbowl.vault.economy.Economy; 20 | 21 | /** 22 | * Created by John on 5/5/2016. 23 | */ 24 | public class WildTP extends JavaPlugin { 25 | private boolean wamuppahTooCool = false; 26 | static boolean 27 | ab, enableUselessGUI, isDebug, newPlayersTeleported, noCreditJustCash, notPaper, 28 | useExperimentalChekar, useOtherChekar, useRandomeWorldz, wb; 29 | static ConfigurationSection randomeWorlds; 30 | static DataStore dataaaastorege; 31 | static Economy econ; 32 | static Location cash; 33 | static TooWildForEnums enums; 34 | static WildTP instace; 35 | String[] bluredLines; 36 | PortalzGoneWild portalz; 37 | HashMap aliaz; 38 | HashMap thugz; 39 | HashMap ohWait; 40 | 41 | public void onEnable() { 42 | if (Integer.parseInt(Bukkit.getBukkitVersion().split("[.\\-]")[1]) <= 12) { 43 | getLogger().severe("This version of Wilderness-TP does not support your ancient server version."); 44 | getLogger().warning("Either update your server to 1.13, or use Wild 1.52"); 45 | getLogger().warning("http://r.robomwm.com/oldwild"); 46 | getServer().getPluginManager().disablePlugin(this); 47 | return; 48 | } 49 | try { Class.forName("com.destroystokyo.paper.PaperConfig"); } catch (Throwable cue) { 50 | getLogger().info(" = = = = = = = = = = = = = = = = = = = ="); 51 | getLogger().info(" "); 52 | getLogger().warning("Btw, dis wild plugin (and ur server) would be a bazillion times"); 53 | getLogger().warning("faster and wilder if u switch 2 Paper/Tuinity/Purpur/etc. for async chunk loading/generation."); 54 | getLogger().warning("Until then, we'll just go wild at ur serburs slower/laggier pace."); 55 | getLogger().warning(" "); 56 | getLogger().warning("Get Paper at https://papermc.io"); 57 | getLogger().warning("Get Tuinity at https://github.com/Spottedleaf/Tuinity"); 58 | getLogger().warning("Get Purpur at https://github.com/pl3xgaming/Purpur"); 59 | getLogger().info(" "); 60 | getLogger().info(" = = = = = = = = = = = = = = = = = = = ="); notPaper = true; 61 | } 62 | instace = this; 63 | ohWait = new HashMap(); 64 | 65 | wildDependencies(); 66 | reloadConfig(); 67 | wildMetrics(); 68 | 69 | enums = new TooWildForEnums(); 70 | portalz = new PortalzGoneWild(this); 71 | 72 | getCommand("wild").setExecutor(new CommandsGoneWild(this)); 73 | getCommand("wildtp").setExecutor(new AdminsGoneWild(this)); 74 | 75 | Bukkit.getPluginManager().registerEvents(new WildSignListener(this), this); 76 | Bukkit.getPluginManager().registerEvents(new WildTPListener(), this); 77 | Bukkit.getPluginManager().registerEvents(new OuchieListener(), this); 78 | Bukkit.getPluginManager().registerEvents(portalz, this); 79 | Bukkit.getPluginManager().registerEvents(new CNNListener(), this); 80 | 81 | if (enableUselessGUI) Bukkit.getPluginManager().registerEvents(new GeeYouEye(), this); 82 | if (newPlayersTeleported) Bukkit.getPluginManager().registerEvents(new NoobieListener(), this); 83 | if (wamuppahTooCool) Bukkit.getPluginManager().registerEvents(new TooCool2Teleport(), this); 84 | } 85 | 86 | @Override 87 | public void onDisable() { 88 | super.onDisable(); 89 | Bukkit.getScheduler().cancelTasks(this); 90 | } 91 | 92 | @Override 93 | public void reloadConfig() { 94 | super.reloadConfig(); 95 | new TooWildForEnums().loadConfig(); 96 | // Copy the default config file from jar/resources/config.yml to plugins/wild/config.yml if not exists 97 | saveDefaultConfig(); 98 | // Read the config (existing config or new one) 99 | FileConfiguration config = getConfig(); 100 | // Merge default values 101 | config.addDefault("useGlobalClaimCheck", dataaaastorege == null); 102 | config.options().copyDefaults(true); 103 | // Do things with worlds 104 | aliaz = new HashMap(); 105 | thugz = new HashMap(); 106 | 107 | ChecKar sharedOrNot = config.getBoolean("shareCoolDown") ? new ChecKar(config.getInt("Cooldown")) : null; 108 | wamuppahTooCool = (config.getInt("Wait") > 0); 109 | 110 | for (World world : Bukkit.getWorlds()) { 111 | String name = world.getName(), alias = config.getString("worldsAliaz." + name, name); 112 | config.set("worldsAliaz." + name, alias); 113 | WorldConfig wc = new WorldConfig(world, config, sharedOrNot); 114 | wamuppahTooCool |= (wc.wamuppah > 0); 115 | aliaz.put(name, alias); 116 | thugz.put(name, wc); 117 | } 118 | // Re-save (so omitted and new parameters are added in the file) 119 | saveConfig(); 120 | getWild(config); 121 | } 122 | 123 | public void getWild(FileConfiguration config) { 124 | ab = config.getBoolean("cooldownMsgUsesActionBar"); 125 | isDebug = config.getBoolean("debug"); 126 | newPlayersTeleported = config.getBoolean("teleportNewPlayers"); 127 | randomeWorlds = config.getConfigurationSection("randomWorlds"); 128 | useExperimentalChekar = config.getBoolean("useGlobalClaimCheck"); 129 | useRandomeWorldz = config.getBoolean("useRandomWorlds"); 130 | enableUselessGUI = config.getBoolean("enableGUI"); //https://www.spigotmc.org/threads/wilderness-tp.145440/page-24#post-3381048 131 | useOtherChekar = config.getBoolean("useAlternativeGlobalClaimCheck"); 132 | bluredLines = new String[] { 133 | TooWildForEnums.translate(config.getString("signTexts.line1")), 134 | TooWildForEnums.translate(config.getString("signTexts.line2")), 135 | TooWildForEnums.translate(config.getString("signTexts.line3")), 136 | config.getString("signTexts.createWith"), 137 | TooWildForEnums.translate(config.getString("signTexts.costFree")), 138 | TooWildForEnums.translate(config.getString("signTexts.costMoney")) 139 | }; 140 | } 141 | 142 | public void wildDependencies() { 143 | new BukkitRunnable() { 144 | @Override 145 | public void run() { 146 | if (getServer().getPluginManager().getPlugin("Vault") != null) { 147 | RegisteredServiceProvider rsp = getServer().getServicesManager() 148 | .getRegistration(Economy.class); 149 | if (rsp != null) 150 | econ = rsp.getProvider(); 151 | } 152 | } 153 | }.runTask(instace); 154 | try { dataaaastorege = ((GriefPrevention) (getServer().getPluginManager() 155 | .getPlugin("GriefPrevention"))).dataStore; 156 | } catch (Throwable rock) { dataaaastorege = null; } 157 | wb = getServer().getPluginManager().isPluginEnabled("WorldBorder"); 158 | } 159 | 160 | public static void debug(Object o) { 161 | if (isDebug) System.out.println("[WildTP] " + o); 162 | } 163 | 164 | public void wildMetrics() { 165 | try { new Metricsa(this).start(); } catch (IOException e) {} 166 | try { 167 | Metrics metrics = new Metrics(this, 3316); 168 | 169 | metrics.addCustomChart(new Metrics.SimplePie("bukkit_impl", new Callable() { 170 | @Override 171 | public String call() throws Exception { 172 | return getServer().getVersion().split("-")[1]; 173 | } 174 | })); 175 | 176 | for (final String key : getConfig().getKeys(false)) { 177 | if (getConfig().isBoolean(key) && !getConfig().isInt(key) && !getConfig().isString(key)) 178 | metrics.addCustomChart(new Metrics.SimplePie(key.toLowerCase(), new Callable() { 179 | @Override 180 | public String call() throws Exception { 181 | return getConfig().getString(key); 182 | } 183 | })); 184 | } 185 | } 186 | catch (Throwable rock) {} 187 | } 188 | } 189 | -------------------------------------------------------------------------------- /src/main/java/net/poweredbyhate/wildtp/WorldConfig.java: -------------------------------------------------------------------------------- 1 | package net.poweredbyhate.wildtp; 2 | 3 | import java.util.HashMap; 4 | import java.util.HashSet; 5 | import java.util.List; 6 | import javax.annotation.Nullable; 7 | import org.bukkit.Bukkit; 8 | import org.bukkit.World; 9 | import org.bukkit.WorldBorder; 10 | import org.bukkit.boss.BarColor; 11 | import org.bukkit.boss.BarStyle; 12 | import org.bukkit.configuration.ConfigurationSection; 13 | import org.bukkit.potion.PotionEffect; 14 | import org.bukkit.potion.PotionEffectType; 15 | import com.wimbli.WorldBorder.BorderData; 16 | import com.wimbli.WorldBorder.Config; 17 | import net.poweredbyhate.wildtp.TeleportGoneWild.Trigger; 18 | 19 | /** 20 | * Created by arboriginal on 7/10/2019. 21 | */ 22 | class WorldConfig { 23 | private int minXY, maxXY; 24 | 25 | boolean bar_enabled, doCommandz, dr0p1n, freeze, freezePortal, moveCancel, moveCancelPortal, 26 | bypass_cooldown_cmd, 27 | bypass_cooldown_gui, 28 | bypass_cooldown_guy, 29 | bypass_cooldown_sg1, 30 | bypass_cooldown_pan, 31 | bypass_cost_cmd, 32 | bypass_cost_gui, 33 | bypass_cost_guy, 34 | bypass_cost_sg1, 35 | bypass_cost_pan, 36 | bypass_delay_cmd, 37 | bypass_delay_gui, 38 | bypass_delay_guy, 39 | bypass_delay_sg1, 40 | bypass_delay_pan, harlemShake, whoYaGonaCall; 41 | 42 | double fusRoDah; 43 | 44 | int coolDownTeim, cost, dr0pFr0m, retries, confirmDelay, maxX, maxZ, minX, minZ, wamuppah, 45 | portal_max_x, portal_max_y, portal_max_z; 46 | 47 | BarColor bar_color_searching, bar_color_waiting; 48 | BarStyle bar_style_searching, bar_style_waiting; 49 | ChecKar checKar; 50 | HashSet bioman, commando, nonoBlocks, portal_gms; 51 | World world; 52 | 53 | HashMap effects; 54 | 55 | WorldConfig(World madWorld, ConfigurationSection c, @Nullable ChecKar shared) { 56 | world = madWorld; 57 | ConfigurationSection s = c.getConfigurationSection("overrides." + madWorld.getName()); 58 | bar_enabled = b("enableBar", s, c); 59 | bioman = h("BlockedBiomes", s, c); 60 | bypass_cooldown_cmd = b("Bypass.cooldown.COMMAND", s, c); 61 | bypass_cooldown_gui = b("Bypass.cooldown.GUI", s, c); 62 | bypass_cooldown_guy = b("Bypass.cooldown.OTHERGUY", s, c); 63 | bypass_cooldown_pan = b("Bypass.cooldown.SIGN", s, c); 64 | bypass_cooldown_sg1 = b("Bypass.cooldown.PORTAL", s, c); 65 | bypass_cost_cmd = b("Bypass.cost.COMMAND", s, c); 66 | bypass_cost_gui = b("Bypass.cost.GUI", s, c); 67 | bypass_cost_guy = b("Bypass.cost.OTHERGUY", s, c); 68 | bypass_cost_pan = b("Bypass.cost.SIGN", s, c); 69 | bypass_cost_sg1 = b("Bypass.cost.PORTAL", s, c); 70 | bypass_delay_cmd = b("Bypass.delay.COMMAND", s, c); 71 | bypass_delay_gui = b("Bypass.delay.GUI", s, c); 72 | bypass_delay_guy = b("Bypass.delay.OTHERGUY", s, c); 73 | bypass_delay_pan = b("Bypass.delay.SIGN", s, c); 74 | bypass_delay_sg1 = b("Bypass.delay.PORTAL", s, c); 75 | commando = h("PostCommands", s, c); 76 | confirmDelay = i("paidTPconfirmation", s, c); 77 | coolDownTeim = i("Cooldown", s, c); 78 | cost = i("Cost", s, c); 79 | doCommandz = b("DoCommands", s, c); 80 | dr0p1n = b("dropPlayerFromAbove", s, c); 81 | dr0pFr0m = i("dropPlayerFromHeight", s, c); 82 | freeze = b("freezeWhileRTP", s, c); 83 | freezePortal = b("Portals.freezeWhileRTP", s, c); 84 | fusRoDah = d("Portals.push", s, c); 85 | harlemShake = b("movingBorder", s, c); 86 | moveCancel = b("moveCancelRTP", s, c); 87 | moveCancelPortal = b("Portals.moveCancelRTP", s, c); 88 | nonoBlocks = h("BlockedBlocks", s, c); 89 | portal_gms = h("Portals.Gamemodes", s, c); 90 | portal_max_x = i("Portals.xMax", s, c); 91 | portal_max_y = i("Portals.yMax", s, c); 92 | portal_max_z = i("Portals.zMax", s, c); 93 | retries = i("Retries", s, c); 94 | wamuppah = i("Wait", s, c); 95 | whoYaGonaCall = b("callFiremenInNether", s, c); 96 | checKar = (shared == null) ? new ChecKar(coolDownTeim) : shared; 97 | effects = hurryPeter(s, c, wamuppah); 98 | if (bar_enabled) paulDance(s, c); 99 | maxXY = i("MaxXY", s, c); 100 | minXY = i("MinXY", s, c); 101 | weNeedToBuildaWallTrumpSaidItAndObviouslyEverybodyLikeHim(); 102 | } 103 | 104 | void weNeedToBuildaWallTrumpSaidItAndObviouslyEverybodyLikeHim() { 105 | if (WildTP.wb) { 106 | WildTP.debug("worldborder plugin detected"); 107 | BorderData b = Config.Border(world.getName()); 108 | // We don't need no education... 109 | if (b != null) { 110 | Boolean s = b.getShape(); 111 | int x = b.getRadiusX(), z = b.getRadiusZ(); 112 | // (guitar riff) 113 | if ((s == null && Config.ShapeRound()) || (s != null && s)) { 114 | x = (int) (Math.sqrt(2) * x) / 2; 115 | z = (int) (Math.sqrt(2) * z) / 2; 116 | } 117 | // We don't need no thought control... 118 | sendBrick(minXY, maxXY, (int) b.getX() - x, (int) b.getX() + x, (int) b.getZ() - z, (int) b.getZ() + z); 119 | return; 120 | } 121 | } 122 | WildTP.debug("WorldBorder plugin not detected (or border not set), checking for vanilla's"); 123 | WorldBorder b = world.getWorldBorder(); 124 | if (b == null) return; 125 | int r = (int) b.getSize() / 2, x = b.getCenter().getBlockX(), z = b.getCenter().getBlockZ(); 126 | sendBrick(minXY, maxXY, x - r, x + r, z - r, z + r); 127 | } 128 | 129 | private boolean b(String k, ConfigurationSection v, ConfigurationSection d) { 130 | if (v != null && v.contains(k)) 131 | return v.getBoolean(k); 132 | return d.getBoolean(k); 133 | } 134 | 135 | private double d(String k, ConfigurationSection v, ConfigurationSection d) { 136 | return ((v != null && v.contains(k)) ? v.getDouble(k) : d.getDouble(k)); 137 | } 138 | 139 | private HashSet h(String k, ConfigurationSection v, ConfigurationSection d) { 140 | return new HashSet((v != null && v.contains(k)) ? v.getStringList(k) : d.getStringList(k)); 141 | } 142 | 143 | private int i(String k, ConfigurationSection v, ConfigurationSection d) { 144 | return (v != null && v.contains(k)) ? v.getInt(k) : d.getInt(k); 145 | } 146 | 147 | private HashMap hurryPeter(ConfigurationSection v, ConfigurationSection d, int w) { 148 | HashMap map = new HashMap(); 149 | for (Trigger when : Trigger.values()) { 150 | HashSet effects = new HashSet(); 151 | String emmaString = "Effects." + when.toString(); 152 | List emmaGivDis = (v != null && v.contains(emmaString)) ? v.getStringList(emmaString) : d.getStringList(emmaString); 153 | emmaGivDis.forEach(patronus -> 154 | { 155 | String[] spell = patronus.split(":"); 156 | PotionEffectType agrud = PotionEffectType.getByName(spell[0]); 157 | if (agrud == null) return; 158 | int voldo = 0; 159 | if (spell.length == 2) 160 | try 161 | { 162 | voldo = Integer.parseInt(spell[1]); 163 | } 164 | catch (NumberFormatException e) {} 165 | effects.add(new PotionEffect(agrud, w + 1200, voldo, false, false, false)); 166 | }); 167 | map.put(when, (PotionEffect[]) effects.toArray(new PotionEffect[] {})); 168 | } 169 | return map; 170 | } 171 | 172 | private String s(String k, ConfigurationSection v, ConfigurationSection d) { 173 | return (v != null && v.contains(k)) ? v.getString(k) : d.getString(k); 174 | } 175 | 176 | private void paulDance(ConfigurationSection v, ConfigurationSection d) { 177 | try { 178 | bar_color_searching = BarColor.valueOf(s("barColor.searching", v, d)); 179 | bar_color_waiting = BarColor.valueOf(s("barColor.waiting", v, d)); 180 | bar_style_searching = BarStyle.valueOf(s("barStyle.searching", v, d)); 181 | bar_style_waiting = BarStyle.valueOf(s("barStyle.waiting", v, d)); 182 | } 183 | catch (Exception e) { 184 | WildTP.instace.getLogger().warning("Your bossbar settings are wrong... bar disabled."); 185 | bar_enabled = false; 186 | } 187 | } 188 | 189 | private void sendBrick(int minXY, int maxXY, int x, int X, int z, int Z) { 190 | minX = Math.max(x, minXY); 191 | maxX = Math.min(X, maxXY); 192 | minZ = Math.max(z, minXY); 193 | maxZ = Math.min(Z, maxXY); 194 | 195 | WildTP.debug(world.getName() + " borders: " + minX + ";" + maxX + ":" + minZ + ";" + maxZ); 196 | } 197 | } 198 | -------------------------------------------------------------------------------- /src/main/resources/config.yml: -------------------------------------------------------------------------------- 1 | # Wilderness-Tp configuration file 2 | # . 3 | # You can retrieve all those parameters with explanation on the online default config: 4 | # https://github.com/AcmeProject/WildernessTp/blob/master/src/main/resources/config.yml 5 | # . 6 | # Detailled & up2date plugin permissions list can be read here: 7 | # https://github.com/AcmeProject/WildernessTp/blob/master/src/main/resources/plugin.yml 8 | # . 9 | # bonus memo: 10 | # - Sounds: https://hub.spigotmc.org/javadocs/bukkit/org/bukkit/Sound.html 11 | # - Biomes: https://hub.spigotmc.org/javadocs/spigot/org/bukkit/block/Biome.html 12 | # - Blocks: https://hub.spigotmc.org/javadocs/spigot/org/bukkit/Material.html 13 | # - Bar colors: https://hub.spigotmc.org/javadocs/spigot/org/bukkit/boss/BarColor.html 14 | # - Bar styles: https://hub.spigotmc.org/javadocs/spigot/org/bukkit/boss/BarStyle.html 15 | # - Gamemodes: https://hub.spigotmc.org/javadocs/spigot/org/bukkit/GameMode.html 16 | # - Effects: https://hub.spigotmc.org/javadocs/spigot/org/bukkit/potion/PotionEffectType.html 17 | # FYI, you really should consider using Paper (https://papermc.io) 18 | # or any fork of it (e.g. Airplane, Purpur etc.) so that you benefit from async chunk generation/loading 19 | 20 | # use "debug: true" to provide debug messages in console/logs to assist in fixing bugs 21 | debug: false 22 | 23 | # If true, cooldown messages will use actionbar instead of chat 24 | # (this is useful not to spam it when players tries to reach a portal) 25 | cooldownMsgUsesActionBar: true 26 | 27 | # dere, configurable 28 | enableGUI: true 29 | 30 | # If true, a bossbar will be displayed to the player while waiting for the RTP proceed 31 | enableBar: true 32 | barColor: 33 | searching: YELLOW 34 | waiting: GREEN 35 | barStyle: 36 | searching: SEGMENTED_6 37 | waiting: SOLID 38 | 39 | # If false, cooldowns are per world not global 40 | shareCoolDown: true # /!\ If true, overriden values of "Cooldown" will be ignored 41 | # If true, extinguish adjacent blocks in nether after a WildTP 42 | callFiremenInNether: false # (Ignored if not in nether) 43 | 44 | # If true, if you request a RTP, you cannot move until its done 45 | freezeWhileRTP: false 46 | # If true, if you request a RTP and move, this will cancel it 47 | moveCancelRTP: true 48 | 49 | # Sound played when your player gone wild /!\ Invalid values will disable it 50 | Sound: ENTITY_ENDERMAN_TELEPORT 51 | # Anything greater than one just increases the radius. 52 | Volume: 1 53 | 54 | BlockedBiomes: # Use « [] » if you don't want to restrict 55 | - COLD_OCEAN 56 | - DEEP_COLD_OCEAN 57 | - DEEP_FROZEN_OCEAN 58 | - DEEP_LUKEWARM_OCEAN 59 | - DEEP_OCEAN 60 | - DEEP_WARM_OCEAN 61 | - FROZEN_OCEAN 62 | - FROZEN_OCEAN 63 | - LUKEWARM_OCEAN 64 | - OCEAN 65 | - RIVER 66 | - WARM_OCEAN 67 | 68 | BlockedBlocks: # Use « [] » if you don't want to restrict 69 | - CACTUS 70 | - FIRE 71 | - LAVA 72 | - MAGMA_BLOCK 73 | - AIR 74 | - VOID_AIR 75 | - CAVE_AIR 76 | 77 | Portals: 78 | # Gamemode NOT listed here will ignore portals (e.g., remove CREATIVE if you don't want to be teleported when in a portal while in creative mode) 79 | Gamemodes: 80 | - ADVENTURE 81 | - SURVIVAL 82 | - CREATIVE 83 | # If true, a player enterring a portal is frozen until it's done 84 | freezeWhileRTP: false 85 | # If true, if you enter a portal and move, this will cancel the RTP 86 | moveCancelRTP: true 87 | # Max size in each axis (in block, 0 will disable the limitation) 88 | # /!\ This doesn't affect previously created portals. 89 | xMax: 10 90 | yMax: 10 91 | zMax: 10 92 | # When a player try to reach a portal when being in cooldown, this push him back 93 | push: 1.0 # Force of the push (float), put 0 or less to disable 94 | # /!\ Big values can be fun but will hurt & irritate your players... I mean literally! 95 | 96 | Bypass: # /!\ Those settings FORCE bypass, whether the player has permission or not! 97 | # Force permission « wild.wildtp.cooldown.bypass » 98 | cooldown: 99 | COMMAND: false # When the player tp via command 100 | GUI: false # When using the GUI 101 | OTHERGUY: true # When another player teleport you (typically staff) 102 | PORTAL: false # When passing a wild portal 103 | SIGN: false # When interacting with a wild sign 104 | # Force permission « wild.wildtp.world.*.free » 105 | cost: 106 | COMMAND: false 107 | GUI: false 108 | OTHERGUY: true 109 | PORTAL: false 110 | SIGN: false 111 | # Force permission « wild.wildtp.delay.bypass » 112 | delay: 113 | COMMAND: false 114 | GUI: false 115 | OTHERGUY: true 116 | PORTAL: true 117 | SIGN: false 118 | 119 | # Format is or : (integer) 120 | # /!\ Invalid multiplier will fallback to 0 121 | Effects: 122 | COMMAND: 123 | - BLINDNESS 124 | - CONFUSION:99 125 | - SLOW_DIGGING:3 126 | GUI: [] # <== This represent an empty list (no effects) 127 | JOIN: # Require « teleportNewPlayers: true » 128 | - BLINDNESS 129 | - CONFUSION 130 | OTHERGUY: [] 131 | PORTAL: 132 | - BLINDNESS 133 | - CONFUSION 134 | - INVISIBILITY 135 | - SLOW:2 136 | SIGN: [] 137 | 138 | # Bounds of the wildness (named XY and not XZ... Another proof! #CatEarthSociety) 139 | MinXY: -5000 140 | MaxXY: 5000 141 | # If true, border is recalculated each RTP - useful if you set your border to grow/shrink (so you should keep it false if not required) 142 | movingBorder: false 143 | 144 | Wait: 0 # (seconds) Time the player have to wait between he type the command and tp be sent in wild 145 | Retries: 6 # Max attempts the plugin will try to find a safe place to tp the player 146 | Cooldown: 0 # (seconds) Time to wait before player can re-do again 147 | 148 | Cost: 0 # Money cost of a RTP (requires Vault) 149 | paidTPconfirmation: 30 # If the RTP has a cost, a confirmation will be asked to the player... 150 | # This is (in second) the time this pending RTP stay valid. (set to 0 if you don't want confirmations) 151 | 152 | teleportNewPlayers: false # Choose "true" if you are not proud of your spawn 153 | dropPlayerFromAbove: false # Choose "true" if you vocal on dumcord and want to hear them scream. Or as I originally intended this to be, a dropship-like teleport 154 | dropPlayerFromHeight: 255 # Height from where the player is dropped (if dropPlayerFromAbove is true) 155 | # /!\ Using too high values can cause issues in some cases... Test before letting your players use them. 156 | # For example, using 300 with datapack "EndAboveOverworld" load the end, then reload overworld... 157 | # (This stops the sound prematurely, perturb the player + load / unload chunks for nothing) 158 | 159 | DoCommands: false # « Do it! » (Shia Labeouf) 160 | PostCommands: # Ignored if DoCommands is false 161 | - 'title %PLAYER% times 20 100 20' 162 | - 'title %PLAYER% title ["",{"text":"Wilderness","color":"green","bold":false}]' 163 | - 'title %PLAYER% subtitle ["",{"text":"Its too dangerous to go alone.","color":"yellow"}]' 164 | # Note: %PLAYER% will be replaced by... the player name! (if you had it, you won 1 point) 165 | # You can also use %X% and %Z% as X and Z coords of new location of the player. 166 | # Example: 167 | # - 'title %PLAYER% subtitle ["",{"text":"Coords %X% / %Z% are so wild!","color":"yellow"}]' 168 | 169 | useRandomWorlds: false 170 | randomWorlds: # Ignored if useRandomWorlds is false 171 | world: 1337 172 | world_nether: 42 173 | 174 | useGlobalClaimCheck: true # (if GriefPrevention plugin is found, default value will be false) 175 | useAlternativeGlobalClaimCheck: false # If you see errors like "Could not pass BlockBreakEvent..." then enable this instead of the global claim check 176 | 177 | signTexts: 178 | # This is what player have to type on a sign (first or second line) to create a WildTP sign 179 | createWith: "[wildtp]" # (case insensitive: means you can write with caps or not) 180 | # (optionaly, the player can write the EXACT name or alias of a world ON LINE 2) 181 | 182 | # This is how WildTP signs will appear 183 | # /!\ If you change this, previously created signs will no more work until you recreate them! 184 | # (same if you use %COST% in texts and change the amount) 185 | line1: "&4====================" 186 | line2: "[&1Wild&0]" 187 | line3: "&4====================" 188 | # (line4 is reserved to display the (optional) world name) 189 | # You can use %COST% as a placeholder for the amount of money the server will rob to the player 190 | 191 | costFree: "&b&lFREE" # How to display cost when it's free 192 | costMoney: "&4%COST% $" # How to display cost when it takes money 193 | 194 | # Example: 195 | # line1: "&8== %COST% &8==" # will give « &8== &b&lFREE &8== » OR « &8== &4100 $ &8== » 196 | # line2: "[&1Wild&0]" 197 | # line3: "&8(right click)" 198 | 199 | # As world names will appear on your WildTP signs, and signs cannot have long lines, 200 | # if a name is too long, it will creates issues (not recognized by the plugin...) 201 | # so you should create short aliases for your worlds (which could also be more understandable by you players) 202 | worldsAliaz: {} 203 | # /!\ This parameter is automatically filled (if empty) by your existing worlds when the plugin starts. 204 | # so, you will see something like that: 205 | # 206 | # worldsAliaz: 207 | # world: world 208 | # world_nether: world_nether 209 | # world_the_end: world_the_end 210 | # 211 | # Now, if you want to customize how worlds name will appear on WildTP signs, do this: 212 | # (this example, you can put whatever names you want...) 213 | # 214 | # worldsAliaz: 215 | # world: ElMondo 216 | # world_nether: Hell 217 | # world_the_end: End 218 | 219 | # You can override almost all parameters per world in this section. 220 | # This is pretty simple: You just have to add a section with the name of the world (not the alias, its real name), 221 | # and put in it the parameter you want to override. All omitted ones will use default config. 222 | overrides: {} # <=== « {} » means there is no overrides at all 223 | 224 | # Examples: 225 | # 226 | # overrides: # (with all parameters you can override) 227 | # an_example: 228 | # BlockedBiomes: 229 | # - JUNGLE 230 | # - MOUNTAINS 231 | # BlockedBlocks: 232 | # - STONE 233 | # - GRASS 234 | # freezeWhileRTP: true 235 | # moveCancelRTP: false 236 | # MinXY: -1000 237 | # MaxXY: 1000 238 | # movingBorder: true 239 | # Wait: 0 240 | # Retries: 1 241 | # Cooldown: 0 242 | # Cost: 99999 243 | # paidTPconfirmation: 120 244 | # DoCommands: false 245 | # PostCommands: [] 246 | # callFiremenInNether: false 247 | # dropPlayerFromAbove: true 248 | # dropPlayerFromHeight: 128 249 | # Bypass: 250 | # cooldown: 251 | # PORTAL: true 252 | # cost: 253 | # PORTAL: true 254 | # delay: 255 | # PORTAL: true 256 | # enableBar: true 257 | # barColor: 258 | # searching: PINK 259 | # waiting: PURPLE 260 | # barStyle: 261 | # searching: SEGMENTED_20 262 | # waiting: SEGMENTED_12 263 | # Portals: 264 | # Gamemodes: 265 | # - ADVENTURE 266 | # - CREATIVE 267 | # - SPECTATOR 268 | # - SURVIVALL 269 | # freezeWhileRTP: true 270 | # moveCancelRTP: false 271 | # xMax: 2 272 | # yMax: 3 273 | # zMax: 2 274 | # push: 0 275 | # Effects: 276 | # COMMAND: 277 | # - BLINDNESS 278 | # GUI: [] 279 | # JOIN: [] 280 | # OTHERGUY: [] 281 | # PORTAL: 282 | # - CONFUSION 283 | # SIGN: [] 284 | # 285 | # another_working_example: # (to show you don't have to add all parameters) 286 | # MinXY: -50000 287 | # MaxXY: 50000 288 | -------------------------------------------------------------------------------- /src/main/java/net/poweredbyhate/wildtp/TeleportGoneWild.java: -------------------------------------------------------------------------------- 1 | package net.poweredbyhate.wildtp; 2 | 3 | import static net.poweredbyhate.wildtp.WildTP.instace; 4 | import static net.poweredbyhate.wildtp.WildTP.randomeWorlds; 5 | import static net.poweredbyhate.wildtp.WildTP.useRandomeWorldz; 6 | import java.util.LinkedHashMap; 7 | import java.util.Map; 8 | import java.util.UUID; 9 | 10 | import io.papermc.lib.PaperLib; 11 | import net.md_5.bungee.api.ChatMessageType; 12 | import org.bukkit.Bukkit; 13 | import org.bukkit.Location; 14 | import org.bukkit.Material; 15 | import org.bukkit.NamespacedKey; 16 | import org.bukkit.World; 17 | import org.bukkit.block.Block; 18 | import org.bukkit.block.BlockFace; 19 | import org.bukkit.boss.BarColor; 20 | import org.bukkit.boss.BarStyle; 21 | import org.bukkit.boss.KeyedBossBar; 22 | import org.bukkit.entity.Player; 23 | import org.bukkit.event.player.PlayerTeleportEvent; 24 | import org.bukkit.potion.PotionEffect; 25 | import org.bukkit.scheduler.BukkitRunnable; 26 | import net.md_5.bungee.api.chat.ClickEvent; 27 | import net.md_5.bungee.api.chat.ComponentBuilder; 28 | import net.md_5.bungee.api.chat.HoverEvent; 29 | import net.md_5.bungee.api.chat.TextComponent; 30 | 31 | public class TeleportGoneWild { 32 | private boolean[] boo; 33 | private Direction way; 34 | private final Trigger how; 35 | private final Player who; 36 | private PotionEffect[] queen; 37 | private World whr; 38 | private WorldConfig wc; 39 | private int retries; 40 | 41 | enum Direction { 42 | EAST, NORTH, SOUTH, WEST 43 | } 44 | 45 | enum Trigger { 46 | COMMAND, GUI, JOIN, OTHERGUY, PORTAL, SIGN 47 | } 48 | 49 | static final String openSesame = "$hut Up And Take My M0ney!"; 50 | 51 | TeleportGoneWild(final Trigger trigger, final Player p) { 52 | this(trigger, p, null); 53 | } 54 | 55 | TeleportGoneWild(final Trigger trigger, final Player p, World w) { 56 | how = trigger; 57 | who = p; 58 | whr = w; 59 | } 60 | 61 | boolean WildTeleport() { 62 | return WildTeleport(null); 63 | } 64 | 65 | boolean WildTeleport(Direction direction) { 66 | return cook(direction) && realTeleportt(); 67 | } 68 | 69 | static private KeyedBossBar auscultate(Player sickPlayer, BarColor color, BarStyle style) { 70 | NamespacedKey key = cerealKiller(sickPlayer); 71 | KeyedBossBar bossbar = Bukkit.getBossBar(key); 72 | 73 | if (bossbar == null) { 74 | bossbar = Bukkit.createBossBar(key, "", color, style); 75 | bossbar.addPlayer(sickPlayer); 76 | bossbar.setVisible(true); 77 | } 78 | else { 79 | bossbar.setColor(color); 80 | bossbar.setStyle(style); 81 | } 82 | 83 | return bossbar; 84 | } 85 | 86 | static NamespacedKey cerealKiller(Player freddy) { 87 | return new NamespacedKey(instace, "iNoWutUdidLastTick/" + freddy.getUniqueId()); 88 | } 89 | 90 | static void cure(Player guiltyPlayer) { 91 | NamespacedKey key = cerealKiller(guiltyPlayer); 92 | KeyedBossBar bossbar = Bukkit.getBossBar(key); 93 | if (bossbar == null) return; 94 | 95 | bossbar.removeAll(); 96 | Bukkit.removeBossBar(cerealKiller(guiltyPlayer)); 97 | } 98 | 99 | static void focus(Player innocentPlayer, WorldConfig virus, int retry) { 100 | if (!virus.bar_enabled) return; 101 | 102 | final KeyedBossBar bossbar = auscultate(innocentPlayer, virus.bar_color_searching, virus.bar_style_searching); 103 | if (bossbar == null) return; 104 | 105 | int attempt = virus.retries - retry; 106 | 107 | bossbar.setProgress(Math.min((float) attempt / virus.retries, 1)); 108 | bossbar.setTitle(TooWildForEnums.ATTEMPT 109 | .replace("%ATTEMPT%", "" + attempt).replace("%MAX%", "" + virus.retries)); 110 | } 111 | 112 | static void infect(Player innocentPlayer, WorldConfig ebola) { 113 | if (!ebola.bar_enabled) return; 114 | 115 | final KeyedBossBar bossbar = auscultate(innocentPlayer, ebola.bar_color_waiting, ebola.bar_style_waiting); 116 | if (bossbar == null) return; 117 | 118 | final int milk = ebola.wamuppah; 119 | 120 | bossbar.setProgress(1); 121 | bossbar.setTitle(TooWildForEnums.PROCEED); 122 | 123 | new BukkitRunnable() { 124 | int i = 0; 125 | 126 | @Override 127 | public void run() { 128 | if (isCancelled()) return; 129 | if (bossbar == null || bossbar.getPlayers().isEmpty()) { cancel(); return; } 130 | // @formatter:on 131 | int s = milk - ++i; 132 | float l = Math.max((float) s / milk, 0F); 133 | 134 | bossbar.setProgress(l); 135 | bossbar.setTitle((l > 0) ? TooWildForEnums.WAIT_MSG.replace("{wait}", "" + s) 136 | : TooWildForEnums.PROCEED); 137 | } 138 | }.runTaskTimer(instace, 20, 20); 139 | } 140 | 141 | private boolean cook(Direction meat) { 142 | WildTP.debug("starting cook()"); 143 | if (who == null || !who.isOnline()) return false; 144 | if (whr == null) whr = useRandomeWorldz ? getRandomeWorld() : who.getWorld(); 145 | if (whr == null) return false; 146 | // for after the digestion... 147 | wc = instace.thugz.get(whr.getName()); 148 | if (wc == null) return false; 149 | 150 | if (wc.checKar.isInCooldown(who.getUniqueId(), wc, how)) { 151 | String m = TooWildForEnums.COOLDOWN.replace("%TIME%", wc.checKar.getTimeLeft(who)); 152 | if (WildTP.ab) who.spigot().sendMessage(ChatMessageType.ACTION_BAR, new TextComponent(m)); else who.sendMessage(m); 153 | return false; 154 | } 155 | 156 | if (!WildTPListener.chargePlayer(who, wc, how, false)) { 157 | who.sendMessage(TooWildForEnums.translate(TooWildForEnums.NO_MONEY)); 158 | return false; 159 | } 160 | way = meat; 161 | boo = TooCool2Teleport.powerSupply( 162 | wc.freeze || (wc.freezePortal && how == Trigger.PORTAL), 163 | wc.moveCancel || (wc.moveCancelPortal && how == Trigger.PORTAL)); 164 | queen = wc.effects.get(how); 165 | return true; 166 | } 167 | 168 | private boolean realTeleportt() { 169 | WildTP.debug("Wild teleport called for " + who.getName() + " for world " + whr.getName()); 170 | 171 | final long wasteUrTime = ChecKar.getEpoch() + wc.confirmDelay; 172 | final UUID youYouEyeDee = who.getUniqueId(); 173 | // What everybody waiting for... 174 | bangbang(youYouEyeDee); 175 | 176 | BukkitRunnable taskyNhutch = new BukkitRunnable() { 177 | @Override 178 | public void run() { 179 | if (!isCancelled() && ChecKar.getEpoch() < wasteUrTime) { 180 | ChecKar shaker = wc.checKar; 181 | if (shaker.isInCooldown(youYouEyeDee, wc, how)) { 182 | WildTP.debug("In cooldown: yes"); 183 | String m = TooWildForEnums.COOLDOWN.replace("%TIME%", shaker.getTimeLeft(who)); 184 | if (WildTP.ab) who.spigot().sendMessage(ChatMessageType.ACTION_BAR, new TextComponent(m)); else who.sendMessage(m); 185 | } 186 | else 187 | { 188 | retries = wc.retries; 189 | getRandomeLocation(); 190 | } 191 | } 192 | bangbang(youYouEyeDee); 193 | } 194 | }; 195 | 196 | if (wc.cost == 0 || wc.confirmDelay < 1 || bypass("cost")) taskyNhutch.runTask(instace); 197 | else { 198 | instace.ohWait.put(youYouEyeDee, taskyNhutch); 199 | taskyNhutch.runTaskLaterAsynchronously(instace, (wc.confirmDelay + 1) * 20); 200 | oralExam(who, wc.confirmDelay, wc.cost); 201 | } 202 | 203 | return true; 204 | } 205 | 206 | private boolean realTeleportt2(Location loc) { 207 | if (!TooCool2Teleport.isCold(who)) return true; 208 | 209 | PreWildTeleportEvent preWildTeleportEvent = new PreWildTeleportEvent(who, loc, wc, how); 210 | WildTP.debug("Calling preTeleportEvent"); 211 | 212 | Bukkit.getPluginManager().callEvent(preWildTeleportEvent); 213 | WildTP.debug("Called preWildTeleportEvent"); 214 | 215 | if (preWildTeleportEvent.isCancelled()) { 216 | WildTP.debug("preWildTeleport Cancelled"); 217 | return true; 218 | } 219 | 220 | WildTP.debug("preping 2 port 2 " + loc); 221 | 222 | if (wc.wamuppah < 1 || bypass("delay")) goWild(loc); 223 | else { 224 | WildTP.debug("Player needs to wait more: " + wc.wamuppah * 20); 225 | 226 | TooCool2Teleport.addPlayer(who, boo, queen, new BukkitRunnable() { 227 | @Override 228 | public void run() { 229 | WildTP.debug("isCancelled: " + isCancelled()); 230 | if (!isCancelled()) 231 | goWild(loc); 232 | } 233 | }.runTaskLater(instace, wc.wamuppah * 20)); 234 | 235 | TeleportGoneWild.infect(who, wc); 236 | who.sendMessage(TooWildForEnums.WAIT_MSG.replace("{wait}", "" + wc.wamuppah)); 237 | } 238 | 239 | return true; 240 | } 241 | 242 | private World getRandomeWorld() { 243 | Map hesDaMap = new LinkedHashMap(); 244 | Integer totalChance = 0; 245 | 246 | for (String worldString : randomeWorlds.getKeys(false)) { 247 | World vote4Pedro = Bukkit.getWorld(worldString); 248 | 249 | if (vote4Pedro == null) { 250 | Bukkit.getLogger().warning("World « " + worldString + " » does not exist. " 251 | + "We recommend removing the world from randomWorlds in config.yml"); 252 | continue; 253 | } 254 | 255 | int chance = randomeWorlds.getInt(worldString); 256 | if (chance < 1) //fixes bug where setting as 0 overwrites previous entry 257 | continue; 258 | 259 | totalChance += chance; 260 | hesDaMap.put(totalChance, vote4Pedro); 261 | } 262 | 263 | int daChosenOne = WildWarrantTax.r4nd0m(totalChance, 0); 264 | 265 | for (Integer blah : hesDaMap.keySet()) 266 | if (blah >= daChosenOne) 267 | return hesDaMap.get(blah); 268 | return null; 269 | } 270 | 271 | private void getRandomeLocation() { 272 | WildTP.debug("starting getRandomeLocation()"); 273 | TooCool2Teleport.addPlayer(who, boo, queen, null); 274 | if (retries-- < 0) 275 | { 276 | WildTP.debug("No suitable locations found"); 277 | who.sendMessage(TooWildForEnums.NO_LOCATION); 278 | TooCool2Teleport.microwave(who); 279 | return; 280 | } 281 | 282 | if (!TooCool2Teleport.isCold(who)) 283 | { 284 | WildTP.debug(who + " is cold"); 285 | return; 286 | } 287 | 288 | TeleportGoneWild.focus(who, wc, retries); 289 | 290 | new WildWarrantTax(who, wc, way).search().thenAccept(location -> 291 | { 292 | Location loco = location; 293 | if (loco != null) 294 | realTeleportt2(loco); 295 | else 296 | { 297 | WildTP.debug("unsuitable location, trying again."); 298 | getRandomeLocation(); 299 | } 300 | }); 301 | } 302 | 303 | private void goWild(Location loc) { 304 | PaperLib.getChunkAtAsync(loc, true).thenAccept(chunk -> 305 | { 306 | if (!TooCool2Teleport.microwave(who)) 307 | { 308 | WildTP.debug("unmicrowaved leftovers."); 309 | return; 310 | } 311 | 312 | WildTP.debug("Teleporting " + who.getName() + loc); 313 | 314 | if (WildWarrantTax.bonelessIceScream(loc)) { 315 | if (wc.whoYaGonaCall) { 316 | WildTP.debug("Here come the §cfiremen§r!"); 317 | Block block = loc.getBlock(); block.setType(Material.AIR); 318 | for (BlockFace flame : 319 | new BlockFace[] { BlockFace.UP, BlockFace.EAST, BlockFace.NORTH, BlockFace.SOUTH, BlockFace.WEST }) { 320 | Block bed = block.getRelative(flame); if (bed.getType() == Material.FIRE) bed.setType(Material.AIR); 321 | } // How do we sleep while our beds are burning? //Ask St. John Vianney 322 | } 323 | } 324 | else if (wc.dr0p1n) { 325 | WildTP.debug("Drop in feature enabled: Setting y=" + wc.dr0pFr0m); 326 | loc.setY(wc.dr0pFr0m); 327 | loc.setPitch(64); 328 | OuchieListener.plsSaveDisDood(who); 329 | } 330 | 331 | if (!who.teleport(loc.clone().add(0.5, 0.5, 0.5), PlayerTeleportEvent.TeleportCause.COMMAND)) { 332 | WildTP.debug("teleport was canceled."); 333 | return; 334 | } 335 | 336 | WildTP.debug(who.getName() + " Teleported to " + who.getLocation()); 337 | 338 | if (!bypass("cooldown")) { 339 | WildTP.debug(who.getName() + " Adding to cooldown"); 340 | wc.checKar.addKewlzDown(who.getUniqueId()); 341 | WildTP.debug("Added to cooldown " + who.getUniqueId()); 342 | } 343 | 344 | PostWildTeleportEvent postWildTeleportEvent = new PostWildTeleportEvent(who, wc); 345 | Bukkit.getPluginManager().callEvent(postWildTeleportEvent); 346 | }); 347 | } 348 | 349 | private boolean bypass(String what) { 350 | return ChecKar.bypass(what, who, wc, how); 351 | } 352 | 353 | private void bangbang(UUID youYouEyeDe) { 354 | if (instace.ohWait.containsKey(youYouEyeDe)) { 355 | instace.ohWait.remove(youYouEyeDe).cancel(); 356 | } 357 | } 358 | 359 | private void oralExam(Player rafiki, int timon, int pumbaa) { 360 | String[] parTs = TooWildForEnums.CONFIRMSG.replace("%TIME%", "" + timon).replace("%COST%", "" + pumbaa) 361 | .split("%CONFIRM%"); 362 | 363 | rafiki.spigot().sendMessage( 364 | new ComponentBuilder(parTs[0]).append( 365 | new ComponentBuilder(TooWildForEnums.CONFIRMOK) 366 | .event(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/wild " + openSesame)) 367 | .event(new HoverEvent(HoverEvent.Action.SHOW_TEXT, 368 | TextComponent.fromLegacyText(TooWildForEnums.CONFIRMON))) 369 | .create()) 370 | .append(parTs[1]).create()); 371 | } 372 | } 373 | -------------------------------------------------------------------------------- /src/main/java/net/poweredbyhate/wildtp/PortalzGoneWild.java: -------------------------------------------------------------------------------- 1 | package net.poweredbyhate.wildtp; 2 | 3 | import java.io.File; 4 | import java.io.IOException; 5 | import java.util.HashMap; 6 | import java.util.UUID; 7 | import org.bukkit.Bukkit; 8 | import org.bukkit.Location; 9 | import org.bukkit.block.Block; 10 | import org.bukkit.command.CommandSender; 11 | import org.bukkit.configuration.InvalidConfigurationException; 12 | import org.bukkit.configuration.file.FileConfiguration; 13 | import org.bukkit.configuration.file.YamlConfiguration; 14 | import org.bukkit.entity.Player; 15 | import org.bukkit.event.EventHandler; 16 | import org.bukkit.event.EventPriority; 17 | import org.bukkit.event.Listener; 18 | import org.bukkit.event.player.PlayerInteractEvent; 19 | import org.bukkit.event.player.PlayerMoveEvent; 20 | import org.bukkit.event.player.PlayerTeleportEvent; 21 | import org.bukkit.inventory.EquipmentSlot; 22 | import org.bukkit.scheduler.BukkitRunnable; 23 | import org.bukkit.scheduler.BukkitTask; 24 | import org.bukkit.util.Vector; 25 | import net.md_5.bungee.api.chat.ClickEvent; 26 | import net.md_5.bungee.api.chat.ComponentBuilder; 27 | import net.md_5.bungee.api.chat.HoverEvent; 28 | import net.md_5.bungee.api.chat.TextComponent; 29 | import net.poweredbyhate.wildtp.TeleportGoneWild.Trigger; 30 | 31 | /** 32 | * Created by Lax on 10/4/2016. 33 | * . 34 | * I've made some improvements in this class. Big ones: 35 | * - Pre-calculation of portals coords instead of do it for each players moves 36 | * - Also test if the player has moved only once in onMove() for all portals, same for recentTP 37 | * - Change HashMap keys to UUID instead of Player, because the Player object can change, not its UUID 38 | * - isInside() "shitty code" has been removed, now a simplified one is used because locs already sorted 39 | * - ... 40 | */ 41 | class PortalzGoneWild implements Listener { 42 | private final String CONFIG_KEY = "Portals"; 43 | private File portalFile; 44 | private FileConfiguration portalConf; 45 | private WildTP will; 46 | 47 | private HashMap recentTPs = new HashMap(); 48 | private HashMap makers = new HashMap(); 49 | 50 | HashMap ports; 51 | 52 | PortalzGoneWild(WildTP wildwildwest) { 53 | will = wildwildwest; 54 | loadConfig(); 55 | } 56 | 57 | boolean gotoLabel5(Player drunk, String glass) { 58 | PortalMaker portal = ports.get(glass); 59 | if (portal == null) return false; 60 | 61 | Location[] lolo = portal.dimensions(); 62 | if (lolo == null || lolo.length != 2) return false; 63 | 64 | return drunk.teleport(new Location( 65 | lolo[0].getWorld(), 66 | (lolo[0].getX() + lolo[1].getX()) / 2, 67 | Math.min(lolo[0].getY(), lolo[1].getY()), 68 | (lolo[0].getZ() + lolo[1].getZ()) / 2)); 69 | } 70 | 71 | void deletePortal(CommandSender p, String name) { 72 | if (!ports.containsKey(name.toLowerCase())) { 73 | p.sendMessage(TooWildForEnums.PORTAL404); 74 | return; 75 | } 76 | 77 | portalConf.set(CONFIG_KEY + "." + name, null); 78 | WildTP.debug("Got delete portal " + name); 79 | String cat; 80 | 81 | if (saveConfig()) { 82 | ports.remove(name); 83 | cat = TooWildForEnums.PORTALDEL.replace("%NAME%", name); 84 | } 85 | else cat = TooWildForEnums.GENERROR; 86 | 87 | p.sendMessage(cat); 88 | } 89 | 90 | void initPortal(Player p, String name, boolean swat) { 91 | if (!swat && ports.containsKey(name.toLowerCase())) { 92 | p.sendMessage(TooWildForEnums.PORTALEXIST); 93 | return; 94 | } 95 | 96 | WildTP.debug("Got create portal"); 97 | makers.put(p.getUniqueId(), new PortalMaker(name)); // SPOILER IN THE NEXT COMMENT! 98 | p.sendMessage(TooWildForEnums.PORTALBEGIN); // At the end, Marion Portillard dies! 99 | p.sendMessage(TooWildForEnums.PORTALCANCEL); // (and she's not credible at all) 100 | } 101 | 102 | boolean linkPortals(CommandSender knockknock, String judasHole, String keyHole, boolean gloryHole) { 103 | if (!knockknock.hasPermission("wild.link.portals")) return false; 104 | // @formatter:off 105 | PortalMaker judlaw = (judasHole == null) ? null : ports.get(judasHole), 106 | keynie = (keyHole == null) ? null : ports.get(keyHole); 107 | // @formatter:on 108 | if (judlaw == null || keyHole == null) { 109 | knockknock.sendMessage(TooWildForEnums.PORTAL404); 110 | return false; 111 | } 112 | 113 | if (!gloryHole) { 114 | if (judlaw.link != null) { 115 | knockknock.sendMessage(TooWildForEnums.PORTALINKED.replace("%PORTAL%", judasHole)); 116 | return false; 117 | } 118 | 119 | if (keynie.link != null) { 120 | knockknock.sendMessage(TooWildForEnums.PORTALINKED.replace("%PORTAL%", keyHole)); 121 | return false; 122 | } 123 | } 124 | 125 | if (judlaw.link != null && judlaw.link != keyHole) { 126 | PortalMaker old = ports.get(judlaw.link); 127 | old.link = null; 128 | savePortal(old); 129 | } 130 | 131 | if (keynie.link != null && keynie.link != judasHole) { 132 | PortalMaker old = ports.get(keynie.link); 133 | old.link = null; 134 | savePortal(old); 135 | } 136 | 137 | judlaw.link = keyHole; 138 | keynie.link = judasHole; 139 | boolean sux = (savePortal(judlaw) && savePortal(keynie)); 140 | 141 | knockknock.sendMessage(sux ? TooWildForEnums.PORTALINKOK : TooWildForEnums.GENERROR); 142 | return sux; 143 | } 144 | 145 | void listPortals(CommandSender p) { 146 | boolean click = (p instanceof Player && p.hasPermission("wild.wildtp.portals")); 147 | 148 | p.sendMessage("Portals:"); 149 | 150 | ports.forEach((name, portal) -> { 151 | String spam = "- §b§l" + name + "§7:§r " 152 | + portal.one.getBlockX() + "§7/§r" + portal.one.getBlockY() + "§7/§r" + portal.one.getBlockZ() 153 | + " §7<->§r " 154 | + portal.two.getBlockX() + "§7/§r" + portal.two.getBlockY() + "§7/§r" + portal.two.getBlockZ() 155 | + " §7(" + portal.one.getWorld().getName() + ")"; 156 | 157 | if (click) { 158 | p.spigot().sendMessage(new ComponentBuilder(spam) 159 | .event(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/wild portal " + name)) 160 | .event(new HoverEvent(HoverEvent.Action.SHOW_TEXT, 161 | TextComponent.fromLegacyText(TooWildForEnums.PORTALHOVER))) 162 | .create()); 163 | } 164 | else p.sendMessage(spam); 165 | }); 166 | } 167 | 168 | @EventHandler(ignoreCancelled = true) 169 | private void onClick(PlayerInteractEvent event) { 170 | if (event.getHand() == EquipmentSlot.OFF_HAND) return; 171 | 172 | final Block b = event.getClickedBlock(); 173 | if (b == null) return; 174 | 175 | final Player p = event.getPlayer(); 176 | final UUID u = p.getUniqueId(); 177 | PortalMaker m = makers.get(u); 178 | if (m == null) return; 179 | 180 | if (isInsideBermudaTriangle(b.getLocation()) != null) { 181 | p.sendMessage(TooWildForEnums.PORTALHERE); 182 | return; 183 | } 184 | 185 | WorldConfig wc = will.thugz.get(b.getWorld().getName()); 186 | if (wc == null) return; 187 | String r; switch (m.setCorner(b.getLocation(), wc.portal_max_x, wc.portal_max_y, wc.portal_max_z)) { 188 | case 0: r = TooWildForEnums.PORTALSTOP; makers.remove(u); break; 189 | case 1: r = TooWildForEnums.PORTALGOHAN; break; 190 | case 2: 191 | if (allYourBasesAreBelongToUs(m)) { 192 | r = TooWildForEnums.PORTALCONTAIN; 193 | makers.remove(u); 194 | break; 195 | } 196 | 197 | r = (savePortal(m) && makers.remove(u) != null) 198 | ? TooWildForEnums.PORTALADD.replace("%NAME%", m.name) 199 | : TooWildForEnums.GENERROR; 200 | break; 201 | 202 | default: 203 | r = TooWildForEnums.PORTALBIG 204 | .replace("{%xMax%}", "" + wc.portal_max_x) 205 | .replace("{%yMax%}", "" + wc.portal_max_y) 206 | .replace("{%zMax%}", "" + wc.portal_max_z); 207 | } 208 | 209 | p.sendMessage(r); 210 | } 211 | 212 | @EventHandler(ignoreCancelled = true, priority = EventPriority.LOW) 213 | private void onMove(PlayerMoveEvent ev) { 214 | if (!hasMoved(ev.getFrom(), ev.getTo())) return; 215 | 216 | Player p = ev.getPlayer(); 217 | if (TooCool2Teleport.isCold(p)) return; 218 | 219 | PortalMaker blackhole = isInsideBermudaTriangle(p.getLocation()); 220 | if (blackhole == null) return; 221 | 222 | UUID u = p.getUniqueId(); 223 | 224 | if (recentTPs.containsKey(u)) return; 225 | flaggleRock(u, 10); 226 | 227 | WorldConfig wc = will.thugz.get(p.getWorld().getName()); 228 | if (!wc.portal_gms.contains(p.getGameMode().toString())) return; 229 | 230 | if (wc.fusRoDah > 0 && wc.checKar.isInCooldown(u, wc, Trigger.PORTAL)) { 231 | p.setVelocity(ev.getTo().toVector().subtract(ev.getFrom().toVector()).normalize().multiply(-wc.fusRoDah)); 232 | String m = TooWildForEnums.COOLDOWN.replace("%TIME%", wc.checKar.getTimeLeft(p)); 233 | if (WildTP.ab) p.sendActionBar(m); else p.sendMessage(m); 234 | return; 235 | } 236 | WildTP.debug("Player: " + p.getDisplayName() + " entered a portal"); 237 | flaggleRock(u, 60); 238 | if (blackhole.link == null) 239 | new TeleportGoneWild(Trigger.PORTAL, p, WildTP.instace.getServer().getWorld(blackhole.name)).WildTeleport(); 240 | else gotoLabel5(p, blackhole.link); 241 | } 242 | 243 | @EventHandler(ignoreCancelled = true, priority = EventPriority.HIGH) 244 | private void onWildAdminAppears(PlayerTeleportEvent ev) { 245 | if (isInsideBermudaTriangle(ev.getTo()) != null) flaggleRock(ev.getPlayer().getUniqueId(), 100); 246 | } 247 | 248 | private void flaggleRock(UUID gobo, long mokey) { 249 | BukkitTask wembley = recentTPs.remove(gobo); 250 | if (wembley != null) wembley.cancel(); 251 | 252 | recentTPs.put(gobo, new BukkitRunnable() { 253 | @Override 254 | public void run() { 255 | recentTPs.remove(gobo); 256 | } 257 | }.runTaskLaterAsynchronously(WildTP.instace, mokey)); 258 | } 259 | 260 | private boolean hasMoved(Location f, Location t) { 261 | return f.distanceSquared(t) > 0; 262 | } 263 | 264 | private PortalMaker isInsideBermudaTriangle(Location sailor) { 265 | for (PortalMaker boat : ports.values()) if (boat.contains(sailor)) return boat; 266 | 267 | return null; 268 | } 269 | 270 | private boolean allYourBasesAreBelongToUs(PortalMaker mine) { 271 | for (PortalMaker your : ports.values()) { 272 | Location[] base = your.dimensions(); 273 | for (int i = 0; i < 2; i++) if (base[i] != null && mine.contains(base[i])) return true; 274 | } 275 | 276 | return false; 277 | } 278 | 279 | private void loadConfig() { 280 | WildTP.debug("Got Load Portal Config"); 281 | 282 | ports = new HashMap(); 283 | portalFile = new File(WildTP.instace.getDataFolder(), "Portals.yml"); 284 | portalConf = new YamlConfiguration(); 285 | 286 | try { 287 | if (portalFile.exists()) 288 | portalConf.load(portalFile); 289 | else { 290 | portalFile.createNewFile(); 291 | portalConf.save(portalFile); 292 | } 293 | } 294 | catch (IOException | InvalidConfigurationException e) { 295 | e.printStackTrace(); 296 | } 297 | 298 | if (portalConf.getConfigurationSection("Portals") == null) { 299 | WildTP.debug("No portals saved."); 300 | return; 301 | } 302 | 303 | for (String s : portalConf.getConfigurationSection(CONFIG_KEY).getKeys(false)) { 304 | WildTP.debug("Reading portal " + s + "..."); 305 | PortalMaker p = new PortalMaker(s, portalConf.getString("Portals." + s)); 306 | if (p.isValid()) ports.put(s, p); 307 | else WildTP.debug("\t\t/!\\ This one leads to the Bermuda triangle :("); 308 | } 309 | 310 | WildTP.debug("Portals conf loaded: " + ports.size() + " valid portals."); 311 | } 312 | 313 | private boolean saveConfig() { 314 | try { 315 | portalConf.save(portalFile); 316 | return true; 317 | } 318 | catch (IOException e) { 319 | e.printStackTrace(); 320 | return false; 321 | } 322 | } 323 | 324 | private boolean savePortal(PortalMaker pm) { 325 | String diamZ = pm.xRay(); 326 | if (diamZ == null) return false; // Early access... 327 | 328 | portalConf.set(CONFIG_KEY + "." + pm.name, diamZ); 329 | 330 | if (saveConfig()) { 331 | ports.put(pm.name, pm); 332 | WildTP.debug("Got save portal " + pm.name + ": " + diamZ); 333 | return true; 334 | } 335 | 336 | return false; 337 | } 338 | 339 | private class PortalMaker { 340 | private Location one, two; 341 | 342 | String name, link = null; 343 | 344 | PortalMaker(String name) { 345 | this.name = name.toLowerCase(); 346 | } 347 | 348 | PortalMaker(String name, String lowcaution) { 349 | this(name); 350 | 351 | String[] wolf = lowcaution.split("~"); 352 | if (wolf.length == 3) { 353 | link = wolf[2]; 354 | wolf = new String[] { wolf[0], wolf[1] }; 355 | } 356 | 357 | if (wolf.length != 2) return; 358 | WildTP.debug("\t2 one two... I can b the answer, ready 2 dance when the vamp up..."); 359 | 360 | for (String fox : wolf) { 361 | WildTP.debug("\tHatee-hatee-hatee-ho! " + fox); 362 | String[] weasel = fox.split("\\."); 363 | if (weasel.length != 4) return; 364 | 365 | try { 366 | setCorner(new Location(Bukkit.getWorld(weasel[0]), Integer.parseInt(weasel[1]), 367 | Integer.parseInt(weasel[2]), Integer.parseInt(weasel[3])), 0, 0, 0); 368 | WildTP.debug("\t\tDo a barrel roll!"); 369 | } 370 | catch (Exception e) { 371 | WildTP.debug("I hear the wolf, the fox and the weasel, but not the « " + name + " » portal..."); 372 | } 373 | } 374 | 375 | WildTP.debug("\tTo Infinity... and Beyond!"); 376 | } 377 | 378 | boolean contains(Location l) { 379 | return l.getWorld() == one.getWorld() 380 | && one.getBlockX() <= l.getBlockX() && l.getBlockX() <= two.getBlockX() 381 | && one.getBlockY() <= l.getBlockY() && l.getBlockY() <= two.getBlockY() 382 | && one.getBlockZ() <= l.getBlockZ() && l.getBlockZ() <= two.getBlockZ(); 383 | } 384 | 385 | Location[] dimensions() { 386 | return isValid() ? new Location[] { one, two } : null; 387 | } 388 | 389 | boolean isValid() { 390 | return (one != null && two != null); 391 | } 392 | 393 | int setCorner(Location l, int maxX, int maxY, int maxZ) { 394 | if (this.one == null) { 395 | one = l; 396 | return 1; 397 | } 398 | if (l.equals(one)) return 0; 399 | Vector v = l.toVector().subtract(one.toVector()); 400 | if ( (maxX > 0 && Math.abs(v.getBlockX()) > maxX) 401 | || (maxY > 0 && Math.abs(v.getBlockY()) > maxY) 402 | || (maxZ > 0 && Math.abs(v.getBlockZ()) > maxZ) ) return -1; 403 | two = l; 404 | minymysteri(); 405 | return 2; 406 | } 407 | 408 | String xRay() { 409 | return isValid() ? johnWouldLikeToKnowYourLocation(one) + "~" + johnWouldLikeToKnowYourLocation(two) + (link == null ? "" : "~" + link) : null; 410 | } 411 | 412 | private void minymysteri() { 413 | Location l = one.clone(), ll = two.clone(); 414 | 415 | one.setX(Math.min(l.getX(), ll.getX())); 416 | one.setY(Math.min(l.getY(), ll.getY())); 417 | one.setZ(Math.min(l.getZ(), ll.getZ())); 418 | two.setX(Math.max(l.getX(), ll.getX())); 419 | two.setY(Math.max(l.getY(), ll.getY())); 420 | two.setZ(Math.max(l.getZ(), ll.getZ())); 421 | } 422 | 423 | private String johnWouldLikeToKnowYourLocation(Location xyz) { 424 | return xyz.getWorld().getName() + "." + xyz.getBlockX() + "." + xyz.getBlockY() + "." + xyz.getBlockZ(); 425 | } 426 | } 427 | } 428 | -------------------------------------------------------------------------------- /src/main/java/net/poweredbyhate/wildtp/Metricsa.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011-2013 Tyler Blair. All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without modification, are 5 | * permitted provided that the following conditions are met: 6 | * 7 | * 1. Redistributions of source code must retain the above copyright notice, this list of 8 | * conditions and the following disclaimer. 9 | * 10 | * 2. Redistributions in binary form must reproduce the above copyright notice, this list 11 | * of conditions and the following disclaimer in the documentation and/or other materials 12 | * provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ''AS IS'' AND ANY EXPRESS OR IMPLIED 15 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 16 | * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR 17 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 18 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 19 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 20 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 21 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 22 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | * 24 | * The views and conclusions contained in the software and documentation are those of the 25 | * authors and contributors and should not be interpreted as representing official policies, 26 | * either expressed or implied, of anybody else. 27 | */ 28 | 29 | package net.poweredbyhate.wildtp; 30 | 31 | import org.bukkit.Bukkit; 32 | import org.bukkit.Server; 33 | import org.bukkit.configuration.InvalidConfigurationException; 34 | import org.bukkit.configuration.file.YamlConfiguration; 35 | import org.bukkit.entity.Player; 36 | import org.bukkit.plugin.Plugin; 37 | import org.bukkit.plugin.PluginDescriptionFile; 38 | import org.bukkit.scheduler.BukkitTask; 39 | 40 | import java.io.BufferedReader; 41 | import java.io.ByteArrayOutputStream; 42 | import java.io.File; 43 | import java.io.IOException; 44 | import java.io.InputStreamReader; 45 | import java.io.OutputStream; 46 | import java.io.UnsupportedEncodingException; 47 | import java.lang.reflect.Method; 48 | import java.net.Proxy; 49 | import java.net.URL; 50 | import java.net.URLConnection; 51 | import java.net.URLEncoder; 52 | import java.util.Collection; 53 | import java.util.UUID; 54 | import java.util.logging.Level; 55 | import java.util.zip.GZIPOutputStream; 56 | 57 | public class Metricsa 58 | { 59 | 60 | /** 61 | * The current revision number 62 | */ 63 | private final static int REVISION = 7; 64 | 65 | /** 66 | * The base url of the metrics domain 67 | */ 68 | private static final String BASE_URL = "http://report.mcstats.org"; 69 | 70 | /** 71 | * The url used to report a server's status 72 | */ 73 | private static final String REPORT_URL = "/plugin/%s"; 74 | 75 | /** 76 | * Interval of time to ping (in minutes) 77 | */ 78 | private final static int PING_INTERVAL = 15; 79 | 80 | /** 81 | * The plugin this metrics submits for 82 | */ 83 | private final Plugin plugin; 84 | 85 | /** 86 | * The plugin configuration file 87 | */ 88 | private final YamlConfiguration configuration; 89 | 90 | /** 91 | * The plugin configuration file 92 | */ 93 | private final File configurationFile; 94 | 95 | /** 96 | * Unique server id 97 | */ 98 | private final String guid; 99 | 100 | /** 101 | * Debug mode 102 | */ 103 | private final boolean debug; 104 | 105 | /** 106 | * Lock for synchronization 107 | */ 108 | private final Object optOutLock = new Object(); 109 | 110 | /** 111 | * Id of the scheduled task 112 | */ 113 | private volatile BukkitTask task = null; 114 | 115 | public Metricsa(Plugin plugin) throws IOException { 116 | if (plugin == null) { 117 | throw new IllegalArgumentException("Plugin cannot be null"); 118 | } 119 | 120 | this.plugin = plugin; 121 | 122 | // load the config 123 | configurationFile = getConfigFile(); 124 | configuration = YamlConfiguration.loadConfiguration(configurationFile); 125 | 126 | // add some defaults 127 | configuration.addDefault("opt-out", false); 128 | configuration.addDefault("guid", UUID.randomUUID().toString()); 129 | configuration.addDefault("debug", false); 130 | 131 | // Do we need to create the file? 132 | if (configuration.get("guid", null) == null) { 133 | configuration.options().header("http://mcstats.org").copyDefaults(true); 134 | configuration.save(configurationFile); 135 | } 136 | 137 | // Load the guid then 138 | guid = configuration.getString("guid"); 139 | debug = configuration.getBoolean("debug", false); 140 | } 141 | 142 | /** 143 | * Start measuring statistics. This will immediately create an async repeating task as the plugin and send 144 | * the initial data to the metrics backend, and then after that it will post in increments of 145 | * PING_INTERVAL * 1200 ticks. 146 | * 147 | * @return True if statistics measuring is running, otherwise false. 148 | */ 149 | public boolean start() { 150 | synchronized (optOutLock) { 151 | // Did we opt out? 152 | if (isOptOut()) { 153 | return false; 154 | } 155 | 156 | // Is metrics already running? 157 | if (task != null) { 158 | return true; 159 | } 160 | 161 | // Begin hitting the server with glorious data 162 | task = plugin.getServer().getScheduler().runTaskTimerAsynchronously(plugin, new Runnable() { 163 | 164 | private boolean firstPost = true; 165 | 166 | public void run() { 167 | try { 168 | // This has to be synchronized or it can collide with the disable method. 169 | synchronized (optOutLock) { 170 | // Disable Task, if it is running and the server owner decided to opt-out 171 | if (isOptOut() && task != null) { 172 | task.cancel(); 173 | task = null; 174 | } 175 | } 176 | 177 | // We use the inverse of firstPost because if it is the first time we are posting, 178 | // it is not a interval ping, so it evaluates to FALSE 179 | // Each time thereafter it will evaluate to TRUE, i.e PING! 180 | postPlugin(!firstPost); 181 | 182 | // After the first post we set firstPost to false 183 | // Each post thereafter will be a ping 184 | firstPost = false; 185 | } catch (IOException e) { 186 | if (debug) { 187 | Bukkit.getLogger().log(Level.INFO, "[Metricsa] " + e.getMessage()); 188 | } 189 | } 190 | } 191 | }, 0, PING_INTERVAL * 1200); 192 | 193 | return true; 194 | } 195 | } 196 | 197 | /** 198 | * Has the server owner denied plugin metrics? 199 | * 200 | * @return true if metrics should be opted out of it 201 | */ 202 | public boolean isOptOut() { 203 | synchronized (optOutLock) { 204 | try { 205 | // Reload the metrics file 206 | configuration.load(getConfigFile()); 207 | } catch (IOException ex) { 208 | if (debug) { 209 | Bukkit.getLogger().log(Level.INFO, "[Metricsa] " + ex.getMessage()); 210 | } 211 | return true; 212 | } catch (InvalidConfigurationException ex) { 213 | if (debug) { 214 | Bukkit.getLogger().log(Level.INFO, "[Metricsa] " + ex.getMessage()); 215 | } 216 | return true; 217 | } 218 | return configuration.getBoolean("opt-out", false); 219 | } 220 | } 221 | 222 | /** 223 | * Enables metrics for the server by setting "opt-out" to false in the config file and starting the metrics task. 224 | * 225 | * @throws java.io.IOException 226 | */ 227 | public void enable() throws IOException { 228 | // This has to be synchronized or it can collide with the check in the task. 229 | synchronized (optOutLock) { 230 | // Check if the server owner has already set opt-out, if not, set it. 231 | if (isOptOut()) { 232 | configuration.set("opt-out", false); 233 | configuration.save(configurationFile); 234 | } 235 | 236 | // Enable Task, if it is not running 237 | if (task == null) { 238 | start(); 239 | } 240 | } 241 | } 242 | 243 | /** 244 | * Disables metrics for the server by setting "opt-out" to true in the config file and canceling the metrics task. 245 | * 246 | * @throws java.io.IOException 247 | */ 248 | public void disable() throws IOException { 249 | // This has to be synchronized or it can collide with the check in the task. 250 | synchronized (optOutLock) { 251 | // Check if the server owner has already set opt-out, if not, set it. 252 | if (!isOptOut()) { 253 | configuration.set("opt-out", true); 254 | configuration.save(configurationFile); 255 | } 256 | 257 | // Disable Task, if it is running 258 | if (task != null) { 259 | task.cancel(); 260 | task = null; 261 | } 262 | } 263 | } 264 | 265 | /** 266 | * Gets the File object of the config file that should be used to store data such as the GUID and opt-out status 267 | * 268 | * @return the File object for the config file 269 | */ 270 | public File getConfigFile() { 271 | // I believe the easiest way to get the base folder (e.g craftbukkit set via -P) for plugins to use 272 | // is to abuse the plugin object we already have 273 | // plugin.getDataFolder() => base/plugins/PluginA/ 274 | // pluginsFolder => base/plugins/ 275 | // The base is not necessarily relative to the startup directory. 276 | File pluginsFolder = plugin.getDataFolder().getParentFile(); 277 | 278 | // return => base/plugins/PluginMetrics/config.yml 279 | return new File(new File(pluginsFolder, "PluginMetrics"), "config.yml"); 280 | } 281 | 282 | /** 283 | * Gets the online player (backwards compatibility) 284 | * 285 | * @return online player amount 286 | */ 287 | private int getOnlinePlayers() { 288 | try { 289 | Method onlinePlayerMethod = Server.class.getMethod("getOnlinePlayers"); 290 | if(onlinePlayerMethod.getReturnType().equals(Collection.class)) { 291 | return ((Collection)onlinePlayerMethod.invoke(Bukkit.getServer())).size(); 292 | } else { 293 | return ((Player[])onlinePlayerMethod.invoke(Bukkit.getServer())).length; 294 | } 295 | } catch (Exception ex) { 296 | if (debug) { 297 | Bukkit.getLogger().log(Level.INFO, "[Metricsa] " + ex.getMessage()); 298 | } 299 | } 300 | 301 | return 0; 302 | } 303 | 304 | /** 305 | * Generic method that posts a plugin to the metrics website 306 | */ 307 | private void postPlugin(boolean isPing) throws IOException { 308 | // Server software specific section 309 | PluginDescriptionFile description = plugin.getDescription(); 310 | String pluginName = description.getName(); 311 | boolean onlineMode = Bukkit.getServer().getOnlineMode(); // TRUE if online mode is enabled 312 | String pluginVersion = description.getVersion(); 313 | String serverVersion = Bukkit.getVersion(); 314 | int playersOnline = this.getOnlinePlayers(); 315 | 316 | // END server software specific section -- all code below does not use any code outside of this class / Java 317 | 318 | // Construct the post data 319 | StringBuilder json = new StringBuilder(1024); 320 | json.append('{'); 321 | 322 | // The plugin's description file containg all of the plugin data such as name, version, author, etc 323 | appendJSONPair(json, "guid", guid); 324 | appendJSONPair(json, "plugin_version", pluginVersion); 325 | appendJSONPair(json, "server_version", serverVersion); 326 | appendJSONPair(json, "players_online", Integer.toString(playersOnline)); 327 | 328 | // New data as of R6 329 | String osname = System.getProperty("os.name"); 330 | String osarch = System.getProperty("os.arch"); 331 | String osversion = System.getProperty("os.version"); 332 | String java_version = System.getProperty("java.version"); 333 | int coreCount = Runtime.getRuntime().availableProcessors(); 334 | 335 | // normalize os arch .. amd64 -> x86_64 336 | if (osarch.equals("amd64")) { 337 | osarch = "x86_64"; 338 | } 339 | 340 | appendJSONPair(json, "osname", osname); 341 | appendJSONPair(json, "osarch", osarch); 342 | appendJSONPair(json, "osversion", osversion); 343 | appendJSONPair(json, "cores", Integer.toString(coreCount)); 344 | appendJSONPair(json, "auth_mode", onlineMode ? "1" : "0"); 345 | appendJSONPair(json, "java_version", java_version); 346 | 347 | // If we're pinging, append it 348 | if (isPing) { 349 | appendJSONPair(json, "ping", "1"); 350 | } 351 | 352 | // close json 353 | json.append('}'); 354 | 355 | // Create the url 356 | URL url = new URL(BASE_URL + String.format(REPORT_URL, urlEncode(pluginName))); 357 | 358 | // Connect to the website 359 | URLConnection connection; 360 | 361 | // Mineshafter creates a socks proxy, so we can safely bypass it 362 | // It does not reroute POST requests so we need to go around it 363 | if (isMineshafterPresent()) { 364 | connection = url.openConnection(Proxy.NO_PROXY); 365 | } else { 366 | connection = url.openConnection(); 367 | } 368 | 369 | 370 | byte[] uncompressed = json.toString().getBytes(); 371 | byte[] compressed = gzip(json.toString()); 372 | 373 | // Headers 374 | connection.addRequestProperty("User-Agent", "MCStats/" + REVISION); 375 | connection.addRequestProperty("Content-Type", "application/json"); 376 | connection.addRequestProperty("Content-Encoding", "gzip"); 377 | connection.addRequestProperty("Content-Length", Integer.toString(compressed.length)); 378 | connection.addRequestProperty("Accept", "application/json"); 379 | connection.addRequestProperty("Connection", "close"); 380 | 381 | connection.setDoOutput(true); 382 | 383 | if (debug) { 384 | System.out.println("[Metricsa] Prepared request for " + pluginName + " uncompressed=" + uncompressed.length + " compressed=" + compressed.length); 385 | } 386 | 387 | // Write the data 388 | OutputStream os = connection.getOutputStream(); 389 | os.write(compressed); 390 | os.flush(); 391 | 392 | // Now read the response 393 | final BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream())); 394 | String response = reader.readLine(); 395 | 396 | // close resources 397 | os.close(); 398 | reader.close(); 399 | 400 | if (response == null || response.startsWith("ERR") || response.startsWith("7")) { 401 | if (response == null) { 402 | response = "null"; 403 | } else if (response.startsWith("7")) { 404 | response = response.substring(response.startsWith("7,") ? 2 : 1); 405 | } 406 | 407 | throw new IOException(response); 408 | } 409 | } 410 | 411 | /** 412 | * GZip compress a string of bytes 413 | * 414 | * @param input 415 | * @return 416 | */ 417 | public static byte[] gzip(String input) { 418 | ByteArrayOutputStream baos = new ByteArrayOutputStream(); 419 | GZIPOutputStream gzos = null; 420 | 421 | try { 422 | gzos = new GZIPOutputStream(baos); 423 | gzos.write(input.getBytes("UTF-8")); 424 | } catch (IOException e) { 425 | e.printStackTrace(); 426 | } finally { 427 | if (gzos != null) try { 428 | gzos.close(); 429 | } catch (IOException ignore) { 430 | } 431 | } 432 | 433 | return baos.toByteArray(); 434 | } 435 | 436 | /** 437 | * Check if mineshafter is present. If it is, we need to bypass it to send POST requests 438 | * 439 | * @return true if mineshafter is installed on the server 440 | */ 441 | private boolean isMineshafterPresent() { 442 | try { 443 | Class.forName("mineshafter.MineServer"); 444 | return true; 445 | } catch (Exception e) { 446 | return false; 447 | } 448 | } 449 | 450 | /** 451 | * Appends a json encoded key/value pair to the given string builder. 452 | * 453 | * @param json 454 | * @param key 455 | * @param value 456 | * @throws UnsupportedEncodingException 457 | */ 458 | private static void appendJSONPair(StringBuilder json, String key, String value) throws UnsupportedEncodingException { 459 | boolean isValueNumeric = false; 460 | 461 | try { 462 | if (value.equals("0") || !value.endsWith("0")) { 463 | Double.parseDouble(value); 464 | isValueNumeric = true; 465 | } 466 | } catch (NumberFormatException e) { 467 | isValueNumeric = false; 468 | } 469 | 470 | if (json.charAt(json.length() - 1) != '{') { 471 | json.append(','); 472 | } 473 | 474 | json.append(escapeJSON(key)); 475 | json.append(':'); 476 | 477 | if (isValueNumeric) { 478 | json.append(value); 479 | } else { 480 | json.append(escapeJSON(value)); 481 | } 482 | } 483 | 484 | /** 485 | * Escape a string to create a valid JSON string 486 | * 487 | * @param text 488 | * @return 489 | */ 490 | private static String escapeJSON(String text) { 491 | StringBuilder builder = new StringBuilder(); 492 | 493 | builder.append('"'); 494 | for (int index = 0; index < text.length(); index++) { 495 | char chr = text.charAt(index); 496 | 497 | switch (chr) { 498 | case '"': 499 | case '\\': 500 | builder.append('\\'); 501 | builder.append(chr); 502 | break; 503 | case '\b': 504 | builder.append("\\b"); 505 | break; 506 | case '\t': 507 | builder.append("\\t"); 508 | break; 509 | case '\n': 510 | builder.append("\\n"); 511 | break; 512 | case '\r': 513 | builder.append("\\r"); 514 | break; 515 | default: 516 | if (chr < ' ') { 517 | String t = "000" + Integer.toHexString(chr); 518 | builder.append("\\u" + t.substring(t.length() - 4)); 519 | } else { 520 | builder.append(chr); 521 | } 522 | break; 523 | } 524 | } 525 | builder.append('"'); 526 | 527 | return builder.toString(); 528 | } 529 | 530 | /** 531 | * Encode text as UTF-8 532 | * 533 | * @param text the text to encode 534 | * @return the encoded text, as UTF-8 535 | */ 536 | private static String urlEncode(final String text) throws UnsupportedEncodingException { 537 | return URLEncoder.encode(text, "UTF-8"); 538 | } 539 | 540 | } -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | # GNU GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 [Free Software Foundation, Inc.](http://fsf.org/) 5 | 6 | Everyone is permitted to copy and distribute verbatim copies of this license 7 | document, but changing it is not allowed. 8 | 9 | ## Preamble 10 | 11 | The GNU General Public License is a free, copyleft license for software and 12 | other kinds of works. 13 | 14 | The licenses for most software and other practical works are designed to take 15 | away your freedom to share and change the works. By contrast, the GNU General 16 | Public License is intended to guarantee your freedom to share and change all 17 | versions of a program--to make sure it remains free software for all its users. 18 | We, the Free Software Foundation, use the GNU General Public License for most 19 | of our software; it applies also to any other work released this way by its 20 | authors. You can apply it to your programs, too. 21 | 22 | When we speak of free software, we are referring to freedom, not price. Our 23 | General Public Licenses are designed to make sure that you have the freedom to 24 | distribute copies of free software (and charge for them if you wish), that you 25 | receive source code or can get it if you want it, that you can change the 26 | software or use pieces of it in new free programs, and that you know you can do 27 | these things. 28 | 29 | To protect your rights, we need to prevent others from denying you these rights 30 | or asking you to surrender the rights. Therefore, you have certain 31 | responsibilities if you distribute copies of the software, or if you modify it: 32 | responsibilities to respect the freedom of others. 33 | 34 | For example, if you distribute copies of such a program, whether gratis or for 35 | a fee, you must pass on to the recipients the same freedoms that you received. 36 | You must make sure that they, too, receive or can get the source code. And you 37 | must show them these terms so they know their rights. 38 | 39 | Developers that use the GNU GPL protect your rights with two steps: 40 | 41 | 1. assert copyright on the software, and 42 | 2. offer you this License giving you legal permission to copy, distribute 43 | and/or modify it. 44 | 45 | For the developers' and authors' protection, the GPL clearly explains that 46 | there is no warranty for this free software. For both users' and authors' sake, 47 | the GPL requires that modified versions be marked as changed, so that their 48 | problems will not be attributed erroneously to authors of previous versions. 49 | 50 | Some devices are designed to deny users access to install or run modified 51 | versions of the software inside them, although the manufacturer can do so. This 52 | is fundamentally incompatible with the aim of protecting users' freedom to 53 | change the software. The systematic pattern of such abuse occurs in the area of 54 | products for individuals to use, which is precisely where it is most 55 | unacceptable. Therefore, we have designed this version of the GPL to prohibit 56 | the practice for those products. If such problems arise substantially in other 57 | domains, we stand ready to extend this provision to those domains in future 58 | versions of the GPL, as needed to protect the freedom of users. 59 | 60 | Finally, every program is threatened constantly by software patents. States 61 | should not allow patents to restrict development and use of software on 62 | general-purpose computers, but in those that do, we wish to avoid the special 63 | danger that patents applied to a free program could make it effectively 64 | proprietary. To prevent this, the GPL assures that patents cannot be used to 65 | render the program non-free. 66 | 67 | The precise terms and conditions for copying, distribution and modification 68 | follow. 69 | 70 | ## TERMS AND CONDITIONS 71 | 72 | ### 0. Definitions. 73 | 74 | *This License* refers to version 3 of the GNU General Public License. 75 | 76 | *Copyright* also means copyright-like laws that apply to other kinds of works, 77 | such as semiconductor masks. 78 | 79 | *The Program* refers to any copyrightable work licensed under this License. 80 | Each licensee is addressed as *you*. *Licensees* and *recipients* may be 81 | individuals or organizations. 82 | 83 | To *modify* a work means to copy from or adapt all or part of the work in a 84 | fashion requiring copyright permission, other than the making of an exact copy. 85 | The resulting work is called a *modified version* of the earlier work or a work 86 | *based on* the earlier work. 87 | 88 | A *covered work* means either the unmodified Program or a work based on the 89 | Program. 90 | 91 | To *propagate* a work means to do anything with it that, without permission, 92 | would make you directly or secondarily liable for infringement under applicable 93 | copyright law, except executing it on a computer or modifying a private copy. 94 | Propagation includes copying, distribution (with or without modification), 95 | making available to the public, and in some countries other activities as well. 96 | 97 | To *convey* a work means any kind of propagation that enables other parties to 98 | make or receive copies. Mere interaction with a user through a computer 99 | network, with no transfer of a copy, is not conveying. 100 | 101 | An interactive user interface displays *Appropriate Legal Notices* to the 102 | extent that it includes a convenient and prominently visible feature that 103 | 104 | 1. displays an appropriate copyright notice, and 105 | 2. tells the user that there is no warranty for the work (except to the 106 | extent that warranties are provided), that licensees may convey the work 107 | under this License, and how to view a copy of this License. 108 | 109 | If the interface presents a list of user commands or options, such as a menu, a 110 | prominent item in the list meets this criterion. 111 | 112 | ### 1. Source Code. 113 | 114 | The *source code* for a work means the preferred form of the work for making 115 | modifications to it. *Object code* means any non-source form of a work. 116 | 117 | A *Standard Interface* means an interface that either is an official standard 118 | defined by a recognized standards body, or, in the case of interfaces specified 119 | for a particular programming language, one that is widely used among developers 120 | working in that language. 121 | 122 | The *System Libraries* of an executable work include anything, other than the 123 | work as a whole, that (a) is included in the normal form of packaging a Major 124 | Component, but which is not part of that Major Component, and (b) serves only 125 | to enable use of the work with that Major Component, or to implement a Standard 126 | Interface for which an implementation is available to the public in source code 127 | form. A *Major Component*, in this context, means a major essential component 128 | (kernel, window system, and so on) of the specific operating system (if any) on 129 | which the executable work runs, or a compiler used to produce the work, or an 130 | object code interpreter used to run it. 131 | 132 | The *Corresponding Source* for a work in object code form means all the source 133 | code needed to generate, install, and (for an executable work) run the object 134 | code and to modify the work, including scripts to control those activities. 135 | However, it does not include the work's System Libraries, or general-purpose 136 | tools or generally available free programs which are used unmodified in 137 | performing those activities but which are not part of the work. For example, 138 | Corresponding Source includes interface definition files associated with source 139 | files for the work, and the source code for shared libraries and dynamically 140 | linked subprograms that the work is specifically designed to require, such as 141 | by intimate data communication or control flow between those subprograms and 142 | other parts of the work. 143 | 144 | The Corresponding Source need not include anything that users can regenerate 145 | automatically from other parts of the Corresponding Source. 146 | 147 | The Corresponding Source for a work in source code form is that same work. 148 | 149 | ### 2. Basic Permissions. 150 | 151 | All rights granted under this License are granted for the term of copyright on 152 | the Program, and are irrevocable provided the stated conditions are met. This 153 | License explicitly affirms your unlimited permission to run the unmodified 154 | Program. The output from running a covered work is covered by this License only 155 | if the output, given its content, constitutes a covered work. This License 156 | acknowledges your rights of fair use or other equivalent, as provided by 157 | copyright law. 158 | 159 | You may make, run and propagate covered works that you do not convey, without 160 | conditions so long as your license otherwise remains in force. You may convey 161 | covered works to others for the sole purpose of having them make modifications 162 | exclusively for you, or provide you with facilities for running those works, 163 | provided that you comply with the terms of this License in conveying all 164 | material for which you do not control copyright. Those thus making or running 165 | the covered works for you must do so exclusively on your behalf, under your 166 | direction and control, on terms that prohibit them from making any copies of 167 | your copyrighted material outside their relationship with you. 168 | 169 | Conveying under any other circumstances is permitted solely under the 170 | conditions stated below. Sublicensing is not allowed; section 10 makes it 171 | unnecessary. 172 | 173 | ### 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 174 | 175 | No covered work shall be deemed part of an effective technological measure 176 | under any applicable law fulfilling obligations under article 11 of the WIPO 177 | copyright treaty adopted on 20 December 1996, or similar laws prohibiting or 178 | restricting circumvention of such measures. 179 | 180 | When you convey a covered work, you waive any legal power to forbid 181 | circumvention of technological measures to the extent such circumvention is 182 | effected by exercising rights under this License with respect to the covered 183 | work, and you disclaim any intention to limit operation or modification of the 184 | work as a means of enforcing, against the work's users, your or third parties' 185 | legal rights to forbid circumvention of technological measures. 186 | 187 | ### 4. Conveying Verbatim Copies. 188 | 189 | You may convey verbatim copies of the Program's source code as you receive it, 190 | in any medium, provided that you conspicuously and appropriately publish on 191 | each copy an appropriate copyright notice; keep intact all notices stating that 192 | this License and any non-permissive terms added in accord with section 7 apply 193 | to the code; keep intact all notices of the absence of any warranty; and give 194 | all recipients a copy of this License along with the Program. 195 | 196 | You may charge any price or no price for each copy that you convey, and you may 197 | offer support or warranty protection for a fee. 198 | 199 | ### 5. Conveying Modified Source Versions. 200 | 201 | You may convey a work based on the Program, or the modifications to produce it 202 | from the Program, in the form of source code under the terms of section 4, 203 | provided that you also meet all of these conditions: 204 | 205 | - a) The work must carry prominent notices stating that you modified it, and 206 | giving a relevant date. 207 | - b) The work must carry prominent notices stating that it is released under 208 | this License and any conditions added under section 7. This requirement 209 | modifies the requirement in section 4 to *keep intact all notices*. 210 | - c) You must license the entire work, as a whole, under this License to 211 | anyone who comes into possession of a copy. This License will therefore 212 | apply, along with any applicable section 7 additional terms, to the whole 213 | of the work, and all its parts, regardless of how they are packaged. This 214 | License gives no permission to license the work in any other way, but it 215 | does not invalidate such permission if you have separately received it. 216 | - d) If the work has interactive user interfaces, each must display 217 | Appropriate Legal Notices; however, if the Program has interactive 218 | interfaces that do not display Appropriate Legal Notices, your work need 219 | not make them do so. 220 | 221 | A compilation of a covered work with other separate and independent works, 222 | which are not by their nature extensions of the covered work, and which are not 223 | combined with it such as to form a larger program, in or on a volume of a 224 | storage or distribution medium, is called an *aggregate* if the compilation and 225 | its resulting copyright are not used to limit the access or legal rights of the 226 | compilation's users beyond what the individual works permit. Inclusion of a 227 | covered work in an aggregate does not cause this License to apply to the other 228 | parts of the aggregate. 229 | 230 | ### 6. Conveying Non-Source Forms. 231 | 232 | You may convey a covered work in object code form under the terms of sections 4 233 | and 5, provided that you also convey the machine-readable Corresponding Source 234 | under the terms of this License, in one of these ways: 235 | 236 | - a) Convey the object code in, or embodied in, a physical product (including 237 | a physical distribution medium), accompanied by the Corresponding Source 238 | fixed on a durable physical medium customarily used for software 239 | interchange. 240 | - b) Convey the object code in, or embodied in, a physical product (including 241 | a physical distribution medium), accompanied by a written offer, valid for 242 | at least three years and valid for as long as you offer spare parts or 243 | customer support for that product model, to give anyone who possesses the 244 | object code either 245 | 1. a copy of the Corresponding Source for all the software in the product 246 | that is covered by this License, on a durable physical medium 247 | customarily used for software interchange, for a price no more than your 248 | reasonable cost of physically performing this conveying of source, or 249 | 2. access to copy the Corresponding Source from a network server at no 250 | charge. 251 | - c) Convey individual copies of the object code with a copy of the written 252 | offer to provide the Corresponding Source. This alternative is allowed only 253 | occasionally and noncommercially, and only if you received the object code 254 | with such an offer, in accord with subsection 6b. 255 | - d) Convey the object code by offering access from a designated place 256 | (gratis or for a charge), and offer equivalent access to the Corresponding 257 | Source in the same way through the same place at no further charge. You 258 | need not require recipients to copy the Corresponding Source along with the 259 | object code. If the place to copy the object code is a network server, the 260 | Corresponding Source may be on a different server operated by you or a 261 | third party) that supports equivalent copying facilities, provided you 262 | maintain clear directions next to the object code saying where to find the 263 | Corresponding Source. Regardless of what server hosts the Corresponding 264 | Source, you remain obligated to ensure that it is available for as long as 265 | needed to satisfy these requirements. 266 | - e) Convey the object code using peer-to-peer transmission, provided you 267 | inform other peers where the object code and Corresponding Source of the 268 | work are being offered to the general public at no charge under subsection 269 | 6d. 270 | 271 | A separable portion of the object code, whose source code is excluded from the 272 | Corresponding Source as a System Library, need not be included in conveying the 273 | object code work. 274 | 275 | A *User Product* is either 276 | 277 | 1. a *consumer product*, which means any tangible personal property which is 278 | normally used for personal, family, or household purposes, or 279 | 2. anything designed or sold for incorporation into a dwelling. 280 | 281 | In determining whether a product is a consumer product, doubtful cases shall be 282 | resolved in favor of coverage. For a particular product received by a 283 | particular user, *normally used* refers to a typical or common use of that 284 | class of product, regardless of the status of the particular user or of the way 285 | in which the particular user actually uses, or expects or is expected to use, 286 | the product. A product is a consumer product regardless of whether the product 287 | has substantial commercial, industrial or non-consumer uses, unless such uses 288 | represent the only significant mode of use of the product. 289 | 290 | *Installation Information* for a User Product means any methods, procedures, 291 | authorization keys, or other information required to install and execute 292 | modified versions of a covered work in that User Product from a modified 293 | version of its Corresponding Source. The information must suffice to ensure 294 | that the continued functioning of the modified object code is in no case 295 | prevented or interfered with solely because modification has been made. 296 | 297 | If you convey an object code work under this section in, or with, or 298 | specifically for use in, a User Product, and the conveying occurs as part of a 299 | transaction in which the right of possession and use of the User Product is 300 | transferred to the recipient in perpetuity or for a fixed term (regardless of 301 | how the transaction is characterized), the Corresponding Source conveyed under 302 | this section must be accompanied by the Installation Information. But this 303 | requirement does not apply if neither you nor any third party retains the 304 | ability to install modified object code on the User Product (for example, the 305 | work has been installed in ROM). 306 | 307 | The requirement to provide Installation Information does not include a 308 | requirement to continue to provide support service, warranty, or updates for a 309 | work that has been modified or installed by the recipient, or for the User 310 | Product in which it has been modified or installed. Access to a network may be 311 | denied when the modification itself materially and adversely affects the 312 | operation of the network or violates the rules and protocols for communication 313 | across the network. 314 | 315 | Corresponding Source conveyed, and Installation Information provided, in accord 316 | with this section must be in a format that is publicly documented (and with an 317 | implementation available to the public in source code form), and must require 318 | no special password or key for unpacking, reading or copying. 319 | 320 | ### 7. Additional Terms. 321 | 322 | *Additional permissions* are terms that supplement the terms of this License by 323 | making exceptions from one or more of its conditions. Additional permissions 324 | that are applicable to the entire Program shall be treated as though they were 325 | included in this License, to the extent that they are valid under applicable 326 | law. If additional permissions apply only to part of the Program, that part may 327 | be used separately under those permissions, but the entire Program remains 328 | governed by this License without regard to the additional permissions. 329 | 330 | When you convey a copy of a covered work, you may at your option remove any 331 | additional permissions from that copy, or from any part of it. (Additional 332 | permissions may be written to require their own removal in certain cases when 333 | you modify the work.) You may place additional permissions on material, added 334 | by you to a covered work, for which you have or can give appropriate copyright 335 | permission. 336 | 337 | Notwithstanding any other provision of this License, for material you add to a 338 | covered work, you may (if authorized by the copyright holders of that material) 339 | supplement the terms of this License with terms: 340 | 341 | - a) Disclaiming warranty or limiting liability differently from the terms of 342 | sections 15 and 16 of this License; or 343 | - b) Requiring preservation of specified reasonable legal notices or author 344 | attributions in that material or in the Appropriate Legal Notices displayed 345 | by works containing it; or 346 | - c) Prohibiting misrepresentation of the origin of that material, or 347 | requiring that modified versions of such material be marked in reasonable 348 | ways as different from the original version; or 349 | - d) Limiting the use for publicity purposes of names of licensors or authors 350 | of the material; or 351 | - e) Declining to grant rights under trademark law for use of some trade 352 | names, trademarks, or service marks; or 353 | - f) Requiring indemnification of licensors and authors of that material by 354 | anyone who conveys the material (or modified versions of it) with 355 | contractual assumptions of liability to the recipient, for any liability 356 | that these contractual assumptions directly impose on those licensors and 357 | authors. 358 | 359 | All other non-permissive additional terms are considered *further restrictions* 360 | within the meaning of section 10. If the Program as you received it, or any 361 | part of it, contains a notice stating that it is governed by this License along 362 | with a term that is a further restriction, you may remove that term. If a 363 | license document contains a further restriction but permits relicensing or 364 | conveying under this License, you may add to a covered work material governed 365 | by the terms of that license document, provided that the further restriction 366 | does not survive such relicensing or conveying. 367 | 368 | If you add terms to a covered work in accord with this section, you must place, 369 | in the relevant source files, a statement of the additional terms that apply to 370 | those files, or a notice indicating where to find the applicable terms. 371 | 372 | Additional terms, permissive or non-permissive, may be stated in the form of a 373 | separately written license, or stated as exceptions; the above requirements 374 | apply either way. 375 | 376 | ### 8. Termination. 377 | 378 | You may not propagate or modify a covered work except as expressly provided 379 | under this License. Any attempt otherwise to propagate or modify it is void, 380 | and will automatically terminate your rights under this License (including any 381 | patent licenses granted under the third paragraph of section 11). 382 | 383 | However, if you cease all violation of this License, then your license from a 384 | particular copyright holder is reinstated 385 | 386 | - a) provisionally, unless and until the copyright holder explicitly and 387 | finally terminates your license, and 388 | - b) permanently, if the copyright holder fails to notify you of the 389 | violation by some reasonable means prior to 60 days after the cessation. 390 | 391 | Moreover, your license from a particular copyright holder is reinstated 392 | permanently if the copyright holder notifies you of the violation by some 393 | reasonable means, this is the first time you have received notice of violation 394 | of this License (for any work) from that copyright holder, and you cure the 395 | violation prior to 30 days after your receipt of the notice. 396 | 397 | Termination of your rights under this section does not terminate the licenses 398 | of parties who have received copies or rights from you under this License. If 399 | your rights have been terminated and not permanently reinstated, you do not 400 | qualify to receive new licenses for the same material under section 10. 401 | 402 | ### 9. Acceptance Not Required for Having Copies. 403 | 404 | You are not required to accept this License in order to receive or run a copy 405 | of the Program. Ancillary propagation of a covered work occurring solely as a 406 | consequence of using peer-to-peer transmission to receive a copy likewise does 407 | not require acceptance. However, nothing other than this License grants you 408 | permission to propagate or modify any covered work. These actions infringe 409 | copyright if you do not accept this License. Therefore, by modifying or 410 | propagating a covered work, you indicate your acceptance of this License to do 411 | so. 412 | 413 | ### 10. Automatic Licensing of Downstream Recipients. 414 | 415 | Each time you convey a covered work, the recipient automatically receives a 416 | license from the original licensors, to run, modify and propagate that work, 417 | subject to this License. You are not responsible for enforcing compliance by 418 | third parties with this License. 419 | 420 | An *entity transaction* is a transaction transferring control of an 421 | organization, or substantially all assets of one, or subdividing an 422 | organization, or merging organizations. If propagation of a covered work 423 | results from an entity transaction, each party to that transaction who receives 424 | a copy of the work also receives whatever licenses to the work the party's 425 | predecessor in interest had or could give under the previous paragraph, plus a 426 | right to possession of the Corresponding Source of the work from the 427 | predecessor in interest, if the predecessor has it or can get it with 428 | reasonable efforts. 429 | 430 | You may not impose any further restrictions on the exercise of the rights 431 | granted or affirmed under this License. For example, you may not impose a 432 | license fee, royalty, or other charge for exercise of rights granted under this 433 | License, and you may not initiate litigation (including a cross-claim or 434 | counterclaim in a lawsuit) alleging that any patent claim is infringed by 435 | making, using, selling, offering for sale, or importing the Program or any 436 | portion of it. 437 | 438 | ### 11. Patents. 439 | 440 | A *contributor* is a copyright holder who authorizes use under this License of 441 | the Program or a work on which the Program is based. The work thus licensed is 442 | called the contributor's *contributor version*. 443 | 444 | A contributor's *essential patent claims* are all patent claims owned or 445 | controlled by the contributor, whether already acquired or hereafter acquired, 446 | that would be infringed by some manner, permitted by this License, of making, 447 | using, or selling its contributor version, but do not include claims that would 448 | be infringed only as a consequence of further modification of the contributor 449 | version. For purposes of this definition, *control* includes the right to grant 450 | patent sublicenses in a manner consistent with the requirements of this 451 | License. 452 | 453 | Each contributor grants you a non-exclusive, worldwide, royalty-free patent 454 | license under the contributor's essential patent claims, to make, use, sell, 455 | offer for sale, import and otherwise run, modify and propagate the contents of 456 | its contributor version. 457 | 458 | In the following three paragraphs, a *patent license* is any express agreement 459 | or commitment, however denominated, not to enforce a patent (such as an express 460 | permission to practice a patent or covenant not to sue for patent 461 | infringement). To *grant* such a patent license to a party means to make such 462 | an agreement or commitment not to enforce a patent against the party. 463 | 464 | If you convey a covered work, knowingly relying on a patent license, and the 465 | Corresponding Source of the work is not available for anyone to copy, free of 466 | charge and under the terms of this License, through a publicly available 467 | network server or other readily accessible means, then you must either 468 | 469 | 1. cause the Corresponding Source to be so available, or 470 | 2. arrange to deprive yourself of the benefit of the patent license for this 471 | particular work, or 472 | 3. arrange, in a manner consistent with the requirements of this License, to 473 | extend the patent license to downstream recipients. 474 | 475 | *Knowingly relying* means you have actual knowledge that, but for the patent 476 | license, your conveying the covered work in a country, or your recipient's use 477 | of the covered work in a country, would infringe one or more identifiable 478 | patents in that country that you have reason to believe are valid. 479 | 480 | If, pursuant to or in connection with a single transaction or arrangement, you 481 | convey, or propagate by procuring conveyance of, a covered work, and grant a 482 | patent license to some of the parties receiving the covered work authorizing 483 | them to use, propagate, modify or convey a specific copy of the covered work, 484 | then the patent license you grant is automatically extended to all recipients 485 | of the covered work and works based on it. 486 | 487 | A patent license is *discriminatory* if it does not include within the scope of 488 | its coverage, prohibits the exercise of, or is conditioned on the non-exercise 489 | of one or more of the rights that are specifically granted under this License. 490 | You may not convey a covered work if you are a party to an arrangement with a 491 | third party that is in the business of distributing software, under which you 492 | make payment to the third party based on the extent of your activity of 493 | conveying the work, and under which the third party grants, to any of the 494 | parties who would receive the covered work from you, a discriminatory patent 495 | license 496 | 497 | - a) in connection with copies of the covered work conveyed by you (or copies 498 | made from those copies), or 499 | - b) primarily for and in connection with specific products or compilations 500 | that contain the covered work, unless you entered into that arrangement, or 501 | that patent license was granted, prior to 28 March 2007. 502 | 503 | Nothing in this License shall be construed as excluding or limiting any implied 504 | license or other defenses to infringement that may otherwise be available to 505 | you under applicable patent law. 506 | 507 | ### 12. No Surrender of Others' Freedom. 508 | 509 | If conditions are imposed on you (whether by court order, agreement or 510 | otherwise) that contradict the conditions of this License, they do not excuse 511 | you from the conditions of this License. If you cannot convey a covered work so 512 | as to satisfy simultaneously your obligations under this License and any other 513 | pertinent obligations, then as a consequence you may not convey it at all. For 514 | example, if you agree to terms that obligate you to collect a royalty for 515 | further conveying from those to whom you convey the Program, the only way you 516 | could satisfy both those terms and this License would be to refrain entirely 517 | from conveying the Program. 518 | 519 | ### 13. Use with the GNU Affero General Public License. 520 | 521 | Notwithstanding any other provision of this License, you have permission to 522 | link or combine any covered work with a work licensed under version 3 of the 523 | GNU Affero General Public License into a single combined work, and to convey 524 | the resulting work. The terms of this License will continue to apply to the 525 | part which is the covered work, but the special requirements of the GNU Affero 526 | General Public License, section 13, concerning interaction through a network 527 | will apply to the combination as such. 528 | 529 | ### 14. Revised Versions of this License. 530 | 531 | The Free Software Foundation may publish revised and/or new versions of the GNU 532 | General Public License from time to time. Such new versions will be similar in 533 | spirit to the present version, but may differ in detail to address new problems 534 | or concerns. 535 | 536 | Each version is given a distinguishing version number. If the Program specifies 537 | that a certain numbered version of the GNU General Public License *or any later 538 | version* applies to it, you have the option of following the terms and 539 | conditions either of that numbered version or of any later version published by 540 | the Free Software Foundation. If the Program does not specify a version number 541 | of the GNU General Public License, you may choose any version ever published by 542 | the Free Software Foundation. 543 | 544 | If the Program specifies that a proxy can decide which future versions of the 545 | GNU General Public License can be used, that proxy's public statement of 546 | acceptance of a version permanently authorizes you to choose that version for 547 | the Program. 548 | 549 | Later license versions may give you additional or different permissions. 550 | However, no additional obligations are imposed on any author or copyright 551 | holder as a result of your choosing to follow a later version. 552 | 553 | ### 15. Disclaimer of Warranty. 554 | 555 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE 556 | LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER 557 | PARTIES PROVIDE THE PROGRAM *AS IS* WITHOUT WARRANTY OF ANY KIND, EITHER 558 | EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 559 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE 560 | QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE 561 | DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR 562 | CORRECTION. 563 | 564 | ### 16. Limitation of Liability. 565 | 566 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY 567 | COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS 568 | PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, 569 | INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE 570 | THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED 571 | INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE 572 | PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY 573 | HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 574 | 575 | ### 17. Interpretation of Sections 15 and 16. 576 | 577 | If the disclaimer of warranty and limitation of liability provided above cannot 578 | be given local legal effect according to their terms, reviewing courts shall 579 | apply local law that most closely approximates an absolute waiver of all civil 580 | liability in connection with the Program, unless a warranty or assumption of 581 | liability accompanies a copy of the Program in return for a fee. 582 | 583 | ## END OF TERMS AND CONDITIONS ### 584 | 585 | ### How to Apply These Terms to Your New Programs 586 | 587 | If you develop a new program, and you want it to be of the greatest possible 588 | use to the public, the best way to achieve this is to make it free software 589 | which everyone can redistribute and change under these terms. 590 | 591 | To do so, attach the following notices to the program. It is safest to attach 592 | them to the start of each source file to most effectively state the exclusion 593 | of warranty; and each file should have at least the *copyright* line and a 594 | pointer to where the full notice is found. 595 | 596 | 597 | Copyright (C) 598 | 599 | This program is free software: you can redistribute it and/or modify 600 | it under the terms of the GNU General Public License as published by 601 | the Free Software Foundation, either version 3 of the License, or 602 | (at your option) any later version. 603 | 604 | This program is distributed in the hope that it will be useful, 605 | but WITHOUT ANY WARRANTY; without even the implied warranty of 606 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 607 | GNU General Public License for more details. 608 | 609 | You should have received a copy of the GNU General Public License 610 | along with this program. If not, see . 611 | 612 | Also add information on how to contact you by electronic and paper mail. 613 | 614 | If the program does terminal interaction, make it output a short notice like 615 | this when it starts in an interactive mode: 616 | 617 | Copyright (C) 618 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 619 | This is free software, and you are welcome to redistribute it 620 | under certain conditions; type `show c' for details. 621 | 622 | The hypothetical commands `show w` and `show c` should show the appropriate 623 | parts of the General Public License. Of course, your program's commands might 624 | be different; for a GUI interface, you would use an *about box*. 625 | 626 | You should also get your employer (if you work as a programmer) or school, if 627 | any, to sign a *copyright disclaimer* for the program, if necessary. For more 628 | information on this, and how to apply and follow the GNU GPL, see 629 | [http://www.gnu.org/licenses/](http://www.gnu.org/licenses/). 630 | 631 | The GNU General Public License does not permit incorporating your program into 632 | proprietary programs. If your program is a subroutine library, you may consider 633 | it more useful to permit linking proprietary applications with the library. If 634 | this is what you want to do, use the GNU Lesser General Public License instead 635 | of this License. But first, please read 636 | [http://www.gnu.org/philosophy/why-not-lgpl.html](http://www.gnu.org/philosophy/why-not-lgpl.html). 637 | --------------------------------------------------------------------------------