From 419f3530ad36745b15c27993e04071ec027a4d70 Mon Sep 17 00:00:00 2001 From: Brokkonaut Date: Mon, 12 Jun 2023 03:41:12 +0200 Subject: [PATCH] properly log sign edits --- .../java/de/diddiz/LogBlock/Consumer.java | 7 +- src/main/java/de/diddiz/LogBlock/Updater.java | 3 +- .../blockstate/BlockStateCodecSign.java | 213 +++++++++++------- .../LogBlock/blockstate/BlockStateCodecs.java | 2 +- .../LogBlock/listeners/InteractLogging.java | 51 +++-- .../LogBlock/listeners/SignChangeLogging.java | 2 +- .../de/diddiz/LogBlock/util/BukkitUtils.java | 86 +++++++ .../de/diddiz/LogBlock/util/Reflections.java | 36 +++ .../java/de/diddiz/LogBlock/util/Utils.java | 11 + 9 files changed, 302 insertions(+), 109 deletions(-) create mode 100644 src/main/java/de/diddiz/LogBlock/util/Reflections.java diff --git a/src/main/java/de/diddiz/LogBlock/Consumer.java b/src/main/java/de/diddiz/LogBlock/Consumer.java index a0b16b0..91a8abf 100644 --- a/src/main/java/de/diddiz/LogBlock/Consumer.java +++ b/src/main/java/de/diddiz/LogBlock/Consumer.java @@ -36,6 +36,7 @@ import org.bukkit.World; import org.bukkit.block.BlockState; import org.bukkit.block.data.BlockData; import org.bukkit.block.data.Waterlogged; +import org.bukkit.block.sign.Side; import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.entity.Entity; import org.bukkit.entity.EntityType; @@ -340,14 +341,16 @@ public class Consumer extends Thread { * Location of the placed sign * @param type * BlockData of the sign + * @param side * @param lines * The four lines on the sign. */ - public void queueSignChange(Actor actor, Location loc, BlockData type, String[] lines) { + public void queueSignChange(Actor actor, Location loc, BlockState state, Side side, String[] lines) { + BlockData type = state.getBlockData(); if (!BukkitUtils.isSign(type.getMaterial())) { return; } - queueBlock(actor, loc, type, type, null, BlockStateCodecSign.serialize(lines), null); + queueBlock(actor, loc, type, type, null, BlockStateCodecSign.INSTANCE.serialize(state, side, lines), null); } public void queueChat(Actor player, String message) { diff --git a/src/main/java/de/diddiz/LogBlock/Updater.java b/src/main/java/de/diddiz/LogBlock/Updater.java index d338736..a134893 100644 --- a/src/main/java/de/diddiz/LogBlock/Updater.java +++ b/src/main/java/de/diddiz/LogBlock/Updater.java @@ -9,6 +9,7 @@ import de.diddiz.LogBlock.util.Utils; import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.block.data.BlockData; +import org.bukkit.block.sign.Side; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.inventory.ItemStack; @@ -674,7 +675,7 @@ class Updater { if (!nullBlock && signText != null) { String[] lines = signText.split("\0", 4); - byte[] bytes = Utils.serializeYamlConfiguration(BlockStateCodecSign.serialize(lines)); + byte[] bytes = Utils.serializeYamlConfiguration(BlockStateCodecSign.INSTANCE.serialize(null, Side.FRONT, lines)); Material replacedMaterial = MaterialConverter.getBlockData(replaced, -1).getMaterial(); Material typeMaterial = MaterialConverter.getBlockData(type, -1).getMaterial(); diff --git a/src/main/java/de/diddiz/LogBlock/blockstate/BlockStateCodecSign.java b/src/main/java/de/diddiz/LogBlock/blockstate/BlockStateCodecSign.java index fb566a9..1cc86d3 100644 --- a/src/main/java/de/diddiz/LogBlock/blockstate/BlockStateCodecSign.java +++ b/src/main/java/de/diddiz/LogBlock/blockstate/BlockStateCodecSign.java @@ -1,6 +1,7 @@ package de.diddiz.LogBlock.blockstate; import de.diddiz.LogBlock.util.BukkitUtils; +import de.diddiz.LogBlock.util.Reflections; import java.util.Arrays; import java.util.Collections; import java.util.List; @@ -8,9 +9,15 @@ import org.bukkit.DyeColor; import org.bukkit.Material; import org.bukkit.block.BlockState; import org.bukkit.block.Sign; +import org.bukkit.block.sign.Side; +import org.bukkit.block.sign.SignSide; +import org.bukkit.configuration.ConfigurationSection; import org.bukkit.configuration.file.YamlConfiguration; public class BlockStateCodecSign implements BlockStateCodec { + + public static final BlockStateCodecSign INSTANCE = new BlockStateCodecSign(); + @Override public Material[] getApplicableMaterials() { return BukkitUtils.getAllSignMaterials().toArray(new Material[BukkitUtils.getAllSignMaterials().size()]); @@ -18,44 +25,63 @@ public class BlockStateCodecSign implements BlockStateCodec { @Override public YamlConfiguration serialize(BlockState state) { - if (state instanceof Sign) { - Sign sign = (Sign) state; - String[] lines = sign.getLines(); - boolean hasText = false; - for (int i = 0; i < lines.length; i++) { - if (lines[i] != null && lines[i].length() > 0) { - hasText = true; - break; - } + YamlConfiguration conf = null; + if (state instanceof Sign sign) { + boolean waxed = Reflections.isSignWaxed(sign); + if (waxed) { + conf = new YamlConfiguration(); + conf.set("waxed", waxed); } - DyeColor signColor = sign.getColor(); - if (signColor == null) { - signColor = DyeColor.BLACK; - } - if (hasText || signColor != DyeColor.BLACK) { - YamlConfiguration conf = new YamlConfiguration(); - if (hasText) { - conf.set("lines", Arrays.asList(lines)); + for (Side side : Side.values()) { + SignSide signSide = sign.getSide(side); + String[] lines = signSide.getLines(); + boolean hasText = false; + for (int i = 0; i < lines.length; i++) { + if (lines[i] != null && lines[i].length() > 0) { + hasText = true; + break; + } } - if (signColor != DyeColor.BLACK) { - conf.set("color", signColor.name()); + DyeColor signColor = signSide.getColor(); + if (signColor == null) { + signColor = DyeColor.BLACK; } - if (sign.isGlowingText()) { - conf.set("glowing", true); + boolean glowing = signSide.isGlowingText(); + if (hasText || signColor != DyeColor.BLACK || glowing) { + if (conf == null) { + conf = new YamlConfiguration(); + } + ConfigurationSection sideSection = side == Side.FRONT ? conf : conf.createSection(side.name().toLowerCase()); + if (hasText) { + sideSection.set("lines", Arrays.asList(lines)); + } + if (signColor != DyeColor.BLACK) { + sideSection.set("color", signColor.name()); + } + if (glowing) { + sideSection.set("glowing", true); + } } - return conf; } } - return null; + return conf; } /** - * This is required for the SignChangeEvent, because we have no BlockState there. + * This is required for the SignChangeEvent, because we have no updated BlockState there. + * @param state */ - public static YamlConfiguration serialize(String[] lines) { - YamlConfiguration conf = new YamlConfiguration(); + public YamlConfiguration serialize(BlockState state, Side side, String[] lines) { + YamlConfiguration conf = state == null ? null : serialize(state); if (lines != null) { - conf.set("lines", Arrays.asList(lines)); + if (conf == null) { + conf = new YamlConfiguration(); + } + ConfigurationSection sideSection = side == Side.FRONT ? conf : conf.getConfigurationSection(side.name().toLowerCase()); + if (sideSection == null) { + sideSection = conf.createSection(side.name().toLowerCase()); + } + sideSection.set("lines", Arrays.asList(lines)); } return conf; } @@ -64,82 +90,105 @@ public class BlockStateCodecSign implements BlockStateCodec { public void deserialize(BlockState state, YamlConfiguration conf) { if (state instanceof Sign) { Sign sign = (Sign) state; - DyeColor signColor = DyeColor.BLACK; - boolean glowing = false; - List lines = Collections.emptyList(); if (conf != null) { - if (conf.contains("lines")) { - lines = conf.getStringList("lines"); - } - if (conf.contains("color")) { - try { - signColor = DyeColor.valueOf(conf.getString("color")); - } catch (IllegalArgumentException | NullPointerException e) { - // ignored + sign.setEditable(!conf.getBoolean("waxed")); + for (Side side : Side.values()) { + ConfigurationSection sideSection = side == Side.FRONT ? conf : conf.getConfigurationSection(side.name().toLowerCase()); + DyeColor signColor = DyeColor.BLACK; + boolean glowing = false; + List lines = Collections.emptyList(); + if (sideSection != null) { + if (sideSection.contains("lines")) { + lines = sideSection.getStringList("lines"); + } + if (sideSection.contains("color")) { + try { + signColor = DyeColor.valueOf(sideSection.getString("color")); + } catch (IllegalArgumentException | NullPointerException e) { + // ignored + } + } + glowing = sideSection.getBoolean("glowing", false); } + SignSide signSide = sign.getSide(side); + for (int i = 0; i < 4; i++) { + String line = lines.size() > i && lines.get(i) != null ? lines.get(i) : ""; + signSide.setLine(i, line); + } + signSide.setColor(signColor); + signSide.setGlowingText(glowing); } - glowing = conf.getBoolean("glowing", false); } - for (int i = 0; i < 4; i++) { - String line = lines.size() > i && lines.get(i) != null ? lines.get(i) : ""; - sign.setLine(i, line); - } - sign.setColor(signColor); - sign.setGlowingText(glowing); } } @Override public String toString(YamlConfiguration state, YamlConfiguration oldState) { if (state != null) { - List lines = state.getStringList("lines"); - List oldLines = Collections.emptyList(); - DyeColor signColor = DyeColor.BLACK; - if (state.contains("color")) { - try { - signColor = DyeColor.valueOf(state.getString("color")); - } catch (IllegalArgumentException | NullPointerException e) { - // ignored - } + StringBuilder sb = new StringBuilder(); + boolean isWaxed = state.getBoolean("waxed"); + boolean oldWaxed = oldState != null && oldState.getBoolean("waxed"); + if (isWaxed != oldWaxed) { + sb.append(isWaxed ? "(waxed)" : "(not waxed)"); } - DyeColor oldSignColor = DyeColor.BLACK; - boolean glowing = state.getBoolean("glowing", false); - boolean oldGlowing = false; - if (oldState != null) { - oldLines = oldState.getStringList("lines"); - if (oldState.contains("color")) { + for (Side side : Side.values()) { + ConfigurationSection sideSection = side == Side.FRONT ? state : state.getConfigurationSection(side.name().toLowerCase()); + if (!sb.isEmpty()) { + sb.append(" "); + } + sb.append(side.name()).append(":"); + + List lines = sideSection == null ? Collections.emptyList() : sideSection.getStringList("lines"); + List oldLines = Collections.emptyList(); + DyeColor signColor = DyeColor.BLACK; + if (sideSection != null && sideSection.contains("color")) { try { - oldSignColor = DyeColor.valueOf(oldState.getString("color")); + signColor = DyeColor.valueOf(sideSection.getString("color")); } catch (IllegalArgumentException | NullPointerException e) { // ignored } } - oldGlowing = oldState.getBoolean("glowing", false); - } + DyeColor oldSignColor = DyeColor.BLACK; + boolean glowing = sideSection != null && sideSection.getBoolean("glowing", false); + boolean oldGlowing = false; + if (oldState != null) { + ConfigurationSection oldSideSection = side == Side.FRONT ? oldState : oldState.getConfigurationSection(side.name().toLowerCase()); + if (oldSideSection != null) { + oldLines = oldSideSection.getStringList("lines"); + if (oldSideSection.contains("color")) { + try { + oldSignColor = DyeColor.valueOf(oldSideSection.getString("color")); + } catch (IllegalArgumentException | NullPointerException e) { + // ignored + } + } + oldGlowing = oldSideSection.getBoolean("glowing", false); + } + } - StringBuilder sb = new StringBuilder(); - if (!lines.equals(oldLines)) { - for (String line : lines) { + if (!lines.equals(oldLines)) { + for (String line : lines) { + if (sb.length() > 0) { + sb.append(" "); + } + sb.append("[").append(line).append("]"); + } + } + if (signColor != oldSignColor) { if (sb.length() > 0) { sb.append(" "); } - sb.append("[").append(line).append("]"); + sb.append("(color: " + signColor.name().toLowerCase() + ")"); } - } - if (signColor != oldSignColor) { - if (sb.length() > 0) { - sb.append(" "); - } - sb.append("(color: " + signColor.name().toLowerCase() + ")"); - } - if (glowing != oldGlowing) { - if (sb.length() > 0) { - sb.append(" "); - } - if (glowing) { - sb.append("(glowing)"); - } else { - sb.append("(not glowing)"); + if (glowing != oldGlowing) { + if (sb.length() > 0) { + sb.append(" "); + } + if (glowing) { + sb.append("(glowing)"); + } else { + sb.append("(not glowing)"); + } } } return sb.toString(); diff --git a/src/main/java/de/diddiz/LogBlock/blockstate/BlockStateCodecs.java b/src/main/java/de/diddiz/LogBlock/blockstate/BlockStateCodecs.java index a33c7f7..0f39776 100644 --- a/src/main/java/de/diddiz/LogBlock/blockstate/BlockStateCodecs.java +++ b/src/main/java/de/diddiz/LogBlock/blockstate/BlockStateCodecs.java @@ -21,7 +21,7 @@ public class BlockStateCodecs { } static { - registerCodec(new BlockStateCodecSign()); + registerCodec(BlockStateCodecSign.INSTANCE); registerCodec(new BlockStateCodecSkull()); registerCodec(new BlockStateCodecBanner()); registerCodec(new BlockStateCodecSpawner()); diff --git a/src/main/java/de/diddiz/LogBlock/listeners/InteractLogging.java b/src/main/java/de/diddiz/LogBlock/listeners/InteractLogging.java index 77f1061..aacc603 100644 --- a/src/main/java/de/diddiz/LogBlock/listeners/InteractLogging.java +++ b/src/main/java/de/diddiz/LogBlock/listeners/InteractLogging.java @@ -5,6 +5,7 @@ import de.diddiz.LogBlock.LogBlock; import de.diddiz.LogBlock.Logging; import de.diddiz.LogBlock.config.WorldConfig; import de.diddiz.LogBlock.util.BukkitUtils; +import de.diddiz.LogBlock.util.Reflections; import java.util.UUID; import org.bukkit.DyeColor; import org.bukkit.GameEvent; @@ -30,6 +31,8 @@ import org.bukkit.block.data.type.NoteBlock; import org.bukkit.block.data.type.Repeater; import org.bukkit.block.data.type.Switch; import org.bukkit.block.data.type.TurtleEgg; +import org.bukkit.block.sign.Side; +import org.bukkit.block.sign.SignSide; import org.bukkit.entity.Player; import org.bukkit.event.Event.Result; import org.bukkit.event.EventHandler; @@ -93,30 +96,34 @@ public class InteractLogging extends LoggingListener { } else if (BukkitUtils.isSign(type)) { if (wcfg.isLogging(Logging.SIGNTEXT) && event.getAction() == Action.RIGHT_CLICK_BLOCK && event.getItem() != null) { Material itemType = event.getItem().getType(); - if (BukkitUtils.isDye(itemType) || itemType == Material.GLOW_INK_SAC || itemType == Material.INK_SAC) { + if (BukkitUtils.isDye(itemType) || itemType == Material.GLOW_INK_SAC || itemType == Material.INK_SAC || itemType == Material.HONEYCOMB) { final BlockState before = event.getClickedBlock().getState(); - if (before instanceof Sign) { - if (itemType == Material.GLOW_INK_SAC) { - Sign signBefore = (Sign) before; - if (!signBefore.isGlowingText()) { - final Sign signAfter = (Sign) event.getClickedBlock().getState(); - signAfter.setGlowingText(true); - consumer.queueBlockReplace(Actor.actorFromEntity(player), signBefore, signAfter); - } - } else if (itemType == Material.INK_SAC) { - Sign signBefore = (Sign) before; - if (signBefore.isGlowingText()) { - final Sign signAfter = (Sign) event.getClickedBlock().getState(); - signAfter.setGlowingText(false); - consumer.queueBlockReplace(Actor.actorFromEntity(player), signBefore, signAfter); - } - } else { - DyeColor newColor = BukkitUtils.dyeToDyeColor(itemType); - Sign signBefore = (Sign) before; - if (newColor != null && signBefore.getColor() != newColor) { - final Sign signAfter = (Sign) event.getClickedBlock().getState(); - signAfter.setColor(newColor); + if (before instanceof Sign signBefore) { + boolean waxed = Reflections.isSignWaxed(signBefore); + if (!waxed) { + final Sign signAfter = (Sign) event.getClickedBlock().getState(); + Side side = BukkitUtils.getFacingSignSide(player, clicked); + SignSide signSideBefore = signBefore.getSide(side); + SignSide signSideAfter = signAfter.getSide(side); + if (itemType == Material.GLOW_INK_SAC) { + if (!signSideBefore.isGlowingText()) { + signSideAfter.setGlowingText(true); + consumer.queueBlockReplace(Actor.actorFromEntity(player), signBefore, signAfter); + } + } else if (itemType == Material.INK_SAC) { + if (signSideBefore.isGlowingText()) { + signSideAfter.setGlowingText(false); + consumer.queueBlockReplace(Actor.actorFromEntity(player), signBefore, signAfter); + } + } else if (itemType == Material.HONEYCOMB) { + signAfter.setEditable(false); consumer.queueBlockReplace(Actor.actorFromEntity(player), signBefore, signAfter); + } else if (BukkitUtils.isDye(itemType)) { + DyeColor newColor = BukkitUtils.dyeToDyeColor(itemType); + if (newColor != null && signSideBefore.getColor() != newColor) { + signSideAfter.setColor(newColor); + consumer.queueBlockReplace(Actor.actorFromEntity(player), signBefore, signAfter); + } } } } diff --git a/src/main/java/de/diddiz/LogBlock/listeners/SignChangeLogging.java b/src/main/java/de/diddiz/LogBlock/listeners/SignChangeLogging.java index 5622ce5..fe42178 100644 --- a/src/main/java/de/diddiz/LogBlock/listeners/SignChangeLogging.java +++ b/src/main/java/de/diddiz/LogBlock/listeners/SignChangeLogging.java @@ -17,7 +17,7 @@ public class SignChangeLogging extends LoggingListener { @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) public void onSignChange(SignChangeEvent event) { if (isLogging(event.getBlock().getWorld(), Logging.SIGNTEXT)) { - consumer.queueSignChange(Actor.actorFromEntity(event.getPlayer()), event.getBlock().getLocation(), event.getBlock().getBlockData(), event.getLines()); + consumer.queueSignChange(Actor.actorFromEntity(event.getPlayer()), event.getBlock().getLocation(), event.getBlock().getState(), event.getSide(), event.getLines()); } } } diff --git a/src/main/java/de/diddiz/LogBlock/util/BukkitUtils.java b/src/main/java/de/diddiz/LogBlock/util/BukkitUtils.java index f4babf3..91d19c0 100644 --- a/src/main/java/de/diddiz/LogBlock/util/BukkitUtils.java +++ b/src/main/java/de/diddiz/LogBlock/util/BukkitUtils.java @@ -36,9 +36,16 @@ import org.bukkit.block.DoubleChest; import org.bukkit.block.data.Bisected; import org.bukkit.block.data.Bisected.Half; import org.bukkit.block.data.BlockData; +import org.bukkit.block.data.Directional; +import org.bukkit.block.data.Rotatable; +import org.bukkit.block.data.type.HangingSign; +import org.bukkit.block.data.type.Sign; import org.bukkit.block.data.type.Slab; import org.bukkit.block.data.type.Slab.Type; import org.bukkit.block.data.type.Stairs; +import org.bukkit.block.data.type.WallHangingSign; +import org.bukkit.block.data.type.WallSign; +import org.bukkit.block.sign.Side; import org.bukkit.entity.ArmorStand; import org.bukkit.entity.Entity; import org.bukkit.entity.EntityType; @@ -1223,4 +1230,83 @@ public class BukkitUtils { public static boolean isSign(Material m) { return allSigns.contains(m); } + + public static Side getFacingSignSide(Entity entity, Block sign) { + BlockData data = sign.getBlockData(); + Material type = data.getMaterial(); + BlockFace signFace = null; + double centerx = 0.5; + double centerz = 0.5; + double yRotationDegree = 0; + if (type.data == Sign.class || type.data == HangingSign.class) { + Rotatable rotatableData = (Rotatable) data; + signFace = rotatableData.getRotation(); + if (signFace == BlockFace.SOUTH) { + yRotationDegree = 360 * 0.0 / 16.0; + } else if (signFace == BlockFace.SOUTH_SOUTH_WEST) { + yRotationDegree = 360 * 1.0 / 16.0; + } else if (signFace == BlockFace.SOUTH_WEST) { + yRotationDegree = 360 * 2.0 / 16.0; + } else if (signFace == BlockFace.WEST_SOUTH_WEST) { + yRotationDegree = 360 * 3.0 / 16.0; + } else if (signFace == BlockFace.WEST) { + yRotationDegree = 360 * 4.0 / 16.0; + } else if (signFace == BlockFace.WEST_NORTH_WEST) { + yRotationDegree = 360 * 5.0 / 16.0; + } else if (signFace == BlockFace.NORTH_WEST) { + yRotationDegree = 360 * 6.0 / 16.0; + } else if (signFace == BlockFace.NORTH_NORTH_WEST) { + yRotationDegree = 360 * 7.0 / 16.0; + } else if (signFace == BlockFace.NORTH) { + yRotationDegree = 360 * 8.0 / 16.0; + } else if (signFace == BlockFace.NORTH_NORTH_EAST) { + yRotationDegree = 360 * 9.0 / 16.0; + } else if (signFace == BlockFace.NORTH_EAST) { + yRotationDegree = 360 * 10.0 / 16.0; + } else if (signFace == BlockFace.EAST_NORTH_EAST) { + yRotationDegree = 360 * 11.0 / 16.0; + } else if (signFace == BlockFace.EAST) { + yRotationDegree = 360 * 12.0 / 16.0; + } else if (signFace == BlockFace.EAST_SOUTH_EAST) { + yRotationDegree = 360 * 13.0 / 16.0; + } else if (signFace == BlockFace.SOUTH_EAST) { + yRotationDegree = 360 * 14.0 / 16.0; + } else if (signFace == BlockFace.SOUTH_SOUTH_EAST) { + yRotationDegree = 360 * 15.0 / 16.0; + } + } else if (type.data == WallSign.class || type.data == WallHangingSign.class) { + Directional directionalData = (Directional) data; + signFace = directionalData.getFacing(); + if (signFace == BlockFace.SOUTH) { + yRotationDegree = 0; + } else if (signFace == BlockFace.WEST) { + yRotationDegree = 90; + } else if (signFace == BlockFace.NORTH) { + yRotationDegree = 180; + } else if (signFace == BlockFace.EAST) { + yRotationDegree = 270; + } + // wall signs are not centered on the block (but hanging wall signs are) + if (type.data == WallSign.class) { + if (signFace == BlockFace.NORTH) { + centerz = 15.0 / 16.0; + } else if (signFace == BlockFace.SOUTH) { + centerz = 1.0 / 16.0; + } else if (signFace == BlockFace.WEST) { + centerx = 15.0 / 16.0; + } else if (signFace == BlockFace.EAST) { + centerx = 1.0 / 16.0; + } + } + } else { + throw new IllegalArgumentException("block is not a sign"); + } + + Location entityLoc = entity.getLocation(); + double relativeX = entityLoc.getX() - (sign.getX() + centerx); + double relativeZ = entityLoc.getZ() - (sign.getZ() + centerz); + double f = Math.atan2(relativeZ, relativeX) * 180.0 / Math.PI - 90.0; + + return Math.abs(Utils.warpDegrees(f - yRotationDegree)) <= 90.0 ? Side.FRONT : Side.BACK; + } } diff --git a/src/main/java/de/diddiz/LogBlock/util/Reflections.java b/src/main/java/de/diddiz/LogBlock/util/Reflections.java new file mode 100644 index 0000000..5c50cc2 --- /dev/null +++ b/src/main/java/de/diddiz/LogBlock/util/Reflections.java @@ -0,0 +1,36 @@ +package de.diddiz.LogBlock.util; + +import de.diddiz.LogBlock.LogBlock; +import java.lang.reflect.Field; +import java.util.logging.Level; +import org.bukkit.block.Sign; + +public class Reflections { + private static Field FIELD_CraftBlockEntityState_snapshot; + private static Field FIELD_SignBlockEntity_isWaxed; + + public static boolean isSignWaxed(Sign sign) { + try { + if (FIELD_CraftBlockEntityState_snapshot == null) { + FIELD_CraftBlockEntityState_snapshot = sign.getClass().getSuperclass().getDeclaredField("snapshot"); + FIELD_CraftBlockEntityState_snapshot.setAccessible(true); + } + Object snapshot = FIELD_CraftBlockEntityState_snapshot.get(sign); + if (snapshot == null) { + return false; + } + if (FIELD_SignBlockEntity_isWaxed == null) { + for (Field f : snapshot.getClass().getDeclaredFields()) { + if (f.getType() == boolean.class) { + FIELD_SignBlockEntity_isWaxed = f; + FIELD_SignBlockEntity_isWaxed.setAccessible(true); + } + } + } + return FIELD_SignBlockEntity_isWaxed != null && FIELD_SignBlockEntity_isWaxed.getBoolean(snapshot); + } catch (SecurityException | NoSuchFieldException | IllegalArgumentException | IllegalAccessException e) { + LogBlock.getInstance().getLogger().log(Level.SEVERE, "Sign.isWaxed reflection failed", e); + } + return false; + } +} diff --git a/src/main/java/de/diddiz/LogBlock/util/Utils.java b/src/main/java/de/diddiz/LogBlock/util/Utils.java index e84f1f9..2c62a90 100644 --- a/src/main/java/de/diddiz/LogBlock/util/Utils.java +++ b/src/main/java/de/diddiz/LogBlock/util/Utils.java @@ -284,4 +284,15 @@ public class Utils { public static String serializeForSQL(YamlConfiguration conf) { return mysqlPrepareBytesForInsertAllowNull(serializeYamlConfiguration(conf)); } + + public static double warpDegrees(double degrees) { + double d = degrees % 360.0; + if (d >= 180.0) { + d -= 360.0; + } + if (d < -180.0) { + d += 360.0; + } + return d; + } }