2014-04-03 03:03:52 +00:00
/ *
2014-04-04 22:03:18 +00:00
* WorldEdit , a Minecraft world manipulation toolkit
* Copyright ( C ) sk89q < http : //www.sk89q.com>
* Copyright ( C ) WorldEdit team and contributors
2014-04-03 03:03:52 +00:00
*
2014-04-04 22:03:18 +00:00
* This program is free software : you can redistribute it and / or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation , either version 3 of the License , or
2014-04-03 03:03:52 +00:00
* ( at your option ) any later version .
*
2014-04-04 22:03:18 +00:00
* This program is distributed in the hope that it will be useful , but WITHOUT
* ANY WARRANTY ; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE . See the GNU Lesser General Public License
* for more details .
2014-04-03 03:03:52 +00:00
*
2014-04-04 22:03:18 +00:00
* You should have received a copy of the GNU Lesser General Public License
2014-04-03 03:03:52 +00:00
* along with this program . If not , see < http : //www.gnu.org/licenses/>.
2014-04-04 22:03:18 +00:00
* /
2014-04-03 03:03:52 +00:00
package com.sk89q.worldedit.bukkit ;
2014-06-28 23:30:02 +00:00
import com.google.common.base.Joiner ;
2014-04-03 03:03:52 +00:00
import com.sk89q.util.yaml.YAMLProcessor ;
import com.sk89q.wepif.PermissionsResolverManager ;
2014-07-14 19:10:38 +00:00
import com.sk89q.worldedit.EditSession ;
import com.sk89q.worldedit.LocalSession ;
import com.sk89q.worldedit.WorldEdit ;
import com.sk89q.worldedit.bukkit.adapter.AdapterLoadException ;
import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter ;
import com.sk89q.worldedit.bukkit.adapter.BukkitImplLoader ;
2014-06-28 00:55:39 +00:00
import com.sk89q.worldedit.event.platform.CommandEvent ;
2014-06-28 23:30:02 +00:00
import com.sk89q.worldedit.event.platform.CommandSuggestionEvent ;
2014-06-27 08:11:35 +00:00
import com.sk89q.worldedit.event.platform.PlatformReadyEvent ;
2019-02-16 09:35:13 +00:00
import com.sk89q.worldedit.extension.input.InputParseException ;
import com.sk89q.worldedit.extension.input.ParserContext ;
2014-06-28 00:55:39 +00:00
import com.sk89q.worldedit.extension.platform.Actor ;
2014-07-19 00:37:03 +00:00
import com.sk89q.worldedit.extension.platform.Capability ;
import com.sk89q.worldedit.extension.platform.Platform ;
2014-04-03 03:03:52 +00:00
import com.sk89q.worldedit.extent.inventory.BlockBag ;
2019-02-16 09:35:13 +00:00
import com.sk89q.worldedit.registry.state.Property ;
import com.sk89q.worldedit.world.biome.BiomeType ;
2019-02-17 03:30:40 +00:00
import com.sk89q.worldedit.world.block.BlockCategory ;
2019-02-16 09:35:13 +00:00
import com.sk89q.worldedit.world.block.BlockState ;
import com.sk89q.worldedit.world.block.BlockType ;
import com.sk89q.worldedit.world.block.FuzzyBlockState ;
import com.sk89q.worldedit.world.entity.EntityType ;
2019-02-17 03:30:40 +00:00
import com.sk89q.worldedit.world.item.ItemCategory ;
2019-02-16 09:35:13 +00:00
import com.sk89q.worldedit.world.item.ItemType ;
2018-09-20 12:59:42 +00:00
import org.bstats.bukkit.Metrics ;
2019-02-17 03:30:40 +00:00
import org.bukkit.Bukkit ;
2019-02-16 09:35:13 +00:00
import org.bukkit.Material ;
2019-02-17 03:30:40 +00:00
import org.bukkit.Tag ;
2019-02-16 09:35:13 +00:00
import org.bukkit.block.Biome ;
2014-06-28 23:30:02 +00:00
import org.bukkit.command.Command ;
2014-04-03 03:03:52 +00:00
import org.bukkit.command.CommandSender ;
2014-06-28 23:30:02 +00:00
import org.bukkit.command.TabCompleter ;
2014-04-03 03:03:52 +00:00
import org.bukkit.entity.Player ;
import org.bukkit.plugin.java.JavaPlugin ;
2019-03-14 02:51:48 +00:00
import org.slf4j.Logger ;
import org.slf4j.LoggerFactory ;
2014-04-03 03:03:52 +00:00
2019-03-14 02:51:48 +00:00
import javax.annotation.Nullable ;
2014-07-14 19:10:38 +00:00
import java.io.File ;
import java.io.FileNotFoundException ;
import java.io.FileOutputStream ;
import java.io.IOException ;
import java.io.InputStream ;
2014-06-28 23:30:02 +00:00
import java.util.List ;
2019-02-16 09:35:13 +00:00
import java.util.Map ;
2014-04-03 03:03:52 +00:00
import java.util.jar.JarFile ;
2014-07-14 19:10:38 +00:00
import java.util.logging.Level ;
2014-04-03 03:03:52 +00:00
import java.util.zip.ZipEntry ;
2019-03-14 02:51:48 +00:00
import static com.google.common.base.Preconditions.checkNotNull ;
2014-07-14 19:10:38 +00:00
2014-04-03 03:03:52 +00:00
/ * *
* Plugin for Bukkit .
* /
2014-06-28 23:30:02 +00:00
public class WorldEditPlugin extends JavaPlugin implements TabCompleter {
2014-04-03 03:03:52 +00:00
2019-03-14 02:51:48 +00:00
private static final Logger log = LoggerFactory . getLogger ( WorldEditPlugin . class ) ;
2018-07-12 12:23:03 +00:00
public static final String CUI_PLUGIN_CHANNEL = " worldedit:cui " ;
2014-07-14 19:10:38 +00:00
private static WorldEditPlugin INSTANCE ;
2014-04-03 03:03:52 +00:00
2014-07-14 19:10:38 +00:00
private BukkitImplAdapter bukkitAdapter ;
2014-04-03 03:03:52 +00:00
private BukkitServerInterface server ;
private BukkitConfiguration config ;
@Override
2019-03-15 22:20:12 +00:00
public void onLoad ( ) {
INSTANCE = this ;
2014-04-03 03:03:52 +00:00
2014-07-29 18:04:04 +00:00
//noinspection ResultOfMethodCallIgnored
2014-07-18 23:47:57 +00:00
getDataFolder ( ) . mkdirs ( ) ;
2014-07-14 19:10:38 +00:00
WorldEdit worldEdit = WorldEdit . getInstance ( ) ;
2014-04-03 03:03:52 +00:00
2014-07-14 19:10:38 +00:00
// Setup platform
2014-04-03 03:03:52 +00:00
server = new BukkitServerInterface ( this , getServer ( ) ) ;
2014-07-14 19:10:38 +00:00
worldEdit . getPlatformManager ( ) . register ( server ) ;
2018-08-26 19:34:33 +00:00
loadAdapter ( ) ; // Need an adapter to work with special blocks with NBT data
2019-02-16 09:35:13 +00:00
setupRegistries ( ) ;
2018-07-17 14:42:09 +00:00
worldEdit . loadMappings ( ) ;
loadConfig ( ) ; // Load configuration
2019-03-15 22:20:12 +00:00
}
/ * *
* Called on plugin enable .
* /
@Override
public void onEnable ( ) {
2019-03-16 02:38:38 +00:00
setupTags ( ) ; // these have to be done post-world since they rely on MC registries. the other ones just use Bukkit enums
2018-07-17 14:42:09 +00:00
PermissionsResolverManager . initialize ( this ) ; // Setup permission resolver
2014-07-14 19:10:38 +00:00
// Register CUI
2014-06-27 08:11:35 +00:00
getServer ( ) . getMessenger ( ) . registerIncomingPluginChannel ( this , CUI_PLUGIN_CHANNEL , new CUIChannelListener ( this ) ) ;
getServer ( ) . getMessenger ( ) . registerOutgoingPluginChannel ( this , CUI_PLUGIN_CHANNEL ) ;
2014-07-14 19:10:38 +00:00
// Now we can register events
2014-06-27 08:11:35 +00:00
getServer ( ) . getPluginManager ( ) . registerEvents ( new WorldEditListener ( this ) , this ) ;
// If we are on MCPC+/Cauldron, then Forge will have already loaded
// Forge WorldEdit and there's (probably) not going to be any other
// platforms to be worried about... at the current time of writing
WorldEdit . getInstance ( ) . getEventBus ( ) . post ( new PlatformReadyEvent ( ) ) ;
2018-09-20 12:59:42 +00:00
// Enable metrics
new Metrics ( this ) ;
2014-04-03 03:03:52 +00:00
}
2019-02-16 09:35:13 +00:00
public void setupRegistries ( ) {
// Biome
for ( Biome biome : Biome . values ( ) ) {
BiomeType . REGISTRY . register ( " minecraft: " + biome . name ( ) . toLowerCase ( ) , new BiomeType ( " minecraft: " + biome . name ( ) . toLowerCase ( ) ) ) ;
}
// Block & Item
for ( Material material : Material . values ( ) ) {
2019-02-25 23:15:26 +00:00
if ( material . isBlock ( ) & & ! material . isLegacy ( ) ) {
2019-02-16 09:35:13 +00:00
BlockType . REGISTRY . register ( material . getKey ( ) . toString ( ) , new BlockType ( material . getKey ( ) . toString ( ) , blockState - > {
// TODO Use something way less hacky than this.
ParserContext context = new ParserContext ( ) ;
context . setPreferringWildcard ( true ) ;
context . setTryLegacy ( false ) ;
context . setRestricted ( false ) ;
try {
FuzzyBlockState state = ( FuzzyBlockState ) WorldEdit . getInstance ( ) . getBlockFactory ( ) . parseFromInput (
BukkitAdapter . adapt ( blockState . getBlockType ( ) ) . createBlockData ( ) . getAsString ( ) , context
) . toImmutableState ( ) ;
BlockState defaultState = blockState . getBlockType ( ) . getAllStates ( ) . get ( 0 ) ;
for ( Map . Entry < Property < ? > , Object > propertyObjectEntry : state . getStates ( ) . entrySet ( ) ) {
defaultState = defaultState . with ( ( Property ) propertyObjectEntry . getKey ( ) , propertyObjectEntry . getValue ( ) ) ;
}
return defaultState ;
} catch ( InputParseException e ) {
e . printStackTrace ( ) ;
return blockState ;
}
} ) ) ;
}
2019-02-25 23:15:26 +00:00
if ( material . isItem ( ) & & ! material . isLegacy ( ) ) {
2019-02-16 09:35:13 +00:00
ItemType . REGISTRY . register ( material . getKey ( ) . toString ( ) , new ItemType ( material . getKey ( ) . toString ( ) ) ) ;
}
}
// Entity
for ( org . bukkit . entity . EntityType entityType : org . bukkit . entity . EntityType . values ( ) ) {
2019-03-08 21:00:42 +00:00
String mcid = entityType . getName ( ) ;
if ( mcid ! = null ) {
EntityType . REGISTRY . register ( " minecraft: " + mcid . toLowerCase ( ) , new EntityType ( " minecraft: " + mcid . toLowerCase ( ) ) ) ;
}
2019-02-16 09:35:13 +00:00
}
2019-03-16 02:38:38 +00:00
}
private void setupTags ( ) {
2019-02-17 03:30:40 +00:00
// Tags
try {
2019-03-16 02:38:38 +00:00
for ( Tag < Material > blockTag : Bukkit . getTags ( Tag . REGISTRY_BLOCKS , Material . class ) ) {
2019-02-17 03:30:40 +00:00
BlockCategory . REGISTRY . register ( blockTag . getKey ( ) . toString ( ) , new BlockCategory ( blockTag . getKey ( ) . toString ( ) ) ) ;
}
2019-03-16 02:38:38 +00:00
for ( Tag < Material > itemTag : Bukkit . getTags ( Tag . REGISTRY_ITEMS , Material . class ) ) {
2019-02-17 03:30:40 +00:00
ItemCategory . REGISTRY . register ( itemTag . getKey ( ) . toString ( ) , new ItemCategory ( itemTag . getKey ( ) . toString ( ) ) ) ;
}
} catch ( NoSuchMethodError e ) {
getLogger ( ) . warning ( " The version of Spigot/Paper you are using doesn't support Tags. The usage of tags with WorldEdit will not work until you update. " ) ;
}
2019-02-16 09:35:13 +00:00
}
2014-07-14 19:10:38 +00:00
private void loadConfig ( ) {
createDefaultConfiguration ( " config.yml " ) ; // Create the default configuration file
config = new BukkitConfiguration ( new YAMLProcessor ( new File ( getDataFolder ( ) , " config.yml " ) , true ) , this ) ;
config . load ( ) ;
}
private void loadAdapter ( ) {
2014-07-19 00:37:03 +00:00
WorldEdit worldEdit = WorldEdit . getInstance ( ) ;
2014-07-14 19:10:38 +00:00
// Attempt to load a Bukkit adapter
BukkitImplLoader adapterLoader = new BukkitImplLoader ( ) ;
2014-04-03 03:03:52 +00:00
try {
2014-07-14 19:10:38 +00:00
adapterLoader . addFromPath ( getClass ( ) . getClassLoader ( ) ) ;
} catch ( IOException e ) {
2019-03-14 02:51:48 +00:00
log . warn ( " Failed to search path for Bukkit adapters " ) ;
2014-07-14 19:10:38 +00:00
}
try {
adapterLoader . addFromJar ( getFile ( ) ) ;
} catch ( IOException e ) {
2019-03-14 02:51:48 +00:00
log . warn ( " Failed to search " + getFile ( ) + " for Bukkit adapters " , e ) ;
2014-07-14 19:10:38 +00:00
}
try {
bukkitAdapter = adapterLoader . loadAdapter ( ) ;
2019-03-14 02:51:48 +00:00
log . info ( " Using " + bukkitAdapter . getClass ( ) . getCanonicalName ( ) + " as the Bukkit adapter " ) ;
2014-07-14 19:10:38 +00:00
} catch ( AdapterLoadException e ) {
2014-07-19 00:37:03 +00:00
Platform platform = worldEdit . getPlatformManager ( ) . queryCapability ( Capability . WORLD_EDITING ) ;
if ( platform instanceof BukkitServerInterface ) {
2019-03-14 02:51:48 +00:00
log . warn ( e . getMessage ( ) ) ;
2014-07-19 00:37:03 +00:00
} else {
2019-03-14 02:51:48 +00:00
log . info ( " WorldEdit could not find a Bukkit adapter for this MC version, " +
2014-07-19 00:37:03 +00:00
" but it seems that you have another implementation of WorldEdit installed ( " + platform . getPlatformName ( ) + " ) " +
" that handles the world editing. " ) ;
}
2014-07-14 19:10:38 +00:00
}
2014-04-03 03:03:52 +00:00
}
/ * *
* Called on plugin disable .
* /
@Override
public void onDisable ( ) {
2014-07-14 19:10:38 +00:00
WorldEdit worldEdit = WorldEdit . getInstance ( ) ;
2018-08-19 03:01:08 +00:00
worldEdit . getSessionManager ( ) . unload ( ) ;
2014-07-14 19:10:38 +00:00
worldEdit . getPlatformManager ( ) . unregister ( server ) ;
if ( config ! = null ) {
2014-06-29 08:43:30 +00:00
config . unload ( ) ;
2014-07-14 19:10:38 +00:00
}
if ( server ! = null ) {
2014-06-29 08:43:30 +00:00
server . unregisterCommands ( ) ;
}
2014-04-03 03:03:52 +00:00
this . getServer ( ) . getScheduler ( ) . cancelTasks ( this ) ;
}
/ * *
* Loads and reloads all configuration .
* /
protected void loadConfiguration ( ) {
config . unload ( ) ;
config . load ( ) ;
getPermissionsResolver ( ) . load ( ) ;
}
/ * *
* Create a default configuration file from the . jar .
*
2014-07-14 19:10:38 +00:00
* @param name the filename
2014-04-03 03:03:52 +00:00
* /
protected void createDefaultConfiguration ( String name ) {
File actual = new File ( getDataFolder ( ) , name ) ;
if ( ! actual . exists ( ) ) {
2018-12-27 00:50:24 +00:00
try ( JarFile file = new JarFile ( getFile ( ) ) ) {
2014-04-03 03:03:52 +00:00
ZipEntry copy = file . getEntry ( " defaults/ " + name ) ;
if ( copy = = null ) throw new FileNotFoundException ( ) ;
2018-12-27 00:50:24 +00:00
copyDefaultConfig ( file . getInputStream ( copy ) , actual , name ) ;
2014-04-03 03:03:52 +00:00
} catch ( IOException e ) {
getLogger ( ) . severe ( " Unable to read default configuration: " + name ) ;
}
2018-12-27 00:50:24 +00:00
}
}
private void copyDefaultConfig ( InputStream input , File actual , String name ) {
try ( FileOutputStream output = new FileOutputStream ( actual ) ) {
byte [ ] buf = new byte [ 8192 ] ;
int length ;
while ( ( length = input . read ( buf ) ) > 0 ) {
output . write ( buf , 0 , length ) ;
2014-04-03 03:03:52 +00:00
}
2018-12-27 00:50:24 +00:00
getLogger ( ) . info ( " Default configuration file written: " + name ) ;
} catch ( IOException e ) {
getLogger ( ) . log ( Level . WARNING , " Failed to write default config file " , e ) ;
2014-04-03 03:03:52 +00:00
}
}
@Override
2014-06-28 23:30:02 +00:00
public boolean onCommand ( CommandSender sender , Command cmd , String commandLabel , String [ ] args ) {
2014-04-03 03:03:52 +00:00
// Add the command to the array because the underlying command handling
// code of WorldEdit expects it
String [ ] split = new String [ args . length + 1 ] ;
System . arraycopy ( args , 0 , split , 1 , args . length ) ;
2019-04-29 21:39:30 +00:00
split [ 0 ] = " / " + cmd . getName ( ) ;
2014-04-03 03:03:52 +00:00
2014-06-28 23:30:02 +00:00
CommandEvent event = new CommandEvent ( wrapCommandSender ( sender ) , Joiner . on ( " " ) . join ( split ) ) ;
2014-06-28 00:55:39 +00:00
getWorldEdit ( ) . getEventBus ( ) . post ( event ) ;
2014-04-03 03:03:52 +00:00
return true ;
}
2014-06-28 23:30:02 +00:00
@Override
public List < String > onTabComplete ( CommandSender sender , Command cmd , String commandLabel , String [ ] args ) {
// Add the command to the array because the underlying command handling
// code of WorldEdit expects it
String [ ] split = new String [ args . length + 1 ] ;
System . arraycopy ( args , 0 , split , 1 , args . length ) ;
2019-04-29 21:39:30 +00:00
split [ 0 ] = " / " + cmd . getName ( ) ;
2014-06-28 23:30:02 +00:00
CommandSuggestionEvent event = new CommandSuggestionEvent ( wrapCommandSender ( sender ) , Joiner . on ( " " ) . join ( split ) ) ;
getWorldEdit ( ) . getEventBus ( ) . post ( event ) ;
return event . getSuggestions ( ) ;
}
2014-04-03 03:03:52 +00:00
/ * *
* Gets the session for the player .
*
2014-07-29 18:04:04 +00:00
* @param player a player
* @return a session
2014-04-03 03:03:52 +00:00
* /
public LocalSession getSession ( Player player ) {
2018-06-16 06:36:55 +00:00
return WorldEdit . getInstance ( ) . getSessionManager ( ) . get ( wrapPlayer ( player ) ) ;
2014-04-03 03:03:52 +00:00
}
/ * *
* Gets the session for the player .
*
2014-07-29 18:04:04 +00:00
* @param player a player
* @return a session
2014-04-03 03:03:52 +00:00
* /
public EditSession createEditSession ( Player player ) {
2018-06-16 05:29:48 +00:00
com . sk89q . worldedit . entity . Player wePlayer = wrapPlayer ( player ) ;
LocalSession session = WorldEdit . getInstance ( ) . getSessionManager ( ) . get ( wePlayer ) ;
2014-04-03 03:03:52 +00:00
BlockBag blockBag = session . getBlockBag ( wePlayer ) ;
2014-07-14 19:10:38 +00:00
EditSession editSession = WorldEdit . getInstance ( ) . getEditSessionFactory ( )
2014-04-03 03:03:52 +00:00
. getEditSession ( wePlayer . getWorld ( ) , session . getBlockChangeLimit ( ) , blockBag , wePlayer ) ;
2018-10-04 17:37:58 +00:00
editSession . enableStandardMode ( ) ;
2014-04-03 03:03:52 +00:00
return editSession ;
}
/ * *
* Remember an edit session .
*
2014-07-29 18:04:04 +00:00
* @param player a player
* @param editSession an edit session
2014-04-03 03:03:52 +00:00
* /
public void remember ( Player player , EditSession editSession ) {
2018-06-16 05:29:48 +00:00
com . sk89q . worldedit . entity . Player wePlayer = wrapPlayer ( player ) ;
LocalSession session = WorldEdit . getInstance ( ) . getSessionManager ( ) . get ( wePlayer ) ;
2014-04-03 03:03:52 +00:00
session . remember ( editSession ) ;
2018-10-21 01:54:58 +00:00
editSession . flushSession ( ) ;
2014-04-03 03:03:52 +00:00
2014-07-14 19:10:38 +00:00
WorldEdit . getInstance ( ) . flushBlockBag ( wePlayer , editSession ) ;
2014-04-03 03:03:52 +00:00
}
/ * *
* Returns the configuration used by WorldEdit .
*
2014-07-29 18:04:04 +00:00
* @return the configuration
2014-04-03 03:03:52 +00:00
* /
public BukkitConfiguration getLocalConfiguration ( ) {
return config ;
}
/ * *
* Get the permissions resolver in use .
*
2014-07-29 18:04:04 +00:00
* @return the permissions resolver
2014-04-03 03:03:52 +00:00
* /
public PermissionsResolverManager getPermissionsResolver ( ) {
return PermissionsResolverManager . getInstance ( ) ;
}
/ * *
2018-06-16 05:29:48 +00:00
* Used to wrap a Bukkit Player as a WorldEdit Player .
2014-04-03 03:03:52 +00:00
*
2014-07-29 18:04:04 +00:00
* @param player a player
* @return a wrapped player
2014-04-03 03:03:52 +00:00
* /
public BukkitPlayer wrapPlayer ( Player player ) {
2018-06-16 05:29:48 +00:00
return new BukkitPlayer ( this , player ) ;
2014-04-03 03:03:52 +00:00
}
2014-06-28 00:55:39 +00:00
public Actor wrapCommandSender ( CommandSender sender ) {
2014-04-03 03:03:52 +00:00
if ( sender instanceof Player ) {
return wrapPlayer ( ( Player ) sender ) ;
}
2014-06-27 20:14:44 +00:00
return new BukkitCommandSender ( this , sender ) ;
2014-04-03 03:03:52 +00:00
}
2014-06-27 08:11:35 +00:00
BukkitServerInterface getInternalPlatform ( ) {
return server ;
}
2014-04-03 03:03:52 +00:00
/ * *
* Get WorldEdit .
*
2014-07-29 18:04:04 +00:00
* @return an instance
2014-04-03 03:03:52 +00:00
* /
public WorldEdit getWorldEdit ( ) {
2014-07-14 19:10:38 +00:00
return WorldEdit . getInstance ( ) ;
2014-04-03 03:03:52 +00:00
}
2014-07-14 19:10:38 +00:00
/ * *
* Gets the instance of this plugin .
*
* @return an instance of the plugin
* @throws NullPointerException if the plugin hasn ' t been enabled
* /
static WorldEditPlugin getInstance ( ) {
return checkNotNull ( INSTANCE ) ;
}
/ * *
* Get the Bukkit implementation adapter .
*
* @return the adapter
* /
@Nullable
BukkitImplAdapter getBukkitImplAdapter ( ) {
return bukkitAdapter ;
}
2014-04-03 03:03:52 +00:00
}