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.StaticCaption; 024import com.plotsquared.core.configuration.caption.TranslatableCaption; 025import com.plotsquared.core.permissions.Permission; 026import com.plotsquared.core.player.MetaDataAccess; 027import com.plotsquared.core.player.PlayerMetaDataKeys; 028import com.plotsquared.core.player.PlotPlayer; 029import com.plotsquared.core.plot.Plot; 030import com.plotsquared.core.plot.PlotArea; 031import com.plotsquared.core.plot.PlotId; 032import com.plotsquared.core.plot.schematic.Schematic; 033import com.plotsquared.core.plot.world.PlotAreaManager; 034import com.plotsquared.core.util.SchematicHandler; 035import com.plotsquared.core.util.TimeUtil; 036import com.plotsquared.core.util.task.RunnableVal; 037import com.plotsquared.core.util.task.TaskManager; 038import net.kyori.adventure.text.Component; 039import net.kyori.adventure.text.minimessage.tag.Tag; 040import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; 041import org.checkerframework.checker.nullness.qual.NonNull; 042 043import java.net.MalformedURLException; 044import java.net.URI; 045import java.net.URL; 046import java.util.Collections; 047import java.util.List; 048 049@CommandDeclaration(command = "load", 050 aliases = "restore", 051 category = CommandCategory.SCHEMATIC, 052 requiredType = RequiredType.NONE, 053 permission = "plots.load", 054 usage = "/plot load") 055public class Load extends SubCommand { 056 057 private final PlotAreaManager plotAreaManager; 058 private final SchematicHandler schematicHandler; 059 060 @Inject 061 public Load( 062 final @NonNull PlotAreaManager plotAreaManager, 063 final @NonNull SchematicHandler schematicHandler 064 ) { 065 this.plotAreaManager = plotAreaManager; 066 this.schematicHandler = schematicHandler; 067 } 068 069 @Override 070 public boolean onCommand(final PlotPlayer<?> player, final String[] args) { 071 final String world = player.getCurrentPlot().getWorldName(); 072 if (!this.plotAreaManager.hasPlotArea(world)) { 073 player.sendMessage(TranslatableCaption.of("errors.not_in_plot_world")); 074 return false; 075 } 076 final Plot plot = player.getCurrentPlot(); 077 if (plot == null) { 078 player.sendMessage(TranslatableCaption.of("errors.not_in_plot")); 079 return false; 080 } 081 if (!plot.hasOwner()) { 082 player.sendMessage(TranslatableCaption.of("info.plot_unowned")); 083 return false; 084 } 085 if (!plot.isOwner(player.getUUID()) && !player.hasPermission(Permission.PERMISSION_ADMIN_COMMAND_LOAD)) { 086 player.sendMessage(TranslatableCaption.of("permission.no_plot_perms")); 087 return false; 088 } 089 if (plot.getRunning() > 0) { 090 player.sendMessage(TranslatableCaption.of("errors.wait_for_timer")); 091 return false; 092 } 093 094 try (final MetaDataAccess<List<String>> metaDataAccess = 095 player.accessTemporaryMetaData(PlayerMetaDataKeys.TEMPORARY_SCHEMATICS)) { 096 if (args.length != 0) { 097 if (args.length == 1) { 098 List<String> schematics = metaDataAccess.get().orElse(null); 099 if (schematics == null) { 100 // No schematics found: 101 player.sendMessage( 102 TranslatableCaption.of("web.load_null"), 103 TagResolver.resolver("command", Tag.inserting(Component.text("/plot load"))) 104 ); 105 return false; 106 } 107 String schematic; 108 try { 109 schematic = schematics.get(Integer.parseInt(args[0]) - 1); 110 } catch (Exception ignored) { 111 // use /plot load <index> 112 player.sendMessage( 113 TranslatableCaption.of("invalid.not_valid_number"), 114 TagResolver.resolver("value", Tag.inserting(Component.text("(1, " + schematics.size() + ')'))) 115 ); 116 return false; 117 } 118 final URL url; 119 try { 120 url = URI.create(Settings.Web.URL + "saves/" + player.getUUID() + '/' + schematic).toURL(); 121 } catch (MalformedURLException e) { 122 e.printStackTrace(); 123 player.sendMessage(TranslatableCaption.of("web.load_failed")); 124 return false; 125 } 126 plot.addRunning(); 127 player.sendMessage(TranslatableCaption.of("working.generating_component")); 128 TaskManager.runTaskAsync(() -> { 129 Schematic taskSchematic = this.schematicHandler.getSchematic(url); 130 if (taskSchematic == null) { 131 plot.removeRunning(); 132 player.sendMessage( 133 TranslatableCaption.of("schematics.schematic_invalid"), 134 TagResolver.resolver( 135 "reason", 136 Tag.inserting(Component.text("non-existent or not in gzip format")) 137 ) 138 ); 139 return; 140 } 141 PlotArea area = plot.getArea(); 142 this.schematicHandler.paste( 143 taskSchematic, 144 plot, 145 0, 146 area.getMinBuildHeight(), 147 0, 148 false, 149 player, 150 new RunnableVal<>() { 151 @Override 152 public void run(Boolean value) { 153 plot.removeRunning(); 154 if (value) { 155 player.sendMessage(TranslatableCaption.of("schematics.schematic_paste_success")); 156 } else { 157 player.sendMessage(TranslatableCaption.of("schematics.schematic_paste_failed")); 158 } 159 } 160 } 161 ); 162 }); 163 return true; 164 } 165 plot.removeRunning(); 166 player.sendMessage( 167 TranslatableCaption.of("commandconfig.command_syntax"), 168 TagResolver.resolver("value", Tag.inserting(Component.text("/plot load <index>"))) 169 ); 170 return false; 171 } 172 173 // list schematics 174 175 List<String> schematics = metaDataAccess.get().orElse(null); 176 if (schematics == null) { 177 plot.addRunning(); 178 TaskManager.runTaskAsync(() -> { 179 List<String> schematics1 = this.schematicHandler.getSaves(player.getUUID()); 180 plot.removeRunning(); 181 if ((schematics1 == null) || schematics1.isEmpty()) { 182 player.sendMessage(TranslatableCaption.of("web.load_failed")); 183 return; 184 } 185 metaDataAccess.set(schematics1); 186 displaySaves(player); 187 }); 188 } else { 189 displaySaves(player); 190 } 191 } 192 return true; 193 } 194 195 public void displaySaves(PlotPlayer<?> player) { 196 try (final MetaDataAccess<List<String>> metaDataAccess = 197 player.accessTemporaryMetaData(PlayerMetaDataKeys.TEMPORARY_SCHEMATICS)) { 198 List<String> schematics = metaDataAccess.get().orElse(Collections.emptyList()); 199 for (int i = 0; i < Math.min(schematics.size(), 32); i++) { 200 try { 201 String schematic = schematics.get(i).split("\\.")[0]; 202 String[] split = schematic.split("_"); 203 if (split.length < 5) { 204 continue; 205 } 206 String time = TimeUtil.secToTime((System.currentTimeMillis() / 1000) - Long.parseLong(split[0])); 207 String world = split[1]; 208 PlotId id = PlotId.fromString(split[2] + ';' + split[3]); 209 String size = split[4]; 210 String color = "<dark_aqua>"; 211 player.sendMessage(StaticCaption.of("<dark_gray>[</dark_gray><gray>" + (i + 1) + "</gray><dark_aqua>] </dark_aqua>" + color + time + "<dark_gray> | </dark_gray>" + color + world + ';' + id 212 + "<dark_gray> | </dark_gray>" + color + size + 'x' + size)); 213 } catch (Exception e) { 214 e.printStackTrace(); 215 } 216 } 217 player.sendMessage( 218 TranslatableCaption.of("web.load_list"), 219 TagResolver.resolver("command", Tag.inserting(Component.text("/plot load #"))) 220 ); 221 } 222 } 223 224}