001/* 002 * PlotSquared, a land and world management plugin for Minecraft. 003 * Copyright (C) IntellectualSites <https://intellectualsites.com> 004 * Copyright (C) IntellectualSites team and contributors 005 * 006 * This program is free software: you can redistribute it and/or modify 007 * it under the terms of the GNU General Public License as published by 008 * the Free Software Foundation, either version 3 of the License, or 009 * (at your option) any later version. 010 * 011 * This program is distributed in the hope that it will be useful, 012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 014 * GNU General Public License for more details. 015 * 016 * You should have received a copy of the GNU General Public License 017 * along with this program. If not, see <https://www.gnu.org/licenses/>. 018 */ 019package com.plotsquared.core.command; 020 021import com.google.inject.Inject; 022import com.plotsquared.core.PlotSquared; 023import com.plotsquared.core.configuration.caption.StaticCaption; 024import com.plotsquared.core.configuration.caption.TranslatableCaption; 025import com.plotsquared.core.events.PlotFlagRemoveEvent; 026import com.plotsquared.core.events.Result; 027import com.plotsquared.core.generator.HybridUtils; 028import com.plotsquared.core.player.PlotPlayer; 029import com.plotsquared.core.plot.Plot; 030import com.plotsquared.core.plot.PlotArea; 031import com.plotsquared.core.plot.expiration.PlotAnalysis; 032import com.plotsquared.core.plot.flag.GlobalFlagContainer; 033import com.plotsquared.core.plot.flag.PlotFlag; 034import com.plotsquared.core.plot.world.PlotAreaManager; 035import com.plotsquared.core.util.EventDispatcher; 036import com.plotsquared.core.util.StringMan; 037import com.plotsquared.core.util.query.PlotQuery; 038import com.plotsquared.core.util.task.RunnableVal; 039import net.kyori.adventure.text.minimessage.Template; 040import org.checkerframework.checker.nullness.qual.NonNull; 041 042import java.util.Arrays; 043import java.util.Collection; 044import java.util.LinkedHashSet; 045import java.util.List; 046import java.util.Locale; 047import java.util.stream.Collectors; 048import java.util.stream.Stream; 049 050@CommandDeclaration(command = "debugexec", 051 permission = "plots.admin", 052 aliases = {"exec", "$"}, 053 category = CommandCategory.DEBUG) 054public class DebugExec extends SubCommand { 055 056 private final PlotAreaManager plotAreaManager; 057 private final EventDispatcher eventDispatcher; 058 private final HybridUtils hybridUtils; 059 060 061 @Inject 062 public DebugExec( 063 final @NonNull PlotAreaManager plotAreaManager, 064 final @NonNull EventDispatcher eventDispatcher, 065 final @NonNull HybridUtils hybridUtils 066 ) { 067 this.plotAreaManager = plotAreaManager; 068 this.eventDispatcher = eventDispatcher; 069 this.hybridUtils = hybridUtils; 070 071 } 072 073 @Override 074 public boolean onCommand(final PlotPlayer<?> player, String[] args) { 075 List<String> allowedParams = Arrays 076 .asList( 077 "analyze", 078 "calibrate-analysis", 079 "start-expire", 080 "stop-expire", 081 "remove-flag", 082 "start-rgar", 083 "stop-rgar" 084 ); 085 if (args.length > 0) { 086 String arg = args[0].toLowerCase(); 087 switch (arg) { 088 case "analyze" -> { 089 Plot plot = player.getCurrentPlot(); 090 if (plot == null) { 091 player.sendMessage(TranslatableCaption.of("errors.not_in_plot")); 092 return false; 093 } 094 PlotAnalysis analysis = plot.getComplexity(null); 095 if (analysis != null) { 096 player.sendMessage( 097 TranslatableCaption.of("debugexec.changes_column"), 098 Template.of("value", String.valueOf(analysis.changes)) 099 ); 100 return true; 101 } 102 player.sendMessage(TranslatableCaption.of("debugexec.starting_task")); 103 this.hybridUtils.analyzePlot(plot, new RunnableVal<>() { 104 @Override 105 public void run(PlotAnalysis value) { 106 player.sendMessage( 107 TranslatableCaption.of("debugexec.analyze_done"), 108 Template.of("command", "/plot debugexec analyze") 109 ); 110 } 111 }); 112 return true; 113 } 114 case "calibrate-analysis" -> { 115 if (args.length != 2) { 116 player.sendMessage( 117 TranslatableCaption.of("commandconfig.command_syntax"), 118 Template.of("value", "/plot debugexec analyze <threshold>") 119 ); 120 player.sendMessage(TranslatableCaption.of("debugexec.threshold_default")); 121 return false; 122 } 123 double threshold; 124 try { 125 threshold = Integer.parseInt(args[1]) / 100d; 126 } catch (NumberFormatException ignored) { 127 player.sendMessage( 128 TranslatableCaption.of("debugexec.invalid_threshold"), 129 Template.of("value", args[1]) 130 ); 131 player.sendMessage(TranslatableCaption.of("debugexec.threshold_default_double")); 132 return false; 133 } 134 PlotAnalysis.calcOptimalModifiers( 135 () -> player.sendMessage(TranslatableCaption.of("debugexec.calibration_done")), 136 threshold 137 ); 138 return true; 139 } 140 case "start-expire" -> { 141 if (PlotSquared.platform().expireManager().runAutomatedTask()) { 142 player.sendMessage(TranslatableCaption.of("debugexec.expiry_started")); 143 } else { 144 player.sendMessage(TranslatableCaption.of("debugexec.expiry_already_started")); 145 } 146 return true; 147 } 148 case "stop-expire" -> { 149 if (!PlotSquared.platform().expireManager().cancelTask()) { 150 player.sendMessage(TranslatableCaption.of("debugexec.task_halted")); 151 } else { 152 player.sendMessage(TranslatableCaption.of("debugexec.task_cancelled")); 153 } 154 return true; 155 } 156 case "remove-flag" -> { 157 if (args.length != 2) { 158 player.sendMessage( 159 TranslatableCaption.of("commandconfig.command_syntax"), 160 Template.of("value", "/plot debugexec remove-flag <flag>") 161 ); 162 return false; 163 } 164 String flag = args[1]; 165 final PlotFlag<?, ?> flagInstance = 166 GlobalFlagContainer.getInstance().getFlagFromString(flag); 167 if (flagInstance != null) { 168 for (Plot plot : PlotQuery.newQuery().whereBasePlot()) { 169 PlotFlagRemoveEvent event = this.eventDispatcher 170 .callFlagRemove(flagInstance, plot); 171 if (event.getEventResult() != Result.DENY) { 172 plot.removeFlag(event.getFlag()); 173 } 174 } 175 } 176 player.sendMessage( 177 TranslatableCaption.of("debugexec.cleared_flag"), 178 Template.of("value", flag) 179 ); 180 return true; 181 } 182 case "start-rgar" -> { 183 if (args.length != 2) { 184 player.sendMessage( 185 TranslatableCaption.of("commandconfig.command_syntax"), 186 Template.of("value", "Invalid syntax: /plot debugexec start-rgar <world>") 187 ); 188 return false; 189 } 190 PlotArea area = this.plotAreaManager.getPlotAreaByString(args[1]); 191 if (area == null) { 192 player.sendMessage( 193 TranslatableCaption.of("errors.not_valid_plot_world"), 194 Template.of("value", args[1]) 195 ); 196 return false; 197 } 198 boolean result; 199 if (HybridUtils.regions != null) { 200 result = this.hybridUtils.scheduleRoadUpdate(area, HybridUtils.regions, 0, new LinkedHashSet<>()); 201 } else { 202 result = this.hybridUtils.scheduleRoadUpdate(area, 0); 203 } 204 if (!result) { 205 player.sendMessage(TranslatableCaption.of("debugexec.mass_schematic_update_in_progress")); 206 return false; 207 } 208 return true; 209 } 210 case "stop-rgar" -> { 211 if (!HybridUtils.UPDATE) { 212 player.sendMessage(TranslatableCaption.of("debugexec.task_not_running")); 213 return false; 214 } 215 HybridUtils.UPDATE = false; 216 player.sendMessage(TranslatableCaption.of("debugexec.task_cancelled")); 217 return true; 218 } 219 } 220 } 221 player.sendMessage(StaticCaption.of("<prefix><gold>Possible sub commands: </gold><gray>/plot debugexec <" 222 + StringMan.join(allowedParams, " | ") + "></gray>")); 223 return false; 224 } 225 226 @Override 227 public Collection<Command> tab(final PlotPlayer<?> player, String[] args, boolean space) { 228 return Stream.of("analyze", "calibrate-analysis", "start-expire", "stop-expire", "remove-flag", "start-rgar", "stop-rgar") 229 .filter(value -> value.startsWith(args[0].toLowerCase(Locale.ENGLISH))) 230 .map(value -> new Command(null, false, value, "plots.admin", RequiredType.NONE, null) { 231 }).collect(Collectors.toList()); 232 } 233 234}