Skip to content

Commit

Permalink
Refactor, renaming, and more documentation of code
Browse files Browse the repository at this point in the history
  • Loading branch information
tastybento committed Jul 5, 2023
1 parent 1f8dfb1 commit bedc6db
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
import world.bentobox.bentobox.util.Util;
import world.bentobox.boxed.Boxed;
import world.bentobox.boxed.listeners.NewAreaListener;
import world.bentobox.boxed.listeners.NewAreaListener.Item;
import world.bentobox.boxed.listeners.NewAreaListener.StructureRecord;

/**
* Enables admins to place templates in a Box and have them recorded for future boxes.
Expand Down Expand Up @@ -149,7 +149,7 @@ public boolean execute(User user, String label, List<String> args) {
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, sr, mirror, PALETTE, INTEGRITY, new Random());
NewAreaListener.removeJigsaw(new Item(tag.getKey(), s, spot, sr, mirror, noMobs));
NewAreaListener.removeJigsaw(new StructureRecord(tag.getKey(), s, spot, sr, mirror, noMobs));
boolean result = saveStructure(spot, tag, user, sr, mirror);
if (result) {
user.sendMessage("boxed.commands.boxadmin.place.saved");
Expand Down
74 changes: 56 additions & 18 deletions src/main/java/world/bentobox/boxed/listeners/NewAreaListener.java
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,19 @@
*/
public class NewAreaListener implements Listener {

/**
* Structure record contains the name of the structure, the structure itself, where it was placed and
* enums for rotation, mirror, and a flag to paste mobs or not.
* @param name - name of structure
* @param structure - Structure object
* @param location - location where it has been placed
* @param rot - rotation
* @param mirror - mirror setting
* @param noMobs - if false, mobs not pasted
*/
public record StructureRecord(String name, Structure structure, Location location, StructureRotation rot, Mirror mirror, Boolean noMobs) {};

private static final Map<Integer, EntityType> BUTCHER_ANIMALS = Map.of(0, EntityType.COW, 1, EntityType.SHEEP, 2, EntityType.PIG);
private static final List<BlockFace> CARDINALS = List.of(BlockFace.NORTH, BlockFace.SOUTH, BlockFace.EAST, BlockFace.WEST);
private static final List<String> JAR_STRUCTURES = List.of("bee", "pillager", "polar_bear", "axolotl", "allay", "parrot", "frog");
private static final List<String> STRUCTURES = List.of("ancient_city", "bastion_remnant", "bastion",
Expand All @@ -77,11 +90,10 @@ public class NewAreaListener implements Listener {
"village_savanna", "village_snowy", "village_taiga");
private final Boxed addon;
private File structureFile;
private Queue<Item> itemsToBuild = new LinkedList<>();
private Queue<StructureRecord> itemsToBuild = new LinkedList<>();
private static Random rand = new Random();
private boolean pasting;
private static Gson gson = new Gson();
public record Item(String name, Structure structure, Location location, StructureRotation rot, Mirror mirror, Boolean noMobs) {};
Pair<Integer, Integer> min = new Pair<Integer, Integer>(0,0);
Pair<Integer, Integer> max = new Pair<Integer, Integer>(0,0);
// Database handler for structure data
Expand All @@ -95,14 +107,18 @@ public record Item(String name, Structure structure, Location location, Structur
*/
public NewAreaListener(Boxed addon) {
this.addon = addon;
// Save the default structures file from the jar
addon.saveResource("structures.yml", false);
// Load the config
structureFile = new File(addon.getDataFolder(), "structures.yml");
// Get database ready
handler = new Database<>(addon, IslandStructures.class);
// Try to build something every second
Bukkit.getScheduler().runTaskTimer(addon.getPlugin(), () -> BuildItem(), 20, 20);
// Experiment: TODO: read all files in from the structure folder including the ones saved from the jar file
runStructurePrinter(addon);
}

private void runStructurePrinter(Boxed addon2) {
Bukkit.getScheduler().runTaskTimer(addon.getPlugin(), () -> buildStructure(), 20, 20);
for (String js : JAR_STRUCTURES) {
addon.saveResource("structures/" + js + ".nbt", false);
File structureFile = new File(addon.getDataFolder(), "structures/" + js + ".nbt");
Expand All @@ -112,24 +128,29 @@ public NewAreaListener(Boxed addon) {
addon.log("Loaded " + js + ".nbt");
} catch (IOException e) {
addon.logError("Error trying to load " + structureFile.getAbsolutePath());
e.printStackTrace();
addon.getPlugin().logStacktrace(e);
}

}

}

private void BuildItem() {
/**
* Build something in the queue
*/
private void buildStructure() {
// Only kick off a build if there is something to build and something isn't already being built
if (!pasting && !itemsToBuild.isEmpty()) {
// Build item
Item item = itemsToBuild.poll();
LoadChunksAsync(item);
StructureRecord item = itemsToBuild.poll();
placeStructure(item);
}
}

/**
* Build a list of structures
* @param event event
* Load known structures from the templates file.
* This makes them available for admins to use in the boxed place file.
* If this is not done, then no structures (templates) will be available.
* @param event BentoBoxReadyEvent
*/
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
public void onBentoBoxReady(BentoBoxReadyEvent event) {
Expand All @@ -147,6 +168,10 @@ public void onBentoBoxReady(BentoBoxReadyEvent event) {

}

/**
* Track if a place has entered a structure.
* @param e PlayerMoveEvent
*/
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
public void onPlayerMove(PlayerMoveEvent e) {
// Ignore head movements
Expand Down Expand Up @@ -195,6 +220,11 @@ private void giveAdvFromCriteria(Player player, String string) {

}

/**
* Get all the known island structures for this island
* @param islandId - island ID
* @return IslandStructures
*/
private IslandStructures getIslandStructData(String islandId) {
// Return from cache if it exists
if (islandStructureCache.containsKey(islandId)) {
Expand Down Expand Up @@ -270,20 +300,22 @@ private void place(String string, ConfigurationSection section, Location center,
int y = Integer.valueOf(value[1].strip());
int z = Integer.valueOf(value[2].strip()) + center.getBlockZ();
Location l = new Location(world, x, y, z);
itemsToBuild.add(new Item(name, s, l, rot, mirror, noMobs));
itemsToBuild.add(new StructureRecord(name, s, l, rot, mirror, noMobs));
} else {
addon.logError("Structure file syntax error: " + vector + ": " + value);
}
}
}

private void LoadChunksAsync(Item item) {
private void placeStructure(StructureRecord item) {
// Set the semaphore - only paste one at a time
pasting = true;
// Place the structure
item.structure().place(item.location(), true, item.rot(), item.mirror(), -1, 1, rand);
addon.log(item.name() + " placed at " + item.location().getWorld().getName() + " " + Util.xyz(item.location().toVector()));
// Find it
// Remove any jigsaw artifacts
BoundingBox bb = removeJigsaw(item);
// Store it
// Store it for future reference
addon.getIslands().getIslandAt(item.location()).map(Island::getUniqueId).ifPresent(id -> {
addon.log("Saved " + item.name());
if (item.location().getWorld().getEnvironment().equals(Environment.NETHER)) {
Expand All @@ -293,7 +325,7 @@ private void LoadChunksAsync(Item item) {
}
handler.saveObjectAsync(getIslandStructData(id));
});

// Clear the semaphore
pasting = false;
}

Expand All @@ -302,7 +334,7 @@ private void LoadChunksAsync(Item item) {
* @param item - record of what's required
* @return the resulting bounding box of the structure
*/
public static BoundingBox removeJigsaw(Item item) {
public static BoundingBox removeJigsaw(StructureRecord item) {
Location loc = item.location();
Structure structure = item.structure();
StructureRotation structureRotation = item.rot();
Expand Down Expand Up @@ -342,6 +374,13 @@ public static BoundingBox removeJigsaw(Item item) {
}


/**
* Process a structure block. Sets it to a structure void at a minimum.
* If the structure block has meta data indicating it is a chest, then it will fill
* the chest with a buried treasure loot. If it is waterlogged, then it will change
* the void to water.
* @param b structure block block
*/
private static void processStructureBlock(Block b) {
// I would like to read the data from the block an do something with it!
String data = nmsData(b);
Expand All @@ -365,7 +404,6 @@ private static void processStructureBlock(Block b) {
}
}

private static final Map<Integer, EntityType> BUTCHER_ANIMALS = Map.of(0, EntityType.COW, 1, EntityType.SHEEP, 2, EntityType.PIG);
private static void processJigsaw(Block b, StructureRotation structureRotation, boolean pasteMobs) {
String data = nmsData(b);
BoxedJigsawBlock bjb = gson.fromJson(data, BoxedJigsawBlock.class);
Expand Down

0 comments on commit bedc6db

Please sign in to comment.