2012-03-28 18:05: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
2012-03-28 18:05: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
2012-03-28 18:05: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 .
2012-03-28 18:05:52 +00:00
*
2014-04-04 22:03:18 +00:00
* You should have received a copy of the GNU Lesser General Public License
2012-03-28 18:05:52 +00:00
* along with this program . If not , see < http : //www.gnu.org/licenses/>.
* /
2014-04-03 02:08:50 +00:00
package com.sk89q.worldedit.command ;
2012-03-28 18:05:52 +00:00
2019-10-23 16:58:36 +00:00
import static com.boydti.fawe.util.ReflectionUtils.as ;
import static com.google.common.base.Preconditions.checkNotNull ;
2019-12-16 09:01:41 +00:00
import com.boydti.fawe.config.Caption ;
2019-11-21 19:56:10 +00:00
import com.sk89q.worldedit.util.formatting.text.TranslatableComponent ;
2018-08-12 14:03:07 +00:00
import com.boydti.fawe.config.Settings ;
import com.boydti.fawe.object.clipboard.MultiClipboardHolder ;
import com.boydti.fawe.object.clipboard.URIClipboardHolder ;
2019-07-20 05:32:15 +00:00
import com.boydti.fawe.object.schematic.MinecraftStructure ;
2018-08-12 14:03:07 +00:00
import com.boydti.fawe.util.MainUtil ;
2019-10-23 14:35:04 +00:00
import com.boydti.fawe.util.MathMan ;
import com.google.common.base.Function ;
2019-09-14 03:05:16 +00:00
import com.google.common.collect.Multimap ;
2014-06-30 00:47:08 +00:00
import com.sk89q.worldedit.LocalConfiguration ;
import com.sk89q.worldedit.LocalSession ;
import com.sk89q.worldedit.WorldEdit ;
import com.sk89q.worldedit.WorldEditException ;
2019-10-23 14:35:04 +00:00
import com.sk89q.worldedit.command.argument.Arguments ;
2019-07-23 02:22:32 +00:00
import com.sk89q.worldedit.command.util.AsyncCommandBuilder ;
2019-07-06 00:46:48 +00:00
import com.sk89q.worldedit.command.util.CommandPermissions ;
import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator ;
2014-06-28 08:01:49 +00:00
import com.sk89q.worldedit.entity.Player ;
2019-08-10 06:01:42 +00:00
import com.sk89q.worldedit.event.extent.ActorSaveClipboardEvent ;
2014-06-28 00:55:39 +00:00
import com.sk89q.worldedit.extension.platform.Actor ;
2014-07-10 05:04:17 +00:00
import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard ;
2014-07-10 04:08:34 +00:00
import com.sk89q.worldedit.extent.clipboard.Clipboard ;
import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormat ;
2018-08-16 16:55:41 +00:00
import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormats ;
2019-07-06 00:46:48 +00:00
import com.sk89q.worldedit.extent.clipboard.io.ClipboardReader ;
2014-07-10 04:08:34 +00:00
import com.sk89q.worldedit.extent.clipboard.io.ClipboardWriter ;
2014-07-10 05:04:17 +00:00
import com.sk89q.worldedit.function.operation.Operations ;
import com.sk89q.worldedit.math.transform.Transform ;
2014-07-10 04:08:34 +00:00
import com.sk89q.worldedit.session.ClipboardHolder ;
2019-07-06 00:46:48 +00:00
import com.sk89q.worldedit.util.formatting.component.ErrorFormat ;
import com.sk89q.worldedit.util.formatting.component.PaginationBox ;
2019-10-23 15:44:36 +00:00
import com.sk89q.worldedit.util.formatting.component.TextComponentProducer ;
2019-07-06 00:46:48 +00:00
import com.sk89q.worldedit.util.formatting.text.Component ;
import com.sk89q.worldedit.util.formatting.text.TextComponent ;
2019-09-14 03:05:16 +00:00
import com.sk89q.worldedit.util.formatting.text.event.ClickEvent ;
import com.sk89q.worldedit.util.formatting.text.event.HoverEvent ;
import com.sk89q.worldedit.util.formatting.text.format.TextColor ;
2019-07-06 00:46:48 +00:00
import com.sk89q.worldedit.util.io.Closer ;
2015-12-28 20:05:16 +00:00
import com.sk89q.worldedit.util.io.file.FilenameException ;
2019-07-06 00:46:48 +00:00
import java.io.BufferedInputStream ;
import java.io.BufferedOutputStream ;
import java.io.File ;
import java.io.FileInputStream ;
import java.io.FileOutputStream ;
import java.io.IOException ;
import java.io.InputStream ;
2019-11-19 21:23:47 +00:00
import static com.google.common.base.Preconditions.checkArgument ;
2018-08-12 14:03:07 +00:00
import java.net.URI ;
import java.net.URISyntaxException ;
2019-04-03 13:25:16 +00:00
import java.net.URL ;
2018-08-12 14:03:07 +00:00
import java.nio.channels.Channels ;
import java.nio.channels.ReadableByteChannel ;
import java.nio.file.Files ;
2019-07-06 00:46:48 +00:00
import java.util.ArrayList ;
import java.util.Arrays ;
import java.util.Collection ;
import java.util.Collections ;
import java.util.List ;
2019-10-23 14:35:04 +00:00
import java.util.Map ;
2019-07-06 00:46:48 +00:00
import java.util.UUID ;
import java.util.concurrent.Callable ;
2016-01-13 23:55:49 +00:00
import java.util.regex.Pattern ;
2019-10-23 16:58:36 +00:00
import org.enginehub.piston.annotation.Command ;
import org.enginehub.piston.annotation.CommandContainer ;
import org.enginehub.piston.annotation.param.Arg ;
import org.enginehub.piston.annotation.param.ArgFlag ;
import org.enginehub.piston.annotation.param.Switch ;
import org.enginehub.piston.exception.StopExecutionException ;
import org.slf4j.Logger ;
import org.slf4j.LoggerFactory ;
2012-12-15 18:49:44 +00:00
2019-07-06 00:46:48 +00:00
//import com.boydti.fawe.object.schematic.visualizer.SchemVis;
2018-08-12 14:03:07 +00:00
2012-03-28 18:05:52 +00:00
/ * *
2014-06-28 08:01:49 +00:00
* Commands that work with schematic files .
2012-03-28 18:05:52 +00:00
* /
2019-07-06 00:46:48 +00:00
@CommandContainer ( superTypes = CommandPermissionsConditionGenerator . Registration . class )
public class SchematicCommands {
2012-03-28 18:05:52 +00:00
2019-03-14 02:51:48 +00:00
private static final Logger log = LoggerFactory . getLogger ( SchematicCommands . class ) ;
2019-07-06 00:46:48 +00:00
private final WorldEdit worldEdit ;
2014-06-28 08:01:49 +00:00
/ * *
* Create a new instance .
*
* @param worldEdit reference to WorldEdit
* /
2019-07-06 00:46:48 +00:00
public SchematicCommands ( WorldEdit worldEdit ) {
checkNotNull ( worldEdit ) ;
this . worldEdit = worldEdit ;
2012-03-28 18:05:52 +00:00
}
@Command (
2019-07-06 00:46:48 +00:00
name = " loadall " ,
2019-07-23 02:22:32 +00:00
desc = " Load multiple clipboards (paste will randomly choose one) "
2012-03-28 18:05:52 +00:00
)
2018-08-12 14:03:07 +00:00
@Deprecated
2018-10-17 12:40:52 +00:00
@CommandPermissions ( { " worldedit.clipboard.load " , " worldedit.schematic.load " , " worldedit.schematic.load.web " , " worldedit.schematic.load.asset " } )
2019-07-23 02:22:32 +00:00
public void loadall ( Player player , LocalSession session ,
2019-07-06 00:46:48 +00:00
@Arg ( desc = " Format name. " , def = " schematic " )
2019-07-23 02:22:32 +00:00
String formatName ,
2019-07-06 00:46:48 +00:00
@Arg ( desc = " File name. " )
2019-07-23 02:22:32 +00:00
String filename ,
2019-07-06 00:46:48 +00:00
@Switch ( name = 'r' , desc = " Apply random rotation " )
boolean randomRotate ) throws FilenameException {
2019-01-31 15:08:58 +00:00
final ClipboardFormat format = ClipboardFormats . findByAlias ( formatName ) ;
2014-07-10 04:08:34 +00:00
if ( format = = null ) {
2019-12-16 09:01:41 +00:00
player . print ( Caption . of ( " fawe.worldedit.clipboard.clipboard.invalid.format " , formatName ) ) ;
2014-07-10 04:08:34 +00:00
return ;
}
2018-08-12 14:03:07 +00:00
try {
2019-01-31 15:08:58 +00:00
MultiClipboardHolder all = ClipboardFormats . loadAllFromInput ( player , filename , null , true ) ;
2018-08-12 14:03:07 +00:00
if ( all ! = null ) {
session . addClipboard ( all ) ;
2019-12-16 09:01:41 +00:00
player . print ( Caption . of ( " fawe.worldedit.schematic.schematic.loaded " , filename ) ) ;
2018-08-12 14:03:07 +00:00
}
} catch ( IOException e ) {
throw new RuntimeException ( e ) ;
}
}
2014-07-10 04:08:34 +00:00
2018-08-12 14:03:07 +00:00
@Command (
2019-07-06 00:46:48 +00:00
name = " clear " ,
desc = " Clear your clipboard "
2018-08-12 14:03:07 +00:00
)
@CommandPermissions ( { " worldedit.clipboard.clear " , " worldedit.schematic.clear " } )
public void clear ( Player player , LocalSession session ) throws WorldEditException {
session . setClipboard ( null ) ;
2019-11-21 19:56:10 +00:00
player . print ( TranslatableComponent . of ( " fawe.worldedit.clipboard.clipboard.cleared " ) ) ;
2018-08-12 14:03:07 +00:00
}
2014-07-10 04:08:34 +00:00
2018-08-12 14:03:07 +00:00
@Command (
2019-07-06 00:46:48 +00:00
name = " unload " ,
desc = " Remove a clipboard from your multi-clipboard "
2018-08-12 14:03:07 +00:00
)
@CommandPermissions ( { " worldedit.clipboard.clear " , " worldedit.schematic.clear " } )
public void unload ( Player player , LocalSession session , String fileName ) throws WorldEditException {
URI uri ;
if ( fileName . startsWith ( " file:/ " ) | | fileName . startsWith ( " http:// " ) | | fileName . startsWith ( " https:// " ) ) {
uri = URI . create ( fileName ) ;
} else {
final LocalConfiguration config = this . worldEdit . getConfiguration ( ) ;
File working = this . worldEdit . getWorkingDirectoryFile ( config . saveDir ) ;
File root = Settings . IMP . PATHS . PER_PLAYER_SCHEMATICS ? new File ( working , player . getUniqueId ( ) . toString ( ) ) : working ;
uri = new File ( root , fileName ) . toURI ( ) ;
}
2014-07-10 04:08:34 +00:00
2018-08-12 14:03:07 +00:00
ClipboardHolder clipboard = session . getClipboard ( ) ;
if ( clipboard instanceof URIClipboardHolder ) {
URIClipboardHolder identifiable = ( URIClipboardHolder ) clipboard ;
if ( identifiable . contains ( uri ) ) {
if ( identifiable instanceof MultiClipboardHolder ) {
MultiClipboardHolder multi = ( MultiClipboardHolder ) identifiable ;
multi . remove ( uri ) ;
if ( multi . getHolders ( ) . isEmpty ( ) ) session . setClipboard ( null ) ;
} else {
session . setClipboard ( null ) ;
}
2019-11-21 19:56:10 +00:00
player . print ( TranslatableComponent . of ( " fawe.worldedit.clipboard.clipboard.cleared " ) ) ;
2018-08-12 14:03:07 +00:00
return ;
}
2014-07-10 04:08:34 +00:00
}
2019-12-16 09:01:41 +00:00
player . print ( Caption . of ( " fawe.worldedit.clipboard.clipboard.uri.not.found " , fileName ) ) ;
2012-03-28 18:05:52 +00:00
}
2020-03-03 22:03:47 +00:00
2019-06-08 00:58:48 +00:00
@Command (
2019-07-06 00:46:48 +00:00
name = " load " ,
desc = " Load a schematic into your clipboard "
2019-06-08 00:58:48 +00:00
)
2018-10-17 12:40:52 +00:00
@CommandPermissions ( { " worldedit.clipboard.load " , " worldedit.schematic.load " , " worldedit.schematic.load.asset " , " worldedit.schematic.load.web " , " worldedit.schematic.load.other " } )
2019-07-23 23:17:38 +00:00
public void load ( Actor actor , LocalSession session ,
2019-07-06 00:46:48 +00:00
@Arg ( desc = " File name. " )
String filename ,
2020-01-11 03:32:12 +00:00
@Arg ( desc = " Format name. " , def = " sponge " )
2019-07-06 00:46:48 +00:00
String formatName ) throws FilenameException {
2019-06-08 00:58:48 +00:00
LocalConfiguration config = worldEdit . getConfiguration ( ) ;
2019-07-23 20:26:18 +00:00
2020-05-05 15:16:27 +00:00
ClipboardFormat format = null ;
2018-08-12 14:03:07 +00:00
InputStream in = null ;
try {
URI uri ;
if ( filename . startsWith ( " url: " ) ) {
2019-07-23 23:17:38 +00:00
if ( ! actor . hasPermission ( " worldedit.schematic.load.web " ) ) {
2020-01-03 20:38:30 +00:00
actor . print ( Caption . of ( " fawe.error.no-perm " , " worldedit.schematic.load.web " ) ) ;
2018-08-12 14:03:07 +00:00
return ;
}
UUID uuid = UUID . fromString ( filename . substring ( 4 ) ) ;
2019-07-23 20:26:18 +00:00
URL webUrl = new URL ( Settings . IMP . WEB . URL ) ;
2020-05-09 15:45:42 +00:00
format = ClipboardFormats . findByAlias ( formatName ) ;
2019-07-23 20:26:18 +00:00
URL url = new URL ( webUrl , " uploads/ " + uuid + " . " + format . getPrimaryFileExtension ( ) ) ;
ReadableByteChannel byteChannel = Channels . newChannel ( url . openStream ( ) ) ;
in = Channels . newInputStream ( byteChannel ) ;
2018-08-12 14:03:07 +00:00
uri = url . toURI ( ) ;
} else {
2019-07-23 20:26:18 +00:00
File saveDir = worldEdit . getWorkingDirectoryFile ( config . saveDir ) ;
2019-07-23 23:17:38 +00:00
File dir = Settings . IMP . PATHS . PER_PLAYER_SCHEMATICS ? new File ( saveDir , actor . getUniqueId ( ) . toString ( ) ) : saveDir ;
2019-07-23 20:26:18 +00:00
File file ;
2018-08-12 14:03:07 +00:00
if ( filename . startsWith ( " # " ) ) {
2020-05-05 15:16:27 +00:00
format = ClipboardFormats . findByAlias ( formatName ) ;
2018-08-16 16:55:41 +00:00
String [ ] extensions ;
if ( format ! = null ) {
extensions = format . getFileExtensions ( ) . toArray ( new String [ 0 ] ) ;
} else {
extensions = ClipboardFormats . getFileExtensionArray ( ) ;
}
2019-07-23 23:17:38 +00:00
file = actor . openFileOpenDialog ( extensions ) ;
2019-07-23 20:26:18 +00:00
if ( file = = null | | ! file . exists ( ) ) {
2019-11-21 13:50:05 +00:00
actor . printError ( TranslatableComponent . of ( " worldedit.schematic.load.does-not-exist " , TextComponent . of ( filename ) ) ) ;
2018-08-12 14:03:07 +00:00
return ;
}
} else {
2019-07-23 23:17:38 +00:00
if ( Settings . IMP . PATHS . PER_PLAYER_SCHEMATICS & & ! actor . hasPermission ( " worldedit.schematic.load.other " ) & & Pattern . compile ( " [0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12} " ) . matcher ( filename ) . find ( ) ) {
2020-01-03 20:38:30 +00:00
actor . print ( Caption . of ( " fawe.error.no-perm " , " worldedit.schematic.load.other " ) ) ;
2018-08-12 14:03:07 +00:00
return ;
}
2020-05-05 15:16:27 +00:00
if ( filename . matches ( " .* \\ .[ \\ w].* " ) ) {
format = ClipboardFormats
. findByExtension ( filename . substring ( filename . lastIndexOf ( '.' ) + 1 ) ) ;
} else {
format = ClipboardFormats . findByAlias ( formatName ) ;
2018-08-12 14:03:07 +00:00
}
2019-07-23 20:26:18 +00:00
file = MainUtil . resolve ( dir , filename , format , false ) ;
2018-08-12 14:03:07 +00:00
}
2019-07-23 20:26:18 +00:00
if ( file = = null | | ! file . exists ( ) ) {
2018-08-12 14:03:07 +00:00
if ( ! filename . contains ( " ../ " ) ) {
dir = this . worldEdit . getWorkingDirectoryFile ( config . saveDir ) ;
2019-07-23 20:26:18 +00:00
file = MainUtil . resolve ( dir , filename , format , false ) ;
2018-08-12 14:03:07 +00:00
}
}
2019-07-23 20:26:18 +00:00
if ( file = = null | | ! file . exists ( ) | | ! MainUtil . isInSubDirectory ( saveDir , file ) ) {
2019-07-23 23:17:38 +00:00
actor . printError ( " Schematic " + filename + " does not exist! ( " + ( file ! = null & & file . exists ( ) ) + " | " + file + " | " + ( file ! = null & & ! MainUtil . isInSubDirectory ( saveDir , file ) ) + " ) " ) ;
2018-08-12 14:03:07 +00:00
return ;
}
2018-08-16 16:55:41 +00:00
if ( format = = null ) {
2019-07-23 20:26:18 +00:00
format = ClipboardFormats . findByFile ( file ) ;
2018-08-16 16:55:41 +00:00
if ( format = = null ) {
2019-11-21 13:50:05 +00:00
actor . printError ( TranslatableComponent . of ( " worldedit.schematic.unknown-format " , TextComponent . of ( formatName ) ) ) ;
2018-08-16 16:55:41 +00:00
return ;
}
}
2019-07-23 20:26:18 +00:00
in = new FileInputStream ( file ) ;
uri = file . toURI ( ) ;
2018-08-12 14:03:07 +00:00
}
2019-07-23 23:17:38 +00:00
format . hold ( actor , uri , in ) ;
2019-12-16 09:01:41 +00:00
actor . print ( Caption . of ( " fawe.worldedit.schematic.schematic.loaded " , filename ) ) ;
2018-08-12 14:03:07 +00:00
} catch ( IllegalArgumentException e ) {
2019-07-23 23:17:38 +00:00
actor . printError ( " Unknown filename: " + filename ) ;
2018-08-12 14:03:07 +00:00
} catch ( URISyntaxException | IOException e ) {
2019-07-23 23:17:38 +00:00
actor . printError ( " File could not be read or it does not exist: " + e . getMessage ( ) ) ;
2019-04-03 13:25:16 +00:00
log . warn ( " Failed to load a saved clipboard " , e ) ;
2018-08-12 14:03:07 +00:00
} finally {
if ( in ! = null ) {
try {
in . close ( ) ;
} catch ( IOException ignored ) {
}
}
2014-07-10 05:04:17 +00:00
}
2018-08-12 14:03:07 +00:00
}
2014-07-10 04:08:34 +00:00
2019-06-08 00:58:48 +00:00
@Command (
2019-07-06 00:46:48 +00:00
name = " save " ,
desc = " Save a schematic into your clipboard "
2019-06-08 00:58:48 +00:00
)
2018-08-12 14:03:07 +00:00
@CommandPermissions ( { " worldedit.clipboard.save " , " worldedit.schematic.save " , " worldedit.schematic.save.other " } )
2019-08-06 15:29:49 +00:00
public void save ( Actor actor , LocalSession session ,
2019-07-06 00:46:48 +00:00
@Arg ( desc = " File name. " )
String filename ,
@Arg ( desc = " Format name. " , def = " sponge " )
String formatName ,
@Switch ( name = 'f' , desc = " Overwrite an existing file. " )
boolean allowOverwrite ,
@Switch ( name = 'g' , desc = " //TODO " )
boolean global
) throws WorldEditException {
2019-06-08 00:58:48 +00:00
LocalConfiguration config = worldEdit . getConfiguration ( ) ;
2019-07-06 00:46:48 +00:00
File dir = worldEdit . getWorkingDirectoryFile ( config . saveDir ) ;
if ( ! global & & Settings . IMP . PATHS . PER_PLAYER_SCHEMATICS ) {
2019-08-06 15:29:49 +00:00
dir = new File ( dir , actor . getUniqueId ( ) . toString ( ) ) ;
2019-07-06 00:46:48 +00:00
}
2019-06-08 00:58:48 +00:00
ClipboardFormat format = ClipboardFormats . findByAlias ( formatName ) ;
2018-08-12 14:03:07 +00:00
if ( format = = null ) {
2019-10-21 13:45:02 +00:00
actor . printError ( TranslatableComponent . of ( " worldedit.schematic.unknown-format " , TextComponent . of ( formatName ) ) ) ;
2018-08-12 14:03:07 +00:00
return ;
}
2019-07-06 00:46:48 +00:00
2019-07-17 16:31:13 +00:00
boolean other = false ;
2018-08-12 14:03:07 +00:00
if ( filename . contains ( " ../ " ) ) {
2019-07-17 16:31:13 +00:00
other = true ;
2019-08-06 15:29:49 +00:00
if ( ! actor . hasPermission ( " worldedit.schematic.save.other " ) ) {
2020-01-03 20:38:30 +00:00
actor . print ( Caption . of ( " fawe.error.no-perm " , " worldedit.schematic.save.other " ) ) ;
2018-08-12 14:03:07 +00:00
return ;
}
if ( filename . startsWith ( " ../ " ) ) {
2019-07-06 00:46:48 +00:00
dir = worldEdit . getWorkingDirectoryFile ( config . saveDir ) ;
2018-08-12 14:03:07 +00:00
filename = filename . substring ( 3 ) ;
}
}
2019-07-06 00:46:48 +00:00
2019-08-06 15:29:49 +00:00
File f = worldEdit . getSafeSaveFile ( actor , dir , filename , format . getPrimaryFileExtension ( ) ) ;
2019-07-06 00:46:48 +00:00
boolean overwrite = f . exists ( ) ;
if ( overwrite ) {
2019-08-06 15:29:49 +00:00
if ( ! actor . hasPermission ( " worldedit.schematic.delete " ) ) {
2019-07-06 00:46:48 +00:00
throw new StopExecutionException ( TextComponent . of ( " That schematic already exists! " ) ) ;
}
2019-07-17 16:31:13 +00:00
if ( other ) {
2019-08-06 15:29:49 +00:00
if ( ! actor . hasPermission ( " worldedit.schematic.delete.other " ) ) {
2020-01-03 20:38:30 +00:00
actor . print ( Caption . of ( " fawe.error.no-perm " , " worldedit.schematic.delete.other " ) ) ;
2019-07-17 16:31:13 +00:00
return ;
}
}
2019-07-06 00:46:48 +00:00
if ( ! allowOverwrite ) {
2019-10-21 13:45:02 +00:00
actor . printError ( TranslatableComponent . of ( " worldedit.schematic.save.already-exists " ) ) ;
2019-07-06 00:46:48 +00:00
return ;
}
}
// Create parent directories
File parent = f . getParentFile ( ) ;
if ( parent ! = null & & ! parent . exists ( ) ) {
2018-08-12 14:03:07 +00:00
if ( ! parent . mkdirs ( ) ) {
2019-10-21 13:45:02 +00:00
throw new StopExecutionException ( TranslatableComponent . of (
" worldedit.schematic.save.failed-directory " ) ) ;
2014-07-10 04:08:34 +00:00
}
2018-08-12 14:03:07 +00:00
}
2019-07-06 00:46:48 +00:00
2019-07-23 02:22:32 +00:00
ClipboardHolder holder = session . getClipboard ( ) ;
2014-07-10 04:08:34 +00:00
2019-08-06 15:29:49 +00:00
SchematicSaveTask task = new SchematicSaveTask ( actor , f , format , holder , overwrite ) ;
AsyncCommandBuilder . wrap ( task , actor )
2019-07-23 02:22:32 +00:00
. registerWithSupervisor ( worldEdit . getSupervisor ( ) , " Saving schematic " + filename )
2019-11-01 12:33:31 +00:00
. sendMessageAfterDelay ( TranslatableComponent . of ( " worldedit.schematic.save.saving " ) )
2019-07-23 02:22:32 +00:00
. onSuccess ( filename + " saved " + ( overwrite ? " (overwriting previous file). " : " . " ) , null )
2019-12-19 18:00:29 +00:00
. onFailure ( " Failed to save schematic " , worldEdit . getPlatformManager ( ) . getPlatformCommandManager ( ) . getExceptionConverter ( ) )
2019-07-23 02:22:32 +00:00
. buildAndExec ( worldEdit . getExecutorService ( ) ) ;
2012-03-28 18:05:52 +00:00
}
2019-06-08 00:58:48 +00:00
@Command (
2019-07-06 00:46:48 +00:00
name = " move " ,
aliases = { " m " } ,
desc = " Move your loaded schematic "
2019-06-08 00:58:48 +00:00
)
2018-08-12 14:03:07 +00:00
@CommandPermissions ( { " worldedit.schematic.move " , " worldedit.schematic.move.other " } )
2019-06-08 00:58:48 +00:00
public void move ( Player player , LocalSession session , String directory ) throws WorldEditException , IOException {
LocalConfiguration config = worldEdit . getConfiguration ( ) ;
File working = worldEdit . getWorkingDirectoryFile ( config . saveDir ) ;
File dir = Settings . IMP . PATHS . PER_PLAYER_SCHEMATICS ? new File ( working , player . getUniqueId ( ) . toString ( ) ) : working ;
2018-08-21 17:22:37 +00:00
File destDir = new File ( dir , directory ) ;
2018-08-12 14:03:07 +00:00
if ( ! MainUtil . isInSubDirectory ( working , destDir ) ) {
2019-06-12 21:12:12 +00:00
player . printError ( " Directory " + destDir + " does not exist! " ) ;
2018-08-12 14:03:07 +00:00
return ;
}
if ( Settings . IMP . PATHS . PER_PLAYER_SCHEMATICS & & ! MainUtil . isInSubDirectory ( dir , destDir ) & & ! player . hasPermission ( " worldedit.schematic.move.other " ) ) {
2020-01-03 20:38:30 +00:00
player . print ( Caption . of ( " fawe.error.no-perm " , " worldedit.schematic.move.other " ) ) ;
2018-08-12 14:03:07 +00:00
return ;
}
ClipboardHolder clipboard = session . getClipboard ( ) ;
List < File > sources = getFiles ( clipboard ) ;
if ( sources . isEmpty ( ) ) {
2019-11-21 19:56:10 +00:00
player . printError ( TranslatableComponent . of ( " fawe.worldedit.schematic.schematic.none " ) ) ;
2018-08-12 14:03:07 +00:00
return ;
}
if ( ! destDir . exists ( ) & & ! destDir . mkdirs ( ) ) {
2019-06-12 21:12:12 +00:00
player . printError ( " Creation of " + destDir + " failed! (check file permissions) " ) ;
2018-08-12 14:03:07 +00:00
return ;
}
for ( File source : sources ) {
File destFile = new File ( destDir , source . getName ( ) ) ;
if ( destFile . exists ( ) ) {
2019-12-16 09:01:41 +00:00
player . print ( Caption . of ( " fawe.worldedit.schematic.schematic.move.exists " , destFile ) ) ;
2018-08-12 14:03:07 +00:00
continue ;
}
if ( Settings . IMP . PATHS . PER_PLAYER_SCHEMATICS & & ( ! MainUtil . isInSubDirectory ( dir , destFile ) | | ! MainUtil . isInSubDirectory ( dir , source ) ) & & ! player . hasPermission ( " worldedit.schematic.delete.other " ) ) {
2019-12-16 09:01:41 +00:00
player . print ( Caption . of ( " fawe.worldedit.schematic.schematic.move.failed " , destFile ,
2020-01-03 20:38:30 +00:00
Caption . of ( " fawe.error.no-perm " , ( " worldedit.schematic.move.other " ) ) ) ) ;
2018-08-12 14:03:07 +00:00
continue ;
}
try {
File cached = new File ( source . getParentFile ( ) , " . " + source . getName ( ) + " .cached " ) ;
Files . move ( source . toPath ( ) , destFile . toPath ( ) ) ;
if ( cached . exists ( ) ) Files . move ( cached . toPath ( ) , destFile . toPath ( ) ) ;
2019-12-16 09:01:41 +00:00
player . print ( Caption . of ( " fawe.worldedit.schematic.schematic.move.success " , source , destFile ) ) ;
2018-08-12 14:03:07 +00:00
} catch ( IOException e ) {
throw new RuntimeException ( e ) ;
}
}
}
2014-05-02 01:00:59 +00:00
2018-08-12 14:03:07 +00:00
private List < File > getFiles ( ClipboardHolder clipboard ) {
Collection < URI > uris = Collections . emptyList ( ) ;
if ( clipboard instanceof URIClipboardHolder ) {
uris = ( ( URIClipboardHolder ) clipboard ) . getURIs ( ) ;
2014-05-02 01:00:59 +00:00
}
2019-07-06 00:46:48 +00:00
List < File > files = new ArrayList < > ( ) ;
2018-08-12 14:03:07 +00:00
for ( URI uri : uris ) {
File file = new File ( uri ) ;
if ( file . exists ( ) ) files . add ( file ) ;
}
return files ;
}
2014-05-02 01:00:59 +00:00
2019-06-08 00:58:48 +00:00
@Command (
2019-07-06 00:46:48 +00:00
name = " formats " ,
aliases = { " listformats " , " f " } ,
desc = " List available formats "
2019-06-08 00:58:48 +00:00
)
2012-04-01 16:21:27 +00:00
@CommandPermissions ( " worldedit.schematic.formats " )
2019-07-06 00:46:48 +00:00
public void formats ( Actor actor ) {
2019-10-21 13:45:02 +00:00
actor . printInfo ( TranslatableComponent . of ( " worldedit.schematic.formats.title " ) ) ;
2019-07-06 00:46:48 +00:00
StringBuilder builder ;
2012-03-28 18:05:52 +00:00
boolean first = true ;
2019-07-06 00:46:48 +00:00
for ( ClipboardFormat format : ClipboardFormats . getAll ( ) ) {
builder = new StringBuilder ( ) ;
2019-01-31 15:08:58 +00:00
builder . append ( format . getName ( ) ) . append ( " : " ) ;
2019-07-06 00:46:48 +00:00
for ( String lookupName : format . getAliases ( ) ) {
2012-03-28 18:05:52 +00:00
if ( ! first ) {
builder . append ( " , " ) ;
}
builder . append ( lookupName ) ;
first = false ;
}
first = true ;
2019-10-21 13:45:02 +00:00
actor . printInfo ( TextComponent . of ( builder . toString ( ) ) ) ;
2012-03-28 18:05:52 +00:00
}
}
2020-03-04 02:41:51 +00:00
2018-08-12 14:03:07 +00:00
@Command (
2019-07-06 00:46:48 +00:00
name = " list " ,
aliases = { " all " , " ls " } ,
desc = " List saved schematics " ,
descFooter = " Note: Format is not fully verified until loading. "
2018-08-12 14:03:07 +00:00
)
@CommandPermissions ( " worldedit.schematic.list " )
2019-10-23 16:58:36 +00:00
public void list ( Actor actor , LocalSession session ,
2020-01-11 03:32:12 +00:00
@ArgFlag ( name = 'p' , desc = " Page to view. " , def = " 1 " )
2019-07-06 00:46:48 +00:00
int page ,
2019-07-23 20:26:18 +00:00
@Switch ( name = 'd' , desc = " Sort by date, oldest first " )
boolean oldFirst ,
@Switch ( name = 'n' , desc = " Sort by date, newest first " )
boolean newFirst ,
2019-11-01 22:22:29 +00:00
@ArgFlag ( name = 'f' , desc = " Restricts by format. " , def = " " )
2019-10-23 16:58:36 +00:00
String formatName ,
@Arg ( name = " filter " , desc = " Filter for schematics " , def = " all " )
String filter ,
2019-10-23 14:35:04 +00:00
Arguments arguments
) throws WorldEditException {
2019-07-23 20:26:18 +00:00
if ( oldFirst & & newFirst ) {
throw new StopExecutionException ( TextComponent . of ( " Cannot sort by oldest and newest. " ) ) ;
}
2019-12-25 02:34:20 +00:00
String pageCommand = " / " + arguments . get ( ) ;
2019-10-23 14:35:04 +00:00
LocalConfiguration config = worldEdit . getConfiguration ( ) ;
File dir = worldEdit . getWorkingDirectoryFile ( config . saveDir ) ;
2019-12-25 02:34:20 +00:00
String schemCmd = " //schematic " ;
2019-11-02 19:53:25 +00:00
String loadSingle = schemCmd + " load " ;
String loadMulti = schemCmd + " loadall " ;
String unload = schemCmd + " unload " ;
String delete = schemCmd + " delete " ;
String list = schemCmd + " list " ;
String showCmd = schemCmd + " show " ;
2019-10-23 14:35:04 +00:00
List < String > args = filter . isEmpty ( ) ? Collections . emptyList ( ) : Arrays . asList ( filter . split ( " " ) ) ;
URIClipboardHolder multi = as ( URIClipboardHolder . class , session . getExistingClipboard ( ) ) ;
final boolean hasShow = false ;
//If player forgot -p argument
boolean playerFolder = Settings . IMP . PATHS . PER_PLAYER_SCHEMATICS ;
UUID uuid = playerFolder ? actor . getUniqueId ( ) : null ;
List < File > files = UtilityCommands . getFiles ( dir , actor , args , formatName , playerFolder , oldFirst , newFirst ) ;
List < Map . Entry < URI , String > > entries = UtilityCommands . filesToEntry ( dir , files , uuid ) ;
Function < URI , Boolean > isLoaded = multi = = null ? f - > false : multi : : contains ;
2019-11-02 19:53:25 +00:00
List < Component > components = UtilityCommands . entryToComponent ( dir , entries , isLoaded ,
( name , path , type , loaded ) - > {
2019-10-23 14:35:04 +00:00
TextColor color = TextColor . GRAY ;
switch ( type ) {
case URL :
color = TextColor . DARK_GRAY ;
break ;
case FILE :
color = TextColor . GREEN ;
break ;
case DIRECTORY :
color = TextColor . GOLD ;
break ;
}
2019-10-23 15:44:36 +00:00
TextComponentProducer msg = new TextComponentProducer ( ) ;
2019-10-23 14:35:04 +00:00
msg . append ( TextComponent . of ( " - " , color ) ) ;
if ( loaded ) {
msg . append ( TextComponent . of ( " [-] " , TextColor . RED )
. clickEvent ( ClickEvent . of ( ClickEvent . Action . SUGGEST_COMMAND , unload + " " + path ) )
. hoverEvent ( HoverEvent . of ( HoverEvent . Action . SHOW_TEXT , TextComponent . of ( " Unload " ) ) ) ) ;
} else {
msg . append ( TextComponent . of ( " [+] " , TextColor . GREEN )
. clickEvent ( ClickEvent . of ( ClickEvent . Action . SUGGEST_COMMAND , loadMulti + " " + path ) )
. hoverEvent ( HoverEvent . of ( HoverEvent . Action . SHOW_TEXT , TextComponent . of ( " Add to clipboard " ) ) ) ) ;
}
if ( type ! = UtilityCommands . URIType . DIRECTORY ) {
2019-10-23 15:44:36 +00:00
msg . append ( TextComponent . of ( " [X] " , TextColor . DARK_RED )
. clickEvent ( ClickEvent . of ( ClickEvent . Action . SUGGEST_COMMAND , delete + " " + path ) )
. hoverEvent ( HoverEvent . of ( HoverEvent . Action . SHOW_TEXT , TextComponent . of ( " delete " ) ) )
) ;
2019-10-23 14:35:04 +00:00
} else if ( hasShow ) {
2019-10-23 15:44:36 +00:00
msg . append ( TextComponent . of ( " [O] " , TextColor . DARK_AQUA )
. clickEvent ( ClickEvent . of ( ClickEvent . Action . SUGGEST_COMMAND , showCmd + " " + path ) )
. hoverEvent ( HoverEvent . of ( HoverEvent . Action . SHOW_TEXT , TextComponent . of ( " visualize " ) ) )
) ;
2019-10-23 14:35:04 +00:00
}
TextComponent msgElem = TextComponent . of ( name , color ) ;
if ( type ! = UtilityCommands . URIType . DIRECTORY ) {
2019-10-23 15:44:36 +00:00
msgElem = msgElem . clickEvent ( ClickEvent . of ( ClickEvent . Action . SUGGEST_COMMAND , loadSingle + " " + path ) ) ;
msgElem = msgElem . hoverEvent ( HoverEvent . of ( HoverEvent . Action . SHOW_TEXT , TextComponent . of ( " Load " ) ) ) ;
2019-10-23 14:35:04 +00:00
} else {
2019-10-23 15:44:36 +00:00
msgElem = msgElem . clickEvent ( ClickEvent . of ( ClickEvent . Action . SUGGEST_COMMAND , list + " " + path ) ) ;
msgElem = msgElem . hoverEvent ( HoverEvent . of ( HoverEvent . Action . SHOW_TEXT , TextComponent . of ( " List " ) ) ) ;
2019-10-23 14:35:04 +00:00
}
msg . append ( msgElem ) ;
2019-10-23 15:44:36 +00:00
return msg . create ( ) ;
2019-11-02 19:53:25 +00:00
} ) ;
2019-10-23 14:35:04 +00:00
PaginationBox paginationBox = PaginationBox . fromStrings ( " Available schematics " , pageCommand , components ) ;
actor . print ( paginationBox . create ( page ) ) ;
2016-01-13 23:55:49 +00:00
}
2019-07-06 00:46:48 +00:00
private static class SchematicLoadTask implements Callable < ClipboardHolder > {
2019-08-06 15:29:49 +00:00
private final Actor actor ;
2019-07-06 00:46:48 +00:00
private final File file ;
private final ClipboardFormat format ;
2019-08-06 15:29:49 +00:00
SchematicLoadTask ( Actor actor , File file , ClipboardFormat format ) {
this . actor = actor ;
2019-07-06 00:46:48 +00:00
this . file = file ;
this . format = format ;
}
@Override
public ClipboardHolder call ( ) throws Exception {
try ( Closer closer = Closer . create ( ) ) {
FileInputStream fis = closer . register ( new FileInputStream ( file ) ) ;
BufferedInputStream bis = closer . register ( new BufferedInputStream ( fis ) ) ;
ClipboardReader reader = closer . register ( format . getReader ( bis ) ) ;
Clipboard clipboard = reader . read ( ) ;
2019-08-06 15:29:49 +00:00
log . info ( actor . getName ( ) + " loaded " + file . getCanonicalPath ( ) ) ;
2019-07-06 00:46:48 +00:00
return new ClipboardHolder ( clipboard ) ;
}
}
}
private static class SchematicSaveTask implements Callable < Void > {
2019-08-06 15:29:49 +00:00
private final Actor actor ;
2019-07-06 00:46:48 +00:00
private final File file ;
private final ClipboardFormat format ;
private final ClipboardHolder holder ;
private final boolean overwrite ;
2019-08-06 15:29:49 +00:00
SchematicSaveTask ( Actor actor , File file , ClipboardFormat format , ClipboardHolder holder , boolean overwrite ) {
this . actor = actor ;
2019-07-06 00:46:48 +00:00
this . file = file ;
this . format = format ;
this . holder = holder ;
this . overwrite = overwrite ;
}
@Override
public Void call ( ) throws Exception {
Clipboard clipboard = holder . getClipboard ( ) ;
Transform transform = holder . getTransform ( ) ;
Clipboard target ;
// If we have a transform, bake it into the copy
if ( transform . isIdentity ( ) ) {
target = clipboard ;
} else {
FlattenedClipboardTransform result = FlattenedClipboardTransform . transform ( clipboard , transform ) ;
target = new BlockArrayClipboard ( result . getTransformedRegion ( ) ) ;
target . setOrigin ( clipboard . getOrigin ( ) ) ;
Operations . completeLegacy ( result . copyTo ( target ) ) ;
}
try ( Closer closer = Closer . create ( ) ) {
FileOutputStream fos = closer . register ( new FileOutputStream ( file ) ) ;
BufferedOutputStream bos = closer . register ( new BufferedOutputStream ( fos ) ) ;
ClipboardWriter writer = closer . register ( format . getWriter ( bos ) ) ;
2019-07-23 02:22:32 +00:00
URI uri = null ;
if ( holder instanceof URIClipboardHolder ) {
uri = ( ( URIClipboardHolder ) holder ) . getURI ( clipboard ) ;
}
2019-08-10 06:01:42 +00:00
if ( new ActorSaveClipboardEvent ( actor , clipboard , uri , file . toURI ( ) ) . call ( ) ) {
2019-07-23 02:22:32 +00:00
if ( writer instanceof MinecraftStructure ) {
2019-08-06 15:29:49 +00:00
( ( MinecraftStructure ) writer ) . write ( target , actor . getName ( ) ) ;
2019-07-23 02:22:32 +00:00
} else {
writer . write ( target ) ;
}
2019-08-06 15:29:49 +00:00
log . info ( actor . getName ( ) + " saved " + file . getCanonicalPath ( ) ) ;
2019-12-16 09:01:41 +00:00
actor . print ( Caption . of ( " fawe.worldedit.schematic.schematic.saved " , file . getName ( ) ) ) ;
2019-07-23 02:22:32 +00:00
} else {
2019-11-21 19:56:10 +00:00
actor . printError ( TranslatableComponent . of ( " fawe.cancel.worldedit.cancel.reason.manual " ) ) ;
2019-07-23 02:22:32 +00:00
}
2019-07-06 00:46:48 +00:00
}
return null ;
}
}
private static class SchematicListTask implements Callable < Component > {
private final String prefix ;
private final int sortType ;
private final int page ;
private final File rootDir ;
private final String pageCommand ;
2019-07-23 20:26:18 +00:00
private final String filter ;
private String formatName ;
2019-07-06 00:46:48 +00:00
2019-07-23 20:26:18 +00:00
SchematicListTask ( String prefix , int sortType , int page , String pageCommand ,
String filter , String formatName ) {
2019-07-06 00:46:48 +00:00
this . prefix = prefix ;
this . sortType = sortType ;
this . page = page ;
this . rootDir = WorldEdit . getInstance ( ) . getWorkingDirectoryFile ( prefix ) ;
this . pageCommand = pageCommand ;
2019-07-23 20:26:18 +00:00
this . filter = filter ;
this . formatName = formatName ;
2019-07-06 00:46:48 +00:00
}
@Override
public Component call ( ) throws Exception {
2019-07-23 20:26:18 +00:00
ClipboardFormat format = ClipboardFormats . findByAlias ( formatName ) ;
List < File > fileList = getFiles ( rootDir , filter , format ) ;
2019-07-06 00:46:48 +00:00
if ( fileList = = null | | fileList . isEmpty ( ) ) {
return ErrorFormat . wrap ( " No schematics found. " ) ;
}
File [ ] files = new File [ fileList . size ( ) ] ;
fileList . toArray ( files ) ;
// cleanup file list
Arrays . sort ( files , ( f1 , f2 ) - > {
// http://stackoverflow.com/questions/203030/best-way-to-list-files-in-java-sorted-by-date-modified
int res ;
if ( sortType = = 0 ) { // use name by default
int p = f1 . getParent ( ) . compareTo ( f2 . getParent ( ) ) ;
if ( p = = 0 ) { // same parent, compare names
res = f1 . getName ( ) . compareTo ( f2 . getName ( ) ) ;
} else { // different parent, sort by that
res = p ;
}
} else {
res = Long . compare ( f1 . lastModified ( ) , f2 . lastModified ( ) ) ; // use date if there is a flag
if ( sortType = = 1 ) res = - res ; // flip date for newest first instead of oldest first
}
return res ;
} ) ;
PaginationBox paginationBox = new SchematicPaginationBox ( prefix , files , pageCommand ) ;
return paginationBox . create ( page ) ;
}
}
2019-07-23 20:26:18 +00:00
//TODO filtering for directories, global, and private scheamtics needs to be reimplemented here
private static List < File > getFiles ( File root , String filter , ClipboardFormat format ) {
2019-07-06 00:46:48 +00:00
File [ ] files = root . listFiles ( ) ;
if ( files = = null ) return null ;
2019-07-23 20:26:18 +00:00
//Only get the files that match the format parameter
if ( format ! = null ) {
files = Arrays . stream ( files ) . filter ( format : : isFormat ) . toArray ( File [ ] : : new ) ;
}
2019-07-06 00:46:48 +00:00
List < File > fileList = new ArrayList < > ( ) ;
for ( File f : files ) {
if ( f . isDirectory ( ) ) {
2019-07-23 20:26:18 +00:00
List < File > subFiles = getFiles ( f , filter , format ) ;
2019-07-06 00:46:48 +00:00
if ( subFiles = = null ) continue ; // empty subdir
fileList . addAll ( subFiles ) ;
} else {
fileList . add ( f ) ;
}
}
return fileList ;
}
2019-07-17 16:31:13 +00:00
2019-11-19 21:23:47 +00:00
@Command (
name = " delete " ,
aliases = { " d " } ,
desc = " Delete a saved schematic "
)
@CommandPermissions ( " worldedit.schematic.delete " )
public void delete ( Actor actor ,
2019-11-20 00:11:54 +00:00
LocalSession session ,
2019-11-19 21:23:47 +00:00
@Arg ( desc = " File name. " )
2019-11-20 00:11:54 +00:00
String filename ) throws WorldEditException , IOException {
2019-11-19 21:23:47 +00:00
LocalConfiguration config = worldEdit . getConfiguration ( ) ;
2019-11-20 00:11:54 +00:00
File working = worldEdit . getWorkingDirectoryFile ( config . saveDir ) ;
File dir = Settings . IMP . PATHS . PER_PLAYER_SCHEMATICS ? new File ( working , actor . getUniqueId ( ) . toString ( ) ) : working ;
List < File > files = new ArrayList < > ( ) ;
2019-11-19 21:23:47 +00:00
2019-11-20 00:11:54 +00:00
if ( filename . equalsIgnoreCase ( " * " ) ) {
files . addAll ( getFiles ( session . getClipboard ( ) ) ) ;
} else {
File f = MainUtil . resolveRelative ( new File ( dir , filename ) ) ;
files . add ( f ) ;
}
2019-11-19 21:23:47 +00:00
2019-11-20 00:11:54 +00:00
if ( files . isEmpty ( ) ) {
2019-11-21 13:50:28 +00:00
actor . printError ( TranslatableComponent . of ( " worldedit.schematic.delete.does-not-exist " , TextComponent . of ( filename ) ) ) ;
2019-11-19 21:23:47 +00:00
return ;
2019-11-20 00:11:54 +00:00
}
for ( File f : files ) {
if ( ! MainUtil . isInSubDirectory ( working , f ) | | ! f . exists ( ) ) {
2019-11-21 13:50:28 +00:00
actor . printError ( TranslatableComponent . of ( " worldedit.schematic.delete.does-not-exist " , TextComponent . of ( filename ) ) ) ;
2019-11-20 00:11:54 +00:00
continue ;
}
if ( Settings . IMP . PATHS . PER_PLAYER_SCHEMATICS & & ! MainUtil . isInSubDirectory ( dir , f ) & & ! actor . hasPermission ( " worldedit.schematic.delete.other " ) ) {
2020-01-03 20:38:30 +00:00
actor . print ( Caption . of ( " fawe.error.no-perm " , " worldedit.schematic.delete.other " ) ) ;
2019-11-20 00:11:54 +00:00
continue ;
}
2019-11-21 13:50:28 +00:00
if ( ! deleteFile ( f ) ) {
actor . printError ( TranslatableComponent . of ( " worldedit.schematic.delete.failed " , TextComponent . of ( filename ) ) ) ;
2019-11-20 00:11:54 +00:00
continue ;
}
2019-12-16 09:01:41 +00:00
actor . print ( Caption . of ( " worldedit.schematic.delete.deleted " , filename ) ) ;
2019-11-20 00:11:54 +00:00
}
}
2019-11-21 13:50:28 +00:00
private boolean deleteFile ( File file ) {
2019-07-17 16:31:13 +00:00
if ( file . delete ( ) ) {
new File ( file . getParentFile ( ) , " . " + file . getName ( ) + " .cached " ) . delete ( ) ;
return true ;
}
return false ;
}
2019-09-14 03:05:16 +00:00
private static class SchematicPaginationBox extends PaginationBox {
private final String prefix ;
private final File [ ] files ;
SchematicPaginationBox ( String rootDir , File [ ] files , String pageCommand ) {
super ( " Available schematics " , pageCommand ) ;
this . prefix = rootDir = = null ? " " : rootDir ;
this . files = files ;
}
@Override
public Component getComponent ( int number ) {
checkArgument ( number < files . length & & number > = 0 ) ;
File file = files [ number ] ;
Multimap < String , ClipboardFormat > exts = ClipboardFormats . getFileExtensionMap ( ) ;
String format = exts . get ( com . google . common . io . Files . getFileExtension ( file . getName ( ) ) )
. stream ( ) . findFirst ( ) . map ( ClipboardFormat : : getName ) . orElse ( " Unknown " ) ;
boolean inRoot = file . getParentFile ( ) . getName ( ) . equals ( prefix ) ;
String path = inRoot ? file . getName ( ) : file . getPath ( ) . split ( Pattern . quote ( prefix + File . separator ) ) [ 1 ] ;
return TextComponent . builder ( )
. content ( " " )
. append ( TextComponent . of ( " [L] " )
. color ( TextColor . GOLD )
. clickEvent ( ClickEvent
. of ( ClickEvent . Action . RUN_COMMAND , " /schem load \" " + path + " \" " ) )
. hoverEvent ( HoverEvent . of ( HoverEvent . Action . SHOW_TEXT , TextComponent . of ( " Click to load " ) ) ) )
. append ( TextComponent . space ( ) )
. append ( TextComponent . of ( path )
. color ( TextColor . DARK_GREEN )
. hoverEvent ( HoverEvent . of ( HoverEvent . Action . SHOW_TEXT , TextComponent . of ( format ) ) ) )
. build ( ) ;
}
@Override
public int getComponentsSize ( ) {
return files . length ;
}
}
2012-03-28 18:05:52 +00:00
}