package vg.civcraft.mc.civmodcore.world;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import net.minecraft.world.level.block.state.properties.IBlockState;
import org.apache.commons.lang3.reflect.FieldUtils;
import org.bukkit.Bukkit;
import org.bukkit.block.Block;
import org.bukkit.craftbukkit.v1_17_R1.CraftWorld;
import org.bukkit.craftbukkit.v1_17_R1.block.CraftBlock;

public final class BlockProperties {

	private static final Map<String, IBlockState<?>> BLOCK_STATES = new HashMap<>();

	static {
		for (final Field field : FieldUtils.getAllFields(net.minecraft.world.level.block.state.properties.BlockProperties.class)) {
			if (!IBlockState.class.isAssignableFrom(field.getType())) {
				continue;
			}
			try {
				final IBlockState<?> state = (IBlockState<?>) FieldUtils.readField(field, (Object) null, true);
				BLOCK_STATES.put(state.getName(), state);
			}
			catch (final IllegalAccessException exception) {
				exception.printStackTrace();
			}
		}
		Bukkit.getLogger().warning("[BlockProperties] Available block states: " +
				String.join(",", BLOCK_STATES.keySet()) + ".");
	}

	public static boolean setBlockProperty(final Block block, final String key, final String value) {
		// we need this wrapper method to trick the java generics
		return innerSetBlockProperty(block, key, value);
	}

	private static <V extends Comparable<V>> boolean innerSetBlockProperty(final Block block,
																		   final String key,
																		   final String value) {
		@SuppressWarnings("unchecked")
		final IBlockState<V> state = (IBlockState<V>) BLOCK_STATES.get(key);
		if (state == null) {
			return false;
		}
		final Optional<V> opt = state.b(value);
		if (opt.isEmpty()) {
			return false;
		}
		final V valueToSet = opt.get();
		final CraftBlock craftBlock = (CraftBlock) block;
		final CraftWorld craftWorld = (CraftWorld) block.getWorld();
		// no idea what the last integer parameter does, I found 2 and 3 being used in NMS code and stuck to that
		craftWorld.getHandle().setTypeAndData(craftBlock.getPosition(), craftBlock.getNMS().set(state, valueToSet), 2);
		return true;
	}

}

@@ -267,34 +267,8 @@
 ls;%0A
-import org.bukkit.Bukkit;%0A
 impo
@@ -406,46 +406,185 @@
 ck;%0A
-%0Apublic final class BlockProperties %7B%0A
+import vg.civcraft.mc.civmodcore.utilities.CivLogger;%0A%0Apublic final class BlockProperties %7B%0A%0A%09private static final CivLogger LOGGER = CivLogger.getLogger(BlockProperties.class);
 %0A%09pr
@@ -1141,34 +1141,19 @@
 %7D%0A%09%09
-Bukkit.getLogger().warning
+LOGGER.info
 (%22%5BB
@@ -1195,21 +1195,17 @@
 tes: %22 +
-%0A%09%09%09%09
+ 
 String.j
@@ -2027,110 +2027,62 @@
 %09// 
-no idea what the last integer parameter does, I found 2 and 3 being used in NMS code and stuck to that
+Deobf path: net.minecraft.world.level.Level.setBlock()
 %0A%09%09c
@@ -2191,12 +2191,166 @@
 et),
- 2);
+%0A%09%09%09%09// This value is named %22flag%22 and appears to be a set of bitwise indicators for block updates%0A%09%09%09%092); // 2 and 3 being used in NMS code and stuck to that
 %0A%09%09r

Update BlockProperties