Mirror von
https://github.com/IntellectualSites/FastAsyncWorldEdit.git
synchronisiert 2024-11-07 12:00:07 +01:00
chunk sending / cfi
Dieser Commit ist enthalten in:
Ursprung
1b28dcda40
Commit
8356004ec9
@ -20,6 +20,7 @@ repositories {
|
||||
maven { url = uri("https://repo.destroystokyo.com/repository/maven-public//") }
|
||||
maven { url = uri("http://repo.dmulloy2.net/content/groups/public/") }
|
||||
maven { url = uri("http://ci.ender.zone/plugin/repository/everything/") }
|
||||
maven { url = uri("https://repo.inventivetalent.org/content/groups/public/")}
|
||||
}
|
||||
|
||||
configurations.all {
|
||||
@ -49,6 +50,9 @@ dependencies {
|
||||
exclude("com.sk89q.worldedit.worldedit-libs", "bukkit")
|
||||
exclude("com.sk89q.worldedit.worldedit-libs", "core")
|
||||
}
|
||||
"implementation"("org.inventivetalent:mapmanager:1.7.3-SNAPSHOT") { isTransitive = false }
|
||||
"implementation"("org.inventivetalent:mapmanager:1.7.3-SNAPSHOT") { isTransitive = false }
|
||||
|
||||
"implementation"("com.massivecraft:factions:2.8.0") { isTransitive = false }
|
||||
"implementation"("com.drtshock:factions:1.6.9.5") { isTransitive = false }
|
||||
"implementation"("com.github.TechFortress:GriefPrevention:16.12.0") { isTransitive = false }
|
||||
|
@ -3,6 +3,8 @@ package com.boydti.fawe.bukkit;
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.IFawe;
|
||||
import com.boydti.fawe.beta.implementation.QueueHandler;
|
||||
import com.boydti.fawe.beta.preloader.AsyncPreloader;
|
||||
import com.boydti.fawe.beta.preloader.Preloader;
|
||||
import com.boydti.fawe.bukkit.adapter.BukkitQueueHandler;
|
||||
import com.boydti.fawe.bukkit.listener.BrushListener;
|
||||
import com.boydti.fawe.bukkit.listener.BukkitImageListener;
|
||||
@ -55,14 +57,14 @@ import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
public class FaweBukkit implements IFawe, Listener {
|
||||
|
||||
// private final WorldEditPlugin plugin;
|
||||
private final Plugin plugin;
|
||||
private VaultUtil vault;
|
||||
private ItemUtil itemUtil;
|
||||
|
||||
private boolean listeningImages;
|
||||
private BukkitImageListener imageListener;
|
||||
//private CFIPacketListener packetListener;
|
||||
|
||||
public static boolean PAPER;
|
||||
|
||||
public VaultUtil getVault() {
|
||||
return this.vault;
|
||||
@ -70,6 +72,13 @@ public class FaweBukkit implements IFawe, Listener {
|
||||
|
||||
public FaweBukkit(Plugin plugin) {
|
||||
this.plugin = plugin;
|
||||
try {
|
||||
Class.forName("com.destroystokyo.paper.Namespaced");
|
||||
PAPER = true;
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
// TODO no paper
|
||||
}
|
||||
try {
|
||||
Settings.IMP.TICK_LIMITER.ENABLED = !Bukkit.hasWhitelist();
|
||||
Fawe.set(this);
|
||||
@ -398,4 +407,12 @@ public class FaweBukkit implements IFawe, Listener {
|
||||
return null;
|
||||
// return ((BlocksHubBukkit) blocksHubPlugin).getApi();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Preloader getPreloader() {
|
||||
if (PAPER) {
|
||||
return new AsyncPreloader();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ package com.boydti.fawe.bukkit.adapter.mc1_14;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.FaweCache;
|
||||
import com.boydti.fawe.bukkit.FaweBukkit;
|
||||
import com.boydti.fawe.bukkit.adapter.DelegateLock;
|
||||
import com.boydti.fawe.config.Settings;
|
||||
import com.boydti.fawe.object.collection.BitArray4096;
|
||||
@ -21,6 +22,7 @@ import net.minecraft.server.v1_14_R1.DataPaletteBlock;
|
||||
import net.minecraft.server.v1_14_R1.DataPaletteLinear;
|
||||
import net.minecraft.server.v1_14_R1.GameProfileSerializer;
|
||||
import net.minecraft.server.v1_14_R1.IBlockData;
|
||||
import net.minecraft.server.v1_14_R1.PacketPlayOutMapChunk;
|
||||
import net.minecraft.server.v1_14_R1.PlayerChunk;
|
||||
import net.minecraft.server.v1_14_R1.PlayerChunkMap;
|
||||
import org.bukkit.craftbukkit.v1_14_R1.CraftChunk;
|
||||
@ -133,8 +135,6 @@ public class BukkitAdapter_1_14 {
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean PAPER = true;
|
||||
|
||||
public static Chunk ensureLoaded(net.minecraft.server.v1_14_R1.World nmsWorld, int X, int Z) {
|
||||
Chunk nmsChunk = nmsWorld.getChunkIfLoaded(X, Z);
|
||||
if (nmsChunk != null) {
|
||||
@ -143,7 +143,7 @@ public class BukkitAdapter_1_14 {
|
||||
if (Fawe.isMainThread()) {
|
||||
return nmsWorld.getChunkAt(X, Z);
|
||||
}
|
||||
if (PAPER) {
|
||||
if (FaweBukkit.PAPER) {
|
||||
CraftWorld craftWorld = nmsWorld.getWorld();
|
||||
CompletableFuture<org.bukkit.Chunk> future = craftWorld.getChunkAtAsync(X, Z, true);
|
||||
try {
|
||||
@ -154,8 +154,7 @@ public class BukkitAdapter_1_14 {
|
||||
} catch (ExecutionException e) {
|
||||
e.printStackTrace();
|
||||
} catch (Throwable e) {
|
||||
System.out.println("Error, cannot load chunk async (paper not installed?)");
|
||||
PAPER = false;
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
// TODO optimize
|
||||
|
@ -19,6 +19,7 @@
|
||||
|
||||
package com.boydti.fawe.bukkit.adapter.mc1_14;
|
||||
|
||||
import com.bekvon.bukkit.residence.commands.material;
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import com.google.common.cache.CacheLoader;
|
||||
@ -132,6 +133,7 @@ import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.OptionalInt;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.function.Supplier;
|
||||
@ -590,6 +592,13 @@ public final class Spigot_v1_14_R4 extends CachedBukkitAdapter implements Bukkit
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public OptionalInt getInternalBlockStateId(BlockState state) {
|
||||
BlockMaterial_1_14 material = (BlockMaterial_1_14) state.getMaterial();
|
||||
IBlockData mcState = material.getCraftBlockData().getState();
|
||||
return OptionalInt.of(Block.REGISTRY_ID.getId(mcState));
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState adapt(BlockData blockData) {
|
||||
CraftBlockData cbd = ((CraftBlockData) blockData);
|
||||
|
@ -1,111 +0,0 @@
|
||||
package com.boydti.fawe.bukkit.chat;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import org.apache.commons.lang.Validate;
|
||||
|
||||
/**
|
||||
* Represents a wrapper around an array class of an arbitrary reference type,
|
||||
* which properly implements "value" hash code and equality functions.
|
||||
* <p>
|
||||
* This class is intended for use as a key to a map.
|
||||
* </p>
|
||||
*
|
||||
* @param <E> The type of elements in the array.
|
||||
* @author Glen Husman
|
||||
* @see Arrays
|
||||
*/
|
||||
public final class ArrayWrapper<E> {
|
||||
|
||||
/**
|
||||
* Creates an array wrapper with some elements.
|
||||
*
|
||||
* @param elements The elements of the array.
|
||||
*/
|
||||
@SafeVarargs
|
||||
public ArrayWrapper(E... elements) {
|
||||
setArray(elements);
|
||||
}
|
||||
|
||||
private E[] _array;
|
||||
|
||||
/**
|
||||
* Retrieves a reference to the wrapped array instance.
|
||||
*
|
||||
* @return The array wrapped by this instance.
|
||||
*/
|
||||
public E[] getArray() {
|
||||
return _array;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set this wrapper to wrap a new array instance.
|
||||
*
|
||||
* @param array The new wrapped array.
|
||||
*/
|
||||
public void setArray(E[] array) {
|
||||
Validate.notNull(array, "The array must not be null.");
|
||||
_array = array;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if this object has a value equivalent to another object.
|
||||
*
|
||||
* @see Arrays#equals(Object[], Object[])
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (!(other instanceof ArrayWrapper)) {
|
||||
return false;
|
||||
}
|
||||
return Arrays.equals(_array, ((ArrayWrapper) other)._array);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the hash code represented by this objects value.
|
||||
*
|
||||
* @return This object's hash code.
|
||||
* @see Arrays#hashCode(Object[])
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Arrays.hashCode(_array);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts an iterable element collection to an array of elements.
|
||||
* The iteration order of the specified object will be used as the array element order.
|
||||
*
|
||||
* @param list The iterable of objects which will be converted to an array.
|
||||
* @param c The type of the elements of the array.
|
||||
* @return An array of elements in the specified iterable.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> T[] toArray(Iterable<? extends T> list, Class<T> c) {
|
||||
int size = -1;
|
||||
if (list instanceof Collection<?>) {
|
||||
@SuppressWarnings("rawtypes")
|
||||
Collection coll = (Collection) list;
|
||||
size = coll.size();
|
||||
}
|
||||
|
||||
|
||||
if (size < 0) {
|
||||
size = 0;
|
||||
// Ugly hack: Count it ourselves
|
||||
for (@SuppressWarnings("unused") T element : list) {
|
||||
size++;
|
||||
}
|
||||
}
|
||||
|
||||
T[] result = (T[]) Array.newInstance(c, size);
|
||||
int i = 0;
|
||||
for (T element : list) { // Assumes iteration order is consistent
|
||||
result[i++] = element; // Assign array element at index THEN increment counter
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
@ -1,18 +0,0 @@
|
||||
package com.boydti.fawe.bukkit.chat;
|
||||
|
||||
import com.google.gson.stream.JsonWriter;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Represents an object that can be serialized to a JSON writer instance.
|
||||
*/
|
||||
interface JsonRepresentedObject {
|
||||
|
||||
/**
|
||||
* Writes the JSON representation of this object to the specified writer.
|
||||
* @param writer The JSON writer which will receive the object.
|
||||
* @throws IOException If an error occurs writing to the stream.
|
||||
*/
|
||||
public void writeJson(JsonWriter writer) throws IOException;
|
||||
|
||||
}
|
@ -1,46 +0,0 @@
|
||||
package com.boydti.fawe.bukkit.chat;
|
||||
|
||||
import com.google.gson.stream.JsonWriter;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import org.bukkit.configuration.serialization.ConfigurationSerializable;
|
||||
|
||||
/**
|
||||
* Represents a JSON string value.
|
||||
* Writes by this object will not write name values nor begin/end objects in the JSON stream.
|
||||
* All writes merely write the represented string value.
|
||||
*/
|
||||
final class JsonString implements JsonRepresentedObject, ConfigurationSerializable {
|
||||
|
||||
private String _value;
|
||||
|
||||
public JsonString(CharSequence value) {
|
||||
_value = value == null ? null : value.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeJson(JsonWriter writer) throws IOException {
|
||||
writer.value(getValue());
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return _value;
|
||||
}
|
||||
|
||||
public Map<String, Object> serialize() {
|
||||
HashMap<String, Object> theSingleValue = new HashMap<>();
|
||||
theSingleValue.put("stringValue", _value);
|
||||
return theSingleValue;
|
||||
}
|
||||
|
||||
public static JsonString deserialize(Map<String, Object> map) {
|
||||
return new JsonString(map.get("stringValue").toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return _value;
|
||||
}
|
||||
|
||||
}
|
@ -1,201 +0,0 @@
|
||||
package com.boydti.fawe.bukkit.chat;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
/**
|
||||
* A class containing static utility methods and caches which are intended as reflective conveniences.
|
||||
* Unless otherwise noted, upon failure methods will return {@code null}.
|
||||
*/
|
||||
public final class Reflection {
|
||||
|
||||
/**
|
||||
* Stores loaded classes from the {@code net.minecraft.server} package.
|
||||
*/
|
||||
private static final Map<String, Class<?>> _loadedNMSClasses = new HashMap<>();
|
||||
/**
|
||||
* Stores loaded classes from the {@code org.bukkit.craftbukkit} package (and subpackages).
|
||||
*/
|
||||
private static final Map<String, Class<?>> _loadedOBCClasses = new HashMap<>();
|
||||
private static final Map<Class<?>, Map<String, Field>> _loadedFields = new HashMap<>();
|
||||
/**
|
||||
* Contains loaded methods in a cache.
|
||||
* The map maps [types to maps of [method names to maps of [parameter types to method instances]]].
|
||||
*/
|
||||
private static final Map<Class<?>, Map<String, Map<ArrayWrapper<Class<?>>, Method>>> _loadedMethods = new HashMap<>();
|
||||
private static String _versionString;
|
||||
|
||||
private Reflection() { }
|
||||
|
||||
/**
|
||||
* Gets the version string from the package name of the CraftBukkit server implementation.
|
||||
* This is needed to bypass the JAR package name changing on each update.
|
||||
*
|
||||
* @return The version string of the OBC and NMS packages, <em>including the trailing dot</em>.
|
||||
*/
|
||||
public synchronized static String getVersion() {
|
||||
if (_versionString == null) {
|
||||
String name = Bukkit.getServer().getClass().getPackage().getName();
|
||||
_versionString = name.substring(name.lastIndexOf('.') + 1) + ".";
|
||||
}
|
||||
|
||||
return _versionString;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a {@link Class} object representing a type contained within the {@code net.minecraft.server} versioned package.
|
||||
* The class instances returned by this method are cached, such that no lookup will be done twice (unless multiple threads are accessing this method simultaneously).
|
||||
*
|
||||
* @param className The name of the class, excluding the package, within NMS.
|
||||
* @return The class instance representing the specified NMS class, or {@code null} if it could not be loaded.
|
||||
*/
|
||||
public synchronized static Class<?> getNMSClass(String className) {
|
||||
if (_loadedNMSClasses.containsKey(className)) {
|
||||
return _loadedNMSClasses.get(className);
|
||||
}
|
||||
|
||||
String fullName = "net.minecraft.server." + getVersion() + className;
|
||||
Class<?> clazz;
|
||||
try {
|
||||
clazz = Class.forName(fullName);
|
||||
} catch (ClassNotFoundException e) {
|
||||
_loadedNMSClasses.put(className, null);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
_loadedNMSClasses.put(className, clazz);
|
||||
return clazz;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a {@link Class} object representing a type contained within the {@code org.bukkit.craftbukkit} versioned package.
|
||||
* The class instances returned by this method are cached, such that no lookup will be done twice (unless multiple threads are accessing this method simultaneously).
|
||||
*
|
||||
* @param className The name of the class, excluding the package, within OBC. This name may contain a subpackage name, such as {@code inventory.CraftItemStack}.
|
||||
* @return The class instance representing the specified OBC class, or {@code null} if it could not be loaded.
|
||||
*/
|
||||
public synchronized static Class<?> getOBCClass(String className) {
|
||||
if (_loadedOBCClasses.containsKey(className)) {
|
||||
return _loadedOBCClasses.get(className);
|
||||
}
|
||||
|
||||
String fullName = "org.bukkit.craftbukkit." + getVersion() + className;
|
||||
Class<?> clazz;
|
||||
try {
|
||||
clazz = Class.forName(fullName);
|
||||
} catch (ClassNotFoundException e) {
|
||||
_loadedOBCClasses.put(className, null);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
_loadedOBCClasses.put(className, clazz);
|
||||
return clazz;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to get the NMS handle of a CraftBukkit object.
|
||||
* <p>
|
||||
* The only match currently attempted by this method is a retrieval by using a parameterless {@code getHandle()} method implemented by the runtime type of the specified object.
|
||||
* </p>
|
||||
*
|
||||
* @param obj The object for which to retrieve an NMS handle.
|
||||
* @return The NMS handle of the specified object, or {@code null} if it could not be retrieved using {@code getHandle()}.
|
||||
*/
|
||||
public synchronized static Object getHandle(Object obj) throws InvocationTargetException, IllegalAccessException, IllegalArgumentException {
|
||||
return getMethod(obj.getClass(), "getHandle").invoke(obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a {@link Field} instance declared by the specified class with the specified name.
|
||||
* Java access modifiers are ignored during this retrieval. No guarantee is made as to whether the field
|
||||
* returned will be an instance or static field.
|
||||
* <p>
|
||||
* A global caching mechanism within this class is used to store fields. Combined with synchronization, this guarantees that
|
||||
* no field will be reflectively looked up twice.
|
||||
* </p>
|
||||
* <p>
|
||||
* If a field is deemed suitable for return, {@link Field#setAccessible(boolean) setAccessible} will be invoked with an argument of {@code true} before it is returned.
|
||||
* This ensures that callers do not have to check or worry about Java access modifiers when dealing with the returned instance.
|
||||
* </p>
|
||||
*
|
||||
* @param clazz The class which contains the field to retrieve.
|
||||
* @param name The declared name of the field in the class.
|
||||
* @return A field object with the specified name declared by the specified class.
|
||||
* @see Class#getDeclaredField(String)
|
||||
*/
|
||||
public synchronized static Field getField(Class<?> clazz, String name) {
|
||||
Map<String, Field> loaded;
|
||||
if (!_loadedFields.containsKey(clazz)) {
|
||||
loaded = new HashMap<>();
|
||||
_loadedFields.put(clazz, loaded);
|
||||
} else {
|
||||
loaded = _loadedFields.get(clazz);
|
||||
}
|
||||
if (loaded.containsKey(name)) {
|
||||
// If the field is loaded (or cached as not existing), return the relevant value, which might be null
|
||||
return loaded.get(name);
|
||||
}
|
||||
try {
|
||||
Field field = clazz.getDeclaredField(name);
|
||||
field.setAccessible(true);
|
||||
loaded.put(name, field);
|
||||
return field;
|
||||
} catch (NoSuchFieldException | SecurityException e) {
|
||||
// Error loading
|
||||
e.printStackTrace();
|
||||
// Cache field as not existing
|
||||
loaded.put(name, null);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a {@link Method} instance declared by the specified class with the specified name and argument types.
|
||||
* Java access modifiers are ignored during this retrieval. No guarantee is made as to whether the field
|
||||
* returned will be an instance or static field.
|
||||
* <p>
|
||||
* A global caching mechanism within this class is used to store method. Combined with synchronization, this guarantees that
|
||||
* no method will be reflectively looked up twice.
|
||||
* <p>
|
||||
* If a method is deemed suitable for return, {@link Method#setAccessible(boolean) setAccessible} will be invoked with an argument of {@code true} before it is returned.
|
||||
* This ensures that callers do not have to check or worry about Java access modifiers when dealing with the returned instance.
|
||||
* <p>
|
||||
* This method does <em>not</em> search superclasses of the specified type for methods with the specified signature.
|
||||
* Callers wishing this behavior should use {@link Class#getDeclaredMethod(String, Class...)}.
|
||||
*
|
||||
* @param clazz The class which contains the method to retrieve.
|
||||
* @param name The declared name of the method in the class.
|
||||
* @param args The formal argument types of the method.
|
||||
* @return A method object with the specified name declared by the specified class.
|
||||
*/
|
||||
public synchronized static Method getMethod(Class<?> clazz, String name, Class<?>... args) {
|
||||
if (!_loadedMethods.containsKey(clazz)) {
|
||||
_loadedMethods.put(clazz, new HashMap<>());
|
||||
}
|
||||
|
||||
Map<String, Map<ArrayWrapper<Class<?>>, Method>> loadedMethodNames = _loadedMethods.get(clazz);
|
||||
if (!loadedMethodNames.containsKey(name)) {
|
||||
loadedMethodNames.put(name, new HashMap<>());
|
||||
}
|
||||
|
||||
Map<ArrayWrapper<Class<?>>, Method> loadedSignatures = loadedMethodNames.get(name);
|
||||
ArrayWrapper<Class<?>> wrappedArg = new ArrayWrapper<>(args);
|
||||
if (loadedSignatures.containsKey(wrappedArg)) {
|
||||
return loadedSignatures.get(wrappedArg);
|
||||
}
|
||||
|
||||
for (Method m : clazz.getMethods()) {
|
||||
if (m.getName().equals(name) && Arrays.equals(args, m.getParameterTypes())) {
|
||||
m.setAccessible(true);
|
||||
loadedSignatures.put(wrappedArg, m);
|
||||
return m;
|
||||
}
|
||||
}
|
||||
loadedSignatures.put(wrappedArg, null);
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
@ -1,4 +0,0 @@
|
||||
package com.boydti.fawe.bukkit.listener;
|
||||
|
||||
public class ChunkCache {
|
||||
}
|
@ -0,0 +1,196 @@
|
||||
package com.boydti.fawe.bukkit.preloader;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.sk89q.worldedit.bukkit.BukkitAdapter;
|
||||
import com.sk89q.worldedit.math.BlockVector2;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
import org.bukkit.Server;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.generator.ChunkGenerator;
|
||||
import org.bukkit.plugin.PluginBase;
|
||||
import org.bukkit.plugin.PluginDescriptionFile;
|
||||
import org.bukkit.plugin.PluginLoader;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.lang.ref.PhantomReference;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class PluginPreloader extends PluginBase {
|
||||
private World world;
|
||||
private Set<BlockVector2> loaded;
|
||||
private int index;
|
||||
private AtomicBoolean invalidator;
|
||||
private final Object invalidatorLock;
|
||||
|
||||
public PluginPreloader() {
|
||||
invalidator = new AtomicBoolean();
|
||||
invalidatorLock = new Object();
|
||||
}
|
||||
|
||||
public AtomicBoolean invalidate() {
|
||||
synchronized (invalidatorLock) {
|
||||
invalidator.set(false);
|
||||
return invalidator = new AtomicBoolean(true);
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized void unload() {
|
||||
World oldWorld = world;
|
||||
if (oldWorld != null) {
|
||||
Set<BlockVector2> toUnload = loaded;
|
||||
if (loaded != null && index > 0) {
|
||||
Iterator<BlockVector2> iter = toUnload.iterator();
|
||||
Fawe.get().getQueueHandler().sync(() -> {
|
||||
for (int i = 0; i < index && iter.hasNext(); i++) {
|
||||
BlockVector2 chunk = iter.next();
|
||||
world.removePluginChunkTicket(chunk.getX(), chunk.getZ(), this);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
this.world = null;
|
||||
this.loaded = null;
|
||||
this.index = 0;
|
||||
}
|
||||
|
||||
public void update(Region region) {
|
||||
AtomicBoolean invalidator = invalidate();
|
||||
synchronized (this) {
|
||||
com.sk89q.worldedit.world.World weWorld = region.getWorld();
|
||||
if (weWorld == null) {
|
||||
return;
|
||||
}
|
||||
unload();
|
||||
index = 0;
|
||||
world = BukkitAdapter.adapt(weWorld);
|
||||
loaded = region.getChunks();
|
||||
Iterator<BlockVector2> iter = loaded.iterator();
|
||||
|
||||
if (!invalidator.get()) return;
|
||||
Fawe.get().getQueueHandler().syncWhenFree(() -> {
|
||||
for (; iter.hasNext() && invalidator.get();index++) {
|
||||
BlockVector2 chunk = iter.next();
|
||||
if (!world.isChunkLoaded(chunk.getX(), chunk.getZ())) {
|
||||
world.addPluginChunkTicket(chunk.getX(), chunk.getZ(), this);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
invalidate();
|
||||
unload();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull File getDataFolder() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull PluginDescriptionFile getDescription() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull FileConfiguration getConfig() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable InputStream getResource(@NotNull String filename) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveConfig() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveDefaultConfig() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveResource(@NotNull String resourcePath, boolean replace) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reloadConfig() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull PluginLoader getPluginLoader() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Server getServer() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoad() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNaggable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNaggable(boolean canNag) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable ChunkGenerator getDefaultWorldGenerator(@NotNull String worldName, @Nullable String id) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Logger getLogger() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, String[] args) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias, String[] args) {
|
||||
return null;
|
||||
}
|
||||
}
|
@ -19,173 +19,173 @@ import org.bukkit.entity.ItemFrame;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.PlayerInventory;
|
||||
//import org.inventivetalent.mapmanager.MapManagerPlugin;
|
||||
//import org.inventivetalent.mapmanager.controller.MapController;
|
||||
//import org.inventivetalent.mapmanager.controller.MultiMapController;
|
||||
//import org.inventivetalent.mapmanager.manager.MapManager;
|
||||
//import org.inventivetalent.mapmanager.wrapper.MapWrapper;
|
||||
import org.inventivetalent.mapmanager.MapManagerPlugin;
|
||||
import org.inventivetalent.mapmanager.controller.MapController;
|
||||
import org.inventivetalent.mapmanager.controller.MultiMapController;
|
||||
import org.inventivetalent.mapmanager.manager.MapManager;
|
||||
import org.inventivetalent.mapmanager.wrapper.MapWrapper;
|
||||
|
||||
public class BukkitImageViewer implements ImageViewer {
|
||||
// private final MapManager mapManager;
|
||||
// private final Player player;
|
||||
// private BufferedImage last;
|
||||
private final MapManager mapManager;
|
||||
private final Player player;
|
||||
private BufferedImage last;
|
||||
private ItemFrame[][] frames;
|
||||
// private boolean reverse;
|
||||
private boolean reverse;
|
||||
|
||||
public BukkitImageViewer(Player player) {
|
||||
// mapManager = ((MapManagerPlugin) Bukkit.getPluginManager().getPlugin("MapManager")).getMapManager();
|
||||
// this.player = player;
|
||||
mapManager = ((MapManagerPlugin) Bukkit.getPluginManager().getPlugin("MapManager")).getMapManager();
|
||||
this.player = player;
|
||||
}
|
||||
//
|
||||
|
||||
public void selectFrame(ItemFrame start) {
|
||||
// Location pos1 = start.getLocation().clone();
|
||||
// Location pos2 = start.getLocation().clone();
|
||||
//
|
||||
// BlockFace facing = start.getFacing();
|
||||
// int planeX = facing.getModX() == 0 ? 1 : 0;
|
||||
// int planeY = facing.getModY() == 0 ? 1 : 0;
|
||||
// int planeZ = facing.getModZ() == 0 ? 1 : 0;
|
||||
//
|
||||
// ItemFrame[][] res = find(pos1, pos2, facing);
|
||||
// Location tmp;
|
||||
// while (true) {
|
||||
// if (res != null) {
|
||||
// frames = res;
|
||||
// }
|
||||
// tmp = pos1.clone().subtract(planeX, planeY, planeZ);
|
||||
// if ((res = find(tmp, pos2, facing)) != null) {
|
||||
// pos1 = tmp;
|
||||
// continue;
|
||||
// }
|
||||
// tmp = pos2.clone().add(planeX, planeY, planeZ);
|
||||
// if ((res = find(pos1, tmp, facing)) != null) {
|
||||
// pos2 = tmp;
|
||||
// continue;
|
||||
// }
|
||||
// tmp = pos1.clone().subtract(planeX, 0, planeZ);
|
||||
// if ((res = find(tmp, pos2, facing)) != null) {
|
||||
// pos1 = tmp;
|
||||
// continue;
|
||||
// }
|
||||
// tmp = pos2.clone().add(planeX, 0, planeZ);
|
||||
// if ((res = find(pos1, tmp, facing)) != null) {
|
||||
// pos2 = tmp;
|
||||
// continue;
|
||||
// }
|
||||
// tmp = pos1.clone().subtract(0, 1, 0);
|
||||
// if ((res = find(tmp, pos2, facing)) != null) {
|
||||
// pos1 = tmp;
|
||||
// continue;
|
||||
// }
|
||||
// tmp = pos2.clone().add(0, 1, 0);
|
||||
// if ((res = find(pos1, tmp, facing)) != null) {
|
||||
// pos2 = tmp;
|
||||
// continue;
|
||||
// }
|
||||
// break;
|
||||
// }
|
||||
Location pos1 = start.getLocation().clone();
|
||||
Location pos2 = start.getLocation().clone();
|
||||
|
||||
BlockFace facing = start.getFacing();
|
||||
int planeX = facing.getModX() == 0 ? 1 : 0;
|
||||
int planeY = facing.getModY() == 0 ? 1 : 0;
|
||||
int planeZ = facing.getModZ() == 0 ? 1 : 0;
|
||||
|
||||
ItemFrame[][] res = find(pos1, pos2, facing);
|
||||
Location tmp;
|
||||
while (true) {
|
||||
if (res != null) {
|
||||
frames = res;
|
||||
}
|
||||
tmp = pos1.clone().subtract(planeX, planeY, planeZ);
|
||||
if ((res = find(tmp, pos2, facing)) != null) {
|
||||
pos1 = tmp;
|
||||
continue;
|
||||
}
|
||||
tmp = pos2.clone().add(planeX, planeY, planeZ);
|
||||
if ((res = find(pos1, tmp, facing)) != null) {
|
||||
pos2 = tmp;
|
||||
continue;
|
||||
}
|
||||
tmp = pos1.clone().subtract(planeX, 0, planeZ);
|
||||
if ((res = find(tmp, pos2, facing)) != null) {
|
||||
pos1 = tmp;
|
||||
continue;
|
||||
}
|
||||
tmp = pos2.clone().add(planeX, 0, planeZ);
|
||||
if ((res = find(pos1, tmp, facing)) != null) {
|
||||
pos2 = tmp;
|
||||
continue;
|
||||
}
|
||||
tmp = pos1.clone().subtract(0, 1, 0);
|
||||
if ((res = find(tmp, pos2, facing)) != null) {
|
||||
pos1 = tmp;
|
||||
continue;
|
||||
}
|
||||
tmp = pos2.clone().add(0, 1, 0);
|
||||
if ((res = find(pos1, tmp, facing)) != null) {
|
||||
pos2 = tmp;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
//
|
||||
|
||||
public ItemFrame[][] getItemFrames() {
|
||||
return frames;
|
||||
}
|
||||
//
|
||||
// private ItemFrame[][] find(Location pos1, Location pos2, BlockFace facing) {
|
||||
// try {
|
||||
// Location distance = pos2.clone().subtract(pos1).add(1, 1, 1);
|
||||
// int width = Math.max(distance.getBlockX(), distance.getBlockZ());
|
||||
// ItemFrame[][] frames = new ItemFrame[width][distance.getBlockY()];
|
||||
//
|
||||
// World world = pos1.getWorld();
|
||||
//
|
||||
// this.reverse = (facing == BlockFace.NORTH || facing == BlockFace.EAST);
|
||||
// int v = 0;
|
||||
// for (double y = pos1.getY(); y <= pos2.getY(); y++, v++) {
|
||||
// int h = 0;
|
||||
// for (double z = pos1.getZ(); z <= pos2.getZ(); z++) {
|
||||
// for (double x = pos1.getX(); x <= pos2.getX(); x++, h++) {
|
||||
// Location pos = new Location(world, x, y, z);
|
||||
// Collection<Entity> entities = world.getNearbyEntities(pos, 0.1, 0.1, 0.1);
|
||||
// boolean contains = false;
|
||||
// for (Entity ent : entities) {
|
||||
// if (ent instanceof ItemFrame && ((ItemFrame) ent).getFacing() == facing) {
|
||||
// ItemFrame itemFrame = (ItemFrame) ent;
|
||||
// itemFrame.setRotation(Rotation.NONE);
|
||||
// contains = true;
|
||||
// frames[reverse ? width - 1 - h : h][v] = (ItemFrame) ent;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// if (!contains) return null;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// return frames;
|
||||
// } catch (Throwable e) {
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
// return null;
|
||||
// }
|
||||
|
||||
private ItemFrame[][] find(Location pos1, Location pos2, BlockFace facing) {
|
||||
try {
|
||||
Location distance = pos2.clone().subtract(pos1).add(1, 1, 1);
|
||||
int width = Math.max(distance.getBlockX(), distance.getBlockZ());
|
||||
ItemFrame[][] frames = new ItemFrame[width][distance.getBlockY()];
|
||||
|
||||
World world = pos1.getWorld();
|
||||
|
||||
this.reverse = (facing == BlockFace.NORTH || facing == BlockFace.EAST);
|
||||
int v = 0;
|
||||
for (double y = pos1.getY(); y <= pos2.getY(); y++, v++) {
|
||||
int h = 0;
|
||||
for (double z = pos1.getZ(); z <= pos2.getZ(); z++) {
|
||||
for (double x = pos1.getX(); x <= pos2.getX(); x++, h++) {
|
||||
Location pos = new Location(world, x, y, z);
|
||||
Collection<Entity> entities = world.getNearbyEntities(pos, 0.1, 0.1, 0.1);
|
||||
boolean contains = false;
|
||||
for (Entity ent : entities) {
|
||||
if (ent instanceof ItemFrame && ((ItemFrame) ent).getFacing() == facing) {
|
||||
ItemFrame itemFrame = (ItemFrame) ent;
|
||||
itemFrame.setRotation(Rotation.NONE);
|
||||
contains = true;
|
||||
frames[reverse ? width - 1 - h : h][v] = (ItemFrame) ent;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!contains) return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
return frames;
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void view(Drawable drawable) {
|
||||
// view(null, drawable);
|
||||
view(null, drawable);
|
||||
}
|
||||
//
|
||||
// private void view(@Nullable BufferedImage image, @Nullable Drawable drawable) {
|
||||
// if (image == null && drawable == null) throw new IllegalArgumentException("An image or drawable must be provided. Both cannot be null");
|
||||
// boolean initializing = last == null;
|
||||
//
|
||||
// if (this.frames != null) {
|
||||
// if (image == null && drawable != null) image = drawable.draw();
|
||||
// last = image;
|
||||
// int width = frames.length;
|
||||
// int height = frames[0].length;
|
||||
// BufferedImage scaled = ImageUtil.getScaledInstance(image, 128 * width, 128 * height, RenderingHints.VALUE_INTERPOLATION_BILINEAR, false);
|
||||
// MapWrapper mapWrapper = mapManager.wrapMultiImage(scaled, width, height);
|
||||
// MultiMapController controller = (MultiMapController) mapWrapper.getController();
|
||||
// controller.addViewer(player);
|
||||
// controller.sendContent(player);
|
||||
// controller.showInFrames(player, frames, true);
|
||||
// } else {
|
||||
// int slot = getMapSlot(player);
|
||||
// if (slot == -1) {
|
||||
// if (initializing) {
|
||||
// player.getInventory().setItemInMainHand(new ItemStack(Material.MAP));
|
||||
// } else {
|
||||
// return;
|
||||
// }
|
||||
// } else if (player.getInventory().getHeldItemSlot() != slot) {
|
||||
// player.getInventory().setHeldItemSlot(slot);
|
||||
// }
|
||||
// if (image == null && drawable != null) image = drawable.draw();
|
||||
// last = image;
|
||||
// BufferedImage scaled = ImageUtil.getScaledInstance(image, 128, 128, RenderingHints.VALUE_INTERPOLATION_BILINEAR, false);
|
||||
// MapWrapper mapWrapper = mapManager.wrapImage(scaled);
|
||||
// MapController controller = mapWrapper.getController();
|
||||
// controller.addViewer(player);
|
||||
// controller.sendContent(player);
|
||||
// controller.showInHand(player, true);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// private int getMapSlot(Player player) {
|
||||
// PlayerInventory inventory = player.getInventory();
|
||||
// for (int i = 0; i < 9; i++) {
|
||||
// ItemStack item = inventory.getItem(i);
|
||||
// if (item != null && item.getType() == Material.MAP) {
|
||||
// return i;
|
||||
// }
|
||||
// }
|
||||
// return -1;
|
||||
// }
|
||||
//
|
||||
|
||||
private void view(@Nullable BufferedImage image, @Nullable Drawable drawable) {
|
||||
if (image == null && drawable == null) throw new IllegalArgumentException("An image or drawable must be provided. Both cannot be null");
|
||||
boolean initializing = last == null;
|
||||
|
||||
if (this.frames != null) {
|
||||
if (image == null && drawable != null) image = drawable.draw();
|
||||
last = image;
|
||||
int width = frames.length;
|
||||
int height = frames[0].length;
|
||||
BufferedImage scaled = ImageUtil.getScaledInstance(image, 128 * width, 128 * height, RenderingHints.VALUE_INTERPOLATION_BILINEAR, false);
|
||||
MapWrapper mapWrapper = mapManager.wrapMultiImage(scaled, width, height);
|
||||
MultiMapController controller = (MultiMapController) mapWrapper.getController();
|
||||
controller.addViewer(player);
|
||||
controller.sendContent(player);
|
||||
controller.showInFrames(player, frames, true);
|
||||
} else {
|
||||
int slot = getMapSlot(player);
|
||||
if (slot == -1) {
|
||||
if (initializing) {
|
||||
player.getInventory().setItemInMainHand(new ItemStack(Material.MAP));
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
} else if (player.getInventory().getHeldItemSlot() != slot) {
|
||||
player.getInventory().setHeldItemSlot(slot);
|
||||
}
|
||||
if (image == null && drawable != null) image = drawable.draw();
|
||||
last = image;
|
||||
BufferedImage scaled = ImageUtil.getScaledInstance(image, 128, 128, RenderingHints.VALUE_INTERPOLATION_BILINEAR, false);
|
||||
MapWrapper mapWrapper = mapManager.wrapImage(scaled);
|
||||
MapController controller = mapWrapper.getController();
|
||||
controller.addViewer(player);
|
||||
controller.sendContent(player);
|
||||
controller.showInHand(player, true);
|
||||
}
|
||||
}
|
||||
|
||||
private int getMapSlot(Player player) {
|
||||
PlayerInventory inventory = player.getInventory();
|
||||
for (int i = 0; i < 9; i++) {
|
||||
ItemStack item = inventory.getItem(i);
|
||||
if (item != null && item.getType() == Material.MAP) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public void refresh() {
|
||||
// if (last != null) view(last, null);
|
||||
if (last != null) view(last, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
// last = null;
|
||||
last = null;
|
||||
}
|
||||
}
|
@ -34,6 +34,7 @@ import javax.annotation.Nullable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.OptionalInt;
|
||||
|
||||
public class BukkitBlockRegistry extends BundledBlockRegistry {
|
||||
|
||||
@ -93,6 +94,10 @@ public class BukkitBlockRegistry extends BundledBlockRegistry {
|
||||
this.material = bukkitMaterial;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return material.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAir() {
|
||||
switch (material) {
|
||||
@ -132,4 +137,9 @@ public class BukkitBlockRegistry extends BundledBlockRegistry {
|
||||
}
|
||||
return blocks;
|
||||
}
|
||||
|
||||
@Override
|
||||
public OptionalInt getInternalBlockStateId(BlockState state) {
|
||||
return WorldEditPlugin.getInstance().getBukkitImplAdapter().getInternalBlockStateId(state);
|
||||
}
|
||||
}
|
||||
|
@ -24,6 +24,10 @@ import com.boydti.fawe.bukkit.FaweBukkit;
|
||||
import com.boydti.fawe.config.Settings;
|
||||
import com.boydti.fawe.object.RunnableVal;
|
||||
import com.boydti.fawe.util.TaskManager;
|
||||
import com.comphenix.protocol.PacketType;
|
||||
import com.comphenix.protocol.ProtocolLibrary;
|
||||
import com.comphenix.protocol.ProtocolManager;
|
||||
import com.comphenix.protocol.injector.netty.WirePacket;
|
||||
import com.sk89q.util.StringUtil;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
@ -47,10 +51,13 @@ import com.sk89q.worldedit.world.block.BlockStateHolder;
|
||||
import com.sk89q.worldedit.world.block.BlockTypes;
|
||||
import com.sk89q.worldedit.world.gamemode.GameMode;
|
||||
import com.sk89q.worldedit.world.gamemode.GameModes;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Supplier;
|
||||
import javax.annotation.Nullable;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
@ -359,6 +366,21 @@ public class BukkitPlayer extends AbstractPlayerActor {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendFakeChunk(int chunkX, int chunkZ, Supplier<byte[]> data) {
|
||||
ProtocolManager manager = ProtocolLibrary.getProtocolManager();
|
||||
// check if the chunk is in range
|
||||
if (true) {
|
||||
try {
|
||||
byte[] raw = data.get();
|
||||
WirePacket packet = new WirePacket(PacketType.Play.Server.MAP_CHUNK, raw);
|
||||
manager.sendWirePacket(getPlayer(), packet);
|
||||
} catch (InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendTitle(String title, String sub) {
|
||||
player.sendTitle(ChatColor.GOLD + title, ChatColor.GOLD + sub, 0, 70, 20);
|
||||
|
@ -21,7 +21,9 @@ package com.sk89q.worldedit.bukkit;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.beta.IChunkGet;
|
||||
import com.boydti.fawe.bukkit.FaweBukkit;
|
||||
import com.boydti.fawe.bukkit.adapter.mc1_14.BukkitGetBlocks_1_14;
|
||||
import com.boydti.fawe.config.Settings;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
@ -317,8 +319,19 @@ public class BukkitWorld extends AbstractWorld {
|
||||
@Override
|
||||
public void checkLoadedChunk(BlockVector3 pt) {
|
||||
World world = getWorld();
|
||||
|
||||
world.getChunkAt(pt.getBlockX() >> 4, pt.getBlockZ() >> 4);
|
||||
int X = pt.getBlockX() >> 4;
|
||||
int Z = pt.getBlockZ() >> 4;
|
||||
if (Fawe.isMainThread()) {
|
||||
world.getChunkAt(X, Z);
|
||||
} else if (!world.isChunkLoaded(X, Z)) {
|
||||
if (FaweBukkit.PAPER) {
|
||||
world.getChunkAtAsync(X, Z, true);
|
||||
} else {
|
||||
Fawe.get().getQueueHandler().sync(() -> {
|
||||
world.getChunkAt(X, Z);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -516,7 +529,8 @@ public class BukkitWorld extends AbstractWorld {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendChunk(int X, int Z, int mask) {
|
||||
public void refreshChunk(int X, int Z) {
|
||||
getWorld().refreshChunk(X, Z);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -84,6 +84,7 @@ import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.world.ChunkUnloadEvent;
|
||||
import org.bukkit.event.world.WorldInitEvent;
|
||||
import org.bukkit.metadata.FixedMetadataValue;
|
||||
import org.bukkit.metadata.MetadataValue;
|
||||
@ -560,16 +561,24 @@ public class WorldEditPlugin extends JavaPlugin { //implements TabCompleter
|
||||
*/
|
||||
public BukkitPlayer wrapPlayer(Player player) {
|
||||
synchronized (player) {
|
||||
@NotNull List<MetadataValue> meta = player.getMetadata("WE");
|
||||
if (meta == null || meta.isEmpty()) {
|
||||
BukkitPlayer wePlayer = new BukkitPlayer(this, player);
|
||||
BukkitPlayer wePlayer = getCachedPlayer(player);
|
||||
if (wePlayer == null) {
|
||||
wePlayer = new BukkitPlayer(this, player);
|
||||
player.setMetadata("WE", new FixedMetadataValue(this, wePlayer));
|
||||
return wePlayer;
|
||||
}
|
||||
return (BukkitPlayer) meta.get(0).value();
|
||||
return wePlayer;
|
||||
}
|
||||
}
|
||||
|
||||
public BukkitPlayer getCachedPlayer(Player player) {
|
||||
List<MetadataValue> meta = player.getMetadata("WE");
|
||||
if (meta == null || meta.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
return (BukkitPlayer) meta.get(0).value();
|
||||
}
|
||||
|
||||
public Actor wrapCommandSender(CommandSender sender) {
|
||||
if (sender instanceof Player) {
|
||||
return wrapPlayer((Player) sender);
|
||||
|
@ -228,6 +228,8 @@ public enum FaweCache implements Trimable {
|
||||
* Holds data for a palette used in a chunk section
|
||||
*/
|
||||
public final class Palette {
|
||||
public int bitsPerEntry;
|
||||
|
||||
public int paletteToBlockLength;
|
||||
/**
|
||||
* Reusable buffer array, MUST check paletteToBlockLength for actual length
|
||||
@ -319,6 +321,7 @@ public enum FaweCache implements Trimable {
|
||||
|
||||
// Construct palette
|
||||
Palette palette = PALETTE_CACHE.get();
|
||||
palette.bitsPerEntry = bitsPerEntry;
|
||||
palette.paletteToBlockLength = num_palette;
|
||||
palette.paletteToBlock = paletteToBlock;
|
||||
|
||||
|
@ -1,6 +1,8 @@
|
||||
package com.boydti.fawe;
|
||||
|
||||
import com.boydti.fawe.beta.implementation.QueueHandler;
|
||||
import com.boydti.fawe.beta.preloader.AsyncPreloader;
|
||||
import com.boydti.fawe.beta.preloader.Preloader;
|
||||
import com.boydti.fawe.object.FaweCommand;
|
||||
import com.boydti.fawe.regions.FaweMaskManager;
|
||||
import com.boydti.fawe.util.TaskManager;
|
||||
@ -54,4 +56,6 @@ public interface IFawe {
|
||||
|
||||
QueueHandler getQueueHandler();
|
||||
|
||||
Preloader getPreloader();
|
||||
|
||||
}
|
||||
|
@ -1,61 +0,0 @@
|
||||
package com.boydti.fawe.beta;
|
||||
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
public class ChunkFuture implements Future<Void> {
|
||||
|
||||
private final IChunk chunk;
|
||||
private volatile boolean cancelled;
|
||||
private volatile boolean done;
|
||||
|
||||
public ChunkFuture(IChunk chunk) {
|
||||
this.chunk = chunk;
|
||||
}
|
||||
|
||||
public IChunk getChunk() {
|
||||
return chunk;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean cancel(boolean mayInterruptIfRunning) {
|
||||
cancelled = true;
|
||||
return !done;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCancelled() {
|
||||
return cancelled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDone() {
|
||||
return done;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void get() throws InterruptedException, ExecutionException {
|
||||
synchronized (chunk) {
|
||||
if (!done) {
|
||||
this.wait();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void get(long timeout, TimeUnit unit)
|
||||
throws InterruptedException, ExecutionException, TimeoutException {
|
||||
synchronized (chunk) {
|
||||
if (!done) {
|
||||
this.wait(unit.toMillis(timeout));
|
||||
if (!done) {
|
||||
throw new TimeoutException();
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
package com.boydti.fawe.beta;
|
||||
|
||||
import com.boydti.fawe.FaweCache;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.world.biome.BiomeType;
|
||||
@ -19,5 +20,20 @@ public interface IBlocks extends Trimable {
|
||||
|
||||
BlockState getBlock(int x, int y, int z);
|
||||
|
||||
Map<BlockVector3, CompoundTag> getTiles();
|
||||
|
||||
Set<CompoundTag> getEntities();
|
||||
|
||||
BiomeType getBiomeType(int x, int z);
|
||||
|
||||
default int getBitMask() {
|
||||
int mask = 0;
|
||||
for (int layer = 0; layer < FaweCache.IMP.CHUNK_LAYERS; layer++) {
|
||||
if (hasSection(layer));
|
||||
mask |= (1 << layer);
|
||||
}
|
||||
return mask;
|
||||
}
|
||||
|
||||
IBlocks reset();
|
||||
}
|
||||
|
@ -28,8 +28,10 @@ public interface IChunkGet extends IBlocks, Trimable, InputExtent {
|
||||
|
||||
CompoundTag getTag(int x, int y, int z);
|
||||
|
||||
@Override
|
||||
Map<BlockVector3, CompoundTag> getTiles();
|
||||
|
||||
@Override
|
||||
Set<CompoundTag> getEntities();
|
||||
|
||||
@Override
|
||||
|
@ -38,8 +38,13 @@ public interface IChunkSet extends IBlocks, OutputExtent {
|
||||
|
||||
BiomeType[] getBiomes();
|
||||
|
||||
@Override
|
||||
BiomeType getBiomeType(int x, int z);
|
||||
|
||||
@Override
|
||||
Map<BlockVector3, CompoundTag> getTiles();
|
||||
|
||||
@Override
|
||||
Set<CompoundTag> getEntities();
|
||||
|
||||
@Override
|
||||
|
@ -45,16 +45,6 @@ public interface IDelegateQueueExtent extends IQueueExtent {
|
||||
return getParent().isQueueEnabled();
|
||||
}
|
||||
|
||||
@Override
|
||||
default void clearBlockUpdates(Player... players) {
|
||||
getParent().clearBlockUpdates(players);
|
||||
}
|
||||
|
||||
@Override
|
||||
default void sendBlockUpdates(Player... players) {
|
||||
getParent().sendBlockUpdates(players);
|
||||
}
|
||||
|
||||
@Override
|
||||
default void enableQueue() {
|
||||
getParent().enableQueue();
|
||||
|
@ -31,22 +31,6 @@ public interface IQueueExtent extends Flushable, Trimable, Extent, IBatchProcess
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear any block updates
|
||||
* @param players
|
||||
*/
|
||||
default void clearBlockUpdates(Player... players) {
|
||||
throw new UnsupportedOperationException("TODO NOT IMPLEMENTED");
|
||||
}
|
||||
|
||||
/**
|
||||
* Send all the chunks as block updates
|
||||
* @param players
|
||||
*/
|
||||
default void sendBlockUpdates(Player... players) {
|
||||
throw new UnsupportedOperationException("TODO NOT IMPLEMENTED");
|
||||
}
|
||||
|
||||
/**
|
||||
* Must ensure that it is enqueued with QueueHandler
|
||||
*/
|
||||
|
@ -0,0 +1,126 @@
|
||||
package com.boydti.fawe.beta.implementation;
|
||||
|
||||
import com.boydti.fawe.FaweCache;
|
||||
import com.boydti.fawe.beta.IBlocks;
|
||||
import com.boydti.fawe.object.FaweOutputStream;
|
||||
import com.boydti.fawe.object.io.FastByteArrayOutputStream;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.extension.platform.Capability;
|
||||
import com.sk89q.worldedit.world.block.BlockID;
|
||||
import com.sk89q.worldedit.world.block.BlockState;
|
||||
import com.sk89q.worldedit.world.registry.BlockRegistry;
|
||||
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class ChunkPacket implements Function<byte[], byte[]>, Supplier<byte[]> {
|
||||
|
||||
private final boolean full;
|
||||
private final boolean biomes;
|
||||
private final IBlocks chunk;
|
||||
private final int chunkX;
|
||||
private final int chunkZ;
|
||||
|
||||
public ChunkPacket(int chunkX, int chunkZ, IBlocks chunk, boolean replaceAllSections, boolean sendBiomeData) {
|
||||
this.chunkX = chunkX;
|
||||
this.chunkZ = chunkZ;
|
||||
this.chunk = chunk;
|
||||
this.full = replaceAllSections;
|
||||
this.biomes = sendBiomeData;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public byte[] get() {
|
||||
System.out.println("TODO deprecated, use buffer");
|
||||
return apply(new byte[8192]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] apply(byte[] buffer) {
|
||||
try {
|
||||
FastByteArrayOutputStream baos = new FastByteArrayOutputStream();
|
||||
FaweOutputStream fos = new FaweOutputStream(baos);
|
||||
|
||||
fos.writeInt(this.chunkX);
|
||||
fos.writeInt(this.chunkZ);
|
||||
|
||||
fos.writeBoolean(this.full);
|
||||
|
||||
fos.writeVarInt(this.chunk.getBitMask()); // writeVarInt
|
||||
|
||||
// TODO write NBTTagCompound of HeightMaps
|
||||
fos.writeVarInt(0); // (Entities / NBT)
|
||||
|
||||
// TODO write chunk data to byte[]
|
||||
{
|
||||
BlockRegistry registry = WorldEdit.getInstance().getPlatformManager().queryCapability(Capability.GAME_HOOKS).getRegistries().getBlockRegistry();
|
||||
try (FastByteArrayOutputStream sectionByteArray = new FastByteArrayOutputStream(buffer); FaweOutputStream sectionWriter = new FaweOutputStream(sectionByteArray)) {
|
||||
for (int layer = 0; layer < FaweCache.IMP.CHUNK_LAYERS; layer++) {
|
||||
if (!this.chunk.hasSection(layer)) continue;
|
||||
char[] ids = this.chunk.getArray(layer);
|
||||
FaweCache.Palette palette = FaweCache.IMP.toPalette(0, ids);
|
||||
|
||||
int nonEmpty = 0; // TODO optimize into same loop as toPalette
|
||||
for (char id :ids) {
|
||||
if (id != 0) nonEmpty++;
|
||||
}
|
||||
sectionWriter.writeShort(nonEmpty); // non empty
|
||||
sectionWriter.writeByte(palette.bitsPerEntry); // bits per block
|
||||
sectionWriter.writeVarInt(palette.paletteToBlockLength);
|
||||
for (int i = 0; i < palette.paletteToBlockLength; i++) {
|
||||
int ordinal = palette.paletteToBlock[i];
|
||||
switch (ordinal) {
|
||||
case BlockID.CAVE_AIR:
|
||||
case BlockID.VOID_AIR:
|
||||
case BlockID.AIR:
|
||||
case BlockID.__RESERVED__:
|
||||
sectionWriter.writeByte(0);
|
||||
break;
|
||||
default:
|
||||
BlockState state = BlockState.getFromOrdinal(ordinal);
|
||||
int mcId = registry.getInternalBlockStateId(state).getAsInt();
|
||||
sectionWriter.writeVarInt(mcId);
|
||||
}
|
||||
}
|
||||
sectionWriter.writeVarInt(palette.blockStatesLength);
|
||||
for (int i = 0; i < palette.blockStatesLength; i++) {
|
||||
sectionWriter.writeLong(palette.blockStates[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO write biomes
|
||||
// boolean writeBiomes = true;
|
||||
// for (int x = 0; x < 16; x++) {
|
||||
// for (int z = 0; z < 16; z++) {
|
||||
// BiomeType biome = this.chunk.getBiomeType(x, z);
|
||||
// if (biome == null) {
|
||||
// if (writeBiomes) {
|
||||
// break;
|
||||
// } else {
|
||||
// biome = BiomeTypes.FOREST;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
if (this.full) {
|
||||
for (int i = 0; i < 256; i++) {
|
||||
sectionWriter.writeInt(0);
|
||||
}
|
||||
}
|
||||
|
||||
fos.writeVarInt(sectionByteArray.getSize());
|
||||
for (byte[] arr : sectionByteArray.toByteArrays()) {
|
||||
fos.write(arr);
|
||||
}
|
||||
}
|
||||
}
|
||||
// TODO entities / NBT
|
||||
fos.writeVarInt(0); // (Entities / NBT)
|
||||
return baos.toByteArray();
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
package com.boydti.fawe.beta.implementation;
|
||||
|
||||
import com.boydti.fawe.beta.IBatchProcessor;
|
||||
import com.boydti.fawe.beta.IChunk;
|
||||
import com.boydti.fawe.beta.IChunkGet;
|
||||
import com.boydti.fawe.beta.IChunkSet;
|
||||
import com.boydti.fawe.object.extent.NullExtent;
|
||||
import com.google.common.base.Suppliers;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.extent.AbstractDelegateExtent;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class ChunkSendProcessor extends AbstractDelegateExtent implements IBatchProcessor {
|
||||
private final Supplier<Stream<Player>> players;
|
||||
|
||||
public ChunkSendProcessor(Supplier<Stream<Player>> players) {
|
||||
super(new NullExtent());
|
||||
this.players = players;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IChunkSet processSet(IChunk chunk, IChunkGet get, IChunkSet set) {
|
||||
int chunkX = chunk.getX();
|
||||
int chunkZ = chunk.getZ();
|
||||
boolean replaceAll = true;
|
||||
boolean sendBiome = set.getBiomes() != null;
|
||||
ChunkPacket packet = new ChunkPacket(chunkX, chunkZ, set, replaceAll, sendBiome);
|
||||
Supplier<byte[]> packetData = Suppliers.memoize(packet::get);
|
||||
players.get().forEach(plr -> plr.sendFakeChunk(chunkX, chunkZ, packetData));
|
||||
return set;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Extent construct(Extent child) {
|
||||
return null;
|
||||
}
|
||||
}
|
@ -170,6 +170,7 @@ public class ParallelQueueExtent extends PassthroughExtent implements IQueueWrap
|
||||
if (vset instanceof Region) {
|
||||
setBlocks((Region) vset, pattern);
|
||||
}
|
||||
// TODO optimize parallel
|
||||
for (BlockVector3 blockVector3 : vset) {
|
||||
pattern.apply(this, blockVector3, blockVector3);
|
||||
}
|
||||
|
@ -19,6 +19,7 @@ import java.lang.ref.WeakReference;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Queue;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
@ -39,6 +40,7 @@ public abstract class QueueHandler implements Trimable, Runnable {
|
||||
private ForkJoinPool forkJoinPoolSecondary = new ForkJoinPool();
|
||||
private ThreadPoolExecutor blockingExecutor = FaweCache.IMP.newBlockingExecutor();
|
||||
private ConcurrentLinkedQueue<FutureTask> syncTasks = new ConcurrentLinkedQueue<>();
|
||||
private ConcurrentLinkedQueue<FutureTask> syncWhenFree = new ConcurrentLinkedQueue<>();
|
||||
|
||||
private Map<World, WeakReference<IChunkCache<IChunkGet>>> chunkGetCache = new HashMap<>();
|
||||
private CleanableThreadLocal<IQueueExtent> queuePool = new CleanableThreadLocal<>(QueueHandler.this::create);
|
||||
@ -60,53 +62,61 @@ public abstract class QueueHandler implements Trimable, Runnable {
|
||||
throw new IllegalStateException("Not main thread");
|
||||
}
|
||||
if (!syncTasks.isEmpty()) {
|
||||
long now = System.currentTimeMillis();
|
||||
targetTPS = 18 - Math.max(Settings.IMP.QUEUE.EXTRA_TIME_MS * 0.05, 0);
|
||||
long diff = 50 + this.last - (this.last = now);
|
||||
long absDiff = Math.abs(diff);
|
||||
if (diff == 0) {
|
||||
allocate = Math.min(50, allocate + 1);
|
||||
} else if (diff < 0) {
|
||||
allocate = Math.max(5, allocate + diff);
|
||||
} else if (!Fawe.get().getTimer().isAbove(targetTPS)) {
|
||||
allocate = Math.max(5, allocate - 1);
|
||||
}
|
||||
long currentAllocate = allocate - absDiff;
|
||||
long currentAllocate = getAllocate();
|
||||
|
||||
if (!MemUtil.isMemoryFree()) {
|
||||
// TODO reduce mem usage
|
||||
// FaweCache trim
|
||||
// Preloader trim
|
||||
}
|
||||
|
||||
boolean wait = false;
|
||||
do {
|
||||
Runnable task = syncTasks.poll();
|
||||
if (task == null) {
|
||||
if (wait) {
|
||||
synchronized (syncTasks) {
|
||||
try {
|
||||
syncTasks.wait(1);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
task = syncTasks.poll();
|
||||
wait = false;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (task != null) {
|
||||
task.run();
|
||||
wait = true;
|
||||
}
|
||||
} while (System.currentTimeMillis() - now < currentAllocate);
|
||||
operate(syncTasks, last, currentAllocate);
|
||||
} else if (!syncWhenFree.isEmpty()) {
|
||||
operate(syncWhenFree, last, getAllocate());
|
||||
} else {
|
||||
// trim??
|
||||
}
|
||||
while (!syncTasks.isEmpty()) {
|
||||
final FutureTask task = syncTasks.poll();
|
||||
}
|
||||
|
||||
private long getAllocate() {
|
||||
long now = System.currentTimeMillis();
|
||||
targetTPS = 18 - Math.max(Settings.IMP.QUEUE.EXTRA_TIME_MS * 0.05, 0);
|
||||
long diff = 50 + this.last - (this.last = now);
|
||||
long absDiff = Math.abs(diff);
|
||||
if (diff == 0) {
|
||||
allocate = Math.min(50, allocate + 1);
|
||||
} else if (diff < 0) {
|
||||
allocate = Math.max(5, allocate + diff);
|
||||
} else if (!Fawe.get().getTimer().isAbove(targetTPS)) {
|
||||
allocate = Math.max(5, allocate - 1);
|
||||
}
|
||||
return allocate - absDiff;
|
||||
}
|
||||
|
||||
private void operate(Queue<FutureTask> queue, long start, long currentAllocate) {
|
||||
boolean wait = false;
|
||||
do {
|
||||
Runnable task = queue.poll();
|
||||
if (task == null) {
|
||||
if (wait) {
|
||||
synchronized (syncTasks) {
|
||||
try {
|
||||
queue.wait(1);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
task = queue.poll();
|
||||
wait = false;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (task != null) {
|
||||
task.run();
|
||||
wait = true;
|
||||
}
|
||||
}
|
||||
} while (System.currentTimeMillis() - start < currentAllocate);
|
||||
}
|
||||
|
||||
public <T extends Future<T>> void complete(Future<T> task) {
|
||||
@ -136,50 +146,83 @@ public abstract class QueueHandler implements Trimable, Runnable {
|
||||
}
|
||||
|
||||
public <T> Future<T> sync(Runnable run, T value) {
|
||||
return sync(run, value, syncTasks);
|
||||
}
|
||||
|
||||
public <T> Future<T> sync(Runnable run) {
|
||||
return sync(run, syncTasks);
|
||||
}
|
||||
|
||||
public <T> Future<T> sync(Callable<T> call) throws Exception {
|
||||
return sync(call, syncTasks);
|
||||
}
|
||||
|
||||
public <T> Future<T> sync(Supplier<T> call) {
|
||||
return sync(call, syncTasks);
|
||||
}
|
||||
|
||||
// Lower priorty sync task (runs only when there are no other tasks)
|
||||
public <T> Future<T> syncWhenFree(Runnable run, T value) {
|
||||
return sync(run, value, syncWhenFree);
|
||||
}
|
||||
|
||||
public <T> Future<T> syncWhenFree(Runnable run) {
|
||||
return sync(run, syncWhenFree);
|
||||
}
|
||||
|
||||
public <T> Future<T> syncWhenFree(Callable<T> call) throws Exception {
|
||||
return sync(call, syncWhenFree);
|
||||
}
|
||||
|
||||
public <T> Future<T> syncWhenFree(Supplier<T> call) {
|
||||
return sync(call, syncWhenFree);
|
||||
}
|
||||
|
||||
private <T> Future<T> sync(Runnable run, T value, Queue<FutureTask> queue) {
|
||||
if (Fawe.isMainThread()) {
|
||||
run.run();
|
||||
return Futures.immediateFuture(value);
|
||||
}
|
||||
final FutureTask<T> result = new FutureTask<>(run, value);
|
||||
syncTasks.add(result);
|
||||
notifySync();
|
||||
queue.add(result);
|
||||
notifySync(queue);
|
||||
return result;
|
||||
}
|
||||
|
||||
public <T> Future<T> sync(Runnable run) {
|
||||
private <T> Future<T> sync(Runnable run, Queue<FutureTask> queue) {
|
||||
if (Fawe.isMainThread()) {
|
||||
run.run();
|
||||
return Futures.immediateCancelledFuture();
|
||||
}
|
||||
final FutureTask<T> result = new FutureTask<>(run, null);
|
||||
syncTasks.add(result);
|
||||
notifySync();
|
||||
queue.add(result);
|
||||
notifySync(queue);
|
||||
return result;
|
||||
}
|
||||
|
||||
public <T> Future<T> sync(Callable<T> call) throws Exception {
|
||||
private <T> Future<T> sync(Callable<T> call, Queue<FutureTask> queue) throws Exception {
|
||||
if (Fawe.isMainThread()) {
|
||||
return Futures.immediateFuture(call.call());
|
||||
}
|
||||
final FutureTask<T> result = new FutureTask<>(call);
|
||||
syncTasks.add(result);
|
||||
notifySync();
|
||||
queue.add(result);
|
||||
notifySync(queue);
|
||||
return result;
|
||||
}
|
||||
|
||||
public <T> Future<T> sync(Supplier<T> call) {
|
||||
private <T> Future<T> sync(Supplier<T> call, Queue<FutureTask> queue) {
|
||||
if (Fawe.isMainThread()) {
|
||||
return Futures.immediateFuture(call.get());
|
||||
}
|
||||
final FutureTask<T> result = new FutureTask<>(call::get);
|
||||
syncTasks.add(result);
|
||||
notifySync();
|
||||
queue.add(result);
|
||||
notifySync(queue);
|
||||
return result;
|
||||
}
|
||||
|
||||
private void notifySync() {
|
||||
synchronized (syncTasks) {
|
||||
syncTasks.notifyAll();
|
||||
private void notifySync(Object object) {
|
||||
synchronized (object) {
|
||||
object.notifyAll();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -115,6 +115,11 @@ public class BitSetBlocks implements IChunkSet {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BiomeType getBiomeType(int x, int z) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<BlockVector3, CompoundTag> getTiles() {
|
||||
return null;
|
||||
|
@ -11,7 +11,7 @@ import com.sk89q.worldedit.world.block.BlockTypes;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public class CharBlocks implements IBlocks {
|
||||
public abstract class CharBlocks implements IBlocks {
|
||||
|
||||
public static final Section FULL = new Section() {
|
||||
@Override
|
||||
|
@ -43,6 +43,11 @@ public class CharSetBlocks extends CharBlocks implements IChunkSet {
|
||||
return biomes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BiomeType getBiomeType(int x, int z) {
|
||||
return biomes[(z << 4) | x];
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<BlockVector3, CompoundTag> getTiles() {
|
||||
return tiles == null ? Collections.emptyMap() : tiles;
|
||||
|
@ -0,0 +1,110 @@
|
||||
package com.boydti.fawe.beta.preloader;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.object.collection.MutablePair;
|
||||
import com.boydti.fawe.util.FaweTimer;
|
||||
import com.sk89q.worldedit.IncompleteRegionException;
|
||||
import com.sk89q.worldedit.LocalSession;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.math.BlockVector2;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.regions.CuboidRegion;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
|
||||
public class AsyncPreloader implements Preloader, Runnable {
|
||||
private final ConcurrentHashMap<UUID, MutablePair<World, Set<BlockVector2>>> update;
|
||||
|
||||
public AsyncPreloader() {
|
||||
this.update = new ConcurrentHashMap<>();
|
||||
Fawe.get().getQueueHandler().async(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancel(Player player) {
|
||||
cancelAndGet(player);
|
||||
}
|
||||
|
||||
private MutablePair<World, Set<BlockVector2>> cancelAndGet(Player player) {
|
||||
MutablePair<World, Set<BlockVector2>> existing = update.get(player.getUniqueId());
|
||||
if (existing != null) {
|
||||
existing.setValue(null);
|
||||
}
|
||||
return existing;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Player player) {
|
||||
LocalSession session = WorldEdit.getInstance().getSessionManager().getIfPresent(player);
|
||||
if (session == null) return;
|
||||
World world = player.getWorld();
|
||||
MutablePair<World, Set<BlockVector2>> existing = cancelAndGet(player);
|
||||
try {
|
||||
Region region = session.getSelection(world);
|
||||
if (!(region instanceof CuboidRegion) || region.getArea() > 50466816) {
|
||||
// TOO LARGE or NOT CUBOID
|
||||
return;
|
||||
}
|
||||
if (existing == null) {
|
||||
MutablePair<World, Set<BlockVector2>> previous = update.putIfAbsent(player.getUniqueId(), existing = new MutablePair<>());
|
||||
if (previous != null) {
|
||||
existing = previous;
|
||||
}
|
||||
synchronized (existing) { // Ensure key & value are mutated together
|
||||
existing.setKey(world);
|
||||
existing.setValue(region.getChunks());
|
||||
}
|
||||
synchronized (update) {
|
||||
update.notify();
|
||||
}
|
||||
}
|
||||
} catch (IncompleteRegionException ignore){}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
FaweTimer timer = Fawe.get().getTimer();
|
||||
try {
|
||||
while (true) {
|
||||
if (!update.isEmpty()) {
|
||||
if (timer.getTPS() > 19) {
|
||||
Iterator<Map.Entry<UUID, MutablePair<World, Set<BlockVector2>>>> plrIter = update.entrySet().iterator();
|
||||
Map.Entry<UUID, MutablePair<World, Set<BlockVector2>>> entry = plrIter.next();
|
||||
MutablePair<World, Set<BlockVector2>> pair = entry.getValue();
|
||||
World world = pair.getKey();
|
||||
Set<BlockVector2> chunks = pair.getValue();
|
||||
if (chunks != null) {
|
||||
Iterator<BlockVector2> chunksIter = chunks.iterator();
|
||||
while (chunksIter.hasNext() && pair.getValue() == chunks) { // Ensure the queued load is still valid
|
||||
BlockVector2 chunk = chunksIter.next();
|
||||
queueLoad(world, chunk);
|
||||
}
|
||||
}
|
||||
plrIter.remove();
|
||||
} else {
|
||||
Thread.sleep(1000);
|
||||
}
|
||||
} else {
|
||||
synchronized (update) {
|
||||
update.wait();
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public void queueLoad(World world, BlockVector2 chunk) {
|
||||
world.checkLoadedChunk(BlockVector3.at(chunk.getX() << 4, 0, chunk.getZ() << 4));
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
package com.boydti.fawe.beta.preloader;
|
||||
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
|
||||
public interface Preloader {
|
||||
void cancel(Player player);
|
||||
|
||||
void update(Player player);
|
||||
}
|
@ -432,7 +432,7 @@ public class CFICommands {
|
||||
Clipboard clipboard = holder.getClipboard();
|
||||
boolean[] ids = new boolean[BlockTypes.size()];
|
||||
for (BlockVector3 pt : clipboard.getRegion()) {
|
||||
ids[clipboard.getBlock(pt).getInternalBlockTypeId()] = true;
|
||||
ids[clipboard.getBlock(pt).getBlockType().getInternalId()] = true;
|
||||
}
|
||||
blocks = new HashSet<>();
|
||||
for (int combined = 0; combined < ids.length; combined++) {
|
||||
@ -606,7 +606,7 @@ public class CFICommands {
|
||||
@CommandPermissions("worldedit.anvil.cfi")
|
||||
public void waterId(Player fp, BlockStateHolder block) throws WorldEditException {
|
||||
CFISettings settings = assertSettings(fp);
|
||||
settings.getGenerator().setWaterId(block.getBlockType().getInternalId());
|
||||
settings.getGenerator().setWater(block.toImmutableState());
|
||||
|
||||
fp.print("Set water id!");
|
||||
settings.resetComponent();
|
||||
@ -621,7 +621,7 @@ public class CFICommands {
|
||||
@CommandPermissions("worldedit.anvil.cfi")
|
||||
public void baseId(Player fp, BlockStateHolder block) throws WorldEditException {
|
||||
CFISettings settings = assertSettings(fp);
|
||||
settings.getGenerator().setBedrockId(block.getBlockType().getInternalId());
|
||||
settings.getGenerator().setBedrock(block.toImmutableState());
|
||||
fp.print(TextComponent.of("Set base id!"));
|
||||
settings.resetComponent();
|
||||
component(fp);
|
||||
|
8
worldedit-core/src/main/java/com/boydti/fawe/object/Lazy.java
Normale Datei
8
worldedit-core/src/main/java/com/boydti/fawe/object/Lazy.java
Normale Datei
@ -0,0 +1,8 @@
|
||||
package com.boydti.fawe.object;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public interface Lazy<T> extends Supplier<T> {
|
||||
Supplier<T> init();
|
||||
public default T get() { return init().get(); }
|
||||
}
|
@ -47,7 +47,7 @@ public class VisualExtent extends AbstractDelegateExtent {
|
||||
@Override
|
||||
public Operation commit() {
|
||||
IQueueExtent queue = (IQueueExtent) getExtent();
|
||||
queue.sendBlockUpdates(this.player);
|
||||
System.out.println("Send block updates");
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -59,7 +59,7 @@ public class VisualExtent extends AbstractDelegateExtent {
|
||||
|
||||
public void clear() {
|
||||
IQueueExtent queue = (IQueueExtent) getExtent();
|
||||
queue.clearBlockUpdates(player);
|
||||
System.out.println("Clear");
|
||||
queue.cancel();
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,142 @@
|
||||
package com.boydti.fawe.object.brush.visualization.cfi;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.util.MathMan;
|
||||
import com.boydti.fawe.util.TextureUtil;
|
||||
import com.sk89q.worldedit.world.block.BlockID;
|
||||
import com.sk89q.worldedit.world.block.BlockTypes;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.DataBufferInt;
|
||||
import java.util.concurrent.ForkJoinPool;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public final class CFIDrawer {
|
||||
private final HeightMapMCAGenerator gen;
|
||||
private final TextureUtil tu;
|
||||
private final ForkJoinPool pool;
|
||||
|
||||
public CFIDrawer(HeightMapMCAGenerator generator, TextureUtil textureUtil) {
|
||||
this.gen = generator;
|
||||
this.tu = textureUtil;
|
||||
this.pool = new ForkJoinPool();
|
||||
}
|
||||
|
||||
public CFIDrawer(HeightMapMCAGenerator generator) {
|
||||
this(generator, Fawe.get().getCachedTextureUtil(false, 0, 100));
|
||||
}
|
||||
|
||||
public BufferedImage draw() {
|
||||
BufferedImage img = new BufferedImage(gen.getWidth(), gen.getLength(), BufferedImage.TYPE_INT_RGB);
|
||||
final char[] overlay = gen.overlay == null ? gen.floor.get() : gen.overlay.get();
|
||||
final char[] floor = gen.floor.get();
|
||||
final char[] main = gen.main.get();
|
||||
final byte[] heights = gen.heights.get();
|
||||
final byte[] biomes = gen.biomes.get();
|
||||
final int waterHeight = gen.primitives.waterHeight;
|
||||
final int width = gen.getWidth();
|
||||
final int length = gen.getLength();
|
||||
|
||||
int[] raw = ((DataBufferInt) img.getRaster().getDataBuffer()).getData();
|
||||
|
||||
int parallelism = pool.getParallelism();
|
||||
int size = (heights.length + parallelism - 1) / parallelism;
|
||||
for (int i = 0; i < parallelism; i++) {
|
||||
int start = i * size;
|
||||
int end = Math.min(heights.length, start + size);
|
||||
pool.submit((Runnable) () -> {
|
||||
for (int index = start; index < end; index ++) {
|
||||
int height = (heights[index] & 0xFF);
|
||||
char ordinal;
|
||||
if ((ordinal = overlay[index]) == 0) {
|
||||
height--;
|
||||
ordinal = floor[index];
|
||||
if (ordinal == 0) {
|
||||
height--;
|
||||
ordinal = main[index];
|
||||
}
|
||||
}
|
||||
// draw ordinal
|
||||
int color;
|
||||
switch (ordinal >> 4) {
|
||||
case 2:
|
||||
color = getAverageBiomeColor(biomes, width, index);
|
||||
break;
|
||||
case 78:
|
||||
color = (0xDD << 16) + (0xDD << 8) + (0xDD << 0);
|
||||
break;
|
||||
default:
|
||||
color = tu.getColor(BlockTypes.getFromStateOrdinal(ordinal));
|
||||
break;
|
||||
}
|
||||
int slope = getSlope(heights, width, index, height);
|
||||
if (slope != 0) {
|
||||
slope = (slope << 3) + (slope << 2);
|
||||
int r = MathMan.clamp(((color >> 16) & 0xFF) + slope, 0, 255);
|
||||
int g = MathMan.clamp(((color >> 8) & 0xFF) + slope, 0, 255);
|
||||
int b = MathMan.clamp(((color >> 0) & 0xFF) + slope, 0, 255);
|
||||
color = (r << 16) + (g << 8) + (b << 0);
|
||||
}
|
||||
if (height + 1 < waterHeight) {
|
||||
char waterId = gen.primitives.waterOrdinal;
|
||||
int waterColor = 0;
|
||||
switch (waterId) {
|
||||
case BlockID.WATER:
|
||||
color = tu.averageColor((0x11 << 16) + (0x66 << 8) + (0xCC), color);
|
||||
break;
|
||||
case BlockID.LAVA:
|
||||
color = (0xCC << 16) + (0x33 << 8) + (0);
|
||||
break;
|
||||
default:
|
||||
color = tu.getColor(BlockTypes.getFromStateOrdinal(waterId));
|
||||
break;
|
||||
}
|
||||
}
|
||||
raw[index] = color;
|
||||
}
|
||||
});
|
||||
}
|
||||
pool.awaitQuiescence(Long.MAX_VALUE, TimeUnit.MILLISECONDS);
|
||||
pool.shutdownNow();
|
||||
return img;
|
||||
}
|
||||
|
||||
private final int getAverageBiomeColor(byte[] biomes, int width, int index) {
|
||||
int c0 = tu.getBiome(biomes[index] & 0xFF).grassCombined;
|
||||
int c2 = getBiome(biomes, index + 1 + width, index);
|
||||
int c1 = getBiome(biomes, index - 1 - width, index);
|
||||
// int c3 = getBiome(biomes, index + width, index);
|
||||
// int c4 = getBiome(biomes, index - width, index);
|
||||
int r = ((c0 >> 16) & 0xFF) + ((c1 >> 16) & 0xFF) + ((c2 >> 16) & 0xFF);// + ((c3 >> 16) & 0xFF) + ((c4 >> 16) & 0xFF);
|
||||
int g = ((c0 >> 8) & 0xFF) + ((c1 >> 8) & 0xFF) + ((c2 >> 8) & 0xFF);// + ((c3 >> 8) & 0xFF) + ((c4 >> 8) & 0xFF);
|
||||
int b = ((c0) & 0xFF) + ((c1) & 0xFF) + ((c2) & 0xFF);// + ((c3) & 0xFF) + ((c4) & 0xFF);
|
||||
r = r * 85 >> 8;
|
||||
g = g * 85 >> 8;
|
||||
b = b * 85 >> 8;
|
||||
return (r << 16) + (g << 8) + (b);
|
||||
}
|
||||
|
||||
private final int getBiome(byte[] biomes, int newIndex, int index) {
|
||||
if (newIndex < 0 || newIndex >= biomes.length) newIndex = index;
|
||||
int biome = biomes[newIndex] & 0xFF;
|
||||
return tu.getBiome(biome).grassCombined;
|
||||
}
|
||||
|
||||
private int getSlope(byte[] heights, int width, int index, int height) {
|
||||
return (
|
||||
+ getHeight(heights, index + 1, height)
|
||||
// + getHeight(heights, index + width, height)
|
||||
+ getHeight(heights, index + width + 1, height)
|
||||
- getHeight(heights, index - 1, height)
|
||||
// - getHeight(heights, index - width, height)
|
||||
- getHeight(heights, index - width - 1, height)
|
||||
);
|
||||
}
|
||||
|
||||
private int getHeight(byte[] heights, int index, int height) {
|
||||
if (index < 0 || index >= heights.length) return height;
|
||||
return heights[index] & 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,6 +3,8 @@ package com.boydti.fawe.object.brush.visualization.cfi;
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.FaweCache;
|
||||
import com.boydti.fawe.beta.IChunkGet;
|
||||
import com.boydti.fawe.beta.IChunkSet;
|
||||
import com.boydti.fawe.beta.implementation.ChunkPacket;
|
||||
import com.boydti.fawe.beta.implementation.FallbackChunkGet;
|
||||
import com.boydti.fawe.object.FaweInputStream;
|
||||
import com.boydti.fawe.object.FaweOutputStream;
|
||||
@ -15,7 +17,6 @@ import com.boydti.fawe.object.collection.DifferentialBlockBuffer;
|
||||
import com.boydti.fawe.object.collection.LocalBlockVector2DSet;
|
||||
import com.boydti.fawe.object.collection.SummedAreaTable;
|
||||
import com.boydti.fawe.object.exception.FaweChunkLoadException;
|
||||
import com.boydti.fawe.object.exception.FaweException;
|
||||
import com.boydti.fawe.object.schematic.Schematic;
|
||||
import com.boydti.fawe.util.CachedTextureUtil;
|
||||
import com.boydti.fawe.util.RandomTextureUtil;
|
||||
@ -23,6 +24,7 @@ import com.boydti.fawe.util.ReflectionUtils;
|
||||
import com.boydti.fawe.util.TextureUtil;
|
||||
import com.boydti.fawe.util.image.Drawable;
|
||||
import com.boydti.fawe.util.image.ImageViewer;
|
||||
import com.google.common.base.Suppliers;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.LocalSession;
|
||||
@ -64,6 +66,7 @@ import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
import java.util.function.Supplier;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
// TODO FIXME
|
||||
@ -73,9 +76,9 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
private final DifferentialBlockBuffer blocks;
|
||||
protected final DifferentialArray<byte[]> heights;
|
||||
protected final DifferentialArray<byte[]> biomes;
|
||||
protected final DifferentialArray<int[]> floor;
|
||||
protected final DifferentialArray<int[]> main;
|
||||
protected DifferentialArray<int[]> overlay;
|
||||
protected final DifferentialArray<char[]> floor;
|
||||
protected final DifferentialArray<char[]> main;
|
||||
protected DifferentialArray<char[]> overlay;
|
||||
|
||||
protected final CFIPrimitives primitives = new CFIPrimitives();
|
||||
private CFIPrimitives oldPrimitives = new CFIPrimitives();
|
||||
@ -86,8 +89,8 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
int worldThickness;
|
||||
boolean randomVariation = true;
|
||||
int biomePriority;
|
||||
int waterId = BlockID.WATER;
|
||||
int bedrockId = BlockID.BEDROCK;
|
||||
char waterOrdinal = BlockID.WATER;
|
||||
char bedrockOrdinal = BlockID.BEDROCK;
|
||||
boolean modifiedMain;
|
||||
|
||||
@Override
|
||||
@ -225,13 +228,13 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
blocks = new DifferentialBlockBuffer(width, length);
|
||||
heights = new DifferentialArray<>(new byte[getArea()]);
|
||||
biomes = new DifferentialArray<>(new byte[getArea()]);
|
||||
floor = new DifferentialArray<>(new int[getArea()]);
|
||||
main = new DifferentialArray<>(new int[getArea()]);
|
||||
floor = new DifferentialArray<>(new char[getArea()]);
|
||||
main = new DifferentialArray<>(new char[getArea()]);
|
||||
|
||||
int stone = BlockID.STONE;
|
||||
int grass = BlockTypes.GRASS_BLOCK.getDefaultState().with(PropertyKey.SNOWY, false).getInternalId();
|
||||
Arrays.fill(main.getIntArray(), stone);
|
||||
Arrays.fill(floor.getIntArray(), grass);
|
||||
char stone = BlockID.STONE;
|
||||
char grass = BlockTypes.GRASS_BLOCK.getDefaultState().with(PropertyKey.SNOWY, false).getOrdinalChar();
|
||||
Arrays.fill(overlay.getCharArray(), stone);
|
||||
Arrays.fill(overlay.getCharArray(), grass);
|
||||
}
|
||||
|
||||
public Metadatable getMetaData() {
|
||||
@ -259,10 +262,10 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
return player;
|
||||
}
|
||||
|
||||
private int[][][] getChunkArray(int x, int z) {
|
||||
int[][][][][] blocksData = blocks.get();
|
||||
private char[][][] getChunkArray(int x, int z) {
|
||||
char[][][][][] blocksData = blocks.get();
|
||||
if (blocksData == null) return null;
|
||||
int[][][][] arr = blocksData[z];
|
||||
char[][][][] arr = blocksData[z];
|
||||
return arr != null ? arr[x] : null;
|
||||
}
|
||||
|
||||
@ -320,8 +323,20 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendChunk(int X, int Z, int mask) {
|
||||
throw new UnsupportedOperationException("TODO NOT IMPLEMENTED"); // add method to adapter to send custom chunk
|
||||
public void refreshChunk(int chunkX, int chunkZ) {
|
||||
IChunkSet chunk = getChunk(chunkX, chunkZ);
|
||||
ChunkPacket packet = new ChunkPacket(chunkX, chunkZ, chunk, true, true);
|
||||
player.sendFakeChunk(chunkX, chunkZ, packet::get);
|
||||
}
|
||||
|
||||
public IChunkSet getChunk(int chunkX, int chunkZ) {
|
||||
// TODO don't generate new Writeable MCA chunk
|
||||
System.out.println("TODO don't generate new Writeable MCA chunk");
|
||||
WritableMCAChunk tmp = new WritableMCAChunk();
|
||||
int bx = chunkX << 4;
|
||||
int bz = chunkZ << 4;
|
||||
write(tmp, bx, bx + 15, bz, bz + 15);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
public TextureUtil getRawTextureUtil() {
|
||||
@ -349,8 +364,8 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
}
|
||||
}
|
||||
|
||||
public void setBedrockId(int bedrockId) {
|
||||
this.primitives.bedrockId = bedrockId;
|
||||
public void setBedrock(BlockState bedrock) {
|
||||
this.primitives.bedrockOrdinal = bedrock.getOrdinalChar();
|
||||
}
|
||||
|
||||
public void setFloorThickness(int floorThickness) {
|
||||
@ -365,8 +380,8 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
this.primitives.waterHeight = waterHeight;
|
||||
}
|
||||
|
||||
public void setWaterId(int waterId) {
|
||||
this.primitives.waterId = waterId;
|
||||
public void setWater(BlockState water) {
|
||||
this.primitives.waterOrdinal = water.getOrdinalChar();
|
||||
}
|
||||
|
||||
public void setTextureRandomVariation(boolean randomVariation) {
|
||||
@ -390,10 +405,10 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
}
|
||||
|
||||
public void smooth(BlockVector2 min, BlockVector2 max, int radius, int iterations) {
|
||||
int snowLayer = BlockTypes.SNOW.getInternalId();
|
||||
int snowBlock = BlockTypes.SNOW_BLOCK.getInternalId();
|
||||
int snowLayer = BlockTypes.SNOW.getDefaultState().getOrdinalChar();
|
||||
int snowBlock = BlockTypes.SNOW_BLOCK.getDefaultState().getOrdinalChar();
|
||||
|
||||
int[] floor = this.floor.get();
|
||||
char[] floor = this.floor.get();
|
||||
byte[] heights = this.heights.get();
|
||||
|
||||
int width = getWidth();
|
||||
@ -421,7 +436,7 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
int index = zIndex + minX;
|
||||
for (int x = minX; x <= maxX; x++, index++, localIndex++) {
|
||||
int combined = floor[index];
|
||||
if (BlockTypes.getFromStateId(combined) == BlockTypes.SNOW) {
|
||||
if (BlockTypes.getFromStateOrdinal(combined) == BlockTypes.SNOW) {
|
||||
layers[localIndex] = (char) (((heights[index] & 0xFF) << 3) + (floor[index] >> BlockTypes.BIT_OFFSET) - 7);
|
||||
} else {
|
||||
layers[localIndex] = (char) ((heights[index] & 0xFF) << 3);
|
||||
@ -453,16 +468,15 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
|
||||
private final void setLayerHeight(int index, int blockHeight, int layerHeight) {
|
||||
int floorState = floor.get()[index];
|
||||
BlockType type = BlockTypes.getFromStateId(floorState);
|
||||
switch (type.getInternalId()) {
|
||||
switch (floorState) {
|
||||
case BlockID.SNOW:
|
||||
case BlockID.SNOW_BLOCK:
|
||||
if (layerHeight != 0) {
|
||||
this.heights.setByte(index, (byte) (blockHeight + 1));
|
||||
this.floor.setInt(index, BlockTypes.SNOW.getInternalId() + layerHeight);
|
||||
this.floor.setInt(index, BlockTypes.SNOW.getDefaultState().getOrdinalChar() + layerHeight);
|
||||
} else {
|
||||
this.heights.setByte(index, (byte) blockHeight);
|
||||
this.floor.setInt(index, BlockTypes.SNOW_BLOCK.getInternalId());
|
||||
this.floor.setInt(index, BlockTypes.SNOW_BLOCK.getDefaultState().getOrdinalChar());
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@ -479,16 +493,15 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
|
||||
private final void setLayerHeightRaw(int index, int blockHeight, int layerHeight) {
|
||||
int floorState = floor.get()[index];
|
||||
BlockType type = BlockTypes.getFromStateId(floorState);
|
||||
switch (type.getInternalId()) {
|
||||
switch (floorState) {
|
||||
case BlockID.SNOW:
|
||||
case BlockID.SNOW_BLOCK:
|
||||
if (layerHeight != 0) {
|
||||
this.heights.getByteArray()[index] = (byte) (blockHeight + 1);
|
||||
this.floor.getIntArray()[index] = BlockTypes.SNOW.getInternalId() + layerHeight;
|
||||
this.overlay.getCharArray()[index] = (char) (BlockTypes.SNOW.getDefaultState().getOrdinalChar() + layerHeight);
|
||||
} else {
|
||||
this.heights.getByteArray()[index] = (byte) blockHeight;
|
||||
this.floor.getIntArray()[index] = BlockTypes.SNOW_BLOCK.getInternalId();
|
||||
this.overlay.getCharArray()[index] = BlockTypes.SNOW_BLOCK.getDefaultState().getOrdinalChar();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@ -498,7 +511,7 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
}
|
||||
|
||||
private void smooth(BufferedImage img, Mask mask, boolean white, int radius, int iterations) {
|
||||
int[] floor = this.floor.get();
|
||||
char[] floor = this.floor.get();
|
||||
byte[] heights = this.heights.get();
|
||||
|
||||
long[] copy = new long[heights.length];
|
||||
@ -511,7 +524,7 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
for (int j = 0; j < iterations; j++) {
|
||||
for (int i = 0; i < heights.length; i++) {
|
||||
int combined = floor[i];
|
||||
if (BlockTypes.getFromStateId(combined) == BlockTypes.SNOW) {
|
||||
if (BlockTypes.getFromStateOrdinal(combined) == BlockTypes.SNOW) {
|
||||
layers[i] = (char) (((heights[i] & 0xFF) << 3) + (floor[i] >> BlockTypes.BIT_OFFSET) - 7);
|
||||
} else {
|
||||
layers[i] = (char) ((heights[i] & 0xFF) << 3);
|
||||
@ -704,7 +717,7 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
return setBlock(position.getBlockX(), position.getBlockY(), position.getBlockZ(), block);
|
||||
}
|
||||
|
||||
private boolean setBlock(int x, int y, int z, int combined) {
|
||||
private boolean setBlock(int x, int y, int z, char combined) {
|
||||
int index = z * getWidth() + x;
|
||||
if (index < 0 || index >= getArea()) return false;
|
||||
int height = heights.getByte(index) & 0xFF;
|
||||
@ -713,8 +726,8 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
floor.setInt(index, combined);
|
||||
return true;
|
||||
case 1:
|
||||
int mainId = main.getInt(index);
|
||||
int floorId = floor.getInt(index);
|
||||
char mainId = overlay.getChar(index);
|
||||
char floorId = overlay.getChar(index);
|
||||
floor.setInt(index, combined);
|
||||
|
||||
byte currentHeight = heights.getByte(index);
|
||||
@ -870,7 +883,7 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
|
||||
for (int cz = scz; cz <= ecz; cz++) {
|
||||
for (int cx = scx; cx <= ecx; cx++) {
|
||||
world.sendChunk(cx + OX, cz + OZ, 0);
|
||||
world.refreshChunk(cx + OX, cz + OZ);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -890,20 +903,19 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
return BiomeTypes.get(biomes.getByte(index));
|
||||
}
|
||||
|
||||
// @Override
|
||||
public int getCombinedId4Data(int x, int y, int z) throws FaweChunkLoadException {
|
||||
public int getOrdinal(int x, int y, int z) throws FaweChunkLoadException {
|
||||
int index = z * getWidth() + x;
|
||||
if (y < 0) return 0;
|
||||
if (index < 0 || index >= getArea() || x < 0 || x >= getWidth()) return 0;
|
||||
int height = heights.getByte(index) & 0xFF;
|
||||
if (y > height) {
|
||||
if (y == height + 1) {
|
||||
return overlay != null ? overlay.getInt(index) : 0;
|
||||
return overlay != null ? overlay.getChar(index) : 0;
|
||||
}
|
||||
if (blocks != null) {
|
||||
short chunkX = (short) (x >> 4);
|
||||
short chunkZ = (short) (z >> 4);
|
||||
int[][][] map = getChunkArray(chunkX, chunkZ);
|
||||
char[][][] map = getChunkArray(chunkX, chunkZ);
|
||||
if (map != null) {
|
||||
int combined = get(map, x, y, z);
|
||||
if (combined != 0) {
|
||||
@ -912,16 +924,16 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
}
|
||||
}
|
||||
if (y <= primitives.waterHeight) {
|
||||
return primitives.waterId << 4;
|
||||
return primitives.waterOrdinal;
|
||||
}
|
||||
return 0;
|
||||
} else if (y == height) {
|
||||
return floor.getInt(index);
|
||||
return overlay.getChar(index);
|
||||
} else {
|
||||
if (blocks != null) {
|
||||
short chunkX = (short) (x >> 4);
|
||||
short chunkZ = (short) (z >> 4);
|
||||
int[][][] map = getChunkArray(chunkX, chunkZ);
|
||||
char[][][] map = getChunkArray(chunkX, chunkZ);
|
||||
if (map != null) {
|
||||
int combined = get(map, x, y, z);
|
||||
if (combined != 0) {
|
||||
@ -929,13 +941,13 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
}
|
||||
}
|
||||
}
|
||||
return main.getInt(index);
|
||||
return overlay.getChar(index);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setBlock(int x, int y, int z, BlockStateHolder block) throws WorldEditException {
|
||||
return this.setBlock(x, y, z, block.getInternalId());
|
||||
return this.setBlock(x, y, z, block.getOrdinalChar());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -950,7 +962,7 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
|
||||
public BlockState getFloor(int x, int z) {
|
||||
int index = z * getWidth() + x;
|
||||
return BlockState.getFromInternalId(floor.getInt(index));
|
||||
return BlockState.getFromOrdinal(overlay.getChar(index));
|
||||
}
|
||||
|
||||
public int getHeight(int x, int z) {
|
||||
@ -964,19 +976,19 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
|
||||
public void setFloor(int x, int z, BlockStateHolder block) {
|
||||
int index = z * getWidth() + x;
|
||||
floor.setInt(index, block.getInternalId());
|
||||
floor.setInt(index, block.getOrdinalChar());
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState getBlock(int x, int y, int z) {
|
||||
return BlockState.getFromInternalId(getCombinedId4Data(x, y, z));
|
||||
return BlockState.getFromOrdinal(getOrdinal(x, y, z));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getNearestSurfaceLayer(int x, int z, int y, int minY, int maxY) {
|
||||
int index = z * getWidth() + x;
|
||||
if (index < 0 || index >= getArea()) index = Math.floorMod(index, getArea());
|
||||
return ((heights.getByte(index) & 0xFF) << 3) + (floor.getInt(index) & 0xFF) + 1;
|
||||
return ((heights.getByte(index) & 0xFF) << 3) + (overlay.getChar(index) & 0xFF) + 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -1017,9 +1029,7 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
|
||||
@Override
|
||||
public BufferedImage draw() {
|
||||
// TODO NOT IMPLEMENTED
|
||||
// return new HeightMapMCADrawer(this).draw();
|
||||
return null;
|
||||
return new CFIDrawer(this).draw();
|
||||
}
|
||||
|
||||
public void setBiomePriority(int value) {
|
||||
@ -1044,12 +1054,12 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
int maxIndex = getArea() - 1;
|
||||
|
||||
biomes.record(() -> floor.record(() -> main.record(() -> {
|
||||
int[] mainArr = main.get();
|
||||
int[] floorArr = floor.get();
|
||||
char[] mainArr = main.get();
|
||||
char[] floorArr = floor.get();
|
||||
byte[] biomesArr = biomes.get();
|
||||
|
||||
int index = 0;
|
||||
int[] buffer = new int[2];
|
||||
char[] buffer = new char[2];
|
||||
for (int z = 0; z < img.getHeight(); z++) {
|
||||
mutable.mutZ(z);
|
||||
for (int x = 0; x < img.getWidth(); x++, index++) {
|
||||
@ -1065,7 +1075,7 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
}
|
||||
int color = img.getRGB(x, z);
|
||||
if (textureUtil.getIsBlockCloserThanBiome(buffer, color, primitives.biomePriority)) {
|
||||
int combined = buffer[0];
|
||||
char combined = buffer[0];
|
||||
mainArr[index] = combined;
|
||||
floorArr[index] = combined;
|
||||
}
|
||||
@ -1079,23 +1089,20 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
if (img.getWidth() != getWidth() || img.getHeight() != getLength())
|
||||
throw new IllegalArgumentException("Input image dimensions do not match the current height map!");
|
||||
TextureUtil textureUtil = getTextureUtil();
|
||||
int widthIndex = img.getWidth() - 1;
|
||||
int heightIndex = img.getHeight() - 1;
|
||||
int maxIndex = getArea() - 1;
|
||||
|
||||
biomes.record(() -> floor.record(() -> main.record(() -> {
|
||||
int[] mainArr = main.get();
|
||||
int[] floorArr = floor.get();
|
||||
char[] mainArr = main.get();
|
||||
char[] floorArr = floor.get();
|
||||
byte[] biomesArr = biomes.get();
|
||||
|
||||
int[] buffer = new int[2];
|
||||
char[] buffer = new char[2];
|
||||
int index = 0;
|
||||
for (int y = 0; y < img.getHeight(); y++) {
|
||||
boolean yBiome = y > 0 && y < heightIndex;
|
||||
for (int x = 0; x < img.getWidth(); x++, index++) {
|
||||
int color = img.getRGB(x, y);
|
||||
if (textureUtil.getIsBlockCloserThanBiome(buffer, color, primitives.biomePriority)) {
|
||||
int combined = buffer[0];
|
||||
char combined = buffer[0];
|
||||
mainArr[index] = combined;
|
||||
floorArr[index] = combined;
|
||||
}
|
||||
@ -1135,8 +1142,8 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
TextureUtil textureUtil = getTextureUtil();
|
||||
|
||||
floor.record(() -> main.record(() -> {
|
||||
int[] mainArr = main.get();
|
||||
int[] floorArr = floor.get();
|
||||
char[] mainArr = main.get();
|
||||
char[] floorArr = floor.get();
|
||||
|
||||
int index = 0;
|
||||
for (int z = 0; z < getLength(); z++) {
|
||||
@ -1147,7 +1154,7 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
int color = img.getRGB(x, z);
|
||||
BlockType block = textureUtil.getNearestBlock(color);
|
||||
if (block != null) {
|
||||
int combined = block.getInternalId();
|
||||
char combined = block.getDefaultState().getOrdinalChar();
|
||||
mainArr[index] = combined;
|
||||
floorArr[index] = combined;
|
||||
}
|
||||
@ -1165,8 +1172,8 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
|
||||
|
||||
floor.record(() -> main.record(() -> {
|
||||
int[] mainArr = main.get();
|
||||
int[] floorArr = floor.get();
|
||||
char[] mainArr = main.get();
|
||||
char[] floorArr = floor.get();
|
||||
|
||||
int index = 0;
|
||||
for (int z = 0; z < getLength(); z++) {
|
||||
@ -1178,7 +1185,7 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
int color = img.getRGB(x, z);
|
||||
BlockType block = textureUtil.getNearestBlock(color);
|
||||
if (block != null) {
|
||||
int combined = block.getInternalId();
|
||||
char combined = block.getDefaultState().getOrdinalChar();
|
||||
mainArr[index] = combined;
|
||||
floorArr[index] = combined;
|
||||
} else {
|
||||
@ -1197,8 +1204,8 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
TextureUtil textureUtil = getTextureUtil();
|
||||
|
||||
floor.record(() -> main.record(() -> {
|
||||
int[] mainArr = main.get();
|
||||
int[] floorArr = floor.get();
|
||||
char[] mainArr = main.get();
|
||||
char[] floorArr = floor.get();
|
||||
|
||||
int index = 0;
|
||||
for (int z = 0; z < img.getHeight(); z++) {
|
||||
@ -1206,7 +1213,7 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
int color = img.getRGB(x, z);
|
||||
BlockType block = textureUtil.getNearestBlock(color);
|
||||
if (block != null) {
|
||||
int combined = block.getInternalId();
|
||||
char combined = block.getDefaultState().getOrdinalChar();
|
||||
mainArr[index] = combined;
|
||||
floorArr[index] = combined;
|
||||
} else {
|
||||
@ -1224,8 +1231,8 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
TextureUtil textureUtil = getTextureUtil();
|
||||
|
||||
floor.record(() -> main.record(() -> {
|
||||
int[] mainArr = main.get();
|
||||
int[] floorArr = floor.get();
|
||||
char[] mainArr = main.get();
|
||||
char[] floorArr = floor.get();
|
||||
|
||||
int index = 0;
|
||||
for (int y = 0; y < img.getHeight(); y++) {
|
||||
@ -1233,8 +1240,8 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
int color = img.getRGB(x, y);
|
||||
BlockType[] layer = textureUtil.getNearestLayer(color);
|
||||
if (layer != null) {
|
||||
floorArr[index] = layer[0].getInternalId();
|
||||
mainArr[index] = layer[1].getInternalId();
|
||||
floorArr[index] = layer[0].getDefaultState().getOrdinalChar();
|
||||
mainArr[index] = layer[1].getDefaultState().getOrdinalChar();
|
||||
}
|
||||
index++;
|
||||
}
|
||||
@ -1260,18 +1267,18 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
|
||||
public void setOverlay(BufferedImage img, Pattern pattern, boolean white) {
|
||||
if (pattern instanceof BlockStateHolder) {
|
||||
setOverlay(img, ((BlockStateHolder) pattern).getInternalId(), white);
|
||||
setOverlay(img, ((BlockStateHolder) pattern).getOrdinalChar(), white);
|
||||
} else if (pattern instanceof BlockType) {
|
||||
setOverlay(img, ((BlockType) pattern).getInternalId(), white);
|
||||
setOverlay(img, ((BlockType) pattern).getDefaultState().getOrdinalChar(), white);
|
||||
} else {
|
||||
if (img.getWidth() != getWidth() || img.getHeight() != getLength())
|
||||
throw new IllegalArgumentException("Input image dimensions do not match the current height map!");
|
||||
if (overlay == null) {
|
||||
overlay = new DifferentialArray<>(new int[getArea()]);
|
||||
overlay = new DifferentialArray<>(new char[getArea()]);
|
||||
}
|
||||
|
||||
overlay.record(() -> {
|
||||
int[] overlayArr = overlay.get();
|
||||
char[] overlayArr = overlay.get();
|
||||
int index = 0;
|
||||
for (int z = 0; z < getLength(); z++) {
|
||||
mutable.mutZ(z);
|
||||
@ -1281,7 +1288,7 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
.nextInt(256) <= height) {
|
||||
mutable.mutX(x);
|
||||
mutable.mutY(height);
|
||||
overlayArr[index] = pattern.apply(mutable).getInternalId();
|
||||
overlayArr[index] = pattern.apply(mutable).getOrdinalChar();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1292,14 +1299,14 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
|
||||
public void setMain(BufferedImage img, Pattern pattern, boolean white) {
|
||||
if (pattern instanceof BlockStateHolder) {
|
||||
setMain(img, ((BlockStateHolder) pattern).getInternalId(), white);
|
||||
setMain(img, ((BlockStateHolder) pattern).getOrdinalChar(), white);
|
||||
} else {
|
||||
if (img.getWidth() != getWidth() || img.getHeight() != getLength())
|
||||
throw new IllegalArgumentException("Input image dimensions do not match the current height map!");
|
||||
primitives.modifiedMain = true;
|
||||
|
||||
main.record(() -> {
|
||||
int[] mainArr = main.get();
|
||||
char[] mainArr = main.get();
|
||||
int index = 0;
|
||||
for (int z = 0; z < getLength(); z++) {
|
||||
mutable.mutZ(z);
|
||||
@ -1309,7 +1316,7 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
.nextInt(256) <= height) {
|
||||
mutable.mutX(x);
|
||||
mutable.mutY(height);
|
||||
mainArr[index] = pattern.apply(mutable).getInternalId();
|
||||
mainArr[index] = pattern.apply(mutable).getOrdinalChar();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1319,13 +1326,13 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
|
||||
public void setFloor(BufferedImage img, Pattern pattern, boolean white) {
|
||||
if (pattern instanceof BlockStateHolder) {
|
||||
setFloor(img, ((BlockStateHolder) pattern).getInternalId(), white);
|
||||
setFloor(img, ((BlockStateHolder) pattern).getOrdinalChar(), white);
|
||||
} else {
|
||||
if (img.getWidth() != getWidth() || img.getHeight() != getLength())
|
||||
throw new IllegalArgumentException("Input image dimensions do not match the current height map!");
|
||||
|
||||
floor.record(() -> {
|
||||
int[] floorArr = floor.get();
|
||||
char[] floorArr = floor.get();
|
||||
int index = 0;
|
||||
for (int z = 0; z < getLength(); z++) {
|
||||
mutable.mutZ(z);
|
||||
@ -1335,7 +1342,7 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
.nextInt(256) <= height) {
|
||||
mutable.mutX(x);
|
||||
mutable.mutY(height);
|
||||
floorArr[index] = pattern.apply(mutable).getInternalId();
|
||||
floorArr[index] = pattern.apply(mutable).getOrdinalChar();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1345,15 +1352,15 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
|
||||
public void setColumn(BufferedImage img, Pattern pattern, boolean white) {
|
||||
if (pattern instanceof BlockStateHolder) {
|
||||
setColumn(img, ((BlockStateHolder) pattern).getInternalId(), white);
|
||||
setColumn(img, ((BlockStateHolder) pattern).getOrdinalChar(), white);
|
||||
} else {
|
||||
if (img.getWidth() != getWidth() || img.getHeight() != getLength())
|
||||
throw new IllegalArgumentException("Input image dimensions do not match the current height map!");
|
||||
primitives.modifiedMain = true;
|
||||
|
||||
main.record(() -> floor.record(() -> {
|
||||
int[] floorArr = floor.get();
|
||||
int[] mainArr = main.get();
|
||||
char[] floorArr = floor.get();
|
||||
char[] mainArr = main.get();
|
||||
int index = 0;
|
||||
for (int z = 0; z < getLength(); z++) {
|
||||
mutable.mutZ(z);
|
||||
@ -1363,7 +1370,7 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
.nextInt(256) <= height) {
|
||||
mutable.mutX(x);
|
||||
mutable.mutY(height);
|
||||
int combined = pattern.apply(mutable).getInternalId();
|
||||
char combined = pattern.apply(mutable).getOrdinalChar();
|
||||
mainArr[index] = combined;
|
||||
floorArr[index] = combined;
|
||||
}
|
||||
@ -1375,10 +1382,10 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
|
||||
public void setOverlay(Mask mask, Pattern pattern) {
|
||||
if (pattern instanceof BlockStateHolder) {
|
||||
setOverlay(mask, ((BlockStateHolder) pattern).getInternalId());
|
||||
setOverlay(mask, ((BlockStateHolder) pattern).getOrdinalChar());
|
||||
} else {
|
||||
int index = 0;
|
||||
if (overlay == null) overlay = new DifferentialArray<>(new int[getArea()]);
|
||||
if (overlay == null) overlay = new DifferentialArray<>(new char[getArea()]);
|
||||
for (int z = 0; z < getLength(); z++) {
|
||||
mutable.mutZ(z);
|
||||
for (int x = 0; x < getWidth(); x++, index++) {
|
||||
@ -1386,7 +1393,7 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
mutable.mutX(x);
|
||||
mutable.mutY(y);
|
||||
if (mask.test(mutable)) {
|
||||
overlay.setInt(index, pattern.apply(mutable).getInternalId());
|
||||
overlay.setInt(index, pattern.apply(mutable).getOrdinalChar());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1395,7 +1402,7 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
|
||||
public void setFloor(Mask mask, Pattern pattern) {
|
||||
if (pattern instanceof BlockStateHolder) {
|
||||
setFloor(mask, ((BlockStateHolder) pattern).getInternalId());
|
||||
setFloor(mask, ((BlockStateHolder) pattern).getOrdinalChar());
|
||||
} else {
|
||||
int index = 0;
|
||||
for (int z = 0; z < getLength(); z++) {
|
||||
@ -1405,7 +1412,7 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
mutable.mutX(x);
|
||||
mutable.mutY(y);
|
||||
if (mask.test(mutable)) {
|
||||
floor.setInt(index, pattern.apply(mutable).getInternalId());
|
||||
floor.setInt(index, pattern.apply(mutable).getOrdinalChar());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1414,7 +1421,7 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
|
||||
public void setMain(Mask mask, Pattern pattern) {
|
||||
if (pattern instanceof BlockStateHolder) {
|
||||
setMain(mask, ((BlockStateHolder) pattern).getInternalId());
|
||||
setMain(mask, ((BlockStateHolder) pattern).getOrdinalChar());
|
||||
} else {
|
||||
primitives.modifiedMain = true;
|
||||
int index = 0;
|
||||
@ -1425,7 +1432,7 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
mutable.mutX(x);
|
||||
mutable.mutY(y);
|
||||
if (mask.test(mutable)) {
|
||||
main.setInt(index, pattern.apply(mutable).getInternalId());
|
||||
main.setInt(index, pattern.apply(mutable).getOrdinalChar());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1434,7 +1441,7 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
|
||||
public void setColumn(Mask mask, Pattern pattern) {
|
||||
if (pattern instanceof BlockStateHolder) {
|
||||
setColumn(mask, ((BlockStateHolder) pattern).getInternalId());
|
||||
setColumn(mask, ((BlockStateHolder) pattern).getOrdinalChar());
|
||||
} else {
|
||||
primitives.modifiedMain = true;
|
||||
int index = 0;
|
||||
@ -1445,7 +1452,7 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
mutable.mutX(x);
|
||||
mutable.mutY(y);
|
||||
if (mask.test(mutable)) {
|
||||
int combined = pattern.apply(mutable).getInternalId();
|
||||
int combined = pattern.apply(mutable).getOrdinalChar();
|
||||
floor.setInt(index, combined);
|
||||
main.setInt(index, combined);
|
||||
}
|
||||
@ -1460,10 +1467,10 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
|
||||
public void setFloor(Pattern value) {
|
||||
if (value instanceof BlockStateHolder) {
|
||||
setFloor(((BlockStateHolder) value).getInternalId());
|
||||
setFloor(((BlockStateHolder) value).getOrdinalChar());
|
||||
} else {
|
||||
floor.record(() -> {
|
||||
int[] floorArr = floor.get();
|
||||
char[] floorArr = floor.get();
|
||||
int index = 0;
|
||||
for (int z = 0; z < getLength(); z++) {
|
||||
mutable.mutZ(z);
|
||||
@ -1471,7 +1478,7 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
int y = heights.getByte(index) & 0xFF;
|
||||
mutable.mutX(x);
|
||||
mutable.mutY(y);
|
||||
floorArr[index] = value.apply(mutable).getInternalId();
|
||||
floorArr[index] = value.apply(mutable).getOrdinalChar();
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -1480,11 +1487,11 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
|
||||
public void setColumn(Pattern value) {
|
||||
if (value instanceof BlockStateHolder) {
|
||||
setColumn(((BlockStateHolder) value).getInternalId());
|
||||
setColumn(((BlockStateHolder) value).getOrdinalChar());
|
||||
} else {
|
||||
main.record(() -> floor.record(() -> {
|
||||
int[] floorArr = floor.get();
|
||||
int[] mainArr = main.get();
|
||||
char[] floorArr = floor.get();
|
||||
char[] mainArr = main.get();
|
||||
int index = 0;
|
||||
for (int z = 0; z < getLength(); z++) {
|
||||
mutable.mutZ(z);
|
||||
@ -1492,7 +1499,7 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
int y = heights.getByte(index) & 0xFF;
|
||||
mutable.mutX(x);
|
||||
mutable.mutY(y);
|
||||
int combined = value.apply(mutable).getInternalId();
|
||||
char combined = value.apply(mutable).getOrdinalChar();
|
||||
mainArr[index] = combined;
|
||||
floorArr[index] = combined;
|
||||
}
|
||||
@ -1503,10 +1510,10 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
|
||||
public void setMain(Pattern value) {
|
||||
if (value instanceof BlockStateHolder) {
|
||||
setMain(((BlockStateHolder) value).getInternalId());
|
||||
setMain(((BlockStateHolder) value).getOrdinalChar());
|
||||
} else {
|
||||
main.record(() -> {
|
||||
int[] mainArr = main.get();
|
||||
char[] mainArr = main.get();
|
||||
int index = 0;
|
||||
for (int z = 0; z < getLength(); z++) {
|
||||
mutable.mutZ(z);
|
||||
@ -1514,7 +1521,7 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
int y = heights.getByte(index) & 0xFF;
|
||||
mutable.mutX(x);
|
||||
mutable.mutY(y);
|
||||
mainArr[index] = value.apply(mutable).getInternalId();
|
||||
mainArr[index] = value.apply(mutable).getOrdinalChar();
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -1522,12 +1529,12 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
}
|
||||
|
||||
public void setOverlay(Pattern value) {
|
||||
if (overlay == null) overlay = new DifferentialArray<>(new int[getArea()]);
|
||||
if (overlay == null) overlay = new DifferentialArray<>(new char[getArea()]);
|
||||
if (value instanceof BlockStateHolder) {
|
||||
setOverlay(((BlockStateHolder) value).getInternalId());
|
||||
setOverlay(((BlockStateHolder) value).getOrdinalChar());
|
||||
} else {
|
||||
overlay.record(() -> {
|
||||
int[] overlayArr = overlay.get();
|
||||
char[] overlayArr = overlay.get();
|
||||
int index = 0;
|
||||
for (int z = 0; z < getLength(); z++) {
|
||||
mutable.mutZ(z);
|
||||
@ -1535,7 +1542,7 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
int y = heights.getByte(index) & 0xFF;
|
||||
mutable.mutX(x);
|
||||
mutable.mutY(y);
|
||||
overlayArr[index] = value.apply(mutable).getInternalId();
|
||||
overlayArr[index] = value.apply(mutable).getOrdinalChar();
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -1567,16 +1574,16 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
public WritableMCAChunk write(WritableMCAChunk chunk, int csx, int cex, int csz, int cez) {
|
||||
byte[] heights = this.heights.get();
|
||||
byte[] biomes = this.biomes.get();
|
||||
int[] main = this.main.get();
|
||||
int[] floor = this.floor.get();
|
||||
int[] overlay = this.overlay != null ? this.overlay.get() : null;
|
||||
char[] main = this.main.get();
|
||||
char[] floor = this.floor.get();
|
||||
char[] overlay = this.overlay != null ? this.overlay.get() : null;
|
||||
try {
|
||||
int[] indexes = FaweCache.IMP.INDEX_STORE.get();
|
||||
|
||||
int index;
|
||||
int maxY = 0;
|
||||
int minY = Integer.MAX_VALUE;
|
||||
int[] heightMap = chunk.biomes;
|
||||
byte[] heightMap = chunk.biomes;
|
||||
int globalIndex;
|
||||
for (int z = csz; z <= cez; z++) {
|
||||
globalIndex = z * getWidth() + csx;
|
||||
@ -1584,7 +1591,7 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
for (int x = csx; x <= cex; x++, index++, globalIndex++) {
|
||||
indexes[index] = globalIndex;
|
||||
int height = heights[globalIndex] & 0xFF;
|
||||
heightMap[index] = height;
|
||||
heightMap[index] = (byte) height;
|
||||
maxY = Math.max(maxY, height);
|
||||
minY = Math.min(minY, height);
|
||||
}
|
||||
@ -1599,7 +1606,7 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
}
|
||||
if (primitives.waterHeight != 0) {
|
||||
int maxIndex = primitives.waterHeight << 8;
|
||||
Arrays.fill(chunk.blocks, 0, maxIndex, primitives.waterId);
|
||||
Arrays.fill(chunk.blocks, 0, maxIndex, primitives.waterOrdinal);
|
||||
}
|
||||
|
||||
if (primitives.modifiedMain) { // If the main block is modified, we can't short circuit this
|
||||
@ -1607,7 +1614,7 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
index = (z & 15) << 4;
|
||||
for (int x = csx; x <= cex; x++, index++) {
|
||||
globalIndex = indexes[index];
|
||||
int mainCombined = main[globalIndex];
|
||||
char mainCombined = main[globalIndex];
|
||||
for (int y = 0; y < minY; y++) {
|
||||
chunk.blocks[index + (y << 8)] = mainCombined;
|
||||
}
|
||||
@ -1615,7 +1622,7 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
}
|
||||
} else {
|
||||
int maxIndex = minY << 8;
|
||||
Arrays.fill(chunk.blocks, 0, maxIndex, BlockID.STONE);
|
||||
Arrays.fill(chunk.blocks, 0, maxIndex, (char) BlockID.STONE);
|
||||
}
|
||||
|
||||
final boolean hasFloorThickness = primitives.floorThickness != 0 || primitives.worldThickness != 0;
|
||||
@ -1630,13 +1637,13 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
index = (z & 15) << 4;
|
||||
for (int x = csx; x <= cex; x++, index++) {
|
||||
globalIndex = indexes[index];
|
||||
int height = heightMap[index];
|
||||
int height = heightMap[index] & 0xFF;
|
||||
int maxMainY = height;
|
||||
int minMainY = minY;
|
||||
|
||||
int mainCombined = main[globalIndex];
|
||||
char mainCombined = main[globalIndex];
|
||||
|
||||
int floorCombined = floor[globalIndex];
|
||||
char floorCombined = floor[globalIndex];
|
||||
if (hasFloorThickness) {
|
||||
if (x > 0) maxMainY = Math.min(heights[globalIndex - 1] & 0xFF, maxMainY);
|
||||
if (x < getWidth() - 1) maxMainY = Math.min(heights[globalIndex + 1] & 0xFF, maxMainY);
|
||||
@ -1671,33 +1678,33 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
}
|
||||
|
||||
if (hasOverlay) {
|
||||
int overlayCombined = overlay[globalIndex];
|
||||
char overlayCombined = overlay[globalIndex];
|
||||
int overlayIndex = index + (height + 1 << 8);
|
||||
chunk.blocks[overlayIndex] = overlayCombined;
|
||||
}
|
||||
|
||||
if (primitives.bedrockId != 0) {
|
||||
chunk.blocks[index] = primitives.bedrockId;
|
||||
if (primitives.bedrockOrdinal != 0) {
|
||||
chunk.blocks[index] = primitives.bedrockOrdinal;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int[][][] localBlocks = getChunkArray(chunk.getX(), chunk.getZ());
|
||||
char[][][] localBlocks = getChunkArray(chunk.getX(), chunk.getZ());
|
||||
if (localBlocks != null) {
|
||||
index = 0;
|
||||
for (int layer = 0; layer < 16; layer++) {
|
||||
int by = layer << 4;
|
||||
int ty = by + 15;
|
||||
for (int y = by; y <= ty; y++, index += 256) {
|
||||
int[][] yBlocks = localBlocks[y];
|
||||
char[][] yBlocks = localBlocks[y];
|
||||
if (yBlocks != null) {
|
||||
chunk.hasSections[layer] = true;
|
||||
for (int z = 0; z < yBlocks.length; z++) {
|
||||
int[] zBlocks = yBlocks[z];
|
||||
char[] zBlocks = yBlocks[z];
|
||||
if (zBlocks != null) {
|
||||
int zIndex = index + (z << 4);
|
||||
for (int x = 0; x < zBlocks.length; x++, zIndex++) {
|
||||
int combined = zBlocks[x];
|
||||
char combined = zBlocks[x];
|
||||
if (combined == 0) continue;
|
||||
chunk.blocks[zIndex] = combined;
|
||||
}
|
||||
@ -1719,24 +1726,24 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
return chunk;
|
||||
}
|
||||
|
||||
private void setUnsafe(int[][][] map, int combined, int x, int y, int z) {
|
||||
int[][] yMap = map[y];
|
||||
private void setUnsafe(char[][][] map, char combined, int x, int y, int z) {
|
||||
char[][] yMap = map[y];
|
||||
if (yMap == null) {
|
||||
map[y] = yMap = new int[16][];
|
||||
map[y] = yMap = new char[16][];
|
||||
}
|
||||
int[] zMap = yMap[z];
|
||||
char[] zMap = yMap[z];
|
||||
if (zMap == null) {
|
||||
yMap[z] = zMap = new int[16];
|
||||
yMap[z] = zMap = new char[16];
|
||||
}
|
||||
zMap[x] = combined;
|
||||
}
|
||||
|
||||
private int get(int[][][] map, int x, int y, int z) {
|
||||
int[][] yMap = map[y];
|
||||
private int get(char[][][] map, int x, int y, int z) {
|
||||
char[][] yMap = map[y];
|
||||
if (yMap == null) {
|
||||
return 0;
|
||||
}
|
||||
int[] zMap = yMap[z & 15];
|
||||
char[] zMap = yMap[z & 15];
|
||||
if (zMap == null) {
|
||||
return 0;
|
||||
}
|
||||
@ -1745,7 +1752,7 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
|
||||
private void setOverlay(Mask mask, int combined) {
|
||||
int index = 0;
|
||||
if (overlay == null) overlay = new DifferentialArray<>(new int[getArea()]);
|
||||
if (overlay == null) overlay = new DifferentialArray<>(new char[getArea()]);
|
||||
for (int z = 0; z < getLength(); z++) {
|
||||
mutable.mutZ(z);
|
||||
for (int x = 0; x < getWidth(); x++, index++) {
|
||||
@ -1807,29 +1814,29 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
}
|
||||
}
|
||||
|
||||
private void setFloor(int value) {
|
||||
private void setFloor(char value) {
|
||||
floor.record(() -> Arrays.fill(floor.get(), value));
|
||||
}
|
||||
|
||||
private void setColumn(int value) {
|
||||
private void setColumn(char value) {
|
||||
setFloor(value);
|
||||
setMain(value);
|
||||
}
|
||||
|
||||
private void setMain(int value) {
|
||||
private void setMain(char value) {
|
||||
primitives.modifiedMain = true;
|
||||
main.record(() -> Arrays.fill(main.get(), value));
|
||||
}
|
||||
|
||||
private void setOverlay(int value) {
|
||||
if (overlay == null) overlay = new DifferentialArray<>(new int[getArea()]);
|
||||
private void setOverlay(char value) {
|
||||
if (overlay == null) overlay = new DifferentialArray<>(new char[getArea()]);
|
||||
overlay.record(() -> Arrays.fill(overlay.get(), value));
|
||||
}
|
||||
|
||||
private void setOverlay(BufferedImage img, int combined, boolean white) {
|
||||
private void setOverlay(BufferedImage img, char combined, boolean white) {
|
||||
if (img.getWidth() != getWidth() || img.getHeight() != getLength())
|
||||
throw new IllegalArgumentException("Input image dimensions do not match the current height map!");
|
||||
if (overlay == null) overlay = new DifferentialArray<>(new int[getArea()]);
|
||||
if (overlay == null) overlay = new DifferentialArray<>(new char[getArea()]);
|
||||
|
||||
overlay.record(() -> {
|
||||
int index = 0;
|
||||
@ -1845,7 +1852,7 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
});
|
||||
}
|
||||
|
||||
private void setMain(BufferedImage img, int combined, boolean white) {
|
||||
private void setMain(BufferedImage img, char combined, boolean white) {
|
||||
if (img.getWidth() != getWidth() || img.getHeight() != getLength())
|
||||
throw new IllegalArgumentException("Input image dimensions do not match the current height map!");
|
||||
primitives.modifiedMain = true;
|
||||
@ -1864,7 +1871,7 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
});
|
||||
}
|
||||
|
||||
private void setFloor(BufferedImage img, int combined, boolean white) {
|
||||
private void setFloor(BufferedImage img, char combined, boolean white) {
|
||||
if (img.getWidth() != getWidth() || img.getHeight() != getLength())
|
||||
throw new IllegalArgumentException("Input image dimensions do not match the current height map!");
|
||||
|
||||
@ -1882,7 +1889,7 @@ public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Dr
|
||||
});
|
||||
}
|
||||
|
||||
private void setColumn(BufferedImage img, int combined, boolean white) {
|
||||
private void setColumn(BufferedImage img, char combined, boolean white) {
|
||||
if (img.getWidth() != getWidth() || img.getHeight() != getLength())
|
||||
throw new IllegalArgumentException("Input image dimensions do not match the current height map!");
|
||||
primitives.modifiedMain = true;
|
||||
|
@ -84,7 +84,7 @@ public abstract class MCAWriter implements Extent {
|
||||
@Override
|
||||
protected WritableMCAChunk initialValue() {
|
||||
WritableMCAChunk chunk = new WritableMCAChunk();
|
||||
Arrays.fill(chunk.blocks, BlockID.AIR);
|
||||
Arrays.fill(chunk.blocks, (char) BlockID.AIR);
|
||||
// Arrays.fill(chunk.skyLight, (byte) 255);
|
||||
return chunk;
|
||||
}
|
||||
@ -142,11 +142,12 @@ public abstract class MCAWriter implements Extent {
|
||||
pool.submit(() -> {
|
||||
try {
|
||||
WritableMCAChunk chunk = chunkStore.get();
|
||||
chunk.clear(fcx, fcz);
|
||||
chunk.reset();
|
||||
chunk.setPosition(fcx, fcz);
|
||||
chunk = write(chunk, csx, cex, csz, cez);
|
||||
if (chunk != null) {
|
||||
// Generation offset
|
||||
chunk.setLoc( fcx + (getOffsetX() >> 4), fcz + (getOffsetZ() >> 4));
|
||||
chunk.setPosition( fcx + (getOffsetX() >> 4), fcz + (getOffsetZ() >> 4));
|
||||
|
||||
// Compress
|
||||
byte[] bytes = chunk.toBytes(byteStore1.get());
|
||||
|
@ -1,39 +1,44 @@
|
||||
package com.boydti.fawe.object.brush.visualization.cfi;
|
||||
|
||||
import com.boydti.fawe.FaweCache;
|
||||
import com.boydti.fawe.beta.IChunkSet;
|
||||
import com.boydti.fawe.object.collection.BitArray4096;
|
||||
import com.boydti.fawe.object.collection.BlockVector3ChunkMap;
|
||||
import com.boydti.fawe.object.io.FastByteArrayOutputStream;
|
||||
import com.boydti.fawe.util.MathMan;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.jnbt.ListTag;
|
||||
import com.sk89q.jnbt.NBTConstants;
|
||||
import com.sk89q.jnbt.NBTOutputStream;
|
||||
import com.sk89q.worldedit.math.BlockVector2;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.registry.state.Property;
|
||||
import com.sk89q.worldedit.world.biome.BiomeType;
|
||||
import com.sk89q.worldedit.world.biome.BiomeTypes;
|
||||
import com.sk89q.worldedit.world.block.BlockID;
|
||||
import com.sk89q.worldedit.world.block.BlockState;
|
||||
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
||||
import com.sk89q.worldedit.world.block.BlockType;
|
||||
import com.sk89q.worldedit.world.block.BlockTypes;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
public class WritableMCAChunk {
|
||||
public class WritableMCAChunk implements IChunkSet {
|
||||
public final boolean[] hasSections = new boolean[16];
|
||||
public final byte[] skyLight = new byte[65536];
|
||||
public final byte[] blockLight = new byte[65536];
|
||||
|
||||
public boolean hasBiomes = false;
|
||||
public final int[] biomes = new int[256];
|
||||
public final byte[] biomes = new byte[256];
|
||||
|
||||
public final int[] blocks = new int[65536];
|
||||
public final char[] blocks = new char[65536];
|
||||
|
||||
public Map<Short, CompoundTag> tiles = new HashMap<>();
|
||||
public BlockVector3ChunkMap<CompoundTag> tiles = new BlockVector3ChunkMap<CompoundTag>();
|
||||
public Map<UUID, CompoundTag> entities = new HashMap<>();
|
||||
public long inhabitedTime = System.currentTimeMillis();
|
||||
public long lastUpdate;
|
||||
@ -54,14 +59,18 @@ public class WritableMCAChunk {
|
||||
return chunkZ;
|
||||
}
|
||||
|
||||
public void setLoc(int X, int Z) {
|
||||
@Override
|
||||
public boolean hasSection(int layer) {
|
||||
return hasSections[layer];
|
||||
}
|
||||
|
||||
public void setPosition(int X, int Z) {
|
||||
this.chunkX = X;
|
||||
this.chunkZ = Z;
|
||||
}
|
||||
|
||||
public void clear(int X, int Z) {
|
||||
this.chunkX = X;
|
||||
this.chunkZ = Z;
|
||||
@Override
|
||||
public IChunkSet reset() {
|
||||
if (!tiles.isEmpty()) {
|
||||
tiles.clear();
|
||||
}
|
||||
@ -76,6 +85,7 @@ public class WritableMCAChunk {
|
||||
blocks[i] = BlockID.AIR;
|
||||
}
|
||||
Arrays.fill(hasSections, false);
|
||||
return this;
|
||||
}
|
||||
|
||||
public void write(NBTOutputStream nbtOut) throws IOException {
|
||||
@ -192,13 +202,13 @@ public class WritableMCAChunk {
|
||||
}
|
||||
|
||||
|
||||
out.writeNamedTagName("BlockLight", NBTConstants.TYPE_BYTE_ARRAY);
|
||||
out.writeInt(2048);
|
||||
out.write(blockLight, layer << 11, 1 << 11);
|
||||
|
||||
out.writeNamedTagName("SkyLight", NBTConstants.TYPE_BYTE_ARRAY);
|
||||
out.writeInt(2048);
|
||||
out.write(skyLight, layer << 11, 1 << 11);
|
||||
// out.writeNamedTagName("BlockLight", NBTConstants.TYPE_BYTE_ARRAY);
|
||||
// out.writeInt(2048);
|
||||
// out.write(blockLight, layer << 11, 1 << 11);
|
||||
//
|
||||
// out.writeNamedTagName("SkyLight", NBTConstants.TYPE_BYTE_ARRAY);
|
||||
// out.writeInt(2048);
|
||||
// out.write(skyLight, layer << 11, 1 << 11);
|
||||
|
||||
|
||||
out.writeEndTag();
|
||||
@ -250,6 +260,15 @@ public class WritableMCAChunk {
|
||||
return deleted;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
if (deleted) return true;
|
||||
for (boolean hasSection : hasSections) {
|
||||
if (hasSection) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean isModified() {
|
||||
return modified != 0;
|
||||
}
|
||||
@ -272,14 +291,17 @@ public class WritableMCAChunk {
|
||||
return bitMask;
|
||||
}
|
||||
|
||||
public void setTile(int x, int y, int z, CompoundTag tile) {
|
||||
@Override
|
||||
public boolean setTile(int x, int y, int z, CompoundTag tile) {
|
||||
setModified();
|
||||
short pair = MathMan.tripleBlockCoord(x, y, z);
|
||||
if (tile != null) {
|
||||
tiles.put(pair, tile);
|
||||
tiles.put(x, y, z, tile);
|
||||
} else {
|
||||
tiles.remove(pair);
|
||||
if (tiles.remove(x, y, z) == null) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void setEntity(CompoundTag entityTag) {
|
||||
@ -289,17 +311,39 @@ public class WritableMCAChunk {
|
||||
entities.put(new UUID(most, least), entityTag);
|
||||
}
|
||||
|
||||
public void setBiome(int x, int z, BiomeType biome) {
|
||||
@Override
|
||||
public BiomeType getBiomeType(int x, int z) {
|
||||
return BiomeTypes.get(this.biomes[(z << 4) | x] & 0xFF);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BiomeType[] getBiomes() {
|
||||
BiomeType[] tmp = new BiomeType[256];
|
||||
for (int i = 0; i < 256; i++) {
|
||||
tmp[i] = BiomeTypes.get(this.biomes[i] & 0xFF);
|
||||
}
|
||||
return tmp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setBiome(BlockVector2 pos, BiomeType biome) {
|
||||
return this.setBiome(pos.getX(), 0, pos.getZ(), biome);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setBiome(int x, int y, int z, BiomeType biome) {
|
||||
setModified();
|
||||
biomes[x + (z << 4)] = biome.getInternalId();
|
||||
biomes[x + (z << 4)] = (byte) biome.getInternalId();
|
||||
return true;
|
||||
}
|
||||
|
||||
public Set<CompoundTag> getEntities() {
|
||||
return new HashSet<>(entities.values());
|
||||
}
|
||||
|
||||
public Map<Short, CompoundTag> getTiles() {
|
||||
return tiles == null ? new HashMap<>() : tiles;
|
||||
@Override
|
||||
public Map<BlockVector3, CompoundTag> getTiles() {
|
||||
return tiles == null ? Collections.emptyMap() : tiles;
|
||||
}
|
||||
|
||||
public CompoundTag getTile(int x, int y, int z) {
|
||||
@ -310,94 +354,51 @@ public class WritableMCAChunk {
|
||||
return tiles.get(pair);
|
||||
}
|
||||
|
||||
public boolean doesSectionExist(int cy) {
|
||||
return hasSections[cy];
|
||||
}
|
||||
|
||||
private final int getIndex(int x, int y, int z) {
|
||||
return x | (z << 4) | (y << 8);
|
||||
}
|
||||
|
||||
public int getBlockCombinedId(int x, int y, int z) {
|
||||
public int getBlockOrdinal(int x, int y, int z) {
|
||||
return blocks[x | (z << 4) | (y << 8)];
|
||||
}
|
||||
|
||||
public BiomeType[] getBiomeArray() {
|
||||
return null;
|
||||
@Override
|
||||
public BlockState getBlock(int x, int y, int z) {
|
||||
int ordinal = getBlockOrdinal(x, y, z);
|
||||
return BlockState.getFromOrdinal(ordinal);
|
||||
}
|
||||
|
||||
public Set<UUID> getEntityRemoves() {
|
||||
return new HashSet<>();
|
||||
}
|
||||
|
||||
public void setSkyLight(int x, int y, int z, int value) {
|
||||
setNibble(getIndex(x, y, z), skyLight, value);
|
||||
@Override
|
||||
public boolean setBlock(int x, int y, int z, BlockStateHolder holder) {
|
||||
setBlock(x, y, z, holder.getOrdinalChar());
|
||||
holder.applyTileEntity(this, x, y, z);
|
||||
return true;
|
||||
}
|
||||
|
||||
public void setBlockLight(int x, int y, int z, int value) {
|
||||
setNibble(getIndex(x, y, z), blockLight, value);
|
||||
}
|
||||
|
||||
public int getSkyLight(int x, int y, int z) {
|
||||
if (!hasSections[y >> 4]) {
|
||||
return 0;
|
||||
}
|
||||
return getNibble(getIndex(x, y, z), skyLight);
|
||||
}
|
||||
|
||||
public int getBlockLight(int x, int y, int z) {
|
||||
if (!hasSections[y >> 4]) {
|
||||
return 0;
|
||||
}
|
||||
return getNibble(getIndex(x, y, z), blockLight);
|
||||
}
|
||||
|
||||
public void setFullbright() {
|
||||
for (int layer = 0; layer < 16; layer++) {
|
||||
if (hasSections[layer]) {
|
||||
Arrays.fill(skyLight, layer << 7, ((layer + 1) << 7), (byte) 255);
|
||||
}
|
||||
@Override
|
||||
public void setBlocks(int layer, char[] data) {
|
||||
int offset = layer << 12;
|
||||
for (int i = 0; i < 4096; i++) {
|
||||
blocks[offset + i] = data[i];
|
||||
}
|
||||
}
|
||||
|
||||
public void removeLight() {
|
||||
for (int i = 0; i < 16; i++) {
|
||||
removeLight(i);
|
||||
@Override
|
||||
public char[] getArray(int layer) {
|
||||
char[] tmp = FaweCache.IMP.SECTION_BITS_TO_CHAR.get();
|
||||
int offset = layer << 12;
|
||||
for (int i = 0; i < 4096; i++) {
|
||||
tmp[i] = blocks[offset + i];
|
||||
}
|
||||
return tmp;
|
||||
}
|
||||
|
||||
public void removeLight(int i) {
|
||||
if (hasSections[i]) {
|
||||
Arrays.fill(skyLight, i << 7, ((i + 1) << 7), (byte) 0);
|
||||
Arrays.fill(blockLight, i << 7, ((i + 1) << 7), (byte) 0);
|
||||
}
|
||||
}
|
||||
|
||||
public int getNibble(int index, byte[] array) {
|
||||
int indexShift = index >> 1;
|
||||
if ((index & 1) == 0) {
|
||||
return array[indexShift] & 15;
|
||||
} else {
|
||||
return array[indexShift] >> 4 & 15;
|
||||
}
|
||||
}
|
||||
|
||||
public void setNibble(int index, byte[] array, int value) {
|
||||
int indexShift = index >> 1;
|
||||
byte existing = array[indexShift];
|
||||
int valueShift = value << 4;
|
||||
if (existing == value + valueShift) {
|
||||
return;
|
||||
}
|
||||
if ((index & 1) == 0) {
|
||||
array[indexShift] = (byte) (existing & 240 | value);
|
||||
} else {
|
||||
array[indexShift] = (byte) (existing & 15 | valueShift);
|
||||
}
|
||||
}
|
||||
|
||||
public void setBlock(int x, int y, int z, int combinedId) {
|
||||
blocks[getIndex(x, y, z)] = combinedId;
|
||||
public void setBlock(int x, int y, int z, char ordinal) {
|
||||
blocks[getIndex(x, y, z)] = ordinal;
|
||||
}
|
||||
|
||||
public void setBiome(BiomeType biome) {
|
||||
@ -407,4 +408,9 @@ public class WritableMCAChunk {
|
||||
public void removeEntity(UUID uuid) {
|
||||
entities.remove(uuid);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean trim(boolean aggressive) {
|
||||
return isEmpty();
|
||||
}
|
||||
}
|
||||
|
@ -47,6 +47,11 @@ public class BlockVector3ChunkMap<T> implements Map<BlockVector3, T>, IAdaptedMa
|
||||
return map.put(key, value);
|
||||
}
|
||||
|
||||
public T remove(int x, int y, int z) {
|
||||
short key = MathMan.tripleBlockCoord(x, y, z);
|
||||
return map.remove(key);
|
||||
}
|
||||
|
||||
public boolean contains(int x, int y, int z) {
|
||||
short key = MathMan.tripleBlockCoord(x, y, z);
|
||||
return map.containsKey(key);
|
||||
|
@ -265,9 +265,9 @@ public final class DifferentialArray<T> implements DifferentialCollection<T> {
|
||||
return dataBytes[index];
|
||||
}
|
||||
|
||||
// public char getChar(int index) {
|
||||
// return dataChars[index];
|
||||
// }
|
||||
public char getChar(int index) {
|
||||
return dataChars[index];
|
||||
}
|
||||
|
||||
public int getInt(int index) {
|
||||
return dataInts[index];
|
||||
|
@ -9,12 +9,12 @@ import java.lang.reflect.Array;
|
||||
* Records changes made through the {@link #set(int, int, int, int)} method<br/>
|
||||
* Changes are not recorded if you edit the raw data
|
||||
*/
|
||||
public final class DifferentialBlockBuffer implements DifferentialCollection<int[][][][][]> {
|
||||
public final class DifferentialBlockBuffer implements DifferentialCollection<char[][][][][]> {
|
||||
|
||||
private final int width, length;
|
||||
private final int t1, t2;
|
||||
private int[][][][][] data;
|
||||
private int[][][][][] changes;
|
||||
private char[][][][][] data;
|
||||
private char[][][][][] changes;
|
||||
|
||||
public DifferentialBlockBuffer(int width, int length) {
|
||||
this.width = width;
|
||||
@ -24,7 +24,7 @@ public final class DifferentialBlockBuffer implements DifferentialCollection<int
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[][][][][] get() {
|
||||
public char[][][][][] get() {
|
||||
return data;
|
||||
}
|
||||
|
||||
@ -116,72 +116,72 @@ public final class DifferentialBlockBuffer implements DifferentialCollection<int
|
||||
changes = null;
|
||||
}
|
||||
|
||||
public void set(int x, int y, int z, int combined) {
|
||||
public void set(int x, int y, int z, char combined) {
|
||||
if (combined == 0) combined = 1;
|
||||
int localX = x & 15;
|
||||
int localZ = z & 15;
|
||||
int chunkX = x >> 4;
|
||||
int chunkZ = z >> 4;
|
||||
if (data == null) {
|
||||
data = new int[t1][][][][];
|
||||
changes = new int[0][][][][];
|
||||
data = new char[t1][][][][];
|
||||
changes = new char[0][][][][];
|
||||
}
|
||||
|
||||
int[][][][] arr = data[chunkZ];
|
||||
char[][][][] arr = data[chunkZ];
|
||||
if (arr == null) {
|
||||
arr = data[chunkZ] = new int[t2][][][];
|
||||
arr = data[chunkZ] = new char[t2][][][];
|
||||
}
|
||||
int[][][] arr2 = arr[chunkX];
|
||||
char[][][] arr2 = arr[chunkX];
|
||||
if (arr2 == null) {
|
||||
arr2 = arr[chunkX] = new int[256][][];
|
||||
arr2 = arr[chunkX] = new char[256][][];
|
||||
}
|
||||
|
||||
int[][] yMap = arr2[y];
|
||||
char[][] yMap = arr2[y];
|
||||
if (yMap == null) {
|
||||
arr2[y] = yMap = new int[16][];
|
||||
arr2[y] = yMap = new char[16][];
|
||||
}
|
||||
boolean newSection;
|
||||
int current;
|
||||
int[] zMap = yMap[localZ];
|
||||
char[] zMap = yMap[localZ];
|
||||
if (zMap == null) {
|
||||
yMap[localZ] = zMap = new int[16];
|
||||
yMap[localZ] = zMap = new char[16];
|
||||
|
||||
if (changes == null) {
|
||||
changes = new int[t1][][][][];
|
||||
changes = new char[t1][][][][];
|
||||
} else if (changes != null && changes.length != 0) {
|
||||
initialChange(changes, chunkX, chunkZ, localX, localZ, y, (int) -combined);
|
||||
initialChange(changes, chunkX, chunkZ, localX, localZ, y, (char) -combined);
|
||||
}
|
||||
|
||||
} else {
|
||||
if (changes == null || changes.length == 0) changes = new int[t1][][][][];
|
||||
appendChange(changes, chunkX, chunkZ, localX, localZ, y, (int) (zMap[localX] - combined));
|
||||
if (changes == null || changes.length == 0) changes = new char[t1][][][][];
|
||||
appendChange(changes, chunkX, chunkZ, localX, localZ, y, (char) (zMap[localX] - combined));
|
||||
}
|
||||
|
||||
zMap[localX] = combined;
|
||||
}
|
||||
|
||||
private void initialChange(int[][][][][] src, int chunkX, int chunkZ, int localX, int localZ, int y, int combined) {
|
||||
int[][][][] arr = src[chunkZ];
|
||||
private void initialChange(char[][][][][] src, int chunkX, int chunkZ, int localX, int localZ, int y, char combined) {
|
||||
char[][][][] arr = src[chunkZ];
|
||||
if (arr == null) {
|
||||
src[chunkZ] = new int[0][][][];
|
||||
src[chunkZ] = new char[0][][][];
|
||||
return;
|
||||
} else if (arr.length == 0) return;
|
||||
|
||||
int[][][] arr2 = arr[chunkX];
|
||||
char[][][] arr2 = arr[chunkX];
|
||||
if (arr2 == null) {
|
||||
arr[chunkX] = new int[0][][];
|
||||
arr[chunkX] = new char[0][][];
|
||||
return;
|
||||
} else if (arr2.length == 0) return;
|
||||
|
||||
int[][] yMap = arr2[y];
|
||||
char[][] yMap = arr2[y];
|
||||
if (yMap == null) {
|
||||
arr2[y] = new int[0][];
|
||||
arr2[y] = new char[0][];
|
||||
return;
|
||||
} else if (yMap.length == 0) return;
|
||||
|
||||
int[] zMap = yMap[localZ];
|
||||
char[] zMap = yMap[localZ];
|
||||
if (zMap == null) {
|
||||
yMap[localZ] = new int[0];
|
||||
yMap[localZ] = new char[0];
|
||||
return;
|
||||
} else if (zMap.length == 0) return;
|
||||
|
||||
@ -189,23 +189,23 @@ public final class DifferentialBlockBuffer implements DifferentialCollection<int
|
||||
zMap[localX] = combined;
|
||||
}
|
||||
|
||||
private void appendChange(int[][][][][] src, int chunkX, int chunkZ, int localX, int localZ, int y, int combined) {
|
||||
int[][][][] arr = src[chunkZ];
|
||||
private void appendChange(char[][][][][] src, int chunkX, int chunkZ, int localX, int localZ, int y, char combined) {
|
||||
char[][][][] arr = src[chunkZ];
|
||||
if (arr == null || arr.length == 0) {
|
||||
arr = src[chunkZ] = new int[t2][][][];
|
||||
arr = src[chunkZ] = new char[t2][][][];
|
||||
}
|
||||
int[][][] arr2 = arr[chunkX];
|
||||
char[][][] arr2 = arr[chunkX];
|
||||
if (arr2 == null || arr2.length == 0) {
|
||||
arr2 = arr[chunkX] = new int[256][][];
|
||||
arr2 = arr[chunkX] = new char[256][][];
|
||||
}
|
||||
|
||||
int[][] yMap = arr2[y];
|
||||
char[][] yMap = arr2[y];
|
||||
if (yMap == null || yMap.length == 0) {
|
||||
arr2[y] = yMap = new int[16][];
|
||||
arr2[y] = yMap = new char[16][];
|
||||
}
|
||||
int[] zMap = yMap[localZ];
|
||||
char[] zMap = yMap[localZ];
|
||||
if (zMap == null || zMap.length == 0) {
|
||||
yMap[localZ] = zMap = new int[16];
|
||||
yMap[localZ] = zMap = new char[16];
|
||||
}
|
||||
zMap[localX] = combined;
|
||||
}
|
||||
|
@ -220,4 +220,15 @@ public class FastByteArrayOutputStream extends OutputStream {
|
||||
size += index;
|
||||
index = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
Arrays.fill(buffer, (byte) 0);
|
||||
index = 0;
|
||||
size = 0;
|
||||
buffers.clear();
|
||||
}
|
||||
}
|
@ -122,7 +122,7 @@ public class FaweLocalBlockQueue extends LocalBlockQueue {
|
||||
|
||||
@Override
|
||||
public void refreshChunk(int x, int z) {
|
||||
world.sendChunk(x, z, 0);
|
||||
world.refreshChunk(x, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -51,7 +51,7 @@ public class DelegateTextureUtil extends TextureUtil {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getIsBlockCloserThanBiome(int[] blockAndBiomeIdOutput, int color, int biomePriority) {
|
||||
public boolean getIsBlockCloserThanBiome(char[] blockAndBiomeIdOutput, int color, int biomePriority) {
|
||||
return parent.getIsBlockCloserThanBiome(blockAndBiomeIdOutput, color, biomePriority);
|
||||
}
|
||||
|
||||
|
@ -10,11 +10,11 @@ import java.util.Base64;
|
||||
|
||||
public enum Jars {
|
||||
|
||||
MM_v1_4_0("https://github.com/InventivetalentDev/MapManager/releases/download/1.4.0-SNAPSHOT/MapManager_v1.4.0-SNAPSHOT.jar",
|
||||
"AEO5SKBUGN4YJRS8XGGNLBM2QRZPTI1KF0/1W1URTGA=", 163279),
|
||||
MM_v1_4_0("https://github.com/InventivetalentDev/MapManager/releases/download/1.7.3-SNAPSHOT/MapManager_v1.7.3-SNAPSHOT.jar",
|
||||
"M3YLUQZZ66K2DMVDCYLEU38U3ZKRKHRAXQGGPVKFO6G=", 554831),
|
||||
|
||||
PL_v3_6_0("https://github.com/InventivetalentDev/PacketListenerAPI/releases/download/3.6.0-SNAPSHOT/PacketListenerAPI_v3.6.0-SNAPSHOT.jar",
|
||||
"OYBE75VIU+NNWHRVREBLDARWA+/TBDQZ1RC562QULBA=", 166508),
|
||||
PL_v3_6_0("https://github.com/InventivetalentDev/PacketListenerAPI/releases/download/3.7.3-SNAPSHOT/PacketListenerAPI_v3.7.3-SNAPSHOT.jar",
|
||||
"ETDBRZLN5PRVDFR/MSQDPM6JJER3WQOKHCN8FUXO5ZM=", 167205),
|
||||
|
||||
;
|
||||
|
||||
|
@ -41,7 +41,7 @@ public class RandomTextureUtil extends CachedTextureUtil {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getIsBlockCloserThanBiome(int[] blockAndBiomeIdOutput, int color, int biomePriority) {
|
||||
public boolean getIsBlockCloserThanBiome(char[] blockAndBiomeIdOutput, int color, int biomePriority) {
|
||||
BlockType block = getNearestBlock(color);
|
||||
int[] mix = biomeMixes.getOrDefault(color, null);
|
||||
if (mix == null) {
|
||||
@ -55,8 +55,8 @@ public class RandomTextureUtil extends CachedTextureUtil {
|
||||
int biomeId = mix[index];
|
||||
int biomeAvColor = mix[3];
|
||||
int blockColor = getColor(block);
|
||||
blockAndBiomeIdOutput[0] = block.getInternalId();
|
||||
blockAndBiomeIdOutput[1] = biomeId;
|
||||
blockAndBiomeIdOutput[0] = block.getDefaultState().getOrdinalChar();
|
||||
blockAndBiomeIdOutput[1] = (char) biomeId;
|
||||
if (colorDistance(biomeAvColor, color) - biomePriority > colorDistance(blockColor, color)) {
|
||||
return true;
|
||||
}
|
||||
|
@ -497,13 +497,13 @@ public class TextureUtil implements TextureHolder {
|
||||
return biomes[biome];
|
||||
}
|
||||
|
||||
public boolean getIsBlockCloserThanBiome(int[] blockAndBiomeIdOutput, int color,
|
||||
public boolean getIsBlockCloserThanBiome(char[] blockAndBiomeIdOutput, int color,
|
||||
int biomePriority) {
|
||||
BlockType block = getNearestBlock(color);
|
||||
TextureUtil.BiomeColor biome = getNearestBiome(color);
|
||||
int blockColor = getColor(block);
|
||||
blockAndBiomeIdOutput[0] = block.getDefaultState().getOrdinalChar();
|
||||
blockAndBiomeIdOutput[1] = biome.id;
|
||||
blockAndBiomeIdOutput[1] = (char) biome.id;
|
||||
if (colorDistance(biome.grassCombined, color) - biomePriority > colorDistance(blockColor,
|
||||
color)) {
|
||||
return true;
|
||||
|
@ -235,8 +235,8 @@ public class WorldWrapper extends AbstractWorld {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendChunk(int X, int Z, int mask) {
|
||||
parent.sendChunk(X, Z, mask);
|
||||
public void refreshChunk(int X, int Z) {
|
||||
parent.refreshChunk(X, Z);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -682,7 +682,12 @@ public class LocalSession implements TextureHolder {
|
||||
public Region getSelection(World world) throws IncompleteRegionException {
|
||||
checkNotNull(world);
|
||||
if (selector.getIncompleteRegion().getWorld() == null || !selector.getIncompleteRegion().getWorld().equals(world)) {
|
||||
throw new IncompleteRegionException();
|
||||
throw new IncompleteRegionException() {
|
||||
@Override
|
||||
public synchronized Throwable fillInStackTrace() {
|
||||
return this;
|
||||
}
|
||||
};
|
||||
}
|
||||
return selector.getRegion();
|
||||
}
|
||||
@ -1288,6 +1293,8 @@ public class LocalSession implements TextureHolder {
|
||||
public void describeCUI(Actor actor) {
|
||||
checkNotNull(actor);
|
||||
|
||||
// TODO preload
|
||||
|
||||
if (!hasCUISupport) {
|
||||
return;
|
||||
}
|
||||
|
@ -74,7 +74,8 @@ public class DistanceWand extends BrushTool implements DoubleActionTraceTool {
|
||||
private Location getTarget(Player player) {
|
||||
Location target;
|
||||
Mask mask = getTraceMask();
|
||||
if (this.range < MAX_RANGE) {
|
||||
int range = getRange();
|
||||
if (range < MAX_RANGE) {
|
||||
target = player.getBlockTrace(getRange(), true, mask);
|
||||
} else {
|
||||
target = player.getBlockTrace(MAX_RANGE, false, mask);
|
||||
|
@ -23,6 +23,10 @@ public interface MapMetadatable extends Metadatable {
|
||||
return !getRawMeta().isEmpty();
|
||||
}
|
||||
|
||||
default Object putIfAbsent(String key, Object value) {
|
||||
return getRawMeta().putIfAbsent(key, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the metadata for a key.
|
||||
*
|
||||
|
@ -20,7 +20,6 @@
|
||||
package com.sk89q.worldedit.entity;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.config.BBC;
|
||||
import com.boydti.fawe.config.Settings;
|
||||
import com.boydti.fawe.object.brush.visualization.VirtualWorld;
|
||||
import com.boydti.fawe.object.clipboard.DiskOptimizedClipboard;
|
||||
@ -39,7 +38,6 @@ import com.sk89q.worldedit.function.mask.Mask;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.math.Vector3;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
import com.sk89q.worldedit.regions.RegionOperationException;
|
||||
import com.sk89q.worldedit.regions.RegionSelector;
|
||||
import com.sk89q.worldedit.session.ClipboardHolder;
|
||||
import com.sk89q.worldedit.util.Direction;
|
||||
@ -49,11 +47,10 @@ import com.sk89q.worldedit.world.World;
|
||||
import com.sk89q.worldedit.world.block.BaseBlock;
|
||||
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
||||
import com.sk89q.worldedit.world.gamemode.GameMode;
|
||||
import java.io.File;
|
||||
import java.text.NumberFormat;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import org.enginehub.piston.inject.InjectedValueAccess;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import java.io.File;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* Represents a player
|
||||
@ -324,6 +321,8 @@ public interface Player extends Entity, Actor {
|
||||
*/
|
||||
<B extends BlockStateHolder<B>> void sendFakeBlock(BlockVector3 pos, @Nullable B block);
|
||||
|
||||
void sendFakeChunk(int chunkX, int chunkZ, Supplier<byte[]> data);
|
||||
|
||||
public Region[] getCurrentRegions();
|
||||
|
||||
Region[] getCurrentRegions(FaweMaskManager.MaskType type);
|
||||
|
@ -41,6 +41,7 @@ import com.sk89q.worldedit.world.gamemode.GameMode;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class PlayerProxy extends AbstractPlayerActor {
|
||||
|
||||
@ -211,6 +212,11 @@ public class PlayerProxy extends AbstractPlayerActor {
|
||||
basePlayer.sendFakeBlock(pos, block);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendFakeChunk(int chunkX, int chunkZ, Supplier<byte[]> data) {
|
||||
basePlayer.sendFakeChunk(chunkX, chunkZ, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendTitle(String title, String sub) {
|
||||
basePlayer.sendTitle(title, sub);
|
||||
|
@ -148,7 +148,7 @@ public class NullWorld extends AbstractWorld {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendChunk(int X, int Z, int mask) {
|
||||
public void refreshChunk(int X, int Z) {
|
||||
|
||||
}
|
||||
|
||||
|
@ -300,7 +300,7 @@ public interface World extends Extent, Keyed, IChunkCache<IChunkGet> {
|
||||
* @param chunkZ
|
||||
* @param bitMask
|
||||
*/
|
||||
void sendChunk(final int X, final int Z, final int mask);
|
||||
void refreshChunk(final int X, final int Z);
|
||||
|
||||
@Override
|
||||
IChunkGet get(int x, int z);
|
||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren