Added new admin command to place and record structures

This command will save the structure in the structures.yml file so that
it can be made when players make a new Box. Note that the server needs
to know about these before they can be loaded (API bug?) by issuing the
/place command or having had them load sometime previously in the
server, e.g., by going into a biome. Just needs to be done once.
This commit is contained in:
tastybento 2023-03-04 18:44:10 -08:00
parent 161b254d77
commit a359f097b9
3 changed files with 142 additions and 6 deletions

View File

@ -22,6 +22,7 @@ import world.bentobox.bentobox.api.flags.Flag;
import world.bentobox.bentobox.api.flags.Flag.Mode;
import world.bentobox.bentobox.api.flags.Flag.Type;
import world.bentobox.bentobox.managers.RanksManager;
import world.bentobox.boxed.commands.AdminPlaceStructureCommand;
import world.bentobox.boxed.generators.biomes.BoxedBiomeGenerator;
import world.bentobox.boxed.generators.biomes.NetherSeedBiomeGenerator;
import world.bentobox.boxed.generators.biomes.SeedBiomeGenerator;
@ -78,7 +79,15 @@ public class Boxed extends GameModeAddon {
// Register commands
playerCommand = new DefaultPlayerCommand(this) {};
adminCommand = new DefaultAdminCommand(this) {};
adminCommand = new DefaultAdminCommand(this) {
@Override
public void setup()
{
super.setup();
new AdminPlaceStructureCommand(this);
}
};
}

View File

@ -0,0 +1,120 @@
package world.bentobox.boxed.commands;
import java.io.File;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.Optional;
import java.util.Random;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.NamespacedKey;
import org.bukkit.block.structure.Mirror;
import org.bukkit.block.structure.StructureRotation;
import org.bukkit.configuration.InvalidConfigurationException;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.structure.Structure;
import world.bentobox.bentobox.api.commands.CompositeCommand;
import world.bentobox.bentobox.api.user.User;
import world.bentobox.bentobox.util.Util;
import world.bentobox.boxed.listeners.NewAreaListener;
import world.bentobox.boxed.Boxed;
/**
* @author tastybento
*
*/
public class AdminPlaceStructureCommand extends CompositeCommand {
public AdminPlaceStructureCommand(CompositeCommand parent) {
super(parent, "place");
}
@Override
public void setup() {
this.setPermission("boxed.admin.place");
this.setOnlyPlayer(false);
this.setParametersHelp("boxed.admin.place.parameters");
this.setDescription("boxed.admin.place.description");
}
@Override
public boolean canExecute(User user, String label, List<String> args) {
// Check world
if (!((Boxed)getAddon()).inWorld(getWorld())) {
user.sendMessage("boxed.admin.place.wrong-world");
return false;
}
// Format is place <structure> ~ ~ ~ or coords
if (args.size() != 1 && args.size() != 4) {
this.showHelp(this, user);
return false;
}
List<String> options = Bukkit.getStructureManager().getStructures().keySet().stream().map(k -> k.getKey()).toList();
if (!options.contains(args.get(0).toLowerCase(Locale.ENGLISH))) {
user.sendMessage("boxed.admin.place.unknown-structure");
return false;
}
if (args.size() == 1) {
return true;
}
if ((!args.get(1).equals("~") && !Util.isInteger(args.get(1), true))
|| (!args.get(2).equals("~") && !Util.isInteger(args.get(2), true))
|| (!args.get(3).equals("~") && !Util.isInteger(args.get(3), true))) {
user.sendMessage("boxed.admin.place.use-integers");
return false;
}
// Syntax is okay
return true;
}
@Override
public boolean execute(User user, String label, List<String> args) {
NamespacedKey tag = NamespacedKey.fromString(args.get(0).toLowerCase(Locale.ENGLISH));
Structure s = Bukkit.getStructureManager().loadStructure(tag);
int x = args.size() == 1 || args.get(1).equals("~") ? user.getLocation().getBlockX() : Integer.valueOf(args.get(1).trim());
int y = args.size() == 1 || args.get(2).equals("~") ? user.getLocation().getBlockY() : Integer.valueOf(args.get(2).trim());
int z = args.size() == 1 || args.get(3).equals("~") ? user.getLocation().getBlockZ() : Integer.valueOf(args.get(3).trim());
Location spot = new Location(user.getWorld(), x, y, z);
s.place(spot, true, StructureRotation.NONE, Mirror.NONE, -1, 1, new Random());
NewAreaListener.removeJigsaw(spot, s);
getAddon().getIslands().getIslandAt(spot).ifPresent(i -> {
int xx = x - i.getCenter().getBlockX();
int zz = z - i.getCenter().getBlockZ();
File structures = new File(getAddon().getDataFolder(), "structures.yml");
YamlConfiguration config = new YamlConfiguration();
try {
config.load(structures);
config.set("structures.new." + tag.getKey(), user.getWorld().getEnvironment().name().toLowerCase() + ", " + xx + ", " + y + ", " + zz);
config.save(structures);
} catch (IOException | InvalidConfigurationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
});
return true;
}
@Override
public Optional<List<String>> tabComplete(User user, String alias, List<String> args)
{
String lastArg = !args.isEmpty() ? args.get(args.size() - 1) : "";
if (args.size() == 2) {
return Optional.of(Util.tabLimit(Bukkit.getStructureManager().getStructures().keySet().stream().map(k -> k.getKey()).toList(), lastArg));
} else if (args.size() == 3) {
return Optional.of(List.of("~", String.valueOf(user.getLocation().getBlockX())));
} else if (args.size() == 4) {
return Optional.of(List.of("~", String.valueOf(user.getLocation().getBlockY())));
} else if (args.size() == 5) {
return Optional.of(List.of("~", String.valueOf(user.getLocation().getBlockZ())));
}
return Optional.of(Collections.emptyList());
}
}

View File

@ -132,19 +132,26 @@ public class NewAreaListener implements Listener {
item.structure().place(item.location(), true, StructureRotation.NONE, Mirror.NONE, -1, 1, new Random());
addon.log("Structure placed at " + item.location);
// Find it
BoundingBox bb = BoundingBox.of(item.location(), item.structure().getSize().getX(), item.structure().getSize().getY(), item.structure().getSize().getZ());
removeJigsaw(item.location().getWorld(), bb);
removeJigsaw(item.location(), item.structure());
pasting = false;
}
private void removeJigsaw(World world, BoundingBox bb) {
/**
* Removes Jigsaw blocks from a placed structure
* @param loc - location where the structure was placed
* @param structure - structure that was placed
*/
public static void removeJigsaw(Location loc, Structure structure) {
BoundingBox bb = BoundingBox.of(loc, structure.getSize().getX(), structure.getSize().getY(), structure.getSize().getZ());
for (int x = (int) bb.getMinX(); x < bb.getMaxX(); x++) {
for (int y = (int) bb.getMinY(); y < bb.getMaxY(); y++) {
for (int z = (int) bb.getMinZ(); z < bb.getMaxZ(); z++) {
Block b = world.getBlockAt(x, y, z);
Block b = loc.getWorld().getBlockAt(x, y, z);
if (b.getType().equals(Material.JIGSAW)) {
b.setType(Material.STRUCTURE_VOID);
BentoBox.getInstance().logDebug("Removing jigsaw at : " + x + " " + y + " " +z);
} else if (b.getType().equals(Material.STRUCTURE_BLOCK)) {
// I would like to read the data from the block an do something with it!
b.setType(Material.STRUCTURE_VOID);
}
}
}