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.Component; 040import net.kyori.adventure.text.minimessage.tag.Tag; 041import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; 042import org.checkerframework.checker.nullness.qual.NonNull; 043 044import java.util.Arrays; 045import java.util.Collection; 046import java.util.LinkedHashSet; 047import java.util.List; 048import java.util.Locale; 049import java.util.stream.Collectors; 050import java.util.stream.Stream; 051 052@CommandDeclaration(command = "debugexec", 053 permission = "plots.admin", 054 aliases = {"exec", "$"}, 055 category = CommandCategory.DEBUG) 056public class DebugExec extends SubCommand { 057 058 private final PlotAreaManager plotAreaManager; 059 private final EventDispatcher eventDispatcher; 060 private final HybridUtils hybridUtils; 061 062 063 @Inject 064 public DebugExec( 065 final @NonNull PlotAreaManager plotAreaManager, 066 final @NonNull EventDispatcher eventDispatcher, 067 final @NonNull HybridUtils hybridUtils 068 ) { 069 this.plotAreaManager = plotAreaManager; 070 this.eventDispatcher = eventDispatcher; 071 this.hybridUtils = hybridUtils; 072 073 } 074 075 @Override 076 public boolean onCommand(final PlotPlayer<?> player, String[] args) { 077 List<String> allowedParams = Arrays 078 .asList( 079 "analyze", 080 "calibrate-analysis", 081 "start-expire", 082 "stop-expire", 083 "remove-flag", 084 "start-rgar", 085 "stop-rgar" 086 ); 087 if (args.length > 0) { 088 String arg = args[0].toLowerCase(); 089 switch (arg) { 090 case "analyze" -> { 091 Plot plot = player.getCurrentPlot(); 092 if (plot == null) { 093 player.sendMessage(TranslatableCaption.of("errors.not_in_plot")); 094 return false; 095 } 096 PlotAnalysis analysis = plot.getComplexity(null); 097 if (analysis != null) { 098 player.sendMessage( 099 TranslatableCaption.of("debugexec.changes_column"), 100 TagResolver.resolver("value", Tag.inserting(Component.text(analysis.changes))) 101 ); 102 return true; 103 } 104 player.sendMessage(TranslatableCaption.of("debugexec.starting_task")); 105 this.hybridUtils.analyzePlot(plot, new RunnableVal<>() { 106 @Override 107 public void run(PlotAnalysis value) { 108 player.sendMessage( 109 TranslatableCaption.of("debugexec.analyze_done"), 110 TagResolver.resolver("command", Tag.inserting(Component.text("/plot debugexec analyze"))) 111 ); 112 } 113 }); 114 return true; 115 } 116 case "calibrate-analysis" -> { 117 if (args.length != 2) { 118 player.sendMessage( 119 TranslatableCaption.of("commandconfig.command_syntax"), 120 TagResolver.resolver( 121 "value", 122 Tag.inserting(Component.text("/plot debugexec analyze <threshold>")) 123 ) 124 ); 125 player.sendMessage(TranslatableCaption.of("debugexec.threshold_default")); 126 return false; 127 } 128 double threshold; 129 try { 130 threshold = Integer.parseInt(args[1]) / 100d; 131 } catch (NumberFormatException ignored) { 132 player.sendMessage( 133 TranslatableCaption.of("debugexec.invalid_threshold"), 134 TagResolver.resolver("value", Tag.inserting(Component.text(args[1]))) 135 ); 136 player.sendMessage(TranslatableCaption.of("debugexec.threshold_default_double")); 137 return false; 138 } 139 PlotAnalysis.calcOptimalModifiers( 140 () -> player.sendMessage(TranslatableCaption.of("debugexec.calibration_done")), 141 threshold 142 ); 143 return true; 144 } 145 case "start-expire" -> { 146 if (PlotSquared.platform().expireManager().runAutomatedTask()) { 147 player.sendMessage(TranslatableCaption.of("debugexec.expiry_started")); 148 } else { 149 player.sendMessage(TranslatableCaption.of("debugexec.expiry_already_started")); 150 } 151 return true; 152 } 153 case "stop-expire" -> { 154 if (!PlotSquared.platform().expireManager().cancelTask()) { 155 player.sendMessage(TranslatableCaption.of("debugexec.task_halted")); 156 } else { 157 player.sendMessage(TranslatableCaption.of("debugexec.task_cancelled")); 158 } 159 return true; 160 } 161 case "remove-flag" -> { 162 if (args.length != 2) { 163 player.sendMessage( 164 TranslatableCaption.of("commandconfig.command_syntax"), 165 TagResolver.resolver("value", Tag.inserting(Component.text("/plot debugexec remove-flag <flag>"))) 166 ); 167 return false; 168 } 169 String flag = args[1]; 170 final PlotFlag<?, ?> flagInstance = 171 GlobalFlagContainer.getInstance().getFlagFromString(flag); 172 if (flagInstance != null) { 173 for (Plot plot : PlotQuery.newQuery().whereBasePlot()) { 174 PlotFlagRemoveEvent event = this.eventDispatcher 175 .callFlagRemove(flagInstance, plot); 176 if (event.getEventResult() != Result.DENY) { 177 plot.removeFlag(event.getFlag()); 178 } 179 } 180 } 181 player.sendMessage( 182 TranslatableCaption.of("debugexec.cleared_flag"), 183 TagResolver.resolver("value", Tag.inserting(Component.text(flag))) 184 ); 185 return true; 186 } 187 case "start-rgar" -> { 188 if (args.length != 2) { 189 player.sendMessage( 190 TranslatableCaption.of("commandconfig.command_syntax"), 191 TagResolver.resolver( 192 "value", 193 Tag.inserting(Component.text("Invalid syntax: /plot debugexec start-rgar <world>")) 194 ) 195 ); 196 return false; 197 } 198 PlotArea area = this.plotAreaManager.getPlotAreaByString(args[1]); 199 if (area == null) { 200 player.sendMessage( 201 TranslatableCaption.of("errors.not_valid_plot_world"), 202 TagResolver.resolver("value", Tag.inserting(Component.text(args[1]))) 203 ); 204 return false; 205 } 206 boolean result; 207 if (HybridUtils.regions != null) { 208 result = this.hybridUtils.scheduleRoadUpdate(area, HybridUtils.regions, 0, new LinkedHashSet<>()); 209 } else { 210 result = this.hybridUtils.scheduleRoadUpdate(area, 0); 211 } 212 if (!result) { 213 player.sendMessage(TranslatableCaption.of("debugexec.mass_schematic_update_in_progress")); 214 return false; 215 } 216 return true; 217 } 218 case "stop-rgar" -> { 219 if (!HybridUtils.UPDATE) { 220 player.sendMessage(TranslatableCaption.of("debugexec.task_not_running")); 221 return false; 222 } 223 HybridUtils.UPDATE = false; 224 player.sendMessage(TranslatableCaption.of("debugexec.task_cancelled")); 225 return true; 226 } 227 } 228 } 229 player.sendMessage(StaticCaption.of("<prefix><gold>Possible sub commands: </gold><gray>/plot debugexec <" 230 + StringMan.join(allowedParams, " | ") + "></gray>")); 231 return false; 232 } 233 234 @Override 235 public Collection<Command> tab(final PlotPlayer<?> player, String[] args, boolean space) { 236 return Stream.of("analyze", "calibrate-analysis", "start-expire", "stop-expire", "remove-flag", "start-rgar", "stop-rgar") 237 .filter(value -> value.startsWith(args[0].toLowerCase(Locale.ENGLISH))) 238 .map(value -> new Command(null, false, value, "plots.admin", RequiredType.NONE, null) { 239 }).collect(Collectors.toList()); 240 } 241 242}