2015-02-15 11:52:51 +01:00
////////////////////////////////////////////////////////////////////////////////////////////////////
// PlotSquared - A plot manager and world generator for the Bukkit API /
// Copyright (c) 2014 IntellectualSites/IntellectualCrafters /
// /
// This program is free software; you can redistribute it and/or modify /
// it under the terms of the GNU General Public License as published by /
// the Free Software Foundation; either version 3 of the License, or /
// (at your option) any later version. /
// /
// This program is distributed in the hope that it will be useful, /
// but WITHOUT ANY WARRANTY; without even the implied warranty of /
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the /
// GNU General Public License for more details. /
// /
// You should have received a copy of the GNU General Public License /
// along with this program; if not, write to the Free Software Foundation, /
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA /
// /
// You can contact us via: support@intellectualsites.com /
////////////////////////////////////////////////////////////////////////////////////////////////////
package com.intellectualcrafters.plot.commands ;
2015-07-30 16:25:16 +02:00
import java.util.ArrayList ;
import java.util.Collection ;
import java.util.HashSet ;
2015-09-22 15:23:28 +02:00
import java.util.Iterator ;
2015-07-30 16:25:16 +02:00
import java.util.List ;
import java.util.Set ;
2015-09-22 15:23:28 +02:00
import java.util.concurrent.atomic.AtomicBoolean ;
2015-07-30 16:25:16 +02:00
2015-07-03 14:15:20 +02:00
import com.intellectualcrafters.plot.PS ;
2015-02-15 11:52:51 +01:00
import com.intellectualcrafters.plot.object.Plot ;
import com.intellectualcrafters.plot.object.PlotId ;
2015-02-21 12:38:44 +01:00
import com.intellectualcrafters.plot.object.PlotPlayer ;
2015-02-22 07:30:58 +01:00
import com.intellectualcrafters.plot.util.BlockManager ;
2015-02-20 12:23:48 +01:00
import com.intellectualcrafters.plot.util.MainUtil ;
2015-07-30 16:25:16 +02:00
import com.intellectualcrafters.plot.util.MathMan ;
2015-09-22 15:23:28 +02:00
import com.intellectualcrafters.plot.util.TaskManager ;
2015-07-27 19:50:04 +02:00
import com.plotsquared.general.commands.CommandDeclaration ;
2015-02-15 11:52:51 +01:00
2015-09-13 06:04:31 +02:00
@CommandDeclaration ( command = " condense " , permission = " plots.admin " , description = " Condense a plotworld " , category = CommandCategory . DEBUG , requiredType = RequiredType . CONSOLE )
public class Condense extends SubCommand {
2015-07-27 00:26:19 +02:00
public static boolean TASK = false ;
2015-09-13 06:04:31 +02:00
2015-02-16 04:46:57 +01:00
@Override
2015-09-13 06:04:31 +02:00
public boolean onCommand ( final PlotPlayer plr , final String . . . args ) {
if ( ( args . length ! = 2 ) & & ( args . length ! = 3 ) ) {
2015-02-21 12:24:46 +01:00
MainUtil . sendMessage ( plr , " /plot condense <world> <start|stop|info> [radius] " ) ;
2015-02-16 04:46:57 +01:00
return false ;
}
2015-02-20 07:34:19 +01:00
final String worldname = args [ 0 ] ;
2015-09-13 06:04:31 +02:00
if ( ! BlockManager . manager . isWorld ( worldname ) | | ! PS . get ( ) . isPlotWorld ( worldname ) ) {
2015-02-21 12:24:46 +01:00
MainUtil . sendMessage ( plr , " INVALID WORLD " ) ;
2015-02-16 04:46:57 +01:00
return false ;
2015-02-15 11:52:51 +01:00
}
2015-09-13 06:04:31 +02:00
switch ( args [ 1 ] . toLowerCase ( ) ) {
case " start " : {
if ( args . length = = 2 ) {
2015-02-21 12:24:46 +01:00
MainUtil . sendMessage ( plr , " /plot condense " + worldname + " start <radius> " ) ;
2015-02-16 04:46:57 +01:00
return false ;
}
2015-09-13 06:04:31 +02:00
if ( TASK ) {
2015-02-21 12:24:46 +01:00
MainUtil . sendMessage ( plr , " TASK ALREADY STARTED " ) ;
2015-02-16 06:36:47 +01:00
return false ;
}
2015-09-13 06:04:31 +02:00
if ( args . length = = 2 ) {
2015-02-21 12:24:46 +01:00
MainUtil . sendMessage ( plr , " /plot condense " + worldname + " start <radius> " ) ;
2015-02-16 06:36:47 +01:00
return false ;
}
2015-09-13 06:04:31 +02:00
if ( ! MathMan . isInteger ( args [ 2 ] ) ) {
2015-02-21 12:24:46 +01:00
MainUtil . sendMessage ( plr , " INVALID RADIUS " ) ;
2015-02-16 06:36:47 +01:00
return false ;
}
2015-02-20 07:34:19 +01:00
final int radius = Integer . parseInt ( args [ 2 ] ) ;
2015-09-22 15:23:28 +02:00
ArrayList < Plot > plots = new ArrayList < > ( PS . get ( ) . getPlotsInWorld ( worldname ) ) ;
// remove non base plots
Iterator < Plot > iter = plots . iterator ( ) ;
int maxSize = 0 ;
ArrayList < Integer > sizes = new ArrayList < > ( ) ;
while ( iter . hasNext ( ) ) {
Plot plot = iter . next ( ) ;
if ( ! plot . isBasePlot ( ) ) {
iter . remove ( ) ;
continue ;
}
int size = plot . getConnectedPlots ( ) . size ( ) ;
if ( size > maxSize ) {
maxSize = size ;
}
sizes . add ( size - 1 ) ;
}
// Sort plots by size (buckets?)]
ArrayList < Plot > [ ] buckets = new ArrayList [ maxSize ] ;
for ( int i = 0 ; i < plots . size ( ) ; i + + ) {
Plot plot = plots . get ( i ) ;
int size = sizes . get ( i ) ;
ArrayList < Plot > array = buckets [ size ] ;
if ( array = = null ) {
array = new ArrayList < Plot > ( ) ;
buckets [ size ] = array ;
}
array . add ( plot ) ;
}
final ArrayList < Plot > allPlots = new ArrayList < Plot > ( plots . size ( ) ) ;
for ( int i = buckets . length - 1 ; i > = 0 ; i - - ) {
ArrayList < Plot > array = buckets [ i ] ;
if ( array ! = null ) {
allPlots . addAll ( array ) ;
}
}
final int size = allPlots . size ( ) ;
2015-02-20 07:34:19 +01:00
final int minimum_radius = ( int ) Math . ceil ( ( Math . sqrt ( size ) / 2 ) + 1 ) ;
2015-09-13 06:04:31 +02:00
if ( radius < minimum_radius ) {
2015-02-21 12:24:46 +01:00
MainUtil . sendMessage ( plr , " RADIUS TOO SMALL " ) ;
2015-02-16 06:36:47 +01:00
return false ;
}
2015-09-22 15:23:28 +02:00
final List < PlotId > to_move = new ArrayList < > ( getPlots ( allPlots , radius ) ) ;
2015-02-16 06:36:47 +01:00
final List < PlotId > free = new ArrayList < > ( ) ;
2015-02-20 07:34:19 +01:00
PlotId start = new PlotId ( 0 , 0 ) ;
2015-09-13 06:04:31 +02:00
while ( ( start . x < = minimum_radius ) & & ( start . y < = minimum_radius ) ) {
2015-09-22 15:23:28 +02:00
final Plot plot = MainUtil . getPlotAbs ( worldname , start ) ;
2015-09-13 06:04:31 +02:00
if ( ! plot . hasOwner ( ) ) {
2016-01-10 21:00:56 +01:00
free . add ( plot . getId ( ) ) ;
2015-02-16 06:36:47 +01:00
}
start = Auto . getNextPlot ( start , 1 ) ;
}
2015-09-13 06:04:31 +02:00
if ( ( free . size ( ) = = 0 ) | | ( to_move . size ( ) = = 0 ) ) {
2015-07-13 21:31:22 +02:00
MainUtil . sendMessage ( plr , " NO FREE PLOTS FOUND " ) ;
2015-03-13 14:29:58 +01:00
return false ;
}
2015-09-22 15:23:28 +02:00
MainUtil . sendMessage ( plr , " TASK STARTED... " ) ;
Runnable run = new Runnable ( ) {
2015-02-16 06:36:47 +01:00
@Override
2015-09-13 06:04:31 +02:00
public void run ( ) {
if ( ! TASK ) {
2015-09-22 15:23:28 +02:00
MainUtil . sendMessage ( plr , " TASK CANCELLED. " ) ;
}
if ( allPlots . size ( ) = = 0 ) {
TASK = false ;
MainUtil . sendMessage ( plr , " TASK COMPLETE. PLEASE VERIFY THAT NO NEW PLOTS HAVE BEEN CLAIMED DURING TASK. " ) ;
2015-02-16 06:36:47 +01:00
return ;
}
2015-09-22 15:23:28 +02:00
final Runnable task = this ;
final Plot origin = allPlots . remove ( 0 ) ;
int i = 0 ;
while ( free . size ( ) > i ) {
final Plot possible = MainUtil . getPlotAbs ( origin . world , free . get ( i ) ) ;
if ( possible . owner ! = null ) {
free . remove ( i ) ;
continue ;
2015-02-16 06:36:47 +01:00
}
2015-09-22 15:23:28 +02:00
i + + ;
final AtomicBoolean result = new AtomicBoolean ( false ) ;
result . set ( MainUtil . move ( origin , possible , new Runnable ( ) {
@Override
public void run ( ) {
if ( result . get ( ) ) {
MainUtil . sendMessage ( plr , " Moving: " + origin + " -> " + possible ) ;
TaskManager . runTaskLater ( task , 1 ) ;
}
}
} , false ) ) ;
if ( result . get ( ) ) {
2015-02-16 06:36:47 +01:00
break ;
}
}
2015-09-13 06:04:31 +02:00
if ( free . size ( ) = = 0 ) {
2015-02-16 06:36:47 +01:00
TASK = false ;
2015-09-22 15:23:28 +02:00
MainUtil . sendMessage ( plr , " TASK FAILED. NO FREE PLOTS FOUND! " ) ;
2015-02-16 06:36:47 +01:00
return ;
}
2015-09-22 15:23:28 +02:00
if ( i > = free . size ( ) ) {
MainUtil . sendMessage ( plr , " SKIPPING COMPLEX PLOT: " + origin ) ;
}
2015-02-16 06:36:47 +01:00
}
2015-09-22 15:23:28 +02:00
} ;
2015-02-16 06:36:47 +01:00
TASK = true ;
2015-09-22 15:23:28 +02:00
TaskManager . runTaskAsync ( run ) ;
2015-02-16 04:46:57 +01:00
return true ;
}
2015-09-13 06:04:31 +02:00
case " stop " : {
if ( ! TASK ) {
2015-02-21 12:24:46 +01:00
MainUtil . sendMessage ( plr , " TASK ALREADY STOPPED " ) ;
2015-02-16 06:36:47 +01:00
return false ;
}
TASK = false ;
2015-02-21 12:24:46 +01:00
MainUtil . sendMessage ( plr , " TASK STOPPED " ) ;
2015-02-16 04:46:57 +01:00
return true ;
}
2015-09-13 06:04:31 +02:00
case " info " : {
if ( args . length = = 2 ) {
2015-02-21 12:24:46 +01:00
MainUtil . sendMessage ( plr , " /plot condense " + worldname + " info <radius> " ) ;
2015-02-16 04:46:57 +01:00
return false ;
}
2015-09-13 06:04:31 +02:00
if ( ! MathMan . isInteger ( args [ 2 ] ) ) {
2015-02-21 12:24:46 +01:00
MainUtil . sendMessage ( plr , " INVALID RADIUS " ) ;
2015-02-16 04:46:57 +01:00
return false ;
}
2015-02-20 07:34:19 +01:00
final int radius = Integer . parseInt ( args [ 2 ] ) ;
2015-08-06 18:05:15 +02:00
final Collection < Plot > plots = PS . get ( ) . getPlotsInWorld ( worldname ) ;
2015-02-20 07:34:19 +01:00
final int size = plots . size ( ) ;
final int minimum_radius = ( int ) Math . ceil ( ( Math . sqrt ( size ) / 2 ) + 1 ) ;
2015-09-13 06:04:31 +02:00
if ( radius < minimum_radius ) {
2015-02-21 12:24:46 +01:00
MainUtil . sendMessage ( plr , " RADIUS TOO SMALL " ) ;
2015-02-16 06:36:47 +01:00
return false ;
}
2015-02-20 07:34:19 +01:00
final int max_move = getPlots ( plots , minimum_radius ) . size ( ) ;
final int user_move = getPlots ( plots , radius ) . size ( ) ;
2015-02-21 12:24:46 +01:00
MainUtil . sendMessage ( plr , " === DEFAULT EVAL === " ) ;
MainUtil . sendMessage ( plr , " MINIMUM RADIUS: " + minimum_radius ) ;
MainUtil . sendMessage ( plr , " MAXIMUM MOVES: " + max_move ) ;
MainUtil . sendMessage ( plr , " === INPUT EVAL === " ) ;
MainUtil . sendMessage ( plr , " INPUT RADIUS: " + radius ) ;
MainUtil . sendMessage ( plr , " ESTIMATED MOVES: " + user_move ) ;
MainUtil . sendMessage ( plr , " ESTIMATED TIME: " + " No idea, times will drastically change based on the system performance and load " ) ;
MainUtil . sendMessage ( plr , " &e - Radius is measured in plot width " ) ;
2015-02-16 04:46:57 +01:00
return true ;
}
2015-02-15 11:52:51 +01:00
}
2015-02-21 12:24:46 +01:00
MainUtil . sendMessage ( plr , " /plot condense " + worldname + " <start|stop|info> [radius] " ) ;
2015-02-16 04:46:57 +01:00
return false ;
2015-02-15 11:52:51 +01:00
}
2015-09-13 06:04:31 +02:00
public Set < PlotId > getPlots ( final Collection < Plot > plots , final int radius ) {
2015-02-20 07:34:19 +01:00
final HashSet < PlotId > outside = new HashSet < > ( ) ;
2015-09-13 06:04:31 +02:00
for ( final Plot plot : plots ) {
2016-01-10 21:00:56 +01:00
if ( ( plot . getId ( ) . x > radius ) | | ( plot . getId ( ) . x < - radius ) | | ( plot . getId ( ) . y > radius ) | | ( plot . getId ( ) . y < - radius ) ) {
outside . add ( plot . getId ( ) ) ;
2015-02-16 04:46:57 +01:00
}
}
return outside ;
2015-02-15 11:52:51 +01:00
}
}