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.configuration.Settings; 023import com.plotsquared.core.configuration.caption.TranslatableCaption; 024import com.plotsquared.core.permissions.Permission; 025import com.plotsquared.core.player.PlotPlayer; 026import com.plotsquared.core.plot.Plot; 027import com.plotsquared.core.plot.flag.implementations.DoneFlag; 028import com.plotsquared.core.plot.world.PlotAreaManager; 029import com.plotsquared.core.util.PlotUploader; 030import com.plotsquared.core.util.SchematicHandler; 031import com.plotsquared.core.util.StringMan; 032import com.plotsquared.core.util.TabCompletions; 033import com.plotsquared.core.util.WorldUtil; 034import com.plotsquared.core.util.task.RunnableVal; 035import net.kyori.adventure.text.Component; 036import net.kyori.adventure.text.minimessage.tag.Tag; 037import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; 038import org.checkerframework.checker.nullness.qual.NonNull; 039 040import java.net.URL; 041import java.util.Collection; 042import java.util.Collections; 043import java.util.LinkedList; 044import java.util.List; 045import java.util.stream.Collectors; 046 047@CommandDeclaration(usage = "/plot download [schem | world]", 048 command = "download", 049 aliases = {"dl"}, 050 category = CommandCategory.SCHEMATIC, 051 requiredType = RequiredType.NONE, 052 permission = "plots.download") 053public class Download extends SubCommand { 054 055 private final PlotAreaManager plotAreaManager; 056 private final PlotUploader plotUploader; 057 @NonNull 058 private final SchematicHandler schematicHandler; 059 private final WorldUtil worldUtil; 060 061 @Inject 062 public Download( 063 final @NonNull PlotAreaManager plotAreaManager, 064 final @NonNull PlotUploader plotUploader, 065 final @NonNull SchematicHandler schematicHandler, 066 final @NonNull WorldUtil worldUtil 067 ) { 068 this.plotAreaManager = plotAreaManager; 069 this.plotUploader = plotUploader; 070 this.schematicHandler = schematicHandler; 071 this.worldUtil = worldUtil; 072 } 073 074 @Override 075 public boolean onCommand(final PlotPlayer<?> player, String[] args) { 076 String world = player.getCurrentPlot().getWorldName(); 077 if (!this.plotAreaManager.hasPlotArea(world)) { 078 player.sendMessage(TranslatableCaption.of("errors.not_in_plot_world")); 079 return false; 080 } 081 final Plot plot = player.getCurrentPlot(); 082 if (plot == null) { 083 player.sendMessage(TranslatableCaption.of("errors.not_in_plot")); 084 return false; 085 } 086 if (!plot.hasOwner()) { 087 player.sendMessage(TranslatableCaption.of("info.plot_unowned")); 088 return false; 089 } 090 if ((Settings.Done.REQUIRED_FOR_DOWNLOAD && !DoneFlag.isDone(plot)) && !player.hasPermission(Permission.PERMISSION_ADMIN_COMMAND_DOWNLOAD)) { 091 player.sendMessage(TranslatableCaption.of("done.done_not_done")); 092 return false; 093 } 094 if (!plot.isOwner(player.getUUID()) && !player.hasPermission(Permission.PERMISSION_ADMIN.toString())) { 095 player.sendMessage(TranslatableCaption.of("permission.no_plot_perms")); 096 return false; 097 } 098 if (plot.getRunning() > 0) { 099 player.sendMessage(TranslatableCaption.of("errors.wait_for_timer")); 100 return false; 101 } 102 if (args.length == 0 || (args.length == 1 && StringMan 103 .isEqualIgnoreCaseToAny(args[0], "sch", "schem", "schematic"))) { 104 if (plot.getVolume() > Integer.MAX_VALUE) { 105 player.sendMessage(TranslatableCaption.of("schematics.schematic_too_large")); 106 return false; 107 } 108 plot.addRunning(); 109 upload(player, plot); 110 } else if (args.length == 1 && StringMan 111 .isEqualIgnoreCaseToAny(args[0], "mcr", "world", "mca")) { 112 if (!player.hasPermission(Permission.PERMISSION_DOWNLOAD_WORLD)) { 113 player.sendMessage( 114 TranslatableCaption.of("permission.no_permission"), 115 TagResolver.resolver( 116 "node", 117 Tag.inserting(Permission.PERMISSION_DOWNLOAD_WORLD) 118 ) 119 ); 120 return false; 121 } 122 player.sendMessage(TranslatableCaption.of("schematics.mca_file_size")); 123 plot.addRunning(); 124 this.worldUtil.saveWorld(world); 125 this.worldUtil.upload(plot, null, null, new RunnableVal<>() { 126 @Override 127 public void run(URL url) { 128 plot.removeRunning(); 129 if (url == null) { 130 player.sendMessage( 131 TranslatableCaption.of("web.generating_link_failed"), 132 TagResolver.resolver("plot", Tag.inserting(Component.text(plot.getId().toString()))) 133 ); 134 return; 135 } 136 player.sendMessage( 137 TranslatableCaption.of("web.generation_link_success_legacy_world"), 138 TagResolver.builder() 139 .tag("url", Tag.preProcessParsed(url.toString())) 140 .build() 141 ); 142 } 143 }); 144 } else { 145 sendUsage(player); 146 return false; 147 } 148 player.sendMessage( 149 TranslatableCaption.of("web.generating_link"), 150 TagResolver.resolver("plot", Tag.inserting(Component.text(plot.getId().toString()))) 151 ); 152 return true; 153 } 154 155 @Override 156 public Collection<Command> tab(final PlotPlayer<?> player, final String[] args, final boolean space) { 157 if (args.length == 1) { 158 final List<String> completions = new LinkedList<>(); 159 if (player.hasPermission(Permission.PERMISSION_DOWNLOAD)) { 160 completions.add("schem"); 161 } 162 if (player.hasPermission(Permission.PERMISSION_DOWNLOAD_WORLD)) { 163 completions.add("world"); 164 } 165 final List<Command> commands = completions.stream().filter(completion -> completion 166 .toLowerCase() 167 .startsWith(args[0].toLowerCase())) 168 .map(completion -> new Command( 169 null, 170 true, 171 completion, 172 "", 173 RequiredType.NONE, 174 CommandCategory.ADMINISTRATION 175 ) { 176 }).collect(Collectors.toCollection(LinkedList::new)); 177 if (player.hasPermission(Permission.PERMISSION_DOWNLOAD) && args[0].length() > 0) { 178 commands.addAll(TabCompletions.completePlayers(player, args[0], Collections.emptyList())); 179 } 180 return commands; 181 } 182 return TabCompletions.completePlayers(player, String.join(",", args).trim(), Collections.emptyList()); 183 } 184 185 private void upload(PlotPlayer<?> player, Plot plot) { 186 if (Settings.Web.LEGACY_WEBINTERFACE) { 187 schematicHandler 188 .getCompoundTag(plot) 189 .whenComplete((compoundTag, throwable) -> schematicHandler.upload( 190 compoundTag, 191 null, 192 null, 193 new RunnableVal<>() { 194 @Override 195 public void run(URL value) { 196 plot.removeRunning(); 197 player.sendMessage( 198 TranslatableCaption.of("web.generation_link_success"), 199 TagResolver.builder() 200 .tag("download", Tag.preProcessParsed(value.toString())) 201 .tag("delete", Tag.preProcessParsed("Not available")) 202 .build() 203 ); 204 } 205 } 206 )); 207 return; 208 } 209 // TODO legacy support 210 this.plotUploader.upload(plot) 211 .whenComplete((result, throwable) -> { 212 if (throwable != null || !result.isSuccess()) { 213 player.sendMessage( 214 TranslatableCaption.of("web.generating_link_failed"), 215 TagResolver.resolver("plot", Tag.inserting(Component.text(plot.getId().toString()))) 216 ); 217 } else { 218 player.sendMessage( 219 TranslatableCaption.of("web.generation_link_success"), 220 TagResolver.builder() 221 .tag("download", Tag.preProcessParsed(result.getDownloadUrl())) 222 .tag("delete", Tag.preProcessParsed(result.getDeletionUrl())) 223 .build() 224 ); 225 } 226 }); 227 } 228 229}