diff --git a/bukkit18/src/main/java/com/boydti/fawe/bukkit/v1_8/BukkitQueue18R3.java b/bukkit18/src/main/java/com/boydti/fawe/bukkit/v1_8/BukkitQueue18R3.java index 1efcb4f6..90d884ea 100644 --- a/bukkit18/src/main/java/com/boydti/fawe/bukkit/v1_8/BukkitQueue18R3.java +++ b/bukkit18/src/main/java/com/boydti/fawe/bukkit/v1_8/BukkitQueue18R3.java @@ -488,9 +488,6 @@ public class BukkitQueue18R3 extends BukkitQueue_0 + * Probably throws some error if you try to get a non existent key + * @param key + * @param + * @return + */ + public static T get(String key, Class root) { + String[] split = key.split("\\."); + Object instance = getInstance(split, root); + if (instance != null) { + Field field = getField(split, instance); + if (field != null) { + try { + return (T) field.get(instance); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + } + } + Fawe.debug("Failed to get config option: " + key); + return null; + } + + /** + * Set the value of a specific node
+ * Probably throws some error if you supply non existing keys or invalid values + * @param key config node + * @param value value + * + */ + public static void set(String key, Object value, Class root) { + String[] split = key.split("\\."); + Object instance = getInstance(split, root); + if (instance != null) { + Field field = getField(split, instance); + if (field != null) { + try { + if (field.getAnnotation(Final.class) != null) { + return; + } + field.set(instance, value); + return; + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + } + } + Fawe.debug("Failed to set config option: " + key + ": " + value + " | " + instance); + } + + public static boolean load(File file, Class root) { + if (!file.exists()) { + return false; + } + YamlConfiguration yml = YamlConfiguration.loadConfiguration(file); + for (String key : yml.getKeys(true)) { + Object value = yml.get(key); + if (value instanceof MemorySection) { + continue; + } + set(key, value, root); + } + return true; + } + + /** + * Set all values in the file (load first to avoid overwriting) + * @param file + */ + public static void save(File file, Class root) { + try { + if (!file.exists()) { + file.getParentFile().mkdirs(); + file.createNewFile(); + } + PrintWriter writer = new PrintWriter(file); + Class clazz = root; + Object instance = root.newInstance(); + save(writer, clazz, instance, 0); + writer.close(); + } catch (Throwable e) { + e.printStackTrace(); + } + } + + /** + * Indicates that a field should be instantiated / created + */ + @Retention(RetentionPolicy.RUNTIME) + @Target({ElementType.FIELD}) + public @interface Create {} + + /** + * Indicates that a field cannot be modified + */ + @Retention(RetentionPolicy.RUNTIME) + @Target({ElementType.FIELD}) + public @interface Final {} + + /** + * Creates a comment + */ + @Retention(RetentionPolicy.RUNTIME) + @Target({ElementType.FIELD,ElementType.TYPE}) + public @interface Comment { + String[] value(); + } + + /** + * The names of any default blocks + */ + @Retention(RetentionPolicy.RUNTIME) + @Target({ElementType.FIELD,ElementType.TYPE}) + public @interface BlockName { + String[] value(); + } + + /** + * Any field or class with is not part of the config + */ + @Retention(RetentionPolicy.RUNTIME) + @Target({ElementType.FIELD,ElementType.TYPE}) + public @interface Ignore {} + + @Ignore // This is not part of the config + public static class ConfigBlock { + + private HashMap INSTANCES = new HashMap<>(); + + public T get(String key) { + return INSTANCES.get(key); + } + + public void put(String key, T value) { + INSTANCES.put(key, value); + } + + public Collection getInstances() { + return INSTANCES.values(); + } + + public Collection getSections() { + return INSTANCES.keySet(); + } + + private Map getRaw() { + return INSTANCES; + } + } + + /** + * Get the static fields in a section + * @param clazz + * @return + */ + public static Map getFields(Class clazz) { + HashMap map = new HashMap<>(); + for (Field field : clazz.getFields()) { + if (java.lang.reflect.Modifier.isStatic(field.getModifiers())) { + try { + map.put(toNodeName(field.getName()), field.get(null)); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + } + } + return map; + } + + private static String toYamlString(Object value, String spacing) { + if (value instanceof List) { + Collection listValue = (Collection) value; + if (listValue.isEmpty()) { + return "[]"; + } + StringBuilder m = new StringBuilder(); + for (Object obj : listValue) { + m.append(System.lineSeparator() + spacing + "- " + toYamlString(obj, spacing)); + } + return m.toString(); + } + if (value instanceof String) { + String stringValue = (String) value; + if (stringValue.isEmpty()) { + return "''"; + } + return "\"" + stringValue + "\""; + } + return value != null ? value.toString() : "null"; + } + + private static void save(PrintWriter writer, Class clazz, Object instance, int indent) { + try { + String CTRF = System.lineSeparator(); + String spacing = StringMan.repeat(" ", indent); + for (Field field : clazz.getFields()) { + if (field.getAnnotation(Ignore.class) != null) { + continue; + } + Comment comment = field.getAnnotation(Comment.class); + if (comment != null) { + for (String commentLine : comment.value()) { + writer.write(spacing + "# " + commentLine + CTRF); + } + } + Create create = field.getAnnotation(Create.class); + if (create != null) { + Object value = field.get(instance); + if (value == null && field.getType() != ConfigBlock.class) { + setAccessible(field); + Class[] classes = clazz.getDeclaredClasses(); + for (Class current : classes) { + if (StringMan.isEqual(current.getSimpleName(), field.getName())) { + field.set(instance, current.newInstance()); + break; + } + } + } + continue; + } else { + writer.write(spacing + toNodeName(field.getName() + ": ") + toYamlString(field.get(instance), spacing) + CTRF); + } + } + for (Class current : clazz.getClasses()) { + if (current.isInterface() || current.getAnnotation(Ignore.class) != null) { + continue; + } + if (indent == 0) { + writer.write(CTRF); + } + Comment comment = current.getAnnotation(Comment.class); + if (comment != null) { + for (String commentLine : comment.value()) { + writer.write(spacing + "# " + commentLine + CTRF); + } + } + writer.write(spacing + toNodeName(current.getSimpleName()) + ":" + CTRF); + BlockName blockNames = current.getAnnotation(BlockName.class); + if (blockNames != null) { + Field instanceField = clazz.getDeclaredField(toFieldName(current.getSimpleName())); + setAccessible(instanceField); + ConfigBlock value = (ConfigBlock) instanceField.get(instance); + if (value == null) { + value = new ConfigBlock(); + instanceField.set(instance, value); + for (String blockName : blockNames.value()) { + value.put(blockName, current.newInstance()); + } + } + // Save each instance + for (Map.Entry entry: ((Map) value.getRaw()).entrySet()) { + String key = entry.getKey(); + writer.write(spacing + " " + toNodeName(key) + ":" + CTRF); + save(writer, current, entry.getValue(), indent + 4); + } + continue; + } else { + save(writer, current, current.newInstance(), indent + 2); + } + } + } catch (Throwable e) { + e.printStackTrace(); + } + } + + /** + * Get the field for a specific config node + * @param split the node (split by period) + * @return + */ + private static Field getField(String[] split, Class root) { + Object instance = getInstance(split, root); + if (instance == null) { + return null; + } + return getField(split, instance); + } + + /** + * Get the field for a specific config node and instance
+ * Note: As expiry can have multiple blocks there will be multiple instances + * @param split the node (split by period) + * @param instance the instance + * @return + */ + private static Field getField(String[] split, Object instance) { + try { + Field field = instance.getClass().getField(toFieldName(split[split.length - 1])); + setAccessible(field); + return field; + } catch (Throwable e) { + Fawe.debug("Invalid config field: " + StringMan.join(split, ".") + " for " + toNodeName(instance.getClass().getSimpleName())); + return null; + } + } + + /** + * Get the instance for a specific config node + * @param split the node (split by period) + * @return The instance or null + */ + private static Object getInstance(String[] split, Class root) { + try { + Class clazz = root == null ? MethodHandles.lookup().lookupClass() : root; + Object instance = clazz.newInstance(); + while (split.length > 0) { + switch (split.length) { + case 1: + return instance; + default: + Class found = null; + Class[] classes = clazz.getDeclaredClasses(); + for (Class current : classes) { + if (StringMan.isEqual(current.getSimpleName(), toFieldName(split[0]))) { + found = current; + break; + } + } + try { + Field instanceField = clazz.getDeclaredField(toFieldName(split[0])); + setAccessible(instanceField); + if (instanceField.getType() != ConfigBlock.class) { + Object value = instanceField.get(instance); + if (value == null) { + value = found.newInstance(); + instanceField.set(instance, value); + } + clazz = found; + instance = value; + split = Arrays.copyOfRange(split, 1, split.length); + continue; + } + ConfigBlock value = (ConfigBlock) instanceField.get(instance); + if (value == null) { + value = new ConfigBlock(); + instanceField.set(instance, value); + } + instance = value.get(split[1]); + if (instance == null) { + instance = found.newInstance(); + value.put(split[1], instance); + } + clazz = found; + split = Arrays.copyOfRange(split, 2, split.length); + continue; + } catch (NoSuchFieldException ignore) {} + if (found != null) { + split = Arrays.copyOfRange(split, 1, split.length); + clazz = found; + instance = clazz.newInstance(); + continue; + } + return null; + } + } + } catch (Throwable e) { + e.printStackTrace(); + } + return null; + } + + /** + * Translate a node to a java field name + * @param node + * @return + */ + private static String toFieldName(String node) { + return node.toUpperCase().replaceAll("-","_"); + } + + /** + * Translate a field to a config node + * @param field + * @return + */ + private static String toNodeName(String field) { + return field.toLowerCase().replace("_","-"); + } + + /** + * Set some field to be accesible + * @param field + * @throws NoSuchFieldException + * @throws IllegalAccessException + */ + private static void setAccessible(Field field) throws NoSuchFieldException, IllegalAccessException { + field.setAccessible(true); + Field modifiersField = Field.class.getDeclaredField("modifiers"); + modifiersField.setAccessible(true); + modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL); + } +} diff --git a/core/src/main/java/com/boydti/fawe/object/FawePlayer.java b/core/src/main/java/com/boydti/fawe/object/FawePlayer.java index 237d18c3..6fa5a899 100644 --- a/core/src/main/java/com/boydti/fawe/object/FawePlayer.java +++ b/core/src/main/java/com/boydti/fawe/object/FawePlayer.java @@ -65,7 +65,8 @@ public abstract class FawePlayer { Field fieldBasePlayer = actor.getClass().getDeclaredField("basePlayer"); fieldBasePlayer.setAccessible(true); Player player = (Player) fieldBasePlayer.get(actor); - return wrap(player); + FawePlayer result = wrap(player); + return (FawePlayer) (result == null ? wrap(player.getName()) : result); } catch (Throwable e) { MainUtil.handleError(e); return Fawe.imp().wrap(actor.getName()); diff --git a/forge1710/src/main/java/com/boydti/fawe/forge/FaweForge.java b/forge1710/src/main/java/com/boydti/fawe/forge/FaweForge.java index 2c418c70..588c8de4 100644 --- a/forge1710/src/main/java/com/boydti/fawe/forge/FaweForge.java +++ b/forge1710/src/main/java/com/boydti/fawe/forge/FaweForge.java @@ -7,8 +7,8 @@ import com.boydti.fawe.forge.v0.ForgeQueue_All; import com.boydti.fawe.object.EditSessionWrapper; import com.boydti.fawe.object.FaweCommand; import com.boydti.fawe.object.FawePlayer; -import com.boydti.fawe.regions.FaweMaskManager; import com.boydti.fawe.object.FaweQueue; +import com.boydti.fawe.regions.FaweMaskManager; import com.boydti.fawe.util.MainUtil; import com.boydti.fawe.util.TaskManager; import com.boydti.fawe.wrappers.WorldWrapper; @@ -19,7 +19,6 @@ import java.io.File; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Collection; -import java.util.List; import java.util.UUID; import javax.management.InstanceAlreadyExistsException; import net.minecraft.command.ServerCommandManager; @@ -72,8 +71,7 @@ public class FaweForge implements IFawe { EntityPlayerMP player = null; if (obj instanceof String) { MinecraftServer server = MinecraftServer.getServer(); - List list = server.getConfigurationManager().getPlayerList((String) obj); - player = list.size() == 1 ? list.get(0) : null; + player = server.getConfigurationManager().func_152612_a((String) obj); } else if (obj instanceof EntityPlayerMP) { player = (EntityPlayerMP) obj; } diff --git a/forge1710/src/main/java/com/boydti/fawe/forge/v0/ForgeQueue_All.java b/forge1710/src/main/java/com/boydti/fawe/forge/v0/ForgeQueue_All.java index db85f870..34d283fe 100644 --- a/forge1710/src/main/java/com/boydti/fawe/forge/v0/ForgeQueue_All.java +++ b/forge1710/src/main/java/com/boydti/fawe/forge/v0/ForgeQueue_All.java @@ -441,9 +441,9 @@ public class ForgeQueue_All extends NMSMappedFaweQueue 0) { + ExtendedBlockStorage section = sections[y >> 4]; + if (section != null) { + section.setExtSkylightValue(x, y & 15, z, l); + } + } + --y; + } while (y > 0 && l > 0); + } } } } - nmsChunk.generateSkylightMap(); if (bc.getTotalRelight() == 0 && mode == RelightMode.MINIMAL) { return true; } - net.minecraft.world.World nmsWorld = nmsChunk.worldObj; - int X = fc.getX() << 4; int Z = fc.getZ() << 4; diff --git a/forge189/src/main/java/com/boydti/fawe/forge/v0/ForgeQueue_All.java b/forge189/src/main/java/com/boydti/fawe/forge/v0/ForgeQueue_All.java index 6e7af89a..cfbf1b7c 100644 --- a/forge189/src/main/java/com/boydti/fawe/forge/v0/ForgeQueue_All.java +++ b/forge189/src/main/java/com/boydti/fawe/forge/v0/ForgeQueue_All.java @@ -199,22 +199,50 @@ public class ForgeQueue_All extends NMSMappedFaweQueue 0) { + ExtendedBlockStorage section = sections[y >> 4]; + if (section != null) { + section.setExtSkylightValue(x, y & 15, z, l); + } + } + --y; + } while (y > 0 && l > 0); + } } } } - nmsChunk.generateSkylightMap(); if (bc.getTotalRelight() == 0 && mode == RelightMode.MINIMAL) { return true; } - net.minecraft.world.World nmsWorld = nmsChunk.getWorld(); - int X = fc.getX() << 4; int Z = fc.getZ() << 4;