properly log sign edits

This commit is contained in:
Brokkonaut
2023-06-12 03:41:12 +02:00
parent 31bef400a6
commit 419f3530ad
9 changed files with 302 additions and 109 deletions

View File

@ -36,6 +36,7 @@ import org.bukkit.World;
import org.bukkit.block.BlockState; import org.bukkit.block.BlockState;
import org.bukkit.block.data.BlockData; import org.bukkit.block.data.BlockData;
import org.bukkit.block.data.Waterlogged; import org.bukkit.block.data.Waterlogged;
import org.bukkit.block.sign.Side;
import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Entity; import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType; import org.bukkit.entity.EntityType;
@ -340,14 +341,16 @@ public class Consumer extends Thread {
* Location of the placed sign * Location of the placed sign
* @param type * @param type
* BlockData of the sign * BlockData of the sign
* @param side
* @param lines * @param lines
* The four lines on the sign. * 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())) { if (!BukkitUtils.isSign(type.getMaterial())) {
return; 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) { public void queueChat(Actor player, String message) {

View File

@ -9,6 +9,7 @@ import de.diddiz.LogBlock.util.Utils;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.block.data.BlockData; import org.bukkit.block.data.BlockData;
import org.bukkit.block.sign.Side;
import org.bukkit.configuration.ConfigurationSection; import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
@ -674,7 +675,7 @@ class Updater {
if (!nullBlock && signText != null) { if (!nullBlock && signText != null) {
String[] lines = signText.split("\0", 4); 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 replacedMaterial = MaterialConverter.getBlockData(replaced, -1).getMaterial();
Material typeMaterial = MaterialConverter.getBlockData(type, -1).getMaterial(); Material typeMaterial = MaterialConverter.getBlockData(type, -1).getMaterial();

View File

@ -1,6 +1,7 @@
package de.diddiz.LogBlock.blockstate; package de.diddiz.LogBlock.blockstate;
import de.diddiz.LogBlock.util.BukkitUtils; import de.diddiz.LogBlock.util.BukkitUtils;
import de.diddiz.LogBlock.util.Reflections;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
@ -8,9 +9,15 @@ import org.bukkit.DyeColor;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.block.BlockState; import org.bukkit.block.BlockState;
import org.bukkit.block.Sign; 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; import org.bukkit.configuration.file.YamlConfiguration;
public class BlockStateCodecSign implements BlockStateCodec { public class BlockStateCodecSign implements BlockStateCodec {
public static final BlockStateCodecSign INSTANCE = new BlockStateCodecSign();
@Override @Override
public Material[] getApplicableMaterials() { public Material[] getApplicableMaterials() {
return BukkitUtils.getAllSignMaterials().toArray(new Material[BukkitUtils.getAllSignMaterials().size()]); return BukkitUtils.getAllSignMaterials().toArray(new Material[BukkitUtils.getAllSignMaterials().size()]);
@ -18,44 +25,63 @@ public class BlockStateCodecSign implements BlockStateCodec {
@Override @Override
public YamlConfiguration serialize(BlockState state) { public YamlConfiguration serialize(BlockState state) {
if (state instanceof Sign) { YamlConfiguration conf = null;
Sign sign = (Sign) state; if (state instanceof Sign sign) {
String[] lines = sign.getLines(); boolean waxed = Reflections.isSignWaxed(sign);
boolean hasText = false; if (waxed) {
for (int i = 0; i < lines.length; i++) { conf = new YamlConfiguration();
if (lines[i] != null && lines[i].length() > 0) { conf.set("waxed", waxed);
hasText = true;
break;
}
} }
DyeColor signColor = sign.getColor(); for (Side side : Side.values()) {
if (signColor == null) { SignSide signSide = sign.getSide(side);
signColor = DyeColor.BLACK; String[] lines = signSide.getLines();
} boolean hasText = false;
if (hasText || signColor != DyeColor.BLACK) { for (int i = 0; i < lines.length; i++) {
YamlConfiguration conf = new YamlConfiguration(); if (lines[i] != null && lines[i].length() > 0) {
if (hasText) { hasText = true;
conf.set("lines", Arrays.asList(lines)); break;
}
} }
if (signColor != DyeColor.BLACK) { DyeColor signColor = signSide.getColor();
conf.set("color", signColor.name()); if (signColor == null) {
signColor = DyeColor.BLACK;
} }
if (sign.isGlowingText()) { boolean glowing = signSide.isGlowingText();
conf.set("glowing", true); 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) { public YamlConfiguration serialize(BlockState state, Side side, String[] lines) {
YamlConfiguration conf = new YamlConfiguration(); YamlConfiguration conf = state == null ? null : serialize(state);
if (lines != null) { 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; return conf;
} }
@ -64,82 +90,105 @@ public class BlockStateCodecSign implements BlockStateCodec {
public void deserialize(BlockState state, YamlConfiguration conf) { public void deserialize(BlockState state, YamlConfiguration conf) {
if (state instanceof Sign) { if (state instanceof Sign) {
Sign sign = (Sign) state; Sign sign = (Sign) state;
DyeColor signColor = DyeColor.BLACK;
boolean glowing = false;
List<String> lines = Collections.emptyList();
if (conf != null) { if (conf != null) {
if (conf.contains("lines")) { sign.setEditable(!conf.getBoolean("waxed"));
lines = conf.getStringList("lines"); for (Side side : Side.values()) {
} ConfigurationSection sideSection = side == Side.FRONT ? conf : conf.getConfigurationSection(side.name().toLowerCase());
if (conf.contains("color")) { DyeColor signColor = DyeColor.BLACK;
try { boolean glowing = false;
signColor = DyeColor.valueOf(conf.getString("color")); List<String> lines = Collections.emptyList();
} catch (IllegalArgumentException | NullPointerException e) { if (sideSection != null) {
// ignored 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 @Override
public String toString(YamlConfiguration state, YamlConfiguration oldState) { public String toString(YamlConfiguration state, YamlConfiguration oldState) {
if (state != null) { if (state != null) {
List<String> lines = state.getStringList("lines"); StringBuilder sb = new StringBuilder();
List<String> oldLines = Collections.emptyList(); boolean isWaxed = state.getBoolean("waxed");
DyeColor signColor = DyeColor.BLACK; boolean oldWaxed = oldState != null && oldState.getBoolean("waxed");
if (state.contains("color")) { if (isWaxed != oldWaxed) {
try { sb.append(isWaxed ? "(waxed)" : "(not waxed)");
signColor = DyeColor.valueOf(state.getString("color"));
} catch (IllegalArgumentException | NullPointerException e) {
// ignored
}
} }
DyeColor oldSignColor = DyeColor.BLACK; for (Side side : Side.values()) {
boolean glowing = state.getBoolean("glowing", false); ConfigurationSection sideSection = side == Side.FRONT ? state : state.getConfigurationSection(side.name().toLowerCase());
boolean oldGlowing = false; if (!sb.isEmpty()) {
if (oldState != null) { sb.append(" ");
oldLines = oldState.getStringList("lines"); }
if (oldState.contains("color")) { sb.append(side.name()).append(":");
List<String> lines = sideSection == null ? Collections.emptyList() : sideSection.getStringList("lines");
List<String> oldLines = Collections.emptyList();
DyeColor signColor = DyeColor.BLACK;
if (sideSection != null && sideSection.contains("color")) {
try { try {
oldSignColor = DyeColor.valueOf(oldState.getString("color")); signColor = DyeColor.valueOf(sideSection.getString("color"));
} catch (IllegalArgumentException | NullPointerException e) { } catch (IllegalArgumentException | NullPointerException e) {
// ignored // 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)) {
if (!lines.equals(oldLines)) { for (String line : lines) {
for (String line : lines) { if (sb.length() > 0) {
sb.append(" ");
}
sb.append("[").append(line).append("]");
}
}
if (signColor != oldSignColor) {
if (sb.length() > 0) { if (sb.length() > 0) {
sb.append(" "); sb.append(" ");
} }
sb.append("[").append(line).append("]"); sb.append("(color: " + signColor.name().toLowerCase() + ")");
} }
} if (glowing != oldGlowing) {
if (signColor != oldSignColor) { if (sb.length() > 0) {
if (sb.length() > 0) { sb.append(" ");
sb.append(" "); }
} if (glowing) {
sb.append("(color: " + signColor.name().toLowerCase() + ")"); sb.append("(glowing)");
} } else {
if (glowing != oldGlowing) { sb.append("(not glowing)");
if (sb.length() > 0) { }
sb.append(" ");
}
if (glowing) {
sb.append("(glowing)");
} else {
sb.append("(not glowing)");
} }
} }
return sb.toString(); return sb.toString();

View File

@ -21,7 +21,7 @@ public class BlockStateCodecs {
} }
static { static {
registerCodec(new BlockStateCodecSign()); registerCodec(BlockStateCodecSign.INSTANCE);
registerCodec(new BlockStateCodecSkull()); registerCodec(new BlockStateCodecSkull());
registerCodec(new BlockStateCodecBanner()); registerCodec(new BlockStateCodecBanner());
registerCodec(new BlockStateCodecSpawner()); registerCodec(new BlockStateCodecSpawner());

View File

@ -5,6 +5,7 @@ import de.diddiz.LogBlock.LogBlock;
import de.diddiz.LogBlock.Logging; import de.diddiz.LogBlock.Logging;
import de.diddiz.LogBlock.config.WorldConfig; import de.diddiz.LogBlock.config.WorldConfig;
import de.diddiz.LogBlock.util.BukkitUtils; import de.diddiz.LogBlock.util.BukkitUtils;
import de.diddiz.LogBlock.util.Reflections;
import java.util.UUID; import java.util.UUID;
import org.bukkit.DyeColor; import org.bukkit.DyeColor;
import org.bukkit.GameEvent; 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.Repeater;
import org.bukkit.block.data.type.Switch; import org.bukkit.block.data.type.Switch;
import org.bukkit.block.data.type.TurtleEgg; 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.entity.Player;
import org.bukkit.event.Event.Result; import org.bukkit.event.Event.Result;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
@ -93,30 +96,34 @@ public class InteractLogging extends LoggingListener {
} else if (BukkitUtils.isSign(type)) { } else if (BukkitUtils.isSign(type)) {
if (wcfg.isLogging(Logging.SIGNTEXT) && event.getAction() == Action.RIGHT_CLICK_BLOCK && event.getItem() != null) { if (wcfg.isLogging(Logging.SIGNTEXT) && event.getAction() == Action.RIGHT_CLICK_BLOCK && event.getItem() != null) {
Material itemType = event.getItem().getType(); 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(); final BlockState before = event.getClickedBlock().getState();
if (before instanceof Sign) { if (before instanceof Sign signBefore) {
if (itemType == Material.GLOW_INK_SAC) { boolean waxed = Reflections.isSignWaxed(signBefore);
Sign signBefore = (Sign) before; if (!waxed) {
if (!signBefore.isGlowingText()) { final Sign signAfter = (Sign) event.getClickedBlock().getState();
final Sign signAfter = (Sign) event.getClickedBlock().getState(); Side side = BukkitUtils.getFacingSignSide(player, clicked);
signAfter.setGlowingText(true); SignSide signSideBefore = signBefore.getSide(side);
consumer.queueBlockReplace(Actor.actorFromEntity(player), signBefore, signAfter); SignSide signSideAfter = signAfter.getSide(side);
} if (itemType == Material.GLOW_INK_SAC) {
} else if (itemType == Material.INK_SAC) { if (!signSideBefore.isGlowingText()) {
Sign signBefore = (Sign) before; signSideAfter.setGlowingText(true);
if (signBefore.isGlowingText()) { consumer.queueBlockReplace(Actor.actorFromEntity(player), signBefore, signAfter);
final Sign signAfter = (Sign) event.getClickedBlock().getState(); }
signAfter.setGlowingText(false); } else if (itemType == Material.INK_SAC) {
consumer.queueBlockReplace(Actor.actorFromEntity(player), signBefore, signAfter); if (signSideBefore.isGlowingText()) {
} signSideAfter.setGlowingText(false);
} else { consumer.queueBlockReplace(Actor.actorFromEntity(player), signBefore, signAfter);
DyeColor newColor = BukkitUtils.dyeToDyeColor(itemType); }
Sign signBefore = (Sign) before; } else if (itemType == Material.HONEYCOMB) {
if (newColor != null && signBefore.getColor() != newColor) { signAfter.setEditable(false);
final Sign signAfter = (Sign) event.getClickedBlock().getState();
signAfter.setColor(newColor);
consumer.queueBlockReplace(Actor.actorFromEntity(player), signBefore, signAfter); 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);
}
} }
} }
} }

View File

@ -17,7 +17,7 @@ public class SignChangeLogging extends LoggingListener {
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onSignChange(SignChangeEvent event) { public void onSignChange(SignChangeEvent event) {
if (isLogging(event.getBlock().getWorld(), Logging.SIGNTEXT)) { 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());
} }
} }
} }

View File

@ -36,9 +36,16 @@ import org.bukkit.block.DoubleChest;
import org.bukkit.block.data.Bisected; import org.bukkit.block.data.Bisected;
import org.bukkit.block.data.Bisected.Half; import org.bukkit.block.data.Bisected.Half;
import org.bukkit.block.data.BlockData; 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;
import org.bukkit.block.data.type.Slab.Type; import org.bukkit.block.data.type.Slab.Type;
import org.bukkit.block.data.type.Stairs; 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.ArmorStand;
import org.bukkit.entity.Entity; import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType; import org.bukkit.entity.EntityType;
@ -1223,4 +1230,83 @@ public class BukkitUtils {
public static boolean isSign(Material m) { public static boolean isSign(Material m) {
return allSigns.contains(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;
}
} }

View File

@ -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;
}
}

View File

@ -284,4 +284,15 @@ public class Utils {
public static String serializeForSQL(YamlConfiguration conf) { public static String serializeForSQL(YamlConfiguration conf) {
return mysqlPrepareBytesForInsertAllowNull(serializeYamlConfiguration(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;
}
} }