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.player.PlotPlayer; 026import com.plotsquared.core.plot.world.PlotAreaManager; 027import com.plotsquared.core.util.StringMan; 028import com.plotsquared.core.util.WorldUtil; 029import com.plotsquared.core.util.entity.EntityCategories; 030import com.plotsquared.core.util.entity.EntityCategory; 031import com.plotsquared.core.util.query.PlotQuery; 032import com.plotsquared.core.util.task.TaskManager; 033import com.plotsquared.core.uuid.UUIDMapping; 034import com.sk89q.worldedit.world.entity.EntityType; 035import net.kyori.adventure.text.Component; 036import net.kyori.adventure.text.TextComponent; 037import net.kyori.adventure.text.minimessage.tag.Tag; 038import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; 039import org.checkerframework.checker.nullness.qual.NonNull; 040 041import java.util.Collection; 042import java.util.Comparator; 043import java.util.Locale; 044import java.util.Map; 045import java.util.Set; 046import java.util.stream.Collectors; 047import java.util.stream.Stream; 048 049@CommandDeclaration(command = "debug", 050 category = CommandCategory.DEBUG, 051 usage = "/plot debug", 052 permission = "plots.admin") 053public class Debug extends SubCommand { 054 055 private final PlotAreaManager plotAreaManager; 056 private final WorldUtil worldUtil; 057 058 @Inject 059 public Debug( 060 final @NonNull PlotAreaManager plotAreaManager, 061 final @NonNull WorldUtil worldUtil 062 ) { 063 this.plotAreaManager = plotAreaManager; 064 this.worldUtil = worldUtil; 065 } 066 067 @Override 068 public boolean onCommand(PlotPlayer<?> player, String[] args) { 069 if (args.length == 0) { 070 player.sendMessage( 071 TranslatableCaption.of("commandconfig.command_syntax"), 072 TagResolver.resolver( 073 "value", 074 Tag.inserting(Component.text("/plot debug <loadedchunks | player | debug-players | entitytypes | msg>")) 075 ) 076 ); 077 } 078 if (args.length > 0) { 079 if ("player".equalsIgnoreCase(args[0])) { 080 for (Map.Entry<String, Object> meta : player.getMeta().entrySet()) { 081 player.sendMessage(StaticCaption.of("Key: " + meta.getKey() + " Value: " + meta 082 .getValue() 083 .toString() + " , ")); 084 } 085 return true; 086 } 087 } 088 if (args.length > 0 && "loadedchunks".equalsIgnoreCase(args[0])) { 089 final long start = System.currentTimeMillis(); 090 player.sendMessage(TranslatableCaption.of("debug.fetching_loaded_chunks")); 091 TaskManager.runTaskAsync(() -> player.sendMessage(StaticCaption 092 .of("Loaded chunks: " + this.worldUtil 093 .getChunkChunks(player.getLocation().getWorldName()) 094 .size() + " (" + (System.currentTimeMillis() 095 - start) + "ms) using thread: " + Thread.currentThread().getName()))); 096 return true; 097 } 098 if (args.length > 0 && "uuids".equalsIgnoreCase(args[0])) { 099 final Collection<UUIDMapping> mappings = PlotSquared.get().getImpromptuUUIDPipeline().getAllImmediately(); 100 player.sendMessage( 101 TranslatableCaption.of("debug.cached_uuids"), 102 TagResolver.resolver("value", Tag.inserting(Component.text(mappings.size()))) 103 ); 104 return true; 105 } 106 if (args.length > 0 && "debug-players".equalsIgnoreCase(args[0])) { 107 player.sendMessage(TranslatableCaption.of("debug.player_in_debugmode")); 108 for (final PlotPlayer<?> pp : PlotPlayer.getDebugModePlayers()) { 109 player.sendMessage( 110 TranslatableCaption.of("debug.player_in_debugmode_list"), 111 TagResolver.resolver("value", Tag.inserting(Component.text(pp.getName()))) 112 ); 113 } 114 return true; 115 } 116 if (args.length > 0 && "entitytypes".equalsIgnoreCase(args[0])) { 117 EntityCategories.init(); 118 player.sendMessage(TranslatableCaption.of("debug.entity_categories")); 119 EntityCategory.REGISTRY.forEach(category -> { 120 final StringBuilder builder = 121 new StringBuilder("<gray>-</gray> <gold>").append(category.getId()).append("</gold><gray>: <gold>"); 122 for (final EntityType entityType : category.getAll()) { 123 builder.append(entityType.getId()).append(" "); 124 } 125 builder.append("</gold>"); 126 player.sendMessage(StaticCaption.of("<prefix>" + builder)); 127 }); 128 EntityType.REGISTRY.values().stream().sorted(Comparator.comparing(EntityType::getId)) 129 .forEach(entityType -> { 130 long categoryCount = EntityCategory.REGISTRY.values().stream() 131 .filter(category -> category.contains(entityType)).count(); 132 if (categoryCount > 0) { 133 return; 134 } 135 player.sendMessage(StaticCaption.of("<prefix>" + entityType.getName() + " is in " 136 + categoryCount + " categories")); 137 }); 138 return true; 139 } 140 Set<TranslatableCaption> captions = PlotSquared 141 .get() 142 .getCaptionMap(TranslatableCaption.DEFAULT_NAMESPACE) 143 .getCaptions(); 144 TextComponent.Builder information = Component.text(); 145 Component header = TranslatableCaption.of("debug.debug_header").toComponent(player) 146 .append(Component.newline()); 147 String line = TranslatableCaption.of("debug.debug_line").getComponent(player) + "\n"; 148 String section = TranslatableCaption.of("debug.debug_section").getComponent(player) + "\n"; 149 information.append(header); 150 information.append(MINI_MESSAGE.deserialize( 151 section, 152 TagResolver.resolver("val", Tag.inserting(Component.text("PlotArea"))) 153 )); 154 information.append(MINI_MESSAGE 155 .deserialize( 156 line, 157 TagResolver.builder() 158 .tag("var", Tag.inserting(Component.text("Plot Worlds"))) 159 .tag( 160 "val", 161 Tag.inserting(Component.text(StringMan.join( 162 this.plotAreaManager.getAllPlotAreas(), 163 ", " 164 ))) 165 ) 166 .build() 167 )); 168 information.append( 169 MINI_MESSAGE.deserialize( 170 line, 171 TagResolver.builder() 172 .tag("var", Tag.inserting(Component.text("Owned Plots"))) 173 .tag( 174 "val", 175 Tag.inserting(Component.text(PlotQuery.newQuery().allPlots().count())) 176 ) 177 .build() 178 )); 179 information.append(MINI_MESSAGE.deserialize( 180 section, 181 TagResolver.resolver("val", Tag.inserting(Component.text("Messages"))) 182 )); 183 information.append(MINI_MESSAGE.deserialize( 184 line, 185 TagResolver.builder() 186 .tag("var", Tag.inserting(Component.text("Total Messages"))) 187 .tag( 188 "val", 189 Tag.inserting(Component.text(captions.size())) 190 ) 191 .build() 192 )); 193 player.sendMessage(StaticCaption.of(MINI_MESSAGE.serialize(information.build()))); 194 return true; 195 } 196 197 @Override 198 public Collection<Command> tab(final PlotPlayer<?> player, String[] args, boolean space) { 199 return Stream.of("loadedchunks", "debug-players", "entitytypes") 200 .filter(value -> value.startsWith(args[0].toLowerCase(Locale.ENGLISH))) 201 .map(value -> new Command(null, false, value, "plots.admin", RequiredType.NONE, null) { 202 }).collect(Collectors.toList()); 203 } 204 205}