package com.epicplayera10.iaedit.hook.process; import com.epicplayera10.iaedit.IAEdit; import com.epicplayera10.iaedit.utils.IABlockType; import com.epicplayera10.iaedit.utils.IACache; import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.FloatTag; import com.sk89q.jnbt.Tag; import com.sk89q.worldedit.blocks.Blocks; import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.command.RegionCommands; import com.sk89q.worldedit.command.SchematicCommands; import com.sk89q.worldedit.entity.BaseEntity; import com.sk89q.worldedit.entity.Entity; import com.sk89q.worldedit.event.Event; import com.sk89q.worldedit.event.extent.EditSessionEvent; import com.sk89q.worldedit.extent.AbstractDelegateExtent; import com.sk89q.worldedit.extent.clipboard.Clipboard; import com.sk89q.worldedit.function.operation.ForwardExtentCopy; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.transform.AffineTransform; import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockStateHolder; import com.sk89q.worldedit.world.block.BlockType; import com.sk89q.worldedit.world.block.BlockTypes; import dev.lone.itemsadder.api.CustomBlock; import dev.lone.itemsadder.api.CustomEntity; import dev.lone.itemsadder.api.CustomFurniture; import dev.lone.itemsadder.api.Events.FurniturePlaceEvent; import dev.lone.itemsadder.api.ItemsAdder; import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.UUID; import java.util.function.Supplier; import org.bukkit.Bukkit; import org.bukkit.Color; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.Rotation; import org.bukkit.World; import org.bukkit.entity.ArmorStand; import org.bukkit.entity.ItemFrame; import org.jetbrains.annotations.Nullable; public class AbstractCustomBlockExtent extends AbstractDelegateExtent { protected final EditSessionEvent event; public AbstractCustomBlockExtent(EditSessionEvent editSessionEvent) { super(editSessionEvent.getExtent()); this.event = editSessionEvent; } @Override public @Nullable Entity createEntity(com.sk89q.worldedit.util.Location location, BaseEntity entity) { CompoundTag nbt = entity.getNbtData(); CompoundTag bukkitValues = getNested(nbt, "BukkitValues"); if (bukkitValues == null) { // Bukkit.broadcastMessage("Invalid nbt: " + nbt.toRaw()); return super.createEntity(location, entity); } String namespaced = bukkitValues.getString("itemsadder:placeable_entity_item"); // String namespace = nbt.getCompound("minecraft:custom_data").getCompound("itemsadder").getString("namespace"); World bukkitWorld = Bukkit.getWorld(this.event.getWorld().getName()); Location bukkitLoc = new Location(bukkitWorld, location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch()); String type = nbt.getString("Id"); int rotation = switch (type) { case "minecraft:item_frame" -> { byte value = nbt.getByte("ItemRotation"); float yaw = bukkitLoc.getYaw(); // Round to nearest 45 degrees int rounded = (int) (yaw / 45) * 45; int steps = rounded / 45; // bukkitLoc.setYaw(0); // Reset yaw to prevent double rotation yield (value + steps) % 8; } default -> (nbt.getList("Rotation", FloatTag.class).getFirst().getValue()).intValue(); }; Color color = locateColor(nbt); if (color != null) { color = color.setAlpha(0); } // Bukkit.broadcastMessage("Rotation: " + rotation); placeFurniture(namespaced, bukkitLoc, rotation, color); return null; } @Override public @Nullable Entity createEntity(com.sk89q.worldedit.util.Location location, BaseEntity entity, UUID uuid) { // Bukkit.broadcastMessage("createEntity 2 " + entity); return super.createEntity(location, entity, uuid); } private CompoundTag getCompoundTag(CompoundTag parent, String name) { Map contents = parent.getValue(); CompoundTag result = (CompoundTag) contents.get(name); if (result == null) { System.err.println("Invalid key: " + name + " in " + contents.keySet()); } return result; } private CompoundTag getNested(CompoundTag parent, String name) { if (parent == null) { return null; } int index = name.indexOf("/"); if (index == -1) { return getCompoundTag(parent, name); } String word = name.substring(0, index); CompoundTag sub = getCompoundTag(parent, word); if (sub == null) { return null; } return getNested(sub, name.substring(index + 1)); } public > Result setBlockInternal(int x, int y, int z, T block) { World bukkitWorld = Bukkit.getWorld(this.event.getWorld().getName()); Location location = new Location(bukkitWorld, x, y, z); BlockType blockType = block.getBlockType(); // Check if the block is String, if so, print its location and return if (blockType.getId().startsWith("minecraft:tripwire")) { String locationText = location.getBlockX() + ", " + location.getBlockY() + ", " + location.getBlockZ(); Bukkit.broadcastMessage("Block at " + locationText + " is " + block.toImmutableState().getAsString()); return Result.DEFAULT; } if (blockType instanceof IABlockType iaType) { placeCustomBlock(iaType.getId(), location); return Result.SUCCESS; } if (!CustomBlocksWorldEditUtils.isCustomBlockType(block.getBlockType())) { return Result.DEFAULT; } BaseBlock baseBlock = block.toBaseBlock(); CompoundTag nbt = baseBlock.getNbtData(); if (nbt != null) { String id = nbt.getString("IABlock"); if (id != null) { placeCustomBlock(id, location); return Result.SUCCESS; } } CustomBlock custom = CustomBlocksWorldEditUtils.getCustomBlockByBlockState(block, nbt); if (custom != null) { placeCustomBlock(custom.getId(), location); return Result.SUCCESS; } return Result.DEFAULT; } protected void placeCustomBlock(String id, Location location) { CustomBlock customBlock = CustomBlock.getInstance(id); if (customBlock == null) { return; } Bukkit.getScheduler().runTaskLater(IAEdit.instance(), () -> { // Bukkit.broadcastMessage("Placing custom block " + id + " at " + location); customBlock.place(location); }, 2L); } protected void placeFurniture(String id, Location location, int rotation, @Nullable Color color) { Bukkit.getScheduler().runTaskLater(IAEdit.instance(), () -> { // Bukkit.broadcastMessage("Placing custom block " + id + " at " + location); location.setYaw(rotation); CustomFurniture furniture = CustomFurniture.spawnPreciseNonSolid(id, location); /* if (color != null) { Bukkit.getScheduler().runTaskLater(IAEdit.instance(), () -> { String locationText = location.getBlockX() + ", " + location.getBlockY() + ", " + location.getBlockZ(); String hex = "#" + Integer.toHexString(color.asRGB()); // furniture.setColor(color); furniture.replaceFurniture(id, color); }, 1L); } */ org.bukkit.entity.Entity entity = furniture.getEntity(); if (entity instanceof ItemFrame frame) { frame.setRotation(Rotation.values()[rotation]); } if (entity instanceof ArmorStand stand) { Location target = stand.getLocation(); target.setYaw(rotation); stand.teleport(target); } }, 1L); } private Color locateColor(CompoundTag nbt) { System.out.println("Locating color in nbt: " + nbt.toRaw()); String type = nbt.getString("Id"); if (type.equals("minecraft:item_frame")) { return getItemNBTColor(getNested(nbt, "Item")); } if (type.equals("minecraft:armor_stand")) { List list = nbt.getList("ArmorItems", CompoundTag.class); for (CompoundTag armor : list) { Color color = getItemNBTColor(armor); if (color != null) { System.out.println("Found color: " + color); return color; } } } System.out.println("Don't know how to locate color for " + type); return null; } private Color getItemNBTColor(CompoundTag nbt) { CompoundTag tag = getNested(nbt, "tag/display"); if (tag == null) { return null; } int color = tag.getInt("color"); return Color.fromRGB(color); } public static enum Result { SUCCESS, FAILURE, DEFAULT } }