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