1
0
mirror of https://github.com/BentoBoxWorld/Boxed.git synced 2025-03-20 14:49:31 +01:00

Handle NBT items and with more structures placed

This commit is contained in:
tastybento 2023-03-05 14:38:04 -08:00
parent af2ec9c483
commit d80035b8f2
5 changed files with 324 additions and 34 deletions

View File

@ -20,8 +20,8 @@ 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;
import world.bentobox.boxed.listeners.NewAreaListener;
/**
* @author tastybento
@ -83,7 +83,7 @@ public class AdminPlaceStructureCommand extends CompositeCommand {
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);
NewAreaListener.removeJigsaw(spot, s);
saveStructure(spot, tag, user);
return true;
}

View File

@ -3,6 +3,7 @@ package world.bentobox.boxed.listeners;
import java.io.File;
import java.lang.reflect.Field;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Queue;
import java.util.Random;
@ -16,6 +17,7 @@ import org.bukkit.World.Environment;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.block.Chest;
import org.bukkit.block.data.BlockData;
import org.bukkit.block.data.Waterlogged;
import org.bukkit.block.structure.Mirror;
import org.bukkit.block.structure.StructureRotation;
@ -27,21 +29,26 @@ import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.inventory.ItemStack;
import org.bukkit.scheduler.BukkitTask;
import org.bukkit.structure.Structure;
import org.bukkit.util.BoundingBox;
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;
import world.bentobox.bentobox.database.objects.Island;
import world.bentobox.bentobox.util.Pair;
import world.bentobox.bentobox.util.Util;
import world.bentobox.boxed.Boxed;
import world.bentobox.boxed.objects.BoxedJigsawBlock;
import world.bentobox.boxed.objects.BoxedStructureBlock;
/**
* @author tastybento
@ -53,9 +60,12 @@ public class NewAreaListener implements Listener {
private File structureFile;
private Queue<Item> itemsToBuild = new LinkedList<>();
private boolean pasting;
private static Gson gson = new Gson();
private record Item(String name, Structure structure, Location location, StructureRotation rot) {};
Pair<Integer, Integer> min = new Pair<Integer, Integer>(0,0);
Pair<Integer, Integer> max = new Pair<Integer, Integer>(0,0);
private BukkitTask task;
private int i;
/**
@ -66,6 +76,7 @@ public class NewAreaListener implements Listener {
addon.saveResource("structures.yml", false);
// Load the config
structureFile = new File(addon.getDataFolder(), "structures.yml");
// Try to build something every second
Bukkit.getScheduler().runTaskTimer(addon.getPlugin(), () -> BuildItem(), 20, 20);
}
@ -79,6 +90,35 @@ public class NewAreaListener implements Listener {
}
}
/**
* Workaround for https://hub.spigotmc.org/jira/browse/SPIGOT-7288
* @param event event
*/
@EventHandler()
public void onBentoBoxReady(BentoBoxReadyEvent event) {
World seedBase = Bukkit.getWorld("seed_base");
if (seedBase == null) {
addon.logError("No seed base world!");
return;
}
File templateFile = new File(addon.getDataFolder(), "templates.yml");
if (templateFile.exists()) {
YamlConfiguration loader = YamlConfiguration.loadConfiguration(templateFile);
List<String> list = loader.getStringList("templates");
task = Bukkit.getScheduler().runTaskTimer(addon.getPlugin(), () -> {
if (i == list.size()) {
task.cancel();
return;
}
String struct = list.get(i++);
Bukkit.getServer().dispatchCommand(Bukkit.getConsoleSender(), "execute in " + seedBase.getName() + " run place template " + struct + " 10000 120 10000");
}, 0, 10);
}
}
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
public void onIslandCreated(IslandCreatedEvent event) {
@ -106,6 +146,13 @@ public class NewAreaListener implements Listener {
for (String vector : section.getKeys(false)) {
StructureRotation rot = StructureRotation.NONE;
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];
}
// Load Structure
Structure s = Bukkit.getStructureManager().loadStructure(NamespacedKey.fromString("minecraft:" + name));
if (s == null) {
@ -119,10 +166,6 @@ public class NewAreaListener implements Listener {
int y = Integer.valueOf(value[1].strip());
int z = Integer.valueOf(value[2].strip()) + center.getBlockZ();
Location l = new Location(world, x, y, z);
if (value.length > 3) {
// Rotation
rot = Enums.getIfPresent(StructureRotation.class, value[3].strip().toUpperCase(Locale.ENGLISH)).or(StructureRotation.NONE);
}
itemsToBuild.add(new Item(name, s, l, rot));
} else {
addon.logError("Structure file syntax error: " + name + " " + vector);
@ -152,37 +195,47 @@ public class NewAreaListener implements Listener {
for (int z = (int) bb.getMinZ(); z < bb.getMaxZ(); z++) {
Block b = loc.getWorld().getBlockAt(x, y, z);
if (b.getType().equals(Material.JIGSAW)) {
b.setType(Material.STRUCTURE_VOID);
// I would like to read the data from the block and do something with it!
String data = nmsData(b);
BoxedJigsawBlock bjb = gson.fromJson(data, BoxedJigsawBlock.class);
BentoBox.getInstance().logDebug("Jigsaw: " + bjb);
BlockData bd = Bukkit.createBlockData(bjb.getFinal_state());
b.setType(bd.getMaterial());
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;
default -> null;
};
if (type != null && loc.getWorld().spawnEntity(b.getRelative(BlockFace.UP).getLocation(), type) != null) {
BentoBox.getInstance().logDebug("Spawned a " + type + " at " + b.getRelative(BlockFace.UP).getLocation());
}
} else if (b.getType().equals(Material.STRUCTURE_BLOCK)) {
// I would like to read the data from the block an do something with it!
String data = nmsData(b);
BoxedStructureBlock bsb = gson.fromJson(data, BoxedStructureBlock.class);
b.setType(Material.STRUCTURE_VOID);
BentoBox.getInstance().logDebug(data);
int index = data.indexOf("metadata:");
if (index > -1) {
data = data.substring(index + 10, data.length());
index = data.indexOf("\"");
data = data.substring(0, index);
BentoBox.getInstance().logDebug(data);
EntityType type = Enums.getIfPresent(EntityType.class, data.toUpperCase(Locale.ENGLISH)).orNull();
if (type != null) {
if (loc.getWorld().spawnEntity(loc, type) != null) {
BentoBox.getInstance().logDebug("Spawned a " + type);
}
EntityType type = Enums.getIfPresent(EntityType.class, bsb.getMetadata().toUpperCase(Locale.ENGLISH)).orNull();
if (type != null) {
if (loc.getWorld().spawnEntity(loc, type) != null) {
BentoBox.getInstance().logDebug("Spawned a " + type);
}
if (data.contains("chest")) {
Block downBlock = b.getRelative(BlockFace.DOWN);
if (downBlock.getType().equals(Material.CHEST)) {
Chest chest = (Chest)downBlock.getState();
chest.getInventory().addItem(new ItemStack(Material.GOLD_INGOT, 3));
if (chest.getBlockData() instanceof Waterlogged wl) {
if (wl.isWaterlogged()) {
b.setType(Material.WATER);
}
}
if (bsb.getMetadata().contains("chest")) {
Block downBlock = b.getRelative(BlockFace.DOWN);
if (downBlock.getType().equals(Material.CHEST)) {
Chest chest = (Chest)downBlock.getState();
// TODO add more stuff
chest.getInventory().addItem(new ItemStack(Material.GOLD_INGOT, 3));
if (chest.getBlockData() instanceof Waterlogged wl) {
if (wl.isWaterlogged()) {
b.setType(Material.WATER);
}
}
}
}
}
}

View File

@ -0,0 +1,53 @@
package world.bentobox.boxed.objects;
import com.google.gson.annotations.Expose;
public class BoxedJigsawBlock {
// final_state:"minecraft:polished_blackstone_bricks",joint:"aligned",name:"minecraft:empty",pool:"minecraft:bastion/bridge/legs",target:"minecraft:leg_connector"
@Expose
private String final_state;
@Expose
private String joint;
@Expose
private String name;
@Expose
private String pool;
@Expose
private String target;
/**
* @return the final_state
*/
public String getFinal_state() {
return final_state;
}
/**
* @return the joint
*/
public String getJoint() {
return joint;
}
/**
* @return the name
*/
public String getName() {
return name;
}
/**
* @return the pool
*/
public String getPool() {
return pool;
}
/**
* @return the target
*/
public String getTarget() {
return target;
}
@Override
public String toString() {
return "BoxedJigsawBlock [" + (final_state != null ? "final_state=" + final_state + ", " : "")
+ (joint != null ? "joint=" + joint + ", " : "") + (name != null ? "name=" + name + ", " : "")
+ (pool != null ? "pool=" + pool + ", " : "") + (target != null ? "target=" + target : "") + "]";
}
}

View File

@ -0,0 +1,174 @@
package world.bentobox.boxed.objects;
import org.bukkit.block.data.type.StructureBlock.Mode;
import org.bukkit.block.structure.Mirror;
import org.bukkit.block.structure.StructureRotation;
import com.google.gson.annotations.Expose;
/**
* @author tastybento
*
*/
public class BoxedStructureBlock {
//{author:"LadyAgnes",ignoreEntities:1b,integrity:1.0f,metadata:"drowned",mirror:"NONE",mode:"DATA",name:"",posX:0,posY:1,posZ:0,powered:0b,rotation:"NONE",seed:0L,showair:0b
//,showboundingbox:1b,sizeX:0,sizeY:0,sizeZ:0}
@Expose
private String author;
@Expose
private boolean ignoreEntities;
@Expose
private float integrity;
@Expose
private String metadata;
@Expose
private Mirror mirror;
@Expose
private Mode mode;
@Expose
private String name;
@Expose
private int posX;
@Expose
private int posY;
@Expose
private int posZ;
@Expose
private boolean powered;
@Expose
private StructureRotation rotation;
@Expose
private String seed;
@Expose
private boolean showair;
@Expose
private boolean showboundingbox;
@Expose
private int sizeX;
@Expose
private int sizeY;
@Expose
private int sizeZ;
/**
* @return the author
*/
public String getAuthor() {
return author;
}
/**
* @return the ignoreEntities
*/
public boolean isIgnoreEntities() {
return ignoreEntities;
}
/**
* @return the integrity
*/
public float getIntegrity() {
return integrity;
}
/**
* @return the metadata
*/
public String getMetadata() {
return metadata;
}
/**
* @return the mirror
*/
public Mirror getMirror() {
return mirror;
}
/**
* @return the mode
*/
public Mode getMode() {
return mode;
}
/**
* @return the name
*/
public String getName() {
return name;
}
/**
* @return the posX
*/
public int getPosX() {
return posX;
}
/**
* @return the posY
*/
public int getPosY() {
return posY;
}
/**
* @return the posZ
*/
public int getPosZ() {
return posZ;
}
/**
* @return the powered
*/
public boolean isPowered() {
return powered;
}
/**
* @return the rotation
*/
public StructureRotation getRotation() {
return rotation;
}
/**
* @return the seed
*/
public String getSeed() {
return seed;
}
/**
* @return the showair
*/
public boolean isShowair() {
return showair;
}
/**
* @return the showboundingbox
*/
public boolean isShowboundingbox() {
return showboundingbox;
}
/**
* @return the sizeX
*/
public int getSizeX() {
return sizeX;
}
/**
* @return the sizeY
*/
public int getSizeY() {
return sizeY;
}
/**
* @return the sizeZ
*/
public int getSizeZ() {
return sizeZ;
}
@Override
public String toString() {
return "BoxedStructureBlock [" + (author != null ? "author=" + author + ", " : "") + "ignoreEntities="
+ ignoreEntities + ", integrity=" + integrity + ", "
+ (metadata != null ? "metadata=" + metadata + ", " : "")
+ (mirror != null ? "mirror=" + mirror + ", " : "") + (mode != null ? "mode=" + mode + ", " : "")
+ (name != null ? "name=" + name + ", " : "") + "posX=" + posX + ", posY=" + posY + ", posZ=" + posZ
+ ", powered=" + powered + ", " + (rotation != null ? "rotation=" + rotation + ", " : "") + "seed="
+ seed + ", showair=" + showair + ", showboundingbox=" + showboundingbox + ", sizeX=" + sizeX
+ ", sizeY=" + sizeY + ", sizeZ=" + sizeZ + "]";
}
}

View File

@ -6,11 +6,21 @@ normal:
-66,63,17: igloo/top
-34,52,-35: underwater_ruin/warm_5
80,71,113: pillager_outpost/watchtower
33,70,-34: village/savanna/town_centers/savanna_meeting_point_1
34,70,-29: village/common/iron_golem
41,70,-26: village/common/animals/cat_calico
35,70,-22: village/common/animals/cat_calico
33,69,-34: village/savanna/town_centers/savanna_meeting_point_1
34,69,-29: village/common/iron_golem
41,69,-26: village/common/animals/cat_calico
35,69,-22: village/common/animals/cat_calico
99,72,118: pillager_outpost/feature_cage1
33,72,100: village/desert/houses/desert_farm_1
26,72,100: village/desert/houses/desert_medium_house_1
36,72,97: village/plains/villagers/unemployed
34,72,98: village/plains/villagers/unemployed
15,70,108: village/desert/houses/desert_butcher_shop_1
10,70,112: village/desert/houses/desert_temple_1
-71,63,107: igloo/top
-25,57,-30: shipwreck/rightsideup_full_degraded
nether:
16,32,0: bastion/bridge/starting_pieces/entrance
62,33,-17: bastion/hoglin_stable/walls/wall_base
68,32,-13: bastion/hoglin_stable/large_stables/inner_0
79,33,-10: bastion/hoglin_stable/ramparts/ramparts_1