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