├── .gitignore ├── src ├── main │ ├── resources │ │ ├── Readme.txt │ │ ├── ExternalTimeSet.php │ │ ├── plugin.yml │ │ ├── changelog.txt │ │ ├── minecraft.php │ │ └── Websend.php │ └── java │ │ └── com │ │ └── github │ │ └── websend │ │ ├── script │ │ ├── ScriptInterface.java │ │ ├── Script.java │ │ └── ScriptManager.java │ │ ├── API.java │ │ ├── Task.java │ │ ├── PacketHandler.java │ │ ├── server │ │ ├── NonSecureCommunicationServer.java │ │ ├── SecureCommunicationServer.java │ │ └── CommunicationServer.java │ │ ├── events │ │ ├── configuration │ │ │ ├── AdvancementEventsConfiguration.java │ │ │ ├── EnchantmentEventsConfiguration.java │ │ │ ├── WeatherEventsConfiguration.java │ │ │ ├── HangingEventsConfiguration.java │ │ │ ├── WorldEventsConfiguration.java │ │ │ ├── VehicleEventsConfiguration.java │ │ │ ├── InventoryEventsConfiguration.java │ │ │ ├── BlockEventsConfiguration.java │ │ │ ├── EntityEventsConfiguration.java │ │ │ ├── Configuration.java │ │ │ ├── PlayerEventsConfiguration.java │ │ │ └── ServerEventsConfiguration.java │ │ ├── listener │ │ │ ├── AdvancementsListener.java │ │ │ ├── EnchantmentListener.java │ │ │ ├── WeatherListener.java │ │ │ ├── HangingListener.java │ │ │ ├── ServerListener.java │ │ │ ├── WorldListener.java │ │ │ ├── VehicleListener.java │ │ │ ├── InventoryListener.java │ │ │ ├── BlockListener.java │ │ │ └── EntityListener.java │ │ └── Main.java │ │ ├── Util.java │ │ ├── post │ │ ├── POSTHandlerThread.java │ │ ├── POSTHandlerThreadPool.java │ │ └── POSTRequest.java │ │ ├── TrustedHosts.java │ │ ├── CompressionToolkit.java │ │ ├── spigot │ │ └── SpigotJSONSerializer.java │ │ ├── Settings.java │ │ ├── PluginOutputManager.java │ │ ├── JSONSerializer.java │ │ ├── WebsendConsoleCommandSender.java │ │ ├── ConfigHandler.java │ │ ├── Main.java │ │ └── CommandParser.java └── test │ └── java │ └── com │ └── github │ └── websend │ └── events │ └── AppTest.java ├── .mvn └── wrapper │ └── maven-wrapper.properties ├── nb-configuration.xml ├── dependency-reduced-pom.xml ├── pom.xml ├── mvnw.cmd ├── Readme.md └── mvnw /.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | /lib/*.jar 3 | /release/ -------------------------------------------------------------------------------- /src/main/resources/Readme.txt: -------------------------------------------------------------------------------- 1 | Go to https://github.com/uncovery/Websend for documentation on installation and usage of this plugin. -------------------------------------------------------------------------------- /src/main/java/com/github/websend/script/ScriptInterface.java: -------------------------------------------------------------------------------- 1 | package com.github.websend.script; 2 | 3 | public interface ScriptInterface { 4 | public void run(); 5 | } 6 | -------------------------------------------------------------------------------- /src/main/java/com/github/websend/API.java: -------------------------------------------------------------------------------- 1 | package com.github.websend; 2 | 3 | public class API { 4 | 5 | public static void registerCustomPacketHandler(PacketHandler wph) { 6 | Main.getCommunicationServer().addPacketHandler(wph); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/main/resources/ExternalTimeSet.php: -------------------------------------------------------------------------------- 1 | password = "websendpassword"; 10 | 11 | if($ws->connect()){ 12 | $ws->doCommandAsConsole("time set 6000"); 13 | echo "Time set."; 14 | }else{ 15 | echo "Failed to connect."; 16 | } 17 | $ws->disconnect(); -------------------------------------------------------------------------------- /src/main/java/com/github/websend/Task.java: -------------------------------------------------------------------------------- 1 | package com.github.websend; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Arrays; 5 | 6 | public abstract class Task implements Runnable { 7 | 8 | private ArrayList arguments = new ArrayList(); 9 | 10 | public Task(Object... arg) { 11 | arguments.addAll(Arrays.asList(arg)); 12 | } 13 | 14 | public ArrayList getArgs() { 15 | return arguments; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/github/websend/PacketHandler.java: -------------------------------------------------------------------------------- 1 | package com.github.websend; 2 | 3 | import java.io.DataInputStream; 4 | import java.io.DataOutputStream; 5 | 6 | public abstract class PacketHandler { 7 | 8 | private byte header; 9 | 10 | public PacketHandler(byte header) { 11 | this.header = header; 12 | } 13 | 14 | public abstract void onHeaderReceived(DataInputStream in, DataOutputStream out); 15 | 16 | public byte getHeader() { 17 | return header; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/com/github/websend/server/NonSecureCommunicationServer.java: -------------------------------------------------------------------------------- 1 | package com.github.websend.server; 2 | 3 | import java.io.IOException; 4 | import java.net.InetAddress; 5 | import java.net.ServerSocket; 6 | 7 | public class NonSecureCommunicationServer extends CommunicationServer{ 8 | @Override 9 | ServerSocket openServerSocket(InetAddress bindIP, int port) throws IOException { 10 | return new ServerSocket(port, 0, bindIP); 11 | } 12 | 13 | @Override 14 | ServerSocket openServerSocket(int port) throws IOException { 15 | return new ServerSocket(port); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/github/websend/events/configuration/AdvancementEventsConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.github.websend.events.configuration; 2 | 3 | import com.github.websend.events.listener.AdvancementsListener; 4 | 5 | public class AdvancementEventsConfiguration extends Configuration { 6 | 7 | @Override 8 | public String getFilename() { 9 | return "advancement.txt"; 10 | } 11 | 12 | @Override 13 | public String[] getEventNameList() { 14 | return new String[]{ 15 | "PlayerAdvancementDoneEvent", 16 | }; 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/com/github/websend/events/configuration/EnchantmentEventsConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.github.websend.events.configuration; 2 | 3 | import com.github.websend.events.listener.EnchantmentListener; 4 | 5 | public class EnchantmentEventsConfiguration extends Configuration { 6 | 7 | @Override 8 | public String getFilename() { 9 | return "enchantment.txt"; 10 | } 11 | 12 | @Override 13 | public String[] getEventNameList() { 14 | return new String[]{ 15 | "EnchantItemEvent", 16 | "PrepareItemEnchantEvent" 17 | }; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/com/github/websend/events/configuration/WeatherEventsConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.github.websend.events.configuration; 2 | 3 | import com.github.websend.events.listener.WeatherListener; 4 | 5 | public class WeatherEventsConfiguration extends Configuration { 6 | 7 | @Override 8 | public String getFilename() { 9 | return "weather.txt"; 10 | } 11 | 12 | @Override 13 | public String[] getEventNameList() { 14 | return new String[]{ 15 | "LightningStrikeEvent", 16 | "ThunderChangeEvent", 17 | "WeatherChangeEvent" 18 | }; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/github/websend/events/configuration/HangingEventsConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.github.websend.events.configuration; 2 | 3 | import com.github.websend.events.listener.HangingListener; 4 | 5 | public class HangingEventsConfiguration extends Configuration { 6 | 7 | @Override 8 | public String getFilename() { 9 | return "hanging.txt"; 10 | } 11 | 12 | @Override 13 | public String[] getEventNameList() { 14 | return new String[]{ 15 | "HangingBreakByEntityEvent", 16 | "HangingBreakEvent", 17 | "HangingPlaceEvent" 18 | }; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/resources/plugin.yml: -------------------------------------------------------------------------------- 1 | name: Websend 2 | main: com.github.websend.Main 3 | version: 5.8 4 | description: Plug-in to enable variables-transfer to the interwebs and backwards. 5 | author: Waterflames 6 | api-version: 1.21.4 7 | commands: 8 | websend: 9 | description: Starts communication. 10 | usage: | 11 | / 12 | ws: 13 | description: Starts communication. 14 | usage: | 15 | / 16 | wsScripts: 17 | description: Scripts 18 | usage: | 19 | / 20 | permissions: 21 | websend: 22 | description: Allows you to use websend 23 | default: op 24 | websend.scripts: 25 | description: Allows you to perform /wsScripts 26 | default: op -------------------------------------------------------------------------------- /src/test/java/com/github/websend/events/AppTest.java: -------------------------------------------------------------------------------- 1 | package com.github.websend.events; 2 | 3 | import junit.framework.Test; 4 | import junit.framework.TestCase; 5 | import junit.framework.TestSuite; 6 | 7 | /** 8 | * Unit test for simple App. 9 | */ 10 | public class AppTest 11 | extends TestCase 12 | { 13 | /** 14 | * Create the test case 15 | * 16 | * @param testName name of the test case 17 | */ 18 | public AppTest( String testName ) 19 | { 20 | super( testName ); 21 | } 22 | 23 | /** 24 | * @return the suite of tests being tested 25 | */ 26 | public static Test suite() 27 | { 28 | return new TestSuite( AppTest.class ); 29 | } 30 | 31 | /** 32 | * Rigourous Test :-) 33 | */ 34 | public void testApp() 35 | { 36 | assertTrue( true ); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/resources/changelog.txt: -------------------------------------------------------------------------------- 1 | This is a changelog from v.5.0 on. Previous changes cover updates to make Websend compatible with recent versions of minecraft and additional information passed in JSON. 2 | 3 | Version 5.6 4 | 5 | - Updated to 1.19 6 | 7 | Version 5.5: 8 | 9 | - Updated to 1.17 10 | 11 | Version 5.4: 12 | 13 | - fixed issues with crossbows crashing command execution 14 | 15 | Version 5.3: 16 | 17 | - Updated to 1.16.5 18 | 19 | Version 5.2: 20 | 21 | - added more debug info for the server 22 | 23 | Version 5.1: 24 | 25 | - improved debug info regarding arguments (not) passed. 26 | - allow toggleDebug to set a state instead of only switching the current state. See Readme.md for details. 27 | 28 | Version 5.0: 29 | 30 | - add toggleDebug action. See Readme.md for details. 31 | - convert data format to be received from mixed-delimited text to JSON. This breaks current code. See Readme.md for details. 32 | -------------------------------------------------------------------------------- /src/main/java/com/github/websend/events/configuration/WorldEventsConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.github.websend.events.configuration; 2 | 3 | import com.github.websend.events.listener.WorldListener; 4 | 5 | public class WorldEventsConfiguration extends Configuration { 6 | 7 | @Override 8 | public String getFilename() { 9 | return "world.txt"; 10 | } 11 | 12 | @Override 13 | public String[] getEventNameList() { 14 | return new String[]{ 15 | "ChunkEvent", 16 | "ChunkLoadEvent", 17 | "ChunkPopulateEvent", 18 | "ChunkUnloadEvent", 19 | "PortalCreateEvent", 20 | "SpawnChangeEvent", 21 | "StructureGrowEvent", 22 | "WorldInitEvent", 23 | "WorldLoadEvent", 24 | "WorldSaveEvent", 25 | "WorldUnloadEvent" 26 | }; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/com/github/websend/events/configuration/VehicleEventsConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.github.websend.events.configuration; 2 | 3 | import com.github.websend.events.listener.VehicleListener; 4 | 5 | public class VehicleEventsConfiguration extends Configuration { 6 | 7 | @Override 8 | public String getFilename() { 9 | return "vehicle.txt"; 10 | } 11 | 12 | @Override 13 | public String[] getEventNameList() { 14 | return new String[]{ 15 | "VehicleBlockCollisionEvent", 16 | "VehicleCollisionEvent", 17 | "VehicleCreateEvent", 18 | "VehicleDamageEvent", 19 | "VehicleDestroyEvent", 20 | "VehicleEnterEvent", 21 | "VehicleEntityCollisionEvent", 22 | "VehicleExitEvent", 23 | "VehicleMoveEvent", 24 | "VehicleUpdateEvent" 25 | }; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one 2 | # or more contributor license agreements. See the NOTICE file 3 | # distributed with this work for additional information 4 | # regarding copyright ownership. The ASF licenses this file 5 | # to you under the Apache License, Version 2.0 (the 6 | # "License"); you may not use this file except in compliance 7 | # with the License. You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, 12 | # software distributed under the License is distributed on an 13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | # KIND, either express or implied. See the License for the 15 | # specific language governing permissions and limitations 16 | # under the License. 17 | wrapperVersion=3.3.2 18 | distributionType=only-script 19 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.9/apache-maven-3.9.9-bin.zip 20 | -------------------------------------------------------------------------------- /src/main/java/com/github/websend/events/listener/AdvancementsListener.java: -------------------------------------------------------------------------------- 1 | package com.github.websend.events.listener; 2 | 3 | import com.github.websend.Main; 4 | import com.github.websend.events.configuration.AdvancementEventsConfiguration; 5 | import org.bukkit.advancement.Advancement; 6 | import org.bukkit.event.EventHandler; 7 | import org.bukkit.event.Listener; 8 | import org.bukkit.event.player.PlayerAdvancementDoneEvent; 9 | 10 | public class AdvancementsListener implements Listener{ 11 | AdvancementEventsConfiguration config = null; 12 | 13 | public AdvancementsListener(AdvancementEventsConfiguration config) { 14 | this.config = config; 15 | } 16 | 17 | @EventHandler 18 | public void onEvent(PlayerAdvancementDoneEvent e){ 19 | if(config.isEventEnabled(e.getEventName())){ 20 | Advancement advancement = e.getAdvancement(); 21 | String[] array = {"event", e.getEventName(), advancement.getKey().toString()}; 22 | Main.doCommand(array, e.getPlayer()); 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /src/main/java/com/github/websend/server/SecureCommunicationServer.java: -------------------------------------------------------------------------------- 1 | package com.github.websend.server; 2 | 3 | import java.io.IOException; 4 | import java.net.InetAddress; 5 | import java.net.ServerSocket; 6 | import javax.net.ssl.SSLServerSocket; 7 | import javax.net.ssl.SSLServerSocketFactory; 8 | 9 | public class SecureCommunicationServer extends CommunicationServer{ 10 | @Override 11 | ServerSocket openServerSocket(InetAddress bindIP, int port) throws IOException { 12 | SSLServerSocketFactory sslserversocketfactory = (SSLServerSocketFactory) SSLServerSocketFactory.getDefault(); 13 | SSLServerSocket sslserversocket = (SSLServerSocket) sslserversocketfactory.createServerSocket(port, 0, bindIP); 14 | return sslserversocket; 15 | } 16 | 17 | @Override 18 | ServerSocket openServerSocket(int port) throws IOException { 19 | SSLServerSocketFactory sslserversocketfactory = (SSLServerSocketFactory) SSLServerSocketFactory.getDefault(); 20 | SSLServerSocket sslserversocket = (SSLServerSocket) sslserversocketfactory.createServerSocket(port); 21 | return sslserversocket; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /nb-configuration.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | 10 | 16 | true 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/main/java/com/github/websend/events/listener/EnchantmentListener.java: -------------------------------------------------------------------------------- 1 | package com.github.websend.events.listener; 2 | 3 | import com.github.websend.Main; 4 | import com.github.websend.events.configuration.EnchantmentEventsConfiguration; 5 | import org.bukkit.event.EventHandler; 6 | import org.bukkit.event.Listener; 7 | import org.bukkit.event.enchantment.*; 8 | 9 | public class EnchantmentListener implements Listener{ 10 | EnchantmentEventsConfiguration config = null; 11 | 12 | public EnchantmentListener(EnchantmentEventsConfiguration config) { 13 | this.config = config; 14 | } 15 | 16 | @EventHandler 17 | public void onEvent(PrepareItemEnchantEvent e){ 18 | if(config.isEventEnabled(e.getEventName())){ 19 | String[] array = {"event", e.getEventName()}; 20 | Main.doCommand(array, "WEBSEND_EVENTS_ENCHANTMENT"); 21 | } 22 | } 23 | 24 | @EventHandler 25 | public void onEvent(EnchantItemEvent e){ 26 | if(config.isEventEnabled(e.getEventName())){ 27 | String[] array = {"event", e.getEventName()}; 28 | Main.doCommand(array, "WEBSEND_EVENTS_ENCHANTMENT"); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/com/github/websend/events/configuration/InventoryEventsConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.github.websend.events.configuration; 2 | 3 | import com.github.websend.events.listener.InventoryListener; 4 | 5 | public class InventoryEventsConfiguration extends Configuration { 6 | 7 | @Override 8 | public String getFilename() { 9 | return "inventory.txt"; 10 | } 11 | 12 | @Override 13 | public String[] getEventNameList() { 14 | return new String[]{ 15 | "BrewEvent", 16 | "CraftItemEvent", 17 | "FurnaceBurnEvent", 18 | "FurnaceExtractEvent", 19 | "FurnaceSmeltEvent", 20 | "InventoryClickEvent", 21 | "InventoryCloseEvent", 22 | "InventoryCreativeEvent", 23 | "InventoryDragEvent", 24 | "InventoryInteractEvent", 25 | "InventoryMoveItemEvent", 26 | "InventoryOpenEvent", 27 | "InventoryPickupItemEvent", 28 | "PrepareAnvilEvent", 29 | "PrepareItemCraftEvent"}; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/com/github/websend/script/Script.java: -------------------------------------------------------------------------------- 1 | package com.github.websend.script; 2 | 3 | import com.github.websend.Main; 4 | import java.util.ArrayList; 5 | import java.util.logging.Level; 6 | 7 | public class Script { 8 | public String name; 9 | public boolean invokeOnLoad = false; 10 | private ArrayList> classes = new ArrayList>(); 11 | private Class main; 12 | 13 | public Script(String name) { 14 | this.name = name; 15 | } 16 | 17 | public void invoke() { 18 | try { 19 | if (main == null) { 20 | Main.getMainLogger().log(Level.SEVERE, "No main class found for " + name + "!"); 21 | } 22 | ScriptInterface scriptMain = main.newInstance(); 23 | scriptMain.run(); 24 | } catch (InstantiationException ex) { 25 | Main.getMainLogger().log(Level.SEVERE, "Could not instantiate script.", ex); 26 | } catch (IllegalAccessException ex) { 27 | Main.getMainLogger().log(Level.SEVERE, "Run method in script is not accessible.", ex); 28 | } 29 | } 30 | 31 | public void addClass(Class newClass) { 32 | classes.add(newClass); 33 | } 34 | 35 | public void setMainClass(Class newMain) { 36 | main = newMain; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/com/github/websend/events/listener/WeatherListener.java: -------------------------------------------------------------------------------- 1 | package com.github.websend.events.listener; 2 | 3 | import com.github.websend.Main; 4 | import com.github.websend.events.configuration.WeatherEventsConfiguration; 5 | import org.bukkit.event.EventHandler; 6 | import org.bukkit.event.Listener; 7 | import org.bukkit.event.weather.*; 8 | 9 | public class WeatherListener implements Listener{ 10 | WeatherEventsConfiguration config = null; 11 | 12 | public WeatherListener(WeatherEventsConfiguration config) { 13 | this.config = config; 14 | } 15 | 16 | @EventHandler 17 | public void onEvent(LightningStrikeEvent e){ 18 | if(config.isEventEnabled(e.getEventName())){ 19 | String[] array = {"event", e.getEventName()}; 20 | Main.doCommand(array, "WEBSEND_EVENTS_WEATHER"); 21 | } 22 | } 23 | 24 | @EventHandler 25 | public void onEvent(ThunderChangeEvent e){ 26 | if(config.isEventEnabled(e.getEventName())){ 27 | String[] array = {"event", e.getEventName()}; 28 | Main.doCommand(array, "WEBSEND_EVENTS_WEATHER"); 29 | } 30 | } 31 | 32 | @EventHandler 33 | public void onEvent(WeatherChangeEvent e){ 34 | if(config.isEventEnabled(e.getEventName())){ 35 | String[] array = {"event", e.getEventName()}; 36 | Main.doCommand(array, "WEBSEND_EVENTS_WEATHER"); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/com/github/websend/events/listener/HangingListener.java: -------------------------------------------------------------------------------- 1 | package com.github.websend.events.listener; 2 | 3 | import com.github.websend.Main; 4 | import com.github.websend.events.configuration.HangingEventsConfiguration; 5 | import org.bukkit.event.EventHandler; 6 | import org.bukkit.event.Listener; 7 | import org.bukkit.event.hanging.*; 8 | 9 | public class HangingListener implements Listener{ 10 | HangingEventsConfiguration config = null; 11 | 12 | public HangingListener(HangingEventsConfiguration config) { 13 | this.config = config; 14 | } 15 | 16 | @EventHandler 17 | public void onEvent(HangingBreakByEntityEvent e){ 18 | if(config.isEventEnabled(e.getEventName())){ 19 | String[] array = {"event", e.getEventName()}; 20 | Main.doCommand(array, "WEBSEND_EVENTS_HANGING"); 21 | } 22 | } 23 | 24 | @EventHandler 25 | public void onEvent(HangingBreakEvent e){ 26 | if(config.isEventEnabled(e.getEventName())){ 27 | String[] array = {"event", e.getEventName()}; 28 | Main.doCommand(array, "WEBSEND_EVENTS_HANGING"); 29 | } 30 | } 31 | 32 | @EventHandler 33 | public void onEvent(HangingPlaceEvent e){ 34 | if(config.isEventEnabled(e.getEventName())){ 35 | String[] array = {"event", e.getEventName()}; 36 | Main.doCommand(array, "WEBSEND_EVENTS_HANGING"); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/com/github/websend/events/configuration/BlockEventsConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.github.websend.events.configuration; 2 | 3 | import com.github.websend.events.listener.BlockListener; 4 | 5 | public class BlockEventsConfiguration extends Configuration { 6 | 7 | @Override 8 | public String getFilename() { 9 | return "block.txt"; 10 | } 11 | 12 | @Override 13 | public String[] getEventNameList() { 14 | return new String[]{ 15 | "BlockBreakEvent", 16 | "BlockBurnEvent", 17 | "BlockCanBuildEvent", 18 | "BlockDamageEvent", 19 | "BlockDispenseEvent", 20 | "BlockExpEvent", 21 | "BlockExplodeEvent", 22 | "BlockFadeEvent", 23 | "BlockFormEvent", 24 | "BlockFromToEvent", 25 | "BlockGrowEvent", 26 | "BlockIgniteEvent", 27 | "BlockPhysicsEvent", 28 | "BlockPistonExtendEvent", 29 | "BlockPistonRetractEvent", 30 | "BlockPlaceEvent", 31 | "BlockMultiPlaceEvent", 32 | "BlockRedstoneEvent", 33 | "CauldronLevelChangeEvent", 34 | "BlockSpreadEvent", 35 | "EntityBlockFormEvent", 36 | "LeavesDecayEvent", 37 | "NotePlayEvent", 38 | "SignChangeEvent" 39 | }; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/com/github/websend/Util.java: -------------------------------------------------------------------------------- 1 | package com.github.websend; 2 | 3 | import java.math.BigInteger; 4 | import java.security.MessageDigest; 5 | import java.util.UUID; 6 | import java.util.logging.Level; 7 | import org.bukkit.entity.Player; 8 | 9 | public class Util { 10 | 11 | public static String stringArrayToString(String[] strings) { 12 | StringBuilder buffer = new StringBuilder(); 13 | for (int i = 0; i < strings.length; i++) { 14 | buffer.append(strings[i]); 15 | } 16 | return buffer.toString(); 17 | } 18 | 19 | public static String hash(String input) { 20 | try { 21 | MessageDigest md = MessageDigest.getInstance(Main.getSettings().getHashingAlgorithm()); 22 | md.update(input.getBytes()); 23 | BigInteger bigInt = new BigInteger(1, md.digest()); 24 | String result = bigInt.toString(16); 25 | if ((result.length() % 2) != 0) { 26 | result = "0" + result; 27 | } 28 | return result; 29 | } catch (Exception ex) { 30 | Main.getMainLogger().info("Failed to hash password to " + Main.getSettings().getHashingAlgorithm()); 31 | return ""; 32 | } 33 | } 34 | 35 | /** 36 | * returns Player Object or Null 37 | * 38 | * @param playerStr 39 | * @return 40 | */ 41 | public static Player findPlayer(String playerStr){ 42 | Player player = null; 43 | try { 44 | UUID playerID = UUID.fromString(playerStr); 45 | player = Main.getBukkitServer().getPlayer(playerID); 46 | } catch (IllegalArgumentException ex) { 47 | if (Main.getSettings().isDebugMode()) { 48 | Main.logDebugInfo(Level.INFO, 49 | "Could not find player with UUID '"+playerStr+"'. " 50 | + "Searching for a player with a matching name instead."); 51 | } 52 | } 53 | 54 | if (player == null) { 55 | player = Main.getBukkitServer().getPlayer(playerStr); 56 | } 57 | 58 | return player; 59 | } 60 | } 61 | 62 | 63 | -------------------------------------------------------------------------------- /src/main/java/com/github/websend/post/POSTHandlerThread.java: -------------------------------------------------------------------------------- 1 | package com.github.websend.post; 2 | 3 | import com.github.websend.Main; 4 | import java.io.IOException; 5 | import java.util.logging.Level; 6 | import java.util.logging.Logger; 7 | import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; 8 | import org.apache.hc.client5.http.impl.classic.HttpClientBuilder; 9 | 10 | public class POSTHandlerThread extends Thread { 11 | private final POSTHandlerThreadPool parent; 12 | private final CloseableHttpClient httpClient; 13 | private boolean running = true; 14 | private boolean busy = false; 15 | private POSTRequest currentRequest; 16 | 17 | public POSTHandlerThread(POSTHandlerThreadPool parent, HttpClientBuilder builder) { 18 | super("Websend POST Request Handler"); 19 | this.httpClient = builder.build(); 20 | this.parent = parent; 21 | } 22 | 23 | @Override 24 | public void run() { 25 | while (running) { 26 | if (currentRequest != null) { 27 | busy = true; 28 | try { 29 | currentRequest.run(httpClient); 30 | } catch (IOException ex) { 31 | Main.getMainLogger().log(Level.SEVERE, "An exception occurred while running a POST request.", ex); 32 | } 33 | parent.onThreadDone(this); 34 | currentRequest = null; 35 | busy = false; 36 | } else { 37 | try { 38 | Thread.sleep(20); 39 | } catch (InterruptedException ex) { 40 | Logger.getLogger(POSTHandlerThread.class.getName()).log(Level.SEVERE, "Thread interrupted.", ex); 41 | } 42 | } 43 | } 44 | try { 45 | httpClient.close(); 46 | } catch (IOException ex) { 47 | Main.logDebugInfo(Level.WARNING, "An exception occurred while closing the HttpClient.", ex); 48 | } 49 | } 50 | 51 | public void startRequest(POSTRequest request) { 52 | if (!busy) { 53 | currentRequest = request; 54 | busy = true; 55 | } else { 56 | throw new RuntimeException("Tried to assign request to busy thread!"); 57 | } 58 | } 59 | 60 | public void stopRunning() { 61 | running = false; 62 | } 63 | 64 | public boolean isBusy() { 65 | return busy; 66 | } 67 | } -------------------------------------------------------------------------------- /src/main/java/com/github/websend/TrustedHosts.java: -------------------------------------------------------------------------------- 1 | package com.github.websend; 2 | 3 | import java.io.*; 4 | import java.net.InetAddress; 5 | import java.util.ArrayList; 6 | import java.util.logging.Level; 7 | 8 | public class TrustedHosts { 9 | 10 | private static ArrayList trusted = new ArrayList(); 11 | private static boolean allIsTrusted = false; 12 | 13 | public static void load(File file) throws IOException { 14 | BufferedReader reader = null; 15 | try { 16 | reader = new BufferedReader(new FileReader(file)); 17 | String line; 18 | while ((line = reader.readLine()) != null) { 19 | if (line.startsWith("#") || line.trim().equals("")) { 20 | } else if ("trust_all".equals(line.trim().toLowerCase())) { 21 | allIsTrusted = true; 22 | } else { 23 | trusted.add(InetAddress.getByName(line)); 24 | } 25 | } 26 | reader.close(); 27 | } finally { 28 | if (reader != null) { 29 | reader.close(); 30 | } 31 | } 32 | } 33 | 34 | public static boolean isTrusted(InetAddress address) { 35 | return trusted.contains(address) || allIsTrusted; 36 | } 37 | 38 | static void writeDefaultFile(File trustedFile) throws IOException { 39 | if (!trustedFile.createNewFile()) { 40 | Main.getMainLogger().log(Level.WARNING, "Failed to make trusted hosts file."); 41 | } 42 | PrintWriter writer = new PrintWriter(new FileWriter(trustedFile)); 43 | writer.println("#Put your trusted domains in this file."); 44 | writer.println("#Trusted domains can connect to websend via php->websend."); 45 | writer.println("#Domains are allowed in either IP or hostname form."); 46 | writer.println("#To allow everybody put trust_all"); 47 | writer.println("trust_all"); 48 | writer.println("#http://example.com/"); 49 | writer.println("#123.456.798.132"); 50 | writer.flush(); 51 | writer.close(); 52 | } 53 | 54 | public static ArrayList getList() { 55 | return trusted; 56 | } 57 | 58 | public static void add(InetAddress address) { 59 | trusted.add(address); 60 | } 61 | 62 | public static void remove(InetAddress address) { 63 | trusted.remove(address); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/main/java/com/github/websend/CompressionToolkit.java: -------------------------------------------------------------------------------- 1 | package com.github.websend; 2 | 3 | import java.io.ByteArrayInputStream; 4 | import java.io.ByteArrayOutputStream; 5 | import java.io.IOException; 6 | import java.util.zip.Deflater; 7 | import java.util.zip.DeflaterOutputStream; 8 | import java.util.zip.GZIPInputStream; 9 | import java.util.zip.GZIPOutputStream; 10 | import java.util.zip.Inflater; 11 | import java.util.zip.InflaterOutputStream; 12 | 13 | public class CompressionToolkit { 14 | 15 | /** 16 | * DEFLATE: usable with DEFLATE Compressed Data Format Specification version 1.3 as used by PHP's gzdeflate 17 | */ 18 | public static byte[] deflateString(String str) throws IOException { 19 | ByteArrayOutputStream baos = new ByteArrayOutputStream(); 20 | Deflater deflater = new Deflater(1, true); 21 | DeflaterOutputStream out = new DeflaterOutputStream(baos, deflater); 22 | byte[] data = str.getBytes("UTF-8"); 23 | out.write(data); 24 | out.flush(); 25 | out.close(); 26 | return baos.toByteArray(); 27 | } 28 | 29 | public static String inflateString(byte[] strData) throws IOException { 30 | ByteArrayOutputStream baos = new ByteArrayOutputStream(); 31 | Inflater inflater = new Inflater(true); 32 | InflaterOutputStream out = new InflaterOutputStream(baos, inflater); 33 | out.write(strData); 34 | out.flush(); 35 | out.close(); 36 | return baos.toString("UTF-8"); 37 | } 38 | 39 | /** 40 | * GZIP: usable with GZIP file format specification version 4.3 as used by PHP's gzencode 41 | */ 42 | public static byte[] gzipString(String str) throws IOException { 43 | ByteArrayOutputStream baos = new ByteArrayOutputStream(); 44 | GZIPOutputStream out = new GZIPOutputStream(baos); 45 | byte[] data = str.getBytes("UTF-8"); 46 | out.write(data); 47 | out.flush(); 48 | out.close(); 49 | return baos.toByteArray(); 50 | } 51 | 52 | public static String ungzipString(byte[] strData) throws IOException { 53 | ByteArrayOutputStream baos = new ByteArrayOutputStream(); 54 | byte[] buffer = new byte[512]; 55 | GZIPInputStream in = new GZIPInputStream(new ByteArrayInputStream(strData)); 56 | while (in.available() != 0) { 57 | int readBytes = in.read(buffer); 58 | if (readBytes != 0) { 59 | baos.write(buffer, 0, readBytes); 60 | } 61 | } 62 | return baos.toString("UTF-8"); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/main/java/com/github/websend/events/configuration/EntityEventsConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.github.websend.events.configuration; 2 | 3 | import com.github.websend.events.listener.EntityListener; 4 | 5 | public class EntityEventsConfiguration extends Configuration { 6 | 7 | @Override 8 | public String getFilename() { 9 | return "entity.txt"; 10 | } 11 | 12 | @Override 13 | public String[] getEventNameList() { 14 | return new String[]{ 15 | "CreatureSpawnEvent", 16 | "CreeperPowerEvent", 17 | "EntityBreakDoorEvent", 18 | "EntityChangeBlockEvent", 19 | "EntityCombustByBlockEvent", 20 | "EntityCombustByEntityEvent", 21 | "EntityCombustEvent", 22 | "EntityCreatePortalEvent", 23 | "EntityDamageByBlockEvent", 24 | "EntityDamageByEntityEvent", 25 | "EntityDamageEvent", 26 | "EntityDeathEvent", 27 | "EntityExplodeEvent", 28 | "EntityInteractEvent", 29 | "EntityPortalEnterEvent", 30 | "EntityPortalEvent", 31 | "EntityPortalExitEvent", 32 | "EntityRegainHealthEvent", 33 | "EntityShootBowEvent", 34 | "EntityTameEvent", 35 | "EntityTargetEvent", 36 | "EntityTargetLivingEntityEvent", 37 | "EntityTeleportEvent", 38 | "EntityUnleashEvent", 39 | "ExpBottleEvent", 40 | "ExplosionPrimeEvent", 41 | "FireworkExplodeEvent", 42 | "FoodLevelChangeEvent", 43 | "HorseJumpEvent", 44 | "ItemDespawnEvent", 45 | "ItemMergeEvent", 46 | "ItemSpawnEvent", 47 | "PigZapEvent", 48 | "PlayerDeathEvent", 49 | "PlayerLeashEntityEvent", 50 | "PotionSplashEvent", 51 | "ProjectileHitEvent", 52 | "ProjectileLaunchEvent", 53 | "SheepDyeWoolEvent", 54 | "SheepRegrowWoolEvent", 55 | "SlimeSplitEvent", 56 | "VillagerAcquireTradeEvent", 57 | "VillagerReplenishTradeEvent" 58 | }; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/com/github/websend/events/configuration/Configuration.java: -------------------------------------------------------------------------------- 1 | package com.github.websend.events.configuration; 2 | 3 | import com.github.websend.events.Main; 4 | import java.io.*; 5 | import java.util.HashSet; 6 | import java.util.logging.Level; 7 | import org.bukkit.event.Listener; 8 | 9 | public abstract class Configuration { 10 | protected HashSet activeEventsList = new HashSet(); 11 | 12 | public void loadConfiguration() throws IOException{ 13 | File configFile = new File(Main.getInstance().getDataFolder(), this.getFilename()); 14 | if(!configFile.exists()){ 15 | Main.getInstance().getDataFolder().mkdirs(); 16 | configFile.createNewFile(); 17 | writeConfigurationFile(configFile); 18 | } 19 | BufferedReader reader = new BufferedReader(new FileReader(configFile)); 20 | String line; 21 | while((line = reader.readLine()) != null){ 22 | this.parseLine(line); 23 | } 24 | reader.close(); 25 | } 26 | 27 | public boolean isEventEnabled(String eventName){ 28 | return activeEventsList.contains(eventName); 29 | } 30 | 31 | public boolean hasActiveEvent(){ 32 | return !activeEventsList.isEmpty(); 33 | } 34 | 35 | protected void parseLine(String line){ 36 | String[] parts = line.split("="); 37 | if(parts.length != 2){ 38 | Main.getInstance().getLogger().log(Level.WARNING, "Invalid config line: "+line); 39 | }else{ 40 | String name = parts[0].trim(); 41 | String boolString = parts[1].trim(); 42 | boolean active = Boolean.parseBoolean(boolString.trim()); 43 | if(active){ 44 | activeEventsList.add(name); 45 | } 46 | } 47 | } 48 | 49 | protected String getDefaultConfig(){ 50 | StringBuilder builder = new StringBuilder(); 51 | for(String str : this.getEventNameList()){ 52 | builder.append(str+"=false\n"); 53 | } 54 | return builder.toString(); 55 | } 56 | 57 | public void writeConfigurationFile(File file) throws IOException{ 58 | try (PrintWriter writer = new PrintWriter(new FileWriter(file))) { 59 | writer.print(getDefaultConfig()); 60 | writer.flush(); 61 | } 62 | }; 63 | 64 | public abstract String getFilename(); 65 | public abstract String[] getEventNameList(); 66 | public void initialize(){} 67 | } 68 | -------------------------------------------------------------------------------- /src/main/java/com/github/websend/post/POSTHandlerThreadPool.java: -------------------------------------------------------------------------------- 1 | package com.github.websend.post; 2 | 3 | import com.github.websend.Main; 4 | import java.util.ArrayList; 5 | import java.util.concurrent.ConcurrentLinkedQueue; 6 | import java.util.logging.Level; 7 | import org.apache.hc.client5.http.impl.classic.HttpClientBuilder; 8 | 9 | public class POSTHandlerThreadPool { 10 | 11 | private ArrayList busyThreads; 12 | private ConcurrentLinkedQueue availableThreadsQueue; 13 | private HttpClientBuilder builder; 14 | private int maxPerRoute; 15 | private int maxTotal; 16 | 17 | public POSTHandlerThreadPool(int poolStartSize) { 18 | busyThreads = new ArrayList<>(); 19 | availableThreadsQueue = new ConcurrentLinkedQueue<>(); 20 | 21 | builder = HttpClientBuilder.create(); 22 | //builder.setMaxConnPerRoute(poolStartSize); // old version 23 | //builder.setMaxConnTotal(poolStartSize * 2); 24 | builder.setUserAgent("Websend/"+Main.getInstance().getDescription().getVersion()); 25 | 26 | maxPerRoute = poolStartSize; 27 | maxTotal = poolStartSize * 2; 28 | 29 | for (int i = 0; i < poolStartSize; i++) { 30 | POSTHandlerThread thread = new POSTHandlerThread(this, builder); 31 | thread.start(); 32 | availableThreadsQueue.offer(thread); 33 | } 34 | } 35 | 36 | public POSTHandlerThreadPool() { 37 | this(5); 38 | } 39 | 40 | public void doRequest(POSTRequest request) { 41 | POSTHandlerThread thread = availableThreadsQueue.poll(); 42 | if (thread == null) { 43 | if (maxTotal < maxPerRoute + 1) { 44 | maxTotal = (maxPerRoute + 1) * 2; 45 | //builder.setMaxConnTotal(maxTotal); // old version 46 | } 47 | //builder.setMaxConnPerRoute(++maxPerRoute); // old version 48 | thread = new POSTHandlerThread(this, builder); 49 | thread.start(); 50 | } 51 | thread.startRequest(request); 52 | } 53 | 54 | protected void onThreadDone(POSTHandlerThread thread) { 55 | busyThreads.remove(thread); 56 | availableThreadsQueue.offer(thread); 57 | } 58 | 59 | public void stopThreads() { 60 | for (POSTHandlerThread cur : availableThreadsQueue) { 61 | cur.stopRunning(); 62 | } 63 | while (!busyThreads.isEmpty()) { 64 | try { 65 | Thread.sleep(1); 66 | } catch (InterruptedException ex) { 67 | Main.logDebugInfo(Level.SEVERE, "PostHandlerThreadPool interrupted while shutting down.", ex); 68 | } 69 | } 70 | for (POSTHandlerThread cur : availableThreadsQueue) { 71 | cur.stopRunning(); 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/main/java/com/github/websend/events/configuration/PlayerEventsConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.github.websend.events.configuration; 2 | 3 | import com.github.websend.events.listener.PlayerListener; 4 | 5 | public class PlayerEventsConfiguration extends Configuration { 6 | 7 | @Override 8 | public String getFilename() { 9 | return "player.txt"; 10 | } 11 | 12 | @Override 13 | public String[] getEventNameList() { 14 | return new String[]{ 15 | "AsyncPlayerChatEvent", 16 | "AsyncPlayerPreLoginEvent", 17 | "PlayerAchievementAwardedEvent", 18 | "PlayerAnimationEvent", 19 | "PlayerArmorStandManipulateEvent", 20 | "PlayerBedEnterEvent", 21 | "PlayerBedLeaveEvent", 22 | "PlayerBucketEmptyEvent", 23 | "PlayerBucketFillEvent", 24 | "PlayerChangedWorldEvent", 25 | "PlayerChannelEvent", 26 | "PlayerChatEvent", 27 | "PlayerChatTabCompleteEvent", 28 | "PlayerCommandPreprocessEvent", 29 | "PlayerDropItemEvent", 30 | "PlayerEditBookEvent", 31 | "PlayerEggThrowEvent", 32 | "PlayerExpChangeEvent", 33 | "PlayerFishEvent", 34 | "PlayerGameModeChangeEvent", 35 | "PlayerInteractEntityEvent", 36 | "PlayerInteractAtEntityEvent", 37 | "PlayerInteractEvent", 38 | "PlayerInventoryEvent", 39 | "PlayerItemBreakEvent", 40 | "PlayerItemConsumeEvent", 41 | "PlayerItemHeldEvent", 42 | "PlayerJoinEvent", 43 | "PlayerKickEvent", 44 | "PlayerLevelChangeEvent", 45 | "PlayerLoginEvent", 46 | "PlayerMoveEvent", 47 | "PlayerPickupItemEvent", 48 | "PlayerPortalEvent", 49 | "PlayerPreLoginEvent", 50 | "PlayerQuitEvent", 51 | "PlayerResourcePackStatusEvent", 52 | "PlayerRegisterChannelEvent", 53 | "PlayerRespawnEvent", 54 | "PlayerShearEntityEvent", 55 | "PlayerStatisticIncrementEvent", 56 | "PlayerTeleportEvent", 57 | "PlayerToggleFlightEvent", 58 | "PlayerToggleSneakEvent", 59 | "PlayerToggleSprintEvent", 60 | "PlayerUnleashEntityEvent", 61 | "PlayerUnregisterChannelEvent", 62 | "PlayerVelocityEvent"}; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/main/resources/minecraft.php: -------------------------------------------------------------------------------- 1 | $action, 84 | 'targetPlayer' => $target_player, 85 | 'command' => $cmd, 86 | ); 87 | 88 | $json = json_encode($websend_array) . CHR(10); 89 | print($json); 90 | } -------------------------------------------------------------------------------- /src/main/java/com/github/websend/events/configuration/ServerEventsConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.github.websend.events.configuration; 2 | 3 | import com.github.websend.events.Main; 4 | import com.github.websend.events.listener.ServerListener; 5 | import java.util.logging.Level; 6 | import org.bukkit.Bukkit; 7 | 8 | public class ServerEventsConfiguration extends Configuration { 9 | private int customTickDuration = 100; 10 | 11 | @Override 12 | public void initialize() { 13 | if(this.isEventEnabled("TickEvent")){ 14 | Bukkit.getScheduler().scheduleSyncRepeatingTask(Main.getInstance(), new Runnable(){ 15 | @Override 16 | public void run() { 17 | String[] array = {"event", "TickEvent"}; 18 | com.github.websend.Main.doCommand(array, "WEBSEND_EVENTS_SERVER"); 19 | } 20 | }, 20, customTickDuration); 21 | } 22 | } 23 | 24 | @Override 25 | public String getFilename() { 26 | return "server.txt"; 27 | } 28 | 29 | @Override 30 | public String[] getEventNameList() { 31 | return new String[]{ 32 | "MapInitializeEvent", 33 | "PluginDisableEvent", 34 | "PluginEnableEvent", 35 | "RemoteServerCommandEvent", 36 | "ServerCommandEvent", 37 | "ServerListPingEvent", 38 | "ServiceRegisterEvent", 39 | "ServiceUnregisterEvent", 40 | "TickEvent" 41 | }; 42 | } 43 | 44 | @Override 45 | protected String getDefaultConfig() { 46 | String config = super.getDefaultConfig(); 47 | config += "TickEventDuration=100\n"; 48 | return config; 49 | } 50 | 51 | @Override 52 | protected void parseLine(String line) { 53 | String[] parts = line.split("="); 54 | if(parts.length != 2){ 55 | Main.getInstance().getLogger().log(Level.WARNING, "Invalid config line: "+line); 56 | }else{ 57 | String name = parts[0].trim(); 58 | String value = parts[1].trim(); 59 | 60 | if(name.equals("TickEvent")){ 61 | if(Boolean.parseBoolean(value.trim())){ 62 | super.activeEventsList.add(name); 63 | } 64 | }else if(name.equals("TickEventDuration")){ 65 | int ticks = Integer.parseInt(value); 66 | if(ticks <= 4){ 67 | Main.getInstance().getLogger().log(Level.WARNING, 68 | "CustomTickDuration is set to a very low value. This might affect server and network performance!"); 69 | } 70 | customTickDuration = ticks; 71 | }else{ 72 | super.parseLine(line); 73 | } 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/main/java/com/github/websend/spigot/SpigotJSONSerializer.java: -------------------------------------------------------------------------------- 1 | package com.github.websend.spigot; 2 | 3 | import com.github.websend.JSONSerializer; 4 | import com.github.websend.Main; 5 | import java.lang.reflect.InvocationTargetException; 6 | import java.util.List; 7 | import org.bukkit.DyeColor; 8 | import org.bukkit.inventory.meta.ItemMeta; 9 | import org.json.JSONArray; 10 | import org.json.JSONException; 11 | import org.json.JSONObject; 12 | 13 | public class SpigotJSONSerializer extends JSONSerializer{ 14 | public JSONObject serializeMetaCustom(ItemMeta meta) throws JSONException { 15 | if(meta.getClass().getSimpleName().equals("CraftMetaBanner")){ 16 | return serializeMetaBanner(meta); 17 | } 18 | return null; 19 | } 20 | 21 | public JSONObject serializeMetaBanner(ItemMeta bannerMeta) throws JSONException { 22 | DyeColor baseColor = (DyeColor)invokeMethod(bannerMeta, "getBaseColor", null); 23 | List patterns = (List)invokeMethod(bannerMeta, "getPatterns", null); 24 | if(baseColor != null && patterns != null){ 25 | JSONObject banner = new JSONObject(); 26 | { 27 | banner.put("BaseColor", baseColor.name()); 28 | 29 | JSONArray jsonPatterns = new JSONArray(); 30 | for(Object curPattern : patterns){ 31 | DyeColor color = (DyeColor)invokeMethod(curPattern, "getColor", null); 32 | String patternType = invokeMethod(curPattern, "getPattern", null).toString(); 33 | JSONObject curJSONPattern = new JSONObject(); 34 | { 35 | curJSONPattern.put("Color", color.name()); 36 | curJSONPattern.put("PatternType", patternType); 37 | } 38 | jsonPatterns.put(curJSONPattern); 39 | } 40 | banner.put("Patterns", jsonPatterns); 41 | } 42 | return banner; 43 | }else{ 44 | return null; 45 | } 46 | } 47 | 48 | private Object invokeMethod(Object targetObject, String methodName, Class[] argTypes, Object... args){ 49 | if(argTypes == null){ 50 | argTypes = new Class[]{}; 51 | } 52 | try { 53 | return targetObject.getClass().getMethod(methodName, argTypes).invoke(targetObject, (Object[])args); 54 | } catch (NoSuchMethodException ex) { 55 | Main.logError("Cannot retrieve Spigot object data: Spigot was detected, but class definition does not match", ex); 56 | } catch (SecurityException ex) { 57 | Main.logError("Cannot retrieve Spigot object data due to security settings preventing reflection", ex); 58 | } catch (IllegalAccessException ex) { 59 | Main.logError("Cannot retrieve Spigot object data: no access", ex); 60 | } catch (IllegalArgumentException ex) { 61 | Main.logError("Cannot retrieve Spigot object data: Spigot was detected, but class definition does not match", ex); 62 | } catch (InvocationTargetException ex) { 63 | Main.logError("An exception occured while retrieving Spigot object data", ex); 64 | } 65 | return null; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /dependency-reduced-pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | com.github.websend 5 | Websend 6 | 5.8 7 | 8 | 9 | 10 | maven-shade-plugin 11 | 3.2.1 12 | 13 | 14 | package 15 | 16 | shade 17 | 18 | 19 | 20 | 21 | Websend-${version} 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | spigot-repo 30 | https://hub.spigotmc.org/nexus/content/repositories/snapshots/ 31 | 32 | 33 | github.com 34 | https://github.com/ 35 | 36 | 37 | minecraft-libraries 38 | Minecraft Libraries 39 | https://libraries.minecraft.net 40 | 41 | 42 | 43 | 44 | junit 45 | junit 46 | 4.13.1 47 | test 48 | 49 | 50 | hamcrest-core 51 | org.hamcrest 52 | 53 | 54 | 55 | 56 | org.spigotmc 57 | spigot-api 58 | 1.21.4-R0.1-SNAPSHOT 59 | provided 60 | 61 | 62 | guava 63 | com.google.guava 64 | 65 | 66 | joml 67 | org.joml 68 | 69 | 70 | bungeecord-chat 71 | net.md-5 72 | 73 | 74 | snakeyaml 75 | org.yaml 76 | 77 | 78 | 79 | 80 | net.forthecrown 81 | PaperNBT 82 | 1.0.0 83 | pom 84 | compile 85 | 86 | 87 | 88 | 21 89 | 21 90 | UTF-8 91 | 92 | 93 | -------------------------------------------------------------------------------- /src/main/java/com/github/websend/events/listener/ServerListener.java: -------------------------------------------------------------------------------- 1 | package com.github.websend.events.listener; 2 | 3 | import com.github.websend.Main; 4 | import com.github.websend.events.configuration.ServerEventsConfiguration; 5 | import org.bukkit.event.EventHandler; 6 | import org.bukkit.event.Listener; 7 | import org.bukkit.event.server.*; 8 | 9 | public class ServerListener implements Listener{ 10 | ServerEventsConfiguration config = null; 11 | 12 | public ServerListener(ServerEventsConfiguration config) { 13 | this.config = config; 14 | } 15 | 16 | @EventHandler 17 | public void onEvent(MapInitializeEvent e){ 18 | if(config.isEventEnabled(e.getEventName())){ 19 | String[] array = {"event", e.getEventName()}; 20 | Main.doCommand(array, "WEBSEND_EVENTS_SERVER"); 21 | } 22 | } 23 | 24 | @EventHandler 25 | public void onEvent(PluginDisableEvent e){ 26 | if(config.isEventEnabled(e.getEventName())){ 27 | String[] array = {"event", e.getEventName()}; 28 | Main.doCommand(array, "WEBSEND_EVENTS_SERVER"); 29 | } 30 | } 31 | 32 | @EventHandler 33 | public void onEvent(PluginEnableEvent e){ 34 | if(config.isEventEnabled(e.getEventName())){ 35 | String[] array = {"event", e.getEventName()}; 36 | Main.doCommand(array, "WEBSEND_EVENTS_SERVER"); 37 | } 38 | } 39 | 40 | //@EventHandler 41 | public void onEvent(PluginEvent e){ 42 | if(config.isEventEnabled(e.getEventName())){ 43 | String[] array = {"event", e.getEventName()}; 44 | Main.doCommand(array, "WEBSEND_EVENTS_SERVER"); 45 | } 46 | } 47 | 48 | @EventHandler 49 | public void onEvent(RemoteServerCommandEvent e){ 50 | if(config.isEventEnabled(e.getEventName())){ 51 | String[] array = {"event", e.getEventName()}; 52 | Main.doCommand(array, "WEBSEND_EVENTS_SERVER"); 53 | } 54 | } 55 | 56 | @EventHandler 57 | public void onEvent(ServerCommandEvent e){ 58 | System.out.println(e.getEventName()); 59 | if(config.isEventEnabled(e.getEventName())){ 60 | System.out.println("ServerCommandEvent happened!"); 61 | String[] array = {"event", e.getEventName()}; 62 | Main.doCommand(array, "WEBSEND_EVENTS_SERVER"); 63 | } 64 | } 65 | 66 | @EventHandler 67 | public void onEvent(ServerListPingEvent e){ 68 | if(config.isEventEnabled(e.getEventName())){ 69 | String[] array = {"event", e.getEventName()}; 70 | Main.doCommand(array, "WEBSEND_EVENTS_SERVER"); 71 | } 72 | } 73 | 74 | @EventHandler 75 | public void onEvent(ServiceRegisterEvent e){ 76 | if(config.isEventEnabled(e.getEventName())){ 77 | String[] array = {"event", e.getEventName()}; 78 | Main.doCommand(array, "WEBSEND_EVENTS_SERVER"); 79 | } 80 | } 81 | 82 | @EventHandler 83 | public void onEvent(ServiceUnregisterEvent e){ 84 | if(config.isEventEnabled(e.getEventName())){ 85 | String[] array = {"event", e.getEventName()}; 86 | Main.doCommand(array, "WEBSEND_EVENTS_SERVER"); 87 | } 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /src/main/java/com/github/websend/events/listener/WorldListener.java: -------------------------------------------------------------------------------- 1 | package com.github.websend.events.listener; 2 | 3 | import com.github.websend.Main; 4 | import com.github.websend.events.configuration.WorldEventsConfiguration; 5 | import org.bukkit.event.EventHandler; 6 | import org.bukkit.event.Listener; 7 | import org.bukkit.event.world.*; 8 | 9 | public class WorldListener implements Listener{ 10 | WorldEventsConfiguration config = null; 11 | 12 | public WorldListener(WorldEventsConfiguration config) { 13 | this.config = config; 14 | } 15 | 16 | @EventHandler 17 | public void onEvent(ChunkLoadEvent e){ 18 | if(config.isEventEnabled(e.getEventName())){ 19 | String[] array = {"event", e.getEventName()}; 20 | Main.doCommand(array, "WEBSEND_EVENTS_WORLD"); 21 | } 22 | } 23 | 24 | @EventHandler 25 | public void onEvent(ChunkPopulateEvent e){ 26 | if(config.isEventEnabled(e.getEventName())){ 27 | String[] array = {"event", e.getEventName()}; 28 | Main.doCommand(array, "WEBSEND_EVENTS_WORLD"); 29 | } 30 | } 31 | 32 | @EventHandler 33 | public void onEvent(ChunkUnloadEvent e){ 34 | if(config.isEventEnabled(e.getEventName())){ 35 | String[] array = {"event", e.getEventName()}; 36 | Main.doCommand(array, "WEBSEND_EVENTS_WORLD"); 37 | } 38 | } 39 | 40 | @EventHandler 41 | public void onEvent(PortalCreateEvent e){ 42 | if(config.isEventEnabled(e.getEventName())){ 43 | String[] array = {"event", e.getEventName()}; 44 | Main.doCommand(array, "WEBSEND_EVENTS_WORLD"); 45 | } 46 | } 47 | 48 | @EventHandler 49 | public void onEvent(SpawnChangeEvent e){ 50 | if(config.isEventEnabled(e.getEventName())){ 51 | String[] array = {"event", e.getEventName()}; 52 | Main.doCommand(array, "WEBSEND_EVENTS_WORLD"); 53 | } 54 | } 55 | 56 | @EventHandler 57 | public void onEvent(StructureGrowEvent e){ 58 | if(config.isEventEnabled(e.getEventName())){ 59 | String[] array = {"event", e.getEventName()}; 60 | Main.doCommand(array, "WEBSEND_EVENTS_WORLD"); 61 | } 62 | } 63 | 64 | @EventHandler 65 | public void onEvent(WorldInitEvent e){ 66 | if(config.isEventEnabled(e.getEventName())){ 67 | String[] array = {"event", e.getEventName()}; 68 | Main.doCommand(array, "WEBSEND_EVENTS_WORLD"); 69 | } 70 | } 71 | 72 | @EventHandler 73 | public void onEvent(WorldLoadEvent e){ 74 | if(config.isEventEnabled(e.getEventName())){ 75 | String[] array = {"event", e.getEventName()}; 76 | Main.doCommand(array, "WEBSEND_EVENTS_WORLD"); 77 | } 78 | } 79 | 80 | @EventHandler 81 | public void onEvent(WorldSaveEvent e){ 82 | if(config.isEventEnabled(e.getEventName())){ 83 | String[] array = {"event", e.getEventName()}; 84 | Main.doCommand(array, "WEBSEND_EVENTS_WORLD"); 85 | } 86 | } 87 | 88 | @EventHandler 89 | public void onEvent(WorldUnloadEvent e){ 90 | if(config.isEventEnabled(e.getEventName())){ 91 | String[] array = {"event", e.getEventName()}; 92 | Main.doCommand(array, "WEBSEND_EVENTS_WORLD"); 93 | } 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/main/java/com/github/websend/events/listener/VehicleListener.java: -------------------------------------------------------------------------------- 1 | package com.github.websend.events.listener; 2 | 3 | import com.github.websend.Main; 4 | import com.github.websend.events.configuration.VehicleEventsConfiguration; 5 | import org.bukkit.event.EventHandler; 6 | import org.bukkit.event.Listener; 7 | import org.bukkit.event.vehicle.*; 8 | 9 | public class VehicleListener implements Listener{ 10 | VehicleEventsConfiguration config = null; 11 | 12 | public VehicleListener(VehicleEventsConfiguration config) { 13 | this.config = config; 14 | } 15 | 16 | @EventHandler 17 | public void onEvent(VehicleBlockCollisionEvent e){ 18 | if(config.isEventEnabled(e.getEventName())){ 19 | String[] array = {"event", e.getEventName()}; 20 | Main.doCommand(array, "WEBSEND_EVENTS_VEHICLE"); 21 | } 22 | } 23 | 24 | //@EventHandler 25 | public void onEvent(VehicleCollisionEvent e){ 26 | if(config.isEventEnabled(e.getEventName())){ 27 | String[] array = {"event", e.getEventName()}; 28 | Main.doCommand(array, "WEBSEND_EVENTS_VEHICLE"); 29 | } 30 | } 31 | 32 | @EventHandler 33 | public void onEvent(VehicleCreateEvent e){ 34 | if(config.isEventEnabled(e.getEventName())){ 35 | String[] array = {"event", e.getEventName()}; 36 | Main.doCommand(array, "WEBSEND_EVENTS_VEHICLE"); 37 | } 38 | } 39 | 40 | @EventHandler 41 | public void onEvent(VehicleDamageEvent e){ 42 | if(config.isEventEnabled(e.getEventName())){ 43 | String[] array = {"event", e.getEventName()}; 44 | Main.doCommand(array, "WEBSEND_EVENTS_VEHICLE"); 45 | } 46 | } 47 | 48 | @EventHandler 49 | public void onEvent(VehicleDestroyEvent e){ 50 | if(config.isEventEnabled(e.getEventName())){ 51 | String[] array = {"event", e.getEventName()}; 52 | Main.doCommand(array, "WEBSEND_EVENTS_VEHICLE"); 53 | } 54 | } 55 | 56 | @EventHandler 57 | public void onEvent(VehicleEnterEvent e){ 58 | if(config.isEventEnabled(e.getEventName())){ 59 | String[] array = {"event", e.getEventName()}; 60 | Main.doCommand(array, "WEBSEND_EVENTS_VEHICLE"); 61 | } 62 | } 63 | 64 | @EventHandler 65 | public void onEvent(VehicleEntityCollisionEvent e){ 66 | if(config.isEventEnabled(e.getEventName())){ 67 | String[] array = {"event", e.getEventName()}; 68 | Main.doCommand(array, "WEBSEND_EVENTS_VEHICLE"); 69 | } 70 | } 71 | 72 | @EventHandler 73 | public void onEvent(VehicleExitEvent e){ 74 | if(config.isEventEnabled(e.getEventName())){ 75 | String[] array = {"event", e.getEventName()}; 76 | Main.doCommand(array, "WEBSEND_EVENTS_VEHICLE"); 77 | } 78 | } 79 | 80 | @EventHandler 81 | public void onEvent(VehicleMoveEvent e){ 82 | if(config.isEventEnabled(e.getEventName())){ 83 | String[] array = {"event", e.getEventName()}; 84 | Main.doCommand(array, "WEBSEND_EVENTS_VEHICLE"); 85 | } 86 | } 87 | 88 | @EventHandler 89 | public void onEvent(VehicleUpdateEvent e){ 90 | if(config.isEventEnabled(e.getEventName())){ 91 | String[] array = {"event", e.getEventName()}; 92 | Main.doCommand(array, "WEBSEND_EVENTS_VEHICLE"); 93 | } 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/main/java/com/github/websend/Settings.java: -------------------------------------------------------------------------------- 1 | package com.github.websend; 2 | 3 | import java.net.InetAddress; 4 | import java.net.URL; 5 | 6 | public class Settings { 7 | 8 | private String responseURL; 9 | private String password; 10 | private String salt = ""; 11 | private String algorithm = "SHA-512"; 12 | private int port = 4445; 13 | private boolean debugMode = false; 14 | private boolean gzipRequests = false; 15 | private boolean serverActive = false; 16 | private URL URL; 17 | private InetAddress serverBindIP = null; 18 | private boolean wrapCommandExecutor; 19 | private boolean sslEnabled = false; 20 | private String sslPassword = null; 21 | private boolean extendedPlayerDataEnabled; 22 | 23 | public URL getURL() { 24 | return URL; 25 | } 26 | 27 | public boolean isDebugMode() { 28 | return debugMode; 29 | } 30 | 31 | public String getPassword() { 32 | return password; 33 | } 34 | 35 | public int getPort() { 36 | return port; 37 | } 38 | 39 | public String getResponseURL() { 40 | return responseURL; 41 | } 42 | 43 | public String getSalt() { 44 | return salt; 45 | } 46 | 47 | public String getHashingAlgorithm() { 48 | return this.algorithm; 49 | } 50 | 51 | public boolean isServerActive() { 52 | return serverActive; 53 | } 54 | 55 | public InetAddress getServerBindIP() { 56 | return serverBindIP; 57 | } 58 | 59 | public void setURL(URL URL) { 60 | this.URL = URL; 61 | } 62 | 63 | public void setDebugMode(boolean debugMode) { 64 | this.debugMode = debugMode; 65 | } 66 | 67 | public void setPassword(String password) { 68 | this.password = password; 69 | } 70 | 71 | public void setPort(int port) { 72 | this.port = port; 73 | } 74 | 75 | public void setResponseURL(String responseURL) { 76 | this.responseURL = responseURL; 77 | } 78 | 79 | public void setSalt(String salt) { 80 | this.salt = salt; 81 | } 82 | 83 | public void setServerActive(boolean serverActive) { 84 | this.serverActive = serverActive; 85 | } 86 | 87 | public void setHashingAlgorithm(String algorithm) { 88 | this.algorithm = algorithm; 89 | } 90 | 91 | public boolean areRequestsGZipped() { 92 | return gzipRequests; 93 | } 94 | 95 | public void setGzipRequests(boolean gzipRequests) { 96 | this.gzipRequests = gzipRequests; 97 | } 98 | 99 | public void setServerBindIP(InetAddress ip) { 100 | this.serverBindIP = ip; 101 | } 102 | 103 | public boolean areCommandExecutorsWrapped() { 104 | return wrapCommandExecutor; 105 | } 106 | 107 | public void setWrapCommandExecutor(boolean b) { 108 | this.wrapCommandExecutor = b; 109 | } 110 | 111 | public boolean isSSLEnabled() { 112 | return sslEnabled; 113 | } 114 | 115 | public void setSSLEnabled(boolean sslEnabled) { 116 | this.sslEnabled = sslEnabled; 117 | } 118 | 119 | public boolean isExtendedPlayerDataEnabled() { 120 | return extendedPlayerDataEnabled; 121 | } 122 | 123 | public void setExtendedPlayerDataEnabled(boolean enabled){ 124 | this.extendedPlayerDataEnabled = enabled; 125 | } 126 | public String getSSLPassword() { 127 | return this.sslPassword; 128 | } 129 | 130 | public void setSslPassword(String sslPassword) { 131 | this.sslPassword = sslPassword; 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | com.github.websend 5 | Websend 6 | 5.8 7 | jar 8 | 9 | 21 10 | 21 11 | UTF-8 12 | 13 | 14 | 15 | spigot-repo 16 | https://hub.spigotmc.org/nexus/content/repositories/snapshots/ 17 | 18 | 19 | github.com 20 | https://github.com/ 21 | 22 | 23 | minecraft-libraries 24 | Minecraft Libraries 25 | https://libraries.minecraft.net 26 | 27 | 28 | 29 | 30 | commons-logging 31 | commons-logging 32 | 1.2 33 | api 34 | 35 | 36 | org.json 37 | json 38 | 20250107 39 | 40 | 41 | junit 42 | junit 43 | 4.13.1 44 | test 45 | jar 46 | 47 | 48 | org.spigotmc 49 | spigot-api 50 | 1.21.4-R0.1-SNAPSHOT 51 | provided 52 | 53 | 54 | com.mojang 55 | brigadier 56 | 1.0.18 57 | 58 | 59 | com.google.code.gson 60 | gson 61 | 2.11.0 62 | 63 | 64 | net.forthecrown 65 | PaperNBT 66 | 1.0.0 67 | pom 68 | 69 | 70 | org.apache.httpcomponents.client5 71 | httpclient5 72 | 5.4.3 73 | jar 74 | 75 | 76 | 77 | 78 | 79 | org.apache.maven.plugins 80 | maven-shade-plugin 81 | 3.2.1 82 | 83 | Websend-shaded-${version} 84 | 85 | 86 | 87 | 88 | 89 | package 90 | 91 | shade 92 | 93 | 94 | 95 | 96 | 97 | 98 | -------------------------------------------------------------------------------- /src/main/java/com/github/websend/PluginOutputManager.java: -------------------------------------------------------------------------------- 1 | package com.github.websend; 2 | 3 | import java.io.PrintStream; 4 | import java.util.ArrayList; 5 | import java.util.HashMap; 6 | import java.util.logging.Handler; 7 | import java.util.logging.LogRecord; 8 | import java.util.logging.Logger; 9 | import org.bukkit.Bukkit; 10 | import org.bukkit.plugin.Plugin; 11 | 12 | public class PluginOutputManager { 13 | 14 | private static HashMap> pluginOutputHashMap = new HashMap>(); 15 | private static boolean handlersRegistered = false; 16 | 17 | public static void registerPluginLoggerHandlers() { 18 | Plugin[] plugins = Bukkit.getPluginManager().getPlugins(); 19 | for (Plugin plugin : plugins) { 20 | plugin.getLogger().addHandler(new WebsendPluginLoggerHandler(plugin)); 21 | } 22 | } 23 | 24 | public static void startRecording(String pluginName) { 25 | Main.logDebugInfo("Starting output recording of plugin " + pluginName); 26 | 27 | //register handlers on first use to prevent missing any plugin on load. 28 | if (!handlersRegistered) { 29 | PluginOutputManager.registerPluginLoggerHandlers(); 30 | handlersRegistered = true; 31 | } 32 | pluginOutputHashMap.put(pluginName, new ArrayList()); 33 | } 34 | 35 | public static ArrayList stopRecording(String pluginName) { 36 | ArrayList result = pluginOutputHashMap.get(pluginName); 37 | Main.logDebugInfo("Stopping output recording of plugin " + pluginName); 38 | Main.logDebugInfo("Recorded " + result.size() + " entries."); 39 | pluginOutputHashMap.remove(pluginName); 40 | return result; 41 | } 42 | 43 | public static void handleLogRecord(Plugin plugin, LogRecord logRecord) { 44 | if (pluginOutputHashMap.containsKey(plugin.getName())) { 45 | pluginOutputHashMap.get(plugin.getName()).add(logRecord.getMessage()); 46 | } 47 | } 48 | 49 | // unused useful functions 50 | public static void hijackSystemOutputStream() { 51 | PrintStream newOutput = new PrintStream(System.out) { 52 | @Override 53 | public void println(String x) { 54 | Throwable t = new Throwable(); 55 | super.println("Class " + t.getStackTrace()[1].getClassName() + " says: " + x); 56 | } 57 | }; 58 | System.setOut(newOutput); 59 | } 60 | 61 | public static void hijackLogger(String loggerName) { 62 | Handler handler = new Handler() { 63 | @Override 64 | public void publish(LogRecord record) { 65 | record.setMessage("Class " + record.getSourceClassName() + " says: " + record.getMessage()); 66 | } 67 | 68 | @Override 69 | public void flush() { 70 | } 71 | 72 | @Override 73 | public void close() throws SecurityException { 74 | } 75 | }; 76 | 77 | // May give problems with openJDK 78 | Logger.getLogger(loggerName).addHandler(handler); 79 | } 80 | } 81 | 82 | class WebsendPluginLoggerHandler extends Handler { 83 | 84 | Plugin plugin; 85 | 86 | WebsendPluginLoggerHandler(Plugin plugin) { 87 | this.plugin = plugin; 88 | Main.logDebugInfo("Tapped into: " + plugin.getName()); 89 | } 90 | 91 | @Override 92 | public void publish(LogRecord record) { 93 | PluginOutputManager.handleLogRecord(plugin, record); 94 | Main.logDebugInfo("Catched log record from " + plugin.getName()); 95 | } 96 | 97 | @Override 98 | public void flush() { 99 | } 100 | 101 | @Override 102 | public void close() throws SecurityException { 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /src/main/java/com/github/websend/JSONSerializer.java: -------------------------------------------------------------------------------- 1 | package com.github.websend; 2 | 3 | import com.github.websend.spigot.SpigotJSONSerializer; 4 | import com.mojang.brigadier.exceptions.CommandSyntaxException; 5 | import org.bukkit.Location; 6 | import org.bukkit.entity.Player; 7 | import org.bukkit.inventory.Inventory; 8 | import org.bukkit.inventory.ItemStack; 9 | import org.json.JSONArray; 10 | import org.json.JSONException; 11 | import org.json.JSONObject; 12 | import java.util.Map; 13 | 14 | public abstract class JSONSerializer { 15 | private static JSONSerializer instance = null; 16 | 17 | public static JSONSerializer getInstance(){ 18 | if(instance == null){ 19 | instance = new SpigotJSONSerializer(); 20 | } 21 | return instance; 22 | } 23 | 24 | public JSONObject serializePlayer(Player ply, boolean serializeAllData) throws JSONException, CommandSyntaxException { 25 | JSONObject player = new JSONObject(); 26 | { 27 | player.put("Name", ply.getName()); 28 | player.put("UUID", ply.getUniqueId()); 29 | player.put("UUIDVersion", ply.getUniqueId().version()); 30 | player.put("XP", ply.getExp()); 31 | player.put("XPLevel", ply.getLevel()); 32 | player.put("Exhaustion", ply.getExhaustion()); 33 | player.put("FoodLevel", ply.getFoodLevel()); 34 | player.put("GameMode", ply.getGameMode()); 35 | player.put("Health", ply.getHealth()); 36 | player.put("IP", ply.getAddress().toString()); 37 | player.put("IsOP", ply.isOp()); 38 | if(serializeAllData){ 39 | player.put("CurrentItemIndex", ply.getInventory().getHeldItemSlot()); 40 | player.put("MainHandItemID", ply.getInventory().getItemInMainHand().getType().name()); 41 | player.put("OffHandItemID", ply.getInventory().getItemInOffHand().getType().name()); 42 | JSONObject location = serializeLocation(ply.getLocation()); 43 | player.put("Location", location); 44 | JSONArray inventory = serializeInventory(ply.getInventory()); 45 | player.put("Inventory", inventory); 46 | } 47 | } 48 | return player; 49 | } 50 | 51 | public JSONObject serializeLocation(Location loc) throws JSONException { 52 | JSONObject location = new JSONObject(); 53 | { 54 | location.put("X", loc.getX()); 55 | location.put("Y", loc.getY()); 56 | location.put("Z", loc.getZ()); 57 | location.put("Yaw", loc.getYaw()); 58 | location.put("Pitch", loc.getPitch()); 59 | location.put("World", loc.getWorld().getName()); 60 | } 61 | return location; 62 | } 63 | 64 | public JSONArray serializeInventory(Inventory inv) throws JSONException, CommandSyntaxException { 65 | JSONArray inventory = new JSONArray(); { 66 | for (int i = 0; i < inv.getSize(); i++) { 67 | ItemStack itemStack = inv.getItem(i); 68 | if (itemStack != null) { 69 | JSONObject item = new JSONObject(); 70 | item.put("Slot", i); 71 | item.put("TypeName", itemStack.getType().name()); 72 | item.put("Amount", itemStack.getAmount()); 73 | if (itemStack.hasItemMeta()) { 74 | item.put("ComponentString", itemStack.getItemMeta().getAsComponentString()); 75 | 76 | 77 | Map serialMeta; 78 | serialMeta = itemStack.getItemMeta().serialize(); 79 | String json2 = serialMeta.toString(); 80 | item.put("nbt_serialMeta_to_string", json2); 81 | } 82 | 83 | inventory.put(item); 84 | } 85 | } 86 | } 87 | return inventory; 88 | } 89 | } -------------------------------------------------------------------------------- /src/main/java/com/github/websend/events/Main.java: -------------------------------------------------------------------------------- 1 | package com.github.websend.events; 2 | 3 | import com.github.websend.events.configuration.*; 4 | import com.github.websend.events.listener.*; 5 | import java.lang.reflect.Constructor; 6 | import java.lang.reflect.InvocationTargetException; 7 | import java.util.logging.Level; 8 | import org.bukkit.event.Listener; 9 | import org.bukkit.plugin.java.JavaPlugin; 10 | 11 | 12 | public class Main extends JavaPlugin{ 13 | private static Main instance; 14 | 15 | @Override 16 | public void onEnable(){ 17 | instance = this; 18 | int loaded = registerListeners(); 19 | this.getLogger().info("Enabled "+loaded+" event listening classes."); 20 | } 21 | 22 | @Override 23 | public void onDisable(){ 24 | 25 | } 26 | 27 | public static Main getInstance() { 28 | return instance; 29 | } 30 | 31 | private int registerListeners(){ 32 | //Ugly, but the most clean and balanced approach I can come up with... 33 | int loadedAmount = 0; 34 | 35 | loadedAmount += loadEventHandler(BlockEventsConfiguration.class, BlockListener.class) ? 1 : 0; 36 | loadedAmount += loadEventHandler(EnchantmentEventsConfiguration.class, EnchantmentListener.class) ? 1 : 0; 37 | loadedAmount += loadEventHandler(EntityEventsConfiguration.class, EntityListener.class) ? 1 : 0; 38 | loadedAmount += loadEventHandler(HangingEventsConfiguration.class, HangingListener.class) ? 1 : 0; 39 | loadedAmount += loadEventHandler(InventoryEventsConfiguration.class, InventoryListener.class) ? 1 : 0; 40 | loadedAmount += loadEventHandler(PlayerEventsConfiguration.class, PlayerListener.class) ? 1 : 0; 41 | loadedAmount += loadEventHandler(ServerEventsConfiguration.class, ServerListener.class) ? 1 : 0; 42 | loadedAmount += loadEventHandler(VehicleEventsConfiguration.class, VehicleListener.class) ? 1 : 0; 43 | loadedAmount += loadEventHandler(WeatherEventsConfiguration.class, WeatherListener.class) ? 1 : 0; 44 | loadedAmount += loadEventHandler(WorldEventsConfiguration.class, WorldListener.class) ? 1 : 0; 45 | loadedAmount += loadEventHandler(AdvancementEventsConfiguration.class, AdvancementsListener.class) ? 1 : 0; 46 | 47 | return loadedAmount; 48 | } 49 | 50 | public boolean loadEventHandler(Class> configClass, Class listenerClass){ 51 | Configuration config = null; 52 | try { 53 | config = configClass.newInstance(); 54 | config.loadConfiguration(); 55 | if(!config.hasActiveEvent()){ 56 | return false; 57 | } 58 | } catch (Exception ex) { 59 | String type = config == null ? "null" : config.getFilename(); 60 | this.getLogger().log(Level.SEVERE, "Failed to load the events config file "+type+".", ex); 61 | } 62 | 63 | T listener = null; 64 | try { 65 | Constructor constructor = listenerClass.getConstructor(configClass); 66 | listener = constructor.newInstance(config); 67 | } catch (SecurityException | NoSuchMethodException | InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) { 68 | this.getLogger().log(Level.SEVERE, "Failed to instanciate "+listenerClass.getName(), ex); 69 | } 70 | 71 | if(listener == null){ 72 | this.getLogger().log(Level.SEVERE, "No valid constructor found for "+listenerClass.getName()); 73 | return false; 74 | } 75 | 76 | try { 77 | config.initialize(); 78 | this.getServer().getPluginManager().registerEvents(listener, this); 79 | return true; 80 | } catch (Exception ex) { 81 | this.getLogger().log(Level.SEVERE, "Failed to load the events config file "+config.getFilename()+".", ex); 82 | } 83 | return false; 84 | } 85 | } -------------------------------------------------------------------------------- /src/main/java/com/github/websend/events/listener/InventoryListener.java: -------------------------------------------------------------------------------- 1 | package com.github.websend.events.listener; 2 | 3 | import com.github.websend.Main; 4 | import com.github.websend.events.configuration.InventoryEventsConfiguration; 5 | import org.bukkit.event.EventHandler; 6 | import org.bukkit.event.Listener; 7 | import org.bukkit.event.inventory.*; 8 | 9 | public class InventoryListener implements Listener{ 10 | InventoryEventsConfiguration config = null; 11 | 12 | public InventoryListener(InventoryEventsConfiguration config) { 13 | this.config = config; 14 | } 15 | 16 | @EventHandler 17 | public void onEvent(BrewEvent e){ 18 | if(config.isEventEnabled(e.getEventName())){ 19 | String[] array = {"event", e.getEventName()}; 20 | Main.doCommand(array, "WEBSEND_EVENTS_INVENTORY"); 21 | } 22 | } 23 | 24 | @EventHandler 25 | public void onEvent(CraftItemEvent e){ 26 | if(config.isEventEnabled(e.getEventName())){ 27 | String[] array = {"event", e.getEventName()}; 28 | Main.doCommand(array, "WEBSEND_EVENTS_INVENTORY"); 29 | } 30 | } 31 | 32 | @EventHandler 33 | public void onEvent(FurnaceBurnEvent e){ 34 | if(config.isEventEnabled(e.getEventName())){ 35 | String[] array = {"event", e.getEventName()}; 36 | Main.doCommand(array, "WEBSEND_EVENTS_INVENTORY"); 37 | } 38 | } 39 | 40 | @EventHandler 41 | public void onEvent(FurnaceExtractEvent e){ 42 | if(config.isEventEnabled(e.getEventName())){ 43 | String[] array = {"event", e.getEventName()}; 44 | Main.doCommand(array, "WEBSEND_EVENTS_INVENTORY"); 45 | } 46 | } 47 | 48 | @EventHandler 49 | public void onEvent(FurnaceSmeltEvent e){ 50 | if(config.isEventEnabled(e.getEventName())){ 51 | String[] array = {"event", e.getEventName()}; 52 | Main.doCommand(array, "WEBSEND_EVENTS_INVENTORY"); 53 | } 54 | } 55 | 56 | @EventHandler 57 | public void onEvent(InventoryClickEvent e){ 58 | if(config.isEventEnabled(e.getEventName())){ 59 | String[] array = {"event", e.getEventName()}; 60 | Main.doCommand(array, "WEBSEND_EVENTS_INVENTORY"); 61 | } 62 | } 63 | 64 | @EventHandler 65 | public void onEvent(InventoryCloseEvent e){ 66 | if(config.isEventEnabled(e.getEventName())){ 67 | String[] array = {"event", e.getEventName()}; 68 | Main.doCommand(array, "WEBSEND_EVENTS_INVENTORY"); 69 | } 70 | } 71 | 72 | @EventHandler 73 | public void onEvent(InventoryCreativeEvent e){ 74 | if(config.isEventEnabled(e.getEventName())){ 75 | String[] array = {"event", e.getEventName()}; 76 | Main.doCommand(array, "WEBSEND_EVENTS_INVENTORY"); 77 | } 78 | } 79 | 80 | @EventHandler 81 | public void onEvent(InventoryDragEvent e){ 82 | if(config.isEventEnabled(e.getEventName())){ 83 | String[] array = {"event", e.getEventName()}; 84 | Main.doCommand(array, "WEBSEND_EVENTS_INVENTORY"); 85 | } 86 | } 87 | 88 | @EventHandler 89 | public void onEvent(InventoryInteractEvent e){ 90 | if(config.isEventEnabled(e.getEventName())){ 91 | String[] array = {"event", e.getEventName()}; 92 | Main.doCommand(array, "WEBSEND_EVENTS_INVENTORY"); 93 | } 94 | } 95 | 96 | @EventHandler 97 | public void onEvent(InventoryMoveItemEvent e){ 98 | if(config.isEventEnabled(e.getEventName())){ 99 | String[] array = {"event", e.getEventName()}; 100 | Main.doCommand(array, "WEBSEND_EVENTS_INVENTORY"); 101 | } 102 | } 103 | 104 | @EventHandler 105 | public void onEvent(InventoryOpenEvent e){ 106 | if(config.isEventEnabled(e.getEventName())){ 107 | String[] array = {"event", e.getEventName()}; 108 | Main.doCommand(array, "WEBSEND_EVENTS_INVENTORY"); 109 | } 110 | } 111 | 112 | @EventHandler 113 | public void onEvent(InventoryPickupItemEvent e){ 114 | if(config.isEventEnabled(e.getEventName())){ 115 | String[] array = {"event", e.getEventName()}; 116 | Main.doCommand(array, "WEBSEND_EVENTS_INVENTORY"); 117 | } 118 | } 119 | 120 | @EventHandler 121 | public void onEvent(PrepareAnvilEvent e){ 122 | if(config.isEventEnabled(e.getEventName())){ 123 | String[] array = {"event", e.getEventName()}; 124 | Main.doCommand(array, "WEBSEND_EVENTS_INVENTORY"); 125 | } 126 | } 127 | 128 | @EventHandler 129 | public void onEvent(PrepareItemCraftEvent e){ 130 | if(config.isEventEnabled(e.getEventName())){ 131 | String[] array = {"event", e.getEventName()}; 132 | Main.doCommand(array, "WEBSEND_EVENTS_INVENTORY"); 133 | } 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /src/main/java/com/github/websend/WebsendConsoleCommandSender.java: -------------------------------------------------------------------------------- 1 | package com.github.websend; 2 | 3 | import java.util.Set; 4 | import java.util.UUID; 5 | import java.util.logging.Level; 6 | import java.util.logging.LogRecord; 7 | import org.bukkit.Server; 8 | import org.bukkit.command.ConsoleCommandSender; 9 | import org.bukkit.conversations.Conversation; 10 | import org.bukkit.conversations.ConversationAbandonedEvent; 11 | import org.bukkit.permissions.Permission; 12 | import org.bukkit.permissions.PermissionAttachment; 13 | import org.bukkit.permissions.PermissionAttachmentInfo; 14 | import org.bukkit.plugin.Plugin; 15 | 16 | public class WebsendConsoleCommandSender implements ConsoleCommandSender { 17 | /* This class allows tapping into command output from plugins 18 | * if the output is sent through the commandsender. 19 | * 20 | * Tap this method(1.6.4): sendRawMessage, sendMessage(String), sendMessage(String[]) 21 | */ 22 | 23 | private final ConsoleCommandSender parent; 24 | private final Plugin commandTargetPlugin; 25 | 26 | public WebsendConsoleCommandSender(ConsoleCommandSender parent, Plugin commandTargetPlugin) { 27 | this.parent = parent; 28 | this.commandTargetPlugin = commandTargetPlugin; 29 | } 30 | 31 | @Override 32 | public void sendMessage(java.lang.String param0) { 33 | PluginOutputManager.handleLogRecord(commandTargetPlugin, new LogRecord(Level.INFO, param0)); 34 | parent.sendMessage(param0); 35 | } 36 | 37 | @Override 38 | public void sendMessage(java.lang.String[] param0) { 39 | for (String str : param0) { 40 | PluginOutputManager.handleLogRecord(commandTargetPlugin, new LogRecord(Level.INFO, str)); 41 | } 42 | parent.sendMessage(param0); 43 | } 44 | 45 | @Override 46 | public void sendRawMessage(java.lang.String param0) { 47 | PluginOutputManager.handleLogRecord(commandTargetPlugin, new LogRecord(Level.INFO, param0)); 48 | parent.sendRawMessage(param0); 49 | } 50 | 51 | @Override 52 | public Server getServer() { 53 | return parent.getServer(); 54 | } 55 | 56 | @Override 57 | public String getName() { 58 | return parent.getName(); 59 | } 60 | 61 | @Override 62 | public boolean isPermissionSet(String string) { 63 | return parent.isPermissionSet(string); 64 | } 65 | 66 | @Override 67 | public boolean isPermissionSet(Permission prmsn) { 68 | return parent.isPermissionSet(prmsn); 69 | } 70 | 71 | @Override 72 | public boolean hasPermission(String string) { 73 | return parent.hasPermission(string); 74 | } 75 | 76 | @Override 77 | public boolean hasPermission(Permission prmsn) { 78 | return parent.hasPermission(prmsn); 79 | } 80 | 81 | @Override 82 | public PermissionAttachment addAttachment(Plugin plugin, String string, boolean bln) { 83 | return parent.addAttachment(plugin, string, bln); 84 | } 85 | 86 | @Override 87 | public PermissionAttachment addAttachment(Plugin plugin) { 88 | return parent.addAttachment(plugin); 89 | } 90 | 91 | @Override 92 | public PermissionAttachment addAttachment(Plugin plugin, String string, boolean bln, int i) { 93 | return parent.addAttachment(plugin, string, bln, i); 94 | } 95 | 96 | @Override 97 | public PermissionAttachment addAttachment(Plugin plugin, int i) { 98 | return parent.addAttachment(plugin, i); 99 | } 100 | 101 | @Override 102 | public void removeAttachment(PermissionAttachment pa) { 103 | parent.removeAttachment(pa); 104 | } 105 | 106 | @Override 107 | public void recalculatePermissions() { 108 | parent.recalculatePermissions(); 109 | } 110 | 111 | @Override 112 | public Set getEffectivePermissions() { 113 | return parent.getEffectivePermissions(); 114 | } 115 | 116 | @Override 117 | public boolean isOp() { 118 | return parent.isOp(); 119 | } 120 | 121 | @Override 122 | public void setOp(boolean bln) { 123 | parent.setOp(bln); 124 | } 125 | 126 | @Override 127 | public boolean isConversing() { 128 | return parent.isConversing(); 129 | } 130 | 131 | @Override 132 | public void acceptConversationInput(String string) { 133 | parent.acceptConversationInput(string); 134 | } 135 | 136 | @Override 137 | public boolean beginConversation(Conversation c) { 138 | return parent.beginConversation(c); 139 | } 140 | 141 | @Override 142 | public void abandonConversation(Conversation c) { 143 | parent.abandonConversation(c); 144 | } 145 | 146 | @Override 147 | public void abandonConversation(Conversation c, ConversationAbandonedEvent cae) { 148 | parent.abandonConversation(c, cae); 149 | } 150 | 151 | @Override 152 | public Spigot spigot() { 153 | throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. 154 | } 155 | 156 | @Override 157 | public void sendMessage(UUID uuid, String string) { 158 | throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. 159 | } 160 | 161 | @Override 162 | public void sendMessage(UUID uuid, String[] strings) { 163 | throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. 164 | } 165 | 166 | @Override 167 | public void sendRawMessage(UUID uuid, String string) { 168 | throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. 169 | } 170 | } -------------------------------------------------------------------------------- /mvnw.cmd: -------------------------------------------------------------------------------- 1 | <# : batch portion 2 | @REM ---------------------------------------------------------------------------- 3 | @REM Licensed to the Apache Software Foundation (ASF) under one 4 | @REM or more contributor license agreements. See the NOTICE file 5 | @REM distributed with this work for additional information 6 | @REM regarding copyright ownership. The ASF licenses this file 7 | @REM to you under the Apache License, Version 2.0 (the 8 | @REM "License"); you may not use this file except in compliance 9 | @REM with the License. You may obtain a copy of the License at 10 | @REM 11 | @REM http://www.apache.org/licenses/LICENSE-2.0 12 | @REM 13 | @REM Unless required by applicable law or agreed to in writing, 14 | @REM software distributed under the License is distributed on an 15 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 | @REM KIND, either express or implied. See the License for the 17 | @REM specific language governing permissions and limitations 18 | @REM under the License. 19 | @REM ---------------------------------------------------------------------------- 20 | 21 | @REM ---------------------------------------------------------------------------- 22 | @REM Apache Maven Wrapper startup batch script, version 3.3.2 23 | @REM 24 | @REM Optional ENV vars 25 | @REM MVNW_REPOURL - repo url base for downloading maven distribution 26 | @REM MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven 27 | @REM MVNW_VERBOSE - true: enable verbose log; others: silence the output 28 | @REM ---------------------------------------------------------------------------- 29 | 30 | @IF "%__MVNW_ARG0_NAME__%"=="" (SET __MVNW_ARG0_NAME__=%~nx0) 31 | @SET __MVNW_CMD__= 32 | @SET __MVNW_ERROR__= 33 | @SET __MVNW_PSMODULEP_SAVE=%PSModulePath% 34 | @SET PSModulePath= 35 | @FOR /F "usebackq tokens=1* delims==" %%A IN (`powershell -noprofile "& {$scriptDir='%~dp0'; $script='%__MVNW_ARG0_NAME__%'; icm -ScriptBlock ([Scriptblock]::Create((Get-Content -Raw '%~f0'))) -NoNewScope}"`) DO @( 36 | IF "%%A"=="MVN_CMD" (set __MVNW_CMD__=%%B) ELSE IF "%%B"=="" (echo %%A) ELSE (echo %%A=%%B) 37 | ) 38 | @SET PSModulePath=%__MVNW_PSMODULEP_SAVE% 39 | @SET __MVNW_PSMODULEP_SAVE= 40 | @SET __MVNW_ARG0_NAME__= 41 | @SET MVNW_USERNAME= 42 | @SET MVNW_PASSWORD= 43 | @IF NOT "%__MVNW_CMD__%"=="" (%__MVNW_CMD__% %*) 44 | @echo Cannot start maven from wrapper >&2 && exit /b 1 45 | @GOTO :EOF 46 | : end batch / begin powershell #> 47 | 48 | $ErrorActionPreference = "Stop" 49 | if ($env:MVNW_VERBOSE -eq "true") { 50 | $VerbosePreference = "Continue" 51 | } 52 | 53 | # calculate distributionUrl, requires .mvn/wrapper/maven-wrapper.properties 54 | $distributionUrl = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionUrl 55 | if (!$distributionUrl) { 56 | Write-Error "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties" 57 | } 58 | 59 | switch -wildcard -casesensitive ( $($distributionUrl -replace '^.*/','') ) { 60 | "maven-mvnd-*" { 61 | $USE_MVND = $true 62 | $distributionUrl = $distributionUrl -replace '-bin\.[^.]*$',"-windows-amd64.zip" 63 | $MVN_CMD = "mvnd.cmd" 64 | break 65 | } 66 | default { 67 | $USE_MVND = $false 68 | $MVN_CMD = $script -replace '^mvnw','mvn' 69 | break 70 | } 71 | } 72 | 73 | # apply MVNW_REPOURL and calculate MAVEN_HOME 74 | # maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/ 75 | if ($env:MVNW_REPOURL) { 76 | $MVNW_REPO_PATTERN = if ($USE_MVND) { "/org/apache/maven/" } else { "/maven/mvnd/" } 77 | $distributionUrl = "$env:MVNW_REPOURL$MVNW_REPO_PATTERN$($distributionUrl -replace '^.*'+$MVNW_REPO_PATTERN,'')" 78 | } 79 | $distributionUrlName = $distributionUrl -replace '^.*/','' 80 | $distributionUrlNameMain = $distributionUrlName -replace '\.[^.]*$','' -replace '-bin$','' 81 | $MAVEN_HOME_PARENT = "$HOME/.m2/wrapper/dists/$distributionUrlNameMain" 82 | if ($env:MAVEN_USER_HOME) { 83 | $MAVEN_HOME_PARENT = "$env:MAVEN_USER_HOME/wrapper/dists/$distributionUrlNameMain" 84 | } 85 | $MAVEN_HOME_NAME = ([System.Security.Cryptography.MD5]::Create().ComputeHash([byte[]][char[]]$distributionUrl) | ForEach-Object {$_.ToString("x2")}) -join '' 86 | $MAVEN_HOME = "$MAVEN_HOME_PARENT/$MAVEN_HOME_NAME" 87 | 88 | if (Test-Path -Path "$MAVEN_HOME" -PathType Container) { 89 | Write-Verbose "found existing MAVEN_HOME at $MAVEN_HOME" 90 | Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD" 91 | exit $? 92 | } 93 | 94 | if (! $distributionUrlNameMain -or ($distributionUrlName -eq $distributionUrlNameMain)) { 95 | Write-Error "distributionUrl is not valid, must end with *-bin.zip, but found $distributionUrl" 96 | } 97 | 98 | # prepare tmp dir 99 | $TMP_DOWNLOAD_DIR_HOLDER = New-TemporaryFile 100 | $TMP_DOWNLOAD_DIR = New-Item -Itemtype Directory -Path "$TMP_DOWNLOAD_DIR_HOLDER.dir" 101 | $TMP_DOWNLOAD_DIR_HOLDER.Delete() | Out-Null 102 | trap { 103 | if ($TMP_DOWNLOAD_DIR.Exists) { 104 | try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null } 105 | catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" } 106 | } 107 | } 108 | 109 | New-Item -Itemtype Directory -Path "$MAVEN_HOME_PARENT" -Force | Out-Null 110 | 111 | # Download and Install Apache Maven 112 | Write-Verbose "Couldn't find MAVEN_HOME, downloading and installing it ..." 113 | Write-Verbose "Downloading from: $distributionUrl" 114 | Write-Verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName" 115 | 116 | $webclient = New-Object System.Net.WebClient 117 | if ($env:MVNW_USERNAME -and $env:MVNW_PASSWORD) { 118 | $webclient.Credentials = New-Object System.Net.NetworkCredential($env:MVNW_USERNAME, $env:MVNW_PASSWORD) 119 | } 120 | [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 121 | $webclient.DownloadFile($distributionUrl, "$TMP_DOWNLOAD_DIR/$distributionUrlName") | Out-Null 122 | 123 | # If specified, validate the SHA-256 sum of the Maven distribution zip file 124 | $distributionSha256Sum = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionSha256Sum 125 | if ($distributionSha256Sum) { 126 | if ($USE_MVND) { 127 | Write-Error "Checksum validation is not supported for maven-mvnd. `nPlease disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." 128 | } 129 | Import-Module $PSHOME\Modules\Microsoft.PowerShell.Utility -Function Get-FileHash 130 | if ((Get-FileHash "$TMP_DOWNLOAD_DIR/$distributionUrlName" -Algorithm SHA256).Hash.ToLower() -ne $distributionSha256Sum) { 131 | Write-Error "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised. If you updated your Maven version, you need to update the specified distributionSha256Sum property." 132 | } 133 | } 134 | 135 | # unzip and move 136 | Expand-Archive "$TMP_DOWNLOAD_DIR/$distributionUrlName" -DestinationPath "$TMP_DOWNLOAD_DIR" | Out-Null 137 | Rename-Item -Path "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" -NewName $MAVEN_HOME_NAME | Out-Null 138 | try { 139 | Move-Item -Path "$TMP_DOWNLOAD_DIR/$MAVEN_HOME_NAME" -Destination $MAVEN_HOME_PARENT | Out-Null 140 | } catch { 141 | if (! (Test-Path -Path "$MAVEN_HOME" -PathType Container)) { 142 | Write-Error "fail to move MAVEN_HOME" 143 | } 144 | } finally { 145 | try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null } 146 | catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" } 147 | } 148 | 149 | Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD" 150 | -------------------------------------------------------------------------------- /src/main/java/com/github/websend/events/listener/BlockListener.java: -------------------------------------------------------------------------------- 1 | package com.github.websend.events.listener; 2 | 3 | import com.github.websend.Main; 4 | import com.github.websend.events.configuration.BlockEventsConfiguration; 5 | import org.bukkit.event.EventHandler; 6 | import org.bukkit.event.Listener; 7 | import org.bukkit.event.block.*; 8 | 9 | public class BlockListener implements Listener{ 10 | BlockEventsConfiguration config = null; 11 | 12 | public BlockListener(BlockEventsConfiguration config) { 13 | this.config = config; 14 | } 15 | 16 | @EventHandler 17 | public void onEvent(BlockBreakEvent e){ 18 | if(config.isEventEnabled(e.getEventName())){ 19 | String[] array = {"event", e.getEventName()}; 20 | Main.doCommand(array, "WEBSEND_EVENTS_BLOCK"); 21 | } 22 | } 23 | 24 | @EventHandler 25 | public void onEvent(BlockBurnEvent e){ 26 | if(config.isEventEnabled(e.getEventName())){ 27 | String[] array = {"event", e.getEventName()}; 28 | Main.doCommand(array, "WEBSEND_EVENTS_BLOCK"); 29 | } 30 | } 31 | 32 | @EventHandler 33 | public void onEvent(BlockCanBuildEvent e){ 34 | if(config.isEventEnabled(e.getEventName())){ 35 | String[] array = {"event", e.getEventName()}; 36 | Main.doCommand(array, "WEBSEND_EVENTS_BLOCK"); 37 | } 38 | } 39 | 40 | @EventHandler 41 | public void onEvent(BlockDamageEvent e){ 42 | if(config.isEventEnabled(e.getEventName())){ 43 | String[] array = {"event", e.getEventName()}; 44 | Main.doCommand(array, "WEBSEND_EVENTS_BLOCK"); 45 | } 46 | } 47 | 48 | @EventHandler 49 | public void onEvent(BlockDispenseEvent e){ 50 | if(config.isEventEnabled(e.getEventName())){ 51 | String[] array = {"event", e.getEventName()}; 52 | Main.doCommand(array, "WEBSEND_EVENTS_BLOCK"); 53 | } 54 | } 55 | 56 | @EventHandler 57 | public void onEvent(BlockExpEvent e){ 58 | if(config.isEventEnabled(e.getEventName())){ 59 | String[] array = {"event", e.getEventName()}; 60 | Main.doCommand(array, "WEBSEND_EVENTS_BLOCK"); 61 | } 62 | } 63 | 64 | @EventHandler 65 | public void onEvent(BlockExplodeEvent e){ 66 | if(config.isEventEnabled(e.getEventName())){ 67 | String[] array = {"event", e.getEventName()}; 68 | Main.doCommand(array, "WEBSEND_EVENTS_BLOCK"); 69 | } 70 | } 71 | 72 | @EventHandler 73 | public void onEvent(BlockFadeEvent e){ 74 | if(config.isEventEnabled(e.getEventName())){ 75 | String[] array = {"event", e.getEventName()}; 76 | Main.doCommand(array, "WEBSEND_EVENTS_BLOCK"); 77 | } 78 | } 79 | 80 | @EventHandler 81 | public void onEvent(BlockFormEvent e){ 82 | if(config.isEventEnabled(e.getEventName())){ 83 | String[] array = {"event", e.getEventName()}; 84 | Main.doCommand(array, "WEBSEND_EVENTS_BLOCK"); 85 | } 86 | } 87 | 88 | @EventHandler 89 | public void onEvent(BlockFromToEvent e){ 90 | if(config.isEventEnabled(e.getEventName())){ 91 | String[] array = {"event", e.getEventName()}; 92 | Main.doCommand(array, "WEBSEND_EVENTS_BLOCK"); 93 | } 94 | } 95 | 96 | @EventHandler 97 | public void onEvent(BlockGrowEvent e){ 98 | if(config.isEventEnabled(e.getEventName())){ 99 | String[] array = {"event", e.getEventName()}; 100 | Main.doCommand(array, "WEBSEND_EVENTS_BLOCK"); 101 | } 102 | } 103 | 104 | @EventHandler 105 | public void onEvent(BlockIgniteEvent e){ 106 | if(config.isEventEnabled(e.getEventName())){ 107 | String[] array = {"event", e.getEventName()}; 108 | Main.doCommand(array, "WEBSEND_EVENTS_BLOCK"); 109 | } 110 | } 111 | 112 | @EventHandler 113 | public void onEvent(BlockPhysicsEvent e){ 114 | if(config.isEventEnabled(e.getEventName())){ 115 | String[] array = {"event", e.getEventName()}; 116 | Main.doCommand(array, "WEBSEND_EVENTS_BLOCK"); 117 | } 118 | } 119 | 120 | @EventHandler 121 | public void onEvent(BlockPistonExtendEvent e){ 122 | if(config.isEventEnabled(e.getEventName())){ 123 | String[] array = {"event", e.getEventName()}; 124 | Main.doCommand(array, "WEBSEND_EVENTS_BLOCK"); 125 | } 126 | } 127 | 128 | @EventHandler 129 | public void onEvent(BlockPistonRetractEvent e){ 130 | if(config.isEventEnabled(e.getEventName())){ 131 | String[] array = {"event", e.getEventName()}; 132 | Main.doCommand(array, "WEBSEND_EVENTS_BLOCK"); 133 | } 134 | } 135 | 136 | @EventHandler 137 | public void onEvent(BlockPlaceEvent e){ 138 | if(config.isEventEnabled(e.getEventName())){ 139 | String[] array = {"event", e.getEventName()}; 140 | Main.doCommand(array, "WEBSEND_EVENTS_BLOCK"); 141 | } 142 | } 143 | 144 | @EventHandler 145 | public void onEvent(BlockMultiPlaceEvent e){ 146 | if(config.isEventEnabled(e.getEventName())){ 147 | String[] array = {"event", e.getEventName()}; 148 | Main.doCommand(array, "WEBSEND_EVENTS_BLOCK"); 149 | } 150 | } 151 | 152 | @EventHandler 153 | public void onEvent(BlockRedstoneEvent e){ 154 | if(config.isEventEnabled(e.getEventName())){ 155 | String[] array = {"event", e.getEventName()}; 156 | Main.doCommand(array, "WEBSEND_EVENTS_BLOCK"); 157 | } 158 | } 159 | 160 | @EventHandler 161 | public void onEvent(CauldronLevelChangeEvent e){ 162 | if(config.isEventEnabled(e.getEventName())){ 163 | String[] array = {"event", e.getEventName()}; 164 | Main.doCommand(array, "WEBSEND_EVENTS_BLOCK"); 165 | } 166 | } 167 | 168 | @EventHandler 169 | public void onEvent(BlockSpreadEvent e){ 170 | if(config.isEventEnabled(e.getEventName())){ 171 | String[] array = {"event", e.getEventName()}; 172 | Main.doCommand(array, "WEBSEND_EVENTS_BLOCK"); 173 | } 174 | } 175 | 176 | @EventHandler 177 | public void onEvent(EntityBlockFormEvent e){ 178 | if(config.isEventEnabled(e.getEventName())){ 179 | String[] array = {"event", e.getEventName()}; 180 | Main.doCommand(array, "WEBSEND_EVENTS_BLOCK"); 181 | } 182 | } 183 | 184 | @EventHandler 185 | public void onEvent(LeavesDecayEvent e){ 186 | if(config.isEventEnabled(e.getEventName())){ 187 | String[] array = {"event", e.getEventName()}; 188 | Main.doCommand(array, "WEBSEND_EVENTS_BLOCK"); 189 | } 190 | } 191 | 192 | @EventHandler 193 | public void onEvent(NotePlayEvent e){ 194 | if(config.isEventEnabled(e.getEventName())){ 195 | String[] array = {"event", e.getEventName()}; 196 | Main.doCommand(array, "WEBSEND_EVENTS_BLOCK"); 197 | } 198 | } 199 | 200 | @EventHandler 201 | public void onEvent(SignChangeEvent e){ 202 | if(config.isEventEnabled(e.getEventName())){ 203 | String[] array = {"event", e.getEventName()}; 204 | Main.doCommand(array, "WEBSEND_EVENTS_BLOCK"); 205 | } 206 | } 207 | } 208 | -------------------------------------------------------------------------------- /src/main/java/com/github/websend/script/ScriptManager.java: -------------------------------------------------------------------------------- 1 | package com.github.websend.script; 2 | 3 | import com.github.websend.Main; 4 | import java.io.*; 5 | import java.net.URL; 6 | import java.net.URLClassLoader; 7 | import java.util.Arrays; 8 | import java.util.HashMap; 9 | import java.util.logging.Level; 10 | import javax.tools.JavaCompiler; 11 | import javax.tools.JavaFileObject; 12 | import javax.tools.StandardJavaFileManager; 13 | import javax.tools.ToolProvider; 14 | 15 | public class ScriptManager { 16 | 17 | File scriptsDir; 18 | File compiledDir; 19 | private HashMap scripts; 20 | 21 | public ScriptManager() { 22 | scriptsDir = Main.getScriptsDir(); 23 | compiledDir = new File(Main.getScriptsDir(), "compiled"); 24 | scripts = new HashMap(); 25 | } 26 | 27 | // ----------- API ----------- 28 | public void invokeScript(String name) { 29 | Main.logDebugInfo(Level.WARNING, "Searching script: " + name); 30 | Script script = scripts.get(name); 31 | if (script != null) { 32 | Main.logDebugInfo(Level.WARNING, "Found script, invoking main method."); 33 | script.invoke(); 34 | } else { 35 | Main.getMainLogger().info("No script with name: " + name); 36 | } 37 | } 38 | 39 | public void clearScripts() { 40 | Main.logDebugInfo(Level.WARNING, "Cleared scripts map."); 41 | scripts.clear(); 42 | } 43 | 44 | public void reload() { 45 | clearScripts(); 46 | loadScripts(); 47 | } 48 | 49 | public void reload(String scriptName) { 50 | if (!scripts.containsKey(scriptName)) { 51 | Main.getMainLogger().log(Level.WARNING, "'" + scriptName + "' was not found and therefore can't be reloaded."); 52 | return; 53 | } 54 | scripts.remove(scriptName); 55 | scripts.put(scriptName, loadScriptFromDir(new File(Main.getScriptsDir(), scriptName))); 56 | } 57 | 58 | public void loadScripts() { 59 | File[] directories = scriptsDir.listFiles(new DirectoryFilter()); 60 | for (File cur : directories) { 61 | if (!cur.getName().equals("compiled")) { 62 | Main.logDebugInfo(Level.WARNING, "Loading script: " + cur.getName()); 63 | Script newScript = loadScriptFromDir(cur); 64 | if (newScript != null) { 65 | scripts.put(newScript.name, newScript); 66 | } 67 | } 68 | } 69 | } 70 | 71 | public String[] getScriptNames() { 72 | return scripts.keySet().toArray(new String[scripts.size()]); 73 | } 74 | 75 | public boolean hasScript(String name) { 76 | return scripts.containsKey(name); 77 | } 78 | 79 | // ----------- private methods ----------- 80 | private Script loadScriptFromDir(File directory) { 81 | String scriptName = directory.getName(); 82 | Script script = new Script(scriptName); 83 | 84 | loadScriptInfo(script, new File(directory, "info.txt")); 85 | 86 | File[] javas = directory.listFiles(new JavaFileFilter()); 87 | if (!compileClasses(scriptName, javas)) { 88 | Main.getMainLogger().log(Level.SEVERE, "Failed to compile script " + scriptName + "!"); 89 | return null; 90 | } 91 | 92 | // File compiledFilesDir = new File(compiledDir, scriptName); 93 | loadClasses(script); 94 | 95 | if (script.invokeOnLoad) { 96 | script.invoke(); 97 | } 98 | 99 | return script; 100 | } 101 | 102 | private void loadScriptInfo(Script script, File scriptInfoFile) { 103 | try { 104 | BufferedReader reader = new BufferedReader(new FileReader(scriptInfoFile)); 105 | String line = ""; 106 | while ((line = reader.readLine()) != null) { 107 | if (line.startsWith("#")) { 108 | continue; 109 | } else if (line.startsWith("INVOKEONLOAD")) { 110 | String strValue = line.split("=")[1]; 111 | script.invokeOnLoad = Boolean.parseBoolean(strValue); 112 | } 113 | } 114 | reader.close(); 115 | } catch (Exception ex) { 116 | Main.getMainLogger().log(Level.WARNING, "Failed to load script info for: " + script.name, ex); 117 | } 118 | } 119 | 120 | private boolean compileClasses(String name, File[] javaFiles) { 121 | Main.logDebugInfo(Level.WARNING, "Compiling classes"); 122 | try { 123 | JavaCompiler jc = ToolProvider.getSystemJavaCompiler(); 124 | if (jc == null) { 125 | Main.getMainLogger().log(Level.WARNING, "Can't get compiler!"); 126 | return false; 127 | } 128 | StandardJavaFileManager sjfm = jc.getStandardFileManager(null, null, null); 129 | Iterable javas = sjfm.getJavaFileObjectsFromFiles(Arrays.asList(javaFiles)); 130 | 131 | File compiledFilesDir = new File(compiledDir, name); 132 | String dir = compiledFilesDir.getCanonicalPath(); 133 | if (!compiledFilesDir.exists()) { 134 | if (!compiledFilesDir.mkdirs()) { 135 | Main.getMainLogger().log(Level.WARNING, "Failed to make compiled scripts directory."); 136 | } 137 | } 138 | 139 | boolean succes = jc.getTask(null, sjfm, null, Arrays.asList(new String[]{"-d", dir}), null, javas).call(); 140 | sjfm.close(); 141 | return succes; 142 | } catch (IOException ex) { 143 | Main.getMainLogger().log(Level.SEVERE, null, ex); 144 | return false; 145 | } 146 | } 147 | 148 | private boolean loadClasses(Script container) { 149 | Main.logDebugInfo(Level.WARNING, "Loading classes into JVM"); 150 | try { 151 | File scriptDir = new File(compiledDir, container.name); 152 | if (!scriptDir.exists()) { 153 | Main.getMainLogger().log(Level.WARNING, "Invalid script! No compiled files dir found!"); 154 | return false; 155 | } 156 | 157 | @SuppressWarnings("resource") 158 | URLClassLoader classLoader = new URLClassLoader(new URL[]{scriptDir.toURI().toURL()}); 159 | File[] classFiles = scriptDir.listFiles(new ClassFileFilter()); 160 | 161 | for (File cur : classFiles) { 162 | Class curClass = classLoader.loadClass(cur.getName().replace(".class", "")); 163 | if (curClass.getName().toLowerCase().equals("main") && ScriptInterface.class.isAssignableFrom(curClass)) { 164 | container.setMainClass((Class)curClass); 165 | } 166 | container.addClass(curClass); 167 | } 168 | 169 | // Java 7 part 170 | /* 171 | * try { classLoader.close(); } catch (IOException e) { 172 | * e.printStackTrace(); } 173 | */ 174 | return true; 175 | } catch (Exception e) { 176 | Main.getMainLogger().log(Level.SEVERE, "Error while loading classes into the JVM!", e); 177 | } 178 | return false; 179 | } 180 | } 181 | 182 | class DirectoryFilter implements FileFilter { 183 | 184 | @Override 185 | public boolean accept(File file) { 186 | return file.isDirectory(); 187 | } 188 | } 189 | 190 | class JavaFileFilter implements FileFilter { 191 | 192 | @Override 193 | public boolean accept(File file) { 194 | return file.getName().endsWith("java"); 195 | } 196 | } 197 | 198 | class ClassFileFilter implements FileFilter { 199 | 200 | @Override 201 | public boolean accept(File file) { 202 | return file.getName().endsWith("class"); 203 | } 204 | } 205 | -------------------------------------------------------------------------------- /src/main/java/com/github/websend/server/CommunicationServer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Packets: 1: DoCommandAsPlayer 2: DoCommandAsConsole 3: DoScript 4: 3 | * StartPluginOutputRecording 5: EndPluginOutputRecording 10: 4 | * WriteOutputToConsole 11: WriteOutputToPlayer 12: Broadcast 20: Disconnect 21: 5 | * Password 6 | */ 7 | package com.github.websend.server; 8 | 9 | import com.github.websend.Main; 10 | import com.github.websend.PacketHandler; 11 | import com.github.websend.TrustedHosts; 12 | import java.io.DataInputStream; 13 | import java.io.DataOutputStream; 14 | import java.io.IOException; 15 | import java.net.InetAddress; 16 | import java.net.ServerSocket; 17 | import java.net.Socket; 18 | import java.util.HashMap; 19 | import java.util.concurrent.ExecutionException; 20 | import java.util.logging.Level; 21 | import java.util.logging.Logger; 22 | 23 | public abstract class CommunicationServer extends Thread { 24 | private static final int MAX_FAILS = 15; 25 | private static final int FAILURE_SLEEP_TIME = 15000; 26 | private final HashMap customPacketHandlers = new HashMap(); 27 | private boolean running = true; 28 | private boolean connected = false; 29 | private boolean authenticated = false; 30 | private ServerSocket serverSkt; 31 | 32 | abstract ServerSocket openServerSocket(InetAddress bindIP, int port) throws IOException; 33 | abstract ServerSocket openServerSocket(int port) throws IOException; 34 | 35 | @Override 36 | public void run() { 37 | int fails = 0; 38 | while (running) { 39 | if (fails == MAX_FAILS) { 40 | try { 41 | Main.getMainLogger().info("Max amount of fails reached. Waiting for " + (FAILURE_SLEEP_TIME / 1000) + " seconds until retry."); 42 | Thread.sleep(FAILURE_SLEEP_TIME); 43 | fails = 0; 44 | } catch (InterruptedException ex) { 45 | Logger.getLogger(CommunicationServer.class.getName()).log(Level.SEVERE, "Failed to sleep", ex); 46 | } 47 | } 48 | try { 49 | Main.logDebugInfo(Level.INFO, "Starting server"); 50 | startServer(); 51 | } catch (Exception ex) { 52 | Main.getMainLogger().log(Level.SEVERE, "Server encountered an error. Attempting restart.", ex); 53 | connected = false; 54 | authenticated = false; 55 | 56 | try { 57 | serverSkt.close(); 58 | } catch (IOException ex1) { 59 | Main.logDebugInfo(Level.WARNING, "Failed to close server.", ex1); 60 | } 61 | } 62 | } 63 | } 64 | 65 | public void addPacketHandler(PacketHandler wph) { 66 | customPacketHandlers.put(wph.getHeader(), wph); 67 | } 68 | 69 | private void startServer() throws IOException, ExecutionException, InterruptedException { 70 | running = true; 71 | if (Main.getSettings().getServerBindIP() != null) { 72 | serverSkt = openServerSocket(Main.getSettings().getServerBindIP(), Main.getSettings().getPort()); 73 | } else { 74 | serverSkt = openServerSocket(Main.getSettings().getPort()); 75 | } 76 | 77 | while (running) { 78 | Main.logDebugInfo("Waiting for client."); 79 | Socket skt = serverSkt.accept(); 80 | Main.logDebugInfo("Client connected."); 81 | if (TrustedHosts.isTrusted(skt.getInetAddress())) { 82 | Main.logDebugInfo("Client is trusted."); 83 | skt.setKeepAlive(true); 84 | DataInputStream in = new DataInputStream(skt.getInputStream()); 85 | DataOutputStream out = new DataOutputStream(skt.getOutputStream()); 86 | connected = true; 87 | 88 | Main.logDebugInfo("Trying to read first byte..."); 89 | try { 90 | if (in.readByte() == 21) { 91 | Main.logDebugInfo("First packet is authentication request packet."); 92 | 93 | authenticated = PacketParser.parseAuthenticationRequestPacket(in, out); 94 | if (!authenticated) { 95 | Main.getMainLogger().log(Level.INFO, "Client failed to authenticate! Disconnecting."); 96 | connected = false; 97 | } else { 98 | Main.logDebugInfo("Password is correct! Client connected."); 99 | } 100 | } else { 101 | Main.getMainLogger().log(Level.WARNING, "First packet wasn't a authentication request packet! Disconnecting. (Are you using the correct version?)"); 102 | connected = false; 103 | } 104 | 105 | while (connected) { 106 | byte packetHeader = in.readByte(); 107 | if (packetHeader == 1) { 108 | Main.logDebugInfo("Got packet header: DoCommandAsPlayer"); 109 | PacketParser.parseDoCommandAsPlayer(in, out); 110 | } else if (packetHeader == 2) { 111 | Main.logDebugInfo("Got packet header: DoCommandAsConsole"); 112 | PacketParser.parseDoCommandAsConsole(in, out); 113 | } else if (packetHeader == 3) { 114 | Main.logDebugInfo("Got packet header: DoScript"); 115 | PacketParser.parseDoScript(in, out); 116 | } else if (packetHeader == 4) { 117 | Main.logDebugInfo("Got packet header: StartPluginOutputRecording"); 118 | PacketParser.parseStartPluginOutputRecording(in, out); 119 | } else if (packetHeader == 5) { 120 | Main.logDebugInfo("Got packet header: EndPluginOutputRecording"); 121 | PacketParser.parseEndPluginOutputRecording(in, out); 122 | } else if (packetHeader == 10) { 123 | Main.logDebugInfo("Got packet header: WriteOutputToConsole"); 124 | PacketParser.parseWriteOutputToConsole(in, out); 125 | } else if (packetHeader == 11) { 126 | Main.logDebugInfo("Got packet header: WriteOutputToPlayer"); 127 | PacketParser.parseWriteOutputToPlayer(in, out); 128 | } else if (packetHeader == 12) { 129 | Main.logDebugInfo("Got packet header: Broadcast"); 130 | PacketParser.parseBroadcast(in, out); 131 | } else if (packetHeader == 20) { 132 | Main.logDebugInfo("Got packet header: Disconnect"); 133 | connected = false; 134 | } else if (customPacketHandlers.containsKey(packetHeader)) { 135 | Main.logDebugInfo("Got custom packet header: " + packetHeader); 136 | customPacketHandlers.get(packetHeader).onHeaderReceived(in, out); 137 | } else { 138 | Main.getMainLogger().log(Level.WARNING, "Unsupported packet header!"); 139 | } 140 | } 141 | Main.logDebugInfo("Closing connection with client."); 142 | out.flush(); 143 | out.close(); 144 | in.close(); 145 | } catch (IOException ex) { 146 | Main.getMainLogger().log(Level.WARNING, "IOException while communicating to client! Disconnecting. ("+ex.getMessage()+")"); 147 | connected = false; 148 | } 149 | } else { 150 | Main.getMainLogger().log(Level.WARNING, "Connection request from unauthorized address!"); 151 | Main.getMainLogger().log(Level.WARNING, "Address: " + skt.getInetAddress()); 152 | Main.getMainLogger().log(Level.WARNING, "Add this address to trusted.txt to allow access."); 153 | } 154 | skt.close(); 155 | } 156 | serverSkt.close(); 157 | } 158 | 159 | public void stopServer() { 160 | running = false; 161 | } 162 | 163 | public boolean isConnected() { 164 | return connected; 165 | } 166 | } 167 | -------------------------------------------------------------------------------- /src/main/resources/Websend.php: -------------------------------------------------------------------------------- 1 | host = $host; 21 | $this->port = $port; 22 | } 23 | 24 | /** 25 | * Connects to a Websend server. 26 | * Returns true if successful. 27 | */ 28 | public function connect() { 29 | $this->stream = fsockopen($this->host, $this->port, $errno, $errstr, $this->timeout); 30 | if ($this->stream){ 31 | $this->writeRawByte(21); 32 | $this->writeString("websendmagic"); 33 | $seed = $this->readRawInt(); 34 | $hashedPassword = hash($this->hashAlgorithm, $seed.$this->password); 35 | $this->writeString($hashedPassword); 36 | $result = $this->readRawInt(); 37 | if ($result == 1) { 38 | return true; 39 | } else { 40 | return false; 41 | } 42 | } else { 43 | error_log("Websend connect() failed: " . var_export($this, true)); 44 | return false; 45 | } 46 | } 47 | 48 | /** 49 | * Sends a disconnect signal to the currently connected Websend server. 50 | */ 51 | public function disconnect() { 52 | $this->writeRawByte(20); 53 | } 54 | 55 | // NETWORK IO 56 | private function writeRawInt($i) { 57 | fwrite( $this->stream, pack("N", $i), 4); 58 | } 59 | 60 | private function writeRawDouble( $d) { 61 | fwrite( $this->stream, strrev(pack("d", $d))); 62 | } 63 | 64 | private function writeRawByte($b) { 65 | fwrite( $this->stream, strrev(pack("C", $b))); 66 | } 67 | 68 | private function writeChar($char) { 69 | $v = ord($char); 70 | $this->writeRawByte((0xff & ($v >> 8))); 71 | $this->writeRawByte((0xff & $v)); 72 | } 73 | 74 | private function writeChars($string) { 75 | $array = str_split($string); 76 | foreach ($array as &$cur) { 77 | $v = ord($cur); 78 | $this->writeRawByte((0xff & ($v >> 8))); 79 | $this->writeRawByte((0xff & $v)); 80 | } 81 | } 82 | 83 | private function writeString($string) { 84 | $array = str_split($string); 85 | $this->writeRawInt(count($array)); 86 | foreach ($array as &$cur) { 87 | $v = ord($cur); 88 | $this->writeRawByte((0xff & ($v >> 8))); 89 | $this->writeRawByte((0xff & $v)); 90 | } 91 | } 92 | 93 | private function readRawInt() { 94 | $a = $this->readRawByte(); 95 | $b = $this->readRawByte(); 96 | $c = $this->readRawByte(); 97 | $d = $this->readRawByte(); 98 | $i = ((($a & 0xff) << 24) | (($b & 0xff) << 16) | (($c & 0xff) << 8) | ($d & 0xff)); 99 | if ($i > 2147483648){ 100 | $i -= 4294967296; 101 | } 102 | return $i; 103 | } 104 | 105 | private function readRawDouble() { 106 | $up = unpack("di", strrev(fread($this->stream, 8))); 107 | $d = $up["i"]; 108 | return $d; 109 | } 110 | 111 | private function readRawByte() { 112 | $up = unpack("Ci", fread($this->stream, 1)); 113 | $b = $up["i"]; 114 | if ($b > 127){ 115 | $b -= 256; 116 | } 117 | return $b; 118 | } 119 | private function readRawUnsignedByte() { 120 | $up = unpack("Ci", fread($this->stream, 1)); 121 | $b = $up["i"]; 122 | return $b; 123 | } 124 | private function readChar() { 125 | $byte1 = $this->readRawByte(); 126 | $byte2 = $this->readRawByte(); 127 | $charValue = chr(utf8_decode((($byte1 << 8) | ($byte2 & 0xff)))); 128 | return $charValue; 129 | } 130 | private function readChars($len) { 131 | $buf = ""; 132 | for ($i=0; $i<$len; $i++) { 133 | $byte1 = $this->readRawByte(); 134 | $byte2 = $this->readRawByte(); 135 | $buf = $buf.chr(utf8_decode((($byte1 << 8) | ($byte2 & 0xff)))); 136 | } 137 | return $buf; 138 | } 139 | 140 | //WEBSEND SPECIFIC 141 | 142 | /** 143 | * Run a command as if the specified player typed it into the chat. 144 | * 145 | * @param string $cmmd Command and arguments to run. 146 | * @param string $playerName Exact name of the player to run it as. 147 | * @return true if the command and player were found, else false 148 | */ 149 | public function doCommandAsPlayer($cmmd, $playerName) { 150 | $this->writeRawByte(1); 151 | $this->writeString($cmmd); 152 | if (isset($playerName)) { 153 | $this->writeString($playerName); 154 | } else { 155 | $this->writeString("null"); 156 | } 157 | 158 | if ($this->readRawInt() == 1) { 159 | return true; 160 | } else { 161 | return false; 162 | } 163 | } 164 | 165 | /** 166 | * Run a command as if it were typed into the console. 167 | * 168 | * @param string $cmmd Command and arguments to run. 169 | * @return true if the command was found, else false 170 | */ 171 | public function doCommandAsConsole($cmmd) { 172 | $this->writeRawByte(2); 173 | $this->writeString($cmmd); 174 | 175 | if ($this->readRawInt() == 1) { 176 | return true; 177 | } else { 178 | error_log("Websend doCommandAsConsole failed: " . var_export($this, true)); 179 | return false; 180 | } 181 | } 182 | 183 | /** 184 | * Run a script. 185 | * The script has to be in the Websend scripts directory and has to be compiled and loaded before this is runned. 186 | * 187 | * @param string $scriptName Name of the script. 188 | */ 189 | public function doScript($scriptName) { 190 | $this->writeRawByte(3); 191 | $this->writeString($scriptName); 192 | } 193 | 194 | /** 195 | * Start plugin output capture 196 | * 197 | * @param string $pluginName Name of the plugin. 198 | */ 199 | public function startPluginOutputListening($pluginName) { 200 | $this->writeRawByte(4); 201 | $this->writeString($pluginName); 202 | } 203 | 204 | /** 205 | * Stop plugin output capture 206 | * 207 | * @param string $pluginName Name of the plugin. 208 | * @return array of strings that contains output. 209 | */ 210 | public function stopPluginOutputListening($pluginName) { 211 | $this->writeRawByte(5); 212 | $this->writeString($pluginName); 213 | $size = $this->readRawInt(); 214 | $data = array(); 215 | for ($i=0; $i<$size; $i++){ 216 | $messageSize = $this->readRawInt(); 217 | $data[$i] = $this->readChars($messageSize); 218 | } 219 | return $data; 220 | } 221 | 222 | /** 223 | * Print output to the console window. Invisible to players. 224 | */ 225 | public function writeOutputToConsole($message) { 226 | $this->writeRawByte(10); 227 | $this->writeString($message); 228 | } 229 | 230 | /** 231 | * Prints output to specified player. 232 | * 233 | * @param string $message Message to be shown. 234 | * @param string $playerName Exact name of the player to print the message to. 235 | * @return true if the player was found, else false 236 | */ 237 | public function writeOutputToPlayer($message, $playerName) { 238 | $this->writeRawByte(11); 239 | $this->writeString($message); 240 | if (isset($playerName)) { 241 | $this->writeString($playerName); 242 | } else { 243 | $this->writeString("null"); 244 | } 245 | 246 | if ($this->readRawInt() == 1) { 247 | return true; 248 | } else { 249 | return false; 250 | } 251 | } 252 | 253 | /** 254 | * Prints a message to all players and the console. 255 | * 256 | * @param string $message Message to be shown. 257 | */ 258 | public function broadcast($message) { 259 | $this->writeRawByte(12); 260 | $this->writeString($message); 261 | } 262 | } 263 | -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | # Websend 2 | 3 | Websend is a spigot/paper plugin for minecraft servers. 4 | Websend enables PHP developers to access minecraft commands from a web-based script. 5 | It allows in-game commands to execute PHP scripts and in return also execute actions in-game through PHP scripts. 6 | 7 | # Installation 8 | 9 | * Put the plugin in the plugin folder. 10 | * Restart the server to allow the configuration file to be generated. 11 | * Stop the server. 12 | * Edit the configuration file. 13 | * Start the server 14 | * run a command as player or console, such as /ws test 15 | 16 | # Configuration 17 | 18 | Option | Comment 19 | -------|-------- 20 | URL=phpURL | URL to send the POST data to when typing a command ingame. You can point it to the minecraft.php in the example files. 21 | PASS=password | Password to be used in connections. 22 | WEBLISTENER_ACTIVE=false/true | Set to true to enable PHP -> Spigot connections. Disabled by default. 23 | ALTPORT=portnumber | Enter a portnumber here to use a different TCP port than 4445 for hosting the PHP -> Spigot server. 24 | Does not affect PHP -> Spigot connections. 25 | HASH_ALGORITHM=algorithmname | If set, the specified hashing algorithm is used to hash the password instead of SHA-512. 26 | DEBUG_WEBSEND=false/true | When set to true Websend will output additional output used for debugging. Disabled by default. 27 | GZIP_REQUESTS=false/true | When set to true Websend will gzip the JSON data in a Spigot -> PHP connection. The data is then available in the $_FILES array instead of the regular $_POST. To use the data, read the "jsonData" file and use the gzdecode function to decompress the bytes into a json string. Then load the json using json_decode function. If the data does not show up serverside, check the upload_max_filesize, post_max_size and file_uploads variables in php.ini. Disabled by default. 28 | SERVER_BIND_IP=123.456.789.123 | Use this option to bind the Websend server to a specific ip address. 29 | WRAP_COMMAND_EXECUTOR=true/false | If true, Websend will use additional methods to capture plugin output. 30 | 31 | Note that a server restart is required to apply the changes to the configuration files. 32 | 33 | # Spigot to PHP 34 | 35 | This allows you to execute PHP scripts by typing in-game commands. Websend creates a HTTP POST request to a URL you give and parses the response given by PHP. 36 | 37 | ## Configuration 38 | 39 | * Open the “minecraft.php” file included in the Websend download. 40 | * Set the password variable to the password specified in the Websend configuration file. 41 | * Upload this file to your website. 42 | * Open the Websend plugin configuration file. 43 | * Set the "URL=" option to the url of your php file. 44 | * Start your Bukkit server. 45 | * Try command “/ws argument1 argument2”. Just /ws will return an "Empty argument" error 46 | 47 | ## Sending a command 48 | 49 | Use the command `/ws argument0 argument1` or `/websend argument0 argument1` to start a request from Spigot to PHP. You can add any number of arguments. These will be passed to your PHP script. 50 | 51 | ## Data sent by websend 52 | 53 | When Websend sends its request it includes information in the POST data. Most of the data is contained in a JSON string under `$_POST['jsonData']`, unless `GZIP_REQUESTS` is enabled, in which case it is available in gzip form under `$_FILES['jsonData']`. Whether the JSON data is compressed or not is specified under the `$_POST['isCompressed']` variable. The `$_POST['authKey']` variable contains the hashed password and the `$_POST['args'][]` has the arguments. 54 | 55 | ## Sending a reply 56 | 57 | You can respond to the request by simply printing commands with print() or echo. Websend will then parse and execute these commands in the order that they were printed. 58 | 59 | ATTENTION: Since Websend 5.x, replies need to be sent in JSON Format and be terminated with CHR(10) which is a linefeed There is no more colon (`;`) needed to terminate. Newer NBT codes in Minecraft use a colon and break the old method of terminating a line with a colon. \n or \r instead of CHR(10) do not work. 60 | Ideally, this is done with a small PHP Function such as: 61 | 62 | ````php 63 | $action, 69 | // use this in case you have a target player other than the user who ran the command in-game 70 | 'targetPlayer' => $targetPlayer, 71 | // this is the command/text to be executed/displayed 72 | 'command' => $command, 73 | ); 74 | 75 | // json-encode the array and append the terminating CHR(10) to conclude 76 | $json = json_encode($websend_array) . CHR(10); 77 | 78 | // finally send this to websend. 79 | print($json); 80 | } 81 | ?> 82 | ```` 83 | 84 | Please see the included minecraft.php for an example how this works. 85 | 86 | You can execute this function several times to do several things in sequence. Please note that minecraft will do commands with the same action in sequence, 87 | but there is a risk that commands such as ExecuteConsoleCommand take longer than PrintToConsole. So if you execeute a PrintToConsole after a ConsoleCommand, the PrintToConsole might still happen first. 88 | 89 | A text send to the player or console can contain a line break with \n. This line break will be executed on the console and on the user screen. 90 | 91 | The action needs to be one of the following types, capitalization is not relevant: 92 | 93 | * `PrintToConsole`: Prints whatever the `command` is set to the console. In-game players won't see this. The targetPlayer argument is ignored and should be `null`. 94 | * `PrintToPlayer`: Prints whatever the `command` is set to as a message to a player currently playing on your server. If you provide targetPlayer, this will be the target, otherwise it will be who 95 | * `Broadcast`: Broadcasts whatever the `command` is set to to all players currently playing on the server. 96 | * `ExecutePlayerCommand`: Executes whatever the `command` is set as a player currently playing on your server. By using "targetPlayer", you can specify the player to set as command source, otherwise the command will be ran as the player that started the websend request. This allows you to 'force' a user to execute a command. 97 | * `ExecuteConsoleCommand`: Executes hatever the `command` is set to as if it was entered directly on the server console. 98 | * `toggleDebug`: Switches debug on or off. If you call this action with empty command (''), it will just toggle the status. Alternatively set a status with the command 'on' or 'off'. targetPlayer needs to be `null`. ATTENTION: If you have basic issues to get websend running, you need to set debug on in the plugin config, not here as this switch will only become active after a successful connection with websend is established. 99 | * `executeScript`: Runs a script. The script (specified by `command`) that has to be in the Websend scripts directory and has to be compiled and loaded before this is run. 100 | * `setResponseURL`: Changes the responseURL as set in the websend config file to whatever is set in `command`. `targetPlayer` needs to be `null`. 101 | 102 | # PHP to Spigot 103 | You can initiate a command to the server via a PHP script as well. For this, you need the `Websend.php` file from the plugin directory. It contains a class that connects to the minecraft server and manages the communication. Further, you need a PHP script that loads the class and executes a command. There is an example `ExternalTimeSet.php` in the plugin directory. 104 | The default port is 4445. Please make sure that your minecraft server is able to listen to that port. 105 | 106 | The base process is as follows: 107 | ````php 108 | password = "websendpassword"; 115 | 116 | // you attempt to connect 117 | if($ws->connect()) { 118 | // execute an action on the server 119 | $check = $ws->doCommandAsConsole("time set 6000"); 120 | // the check is returning true or false 121 | if (!$check) { 122 | echo "Failure to set time"; 123 | } else { 124 | echo "Time set."; 125 | } 126 | } else { 127 | echo "Failed to connect."; 128 | } 129 | $ws->disconnect(); 130 | ```` 131 | There are several commands that can be executed on the minecraft server, similar to the Spigot->PHP direction: 132 | 133 | * `$ws->doCommandAsConsole($cmd);`: Executes a command on the console 134 | * `$ws->doCommandAsPlayer($cmd, $player);`: Executes a command as if done by a player 135 | * `$ws->writeOutputToConsole($cmd);`: Writes text to the console 136 | * `$ws->writeOutputToPlayer($cmd, $player);`: Writes text to a player 137 | * `$ws->broadcast($cmd);`: Broadcasts text to all players 138 | * `$ws->doScript($cmd);`: Executes a script. 139 | 140 | -------------------------------------------------------------------------------- /src/main/java/com/github/websend/ConfigHandler.java: -------------------------------------------------------------------------------- 1 | package com.github.websend; 2 | 3 | import java.io.*; 4 | import java.net.InetAddress; 5 | import java.net.MalformedURLException; 6 | import java.net.URL; 7 | import java.security.MessageDigest; 8 | import java.security.NoSuchAlgorithmException; 9 | import java.util.logging.Level; 10 | 11 | public class ConfigHandler { 12 | 13 | public Settings loadSettings() throws FileNotFoundException, IOException { 14 | // Prepare new settings map 15 | Settings settings = new Settings(); 16 | 17 | // Open file 18 | BufferedReader reader = openFile(); 19 | 20 | // Parse each line if line is not null 21 | String currentLine; 22 | while ((currentLine = reader.readLine()) != null) { 23 | parseLine(currentLine, settings); 24 | } 25 | 26 | return settings; 27 | } 28 | 29 | public void generateConfig() { 30 | // File declaration 31 | File websendDir = Main.getInstance().getDataFolder(); 32 | if (!websendDir.exists()) { 33 | if (!websendDir.mkdirs()) { 34 | Main.getMainLogger().log(Level.SEVERE, "Could not create plugin directory."); 35 | } 36 | } 37 | File configFile = new File(websendDir, "config.txt"); 38 | 39 | // Prepare file 40 | PrintWriter writer = null; 41 | try { 42 | if (!configFile.createNewFile()) { 43 | Main.getMainLogger().log(Level.WARNING, "Could not create new config file."); 44 | } 45 | writer = new PrintWriter(new FileWriter(configFile)); 46 | } catch (IOException ex) { 47 | Main.getMainLogger().info("Websend failed to create a new configuration file."); 48 | Main.getMainLogger().log(Level.SEVERE, null, ex); 49 | } 50 | 51 | // Fill file 52 | writer.println("#Configuration and settings file!"); 53 | writer.println("#Help: PASS: change the password to one of your choice (set the same in the server php file)."); 54 | writer.println("#Help: DEBUG_WEBSEND: shows debugging messages for easier tracking of bugs."); 55 | writer.println("#Help: SALT: adds a salt to the hashed password when sending over bukkit -> php connection."); 56 | writer.println("PASS=YourPassHere"); 57 | writer.println("#Optional settings. Remove the '#' to use."); 58 | writer.println("#URL=yoururl.com/page.php"); 59 | writer.println("#WEBLISTENER_ACTIVE=false/true"); 60 | writer.println("#ALTPORT=1234"); 61 | writer.println("#DEBUG_WEBSEND=false/true"); 62 | writer.println("#GZIP_REQUESTS=false/true"); 63 | writer.close(); 64 | } 65 | 66 | private BufferedReader openFile() throws FileNotFoundException { 67 | // File declaration 68 | File folder = Main.getInstance().getDataFolder(); 69 | File configFile = new File(folder, "config.txt"); 70 | 71 | // Reader opening 72 | BufferedReader reader = new BufferedReader(new FileReader(configFile)); 73 | return reader; 74 | } 75 | 76 | private void parseLine(String line, Settings settings) { 77 | // Is the line a comment? 78 | if (line.trim().startsWith("#")) { 79 | return; 80 | } else { 81 | // What value does this line contain? 82 | if (line.startsWith("RESPONSEURL=")) { 83 | // Clean and store value 84 | String value = line.replaceFirst("RESPONSEURL=", ""); 85 | settings.setResponseURL(value); 86 | Main.logDebugInfo(Level.INFO, "Config read: Response URL is :" + value); 87 | } else if (line.startsWith("PASS=")) { 88 | String value = line.replaceFirst("PASS=", ""); 89 | settings.setPassword(value); 90 | Main.logDebugInfo(Level.INFO, "Config read: Password is set!"); 91 | } else if (line.startsWith("ALTPORT=")) { 92 | String value = line.replaceFirst("ALTPORT=", ""); 93 | Main.logDebugInfo(Level.INFO, "Config read: AltPort is set to " + value); 94 | int convertedValue = 0; 95 | try { 96 | convertedValue = Integer.parseInt(value.trim()); 97 | if (convertedValue == Main.getBukkitServer().getPort()) { 98 | Main.getMainLogger().log(Level.WARNING, "You are trying to host Websend on the minecraft server port! Choose a different port."); 99 | } 100 | } catch (Exception ex) { 101 | Main.getMainLogger().log(Level.SEVERE, "Websend failed to parse your new port value:" + value, ex); 102 | return; 103 | } 104 | settings.setPort(convertedValue); 105 | } else if (line.startsWith("DEBUG_WEBSEND=")) { 106 | String value = line.replaceFirst("DEBUG_WEBSEND=", ""); 107 | if (value.toLowerCase().trim().contains("true")) { 108 | settings.setDebugMode(true); 109 | Main.logDebugInfo(Level.INFO, "Config read: DEBUG Mode is ON"); 110 | } else { 111 | settings.setDebugMode(false); 112 | Main.logDebugInfo(Level.INFO, "Config read: DEBUG Mode is OFF"); 113 | } 114 | } else if (line.startsWith("WEBLISTENER_ACTIVE=")) { 115 | String value = line.replaceFirst("WEBLISTENER_ACTIVE=", ""); 116 | if (value.toLowerCase().trim().contains("true")) { 117 | settings.setServerActive(true); 118 | Main.logDebugInfo(Level.INFO, "Config read: Web Listener is ON"); 119 | } else { 120 | settings.setServerActive(false); 121 | Main.logDebugInfo(Level.INFO, "Config read: Web Listener is OFF"); 122 | } 123 | } else if (line.startsWith("URL=")) { 124 | String value = line.replaceFirst("URL=", ""); 125 | try { 126 | settings.setURL(new URL(value)); 127 | Main.logDebugInfo(Level.INFO, "Config read: URL is set to " + value); 128 | } catch (MalformedURLException ex) { 129 | Main.getMainLogger().log(Level.SEVERE, "Invalid URL"); 130 | } 131 | } else if (line.startsWith("SALT=")) { 132 | String value = line.replaceFirst("SALT=", ""); 133 | settings.setSalt(value); 134 | Main.logDebugInfo(Level.INFO, "Config read: Salt is set to " + value); 135 | } else if (line.startsWith("HASH_ALGORITHM=")) { 136 | String value = line.replaceFirst("HASH_ALGORITHM=", ""); 137 | try { 138 | @SuppressWarnings("unused") 139 | MessageDigest md = MessageDigest.getInstance(value); 140 | settings.setHashingAlgorithm(value); 141 | } catch (NoSuchAlgorithmException ex) { 142 | Main.getMainLogger().info("Hashing algorithm '" + value + "' is not available on this machine."); 143 | } 144 | Main.logDebugInfo(Level.INFO, "Config read: Hash algorithm is set to " + value); 145 | } else if (line.startsWith("GZIP_REQUESTS=")) { 146 | String value = line.replaceFirst("GZIP_REQUESTS=", ""); 147 | settings.setGzipRequests(Boolean.parseBoolean(value)); 148 | Main.logDebugInfo(Level.INFO, "Config read: GZIP is set to " + value); 149 | } else if (line.startsWith("SERVER_BIND_IP=")) { 150 | String value = line.replaceFirst("SERVER_BIND_IP=", ""); 151 | try { 152 | InetAddress address = InetAddress.getByName(value); 153 | if (address != null) { 154 | settings.setServerBindIP(address); 155 | } else { 156 | Main.getMainLogger().log(Level.WARNING, "Error while parsing bind ip address."); 157 | } 158 | } catch (Exception ex) { 159 | Main.getMainLogger().log(Level.WARNING, "Error while parsing bind ip address."); 160 | } 161 | Main.logDebugInfo(Level.INFO, "Config read: Server bind IP is set to " + value); 162 | } else if (line.startsWith("WRAP_COMMAND_EXECUTOR=")) { 163 | String value = line.replaceFirst("WRAP_COMMAND_EXECUTOR=", ""); 164 | if (value.toLowerCase().trim().contains("true")) { 165 | settings.setWrapCommandExecutor(true); 166 | } else { 167 | settings.setWrapCommandExecutor(false); 168 | } 169 | } else if (line.startsWith("USE_SSL=")) { 170 | String value = line.replaceFirst("USE_SSL=", ""); 171 | if (value.toLowerCase().trim().contains("true")) { 172 | settings.setSSLEnabled(true); 173 | Main.logDebugInfo(Level.INFO, "Config read: SSL is set to ON"); 174 | } else { 175 | settings.setSSLEnabled(false); 176 | Main.logDebugInfo(Level.INFO, "Config read: SS: is set to OFF"); 177 | } 178 | 179 | } else if (line.startsWith("SSL_PASS=")) { 180 | String value = line.replaceFirst("SSL_PASS=", ""); 181 | settings.setSslPassword(value); 182 | } else if (line.startsWith("EXTENDED_PLAYER_DATA=")) { 183 | String value = line.replaceFirst("EXTENDED_PLAYER_DATA=", ""); 184 | if (value.toLowerCase().trim().contains("true")) { 185 | settings.setExtendedPlayerDataEnabled(true); 186 | } else { 187 | settings.setExtendedPlayerDataEnabled(false); 188 | } 189 | } else { 190 | Main.getMainLogger().log(Level.WARNING, "Error while parsing config file. Invalid line: \n" + line); 191 | } 192 | } 193 | } 194 | } 195 | -------------------------------------------------------------------------------- /src/main/java/com/github/websend/post/POSTRequest.java: -------------------------------------------------------------------------------- 1 | package com.github.websend.post; 2 | 3 | import com.github.websend.CommandParser; 4 | import com.github.websend.CompressionToolkit; 5 | import com.github.websend.JSONSerializer; 6 | import com.github.websend.Main; 7 | import com.github.websend.Util; 8 | import com.mojang.brigadier.exceptions.CommandSyntaxException; 9 | import java.io.BufferedReader; 10 | import java.io.IOException; 11 | import java.io.InputStreamReader; 12 | import java.net.URL; 13 | import java.nio.charset.Charset; 14 | import java.util.ArrayList; 15 | import java.util.logging.Level; 16 | import java.util.logging.Logger; 17 | import org.apache.hc.client5.http.classic.methods.HttpPost; 18 | import org.apache.hc.client5.http.entity.mime.MultipartEntityBuilder; 19 | import org.apache.hc.client5.http.entity.mime.ByteArrayBody; 20 | import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; 21 | import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse; 22 | import org.apache.hc.client5.http.impl.classic.HttpClients; 23 | import org.apache.hc.core5.http.ContentType; 24 | import org.apache.hc.core5.http.HttpEntity; 25 | import org.apache.hc.core5.http.io.entity.EntityUtils; 26 | import org.bukkit.Server; 27 | import org.bukkit.entity.Player; 28 | import org.bukkit.plugin.Plugin; 29 | import org.json.JSONArray; 30 | import org.json.JSONException; 31 | import org.json.JSONObject; 32 | 33 | public class POSTRequest { 34 | 35 | private final ArrayList content; 36 | private final URL url; 37 | private final String jsonData; 38 | private Player player; 39 | 40 | public POSTRequest(URL url, String args[], Player player, boolean isResponse) { 41 | this.content = new ArrayList<>(); 42 | this.player = player; 43 | 44 | if (args.length == 0) { 45 | Main.getMainLogger().info("POSTRequest ERROR: You need to pass arguments with /ws and /websend!"); 46 | } else { 47 | Main.logDebugInfo("POSTRequest: Executing commands by player " + player.getDisplayName() + " with arguments '" + String.join("', '", args) + "'"); 48 | } 49 | 50 | content.add(new org.apache.hc.core5.http.message.BasicNameValuePair("isResponse", Boolean.toString(isResponse))); 51 | content.add(new org.apache.hc.core5.http.message.BasicNameValuePair("authKey", Util.hash(Main.getSettings().getPassword()))); 52 | content.add(new org.apache.hc.core5.http.message.BasicNameValuePair("isCompressed", Boolean.toString(Main.getSettings().areRequestsGZipped()))); 53 | jsonData = getJSONDataString(player, null); 54 | 55 | for (int i = 0; i < args.length; i++) { 56 | content.add(new org.apache.hc.core5.http.message.BasicNameValuePair("args[" + i + "]", args[i])); 57 | } 58 | this.url = url; 59 | } 60 | 61 | public POSTRequest(URL url, String args[], String playerNameArg, boolean isResponse) { 62 | this.content = new ArrayList<>(); 63 | 64 | if (args.length == 0) { 65 | Main.getMainLogger().info("POSTRequest ERROR: You need to pass arguments with /ws and /websend!"); 66 | } else { 67 | Main.logDebugInfo("POSTRequest: Executing commands by player " + playerNameArg + " with arguments '" + String.join("', '", args) + "'"); 68 | } 69 | 70 | content.add(new org.apache.hc.core5.http.message.BasicNameValuePair("isResponse", Boolean.toString(isResponse))); 71 | content.add(new org.apache.hc.core5.http.message.BasicNameValuePair("authKey", Util.hash(Main.getSettings().getPassword()))); 72 | content.add(new org.apache.hc.core5.http.message.BasicNameValuePair("isCompressed", Boolean.toString(Main.getSettings().areRequestsGZipped()))); 73 | 74 | jsonData = getJSONDataString(null, playerNameArg); 75 | for (int i = 0; i < args.length; i++) { 76 | content.add(new org.apache.hc.core5.http.message.BasicNameValuePair("args[" + i + "]", args[i])); 77 | } 78 | this.url = url; 79 | } 80 | 81 | public void run(CloseableHttpClient httpClient) throws IOException { 82 | try (CloseableHttpResponse response = doRequest(httpClient)) { 83 | int responseCode = response.getCode(); 84 | String reason = response.getReasonPhrase(); 85 | 86 | String message = ""; 87 | Level logLevel = Level.WARNING; 88 | 89 | if (responseCode >= 200 && responseCode < 300) { 90 | if (Main.getSettings().isDebugMode()) { 91 | message = "The server responded to the request with a 2xx code. Assuming request OK. (" + reason + ")"; 92 | logLevel = Level.INFO; 93 | } 94 | } else if (responseCode >= 400) { 95 | message = "HTTP request failed. (" + reason + ")"; 96 | Main.getMainLogger().log(Level.SEVERE, message); 97 | } else if (responseCode >= 300) { 98 | message = "The server responded to the request with a redirection message. Assuming request OK. (" + reason + ")"; 99 | } else if (responseCode < 200) { 100 | message = "The server responded to the request with a continue or protocol switching message. Assuming request OK. (" + reason + ")"; 101 | } else { 102 | message = "The server responded to the request with an unknown response code (" + responseCode + "). Assuming request OK. (" + reason + ")"; 103 | } 104 | 105 | Main.logDebugInfo(logLevel, message); 106 | 107 | CommandParser parser = new CommandParser(); 108 | HttpEntity entity = response.getEntity(); 109 | BufferedReader reader = new BufferedReader(new InputStreamReader(entity.getContent())); 110 | String cur; 111 | while ((cur = reader.readLine()) != null) { 112 | parser.parse(cur, player); 113 | } 114 | reader.close(); 115 | EntityUtils.consume(entity); 116 | } 117 | } 118 | 119 | private CloseableHttpResponse doRequest(CloseableHttpClient httpClient) throws IOException { 120 | HttpPost httpPost = new HttpPost(url.toString()); 121 | httpPost.setHeader("enctype", "multipart/form-data"); 122 | 123 | MultipartEntityBuilder builder = MultipartEntityBuilder.create(); 124 | builder.setCharset(Charset.forName("UTF-8")); 125 | for (org.apache.hc.core5.http.NameValuePair cur : content) { 126 | builder.addTextBody(cur.getName(), cur.getValue()); 127 | } 128 | if (Main.getSettings().areRequestsGZipped()) { 129 | builder.addPart("jsonData", new ByteArrayBody(CompressionToolkit.gzipString(jsonData), ContentType.DEFAULT_BINARY, "jsonData")); 130 | } else { 131 | builder.addTextBody("jsonData", jsonData, ContentType.APPLICATION_JSON); 132 | } 133 | httpPost.setEntity(builder.build()); 134 | return httpClient.execute(httpPost); 135 | } 136 | 137 | private String getJSONDataString(Player ply, String playerNameArg) throws JSONException { 138 | Server server = Main.getBukkitServer(); 139 | JSONObject data = new JSONObject(); 140 | { 141 | if (ply != null) { 142 | org.json.JSONObject jsonPlayer = null; 143 | try { 144 | jsonPlayer = JSONSerializer.getInstance().serializePlayer(ply, true); 145 | } catch (CommandSyntaxException ex) { 146 | Logger.getLogger(POSTRequest.class.getName()).log(Level.SEVERE, null, ex); 147 | } 148 | data.put("Invoker", jsonPlayer); 149 | } else if (playerNameArg != null) { 150 | JSONObject jsonPlayer = new JSONObject(); 151 | { 152 | jsonPlayer.put("Name", playerNameArg); 153 | } 154 | data.put("Invoker", jsonPlayer); 155 | } else { 156 | JSONObject jsonPlayer = new JSONObject(); 157 | { 158 | jsonPlayer.put("Name", "@Console"); 159 | } 160 | data.put("Invoker", jsonPlayer); 161 | } 162 | 163 | JSONArray plugins = new JSONArray(); 164 | for (Plugin plugin : server.getPluginManager().getPlugins()) { 165 | JSONObject plug = new JSONObject(); 166 | plug.put("Name", plugin.getDescription().getFullName()); 167 | plugins.put(plug); 168 | } 169 | data.put("Plugins", plugins); 170 | 171 | JSONObject serverSettings = new JSONObject(); 172 | { 173 | serverSettings.put("Name", server.getName()); 174 | serverSettings.put("Build", server.getVersion()); 175 | serverSettings.put("Port", server.getPort()); 176 | serverSettings.put("NetherEnabled", server.getAllowNether()); 177 | serverSettings.put("FlyingEnabled", server.getAllowFlight()); 178 | serverSettings.put("DefaultGameMode", server.getDefaultGameMode()); 179 | serverSettings.put("OnlineMode", server.getOnlineMode()); 180 | serverSettings.put("MaxPlayers", server.getMaxPlayers()); 181 | } 182 | data.put("ServerSettings", serverSettings); 183 | 184 | JSONObject serverStatus = new JSONObject(); 185 | { 186 | JSONArray onlinePlayers = new JSONArray(); 187 | { 188 | for (Player cur : server.getOnlinePlayers()) { 189 | boolean extendedData = Main.getSettings().isExtendedPlayerDataEnabled(); 190 | JSONObject curPlayer = null; 191 | try { 192 | curPlayer = JSONSerializer.getInstance().serializePlayer(cur, extendedData); 193 | } catch (CommandSyntaxException ex) { 194 | Logger.getLogger(POSTRequest.class.getName()).log(Level.SEVERE, null, ex); 195 | } 196 | onlinePlayers.put(curPlayer); 197 | } 198 | } 199 | serverStatus.put("OnlinePlayers", onlinePlayers); 200 | serverStatus.put("AvailableMemory", Runtime.getRuntime().freeMemory()); 201 | serverStatus.put("MaxMemory", Runtime.getRuntime().maxMemory()); 202 | } 203 | data.put("ServerStatus", serverStatus); 204 | } 205 | return data.toString(); 206 | } 207 | } -------------------------------------------------------------------------------- /mvnw: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # ---------------------------------------------------------------------------- 3 | # Licensed to the Apache Software Foundation (ASF) under one 4 | # or more contributor license agreements. See the NOTICE file 5 | # distributed with this work for additional information 6 | # regarding copyright ownership. The ASF licenses this file 7 | # to you under the Apache License, Version 2.0 (the 8 | # "License"); you may not use this file except in compliance 9 | # with the License. You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, 14 | # software distributed under the License is distributed on an 15 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 | # KIND, either express or implied. See the License for the 17 | # specific language governing permissions and limitations 18 | # under the License. 19 | # ---------------------------------------------------------------------------- 20 | 21 | # ---------------------------------------------------------------------------- 22 | # Apache Maven Wrapper startup batch script, version 3.3.2 23 | # 24 | # Optional ENV vars 25 | # ----------------- 26 | # JAVA_HOME - location of a JDK home dir, required when download maven via java source 27 | # MVNW_REPOURL - repo url base for downloading maven distribution 28 | # MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven 29 | # MVNW_VERBOSE - true: enable verbose log; debug: trace the mvnw script; others: silence the output 30 | # ---------------------------------------------------------------------------- 31 | 32 | set -euf 33 | [ "${MVNW_VERBOSE-}" != debug ] || set -x 34 | 35 | # OS specific support. 36 | native_path() { printf %s\\n "$1"; } 37 | case "$(uname)" in 38 | CYGWIN* | MINGW*) 39 | [ -z "${JAVA_HOME-}" ] || JAVA_HOME="$(cygpath --unix "$JAVA_HOME")" 40 | native_path() { cygpath --path --windows "$1"; } 41 | ;; 42 | esac 43 | 44 | # set JAVACMD and JAVACCMD 45 | set_java_home() { 46 | # For Cygwin and MinGW, ensure paths are in Unix format before anything is touched 47 | if [ -n "${JAVA_HOME-}" ]; then 48 | if [ -x "$JAVA_HOME/jre/sh/java" ]; then 49 | # IBM's JDK on AIX uses strange locations for the executables 50 | JAVACMD="$JAVA_HOME/jre/sh/java" 51 | JAVACCMD="$JAVA_HOME/jre/sh/javac" 52 | else 53 | JAVACMD="$JAVA_HOME/bin/java" 54 | JAVACCMD="$JAVA_HOME/bin/javac" 55 | 56 | if [ ! -x "$JAVACMD" ] || [ ! -x "$JAVACCMD" ]; then 57 | echo "The JAVA_HOME environment variable is not defined correctly, so mvnw cannot run." >&2 58 | echo "JAVA_HOME is set to \"$JAVA_HOME\", but \"\$JAVA_HOME/bin/java\" or \"\$JAVA_HOME/bin/javac\" does not exist." >&2 59 | return 1 60 | fi 61 | fi 62 | else 63 | JAVACMD="$( 64 | 'set' +e 65 | 'unset' -f command 2>/dev/null 66 | 'command' -v java 67 | )" || : 68 | JAVACCMD="$( 69 | 'set' +e 70 | 'unset' -f command 2>/dev/null 71 | 'command' -v javac 72 | )" || : 73 | 74 | if [ ! -x "${JAVACMD-}" ] || [ ! -x "${JAVACCMD-}" ]; then 75 | echo "The java/javac command does not exist in PATH nor is JAVA_HOME set, so mvnw cannot run." >&2 76 | return 1 77 | fi 78 | fi 79 | } 80 | 81 | # hash string like Java String::hashCode 82 | hash_string() { 83 | str="${1:-}" h=0 84 | while [ -n "$str" ]; do 85 | char="${str%"${str#?}"}" 86 | h=$(((h * 31 + $(LC_CTYPE=C printf %d "'$char")) % 4294967296)) 87 | str="${str#?}" 88 | done 89 | printf %x\\n $h 90 | } 91 | 92 | verbose() { :; } 93 | [ "${MVNW_VERBOSE-}" != true ] || verbose() { printf %s\\n "${1-}"; } 94 | 95 | die() { 96 | printf %s\\n "$1" >&2 97 | exit 1 98 | } 99 | 100 | trim() { 101 | # MWRAPPER-139: 102 | # Trims trailing and leading whitespace, carriage returns, tabs, and linefeeds. 103 | # Needed for removing poorly interpreted newline sequences when running in more 104 | # exotic environments such as mingw bash on Windows. 105 | printf "%s" "${1}" | tr -d '[:space:]' 106 | } 107 | 108 | # parse distributionUrl and optional distributionSha256Sum, requires .mvn/wrapper/maven-wrapper.properties 109 | while IFS="=" read -r key value; do 110 | case "${key-}" in 111 | distributionUrl) distributionUrl=$(trim "${value-}") ;; 112 | distributionSha256Sum) distributionSha256Sum=$(trim "${value-}") ;; 113 | esac 114 | done <"${0%/*}/.mvn/wrapper/maven-wrapper.properties" 115 | [ -n "${distributionUrl-}" ] || die "cannot read distributionUrl property in ${0%/*}/.mvn/wrapper/maven-wrapper.properties" 116 | 117 | case "${distributionUrl##*/}" in 118 | maven-mvnd-*bin.*) 119 | MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ 120 | case "${PROCESSOR_ARCHITECTURE-}${PROCESSOR_ARCHITEW6432-}:$(uname -a)" in 121 | *AMD64:CYGWIN* | *AMD64:MINGW*) distributionPlatform=windows-amd64 ;; 122 | :Darwin*x86_64) distributionPlatform=darwin-amd64 ;; 123 | :Darwin*arm64) distributionPlatform=darwin-aarch64 ;; 124 | :Linux*x86_64*) distributionPlatform=linux-amd64 ;; 125 | *) 126 | echo "Cannot detect native platform for mvnd on $(uname)-$(uname -m), use pure java version" >&2 127 | distributionPlatform=linux-amd64 128 | ;; 129 | esac 130 | distributionUrl="${distributionUrl%-bin.*}-$distributionPlatform.zip" 131 | ;; 132 | maven-mvnd-*) MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ ;; 133 | *) MVN_CMD="mvn${0##*/mvnw}" _MVNW_REPO_PATTERN=/org/apache/maven/ ;; 134 | esac 135 | 136 | # apply MVNW_REPOURL and calculate MAVEN_HOME 137 | # maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/ 138 | [ -z "${MVNW_REPOURL-}" ] || distributionUrl="$MVNW_REPOURL$_MVNW_REPO_PATTERN${distributionUrl#*"$_MVNW_REPO_PATTERN"}" 139 | distributionUrlName="${distributionUrl##*/}" 140 | distributionUrlNameMain="${distributionUrlName%.*}" 141 | distributionUrlNameMain="${distributionUrlNameMain%-bin}" 142 | MAVEN_USER_HOME="${MAVEN_USER_HOME:-${HOME}/.m2}" 143 | MAVEN_HOME="${MAVEN_USER_HOME}/wrapper/dists/${distributionUrlNameMain-}/$(hash_string "$distributionUrl")" 144 | 145 | exec_maven() { 146 | unset MVNW_VERBOSE MVNW_USERNAME MVNW_PASSWORD MVNW_REPOURL || : 147 | exec "$MAVEN_HOME/bin/$MVN_CMD" "$@" || die "cannot exec $MAVEN_HOME/bin/$MVN_CMD" 148 | } 149 | 150 | if [ -d "$MAVEN_HOME" ]; then 151 | verbose "found existing MAVEN_HOME at $MAVEN_HOME" 152 | exec_maven "$@" 153 | fi 154 | 155 | case "${distributionUrl-}" in 156 | *?-bin.zip | *?maven-mvnd-?*-?*.zip) ;; 157 | *) die "distributionUrl is not valid, must match *-bin.zip or maven-mvnd-*.zip, but found '${distributionUrl-}'" ;; 158 | esac 159 | 160 | # prepare tmp dir 161 | if TMP_DOWNLOAD_DIR="$(mktemp -d)" && [ -d "$TMP_DOWNLOAD_DIR" ]; then 162 | clean() { rm -rf -- "$TMP_DOWNLOAD_DIR"; } 163 | trap clean HUP INT TERM EXIT 164 | else 165 | die "cannot create temp dir" 166 | fi 167 | 168 | mkdir -p -- "${MAVEN_HOME%/*}" 169 | 170 | # Download and Install Apache Maven 171 | verbose "Couldn't find MAVEN_HOME, downloading and installing it ..." 172 | verbose "Downloading from: $distributionUrl" 173 | verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName" 174 | 175 | # select .zip or .tar.gz 176 | if ! command -v unzip >/dev/null; then 177 | distributionUrl="${distributionUrl%.zip}.tar.gz" 178 | distributionUrlName="${distributionUrl##*/}" 179 | fi 180 | 181 | # verbose opt 182 | __MVNW_QUIET_WGET=--quiet __MVNW_QUIET_CURL=--silent __MVNW_QUIET_UNZIP=-q __MVNW_QUIET_TAR='' 183 | [ "${MVNW_VERBOSE-}" != true ] || __MVNW_QUIET_WGET='' __MVNW_QUIET_CURL='' __MVNW_QUIET_UNZIP='' __MVNW_QUIET_TAR=v 184 | 185 | # normalize http auth 186 | case "${MVNW_PASSWORD:+has-password}" in 187 | '') MVNW_USERNAME='' MVNW_PASSWORD='' ;; 188 | has-password) [ -n "${MVNW_USERNAME-}" ] || MVNW_USERNAME='' MVNW_PASSWORD='' ;; 189 | esac 190 | 191 | if [ -z "${MVNW_USERNAME-}" ] && command -v wget >/dev/null; then 192 | verbose "Found wget ... using wget" 193 | wget ${__MVNW_QUIET_WGET:+"$__MVNW_QUIET_WGET"} "$distributionUrl" -O "$TMP_DOWNLOAD_DIR/$distributionUrlName" || die "wget: Failed to fetch $distributionUrl" 194 | elif [ -z "${MVNW_USERNAME-}" ] && command -v curl >/dev/null; then 195 | verbose "Found curl ... using curl" 196 | curl ${__MVNW_QUIET_CURL:+"$__MVNW_QUIET_CURL"} -f -L -o "$TMP_DOWNLOAD_DIR/$distributionUrlName" "$distributionUrl" || die "curl: Failed to fetch $distributionUrl" 197 | elif set_java_home; then 198 | verbose "Falling back to use Java to download" 199 | javaSource="$TMP_DOWNLOAD_DIR/Downloader.java" 200 | targetZip="$TMP_DOWNLOAD_DIR/$distributionUrlName" 201 | cat >"$javaSource" <<-END 202 | public class Downloader extends java.net.Authenticator 203 | { 204 | protected java.net.PasswordAuthentication getPasswordAuthentication() 205 | { 206 | return new java.net.PasswordAuthentication( System.getenv( "MVNW_USERNAME" ), System.getenv( "MVNW_PASSWORD" ).toCharArray() ); 207 | } 208 | public static void main( String[] args ) throws Exception 209 | { 210 | setDefault( new Downloader() ); 211 | java.nio.file.Files.copy( java.net.URI.create( args[0] ).toURL().openStream(), java.nio.file.Paths.get( args[1] ).toAbsolutePath().normalize() ); 212 | } 213 | } 214 | END 215 | # For Cygwin/MinGW, switch paths to Windows format before running javac and java 216 | verbose " - Compiling Downloader.java ..." 217 | "$(native_path "$JAVACCMD")" "$(native_path "$javaSource")" || die "Failed to compile Downloader.java" 218 | verbose " - Running Downloader.java ..." 219 | "$(native_path "$JAVACMD")" -cp "$(native_path "$TMP_DOWNLOAD_DIR")" Downloader "$distributionUrl" "$(native_path "$targetZip")" 220 | fi 221 | 222 | # If specified, validate the SHA-256 sum of the Maven distribution zip file 223 | if [ -n "${distributionSha256Sum-}" ]; then 224 | distributionSha256Result=false 225 | if [ "$MVN_CMD" = mvnd.sh ]; then 226 | echo "Checksum validation is not supported for maven-mvnd." >&2 227 | echo "Please disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2 228 | exit 1 229 | elif command -v sha256sum >/dev/null; then 230 | if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | sha256sum -c >/dev/null 2>&1; then 231 | distributionSha256Result=true 232 | fi 233 | elif command -v shasum >/dev/null; then 234 | if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | shasum -a 256 -c >/dev/null 2>&1; then 235 | distributionSha256Result=true 236 | fi 237 | else 238 | echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." >&2 239 | echo "Please install either command, or disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2 240 | exit 1 241 | fi 242 | if [ $distributionSha256Result = false ]; then 243 | echo "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised." >&2 244 | echo "If you updated your Maven version, you need to update the specified distributionSha256Sum property." >&2 245 | exit 1 246 | fi 247 | fi 248 | 249 | # unzip and move 250 | if command -v unzip >/dev/null; then 251 | unzip ${__MVNW_QUIET_UNZIP:+"$__MVNW_QUIET_UNZIP"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -d "$TMP_DOWNLOAD_DIR" || die "failed to unzip" 252 | else 253 | tar xzf${__MVNW_QUIET_TAR:+"$__MVNW_QUIET_TAR"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -C "$TMP_DOWNLOAD_DIR" || die "failed to untar" 254 | fi 255 | printf %s\\n "$distributionUrl" >"$TMP_DOWNLOAD_DIR/$distributionUrlNameMain/mvnw.url" 256 | mv -- "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" "$MAVEN_HOME" || [ -d "$MAVEN_HOME" ] || die "fail to move MAVEN_HOME" 257 | 258 | clean || : 259 | exec_maven "$@" 260 | -------------------------------------------------------------------------------- /src/main/java/com/github/websend/Main.java: -------------------------------------------------------------------------------- 1 | package com.github.websend; 2 | 3 | import com.github.websend.post.POSTHandlerThreadPool; 4 | import com.github.websend.post.POSTRequest; 5 | import com.github.websend.script.ScriptManager; 6 | import com.github.websend.server.CommunicationServer; 7 | import com.github.websend.server.NonSecureCommunicationServer; 8 | import com.github.websend.server.PacketParser; 9 | import com.github.websend.server.SecureCommunicationServer; 10 | import java.io.File; 11 | import java.io.FileNotFoundException; 12 | import java.io.IOException; 13 | import java.net.URL; 14 | import java.util.List; 15 | import java.util.logging.Level; 16 | import java.util.logging.Logger; 17 | import org.bukkit.Bukkit; 18 | import org.bukkit.Server; 19 | import org.bukkit.command.BlockCommandSender; 20 | import org.bukkit.command.Command; 21 | import org.bukkit.command.CommandSender; 22 | import org.bukkit.command.ConsoleCommandSender; 23 | import org.bukkit.command.RemoteConsoleCommandSender; 24 | import org.bukkit.entity.Player; 25 | import org.bukkit.plugin.java.JavaPlugin; 26 | 27 | public class Main extends JavaPlugin { 28 | private static Settings settings; 29 | private static Logger logger; 30 | private static Server bukkitServer; 31 | private static Main plugin; 32 | private static File scriptsDir; 33 | private static int port; 34 | private static ScriptManager scriptManager; 35 | private static CommunicationServer server; 36 | private static POSTHandlerThreadPool requestThreadPool; 37 | 38 | @Override 39 | public void onEnable() { 40 | // Setup vars 41 | logger = this.getLogger(); 42 | bukkitServer = this.getServer(); 43 | plugin = this; 44 | port = this.getServer().getPort(); 45 | 46 | // Parse config 47 | ConfigHandler configHandler = new ConfigHandler(); 48 | try { 49 | settings = configHandler.loadSettings(); 50 | } catch (FileNotFoundException ex) { 51 | configHandler.generateConfig(); 52 | logger.info("Websend generated a config file. Go edit it!"); 53 | return; 54 | } catch (IOException ex) { 55 | logger.info("Websend failed to read your configuration file."); 56 | logger.log(Level.SEVERE, null, ex); 57 | this.getPluginLoader().disablePlugin(this); 58 | return; 59 | } 60 | 61 | Main.logDebugInfo("Loading trusted hosts list."); 62 | try { 63 | File trustedFile = new File(this.getDataFolder(), "trusted.txt"); 64 | if (!trustedFile.exists()) { 65 | TrustedHosts.writeDefaultFile(trustedFile); 66 | } 67 | TrustedHosts.load(trustedFile); 68 | } catch (IOException ex) { 69 | logger.log(Level.SEVERE, "Failed to load trusted hosts file", ex); 70 | } 71 | 72 | //Setup SSL keystore 73 | if(settings.isSSLEnabled()){ 74 | Main.logDebugInfo("Loading SSL settings."); 75 | if(settings.getSSLPassword() == null){ 76 | Main.logger.log(Level.WARNING, "SSL password is not set in configuration. Connections are INSECURE."); 77 | }else{ 78 | if(System.getProperty("javax.net.ssl.keyStore") != null){ 79 | Main.logger.log(Level.WARNING, "javax.net.ssl.keyStore is already set. " 80 | + "Websend will override it, but this may introduce unexpected behaviour in other plugins."); 81 | }else if(System.getProperty("javax.net.ssl.keyStorePassword") != null){ 82 | Main.logger.log(Level.WARNING, "javax.net.ssl.keyStorePassword is already set. " 83 | + "Websend will override it, but this may introduce unexpected behaviour in other plugins."); 84 | } 85 | try { 86 | File certFile = new File(this.getDataFolder(), "websendKeyStore"); 87 | if(certFile.exists()){ 88 | System.setProperty("javax.net.ssl.keyStore", certFile.getCanonicalPath()); 89 | System.setProperty("javax.net.ssl.keyStorePassword", settings.getSSLPassword()); 90 | }else{ 91 | Main.logger.log(Level.WARNING, "No SSL keystore found. Connections are INSECURE."); 92 | } 93 | } catch (IOException ex) { 94 | Main.logger.log(Level.WARNING, "Failed to set SSL keystore path. Connections are INSECURE.", ex); 95 | settings.setSSLEnabled(false); 96 | } 97 | } 98 | } 99 | 100 | //Setup webrequest thread pool 101 | Main.logDebugInfo("Loading POST handler pool."); 102 | requestThreadPool = new POSTHandlerThreadPool(); 103 | 104 | // Setup scripts 105 | Main.logDebugInfo("Loading scripts."); 106 | scriptsDir = new File(this.getDataFolder(), "scripts"); 107 | scriptManager = new ScriptManager(); 108 | if (scriptsDir.exists()) { 109 | scriptManager.loadScripts(); 110 | } else { 111 | if (!new File(scriptsDir, "compiled").mkdirs()) { 112 | Main.logger.log(Level.WARNING, "Failed to make scripts directory."); 113 | } 114 | } 115 | 116 | // Start server 117 | if (settings.isServerActive()) { 118 | if(settings.isSSLEnabled()){ 119 | Main.logDebugInfo("Loading secure webrequest server on port "+settings.getPort()+"."); 120 | server = new SecureCommunicationServer(); 121 | }else{ 122 | Main.logDebugInfo("Loading regular webrequest server on port "+settings.getPort()+"."); 123 | server = new NonSecureCommunicationServer(); 124 | } 125 | server.start(); 126 | } 127 | } 128 | 129 | @Override 130 | public void onDisable() { 131 | if (server != null) { 132 | server.stopServer(); 133 | } 134 | } 135 | 136 | public static void doCommand(String[] args, Player player) { 137 | POSTRequest request = new POSTRequest(Main.getSettings().getURL(), args, player, false); 138 | requestThreadPool.doRequest(request); 139 | } 140 | 141 | public static void doCommand(String[] args, String ply) { 142 | POSTRequest request = new POSTRequest(Main.getSettings().getURL(), args, ply, false); 143 | requestThreadPool.doRequest(request); 144 | } 145 | 146 | @Override 147 | public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) { 148 | if(!this.isEnabled()){ 149 | logger.log(Level.SEVERE, "Websend is disabled. Restart the server to run commands."); 150 | } else if (cmd.getName().equalsIgnoreCase("websend") || cmd.getName().equalsIgnoreCase("ws")) { 151 | URL url = Main.getSettings().getURL(); 152 | if (sender instanceof ConsoleCommandSender || sender instanceof RemoteConsoleCommandSender || sender instanceof BlockCommandSender) { 153 | POSTRequest request = new POSTRequest(url, args, "@Console", false); 154 | requestThreadPool.doRequest(request); 155 | return true; 156 | } else if (sender instanceof Player) { 157 | Player plsender = (Player) sender; 158 | // try{ 159 | if (plsender.hasPermission("websend")) { 160 | if (args.length > 0) { 161 | if (args[0].contains("-wp:")) { 162 | if (plsender.isOp()) { 163 | url = Main.getSettings().getURL(); 164 | } 165 | } 166 | } 167 | POSTRequest request = new POSTRequest(url, args, plsender, false); 168 | requestThreadPool.doRequest(request); 169 | return true; 170 | } else { 171 | plsender.sendMessage("You are not allowed to use this command."); 172 | } 173 | } 174 | } else if (cmd.getName().equalsIgnoreCase("wsScripts")) { 175 | if (sender.hasPermission("websend.scripts")) { 176 | if (args.length < 1) { 177 | sender.sendMessage(" /*/ Websend Scripts Menu /*/"); 178 | sender.sendMessage(" -wsScripts reload"); 179 | sender.sendMessage(" Reloads the scripts in the scripts folder."); 180 | sender.sendMessage(" -wsScripts reload "); 181 | sender.sendMessage(" Reloads the script."); 182 | sender.sendMessage(" -wsScripts list"); 183 | sender.sendMessage(" Lists the currently loaded scripts."); 184 | } else if (args[0].equals("reload")) { 185 | if (args.length < 2) { 186 | scriptManager.reload(); 187 | } else { 188 | scriptManager.reload(args[1]); 189 | } 190 | sender.sendMessage("Reload complete."); 191 | } else if (args[0].equals("list")) { 192 | sender.sendMessage("Currently loaded scripts:"); 193 | for (String string : scriptManager.getScriptNames()) { 194 | sender.sendMessage(" -" + string); 195 | } 196 | } else if (scriptManager.hasScript(args[0])) { 197 | scriptManager.invokeScript(args[0]); 198 | } else { 199 | sender.sendMessage("/wsscript " + args[0] + " does not exist."); 200 | } 201 | } else { 202 | sender.sendMessage("You are not allowed to use this command.('websend.scripts')"); 203 | } 204 | return true; 205 | } 206 | return false; 207 | } 208 | 209 | public void dispatchCommandAsync(Player player, String command, PacketParser.CommandCallback callback) { 210 | Bukkit.getScheduler().runTask(Main.getInstance(), () -> { 211 | boolean result = Main.getBukkitServer().dispatchCommand(player, command); 212 | callback.onCommandResult(result); // Pass the result to the callback 213 | }); 214 | } 215 | 216 | public static Server getBukkitServer() { 217 | return bukkitServer; 218 | } 219 | 220 | public static Main getInstance() { 221 | return plugin; 222 | } 223 | 224 | public static int getPort() { 225 | return port; 226 | } 227 | 228 | public static ScriptManager getScriptManager() { 229 | return scriptManager; 230 | } 231 | 232 | public static File getScriptsDir() { 233 | return scriptsDir; 234 | } 235 | 236 | public static CommunicationServer getCommunicationServer() { 237 | return server; 238 | } 239 | 240 | public static Settings getSettings() { 241 | return settings; 242 | } 243 | 244 | public static Logger getMainLogger() { 245 | return logger; 246 | } 247 | 248 | public static void logDebugInfo(String message) { 249 | logDebugInfo(Level.INFO, message); 250 | } 251 | 252 | public static void logDebugInfo(Level level, String message) { 253 | logDebugInfo(level, message, null); 254 | } 255 | 256 | public static void logDebugInfo(Level level, String message, Exception ex) { 257 | if (Main.getSettings() == null || Main.getSettings().isDebugMode()) { 258 | Main.getMainLogger().log(level, message, ex); 259 | } 260 | } 261 | 262 | public static void logError(String message, Exception ex) { 263 | Main.getMainLogger().log(Level.SEVERE, message, ex); 264 | } 265 | 266 | public List onTabComplete(CommandSender sender, Command command, String alias, String[] args) { 267 | return null; 268 | } 269 | } 270 | -------------------------------------------------------------------------------- /src/main/java/com/github/websend/CommandParser.java: -------------------------------------------------------------------------------- 1 | package com.github.websend; 2 | 3 | import java.util.logging.Level; 4 | import org.bukkit.Bukkit; 5 | import org.bukkit.ChatColor; 6 | import org.bukkit.Server; 7 | import org.bukkit.command.ConsoleCommandSender; 8 | import org.bukkit.entity.Player; 9 | import org.bukkit.plugin.Plugin; 10 | import org.json.JSONException; 11 | import org.json.JSONObject; 12 | 13 | public class CommandParser { 14 | 15 | Settings settings; 16 | Server server; 17 | 18 | public CommandParser() { 19 | settings = Main.getSettings(); 20 | server = Main.getBukkitServer(); 21 | } 22 | 23 | /** 24 | * @param line 25 | * @param player 26 | */ 27 | public void parse(String line, Player player) { 28 | // new version, do we have JSON? 29 | if (isJSONValid(line)) { 30 | JSONObject JSONobj = new JSONObject(line); 31 | 32 | String targetPlayer; 33 | // we put a couple of safeguards to make sure we have a valid player, otherwise the getString will fail 34 | // we will check if we have a valid player further down when it's actually used. 35 | if (!JSONobj.isNull("targetPlayer") && !JSONobj.getBoolean("targetPlayer")) { 36 | targetPlayer = JSONobj.getString("targetPlayer").trim(); 37 | } else { 38 | targetPlayer = null; 39 | } 40 | 41 | if (JSONobj.isNull("command")) { 42 | Main.getMainLogger().log(Level.SEVERE, "Websend: The 'command' component of the JSON is missing: " + line); 43 | return; 44 | } 45 | 46 | if (JSONobj.isNull("action")) { 47 | Main.getMainLogger().log(Level.SEVERE, "Websend ERROR: The 'action' component of the JSON is missing!" + line); 48 | return; 49 | } 50 | 51 | Main.logDebugInfo("Command parsing: Execute JSON commnad " + line); 52 | 53 | String action = JSONobj.getString("action").trim().toLowerCase(); 54 | String command = JSONobj.getString("command").trim(); 55 | 56 | switch (action) { 57 | case "executeplayercommand": 58 | onExecutePlayerCommand(player, command, targetPlayer); 59 | break; 60 | case "executeconsolecommand": 61 | onExecuteConsoleCommand(player, command); 62 | break; 63 | case "executescript": 64 | onExecuteScript(command); 65 | break; 66 | case "setresponseurl": 67 | onSetResponseURL(command); 68 | break; 69 | case "printtoconsole": 70 | onPrintToConsole(command); 71 | break; 72 | case "printtoplayer": 73 | onPrintToPlayer(command, player, targetPlayer); 74 | break; 75 | case "broadcast": 76 | onBroadcast(command); 77 | break; 78 | case "toggledebug": 79 | onToggleDebug(command); 80 | break; 81 | default: 82 | Main.getMainLogger().info("Websend ERROR: invalid action '" + action + "'. Valid Actions are (case-insensitive):"); 83 | Main.getMainLogger().info("'ExecutePlayerCommand','ExecuteConsoleCommand','ExecuteScript','SetResponseURL','PrintToConsole','PrintToPlayer','Broadcast','toggleDebug'"); 84 | break; 85 | } 86 | } else { 87 | Main.getMainLogger().info("Websend ERROR: The input format from PHP is not valid JSON: " + line); 88 | } 89 | } 90 | 91 | private void onSetResponseURL(String newURL) { 92 | Main.logDebugInfo("Command parsing: Changed ResponseURL to " + newURL); 93 | settings.setResponseURL(newURL); 94 | } 95 | 96 | private void onToggleDebug(String arg) { 97 | if (arg == null) { 98 | if (settings.isDebugMode()) { 99 | settings.setDebugMode(false); 100 | Main.getMainLogger().info("Debug mode is now OFF"); 101 | } else { 102 | settings.setDebugMode(true); 103 | Main.logDebugInfo("Debug mode is now ON"); 104 | } 105 | } else { 106 | if ("on".equals(arg)) { 107 | settings.setDebugMode(true); 108 | Main.logDebugInfo("Debug mode is now ON"); 109 | } else if ("off".equals(arg)) { 110 | settings.setDebugMode(false); 111 | Main.getMainLogger().info("Debug mode is now OFF"); 112 | } 113 | } 114 | } 115 | 116 | private void onExecutePlayerCommand(Player player, String command, String targetPlayer) { 117 | if (player == null) { 118 | Main.getMainLogger().info("Websend: ExecutePlayerCommand is used in a wrong context."); 119 | } 120 | Main.logDebugInfo("Command parsing: An ExecutePlayerCommand was found: '" + command + "'"); 121 | Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(Main.getInstance(), new Task(command, player, targetPlayer) { 122 | 123 | @Override 124 | public void run() { 125 | String command = (String) this.getArgs().get(0); 126 | Player player = (Player) this.getArgs().get(1); 127 | String targetPlayer = (String) this.getArgs().get(2); 128 | 129 | if (targetPlayer != null) { 130 | Player fakePlayer = Util.findPlayer(targetPlayer); 131 | if (!server.dispatchCommand(fakePlayer, command)) { // execute command and check for succes. 132 | Main.getMainLogger().info("Error executing onExecutePlayerCommand: Command dispatching failed: '" + command + "'"); // error 133 | } 134 | } else { 135 | try { 136 | if (player == null) { 137 | Main.getMainLogger().info("Error executing onExecutePlayerCommand: Command dispatching from terminal is not allowed. Try again in-game or set a targetplayer."); 138 | } else if (!player.getServer().dispatchCommand(player, command)) { // execute command and check for succes. 139 | player.sendMessage("Error executing onExecutePlayerCommand: Command dispatching failed: '" + command + "'"); // error 140 | } 141 | } catch (Exception ex) { 142 | Main.getMainLogger().info("Error executing onExecutePlayerCommand: Are you trying to execute a player command from console?"); 143 | } 144 | } 145 | } 146 | }); 147 | } 148 | 149 | private void onExecuteScript(String command) { 150 | Main.logDebugInfo("Command parsing: executing script: " + command); 151 | Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(Main.getInstance(), new Task(command) { 152 | @Override 153 | public void run() { 154 | Main.getScriptManager().invokeScript((String) this.getArgs().get(0)); 155 | } 156 | }); 157 | } 158 | 159 | private void onExecuteConsoleCommand(Player player, String command) { 160 | // split line into command and variables 161 | Main.logDebugInfo("Command parsing: An ExecuteConsoleCommand was found: '" + command + "'"); 162 | 163 | Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(Main.getInstance(), new Task(command, player) { 164 | @Override 165 | public void run() { 166 | String command = (String) this.getArgs().get(0); 167 | Player player = (Player) this.getArgs().get(1); 168 | ConsoleCommandSender ccs = server.getConsoleSender(); 169 | if (!server.dispatchCommand(ccs, command)) { // execute command and check for succes. 170 | if (player != null) { 171 | player.sendMessage("Command dispatching failed: '" + command + "'"); // error 172 | } else { 173 | Main.getMainLogger().info("Command dispatching failed: '" + command + "'"); // error 174 | } 175 | } 176 | } 177 | }); 178 | } 179 | 180 | private void onPrintToConsole(String line) { 181 | Main.logDebugInfo("Command parsing: printing text to console " + line); 182 | String text = line.replaceFirst("PrintToConsole:", ""); 183 | Main.getMainLogger().info(text); 184 | } 185 | 186 | private void onPrintToPlayer(String line, Player player, String targetPlayer) { 187 | Main.logDebugInfo("Command parsing: printing text to player " + line); 188 | if (player == null && targetPlayer == null) { 189 | Main.getMainLogger().log(Level.WARNING, "Websend: No player to print text to. Use the targetPlayer argument in JSON to sent text in this context."); 190 | Main.getMainLogger().log(Level.WARNING, line.replaceFirst("PrintToConsole:", "")); 191 | } else if (player != null) { 192 | String playerName = targetPlayer; 193 | String message = line; 194 | 195 | if ("console".equals(playerName)) { 196 | Main.logDebugInfo("Websend: sending to Player 'console'? Using PrintToConsole instead."); 197 | } else if (targetPlayer == null) { 198 | Main.getMainLogger().log(Level.WARNING, "Websend: No player '" + playerName + "' found on PrintToPlayer."); 199 | } else if (!player.isOnline()) { 200 | Main.logDebugInfo("Websend: Player '" + playerName + "' is offline. Ignoring PrintToPlayer"); 201 | } else { 202 | player.sendMessage(parseColor(message)); 203 | } 204 | String text = line.replaceFirst("PrintToPlayer:", ""); 205 | player.sendMessage(parseColor(text)); 206 | } else if (targetPlayer != null) { 207 | // this would be if a command is coming from external targeting a player 208 | 209 | } 210 | } 211 | 212 | private void onBroadcast(String line) { 213 | Main.logDebugInfo("Command parsing: Broadcasting text " + line); 214 | String text = line.replaceFirst("Broadcast:", ""); 215 | server.broadcastMessage(parseColor(text)); 216 | } 217 | 218 | public String parseColor(String line) { 219 | return ChatColor.translateAlternateColorCodes('&', line); 220 | } 221 | 222 | // check if JSon is valid 223 | // from https://stackoverflow.com/questions/10174898/how-to-check-whether-a-given-string-is-valid-json-in-java 224 | public boolean isJSONValid(String test) { 225 | try { 226 | new JSONObject(test); 227 | } catch (JSONException ex) { 228 | return false; 229 | } 230 | return true; 231 | } 232 | 233 | 234 | @SuppressWarnings("unused") 235 | private void onExecuteConsoleCommandAndReturn(String line) { 236 | // split line into command and variables 237 | String[] commandArray = line.split("ExecuteConsoleCommandAndReturn-"); 238 | Main.logDebugInfo("Command parsing: An ExecuteConsoleCommandAndReturn was found: '" + Util.stringArrayToString(commandArray) + "'"); 239 | Plugin plugin = null; 240 | if (commandArray[1].split(":")[0].toLowerCase().startsWith("bukkit")) { 241 | // TODO: implement bukkit listening. 242 | } else { 243 | plugin = server.getPluginManager().getPlugin(commandArray[1].split(":")[0]); 244 | if (plugin == null) { 245 | Main.getMainLogger().info("ERROR: An invalid plugin name was provided."); 246 | return; 247 | } 248 | // TODO: Implement or remove. 249 | } 250 | } 251 | 252 | @SuppressWarnings("unused") 253 | private void onExecutePlayerCommandAndReturn(String line) { 254 | String commandArray[]; 255 | // split line into command and variables 256 | commandArray = line.split("ExecutePlayerCommandAndReturn-"); 257 | Main.logDebugInfo("Command parsing: An ExecutePlayerCommandAndReturn was found: '" + Util.stringArrayToString(commandArray) + "'"); 258 | String argArray[] = commandArray[1].split("-"); 259 | Player fakePlayer = Util.findPlayer(argArray[0].trim()); 260 | String command = argArray[1].split(":")[1]; 261 | Plugin plugin = null; 262 | if (commandArray[1].split(":")[0].toLowerCase().startsWith("bukkit")) { 263 | // TODO: implement bukkit listening. 264 | } else { 265 | plugin = server.getPluginManager().getPlugin(commandArray[1].split(":")[0]); 266 | if (plugin == null) { 267 | Main.getMainLogger().info("ERROR: An invalid plugin name was provided."); 268 | return; 269 | } 270 | // TODO: Implement or remove. 271 | } 272 | } 273 | } 274 | -------------------------------------------------------------------------------- /src/main/java/com/github/websend/events/listener/EntityListener.java: -------------------------------------------------------------------------------- 1 | package com.github.websend.events.listener; 2 | 3 | import com.github.websend.Main; 4 | import com.github.websend.events.configuration.EntityEventsConfiguration; 5 | import org.bukkit.event.EventHandler; 6 | import org.bukkit.event.Listener; 7 | import org.bukkit.event.entity.*; 8 | 9 | public class EntityListener implements Listener { 10 | EntityEventsConfiguration config = null; 11 | 12 | public EntityListener(EntityEventsConfiguration config) { 13 | this.config = config; 14 | } 15 | 16 | @EventHandler 17 | public void onEvent(CreatureSpawnEvent e){ 18 | if(config.isEventEnabled(e.getEventName())){ 19 | String[] array = {"event", e.getEventName()}; 20 | Main.doCommand(array, "WEBSEND_EVENTS_ENTITY"); 21 | } 22 | } 23 | 24 | @EventHandler 25 | public void onEvent(CreeperPowerEvent e){ 26 | if(config.isEventEnabled(e.getEventName())){ 27 | String[] array = {"event", e.getEventName()}; 28 | Main.doCommand(array, "WEBSEND_EVENTS_ENTITY"); 29 | } 30 | } 31 | 32 | @EventHandler 33 | public void onEvent(EntityBreakDoorEvent e){ 34 | if(config.isEventEnabled(e.getEventName())){ 35 | String[] array = {"event", e.getEventName()}; 36 | Main.doCommand(array, "WEBSEND_EVENTS_ENTITY"); 37 | } 38 | } 39 | 40 | @EventHandler 41 | public void onEvent(EntityChangeBlockEvent e){ 42 | if(config.isEventEnabled(e.getEventName())){ 43 | String[] array = {"event", e.getEventName()}; 44 | Main.doCommand(array, "WEBSEND_EVENTS_ENTITY"); 45 | } 46 | } 47 | 48 | @EventHandler 49 | public void onEvent(EntityCombustByBlockEvent e){ 50 | if(config.isEventEnabled(e.getEventName())){ 51 | String[] array = {"event", e.getEventName()}; 52 | Main.doCommand(array, "WEBSEND_EVENTS_ENTITY"); 53 | } 54 | } 55 | 56 | @EventHandler 57 | public void onEvent(EntityCombustByEntityEvent e){ 58 | if(config.isEventEnabled(e.getEventName())){ 59 | String[] array = {"event", e.getEventName()}; 60 | Main.doCommand(array, "WEBSEND_EVENTS_ENTITY"); 61 | } 62 | } 63 | 64 | @EventHandler 65 | public void onEvent(EntityCombustEvent e){ 66 | if(config.isEventEnabled(e.getEventName())){ 67 | String[] array = {"event", e.getEventName()}; 68 | Main.doCommand(array, "WEBSEND_EVENTS_ENTITY"); 69 | } 70 | } 71 | 72 | @EventHandler 73 | public void onEvent(EntityCreatePortalEvent e){ 74 | if(config.isEventEnabled(e.getEventName())){ 75 | String[] array = {"event", e.getEventName()}; 76 | Main.doCommand(array, "WEBSEND_EVENTS_ENTITY"); 77 | } 78 | } 79 | 80 | @EventHandler 81 | public void onEvent(EntityDamageByBlockEvent e){ 82 | if(config.isEventEnabled(e.getEventName())){ 83 | String[] array = {"event", e.getEventName()}; 84 | Main.doCommand(array, "WEBSEND_EVENTS_ENTITY"); 85 | } 86 | } 87 | 88 | @EventHandler 89 | public void onEvent(EntityDamageByEntityEvent e){ 90 | if(config.isEventEnabled(e.getEventName())){ 91 | String[] array = {"event", e.getEventName()}; 92 | Main.doCommand(array, "WEBSEND_EVENTS_ENTITY"); 93 | } 94 | } 95 | 96 | @EventHandler 97 | public void onEvent(EntityDamageEvent e){ 98 | if(config.isEventEnabled(e.getEventName())){ 99 | String[] array = {"event", e.getEventName()}; 100 | Main.doCommand(array, "WEBSEND_EVENTS_ENTITY"); 101 | } 102 | } 103 | 104 | @EventHandler 105 | public void onEvent(EntityDeathEvent e){ 106 | if(config.isEventEnabled(e.getEventName())){ 107 | String[] array = {"event", e.getEventName()}; 108 | Main.doCommand(array, "WEBSEND_EVENTS_ENTITY"); 109 | } 110 | } 111 | 112 | @EventHandler 113 | public void onEvent(EntityExplodeEvent e){ 114 | if(config.isEventEnabled(e.getEventName())){ 115 | String[] array = {"event", e.getEventName()}; 116 | Main.doCommand(array, "WEBSEND_EVENTS_ENTITY"); 117 | } 118 | } 119 | 120 | @EventHandler 121 | public void onEvent(EntityInteractEvent e){ 122 | if(config.isEventEnabled(e.getEventName())){ 123 | String[] array = {"event", e.getEventName()}; 124 | Main.doCommand(array, "WEBSEND_EVENTS_ENTITY"); 125 | } 126 | } 127 | 128 | @EventHandler 129 | public void onEvent(EntityPortalEnterEvent e){ 130 | if(config.isEventEnabled(e.getEventName())){ 131 | String[] array = {"event", e.getEventName()}; 132 | Main.doCommand(array, "WEBSEND_EVENTS_ENTITY"); 133 | } 134 | } 135 | 136 | @EventHandler 137 | public void onEvent(EntityPortalEvent e){ 138 | if(config.isEventEnabled(e.getEventName())){ 139 | String[] array = {"event", e.getEventName()}; 140 | Main.doCommand(array, "WEBSEND_EVENTS_ENTITY"); 141 | } 142 | } 143 | 144 | @EventHandler 145 | public void onEvent(EntityPortalExitEvent e){ 146 | if(config.isEventEnabled(e.getEventName())){ 147 | String[] array = {"event", e.getEventName()}; 148 | Main.doCommand(array, "WEBSEND_EVENTS_ENTITY"); 149 | } 150 | } 151 | 152 | @EventHandler 153 | public void onEvent(EntityRegainHealthEvent e){ 154 | if(config.isEventEnabled(e.getEventName())){ 155 | String[] array = {"event", e.getEventName()}; 156 | Main.doCommand(array, "WEBSEND_EVENTS_ENTITY"); 157 | } 158 | } 159 | 160 | @EventHandler 161 | public void onEvent(EntityShootBowEvent e){ 162 | if(config.isEventEnabled(e.getEventName())){ 163 | String[] array = {"event", e.getEventName()}; 164 | Main.doCommand(array, "WEBSEND_EVENTS_ENTITY"); 165 | } 166 | } 167 | 168 | @EventHandler 169 | public void onEvent(EntityTameEvent e){ 170 | if(config.isEventEnabled(e.getEventName())){ 171 | String[] array = {"event", e.getEventName()}; 172 | Main.doCommand(array, "WEBSEND_EVENTS_ENTITY"); 173 | } 174 | } 175 | 176 | @EventHandler 177 | public void onEvent(EntityTargetEvent e){ 178 | if(config.isEventEnabled(e.getEventName())){ 179 | String[] array = {"event", e.getEventName()}; 180 | Main.doCommand(array, "WEBSEND_EVENTS_ENTITY"); 181 | } 182 | } 183 | 184 | @EventHandler 185 | public void onEvent(EntityTargetLivingEntityEvent e){ 186 | if(config.isEventEnabled(e.getEventName())){ 187 | String[] array = {"event", e.getEventName()}; 188 | Main.doCommand(array, "WEBSEND_EVENTS_ENTITY"); 189 | } 190 | } 191 | 192 | @EventHandler 193 | public void onEvent(EntityTeleportEvent e){ 194 | if(config.isEventEnabled(e.getEventName())){ 195 | String[] array = {"event", e.getEventName()}; 196 | Main.doCommand(array, "WEBSEND_EVENTS_ENTITY"); 197 | } 198 | } 199 | 200 | @EventHandler 201 | public void onEvent(EntityUnleashEvent e){ 202 | if(config.isEventEnabled(e.getEventName())){ 203 | String[] array = {"event", e.getEventName()}; 204 | Main.doCommand(array, "WEBSEND_EVENTS_ENTITY"); 205 | } 206 | } 207 | 208 | @EventHandler 209 | public void onEvent(ExpBottleEvent e){ 210 | if(config.isEventEnabled(e.getEventName())){ 211 | String[] array = {"event", e.getEventName()}; 212 | Main.doCommand(array, "WEBSEND_EVENTS_ENTITY"); 213 | } 214 | } 215 | 216 | @EventHandler 217 | public void onEvent(ExplosionPrimeEvent e){ 218 | if(config.isEventEnabled(e.getEventName())){ 219 | String[] array = {"event", e.getEventName()}; 220 | Main.doCommand(array, "WEBSEND_EVENTS_ENTITY"); 221 | } 222 | } 223 | 224 | @EventHandler 225 | public void onEvent(FireworkExplodeEvent e){ 226 | if(config.isEventEnabled(e.getEventName())){ 227 | String[] array = {"event", e.getEventName()}; 228 | Main.doCommand(array, "WEBSEND_EVENTS_ENTITY"); 229 | } 230 | } 231 | 232 | @EventHandler 233 | public void onEvent(FoodLevelChangeEvent e){ 234 | if(config.isEventEnabled(e.getEventName())){ 235 | String[] array = {"event", e.getEventName()}; 236 | Main.doCommand(array, "WEBSEND_EVENTS_ENTITY"); 237 | } 238 | } 239 | 240 | @EventHandler 241 | public void onEvent(HorseJumpEvent e){ 242 | if(config.isEventEnabled(e.getEventName())){ 243 | String[] array = {"event", e.getEventName()}; 244 | Main.doCommand(array, "WEBSEND_EVENTS_ENTITY"); 245 | } 246 | } 247 | 248 | @EventHandler 249 | public void onEvent(ItemDespawnEvent e){ 250 | if(config.isEventEnabled(e.getEventName())){ 251 | String[] array = {"event", e.getEventName()}; 252 | Main.doCommand(array, "WEBSEND_EVENTS_ENTITY"); 253 | } 254 | } 255 | 256 | @EventHandler 257 | public void onEvent(ItemMergeEvent e){ 258 | if(config.isEventEnabled(e.getEventName())){ 259 | String[] array = {"event", e.getEventName()}; 260 | Main.doCommand(array, "WEBSEND_EVENTS_ENTITY"); 261 | } 262 | } 263 | 264 | @EventHandler 265 | public void onEvent(ItemSpawnEvent e){ 266 | if(config.isEventEnabled(e.getEventName())){ 267 | String[] array = {"event", e.getEventName()}; 268 | Main.doCommand(array, "WEBSEND_EVENTS_ENTITY"); 269 | } 270 | } 271 | 272 | @EventHandler 273 | public void onEvent(PigZapEvent e){ 274 | if(config.isEventEnabled(e.getEventName())){ 275 | String[] array = {"event", e.getEventName()}; 276 | Main.doCommand(array, "WEBSEND_EVENTS_ENTITY"); 277 | } 278 | } 279 | 280 | @EventHandler 281 | public void onEvent(PlayerDeathEvent e){ 282 | if(config.isEventEnabled(e.getEventName())){ 283 | String[] array = {"event", e.getEventName()}; 284 | Main.doCommand(array, "WEBSEND_EVENTS_ENTITY"); 285 | } 286 | 287 | } 288 | @EventHandler 289 | public void onEvent(PlayerLeashEntityEvent e){ 290 | if(config.isEventEnabled(e.getEventName())){ 291 | String[] array = {"event", e.getEventName()}; 292 | Main.doCommand(array, "WEBSEND_EVENTS_ENTITY"); 293 | } 294 | } 295 | 296 | @EventHandler 297 | public void onEvent(PotionSplashEvent e){ 298 | if(config.isEventEnabled(e.getEventName())){ 299 | String[] array = {"event", e.getEventName()}; 300 | Main.doCommand(array, "WEBSEND_EVENTS_ENTITY"); 301 | } 302 | } 303 | 304 | @EventHandler 305 | public void onEvent(ProjectileHitEvent e){ 306 | if(config.isEventEnabled(e.getEventName())){ 307 | String[] array = {"event", e.getEventName()}; 308 | Main.doCommand(array, "WEBSEND_EVENTS_ENTITY"); 309 | } 310 | } 311 | 312 | @EventHandler 313 | public void onEvent(ProjectileLaunchEvent e){ 314 | if(config.isEventEnabled(e.getEventName())){ 315 | String[] array = {"event", e.getEventName()}; 316 | Main.doCommand(array, "WEBSEND_EVENTS_ENTITY"); 317 | } 318 | } 319 | 320 | @EventHandler 321 | public void onEvent(SheepDyeWoolEvent e){ 322 | if(config.isEventEnabled(e.getEventName())){ 323 | String[] array = {"event", e.getEventName()}; 324 | Main.doCommand(array, "WEBSEND_EVENTS_ENTITY"); 325 | } 326 | } 327 | 328 | @EventHandler 329 | public void onEvent(SheepRegrowWoolEvent e){ 330 | if(config.isEventEnabled(e.getEventName())){ 331 | String[] array = {"event", e.getEventName()}; 332 | Main.doCommand(array, "WEBSEND_EVENTS_ENTITY"); 333 | } 334 | } 335 | 336 | @EventHandler 337 | public void onEvent(SlimeSplitEvent e){ 338 | if(config.isEventEnabled(e.getEventName())){ 339 | String[] array = {"event", e.getEventName()}; 340 | Main.doCommand(array, "WEBSEND_EVENTS_ENTITY"); 341 | } 342 | } 343 | 344 | @EventHandler 345 | public void onEvent(VillagerAcquireTradeEvent e){ 346 | if(config.isEventEnabled(e.getEventName())){ 347 | String[] array = {"event", e.getEventName()}; 348 | Main.doCommand(array, "WEBSEND_EVENTS_ENTITY"); 349 | } 350 | } 351 | 352 | @EventHandler 353 | public void onEvent(VillagerReplenishTradeEvent e){ 354 | if(config.isEventEnabled(e.getEventName())){ 355 | String[] array = {"event", e.getEventName()}; 356 | Main.doCommand(array, "WEBSEND_EVENTS_ENTITY"); 357 | } 358 | } 359 | } 360 | --------------------------------------------------------------------------------