Added BlockType support for custom block support (implements #801)

This commit is contained in:
Intelli committed 2026-04-23 18:28:10 -06:00
1 parent fc91bc558c
commit eee96fb5f9
25 files changed
+415 -69

No files matched your search

@@ -68,7 +68,7 @@ public class CoreProtectAPI extends Queue {
if (list != null) { if (list != null) {
for (Object value : list) { for (Object value : list) {
if (value instanceof Material || value instanceof EntityType) { if (value instanceof Material || value instanceof EntityType || value instanceof String) {
result.put(value, false); result.put(value, false);
} }
else if (value instanceof Integer) { else if (value instanceof Integer) {
@@ -341,6 +341,27 @@ public class CoreProtectAPI extends Queue {
return true; return true;
} }
/**
* Logs a block placement by a user with specific block data.
*
* @param user
* The username
* @param location
* The location
* @param blockData
* The block data
* @return True if the placement was logged
*/
public boolean logPlacement(String user, Location location, BlockData blockData) {
if (!isEnabled() || !isValidUserAndLocation(user, location) || blockData == null) {
return false;
}
Block block = location.getBlock();
Queue.queueBlockPlace(user, block.getState(), block.getType(), null, block.getType(), -1, 0, blockData.getAsString());
return true;
}
/** /**
* Logs a block placement by a user with a specific material and data value. * Logs a block placement by a user with a specific material and data value.
* *
@@ -412,6 +433,28 @@ public class CoreProtectAPI extends Queue {
return true; return true;
} }
/**
* Logs a block removal by a user with specific block data.
*
* @param user
* The username
* @param location
* The location
* @param blockData
* The block data
* @return True if the removal was logged
*/
public boolean logRemoval(String user, Location location, BlockData blockData) {
if (!isEnabled() || !isValidUserAndLocation(user, location) || blockData == null) {
return false;
}
Block block = location.getBlock();
Database.containerBreakCheck(user, block.getType(), block, null, location);
Queue.queueBlockBreak(user, block.getState(), block.getType(), blockData.getAsString(), 0);
return true;
}
/** /**
* Logs a block removal by a user with a specific material and data value. * Logs a block removal by a user with a specific material and data value.
* *
@@ -7,6 +7,8 @@ import org.bukkit.Material;
import org.bukkit.block.data.BlockData; import org.bukkit.block.data.BlockData;
import net.coreprotect.api.SessionLookup; import net.coreprotect.api.SessionLookup;
import net.coreprotect.utility.BlockUtils;
import net.coreprotect.utility.BlockTypeUtils;
import net.coreprotect.utility.EntityUtils; import net.coreprotect.utility.EntityUtils;
import net.coreprotect.utility.MaterialUtils; import net.coreprotect.utility.MaterialUtils;
import net.coreprotect.utility.StringUtils; import net.coreprotect.utility.StringUtils;
@@ -84,7 +86,12 @@ public class ParseResult {
typeName = EntityUtils.getEntityType(type).name(); typeName = EntityUtils.getEntityType(type).name();
} }
else { else {
typeName = MaterialUtils.getType(type).name().toLowerCase(Locale.ROOT); Material material = MaterialUtils.getType(type);
if (material == null) {
return null;
}
typeName = material.name().toLowerCase(Locale.ROOT);
typeName = StringUtils.nameFilter(typeName, this.getData()); typeName = StringUtils.nameFilter(typeName, this.getData());
} }
@@ -98,9 +105,16 @@ public class ParseResult {
String blockData = parse[12]; String blockData = parse[12];
if (blockData == null || blockData.length() == 0) { if (blockData == null || blockData.length() == 0) {
return getType().createBlockData(); Material type = getType();
if (type != null) {
return type.createBlockData();
}
return BlockUtils.createBlockData(Integer.parseInt(parse[5]));
} }
return Bukkit.getServer().createBlockData(blockData);
BlockData result = BlockTypeUtils.createBlockDataFromString(blockData);
return result != null ? result : Bukkit.getServer().createBlockData(blockData);
} }
public int getX() { public int getX() {
@@ -223,6 +223,21 @@ public class BukkitAdapter implements BukkitInterface {
return Material.AIR; return Material.AIR;
} }
@Override
public boolean hasBlockType(String key) {
return false;
}
@Override
public BlockData createBlockData(String key) {
return null;
}
@Override
public BlockData createBlockDataFromString(String blockData) {
return null;
}
@Override @Override
public boolean isInvisible(Material material) { public boolean isInvisible(Material material) {
return BlockUtils.isAir(material); return BlockUtils.isAir(material);
@@ -76,6 +76,33 @@ public interface BukkitInterface {
*/ */
Material getBucketContents(Material material); Material getBucketContents(Material material);
/**
* Checks whether the runtime supports and contains a block type key.
*
* @param key
* The namespaced block key
* @return true if the block type exists, false otherwise
*/
boolean hasBlockType(String key);
/**
* Creates default block data for a block type key.
*
* @param key
* The namespaced block key
* @return The block data, or null if unsupported/unavailable
*/
BlockData createBlockData(String key);
/**
* Creates block data from a serialized block data string.
*
* @param blockData
* The serialized block data
* @return The block data, or null if unsupported/unavailable
*/
BlockData createBlockDataFromString(String blockData);
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
// Material type checking methods // Material type checking methods
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
@@ -10,7 +10,10 @@ import org.bukkit.ExplosionResult;
import org.bukkit.Keyed; import org.bukkit.Keyed;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.NamespacedKey; import org.bukkit.NamespacedKey;
import org.bukkit.Registry;
import org.bukkit.Tag; import org.bukkit.Tag;
import org.bukkit.block.BlockType;
import org.bukkit.block.data.BlockData;
import org.bukkit.entity.EntityType; import org.bukkit.entity.EntityType;
import org.bukkit.event.Event; import org.bukkit.event.Event;
import org.bukkit.event.block.BlockExplodeEvent; import org.bukkit.event.block.BlockExplodeEvent;
@@ -19,6 +22,7 @@ import org.bukkit.event.inventory.InventoryType;
import net.coreprotect.model.BlockGroup; import net.coreprotect.model.BlockGroup;
import net.coreprotect.utility.BlockTypeUtils;
/** /**
* Bukkit adapter implementation for Minecraft 1.21. * Bukkit adapter implementation for Minecraft 1.21.
@@ -103,6 +107,43 @@ public class Bukkit_v1_21 extends Bukkit_v1_20 {
} }
} }
@Override
public boolean hasBlockType(String key) {
return getBlockType(key) != null;
}
@Override
public BlockData createBlockData(String key) {
try {
BlockType blockType = getBlockType(key);
return blockType == null ? null : blockType.createBlockData();
}
catch (Exception e) {
return null;
}
}
@Override
public BlockData createBlockDataFromString(String blockData) {
try {
BlockType blockType = getBlockType(BlockTypeUtils.getBlockDataKey(blockData));
if (blockType == null) {
return null;
}
String states = BlockTypeUtils.getBlockDataStates(blockData);
return states == null ? blockType.createBlockData() : blockType.createBlockData(states);
}
catch (Exception e) {
return null;
}
}
private BlockType getBlockType(String key) {
NamespacedKey namespacedKey = NamespacedKey.fromString(BlockTypeUtils.normalizeKey(key));
return namespacedKey == null ? null : Registry.BLOCK.get(namespacedKey);
}
/** /**
* Gets the EntityType corresponding to a Material. * Gets the EntityType corresponding to a Material.
* Maps Material to its equivalent EntityType for entity handling. * Maps Material to its equivalent EntityType for entity handling.
@@ -67,7 +67,7 @@ public class LookupCommand {
boolean hasBlock = false; boolean hasBlock = false;
boolean hasEntity = false; boolean hasEntity = false;
for (Object arg : argBlocks) { for (Object arg : argBlocks) {
if (arg instanceof Material) { if (arg instanceof Material || arg instanceof String) {
hasBlock = true; hasBlock = true;
} }
else if (arg instanceof EntityType) { else if (arg instanceof EntityType) {
@@ -84,7 +84,7 @@ public class LookupCommand {
/* check for invalid block/entity combinations (exclude) */ /* check for invalid block/entity combinations (exclude) */
for (Object arg : argExclude.keySet()) { for (Object arg : argExclude.keySet()) {
if (arg instanceof Material) { if (arg instanceof Material || arg instanceof String) {
hasBlock = true; hasBlock = true;
} }
else if (arg instanceof EntityType) { else if (arg instanceof EntityType) {
@@ -192,6 +192,18 @@ public class PurgeCommand extends Consumer {
targetName = ((EntityType) restrictTarget).name().toLowerCase(Locale.ROOT); targetName = ((EntityType) restrictTarget).name().toLowerCase(Locale.ROOT);
entity = true; entity = true;
} }
else if (restrictTarget instanceof String) {
int blockId = MaterialUtils.getBlockId((String) restrictTarget, false);
if (includeListMaterial.length() == 0) {
includeListMaterial = includeListMaterial.append(blockId);
}
else {
includeListMaterial.append(",").append(blockId);
}
targetName = ((String) restrictTarget).toLowerCase(Locale.ROOT);
hasBlock = true;
}
if (restrictCount == 0) { if (restrictCount == 0) {
restrict = restrict.append("" + targetName + ""); restrict = restrict.append("" + targetName + "");
@@ -61,7 +61,7 @@ public class RollbackRestoreCommand {
boolean hasBlock = false; boolean hasBlock = false;
boolean hasEntity = false; boolean hasEntity = false;
for (Object arg : argBlocks) { for (Object arg : argBlocks) {
if (arg instanceof Material) { if (arg instanceof Material || arg instanceof String) {
hasBlock = true; hasBlock = true;
} }
else if (arg instanceof EntityType) { else if (arg instanceof EntityType) {
@@ -78,7 +78,7 @@ public class RollbackRestoreCommand {
/* check for invalid block/entity combinations (exclude) */ /* check for invalid block/entity combinations (exclude) */
for (Object arg : argExclude.keySet()) { for (Object arg : argExclude.keySet()) {
if (arg instanceof Material) { if (arg instanceof Material || arg instanceof String) {
hasBlock = true; hasBlock = true;
} }
else if (arg instanceof EntityType) { else if (arg instanceof EntityType) {
@@ -366,10 +366,9 @@ public class StandardLookupThread implements Runnable {
} }
} }
else { else {
dname = MaterialUtils.getType(dtype).name().toLowerCase(Locale.ROOT); dname = MaterialUtils.getBlockDisplayName(dtype, ddata);
dname = StringUtils.nameFilter(dname, ddata);
} }
if (dname.length() > 0 && !isPlayer) { if (dname.length() > 0 && !isPlayer && !dname.contains(":")) {
dname = "minecraft:" + dname.toLowerCase(Locale.ROOT) + ""; dname = "minecraft:" + dname.toLowerCase(Locale.ROOT) + "";
} }
@@ -14,6 +14,7 @@ import org.bukkit.entity.EntityType;
import net.coreprotect.language.Phrase; import net.coreprotect.language.Phrase;
import net.coreprotect.model.BlockGroup; import net.coreprotect.model.BlockGroup;
import net.coreprotect.utility.BlockTypeUtils;
import net.coreprotect.utility.Chat; import net.coreprotect.utility.Chat;
import net.coreprotect.utility.Color; import net.coreprotect.utility.Color;
import net.coreprotect.utility.EntityUtils; import net.coreprotect.utility.EntityUtils;
@@ -65,6 +66,9 @@ public class MaterialParser {
if (i3_material != null && (i3_material.isBlock() || argAction.contains(4))) { if (i3_material != null && (i3_material.isBlock() || argAction.contains(4))) {
restricted.add(i3_material); restricted.add(i3_material);
} }
else if (!argAction.contains(4) && BlockTypeUtils.hasBlockType(i3)) {
restricted.add(BlockTypeUtils.normalizeKey(i3));
}
else { else {
EntityType i3_entity = EntityUtils.getEntityType(i3); EntityType i3_entity = EntityUtils.getEntityType(i3);
if (i3_entity != null) { if (i3_entity != null) {
@@ -94,6 +98,9 @@ public class MaterialParser {
if (material != null && (material.isBlock() || argAction.contains(4))) { if (material != null && (material.isBlock() || argAction.contains(4))) {
restricted.add(material); restricted.add(material);
} }
else if (!argAction.contains(4) && BlockTypeUtils.hasBlockType(argument)) {
restricted.add(BlockTypeUtils.normalizeKey(argument));
}
else { else {
EntityType entityType = EntityUtils.getEntityType(argument); EntityType entityType = EntityUtils.getEntityType(argument);
if (entityType != null) { if (entityType != null) {
@@ -157,6 +164,9 @@ public class MaterialParser {
if (i3_material != null && (i3_material.isBlock() || argAction.contains(4))) { if (i3_material != null && (i3_material.isBlock() || argAction.contains(4))) {
excluded.put(i3_material, false); excluded.put(i3_material, false);
} }
else if (!argAction.contains(4) && BlockTypeUtils.hasBlockType(i3)) {
excluded.put(BlockTypeUtils.normalizeKey(i3), false);
}
else { else {
EntityType i3_entity = EntityUtils.getEntityType(i3); EntityType i3_entity = EntityUtils.getEntityType(i3);
if (i3_entity != null) { if (i3_entity != null) {
@@ -181,6 +191,9 @@ public class MaterialParser {
if (iMaterial != null && (iMaterial.isBlock() || argAction.contains(4))) { if (iMaterial != null && (iMaterial.isBlock() || argAction.contains(4))) {
excluded.put(iMaterial, false); excluded.put(iMaterial, false);
} }
else if (!argAction.contains(4) && BlockTypeUtils.hasBlockType(argument)) {
excluded.put(BlockTypeUtils.normalizeKey(argument), false);
}
else { else {
EntityType iEntity = EntityUtils.getEntityType(argument); EntityType iEntity = EntityUtils.getEntityType(argument);
if (iEntity != null) { if (iEntity != null) {
@@ -299,6 +312,9 @@ public class MaterialParser {
if (material != null) { if (material != null) {
isBlock = true; isBlock = true;
} }
else if (BlockTypeUtils.hasBlockType(argument)) {
isBlock = true;
}
else { else {
EntityType entityType = EntityUtils.getEntityType(argument); EntityType entityType = EntityUtils.getEntityType(argument);
if (entityType != null) { if (entityType != null) {
@@ -2,6 +2,7 @@ package net.coreprotect.consumer;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Objects;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Location; import org.bukkit.Location;
@@ -93,7 +94,7 @@ public class Queue {
protected static void queueBlockBreakValidate(final String user, final Block block, final BlockState blockState, final Material type, final String blockData, final int extraData, int ticks) { protected static void queueBlockBreakValidate(final String user, final Block block, final BlockState blockState, final Material type, final String blockData, final int extraData, int ticks) {
Scheduler.scheduleSyncDelayedTask(CoreProtect.getInstance(), () -> { Scheduler.scheduleSyncDelayedTask(CoreProtect.getInstance(), () -> {
try { try {
if (!block.getType().equals(type)) { if (!Objects.equals(block.getType(), type)) {
queueBlockBreak(user, blockState, type, blockData, null, extraData, 0); queueBlockBreak(user, blockState, type, blockData, null, extraData, 0);
} }
} }
@@ -108,7 +109,7 @@ public class Queue {
CreatureSpawner mobSpawner = (CreatureSpawner) block; CreatureSpawner mobSpawner = (CreatureSpawner) block;
extraData = EntityUtils.getSpawnerType(mobSpawner.getSpawnedType()); extraData = EntityUtils.getSpawnerType(mobSpawner.getSpawnedType());
} }
else if (type == Material.IRON_DOOR || BlockGroup.DOORS.contains(type) || type.equals(Material.SUNFLOWER) || type.equals(Material.LILAC) || type.equals(Material.TALL_GRASS) || type.equals(Material.LARGE_FERN) || type.equals(Material.ROSE_BUSH) || type.equals(Material.PEONY)) { // Double plant else if (type != null && (type == Material.IRON_DOOR || BlockGroup.DOORS.contains(type) || type.equals(Material.SUNFLOWER) || type.equals(Material.LILAC) || type.equals(Material.TALL_GRASS) || type.equals(Material.LARGE_FERN) || type.equals(Material.ROSE_BUSH) || type.equals(Material.PEONY))) { // Double plant
if (block.getBlockData() instanceof Bisected) { if (block.getBlockData() instanceof Bisected) {
if (((Bisected) block.getBlockData()).getHalf().equals(Half.TOP)) { if (((Bisected) block.getBlockData()).getHalf().equals(Half.TOP)) {
if (blockNumber == 5) { if (blockNumber == 5) {
@@ -126,7 +127,7 @@ public class Queue {
} }
} }
} }
else if (type.name().endsWith("_BED") && block.getBlockData() instanceof Bed) { else if (type != null && type.name().endsWith("_BED") && block.getBlockData() instanceof Bed) {
if (((Bed) block.getBlockData()).getPart().equals(Part.HEAD)) { if (((Bed) block.getBlockData()).getPart().equals(Part.HEAD)) {
return; return;
} }
@@ -155,7 +156,7 @@ public class Queue {
replaceType = blockReplaced.getType(); replaceType = blockReplaced.getType();
replaceData = 0; replaceData = 0;
if ((replaceType == Material.IRON_DOOR || BlockGroup.DOORS.contains(replaceType) || replaceType.equals(Material.SUNFLOWER) || replaceType.equals(Material.LILAC) || replaceType.equals(Material.TALL_GRASS) || replaceType.equals(Material.LARGE_FERN) || replaceType.equals(Material.ROSE_BUSH) || replaceType.equals(Material.PEONY)) && replaceData >= 8) { // Double plant top half if (replaceType != null && (replaceType == Material.IRON_DOOR || BlockGroup.DOORS.contains(replaceType) || replaceType.equals(Material.SUNFLOWER) || replaceType.equals(Material.LILAC) || replaceType.equals(Material.TALL_GRASS) || replaceType.equals(Material.LARGE_FERN) || replaceType.equals(Material.ROSE_BUSH) || replaceType.equals(Material.PEONY)) && replaceData >= 8) { // Double plant top half
BlockState blockBelow = blockReplaced.getWorld().getBlockAt(blockReplaced.getX(), blockReplaced.getY() - 1, blockReplaced.getZ()).getState(); BlockState blockBelow = blockReplaced.getWorld().getBlockAt(blockReplaced.getX(), blockReplaced.getY() - 1, blockReplaced.getZ()).getState();
Material belowType = blockBelow.getType(); Material belowType = blockBelow.getType();
Queue.queueBlockBreak(user, blockBelow, belowType, blockBelow.getBlockData().getAsString(), 0); Queue.queueBlockBreak(user, blockBelow, belowType, blockBelow.getBlockData().getAsString(), 0);
@@ -203,7 +204,7 @@ public class Queue {
try { try {
Material blockType = block.getType(); Material blockType = block.getType();
BlockState replacedBlock = blockReplaced; BlockState replacedBlock = blockReplaced;
boolean placed = blockType.equals(forceT); boolean placed = Objects.equals(blockType, forceT);
if (!placed && forceT == Material.WATER) { if (!placed && forceT == Material.WATER) {
BlockData currentBlockData = block.getBlockData(); BlockData currentBlockData = block.getBlockData();
if (currentBlockData instanceof Waterlogged) { if (currentBlockData instanceof Waterlogged) {
@@ -227,7 +228,7 @@ public class Queue {
if (placed) { if (placed) {
BlockState blockStateLocation = blockLocation; BlockState blockStateLocation = blockLocation;
if (blockType.equals(forceT) && Config.getConfig(blockLocation.getWorld()).BLOCK_MOVEMENT) { if (blockType != null && Objects.equals(blockType, forceT) && Config.getConfig(blockLocation.getWorld()).BLOCK_MOVEMENT) {
blockStateLocation = BlockUtil.gravityScan(blockLocation.getLocation(), blockType, user).getState(); blockStateLocation = BlockUtil.gravityScan(blockLocation.getLocation(), blockType, user).getState();
} }
@@ -17,7 +17,7 @@ class BlockPlaceProcess {
if (object instanceof BlockState) { if (object instanceof BlockState) {
BlockState block = (BlockState) object; BlockState block = (BlockState) object;
List<Object> meta = BlockUtils.processMeta(block); List<Object> meta = BlockUtils.processMeta(block);
if (blockType.equals(Material.SKELETON_SKULL) || blockType.equals(Material.SKELETON_WALL_SKULL) || blockType.equals(Material.WITHER_SKELETON_SKULL) || blockType.equals(Material.WITHER_SKELETON_WALL_SKULL) || blockType.equals(Material.ZOMBIE_HEAD) || blockType.equals(Material.ZOMBIE_WALL_HEAD) || blockType.equals(Material.PLAYER_HEAD) || blockType.equals(Material.PLAYER_WALL_HEAD) || blockType.equals(Material.CREEPER_HEAD) || blockType.equals(Material.CREEPER_WALL_HEAD) || blockType.equals(Material.DRAGON_HEAD) || blockType.equals(Material.DRAGON_WALL_HEAD)) { if (blockType != null && (blockType.equals(Material.SKELETON_SKULL) || blockType.equals(Material.SKELETON_WALL_SKULL) || blockType.equals(Material.WITHER_SKELETON_SKULL) || blockType.equals(Material.WITHER_SKELETON_WALL_SKULL) || blockType.equals(Material.ZOMBIE_HEAD) || blockType.equals(Material.ZOMBIE_WALL_HEAD) || blockType.equals(Material.PLAYER_HEAD) || blockType.equals(Material.PLAYER_WALL_HEAD) || blockType.equals(Material.CREEPER_HEAD) || blockType.equals(Material.CREEPER_WALL_HEAD) || blockType.equals(Material.DRAGON_HEAD) || blockType.equals(Material.DRAGON_WALL_HEAD))) {
SkullPlaceLogger.log(preparedStmt, preparedStmtSkulls, batchCount, user, block, MaterialUtils.getBlockId(replaceType), replaceData); SkullPlaceLogger.log(preparedStmt, preparedStmtSkulls, batchCount, user, block, MaterialUtils.getBlockId(replaceType), replaceData);
} }
else if (forceData == 1) { else if (forceData == 1) {
@@ -314,6 +314,15 @@ public class LookupRaw extends Queue {
includeListEntity.append(",").append(EntityUtils.getEntityId(targetName, false)); includeListEntity.append(",").append(EntityUtils.getEntityId(targetName, false));
} }
} }
else if (restrictTarget instanceof String) {
int blockId = MaterialUtils.getBlockId((String) restrictTarget, false);
if (includeListMaterial.length() == 0) {
includeListMaterial = includeListMaterial.append(blockId);
}
else {
includeListMaterial.append(",").append(blockId);
}
}
} }
includeBlock = includeListMaterial.toString(); includeBlock = includeListMaterial.toString();
@@ -351,6 +360,17 @@ public class LookupRaw extends Queue {
excludeListEntity.append(",").append(EntityUtils.getEntityId(targetName, false)); excludeListEntity.append(",").append(EntityUtils.getEntityId(targetName, false));
} }
} }
else if (restrictTarget instanceof String) {
int blockId = MaterialUtils.getBlockId((String) restrictTarget, false);
if (blockId > -1) {
if (excludeListMaterial.length() == 0) {
excludeListMaterial = excludeListMaterial.append(blockId);
}
else {
excludeListMaterial.append(",").append(blockId);
}
}
}
} }
excludeBlock = excludeListMaterial.toString(); excludeBlock = excludeListMaterial.toString();
@@ -16,6 +16,7 @@ import net.coreprotect.database.statement.BlockStatement;
import net.coreprotect.database.statement.UserStatement; import net.coreprotect.database.statement.UserStatement;
import net.coreprotect.event.CoreProtectPreLogEvent; import net.coreprotect.event.CoreProtectPreLogEvent;
import net.coreprotect.thread.CacheHandler; import net.coreprotect.thread.CacheHandler;
import net.coreprotect.utility.BlockTypeUtils;
import net.coreprotect.utility.WorldUtils; import net.coreprotect.utility.WorldUtils;
public class BlockBreakLogger { public class BlockBreakLogger {
@@ -27,14 +28,19 @@ public class BlockBreakLogger {
public static void log(PreparedStatement preparedStmt, int batchCount, String user, Location location, int type, int data, List<Object> meta, String blockData, String overrideData) { public static void log(PreparedStatement preparedStmt, int batchCount, String user, Location location, int type, int data, List<Object> meta, String blockData, String overrideData) {
try { try {
Material checkType = net.coreprotect.utility.MaterialUtils.getType(type); Material checkType = net.coreprotect.utility.MaterialUtils.getType(type);
if (checkType == null) { String blockKey = BlockTypeUtils.getBlockDataKey(blockData);
if (blockKey.length() == 0 && checkType != null) {
blockKey = checkType.getKey().toString();
}
if (checkType == null && blockKey.length() == 0) {
return; return;
} }
else if (checkType.equals(Material.AIR) || checkType.equals(Material.CAVE_AIR)) { else if (checkType != null && (checkType.equals(Material.AIR) || checkType.equals(Material.CAVE_AIR)) && BlockTypeUtils.isAir(blockKey)) {
return; return;
} }
if (ConfigHandler.isBlacklisted(user, checkType.getKey().toString())) { if (ConfigHandler.isBlacklisted(user, blockKey)) {
return; return;
} }
@@ -46,7 +52,7 @@ public class BlockBreakLogger {
if (checkType == Material.LECTERN) { if (checkType == Material.LECTERN) {
blockData = blockData.replaceFirst("has_book=true", "has_book=false"); blockData = blockData.replaceFirst("has_book=true", "has_book=false");
} }
else if (checkType == Material.PAINTING || BukkitAdapter.ADAPTER.isItemFrame(checkType)) { else if (checkType != null && (checkType == Material.PAINTING || BukkitAdapter.ADAPTER.isItemFrame(checkType))) {
blockData = overrideData; blockData = overrideData;
} }
@@ -68,7 +74,8 @@ public class BlockBreakLogger {
return; return;
} }
BlockStatement.insert(preparedStmt, batchCount, time, userId, wid, x, y, z, type, data, meta, blockData, 0, 0); int internalType = blockKey.length() > 0 ? net.coreprotect.utility.MaterialUtils.getBlockId(blockKey, true) : type;
BlockStatement.insert(preparedStmt, batchCount, time, userId, wid, x, y, z, internalType, data, meta, blockData, 0, 0);
} }
catch (Exception e) { catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
@@ -17,6 +17,7 @@ import net.coreprotect.database.statement.BlockStatement;
import net.coreprotect.database.statement.UserStatement; import net.coreprotect.database.statement.UserStatement;
import net.coreprotect.event.CoreProtectPreLogEvent; import net.coreprotect.event.CoreProtectPreLogEvent;
import net.coreprotect.thread.CacheHandler; import net.coreprotect.thread.CacheHandler;
import net.coreprotect.utility.BlockTypeUtils;
import net.coreprotect.utility.MaterialUtils; import net.coreprotect.utility.MaterialUtils;
import net.coreprotect.utility.WorldUtils; import net.coreprotect.utility.WorldUtils;
@@ -31,10 +32,11 @@ public class BlockPlaceLogger {
Material type = block.getType(); Material type = block.getType();
if (blockData == null && (forceType == null || (!forceType.equals(Material.WATER)) && (!forceType.equals(Material.LAVA)))) { if (blockData == null && (forceType == null || (!forceType.equals(Material.WATER)) && (!forceType.equals(Material.LAVA)))) {
blockData = block.getBlockData().getAsString(); blockData = block.getBlockData().getAsString();
if (blockData.equals("minecraft:air")) { if (BlockTypeUtils.isAir(BlockTypeUtils.getBlockDataKey(blockData))) {
blockData = null; blockData = null;
} }
} }
String blockKey = BlockTypeUtils.getBlockDataKey(blockData);
int data = 0; int data = 0;
if (forceType != null && force) { if (forceType != null && force) {
type = forceType; type = forceType;
@@ -45,16 +47,22 @@ public class BlockPlaceLogger {
data = forceData; data = forceData;
} }
} }
else if (forceType != null && !type.equals(forceType)) { else if (forceType != null && (type == null || !type.equals(forceType))) {
type = forceType; type = forceType;
data = forceData; data = forceData;
} }
if (blockKey.length() == 0) {
if (type == null) {
return;
}
blockKey = type.getKey().toString();
}
if (type.equals(Material.AIR) || type.equals(Material.CAVE_AIR)) { if (type != null && (type.equals(Material.AIR) || type.equals(Material.CAVE_AIR)) && BlockTypeUtils.isAir(blockKey)) {
return; return;
} }
if (ConfigHandler.isBlacklisted(user, type.getKey().toString())){ if (ConfigHandler.isBlacklisted(user, blockKey)){
return; return;
} }
@@ -105,9 +113,10 @@ public class BlockPlaceLogger {
return; return;
} }
int internalType = MaterialUtils.getBlockId(type.name(), true); int internalType = MaterialUtils.getBlockId(blockKey, true);
if (replacedType > 0 && MaterialUtils.getType(replacedType) != Material.AIR && MaterialUtils.getType(replacedType) != Material.CAVE_AIR) { int replacedInternalType = MaterialUtils.getBlockId(replaceBlockData, MaterialUtils.getType(replacedType), true);
BlockStatement.insert(preparedStmt, batchCount, time, userId, wid, x, y, z, replacedType, replacedData, null, replaceBlockData, 0, 0); if (replacedInternalType > 0 && !BlockTypeUtils.isAir(MaterialUtils.getBlockName(replacedInternalType))) {
BlockStatement.insert(preparedStmt, batchCount, time, userId, wid, x, y, z, replacedInternalType, replacedData, null, replaceBlockData, 0, 0);
} }
BlockStatement.insert(preparedStmt, batchCount, time, userId, wid, x, y, z, internalType, data, meta, blockData, 1, 0); BlockStatement.insert(preparedStmt, batchCount, time, userId, wid, x, y, z, internalType, data, meta, blockData, 1, 0);
@@ -1,8 +1,6 @@
package net.coreprotect.database.logger; package net.coreprotect.database.logger;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
import java.util.Locale;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.Location; import org.bukkit.Location;
@@ -14,6 +12,7 @@ import net.coreprotect.config.ConfigHandler;
import net.coreprotect.database.statement.BlockStatement; import net.coreprotect.database.statement.BlockStatement;
import net.coreprotect.database.statement.UserStatement; import net.coreprotect.database.statement.UserStatement;
import net.coreprotect.event.CoreProtectPreLogEvent; import net.coreprotect.event.CoreProtectPreLogEvent;
import net.coreprotect.utility.BlockTypeUtils;
import net.coreprotect.utility.MaterialUtils; import net.coreprotect.utility.MaterialUtils;
import net.coreprotect.utility.WorldUtils; import net.coreprotect.utility.WorldUtils;
@@ -25,8 +24,17 @@ public class PlayerInteractLogger {
public static void log(PreparedStatement preparedStmt, int batchCount, String user, BlockState block, Material blockType) { public static void log(PreparedStatement preparedStmt, int batchCount, String user, BlockState block, Material blockType) {
try { try {
int type = MaterialUtils.getBlockId(blockType.name(), true); String blockData = block.getBlockData().getAsString();
if (ConfigHandler.isBlacklisted(user) || MaterialUtils.getType(type).equals(Material.AIR) || MaterialUtils.getType(type).equals(Material.CAVE_AIR)) { String blockKey = BlockTypeUtils.getBlockDataKey(blockData);
if (blockKey.length() == 0 && blockType != null) {
blockKey = blockType.getKey().toString();
}
if (blockKey.length() == 0) {
return;
}
int type = MaterialUtils.getBlockId(blockKey, true);
if (ConfigHandler.isBlacklisted(user) || BlockTypeUtils.isAir(blockKey)) {
return; return;
} }
@@ -47,7 +55,7 @@ public class PlayerInteractLogger {
int y = eventLocation.getBlockY(); int y = eventLocation.getBlockY();
int z = eventLocation.getBlockZ(); int z = eventLocation.getBlockZ();
int data = 0; int data = 0;
BlockStatement.insert(preparedStmt, batchCount, time, userId, wid, x, y, z, type, data, null, null, 2, 0); BlockStatement.insert(preparedStmt, batchCount, time, userId, wid, x, y, z, type, data, null, blockData, 2, 0);
} }
catch (Exception e) { catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
@@ -112,12 +112,10 @@ public class BlockLookup {
target = EntityUtils.getEntityType(resultType).name(); target = EntityUtils.getEntityType(resultType).name();
} }
else { else {
Material resultMaterial = MaterialUtils.getType(resultType); target = MaterialUtils.getBlockDisplayName(resultType, resultData);
if (resultMaterial == null) { if (target.length() > 0 && !target.contains(":")) {
resultMaterial = Material.AIR; target = "minecraft:" + target.toLowerCase(Locale.ROOT);
} }
target = StringUtils.nameFilter(resultMaterial.name().toLowerCase(Locale.ROOT), resultData);
target = "minecraft:" + target.toLowerCase(Locale.ROOT);
} }
if (target.length() > 0) { if (target.length() > 0) {
target = "" + target + ""; target = "" + target + "";
@@ -108,13 +108,8 @@ public class ChestTransactionLookup {
rbFormat = Color.STRIKETHROUGH; rbFormat = Color.STRIKETHROUGH;
} }
Material resultMaterial = MaterialUtils.getType(resultType); String target = MaterialUtils.getBlockDisplayName(resultType, resultData);
if (resultMaterial == null) { if (target.length() > 0 && !target.contains(":")) {
resultMaterial = Material.AIR;
}
String target = resultMaterial.name().toLowerCase(Locale.ROOT);
target = StringUtils.nameFilter(target, resultData);
if (target.length() > 0) {
target = "minecraft:" + target.toLowerCase(Locale.ROOT) + ""; target = "minecraft:" + target.toLowerCase(Locale.ROOT) + "";
} }
@@ -4,7 +4,6 @@ import java.sql.ResultSet;
import java.sql.Statement; import java.sql.Statement;
import java.util.Locale; import java.util.Locale;
import org.bukkit.Material;
import org.bukkit.block.Block; import org.bukkit.block.Block;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
@@ -16,7 +15,6 @@ import net.coreprotect.listener.channel.PluginChannelListener;
import net.coreprotect.utility.ChatUtils; import net.coreprotect.utility.ChatUtils;
import net.coreprotect.utility.Color; import net.coreprotect.utility.Color;
import net.coreprotect.utility.MaterialUtils; import net.coreprotect.utility.MaterialUtils;
import net.coreprotect.utility.StringUtils;
import net.coreprotect.utility.WorldUtils; import net.coreprotect.utility.WorldUtils;
public class InteractionLookup { public class InteractionLookup {
@@ -96,13 +94,8 @@ public class InteractionLookup {
rbFormat = Color.STRIKETHROUGH; rbFormat = Color.STRIKETHROUGH;
} }
Material resultMaterial = MaterialUtils.getType(resultType); String target = MaterialUtils.getBlockDisplayName(resultType, resultData);
if (resultMaterial == null) { if (target.length() > 0 && !target.contains(":")) {
resultMaterial = Material.AIR;
}
String target = resultMaterial.name().toLowerCase(Locale.ROOT);
target = StringUtils.nameFilter(target, resultData);
if (target.length() > 0) {
target = "minecraft:" + target.toLowerCase(Locale.ROOT) + ""; target = "minecraft:" + target.toLowerCase(Locale.ROOT) + "";
} }
@@ -77,6 +77,15 @@ public class RollbackBlockHandler extends Queue {
((Piston) blockData).setFacing(technicalPiston.getFacing()); ((Piston) blockData).setFacing(technicalPiston.getFacing());
} }
if (rowType == null) {
if (blockData != null) {
BlockUtils.prepareTypeAndData(chunkChanges, block, null, blockData, true);
return countBlock;
}
return false;
}
if ((rowType == Material.AIR) && ((BukkitAdapter.ADAPTER.isItemFrame(oldTypeMaterial)) || (oldTypeMaterial == Material.PAINTING))) { if ((rowType == Material.AIR) && ((BukkitAdapter.ADAPTER.isItemFrame(oldTypeMaterial)) || (oldTypeMaterial == Material.PAINTING))) {
HangingUtil.removeHanging(block.getState(), blockDataString); HangingUtil.removeHanging(block.getState(), blockDataString);
} }
@@ -124,6 +124,10 @@ public class RollbackComplete {
item = (!item ? !(((Material) restrictTarget).isBlock()) : item); item = (!item ? !(((Material) restrictTarget).isBlock()) : item);
material = true; material = true;
} }
else if (restrictTarget instanceof String) {
targetName = ((String) restrictTarget).toLowerCase(Locale.ROOT);
material = true;
}
else if (restrictTarget instanceof EntityType) { else if (restrictTarget instanceof EntityType) {
targetName = ((EntityType) restrictTarget).name().toLowerCase(Locale.ROOT); targetName = ((EntityType) restrictTarget).name().toLowerCase(Locale.ROOT);
entity = true; entity = true;
@@ -182,6 +186,10 @@ public class RollbackComplete {
item = (!item ? !(((Material) excludeTarget).isBlock()) : item); item = (!item ? !(((Material) excludeTarget).isBlock()) : item);
material = true; material = true;
} }
else if (excludeTarget instanceof String) {
targetName = ((String) excludeTarget).toLowerCase(Locale.ROOT);
material = true;
}
else if (excludeTarget instanceof EntityType) { else if (excludeTarget instanceof EntityType) {
targetName = ((EntityType) excludeTarget).name().toLowerCase(Locale.ROOT); targetName = ((EntityType) excludeTarget).name().toLowerCase(Locale.ROOT);
entity = true; entity = true;
@@ -33,6 +33,7 @@ import net.coreprotect.database.logger.ItemLogger;
import net.coreprotect.model.BlockGroup; import net.coreprotect.model.BlockGroup;
import net.coreprotect.thread.Scheduler; import net.coreprotect.thread.Scheduler;
import net.coreprotect.utility.BlockUtils; import net.coreprotect.utility.BlockUtils;
import net.coreprotect.utility.BlockTypeUtils;
import net.coreprotect.utility.ItemUtils; import net.coreprotect.utility.ItemUtils;
import net.coreprotect.utility.MaterialUtils; import net.coreprotect.utility.MaterialUtils;
import net.coreprotect.utility.Teleport; import net.coreprotect.utility.Teleport;
@@ -101,7 +102,10 @@ public class RollbackProcessor {
BlockData blockData = null; BlockData blockData = null;
if (blockDataString != null && blockDataString.contains(":")) { if (blockDataString != null && blockDataString.contains(":")) {
try { try {
blockData = Bukkit.getServer().createBlockData(blockDataString); blockData = BlockTypeUtils.createBlockDataFromString(blockDataString);
if (blockData == null) {
blockData = Bukkit.getServer().createBlockData(blockDataString);
}
} }
catch (Exception e) { catch (Exception e) {
// corrupt BlockData, let the server automatically set the BlockData instead // corrupt BlockData, let the server automatically set the BlockData instead
@@ -112,8 +116,8 @@ public class RollbackProcessor {
if (blockData != null) { if (blockData != null) {
rawBlockData = blockData.clone(); rawBlockData = blockData.clone();
} }
if (rawBlockData == null && rowType != null && rowType.isBlock()) { if (rawBlockData == null) {
rawBlockData = BlockUtils.createBlockData(rowType); rawBlockData = BlockUtils.createBlockData(rowTypeRaw);
} }
String rowUser = ConfigHandler.playerIdCacheReversed.get((Integer) row[2]); String rowUser = ConfigHandler.playerIdCacheReversed.get((Integer) row[2]);
@@ -0,0 +1,94 @@
package net.coreprotect.utility;
import java.util.Locale;
import org.bukkit.block.data.BlockData;
import org.bukkit.block.data.Waterlogged;
import net.coreprotect.bukkit.BukkitAdapter;
public class BlockTypeUtils {
private static final String NAMESPACE = "minecraft:";
private BlockTypeUtils() {
throw new IllegalStateException("Utility class");
}
public static String normalizeKey(String key) {
if (key == null) {
return "";
}
key = key.toLowerCase(Locale.ROOT).trim();
if (key.length() > 0 && !key.contains(":")) {
key = NAMESPACE + key;
}
return key;
}
public static String getBlockDataKey(String blockData) {
if (blockData == null) {
return "";
}
String key = blockData;
int propertyIndex = key.indexOf('[');
if (propertyIndex > -1) {
key = key.substring(0, propertyIndex);
}
return normalizeKey(key);
}
public static String getBlockDataStates(String blockData) {
if (blockData == null) {
return null;
}
int propertyIndex = blockData.indexOf('[');
if (propertyIndex == -1 || !blockData.endsWith("]")) {
return null;
}
return blockData.substring(propertyIndex);
}
public static boolean hasBlockType(String key) {
return BukkitAdapter.ADAPTER != null && BukkitAdapter.ADAPTER.hasBlockType(normalizeKey(key));
}
public static BlockData createBlockData(String key) {
if (BukkitAdapter.ADAPTER == null) {
return null;
}
return normalizeBlockData(BukkitAdapter.ADAPTER.createBlockData(normalizeKey(key)));
}
public static BlockData createBlockDataFromString(String blockData) {
if (BukkitAdapter.ADAPTER == null) {
return null;
}
return normalizeBlockData(BukkitAdapter.ADAPTER.createBlockDataFromString(blockData));
}
public static boolean isAir(String key) {
key = normalizeKey(key);
return "minecraft:air".equals(key) || "minecraft:cave_air".equals(key) || "minecraft:void_air".equals(key);
}
private static BlockData normalizeBlockData(BlockData blockData) {
if (blockData == null) {
return null;
}
if (blockData instanceof Waterlogged) {
((Waterlogged) blockData).setWaterlogged(false);
}
return blockData;
}
}
@@ -3,7 +3,6 @@ package net.coreprotect.utility;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Locale;
import java.util.Map; import java.util.Map;
import org.bukkit.Material; import org.bukkit.Material;
@@ -26,8 +25,6 @@ import net.coreprotect.thread.Scheduler;
public class BlockUtils { public class BlockUtils {
private static final String NAMESPACE = "minecraft:";
private BlockUtils() { private BlockUtils() {
throw new IllegalStateException("Utility class"); throw new IllegalStateException("Utility class");
} }
@@ -36,12 +33,17 @@ public class BlockUtils {
byte[] result = null; byte[] result = null;
if (string != null) { if (string != null) {
Material material = MaterialUtils.getType(type); Material material = MaterialUtils.getType(type);
if (material == null) { String blockKey = MaterialUtils.getBlockName(type);
if ((blockKey == null || blockKey.length() == 0) && material != null) {
blockKey = material.getKey().toString();
}
if (blockKey == null || blockKey.length() == 0) {
return result; return result;
} }
if (material.isBlock() && !createBlockData(material).getAsString().equals(string) && string.startsWith(NAMESPACE + material.name().toLowerCase(Locale.ROOT) + "[") && string.endsWith("]")) { BlockData defaultBlockData = createBlockData(type);
String substring = string.substring(material.name().length() + 11, string.length() - 1); if (defaultBlockData != null && !defaultBlockData.getAsString().equals(string) && string.startsWith(blockKey + "[") && string.endsWith("]")) {
String substring = string.substring(blockKey.length() + 1, string.length() - 1);
String[] blockDataSplit = substring.split(","); String[] blockDataSplit = substring.split(",");
ArrayList<String> blockDataArray = new ArrayList<>(); ArrayList<String> blockDataArray = new ArrayList<>();
for (String data : blockDataSplit) { for (String data : blockDataSplit) {
@@ -52,7 +54,7 @@ public class BlockUtils {
} }
string = String.join(",", blockDataArray); string = String.join(",", blockDataArray);
} }
else if (!string.contains(":") && (material == Material.PAINTING || BukkitAdapter.ADAPTER.isItemFrame(material))) { else if (material != null && !string.contains(":") && (material == Material.PAINTING || BukkitAdapter.ADAPTER.isItemFrame(material))) {
int id = MaterialUtils.getBlockdataId(string, true); int id = MaterialUtils.getBlockdataId(string, true);
if (id > -1) { if (id > -1) {
string = Integer.toString(id); string = Integer.toString(id);
@@ -75,7 +77,11 @@ public class BlockUtils {
String result = ""; String result = "";
if (data != null) { if (data != null) {
Material material = MaterialUtils.getType(type); Material material = MaterialUtils.getType(type);
if (material == null) { String blockKey = MaterialUtils.getBlockName(type);
if ((blockKey == null || blockKey.length() == 0) && material != null) {
blockKey = material.getKey().toString();
}
if (blockKey == null || blockKey.length() == 0) {
return result; return result;
} }
@@ -94,11 +100,11 @@ public class BlockUtils {
} }
} }
if (material == Material.PAINTING || BukkitAdapter.ADAPTER.isItemFrame(material)) { if (material != null && (material == Material.PAINTING || BukkitAdapter.ADAPTER.isItemFrame(material))) {
result = String.join(",", blockDataArray); result = String.join(",", blockDataArray);
} }
else { else {
result = NAMESPACE + material.name().toLowerCase(Locale.ROOT) + "[" + String.join(",", blockDataArray) + "]"; result = blockKey + "[" + String.join(",", blockDataArray) + "]";
} }
} }
else { else {
@@ -161,6 +167,15 @@ public class BlockUtils {
} }
} }
public static BlockData createBlockData(int type) {
Material material = MaterialUtils.getType(type);
if (material != null && material.isBlock()) {
return createBlockData(material);
}
return BlockTypeUtils.createBlockData(MaterialUtils.getBlockName(type));
}
public static void prepareTypeAndData(Map<Block, BlockData> map, Block block, Material type, BlockData blockData, boolean update) { public static void prepareTypeAndData(Map<Block, BlockData> map, Block block, Material type, BlockData blockData, boolean update) {
if (blockData == null) { if (blockData == null) {
blockData = createBlockData(type); blockData = createBlockData(type);
@@ -24,6 +24,15 @@ public class MaterialUtils extends Queue {
return getBlockId(material.name(), true); return getBlockId(material.name(), true);
} }
public static int getBlockId(String blockData, Material fallback, boolean internal) {
String name = BlockTypeUtils.getBlockDataKey(blockData);
if (name.length() == 0 && fallback != null) {
name = fallback.getKey().toString();
}
return name.length() == 0 ? -1 : getBlockId(name, internal);
}
public static int getBlockId(String name, boolean internal) { public static int getBlockId(String name, boolean internal) {
int id = -1; int id = -1;
@@ -95,6 +104,15 @@ public class MaterialUtils extends Queue {
return name; return name;
} }
public static String getBlockDisplayName(int id, int data) {
Material material = getType(id);
if (material != null) {
return StringUtils.nameFilter(material.name().toLowerCase(Locale.ROOT), data);
}
return getBlockName(id);
}
public static String getBlockNameShort(int id) { public static String getBlockNameShort(int id) {
String name = getBlockName(id); String name = getBlockName(id);
if (name.contains(":")) { if (name.contains(":")) {