Skip to content

Commit

Permalink
Added new admin command to place and record structures
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
tastybento committed Mar 5, 2023
1 parent 161b254 commit a359f09
Show file tree
Hide file tree
Showing 3 changed files with 142 additions and 6 deletions.
11 changes: 10 additions & 1 deletion src/main/java/world/bentobox/boxed/Boxed.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
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;
Expand Down Expand Up @@ -78,7 +79,15 @@ public void onLoad() {
// Register commands
playerCommand = new DefaultPlayerCommand(this) {};

adminCommand = new DefaultAdminCommand(this) {};
adminCommand = new DefaultAdminCommand(this) {
@Override
public void setup()
{
super.setup();
new AdminPlaceStructureCommand(this);
}
};


}

Expand Down
Original file line number Diff line number Diff line change
@@ -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());
}
}
17 changes: 12 additions & 5 deletions src/main/java/world/bentobox/boxed/listeners/NewAreaListener.java
Original file line number Diff line number Diff line change
Expand Up @@ -132,19 +132,26 @@ private void LoadChunksAsync(Item item) {
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);
}
}
}
Expand Down

0 comments on commit a359f09

Please sign in to comment.