diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 825b18d..0bc21e0 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -14,11 +14,11 @@ jobs:
- uses: actions/checkout@v3
with:
fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis
- - name: Set up JDK 17
+ - name: Set up JDK 21
uses: actions/setup-java@v3
with:
distribution: 'adopt'
- java-version: 17
+ java-version: 21
- name: Cache SonarCloud packages
uses: actions/cache@v3
with:
diff --git a/pom.xml b/pom.xml
index ea38ff5..19d65d7 100644
--- a/pom.xml
+++ b/pom.xml
@@ -178,7 +178,36 @@
${spigot.version}
provided
-
+
+ org.spigotmc.....
+ spigot
+ 1.21-R0.1-SNAPSHOT
+ provided
+
+
+ org.spigotmc....
+ spigot
+ 1.20.6-R0.1-SNAPSHOT
+ provided
+
+
+ org.spigotmc.
+ spigot
+ 1.20.3-R0.1-SNAPSHOT
+ provided
+
+
+ org.spigotmc..
+ spigot
+ 1.20.2-R0.1-SNAPSHOT
+ provided
+
+
+ org.spigotmc...
+ spigot
+ 1.20.1-R0.1-SNAPSHOT
+ provided
+
diff --git a/src/main/java/world/bentobox/boxed/listeners/NewAreaListener.java b/src/main/java/world/bentobox/boxed/listeners/NewAreaListener.java
index 64787cc..579f01c 100644
--- a/src/main/java/world/bentobox/boxed/listeners/NewAreaListener.java
+++ b/src/main/java/world/bentobox/boxed/listeners/NewAreaListener.java
@@ -2,7 +2,6 @@
import java.io.File;
import java.io.IOException;
-import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedList;
@@ -27,7 +26,6 @@
import org.bukkit.block.structure.StructureRotation;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.YamlConfiguration;
-import org.bukkit.craftbukkit.v1_20_R3.CraftWorld;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
@@ -43,10 +41,6 @@
import com.google.common.base.Enums;
import com.google.gson.Gson;
-import net.minecraft.core.BlockPosition;
-import net.minecraft.nbt.NBTTagCompound;
-import net.minecraft.network.protocol.game.PacketPlayOutTileEntityData;
-import net.minecraft.world.level.block.entity.TileEntity;
import world.bentobox.bentobox.BentoBox;
import world.bentobox.bentobox.api.events.BentoBoxReadyEvent;
import world.bentobox.bentobox.api.events.island.IslandCreatedEvent;
@@ -56,6 +50,7 @@
import world.bentobox.bentobox.util.Pair;
import world.bentobox.bentobox.util.Util;
import world.bentobox.boxed.Boxed;
+import world.bentobox.boxed.nms.AbstractMetaData;
import world.bentobox.boxed.objects.BoxedJigsawBlock;
import world.bentobox.boxed.objects.BoxedStructureBlock;
import world.bentobox.boxed.objects.IslandStructures;
@@ -78,22 +73,22 @@ public class NewAreaListener implements Listener {
* @param noMobs - if false, mobs not pasted
*/
public record StructureRecord(String name, Structure structure, Location location, StructureRotation rot,
- Mirror mirror, Boolean noMobs) {
+ Mirror mirror, Boolean noMobs) {
}
private static final Map BUTCHER_ANIMALS = Map.of(0, EntityType.COW, 1, EntityType.SHEEP, 2,
- EntityType.PIG);
+ EntityType.PIG);
private static final List CARDINALS = List.of(BlockFace.NORTH, BlockFace.SOUTH, BlockFace.EAST,
- BlockFace.WEST);
+ BlockFace.WEST);
private static final List JAR_STRUCTURES = List.of("bee", "pillager", "polar_bear", "axolotl", "allay",
- "parrot", "frog");
+ "parrot", "frog");
private static final List STRUCTURES = List.of("ancient_city", "bastion_remnant", "bastion",
- "buried_treasure", "desert_pyramid", "end_city", "fortress", "igloo", "jungle_pyramid", "mansion",
- "mineshaft", "mineshaft_mesa", "monument", "nether_fossil", "ocean_ruin_cold", "ocean_ruin_warm",
- "pillager_outpost", "ruined_portal_desert", "ruined_portal_jungle", "ruined_portal_mountain",
- "ruined_portal_nether", "ruined_portal_ocean", "ruined_portal_swamp", "ruined_portal", "shipwreck_beached",
- "shipwreck", "stronghold", "swamp_hut", "village_desert", "village_plains", "village_savanna",
- "village_snowy", "village_taiga");
+ "buried_treasure", "desert_pyramid", "end_city", "fortress", "igloo", "jungle_pyramid", "mansion",
+ "mineshaft", "mineshaft_mesa", "monument", "nether_fossil", "ocean_ruin_cold", "ocean_ruin_warm",
+ "pillager_outpost", "ruined_portal_desert", "ruined_portal_jungle", "ruined_portal_mountain",
+ "ruined_portal_nether", "ruined_portal_ocean", "ruined_portal_swamp", "ruined_portal", "shipwreck_beached",
+ "shipwreck", "stronghold", "swamp_hut", "village_desert", "village_plains", "village_savanna",
+ "village_snowy", "village_taiga");
private final Boxed addon;
private final File structureFile;
private final Queue itemsToBuild = new LinkedList<>();
@@ -110,31 +105,31 @@ public record StructureRecord(String name, Structure structure, Location locatio
* @param addon addon
*/
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
- runStructurePrinter(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
+ runStructurePrinter(addon);
}
private void runStructurePrinter(Boxed addon2) {
- Bukkit.getScheduler().runTaskTimer(addon.getPlugin(), this::buildStructure, 20, 20);
- for (String js : JAR_STRUCTURES) {
- addon.saveResource("structures/" + js + ".nbt", false);
- File structureFile = new File(addon.getDataFolder(), "structures/" + js + ".nbt");
- try {
- Structure s = Bukkit.getStructureManager().loadStructure(structureFile);
- Bukkit.getStructureManager().registerStructure(NamespacedKey.fromString("minecraft:boxed/" + js), s);
- addon.log("Loaded " + js + ".nbt");
- } catch (IOException e) {
- addon.logError("Error trying to load " + structureFile.getAbsolutePath());
- addon.getPlugin().logStacktrace(e);
- }
- }
+ Bukkit.getScheduler().runTaskTimer(addon.getPlugin(), this::buildStructure, 20, 20);
+ for (String js : JAR_STRUCTURES) {
+ addon.saveResource("structures/" + js + ".nbt", false);
+ File structureFile = new File(addon.getDataFolder(), "structures/" + js + ".nbt");
+ try {
+ Structure s = Bukkit.getStructureManager().loadStructure(structureFile);
+ Bukkit.getStructureManager().registerStructure(NamespacedKey.fromString("minecraft:boxed/" + js), s);
+ addon.log("Loaded " + js + ".nbt");
+ } catch (IOException e) {
+ addon.logError("Error trying to load " + structureFile.getAbsolutePath());
+ addon.getPlugin().logStacktrace(e);
+ }
+ }
}
@@ -142,13 +137,13 @@ private void runStructurePrinter(Boxed addon2) {
* 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
- StructureRecord item = itemsToBuild.poll();
- placeStructure(item);
- }
+ // Only kick off a build if there is something to build and something isn't
+ // already being built
+ if (!pasting && !itemsToBuild.isEmpty()) {
+ // Build item
+ StructureRecord item = itemsToBuild.poll();
+ placeStructure(item);
+ }
}
/**
@@ -160,17 +155,17 @@ private void buildStructure() {
*/
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
public void onBentoBoxReady(BentoBoxReadyEvent event) {
- addon.saveResource("templates.yml", false);
- File templateFile = new File(addon.getDataFolder(), "templates.yml");
- if (templateFile.exists()) {
- YamlConfiguration loader = YamlConfiguration.loadConfiguration(templateFile);
- List list = loader.getStringList("templates");
- for (String struct : list) {
- if (!struct.endsWith("/")) {
- Bukkit.getStructureManager().loadStructure(NamespacedKey.fromString(struct));
- }
- }
- }
+ addon.saveResource("templates.yml", false);
+ File templateFile = new File(addon.getDataFolder(), "templates.yml");
+ if (templateFile.exists()) {
+ YamlConfiguration loader = YamlConfiguration.loadConfiguration(templateFile);
+ List list = loader.getStringList("templates");
+ for (String struct : list) {
+ if (!struct.endsWith("/")) {
+ Bukkit.getStructureManager().loadStructure(NamespacedKey.fromString(struct));
+ }
+ }
+ }
}
@@ -181,31 +176,31 @@ public void onBentoBoxReady(BentoBoxReadyEvent event) {
*/
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
public void onPlayerMove(PlayerMoveEvent e) {
- // Ignore head movements
- if (!addon.inWorld(e.getFrom().getWorld()) || e.getFrom().toVector().equals(e.getTo().toVector())) {
- return;
- }
- // Check where the player is
- addon.getIslands().getIslandAt(e.getTo()).ifPresent(island -> {
- // See if island is in cache
- final String islandId = island.getUniqueId();
- IslandStructures is = getIslandStructData(islandId);
- // Check if player is in any of the structures
- Map structures = e.getTo().getWorld().getEnvironment().equals(Environment.NETHER)
- ? is.getNetherStructureBoundingBoxMap()
- : is.getStructureBoundingBoxMap();
- for (Map.Entry en : structures.entrySet()) {
- if (en.getKey().contains(e.getTo().toVector())) {
- for (String s : STRUCTURES) {
- if (en.getValue().startsWith(s)) {
- giveAdvFromCriteria(e.getPlayer(), s);
- }
- }
- // STRUCTURES.stream().filter(en.getValue()::startsWith).forEach(s ->
- // giveAdvFromCriteria(e.getPlayer(), s));
- }
- }
- });
+ // Ignore head movements
+ if (!addon.inWorld(e.getFrom().getWorld()) || e.getFrom().toVector().equals(e.getTo().toVector())) {
+ return;
+ }
+ // Check where the player is
+ addon.getIslands().getIslandAt(e.getTo()).ifPresent(island -> {
+ // See if island is in cache
+ final String islandId = island.getUniqueId();
+ IslandStructures is = getIslandStructData(islandId);
+ // Check if player is in any of the structures
+ Map structures = e.getTo().getWorld().getEnvironment().equals(Environment.NETHER)
+ ? is.getNetherStructureBoundingBoxMap()
+ : is.getStructureBoundingBoxMap();
+ for (Map.Entry en : structures.entrySet()) {
+ if (en.getKey().contains(e.getTo().toVector())) {
+ for (String s : STRUCTURES) {
+ if (en.getValue().startsWith(s)) {
+ giveAdvFromCriteria(e.getPlayer(), s);
+ }
+ }
+ // STRUCTURES.stream().filter(en.getValue()::startsWith).forEach(s ->
+ // giveAdvFromCriteria(e.getPlayer(), s));
+ }
+ }
+ });
}
/**
@@ -215,18 +210,18 @@ public void onPlayerMove(PlayerMoveEvent e) {
* @param string - criteria
*/
private void giveAdvFromCriteria(Player player, String string) {
- // Give every advancement that requires a bastion
- Bukkit.advancementIterator().forEachRemaining(ad -> {
- if (!player.getAdvancementProgress(ad).isDone()) {
- for (String crit : ad.getCriteria()) {
- if (crit.equals(string)) {
- // Set the criteria (it may not complete the advancement completely
- player.getAdvancementProgress(ad).awardCriteria(crit);
- break;
- }
- }
- }
- });
+ // Give every advancement that requires a bastion
+ Bukkit.advancementIterator().forEachRemaining(ad -> {
+ if (!player.getAdvancementProgress(ad).isDone()) {
+ for (String crit : ad.getCriteria()) {
+ if (crit.equals(string)) {
+ // Set the criteria (it may not complete the advancement completely
+ player.getAdvancementProgress(ad).awardCriteria(crit);
+ break;
+ }
+ }
+ }
+ });
}
@@ -237,114 +232,114 @@ private void giveAdvFromCriteria(Player player, String string) {
* @return IslandStructures
*/
private IslandStructures getIslandStructData(String islandId) {
- // Return from cache if it exists
- if (islandStructureCache.containsKey(islandId)) {
- return islandStructureCache.get(islandId);
- }
- // Get from database
- IslandStructures struct = handler.objectExists(islandId) ? handler.loadObject(islandId)
- : new IslandStructures(islandId);
- this.islandStructureCache.put(islandId, struct);
- return struct;
+ // Return from cache if it exists
+ if (islandStructureCache.containsKey(islandId)) {
+ return islandStructureCache.get(islandId);
+ }
+ // Get from database
+ IslandStructures struct = handler.objectExists(islandId) ? handler.loadObject(islandId)
+ : new IslandStructures(islandId);
+ this.islandStructureCache.put(islandId, struct);
+ return struct;
}
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
public void onIslandCreated(IslandCreatedEvent event) {
- setUpIsland(event.getIsland());
+ setUpIsland(event.getIsland());
}
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
public void onIslandReset(IslandResettedEvent event) {
- setUpIsland(event.getIsland());
+ setUpIsland(event.getIsland());
}
private void setUpIsland(Island island) {
- // Check if this island is in this game
- if (!(addon.inWorld(island.getWorld()))) {
- return;
- }
- // Load the latest config so that admins can change it on the fly without
- // reloading
- YamlConfiguration config = YamlConfiguration.loadConfiguration(structureFile);
- Location center = island.getProtectionCenter();
- for (String env : config.getKeys(false)) {
- Environment e = Enums.getIfPresent(Environment.class, env.toUpperCase(Locale.ENGLISH)).orNull();
- if (e == null) {
- addon.logError("Error in structures.yml - unknown environment " + env);
- } else {
- place(config.getConfigurationSection(env), center, e);
- }
- }
+ // Check if this island is in this game
+ if (!(addon.inWorld(island.getWorld()))) {
+ return;
+ }
+ // Load the latest config so that admins can change it on the fly without
+ // reloading
+ YamlConfiguration config = YamlConfiguration.loadConfiguration(structureFile);
+ Location center = island.getProtectionCenter();
+ for (String env : config.getKeys(false)) {
+ Environment e = Enums.getIfPresent(Environment.class, env.toUpperCase(Locale.ENGLISH)).orNull();
+ if (e == null) {
+ addon.logError("Error in structures.yml - unknown environment " + env);
+ } else {
+ place(config.getConfigurationSection(env), center, e);
+ }
+ }
}
private void place(ConfigurationSection section, Location center, Environment env) {
- World world = env.equals(Environment.NORMAL) ? addon.getOverWorld() : addon.getNetherWorld();
- if (world == null) {
- return;
- }
- // Loop through the structures in the file - there could be more than one
- for (String vector : section.getKeys(false)) {
- StructureRotation rot = StructureRotation.NONE;
- Mirror mirror = Mirror.NONE;
- boolean noMobs = false;
- String name = section.getString(vector);
- // Check for rotation
- String[] split = name.split(",");
- if (split.length > 1) {
- // Rotation
- rot = Enums.getIfPresent(StructureRotation.class, split[1].strip().toUpperCase(Locale.ENGLISH))
- .or(StructureRotation.NONE);
- name = split[0];
- }
- if (split.length == 3) {
- // Mirror
- mirror = Enums.getIfPresent(Mirror.class, split[2].strip().toUpperCase(Locale.ENGLISH)).or(Mirror.NONE);
- }
- if (split.length == 4) {
- noMobs = split[3].strip().toUpperCase(Locale.ENGLISH).equals("NO_MOBS");
- }
- // Load Structure
- Structure s = Bukkit.getStructureManager().loadStructure(NamespacedKey.fromString("minecraft:" + name));
- if (s == null) {
- BentoBox.getInstance().logError("Could not load " + name);
- return;
- }
- // Extract coords
- String[] value = vector.split(",");
- if (value.length > 2) {
- int x = Integer.parseInt(value[0].strip()) + center.getBlockX();
- int y = Integer.parseInt(value[1].strip());
- int z = Integer.parseInt(value[2].strip()) + center.getBlockZ();
- Location l = new Location(world, x, y, z);
- itemsToBuild.add(new StructureRecord(name, s, l, rot, mirror, noMobs));
- } else {
- addon.logError("Structure file syntax error: " + vector + ": " + Arrays.toString(value));
- }
- }
+ World world = env.equals(Environment.NORMAL) ? addon.getOverWorld() : addon.getNetherWorld();
+ if (world == null) {
+ return;
+ }
+ // Loop through the structures in the file - there could be more than one
+ for (String vector : section.getKeys(false)) {
+ StructureRotation rot = StructureRotation.NONE;
+ Mirror mirror = Mirror.NONE;
+ boolean noMobs = false;
+ String name = section.getString(vector);
+ // Check for rotation
+ String[] split = name.split(",");
+ if (split.length > 1) {
+ // Rotation
+ rot = Enums.getIfPresent(StructureRotation.class, split[1].strip().toUpperCase(Locale.ENGLISH))
+ .or(StructureRotation.NONE);
+ name = split[0];
+ }
+ if (split.length == 3) {
+ // Mirror
+ mirror = Enums.getIfPresent(Mirror.class, split[2].strip().toUpperCase(Locale.ENGLISH)).or(Mirror.NONE);
+ }
+ if (split.length == 4) {
+ noMobs = split[3].strip().toUpperCase(Locale.ENGLISH).equals("NO_MOBS");
+ }
+ // Load Structure
+ Structure s = Bukkit.getStructureManager().loadStructure(NamespacedKey.fromString("minecraft:" + name));
+ if (s == null) {
+ BentoBox.getInstance().logError("Could not load " + name);
+ return;
+ }
+ // Extract coords
+ String[] value = vector.split(",");
+ if (value.length > 2) {
+ int x = Integer.parseInt(value[0].strip()) + center.getBlockX();
+ int y = Integer.parseInt(value[1].strip());
+ int z = Integer.parseInt(value[2].strip()) + center.getBlockZ();
+ Location l = new Location(world, x, y, z);
+ itemsToBuild.add(new StructureRecord(name, s, l, rot, mirror, noMobs));
+ } else {
+ addon.logError("Structure file syntax error: " + vector + ": " + Arrays.toString(value));
+ }
+ }
}
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()));
- // Remove any jigsaw artifacts
- BoundingBox bb = removeJigsaw(item);
- // 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)) {
- getIslandStructData(id).addNetherStructure(bb, item.name());
- } else {
- getIslandStructData(id).addStructure(bb, item.name());
- }
- handler.saveObjectAsync(getIslandStructData(id));
- });
- // Clear the semaphore
- pasting = false;
+ // 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()));
+ // Remove any jigsaw artifacts
+ BoundingBox bb = removeJigsaw(item);
+ // 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)) {
+ getIslandStructData(id).addNetherStructure(bb, item.name());
+ } else {
+ getIslandStructData(id).addStructure(bb, item.name());
+ }
+ handler.saveObjectAsync(getIslandStructData(id));
+ });
+ // Clear the semaphore
+ pasting = false;
}
/**
@@ -355,46 +350,46 @@ private void placeStructure(StructureRecord item) {
* @return the resulting bounding box of the structure
*/
public static BoundingBox removeJigsaw(StructureRecord item) {
- Location loc = item.location();
- Structure structure = item.structure();
- StructureRotation structureRotation = item.rot();
- String key = item.name();
-
- Location otherCorner = switch (structureRotation) {
-
- case CLOCKWISE_180 -> loc.clone()
- .add(new Vector(-structure.getSize().getX(), structure.getSize().getY(), -structure.getSize().getZ()));
-
- case CLOCKWISE_90 -> loc.clone()
- .add(new Vector(-structure.getSize().getZ(), structure.getSize().getY(), structure.getSize().getX()));
-
- case COUNTERCLOCKWISE_90 -> loc.clone()
- .add(new Vector(structure.getSize().getZ(), structure.getSize().getY(), -structure.getSize().getX()));
-
- case NONE -> loc.clone()
- .add(new Vector(structure.getSize().getX(), structure.getSize().getY(), structure.getSize().getZ()));
-
- };
-
- BoundingBox bb = BoundingBox.of(loc, otherCorner);
- 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 = loc.getWorld().getBlockAt(x, y, z);
- if (b.getType().equals(Material.JIGSAW)) {
- // I would like to read the data from the block and do something with it!
- processJigsaw(b, structureRotation, !item.noMobs());
- } else if (b.getType().equals(Material.STRUCTURE_BLOCK)) {
- processStructureBlock(b);
- }
- // Set water blocks for underwater ruins
- if (key.contains("underwater_ruin") && b.getType().equals(Material.AIR)) {
- b.setType(Material.WATER);
- }
- }
- }
- }
- return bb;
+ Location loc = item.location();
+ Structure structure = item.structure();
+ StructureRotation structureRotation = item.rot();
+ String key = item.name();
+
+ Location otherCorner = switch (structureRotation) {
+
+ case CLOCKWISE_180 -> loc.clone()
+ .add(new Vector(-structure.getSize().getX(), structure.getSize().getY(), -structure.getSize().getZ()));
+
+ case CLOCKWISE_90 -> loc.clone()
+ .add(new Vector(-structure.getSize().getZ(), structure.getSize().getY(), structure.getSize().getX()));
+
+ case COUNTERCLOCKWISE_90 -> loc.clone()
+ .add(new Vector(structure.getSize().getZ(), structure.getSize().getY(), -structure.getSize().getX()));
+
+ case NONE -> loc.clone()
+ .add(new Vector(structure.getSize().getX(), structure.getSize().getY(), structure.getSize().getZ()));
+
+ };
+
+ BoundingBox bb = BoundingBox.of(loc, otherCorner);
+ 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 = loc.getWorld().getBlockAt(x, y, z);
+ if (b.getType().equals(Material.JIGSAW)) {
+ // I would like to read the data from the block and do something with it!
+ processJigsaw(b, structureRotation, !item.noMobs());
+ } else if (b.getType().equals(Material.STRUCTURE_BLOCK)) {
+ processStructureBlock(b);
+ }
+ // Set water blocks for underwater ruins
+ if (key.contains("underwater_ruin") && b.getType().equals(Material.AIR)) {
+ b.setType(Material.WATER);
+ }
+ }
+ }
+ }
+ return bb;
}
/**
@@ -406,79 +401,79 @@ public static BoundingBox removeJigsaw(StructureRecord item) {
* @param b structure block
*/
private static void processStructureBlock(Block b) {
- // I would like to read the data from the block and do something with it!
- String data = nmsData(b);
- BoxedStructureBlock bsb = gson.fromJson(data, BoxedStructureBlock.class);
- b.setType(Material.STRUCTURE_VOID);
- Enums.getIfPresent(EntityType.class, bsb.getMetadata().toUpperCase(Locale.ENGLISH)).toJavaUtil()
- .ifPresent(type -> b.getWorld().spawnEntity(b.getRelative(BlockFace.UP).getLocation(), type));
- if (bsb.getMetadata().contains("chest")) {
- Block downBlock = b.getRelative(BlockFace.DOWN);
- if (downBlock.getType().equals(Material.CHEST)) {
- Chest chest = (Chest) downBlock.getState();
- // TODO: for now just give treasure
- chest.setLootTable(LootTables.BURIED_TREASURE.getLootTable());
- chest.update();
- if (chest.getBlockData() instanceof Waterlogged wl) {
- if (wl.isWaterlogged()) {
- b.setType(Material.WATER);
- }
- }
- }
- }
+ // I would like to read the data from the block and do something with it!
+ String data = nmsData(b);
+ BoxedStructureBlock bsb = gson.fromJson(data, BoxedStructureBlock.class);
+ b.setType(Material.STRUCTURE_VOID);
+ Enums.getIfPresent(EntityType.class, bsb.getMetadata().toUpperCase(Locale.ENGLISH)).toJavaUtil()
+ .ifPresent(type -> b.getWorld().spawnEntity(b.getRelative(BlockFace.UP).getLocation(), type));
+ if (bsb.getMetadata().contains("chest")) {
+ Block downBlock = b.getRelative(BlockFace.DOWN);
+ if (downBlock.getType().equals(Material.CHEST)) {
+ Chest chest = (Chest) downBlock.getState();
+ // TODO: for now just give treasure
+ chest.setLootTable(LootTables.BURIED_TREASURE.getLootTable());
+ chest.update();
+ if (chest.getBlockData() instanceof Waterlogged wl) {
+ if (wl.isWaterlogged()) {
+ b.setType(Material.WATER);
+ }
+ }
+ }
+ }
}
private static void processJigsaw(Block b, StructureRotation structureRotation, boolean pasteMobs) {
- String data = nmsData(b);
- BoxedJigsawBlock bjb = gson.fromJson(data, BoxedJigsawBlock.class);
- String finalState = correctDirection(bjb.getFinal_state(), structureRotation);
- BlockData bd = Bukkit.createBlockData(finalState);
- b.setBlockData(bd);
- if (!bjb.getPool().equalsIgnoreCase("minecraft:empty") && pasteMobs) {
- spawnMob(b, bjb);
- }
+ String data = nmsData(b);
+ BoxedJigsawBlock bjb = gson.fromJson(data, BoxedJigsawBlock.class);
+ String finalState = correctDirection(bjb.getFinal_state(), structureRotation);
+ BlockData bd = Bukkit.createBlockData(finalState);
+ b.setBlockData(bd);
+ if (!bjb.getPool().equalsIgnoreCase("minecraft:empty") && pasteMobs) {
+ spawnMob(b, bjb);
+ }
}
private static void spawnMob(Block b, BoxedJigsawBlock bjb) {
- // bjb.getPool contains a lot more than just mobs, so we have to filter it to
- // see if any mobs are in there. This list may need to grow in the future
- EntityType type = switch (bjb.getPool()) {
- case "minecraft:bastion/mobs/piglin" -> EntityType.PIGLIN;
- case "minecraft:bastion/mobs/hoglin" -> EntityType.HOGLIN;
- case "minecraft:bastion/mobs/piglin_melee" -> EntityType.PIGLIN_BRUTE;
- case "minecraft:village/common/cats" -> EntityType.CAT;
- case "minecraft:village/common/horses" -> EntityType.HORSE;
- case "minecraft:village/common/sheep" -> EntityType.SHEEP;
- case "minecraft:village/common/pigs" -> EntityType.PIG;
- case "minecraft:village/common/cows" -> EntityType.COW;
- case "minecraft:village/common/iron_golem" -> EntityType.IRON_GOLEM;
- case "minecraft:village/common/butcher_animals", "minecraft:village/common/animals" ->
- BUTCHER_ANIMALS.get(rand.nextInt(3));
- default -> null;
- };
- // Boxed
- if (type == null && bjb.getPool().startsWith("minecraft:boxed/")) {
- String entString = bjb.getPool().toUpperCase(Locale.ENGLISH).substring(16, bjb.getPool().length());
- type = Enums.getIfPresent(EntityType.class, entString).orNull();
- }
- // Villagers
- if (bjb.getPool().contains("zombie/villagers")) {
- type = EntityType.ZOMBIE_VILLAGER;
- } else if (bjb.getPool().contains("villagers")) {
- type = EntityType.VILLAGER;
- }
- // if (type == null) {
- // BentoBox.getInstance().logDebug(bjb.getPool());
- // }
- // Spawn it
- if (type != null) {
- Entity e = b.getWorld().spawnEntity(b.getRelative(BlockFace.UP).getLocation(), type);
- if (e != null) {
- e.setPersistent(true);
- }
- // BentoBox.getInstance().logDebug("Spawned a " + type + " at " +
- // b.getRelative(BlockFace.UP).getLocation());
- }
+ // bjb.getPool contains a lot more than just mobs, so we have to filter it to
+ // see if any mobs are in there. This list may need to grow in the future
+ EntityType type = switch (bjb.getPool()) {
+ case "minecraft:bastion/mobs/piglin" -> EntityType.PIGLIN;
+ case "minecraft:bastion/mobs/hoglin" -> EntityType.HOGLIN;
+ case "minecraft:bastion/mobs/piglin_melee" -> EntityType.PIGLIN_BRUTE;
+ case "minecraft:village/common/cats" -> EntityType.CAT;
+ case "minecraft:village/common/horses" -> EntityType.HORSE;
+ case "minecraft:village/common/sheep" -> EntityType.SHEEP;
+ case "minecraft:village/common/pigs" -> EntityType.PIG;
+ case "minecraft:village/common/cows" -> EntityType.COW;
+ case "minecraft:village/common/iron_golem" -> EntityType.IRON_GOLEM;
+ case "minecraft:village/common/butcher_animals", "minecraft:village/common/animals" ->
+ BUTCHER_ANIMALS.get(rand.nextInt(3));
+ default -> null;
+ };
+ // Boxed
+ if (type == null && bjb.getPool().startsWith("minecraft:boxed/")) {
+ String entString = bjb.getPool().toUpperCase(Locale.ENGLISH).substring(16, bjb.getPool().length());
+ type = Enums.getIfPresent(EntityType.class, entString).orNull();
+ }
+ // Villagers
+ if (bjb.getPool().contains("zombie/villagers")) {
+ type = EntityType.ZOMBIE_VILLAGER;
+ } else if (bjb.getPool().contains("villagers")) {
+ type = EntityType.VILLAGER;
+ }
+ // if (type == null) {
+ // BentoBox.getInstance().logDebug(bjb.getPool());
+ // }
+ // Spawn it
+ if (type != null) {
+ Entity e = b.getWorld().spawnEntity(b.getRelative(BlockFace.UP).getLocation(), type);
+ if (e != null) {
+ e.setPersistent(true);
+ }
+ // BentoBox.getInstance().logDebug("Spawned a " + type + " at " +
+ // b.getRelative(BlockFace.UP).getLocation());
+ }
}
/**
@@ -490,18 +485,18 @@ private static void spawnMob(Block b, BoxedJigsawBlock bjb) {
* @return a rewritten blockstate with the updated direction, if required
*/
private static String correctDirection(String finalState, StructureRotation sr) {
- if (sr.equals(StructureRotation.NONE)) {
- // No change
- return finalState;
- }
- BlockFace oldDirection = getDirection(finalState);
- BlockFace newDirection = getNewDirection(oldDirection, sr);
- if (newDirection.equals(BlockFace.SELF)) {
- // No change - shouldn't happen, but just in case
- return finalState;
- }
- return finalState.replace(oldDirection.name().toLowerCase(Locale.ENGLISH),
- newDirection.name().toLowerCase(Locale.ENGLISH));
+ if (sr.equals(StructureRotation.NONE)) {
+ // No change
+ return finalState;
+ }
+ BlockFace oldDirection = getDirection(finalState);
+ BlockFace newDirection = getNewDirection(oldDirection, sr);
+ if (newDirection.equals(BlockFace.SELF)) {
+ // No change - shouldn't happen, but just in case
+ return finalState;
+ }
+ return finalState.replace(oldDirection.name().toLowerCase(Locale.ENGLISH),
+ newDirection.name().toLowerCase(Locale.ENGLISH));
}
@@ -513,26 +508,26 @@ private static String correctDirection(String finalState, StructureRotation sr)
* @return the new direction, or SELF if something weird happens
*/
private static BlockFace getNewDirection(BlockFace oldDirection, StructureRotation sr) {
- if (sr.equals(StructureRotation.CLOCKWISE_180)) {
- return oldDirection.getOppositeFace();
- } else if (sr.equals(StructureRotation.CLOCKWISE_90)) {
- return switch (oldDirection) {
- case EAST -> BlockFace.SOUTH;
- case NORTH -> BlockFace.EAST;
- case SOUTH -> BlockFace.WEST;
- case WEST -> BlockFace.NORTH;
- default -> BlockFace.SELF;
- };
- } else if (sr.equals(StructureRotation.COUNTERCLOCKWISE_90)) {
- return switch (oldDirection) {
- case EAST -> BlockFace.NORTH;
- case NORTH -> BlockFace.WEST;
- case SOUTH -> BlockFace.EAST;
- case WEST -> BlockFace.SOUTH;
- default -> BlockFace.SELF;
- };
- }
- return BlockFace.SELF;
+ if (sr.equals(StructureRotation.CLOCKWISE_180)) {
+ return oldDirection.getOppositeFace();
+ } else if (sr.equals(StructureRotation.CLOCKWISE_90)) {
+ return switch (oldDirection) {
+ case EAST -> BlockFace.SOUTH;
+ case NORTH -> BlockFace.EAST;
+ case SOUTH -> BlockFace.WEST;
+ case WEST -> BlockFace.NORTH;
+ default -> BlockFace.SELF;
+ };
+ } else if (sr.equals(StructureRotation.COUNTERCLOCKWISE_90)) {
+ return switch (oldDirection) {
+ case EAST -> BlockFace.NORTH;
+ case NORTH -> BlockFace.WEST;
+ case SOUTH -> BlockFace.EAST;
+ case WEST -> BlockFace.SOUTH;
+ default -> BlockFace.SELF;
+ };
+ }
+ return BlockFace.SELF;
}
/**
@@ -542,27 +537,28 @@ private static BlockFace getNewDirection(BlockFace oldDirection, StructureRotati
* @return direction, if found, otherwise SELF
*/
private static BlockFace getDirection(String finalState) {
- return CARDINALS.stream().filter(bf -> finalState.contains(bf.name().toLowerCase(Locale.ENGLISH))).findFirst()
- .orElse(BlockFace.SELF);
+ return CARDINALS.stream().filter(bf -> finalState.contains(bf.name().toLowerCase(Locale.ENGLISH))).findFirst()
+ .orElse(BlockFace.SELF);
}
private static String nmsData(Block block) {
- Location w = block.getLocation();
- CraftWorld cw = (CraftWorld) w.getWorld(); // CraftWorld is NMS one
- // for 1.13+ (we have use WorldServer)
- TileEntity te = cw.getHandle().c_(new BlockPosition(w.getBlockX(), w.getBlockY(), w.getBlockZ()));
- try {
- PacketPlayOutTileEntityData packet = ((PacketPlayOutTileEntityData) te.j()); // get update packet from NMS
- // object
- // here we should use reflection because "c" field isn't accessible
- Field f = packet.getClass().getDeclaredField("c"); // get field
- f.setAccessible(true); // make it available
- NBTTagCompound nbtTag = (NBTTagCompound) f.get(packet);
- return nbtTag.toString(); // this will show what you want
- } catch (Exception exc) {
- exc.printStackTrace();
- }
- return "Nothing";
+ // Bukkit method that was added in 2011
+ // Example value: 1.20.4-R0.1-SNAPSHOT
+ String bukkitVersion = "v" + Bukkit.getBukkitVersion().replace('.', '_').replace('-', '_');
+ String pluginPackageName = BentoBox.getInstance().getClass().getPackage().getName();
+ AbstractMetaData handler;
+ try {
+ Class> clazz = Class.forName(pluginPackageName + ".nms." + bukkitVersion + ".GetMetaData");
+ if (AbstractMetaData.class.isAssignableFrom(clazz)) {
+ handler = (AbstractMetaData) clazz.getConstructor().newInstance();
+ } else {
+ throw new IllegalStateException("Class " + clazz.getName() + " does not implement AbstractGetMetaData");
+ }
+ } catch (Exception e) {
+ BentoBox.getInstance().logWarning("No metadata handler found for " + bukkitVersion + " in Boxed.");
+ handler = new world.bentobox.boxed.nms.fallback.GetMetaData();
+ }
+ return handler.nmsData(block);
}
}
diff --git a/src/main/java/world/bentobox/boxed/nms/AbstractMetaData.java b/src/main/java/world/bentobox/boxed/nms/AbstractMetaData.java
new file mode 100644
index 0000000..51196bc
--- /dev/null
+++ b/src/main/java/world/bentobox/boxed/nms/AbstractMetaData.java
@@ -0,0 +1,12 @@
+package world.bentobox.boxed.nms;
+
+import org.bukkit.block.Block;
+
+/**
+ *
+ */
+public abstract class AbstractMetaData {
+
+ public abstract String nmsData(Block block);
+
+}
diff --git a/src/main/java/world/bentobox/boxed/nms/fallback/GetMetaData.java b/src/main/java/world/bentobox/boxed/nms/fallback/GetMetaData.java
new file mode 100644
index 0000000..423e6ee
--- /dev/null
+++ b/src/main/java/world/bentobox/boxed/nms/fallback/GetMetaData.java
@@ -0,0 +1,17 @@
+package world.bentobox.boxed.nms.fallback;
+
+import org.bukkit.block.Block;
+
+import world.bentobox.boxed.nms.AbstractMetaData;
+
+/**
+ * Fallback
+ */
+public class GetMetaData extends AbstractMetaData {
+
+ @Override
+ public String nmsData(Block block) {
+ return "Nothing"; // We cannot read it if we have no NMS
+ }
+
+}
diff --git a/src/main/java/world/bentobox/boxed/nms/v1_20_4_R0_1_SNAPSHOT/GetMetaData.java b/src/main/java/world/bentobox/boxed/nms/v1_20_4_R0_1_SNAPSHOT/GetMetaData.java
new file mode 100644
index 0000000..57ed417
--- /dev/null
+++ b/src/main/java/world/bentobox/boxed/nms/v1_20_4_R0_1_SNAPSHOT/GetMetaData.java
@@ -0,0 +1,37 @@
+package world.bentobox.boxed.nms.v1_20_4_R0_1_SNAPSHOT;
+
+import java.lang.reflect.Field;
+
+import org.bukkit.Location;
+import org.bukkit.block.Block;
+import org.bukkit.craftbukkit.v1_20_R3.CraftWorld;
+
+import net.minecraft.core.BlockPosition;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.network.protocol.game.PacketPlayOutTileEntityData;
+import net.minecraft.world.level.block.entity.TileEntity;
+import world.bentobox.boxed.nms.AbstractMetaData;
+
+public class GetMetaData extends AbstractMetaData {
+
+ @Override
+ public String nmsData(Block block) {
+ Location w = block.getLocation();
+ CraftWorld cw = (CraftWorld) w.getWorld(); // CraftWorld is NMS one
+ // for 1.13+ (we have use WorldServer)
+ TileEntity te = cw.getHandle().c_(new BlockPosition(w.getBlockX(), w.getBlockY(), w.getBlockZ()));
+ try {
+ PacketPlayOutTileEntityData packet = ((PacketPlayOutTileEntityData) te.j()); // get update packet from NMS
+ // object
+ // here we should use reflection because "c" field isn't accessible
+ Field f = packet.getClass().getDeclaredField("c"); // get field
+ f.setAccessible(true); // make it available
+ NBTTagCompound nbtTag = (NBTTagCompound) f.get(packet);
+ return nbtTag.toString(); // this will show what you want
+ } catch (Exception exc) {
+ exc.printStackTrace();
+ }
+ return "Nothing";
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/java/world/bentobox/boxed/nms/v1_20_6_R0_1_SNAPSHOT/GetMetaData.java b/src/main/java/world/bentobox/boxed/nms/v1_20_6_R0_1_SNAPSHOT/GetMetaData.java
new file mode 100644
index 0000000..be6b438
--- /dev/null
+++ b/src/main/java/world/bentobox/boxed/nms/v1_20_6_R0_1_SNAPSHOT/GetMetaData.java
@@ -0,0 +1,37 @@
+package world.bentobox.boxed.nms.v1_20_6_R0_1_SNAPSHOT;
+
+import java.lang.reflect.Field;
+
+import org.bukkit.Location;
+import org.bukkit.block.Block;
+import org.bukkit.craftbukkit.v1_20_R4.CraftWorld;
+
+import net.minecraft.core.BlockPosition;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.network.protocol.game.PacketPlayOutTileEntityData;
+import net.minecraft.world.level.block.entity.TileEntity;
+import world.bentobox.boxed.nms.AbstractMetaData;
+
+public class GetMetaData extends AbstractMetaData {
+
+ @Override
+ public String nmsData(Block block) {
+ Location w = block.getLocation();
+ CraftWorld cw = (CraftWorld) w.getWorld(); // CraftWorld is NMS one
+ // for 1.13+ (we have use WorldServer)
+ TileEntity te = cw.getHandle().c_(new BlockPosition(w.getBlockX(), w.getBlockY(), w.getBlockZ()));
+ try {
+ PacketPlayOutTileEntityData packet = ((PacketPlayOutTileEntityData) te.j()); // get update packet from NMS
+ // object
+ // here we should use reflection because "c" field isn't accessible
+ Field f = packet.getClass().getDeclaredField("c"); // get field
+ f.setAccessible(true); // make it available
+ NBTTagCompound nbtTag = (NBTTagCompound) f.get(packet);
+ return nbtTag.toString(); // this will show what you want
+ } catch (Exception exc) {
+ exc.printStackTrace();
+ }
+ return "Nothing";
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/java/world/bentobox/boxed/nms/v1_21_R0_1_SNAPSHOT/GetMetaData.java b/src/main/java/world/bentobox/boxed/nms/v1_21_R0_1_SNAPSHOT/GetMetaData.java
new file mode 100644
index 0000000..d0634a0
--- /dev/null
+++ b/src/main/java/world/bentobox/boxed/nms/v1_21_R0_1_SNAPSHOT/GetMetaData.java
@@ -0,0 +1,37 @@
+package world.bentobox.boxed.nms.v1_21_R0_1_SNAPSHOT;
+
+import java.lang.reflect.Field;
+
+import org.bukkit.Location;
+import org.bukkit.block.Block;
+import org.bukkit.craftbukkit.v1_21_R1.CraftWorld;
+
+import net.minecraft.core.BlockPosition;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.network.protocol.game.PacketPlayOutTileEntityData;
+import net.minecraft.world.level.block.entity.TileEntity;
+import world.bentobox.boxed.nms.AbstractMetaData;
+
+public class GetMetaData extends AbstractMetaData {
+
+ @Override
+ public String nmsData(Block block) {
+ Location w = block.getLocation();
+ CraftWorld cw = (CraftWorld) w.getWorld(); // CraftWorld is NMS one
+ // for 1.13+ (we have use WorldServer)
+ TileEntity te = cw.getHandle().c_(new BlockPosition(w.getBlockX(), w.getBlockY(), w.getBlockZ()));
+ try {
+ PacketPlayOutTileEntityData packet = ((PacketPlayOutTileEntityData) te.j()); // get update packet from NMS
+ // object
+ // here we should use reflection because "c" field isn't accessible
+ Field f = packet.getClass().getDeclaredField("c"); // get field
+ f.setAccessible(true); // make it available
+ NBTTagCompound nbtTag = (NBTTagCompound) f.get(packet);
+ return nbtTag.toString(); // this will show what you want
+ } catch (Exception exc) {
+ exc.printStackTrace();
+ }
+ return "Nothing";
+ }
+
+}
\ No newline at end of file